[v3,50/51] net/bnxt: add support for count action in flow query
diff mbox series

Message ID 20200702041134.43198-51-ajit.khaparde@broadcom.com
State Superseded
Delegated to: Ajit Khaparde
Headers show
Series
  • add features for host-based flow management
Related show

Checks

Context Check Description
ci/Intel-compilation success Compilation OK
ci/checkpatch success coding style OK

Commit Message

Ajit Khaparde July 2, 2020, 4:11 a.m. UTC
From: Somnath Kotur <somnath.kotur@broadcom.com>

Use the flow counter manager to fetch the accumulated stats for
a flow.

Signed-off-by: Somnath Kotur <somnath.kotur@broadcom.com>
Signed-off-by: Venkat Duvvuru <venkatkumar.duvvuru@broadcom.com>
Reviewed-by: Ajit Khaparde <ajit.khaparde@broadcom.com>
---
 drivers/net/bnxt/tf_ulp/bnxt_ulp_flow.c |  45 +++++++-
 drivers/net/bnxt/tf_ulp/ulp_fc_mgr.c    | 141 +++++++++++++++++++++++-
 drivers/net/bnxt/tf_ulp/ulp_fc_mgr.h    |  17 ++-
 3 files changed, 196 insertions(+), 7 deletions(-)

Patch
diff mbox series

diff --git a/drivers/net/bnxt/tf_ulp/bnxt_ulp_flow.c b/drivers/net/bnxt/tf_ulp/bnxt_ulp_flow.c
index 7ef306e58..36a014184 100644
--- a/drivers/net/bnxt/tf_ulp/bnxt_ulp_flow.c
+++ b/drivers/net/bnxt/tf_ulp/bnxt_ulp_flow.c
@@ -9,6 +9,7 @@ 
 #include "ulp_matcher.h"
 #include "ulp_flow_db.h"
 #include "ulp_mapper.h"
+#include "ulp_fc_mgr.h"
 #include <rte_malloc.h>
 
 static int32_t
@@ -289,11 +290,53 @@  bnxt_ulp_flow_flush(struct rte_eth_dev *eth_dev,
 	return ret;
 }
 
+/* Function to query the rte flows. */
+static int32_t
+bnxt_ulp_flow_query(struct rte_eth_dev *eth_dev,
+		    struct rte_flow *flow,
+		    const struct rte_flow_action *action,
+		    void *data,
+		    struct rte_flow_error *error)
+{
+	int rc = 0;
+	struct bnxt_ulp_context *ulp_ctx;
+	struct rte_flow_query_count *count;
+	uint32_t flow_id;
+
+	ulp_ctx = bnxt_ulp_eth_dev_ptr2_cntxt_get(eth_dev);
+	if (!ulp_ctx) {
+		BNXT_TF_DBG(ERR, "ULP context is not initialized\n");
+		rte_flow_error_set(error, EINVAL,
+				   RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
+				   "Failed to query flow.");
+		return -EINVAL;
+	}
+
+	flow_id = (uint32_t)(uintptr_t)flow;
+
+	switch (action->type) {
+	case RTE_FLOW_ACTION_TYPE_COUNT:
+		count = data;
+		rc = ulp_fc_mgr_query_count_get(ulp_ctx, flow_id, count);
+		if (rc) {
+			rte_flow_error_set(error, EINVAL,
+					   RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
+					   "Failed to query flow.");
+		}
+		break;
+	default:
+		rte_flow_error_set(error, -rc, RTE_FLOW_ERROR_TYPE_ACTION_NUM,
+				   NULL, "Unsupported action item");
+	}
+
+	return rc;
+}
+
 const struct rte_flow_ops bnxt_ulp_rte_flow_ops = {
 	.validate = bnxt_ulp_flow_validate,
 	.create = bnxt_ulp_flow_create,
 	.destroy = bnxt_ulp_flow_destroy,
 	.flush = bnxt_ulp_flow_flush,
-	.query = NULL,
+	.query = bnxt_ulp_flow_query,
 	.isolate = NULL
 };
diff --git a/drivers/net/bnxt/tf_ulp/ulp_fc_mgr.c b/drivers/net/bnxt/tf_ulp/ulp_fc_mgr.c
index f70d4a295..9944e9e5c 100644
--- a/drivers/net/bnxt/tf_ulp/ulp_fc_mgr.c
+++ b/drivers/net/bnxt/tf_ulp/ulp_fc_mgr.c
@@ -11,6 +11,7 @@ 
 #include "bnxt_ulp.h"
 #include "bnxt_tf_common.h"
 #include "ulp_fc_mgr.h"
+#include "ulp_flow_db.h"
 #include "ulp_template_db_enum.h"
 #include "ulp_template_struct.h"
 #include "tf_tbl.h"
@@ -226,9 +227,10 @@  void ulp_fc_mgr_thread_cancel(struct bnxt_ulp_context *ctxt)
  * num_counters [in] The number of counters
  *
  */
-static int32_t ulp_bulk_get_flow_stats(struct tf *tfp,
+__rte_unused static int32_t ulp_bulk_get_flow_stats(struct tf *tfp,
 				       struct bnxt_ulp_fc_info *fc_info,
 				       enum tf_dir dir, uint32_t num_counters)
+/* MARK AS UNUSED FOR NOW TO AVOID COMPILATION ERRORS TILL API is RESOLVED */
 {
 	int rc = 0;
 	struct tf_tbl_get_bulk_parms parms = { 0 };
@@ -275,6 +277,45 @@  static int32_t ulp_bulk_get_flow_stats(struct tf *tfp,
 
 	return rc;
 }
+
+static int ulp_get_single_flow_stat(struct tf *tfp,
+				    struct bnxt_ulp_fc_info *fc_info,
+				    enum tf_dir dir,
+				    uint32_t hw_cntr_id)
+{
+	int rc = 0;
+	struct tf_get_tbl_entry_parms parms = { 0 };
+	enum tf_tbl_type stype = TF_TBL_TYPE_ACT_STATS_64;  /* TBD:Template? */
+	struct sw_acc_counter *sw_acc_tbl_entry = NULL;
+	uint64_t stats = 0;
+	uint32_t sw_cntr_indx = 0;
+
+	parms.dir = dir;
+	parms.type = stype;
+	parms.idx = hw_cntr_id;
+	/*
+	 * TODO:
+	 * Size of an entry needs to obtained from template
+	 */
+	parms.data_sz_in_bytes = sizeof(uint64_t);
+	parms.data = (uint8_t *)&stats;
+	rc = tf_get_tbl_entry(tfp, &parms);
+	if (rc) {
+		PMD_DRV_LOG(ERR,
+			    "Get failed for id:0x%x rc:%d\n",
+			    parms.idx, rc);
+		return rc;
+	}
+
+	/* TBD - Get PKT/BYTE COUNT SHIFT/MASK from Template */
+	sw_cntr_indx = hw_cntr_id - fc_info->shadow_hw_tbl[dir].start_idx;
+	sw_acc_tbl_entry = &fc_info->sw_acc_tbl[dir][sw_cntr_indx];
+	sw_acc_tbl_entry->pkt_count += FLOW_CNTR_PKTS(stats);
+	sw_acc_tbl_entry->byte_count += FLOW_CNTR_BYTES(stats);
+
+	return rc;
+}
+
 /*
  * Alarm handler that will issue the TF-Core API to fetch
  * data from the chip's internal flow counters
@@ -282,15 +323,18 @@  static int32_t ulp_bulk_get_flow_stats(struct tf *tfp,
  * ctxt [in] The ulp context for the flow counter manager
  *
  */
+
 void
 ulp_fc_mgr_alarm_cb(void *arg)
 {
-	int rc = 0, i;
+	int rc = 0;
+	unsigned int j;
+	enum tf_dir i;
 	struct bnxt_ulp_context *ctxt = arg;
 	struct bnxt_ulp_fc_info *ulp_fc_info;
 	struct bnxt_ulp_device_params *dparms;
 	struct tf *tfp;
-	uint32_t dev_id;
+	uint32_t dev_id, hw_cntr_id = 0;
 
 	ulp_fc_info = bnxt_ulp_cntxt_ptr2_fc_info_get(ctxt);
 	if (!ulp_fc_info)
@@ -325,13 +369,27 @@  ulp_fc_mgr_alarm_cb(void *arg)
 		ulp_fc_mgr_thread_cancel(ctxt);
 		return;
 	}
-
-	for (i = 0; i < TF_DIR_MAX; i++) {
+	/*
+	 * Commented for now till GET_BULK is resolved, just get the first flow
+	 * stat for now
+	 for (i = 0; i < TF_DIR_MAX; i++) {
 		rc = ulp_bulk_get_flow_stats(tfp, ulp_fc_info, i,
 					     dparms->flow_count_db_entries);
 		if (rc)
 			break;
 	}
+	*/
+	for (i = 0; i < TF_DIR_MAX; i++) {
+		for (j = 0; j < ulp_fc_info->num_entries; j++) {
+			if (!ulp_fc_info->sw_acc_tbl[i][j].valid)
+				continue;
+			hw_cntr_id = ulp_fc_info->sw_acc_tbl[i][j].hw_cntr_id;
+			rc = ulp_get_single_flow_stat(tfp, ulp_fc_info, i,
+						      hw_cntr_id);
+			if (rc)
+				break;
+		}
+	}
 
 	pthread_mutex_unlock(&ulp_fc_info->fc_lock);
 
@@ -425,6 +483,7 @@  int32_t ulp_fc_mgr_cntr_set(struct bnxt_ulp_context *ctxt, enum tf_dir dir,
 	pthread_mutex_lock(&ulp_fc_info->fc_lock);
 	sw_cntr_idx = hw_cntr_id - ulp_fc_info->shadow_hw_tbl[dir].start_idx;
 	ulp_fc_info->sw_acc_tbl[dir][sw_cntr_idx].valid = true;
+	ulp_fc_info->sw_acc_tbl[dir][sw_cntr_idx].hw_cntr_id = hw_cntr_id;
 	ulp_fc_info->num_entries++;
 	pthread_mutex_unlock(&ulp_fc_info->fc_lock);
 
@@ -456,6 +515,7 @@  int32_t ulp_fc_mgr_cntr_reset(struct bnxt_ulp_context *ctxt, enum tf_dir dir,
 	pthread_mutex_lock(&ulp_fc_info->fc_lock);
 	sw_cntr_idx = hw_cntr_id - ulp_fc_info->shadow_hw_tbl[dir].start_idx;
 	ulp_fc_info->sw_acc_tbl[dir][sw_cntr_idx].valid = false;
+	ulp_fc_info->sw_acc_tbl[dir][sw_cntr_idx].hw_cntr_id = 0;
 	ulp_fc_info->sw_acc_tbl[dir][sw_cntr_idx].pkt_count = 0;
 	ulp_fc_info->sw_acc_tbl[dir][sw_cntr_idx].byte_count = 0;
 	ulp_fc_info->num_entries--;
@@ -463,3 +523,74 @@  int32_t ulp_fc_mgr_cntr_reset(struct bnxt_ulp_context *ctxt, enum tf_dir dir,
 
 	return 0;
 }
+
+/*
+ * Fill the rte_flow_query_count 'data' argument passed
+ * in the rte_flow_query() with the values obtained and
+ * accumulated locally.
+ *
+ * ctxt [in] The ulp context for the flow counter manager
+ *
+ * flow_id [in] The HW flow ID
+ *
+ * count [out] The rte_flow_query_count 'data' that is set
+ *
+ */
+int ulp_fc_mgr_query_count_get(struct bnxt_ulp_context *ctxt,
+			       uint32_t flow_id,
+			       struct rte_flow_query_count *count)
+{
+	int rc = 0;
+	uint32_t nxt_resource_index = 0;
+	struct bnxt_ulp_fc_info *ulp_fc_info;
+	struct ulp_flow_db_res_params params;
+	enum tf_dir dir;
+	uint32_t hw_cntr_id = 0, sw_cntr_idx = 0;
+	struct sw_acc_counter sw_acc_tbl_entry;
+	bool found_cntr_resource = false;
+
+	ulp_fc_info = bnxt_ulp_cntxt_ptr2_fc_info_get(ctxt);
+	if (!ulp_fc_info)
+		return -ENODEV;
+
+	do {
+		rc = ulp_flow_db_resource_get(ctxt,
+					      BNXT_ULP_REGULAR_FLOW_TABLE,
+					      flow_id,
+					      &nxt_resource_index,
+					      &params);
+		if (params.resource_func ==
+		     BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE &&
+		     (params.resource_sub_type ==
+		      BNXT_ULP_RESOURCE_SUB_TYPE_INDEX_TYPE_INT_COUNT ||
+		      params.resource_sub_type ==
+		      BNXT_ULP_RESOURCE_SUB_TYPE_INDEX_TYPE_EXT_COUNT)) {
+			found_cntr_resource = true;
+			break;
+		}
+
+	} while (!rc);
+
+	if (rc)
+		return rc;
+
+	if (found_cntr_resource) {
+		dir = params.direction;
+		hw_cntr_id = params.resource_hndl;
+		sw_cntr_idx = hw_cntr_id -
+				ulp_fc_info->shadow_hw_tbl[dir].start_idx;
+		sw_acc_tbl_entry = ulp_fc_info->sw_acc_tbl[dir][sw_cntr_idx];
+		if (params.resource_sub_type ==
+			BNXT_ULP_RESOURCE_SUB_TYPE_INDEX_TYPE_INT_COUNT) {
+			count->hits_set = 1;
+			count->bytes_set = 1;
+			count->hits = sw_acc_tbl_entry.pkt_count;
+			count->bytes = sw_acc_tbl_entry.byte_count;
+		} else {
+			/* TBD: Handle External counters */
+			rc = -EINVAL;
+		}
+	}
+
+	return rc;
+}
diff --git a/drivers/net/bnxt/tf_ulp/ulp_fc_mgr.h b/drivers/net/bnxt/tf_ulp/ulp_fc_mgr.h
index faa77dd75..207267049 100644
--- a/drivers/net/bnxt/tf_ulp/ulp_fc_mgr.h
+++ b/drivers/net/bnxt/tf_ulp/ulp_fc_mgr.h
@@ -23,6 +23,7 @@  struct sw_acc_counter {
 	uint64_t pkt_count;
 	uint64_t byte_count;
 	bool	valid;
+	uint32_t hw_cntr_id;
 };
 
 struct hw_fc_mem_info {
@@ -142,7 +143,21 @@  bool ulp_fc_mgr_start_idx_isset(struct bnxt_ulp_context *ctxt, enum tf_dir dir);
  * ctxt [in] The ulp context for the flow counter manager
  *
  */
-
 bool ulp_fc_mgr_thread_isstarted(struct bnxt_ulp_context *ctxt);
 
+/*
+ * Fill the rte_flow_query_count 'data' argument passed
+ * in the rte_flow_query() with the values obtained and
+ * accumulated locally.
+ *
+ * ctxt [in] The ulp context for the flow counter manager
+ *
+ * flow_id [in] The HW flow ID
+ *
+ * count [out] The rte_flow_query_count 'data' that is set
+ *
+ */
+int ulp_fc_mgr_query_count_get(struct bnxt_ulp_context *ulp_ctx,
+			       uint32_t flow_id,
+			       struct rte_flow_query_count *count);
 #endif /* _ULP_FC_MGR_H_ */