Commit fa81d6d2 authored by Louis Peens's avatar Louis Peens Committed by David S. Miller

nfp: flower-ct: add a table to map flow cookies to ct flows

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: default avatarLouis Peens <louis.peens@corigine.com>
Signed-off-by: default avatarYinjun Zhang <yinjun.zhang@corigine.com>
Signed-off-by: default avatarSimon Horman <simon.horman@corigine.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 072c089c
......@@ -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;
......@@ -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:
......@@ -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;
......@@ -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);
......
......@@ -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
......@@ -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);
......
......@@ -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;
......@@ -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;
};
/**
......
......@@ -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)
{
......@@ -528,6 +535,10 @@ 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. */
......@@ -535,7 +546,7 @@ int nfp_flower_metadata_init(struct nfp_app *app, u64 host_ctx_count,
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;
......@@ -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:
......@@ -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);
......@@ -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;
......@@ -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);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment