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 config_flags(self):
580 return VppEnum.vl_api_nat_config_flags_t
584 super(TestGBP, cls).setUpClass()
587 def tearDownClass(cls):
588 super(TestGBP, cls).tearDownClass()
591 super(TestGBP, self).setUp()
593 self.create_pg_interfaces(range(9))
594 self.create_loopback_interfaces(8)
596 self.router_mac = MACAddress("00:11:22:33:44:55")
598 for i in self.pg_interfaces:
600 for i in self.lo_interfaces:
603 self.vlan_100 = VppDot1QSubint(self, self.pg0, 100)
604 self.vlan_100.admin_up()
605 self.vlan_101 = VppDot1QSubint(self, self.pg0, 101)
606 self.vlan_101.admin_up()
607 self.vlan_102 = VppDot1QSubint(self, self.pg0, 102)
608 self.vlan_102.admin_up()
611 for i in self.pg_interfaces:
613 super(TestGBP, self).tearDown()
614 for i in self.lo_interfaces:
615 i.remove_vpp_config()
616 self.lo_interfaces = []
617 self.vlan_102.remove_vpp_config()
618 self.vlan_101.remove_vpp_config()
619 self.vlan_100.remove_vpp_config()
621 def send_and_expect_bridged(self, src, tx, dst):
622 rx = self.send_and_expect(src, tx, dst)
625 self.assertEqual(r[Ether].src, tx[0][Ether].src)
626 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
627 self.assertEqual(r[IP].src, tx[0][IP].src)
628 self.assertEqual(r[IP].dst, tx[0][IP].dst)
631 def send_and_expect_bridged6(self, src, tx, dst):
632 rx = self.send_and_expect(src, tx, dst)
635 self.assertEqual(r[Ether].src, tx[0][Ether].src)
636 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
637 self.assertEqual(r[IPv6].src, tx[0][IPv6].src)
638 self.assertEqual(r[IPv6].dst, tx[0][IPv6].dst)
641 def send_and_expect_routed(self, src, tx, dst, src_mac):
642 rx = self.send_and_expect(src, tx, dst)
645 self.assertEqual(r[Ether].src, src_mac)
646 self.assertEqual(r[Ether].dst, dst.remote_mac)
647 self.assertEqual(r[IP].src, tx[0][IP].src)
648 self.assertEqual(r[IP].dst, tx[0][IP].dst)
651 def send_and_expect_routed6(self, src, tx, dst, src_mac):
652 rx = self.send_and_expect(src, tx, dst)
655 self.assertEqual(r[Ether].src, src_mac)
656 self.assertEqual(r[Ether].dst, dst.remote_mac)
657 self.assertEqual(r[IPv6].src, tx[0][IPv6].src)
658 self.assertEqual(r[IPv6].dst, tx[0][IPv6].dst)
661 def send_and_expect_natted(self, src, tx, dst, src_ip):
662 rx = self.send_and_expect(src, tx, dst)
665 self.assertEqual(r[Ether].src, tx[0][Ether].src)
666 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
667 self.assertEqual(r[IP].src, src_ip)
668 self.assertEqual(r[IP].dst, tx[0][IP].dst)
671 def send_and_expect_natted6(self, src, tx, dst, src_ip):
672 rx = self.send_and_expect(src, tx, dst)
675 self.assertEqual(r[Ether].src, tx[0][Ether].src)
676 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
677 self.assertEqual(r[IPv6].src, src_ip)
678 self.assertEqual(r[IPv6].dst, tx[0][IPv6].dst)
681 def send_and_expect_unnatted(self, src, tx, dst, dst_ip):
682 rx = self.send_and_expect(src, tx, dst)
685 self.assertEqual(r[Ether].src, tx[0][Ether].src)
686 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
687 self.assertEqual(r[IP].dst, dst_ip)
688 self.assertEqual(r[IP].src, tx[0][IP].src)
691 def send_and_expect_unnatted6(self, src, tx, dst, dst_ip):
692 rx = self.send_and_expect(src, tx, dst)
695 self.assertEqual(r[Ether].src, tx[0][Ether].src)
696 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
697 self.assertEqual(r[IPv6].dst, dst_ip)
698 self.assertEqual(r[IPv6].src, tx[0][IPv6].src)
701 def send_and_expect_double_natted(self, src, tx, dst, src_ip, dst_ip):
702 rx = self.send_and_expect(src, tx, dst)
705 self.assertEqual(r[Ether].src, str(self.router_mac))
706 self.assertEqual(r[Ether].dst, dst.remote_mac)
707 self.assertEqual(r[IP].dst, dst_ip)
708 self.assertEqual(r[IP].src, src_ip)
711 def send_and_expect_double_natted6(self, src, tx, dst, src_ip, dst_ip):
712 rx = self.send_and_expect(src, tx, dst)
715 self.assertEqual(r[Ether].src, str(self.router_mac))
716 self.assertEqual(r[Ether].dst, dst.remote_mac)
717 self.assertEqual(r[IPv6].dst, dst_ip)
718 self.assertEqual(r[IPv6].src, src_ip)
721 def send_and_expect_no_arp(self, src, tx, dst):
722 self.pg_send(src, tx)
723 dst.get_capture(0, timeout=1)
724 dst.assert_nothing_captured(remark="")
727 def send_and_expect_arp(self, src, tx, dst):
728 rx = self.send_and_expect(src, tx, dst)
731 self.assertEqual(r[Ether].src, tx[0][Ether].src)
732 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
733 self.assertEqual(r[ARP].psrc, tx[0][ARP].psrc)
734 self.assertEqual(r[ARP].pdst, tx[0][ARP].pdst)
735 self.assertEqual(r[ARP].hwsrc, tx[0][ARP].hwsrc)
736 self.assertEqual(r[ARP].hwdst, tx[0][ARP].hwdst)
740 """ Group Based Policy """
742 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
747 gt4 = VppIpTable(self, 0)
749 gt6 = VppIpTable(self, 0, is_ip6=True)
751 nt4 = VppIpTable(self, 20)
753 nt6 = VppIpTable(self, 20, is_ip6=True)
756 rd0 = VppGbpRouteDomain(self, 0, 400, gt4, gt6, None, None)
757 rd20 = VppGbpRouteDomain(self, 20, 420, nt4, nt6, None, None)
760 rd20.add_vpp_config()
765 bd1 = VppBridgeDomain(self, 1)
766 bd2 = VppBridgeDomain(self, 2)
767 bd20 = VppBridgeDomain(self, 20)
771 bd20.add_vpp_config()
773 gbd1 = VppGbpBridgeDomain(self, bd1, rd0, self.loop0)
774 gbd2 = VppGbpBridgeDomain(self, bd2, rd0, self.loop1)
775 gbd20 = VppGbpBridgeDomain(self, bd20, rd20, self.loop2)
777 gbd1.add_vpp_config()
778 gbd2.add_vpp_config()
779 gbd20.add_vpp_config()
782 # 3 EPGs, 2 of which share a BD.
783 # 2 NAT EPGs, one for floating-IP subnets, the other for internet
785 epgs = [VppGbpEndpointGroup(self, 220, 1220, rd0, gbd1,
786 self.pg4, self.loop0,
787 "10.0.0.128", "2001:10::128"),
788 VppGbpEndpointGroup(self, 221, 1221, rd0, gbd1,
789 self.pg5, self.loop0,
790 "10.0.1.128", "2001:10:1::128"),
791 VppGbpEndpointGroup(self, 222, 1222, rd0, gbd2,
792 self.pg6, self.loop1,
793 "10.0.2.128", "2001:10:2::128"),
794 VppGbpEndpointGroup(self, 333, 1333, rd20, gbd20,
795 self.pg7, self.loop2,
796 "11.0.0.128", "3001::128"),
797 VppGbpEndpointGroup(self, 444, 1444, rd20, gbd20,
798 self.pg8, self.loop2,
799 "11.0.0.129", "3001::129")]
800 recircs = [VppGbpRecirc(self, epgs[0], self.loop3),
801 VppGbpRecirc(self, epgs[1], self.loop4),
802 VppGbpRecirc(self, epgs[2], self.loop5),
803 VppGbpRecirc(self, epgs[3], self.loop6, is_ext=True),
804 VppGbpRecirc(self, epgs[4], self.loop7, is_ext=True)]
807 recirc_nat = recircs[3]
810 # 4 end-points, 2 in the same subnet, 3 in the same BD
812 eps = [VppGbpEndpoint(self, self.pg0,
814 "10.0.0.1", "11.0.0.1",
815 "2001:10::1", "3001::1"),
816 VppGbpEndpoint(self, self.pg1,
818 "10.0.0.2", "11.0.0.2",
819 "2001:10::2", "3001::2"),
820 VppGbpEndpoint(self, self.pg2,
822 "10.0.1.1", "11.0.0.3",
823 "2001:10:1::1", "3001::3"),
824 VppGbpEndpoint(self, self.pg3,
826 "10.0.2.1", "11.0.0.4",
827 "2001:10:2::1", "3001::4")]
830 # Config related to each of the EPGs
833 # IP config on the BVI interfaces
834 if epg != epgs[1] and epg != epgs[4]:
835 VppIpInterfaceBind(self, epg.bvi, epg.rd.t4).add_vpp_config()
836 VppIpInterfaceBind(self, epg.bvi, epg.rd.t6).add_vpp_config()
837 epg.bvi.set_mac(self.router_mac)
839 # The BVIs are NAT inside interfaces
840 flags = self.config_flags.NAT_IS_INSIDE
841 self.vapi.nat44_interface_add_del_feature(
842 sw_if_index=epg.bvi.sw_if_index,
843 flags=flags, is_add=1)
844 self.vapi.nat66_add_del_interface(
845 is_add=1, flags=flags,
846 sw_if_index=epg.bvi.sw_if_index)
848 if_ip4 = VppIpInterfaceAddress(self, epg.bvi, epg.bvi_ip4, 32)
849 if_ip6 = VppIpInterfaceAddress(self, epg.bvi, epg.bvi_ip6, 128)
850 if_ip4.add_vpp_config()
851 if_ip6.add_vpp_config()
853 # EPG uplink interfaces in the RD
854 VppIpInterfaceBind(self, epg.uplink, epg.rd.t4).add_vpp_config()
855 VppIpInterfaceBind(self, epg.uplink, epg.rd.t6).add_vpp_config()
857 # add the BD ARP termination entry for BVI IP
858 epg.bd_arp_ip4 = VppBridgeDomainArpEntry(self, epg.bd.bd,
859 str(self.router_mac),
861 epg.bd_arp_ip6 = VppBridgeDomainArpEntry(self, epg.bd.bd,
862 str(self.router_mac),
864 epg.bd_arp_ip4.add_vpp_config()
865 epg.bd_arp_ip6.add_vpp_config()
870 for recirc in recircs:
871 # EPG's ingress recirculation interface maps to its RD
872 VppIpInterfaceBind(self, recirc.recirc,
873 recirc.epg.rd.t4).add_vpp_config()
874 VppIpInterfaceBind(self, recirc.recirc,
875 recirc.epg.rd.t6).add_vpp_config()
877 self.vapi.nat44_interface_add_del_feature(
878 sw_if_index=recirc.recirc.sw_if_index, is_add=1)
879 self.vapi.nat66_add_del_interface(
881 sw_if_index=recirc.recirc.sw_if_index)
883 recirc.add_vpp_config()
885 for recirc in recircs:
886 self.assertTrue(find_bridge_domain_port(self,
887 recirc.epg.bd.bd.bd_id,
888 recirc.recirc.sw_if_index))
891 self.pg_enable_capture(self.pg_interfaces)
894 # routes to the endpoints. We need these since there are no
895 # adj-fibs due to the fact the the BVI address has /32 and
896 # the subnet is not attached.
898 for (ip, fip) in zip(ep.ips, ep.fips):
899 # Add static mappings for each EP from the 10/8 to 11/8 network
900 if ip_address(ip).version == 4:
901 flags = self.config_flags.NAT_IS_ADDR_ONLY
902 self.vapi.nat44_add_del_static_mapping(
905 external_ip_address=fip,
906 external_sw_if_index=0xFFFFFFFF,
910 self.vapi.nat66_add_del_static_mapping(
912 external_ip_address=fip,
918 self.logger.info(self.vapi.cli("sh gbp endpoint"))
920 # ... results in a Gratuitous ARP/ND on the EPG's uplink
921 rx = ep.epg.uplink.get_capture(len(ep.ips), timeout=0.2)
923 for ii, ip in enumerate(ep.ips):
926 if ip_address(ip).version == 6:
927 self.assertTrue(p.haslayer(ICMPv6ND_NA))
928 self.assertEqual(p[ICMPv6ND_NA].tgt, ip)
930 self.assertTrue(p.haslayer(ARP))
931 self.assertEqual(p[ARP].psrc, ip)
932 self.assertEqual(p[ARP].pdst, ip)
934 # add the BD ARP termination entry for floating IP
936 ba = VppBridgeDomainArpEntry(self, epg_nat.bd.bd, ep.mac,
940 # floating IPs route via EPG recirc
942 self, fip, ip_address(fip).max_prefixlen,
944 ep.recirc.recirc.sw_if_index,
945 type=FibPathType.FIB_PATH_TYPE_DVR,
946 proto=get_dpo_proto(fip))],
950 # L2 FIB entries in the NAT EPG BD to bridge the packets from
951 # the outside direct to the internal EPG
952 lf = VppL2FibEntry(self, epg_nat.bd.bd, ep.mac,
953 ep.recirc.recirc, bvi_mac=0)
957 # ARP packets for unknown IP are sent to the EPG uplink
959 pkt_arp = (Ether(dst="ff:ff:ff:ff:ff:ff",
960 src=self.pg0.remote_mac) /
962 hwdst="ff:ff:ff:ff:ff:ff",
963 hwsrc=self.pg0.remote_mac,
967 self.vapi.cli("clear trace")
968 self.pg0.add_stream(pkt_arp)
970 self.pg_enable_capture(self.pg_interfaces)
973 rxd = epgs[0].uplink.get_capture(1)
976 # ARP/ND packets get a response
978 pkt_arp = (Ether(dst="ff:ff:ff:ff:ff:ff",
979 src=self.pg0.remote_mac) /
981 hwdst="ff:ff:ff:ff:ff:ff",
982 hwsrc=self.pg0.remote_mac,
983 pdst=epgs[0].bvi_ip4,
986 self.send_and_expect(self.pg0, [pkt_arp], self.pg0)
988 nsma = in6_getnsma(inet_pton(AF_INET6, eps[0].ip6))
989 d = inet_ntop(AF_INET6, nsma)
990 pkt_nd = (Ether(dst=in6_getnsmac(nsma),
991 src=self.pg0.remote_mac) /
992 IPv6(dst=d, src=eps[0].ip6) /
993 ICMPv6ND_NS(tgt=epgs[0].bvi_ip6) /
994 ICMPv6NDOptSrcLLAddr(lladdr=self.pg0.remote_mac))
995 self.send_and_expect(self.pg0, [pkt_nd], self.pg0)
998 # broadcast packets are flooded
1000 pkt_bcast = (Ether(dst="ff:ff:ff:ff:ff:ff",
1001 src=self.pg0.remote_mac) /
1002 IP(src=eps[0].ip4, dst="232.1.1.1") /
1003 UDP(sport=1234, dport=1234) /
1006 self.vapi.cli("clear trace")
1007 self.pg0.add_stream(pkt_bcast)
1009 self.pg_enable_capture(self.pg_interfaces)
1012 rxd = eps[1].itf.get_capture(1)
1013 self.assertEqual(rxd[0][Ether].dst, pkt_bcast[Ether].dst)
1014 rxd = epgs[0].uplink.get_capture(1)
1015 self.assertEqual(rxd[0][Ether].dst, pkt_bcast[Ether].dst)
1018 # packets to non-local L3 destinations dropped
1020 pkt_intra_epg_220_ip4 = (Ether(src=self.pg0.remote_mac,
1021 dst=str(self.router_mac)) /
1024 UDP(sport=1234, dport=1234) /
1026 pkt_inter_epg_222_ip4 = (Ether(src=self.pg0.remote_mac,
1027 dst=str(self.router_mac)) /
1030 UDP(sport=1234, dport=1234) /
1033 self.send_and_assert_no_replies(self.pg0,
1034 pkt_intra_epg_220_ip4 * NUM_PKTS)
1036 pkt_inter_epg_222_ip6 = (Ether(src=self.pg0.remote_mac,
1037 dst=str(self.router_mac)) /
1038 IPv6(src=eps[0].ip6,
1039 dst="2001:10::99") /
1040 UDP(sport=1234, dport=1234) /
1042 self.send_and_assert_no_replies(self.pg0,
1043 pkt_inter_epg_222_ip6 * NUM_PKTS)
1046 # Add the subnet routes
1049 self, rd0, "10.0.0.0", 24,
1050 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1052 self, rd0, "10.0.1.0", 24,
1053 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1055 self, rd0, "10.0.2.0", 24,
1056 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1058 self, rd0, "2001:10::1", 64,
1059 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1061 self, rd0, "2001:10:1::1", 64,
1062 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1064 self, rd0, "2001:10:2::1", 64,
1065 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1066 s41.add_vpp_config()
1067 s42.add_vpp_config()
1068 s43.add_vpp_config()
1069 s61.add_vpp_config()
1070 s62.add_vpp_config()
1071 s63.add_vpp_config()
1073 self.send_and_expect_bridged(eps[0].itf,
1074 pkt_intra_epg_220_ip4 * NUM_PKTS,
1076 self.send_and_expect_bridged(eps[0].itf,
1077 pkt_inter_epg_222_ip4 * NUM_PKTS,
1079 self.send_and_expect_bridged6(eps[0].itf,
1080 pkt_inter_epg_222_ip6 * NUM_PKTS,
1083 self.logger.info(self.vapi.cli("sh ip fib 11.0.0.2"))
1084 self.logger.info(self.vapi.cli("sh gbp endpoint-group"))
1085 self.logger.info(self.vapi.cli("sh gbp endpoint"))
1086 self.logger.info(self.vapi.cli("sh gbp recirc"))
1087 self.logger.info(self.vapi.cli("sh int"))
1088 self.logger.info(self.vapi.cli("sh int addr"))
1089 self.logger.info(self.vapi.cli("sh int feat loop6"))
1090 self.logger.info(self.vapi.cli("sh vlib graph ip4-gbp-src-classify"))
1091 self.logger.info(self.vapi.cli("sh int feat loop3"))
1092 self.logger.info(self.vapi.cli("sh int feat pg0"))
1095 # Packet destined to unknown unicast is sent on the epg uplink ...
1097 pkt_intra_epg_220_to_uplink = (Ether(src=self.pg0.remote_mac,
1098 dst="00:00:00:33:44:55") /
1101 UDP(sport=1234, dport=1234) /
1104 self.send_and_expect_bridged(eps[0].itf,
1105 pkt_intra_epg_220_to_uplink * NUM_PKTS,
1107 # ... and nowhere else
1108 self.pg1.get_capture(0, timeout=0.1)
1109 self.pg1.assert_nothing_captured(remark="Flood onto other VMS")
1111 pkt_intra_epg_221_to_uplink = (Ether(src=self.pg2.remote_mac,
1112 dst="00:00:00:33:44:66") /
1115 UDP(sport=1234, dport=1234) /
1118 self.send_and_expect_bridged(eps[2].itf,
1119 pkt_intra_epg_221_to_uplink * NUM_PKTS,
1123 # Packets from the uplink are forwarded in the absence of a contract
1125 pkt_intra_epg_220_from_uplink = (Ether(src="00:00:00:33:44:55",
1126 dst=self.pg0.remote_mac) /
1129 UDP(sport=1234, dport=1234) /
1132 self.send_and_expect_bridged(self.pg4,
1133 pkt_intra_epg_220_from_uplink * NUM_PKTS,
1137 # in the absence of policy, endpoints in the same EPG
1140 pkt_intra_epg = (Ether(src=self.pg0.remote_mac,
1141 dst=self.pg1.remote_mac) /
1144 UDP(sport=1234, dport=1234) /
1147 self.send_and_expect_bridged(self.pg0,
1148 pkt_intra_epg * NUM_PKTS,
1152 # in the absence of policy, endpoints in the different EPG
1153 # cannot communicate
1155 pkt_inter_epg_220_to_221 = (Ether(src=self.pg0.remote_mac,
1156 dst=self.pg2.remote_mac) /
1159 UDP(sport=1234, dport=1234) /
1161 pkt_inter_epg_221_to_220 = (Ether(src=self.pg2.remote_mac,
1162 dst=self.pg0.remote_mac) /
1165 UDP(sport=1234, dport=1234) /
1167 pkt_inter_epg_220_to_222 = (Ether(src=self.pg0.remote_mac,
1168 dst=str(self.router_mac)) /
1171 UDP(sport=1234, dport=1234) /
1174 self.send_and_assert_no_replies(eps[0].itf,
1175 pkt_inter_epg_220_to_221 * NUM_PKTS)
1176 self.send_and_assert_no_replies(eps[0].itf,
1177 pkt_inter_epg_220_to_222 * NUM_PKTS)
1180 # A uni-directional contract from EPG 220 -> 221
1182 rule = AclRule(is_permit=1, proto=17)
1183 rule2 = AclRule(src_prefix=IPv6Network((0, 0)),
1184 dst_prefix=IPv6Network((0, 0)), is_permit=1, proto=17)
1185 acl = VppAcl(self, rules=[rule, rule2])
1186 acl.add_vpp_config()
1188 c1 = VppGbpContract(
1189 self, 400, epgs[0].sclass, epgs[1].sclass, acl.acl_index,
1190 [VppGbpContractRule(
1191 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1192 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1195 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1196 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1198 [ETH_P_IP, ETH_P_IPV6])
1201 self.send_and_expect_bridged(eps[0].itf,
1202 pkt_inter_epg_220_to_221 * NUM_PKTS,
1204 self.send_and_assert_no_replies(eps[0].itf,
1205 pkt_inter_epg_220_to_222 * NUM_PKTS)
1208 # contract for the return direction
1210 c2 = VppGbpContract(
1211 self, 400, epgs[1].sclass, epgs[0].sclass, acl.acl_index,
1212 [VppGbpContractRule(
1213 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1214 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1217 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1218 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1220 [ETH_P_IP, ETH_P_IPV6])
1223 self.send_and_expect_bridged(eps[0].itf,
1224 pkt_inter_epg_220_to_221 * NUM_PKTS,
1226 self.send_and_expect_bridged(eps[2].itf,
1227 pkt_inter_epg_221_to_220 * NUM_PKTS,
1230 ds = c2.get_drop_stats()
1231 self.assertEqual(ds['packets'], 0)
1232 ps = c2.get_permit_stats()
1233 self.assertEqual(ps['packets'], NUM_PKTS)
1236 # the contract does not allow non-IP
1238 pkt_non_ip_inter_epg_220_to_221 = (Ether(src=self.pg0.remote_mac,
1239 dst=self.pg2.remote_mac) /
1241 self.send_and_assert_no_replies(eps[0].itf,
1242 pkt_non_ip_inter_epg_220_to_221 * 17)
1245 # check that inter group is still disabled for the groups
1246 # not in the contract.
1248 self.send_and_assert_no_replies(eps[0].itf,
1249 pkt_inter_epg_220_to_222 * NUM_PKTS)
1252 # A uni-directional contract from EPG 220 -> 222 'L3 routed'
1254 c3 = VppGbpContract(
1255 self, 400, epgs[0].sclass, epgs[2].sclass, acl.acl_index,
1256 [VppGbpContractRule(
1257 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1258 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1261 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1262 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1264 [ETH_P_IP, ETH_P_IPV6])
1267 self.logger.info(self.vapi.cli("sh gbp contract"))
1269 self.send_and_expect_routed(eps[0].itf,
1270 pkt_inter_epg_220_to_222 * NUM_PKTS,
1272 str(self.router_mac))
1275 # remove both contracts, traffic stops in both directions
1277 c2.remove_vpp_config()
1278 c1.remove_vpp_config()
1279 c3.remove_vpp_config()
1280 acl.remove_vpp_config()
1282 self.send_and_assert_no_replies(eps[2].itf,
1283 pkt_inter_epg_221_to_220 * NUM_PKTS)
1284 self.send_and_assert_no_replies(eps[0].itf,
1285 pkt_inter_epg_220_to_221 * NUM_PKTS)
1286 self.send_and_expect_bridged(eps[0].itf,
1287 pkt_intra_epg * NUM_PKTS,
1291 # EPs to the outside world
1294 # in the EP's RD an external subnet via the NAT EPG's recirc
1296 self, rd0, "0.0.0.0", 0,
1297 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1298 sw_if_index=recirc_nat.recirc.sw_if_index,
1299 sclass=epg_nat.sclass)
1301 self, rd0, "11.0.0.0", 8,
1302 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1303 sw_if_index=recirc_nat.recirc.sw_if_index,
1304 sclass=epg_nat.sclass)
1305 se16 = VppGbpSubnet(
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)
1310 # in the NAT RD an external subnet via the NAT EPG's uplink
1312 self, rd20, "0.0.0.0", 0,
1313 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1314 sw_if_index=epg_nat.uplink.sw_if_index,
1315 sclass=epg_nat.sclass)
1316 se36 = VppGbpSubnet(
1317 self, rd20, "::", 0,
1318 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1319 sw_if_index=epg_nat.uplink.sw_if_index,
1320 sclass=epg_nat.sclass)
1322 self, rd20, "11.0.0.0", 8,
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 se1.add_vpp_config()
1327 se2.add_vpp_config()
1328 se16.add_vpp_config()
1329 se3.add_vpp_config()
1330 se36.add_vpp_config()
1331 se4.add_vpp_config()
1333 self.logger.info(self.vapi.cli("sh ip fib 0.0.0.0/0"))
1334 self.logger.info(self.vapi.cli("sh ip fib 11.0.0.1"))
1335 self.logger.info(self.vapi.cli("sh ip6 fib ::/0"))
1336 self.logger.info(self.vapi.cli("sh ip6 fib %s" %
1340 # From an EP to an outside address: IN2OUT
1342 pkt_inter_epg_220_to_global = (Ether(src=self.pg0.remote_mac,
1343 dst=str(self.router_mac)) /
1346 UDP(sport=1234, dport=1234) /
1350 self.send_and_assert_no_replies(eps[0].itf,
1351 pkt_inter_epg_220_to_global * NUM_PKTS)
1352 rule = AclRule(is_permit=1, proto=17, ports=1234)
1353 rule2 = AclRule(is_permit=1, proto=17, ports=1234,
1354 src_prefix=IPv6Network((0, 0)),
1355 dst_prefix=IPv6Network((0, 0)))
1356 acl2 = VppAcl(self, rules=[rule, rule2])
1357 acl2.add_vpp_config()
1359 c4 = VppGbpContract(
1360 self, 400, epgs[0].sclass, epgs[3].sclass, acl2.acl_index,
1361 [VppGbpContractRule(
1362 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1363 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1366 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1367 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1369 [ETH_P_IP, ETH_P_IPV6])
1372 self.send_and_expect_natted(eps[0].itf,
1373 pkt_inter_epg_220_to_global * NUM_PKTS,
1377 pkt_inter_epg_220_to_global = (Ether(src=self.pg0.remote_mac,
1378 dst=str(self.router_mac)) /
1379 IPv6(src=eps[0].ip6,
1381 UDP(sport=1234, dport=1234) /
1384 self.send_and_expect_natted6(self.pg0,
1385 pkt_inter_epg_220_to_global * NUM_PKTS,
1390 # From a global address to an EP: OUT2IN
1392 pkt_inter_epg_220_from_global = (Ether(src=str(self.router_mac),
1393 dst=self.pg0.remote_mac) /
1396 UDP(sport=1234, dport=1234) /
1399 self.send_and_assert_no_replies(
1400 self.pg7, pkt_inter_epg_220_from_global * NUM_PKTS)
1402 c5 = VppGbpContract(
1403 self, 400, epgs[3].sclass, epgs[0].sclass, acl2.acl_index,
1404 [VppGbpContractRule(
1405 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1406 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1409 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1410 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1412 [ETH_P_IP, ETH_P_IPV6])
1415 self.send_and_expect_unnatted(self.pg7,
1416 pkt_inter_epg_220_from_global * NUM_PKTS,
1420 pkt_inter_epg_220_from_global = (Ether(src=str(self.router_mac),
1421 dst=self.pg0.remote_mac) /
1422 IPv6(dst=eps[0].fip6,
1424 UDP(sport=1234, dport=1234) /
1427 self.send_and_expect_unnatted6(
1429 pkt_inter_epg_220_from_global * NUM_PKTS,
1434 # From a local VM to another local VM using resp. public addresses:
1437 pkt_intra_epg_220_global = (Ether(src=self.pg0.remote_mac,
1438 dst=str(self.router_mac)) /
1441 UDP(sport=1234, dport=1234) /
1444 self.send_and_expect_double_natted(eps[0].itf,
1445 pkt_intra_epg_220_global * NUM_PKTS,
1450 pkt_intra_epg_220_global = (Ether(src=self.pg0.remote_mac,
1451 dst=str(self.router_mac)) /
1452 IPv6(src=eps[0].ip6,
1454 UDP(sport=1234, dport=1234) /
1457 self.send_and_expect_double_natted6(
1459 pkt_intra_epg_220_global * NUM_PKTS,
1468 # del static mappings for each EP from the 10/8 to 11/8 network
1469 flags = self.config_flags.NAT_IS_ADDR_ONLY
1470 self.vapi.nat44_add_del_static_mapping(
1472 local_ip_address=ep.ip4,
1473 external_ip_address=ep.fip4,
1474 external_sw_if_index=0xFFFFFFFF,
1477 self.vapi.nat66_add_del_static_mapping(
1478 local_ip_address=ep.ip6,
1479 external_ip_address=ep.fip6,
1483 # IP config on the BVI interfaces
1484 if epg != epgs[0] and epg != epgs[3]:
1485 flags = self.config_flags.NAT_IS_INSIDE
1486 self.vapi.nat44_interface_add_del_feature(
1487 sw_if_index=epg.bvi.sw_if_index,
1490 self.vapi.nat66_add_del_interface(
1491 is_add=0, flags=flags,
1492 sw_if_index=epg.bvi.sw_if_index)
1494 for recirc in recircs:
1495 self.vapi.nat44_interface_add_del_feature(
1496 sw_if_index=recirc.recirc.sw_if_index,
1498 self.vapi.nat66_add_del_interface(
1500 sw_if_index=recirc.recirc.sw_if_index)
1502 def wait_for_ep_timeout(self, sw_if_index=None, ip=None, mac=None,
1503 tep=None, n_tries=100, s_time=1):
1504 # only learnt EP can timeout
1505 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
1506 flags = ep_flags.GBP_API_ENDPOINT_FLAG_LEARNT
1508 if not find_gbp_endpoint(self, sw_if_index, ip, mac, tep=tep,
1511 n_tries = n_tries - 1
1513 self.assertFalse(find_gbp_endpoint(self, sw_if_index, ip, mac, tep=tep,
1517 def test_gbp_learn_l2(self):
1518 """ GBP L2 Endpoint Learning """
1520 drop_no_contract = self.statistics.get_err_counter(
1521 '/err/gbp-policy-port/drop-no-contract')
1522 allow_intra_class = self.statistics.get_err_counter(
1523 '/err/gbp-policy-port/allow-intra-sclass')
1525 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
1526 learnt = [{'mac': '00:00:11:11:11:01',
1528 'ip6': '2001:10::2'},
1529 {'mac': '00:00:11:11:11:02',
1531 'ip6': '2001:10::3'}]
1536 gt4 = VppIpTable(self, 1)
1537 gt4.add_vpp_config()
1538 gt6 = VppIpTable(self, 1, is_ip6=True)
1539 gt6.add_vpp_config()
1541 rd1 = VppGbpRouteDomain(self, 1, 401, gt4, gt6)
1542 rd1.add_vpp_config()
1545 # Pg2 hosts the vxlan tunnel, hosts on pg2 to act as TEPs
1546 # Pg3 hosts the IP4 UU-flood VXLAN tunnel
1547 # Pg4 hosts the IP6 UU-flood VXLAN tunnel
1549 self.pg2.config_ip4()
1550 self.pg2.resolve_arp()
1551 self.pg2.generate_remote_hosts(4)
1552 self.pg2.configure_ipv4_neighbors()
1553 self.pg3.config_ip4()
1554 self.pg3.resolve_arp()
1555 self.pg4.config_ip4()
1556 self.pg4.resolve_arp()
1559 # Add a mcast destination VXLAN-GBP tunnel for B&M traffic
1561 tun_bm = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
1564 tun_bm.add_vpp_config()
1567 # a GBP bridge domain with a BVI and a UU-flood interface
1569 bd1 = VppBridgeDomain(self, 1)
1570 bd1.add_vpp_config()
1571 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0,
1573 gbd1.add_vpp_config()
1575 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1576 self.logger.info(self.vapi.cli("sh gbp bridge"))
1578 # ... and has a /32 applied
1579 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
1580 ip_addr.add_vpp_config()
1583 # The Endpoint-group in which we are learning endpoints
1585 epg_220 = VppGbpEndpointGroup(self, 220, 112, rd1, gbd1,
1589 VppGbpEndpointRetention(4))
1590 epg_220.add_vpp_config()
1591 epg_330 = VppGbpEndpointGroup(self, 330, 113, rd1, gbd1,
1595 VppGbpEndpointRetention(4))
1596 epg_330.add_vpp_config()
1599 # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
1602 vx_tun_l2_1 = VppGbpVxlanTunnel(
1603 self, 99, bd1.bd_id,
1604 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L2,
1606 vx_tun_l2_1.add_vpp_config()
1609 # A static endpoint that the learnt endpoints are trying to
1612 ep = VppGbpEndpoint(self, self.pg0,
1614 "10.0.0.127", "11.0.0.127",
1615 "2001:10::1", "3001::1")
1618 self.assertTrue(find_route(self, ep.ip4, 32, table_id=1))
1620 # a packet with an sclass from an unknown EPG
1621 p = (Ether(src=self.pg2.remote_mac,
1622 dst=self.pg2.local_mac) /
1623 IP(src=self.pg2.remote_hosts[0].ip4,
1624 dst=self.pg2.local_ip4) /
1625 UDP(sport=1234, dport=48879) /
1626 VXLAN(vni=99, gpid=88, flags=0x88) /
1627 Ether(src=learnt[0]["mac"], dst=ep.mac) /
1628 IP(src=learnt[0]["ip"], dst=ep.ip4) /
1629 UDP(sport=1234, dport=1234) /
1632 self.send_and_assert_no_replies(self.pg2, p)
1634 self.logger.info(self.vapi.cli("sh error"))
1635 self.assert_error_counter_equal(
1636 '/err/gbp-policy-port/drop-no-contract',
1637 drop_no_contract + 1)
1640 # we should not have learnt a new tunnel endpoint, since
1641 # the EPG was not learnt.
1643 self.assertEqual(INDEX_INVALID,
1644 find_vxlan_gbp_tunnel(self,
1646 self.pg2.remote_hosts[0].ip4,
1649 # ep is not learnt, because the EPG is unknown
1650 self.assertEqual(len(self.vapi.gbp_endpoint_dump()), 1)
1653 # Learn new EPs from IP packets
1655 for ii, l in enumerate(learnt):
1656 # a packet with an sclass from a known EPG
1657 # arriving on an unknown TEP
1658 p = (Ether(src=self.pg2.remote_mac,
1659 dst=self.pg2.local_mac) /
1660 IP(src=self.pg2.remote_hosts[1].ip4,
1661 dst=self.pg2.local_ip4) /
1662 UDP(sport=1234, dport=48879) /
1663 VXLAN(vni=99, gpid=112, flags=0x88) /
1664 Ether(src=l['mac'], dst=ep.mac) /
1665 IP(src=l['ip'], dst=ep.ip4) /
1666 UDP(sport=1234, dport=1234) /
1669 rx = self.send_and_expect(self.pg2, [p], self.pg0)
1672 tep1_sw_if_index = find_vxlan_gbp_tunnel(
1675 self.pg2.remote_hosts[1].ip4,
1677 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
1680 # the EP is learnt via the learnt TEP
1681 # both from its MAC and its IP
1683 self.assertTrue(find_gbp_endpoint(self,
1684 vx_tun_l2_1.sw_if_index,
1686 self.assertTrue(find_gbp_endpoint(self,
1687 vx_tun_l2_1.sw_if_index,
1690 self.assert_error_counter_equal(
1691 '/err/gbp-policy-port/allow-intra-sclass',
1692 allow_intra_class + 2)
1694 self.logger.info(self.vapi.cli("show gbp endpoint"))
1695 self.logger.info(self.vapi.cli("show gbp vxlan"))
1696 self.logger.info(self.vapi.cli("show ip mfib"))
1699 # If we sleep for the threshold time, the learnt endpoints should
1703 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1707 # Learn new EPs from GARP packets received on the BD's mcast tunnel
1709 for ii, l in enumerate(learnt):
1710 # add some junk in the reserved field of the vxlan-header
1711 # next to the VNI. we should accept since reserved bits are
1713 p = (Ether(src=self.pg2.remote_mac,
1714 dst=self.pg2.local_mac) /
1715 IP(src=self.pg2.remote_hosts[1].ip4,
1717 UDP(sport=1234, dport=48879) /
1718 VXLAN(vni=88, reserved2=0x80, gpid=112, flags=0x88) /
1719 Ether(src=l['mac'], dst="ff:ff:ff:ff:ff:ff") /
1721 psrc=l['ip'], pdst=l['ip'],
1722 hwsrc=l['mac'], hwdst="ff:ff:ff:ff:ff:ff"))
1724 rx = self.send_and_expect(self.pg4, [p], self.pg0)
1727 tep1_sw_if_index = find_vxlan_gbp_tunnel(
1730 self.pg2.remote_hosts[1].ip4,
1732 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
1735 # the EP is learnt via the learnt TEP
1736 # both from its MAC and its IP
1738 self.assertTrue(find_gbp_endpoint(self,
1739 vx_tun_l2_1.sw_if_index,
1741 self.assertTrue(find_gbp_endpoint(self,
1742 vx_tun_l2_1.sw_if_index,
1746 # wait for the learnt endpoints to age out
1749 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1753 # Learn new EPs from L2 packets
1755 for ii, l in enumerate(learnt):
1756 # a packet with an sclass from a known EPG
1757 # arriving on an unknown TEP
1758 p = (Ether(src=self.pg2.remote_mac,
1759 dst=self.pg2.local_mac) /
1760 IP(src=self.pg2.remote_hosts[1].ip4,
1761 dst=self.pg2.local_ip4) /
1762 UDP(sport=1234, dport=48879) /
1763 VXLAN(vni=99, gpid=112, flags=0x88) /
1764 Ether(src=l['mac'], dst=ep.mac) /
1767 rx = self.send_and_expect(self.pg2, [p], self.pg0)
1770 tep1_sw_if_index = find_vxlan_gbp_tunnel(
1773 self.pg2.remote_hosts[1].ip4,
1775 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
1778 # the EP is learnt via the learnt TEP
1779 # both from its MAC and its IP
1781 self.assertTrue(find_gbp_endpoint(self,
1782 vx_tun_l2_1.sw_if_index,
1785 self.logger.info(self.vapi.cli("show gbp endpoint"))
1786 self.logger.info(self.vapi.cli("show gbp vxlan"))
1787 self.logger.info(self.vapi.cli("show vxlan-gbp tunnel"))
1790 # wait for the learnt endpoints to age out
1793 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1797 # repeat. the do not learn bit is set so the EPs are not learnt
1800 # a packet with an sclass from a known EPG
1801 p = (Ether(src=self.pg2.remote_mac,
1802 dst=self.pg2.local_mac) /
1803 IP(src=self.pg2.remote_hosts[1].ip4,
1804 dst=self.pg2.local_ip4) /
1805 UDP(sport=1234, dport=48879) /
1806 VXLAN(vni=99, gpid=112, flags=0x88, gpflags="D") /
1807 Ether(src=l['mac'], dst=ep.mac) /
1808 IP(src=l['ip'], dst=ep.ip4) /
1809 UDP(sport=1234, dport=1234) /
1812 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
1815 self.assertFalse(find_gbp_endpoint(self,
1816 vx_tun_l2_1.sw_if_index,
1823 # a packet with an sclass from a known EPG
1824 # set a reserved bit in addition to the G and I
1825 # reserved bits should not be checked on rx.
1826 p = (Ether(src=self.pg2.remote_mac,
1827 dst=self.pg2.local_mac) /
1828 IP(src=self.pg2.remote_hosts[1].ip4,
1829 dst=self.pg2.local_ip4) /
1830 UDP(sport=1234, dport=48879) /
1831 VXLAN(vni=99, gpid=112, flags=0xc8) /
1832 Ether(src=l['mac'], dst=ep.mac) /
1833 IP(src=l['ip'], dst=ep.ip4) /
1834 UDP(sport=1234, dport=1234) /
1837 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
1839 self.assertTrue(find_gbp_endpoint(self,
1840 vx_tun_l2_1.sw_if_index,
1844 # Static EP replies to dynamics
1846 self.logger.info(self.vapi.cli("sh l2fib bd_id 1"))
1848 p = (Ether(src=ep.mac, dst=l['mac']) /
1849 IP(dst=l['ip'], src=ep.ip4) /
1850 UDP(sport=1234, dport=1234) /
1853 rxs = self.send_and_expect(self.pg0, p * 17, self.pg2)
1856 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
1857 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
1858 self.assertEqual(rx[UDP].dport, 48879)
1859 # the UDP source port is a random value for hashing
1860 self.assertEqual(rx[VXLAN].gpid, 112)
1861 self.assertEqual(rx[VXLAN].vni, 99)
1862 self.assertTrue(rx[VXLAN].flags.G)
1863 self.assertTrue(rx[VXLAN].flags.Instance)
1864 self.assertTrue(rx[VXLAN].gpflags.A)
1865 self.assertFalse(rx[VXLAN].gpflags.D)
1868 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1872 # repeat in the other EPG
1873 # there's no contract between 220 and 330, but the A-bit is set
1874 # so the packet is cleared for delivery
1877 # a packet with an sclass from a known EPG
1878 p = (Ether(src=self.pg2.remote_mac,
1879 dst=self.pg2.local_mac) /
1880 IP(src=self.pg2.remote_hosts[1].ip4,
1881 dst=self.pg2.local_ip4) /
1882 UDP(sport=1234, dport=48879) /
1883 VXLAN(vni=99, gpid=113, flags=0x88, gpflags='A') /
1884 Ether(src=l['mac'], dst=ep.mac) /
1885 IP(src=l['ip'], dst=ep.ip4) /
1886 UDP(sport=1234, dport=1234) /
1889 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
1891 self.assertTrue(find_gbp_endpoint(self,
1892 vx_tun_l2_1.sw_if_index,
1896 # static EP cannot reach the learnt EPs since there is no contract
1897 # only test 1 EP as the others could timeout
1899 p = (Ether(src=ep.mac, dst=l['mac']) /
1900 IP(dst=learnt[0]['ip'], src=ep.ip4) /
1901 UDP(sport=1234, dport=1234) /
1904 self.send_and_assert_no_replies(self.pg0, [p])
1907 # refresh the entries after the check for no replies above
1910 # a packet with an sclass from a known EPG
1911 p = (Ether(src=self.pg2.remote_mac,
1912 dst=self.pg2.local_mac) /
1913 IP(src=self.pg2.remote_hosts[1].ip4,
1914 dst=self.pg2.local_ip4) /
1915 UDP(sport=1234, dport=48879) /
1916 VXLAN(vni=99, gpid=113, flags=0x88, gpflags='A') /
1917 Ether(src=l['mac'], dst=ep.mac) /
1918 IP(src=l['ip'], dst=ep.ip4) /
1919 UDP(sport=1234, dport=1234) /
1922 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
1924 self.assertTrue(find_gbp_endpoint(self,
1925 vx_tun_l2_1.sw_if_index,
1929 # Add the contract so they can talk
1931 rule = AclRule(is_permit=1, proto=17)
1932 rule2 = AclRule(src_prefix=IPv6Network((0, 0)),
1933 dst_prefix=IPv6Network((0, 0)), is_permit=1, proto=17)
1934 acl = VppAcl(self, rules=[rule, rule2])
1935 acl.add_vpp_config()
1937 c1 = VppGbpContract(
1938 self, 401, epg_220.sclass, epg_330.sclass, acl.acl_index,
1939 [VppGbpContractRule(
1940 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1941 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1944 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1945 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1947 [ETH_P_IP, ETH_P_IPV6])
1951 p = (Ether(src=ep.mac, dst=l['mac']) /
1952 IP(dst=l['ip'], src=ep.ip4) /
1953 UDP(sport=1234, dport=1234) /
1956 self.send_and_expect(self.pg0, [p], self.pg2)
1959 # send UU packets from the local EP
1961 self.logger.info(self.vapi.cli("sh gbp bridge"))
1962 self.logger.info(self.vapi.cli("sh bridge-domain 1 detail"))
1963 p_uu = (Ether(src=ep.mac, dst="00:11:11:11:11:11") /
1964 IP(dst="10.0.0.133", src=ep.ip4) /
1965 UDP(sport=1234, dport=1234) /
1967 rxs = self.send_and_expect(ep.itf, [p_uu], gbd1.uu_fwd)
1969 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1971 p_bm = (Ether(src=ep.mac, dst="ff:ff:ff:ff:ff:ff") /
1972 IP(dst="10.0.0.133", src=ep.ip4) /
1973 UDP(sport=1234, dport=1234) /
1975 rxs = self.send_and_expect_only(ep.itf, [p_bm], tun_bm.mcast_itf)
1978 self.assertEqual(rx[IP].src, self.pg4.local_ip4)
1979 self.assertEqual(rx[IP].dst, "239.1.1.1")
1980 self.assertEqual(rx[UDP].dport, 48879)
1981 # the UDP source port is a random value for hashing
1982 self.assertEqual(rx[VXLAN].gpid, 112)
1983 self.assertEqual(rx[VXLAN].vni, 88)
1984 self.assertTrue(rx[VXLAN].flags.G)
1985 self.assertTrue(rx[VXLAN].flags.Instance)
1986 self.assertFalse(rx[VXLAN].gpflags.A)
1987 self.assertFalse(rx[VXLAN].gpflags.D)
1989 rule = AclRule(is_permit=1, proto=17)
1990 rule2 = AclRule(src_prefix=IPv6Network((0, 0)),
1991 dst_prefix=IPv6Network((0, 0)), is_permit=1, proto=17)
1992 acl = VppAcl(self, rules=[rule, rule2])
1993 acl.add_vpp_config()
1995 c2 = VppGbpContract(
1996 self, 401, epg_330.sclass, epg_220.sclass, acl.acl_index,
1997 [VppGbpContractRule(
1998 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1999 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2002 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2003 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2005 [ETH_P_IP, ETH_P_IPV6])
2009 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
2012 # Check v6 Endpoints learning
2015 # a packet with an sclass from a known EPG
2016 p = (Ether(src=self.pg2.remote_mac,
2017 dst=self.pg2.local_mac) /
2018 IP(src=self.pg2.remote_hosts[1].ip4,
2019 dst=self.pg2.local_ip4) /
2020 UDP(sport=1234, dport=48879) /
2021 VXLAN(vni=99, gpid=113, flags=0x88) /
2022 Ether(src=l['mac'], dst=ep.mac) /
2023 IPv6(src=l['ip6'], dst=ep.ip6) /
2024 UDP(sport=1234, dport=1234) /
2027 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
2028 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
2030 self.assertTrue(find_gbp_endpoint(
2032 vx_tun_l2_1.sw_if_index,
2034 tep=[self.pg2.local_ip4,
2035 self.pg2.remote_hosts[1].ip4]))
2037 self.logger.info(self.vapi.cli("sh int"))
2038 self.logger.info(self.vapi.cli("sh vxlan-gbp tunnel"))
2039 self.logger.info(self.vapi.cli("sh gbp vxlan"))
2040 self.logger.info(self.vapi.cli("sh gbp endpoint"))
2041 self.logger.info(self.vapi.cli("sh gbp interface"))
2044 # EP moves to a different TEP
2047 # a packet with an sclass from a known EPG
2048 p = (Ether(src=self.pg2.remote_mac,
2049 dst=self.pg2.local_mac) /
2050 IP(src=self.pg2.remote_hosts[2].ip4,
2051 dst=self.pg2.local_ip4) /
2052 UDP(sport=1234, dport=48879) /
2053 VXLAN(vni=99, gpid=113, flags=0x88) /
2054 Ether(src=l['mac'], dst=ep.mac) /
2055 IPv6(src=l['ip6'], dst=ep.ip6) /
2056 UDP(sport=1234, dport=1234) /
2059 rx = self.send_and_expect(self.pg2, p * 1, self.pg0)
2060 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
2062 self.assertTrue(find_gbp_endpoint(
2064 vx_tun_l2_1.sw_if_index,
2067 tep=[self.pg2.local_ip4,
2068 self.pg2.remote_hosts[2].ip4]))
2071 # v6 remote EP reachability
2074 p = (Ether(src=ep.mac, dst=l['mac']) /
2075 IPv6(dst=l['ip6'], src=ep.ip6) /
2076 UDP(sport=1234, dport=1234) /
2079 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
2082 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2083 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[2].ip4)
2084 self.assertEqual(rx[UDP].dport, 48879)
2085 # the UDP source port is a random value for hashing
2086 self.assertEqual(rx[VXLAN].gpid, 112)
2087 self.assertEqual(rx[VXLAN].vni, 99)
2088 self.assertTrue(rx[VXLAN].flags.G)
2089 self.assertTrue(rx[VXLAN].flags.Instance)
2090 self.assertTrue(rx[VXLAN].gpflags.A)
2091 self.assertFalse(rx[VXLAN].gpflags.D)
2092 self.assertEqual(rx[IPv6].dst, l['ip6'])
2098 # a packet with an sclass from a known EPG
2099 p = (Ether(src=self.pg2.remote_mac,
2100 dst=self.pg2.local_mac) /
2101 IP(src=self.pg2.remote_hosts[2].ip4,
2102 dst=self.pg2.local_ip4) /
2103 UDP(sport=1234, dport=48879) /
2104 VXLAN(vni=99, gpid=112, flags=0x88) /
2105 Ether(src=l['mac'], dst=ep.mac) /
2106 IPv6(src=l['ip6'], dst=ep.ip6) /
2107 UDP(sport=1234, dport=1234) /
2110 rx = self.send_and_expect(self.pg2, p * 1, self.pg0)
2111 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
2113 self.assertTrue(find_gbp_endpoint(
2115 vx_tun_l2_1.sw_if_index,
2118 tep=[self.pg2.local_ip4,
2119 self.pg2.remote_hosts[2].ip4]))
2122 # check reachability and contract intra-epg
2124 allow_intra_class = self.statistics.get_err_counter(
2125 '/err/gbp-policy-mac/allow-intra-sclass')
2128 p = (Ether(src=ep.mac, dst=l['mac']) /
2129 IPv6(dst=l['ip6'], src=ep.ip6) /
2130 UDP(sport=1234, dport=1234) /
2133 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
2136 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2137 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[2].ip4)
2138 self.assertEqual(rx[UDP].dport, 48879)
2139 self.assertEqual(rx[VXLAN].gpid, 112)
2140 self.assertEqual(rx[VXLAN].vni, 99)
2141 self.assertTrue(rx[VXLAN].flags.G)
2142 self.assertTrue(rx[VXLAN].flags.Instance)
2143 self.assertTrue(rx[VXLAN].gpflags.A)
2144 self.assertFalse(rx[VXLAN].gpflags.D)
2145 self.assertEqual(rx[IPv6].dst, l['ip6'])
2147 allow_intra_class += NUM_PKTS
2149 self.assert_error_counter_equal(
2150 '/err/gbp-policy-mac/allow-intra-sclass',
2157 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
2159 self.pg2.unconfig_ip4()
2160 self.pg3.unconfig_ip4()
2161 self.pg4.unconfig_ip4()
2163 def test_gbp_contract(self):
2164 """ GBP Contracts """
2169 gt4 = VppIpTable(self, 0)
2170 gt4.add_vpp_config()
2171 gt6 = VppIpTable(self, 0, is_ip6=True)
2172 gt6.add_vpp_config()
2174 rd0 = VppGbpRouteDomain(self, 0, 400, gt4, gt6, None, None)
2176 rd0.add_vpp_config()
2181 bd1 = VppBridgeDomain(self, 1, arp_term=0)
2182 bd2 = VppBridgeDomain(self, 2, arp_term=0)
2184 bd1.add_vpp_config()
2185 bd2.add_vpp_config()
2187 gbd1 = VppGbpBridgeDomain(self, bd1, rd0, self.loop0)
2188 gbd2 = VppGbpBridgeDomain(self, bd2, rd0, self.loop1)
2190 gbd1.add_vpp_config()
2191 gbd2.add_vpp_config()
2194 # 3 EPGs, 2 of which share a BD.
2196 epgs = [VppGbpEndpointGroup(self, 220, 1220, rd0, gbd1,
2198 "10.0.0.128", "2001:10::128"),
2199 VppGbpEndpointGroup(self, 221, 1221, rd0, gbd1,
2201 "10.0.1.128", "2001:10:1::128"),
2202 VppGbpEndpointGroup(self, 222, 1222, rd0, gbd2,
2204 "10.0.2.128", "2001:10:2::128")]
2206 # 4 end-points, 2 in the same subnet, 3 in the same BD
2208 eps = [VppGbpEndpoint(self, self.pg0,
2210 "10.0.0.1", "11.0.0.1",
2211 "2001:10::1", "3001::1"),
2212 VppGbpEndpoint(self, self.pg1,
2214 "10.0.0.2", "11.0.0.2",
2215 "2001:10::2", "3001::2"),
2216 VppGbpEndpoint(self, self.pg2,
2218 "10.0.1.1", "11.0.0.3",
2219 "2001:10:1::1", "3001::3"),
2220 VppGbpEndpoint(self, self.pg3,
2222 "10.0.2.1", "11.0.0.4",
2223 "2001:10:2::1", "3001::4")]
2226 # Config related to each of the EPGs
2229 # IP config on the BVI interfaces
2231 VppIpInterfaceBind(self, epg.bvi, epg.rd.t4).add_vpp_config()
2232 VppIpInterfaceBind(self, epg.bvi, epg.rd.t6).add_vpp_config()
2233 epg.bvi.set_mac(self.router_mac)
2235 if_ip4 = VppIpInterfaceAddress(self, epg.bvi, epg.bvi_ip4, 32)
2236 if_ip6 = VppIpInterfaceAddress(self, epg.bvi, epg.bvi_ip6, 128)
2237 if_ip4.add_vpp_config()
2238 if_ip6.add_vpp_config()
2240 # add the BD ARP termination entry for BVI IP
2241 epg.bd_arp_ip4 = VppBridgeDomainArpEntry(self, epg.bd.bd,
2242 str(self.router_mac),
2244 epg.bd_arp_ip4.add_vpp_config()
2247 epg.add_vpp_config()
2255 self.logger.info(self.vapi.cli("show gbp endpoint"))
2256 self.logger.info(self.vapi.cli("show interface"))
2257 self.logger.info(self.vapi.cli("show br"))
2260 # Intra epg allowed without contract
2262 pkt_intra_epg_220_to_220 = (Ether(src=self.pg0.remote_mac,
2263 dst=self.pg1.remote_mac) /
2266 UDP(sport=1234, dport=1234) /
2269 self.send_and_expect_bridged(self.pg0,
2270 pkt_intra_epg_220_to_220 * 65,
2273 pkt_intra_epg_220_to_220 = (Ether(src=self.pg0.remote_mac,
2274 dst=self.pg1.remote_mac) /
2275 IPv6(src=eps[0].ip6,
2277 UDP(sport=1234, dport=1234) /
2280 self.send_and_expect_bridged6(self.pg0,
2281 pkt_intra_epg_220_to_220 * 65,
2285 # Inter epg denied without contract
2287 pkt_inter_epg_220_to_221 = (Ether(src=self.pg0.remote_mac,
2288 dst=self.pg2.remote_mac) /
2291 UDP(sport=1234, dport=1234) /
2294 self.send_and_assert_no_replies(self.pg0, pkt_inter_epg_220_to_221)
2297 # A uni-directional contract from EPG 220 -> 221
2299 rule = AclRule(is_permit=1, proto=17)
2300 rule2 = AclRule(src_prefix=IPv6Network((0, 0)),
2301 dst_prefix=IPv6Network((0, 0)), is_permit=1, proto=17)
2302 rule3 = AclRule(is_permit=1, proto=1)
2303 acl = VppAcl(self, rules=[rule, rule2, rule3])
2304 acl.add_vpp_config()
2306 c1 = VppGbpContract(
2307 self, 400, epgs[0].sclass, epgs[1].sclass, acl.acl_index,
2308 [VppGbpContractRule(
2309 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2310 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2313 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2314 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2317 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2318 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2320 [ETH_P_IP, ETH_P_IPV6])
2323 self.send_and_expect_bridged(eps[0].itf,
2324 pkt_inter_epg_220_to_221 * 65,
2327 pkt_inter_epg_220_to_222 = (Ether(src=self.pg0.remote_mac,
2328 dst=str(self.router_mac)) /
2331 UDP(sport=1234, dport=1234) /
2333 self.send_and_assert_no_replies(eps[0].itf,
2334 pkt_inter_epg_220_to_222 * 65)
2337 # ping router IP in different BD
2339 pkt_router_ping_220_to_221 = (Ether(src=self.pg0.remote_mac,
2340 dst=str(self.router_mac)) /
2342 dst=epgs[1].bvi_ip4) /
2343 ICMP(type='echo-request'))
2345 self.send_and_expect(self.pg0, [pkt_router_ping_220_to_221], self.pg0)
2347 pkt_router_ping_220_to_221 = (Ether(src=self.pg0.remote_mac,
2348 dst=str(self.router_mac)) /
2349 IPv6(src=eps[0].ip6,
2350 dst=epgs[1].bvi_ip6) /
2351 ICMPv6EchoRequest())
2353 self.send_and_expect(self.pg0, [pkt_router_ping_220_to_221], self.pg0)
2356 # contract for the return direction
2358 c2 = VppGbpContract(
2359 self, 400, epgs[1].sclass, epgs[0].sclass, acl.acl_index,
2360 [VppGbpContractRule(
2361 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2362 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2365 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2366 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2368 [ETH_P_IP, ETH_P_IPV6])
2371 self.send_and_expect_bridged(eps[0].itf,
2372 pkt_inter_epg_220_to_221 * 65,
2374 pkt_inter_epg_221_to_220 = (Ether(src=self.pg2.remote_mac,
2375 dst=self.pg0.remote_mac) /
2378 UDP(sport=1234, dport=1234) /
2380 self.send_and_expect_bridged(eps[2].itf,
2381 pkt_inter_epg_221_to_220 * 65,
2383 pkt_inter_epg_221_to_220 = (Ether(src=self.pg2.remote_mac,
2384 dst=str(self.router_mac)) /
2387 UDP(sport=1234, dport=1234) /
2389 self.send_and_expect_routed(eps[2].itf,
2390 pkt_inter_epg_221_to_220 * 65,
2392 str(self.router_mac))
2393 pkt_inter_epg_221_to_220 = (Ether(src=self.pg2.remote_mac,
2394 dst=str(self.router_mac)) /
2395 IPv6(src=eps[2].ip6,
2397 UDP(sport=1234, dport=1234) /
2399 self.send_and_expect_routed6(eps[2].itf,
2400 pkt_inter_epg_221_to_220 * 65,
2402 str(self.router_mac))
2405 # contract between 220 and 222 uni-direction
2407 c3 = VppGbpContract(
2408 self, 400, epgs[0].sclass, epgs[2].sclass, acl.acl_index,
2409 [VppGbpContractRule(
2410 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2411 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2414 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2415 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2417 [ETH_P_IP, ETH_P_IPV6])
2420 self.send_and_expect(eps[0].itf,
2421 pkt_inter_epg_220_to_222 * 65,
2424 c3.remove_vpp_config()
2425 c1.remove_vpp_config()
2426 c2.remove_vpp_config()
2427 acl.remove_vpp_config()
2429 def test_gbp_bd_drop_flags(self):
2430 """ GBP BD drop flags """
2435 gt4 = VppIpTable(self, 1)
2436 gt4.add_vpp_config()
2437 gt6 = VppIpTable(self, 1, is_ip6=True)
2438 gt6.add_vpp_config()
2440 rd1 = VppGbpRouteDomain(self, 1, 401, gt4, gt6)
2441 rd1.add_vpp_config()
2444 # a GBP bridge domain with a BVI only
2446 bd1 = VppBridgeDomain(self, 1)
2447 bd1.add_vpp_config()
2449 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0,
2451 uu_drop=True, bm_drop=True)
2452 gbd1.add_vpp_config()
2454 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2455 self.logger.info(self.vapi.cli("sh gbp bridge"))
2457 # ... and has a /32 applied
2458 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2459 ip_addr.add_vpp_config()
2462 # The Endpoint-group
2464 epg_220 = VppGbpEndpointGroup(self, 220, 112, rd1, gbd1,
2468 VppGbpEndpointRetention(3))
2469 epg_220.add_vpp_config()
2471 ep = VppGbpEndpoint(self, self.pg0,
2473 "10.0.0.127", "11.0.0.127",
2474 "2001:10::1", "3001::1")
2478 # send UU/BM packet from the local EP with UU drop and BM drop enabled
2481 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2482 self.logger.info(self.vapi.cli("sh gbp bridge"))
2483 p_uu = (Ether(src=ep.mac, dst="00:11:11:11:11:11") /
2484 IP(dst="10.0.0.133", src=ep.ip4) /
2485 UDP(sport=1234, dport=1234) /
2487 self.send_and_assert_no_replies(ep.itf, [p_uu])
2489 p_bm = (Ether(src=ep.mac, dst="ff:ff:ff:ff:ff:ff") /
2490 IP(dst="10.0.0.133", src=ep.ip4) /
2491 UDP(sport=1234, dport=1234) /
2493 self.send_and_assert_no_replies(ep.itf, [p_bm])
2495 self.pg3.unconfig_ip4()
2497 self.logger.info(self.vapi.cli("sh int"))
2499 def test_gbp_bd_arp_flags(self):
2500 """ GBP BD arp flags """
2505 gt4 = VppIpTable(self, 1)
2506 gt4.add_vpp_config()
2507 gt6 = VppIpTable(self, 1, is_ip6=True)
2508 gt6.add_vpp_config()
2510 rd1 = VppGbpRouteDomain(self, 1, 401, gt4, gt6)
2511 rd1.add_vpp_config()
2514 # Pg4 hosts the IP6 UU-flood VXLAN tunnel
2516 self.pg4.config_ip4()
2517 self.pg4.resolve_arp()
2520 # Add a mcast destination VXLAN-GBP tunnel for B&M traffic
2522 tun_uu = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
2525 tun_uu.add_vpp_config()
2528 # a GBP bridge domain with a BVI and a UU-flood interface
2530 bd1 = VppBridgeDomain(self, 1)
2531 bd1.add_vpp_config()
2533 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0,
2536 gbd1.add_vpp_config()
2538 # ... and has a /32 applied
2539 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2540 ip_addr.add_vpp_config()
2543 # The Endpoint-group
2545 epg_220 = VppGbpEndpointGroup(self, 220, 112, rd1, gbd1,
2549 VppGbpEndpointRetention(2))
2550 epg_220.add_vpp_config()
2552 ep = VppGbpEndpoint(self, self.pg0,
2554 "10.0.0.127", "11.0.0.127",
2555 "2001:10::1", "3001::1")
2559 # send ARP packet from the local EP expect it on the uu interface
2561 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2562 self.logger.info(self.vapi.cli("sh gbp bridge"))
2563 p_arp = (Ether(src=ep.mac, dst="ff:ff:ff:ff:ff:ff") /
2565 psrc=ep.ip4, pdst="10.0.0.99",
2567 hwdst="ff:ff:ff:ff:ff:ff"))
2568 self.send_and_expect(ep.itf, [p_arp], self.pg4)
2570 self.pg4.unconfig_ip4()
2572 def test_gbp_learn_vlan_l2(self):
2573 """ GBP L2 Endpoint w/ VLANs"""
2575 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
2576 learnt = [{'mac': '00:00:11:11:11:01',
2578 'ip6': '2001:10::2'},
2579 {'mac': '00:00:11:11:11:02',
2581 'ip6': '2001:10::3'}]
2586 gt4 = VppIpTable(self, 1)
2587 gt4.add_vpp_config()
2588 gt6 = VppIpTable(self, 1, is_ip6=True)
2589 gt6.add_vpp_config()
2591 rd1 = VppGbpRouteDomain(self, 1, 401, gt4, gt6)
2592 rd1.add_vpp_config()
2595 # Pg2 hosts the vxlan tunnel, hosts on pg2 to act as TEPs
2597 self.pg2.config_ip4()
2598 self.pg2.resolve_arp()
2599 self.pg2.generate_remote_hosts(4)
2600 self.pg2.configure_ipv4_neighbors()
2601 self.pg3.config_ip4()
2602 self.pg3.resolve_arp()
2605 # The EP will be on a vlan sub-interface
2607 vlan_11 = VppDot1QSubint(self, self.pg0, 11)
2609 self.vapi.l2_interface_vlan_tag_rewrite(
2610 sw_if_index=vlan_11.sw_if_index, vtr_op=L2_VTR_OP.L2_POP_1,
2613 bd_uu_fwd = VppVxlanGbpTunnel(self, self.pg3.local_ip4,
2614 self.pg3.remote_ip4, 116)
2615 bd_uu_fwd.add_vpp_config()
2618 # a GBP bridge domain with a BVI and a UU-flood interface
2619 # The BD is marked as do not learn, so no endpoints are ever
2620 # learnt in this BD.
2622 bd1 = VppBridgeDomain(self, 1)
2623 bd1.add_vpp_config()
2624 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0, bd_uu_fwd,
2626 gbd1.add_vpp_config()
2628 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2629 self.logger.info(self.vapi.cli("sh gbp bridge"))
2631 # ... and has a /32 applied
2632 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2633 ip_addr.add_vpp_config()
2636 # The Endpoint-group in which we are learning endpoints
2638 epg_220 = VppGbpEndpointGroup(self, 220, 441, rd1, gbd1,
2642 VppGbpEndpointRetention(4))
2643 epg_220.add_vpp_config()
2646 # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
2649 vx_tun_l2_1 = VppGbpVxlanTunnel(
2650 self, 99, bd1.bd_id,
2651 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L2,
2653 vx_tun_l2_1.add_vpp_config()
2656 # A static endpoint that the learnt endpoints are trying to
2659 ep = VppGbpEndpoint(self, vlan_11,
2661 "10.0.0.127", "11.0.0.127",
2662 "2001:10::1", "3001::1")
2665 self.assertTrue(find_route(self, ep.ip4, 32, table_id=1))
2668 # Send to the static EP
2670 for ii, l in enumerate(learnt):
2671 # a packet with an sclass from a known EPG
2672 # arriving on an unknown TEP
2673 p = (Ether(src=self.pg2.remote_mac,
2674 dst=self.pg2.local_mac) /
2675 IP(src=self.pg2.remote_hosts[1].ip4,
2676 dst=self.pg2.local_ip4) /
2677 UDP(sport=1234, dport=48879) /
2678 VXLAN(vni=99, gpid=441, flags=0x88) /
2679 Ether(src=l['mac'], dst=ep.mac) /
2680 IP(src=l['ip'], dst=ep.ip4) /
2681 UDP(sport=1234, dport=1234) /
2684 rxs = self.send_and_expect(self.pg2, [p], self.pg0)
2687 # packet to EP has the EP's vlan tag
2690 self.assertEqual(rx[Dot1Q].vlan, 11)
2693 # the EP is not learnt since the BD setting prevents it
2696 self.assertFalse(find_gbp_endpoint(self,
2697 vx_tun_l2_1.sw_if_index,
2699 self.assertEqual(INDEX_INVALID,
2700 find_vxlan_gbp_tunnel(
2703 self.pg2.remote_hosts[1].ip4,
2706 self.assertEqual(len(self.vapi.gbp_endpoint_dump()), 1)
2710 # we didn't learn the remotes so they are sent to the UU-fwd
2713 p = (Ether(src=ep.mac, dst=l['mac']) /
2715 IP(dst=l['ip'], src=ep.ip4) /
2716 UDP(sport=1234, dport=1234) /
2719 rxs = self.send_and_expect(self.pg0, p * 17, self.pg3)
2722 self.assertEqual(rx[IP].src, self.pg3.local_ip4)
2723 self.assertEqual(rx[IP].dst, self.pg3.remote_ip4)
2724 self.assertEqual(rx[UDP].dport, 48879)
2725 # the UDP source port is a random value for hashing
2726 self.assertEqual(rx[VXLAN].gpid, 441)
2727 self.assertEqual(rx[VXLAN].vni, 116)
2728 self.assertTrue(rx[VXLAN].flags.G)
2729 self.assertTrue(rx[VXLAN].flags.Instance)
2730 self.assertFalse(rx[VXLAN].gpflags.A)
2731 self.assertFalse(rx[VXLAN].gpflags.D)
2733 self.pg2.unconfig_ip4()
2734 self.pg3.unconfig_ip4()
2736 def test_gbp_learn_l3(self):
2737 """ GBP L3 Endpoint Learning """
2739 self.vapi.cli("set logging class gbp level debug")
2741 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
2742 routed_dst_mac = "00:0c:0c:0c:0c:0c"
2743 routed_src_mac = "00:22:bd:f8:19:ff"
2745 learnt = [{'mac': '00:00:11:11:11:02',
2747 'ip6': '2001:10::2'},
2748 {'mac': '00:00:11:11:11:03',
2750 'ip6': '2001:10::3'}]
2755 t4 = VppIpTable(self, 1)
2757 t6 = VppIpTable(self, 1, True)
2760 tun_ip4_uu = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
2761 self.pg4.remote_ip4, 114)
2762 tun_ip6_uu = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
2763 self.pg4.remote_ip4, 116)
2764 tun_ip4_uu.add_vpp_config()
2765 tun_ip6_uu.add_vpp_config()
2767 rd1 = VppGbpRouteDomain(self, 2, 401, t4, t6, tun_ip4_uu, tun_ip6_uu)
2768 rd1.add_vpp_config()
2770 self.loop0.set_mac(self.router_mac)
2773 # Bind the BVI to the RD
2775 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
2776 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
2779 # Pg2 hosts the vxlan tunnel
2780 # hosts on pg2 to act as TEPs
2784 self.pg2.config_ip4()
2785 self.pg2.resolve_arp()
2786 self.pg2.generate_remote_hosts(4)
2787 self.pg2.configure_ipv4_neighbors()
2788 self.pg3.config_ip4()
2789 self.pg3.resolve_arp()
2790 self.pg4.config_ip4()
2791 self.pg4.resolve_arp()
2794 # a GBP bridge domain with a BVI and a UU-flood interface
2796 bd1 = VppBridgeDomain(self, 1)
2797 bd1.add_vpp_config()
2798 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0, self.pg3)
2799 gbd1.add_vpp_config()
2801 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2802 self.logger.info(self.vapi.cli("sh gbp bridge"))
2803 self.logger.info(self.vapi.cli("sh gbp route"))
2805 # ... and has a /32 and /128 applied
2806 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2807 ip4_addr.add_vpp_config()
2808 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 128)
2809 ip6_addr.add_vpp_config()
2812 # The Endpoint-group in which we are learning endpoints
2814 epg_220 = VppGbpEndpointGroup(self, 220, 441, rd1, gbd1,
2818 VppGbpEndpointRetention(4))
2819 epg_220.add_vpp_config()
2822 # The VXLAN GBP tunnel is in L3 mode with learning enabled
2824 vx_tun_l3 = VppGbpVxlanTunnel(
2825 self, 101, rd1.rd_id,
2826 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
2828 vx_tun_l3.add_vpp_config()
2831 # A static endpoint that the learnt endpoints are trying to
2834 ep = VppGbpEndpoint(self, self.pg0,
2836 "10.0.0.127", "11.0.0.127",
2837 "2001:10::1", "3001::1")
2841 # learn some remote IPv4 EPs
2843 for ii, l in enumerate(learnt):
2844 # a packet with an sclass from a known EPG
2845 # arriving on an unknown TEP
2846 p = (Ether(src=self.pg2.remote_mac,
2847 dst=self.pg2.local_mac) /
2848 IP(src=self.pg2.remote_hosts[1].ip4,
2849 dst=self.pg2.local_ip4) /
2850 UDP(sport=1234, dport=48879) /
2851 VXLAN(vni=101, gpid=441, flags=0x88) /
2852 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2853 IP(src=l['ip'], dst=ep.ip4) /
2854 UDP(sport=1234, dport=1234) /
2857 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2860 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2863 self.pg2.remote_hosts[1].ip4,
2865 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2867 # endpoint learnt via the parent GBP-vxlan interface
2868 self.assertTrue(find_gbp_endpoint(self,
2869 vx_tun_l3._sw_if_index,
2873 # Static IPv4 EP replies to learnt
2876 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2877 IP(dst=l['ip'], src=ep.ip4) /
2878 UDP(sport=1234, dport=1234) /
2881 rxs = self.send_and_expect(self.pg0, p * 1, self.pg2)
2884 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2885 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2886 self.assertEqual(rx[UDP].dport, 48879)
2887 # the UDP source port is a random value for hashing
2888 self.assertEqual(rx[VXLAN].gpid, 441)
2889 self.assertEqual(rx[VXLAN].vni, 101)
2890 self.assertTrue(rx[VXLAN].flags.G)
2891 self.assertTrue(rx[VXLAN].flags.Instance)
2892 self.assertTrue(rx[VXLAN].gpflags.A)
2893 self.assertFalse(rx[VXLAN].gpflags.D)
2895 inner = rx[VXLAN].payload
2897 self.assertEqual(inner[Ether].src, routed_src_mac)
2898 self.assertEqual(inner[Ether].dst, routed_dst_mac)
2899 self.assertEqual(inner[IP].src, ep.ip4)
2900 self.assertEqual(inner[IP].dst, l['ip'])
2903 self.assertFalse(find_gbp_endpoint(self,
2908 # learn some remote IPv6 EPs
2910 for ii, l in enumerate(learnt):
2911 # a packet with an sclass from a known EPG
2912 # arriving on an unknown TEP
2913 p = (Ether(src=self.pg2.remote_mac,
2914 dst=self.pg2.local_mac) /
2915 IP(src=self.pg2.remote_hosts[1].ip4,
2916 dst=self.pg2.local_ip4) /
2917 UDP(sport=1234, dport=48879) /
2918 VXLAN(vni=101, gpid=441, flags=0x88) /
2919 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2920 IPv6(src=l['ip6'], dst=ep.ip6) /
2921 UDP(sport=1234, dport=1234) /
2924 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2927 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2930 self.pg2.remote_hosts[1].ip4,
2932 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2934 self.logger.info(self.vapi.cli("show gbp bridge"))
2935 self.logger.info(self.vapi.cli("show vxlan-gbp tunnel"))
2936 self.logger.info(self.vapi.cli("show gbp vxlan"))
2937 self.logger.info(self.vapi.cli("show int addr"))
2939 # endpoint learnt via the TEP
2940 self.assertTrue(find_gbp_endpoint(self, ip=l['ip6']))
2942 self.logger.info(self.vapi.cli("show gbp endpoint"))
2943 self.logger.info(self.vapi.cli("show ip fib index 1 %s" % l['ip']))
2946 # Static EP replies to learnt
2949 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2950 IPv6(dst=l['ip6'], src=ep.ip6) /
2951 UDP(sport=1234, dport=1234) /
2954 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
2957 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2958 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2959 self.assertEqual(rx[UDP].dport, 48879)
2960 # the UDP source port is a random value for hashing
2961 self.assertEqual(rx[VXLAN].gpid, 441)
2962 self.assertEqual(rx[VXLAN].vni, 101)
2963 self.assertTrue(rx[VXLAN].flags.G)
2964 self.assertTrue(rx[VXLAN].flags.Instance)
2965 self.assertTrue(rx[VXLAN].gpflags.A)
2966 self.assertFalse(rx[VXLAN].gpflags.D)
2968 inner = rx[VXLAN].payload
2970 self.assertEqual(inner[Ether].src, routed_src_mac)
2971 self.assertEqual(inner[Ether].dst, routed_dst_mac)
2972 self.assertEqual(inner[IPv6].src, ep.ip6)
2973 self.assertEqual(inner[IPv6].dst, l['ip6'])
2975 self.logger.info(self.vapi.cli("sh gbp endpoint"))
2977 self.wait_for_ep_timeout(ip=l['ip'])
2980 # Static sends to unknown EP with no route
2982 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2983 IP(dst="10.0.0.99", src=ep.ip4) /
2984 UDP(sport=1234, dport=1234) /
2987 self.send_and_assert_no_replies(self.pg0, [p])
2990 # Add a route to static EP's v4 and v6 subnet
2992 se_10_24 = VppGbpSubnet(
2993 self, rd1, "10.0.0.0", 24,
2994 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT)
2995 se_10_24.add_vpp_config()
2998 # static pings router
3000 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
3001 IP(dst=epg_220.bvi_ip4, src=ep.ip4) /
3002 UDP(sport=1234, dport=1234) /
3005 self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg0)
3007 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
3008 IPv6(dst=epg_220.bvi_ip6, src=ep.ip6) /
3009 UDP(sport=1234, dport=1234) /
3012 self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg0)
3015 # packets to address in the subnet are sent on the uu-fwd
3017 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
3018 IP(dst="10.0.0.99", src=ep.ip4) /
3019 UDP(sport=1234, dport=1234) /
3022 rxs = self.send_and_expect(self.pg0, [p], self.pg4)
3024 self.assertEqual(rx[IP].src, self.pg4.local_ip4)
3025 self.assertEqual(rx[IP].dst, self.pg4.remote_ip4)
3026 self.assertEqual(rx[UDP].dport, 48879)
3027 # the UDP source port is a random value for hashing
3028 self.assertEqual(rx[VXLAN].gpid, 441)
3029 self.assertEqual(rx[VXLAN].vni, 114)
3030 self.assertTrue(rx[VXLAN].flags.G)
3031 self.assertTrue(rx[VXLAN].flags.Instance)
3032 # policy is not applied to packets sent to the uu-fwd interfaces
3033 self.assertFalse(rx[VXLAN].gpflags.A)
3034 self.assertFalse(rx[VXLAN].gpflags.D)
3037 # learn some remote IPv4 EPs
3039 for ii, l in enumerate(learnt):
3040 # a packet with an sclass from a known EPG
3041 # arriving on an unknown TEP
3042 p = (Ether(src=self.pg2.remote_mac,
3043 dst=self.pg2.local_mac) /
3044 IP(src=self.pg2.remote_hosts[2].ip4,
3045 dst=self.pg2.local_ip4) /
3046 UDP(sport=1234, dport=48879) /
3047 VXLAN(vni=101, gpid=441, flags=0x88) /
3048 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
3049 IP(src=l['ip'], dst=ep.ip4) /
3050 UDP(sport=1234, dport=1234) /
3053 rx = self.send_and_expect(self.pg2, [p], self.pg0)
3056 tep1_sw_if_index = find_vxlan_gbp_tunnel(
3059 self.pg2.remote_hosts[2].ip4,
3061 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
3063 # endpoint learnt via the parent GBP-vxlan interface
3064 self.assertTrue(find_gbp_endpoint(self,
3065 vx_tun_l3._sw_if_index,
3069 # Add a remote endpoint from the API
3071 rep_88 = VppGbpEndpoint(self, vx_tun_l3,
3073 "10.0.0.88", "11.0.0.88",
3074 "2001:10::88", "3001::88",
3075 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
3077 self.pg2.remote_hosts[2].ip4,
3079 rep_88.add_vpp_config()
3082 # Add a remote endpoint from the API that matches an existing one
3083 # this is a lower priority, hence the packet is sent to the DP leanrt
3086 rep_2 = VppGbpEndpoint(self, vx_tun_l3,
3088 learnt[0]['ip'], "11.0.0.101",
3089 learnt[0]['ip6'], "3001::101",
3090 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
3092 self.pg2.remote_hosts[1].ip4,
3094 rep_2.add_vpp_config()
3097 # Add a route to the learned EP's v4 subnet
3098 # packets should be send on the v4/v6 uu=fwd interface resp.
3100 se_10_1_24 = VppGbpSubnet(
3101 self, rd1, "10.0.1.0", 24,
3102 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT)
3103 se_10_1_24.add_vpp_config()
3105 self.logger.info(self.vapi.cli("show gbp endpoint"))
3107 ips = ["10.0.0.88", learnt[0]['ip']]
3109 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
3110 IP(dst=ip, src=ep.ip4) /
3111 UDP(sport=1234, dport=1234) /
3114 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
3117 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
3118 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[2].ip4)
3119 self.assertEqual(rx[UDP].dport, 48879)
3120 # the UDP source port is a random value for hashing
3121 self.assertEqual(rx[VXLAN].gpid, 441)
3122 self.assertEqual(rx[VXLAN].vni, 101)
3123 self.assertTrue(rx[VXLAN].flags.G)
3124 self.assertTrue(rx[VXLAN].flags.Instance)
3125 self.assertTrue(rx[VXLAN].gpflags.A)
3126 self.assertFalse(rx[VXLAN].gpflags.D)
3128 inner = rx[VXLAN].payload
3130 self.assertEqual(inner[Ether].src, routed_src_mac)
3131 self.assertEqual(inner[Ether].dst, routed_dst_mac)
3132 self.assertEqual(inner[IP].src, ep.ip4)
3133 self.assertEqual(inner[IP].dst, ip)
3136 # remove the API remote EPs, only API sourced is gone, the DP
3137 # learnt one remains
3139 rep_88.remove_vpp_config()
3140 rep_2.remove_vpp_config()
3142 self.assertTrue(find_gbp_endpoint(self, ip=rep_2.ip4))
3144 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
3145 IP(src=ep.ip4, dst=rep_2.ip4) /
3146 UDP(sport=1234, dport=1234) /
3148 rxs = self.send_and_expect(self.pg0, [p], self.pg2)
3150 self.assertFalse(find_gbp_endpoint(self, ip=rep_88.ip4))
3152 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
3153 IP(src=ep.ip4, dst=rep_88.ip4) /
3154 UDP(sport=1234, dport=1234) /
3156 rxs = self.send_and_expect(self.pg0, [p], self.pg4)
3159 # to appease the testcase we cannot have the registered EP still
3160 # present (because it's DP learnt) when the TC ends so wait until
3163 self.wait_for_ep_timeout(ip=rep_88.ip4)
3164 self.wait_for_ep_timeout(ip=rep_2.ip4)
3167 # Same as above, learn a remote EP via CP and DP
3168 # this time remove the DP one first. expect the CP data to remain
3170 rep_3 = VppGbpEndpoint(self, vx_tun_l3,
3172 "10.0.1.4", "11.0.0.103",
3173 "2001::10:3", "3001::103",
3174 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
3176 self.pg2.remote_hosts[1].ip4,
3178 rep_3.add_vpp_config()
3180 p = (Ether(src=self.pg2.remote_mac,
3181 dst=self.pg2.local_mac) /
3182 IP(src=self.pg2.remote_hosts[2].ip4,
3183 dst=self.pg2.local_ip4) /
3184 UDP(sport=1234, dport=48879) /
3185 VXLAN(vni=101, gpid=441, flags=0x88) /
3186 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
3187 IP(src="10.0.1.4", dst=ep.ip4) /
3188 UDP(sport=1234, dport=1234) /
3190 rxs = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
3192 self.assertTrue(find_gbp_endpoint(self,
3193 vx_tun_l3._sw_if_index,
3195 tep=[self.pg2.local_ip4,
3196 self.pg2.remote_hosts[2].ip4]))
3198 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
3199 IP(dst="10.0.1.4", src=ep.ip4) /
3200 UDP(sport=1234, dport=1234) /
3202 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
3204 # host 2 is the DP learned TEP
3206 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
3207 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[2].ip4)
3209 self.wait_for_ep_timeout(ip=rep_3.ip4,
3210 tep=[self.pg2.local_ip4,
3211 self.pg2.remote_hosts[2].ip4])
3213 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
3215 # host 1 is the CP learned TEP
3217 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
3218 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
3221 # shutdown with learnt endpoint present
3223 p = (Ether(src=self.pg2.remote_mac,
3224 dst=self.pg2.local_mac) /
3225 IP(src=self.pg2.remote_hosts[1].ip4,
3226 dst=self.pg2.local_ip4) /
3227 UDP(sport=1234, dport=48879) /
3228 VXLAN(vni=101, gpid=441, flags=0x88) /
3229 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
3230 IP(src=learnt[1]['ip'], dst=ep.ip4) /
3231 UDP(sport=1234, dport=1234) /
3234 rx = self.send_and_expect(self.pg2, [p], self.pg0)
3236 # endpoint learnt via the parent GBP-vxlan interface
3237 self.assertTrue(find_gbp_endpoint(self,
3238 vx_tun_l3._sw_if_index,
3243 # remote endpoint becomes local
3245 self.pg2.unconfig_ip4()
3246 self.pg3.unconfig_ip4()
3247 self.pg4.unconfig_ip4()
3249 def test_gbp_redirect(self):
3250 """ GBP Endpoint Redirect """
3252 self.vapi.cli("set logging class gbp level debug")
3254 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
3255 routed_dst_mac = "00:0c:0c:0c:0c:0c"
3256 routed_src_mac = "00:22:bd:f8:19:ff"
3258 learnt = [{'mac': '00:00:11:11:11:02',
3260 'ip6': '2001:10::2'},
3261 {'mac': '00:00:11:11:11:03',
3263 'ip6': '2001:10::3'}]
3268 t4 = VppIpTable(self, 1)
3270 t6 = VppIpTable(self, 1, True)
3273 rd1 = VppGbpRouteDomain(self, 2, 402, t4, t6)
3274 rd1.add_vpp_config()
3276 self.loop0.set_mac(self.router_mac)
3279 # Bind the BVI to the RD
3281 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
3282 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
3285 # Pg7 hosts a BD's UU-fwd
3287 self.pg7.config_ip4()
3288 self.pg7.resolve_arp()
3291 # a GBP bridge domains for the EPs
3293 bd1 = VppBridgeDomain(self, 1)
3294 bd1.add_vpp_config()
3295 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0)
3296 gbd1.add_vpp_config()
3298 bd2 = VppBridgeDomain(self, 2)
3299 bd2.add_vpp_config()
3300 gbd2 = VppGbpBridgeDomain(self, bd2, rd1, self.loop1)
3301 gbd2.add_vpp_config()
3303 # ... and has a /32 and /128 applied
3304 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
3305 ip4_addr.add_vpp_config()
3306 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 128)
3307 ip6_addr.add_vpp_config()
3308 ip4_addr = VppIpInterfaceAddress(self, gbd2.bvi, "10.0.1.128", 32)
3309 ip4_addr.add_vpp_config()
3310 ip6_addr = VppIpInterfaceAddress(self, gbd2.bvi, "2001:11::128", 128)
3311 ip6_addr.add_vpp_config()
3314 # The Endpoint-groups in which we are learning endpoints
3316 epg_220 = VppGbpEndpointGroup(self, 220, 440, rd1, gbd1,
3320 VppGbpEndpointRetention(60))
3321 epg_220.add_vpp_config()
3322 epg_221 = VppGbpEndpointGroup(self, 221, 441, rd1, gbd2,
3326 VppGbpEndpointRetention(60))
3327 epg_221.add_vpp_config()
3328 epg_222 = VppGbpEndpointGroup(self, 222, 442, rd1, gbd1,
3332 VppGbpEndpointRetention(60))
3333 epg_222.add_vpp_config()
3336 # a GBP bridge domains for the SEPs
3338 bd_uu1 = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
3339 self.pg7.remote_ip4, 116)
3340 bd_uu1.add_vpp_config()
3341 bd_uu2 = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
3342 self.pg7.remote_ip4, 117)
3343 bd_uu2.add_vpp_config()
3345 bd3 = VppBridgeDomain(self, 3)
3346 bd3.add_vpp_config()
3347 gbd3 = VppGbpBridgeDomain(self, bd3, rd1, self.loop2,
3348 bd_uu1, learn=False)
3349 gbd3.add_vpp_config()
3350 bd4 = VppBridgeDomain(self, 4)
3351 bd4.add_vpp_config()
3352 gbd4 = VppGbpBridgeDomain(self, bd4, rd1, self.loop3,
3353 bd_uu2, learn=False)
3354 gbd4.add_vpp_config()
3357 # EPGs in which the service endpoints exist
3359 epg_320 = VppGbpEndpointGroup(self, 320, 550, rd1, gbd3,
3363 VppGbpEndpointRetention(60))
3364 epg_320.add_vpp_config()
3365 epg_321 = VppGbpEndpointGroup(self, 321, 551, rd1, gbd4,
3369 VppGbpEndpointRetention(60))
3370 epg_321.add_vpp_config()
3373 # three local endpoints
3375 ep1 = VppGbpEndpoint(self, self.pg0,
3377 "10.0.0.1", "11.0.0.1",
3378 "2001:10::1", "3001:10::1")
3379 ep1.add_vpp_config()
3380 ep2 = VppGbpEndpoint(self, self.pg1,
3382 "10.0.1.1", "11.0.1.1",
3383 "2001:11::1", "3001:11::1")
3384 ep2.add_vpp_config()
3385 ep3 = VppGbpEndpoint(self, self.pg2,
3387 "10.0.2.2", "11.0.2.2",
3388 "2001:12::1", "3001:12::1")
3389 ep3.add_vpp_config()
3394 sep1 = VppGbpEndpoint(self, self.pg3,
3396 "12.0.0.1", "13.0.0.1",
3397 "4001:10::1", "5001:10::1")
3398 sep1.add_vpp_config()
3399 sep2 = VppGbpEndpoint(self, self.pg4,
3401 "12.0.0.2", "13.0.0.2",
3402 "4001:10::2", "5001:10::2")
3403 sep2.add_vpp_config()
3404 sep3 = VppGbpEndpoint(self, self.pg5,
3406 "12.0.1.1", "13.0.1.1",
3407 "4001:11::1", "5001:11::1")
3408 sep3.add_vpp_config()
3409 # this EP is not installed immediately
3410 sep4 = VppGbpEndpoint(self, self.pg6,
3412 "12.0.1.2", "13.0.1.2",
3413 "4001:11::2", "5001:11::2")
3416 # an L2 switch packet between local EPs in different EPGs
3417 # different dest ports on each so the are LB hashed differently
3419 p4 = [(Ether(src=ep1.mac, dst=ep3.mac) /
3420 IP(src=ep1.ip4, dst=ep3.ip4) /
3421 UDP(sport=1234, dport=1234) /
3422 Raw(b'\xa5' * 100)),
3423 (Ether(src=ep3.mac, dst=ep1.mac) /
3424 IP(src=ep3.ip4, dst=ep1.ip4) /
3425 UDP(sport=1234, dport=1234) /
3426 Raw(b'\xa5' * 100))]
3427 p6 = [(Ether(src=ep1.mac, dst=ep3.mac) /
3428 IPv6(src=ep1.ip6, dst=ep3.ip6) /
3429 UDP(sport=1234, dport=1234) /
3430 Raw(b'\xa5' * 100)),
3431 (Ether(src=ep3.mac, dst=ep1.mac) /
3432 IPv6(src=ep3.ip6, dst=ep1.ip6) /
3433 UDP(sport=1234, dport=1230) /
3434 Raw(b'\xa5' * 100))]
3436 # should be dropped since no contract yet
3437 self.send_and_assert_no_replies(self.pg0, [p4[0]])
3438 self.send_and_assert_no_replies(self.pg0, [p6[0]])
3441 # Add a contract with a rule to load-balance redirect via SEP1 and SEP2
3442 # one of the next-hops is via an EP that is not known
3444 rule4 = AclRule(is_permit=1, proto=17)
3445 rule6 = AclRule(src_prefix=IPv6Network((0, 0)),
3446 dst_prefix=IPv6Network((0, 0)), is_permit=1, proto=17)
3447 acl = VppAcl(self, rules=[rule4, rule6])
3448 acl.add_vpp_config()
3451 # test the src-ip hash mode
3453 c1 = VppGbpContract(
3454 self, 402, epg_220.sclass, epg_222.sclass, acl.acl_index,
3455 [VppGbpContractRule(
3456 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3457 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3458 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3459 sep1.ip4, sep1.epg.rd),
3460 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3461 sep2.ip4, sep2.epg.rd)]),
3463 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3464 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3465 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3466 sep3.ip6, sep3.epg.rd),
3467 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3468 sep4.ip6, sep4.epg.rd)])],
3469 [ETH_P_IP, ETH_P_IPV6])
3472 c2 = VppGbpContract(
3473 self, 402, epg_222.sclass, epg_220.sclass, acl.acl_index,
3474 [VppGbpContractRule(
3475 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3476 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3477 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3478 sep1.ip4, sep1.epg.rd),
3479 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3480 sep2.ip4, sep2.epg.rd)]),
3482 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3483 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3484 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3485 sep3.ip6, sep3.epg.rd),
3486 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3487 sep4.ip6, sep4.epg.rd)])],
3488 [ETH_P_IP, ETH_P_IPV6])
3492 # send again with the contract preset, now packets arrive
3493 # at SEP1 or SEP2 depending on the hashing
3495 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3498 self.assertEqual(rx[Ether].src, routed_src_mac)
3499 self.assertEqual(rx[Ether].dst, sep1.mac)
3500 self.assertEqual(rx[IP].src, ep1.ip4)
3501 self.assertEqual(rx[IP].dst, ep3.ip4)
3503 rxs = self.send_and_expect(self.pg2, p4[1] * 17, sep2.itf)
3506 self.assertEqual(rx[Ether].src, routed_src_mac)
3507 self.assertEqual(rx[Ether].dst, sep2.mac)
3508 self.assertEqual(rx[IP].src, ep3.ip4)
3509 self.assertEqual(rx[IP].dst, ep1.ip4)
3511 rxs = self.send_and_expect(self.pg0, p6[0] * 17, self.pg7)
3514 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3515 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3516 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3517 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
3518 self.assertEqual(rx[VXLAN].vni, 117)
3519 self.assertTrue(rx[VXLAN].flags.G)
3520 self.assertTrue(rx[VXLAN].flags.Instance)
3521 # redirect policy has been applied
3522 self.assertTrue(rx[VXLAN].gpflags.A)
3523 self.assertFalse(rx[VXLAN].gpflags.D)
3525 inner = rx[VXLAN].payload
3527 self.assertEqual(inner[Ether].src, routed_src_mac)
3528 self.assertEqual(inner[Ether].dst, sep4.mac)
3529 self.assertEqual(inner[IPv6].src, ep1.ip6)
3530 self.assertEqual(inner[IPv6].dst, ep3.ip6)
3532 rxs = self.send_and_expect(self.pg2, p6[1] * 17, sep3.itf)
3535 self.assertEqual(rx[Ether].src, routed_src_mac)
3536 self.assertEqual(rx[Ether].dst, sep3.mac)
3537 self.assertEqual(rx[IPv6].src, ep3.ip6)
3538 self.assertEqual(rx[IPv6].dst, ep1.ip6)
3541 # programme the unknown EP
3543 sep4.add_vpp_config()
3545 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep4.itf)
3548 self.assertEqual(rx[Ether].src, routed_src_mac)
3549 self.assertEqual(rx[Ether].dst, sep4.mac)
3550 self.assertEqual(rx[IPv6].src, ep1.ip6)
3551 self.assertEqual(rx[IPv6].dst, ep3.ip6)
3554 # and revert back to unprogrammed
3556 sep4.remove_vpp_config()
3558 rxs = self.send_and_expect(self.pg0, p6[0] * 17, self.pg7)
3561 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3562 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3563 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3564 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
3565 self.assertEqual(rx[VXLAN].vni, 117)
3566 self.assertTrue(rx[VXLAN].flags.G)
3567 self.assertTrue(rx[VXLAN].flags.Instance)
3568 # redirect policy has been applied
3569 self.assertTrue(rx[VXLAN].gpflags.A)
3570 self.assertFalse(rx[VXLAN].gpflags.D)
3572 inner = rx[VXLAN].payload
3574 self.assertEqual(inner[Ether].src, routed_src_mac)
3575 self.assertEqual(inner[Ether].dst, sep4.mac)
3576 self.assertEqual(inner[IPv6].src, ep1.ip6)
3577 self.assertEqual(inner[IPv6].dst, ep3.ip6)
3579 c1.remove_vpp_config()
3580 c2.remove_vpp_config()
3583 # test the symmetric hash mode
3585 c1 = VppGbpContract(
3586 self, 402, epg_220.sclass, epg_222.sclass, acl.acl_index,
3587 [VppGbpContractRule(
3588 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3589 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3590 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3591 sep1.ip4, sep1.epg.rd),
3592 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3593 sep2.ip4, sep2.epg.rd)]),
3595 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3596 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3597 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3598 sep3.ip6, sep3.epg.rd),
3599 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3600 sep4.ip6, sep4.epg.rd)])],
3601 [ETH_P_IP, ETH_P_IPV6])
3604 c2 = VppGbpContract(
3605 self, 402, epg_222.sclass, epg_220.sclass, acl.acl_index,
3606 [VppGbpContractRule(
3607 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3608 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3609 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3610 sep1.ip4, sep1.epg.rd),
3611 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3612 sep2.ip4, sep2.epg.rd)]),
3614 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3615 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3616 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3617 sep3.ip6, sep3.epg.rd),
3618 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3619 sep4.ip6, sep4.epg.rd)])],
3620 [ETH_P_IP, ETH_P_IPV6])
3624 # send again with the contract preset, now packets arrive
3625 # at SEP1 for both directions
3627 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3630 self.assertEqual(rx[Ether].src, routed_src_mac)
3631 self.assertEqual(rx[Ether].dst, sep1.mac)
3632 self.assertEqual(rx[IP].src, ep1.ip4)
3633 self.assertEqual(rx[IP].dst, ep3.ip4)
3635 rxs = self.send_and_expect(self.pg2, p4[1] * 17, sep1.itf)
3638 self.assertEqual(rx[Ether].src, routed_src_mac)
3639 self.assertEqual(rx[Ether].dst, sep1.mac)
3640 self.assertEqual(rx[IP].src, ep3.ip4)
3641 self.assertEqual(rx[IP].dst, ep1.ip4)
3644 # programme the unknown EP for the L3 tests
3646 sep4.add_vpp_config()
3649 # an L3 switch packet between local EPs in different EPGs
3650 # different dest ports on each so the are LB hashed differently
3652 p4 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3653 IP(src=ep1.ip4, dst=ep2.ip4) /
3654 UDP(sport=1234, dport=1234) /
3655 Raw(b'\xa5' * 100)),
3656 (Ether(src=ep2.mac, dst=str(self.router_mac)) /
3657 IP(src=ep2.ip4, dst=ep1.ip4) /
3658 UDP(sport=1234, dport=1234) /
3659 Raw(b'\xa5' * 100))]
3660 p6 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3661 IPv6(src=ep1.ip6, dst=ep2.ip6) /
3662 UDP(sport=1234, dport=1234) /
3663 Raw(b'\xa5' * 100)),
3664 (Ether(src=ep2.mac, dst=str(self.router_mac)) /
3665 IPv6(src=ep2.ip6, dst=ep1.ip6) /
3666 UDP(sport=1234, dport=1234) /
3667 Raw(b'\xa5' * 100))]
3669 c3 = VppGbpContract(
3670 self, 402, epg_220.sclass, epg_221.sclass, acl.acl_index,
3671 [VppGbpContractRule(
3672 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3673 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3674 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3675 sep1.ip4, sep1.epg.rd),
3676 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3677 sep2.ip4, sep2.epg.rd)]),
3679 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3680 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3681 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3682 sep3.ip6, sep3.epg.rd),
3683 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3684 sep4.ip6, sep4.epg.rd)])],
3685 [ETH_P_IP, ETH_P_IPV6])
3688 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3691 self.assertEqual(rx[Ether].src, routed_src_mac)
3692 self.assertEqual(rx[Ether].dst, sep1.mac)
3693 self.assertEqual(rx[IP].src, ep1.ip4)
3694 self.assertEqual(rx[IP].dst, ep2.ip4)
3697 # learn a remote EP in EPG 221
3698 # packets coming from unknown remote EPs will be leant & redirected
3700 vx_tun_l3 = VppGbpVxlanTunnel(
3701 self, 444, rd1.rd_id,
3702 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
3704 vx_tun_l3.add_vpp_config()
3706 c4 = VppGbpContract(
3707 self, 402, epg_221.sclass, epg_220.sclass, acl.acl_index,
3708 [VppGbpContractRule(
3709 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3710 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3711 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3712 sep1.ip4, sep1.epg.rd),
3713 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3714 sep2.ip4, sep2.epg.rd)]),
3716 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3717 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3718 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3719 sep3.ip6, sep3.epg.rd),
3720 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3721 sep4.ip6, sep4.epg.rd)])],
3722 [ETH_P_IP, ETH_P_IPV6])
3725 p = (Ether(src=self.pg7.remote_mac,
3726 dst=self.pg7.local_mac) /
3727 IP(src=self.pg7.remote_ip4,
3728 dst=self.pg7.local_ip4) /
3729 UDP(sport=1234, dport=48879) /
3730 VXLAN(vni=444, gpid=441, flags=0x88) /
3731 Ether(src="00:22:22:22:22:33", dst=str(self.router_mac)) /
3732 IP(src="10.0.0.88", dst=ep1.ip4) /
3733 UDP(sport=1234, dport=1234) /
3736 # unknown remote EP to local EP redirected
3737 rxs = self.send_and_expect(self.pg7, [p], sep1.itf)
3740 self.assertEqual(rx[Ether].src, routed_src_mac)
3741 self.assertEqual(rx[Ether].dst, sep1.mac)
3742 self.assertEqual(rx[IP].src, "10.0.0.88")
3743 self.assertEqual(rx[IP].dst, ep1.ip4)
3745 # endpoint learnt via the parent GBP-vxlan interface
3746 self.assertTrue(find_gbp_endpoint(self,
3747 vx_tun_l3._sw_if_index,
3750 p = (Ether(src=self.pg7.remote_mac,
3751 dst=self.pg7.local_mac) /
3752 IP(src=self.pg7.remote_ip4,
3753 dst=self.pg7.local_ip4) /
3754 UDP(sport=1234, dport=48879) /
3755 VXLAN(vni=444, gpid=441, flags=0x88) /
3756 Ether(src="00:22:22:22:22:33", dst=str(self.router_mac)) /
3757 IPv6(src="2001:10::88", dst=ep1.ip6) /
3758 UDP(sport=1234, dport=1234) /
3761 # unknown remote EP to local EP redirected (ipv6)
3762 rxs = self.send_and_expect(self.pg7, [p], sep3.itf)
3765 self.assertEqual(rx[Ether].src, routed_src_mac)
3766 self.assertEqual(rx[Ether].dst, sep3.mac)
3767 self.assertEqual(rx[IPv6].src, "2001:10::88")
3768 self.assertEqual(rx[IPv6].dst, ep1.ip6)
3770 # endpoint learnt via the parent GBP-vxlan interface
3771 self.assertTrue(find_gbp_endpoint(self,
3772 vx_tun_l3._sw_if_index,
3776 # L3 switch from local to remote EP
3778 p4 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3779 IP(src=ep1.ip4, dst="10.0.0.88") /
3780 UDP(sport=1234, dport=1234) /
3781 Raw(b'\xa5' * 100))]
3782 p6 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3783 IPv6(src=ep1.ip6, dst="2001:10::88") /
3784 UDP(sport=1234, dport=1234) /
3785 Raw(b'\xa5' * 100))]
3787 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3790 self.assertEqual(rx[Ether].src, routed_src_mac)
3791 self.assertEqual(rx[Ether].dst, sep1.mac)
3792 self.assertEqual(rx[IP].src, ep1.ip4)
3793 self.assertEqual(rx[IP].dst, "10.0.0.88")
3795 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep4.itf)
3798 self.assertEqual(rx[Ether].src, routed_src_mac)
3799 self.assertEqual(rx[Ether].dst, sep4.mac)
3800 self.assertEqual(rx[IPv6].src, ep1.ip6)
3801 self.assertEqual(rx[IPv6].dst, "2001:10::88")
3804 # test the dst-ip hash mode
3806 c5 = VppGbpContract(
3807 self, 402, epg_220.sclass, epg_221.sclass, acl.acl_index,
3808 [VppGbpContractRule(
3809 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3810 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
3811 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3812 sep1.ip4, sep1.epg.rd),
3813 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3814 sep2.ip4, sep2.epg.rd)]),
3816 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3817 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
3818 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3819 sep3.ip6, sep3.epg.rd),
3820 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3821 sep4.ip6, sep4.epg.rd)])],
3822 [ETH_P_IP, ETH_P_IPV6])
3825 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3828 self.assertEqual(rx[Ether].src, routed_src_mac)
3829 self.assertEqual(rx[Ether].dst, sep1.mac)
3830 self.assertEqual(rx[IP].src, ep1.ip4)
3831 self.assertEqual(rx[IP].dst, "10.0.0.88")
3833 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep3.itf)
3836 self.assertEqual(rx[Ether].src, routed_src_mac)
3837 self.assertEqual(rx[Ether].dst, sep3.mac)
3838 self.assertEqual(rx[IPv6].src, ep1.ip6)
3839 self.assertEqual(rx[IPv6].dst, "2001:10::88")
3842 # a programmed remote SEP in EPG 320
3845 # gbp vxlan tunnel for the remote SEP
3846 vx_tun_l3_sep = VppGbpVxlanTunnel(
3847 self, 555, rd1.rd_id,
3848 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
3850 vx_tun_l3_sep.add_vpp_config()
3853 sep5 = VppGbpEndpoint(self, vx_tun_l3_sep,
3855 "12.0.0.10", "13.0.0.10",
3856 "4001:10::10", "5001:10::10",
3857 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
3859 self.pg7.remote_ip4,
3861 sep5.add_vpp_config()
3864 # local l3out redirect tests
3869 self.loop4.set_mac(self.router_mac)
3870 VppIpInterfaceBind(self, self.loop4, t4).add_vpp_config()
3871 VppIpInterfaceBind(self, self.loop4, t6).add_vpp_config()
3872 ebd = VppBridgeDomain(self, 100)
3873 ebd.add_vpp_config()
3874 gebd = VppGbpBridgeDomain(self, ebd, rd1, self.loop4, None, None)
3875 gebd.add_vpp_config()
3877 eepg = VppGbpEndpointGroup(self, 888, 765, rd1, gebd,
3881 VppGbpEndpointRetention(60))
3882 eepg.add_vpp_config()
3883 # add subnets to BVI
3884 VppIpInterfaceAddress(
3888 24).add_vpp_config()
3889 VppIpInterfaceAddress(
3893 64).add_vpp_config()
3894 # ... which are L3-out subnets
3895 VppGbpSubnet(self, rd1, "10.1.0.0", 24,
3896 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3897 sclass=765).add_vpp_config()
3898 VppGbpSubnet(self, rd1, "2001:10:1::128", 64,
3899 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3900 sclass=765).add_vpp_config()
3901 # external endpoints
3902 VppL2Vtr(self, self.vlan_100, L2_VTR_OP.L2_POP_1).add_vpp_config()
3903 eep1 = VppGbpEndpoint(self, self.vlan_100, eepg, None, "10.1.0.1",
3904 "11.1.0.1", "2001:10:1::1", "3001:10:1::1",
3905 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
3906 eep1.add_vpp_config()
3907 VppL2Vtr(self, self.vlan_101, L2_VTR_OP.L2_POP_1).add_vpp_config()
3908 eep2 = VppGbpEndpoint(self, self.vlan_101, eepg, None, "10.1.0.2",
3909 "11.1.0.2", "2001:10:1::2", "3001:10:1::2",
3910 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
3911 eep2.add_vpp_config()
3913 # external subnets reachable though eep1 and eep2 respectively
3914 VppIpRoute(self, "10.220.0.0", 24,
3915 [VppRoutePath(eep1.ip4, eep1.epg.bvi.sw_if_index)],
3916 table_id=t4.table_id).add_vpp_config()
3917 VppGbpSubnet(self, rd1, "10.220.0.0", 24,
3918 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3919 sclass=4220).add_vpp_config()
3920 VppIpRoute(self, "10:220::", 64,
3921 [VppRoutePath(eep1.ip6, eep1.epg.bvi.sw_if_index)],
3922 table_id=t6.table_id).add_vpp_config()
3923 VppGbpSubnet(self, rd1, "10:220::", 64,
3924 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3925 sclass=4220).add_vpp_config()
3926 VppIpRoute(self, "10.221.0.0", 24,
3927 [VppRoutePath(eep2.ip4, eep2.epg.bvi.sw_if_index)],
3928 table_id=t4.table_id).add_vpp_config()
3929 VppGbpSubnet(self, rd1, "10.221.0.0", 24,
3930 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3931 sclass=4221).add_vpp_config()
3932 VppIpRoute(self, "10:221::", 64,
3933 [VppRoutePath(eep2.ip6, eep2.epg.bvi.sw_if_index)],
3934 table_id=t6.table_id).add_vpp_config()
3935 VppGbpSubnet(self, rd1, "10:221::", 64,
3936 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3937 sclass=4221).add_vpp_config()
3940 # l3out redirect to remote (known, then unknown) SEP
3943 # packets from 1 external subnet to the other
3944 p = [(Ether(src=eep1.mac, dst=self.router_mac) /
3946 IP(src="10.220.0.17", dst="10.221.0.65") /
3947 UDP(sport=1234, dport=1234) /
3948 Raw(b'\xa5' * 100)),
3949 (Ether(src=eep1.mac, dst=self.router_mac) /
3951 IPv6(src="10:220::17", dst="10:221::65") /
3952 UDP(sport=1234, dport=1234) /
3953 Raw(b'\xa5' * 100))]
3955 # packets should be dropped in absence of contract
3956 self.send_and_assert_no_replies(self.pg0, p)
3958 # contract redirecting to sep5
3960 self, 402, 4220, 4221, acl.acl_index,
3961 [VppGbpContractRule(
3962 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3963 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
3964 [VppGbpContractNextHop(sep5.vmac, sep5.epg.bd,
3965 sep5.ip4, sep5.epg.rd)]),
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.ip6, sep5.epg.rd)])],
3971 [ETH_P_IP, ETH_P_IPV6]).add_vpp_config()
3973 rxs = self.send_and_expect(self.pg0, p, self.pg7)
3975 for rx, tx in zip(rxs, p):
3976 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3977 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3978 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3979 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
3980 # this should use the programmed remote leaf TEP
3981 self.assertEqual(rx[VXLAN].vni, 555)
3982 self.assertEqual(rx[VXLAN].gpid, 4220)
3983 self.assertTrue(rx[VXLAN].flags.G)
3984 self.assertTrue(rx[VXLAN].flags.Instance)
3985 # redirect policy has been applied
3986 self.assertTrue(rx[VXLAN].gpflags.A)
3987 self.assertTrue(rx[VXLAN].gpflags.D)
3988 rxip = rx[VXLAN][Ether].payload
3989 txip = tx[Dot1Q].payload
3990 self.assertEqual(rxip.src, txip.src)
3991 self.assertEqual(rxip.dst, txip.dst)
3993 # remote SEP: it is now an unknown remote SEP and should go
3995 sep5.remove_vpp_config()
3997 rxs = self.send_and_expect(self.pg0, p, self.pg7)
3999 for rx, tx in zip(rxs, p):
4000 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4001 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4002 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4003 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4004 # this should use the spine proxy TEP
4005 self.assertEqual(rx[VXLAN].vni, epg_320.bd.uu_fwd.vni)
4006 self.assertEqual(rx[VXLAN].gpid, 4220)
4007 self.assertTrue(rx[VXLAN].flags.G)
4008 self.assertTrue(rx[VXLAN].flags.Instance)
4009 # redirect policy has been applied
4010 self.assertTrue(rx[VXLAN].gpflags.A)
4011 self.assertTrue(rx[VXLAN].gpflags.D)
4012 rxip = rx[VXLAN][Ether].payload
4013 txip = tx[Dot1Q].payload
4014 self.assertEqual(rxip.src, txip.src)
4015 self.assertEqual(rxip.dst, txip.dst)
4018 # l3out redirect to local SEP
4021 # change the contract between l3out to redirect to local SEPs
4022 # instead of remote SEP
4024 self, 402, 4220, 4221, acl.acl_index,
4025 [VppGbpContractRule(
4026 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4027 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
4028 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
4029 sep1.ip4, sep1.epg.rd)]),
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.ip6, sep1.epg.rd)])],
4035 [ETH_P_IP, ETH_P_IPV6]).add_vpp_config()
4037 rxs = self.send_and_expect(self.pg0, p, sep1.itf)
4038 for rx, tx in zip(rxs, p):
4039 self.assertEqual(rx[Ether].src, routed_src_mac)
4040 self.assertEqual(rx[Ether].dst, sep1.mac)
4041 rxip = rx[Ether].payload
4042 txip = tx[Ether].payload
4043 self.assertEqual(rxip.src, txip.src)
4044 self.assertEqual(rxip.dst, txip.dst)
4047 # redirect remote EP to remote (known then unknown) SEP
4050 # remote SEP known again
4051 sep5.add_vpp_config()
4053 # contract to redirect to learnt SEP
4055 self, 402, epg_221.sclass, epg_222.sclass, acl.acl_index,
4056 [VppGbpContractRule(
4057 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4058 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
4059 [VppGbpContractNextHop(sep5.vmac, sep5.epg.bd,
4060 sep5.ip4, sep5.epg.rd)]),
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.ip6, sep5.epg.rd)])],
4066 [ETH_P_IP, ETH_P_IPV6]).add_vpp_config()
4068 # packets from unknown EP 221 to known EP in EPG 222
4069 # should be redirected to known remote SEP
4070 base = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
4071 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
4072 UDP(sport=1234, dport=48879) /
4073 VXLAN(vni=444, gpid=441, flags=0x88) /
4074 Ether(src="00:22:22:22:22:44", dst=str(self.router_mac)))
4076 IP(src="10.0.1.100", dst=ep3.ip4) /
4077 UDP(sport=1234, dport=1234) /
4078 Raw(b'\xa5' * 100)),
4080 IPv6(src="2001:10::100", dst=ep3.ip6) /
4081 UDP(sport=1234, dport=1234) /
4082 Raw(b'\xa5' * 100))]
4084 # unknown remote EP to local EP redirected to known remote SEP
4085 rxs = self.send_and_expect(self.pg7, p, self.pg7)
4087 for rx, tx in zip(rxs, p):
4088 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4089 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4090 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4091 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4092 # this should use the programmed remote leaf TEP
4093 self.assertEqual(rx[VXLAN].vni, 555)
4094 self.assertEqual(rx[VXLAN].gpid, epg_221.sclass)
4095 self.assertTrue(rx[VXLAN].flags.G)
4096 self.assertTrue(rx[VXLAN].flags.Instance)
4097 # redirect policy has been applied
4098 self.assertTrue(rx[VXLAN].gpflags.A)
4099 self.assertFalse(rx[VXLAN].gpflags.D)
4100 rxip = rx[VXLAN][Ether].payload
4101 txip = tx[VXLAN][Ether].payload
4102 self.assertEqual(rxip.src, txip.src)
4103 self.assertEqual(rxip.dst, txip.dst)
4105 # endpoint learnt via the parent GBP-vxlan interface
4106 self.assertTrue(find_gbp_endpoint(self,
4107 vx_tun_l3._sw_if_index,
4109 self.assertTrue(find_gbp_endpoint(self,
4110 vx_tun_l3._sw_if_index,
4113 # remote SEP: it is now an unknown remote SEP and should go
4115 sep5.remove_vpp_config()
4117 # remote EP (coming from spine proxy) to local EP redirected to
4119 rxs = self.send_and_expect(self.pg7, p, self.pg7)
4121 for rx, tx in zip(rxs, p):
4122 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4123 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4124 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4125 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4126 # this should use the spine proxy TEP
4127 self.assertEqual(rx[VXLAN].vni, epg_320.bd.uu_fwd.vni)
4128 self.assertEqual(rx[VXLAN].gpid, epg_221.sclass)
4129 self.assertTrue(rx[VXLAN].flags.G)
4130 self.assertTrue(rx[VXLAN].flags.Instance)
4131 # redirect policy has been applied
4132 self.assertTrue(rx[VXLAN].gpflags.A)
4133 self.assertFalse(rx[VXLAN].gpflags.D)
4134 rxip = rx[VXLAN][Ether].payload
4135 txip = tx[VXLAN][Ether].payload
4136 self.assertEqual(rxip.src, txip.src)
4137 self.assertEqual(rxip.dst, txip.dst)
4142 self.pg7.unconfig_ip4()
4144 def test_gbp_redirect_extended(self):
4145 """ GBP Endpoint Redirect Extended """
4147 self.vapi.cli("set logging class gbp level debug")
4149 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
4150 routed_dst_mac = "00:0c:0c:0c:0c:0c"
4151 routed_src_mac = "00:22:bd:f8:19:ff"
4153 learnt = [{'mac': '00:00:11:11:11:02',
4155 'ip6': '2001:10::2'},
4156 {'mac': '00:00:11:11:11:03',
4158 'ip6': '2001:10::3'}]
4163 t4 = VppIpTable(self, 1)
4165 t6 = VppIpTable(self, 1, True)
4168 # create IPv4 and IPv6 RD UU VxLAN-GBP TEP and bind them to the right
4170 rd_uu4 = VppVxlanGbpTunnel(
4173 self.pg7.remote_ip4,
4175 mode=(VppEnum.vl_api_vxlan_gbp_api_tunnel_mode_t.
4176 VXLAN_GBP_API_TUNNEL_MODE_L3))
4177 rd_uu4.add_vpp_config()
4178 VppIpInterfaceBind(self, rd_uu4, t4).add_vpp_config()
4180 rd_uu6 = VppVxlanGbpTunnel(
4183 self.pg7.remote_ip4,
4185 mode=(VppEnum.vl_api_vxlan_gbp_api_tunnel_mode_t.
4186 VXLAN_GBP_API_TUNNEL_MODE_L3))
4187 rd_uu6.add_vpp_config()
4188 VppIpInterfaceBind(self, rd_uu6, t4).add_vpp_config()
4190 rd1 = VppGbpRouteDomain(self, 2, 402, t4, t6, rd_uu4, rd_uu6)
4191 rd1.add_vpp_config()
4193 self.loop0.set_mac(self.router_mac)
4194 self.loop1.set_mac(self.router_mac)
4195 self.loop2.set_mac(self.router_mac)
4198 # Bind the BVI to the RD
4200 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
4201 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
4202 VppIpInterfaceBind(self, self.loop1, t4).add_vpp_config()
4203 VppIpInterfaceBind(self, self.loop1, t6).add_vpp_config()
4204 VppIpInterfaceBind(self, self.loop2, t4).add_vpp_config()
4205 VppIpInterfaceBind(self, self.loop2, t6).add_vpp_config()
4208 # Pg7 hosts a BD's UU-fwd
4210 self.pg7.config_ip4()
4211 self.pg7.resolve_arp()
4214 # a GBP bridge domains for the EPs
4216 bd1 = VppBridgeDomain(self, 1)
4217 bd1.add_vpp_config()
4218 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0)
4219 gbd1.add_vpp_config()
4221 bd2 = VppBridgeDomain(self, 2)
4222 bd2.add_vpp_config()
4223 gbd2 = VppGbpBridgeDomain(self, bd2, rd1, self.loop1)
4224 gbd2.add_vpp_config()
4226 # ... and has a /32 and /128 applied
4227 ip4_addr1 = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
4228 ip4_addr1.add_vpp_config()
4229 ip6_addr1 = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 128)
4230 ip6_addr1.add_vpp_config()
4231 ip4_addr2 = VppIpInterfaceAddress(self, gbd2.bvi, "10.0.1.128", 32)
4232 ip4_addr2.add_vpp_config()
4233 ip6_addr2 = VppIpInterfaceAddress(self, gbd2.bvi, "2001:11::128", 128)
4234 ip6_addr2.add_vpp_config()
4237 # The Endpoint-groups
4239 epg_220 = VppGbpEndpointGroup(self, 220, 440, rd1, gbd1,
4243 VppGbpEndpointRetention(60))
4244 epg_220.add_vpp_config()
4245 epg_221 = VppGbpEndpointGroup(self, 221, 441, rd1, gbd2,
4249 VppGbpEndpointRetention(60))
4250 epg_221.add_vpp_config()
4253 # a GBP bridge domains for the SEPs
4255 bd_uu3 = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
4256 self.pg7.remote_ip4, 116)
4257 bd_uu3.add_vpp_config()
4259 bd3 = VppBridgeDomain(self, 3)
4260 bd3.add_vpp_config()
4261 gbd3 = VppGbpBridgeDomain(self, bd3, rd1, self.loop2,
4262 bd_uu3, learn=False)
4263 gbd3.add_vpp_config()
4265 ip4_addr3 = VppIpInterfaceAddress(self, gbd3.bvi, "12.0.0.128", 32)
4266 ip4_addr3.add_vpp_config()
4267 ip6_addr3 = VppIpInterfaceAddress(self, gbd3.bvi, "4001:10::128", 128)
4268 ip6_addr3.add_vpp_config()
4271 # self.logger.info(self.vapi.cli("show gbp bridge"))
4272 # self.logger.info(self.vapi.cli("show vxlan-gbp tunnel"))
4273 # self.logger.info(self.vapi.cli("show gbp vxlan"))
4274 # self.logger.info(self.vapi.cli("show int addr"))
4278 # EPGs in which the service endpoints exist
4280 epg_320 = VppGbpEndpointGroup(self, 320, 550, rd1, gbd3,
4284 VppGbpEndpointRetention(60))
4285 epg_320.add_vpp_config()
4290 ep1 = VppGbpEndpoint(self, self.pg0,
4292 "10.0.0.1", "11.0.0.1",
4293 "2001:10::1", "3001:10::1")
4294 ep1.add_vpp_config()
4295 ep2 = VppGbpEndpoint(self, self.pg1,
4297 "10.0.1.1", "11.0.1.1",
4298 "2001:11::1", "3001:11::1")
4299 ep2.add_vpp_config()
4304 sep1 = VppGbpEndpoint(self, self.pg3,
4306 "12.0.0.1", "13.0.0.1",
4307 "4001:10::1", "5001:10::1")
4308 sep2 = VppGbpEndpoint(self, self.pg4,
4310 "12.0.0.2", "13.0.0.2",
4311 "4001:10::2", "5001:10::2")
4313 # sep1 and sep2 are not added to config yet
4314 # they are unknown for now
4317 # add routes to EPG subnets
4319 VppGbpSubnet(self, rd1, "10.0.0.0", 24,
4320 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT
4322 VppGbpSubnet(self, rd1, "10.0.1.0", 24,
4323 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT
4327 # Local host to known local host in different BD
4328 # with SFC contract (source and destination are in
4329 # one node and service endpoint in another node)
4331 p4 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
4332 IP(src=ep1.ip4, dst=ep2.ip4) /
4333 UDP(sport=1234, dport=1234) /
4334 Raw(b'\xa5' * 100)),
4335 (Ether(src=ep2.mac, dst=str(self.router_mac)) /
4336 IP(src=ep2.ip4, dst=ep1.ip4) /
4337 UDP(sport=1234, dport=1234) /
4338 Raw(b'\xa5' * 100))]
4339 p6 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
4340 IPv6(src=ep1.ip6, dst=ep2.ip6) /
4341 UDP(sport=1234, dport=1234) /
4342 Raw(b'\xa5' * 100)),
4343 (Ether(src=ep2.mac, dst=str(self.router_mac)) /
4344 IPv6(src=ep2.ip6, dst=ep1.ip6) /
4345 UDP(sport=1234, dport=1230) /
4346 Raw(b'\xa5' * 100))]
4348 # should be dropped since no contract yet
4349 self.send_and_assert_no_replies(self.pg0, [p4[0]])
4350 self.send_and_assert_no_replies(self.pg0, [p6[0]])
4353 # Add a contract with a rule to load-balance redirect via SEP1 and SEP2
4354 # one of the next-hops is via an EP that is not known
4356 rule4 = AclRule(is_permit=1, proto=17)
4357 rule6 = AclRule(src_prefix=IPv6Network((0, 0)),
4358 dst_prefix=IPv6Network((0, 0)), is_permit=1, proto=17)
4359 acl = VppAcl(self, rules=[rule4, rule6])
4360 acl.add_vpp_config()
4363 # test the src-ip hash mode
4365 c1 = VppGbpContract(
4366 self, 402, epg_220.sclass, epg_221.sclass, acl.acl_index,
4367 [VppGbpContractRule(
4368 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4369 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
4370 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
4371 sep1.ip4, sep1.epg.rd)]),
4373 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4374 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
4375 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
4376 sep1.ip6, sep1.epg.rd)])],
4377 [ETH_P_IP, ETH_P_IPV6])
4380 c2 = VppGbpContract(
4381 self, 402, epg_221.sclass, epg_220.sclass, acl.acl_index,
4382 [VppGbpContractRule(
4383 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4384 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
4385 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
4386 sep1.ip4, sep1.epg.rd)]),
4388 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4389 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
4390 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
4391 sep1.ip6, sep1.epg.rd)])],
4392 [ETH_P_IP, ETH_P_IPV6])
4395 # ep1 <--> ep2 redirected through sep1
4397 # packet is redirected to sep bd and then go through sep bd UU
4399 rxs = self.send_and_expect(self.pg0, p4[0] * 17, self.pg7)
4402 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4403 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4404 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4405 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4406 self.assertEqual(rx[VXLAN].vni, 116)
4407 self.assertTrue(rx[VXLAN].flags.G)
4408 self.assertTrue(rx[VXLAN].flags.Instance)
4409 # redirect policy has been applied
4410 self.assertTrue(rx[VXLAN].gpflags.A)
4411 self.assertFalse(rx[VXLAN].gpflags.D)
4413 inner = rx[VXLAN].payload
4415 self.assertEqual(inner[Ether].src, routed_src_mac)
4416 self.assertEqual(inner[Ether].dst, sep1.mac)
4417 self.assertEqual(inner[IP].src, ep1.ip4)
4418 self.assertEqual(inner[IP].dst, ep2.ip4)
4420 rxs = self.send_and_expect(self.pg1, p4[1] * 17, self.pg7)
4423 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4424 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4425 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4426 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4427 self.assertEqual(rx[VXLAN].vni, 116)
4428 self.assertTrue(rx[VXLAN].flags.G)
4429 self.assertTrue(rx[VXLAN].flags.Instance)
4430 # redirect policy has been applied
4431 self.assertTrue(rx[VXLAN].gpflags.A)
4432 self.assertFalse(rx[VXLAN].gpflags.D)
4434 inner = rx[VXLAN].payload
4436 self.assertEqual(inner[Ether].src, routed_src_mac)
4437 self.assertEqual(inner[Ether].dst, sep1.mac)
4438 self.assertEqual(inner[IP].src, ep2.ip4)
4439 self.assertEqual(inner[IP].dst, ep1.ip4)
4441 rxs = self.send_and_expect(self.pg0, p6[0] * 17, self.pg7)
4444 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4445 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4446 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4447 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4448 self.assertEqual(rx[VXLAN].vni, 116)
4449 self.assertTrue(rx[VXLAN].flags.G)
4450 self.assertTrue(rx[VXLAN].flags.Instance)
4451 # redirect policy has been applied
4452 inner = rx[VXLAN].payload
4454 self.assertEqual(inner[Ether].src, routed_src_mac)
4455 self.assertEqual(inner[Ether].dst, sep1.mac)
4456 self.assertEqual(inner[IPv6].src, ep1.ip6)
4457 self.assertEqual(inner[IPv6].dst, ep2.ip6)
4459 rxs = self.send_and_expect(self.pg1, p6[1] * 17, self.pg7)
4462 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4463 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4464 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4465 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4466 self.assertEqual(rx[VXLAN].vni, 116)
4467 self.assertTrue(rx[VXLAN].flags.G)
4468 self.assertTrue(rx[VXLAN].flags.Instance)
4469 # redirect policy has been applied
4470 self.assertTrue(rx[VXLAN].gpflags.A)
4471 self.assertFalse(rx[VXLAN].gpflags.D)
4473 inner = rx[VXLAN].payload
4475 self.assertEqual(inner[Ether].src, routed_src_mac)
4476 self.assertEqual(inner[Ether].dst, sep1.mac)
4477 self.assertEqual(inner[IPv6].src, ep2.ip6)
4478 self.assertEqual(inner[IPv6].dst, ep1.ip6)
4480 # configure sep1: it is now local
4481 # packets between ep1 and ep2 are redirected locally
4482 sep1.add_vpp_config()
4484 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
4487 self.assertEqual(rx[Ether].src, routed_src_mac)
4488 self.assertEqual(rx[Ether].dst, sep1.mac)
4489 self.assertEqual(rx[IP].src, ep1.ip4)
4490 self.assertEqual(rx[IP].dst, ep2.ip4)
4492 rxs = self.send_and_expect(self.pg1, p6[1] * 17, sep1.itf)
4495 self.assertEqual(rx[Ether].src, routed_src_mac)
4496 self.assertEqual(rx[Ether].dst, sep1.mac)
4497 self.assertEqual(rx[IPv6].src, ep2.ip6)
4498 self.assertEqual(rx[IPv6].dst, ep1.ip6)
4500 # packet coming from the l2 spine-proxy to sep1
4501 p = (Ether(src=self.pg7.remote_mac,
4502 dst=self.pg7.local_mac) /
4503 IP(src=self.pg7.remote_ip4,
4504 dst=self.pg7.local_ip4) /
4505 UDP(sport=1234, dport=48879) /
4506 VXLAN(vni=116, gpid=440, gpflags=0x08, flags=0x88) /
4507 Ether(src=str(self.router_mac), dst=sep1.mac) /
4508 IP(src=ep1.ip4, dst=ep2.ip4) /
4509 UDP(sport=1234, dport=1234) /
4512 rxs = self.send_and_expect(self.pg7, [p] * 17, sep1.itf)
4515 self.assertEqual(rx[Ether].src, str(self.router_mac))
4516 self.assertEqual(rx[Ether].dst, sep1.mac)
4517 self.assertEqual(rx[IP].src, ep1.ip4)
4518 self.assertEqual(rx[IP].dst, ep2.ip4)
4520 # contract for SEP to communicate with dst EP
4521 c3 = VppGbpContract(
4522 self, 402, epg_320.sclass, epg_221.sclass, acl.acl_index,
4523 [VppGbpContractRule(
4524 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4525 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC),
4527 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4528 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC)],
4529 [ETH_P_IP, ETH_P_IPV6])
4532 # temporarily remove ep2, so that ep2 is remote & unknown
4533 ep2.remove_vpp_config()
4535 # packet going back from sep1 to its original dest (ep2)
4536 # as ep2 is now unknown (see above), it must go through
4537 # the rd UU (packet is routed)
4539 p1 = (Ether(src=sep1.mac, dst=self.router_mac) /
4540 IP(src=ep1.ip4, dst=ep2.ip4) /
4541 UDP(sport=1234, dport=1234) /
4544 rxs = self.send_and_expect(self.pg3, [p1] * 17, self.pg7)
4547 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4548 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4549 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4550 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4551 self.assertEqual(rx[VXLAN].vni, 114)
4552 self.assertTrue(rx[VXLAN].flags.G)
4553 self.assertTrue(rx[VXLAN].flags.Instance)
4554 # redirect policy has been applied
4555 inner = rx[VXLAN].payload
4556 self.assertEqual(inner[Ether].src, routed_src_mac)
4557 self.assertEqual(inner[Ether].dst, routed_dst_mac)
4558 self.assertEqual(inner[IP].src, ep1.ip4)
4559 self.assertEqual(inner[IP].dst, ep2.ip4)
4561 self.logger.info(self.vapi.cli("show bridge 3 detail"))
4562 sep1.remove_vpp_config()
4564 self.logger.info(self.vapi.cli("show bridge 1 detail"))
4565 self.logger.info(self.vapi.cli("show bridge 2 detail"))
4567 # re-add ep2: it is local again :)
4568 ep2.add_vpp_config()
4570 # packet coming back from the remote sep through rd UU
4571 p2 = (Ether(src=self.pg7.remote_mac,
4572 dst=self.pg7.local_mac) /
4573 IP(src=self.pg7.remote_ip4,
4574 dst=self.pg7.local_ip4) /
4575 UDP(sport=1234, dport=48879) /
4576 VXLAN(vni=114, gpid=441, gpflags=0x09, flags=0x88) /
4577 Ether(src=str(self.router_mac), dst=self.router_mac) /
4578 IP(src=ep1.ip4, dst=ep2.ip4) /
4579 UDP(sport=1234, dport=1234) /
4582 rxs = self.send_and_expect(self.pg7, [p2], self.pg1)
4585 self.assertEqual(rx[Ether].src, str(self.router_mac))
4586 self.assertEqual(rx[Ether].dst, self.pg1.remote_mac)
4587 self.assertEqual(rx[IP].src, ep1.ip4)
4588 self.assertEqual(rx[IP].dst, ep2.ip4)
4591 # bd_uu2.add_vpp_config()
4597 c1.remove_vpp_config()
4598 c2.remove_vpp_config()
4599 c3.remove_vpp_config()
4600 self.pg7.unconfig_ip4()
4602 def test_gbp_l3_out(self):
4605 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
4606 self.vapi.cli("set logging class gbp level debug")
4608 routed_dst_mac = "00:0c:0c:0c:0c:0c"
4609 routed_src_mac = "00:22:bd:f8:19:ff"
4614 t4 = VppIpTable(self, 1)
4616 t6 = VppIpTable(self, 1, True)
4619 rd1 = VppGbpRouteDomain(self, 2, 55, t4, t6)
4620 rd1.add_vpp_config()
4622 self.loop0.set_mac(self.router_mac)
4625 # Bind the BVI to the RD
4627 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
4628 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
4631 # Pg7 hosts a BD's BUM
4632 # Pg1 some other l3 interface
4634 self.pg7.config_ip4()
4635 self.pg7.resolve_arp()
4638 # a multicast vxlan-gbp tunnel for broadcast in the BD
4640 tun_bm = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
4643 tun_bm.add_vpp_config()
4646 # a GBP external bridge domains for the EPs
4648 bd1 = VppBridgeDomain(self, 1)
4649 bd1.add_vpp_config()
4650 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0, None, tun_bm)
4651 gbd1.add_vpp_config()
4654 # The Endpoint-groups in which the external endpoints exist
4656 epg_220 = VppGbpEndpointGroup(self, 220, 113, rd1, gbd1,
4660 VppGbpEndpointRetention(4))
4661 epg_220.add_vpp_config()
4663 # the BVIs have the subnets applied ...
4664 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 24)
4665 ip4_addr.add_vpp_config()
4666 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 64)
4667 ip6_addr.add_vpp_config()
4669 # ... which are L3-out subnets
4670 l3o_1 = VppGbpSubnet(
4671 self, rd1, "10.0.0.0", 24,
4672 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
4674 l3o_1.add_vpp_config()
4677 # an external interface attached to the outside world and the
4680 VppL2Vtr(self, self.vlan_100, L2_VTR_OP.L2_POP_1).add_vpp_config()
4681 VppL2Vtr(self, self.vlan_101, L2_VTR_OP.L2_POP_1).add_vpp_config()
4682 vlan_144 = VppDot1QSubint(self, self.pg0, 144)
4684 # vlan_102 is not poped
4687 # an unicast vxlan-gbp for inter-RD traffic
4689 vx_tun_l3 = VppGbpVxlanTunnel(
4690 self, 444, rd1.rd_id,
4691 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
4693 vx_tun_l3.add_vpp_config()
4696 # External Endpoints
4698 eep1 = VppGbpEndpoint(self, self.vlan_100,
4700 "10.0.0.1", "11.0.0.1",
4701 "2001:10::1", "3001::1",
4702 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
4703 eep1.add_vpp_config()
4704 eep2 = VppGbpEndpoint(self, self.vlan_101,
4706 "10.0.0.2", "11.0.0.2",
4707 "2001:10::2", "3001::2",
4708 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
4709 eep2.add_vpp_config()
4710 eep3 = VppGbpEndpoint(self, self.vlan_102,
4712 "10.0.0.3", "11.0.0.3",
4713 "2001:10::3", "3001::3",
4714 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
4715 eep3.add_vpp_config()
4718 # A remote external endpoint
4720 rep = VppGbpEndpoint(self, vx_tun_l3,
4722 "10.0.0.101", "11.0.0.101",
4723 "2001:10::101", "3001::101",
4724 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
4726 self.pg7.remote_ip4,
4728 rep.add_vpp_config()
4731 # EP1 impersonating EP3 is dropped
4733 p = (Ether(src=eep1.mac, dst="ff:ff:ff:ff:ff:ff") /
4736 psrc="10.0.0.3", pdst="10.0.0.128",
4737 hwsrc=eep1.mac, hwdst="ff:ff:ff:ff:ff:ff"))
4738 self.send_and_assert_no_replies(self.pg0, p)
4741 # ARP packet from External EPs are accepted and replied to
4743 p_arp = (Ether(src=eep1.mac, dst="ff:ff:ff:ff:ff:ff") /
4746 psrc=eep1.ip4, pdst="10.0.0.128",
4747 hwsrc=eep1.mac, hwdst="ff:ff:ff:ff:ff:ff"))
4748 rxs = self.send_and_expect(self.pg0, p_arp * 1, self.pg0)
4751 # ARP packet from host in remote subnet are accepted and replied to
4753 p_arp = (Ether(src=eep3.mac, dst="ff:ff:ff:ff:ff:ff") /
4756 psrc=eep3.ip4, pdst="10.0.0.128",
4757 hwsrc=eep3.mac, hwdst="ff:ff:ff:ff:ff:ff"))
4758 rxs = self.send_and_expect(self.pg0, p_arp * 1, self.pg0)
4761 # packets destined to unknown addresses in the BVI's subnet
4764 p4 = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
4766 IP(src="10.0.0.1", dst="10.0.0.88") /
4767 UDP(sport=1234, dport=1234) /
4769 p6 = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
4771 IPv6(src="2001:10::1", dst="2001:10::88") /
4772 UDP(sport=1234, dport=1234) /
4775 rxs = self.send_and_expect(self.pg0, p4 * 1, self.pg7)
4778 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4779 # self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4780 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4781 self.assertEqual(rx[IP].dst, "239.1.1.1")
4782 self.assertEqual(rx[VXLAN].vni, 88)
4783 self.assertTrue(rx[VXLAN].flags.G)
4784 self.assertTrue(rx[VXLAN].flags.Instance)
4785 # policy was applied to the original IP packet
4786 self.assertEqual(rx[VXLAN].gpid, 113)
4787 self.assertTrue(rx[VXLAN].gpflags.A)
4788 self.assertFalse(rx[VXLAN].gpflags.D)
4790 inner = rx[VXLAN].payload
4792 self.assertTrue(inner.haslayer(ARP))
4795 # remote to external
4797 p = (Ether(src=self.pg7.remote_mac,
4798 dst=self.pg7.local_mac) /
4799 IP(src=self.pg7.remote_ip4,
4800 dst=self.pg7.local_ip4) /
4801 UDP(sport=1234, dport=48879) /
4802 VXLAN(vni=444, gpid=113, flags=0x88) /
4803 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
4804 IP(src="10.0.0.101", dst="10.0.0.1") /
4805 UDP(sport=1234, dport=1234) /
4808 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
4811 # local EP pings router
4813 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
4815 IP(src=eep1.ip4, dst="10.0.0.128") /
4816 ICMP(type='echo-request'))
4818 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
4821 self.assertEqual(rx[Ether].src, str(self.router_mac))
4822 self.assertEqual(rx[Ether].dst, eep1.mac)
4823 self.assertEqual(rx[Dot1Q].vlan, 100)
4826 # local EP pings other local EP
4828 p = (Ether(src=eep1.mac, dst=eep2.mac) /
4830 IP(src=eep1.ip4, dst=eep2.ip4) /
4831 ICMP(type='echo-request'))
4833 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
4836 self.assertEqual(rx[Ether].src, eep1.mac)
4837 self.assertEqual(rx[Ether].dst, eep2.mac)
4838 self.assertEqual(rx[Dot1Q].vlan, 101)
4841 # local EP pings router w/o vlan tag poped
4843 p = (Ether(src=eep3.mac, dst=str(self.router_mac)) /
4845 IP(src=eep3.ip4, dst="10.0.0.128") /
4846 ICMP(type='echo-request'))
4848 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
4851 self.assertEqual(rx[Ether].src, str(self.router_mac))
4852 self.assertEqual(rx[Ether].dst, self.vlan_102.remote_mac)
4855 # A ip4 subnet reachable through the external EP1
4857 ip_220 = VppIpRoute(self, "10.220.0.0", 24,
4858 [VppRoutePath(eep1.ip4,
4859 eep1.epg.bvi.sw_if_index)],
4860 table_id=t4.table_id)
4861 ip_220.add_vpp_config()
4863 l3o_220 = VppGbpSubnet(
4864 self, rd1, "10.220.0.0", 24,
4865 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
4867 l3o_220.add_vpp_config()
4870 # An ip6 subnet reachable through the external EP1
4872 ip6_220 = VppIpRoute(self, "10:220::", 64,
4873 [VppRoutePath(eep1.ip6,
4874 eep1.epg.bvi.sw_if_index)],
4875 table_id=t6.table_id)
4876 ip6_220.add_vpp_config()
4878 l3o6_220 = VppGbpSubnet(
4879 self, rd1, "10:220::", 64,
4880 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
4882 l3o6_220.add_vpp_config()
4885 # A subnet reachable through the external EP2
4887 ip_221 = VppIpRoute(self, "10.221.0.0", 24,
4888 [VppRoutePath(eep2.ip4,
4889 eep2.epg.bvi.sw_if_index)],
4890 table_id=t4.table_id)
4891 ip_221.add_vpp_config()
4893 l3o_221 = VppGbpSubnet(
4894 self, rd1, "10.221.0.0", 24,
4895 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
4897 l3o_221.add_vpp_config()
4900 # ping between hosts in remote subnets
4901 # dropped without a contract
4903 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
4905 IP(src="10.220.0.1", dst="10.221.0.1") /
4906 ICMP(type='echo-request'))
4908 self.send_and_assert_no_replies(self.pg0, p * 1)
4911 # contract for the external nets to communicate
4913 rule4 = AclRule(is_permit=1, proto=17)
4914 rule6 = AclRule(src_prefix=IPv6Network((0, 0)),
4915 dst_prefix=IPv6Network((0, 0)), is_permit=1, proto=17)
4916 acl = VppAcl(self, rules=[rule4, rule6])
4917 acl.add_vpp_config()
4920 # A contract with the wrong scope is not matched
4922 c_44 = VppGbpContract(
4923 self, 44, 4220, 4221, acl.acl_index,
4924 [VppGbpContractRule(
4925 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4926 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4929 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4930 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4932 [ETH_P_IP, ETH_P_IPV6])
4933 c_44.add_vpp_config()
4934 self.send_and_assert_no_replies(self.pg0, p * 1)
4936 c1 = VppGbpContract(
4937 self, 55, 4220, 4221, acl.acl_index,
4938 [VppGbpContractRule(
4939 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4940 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4943 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4944 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4946 [ETH_P_IP, ETH_P_IPV6])
4950 # Contracts allowing ext-net 200 to talk with external EPs
4952 c2 = VppGbpContract(
4953 self, 55, 4220, 113, acl.acl_index,
4954 [VppGbpContractRule(
4955 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4956 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4959 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4960 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4962 [ETH_P_IP, ETH_P_IPV6])
4964 c3 = VppGbpContract(
4965 self, 55, 113, 4220, acl.acl_index,
4966 [VppGbpContractRule(
4967 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4968 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4971 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4972 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4974 [ETH_P_IP, ETH_P_IPV6])
4978 # ping between hosts in remote subnets
4980 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
4982 IP(src="10.220.0.1", dst="10.221.0.1") /
4983 UDP(sport=1234, dport=1234) /
4986 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
4989 self.assertEqual(rx[Ether].src, str(self.router_mac))
4990 self.assertEqual(rx[Ether].dst, eep2.mac)
4991 self.assertEqual(rx[Dot1Q].vlan, 101)
4993 # we did not learn these external hosts
4994 self.assertFalse(find_gbp_endpoint(self, ip="10.220.0.1"))
4995 self.assertFalse(find_gbp_endpoint(self, ip="10.221.0.1"))
4998 # from remote external EP to local external EP
5000 p = (Ether(src=self.pg7.remote_mac,
5001 dst=self.pg7.local_mac) /
5002 IP(src=self.pg7.remote_ip4,
5003 dst=self.pg7.local_ip4) /
5004 UDP(sport=1234, dport=48879) /
5005 VXLAN(vni=444, gpid=113, flags=0x88) /
5006 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
5007 IP(src="10.0.0.101", dst="10.220.0.1") /
5008 UDP(sport=1234, dport=1234) /
5011 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
5014 # ping from an external host to the remote external EP
5016 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
5018 IP(src="10.220.0.1", dst=rep.ip4) /
5019 UDP(sport=1234, dport=1234) /
5022 rxs = self.send_and_expect(self.pg0, p * 1, self.pg7)
5025 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
5026 # self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
5027 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
5028 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
5029 self.assertEqual(rx[VXLAN].vni, 444)
5030 self.assertTrue(rx[VXLAN].flags.G)
5031 self.assertTrue(rx[VXLAN].flags.Instance)
5032 # the sclass of the ext-net the packet came from
5033 self.assertEqual(rx[VXLAN].gpid, 4220)
5034 # policy was applied to the original IP packet
5035 self.assertTrue(rx[VXLAN].gpflags.A)
5036 # since it's an external host the reciever should not learn it
5037 self.assertTrue(rx[VXLAN].gpflags.D)
5038 inner = rx[VXLAN].payload
5039 self.assertEqual(inner[IP].src, "10.220.0.1")
5040 self.assertEqual(inner[IP].dst, rep.ip4)
5043 # An external subnet reachable via the remote external EP
5047 # first the VXLAN-GBP tunnel over which it is reached
5049 vx_tun_r1 = VppVxlanGbpTunnel(
5050 self, self.pg7.local_ip4,
5051 self.pg7.remote_ip4, 445,
5052 mode=(VppEnum.vl_api_vxlan_gbp_api_tunnel_mode_t.
5053 VXLAN_GBP_API_TUNNEL_MODE_L3))
5054 vx_tun_r1.add_vpp_config()
5055 VppIpInterfaceBind(self, vx_tun_r1, t4).add_vpp_config()
5057 self.logger.info(self.vapi.cli("sh vxlan-gbp tunnel"))
5060 # then the special adj to resolve through on that tunnel
5062 n1 = VppNeighbor(self,
5063 vx_tun_r1.sw_if_index,
5064 "00:0c:0c:0c:0c:0c",
5065 self.pg7.remote_ip4)
5069 # the route via the adj above
5071 ip_222 = VppIpRoute(self, "10.222.0.0", 24,
5072 [VppRoutePath(self.pg7.remote_ip4,
5073 vx_tun_r1.sw_if_index)],
5074 table_id=t4.table_id)
5075 ip_222.add_vpp_config()
5077 l3o_222 = VppGbpSubnet(
5078 self, rd1, "10.222.0.0", 24,
5079 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
5081 l3o_222.add_vpp_config()
5084 # ping between hosts in local and remote external subnets
5085 # dropped without a contract
5087 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
5089 IP(src="10.220.0.1", dst="10.222.0.1") /
5090 UDP(sport=1234, dport=1234) /
5093 rxs = self.send_and_assert_no_replies(self.pg0, p * 1)
5096 # Add contracts ext-nets for 220 -> 222
5098 c4 = VppGbpContract(
5099 self, 55, 4220, 4222, acl.acl_index,
5100 [VppGbpContractRule(
5101 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5102 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5105 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5106 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5108 [ETH_P_IP, ETH_P_IPV6])
5112 # ping from host in local to remote external subnets
5114 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
5116 IP(src="10.220.0.1", dst="10.222.0.1") /
5117 UDP(sport=1234, dport=1234) /
5120 rxs = self.send_and_expect(self.pg0, p * 3, self.pg7)
5123 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
5124 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
5125 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
5126 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
5127 self.assertEqual(rx[VXLAN].vni, 445)
5128 self.assertTrue(rx[VXLAN].flags.G)
5129 self.assertTrue(rx[VXLAN].flags.Instance)
5130 # the sclass of the ext-net the packet came from
5131 self.assertEqual(rx[VXLAN].gpid, 4220)
5132 # policy was applied to the original IP packet
5133 self.assertTrue(rx[VXLAN].gpflags.A)
5134 # since it's an external host the reciever should not learn it
5135 self.assertTrue(rx[VXLAN].gpflags.D)
5136 inner = rx[VXLAN].payload
5137 self.assertEqual(inner[Ether].dst, "00:0c:0c:0c:0c:0c")
5138 self.assertEqual(inner[IP].src, "10.220.0.1")
5139 self.assertEqual(inner[IP].dst, "10.222.0.1")
5142 # make the external subnet ECMP
5144 vx_tun_r2 = VppVxlanGbpTunnel(
5145 self, self.pg7.local_ip4,
5146 self.pg7.remote_ip4, 446,
5147 mode=(VppEnum.vl_api_vxlan_gbp_api_tunnel_mode_t.
5148 VXLAN_GBP_API_TUNNEL_MODE_L3))
5149 vx_tun_r2.add_vpp_config()
5150 VppIpInterfaceBind(self, vx_tun_r2, t4).add_vpp_config()
5152 self.logger.info(self.vapi.cli("sh vxlan-gbp tunnel"))
5154 n2 = VppNeighbor(self,
5155 vx_tun_r2.sw_if_index,
5156 "00:0c:0c:0c:0c:0c",
5157 self.pg7.remote_ip4)
5160 ip_222.modify([VppRoutePath(self.pg7.remote_ip4,
5161 vx_tun_r1.sw_if_index),
5162 VppRoutePath(self.pg7.remote_ip4,
5163 vx_tun_r2.sw_if_index)])
5166 # now expect load-balance
5168 p = [(Ether(src=eep1.mac, dst=str(self.router_mac)) /
5170 IP(src="10.220.0.1", dst="10.222.0.1") /
5171 UDP(sport=1234, dport=1234) /
5172 Raw(b'\xa5' * 100)),
5173 (Ether(src=eep1.mac, dst=str(self.router_mac)) /
5175 IP(src="10.220.0.1", dst="10.222.0.1") /
5176 UDP(sport=1222, dport=1235) /
5177 Raw(b'\xa5' * 100))]
5179 rxs = self.send_and_expect(self.pg0, p, self.pg7)
5181 self.assertEqual(rxs[0][VXLAN].vni, 445)
5182 self.assertEqual(rxs[1][VXLAN].vni, 446)
5185 # Same LB test for v6
5187 n3 = VppNeighbor(self,
5188 vx_tun_r1.sw_if_index,
5189 "00:0c:0c:0c:0c:0c",
5190 self.pg7.remote_ip6)
5192 n4 = VppNeighbor(self,
5193 vx_tun_r2.sw_if_index,
5194 "00:0c:0c:0c:0c:0c",
5195 self.pg7.remote_ip6)
5198 ip_222_6 = VppIpRoute(self, "10:222::", 64,
5199 [VppRoutePath(self.pg7.remote_ip6,
5200 vx_tun_r1.sw_if_index),
5201 VppRoutePath(self.pg7.remote_ip6,
5202 vx_tun_r2.sw_if_index)],
5203 table_id=t6.table_id)
5204 ip_222_6.add_vpp_config()
5206 l3o_222_6 = VppGbpSubnet(
5207 self, rd1, "10:222::", 64,
5208 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
5210 l3o_222_6.add_vpp_config()
5212 p = [(Ether(src=eep1.mac, dst=str(self.router_mac)) /
5214 IPv6(src="10:220::1", dst="10:222::1") /
5215 UDP(sport=1234, dport=1234) /
5216 Raw(b'\xa5' * 100)),
5217 (Ether(src=eep1.mac, dst=str(self.router_mac)) /
5219 IPv6(src="10:220::1", dst="10:222::1") /
5220 UDP(sport=7777, dport=8881) /
5221 Raw(b'\xa5' * 100))]
5223 self.logger.info(self.vapi.cli("sh ip6 fib 10:222::1"))
5224 rxs = self.send_and_expect(self.pg0, p, self.pg7)
5226 self.assertEqual(rxs[0][VXLAN].vni, 445)
5227 self.assertEqual(rxs[1][VXLAN].vni, 446)
5230 # ping from host in remote to local external subnets
5231 # there's no contract for this, but the A bit is set.
5233 p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
5234 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
5235 UDP(sport=1234, dport=48879) /
5236 VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
5237 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
5238 IP(src="10.222.0.1", dst="10.220.0.1") /
5239 UDP(sport=1234, dport=1234) /
5242 rxs = self.send_and_expect(self.pg7, p * 3, self.pg0)
5243 self.assertFalse(find_gbp_endpoint(self, ip="10.222.0.1"))
5246 # ping from host in remote to remote external subnets
5247 # this is dropped by reflection check.
5249 p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
5250 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
5251 UDP(sport=1234, dport=48879) /
5252 VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
5253 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
5254 IP(src="10.222.0.1", dst="10.222.0.2") /
5255 UDP(sport=1234, dport=1234) /
5258 rxs = self.send_and_assert_no_replies(self.pg7, p * 3)
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 IPv6(src="10:222::1", dst="10:222::2") /
5266 UDP(sport=1234, dport=1234) /
5269 rxs = self.send_and_assert_no_replies(self.pg7, p * 3)
5274 lep1 = VppGbpEndpoint(self, vlan_144,
5276 "10.0.0.44", "11.0.0.44",
5277 "2001:10::44", "3001::44")
5278 lep1.add_vpp_config()
5281 # local EP to local ip4 external subnet
5283 p = (Ether(src=lep1.mac, dst=str(self.router_mac)) /
5285 IP(src=lep1.ip4, dst="10.220.0.1") /
5286 UDP(sport=1234, dport=1234) /
5289 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
5292 self.assertEqual(rx[Ether].src, str(self.router_mac))
5293 self.assertEqual(rx[Ether].dst, eep1.mac)
5294 self.assertEqual(rx[Dot1Q].vlan, 100)
5297 # local EP to local ip6 external subnet
5299 p = (Ether(src=lep1.mac, dst=str(self.router_mac)) /
5301 IPv6(src=lep1.ip6, dst="10:220::1") /
5302 UDP(sport=1234, dport=1234) /
5305 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
5308 self.assertEqual(rx[Ether].src, str(self.router_mac))
5309 self.assertEqual(rx[Ether].dst, eep1.mac)
5310 self.assertEqual(rx[Dot1Q].vlan, 100)
5313 # ip4 and ip6 subnets that load-balance
5315 ip_20 = VppIpRoute(self, "10.20.0.0", 24,
5316 [VppRoutePath(eep1.ip4,
5317 eep1.epg.bvi.sw_if_index),
5318 VppRoutePath(eep2.ip4,
5319 eep2.epg.bvi.sw_if_index)],
5320 table_id=t4.table_id)
5321 ip_20.add_vpp_config()
5323 l3o_20 = VppGbpSubnet(
5324 self, rd1, "10.20.0.0", 24,
5325 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
5327 l3o_20.add_vpp_config()
5329 ip6_20 = VppIpRoute(self, "10:20::", 64,
5330 [VppRoutePath(eep1.ip6,
5331 eep1.epg.bvi.sw_if_index),
5332 VppRoutePath(eep2.ip6,
5333 eep2.epg.bvi.sw_if_index)],
5334 table_id=t6.table_id)
5335 ip6_20.add_vpp_config()
5337 l3o6_20 = VppGbpSubnet(
5338 self, rd1, "10:20::", 64,
5339 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
5341 l3o6_20.add_vpp_config()
5343 self.logger.info(self.vapi.cli("sh ip fib 10.20.0.1"))
5344 self.logger.info(self.vapi.cli("sh ip6 fib 10:20::1"))
5346 # two ip6 packets whose port are chosen so they load-balance
5347 p = [(Ether(src=lep1.mac, dst=str(self.router_mac)) /
5349 IPv6(src=lep1.ip6, dst="10:20::1") /
5350 UDP(sport=1234, dport=1234) /
5351 Raw(b'\xa5' * 100)),
5352 (Ether(src=lep1.mac, dst=str(self.router_mac)) /
5354 IPv6(src=lep1.ip6, dst="10:20::1") /
5355 UDP(sport=124, dport=1230) /
5356 Raw(b'\xa5' * 100))]
5358 rxs = self.send_and_expect(self.pg0, p, self.pg0, 2)
5360 self.assertEqual(rxs[0][Dot1Q].vlan, 101)
5361 self.assertEqual(rxs[1][Dot1Q].vlan, 100)
5363 # two ip4 packets whose port are chosen so they load-balance
5364 p = [(Ether(src=lep1.mac, dst=str(self.router_mac)) /
5366 IP(src=lep1.ip4, dst="10.20.0.1") /
5367 UDP(sport=1235, dport=1235) /
5368 Raw(b'\xa5' * 100)),
5369 (Ether(src=lep1.mac, dst=str(self.router_mac)) /
5371 IP(src=lep1.ip4, dst="10.20.0.1") /
5372 UDP(sport=124, dport=1230) /
5373 Raw(b'\xa5' * 100))]
5375 rxs = self.send_and_expect(self.pg0, p, self.pg0, 2)
5377 self.assertEqual(rxs[0][Dot1Q].vlan, 101)
5378 self.assertEqual(rxs[1][Dot1Q].vlan, 100)
5383 ip_222.remove_vpp_config()
5384 self.pg7.unconfig_ip4()
5385 self.vlan_101.set_vtr(L2_VTR_OP.L2_DISABLED)
5386 self.vlan_100.set_vtr(L2_VTR_OP.L2_DISABLED)
5388 def test_gbp_anon_l3_out(self):
5389 """ GBP Anonymous L3 Out """
5391 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
5392 self.vapi.cli("set logging class gbp level debug")
5394 routed_dst_mac = "00:0c:0c:0c:0c:0c"
5395 routed_src_mac = "00:22:bd:f8:19:ff"
5400 t4 = VppIpTable(self, 1)
5402 t6 = VppIpTable(self, 1, True)
5405 rd1 = VppGbpRouteDomain(self, 2, 55, t4, t6)
5406 rd1.add_vpp_config()
5408 self.loop0.set_mac(self.router_mac)
5411 # Bind the BVI to the RD
5413 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
5414 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
5417 # Pg7 hosts a BD's BUM
5418 # Pg1 some other l3 interface
5420 self.pg7.config_ip4()
5421 self.pg7.resolve_arp()
5424 # a GBP external bridge domains for the EPs
5426 bd1 = VppBridgeDomain(self, 1)
5427 bd1.add_vpp_config()
5428 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0, None, None)
5429 gbd1.add_vpp_config()
5432 # The Endpoint-groups in which the external endpoints exist
5434 epg_220 = VppGbpEndpointGroup(self, 220, 113, rd1, gbd1,
5438 VppGbpEndpointRetention(4))
5439 epg_220.add_vpp_config()
5441 # the BVIs have the subnet applied ...
5442 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 24)
5443 ip4_addr.add_vpp_config()
5445 # ... which is an Anonymous L3-out subnets
5446 l3o_1 = VppGbpSubnet(
5447 self, rd1, "10.0.0.0", 24,
5448 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_ANON_L3_OUT,
5450 l3o_1.add_vpp_config()
5453 # an external interface attached to the outside world and the
5456 VppL2Vtr(self, self.vlan_100, L2_VTR_OP.L2_POP_1).add_vpp_config()
5457 VppL2Vtr(self, self.vlan_101, L2_VTR_OP.L2_POP_1).add_vpp_config()
5460 # vlan_100 and vlan_101 are anonymous l3-out interfaces
5462 ext_itf = VppGbpExtItf(self, self.vlan_100, bd1, rd1, anon=True)
5463 ext_itf.add_vpp_config()
5464 ext_itf = VppGbpExtItf(self, self.vlan_101, bd1, rd1, anon=True)
5465 ext_itf.add_vpp_config()
5468 # an unicast vxlan-gbp for inter-RD traffic
5470 vx_tun_l3 = VppGbpVxlanTunnel(
5471 self, 444, rd1.rd_id,
5472 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
5474 vx_tun_l3.add_vpp_config()
5477 # A remote external endpoint
5479 rep = VppGbpEndpoint(self, vx_tun_l3,
5481 "10.0.0.201", "11.0.0.201",
5482 "2001:10::201", "3001::101",
5483 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
5485 self.pg7.remote_ip4,
5487 rep.add_vpp_config()
5490 # ARP packet from host in external subnet are accepted, flooded and
5491 # replied to. We expect 2 packets:
5492 # - APR request flooded over the other vlan subif
5493 # - ARP reply from BVI
5495 p_arp = (Ether(src=self.vlan_100.remote_mac,
5496 dst="ff:ff:ff:ff:ff:ff") /
5501 hwsrc=self.vlan_100.remote_mac,
5502 hwdst="ff:ff:ff:ff:ff:ff"))
5503 rxs = self.send_and_expect(self.pg0, p_arp * 1, self.pg0, n_rx=2)
5505 p_arp = (Ether(src=self.vlan_101.remote_mac,
5506 dst="ff:ff:ff:ff:ff:ff") /
5511 hwsrc=self.vlan_101.remote_mac,
5512 hwdst="ff:ff:ff:ff:ff:ff"))
5513 rxs = self.send_and_expect(self.pg0, p_arp * 1, self.pg0, n_rx=2)
5516 # remote to external
5518 p = (Ether(src=self.pg7.remote_mac,
5519 dst=self.pg7.local_mac) /
5520 IP(src=self.pg7.remote_ip4,
5521 dst=self.pg7.local_ip4) /
5522 UDP(sport=1234, dport=48879) /
5523 VXLAN(vni=vx_tun_l3.vni, gpid=epg_220.sclass, flags=0x88) /
5524 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
5525 IP(src=str(rep.ip4), dst="10.0.0.100") /
5526 UDP(sport=1234, dport=1234) /
5528 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
5531 # local EP pings router
5533 p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
5535 IP(src="10.0.0.100", dst="10.0.0.128") /
5536 ICMP(type='echo-request'))
5537 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
5540 self.assertEqual(rx[Ether].src, str(self.router_mac))
5541 self.assertEqual(rx[Ether].dst, self.vlan_100.remote_mac)
5542 self.assertEqual(rx[Dot1Q].vlan, 100)
5545 # local EP pings other local EP
5547 p = (Ether(src=self.vlan_100.remote_mac,
5548 dst=self.vlan_101.remote_mac) /
5550 IP(src="10.0.0.100", dst="10.0.0.101") /
5551 ICMP(type='echo-request'))
5552 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
5555 self.assertEqual(rx[Ether].src, self.vlan_100.remote_mac)
5556 self.assertEqual(rx[Ether].dst, self.vlan_101.remote_mac)
5557 self.assertEqual(rx[Dot1Q].vlan, 101)
5560 # A subnet reachable through an external router on vlan 100
5562 ip_220 = VppIpRoute(self, "10.220.0.0", 24,
5563 [VppRoutePath("10.0.0.100",
5564 epg_220.bvi.sw_if_index)],
5565 table_id=t4.table_id)
5566 ip_220.add_vpp_config()
5568 l3o_220 = VppGbpSubnet(
5569 self, rd1, "10.220.0.0", 24,
5570 # note: this a "regular" L3 out subnet (not connected)
5571 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
5573 l3o_220.add_vpp_config()
5576 # A subnet reachable through an external router on vlan 101
5578 ip_221 = VppIpRoute(self, "10.221.0.0", 24,
5579 [VppRoutePath("10.0.0.101",
5580 epg_220.bvi.sw_if_index)],
5581 table_id=t4.table_id)
5582 ip_221.add_vpp_config()
5584 l3o_221 = VppGbpSubnet(
5585 self, rd1, "10.221.0.0", 24,
5586 # note: this a "regular" L3 out subnet (not connected)
5587 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
5589 l3o_221.add_vpp_config()
5592 # ping between hosts in remote subnets
5593 # dropped without a contract
5595 p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
5597 IP(src="10.220.0.1", dst="10.221.0.1") /
5598 ICMP(type='echo-request'))
5600 rxs = self.send_and_assert_no_replies(self.pg0, p * 1)
5603 # contract for the external nets to communicate
5605 rule4 = AclRule(is_permit=1, proto=17)
5606 rule6 = AclRule(src_prefix=IPv6Network((0, 0)),
5607 dst_prefix=IPv6Network((0, 0)), is_permit=1, proto=17)
5608 acl = VppAcl(self, rules=[rule4, rule6])
5609 acl.add_vpp_config()
5611 c1 = VppGbpContract(
5612 self, 55, 4220, 4221, acl.acl_index,
5613 [VppGbpContractRule(
5614 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5615 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5618 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5619 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5621 [ETH_P_IP, ETH_P_IPV6])
5625 # Contracts allowing ext-net 200 to talk with external EPs
5627 c2 = VppGbpContract(
5628 self, 55, 4220, 113, acl.acl_index,
5629 [VppGbpContractRule(
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,
5634 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5635 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5637 [ETH_P_IP, ETH_P_IPV6])
5639 c3 = VppGbpContract(
5640 self, 55, 113, 4220, 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])
5653 # ping between hosts in remote subnets
5655 p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
5657 IP(src="10.220.0.1", dst="10.221.0.1") /
5658 UDP(sport=1234, dport=1234) /
5661 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
5664 self.assertEqual(rx[Ether].src, str(self.router_mac))
5665 self.assertEqual(rx[Ether].dst, self.vlan_101.remote_mac)
5666 self.assertEqual(rx[Dot1Q].vlan, 101)
5668 # we did not learn these external hosts
5669 self.assertFalse(find_gbp_endpoint(self, ip="10.220.0.1"))
5670 self.assertFalse(find_gbp_endpoint(self, ip="10.221.0.1"))
5673 # from remote external EP to local external EP
5675 p = (Ether(src=self.pg7.remote_mac,
5676 dst=self.pg7.local_mac) /
5677 IP(src=self.pg7.remote_ip4,
5678 dst=self.pg7.local_ip4) /
5679 UDP(sport=1234, dport=48879) /
5680 VXLAN(vni=444, gpid=113, flags=0x88) /
5681 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
5682 IP(src=rep.ip4, dst="10.220.0.1") /
5683 UDP(sport=1234, dport=1234) /
5686 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
5689 # ping from an external host to the remote external EP
5691 p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
5693 IP(src="10.220.0.1", dst=rep.ip4) /
5694 UDP(sport=1234, dport=1234) /
5697 rxs = self.send_and_expect(self.pg0, p * 1, self.pg7)
5700 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
5701 # self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
5702 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
5703 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
5704 self.assertEqual(rx[VXLAN].vni, 444)
5705 self.assertTrue(rx[VXLAN].flags.G)
5706 self.assertTrue(rx[VXLAN].flags.Instance)
5707 # the sclass of the ext-net the packet came from
5708 self.assertEqual(rx[VXLAN].gpid, 4220)
5709 # policy was applied to the original IP packet
5710 self.assertTrue(rx[VXLAN].gpflags.A)
5711 # since it's an external host the reciever should not learn it
5712 self.assertTrue(rx[VXLAN].gpflags.D)
5713 inner = rx[VXLAN].payload
5714 self.assertEqual(inner[IP].src, "10.220.0.1")
5715 self.assertEqual(inner[IP].dst, rep.ip4)
5718 # An external subnet reachable via the remote external EP
5722 # first the VXLAN-GBP tunnel over which it is reached
5724 vx_tun_r = VppVxlanGbpTunnel(
5725 self, self.pg7.local_ip4,
5726 self.pg7.remote_ip4, 445,
5727 mode=(VppEnum.vl_api_vxlan_gbp_api_tunnel_mode_t.
5728 VXLAN_GBP_API_TUNNEL_MODE_L3))
5729 vx_tun_r.add_vpp_config()
5730 VppIpInterfaceBind(self, vx_tun_r, t4).add_vpp_config()
5732 self.logger.info(self.vapi.cli("sh vxlan-gbp tunnel"))
5735 # then the special adj to resolve through on that tunnel
5737 n1 = VppNeighbor(self,
5738 vx_tun_r.sw_if_index,
5739 "00:0c:0c:0c:0c:0c",
5740 self.pg7.remote_ip4)
5744 # the route via the adj above
5746 ip_222 = VppIpRoute(self, "10.222.0.0", 24,
5747 [VppRoutePath(self.pg7.remote_ip4,
5748 vx_tun_r.sw_if_index)],
5749 table_id=t4.table_id)
5750 ip_222.add_vpp_config()
5752 l3o_222 = VppGbpSubnet(
5753 self, rd1, "10.222.0.0", 24,
5754 # note: this a "regular" l3out subnet (not connected)
5755 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
5757 l3o_222.add_vpp_config()
5760 # ping between hosts in local and remote external subnets
5761 # dropped without a contract
5763 p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
5765 IP(src="10.220.0.1", dst="10.222.0.1") /
5766 UDP(sport=1234, dport=1234) /
5769 rxs = self.send_and_assert_no_replies(self.pg0, p * 1)
5772 # Add contracts ext-nets for 220 -> 222
5774 c4 = VppGbpContract(
5775 self, 55, 4220, 4222, acl.acl_index,
5776 [VppGbpContractRule(
5777 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5778 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5781 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5782 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5784 [ETH_P_IP, ETH_P_IPV6])
5788 # ping from host in local to remote external subnets
5790 p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
5792 IP(src="10.220.0.1", dst="10.222.0.1") /
5793 UDP(sport=1234, dport=1234) /
5796 rxs = self.send_and_expect(self.pg0, p * 3, self.pg7)
5799 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
5800 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
5801 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
5802 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
5803 self.assertEqual(rx[VXLAN].vni, 445)
5804 self.assertTrue(rx[VXLAN].flags.G)
5805 self.assertTrue(rx[VXLAN].flags.Instance)
5806 # the sclass of the ext-net the packet came from
5807 self.assertEqual(rx[VXLAN].gpid, 4220)
5808 # policy was applied to the original IP packet
5809 self.assertTrue(rx[VXLAN].gpflags.A)
5810 # since it's an external host the reciever should not learn it
5811 self.assertTrue(rx[VXLAN].gpflags.D)
5812 inner = rx[VXLAN].payload
5813 self.assertEqual(inner[Ether].dst, "00:0c:0c:0c:0c:0c")
5814 self.assertEqual(inner[IP].src, "10.220.0.1")
5815 self.assertEqual(inner[IP].dst, "10.222.0.1")
5818 # ping from host in remote to local external subnets
5819 # there's no contract for this, but the A bit is set.
5821 p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
5822 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
5823 UDP(sport=1234, dport=48879) /
5824 VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
5825 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
5826 IP(src="10.222.0.1", dst="10.220.0.1") /
5827 UDP(sport=1234, dport=1234) /
5830 rxs = self.send_and_expect(self.pg7, p * 3, self.pg0)
5831 self.assertFalse(find_gbp_endpoint(self, ip="10.222.0.1"))
5834 # ping from host in remote to remote external subnets
5835 # this is dropped by reflection check.
5837 p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
5838 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
5839 UDP(sport=1234, dport=48879) /
5840 VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
5841 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
5842 IP(src="10.222.0.1", dst="10.222.0.2") /
5843 UDP(sport=1234, dport=1234) /
5846 rxs = self.send_and_assert_no_replies(self.pg7, p * 3)
5851 self.vlan_101.set_vtr(L2_VTR_OP.L2_DISABLED)
5852 self.vlan_100.set_vtr(L2_VTR_OP.L2_DISABLED)
5853 self.pg7.unconfig_ip4()
5854 # make sure the programmed EP is no longer learnt from DP
5855 self.wait_for_ep_timeout(sw_if_index=rep.itf.sw_if_index, ip=rep.ip4)
5858 if __name__ == '__main__':
5859 unittest.main(testRunner=VppTestRunner)