net/bnxt: add session and function flow flush
authorKishore Padmanabha <kishore.padmanabha@broadcom.com>
Wed, 15 Apr 2020 14:49:13 +0000 (20:19 +0530)
committerFerruh Yigit <ferruh.yigit@intel.com>
Tue, 21 Apr 2020 11:57:09 +0000 (13:57 +0200)
The ulp flow flush has been extended to support session flow
flush and function flow flush. The session flow flush is called when
there the device is sole owner of the session and it deletes all the
flows associated with that session. The function flow flush is
called if the device function is not the sole owner of the session,
it deletes all the flows that are associated with that device
function.

Reviewed-by: Venkat Duvvuru <venkatkumar.duvvuru@broadcom.com>
Reviewed-by: Mike Baucom <michael.baucom@broadcom.com>
Reviewed-by: Ajit Khaparde <ajit.khaparde@broadcom.com>
Signed-off-by: Kishore Padmanabha <kishore.padmanabha@broadcom.com>
Signed-off-by: Venkat Duvvuru <venkatkumar.duvvuru@broadcom.com>
drivers/net/bnxt/bnxt.h
drivers/net/bnxt/bnxt_ethdev.c
drivers/net/bnxt/tf_ulp/bnxt_ulp.c
drivers/net/bnxt/tf_ulp/bnxt_ulp_flow.c
drivers/net/bnxt/tf_ulp/ulp_flow_db.c
drivers/net/bnxt/tf_ulp/ulp_flow_db.h
drivers/net/bnxt/tf_ulp/ulp_mapper.c
drivers/net/bnxt/tf_ulp/ulp_mapper.h

index ffb3a0e..a7a9e41 100644 (file)
@@ -755,6 +755,7 @@ void bnxt_ulp_deinit(struct bnxt *bp);
 
 uint16_t bnxt_get_vnic_id(uint16_t port);
 uint16_t bnxt_get_svif(uint16_t port_id, bool func_svif);
+uint16_t bnxt_get_fw_func_id(uint16_t port);
 
 void bnxt_cancel_fc_thread(struct bnxt *bp);
 void bnxt_flow_cnt_alarm_cb(void *arg);
index 6c1234b..d29671d 100644 (file)
@@ -4905,6 +4905,18 @@ bnxt_get_vnic_id(uint16_t port)
        return vnic->fw_vnic_id;
 }
 
+uint16_t
+bnxt_get_fw_func_id(uint16_t port)
+{
+       struct rte_eth_dev *eth_dev;
+       struct bnxt *bp;
+
+       eth_dev = &rte_eth_devices[port];
+       bp = eth_dev->data->dev_private;
+
+       return bp->fw_fid;
+}
+
 static int bnxt_init_fw(struct bnxt *bp)
 {
        uint16_t mtu;
index 56e08f2..c67da6d 100644 (file)
@@ -659,10 +659,8 @@ int32_t
 bnxt_ulp_cntxt_ptr2_flow_db_set(struct bnxt_ulp_context        *ulp_ctx,
                                struct bnxt_ulp_flow_db *flow_db)
 {
-       if (!ulp_ctx || !ulp_ctx->cfg_data) {
-               BNXT_TF_DBG(ERR, "Invalid ulp context data\n");
+       if (!ulp_ctx || !ulp_ctx->cfg_data)
                return -EINVAL;
-       }
 
        ulp_ctx->cfg_data->flow_db = flow_db;
        return 0;
@@ -672,10 +670,8 @@ bnxt_ulp_cntxt_ptr2_flow_db_set(struct bnxt_ulp_context    *ulp_ctx,
 struct bnxt_ulp_flow_db        *
 bnxt_ulp_cntxt_ptr2_flow_db_get(struct bnxt_ulp_context        *ulp_ctx)
 {
-       if (!ulp_ctx || !ulp_ctx->cfg_data) {
-               BNXT_TF_DBG(ERR, "Invalid ulp context data\n");
+       if (!ulp_ctx || !ulp_ctx->cfg_data)
                return NULL;
-       }
 
        return ulp_ctx->cfg_data->flow_db;
 }
index 7f7aa24..f0c812c 100644 (file)
@@ -125,6 +125,7 @@ bnxt_ulp_flow_create(struct rte_eth_dev *dev,
        mapper_cparms.act_prop = &params.act_prop;
        mapper_cparms.class_tid = class_id;
        mapper_cparms.act_tid = act_tmpl;
+       mapper_cparms.func_id = bnxt_get_fw_func_id(dev->data->port_id);
 
        /* call the ulp mapper to create the flow in the hardware */
        ret = ulp_mapper_flow_create(ulp_ctx,
@@ -202,7 +203,8 @@ bnxt_ulp_flow_destroy(struct rte_eth_dev *dev,
 {
        int ret = 0;
        struct bnxt_ulp_context *ulp_ctx;
-       uint32_t fid;
+       uint32_t flow_id;
+       uint16_t func_id;
 
        ulp_ctx = bnxt_ulp_eth_dev_ptr2_cntxt_get(dev);
        if (!ulp_ctx) {
@@ -213,9 +215,19 @@ bnxt_ulp_flow_destroy(struct rte_eth_dev *dev,
                return -EINVAL;
        }
 
-       fid = (uint32_t)(uintptr_t)flow;
+       flow_id = (uint32_t)(uintptr_t)flow;
+       func_id = bnxt_get_fw_func_id(dev->data->port_id);
 
-       ret = ulp_mapper_flow_destroy(ulp_ctx, fid);
+       if (ulp_flow_db_validate_flow_func(ulp_ctx, flow_id, func_id) ==
+           false) {
+               BNXT_TF_DBG(ERR, "Incorrect device params\n");
+               rte_flow_error_set(error, EINVAL,
+                                  RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
+                                  "Failed to destroy flow.");
+               return -EINVAL;
+       }
+
+       ret = ulp_mapper_flow_destroy(ulp_ctx, flow_id);
        if (ret)
                rte_flow_error_set(error, -ret,
                                   RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
@@ -230,8 +242,9 @@ bnxt_ulp_flow_flush(struct rte_eth_dev *eth_dev,
                    struct rte_flow_error *error)
 {
        struct bnxt_ulp_context *ulp_ctx;
-       int32_t ret;
+       int32_t ret = 0;
        struct bnxt *bp;
+       uint16_t func_id;
 
        ulp_ctx = bnxt_ulp_eth_dev_ptr2_cntxt_get(eth_dev);
        if (!ulp_ctx) {
@@ -244,10 +257,12 @@ bnxt_ulp_flow_flush(struct rte_eth_dev *eth_dev,
        bp = eth_dev->data->dev_private;
 
        /* Free the resources for the last device */
-       if (!ulp_ctx_deinit_allowed(bp))
-               return 0;
-
-       ret = ulp_flow_db_flush_flows(ulp_ctx, BNXT_ULP_REGULAR_FLOW_TABLE);
+       if (ulp_ctx_deinit_allowed(bp)) {
+               ret = ulp_flow_db_session_flow_flush(ulp_ctx);
+       } else if (bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctx)) {
+               func_id = bnxt_get_fw_func_id(eth_dev->data->port_id);
+               ret = ulp_flow_db_function_flow_flush(ulp_ctx, func_id);
+       }
        if (ret)
                rte_flow_error_set(error, ret,
                                   RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
index 9e7f9f5..35a7f86 100644 (file)
@@ -209,6 +209,27 @@ ulp_flow_db_dealloc_resource(struct bnxt_ulp_flow_db *flow_db,
        }
 }
 
+/*
+ * Helper function to add function id to the flow table
+ *
+ * flow_db [in] Ptr to flow table
+ * flow_id [in] The flow id of the flow
+ * func_id [in] The func_id to be set, for reset pass zero
+ *
+ * returns none
+ */
+static void
+ulp_flow_db_func_id_set(struct bnxt_ulp_flow_db *flow_db,
+                       uint32_t flow_id,
+                       uint32_t func_id)
+{
+       /* set the function id in the function table */
+       if (flow_id < flow_db->func_id_tbl_size)
+               flow_db->func_id_tbl[flow_id] = func_id;
+       else /* This should never happen */
+               BNXT_TF_DBG(ERR, "Invalid flow id, flowdb corrupt\n");
+}
+
 /*
  * Initialize the flow database. Memory is allocated in this
  * call and assigned to the flow database.
@@ -241,7 +262,7 @@ int32_t     ulp_flow_db_init(struct bnxt_ulp_context *ulp_ctxt)
        if (!flow_db) {
                BNXT_TF_DBG(ERR,
                            "Failed to allocate memory for flow table ptr\n");
-               goto error_free;
+               return -ENOMEM;
        }
 
        /* Attach the flow database to the ulp context. */
@@ -265,6 +286,17 @@ int32_t    ulp_flow_db_init(struct bnxt_ulp_context *ulp_ctxt)
        if (ulp_flow_db_alloc_resource(flow_db, BNXT_ULP_DEFAULT_FLOW_TABLE))
                goto error_free;
 
+       /* add 1 since we are not using index 0 for flow id */
+       flow_db->func_id_tbl_size = dparms->num_flows + 1;
+       /* Allocate the function Id table */
+       flow_db->func_id_tbl = rte_zmalloc("bnxt_ulp_flow_db_func_id_table",
+                                          flow_db->func_id_tbl_size *
+                                          sizeof(uint16_t), 0);
+       if (!flow_db->func_id_tbl) {
+               BNXT_TF_DBG(ERR,
+                           "Failed to allocate mem for flow table func id\n");
+               goto error_free;
+       }
        /* All good so return. */
        return 0;
 error_free:
@@ -297,6 +329,7 @@ int32_t     ulp_flow_db_deinit(struct bnxt_ulp_context *ulp_ctxt)
        /* Free up all the memory. */
        ulp_flow_db_dealloc_resource(flow_db, BNXT_ULP_REGULAR_FLOW_TABLE);
        ulp_flow_db_dealloc_resource(flow_db, BNXT_ULP_DEFAULT_FLOW_TABLE);
+       rte_free(flow_db->func_id_tbl);
        rte_free(flow_db);
 
        return 0;
@@ -311,12 +344,13 @@ int32_t   ulp_flow_db_deinit(struct bnxt_ulp_context *ulp_ctxt)
  *
  * returns 0 on success and negative on failure.
  */
-int32_t ulp_flow_db_fid_alloc(struct bnxt_ulp_context          *ulp_ctxt,
-                             enum bnxt_ulp_flow_db_tables      tbl_idx,
-                             uint32_t                          *fid)
+int32_t ulp_flow_db_fid_alloc(struct bnxt_ulp_context *ulp_ctxt,
+                             enum bnxt_ulp_flow_db_tables tbl_idx,
+                             uint16_t func_id,
+                             uint32_t *fid)
 {
-       struct bnxt_ulp_flow_db         *flow_db;
-       struct bnxt_ulp_flow_tbl        *flow_tbl;
+       struct bnxt_ulp_flow_db *flow_db;
+       struct bnxt_ulp_flow_tbl *flow_tbl;
 
        *fid = 0; /* Initialize fid to invalid value */
        flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
@@ -339,6 +373,10 @@ int32_t ulp_flow_db_fid_alloc(struct bnxt_ulp_context              *ulp_ctxt,
        flow_tbl->head_index++;
        ulp_flow_db_active_flow_set(flow_tbl, *fid, 1);
 
+       /* The function id update is only valid for regular flow table */
+       if (tbl_idx == BNXT_ULP_REGULAR_FLOW_TABLE)
+               ulp_flow_db_func_id_set(flow_db, *fid, func_id);
+
        /* all good, return success */
        return 0;
 }
@@ -555,6 +593,8 @@ int32_t     ulp_flow_db_fid_free(struct bnxt_ulp_context            *ulp_ctxt,
        }
        flow_tbl->flow_tbl_stack[flow_tbl->head_index] = fid;
        ulp_flow_db_active_flow_set(flow_tbl, fid, 0);
+       if (tbl_idx == BNXT_ULP_REGULAR_FLOW_TABLE)
+               ulp_flow_db_func_id_set(flow_db, fid, 0);
 
        /* all good, return success */
        return 0;
@@ -636,19 +676,29 @@ ulp_flow_db_next_entry_get(struct bnxt_ulp_flow_tbl       *flowtbl,
                           uint32_t                     *fid)
 {
        uint32_t        lfid = *fid;
-       uint32_t        idx;
+       uint32_t        idx, s_idx, mod_fid;
        uint64_t        bs;
 
        do {
+               /* increment the flow id to find the next valid flow id */
                lfid++;
                if (lfid >= flowtbl->num_flows)
                        return -ENOENT;
                idx = lfid / ULP_INDEX_BITMAP_SIZE;
+               mod_fid = lfid % ULP_INDEX_BITMAP_SIZE;
+               s_idx = idx;
                while (!(bs = flowtbl->active_flow_tbl[idx])) {
                        idx++;
                        if ((idx * ULP_INDEX_BITMAP_SIZE) >= flowtbl->num_flows)
                                return -ENOENT;
                }
+               /*
+                * remove the previous bits in the bitset bs to find the
+                * next non zero bit in the bitset. This needs to be done
+                * only if the idx is same as he one you started.
+                */
+               if (s_idx == idx)
+                       bs &= (-1UL >> mod_fid);
                lfid = (idx * ULP_INDEX_BITMAP_SIZE) + __builtin_clzl(bs);
                if (*fid >= lfid) {
                        BNXT_TF_DBG(ERR, "Flow Database is corrupt\n");
@@ -688,7 +738,90 @@ int32_t    ulp_flow_db_flush_flows(struct bnxt_ulp_context *ulp_ctx,
        }
        flow_tbl = &flow_db->flow_tbl[idx];
        while (!ulp_flow_db_next_entry_get(flow_tbl, &fid))
-               (void)ulp_mapper_resources_free(ulp_ctx, fid, idx);
+               ulp_mapper_resources_free(ulp_ctx, fid, idx);
 
        return 0;
 }
+
+/*
+ * Flush all flows in the flow database that belong to a device function.
+ *
+ * ulp_ctxt [in] Ptr to ulp context
+ * tbl_idx [in] The index to table
+ *
+ * returns 0 on success or negative number on failure
+ */
+int32_t
+ulp_flow_db_function_flow_flush(struct bnxt_ulp_context *ulp_ctx,
+                               uint16_t func_id)
+{
+       uint32_t flow_id = 0;
+       struct bnxt_ulp_flow_db *flow_db;
+       struct bnxt_ulp_flow_tbl *flow_tbl;
+
+       if (!ulp_ctx || !func_id) {
+               BNXT_TF_DBG(ERR, "Invalid Argument\n");
+               return -EINVAL;
+       }
+
+       flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctx);
+       if (!flow_db) {
+               BNXT_TF_DBG(ERR, "Flow database not found\n");
+               return -EINVAL;
+       }
+       flow_tbl = &flow_db->flow_tbl[BNXT_ULP_REGULAR_FLOW_TABLE];
+       while (!ulp_flow_db_next_entry_get(flow_tbl, &flow_id)) {
+               if (flow_db->func_id_tbl[flow_id] == func_id)
+                       ulp_mapper_resources_free(ulp_ctx, flow_id,
+                                                 BNXT_ULP_REGULAR_FLOW_TABLE);
+       }
+
+       return 0;
+}
+
+/*
+ * Flush all flows in the flow database that are associated with the session.
+ *
+ * ulp_ctxt [in] Ptr to ulp context
+ *
+ * returns 0 on success or negative number on failure
+ */
+int32_t
+ulp_flow_db_session_flow_flush(struct bnxt_ulp_context *ulp_ctx)
+{
+       /*
+        * TBD: Tf core implementation of FW session flush shall change this
+        * implementation.
+        */
+       return ulp_flow_db_flush_flows(ulp_ctx, BNXT_ULP_REGULAR_FLOW_TABLE);
+}
+
+/*
+ * Check that flow id matches the function id or not
+ *
+ * ulp_ctxt [in] Ptr to ulp context
+ * flow_db [in] Ptr to flow table
+ * func_id [in] The func_id to be set, for reset pass zero.
+ *
+ * returns true on success or false on failure
+ */
+bool
+ulp_flow_db_validate_flow_func(struct bnxt_ulp_context *ulp_ctx,
+                              uint32_t flow_id,
+                              uint32_t func_id)
+{
+       struct bnxt_ulp_flow_db *flow_db;
+
+       flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctx);
+       if (!flow_db) {
+               BNXT_TF_DBG(ERR, "Flow database not found\n");
+               return false;
+       }
+
+       /* set the function id in the function table */
+       if (flow_id < flow_db->func_id_tbl_size && func_id &&
+           flow_db->func_id_tbl[flow_id] == func_id)
+               return true;
+
+       return false;
+}
index 5361dd0..ebca849 100644 (file)
@@ -51,6 +51,8 @@ enum bnxt_ulp_flow_db_tables {
 /* Structure for the flow database resource information. */
 struct bnxt_ulp_flow_db {
        struct bnxt_ulp_flow_tbl        flow_tbl[BNXT_ULP_FLOW_TABLE_MAX];
+       uint16_t                        *func_id_tbl;
+       uint32_t                        func_id_tbl_size;
 };
 
 /* flow db resource params to add resources */
@@ -88,13 +90,15 @@ int32_t     ulp_flow_db_deinit(struct bnxt_ulp_context *ulp_ctxt);
  *
  * ulp_ctxt [in] Ptr to ulp_context
  * tbl_idx [in] Specify it is regular or default flow
+ * func_id [in] The function id of the device.Valid only for regular flows.
  * fid [out] The index to the flow entry
  *
  * returns 0 on success and negative on failure.
  */
-int32_t ulp_flow_db_fid_alloc(struct bnxt_ulp_context          *ulp_ctxt,
-                             enum bnxt_ulp_flow_db_tables      tbl_idx,
-                             uint32_t                          *fid);
+int32_t ulp_flow_db_fid_alloc(struct bnxt_ulp_context *ulp_ctxt,
+                             enum bnxt_ulp_flow_db_tables tbl_idx,
+                             uint16_t func_id,
+                             uint32_t *fid);
 
 /*
  * Allocate the flow database entry.
@@ -170,4 +174,40 @@ int32_t    ulp_flow_db_resource_get(struct bnxt_ulp_context        *ulp_ctxt,
 int32_t        ulp_flow_db_flush_flows(struct bnxt_ulp_context *ulp_ctx,
                                uint32_t                idx);
 
+/*
+ * Flush all flows in the flow database that belong to a device function.
+ *
+ * ulp_ctxt [in] Ptr to ulp context
+ * tbl_idx [in] The index to table
+ *
+ * returns 0 on success or negative number on failure
+ */
+int32_t
+ulp_flow_db_function_flow_flush(struct bnxt_ulp_context *ulp_ctx,
+                               uint16_t func_id);
+
+/*
+ * Flush all flows in the flow database that are associated with the session.
+ *
+ * ulp_ctxt [in] Ptr to ulp context
+ *
+ * returns 0 on success or negative number on failure
+ */
+int32_t
+ulp_flow_db_session_flow_flush(struct bnxt_ulp_context *ulp_ctx);
+
+/*
+ * Check that flow id matches the function id or not
+ *
+ * ulp_ctxt [in] Ptr to ulp context
+ * flow_db [in] Ptr to flow table
+ * func_id [in] The func_id to be set, for reset pass zero.
+ *
+ * returns true on success or false on failure
+ */
+bool
+ulp_flow_db_validate_flow_func(struct bnxt_ulp_context *ulp_ctx,
+                              uint32_t flow_id,
+                              uint32_t func_id);
+
 #endif /* _ULP_FLOW_DB_H_ */
index a0aba40..94899c0 100644 (file)
@@ -461,7 +461,6 @@ ulp_mapper_result_field_process(struct bnxt_ulp_mapper_parms *parms,
        default:
                return -EINVAL;
        }
-
        return 0;
 }
 
@@ -1481,6 +1480,7 @@ ulp_mapper_flow_create(struct bnxt_ulp_context *ulp_ctx,
         */
        rc = ulp_flow_db_fid_alloc(ulp_ctx,
                                   BNXT_ULP_REGULAR_FLOW_TABLE,
+                                  cparms->func_id,
                                   &parms.fid);
        if (rc) {
                BNXT_TF_DBG(ERR, "Unable to allocate flow table entry\n");
index 24727a3..2fa6ffc 100644 (file)
@@ -46,6 +46,7 @@ struct bnxt_ulp_mapper_create_parms {
        struct ulp_rte_act_prop         *act_prop;
        uint32_t                        class_tid;
        uint32_t                        act_tid;
+       uint16_t                        func_id;
 };
 
 /*