struct rte_flow {
TAILQ_ENTRY(rte_flow) next; /**< Pointer to the next flow structure. */
struct ibv_flow_attr *ibv_attr; /**< Pointer to Verbs attributes. */
- struct ibv_rwq_ind_table *ind_table; /**< Indirection table. */
+ struct mlx5_ind_table_ibv *ind_table; /**< Indirection table. */
struct ibv_qp *qp; /**< Verbs queue pair. */
struct ibv_flow *ibv_flow; /**< Verbs flow. */
struct ibv_wq *wq; /**< Verbs work queue. */
struct ibv_cq *cq; /**< Verbs completion queue. */
- uint16_t rxqs_n; /**< Number of queues in this flow, 0 if drop queue. */
uint32_t mark:1; /**< Set if the flow is marked. */
uint32_t drop:1; /**< Drop queue. */
uint64_t hash_fields; /**< Fields that participate in the hash. */
- struct mlx5_rxq_data *rxqs[]; /**< Pointer to the queues array. */
};
/** Static initializer for items. */
{
struct rte_flow *rte_flow;
unsigned int i;
- unsigned int j;
- const unsigned int wqs_n = 1 << log2above(flow->actions.queues_n);
- struct ibv_wq *wqs[wqs_n];
assert(priv->pd);
assert(priv->ctx);
assert(!flow->actions.drop);
- rte_flow = rte_calloc(__func__, 1, sizeof(*rte_flow) +
- sizeof(*rte_flow->rxqs) * flow->actions.queues_n,
- 0);
+ rte_flow = rte_calloc(__func__, 1, sizeof(*rte_flow), 0);
if (!rte_flow) {
rte_flow_error_set(error, ENOMEM, RTE_FLOW_ERROR_TYPE_HANDLE,
NULL, "cannot allocate flow memory");
return NULL;
}
- for (i = 0; i < flow->actions.queues_n; ++i) {
- struct mlx5_rxq_ctrl *rxq;
-
- rxq = container_of((*priv->rxqs)[flow->actions.queues[i]],
- struct mlx5_rxq_ctrl, rxq);
- wqs[i] = rxq->wq;
- rte_flow->rxqs[i] = &rxq->rxq;
- ++rte_flow->rxqs_n;
- rxq->rxq.mark |= flow->actions.mark;
- }
- /* finalise indirection table. */
- for (j = 0; i < wqs_n; ++i, ++j) {
- wqs[i] = wqs[j];
- if (j == flow->actions.queues_n)
- j = 0;
+ for (i = 0; i != flow->actions.queues_n; ++i) {
+ struct mlx5_rxq_data *q =
+ (*priv->rxqs)[flow->actions.queues[i]];
+
+ q->mark |= flow->actions.mark;
}
rte_flow->mark = flow->actions.mark;
rte_flow->ibv_attr = flow->ibv_attr;
rte_flow->hash_fields = flow->hash_fields;
- rte_flow->ind_table = ibv_create_rwq_ind_table(
- priv->ctx,
- &(struct ibv_rwq_ind_table_init_attr){
- .log_ind_tbl_size = log2above(flow->actions.queues_n),
- .ind_tbl = wqs,
- .comp_mask = 0,
- });
+ rte_flow->ind_table =
+ mlx5_priv_ind_table_ibv_get(priv, flow->actions.queues,
+ flow->actions.queues_n);
if (!rte_flow->ind_table) {
- rte_flow_error_set(error, ENOMEM, RTE_FLOW_ERROR_TYPE_HANDLE,
- NULL, "cannot allocate indirection table");
- goto error;
+ rte_flow->ind_table =
+ mlx5_priv_ind_table_ibv_new(priv, flow->actions.queues,
+ flow->actions.queues_n);
+ if (!rte_flow->ind_table) {
+ rte_flow_error_set(error, ENOMEM,
+ RTE_FLOW_ERROR_TYPE_HANDLE,
+ NULL,
+ "cannot allocate indirection table");
+ goto error;
+ }
}
rte_flow->qp = ibv_create_qp_ex(
priv->ctx,
.rx_hash_key = rss_hash_default_key,
.rx_hash_fields_mask = rte_flow->hash_fields,
},
- .rwq_ind_tbl = rte_flow->ind_table,
+ .rwq_ind_tbl = rte_flow->ind_table->ind_table,
.pd = priv->pd
});
if (!rte_flow->qp) {
if (rte_flow->qp)
ibv_destroy_qp(rte_flow->qp);
if (rte_flow->ind_table)
- ibv_destroy_rwq_ind_table(rte_flow->ind_table);
+ mlx5_priv_ind_table_ibv_release(priv, rte_flow->ind_table);
rte_free(rte_flow);
return NULL;
}
priv_flow_destroy(struct priv *priv,
struct rte_flow *flow)
{
+ unsigned int i;
+
TAILQ_REMOVE(&priv->flows, flow, next);
if (flow->ibv_flow)
claim_zero(ibv_destroy_flow(flow->ibv_flow));
goto free;
if (flow->qp)
claim_zero(ibv_destroy_qp(flow->qp));
- if (flow->ind_table)
- claim_zero(ibv_destroy_rwq_ind_table(flow->ind_table));
- if (flow->mark) {
+ for (i = 0; i != flow->ind_table->queues_n; ++i) {
struct rte_flow *tmp;
- struct mlx5_rxq_data *rxq;
- uint32_t mark_n = 0;
- uint32_t queue_n;
+ struct mlx5_rxq_data *rxq_data =
+ (*priv->rxqs)[flow->ind_table->queues[i]];
/*
* To remove the mark from the queue, the queue must not be
* present in any other marked flow (RSS or not).
*/
- for (queue_n = 0; queue_n < flow->rxqs_n; ++queue_n) {
- rxq = flow->rxqs[queue_n];
- for (tmp = TAILQ_FIRST(&priv->flows);
- tmp;
- tmp = TAILQ_NEXT(tmp, next)) {
- uint32_t tqueue_n;
+ if (flow->mark) {
+ int mark = 0;
+
+ TAILQ_FOREACH(tmp, &priv->flows, next) {
+ unsigned int j;
if (tmp->drop)
continue;
- for (tqueue_n = 0;
- tqueue_n < tmp->rxqs_n;
- ++tqueue_n) {
- struct mlx5_rxq_data *trxq;
-
- trxq = tmp->rxqs[tqueue_n];
- if (rxq == trxq)
- ++mark_n;
- }
+ if (!tmp->mark)
+ continue;
+ for (j = 0;
+ (j != tmp->ind_table->queues_n) && !mark;
+ j++)
+ if (tmp->ind_table->queues[j] ==
+ flow->ind_table->queues[i])
+ mark = 1;
}
- rxq->mark = !!mark_n;
+ rxq_data->mark = mark;
}
}
+ mlx5_priv_ind_table_ibv_release(priv, flow->ind_table);
free:
rte_free(flow->ibv_attr);
DEBUG("Flow destroyed %p", (void *)flow);
flow->ibv_flow = NULL;
if (flow->mark) {
unsigned int n;
+ struct mlx5_ind_table_ibv *ind_tbl = flow->ind_table;
- for (n = 0; n < flow->rxqs_n; ++n)
- flow->rxqs[n]->mark = 0;
+ for (n = 0; n < ind_tbl->queues_n; ++n)
+ (*priv->rxqs)[ind_tbl->queues[n]]->mark = 0;
}
DEBUG("Flow %p removed", (void *)flow);
}
if (flow->mark) {
unsigned int n;
- for (n = 0; n < flow->rxqs_n; ++n)
- flow->rxqs[n]->mark = 1;
- }
- }
- return 0;
-}
-
-/**
- * Verify if the Rx queue is used in a flow.
- *
- * @param priv
- * Pointer to private structure.
- * @param rxq
- * Pointer to the queue to search.
- *
- * @return
- * Nonzero if the queue is used by a flow.
- */
-int
-priv_flow_rxq_in_use(struct priv *priv, struct mlx5_rxq_data *rxq)
-{
- struct rte_flow *flow;
-
- for (flow = TAILQ_FIRST(&priv->flows);
- flow;
- flow = TAILQ_NEXT(flow, next)) {
- unsigned int n;
-
- if (flow->drop)
- continue;
- for (n = 0; n < flow->rxqs_n; ++n) {
- if (flow->rxqs[n] == rxq)
- return 1;
+ for (n = 0; n < flow->ind_table->queues_n; ++n) {
+ uint16_t idx = flow->ind_table->queues[n];
+ (*priv->rxqs)[idx]->mark = 1;
+ }
}
}
return 0;
priv_unlock(priv);
return 0;
}
+
+/**
+ * Verify the flow list is empty
+ *
+ * @param priv
+ * Pointer to private structure.
+ *
+ * @return the number of flows not released.
+ */
+int
+priv_flow_verify(struct priv *priv)
+{
+ struct rte_flow *flow;
+ int ret = 0;
+
+ TAILQ_FOREACH(flow, &priv->flows, next) {
+ DEBUG("%p: flow %p still referenced", (void *)priv,
+ (void *)flow);
+ ++ret;
+ }
+ return ret;
+}