Skip to content

Commit

Permalink
nfp: flower-ct: add a table to map flow cookies to ct flows
Browse files Browse the repository at this point in the history
Add a hashtable which contains entries to map flow cookies to ct
flow entries. Currently the entries are added and not used, but
follow-up patches will use this for stats updates and flow deletes.

Signed-off-by: Louis Peens <louis.peens@corigine.com>
Signed-off-by: Yinjun Zhang <yinjun.zhang@corigine.com>
Signed-off-by: Simon Horman <simon.horman@corigine.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Louis Peens authored and David S. Miller committed Jun 2, 2021
1 parent 072c089 commit fa81d6d
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 7 deletions.
35 changes: 29 additions & 6 deletions drivers/net/ethernet/netronome/nfp/flower/conntrack.c
Original file line number Diff line number Diff line change
Expand Up @@ -107,9 +107,11 @@ nfp_fl_ct_zone_entry *get_nfp_zone_entry(struct nfp_flower_priv *priv,
static struct
nfp_fl_ct_flow_entry *nfp_fl_ct_add_flow(struct nfp_fl_ct_zone_entry *zt,
struct net_device *netdev,
struct flow_cls_offload *flow)
struct flow_cls_offload *flow,
struct netlink_ext_ack *extack)
{
struct nfp_fl_ct_flow_entry *entry;
struct nfp_fl_ct_map_entry *map;
struct flow_action_entry *act;
int err, i;

Expand Down Expand Up @@ -160,12 +162,33 @@ nfp_fl_ct_flow_entry *nfp_fl_ct_add_flow(struct nfp_fl_ct_zone_entry *zt,

INIT_LIST_HEAD(&entry->children);

/* Creation of a ct_map_entry and adding it to a hashtable
* will happen here in follow up patches.
*/
/* Now add a ct map entry to flower-priv */
map = get_hashentry(&zt->priv->ct_map_table, &flow->cookie,
nfp_ct_map_params, sizeof(*map));
if (IS_ERR(map)) {
NL_SET_ERR_MSG_MOD(extack,
"offload error: ct map entry creation failed");
err = -ENOMEM;
goto err_ct_flow_insert;
}
map->cookie = flow->cookie;
map->ct_entry = entry;
err = rhashtable_insert_fast(&zt->priv->ct_map_table,
&map->hash_node,
nfp_ct_map_params);
if (err) {
NL_SET_ERR_MSG_MOD(extack,
"offload error: ct map entry table add failed");
goto err_map_insert;
}

return entry;

err_map_insert:
kfree(map);
err_ct_flow_insert:
if (entry->tun_offset != NFP_FL_CT_NO_TUN)
kfree(entry->rule->action.entries[entry->tun_offset].tunnel);
err_pre_ct_tun_cp:
kfree(entry->rule);
err_pre_ct_act:
Expand Down Expand Up @@ -245,7 +268,7 @@ int nfp_fl_ct_handle_pre_ct(struct nfp_flower_priv *priv,
zt->nft = ct_act->ct.flow_table;

/* Add entry to pre_ct_list */
ct_entry = nfp_fl_ct_add_flow(zt, netdev, flow);
ct_entry = nfp_fl_ct_add_flow(zt, netdev, flow, extack);
if (IS_ERR(ct_entry))
return PTR_ERR(ct_entry);
ct_entry->type = CT_TYPE_PRE_CT;
Expand Down Expand Up @@ -286,7 +309,7 @@ int nfp_fl_ct_handle_post_ct(struct nfp_flower_priv *priv,
}

/* Add entry to post_ct_list */
ct_entry = nfp_fl_ct_add_flow(zt, netdev, flow);
ct_entry = nfp_fl_ct_add_flow(zt, netdev, flow, extack);
if (IS_ERR(ct_entry))
return PTR_ERR(ct_entry);

Expand Down
13 changes: 13 additions & 0 deletions drivers/net/ethernet/netronome/nfp/flower/conntrack.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#define NFP_FL_CT_NO_TUN 0xff

extern const struct rhashtable_params nfp_zone_table_params;
extern const struct rhashtable_params nfp_ct_map_params;

/**
* struct nfp_fl_ct_zone_entry - Zone entry containing conntrack flow information
Expand Down Expand Up @@ -69,6 +70,18 @@ struct nfp_fl_ct_flow_entry {
u8 tun_offset; // Set to NFP_FL_CT_NO_TUN if no tun
};

/**
* struct nfp_fl_ct_map_entry - Map between flow cookie and specific ct_flow
* @cookie: Flow cookie, same as original TC flow, used as key
* @hash_node: Used by the hashtable
* @ct_entry: Pointer to corresponding ct_entry
*/
struct nfp_fl_ct_map_entry {
unsigned long cookie;
struct rhash_head hash_node;
struct nfp_fl_ct_flow_entry *ct_entry;
};

bool is_pre_ct_flow(struct flow_cls_offload *flow);
bool is_post_ct_flow(struct flow_cls_offload *flow);

Expand Down
2 changes: 2 additions & 0 deletions drivers/net/ethernet/netronome/nfp/flower/main.h
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,7 @@ struct nfp_fl_internal_ports {
* @merge_table: Hash table to store merged flows
* @ct_zone_table: Hash table used to store the different zones
* @ct_zone_wc: Special zone entry for wildcarded zone matches
* @ct_map_table: Hash table used to referennce ct flows
*/
struct nfp_flower_priv {
struct nfp_app *app;
Expand Down Expand Up @@ -231,6 +232,7 @@ struct nfp_flower_priv {
struct rhashtable merge_table;
struct rhashtable ct_zone_table;
struct nfp_fl_ct_zone_entry *ct_zone_wc;
struct rhashtable ct_map_table;
};

/**
Expand Down
46 changes: 45 additions & 1 deletion drivers/net/ethernet/netronome/nfp/flower/metadata.c
Original file line number Diff line number Diff line change
Expand Up @@ -504,6 +504,13 @@ const struct rhashtable_params nfp_zone_table_params = {
.automatic_shrinking = false,
};

const struct rhashtable_params nfp_ct_map_params = {
.head_offset = offsetof(struct nfp_fl_ct_map_entry, hash_node),
.key_len = sizeof(unsigned long),
.key_offset = offsetof(struct nfp_fl_ct_map_entry, cookie),
.automatic_shrinking = true,
};

int nfp_flower_metadata_init(struct nfp_app *app, u64 host_ctx_count,
unsigned int host_num_mems)
{
Expand All @@ -528,14 +535,18 @@ int nfp_flower_metadata_init(struct nfp_app *app, u64 host_ctx_count,
if (err)
goto err_free_merge_table;

err = rhashtable_init(&priv->ct_map_table, &nfp_ct_map_params);
if (err)
goto err_free_ct_zone_table;

get_random_bytes(&priv->mask_id_seed, sizeof(priv->mask_id_seed));

/* Init ring buffer and unallocated mask_ids. */
priv->mask_ids.mask_id_free_list.buf =
kmalloc_array(NFP_FLOWER_MASK_ENTRY_RS,
NFP_FLOWER_MASK_ELEMENT_RS, GFP_KERNEL);
if (!priv->mask_ids.mask_id_free_list.buf)
goto err_free_ct_zone_table;
goto err_free_ct_map_table;

priv->mask_ids.init_unallocated = NFP_FLOWER_MASK_ENTRY_RS - 1;

Expand Down Expand Up @@ -572,6 +583,8 @@ int nfp_flower_metadata_init(struct nfp_app *app, u64 host_ctx_count,
kfree(priv->mask_ids.last_used);
err_free_mask_id:
kfree(priv->mask_ids.mask_id_free_list.buf);
err_free_ct_map_table:
rhashtable_destroy(&priv->ct_map_table);
err_free_ct_zone_table:
rhashtable_destroy(&priv->ct_zone_table);
err_free_merge_table:
Expand All @@ -589,22 +602,40 @@ static void nfp_zone_table_entry_destroy(struct nfp_fl_ct_zone_entry *zt)
return;

if (!list_empty(&zt->pre_ct_list)) {
struct rhashtable *m_table = &zt->priv->ct_map_table;
struct nfp_fl_ct_flow_entry *entry, *tmp;
struct nfp_fl_ct_map_entry *map;

WARN_ONCE(1, "pre_ct_list not empty as expected, cleaning up\n");
list_for_each_entry_safe(entry, tmp, &zt->pre_ct_list,
list_node) {
map = rhashtable_lookup_fast(m_table,
&entry->cookie,
nfp_ct_map_params);
WARN_ON_ONCE(rhashtable_remove_fast(m_table,
&map->hash_node,
nfp_ct_map_params));
nfp_fl_ct_clean_flow_entry(entry);
kfree(map);
}
}

if (!list_empty(&zt->post_ct_list)) {
struct rhashtable *m_table = &zt->priv->ct_map_table;
struct nfp_fl_ct_flow_entry *entry, *tmp;
struct nfp_fl_ct_map_entry *map;

WARN_ONCE(1, "post_ct_list not empty as expected, cleaning up\n");
list_for_each_entry_safe(entry, tmp, &zt->post_ct_list,
list_node) {
map = rhashtable_lookup_fast(m_table,
&entry->cookie,
nfp_ct_map_params);
WARN_ON_ONCE(rhashtable_remove_fast(m_table,
&map->hash_node,
nfp_ct_map_params));
nfp_fl_ct_clean_flow_entry(entry);
kfree(map);
}
}
kfree(zt);
Expand All @@ -617,6 +648,16 @@ static void nfp_free_zone_table_entry(void *ptr, void *arg)
nfp_zone_table_entry_destroy(zt);
}

static void nfp_free_map_table_entry(void *ptr, void *arg)
{
struct nfp_fl_ct_map_entry *map = ptr;

if (!map)
return;

kfree(map);
}

void nfp_flower_metadata_cleanup(struct nfp_app *app)
{
struct nfp_flower_priv *priv = app->priv;
Expand All @@ -633,6 +674,9 @@ void nfp_flower_metadata_cleanup(struct nfp_app *app)
rhashtable_free_and_destroy(&priv->ct_zone_table,
nfp_free_zone_table_entry, NULL);
nfp_zone_table_entry_destroy(priv->ct_zone_wc);

rhashtable_free_and_destroy(&priv->ct_map_table,
nfp_free_map_table_entry, NULL);
kvfree(priv->stats);
kfree(priv->mask_ids.mask_id_free_list.buf);
kfree(priv->mask_ids.last_used);
Expand Down

0 comments on commit fa81d6d

Please sign in to comment.