Add support for modify field in tunnel MPLS header. For now it is supported only to copy from.
Signed-off-by: Michael Baum <michae...@nvidia.com> Acked-by: Matan Azrad <ma...@nvidia.com> --- doc/guides/nics/mlx5.rst | 2 ++ drivers/common/mlx5/mlx5_prm.h | 5 +++++ drivers/net/mlx5/mlx5_flow.h | 1 + drivers/net/mlx5/mlx5_flow_dv.c | 23 +++++++++++++++++++++++ drivers/net/mlx5/mlx5_flow_hw.c | 10 +++++++--- 5 files changed, 38 insertions(+), 3 deletions(-) diff --git a/doc/guides/nics/mlx5.rst b/doc/guides/nics/mlx5.rst index 85db539f19..67f7c407fc 100644 --- a/doc/guides/nics/mlx5.rst +++ b/doc/guides/nics/mlx5.rst @@ -538,6 +538,8 @@ Limitations - Supports the 'set' and 'add' operations for ``RTE_FLOW_ACTION_TYPE_MODIFY_FIELD`` action. - Modification of an arbitrary place in a packet via the special ``RTE_FLOW_FIELD_START`` Field ID is not supported. + - Modification of the MPLS header is supported only in HWS and only to copy + from, the encapsulation level is always 0. - Modification of the 802.1Q Tag, VXLAN Network or GENEVE Network ID's is not supported. - Encapsulation levels are not supported, can modify outermost header fields only. - Offsets cannot skip past the boundary of a field. diff --git a/drivers/common/mlx5/mlx5_prm.h b/drivers/common/mlx5/mlx5_prm.h index d67c4336e6..4a8e1a10e5 100644 --- a/drivers/common/mlx5/mlx5_prm.h +++ b/drivers/common/mlx5/mlx5_prm.h @@ -787,6 +787,11 @@ enum mlx5_modification_field { MLX5_MODI_TUNNEL_HDR_DW_1 = 0x75, MLX5_MODI_GTPU_FIRST_EXT_DW_0 = 0x76, MLX5_MODI_HASH_RESULT = 0x81, + MLX5_MODI_IN_MPLS_LABEL_0 = 0x8a, + MLX5_MODI_IN_MPLS_LABEL_1, + MLX5_MODI_IN_MPLS_LABEL_2, + MLX5_MODI_IN_MPLS_LABEL_3, + MLX5_MODI_IN_MPLS_LABEL_4, MLX5_MODI_OUT_IPV6_NEXT_HDR = 0x4A, MLX5_MODI_INVALID = INT_MAX, }; diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h index 568dae751e..ca9d7ac40c 100644 --- a/drivers/net/mlx5/mlx5_flow.h +++ b/drivers/net/mlx5/mlx5_flow.h @@ -1113,6 +1113,7 @@ flow_modify_field_support_tag_array(enum rte_flow_field_id field) { switch (field) { case RTE_FLOW_FIELD_TAG: + case RTE_FLOW_FIELD_MPLS: return true; default: break; diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c index f6278935c1..8e89b41c2d 100644 --- a/drivers/net/mlx5/mlx5_flow_dv.c +++ b/drivers/net/mlx5/mlx5_flow_dv.c @@ -1388,6 +1388,7 @@ mlx5_flow_item_field_width(struct rte_eth_dev *dev, case RTE_FLOW_FIELD_GENEVE_VNI: return 24; case RTE_FLOW_FIELD_GTP_TEID: + case RTE_FLOW_FIELD_MPLS: case RTE_FLOW_FIELD_TAG: return 32; case RTE_FLOW_FIELD_MARK: @@ -1435,6 +1436,12 @@ flow_modify_info_mask_32_masked(uint32_t length, uint32_t off, uint32_t post_mas return rte_cpu_to_be_32(mask & post_mask); } +static __rte_always_inline enum mlx5_modification_field +mlx5_mpls_modi_field_get(const struct rte_flow_action_modify_data *data) +{ + return MLX5_MODI_IN_MPLS_LABEL_0 + data->tag_index; +} + static void mlx5_modify_flex_item(const struct rte_eth_dev *dev, const struct mlx5_flex_item *flex, @@ -1893,6 +1900,16 @@ mlx5_flow_field_id_to_modify_info else info[idx].offset = off_be; break; + case RTE_FLOW_FIELD_MPLS: + MLX5_ASSERT(data->offset + width <= 32); + off_be = 32 - (data->offset + width); + info[idx] = (struct field_modify_info){4, 0, + mlx5_mpls_modi_field_get(data)}; + if (mask) + mask[idx] = flow_modify_info_mask_32(width, off_be); + else + info[idx].offset = off_be; + break; case RTE_FLOW_FIELD_TAG: { MLX5_ASSERT(data->offset + width <= 32); @@ -5362,6 +5379,12 @@ flow_dv_validate_action_modify_field(struct rte_eth_dev *dev, RTE_FLOW_ERROR_TYPE_ACTION, action, "modifications of the GENEVE Network" " Identifier is not supported"); + if (dst_data->field == RTE_FLOW_FIELD_MPLS || + src_data->field == RTE_FLOW_FIELD_MPLS) + return rte_flow_error_set(error, ENOTSUP, + RTE_FLOW_ERROR_TYPE_ACTION, action, + "modifications of the MPLS header " + "is not supported"); if (dst_data->field == RTE_FLOW_FIELD_MARK || src_data->field == RTE_FLOW_FIELD_MARK) if (config->dv_xmeta_en == MLX5_XMETA_MODE_LEGACY || diff --git a/drivers/net/mlx5/mlx5_flow_hw.c b/drivers/net/mlx5/mlx5_flow_hw.c index 0c76ee7446..8f35356c41 100644 --- a/drivers/net/mlx5/mlx5_flow_hw.c +++ b/drivers/net/mlx5/mlx5_flow_hw.c @@ -3713,6 +3713,11 @@ flow_hw_validate_action_modify_field(const struct rte_flow_action *action, return rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION, action, "modifying Geneve VNI is not supported"); + /* Due to HW bug, tunnel MPLS header is read only. */ + if (action_conf->dst.field == RTE_FLOW_FIELD_MPLS) + return rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ACTION, action, + "MPLS cannot be used as destination"); return 0; } @@ -4243,9 +4248,8 @@ mlx5_flow_hw_actions_validate(struct rte_eth_dev *dev, action_flags |= MLX5_FLOW_ACTION_METER; break; case RTE_FLOW_ACTION_TYPE_MODIFY_FIELD: - ret = flow_hw_validate_action_modify_field(action, - mask, - error); + ret = flow_hw_validate_action_modify_field(action, mask, + error); if (ret < 0) return ret; action_flags |= MLX5_FLOW_ACTION_MODIFY_FIELD; -- 2.25.1