@@ -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.
@@ -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,
};
@@ -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;
@@ -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 ||
@@ -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;