net/nfp: add structures and functions for flow offload
Add the structures and functions to process mask table, flow table, and flow stats id, which are used in the rte_flow offload logics. Signed-off-by: Chaoyong He <chaoyong.he@corigine.com> Reviewed-by: Niklas Söderlund <niklas.soderlund@corigine.com>
This commit is contained in:
parent
bab0e6f48b
commit
ac09376096
@ -15,6 +15,7 @@
|
||||
#include "../nfp_ctrl.h"
|
||||
#include "../nfp_cpp_bridge.h"
|
||||
#include "../nfp_rxtx.h"
|
||||
#include "../nfp_flow.h"
|
||||
#include "../nfpcore/nfp_mip.h"
|
||||
#include "../nfpcore/nfp_rtsym.h"
|
||||
#include "../nfpcore/nfp_nsp.h"
|
||||
@ -1090,13 +1091,19 @@ nfp_init_app_fw_flower(struct nfp_pf_dev *pf_dev)
|
||||
|
||||
pf_dev->app_fw_priv = app_fw_flower;
|
||||
|
||||
ret = nfp_flow_priv_init(pf_dev);
|
||||
if (ret != 0) {
|
||||
PMD_INIT_LOG(ERR, "init flow priv failed");
|
||||
goto app_cleanup;
|
||||
}
|
||||
|
||||
/* Allocate memory for the PF AND ctrl vNIC here (hence the * 2) */
|
||||
pf_hw = rte_zmalloc_socket("nfp_pf_vnic", 2 * sizeof(struct nfp_net_adapter),
|
||||
RTE_CACHE_LINE_SIZE, numa_node);
|
||||
if (pf_hw == NULL) {
|
||||
PMD_INIT_LOG(ERR, "Could not malloc nfp pf vnic");
|
||||
ret = -ENOMEM;
|
||||
goto app_cleanup;
|
||||
goto flow_priv_cleanup;
|
||||
}
|
||||
|
||||
/* Map the PF ctrl bar */
|
||||
@ -1174,6 +1181,8 @@ nfp_init_app_fw_flower(struct nfp_pf_dev *pf_dev)
|
||||
nfp_cpp_area_free(pf_dev->ctrl_area);
|
||||
vnic_cleanup:
|
||||
rte_free(pf_hw);
|
||||
flow_priv_cleanup:
|
||||
nfp_flow_priv_uninit(pf_dev);
|
||||
app_cleanup:
|
||||
rte_free(app_fw_flower);
|
||||
|
||||
|
@ -54,6 +54,8 @@ struct nfp_app_fw_flower {
|
||||
|
||||
/* service id of ctrl vnic service */
|
||||
uint32_t ctrl_vnic_id;
|
||||
|
||||
struct nfp_flow_priv *flow_priv;
|
||||
};
|
||||
|
||||
int nfp_init_app_fw_flower(struct nfp_pf_dev *pf_dev);
|
||||
|
@ -27,4 +27,7 @@ sources = files(
|
||||
'nfp_cpp_bridge.c',
|
||||
'nfp_ethdev_vf.c',
|
||||
'nfp_ethdev.c',
|
||||
'nfp_flow.c',
|
||||
)
|
||||
|
||||
deps += ['hash']
|
||||
|
496
drivers/net/nfp/nfp_flow.c
Normal file
496
drivers/net/nfp/nfp_flow.c
Normal file
@ -0,0 +1,496 @@
|
||||
/* SPDX-License-Identifier: BSD-3-Clause
|
||||
* Copyright (c) 2022 Corigine, Inc.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
#include <rte_flow_driver.h>
|
||||
#include <rte_hash.h>
|
||||
#include <rte_jhash.h>
|
||||
#include <bus_pci_driver.h>
|
||||
|
||||
#include "nfp_common.h"
|
||||
#include "nfp_flow.h"
|
||||
#include "nfp_logs.h"
|
||||
#include "flower/nfp_flower.h"
|
||||
#include "nfpcore/nfp_mip.h"
|
||||
#include "nfpcore/nfp_rtsym.h"
|
||||
|
||||
struct nfp_mask_id_entry {
|
||||
uint32_t hash_key;
|
||||
uint32_t ref_cnt;
|
||||
uint8_t mask_id;
|
||||
};
|
||||
|
||||
static int
|
||||
nfp_mask_id_alloc(struct nfp_flow_priv *priv, uint8_t *mask_id)
|
||||
{
|
||||
uint8_t temp_id;
|
||||
uint8_t freed_id;
|
||||
struct circ_buf *ring;
|
||||
|
||||
/* Checking for unallocated entries first. */
|
||||
if (priv->mask_ids.init_unallocated > 0) {
|
||||
*mask_id = priv->mask_ids.init_unallocated;
|
||||
priv->mask_ids.init_unallocated--;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Checking if buffer is empty. */
|
||||
freed_id = NFP_FLOWER_MASK_ENTRY_RS - 1;
|
||||
ring = &priv->mask_ids.free_list;
|
||||
if (ring->head == ring->tail) {
|
||||
*mask_id = freed_id;
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
rte_memcpy(&temp_id, &ring->buf[ring->tail], NFP_FLOWER_MASK_ELEMENT_RS);
|
||||
*mask_id = temp_id;
|
||||
|
||||
rte_memcpy(&ring->buf[ring->tail], &freed_id, NFP_FLOWER_MASK_ELEMENT_RS);
|
||||
ring->tail = (ring->tail + NFP_FLOWER_MASK_ELEMENT_RS) %
|
||||
(NFP_FLOWER_MASK_ENTRY_RS * NFP_FLOWER_MASK_ELEMENT_RS);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
nfp_mask_id_free(struct nfp_flow_priv *priv, uint8_t mask_id)
|
||||
{
|
||||
struct circ_buf *ring;
|
||||
|
||||
ring = &priv->mask_ids.free_list;
|
||||
|
||||
/* Checking if buffer is full. */
|
||||
if (CIRC_SPACE(ring->head, ring->tail, NFP_FLOWER_MASK_ENTRY_RS) == 0)
|
||||
return -ENOBUFS;
|
||||
|
||||
rte_memcpy(&ring->buf[ring->head], &mask_id, NFP_FLOWER_MASK_ELEMENT_RS);
|
||||
ring->head = (ring->head + NFP_FLOWER_MASK_ELEMENT_RS) %
|
||||
(NFP_FLOWER_MASK_ENTRY_RS * NFP_FLOWER_MASK_ELEMENT_RS);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
nfp_mask_table_add(struct nfp_flow_priv *priv,
|
||||
char *mask_data,
|
||||
uint32_t mask_len,
|
||||
uint8_t *id)
|
||||
{
|
||||
int ret;
|
||||
uint8_t mask_id;
|
||||
uint32_t hash_key;
|
||||
struct nfp_mask_id_entry *mask_entry;
|
||||
|
||||
mask_entry = rte_zmalloc("mask_entry", sizeof(struct nfp_mask_id_entry), 0);
|
||||
if (mask_entry == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
ret = nfp_mask_id_alloc(priv, &mask_id);
|
||||
if (ret != 0)
|
||||
goto mask_entry_free;
|
||||
|
||||
hash_key = rte_jhash(mask_data, mask_len, priv->hash_seed);
|
||||
mask_entry->mask_id = mask_id;
|
||||
mask_entry->hash_key = hash_key;
|
||||
mask_entry->ref_cnt = 1;
|
||||
PMD_DRV_LOG(DEBUG, "hash_key=%#x id=%u ref=%u", hash_key,
|
||||
mask_id, mask_entry->ref_cnt);
|
||||
|
||||
ret = rte_hash_add_key_data(priv->mask_table, &hash_key, mask_entry);
|
||||
if (ret != 0) {
|
||||
PMD_DRV_LOG(ERR, "Add to mask table failed.");
|
||||
goto mask_id_free;
|
||||
}
|
||||
|
||||
*id = mask_id;
|
||||
return 0;
|
||||
|
||||
mask_id_free:
|
||||
nfp_mask_id_free(priv, mask_id);
|
||||
mask_entry_free:
|
||||
rte_free(mask_entry);
|
||||
exit:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
nfp_mask_table_del(struct nfp_flow_priv *priv,
|
||||
char *mask_data,
|
||||
uint32_t mask_len,
|
||||
uint8_t id)
|
||||
{
|
||||
int ret;
|
||||
uint32_t hash_key;
|
||||
|
||||
hash_key = rte_jhash(mask_data, mask_len, priv->hash_seed);
|
||||
ret = rte_hash_del_key(priv->mask_table, &hash_key);
|
||||
if (ret < 0) {
|
||||
PMD_DRV_LOG(ERR, "Delete from mask table failed.");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = nfp_mask_id_free(priv, id);
|
||||
if (ret != 0) {
|
||||
PMD_DRV_LOG(ERR, "Free mask id failed.");
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct nfp_mask_id_entry *
|
||||
nfp_mask_table_search(struct nfp_flow_priv *priv,
|
||||
char *mask_data,
|
||||
uint32_t mask_len)
|
||||
{
|
||||
int index;
|
||||
uint32_t hash_key;
|
||||
struct nfp_mask_id_entry *entry;
|
||||
|
||||
hash_key = rte_jhash(mask_data, mask_len, priv->hash_seed);
|
||||
index = rte_hash_lookup_data(priv->mask_table, &hash_key, (void **)&entry);
|
||||
if (index < 0) {
|
||||
PMD_DRV_LOG(DEBUG, "Data NOT found in the mask table.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
__rte_unused static bool
|
||||
nfp_check_mask_add(struct nfp_flow_priv *priv,
|
||||
char *mask_data,
|
||||
uint32_t mask_len,
|
||||
uint8_t *meta_flags,
|
||||
uint8_t *mask_id)
|
||||
{
|
||||
int ret;
|
||||
struct nfp_mask_id_entry *mask_entry;
|
||||
|
||||
mask_entry = nfp_mask_table_search(priv, mask_data, mask_len);
|
||||
if (mask_entry == NULL) {
|
||||
/* mask entry does not exist, let's create one */
|
||||
ret = nfp_mask_table_add(priv, mask_data, mask_len, mask_id);
|
||||
if (ret != 0)
|
||||
return false;
|
||||
|
||||
*meta_flags |= NFP_FL_META_FLAG_MANAGE_MASK;
|
||||
} else {
|
||||
/* mask entry already exist */
|
||||
mask_entry->ref_cnt++;
|
||||
*mask_id = mask_entry->mask_id;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
__rte_unused static bool
|
||||
nfp_check_mask_remove(struct nfp_flow_priv *priv,
|
||||
char *mask_data,
|
||||
uint32_t mask_len,
|
||||
uint8_t *meta_flags)
|
||||
{
|
||||
int ret;
|
||||
struct nfp_mask_id_entry *mask_entry;
|
||||
|
||||
mask_entry = nfp_mask_table_search(priv, mask_data, mask_len);
|
||||
if (mask_entry == NULL)
|
||||
return false;
|
||||
|
||||
mask_entry->ref_cnt--;
|
||||
if (mask_entry->ref_cnt == 0) {
|
||||
ret = nfp_mask_table_del(priv, mask_data, mask_len,
|
||||
mask_entry->mask_id);
|
||||
if (ret != 0)
|
||||
return false;
|
||||
|
||||
rte_free(mask_entry);
|
||||
if (meta_flags)
|
||||
*meta_flags &= ~NFP_FL_META_FLAG_MANAGE_MASK;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
__rte_unused static int
|
||||
nfp_flow_table_add(struct nfp_flow_priv *priv,
|
||||
struct rte_flow *nfp_flow)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = rte_hash_add_key_data(priv->flow_table, &nfp_flow->hash_key, nfp_flow);
|
||||
if (ret != 0) {
|
||||
PMD_DRV_LOG(ERR, "Add to flow table failed.");
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
__rte_unused static int
|
||||
nfp_flow_table_delete(struct nfp_flow_priv *priv,
|
||||
struct rte_flow *nfp_flow)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = rte_hash_del_key(priv->flow_table, &nfp_flow->hash_key);
|
||||
if (ret < 0) {
|
||||
PMD_DRV_LOG(ERR, "Delete from flow table failed.");
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
__rte_unused static struct rte_flow *
|
||||
nfp_flow_table_search(struct nfp_flow_priv *priv,
|
||||
struct rte_flow *nfp_flow)
|
||||
{
|
||||
int index;
|
||||
struct rte_flow *flow_find;
|
||||
|
||||
index = rte_hash_lookup_data(priv->flow_table, &nfp_flow->hash_key,
|
||||
(void **)&flow_find);
|
||||
if (index < 0) {
|
||||
PMD_DRV_LOG(DEBUG, "Data NOT found in the flow table.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return flow_find;
|
||||
}
|
||||
|
||||
__rte_unused static struct rte_flow *
|
||||
nfp_flow_alloc(struct nfp_fl_key_ls *key_layer)
|
||||
{
|
||||
char *tmp;
|
||||
size_t len;
|
||||
struct rte_flow *nfp_flow;
|
||||
struct nfp_fl_payload *payload;
|
||||
|
||||
nfp_flow = rte_zmalloc("nfp_flow", sizeof(struct rte_flow), 0);
|
||||
if (nfp_flow == NULL)
|
||||
goto exit;
|
||||
|
||||
len = key_layer->key_size + key_layer->key_size + key_layer->act_size;
|
||||
tmp = rte_zmalloc("nfp_flow_payload", len + sizeof(struct nfp_fl_rule_metadata), 0);
|
||||
if (tmp == NULL)
|
||||
goto free_flow;
|
||||
|
||||
nfp_flow->length = len;
|
||||
|
||||
payload = &nfp_flow->payload;
|
||||
payload->meta = (struct nfp_fl_rule_metadata *)tmp;
|
||||
payload->unmasked_data = tmp + sizeof(struct nfp_fl_rule_metadata);
|
||||
payload->mask_data = payload->unmasked_data + key_layer->key_size;
|
||||
payload->action_data = payload->mask_data + key_layer->key_size;
|
||||
|
||||
return nfp_flow;
|
||||
|
||||
free_flow:
|
||||
rte_free(nfp_flow);
|
||||
exit:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
__rte_unused static void
|
||||
nfp_flow_free(struct rte_flow *nfp_flow)
|
||||
{
|
||||
rte_free(nfp_flow->payload.meta);
|
||||
rte_free(nfp_flow);
|
||||
}
|
||||
|
||||
__rte_unused static int
|
||||
nfp_stats_id_alloc(struct nfp_flow_priv *priv, uint32_t *ctx)
|
||||
{
|
||||
struct circ_buf *ring;
|
||||
uint32_t temp_stats_id;
|
||||
uint32_t freed_stats_id;
|
||||
|
||||
/* Check for unallocated entries first. */
|
||||
if (priv->stats_ids.init_unallocated > 0) {
|
||||
*ctx = ((priv->stats_ids.init_unallocated - 1) & NFP_FL_STAT_ID_STAT) |
|
||||
(priv->active_mem_unit & NFP_FL_STAT_ID_MU_NUM);
|
||||
if (++priv->active_mem_unit == priv->total_mem_units) {
|
||||
priv->stats_ids.init_unallocated--;
|
||||
priv->active_mem_unit = 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Check if buffer is empty */
|
||||
ring = &priv->stats_ids.free_list;
|
||||
freed_stats_id = priv->stats_ring_size;
|
||||
if (ring->head == ring->tail) {
|
||||
*ctx = freed_stats_id;
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
memcpy(&temp_stats_id, &ring->buf[ring->tail], NFP_FL_STATS_ELEM_RS);
|
||||
*ctx = temp_stats_id;
|
||||
memcpy(&ring->buf[ring->tail], &freed_stats_id, NFP_FL_STATS_ELEM_RS);
|
||||
ring->tail = (ring->tail + NFP_FL_STATS_ELEM_RS) %
|
||||
(priv->stats_ring_size * NFP_FL_STATS_ELEM_RS);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
__rte_unused static int
|
||||
nfp_stats_id_free(struct nfp_flow_priv *priv, uint32_t ctx)
|
||||
{
|
||||
struct circ_buf *ring;
|
||||
|
||||
/* Check if buffer is full */
|
||||
ring = &priv->stats_ids.free_list;
|
||||
if (!CIRC_SPACE(ring->head, ring->tail, priv->stats_ring_size *
|
||||
NFP_FL_STATS_ELEM_RS - NFP_FL_STATS_ELEM_RS + 1))
|
||||
return -ENOBUFS;
|
||||
|
||||
memcpy(&ring->buf[ring->head], &ctx, NFP_FL_STATS_ELEM_RS);
|
||||
ring->head = (ring->head + NFP_FL_STATS_ELEM_RS) %
|
||||
(priv->stats_ring_size * NFP_FL_STATS_ELEM_RS);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
nfp_flow_priv_init(struct nfp_pf_dev *pf_dev)
|
||||
{
|
||||
int ret = 0;
|
||||
size_t stats_size;
|
||||
uint64_t ctx_count;
|
||||
uint64_t ctx_split;
|
||||
struct nfp_flow_priv *priv;
|
||||
struct nfp_app_fw_flower *app_fw_flower;
|
||||
|
||||
struct rte_hash_parameters mask_hash_params = {
|
||||
.name = "mask_hash_table",
|
||||
.entries = NFP_MASK_TABLE_ENTRIES,
|
||||
.hash_func = rte_jhash,
|
||||
.socket_id = rte_socket_id(),
|
||||
.key_len = sizeof(uint32_t),
|
||||
.extra_flag = RTE_HASH_EXTRA_FLAGS_RW_CONCURRENCY,
|
||||
};
|
||||
|
||||
struct rte_hash_parameters flow_hash_params = {
|
||||
.name = "flow_hash_table",
|
||||
.hash_func = rte_jhash,
|
||||
.socket_id = rte_socket_id(),
|
||||
.key_len = sizeof(uint32_t),
|
||||
.extra_flag = RTE_HASH_EXTRA_FLAGS_RW_CONCURRENCY,
|
||||
};
|
||||
|
||||
ctx_count = nfp_rtsym_read_le(pf_dev->sym_tbl,
|
||||
"CONFIG_FC_HOST_CTX_COUNT", &ret);
|
||||
if (ret < 0) {
|
||||
PMD_INIT_LOG(ERR, "Read CTX_COUNT from symbol table failed");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
ctx_split = nfp_rtsym_read_le(pf_dev->sym_tbl,
|
||||
"CONFIG_FC_HOST_CTX_SPLIT", &ret);
|
||||
if (ret < 0) {
|
||||
PMD_INIT_LOG(ERR, "Read CTX_SPLIT from symbol table failed");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
priv = rte_zmalloc("nfp_app_flow_priv", sizeof(struct nfp_flow_priv), 0);
|
||||
if (priv == NULL) {
|
||||
PMD_INIT_LOG(ERR, "nfp app flow priv creation failed");
|
||||
ret = -ENOMEM;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
app_fw_flower = NFP_PRIV_TO_APP_FW_FLOWER(pf_dev->app_fw_priv);
|
||||
app_fw_flower->flow_priv = priv;
|
||||
priv->hash_seed = (uint32_t)rte_rand();
|
||||
priv->stats_ring_size = ctx_count;
|
||||
priv->total_mem_units = ctx_split;
|
||||
|
||||
/* Init ring buffer and unallocated mask_ids. */
|
||||
priv->mask_ids.init_unallocated = NFP_FLOWER_MASK_ENTRY_RS - 1;
|
||||
priv->mask_ids.free_list.buf = rte_zmalloc("nfp_app_mask_ids",
|
||||
NFP_FLOWER_MASK_ENTRY_RS * NFP_FLOWER_MASK_ELEMENT_RS, 0);
|
||||
if (priv->mask_ids.free_list.buf == NULL) {
|
||||
PMD_INIT_LOG(ERR, "mask id free list creation failed");
|
||||
ret = -ENOMEM;
|
||||
goto free_priv;
|
||||
}
|
||||
|
||||
/* Init ring buffer and unallocated stats_ids. */
|
||||
priv->stats_ids.init_unallocated = ctx_count / ctx_split;
|
||||
priv->stats_ids.free_list.buf = rte_zmalloc("nfp_app_stats_ids",
|
||||
priv->stats_ring_size * NFP_FL_STATS_ELEM_RS, 0);
|
||||
if (priv->stats_ids.free_list.buf == NULL) {
|
||||
PMD_INIT_LOG(ERR, "stats id free list creation failed");
|
||||
ret = -ENOMEM;
|
||||
goto free_mask_id;
|
||||
}
|
||||
|
||||
/* flow stats */
|
||||
rte_spinlock_init(&priv->stats_lock);
|
||||
stats_size = (ctx_count & NFP_FL_STAT_ID_STAT) |
|
||||
((ctx_split - 1) & NFP_FL_STAT_ID_MU_NUM);
|
||||
PMD_INIT_LOG(INFO, "ctx_count:%0lx, ctx_split:%0lx, stats_size:%0lx ",
|
||||
ctx_count, ctx_split, stats_size);
|
||||
priv->stats = rte_zmalloc("nfp_flow_stats",
|
||||
stats_size * sizeof(struct nfp_fl_stats), 0);
|
||||
if (priv->stats == NULL) {
|
||||
PMD_INIT_LOG(ERR, "flow stats creation failed");
|
||||
ret = -ENOMEM;
|
||||
goto free_stats_id;
|
||||
}
|
||||
|
||||
/* mask table */
|
||||
mask_hash_params.hash_func_init_val = priv->hash_seed;
|
||||
priv->mask_table = rte_hash_create(&mask_hash_params);
|
||||
if (priv->mask_table == NULL) {
|
||||
PMD_INIT_LOG(ERR, "mask hash table creation failed");
|
||||
ret = -ENOMEM;
|
||||
goto free_stats;
|
||||
}
|
||||
|
||||
/* flow table */
|
||||
flow_hash_params.hash_func_init_val = priv->hash_seed;
|
||||
flow_hash_params.entries = ctx_count;
|
||||
priv->flow_table = rte_hash_create(&flow_hash_params);
|
||||
if (priv->flow_table == NULL) {
|
||||
PMD_INIT_LOG(ERR, "flow hash table creation failed");
|
||||
ret = -ENOMEM;
|
||||
goto free_mask_table;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
free_mask_table:
|
||||
rte_free(priv->mask_table);
|
||||
free_stats:
|
||||
rte_free(priv->stats);
|
||||
free_stats_id:
|
||||
rte_free(priv->stats_ids.free_list.buf);
|
||||
free_mask_id:
|
||||
rte_free(priv->mask_ids.free_list.buf);
|
||||
free_priv:
|
||||
rte_free(priv);
|
||||
exit:
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
nfp_flow_priv_uninit(struct nfp_pf_dev *pf_dev)
|
||||
{
|
||||
struct nfp_flow_priv *priv;
|
||||
struct nfp_app_fw_flower *app_fw_flower;
|
||||
|
||||
app_fw_flower = NFP_PRIV_TO_APP_FW_FLOWER(pf_dev->app_fw_priv);
|
||||
priv = app_fw_flower->flow_priv;
|
||||
|
||||
rte_hash_free(priv->flow_table);
|
||||
rte_hash_free(priv->mask_table);
|
||||
rte_free(priv->stats);
|
||||
rte_free(priv->stats_ids.free_list.buf);
|
||||
rte_free(priv->mask_ids.free_list.buf);
|
||||
rte_free(priv);
|
||||
}
|
104
drivers/net/nfp/nfp_flow.h
Normal file
104
drivers/net/nfp/nfp_flow.h
Normal file
@ -0,0 +1,104 @@
|
||||
/* SPDX-License-Identifier: BSD-3-Clause
|
||||
* Copyright (c) 2022 Corigine, Inc.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _NFP_FLOW_H_
|
||||
#define _NFP_FLOW_H_
|
||||
|
||||
#include <rte_bitops.h>
|
||||
|
||||
#define NFP_FL_META_FLAG_MANAGE_MASK RTE_BIT32(7)
|
||||
|
||||
#define NFP_MASK_TABLE_ENTRIES 1024
|
||||
|
||||
enum nfp_flower_tun_type {
|
||||
NFP_FL_TUN_NONE = 0,
|
||||
NFP_FL_TUN_GRE = 1,
|
||||
NFP_FL_TUN_VXLAN = 2,
|
||||
NFP_FL_TUN_GENEVE = 4,
|
||||
};
|
||||
|
||||
struct nfp_fl_key_ls {
|
||||
uint32_t key_layer_two;
|
||||
uint8_t key_layer;
|
||||
int key_size;
|
||||
int act_size;
|
||||
uint32_t port;
|
||||
uint16_t vlan;
|
||||
enum nfp_flower_tun_type tun_type;
|
||||
};
|
||||
|
||||
struct nfp_fl_rule_metadata {
|
||||
uint8_t key_len;
|
||||
uint8_t mask_len;
|
||||
uint8_t act_len;
|
||||
uint8_t flags;
|
||||
rte_be32_t host_ctx_id;
|
||||
rte_be64_t host_cookie __rte_packed;
|
||||
rte_be64_t flow_version __rte_packed;
|
||||
rte_be32_t shortcut;
|
||||
};
|
||||
|
||||
struct nfp_fl_payload {
|
||||
struct nfp_fl_rule_metadata *meta;
|
||||
char *unmasked_data;
|
||||
char *mask_data;
|
||||
char *action_data;
|
||||
};
|
||||
|
||||
#define CIRC_CNT(head, tail, size) (((head) - (tail)) & ((size) - 1))
|
||||
#define CIRC_SPACE(head, tail, size) CIRC_CNT((tail), ((head) + 1), (size))
|
||||
struct circ_buf {
|
||||
uint32_t head;
|
||||
uint32_t tail;
|
||||
char *buf;
|
||||
};
|
||||
|
||||
#define NFP_FLOWER_MASK_ENTRY_RS 256
|
||||
#define NFP_FLOWER_MASK_ELEMENT_RS sizeof(uint8_t)
|
||||
struct nfp_fl_mask_id {
|
||||
struct circ_buf free_list;
|
||||
uint8_t init_unallocated;
|
||||
};
|
||||
|
||||
#define NFP_FL_STATS_ELEM_RS sizeof(uint32_t)
|
||||
struct nfp_fl_stats_id {
|
||||
struct circ_buf free_list;
|
||||
uint32_t init_unallocated;
|
||||
};
|
||||
|
||||
#define NFP_FL_STAT_ID_MU_NUM 0xffc00000
|
||||
#define NFP_FL_STAT_ID_STAT 0x003fffff
|
||||
struct nfp_fl_stats {
|
||||
uint64_t pkts;
|
||||
uint64_t bytes;
|
||||
};
|
||||
|
||||
struct nfp_flow_priv {
|
||||
uint32_t hash_seed; /**< Hash seed for hash tables in this structure. */
|
||||
/* mask hash table */
|
||||
struct nfp_fl_mask_id mask_ids; /**< Entry for mask hash table */
|
||||
struct rte_hash *mask_table; /**< Hash table to store mask ids. */
|
||||
/* flow hash table */
|
||||
struct rte_hash *flow_table; /**< Hash table to store flow rules. */
|
||||
/* flow stats */
|
||||
uint32_t active_mem_unit; /**< The size of active mem units. */
|
||||
uint32_t total_mem_units; /**< The size of total mem units. */
|
||||
uint32_t stats_ring_size; /**< The size of stats id ring. */
|
||||
struct nfp_fl_stats_id stats_ids; /**< The stats id ring. */
|
||||
struct nfp_fl_stats *stats; /**< Store stats of flow. */
|
||||
rte_spinlock_t stats_lock; /** < Lock the update of 'stats' field. */
|
||||
};
|
||||
|
||||
struct rte_flow {
|
||||
struct nfp_fl_payload payload;
|
||||
size_t length;
|
||||
uint32_t hash_key;
|
||||
bool install_flag;
|
||||
};
|
||||
|
||||
int nfp_flow_priv_init(struct nfp_pf_dev *pf_dev);
|
||||
void nfp_flow_priv_uninit(struct nfp_pf_dev *pf_dev);
|
||||
|
||||
#endif /* _NFP_FLOW_H_ */
|
Loading…
Reference in New Issue
Block a user