3 from socket import AF_INET, AF_INET6, inet_pton, inet_ntop
5 from ipaddress import ip_address, IPv4Network, IPv6Network
7 from scapy.packet import Raw
8 from scapy.layers.l2 import Ether, ARP, Dot1Q
9 from scapy.layers.inet import IP, UDP, ICMP
10 from scapy.layers.inet6 import IPv6, ICMPv6ND_NS, ICMPv6NDOptSrcLLAddr, \
11 ICMPv6ND_NA, ICMPv6EchoRequest
12 from scapy.utils6 import in6_getnsma, in6_getnsmac
13 from scapy.layers.vxlan import VXLAN
14 from scapy.data import ETH_P_IP, ETH_P_IPV6, ETH_P_ARP
16 from framework import VppTestCase, VppTestRunner
17 from vpp_object import VppObject
18 from vpp_interface import VppInterface
19 from vpp_ip_route import VppIpRoute, VppRoutePath, VppIpTable, \
20 VppIpInterfaceAddress, VppIpInterfaceBind, find_route, FibPathProto, \
22 from vpp_l2 import VppBridgeDomain, VppBridgeDomainPort, \
23 VppBridgeDomainArpEntry, VppL2FibEntry, find_bridge_domain_port, VppL2Vtr
24 from vpp_sub_interface import L2_VTR_OP, VppDot1QSubint
25 from vpp_ip import DpoProto, get_dpo_proto
26 from vpp_papi import VppEnum, MACAddress
27 from vpp_vxlan_gbp_tunnel import find_vxlan_gbp_tunnel, INDEX_INVALID, \
29 from vpp_neighbor import VppNeighbor
30 from vpp_acl import AclRule, VppAcl
39 def find_gbp_endpoint(test, sw_if_index=None, ip=None, mac=None,
40 tep=None, sclass=None, flags=None):
44 vmac = MACAddress(mac)
46 eps = test.vapi.gbp_endpoint_dump()
52 if src != str(ep.endpoint.tun.src) or \
53 dst != str(ep.endpoint.tun.dst):
56 if ep.endpoint.sw_if_index != sw_if_index:
59 if ep.endpoint.sclass != sclass:
62 if flags != (flags & ep.endpoint.flags):
65 for eip in ep.endpoint.ips:
69 if vmac == ep.endpoint.mac:
75 def find_gbp_vxlan(test, vni):
76 ts = test.vapi.gbp_vxlan_tunnel_dump()
78 if t.tunnel.vni == vni:
83 class VppGbpEndpoint(VppObject):
110 return [self.ip4, self.ip6]
114 return [self.fip4, self.fip6]
116 def __init__(self, test, itf, epg, recirc, ip4, fip4, ip6, fip6,
132 self.vmac = MACAddress(self.itf.remote_mac)
134 self.vmac = MACAddress("00:00:00:00:00:00")
137 self.tun_src = tun_src
138 self.tun_dst = tun_dst
140 def add_vpp_config(self):
141 res = self._test.vapi.gbp_endpoint_add(
142 self.itf.sw_if_index,
143 [self.ip4, self.ip6],
149 self.handle = res.handle
150 self._test.registry.register(self, self._test.logger)
152 def remove_vpp_config(self):
153 self._test.vapi.gbp_endpoint_del(self.handle)
156 return "gbp-endpoint:[%d==%d:%s:%d]" % (self.handle,
157 self.itf.sw_if_index,
161 def query_vpp_config(self):
162 return find_gbp_endpoint(self._test,
163 self.itf.sw_if_index,
167 class VppGbpRecirc(VppObject):
169 GBP Recirculation Interface
172 def __init__(self, test, epg, recirc, is_ext=False):
178 def add_vpp_config(self):
179 self._test.vapi.gbp_recirc_add_del(
181 self.recirc.sw_if_index,
184 self._test.registry.register(self, self._test.logger)
186 def remove_vpp_config(self):
187 self._test.vapi.gbp_recirc_add_del(
189 self.recirc.sw_if_index,
194 return "gbp-recirc:[%d]" % (self.recirc.sw_if_index)
196 def query_vpp_config(self):
197 rs = self._test.vapi.gbp_recirc_dump()
199 if r.recirc.sw_if_index == self.recirc.sw_if_index:
204 class VppGbpExtItf(VppObject):
206 GBP ExtItfulation Interface
209 def __init__(self, test, itf, bd, rd, anon=False):
214 self.flags = 1 if anon else 0
216 def add_vpp_config(self):
217 self._test.vapi.gbp_ext_itf_add_del(
218 1, self.itf.sw_if_index, self.bd.bd_id, self.rd.rd_id, self.flags)
219 self._test.registry.register(self, self._test.logger)
221 def remove_vpp_config(self):
222 self._test.vapi.gbp_ext_itf_add_del(
223 0, self.itf.sw_if_index, self.bd.bd_id, self.rd.rd_id, self.flags)
226 return "gbp-ext-itf:[%d]%s" % (self.itf.sw_if_index,
227 " [anon]" if self.flags else "")
229 def query_vpp_config(self):
230 rs = self._test.vapi.gbp_ext_itf_dump()
232 if r.ext_itf.sw_if_index == self.itf.sw_if_index:
237 class VppGbpSubnet(VppObject):
242 def __init__(self, test, rd, address, address_len,
243 type, sw_if_index=None, sclass=None):
245 self.rd_id = rd.rd_id
246 a = ip_address(address)
248 self.prefix = IPv4Network("%s/%d" % (address, address_len),
251 self.prefix = IPv6Network("%s/%d" % (address, address_len),
254 self.sw_if_index = sw_if_index
257 def add_vpp_config(self):
258 self._test.vapi.gbp_subnet_add_del(
263 sw_if_index=self.sw_if_index if self.sw_if_index else 0xffffffff,
264 sclass=self.sclass if self.sclass else 0xffff)
265 self._test.registry.register(self, self._test.logger)
267 def remove_vpp_config(self):
268 self._test.vapi.gbp_subnet_add_del(
275 return "gbp-subnet:[%d-%s]" % (self.rd_id, self.prefix)
277 def query_vpp_config(self):
278 ss = self._test.vapi.gbp_subnet_dump()
280 if s.subnet.rd_id == self.rd_id and \
281 s.subnet.type == self.type and \
282 s.subnet.prefix == self.prefix:
287 class VppGbpEndpointRetention(object):
288 def __init__(self, remote_ep_timeout=0xffffffff):
289 self.remote_ep_timeout = remote_ep_timeout
292 return {'remote_ep_timeout': self.remote_ep_timeout}
295 class VppGbpEndpointGroup(VppObject):
300 def __init__(self, test, vnid, sclass, rd, bd, uplink,
301 bvi, bvi_ip4, bvi_ip6=None,
302 retention=VppGbpEndpointRetention()):
306 self.bvi_ip4 = bvi_ip4
307 self.bvi_ip6 = bvi_ip6
314 self.retention = retention
316 def add_vpp_config(self):
317 self._test.vapi.gbp_endpoint_group_add(
322 self.uplink.sw_if_index if self.uplink else INDEX_INVALID,
323 self.retention.encode())
324 self._test.registry.register(self, self._test.logger)
326 def remove_vpp_config(self):
327 self._test.vapi.gbp_endpoint_group_del(self.sclass)
330 return "gbp-endpoint-group:[%d]" % (self.vnid)
332 def query_vpp_config(self):
333 epgs = self._test.vapi.gbp_endpoint_group_dump()
335 if epg.epg.vnid == self.vnid:
340 class VppGbpBridgeDomain(VppObject):
345 def __init__(self, test, bd, rd, bvi, uu_fwd=None,
346 bm_flood=None, learn=True,
347 uu_drop=False, bm_drop=False,
352 self.bm_flood = bm_flood
356 e = VppEnum.vl_api_gbp_bridge_domain_flags_t
358 self.flags = e.GBP_BD_API_FLAG_NONE
360 self.flags |= e.GBP_BD_API_FLAG_DO_NOT_LEARN
362 self.flags |= e.GBP_BD_API_FLAG_UU_FWD_DROP
364 self.flags |= e.GBP_BD_API_FLAG_MCAST_DROP
366 self.flags |= e.GBP_BD_API_FLAG_UCAST_ARP
368 def add_vpp_config(self):
369 self._test.vapi.gbp_bridge_domain_add(
373 self.bvi.sw_if_index,
374 self.uu_fwd.sw_if_index if self.uu_fwd else INDEX_INVALID,
375 self.bm_flood.sw_if_index if self.bm_flood else INDEX_INVALID)
376 self._test.registry.register(self, self._test.logger)
378 def remove_vpp_config(self):
379 self._test.vapi.gbp_bridge_domain_del(self.bd.bd_id)
382 return "gbp-bridge-domain:[%d]" % (self.bd.bd_id)
384 def query_vpp_config(self):
385 bds = self._test.vapi.gbp_bridge_domain_dump()
387 if bd.bd.bd_id == self.bd.bd_id:
392 class VppGbpRouteDomain(VppObject):
397 def __init__(self, test, rd_id, scope, t4, t6, ip4_uu=None, ip6_uu=None):
406 def add_vpp_config(self):
407 self._test.vapi.gbp_route_domain_add(
412 self.ip4_uu.sw_if_index if self.ip4_uu else INDEX_INVALID,
413 self.ip6_uu.sw_if_index if self.ip6_uu else INDEX_INVALID)
414 self._test.registry.register(self, self._test.logger)
416 def remove_vpp_config(self):
417 self._test.vapi.gbp_route_domain_del(self.rd_id)
420 return "gbp-route-domain:[%d]" % (self.rd_id)
422 def query_vpp_config(self):
423 rds = self._test.vapi.gbp_route_domain_dump()
425 if rd.rd.rd_id == self.rd_id:
430 class VppGbpContractNextHop():
431 def __init__(self, mac, bd, ip, rd):
438 return {'ip': self.ip,
439 'mac': self.mac.packed,
440 'bd_id': self.bd.bd.bd_id,
441 'rd_id': self.rd.rd_id}
444 class VppGbpContractRule():
445 def __init__(self, action, hash_mode, nhs=None):
447 self.hash_mode = hash_mode
448 self.nhs = [] if nhs is None else nhs
453 nhs.append(nh.encode())
456 return {'action': self.action,
458 'hash_mode': self.hash_mode,
459 'n_nhs': len(self.nhs),
463 return '<VppGbpContractRule action=%s, hash_mode=%s>' % (
464 self.action, self.hash_mode)
467 class VppGbpContract(VppObject):
472 def __init__(self, test, scope, sclass, dclass, acl_index,
473 rules, allowed_ethertypes):
475 if not isinstance(rules, list):
476 raise ValueError("'rules' must be a list.")
477 if not isinstance(allowed_ethertypes, list):
478 raise ValueError("'allowed_ethertypes' must be a list.")
480 self.acl_index = acl_index
484 self.allowed_ethertypes = allowed_ethertypes
485 while (len(self.allowed_ethertypes) < 16):
486 self.allowed_ethertypes.append(0)
488 def add_vpp_config(self):
491 rules.append(r.encode())
492 r = self._test.vapi.gbp_contract_add_del(
495 'acl_index': self.acl_index,
497 'sclass': self.sclass,
498 'dclass': self.dclass,
499 'n_rules': len(rules),
501 'n_ether_types': len(self.allowed_ethertypes),
502 'allowed_ethertypes': self.allowed_ethertypes})
503 self.stats_index = r.stats_index
504 self._test.registry.register(self, self._test.logger)
506 def remove_vpp_config(self):
507 self._test.vapi.gbp_contract_add_del(
510 'acl_index': self.acl_index,
512 'sclass': self.sclass,
513 'dclass': self.dclass,
516 'n_ether_types': len(self.allowed_ethertypes),
517 'allowed_ethertypes': self.allowed_ethertypes})
520 return "gbp-contract:[%d:%d:%d:%d]" % (self.scope,
525 def query_vpp_config(self):
526 cs = self._test.vapi.gbp_contract_dump()
528 if c.contract.scope == self.scope \
529 and c.contract.sclass == self.sclass \
530 and c.contract.dclass == self.dclass:
534 def get_drop_stats(self):
535 c = self._test.statistics.get_counter("/net/gbp/contract/drop")
536 return c[0][self.stats_index]
538 def get_permit_stats(self):
539 c = self._test.statistics.get_counter("/net/gbp/contract/permit")
540 return c[0][self.stats_index]
543 class VppGbpVxlanTunnel(VppInterface):
548 def __init__(self, test, vni, bd_rd_id, mode, src):
549 super(VppGbpVxlanTunnel, self).__init__(test)
552 self.bd_rd_id = bd_rd_id
556 def add_vpp_config(self):
557 r = self._test.vapi.gbp_vxlan_tunnel_add(
562 self.set_sw_if_index(r.sw_if_index)
563 self._test.registry.register(self, self._test.logger)
565 def remove_vpp_config(self):
566 self._test.vapi.gbp_vxlan_tunnel_del(self.vni)
569 return "gbp-vxlan:%d" % (self.sw_if_index)
571 def query_vpp_config(self):
572 return find_gbp_vxlan(self._test, self.vni)
575 class TestGBP(VppTestCase):
576 """ GBP Test Case """
579 def nat_config_flags(self):
580 return VppEnum.vl_api_nat_config_flags_t
583 def nat44_config_flags(self):
584 return VppEnum.vl_api_nat44_config_flags_t
588 super(TestGBP, cls).setUpClass()
591 def tearDownClass(cls):
592 super(TestGBP, cls).tearDownClass()
595 super(TestGBP, self).setUp()
597 self.create_pg_interfaces(range(9))
598 self.create_loopback_interfaces(8)
600 self.router_mac = MACAddress("00:11:22:33:44:55")
602 for i in self.pg_interfaces:
604 for i in self.lo_interfaces:
607 self.vlan_100 = VppDot1QSubint(self, self.pg0, 100)
608 self.vlan_100.admin_up()
609 self.vlan_101 = VppDot1QSubint(self, self.pg0, 101)
610 self.vlan_101.admin_up()
611 self.vlan_102 = VppDot1QSubint(self, self.pg0, 102)
612 self.vlan_102.admin_up()
615 for i in self.pg_interfaces:
617 super(TestGBP, self).tearDown()
618 for i in self.lo_interfaces:
619 i.remove_vpp_config()
620 self.lo_interfaces = []
621 self.vlan_102.remove_vpp_config()
622 self.vlan_101.remove_vpp_config()
623 self.vlan_100.remove_vpp_config()
625 def send_and_expect_bridged(self, src, tx, dst):
626 rx = self.send_and_expect(src, tx, dst)
629 self.assertEqual(r[Ether].src, tx[0][Ether].src)
630 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
631 self.assertEqual(r[IP].src, tx[0][IP].src)
632 self.assertEqual(r[IP].dst, tx[0][IP].dst)
635 def send_and_expect_bridged6(self, src, tx, dst):
636 rx = self.send_and_expect(src, tx, dst)
639 self.assertEqual(r[Ether].src, tx[0][Ether].src)
640 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
641 self.assertEqual(r[IPv6].src, tx[0][IPv6].src)
642 self.assertEqual(r[IPv6].dst, tx[0][IPv6].dst)
645 def send_and_expect_routed(self, src, tx, dst, src_mac):
646 rx = self.send_and_expect(src, tx, dst)
649 self.assertEqual(r[Ether].src, src_mac)
650 self.assertEqual(r[Ether].dst, dst.remote_mac)
651 self.assertEqual(r[IP].src, tx[0][IP].src)
652 self.assertEqual(r[IP].dst, tx[0][IP].dst)
655 def send_and_expect_routed6(self, src, tx, dst, src_mac):
656 rx = self.send_and_expect(src, tx, dst)
659 self.assertEqual(r[Ether].src, src_mac)
660 self.assertEqual(r[Ether].dst, dst.remote_mac)
661 self.assertEqual(r[IPv6].src, tx[0][IPv6].src)
662 self.assertEqual(r[IPv6].dst, tx[0][IPv6].dst)
665 def send_and_expect_natted(self, src, tx, dst, src_ip):
666 rx = self.send_and_expect(src, tx, dst)
669 self.assertEqual(r[Ether].src, tx[0][Ether].src)
670 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
671 self.assertEqual(r[IP].src, src_ip)
672 self.assertEqual(r[IP].dst, tx[0][IP].dst)
675 def send_and_expect_natted6(self, src, tx, dst, src_ip):
676 rx = self.send_and_expect(src, tx, dst)
679 self.assertEqual(r[Ether].src, tx[0][Ether].src)
680 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
681 self.assertEqual(r[IPv6].src, src_ip)
682 self.assertEqual(r[IPv6].dst, tx[0][IPv6].dst)
685 def send_and_expect_unnatted(self, src, tx, dst, dst_ip):
686 rx = self.send_and_expect(src, tx, dst)
689 self.assertEqual(r[Ether].src, tx[0][Ether].src)
690 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
691 self.assertEqual(r[IP].dst, dst_ip)
692 self.assertEqual(r[IP].src, tx[0][IP].src)
695 def send_and_expect_unnatted6(self, src, tx, dst, dst_ip):
696 rx = self.send_and_expect(src, tx, dst)
699 self.assertEqual(r[Ether].src, tx[0][Ether].src)
700 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
701 self.assertEqual(r[IPv6].dst, dst_ip)
702 self.assertEqual(r[IPv6].src, tx[0][IPv6].src)
705 def send_and_expect_double_natted(self, src, tx, dst, src_ip, dst_ip):
706 rx = self.send_and_expect(src, tx, dst)
709 self.assertEqual(r[Ether].src, str(self.router_mac))
710 self.assertEqual(r[Ether].dst, dst.remote_mac)
711 self.assertEqual(r[IP].dst, dst_ip)
712 self.assertEqual(r[IP].src, src_ip)
715 def send_and_expect_double_natted6(self, src, tx, dst, src_ip, dst_ip):
716 rx = self.send_and_expect(src, tx, dst)
719 self.assertEqual(r[Ether].src, str(self.router_mac))
720 self.assertEqual(r[Ether].dst, dst.remote_mac)
721 self.assertEqual(r[IPv6].dst, dst_ip)
722 self.assertEqual(r[IPv6].src, src_ip)
725 def send_and_expect_no_arp(self, src, tx, dst):
726 self.pg_send(src, tx)
727 dst.get_capture(0, timeout=1)
728 dst.assert_nothing_captured(remark="")
731 def send_and_expect_arp(self, src, tx, dst):
732 rx = self.send_and_expect(src, tx, dst)
735 self.assertEqual(r[Ether].src, tx[0][Ether].src)
736 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
737 self.assertEqual(r[ARP].psrc, tx[0][ARP].psrc)
738 self.assertEqual(r[ARP].pdst, tx[0][ARP].pdst)
739 self.assertEqual(r[ARP].hwsrc, tx[0][ARP].hwsrc)
740 self.assertEqual(r[ARP].hwdst, tx[0][ARP].hwdst)
744 """ Group Based Policy """
746 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
751 gt4 = VppIpTable(self, 0)
753 gt6 = VppIpTable(self, 0, is_ip6=True)
755 nt4 = VppIpTable(self, 20)
757 nt6 = VppIpTable(self, 20, is_ip6=True)
760 rd0 = VppGbpRouteDomain(self, 0, 400, gt4, gt6, None, None)
761 rd20 = VppGbpRouteDomain(self, 20, 420, nt4, nt6, None, None)
764 rd20.add_vpp_config()
769 bd1 = VppBridgeDomain(self, 1)
770 bd2 = VppBridgeDomain(self, 2)
771 bd20 = VppBridgeDomain(self, 20)
775 bd20.add_vpp_config()
777 gbd1 = VppGbpBridgeDomain(self, bd1, rd0, self.loop0)
778 gbd2 = VppGbpBridgeDomain(self, bd2, rd0, self.loop1)
779 gbd20 = VppGbpBridgeDomain(self, bd20, rd20, self.loop2)
781 gbd1.add_vpp_config()
782 gbd2.add_vpp_config()
783 gbd20.add_vpp_config()
786 # 3 EPGs, 2 of which share a BD.
787 # 2 NAT EPGs, one for floating-IP subnets, the other for internet
789 epgs = [VppGbpEndpointGroup(self, 220, 1220, rd0, gbd1,
790 self.pg4, self.loop0,
791 "10.0.0.128", "2001:10::128"),
792 VppGbpEndpointGroup(self, 221, 1221, rd0, gbd1,
793 self.pg5, self.loop0,
794 "10.0.1.128", "2001:10:1::128"),
795 VppGbpEndpointGroup(self, 222, 1222, rd0, gbd2,
796 self.pg6, self.loop1,
797 "10.0.2.128", "2001:10:2::128"),
798 VppGbpEndpointGroup(self, 333, 1333, rd20, gbd20,
799 self.pg7, self.loop2,
800 "11.0.0.128", "3001::128"),
801 VppGbpEndpointGroup(self, 444, 1444, rd20, gbd20,
802 self.pg8, self.loop2,
803 "11.0.0.129", "3001::129")]
804 recircs = [VppGbpRecirc(self, epgs[0], self.loop3),
805 VppGbpRecirc(self, epgs[1], self.loop4),
806 VppGbpRecirc(self, epgs[2], self.loop5),
807 VppGbpRecirc(self, epgs[3], self.loop6, is_ext=True),
808 VppGbpRecirc(self, epgs[4], self.loop7, is_ext=True)]
811 recirc_nat = recircs[3]
814 # 4 end-points, 2 in the same subnet, 3 in the same BD
816 eps = [VppGbpEndpoint(self, self.pg0,
818 "10.0.0.1", "11.0.0.1",
819 "2001:10::1", "3001::1"),
820 VppGbpEndpoint(self, self.pg1,
822 "10.0.0.2", "11.0.0.2",
823 "2001:10::2", "3001::2"),
824 VppGbpEndpoint(self, self.pg2,
826 "10.0.1.1", "11.0.0.3",
827 "2001:10:1::1", "3001::3"),
828 VppGbpEndpoint(self, self.pg3,
830 "10.0.2.1", "11.0.0.4",
831 "2001:10:2::1", "3001::4")]
833 self.vapi.nat44_plugin_enable_disable(enable=1)
836 # Config related to each of the EPGs
839 # IP config on the BVI interfaces
840 if epg != epgs[1] and epg != epgs[4]:
841 b4 = VppIpInterfaceBind(self, epg.bvi,
842 epg.rd.t4).add_vpp_config()
843 b6 = VppIpInterfaceBind(self, epg.bvi,
844 epg.rd.t6).add_vpp_config()
845 epg.bvi.set_mac(self.router_mac)
847 # The BVIs are NAT inside interfaces
848 flags = self.nat_config_flags.NAT_IS_INSIDE
849 self.vapi.nat44_interface_add_del_feature(
850 sw_if_index=epg.bvi.sw_if_index,
851 flags=flags, is_add=1)
852 self.vapi.nat66_add_del_interface(
853 is_add=1, flags=flags,
854 sw_if_index=epg.bvi.sw_if_index)
856 if_ip4 = VppIpInterfaceAddress(self, epg.bvi,
858 bind=b4).add_vpp_config()
859 if_ip6 = VppIpInterfaceAddress(self, epg.bvi,
861 bind=b6).add_vpp_config()
863 # EPG uplink interfaces in the RD
864 VppIpInterfaceBind(self, epg.uplink, epg.rd.t4).add_vpp_config()
865 VppIpInterfaceBind(self, epg.uplink, epg.rd.t6).add_vpp_config()
867 # add the BD ARP termination entry for BVI IP
868 epg.bd_arp_ip4 = VppBridgeDomainArpEntry(self, epg.bd.bd,
869 str(self.router_mac),
871 epg.bd_arp_ip6 = VppBridgeDomainArpEntry(self, epg.bd.bd,
872 str(self.router_mac),
874 epg.bd_arp_ip4.add_vpp_config()
875 epg.bd_arp_ip6.add_vpp_config()
880 for recirc in recircs:
881 # EPG's ingress recirculation interface maps to its RD
882 VppIpInterfaceBind(self, recirc.recirc,
883 recirc.epg.rd.t4).add_vpp_config()
884 VppIpInterfaceBind(self, recirc.recirc,
885 recirc.epg.rd.t6).add_vpp_config()
887 self.vapi.nat44_interface_add_del_feature(
888 sw_if_index=recirc.recirc.sw_if_index, is_add=1)
889 self.vapi.nat66_add_del_interface(
891 sw_if_index=recirc.recirc.sw_if_index)
893 recirc.add_vpp_config()
895 for recirc in recircs:
896 self.assertTrue(find_bridge_domain_port(self,
897 recirc.epg.bd.bd.bd_id,
898 recirc.recirc.sw_if_index))
901 self.pg_enable_capture(self.pg_interfaces)
904 # routes to the endpoints. We need these since there are no
905 # adj-fibs due to the fact the the BVI address has /32 and
906 # the subnet is not attached.
908 for (ip, fip) in zip(ep.ips, ep.fips):
909 # Add static mappings for each EP from the 10/8 to 11/8 network
910 if ip_address(ip).version == 4:
911 flags = self.nat_config_flags.NAT_IS_ADDR_ONLY
912 self.vapi.nat44_add_del_static_mapping(
915 external_ip_address=fip,
916 external_sw_if_index=0xFFFFFFFF,
920 self.vapi.nat66_add_del_static_mapping(
922 external_ip_address=fip,
928 self.logger.info(self.vapi.cli("sh gbp endpoint"))
930 # ... results in a Gratuitous ARP/ND on the EPG's uplink
931 rx = ep.epg.uplink.get_capture(len(ep.ips), timeout=0.2)
933 for ii, ip in enumerate(ep.ips):
936 if ip_address(ip).version == 6:
937 self.assertTrue(p.haslayer(ICMPv6ND_NA))
938 self.assertEqual(p[ICMPv6ND_NA].tgt, ip)
940 self.assertTrue(p.haslayer(ARP))
941 self.assertEqual(p[ARP].psrc, ip)
942 self.assertEqual(p[ARP].pdst, ip)
944 # add the BD ARP termination entry for floating IP
946 ba = VppBridgeDomainArpEntry(self, epg_nat.bd.bd, ep.mac,
950 # floating IPs route via EPG recirc
952 self, fip, ip_address(fip).max_prefixlen,
954 ep.recirc.recirc.sw_if_index,
955 type=FibPathType.FIB_PATH_TYPE_DVR,
956 proto=get_dpo_proto(fip))],
960 # L2 FIB entries in the NAT EPG BD to bridge the packets from
961 # the outside direct to the internal EPG
962 lf = VppL2FibEntry(self, epg_nat.bd.bd, ep.mac,
963 ep.recirc.recirc, bvi_mac=0)
967 # ARP packets for unknown IP are sent to the EPG uplink
969 pkt_arp = (Ether(dst="ff:ff:ff:ff:ff:ff",
970 src=self.pg0.remote_mac) /
972 hwdst="ff:ff:ff:ff:ff:ff",
973 hwsrc=self.pg0.remote_mac,
977 self.vapi.cli("clear trace")
978 self.pg0.add_stream(pkt_arp)
980 self.pg_enable_capture(self.pg_interfaces)
983 rxd = epgs[0].uplink.get_capture(1)
986 # ARP/ND packets get a response
988 pkt_arp = (Ether(dst="ff:ff:ff:ff:ff:ff",
989 src=self.pg0.remote_mac) /
991 hwdst="ff:ff:ff:ff:ff:ff",
992 hwsrc=self.pg0.remote_mac,
993 pdst=epgs[0].bvi_ip4,
996 self.send_and_expect(self.pg0, [pkt_arp], self.pg0)
998 nsma = in6_getnsma(inet_pton(AF_INET6, eps[0].ip6))
999 d = inet_ntop(AF_INET6, nsma)
1000 pkt_nd = (Ether(dst=in6_getnsmac(nsma),
1001 src=self.pg0.remote_mac) /
1002 IPv6(dst=d, src=eps[0].ip6) /
1003 ICMPv6ND_NS(tgt=epgs[0].bvi_ip6) /
1004 ICMPv6NDOptSrcLLAddr(lladdr=self.pg0.remote_mac))
1005 self.send_and_expect(self.pg0, [pkt_nd], self.pg0)
1008 # broadcast packets are flooded
1010 pkt_bcast = (Ether(dst="ff:ff:ff:ff:ff:ff",
1011 src=self.pg0.remote_mac) /
1012 IP(src=eps[0].ip4, dst="232.1.1.1") /
1013 UDP(sport=1234, dport=1234) /
1016 self.vapi.cli("clear trace")
1017 self.pg0.add_stream(pkt_bcast)
1019 self.pg_enable_capture(self.pg_interfaces)
1022 rxd = eps[1].itf.get_capture(1)
1023 self.assertEqual(rxd[0][Ether].dst, pkt_bcast[Ether].dst)
1024 rxd = epgs[0].uplink.get_capture(1)
1025 self.assertEqual(rxd[0][Ether].dst, pkt_bcast[Ether].dst)
1028 # packets to non-local L3 destinations dropped
1030 pkt_intra_epg_220_ip4 = (Ether(src=self.pg0.remote_mac,
1031 dst=str(self.router_mac)) /
1034 UDP(sport=1234, dport=1234) /
1036 pkt_inter_epg_222_ip4 = (Ether(src=self.pg0.remote_mac,
1037 dst=str(self.router_mac)) /
1040 UDP(sport=1234, dport=1234) /
1043 self.send_and_assert_no_replies(self.pg0,
1044 pkt_intra_epg_220_ip4 * NUM_PKTS)
1046 pkt_inter_epg_222_ip6 = (Ether(src=self.pg0.remote_mac,
1047 dst=str(self.router_mac)) /
1048 IPv6(src=eps[0].ip6,
1049 dst="2001:10::99") /
1050 UDP(sport=1234, dport=1234) /
1052 self.send_and_assert_no_replies(self.pg0,
1053 pkt_inter_epg_222_ip6 * NUM_PKTS)
1056 # Add the subnet routes
1059 self, rd0, "10.0.0.0", 24,
1060 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1062 self, rd0, "10.0.1.0", 24,
1063 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1065 self, rd0, "10.0.2.0", 24,
1066 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1068 self, rd0, "2001:10::1", 64,
1069 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1071 self, rd0, "2001:10:1::1", 64,
1072 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1074 self, rd0, "2001:10:2::1", 64,
1075 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1076 s41.add_vpp_config()
1077 s42.add_vpp_config()
1078 s43.add_vpp_config()
1079 s61.add_vpp_config()
1080 s62.add_vpp_config()
1081 s63.add_vpp_config()
1083 self.send_and_expect_bridged(eps[0].itf,
1084 pkt_intra_epg_220_ip4 * NUM_PKTS,
1086 self.send_and_expect_bridged(eps[0].itf,
1087 pkt_inter_epg_222_ip4 * NUM_PKTS,
1089 self.send_and_expect_bridged6(eps[0].itf,
1090 pkt_inter_epg_222_ip6 * NUM_PKTS,
1093 self.logger.info(self.vapi.cli("sh ip fib 11.0.0.2"))
1094 self.logger.info(self.vapi.cli("sh gbp endpoint-group"))
1095 self.logger.info(self.vapi.cli("sh gbp endpoint"))
1096 self.logger.info(self.vapi.cli("sh gbp recirc"))
1097 self.logger.info(self.vapi.cli("sh int"))
1098 self.logger.info(self.vapi.cli("sh int addr"))
1099 self.logger.info(self.vapi.cli("sh int feat loop6"))
1100 self.logger.info(self.vapi.cli("sh vlib graph ip4-gbp-src-classify"))
1101 self.logger.info(self.vapi.cli("sh int feat loop3"))
1102 self.logger.info(self.vapi.cli("sh int feat pg0"))
1105 # Packet destined to unknown unicast is sent on the epg uplink ...
1107 pkt_intra_epg_220_to_uplink = (Ether(src=self.pg0.remote_mac,
1108 dst="00:00:00:33:44:55") /
1111 UDP(sport=1234, dport=1234) /
1114 self.send_and_expect_bridged(eps[0].itf,
1115 pkt_intra_epg_220_to_uplink * NUM_PKTS,
1117 # ... and nowhere else
1118 self.pg1.get_capture(0, timeout=0.1)
1119 self.pg1.assert_nothing_captured(remark="Flood onto other VMS")
1121 pkt_intra_epg_221_to_uplink = (Ether(src=self.pg2.remote_mac,
1122 dst="00:00:00:33:44:66") /
1125 UDP(sport=1234, dport=1234) /
1128 self.send_and_expect_bridged(eps[2].itf,
1129 pkt_intra_epg_221_to_uplink * NUM_PKTS,
1133 # Packets from the uplink are forwarded in the absence of a contract
1135 pkt_intra_epg_220_from_uplink = (Ether(src="00:00:00:33:44:55",
1136 dst=self.pg0.remote_mac) /
1139 UDP(sport=1234, dport=1234) /
1142 self.send_and_expect_bridged(self.pg4,
1143 pkt_intra_epg_220_from_uplink * NUM_PKTS,
1147 # in the absence of policy, endpoints in the same EPG
1150 pkt_intra_epg = (Ether(src=self.pg0.remote_mac,
1151 dst=self.pg1.remote_mac) /
1154 UDP(sport=1234, dport=1234) /
1157 self.send_and_expect_bridged(self.pg0,
1158 pkt_intra_epg * NUM_PKTS,
1162 # in the absence of policy, endpoints in the different EPG
1163 # cannot communicate
1165 pkt_inter_epg_220_to_221 = (Ether(src=self.pg0.remote_mac,
1166 dst=self.pg2.remote_mac) /
1169 UDP(sport=1234, dport=1234) /
1171 pkt_inter_epg_221_to_220 = (Ether(src=self.pg2.remote_mac,
1172 dst=self.pg0.remote_mac) /
1175 UDP(sport=1234, dport=1234) /
1177 pkt_inter_epg_220_to_222 = (Ether(src=self.pg0.remote_mac,
1178 dst=str(self.router_mac)) /
1181 UDP(sport=1234, dport=1234) /
1184 self.send_and_assert_no_replies(eps[0].itf,
1185 pkt_inter_epg_220_to_221 * NUM_PKTS)
1186 self.send_and_assert_no_replies(eps[0].itf,
1187 pkt_inter_epg_220_to_222 * NUM_PKTS)
1190 # A uni-directional contract from EPG 220 -> 221
1192 rule = AclRule(is_permit=1, proto=17)
1193 rule2 = AclRule(src_prefix=IPv6Network((0, 0)),
1194 dst_prefix=IPv6Network((0, 0)), is_permit=1, proto=17)
1195 acl = VppAcl(self, rules=[rule, rule2])
1196 acl.add_vpp_config()
1198 c1 = VppGbpContract(
1199 self, 400, epgs[0].sclass, epgs[1].sclass, acl.acl_index,
1200 [VppGbpContractRule(
1201 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1202 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1205 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1206 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1208 [ETH_P_IP, ETH_P_IPV6])
1211 self.send_and_expect_bridged(eps[0].itf,
1212 pkt_inter_epg_220_to_221 * NUM_PKTS,
1214 self.send_and_assert_no_replies(eps[0].itf,
1215 pkt_inter_epg_220_to_222 * NUM_PKTS)
1218 # contract for the return direction
1220 c2 = VppGbpContract(
1221 self, 400, epgs[1].sclass, epgs[0].sclass, acl.acl_index,
1222 [VppGbpContractRule(
1223 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1224 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1227 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1228 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1230 [ETH_P_IP, ETH_P_IPV6])
1233 self.send_and_expect_bridged(eps[0].itf,
1234 pkt_inter_epg_220_to_221 * NUM_PKTS,
1236 self.send_and_expect_bridged(eps[2].itf,
1237 pkt_inter_epg_221_to_220 * NUM_PKTS,
1240 ds = c2.get_drop_stats()
1241 self.assertEqual(ds['packets'], 0)
1242 ps = c2.get_permit_stats()
1243 self.assertEqual(ps['packets'], NUM_PKTS)
1246 # the contract does not allow non-IP
1248 pkt_non_ip_inter_epg_220_to_221 = (Ether(src=self.pg0.remote_mac,
1249 dst=self.pg2.remote_mac) /
1251 self.send_and_assert_no_replies(eps[0].itf,
1252 pkt_non_ip_inter_epg_220_to_221 * 17)
1255 # check that inter group is still disabled for the groups
1256 # not in the contract.
1258 self.send_and_assert_no_replies(eps[0].itf,
1259 pkt_inter_epg_220_to_222 * NUM_PKTS)
1262 # A uni-directional contract from EPG 220 -> 222 'L3 routed'
1264 c3 = VppGbpContract(
1265 self, 400, epgs[0].sclass, epgs[2].sclass, acl.acl_index,
1266 [VppGbpContractRule(
1267 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1268 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1271 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1272 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1274 [ETH_P_IP, ETH_P_IPV6])
1277 self.logger.info(self.vapi.cli("sh gbp contract"))
1279 self.send_and_expect_routed(eps[0].itf,
1280 pkt_inter_epg_220_to_222 * NUM_PKTS,
1282 str(self.router_mac))
1285 # remove both contracts, traffic stops in both directions
1287 c2.remove_vpp_config()
1288 c1.remove_vpp_config()
1289 c3.remove_vpp_config()
1290 acl.remove_vpp_config()
1292 self.send_and_assert_no_replies(eps[2].itf,
1293 pkt_inter_epg_221_to_220 * NUM_PKTS)
1294 self.send_and_assert_no_replies(eps[0].itf,
1295 pkt_inter_epg_220_to_221 * NUM_PKTS)
1296 self.send_and_expect_bridged(eps[0].itf,
1297 pkt_intra_epg * NUM_PKTS,
1301 # EPs to the outside world
1304 # in the EP's RD an external subnet via the NAT EPG's recirc
1306 self, rd0, "0.0.0.0", 0,
1307 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1308 sw_if_index=recirc_nat.recirc.sw_if_index,
1309 sclass=epg_nat.sclass)
1311 self, rd0, "11.0.0.0", 8,
1312 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1313 sw_if_index=recirc_nat.recirc.sw_if_index,
1314 sclass=epg_nat.sclass)
1315 se16 = VppGbpSubnet(
1317 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1318 sw_if_index=recirc_nat.recirc.sw_if_index,
1319 sclass=epg_nat.sclass)
1320 # in the NAT RD an external subnet via the NAT EPG's uplink
1322 self, rd20, "0.0.0.0", 0,
1323 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1324 sw_if_index=epg_nat.uplink.sw_if_index,
1325 sclass=epg_nat.sclass)
1326 se36 = VppGbpSubnet(
1327 self, rd20, "::", 0,
1328 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1329 sw_if_index=epg_nat.uplink.sw_if_index,
1330 sclass=epg_nat.sclass)
1332 self, rd20, "11.0.0.0", 8,
1333 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1334 sw_if_index=epg_nat.uplink.sw_if_index,
1335 sclass=epg_nat.sclass)
1336 se1.add_vpp_config()
1337 se2.add_vpp_config()
1338 se16.add_vpp_config()
1339 se3.add_vpp_config()
1340 se36.add_vpp_config()
1341 se4.add_vpp_config()
1343 self.logger.info(self.vapi.cli("sh ip fib 0.0.0.0/0"))
1344 self.logger.info(self.vapi.cli("sh ip fib 11.0.0.1"))
1345 self.logger.info(self.vapi.cli("sh ip6 fib ::/0"))
1346 self.logger.info(self.vapi.cli("sh ip6 fib %s" %
1350 # From an EP to an outside address: IN2OUT
1352 pkt_inter_epg_220_to_global = (Ether(src=self.pg0.remote_mac,
1353 dst=str(self.router_mac)) /
1356 UDP(sport=1234, dport=1234) /
1360 self.send_and_assert_no_replies(eps[0].itf,
1361 pkt_inter_epg_220_to_global * NUM_PKTS)
1362 rule = AclRule(is_permit=1, proto=17, ports=1234)
1363 rule2 = AclRule(is_permit=1, proto=17, ports=1234,
1364 src_prefix=IPv6Network((0, 0)),
1365 dst_prefix=IPv6Network((0, 0)))
1366 acl2 = VppAcl(self, rules=[rule, rule2])
1367 acl2.add_vpp_config()
1369 c4 = VppGbpContract(
1370 self, 400, epgs[0].sclass, epgs[3].sclass, acl2.acl_index,
1371 [VppGbpContractRule(
1372 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1373 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1376 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1377 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1379 [ETH_P_IP, ETH_P_IPV6])
1382 self.send_and_expect_natted(eps[0].itf,
1383 pkt_inter_epg_220_to_global * NUM_PKTS,
1387 pkt_inter_epg_220_to_global = (Ether(src=self.pg0.remote_mac,
1388 dst=str(self.router_mac)) /
1389 IPv6(src=eps[0].ip6,
1391 UDP(sport=1234, dport=1234) /
1394 self.send_and_expect_natted6(self.pg0,
1395 pkt_inter_epg_220_to_global * NUM_PKTS,
1400 # From a global address to an EP: OUT2IN
1402 pkt_inter_epg_220_from_global = (Ether(src=str(self.router_mac),
1403 dst=self.pg0.remote_mac) /
1406 UDP(sport=1234, dport=1234) /
1409 self.send_and_assert_no_replies(
1410 self.pg7, pkt_inter_epg_220_from_global * NUM_PKTS)
1412 c5 = VppGbpContract(
1413 self, 400, epgs[3].sclass, epgs[0].sclass, acl2.acl_index,
1414 [VppGbpContractRule(
1415 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1416 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1419 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1420 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1422 [ETH_P_IP, ETH_P_IPV6])
1425 self.send_and_expect_unnatted(self.pg7,
1426 pkt_inter_epg_220_from_global * NUM_PKTS,
1430 pkt_inter_epg_220_from_global = (Ether(src=str(self.router_mac),
1431 dst=self.pg0.remote_mac) /
1432 IPv6(dst=eps[0].fip6,
1434 UDP(sport=1234, dport=1234) /
1437 self.send_and_expect_unnatted6(
1439 pkt_inter_epg_220_from_global * NUM_PKTS,
1444 # From a local VM to another local VM using resp. public addresses:
1447 pkt_intra_epg_220_global = (Ether(src=self.pg0.remote_mac,
1448 dst=str(self.router_mac)) /
1451 UDP(sport=1234, dport=1234) /
1454 self.send_and_expect_double_natted(eps[0].itf,
1455 pkt_intra_epg_220_global * NUM_PKTS,
1460 pkt_intra_epg_220_global = (Ether(src=self.pg0.remote_mac,
1461 dst=str(self.router_mac)) /
1462 IPv6(src=eps[0].ip6,
1464 UDP(sport=1234, dport=1234) /
1467 self.send_and_expect_double_natted6(
1469 pkt_intra_epg_220_global * NUM_PKTS,
1477 self.vapi.nat44_plugin_enable_disable(enable=0)
1480 # del static mappings for each EP from the 10/8 to 11/8 network
1481 flags = self.nat_config_flags.NAT_IS_ADDR_ONLY
1482 self.vapi.nat66_add_del_static_mapping(
1483 local_ip_address=ep.ip6,
1484 external_ip_address=ep.fip6,
1488 # IP config on the BVI interfaces
1489 if epg != epgs[0] and epg != epgs[3]:
1490 flags = self.nat_config_flags.NAT_IS_INSIDE
1491 self.vapi.nat66_add_del_interface(
1492 sw_if_index=epg.bvi.sw_if_index,
1493 flags=flags, is_add=0)
1495 for recirc in recircs:
1496 self.vapi.nat66_add_del_interface(
1497 sw_if_index=recirc.recirc.sw_if_index, is_add=0)
1499 def wait_for_ep_timeout(self, sw_if_index=None, ip=None, mac=None,
1500 tep=None, n_tries=100, s_time=1):
1501 # only learnt EP can timeout
1502 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
1503 flags = ep_flags.GBP_API_ENDPOINT_FLAG_LEARNT
1505 if not find_gbp_endpoint(self, sw_if_index, ip, mac, tep=tep,
1508 n_tries = n_tries - 1
1510 self.assertFalse(find_gbp_endpoint(self, sw_if_index, ip, mac, tep=tep,
1514 def test_gbp_learn_l2(self):
1515 """ GBP L2 Endpoint Learning """
1517 drop_no_contract = self.statistics.get_err_counter(
1518 '/err/gbp-policy-port/drop-no-contract')
1519 allow_intra_class = self.statistics.get_err_counter(
1520 '/err/gbp-policy-port/allow-intra-sclass')
1522 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
1523 learnt = [{'mac': '00:00:11:11:11:01',
1525 'ip6': '2001:10::2'},
1526 {'mac': '00:00:11:11:11:02',
1528 'ip6': '2001:10::3'}]
1533 gt4 = VppIpTable(self, 1)
1534 gt4.add_vpp_config()
1535 gt6 = VppIpTable(self, 1, is_ip6=True)
1536 gt6.add_vpp_config()
1538 rd1 = VppGbpRouteDomain(self, 1, 401, gt4, gt6)
1539 rd1.add_vpp_config()
1542 # Pg2 hosts the vxlan tunnel, hosts on pg2 to act as TEPs
1543 # Pg3 hosts the IP4 UU-flood VXLAN tunnel
1544 # Pg4 hosts the IP6 UU-flood VXLAN tunnel
1546 self.pg2.config_ip4()
1547 self.pg2.resolve_arp()
1548 self.pg2.generate_remote_hosts(4)
1549 self.pg2.configure_ipv4_neighbors()
1550 self.pg3.config_ip4()
1551 self.pg3.resolve_arp()
1552 self.pg4.config_ip4()
1553 self.pg4.resolve_arp()
1556 # Add a mcast destination VXLAN-GBP tunnel for B&M traffic
1558 tun_bm = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
1561 tun_bm.add_vpp_config()
1564 # a GBP bridge domain with a BVI and a UU-flood interface
1566 bd1 = VppBridgeDomain(self, 1)
1567 bd1.add_vpp_config()
1568 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0,
1570 gbd1.add_vpp_config()
1572 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1573 self.logger.info(self.vapi.cli("sh gbp bridge"))
1575 # ... and has a /32 applied
1576 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
1577 ip_addr.add_vpp_config()
1580 # The Endpoint-group in which we are learning endpoints
1582 epg_220 = VppGbpEndpointGroup(self, 220, 112, rd1, gbd1,
1586 VppGbpEndpointRetention(4))
1587 epg_220.add_vpp_config()
1588 epg_330 = VppGbpEndpointGroup(self, 330, 113, rd1, gbd1,
1592 VppGbpEndpointRetention(4))
1593 epg_330.add_vpp_config()
1596 # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
1599 vx_tun_l2_1 = VppGbpVxlanTunnel(
1600 self, 99, bd1.bd_id,
1601 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L2,
1603 vx_tun_l2_1.add_vpp_config()
1606 # A static endpoint that the learnt endpoints are trying to
1609 ep = VppGbpEndpoint(self, self.pg0,
1611 "10.0.0.127", "11.0.0.127",
1612 "2001:10::1", "3001::1")
1615 self.assertTrue(find_route(self, ep.ip4, 32, table_id=1))
1617 # a packet with an sclass from an unknown EPG
1618 p = (Ether(src=self.pg2.remote_mac,
1619 dst=self.pg2.local_mac) /
1620 IP(src=self.pg2.remote_hosts[0].ip4,
1621 dst=self.pg2.local_ip4) /
1622 UDP(sport=1234, dport=48879) /
1623 VXLAN(vni=99, gpid=88, flags=0x88) /
1624 Ether(src=learnt[0]["mac"], dst=ep.mac) /
1625 IP(src=learnt[0]["ip"], dst=ep.ip4) /
1626 UDP(sport=1234, dport=1234) /
1629 self.send_and_assert_no_replies(self.pg2, p)
1631 self.logger.info(self.vapi.cli("sh error"))
1632 self.assert_error_counter_equal(
1633 '/err/gbp-policy-port/drop-no-contract',
1634 drop_no_contract + 1)
1637 # we should not have learnt a new tunnel endpoint, since
1638 # the EPG was not learnt.
1640 self.assertEqual(INDEX_INVALID,
1641 find_vxlan_gbp_tunnel(self,
1643 self.pg2.remote_hosts[0].ip4,
1646 # ep is not learnt, because the EPG is unknown
1647 self.assertEqual(len(self.vapi.gbp_endpoint_dump()), 1)
1650 # Learn new EPs from IP packets
1652 for ii, l in enumerate(learnt):
1653 # a packet with an sclass from a known EPG
1654 # arriving on an unknown TEP
1655 p = (Ether(src=self.pg2.remote_mac,
1656 dst=self.pg2.local_mac) /
1657 IP(src=self.pg2.remote_hosts[1].ip4,
1658 dst=self.pg2.local_ip4) /
1659 UDP(sport=1234, dport=48879) /
1660 VXLAN(vni=99, gpid=112, flags=0x88) /
1661 Ether(src=l['mac'], dst=ep.mac) /
1662 IP(src=l['ip'], dst=ep.ip4) /
1663 UDP(sport=1234, dport=1234) /
1666 rx = self.send_and_expect(self.pg2, [p], self.pg0)
1669 tep1_sw_if_index = find_vxlan_gbp_tunnel(
1672 self.pg2.remote_hosts[1].ip4,
1674 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
1677 # the EP is learnt via the learnt TEP
1678 # both from its MAC and its IP
1680 self.assertTrue(find_gbp_endpoint(self,
1681 vx_tun_l2_1.sw_if_index,
1683 self.assertTrue(find_gbp_endpoint(self,
1684 vx_tun_l2_1.sw_if_index,
1687 self.assert_error_counter_equal(
1688 '/err/gbp-policy-port/allow-intra-sclass',
1689 allow_intra_class + 2)
1691 self.logger.info(self.vapi.cli("show gbp endpoint"))
1692 self.logger.info(self.vapi.cli("show gbp vxlan"))
1693 self.logger.info(self.vapi.cli("show ip mfib"))
1696 # If we sleep for the threshold time, the learnt endpoints should
1700 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1704 # Learn new EPs from GARP packets received on the BD's mcast tunnel
1706 for ii, l in enumerate(learnt):
1707 # add some junk in the reserved field of the vxlan-header
1708 # next to the VNI. we should accept since reserved bits are
1710 p = (Ether(src=self.pg2.remote_mac,
1711 dst=self.pg2.local_mac) /
1712 IP(src=self.pg2.remote_hosts[1].ip4,
1714 UDP(sport=1234, dport=48879) /
1715 VXLAN(vni=88, reserved2=0x80, gpid=112, flags=0x88) /
1716 Ether(src=l['mac'], dst="ff:ff:ff:ff:ff:ff") /
1718 psrc=l['ip'], pdst=l['ip'],
1719 hwsrc=l['mac'], hwdst="ff:ff:ff:ff:ff:ff"))
1721 rx = self.send_and_expect(self.pg4, [p], self.pg0)
1724 tep1_sw_if_index = find_vxlan_gbp_tunnel(
1727 self.pg2.remote_hosts[1].ip4,
1729 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
1732 # the EP is learnt via the learnt TEP
1733 # both from its MAC and its IP
1735 self.assertTrue(find_gbp_endpoint(self,
1736 vx_tun_l2_1.sw_if_index,
1738 self.assertTrue(find_gbp_endpoint(self,
1739 vx_tun_l2_1.sw_if_index,
1743 # wait for the learnt endpoints to age out
1746 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1750 # Learn new EPs from L2 packets
1752 for ii, l in enumerate(learnt):
1753 # a packet with an sclass from a known EPG
1754 # arriving on an unknown TEP
1755 p = (Ether(src=self.pg2.remote_mac,
1756 dst=self.pg2.local_mac) /
1757 IP(src=self.pg2.remote_hosts[1].ip4,
1758 dst=self.pg2.local_ip4) /
1759 UDP(sport=1234, dport=48879) /
1760 VXLAN(vni=99, gpid=112, flags=0x88) /
1761 Ether(src=l['mac'], dst=ep.mac) /
1764 rx = self.send_and_expect(self.pg2, [p], self.pg0)
1767 tep1_sw_if_index = find_vxlan_gbp_tunnel(
1770 self.pg2.remote_hosts[1].ip4,
1772 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
1775 # the EP is learnt via the learnt TEP
1776 # both from its MAC and its IP
1778 self.assertTrue(find_gbp_endpoint(self,
1779 vx_tun_l2_1.sw_if_index,
1782 self.logger.info(self.vapi.cli("show gbp endpoint"))
1783 self.logger.info(self.vapi.cli("show gbp vxlan"))
1784 self.logger.info(self.vapi.cli("show vxlan-gbp tunnel"))
1787 # wait for the learnt endpoints to age out
1790 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1794 # repeat. the do not learn bit is set so the EPs are not learnt
1797 # a packet with an sclass from a known EPG
1798 p = (Ether(src=self.pg2.remote_mac,
1799 dst=self.pg2.local_mac) /
1800 IP(src=self.pg2.remote_hosts[1].ip4,
1801 dst=self.pg2.local_ip4) /
1802 UDP(sport=1234, dport=48879) /
1803 VXLAN(vni=99, gpid=112, flags=0x88, gpflags="D") /
1804 Ether(src=l['mac'], dst=ep.mac) /
1805 IP(src=l['ip'], dst=ep.ip4) /
1806 UDP(sport=1234, dport=1234) /
1809 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
1812 self.assertFalse(find_gbp_endpoint(self,
1813 vx_tun_l2_1.sw_if_index,
1820 # a packet with an sclass from a known EPG
1821 # set a reserved bit in addition to the G and I
1822 # reserved bits should not be checked on rx.
1823 p = (Ether(src=self.pg2.remote_mac,
1824 dst=self.pg2.local_mac) /
1825 IP(src=self.pg2.remote_hosts[1].ip4,
1826 dst=self.pg2.local_ip4) /
1827 UDP(sport=1234, dport=48879) /
1828 VXLAN(vni=99, gpid=112, flags=0xc8) /
1829 Ether(src=l['mac'], dst=ep.mac) /
1830 IP(src=l['ip'], dst=ep.ip4) /
1831 UDP(sport=1234, dport=1234) /
1834 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
1836 self.assertTrue(find_gbp_endpoint(self,
1837 vx_tun_l2_1.sw_if_index,
1841 # Static EP replies to dynamics
1843 self.logger.info(self.vapi.cli("sh l2fib bd_id 1"))
1845 p = (Ether(src=ep.mac, dst=l['mac']) /
1846 IP(dst=l['ip'], src=ep.ip4) /
1847 UDP(sport=1234, dport=1234) /
1850 rxs = self.send_and_expect(self.pg0, p * 17, self.pg2)
1853 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
1854 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
1855 self.assertEqual(rx[UDP].dport, 48879)
1856 # the UDP source port is a random value for hashing
1857 self.assertEqual(rx[VXLAN].gpid, 112)
1858 self.assertEqual(rx[VXLAN].vni, 99)
1859 self.assertTrue(rx[VXLAN].flags.G)
1860 self.assertTrue(rx[VXLAN].flags.Instance)
1861 self.assertTrue(rx[VXLAN].gpflags.A)
1862 self.assertFalse(rx[VXLAN].gpflags.D)
1865 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1869 # repeat in the other EPG
1870 # there's no contract between 220 and 330, but the A-bit is set
1871 # so the packet is cleared for delivery
1874 # a packet with an sclass from a known EPG
1875 p = (Ether(src=self.pg2.remote_mac,
1876 dst=self.pg2.local_mac) /
1877 IP(src=self.pg2.remote_hosts[1].ip4,
1878 dst=self.pg2.local_ip4) /
1879 UDP(sport=1234, dport=48879) /
1880 VXLAN(vni=99, gpid=113, flags=0x88, gpflags='A') /
1881 Ether(src=l['mac'], dst=ep.mac) /
1882 IP(src=l['ip'], dst=ep.ip4) /
1883 UDP(sport=1234, dport=1234) /
1886 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
1888 self.assertTrue(find_gbp_endpoint(self,
1889 vx_tun_l2_1.sw_if_index,
1893 # static EP cannot reach the learnt EPs since there is no contract
1894 # only test 1 EP as the others could timeout
1896 p = (Ether(src=ep.mac, dst=l['mac']) /
1897 IP(dst=learnt[0]['ip'], src=ep.ip4) /
1898 UDP(sport=1234, dport=1234) /
1901 self.send_and_assert_no_replies(self.pg0, [p])
1904 # refresh the entries after the check for no replies above
1907 # a packet with an sclass from a known EPG
1908 p = (Ether(src=self.pg2.remote_mac,
1909 dst=self.pg2.local_mac) /
1910 IP(src=self.pg2.remote_hosts[1].ip4,
1911 dst=self.pg2.local_ip4) /
1912 UDP(sport=1234, dport=48879) /
1913 VXLAN(vni=99, gpid=113, flags=0x88, gpflags='A') /
1914 Ether(src=l['mac'], dst=ep.mac) /
1915 IP(src=l['ip'], dst=ep.ip4) /
1916 UDP(sport=1234, dport=1234) /
1919 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
1921 self.assertTrue(find_gbp_endpoint(self,
1922 vx_tun_l2_1.sw_if_index,
1926 # Add the contract so they can talk
1928 rule = AclRule(is_permit=1, proto=17)
1929 rule2 = AclRule(src_prefix=IPv6Network((0, 0)),
1930 dst_prefix=IPv6Network((0, 0)), is_permit=1, proto=17)
1931 acl = VppAcl(self, rules=[rule, rule2])
1932 acl.add_vpp_config()
1934 c1 = VppGbpContract(
1935 self, 401, epg_220.sclass, epg_330.sclass, acl.acl_index,
1936 [VppGbpContractRule(
1937 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1938 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1941 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1942 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1944 [ETH_P_IP, ETH_P_IPV6])
1948 p = (Ether(src=ep.mac, dst=l['mac']) /
1949 IP(dst=l['ip'], src=ep.ip4) /
1950 UDP(sport=1234, dport=1234) /
1953 self.send_and_expect(self.pg0, [p], self.pg2)
1956 # send UU packets from the local EP
1958 self.logger.info(self.vapi.cli("sh gbp bridge"))
1959 self.logger.info(self.vapi.cli("sh bridge-domain 1 detail"))
1960 p_uu = (Ether(src=ep.mac, dst="00:11:11:11:11:11") /
1961 IP(dst="10.0.0.133", src=ep.ip4) /
1962 UDP(sport=1234, dport=1234) /
1964 rxs = self.send_and_expect(ep.itf, [p_uu], gbd1.uu_fwd)
1966 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1968 p_bm = (Ether(src=ep.mac, dst="ff:ff:ff:ff:ff:ff") /
1969 IP(dst="10.0.0.133", src=ep.ip4) /
1970 UDP(sport=1234, dport=1234) /
1972 rxs = self.send_and_expect_only(ep.itf, [p_bm], tun_bm.mcast_itf)
1975 self.assertEqual(rx[IP].src, self.pg4.local_ip4)
1976 self.assertEqual(rx[IP].dst, "239.1.1.1")
1977 self.assertEqual(rx[UDP].dport, 48879)
1978 # the UDP source port is a random value for hashing
1979 self.assertEqual(rx[VXLAN].gpid, 112)
1980 self.assertEqual(rx[VXLAN].vni, 88)
1981 self.assertTrue(rx[VXLAN].flags.G)
1982 self.assertTrue(rx[VXLAN].flags.Instance)
1983 self.assertFalse(rx[VXLAN].gpflags.A)
1984 self.assertFalse(rx[VXLAN].gpflags.D)
1986 rule = AclRule(is_permit=1, proto=17)
1987 rule2 = AclRule(src_prefix=IPv6Network((0, 0)),
1988 dst_prefix=IPv6Network((0, 0)), is_permit=1, proto=17)
1989 acl = VppAcl(self, rules=[rule, rule2])
1990 acl.add_vpp_config()
1992 c2 = VppGbpContract(
1993 self, 401, epg_330.sclass, epg_220.sclass, acl.acl_index,
1994 [VppGbpContractRule(
1995 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1996 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1999 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2000 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2002 [ETH_P_IP, ETH_P_IPV6])
2006 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
2009 # Check v6 Endpoints learning
2012 # a packet with an sclass from a known EPG
2013 p = (Ether(src=self.pg2.remote_mac,
2014 dst=self.pg2.local_mac) /
2015 IP(src=self.pg2.remote_hosts[1].ip4,
2016 dst=self.pg2.local_ip4) /
2017 UDP(sport=1234, dport=48879) /
2018 VXLAN(vni=99, gpid=113, flags=0x88) /
2019 Ether(src=l['mac'], dst=ep.mac) /
2020 IPv6(src=l['ip6'], dst=ep.ip6) /
2021 UDP(sport=1234, dport=1234) /
2024 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
2025 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
2027 self.assertTrue(find_gbp_endpoint(
2029 vx_tun_l2_1.sw_if_index,
2031 tep=[self.pg2.local_ip4,
2032 self.pg2.remote_hosts[1].ip4]))
2034 self.logger.info(self.vapi.cli("sh int"))
2035 self.logger.info(self.vapi.cli("sh vxlan-gbp tunnel"))
2036 self.logger.info(self.vapi.cli("sh gbp vxlan"))
2037 self.logger.info(self.vapi.cli("sh gbp endpoint"))
2038 self.logger.info(self.vapi.cli("sh gbp interface"))
2041 # EP moves to a different TEP
2044 # a packet with an sclass from a known EPG
2045 p = (Ether(src=self.pg2.remote_mac,
2046 dst=self.pg2.local_mac) /
2047 IP(src=self.pg2.remote_hosts[2].ip4,
2048 dst=self.pg2.local_ip4) /
2049 UDP(sport=1234, dport=48879) /
2050 VXLAN(vni=99, gpid=113, flags=0x88) /
2051 Ether(src=l['mac'], dst=ep.mac) /
2052 IPv6(src=l['ip6'], dst=ep.ip6) /
2053 UDP(sport=1234, dport=1234) /
2056 rx = self.send_and_expect(self.pg2, p * 1, self.pg0)
2057 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
2059 self.assertTrue(find_gbp_endpoint(
2061 vx_tun_l2_1.sw_if_index,
2064 tep=[self.pg2.local_ip4,
2065 self.pg2.remote_hosts[2].ip4]))
2068 # v6 remote EP reachability
2071 p = (Ether(src=ep.mac, dst=l['mac']) /
2072 IPv6(dst=l['ip6'], src=ep.ip6) /
2073 UDP(sport=1234, dport=1234) /
2076 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
2079 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2080 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[2].ip4)
2081 self.assertEqual(rx[UDP].dport, 48879)
2082 # the UDP source port is a random value for hashing
2083 self.assertEqual(rx[VXLAN].gpid, 112)
2084 self.assertEqual(rx[VXLAN].vni, 99)
2085 self.assertTrue(rx[VXLAN].flags.G)
2086 self.assertTrue(rx[VXLAN].flags.Instance)
2087 self.assertTrue(rx[VXLAN].gpflags.A)
2088 self.assertFalse(rx[VXLAN].gpflags.D)
2089 self.assertEqual(rx[IPv6].dst, l['ip6'])
2095 # a packet with an sclass from a known EPG
2096 p = (Ether(src=self.pg2.remote_mac,
2097 dst=self.pg2.local_mac) /
2098 IP(src=self.pg2.remote_hosts[2].ip4,
2099 dst=self.pg2.local_ip4) /
2100 UDP(sport=1234, dport=48879) /
2101 VXLAN(vni=99, gpid=112, flags=0x88) /
2102 Ether(src=l['mac'], dst=ep.mac) /
2103 IPv6(src=l['ip6'], dst=ep.ip6) /
2104 UDP(sport=1234, dport=1234) /
2107 rx = self.send_and_expect(self.pg2, p * 1, self.pg0)
2108 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
2110 self.assertTrue(find_gbp_endpoint(
2112 vx_tun_l2_1.sw_if_index,
2115 tep=[self.pg2.local_ip4,
2116 self.pg2.remote_hosts[2].ip4]))
2119 # check reachability and contract intra-epg
2121 allow_intra_class = self.statistics.get_err_counter(
2122 '/err/gbp-policy-mac/allow-intra-sclass')
2125 p = (Ether(src=ep.mac, dst=l['mac']) /
2126 IPv6(dst=l['ip6'], src=ep.ip6) /
2127 UDP(sport=1234, dport=1234) /
2130 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
2133 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2134 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[2].ip4)
2135 self.assertEqual(rx[UDP].dport, 48879)
2136 self.assertEqual(rx[VXLAN].gpid, 112)
2137 self.assertEqual(rx[VXLAN].vni, 99)
2138 self.assertTrue(rx[VXLAN].flags.G)
2139 self.assertTrue(rx[VXLAN].flags.Instance)
2140 self.assertTrue(rx[VXLAN].gpflags.A)
2141 self.assertFalse(rx[VXLAN].gpflags.D)
2142 self.assertEqual(rx[IPv6].dst, l['ip6'])
2144 allow_intra_class += NUM_PKTS
2146 self.assert_error_counter_equal(
2147 '/err/gbp-policy-mac/allow-intra-sclass',
2154 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
2156 self.pg2.unconfig_ip4()
2157 self.pg3.unconfig_ip4()
2158 self.pg4.unconfig_ip4()
2160 def test_gbp_contract(self):
2161 """ GBP Contracts """
2166 gt4 = VppIpTable(self, 0)
2167 gt4.add_vpp_config()
2168 gt6 = VppIpTable(self, 0, is_ip6=True)
2169 gt6.add_vpp_config()
2171 rd0 = VppGbpRouteDomain(self, 0, 400, gt4, gt6, None, None)
2173 rd0.add_vpp_config()
2178 bd1 = VppBridgeDomain(self, 1, arp_term=0)
2179 bd2 = VppBridgeDomain(self, 2, arp_term=0)
2181 bd1.add_vpp_config()
2182 bd2.add_vpp_config()
2184 gbd1 = VppGbpBridgeDomain(self, bd1, rd0, self.loop0)
2185 gbd2 = VppGbpBridgeDomain(self, bd2, rd0, self.loop1)
2187 gbd1.add_vpp_config()
2188 gbd2.add_vpp_config()
2191 # 3 EPGs, 2 of which share a BD.
2193 epgs = [VppGbpEndpointGroup(self, 220, 1220, rd0, gbd1,
2195 "10.0.0.128", "2001:10::128"),
2196 VppGbpEndpointGroup(self, 221, 1221, rd0, gbd1,
2198 "10.0.1.128", "2001:10:1::128"),
2199 VppGbpEndpointGroup(self, 222, 1222, rd0, gbd2,
2201 "10.0.2.128", "2001:10:2::128")]
2203 # 4 end-points, 2 in the same subnet, 3 in the same BD
2205 eps = [VppGbpEndpoint(self, self.pg0,
2207 "10.0.0.1", "11.0.0.1",
2208 "2001:10::1", "3001::1"),
2209 VppGbpEndpoint(self, self.pg1,
2211 "10.0.0.2", "11.0.0.2",
2212 "2001:10::2", "3001::2"),
2213 VppGbpEndpoint(self, self.pg2,
2215 "10.0.1.1", "11.0.0.3",
2216 "2001:10:1::1", "3001::3"),
2217 VppGbpEndpoint(self, self.pg3,
2219 "10.0.2.1", "11.0.0.4",
2220 "2001:10:2::1", "3001::4")]
2223 # Config related to each of the EPGs
2226 # IP config on the BVI interfaces
2228 b4 = VppIpInterfaceBind(self, epg.bvi,
2229 epg.rd.t4).add_vpp_config()
2230 b6 = VppIpInterfaceBind(self, epg.bvi,
2231 epg.rd.t6).add_vpp_config()
2232 epg.bvi.set_mac(self.router_mac)
2234 if_ip4 = VppIpInterfaceAddress(self, epg.bvi,
2236 bind=b4).add_vpp_config()
2237 if_ip6 = VppIpInterfaceAddress(self, epg.bvi,
2239 bind=b6).add_vpp_config()
2241 # add the BD ARP termination entry for BVI IP
2242 epg.bd_arp_ip4 = VppBridgeDomainArpEntry(self, epg.bd.bd,
2243 str(self.router_mac),
2245 epg.bd_arp_ip4.add_vpp_config()
2248 epg.add_vpp_config()
2256 self.logger.info(self.vapi.cli("show gbp endpoint"))
2257 self.logger.info(self.vapi.cli("show interface"))
2258 self.logger.info(self.vapi.cli("show br"))
2261 # Intra epg allowed without contract
2263 pkt_intra_epg_220_to_220 = (Ether(src=self.pg0.remote_mac,
2264 dst=self.pg1.remote_mac) /
2267 UDP(sport=1234, dport=1234) /
2270 self.send_and_expect_bridged(self.pg0,
2271 pkt_intra_epg_220_to_220 * 65,
2274 pkt_intra_epg_220_to_220 = (Ether(src=self.pg0.remote_mac,
2275 dst=self.pg1.remote_mac) /
2276 IPv6(src=eps[0].ip6,
2278 UDP(sport=1234, dport=1234) /
2281 self.send_and_expect_bridged6(self.pg0,
2282 pkt_intra_epg_220_to_220 * 65,
2286 # Inter epg denied without contract
2288 pkt_inter_epg_220_to_221 = (Ether(src=self.pg0.remote_mac,
2289 dst=self.pg2.remote_mac) /
2292 UDP(sport=1234, dport=1234) /
2295 self.send_and_assert_no_replies(self.pg0, pkt_inter_epg_220_to_221)
2298 # A uni-directional contract from EPG 220 -> 221
2300 rule = AclRule(is_permit=1, proto=17)
2301 rule2 = AclRule(src_prefix=IPv6Network((0, 0)),
2302 dst_prefix=IPv6Network((0, 0)), is_permit=1, proto=17)
2303 rule3 = AclRule(is_permit=1, proto=1)
2304 acl = VppAcl(self, rules=[rule, rule2, rule3])
2305 acl.add_vpp_config()
2307 c1 = VppGbpContract(
2308 self, 400, epgs[0].sclass, epgs[1].sclass, acl.acl_index,
2309 [VppGbpContractRule(
2310 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2311 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2314 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2315 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2318 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2319 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2321 [ETH_P_IP, ETH_P_IPV6])
2324 self.send_and_expect_bridged(eps[0].itf,
2325 pkt_inter_epg_220_to_221 * 65,
2328 pkt_inter_epg_220_to_222 = (Ether(src=self.pg0.remote_mac,
2329 dst=str(self.router_mac)) /
2332 UDP(sport=1234, dport=1234) /
2334 self.send_and_assert_no_replies(eps[0].itf,
2335 pkt_inter_epg_220_to_222 * 65)
2338 # ping router IP in different BD
2340 pkt_router_ping_220_to_221 = (Ether(src=self.pg0.remote_mac,
2341 dst=str(self.router_mac)) /
2343 dst=epgs[1].bvi_ip4) /
2344 ICMP(type='echo-request'))
2346 self.send_and_expect(self.pg0, [pkt_router_ping_220_to_221], self.pg0)
2348 pkt_router_ping_220_to_221 = (Ether(src=self.pg0.remote_mac,
2349 dst=str(self.router_mac)) /
2350 IPv6(src=eps[0].ip6,
2351 dst=epgs[1].bvi_ip6) /
2352 ICMPv6EchoRequest())
2354 self.send_and_expect(self.pg0, [pkt_router_ping_220_to_221], self.pg0)
2357 # contract for the return direction
2359 c2 = VppGbpContract(
2360 self, 400, epgs[1].sclass, epgs[0].sclass, acl.acl_index,
2361 [VppGbpContractRule(
2362 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2363 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2366 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2367 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2369 [ETH_P_IP, ETH_P_IPV6])
2372 self.send_and_expect_bridged(eps[0].itf,
2373 pkt_inter_epg_220_to_221 * 65,
2375 pkt_inter_epg_221_to_220 = (Ether(src=self.pg2.remote_mac,
2376 dst=self.pg0.remote_mac) /
2379 UDP(sport=1234, dport=1234) /
2381 self.send_and_expect_bridged(eps[2].itf,
2382 pkt_inter_epg_221_to_220 * 65,
2384 pkt_inter_epg_221_to_220 = (Ether(src=self.pg2.remote_mac,
2385 dst=str(self.router_mac)) /
2388 UDP(sport=1234, dport=1234) /
2390 self.send_and_expect_routed(eps[2].itf,
2391 pkt_inter_epg_221_to_220 * 65,
2393 str(self.router_mac))
2394 pkt_inter_epg_221_to_220 = (Ether(src=self.pg2.remote_mac,
2395 dst=str(self.router_mac)) /
2396 IPv6(src=eps[2].ip6,
2398 UDP(sport=1234, dport=1234) /
2400 self.send_and_expect_routed6(eps[2].itf,
2401 pkt_inter_epg_221_to_220 * 65,
2403 str(self.router_mac))
2406 # contract between 220 and 222 uni-direction
2408 c3 = VppGbpContract(
2409 self, 400, epgs[0].sclass, epgs[2].sclass, acl.acl_index,
2410 [VppGbpContractRule(
2411 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2412 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2415 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2416 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2418 [ETH_P_IP, ETH_P_IPV6])
2421 self.send_and_expect(eps[0].itf,
2422 pkt_inter_epg_220_to_222 * 65,
2425 c3.remove_vpp_config()
2426 c1.remove_vpp_config()
2427 c2.remove_vpp_config()
2428 acl.remove_vpp_config()
2430 def test_gbp_bd_drop_flags(self):
2431 """ GBP BD drop flags """
2436 gt4 = VppIpTable(self, 1)
2437 gt4.add_vpp_config()
2438 gt6 = VppIpTable(self, 1, is_ip6=True)
2439 gt6.add_vpp_config()
2441 rd1 = VppGbpRouteDomain(self, 1, 401, gt4, gt6)
2442 rd1.add_vpp_config()
2445 # a GBP bridge domain with a BVI only
2447 bd1 = VppBridgeDomain(self, 1)
2448 bd1.add_vpp_config()
2450 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0,
2452 uu_drop=True, bm_drop=True)
2453 gbd1.add_vpp_config()
2455 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2456 self.logger.info(self.vapi.cli("sh gbp bridge"))
2458 # ... and has a /32 applied
2459 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi,
2460 "10.0.0.128", 32).add_vpp_config()
2463 # The Endpoint-group
2465 epg_220 = VppGbpEndpointGroup(self, 220, 112, rd1, gbd1,
2469 VppGbpEndpointRetention(3))
2470 epg_220.add_vpp_config()
2472 ep = VppGbpEndpoint(self, self.pg0,
2474 "10.0.0.127", "11.0.0.127",
2475 "2001:10::1", "3001::1")
2479 # send UU/BM packet from the local EP with UU drop and BM drop enabled
2482 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2483 self.logger.info(self.vapi.cli("sh gbp bridge"))
2484 p_uu = (Ether(src=ep.mac, dst="00:11:11:11:11:11") /
2485 IP(dst="10.0.0.133", src=ep.ip4) /
2486 UDP(sport=1234, dport=1234) /
2488 self.send_and_assert_no_replies(ep.itf, [p_uu])
2490 p_bm = (Ether(src=ep.mac, dst="ff:ff:ff:ff:ff:ff") /
2491 IP(dst="10.0.0.133", src=ep.ip4) /
2492 UDP(sport=1234, dport=1234) /
2494 self.send_and_assert_no_replies(ep.itf, [p_bm])
2496 self.pg3.unconfig_ip4()
2498 self.logger.info(self.vapi.cli("sh int"))
2500 def test_gbp_bd_arp_flags(self):
2501 """ GBP BD arp flags """
2506 gt4 = VppIpTable(self, 1)
2507 gt4.add_vpp_config()
2508 gt6 = VppIpTable(self, 1, is_ip6=True)
2509 gt6.add_vpp_config()
2511 rd1 = VppGbpRouteDomain(self, 1, 401, gt4, gt6)
2512 rd1.add_vpp_config()
2515 # Pg4 hosts the IP6 UU-flood VXLAN tunnel
2517 self.pg4.config_ip4()
2518 self.pg4.resolve_arp()
2521 # Add a mcast destination VXLAN-GBP tunnel for B&M traffic
2523 tun_uu = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
2526 tun_uu.add_vpp_config()
2529 # a GBP bridge domain with a BVI and a UU-flood interface
2531 bd1 = VppBridgeDomain(self, 1)
2532 bd1.add_vpp_config()
2534 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0,
2537 gbd1.add_vpp_config()
2539 # ... and has a /32 applied
2540 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi,
2541 "10.0.0.128", 32).add_vpp_config()
2544 # The Endpoint-group
2546 epg_220 = VppGbpEndpointGroup(self, 220, 112, rd1, gbd1,
2550 VppGbpEndpointRetention(2))
2551 epg_220.add_vpp_config()
2553 ep = VppGbpEndpoint(self, self.pg0,
2555 "10.0.0.127", "11.0.0.127",
2556 "2001:10::1", "3001::1")
2560 # send ARP packet from the local EP expect it on the uu interface
2562 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2563 self.logger.info(self.vapi.cli("sh gbp bridge"))
2564 p_arp = (Ether(src=ep.mac, dst="ff:ff:ff:ff:ff:ff") /
2566 psrc=ep.ip4, pdst="10.0.0.99",
2568 hwdst="ff:ff:ff:ff:ff:ff"))
2569 self.send_and_expect(ep.itf, [p_arp], self.pg4)
2571 self.pg4.unconfig_ip4()
2573 def test_gbp_learn_vlan_l2(self):
2574 """ GBP L2 Endpoint w/ VLANs"""
2576 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
2577 learnt = [{'mac': '00:00:11:11:11:01',
2579 'ip6': '2001:10::2'},
2580 {'mac': '00:00:11:11:11:02',
2582 'ip6': '2001:10::3'}]
2587 gt4 = VppIpTable(self, 1)
2588 gt4.add_vpp_config()
2589 gt6 = VppIpTable(self, 1, is_ip6=True)
2590 gt6.add_vpp_config()
2592 rd1 = VppGbpRouteDomain(self, 1, 401, gt4, gt6)
2593 rd1.add_vpp_config()
2596 # Pg2 hosts the vxlan tunnel, hosts on pg2 to act as TEPs
2598 self.pg2.config_ip4()
2599 self.pg2.resolve_arp()
2600 self.pg2.generate_remote_hosts(4)
2601 self.pg2.configure_ipv4_neighbors()
2602 self.pg3.config_ip4()
2603 self.pg3.resolve_arp()
2606 # The EP will be on a vlan sub-interface
2608 vlan_11 = VppDot1QSubint(self, self.pg0, 11)
2610 self.vapi.l2_interface_vlan_tag_rewrite(
2611 sw_if_index=vlan_11.sw_if_index, vtr_op=L2_VTR_OP.L2_POP_1,
2614 bd_uu_fwd = VppVxlanGbpTunnel(self, self.pg3.local_ip4,
2615 self.pg3.remote_ip4, 116)
2616 bd_uu_fwd.add_vpp_config()
2619 # a GBP bridge domain with a BVI and a UU-flood interface
2620 # The BD is marked as do not learn, so no endpoints are ever
2621 # learnt in this BD.
2623 bd1 = VppBridgeDomain(self, 1)
2624 bd1.add_vpp_config()
2625 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0, bd_uu_fwd,
2627 gbd1.add_vpp_config()
2629 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2630 self.logger.info(self.vapi.cli("sh gbp bridge"))
2632 # ... and has a /32 applied
2633 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi,
2634 "10.0.0.128", 32).add_vpp_config()
2637 # The Endpoint-group in which we are learning endpoints
2639 epg_220 = VppGbpEndpointGroup(self, 220, 441, rd1, gbd1,
2643 VppGbpEndpointRetention(4))
2644 epg_220.add_vpp_config()
2647 # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
2650 vx_tun_l2_1 = VppGbpVxlanTunnel(
2651 self, 99, bd1.bd_id,
2652 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L2,
2654 vx_tun_l2_1.add_vpp_config()
2657 # A static endpoint that the learnt endpoints are trying to
2660 ep = VppGbpEndpoint(self, vlan_11,
2662 "10.0.0.127", "11.0.0.127",
2663 "2001:10::1", "3001::1")
2666 self.assertTrue(find_route(self, ep.ip4, 32, table_id=1))
2669 # Send to the static EP
2671 for ii, l in enumerate(learnt):
2672 # a packet with an sclass from a known EPG
2673 # arriving on an unknown TEP
2674 p = (Ether(src=self.pg2.remote_mac,
2675 dst=self.pg2.local_mac) /
2676 IP(src=self.pg2.remote_hosts[1].ip4,
2677 dst=self.pg2.local_ip4) /
2678 UDP(sport=1234, dport=48879) /
2679 VXLAN(vni=99, gpid=441, flags=0x88) /
2680 Ether(src=l['mac'], dst=ep.mac) /
2681 IP(src=l['ip'], dst=ep.ip4) /
2682 UDP(sport=1234, dport=1234) /
2685 rxs = self.send_and_expect(self.pg2, [p], self.pg0)
2688 # packet to EP has the EP's vlan tag
2691 self.assertEqual(rx[Dot1Q].vlan, 11)
2694 # the EP is not learnt since the BD setting prevents it
2697 self.assertFalse(find_gbp_endpoint(self,
2698 vx_tun_l2_1.sw_if_index,
2700 self.assertEqual(INDEX_INVALID,
2701 find_vxlan_gbp_tunnel(
2704 self.pg2.remote_hosts[1].ip4,
2707 self.assertEqual(len(self.vapi.gbp_endpoint_dump()), 1)
2711 # we didn't learn the remotes so they are sent to the UU-fwd
2714 p = (Ether(src=ep.mac, dst=l['mac']) /
2716 IP(dst=l['ip'], src=ep.ip4) /
2717 UDP(sport=1234, dport=1234) /
2720 rxs = self.send_and_expect(self.pg0, p * 17, self.pg3)
2723 self.assertEqual(rx[IP].src, self.pg3.local_ip4)
2724 self.assertEqual(rx[IP].dst, self.pg3.remote_ip4)
2725 self.assertEqual(rx[UDP].dport, 48879)
2726 # the UDP source port is a random value for hashing
2727 self.assertEqual(rx[VXLAN].gpid, 441)
2728 self.assertEqual(rx[VXLAN].vni, 116)
2729 self.assertTrue(rx[VXLAN].flags.G)
2730 self.assertTrue(rx[VXLAN].flags.Instance)
2731 self.assertFalse(rx[VXLAN].gpflags.A)
2732 self.assertFalse(rx[VXLAN].gpflags.D)
2734 self.pg2.unconfig_ip4()
2735 self.pg3.unconfig_ip4()
2737 def test_gbp_learn_l3(self):
2738 """ GBP L3 Endpoint Learning """
2740 self.vapi.cli("set logging class gbp level debug")
2742 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
2743 routed_dst_mac = "00:0c:0c:0c:0c:0c"
2744 routed_src_mac = "00:22:bd:f8:19:ff"
2746 learnt = [{'mac': '00:00:11:11:11:02',
2748 'ip6': '2001:10::2'},
2749 {'mac': '00:00:11:11:11:03',
2751 'ip6': '2001:10::3'}]
2756 t4 = VppIpTable(self, 1)
2758 t6 = VppIpTable(self, 1, True)
2761 tun_ip4_uu = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
2762 self.pg4.remote_ip4, 114)
2763 tun_ip6_uu = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
2764 self.pg4.remote_ip4, 116)
2765 tun_ip4_uu.add_vpp_config()
2766 tun_ip6_uu.add_vpp_config()
2768 rd1 = VppGbpRouteDomain(self, 2, 401, t4, t6, tun_ip4_uu, tun_ip6_uu)
2769 rd1.add_vpp_config()
2771 self.loop0.set_mac(self.router_mac)
2774 # Bind the BVI to the RD
2776 b4 = VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
2777 b6 = VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
2780 # Pg2 hosts the vxlan tunnel
2781 # hosts on pg2 to act as TEPs
2785 self.pg2.config_ip4()
2786 self.pg2.resolve_arp()
2787 self.pg2.generate_remote_hosts(4)
2788 self.pg2.configure_ipv4_neighbors()
2789 self.pg3.config_ip4()
2790 self.pg3.resolve_arp()
2791 self.pg4.config_ip4()
2792 self.pg4.resolve_arp()
2795 # a GBP bridge domain with a BVI and a UU-flood interface
2797 bd1 = VppBridgeDomain(self, 1)
2798 bd1.add_vpp_config()
2799 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0, self.pg3)
2800 gbd1.add_vpp_config()
2802 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2803 self.logger.info(self.vapi.cli("sh gbp bridge"))
2804 self.logger.info(self.vapi.cli("sh gbp route"))
2806 # ... and has a /32 and /128 applied
2807 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi,
2809 bind=b4).add_vpp_config()
2810 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi,
2811 "2001:10::128", 128,
2812 bind=b6).add_vpp_config()
2815 # The Endpoint-group in which we are learning endpoints
2817 epg_220 = VppGbpEndpointGroup(self, 220, 441, rd1, gbd1,
2821 VppGbpEndpointRetention(4))
2822 epg_220.add_vpp_config()
2825 # The VXLAN GBP tunnel is in L3 mode with learning enabled
2827 vx_tun_l3 = VppGbpVxlanTunnel(
2828 self, 101, rd1.rd_id,
2829 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
2831 vx_tun_l3.add_vpp_config()
2834 # A static endpoint that the learnt endpoints are trying to
2837 ep = VppGbpEndpoint(self, self.pg0,
2839 "10.0.0.127", "11.0.0.127",
2840 "2001:10::1", "3001::1")
2844 # learn some remote IPv4 EPs
2846 for ii, l in enumerate(learnt):
2847 # a packet with an sclass from a known EPG
2848 # arriving on an unknown TEP
2849 p = (Ether(src=self.pg2.remote_mac,
2850 dst=self.pg2.local_mac) /
2851 IP(src=self.pg2.remote_hosts[1].ip4,
2852 dst=self.pg2.local_ip4) /
2853 UDP(sport=1234, dport=48879) /
2854 VXLAN(vni=101, gpid=441, flags=0x88) /
2855 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2856 IP(src=l['ip'], dst=ep.ip4) /
2857 UDP(sport=1234, dport=1234) /
2860 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2863 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2866 self.pg2.remote_hosts[1].ip4,
2868 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2870 # endpoint learnt via the parent GBP-vxlan interface
2871 self.assertTrue(find_gbp_endpoint(self,
2872 vx_tun_l3._sw_if_index,
2876 # Static IPv4 EP replies to learnt
2879 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2880 IP(dst=l['ip'], src=ep.ip4) /
2881 UDP(sport=1234, dport=1234) /
2884 rxs = self.send_and_expect(self.pg0, p * 1, self.pg2)
2887 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2888 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2889 self.assertEqual(rx[UDP].dport, 48879)
2890 # the UDP source port is a random value for hashing
2891 self.assertEqual(rx[VXLAN].gpid, 441)
2892 self.assertEqual(rx[VXLAN].vni, 101)
2893 self.assertTrue(rx[VXLAN].flags.G)
2894 self.assertTrue(rx[VXLAN].flags.Instance)
2895 self.assertTrue(rx[VXLAN].gpflags.A)
2896 self.assertFalse(rx[VXLAN].gpflags.D)
2898 inner = rx[VXLAN].payload
2900 self.assertEqual(inner[Ether].src, routed_src_mac)
2901 self.assertEqual(inner[Ether].dst, routed_dst_mac)
2902 self.assertEqual(inner[IP].src, ep.ip4)
2903 self.assertEqual(inner[IP].dst, l['ip'])
2906 self.assertFalse(find_gbp_endpoint(self,
2911 # learn some remote IPv6 EPs
2913 for ii, l in enumerate(learnt):
2914 # a packet with an sclass from a known EPG
2915 # arriving on an unknown TEP
2916 p = (Ether(src=self.pg2.remote_mac,
2917 dst=self.pg2.local_mac) /
2918 IP(src=self.pg2.remote_hosts[1].ip4,
2919 dst=self.pg2.local_ip4) /
2920 UDP(sport=1234, dport=48879) /
2921 VXLAN(vni=101, gpid=441, flags=0x88) /
2922 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2923 IPv6(src=l['ip6'], dst=ep.ip6) /
2924 UDP(sport=1234, dport=1234) /
2927 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2930 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2933 self.pg2.remote_hosts[1].ip4,
2935 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2937 self.logger.info(self.vapi.cli("show gbp bridge"))
2938 self.logger.info(self.vapi.cli("show vxlan-gbp tunnel"))
2939 self.logger.info(self.vapi.cli("show gbp vxlan"))
2940 self.logger.info(self.vapi.cli("show int addr"))
2942 # endpoint learnt via the TEP
2943 self.assertTrue(find_gbp_endpoint(self, ip=l['ip6']))
2945 self.logger.info(self.vapi.cli("show gbp endpoint"))
2946 self.logger.info(self.vapi.cli("show ip fib index 1 %s" % l['ip']))
2949 # Static EP replies to learnt
2952 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2953 IPv6(dst=l['ip6'], src=ep.ip6) /
2954 UDP(sport=1234, dport=1234) /
2957 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
2960 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2961 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2962 self.assertEqual(rx[UDP].dport, 48879)
2963 # the UDP source port is a random value for hashing
2964 self.assertEqual(rx[VXLAN].gpid, 441)
2965 self.assertEqual(rx[VXLAN].vni, 101)
2966 self.assertTrue(rx[VXLAN].flags.G)
2967 self.assertTrue(rx[VXLAN].flags.Instance)
2968 self.assertTrue(rx[VXLAN].gpflags.A)
2969 self.assertFalse(rx[VXLAN].gpflags.D)
2971 inner = rx[VXLAN].payload
2973 self.assertEqual(inner[Ether].src, routed_src_mac)
2974 self.assertEqual(inner[Ether].dst, routed_dst_mac)
2975 self.assertEqual(inner[IPv6].src, ep.ip6)
2976 self.assertEqual(inner[IPv6].dst, l['ip6'])
2978 self.logger.info(self.vapi.cli("sh gbp endpoint"))
2980 self.wait_for_ep_timeout(ip=l['ip'])
2983 # Static sends to unknown EP with no route
2985 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2986 IP(dst="10.0.0.99", src=ep.ip4) /
2987 UDP(sport=1234, dport=1234) /
2990 self.send_and_assert_no_replies(self.pg0, [p])
2993 # Add a route to static EP's v4 and v6 subnet
2995 se_10_24 = VppGbpSubnet(
2996 self, rd1, "10.0.0.0", 24,
2997 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT)
2998 se_10_24.add_vpp_config()
3001 # static pings router
3003 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
3004 IP(dst=epg_220.bvi_ip4, src=ep.ip4) /
3005 UDP(sport=1234, dport=1234) /
3008 self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg0)
3010 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
3011 IPv6(dst=epg_220.bvi_ip6, src=ep.ip6) /
3012 UDP(sport=1234, dport=1234) /
3015 self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg0)
3018 # packets to address in the subnet are sent on the uu-fwd
3020 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
3021 IP(dst="10.0.0.99", src=ep.ip4) /
3022 UDP(sport=1234, dport=1234) /
3025 rxs = self.send_and_expect(self.pg0, [p], self.pg4)
3027 self.assertEqual(rx[IP].src, self.pg4.local_ip4)
3028 self.assertEqual(rx[IP].dst, self.pg4.remote_ip4)
3029 self.assertEqual(rx[UDP].dport, 48879)
3030 # the UDP source port is a random value for hashing
3031 self.assertEqual(rx[VXLAN].gpid, 441)
3032 self.assertEqual(rx[VXLAN].vni, 114)
3033 self.assertTrue(rx[VXLAN].flags.G)
3034 self.assertTrue(rx[VXLAN].flags.Instance)
3035 # policy is not applied to packets sent to the uu-fwd interfaces
3036 self.assertFalse(rx[VXLAN].gpflags.A)
3037 self.assertFalse(rx[VXLAN].gpflags.D)
3040 # learn some remote IPv4 EPs
3042 for ii, l in enumerate(learnt):
3043 # a packet with an sclass from a known EPG
3044 # arriving on an unknown TEP
3045 p = (Ether(src=self.pg2.remote_mac,
3046 dst=self.pg2.local_mac) /
3047 IP(src=self.pg2.remote_hosts[2].ip4,
3048 dst=self.pg2.local_ip4) /
3049 UDP(sport=1234, dport=48879) /
3050 VXLAN(vni=101, gpid=441, flags=0x88) /
3051 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
3052 IP(src=l['ip'], dst=ep.ip4) /
3053 UDP(sport=1234, dport=1234) /
3056 rx = self.send_and_expect(self.pg2, [p], self.pg0)
3059 tep1_sw_if_index = find_vxlan_gbp_tunnel(
3062 self.pg2.remote_hosts[2].ip4,
3064 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
3066 # endpoint learnt via the parent GBP-vxlan interface
3067 self.assertTrue(find_gbp_endpoint(self,
3068 vx_tun_l3._sw_if_index,
3072 # Add a remote endpoint from the API
3074 rep_88 = VppGbpEndpoint(self, vx_tun_l3,
3076 "10.0.0.88", "11.0.0.88",
3077 "2001:10::88", "3001::88",
3078 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
3080 self.pg2.remote_hosts[2].ip4,
3082 rep_88.add_vpp_config()
3085 # Add a remote endpoint from the API that matches an existing one
3086 # this is a lower priority, hence the packet is sent to the DP leanrt
3089 rep_2 = VppGbpEndpoint(self, vx_tun_l3,
3091 learnt[0]['ip'], "11.0.0.101",
3092 learnt[0]['ip6'], "3001::101",
3093 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
3095 self.pg2.remote_hosts[1].ip4,
3097 rep_2.add_vpp_config()
3100 # Add a route to the learned EP's v4 subnet
3101 # packets should be send on the v4/v6 uu=fwd interface resp.
3103 se_10_1_24 = VppGbpSubnet(
3104 self, rd1, "10.0.1.0", 24,
3105 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT)
3106 se_10_1_24.add_vpp_config()
3108 self.logger.info(self.vapi.cli("show gbp endpoint"))
3110 ips = ["10.0.0.88", learnt[0]['ip']]
3112 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
3113 IP(dst=ip, src=ep.ip4) /
3114 UDP(sport=1234, dport=1234) /
3117 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
3120 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
3121 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[2].ip4)
3122 self.assertEqual(rx[UDP].dport, 48879)
3123 # the UDP source port is a random value for hashing
3124 self.assertEqual(rx[VXLAN].gpid, 441)
3125 self.assertEqual(rx[VXLAN].vni, 101)
3126 self.assertTrue(rx[VXLAN].flags.G)
3127 self.assertTrue(rx[VXLAN].flags.Instance)
3128 self.assertTrue(rx[VXLAN].gpflags.A)
3129 self.assertFalse(rx[VXLAN].gpflags.D)
3131 inner = rx[VXLAN].payload
3133 self.assertEqual(inner[Ether].src, routed_src_mac)
3134 self.assertEqual(inner[Ether].dst, routed_dst_mac)
3135 self.assertEqual(inner[IP].src, ep.ip4)
3136 self.assertEqual(inner[IP].dst, ip)
3139 # remove the API remote EPs, only API sourced is gone, the DP
3140 # learnt one remains
3142 rep_88.remove_vpp_config()
3143 rep_2.remove_vpp_config()
3145 self.assertTrue(find_gbp_endpoint(self, ip=rep_2.ip4))
3147 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
3148 IP(src=ep.ip4, dst=rep_2.ip4) /
3149 UDP(sport=1234, dport=1234) /
3151 rxs = self.send_and_expect(self.pg0, [p], self.pg2)
3153 self.assertFalse(find_gbp_endpoint(self, ip=rep_88.ip4))
3155 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
3156 IP(src=ep.ip4, dst=rep_88.ip4) /
3157 UDP(sport=1234, dport=1234) /
3159 rxs = self.send_and_expect(self.pg0, [p], self.pg4)
3162 # to appease the testcase we cannot have the registered EP still
3163 # present (because it's DP learnt) when the TC ends so wait until
3166 self.wait_for_ep_timeout(ip=rep_88.ip4)
3167 self.wait_for_ep_timeout(ip=rep_2.ip4)
3170 # Same as above, learn a remote EP via CP and DP
3171 # this time remove the DP one first. expect the CP data to remain
3173 rep_3 = VppGbpEndpoint(self, vx_tun_l3,
3175 "10.0.1.4", "11.0.0.103",
3176 "2001::10:3", "3001::103",
3177 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
3179 self.pg2.remote_hosts[1].ip4,
3181 rep_3.add_vpp_config()
3183 p = (Ether(src=self.pg2.remote_mac,
3184 dst=self.pg2.local_mac) /
3185 IP(src=self.pg2.remote_hosts[2].ip4,
3186 dst=self.pg2.local_ip4) /
3187 UDP(sport=1234, dport=48879) /
3188 VXLAN(vni=101, gpid=441, flags=0x88) /
3189 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
3190 IP(src="10.0.1.4", dst=ep.ip4) /
3191 UDP(sport=1234, dport=1234) /
3193 rxs = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
3195 self.assertTrue(find_gbp_endpoint(self,
3196 vx_tun_l3._sw_if_index,
3198 tep=[self.pg2.local_ip4,
3199 self.pg2.remote_hosts[2].ip4]))
3201 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
3202 IP(dst="10.0.1.4", src=ep.ip4) /
3203 UDP(sport=1234, dport=1234) /
3205 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
3207 # host 2 is the DP learned TEP
3209 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
3210 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[2].ip4)
3212 self.wait_for_ep_timeout(ip=rep_3.ip4,
3213 tep=[self.pg2.local_ip4,
3214 self.pg2.remote_hosts[2].ip4])
3216 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
3218 # host 1 is the CP learned TEP
3220 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
3221 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
3224 # shutdown with learnt endpoint present
3226 p = (Ether(src=self.pg2.remote_mac,
3227 dst=self.pg2.local_mac) /
3228 IP(src=self.pg2.remote_hosts[1].ip4,
3229 dst=self.pg2.local_ip4) /
3230 UDP(sport=1234, dport=48879) /
3231 VXLAN(vni=101, gpid=441, flags=0x88) /
3232 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
3233 IP(src=learnt[1]['ip'], dst=ep.ip4) /
3234 UDP(sport=1234, dport=1234) /
3237 rx = self.send_and_expect(self.pg2, [p], self.pg0)
3239 # endpoint learnt via the parent GBP-vxlan interface
3240 self.assertTrue(find_gbp_endpoint(self,
3241 vx_tun_l3._sw_if_index,
3246 # remote endpoint becomes local
3248 self.pg2.unconfig_ip4()
3249 self.pg3.unconfig_ip4()
3250 self.pg4.unconfig_ip4()
3252 def test_gbp_redirect(self):
3253 """ GBP Endpoint Redirect """
3255 self.vapi.cli("set logging class gbp level debug")
3257 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
3258 routed_dst_mac = "00:0c:0c:0c:0c:0c"
3259 routed_src_mac = "00:22:bd:f8:19:ff"
3261 learnt = [{'mac': '00:00:11:11:11:02',
3263 'ip6': '2001:10::2'},
3264 {'mac': '00:00:11:11:11:03',
3266 'ip6': '2001:10::3'}]
3271 t4 = VppIpTable(self, 1)
3273 t6 = VppIpTable(self, 1, True)
3276 rd1 = VppGbpRouteDomain(self, 2, 402, t4, t6)
3277 rd1.add_vpp_config()
3279 self.loop0.set_mac(self.router_mac)
3282 # Bind the BVI to the RD
3284 b_ip4 = VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
3285 b_ip6 = VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
3288 # Pg7 hosts a BD's UU-fwd
3290 self.pg7.config_ip4()
3291 self.pg7.resolve_arp()
3294 # a GBP bridge domains for the EPs
3296 bd1 = VppBridgeDomain(self, 1)
3297 bd1.add_vpp_config()
3298 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0)
3299 gbd1.add_vpp_config()
3301 bd2 = VppBridgeDomain(self, 2)
3302 bd2.add_vpp_config()
3303 gbd2 = VppGbpBridgeDomain(self, bd2, rd1, self.loop1)
3304 gbd2.add_vpp_config()
3306 # ... and has a /32 and /128 applied
3307 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi,
3309 bind=b_ip4).add_vpp_config()
3310 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi,
3311 "2001:10::128", 128,
3312 bind=b_ip6).add_vpp_config()
3313 ip4_addr = VppIpInterfaceAddress(self, gbd2.bvi,
3314 "10.0.1.128", 32).add_vpp_config()
3315 ip6_addr = VppIpInterfaceAddress(self, gbd2.bvi,
3316 "2001:11::128", 128).add_vpp_config()
3319 # The Endpoint-groups in which we are learning endpoints
3321 epg_220 = VppGbpEndpointGroup(self, 220, 440, rd1, gbd1,
3325 VppGbpEndpointRetention(60))
3326 epg_220.add_vpp_config()
3327 epg_221 = VppGbpEndpointGroup(self, 221, 441, rd1, gbd2,
3331 VppGbpEndpointRetention(60))
3332 epg_221.add_vpp_config()
3333 epg_222 = VppGbpEndpointGroup(self, 222, 442, rd1, gbd1,
3337 VppGbpEndpointRetention(60))
3338 epg_222.add_vpp_config()
3341 # a GBP bridge domains for the SEPs
3343 bd_uu1 = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
3344 self.pg7.remote_ip4, 116)
3345 bd_uu1.add_vpp_config()
3346 bd_uu2 = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
3347 self.pg7.remote_ip4, 117)
3348 bd_uu2.add_vpp_config()
3350 bd3 = VppBridgeDomain(self, 3)
3351 bd3.add_vpp_config()
3352 gbd3 = VppGbpBridgeDomain(self, bd3, rd1, self.loop2,
3353 bd_uu1, learn=False)
3354 gbd3.add_vpp_config()
3355 bd4 = VppBridgeDomain(self, 4)
3356 bd4.add_vpp_config()
3357 gbd4 = VppGbpBridgeDomain(self, bd4, rd1, self.loop3,
3358 bd_uu2, learn=False)
3359 gbd4.add_vpp_config()
3362 # EPGs in which the service endpoints exist
3364 epg_320 = VppGbpEndpointGroup(self, 320, 550, rd1, gbd3,
3368 VppGbpEndpointRetention(60))
3369 epg_320.add_vpp_config()
3370 epg_321 = VppGbpEndpointGroup(self, 321, 551, rd1, gbd4,
3374 VppGbpEndpointRetention(60))
3375 epg_321.add_vpp_config()
3378 # three local endpoints
3380 ep1 = VppGbpEndpoint(self, self.pg0,
3382 "10.0.0.1", "11.0.0.1",
3383 "2001:10::1", "3001:10::1")
3384 ep1.add_vpp_config()
3385 ep2 = VppGbpEndpoint(self, self.pg1,
3387 "10.0.1.1", "11.0.1.1",
3388 "2001:11::1", "3001:11::1")
3389 ep2.add_vpp_config()
3390 ep3 = VppGbpEndpoint(self, self.pg2,
3392 "10.0.2.2", "11.0.2.2",
3393 "2001:12::1", "3001:12::1")
3394 ep3.add_vpp_config()
3399 sep1 = VppGbpEndpoint(self, self.pg3,
3401 "12.0.0.1", "13.0.0.1",
3402 "4001:10::1", "5001:10::1")
3403 sep1.add_vpp_config()
3404 sep2 = VppGbpEndpoint(self, self.pg4,
3406 "12.0.0.2", "13.0.0.2",
3407 "4001:10::2", "5001:10::2")
3408 sep2.add_vpp_config()
3409 sep3 = VppGbpEndpoint(self, self.pg5,
3411 "12.0.1.1", "13.0.1.1",
3412 "4001:11::1", "5001:11::1")
3413 sep3.add_vpp_config()
3414 # this EP is not installed immediately
3415 sep4 = VppGbpEndpoint(self, self.pg6,
3417 "12.0.1.2", "13.0.1.2",
3418 "4001:11::2", "5001:11::2")
3421 # an L2 switch packet between local EPs in different EPGs
3422 # different dest ports on each so the are LB hashed differently
3424 p4 = [(Ether(src=ep1.mac, dst=ep3.mac) /
3425 IP(src=ep1.ip4, dst=ep3.ip4) /
3426 UDP(sport=1234, dport=1234) /
3427 Raw(b'\xa5' * 100)),
3428 (Ether(src=ep3.mac, dst=ep1.mac) /
3429 IP(src=ep3.ip4, dst=ep1.ip4) /
3430 UDP(sport=1234, dport=1234) /
3431 Raw(b'\xa5' * 100))]
3432 p6 = [(Ether(src=ep1.mac, dst=ep3.mac) /
3433 IPv6(src=ep1.ip6, dst=ep3.ip6) /
3434 UDP(sport=1234, dport=1234) /
3435 Raw(b'\xa5' * 100)),
3436 (Ether(src=ep3.mac, dst=ep1.mac) /
3437 IPv6(src=ep3.ip6, dst=ep1.ip6) /
3438 UDP(sport=1234, dport=1230) /
3439 Raw(b'\xa5' * 100))]
3441 # should be dropped since no contract yet
3442 self.send_and_assert_no_replies(self.pg0, [p4[0]])
3443 self.send_and_assert_no_replies(self.pg0, [p6[0]])
3446 # Add a contract with a rule to load-balance redirect via SEP1 and SEP2
3447 # one of the next-hops is via an EP that is not known
3449 rule4 = AclRule(is_permit=1, proto=17)
3450 rule6 = AclRule(src_prefix=IPv6Network((0, 0)),
3451 dst_prefix=IPv6Network((0, 0)), is_permit=1, proto=17)
3452 acl = VppAcl(self, rules=[rule4, rule6])
3453 acl.add_vpp_config()
3456 # test the src-ip hash mode
3458 c1 = VppGbpContract(
3459 self, 402, epg_220.sclass, epg_222.sclass, acl.acl_index,
3460 [VppGbpContractRule(
3461 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3462 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3463 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3464 sep1.ip4, sep1.epg.rd),
3465 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3466 sep2.ip4, sep2.epg.rd)]),
3468 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3469 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3470 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3471 sep3.ip6, sep3.epg.rd),
3472 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3473 sep4.ip6, sep4.epg.rd)])],
3474 [ETH_P_IP, ETH_P_IPV6])
3477 c2 = VppGbpContract(
3478 self, 402, epg_222.sclass, epg_220.sclass, acl.acl_index,
3479 [VppGbpContractRule(
3480 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3481 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3482 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3483 sep1.ip4, sep1.epg.rd),
3484 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3485 sep2.ip4, sep2.epg.rd)]),
3487 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3488 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3489 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3490 sep3.ip6, sep3.epg.rd),
3491 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3492 sep4.ip6, sep4.epg.rd)])],
3493 [ETH_P_IP, ETH_P_IPV6])
3497 # send again with the contract preset, now packets arrive
3498 # at SEP1 or SEP2 depending on the hashing
3500 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3503 self.assertEqual(rx[Ether].src, routed_src_mac)
3504 self.assertEqual(rx[Ether].dst, sep1.mac)
3505 self.assertEqual(rx[IP].src, ep1.ip4)
3506 self.assertEqual(rx[IP].dst, ep3.ip4)
3508 rxs = self.send_and_expect(self.pg2, p4[1] * 17, sep2.itf)
3511 self.assertEqual(rx[Ether].src, routed_src_mac)
3512 self.assertEqual(rx[Ether].dst, sep2.mac)
3513 self.assertEqual(rx[IP].src, ep3.ip4)
3514 self.assertEqual(rx[IP].dst, ep1.ip4)
3516 rxs = self.send_and_expect(self.pg0, p6[0] * 17, self.pg7)
3519 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3520 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3521 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3522 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
3523 self.assertEqual(rx[VXLAN].vni, 117)
3524 self.assertTrue(rx[VXLAN].flags.G)
3525 self.assertTrue(rx[VXLAN].flags.Instance)
3526 # redirect policy has been applied
3527 self.assertTrue(rx[VXLAN].gpflags.A)
3528 self.assertFalse(rx[VXLAN].gpflags.D)
3530 inner = rx[VXLAN].payload
3532 self.assertEqual(inner[Ether].src, routed_src_mac)
3533 self.assertEqual(inner[Ether].dst, sep4.mac)
3534 self.assertEqual(inner[IPv6].src, ep1.ip6)
3535 self.assertEqual(inner[IPv6].dst, ep3.ip6)
3537 rxs = self.send_and_expect(self.pg2, p6[1] * 17, sep3.itf)
3540 self.assertEqual(rx[Ether].src, routed_src_mac)
3541 self.assertEqual(rx[Ether].dst, sep3.mac)
3542 self.assertEqual(rx[IPv6].src, ep3.ip6)
3543 self.assertEqual(rx[IPv6].dst, ep1.ip6)
3546 # programme the unknown EP
3548 sep4.add_vpp_config()
3550 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep4.itf)
3553 self.assertEqual(rx[Ether].src, routed_src_mac)
3554 self.assertEqual(rx[Ether].dst, sep4.mac)
3555 self.assertEqual(rx[IPv6].src, ep1.ip6)
3556 self.assertEqual(rx[IPv6].dst, ep3.ip6)
3559 # and revert back to unprogrammed
3561 sep4.remove_vpp_config()
3563 rxs = self.send_and_expect(self.pg0, p6[0] * 17, self.pg7)
3566 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3567 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3568 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3569 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
3570 self.assertEqual(rx[VXLAN].vni, 117)
3571 self.assertTrue(rx[VXLAN].flags.G)
3572 self.assertTrue(rx[VXLAN].flags.Instance)
3573 # redirect policy has been applied
3574 self.assertTrue(rx[VXLAN].gpflags.A)
3575 self.assertFalse(rx[VXLAN].gpflags.D)
3577 inner = rx[VXLAN].payload
3579 self.assertEqual(inner[Ether].src, routed_src_mac)
3580 self.assertEqual(inner[Ether].dst, sep4.mac)
3581 self.assertEqual(inner[IPv6].src, ep1.ip6)
3582 self.assertEqual(inner[IPv6].dst, ep3.ip6)
3584 c1.remove_vpp_config()
3585 c2.remove_vpp_config()
3588 # test the symmetric hash mode
3590 c1 = VppGbpContract(
3591 self, 402, epg_220.sclass, epg_222.sclass, acl.acl_index,
3592 [VppGbpContractRule(
3593 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3594 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3595 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3596 sep1.ip4, sep1.epg.rd),
3597 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3598 sep2.ip4, sep2.epg.rd)]),
3600 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3601 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3602 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3603 sep3.ip6, sep3.epg.rd),
3604 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3605 sep4.ip6, sep4.epg.rd)])],
3606 [ETH_P_IP, ETH_P_IPV6])
3609 c2 = VppGbpContract(
3610 self, 402, epg_222.sclass, epg_220.sclass, acl.acl_index,
3611 [VppGbpContractRule(
3612 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3613 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3614 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3615 sep1.ip4, sep1.epg.rd),
3616 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3617 sep2.ip4, sep2.epg.rd)]),
3619 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3620 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3621 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3622 sep3.ip6, sep3.epg.rd),
3623 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3624 sep4.ip6, sep4.epg.rd)])],
3625 [ETH_P_IP, ETH_P_IPV6])
3629 # send again with the contract preset, now packets arrive
3630 # at SEP1 for both directions
3632 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3635 self.assertEqual(rx[Ether].src, routed_src_mac)
3636 self.assertEqual(rx[Ether].dst, sep1.mac)
3637 self.assertEqual(rx[IP].src, ep1.ip4)
3638 self.assertEqual(rx[IP].dst, ep3.ip4)
3640 rxs = self.send_and_expect(self.pg2, p4[1] * 17, sep1.itf)
3643 self.assertEqual(rx[Ether].src, routed_src_mac)
3644 self.assertEqual(rx[Ether].dst, sep1.mac)
3645 self.assertEqual(rx[IP].src, ep3.ip4)
3646 self.assertEqual(rx[IP].dst, ep1.ip4)
3649 # programme the unknown EP for the L3 tests
3651 sep4.add_vpp_config()
3654 # an L3 switch packet between local EPs in different EPGs
3655 # different dest ports on each so the are LB hashed differently
3657 p4 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3658 IP(src=ep1.ip4, dst=ep2.ip4) /
3659 UDP(sport=1234, dport=1234) /
3660 Raw(b'\xa5' * 100)),
3661 (Ether(src=ep2.mac, dst=str(self.router_mac)) /
3662 IP(src=ep2.ip4, dst=ep1.ip4) /
3663 UDP(sport=1234, dport=1234) /
3664 Raw(b'\xa5' * 100))]
3665 p6 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3666 IPv6(src=ep1.ip6, dst=ep2.ip6) /
3667 UDP(sport=1234, dport=1234) /
3668 Raw(b'\xa5' * 100)),
3669 (Ether(src=ep2.mac, dst=str(self.router_mac)) /
3670 IPv6(src=ep2.ip6, dst=ep1.ip6) /
3671 UDP(sport=1234, dport=1234) /
3672 Raw(b'\xa5' * 100))]
3674 c3 = VppGbpContract(
3675 self, 402, epg_220.sclass, epg_221.sclass, acl.acl_index,
3676 [VppGbpContractRule(
3677 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3678 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3679 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3680 sep1.ip4, sep1.epg.rd),
3681 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3682 sep2.ip4, sep2.epg.rd)]),
3684 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3685 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3686 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3687 sep3.ip6, sep3.epg.rd),
3688 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3689 sep4.ip6, sep4.epg.rd)])],
3690 [ETH_P_IP, ETH_P_IPV6])
3693 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3696 self.assertEqual(rx[Ether].src, routed_src_mac)
3697 self.assertEqual(rx[Ether].dst, sep1.mac)
3698 self.assertEqual(rx[IP].src, ep1.ip4)
3699 self.assertEqual(rx[IP].dst, ep2.ip4)
3702 # learn a remote EP in EPG 221
3703 # packets coming from unknown remote EPs will be leant & redirected
3705 vx_tun_l3 = VppGbpVxlanTunnel(
3706 self, 444, rd1.rd_id,
3707 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
3709 vx_tun_l3.add_vpp_config()
3711 c4 = VppGbpContract(
3712 self, 402, epg_221.sclass, epg_220.sclass, acl.acl_index,
3713 [VppGbpContractRule(
3714 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3715 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3716 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3717 sep1.ip4, sep1.epg.rd),
3718 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3719 sep2.ip4, sep2.epg.rd)]),
3721 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3722 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3723 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3724 sep3.ip6, sep3.epg.rd),
3725 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3726 sep4.ip6, sep4.epg.rd)])],
3727 [ETH_P_IP, ETH_P_IPV6])
3730 p = (Ether(src=self.pg7.remote_mac,
3731 dst=self.pg7.local_mac) /
3732 IP(src=self.pg7.remote_ip4,
3733 dst=self.pg7.local_ip4) /
3734 UDP(sport=1234, dport=48879) /
3735 VXLAN(vni=444, gpid=441, flags=0x88) /
3736 Ether(src="00:22:22:22:22:33", dst=str(self.router_mac)) /
3737 IP(src="10.0.0.88", dst=ep1.ip4) /
3738 UDP(sport=1234, dport=1234) /
3741 # unknown remote EP to local EP redirected
3742 rxs = self.send_and_expect(self.pg7, [p], sep1.itf)
3745 self.assertEqual(rx[Ether].src, routed_src_mac)
3746 self.assertEqual(rx[Ether].dst, sep1.mac)
3747 self.assertEqual(rx[IP].src, "10.0.0.88")
3748 self.assertEqual(rx[IP].dst, ep1.ip4)
3750 # endpoint learnt via the parent GBP-vxlan interface
3751 self.assertTrue(find_gbp_endpoint(self,
3752 vx_tun_l3._sw_if_index,
3755 p = (Ether(src=self.pg7.remote_mac,
3756 dst=self.pg7.local_mac) /
3757 IP(src=self.pg7.remote_ip4,
3758 dst=self.pg7.local_ip4) /
3759 UDP(sport=1234, dport=48879) /
3760 VXLAN(vni=444, gpid=441, flags=0x88) /
3761 Ether(src="00:22:22:22:22:33", dst=str(self.router_mac)) /
3762 IPv6(src="2001:10::88", dst=ep1.ip6) /
3763 UDP(sport=1234, dport=1234) /
3766 # unknown remote EP to local EP redirected (ipv6)
3767 rxs = self.send_and_expect(self.pg7, [p], sep3.itf)
3770 self.assertEqual(rx[Ether].src, routed_src_mac)
3771 self.assertEqual(rx[Ether].dst, sep3.mac)
3772 self.assertEqual(rx[IPv6].src, "2001:10::88")
3773 self.assertEqual(rx[IPv6].dst, ep1.ip6)
3775 # endpoint learnt via the parent GBP-vxlan interface
3776 self.assertTrue(find_gbp_endpoint(self,
3777 vx_tun_l3._sw_if_index,
3781 # L3 switch from local to remote EP
3783 p4 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3784 IP(src=ep1.ip4, dst="10.0.0.88") /
3785 UDP(sport=1234, dport=1234) /
3786 Raw(b'\xa5' * 100))]
3787 p6 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3788 IPv6(src=ep1.ip6, dst="2001:10::88") /
3789 UDP(sport=1234, dport=1234) /
3790 Raw(b'\xa5' * 100))]
3792 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3795 self.assertEqual(rx[Ether].src, routed_src_mac)
3796 self.assertEqual(rx[Ether].dst, sep1.mac)
3797 self.assertEqual(rx[IP].src, ep1.ip4)
3798 self.assertEqual(rx[IP].dst, "10.0.0.88")
3800 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep4.itf)
3803 self.assertEqual(rx[Ether].src, routed_src_mac)
3804 self.assertEqual(rx[Ether].dst, sep4.mac)
3805 self.assertEqual(rx[IPv6].src, ep1.ip6)
3806 self.assertEqual(rx[IPv6].dst, "2001:10::88")
3809 # test the dst-ip hash mode
3811 c5 = VppGbpContract(
3812 self, 402, epg_220.sclass, epg_221.sclass, acl.acl_index,
3813 [VppGbpContractRule(
3814 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3815 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
3816 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3817 sep1.ip4, sep1.epg.rd),
3818 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3819 sep2.ip4, sep2.epg.rd)]),
3821 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3822 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
3823 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3824 sep3.ip6, sep3.epg.rd),
3825 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3826 sep4.ip6, sep4.epg.rd)])],
3827 [ETH_P_IP, ETH_P_IPV6])
3830 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3833 self.assertEqual(rx[Ether].src, routed_src_mac)
3834 self.assertEqual(rx[Ether].dst, sep1.mac)
3835 self.assertEqual(rx[IP].src, ep1.ip4)
3836 self.assertEqual(rx[IP].dst, "10.0.0.88")
3838 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep3.itf)
3841 self.assertEqual(rx[Ether].src, routed_src_mac)
3842 self.assertEqual(rx[Ether].dst, sep3.mac)
3843 self.assertEqual(rx[IPv6].src, ep1.ip6)
3844 self.assertEqual(rx[IPv6].dst, "2001:10::88")
3847 # a programmed remote SEP in EPG 320
3850 # gbp vxlan tunnel for the remote SEP
3851 vx_tun_l3_sep = VppGbpVxlanTunnel(
3852 self, 555, rd1.rd_id,
3853 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
3855 vx_tun_l3_sep.add_vpp_config()
3858 sep5 = VppGbpEndpoint(self, vx_tun_l3_sep,
3860 "12.0.0.10", "13.0.0.10",
3861 "4001:10::10", "5001:10::10",
3862 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
3864 self.pg7.remote_ip4,
3866 sep5.add_vpp_config()
3869 # local l3out redirect tests
3874 self.loop4.set_mac(self.router_mac)
3875 b_lo4_ip4 = VppIpInterfaceBind(self, self.loop4, t4).add_vpp_config()
3876 b_lo4_ip6 = VppIpInterfaceBind(self, self.loop4, t6).add_vpp_config()
3877 ebd = VppBridgeDomain(self, 100)
3878 ebd.add_vpp_config()
3879 gebd = VppGbpBridgeDomain(self, ebd, rd1, self.loop4, None, None)
3880 gebd.add_vpp_config()
3882 eepg = VppGbpEndpointGroup(self, 888, 765, rd1, gebd,
3886 VppGbpEndpointRetention(60))
3887 eepg.add_vpp_config()
3888 # add subnets to BVI
3889 VppIpInterfaceAddress(
3893 24, bind=b_lo4_ip4).add_vpp_config()
3894 VppIpInterfaceAddress(
3898 64, bind=b_lo4_ip6).add_vpp_config()
3899 # ... which are L3-out subnets
3900 VppGbpSubnet(self, rd1, "10.1.0.0", 24,
3901 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3902 sclass=765).add_vpp_config()
3903 VppGbpSubnet(self, rd1, "2001:10:1::128", 64,
3904 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3905 sclass=765).add_vpp_config()
3906 # external endpoints
3907 VppL2Vtr(self, self.vlan_100, L2_VTR_OP.L2_POP_1).add_vpp_config()
3908 eep1 = VppGbpEndpoint(self, self.vlan_100, eepg, None, "10.1.0.1",
3909 "11.1.0.1", "2001:10:1::1", "3001:10:1::1",
3910 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
3911 eep1.add_vpp_config()
3912 VppL2Vtr(self, self.vlan_101, L2_VTR_OP.L2_POP_1).add_vpp_config()
3913 eep2 = VppGbpEndpoint(self, self.vlan_101, eepg, None, "10.1.0.2",
3914 "11.1.0.2", "2001:10:1::2", "3001:10:1::2",
3915 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
3916 eep2.add_vpp_config()
3918 # external subnets reachable though eep1 and eep2 respectively
3919 VppIpRoute(self, "10.220.0.0", 24,
3920 [VppRoutePath(eep1.ip4, eep1.epg.bvi.sw_if_index)],
3921 table_id=t4.table_id).add_vpp_config()
3922 VppGbpSubnet(self, rd1, "10.220.0.0", 24,
3923 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3924 sclass=4220).add_vpp_config()
3925 VppIpRoute(self, "10:220::", 64,
3926 [VppRoutePath(eep1.ip6, eep1.epg.bvi.sw_if_index)],
3927 table_id=t6.table_id).add_vpp_config()
3928 VppGbpSubnet(self, rd1, "10:220::", 64,
3929 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3930 sclass=4220).add_vpp_config()
3931 VppIpRoute(self, "10.221.0.0", 24,
3932 [VppRoutePath(eep2.ip4, eep2.epg.bvi.sw_if_index)],
3933 table_id=t4.table_id).add_vpp_config()
3934 VppGbpSubnet(self, rd1, "10.221.0.0", 24,
3935 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3936 sclass=4221).add_vpp_config()
3937 VppIpRoute(self, "10:221::", 64,
3938 [VppRoutePath(eep2.ip6, eep2.epg.bvi.sw_if_index)],
3939 table_id=t6.table_id).add_vpp_config()
3940 VppGbpSubnet(self, rd1, "10:221::", 64,
3941 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3942 sclass=4221).add_vpp_config()
3945 # l3out redirect to remote (known, then unknown) SEP
3948 # packets from 1 external subnet to the other
3949 p = [(Ether(src=eep1.mac, dst=self.router_mac) /
3951 IP(src="10.220.0.17", dst="10.221.0.65") /
3952 UDP(sport=1234, dport=1234) /
3953 Raw(b'\xa5' * 100)),
3954 (Ether(src=eep1.mac, dst=self.router_mac) /
3956 IPv6(src="10:220::17", dst="10:221::65") /
3957 UDP(sport=1234, dport=1234) /
3958 Raw(b'\xa5' * 100))]
3960 # packets should be dropped in absence of contract
3961 self.send_and_assert_no_replies(self.pg0, p)
3963 # contract redirecting to sep5
3965 self, 402, 4220, 4221, acl.acl_index,
3966 [VppGbpContractRule(
3967 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3968 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
3969 [VppGbpContractNextHop(sep5.vmac, sep5.epg.bd,
3970 sep5.ip4, sep5.epg.rd)]),
3972 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3973 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
3974 [VppGbpContractNextHop(sep5.vmac, sep5.epg.bd,
3975 sep5.ip6, sep5.epg.rd)])],
3976 [ETH_P_IP, ETH_P_IPV6]).add_vpp_config()
3978 rxs = self.send_and_expect(self.pg0, p, self.pg7)
3980 for rx, tx in zip(rxs, p):
3981 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3982 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3983 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3984 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
3985 # this should use the programmed remote leaf TEP
3986 self.assertEqual(rx[VXLAN].vni, 555)
3987 self.assertEqual(rx[VXLAN].gpid, 4220)
3988 self.assertTrue(rx[VXLAN].flags.G)
3989 self.assertTrue(rx[VXLAN].flags.Instance)
3990 # redirect policy has been applied
3991 self.assertTrue(rx[VXLAN].gpflags.A)
3992 self.assertTrue(rx[VXLAN].gpflags.D)
3993 rxip = rx[VXLAN][Ether].payload
3994 txip = tx[Dot1Q].payload
3995 self.assertEqual(rxip.src, txip.src)
3996 self.assertEqual(rxip.dst, txip.dst)
3998 # remote SEP: it is now an unknown remote SEP and should go
4000 sep5.remove_vpp_config()
4002 rxs = self.send_and_expect(self.pg0, p, self.pg7)
4004 for rx, tx in zip(rxs, p):
4005 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4006 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4007 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4008 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4009 # this should use the spine proxy TEP
4010 self.assertEqual(rx[VXLAN].vni, epg_320.bd.uu_fwd.vni)
4011 self.assertEqual(rx[VXLAN].gpid, 4220)
4012 self.assertTrue(rx[VXLAN].flags.G)
4013 self.assertTrue(rx[VXLAN].flags.Instance)
4014 # redirect policy has been applied
4015 self.assertTrue(rx[VXLAN].gpflags.A)
4016 self.assertTrue(rx[VXLAN].gpflags.D)
4017 rxip = rx[VXLAN][Ether].payload
4018 txip = tx[Dot1Q].payload
4019 self.assertEqual(rxip.src, txip.src)
4020 self.assertEqual(rxip.dst, txip.dst)
4023 # l3out redirect to local SEP
4026 # change the contract between l3out to redirect to local SEPs
4027 # instead of remote SEP
4029 self, 402, 4220, 4221, acl.acl_index,
4030 [VppGbpContractRule(
4031 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4032 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
4033 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
4034 sep1.ip4, sep1.epg.rd)]),
4036 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4037 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
4038 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
4039 sep1.ip6, sep1.epg.rd)])],
4040 [ETH_P_IP, ETH_P_IPV6]).add_vpp_config()
4042 rxs = self.send_and_expect(self.pg0, p, sep1.itf)
4043 for rx, tx in zip(rxs, p):
4044 self.assertEqual(rx[Ether].src, routed_src_mac)
4045 self.assertEqual(rx[Ether].dst, sep1.mac)
4046 rxip = rx[Ether].payload
4047 txip = tx[Ether].payload
4048 self.assertEqual(rxip.src, txip.src)
4049 self.assertEqual(rxip.dst, txip.dst)
4052 # redirect remote EP to remote (known then unknown) SEP
4055 # remote SEP known again
4056 sep5.add_vpp_config()
4058 # contract to redirect to learnt SEP
4060 self, 402, epg_221.sclass, epg_222.sclass, acl.acl_index,
4061 [VppGbpContractRule(
4062 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4063 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
4064 [VppGbpContractNextHop(sep5.vmac, sep5.epg.bd,
4065 sep5.ip4, sep5.epg.rd)]),
4067 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4068 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
4069 [VppGbpContractNextHop(sep5.vmac, sep5.epg.bd,
4070 sep5.ip6, sep5.epg.rd)])],
4071 [ETH_P_IP, ETH_P_IPV6]).add_vpp_config()
4073 # packets from unknown EP 221 to known EP in EPG 222
4074 # should be redirected to known remote SEP
4075 base = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
4076 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
4077 UDP(sport=1234, dport=48879) /
4078 VXLAN(vni=444, gpid=441, flags=0x88) /
4079 Ether(src="00:22:22:22:22:44", dst=str(self.router_mac)))
4081 IP(src="10.0.1.100", dst=ep3.ip4) /
4082 UDP(sport=1234, dport=1234) /
4083 Raw(b'\xa5' * 100)),
4085 IPv6(src="2001:10::100", dst=ep3.ip6) /
4086 UDP(sport=1234, dport=1234) /
4087 Raw(b'\xa5' * 100))]
4089 # unknown remote EP to local EP redirected to known remote SEP
4090 rxs = self.send_and_expect(self.pg7, p, self.pg7)
4092 for rx, tx in zip(rxs, p):
4093 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4094 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4095 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4096 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4097 # this should use the programmed remote leaf TEP
4098 self.assertEqual(rx[VXLAN].vni, 555)
4099 self.assertEqual(rx[VXLAN].gpid, epg_221.sclass)
4100 self.assertTrue(rx[VXLAN].flags.G)
4101 self.assertTrue(rx[VXLAN].flags.Instance)
4102 # redirect policy has been applied
4103 self.assertTrue(rx[VXLAN].gpflags.A)
4104 self.assertFalse(rx[VXLAN].gpflags.D)
4105 rxip = rx[VXLAN][Ether].payload
4106 txip = tx[VXLAN][Ether].payload
4107 self.assertEqual(rxip.src, txip.src)
4108 self.assertEqual(rxip.dst, txip.dst)
4110 # endpoint learnt via the parent GBP-vxlan interface
4111 self.assertTrue(find_gbp_endpoint(self,
4112 vx_tun_l3._sw_if_index,
4114 self.assertTrue(find_gbp_endpoint(self,
4115 vx_tun_l3._sw_if_index,
4118 # remote SEP: it is now an unknown remote SEP and should go
4120 sep5.remove_vpp_config()
4122 # remote EP (coming from spine proxy) to local EP redirected to
4124 rxs = self.send_and_expect(self.pg7, p, self.pg7)
4126 for rx, tx in zip(rxs, p):
4127 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4128 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4129 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4130 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4131 # this should use the spine proxy TEP
4132 self.assertEqual(rx[VXLAN].vni, epg_320.bd.uu_fwd.vni)
4133 self.assertEqual(rx[VXLAN].gpid, epg_221.sclass)
4134 self.assertTrue(rx[VXLAN].flags.G)
4135 self.assertTrue(rx[VXLAN].flags.Instance)
4136 # redirect policy has been applied
4137 self.assertTrue(rx[VXLAN].gpflags.A)
4138 self.assertFalse(rx[VXLAN].gpflags.D)
4139 rxip = rx[VXLAN][Ether].payload
4140 txip = tx[VXLAN][Ether].payload
4141 self.assertEqual(rxip.src, txip.src)
4142 self.assertEqual(rxip.dst, txip.dst)
4147 self.pg7.unconfig_ip4()
4149 def test_gbp_redirect_extended(self):
4150 """ GBP Endpoint Redirect Extended """
4152 self.vapi.cli("set logging class gbp level debug")
4154 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
4155 routed_dst_mac = "00:0c:0c:0c:0c:0c"
4156 routed_src_mac = "00:22:bd:f8:19:ff"
4158 learnt = [{'mac': '00:00:11:11:11:02',
4160 'ip6': '2001:10::2'},
4161 {'mac': '00:00:11:11:11:03',
4163 'ip6': '2001:10::3'}]
4168 t4 = VppIpTable(self, 1)
4170 t6 = VppIpTable(self, 1, True)
4173 # create IPv4 and IPv6 RD UU VxLAN-GBP TEP and bind them to the right
4175 rd_uu4 = VppVxlanGbpTunnel(
4178 self.pg7.remote_ip4,
4180 mode=(VppEnum.vl_api_vxlan_gbp_api_tunnel_mode_t.
4181 VXLAN_GBP_API_TUNNEL_MODE_L3))
4182 rd_uu4.add_vpp_config()
4183 VppIpInterfaceBind(self, rd_uu4, t4).add_vpp_config()
4185 rd_uu6 = VppVxlanGbpTunnel(
4188 self.pg7.remote_ip4,
4190 mode=(VppEnum.vl_api_vxlan_gbp_api_tunnel_mode_t.
4191 VXLAN_GBP_API_TUNNEL_MODE_L3))
4192 rd_uu6.add_vpp_config()
4193 VppIpInterfaceBind(self, rd_uu6, t4).add_vpp_config()
4195 rd1 = VppGbpRouteDomain(self, 2, 402, t4, t6, rd_uu4, rd_uu6)
4196 rd1.add_vpp_config()
4198 self.loop0.set_mac(self.router_mac)
4199 self.loop1.set_mac(self.router_mac)
4200 self.loop2.set_mac(self.router_mac)
4203 # Bind the BVI to the RD
4205 b_lo0_ip4 = VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
4206 b_lo0_ip6 = VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
4207 b_lo1_ip4 = VppIpInterfaceBind(self, self.loop1, t4).add_vpp_config()
4208 b_lo1_ip6 = VppIpInterfaceBind(self, self.loop1, t6).add_vpp_config()
4209 b_lo2_ip4 = VppIpInterfaceBind(self, self.loop2, t4).add_vpp_config()
4210 b_lo2_ip6 = VppIpInterfaceBind(self, self.loop2, t6).add_vpp_config()
4213 # Pg7 hosts a BD's UU-fwd
4215 self.pg7.config_ip4()
4216 self.pg7.resolve_arp()
4219 # a GBP bridge domains for the EPs
4221 bd1 = VppBridgeDomain(self, 1)
4222 bd1.add_vpp_config()
4223 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0)
4224 gbd1.add_vpp_config()
4226 bd2 = VppBridgeDomain(self, 2)
4227 bd2.add_vpp_config()
4228 gbd2 = VppGbpBridgeDomain(self, bd2, rd1, self.loop1)
4229 gbd2.add_vpp_config()
4231 # ... and has a /32 and /128 applied
4232 ip4_addr1 = VppIpInterfaceAddress(self, gbd1.bvi,
4234 bind=b_lo0_ip4).add_vpp_config()
4235 ip6_addr1 = VppIpInterfaceAddress(self, gbd1.bvi,
4236 "2001:10::128", 128,
4237 bind=b_lo0_ip6).add_vpp_config()
4238 ip4_addr2 = VppIpInterfaceAddress(self, gbd2.bvi,
4240 bind=b_lo1_ip4).add_vpp_config()
4241 ip6_addr2 = VppIpInterfaceAddress(self, gbd2.bvi,
4242 "2001:11::128", 128,
4243 bind=b_lo1_ip6).add_vpp_config()
4246 # The Endpoint-groups
4248 epg_220 = VppGbpEndpointGroup(self, 220, 440, rd1, gbd1,
4252 VppGbpEndpointRetention(60))
4253 epg_220.add_vpp_config()
4254 epg_221 = VppGbpEndpointGroup(self, 221, 441, rd1, gbd2,
4258 VppGbpEndpointRetention(60))
4259 epg_221.add_vpp_config()
4262 # a GBP bridge domains for the SEPs
4264 bd_uu3 = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
4265 self.pg7.remote_ip4, 116)
4266 bd_uu3.add_vpp_config()
4268 bd3 = VppBridgeDomain(self, 3)
4269 bd3.add_vpp_config()
4270 gbd3 = VppGbpBridgeDomain(self, bd3, rd1, self.loop2,
4271 bd_uu3, learn=False)
4272 gbd3.add_vpp_config()
4274 ip4_addr3 = VppIpInterfaceAddress(self, gbd3.bvi,
4276 bind=b_lo2_ip4).add_vpp_config()
4277 ip6_addr3 = VppIpInterfaceAddress(self, gbd3.bvi,
4278 "4001:10::128", 128,
4279 bind=b_lo2_ip6).add_vpp_config()
4282 # self.logger.info(self.vapi.cli("show gbp bridge"))
4283 # self.logger.info(self.vapi.cli("show vxlan-gbp tunnel"))
4284 # self.logger.info(self.vapi.cli("show gbp vxlan"))
4285 # self.logger.info(self.vapi.cli("show int addr"))
4289 # EPGs in which the service endpoints exist
4291 epg_320 = VppGbpEndpointGroup(self, 320, 550, rd1, gbd3,
4295 VppGbpEndpointRetention(60))
4296 epg_320.add_vpp_config()
4301 ep1 = VppGbpEndpoint(self, self.pg0,
4303 "10.0.0.1", "11.0.0.1",
4304 "2001:10::1", "3001:10::1")
4305 ep1.add_vpp_config()
4306 ep2 = VppGbpEndpoint(self, self.pg1,
4308 "10.0.1.1", "11.0.1.1",
4309 "2001:11::1", "3001:11::1")
4310 ep2.add_vpp_config()
4315 sep1 = VppGbpEndpoint(self, self.pg3,
4317 "12.0.0.1", "13.0.0.1",
4318 "4001:10::1", "5001:10::1")
4319 sep2 = VppGbpEndpoint(self, self.pg4,
4321 "12.0.0.2", "13.0.0.2",
4322 "4001:10::2", "5001:10::2")
4324 # sep1 and sep2 are not added to config yet
4325 # they are unknown for now
4328 # add routes to EPG subnets
4330 VppGbpSubnet(self, rd1, "10.0.0.0", 24,
4331 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT
4333 VppGbpSubnet(self, rd1, "10.0.1.0", 24,
4334 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT
4338 # Local host to known local host in different BD
4339 # with SFC contract (source and destination are in
4340 # one node and service endpoint in another node)
4342 p4 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
4343 IP(src=ep1.ip4, dst=ep2.ip4) /
4344 UDP(sport=1234, dport=1234) /
4345 Raw(b'\xa5' * 100)),
4346 (Ether(src=ep2.mac, dst=str(self.router_mac)) /
4347 IP(src=ep2.ip4, dst=ep1.ip4) /
4348 UDP(sport=1234, dport=1234) /
4349 Raw(b'\xa5' * 100))]
4350 p6 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
4351 IPv6(src=ep1.ip6, dst=ep2.ip6) /
4352 UDP(sport=1234, dport=1234) /
4353 Raw(b'\xa5' * 100)),
4354 (Ether(src=ep2.mac, dst=str(self.router_mac)) /
4355 IPv6(src=ep2.ip6, dst=ep1.ip6) /
4356 UDP(sport=1234, dport=1230) /
4357 Raw(b'\xa5' * 100))]
4359 # should be dropped since no contract yet
4360 self.send_and_assert_no_replies(self.pg0, [p4[0]])
4361 self.send_and_assert_no_replies(self.pg0, [p6[0]])
4364 # Add a contract with a rule to load-balance redirect via SEP1 and SEP2
4365 # one of the next-hops is via an EP that is not known
4367 rule4 = AclRule(is_permit=1, proto=17)
4368 rule6 = AclRule(src_prefix=IPv6Network((0, 0)),
4369 dst_prefix=IPv6Network((0, 0)), is_permit=1, proto=17)
4370 acl = VppAcl(self, rules=[rule4, rule6])
4371 acl.add_vpp_config()
4374 # test the src-ip hash mode
4376 c1 = VppGbpContract(
4377 self, 402, epg_220.sclass, epg_221.sclass, acl.acl_index,
4378 [VppGbpContractRule(
4379 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4380 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
4381 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
4382 sep1.ip4, sep1.epg.rd)]),
4384 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4385 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
4386 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
4387 sep1.ip6, sep1.epg.rd)])],
4388 [ETH_P_IP, ETH_P_IPV6])
4391 c2 = VppGbpContract(
4392 self, 402, epg_221.sclass, epg_220.sclass, acl.acl_index,
4393 [VppGbpContractRule(
4394 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4395 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
4396 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
4397 sep1.ip4, sep1.epg.rd)]),
4399 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4400 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
4401 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
4402 sep1.ip6, sep1.epg.rd)])],
4403 [ETH_P_IP, ETH_P_IPV6])
4406 # ep1 <--> ep2 redirected through sep1
4408 # packet is redirected to sep bd and then go through sep bd UU
4410 rxs = self.send_and_expect(self.pg0, p4[0] * 17, self.pg7)
4413 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4414 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4415 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4416 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4417 self.assertEqual(rx[VXLAN].vni, 116)
4418 self.assertTrue(rx[VXLAN].flags.G)
4419 self.assertTrue(rx[VXLAN].flags.Instance)
4420 # redirect policy has been applied
4421 self.assertTrue(rx[VXLAN].gpflags.A)
4422 self.assertFalse(rx[VXLAN].gpflags.D)
4424 inner = rx[VXLAN].payload
4426 self.assertEqual(inner[Ether].src, routed_src_mac)
4427 self.assertEqual(inner[Ether].dst, sep1.mac)
4428 self.assertEqual(inner[IP].src, ep1.ip4)
4429 self.assertEqual(inner[IP].dst, ep2.ip4)
4431 rxs = self.send_and_expect(self.pg1, p4[1] * 17, self.pg7)
4434 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4435 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4436 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4437 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4438 self.assertEqual(rx[VXLAN].vni, 116)
4439 self.assertTrue(rx[VXLAN].flags.G)
4440 self.assertTrue(rx[VXLAN].flags.Instance)
4441 # redirect policy has been applied
4442 self.assertTrue(rx[VXLAN].gpflags.A)
4443 self.assertFalse(rx[VXLAN].gpflags.D)
4445 inner = rx[VXLAN].payload
4447 self.assertEqual(inner[Ether].src, routed_src_mac)
4448 self.assertEqual(inner[Ether].dst, sep1.mac)
4449 self.assertEqual(inner[IP].src, ep2.ip4)
4450 self.assertEqual(inner[IP].dst, ep1.ip4)
4452 rxs = self.send_and_expect(self.pg0, p6[0] * 17, self.pg7)
4455 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4456 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4457 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4458 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4459 self.assertEqual(rx[VXLAN].vni, 116)
4460 self.assertTrue(rx[VXLAN].flags.G)
4461 self.assertTrue(rx[VXLAN].flags.Instance)
4462 # redirect policy has been applied
4463 inner = rx[VXLAN].payload
4465 self.assertEqual(inner[Ether].src, routed_src_mac)
4466 self.assertEqual(inner[Ether].dst, sep1.mac)
4467 self.assertEqual(inner[IPv6].src, ep1.ip6)
4468 self.assertEqual(inner[IPv6].dst, ep2.ip6)
4470 rxs = self.send_and_expect(self.pg1, p6[1] * 17, self.pg7)
4473 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4474 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4475 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4476 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4477 self.assertEqual(rx[VXLAN].vni, 116)
4478 self.assertTrue(rx[VXLAN].flags.G)
4479 self.assertTrue(rx[VXLAN].flags.Instance)
4480 # redirect policy has been applied
4481 self.assertTrue(rx[VXLAN].gpflags.A)
4482 self.assertFalse(rx[VXLAN].gpflags.D)
4484 inner = rx[VXLAN].payload
4486 self.assertEqual(inner[Ether].src, routed_src_mac)
4487 self.assertEqual(inner[Ether].dst, sep1.mac)
4488 self.assertEqual(inner[IPv6].src, ep2.ip6)
4489 self.assertEqual(inner[IPv6].dst, ep1.ip6)
4491 # configure sep1: it is now local
4492 # packets between ep1 and ep2 are redirected locally
4493 sep1.add_vpp_config()
4495 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
4498 self.assertEqual(rx[Ether].src, routed_src_mac)
4499 self.assertEqual(rx[Ether].dst, sep1.mac)
4500 self.assertEqual(rx[IP].src, ep1.ip4)
4501 self.assertEqual(rx[IP].dst, ep2.ip4)
4503 rxs = self.send_and_expect(self.pg1, p6[1] * 17, sep1.itf)
4506 self.assertEqual(rx[Ether].src, routed_src_mac)
4507 self.assertEqual(rx[Ether].dst, sep1.mac)
4508 self.assertEqual(rx[IPv6].src, ep2.ip6)
4509 self.assertEqual(rx[IPv6].dst, ep1.ip6)
4511 # packet coming from the l2 spine-proxy to sep1
4512 p = (Ether(src=self.pg7.remote_mac,
4513 dst=self.pg7.local_mac) /
4514 IP(src=self.pg7.remote_ip4,
4515 dst=self.pg7.local_ip4) /
4516 UDP(sport=1234, dport=48879) /
4517 VXLAN(vni=116, gpid=440, gpflags=0x08, flags=0x88) /
4518 Ether(src=str(self.router_mac), dst=sep1.mac) /
4519 IP(src=ep1.ip4, dst=ep2.ip4) /
4520 UDP(sport=1234, dport=1234) /
4523 rxs = self.send_and_expect(self.pg7, [p] * 17, sep1.itf)
4526 self.assertEqual(rx[Ether].src, str(self.router_mac))
4527 self.assertEqual(rx[Ether].dst, sep1.mac)
4528 self.assertEqual(rx[IP].src, ep1.ip4)
4529 self.assertEqual(rx[IP].dst, ep2.ip4)
4531 # contract for SEP to communicate with dst EP
4532 c3 = VppGbpContract(
4533 self, 402, epg_320.sclass, epg_221.sclass, acl.acl_index,
4534 [VppGbpContractRule(
4535 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4536 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC),
4538 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4539 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC)],
4540 [ETH_P_IP, ETH_P_IPV6])
4543 # temporarily remove ep2, so that ep2 is remote & unknown
4544 ep2.remove_vpp_config()
4546 # packet going back from sep1 to its original dest (ep2)
4547 # as ep2 is now unknown (see above), it must go through
4548 # the rd UU (packet is routed)
4550 p1 = (Ether(src=sep1.mac, dst=self.router_mac) /
4551 IP(src=ep1.ip4, dst=ep2.ip4) /
4552 UDP(sport=1234, dport=1234) /
4555 rxs = self.send_and_expect(self.pg3, [p1] * 17, self.pg7)
4558 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4559 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4560 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4561 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4562 self.assertEqual(rx[VXLAN].vni, 114)
4563 self.assertTrue(rx[VXLAN].flags.G)
4564 self.assertTrue(rx[VXLAN].flags.Instance)
4565 # redirect policy has been applied
4566 inner = rx[VXLAN].payload
4567 self.assertEqual(inner[Ether].src, routed_src_mac)
4568 self.assertEqual(inner[Ether].dst, routed_dst_mac)
4569 self.assertEqual(inner[IP].src, ep1.ip4)
4570 self.assertEqual(inner[IP].dst, ep2.ip4)
4572 self.logger.info(self.vapi.cli("show bridge 3 detail"))
4573 sep1.remove_vpp_config()
4575 self.logger.info(self.vapi.cli("show bridge 1 detail"))
4576 self.logger.info(self.vapi.cli("show bridge 2 detail"))
4578 # re-add ep2: it is local again :)
4579 ep2.add_vpp_config()
4581 # packet coming back from the remote sep through rd UU
4582 p2 = (Ether(src=self.pg7.remote_mac,
4583 dst=self.pg7.local_mac) /
4584 IP(src=self.pg7.remote_ip4,
4585 dst=self.pg7.local_ip4) /
4586 UDP(sport=1234, dport=48879) /
4587 VXLAN(vni=114, gpid=441, gpflags=0x09, flags=0x88) /
4588 Ether(src=str(self.router_mac), dst=self.router_mac) /
4589 IP(src=ep1.ip4, dst=ep2.ip4) /
4590 UDP(sport=1234, dport=1234) /
4593 rxs = self.send_and_expect(self.pg7, [p2], self.pg1)
4596 self.assertEqual(rx[Ether].src, str(self.router_mac))
4597 self.assertEqual(rx[Ether].dst, self.pg1.remote_mac)
4598 self.assertEqual(rx[IP].src, ep1.ip4)
4599 self.assertEqual(rx[IP].dst, ep2.ip4)
4602 # bd_uu2.add_vpp_config()
4608 c1.remove_vpp_config()
4609 c2.remove_vpp_config()
4610 c3.remove_vpp_config()
4611 self.pg7.unconfig_ip4()
4613 def test_gbp_l3_out(self):
4616 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
4617 self.vapi.cli("set logging class gbp level debug")
4619 routed_dst_mac = "00:0c:0c:0c:0c:0c"
4620 routed_src_mac = "00:22:bd:f8:19:ff"
4625 t4 = VppIpTable(self, 1)
4627 t6 = VppIpTable(self, 1, True)
4630 rd1 = VppGbpRouteDomain(self, 2, 55, t4, t6)
4631 rd1.add_vpp_config()
4633 self.loop0.set_mac(self.router_mac)
4636 # Bind the BVI to the RD
4638 b_ip4 = VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
4639 b_ip6 = VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
4642 # Pg7 hosts a BD's BUM
4643 # Pg1 some other l3 interface
4645 self.pg7.config_ip4()
4646 self.pg7.resolve_arp()
4649 # a multicast vxlan-gbp tunnel for broadcast in the BD
4651 tun_bm = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
4654 tun_bm.add_vpp_config()
4657 # a GBP external bridge domains for the EPs
4659 bd1 = VppBridgeDomain(self, 1)
4660 bd1.add_vpp_config()
4661 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0, None, tun_bm)
4662 gbd1.add_vpp_config()
4665 # The Endpoint-groups in which the external endpoints exist
4667 epg_220 = VppGbpEndpointGroup(self, 220, 113, rd1, gbd1,
4671 VppGbpEndpointRetention(4))
4672 epg_220.add_vpp_config()
4674 # the BVIs have the subnets applied ...
4675 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128",
4676 24, bind=b_ip4).add_vpp_config()
4677 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128",
4678 64, bind=b_ip6).add_vpp_config()
4680 # ... which are L3-out subnets
4681 l3o_1 = VppGbpSubnet(
4682 self, rd1, "10.0.0.0", 24,
4683 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
4685 l3o_1.add_vpp_config()
4688 # an external interface attached to the outside world and the
4691 VppL2Vtr(self, self.vlan_100, L2_VTR_OP.L2_POP_1).add_vpp_config()
4692 VppL2Vtr(self, self.vlan_101, L2_VTR_OP.L2_POP_1).add_vpp_config()
4693 vlan_144 = VppDot1QSubint(self, self.pg0, 144)
4695 # vlan_102 is not poped
4698 # an unicast vxlan-gbp for inter-RD traffic
4700 vx_tun_l3 = VppGbpVxlanTunnel(
4701 self, 444, rd1.rd_id,
4702 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
4704 vx_tun_l3.add_vpp_config()
4707 # External Endpoints
4709 eep1 = VppGbpEndpoint(self, self.vlan_100,
4711 "10.0.0.1", "11.0.0.1",
4712 "2001:10::1", "3001::1",
4713 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
4714 eep1.add_vpp_config()
4715 eep2 = VppGbpEndpoint(self, self.vlan_101,
4717 "10.0.0.2", "11.0.0.2",
4718 "2001:10::2", "3001::2",
4719 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
4720 eep2.add_vpp_config()
4721 eep3 = VppGbpEndpoint(self, self.vlan_102,
4723 "10.0.0.3", "11.0.0.3",
4724 "2001:10::3", "3001::3",
4725 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
4726 eep3.add_vpp_config()
4729 # A remote external endpoint
4731 rep = VppGbpEndpoint(self, vx_tun_l3,
4733 "10.0.0.101", "11.0.0.101",
4734 "2001:10::101", "3001::101",
4735 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
4737 self.pg7.remote_ip4,
4739 rep.add_vpp_config()
4742 # EP1 impersonating EP3 is dropped
4744 p = (Ether(src=eep1.mac, dst="ff:ff:ff:ff:ff:ff") /
4747 psrc="10.0.0.3", pdst="10.0.0.128",
4748 hwsrc=eep1.mac, hwdst="ff:ff:ff:ff:ff:ff"))
4749 self.send_and_assert_no_replies(self.pg0, p)
4752 # ARP packet from External EPs are accepted and replied to
4754 p_arp = (Ether(src=eep1.mac, dst="ff:ff:ff:ff:ff:ff") /
4757 psrc=eep1.ip4, pdst="10.0.0.128",
4758 hwsrc=eep1.mac, hwdst="ff:ff:ff:ff:ff:ff"))
4759 rxs = self.send_and_expect(self.pg0, p_arp * 1, self.pg0)
4762 # ARP packet from host in remote subnet are accepted and replied to
4764 p_arp = (Ether(src=eep3.mac, dst="ff:ff:ff:ff:ff:ff") /
4767 psrc=eep3.ip4, pdst="10.0.0.128",
4768 hwsrc=eep3.mac, hwdst="ff:ff:ff:ff:ff:ff"))
4769 rxs = self.send_and_expect(self.pg0, p_arp * 1, self.pg0)
4772 # packets destined to unknown addresses in the BVI's subnet
4775 p4 = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
4777 IP(src="10.0.0.1", dst="10.0.0.88") /
4778 UDP(sport=1234, dport=1234) /
4780 p6 = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
4782 IPv6(src="2001:10::1", dst="2001:10::88") /
4783 UDP(sport=1234, dport=1234) /
4786 rxs = self.send_and_expect(self.pg0, p4 * 1, self.pg7)
4789 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4790 # self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4791 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4792 self.assertEqual(rx[IP].dst, "239.1.1.1")
4793 self.assertEqual(rx[VXLAN].vni, 88)
4794 self.assertTrue(rx[VXLAN].flags.G)
4795 self.assertTrue(rx[VXLAN].flags.Instance)
4796 # policy was applied to the original IP packet
4797 self.assertEqual(rx[VXLAN].gpid, 113)
4798 self.assertTrue(rx[VXLAN].gpflags.A)
4799 self.assertFalse(rx[VXLAN].gpflags.D)
4801 inner = rx[VXLAN].payload
4803 self.assertTrue(inner.haslayer(ARP))
4806 # remote to external
4808 p = (Ether(src=self.pg7.remote_mac,
4809 dst=self.pg7.local_mac) /
4810 IP(src=self.pg7.remote_ip4,
4811 dst=self.pg7.local_ip4) /
4812 UDP(sport=1234, dport=48879) /
4813 VXLAN(vni=444, gpid=113, flags=0x88) /
4814 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
4815 IP(src="10.0.0.101", dst="10.0.0.1") /
4816 UDP(sport=1234, dport=1234) /
4819 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
4822 # local EP pings router
4824 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
4826 IP(src=eep1.ip4, dst="10.0.0.128") /
4827 ICMP(type='echo-request'))
4829 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
4832 self.assertEqual(rx[Ether].src, str(self.router_mac))
4833 self.assertEqual(rx[Ether].dst, eep1.mac)
4834 self.assertEqual(rx[Dot1Q].vlan, 100)
4837 # local EP pings other local EP
4839 p = (Ether(src=eep1.mac, dst=eep2.mac) /
4841 IP(src=eep1.ip4, dst=eep2.ip4) /
4842 ICMP(type='echo-request'))
4844 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
4847 self.assertEqual(rx[Ether].src, eep1.mac)
4848 self.assertEqual(rx[Ether].dst, eep2.mac)
4849 self.assertEqual(rx[Dot1Q].vlan, 101)
4852 # local EP pings router w/o vlan tag poped
4854 p = (Ether(src=eep3.mac, dst=str(self.router_mac)) /
4856 IP(src=eep3.ip4, dst="10.0.0.128") /
4857 ICMP(type='echo-request'))
4859 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
4862 self.assertEqual(rx[Ether].src, str(self.router_mac))
4863 self.assertEqual(rx[Ether].dst, self.vlan_102.remote_mac)
4866 # A ip4 subnet reachable through the external EP1
4868 ip_220 = VppIpRoute(self, "10.220.0.0", 24,
4869 [VppRoutePath(eep1.ip4,
4870 eep1.epg.bvi.sw_if_index)],
4871 table_id=t4.table_id)
4872 ip_220.add_vpp_config()
4874 l3o_220 = VppGbpSubnet(
4875 self, rd1, "10.220.0.0", 24,
4876 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
4878 l3o_220.add_vpp_config()
4881 # An ip6 subnet reachable through the external EP1
4883 ip6_220 = VppIpRoute(self, "10:220::", 64,
4884 [VppRoutePath(eep1.ip6,
4885 eep1.epg.bvi.sw_if_index)],
4886 table_id=t6.table_id)
4887 ip6_220.add_vpp_config()
4889 l3o6_220 = VppGbpSubnet(
4890 self, rd1, "10:220::", 64,
4891 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
4893 l3o6_220.add_vpp_config()
4896 # A subnet reachable through the external EP2
4898 ip_221 = VppIpRoute(self, "10.221.0.0", 24,
4899 [VppRoutePath(eep2.ip4,
4900 eep2.epg.bvi.sw_if_index)],
4901 table_id=t4.table_id)
4902 ip_221.add_vpp_config()
4904 l3o_221 = VppGbpSubnet(
4905 self, rd1, "10.221.0.0", 24,
4906 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
4908 l3o_221.add_vpp_config()
4911 # ping between hosts in remote subnets
4912 # dropped without a contract
4914 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
4916 IP(src="10.220.0.1", dst="10.221.0.1") /
4917 ICMP(type='echo-request'))
4919 self.send_and_assert_no_replies(self.pg0, p * 1)
4922 # contract for the external nets to communicate
4924 rule4 = AclRule(is_permit=1, proto=17)
4925 rule6 = AclRule(src_prefix=IPv6Network((0, 0)),
4926 dst_prefix=IPv6Network((0, 0)), is_permit=1, proto=17)
4927 acl = VppAcl(self, rules=[rule4, rule6])
4928 acl.add_vpp_config()
4931 # A contract with the wrong scope is not matched
4933 c_44 = VppGbpContract(
4934 self, 44, 4220, 4221, acl.acl_index,
4935 [VppGbpContractRule(
4936 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4937 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4940 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4941 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4943 [ETH_P_IP, ETH_P_IPV6])
4944 c_44.add_vpp_config()
4945 self.send_and_assert_no_replies(self.pg0, p * 1)
4947 c1 = VppGbpContract(
4948 self, 55, 4220, 4221, acl.acl_index,
4949 [VppGbpContractRule(
4950 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4951 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4954 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4955 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4957 [ETH_P_IP, ETH_P_IPV6])
4961 # Contracts allowing ext-net 200 to talk with external EPs
4963 c2 = VppGbpContract(
4964 self, 55, 4220, 113, acl.acl_index,
4965 [VppGbpContractRule(
4966 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4967 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4970 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4971 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4973 [ETH_P_IP, ETH_P_IPV6])
4975 c3 = VppGbpContract(
4976 self, 55, 113, 4220, acl.acl_index,
4977 [VppGbpContractRule(
4978 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4979 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4982 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4983 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4985 [ETH_P_IP, ETH_P_IPV6])
4989 # ping between hosts in remote subnets
4991 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
4993 IP(src="10.220.0.1", dst="10.221.0.1") /
4994 UDP(sport=1234, dport=1234) /
4997 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
5000 self.assertEqual(rx[Ether].src, str(self.router_mac))
5001 self.assertEqual(rx[Ether].dst, eep2.mac)
5002 self.assertEqual(rx[Dot1Q].vlan, 101)
5004 # we did not learn these external hosts
5005 self.assertFalse(find_gbp_endpoint(self, ip="10.220.0.1"))
5006 self.assertFalse(find_gbp_endpoint(self, ip="10.221.0.1"))
5009 # from remote external EP to local external EP
5011 p = (Ether(src=self.pg7.remote_mac,
5012 dst=self.pg7.local_mac) /
5013 IP(src=self.pg7.remote_ip4,
5014 dst=self.pg7.local_ip4) /
5015 UDP(sport=1234, dport=48879) /
5016 VXLAN(vni=444, gpid=113, flags=0x88) /
5017 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
5018 IP(src="10.0.0.101", dst="10.220.0.1") /
5019 UDP(sport=1234, dport=1234) /
5022 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
5025 # ping from an external host to the remote external EP
5027 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
5029 IP(src="10.220.0.1", dst=rep.ip4) /
5030 UDP(sport=1234, dport=1234) /
5033 rxs = self.send_and_expect(self.pg0, p * 1, self.pg7)
5036 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
5037 # self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
5038 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
5039 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
5040 self.assertEqual(rx[VXLAN].vni, 444)
5041 self.assertTrue(rx[VXLAN].flags.G)
5042 self.assertTrue(rx[VXLAN].flags.Instance)
5043 # the sclass of the ext-net the packet came from
5044 self.assertEqual(rx[VXLAN].gpid, 4220)
5045 # policy was applied to the original IP packet
5046 self.assertTrue(rx[VXLAN].gpflags.A)
5047 # since it's an external host the reciever should not learn it
5048 self.assertTrue(rx[VXLAN].gpflags.D)
5049 inner = rx[VXLAN].payload
5050 self.assertEqual(inner[IP].src, "10.220.0.1")
5051 self.assertEqual(inner[IP].dst, rep.ip4)
5054 # An external subnet reachable via the remote external EP
5058 # first the VXLAN-GBP tunnel over which it is reached
5060 vx_tun_r1 = VppVxlanGbpTunnel(
5061 self, self.pg7.local_ip4,
5062 self.pg7.remote_ip4, 445,
5063 mode=(VppEnum.vl_api_vxlan_gbp_api_tunnel_mode_t.
5064 VXLAN_GBP_API_TUNNEL_MODE_L3))
5065 vx_tun_r1.add_vpp_config()
5066 VppIpInterfaceBind(self, vx_tun_r1, t4).add_vpp_config()
5068 self.logger.info(self.vapi.cli("sh vxlan-gbp tunnel"))
5071 # then the special adj to resolve through on that tunnel
5073 n1 = VppNeighbor(self,
5074 vx_tun_r1.sw_if_index,
5075 "00:0c:0c:0c:0c:0c",
5076 self.pg7.remote_ip4)
5080 # the route via the adj above
5082 ip_222 = VppIpRoute(self, "10.222.0.0", 24,
5083 [VppRoutePath(self.pg7.remote_ip4,
5084 vx_tun_r1.sw_if_index)],
5085 table_id=t4.table_id)
5086 ip_222.add_vpp_config()
5088 l3o_222 = VppGbpSubnet(
5089 self, rd1, "10.222.0.0", 24,
5090 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
5092 l3o_222.add_vpp_config()
5095 # ping between hosts in local and remote external subnets
5096 # dropped without a contract
5098 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
5100 IP(src="10.220.0.1", dst="10.222.0.1") /
5101 UDP(sport=1234, dport=1234) /
5104 rxs = self.send_and_assert_no_replies(self.pg0, p * 1)
5107 # Add contracts ext-nets for 220 -> 222
5109 c4 = VppGbpContract(
5110 self, 55, 4220, 4222, acl.acl_index,
5111 [VppGbpContractRule(
5112 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5113 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5116 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5117 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5119 [ETH_P_IP, ETH_P_IPV6])
5123 # ping from host in local to remote external subnets
5125 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
5127 IP(src="10.220.0.1", dst="10.222.0.1") /
5128 UDP(sport=1234, dport=1234) /
5131 rxs = self.send_and_expect(self.pg0, p * 3, self.pg7)
5134 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
5135 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
5136 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
5137 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
5138 self.assertEqual(rx[VXLAN].vni, 445)
5139 self.assertTrue(rx[VXLAN].flags.G)
5140 self.assertTrue(rx[VXLAN].flags.Instance)
5141 # the sclass of the ext-net the packet came from
5142 self.assertEqual(rx[VXLAN].gpid, 4220)
5143 # policy was applied to the original IP packet
5144 self.assertTrue(rx[VXLAN].gpflags.A)
5145 # since it's an external host the reciever should not learn it
5146 self.assertTrue(rx[VXLAN].gpflags.D)
5147 inner = rx[VXLAN].payload
5148 self.assertEqual(inner[Ether].dst, "00:0c:0c:0c:0c:0c")
5149 self.assertEqual(inner[IP].src, "10.220.0.1")
5150 self.assertEqual(inner[IP].dst, "10.222.0.1")
5153 # make the external subnet ECMP
5155 vx_tun_r2 = VppVxlanGbpTunnel(
5156 self, self.pg7.local_ip4,
5157 self.pg7.remote_ip4, 446,
5158 mode=(VppEnum.vl_api_vxlan_gbp_api_tunnel_mode_t.
5159 VXLAN_GBP_API_TUNNEL_MODE_L3))
5160 vx_tun_r2.add_vpp_config()
5161 VppIpInterfaceBind(self, vx_tun_r2, t4).add_vpp_config()
5163 self.logger.info(self.vapi.cli("sh vxlan-gbp tunnel"))
5165 n2 = VppNeighbor(self,
5166 vx_tun_r2.sw_if_index,
5167 "00:0c:0c:0c:0c:0c",
5168 self.pg7.remote_ip4)
5171 ip_222.modify([VppRoutePath(self.pg7.remote_ip4,
5172 vx_tun_r1.sw_if_index),
5173 VppRoutePath(self.pg7.remote_ip4,
5174 vx_tun_r2.sw_if_index)])
5177 # now expect load-balance
5179 p = [(Ether(src=eep1.mac, dst=str(self.router_mac)) /
5181 IP(src="10.220.0.1", dst="10.222.0.1") /
5182 UDP(sport=1234, dport=1234) /
5183 Raw(b'\xa5' * 100)),
5184 (Ether(src=eep1.mac, dst=str(self.router_mac)) /
5186 IP(src="10.220.0.1", dst="10.222.0.1") /
5187 UDP(sport=1222, dport=1235) /
5188 Raw(b'\xa5' * 100))]
5190 rxs = self.send_and_expect(self.pg0, p, self.pg7)
5192 self.assertEqual(rxs[0][VXLAN].vni, 445)
5193 self.assertEqual(rxs[1][VXLAN].vni, 446)
5196 # Same LB test for v6
5198 n3 = VppNeighbor(self,
5199 vx_tun_r1.sw_if_index,
5200 "00:0c:0c:0c:0c:0c",
5201 self.pg7.remote_ip6)
5203 n4 = VppNeighbor(self,
5204 vx_tun_r2.sw_if_index,
5205 "00:0c:0c:0c:0c:0c",
5206 self.pg7.remote_ip6)
5209 ip_222_6 = VppIpRoute(self, "10:222::", 64,
5210 [VppRoutePath(self.pg7.remote_ip6,
5211 vx_tun_r1.sw_if_index),
5212 VppRoutePath(self.pg7.remote_ip6,
5213 vx_tun_r2.sw_if_index)],
5214 table_id=t6.table_id)
5215 ip_222_6.add_vpp_config()
5217 l3o_222_6 = VppGbpSubnet(
5218 self, rd1, "10:222::", 64,
5219 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
5221 l3o_222_6.add_vpp_config()
5223 p = [(Ether(src=eep1.mac, dst=str(self.router_mac)) /
5225 IPv6(src="10:220::1", dst="10:222::1") /
5226 UDP(sport=1234, dport=1234) /
5227 Raw(b'\xa5' * 100)),
5228 (Ether(src=eep1.mac, dst=str(self.router_mac)) /
5230 IPv6(src="10:220::1", dst="10:222::1") /
5231 UDP(sport=7777, dport=8881) /
5232 Raw(b'\xa5' * 100))]
5234 self.logger.info(self.vapi.cli("sh ip6 fib 10:222::1"))
5235 rxs = self.send_and_expect(self.pg0, p, self.pg7)
5237 self.assertEqual(rxs[0][VXLAN].vni, 445)
5238 self.assertEqual(rxs[1][VXLAN].vni, 446)
5241 # ping from host in remote to local external subnets
5242 # there's no contract for this, but the A bit is set.
5244 p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
5245 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
5246 UDP(sport=1234, dport=48879) /
5247 VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
5248 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
5249 IP(src="10.222.0.1", dst="10.220.0.1") /
5250 UDP(sport=1234, dport=1234) /
5253 rxs = self.send_and_expect(self.pg7, p * 3, self.pg0)
5254 self.assertFalse(find_gbp_endpoint(self, ip="10.222.0.1"))
5257 # ping from host in remote to remote external subnets
5258 # this is dropped by reflection check.
5260 p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
5261 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
5262 UDP(sport=1234, dport=48879) /
5263 VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
5264 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
5265 IP(src="10.222.0.1", dst="10.222.0.2") /
5266 UDP(sport=1234, dport=1234) /
5269 rxs = self.send_and_assert_no_replies(self.pg7, p * 3)
5271 p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
5272 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
5273 UDP(sport=1234, dport=48879) /
5274 VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
5275 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
5276 IPv6(src="10:222::1", dst="10:222::2") /
5277 UDP(sport=1234, dport=1234) /
5280 rxs = self.send_and_assert_no_replies(self.pg7, p * 3)
5285 lep1 = VppGbpEndpoint(self, vlan_144,
5287 "10.0.0.44", "11.0.0.44",
5288 "2001:10::44", "3001::44")
5289 lep1.add_vpp_config()
5292 # local EP to local ip4 external subnet
5294 p = (Ether(src=lep1.mac, dst=str(self.router_mac)) /
5296 IP(src=lep1.ip4, dst="10.220.0.1") /
5297 UDP(sport=1234, dport=1234) /
5300 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
5303 self.assertEqual(rx[Ether].src, str(self.router_mac))
5304 self.assertEqual(rx[Ether].dst, eep1.mac)
5305 self.assertEqual(rx[Dot1Q].vlan, 100)
5308 # local EP to local ip6 external subnet
5310 p = (Ether(src=lep1.mac, dst=str(self.router_mac)) /
5312 IPv6(src=lep1.ip6, dst="10:220::1") /
5313 UDP(sport=1234, dport=1234) /
5316 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
5319 self.assertEqual(rx[Ether].src, str(self.router_mac))
5320 self.assertEqual(rx[Ether].dst, eep1.mac)
5321 self.assertEqual(rx[Dot1Q].vlan, 100)
5324 # ip4 and ip6 subnets that load-balance
5326 ip_20 = VppIpRoute(self, "10.20.0.0", 24,
5327 [VppRoutePath(eep1.ip4,
5328 eep1.epg.bvi.sw_if_index),
5329 VppRoutePath(eep2.ip4,
5330 eep2.epg.bvi.sw_if_index)],
5331 table_id=t4.table_id)
5332 ip_20.add_vpp_config()
5334 l3o_20 = VppGbpSubnet(
5335 self, rd1, "10.20.0.0", 24,
5336 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
5338 l3o_20.add_vpp_config()
5340 ip6_20 = VppIpRoute(self, "10:20::", 64,
5341 [VppRoutePath(eep1.ip6,
5342 eep1.epg.bvi.sw_if_index),
5343 VppRoutePath(eep2.ip6,
5344 eep2.epg.bvi.sw_if_index)],
5345 table_id=t6.table_id)
5346 ip6_20.add_vpp_config()
5348 l3o6_20 = VppGbpSubnet(
5349 self, rd1, "10:20::", 64,
5350 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
5352 l3o6_20.add_vpp_config()
5354 self.logger.info(self.vapi.cli("sh ip fib 10.20.0.1"))
5355 self.logger.info(self.vapi.cli("sh ip6 fib 10:20::1"))
5357 # two ip6 packets whose port are chosen so they load-balance
5358 p = [(Ether(src=lep1.mac, dst=str(self.router_mac)) /
5360 IPv6(src=lep1.ip6, dst="10:20::1") /
5361 UDP(sport=1234, dport=1234) /
5362 Raw(b'\xa5' * 100)),
5363 (Ether(src=lep1.mac, dst=str(self.router_mac)) /
5365 IPv6(src=lep1.ip6, dst="10:20::1") /
5366 UDP(sport=124, dport=1230) /
5367 Raw(b'\xa5' * 100))]
5369 rxs = self.send_and_expect(self.pg0, p, self.pg0, 2)
5371 self.assertEqual(rxs[0][Dot1Q].vlan, 101)
5372 self.assertEqual(rxs[1][Dot1Q].vlan, 100)
5374 # two ip4 packets whose port are chosen so they load-balance
5375 p = [(Ether(src=lep1.mac, dst=str(self.router_mac)) /
5377 IP(src=lep1.ip4, dst="10.20.0.1") /
5378 UDP(sport=1235, dport=1235) /
5379 Raw(b'\xa5' * 100)),
5380 (Ether(src=lep1.mac, dst=str(self.router_mac)) /
5382 IP(src=lep1.ip4, dst="10.20.0.1") /
5383 UDP(sport=124, dport=1230) /
5384 Raw(b'\xa5' * 100))]
5386 rxs = self.send_and_expect(self.pg0, p, self.pg0, 2)
5388 self.assertEqual(rxs[0][Dot1Q].vlan, 101)
5389 self.assertEqual(rxs[1][Dot1Q].vlan, 100)
5394 ip_222.remove_vpp_config()
5395 self.pg7.unconfig_ip4()
5396 self.vlan_101.set_vtr(L2_VTR_OP.L2_DISABLED)
5397 self.vlan_100.set_vtr(L2_VTR_OP.L2_DISABLED)
5399 def test_gbp_anon_l3_out(self):
5400 """ GBP Anonymous L3 Out """
5402 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
5403 self.vapi.cli("set logging class gbp level debug")
5405 routed_dst_mac = "00:0c:0c:0c:0c:0c"
5406 routed_src_mac = "00:22:bd:f8:19:ff"
5411 t4 = VppIpTable(self, 1)
5413 t6 = VppIpTable(self, 1, True)
5416 rd1 = VppGbpRouteDomain(self, 2, 55, t4, t6)
5417 rd1.add_vpp_config()
5419 self.loop0.set_mac(self.router_mac)
5422 # Bind the BVI to the RD
5424 bind_l0_ip4 = VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
5425 bind_l0_ip6 = VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
5428 # Pg7 hosts a BD's BUM
5429 # Pg1 some other l3 interface
5431 self.pg7.config_ip4()
5432 self.pg7.resolve_arp()
5435 # a GBP external bridge domains for the EPs
5437 bd1 = VppBridgeDomain(self, 1)
5438 bd1.add_vpp_config()
5439 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0, None, None)
5440 gbd1.add_vpp_config()
5443 # The Endpoint-groups in which the external endpoints exist
5445 epg_220 = VppGbpEndpointGroup(self, 220, 113, rd1, gbd1,
5449 VppGbpEndpointRetention(4))
5450 epg_220.add_vpp_config()
5452 # the BVIs have the subnet applied ...
5453 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi,
5455 bind=bind_l0_ip4).add_vpp_config()
5457 # ... which is an Anonymous L3-out subnets
5458 l3o_1 = VppGbpSubnet(
5459 self, rd1, "10.0.0.0", 24,
5460 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_ANON_L3_OUT,
5462 l3o_1.add_vpp_config()
5465 # an external interface attached to the outside world and the
5468 VppL2Vtr(self, self.vlan_100, L2_VTR_OP.L2_POP_1).add_vpp_config()
5469 VppL2Vtr(self, self.vlan_101, L2_VTR_OP.L2_POP_1).add_vpp_config()
5472 # vlan_100 and vlan_101 are anonymous l3-out interfaces
5474 ext_itf = VppGbpExtItf(self, self.vlan_100, bd1, rd1, anon=True)
5475 ext_itf.add_vpp_config()
5476 ext_itf = VppGbpExtItf(self, self.vlan_101, bd1, rd1, anon=True)
5477 ext_itf.add_vpp_config()
5480 # an unicast vxlan-gbp for inter-RD traffic
5482 vx_tun_l3 = VppGbpVxlanTunnel(
5483 self, 444, rd1.rd_id,
5484 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
5486 vx_tun_l3.add_vpp_config()
5489 # A remote external endpoint
5491 rep = VppGbpEndpoint(self, vx_tun_l3,
5493 "10.0.0.201", "11.0.0.201",
5494 "2001:10::201", "3001::101",
5495 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
5497 self.pg7.remote_ip4,
5499 rep.add_vpp_config()
5502 # ARP packet from host in external subnet are accepted, flooded and
5503 # replied to. We expect 2 packets:
5504 # - APR request flooded over the other vlan subif
5505 # - ARP reply from BVI
5507 p_arp = (Ether(src=self.vlan_100.remote_mac,
5508 dst="ff:ff:ff:ff:ff:ff") /
5513 hwsrc=self.vlan_100.remote_mac,
5514 hwdst="ff:ff:ff:ff:ff:ff"))
5515 rxs = self.send_and_expect(self.pg0, p_arp * 1, self.pg0, n_rx=2)
5517 p_arp = (Ether(src=self.vlan_101.remote_mac,
5518 dst="ff:ff:ff:ff:ff:ff") /
5523 hwsrc=self.vlan_101.remote_mac,
5524 hwdst="ff:ff:ff:ff:ff:ff"))
5525 rxs = self.send_and_expect(self.pg0, p_arp * 1, self.pg0, n_rx=2)
5528 # remote to external
5530 p = (Ether(src=self.pg7.remote_mac,
5531 dst=self.pg7.local_mac) /
5532 IP(src=self.pg7.remote_ip4,
5533 dst=self.pg7.local_ip4) /
5534 UDP(sport=1234, dport=48879) /
5535 VXLAN(vni=vx_tun_l3.vni, gpid=epg_220.sclass, flags=0x88) /
5536 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
5537 IP(src=str(rep.ip4), dst="10.0.0.100") /
5538 UDP(sport=1234, dport=1234) /
5540 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
5543 # local EP pings router
5545 p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
5547 IP(src="10.0.0.100", dst="10.0.0.128") /
5548 ICMP(type='echo-request'))
5549 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
5552 self.assertEqual(rx[Ether].src, str(self.router_mac))
5553 self.assertEqual(rx[Ether].dst, self.vlan_100.remote_mac)
5554 self.assertEqual(rx[Dot1Q].vlan, 100)
5557 # local EP pings other local EP
5559 p = (Ether(src=self.vlan_100.remote_mac,
5560 dst=self.vlan_101.remote_mac) /
5562 IP(src="10.0.0.100", dst="10.0.0.101") /
5563 ICMP(type='echo-request'))
5564 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
5567 self.assertEqual(rx[Ether].src, self.vlan_100.remote_mac)
5568 self.assertEqual(rx[Ether].dst, self.vlan_101.remote_mac)
5569 self.assertEqual(rx[Dot1Q].vlan, 101)
5572 # A subnet reachable through an external router on vlan 100
5574 ip_220 = VppIpRoute(self, "10.220.0.0", 24,
5575 [VppRoutePath("10.0.0.100",
5576 epg_220.bvi.sw_if_index)],
5577 table_id=t4.table_id)
5578 ip_220.add_vpp_config()
5580 l3o_220 = VppGbpSubnet(
5581 self, rd1, "10.220.0.0", 24,
5582 # note: this a "regular" L3 out subnet (not connected)
5583 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
5585 l3o_220.add_vpp_config()
5588 # A subnet reachable through an external router on vlan 101
5590 ip_221 = VppIpRoute(self, "10.221.0.0", 24,
5591 [VppRoutePath("10.0.0.101",
5592 epg_220.bvi.sw_if_index)],
5593 table_id=t4.table_id)
5594 ip_221.add_vpp_config()
5596 l3o_221 = VppGbpSubnet(
5597 self, rd1, "10.221.0.0", 24,
5598 # note: this a "regular" L3 out subnet (not connected)
5599 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
5601 l3o_221.add_vpp_config()
5604 # ping between hosts in remote subnets
5605 # dropped without a contract
5607 p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
5609 IP(src="10.220.0.1", dst="10.221.0.1") /
5610 ICMP(type='echo-request'))
5612 rxs = self.send_and_assert_no_replies(self.pg0, p * 1)
5615 # contract for the external nets to communicate
5617 rule4 = AclRule(is_permit=1, proto=17)
5618 rule6 = AclRule(src_prefix=IPv6Network((0, 0)),
5619 dst_prefix=IPv6Network((0, 0)), is_permit=1, proto=17)
5620 acl = VppAcl(self, rules=[rule4, rule6])
5621 acl.add_vpp_config()
5623 c1 = VppGbpContract(
5624 self, 55, 4220, 4221, acl.acl_index,
5625 [VppGbpContractRule(
5626 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5627 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5630 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5631 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5633 [ETH_P_IP, ETH_P_IPV6])
5637 # Contracts allowing ext-net 200 to talk with external EPs
5639 c2 = VppGbpContract(
5640 self, 55, 4220, 113, acl.acl_index,
5641 [VppGbpContractRule(
5642 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5643 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5646 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5647 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5649 [ETH_P_IP, ETH_P_IPV6])
5651 c3 = VppGbpContract(
5652 self, 55, 113, 4220, acl.acl_index,
5653 [VppGbpContractRule(
5654 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5655 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5658 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5659 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5661 [ETH_P_IP, ETH_P_IPV6])
5665 # ping between hosts in remote subnets
5667 p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
5669 IP(src="10.220.0.1", dst="10.221.0.1") /
5670 UDP(sport=1234, dport=1234) /
5673 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
5676 self.assertEqual(rx[Ether].src, str(self.router_mac))
5677 self.assertEqual(rx[Ether].dst, self.vlan_101.remote_mac)
5678 self.assertEqual(rx[Dot1Q].vlan, 101)
5680 # we did not learn these external hosts
5681 self.assertFalse(find_gbp_endpoint(self, ip="10.220.0.1"))
5682 self.assertFalse(find_gbp_endpoint(self, ip="10.221.0.1"))
5685 # from remote external EP to local external EP
5687 p = (Ether(src=self.pg7.remote_mac,
5688 dst=self.pg7.local_mac) /
5689 IP(src=self.pg7.remote_ip4,
5690 dst=self.pg7.local_ip4) /
5691 UDP(sport=1234, dport=48879) /
5692 VXLAN(vni=444, gpid=113, flags=0x88) /
5693 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
5694 IP(src=rep.ip4, dst="10.220.0.1") /
5695 UDP(sport=1234, dport=1234) /
5698 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
5701 # ping from an external host to the remote external EP
5703 p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
5705 IP(src="10.220.0.1", dst=rep.ip4) /
5706 UDP(sport=1234, dport=1234) /
5709 rxs = self.send_and_expect(self.pg0, p * 1, self.pg7)
5712 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
5713 # self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
5714 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
5715 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
5716 self.assertEqual(rx[VXLAN].vni, 444)
5717 self.assertTrue(rx[VXLAN].flags.G)
5718 self.assertTrue(rx[VXLAN].flags.Instance)
5719 # the sclass of the ext-net the packet came from
5720 self.assertEqual(rx[VXLAN].gpid, 4220)
5721 # policy was applied to the original IP packet
5722 self.assertTrue(rx[VXLAN].gpflags.A)
5723 # since it's an external host the reciever should not learn it
5724 self.assertTrue(rx[VXLAN].gpflags.D)
5725 inner = rx[VXLAN].payload
5726 self.assertEqual(inner[IP].src, "10.220.0.1")
5727 self.assertEqual(inner[IP].dst, rep.ip4)
5730 # An external subnet reachable via the remote external EP
5734 # first the VXLAN-GBP tunnel over which it is reached
5736 vx_tun_r = VppVxlanGbpTunnel(
5737 self, self.pg7.local_ip4,
5738 self.pg7.remote_ip4, 445,
5739 mode=(VppEnum.vl_api_vxlan_gbp_api_tunnel_mode_t.
5740 VXLAN_GBP_API_TUNNEL_MODE_L3))
5741 vx_tun_r.add_vpp_config()
5742 VppIpInterfaceBind(self, vx_tun_r, t4).add_vpp_config()
5744 self.logger.info(self.vapi.cli("sh vxlan-gbp tunnel"))
5747 # then the special adj to resolve through on that tunnel
5749 n1 = VppNeighbor(self,
5750 vx_tun_r.sw_if_index,
5751 "00:0c:0c:0c:0c:0c",
5752 self.pg7.remote_ip4)
5756 # the route via the adj above
5758 ip_222 = VppIpRoute(self, "10.222.0.0", 24,
5759 [VppRoutePath(self.pg7.remote_ip4,
5760 vx_tun_r.sw_if_index)],
5761 table_id=t4.table_id)
5762 ip_222.add_vpp_config()
5764 l3o_222 = VppGbpSubnet(
5765 self, rd1, "10.222.0.0", 24,
5766 # note: this a "regular" l3out subnet (not connected)
5767 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
5769 l3o_222.add_vpp_config()
5772 # ping between hosts in local and remote external subnets
5773 # dropped without a contract
5775 p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
5777 IP(src="10.220.0.1", dst="10.222.0.1") /
5778 UDP(sport=1234, dport=1234) /
5781 rxs = self.send_and_assert_no_replies(self.pg0, p * 1)
5784 # Add contracts ext-nets for 220 -> 222
5786 c4 = VppGbpContract(
5787 self, 55, 4220, 4222, acl.acl_index,
5788 [VppGbpContractRule(
5789 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5790 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5793 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5794 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5796 [ETH_P_IP, ETH_P_IPV6])
5800 # ping from host in local to remote external subnets
5802 p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
5804 IP(src="10.220.0.1", dst="10.222.0.1") /
5805 UDP(sport=1234, dport=1234) /
5808 rxs = self.send_and_expect(self.pg0, p * 3, self.pg7)
5811 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
5812 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
5813 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
5814 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
5815 self.assertEqual(rx[VXLAN].vni, 445)
5816 self.assertTrue(rx[VXLAN].flags.G)
5817 self.assertTrue(rx[VXLAN].flags.Instance)
5818 # the sclass of the ext-net the packet came from
5819 self.assertEqual(rx[VXLAN].gpid, 4220)
5820 # policy was applied to the original IP packet
5821 self.assertTrue(rx[VXLAN].gpflags.A)
5822 # since it's an external host the reciever should not learn it
5823 self.assertTrue(rx[VXLAN].gpflags.D)
5824 inner = rx[VXLAN].payload
5825 self.assertEqual(inner[Ether].dst, "00:0c:0c:0c:0c:0c")
5826 self.assertEqual(inner[IP].src, "10.220.0.1")
5827 self.assertEqual(inner[IP].dst, "10.222.0.1")
5830 # ping from host in remote to local external subnets
5831 # there's no contract for this, but the A bit is set.
5833 p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
5834 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
5835 UDP(sport=1234, dport=48879) /
5836 VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
5837 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
5838 IP(src="10.222.0.1", dst="10.220.0.1") /
5839 UDP(sport=1234, dport=1234) /
5842 rxs = self.send_and_expect(self.pg7, p * 3, self.pg0)
5843 self.assertFalse(find_gbp_endpoint(self, ip="10.222.0.1"))
5846 # ping from host in remote to remote external subnets
5847 # this is dropped by reflection check.
5849 p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
5850 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
5851 UDP(sport=1234, dport=48879) /
5852 VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
5853 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
5854 IP(src="10.222.0.1", dst="10.222.0.2") /
5855 UDP(sport=1234, dport=1234) /
5858 rxs = self.send_and_assert_no_replies(self.pg7, p * 3)
5863 self.vlan_101.set_vtr(L2_VTR_OP.L2_DISABLED)
5864 self.vlan_100.set_vtr(L2_VTR_OP.L2_DISABLED)
5865 self.pg7.unconfig_ip4()
5866 # make sure the programmed EP is no longer learnt from DP
5867 self.wait_for_ep_timeout(sw_if_index=rep.itf.sw_if_index, ip=rep.ip4)
5870 if __name__ == '__main__':
5871 unittest.main(testRunner=VppTestRunner)