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, ...@@ -107,9 +107,11 @@ nfp_fl_ct_zone_entry *get_nfp_zone_entry(struct nfp_flower_priv *priv,
static struct static struct
nfp_fl_ct_flow_entry *nfp_fl_ct_add_flow(struct nfp_fl_ct_zone_entry *zt, nfp_fl_ct_flow_entry *nfp_fl_ct_add_flow(struct nfp_fl_ct_zone_entry *zt,
struct net_device *netdev, 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_flow_entry *entry;
struct nfp_fl_ct_map_entry *map;
struct flow_action_entry *act; struct flow_action_entry *act;
int err, i; int err, i;
...@@ -160,12 +162,33 @@ nfp_fl_ct_flow_entry *nfp_fl_ct_add_flow(struct nfp_fl_ct_zone_entry *zt, ...@@ -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); INIT_LIST_HEAD(&entry->children);
/* Creation of a ct_map_entry and adding it to a hashtable /* Now add a ct map entry to flower-priv */
* will happen here in follow up patches. 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; 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: err_pre_ct_tun_cp:
kfree(entry->rule); kfree(entry->rule);
err_pre_ct_act: err_pre_ct_act:
...@@ -245,7 +268,7 @@ int nfp_fl_ct_handle_pre_ct(struct nfp_flower_priv *priv, ...@@ -245,7 +268,7 @@ int nfp_fl_ct_handle_pre_ct(struct nfp_flower_priv *priv,
zt->nft = ct_act->ct.flow_table; zt->nft = ct_act->ct.flow_table;
/* Add entry to pre_ct_list */ /* 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)) if (IS_ERR(ct_entry))
return PTR_ERR(ct_entry); return PTR_ERR(ct_entry);
ct_entry->type = CT_TYPE_PRE_CT; ct_entry->type = CT_TYPE_PRE_CT;
...@@ -286,7 +309,7 @@ int nfp_fl_ct_handle_post_ct(struct nfp_flower_priv *priv, ...@@ -286,7 +309,7 @@ int nfp_fl_ct_handle_post_ct(struct nfp_flower_priv *priv,
} }
/* Add entry to post_ct_list */ /* 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)) if (IS_ERR(ct_entry))
return PTR_ERR(ct_entry); return PTR_ERR(ct_entry);
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#define NFP_FL_CT_NO_TUN 0xff #define NFP_FL_CT_NO_TUN 0xff
extern const struct rhashtable_params nfp_zone_table_params; 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 * struct nfp_fl_ct_zone_entry - Zone entry containing conntrack flow information
...@@ -69,6 +70,18 @@ struct nfp_fl_ct_flow_entry { ...@@ -69,6 +70,18 @@ struct nfp_fl_ct_flow_entry {
u8 tun_offset; // Set to NFP_FL_CT_NO_TUN if no tun 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_pre_ct_flow(struct flow_cls_offload *flow);
bool is_post_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 { ...@@ -195,6 +195,7 @@ struct nfp_fl_internal_ports {
* @merge_table: Hash table to store merged flows * @merge_table: Hash table to store merged flows
* @ct_zone_table: Hash table used to store the different zones * @ct_zone_table: Hash table used to store the different zones
* @ct_zone_wc: Special zone entry for wildcarded zone matches * @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_flower_priv {
struct nfp_app *app; struct nfp_app *app;
...@@ -231,6 +232,7 @@ struct nfp_flower_priv { ...@@ -231,6 +232,7 @@ struct nfp_flower_priv {
struct rhashtable merge_table; struct rhashtable merge_table;
struct rhashtable ct_zone_table; struct rhashtable ct_zone_table;
struct nfp_fl_ct_zone_entry *ct_zone_wc; 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 = { ...@@ -504,6 +504,13 @@ const struct rhashtable_params nfp_zone_table_params = {
.automatic_shrinking = false, .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, int nfp_flower_metadata_init(struct nfp_app *app, u64 host_ctx_count,
unsigned int host_num_mems) unsigned int host_num_mems)
{ {
...@@ -528,6 +535,10 @@ int nfp_flower_metadata_init(struct nfp_app *app, u64 host_ctx_count, ...@@ -528,6 +535,10 @@ int nfp_flower_metadata_init(struct nfp_app *app, u64 host_ctx_count,
if (err) if (err)
goto err_free_merge_table; 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)); get_random_bytes(&priv->mask_id_seed, sizeof(priv->mask_id_seed));
/* Init ring buffer and unallocated mask_ids. */ /* Init ring buffer and unallocated mask_ids. */
...@@ -535,7 +546,7 @@ int nfp_flower_metadata_init(struct nfp_app *app, u64 host_ctx_count, ...@@ -535,7 +546,7 @@ int nfp_flower_metadata_init(struct nfp_app *app, u64 host_ctx_count,
kmalloc_array(NFP_FLOWER_MASK_ENTRY_RS, kmalloc_array(NFP_FLOWER_MASK_ENTRY_RS,
NFP_FLOWER_MASK_ELEMENT_RS, GFP_KERNEL); NFP_FLOWER_MASK_ELEMENT_RS, GFP_KERNEL);
if (!priv->mask_ids.mask_id_free_list.buf) 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; 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, ...@@ -572,6 +583,8 @@ int nfp_flower_metadata_init(struct nfp_app *app, u64 host_ctx_count,
kfree(priv->mask_ids.last_used); kfree(priv->mask_ids.last_used);
err_free_mask_id: err_free_mask_id:
kfree(priv->mask_ids.mask_id_free_list.buf); 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: err_free_ct_zone_table:
rhashtable_destroy(&priv->ct_zone_table); rhashtable_destroy(&priv->ct_zone_table);
err_free_merge_table: err_free_merge_table:
...@@ -589,22 +602,40 @@ static void nfp_zone_table_entry_destroy(struct nfp_fl_ct_zone_entry *zt) ...@@ -589,22 +602,40 @@ static void nfp_zone_table_entry_destroy(struct nfp_fl_ct_zone_entry *zt)
return; return;
if (!list_empty(&zt->pre_ct_list)) { 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_flow_entry *entry, *tmp;
struct nfp_fl_ct_map_entry *map;
WARN_ONCE(1, "pre_ct_list not empty as expected, cleaning up\n"); 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_for_each_entry_safe(entry, tmp, &zt->pre_ct_list,
list_node) { 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); nfp_fl_ct_clean_flow_entry(entry);
kfree(map);
} }
} }
if (!list_empty(&zt->post_ct_list)) { 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_flow_entry *entry, *tmp;
struct nfp_fl_ct_map_entry *map;
WARN_ONCE(1, "post_ct_list not empty as expected, cleaning up\n"); 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_for_each_entry_safe(entry, tmp, &zt->post_ct_list,
list_node) { 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); nfp_fl_ct_clean_flow_entry(entry);
kfree(map);
} }
} }
kfree(zt); kfree(zt);
...@@ -617,6 +648,16 @@ static void nfp_free_zone_table_entry(void *ptr, void *arg) ...@@ -617,6 +648,16 @@ static void nfp_free_zone_table_entry(void *ptr, void *arg)
nfp_zone_table_entry_destroy(zt); 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) void nfp_flower_metadata_cleanup(struct nfp_app *app)
{ {
struct nfp_flower_priv *priv = app->priv; struct nfp_flower_priv *priv = app->priv;
...@@ -633,6 +674,9 @@ void nfp_flower_metadata_cleanup(struct nfp_app *app) ...@@ -633,6 +674,9 @@ void nfp_flower_metadata_cleanup(struct nfp_app *app)
rhashtable_free_and_destroy(&priv->ct_zone_table, rhashtable_free_and_destroy(&priv->ct_zone_table,
nfp_free_zone_table_entry, NULL); nfp_free_zone_table_entry, NULL);
nfp_zone_table_entry_destroy(priv->ct_zone_wc); 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); kvfree(priv->stats);
kfree(priv->mask_ids.mask_id_free_list.buf); kfree(priv->mask_ids.mask_id_free_list.buf);
kfree(priv->mask_ids.last_used); 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