[v5,7/7] net/mlx5: supp modify VLAN ID on existing VLAN hdr

Message ID ea82f2122540a68cf829da38337134d1429fbedd.1567951423.git.motih@mellanox.com (mailing list archive)
State Accepted, archived
Delegated to: Raslan Darawsheh
Headers
Series net/mlx5: support for flow action on VLAN header |

Checks

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

Commit Message

Moti Haimovsky Sept. 9, 2019, 3:56 p.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>
---
 doc/guides/nics/mlx5.rst        | 20 ++++-----
 drivers/net/mlx5/mlx5_flow.h    |  3 +-
 drivers/net/mlx5/mlx5_flow_dv.c | 89 ++++++++++++++++++++++++++++++++++++-----
 drivers/net/mlx5/mlx5_prm.h     |  1 +
 4 files changed, 92 insertions(+), 21 deletions(-)
  

Comments

Slava Ovsiienko Sept. 10, 2019, 8:13 a.m. UTC | #1
> -----Original Message-----
> From: Moti Haimovsky <motih@mellanox.com>
> Sent: Monday, September 9, 2019 18:57
> To: Slava Ovsiienko <viacheslavo@mellanox.com>; Raslan Darawsheh
> <rasland@mellanox.com>
> Cc: dev@dpdk.org
> Subject: [PATCH v5 7/7] net/mlx5: supp modify VLAN ID on existing VLAN hdr
> 
> 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>
Acked-by: Viacheslav Ovsiienko <viacheslavo@mellanox.com>

