From fa81d6d214a4202b539a815d6c9d6b3c8e70ca95 Mon Sep 17 00:00:00 2001 From: Louis Peens Date: Wed, 2 Jun 2021 13:59:50 +0200 Subject: [PATCH] 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: Louis Peens Signed-off-by: Yinjun Zhang Signed-off-by: Simon Horman Signed-off-by: David S. Miller --- .../net/ethernet/netronome/nfp/flower/conntrack.c | 35 +++++++++++++--- .../net/ethernet/netronome/nfp/flower/conntrack.h | 13 ++++++ drivers/net/ethernet/netronome/nfp/flower/main.h | 2 + .../net/ethernet/netronome/nfp/flower/metadata.c | 46 +++++++++++++++++++++- 4 files changed, 89 insertions(+), 7 deletions(-) diff --git a/drivers/net/ethernet/netronome/nfp/flower/conntrack.c b/drivers/net/ethernet/netronome/nfp/flower/conntrack.c index 57a5ba5..f6f9722 100644 --- a/drivers/net/ethernet/netronome/nfp/flower/conntrack.c +++ b/drivers/net/ethernet/netronome/nfp/flower/conntrack.c @@ -107,9 +107,11 @@ err_zone_insert: 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); diff --git a/drivers/net/ethernet/netronome/nfp/flower/conntrack.h b/drivers/net/ethernet/netronome/nfp/flower/conntrack.h index 46437de..a7f0d7c 100644 --- a/drivers/net/ethernet/netronome/nfp/flower/conntrack.h +++ b/drivers/net/ethernet/netronome/nfp/flower/conntrack.h @@ -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); diff --git a/drivers/net/ethernet/netronome/nfp/flower/main.h b/drivers/net/ethernet/netronome/nfp/flower/main.h index 060c6de..0fbd682 100644 --- a/drivers/net/ethernet/netronome/nfp/flower/main.h +++ b/drivers/net/ethernet/netronome/nfp/flower/main.h @@ -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; }; /** diff --git a/drivers/net/ethernet/netronome/nfp/flower/metadata.c b/drivers/net/ethernet/netronome/nfp/flower/metadata.c index 062e963..7654cf6 100644 --- a/drivers/net/ethernet/netronome/nfp/flower/metadata.c +++ b/drivers/net/ethernet/netronome/nfp/flower/metadata.c @@ -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 @@ err_free_last_used: 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); -- 2.7.4