@@ -218,6 +218,7 @@ enum mlx5_feature_name {
#define MLX5_FLOW_ACTION_SAMPLE (1ull << 36)
#define MLX5_FLOW_ACTION_TUNNEL_SET (1ull << 37)
#define MLX5_FLOW_ACTION_TUNNEL_MATCH (1ull << 38)
+#define MLX5_FLOW_ACTION_MODIFY_FIELD (1ull << 39)
#define MLX5_FLOW_FATE_ACTIONS \
(MLX5_FLOW_ACTION_DROP | MLX5_FLOW_ACTION_QUEUE | \
@@ -248,7 +249,8 @@ enum mlx5_feature_name {
MLX5_FLOW_ACTION_MARK_EXT | \
MLX5_FLOW_ACTION_SET_META | \
MLX5_FLOW_ACTION_SET_IPV4_DSCP | \
- MLX5_FLOW_ACTION_SET_IPV6_DSCP)
+ MLX5_FLOW_ACTION_SET_IPV6_DSCP | \
+ MLX5_FLOW_ACTION_MODIFY_FIELD)
#define MLX5_FLOW_VLAN_ACTIONS (MLX5_FLOW_ACTION_OF_POP_VLAN | \
MLX5_FLOW_ACTION_OF_PUSH_VLAN)
@@ -1320,6 +1320,52 @@ flow_dv_convert_action_modify_ipv6_dscp
MLX5_MODIFICATION_TYPE_SET, error);
}
+/**
+ * Convert modify_field 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_field
+ (struct mlx5_flow_dv_modify_hdr_resource *resource,
+ const struct rte_flow_action *action,
+ struct rte_flow_error *error)
+{
+ const struct rte_flow_action_modify_field *conf =
+ (const struct rte_flow_action_modify_field *)(action->conf);
+ struct rte_flow_item item = { .type = RTE_FLOW_ITEM_TYPE_ETH };
+ struct rte_flow_item_eth eth;
+ struct rte_flow_item_eth eth_mask;
+
+ memset(ð, 0, sizeof(eth));
+ memset(ð_mask, 0, sizeof(eth_mask));
+ if (conf->dst.field == RTE_FLOW_FIELD_MAC_SRC) {
+ memcpy(ð.src.addr_bytes, &conf->src.value,
+ sizeof(eth.src.addr_bytes));
+ memcpy(ð_mask.src.addr_bytes,
+ &rte_flow_item_eth_mask.src.addr_bytes,
+ sizeof(eth_mask.src.addr_bytes));
+ } else {
+ memcpy(ð.dst.addr_bytes, &conf->src.value,
+ sizeof(eth.dst.addr_bytes));
+ memcpy(ð_mask.dst.addr_bytes,
+ &rte_flow_item_eth_mask.dst.addr_bytes,
+ sizeof(eth_mask.dst.addr_bytes));
+ }
+ item.spec = ð
+ item.mask = ð_mask;
+ return flow_dv_convert_modify_action(&item, modify_eth, NULL, resource,
+ MLX5_MODIFICATION_TYPE_SET, error);
+}
+
/**
* Validate MARK item.
*
@@ -3984,6 +4030,61 @@ flow_dv_validate_action_modify_ttl(const uint64_t action_flags,
return ret;
}
+/**
+ * Validate the generic modify field actions.
+ *
+ * @param[in] action_flags
+ * Holds the actions detected until now.
+ * @param[in] action
+ * Pointer to the modify action.
+ * @param[in] item_flags
+ * Holds the items detected.
+ * @param[out] error
+ * Pointer to error structure.
+ *
+ * @return
+ * 0 on success, a negative errno value otherwise and rte_errno is set.
+ */
+static int
+flow_dv_validate_action_modify_field(const uint64_t action_flags,
+ const struct rte_flow_action *action,
+ const uint64_t item_flags,
+ struct rte_flow_error *error)
+{
+ int ret = 0;
+ const struct rte_flow_action_modify_field *action_modify_field =
+ action->conf;
+
+ ret = flow_dv_validate_action_modify_hdr(action_flags, action, error);
+ if (!ret) {
+ if (!(item_flags & MLX5_FLOW_LAYER_L2))
+ return rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ACTION,
+ NULL,
+ "no L2 item in pattern");
+ if (action_modify_field->operation != RTE_FLOW_MODIFY_SET)
+ return rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ACTION,
+ NULL,
+ "add and sub opearation are"
+ " not supported");
+ if (action_modify_field->dst.field != RTE_FLOW_FIELD_MAC_DST &&
+ action_modify_field->dst.field != RTE_FLOW_FIELD_MAC_SRC)
+ return rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ACTION,
+ NULL,
+ "cannot modify requested"
+ " header field");
+ if (action_modify_field->src.field != RTE_FLOW_FIELD_VALUE)
+ return rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ACTION,
+ NULL,
+ "copy form another packet"
+ " field is not suported");
+ }
+ return ret;
+}
+
/**
* Validate jump action.
*
@@ -6120,6 +6221,19 @@ flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
action_flags |= MLX5_FLOW_ACTION_TUNNEL_SET;
break;
+ case RTE_FLOW_ACTION_TYPE_MODIFY_FIELD:
+ ret = flow_dv_validate_action_modify_field(action_flags,
+ actions,
+ item_flags,
+ error);
+ if (ret < 0)
+ return ret;
+ /* Count all modify-header actions as one action. */
+ if (!(action_flags & MLX5_FLOW_ACTION_MODIFY_FIELD))
+ ++actions_n;
+ action_flags |= MLX5_FLOW_ACTION_MODIFY_FIELD;
+ rw_act_num += MLX5_ACT_NUM_MDF_MAC;
+ break;
default:
return rte_flow_error_set(error, ENOTSUP,
RTE_FLOW_ERROR_TYPE_ACTION,
@@ -10404,6 +10518,12 @@ flow_dv_translate(struct rte_eth_dev *dev,
sample_act->action_flags |=
MLX5_FLOW_ACTION_ENCAP;
break;
+ case RTE_FLOW_ACTION_TYPE_MODIFY_FIELD:
+ if (flow_dv_convert_action_modify_field
+ (mhdr_res, actions, error))
+ return -rte_errno;
+ action_flags |= MLX5_FLOW_ACTION_MODIFY_FIELD;
+ break;
case RTE_FLOW_ACTION_TYPE_END:
actions_end = true;
if (mhdr_res->actions_num) {