> -----Original Message-----
> From: Moti Haimovsky <mo...@mellanox.com>
> Sent: Monday, September 9, 2019 18:57
> To: Slava Ovsiienko <viachesl...@mellanox.com>; Raslan Darawsheh
> <rasl...@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 <mo...@mellanox.com>
Acked-by: Viacheslav Ovsiienko <viachesl...@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

Reply via email to