#include "mlx5_prm.h"
#include "mlx5_glue.h"
#include "mlx5_flow.h"
-
#ifdef HAVE_IBV_FLOW_DV_SUPPORT
#ifndef HAVE_IBV_FLOW_DEVX_COUNTERS
.id = id,
.dcs = dcs,
};
+ tmpl.action = mlx5_glue->dv_create_flow_action_counter(dcs->obj, 0);
+ if (!tmpl.action) {
+ ret = errno;
+ goto error_exit;
+ }
*cnt = tmpl;
LIST_INSERT_HEAD(&priv->flow_counters, cnt, next);
return cnt;
MLX5_SET(fte_match_set_misc, misc_v, source_port, port);
}
+/**
+ * Find existing tag resource or create and register a new one.
+ *
+ * @param dev[in, out]
+ * Pointer to rte_eth_dev structure.
+ * @param[in, out] resource
+ * Pointer to tag resource.
+ * @parm[in, out] dev_flow
+ * Pointer to the dev_flow.
+ * @param[out] error
+ * pointer to error structure.
+ *
+ * @return
+ * 0 on success otherwise -errno and errno is set.
+ */
+static int
+flow_dv_tag_resource_register
+ (struct rte_eth_dev *dev,
+ struct mlx5_flow_dv_tag_resource *resource,
+ struct mlx5_flow *dev_flow,
+ struct rte_flow_error *error)
+{
+ struct mlx5_priv *priv = dev->data->dev_private;
+ struct mlx5_flow_dv_tag_resource *cache_resource;
+
+ /* Lookup a matching resource from cache. */
+ LIST_FOREACH(cache_resource, &priv->tags, next) {
+ if (resource->tag == cache_resource->tag) {
+ DRV_LOG(DEBUG, "tag resource %p: refcnt %d++",
+ (void *)cache_resource,
+ rte_atomic32_read(&cache_resource->refcnt));
+ rte_atomic32_inc(&cache_resource->refcnt);
+ dev_flow->flow->tag_resource = cache_resource;
+ return 0;
+ }
+ }
+ /* Register new resource. */
+ cache_resource = rte_calloc(__func__, 1, sizeof(*cache_resource), 0);
+ if (!cache_resource)
+ return rte_flow_error_set(error, ENOMEM,
+ RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+ "cannot allocate resource memory");
+ *cache_resource = *resource;
+ cache_resource->action = mlx5_glue->dv_create_flow_action_tag
+ (resource->tag);
+ if (!cache_resource->action) {
+ rte_free(cache_resource);
+ return rte_flow_error_set(error, ENOMEM,
+ RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+ NULL, "cannot create action");
+ }
+ rte_atomic32_init(&cache_resource->refcnt);
+ rte_atomic32_inc(&cache_resource->refcnt);
+ LIST_INSERT_HEAD(&priv->tags, cache_resource, next);
+ dev_flow->flow->tag_resource = cache_resource;
+ DRV_LOG(DEBUG, "new tag resource %p: refcnt %d++",
+ (void *)cache_resource,
+ rte_atomic32_read(&cache_resource->refcnt));
+ return 0;
+}
+
+/**
+ * Release the tag.
+ *
+ * @param dev
+ * Pointer to Ethernet device.
+ * @param flow
+ * Pointer to mlx5_flow.
+ *
+ * @return
+ * 1 while a reference on it exists, 0 when freed.
+ */
+static int
+flow_dv_tag_release(struct rte_eth_dev *dev,
+ struct mlx5_flow_dv_tag_resource *tag)
+{
+ assert(tag);
+ DRV_LOG(DEBUG, "port %u tag %p: refcnt %d--",
+ dev->data->port_id, (void *)tag,
+ rte_atomic32_read(&tag->refcnt));
+ if (rte_atomic32_dec_and_test(&tag->refcnt)) {
+ claim_zero(mlx5_glue->destroy_flow_action(tag->action));
+ LIST_REMOVE(tag, next);
+ DRV_LOG(DEBUG, "port %u tag %p: removed",
+ dev->data->port_id, (void *)tag);
+ rte_free(tag);
+ return 0;
+ }
+ return 1;
+}
+
/**
* Fill the flow with DV spec.
*
MLX5DV_FLOW_TABLE_TYPE_NIC_RX
};
union flow_dv_attr flow_attr = { .attr = 0 };
+ struct mlx5_flow_dv_tag_resource tag_resource;
if (priority == MLX5_FLOW_PRIO_RSVD)
priority = priv->config.flow_prio - 1;
case RTE_FLOW_ACTION_TYPE_VOID:
break;
case RTE_FLOW_ACTION_TYPE_FLAG:
- dev_flow->dv.actions[actions_n].type =
- MLX5DV_FLOW_ACTION_TAG;
- dev_flow->dv.actions[actions_n].tag_value =
+ tag_resource.tag =
mlx5_flow_mark_set(MLX5_FLOW_MARK_DEFAULT);
- actions_n++;
+ if (!flow->tag_resource)
+ if (flow_dv_tag_resource_register
+ (dev, &tag_resource, dev_flow, error))
+ return errno;
+ dev_flow->dv.actions[actions_n++] =
+ flow->tag_resource->action;
action_flags |= MLX5_FLOW_ACTION_FLAG;
break;
case RTE_FLOW_ACTION_TYPE_MARK:
- dev_flow->dv.actions[actions_n].type =
- MLX5DV_FLOW_ACTION_TAG;
- dev_flow->dv.actions[actions_n].tag_value =
- mlx5_flow_mark_set
- (((const struct rte_flow_action_mark *)
- (actions->conf))->id);
- actions_n++;
+ tag_resource.tag = mlx5_flow_mark_set
+ (((const struct rte_flow_action_mark *)
+ (actions->conf))->id);
+ if (!flow->tag_resource)
+ if (flow_dv_tag_resource_register
+ (dev, &tag_resource, dev_flow, error))
+ return errno;
+ dev_flow->dv.actions[actions_n++] =
+ flow->tag_resource->action;
action_flags |= MLX5_FLOW_ACTION_MARK;
break;
case RTE_FLOW_ACTION_TYPE_DROP:
- dev_flow->dv.actions[actions_n].type =
- MLX5DV_FLOW_ACTION_DROP;
action_flags |= MLX5_FLOW_ACTION_DROP;
break;
case RTE_FLOW_ACTION_TYPE_QUEUE:
rte_errno = ENOTSUP;
goto cnt_err;
}
- flow->counter =
- flow_dv_counter_new(dev,
- count->shared, count->id);
+ flow->counter = flow_dv_counter_new(dev, count->shared,
+ count->id);
if (flow->counter == NULL)
goto cnt_err;
- dev_flow->dv.actions[actions_n].type =
- MLX5DV_FLOW_ACTION_COUNTERS_DEVX;
- dev_flow->dv.actions[actions_n].obj =
- flow->counter->dcs->obj;
+ dev_flow->dv.actions[actions_n++] =
+ flow->counter->action;
action_flags |= MLX5_FLOW_ACTION_COUNT;
- ++actions_n;
break;
cnt_err:
if (rte_errno == ENOTSUP)
if (flow_dv_create_action_l2_encap(dev, actions,
dev_flow, error))
return -rte_errno;
- dev_flow->dv.actions[actions_n].type =
- MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION;
- dev_flow->dv.actions[actions_n].action =
+ dev_flow->dv.actions[actions_n++] =
dev_flow->dv.encap_decap->verbs_action;
- actions_n++;
action_flags |= actions->type ==
RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP ?
MLX5_FLOW_ACTION_VXLAN_ENCAP :
if (flow_dv_create_action_l2_decap(dev, dev_flow,
error))
return -rte_errno;
- dev_flow->dv.actions[actions_n].type =
- MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION;
- dev_flow->dv.actions[actions_n].action =
+ dev_flow->dv.actions[actions_n++] =
dev_flow->dv.encap_decap->verbs_action;
- actions_n++;
action_flags |= actions->type ==
RTE_FLOW_ACTION_TYPE_VXLAN_DECAP ?
MLX5_FLOW_ACTION_VXLAN_DECAP :
if (flow_dv_create_action_raw_encap
(dev, actions, dev_flow, attr, error))
return -rte_errno;
- dev_flow->dv.actions[actions_n].type =
- MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION;
- dev_flow->dv.actions[actions_n].action =
+ dev_flow->dv.actions[actions_n++] =
dev_flow->dv.encap_decap->verbs_action;
} else {
/* Handle encap without preceding decap. */
dev_flow,
error))
return -rte_errno;
- dev_flow->dv.actions[actions_n].type =
- MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION;
- dev_flow->dv.actions[actions_n].action =
+ dev_flow->dv.actions[actions_n++] =
dev_flow->dv.encap_decap->verbs_action;
}
- actions_n++;
action_flags |= MLX5_FLOW_ACTION_RAW_ENCAP;
break;
case RTE_FLOW_ACTION_TYPE_RAW_DECAP:
dev_flow,
error))
return -rte_errno;
- dev_flow->dv.actions[actions_n].type =
- MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION;
- dev_flow->dv.actions[actions_n].action =
+ dev_flow->dv.actions[actions_n++] =
dev_flow->dv.encap_decap->verbs_action;
- actions_n++;
}
/* If decap is followed by encap, handle it at encap. */
action_flags |= MLX5_FLOW_ACTION_RAW_DECAP;
dev_flow,
error))
return -rte_errno;
- dev_flow->dv.actions[actions_n].type =
- MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION;
- dev_flow->dv.actions[actions_n].action =
+ dev_flow->dv.actions[actions_n++] =
dev_flow->dv.modify_hdr->verbs_action;
- actions_n++;
}
break;
default:
"cannot get drop hash queue");
goto error;
}
- dv->actions[n].type = MLX5DV_FLOW_ACTION_DEST_IBV_QP;
- dv->actions[n].qp = dv->hrxq->qp;
- n++;
+ dv->actions[n++] =
+ mlx5_glue->dv_create_flow_action_dest_ibv_qp
+ (dv->hrxq->qp);
} else if (flow->actions &
(MLX5_FLOW_ACTION_QUEUE | MLX5_FLOW_ACTION_RSS)) {
struct mlx5_hrxq *hrxq;
goto error;
}
dv->hrxq = hrxq;
- dv->actions[n].type = MLX5DV_FLOW_ACTION_DEST_IBV_QP;
- dv->actions[n].qp = hrxq->qp;
- n++;
+ dv->actions[n++] =
+ mlx5_glue->dv_create_flow_action_dest_ibv_qp
+ (dv->hrxq->qp);
}
dv->flow =
mlx5_glue->dv_create_flow(dv->matcher->matcher_object,
flow_dv_counter_release(flow->counter);
flow->counter = NULL;
}
+ if (flow->tag_resource) {
+ flow_dv_tag_release(dev, flow->tag_resource);
+ flow->tag_resource = NULL;
+ }
while (!LIST_EMPTY(&flow->dev_flows)) {
dev_flow = LIST_FIRST(&flow->dev_flows);
LIST_REMOVE(dev_flow, next);
}
static int
-mlx5_glue_destroy_flow_action(struct ibv_flow_action *action)
+mlx5_glue_destroy_flow_action(void *action)
{
#ifdef HAVE_IBV_FLOW_DV_SUPPORT
- return ibv_destroy_flow_action(action);
+ struct mlx5dv_flow_action_attr *attr = action;
+ int res = 0;
+ switch (attr->type) {
+ case MLX5DV_FLOW_ACTION_TAG:
+ break;
+ default:
+ res = ibv_destroy_flow_action(attr->action);
+ break;
+ }
+ free(action);
+ return res;
#else
(void)action;
return ENOTSUP;
mlx5_glue_dv_create_flow(struct mlx5dv_flow_matcher *matcher,
struct mlx5dv_flow_match_parameters *match_value,
size_t num_actions,
- struct mlx5dv_flow_action_attr *actions_attr)
+ void *actions[])
{
#ifdef HAVE_IBV_FLOW_DV_SUPPORT
+ struct mlx5dv_flow_action_attr actions_attr[8];
+
+ if (num_actions > 8)
+ return NULL;
+ for (size_t i = 0; i < num_actions; i++)
+ actions_attr[i] =
+ *((struct mlx5dv_flow_action_attr *)(actions[i]));
return mlx5dv_create_flow(matcher, match_value,
num_actions, actions_attr);
#else
(void)matcher;
(void)match_value;
(void)num_actions;
- (void)actions_attr;
+ (void)actions;
return NULL;
#endif
}
#endif
}
-static struct ibv_flow_action *
-mlx5_glue_dv_create_flow_action_packet_reformat
- (struct ibv_context *ctx,
- size_t data_sz,
- void *data,
- enum mlx5dv_flow_action_packet_reformat_type reformat_type,
- enum mlx5dv_flow_table_type ft_type)
+static void *
+mlx5_glue_dv_create_flow_action_counter(void *counter_obj, uint32_t offset)
{
#ifdef HAVE_IBV_FLOW_DV_SUPPORT
- return mlx5dv_create_flow_action_packet_reformat(ctx,
- data_sz,
- data,
- reformat_type,
- ft_type);
+ struct mlx5dv_flow_action_attr *action;
+
+ (void)offset;
+ action = malloc(sizeof(*action));
+ if (!action)
+ return NULL;
+ action->type = MLX5DV_FLOW_ACTION_COUNTERS_DEVX;
+ action->obj = counter_obj;
+ return action;
#else
- (void)ctx;
- (void)data_sz;
- (void)data;
- (void)reformat_type;
- (void)ft_type;
+ (void)counter_obj;
+ (void)offset;
return NULL;
#endif
}
-static struct ibv_flow_action *
+static void *
+mlx5_glue_dv_create_flow_action_dest_ibv_qp(void *qp)
+{
+#ifdef HAVE_IBV_FLOW_DV_SUPPORT
+ struct mlx5dv_flow_action_attr *action;
+
+ action = malloc(sizeof(*action));
+ if (!action)
+ return NULL;
+ action->type = MLX5DV_FLOW_ACTION_DEST_IBV_QP;
+ action->obj = qp;
+ return action;
+#else
+ (void)qp;
+ return NULL;
+#endif
+}
+
+static void *
mlx5_glue_dv_create_flow_action_modify_header
(struct ibv_context *ctx,
size_t actions_sz,
enum mlx5dv_flow_table_type ft_type)
{
#ifdef HAVE_IBV_FLOW_DV_SUPPORT
- return mlx5dv_create_flow_action_modify_header(ctx, actions_sz,
- actions, ft_type);
+ struct mlx5dv_flow_action_attr *action;
+
+ action = malloc(sizeof(*action));
+ if (!action)
+ return NULL;
+ action->type = MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION;
+ action->action = mlx5dv_create_flow_action_modify_header
+ (ctx, actions_sz, actions, ft_type);
+ return action;
#else
(void)ctx;
(void)actions_sz;
#endif
}
+static void *
+mlx5_glue_dv_create_flow_action_packet_reformat
+ (struct ibv_context *ctx,
+ size_t data_sz,
+ void *data,
+ enum mlx5dv_flow_action_packet_reformat_type reformat_type,
+ enum mlx5dv_flow_table_type ft_type)
+{
+#ifdef HAVE_IBV_FLOW_DV_SUPPORT
+ struct mlx5dv_flow_action_attr *action;
+
+ action = malloc(sizeof(*action));
+ if (!action)
+ return NULL;
+ action->type = MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION;
+ action->action = mlx5dv_create_flow_action_packet_reformat
+ (ctx, data_sz, data, reformat_type, ft_type);
+ return action;
+#else
+ (void)ctx;
+ (void)data_sz;
+ (void)data;
+ (void)reformat_type;
+ (void)ft_type;
+ return NULL;
+#endif
+}
+
+static void *
+mlx5_glue_dv_create_flow_action_tag(uint32_t tag)
+{
+#ifdef HAVE_IBV_FLOW_DV_SUPPORT
+ struct mlx5dv_flow_action_attr *action;
+ action = malloc(sizeof(*action));
+ if (!action)
+ return NULL;
+ action->type = MLX5DV_FLOW_ACTION_TAG;
+ action->tag_value = tag;
+ return action;
+#endif
+ (void)tag;
+ return NULL;
+}
+
static struct ibv_context *
mlx5_glue_dv_open_device(struct ibv_device *device)
{
.dv_create_flow_matcher = mlx5_glue_dv_create_flow_matcher,
.dv_destroy_flow_matcher = mlx5_glue_dv_destroy_flow_matcher,
.dv_create_flow = mlx5_glue_dv_create_flow,
- .dv_create_flow_action_packet_reformat =
- mlx5_glue_dv_create_flow_action_packet_reformat,
+ .dv_create_flow_action_counter =
+ mlx5_glue_dv_create_flow_action_counter,
+ .dv_create_flow_action_dest_ibv_qp =
+ mlx5_glue_dv_create_flow_action_dest_ibv_qp,
.dv_create_flow_action_modify_header =
- mlx5_glue_dv_create_flow_action_modify_header,
+ mlx5_glue_dv_create_flow_action_modify_header,
+ .dv_create_flow_action_packet_reformat =
+ mlx5_glue_dv_create_flow_action_packet_reformat,
+ .dv_create_flow_action_tag = mlx5_glue_dv_create_flow_action_tag,
.dv_open_device = mlx5_glue_dv_open_device,
.devx_obj_create = mlx5_glue_devx_obj_create,
.devx_obj_destroy = mlx5_glue_devx_obj_destroy,
enum mlx5dv_flow_table_type { flow_table_type = 0, };
#endif
+#ifndef HAVE_IBV_FLOW_DEVX_COUNTERS
+#define MLX5DV_FLOW_ACTION_COUNTERS_DEVX 0
+#endif
+
#ifndef HAVE_IBV_DEVX_OBJ
struct mlx5dv_devx_obj;
#endif
struct ibv_flow *(*create_flow)(struct ibv_qp *qp,
struct ibv_flow_attr *flow);
int (*destroy_flow)(struct ibv_flow *flow_id);
- int (*destroy_flow_action)(struct ibv_flow_action *action);
+ int (*destroy_flow_action)(void *action);
struct ibv_qp *(*create_qp)(struct ibv_pd *pd,
struct ibv_qp_init_attr *qp_init_attr);
struct ibv_qp *(*create_qp_ex)
int (*dv_destroy_flow_matcher)(struct mlx5dv_flow_matcher *matcher);
struct ibv_flow *(*dv_create_flow)(struct mlx5dv_flow_matcher *matcher,
struct mlx5dv_flow_match_parameters *match_value,
- size_t num_actions,
- struct mlx5dv_flow_action_attr *actions_attr);
- struct ibv_flow_action *(*dv_create_flow_action_packet_reformat)
- (struct ibv_context *ctx,
- size_t data_sz,
- void *data,
+ size_t num_actions, void *actions[]);
+ void *(*dv_create_flow_action_counter)(void *obj, uint32_t offset);
+ void *(*dv_create_flow_action_dest_ibv_qp)(void *qp);
+ void *(*dv_create_flow_action_modify_header)
+ (struct ibv_context *ctx, size_t actions_sz, uint64_t actions[],
+ enum mlx5dv_flow_table_type ft_type);
+ void *(*dv_create_flow_action_packet_reformat)
+ (struct ibv_context *ctx, size_t data_sz, void *data,
enum mlx5dv_flow_action_packet_reformat_type reformat_type,
enum mlx5dv_flow_table_type ft_type);
- struct ibv_flow_action *(*dv_create_flow_action_modify_header)
- (struct ibv_context *ctx,
- size_t actions_sz,
- uint64_t actions[],
- enum mlx5dv_flow_table_type ft_type);
+ void *(*dv_create_flow_action_tag)(uint32_t tag);
struct ibv_context *(*dv_open_device)(struct ibv_device *device);
struct mlx5dv_devx_obj *(*devx_obj_create)
(struct ibv_context *ctx,