[7/7] net/mlx5: supp modify VLAN ID on existing VLAN hdr
diff mbox series

Message ID 5cb8e07272a7a58781cdaeff7c6ae603bd87a49d.1565072905.git.motih@mellanox.com
State Superseded, archived
Delegated to: Raslan Darawsheh
Headers show
Series
  • net/mlx5: support for flow action on VLAN header
Related show

Checks

Context Check Description
ci/checkpatch success coding style OK

Commit Message

Moti Haimovsky Aug. 6, 2019, 8:24 a.m. UTC
This commit adds support for modifying the VID of the outermost VLAN
header already present in the packet.

Signed-off-by: Moti Haimovsky <motih@mellanox.com>
---
 drivers/net/mlx5/mlx5_flow.h    |  3 +-
 drivers/net/mlx5/mlx5_flow_dv.c | 90 +++++++++++++++++++++++++++++++++++------
 drivers/net/mlx5/mlx5_prm.h     |  1 +
 3 files changed, 81 insertions(+), 13 deletions(-)

Patch
diff mbox series

diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h
index 15c9c04..95abbb8 100644
--- a/drivers/net/mlx5/mlx5_flow.h
+++ b/drivers/net/mlx5/mlx5_flow.h
@@ -171,7 +171,8 @@ 
 				      MLX5_FLOW_ACTION_INC_TCP_SEQ | \
 				      MLX5_FLOW_ACTION_DEC_TCP_SEQ | \
 				      MLX5_FLOW_ACTION_INC_TCP_ACK | \
-				      MLX5_FLOW_ACTION_DEC_TCP_ACK)
+				      MLX5_FLOW_ACTION_DEC_TCP_ACK | \
+				      MLX5_FLOW_ACTION_OF_SET_VLAN_VID)
 
 #define MLX5_FLOW_VLAN_ACTIONS (MLX5_FLOW_ACTION_OF_POP_VLAN | \
 				MLX5_FLOW_ACTION_OF_PUSH_VLAN)
diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c
index c9bfad8..0250047 100644
--- a/drivers/net/mlx5/mlx5_flow_dv.c
+++ b/drivers/net/mlx5/mlx5_flow_dv.c
@@ -123,6 +123,12 @@  struct field_modify_info modify_eth[] = {
 	{0, 0, 0},
 };
 
+struct field_modify_info modify_vlan_out_first_vid[] = {
+	/* Size in bits !!! */
+	{12, 0, MLX5_MODI_OUT_FIRST_VID},
+	{0, 0, 0},
+};
+
 struct field_modify_info modify_ipv4[] = {
 	{1,  8, MLX5_MODI_OUT_IPV4_TTL},
 	{4, 12, MLX5_MODI_OUT_SIPV4},
@@ -421,6 +427,46 @@  struct field_modify_info modify_tcp[] = {
 }
 
 /**
+ * Convert modify-header set VLAN VID action to DV specification.
+ *
+ * @param[in,out] resource
+ *   Pointer to the modify-header resource.
+ * @param[in] action
+ *   Pointer to action specification.
+ * @param[out] error
+ *   Pointer to the error structure.
+ *
+ * @return
+ *   0 on success, a negative errno value otherwise and rte_errno is set.
+ */
+static int
+flow_dv_convert_action_modify_vlan_vid
+			(struct mlx5_flow_dv_modify_hdr_resource *resource,
+			 const struct rte_flow_action *action,
+			 struct rte_flow_error *error)
+{
+	const struct rte_flow_action_of_set_vlan_vid *conf =
+		(const struct rte_flow_action_of_set_vlan_vid *)(action->conf);
+	int i = resource->actions_num;
+	struct mlx5_modification_cmd *actions = &resource->actions[i];
+	struct field_modify_info *field = modify_vlan_out_first_vid;
+
+	if (i >= MLX5_MODIFY_NUM)
+		return rte_flow_error_set(error, EINVAL,
+			 RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+			 "too many items to modify");
+	actions[i].action_type = MLX5_MODIFICATION_TYPE_SET;
+	actions[i].field = field->id;
+	actions[i].length = field->size;
+	actions[i].offset = field->offset;
+	actions[i].data0 = rte_cpu_to_be_32(actions[i].data0);
+	actions[i].data1 = conf->vlan_vid;
+	actions[i].data1 = actions[i].data1 << 16;
+	resource->actions_num = ++i;
+	return 0;
+}
+
+/**
  * Convert modify-header set TP action to DV specification.
  *
  * @param[in,out] resource
@@ -1026,8 +1072,8 @@  struct field_modify_info modify_tcp[] = {
 /**
  * Validate the set VLAN VID.
  *
- * @param[in] action_flags
- *   Holds the actions detected until now.
+ * @param[in] item_flags
+ *   Holds the items detected in this rule.
  * @param[in] actions
  *   Pointer to the list of actions remaining in the flow rule.
  * @param[in] attr
@@ -1039,7 +1085,7 @@  struct field_modify_info modify_tcp[] = {
  *   0 on success, a negative errno value otherwise and rte_errno is set.
  */
 static int
-flow_dv_validate_action_set_vlan_vid(uint64_t action_flags,
+flow_dv_validate_action_set_vlan_vid(uint64_t item_flags,
 				     const struct rte_flow_action actions[],
 				     struct rte_flow_error *error)
 {
@@ -1050,17 +1096,27 @@  struct field_modify_info modify_tcp[] = {
 		return rte_flow_error_set(error, EINVAL,
 					  RTE_FLOW_ERROR_TYPE_ACTION, action,
 					  "VLAN VID value to too big");
+	/* If a push VLAN action follows then it will handle this action */
 	if (mlx5_flow_find_action(actions,
-				  RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN) == NULL)
+				  RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN))
+		return 0;
+
+	/*
+	 * Action is on an existing VLAN header:
+	 *    Need to verify this is a single modify CID action.
+	 *   Rule mast include a match on outer VLAN.
+	 */
+	if (mlx5_flow_find_action(++action,
+				  RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID))
 		return rte_flow_error_set(error, ENOTSUP,
 					  RTE_FLOW_ERROR_TYPE_ACTION, action,
-					  "set VLAN VID can only be used "
-					  "with push VLAN action");
-	if (action_flags & MLX5_FLOW_ACTION_OF_PUSH_VLAN)
-		return rte_flow_error_set(error, ENOTSUP,
+					  "Multiple VLAN VID modifications are "
+					  "not supported");
+	if (!(item_flags & MLX5_FLOW_LAYER_OUTER_VLAN))
+		return rte_flow_error_set(error, EINVAL,
 					  RTE_FLOW_ERROR_TYPE_ACTION, action,
-					  "set VLAN VID action must precede "
-					  "the push VLAN action");
+					  "match on VLAN is required in order "
+					  "to set VLAN VID");
 	return 0;
 }
 
