[dpdk-dev,RFC,v1] net/mlx4: support count flow action

Message ID 1503489899-26967-1-git-send-email-orika@mellanox.com (mailing list archive)
State Superseded, archived
Delegated to: Ferruh Yigit
Headers

Checks

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

Commit Message

Ori Kam Aug. 23, 2017, 12:04 p.m. UTC
  Support count flow action in mlx4.

This patch is draft only, do to missing features on the
verbs driver. As soon as the features will be implemented on the
verbs driver this patch will be updated and rebased on
top of the head version.

Signed-off-by: Ori Kam <orika@mellanox.com>
---
 drivers/net/mlx4/mlx4_flow.c |  101 ++++++++++++++++++++++++++++++++++++++++++
 drivers/net/mlx4/mlx4_flow.h |    7 +++
 2 files changed, 108 insertions(+), 0 deletions(-)
  

Patch

diff --git a/drivers/net/mlx4/mlx4_flow.c b/drivers/net/mlx4/mlx4_flow.c
index 925c89c..8a2bb14 100644
--- a/drivers/net/mlx4/mlx4_flow.c
+++ b/drivers/net/mlx4/mlx4_flow.c
@@ -113,6 +113,9 @@  struct rte_flow_drop {
 	RTE_FLOW_ACTION_TYPE_DROP,
 	RTE_FLOW_ACTION_TYPE_QUEUE,
 	RTE_FLOW_ACTION_TYPE_RSS,
+#ifdef 	HAVE_VERBS_IBV_EXP_FLOW_SPEC_ACTION_COUNT
+	RTE_FLOW_ACTION_TYPE_COUNT,
+#endif
 	RTE_FLOW_ACTION_TYPE_END,
 };
 
@@ -575,6 +578,7 @@  struct rte_flow_drop {
 	struct mlx4_flow_action action = {
 		.queue = 0,
 		.drop = 0,
+		.count = 0,
 	};
 
 	(void)priv;
@@ -743,6 +747,12 @@  struct rte_flow_drop {
 			action.queues_n = rss->num;
 			for (i = 0; i < rss->num; ++i)
 				action.queues[i] = rss->queue[i];
+		} else if(actions->type == RTE_FLOW_ACTION_TYPE_COUNT) {
+#ifdef HAVE_VERBS_IBV_EXP_FLOW_SPEC_ACTION_COUNT
+			action.count = 1;
+#else
+			goto exit_action_not_supported;
+#endif
 		} else {
 			goto exit_action_not_supported;
 		}
@@ -1085,6 +1095,7 @@  struct rte_flow_drop {
 	action = (struct mlx4_flow_action){
 		.queue = 0,
 		.drop = 0,
+		.count = 0,
 	};
 	for (; actions->type != RTE_FLOW_ACTION_TYPE_END; ++actions) {
 		if (actions->type == RTE_FLOW_ACTION_TYPE_VOID) {
@@ -1107,6 +1118,8 @@  struct rte_flow_drop {
 			action.queues_n = rss->num;
 			for (i = 0; i < rss->num; ++i)
 				action.queues[i] = rss->queue[i];
+		} else if (actions->type == RTE_FLOW_ACTION_TYPE_COUNT) {
+			action.count = 1;
 		} else {
 			rte_flow_error_set(error, ENOTSUP,
 					   RTE_FLOW_ERROR_TYPE_ACTION,
@@ -1318,3 +1331,91 @@  struct rte_flow *
 	}
 	return 0;
 }
+
+/**
+ * Internal function to read the counter.
+ *
+ * @param priv
+ *   Pointer to private structure.
+ * @param counter_set
+ *   Pointer to the counter_set structure.
+ * @param res
+ *   Pointer to rte_flow_query_count struct
+ *   used to return the values from the counters
+ * @param error
+ *   returns the error
+ *
+ * @return
+ *   0 on success, -1 otherwise.
+ */
+#ifdef HAVE_VERBS_IBV_EXP_FLOW_SPEC_ACTION_COUNT
+static int
+priv_flow_query_counter(struct priv *priv,
+				struct ibv_counter_set *counter_set,
+				struct rte_flow_query_count *res,
+				struct rte_flow_error *error)
+{
+	int res_value = 0;
+	uint64_t counters[2];
+	struct ibv_counter_set_description description;
+	struct ibv_query_counter_set_attr attr = { .counter_set = counter_set};
+
+	res_value = ibv_query_counter_set(attr, counters);
+	if(res_value < 0) {
+		rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+					NULL, "Error while querying counter set");
+
+	}
+	res->hits_set = 1;
+	res->hits = counters[0];
+	res->bytes_set = 1;
+	res->bytes = counters[1];
+}
+#endif
+
+/**
+ * Query an existing flow rule.
+ *
+ * @see rte_flow_query()
+ * @see rte_flow_ops
+ */
+int mlx4_flow_query(struct rte_eth_dev *dev,
+					struct rte_flow *flow,
+					enum rte_flow_action_type type,
+					void *res,
+					struct rte_flow_error *error)
+{
+	int res_value = 0;
+
+	switch (type) {
+		case RTE_FLOW_ACTION_TYPE_COUNT:
+#ifdef HAVE_VERBS_IBV_EXP_FLOW_SPEC_ACTION_COUNT
+			if(!flow->counter) {
+				rte_flow_error_set(error, EINVAL,
+						RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+						NULL,
+						"No counter is set for this flow");
+			}
+
+			res_value = priv_flow_query_counter(mlx4_get_priv(dev),
+							(struct rte_flow_query_count*)res,
+							error);
+#else
+			rte_flow_error_set(error, ENOTSUP,
+						RTE_FLOW_ERROR_TYPE_ACTION,
+						NULL, "Flow count unsupported");
+			(void)dev;
+			(void)flow;
+			(void)type;
+			(void)res;
+			(void)error;
+			return -1;
+#endif
+			break;
+		default:
+			rte_flow_error_set(error, ENOTSUP,
+						RTE_FLOW_ERROR_TYPE_ACTION,
+						NULL, "Type not supported");
+	}
+	return res_value;
+}
diff --git a/drivers/net/mlx4/mlx4_flow.h b/drivers/net/mlx4/mlx4_flow.h
index beabcf2..9c536b9 100644
--- a/drivers/net/mlx4/mlx4_flow.h
+++ b/drivers/net/mlx4/mlx4_flow.h
@@ -80,6 +80,12 @@  struct rte_flow *
 		  struct rte_flow *flow,
 		  struct rte_flow_error *error);
 
+int mlx4_flow_query(struct rte_eth_dev *dev,
+					struct rte_flow *flow,
+					enum rte_flow_action_type type,
+					void *res,
+					struct rte_flow_error *error);
+
 int
 mlx4_flow_flush(struct rte_eth_dev *dev,
 		struct rte_flow_error *error);
@@ -98,6 +104,7 @@  struct mlx4_flow {
 struct mlx4_flow_action {
 	uint32_t drop:1; /**< Target is a drop queue. */
 	uint32_t queue:1; /**< Target is a receive queue. */
+	uint32_t count:1; /**< Count action is present in the flow. */
 	uint16_t queues[RTE_MAX_QUEUES_PER_PORT]; /**< Queue indices to use. */
 	uint16_t queues_n; /**< Number of entries in queue[] */
 };