net/mlx4: relax check on missing flow rule target
authorAdrien Mazarguil <adrien.mazarguil@6wind.com>
Thu, 12 Oct 2017 12:19:26 +0000 (14:19 +0200)
committerFerruh Yigit <ferruh.yigit@intel.com>
Fri, 13 Oct 2017 00:18:48 +0000 (01:18 +0100)
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

index 8f4898b..669eba2 100644 (file)
@@ -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;