[dpdk-stable] [PATCH 19.11 10/11] net/mlx5: fix VLAN actions in meter

Suanming Mou suanmingm at mellanox.com
Fri Feb 28 04:33:54 CET 2020


[ upstream commit 50f576d657d78e87a3eac597353d236969969c17 ]

Meter suffix subflow only has the port id and tag match item, if VLAN
push and set VLAN id actions exist in the suffix subflow, the user
defined VLAN items is required for the actions to set a correct VLAN
id.

Currently, the VLAN item stays in the meter prefix subflow. Without
the VLAN item, VLAN id or pcp will not be inherited.

Actions require the VLAN item as below:
RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN
RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID

Add a private VLAN item to copy the user defined VLAN item to the meter
suffix subflow, so the suffix subflow will have the chance to get the
correct original VLAN id and pcp value from the VLAN item.

Fixes: 9ea9b049a960 ("net/mlx5: split meter flow")

Signed-off-by: Suanming Mou <suanmingm at mellanox.com>
Acked-by: Matan Azrad <matan at mellanox.com>
---
 drivers/net/mlx5/mlx5_flow.c    | 153 ++++++++++++++++++----------------------
 drivers/net/mlx5/mlx5_flow.h    |   4 ++
 drivers/net/mlx5/mlx5_flow_dv.c |  14 ++--
 3 files changed, 82 insertions(+), 89 deletions(-)

diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c
index 365b832..17ce2e3 100644
--- a/drivers/net/mlx5/mlx5_flow.c
+++ b/drivers/net/mlx5/mlx5_flow.c
@@ -2645,26 +2645,6 @@ uint32_t mlx5_flow_adjust_priority(struct rte_eth_dev *dev, int32_t priority,
 }
 
 /**
- * Get port id item from the item list.
- *
- * @param[in] item
- *   Pointer to the list of items.
- *
- * @return
- *   Pointer to the port id item if exist, else return NULL.
- */
-static const struct rte_flow_item *
-find_port_id_item(const struct rte_flow_item *item)
-{
-	assert(item);
-	for (; item->type != RTE_FLOW_ITEM_TYPE_END; item++) {
-		if (item->type == RTE_FLOW_ITEM_TYPE_PORT_ID)
-			return item;
-	}
-	return NULL;
-}
-
-/**
  * Get RSS action from the action list.
  *
  * @param[in] actions
@@ -3482,6 +3462,10 @@ uint32_t mlx5_flow_adjust_priority(struct rte_eth_dev *dev, int32_t priority,
  *
  * @param dev
  *   Pointer to Ethernet device.
+ * @param[in] items
+ *   Pattern specification (list terminated by the END pattern item).
+ * @param[out] sfx_items
+ *   Suffix flow match items (list terminated by the END pattern item).
  * @param[in] actions
  *   Associated actions (list terminated by the END action).
  * @param[out] actions_sfx
@@ -3498,70 +3482,60 @@ uint32_t mlx5_flow_adjust_priority(struct rte_eth_dev *dev, int32_t priority,
  */
 static int
 flow_meter_split_prep(struct rte_eth_dev *dev,
+		 const struct rte_flow_item items[],
+		 struct rte_flow_item sfx_items[],
 		 const struct rte_flow_action actions[],
 		 struct rte_flow_action actions_sfx[],
 		 struct rte_flow_action actions_pre[])
 {
 	struct rte_flow_action *tag_action = NULL;
+	struct rte_flow_item *tag_item;
 	struct mlx5_rte_flow_action_set_tag *set_tag;
 	struct rte_flow_error error;
 	const struct rte_flow_action_raw_encap *raw_encap;
 	const struct rte_flow_action_raw_decap *raw_decap;
+	struct mlx5_rte_flow_item_tag *tag_spec;
+	struct mlx5_rte_flow_item_tag *tag_mask;
 	uint32_t tag_id;
+	bool copy_vlan = false;
 
 	/* Prepare the actions for prefix and suffix flow. */
 	for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) {
+		struct rte_flow_action **action_cur = NULL;
+
 		switch (actions->type) {
 		case RTE_FLOW_ACTION_TYPE_METER:
 			/* Add the extra tag action first. */
 			tag_action = actions_pre;
 			tag_action->type = MLX5_RTE_FLOW_ACTION_TYPE_TAG;
 			actions_pre++;
-			memcpy(actions_pre, actions,
-			       sizeof(struct rte_flow_action));
-			actions_pre++;
+			action_cur = &actions_pre;
 			break;
 		case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:
 		case RTE_FLOW_ACTION_TYPE_NVGRE_DECAP:
-			memcpy(actions_pre, actions,
-			       sizeof(struct rte_flow_action));
-			actions_pre++;
+			action_cur = &actions_pre;
 			break;
 		case RTE_FLOW_ACTION_TYPE_RAW_ENCAP:
 			raw_encap = actions->conf;
-			if (raw_encap->size >
-			    (sizeof(struct rte_flow_item_eth) +
-			     sizeof(struct rte_flow_item_ipv4))) {
-				memcpy(actions_sfx, actions,
-				       sizeof(struct rte_flow_action));
-				actions_sfx++;
-			} else {
-				rte_memcpy(actions_pre, actions,
-					   sizeof(struct rte_flow_action));
-				actions_pre++;
-			}
+			if (raw_encap->size < MLX5_ENCAPSULATION_DECISION_SIZE)
+				action_cur = &actions_pre;
 			break;
 		case RTE_FLOW_ACTION_TYPE_RAW_DECAP:
 			raw_decap = actions->conf;
-			/* Size 0 decap means 50 bytes as vxlan decap. */
-			if (raw_decap->size && (raw_decap->size <
-			    (sizeof(struct rte_flow_item_eth) +
-			     sizeof(struct rte_flow_item_ipv4)))) {
-				memcpy(actions_sfx, actions,
-				       sizeof(struct rte_flow_action));
-				actions_sfx++;
-			} else {
-				rte_memcpy(actions_pre, actions,
-					   sizeof(struct rte_flow_action));
-				actions_pre++;
-			}
+			if (raw_decap->size > MLX5_ENCAPSULATION_DECISION_SIZE)
+				action_cur = &actions_pre;
+			break;
+		case RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN:
+		case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID:
+			copy_vlan = true;
 			break;
 		default:
-			memcpy(actions_sfx, actions,
-				sizeof(struct rte_flow_action));
-			actions_sfx++;
 			break;
 		}
+		if (!action_cur)
+			action_cur = &actions_sfx;
+		memcpy(*action_cur, actions, sizeof(struct rte_flow_action));
+		(*action_cur)++;
 	}
 	/* Add end action to the actions. */
 	actions_sfx->type = RTE_FLOW_ACTION_TYPE_END;
@@ -3577,6 +3551,42 @@ uint32_t mlx5_flow_adjust_priority(struct rte_eth_dev *dev, int32_t priority,
 	set_tag->data = tag_id << MLX5_MTR_COLOR_BITS;
 	assert(tag_action);
 	tag_action->conf = set_tag;
+	/* Prepare the suffix subflow items. */
+	tag_item = sfx_items++;
+	for (; items->type != RTE_FLOW_ITEM_TYPE_END; items++) {
+		int item_type = items->type;
+
+		switch (item_type) {
+		case RTE_FLOW_ITEM_TYPE_PORT_ID:
+			memcpy(sfx_items, items, sizeof(*sfx_items));
+			sfx_items++;
+			break;
+		case RTE_FLOW_ITEM_TYPE_VLAN:
+			if (copy_vlan) {
+				memcpy(sfx_items, items, sizeof(*sfx_items));
+				/*
+				 * Convert to internal match item, it is used
+				 * for vlan push and set vid.
+				 */
+				sfx_items->type = MLX5_RTE_FLOW_ITEM_TYPE_VLAN;
+				sfx_items++;
+			}
+			break;
+		default:
+			break;
+		}
+	}
+	sfx_items->type = RTE_FLOW_ITEM_TYPE_END;
+	sfx_items++;
+	tag_spec = (struct mlx5_rte_flow_item_tag *)sfx_items;
+	tag_spec->data = tag_id << MLX5_MTR_COLOR_BITS;
+	tag_spec->id = mlx5_flow_get_reg_id(dev, MLX5_MTR_SFX, 0, &error);
+	tag_mask = tag_spec + 1;
+	tag_mask->data = 0xffffff00;
+	tag_item->type = MLX5_RTE_FLOW_ITEM_TYPE_TAG;
+	tag_item->spec = tag_spec;
+	tag_item->last = NULL;
+	tag_item->mask = tag_mask;
 	return tag_id;
 }
 
