flow: add l2tpv3oip flow 02/26502/5
authorChenmin Sun <chenmin.sun@intel.com>
Tue, 14 Apr 2020 17:55:58 +0000 (01:55 +0800)
committerDamjan Marion <dmarion@me.com>
Thu, 30 Apr 2020 15:37:15 +0000 (15:37 +0000)
This patch adds the l2tpv3oip type flow support
Have tested on E810 with Intel iAVF driver

Type: feature

Signed-off-by: Chenmin Sun <chenmin.sun@intel.com>
Change-Id: Icb5114b5f70dd7a63f681e7c6ac802fade8b8cf1

src/plugins/dpdk/device/flow.c
src/vnet/flow/flow.h
src/vnet/flow/flow_cli.c

index ffc86a1..9d0887c 100644 (file)
@@ -90,6 +90,7 @@ dpdk_flow_add (dpdk_device_t * xd, vnet_flow_t * f, dpdk_flow_entry_t * fe)
   struct rte_flow_item_udp udp[2] = { };
   struct rte_flow_item_tcp tcp[2] = { };
   struct rte_flow_item_gtp gtp[2] = { };
+  struct rte_flow_item_l2tpv3oip l2tp[2] = { };
   struct rte_flow_action_mark mark = { 0 };
   struct rte_flow_action_queue queue = { 0 };
   struct rte_flow_action_rss rss = { 0 };
@@ -109,8 +110,8 @@ dpdk_flow_add (dpdk_device_t * xd, vnet_flow_t * f, dpdk_flow_entry_t * fe)
     u8 val[raw_sz + vxlan_hdr_sz];
   } raw[2];
 
-  u16 src_port, dst_port, src_port_mask, dst_port_mask;
-  u8 protocol;
+  u16 src_port = 0, dst_port = 0, src_port_mask = 0, dst_port_mask = 0;
+  u8 protocol = IP_PROTOCOL_RESERVED;
   int rv = 0;
 
   if (f->actions & (~xd->supported_flow_actions))
@@ -170,11 +171,32 @@ dpdk_flow_add (dpdk_device_t * xd, vnet_flow_t * f, dpdk_flow_entry_t * fe)
 
   /* IP */
   vec_add2 (items, item, 1);
-  if ((f->type == VNET_FLOW_TYPE_IP6_N_TUPLE) ||
-      (f->type == VNET_FLOW_TYPE_IP6_GTPC) ||
-      (f->type == VNET_FLOW_TYPE_IP6_GTPU) ||
-      (f->type == VNET_FLOW_TYPE_IP6_GTPU_IP4) ||
-      (f->type == VNET_FLOW_TYPE_IP6_GTPU_IP6))
+  if (f->type == VNET_FLOW_TYPE_IP4_L2TPV3OIP)
+    {
+      vnet_flow_ip4_l2tpv3oip_t *l2tp = &f->ip4_l2tpv3oip;
+      item->type = RTE_FLOW_ITEM_TYPE_IPV4;
+
+      if (!l2tp->src_addr.mask.as_u32 && !l2tp->dst_addr.mask.as_u32)
+       {
+         item->spec = NULL;
+         item->mask = NULL;
+       }
+      else
+       {
+         ip4[0].hdr.src_addr = l2tp->src_addr.addr.as_u32;
+         ip4[1].hdr.src_addr = l2tp->src_addr.mask.as_u32;
+         ip4[0].hdr.dst_addr = l2tp->dst_addr.addr.as_u32;
+         ip4[1].hdr.dst_addr = l2tp->dst_addr.mask.as_u32;
+         item->spec = ip4;
+         item->mask = ip4 + 1;
+       }
+      protocol = l2tp->protocol;
+    }
+  else if ((f->type == VNET_FLOW_TYPE_IP6_N_TUPLE) ||
+          (f->type == VNET_FLOW_TYPE_IP6_GTPC) ||
+          (f->type == VNET_FLOW_TYPE_IP6_GTPU) ||
+          (f->type == VNET_FLOW_TYPE_IP6_GTPU_IP4) ||
+          (f->type == VNET_FLOW_TYPE_IP6_GTPU_IP6))
     {
       vnet_flow_ip6_n_tuple_t *t6 = &f->ip6_n_tuple;
       item->type = RTE_FLOW_ITEM_TYPE_IPV6;
@@ -255,9 +277,9 @@ dpdk_flow_add (dpdk_device_t * xd, vnet_flow_t * f, dpdk_flow_entry_t * fe)
     }
 
   /* Layer 4 */
-  vec_add2 (items, item, 1);
   if (protocol == IP_PROTOCOL_UDP)
     {
+      vec_add2 (items, item, 1);
       item->type = RTE_FLOW_ITEM_TYPE_UDP;
 
       if ((src_port_mask == 0) && (dst_port_mask == 0))
@@ -277,6 +299,7 @@ dpdk_flow_add (dpdk_device_t * xd, vnet_flow_t * f, dpdk_flow_entry_t * fe)
     }
   else if (protocol == IP_PROTOCOL_TCP)
     {
+      vec_add2 (items, item, 1);
       item->type = RTE_FLOW_ITEM_TYPE_TCP;
 
       if ((src_port_mask == 0) && (dst_port_mask == 0))
@@ -294,13 +317,25 @@ dpdk_flow_add (dpdk_device_t * xd, vnet_flow_t * f, dpdk_flow_entry_t * fe)
          item->mask = tcp + 1;
        }
     }
-  else
+  else if (protocol == IP_PROTOCOL_RESERVED)
     {
       rv = VNET_FLOW_ERROR_NOT_SUPPORTED;
       goto done;
     }
 
   /* Tunnel header match */
