Hi Jiawei,
PSB,
Thanks,
Ori
> -----Original Message-----
> From: Jiawei Wang <jiaweiw@mellanox.com>
> Sent: Thursday, June 25, 2020 7:26 PM
> Subject: [PATCH 6/8] net/mlx5: update translate function for sample action
>
> Translate the attribute of sample action that include sample ratio
> and sub actions list, then create the sample DR action.
>
> Signed-off-by: Jiawei Wang <jiaweiw@mellanox.com>
> ---
> drivers/net/mlx5/mlx5_flow.c | 16 +-
> drivers/net/mlx5/mlx5_flow.h | 14 +-
> drivers/net/mlx5/mlx5_flow_dv.c | 502
> +++++++++++++++++++++++++++++++++++++++-
> 3 files changed, 511 insertions(+), 21 deletions(-)
>
> diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c
> index 7c65a9a..73ef290 100644
> --- a/drivers/net/mlx5/mlx5_flow.c
> +++ b/drivers/net/mlx5/mlx5_flow.c
> @@ -4569,10 +4569,14 @@ uint32_t mlx5_flow_adjust_priority(struct
> rte_eth_dev *dev, int32_t priority,
> int hairpin_flow;
> uint32_t hairpin_id = 0;
> struct rte_flow_attr attr_tx = { .priority = 0 };
> + struct rte_flow_attr attr_factor = {0};
> int ret;
>
> - hairpin_flow = flow_check_hairpin_split(dev, attr, actions);
> - ret = flow_drv_validate(dev, attr, items, p_actions_rx,
> + memcpy((void *)&attr_factor, (const void *)attr, sizeof(*attr));
> + if (external)
> + attr_factor.group *= MLX5_FLOW_TABLE_FACTOR;
> + hairpin_flow = flow_check_hairpin_split(dev, &attr_factor, actions);
> + ret = flow_drv_validate(dev, &attr_factor, items, p_actions_rx,
> external, hairpin_flow, error);
> if (ret < 0)
> return 0;
> @@ -4591,7 +4595,7 @@ uint32_t mlx5_flow_adjust_priority(struct
> rte_eth_dev *dev, int32_t priority,
> rte_errno = ENOMEM;
> goto error_before_flow;
> }
> - flow->drv_type = flow_get_drv_type(dev, attr);
> + flow->drv_type = flow_get_drv_type(dev, &attr_factor);
> if (hairpin_id != 0)
> flow->hairpin_flow_id = hairpin_id;
> MLX5_ASSERT(flow->drv_type > MLX5_FLOW_TYPE_MIN &&
> @@ -4637,7 +4641,7 @@ uint32_t mlx5_flow_adjust_priority(struct
> rte_eth_dev *dev, int32_t priority,
> * depending on configuration. In the simplest
> * case it just creates unmodified original flow.
> */
> - ret = flow_create_split_outer(dev, flow, attr,
> + ret = flow_create_split_outer(dev, flow, &attr_factor,
> buf->entry[i].pattern,
> p_actions_rx, external, idx,
> error);
> @@ -4674,8 +4678,8 @@ uint32_t mlx5_flow_adjust_priority(struct
> rte_eth_dev *dev, int32_t priority,
> * the egress Flows belong to the different device and
> * copy table should be updated in peer NIC Rx domain.
> */
> - if (attr->ingress &&
> - (external || attr->group != MLX5_FLOW_MREG_CP_TABLE_GROUP))
> {
> + if (attr_factor.ingress &&
> + (external || attr_factor.group !=
> MLX5_FLOW_MREG_CP_TABLE_GROUP)) {
> ret = flow_mreg_update_copy_table(dev, flow, actions, error);
> if (ret)
> goto error;
> diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h
> index 941de5f..4163183 100644
> --- a/drivers/net/mlx5/mlx5_flow.h
> +++ b/drivers/net/mlx5/mlx5_flow.h
> @@ -369,6 +369,13 @@ enum mlx5_flow_fate_type {
> MLX5_FLOW_FATE_MAX,
> };
>
> +/*
> + * Max number of actions per DV flow.
> + * See CREATE_FLOW_MAX_FLOW_ACTIONS_SUPPORTED
> + * in rdma-core file providers/mlx5/verbs.c.
> + */
> +#define MLX5_DV_MAX_NUMBER_OF_ACTIONS 8
> +
> /* Matcher PRM representation */
> struct mlx5_flow_dv_match_params {
> size_t size;
> @@ -599,13 +606,6 @@ struct mlx5_flow_handle {
> #define MLX5_FLOW_HANDLE_VERBS_SIZE (sizeof(struct mlx5_flow_handle))
> #endif
>
> -/*
> - * Max number of actions per DV flow.
> - * See CREATE_FLOW_MAX_FLOW_ACTIONS_SUPPORTED
> - * in rdma-core file providers/mlx5/verbs.c.
> - */
> -#define MLX5_DV_MAX_NUMBER_OF_ACTIONS 8
> -
> /** Device flow structure only for DV flow creation. */
> struct mlx5_flow_dv_workspace {
> uint32_t group; /**< The group index. */
> diff --git a/drivers/net/mlx5/mlx5_flow_dv.c
> b/drivers/net/mlx5/mlx5_flow_dv.c
> index 710c0f3..62a4a3b 100644
> --- a/drivers/net/mlx5/mlx5_flow_dv.c
> +++ b/drivers/net/mlx5/mlx5_flow_dv.c
> @@ -79,6 +79,10 @@
> flow_dv_tbl_resource_release(struct rte_eth_dev *dev,
> struct mlx5_flow_tbl_resource *tbl);
>
> +static int
> +flow_dv_encap_decap_resource_release(struct rte_eth_dev *dev,
> + uint32_t encap_decap_idx);
> +
> /**
> * Initialize flow attributes structure according to flow items' types.
> *
> @@ -7897,6 +7901,385 @@ struct field_modify_info modify_tcp[] = {
> }
>
> /**
> + * Create an Rx Hash queue.
> + *
> + * @param dev
> + * Pointer to Ethernet device.
> + * @param[in] dev_flow
> + * Pointer to the mlx5_flow.
> + * @param[in] rss_desc
> + * Pointer to the mlx5_flow_rss_desc.
> + * @param[in, out] hrxq_idx
I think this is only used as out.
> + * Hash Rx queue index.
> + * @param[out] error
> + * Pointer to error structure.
> + *
> + * @return
> + * The Verbs/DevX object initialised, NULL otherwise and rte_errno is set.
> + */
> +static struct mlx5_hrxq *
> +flow_dv_handle_rx_queue(struct rte_eth_dev *dev,
> + struct mlx5_flow *dev_flow,
> + struct mlx5_flow_rss_desc *rss_desc,
> + uint32_t *hrxq_idx,
> + struct rte_flow_error *error)
> +{
> + struct mlx5_priv *priv = dev->data->dev_private;
> + struct mlx5_flow_handle *dh = dev_flow->handle;
> + struct mlx5_hrxq *hrxq;
> +
> + MLX5_ASSERT(rss_desc->queue_num);
> + *hrxq_idx = mlx5_hrxq_get(dev, rss_desc->key,
> + MLX5_RSS_HASH_KEY_LEN,
> + dev_flow->hash_fields,
> + rss_desc->queue,
> + rss_desc->queue_num);
> + if (!*hrxq_idx) {
> + *hrxq_idx = mlx5_hrxq_new
> + (dev, rss_desc->key,
> + MLX5_RSS_HASH_KEY_LEN,
> + dev_flow->hash_fields,
> + rss_desc->queue,
> + rss_desc->queue_num,
> + !!(dh->layers &
> + MLX5_FLOW_LAYER_TUNNEL));
> + }
> + hrxq = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_HRXQ],
> + *hrxq_idx);
Why do you need this line? You can compare the hrxq_idx to check for error.
> + if (!hrxq) {
> + rte_flow_error_set
> + (error, rte_errno,
> + RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
> + "cannot get hash queue");
> + goto error;
> + }
> + dh->rix_hrxq = *hrxq_idx;
> + return hrxq;
> +error:
> + /* hrxq is union, don't clear it if the flag is not set. */
> + if (dh->rix_hrxq) {
> + mlx5_hrxq_release(dev, dh->rix_hrxq);
> + dh->rix_hrxq = 0;
> + }
> + return NULL;
> +}
> +
[snap...]
> -----Original Message-----
> From: Ori Kam <orika@mellanox.com>
> Sent: Wednesday, July 1, 2020 3:55 AM
> To: Jiawei(Jonny) Wang <jiaweiw@mellanox.com>; Slava Ovsiienko
> <viacheslavo@mellanox.com>; Matan Azrad <matan@mellanox.com>
> Cc: dev@dpdk.org; Thomas Monjalon <thomas@monjalon.net>; Raslan
> Darawsheh <rasland@mellanox.com>; ian.stokes@intel.com;
> fbl@redhat.com; Jiawei(Jonny) Wang <jiaweiw@mellanox.com>
> Subject: RE: [PATCH 6/8] net/mlx5: update translate function for sample
> action
>
> Hi Jiawei,
> PSB,
>
> Thanks,
> Ori
>
> > -----Original Message-----
> > From: Jiawei Wang <jiaweiw@mellanox.com>
> > Sent: Thursday, June 25, 2020 7:26 PM
> > Subject: [PATCH 6/8] net/mlx5: update translate function for sample
> > action
> >
> > Translate the attribute of sample action that include sample ratio and
> > sub actions list, then create the sample DR action.
> >
> > Signed-off-by: Jiawei Wang <jiaweiw@mellanox.com>
> > ---
> > drivers/net/mlx5/mlx5_flow.c | 16 +-
> > drivers/net/mlx5/mlx5_flow.h | 14 +-
> > drivers/net/mlx5/mlx5_flow_dv.c | 502
> > +++++++++++++++++++++++++++++++++++++++-
> > 3 files changed, 511 insertions(+), 21 deletions(-)
> >
> > diff --git a/drivers/net/mlx5/mlx5_flow.c
> > b/drivers/net/mlx5/mlx5_flow.c index 7c65a9a..73ef290 100644
> > --- a/drivers/net/mlx5/mlx5_flow.c
> > +++ b/drivers/net/mlx5/mlx5_flow.c
> > @@ -4569,10 +4569,14 @@ uint32_t mlx5_flow_adjust_priority(struct
> > rte_eth_dev *dev, int32_t priority,
> > int hairpin_flow;
> > uint32_t hairpin_id = 0;
> > struct rte_flow_attr attr_tx = { .priority = 0 };
> > + struct rte_flow_attr attr_factor = {0};
> > int ret;
> >
> > - hairpin_flow = flow_check_hairpin_split(dev, attr, actions);
> > - ret = flow_drv_validate(dev, attr, items, p_actions_rx,
> > + memcpy((void *)&attr_factor, (const void *)attr, sizeof(*attr));
> > + if (external)
> > + attr_factor.group *= MLX5_FLOW_TABLE_FACTOR;
> > + hairpin_flow = flow_check_hairpin_split(dev, &attr_factor, actions);
> > + ret = flow_drv_validate(dev, &attr_factor, items, p_actions_rx,
> > external, hairpin_flow, error);
> > if (ret < 0)
> > return 0;
> > @@ -4591,7 +4595,7 @@ uint32_t mlx5_flow_adjust_priority(struct
> > rte_eth_dev *dev, int32_t priority,
> > rte_errno = ENOMEM;
> > goto error_before_flow;
> > }
> > - flow->drv_type = flow_get_drv_type(dev, attr);
> > + flow->drv_type = flow_get_drv_type(dev, &attr_factor);
> > if (hairpin_id != 0)
> > flow->hairpin_flow_id = hairpin_id;
> > MLX5_ASSERT(flow->drv_type > MLX5_FLOW_TYPE_MIN && @@ -
> 4637,7
> > +4641,7 @@ uint32_t mlx5_flow_adjust_priority(struct rte_eth_dev *dev,
> > int32_t priority,
> > * depending on configuration. In the simplest
> > * case it just creates unmodified original flow.
> > */
> > - ret = flow_create_split_outer(dev, flow, attr,
> > + ret = flow_create_split_outer(dev, flow, &attr_factor,
> > buf->entry[i].pattern,
> > p_actions_rx, external, idx,
> > error);
> > @@ -4674,8 +4678,8 @@ uint32_t mlx5_flow_adjust_priority(struct
> > rte_eth_dev *dev, int32_t priority,
> > * the egress Flows belong to the different device and
> > * copy table should be updated in peer NIC Rx domain.
> > */
> > - if (attr->ingress &&
> > - (external || attr->group != MLX5_FLOW_MREG_CP_TABLE_GROUP))
> > {
> > + if (attr_factor.ingress &&
> > + (external || attr_factor.group !=
> > MLX5_FLOW_MREG_CP_TABLE_GROUP)) {
> > ret = flow_mreg_update_copy_table(dev, flow, actions,
> error);
> > if (ret)
> > goto error;
> > diff --git a/drivers/net/mlx5/mlx5_flow.h
> > b/drivers/net/mlx5/mlx5_flow.h index 941de5f..4163183 100644
> > --- a/drivers/net/mlx5/mlx5_flow.h
> > +++ b/drivers/net/mlx5/mlx5_flow.h
> > @@ -369,6 +369,13 @@ enum mlx5_flow_fate_type {
> > MLX5_FLOW_FATE_MAX,
> > };
> >
> > +/*
> > + * Max number of actions per DV flow.
> > + * See CREATE_FLOW_MAX_FLOW_ACTIONS_SUPPORTED
> > + * in rdma-core file providers/mlx5/verbs.c.
> > + */
> > +#define MLX5_DV_MAX_NUMBER_OF_ACTIONS 8
> > +
> > /* Matcher PRM representation */
> > struct mlx5_flow_dv_match_params {
> > size_t size;
> > @@ -599,13 +606,6 @@ struct mlx5_flow_handle { #define
> > MLX5_FLOW_HANDLE_VERBS_SIZE (sizeof(struct mlx5_flow_handle))
> #endif
> >
> > -/*
> > - * Max number of actions per DV flow.
> > - * See CREATE_FLOW_MAX_FLOW_ACTIONS_SUPPORTED
> > - * in rdma-core file providers/mlx5/verbs.c.
> > - */
> > -#define MLX5_DV_MAX_NUMBER_OF_ACTIONS 8
> > -
> > /** Device flow structure only for DV flow creation. */ struct
> > mlx5_flow_dv_workspace {
> > uint32_t group; /**< The group index. */ diff --git
> > a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c
> > index 710c0f3..62a4a3b 100644
> > --- a/drivers/net/mlx5/mlx5_flow_dv.c
> > +++ b/drivers/net/mlx5/mlx5_flow_dv.c
> > @@ -79,6 +79,10 @@
> > flow_dv_tbl_resource_release(struct rte_eth_dev *dev,
> > struct mlx5_flow_tbl_resource *tbl);
> >
> > +static int
> > +flow_dv_encap_decap_resource_release(struct rte_eth_dev *dev,
> > + uint32_t encap_decap_idx);
> > +
> > /**
> > * Initialize flow attributes structure according to flow items' types.
> > *
> > @@ -7897,6 +7901,385 @@ struct field_modify_info modify_tcp[] = { }
> >
> > /**
> > + * Create an Rx Hash queue.
> > + *
> > + * @param dev
> > + * Pointer to Ethernet device.
> > + * @param[in] dev_flow
> > + * Pointer to the mlx5_flow.
> > + * @param[in] rss_desc
> > + * Pointer to the mlx5_flow_rss_desc.
> > + * @param[in, out] hrxq_idx
>
> I think this is only used as out.
>
right, will change it.
> > + * Hash Rx queue index.
> > + * @param[out] error
> > + * Pointer to error structure.
> > + *
> > + * @return
> > + * The Verbs/DevX object initialised, NULL otherwise and rte_errno is set.
> > + */
> > +static struct mlx5_hrxq *
> > +flow_dv_handle_rx_queue(struct rte_eth_dev *dev,
> > + struct mlx5_flow *dev_flow,
> > + struct mlx5_flow_rss_desc *rss_desc,
> > + uint32_t *hrxq_idx,
> > + struct rte_flow_error *error)
> > +{
> > + struct mlx5_priv *priv = dev->data->dev_private;
> > + struct mlx5_flow_handle *dh = dev_flow->handle;
> > + struct mlx5_hrxq *hrxq;
> > +
> > + MLX5_ASSERT(rss_desc->queue_num);
> > + *hrxq_idx = mlx5_hrxq_get(dev, rss_desc->key,
> > + MLX5_RSS_HASH_KEY_LEN,
> > + dev_flow->hash_fields,
> > + rss_desc->queue,
> > + rss_desc->queue_num);
> > + if (!*hrxq_idx) {
> > + *hrxq_idx = mlx5_hrxq_new
> > + (dev, rss_desc->key,
> > + MLX5_RSS_HASH_KEY_LEN,
> > + dev_flow->hash_fields,
> > + rss_desc->queue,
> > + rss_desc->queue_num,
> > + !!(dh->layers &
> > + MLX5_FLOW_LAYER_TUNNEL));
> > + }
> > + hrxq = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_HRXQ],
> > + *hrxq_idx);
>
> Why do you need this line? You can compare the hrxq_idx to check for error.
>
Yes, we can check by *hrxq_idx==0 for error, or return corresponding hash rx queue object if no error.
Thanks.
> > + if (!hrxq) {
> > + rte_flow_error_set
> > + (error, rte_errno,
> > + RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
> > + "cannot get hash queue");
> > + goto error;
> > + }
> > + dh->rix_hrxq = *hrxq_idx;
> > + return hrxq;
> > +error:
> > + /* hrxq is union, don't clear it if the flag is not set. */
> > + if (dh->rix_hrxq) {
> > + mlx5_hrxq_release(dev, dh->rix_hrxq);
> > + dh->rix_hrxq = 0;
> > + }
> > + return NULL;
> > +}
> > +
>
>
> [snap...]
@@ -4569,10 +4569,14 @@ uint32_t mlx5_flow_adjust_priority(struct rte_eth_dev *dev, int32_t priority,
int hairpin_flow;
uint32_t hairpin_id = 0;
struct rte_flow_attr attr_tx = { .priority = 0 };
+ struct rte_flow_attr attr_factor = {0};
int ret;
- hairpin_flow = flow_check_hairpin_split(dev, attr, actions);
- ret = flow_drv_validate(dev, attr, items, p_actions_rx,
+ memcpy((void *)&attr_factor, (const void *)attr, sizeof(*attr));
+ if (external)
+ attr_factor.group *= MLX5_FLOW_TABLE_FACTOR;
+ hairpin_flow = flow_check_hairpin_split(dev, &attr_factor, actions);
+ ret = flow_drv_validate(dev, &attr_factor, items, p_actions_rx,
external, hairpin_flow, error);
if (ret < 0)
return 0;
@@ -4591,7 +4595,7 @@ uint32_t mlx5_flow_adjust_priority(struct rte_eth_dev *dev, int32_t priority,
rte_errno = ENOMEM;
goto error_before_flow;
}
- flow->drv_type = flow_get_drv_type(dev, attr);
+ flow->drv_type = flow_get_drv_type(dev, &attr_factor);
if (hairpin_id != 0)
flow->hairpin_flow_id = hairpin_id;
MLX5_ASSERT(flow->drv_type > MLX5_FLOW_TYPE_MIN &&
@@ -4637,7 +4641,7 @@ uint32_t mlx5_flow_adjust_priority(struct rte_eth_dev *dev, int32_t priority,
* depending on configuration. In the simplest
* case it just creates unmodified original flow.
*/
- ret = flow_create_split_outer(dev, flow, attr,
+ ret = flow_create_split_outer(dev, flow, &attr_factor,
buf->entry[i].pattern,
p_actions_rx, external, idx,
error);
@@ -4674,8 +4678,8 @@ uint32_t mlx5_flow_adjust_priority(struct rte_eth_dev *dev, int32_t priority,
* the egress Flows belong to the different device and
* copy table should be updated in peer NIC Rx domain.
*/
- if (attr->ingress &&
- (external || attr->group != MLX5_FLOW_MREG_CP_TABLE_GROUP)) {
+ if (attr_factor.ingress &&
+ (external || attr_factor.group != MLX5_FLOW_MREG_CP_TABLE_GROUP)) {
ret = flow_mreg_update_copy_table(dev, flow, actions, error);
if (ret)
goto error;
@@ -369,6 +369,13 @@ enum mlx5_flow_fate_type {
MLX5_FLOW_FATE_MAX,
};
+/*
+ * Max number of actions per DV flow.
+ * See CREATE_FLOW_MAX_FLOW_ACTIONS_SUPPORTED
+ * in rdma-core file providers/mlx5/verbs.c.
+ */
+#define MLX5_DV_MAX_NUMBER_OF_ACTIONS 8
+
/* Matcher PRM representation */
struct mlx5_flow_dv_match_params {
size_t size;
@@ -599,13 +606,6 @@ struct mlx5_flow_handle {
#define MLX5_FLOW_HANDLE_VERBS_SIZE (sizeof(struct mlx5_flow_handle))
#endif
-/*
- * Max number of actions per DV flow.
- * See CREATE_FLOW_MAX_FLOW_ACTIONS_SUPPORTED
- * in rdma-core file providers/mlx5/verbs.c.
- */
-#define MLX5_DV_MAX_NUMBER_OF_ACTIONS 8
-
/** Device flow structure only for DV flow creation. */
struct mlx5_flow_dv_workspace {
uint32_t group; /**< The group index. */
@@ -79,6 +79,10 @@
flow_dv_tbl_resource_release(struct rte_eth_dev *dev,
struct mlx5_flow_tbl_resource *tbl);
+static int
+flow_dv_encap_decap_resource_release(struct rte_eth_dev *dev,
+ uint32_t encap_decap_idx);
+
/**
* Initialize flow attributes structure according to flow items' types.
*
@@ -7897,6 +7901,385 @@ struct field_modify_info modify_tcp[] = {
}
/**
+ * Create an Rx Hash queue.
+ *
+ * @param dev
+ * Pointer to Ethernet device.
+ * @param[in] dev_flow
+ * Pointer to the mlx5_flow.
+ * @param[in] rss_desc
+ * Pointer to the mlx5_flow_rss_desc.
+ * @param[in, out] hrxq_idx
+ * Hash Rx queue index.
+ * @param[out] error
+ * Pointer to error structure.
+ *
+ * @return
+ * The Verbs/DevX object initialised, NULL otherwise and rte_errno is set.
+ */
+static struct mlx5_hrxq *
+flow_dv_handle_rx_queue(struct rte_eth_dev *dev,
+ struct mlx5_flow *dev_flow,
+ struct mlx5_flow_rss_desc *rss_desc,
+ uint32_t *hrxq_idx,
+ struct rte_flow_error *error)
+{
+ struct mlx5_priv *priv = dev->data->dev_private;
+ struct mlx5_flow_handle *dh = dev_flow->handle;
+ struct mlx5_hrxq *hrxq;
+
+ MLX5_ASSERT(rss_desc->queue_num);
+ *hrxq_idx = mlx5_hrxq_get(dev, rss_desc->key,
+ MLX5_RSS_HASH_KEY_LEN,
+ dev_flow->hash_fields,
+ rss_desc->queue,
+ rss_desc->queue_num);
+ if (!*hrxq_idx) {
+ *hrxq_idx = mlx5_hrxq_new
+ (dev, rss_desc->key,
+ MLX5_RSS_HASH_KEY_LEN,
+ dev_flow->hash_fields,
+ rss_desc->queue,
+ rss_desc->queue_num,
+ !!(dh->layers &
+ MLX5_FLOW_LAYER_TUNNEL));
+ }
+ hrxq = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_HRXQ],
+ *hrxq_idx);
+ if (!hrxq) {
+ rte_flow_error_set
+ (error, rte_errno,
+ RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+ "cannot get hash queue");
+ goto error;
+ }
+ dh->rix_hrxq = *hrxq_idx;
+ return hrxq;
+error:
+ /* hrxq is union, don't clear it if the flag is not set. */
+ if (dh->rix_hrxq) {
+ mlx5_hrxq_release(dev, dh->rix_hrxq);
+ dh->rix_hrxq = 0;
+ }
+ return NULL;
+}
+
+/**
+ * Find existing sample resource or create and register a new one.
+ *
+ * @param[in, out] dev
+ * Pointer to rte_eth_dev structure.
+ * @param[in] attr
+ * Attributes of flow that includes this item.
+ * @param[in] resource
+ * Pointer to sample resource.
+ * @parm[in, out] dev_flow
+ * Pointer to the dev_flow.
+ * @param[in, out] sample_dv_actions
+ * Pointer to sample actions list.
+ * @param[out] error
+ * pointer to error structure.
+ *
+ * @return
+ * 0 on success otherwise -errno and errno is set.
+ */
+static int
+flow_dv_sample_resource_register(struct rte_eth_dev *dev,
+ const struct rte_flow_attr *attr,
+ struct mlx5_flow_dv_sample_resource *resource,
+ struct mlx5_flow *dev_flow,
+ void **sample_dv_actions,
+ struct rte_flow_error *error)
+{
+ struct mlx5_flow_dv_sample_resource *cache_resource;
+ struct mlx5dv_dr_flow_sampler_attr sampler_attr;
+ struct mlx5_priv *priv = dev->data->dev_private;
+ struct mlx5_dev_ctx_shared *sh = priv->sh;
+ struct mlx5_flow_tbl_resource *tbl;
+ uint32_t idx = 0;
+ const uint32_t next_ft_step = 1;
+ uint32_t next_ft_id = resource->ft_id + next_ft_step;
+
+ /* Lookup a matching resource from cache. */
+ ILIST_FOREACH(sh->ipool[MLX5_IPOOL_SAMPLE], sh->sample_action_list,
+ idx, cache_resource, next) {
+ if (resource->ratio == cache_resource->ratio &&
+ resource->ft_type == cache_resource->ft_type &&
+ resource->ft_id == cache_resource->ft_id &&
+ !memcmp((void *)&resource->sample_act,
+ (void *)&cache_resource->sample_act,
+ sizeof(struct mlx5_flow_sub_actions_list))) {
+ DRV_LOG(DEBUG, "sample resource %p: refcnt %d++",
+ (void *)cache_resource,
+ rte_atomic32_read(&cache_resource->refcnt));
+ rte_atomic32_inc(&cache_resource->refcnt);
+ dev_flow->handle->dvh.rix_sample = idx;
+ dev_flow->dv.sample_res = cache_resource;
+ return 0;
+ }
+ }
+ /* Register new sample resource. */
+ cache_resource = mlx5_ipool_zmalloc(sh->ipool[MLX5_IPOOL_SAMPLE],
+ &dev_flow->handle->dvh.rix_sample);
+ if (!cache_resource)
+ return rte_flow_error_set(error, ENOMEM,
+ RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+ NULL,
+ "cannot allocate resource memory");
+ *cache_resource = *resource;
+ /* Create normal path table level */
+ tbl = flow_dv_tbl_resource_get(dev, next_ft_id,
+ attr->egress, attr->transfer, error);
+ if (!tbl) {
+ rte_flow_error_set(error, ENOMEM,
+ RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+ NULL,
+ "fail to create normal path table "
+ "for sample");
+ goto error;
+ }
+ cache_resource->normal_path_tbl = tbl;
+ if (resource->ft_type == MLX5DV_FLOW_TABLE_TYPE_FDB) {
+ cache_resource->default_miss =
+ mlx5_glue->dr_create_flow_action_default_miss();
+ if (!cache_resource->default_miss) {
+ rte_flow_error_set(error, ENOMEM,
+ RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+ NULL,
+ "cannot create default miss "
+ "action");
+ goto error;
+ }
+ sample_dv_actions[resource->sample_act.actions_num++] =
+ cache_resource->default_miss;
+ }
+ /* Create a DR sample action */
+ sampler_attr.sample_ratio = cache_resource->ratio;
+ sampler_attr.default_next_table = tbl->obj;
+ sampler_attr.num_sample_actions = resource->sample_act.actions_num;
+ sampler_attr.sample_actions = (struct mlx5dv_dr_action **)
+ &sample_dv_actions[0];
+ cache_resource->verbs_action =
+ mlx5_glue->dr_create_flow_action_sampler(&sampler_attr);
+ if (!cache_resource->verbs_action) {
+ rte_flow_error_set(error, ENOMEM,
+ RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+ NULL, "cannot create sample action");
+ goto error;
+ }
+ rte_atomic32_init(&cache_resource->refcnt);
+ rte_atomic32_inc(&cache_resource->refcnt);
+ ILIST_INSERT(sh->ipool[MLX5_IPOOL_SAMPLE], &sh->sample_action_list,
+ dev_flow->handle->dvh.rix_sample, cache_resource,
+ next);
+ dev_flow->dv.sample_res = cache_resource;
+ DRV_LOG(DEBUG, "new sample resource %p: refcnt %d++",
+ (void *)cache_resource,
+ rte_atomic32_read(&cache_resource->refcnt));
+ return 0;
+error:
+ if (cache_resource->ft_type == MLX5DV_FLOW_TABLE_TYPE_FDB) {
+ if (cache_resource->default_miss)
+ claim_zero(mlx5_glue->destroy_flow_action
+ (cache_resource->default_miss));
+ } else {
+ if (cache_resource->sample_idx.rix_hrxq &&
+ !mlx5_hrxq_release(dev,
+ cache_resource->sample_idx.rix_hrxq))
+ cache_resource->sample_idx.rix_hrxq = 0;
+ if (cache_resource->sample_idx.rix_tag &&
+ !flow_dv_tag_release(dev,
+ cache_resource->sample_idx.rix_tag))
+ cache_resource->sample_idx.rix_tag = 0;
+ if (cache_resource->sample_idx.cnt) {
+ flow_dv_counter_release(dev,
+ cache_resource->sample_idx.cnt);
+ cache_resource->sample_idx.cnt = 0;
+ }
+ }
+ if (cache_resource->normal_path_tbl)
+ flow_dv_tbl_resource_release(dev,
+ cache_resource->normal_path_tbl);
+ mlx5_ipool_free(sh->ipool[MLX5_IPOOL_SAMPLE],
+ dev_flow->handle->dvh.rix_sample);
+ dev_flow->handle->dvh.rix_sample = 0;
+ return -rte_errno;
+}
+
+/**
+ * Convert Sample action to DV specification.
+ *
+ * @param[in] dev
+ * Pointer to rte_eth_dev structure.
+ * @param[in] action
+ * Pointer to action structure.
+ * @param[in, out] dev_flow
+ * Pointer to the mlx5_flow.
+ * @param[in] attr
+ * Pointer to the flow attributes.
+ * @param[in, out] sample_actions
+ * Pointer to sample actions list.
+ * @param[in, out] res
+ * Pointer to sample resource.
+ * @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_translate_action_sample(struct rte_eth_dev *dev,
+ const struct rte_flow_action *action,
+ struct mlx5_flow *dev_flow,
+ const struct rte_flow_attr *attr,
+ void **sample_actions,
+ struct mlx5_flow_dv_sample_resource *res,
+ struct rte_flow_error *error)
+{
+ struct mlx5_priv *priv = dev->data->dev_private;
+ const struct rte_flow_action_sample *sample_action;
+ const struct rte_flow_action *sub_actions;
+ const struct rte_flow_action_queue *queue;
+ struct mlx5_flow_sub_actions_list *sample_act;
+ struct mlx5_flow_sub_actions_idx *sample_idx;
+ struct mlx5_flow_rss_desc *rss_desc = &((struct mlx5_flow_rss_desc *)
+ priv->rss_desc)
+ [!!priv->flow_nested_idx];
+ uint64_t action_flags = 0;
+
+ sample_act = &res->sample_act;
+ sample_idx = &res->sample_idx;
+ sample_action = (const struct rte_flow_action_sample *)action->conf;
+ res->ratio = sample_action->ratio;
+ sub_actions = sample_action->actions;
+ for (; sub_actions->type != RTE_FLOW_ACTION_TYPE_END; sub_actions++) {
+ int type = sub_actions->type;
+ uint32_t pre_rix = 0;
+ void *pre_r;
+ switch (type) {
+ case RTE_FLOW_ACTION_TYPE_QUEUE:
+ {
+ struct mlx5_hrxq *hrxq;
+ uint32_t hrxq_idx;
+
+ queue = sub_actions->conf;
+ rss_desc->queue_num = 1;
+ rss_desc->queue[0] = queue->index;
+ hrxq = flow_dv_handle_rx_queue(dev, dev_flow,
+ rss_desc, &hrxq_idx,
+ error);
+ if (!hrxq)
+ return rte_flow_error_set
+ (error, rte_errno,
+ RTE_FLOW_ERROR_TYPE_ACTION,
+ NULL,
+ "cannot create fate queue");
+ sample_act->dr_queue_action = hrxq->action;
+ sample_idx->rix_hrxq = hrxq_idx;
+ sample_actions[sample_act->actions_num++] =
+ hrxq->action;
+ action_flags |= MLX5_FLOW_ACTION_QUEUE;
+ break;
+ }
+ case RTE_FLOW_ACTION_TYPE_MARK:
+ {
+ uint32_t tag_be = mlx5_flow_mark_set
+ (((const struct rte_flow_action_mark *)
+ (sub_actions->conf))->id);
+ pre_rix = dev_flow->handle->dvh.rix_tag;
+ /* Save the mark resource before sample */
+ pre_r = dev_flow->dv.tag_resource;
+ if (flow_dv_tag_resource_register(dev, tag_be,
+ dev_flow, error))
+ return -rte_errno;
+ MLX5_ASSERT(dev_flow->dv.tag_resource);
+ sample_act->dr_tag_action =
+ dev_flow->dv.tag_resource->action;
+ sample_idx->rix_tag =
+ dev_flow->handle->dvh.rix_tag;
+ sample_actions[sample_act->actions_num++] =
+ sample_act->dr_tag_action;
+ /* Recover the mark resource after sample */
+ dev_flow->dv.tag_resource = pre_r;
+ dev_flow->handle->dvh.rix_tag = pre_rix;
+ action_flags |= MLX5_FLOW_ACTION_MARK;
+ break;
+ }
+ case RTE_FLOW_ACTION_TYPE_COUNT:
+ {
+ uint32_t counter;
+
+ counter = flow_dv_translate_create_counter(dev,
+ dev_flow, sub_actions->conf, 0);
+ if (!counter)
+ return rte_flow_error_set
+ (error, rte_errno,
+ RTE_FLOW_ERROR_TYPE_ACTION,
+ NULL,
+ "cannot create counter"
+ " object.");
+ sample_idx->cnt = counter;
+ sample_act->dr_cnt_action =
+ (flow_dv_counter_get_by_idx(dev,
+ counter, NULL))->action;
+ sample_actions[sample_act->actions_num++] =
+ sample_act->dr_cnt_action;
+ action_flags |= MLX5_FLOW_ACTION_COUNT;
+ break;
+ }
+ default:
+ return rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+ NULL,
+ "Not suppport for sampler action");
+ }
+ }
+ sample_act->action_flags = action_flags;
+ res->ft_id = dev_flow->dv.group;
+ if (attr->transfer)
+ res->ft_type = MLX5DV_FLOW_TABLE_TYPE_FDB;
+ else if (attr->ingress)
+ res->ft_type = MLX5DV_FLOW_TABLE_TYPE_NIC_RX;
+
+ return 0;
+}
+
+/**
+ * Convert Sample action to DV specification.
+ *
+ * @param[in] dev
+ * Pointer to rte_eth_dev structure.
+ * @param[in, out] dev_flow
+ * Pointer to the mlx5_flow.
+ * @param[in] attr
+ * Pointer to the flow attributes.
+ * @param[in, out] res
+ * Pointer to sample resource.
+ * @param[in] sample_actions
+ * Pointer to sample path actions list.
+ * @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_create_action_sample(struct rte_eth_dev *dev,
+ struct mlx5_flow *dev_flow,
+ const struct rte_flow_attr *attr,
+ struct mlx5_flow_dv_sample_resource *res,
+ void **sample_actions,
+ struct rte_flow_error *error)
+{
+ if (flow_dv_sample_resource_register(dev, attr, res, dev_flow,
+ sample_actions, error))
+ return rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ACTION,
+ NULL, "can't create sample action");
+ return 0;
+}
+
+/**
* Fill the flow with DV spec, lock free
* (mutex should be acquired by caller).
*
@@ -7959,9 +8342,13 @@ struct field_modify_info modify_tcp[] = {
void *match_value = dev_flow->dv.value.buf;
uint8_t next_protocol = 0xff;
struct rte_vlan_hdr vlan = { 0 };
+ struct mlx5_flow_dv_sample_resource sample_res;
+ void *sample_actions[MLX5_DV_MAX_NUMBER_OF_ACTIONS] = {0};
+ uint32_t sample_act_pos = UINT32_MAX;
uint32_t table;
int ret = 0;
+ memset(&sample_res, 0, sizeof(struct mlx5_flow_dv_sample_resource));
mhdr_res->ft_type = attr->egress ? MLX5DV_FLOW_TABLE_TYPE_NIC_TX :
MLX5DV_FLOW_TABLE_TYPE_NIC_RX;
ret = mlx5_flow_group_to_table(attr, dev_flow->external, attr->group,
@@ -7980,7 +8367,6 @@ struct field_modify_info modify_tcp[] = {
const struct rte_flow_action_rss *rss;
const struct rte_flow_action *action = actions;
const uint8_t *rss_key;
- const struct rte_flow_action_jump *jump_data;
const struct rte_flow_action_meter *mtr;
struct mlx5_flow_tbl_resource *tbl;
uint32_t port_id = 0;
@@ -7988,6 +8374,7 @@ struct field_modify_info modify_tcp[] = {
int action_type = actions->type;
const struct rte_flow_action *found_action = NULL;
struct mlx5_flow_meter *fm = NULL;
+ uint32_t jump_group = 0;
switch (action_type) {
case RTE_FLOW_ACTION_TYPE_VOID:
@@ -8221,9 +8608,12 @@ struct field_modify_info modify_tcp[] = {
action_flags |= MLX5_FLOW_ACTION_DECAP;
break;
case RTE_FLOW_ACTION_TYPE_JUMP:
- jump_data = action->conf;
+ jump_group = ((const struct rte_flow_action_jump *)
+ action->conf)->group;
+ if (dev_flow->external)
+ jump_group *= MLX5_FLOW_TABLE_FACTOR;
ret = mlx5_flow_group_to_table(attr, dev_flow->external,
- jump_data->group,
+ jump_group,
!!priv->fdb_def_rule,
&table, error);
if (ret)
@@ -8384,6 +8774,19 @@ struct field_modify_info modify_tcp[] = {
return -rte_errno;
action_flags |= MLX5_FLOW_ACTION_SET_IPV6_DSCP;
break;
+ case RTE_FLOW_ACTION_TYPE_SAMPLE:
+ sample_act_pos = actions_n;
+ ret = flow_dv_translate_action_sample(dev,
+ actions,
+ dev_flow, attr,
+ sample_actions,
+ &sample_res,
+ error);
+ if (ret < 0)
+ return ret;
+ actions_n++;
+ action_flags |= MLX5_FLOW_ACTION_SAMPLE;
+ break;
case RTE_FLOW_ACTION_TYPE_END:
actions_end = true;
if (mhdr_res->actions_num) {
@@ -8410,6 +8813,21 @@ struct field_modify_info modify_tcp[] = {
(flow_dv_counter_get_by_idx(dev,
flow->counter, NULL))->action;
}
+ if (action_flags & MLX5_FLOW_ACTION_SAMPLE) {
+ ret = flow_dv_create_action_sample(dev,
+ dev_flow, attr,
+ &sample_res,
+ sample_actions,
+ error);
+ if (ret < 0)
+ return rte_flow_error_set
+ (error, rte_errno,
+ RTE_FLOW_ERROR_TYPE_ACTION,
+ NULL,
+ "cannot create sample action");
+ dev_flow->dv.actions[sample_act_pos] =
+ dev_flow->dv.sample_res->verbs_action;
+ }
break;
default:
break;
@@ -8819,18 +9237,18 @@ struct field_modify_info modify_tcp[] = {
*
* @param dev
* Pointer to Ethernet device.
- * @param handle
- * Pointer to mlx5_flow_handle.
+ * @param encap_decap_idx
+ * Index of encap decap resource.
*
* @return
* 1 while a reference on it exists, 0 when freed.
*/
static int
flow_dv_encap_decap_resource_release(struct rte_eth_dev *dev,
- struct mlx5_flow_handle *handle)
+ uint32_t encap_decap_idx)
{
struct mlx5_priv *priv = dev->data->dev_private;
- uint32_t idx = handle->dvh.rix_encap_decap;
+ uint32_t idx = encap_decap_idx;
struct mlx5_flow_dv_encap_decap_resource *cache_resource;
cache_resource = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_DECAP_ENCAP],
@@ -9036,6 +9454,71 @@ struct field_modify_info modify_tcp[] = {
}
/**
+ * Release an encap/decap resource.
+ *
+ * @param dev
+ * Pointer to Ethernet device.
+ * @param handle
+ * Pointer to mlx5_flow_handle.
+ *
+ * @return
+ * 1 while a reference on it exists, 0 when freed.
+ */
+static int
+flow_dv_sample_resource_release(struct rte_eth_dev *dev,
+ struct mlx5_flow_handle *handle)
+{
+ struct mlx5_priv *priv = dev->data->dev_private;
+ uint32_t idx = handle->dvh.rix_sample;
+ struct mlx5_flow_dv_sample_resource *cache_resource;
+
+ cache_resource = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_SAMPLE],
+ idx);
+ if (!cache_resource)
+ return 0;
+ MLX5_ASSERT(cache_resource->verbs_action);
+ DRV_LOG(DEBUG, "sample resource %p: refcnt %d--",
+ (void *)cache_resource,
+ rte_atomic32_read(&cache_resource->refcnt));
+ if (rte_atomic32_dec_and_test(&cache_resource->refcnt)) {
+ if (cache_resource->verbs_action)
+ claim_zero(mlx5_glue->destroy_flow_action
+ (cache_resource->verbs_action));
+ if (cache_resource->ft_type == MLX5DV_FLOW_TABLE_TYPE_FDB) {
+ if (cache_resource->default_miss)
+ claim_zero(mlx5_glue->destroy_flow_action
+ (cache_resource->default_miss));
+ }
+ if (cache_resource->normal_path_tbl)
+ flow_dv_tbl_resource_release(dev,
+ cache_resource->normal_path_tbl);
+ }
+ if (cache_resource->sample_idx.rix_hrxq &&
+ !mlx5_hrxq_release(dev,
+ cache_resource->sample_idx.rix_hrxq))
+ cache_resource->sample_idx.rix_hrxq = 0;
+ if (cache_resource->sample_idx.rix_tag &&
+ !flow_dv_tag_release(dev,
+ cache_resource->sample_idx.rix_tag))
+ cache_resource->sample_idx.rix_tag = 0;
+ if (cache_resource->sample_idx.cnt) {
+ flow_dv_counter_release(dev,
+ cache_resource->sample_idx.cnt);
+ cache_resource->sample_idx.cnt = 0;
+ }
+ if (!rte_atomic32_read(&cache_resource->refcnt)) {
+ ILIST_REMOVE(priv->sh->ipool[MLX5_IPOOL_SAMPLE],
+ &priv->sh->sample_action_list, idx,
+ cache_resource, next);
+ mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_SAMPLE], idx);
+ DRV_LOG(DEBUG, "sample resource %p: removed",
+ (void *)cache_resource);
+ return 0;
+ }
+ return 1;
+}
+
+/**
* Remove the flow from the NIC but keeps it in memory.
* Lock free, (mutex should be acquired by caller).
*
@@ -9113,8 +9596,11 @@ struct field_modify_info modify_tcp[] = {
flow->dev_handles = dev_handle->next.next;
if (dev_handle->dvh.matcher)
flow_dv_matcher_release(dev, dev_handle);
+ if (dev_handle->dvh.rix_sample)
+ flow_dv_sample_resource_release(dev, dev_handle);
if (dev_handle->dvh.rix_encap_decap)
- flow_dv_encap_decap_resource_release(dev, dev_handle);
+ flow_dv_encap_decap_resource_release(dev,
+ dev_handle->dvh.rix_encap_decap);
if (dev_handle->dvh.modify_hdr)
flow_dv_modify_hdr_resource_release(dev_handle);
if (dev_handle->dvh.rix_push_vlan)