]> git.droids-corp.org - dpdk.git/commitdiff
net/mlx5: add MPLS to Direct Verbs flow engine
authorDekel Peled <dekelp@mellanox.com>
Thu, 15 Nov 2018 15:17:12 +0000 (17:17 +0200)
committerFerruh Yigit <ferruh.yigit@intel.com>
Fri, 16 Nov 2018 09:45:37 +0000 (10:45 +0100)
The support in MPLS on this flow engine was overlooked. It's absence is
critical because there are required actions for MPLS which can be done
only with the DV engine.

To set correctly the MPLS filter, we need to reason about the flow item
before the MPLS (UDP, GRE or other).
To do that, a new variable last_item was added and updated after each
translation. the full item flags are updated after each item iteration.

Signed-off-by: Dekel Peled <dekelp@mellanox.com>
Acked-by: Shahaf Shuler <shahafs@mellanox.com>
drivers/net/mlx5/mlx5_flow.h
drivers/net/mlx5/mlx5_flow_dv.c

index 57b312e7c1418307004687a0cf0a892b577ff725..dd954d8392ee1b3d46308848294c59800ef0d36b 100644 (file)
 #define IPPROTO_MPLS 137
 #endif
 
+/* UDP port number for MPLS */
+#define MLX5_UDP_PORT_MPLS 6635
+
 /* UDP port numbers for VxLAN. */
 #define MLX5_UDP_PORT_VXLAN 4789
 #define MLX5_UDP_PORT_VXLAN_GPE 4790
index 9991cad290cb069835ea2ecb5fbf6a7bfcd99827..b9293bda9a11677bc9134783ab7047ec15c2adae 100644 (file)
@@ -890,6 +890,14 @@ flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
                                return ret;
                        item_flags |= MLX5_FLOW_LAYER_VXLAN_GPE;
                        break;
+               case RTE_FLOW_ITEM_TYPE_MPLS:
+                       ret = mlx5_flow_validate_item_mpls(items, item_flags,
+                                                          next_protocol,
+                                                          error);
+                       if (ret < 0)
+                               return ret;
+                       item_flags |= MLX5_FLOW_LAYER_MPLS;
+                       break;
                case RTE_FLOW_ITEM_TYPE_META:
                        ret = flow_dv_validate_item_meta(dev, items, attr,
                                                         error);
@@ -1608,6 +1616,96 @@ flow_dv_translate_item_vxlan(void *matcher, void *key,
                vni_v[i] = vni_m[i] & vxlan_v->vni[i];
 }
 
