From be8acb27c20f974b8f4e78cc842b2d301d5d77c2 Mon Sep 17 00:00:00 2001 From: Kishore Padmanabha Date: Fri, 9 Oct 2020 16:41:29 +0530 Subject: [PATCH] net/bnxt: add parent child flow create and free Added support in the ULP mapper to enable parent child flow creation and destroy. This feature enables support for the vxlan decap functionality. Signed-off-by: Kishore Padmanabha Reviewed-by: Mike Baucom Reviewed-by: Ajit Khaparde --- drivers/net/bnxt/tf_ulp/ulp_flow_db.c | 177 +++++++++++++++++- drivers/net/bnxt/tf_ulp/ulp_flow_db.h | 36 ++++ drivers/net/bnxt/tf_ulp/ulp_mapper.c | 87 ++++++++- drivers/net/bnxt/tf_ulp/ulp_mapper.h | 7 + .../net/bnxt/tf_ulp/ulp_template_db_enum.h | 5 +- 5 files changed, 302 insertions(+), 10 deletions(-) diff --git a/drivers/net/bnxt/tf_ulp/ulp_flow_db.c b/drivers/net/bnxt/tf_ulp/ulp_flow_db.c index a1c39329f7..3be7489083 100644 --- a/drivers/net/bnxt/tf_ulp/ulp_flow_db.c +++ b/drivers/net/bnxt/tf_ulp/ulp_flow_db.c @@ -6,10 +6,10 @@ #include #include "bnxt.h" #include "bnxt_tf_common.h" -#include "ulp_flow_db.h" #include "ulp_utils.h" #include "ulp_template_struct.h" #include "ulp_mapper.h" +#include "ulp_flow_db.h" #include "ulp_fc_mgr.h" #define ULP_FLOW_DB_RES_DIR_BIT 31 @@ -56,10 +56,10 @@ ulp_flow_db_active_flows_bit_set(struct bnxt_ulp_flow_db *flow_db, } else { if (flow_type == BNXT_ULP_FDB_TYPE_REGULAR) ULP_INDEX_BITMAP_RESET(f_tbl->active_reg_flows[a_idx], - idx); + idx); else ULP_INDEX_BITMAP_RESET(f_tbl->active_dflt_flows[a_idx], - idx); + idx); } } @@ -89,6 +89,13 @@ ulp_flow_db_active_flows_bit_is_set(struct bnxt_ulp_flow_db *flow_db, idx); } +static inline enum tf_dir +ulp_flow_db_resource_dir_get(struct ulp_fdb_resource_info *res_info) +{ + return ((res_info->nxt_resource_idx & ULP_FLOW_DB_RES_DIR_MASK) >> + ULP_FLOW_DB_RES_DIR_BIT); +} + static uint8_t ulp_flow_db_resource_func_get(struct ulp_fdb_resource_info *res_info) { @@ -157,11 +164,9 @@ ulp_flow_db_res_info_to_params(struct ulp_fdb_resource_info *resource_info, struct ulp_flow_db_res_params *params) { memset(params, 0, sizeof(struct ulp_flow_db_res_params)); - params->direction = ((resource_info->nxt_resource_idx & - ULP_FLOW_DB_RES_DIR_MASK) >> - ULP_FLOW_DB_RES_DIR_BIT); /* use the helper function to get the resource func */ + params->direction = ulp_flow_db_resource_dir_get(resource_info); params->resource_func = ulp_flow_db_resource_func_get(resource_info); if (params->resource_func == BNXT_ULP_RESOURCE_FUNC_EXT_EM_TABLE || @@ -303,6 +308,9 @@ ulp_flow_db_parent_tbl_init(struct bnxt_ulp_flow_db *flow_db, struct ulp_fdb_parent_child_db *p_db; uint32_t size, idx; + if (!num_entries) + return 0; + /* update the sizes for the allocation */ p_db = &flow_db->parent_child_db; p_db->child_bitset_size = (flow_db->flow_tbl.num_flows / @@ -1171,6 +1179,12 @@ ulp_flow_db_parent_flow_alloc(struct bnxt_ulp_context *ulp_ctxt, return -EINVAL; } + /* No support for parent child db then just exit */ + if (!flow_db->parent_child_db.entries_count) { + BNXT_TF_DBG(ERR, "parent child db not supported\n"); + return -EINVAL; + } + p_pdb = &flow_db->parent_child_db; for (idx = 0; idx <= p_pdb->entries_count; idx++) { if (p_pdb->parent_flow_tbl[idx].parent_fid == fid) { @@ -1220,6 +1234,12 @@ ulp_flow_db_parent_flow_free(struct bnxt_ulp_context *ulp_ctxt, return -EINVAL; } + /* No support for parent child db then just exit */ + if (!flow_db->parent_child_db.entries_count) { + BNXT_TF_DBG(ERR, "parent child db not supported\n"); + return -EINVAL; + } + p_pdb = &flow_db->parent_child_db; for (idx = 0; idx <= p_pdb->entries_count; idx++) { if (p_pdb->parent_flow_tbl[idx].parent_fid == fid) { @@ -1273,6 +1293,12 @@ ulp_flow_db_parent_child_flow_set(struct bnxt_ulp_context *ulp_ctxt, return -EINVAL; } + /* No support for parent child db then just exit */ + if (!flow_db->parent_child_db.entries_count) { + BNXT_TF_DBG(ERR, "parent child db not supported\n"); + return -EINVAL; + } + p_pdb = &flow_db->parent_child_db; a_idx = child_fid / ULP_INDEX_BITMAP_SIZE; for (idx = 0; idx <= p_pdb->entries_count; idx++) { @@ -1320,6 +1346,12 @@ ulp_flow_db_parent_flow_idx_get(struct bnxt_ulp_context *ulp_ctxt, return -EINVAL; } + /* No support for parent child db then just exit */ + if (!flow_db->parent_child_db.entries_count) { + BNXT_TF_DBG(ERR, "parent child db not supported\n"); + return -EINVAL; + } + p_pdb = &flow_db->parent_child_db; for (idx = 0; idx <= p_pdb->entries_count; idx++) { if (p_pdb->parent_flow_tbl[idx].parent_fid == parent_fid) { @@ -1392,3 +1424,136 @@ ulp_flow_db_parent_child_flow_next_entry_get(struct bnxt_ulp_flow_db *flow_db, *child_fid = next_fid; return 0; } + +/* + * Orphan the child flow entry + * This is called only for child flows that have + * BNXT_ULP_RESOURCE_FUNC_CHILD_FLOW resource + * + * ulp_ctxt [in] Ptr to ulp_context + * flow_type [in] Specify it is regular or default flow + * fid [in] The index to the flow entry + * + * Returns 0 on success and negative on failure. + */ +int32_t +ulp_flow_db_child_flow_reset(struct bnxt_ulp_context *ulp_ctxt, + enum bnxt_ulp_fdb_type flow_type, + uint32_t fid) +{ + struct bnxt_ulp_flow_db *flow_db; + struct bnxt_ulp_flow_tbl *flow_tbl; + struct ulp_fdb_resource_info *fid_res; + uint32_t res_id = 0; + + flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt); + if (!flow_db) { + BNXT_TF_DBG(ERR, "Invalid Arguments\n"); + return -EINVAL; + } + + if (flow_type > BNXT_ULP_FDB_TYPE_DEFAULT) { + BNXT_TF_DBG(ERR, "Invalid flow type\n"); + return -EINVAL; + } + + flow_tbl = &flow_db->flow_tbl; + /* check for max flows */ + if (fid >= flow_tbl->num_flows || !fid) { + BNXT_TF_DBG(ERR, "Invalid flow index %x\n", fid); + return -EINVAL; + } + + /* check if the flow is active or not */ + if (!ulp_flow_db_active_flows_bit_is_set(flow_db, flow_type, fid)) { + BNXT_TF_DBG(ERR, "flow does not exist\n"); + return -EINVAL; + } + + /* Iterate the resource to get the resource handle */ + res_id = fid; + while (res_id) { + fid_res = &flow_tbl->flow_resources[res_id]; + if (ulp_flow_db_resource_func_get(fid_res) == + BNXT_ULP_RESOURCE_FUNC_CHILD_FLOW) { + /* invalidate the resource details */ + fid_res->resource_hndl = 0; + return 0; + } + res_id = 0; + ULP_FLOW_DB_RES_NXT_SET(res_id, fid_res->nxt_resource_idx); + } + /* failed */ + return -1; +} + +/* + * Create parent flow in the parent flow tbl + * + * parms [in] Ptr to mapper params + * + * Returns 0 on success and negative on failure. + */ +int32_t +ulp_flow_db_parent_flow_create(struct bnxt_ulp_mapper_parms *parms) +{ + struct ulp_flow_db_res_params fid_parms; + int32_t fid_idx; + + /* create the child flow entry in parent flow table */ + fid_idx = ulp_flow_db_parent_flow_alloc(parms->ulp_ctx, parms->fid); + if (fid_idx < 0) { + BNXT_TF_DBG(ERR, "Error in creating parent flow fid %x\n", + parms->fid); + return -1; + } + + /* Add the parent details in the resource list of the flow */ + memset(&fid_parms, 0, sizeof(fid_parms)); + fid_parms.resource_func = BNXT_ULP_RESOURCE_FUNC_PARENT_FLOW; + fid_parms.resource_hndl = fid_idx; + fid_parms.critical_resource = BNXT_ULP_CRITICAL_RESOURCE_NO; + if (ulp_flow_db_resource_add(parms->ulp_ctx, BNXT_ULP_FDB_TYPE_REGULAR, + parms->fid, &fid_parms)) { + BNXT_TF_DBG(ERR, "Error in adding flow res for fid %x\n", + parms->fid); + return -1; + } + return 0; +} + +/* + * Create child flow in the parent flow tbl + * + * parms [in] Ptr to mapper params + * + * Returns 0 on success and negative on failure. + */ +int32_t +ulp_flow_db_child_flow_create(struct bnxt_ulp_mapper_parms *parms) +{ + struct ulp_flow_db_res_params fid_parms; + int32_t rc; + + /* create the parent flow entry in parent flow table */ + rc = ulp_flow_db_parent_child_flow_set(parms->ulp_ctx, + parms->parent_fid, + parms->fid, 1); + if (rc) { + BNXT_TF_DBG(ERR, "Error in setting child fid %x\n", parms->fid); + return -1; + } + + /* Add the parent details in the resource list of the flow */ + memset(&fid_parms, 0, sizeof(fid_parms)); + fid_parms.resource_func = BNXT_ULP_RESOURCE_FUNC_CHILD_FLOW; + fid_parms.resource_hndl = parms->parent_fid; + fid_parms.critical_resource = BNXT_ULP_CRITICAL_RESOURCE_NO; + if (ulp_flow_db_resource_add(parms->ulp_ctx, BNXT_ULP_FDB_TYPE_REGULAR, + parms->fid, &fid_parms)) { + BNXT_TF_DBG(ERR, "Error in adding flow res for fid %x\n", + parms->fid); + return -1; + } + return 0; +} diff --git a/drivers/net/bnxt/tf_ulp/ulp_flow_db.h b/drivers/net/bnxt/tf_ulp/ulp_flow_db.h index 87bcd69aee..95fd1992d6 100644 --- a/drivers/net/bnxt/tf_ulp/ulp_flow_db.h +++ b/drivers/net/bnxt/tf_ulp/ulp_flow_db.h @@ -8,6 +8,7 @@ #include "bnxt_ulp.h" #include "ulp_template_db_enum.h" +#include "ulp_mapper.h" #define BNXT_FLOW_DB_DEFAULT_NUM_FLOWS 512 #define BNXT_FLOW_DB_DEFAULT_NUM_RESOURCES 8 @@ -319,5 +320,40 @@ ulp_flow_db_parent_child_flow_next_entry_get(struct bnxt_ulp_flow_db *flow_db, uint32_t parent_idx, uint32_t *child_fid); +/* + * Orphan the child flow entry + * This is called only for child flows that have + * BNXT_ULP_RESOURCE_FUNC_CHILD_FLOW resource + * + * ulp_ctxt [in] Ptr to ulp_context + * flow_type [in] Specify it is regular or default flow + * fid [in] The index to the flow entry + * + * Returns 0 on success and negative on failure. + */ +int32_t +ulp_flow_db_child_flow_reset(struct bnxt_ulp_context *ulp_ctxt, + enum bnxt_ulp_fdb_type flow_type, + uint32_t fid); + +/* + * Create parent flow in the parent flow tbl + * + * parms [in] Ptr to mapper params + * + * Returns 0 on success and negative on failure. + */ +int32_t +ulp_flow_db_parent_flow_create(struct bnxt_ulp_mapper_parms *parms); + +/* + * Create child flow in the parent flow tbl + * + * parms [in] Ptr to mapper params + * + * Returns 0 on success and negative on failure. + */ +int32_t +ulp_flow_db_child_flow_create(struct bnxt_ulp_mapper_parms *parms); #endif /* _ULP_FLOW_DB_H_ */ diff --git a/drivers/net/bnxt/tf_ulp/ulp_mapper.c b/drivers/net/bnxt/tf_ulp/ulp_mapper.c index cd289cc40d..b74cb92f57 100644 --- a/drivers/net/bnxt/tf_ulp/ulp_mapper.c +++ b/drivers/net/bnxt/tf_ulp/ulp_mapper.c @@ -14,8 +14,8 @@ #include "tfp.h" #include "tf_ext_flow_handle.h" #include "ulp_mark_mgr.h" -#include "ulp_flow_db.h" #include "ulp_mapper.h" +#include "ulp_flow_db.h" #include "tf_util.h" static struct bnxt_ulp_glb_resource_info * @@ -537,6 +537,65 @@ ulp_mapper_mark_free(struct bnxt_ulp_context *ulp, res->resource_hndl); } + +static inline int32_t +ulp_mapper_parent_flow_free(struct bnxt_ulp_context *ulp, + uint32_t parent_fid, + struct ulp_flow_db_res_params *res) +{ + uint32_t idx, child_fid = 0, parent_idx; + struct bnxt_ulp_flow_db *flow_db; + + parent_idx = (uint32_t)res->resource_hndl; + + /* check the validity of the parent fid */ + if (ulp_flow_db_parent_flow_idx_get(ulp, parent_fid, &idx) || + idx != parent_idx) { + BNXT_TF_DBG(ERR, "invalid parent flow id %x\n", parent_fid); + return -EINVAL; + } + + /* Clear all the child flows parent index */ + flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp); + while (!ulp_flow_db_parent_child_flow_next_entry_get(flow_db, idx, + &child_fid)) { + /* update the child flows resource handle */ + if (ulp_flow_db_child_flow_reset(ulp, BNXT_ULP_FDB_TYPE_REGULAR, + child_fid)) { + BNXT_TF_DBG(ERR, "failed to reset child flow %x\n", + child_fid); + return -EINVAL; + } + } + + /* free the parent entry in the parent table flow */ + if (ulp_flow_db_parent_flow_free(ulp, parent_fid)) { + BNXT_TF_DBG(ERR, "failed to free parent flow %x\n", parent_fid); + return -EINVAL; + } + return 0; +} + +static inline int32_t +ulp_mapper_child_flow_free(struct bnxt_ulp_context *ulp, + uint32_t child_fid, + struct ulp_flow_db_res_params *res) +{ + uint32_t parent_fid; + + parent_fid = (uint32_t)res->resource_hndl; + if (!parent_fid) + return 0; /* Already freed - orphan child*/ + + /* reset the child flow bitset*/ + if (ulp_flow_db_parent_child_flow_set(ulp, parent_fid, child_fid, 0)) { + BNXT_TF_DBG(ERR, "error in resetting child flow bitset %x:%x\n", + parent_fid, child_fid); + return -EINVAL; + } + return 0; +} + /* * Process the identifier instruction and either store it in the flow database * or return it in the val (if not NULL) on success. If val is NULL, the @@ -2484,6 +2543,7 @@ error: static int32_t ulp_mapper_resource_free(struct bnxt_ulp_context *ulp, + uint32_t fid, struct ulp_flow_db_res_params *res) { struct tf *tfp; @@ -2520,6 +2580,12 @@ ulp_mapper_resource_free(struct bnxt_ulp_context *ulp, case BNXT_ULP_RESOURCE_FUNC_HW_FID: rc = ulp_mapper_mark_free(ulp, res); break; + case BNXT_ULP_RESOURCE_FUNC_PARENT_FLOW: + rc = ulp_mapper_parent_flow_free(ulp, fid, res); + break; + case BNXT_ULP_RESOURCE_FUNC_CHILD_FLOW: + rc = ulp_mapper_child_flow_free(ulp, fid, res); + break; default: break; } @@ -2558,7 +2624,7 @@ ulp_mapper_resources_free(struct bnxt_ulp_context *ulp_ctx, } while (!rc) { - trc = ulp_mapper_resource_free(ulp_ctx, &res_parms); + trc = ulp_mapper_resource_free(ulp_ctx, fid, &res_parms); if (trc) /* * On fail, we still need to attempt to free the @@ -2608,7 +2674,7 @@ ulp_mapper_glb_resource_info_deinit(struct bnxt_ulp_context *ulp_ctx, /*convert it from BE to cpu */ res.resource_hndl = tfp_be_to_cpu_64(ent->resource_hndl); - ulp_mapper_resource_free(ulp_ctx, &res); + ulp_mapper_resource_free(ulp_ctx, 0, &res); } } } @@ -2720,6 +2786,8 @@ ulp_mapper_flow_create(struct bnxt_ulp_context *ulp_ctx, parms.act_tid = cparms->act_tid; parms.class_tid = cparms->class_tid; parms.flow_type = cparms->flow_type; + parms.parent_flow = cparms->parent_flow; + parms.parent_fid = cparms->parent_fid; /* Get the device id from the ulp context */ if (bnxt_ulp_cntxt_dev_id_get(ulp_ctx, &parms.dev_id)) { @@ -2797,6 +2865,19 @@ ulp_mapper_flow_create(struct bnxt_ulp_context *ulp_ctx, goto flow_error; } + /* setup the parent-child details */ + if (parms.parent_flow) { + /* create a parent flow details */ + rc = ulp_flow_db_parent_flow_create(&parms); + if (rc) + goto flow_error; + } else if (parms.parent_fid) { + /* create a child flow details */ + rc = ulp_flow_db_child_flow_create(&parms); + if (rc) + goto flow_error; + } + *flowid = parms.fid; bnxt_ulp_cntxt_release_fdb_lock(ulp_ctx); diff --git a/drivers/net/bnxt/tf_ulp/ulp_mapper.h b/drivers/net/bnxt/tf_ulp/ulp_mapper.h index 6f93bcdc1f..542e41e5aa 100644 --- a/drivers/net/bnxt/tf_ulp/ulp_mapper.h +++ b/drivers/net/bnxt/tf_ulp/ulp_mapper.h @@ -76,6 +76,8 @@ struct bnxt_ulp_mapper_parms { enum bnxt_ulp_cache_table_opc tcam_tbl_opc; struct bnxt_ulp_mapper_cache_entry *cache_ptr; struct bnxt_ulp_device_params *device_params; + uint32_t parent_fid; + uint32_t parent_flow; }; struct bnxt_ulp_mapper_create_parms { @@ -90,6 +92,11 @@ struct bnxt_ulp_mapper_create_parms { uint16_t func_id; uint32_t dir_attr; enum bnxt_ulp_fdb_type flow_type; + + /* if set then create it as a child flow with parent as parent_fid */ + uint32_t parent_fid; + /* if set then create a parent flow */ + uint32_t parent_flow; }; /* Function to initialize any dynamic mapper data. */ diff --git a/drivers/net/bnxt/tf_ulp/ulp_template_db_enum.h b/drivers/net/bnxt/tf_ulp/ulp_template_db_enum.h index 81da34e3a2..168e308c2b 100644 --- a/drivers/net/bnxt/tf_ulp/ulp_template_db_enum.h +++ b/drivers/net/bnxt/tf_ulp/ulp_template_db_enum.h @@ -321,7 +321,10 @@ enum bnxt_ulp_resource_func { BNXT_ULP_RESOURCE_FUNC_CACHE_TABLE = 0x82, BNXT_ULP_RESOURCE_FUNC_IDENTIFIER = 0x83, BNXT_ULP_RESOURCE_FUNC_IF_TABLE = 0x84, - BNXT_ULP_RESOURCE_FUNC_HW_FID = 0x85 + BNXT_ULP_RESOURCE_FUNC_HW_FID = 0x85, + BNXT_ULP_RESOURCE_FUNC_SHARED_TABLE = 0x86, + BNXT_ULP_RESOURCE_FUNC_PARENT_FLOW = 0x87, + BNXT_ULP_RESOURCE_FUNC_CHILD_FLOW = 0x88 }; enum bnxt_ulp_resource_sub_type { -- 2.20.1