@@ -3482,7 +3538,7 @@  struct field_modify_info modify_tcp[] = {
 			break;
 		case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID:
 			ret = flow_dv_validate_action_set_vlan_vid
-						(action_flags, actions, error);
+						(item_flags, actions, error);
 			if (ret < 0)
 				return ret;
 			/* Count VID with push_vlan command. */
@@ -5203,6 +5259,8 @@  struct field_modify_info modify_tcp[] = {
 			dev_flow->dv.actions[actions_n++] =
 					   dev_flow->dv.push_vlan_res->action;
 			action_flags |= MLX5_FLOW_ACTION_OF_PUSH_VLAN;
+			/* Push VLAN command is also handling this VLAN_VID */
+			action_flags &= ~MLX5_FLOW_ACTION_OF_SET_VLAN_VID;
 			break;
 		case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP:
 			vlan_tci =
@@ -5218,7 +5276,15 @@  struct field_modify_info modify_tcp[] = {
 			vlan.tci |=
 			    ((const struct rte_flow_action_of_set_vlan_vid *)
 						       actions->conf)->vlan_vid;
-			/* Push VLAN command will use this value */
+			if (mlx5_flow_find_action
+				(actions,
+				 RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN))
+				break;
+			/* If no VLAN push - this is a modify header action */
+			if (flow_dv_convert_action_modify_vlan_vid
+							(&res, actions, error))
+				return -rte_errno;
+			action_flags |= MLX5_FLOW_ACTION_OF_SET_VLAN_VID;
 			break;
 		case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
 		case RTE_FLOW_ACTION_TYPE_NVGRE_ENCAP:
diff --git a/drivers/net/mlx5/mlx5_prm.h b/drivers/net/mlx5/mlx5_prm.h
index d62837e..e5afc1c 100644
--- a/drivers/net/mlx5/mlx5_prm.h
+++ b/drivers/net/mlx5/mlx5_prm.h
@@ -413,6 +413,7 @@  enum mlx5_modification_field {
 	MLX5_MODI_OUT_DIPV6_31_0,
 	MLX5_MODI_OUT_SIPV4,
 	MLX5_MODI_OUT_DIPV4,
+	MLX5_MODI_OUT_FIRST_VID,
 	MLX5_MODI_IN_SMAC_47_16 = 0x31,
 	MLX5_MODI_IN_SMAC_15_0,
 	MLX5_MODI_IN_ETHERTYPE,