@@ -4002,7 +4012,6 @@ uint32_t mlx5_flow_adjust_priority(struct rte_eth_dev *dev, int32_t priority,
 	struct rte_flow_action *sfx_actions = NULL;
 	struct rte_flow_action *pre_actions = NULL;
 	struct rte_flow_item *sfx_items = NULL;
-	const  struct rte_flow_item *sfx_port_id_item;
 	struct mlx5_flow *dev_flow = NULL;
 	struct rte_flow_attr sfx_attr = *attr;
 	uint32_t mtr = 0;
@@ -4015,13 +4024,11 @@ uint32_t mlx5_flow_adjust_priority(struct rte_eth_dev *dev, int32_t priority,
 	if (priv->mtr_en)
 		actions_n = flow_check_meter_action(actions, &mtr);
 	if (mtr) {
-		struct mlx5_rte_flow_item_tag *tag_spec;
-		struct mlx5_rte_flow_item_tag *tag_mask;
 		/* The five prefix actions: meter, decap, encap, tag, end. */
 		act_size = sizeof(struct rte_flow_action) * (actions_n + 5) +
-			   sizeof(struct rte_flow_action_set_tag);
-		/* tag, end. */
-#define METER_SUFFIX_ITEM 3
+			   sizeof(struct mlx5_rte_flow_action_set_tag);
+		/* tag, vlan, port id, end. */
+#define METER_SUFFIX_ITEM 4
 		item_size = sizeof(struct rte_flow_item) * METER_SUFFIX_ITEM +
 			    sizeof(struct mlx5_rte_flow_item_tag) * 2;
 		sfx_actions = rte_zmalloc(__func__, (act_size + item_size), 0);
@@ -4030,9 +4037,12 @@ uint32_t mlx5_flow_adjust_priority(struct rte_eth_dev *dev, int32_t priority,
 						  RTE_FLOW_ERROR_TYPE_ACTION,
 						  NULL, "no memory to split "
 						  "meter flow");
+		sfx_items = (struct rte_flow_item *)((char *)sfx_actions +
+			     act_size);
 		pre_actions = sfx_actions + actions_n;
-		mtr_tag_id = flow_meter_split_prep(dev, actions, sfx_actions,
-						     pre_actions);
+		mtr_tag_id = flow_meter_split_prep(dev, items, sfx_items,
+						   actions, sfx_actions,
+						   pre_actions);
 		if (!mtr_tag_id) {
 			ret = -rte_errno;
 			goto exit;
@@ -4046,29 +4056,6 @@ uint32_t mlx5_flow_adjust_priority(struct rte_eth_dev *dev, int32_t priority,
 			goto exit;
 		}
 		dev_flow->mtr_flow_id = mtr_tag_id;
-		/* Prepare the suffix flow match pattern. */
-		sfx_items = (struct rte_flow_item *)((char *)sfx_actions +
-			     act_size);
-		tag_spec = (struct mlx5_rte_flow_item_tag *)(sfx_items +
-			    METER_SUFFIX_ITEM);
-		tag_spec->data = dev_flow->mtr_flow_id << MLX5_MTR_COLOR_BITS;
-		tag_spec->id = mlx5_flow_get_reg_id(dev, MLX5_MTR_SFX, 0,
-						    error);
-		tag_mask = tag_spec + 1;
-		tag_mask->data = 0xffffff00;
-		sfx_items->type = MLX5_RTE_FLOW_ITEM_TYPE_TAG;
-		sfx_items->spec = tag_spec;
-		sfx_items->last = NULL;
-		sfx_items->mask = tag_mask;
-		sfx_items++;
-		sfx_port_id_item = find_port_id_item(items);
-		if (sfx_port_id_item) {
-			memcpy(sfx_items, sfx_port_id_item,
-			       sizeof(*sfx_items));
-			sfx_items++;
-		}
-		sfx_items->type = RTE_FLOW_ITEM_TYPE_END;
-		sfx_items -= sfx_port_id_item ? 2 : 1;
 		/* Setting the sfx group atrr. */
 		sfx_attr.group = sfx_attr.transfer ?
 				(MLX5_FLOW_TABLE_LEVEL_SUFFIX - 1) :
diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h
index a15ee2c..2353e18 100644
--- a/drivers/net/mlx5/mlx5_flow.h
+++ b/drivers/net/mlx5/mlx5_flow.h
@@ -33,6 +33,7 @@ enum mlx5_rte_flow_item_type {
 	MLX5_RTE_FLOW_ITEM_TYPE_END = INT_MIN,
 	MLX5_RTE_FLOW_ITEM_TYPE_TAG,
 	MLX5_RTE_FLOW_ITEM_TYPE_TX_QUEUE,
+	MLX5_RTE_FLOW_ITEM_TYPE_VLAN,
 };
 
 /* Private (internal) rte flow actions. */
@@ -326,6 +327,9 @@ enum mlx5_feature_name {
 #define MLX5_GENEVE_OPT_LEN_0 14
 #define MLX5_GENEVE_OPT_LEN_1 63
 
+#define MLX5_ENCAPSULATION_DECISION_SIZE (sizeof(struct rte_flow_item_eth) + \
+					  sizeof(struct rte_flow_item_ipv4))
+
 enum mlx5_flow_drv_type {
 	MLX5_FLOW_TYPE_MIN,
 	MLX5_FLOW_TYPE_DV,
diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c
index a5824dc..3694d6d 100644
--- a/drivers/net/mlx5/mlx5_flow_dv.c
+++ b/drivers/net/mlx5/mlx5_flow_dv.c
@@ -51,8 +51,6 @@
 #define MLX5DV_DR_ACTION_FLAGS_ROOT_LEVEL 1
 #endif
 
-#define MLX5_ENCAPSULATION_DECISION_SIZE (sizeof(struct rte_flow_item_eth) + \
-					  sizeof(struct rte_flow_item_ipv4))
 /* VLAN header definitions */
 #define MLX5DV_FLOW_VLAN_PCP_SHIFT 13
 #define MLX5DV_FLOW_VLAN_PCP_MASK (0x7 << MLX5DV_FLOW_VLAN_PCP_SHIFT)
@@ -1626,10 +1624,14 @@ struct field_modify_info modify_tcp[] = {
 
 	if (items == NULL)
 		return;
-	for (; items->type != RTE_FLOW_ITEM_TYPE_END &&
-	       items->type != RTE_FLOW_ITEM_TYPE_VLAN; items++)
-		;
-	if (items->type == RTE_FLOW_ITEM_TYPE_VLAN) {
+	for (; items->type != RTE_FLOW_ITEM_TYPE_END; items++) {
+		int type = items->type;
+
+		if (type == RTE_FLOW_ITEM_TYPE_VLAN ||
+		    type == MLX5_RTE_FLOW_ITEM_TYPE_VLAN)
+			break;
+	}
+	if (items->type != RTE_FLOW_ITEM_TYPE_END) {
 		const struct rte_flow_item_vlan *vlan_m = items->mask;
 		const struct rte_flow_item_vlan *vlan_v = items->spec;
 
-- 
1.8.3.1



More information about the stable mailing list