@@ -636,6 +636,7 @@ enum index {
ACTION_MODIFY_FIELD_DST_TYPE_VALUE,
ACTION_MODIFY_FIELD_DST_LEVEL,
ACTION_MODIFY_FIELD_DST_LEVEL_VALUE,
+ ACTION_MODIFY_FIELD_DST_TAG_INDEX,
ACTION_MODIFY_FIELD_DST_TYPE_ID,
ACTION_MODIFY_FIELD_DST_CLASS_ID,
ACTION_MODIFY_FIELD_DST_OFFSET,
@@ -643,6 +644,7 @@ enum index {
ACTION_MODIFY_FIELD_SRC_TYPE_VALUE,
ACTION_MODIFY_FIELD_SRC_LEVEL,
ACTION_MODIFY_FIELD_SRC_LEVEL_VALUE,
+ ACTION_MODIFY_FIELD_SRC_TAG_INDEX,
ACTION_MODIFY_FIELD_SRC_TYPE_ID,
ACTION_MODIFY_FIELD_SRC_CLASS_ID,
ACTION_MODIFY_FIELD_SRC_OFFSET,
@@ -859,7 +861,7 @@ static const char *const modify_field_ids[] = {
"ipv6_proto",
"flex_item",
"hash_result",
- "geneve_opt_type", "geneve_opt_class", "geneve_opt_data",
+ "geneve_opt_type", "geneve_opt_class", "geneve_opt_data", "mpls",
NULL
};
@@ -2301,6 +2303,7 @@ static const enum index next_action_sample[] = {
static const enum index action_modify_field_dst[] = {
ACTION_MODIFY_FIELD_DST_LEVEL,
+ ACTION_MODIFY_FIELD_DST_TAG_INDEX,
ACTION_MODIFY_FIELD_DST_TYPE_ID,
ACTION_MODIFY_FIELD_DST_CLASS_ID,
ACTION_MODIFY_FIELD_DST_OFFSET,
@@ -2310,6 +2313,7 @@ static const enum index action_modify_field_dst[] = {
static const enum index action_modify_field_src[] = {
ACTION_MODIFY_FIELD_SRC_LEVEL,
+ ACTION_MODIFY_FIELD_SRC_TAG_INDEX,
ACTION_MODIFY_FIELD_SRC_TYPE_ID,
ACTION_MODIFY_FIELD_SRC_CLASS_ID,
ACTION_MODIFY_FIELD_SRC_OFFSET,
@@ -6398,6 +6402,15 @@ static const struct token token_list[] = {
.call = parse_vc_modify_field_level,
.comp = comp_none,
},
+ [ACTION_MODIFY_FIELD_DST_TAG_INDEX] = {
+ .name = "dst_tag_index",
+ .help = "destination field tag array",
+ .next = NEXT(action_modify_field_dst,
+ NEXT_ENTRY(COMMON_UNSIGNED)),
+ .args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
+ dst.tag_index)),
+ .call = parse_vc_conf,
+ },
[ACTION_MODIFY_FIELD_DST_TYPE_ID] = {
.name = "dst_type_id",
.help = "destination field type ID",
@@ -6451,6 +6464,15 @@ static const struct token token_list[] = {
.call = parse_vc_modify_field_level,
.comp = comp_none,
},
+ [ACTION_MODIFY_FIELD_SRC_TAG_INDEX] = {
+ .name = "stc_tag_index",
+ .help = "source field tag array",
+ .next = NEXT(action_modify_field_src,
+ NEXT_ENTRY(COMMON_UNSIGNED)),
+ .args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
+ src.tag_index)),
+ .call = parse_vc_conf,
+ },
[ACTION_MODIFY_FIELD_SRC_TYPE_ID] = {
.name = "src_type_id",
.help = "source field type ID",
@@ -2925,8 +2925,7 @@ See ``enum rte_flow_field_id`` for the list of supported fields.
``width`` defines a number of bits to use from ``src`` field.
-``level`` is used to access any packet field on any encapsulation level
-as well as any tag element in the tag array:
+``level`` is used to access any packet field on any encapsulation level:
- ``0`` means the default behaviour. Depending on the packet type,
it can mean outermost, innermost or anything in between.
@@ -2934,8 +2933,15 @@ as well as any tag element in the tag array:
- ``2`` and subsequent values requests access to the specified packet
encapsulation level, from outermost to innermost (lower to higher values).
-For the tag array (in case of multiple tags are supported and present)
-``level`` translates directly into the array index.
+``tag_index`` is the index of the header inside encapsulation level.
+It is used for modify either ``VLAN`` or ``MPLS`` or ``TAG`` headers which
+multiple of them might be supported in same encapsulation level.
+
+.. note::
+
+ For ``RTE_FLOW_FIELD_TAG`` type, the tag array was provided in ``level``
+ field and it is still supported for backwards compatibility.
+ When ``tag_index`` is zero, the tag array is taken from ``level`` field.
``type`` is used to specify (along with ``class_id``) the Geneve option which
is being modified.
@@ -3011,7 +3017,9 @@ and provide immediate value 0xXXXX85XX.
+=================+==========================================================+
| ``field`` | ID: packet field, mark, meta, tag, immediate, pointer |
+-----------------+----------------------------------------------------------+
- | ``level`` | encapsulation level of a packet field or tag array index |
+ | ``level`` | encapsulation level of a packet field |
+ +-----------------+----------------------------------------------------------+
+ | ``tag_index`` | tag index inside encapsulation level |
+-----------------+----------------------------------------------------------+
| ``type`` | geneve option type |
+-----------------+----------------------------------------------------------+
@@ -84,8 +84,12 @@ API Changes
Also, make sure to start the actual text at the margin.
=======================================================
-* The ``level`` field in experimental structure
- ``struct rte_flow_action_modify_data`` was reduced to 8 bits.
+* ethdev: in experimental structure ``struct rte_flow_action_modify_data``:
+
+ * ``level`` field was reduced to 8 bits.
+
+ * ``tag_index`` field replaced ``level`` field in representing tag array for
+ ``RTE_FLOW_FIELD_TAG`` type.
ABI Changes
@@ -2318,6 +2318,40 @@ mlx5_validate_action_ct(struct rte_eth_dev *dev,
return 0;
}
+/**
+ * Validate the level value for modify field action.
+ *
+ * @param[in] data
+ * Pointer to the rte_flow_action_modify_data structure either src or dst.
+ * @param[out] error
+ * Pointer to error structure.
+ *
+ * @return
+ * 0 on success, a negative errno value otherwise and rte_errno is set.
+ */
+int
+flow_validate_modify_field_level(const struct rte_flow_action_modify_data *data,
+ struct rte_flow_error *error)
+{
+ if (data->level == 0)
+ return 0;
+ if (data->field != RTE_FLOW_FIELD_TAG)
+ return rte_flow_error_set(error, ENOTSUP,
+ RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+ "inner header fields modification is not supported");
+ if (data->tag_index != 0)
+ return rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+ "tag array can be provided using 'level' or 'tag_index' fields, not both");
+ /*
+ * The tag array for RTE_FLOW_FIELD_TAG type is provided using
+ * 'tag_index' field. In old API, it was provided using 'level' field
+ * and it is still supported for backwards compatibility.
+ */
+ DRV_LOG(WARNING, "tag array provided in 'level' field instead of 'tag_index' field.");
+ return 0;
+}
+
/**
* Validate ICMP6 item.
*
@@ -1045,6 +1045,26 @@ flow_items_to_tunnel(const struct rte_flow_item items[])
return items[0].spec;
}
+/**
+ * Gets the tag array given for RTE_FLOW_FIELD_TAG type.
+ *
+ * In old API the value was provided in "level" field, but in new API
+ * it is provided in "tag_array" field. Since encapsulation level is not
+ * relevant for metadata, the tag array can be still provided in "level"
+ * for backwards compatibility.
+ *
+ * @param[in] data
+ * Pointer to tag modify data structure.
+ *
+ * @return
+ * Tag array index.
+ */
+static inline uint8_t
+flow_tag_index_get(const struct rte_flow_action_modify_data *data)
+{
+ return data->tag_index ? data->tag_index : data->level;
+}
+
/**
* Fetch 1, 2, 3 or 4 byte field from the byte array
* and return as unsigned integer in host-endian format.
@@ -2276,6 +2296,9 @@ int mlx5_flow_validate_action_rss(const struct rte_flow_action *action,
int mlx5_flow_validate_action_default_miss(uint64_t action_flags,
const struct rte_flow_attr *attr,
struct rte_flow_error *error);
+int flow_validate_modify_field_level
+ (const struct rte_flow_action_modify_data *data,
+ struct rte_flow_error *error);
int mlx5_flow_item_acceptable(const struct rte_flow_item *item,
const uint8_t *mask,
const uint8_t *nic_mask,
@@ -1896,16 +1896,17 @@ mlx5_flow_field_id_to_modify_info
case RTE_FLOW_FIELD_TAG:
{
MLX5_ASSERT(data->offset + width <= 32);
+ uint8_t tag_index = flow_tag_index_get(data);
int reg;
- off_be = (data->level == MLX5_LINEAR_HASH_TAG_INDEX) ?
+ off_be = (tag_index == MLX5_LINEAR_HASH_TAG_INDEX) ?
16 - (data->offset + width) + 16 : data->offset;
if (priv->sh->config.dv_flow_en == 2)
reg = flow_hw_get_reg_id(RTE_FLOW_ITEM_TYPE_TAG,
- data->level);
+ tag_index);
else
reg = mlx5_flow_get_reg_id(dev, MLX5_APP_TAG,
- data->level, error);
+ tag_index, error);
if (reg < 0)
return;
MLX5_ASSERT(reg != REG_NON);
@@ -1985,7 +1986,7 @@ mlx5_flow_field_id_to_modify_info
{
uint32_t meta_mask = priv->sh->dv_meta_mask;
uint32_t meta_count = __builtin_popcount(meta_mask);
- uint32_t reg = data->level;
+ uint8_t reg = flow_tag_index_get(data);
RTE_SET_USED(meta_count);
MLX5_ASSERT(data->offset + width <= meta_count);
@@ -5245,115 +5246,105 @@ flow_dv_validate_action_modify_field(struct rte_eth_dev *dev,
struct mlx5_priv *priv = dev->data->dev_private;
struct mlx5_sh_config *config = &priv->sh->config;
struct mlx5_hca_attr *hca_attr = &priv->sh->cdev->config.hca_attr;
- const struct rte_flow_action_modify_field *action_modify_field =
- action->conf;
- uint32_t dst_width, src_width;
+ const struct rte_flow_action_modify_field *conf = action->conf;
+ const struct rte_flow_action_modify_data *src_data = &conf->src;
+ const struct rte_flow_action_modify_data *dst_data = &conf->dst;
+ uint32_t dst_width, src_width, width = conf->width;
ret = flow_dv_validate_action_modify_hdr(action_flags, action, error);
if (ret)
return ret;
- if (action_modify_field->src.field == RTE_FLOW_FIELD_FLEX_ITEM ||
- action_modify_field->dst.field == RTE_FLOW_FIELD_FLEX_ITEM)
+ if (src_data->field == RTE_FLOW_FIELD_FLEX_ITEM ||
+ dst_data->field == RTE_FLOW_FIELD_FLEX_ITEM)
return rte_flow_error_set(error, ENOTSUP,
RTE_FLOW_ERROR_TYPE_ACTION, action,
"flex item fields modification"
" is not supported");
- dst_width = mlx5_flow_item_field_width(dev, action_modify_field->dst.field,
+ dst_width = mlx5_flow_item_field_width(dev, dst_data->field,
-1, attr, error);
- src_width = mlx5_flow_item_field_width(dev, action_modify_field->src.field,
+ src_width = mlx5_flow_item_field_width(dev, src_data->field,
dst_width, attr, error);
- if (action_modify_field->width == 0)
+ if (width == 0)
return rte_flow_error_set(error, EINVAL,
RTE_FLOW_ERROR_TYPE_ACTION, action,
"no bits are requested to be modified");
- else if (action_modify_field->width > dst_width ||
- action_modify_field->width > src_width)
+ else if (width > dst_width || width > src_width)
return rte_flow_error_set(error, EINVAL,
RTE_FLOW_ERROR_TYPE_ACTION, action,
"cannot modify more bits than"
" the width of a field");
- if (action_modify_field->dst.field != RTE_FLOW_FIELD_VALUE &&
- action_modify_field->dst.field != RTE_FLOW_FIELD_POINTER) {
- if (action_modify_field->dst.offset +
- action_modify_field->width > dst_width)
+ if (dst_data->field != RTE_FLOW_FIELD_VALUE &&
+ dst_data->field != RTE_FLOW_FIELD_POINTER) {
+ if (dst_data->offset + width > dst_width)
return rte_flow_error_set(error, EINVAL,
RTE_FLOW_ERROR_TYPE_ACTION, action,
"destination offset is too big");
- if (action_modify_field->dst.level &&
- action_modify_field->dst.field != RTE_FLOW_FIELD_TAG)
- return rte_flow_error_set(error, ENOTSUP,
- RTE_FLOW_ERROR_TYPE_ACTION, action,
- "inner header fields modification"
- " is not supported");
+ ret = flow_validate_modify_field_level(dst_data, error);
+ if (ret)
+ return ret;
}
- if (action_modify_field->src.field != RTE_FLOW_FIELD_VALUE &&
- action_modify_field->src.field != RTE_FLOW_FIELD_POINTER) {
+ if (src_data->field != RTE_FLOW_FIELD_VALUE &&
+ src_data->field != RTE_FLOW_FIELD_POINTER) {
if (root)
return rte_flow_error_set(error, ENOTSUP,
RTE_FLOW_ERROR_TYPE_ACTION, action,
"modify field action is not"
" supported for group 0");
- if (action_modify_field->src.offset +
- action_modify_field->width > src_width)
+ if (src_data->offset + width > src_width)
return rte_flow_error_set(error, EINVAL,
RTE_FLOW_ERROR_TYPE_ACTION, action,
"source offset is too big");
- if (action_modify_field->src.level &&
- action_modify_field->src.field != RTE_FLOW_FIELD_TAG)
- return rte_flow_error_set(error, ENOTSUP,
- RTE_FLOW_ERROR_TYPE_ACTION, action,
- "inner header fields modification"
- " is not supported");
+ ret = flow_validate_modify_field_level(src_data, error);
+ if (ret)
+ return ret;
}
- if ((action_modify_field->dst.field ==
- action_modify_field->src.field) &&
- (action_modify_field->dst.level ==
- action_modify_field->src.level))
+ if ((dst_data->field == src_data->field) &&
+ (dst_data->level == src_data->level))
return rte_flow_error_set(error, EINVAL,
RTE_FLOW_ERROR_TYPE_ACTION, action,
"source and destination fields"
" cannot be the same");
- if (action_modify_field->dst.field == RTE_FLOW_FIELD_VALUE ||
- action_modify_field->dst.field == RTE_FLOW_FIELD_POINTER ||
- action_modify_field->dst.field == RTE_FLOW_FIELD_MARK)
+ if (dst_data->field == RTE_FLOW_FIELD_VALUE ||
+ dst_data->field == RTE_FLOW_FIELD_POINTER ||
+ dst_data->field == RTE_FLOW_FIELD_MARK)
return rte_flow_error_set(error, EINVAL,
RTE_FLOW_ERROR_TYPE_ACTION, action,
"mark, immediate value or a pointer to it"
" cannot be used as a destination");
- if (action_modify_field->dst.field == RTE_FLOW_FIELD_START ||
- action_modify_field->src.field == RTE_FLOW_FIELD_START)
+ if (dst_data->field == RTE_FLOW_FIELD_START ||
+ src_data->field == RTE_FLOW_FIELD_START)
return rte_flow_error_set(error, ENOTSUP,
RTE_FLOW_ERROR_TYPE_ACTION, action,
"modifications of an arbitrary"
" place in a packet is not supported");
- if (action_modify_field->dst.field == RTE_FLOW_FIELD_VLAN_TYPE ||
- action_modify_field->src.field == RTE_FLOW_FIELD_VLAN_TYPE)
+ if (dst_data->field == RTE_FLOW_FIELD_VLAN_TYPE ||
+ src_data->field == RTE_FLOW_FIELD_VLAN_TYPE)
return rte_flow_error_set(error, ENOTSUP,
RTE_FLOW_ERROR_TYPE_ACTION, action,
"modifications of the 802.1Q Tag"
" Identifier is not supported");
- if (action_modify_field->dst.field == RTE_FLOW_FIELD_VXLAN_VNI ||
- action_modify_field->src.field == RTE_FLOW_FIELD_VXLAN_VNI)
+ if (dst_data->field == RTE_FLOW_FIELD_VXLAN_VNI ||
+ src_data->field == RTE_FLOW_FIELD_VXLAN_VNI)
return rte_flow_error_set(error, ENOTSUP,
RTE_FLOW_ERROR_TYPE_ACTION, action,
"modifications of the VXLAN Network"
" Identifier is not supported");
- if (action_modify_field->dst.field == RTE_FLOW_FIELD_GENEVE_VNI ||
- action_modify_field->src.field == RTE_FLOW_FIELD_GENEVE_VNI)
+ if (dst_data->field == RTE_FLOW_FIELD_GENEVE_VNI ||
+ src_data->field == RTE_FLOW_FIELD_GENEVE_VNI)
return rte_flow_error_set(error, ENOTSUP,
RTE_FLOW_ERROR_TYPE_ACTION, action,
"modifications of the GENEVE Network"
" Identifier is not supported");
- if (action_modify_field->dst.field == RTE_FLOW_FIELD_MARK ||
- action_modify_field->src.field == RTE_FLOW_FIELD_MARK)
+ if (dst_data->field == RTE_FLOW_FIELD_MARK ||
+ src_data->field == RTE_FLOW_FIELD_MARK)
if (config->dv_xmeta_en == MLX5_XMETA_MODE_LEGACY ||
!mlx5_flow_ext_mreg_supported(dev))
return rte_flow_error_set(error, ENOTSUP,
RTE_FLOW_ERROR_TYPE_ACTION, action,
"cannot modify mark in legacy mode"
" or without extensive registers");
- if (action_modify_field->dst.field == RTE_FLOW_FIELD_META ||
- action_modify_field->src.field == RTE_FLOW_FIELD_META) {
+ if (dst_data->field == RTE_FLOW_FIELD_META ||
+ src_data->field == RTE_FLOW_FIELD_META) {
if (config->dv_xmeta_en != MLX5_XMETA_MODE_LEGACY &&
!mlx5_flow_ext_mreg_supported(dev))
return rte_flow_error_set(error, ENOTSUP,
@@ -5367,20 +5358,19 @@ flow_dv_validate_action_modify_field(struct rte_eth_dev *dev,
"cannot modify meta without"
" extensive registers available");
}
- if (action_modify_field->operation == RTE_FLOW_MODIFY_SUB)
+ if (conf->operation == RTE_FLOW_MODIFY_SUB)
return rte_flow_error_set(error, ENOTSUP,
RTE_FLOW_ERROR_TYPE_ACTION, action,
"sub operations are not supported");
- if (action_modify_field->dst.field == RTE_FLOW_FIELD_IPV4_ECN ||
- action_modify_field->src.field == RTE_FLOW_FIELD_IPV4_ECN ||
- action_modify_field->dst.field == RTE_FLOW_FIELD_IPV6_ECN ||
- action_modify_field->src.field == RTE_FLOW_FIELD_IPV6_ECN)
+ if (dst_data->field == RTE_FLOW_FIELD_IPV4_ECN ||
+ src_data->field == RTE_FLOW_FIELD_IPV4_ECN ||
+ dst_data->field == RTE_FLOW_FIELD_IPV6_ECN ||
+ src_data->field == RTE_FLOW_FIELD_IPV6_ECN)
if (!hca_attr->modify_outer_ip_ecn && root)
return rte_flow_error_set(error, ENOTSUP,
RTE_FLOW_ERROR_TYPE_ACTION, action,
"modifications of the ECN for current firmware is not supported");
- return (action_modify_field->width / 32) +
- !!(action_modify_field->width % 32);
+ return (width / 32) + !!(width % 32);
}
/**
@@ -1022,9 +1022,11 @@ flow_hw_modify_field_compile(struct rte_eth_dev *dev,
conf->dst.field == RTE_FLOW_FIELD_TAG ||
conf->dst.field == RTE_FLOW_FIELD_METER_COLOR ||
conf->dst.field == (enum rte_flow_field_id)MLX5_RTE_FLOW_FIELD_META_REG) {
+ uint8_t tag_index = flow_tag_index_get(&conf->dst);
+
value = *(const unaligned_uint32_t *)item.spec;
if (conf->dst.field == RTE_FLOW_FIELD_TAG &&
- conf->dst.level == MLX5_LINEAR_HASH_TAG_INDEX)
+ tag_index == MLX5_LINEAR_HASH_TAG_INDEX)
value = rte_cpu_to_be_32(value << 16);
else
value = rte_cpu_to_be_32(value);
@@ -2055,9 +2057,11 @@ flow_hw_modify_field_construct(struct mlx5_hw_q_job *job,
mhdr_action->dst.field == RTE_FLOW_FIELD_TAG ||
mhdr_action->dst.field == RTE_FLOW_FIELD_METER_COLOR ||
mhdr_action->dst.field == (enum rte_flow_field_id)MLX5_RTE_FLOW_FIELD_META_REG) {
+ uint8_t tag_index = flow_tag_index_get(&mhdr_action->dst);
+
value_p = (unaligned_uint32_t *)values;
if (mhdr_action->dst.field == RTE_FLOW_FIELD_TAG &&
- mhdr_action->dst.level == MLX5_LINEAR_HASH_TAG_INDEX)
+ tag_index == MLX5_LINEAR_HASH_TAG_INDEX)
*value_p = rte_cpu_to_be_32(*value_p << 16);
else
*value_p = rte_cpu_to_be_32(*value_p);
@@ -3546,10 +3550,9 @@ flow_hw_validate_action_modify_field(const struct rte_flow_action *action,
const struct rte_flow_action *mask,
struct rte_flow_error *error)
{
- const struct rte_flow_action_modify_field *action_conf =
- action->conf;
- const struct rte_flow_action_modify_field *mask_conf =
- mask->conf;
+ const struct rte_flow_action_modify_field *action_conf = action->conf;
+ const struct rte_flow_action_modify_field *mask_conf = mask->conf;
+ int ret;
if (action_conf->operation != mask_conf->operation)
return rte_flow_error_set(error, EINVAL,
@@ -3565,6 +3568,9 @@ 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,
"immediate value, pointer and hash result cannot be used as destination");
+ ret = flow_validate_modify_field_level(&action_conf->dst, error);
+ if (ret)
+ return ret;
if (mask_conf->dst.level != UINT8_MAX)
return rte_flow_error_set(error, EINVAL,
RTE_FLOW_ERROR_TYPE_ACTION, action,
@@ -3587,6 +3593,9 @@ 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,
"source offset level must be fully masked");
+ ret = flow_validate_modify_field_level(&action_conf->src, error);
+ if (ret)
+ return ret;
}
if (mask_conf->width != UINT32_MAX)
return rte_flow_error_set(error, EINVAL,
@@ -3740,8 +3740,8 @@ enum rte_flow_field_id {
RTE_FLOW_FIELD_START = 0, /**< Start of a packet. */
RTE_FLOW_FIELD_MAC_DST, /**< Destination MAC Address. */
RTE_FLOW_FIELD_MAC_SRC, /**< Source MAC Address. */
- RTE_FLOW_FIELD_VLAN_TYPE, /**< 802.1Q Tag Identifier. */
- RTE_FLOW_FIELD_VLAN_ID, /**< 802.1Q VLAN Identifier. */
+ RTE_FLOW_FIELD_VLAN_TYPE, /**< VLAN Tag Identifier. */
+ RTE_FLOW_FIELD_VLAN_ID, /**< VLAN Identifier. */
RTE_FLOW_FIELD_MAC_TYPE, /**< EtherType. */
RTE_FLOW_FIELD_IPV4_DSCP, /**< IPv4 DSCP. */
RTE_FLOW_FIELD_IPV4_TTL, /**< IPv4 Time To Live. */
@@ -3775,7 +3775,8 @@ enum rte_flow_field_id {
RTE_FLOW_FIELD_HASH_RESULT, /**< Hash result. */
RTE_FLOW_FIELD_GENEVE_OPT_TYPE, /**< GENEVE option type */
RTE_FLOW_FIELD_GENEVE_OPT_CLASS,/**< GENEVE option class */
- RTE_FLOW_FIELD_GENEVE_OPT_DATA /**< GENEVE option data */
+ RTE_FLOW_FIELD_GENEVE_OPT_DATA, /**< GENEVE option data */
+ RTE_FLOW_FIELD_MPLS /**< MPLS header. */
};
/**
@@ -3789,7 +3790,7 @@ struct rte_flow_action_modify_data {
RTE_STD_C11
union {
struct {
- /** Encapsulation level or tag index or flex item handle. */
+ /** Encapsulation level and tag index or flex item handle. */
union {
struct {
/**
@@ -3820,20 +3821,38 @@ struct rte_flow_action_modify_data {
*
* Values other than @p 0 are not
* necessarily supported.
+ *
+ * @note that for MPLS field,
+ * encapsulation level also include
+ * tunnel since MPLS may appear in
+ * outer, inner or tunnel.
*/
uint8_t level;
- /**
- * Geneve option type. relevant only
- * for RTE_FLOW_FIELD_GENEVE_OPT_XXXX
- * modification type.
- */
- uint8_t type;
- /**
- * Geneve option class. relevant only
- * for RTE_FLOW_FIELD_GENEVE_OPT_XXXX
- * modification type.
- */
- rte_be16_t class_id;
+ union {
+ /**
+ * Tag index array inside
+ * encapsulation level.
+ * Used for VLAN, MPLS or TAG
+ * types.
+ */
+ uint8_t tag_index;
+ /**
+ * Geneve option identifier.
+ * relevant only for
+ * RTE_FLOW_FIELD_GENEVE_OPT_XXXX
+ * modification type.
+ */
+ struct {
+ /**
+ * Geneve option type.
+ */
+ uint8_t type;
+ /**
+ * Geneve option class.
+ */
+ rte_be16_t class_id;
+ };
+ };
};
struct rte_flow_item_flex_handle *flex_handle;
};