> ---
>  doc/guides/nics/mlx5.rst        | 20 ++++-----
>  drivers/net/mlx5/mlx5_flow.h    |  3 +-
>  drivers/net/mlx5/mlx5_flow_dv.c | 89
> ++++++++++++++++++++++++++++++++++++-----
>  drivers/net/mlx5/mlx5_prm.h     |  1 +
>  4 files changed, 92 insertions(+), 21 deletions(-)
> 
> diff --git a/doc/guides/nics/mlx5.rst b/doc/guides/nics/mlx5.rst index
> 3a2a366..c2e9003 100644
> --- a/doc/guides/nics/mlx5.rst
> +++ b/doc/guides/nics/mlx5.rst
> @@ -134,8 +134,6 @@ Limitations
> 
>  - VLAN set PCP offload is not supported on existing headers.
> 
> -- VLAN set VID offload is not supported on existing headers.
> -
>  - A multi segment packet must have not more segments than reported by
> dev_infos_get()
>    in tx_desc_lim.nb_seg_max field. This value depends on maximal supported
> Tx descriptor
>    size and ``txq_inline_min`` settings and may be from 2 (worst case forced
> by maximal @@ -1021,13 +1019,17 @@ Supported hardware offloads
>     | | (set_ipv4_src /     | | OFED 4.6-2    | | OFED 4.6-2    |
>     | | set_ipv4_dst /      | | rdma-core 24  | | rdma-core 23  |
>     | | set_ipv6_src /      | | ConnectX-5    | | ConnectX-5    |
> -   | | set_ipv6_dst /      |                 |                 |
> -   | | set_tp_src /        |                 |                 |
> -   | | set_tp_dst /        |                 |                 |
> -   | | dec_ttl /           |                 |                 |
> -   | | set_ttl /           |                 |                 |
> -   | | set_mac_src /       |                 |                 |
> -   | | set_mac_dst)        |                 |                 |
> +   | | set_ipv6_dst /      | |               | |               |
> +   | | set_tp_src /        | |               | |               |
> +   | | set_tp_dst /        | |               | |               |
> +   | | dec_ttl /           | |               | |               |
> +   | | set_ttl /           | |               | |               |
> +   | | set_mac_src /       | |               | |               |
> +   | | set_mac_dst)        | |               | |               |
> +   | |                     | |               | |               |
> +   | | (of_set_vlan_vid)   | | DPDK 19.11    | | DPDK 19.11    |
> +   |                       | | OFED 4.6-4    | | OFED 4.6-4    |
> +   |                       | | ConnectX-5    | | ConnectX-5    |
>     +-----------------------+-----------------+-----------------+
>     | Jump                  | | DPDK 19.05    | | DPDK 19.02    |
>     |                       | | OFED 4.6-4    | | OFED 4.6-4    |
> 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 4b68aa6..330a868 100644
> --- a/drivers/net/mlx5/mlx5_flow_dv.c
> +++ b/drivers/net/mlx5/mlx5_flow_dv.c
> @@ -115,6 +115,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},
> @@ -397,6 +403,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
> @@ -1017,8 +1063,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
> @@ -1030,7 +1076,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)
>  {
> @@ -1041,17 +1087,27 @@ struct field_modify_info modify_tcp[] = {
>  		return rte_flow_error_set(error, EINVAL,
>  					  RTE_FLOW_ERROR_TYPE_ACTION,
> action,
>  					  "VLAN VID value is 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;
>  }
> 
> @@ -3487,7 +3543,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. */ @@ -
> 5214,6 +5270,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:
>  			if (!vlan_inherited) {
> @@ -5238,6 +5296,15 @@ struct field_modify_info modify_tcp[] = {
>  			    (((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,
> --
> 1.8.3.1
  

Patch

diff --git a/doc/guides/nics/mlx5.rst b/doc/guides/nics/mlx5.rst
index 3a2a366..c2e9003 100644
--- a/doc/guides/nics/mlx5.rst
+++ b/doc/guides/nics/mlx5.rst
@@ -134,8 +134,6 @@  Limitations
 
 - VLAN set PCP offload is not supported on existing headers.
 
-- VLAN set VID offload is not supported on existing headers.
-
 - A multi segment packet must have not more segments than reported by dev_infos_get()
   in tx_desc_lim.nb_seg_max field. This value depends on maximal supported Tx descriptor
   size and ``txq_inline_min`` settings and may be from 2 (worst case forced by maximal
@@ -1021,13 +1019,17 @@  Supported hardware offloads
    | | (set_ipv4_src /     | | OFED 4.6-2    | | OFED 4.6-2    |
    | | set_ipv4_dst /      | | rdma-core 24  | | rdma-core 23  |
    | | set_ipv6_src /      | | ConnectX-5    | | ConnectX-5    |
-   | | set_ipv6_dst /      |                 |                 |
-   | | set_tp_src /        |                 |                 |
-   | | set_tp_dst /        |                 |                 |
-   | | dec_ttl /           |                 |                 |
-   | | set_ttl /           |                 |                 |
-   | | set_mac_src /       |                 |                 |
-   | | set_mac_dst)        |                 |                 |
+   | | set_ipv6_dst /      | |               | |               |
+   | | set_tp_src /        | |               | |               |
+   | | set_tp_dst /        | |               | |               |
+   | | dec_ttl /           | |               | |               |
+   | | set_ttl /           | |               | |               |
+   | | set_mac_src /       | |               | |               |
+   | | set_mac_dst)        | |               | |               |
+   | |                     | |               | |               |
+   | | (of_set_vlan_vid)   | | DPDK 19.11    | | DPDK 19.11    |
+   |                       | | OFED 4.6-4    | | OFED 4.6-4    |
+   |                       | | ConnectX-5    | | ConnectX-5    |
    +-----------------------+-----------------+-----------------+
    | Jump                  | | DPDK 19.05    | | DPDK 19.02    |
    |                       | | OFED 4.6-4    | | OFED 4.6-4    |
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 4b68aa6..330a868 100644
--- a/drivers/net/mlx5/mlx5_flow_dv.c
+++ b/drivers/net/mlx5/mlx5_flow_dv.c
@@ -115,6 +115,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},
@@ -397,6 +403,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
@@ -1017,8 +1063,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
@@ -1030,7 +1076,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)
 {
@@ -1041,17 +1087,27 @@  struct field_modify_info modify_tcp[] = {
 		return rte_flow_error_set(error, EINVAL,
 					  RTE_FLOW_ERROR_TYPE_ACTION, action,
 					  "VLAN VID value is 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;
 }
 
@@ -3487,7 +3543,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. */
@@ -5214,6 +5270,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:
 			if (!vlan_inherited) {
@@ -5238,6 +5296,15 @@  struct field_modify_info modify_tcp[] = {
 			    (((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,