+/**
+ * Add MPLS item to matcher and to the value.
+ *
+ * @param[in, out] matcher
+ *   Flow matcher.
+ * @param[in, out] key
+ *   Flow matcher value.
+ * @param[in] item
+ *   Flow pattern to translate.
+ * @param[in] prev_layer
+ *   The protocol layer indicated in previous item.
+ * @param[in] inner
+ *   Item is inner pattern.
+ */
+static void
+flow_dv_translate_item_mpls(void *matcher, void *key,
+                           const struct rte_flow_item *item,
+                           uint64_t prev_layer,
+                           int inner)
+{
+       const uint32_t *in_mpls_m = item->mask;
+       const uint32_t *in_mpls_v = item->spec;
+       uint32_t *out_mpls_m = 0;
+       uint32_t *out_mpls_v = 0;
+       void *misc_m = MLX5_ADDR_OF(fte_match_param, matcher, misc_parameters);
+       void *misc_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters);
+       void *misc2_m = MLX5_ADDR_OF(fte_match_param, matcher,
+                                    misc_parameters_2);
+       void *misc2_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters_2);
+       void *headers_m = MLX5_ADDR_OF(fte_match_param, matcher, outer_headers);
+       void *headers_v = MLX5_ADDR_OF(fte_match_param, key, outer_headers);
+
+       switch (prev_layer) {
+       case MLX5_FLOW_LAYER_OUTER_L4_UDP:
+               MLX5_SET(fte_match_set_lyr_2_4, headers_m, udp_dport, 0xffff);
+               MLX5_SET(fte_match_set_lyr_2_4, headers_v, udp_dport,
+                        MLX5_UDP_PORT_MPLS);
+               break;
+       case MLX5_FLOW_LAYER_GRE:
+               MLX5_SET(fte_match_set_misc, misc_m, gre_protocol, 0xffff);
+               MLX5_SET(fte_match_set_misc, misc_v, gre_protocol,
+                        ETHER_TYPE_MPLS);
+               break;
+       default:
+               MLX5_SET(fte_match_set_lyr_2_4, headers_m, ip_protocol, 0xff);
+               MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_protocol,
+                        IPPROTO_MPLS);
+               break;
+       }
+       if (!in_mpls_v)
+               return;
+       if (!in_mpls_m)
+               in_mpls_m = (const uint32_t *)&rte_flow_item_mpls_mask;
+       switch (prev_layer) {
+       case MLX5_FLOW_LAYER_OUTER_L4_UDP:
+               out_mpls_m =
+                       (uint32_t *)MLX5_ADDR_OF(fte_match_set_misc2, misc2_m,
+                                                outer_first_mpls_over_udp);
+               out_mpls_v =
+                       (uint32_t *)MLX5_ADDR_OF(fte_match_set_misc2, misc2_v,
+                                                outer_first_mpls_over_udp);
+               break;
+       case MLX5_FLOW_LAYER_GRE:
+               out_mpls_m =
+                       (uint32_t *)MLX5_ADDR_OF(fte_match_set_misc2, misc2_m,
+                                                outer_first_mpls_over_gre);
+               out_mpls_v =
+                       (uint32_t *)MLX5_ADDR_OF(fte_match_set_misc2, misc2_v,
+                                                outer_first_mpls_over_gre);
+               break;
+       default:
+               /* Inner MPLS not over GRE is not supported. */
+               if (!inner) {
+                       out_mpls_m =
+                               (uint32_t *)MLX5_ADDR_OF(fte_match_set_misc2,
+                                                        misc2_m,
+                                                        outer_first_mpls);
+                       out_mpls_v =
+                               (uint32_t *)MLX5_ADDR_OF(fte_match_set_misc2,
+                                                        misc2_v,
+                                                        outer_first_mpls);
+               }
+               break;
+       }
+       if (out_mpls_m && out_mpls_v) {
+               *out_mpls_m = *in_mpls_m;
+               *out_mpls_v = *in_mpls_v & *in_mpls_m;
+       }
+}
+
 /**
  * Add META item to matcher
  *
@@ -1786,6 +1884,7 @@ flow_dv_translate(struct rte_eth_dev *dev,
        struct priv *priv = dev->data->dev_private;
        struct rte_flow *flow = dev_flow->flow;
        uint64_t item_flags = 0;
+       uint64_t last_item = 0;
        uint64_t action_flags = 0;
        uint64_t priority = attr->priority;
        struct mlx5_flow_dv_matcher matcher = {
@@ -1940,17 +2039,17 @@ flow_dv_translate(struct rte_eth_dev *dev,
                        flow_dv_translate_item_eth(match_mask, match_value,
                                                   items, tunnel);
                        matcher.priority = MLX5_PRIORITY_MAP_L2;
-                       item_flags |= tunnel ? MLX5_FLOW_LAYER_INNER_L2 :
-                                              MLX5_FLOW_LAYER_OUTER_L2;
+                       last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L2 :
+                                            MLX5_FLOW_LAYER_OUTER_L2;
                        break;
                case RTE_FLOW_ITEM_TYPE_VLAN:
                        flow_dv_translate_item_vlan(match_mask, match_value,
                                                    items, tunnel);
                        matcher.priority = MLX5_PRIORITY_MAP_L2;
-                       item_flags |= tunnel ? (MLX5_FLOW_LAYER_INNER_L2 |
-                                               MLX5_FLOW_LAYER_INNER_VLAN) :
-                                              (MLX5_FLOW_LAYER_OUTER_L2 |
-                                               MLX5_FLOW_LAYER_OUTER_VLAN);
+                       last_item = tunnel ? (MLX5_FLOW_LAYER_INNER_L2 |
+                                             MLX5_FLOW_LAYER_INNER_VLAN) :
+                                            (MLX5_FLOW_LAYER_OUTER_L2 |
+                                             MLX5_FLOW_LAYER_OUTER_VLAN);
                        break;
                case RTE_FLOW_ITEM_TYPE_IPV4:
                        flow_dv_translate_item_ipv4(match_mask, match_value,
@@ -1961,8 +2060,8 @@ flow_dv_translate(struct rte_eth_dev *dev,
                                        (dev_flow, tunnel,
                                         MLX5_IPV4_LAYER_TYPES,
                                         MLX5_IPV4_IBV_RX_HASH);
-                       item_flags |= tunnel ? MLX5_FLOW_LAYER_INNER_L3_IPV4 :
-                                              MLX5_FLOW_LAYER_OUTER_L3_IPV4;
+                       last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L3_IPV4 :
+                                            MLX5_FLOW_LAYER_OUTER_L3_IPV4;
                        break;
                case RTE_FLOW_ITEM_TYPE_IPV6:
                        flow_dv_translate_item_ipv6(match_mask, match_value,
@@ -1973,8 +2072,8 @@ flow_dv_translate(struct rte_eth_dev *dev,
                                        (dev_flow, tunnel,
                                         MLX5_IPV6_LAYER_TYPES,
                                         MLX5_IPV6_IBV_RX_HASH);
-                       item_flags |= tunnel ? MLX5_FLOW_LAYER_INNER_L3_IPV6 :
-                                              MLX5_FLOW_LAYER_OUTER_L3_IPV6;
+                       last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L3_IPV6 :
+                                            MLX5_FLOW_LAYER_OUTER_L3_IPV6;
                        break;
                case RTE_FLOW_ITEM_TYPE_TCP:
                        flow_dv_translate_item_tcp(match_mask, match_value,
@@ -1985,8 +2084,8 @@ flow_dv_translate(struct rte_eth_dev *dev,
                                        (dev_flow, tunnel, ETH_RSS_TCP,
                                         IBV_RX_HASH_SRC_PORT_TCP |
                                         IBV_RX_HASH_DST_PORT_TCP);
-                       item_flags |= tunnel ? MLX5_FLOW_LAYER_INNER_L4_TCP :
-                                              MLX5_FLOW_LAYER_OUTER_L4_TCP;
+                       last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L4_TCP :
+                                            MLX5_FLOW_LAYER_OUTER_L4_TCP;
                        break;
                case RTE_FLOW_ITEM_TYPE_UDP:
                        flow_dv_translate_item_udp(match_mask, match_value,
@@ -1997,37 +2096,43 @@ flow_dv_translate(struct rte_eth_dev *dev,
                                        (dev_flow, tunnel, ETH_RSS_UDP,
                                         IBV_RX_HASH_SRC_PORT_UDP |
                                         IBV_RX_HASH_DST_PORT_UDP);
-                       item_flags |= tunnel ? MLX5_FLOW_LAYER_INNER_L4_UDP :
-                                              MLX5_FLOW_LAYER_OUTER_L4_UDP;
+                       last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L4_UDP :
+                                            MLX5_FLOW_LAYER_OUTER_L4_UDP;
                        break;
                case RTE_FLOW_ITEM_TYPE_GRE:
                        flow_dv_translate_item_gre(match_mask, match_value,
                                                   items, tunnel);
-                       item_flags |= MLX5_FLOW_LAYER_GRE;
+                       last_item = MLX5_FLOW_LAYER_GRE;
                        break;
                case RTE_FLOW_ITEM_TYPE_NVGRE:
                        flow_dv_translate_item_nvgre(match_mask, match_value,
                                                     items, tunnel);
-                       item_flags |= MLX5_FLOW_LAYER_GRE;
+                       last_item = MLX5_FLOW_LAYER_GRE;
                        break;
                case RTE_FLOW_ITEM_TYPE_VXLAN:
                        flow_dv_translate_item_vxlan(match_mask, match_value,
                                                     items, tunnel);
-                       item_flags |= MLX5_FLOW_LAYER_VXLAN;
+                       last_item = MLX5_FLOW_LAYER_VXLAN;
                        break;
                case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
                        flow_dv_translate_item_vxlan(match_mask, match_value,
                                                     items, tunnel);
-                       item_flags |= MLX5_FLOW_LAYER_VXLAN_GPE;
+                       last_item = MLX5_FLOW_LAYER_VXLAN_GPE;
+                       break;
+               case RTE_FLOW_ITEM_TYPE_MPLS:
+                       flow_dv_translate_item_mpls(match_mask, match_value,
+                                                   items, last_item, tunnel);
+                       last_item = MLX5_FLOW_LAYER_MPLS;
                        break;
                case RTE_FLOW_ITEM_TYPE_META:
                        flow_dv_translate_item_meta(match_mask, match_value,
                                                    items);
-                       item_flags |= MLX5_FLOW_ITEM_METADATA;
+                       last_item = MLX5_FLOW_ITEM_METADATA;
                        break;
                default:
                        break;
                }
+               item_flags |= last_item;
        }
        assert(!flow_dv_check_valid_spec(matcher.mask.buf,
                                         dev_flow->dv.value.buf));