@@ -1616,6 +1616,10 @@ int mlx5_flow_dev_dump(struct rte_eth_dev *dev, struct rte_flow *flow,
void mlx5_flow_rxq_dynf_metadata_set(struct rte_eth_dev *dev);
int mlx5_flow_get_aged_flows(struct rte_eth_dev *dev, void **contexts,
uint32_t nb_contexts, struct rte_flow_error *error);
+int mlx5_validate_action_ct(struct rte_eth_dev *dev,
+ const struct rte_flow_action_conntrack *conntrack,
+ struct rte_flow_error *error);
+
/* mlx5_mp_os.c */
@@ -1688,6 +1688,37 @@ mlx5_flow_validate_action_count(struct rte_eth_dev *dev __rte_unused,
return 0;
}
+/*
+ * Validate the ASO CT action.
+ *
+ * @param[in] dev
+ * Pointer to the Ethernet device structure.
+ * @param[in] conntrack
+ * Pointer to the CT action profile.
+ * @param[out] error
+ * Pointer to error structure.
+ *
+ * @return
+ * 0 on success, a negative errno value otherwise and rte_errno is set.
+ */
+int
+mlx5_validate_action_ct(struct rte_eth_dev *dev,
+ const struct rte_flow_action_conntrack *conntrack,
+ struct rte_flow_error *error)
+{
+ RTE_SET_USED(dev);
+
+ if (conntrack->state > RTE_FLOW_CONNTRACK_STATE_TIME_WAIT)
+ return rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+ "Invalid CT state");
+ if (conntrack->last_index > RTE_FLOW_CONNTRACK_FLAG_RST)
+ return rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+ "Invalid last TCP packet flag");
+ return 0;
+}
+
/**
* Verify the @p attributes will be correctly understood by the NIC and store
* them in the @p flow if everything is correct.
@@ -3442,6 +3442,57 @@ flow_dv_validate_action_raw_encap_decap
return 0;
}
+/*
+ * Validate the ASO CT action.
+ *
+ * @param[in] dev
+ * Pointer to the rte_eth_dev structure.
+ * @param[in] action_flags
+ * Holds the actions detected until now.
+ * @param[in] item_flags
+ * The items found in this flow rule.
+ * @param[in] attr
+ * Pointer to flow attributes.
+ * @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_aso_ct(struct rte_eth_dev *dev,
+ uint64_t action_flags,
+ uint64_t item_flags,
+ const struct rte_flow_attr *attr,
+ struct rte_flow_error *error)
+{
+ RTE_SET_USED(dev);
+
+ if (attr->group == 0 && !attr->transfer)
+ return rte_flow_error_set(error, ENOTSUP,
+ RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+ NULL,
+ "Only support non-root table");
+ if (action_flags & MLX5_FLOW_FATE_ACTIONS)
+ return rte_flow_error_set(error, ENOTSUP,
+ RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+ "CT cannot follow a fate action");
+ if ((action_flags & MLX5_FLOW_ACTION_METER) ||
+ (action_flags & MLX5_FLOW_ACTION_AGE))
+ return rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+ "Only one ASO action is supported");
+ if (action_flags & MLX5_FLOW_ACTION_ENCAP)
+ return rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+ "Encap cannot exist before CT");
+ if (!(item_flags & MLX5_FLOW_LAYER_OUTER_L4_TCP))
+ return rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+ "Not a outer TCP packet");
+ return 0;
+}
+
/**
* Match encap_decap resource.
*
@@ -7442,6 +7493,14 @@ flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
action_flags |= MLX5_FLOW_ACTION_MODIFY_FIELD;
rw_act_num += ret;
break;
+ case RTE_FLOW_ACTION_TYPE_CONNTRACK:
+ ret = flow_dv_validate_action_aso_ct(dev, action_flags,
+ item_flags, attr,
+ error);
+ if (ret < 0)
+ return ret;
+ action_flags |= MLX5_FLOW_ACTION_CT;
+ break;
default:
return rte_flow_error_set(error, ENOTSUP,
RTE_FLOW_ERROR_TYPE_ACTION,
@@ -14292,6 +14351,10 @@ __flow_dv_action_ct_update(struct rte_eth_dev *dev, uint32_t idx,
if (update->direction)
ct->is_original = !!new_prf->is_original_dir;
if (update->state) {
+ /* Only validate the profile when it needs to be updated. */
+ ret = mlx5_validate_action_ct(dev, new_prf, error);
+ if (ret)
+ return ret;
ret = mlx5_aso_ct_update_by_wqe(priv->sh, ct, new_prf);
if (ret)
return rte_flow_error_set(error, EIO,
@@ -16176,6 +16239,12 @@ flow_dv_action_validate(struct rte_eth_dev *dev,
NULL,
"Mix shared and indirect counter is not supported");
return flow_dv_validate_action_count(dev, true, 0, err);
+ case RTE_FLOW_ACTION_TYPE_CONNTRACK:
+ if (!priv->sh->ct_aso_en)
+ return rte_flow_error_set(err, ENOTSUP,
+ RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+ "ASO CT is not supported");
+ return mlx5_validate_action_ct(dev, action->conf, err);
default:
return rte_flow_error_set(err, ENOTSUP,
RTE_FLOW_ERROR_TYPE_ACTION,