This patch supports new tunnel type MPLS-in-GRE and MPLS-in-UDP.

Signed-off-by: Xueming Li <xuemi...@mellanox.com>
---
 drivers/net/mlx5/mlx5_flow.c | 122 ++++++++++++++++++++++++++++++++++++-------
 1 file changed, 104 insertions(+), 18 deletions(-)

diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c
index bda1a58..00c705a 100644
--- a/drivers/net/mlx5/mlx5_flow.c
+++ b/drivers/net/mlx5/mlx5_flow.c
@@ -98,6 +98,11 @@ struct ibv_flow_spec_counter_action {
                       const void *default_mask,
                       void *data);
 
+static int
+mlx5_flow_create_mpls(const struct rte_flow_item *item,
+                     const void *default_mask,
+                     void *data);
+
 struct mlx5_flow_parse;
 
 static void
@@ -246,21 +251,29 @@ struct rte_flow {
 #define IS_TUNNEL(type) ( \
        (type) == RTE_FLOW_ITEM_TYPE_VXLAN || \
        (type) == RTE_FLOW_ITEM_TYPE_VXLAN_GPE || \
+       (type) == RTE_FLOW_ITEM_TYPE_MPLS || \
        (type) == RTE_FLOW_ITEM_TYPE_GRE)
 
