net/mlx4: fix targetless internal rule creation
[dpdk.git] / drivers / net / mlx4 / mlx4_flow.c
index 2b60d76..7a6097f 100644 (file)
@@ -133,9 +133,11 @@ mlx4_conv_rss_hf(uint64_t rss_hf)
                [TCP] = (ETH_RSS_NONFRAG_IPV4_TCP |
                         ETH_RSS_NONFRAG_IPV6_TCP |
                         ETH_RSS_IPV6_TCP_EX),
-               [UDP] = (ETH_RSS_NONFRAG_IPV4_UDP |
-                        ETH_RSS_NONFRAG_IPV6_UDP |
-                        ETH_RSS_IPV6_UDP_EX),
+               /*
+                * UDP support is temporarily disabled due to an
+                * implementation issue in the kernel.
+                */
+               [UDP] = 0,
        };
        const uint64_t out[RTE_DIM(in)] = {
                [IPV4] = IBV_RX_HASH_SRC_IPV4 | IBV_RX_HASH_DST_IPV4,
@@ -402,7 +404,7 @@ mlx4_flow_merge_udp(struct rte_flow *flow,
        struct ibv_flow_spec_tcp_udp *udp;
        const char *msg;
 
-       if (!mask ||
+       if (mask &&
            ((uint16_t)(mask->hdr.src_port + 1) > UINT16_C(1) ||
             (uint16_t)(mask->hdr.dst_port + 1) > UINT16_C(1))) {
                msg = "mlx4 does not support matching partial UDP fields";
@@ -462,7 +464,7 @@ mlx4_flow_merge_tcp(struct rte_flow *flow,
        struct ibv_flow_spec_tcp_udp *tcp;
        const char *msg;
 
-       if (!mask ||
+       if (mask &&
            ((uint16_t)(mask->hdr.src_port + 1) > UINT16_C(1) ||
             (uint16_t)(mask->hdr.dst_port + 1) > UINT16_C(1))) {
                msg = "mlx4 does not support matching partial TCP fields";
@@ -753,10 +755,8 @@ fill:
                                        .rss_key = mlx4_rss_hash_key_default,
                                        .rss_key_len = MLX4_RSS_HASH_KEY_SIZE,
                                        .rss_hf = (ETH_RSS_IPV4 |
-                                                  ETH_RSS_NONFRAG_IPV4_UDP |
                                                   ETH_RSS_NONFRAG_IPV4_TCP |
                                                   ETH_RSS_IPV6 |
-                                                  ETH_RSS_NONFRAG_IPV6_UDP |
                                                   ETH_RSS_NONFRAG_IPV6_TCP),
                                };
                        /* Sanity checks. */
@@ -1256,12 +1256,21 @@ mlx4_flow_internal(struct priv *priv, struct rte_flow_error *error)
                        .type = RTE_FLOW_ITEM_TYPE_END,
                },
        };
+       /*
+        * Round number of queues down to their previous power of 2 to
+        * comply with RSS context limitations. Extra queues silently do not
+        * get RSS by default.
+        */
+       uint32_t queues =
+               rte_align32pow2(priv->dev->data->nb_rx_queues + 1) >> 1;
+       alignas(struct rte_flow_action_rss) uint8_t rss_conf_data
+               [offsetof(struct rte_flow_action_rss, queue) +
+                sizeof(((struct rte_flow_action_rss *)0)->queue[0]) * queues];
+       struct rte_flow_action_rss *rss_conf = (void *)rss_conf_data;
        struct rte_flow_action actions[] = {
                {
-                       .type = RTE_FLOW_ACTION_TYPE_QUEUE,
-                       .conf = &(struct rte_flow_action_queue){
-                               .index = 0,
-                       },
+                       .type = RTE_FLOW_ACTION_TYPE_RSS,
+                       .conf = rss_conf,
                },
                {
                        .type = RTE_FLOW_ACTION_TYPE_END,
@@ -1281,6 +1290,16 @@ mlx4_flow_internal(struct priv *priv, struct rte_flow_error *error)
        unsigned int i;
        int err = 0;
 
+       /* Nothing to be done if there are no Rx queues. */
+       if (!queues)
+               goto error;
+       /* Prepare default RSS configuration. */
+       *rss_conf = (struct rte_flow_action_rss){
+               .rss_conf = NULL, /* Rely on default fallback settings. */
+               .num = queues,
+       };
+       for (i = 0; i != queues; ++i)
+               rss_conf->queue[i] = i;
        /*
         * Set up VLAN item if filtering is enabled and at least one VLAN
         * filter is configured.
@@ -1444,9 +1463,7 @@ mlx4_flow_sync(struct priv *priv, struct rte_flow_error *error)
                        return ret;
        }
        /* Toggle the remaining flow rules . */
-       for (flow = LIST_FIRST(&priv->flows);
-            flow;
-            flow = LIST_NEXT(flow, next)) {
+       LIST_FOREACH(flow, &priv->flows, next) {
                ret = mlx4_flow_toggle(priv, flow, priv->started, error);
                if (ret)
                        return ret;