net/mlx5: fix VLAN filtering
authorShahaf Shuler <shahafs@mellanox.com>
Tue, 31 Jul 2018 07:57:20 +0000 (10:57 +0300)
committerShahaf Shuler <shahafs@mellanox.com>
Thu, 2 Aug 2018 11:15:18 +0000 (13:15 +0200)
The below commit has added a graph based expansion logic for RSS rule to
satisfy Verbs requirements. With this logic, for example, the rule:

flow create 0 ingress pattern eth / end actions rss queues 0 1 end types
ipv4-tcp ipv6-tcp end / end

will be expanded into the rules:

flow create 0 ingress pattern eth / ipv4 / tcp / end actions rss queues 0 1
end types ipv4-tcp ipv6-tcp end / end

flow create 0 ingress pattern eth / ipv6 / tcp / end actions rss queues 0 1
end types ipv4-tcp ipv6-tcp end / end

flow create 0 ingress pattern eth / end actions queue index 0 / end

The below commit defined two graphs:
1. graph for the tunnel case which starts from the ETH item
2. graph for the non-tunnel case which starts from the ETH item

The graphs are ignoring the VLAN case. Hence rules with VLAN item will
fail to traverse the graph and it will result in flow rule creation error.

Adding the VLAN item to the existing graphs will not work as the flow
engine will reject any VLAN item without a specific vid.

To solve this case two new graphs were added (for the tunnel and
non-tunnel case) which contain the VLAN item and are being used only
when the VLAN item exists in the flow pattern.

Two cases left un-covered for the inner RSS:
1. The case were VLAN exists in the pattern as part of the inner headers
2. The case were VLAN exists in the pattern both in the outer and the
inner headers

Solving those cases will require to add two more graphs.
Holding a VLAN for the overlay network is not common, the subnets are
usually defined by the tunnel protocol, for example the VXLAN vni.
Hence adding those two graphs seems like an overkill at this point.
Based on needs one can add those to provide the full support.

Fixes: 592f05b29a25 ("net/mlx5: add RSS flow action")

Signed-off-by: Shahaf Shuler <shahafs@mellanox.com>
drivers/net/mlx5/mlx5_flow.c

