@@ -600,6 +600,7 @@ struct mlx5_priv {
#endif
uint8_t skip_default_rss_reta; /* Skip configuration of default reta. */
uint8_t fdb_def_rule; /* Whether fdb jump to table 1 is configured. */
+ LIST_HEAD(fdir, mlx5_fdir_flow) fdir_flows; /* fdir flows. */
};
#define PORT_ID(priv) ((priv)->dev_data->port_id)
@@ -4501,6 +4501,7 @@ struct rte_flow *
struct rte_flow *flow)
{
struct mlx5_priv *priv = dev->data->dev_private;
+ struct mlx5_fdir_flow *priv_fdir_flow = NULL;
/*
* Update RX queue flags only if port is started, otherwise it is
@@ -4515,7 +4516,17 @@ struct rte_flow *
if (list)
TAILQ_REMOVE(list, flow, next);
flow_mreg_del_copy_action(dev, flow);
- rte_free(flow->fdir);
+ if (flow->fdir) {
+ LIST_FOREACH(priv_fdir_flow, &priv->fdir_flows, next) {
+ if (priv_fdir_flow->flow == flow)
+ break;
+ }
+ if (priv_fdir_flow) {
+ LIST_REMOVE(priv_fdir_flow, next);
+ rte_free(priv_fdir_flow->flow);
+ rte_free(priv_fdir_flow);
+ }
+ }
if (flow->idx)
mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_RTE_FLOW],
flow->idx);
@@ -5211,12 +5222,14 @@ struct rte_flow *
{
struct mlx5_priv *priv = dev->data->dev_private;
struct rte_flow *flow = NULL;
+ struct mlx5_fdir_flow *priv_fdir_flow = NULL;
MLX5_ASSERT(fdir_flow);
- TAILQ_FOREACH(flow, &priv->flows, next) {
- if (flow->fdir && !flow_fdir_cmp(flow->fdir, fdir_flow)) {
+ LIST_FOREACH(priv_fdir_flow, &priv->fdir_flows, next) {
+ if (!flow_fdir_cmp(priv_fdir_flow->fdir, fdir_flow)) {
DRV_LOG(DEBUG, "port %u found FDIR flow %p",
dev->data->port_id, (void *)flow);
+ flow = priv_fdir_flow->flow;
break;
}
}
@@ -5241,6 +5254,7 @@ struct rte_flow *
struct mlx5_priv *priv = dev->data->dev_private;
struct mlx5_fdir *fdir_flow;
struct rte_flow *flow;
+ struct mlx5_fdir_flow *priv_fdir_flow = NULL;
int ret;
fdir_flow = rte_zmalloc(__func__, sizeof(*fdir_flow), 0);
@@ -5256,17 +5270,26 @@ struct rte_flow *
rte_errno = EEXIST;
goto error;
}
+ priv_fdir_flow = rte_zmalloc(__func__, sizeof(struct mlx5_fdir_flow),
+ 0);
+ if (!priv_fdir_flow) {
+ rte_errno = ENOMEM;
+ goto error;
+ }
flow = flow_list_create(dev, &priv->flows, &fdir_flow->attr,
fdir_flow->items, fdir_flow->actions, true,
NULL);
if (!flow)
goto error;
- MLX5_ASSERT(!flow->fdir);
- flow->fdir = fdir_flow;
+ flow->fdir = 1;
+ priv_fdir_flow->fdir = fdir_flow;
+ priv_fdir_flow->flow = flow;
+ LIST_INSERT_HEAD(&priv->fdir_flows, priv_fdir_flow, next);
DRV_LOG(DEBUG, "port %u created FDIR flow %p",
dev->data->port_id, (void *)flow);
return 0;
error:
+ rte_free(priv_fdir_flow);
rte_free(fdir_flow);
return -rte_errno;
}
@@ -5291,17 +5314,26 @@ struct rte_flow *
struct mlx5_fdir fdir_flow = {
.attr.group = 0,
};
+ struct mlx5_fdir_flow *priv_fdir_flow = NULL;
int ret;
ret = flow_fdir_filter_convert(dev, fdir_filter, &fdir_flow);
if (ret)
return -rte_errno;
- flow = flow_fdir_filter_lookup(dev, &fdir_flow);
- if (!flow) {
- rte_errno = ENOENT;
- return -rte_errno;
+ LIST_FOREACH(priv_fdir_flow, &priv->fdir_flows, next) {
+ /* Find the fdir in priv list */
+ if (!flow_fdir_cmp(priv_fdir_flow->fdir, &fdir_flow))
+ break;
}
+ if (!priv_fdir_flow)
+ return 0;
+ LIST_REMOVE(priv_fdir_flow, next);
+ flow = priv_fdir_flow->flow;
+ /* Fdir resource will be releasd after flow destroy. */
+ flow->fdir = 0;
flow_list_destroy(dev, &priv->flows, flow);
+ rte_free(priv_fdir_flow->fdir);
+ rte_free(priv_fdir_flow);
DRV_LOG(DEBUG, "port %u deleted FDIR flow %p",
dev->data->port_id, (void *)flow);
return 0;
@@ -5340,8 +5372,16 @@ struct rte_flow *
flow_fdir_filter_flush(struct rte_eth_dev *dev)
{
struct mlx5_priv *priv = dev->data->dev_private;
-
- mlx5_flow_list_flush(dev, &priv->flows, false);
+ struct mlx5_fdir_flow *priv_fdir_flow = NULL;
+
+ while (!LIST_EMPTY(&priv->fdir_flows)) {
+ priv_fdir_flow = LIST_FIRST(&priv->fdir_flows);
+ LIST_REMOVE(priv_fdir_flow, next);
+ priv_fdir_flow->flow->fdir = 0;
+ flow_list_destroy(dev, &priv->flows, priv_fdir_flow->flow);
+ rte_free(priv_fdir_flow->fdir);
+ rte_free(priv_fdir_flow);
+ }
}
/**
@@ -753,6 +753,13 @@ struct mlx5_flow_meter_profile {
uint32_t ref_cnt; /**< Use count. */
};
+/* Fdir flow struture */
+struct mlx5_fdir_flow {
+ LIST_ENTRY(mlx5_fdir_flow) next; /* Pointer to the next element. */
+ struct mlx5_fdir *fdir; /* Pointer to fdir. */
+ struct rte_flow *flow; /* Pointer to flow. */
+};
+
/* Flow structure. */
struct rte_flow {
TAILQ_ENTRY(rte_flow) next; /**< Pointer to the next flow structure. */
@@ -764,7 +771,7 @@ struct rte_flow {
uint16_t meter; /**< Holds flow meter id. */
uint32_t dev_handles;
/**< Device flow handles that are part of the flow. */
- struct mlx5_fdir *fdir; /**< Pointer to associated FDIR if any. */
+ uint32_t fdir:1; /**< Identifier of associated FDIR if any. */
uint32_t hairpin_flow_id; /**< The flow id used for hairpin. */
uint32_t copy_applied:1; /**< The MARK copy Flow os applied. */
uint32_t idx; /**< Index to the rte flow allocated from indexed pool. */