[dpdk-dev,v1,12/29] net/mlx4: relax check on missing flow rule target

Message ID 6403e1ccae50cbd85f828ec722f200ff41468531.1507730496.git.adrien.mazarguil@6wind.com (mailing list archive)
State Superseded, archived
Headers

Checks

Context Check Description
ci/checkpatch success coding style OK
ci/Intel-compilation fail apply patch file failure

Commit Message

Adrien Mazarguil Oct. 11, 2017, 2:35 p.m. UTC
  Creating a flow rule targeting a missing (unconfigured) queue is not
possible. However, nothing really prevents the destruction of a queue with
existing flow rules still pointing at it, except currently the port must be
in a stopped state in order to avoid crashing.

Problem is that the port cannot be restarted if flow rules cannot be
re-applied due to missing queues. This flexibility will be needed by
subsequent work on this PMD.

Given that a PMD cannot decide on its own to remove problematic
user-defined flow rules in order to restart a port, work around this
restriction by making the affected ones drop-like, i.e. rules targeting
nonexistent queues drop packets instead.

Signed-off-by: Adrien Mazarguil <adrien.mazarguil@6wind.com>
Acked-by: Nelio Laranjeiro <nelio.laranjeiro@6wind.com>
---
 drivers/net/mlx4/mlx4_flow.c | 28 +++++++++++++++++-----------
 1 file changed, 17 insertions(+), 11 deletions(-)
  

Patch

diff --git a/drivers/net/mlx4/mlx4_flow.c b/drivers/net/mlx4/mlx4_flow.c
index 658c92f..3f97987 100644
--- a/drivers/net/mlx4/mlx4_flow.c
+++ b/drivers/net/mlx4/mlx4_flow.c
@@ -850,20 +850,24 @@  mlx4_flow_toggle(struct priv *priv,
 			mlx4_drop_put(priv->drop);
 		return 0;
 	}
-	if (flow->ibv_flow)
-		return 0;
-	assert(flow->queue ^ flow->drop);
 	if (flow->queue) {
-		struct rxq *rxq;
+		struct rxq *rxq = NULL;
 
-		assert(flow->queue_id < priv->dev->data->nb_rx_queues);
-		rxq = priv->dev->data->rx_queues[flow->queue_id];
-		if (!rxq) {
-			err = EINVAL;
-			msg = "target queue must be configured first";
-			goto error;
+		if (flow->queue_id < priv->dev->data->nb_rx_queues)
+			rxq = priv->dev->data->rx_queues[flow->queue_id];
+		if (flow->ibv_flow) {
+			if (!rxq ^ !flow->drop)
+				return 0;
+			/* Verbs flow needs updating. */
+			claim_zero(ibv_destroy_flow(flow->ibv_flow));
+			flow->ibv_flow = NULL;
+			if (flow->drop)
+				mlx4_drop_put(priv->drop);
 		}
-		qp = rxq->qp;
+		if (rxq)
+			qp = rxq->qp;
+		/* A missing target queue drops traffic implicitly. */
+		flow->drop = !rxq;
 	}
 	if (flow->drop) {
 		mlx4_drop_get(priv);
@@ -876,6 +880,8 @@  mlx4_flow_toggle(struct priv *priv,
 	}
 	assert(qp);
 	assert(flow->ibv_attr);
+	if (flow->ibv_flow)
+		return 0;
 	flow->ibv_flow = ibv_create_flow(qp, flow->ibv_attr);
 	if (flow->ibv_flow)
 		return 0;