From 286921eef8aa07e9edd83078c0a8397d06dc448c Mon Sep 17 00:00:00 2001 From: Benoît Ganne Date: Wed, 5 Jun 2019 19:08:40 +0200 Subject: gbp: fix lpm classification with vlan MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix GBP LPM packet classification in the presence of a VLAN header. Change-Id: I2ff63b34f7475d696b10b5a245ff802bbb1ff01a Signed-off-by: Benoît Ganne --- src/plugins/gbp/gbp_classify_node.c | 62 +++++++------------------------------ test/test_gbp.py | 33 ++++++++++++++++++++ 2 files changed, 45 insertions(+), 50 deletions(-) diff --git a/src/plugins/gbp/gbp_classify_node.c b/src/plugins/gbp/gbp_classify_node.c index f7124be84dc..a2d6d4c47ae 100644 --- a/src/plugins/gbp/gbp_classify_node.c +++ b/src/plugins/gbp/gbp_classify_node.c @@ -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; } } diff --git a/test/test_gbp.py b/test/test_gbp.py index e386a31e039..19ca81b9cfe 100644 --- a/test/test_gbp.py +++ b/test/test_gbp.py @@ -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 # -- cgit 1.2.3-korg