index 923fc28..6c3021a 100644 (file)
@@ -103,7 +103,11 @@ extern const struct eth_dev_ops mlx5_dev_ops_isolate;
 enum mlx5_expansion {
        MLX5_EXPANSION_ROOT,
        MLX5_EXPANSION_ROOT_OUTER,
+       MLX5_EXPANSION_ROOT_ETH_VLAN,
+       MLX5_EXPANSION_ROOT_OUTER_ETH_VLAN,
        MLX5_EXPANSION_OUTER_ETH,
+       MLX5_EXPANSION_OUTER_ETH_VLAN,
+       MLX5_EXPANSION_OUTER_VLAN,
        MLX5_EXPANSION_OUTER_IPV4,
        MLX5_EXPANSION_OUTER_IPV4_UDP,
        MLX5_EXPANSION_OUTER_IPV4_TCP,
@@ -115,6 +119,8 @@ enum mlx5_expansion {
        MLX5_EXPANSION_GRE,
        MLX5_EXPANSION_MPLS,
        MLX5_EXPANSION_ETH,
+       MLX5_EXPANSION_ETH_VLAN,
+       MLX5_EXPANSION_VLAN,
        MLX5_EXPANSION_IPV4,
        MLX5_EXPANSION_IPV4_UDP,
        MLX5_EXPANSION_IPV4_TCP,
@@ -137,6 +143,14 @@ static const struct rte_flow_expand_node mlx5_support_expansion[] = {
                                                 MLX5_EXPANSION_OUTER_IPV6),
                .type = RTE_FLOW_ITEM_TYPE_END,
        },
+       [MLX5_EXPANSION_ROOT_ETH_VLAN] = {
+               .next = RTE_FLOW_EXPAND_RSS_NEXT(MLX5_EXPANSION_ETH_VLAN),
+               .type = RTE_FLOW_ITEM_TYPE_END,
+       },
+       [MLX5_EXPANSION_ROOT_OUTER_ETH_VLAN] = {
+               .next = RTE_FLOW_EXPAND_RSS_NEXT(MLX5_EXPANSION_OUTER_ETH_VLAN),
+               .type = RTE_FLOW_ITEM_TYPE_END,
+       },
        [MLX5_EXPANSION_OUTER_ETH] = {
                .next = RTE_FLOW_EXPAND_RSS_NEXT(MLX5_EXPANSION_OUTER_IPV4,
                                                 MLX5_EXPANSION_OUTER_IPV6,
@@ -144,6 +158,16 @@ static const struct rte_flow_expand_node mlx5_support_expansion[] = {
                .type = RTE_FLOW_ITEM_TYPE_ETH,
                .rss_types = 0,
        },
+       [MLX5_EXPANSION_OUTER_ETH_VLAN] = {
+               .next = RTE_FLOW_EXPAND_RSS_NEXT(MLX5_EXPANSION_OUTER_VLAN),
+               .type = RTE_FLOW_ITEM_TYPE_ETH,
+               .rss_types = 0,
+       },
+       [MLX5_EXPANSION_OUTER_VLAN] = {
+               .next = RTE_FLOW_EXPAND_RSS_NEXT(MLX5_EXPANSION_OUTER_IPV4,
+                                                MLX5_EXPANSION_OUTER_IPV6),
+               .type = RTE_FLOW_ITEM_TYPE_VLAN,
+       },
        [MLX5_EXPANSION_OUTER_IPV4] = {
                .next = RTE_FLOW_EXPAND_RSS_NEXT
                        (MLX5_EXPANSION_OUTER_IPV4_UDP,
@@ -205,6 +229,15 @@ static const struct rte_flow_expand_node mlx5_support_expansion[] = {
                                                 MLX5_EXPANSION_IPV6),
                .type = RTE_FLOW_ITEM_TYPE_ETH,
        },
+       [MLX5_EXPANSION_ETH_VLAN] = {
+               .next = RTE_FLOW_EXPAND_RSS_NEXT(MLX5_EXPANSION_VLAN),
+               .type = RTE_FLOW_ITEM_TYPE_ETH,
+       },
+       [MLX5_EXPANSION_VLAN] = {
+               .next = RTE_FLOW_EXPAND_RSS_NEXT(MLX5_EXPANSION_IPV4,
+                                                MLX5_EXPANSION_IPV6),
+               .type = RTE_FLOW_ITEM_TYPE_VLAN,
+       },
        [MLX5_EXPANSION_IPV4] = {
                .next = RTE_FLOW_EXPAND_RSS_NEXT(MLX5_EXPANSION_IPV4_UDP,
                                                 MLX5_EXPANSION_IPV4_TCP),
@@ -2464,6 +2497,25 @@ mlx5_flow_merge_switch(struct rte_eth_dev *dev,
        return off + ret;
 }
 
+static unsigned int
+mlx5_find_graph_root(const struct rte_flow_item pattern[], uint32_t rss_level)
+{
+       const struct rte_flow_item *item;
+       unsigned int has_vlan = 0;
+
+       for (item = pattern; item->type != RTE_FLOW_ITEM_TYPE_END; item++) {
+               if (item->type == RTE_FLOW_ITEM_TYPE_VLAN) {
+                       has_vlan = 1;
+                       break;
+               }
+       }
+       if (has_vlan)
+               return rss_level < 2 ? MLX5_EXPANSION_ROOT_ETH_VLAN :
+                                      MLX5_EXPANSION_ROOT_OUTER_ETH_VLAN;
+       return rss_level < 2 ? MLX5_EXPANSION_ROOT :
+                              MLX5_EXPANSION_ROOT_OUTER;
+}
+
 /**
  * Convert the @p attributes, @p pattern, @p action, into an flow for the NIC
  * after ensuring the NIC will understand and process it correctly.
@@ -2531,12 +2583,14 @@ mlx5_flow_merge(struct rte_eth_dev *dev, struct rte_flow *flow,
        if (ret < 0)
                return ret;
        if (local_flow.rss.types) {
+               unsigned int graph_root;
+
+               graph_root = mlx5_find_graph_root(pattern,
+                                                 local_flow.rss.level);
                ret = rte_flow_expand_rss(buf, sizeof(expand_buffer.buffer),
                                          pattern, local_flow.rss.types,
                                          mlx5_support_expansion,
-                                         local_flow.rss.level < 2 ?
-                                         MLX5_EXPANSION_ROOT :
-                                         MLX5_EXPANSION_ROOT_OUTER);
+                                         graph_root);
                assert(ret > 0 &&
                       (unsigned int)ret < sizeof(expand_buffer.buffer));
        } else {