gbp: fix lpm classification with vlan 86/19986/2
authorBenoît Ganne <bganne@cisco.com>
Wed, 5 Jun 2019 17:08:40 +0000 (19:08 +0200)
committerNeale Ranns <nranns@cisco.com>
Thu, 6 Jun 2019 08:07:35 +0000 (08:07 +0000)
Fix GBP LPM packet classification in the presence of a VLAN header.

Change-Id: I2ff63b34f7475d696b10b5a245ff802bbb1ff01a
Signed-off-by: Benoît Ganne <bganne@cisco.com>
src/plugins/gbp/gbp_classify_node.c
test/test_gbp.py

index f7124be..a2d6d4c 100644 (file)
@@ -279,70 +279,32 @@ typedef enum gbp_lpm_classify_next_t_
   GPB_LPM_CLASSIFY_DROP,
 } gbp_lpm_classify_next_t;
 
-always_inline void
-gbp_classify_get_src_ip4_address (const ethernet_header_t * eh0,
-                                 const ip4_address_t ** ip4)
-{
-  const ip4_header_t *iph4;
-
-  iph4 = (ip4_header_t *) (eh0 + 1);
-  *ip4 = &iph4->src_address;
-}
-
-always_inline void
-gbp_classify_get_src_ip6_address (const ethernet_header_t * eh0,
-                                 const ip6_address_t ** ip6)
-{
-  const ip6_header_t *iph6;
-
-  iph6 = (ip6_header_t *) (eh0 + 1);
-  *ip6 = &iph6->src_address;
-}
-
 always_inline void
 gbp_classify_get_src_ip_address (const ethernet_header_t * eh0,
                                 const ip4_address_t ** ip4,
                                 const ip6_address_t ** ip6)
 {
   u16 etype = clib_net_to_host_u16 (eh0->type);
+  const void *l3h0 = eh0 + 1;
+
+  if (ETHERNET_TYPE_VLAN == etype)
+    {
+      const ethernet_vlan_header_t *vh0 =
+       (ethernet_vlan_header_t *) (eh0 + 1);
+      etype = clib_net_to_host_u16 (vh0->type);
+      l3h0 = vh0 + 1;
+    }
 
   switch (etype)
     {
     case ETHERNET_TYPE_IP4:
-      gbp_classify_get_src_ip4_address (eh0, ip4);
+      *ip4 = &((const ip4_header_t *) l3h0)->src_address;
       break;
     case ETHERNET_TYPE_IP6:
-      gbp_classify_get_src_ip6_address (eh0, ip6);
+      *ip6 = &((const ip6_header_t *) l3h0)->src_address;
       break;
-    case ETHERNET_TYPE_VLAN:
-      {
-       ethernet_vlan_header_t *vh0;
-
-       vh0 = (ethernet_vlan_header_t *) (eh0 + 1);
-
-       switch (clib_net_to_host_u16 (vh0->type))
-         {
-         case ETHERNET_TYPE_IP4:
-           {
-             gbp_classify_get_src_ip4_address (eh0, ip4);
-             break;
-         case ETHERNET_TYPE_IP6:
-             gbp_classify_get_src_ip6_address (eh0, ip6);
-             break;
-           }
-         }
-       break;
-      }
     case ETHERNET_TYPE_ARP:
-      {
-       const ethernet_arp_header_t *ea0;
-
-       ea0 = (ethernet_arp_header_t *) (eh0 + 1);
-
-       *ip4 = &ea0->ip4_over_ethernet[0].ip4;
-       break;
-      }
-    default:
+      *ip4 = &((ethernet_arp_header_t *) l3h0)->ip4_over_ethernet[0].ip4;
       break;
     }
 }
index e386a31..19ca81b 100644 (file)
@@ -3529,6 +3529,9 @@ class TestGBP(VppTestCase):
         vlan_101 = VppDot1QSubint(self, self.pg0, 101)
         vlan_101.admin_up()
         VppL2Vtr(self, vlan_101, L2_VTR_OP.L2_POP_1).add_vpp_config()
+        # vlan_102 is not poped
+        vlan_102 = VppDot1QSubint(self, self.pg0, 102)
+        vlan_102.admin_up()
 
         ext_itf = VppGbpExtItf(self, self.loop0, bd1, rd1)
         ext_itf.add_vpp_config()
@@ -3557,6 +3560,12 @@ class TestGBP(VppTestCase):
                               "2001:10::2", "3001::2",
                               ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
         eep2.add_vpp_config()
+        eep3 = VppGbpEndpoint(self, vlan_102,
+                              epg_220, None,
+                              "10.0.0.3", "11.0.0.3",
+                              "2001:10::3", "3001::3",
+                              ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
+        eep3.add_vpp_config()
 
         #
         # A remote external endpoint
@@ -3581,6 +3590,16 @@ class TestGBP(VppTestCase):
                      hwsrc=eep1.mac, hwdst="ff:ff:ff:ff:ff:ff"))
         rxs = self.send_and_expect(self.pg0, p_arp * 1, self.pg0)
 
+        #
+        # ARP packet from host in remote subnet are accepted and replied to
+        #
+        p_arp = (Ether(src=vlan_102.remote_mac, dst="ff:ff:ff:ff:ff:ff") /
+                 Dot1Q(vlan=102) /
+                 ARP(op="who-has",
+                     psrc="10.0.0.17", pdst="10.0.0.128",
+                     hwsrc=vlan_102.remote_mac, hwdst="ff:ff:ff:ff:ff:ff"))
+        rxs = self.send_and_expect(self.pg0, p_arp * 1, self.pg0)
+
         #
         # packets destined to unknown addresses in the BVI's subnet
         # are ARP'd for
@@ -3661,6 +3680,20 @@ class TestGBP(VppTestCase):
             self.assertEqual(rx[Ether].dst, eep2.mac)
             self.assertEqual(rx[Dot1Q].vlan, 101)
 
+        #
+        # local EP pings router w/o vlan tag poped
+        #
+        p = (Ether(src=eep3.mac, dst=str(self.router_mac)) /
+             Dot1Q(vlan=102) /
+             IP(src=eep3.ip4.address, dst="10.0.0.128") /
+             ICMP(type='echo-request'))
+
+        rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
+
+        for rx in rxs:
+            self.assertEqual(rx[Ether].src, str(self.router_mac))
+            self.assertEqual(rx[Ether].dst, vlan_102.remote_mac)
+
         #
         # A subnet reachable through the external EP1
         #