+  if (f->type == VNET_FLOW_TYPE_IP4_L2TPV3OIP)
+    {
+      vec_add2 (items, item, 1);
+      item->type = RTE_FLOW_ITEM_TYPE_L2TPV3OIP;
+
+      vnet_flow_ip4_l2tpv3oip_t *tl2tp = &f->ip4_l2tpv3oip;
+      l2tp[0].session_id = clib_host_to_net_u32 (tl2tp->session_id);
+      l2tp[1].session_id = ~0;
+
+      item->spec = l2tp;
+      item->mask = l2tp + 1;
+    }
   if (f->type == VNET_FLOW_TYPE_IP4_VXLAN)
     {
       u32 vni = f->ip4_vxlan.vni;
@@ -699,6 +734,7 @@ dpdk_flow_ops_fn (vnet_main_t * vnm, vnet_flow_dev_op_t op, u32 dev_instance,
     case VNET_FLOW_TYPE_IP6_GTPU:
     case VNET_FLOW_TYPE_IP6_GTPU_IP4:
     case VNET_FLOW_TYPE_IP6_GTPU_IP6:
+    case VNET_FLOW_TYPE_IP4_L2TPV3OIP:
       if ((rv = dpdk_flow_add (xd, flow, fe)))
        goto done;
       break;
index d6850b2..a880b8a 100644 (file)
@@ -31,6 +31,8 @@
   _(IP6_N_TUPLE, ip6_n_tuple, "ipv6-n-tuple") \
   _(IP4_N_TUPLE_TAGGED, ip4_n_tuple_tagged, "ipv4-n-tuple-tagged") \
   _(IP6_N_TUPLE_TAGGED, ip6_n_tuple_tagged, "ipv6-n-tuple-tagged") \
+  /* IP tunnel flow */ \
+  _(IP4_L2TPV3OIP, ip4_l2tpv3oip, "ipv4-l2tpv3oip") \
   /* L4 tunnel flow*/ \
   _(IP4_VXLAN, ip4_vxlan, "ipv4-vxlan") \
   _(IP6_VXLAN, ip6_vxlan, "ipv6-vxlan") \
   _fe(ip_port_and_mask_t, dst_port) \
   _fe(ip_protocol_t, protocol)
 
+#define foreach_flow_entry_ip4_l2tpv3oip \
+  _fe(ip4_address_and_mask_t, src_addr) \
+  _fe(ip4_address_and_mask_t, dst_addr) \
+  _fe(ip_protocol_t, protocol)          \
+  _fe(u32, session_id)
 
 #define foreach_flow_entry_ip4_vxlan \
   _fe(ip4_address_t, src_addr) \
index 772f89a..364b475 100644 (file)
@@ -276,10 +276,11 @@ test_flow (vlib_main_t * vm, unformat_input_t * input,
   } action = FLOW_UNKNOWN_ACTION;
   u32 hw_if_index = ~0, flow_index = ~0;
   int rv;
-  u32 prot = 0, teid = 0;
+  u32 prot = 0, teid = 0, session_id = 0;
   vnet_flow_type_t type = VNET_FLOW_TYPE_IP4_N_TUPLE;
   bool is_gtpc_set = false;
   bool is_gtpu_set = false;
+  bool is_l2tpv3oip_set = false;
   vnet_flow_type_t outer_type = VNET_FLOW_TYPE_UNKNOWN;
   vnet_flow_type_t inner_type = VNET_FLOW_TYPE_UNKNOWN;
   bool outer_ip4_set = false, inner_ip4_set = false;
@@ -357,6 +358,11 @@ test_flow (vlib_main_t * vm, unformat_input_t * input,
        is_gtpc_set = true;
       else if (unformat (line_input, "gtpu teid %u", &teid))
        is_gtpu_set = true;
+      else if (unformat (line_input, "session id %u", &session_id))
+       {
+         if (prot == IP_PROTOCOL_L2TP)
+           is_l2tpv3oip_set = true;
+       }
       else if (unformat (line_input, "index %u", &flow_index))
        ;
       else if (unformat (line_input, "next-node %U", unformat_vlib_node, vm,
@@ -481,6 +487,8 @@ test_flow (vlib_main_t * vm, unformat_input_t * input,
                type = VNET_FLOW_TYPE_IP4_GTPC;
              else if (is_gtpu_set)
                type = VNET_FLOW_TYPE_IP4_GTPU;
+             else if (is_l2tpv3oip_set)
+               type = VNET_FLOW_TYPE_IP4_L2TPV3OIP;
            }
          else if (inner_type == VNET_FLOW_TYPE_IP4_N_TUPLE)
            {
@@ -523,7 +531,14 @@ test_flow (vlib_main_t * vm, unformat_input_t * input,
          memset (&flow.ethernet, 0, sizeof (flow.ethernet));
          flow.ethernet.eth_hdr.type = eth_type;
          break;
-
+       case VNET_FLOW_TYPE_IP4_L2TPV3OIP:
+         clib_memcpy (&flow.ip4_l2tpv3oip.src_addr, &ip4s,
+                      sizeof (ip4_address_and_mask_t));
+         clib_memcpy (&flow.ip4_l2tpv3oip.dst_addr, &ip4d,
+                      sizeof (ip4_address_and_mask_t));
+         flow.ip4_l2tpv3oip.protocol = prot;
+         flow.ip4_l2tpv3oip.session_id = session_id;
+         break;
        case VNET_FLOW_TYPE_IP4_N_TUPLE:
        case VNET_FLOW_TYPE_IP4_GTPC:
        case VNET_FLOW_TYPE_IP4_GTPU: