New upstream version 17.08
[deb_dpdk.git] / drivers / net / mlx5 / mlx5_flow.c
index adcbe3f..86be929 100644 (file)
 #include "mlx5_prm.h"
 
 /* Number of Work Queue necessary for the DROP queue. */
+#ifndef HAVE_VERBS_IBV_EXP_FLOW_SPEC_ACTION_DROP
 #define MLX5_DROP_WQ_N 4
+#else
+#define MLX5_DROP_WQ_N 1
+#endif
 
 static int
 mlx5_flow_create_eth(const struct rte_flow_item *item,
@@ -91,7 +95,7 @@ mlx5_flow_create_vxlan(const struct rte_flow_item *item,
                       void *data);
 
 struct rte_flow {
-       LIST_ENTRY(rte_flow) next; /**< Pointer to the next flow structure. */
+       TAILQ_ENTRY(rte_flow) next; /**< Pointer to the next flow structure. */
        struct ibv_exp_flow_attr *ibv_attr; /**< Pointer to Verbs attributes. */
        struct ibv_exp_rwq_ind_table *ind_table; /**< Indirection table. */
        struct ibv_qp *qp; /**< Verbs queue pair. */
@@ -576,6 +580,10 @@ priv_flow_validate(struct priv *priv,
        }
        if (action->mark && !flow->ibv_attr && !action->drop)
                flow->offset += sizeof(struct ibv_exp_flow_spec_action_tag);
+#ifdef HAVE_VERBS_IBV_EXP_FLOW_SPEC_ACTION_DROP
+       if (!flow->ibv_attr && action->drop)
+               flow->offset += sizeof(struct ibv_exp_flow_spec_action_drop);
+#endif
        if (!action->queue && !action->drop) {
                rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_HANDLE,
                                   NULL, "no valid action");
@@ -993,6 +1001,10 @@ priv_flow_create_action_queue_drop(struct priv *priv,
                                   struct rte_flow_error *error)
 {
        struct rte_flow *rte_flow;
+#ifdef HAVE_VERBS_IBV_EXP_FLOW_SPEC_ACTION_DROP
+       struct ibv_exp_flow_spec_action_drop *drop;
+       unsigned int size = sizeof(struct ibv_exp_flow_spec_action_drop);
+#endif
 
        assert(priv->pd);
        assert(priv->ctx);
@@ -1003,10 +1015,19 @@ priv_flow_create_action_queue_drop(struct priv *priv,
                return NULL;
        }
        rte_flow->drop = 1;
+#ifdef HAVE_VERBS_IBV_EXP_FLOW_SPEC_ACTION_DROP
+       drop = (void *)((uintptr_t)flow->ibv_attr + flow->offset);
+       *drop = (struct ibv_exp_flow_spec_action_drop){
+                       .type = IBV_EXP_FLOW_SPEC_ACTION_DROP,
+                       .size = size,
+       };
+       ++flow->ibv_attr->num_of_specs;
+       flow->offset += sizeof(struct ibv_exp_flow_spec_action_drop);
+#endif
        rte_flow->ibv_attr = flow->ibv_attr;
-       rte_flow->qp = priv->flow_drop_queue->qp;
        if (!priv->started)
                return rte_flow;
+       rte_flow->qp = priv->flow_drop_queue->qp;
        rte_flow->ibv_flow = ibv_exp_create_flow(rte_flow->qp,
                                                 rte_flow->ibv_attr);
        if (!rte_flow->ibv_flow) {
@@ -1230,7 +1251,7 @@ mlx5_flow_create(struct rte_eth_dev *dev,
        priv_lock(priv);
        flow = priv_flow_create(priv, attr, items, actions, error);
        if (flow) {
-               LIST_INSERT_HEAD(&priv->flows, flow, next);
+               TAILQ_INSERT_TAIL(&priv->flows, flow, next);
                DEBUG("Flow created %p", (void *)flow);
        }
        priv_unlock(priv);
@@ -1249,8 +1270,7 @@ static void
 priv_flow_destroy(struct priv *priv,
                  struct rte_flow *flow)
 {
-       (void)priv;
-       LIST_REMOVE(flow, next);
+       TAILQ_REMOVE(&priv->flows, flow, next);
        if (flow->ibv_flow)
                claim_zero(ibv_exp_destroy_flow(flow->ibv_flow));
        if (flow->drop)
@@ -1275,9 +1295,9 @@ priv_flow_destroy(struct priv *priv,
                 */
                for (queue_n = 0; queue_n < flow->rxqs_n; ++queue_n) {
                        rxq = flow->rxqs[queue_n];
-                       for (tmp = LIST_FIRST(&priv->flows);
+                       for (tmp = TAILQ_FIRST(&priv->flows);
                             tmp;
-                            tmp = LIST_NEXT(tmp, next)) {
+                            tmp = TAILQ_NEXT(tmp, next)) {
                                uint32_t tqueue_n;
 
                                if (tmp->drop)
@@ -1330,10 +1350,10 @@ mlx5_flow_destroy(struct rte_eth_dev *dev,
 static void
 priv_flow_flush(struct priv *priv)
 {
-       while (!LIST_EMPTY(&priv->flows)) {
+       while (!TAILQ_EMPTY(&priv->flows)) {
                struct rte_flow *flow;
 
-               flow = LIST_FIRST(&priv->flows);
+               flow = TAILQ_FIRST(&priv->flows);
                priv_flow_destroy(priv, flow);
        }
 }
@@ -1494,9 +1514,7 @@ priv_flow_stop(struct priv *priv)
 {
        struct rte_flow *flow;
 
-       for (flow = LIST_FIRST(&priv->flows);
-            flow;
-            flow = LIST_NEXT(flow, next)) {
+       TAILQ_FOREACH_REVERSE(flow, &priv->flows, mlx5_flows, next) {
                claim_zero(ibv_exp_destroy_flow(flow->ibv_flow));
                flow->ibv_flow = NULL;
                if (flow->mark) {
@@ -1528,9 +1546,7 @@ priv_flow_start(struct priv *priv)
        ret = priv_flow_create_drop_queue(priv);
        if (ret)
                return -1;
-       for (flow = LIST_FIRST(&priv->flows);
-            flow;
-            flow = LIST_NEXT(flow, next)) {
+       TAILQ_FOREACH(flow, &priv->flows, next) {
                struct ibv_qp *qp;
 
                if (flow->drop)
@@ -1570,9 +1586,9 @@ priv_flow_rxq_in_use(struct priv *priv, struct rxq *rxq)
 {
        struct rte_flow *flow;
 
-       for (flow = LIST_FIRST(&priv->flows);
+       for (flow = TAILQ_FIRST(&priv->flows);
             flow;
-            flow = LIST_NEXT(flow, next)) {
+            flow = TAILQ_NEXT(flow, next)) {
                unsigned int n;
 
                if (flow->drop)
@@ -1584,3 +1600,30 @@ priv_flow_rxq_in_use(struct priv *priv, struct rxq *rxq)
        }
        return 0;
 }
+
+/**
+ * Isolated mode.
+ *
+ * @see rte_flow_isolate()
+ * @see rte_flow_ops
+ */
+int
+mlx5_flow_isolate(struct rte_eth_dev *dev,
+                 int enable,
+                 struct rte_flow_error *error)
+{
+       struct priv *priv = dev->data->dev_private;
+
+       priv_lock(priv);
+       if (priv->started) {
+               rte_flow_error_set(error, EBUSY,
+                                  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+                                  NULL,
+                                  "port must be stopped first");
+               priv_unlock(priv);
+               return -rte_errno;
+       }
+       priv->isolated = !!enable;
+       priv_unlock(priv);
+       return 0;
+}