-const uint32_t rte_ptype[] = {
-       [RTE_FLOW_ITEM_TYPE_VXLAN]     = RTE_PTYPE_TUNNEL_VXLAN |
-                                        RTE_PTYPE_L4_UDP,
-       [RTE_FLOW_ITEM_TYPE_VXLAN_GPE] = RTE_PTYPE_TUNNEL_VXLAN_GPE |
-                                        RTE_PTYPE_L4_UDP,
-       [RTE_FLOW_ITEM_TYPE_GRE]       = RTE_PTYPE_TUNNEL_GRE,
+const uint32_t flow2ptype[] = {
+       [RTE_FLOW_ITEM_TYPE_VXLAN]      = RTE_PTYPE_TUNNEL_VXLAN,
+       [RTE_FLOW_ITEM_TYPE_VXLAN_GPE]  = RTE_PTYPE_TUNNEL_VXLAN_GPE,
+       [RTE_FLOW_ITEM_TYPE_GRE]        = RTE_PTYPE_TUNNEL_GRE,
+       [RTE_FLOW_ITEM_TYPE_MPLS]       = RTE_PTYPE_TUNNEL_MPLS_IN_GRE,
 };
 
 #define PTYPE_TUN(t) ((RTE_PTYPE_TUNNEL_MASK & (t)) >> 12)
-static const uint32_t ptype_flow_type[] = {
-       [PTYPE_TUN(RTE_PTYPE_TUNNEL_VXLAN)]     = RTE_FLOW_ITEM_TYPE_VXLAN,
-       [PTYPE_TUN(RTE_PTYPE_TUNNEL_VXLAN_GPE)] = RTE_FLOW_ITEM_TYPE_VXLAN_GPE,
-       [PTYPE_TUN(RTE_PTYPE_TUNNEL_GRE)]       = RTE_FLOW_ITEM_TYPE_GRE,
+
+const uint32_t ptype2ptype[] = {
+       [PTYPE_TUN(RTE_PTYPE_TUNNEL_VXLAN)]     = RTE_PTYPE_TUNNEL_VXLAN |
+                                                 RTE_PTYPE_L4_UDP,
+       [PTYPE_TUN(RTE_PTYPE_TUNNEL_VXLAN_GPE)] = RTE_PTYPE_TUNNEL_VXLAN_GPE |
+                                                 RTE_PTYPE_L4_UDP,
+       [PTYPE_TUN(RTE_PTYPE_TUNNEL_GRE)]       = RTE_PTYPE_TUNNEL_GRE,
+       [PTYPE_TUN(RTE_PTYPE_TUNNEL_MPLS_IN_GRE)] =
+                                                 RTE_PTYPE_TUNNEL_MPLS_IN_GRE,
+       [PTYPE_TUN(RTE_PTYPE_TUNNEL_MPLS_IN_UDP)] =
+                                                 RTE_PTYPE_TUNNEL_MPLS_IN_GRE |
+                                                 RTE_PTYPE_L4_UDP,
 };
 
 /** Structure to generate a simple graph of layers supported by the NIC. */
@@ -395,7 +408,8 @@ struct mlx5_flow_items {
        },
        [RTE_FLOW_ITEM_TYPE_UDP] = {
                .items = ITEMS(RTE_FLOW_ITEM_TYPE_VXLAN,
-                              RTE_FLOW_ITEM_TYPE_VXLAN_GPE),
+                              RTE_FLOW_ITEM_TYPE_VXLAN_GPE,
+                              RTE_FLOW_ITEM_TYPE_MPLS),
                .actions = valid_actions,
                .mask = &(const struct rte_flow_item_udp){
                        .hdr = {
@@ -423,7 +437,8 @@ struct mlx5_flow_items {
        },
        [RTE_FLOW_ITEM_TYPE_GRE] = {
                .items = ITEMS(RTE_FLOW_ITEM_TYPE_IPV4,
-                              RTE_FLOW_ITEM_TYPE_IPV6),
+                              RTE_FLOW_ITEM_TYPE_IPV6,
+                              RTE_FLOW_ITEM_TYPE_MPLS),
                .actions = valid_actions,
                .mask = &(const struct rte_flow_item_gre){
                        .protocol = -1,
@@ -459,6 +474,19 @@ struct mlx5_flow_items {
                .convert = mlx5_flow_create_vxlan_gpe,
                .dst_sz = sizeof(struct ibv_flow_spec_tunnel),
        },
+       [RTE_FLOW_ITEM_TYPE_MPLS] = {
+               .items = ITEMS(RTE_FLOW_ITEM_TYPE_ETH,
+                              RTE_FLOW_ITEM_TYPE_IPV4,
+                              RTE_FLOW_ITEM_TYPE_IPV6),
+               .actions = valid_actions,
+               .mask = &(const struct rte_flow_item_mpls){
+                       .label_tc_s = "\xff\xff\xf0",
+               },
+               .default_mask = &rte_flow_item_mpls_mask,
+               .mask_sz = sizeof(struct rte_flow_item_mpls),
+               .convert = mlx5_flow_create_mpls,
+               .dst_sz = sizeof(struct ibv_flow_spec_tunnel),
+       },
 };
 
 /** Structure to pass to the conversion function. */
@@ -908,7 +936,9 @@ struct ibv_spec_header {
                if (err)
                        goto exit_item_not_supported;
                if (IS_TUNNEL(items->type)) {
-                       if (parser->tunnel) {
+                       if (parser->tunnel &&
+                          !(parser->tunnel == RTE_PTYPE_TUNNEL_GRE &&
+                            items->type == RTE_FLOW_ITEM_TYPE_MPLS)) {
                                rte_flow_error_set(error, ENOTSUP,
                                                   RTE_FLOW_ERROR_TYPE_ITEM,
                                                   items,
@@ -929,7 +959,7 @@ struct ibv_spec_header {
                                        items,
                                        "Cannot support tunnel inner RSS");
                        parser->inner = IBV_FLOW_SPEC_INNER;
-                       parser->tunnel = rte_ptype[items->type];
+                       parser->tunnel = flow2ptype[items->type];
                        parser->layer = HASH_RXQ_TUNNEL;
                } else {
                        parser->layer = HASH_RXQ_ETH;
@@ -1726,7 +1756,7 @@ struct ibv_spec_header {
 
        id.vni[0] = 0;
        parser->inner = IBV_FLOW_SPEC_INNER;
-       parser->tunnel = rte_ptype[item->type];
+       parser->tunnel = ptype2ptype[PTYPE_TUN(RTE_PTYPE_TUNNEL_VXLAN)];
        parser->out_layer = parser->layer;
        parser->layer = HASH_RXQ_TUNNEL;
        if (spec) {
@@ -1788,7 +1818,7 @@ struct ibv_spec_header {
 
        id.vni[0] = 0;
        parser->inner = IBV_FLOW_SPEC_INNER;
-       parser->tunnel = rte_ptype[item->type];
+       parser->tunnel = ptype2ptype[PTYPE_TUN(RTE_PTYPE_TUNNEL_VXLAN_GPE)];
        parser->out_layer = parser->layer;
        parser->layer = HASH_RXQ_TUNNEL;
        if (spec) {
@@ -1827,6 +1857,62 @@ struct ibv_spec_header {
 }
 
 /**
+ * Convert MPLS item to Verbs specification.
+ * Tunnel types currently supported are MPLS-in-GRE and MPLS-in-UDP.
+ *
+ * @param item[in]
+ *   Item specification.
+ * @param default_mask[in]
+ *   Default bit-masks to use when item->mask is not provided.
+ * @param data[in, out]
+ *   User structure.
+ */
+static int
+mlx5_flow_create_mpls(const struct rte_flow_item *item,
+                          const void *default_mask,
+                          void *data)
+{
+       const struct rte_flow_item_mpls *spec = item->spec;
+       const struct rte_flow_item_mpls *mask = item->mask;
+       struct mlx5_flow_parse *parser = (struct mlx5_flow_parse *)data;
+       unsigned int size = sizeof(struct ibv_flow_spec_tunnel);
+       struct ibv_flow_spec_tunnel mpls = {
+               .type = parser->inner | IBV_FLOW_SPEC_VXLAN_TUNNEL,
+               .size = size,
+       };
+       union vni {
+               uint32_t vlan_id;
+               uint8_t vni[4];
+       } id;
+
+       id.vni[0] = 0;
+       parser->inner = IBV_FLOW_SPEC_INNER;
+       if (parser->layer == HASH_RXQ_UDPV4 ||
+           parser->layer == HASH_RXQ_UDPV6) {
+               parser->tunnel =
+                       ptype2ptype[PTYPE_TUN(RTE_PTYPE_TUNNEL_MPLS_IN_UDP)];
+               parser->out_layer = parser->layer;
+       } else {
+               parser->tunnel =
+                       ptype2ptype[PTYPE_TUN(RTE_PTYPE_TUNNEL_MPLS_IN_GRE)];
+       }
+       parser->layer = HASH_RXQ_TUNNEL;
+       if (spec) {
+               if (!mask)
+                       mask = default_mask;
+               memcpy(&id.vni[1], spec->label_tc_s, 3);
+               mpls.val.tunnel_id = id.vlan_id;
+               memcpy(&id.vni[1], mask->label_tc_s, 3);
+               mpls.mask.tunnel_id = id.vlan_id;
+               /* Remove unwanted bits from values. */
+               mpls.val.tunnel_id &= mpls.mask.tunnel_id;
+       }
+
+       mlx5_flow_create_copy(parser, &mpls, size);
+       return 0;
+}
+
+/**
  * Convert GRE item to Verbs specification.
  *
  * @param item[in]
@@ -1851,7 +1937,7 @@ struct ibv_spec_header {
        (void)item;
        (void)default_mask;
        parser->inner = IBV_FLOW_SPEC_INNER;
-       parser->tunnel = rte_ptype[item->type];
+       parser->tunnel = ptype2ptype[PTYPE_TUN(RTE_PTYPE_TUNNEL_GRE)];
        parser->out_layer = parser->layer;
        parser->layer = HASH_RXQ_TUNNEL;
        mlx5_flow_create_copy(parser, &tunnel, size);
@@ -2325,7 +2411,7 @@ struct rte_flow *
                                }
                        /* Keep same if more than one tunnel types left. */
                        if (types == 1)
-                               rxq->tunnel = rte_ptype[ptype_flow_type[last]];
+                               rxq->tunnel = ptype2ptype[last];
                        else if (types == 0) /* No tunnel type left. */
                                rxq->tunnel = 0;
                }
-- 
1.8.3.1

Reply via email to