3 from socket import 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 (
17 from scapy.utils6 import in6_getnsma, in6_getnsmac
18 from scapy.layers.vxlan import VXLAN
19 from scapy.data import ETH_P_IP, ETH_P_IPV6
21 from framework import tag_fixme_vpp_workers
22 from framework import VppTestCase, VppTestRunner
23 from vpp_object import VppObject
24 from vpp_interface import VppInterface
25 from vpp_ip_route import (
29 VppIpInterfaceAddress,
38 VppBridgeDomainArpEntry,
40 find_bridge_domain_port,
43 from vpp_sub_interface import L2_VTR_OP, VppDot1QSubint
44 from vpp_ip import DpoProto, get_dpo_proto
45 from vpp_papi import VppEnum, MACAddress
46 from vpp_vxlan_gbp_tunnel import find_vxlan_gbp_tunnel, INDEX_INVALID, VppVxlanGbpTunnel
47 from vpp_neighbor import VppNeighbor
48 from vpp_acl import AclRule, VppAcl
53 def find_gbp_endpoint(
54 test, sw_if_index=None, ip=None, mac=None, tep=None, sclass=None, flags=None
59 vmac = MACAddress(mac)
61 eps = test.vapi.gbp_endpoint_dump()
67 if src != str(ep.endpoint.tun.src) or dst != str(ep.endpoint.tun.dst):
70 if ep.endpoint.sw_if_index != sw_if_index:
73 if ep.endpoint.sclass != sclass:
76 if flags != (flags & ep.endpoint.flags):
79 for eip in ep.endpoint.ips:
83 if vmac == ep.endpoint.mac:
89 def find_gbp_vxlan(test: VppTestCase, vni):
90 ts = test.vapi.gbp_vxlan_tunnel_dump()
92 if t.tunnel.vni == vni:
97 class VppGbpEndpoint(VppObject):
104 return str(self.vmac)
124 return [self.ip4, self.ip6]
128 return [self.fip4, self.fip6]
157 self.vmac = MACAddress(self.itf.remote_mac)
159 self.vmac = MACAddress("00:00:00:00:00:00")
162 self.tun_src = tun_src
163 self.tun_dst = tun_dst
166 ips = [self.ip4, self.ip6]
168 "sw_if_index": self.itf.sw_if_index,
171 "mac": self.vmac.packed,
172 "sclass": self.epg.sclass,
180 def add_vpp_config(self):
181 res = self._test.vapi.gbp_endpoint_add(
182 endpoint=self.encode(),
184 self.handle = res.handle
185 self._test.registry.register(self, self._test.logger)
187 def remove_vpp_config(self):
188 self._test.vapi.gbp_endpoint_del(handle=self.handle)
191 return "gbp-endpoint:[%d==%d:%s:%d]" % (
193 self.itf.sw_if_index,
198 def query_vpp_config(self):
199 return find_gbp_endpoint(self._test, self.itf.sw_if_index, self.ip4)
202 class VppGbpRecirc(VppObject):
204 GBP Recirculation Interface
207 def __init__(self, test, epg, recirc, is_ext=False):
215 "is_ext": self.is_ext,
216 "sw_if_index": self.recirc.sw_if_index,
217 "sclass": self.epg.sclass,
220 def add_vpp_config(self):
221 self._test.vapi.gbp_recirc_add_del(
223 recirc=self.encode(),
225 self._test.registry.register(self, self._test.logger)
227 def remove_vpp_config(self):
228 self._test.vapi.gbp_recirc_add_del(
230 recirc=self.encode(),
234 return "gbp-recirc:[%d]" % (self.recirc.sw_if_index)
236 def query_vpp_config(self):
237 rs = self._test.vapi.gbp_recirc_dump()
239 if r.recirc.sw_if_index == self.recirc.sw_if_index:
244 class VppGbpExtItf(VppObject):
246 GBP ExtItfulation Interface
249 def __init__(self, test, itf, bd, rd, anon=False):
254 self.flags = 1 if anon else 0
258 "sw_if_index": self.itf.sw_if_index,
259 "bd_id": self.bd.bd_id,
260 "rd_id": self.rd.rd_id,
264 def add_vpp_config(self):
265 self._test.vapi.gbp_ext_itf_add_del(
267 ext_itf=self.encode(),
269 self._test.registry.register(self, self._test.logger)
271 def remove_vpp_config(self):
272 self._test.vapi.gbp_ext_itf_add_del(
274 ext_itf=self.encode(),
278 return "gbp-ext-itf:[%d]%s" % (
279 self.itf.sw_if_index,
280 " [anon]" if self.flags else "",
283 def query_vpp_config(self):
284 rs = self._test.vapi.gbp_ext_itf_dump()
286 if r.ext_itf.sw_if_index == self.itf.sw_if_index:
291 class VppGbpSubnet(VppObject):
303 sw_if_index=0xFFFFFFFF,
306 # TODO: replace hardcoded defaults when vpp_papi supports
307 # defaults in typedefs
309 self.rd_id = rd.rd_id
310 a = ip_address(address)
312 self.prefix = IPv4Network("%s/%d" % (address, address_len), strict=False)
314 self.prefix = IPv6Network("%s/%d" % (address, address_len), strict=False)
316 self.sw_if_index = sw_if_index
322 "sw_if_index": self.sw_if_index,
323 "sclass": self.sclass,
324 "prefix": self.prefix,
328 def add_vpp_config(self):
329 self._test.vapi.gbp_subnet_add_del(
331 subnet=self.encode(),
333 self._test.registry.register(self, self._test.logger)
335 def remove_vpp_config(self):
336 self._test.vapi.gbp_subnet_add_del(is_add=0, subnet=self.encode())
339 return "gbp-subnet:[%d-%s]" % (self.rd_id, self.prefix)
341 def query_vpp_config(self):
342 ss = self._test.vapi.gbp_subnet_dump()
345 s.subnet.rd_id == self.rd_id
346 and s.subnet.type == self.type
347 and s.subnet.prefix == self.prefix
353 class VppGbpEndpointRetention(object):
354 def __init__(self, remote_ep_timeout=0xFFFFFFFF):
355 self.remote_ep_timeout = remote_ep_timeout
358 return {"remote_ep_timeout": self.remote_ep_timeout}
361 class VppGbpEndpointGroup(VppObject):
377 retention=VppGbpEndpointRetention(),
382 self.bvi_ip4 = bvi_ip4
383 self.bvi_ip6 = bvi_ip6
385 self.bd = bd # VppGbpBridgeDomain
390 self.retention = retention
392 def encode(self) -> dict:
394 "uplink_sw_if_index": self.uplink.sw_if_index
397 "bd_id": self.bd.bd.bd_id,
398 "rd_id": self.rd.rd_id,
400 "sclass": self.sclass,
401 "retention": self.retention.encode(),
404 def add_vpp_config(self):
405 self._test.vapi.gbp_endpoint_group_add(epg=self.encode())
406 self._test.registry.register(self, self._test.logger)
408 def remove_vpp_config(self):
409 self._test.vapi.gbp_endpoint_group_del(sclass=self.sclass)
411 def object_id(self) -> str:
412 return "gbp-endpoint-group:[%d]" % (self.vnid)
414 def query_vpp_config(self) -> bool:
415 epgs = self._test.vapi.gbp_endpoint_group_dump()
417 if epg.epg.vnid == self.vnid:
422 class VppGbpBridgeDomain(VppObject):
433 uu_fwd: typing.Optional[VppVxlanGbpTunnel] = None,
443 self.bm_flood = bm_flood
447 e = VppEnum.vl_api_gbp_bridge_domain_flags_t
449 self.flags = e.GBP_BD_API_FLAG_NONE
451 self.flags |= e.GBP_BD_API_FLAG_DO_NOT_LEARN
453 self.flags |= e.GBP_BD_API_FLAG_UU_FWD_DROP
455 self.flags |= e.GBP_BD_API_FLAG_MCAST_DROP
457 self.flags |= e.GBP_BD_API_FLAG_UCAST_ARP
459 def encode(self) -> dict:
462 "bvi_sw_if_index": self.bvi.sw_if_index,
463 "uu_fwd_sw_if_index": self.uu_fwd.sw_if_index
466 "bm_flood_sw_if_index": self.bm_flood.sw_if_index
469 "bd_id": self.bd.bd_id,
470 "rd_id": self.rd.rd_id,
473 def add_vpp_config(self):
474 self._test.vapi.gbp_bridge_domain_add(
477 self._test.registry.register(self, self._test.logger)
479 def remove_vpp_config(self):
480 self._test.vapi.gbp_bridge_domain_del(bd_id=self.bd.bd_id)
482 def object_id(self) -> str:
483 return "gbp-bridge-domain:[%d]" % (self.bd.bd_id)
485 def query_vpp_config(self) -> bool:
486 bds = self._test.vapi.gbp_bridge_domain_dump()
488 if bd.bd.bd_id == self.bd.bd_id:
493 class VppGbpRouteDomain(VppObject):
498 def __init__(self, test, rd_id, scope, t4, t6, ip4_uu=None, ip6_uu=None):
507 def encode(self) -> dict:
511 "ip4_table_id": self.t4.table_id,
512 "ip6_table_id": self.t6.table_id,
513 "ip4_uu_sw_if_index": self.ip4_uu.sw_if_index
516 "ip6_uu_sw_if_index": self.ip6_uu.sw_if_index
521 def add_vpp_config(self):
522 self._test.vapi.gbp_route_domain_add(
525 self._test.registry.register(self, self._test.logger)
527 def remove_vpp_config(self):
528 self._test.vapi.gbp_route_domain_del(rd_id=self.rd_id)
531 return "gbp-route-domain:[%d]" % (self.rd_id)
533 def query_vpp_config(self):
534 rds = self._test.vapi.gbp_route_domain_dump()
536 if rd.rd.rd_id == self.rd_id:
541 class VppGbpContractNextHop:
542 def __init__(self, mac, bd, ip, rd):
548 def encode(self) -> dict:
551 "mac": self.mac.packed,
552 "bd_id": self.bd.bd.bd_id,
553 "rd_id": self.rd.rd_id,
557 class VppGbpContractRule:
558 def __init__(self, action, hash_mode, nhs=None):
560 self.hash_mode = hash_mode
561 self.nhs = [] if nhs is None else nhs
563 def encode(self) -> dict:
566 nhs.append(nh.encode())
570 "action": self.action,
571 "nh_set": {"hash_mode": self.hash_mode, "n_nhs": len(self.nhs), "nhs": nhs},
575 return "<VppGbpContractRule action=%s, hash_mode=%s>" % (
581 class VppGbpContract(VppObject):
594 allowed_ethertypes: list,
598 self.acl_index = acl_index
602 self.allowed_ethertypes = allowed_ethertypes
603 while len(self.allowed_ethertypes) < 16:
604 self.allowed_ethertypes.append(0)
606 def encode(self) -> dict:
609 rules.append(r.encode())
611 "acl_index": self.acl_index,
613 "sclass": self.sclass,
614 "dclass": self.dclass,
615 "n_rules": len(rules),
617 "n_ether_types": len(self.allowed_ethertypes),
618 "allowed_ethertypes": self.allowed_ethertypes,
621 def add_vpp_config(self):
622 r = self._test.vapi.gbp_contract_add_del(is_add=1, contract=self.encode())
624 self.stats_index = r.stats_index
625 self._test.registry.register(self, self._test.logger)
627 def remove_vpp_config(self):
628 self._test.vapi.gbp_contract_add_del(
630 contract=self.encode(),
634 return "gbp-contract:[%d:%d:%d:%d]" % (
641 def query_vpp_config(self):
642 cs = self._test.vapi.gbp_contract_dump()
645 c.contract.scope == self.scope
646 and c.contract.sclass == self.sclass
647 and c.contract.dclass == self.dclass
652 def get_drop_stats(self):
653 c = self._test.statistics.get_counter("/net/gbp/contract/drop")
654 return c[0][self.stats_index]
656 def get_permit_stats(self):
657 c = self._test.statistics.get_counter("/net/gbp/contract/permit")
658 return c[0][self.stats_index]
661 class VppGbpVxlanTunnel(VppInterface):
666 def __init__(self, test, vni, bd_rd_id, mode, src):
667 super(VppGbpVxlanTunnel, self).__init__(test)
670 self.bd_rd_id = bd_rd_id
674 def encode(self) -> dict:
678 "bd_rd_id": self.bd_rd_id,
682 def add_vpp_config(self):
683 r = self._test.vapi.gbp_vxlan_tunnel_add(
684 tunnel=self.encode(),
686 self.set_sw_if_index(r.sw_if_index)
687 self._test.registry.register(self, self._test.logger)
689 def remove_vpp_config(self):
690 self._test.vapi.gbp_vxlan_tunnel_del(vni=self.vni)
693 return "gbp-vxlan:%d" % (self.sw_if_index)
695 def query_vpp_config(self):
696 return find_gbp_vxlan(self._test, self.vni)
699 @tag_fixme_vpp_workers
700 class TestGBP(VppTestCase):
704 def nat_config_flags(self):
705 return VppEnum.vl_api_nat_config_flags_t
708 def nat44_config_flags(self):
709 return VppEnum.vl_api_nat44_config_flags_t
713 super(TestGBP, cls).setUpClass()
716 def tearDownClass(cls):
717 super(TestGBP, cls).tearDownClass()
720 super(TestGBP, self).setUp()
722 self.create_pg_interfaces(range(9))
723 self.create_loopback_interfaces(8)
725 self.router_mac = MACAddress("00:11:22:33:44:55")
727 for i in self.pg_interfaces:
729 for i in self.lo_interfaces:
732 self.vlan_100 = VppDot1QSubint(self, self.pg0, 100)
733 self.vlan_100.admin_up()
734 self.vlan_101 = VppDot1QSubint(self, self.pg0, 101)
735 self.vlan_101.admin_up()
736 self.vlan_102 = VppDot1QSubint(self, self.pg0, 102)
737 self.vlan_102.admin_up()
740 for i in self.pg_interfaces:
742 super(TestGBP, self).tearDown()
743 for i in self.lo_interfaces:
744 i.remove_vpp_config()
745 self.lo_interfaces = []
746 self.vlan_102.remove_vpp_config()
747 self.vlan_101.remove_vpp_config()
748 self.vlan_100.remove_vpp_config()
750 def send_and_expect_bridged(self, src, tx, dst):
751 rx = self.send_and_expect(src, tx, dst)
754 self.assertEqual(r[Ether].src, tx[0][Ether].src)
755 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
756 self.assertEqual(r[IP].src, tx[0][IP].src)
757 self.assertEqual(r[IP].dst, tx[0][IP].dst)
760 def send_and_expect_bridged6(self, src, tx, dst):
761 rx = self.send_and_expect(src, tx, dst)
764 self.assertEqual(r[Ether].src, tx[0][Ether].src)
765 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
766 self.assertEqual(r[IPv6].src, tx[0][IPv6].src)
767 self.assertEqual(r[IPv6].dst, tx[0][IPv6].dst)
770 def send_and_expect_routed(self, src, tx, dst, src_mac):
771 rx = self.send_and_expect(src, tx, dst)
774 self.assertEqual(r[Ether].src, src_mac)
775 self.assertEqual(r[Ether].dst, dst.remote_mac)
776 self.assertEqual(r[IP].src, tx[0][IP].src)
777 self.assertEqual(r[IP].dst, tx[0][IP].dst)
780 def send_and_expect_routed6(self, src, tx, dst, src_mac):
781 rx = self.send_and_expect(src, tx, dst)
784 self.assertEqual(r[Ether].src, src_mac)
785 self.assertEqual(r[Ether].dst, dst.remote_mac)
786 self.assertEqual(r[IPv6].src, tx[0][IPv6].src)
787 self.assertEqual(r[IPv6].dst, tx[0][IPv6].dst)
790 def send_and_expect_natted(self, src, tx, dst, src_ip):
791 rx = self.send_and_expect(src, tx, dst)
794 self.assertEqual(r[Ether].src, tx[0][Ether].src)
795 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
796 self.assertEqual(r[IP].src, src_ip)
797 self.assertEqual(r[IP].dst, tx[0][IP].dst)
800 def send_and_expect_natted6(self, src, tx, dst, src_ip):
801 rx = self.send_and_expect(src, tx, dst)
804 self.assertEqual(r[Ether].src, tx[0][Ether].src)
805 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
806 self.assertEqual(r[IPv6].src, src_ip)
807 self.assertEqual(r[IPv6].dst, tx[0][IPv6].dst)
810 def send_and_expect_unnatted(self, src, tx, dst, dst_ip):
811 rx = self.send_and_expect(src, tx, dst)
814 self.assertEqual(r[Ether].src, tx[0][Ether].src)
815 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
816 self.assertEqual(r[IP].dst, dst_ip)
817 self.assertEqual(r[IP].src, tx[0][IP].src)
820 def send_and_expect_unnatted6(self, src, tx, dst, dst_ip):
821 rx = self.send_and_expect(src, tx, dst)
824 self.assertEqual(r[Ether].src, tx[0][Ether].src)
825 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
826 self.assertEqual(r[IPv6].dst, dst_ip)
827 self.assertEqual(r[IPv6].src, tx[0][IPv6].src)
830 def send_and_expect_double_natted(self, src, tx, dst, src_ip, dst_ip):
831 rx = self.send_and_expect(src, tx, dst)
834 self.assertEqual(r[Ether].src, str(self.router_mac))
835 self.assertEqual(r[Ether].dst, dst.remote_mac)
836 self.assertEqual(r[IP].dst, dst_ip)
837 self.assertEqual(r[IP].src, src_ip)
840 def send_and_expect_double_natted6(self, src, tx, dst, src_ip, dst_ip):
841 rx = self.send_and_expect(src, tx, dst)
844 self.assertEqual(r[Ether].src, str(self.router_mac))
845 self.assertEqual(r[Ether].dst, dst.remote_mac)
846 self.assertEqual(r[IPv6].dst, dst_ip)
847 self.assertEqual(r[IPv6].src, src_ip)
850 def send_and_expect_no_arp(self, src, tx, dst):
851 self.pg_send(src, tx)
852 dst.get_capture(0, timeout=1)
853 dst.assert_nothing_captured(remark="")
855 def send_and_expect_arp(self, src, tx, dst):
856 rx = self.send_and_expect(src, tx, dst)
859 self.assertEqual(r[Ether].src, tx[0][Ether].src)
860 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
861 self.assertEqual(r[ARP].psrc, tx[0][ARP].psrc)
862 self.assertEqual(r[ARP].pdst, tx[0][ARP].pdst)
863 self.assertEqual(r[ARP].hwsrc, tx[0][ARP].hwsrc)
864 self.assertEqual(r[ARP].hwdst, tx[0][ARP].hwdst)
868 """Group Based Policy"""
870 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
875 gt4 = VppIpTable(self, 0)
877 gt6 = VppIpTable(self, 0, is_ip6=True)
879 nt4 = VppIpTable(self, 20)
881 nt6 = VppIpTable(self, 20, is_ip6=True)
884 rd0 = VppGbpRouteDomain(self, 0, 400, gt4, gt6, None, None)
885 rd20 = VppGbpRouteDomain(self, 20, 420, nt4, nt6, None, None)
888 rd20.add_vpp_config()
893 bd1 = VppBridgeDomain(self, 1)
894 bd2 = VppBridgeDomain(self, 2)
895 bd20 = VppBridgeDomain(self, 20)
899 bd20.add_vpp_config()
901 gbd1 = VppGbpBridgeDomain(self, bd1, rd0, self.loop0)
902 gbd2 = VppGbpBridgeDomain(self, bd2, rd0, self.loop1)
903 gbd20 = VppGbpBridgeDomain(self, bd20, rd20, self.loop2)
905 gbd1.add_vpp_config()
906 gbd2.add_vpp_config()
907 gbd20.add_vpp_config()
910 # 3 EPGs, 2 of which share a BD.
911 # 2 NAT EPGs, one for floating-IP subnets, the other for internet
971 VppGbpRecirc(self, epgs[0], self.loop3),
972 VppGbpRecirc(self, epgs[1], self.loop4),
973 VppGbpRecirc(self, epgs[2], self.loop5),
974 VppGbpRecirc(self, epgs[3], self.loop6, is_ext=True),
975 VppGbpRecirc(self, epgs[4], self.loop7, is_ext=True),
979 recirc_nat = recircs[3]
982 # 4 end-points, 2 in the same subnet, 3 in the same BD
1027 self.vapi.nat44_ed_plugin_enable_disable(enable=1)
1028 self.vapi.nat66_plugin_enable_disable(enable=1)
1031 # Config related to each of the EPGs
1034 # IP config on the BVI interfaces
1035 if epg != epgs[1] and epg != epgs[4]:
1036 b4 = VppIpInterfaceBind(self, epg.bvi, epg.rd.t4).add_vpp_config()
1037 b6 = VppIpInterfaceBind(self, epg.bvi, epg.rd.t6).add_vpp_config()
1038 epg.bvi.set_mac(self.router_mac)
1040 # The BVIs are NAT inside interfaces
1041 flags = self.nat_config_flags.NAT_IS_INSIDE
1042 self.vapi.nat44_interface_add_del_feature(
1043 sw_if_index=epg.bvi.sw_if_index, flags=flags, is_add=1
1045 self.vapi.nat66_add_del_interface(
1046 sw_if_index=epg.bvi.sw_if_index, flags=flags, is_add=1
1049 if_ip4 = VppIpInterfaceAddress(
1050 self, epg.bvi, epg.bvi_ip4, 32, bind=b4
1052 if_ip6 = VppIpInterfaceAddress(
1053 self, epg.bvi, epg.bvi_ip6, 128, bind=b6
1056 # EPG uplink interfaces in the RD
1057 VppIpInterfaceBind(self, epg.uplink, epg.rd.t4).add_vpp_config()
1058 VppIpInterfaceBind(self, epg.uplink, epg.rd.t6).add_vpp_config()
1060 # add the BD ARP termination entry for BVI IP
1061 epg.bd_arp_ip4 = VppBridgeDomainArpEntry(
1062 self, epg.bd.bd, str(self.router_mac), epg.bvi_ip4
1064 epg.bd_arp_ip6 = VppBridgeDomainArpEntry(
1065 self, epg.bd.bd, str(self.router_mac), epg.bvi_ip6
1067 epg.bd_arp_ip4.add_vpp_config()
1068 epg.bd_arp_ip6.add_vpp_config()
1071 epg.add_vpp_config()
1073 for recirc in recircs:
1074 # EPG's ingress recirculation interface maps to its RD
1075 VppIpInterfaceBind(self, recirc.recirc, recirc.epg.rd.t4).add_vpp_config()
1076 VppIpInterfaceBind(self, recirc.recirc, recirc.epg.rd.t6).add_vpp_config()
1078 self.vapi.nat44_interface_add_del_feature(
1079 sw_if_index=recirc.recirc.sw_if_index, is_add=1
1081 self.vapi.nat66_add_del_interface(
1082 sw_if_index=recirc.recirc.sw_if_index, is_add=1
1085 recirc.add_vpp_config()
1087 for recirc in recircs:
1089 find_bridge_domain_port(
1090 self, recirc.epg.bd.bd.bd_id, recirc.recirc.sw_if_index
1095 self.pg_enable_capture(self.pg_interfaces)
1098 # routes to the endpoints. We need these since there are no
1099 # adj-fibs due to the fact the the BVI address has /32 and
1100 # the subnet is not attached.
1102 for (ip, fip) in zip(ep.ips, ep.fips):
1103 # Add static mappings for each EP from the 10/8 to 11/8 network
1104 if ip_address(ip).version == 4:
1105 flags = self.nat_config_flags.NAT_IS_ADDR_ONLY
1106 self.vapi.nat44_add_del_static_mapping(
1108 local_ip_address=ip,
1109 external_ip_address=fip,
1110 external_sw_if_index=0xFFFFFFFF,
1115 self.vapi.nat66_add_del_static_mapping(
1116 local_ip_address=ip, external_ip_address=fip, vrf_id=0, is_add=1
1122 self.logger.info(self.vapi.cli("sh gbp endpoint"))
1124 # ... results in a Gratuitous ARP/ND on the EPG's uplink
1125 rx = ep.epg.uplink.get_capture(len(ep.ips) + 1, timeout=0.2)
1127 for ii, ip in enumerate(ep.ips):
1130 if ip_address(ip).version == 6:
1131 self.assertTrue(p.haslayer(ICMPv6ND_NA))
1132 self.assertEqual(p[ICMPv6ND_NA].tgt, ip)
1134 self.assertTrue(p.haslayer(ARP))
1135 self.assertEqual(p[ARP].psrc, ip)
1136 self.assertEqual(p[ARP].pdst, ip)
1138 # add the BD ARP termination entry for floating IP
1140 ba = VppBridgeDomainArpEntry(self, epg_nat.bd.bd, ep.mac, fip)
1143 # floating IPs route via EPG recirc
1147 ip_address(fip).max_prefixlen,
1151 ep.recirc.recirc.sw_if_index,
1152 type=FibPathType.FIB_PATH_TYPE_DVR,
1153 proto=get_dpo_proto(fip),
1160 # L2 FIB entries in the NAT EPG BD to bridge the packets from
1161 # the outside direct to the internal EPG
1162 lf = VppL2FibEntry(self, epg_nat.bd.bd, ep.mac, ep.recirc.recirc, bvi_mac=0)
1166 # ARP packets for unknown IP are sent to the EPG uplink
1168 pkt_arp = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) / ARP(
1170 hwdst="ff:ff:ff:ff:ff:ff",
1171 hwsrc=self.pg0.remote_mac,
1176 self.vapi.cli("clear trace")
1177 self.pg0.add_stream(pkt_arp)
1179 self.pg_enable_capture(self.pg_interfaces)
1182 rxd = epgs[0].uplink.get_capture(1)
1185 # ARP/ND packets get a response
1187 pkt_arp = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) / ARP(
1189 hwdst="ff:ff:ff:ff:ff:ff",
1190 hwsrc=self.pg0.remote_mac,
1191 pdst=epgs[0].bvi_ip4,
1195 self.send_and_expect(self.pg0, [pkt_arp], self.pg0)
1197 nsma = in6_getnsma(inet_pton(AF_INET6, eps[0].ip6))
1198 d = inet_ntop(AF_INET6, nsma)
1200 Ether(dst=in6_getnsmac(nsma), src=self.pg0.remote_mac)
1201 / IPv6(dst=d, src=eps[0].ip6)
1202 / ICMPv6ND_NS(tgt=epgs[0].bvi_ip6)
1203 / ICMPv6NDOptSrcLLAddr(lladdr=self.pg0.remote_mac)
1205 self.send_and_expect(self.pg0, [pkt_nd], self.pg0)
1208 # broadcast packets are flooded
1211 Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac)
1212 / IP(src=eps[0].ip4, dst="232.1.1.1")
1213 / UDP(sport=1234, dport=1234)
1214 / Raw(b"\xa5" * 100)
1217 self.vapi.cli("clear trace")
1218 self.pg0.add_stream(pkt_bcast)
1220 self.pg_enable_capture(self.pg_interfaces)
1223 rxd = eps[1].itf.get_capture(1)
1224 self.assertEqual(rxd[0][Ether].dst, pkt_bcast[Ether].dst)
1225 rxd = epgs[0].uplink.get_capture(1)
1226 self.assertEqual(rxd[0][Ether].dst, pkt_bcast[Ether].dst)
1229 # packets to non-local L3 destinations dropped
1231 pkt_intra_epg_220_ip4 = (
1232 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac))
1233 / IP(src=eps[0].ip4, dst="10.0.0.99")
1234 / UDP(sport=1234, dport=1234)
1235 / Raw(b"\xa5" * 100)
1237 pkt_inter_epg_222_ip4 = (
1238 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac))
1239 / IP(src=eps[0].ip4, dst="10.0.1.99")
1240 / UDP(sport=1234, dport=1234)
1241 / Raw(b"\xa5" * 100)
1244 self.send_and_assert_no_replies(self.pg0, pkt_intra_epg_220_ip4 * NUM_PKTS)
1246 pkt_inter_epg_222_ip6 = (
1247 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac))
1248 / IPv6(src=eps[0].ip6, dst="2001:10::99")
1249 / UDP(sport=1234, dport=1234)
1250 / Raw(b"\xa5" * 100)
1252 self.send_and_assert_no_replies(self.pg0, pkt_inter_epg_222_ip6 * NUM_PKTS)
1255 # Add the subnet routes
1262 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL,
1269 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL,
1276 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL,
1283 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL,
1290 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL,
1297 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL,
1299 s41.add_vpp_config()
1300 s42.add_vpp_config()
1301 s43.add_vpp_config()
1302 s61.add_vpp_config()
1303 s62.add_vpp_config()
1304 s63.add_vpp_config()
1306 self.send_and_expect_bridged(
1307 eps[0].itf, pkt_intra_epg_220_ip4 * NUM_PKTS, eps[0].epg.uplink
1309 self.send_and_expect_bridged(
1310 eps[0].itf, pkt_inter_epg_222_ip4 * NUM_PKTS, eps[0].epg.uplink
1312 self.send_and_expect_bridged6(
1313 eps[0].itf, pkt_inter_epg_222_ip6 * NUM_PKTS, eps[0].epg.uplink
1316 self.logger.info(self.vapi.cli("sh ip fib 11.0.0.2"))
1317 self.logger.info(self.vapi.cli("sh gbp endpoint-group"))
1318 self.logger.info(self.vapi.cli("sh gbp endpoint"))
1319 self.logger.info(self.vapi.cli("sh gbp recirc"))
1320 self.logger.info(self.vapi.cli("sh int"))
1321 self.logger.info(self.vapi.cli("sh int addr"))
1322 self.logger.info(self.vapi.cli("sh int feat loop6"))
1323 self.logger.info(self.vapi.cli("sh vlib graph ip4-gbp-src-classify"))
1324 self.logger.info(self.vapi.cli("sh int feat loop3"))
1325 self.logger.info(self.vapi.cli("sh int feat pg0"))
1328 # Packet destined to unknown unicast is sent on the epg uplink ...
1330 pkt_intra_epg_220_to_uplink = (
1331 Ether(src=self.pg0.remote_mac, dst="00:00:00:33:44:55")
1332 / IP(src=eps[0].ip4, dst="10.0.0.99")
1333 / UDP(sport=1234, dport=1234)
1334 / Raw(b"\xa5" * 100)
1337 self.send_and_expect_bridged(
1338 eps[0].itf, pkt_intra_epg_220_to_uplink * NUM_PKTS, eps[0].epg.uplink
1340 # ... and nowhere else
1341 self.pg1.get_capture(0, timeout=0.1)
1342 self.pg1.assert_nothing_captured(remark="Flood onto other VMS")
1344 pkt_intra_epg_221_to_uplink = (
1345 Ether(src=self.pg2.remote_mac, dst="00:00:00:33:44:66")
1346 / IP(src=eps[0].ip4, dst="10.0.0.99")
1347 / UDP(sport=1234, dport=1234)
1348 / Raw(b"\xa5" * 100)
1351 self.send_and_expect_bridged(
1352 eps[2].itf, pkt_intra_epg_221_to_uplink * NUM_PKTS, eps[2].epg.uplink
1356 # Packets from the uplink are forwarded in the absence of a contract
1358 pkt_intra_epg_220_from_uplink = (
1359 Ether(src="00:00:00:33:44:55", dst=self.pg0.remote_mac)
1360 / IP(src=eps[0].ip4, dst="10.0.0.99")
1361 / UDP(sport=1234, dport=1234)
1362 / Raw(b"\xa5" * 100)
1365 self.send_and_expect_bridged(
1366 self.pg4, pkt_intra_epg_220_from_uplink * NUM_PKTS, self.pg0
1370 # in the absence of policy, endpoints in the same EPG
1374 Ether(src=self.pg0.remote_mac, dst=self.pg1.remote_mac)
1375 / IP(src=eps[0].ip4, dst=eps[1].ip4)
1376 / UDP(sport=1234, dport=1234)
1377 / Raw(b"\xa5" * 100)
1380 self.send_and_expect_bridged(self.pg0, pkt_intra_epg * NUM_PKTS, self.pg1)
1383 # in the absence of policy, endpoints in the different EPG
1384 # cannot communicate
1386 pkt_inter_epg_220_to_221 = (
1387 Ether(src=self.pg0.remote_mac, dst=self.pg2.remote_mac)
1388 / IP(src=eps[0].ip4, dst=eps[2].ip4)
1389 / UDP(sport=1234, dport=1234)
1390 / Raw(b"\xa5" * 100)
1392 pkt_inter_epg_221_to_220 = (
1393 Ether(src=self.pg2.remote_mac, dst=self.pg0.remote_mac)
1394 / IP(src=eps[2].ip4, dst=eps[0].ip4)
1395 / UDP(sport=1234, dport=1234)
1396 / Raw(b"\xa5" * 100)
1398 pkt_inter_epg_220_to_222 = (
1399 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac))
1400 / IP(src=eps[0].ip4, dst=eps[3].ip4)
1401 / UDP(sport=1234, dport=1234)
1402 / Raw(b"\xa5" * 100)
1405 self.send_and_assert_no_replies(eps[0].itf, pkt_inter_epg_220_to_221 * NUM_PKTS)
1406 self.send_and_assert_no_replies(eps[0].itf, pkt_inter_epg_220_to_222 * NUM_PKTS)
1409 # A uni-directional contract from EPG 220 -> 221
1411 rule = AclRule(is_permit=1, proto=17)
1413 src_prefix=IPv6Network((0, 0)),
1414 dst_prefix=IPv6Network((0, 0)),
1418 acl = VppAcl(self, rules=[rule, rule2])
1419 acl.add_vpp_config()
1421 c1 = VppGbpContract(
1429 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1430 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1434 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1435 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1439 [ETH_P_IP, ETH_P_IPV6],
1443 self.send_and_expect_bridged(
1444 eps[0].itf, pkt_inter_epg_220_to_221 * NUM_PKTS, eps[2].itf
1446 self.send_and_assert_no_replies(eps[0].itf, pkt_inter_epg_220_to_222 * NUM_PKTS)
1449 # contract for the return direction
1451 c2 = VppGbpContract(
1459 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1460 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1464 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1465 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1469 [ETH_P_IP, ETH_P_IPV6],
1473 self.send_and_expect_bridged(
1474 eps[0].itf, pkt_inter_epg_220_to_221 * NUM_PKTS, eps[2].itf
1476 self.send_and_expect_bridged(
1477 eps[2].itf, pkt_inter_epg_221_to_220 * NUM_PKTS, eps[0].itf
1480 ds = c2.get_drop_stats()
1481 self.assertEqual(ds["packets"], 0)
1482 ps = c2.get_permit_stats()
1483 self.assertEqual(ps["packets"], NUM_PKTS)
1486 # the contract does not allow non-IP
1488 pkt_non_ip_inter_epg_220_to_221 = (
1489 Ether(src=self.pg0.remote_mac, dst=self.pg2.remote_mac) / ARP()
1491 self.send_and_assert_no_replies(
1492 eps[0].itf, pkt_non_ip_inter_epg_220_to_221 * 17
1496 # check that inter group is still disabled for the groups
1497 # not in the contract.
1499 self.send_and_assert_no_replies(eps[0].itf, pkt_inter_epg_220_to_222 * NUM_PKTS)
1502 # A uni-directional contract from EPG 220 -> 222 'L3 routed'
1504 c3 = VppGbpContract(
1512 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1513 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1517 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1518 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1522 [ETH_P_IP, ETH_P_IPV6],
1526 self.logger.info(self.vapi.cli("sh gbp contract"))
1528 self.send_and_expect_routed(
1530 pkt_inter_epg_220_to_222 * NUM_PKTS,
1532 str(self.router_mac),
1535 # remove both contracts, traffic stops in both directions
1537 c2.remove_vpp_config()
1538 c1.remove_vpp_config()
1539 c3.remove_vpp_config()
1540 acl.remove_vpp_config()
1542 self.send_and_assert_no_replies(eps[2].itf, pkt_inter_epg_221_to_220 * NUM_PKTS)
1543 self.send_and_assert_no_replies(eps[0].itf, pkt_inter_epg_220_to_221 * NUM_PKTS)
1544 self.send_and_expect_bridged(eps[0].itf, pkt_intra_epg * NUM_PKTS, eps[1].itf)
1547 # EPs to the outside world
1550 # in the EP's RD an external subnet via the NAT EPG's recirc
1556 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1557 sw_if_index=recirc_nat.recirc.sw_if_index,
1558 sclass=epg_nat.sclass,
1565 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1566 sw_if_index=recirc_nat.recirc.sw_if_index,
1567 sclass=epg_nat.sclass,
1569 se16 = VppGbpSubnet(
1574 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1575 sw_if_index=recirc_nat.recirc.sw_if_index,
1576 sclass=epg_nat.sclass,
1578 # in the NAT RD an external subnet via the NAT EPG's uplink
1584 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1585 sw_if_index=epg_nat.uplink.sw_if_index,
1586 sclass=epg_nat.sclass,
1588 se36 = VppGbpSubnet(
1593 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1594 sw_if_index=epg_nat.uplink.sw_if_index,
1595 sclass=epg_nat.sclass,
1602 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1603 sw_if_index=epg_nat.uplink.sw_if_index,
1604 sclass=epg_nat.sclass,
1606 se1.add_vpp_config()
1607 se2.add_vpp_config()
1608 se16.add_vpp_config()
1609 se3.add_vpp_config()
1610 se36.add_vpp_config()
1611 se4.add_vpp_config()
1613 self.logger.info(self.vapi.cli("sh ip fib 0.0.0.0/0"))
1614 self.logger.info(self.vapi.cli("sh ip fib 11.0.0.1"))
1615 self.logger.info(self.vapi.cli("sh ip6 fib ::/0"))
1616 self.logger.info(self.vapi.cli("sh ip6 fib %s" % eps[0].fip6))
1619 # From an EP to an outside address: IN2OUT
1621 pkt_inter_epg_220_to_global = (
1622 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac))
1623 / IP(src=eps[0].ip4, dst="1.1.1.1")
1624 / UDP(sport=1234, dport=1234)
1625 / Raw(b"\xa5" * 100)
1629 self.send_and_assert_no_replies(
1630 eps[0].itf, pkt_inter_epg_220_to_global * NUM_PKTS
1632 rule = AclRule(is_permit=1, proto=17, ports=1234)
1637 src_prefix=IPv6Network((0, 0)),
1638 dst_prefix=IPv6Network((0, 0)),
1640 acl2 = VppAcl(self, rules=[rule, rule2])
1641 acl2.add_vpp_config()
1643 c4 = VppGbpContract(
1651 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1652 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1656 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1657 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1661 [ETH_P_IP, ETH_P_IPV6],
1665 self.send_and_expect_natted(
1666 eps[0].itf, pkt_inter_epg_220_to_global * NUM_PKTS, self.pg7, eps[0].fip4
1669 pkt_inter_epg_220_to_global = (
1670 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac))
1671 / IPv6(src=eps[0].ip6, dst="6001::1")
1672 / UDP(sport=1234, dport=1234)
1673 / Raw(b"\xa5" * 100)
1676 self.send_and_expect_natted6(
1677 self.pg0, pkt_inter_epg_220_to_global * NUM_PKTS, self.pg7, eps[0].fip6
1680 # From a global address to an EP: OUT2IN
1682 pkt_inter_epg_220_from_global = (
1683 Ether(src=str(self.router_mac), dst=self.pg0.remote_mac)
1684 / IP(dst=eps[0].fip4, src="1.1.1.1")
1685 / UDP(sport=1234, dport=1234)
1686 / Raw(b"\xa5" * 100)
1689 self.send_and_assert_no_replies(
1690 self.pg7, pkt_inter_epg_220_from_global * NUM_PKTS
1693 c5 = VppGbpContract(
1701 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1702 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1706 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1707 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1711 [ETH_P_IP, ETH_P_IPV6],
1715 self.send_and_expect_unnatted(
1716 self.pg7, pkt_inter_epg_220_from_global * NUM_PKTS, eps[0].itf, eps[0].ip4
1719 pkt_inter_epg_220_from_global = (
1720 Ether(src=str(self.router_mac), dst=self.pg0.remote_mac)
1721 / IPv6(dst=eps[0].fip6, src="6001::1")
1722 / UDP(sport=1234, dport=1234)
1723 / Raw(b"\xa5" * 100)
1726 self.send_and_expect_unnatted6(
1727 self.pg7, pkt_inter_epg_220_from_global * NUM_PKTS, eps[0].itf, eps[0].ip6
1731 # From a local VM to another local VM using resp. public addresses:
1734 pkt_intra_epg_220_global = (
1735 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac))
1736 / IP(src=eps[0].ip4, dst=eps[1].fip4)
1737 / UDP(sport=1234, dport=1234)
1738 / Raw(b"\xa5" * 100)
1741 self.send_and_expect_double_natted(
1743 pkt_intra_epg_220_global * NUM_PKTS,
1749 pkt_intra_epg_220_global = (
1750 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac))
1751 / IPv6(src=eps[0].ip6, dst=eps[1].fip6)
1752 / UDP(sport=1234, dport=1234)
1753 / Raw(b"\xa5" * 100)
1756 self.send_and_expect_double_natted6(
1758 pkt_intra_epg_220_global * NUM_PKTS,
1767 self.vapi.nat44_ed_plugin_enable_disable(enable=0)
1768 self.vapi.nat66_plugin_enable_disable(enable=0)
1770 def wait_for_ep_timeout(
1771 self, sw_if_index=None, ip=None, mac=None, tep=None, n_tries=100, s_time=1
1773 # only learnt EP can timeout
1774 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
1775 flags = ep_flags.GBP_API_ENDPOINT_FLAG_LEARNT
1777 if not find_gbp_endpoint(self, sw_if_index, ip, mac, tep=tep, flags=flags):
1779 n_tries = n_tries - 1
1782 find_gbp_endpoint(self, sw_if_index, ip, mac, tep=tep, flags=flags)
1786 def test_gbp_learn_l2(self):
1787 """GBP L2 Endpoint Learning"""
1789 drop_no_contract = self.statistics.get_err_counter(
1790 "/err/gbp-policy-port/drop-no-contract"
1792 allow_intra_class = self.statistics.get_err_counter(
1793 "/err/gbp-policy-port/allow-intra-sclass"
1796 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
1798 {"mac": "00:00:11:11:11:01", "ip": "10.0.0.1", "ip6": "2001:10::2"},
1799 {"mac": "00:00:11:11:11:02", "ip": "10.0.0.2", "ip6": "2001:10::3"},
1805 gt4 = VppIpTable(self, 1)
1806 gt4.add_vpp_config()
1807 gt6 = VppIpTable(self, 1, is_ip6=True)
1808 gt6.add_vpp_config()
1810 rd1 = VppGbpRouteDomain(self, 1, 401, gt4, gt6)
1811 rd1.add_vpp_config()
1814 # Pg2 hosts the vxlan tunnel, hosts on pg2 to act as TEPs
1815 # Pg3 hosts the IP4 UU-flood VXLAN tunnel
1816 # Pg4 hosts the IP6 UU-flood VXLAN tunnel
1818 self.pg2.config_ip4()
1819 self.pg2.resolve_arp()
1820 self.pg2.generate_remote_hosts(4)
1821 self.pg2.configure_ipv4_neighbors()
1822 self.pg3.config_ip4()
1823 self.pg3.resolve_arp()
1824 self.pg4.config_ip4()
1825 self.pg4.resolve_arp()
1828 # Add a mcast destination VXLAN-GBP tunnel for B&M traffic
1830 tun_bm = VppVxlanGbpTunnel(
1831 self, self.pg4.local_ip4, "239.1.1.1", 88, mcast_itf=self.pg4
1833 tun_bm.add_vpp_config()
1836 # a GBP bridge domain with a BVI and a UU-flood interface
1838 bd1 = VppBridgeDomain(self, 1)
1839 bd1.add_vpp_config()
1840 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0, self.pg3, tun_bm)
1841 gbd1.add_vpp_config()
1843 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1844 self.logger.info(self.vapi.cli("sh gbp bridge"))
1846 # ... and has a /32 applied
1847 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
1848 ip_addr.add_vpp_config()
1851 # The Endpoint-group in which we are learning endpoints
1853 epg_220 = VppGbpEndpointGroup(
1863 VppGbpEndpointRetention(4),
1865 epg_220.add_vpp_config()
1866 epg_330 = VppGbpEndpointGroup(
1876 VppGbpEndpointRetention(4),
1878 epg_330.add_vpp_config()
1881 # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
1884 vx_tun_l2_1 = VppGbpVxlanTunnel(
1888 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L2,
1891 vx_tun_l2_1.add_vpp_config()
1894 # A static endpoint that the learnt endpoints are trying to
1897 ep = VppGbpEndpoint(
1909 self.assertTrue(find_route(self, ep.ip4, 32, table_id=1))
1911 # a packet with an sclass from an unknown EPG
1913 Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac)
1914 / IP(src=self.pg2.remote_hosts[0].ip4, dst=self.pg2.local_ip4)
1915 / UDP(sport=1234, dport=48879)
1916 / VXLAN(vni=99, gpid=88, flags=0x88)
1917 / Ether(src=learnt[0]["mac"], dst=ep.mac)
1918 / IP(src=learnt[0]["ip"], dst=ep.ip4)
1919 / UDP(sport=1234, dport=1234)
1920 / Raw(b"\xa5" * 100)
1923 self.send_and_assert_no_replies(self.pg2, p)
1925 self.logger.info(self.vapi.cli("sh error"))
1926 self.assert_error_counter_equal(
1927 "/err/gbp-policy-port/drop-no-contract", drop_no_contract + 1
1931 # we should not have learnt a new tunnel endpoint, since
1932 # the EPG was not learnt.
1936 find_vxlan_gbp_tunnel(
1937 self, self.pg2.local_ip4, self.pg2.remote_hosts[0].ip4, 99
1941 # ep is not learnt, because the EPG is unknown
1942 self.assertEqual(len(self.vapi.gbp_endpoint_dump()), 1)
1945 # Learn new EPs from IP packets
1947 for ii, l in enumerate(learnt):
1948 # a packet with an sclass from a known EPG
1949 # arriving on an unknown TEP
1951 Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac)
1952 / IP(src=self.pg2.remote_hosts[1].ip4, dst=self.pg2.local_ip4)
1953 / UDP(sport=1234, dport=48879)
1954 / VXLAN(vni=99, gpid=112, flags=0x88)
1955 / Ether(src=l["mac"], dst=ep.mac)
1956 / IP(src=l["ip"], dst=ep.ip4)
1957 / UDP(sport=1234, dport=1234)
1958 / Raw(b"\xa5" * 100)
1961 rx = self.send_and_expect(self.pg2, [p], self.pg0)
1964 tep1_sw_if_index = find_vxlan_gbp_tunnel(
1965 self, self.pg2.local_ip4, self.pg2.remote_hosts[1].ip4, 99
1967 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
1970 # the EP is learnt via the learnt TEP
1971 # both from its MAC and its IP
1974 find_gbp_endpoint(self, vx_tun_l2_1.sw_if_index, mac=l["mac"])
1977 find_gbp_endpoint(self, vx_tun_l2_1.sw_if_index, ip=l["ip"])
1980 self.assert_error_counter_equal(
1981 "/err/gbp-policy-port/allow-intra-sclass", allow_intra_class + 2
1984 self.logger.info(self.vapi.cli("show gbp endpoint"))
1985 self.logger.info(self.vapi.cli("show gbp vxlan"))
1986 self.logger.info(self.vapi.cli("show ip mfib"))
1989 # If we sleep for the threshold time, the learnt endpoints should
1993 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index, mac=l["mac"])
1996 # Learn new EPs from GARP packets received on the BD's mcast tunnel
1998 for ii, l in enumerate(learnt):
1999 # add some junk in the reserved field of the vxlan-header
2000 # next to the VNI. we should accept since reserved bits are
2003 Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac)
2004 / IP(src=self.pg2.remote_hosts[1].ip4, dst="239.1.1.1")
2005 / UDP(sport=1234, dport=48879)
2006 / VXLAN(vni=88, reserved2=0x80, gpid=112, flags=0x88)
2007 / Ether(src=l["mac"], dst="ff:ff:ff:ff:ff:ff")
2013 hwdst="ff:ff:ff:ff:ff:ff",
2017 rx = self.send_and_expect(self.pg4, [p], self.pg0)
2020 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2021 self, self.pg2.local_ip4, self.pg2.remote_hosts[1].ip4, 99
2023 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2026 # the EP is learnt via the learnt TEP
2027 # both from its MAC and its IP
2030 find_gbp_endpoint(self, vx_tun_l2_1.sw_if_index, mac=l["mac"])
2033 find_gbp_endpoint(self, vx_tun_l2_1.sw_if_index, ip=l["ip"])
2037 # wait for the learnt endpoints to age out
2040 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index, mac=l["mac"])
2043 # Learn new EPs from L2 packets
2045 for ii, l in enumerate(learnt):
2046 # a packet with an sclass from a known EPG
2047 # arriving on an unknown TEP
2049 Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac)
2050 / IP(src=self.pg2.remote_hosts[1].ip4, dst=self.pg2.local_ip4)
2051 / UDP(sport=1234, dport=48879)
2052 / VXLAN(vni=99, gpid=112, flags=0x88)
2053 / Ether(src=l["mac"], dst=ep.mac)
2054 / Raw(b"\xa5" * 100)
2057 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2060 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2061 self, self.pg2.local_ip4, self.pg2.remote_hosts[1].ip4, 99
2063 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2066 # the EP is learnt via the learnt TEP
2067 # both from its MAC and its IP
2070 find_gbp_endpoint(self, vx_tun_l2_1.sw_if_index, mac=l["mac"])
2073 self.logger.info(self.vapi.cli("show gbp endpoint"))
2074 self.logger.info(self.vapi.cli("show gbp vxlan"))
2075 self.logger.info(self.vapi.cli("show vxlan-gbp tunnel"))
2078 # wait for the learnt endpoints to age out
2081 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index, mac=l["mac"])
2084 # repeat. the do not learn bit is set so the EPs are not learnt
2087 # a packet with an sclass from a known EPG
2089 Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac)
2090 / IP(src=self.pg2.remote_hosts[1].ip4, dst=self.pg2.local_ip4)
2091 / UDP(sport=1234, dport=48879)
2092 / VXLAN(vni=99, gpid=112, flags=0x88, gpflags="D")
2093 / Ether(src=l["mac"], dst=ep.mac)
2094 / IP(src=l["ip"], dst=ep.ip4)
2095 / UDP(sport=1234, dport=1234)
2096 / Raw(b"\xa5" * 100)
2099 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
2103 find_gbp_endpoint(self, vx_tun_l2_1.sw_if_index, mac=l["mac"])
2110 # a packet with an sclass from a known EPG
2111 # set a reserved bit in addition to the G and I
2112 # reserved bits should not be checked on rx.
2114 Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac)
2115 / IP(src=self.pg2.remote_hosts[1].ip4, dst=self.pg2.local_ip4)
2116 / UDP(sport=1234, dport=48879)
2117 / VXLAN(vni=99, gpid=112, flags=0xC8)
2118 / Ether(src=l["mac"], dst=ep.mac)
2119 / IP(src=l["ip"], dst=ep.ip4)
2120 / UDP(sport=1234, dport=1234)
2121 / Raw(b"\xa5" * 100)
2124 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
2127 find_gbp_endpoint(self, vx_tun_l2_1.sw_if_index, mac=l["mac"])
2131 # Static EP replies to dynamics
2133 self.logger.info(self.vapi.cli("sh l2fib bd_id 1"))
2136 Ether(src=ep.mac, dst=l["mac"])
2137 / IP(dst=l["ip"], src=ep.ip4)
2138 / UDP(sport=1234, dport=1234)
2139 / Raw(b"\xa5" * 100)
2142 rxs = self.send_and_expect(self.pg0, p * 17, self.pg2)
2145 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2146 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2147 self.assertEqual(rx[UDP].dport, 48879)
2148 # the UDP source port is a random value for hashing
2149 self.assertEqual(rx[VXLAN].gpid, 112)
2150 self.assertEqual(rx[VXLAN].vni, 99)
2151 self.assertTrue(rx[VXLAN].flags.G)
2152 self.assertTrue(rx[VXLAN].flags.Instance)
2153 self.assertTrue(rx[VXLAN].gpflags.A)
2154 self.assertFalse(rx[VXLAN].gpflags.D)
2157 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index, mac=l["mac"])
2160 # repeat in the other EPG
2161 # there's no contract between 220 and 330, but the A-bit is set
2162 # so the packet is cleared for delivery
2165 # a packet with an sclass from a known EPG
2167 Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac)
2168 / IP(src=self.pg2.remote_hosts[1].ip4, dst=self.pg2.local_ip4)
2169 / UDP(sport=1234, dport=48879)
2170 / VXLAN(vni=99, gpid=113, flags=0x88, gpflags="A")
2171 / Ether(src=l["mac"], dst=ep.mac)
2172 / IP(src=l["ip"], dst=ep.ip4)
2173 / UDP(sport=1234, dport=1234)
2174 / Raw(b"\xa5" * 100)
2177 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
2180 find_gbp_endpoint(self, vx_tun_l2_1.sw_if_index, mac=l["mac"])
2184 # static EP cannot reach the learnt EPs since there is no contract
2185 # only test 1 EP as the others could timeout
2188 Ether(src=ep.mac, dst=l["mac"])
2189 / IP(dst=learnt[0]["ip"], src=ep.ip4)
2190 / UDP(sport=1234, dport=1234)
2191 / Raw(b"\xa5" * 100)
2194 self.send_and_assert_no_replies(self.pg0, [p])
2197 # refresh the entries after the check for no replies above
2200 # a packet with an sclass from a known EPG
2202 Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac)
2203 / IP(src=self.pg2.remote_hosts[1].ip4, dst=self.pg2.local_ip4)
2204 / UDP(sport=1234, dport=48879)
2205 / VXLAN(vni=99, gpid=113, flags=0x88, gpflags="A")
2206 / Ether(src=l["mac"], dst=ep.mac)
2207 / IP(src=l["ip"], dst=ep.ip4)
2208 / UDP(sport=1234, dport=1234)
2209 / Raw(b"\xa5" * 100)
2212 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
2215 find_gbp_endpoint(self, vx_tun_l2_1.sw_if_index, mac=l["mac"])
2219 # Add the contract so they can talk
2221 rule = AclRule(is_permit=1, proto=17)
2223 src_prefix=IPv6Network((0, 0)),
2224 dst_prefix=IPv6Network((0, 0)),
2228 acl = VppAcl(self, rules=[rule, rule2])
2229 acl.add_vpp_config()
2231 c1 = VppGbpContract(
2239 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2240 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2244 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2245 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2249 [ETH_P_IP, ETH_P_IPV6],
2255 Ether(src=ep.mac, dst=l["mac"])
2256 / IP(dst=l["ip"], src=ep.ip4)
2257 / UDP(sport=1234, dport=1234)
2258 / Raw(b"\xa5" * 100)
2261 self.send_and_expect(self.pg0, [p], self.pg2)
2264 # send UU packets from the local EP
2266 self.logger.info(self.vapi.cli("sh gbp bridge"))
2267 self.logger.info(self.vapi.cli("sh bridge-domain 1 detail"))
2269 Ether(src=ep.mac, dst="00:11:11:11:11:11")
2270 / IP(dst="10.0.0.133", src=ep.ip4)
2271 / UDP(sport=1234, dport=1234)
2272 / Raw(b"\xa5" * 100)
2274 rxs = self.send_and_expect(ep.itf, [p_uu], gbd1.uu_fwd)
2276 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2279 Ether(src=ep.mac, dst="ff:ff:ff:ff:ff:ff")
2280 / IP(dst="10.0.0.133", src=ep.ip4)
2281 / UDP(sport=1234, dport=1234)
2282 / Raw(b"\xa5" * 100)
2284 rxs = self.send_and_expect_only(ep.itf, [p_bm], tun_bm.mcast_itf)
2287 self.assertEqual(rx[IP].src, self.pg4.local_ip4)
2288 self.assertEqual(rx[IP].dst, "239.1.1.1")
2289 self.assertEqual(rx[UDP].dport, 48879)
2290 # the UDP source port is a random value for hashing
2291 self.assertEqual(rx[VXLAN].gpid, 112)
2292 self.assertEqual(rx[VXLAN].vni, 88)
2293 self.assertTrue(rx[VXLAN].flags.G)
2294 self.assertTrue(rx[VXLAN].flags.Instance)
2295 self.assertFalse(rx[VXLAN].gpflags.A)
2296 self.assertFalse(rx[VXLAN].gpflags.D)
2298 rule = AclRule(is_permit=1, proto=17)
2300 src_prefix=IPv6Network((0, 0)),
2301 dst_prefix=IPv6Network((0, 0)),
2305 acl = VppAcl(self, rules=[rule, rule2])
2306 acl.add_vpp_config()
2308 c2 = VppGbpContract(
2316 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2317 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2321 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2322 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2326 [ETH_P_IP, ETH_P_IPV6],
2331 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index, mac=l["mac"])
2333 # Check v6 Endpoints learning
2336 # a packet with an sclass from a known EPG
2338 Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac)
2339 / IP(src=self.pg2.remote_hosts[1].ip4, dst=self.pg2.local_ip4)
2340 / UDP(sport=1234, dport=48879)
2341 / VXLAN(vni=99, gpid=113, flags=0x88)
2342 / Ether(src=l["mac"], dst=ep.mac)
2343 / IPv6(src=l["ip6"], dst=ep.ip6)
2344 / UDP(sport=1234, dport=1234)
2345 / Raw(b"\xa5" * 100)
2348 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
2349 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
2354 vx_tun_l2_1.sw_if_index,
2356 tep=[self.pg2.local_ip4, self.pg2.remote_hosts[1].ip4],
2360 self.logger.info(self.vapi.cli("sh int"))
2361 self.logger.info(self.vapi.cli("sh vxlan-gbp tunnel"))
2362 self.logger.info(self.vapi.cli("sh gbp vxlan"))
2363 self.logger.info(self.vapi.cli("sh gbp endpoint"))
2364 self.logger.info(self.vapi.cli("sh gbp interface"))
2367 # EP moves to a different TEP
2370 # a packet with an sclass from a known EPG
2372 Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac)
2373 / IP(src=self.pg2.remote_hosts[2].ip4, dst=self.pg2.local_ip4)
2374 / UDP(sport=1234, dport=48879)
2375 / VXLAN(vni=99, gpid=113, flags=0x88)
2376 / Ether(src=l["mac"], dst=ep.mac)
2377 / IPv6(src=l["ip6"], dst=ep.ip6)
2378 / UDP(sport=1234, dport=1234)
2379 / Raw(b"\xa5" * 100)
2382 rx = self.send_and_expect(self.pg2, p * 1, self.pg0)
2383 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
2388 vx_tun_l2_1.sw_if_index,
2391 tep=[self.pg2.local_ip4, self.pg2.remote_hosts[2].ip4],
2396 # v6 remote EP reachability
2400 Ether(src=ep.mac, dst=l["mac"])
2401 / IPv6(dst=l["ip6"], src=ep.ip6)
2402 / UDP(sport=1234, dport=1234)
2403 / Raw(b"\xa5" * 100)
2406 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
2409 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2410 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[2].ip4)
2411 self.assertEqual(rx[UDP].dport, 48879)
2412 # the UDP source port is a random value for hashing
2413 self.assertEqual(rx[VXLAN].gpid, 112)
2414 self.assertEqual(rx[VXLAN].vni, 99)
2415 self.assertTrue(rx[VXLAN].flags.G)
2416 self.assertTrue(rx[VXLAN].flags.Instance)
2417 self.assertTrue(rx[VXLAN].gpflags.A)
2418 self.assertFalse(rx[VXLAN].gpflags.D)
2419 self.assertEqual(rx[IPv6].dst, l["ip6"])
2425 # a packet with an sclass from a known EPG
2427 Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac)
2428 / IP(src=self.pg2.remote_hosts[2].ip4, dst=self.pg2.local_ip4)
2429 / UDP(sport=1234, dport=48879)
2430 / VXLAN(vni=99, gpid=112, flags=0x88)
2431 / Ether(src=l["mac"], dst=ep.mac)
2432 / IPv6(src=l["ip6"], dst=ep.ip6)
2433 / UDP(sport=1234, dport=1234)
2434 / Raw(b"\xa5" * 100)
2437 rx = self.send_and_expect(self.pg2, p * 1, self.pg0)
2438 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
2443 vx_tun_l2_1.sw_if_index,
2446 tep=[self.pg2.local_ip4, self.pg2.remote_hosts[2].ip4],
2451 # check reachability and contract intra-epg
2453 allow_intra_class = self.statistics.get_err_counter(
2454 "/err/gbp-policy-mac/allow-intra-sclass"
2459 Ether(src=ep.mac, dst=l["mac"])
2460 / IPv6(dst=l["ip6"], src=ep.ip6)
2461 / UDP(sport=1234, dport=1234)
2462 / Raw(b"\xa5" * 100)
2465 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
2468 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2469 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[2].ip4)
2470 self.assertEqual(rx[UDP].dport, 48879)
2471 self.assertEqual(rx[VXLAN].gpid, 112)
2472 self.assertEqual(rx[VXLAN].vni, 99)
2473 self.assertTrue(rx[VXLAN].flags.G)
2474 self.assertTrue(rx[VXLAN].flags.Instance)
2475 self.assertTrue(rx[VXLAN].gpflags.A)
2476 self.assertFalse(rx[VXLAN].gpflags.D)
2477 self.assertEqual(rx[IPv6].dst, l["ip6"])
2479 allow_intra_class += NUM_PKTS
2481 self.assert_error_counter_equal(
2482 "/err/gbp-policy-mac/allow-intra-sclass", allow_intra_class
2489 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index, mac=l["mac"])
2490 self.pg2.unconfig_ip4()
2491 self.pg3.unconfig_ip4()
2492 self.pg4.unconfig_ip4()
2494 def test_gbp_contract(self):
2500 gt4 = VppIpTable(self, 0)
2501 gt4.add_vpp_config()
2502 gt6 = VppIpTable(self, 0, is_ip6=True)
2503 gt6.add_vpp_config()
2505 rd0 = VppGbpRouteDomain(self, 0, 400, gt4, gt6, None, None)
2507 rd0.add_vpp_config()
2512 bd1 = VppBridgeDomain(self, 1, arp_term=0)
2513 bd2 = VppBridgeDomain(self, 2, arp_term=0)
2515 bd1.add_vpp_config()
2516 bd2.add_vpp_config()
2518 gbd1 = VppGbpBridgeDomain(self, bd1, rd0, self.loop0)
2519 gbd2 = VppGbpBridgeDomain(self, bd2, rd0, self.loop1)
2521 gbd1.add_vpp_config()
2522 gbd2.add_vpp_config()
2525 # 3 EPGs, 2 of which share a BD.
2528 VppGbpEndpointGroup(
2539 VppGbpEndpointGroup(
2550 VppGbpEndpointGroup(
2563 # 4 end-points, 2 in the same subnet, 3 in the same BD
2609 # Config related to each of the EPGs
2612 # IP config on the BVI interfaces
2614 b4 = VppIpInterfaceBind(self, epg.bvi, epg.rd.t4).add_vpp_config()
2615 b6 = VppIpInterfaceBind(self, epg.bvi, epg.rd.t6).add_vpp_config()
2616 epg.bvi.set_mac(self.router_mac)
2618 if_ip4 = VppIpInterfaceAddress(
2619 self, epg.bvi, epg.bvi_ip4, 32, bind=b4
2621 if_ip6 = VppIpInterfaceAddress(
2622 self, epg.bvi, epg.bvi_ip6, 128, bind=b6
2625 # add the BD ARP termination entry for BVI IP
2626 epg.bd_arp_ip4 = VppBridgeDomainArpEntry(
2627 self, epg.bd.bd, str(self.router_mac), epg.bvi_ip4
2629 epg.bd_arp_ip4.add_vpp_config()
2632 epg.add_vpp_config()
2640 self.logger.info(self.vapi.cli("show gbp endpoint"))
2641 self.logger.info(self.vapi.cli("show interface"))
2642 self.logger.info(self.vapi.cli("show br"))
2645 # Intra epg allowed without contract
2647 pkt_intra_epg_220_to_220 = (
2648 Ether(src=self.pg0.remote_mac, dst=self.pg1.remote_mac)
2649 / IP(src=eps[0].ip4, dst=eps[1].ip4)
2650 / UDP(sport=1234, dport=1234)
2651 / Raw(b"\xa5" * 100)
2654 self.send_and_expect_bridged(self.pg0, pkt_intra_epg_220_to_220 * 65, self.pg1)
2656 pkt_intra_epg_220_to_220 = (
2657 Ether(src=self.pg0.remote_mac, dst=self.pg1.remote_mac)
2658 / IPv6(src=eps[0].ip6, dst=eps[1].ip6)
2659 / UDP(sport=1234, dport=1234)
2660 / Raw(b"\xa5" * 100)
2663 self.send_and_expect_bridged6(self.pg0, pkt_intra_epg_220_to_220 * 65, self.pg1)
2666 # Inter epg denied without contract
2668 pkt_inter_epg_220_to_221 = (
2669 Ether(src=self.pg0.remote_mac, dst=self.pg2.remote_mac)
2670 / IP(src=eps[0].ip4, dst=eps[2].ip4)
2671 / UDP(sport=1234, dport=1234)
2672 / Raw(b"\xa5" * 100)
2675 self.send_and_assert_no_replies(self.pg0, pkt_inter_epg_220_to_221)
2678 # A uni-directional contract from EPG 220 -> 221
2680 rule = AclRule(is_permit=1, proto=17)
2682 src_prefix=IPv6Network((0, 0)),
2683 dst_prefix=IPv6Network((0, 0)),
2687 rule3 = AclRule(is_permit=1, proto=1)
2688 acl = VppAcl(self, rules=[rule, rule2, rule3])
2689 acl.add_vpp_config()
2691 c1 = VppGbpContract(
2699 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2700 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2704 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2705 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2709 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2710 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2714 [ETH_P_IP, ETH_P_IPV6],
2718 self.send_and_expect_bridged(
2719 eps[0].itf, pkt_inter_epg_220_to_221 * 65, eps[2].itf
2722 pkt_inter_epg_220_to_222 = (
2723 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac))
2724 / IP(src=eps[0].ip4, dst=eps[3].ip4)
2725 / UDP(sport=1234, dport=1234)
2726 / Raw(b"\xa5" * 100)
2728 self.send_and_assert_no_replies(eps[0].itf, pkt_inter_epg_220_to_222 * 65)
2731 # ping router IP in different BD
2733 pkt_router_ping_220_to_221 = (
2734 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac))
2735 / IP(src=eps[0].ip4, dst=epgs[1].bvi_ip4)
2736 / ICMP(type="echo-request")
2739 self.send_and_expect(self.pg0, [pkt_router_ping_220_to_221], self.pg0)
2741 pkt_router_ping_220_to_221 = (
2742 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac))
2743 / IPv6(src=eps[0].ip6, dst=epgs[1].bvi_ip6)
2744 / ICMPv6EchoRequest()
2747 self.send_and_expect(self.pg0, [pkt_router_ping_220_to_221], self.pg0)
2750 # contract for the return direction
2752 c2 = VppGbpContract(
2760 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2761 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2765 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2766 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2770 [ETH_P_IP, ETH_P_IPV6],
2774 self.send_and_expect_bridged(
2775 eps[0].itf, pkt_inter_epg_220_to_221 * 65, eps[2].itf
2777 pkt_inter_epg_221_to_220 = (
2778 Ether(src=self.pg2.remote_mac, dst=self.pg0.remote_mac)
2779 / IP(src=eps[2].ip4, dst=eps[0].ip4)
2780 / UDP(sport=1234, dport=1234)
2781 / Raw(b"\xa5" * 100)
2783 self.send_and_expect_bridged(
2784 eps[2].itf, pkt_inter_epg_221_to_220 * 65, eps[0].itf
2786 pkt_inter_epg_221_to_220 = (
2787 Ether(src=self.pg2.remote_mac, dst=str(self.router_mac))
2788 / IP(src=eps[2].ip4, dst=eps[0].ip4)
2789 / UDP(sport=1234, dport=1234)
2790 / Raw(b"\xa5" * 100)
2792 self.send_and_expect_routed(
2793 eps[2].itf, pkt_inter_epg_221_to_220 * 65, eps[0].itf, str(self.router_mac)
2795 pkt_inter_epg_221_to_220 = (
2796 Ether(src=self.pg2.remote_mac, dst=str(self.router_mac))
2797 / IPv6(src=eps[2].ip6, dst=eps[0].ip6)
2798 / UDP(sport=1234, dport=1234)
2799 / Raw(b"\xa5" * 100)
2801 self.send_and_expect_routed6(
2802 eps[2].itf, pkt_inter_epg_221_to_220 * 65, eps[0].itf, str(self.router_mac)
2806 # contract between 220 and 222 uni-direction
2808 c3 = VppGbpContract(
2816 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2817 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2821 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2822 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2826 [ETH_P_IP, ETH_P_IPV6],
2830 self.send_and_expect(eps[0].itf, pkt_inter_epg_220_to_222 * 65, eps[3].itf)
2832 c3.remove_vpp_config()
2833 c1.remove_vpp_config()
2834 c2.remove_vpp_config()
2835 acl.remove_vpp_config()
2837 def test_gbp_bd_drop_flags(self):
2838 """GBP BD drop flags"""
2843 gt4 = VppIpTable(self, 1)
2844 gt4.add_vpp_config()
2845 gt6 = VppIpTable(self, 1, is_ip6=True)
2846 gt6.add_vpp_config()
2848 rd1 = VppGbpRouteDomain(self, 1, 401, gt4, gt6)
2849 rd1.add_vpp_config()
2852 # a GBP bridge domain with a BVI only
2854 bd1 = VppBridgeDomain(self, 1)
2855 bd1.add_vpp_config()
2857 gbd1 = VppGbpBridgeDomain(
2858 self, bd1, rd1, self.loop0, None, None, uu_drop=True, bm_drop=True
2860 gbd1.add_vpp_config()
2862 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2863 self.logger.info(self.vapi.cli("sh gbp bridge"))
2865 # ... and has a /32 applied
2866 ip_addr = VppIpInterfaceAddress(
2867 self, gbd1.bvi, "10.0.0.128", 32
2871 # The Endpoint-group
2873 epg_220 = VppGbpEndpointGroup(
2883 VppGbpEndpointRetention(3),
2885 epg_220.add_vpp_config()
2887 ep = VppGbpEndpoint(
2900 # send UU/BM packet from the local EP with UU drop and BM drop enabled
2903 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2904 self.logger.info(self.vapi.cli("sh gbp bridge"))
2906 Ether(src=ep.mac, dst="00:11:11:11:11:11")
2907 / IP(dst="10.0.0.133", src=ep.ip4)
2908 / UDP(sport=1234, dport=1234)
2909 / Raw(b"\xa5" * 100)
2911 self.send_and_assert_no_replies(ep.itf, [p_uu])
2914 Ether(src=ep.mac, dst="ff:ff:ff:ff:ff:ff")
2915 / IP(dst="10.0.0.133", src=ep.ip4)
2916 / UDP(sport=1234, dport=1234)
2917 / Raw(b"\xa5" * 100)
2919 self.send_and_assert_no_replies(ep.itf, [p_bm])
2921 self.pg3.unconfig_ip4()
2923 self.logger.info(self.vapi.cli("sh int"))
2925 def test_gbp_bd_arp_flags(self):
2926 """GBP BD arp flags"""
2931 gt4 = VppIpTable(self, 1)
2932 gt4.add_vpp_config()
2933 gt6 = VppIpTable(self, 1, is_ip6=True)
2934 gt6.add_vpp_config()
2936 rd1 = VppGbpRouteDomain(self, 1, 401, gt4, gt6)
2937 rd1.add_vpp_config()
2940 # Pg4 hosts the IP6 UU-flood VXLAN tunnel
2942 self.pg4.config_ip4()
2943 self.pg4.resolve_arp()
2946 # Add a mcast destination VXLAN-GBP tunnel for B&M traffic
2948 tun_uu = VppVxlanGbpTunnel(
2949 self, self.pg4.local_ip4, "239.1.1.1", 88, mcast_itf=self.pg4
2951 tun_uu.add_vpp_config()
2954 # a GBP bridge domain with a BVI and a UU-flood interface
2956 bd1 = VppBridgeDomain(self, 1)
2957 bd1.add_vpp_config()
2959 gbd1 = VppGbpBridgeDomain(
2960 self, bd1, rd1, self.loop0, tun_uu, None, ucast_arp=True
2962 gbd1.add_vpp_config()
2964 # ... and has a /32 applied
2965 ip_addr = VppIpInterfaceAddress(
2966 self, gbd1.bvi, "10.0.0.128", 32
2970 # The Endpoint-group
2972 epg_220 = VppGbpEndpointGroup(
2982 VppGbpEndpointRetention(2),
2984 epg_220.add_vpp_config()
2986 ep = VppGbpEndpoint(
2999 # send ARP packet from the local EP expect it on the uu interface
3001 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
3002 self.logger.info(self.vapi.cli("sh gbp bridge"))
3003 p_arp = Ether(src=ep.mac, dst="ff:ff:ff:ff:ff:ff") / ARP(
3008 hwdst="ff:ff:ff:ff:ff:ff",
3010 self.send_and_expect(ep.itf, [p_arp], self.pg4)
3012 self.pg4.unconfig_ip4()
3014 def test_gbp_learn_vlan_l2(self):
3015 """GBP L2 Endpoint w/ VLANs"""
3017 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
3019 {"mac": "00:00:11:11:11:01", "ip": "10.0.0.1", "ip6": "2001:10::2"},
3020 {"mac": "00:00:11:11:11:02", "ip": "10.0.0.2", "ip6": "2001:10::3"},
3026 gt4 = VppIpTable(self, 1)
3027 gt4.add_vpp_config()
3028 gt6 = VppIpTable(self, 1, is_ip6=True)
3029 gt6.add_vpp_config()
3031 rd1 = VppGbpRouteDomain(self, 1, 401, gt4, gt6)
3032 rd1.add_vpp_config()
3035 # Pg2 hosts the vxlan tunnel, hosts on pg2 to act as TEPs
3037 self.pg2.config_ip4()
3038 self.pg2.resolve_arp()
3039 self.pg2.generate_remote_hosts(4)
3040 self.pg2.configure_ipv4_neighbors()
3041 self.pg3.config_ip4()
3042 self.pg3.resolve_arp()
3045 # The EP will be on a vlan sub-interface
3047 vlan_11 = VppDot1QSubint(self, self.pg0, 11)
3049 self.vapi.l2_interface_vlan_tag_rewrite(
3050 sw_if_index=vlan_11.sw_if_index, vtr_op=L2_VTR_OP.L2_POP_1, push_dot1q=11
3053 bd_uu_fwd = VppVxlanGbpTunnel(
3054 self, self.pg3.local_ip4, self.pg3.remote_ip4, 116
3056 bd_uu_fwd.add_vpp_config()
3059 # a GBP bridge domain with a BVI and a UU-flood interface
3060 # The BD is marked as do not learn, so no endpoints are ever
3061 # learnt in this BD.
3063 bd1 = VppBridgeDomain(self, 1)
3064 bd1.add_vpp_config()
3065 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0, bd_uu_fwd, learn=False)
3066 gbd1.add_vpp_config()
3068 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
3069 self.logger.info(self.vapi.cli("sh gbp bridge"))
3071 # ... and has a /32 applied
3072 ip_addr = VppIpInterfaceAddress(
3073 self, gbd1.bvi, "10.0.0.128", 32
3077 # The Endpoint-group in which we are learning endpoints
3079 epg_220 = VppGbpEndpointGroup(
3089 VppGbpEndpointRetention(4),
3091 epg_220.add_vpp_config()
3094 # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
3097 vx_tun_l2_1 = VppGbpVxlanTunnel(
3101 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L2,
3104 vx_tun_l2_1.add_vpp_config()
3107 # A static endpoint that the learnt endpoints are trying to
3110 ep = VppGbpEndpoint(
3122 self.assertTrue(find_route(self, ep.ip4, 32, table_id=1))
3125 # Send to the static EP
3127 for ii, l in enumerate(learnt):
3128 # a packet with an sclass from a known EPG
3129 # arriving on an unknown TEP
3131 Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac)
3132 / IP(src=self.pg2.remote_hosts[1].ip4, dst=self.pg2.local_ip4)
3133 / UDP(sport=1234, dport=48879)
3134 / VXLAN(vni=99, gpid=441, flags=0x88)
3135 / Ether(src=l["mac"], dst=ep.mac)
3136 / IP(src=l["ip"], dst=ep.ip4)
3137 / UDP(sport=1234, dport=1234)
3138 / Raw(b"\xa5" * 100)
3141 rxs = self.send_and_expect(self.pg2, [p], self.pg0)
3144 # packet to EP has the EP's vlan tag
3147 self.assertEqual(rx[Dot1Q].vlan, 11)
3150 # the EP is not learnt since the BD setting prevents it
3154 find_gbp_endpoint(self, vx_tun_l2_1.sw_if_index, mac=l["mac"])
3158 find_vxlan_gbp_tunnel(
3159 self, self.pg2.local_ip4, self.pg2.remote_hosts[1].ip4, 99
3163 self.assertEqual(len(self.vapi.gbp_endpoint_dump()), 1)
3167 # we didn't learn the remotes so they are sent to the UU-fwd
3171 Ether(src=ep.mac, dst=l["mac"])
3173 / IP(dst=l["ip"], src=ep.ip4)
3174 / UDP(sport=1234, dport=1234)
3175 / Raw(b"\xa5" * 100)
3178 rxs = self.send_and_expect(self.pg0, p * 17, self.pg3)
3181 self.assertEqual(rx[IP].src, self.pg3.local_ip4)
3182 self.assertEqual(rx[IP].dst, self.pg3.remote_ip4)
3183 self.assertEqual(rx[UDP].dport, 48879)
3184 # the UDP source port is a random value for hashing
3185 self.assertEqual(rx[VXLAN].gpid, 441)
3186 self.assertEqual(rx[VXLAN].vni, 116)
3187 self.assertTrue(rx[VXLAN].flags.G)
3188 self.assertTrue(rx[VXLAN].flags.Instance)
3189 self.assertFalse(rx[VXLAN].gpflags.A)
3190 self.assertFalse(rx[VXLAN].gpflags.D)
3192 self.pg2.unconfig_ip4()
3193 self.pg3.unconfig_ip4()
3195 def test_gbp_learn_l3(self):
3196 """GBP L3 Endpoint Learning"""
3198 self.vapi.cli("set logging class gbp level debug")
3200 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
3201 routed_dst_mac = "00:0c:0c:0c:0c:0c"
3202 routed_src_mac = "00:22:bd:f8:19:ff"
3205 {"mac": "00:00:11:11:11:02", "ip": "10.0.1.2", "ip6": "2001:10::2"},
3206 {"mac": "00:00:11:11:11:03", "ip": "10.0.1.3", "ip6": "2001:10::3"},
3212 t4 = VppIpTable(self, 1)
3214 t6 = VppIpTable(self, 1, True)
3217 tun_ip4_uu = VppVxlanGbpTunnel(
3218 self, self.pg4.local_ip4, self.pg4.remote_ip4, 114
3220 tun_ip6_uu = VppVxlanGbpTunnel(
3221 self, self.pg4.local_ip4, self.pg4.remote_ip4, 116
3223 tun_ip4_uu.add_vpp_config()
3224 tun_ip6_uu.add_vpp_config()
3226 rd1 = VppGbpRouteDomain(self, 2, 401, t4, t6, tun_ip4_uu, tun_ip6_uu)
3227 rd1.add_vpp_config()
3229 self.loop0.set_mac(self.router_mac)
3232 # Bind the BVI to the RD
3234 b4 = VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
3235 b6 = VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
3238 # Pg2 hosts the vxlan tunnel
3239 # hosts on pg2 to act as TEPs
3243 self.pg2.config_ip4()
3244 self.pg2.resolve_arp()
3245 self.pg2.generate_remote_hosts(4)
3246 self.pg2.configure_ipv4_neighbors()
3247 self.pg3.config_ip4()
3248 self.pg3.resolve_arp()
3249 self.pg4.config_ip4()
3250 self.pg4.resolve_arp()
3253 # a GBP bridge domain with a BVI and a UU-flood interface
3255 bd1 = VppBridgeDomain(self, 1)
3256 bd1.add_vpp_config()
3257 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0, self.pg3)
3258 gbd1.add_vpp_config()
3260 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
3261 self.logger.info(self.vapi.cli("sh gbp bridge"))
3262 self.logger.info(self.vapi.cli("sh gbp route"))
3264 # ... and has a /32 and /128 applied
3265 ip4_addr = VppIpInterfaceAddress(
3266 self, gbd1.bvi, "10.0.0.128", 32, bind=b4
3268 ip6_addr = VppIpInterfaceAddress(
3269 self, gbd1.bvi, "2001:10::128", 128, bind=b6
3273 # The Endpoint-group in which we are learning endpoints
3275 epg_220 = VppGbpEndpointGroup(
3285 VppGbpEndpointRetention(4),
3287 epg_220.add_vpp_config()
3290 # The VXLAN GBP tunnel is in L3 mode with learning enabled
3292 vx_tun_l3 = VppGbpVxlanTunnel(
3296 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
3299 vx_tun_l3.add_vpp_config()
3302 # A static endpoint that the learnt endpoints are trying to
3305 ep = VppGbpEndpoint(
3318 # learn some remote IPv4 EPs
3320 for ii, l in enumerate(learnt):
3321 # a packet with an sclass from a known EPG
3322 # arriving on an unknown TEP
3324 Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac)
3325 / IP(src=self.pg2.remote_hosts[1].ip4, dst=self.pg2.local_ip4)
3326 / UDP(sport=1234, dport=48879)
3327 / VXLAN(vni=101, gpid=441, flags=0x88)
3328 / Ether(src=l["mac"], dst="00:00:00:11:11:11")
3329 / IP(src=l["ip"], dst=ep.ip4)
3330 / UDP(sport=1234, dport=1234)
3331 / Raw(b"\xa5" * 100)
3334 rx = self.send_and_expect(self.pg2, [p], self.pg0)
3337 tep1_sw_if_index = find_vxlan_gbp_tunnel(
3338 self, self.pg2.local_ip4, self.pg2.remote_hosts[1].ip4, vx_tun_l3.vni
3340 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
3342 # endpoint learnt via the parent GBP-vxlan interface
3343 self.assertTrue(find_gbp_endpoint(self, vx_tun_l3._sw_if_index, ip=l["ip"]))
3346 # Static IPv4 EP replies to learnt
3350 Ether(src=ep.mac, dst=self.loop0.local_mac)
3351 / IP(dst=l["ip"], src=ep.ip4)
3352 / UDP(sport=1234, dport=1234)
3353 / Raw(b"\xa5" * 100)
3356 rxs = self.send_and_expect(self.pg0, p * 1, self.pg2)
3359 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
3360 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
3361 self.assertEqual(rx[UDP].dport, 48879)
3362 # the UDP source port is a random value for hashing
3363 self.assertEqual(rx[VXLAN].gpid, 441)
3364 self.assertEqual(rx[VXLAN].vni, 101)
3365 self.assertTrue(rx[VXLAN].flags.G)
3366 self.assertTrue(rx[VXLAN].flags.Instance)
3367 self.assertTrue(rx[VXLAN].gpflags.A)
3368 self.assertFalse(rx[VXLAN].gpflags.D)
3370 inner = rx[VXLAN].payload
3372 self.assertEqual(inner[Ether].src, routed_src_mac)
3373 self.assertEqual(inner[Ether].dst, routed_dst_mac)
3374 self.assertEqual(inner[IP].src, ep.ip4)
3375 self.assertEqual(inner[IP].dst, l["ip"])
3378 self.assertFalse(find_gbp_endpoint(self, tep1_sw_if_index, ip=l["ip"]))
3381 # learn some remote IPv6 EPs
3383 for ii, l in enumerate(learnt):
3384 # a packet with an sclass from a known EPG
3385 # arriving on an unknown TEP
3387 Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac)
3388 / IP(src=self.pg2.remote_hosts[1].ip4, dst=self.pg2.local_ip4)
3389 / UDP(sport=1234, dport=48879)
3390 / VXLAN(vni=101, gpid=441, flags=0x88)
3391 / Ether(src=l["mac"], dst="00:00:00:11:11:11")
3392 / IPv6(src=l["ip6"], dst=ep.ip6)
3393 / UDP(sport=1234, dport=1234)
3394 / Raw(b"\xa5" * 100)
3397 rx = self.send_and_expect(self.pg2, [p], self.pg0)
3400 tep1_sw_if_index = find_vxlan_gbp_tunnel(
3401 self, self.pg2.local_ip4, self.pg2.remote_hosts[1].ip4, vx_tun_l3.vni
3403 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
3405 self.logger.info(self.vapi.cli("show gbp bridge"))
3406 self.logger.info(self.vapi.cli("show vxlan-gbp tunnel"))
3407 self.logger.info(self.vapi.cli("show gbp vxlan"))
3408 self.logger.info(self.vapi.cli("show int addr"))
3410 # endpoint learnt via the TEP
3411 self.assertTrue(find_gbp_endpoint(self, ip=l["ip6"]))
3413 self.logger.info(self.vapi.cli("show gbp endpoint"))
3414 self.logger.info(self.vapi.cli("show ip fib index 1 %s" % l["ip"]))
3417 # Static EP replies to learnt
3421 Ether(src=ep.mac, dst=self.loop0.local_mac)
3422 / IPv6(dst=l["ip6"], src=ep.ip6)
3423 / UDP(sport=1234, dport=1234)
3424 / Raw(b"\xa5" * 100)
3427 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
3430 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
3431 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
3432 self.assertEqual(rx[UDP].dport, 48879)
3433 # the UDP source port is a random value for hashing
3434 self.assertEqual(rx[VXLAN].gpid, 441)
3435 self.assertEqual(rx[VXLAN].vni, 101)
3436 self.assertTrue(rx[VXLAN].flags.G)
3437 self.assertTrue(rx[VXLAN].flags.Instance)
3438 self.assertTrue(rx[VXLAN].gpflags.A)
3439 self.assertFalse(rx[VXLAN].gpflags.D)
3441 inner = rx[VXLAN].payload
3443 self.assertEqual(inner[Ether].src, routed_src_mac)
3444 self.assertEqual(inner[Ether].dst, routed_dst_mac)
3445 self.assertEqual(inner[IPv6].src, ep.ip6)
3446 self.assertEqual(inner[IPv6].dst, l["ip6"])
3448 self.logger.info(self.vapi.cli("sh gbp endpoint"))
3450 self.wait_for_ep_timeout(ip=l["ip"])
3453 # Static sends to unknown EP with no route
3456 Ether(src=ep.mac, dst=self.loop0.local_mac)
3457 / IP(dst="10.0.0.99", src=ep.ip4)
3458 / UDP(sport=1234, dport=1234)
3459 / Raw(b"\xa5" * 100)
3462 self.send_and_assert_no_replies(self.pg0, [p])
3465 # Add a route to static EP's v4 and v6 subnet
3467 se_10_24 = VppGbpSubnet(
3472 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT,
3474 se_10_24.add_vpp_config()
3477 # static pings router
3480 Ether(src=ep.mac, dst=self.loop0.local_mac)
3481 / IP(dst=epg_220.bvi_ip4, src=ep.ip4)
3482 / UDP(sport=1234, dport=1234)
3483 / Raw(b"\xa5" * 100)
3486 self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg0)
3489 Ether(src=ep.mac, dst=self.loop0.local_mac)
3490 / IPv6(dst=epg_220.bvi_ip6, src=ep.ip6)
3491 / UDP(sport=1234, dport=1234)
3492 / Raw(b"\xa5" * 100)
3495 self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg0)
3498 # packets to address in the subnet are sent on the uu-fwd
3501 Ether(src=ep.mac, dst=self.loop0.local_mac)
3502 / IP(dst="10.0.0.99", src=ep.ip4)
3503 / UDP(sport=1234, dport=1234)
3504 / Raw(b"\xa5" * 100)
3507 rxs = self.send_and_expect(self.pg0, [p], self.pg4)
3509 self.assertEqual(rx[IP].src, self.pg4.local_ip4)
3510 self.assertEqual(rx[IP].dst, self.pg4.remote_ip4)
3511 self.assertEqual(rx[UDP].dport, 48879)
3512 # the UDP source port is a random value for hashing
3513 self.assertEqual(rx[VXLAN].gpid, 441)
3514 self.assertEqual(rx[VXLAN].vni, 114)
3515 self.assertTrue(rx[VXLAN].flags.G)
3516 self.assertTrue(rx[VXLAN].flags.Instance)
3517 # policy is not applied to packets sent to the uu-fwd interfaces
3518 self.assertFalse(rx[VXLAN].gpflags.A)
3519 self.assertFalse(rx[VXLAN].gpflags.D)
3522 # learn some remote IPv4 EPs
3524 for ii, l in enumerate(learnt):
3525 # a packet with an sclass from a known EPG
3526 # arriving on an unknown TEP
3528 Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac)
3529 / IP(src=self.pg2.remote_hosts[2].ip4, dst=self.pg2.local_ip4)
3530 / UDP(sport=1234, dport=48879)
3531 / VXLAN(vni=101, gpid=441, flags=0x88)
3532 / Ether(src=l["mac"], dst="00:00:00:11:11:11")
3533 / IP(src=l["ip"], dst=ep.ip4)
3534 / UDP(sport=1234, dport=1234)
3535 / Raw(b"\xa5" * 100)
3538 rx = self.send_and_expect(self.pg2, [p], self.pg0)
3541 tep1_sw_if_index = find_vxlan_gbp_tunnel(
3542 self, self.pg2.local_ip4, self.pg2.remote_hosts[2].ip4, vx_tun_l3.vni
3544 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
3546 # endpoint learnt via the parent GBP-vxlan interface
3547 self.assertTrue(find_gbp_endpoint(self, vx_tun_l3._sw_if_index, ip=l["ip"]))
3550 # Add a remote endpoint from the API
3552 rep_88 = VppGbpEndpoint(
3561 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
3563 self.pg2.remote_hosts[2].ip4,
3566 rep_88.add_vpp_config()
3569 # Add a remote endpoint from the API that matches an existing one
3570 # this is a lower priority, hence the packet is sent to the DP leanrt
3573 rep_2 = VppGbpEndpoint(
3582 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
3584 self.pg2.remote_hosts[1].ip4,
3587 rep_2.add_vpp_config()
3590 # Add a route to the learned EP's v4 subnet
3591 # packets should be send on the v4/v6 uu=fwd interface resp.
3593 se_10_1_24 = VppGbpSubnet(
3598 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT,
3600 se_10_1_24.add_vpp_config()
3602 self.logger.info(self.vapi.cli("show gbp endpoint"))
3604 ips = ["10.0.0.88", learnt[0]["ip"]]
3607 Ether(src=ep.mac, dst=self.loop0.local_mac)
3608 / IP(dst=ip, src=ep.ip4)
3609 / UDP(sport=1234, dport=1234)
3610 / Raw(b"\xa5" * 100)
3613 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
3616 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
3617 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[2].ip4)
3618 self.assertEqual(rx[UDP].dport, 48879)
3619 # the UDP source port is a random value for hashing
3620 self.assertEqual(rx[VXLAN].gpid, 441)
3621 self.assertEqual(rx[VXLAN].vni, 101)
3622 self.assertTrue(rx[VXLAN].flags.G)
3623 self.assertTrue(rx[VXLAN].flags.Instance)
3624 self.assertTrue(rx[VXLAN].gpflags.A)
3625 self.assertFalse(rx[VXLAN].gpflags.D)
3627 inner = rx[VXLAN].payload
3629 self.assertEqual(inner[Ether].src, routed_src_mac)
3630 self.assertEqual(inner[Ether].dst, routed_dst_mac)
3631 self.assertEqual(inner[IP].src, ep.ip4)
3632 self.assertEqual(inner[IP].dst, ip)
3635 # remove the API remote EPs, only API sourced is gone, the DP
3636 # learnt one remains
3638 rep_88.remove_vpp_config()
3639 rep_2.remove_vpp_config()
3641 self.assertTrue(find_gbp_endpoint(self, ip=rep_2.ip4))
3644 Ether(src=ep.mac, dst=self.loop0.local_mac)
3645 / IP(src=ep.ip4, dst=rep_2.ip4)
3646 / UDP(sport=1234, dport=1234)
3647 / Raw(b"\xa5" * 100)
3649 rxs = self.send_and_expect(self.pg0, [p], self.pg2)
3651 self.assertFalse(find_gbp_endpoint(self, ip=rep_88.ip4))
3654 Ether(src=ep.mac, dst=self.loop0.local_mac)
3655 / IP(src=ep.ip4, dst=rep_88.ip4)
3656 / UDP(sport=1234, dport=1234)
3657 / Raw(b"\xa5" * 100)
3659 rxs = self.send_and_expect(self.pg0, [p], self.pg4)
3662 # to appease the testcase we cannot have the registered EP still
3663 # present (because it's DP learnt) when the TC ends so wait until
3666 self.wait_for_ep_timeout(ip=rep_88.ip4)
3667 self.wait_for_ep_timeout(ip=rep_2.ip4)
3670 # Same as above, learn a remote EP via CP and DP
3671 # this time remove the DP one first. expect the CP data to remain
3673 rep_3 = VppGbpEndpoint(
3682 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
3684 self.pg2.remote_hosts[1].ip4,
3687 rep_3.add_vpp_config()
3690 Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac)
3691 / IP(src=self.pg2.remote_hosts[2].ip4, dst=self.pg2.local_ip4)
3692 / UDP(sport=1234, dport=48879)
3693 / VXLAN(vni=101, gpid=441, flags=0x88)
3694 / Ether(src=l["mac"], dst="00:00:00:11:11:11")
3695 / IP(src="10.0.1.4", dst=ep.ip4)
3696 / UDP(sport=1234, dport=1234)
3697 / Raw(b"\xa5" * 100)
3699 rxs = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
3704 vx_tun_l3._sw_if_index,
3706 tep=[self.pg2.local_ip4, self.pg2.remote_hosts[2].ip4],
3711 Ether(src=ep.mac, dst=self.loop0.local_mac)
3712 / IP(dst="10.0.1.4", src=ep.ip4)
3713 / UDP(sport=1234, dport=1234)
3714 / Raw(b"\xa5" * 100)
3716 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
3718 # host 2 is the DP learned TEP
3720 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
3721 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[2].ip4)
3723 self.wait_for_ep_timeout(
3724 ip=rep_3.ip4, tep=[self.pg2.local_ip4, self.pg2.remote_hosts[2].ip4]
3727 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
3729 # host 1 is the CP learned TEP
3731 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
3732 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
3735 # shutdown with learnt endpoint present
3738 Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac)
3739 / IP(src=self.pg2.remote_hosts[1].ip4, dst=self.pg2.local_ip4)
3740 / UDP(sport=1234, dport=48879)
3741 / VXLAN(vni=101, gpid=441, flags=0x88)
3742 / Ether(src=l["mac"], dst="00:00:00:11:11:11")
3743 / IP(src=learnt[1]["ip"], dst=ep.ip4)
3744 / UDP(sport=1234, dport=1234)
3745 / Raw(b"\xa5" * 100)
3748 rx = self.send_and_expect(self.pg2, [p], self.pg0)
3750 # endpoint learnt via the parent GBP-vxlan interface
3751 self.assertTrue(find_gbp_endpoint(self, vx_tun_l3._sw_if_index, ip=l["ip"]))
3755 # remote endpoint becomes local
3757 self.pg2.unconfig_ip4()
3758 self.pg3.unconfig_ip4()
3759 self.pg4.unconfig_ip4()
3761 def test_gbp_redirect(self):
3762 """GBP Endpoint Redirect"""
3764 self.vapi.cli("set logging class gbp level debug")
3766 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
3767 routed_dst_mac = "00:0c:0c:0c:0c:0c"
3768 routed_src_mac = "00:22:bd:f8:19:ff"
3771 {"mac": "00:00:11:11:11:02", "ip": "10.0.1.2", "ip6": "2001:10::2"},
3772 {"mac": "00:00:11:11:11:03", "ip": "10.0.1.3", "ip6": "2001:10::3"},
3778 t4 = VppIpTable(self, 1)
3780 t6 = VppIpTable(self, 1, True)
3783 rd1 = VppGbpRouteDomain(self, 2, 402, t4, t6)
3784 rd1.add_vpp_config()
3786 self.loop0.set_mac(self.router_mac)
3789 # Bind the BVI to the RD
3791 b_ip4 = VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
3792 b_ip6 = VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
3795 # Pg7 hosts a BD's UU-fwd
3797 self.pg7.config_ip4()
3798 self.pg7.resolve_arp()
3801 # a GBP bridge domains for the EPs
3803 bd1 = VppBridgeDomain(self, 1)
3804 bd1.add_vpp_config()
3805 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0)
3806 gbd1.add_vpp_config()
3808 bd2 = VppBridgeDomain(self, 2)
3809 bd2.add_vpp_config()
3810 gbd2 = VppGbpBridgeDomain(self, bd2, rd1, self.loop1)
3811 gbd2.add_vpp_config()
3813 # ... and has a /32 and /128 applied
3814 ip4_addr = VppIpInterfaceAddress(
3815 self, gbd1.bvi, "10.0.0.128", 32, bind=b_ip4
3817 ip6_addr = VppIpInterfaceAddress(
3818 self, gbd1.bvi, "2001:10::128", 128, bind=b_ip6
3820 ip4_addr = VppIpInterfaceAddress(
3821 self, gbd2.bvi, "10.0.1.128", 32
3823 ip6_addr = VppIpInterfaceAddress(
3824 self, gbd2.bvi, "2001:11::128", 128
3828 # The Endpoint-groups in which we are learning endpoints
3830 epg_220 = VppGbpEndpointGroup(
3840 VppGbpEndpointRetention(60),
3842 epg_220.add_vpp_config()
3843 epg_221 = VppGbpEndpointGroup(
3853 VppGbpEndpointRetention(60),
3855 epg_221.add_vpp_config()
3856 epg_222 = VppGbpEndpointGroup(
3866 VppGbpEndpointRetention(60),
3868 epg_222.add_vpp_config()
3871 # a GBP bridge domains for the SEPs
3873 bd_uu1 = VppVxlanGbpTunnel(self, self.pg7.local_ip4, self.pg7.remote_ip4, 116)
3874 bd_uu1.add_vpp_config()
3875 bd_uu2 = VppVxlanGbpTunnel(self, self.pg7.local_ip4, self.pg7.remote_ip4, 117)
3876 bd_uu2.add_vpp_config()
3878 bd3 = VppBridgeDomain(self, 3)
3879 bd3.add_vpp_config()
3880 gbd3 = VppGbpBridgeDomain(self, bd3, rd1, self.loop2, bd_uu1, learn=False)
3881 gbd3.add_vpp_config()
3882 bd4 = VppBridgeDomain(self, 4)
3883 bd4.add_vpp_config()
3884 gbd4 = VppGbpBridgeDomain(self, bd4, rd1, self.loop3, bd_uu2, learn=False)
3885 gbd4.add_vpp_config()
3888 # EPGs in which the service endpoints exist
3890 epg_320 = VppGbpEndpointGroup(
3900 VppGbpEndpointRetention(60),
3902 epg_320.add_vpp_config()
3903 epg_321 = VppGbpEndpointGroup(
3913 VppGbpEndpointRetention(60),
3915 epg_321.add_vpp_config()
3918 # three local endpoints
3920 ep1 = VppGbpEndpoint(
3930 ep1.add_vpp_config()
3931 ep2 = VppGbpEndpoint(
3941 ep2.add_vpp_config()
3942 ep3 = VppGbpEndpoint(
3952 ep3.add_vpp_config()
3957 sep1 = VppGbpEndpoint(
3967 sep1.add_vpp_config()
3968 sep2 = VppGbpEndpoint(
3978 sep2.add_vpp_config()
3979 sep3 = VppGbpEndpoint(
3989 sep3.add_vpp_config()
3990 # this EP is not installed immediately
3991 sep4 = VppGbpEndpoint(
4003 # an L2 switch packet between local EPs in different EPGs
4004 # different dest ports on each so the are LB hashed differently
4008 Ether(src=ep1.mac, dst=ep3.mac)
4009 / IP(src=ep1.ip4, dst=ep3.ip4)
4010 / UDP(sport=1234, dport=1234)
4011 / Raw(b"\xa5" * 100)
4014 Ether(src=ep3.mac, dst=ep1.mac)
4015 / IP(src=ep3.ip4, dst=ep1.ip4)
4016 / UDP(sport=1234, dport=1234)
4017 / Raw(b"\xa5" * 100)
4022 Ether(src=ep1.mac, dst=ep3.mac)
4023 / IPv6(src=ep1.ip6, dst=ep3.ip6)
4024 / UDP(sport=1234, dport=1234)
4025 / Raw(b"\xa5" * 100)
4028 Ether(src=ep3.mac, dst=ep1.mac)
4029 / IPv6(src=ep3.ip6, dst=ep1.ip6)
4030 / UDP(sport=1234, dport=1230)
4031 / Raw(b"\xa5" * 100)
4035 # should be dropped since no contract yet
4036 self.send_and_assert_no_replies(self.pg0, [p4[0]])
4037 self.send_and_assert_no_replies(self.pg0, [p6[0]])
4040 # Add a contract with a rule to load-balance redirect via SEP1 and SEP2
4041 # one of the next-hops is via an EP that is not known
4043 rule4 = AclRule(is_permit=1, proto=17)
4045 src_prefix=IPv6Network((0, 0)),
4046 dst_prefix=IPv6Network((0, 0)),
4050 acl = VppAcl(self, rules=[rule4, rule6])
4051 acl.add_vpp_config()
4054 # test the src-ip hash mode
4056 c1 = VppGbpContract(
4064 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4065 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4067 VppGbpContractNextHop(
4068 sep1.vmac, sep1.epg.bd, sep1.ip4, sep1.epg.rd
4070 VppGbpContractNextHop(
4071 sep2.vmac, sep2.epg.bd, sep2.ip4, sep2.epg.rd
4076 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4077 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4079 VppGbpContractNextHop(
4080 sep3.vmac, sep3.epg.bd, sep3.ip6, sep3.epg.rd
4082 VppGbpContractNextHop(
4083 sep4.vmac, sep4.epg.bd, sep4.ip6, sep4.epg.rd
4088 [ETH_P_IP, ETH_P_IPV6],
4092 c2 = VppGbpContract(
4100 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4101 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4103 VppGbpContractNextHop(
4104 sep1.vmac, sep1.epg.bd, sep1.ip4, sep1.epg.rd
4106 VppGbpContractNextHop(
4107 sep2.vmac, sep2.epg.bd, sep2.ip4, sep2.epg.rd
4112 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4113 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4115 VppGbpContractNextHop(
4116 sep3.vmac, sep3.epg.bd, sep3.ip6, sep3.epg.rd
4118 VppGbpContractNextHop(
4119 sep4.vmac, sep4.epg.bd, sep4.ip6, sep4.epg.rd
4124 [ETH_P_IP, ETH_P_IPV6],
4129 # send again with the contract preset, now packets arrive
4130 # at SEP1 or SEP2 depending on the hashing
4132 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
4135 self.assertEqual(rx[Ether].src, routed_src_mac)
4136 self.assertEqual(rx[Ether].dst, sep1.mac)
4137 self.assertEqual(rx[IP].src, ep1.ip4)
4138 self.assertEqual(rx[IP].dst, ep3.ip4)
4140 rxs = self.send_and_expect(self.pg2, p4[1] * 17, sep2.itf)
4143 self.assertEqual(rx[Ether].src, routed_src_mac)
4144 self.assertEqual(rx[Ether].dst, sep2.mac)
4145 self.assertEqual(rx[IP].src, ep3.ip4)
4146 self.assertEqual(rx[IP].dst, ep1.ip4)
4148 rxs = self.send_and_expect(self.pg0, p6[0] * 17, self.pg7)
4151 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4152 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4153 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4154 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4155 self.assertEqual(rx[VXLAN].vni, 117)
4156 self.assertTrue(rx[VXLAN].flags.G)
4157 self.assertTrue(rx[VXLAN].flags.Instance)
4158 # redirect policy has been applied
4159 self.assertTrue(rx[VXLAN].gpflags.A)
4160 self.assertFalse(rx[VXLAN].gpflags.D)
4162 inner = rx[VXLAN].payload
4164 self.assertEqual(inner[Ether].src, routed_src_mac)
4165 self.assertEqual(inner[Ether].dst, sep4.mac)
4166 self.assertEqual(inner[IPv6].src, ep1.ip6)
4167 self.assertEqual(inner[IPv6].dst, ep3.ip6)
4169 rxs = self.send_and_expect(self.pg2, p6[1] * 17, sep3.itf)
4172 self.assertEqual(rx[Ether].src, routed_src_mac)
4173 self.assertEqual(rx[Ether].dst, sep3.mac)
4174 self.assertEqual(rx[IPv6].src, ep3.ip6)
4175 self.assertEqual(rx[IPv6].dst, ep1.ip6)
4178 # programme the unknown EP
4180 sep4.add_vpp_config()
4182 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep4.itf)
4185 self.assertEqual(rx[Ether].src, routed_src_mac)
4186 self.assertEqual(rx[Ether].dst, sep4.mac)
4187 self.assertEqual(rx[IPv6].src, ep1.ip6)
4188 self.assertEqual(rx[IPv6].dst, ep3.ip6)
4191 # and revert back to unprogrammed
4193 sep4.remove_vpp_config()
4195 rxs = self.send_and_expect(self.pg0, p6[0] * 17, self.pg7)
4198 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4199 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4200 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4201 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4202 self.assertEqual(rx[VXLAN].vni, 117)
4203 self.assertTrue(rx[VXLAN].flags.G)
4204 self.assertTrue(rx[VXLAN].flags.Instance)
4205 # redirect policy has been applied
4206 self.assertTrue(rx[VXLAN].gpflags.A)
4207 self.assertFalse(rx[VXLAN].gpflags.D)
4209 inner = rx[VXLAN].payload
4211 self.assertEqual(inner[Ether].src, routed_src_mac)
4212 self.assertEqual(inner[Ether].dst, sep4.mac)
4213 self.assertEqual(inner[IPv6].src, ep1.ip6)
4214 self.assertEqual(inner[IPv6].dst, ep3.ip6)
4216 c1.remove_vpp_config()
4217 c2.remove_vpp_config()
4220 # test the symmetric hash mode
4222 c1 = VppGbpContract(
4230 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4231 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
4233 VppGbpContractNextHop(
4234 sep1.vmac, sep1.epg.bd, sep1.ip4, sep1.epg.rd
4236 VppGbpContractNextHop(
4237 sep2.vmac, sep2.epg.bd, sep2.ip4, sep2.epg.rd
4242 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4243 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
4245 VppGbpContractNextHop(
4246 sep3.vmac, sep3.epg.bd, sep3.ip6, sep3.epg.rd
4248 VppGbpContractNextHop(
4249 sep4.vmac, sep4.epg.bd, sep4.ip6, sep4.epg.rd
4254 [ETH_P_IP, ETH_P_IPV6],
4258 c2 = VppGbpContract(
4266 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4267 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
4269 VppGbpContractNextHop(
4270 sep1.vmac, sep1.epg.bd, sep1.ip4, sep1.epg.rd
4272 VppGbpContractNextHop(
4273 sep2.vmac, sep2.epg.bd, sep2.ip4, sep2.epg.rd
4278 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4279 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
4281 VppGbpContractNextHop(
4282 sep3.vmac, sep3.epg.bd, sep3.ip6, sep3.epg.rd
4284 VppGbpContractNextHop(
4285 sep4.vmac, sep4.epg.bd, sep4.ip6, sep4.epg.rd
4290 [ETH_P_IP, ETH_P_IPV6],
4295 # send again with the contract preset, now packets arrive
4296 # at SEP1 for both directions
4298 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
4301 self.assertEqual(rx[Ether].src, routed_src_mac)
4302 self.assertEqual(rx[Ether].dst, sep1.mac)
4303 self.assertEqual(rx[IP].src, ep1.ip4)
4304 self.assertEqual(rx[IP].dst, ep3.ip4)
4306 rxs = self.send_and_expect(self.pg2, p4[1] * 17, sep1.itf)
4309 self.assertEqual(rx[Ether].src, routed_src_mac)
4310 self.assertEqual(rx[Ether].dst, sep1.mac)
4311 self.assertEqual(rx[IP].src, ep3.ip4)
4312 self.assertEqual(rx[IP].dst, ep1.ip4)
4315 # programme the unknown EP for the L3 tests
4317 sep4.add_vpp_config()
4320 # an L3 switch packet between local EPs in different EPGs
4321 # different dest ports on each so the are LB hashed differently
4325 Ether(src=ep1.mac, dst=str(self.router_mac))
4326 / IP(src=ep1.ip4, dst=ep2.ip4)
4327 / UDP(sport=1234, dport=1234)
4328 / Raw(b"\xa5" * 100)
4331 Ether(src=ep2.mac, dst=str(self.router_mac))
4332 / IP(src=ep2.ip4, dst=ep1.ip4)
4333 / UDP(sport=1234, dport=1234)
4334 / Raw(b"\xa5" * 100)
4339 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)
4345 Ether(src=ep2.mac, dst=str(self.router_mac))
4346 / IPv6(src=ep2.ip6, dst=ep1.ip6)
4347 / UDP(sport=1234, dport=1234)
4348 / Raw(b"\xa5" * 100)
4352 c3 = VppGbpContract(
4360 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4361 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
4363 VppGbpContractNextHop(
4364 sep1.vmac, sep1.epg.bd, sep1.ip4, sep1.epg.rd
4366 VppGbpContractNextHop(
4367 sep2.vmac, sep2.epg.bd, sep2.ip4, sep2.epg.rd
4372 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4373 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
4375 VppGbpContractNextHop(
4376 sep3.vmac, sep3.epg.bd, sep3.ip6, sep3.epg.rd
4378 VppGbpContractNextHop(
4379 sep4.vmac, sep4.epg.bd, sep4.ip6, sep4.epg.rd
4384 [ETH_P_IP, ETH_P_IPV6],
4388 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
4391 self.assertEqual(rx[Ether].src, routed_src_mac)
4392 self.assertEqual(rx[Ether].dst, sep1.mac)
4393 self.assertEqual(rx[IP].src, ep1.ip4)
4394 self.assertEqual(rx[IP].dst, ep2.ip4)
4397 # learn a remote EP in EPG 221
4398 # packets coming from unknown remote EPs will be leant & redirected
4400 vx_tun_l3 = VppGbpVxlanTunnel(
4404 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
4407 vx_tun_l3.add_vpp_config()
4409 c4 = VppGbpContract(
4417 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4418 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4420 VppGbpContractNextHop(
4421 sep1.vmac, sep1.epg.bd, sep1.ip4, sep1.epg.rd
4423 VppGbpContractNextHop(
4424 sep2.vmac, sep2.epg.bd, sep2.ip4, sep2.epg.rd
4429 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4430 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4432 VppGbpContractNextHop(
4433 sep3.vmac, sep3.epg.bd, sep3.ip6, sep3.epg.rd
4435 VppGbpContractNextHop(
4436 sep4.vmac, sep4.epg.bd, sep4.ip6, sep4.epg.rd
4441 [ETH_P_IP, ETH_P_IPV6],
4446 Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac)
4447 / IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4)
4448 / UDP(sport=1234, dport=48879)
4449 / VXLAN(vni=444, gpid=441, flags=0x88)
4450 / Ether(src="00:22:22:22:22:33", dst=str(self.router_mac))
4451 / IP(src="10.0.0.88", dst=ep1.ip4)
4452 / UDP(sport=1234, dport=1234)
4453 / Raw(b"\xa5" * 100)
4456 # unknown remote EP to local EP redirected
4457 rxs = self.send_and_expect(self.pg7, [p], sep1.itf)
4460 self.assertEqual(rx[Ether].src, routed_src_mac)
4461 self.assertEqual(rx[Ether].dst, sep1.mac)
4462 self.assertEqual(rx[IP].src, "10.0.0.88")
4463 self.assertEqual(rx[IP].dst, ep1.ip4)
4465 # endpoint learnt via the parent GBP-vxlan interface
4466 self.assertTrue(find_gbp_endpoint(self, vx_tun_l3._sw_if_index, ip="10.0.0.88"))
4469 Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac)
4470 / IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4)
4471 / UDP(sport=1234, dport=48879)
4472 / VXLAN(vni=444, gpid=441, flags=0x88)
4473 / Ether(src="00:22:22:22:22:33", dst=str(self.router_mac))
4474 / IPv6(src="2001:10::88", dst=ep1.ip6)
4475 / UDP(sport=1234, dport=1234)
4476 / Raw(b"\xa5" * 100)
4479 # unknown remote EP to local EP redirected (ipv6)
4480 rxs = self.send_and_expect(self.pg7, [p], sep3.itf)
4483 self.assertEqual(rx[Ether].src, routed_src_mac)
4484 self.assertEqual(rx[Ether].dst, sep3.mac)
4485 self.assertEqual(rx[IPv6].src, "2001:10::88")
4486 self.assertEqual(rx[IPv6].dst, ep1.ip6)
4488 # endpoint learnt via the parent GBP-vxlan interface
4490 find_gbp_endpoint(self, vx_tun_l3._sw_if_index, ip="2001:10::88")
4494 # L3 switch from local to remote EP
4498 Ether(src=ep1.mac, dst=str(self.router_mac))
4499 / IP(src=ep1.ip4, dst="10.0.0.88")
4500 / UDP(sport=1234, dport=1234)
4501 / Raw(b"\xa5" * 100)
4506 Ether(src=ep1.mac, dst=str(self.router_mac))
4507 / IPv6(src=ep1.ip6, dst="2001:10::88")
4508 / UDP(sport=1234, dport=1234)
4509 / Raw(b"\xa5" * 100)
4513 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
4516 self.assertEqual(rx[Ether].src, routed_src_mac)
4517 self.assertEqual(rx[Ether].dst, sep1.mac)
4518 self.assertEqual(rx[IP].src, ep1.ip4)
4519 self.assertEqual(rx[IP].dst, "10.0.0.88")
4521 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep4.itf)
4524 self.assertEqual(rx[Ether].src, routed_src_mac)
4525 self.assertEqual(rx[Ether].dst, sep4.mac)
4526 self.assertEqual(rx[IPv6].src, ep1.ip6)
4527 self.assertEqual(rx[IPv6].dst, "2001:10::88")
4530 # test the dst-ip hash mode
4532 c5 = VppGbpContract(
4540 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4541 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
4543 VppGbpContractNextHop(
4544 sep1.vmac, sep1.epg.bd, sep1.ip4, sep1.epg.rd
4546 VppGbpContractNextHop(
4547 sep2.vmac, sep2.epg.bd, sep2.ip4, sep2.epg.rd
4552 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4553 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
4555 VppGbpContractNextHop(
4556 sep3.vmac, sep3.epg.bd, sep3.ip6, sep3.epg.rd
4558 VppGbpContractNextHop(
4559 sep4.vmac, sep4.epg.bd, sep4.ip6, sep4.epg.rd
4564 [ETH_P_IP, ETH_P_IPV6],
4568 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
4571 self.assertEqual(rx[Ether].src, routed_src_mac)
4572 self.assertEqual(rx[Ether].dst, sep1.mac)
4573 self.assertEqual(rx[IP].src, ep1.ip4)
4574 self.assertEqual(rx[IP].dst, "10.0.0.88")
4576 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep3.itf)
4579 self.assertEqual(rx[Ether].src, routed_src_mac)
4580 self.assertEqual(rx[Ether].dst, sep3.mac)
4581 self.assertEqual(rx[IPv6].src, ep1.ip6)
4582 self.assertEqual(rx[IPv6].dst, "2001:10::88")
4585 # a programmed remote SEP in EPG 320
4588 # gbp vxlan tunnel for the remote SEP
4589 vx_tun_l3_sep = VppGbpVxlanTunnel(
4593 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
4596 vx_tun_l3_sep.add_vpp_config()
4599 sep5 = VppGbpEndpoint(
4608 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
4610 self.pg7.remote_ip4,
4613 sep5.add_vpp_config()
4616 # local l3out redirect tests
4621 self.loop4.set_mac(self.router_mac)
4622 b_lo4_ip4 = VppIpInterfaceBind(self, self.loop4, t4).add_vpp_config()
4623 b_lo4_ip6 = VppIpInterfaceBind(self, self.loop4, t6).add_vpp_config()
4624 ebd = VppBridgeDomain(self, 100)
4625 ebd.add_vpp_config()
4626 gebd = VppGbpBridgeDomain(self, ebd, rd1, self.loop4, None, None)
4627 gebd.add_vpp_config()
4629 eepg = VppGbpEndpointGroup(
4639 VppGbpEndpointRetention(60),
4641 eepg.add_vpp_config()
4642 # add subnets to BVI
4643 VppIpInterfaceAddress(
4644 self, gebd.bvi, "10.1.0.128", 24, bind=b_lo4_ip4
4646 VppIpInterfaceAddress(
4647 self, gebd.bvi, "2001:10:1::128", 64, bind=b_lo4_ip6
4649 # ... which are L3-out subnets
4655 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
4663 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
4666 # external endpoints
4667 VppL2Vtr(self, self.vlan_100, L2_VTR_OP.L2_POP_1).add_vpp_config()
4668 eep1 = VppGbpEndpoint(
4677 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL,
4679 eep1.add_vpp_config()
4680 VppL2Vtr(self, self.vlan_101, L2_VTR_OP.L2_POP_1).add_vpp_config()
4681 eep2 = VppGbpEndpoint(
4690 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL,
4692 eep2.add_vpp_config()
4694 # external subnets reachable though eep1 and eep2 respectively
4699 [VppRoutePath(eep1.ip4, eep1.epg.bvi.sw_if_index)],
4700 table_id=t4.table_id,
4707 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
4714 [VppRoutePath(eep1.ip6, eep1.epg.bvi.sw_if_index)],
4715 table_id=t6.table_id,
4722 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
4729 [VppRoutePath(eep2.ip4, eep2.epg.bvi.sw_if_index)],
4730 table_id=t4.table_id,
4737 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
4744 [VppRoutePath(eep2.ip6, eep2.epg.bvi.sw_if_index)],
4745 table_id=t6.table_id,
4752 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
4757 # l3out redirect to remote (known, then unknown) SEP
4760 # packets from 1 external subnet to the other
4763 Ether(src=eep1.mac, dst=self.router_mac)
4765 / IP(src="10.220.0.17", dst="10.221.0.65")
4766 / UDP(sport=1234, dport=1234)
4767 / Raw(b"\xa5" * 100)
4770 Ether(src=eep1.mac, dst=self.router_mac)
4772 / IPv6(src="10:220::17", dst="10:221::65")
4773 / UDP(sport=1234, dport=1234)
4774 / Raw(b"\xa5" * 100)
4778 # packets should be dropped in absence of contract
4779 self.send_and_assert_no_replies(self.pg0, p)
4781 # contract redirecting to sep5
4790 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4791 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
4793 VppGbpContractNextHop(
4794 sep5.vmac, sep5.epg.bd, sep5.ip4, sep5.epg.rd
4799 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4800 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
4802 VppGbpContractNextHop(
4803 sep5.vmac, sep5.epg.bd, sep5.ip6, sep5.epg.rd
4808 [ETH_P_IP, ETH_P_IPV6],
4811 rxs = self.send_and_expect(self.pg0, p, self.pg7)
4813 for rx, tx in zip(rxs, p):
4814 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4815 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4816 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4817 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4818 # this should use the programmed remote leaf TEP
4819 self.assertEqual(rx[VXLAN].vni, 555)
4820 self.assertEqual(rx[VXLAN].gpid, 4220)
4821 self.assertTrue(rx[VXLAN].flags.G)
4822 self.assertTrue(rx[VXLAN].flags.Instance)
4823 # redirect policy has been applied
4824 self.assertTrue(rx[VXLAN].gpflags.A)
4825 self.assertTrue(rx[VXLAN].gpflags.D)
4826 rxip = rx[VXLAN][Ether].payload
4827 txip = tx[Dot1Q].payload
4828 self.assertEqual(rxip.src, txip.src)
4829 self.assertEqual(rxip.dst, txip.dst)
4831 # remote SEP: it is now an unknown remote SEP and should go
4833 sep5.remove_vpp_config()
4835 rxs = self.send_and_expect(self.pg0, p, self.pg7)
4837 for rx, tx in zip(rxs, p):
4838 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4839 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4840 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4841 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4842 # this should use the spine proxy TEP
4843 self.assertEqual(rx[VXLAN].vni, epg_320.bd.uu_fwd.vni)
4844 self.assertEqual(rx[VXLAN].gpid, 4220)
4845 self.assertTrue(rx[VXLAN].flags.G)
4846 self.assertTrue(rx[VXLAN].flags.Instance)
4847 # redirect policy has been applied
4848 self.assertTrue(rx[VXLAN].gpflags.A)
4849 self.assertTrue(rx[VXLAN].gpflags.D)
4850 rxip = rx[VXLAN][Ether].payload
4851 txip = tx[Dot1Q].payload
4852 self.assertEqual(rxip.src, txip.src)
4853 self.assertEqual(rxip.dst, txip.dst)
4856 # l3out redirect to local SEP
4859 # change the contract between l3out to redirect to local SEPs
4860 # instead of remote SEP
4869 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4870 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
4872 VppGbpContractNextHop(
4873 sep1.vmac, sep1.epg.bd, sep1.ip4, sep1.epg.rd
4878 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4879 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
4881 VppGbpContractNextHop(
4882 sep1.vmac, sep1.epg.bd, sep1.ip6, sep1.epg.rd
4887 [ETH_P_IP, ETH_P_IPV6],
4890 rxs = self.send_and_expect(self.pg0, p, sep1.itf)
4891 for rx, tx in zip(rxs, p):
4892 self.assertEqual(rx[Ether].src, routed_src_mac)
4893 self.assertEqual(rx[Ether].dst, sep1.mac)
4894 rxip = rx[Ether].payload
4895 txip = tx[Ether].payload
4896 self.assertEqual(rxip.src, txip.src)
4897 self.assertEqual(rxip.dst, txip.dst)
4900 # redirect remote EP to remote (known then unknown) SEP
4903 # remote SEP known again
4904 sep5.add_vpp_config()
4906 # contract to redirect to learnt SEP
4915 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4916 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
4918 VppGbpContractNextHop(
4919 sep5.vmac, sep5.epg.bd, sep5.ip4, sep5.epg.rd
4924 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4925 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
4927 VppGbpContractNextHop(
4928 sep5.vmac, sep5.epg.bd, sep5.ip6, sep5.epg.rd
4933 [ETH_P_IP, ETH_P_IPV6],
4936 # packets from unknown EP 221 to known EP in EPG 222
4937 # should be redirected to known remote SEP
4939 Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac)
4940 / IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4)
4941 / UDP(sport=1234, dport=48879)
4942 / VXLAN(vni=444, gpid=441, flags=0x88)
4943 / Ether(src="00:22:22:22:22:44", dst=str(self.router_mac))
4948 / IP(src="10.0.1.100", dst=ep3.ip4)
4949 / UDP(sport=1234, dport=1234)
4950 / Raw(b"\xa5" * 100)
4954 / IPv6(src="2001:10::100", dst=ep3.ip6)
4955 / UDP(sport=1234, dport=1234)
4956 / Raw(b"\xa5" * 100)
4960 # unknown remote EP to local EP redirected to known remote SEP
4961 rxs = self.send_and_expect(self.pg7, p, self.pg7)
4963 for rx, tx in zip(rxs, p):
4964 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4965 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4966 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4967 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4968 # this should use the programmed remote leaf TEP
4969 self.assertEqual(rx[VXLAN].vni, 555)
4970 self.assertEqual(rx[VXLAN].gpid, epg_221.sclass)
4971 self.assertTrue(rx[VXLAN].flags.G)
4972 self.assertTrue(rx[VXLAN].flags.Instance)
4973 # redirect policy has been applied
4974 self.assertTrue(rx[VXLAN].gpflags.A)
4975 self.assertFalse(rx[VXLAN].gpflags.D)
4976 rxip = rx[VXLAN][Ether].payload
4977 txip = tx[VXLAN][Ether].payload
4978 self.assertEqual(rxip.src, txip.src)
4979 self.assertEqual(rxip.dst, txip.dst)
4981 # endpoint learnt via the parent GBP-vxlan interface
4983 find_gbp_endpoint(self, vx_tun_l3._sw_if_index, ip="10.0.1.100")
4986 find_gbp_endpoint(self, vx_tun_l3._sw_if_index, ip="2001:10::100")
4989 # remote SEP: it is now an unknown remote SEP and should go
4991 sep5.remove_vpp_config()
4993 # remote EP (coming from spine proxy) to local EP redirected to
4995 rxs = self.send_and_expect(self.pg7, p, self.pg7)
4997 for rx, tx in zip(rxs, p):
4998 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4999 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
5000 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
5001 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
5002 # this should use the spine proxy TEP
5003 self.assertEqual(rx[VXLAN].vni, epg_320.bd.uu_fwd.vni)
5004 self.assertEqual(rx[VXLAN].gpid, epg_221.sclass)
5005 self.assertTrue(rx[VXLAN].flags.G)
5006 self.assertTrue(rx[VXLAN].flags.Instance)
5007 # redirect policy has been applied
5008 self.assertTrue(rx[VXLAN].gpflags.A)
5009 self.assertFalse(rx[VXLAN].gpflags.D)
5010 rxip = rx[VXLAN][Ether].payload
5011 txip = tx[VXLAN][Ether].payload
5012 self.assertEqual(rxip.src, txip.src)
5013 self.assertEqual(rxip.dst, txip.dst)
5018 self.pg7.unconfig_ip4()
5020 def test_gbp_redirect_extended(self):
5021 """GBP Endpoint Redirect Extended"""
5023 self.vapi.cli("set logging class gbp level debug")
5025 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
5026 routed_dst_mac = "00:0c:0c:0c:0c:0c"
5027 routed_src_mac = "00:22:bd:f8:19:ff"
5030 {"mac": "00:00:11:11:11:02", "ip": "10.0.1.2", "ip6": "2001:10::2"},
5031 {"mac": "00:00:11:11:11:03", "ip": "10.0.1.3", "ip6": "2001:10::3"},
5037 t4 = VppIpTable(self, 1)
5039 t6 = VppIpTable(self, 1, True)
5042 # create IPv4 and IPv6 RD UU VxLAN-GBP TEP and bind them to the right
5044 rd_uu4 = VppVxlanGbpTunnel(
5047 self.pg7.remote_ip4,
5050 VppEnum.vl_api_vxlan_gbp_api_tunnel_mode_t.VXLAN_GBP_API_TUNNEL_MODE_L3
5053 rd_uu4.add_vpp_config()
5054 VppIpInterfaceBind(self, rd_uu4, t4).add_vpp_config()
5056 rd_uu6 = VppVxlanGbpTunnel(
5059 self.pg7.remote_ip4,
5062 VppEnum.vl_api_vxlan_gbp_api_tunnel_mode_t.VXLAN_GBP_API_TUNNEL_MODE_L3
5065 rd_uu6.add_vpp_config()
5066 VppIpInterfaceBind(self, rd_uu6, t4).add_vpp_config()
5068 rd1 = VppGbpRouteDomain(self, 2, 402, t4, t6, rd_uu4, rd_uu6)
5069 rd1.add_vpp_config()
5071 self.loop0.set_mac(self.router_mac)
5072 self.loop1.set_mac(self.router_mac)
5073 self.loop2.set_mac(self.router_mac)
5076 # Bind the BVI to the RD
5078 b_lo0_ip4 = VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
5079 b_lo0_ip6 = VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
5080 b_lo1_ip4 = VppIpInterfaceBind(self, self.loop1, t4).add_vpp_config()
5081 b_lo1_ip6 = VppIpInterfaceBind(self, self.loop1, t6).add_vpp_config()
5082 b_lo2_ip4 = VppIpInterfaceBind(self, self.loop2, t4).add_vpp_config()
5083 b_lo2_ip6 = VppIpInterfaceBind(self, self.loop2, t6).add_vpp_config()
5086 # Pg7 hosts a BD's UU-fwd
5088 self.pg7.config_ip4()
5089 self.pg7.resolve_arp()
5092 # a GBP bridge domains for the EPs
5094 bd1 = VppBridgeDomain(self, 1)
5095 bd1.add_vpp_config()
5096 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0)
5097 gbd1.add_vpp_config()
5099 bd2 = VppBridgeDomain(self, 2)
5100 bd2.add_vpp_config()
5101 gbd2 = VppGbpBridgeDomain(self, bd2, rd1, self.loop1)
5102 gbd2.add_vpp_config()
5104 # ... and has a /32 and /128 applied
5105 ip4_addr1 = VppIpInterfaceAddress(
5106 self, gbd1.bvi, "10.0.0.128", 32, bind=b_lo0_ip4
5108 ip6_addr1 = VppIpInterfaceAddress(
5109 self, gbd1.bvi, "2001:10::128", 128, bind=b_lo0_ip6
5111 ip4_addr2 = VppIpInterfaceAddress(
5112 self, gbd2.bvi, "10.0.1.128", 32, bind=b_lo1_ip4
5114 ip6_addr2 = VppIpInterfaceAddress(
5115 self, gbd2.bvi, "2001:11::128", 128, bind=b_lo1_ip6
5119 # The Endpoint-groups
5121 epg_220 = VppGbpEndpointGroup(
5131 VppGbpEndpointRetention(60),
5133 epg_220.add_vpp_config()
5134 epg_221 = VppGbpEndpointGroup(
5144 VppGbpEndpointRetention(60),
5146 epg_221.add_vpp_config()
5149 # a GBP bridge domains for the SEPs
5151 bd_uu3 = VppVxlanGbpTunnel(self, self.pg7.local_ip4, self.pg7.remote_ip4, 116)
5152 bd_uu3.add_vpp_config()
5154 bd3 = VppBridgeDomain(self, 3)
5155 bd3.add_vpp_config()
5156 gbd3 = VppGbpBridgeDomain(self, bd3, rd1, self.loop2, bd_uu3, learn=False)
5157 gbd3.add_vpp_config()
5159 ip4_addr3 = VppIpInterfaceAddress(
5160 self, gbd3.bvi, "12.0.0.128", 32, bind=b_lo2_ip4
5162 ip6_addr3 = VppIpInterfaceAddress(
5163 self, gbd3.bvi, "4001:10::128", 128, bind=b_lo2_ip6
5167 # self.logger.info(self.vapi.cli("show gbp bridge"))
5168 # self.logger.info(self.vapi.cli("show vxlan-gbp tunnel"))
5169 # self.logger.info(self.vapi.cli("show gbp vxlan"))
5170 # self.logger.info(self.vapi.cli("show int addr"))
5174 # EPGs in which the service endpoints exist
5176 epg_320 = VppGbpEndpointGroup(
5186 VppGbpEndpointRetention(60),
5188 epg_320.add_vpp_config()
5193 ep1 = VppGbpEndpoint(
5203 ep1.add_vpp_config()
5204 ep2 = VppGbpEndpoint(
5214 ep2.add_vpp_config()
5219 sep1 = VppGbpEndpoint(
5229 sep2 = VppGbpEndpoint(
5240 # sep1 and sep2 are not added to config yet
5241 # they are unknown for now
5244 # add routes to EPG subnets
5251 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT,
5258 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT,
5262 # Local host to known local host in different BD
5263 # with SFC contract (source and destination are in
5264 # one node and service endpoint in another node)
5268 Ether(src=ep1.mac, dst=str(self.router_mac))
5269 / IP(src=ep1.ip4, dst=ep2.ip4)
5270 / UDP(sport=1234, dport=1234)
5271 / Raw(b"\xa5" * 100)
5274 Ether(src=ep2.mac, dst=str(self.router_mac))
5275 / IP(src=ep2.ip4, dst=ep1.ip4)
5276 / UDP(sport=1234, dport=1234)
5277 / Raw(b"\xa5" * 100)
5282 Ether(src=ep1.mac, dst=str(self.router_mac))
5283 / IPv6(src=ep1.ip6, dst=ep2.ip6)
5284 / UDP(sport=1234, dport=1234)
5285 / Raw(b"\xa5" * 100)
5288 Ether(src=ep2.mac, dst=str(self.router_mac))
5289 / IPv6(src=ep2.ip6, dst=ep1.ip6)
5290 / UDP(sport=1234, dport=1230)
5291 / Raw(b"\xa5" * 100)
5295 # should be dropped since no contract yet
5296 self.send_and_assert_no_replies(self.pg0, [p4[0]])
5297 self.send_and_assert_no_replies(self.pg0, [p6[0]])
5300 # Add a contract with a rule to load-balance redirect via SEP1 and SEP2
5301 # one of the next-hops is via an EP that is not known
5303 rule4 = AclRule(is_permit=1, proto=17)
5305 src_prefix=IPv6Network((0, 0)),
5306 dst_prefix=IPv6Network((0, 0)),
5310 acl = VppAcl(self, rules=[rule4, rule6])
5311 acl.add_vpp_config()
5314 # test the src-ip hash mode
5316 c1 = VppGbpContract(
5324 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
5325 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
5327 VppGbpContractNextHop(
5328 sep1.vmac, sep1.epg.bd, sep1.ip4, sep1.epg.rd
5333 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
5334 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
5336 VppGbpContractNextHop(
5337 sep1.vmac, sep1.epg.bd, sep1.ip6, sep1.epg.rd
5342 [ETH_P_IP, ETH_P_IPV6],
5346 c2 = VppGbpContract(
5354 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
5355 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
5357 VppGbpContractNextHop(
5358 sep1.vmac, sep1.epg.bd, sep1.ip4, sep1.epg.rd
5363 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
5364 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
5366 VppGbpContractNextHop(
5367 sep1.vmac, sep1.epg.bd, sep1.ip6, sep1.epg.rd
5372 [ETH_P_IP, ETH_P_IPV6],
5376 # ep1 <--> ep2 redirected through sep1
5378 # packet is redirected to sep bd and then go through sep bd UU
5380 rxs = self.send_and_expect(self.pg0, p4[0] * 17, self.pg7)
5383 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
5384 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
5385 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
5386 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
5387 self.assertEqual(rx[VXLAN].vni, 116)
5388 self.assertTrue(rx[VXLAN].flags.G)
5389 self.assertTrue(rx[VXLAN].flags.Instance)
5390 # redirect policy has been applied
5391 self.assertTrue(rx[VXLAN].gpflags.A)
5392 self.assertFalse(rx[VXLAN].gpflags.D)
5394 inner = rx[VXLAN].payload
5396 self.assertEqual(inner[Ether].src, routed_src_mac)
5397 self.assertEqual(inner[Ether].dst, sep1.mac)
5398 self.assertEqual(inner[IP].src, ep1.ip4)
5399 self.assertEqual(inner[IP].dst, ep2.ip4)
5401 rxs = self.send_and_expect(self.pg1, p4[1] * 17, self.pg7)
5404 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
5405 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
5406 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
5407 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
5408 self.assertEqual(rx[VXLAN].vni, 116)
5409 self.assertTrue(rx[VXLAN].flags.G)
5410 self.assertTrue(rx[VXLAN].flags.Instance)
5411 # redirect policy has been applied
5412 self.assertTrue(rx[VXLAN].gpflags.A)
5413 self.assertFalse(rx[VXLAN].gpflags.D)
5415 inner = rx[VXLAN].payload
5417 self.assertEqual(inner[Ether].src, routed_src_mac)
5418 self.assertEqual(inner[Ether].dst, sep1.mac)
5419 self.assertEqual(inner[IP].src, ep2.ip4)
5420 self.assertEqual(inner[IP].dst, ep1.ip4)
5422 rxs = self.send_and_expect(self.pg0, p6[0] * 17, self.pg7)
5425 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
5426 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
5427 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
5428 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
5429 self.assertEqual(rx[VXLAN].vni, 116)
5430 self.assertTrue(rx[VXLAN].flags.G)
5431 self.assertTrue(rx[VXLAN].flags.Instance)
5432 # redirect policy has been applied
5433 inner = rx[VXLAN].payload
5435 self.assertEqual(inner[Ether].src, routed_src_mac)
5436 self.assertEqual(inner[Ether].dst, sep1.mac)
5437 self.assertEqual(inner[IPv6].src, ep1.ip6)
5438 self.assertEqual(inner[IPv6].dst, ep2.ip6)
5440 rxs = self.send_and_expect(self.pg1, p6[1] * 17, self.pg7)
5443 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
5444 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
5445 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
5446 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
5447 self.assertEqual(rx[VXLAN].vni, 116)
5448 self.assertTrue(rx[VXLAN].flags.G)
5449 self.assertTrue(rx[VXLAN].flags.Instance)
5450 # redirect policy has been applied
5451 self.assertTrue(rx[VXLAN].gpflags.A)
5452 self.assertFalse(rx[VXLAN].gpflags.D)
5454 inner = rx[VXLAN].payload
5456 self.assertEqual(inner[Ether].src, routed_src_mac)
5457 self.assertEqual(inner[Ether].dst, sep1.mac)
5458 self.assertEqual(inner[IPv6].src, ep2.ip6)
5459 self.assertEqual(inner[IPv6].dst, ep1.ip6)
5461 # configure sep1: it is now local
5462 # packets between ep1 and ep2 are redirected locally
5463 sep1.add_vpp_config()
5465 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
5468 self.assertEqual(rx[Ether].src, routed_src_mac)
5469 self.assertEqual(rx[Ether].dst, sep1.mac)
5470 self.assertEqual(rx[IP].src, ep1.ip4)
5471 self.assertEqual(rx[IP].dst, ep2.ip4)
5473 rxs = self.send_and_expect(self.pg1, p6[1] * 17, sep1.itf)
5476 self.assertEqual(rx[Ether].src, routed_src_mac)
5477 self.assertEqual(rx[Ether].dst, sep1.mac)
5478 self.assertEqual(rx[IPv6].src, ep2.ip6)
5479 self.assertEqual(rx[IPv6].dst, ep1.ip6)
5481 # packet coming from the l2 spine-proxy to sep1
5483 Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac)
5484 / IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4)
5485 / UDP(sport=1234, dport=48879)
5486 / VXLAN(vni=116, gpid=440, gpflags=0x08, flags=0x88)
5487 / Ether(src=str(self.router_mac), dst=sep1.mac)
5488 / IP(src=ep1.ip4, dst=ep2.ip4)
5489 / UDP(sport=1234, dport=1234)
5490 / Raw(b"\xa5" * 100)
5493 rxs = self.send_and_expect(self.pg7, [p] * 17, sep1.itf)
5496 self.assertEqual(rx[Ether].src, str(self.router_mac))
5497 self.assertEqual(rx[Ether].dst, sep1.mac)
5498 self.assertEqual(rx[IP].src, ep1.ip4)
5499 self.assertEqual(rx[IP].dst, ep2.ip4)
5501 # contract for SEP to communicate with dst EP
5502 c3 = VppGbpContract(
5510 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5511 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
5514 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5515 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
5518 [ETH_P_IP, ETH_P_IPV6],
5522 # temporarily remove ep2, so that ep2 is remote & unknown
5523 ep2.remove_vpp_config()
5525 # packet going back from sep1 to its original dest (ep2)
5526 # as ep2 is now unknown (see above), it must go through
5527 # the rd UU (packet is routed)
5530 Ether(src=sep1.mac, dst=self.router_mac)
5531 / IP(src=ep1.ip4, dst=ep2.ip4)
5532 / UDP(sport=1234, dport=1234)
5533 / Raw(b"\xa5" * 100)
5536 rxs = self.send_and_expect(self.pg3, [p1] * 17, self.pg7)
5539 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
5540 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
5541 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
5542 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
5543 self.assertEqual(rx[VXLAN].vni, 114)
5544 self.assertTrue(rx[VXLAN].flags.G)
5545 self.assertTrue(rx[VXLAN].flags.Instance)
5546 # redirect policy has been applied
5547 inner = rx[VXLAN].payload
5548 self.assertEqual(inner[Ether].src, routed_src_mac)
5549 self.assertEqual(inner[Ether].dst, routed_dst_mac)
5550 self.assertEqual(inner[IP].src, ep1.ip4)
5551 self.assertEqual(inner[IP].dst, ep2.ip4)
5553 self.logger.info(self.vapi.cli("show bridge 3 detail"))
5554 sep1.remove_vpp_config()
5556 self.logger.info(self.vapi.cli("show bridge 1 detail"))
5557 self.logger.info(self.vapi.cli("show bridge 2 detail"))
5559 # re-add ep2: it is local again :)
5560 ep2.add_vpp_config()
5562 # packet coming back from the remote sep through rd UU
5564 Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac)
5565 / IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4)
5566 / UDP(sport=1234, dport=48879)
5567 / VXLAN(vni=114, gpid=441, gpflags=0x09, flags=0x88)
5568 / Ether(src=str(self.router_mac), dst=self.router_mac)
5569 / IP(src=ep1.ip4, dst=ep2.ip4)
5570 / UDP(sport=1234, dport=1234)
5571 / Raw(b"\xa5" * 100)
5574 rxs = self.send_and_expect(self.pg7, [p2], self.pg1)
5577 self.assertEqual(rx[Ether].src, str(self.router_mac))
5578 self.assertEqual(rx[Ether].dst, self.pg1.remote_mac)
5579 self.assertEqual(rx[IP].src, ep1.ip4)
5580 self.assertEqual(rx[IP].dst, ep2.ip4)
5583 # bd_uu2.add_vpp_config()
5589 c1.remove_vpp_config()
5590 c2.remove_vpp_config()
5591 c3.remove_vpp_config()
5592 self.pg7.unconfig_ip4()
5594 def test_gbp_l3_out(self):
5597 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
5598 self.vapi.cli("set logging class gbp level debug")
5600 routed_dst_mac = "00:0c:0c:0c:0c:0c"
5601 routed_src_mac = "00:22:bd:f8:19:ff"
5606 t4 = VppIpTable(self, 1)
5608 t6 = VppIpTable(self, 1, True)
5611 rd1 = VppGbpRouteDomain(self, 2, 55, t4, t6)
5612 rd1.add_vpp_config()
5614 self.loop0.set_mac(self.router_mac)
5617 # Bind the BVI to the RD
5619 b_ip4 = VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
5620 b_ip6 = VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
5623 # Pg7 hosts a BD's BUM
5624 # Pg1 some other l3 interface
5626 self.pg7.config_ip4()
5627 self.pg7.resolve_arp()
5630 # a multicast vxlan-gbp tunnel for broadcast in the BD
5632 tun_bm = VppVxlanGbpTunnel(
5633 self, self.pg7.local_ip4, "239.1.1.1", 88, mcast_itf=self.pg7
5635 tun_bm.add_vpp_config()
5638 # a GBP external bridge domains for the EPs
5640 bd1 = VppBridgeDomain(self, 1)
5641 bd1.add_vpp_config()
5642 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0, None, tun_bm)
5643 gbd1.add_vpp_config()
5646 # The Endpoint-groups in which the external endpoints exist
5648 epg_220 = VppGbpEndpointGroup(
5658 VppGbpEndpointRetention(4),
5660 epg_220.add_vpp_config()
5662 # the BVIs have the subnets applied ...
5663 ip4_addr = VppIpInterfaceAddress(
5664 self, gbd1.bvi, "10.0.0.128", 24, bind=b_ip4
5666 ip6_addr = VppIpInterfaceAddress(
5667 self, gbd1.bvi, "2001:10::128", 64, bind=b_ip6
5670 # ... which are L3-out subnets
5671 l3o_1 = VppGbpSubnet(
5676 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
5679 l3o_1.add_vpp_config()
5682 # an external interface attached to the outside world and the
5685 VppL2Vtr(self, self.vlan_100, L2_VTR_OP.L2_POP_1).add_vpp_config()
5686 VppL2Vtr(self, self.vlan_101, L2_VTR_OP.L2_POP_1).add_vpp_config()
5687 vlan_144 = VppDot1QSubint(self, self.pg0, 144)
5689 # vlan_102 is not poped
5692 # an unicast vxlan-gbp for inter-RD traffic
5694 vx_tun_l3 = VppGbpVxlanTunnel(
5698 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
5701 vx_tun_l3.add_vpp_config()
5704 # External Endpoints
5706 eep1 = VppGbpEndpoint(
5715 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL,
5717 eep1.add_vpp_config()
5718 eep2 = VppGbpEndpoint(
5727 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL,
5729 eep2.add_vpp_config()
5730 eep3 = VppGbpEndpoint(
5739 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL,
5741 eep3.add_vpp_config()
5744 # A remote external endpoint
5746 rep = VppGbpEndpoint(
5755 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
5757 self.pg7.remote_ip4,
5760 rep.add_vpp_config()
5763 # EP1 impersonating EP3 is dropped
5766 Ether(src=eep1.mac, dst="ff:ff:ff:ff:ff:ff")
5773 hwdst="ff:ff:ff:ff:ff:ff",
5776 self.send_and_assert_no_replies(self.pg0, p)
5779 # ARP packet from External EPs are accepted and replied to
5782 Ether(src=eep1.mac, dst="ff:ff:ff:ff:ff:ff")
5789 hwdst="ff:ff:ff:ff:ff:ff",
5792 rxs = self.send_and_expect(self.pg0, p_arp * 1, self.pg0)
5795 # ARP packet from host in remote subnet are accepted and replied to
5798 Ether(src=eep3.mac, dst="ff:ff:ff:ff:ff:ff")
5805 hwdst="ff:ff:ff:ff:ff:ff",
5808 rxs = self.send_and_expect(self.pg0, p_arp * 1, self.pg0)
5811 # packets destined to unknown addresses in the BVI's subnet
5815 Ether(src=eep1.mac, dst=str(self.router_mac))
5817 / IP(src="10.0.0.1", dst="10.0.0.88")
5818 / UDP(sport=1234, dport=1234)
5819 / Raw(b"\xa5" * 100)
5822 Ether(src=eep1.mac, dst=str(self.router_mac))
5824 / IPv6(src="2001:10::1", dst="2001:10::88")
5825 / UDP(sport=1234, dport=1234)
5826 / Raw(b"\xa5" * 100)
5829 rxs = self.send_and_expect(self.pg0, p4 * 1, self.pg7)
5832 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
5833 # self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
5834 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
5835 self.assertEqual(rx[IP].dst, "239.1.1.1")
5836 self.assertEqual(rx[VXLAN].vni, 88)
5837 self.assertTrue(rx[VXLAN].flags.G)
5838 self.assertTrue(rx[VXLAN].flags.Instance)
5839 # policy was applied to the original IP packet
5840 self.assertEqual(rx[VXLAN].gpid, 113)
5841 self.assertTrue(rx[VXLAN].gpflags.A)
5842 self.assertFalse(rx[VXLAN].gpflags.D)
5844 inner = rx[VXLAN].payload
5846 self.assertTrue(inner.haslayer(ARP))
5849 # remote to external
5852 Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac)
5853 / IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4)
5854 / UDP(sport=1234, dport=48879)
5855 / VXLAN(vni=444, gpid=113, flags=0x88)
5856 / Ether(src=self.pg0.remote_mac, dst=str(self.router_mac))
5857 / IP(src="10.0.0.101", dst="10.0.0.1")
5858 / UDP(sport=1234, dport=1234)
5859 / Raw(b"\xa5" * 100)
5862 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
5865 # local EP pings router
5868 Ether(src=eep1.mac, dst=str(self.router_mac))
5870 / IP(src=eep1.ip4, dst="10.0.0.128")
5871 / ICMP(type="echo-request")
5874 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
5877 self.assertEqual(rx[Ether].src, str(self.router_mac))
5878 self.assertEqual(rx[Ether].dst, eep1.mac)
5879 self.assertEqual(rx[Dot1Q].vlan, 100)
5882 # local EP pings other local EP
5885 Ether(src=eep1.mac, dst=eep2.mac)
5887 / IP(src=eep1.ip4, dst=eep2.ip4)
5888 / ICMP(type="echo-request")
5891 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
5894 self.assertEqual(rx[Ether].src, eep1.mac)
5895 self.assertEqual(rx[Ether].dst, eep2.mac)
5896 self.assertEqual(rx[Dot1Q].vlan, 101)
5899 # local EP pings router w/o vlan tag poped
5902 Ether(src=eep3.mac, dst=str(self.router_mac))
5904 / IP(src=eep3.ip4, dst="10.0.0.128")
5905 / ICMP(type="echo-request")
5908 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
5911 self.assertEqual(rx[Ether].src, str(self.router_mac))
5912 self.assertEqual(rx[Ether].dst, self.vlan_102.remote_mac)
5915 # A ip4 subnet reachable through the external EP1
5917 ip_220 = VppIpRoute(
5921 [VppRoutePath(eep1.ip4, eep1.epg.bvi.sw_if_index)],
5922 table_id=t4.table_id,
5924 ip_220.add_vpp_config()
5926 l3o_220 = VppGbpSubnet(
5931 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
5934 l3o_220.add_vpp_config()
5937 # An ip6 subnet reachable through the external EP1
5939 ip6_220 = VppIpRoute(
5943 [VppRoutePath(eep1.ip6, eep1.epg.bvi.sw_if_index)],
5944 table_id=t6.table_id,
5946 ip6_220.add_vpp_config()
5948 l3o6_220 = VppGbpSubnet(
5953 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
5956 l3o6_220.add_vpp_config()
5959 # A subnet reachable through the external EP2
5961 ip_221 = VppIpRoute(
5965 [VppRoutePath(eep2.ip4, eep2.epg.bvi.sw_if_index)],
5966 table_id=t4.table_id,
5968 ip_221.add_vpp_config()
5970 l3o_221 = VppGbpSubnet(
5975 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
5978 l3o_221.add_vpp_config()
5981 # ping between hosts in remote subnets
5982 # dropped without a contract
5985 Ether(src=eep1.mac, dst=str(self.router_mac))
5987 / IP(src="10.220.0.1", dst="10.221.0.1")
5988 / ICMP(type="echo-request")
5991 self.send_and_assert_no_replies(self.pg0, p * 1)
5994 # contract for the external nets to communicate
5996 rule4 = AclRule(is_permit=1, proto=17)
5998 src_prefix=IPv6Network((0, 0)),
5999 dst_prefix=IPv6Network((0, 0)),
6003 acl = VppAcl(self, rules=[rule4, rule6])
6004 acl.add_vpp_config()
6007 # A contract with the wrong scope is not matched
6009 c_44 = VppGbpContract(
6017 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
6018 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
6022 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
6023 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
6027 [ETH_P_IP, ETH_P_IPV6],
6029 c_44.add_vpp_config()
6030 self.send_and_assert_no_replies(self.pg0, p * 1)
6032 c1 = VppGbpContract(
6040 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
6041 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
6045 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
6046 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
6050 [ETH_P_IP, ETH_P_IPV6],
6055 # Contracts allowing ext-net 200 to talk with external EPs
6057 c2 = VppGbpContract(
6065 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
6066 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
6070 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
6071 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
6075 [ETH_P_IP, ETH_P_IPV6],
6078 c3 = VppGbpContract(
6086 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
6087 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
6091 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
6092 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
6096 [ETH_P_IP, ETH_P_IPV6],
6101 # ping between hosts in remote subnets
6104 Ether(src=eep1.mac, dst=str(self.router_mac))
6106 / IP(src="10.220.0.1", dst="10.221.0.1")
6107 / UDP(sport=1234, dport=1234)
6108 / Raw(b"\xa5" * 100)
6111 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
6114 self.assertEqual(rx[Ether].src, str(self.router_mac))
6115 self.assertEqual(rx[Ether].dst, eep2.mac)
6116 self.assertEqual(rx[Dot1Q].vlan, 101)
6118 # we did not learn these external hosts
6119 self.assertFalse(find_gbp_endpoint(self, ip="10.220.0.1"))
6120 self.assertFalse(find_gbp_endpoint(self, ip="10.221.0.1"))
6123 # from remote external EP to local external EP
6126 Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac)
6127 / IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4)
6128 / UDP(sport=1234, dport=48879)
6129 / VXLAN(vni=444, gpid=113, flags=0x88)
6130 / Ether(src=self.pg0.remote_mac, dst=str(self.router_mac))
6131 / IP(src="10.0.0.101", dst="10.220.0.1")
6132 / UDP(sport=1234, dport=1234)
6133 / Raw(b"\xa5" * 100)
6136 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
6139 # ping from an external host to the remote external EP
6142 Ether(src=eep1.mac, dst=str(self.router_mac))
6144 / IP(src="10.220.0.1", dst=rep.ip4)
6145 / UDP(sport=1234, dport=1234)
6146 / Raw(b"\xa5" * 100)
6149 rxs = self.send_and_expect(self.pg0, p * 1, self.pg7)
6152 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
6153 # self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
6154 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
6155 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
6156 self.assertEqual(rx[VXLAN].vni, 444)
6157 self.assertTrue(rx[VXLAN].flags.G)
6158 self.assertTrue(rx[VXLAN].flags.Instance)
6159 # the sclass of the ext-net the packet came from
6160 self.assertEqual(rx[VXLAN].gpid, 4220)
6161 # policy was applied to the original IP packet
6162 self.assertTrue(rx[VXLAN].gpflags.A)
6163 # since it's an external host the reciever should not learn it
6164 self.assertTrue(rx[VXLAN].gpflags.D)
6165 inner = rx[VXLAN].payload
6166 self.assertEqual(inner[IP].src, "10.220.0.1")
6167 self.assertEqual(inner[IP].dst, rep.ip4)
6170 # An external subnet reachable via the remote external EP
6174 # first the VXLAN-GBP tunnel over which it is reached
6176 vx_tun_r1 = VppVxlanGbpTunnel(
6179 self.pg7.remote_ip4,
6182 VppEnum.vl_api_vxlan_gbp_api_tunnel_mode_t.VXLAN_GBP_API_TUNNEL_MODE_L3
6185 vx_tun_r1.add_vpp_config()
6186 VppIpInterfaceBind(self, vx_tun_r1, t4).add_vpp_config()
6188 self.logger.info(self.vapi.cli("sh vxlan-gbp tunnel"))
6191 # then the special adj to resolve through on that tunnel
6194 self, vx_tun_r1.sw_if_index, "00:0c:0c:0c:0c:0c", self.pg7.remote_ip4
6199 # the route via the adj above
6201 ip_222 = VppIpRoute(
6205 [VppRoutePath(self.pg7.remote_ip4, vx_tun_r1.sw_if_index)],
6206 table_id=t4.table_id,
6208 ip_222.add_vpp_config()
6210 l3o_222 = VppGbpSubnet(
6215 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
6218 l3o_222.add_vpp_config()
6221 # ping between hosts in local and remote external subnets
6222 # dropped without a contract
6225 Ether(src=eep1.mac, dst=str(self.router_mac))
6227 / IP(src="10.220.0.1", dst="10.222.0.1")
6228 / UDP(sport=1234, dport=1234)
6229 / Raw(b"\xa5" * 100)
6232 rxs = self.send_and_assert_no_replies(self.pg0, p * 1)
6235 # Add contracts ext-nets for 220 -> 222
6237 c4 = VppGbpContract(
6245 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
6246 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
6250 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
6251 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
6255 [ETH_P_IP, ETH_P_IPV6],
6260 # ping from host in local to remote external subnets
6263 Ether(src=eep1.mac, dst=str(self.router_mac))
6265 / IP(src="10.220.0.1", dst="10.222.0.1")
6266 / UDP(sport=1234, dport=1234)
6267 / Raw(b"\xa5" * 100)
6270 rxs = self.send_and_expect(self.pg0, p * 3, self.pg7)
6273 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
6274 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
6275 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
6276 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
6277 self.assertEqual(rx[VXLAN].vni, 445)
6278 self.assertTrue(rx[VXLAN].flags.G)
6279 self.assertTrue(rx[VXLAN].flags.Instance)
6280 # the sclass of the ext-net the packet came from
6281 self.assertEqual(rx[VXLAN].gpid, 4220)
6282 # policy was applied to the original IP packet
6283 self.assertTrue(rx[VXLAN].gpflags.A)
6284 # since it's an external host the reciever should not learn it
6285 self.assertTrue(rx[VXLAN].gpflags.D)
6286 inner = rx[VXLAN].payload
6287 self.assertEqual(inner[Ether].dst, "00:0c:0c:0c:0c:0c")
6288 self.assertEqual(inner[IP].src, "10.220.0.1")
6289 self.assertEqual(inner[IP].dst, "10.222.0.1")
6292 # make the external subnet ECMP
6294 vx_tun_r2 = VppVxlanGbpTunnel(
6297 self.pg7.remote_ip4,
6300 VppEnum.vl_api_vxlan_gbp_api_tunnel_mode_t.VXLAN_GBP_API_TUNNEL_MODE_L3
6303 vx_tun_r2.add_vpp_config()
6304 VppIpInterfaceBind(self, vx_tun_r2, t4).add_vpp_config()
6306 self.logger.info(self.vapi.cli("sh vxlan-gbp tunnel"))
6309 self, vx_tun_r2.sw_if_index, "00:0c:0c:0c:0c:0c", self.pg7.remote_ip4
6315 VppRoutePath(self.pg7.remote_ip4, vx_tun_r1.sw_if_index),
6316 VppRoutePath(self.pg7.remote_ip4, vx_tun_r2.sw_if_index),
6321 # now expect load-balance
6325 Ether(src=eep1.mac, dst=str(self.router_mac))
6327 / IP(src="10.220.0.1", dst="10.222.0.1")
6328 / UDP(sport=1234, dport=1234)
6329 / Raw(b"\xa5" * 100)
6332 Ether(src=eep1.mac, dst=str(self.router_mac))
6334 / IP(src="10.220.0.1", dst="10.222.0.1")
6335 / UDP(sport=1222, dport=1235)
6336 / Raw(b"\xa5" * 100)
6340 rxs = self.send_and_expect(self.pg0, p, self.pg7)
6342 self.assertEqual(rxs[0][VXLAN].vni, 445)
6343 self.assertEqual(rxs[1][VXLAN].vni, 446)
6346 # Same LB test for v6
6349 self, vx_tun_r1.sw_if_index, "00:0c:0c:0c:0c:0c", self.pg7.remote_ip6
6353 self, vx_tun_r2.sw_if_index, "00:0c:0c:0c:0c:0c", self.pg7.remote_ip6
6357 ip_222_6 = VppIpRoute(
6362 VppRoutePath(self.pg7.remote_ip6, vx_tun_r1.sw_if_index),
6363 VppRoutePath(self.pg7.remote_ip6, vx_tun_r2.sw_if_index),
6365 table_id=t6.table_id,
6367 ip_222_6.add_vpp_config()
6369 l3o_222_6 = VppGbpSubnet(
6374 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
6377 l3o_222_6.add_vpp_config()
6381 Ether(src=eep1.mac, dst=str(self.router_mac))
6383 / IPv6(src="10:220::1", dst="10:222::1")
6384 / UDP(sport=1234, dport=1234)
6385 / Raw(b"\xa5" * 100)
6388 Ether(src=eep1.mac, dst=str(self.router_mac))
6390 / IPv6(src="10:220::1", dst="10:222::1")
6391 / UDP(sport=7777, dport=8881)
6392 / Raw(b"\xa5" * 100)
6396 self.logger.info(self.vapi.cli("sh ip6 fib 10:222::1"))
6397 rxs = self.send_and_expect(self.pg0, p, self.pg7)
6399 self.assertEqual(rxs[0][VXLAN].vni, 445)
6400 self.assertEqual(rxs[1][VXLAN].vni, 446)
6403 # ping from host in remote to local external subnets
6404 # there's no contract for this, but the A bit is set.
6407 Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac)
6408 / IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4)
6409 / UDP(sport=1234, dport=48879)
6410 / VXLAN(vni=445, gpid=4222, flags=0x88, gpflags="A")
6411 / Ether(src=self.pg0.remote_mac, dst=str(self.router_mac))
6412 / IP(src="10.222.0.1", dst="10.220.0.1")
6413 / UDP(sport=1234, dport=1234)
6414 / Raw(b"\xa5" * 100)
6417 rxs = self.send_and_expect(self.pg7, p * 3, self.pg0)
6418 self.assertFalse(find_gbp_endpoint(self, ip="10.222.0.1"))
6421 # ping from host in remote to remote external subnets
6422 # this is dropped by reflection check.
6425 Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac)
6426 / IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4)
6427 / UDP(sport=1234, dport=48879)
6428 / VXLAN(vni=445, gpid=4222, flags=0x88, gpflags="A")
6429 / Ether(src=self.pg0.remote_mac, dst=str(self.router_mac))
6430 / IP(src="10.222.0.1", dst="10.222.0.2")
6431 / UDP(sport=1234, dport=1234)
6432 / Raw(b"\xa5" * 100)
6435 rxs = self.send_and_assert_no_replies(self.pg7, p * 3)
6438 Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac)
6439 / IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4)
6440 / UDP(sport=1234, dport=48879)
6441 / VXLAN(vni=445, gpid=4222, flags=0x88, gpflags="A")
6442 / Ether(src=self.pg0.remote_mac, dst=str(self.router_mac))
6443 / IPv6(src="10:222::1", dst="10:222::2")
6444 / UDP(sport=1234, dport=1234)
6445 / Raw(b"\xa5" * 100)
6448 rxs = self.send_and_assert_no_replies(self.pg7, p * 3)
6453 lep1 = VppGbpEndpoint(
6463 lep1.add_vpp_config()
6466 # local EP to local ip4 external subnet
6469 Ether(src=lep1.mac, dst=str(self.router_mac))
6471 / IP(src=lep1.ip4, dst="10.220.0.1")
6472 / UDP(sport=1234, dport=1234)
6473 / Raw(b"\xa5" * 100)
6476 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
6479 self.assertEqual(rx[Ether].src, str(self.router_mac))
6480 self.assertEqual(rx[Ether].dst, eep1.mac)
6481 self.assertEqual(rx[Dot1Q].vlan, 100)
6484 # local EP to local ip6 external subnet
6487 Ether(src=lep1.mac, dst=str(self.router_mac))
6489 / IPv6(src=lep1.ip6, dst="10:220::1")
6490 / UDP(sport=1234, dport=1234)
6491 / Raw(b"\xa5" * 100)
6494 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
6497 self.assertEqual(rx[Ether].src, str(self.router_mac))
6498 self.assertEqual(rx[Ether].dst, eep1.mac)
6499 self.assertEqual(rx[Dot1Q].vlan, 100)
6502 # ip4 and ip6 subnets that load-balance
6509 VppRoutePath(eep1.ip4, eep1.epg.bvi.sw_if_index),
6510 VppRoutePath(eep2.ip4, eep2.epg.bvi.sw_if_index),
6512 table_id=t4.table_id,
6514 ip_20.add_vpp_config()
6516 l3o_20 = VppGbpSubnet(
6521 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
6524 l3o_20.add_vpp_config()
6526 ip6_20 = VppIpRoute(
6531 VppRoutePath(eep1.ip6, eep1.epg.bvi.sw_if_index),
6532 VppRoutePath(eep2.ip6, eep2.epg.bvi.sw_if_index),
6534 table_id=t6.table_id,
6536 ip6_20.add_vpp_config()
6538 l3o6_20 = VppGbpSubnet(
6543 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
6546 l3o6_20.add_vpp_config()
6548 self.logger.info(self.vapi.cli("sh ip fib 10.20.0.1"))
6549 self.logger.info(self.vapi.cli("sh ip6 fib 10:20::1"))
6551 # two ip6 packets whose port are chosen so they load-balance
6554 Ether(src=lep1.mac, dst=str(self.router_mac))
6556 / IPv6(src=lep1.ip6, dst="10:20::1")
6557 / UDP(sport=1234, dport=1234)
6558 / Raw(b"\xa5" * 100)
6561 Ether(src=lep1.mac, dst=str(self.router_mac))
6563 / IPv6(src=lep1.ip6, dst="10:20::1")
6564 / UDP(sport=124, dport=1230)
6565 / Raw(b"\xa5" * 100)
6569 rxs = self.send_and_expect(self.pg0, p, self.pg0, 2)
6571 self.assertEqual(rxs[0][Dot1Q].vlan, 101)
6572 self.assertEqual(rxs[1][Dot1Q].vlan, 100)
6574 # two ip4 packets whose port are chosen so they load-balance
6577 Ether(src=lep1.mac, dst=str(self.router_mac))
6579 / IP(src=lep1.ip4, dst="10.20.0.1")
6580 / UDP(sport=1235, dport=1235)
6581 / Raw(b"\xa5" * 100)
6584 Ether(src=lep1.mac, dst=str(self.router_mac))
6586 / IP(src=lep1.ip4, dst="10.20.0.1")
6587 / UDP(sport=124, dport=1230)
6588 / Raw(b"\xa5" * 100)
6592 rxs = self.send_and_expect(self.pg0, p, self.pg0, 2)
6594 self.assertEqual(rxs[0][Dot1Q].vlan, 101)
6595 self.assertEqual(rxs[1][Dot1Q].vlan, 100)
6600 ip_222.remove_vpp_config()
6601 self.pg7.unconfig_ip4()
6602 self.vlan_101.set_vtr(L2_VTR_OP.L2_DISABLED)
6603 self.vlan_100.set_vtr(L2_VTR_OP.L2_DISABLED)
6605 def test_gbp_anon_l3_out(self):
6606 """GBP Anonymous L3 Out"""
6608 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
6609 self.vapi.cli("set logging class gbp level debug")
6611 routed_dst_mac = "00:0c:0c:0c:0c:0c"
6612 routed_src_mac = "00:22:bd:f8:19:ff"
6617 t4 = VppIpTable(self, 1)
6619 t6 = VppIpTable(self, 1, True)
6622 rd1 = VppGbpRouteDomain(self, 2, 55, t4, t6)
6623 rd1.add_vpp_config()
6625 self.loop0.set_mac(self.router_mac)
6628 # Bind the BVI to the RD
6630 bind_l0_ip4 = VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
6631 bind_l0_ip6 = VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
6634 # Pg7 hosts a BD's BUM
6635 # Pg1 some other l3 interface
6637 self.pg7.config_ip4()
6638 self.pg7.resolve_arp()
6641 # a GBP external bridge domains for the EPs
6643 bd1 = VppBridgeDomain(self, 1)
6644 bd1.add_vpp_config()
6645 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0, None, None)
6646 gbd1.add_vpp_config()
6649 # The Endpoint-groups in which the external endpoints exist
6651 epg_220 = VppGbpEndpointGroup(
6661 VppGbpEndpointRetention(4),
6663 epg_220.add_vpp_config()
6665 # the BVIs have the subnet applied ...
6666 ip4_addr = VppIpInterfaceAddress(
6667 self, gbd1.bvi, "10.0.0.128", 24, bind=bind_l0_ip4
6670 # ... which is an Anonymous L3-out subnets
6671 l3o_1 = VppGbpSubnet(
6676 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_ANON_L3_OUT,
6679 l3o_1.add_vpp_config()
6682 # an external interface attached to the outside world and the
6685 VppL2Vtr(self, self.vlan_100, L2_VTR_OP.L2_POP_1).add_vpp_config()
6686 VppL2Vtr(self, self.vlan_101, L2_VTR_OP.L2_POP_1).add_vpp_config()
6689 # vlan_100 and vlan_101 are anonymous l3-out interfaces
6691 ext_itf = VppGbpExtItf(self, self.vlan_100, bd1, rd1, anon=True)
6692 ext_itf.add_vpp_config()
6693 ext_itf = VppGbpExtItf(self, self.vlan_101, bd1, rd1, anon=True)
6694 ext_itf.add_vpp_config()
6697 # an unicast vxlan-gbp for inter-RD traffic
6699 vx_tun_l3 = VppGbpVxlanTunnel(
6703 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
6706 vx_tun_l3.add_vpp_config()
6709 # A remote external endpoint
6711 rep = VppGbpEndpoint(
6720 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
6722 self.pg7.remote_ip4,
6725 rep.add_vpp_config()
6728 # ARP packet from host in external subnet are accepted, flooded and
6729 # replied to. We expect 2 packets:
6730 # - APR request flooded over the other vlan subif
6731 # - ARP reply from BVI
6734 Ether(src=self.vlan_100.remote_mac, dst="ff:ff:ff:ff:ff:ff")
6740 hwsrc=self.vlan_100.remote_mac,
6741 hwdst="ff:ff:ff:ff:ff:ff",
6744 rxs = self.send_and_expect(self.pg0, p_arp * 1, self.pg0, n_rx=2)
6747 Ether(src=self.vlan_101.remote_mac, dst="ff:ff:ff:ff:ff:ff")
6753 hwsrc=self.vlan_101.remote_mac,
6754 hwdst="ff:ff:ff:ff:ff:ff",
6757 rxs = self.send_and_expect(self.pg0, p_arp * 1, self.pg0, n_rx=2)
6760 # remote to external
6763 Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac)
6764 / IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4)
6765 / UDP(sport=1234, dport=48879)
6766 / VXLAN(vni=vx_tun_l3.vni, gpid=epg_220.sclass, flags=0x88)
6767 / Ether(src=self.pg0.remote_mac, dst=str(self.router_mac))
6768 / IP(src=str(rep.ip4), dst="10.0.0.100")
6769 / UDP(sport=1234, dport=1234)
6770 / Raw(b"\xa5" * 100)
6772 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
6775 # local EP pings router
6778 Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac))
6780 / IP(src="10.0.0.100", dst="10.0.0.128")
6781 / ICMP(type="echo-request")
6783 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
6786 self.assertEqual(rx[Ether].src, str(self.router_mac))
6787 self.assertEqual(rx[Ether].dst, self.vlan_100.remote_mac)
6788 self.assertEqual(rx[Dot1Q].vlan, 100)
6791 # local EP pings other local EP
6794 Ether(src=self.vlan_100.remote_mac, dst=self.vlan_101.remote_mac)
6796 / IP(src="10.0.0.100", dst="10.0.0.101")
6797 / ICMP(type="echo-request")
6799 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
6802 self.assertEqual(rx[Ether].src, self.vlan_100.remote_mac)
6803 self.assertEqual(rx[Ether].dst, self.vlan_101.remote_mac)
6804 self.assertEqual(rx[Dot1Q].vlan, 101)
6807 # A subnet reachable through an external router on vlan 100
6809 ip_220 = VppIpRoute(
6813 [VppRoutePath("10.0.0.100", epg_220.bvi.sw_if_index)],
6814 table_id=t4.table_id,
6816 ip_220.add_vpp_config()
6818 l3o_220 = VppGbpSubnet(
6823 # note: this a "regular" L3 out subnet (not connected)
6824 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
6827 l3o_220.add_vpp_config()
6830 # A subnet reachable through an external router on vlan 101
6832 ip_221 = VppIpRoute(
6836 [VppRoutePath("10.0.0.101", epg_220.bvi.sw_if_index)],
6837 table_id=t4.table_id,
6839 ip_221.add_vpp_config()
6841 l3o_221 = VppGbpSubnet(
6846 # note: this a "regular" L3 out subnet (not connected)
6847 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
6850 l3o_221.add_vpp_config()
6853 # ping between hosts in remote subnets
6854 # dropped without a contract
6857 Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac))
6859 / IP(src="10.220.0.1", dst="10.221.0.1")
6860 / ICMP(type="echo-request")
6863 rxs = self.send_and_assert_no_replies(self.pg0, p * 1)
6866 # contract for the external nets to communicate
6868 rule4 = AclRule(is_permit=1, proto=17)
6870 src_prefix=IPv6Network((0, 0)),
6871 dst_prefix=IPv6Network((0, 0)),
6875 acl = VppAcl(self, rules=[rule4, rule6])
6876 acl.add_vpp_config()
6878 c1 = VppGbpContract(
6886 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
6887 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
6891 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
6892 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
6896 [ETH_P_IP, ETH_P_IPV6],
6901 # Contracts allowing ext-net 200 to talk with external EPs
6903 c2 = VppGbpContract(
6911 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
6912 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
6916 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
6917 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
6921 [ETH_P_IP, ETH_P_IPV6],
6924 c3 = VppGbpContract(
6932 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
6933 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
6937 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
6938 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
6942 [ETH_P_IP, ETH_P_IPV6],
6947 # ping between hosts in remote subnets
6950 Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac))
6952 / IP(src="10.220.0.1", dst="10.221.0.1")
6953 / UDP(sport=1234, dport=1234)
6954 / Raw(b"\xa5" * 100)
6957 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
6960 self.assertEqual(rx[Ether].src, str(self.router_mac))
6961 self.assertEqual(rx[Ether].dst, self.vlan_101.remote_mac)
6962 self.assertEqual(rx[Dot1Q].vlan, 101)
6964 # we did not learn these external hosts
6965 self.assertFalse(find_gbp_endpoint(self, ip="10.220.0.1"))
6966 self.assertFalse(find_gbp_endpoint(self, ip="10.221.0.1"))
6969 # from remote external EP to local external EP
6972 Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac)
6973 / IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4)
6974 / UDP(sport=1234, dport=48879)
6975 / VXLAN(vni=444, gpid=113, flags=0x88)
6976 / Ether(src=self.pg0.remote_mac, dst=str(self.router_mac))
6977 / IP(src=rep.ip4, dst="10.220.0.1")
6978 / UDP(sport=1234, dport=1234)
6979 / Raw(b"\xa5" * 100)
6982 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
6985 # ping from an external host to the remote external EP
6988 Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac))
6990 / IP(src="10.220.0.1", dst=rep.ip4)
6991 / UDP(sport=1234, dport=1234)
6992 / Raw(b"\xa5" * 100)
6995 rxs = self.send_and_expect(self.pg0, p * 1, self.pg7)
6998 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
6999 # self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
7000 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
7001 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
7002 self.assertEqual(rx[VXLAN].vni, 444)
7003 self.assertTrue(rx[VXLAN].flags.G)
7004 self.assertTrue(rx[VXLAN].flags.Instance)
7005 # the sclass of the ext-net the packet came from
7006 self.assertEqual(rx[VXLAN].gpid, 4220)
7007 # policy was applied to the original IP packet
7008 self.assertTrue(rx[VXLAN].gpflags.A)
7009 # since it's an external host the reciever should not learn it
7010 self.assertTrue(rx[VXLAN].gpflags.D)
7011 inner = rx[VXLAN].payload
7012 self.assertEqual(inner[IP].src, "10.220.0.1")
7013 self.assertEqual(inner[IP].dst, rep.ip4)
7016 # An external subnet reachable via the remote external EP
7020 # first the VXLAN-GBP tunnel over which it is reached
7022 vx_tun_r = VppVxlanGbpTunnel(
7025 self.pg7.remote_ip4,
7028 VppEnum.vl_api_vxlan_gbp_api_tunnel_mode_t.VXLAN_GBP_API_TUNNEL_MODE_L3
7031 vx_tun_r.add_vpp_config()
7032 VppIpInterfaceBind(self, vx_tun_r, t4).add_vpp_config()
7034 self.logger.info(self.vapi.cli("sh vxlan-gbp tunnel"))
7037 # then the special adj to resolve through on that tunnel
7040 self, vx_tun_r.sw_if_index, "00:0c:0c:0c:0c:0c", self.pg7.remote_ip4
7045 # the route via the adj above
7047 ip_222 = VppIpRoute(
7051 [VppRoutePath(self.pg7.remote_ip4, vx_tun_r.sw_if_index)],
7052 table_id=t4.table_id,
7054 ip_222.add_vpp_config()
7056 l3o_222 = VppGbpSubnet(
7061 # note: this a "regular" l3out subnet (not connected)
7062 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
7065 l3o_222.add_vpp_config()
7068 # ping between hosts in local and remote external subnets
7069 # dropped without a contract
7072 Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac))
7074 / IP(src="10.220.0.1", dst="10.222.0.1")
7075 / UDP(sport=1234, dport=1234)
7076 / Raw(b"\xa5" * 100)
7079 rxs = self.send_and_assert_no_replies(self.pg0, p * 1)
7082 # Add contracts ext-nets for 220 -> 222
7084 c4 = VppGbpContract(
7092 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
7093 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
7097 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
7098 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
7102 [ETH_P_IP, ETH_P_IPV6],
7107 # ping from host in local to remote external subnets
7110 Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac))
7112 / IP(src="10.220.0.1", dst="10.222.0.1")
7113 / UDP(sport=1234, dport=1234)
7114 / Raw(b"\xa5" * 100)
7117 rxs = self.send_and_expect(self.pg0, p * 3, self.pg7)
7120 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
7121 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
7122 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
7123 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
7124 self.assertEqual(rx[VXLAN].vni, 445)
7125 self.assertTrue(rx[VXLAN].flags.G)
7126 self.assertTrue(rx[VXLAN].flags.Instance)
7127 # the sclass of the ext-net the packet came from
7128 self.assertEqual(rx[VXLAN].gpid, 4220)
7129 # policy was applied to the original IP packet
7130 self.assertTrue(rx[VXLAN].gpflags.A)
7131 # since it's an external host the reciever should not learn it
7132 self.assertTrue(rx[VXLAN].gpflags.D)
7133 inner = rx[VXLAN].payload
7134 self.assertEqual(inner[Ether].dst, "00:0c:0c:0c:0c:0c")
7135 self.assertEqual(inner[IP].src, "10.220.0.1")
7136 self.assertEqual(inner[IP].dst, "10.222.0.1")
7139 # ping from host in remote to local external subnets
7140 # there's no contract for this, but the A bit is set.
7143 Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac)
7144 / IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4)
7145 / UDP(sport=1234, dport=48879)
7146 / VXLAN(vni=445, gpid=4222, flags=0x88, gpflags="A")
7147 / Ether(src=self.pg0.remote_mac, dst=str(self.router_mac))
7148 / IP(src="10.222.0.1", dst="10.220.0.1")
7149 / UDP(sport=1234, dport=1234)
7150 / Raw(b"\xa5" * 100)
7153 rxs = self.send_and_expect(self.pg7, p * 3, self.pg0)
7154 self.assertFalse(find_gbp_endpoint(self, ip="10.222.0.1"))
7157 # ping from host in remote to remote external subnets
7158 # this is dropped by reflection check.
7161 Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac)
7162 / IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4)
7163 / UDP(sport=1234, dport=48879)
7164 / VXLAN(vni=445, gpid=4222, flags=0x88, gpflags="A")
7165 / Ether(src=self.pg0.remote_mac, dst=str(self.router_mac))
7166 / IP(src="10.222.0.1", dst="10.222.0.2")
7167 / UDP(sport=1234, dport=1234)
7168 / Raw(b"\xa5" * 100)
7171 rxs = self.send_and_assert_no_replies(self.pg7, p * 3)
7176 self.vlan_101.set_vtr(L2_VTR_OP.L2_DISABLED)
7177 self.vlan_100.set_vtr(L2_VTR_OP.L2_DISABLED)
7178 self.pg7.unconfig_ip4()
7179 # make sure the programmed EP is no longer learnt from DP
7180 self.wait_for_ep_timeout(sw_if_index=rep.itf.sw_if_index, ip=rep.ip4)
7183 if __name__ == "__main__":
7184 unittest.main(testRunner=VppTestRunner)