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 self.statistics["/net/arp/tx/gratuitous"][
1167 :, epgs[0].uplink.sw_if_index
1172 self.statistics["/net/arp/tx/gratuitous"][
1173 :, epgs[1].uplink.sw_if_index
1178 self.statistics["/net/ip6-nd/tx/gratuitous"][
1179 :, epgs[0].uplink.sw_if_index
1184 self.statistics["/net/ip6-nd/tx/gratuitous"][
1185 :, epgs[1].uplink.sw_if_index
1191 # ARP packets for unknown IP are sent to the EPG uplink
1193 pkt_arp = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) / ARP(
1195 hwdst="ff:ff:ff:ff:ff:ff",
1196 hwsrc=self.pg0.remote_mac,
1201 self.vapi.cli("clear trace")
1202 self.pg0.add_stream(pkt_arp)
1204 self.pg_enable_capture(self.pg_interfaces)
1207 rxd = epgs[0].uplink.get_capture(1)
1210 # ARP/ND packets get a response
1212 pkt_arp = Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) / ARP(
1214 hwdst="ff:ff:ff:ff:ff:ff",
1215 hwsrc=self.pg0.remote_mac,
1216 pdst=epgs[0].bvi_ip4,
1220 self.send_and_expect(self.pg0, [pkt_arp], self.pg0)
1222 nsma = in6_getnsma(inet_pton(AF_INET6, eps[0].ip6))
1223 d = inet_ntop(AF_INET6, nsma)
1225 Ether(dst=in6_getnsmac(nsma), src=self.pg0.remote_mac)
1226 / IPv6(dst=d, src=eps[0].ip6)
1227 / ICMPv6ND_NS(tgt=epgs[0].bvi_ip6)
1228 / ICMPv6NDOptSrcLLAddr(lladdr=self.pg0.remote_mac)
1230 self.send_and_expect(self.pg0, [pkt_nd], self.pg0)
1233 # broadcast packets are flooded
1236 Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac)
1237 / IP(src=eps[0].ip4, dst="232.1.1.1")
1238 / UDP(sport=1234, dport=1234)
1239 / Raw(b"\xa5" * 100)
1242 self.vapi.cli("clear trace")
1243 self.pg0.add_stream(pkt_bcast)
1245 self.pg_enable_capture(self.pg_interfaces)
1248 rxd = eps[1].itf.get_capture(1)
1249 self.assertEqual(rxd[0][Ether].dst, pkt_bcast[Ether].dst)
1250 rxd = epgs[0].uplink.get_capture(1)
1251 self.assertEqual(rxd[0][Ether].dst, pkt_bcast[Ether].dst)
1254 # packets to non-local L3 destinations dropped
1256 pkt_intra_epg_220_ip4 = (
1257 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac))
1258 / IP(src=eps[0].ip4, dst="10.0.0.99")
1259 / UDP(sport=1234, dport=1234)
1260 / Raw(b"\xa5" * 100)
1262 pkt_inter_epg_222_ip4 = (
1263 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac))
1264 / IP(src=eps[0].ip4, dst="10.0.1.99")
1265 / UDP(sport=1234, dport=1234)
1266 / Raw(b"\xa5" * 100)
1269 self.send_and_assert_no_replies(self.pg0, pkt_intra_epg_220_ip4 * NUM_PKTS)
1271 pkt_inter_epg_222_ip6 = (
1272 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac))
1273 / IPv6(src=eps[0].ip6, dst="2001:10::99")
1274 / UDP(sport=1234, dport=1234)
1275 / Raw(b"\xa5" * 100)
1277 self.send_and_assert_no_replies(self.pg0, pkt_inter_epg_222_ip6 * NUM_PKTS)
1280 # Add the subnet routes
1287 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL,
1294 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL,
1301 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL,
1308 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL,
1315 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL,
1322 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL,
1324 s41.add_vpp_config()
1325 s42.add_vpp_config()
1326 s43.add_vpp_config()
1327 s61.add_vpp_config()
1328 s62.add_vpp_config()
1329 s63.add_vpp_config()
1331 self.send_and_expect_bridged(
1332 eps[0].itf, pkt_intra_epg_220_ip4 * NUM_PKTS, eps[0].epg.uplink
1334 self.send_and_expect_bridged(
1335 eps[0].itf, pkt_inter_epg_222_ip4 * NUM_PKTS, eps[0].epg.uplink
1337 self.send_and_expect_bridged6(
1338 eps[0].itf, pkt_inter_epg_222_ip6 * NUM_PKTS, eps[0].epg.uplink
1341 self.logger.info(self.vapi.cli("sh ip fib 11.0.0.2"))
1342 self.logger.info(self.vapi.cli("sh gbp endpoint-group"))
1343 self.logger.info(self.vapi.cli("sh gbp endpoint"))
1344 self.logger.info(self.vapi.cli("sh gbp recirc"))
1345 self.logger.info(self.vapi.cli("sh int"))
1346 self.logger.info(self.vapi.cli("sh int addr"))
1347 self.logger.info(self.vapi.cli("sh int feat loop6"))
1348 self.logger.info(self.vapi.cli("sh vlib graph ip4-gbp-src-classify"))
1349 self.logger.info(self.vapi.cli("sh int feat loop3"))
1350 self.logger.info(self.vapi.cli("sh int feat pg0"))
1353 # Packet destined to unknown unicast is sent on the epg uplink ...
1355 pkt_intra_epg_220_to_uplink = (
1356 Ether(src=self.pg0.remote_mac, dst="00:00:00:33:44:55")
1357 / IP(src=eps[0].ip4, dst="10.0.0.99")
1358 / UDP(sport=1234, dport=1234)
1359 / Raw(b"\xa5" * 100)
1362 self.send_and_expect_bridged(
1363 eps[0].itf, pkt_intra_epg_220_to_uplink * NUM_PKTS, eps[0].epg.uplink
1365 # ... and nowhere else
1366 self.pg1.get_capture(0, timeout=0.1)
1367 self.pg1.assert_nothing_captured(remark="Flood onto other VMS")
1369 pkt_intra_epg_221_to_uplink = (
1370 Ether(src=self.pg2.remote_mac, dst="00:00:00:33:44:66")
1371 / IP(src=eps[0].ip4, dst="10.0.0.99")
1372 / UDP(sport=1234, dport=1234)
1373 / Raw(b"\xa5" * 100)
1376 self.send_and_expect_bridged(
1377 eps[2].itf, pkt_intra_epg_221_to_uplink * NUM_PKTS, eps[2].epg.uplink
1381 # Packets from the uplink are forwarded in the absence of a contract
1383 pkt_intra_epg_220_from_uplink = (
1384 Ether(src="00:00:00:33:44:55", dst=self.pg0.remote_mac)
1385 / IP(src=eps[0].ip4, dst="10.0.0.99")
1386 / UDP(sport=1234, dport=1234)
1387 / Raw(b"\xa5" * 100)
1390 self.send_and_expect_bridged(
1391 self.pg4, pkt_intra_epg_220_from_uplink * NUM_PKTS, self.pg0
1395 # in the absence of policy, endpoints in the same EPG
1399 Ether(src=self.pg0.remote_mac, dst=self.pg1.remote_mac)
1400 / IP(src=eps[0].ip4, dst=eps[1].ip4)
1401 / UDP(sport=1234, dport=1234)
1402 / Raw(b"\xa5" * 100)
1405 self.send_and_expect_bridged(self.pg0, pkt_intra_epg * NUM_PKTS, self.pg1)
1408 # in the absence of policy, endpoints in the different EPG
1409 # cannot communicate
1411 pkt_inter_epg_220_to_221 = (
1412 Ether(src=self.pg0.remote_mac, dst=self.pg2.remote_mac)
1413 / IP(src=eps[0].ip4, dst=eps[2].ip4)
1414 / UDP(sport=1234, dport=1234)
1415 / Raw(b"\xa5" * 100)
1417 pkt_inter_epg_221_to_220 = (
1418 Ether(src=self.pg2.remote_mac, dst=self.pg0.remote_mac)
1419 / IP(src=eps[2].ip4, dst=eps[0].ip4)
1420 / UDP(sport=1234, dport=1234)
1421 / Raw(b"\xa5" * 100)
1423 pkt_inter_epg_220_to_222 = (
1424 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac))
1425 / IP(src=eps[0].ip4, dst=eps[3].ip4)
1426 / UDP(sport=1234, dport=1234)
1427 / Raw(b"\xa5" * 100)
1430 self.send_and_assert_no_replies(eps[0].itf, pkt_inter_epg_220_to_221 * NUM_PKTS)
1431 self.send_and_assert_no_replies(eps[0].itf, pkt_inter_epg_220_to_222 * NUM_PKTS)
1434 # A uni-directional contract from EPG 220 -> 221
1436 rule = AclRule(is_permit=1, proto=17)
1438 src_prefix=IPv6Network((0, 0)),
1439 dst_prefix=IPv6Network((0, 0)),
1443 acl = VppAcl(self, rules=[rule, rule2])
1444 acl.add_vpp_config()
1446 c1 = VppGbpContract(
1454 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1455 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
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 [ETH_P_IP, ETH_P_IPV6],
1468 self.send_and_expect_bridged(
1469 eps[0].itf, pkt_inter_epg_220_to_221 * NUM_PKTS, eps[2].itf
1471 self.send_and_assert_no_replies(eps[0].itf, pkt_inter_epg_220_to_222 * NUM_PKTS)
1474 # contract for the return direction
1476 c2 = VppGbpContract(
1484 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1485 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1489 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1490 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1494 [ETH_P_IP, ETH_P_IPV6],
1498 self.send_and_expect_bridged(
1499 eps[0].itf, pkt_inter_epg_220_to_221 * NUM_PKTS, eps[2].itf
1501 self.send_and_expect_bridged(
1502 eps[2].itf, pkt_inter_epg_221_to_220 * NUM_PKTS, eps[0].itf
1505 ds = c2.get_drop_stats()
1506 self.assertEqual(ds["packets"], 0)
1507 ps = c2.get_permit_stats()
1508 self.assertEqual(ps["packets"], NUM_PKTS)
1511 # the contract does not allow non-IP
1513 pkt_non_ip_inter_epg_220_to_221 = (
1514 Ether(src=self.pg0.remote_mac, dst=self.pg2.remote_mac) / ARP()
1516 self.send_and_assert_no_replies(
1517 eps[0].itf, pkt_non_ip_inter_epg_220_to_221 * 17
1521 # check that inter group is still disabled for the groups
1522 # not in the contract.
1524 self.send_and_assert_no_replies(eps[0].itf, pkt_inter_epg_220_to_222 * NUM_PKTS)
1527 # A uni-directional contract from EPG 220 -> 222 'L3 routed'
1529 c3 = VppGbpContract(
1537 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1538 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1542 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1543 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1547 [ETH_P_IP, ETH_P_IPV6],
1551 self.logger.info(self.vapi.cli("sh gbp contract"))
1553 self.send_and_expect_routed(
1555 pkt_inter_epg_220_to_222 * NUM_PKTS,
1557 str(self.router_mac),
1560 # remove both contracts, traffic stops in both directions
1562 c2.remove_vpp_config()
1563 c1.remove_vpp_config()
1564 c3.remove_vpp_config()
1565 acl.remove_vpp_config()
1567 self.send_and_assert_no_replies(eps[2].itf, pkt_inter_epg_221_to_220 * NUM_PKTS)
1568 self.send_and_assert_no_replies(eps[0].itf, pkt_inter_epg_220_to_221 * NUM_PKTS)
1569 self.send_and_expect_bridged(eps[0].itf, pkt_intra_epg * NUM_PKTS, eps[1].itf)
1572 # EPs to the outside world
1575 # in the EP's RD an external subnet via the NAT EPG's recirc
1581 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1582 sw_if_index=recirc_nat.recirc.sw_if_index,
1583 sclass=epg_nat.sclass,
1590 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1591 sw_if_index=recirc_nat.recirc.sw_if_index,
1592 sclass=epg_nat.sclass,
1594 se16 = VppGbpSubnet(
1599 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1600 sw_if_index=recirc_nat.recirc.sw_if_index,
1601 sclass=epg_nat.sclass,
1603 # in the NAT RD an external subnet via the NAT EPG's uplink
1609 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1610 sw_if_index=epg_nat.uplink.sw_if_index,
1611 sclass=epg_nat.sclass,
1613 se36 = VppGbpSubnet(
1618 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1619 sw_if_index=epg_nat.uplink.sw_if_index,
1620 sclass=epg_nat.sclass,
1627 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1628 sw_if_index=epg_nat.uplink.sw_if_index,
1629 sclass=epg_nat.sclass,
1631 se1.add_vpp_config()
1632 se2.add_vpp_config()
1633 se16.add_vpp_config()
1634 se3.add_vpp_config()
1635 se36.add_vpp_config()
1636 se4.add_vpp_config()
1638 self.logger.info(self.vapi.cli("sh ip fib 0.0.0.0/0"))
1639 self.logger.info(self.vapi.cli("sh ip fib 11.0.0.1"))
1640 self.logger.info(self.vapi.cli("sh ip6 fib ::/0"))
1641 self.logger.info(self.vapi.cli("sh ip6 fib %s" % eps[0].fip6))
1644 # From an EP to an outside address: IN2OUT
1646 pkt_inter_epg_220_to_global = (
1647 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac))
1648 / IP(src=eps[0].ip4, dst="1.1.1.1")
1649 / UDP(sport=1234, dport=1234)
1650 / Raw(b"\xa5" * 100)
1654 self.send_and_assert_no_replies(
1655 eps[0].itf, pkt_inter_epg_220_to_global * NUM_PKTS
1657 rule = AclRule(is_permit=1, proto=17, ports=1234)
1662 src_prefix=IPv6Network((0, 0)),
1663 dst_prefix=IPv6Network((0, 0)),
1665 acl2 = VppAcl(self, rules=[rule, rule2])
1666 acl2.add_vpp_config()
1668 c4 = VppGbpContract(
1676 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1677 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1681 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1682 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1686 [ETH_P_IP, ETH_P_IPV6],
1690 self.send_and_expect_natted(
1691 eps[0].itf, pkt_inter_epg_220_to_global * NUM_PKTS, self.pg7, eps[0].fip4
1694 pkt_inter_epg_220_to_global = (
1695 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac))
1696 / IPv6(src=eps[0].ip6, dst="6001::1")
1697 / UDP(sport=1234, dport=1234)
1698 / Raw(b"\xa5" * 100)
1701 self.send_and_expect_natted6(
1702 self.pg0, pkt_inter_epg_220_to_global * NUM_PKTS, self.pg7, eps[0].fip6
1705 # From a global address to an EP: OUT2IN
1707 pkt_inter_epg_220_from_global = (
1708 Ether(src=str(self.router_mac), dst=self.pg0.remote_mac)
1709 / IP(dst=eps[0].fip4, src="1.1.1.1")
1710 / UDP(sport=1234, dport=1234)
1711 / Raw(b"\xa5" * 100)
1714 self.send_and_assert_no_replies(
1715 self.pg7, pkt_inter_epg_220_from_global * NUM_PKTS
1718 c5 = VppGbpContract(
1726 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1727 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1731 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1732 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1736 [ETH_P_IP, ETH_P_IPV6],
1740 self.send_and_expect_unnatted(
1741 self.pg7, pkt_inter_epg_220_from_global * NUM_PKTS, eps[0].itf, eps[0].ip4
1744 pkt_inter_epg_220_from_global = (
1745 Ether(src=str(self.router_mac), dst=self.pg0.remote_mac)
1746 / IPv6(dst=eps[0].fip6, src="6001::1")
1747 / UDP(sport=1234, dport=1234)
1748 / Raw(b"\xa5" * 100)
1751 self.send_and_expect_unnatted6(
1752 self.pg7, pkt_inter_epg_220_from_global * NUM_PKTS, eps[0].itf, eps[0].ip6
1756 # From a local VM to another local VM using resp. public addresses:
1759 pkt_intra_epg_220_global = (
1760 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac))
1761 / IP(src=eps[0].ip4, dst=eps[1].fip4)
1762 / UDP(sport=1234, dport=1234)
1763 / Raw(b"\xa5" * 100)
1766 self.send_and_expect_double_natted(
1768 pkt_intra_epg_220_global * NUM_PKTS,
1774 pkt_intra_epg_220_global = (
1775 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac))
1776 / IPv6(src=eps[0].ip6, dst=eps[1].fip6)
1777 / UDP(sport=1234, dport=1234)
1778 / Raw(b"\xa5" * 100)
1781 self.send_and_expect_double_natted6(
1783 pkt_intra_epg_220_global * NUM_PKTS,
1792 self.vapi.nat44_ed_plugin_enable_disable(enable=0)
1793 self.vapi.nat66_plugin_enable_disable(enable=0)
1795 def wait_for_ep_timeout(
1796 self, sw_if_index=None, ip=None, mac=None, tep=None, n_tries=100, s_time=1
1798 # only learnt EP can timeout
1799 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
1800 flags = ep_flags.GBP_API_ENDPOINT_FLAG_LEARNT
1802 if not find_gbp_endpoint(self, sw_if_index, ip, mac, tep=tep, flags=flags):
1804 n_tries = n_tries - 1
1807 find_gbp_endpoint(self, sw_if_index, ip, mac, tep=tep, flags=flags)
1811 def test_gbp_learn_l2(self):
1812 """GBP L2 Endpoint Learning"""
1814 drop_no_contract = self.statistics.get_err_counter(
1815 "/err/gbp-policy-port/drop-no-contract"
1817 allow_intra_class = self.statistics.get_err_counter(
1818 "/err/gbp-policy-port/allow-intra-sclass"
1821 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
1823 {"mac": "00:00:11:11:11:01", "ip": "10.0.0.1", "ip6": "2001:10::2"},
1824 {"mac": "00:00:11:11:11:02", "ip": "10.0.0.2", "ip6": "2001:10::3"},
1830 gt4 = VppIpTable(self, 1)
1831 gt4.add_vpp_config()
1832 gt6 = VppIpTable(self, 1, is_ip6=True)
1833 gt6.add_vpp_config()
1835 rd1 = VppGbpRouteDomain(self, 1, 401, gt4, gt6)
1836 rd1.add_vpp_config()
1839 # Pg2 hosts the vxlan tunnel, hosts on pg2 to act as TEPs
1840 # Pg3 hosts the IP4 UU-flood VXLAN tunnel
1841 # Pg4 hosts the IP6 UU-flood VXLAN tunnel
1843 self.pg2.config_ip4()
1844 self.pg2.resolve_arp()
1845 self.pg2.generate_remote_hosts(4)
1846 self.pg2.configure_ipv4_neighbors()
1847 self.pg3.config_ip4()
1848 self.pg3.resolve_arp()
1849 self.pg4.config_ip4()
1850 self.pg4.resolve_arp()
1853 # Add a mcast destination VXLAN-GBP tunnel for B&M traffic
1855 tun_bm = VppVxlanGbpTunnel(
1856 self, self.pg4.local_ip4, "239.1.1.1", 88, mcast_itf=self.pg4
1858 tun_bm.add_vpp_config()
1861 # a GBP bridge domain with a BVI and a UU-flood interface
1863 bd1 = VppBridgeDomain(self, 1)
1864 bd1.add_vpp_config()
1865 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0, self.pg3, tun_bm)
1866 gbd1.add_vpp_config()
1868 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1869 self.logger.info(self.vapi.cli("sh gbp bridge"))
1871 # ... and has a /32 applied
1872 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
1873 ip_addr.add_vpp_config()
1876 # The Endpoint-group in which we are learning endpoints
1878 epg_220 = VppGbpEndpointGroup(
1888 VppGbpEndpointRetention(4),
1890 epg_220.add_vpp_config()
1891 epg_330 = VppGbpEndpointGroup(
1901 VppGbpEndpointRetention(4),
1903 epg_330.add_vpp_config()
1906 # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
1909 vx_tun_l2_1 = VppGbpVxlanTunnel(
1913 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L2,
1916 vx_tun_l2_1.add_vpp_config()
1919 # A static endpoint that the learnt endpoints are trying to
1922 ep = VppGbpEndpoint(
1934 self.assertTrue(find_route(self, ep.ip4, 32, table_id=1))
1936 # a packet with an sclass from an unknown EPG
1938 Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac)
1939 / IP(src=self.pg2.remote_hosts[0].ip4, dst=self.pg2.local_ip4)
1940 / UDP(sport=1234, dport=48879)
1941 / VXLAN(vni=99, gpid=88, flags=0x88)
1942 / Ether(src=learnt[0]["mac"], dst=ep.mac)
1943 / IP(src=learnt[0]["ip"], dst=ep.ip4)
1944 / UDP(sport=1234, dport=1234)
1945 / Raw(b"\xa5" * 100)
1948 self.send_and_assert_no_replies(self.pg2, p)
1950 self.logger.info(self.vapi.cli("sh error"))
1951 self.assert_error_counter_equal(
1952 "/err/gbp-policy-port/drop-no-contract", drop_no_contract + 1
1956 # we should not have learnt a new tunnel endpoint, since
1957 # the EPG was not learnt.
1961 find_vxlan_gbp_tunnel(
1962 self, self.pg2.local_ip4, self.pg2.remote_hosts[0].ip4, 99
1966 # ep is not learnt, because the EPG is unknown
1967 self.assertEqual(len(self.vapi.gbp_endpoint_dump()), 1)
1970 # Learn new EPs from IP packets
1972 for ii, l in enumerate(learnt):
1973 # a packet with an sclass from a known EPG
1974 # arriving on an unknown TEP
1976 Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac)
1977 / IP(src=self.pg2.remote_hosts[1].ip4, dst=self.pg2.local_ip4)
1978 / UDP(sport=1234, dport=48879)
1979 / VXLAN(vni=99, gpid=112, flags=0x88)
1980 / Ether(src=l["mac"], dst=ep.mac)
1981 / IP(src=l["ip"], dst=ep.ip4)
1982 / UDP(sport=1234, dport=1234)
1983 / Raw(b"\xa5" * 100)
1986 rx = self.send_and_expect(self.pg2, [p], self.pg0)
1989 tep1_sw_if_index = find_vxlan_gbp_tunnel(
1990 self, self.pg2.local_ip4, self.pg2.remote_hosts[1].ip4, 99
1992 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
1995 # the EP is learnt via the learnt TEP
1996 # both from its MAC and its IP
1999 find_gbp_endpoint(self, vx_tun_l2_1.sw_if_index, mac=l["mac"])
2002 find_gbp_endpoint(self, vx_tun_l2_1.sw_if_index, ip=l["ip"])
2005 self.assert_error_counter_equal(
2006 "/err/gbp-policy-port/allow-intra-sclass", allow_intra_class + 2
2009 self.logger.info(self.vapi.cli("show gbp endpoint"))
2010 self.logger.info(self.vapi.cli("show gbp vxlan"))
2011 self.logger.info(self.vapi.cli("show ip mfib"))
2014 # If we sleep for the threshold time, the learnt endpoints should
2018 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index, mac=l["mac"])
2021 # Learn new EPs from GARP packets received on the BD's mcast tunnel
2023 for ii, l in enumerate(learnt):
2024 # add some junk in the reserved field of the vxlan-header
2025 # next to the VNI. we should accept since reserved bits are
2028 Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac)
2029 / IP(src=self.pg2.remote_hosts[1].ip4, dst="239.1.1.1")
2030 / UDP(sport=1234, dport=48879)
2031 / VXLAN(vni=88, reserved2=0x80, gpid=112, flags=0x88)
2032 / Ether(src=l["mac"], dst="ff:ff:ff:ff:ff:ff")
2038 hwdst="ff:ff:ff:ff:ff:ff",
2042 rx = self.send_and_expect(self.pg4, [p], self.pg0)
2045 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2046 self, self.pg2.local_ip4, self.pg2.remote_hosts[1].ip4, 99
2048 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2051 # the EP is learnt via the learnt TEP
2052 # both from its MAC and its IP
2055 find_gbp_endpoint(self, vx_tun_l2_1.sw_if_index, mac=l["mac"])
2058 find_gbp_endpoint(self, vx_tun_l2_1.sw_if_index, ip=l["ip"])
2062 # wait for the learnt endpoints to age out
2065 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index, mac=l["mac"])
2068 # Learn new EPs from L2 packets
2070 for ii, l in enumerate(learnt):
2071 # a packet with an sclass from a known EPG
2072 # arriving on an unknown TEP
2074 Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac)
2075 / IP(src=self.pg2.remote_hosts[1].ip4, dst=self.pg2.local_ip4)
2076 / UDP(sport=1234, dport=48879)
2077 / VXLAN(vni=99, gpid=112, flags=0x88)
2078 / Ether(src=l["mac"], dst=ep.mac)
2079 / Raw(b"\xa5" * 100)
2082 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2085 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2086 self, self.pg2.local_ip4, self.pg2.remote_hosts[1].ip4, 99
2088 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2091 # the EP is learnt via the learnt TEP
2092 # both from its MAC and its IP
2095 find_gbp_endpoint(self, vx_tun_l2_1.sw_if_index, mac=l["mac"])
2098 self.logger.info(self.vapi.cli("show gbp endpoint"))
2099 self.logger.info(self.vapi.cli("show gbp vxlan"))
2100 self.logger.info(self.vapi.cli("show vxlan-gbp tunnel"))
2103 # wait for the learnt endpoints to age out
2106 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index, mac=l["mac"])
2109 # repeat. the do not learn bit is set so the EPs are not learnt
2112 # a packet with an sclass from a known EPG
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=0x88, gpflags="D")
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)
2128 find_gbp_endpoint(self, vx_tun_l2_1.sw_if_index, mac=l["mac"])
2135 # a packet with an sclass from a known EPG
2136 # set a reserved bit in addition to the G and I
2137 # reserved bits should not be checked on rx.
2139 Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac)
2140 / IP(src=self.pg2.remote_hosts[1].ip4, dst=self.pg2.local_ip4)
2141 / UDP(sport=1234, dport=48879)
2142 / VXLAN(vni=99, gpid=112, flags=0xC8)
2143 / Ether(src=l["mac"], dst=ep.mac)
2144 / IP(src=l["ip"], dst=ep.ip4)
2145 / UDP(sport=1234, dport=1234)
2146 / Raw(b"\xa5" * 100)
2149 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
2152 find_gbp_endpoint(self, vx_tun_l2_1.sw_if_index, mac=l["mac"])
2156 # Static EP replies to dynamics
2158 self.logger.info(self.vapi.cli("sh l2fib bd_id 1"))
2161 Ether(src=ep.mac, dst=l["mac"])
2162 / IP(dst=l["ip"], src=ep.ip4)
2163 / UDP(sport=1234, dport=1234)
2164 / Raw(b"\xa5" * 100)
2167 rxs = self.send_and_expect(self.pg0, p * 17, self.pg2)
2170 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2171 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2172 self.assertEqual(rx[UDP].dport, 48879)
2173 # the UDP source port is a random value for hashing
2174 self.assertEqual(rx[VXLAN].gpid, 112)
2175 self.assertEqual(rx[VXLAN].vni, 99)
2176 self.assertTrue(rx[VXLAN].flags.G)
2177 self.assertTrue(rx[VXLAN].flags.Instance)
2178 self.assertTrue(rx[VXLAN].gpflags.A)
2179 self.assertFalse(rx[VXLAN].gpflags.D)
2182 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index, mac=l["mac"])
2185 # repeat in the other EPG
2186 # there's no contract between 220 and 330, but the A-bit is set
2187 # so the packet is cleared for delivery
2190 # a packet with an sclass from a known EPG
2192 Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac)
2193 / IP(src=self.pg2.remote_hosts[1].ip4, dst=self.pg2.local_ip4)
2194 / UDP(sport=1234, dport=48879)
2195 / VXLAN(vni=99, gpid=113, flags=0x88, gpflags="A")
2196 / Ether(src=l["mac"], dst=ep.mac)
2197 / IP(src=l["ip"], dst=ep.ip4)
2198 / UDP(sport=1234, dport=1234)
2199 / Raw(b"\xa5" * 100)
2202 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
2205 find_gbp_endpoint(self, vx_tun_l2_1.sw_if_index, mac=l["mac"])
2209 # static EP cannot reach the learnt EPs since there is no contract
2210 # only test 1 EP as the others could timeout
2213 Ether(src=ep.mac, dst=l["mac"])
2214 / IP(dst=learnt[0]["ip"], src=ep.ip4)
2215 / UDP(sport=1234, dport=1234)
2216 / Raw(b"\xa5" * 100)
2219 self.send_and_assert_no_replies(self.pg0, [p])
2222 # refresh the entries after the check for no replies above
2225 # a packet with an sclass from a known EPG
2227 Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac)
2228 / IP(src=self.pg2.remote_hosts[1].ip4, dst=self.pg2.local_ip4)
2229 / UDP(sport=1234, dport=48879)
2230 / VXLAN(vni=99, gpid=113, flags=0x88, gpflags="A")
2231 / Ether(src=l["mac"], dst=ep.mac)
2232 / IP(src=l["ip"], dst=ep.ip4)
2233 / UDP(sport=1234, dport=1234)
2234 / Raw(b"\xa5" * 100)
2237 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
2240 find_gbp_endpoint(self, vx_tun_l2_1.sw_if_index, mac=l["mac"])
2244 # Add the contract so they can talk
2246 rule = AclRule(is_permit=1, proto=17)
2248 src_prefix=IPv6Network((0, 0)),
2249 dst_prefix=IPv6Network((0, 0)),
2253 acl = VppAcl(self, rules=[rule, rule2])
2254 acl.add_vpp_config()
2256 c1 = VppGbpContract(
2264 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2265 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2269 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2270 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2274 [ETH_P_IP, ETH_P_IPV6],
2280 Ether(src=ep.mac, dst=l["mac"])
2281 / IP(dst=l["ip"], src=ep.ip4)
2282 / UDP(sport=1234, dport=1234)
2283 / Raw(b"\xa5" * 100)
2286 self.send_and_expect(self.pg0, [p], self.pg2)
2289 # send UU packets from the local EP
2291 self.logger.info(self.vapi.cli("sh gbp bridge"))
2292 self.logger.info(self.vapi.cli("sh bridge-domain 1 detail"))
2294 Ether(src=ep.mac, dst="00:11:11:11:11:11")
2295 / IP(dst="10.0.0.133", src=ep.ip4)
2296 / UDP(sport=1234, dport=1234)
2297 / Raw(b"\xa5" * 100)
2299 rxs = self.send_and_expect(ep.itf, [p_uu], gbd1.uu_fwd)
2301 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2304 Ether(src=ep.mac, dst="ff:ff:ff:ff:ff:ff")
2305 / IP(dst="10.0.0.133", src=ep.ip4)
2306 / UDP(sport=1234, dport=1234)
2307 / Raw(b"\xa5" * 100)
2309 rxs = self.send_and_expect_only(ep.itf, [p_bm], tun_bm.mcast_itf)
2312 self.assertEqual(rx[IP].src, self.pg4.local_ip4)
2313 self.assertEqual(rx[IP].dst, "239.1.1.1")
2314 self.assertEqual(rx[UDP].dport, 48879)
2315 # the UDP source port is a random value for hashing
2316 self.assertEqual(rx[VXLAN].gpid, 112)
2317 self.assertEqual(rx[VXLAN].vni, 88)
2318 self.assertTrue(rx[VXLAN].flags.G)
2319 self.assertTrue(rx[VXLAN].flags.Instance)
2320 self.assertFalse(rx[VXLAN].gpflags.A)
2321 self.assertFalse(rx[VXLAN].gpflags.D)
2323 rule = AclRule(is_permit=1, proto=17)
2325 src_prefix=IPv6Network((0, 0)),
2326 dst_prefix=IPv6Network((0, 0)),
2330 acl = VppAcl(self, rules=[rule, rule2])
2331 acl.add_vpp_config()
2333 c2 = VppGbpContract(
2341 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2342 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2346 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2347 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2351 [ETH_P_IP, ETH_P_IPV6],
2356 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index, mac=l["mac"])
2358 # Check v6 Endpoints learning
2361 # a packet with an sclass from a known EPG
2363 Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac)
2364 / IP(src=self.pg2.remote_hosts[1].ip4, dst=self.pg2.local_ip4)
2365 / UDP(sport=1234, dport=48879)
2366 / VXLAN(vni=99, gpid=113, flags=0x88)
2367 / Ether(src=l["mac"], dst=ep.mac)
2368 / IPv6(src=l["ip6"], dst=ep.ip6)
2369 / UDP(sport=1234, dport=1234)
2370 / Raw(b"\xa5" * 100)
2373 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
2374 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
2379 vx_tun_l2_1.sw_if_index,
2381 tep=[self.pg2.local_ip4, self.pg2.remote_hosts[1].ip4],
2385 self.logger.info(self.vapi.cli("sh int"))
2386 self.logger.info(self.vapi.cli("sh vxlan-gbp tunnel"))
2387 self.logger.info(self.vapi.cli("sh gbp vxlan"))
2388 self.logger.info(self.vapi.cli("sh gbp endpoint"))
2389 self.logger.info(self.vapi.cli("sh gbp interface"))
2392 # EP moves to a different TEP
2395 # a packet with an sclass from a known EPG
2397 Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac)
2398 / IP(src=self.pg2.remote_hosts[2].ip4, dst=self.pg2.local_ip4)
2399 / UDP(sport=1234, dport=48879)
2400 / VXLAN(vni=99, gpid=113, flags=0x88)
2401 / Ether(src=l["mac"], dst=ep.mac)
2402 / IPv6(src=l["ip6"], dst=ep.ip6)
2403 / UDP(sport=1234, dport=1234)
2404 / Raw(b"\xa5" * 100)
2407 rx = self.send_and_expect(self.pg2, p * 1, self.pg0)
2408 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
2413 vx_tun_l2_1.sw_if_index,
2416 tep=[self.pg2.local_ip4, self.pg2.remote_hosts[2].ip4],
2421 # v6 remote EP reachability
2425 Ether(src=ep.mac, dst=l["mac"])
2426 / IPv6(dst=l["ip6"], src=ep.ip6)
2427 / UDP(sport=1234, dport=1234)
2428 / Raw(b"\xa5" * 100)
2431 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
2434 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2435 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[2].ip4)
2436 self.assertEqual(rx[UDP].dport, 48879)
2437 # the UDP source port is a random value for hashing
2438 self.assertEqual(rx[VXLAN].gpid, 112)
2439 self.assertEqual(rx[VXLAN].vni, 99)
2440 self.assertTrue(rx[VXLAN].flags.G)
2441 self.assertTrue(rx[VXLAN].flags.Instance)
2442 self.assertTrue(rx[VXLAN].gpflags.A)
2443 self.assertFalse(rx[VXLAN].gpflags.D)
2444 self.assertEqual(rx[IPv6].dst, l["ip6"])
2450 # a packet with an sclass from a known EPG
2452 Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac)
2453 / IP(src=self.pg2.remote_hosts[2].ip4, dst=self.pg2.local_ip4)
2454 / UDP(sport=1234, dport=48879)
2455 / VXLAN(vni=99, gpid=112, flags=0x88)
2456 / Ether(src=l["mac"], dst=ep.mac)
2457 / IPv6(src=l["ip6"], dst=ep.ip6)
2458 / UDP(sport=1234, dport=1234)
2459 / Raw(b"\xa5" * 100)
2462 rx = self.send_and_expect(self.pg2, p * 1, self.pg0)
2463 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
2468 vx_tun_l2_1.sw_if_index,
2471 tep=[self.pg2.local_ip4, self.pg2.remote_hosts[2].ip4],
2476 # check reachability and contract intra-epg
2478 allow_intra_class = self.statistics.get_err_counter(
2479 "/err/gbp-policy-mac/allow-intra-sclass"
2484 Ether(src=ep.mac, dst=l["mac"])
2485 / IPv6(dst=l["ip6"], src=ep.ip6)
2486 / UDP(sport=1234, dport=1234)
2487 / Raw(b"\xa5" * 100)
2490 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
2493 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2494 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[2].ip4)
2495 self.assertEqual(rx[UDP].dport, 48879)
2496 self.assertEqual(rx[VXLAN].gpid, 112)
2497 self.assertEqual(rx[VXLAN].vni, 99)
2498 self.assertTrue(rx[VXLAN].flags.G)
2499 self.assertTrue(rx[VXLAN].flags.Instance)
2500 self.assertTrue(rx[VXLAN].gpflags.A)
2501 self.assertFalse(rx[VXLAN].gpflags.D)
2502 self.assertEqual(rx[IPv6].dst, l["ip6"])
2504 allow_intra_class += NUM_PKTS
2506 self.assert_error_counter_equal(
2507 "/err/gbp-policy-mac/allow-intra-sclass", allow_intra_class
2514 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index, mac=l["mac"])
2515 self.pg2.unconfig_ip4()
2516 self.pg3.unconfig_ip4()
2517 self.pg4.unconfig_ip4()
2519 def test_gbp_contract(self):
2525 gt4 = VppIpTable(self, 0)
2526 gt4.add_vpp_config()
2527 gt6 = VppIpTable(self, 0, is_ip6=True)
2528 gt6.add_vpp_config()
2530 rd0 = VppGbpRouteDomain(self, 0, 400, gt4, gt6, None, None)
2532 rd0.add_vpp_config()
2537 bd1 = VppBridgeDomain(self, 1, arp_term=0)
2538 bd2 = VppBridgeDomain(self, 2, arp_term=0)
2540 bd1.add_vpp_config()
2541 bd2.add_vpp_config()
2543 gbd1 = VppGbpBridgeDomain(self, bd1, rd0, self.loop0)
2544 gbd2 = VppGbpBridgeDomain(self, bd2, rd0, self.loop1)
2546 gbd1.add_vpp_config()
2547 gbd2.add_vpp_config()
2550 # 3 EPGs, 2 of which share a BD.
2553 VppGbpEndpointGroup(
2564 VppGbpEndpointGroup(
2575 VppGbpEndpointGroup(
2588 # 4 end-points, 2 in the same subnet, 3 in the same BD
2634 # Config related to each of the EPGs
2637 # IP config on the BVI interfaces
2639 b4 = VppIpInterfaceBind(self, epg.bvi, epg.rd.t4).add_vpp_config()
2640 b6 = VppIpInterfaceBind(self, epg.bvi, epg.rd.t6).add_vpp_config()
2641 epg.bvi.set_mac(self.router_mac)
2643 if_ip4 = VppIpInterfaceAddress(
2644 self, epg.bvi, epg.bvi_ip4, 32, bind=b4
2646 if_ip6 = VppIpInterfaceAddress(
2647 self, epg.bvi, epg.bvi_ip6, 128, bind=b6
2650 # add the BD ARP termination entry for BVI IP
2651 epg.bd_arp_ip4 = VppBridgeDomainArpEntry(
2652 self, epg.bd.bd, str(self.router_mac), epg.bvi_ip4
2654 epg.bd_arp_ip4.add_vpp_config()
2657 epg.add_vpp_config()
2665 self.logger.info(self.vapi.cli("show gbp endpoint"))
2666 self.logger.info(self.vapi.cli("show interface"))
2667 self.logger.info(self.vapi.cli("show br"))
2670 # Intra epg allowed without contract
2672 pkt_intra_epg_220_to_220 = (
2673 Ether(src=self.pg0.remote_mac, dst=self.pg1.remote_mac)
2674 / IP(src=eps[0].ip4, dst=eps[1].ip4)
2675 / UDP(sport=1234, dport=1234)
2676 / Raw(b"\xa5" * 100)
2679 self.send_and_expect_bridged(self.pg0, pkt_intra_epg_220_to_220 * 65, self.pg1)
2681 pkt_intra_epg_220_to_220 = (
2682 Ether(src=self.pg0.remote_mac, dst=self.pg1.remote_mac)
2683 / IPv6(src=eps[0].ip6, dst=eps[1].ip6)
2684 / UDP(sport=1234, dport=1234)
2685 / Raw(b"\xa5" * 100)
2688 self.send_and_expect_bridged6(self.pg0, pkt_intra_epg_220_to_220 * 65, self.pg1)
2691 # Inter epg denied without contract
2693 pkt_inter_epg_220_to_221 = (
2694 Ether(src=self.pg0.remote_mac, dst=self.pg2.remote_mac)
2695 / IP(src=eps[0].ip4, dst=eps[2].ip4)
2696 / UDP(sport=1234, dport=1234)
2697 / Raw(b"\xa5" * 100)
2700 self.send_and_assert_no_replies(self.pg0, pkt_inter_epg_220_to_221)
2703 # A uni-directional contract from EPG 220 -> 221
2705 rule = AclRule(is_permit=1, proto=17)
2707 src_prefix=IPv6Network((0, 0)),
2708 dst_prefix=IPv6Network((0, 0)),
2712 rule3 = AclRule(is_permit=1, proto=1)
2713 acl = VppAcl(self, rules=[rule, rule2, rule3])
2714 acl.add_vpp_config()
2716 c1 = VppGbpContract(
2724 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2725 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2729 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2730 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2734 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2735 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2739 [ETH_P_IP, ETH_P_IPV6],
2743 self.send_and_expect_bridged(
2744 eps[0].itf, pkt_inter_epg_220_to_221 * 65, eps[2].itf
2747 pkt_inter_epg_220_to_222 = (
2748 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac))
2749 / IP(src=eps[0].ip4, dst=eps[3].ip4)
2750 / UDP(sport=1234, dport=1234)
2751 / Raw(b"\xa5" * 100)
2753 self.send_and_assert_no_replies(eps[0].itf, pkt_inter_epg_220_to_222 * 65)
2756 # ping router IP in different BD
2758 pkt_router_ping_220_to_221 = (
2759 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac))
2760 / IP(src=eps[0].ip4, dst=epgs[1].bvi_ip4)
2761 / ICMP(type="echo-request")
2764 self.send_and_expect(self.pg0, [pkt_router_ping_220_to_221], self.pg0)
2766 pkt_router_ping_220_to_221 = (
2767 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac))
2768 / IPv6(src=eps[0].ip6, dst=epgs[1].bvi_ip6)
2769 / ICMPv6EchoRequest()
2772 self.send_and_expect(self.pg0, [pkt_router_ping_220_to_221], self.pg0)
2775 # contract for the return direction
2777 c2 = VppGbpContract(
2785 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2786 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2790 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2791 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2795 [ETH_P_IP, ETH_P_IPV6],
2799 self.send_and_expect_bridged(
2800 eps[0].itf, pkt_inter_epg_220_to_221 * 65, eps[2].itf
2802 pkt_inter_epg_221_to_220 = (
2803 Ether(src=self.pg2.remote_mac, dst=self.pg0.remote_mac)
2804 / IP(src=eps[2].ip4, dst=eps[0].ip4)
2805 / UDP(sport=1234, dport=1234)
2806 / Raw(b"\xa5" * 100)
2808 self.send_and_expect_bridged(
2809 eps[2].itf, pkt_inter_epg_221_to_220 * 65, eps[0].itf
2811 pkt_inter_epg_221_to_220 = (
2812 Ether(src=self.pg2.remote_mac, dst=str(self.router_mac))
2813 / IP(src=eps[2].ip4, dst=eps[0].ip4)
2814 / UDP(sport=1234, dport=1234)
2815 / Raw(b"\xa5" * 100)
2817 self.send_and_expect_routed(
2818 eps[2].itf, pkt_inter_epg_221_to_220 * 65, eps[0].itf, str(self.router_mac)
2820 pkt_inter_epg_221_to_220 = (
2821 Ether(src=self.pg2.remote_mac, dst=str(self.router_mac))
2822 / IPv6(src=eps[2].ip6, dst=eps[0].ip6)
2823 / UDP(sport=1234, dport=1234)
2824 / Raw(b"\xa5" * 100)
2826 self.send_and_expect_routed6(
2827 eps[2].itf, pkt_inter_epg_221_to_220 * 65, eps[0].itf, str(self.router_mac)
2831 # contract between 220 and 222 uni-direction
2833 c3 = VppGbpContract(
2841 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2842 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2846 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2847 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2851 [ETH_P_IP, ETH_P_IPV6],
2855 self.send_and_expect(eps[0].itf, pkt_inter_epg_220_to_222 * 65, eps[3].itf)
2857 c3.remove_vpp_config()
2858 c1.remove_vpp_config()
2859 c2.remove_vpp_config()
2860 acl.remove_vpp_config()
2862 def test_gbp_bd_drop_flags(self):
2863 """GBP BD drop flags"""
2868 gt4 = VppIpTable(self, 1)
2869 gt4.add_vpp_config()
2870 gt6 = VppIpTable(self, 1, is_ip6=True)
2871 gt6.add_vpp_config()
2873 rd1 = VppGbpRouteDomain(self, 1, 401, gt4, gt6)
2874 rd1.add_vpp_config()
2877 # a GBP bridge domain with a BVI only
2879 bd1 = VppBridgeDomain(self, 1)
2880 bd1.add_vpp_config()
2882 gbd1 = VppGbpBridgeDomain(
2883 self, bd1, rd1, self.loop0, None, None, uu_drop=True, bm_drop=True
2885 gbd1.add_vpp_config()
2887 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2888 self.logger.info(self.vapi.cli("sh gbp bridge"))
2890 # ... and has a /32 applied
2891 ip_addr = VppIpInterfaceAddress(
2892 self, gbd1.bvi, "10.0.0.128", 32
2896 # The Endpoint-group
2898 epg_220 = VppGbpEndpointGroup(
2908 VppGbpEndpointRetention(3),
2910 epg_220.add_vpp_config()
2912 ep = VppGbpEndpoint(
2925 # send UU/BM packet from the local EP with UU drop and BM drop enabled
2928 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2929 self.logger.info(self.vapi.cli("sh gbp bridge"))
2931 Ether(src=ep.mac, dst="00:11:11:11:11:11")
2932 / IP(dst="10.0.0.133", src=ep.ip4)
2933 / UDP(sport=1234, dport=1234)
2934 / Raw(b"\xa5" * 100)
2936 self.send_and_assert_no_replies(ep.itf, [p_uu])
2939 Ether(src=ep.mac, dst="ff:ff:ff:ff:ff:ff")
2940 / IP(dst="10.0.0.133", src=ep.ip4)
2941 / UDP(sport=1234, dport=1234)
2942 / Raw(b"\xa5" * 100)
2944 self.send_and_assert_no_replies(ep.itf, [p_bm])
2946 self.pg3.unconfig_ip4()
2948 self.logger.info(self.vapi.cli("sh int"))
2950 def test_gbp_bd_arp_flags(self):
2951 """GBP BD arp flags"""
2956 gt4 = VppIpTable(self, 1)
2957 gt4.add_vpp_config()
2958 gt6 = VppIpTable(self, 1, is_ip6=True)
2959 gt6.add_vpp_config()
2961 rd1 = VppGbpRouteDomain(self, 1, 401, gt4, gt6)
2962 rd1.add_vpp_config()
2965 # Pg4 hosts the IP6 UU-flood VXLAN tunnel
2967 self.pg4.config_ip4()
2968 self.pg4.resolve_arp()
2971 # Add a mcast destination VXLAN-GBP tunnel for B&M traffic
2973 tun_uu = VppVxlanGbpTunnel(
2974 self, self.pg4.local_ip4, "239.1.1.1", 88, mcast_itf=self.pg4
2976 tun_uu.add_vpp_config()
2979 # a GBP bridge domain with a BVI and a UU-flood interface
2981 bd1 = VppBridgeDomain(self, 1)
2982 bd1.add_vpp_config()
2984 gbd1 = VppGbpBridgeDomain(
2985 self, bd1, rd1, self.loop0, tun_uu, None, ucast_arp=True
2987 gbd1.add_vpp_config()
2989 # ... and has a /32 applied
2990 ip_addr = VppIpInterfaceAddress(
2991 self, gbd1.bvi, "10.0.0.128", 32
2995 # The Endpoint-group
2997 epg_220 = VppGbpEndpointGroup(
3007 VppGbpEndpointRetention(2),
3009 epg_220.add_vpp_config()
3011 ep = VppGbpEndpoint(
3024 # send ARP packet from the local EP expect it on the uu interface
3026 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
3027 self.logger.info(self.vapi.cli("sh gbp bridge"))
3028 p_arp = Ether(src=ep.mac, dst="ff:ff:ff:ff:ff:ff") / ARP(
3033 hwdst="ff:ff:ff:ff:ff:ff",
3035 self.send_and_expect(ep.itf, [p_arp], self.pg4)
3037 self.pg4.unconfig_ip4()
3039 def test_gbp_learn_vlan_l2(self):
3040 """GBP L2 Endpoint w/ VLANs"""
3042 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
3044 {"mac": "00:00:11:11:11:01", "ip": "10.0.0.1", "ip6": "2001:10::2"},
3045 {"mac": "00:00:11:11:11:02", "ip": "10.0.0.2", "ip6": "2001:10::3"},
3051 gt4 = VppIpTable(self, 1)
3052 gt4.add_vpp_config()
3053 gt6 = VppIpTable(self, 1, is_ip6=True)
3054 gt6.add_vpp_config()
3056 rd1 = VppGbpRouteDomain(self, 1, 401, gt4, gt6)
3057 rd1.add_vpp_config()
3060 # Pg2 hosts the vxlan tunnel, hosts on pg2 to act as TEPs
3062 self.pg2.config_ip4()
3063 self.pg2.resolve_arp()
3064 self.pg2.generate_remote_hosts(4)
3065 self.pg2.configure_ipv4_neighbors()
3066 self.pg3.config_ip4()
3067 self.pg3.resolve_arp()
3070 # The EP will be on a vlan sub-interface
3072 vlan_11 = VppDot1QSubint(self, self.pg0, 11)
3074 self.vapi.l2_interface_vlan_tag_rewrite(
3075 sw_if_index=vlan_11.sw_if_index, vtr_op=L2_VTR_OP.L2_POP_1, push_dot1q=11
3078 bd_uu_fwd = VppVxlanGbpTunnel(
3079 self, self.pg3.local_ip4, self.pg3.remote_ip4, 116
3081 bd_uu_fwd.add_vpp_config()
3084 # a GBP bridge domain with a BVI and a UU-flood interface
3085 # The BD is marked as do not learn, so no endpoints are ever
3086 # learnt in this BD.
3088 bd1 = VppBridgeDomain(self, 1)
3089 bd1.add_vpp_config()
3090 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0, bd_uu_fwd, learn=False)
3091 gbd1.add_vpp_config()
3093 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
3094 self.logger.info(self.vapi.cli("sh gbp bridge"))
3096 # ... and has a /32 applied
3097 ip_addr = VppIpInterfaceAddress(
3098 self, gbd1.bvi, "10.0.0.128", 32
3102 # The Endpoint-group in which we are learning endpoints
3104 epg_220 = VppGbpEndpointGroup(
3114 VppGbpEndpointRetention(4),
3116 epg_220.add_vpp_config()
3119 # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
3122 vx_tun_l2_1 = VppGbpVxlanTunnel(
3126 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L2,
3129 vx_tun_l2_1.add_vpp_config()
3132 # A static endpoint that the learnt endpoints are trying to
3135 ep = VppGbpEndpoint(
3147 self.assertTrue(find_route(self, ep.ip4, 32, table_id=1))
3150 # Send to the static EP
3152 for ii, l in enumerate(learnt):
3153 # a packet with an sclass from a known EPG
3154 # arriving on an unknown TEP
3156 Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac)
3157 / IP(src=self.pg2.remote_hosts[1].ip4, dst=self.pg2.local_ip4)
3158 / UDP(sport=1234, dport=48879)
3159 / VXLAN(vni=99, gpid=441, flags=0x88)
3160 / Ether(src=l["mac"], dst=ep.mac)
3161 / IP(src=l["ip"], dst=ep.ip4)
3162 / UDP(sport=1234, dport=1234)
3163 / Raw(b"\xa5" * 100)
3166 rxs = self.send_and_expect(self.pg2, [p], self.pg0)
3169 # packet to EP has the EP's vlan tag
3172 self.assertEqual(rx[Dot1Q].vlan, 11)
3175 # the EP is not learnt since the BD setting prevents it
3179 find_gbp_endpoint(self, vx_tun_l2_1.sw_if_index, mac=l["mac"])
3183 find_vxlan_gbp_tunnel(
3184 self, self.pg2.local_ip4, self.pg2.remote_hosts[1].ip4, 99
3188 self.assertEqual(len(self.vapi.gbp_endpoint_dump()), 1)
3192 # we didn't learn the remotes so they are sent to the UU-fwd
3196 Ether(src=ep.mac, dst=l["mac"])
3198 / IP(dst=l["ip"], src=ep.ip4)
3199 / UDP(sport=1234, dport=1234)
3200 / Raw(b"\xa5" * 100)
3203 rxs = self.send_and_expect(self.pg0, p * 17, self.pg3)
3206 self.assertEqual(rx[IP].src, self.pg3.local_ip4)
3207 self.assertEqual(rx[IP].dst, self.pg3.remote_ip4)
3208 self.assertEqual(rx[UDP].dport, 48879)
3209 # the UDP source port is a random value for hashing
3210 self.assertEqual(rx[VXLAN].gpid, 441)
3211 self.assertEqual(rx[VXLAN].vni, 116)
3212 self.assertTrue(rx[VXLAN].flags.G)
3213 self.assertTrue(rx[VXLAN].flags.Instance)
3214 self.assertFalse(rx[VXLAN].gpflags.A)
3215 self.assertFalse(rx[VXLAN].gpflags.D)
3217 self.pg2.unconfig_ip4()
3218 self.pg3.unconfig_ip4()
3220 def test_gbp_learn_l3(self):
3221 """GBP L3 Endpoint Learning"""
3223 self.vapi.cli("set logging class gbp level debug")
3225 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
3226 routed_dst_mac = "00:0c:0c:0c:0c:0c"
3227 routed_src_mac = "00:22:bd:f8:19:ff"
3230 {"mac": "00:00:11:11:11:02", "ip": "10.0.1.2", "ip6": "2001:10::2"},
3231 {"mac": "00:00:11:11:11:03", "ip": "10.0.1.3", "ip6": "2001:10::3"},
3237 t4 = VppIpTable(self, 1)
3239 t6 = VppIpTable(self, 1, True)
3242 tun_ip4_uu = VppVxlanGbpTunnel(
3243 self, self.pg4.local_ip4, self.pg4.remote_ip4, 114
3245 tun_ip6_uu = VppVxlanGbpTunnel(
3246 self, self.pg4.local_ip4, self.pg4.remote_ip4, 116
3248 tun_ip4_uu.add_vpp_config()
3249 tun_ip6_uu.add_vpp_config()
3251 rd1 = VppGbpRouteDomain(self, 2, 401, t4, t6, tun_ip4_uu, tun_ip6_uu)
3252 rd1.add_vpp_config()
3254 self.loop0.set_mac(self.router_mac)
3257 # Bind the BVI to the RD
3259 b4 = VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
3260 b6 = VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
3263 # Pg2 hosts the vxlan tunnel
3264 # hosts on pg2 to act as TEPs
3268 self.pg2.config_ip4()
3269 self.pg2.resolve_arp()
3270 self.pg2.generate_remote_hosts(4)
3271 self.pg2.configure_ipv4_neighbors()
3272 self.pg3.config_ip4()
3273 self.pg3.resolve_arp()
3274 self.pg4.config_ip4()
3275 self.pg4.resolve_arp()
3278 # a GBP bridge domain with a BVI and a UU-flood interface
3280 bd1 = VppBridgeDomain(self, 1)
3281 bd1.add_vpp_config()
3282 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0, self.pg3)
3283 gbd1.add_vpp_config()
3285 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
3286 self.logger.info(self.vapi.cli("sh gbp bridge"))
3287 self.logger.info(self.vapi.cli("sh gbp route"))
3289 # ... and has a /32 and /128 applied
3290 ip4_addr = VppIpInterfaceAddress(
3291 self, gbd1.bvi, "10.0.0.128", 32, bind=b4
3293 ip6_addr = VppIpInterfaceAddress(
3294 self, gbd1.bvi, "2001:10::128", 128, bind=b6
3298 # The Endpoint-group in which we are learning endpoints
3300 epg_220 = VppGbpEndpointGroup(
3310 VppGbpEndpointRetention(4),
3312 epg_220.add_vpp_config()
3315 # The VXLAN GBP tunnel is in L3 mode with learning enabled
3317 vx_tun_l3 = VppGbpVxlanTunnel(
3321 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
3324 vx_tun_l3.add_vpp_config()
3327 # A static endpoint that the learnt endpoints are trying to
3330 ep = VppGbpEndpoint(
3343 # learn some remote IPv4 EPs
3345 for ii, l in enumerate(learnt):
3346 # a packet with an sclass from a known EPG
3347 # arriving on an unknown TEP
3349 Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac)
3350 / IP(src=self.pg2.remote_hosts[1].ip4, dst=self.pg2.local_ip4)
3351 / UDP(sport=1234, dport=48879)
3352 / VXLAN(vni=101, gpid=441, flags=0x88)
3353 / Ether(src=l["mac"], dst="00:00:00:11:11:11")
3354 / IP(src=l["ip"], dst=ep.ip4)
3355 / UDP(sport=1234, dport=1234)
3356 / Raw(b"\xa5" * 100)
3359 rx = self.send_and_expect(self.pg2, [p], self.pg0)
3362 tep1_sw_if_index = find_vxlan_gbp_tunnel(
3363 self, self.pg2.local_ip4, self.pg2.remote_hosts[1].ip4, vx_tun_l3.vni
3365 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
3367 # endpoint learnt via the parent GBP-vxlan interface
3368 self.assertTrue(find_gbp_endpoint(self, vx_tun_l3._sw_if_index, ip=l["ip"]))
3371 # Static IPv4 EP replies to learnt
3375 Ether(src=ep.mac, dst=self.loop0.local_mac)
3376 / IP(dst=l["ip"], src=ep.ip4)
3377 / UDP(sport=1234, dport=1234)
3378 / Raw(b"\xa5" * 100)
3381 rxs = self.send_and_expect(self.pg0, p * 1, self.pg2)
3384 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
3385 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
3386 self.assertEqual(rx[UDP].dport, 48879)
3387 # the UDP source port is a random value for hashing
3388 self.assertEqual(rx[VXLAN].gpid, 441)
3389 self.assertEqual(rx[VXLAN].vni, 101)
3390 self.assertTrue(rx[VXLAN].flags.G)
3391 self.assertTrue(rx[VXLAN].flags.Instance)
3392 self.assertTrue(rx[VXLAN].gpflags.A)
3393 self.assertFalse(rx[VXLAN].gpflags.D)
3395 inner = rx[VXLAN].payload
3397 self.assertEqual(inner[Ether].src, routed_src_mac)
3398 self.assertEqual(inner[Ether].dst, routed_dst_mac)
3399 self.assertEqual(inner[IP].src, ep.ip4)
3400 self.assertEqual(inner[IP].dst, l["ip"])
3403 self.assertFalse(find_gbp_endpoint(self, tep1_sw_if_index, ip=l["ip"]))
3406 # learn some remote IPv6 EPs
3408 for ii, l in enumerate(learnt):
3409 # a packet with an sclass from a known EPG
3410 # arriving on an unknown TEP
3412 Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac)
3413 / IP(src=self.pg2.remote_hosts[1].ip4, dst=self.pg2.local_ip4)
3414 / UDP(sport=1234, dport=48879)
3415 / VXLAN(vni=101, gpid=441, flags=0x88)
3416 / Ether(src=l["mac"], dst="00:00:00:11:11:11")
3417 / IPv6(src=l["ip6"], dst=ep.ip6)
3418 / UDP(sport=1234, dport=1234)
3419 / Raw(b"\xa5" * 100)
3422 rx = self.send_and_expect(self.pg2, [p], self.pg0)
3425 tep1_sw_if_index = find_vxlan_gbp_tunnel(
3426 self, self.pg2.local_ip4, self.pg2.remote_hosts[1].ip4, vx_tun_l3.vni
3428 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
3430 self.logger.info(self.vapi.cli("show gbp bridge"))
3431 self.logger.info(self.vapi.cli("show vxlan-gbp tunnel"))
3432 self.logger.info(self.vapi.cli("show gbp vxlan"))
3433 self.logger.info(self.vapi.cli("show int addr"))
3435 # endpoint learnt via the TEP
3436 self.assertTrue(find_gbp_endpoint(self, ip=l["ip6"]))
3438 self.logger.info(self.vapi.cli("show gbp endpoint"))
3439 self.logger.info(self.vapi.cli("show ip fib index 1 %s" % l["ip"]))
3442 # Static EP replies to learnt
3446 Ether(src=ep.mac, dst=self.loop0.local_mac)
3447 / IPv6(dst=l["ip6"], src=ep.ip6)
3448 / UDP(sport=1234, dport=1234)
3449 / Raw(b"\xa5" * 100)
3452 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
3455 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
3456 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
3457 self.assertEqual(rx[UDP].dport, 48879)
3458 # the UDP source port is a random value for hashing
3459 self.assertEqual(rx[VXLAN].gpid, 441)
3460 self.assertEqual(rx[VXLAN].vni, 101)
3461 self.assertTrue(rx[VXLAN].flags.G)
3462 self.assertTrue(rx[VXLAN].flags.Instance)
3463 self.assertTrue(rx[VXLAN].gpflags.A)
3464 self.assertFalse(rx[VXLAN].gpflags.D)
3466 inner = rx[VXLAN].payload
3468 self.assertEqual(inner[Ether].src, routed_src_mac)
3469 self.assertEqual(inner[Ether].dst, routed_dst_mac)
3470 self.assertEqual(inner[IPv6].src, ep.ip6)
3471 self.assertEqual(inner[IPv6].dst, l["ip6"])
3473 self.logger.info(self.vapi.cli("sh gbp endpoint"))
3475 self.wait_for_ep_timeout(ip=l["ip"])
3478 # Static sends to unknown EP with no route
3481 Ether(src=ep.mac, dst=self.loop0.local_mac)
3482 / IP(dst="10.0.0.99", src=ep.ip4)
3483 / UDP(sport=1234, dport=1234)
3484 / Raw(b"\xa5" * 100)
3487 self.send_and_assert_no_replies(self.pg0, [p])
3490 # Add a route to static EP's v4 and v6 subnet
3492 se_10_24 = VppGbpSubnet(
3497 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT,
3499 se_10_24.add_vpp_config()
3502 # static pings router
3505 Ether(src=ep.mac, dst=self.loop0.local_mac)
3506 / IP(dst=epg_220.bvi_ip4, src=ep.ip4)
3507 / UDP(sport=1234, dport=1234)
3508 / Raw(b"\xa5" * 100)
3511 self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg0)
3514 Ether(src=ep.mac, dst=self.loop0.local_mac)
3515 / IPv6(dst=epg_220.bvi_ip6, src=ep.ip6)
3516 / UDP(sport=1234, dport=1234)
3517 / Raw(b"\xa5" * 100)
3520 self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg0)
3523 # packets to address in the subnet are sent on the uu-fwd
3526 Ether(src=ep.mac, dst=self.loop0.local_mac)
3527 / IP(dst="10.0.0.99", src=ep.ip4)
3528 / UDP(sport=1234, dport=1234)
3529 / Raw(b"\xa5" * 100)
3532 rxs = self.send_and_expect(self.pg0, [p], self.pg4)
3534 self.assertEqual(rx[IP].src, self.pg4.local_ip4)
3535 self.assertEqual(rx[IP].dst, self.pg4.remote_ip4)
3536 self.assertEqual(rx[UDP].dport, 48879)
3537 # the UDP source port is a random value for hashing
3538 self.assertEqual(rx[VXLAN].gpid, 441)
3539 self.assertEqual(rx[VXLAN].vni, 114)
3540 self.assertTrue(rx[VXLAN].flags.G)
3541 self.assertTrue(rx[VXLAN].flags.Instance)
3542 # policy is not applied to packets sent to the uu-fwd interfaces
3543 self.assertFalse(rx[VXLAN].gpflags.A)
3544 self.assertFalse(rx[VXLAN].gpflags.D)
3547 # learn some remote IPv4 EPs
3549 for ii, l in enumerate(learnt):
3550 # a packet with an sclass from a known EPG
3551 # arriving on an unknown TEP
3553 Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac)
3554 / IP(src=self.pg2.remote_hosts[2].ip4, dst=self.pg2.local_ip4)
3555 / UDP(sport=1234, dport=48879)
3556 / VXLAN(vni=101, gpid=441, flags=0x88)
3557 / Ether(src=l["mac"], dst="00:00:00:11:11:11")
3558 / IP(src=l["ip"], dst=ep.ip4)
3559 / UDP(sport=1234, dport=1234)
3560 / Raw(b"\xa5" * 100)
3563 rx = self.send_and_expect(self.pg2, [p], self.pg0)
3566 tep1_sw_if_index = find_vxlan_gbp_tunnel(
3567 self, self.pg2.local_ip4, self.pg2.remote_hosts[2].ip4, vx_tun_l3.vni
3569 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
3571 # endpoint learnt via the parent GBP-vxlan interface
3572 self.assertTrue(find_gbp_endpoint(self, vx_tun_l3._sw_if_index, ip=l["ip"]))
3575 # Add a remote endpoint from the API
3577 rep_88 = VppGbpEndpoint(
3586 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
3588 self.pg2.remote_hosts[2].ip4,
3591 rep_88.add_vpp_config()
3594 # Add a remote endpoint from the API that matches an existing one
3595 # this is a lower priority, hence the packet is sent to the DP leanrt
3598 rep_2 = VppGbpEndpoint(
3607 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
3609 self.pg2.remote_hosts[1].ip4,
3612 rep_2.add_vpp_config()
3615 # Add a route to the learned EP's v4 subnet
3616 # packets should be send on the v4/v6 uu=fwd interface resp.
3618 se_10_1_24 = VppGbpSubnet(
3623 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT,
3625 se_10_1_24.add_vpp_config()
3627 self.logger.info(self.vapi.cli("show gbp endpoint"))
3629 ips = ["10.0.0.88", learnt[0]["ip"]]
3632 Ether(src=ep.mac, dst=self.loop0.local_mac)
3633 / IP(dst=ip, src=ep.ip4)
3634 / UDP(sport=1234, dport=1234)
3635 / Raw(b"\xa5" * 100)
3638 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
3641 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
3642 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[2].ip4)
3643 self.assertEqual(rx[UDP].dport, 48879)
3644 # the UDP source port is a random value for hashing
3645 self.assertEqual(rx[VXLAN].gpid, 441)
3646 self.assertEqual(rx[VXLAN].vni, 101)
3647 self.assertTrue(rx[VXLAN].flags.G)
3648 self.assertTrue(rx[VXLAN].flags.Instance)
3649 self.assertTrue(rx[VXLAN].gpflags.A)
3650 self.assertFalse(rx[VXLAN].gpflags.D)
3652 inner = rx[VXLAN].payload
3654 self.assertEqual(inner[Ether].src, routed_src_mac)
3655 self.assertEqual(inner[Ether].dst, routed_dst_mac)
3656 self.assertEqual(inner[IP].src, ep.ip4)
3657 self.assertEqual(inner[IP].dst, ip)
3660 # remove the API remote EPs, only API sourced is gone, the DP
3661 # learnt one remains
3663 rep_88.remove_vpp_config()
3664 rep_2.remove_vpp_config()
3666 self.assertTrue(find_gbp_endpoint(self, ip=rep_2.ip4))
3669 Ether(src=ep.mac, dst=self.loop0.local_mac)
3670 / IP(src=ep.ip4, dst=rep_2.ip4)
3671 / UDP(sport=1234, dport=1234)
3672 / Raw(b"\xa5" * 100)
3674 rxs = self.send_and_expect(self.pg0, [p], self.pg2)
3676 self.assertFalse(find_gbp_endpoint(self, ip=rep_88.ip4))
3679 Ether(src=ep.mac, dst=self.loop0.local_mac)
3680 / IP(src=ep.ip4, dst=rep_88.ip4)
3681 / UDP(sport=1234, dport=1234)
3682 / Raw(b"\xa5" * 100)
3684 rxs = self.send_and_expect(self.pg0, [p], self.pg4)
3687 # to appease the testcase we cannot have the registered EP still
3688 # present (because it's DP learnt) when the TC ends so wait until
3691 self.wait_for_ep_timeout(ip=rep_88.ip4)
3692 self.wait_for_ep_timeout(ip=rep_2.ip4)
3695 # Same as above, learn a remote EP via CP and DP
3696 # this time remove the DP one first. expect the CP data to remain
3698 rep_3 = VppGbpEndpoint(
3707 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
3709 self.pg2.remote_hosts[1].ip4,
3712 rep_3.add_vpp_config()
3715 Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac)
3716 / IP(src=self.pg2.remote_hosts[2].ip4, dst=self.pg2.local_ip4)
3717 / UDP(sport=1234, dport=48879)
3718 / VXLAN(vni=101, gpid=441, flags=0x88)
3719 / Ether(src=l["mac"], dst="00:00:00:11:11:11")
3720 / IP(src="10.0.1.4", dst=ep.ip4)
3721 / UDP(sport=1234, dport=1234)
3722 / Raw(b"\xa5" * 100)
3724 rxs = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
3729 vx_tun_l3._sw_if_index,
3731 tep=[self.pg2.local_ip4, self.pg2.remote_hosts[2].ip4],
3736 Ether(src=ep.mac, dst=self.loop0.local_mac)
3737 / IP(dst="10.0.1.4", src=ep.ip4)
3738 / UDP(sport=1234, dport=1234)
3739 / Raw(b"\xa5" * 100)
3741 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
3743 # host 2 is the DP learned TEP
3745 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
3746 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[2].ip4)
3748 self.wait_for_ep_timeout(
3749 ip=rep_3.ip4, tep=[self.pg2.local_ip4, self.pg2.remote_hosts[2].ip4]
3752 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
3754 # host 1 is the CP learned TEP
3756 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
3757 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
3760 # shutdown with learnt endpoint present
3763 Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac)
3764 / IP(src=self.pg2.remote_hosts[1].ip4, dst=self.pg2.local_ip4)
3765 / UDP(sport=1234, dport=48879)
3766 / VXLAN(vni=101, gpid=441, flags=0x88)
3767 / Ether(src=l["mac"], dst="00:00:00:11:11:11")
3768 / IP(src=learnt[1]["ip"], dst=ep.ip4)
3769 / UDP(sport=1234, dport=1234)
3770 / Raw(b"\xa5" * 100)
3773 rx = self.send_and_expect(self.pg2, [p], self.pg0)
3775 # endpoint learnt via the parent GBP-vxlan interface
3776 self.assertTrue(find_gbp_endpoint(self, vx_tun_l3._sw_if_index, ip=l["ip"]))
3780 # remote endpoint becomes local
3782 self.pg2.unconfig_ip4()
3783 self.pg3.unconfig_ip4()
3784 self.pg4.unconfig_ip4()
3786 def test_gbp_redirect(self):
3787 """GBP Endpoint Redirect"""
3789 self.vapi.cli("set logging class gbp level debug")
3791 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
3792 routed_dst_mac = "00:0c:0c:0c:0c:0c"
3793 routed_src_mac = "00:22:bd:f8:19:ff"
3796 {"mac": "00:00:11:11:11:02", "ip": "10.0.1.2", "ip6": "2001:10::2"},
3797 {"mac": "00:00:11:11:11:03", "ip": "10.0.1.3", "ip6": "2001:10::3"},
3803 t4 = VppIpTable(self, 1)
3805 t6 = VppIpTable(self, 1, True)
3808 rd1 = VppGbpRouteDomain(self, 2, 402, t4, t6)
3809 rd1.add_vpp_config()
3811 self.loop0.set_mac(self.router_mac)
3814 # Bind the BVI to the RD
3816 b_ip4 = VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
3817 b_ip6 = VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
3820 # Pg7 hosts a BD's UU-fwd
3822 self.pg7.config_ip4()
3823 self.pg7.resolve_arp()
3826 # a GBP bridge domains for the EPs
3828 bd1 = VppBridgeDomain(self, 1)
3829 bd1.add_vpp_config()
3830 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0)
3831 gbd1.add_vpp_config()
3833 bd2 = VppBridgeDomain(self, 2)
3834 bd2.add_vpp_config()
3835 gbd2 = VppGbpBridgeDomain(self, bd2, rd1, self.loop1)
3836 gbd2.add_vpp_config()
3838 # ... and has a /32 and /128 applied
3839 ip4_addr = VppIpInterfaceAddress(
3840 self, gbd1.bvi, "10.0.0.128", 32, bind=b_ip4
3842 ip6_addr = VppIpInterfaceAddress(
3843 self, gbd1.bvi, "2001:10::128", 128, bind=b_ip6
3845 ip4_addr = VppIpInterfaceAddress(
3846 self, gbd2.bvi, "10.0.1.128", 32
3848 ip6_addr = VppIpInterfaceAddress(
3849 self, gbd2.bvi, "2001:11::128", 128
3853 # The Endpoint-groups in which we are learning endpoints
3855 epg_220 = VppGbpEndpointGroup(
3865 VppGbpEndpointRetention(60),
3867 epg_220.add_vpp_config()
3868 epg_221 = VppGbpEndpointGroup(
3878 VppGbpEndpointRetention(60),
3880 epg_221.add_vpp_config()
3881 epg_222 = VppGbpEndpointGroup(
3891 VppGbpEndpointRetention(60),
3893 epg_222.add_vpp_config()
3896 # a GBP bridge domains for the SEPs
3898 bd_uu1 = VppVxlanGbpTunnel(self, self.pg7.local_ip4, self.pg7.remote_ip4, 116)
3899 bd_uu1.add_vpp_config()
3900 bd_uu2 = VppVxlanGbpTunnel(self, self.pg7.local_ip4, self.pg7.remote_ip4, 117)
3901 bd_uu2.add_vpp_config()
3903 bd3 = VppBridgeDomain(self, 3)
3904 bd3.add_vpp_config()
3905 gbd3 = VppGbpBridgeDomain(self, bd3, rd1, self.loop2, bd_uu1, learn=False)
3906 gbd3.add_vpp_config()
3907 bd4 = VppBridgeDomain(self, 4)
3908 bd4.add_vpp_config()
3909 gbd4 = VppGbpBridgeDomain(self, bd4, rd1, self.loop3, bd_uu2, learn=False)
3910 gbd4.add_vpp_config()
3913 # EPGs in which the service endpoints exist
3915 epg_320 = VppGbpEndpointGroup(
3925 VppGbpEndpointRetention(60),
3927 epg_320.add_vpp_config()
3928 epg_321 = VppGbpEndpointGroup(
3938 VppGbpEndpointRetention(60),
3940 epg_321.add_vpp_config()
3943 # three local endpoints
3945 ep1 = VppGbpEndpoint(
3955 ep1.add_vpp_config()
3956 ep2 = VppGbpEndpoint(
3966 ep2.add_vpp_config()
3967 ep3 = VppGbpEndpoint(
3977 ep3.add_vpp_config()
3982 sep1 = VppGbpEndpoint(
3992 sep1.add_vpp_config()
3993 sep2 = VppGbpEndpoint(
4003 sep2.add_vpp_config()
4004 sep3 = VppGbpEndpoint(
4014 sep3.add_vpp_config()
4015 # this EP is not installed immediately
4016 sep4 = VppGbpEndpoint(
4028 # an L2 switch packet between local EPs in different EPGs
4029 # different dest ports on each so the are LB hashed differently
4033 Ether(src=ep1.mac, dst=ep3.mac)
4034 / IP(src=ep1.ip4, dst=ep3.ip4)
4035 / UDP(sport=1234, dport=1234)
4036 / Raw(b"\xa5" * 100)
4039 Ether(src=ep3.mac, dst=ep1.mac)
4040 / IP(src=ep3.ip4, dst=ep1.ip4)
4041 / UDP(sport=1234, dport=1234)
4042 / Raw(b"\xa5" * 100)
4047 Ether(src=ep1.mac, dst=ep3.mac)
4048 / IPv6(src=ep1.ip6, dst=ep3.ip6)
4049 / UDP(sport=1234, dport=1234)
4050 / Raw(b"\xa5" * 100)
4053 Ether(src=ep3.mac, dst=ep1.mac)
4054 / IPv6(src=ep3.ip6, dst=ep1.ip6)
4055 / UDP(sport=1234, dport=1230)
4056 / Raw(b"\xa5" * 100)
4060 # should be dropped since no contract yet
4061 self.send_and_assert_no_replies(self.pg0, [p4[0]])
4062 self.send_and_assert_no_replies(self.pg0, [p6[0]])
4065 # Add a contract with a rule to load-balance redirect via SEP1 and SEP2
4066 # one of the next-hops is via an EP that is not known
4068 rule4 = AclRule(is_permit=1, proto=17)
4070 src_prefix=IPv6Network((0, 0)),
4071 dst_prefix=IPv6Network((0, 0)),
4075 acl = VppAcl(self, rules=[rule4, rule6])
4076 acl.add_vpp_config()
4079 # test the src-ip hash mode
4081 c1 = VppGbpContract(
4089 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4090 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4092 VppGbpContractNextHop(
4093 sep1.vmac, sep1.epg.bd, sep1.ip4, sep1.epg.rd
4095 VppGbpContractNextHop(
4096 sep2.vmac, sep2.epg.bd, sep2.ip4, sep2.epg.rd
4101 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4102 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4104 VppGbpContractNextHop(
4105 sep3.vmac, sep3.epg.bd, sep3.ip6, sep3.epg.rd
4107 VppGbpContractNextHop(
4108 sep4.vmac, sep4.epg.bd, sep4.ip6, sep4.epg.rd
4113 [ETH_P_IP, ETH_P_IPV6],
4117 c2 = VppGbpContract(
4125 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4126 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4128 VppGbpContractNextHop(
4129 sep1.vmac, sep1.epg.bd, sep1.ip4, sep1.epg.rd
4131 VppGbpContractNextHop(
4132 sep2.vmac, sep2.epg.bd, sep2.ip4, sep2.epg.rd
4137 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4138 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4140 VppGbpContractNextHop(
4141 sep3.vmac, sep3.epg.bd, sep3.ip6, sep3.epg.rd
4143 VppGbpContractNextHop(
4144 sep4.vmac, sep4.epg.bd, sep4.ip6, sep4.epg.rd
4149 [ETH_P_IP, ETH_P_IPV6],
4154 # send again with the contract preset, now packets arrive
4155 # at SEP1 or SEP2 depending on the hashing
4157 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
4160 self.assertEqual(rx[Ether].src, routed_src_mac)
4161 self.assertEqual(rx[Ether].dst, sep1.mac)
4162 self.assertEqual(rx[IP].src, ep1.ip4)
4163 self.assertEqual(rx[IP].dst, ep3.ip4)
4165 rxs = self.send_and_expect(self.pg2, p4[1] * 17, sep2.itf)
4168 self.assertEqual(rx[Ether].src, routed_src_mac)
4169 self.assertEqual(rx[Ether].dst, sep2.mac)
4170 self.assertEqual(rx[IP].src, ep3.ip4)
4171 self.assertEqual(rx[IP].dst, ep1.ip4)
4173 rxs = self.send_and_expect(self.pg0, p6[0] * 17, self.pg7)
4176 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4177 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4178 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4179 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4180 self.assertEqual(rx[VXLAN].vni, 117)
4181 self.assertTrue(rx[VXLAN].flags.G)
4182 self.assertTrue(rx[VXLAN].flags.Instance)
4183 # redirect policy has been applied
4184 self.assertTrue(rx[VXLAN].gpflags.A)
4185 self.assertFalse(rx[VXLAN].gpflags.D)
4187 inner = rx[VXLAN].payload
4189 self.assertEqual(inner[Ether].src, routed_src_mac)
4190 self.assertEqual(inner[Ether].dst, sep4.mac)
4191 self.assertEqual(inner[IPv6].src, ep1.ip6)
4192 self.assertEqual(inner[IPv6].dst, ep3.ip6)
4194 rxs = self.send_and_expect(self.pg2, p6[1] * 17, sep3.itf)
4197 self.assertEqual(rx[Ether].src, routed_src_mac)
4198 self.assertEqual(rx[Ether].dst, sep3.mac)
4199 self.assertEqual(rx[IPv6].src, ep3.ip6)
4200 self.assertEqual(rx[IPv6].dst, ep1.ip6)
4203 # programme the unknown EP
4205 sep4.add_vpp_config()
4207 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep4.itf)
4210 self.assertEqual(rx[Ether].src, routed_src_mac)
4211 self.assertEqual(rx[Ether].dst, sep4.mac)
4212 self.assertEqual(rx[IPv6].src, ep1.ip6)
4213 self.assertEqual(rx[IPv6].dst, ep3.ip6)
4216 # and revert back to unprogrammed
4218 sep4.remove_vpp_config()
4220 rxs = self.send_and_expect(self.pg0, p6[0] * 17, self.pg7)
4223 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4224 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4225 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4226 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4227 self.assertEqual(rx[VXLAN].vni, 117)
4228 self.assertTrue(rx[VXLAN].flags.G)
4229 self.assertTrue(rx[VXLAN].flags.Instance)
4230 # redirect policy has been applied
4231 self.assertTrue(rx[VXLAN].gpflags.A)
4232 self.assertFalse(rx[VXLAN].gpflags.D)
4234 inner = rx[VXLAN].payload
4236 self.assertEqual(inner[Ether].src, routed_src_mac)
4237 self.assertEqual(inner[Ether].dst, sep4.mac)
4238 self.assertEqual(inner[IPv6].src, ep1.ip6)
4239 self.assertEqual(inner[IPv6].dst, ep3.ip6)
4241 c1.remove_vpp_config()
4242 c2.remove_vpp_config()
4245 # test the symmetric hash mode
4247 c1 = VppGbpContract(
4255 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4256 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
4258 VppGbpContractNextHop(
4259 sep1.vmac, sep1.epg.bd, sep1.ip4, sep1.epg.rd
4261 VppGbpContractNextHop(
4262 sep2.vmac, sep2.epg.bd, sep2.ip4, sep2.epg.rd
4267 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4268 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
4270 VppGbpContractNextHop(
4271 sep3.vmac, sep3.epg.bd, sep3.ip6, sep3.epg.rd
4273 VppGbpContractNextHop(
4274 sep4.vmac, sep4.epg.bd, sep4.ip6, sep4.epg.rd
4279 [ETH_P_IP, ETH_P_IPV6],
4283 c2 = VppGbpContract(
4291 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4292 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
4294 VppGbpContractNextHop(
4295 sep1.vmac, sep1.epg.bd, sep1.ip4, sep1.epg.rd
4297 VppGbpContractNextHop(
4298 sep2.vmac, sep2.epg.bd, sep2.ip4, sep2.epg.rd
4303 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4304 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
4306 VppGbpContractNextHop(
4307 sep3.vmac, sep3.epg.bd, sep3.ip6, sep3.epg.rd
4309 VppGbpContractNextHop(
4310 sep4.vmac, sep4.epg.bd, sep4.ip6, sep4.epg.rd
4315 [ETH_P_IP, ETH_P_IPV6],
4320 # send again with the contract preset, now packets arrive
4321 # at SEP1 for both directions
4323 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
4326 self.assertEqual(rx[Ether].src, routed_src_mac)
4327 self.assertEqual(rx[Ether].dst, sep1.mac)
4328 self.assertEqual(rx[IP].src, ep1.ip4)
4329 self.assertEqual(rx[IP].dst, ep3.ip4)
4331 rxs = self.send_and_expect(self.pg2, p4[1] * 17, sep1.itf)
4334 self.assertEqual(rx[Ether].src, routed_src_mac)
4335 self.assertEqual(rx[Ether].dst, sep1.mac)
4336 self.assertEqual(rx[IP].src, ep3.ip4)
4337 self.assertEqual(rx[IP].dst, ep1.ip4)
4340 # programme the unknown EP for the L3 tests
4342 sep4.add_vpp_config()
4345 # an L3 switch packet between local EPs in different EPGs
4346 # different dest ports on each so the are LB hashed differently
4350 Ether(src=ep1.mac, dst=str(self.router_mac))
4351 / IP(src=ep1.ip4, dst=ep2.ip4)
4352 / UDP(sport=1234, dport=1234)
4353 / Raw(b"\xa5" * 100)
4356 Ether(src=ep2.mac, dst=str(self.router_mac))
4357 / IP(src=ep2.ip4, dst=ep1.ip4)
4358 / UDP(sport=1234, dport=1234)
4359 / Raw(b"\xa5" * 100)
4364 Ether(src=ep1.mac, dst=str(self.router_mac))
4365 / IPv6(src=ep1.ip6, dst=ep2.ip6)
4366 / UDP(sport=1234, dport=1234)
4367 / Raw(b"\xa5" * 100)
4370 Ether(src=ep2.mac, dst=str(self.router_mac))
4371 / IPv6(src=ep2.ip6, dst=ep1.ip6)
4372 / UDP(sport=1234, dport=1234)
4373 / Raw(b"\xa5" * 100)
4377 c3 = VppGbpContract(
4385 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4386 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
4388 VppGbpContractNextHop(
4389 sep1.vmac, sep1.epg.bd, sep1.ip4, sep1.epg.rd
4391 VppGbpContractNextHop(
4392 sep2.vmac, sep2.epg.bd, sep2.ip4, sep2.epg.rd
4397 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4398 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
4400 VppGbpContractNextHop(
4401 sep3.vmac, sep3.epg.bd, sep3.ip6, sep3.epg.rd
4403 VppGbpContractNextHop(
4404 sep4.vmac, sep4.epg.bd, sep4.ip6, sep4.epg.rd
4409 [ETH_P_IP, ETH_P_IPV6],
4413 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
4416 self.assertEqual(rx[Ether].src, routed_src_mac)
4417 self.assertEqual(rx[Ether].dst, sep1.mac)
4418 self.assertEqual(rx[IP].src, ep1.ip4)
4419 self.assertEqual(rx[IP].dst, ep2.ip4)
4422 # learn a remote EP in EPG 221
4423 # packets coming from unknown remote EPs will be leant & redirected
4425 vx_tun_l3 = VppGbpVxlanTunnel(
4429 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
4432 vx_tun_l3.add_vpp_config()
4434 c4 = VppGbpContract(
4442 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4443 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4445 VppGbpContractNextHop(
4446 sep1.vmac, sep1.epg.bd, sep1.ip4, sep1.epg.rd
4448 VppGbpContractNextHop(
4449 sep2.vmac, sep2.epg.bd, sep2.ip4, sep2.epg.rd
4454 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4455 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4457 VppGbpContractNextHop(
4458 sep3.vmac, sep3.epg.bd, sep3.ip6, sep3.epg.rd
4460 VppGbpContractNextHop(
4461 sep4.vmac, sep4.epg.bd, sep4.ip6, sep4.epg.rd
4466 [ETH_P_IP, ETH_P_IPV6],
4471 Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac)
4472 / IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4)
4473 / UDP(sport=1234, dport=48879)
4474 / VXLAN(vni=444, gpid=441, flags=0x88)
4475 / Ether(src="00:22:22:22:22:33", dst=str(self.router_mac))
4476 / IP(src="10.0.0.88", dst=ep1.ip4)
4477 / UDP(sport=1234, dport=1234)
4478 / Raw(b"\xa5" * 100)
4481 # unknown remote EP to local EP redirected
4482 rxs = self.send_and_expect(self.pg7, [p], sep1.itf)
4485 self.assertEqual(rx[Ether].src, routed_src_mac)
4486 self.assertEqual(rx[Ether].dst, sep1.mac)
4487 self.assertEqual(rx[IP].src, "10.0.0.88")
4488 self.assertEqual(rx[IP].dst, ep1.ip4)
4490 # endpoint learnt via the parent GBP-vxlan interface
4491 self.assertTrue(find_gbp_endpoint(self, vx_tun_l3._sw_if_index, ip="10.0.0.88"))
4494 Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac)
4495 / IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4)
4496 / UDP(sport=1234, dport=48879)
4497 / VXLAN(vni=444, gpid=441, flags=0x88)
4498 / Ether(src="00:22:22:22:22:33", dst=str(self.router_mac))
4499 / IPv6(src="2001:10::88", dst=ep1.ip6)
4500 / UDP(sport=1234, dport=1234)
4501 / Raw(b"\xa5" * 100)
4504 # unknown remote EP to local EP redirected (ipv6)
4505 rxs = self.send_and_expect(self.pg7, [p], sep3.itf)
4508 self.assertEqual(rx[Ether].src, routed_src_mac)
4509 self.assertEqual(rx[Ether].dst, sep3.mac)
4510 self.assertEqual(rx[IPv6].src, "2001:10::88")
4511 self.assertEqual(rx[IPv6].dst, ep1.ip6)
4513 # endpoint learnt via the parent GBP-vxlan interface
4515 find_gbp_endpoint(self, vx_tun_l3._sw_if_index, ip="2001:10::88")
4519 # L3 switch from local to remote EP
4523 Ether(src=ep1.mac, dst=str(self.router_mac))
4524 / IP(src=ep1.ip4, dst="10.0.0.88")
4525 / UDP(sport=1234, dport=1234)
4526 / Raw(b"\xa5" * 100)
4531 Ether(src=ep1.mac, dst=str(self.router_mac))
4532 / IPv6(src=ep1.ip6, dst="2001:10::88")
4533 / UDP(sport=1234, dport=1234)
4534 / Raw(b"\xa5" * 100)
4538 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
4541 self.assertEqual(rx[Ether].src, routed_src_mac)
4542 self.assertEqual(rx[Ether].dst, sep1.mac)
4543 self.assertEqual(rx[IP].src, ep1.ip4)
4544 self.assertEqual(rx[IP].dst, "10.0.0.88")
4546 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep4.itf)
4549 self.assertEqual(rx[Ether].src, routed_src_mac)
4550 self.assertEqual(rx[Ether].dst, sep4.mac)
4551 self.assertEqual(rx[IPv6].src, ep1.ip6)
4552 self.assertEqual(rx[IPv6].dst, "2001:10::88")
4555 # test the dst-ip hash mode
4557 c5 = VppGbpContract(
4565 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4566 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
4568 VppGbpContractNextHop(
4569 sep1.vmac, sep1.epg.bd, sep1.ip4, sep1.epg.rd
4571 VppGbpContractNextHop(
4572 sep2.vmac, sep2.epg.bd, sep2.ip4, sep2.epg.rd
4577 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4578 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
4580 VppGbpContractNextHop(
4581 sep3.vmac, sep3.epg.bd, sep3.ip6, sep3.epg.rd
4583 VppGbpContractNextHop(
4584 sep4.vmac, sep4.epg.bd, sep4.ip6, sep4.epg.rd
4589 [ETH_P_IP, ETH_P_IPV6],
4593 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
4596 self.assertEqual(rx[Ether].src, routed_src_mac)
4597 self.assertEqual(rx[Ether].dst, sep1.mac)
4598 self.assertEqual(rx[IP].src, ep1.ip4)
4599 self.assertEqual(rx[IP].dst, "10.0.0.88")
4601 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep3.itf)
4604 self.assertEqual(rx[Ether].src, routed_src_mac)
4605 self.assertEqual(rx[Ether].dst, sep3.mac)
4606 self.assertEqual(rx[IPv6].src, ep1.ip6)
4607 self.assertEqual(rx[IPv6].dst, "2001:10::88")
4610 # a programmed remote SEP in EPG 320
4613 # gbp vxlan tunnel for the remote SEP
4614 vx_tun_l3_sep = VppGbpVxlanTunnel(
4618 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
4621 vx_tun_l3_sep.add_vpp_config()
4624 sep5 = VppGbpEndpoint(
4633 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
4635 self.pg7.remote_ip4,
4638 sep5.add_vpp_config()
4641 # local l3out redirect tests
4646 self.loop4.set_mac(self.router_mac)
4647 b_lo4_ip4 = VppIpInterfaceBind(self, self.loop4, t4).add_vpp_config()
4648 b_lo4_ip6 = VppIpInterfaceBind(self, self.loop4, t6).add_vpp_config()
4649 ebd = VppBridgeDomain(self, 100)
4650 ebd.add_vpp_config()
4651 gebd = VppGbpBridgeDomain(self, ebd, rd1, self.loop4, None, None)
4652 gebd.add_vpp_config()
4654 eepg = VppGbpEndpointGroup(
4664 VppGbpEndpointRetention(60),
4666 eepg.add_vpp_config()
4667 # add subnets to BVI
4668 VppIpInterfaceAddress(
4669 self, gebd.bvi, "10.1.0.128", 24, bind=b_lo4_ip4
4671 VppIpInterfaceAddress(
4672 self, gebd.bvi, "2001:10:1::128", 64, bind=b_lo4_ip6
4674 # ... which are L3-out subnets
4680 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
4688 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
4691 # external endpoints
4692 VppL2Vtr(self, self.vlan_100, L2_VTR_OP.L2_POP_1).add_vpp_config()
4693 eep1 = VppGbpEndpoint(
4702 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL,
4704 eep1.add_vpp_config()
4705 VppL2Vtr(self, self.vlan_101, L2_VTR_OP.L2_POP_1).add_vpp_config()
4706 eep2 = VppGbpEndpoint(
4715 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL,
4717 eep2.add_vpp_config()
4719 # external subnets reachable though eep1 and eep2 respectively
4724 [VppRoutePath(eep1.ip4, eep1.epg.bvi.sw_if_index)],
4725 table_id=t4.table_id,
4732 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
4739 [VppRoutePath(eep1.ip6, eep1.epg.bvi.sw_if_index)],
4740 table_id=t6.table_id,
4747 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
4754 [VppRoutePath(eep2.ip4, eep2.epg.bvi.sw_if_index)],
4755 table_id=t4.table_id,
4762 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
4769 [VppRoutePath(eep2.ip6, eep2.epg.bvi.sw_if_index)],
4770 table_id=t6.table_id,
4777 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
4782 # l3out redirect to remote (known, then unknown) SEP
4785 # packets from 1 external subnet to the other
4788 Ether(src=eep1.mac, dst=self.router_mac)
4790 / IP(src="10.220.0.17", dst="10.221.0.65")
4791 / UDP(sport=1234, dport=1234)
4792 / Raw(b"\xa5" * 100)
4795 Ether(src=eep1.mac, dst=self.router_mac)
4797 / IPv6(src="10:220::17", dst="10:221::65")
4798 / UDP(sport=1234, dport=1234)
4799 / Raw(b"\xa5" * 100)
4803 # packets should be dropped in absence of contract
4804 self.send_and_assert_no_replies(self.pg0, p)
4806 # contract redirecting to sep5
4815 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4816 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
4818 VppGbpContractNextHop(
4819 sep5.vmac, sep5.epg.bd, sep5.ip4, sep5.epg.rd
4824 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4825 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
4827 VppGbpContractNextHop(
4828 sep5.vmac, sep5.epg.bd, sep5.ip6, sep5.epg.rd
4833 [ETH_P_IP, ETH_P_IPV6],
4836 rxs = self.send_and_expect(self.pg0, p, self.pg7)
4838 for rx, tx in zip(rxs, p):
4839 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4840 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4841 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4842 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4843 # this should use the programmed remote leaf TEP
4844 self.assertEqual(rx[VXLAN].vni, 555)
4845 self.assertEqual(rx[VXLAN].gpid, 4220)
4846 self.assertTrue(rx[VXLAN].flags.G)
4847 self.assertTrue(rx[VXLAN].flags.Instance)
4848 # redirect policy has been applied
4849 self.assertTrue(rx[VXLAN].gpflags.A)
4850 self.assertTrue(rx[VXLAN].gpflags.D)
4851 rxip = rx[VXLAN][Ether].payload
4852 txip = tx[Dot1Q].payload
4853 self.assertEqual(rxip.src, txip.src)
4854 self.assertEqual(rxip.dst, txip.dst)
4856 # remote SEP: it is now an unknown remote SEP and should go
4858 sep5.remove_vpp_config()
4860 rxs = self.send_and_expect(self.pg0, p, self.pg7)
4862 for rx, tx in zip(rxs, p):
4863 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4864 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4865 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4866 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4867 # this should use the spine proxy TEP
4868 self.assertEqual(rx[VXLAN].vni, epg_320.bd.uu_fwd.vni)
4869 self.assertEqual(rx[VXLAN].gpid, 4220)
4870 self.assertTrue(rx[VXLAN].flags.G)
4871 self.assertTrue(rx[VXLAN].flags.Instance)
4872 # redirect policy has been applied
4873 self.assertTrue(rx[VXLAN].gpflags.A)
4874 self.assertTrue(rx[VXLAN].gpflags.D)
4875 rxip = rx[VXLAN][Ether].payload
4876 txip = tx[Dot1Q].payload
4877 self.assertEqual(rxip.src, txip.src)
4878 self.assertEqual(rxip.dst, txip.dst)
4881 # l3out redirect to local SEP
4884 # change the contract between l3out to redirect to local SEPs
4885 # instead of remote SEP
4894 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4895 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
4897 VppGbpContractNextHop(
4898 sep1.vmac, sep1.epg.bd, sep1.ip4, sep1.epg.rd
4903 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4904 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
4906 VppGbpContractNextHop(
4907 sep1.vmac, sep1.epg.bd, sep1.ip6, sep1.epg.rd
4912 [ETH_P_IP, ETH_P_IPV6],
4915 rxs = self.send_and_expect(self.pg0, p, sep1.itf)
4916 for rx, tx in zip(rxs, p):
4917 self.assertEqual(rx[Ether].src, routed_src_mac)
4918 self.assertEqual(rx[Ether].dst, sep1.mac)
4919 rxip = rx[Ether].payload
4920 txip = tx[Ether].payload
4921 self.assertEqual(rxip.src, txip.src)
4922 self.assertEqual(rxip.dst, txip.dst)
4925 # redirect remote EP to remote (known then unknown) SEP
4928 # remote SEP known again
4929 sep5.add_vpp_config()
4931 # contract to redirect to learnt SEP
4940 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4941 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
4943 VppGbpContractNextHop(
4944 sep5.vmac, sep5.epg.bd, sep5.ip4, sep5.epg.rd
4949 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4950 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
4952 VppGbpContractNextHop(
4953 sep5.vmac, sep5.epg.bd, sep5.ip6, sep5.epg.rd
4958 [ETH_P_IP, ETH_P_IPV6],
4961 # packets from unknown EP 221 to known EP in EPG 222
4962 # should be redirected to known remote SEP
4964 Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac)
4965 / IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4)
4966 / UDP(sport=1234, dport=48879)
4967 / VXLAN(vni=444, gpid=441, flags=0x88)
4968 / Ether(src="00:22:22:22:22:44", dst=str(self.router_mac))
4973 / IP(src="10.0.1.100", dst=ep3.ip4)
4974 / UDP(sport=1234, dport=1234)
4975 / Raw(b"\xa5" * 100)
4979 / IPv6(src="2001:10::100", dst=ep3.ip6)
4980 / UDP(sport=1234, dport=1234)
4981 / Raw(b"\xa5" * 100)
4985 # unknown remote EP to local EP redirected to known remote SEP
4986 rxs = self.send_and_expect(self.pg7, p, self.pg7)
4988 for rx, tx in zip(rxs, p):
4989 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4990 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4991 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4992 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4993 # this should use the programmed remote leaf TEP
4994 self.assertEqual(rx[VXLAN].vni, 555)
4995 self.assertEqual(rx[VXLAN].gpid, epg_221.sclass)
4996 self.assertTrue(rx[VXLAN].flags.G)
4997 self.assertTrue(rx[VXLAN].flags.Instance)
4998 # redirect policy has been applied
4999 self.assertTrue(rx[VXLAN].gpflags.A)
5000 self.assertFalse(rx[VXLAN].gpflags.D)
5001 rxip = rx[VXLAN][Ether].payload
5002 txip = tx[VXLAN][Ether].payload
5003 self.assertEqual(rxip.src, txip.src)
5004 self.assertEqual(rxip.dst, txip.dst)
5006 # endpoint learnt via the parent GBP-vxlan interface
5008 find_gbp_endpoint(self, vx_tun_l3._sw_if_index, ip="10.0.1.100")
5011 find_gbp_endpoint(self, vx_tun_l3._sw_if_index, ip="2001:10::100")
5014 # remote SEP: it is now an unknown remote SEP and should go
5016 sep5.remove_vpp_config()
5018 # remote EP (coming from spine proxy) to local EP redirected to
5020 rxs = self.send_and_expect(self.pg7, p, self.pg7)
5022 for rx, tx in zip(rxs, p):
5023 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
5024 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
5025 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
5026 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
5027 # this should use the spine proxy TEP
5028 self.assertEqual(rx[VXLAN].vni, epg_320.bd.uu_fwd.vni)
5029 self.assertEqual(rx[VXLAN].gpid, epg_221.sclass)
5030 self.assertTrue(rx[VXLAN].flags.G)
5031 self.assertTrue(rx[VXLAN].flags.Instance)
5032 # redirect policy has been applied
5033 self.assertTrue(rx[VXLAN].gpflags.A)
5034 self.assertFalse(rx[VXLAN].gpflags.D)
5035 rxip = rx[VXLAN][Ether].payload
5036 txip = tx[VXLAN][Ether].payload
5037 self.assertEqual(rxip.src, txip.src)
5038 self.assertEqual(rxip.dst, txip.dst)
5043 self.pg7.unconfig_ip4()
5045 def test_gbp_redirect_extended(self):
5046 """GBP Endpoint Redirect Extended"""
5048 self.vapi.cli("set logging class gbp level debug")
5050 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
5051 routed_dst_mac = "00:0c:0c:0c:0c:0c"
5052 routed_src_mac = "00:22:bd:f8:19:ff"
5055 {"mac": "00:00:11:11:11:02", "ip": "10.0.1.2", "ip6": "2001:10::2"},
5056 {"mac": "00:00:11:11:11:03", "ip": "10.0.1.3", "ip6": "2001:10::3"},
5062 t4 = VppIpTable(self, 1)
5064 t6 = VppIpTable(self, 1, True)
5067 # create IPv4 and IPv6 RD UU VxLAN-GBP TEP and bind them to the right
5069 rd_uu4 = VppVxlanGbpTunnel(
5072 self.pg7.remote_ip4,
5075 VppEnum.vl_api_vxlan_gbp_api_tunnel_mode_t.VXLAN_GBP_API_TUNNEL_MODE_L3
5078 rd_uu4.add_vpp_config()
5079 VppIpInterfaceBind(self, rd_uu4, t4).add_vpp_config()
5081 rd_uu6 = VppVxlanGbpTunnel(
5084 self.pg7.remote_ip4,
5087 VppEnum.vl_api_vxlan_gbp_api_tunnel_mode_t.VXLAN_GBP_API_TUNNEL_MODE_L3
5090 rd_uu6.add_vpp_config()
5091 VppIpInterfaceBind(self, rd_uu6, t4).add_vpp_config()
5093 rd1 = VppGbpRouteDomain(self, 2, 402, t4, t6, rd_uu4, rd_uu6)
5094 rd1.add_vpp_config()
5096 self.loop0.set_mac(self.router_mac)
5097 self.loop1.set_mac(self.router_mac)
5098 self.loop2.set_mac(self.router_mac)
5101 # Bind the BVI to the RD
5103 b_lo0_ip4 = VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
5104 b_lo0_ip6 = VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
5105 b_lo1_ip4 = VppIpInterfaceBind(self, self.loop1, t4).add_vpp_config()
5106 b_lo1_ip6 = VppIpInterfaceBind(self, self.loop1, t6).add_vpp_config()
5107 b_lo2_ip4 = VppIpInterfaceBind(self, self.loop2, t4).add_vpp_config()
5108 b_lo2_ip6 = VppIpInterfaceBind(self, self.loop2, t6).add_vpp_config()
5111 # Pg7 hosts a BD's UU-fwd
5113 self.pg7.config_ip4()
5114 self.pg7.resolve_arp()
5117 # a GBP bridge domains for the EPs
5119 bd1 = VppBridgeDomain(self, 1)
5120 bd1.add_vpp_config()
5121 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0)
5122 gbd1.add_vpp_config()
5124 bd2 = VppBridgeDomain(self, 2)
5125 bd2.add_vpp_config()
5126 gbd2 = VppGbpBridgeDomain(self, bd2, rd1, self.loop1)
5127 gbd2.add_vpp_config()
5129 # ... and has a /32 and /128 applied
5130 ip4_addr1 = VppIpInterfaceAddress(
5131 self, gbd1.bvi, "10.0.0.128", 32, bind=b_lo0_ip4
5133 ip6_addr1 = VppIpInterfaceAddress(
5134 self, gbd1.bvi, "2001:10::128", 128, bind=b_lo0_ip6
5136 ip4_addr2 = VppIpInterfaceAddress(
5137 self, gbd2.bvi, "10.0.1.128", 32, bind=b_lo1_ip4
5139 ip6_addr2 = VppIpInterfaceAddress(
5140 self, gbd2.bvi, "2001:11::128", 128, bind=b_lo1_ip6
5144 # The Endpoint-groups
5146 epg_220 = VppGbpEndpointGroup(
5156 VppGbpEndpointRetention(60),
5158 epg_220.add_vpp_config()
5159 epg_221 = VppGbpEndpointGroup(
5169 VppGbpEndpointRetention(60),
5171 epg_221.add_vpp_config()
5174 # a GBP bridge domains for the SEPs
5176 bd_uu3 = VppVxlanGbpTunnel(self, self.pg7.local_ip4, self.pg7.remote_ip4, 116)
5177 bd_uu3.add_vpp_config()
5179 bd3 = VppBridgeDomain(self, 3)
5180 bd3.add_vpp_config()
5181 gbd3 = VppGbpBridgeDomain(self, bd3, rd1, self.loop2, bd_uu3, learn=False)
5182 gbd3.add_vpp_config()
5184 ip4_addr3 = VppIpInterfaceAddress(
5185 self, gbd3.bvi, "12.0.0.128", 32, bind=b_lo2_ip4
5187 ip6_addr3 = VppIpInterfaceAddress(
5188 self, gbd3.bvi, "4001:10::128", 128, bind=b_lo2_ip6
5192 # self.logger.info(self.vapi.cli("show gbp bridge"))
5193 # self.logger.info(self.vapi.cli("show vxlan-gbp tunnel"))
5194 # self.logger.info(self.vapi.cli("show gbp vxlan"))
5195 # self.logger.info(self.vapi.cli("show int addr"))
5199 # EPGs in which the service endpoints exist
5201 epg_320 = VppGbpEndpointGroup(
5211 VppGbpEndpointRetention(60),
5213 epg_320.add_vpp_config()
5218 ep1 = VppGbpEndpoint(
5228 ep1.add_vpp_config()
5229 ep2 = VppGbpEndpoint(
5239 ep2.add_vpp_config()
5244 sep1 = VppGbpEndpoint(
5254 sep2 = VppGbpEndpoint(
5265 # sep1 and sep2 are not added to config yet
5266 # they are unknown for now
5269 # add routes to EPG subnets
5276 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT,
5283 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT,
5287 # Local host to known local host in different BD
5288 # with SFC contract (source and destination are in
5289 # one node and service endpoint in another node)
5293 Ether(src=ep1.mac, dst=str(self.router_mac))
5294 / IP(src=ep1.ip4, dst=ep2.ip4)
5295 / UDP(sport=1234, dport=1234)
5296 / Raw(b"\xa5" * 100)
5299 Ether(src=ep2.mac, dst=str(self.router_mac))
5300 / IP(src=ep2.ip4, dst=ep1.ip4)
5301 / UDP(sport=1234, dport=1234)
5302 / Raw(b"\xa5" * 100)
5307 Ether(src=ep1.mac, dst=str(self.router_mac))
5308 / IPv6(src=ep1.ip6, dst=ep2.ip6)
5309 / UDP(sport=1234, dport=1234)
5310 / Raw(b"\xa5" * 100)
5313 Ether(src=ep2.mac, dst=str(self.router_mac))
5314 / IPv6(src=ep2.ip6, dst=ep1.ip6)
5315 / UDP(sport=1234, dport=1230)
5316 / Raw(b"\xa5" * 100)
5320 # should be dropped since no contract yet
5321 self.send_and_assert_no_replies(self.pg0, [p4[0]])
5322 self.send_and_assert_no_replies(self.pg0, [p6[0]])
5325 # Add a contract with a rule to load-balance redirect via SEP1 and SEP2
5326 # one of the next-hops is via an EP that is not known
5328 rule4 = AclRule(is_permit=1, proto=17)
5330 src_prefix=IPv6Network((0, 0)),
5331 dst_prefix=IPv6Network((0, 0)),
5335 acl = VppAcl(self, rules=[rule4, rule6])
5336 acl.add_vpp_config()
5339 # test the src-ip hash mode
5341 c1 = VppGbpContract(
5349 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
5350 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
5352 VppGbpContractNextHop(
5353 sep1.vmac, sep1.epg.bd, sep1.ip4, sep1.epg.rd
5358 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
5359 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
5361 VppGbpContractNextHop(
5362 sep1.vmac, sep1.epg.bd, sep1.ip6, sep1.epg.rd
5367 [ETH_P_IP, ETH_P_IPV6],
5371 c2 = VppGbpContract(
5379 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
5380 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
5382 VppGbpContractNextHop(
5383 sep1.vmac, sep1.epg.bd, sep1.ip4, sep1.epg.rd
5388 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
5389 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
5391 VppGbpContractNextHop(
5392 sep1.vmac, sep1.epg.bd, sep1.ip6, sep1.epg.rd
5397 [ETH_P_IP, ETH_P_IPV6],
5401 # ep1 <--> ep2 redirected through sep1
5403 # packet is redirected to sep bd and then go through sep bd UU
5405 rxs = self.send_and_expect(self.pg0, p4[0] * 17, self.pg7)
5408 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
5409 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
5410 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
5411 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
5412 self.assertEqual(rx[VXLAN].vni, 116)
5413 self.assertTrue(rx[VXLAN].flags.G)
5414 self.assertTrue(rx[VXLAN].flags.Instance)
5415 # redirect policy has been applied
5416 self.assertTrue(rx[VXLAN].gpflags.A)
5417 self.assertFalse(rx[VXLAN].gpflags.D)
5419 inner = rx[VXLAN].payload
5421 self.assertEqual(inner[Ether].src, routed_src_mac)
5422 self.assertEqual(inner[Ether].dst, sep1.mac)
5423 self.assertEqual(inner[IP].src, ep1.ip4)
5424 self.assertEqual(inner[IP].dst, ep2.ip4)
5426 rxs = self.send_and_expect(self.pg1, p4[1] * 17, self.pg7)
5429 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
5430 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
5431 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
5432 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
5433 self.assertEqual(rx[VXLAN].vni, 116)
5434 self.assertTrue(rx[VXLAN].flags.G)
5435 self.assertTrue(rx[VXLAN].flags.Instance)
5436 # redirect policy has been applied
5437 self.assertTrue(rx[VXLAN].gpflags.A)
5438 self.assertFalse(rx[VXLAN].gpflags.D)
5440 inner = rx[VXLAN].payload
5442 self.assertEqual(inner[Ether].src, routed_src_mac)
5443 self.assertEqual(inner[Ether].dst, sep1.mac)
5444 self.assertEqual(inner[IP].src, ep2.ip4)
5445 self.assertEqual(inner[IP].dst, ep1.ip4)
5447 rxs = self.send_and_expect(self.pg0, p6[0] * 17, self.pg7)
5450 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
5451 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
5452 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
5453 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
5454 self.assertEqual(rx[VXLAN].vni, 116)
5455 self.assertTrue(rx[VXLAN].flags.G)
5456 self.assertTrue(rx[VXLAN].flags.Instance)
5457 # redirect policy has been applied
5458 inner = rx[VXLAN].payload
5460 self.assertEqual(inner[Ether].src, routed_src_mac)
5461 self.assertEqual(inner[Ether].dst, sep1.mac)
5462 self.assertEqual(inner[IPv6].src, ep1.ip6)
5463 self.assertEqual(inner[IPv6].dst, ep2.ip6)
5465 rxs = self.send_and_expect(self.pg1, p6[1] * 17, self.pg7)
5468 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
5469 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
5470 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
5471 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
5472 self.assertEqual(rx[VXLAN].vni, 116)
5473 self.assertTrue(rx[VXLAN].flags.G)
5474 self.assertTrue(rx[VXLAN].flags.Instance)
5475 # redirect policy has been applied
5476 self.assertTrue(rx[VXLAN].gpflags.A)
5477 self.assertFalse(rx[VXLAN].gpflags.D)
5479 inner = rx[VXLAN].payload
5481 self.assertEqual(inner[Ether].src, routed_src_mac)
5482 self.assertEqual(inner[Ether].dst, sep1.mac)
5483 self.assertEqual(inner[IPv6].src, ep2.ip6)
5484 self.assertEqual(inner[IPv6].dst, ep1.ip6)
5486 # configure sep1: it is now local
5487 # packets between ep1 and ep2 are redirected locally
5488 sep1.add_vpp_config()
5490 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
5493 self.assertEqual(rx[Ether].src, routed_src_mac)
5494 self.assertEqual(rx[Ether].dst, sep1.mac)
5495 self.assertEqual(rx[IP].src, ep1.ip4)
5496 self.assertEqual(rx[IP].dst, ep2.ip4)
5498 rxs = self.send_and_expect(self.pg1, p6[1] * 17, sep1.itf)
5501 self.assertEqual(rx[Ether].src, routed_src_mac)
5502 self.assertEqual(rx[Ether].dst, sep1.mac)
5503 self.assertEqual(rx[IPv6].src, ep2.ip6)
5504 self.assertEqual(rx[IPv6].dst, ep1.ip6)
5506 # packet coming from the l2 spine-proxy to sep1
5508 Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac)
5509 / IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4)
5510 / UDP(sport=1234, dport=48879)
5511 / VXLAN(vni=116, gpid=440, gpflags=0x08, flags=0x88)
5512 / Ether(src=str(self.router_mac), dst=sep1.mac)
5513 / IP(src=ep1.ip4, dst=ep2.ip4)
5514 / UDP(sport=1234, dport=1234)
5515 / Raw(b"\xa5" * 100)
5518 rxs = self.send_and_expect(self.pg7, [p] * 17, sep1.itf)
5521 self.assertEqual(rx[Ether].src, str(self.router_mac))
5522 self.assertEqual(rx[Ether].dst, sep1.mac)
5523 self.assertEqual(rx[IP].src, ep1.ip4)
5524 self.assertEqual(rx[IP].dst, ep2.ip4)
5526 # contract for SEP to communicate with dst EP
5527 c3 = VppGbpContract(
5535 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5536 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
5539 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5540 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
5543 [ETH_P_IP, ETH_P_IPV6],
5547 # temporarily remove ep2, so that ep2 is remote & unknown
5548 ep2.remove_vpp_config()
5550 # packet going back from sep1 to its original dest (ep2)
5551 # as ep2 is now unknown (see above), it must go through
5552 # the rd UU (packet is routed)
5555 Ether(src=sep1.mac, dst=self.router_mac)
5556 / IP(src=ep1.ip4, dst=ep2.ip4)
5557 / UDP(sport=1234, dport=1234)
5558 / Raw(b"\xa5" * 100)
5561 rxs = self.send_and_expect(self.pg3, [p1] * 17, self.pg7)
5564 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
5565 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
5566 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
5567 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
5568 self.assertEqual(rx[VXLAN].vni, 114)
5569 self.assertTrue(rx[VXLAN].flags.G)
5570 self.assertTrue(rx[VXLAN].flags.Instance)
5571 # redirect policy has been applied
5572 inner = rx[VXLAN].payload
5573 self.assertEqual(inner[Ether].src, routed_src_mac)
5574 self.assertEqual(inner[Ether].dst, routed_dst_mac)
5575 self.assertEqual(inner[IP].src, ep1.ip4)
5576 self.assertEqual(inner[IP].dst, ep2.ip4)
5578 self.logger.info(self.vapi.cli("show bridge 3 detail"))
5579 sep1.remove_vpp_config()
5581 self.logger.info(self.vapi.cli("show bridge 1 detail"))
5582 self.logger.info(self.vapi.cli("show bridge 2 detail"))
5584 # re-add ep2: it is local again :)
5585 ep2.add_vpp_config()
5587 # packet coming back from the remote sep through rd UU
5589 Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac)
5590 / IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4)
5591 / UDP(sport=1234, dport=48879)
5592 / VXLAN(vni=114, gpid=441, gpflags=0x09, flags=0x88)
5593 / Ether(src=str(self.router_mac), dst=self.router_mac)
5594 / IP(src=ep1.ip4, dst=ep2.ip4)
5595 / UDP(sport=1234, dport=1234)
5596 / Raw(b"\xa5" * 100)
5599 rxs = self.send_and_expect(self.pg7, [p2], self.pg1)
5602 self.assertEqual(rx[Ether].src, str(self.router_mac))
5603 self.assertEqual(rx[Ether].dst, self.pg1.remote_mac)
5604 self.assertEqual(rx[IP].src, ep1.ip4)
5605 self.assertEqual(rx[IP].dst, ep2.ip4)
5608 # bd_uu2.add_vpp_config()
5614 c1.remove_vpp_config()
5615 c2.remove_vpp_config()
5616 c3.remove_vpp_config()
5617 self.pg7.unconfig_ip4()
5619 def test_gbp_l3_out(self):
5622 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
5623 self.vapi.cli("set logging class gbp level debug")
5625 routed_dst_mac = "00:0c:0c:0c:0c:0c"
5626 routed_src_mac = "00:22:bd:f8:19:ff"
5631 t4 = VppIpTable(self, 1)
5633 t6 = VppIpTable(self, 1, True)
5636 rd1 = VppGbpRouteDomain(self, 2, 55, t4, t6)
5637 rd1.add_vpp_config()
5639 self.loop0.set_mac(self.router_mac)
5642 # Bind the BVI to the RD
5644 b_ip4 = VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
5645 b_ip6 = VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
5648 # Pg7 hosts a BD's BUM
5649 # Pg1 some other l3 interface
5651 self.pg7.config_ip4()
5652 self.pg7.resolve_arp()
5655 # a multicast vxlan-gbp tunnel for broadcast in the BD
5657 tun_bm = VppVxlanGbpTunnel(
5658 self, self.pg7.local_ip4, "239.1.1.1", 88, mcast_itf=self.pg7
5660 tun_bm.add_vpp_config()
5663 # a GBP external bridge domains for the EPs
5665 bd1 = VppBridgeDomain(self, 1)
5666 bd1.add_vpp_config()
5667 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0, None, tun_bm)
5668 gbd1.add_vpp_config()
5671 # The Endpoint-groups in which the external endpoints exist
5673 epg_220 = VppGbpEndpointGroup(
5683 VppGbpEndpointRetention(4),
5685 epg_220.add_vpp_config()
5687 # the BVIs have the subnets applied ...
5688 ip4_addr = VppIpInterfaceAddress(
5689 self, gbd1.bvi, "10.0.0.128", 24, bind=b_ip4
5691 ip6_addr = VppIpInterfaceAddress(
5692 self, gbd1.bvi, "2001:10::128", 64, bind=b_ip6
5695 # ... which are L3-out subnets
5696 l3o_1 = VppGbpSubnet(
5701 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
5704 l3o_1.add_vpp_config()
5707 # an external interface attached to the outside world and the
5710 VppL2Vtr(self, self.vlan_100, L2_VTR_OP.L2_POP_1).add_vpp_config()
5711 VppL2Vtr(self, self.vlan_101, L2_VTR_OP.L2_POP_1).add_vpp_config()
5712 vlan_144 = VppDot1QSubint(self, self.pg0, 144)
5714 # vlan_102 is not poped
5717 # an unicast vxlan-gbp for inter-RD traffic
5719 vx_tun_l3 = VppGbpVxlanTunnel(
5723 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
5726 vx_tun_l3.add_vpp_config()
5729 # External Endpoints
5731 eep1 = VppGbpEndpoint(
5740 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL,
5742 eep1.add_vpp_config()
5743 eep2 = VppGbpEndpoint(
5752 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL,
5754 eep2.add_vpp_config()
5755 eep3 = VppGbpEndpoint(
5764 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL,
5766 eep3.add_vpp_config()
5769 # A remote external endpoint
5771 rep = VppGbpEndpoint(
5780 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
5782 self.pg7.remote_ip4,
5785 rep.add_vpp_config()
5788 # EP1 impersonating EP3 is dropped
5791 Ether(src=eep1.mac, dst="ff:ff:ff:ff:ff:ff")
5798 hwdst="ff:ff:ff:ff:ff:ff",
5801 self.send_and_assert_no_replies(self.pg0, p)
5804 # ARP packet from External EPs are accepted and replied to
5807 Ether(src=eep1.mac, dst="ff:ff:ff:ff:ff:ff")
5814 hwdst="ff:ff:ff:ff:ff:ff",
5817 rxs = self.send_and_expect(self.pg0, p_arp * 1, self.pg0)
5820 # ARP packet from host in remote subnet are accepted and replied to
5823 Ether(src=eep3.mac, dst="ff:ff:ff:ff:ff:ff")
5830 hwdst="ff:ff:ff:ff:ff:ff",
5833 rxs = self.send_and_expect(self.pg0, p_arp * 1, self.pg0)
5836 # packets destined to unknown addresses in the BVI's subnet
5840 Ether(src=eep1.mac, dst=str(self.router_mac))
5842 / IP(src="10.0.0.1", dst="10.0.0.88")
5843 / UDP(sport=1234, dport=1234)
5844 / Raw(b"\xa5" * 100)
5847 Ether(src=eep1.mac, dst=str(self.router_mac))
5849 / IPv6(src="2001:10::1", dst="2001:10::88")
5850 / UDP(sport=1234, dport=1234)
5851 / Raw(b"\xa5" * 100)
5854 rxs = self.send_and_expect(self.pg0, p4 * 1, self.pg7)
5857 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
5858 # self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
5859 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
5860 self.assertEqual(rx[IP].dst, "239.1.1.1")
5861 self.assertEqual(rx[VXLAN].vni, 88)
5862 self.assertTrue(rx[VXLAN].flags.G)
5863 self.assertTrue(rx[VXLAN].flags.Instance)
5864 # policy was applied to the original IP packet
5865 self.assertEqual(rx[VXLAN].gpid, 113)
5866 self.assertTrue(rx[VXLAN].gpflags.A)
5867 self.assertFalse(rx[VXLAN].gpflags.D)
5869 inner = rx[VXLAN].payload
5871 self.assertTrue(inner.haslayer(ARP))
5874 # remote to external
5877 Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac)
5878 / IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4)
5879 / UDP(sport=1234, dport=48879)
5880 / VXLAN(vni=444, gpid=113, flags=0x88)
5881 / Ether(src=self.pg0.remote_mac, dst=str(self.router_mac))
5882 / IP(src="10.0.0.101", dst="10.0.0.1")
5883 / UDP(sport=1234, dport=1234)
5884 / Raw(b"\xa5" * 100)
5887 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
5890 # local EP pings router
5893 Ether(src=eep1.mac, dst=str(self.router_mac))
5895 / IP(src=eep1.ip4, dst="10.0.0.128")
5896 / ICMP(type="echo-request")
5899 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
5902 self.assertEqual(rx[Ether].src, str(self.router_mac))
5903 self.assertEqual(rx[Ether].dst, eep1.mac)
5904 self.assertEqual(rx[Dot1Q].vlan, 100)
5907 # local EP pings other local EP
5910 Ether(src=eep1.mac, dst=eep2.mac)
5912 / IP(src=eep1.ip4, dst=eep2.ip4)
5913 / ICMP(type="echo-request")
5916 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
5919 self.assertEqual(rx[Ether].src, eep1.mac)
5920 self.assertEqual(rx[Ether].dst, eep2.mac)
5921 self.assertEqual(rx[Dot1Q].vlan, 101)
5924 # local EP pings router w/o vlan tag poped
5927 Ether(src=eep3.mac, dst=str(self.router_mac))
5929 / IP(src=eep3.ip4, dst="10.0.0.128")
5930 / ICMP(type="echo-request")
5933 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
5936 self.assertEqual(rx[Ether].src, str(self.router_mac))
5937 self.assertEqual(rx[Ether].dst, self.vlan_102.remote_mac)
5940 # A ip4 subnet reachable through the external EP1
5942 ip_220 = VppIpRoute(
5946 [VppRoutePath(eep1.ip4, eep1.epg.bvi.sw_if_index)],
5947 table_id=t4.table_id,
5949 ip_220.add_vpp_config()
5951 l3o_220 = VppGbpSubnet(
5956 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
5959 l3o_220.add_vpp_config()
5962 # An ip6 subnet reachable through the external EP1
5964 ip6_220 = VppIpRoute(
5968 [VppRoutePath(eep1.ip6, eep1.epg.bvi.sw_if_index)],
5969 table_id=t6.table_id,
5971 ip6_220.add_vpp_config()
5973 l3o6_220 = VppGbpSubnet(
5978 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
5981 l3o6_220.add_vpp_config()
5984 # A subnet reachable through the external EP2
5986 ip_221 = VppIpRoute(
5990 [VppRoutePath(eep2.ip4, eep2.epg.bvi.sw_if_index)],
5991 table_id=t4.table_id,
5993 ip_221.add_vpp_config()
5995 l3o_221 = VppGbpSubnet(
6000 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
6003 l3o_221.add_vpp_config()
6006 # ping between hosts in remote subnets
6007 # dropped without a contract
6010 Ether(src=eep1.mac, dst=str(self.router_mac))
6012 / IP(src="10.220.0.1", dst="10.221.0.1")
6013 / ICMP(type="echo-request")
6016 self.send_and_assert_no_replies(self.pg0, p * 1)
6019 # contract for the external nets to communicate
6021 rule4 = AclRule(is_permit=1, proto=17)
6023 src_prefix=IPv6Network((0, 0)),
6024 dst_prefix=IPv6Network((0, 0)),
6028 acl = VppAcl(self, rules=[rule4, rule6])
6029 acl.add_vpp_config()
6032 # A contract with the wrong scope is not matched
6034 c_44 = VppGbpContract(
6042 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
6043 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
6047 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
6048 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
6052 [ETH_P_IP, ETH_P_IPV6],
6054 c_44.add_vpp_config()
6055 self.send_and_assert_no_replies(self.pg0, p * 1)
6057 c1 = 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],
6080 # Contracts allowing ext-net 200 to talk with external EPs
6082 c2 = VppGbpContract(
6090 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
6091 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
6095 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
6096 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
6100 [ETH_P_IP, ETH_P_IPV6],
6103 c3 = VppGbpContract(
6111 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
6112 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
6116 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
6117 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
6121 [ETH_P_IP, ETH_P_IPV6],
6126 # ping between hosts in remote subnets
6129 Ether(src=eep1.mac, dst=str(self.router_mac))
6131 / IP(src="10.220.0.1", dst="10.221.0.1")
6132 / UDP(sport=1234, dport=1234)
6133 / Raw(b"\xa5" * 100)
6136 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
6139 self.assertEqual(rx[Ether].src, str(self.router_mac))
6140 self.assertEqual(rx[Ether].dst, eep2.mac)
6141 self.assertEqual(rx[Dot1Q].vlan, 101)
6143 # we did not learn these external hosts
6144 self.assertFalse(find_gbp_endpoint(self, ip="10.220.0.1"))
6145 self.assertFalse(find_gbp_endpoint(self, ip="10.221.0.1"))
6148 # from remote external EP to local external EP
6151 Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac)
6152 / IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4)
6153 / UDP(sport=1234, dport=48879)
6154 / VXLAN(vni=444, gpid=113, flags=0x88)
6155 / Ether(src=self.pg0.remote_mac, dst=str(self.router_mac))
6156 / IP(src="10.0.0.101", dst="10.220.0.1")
6157 / UDP(sport=1234, dport=1234)
6158 / Raw(b"\xa5" * 100)
6161 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
6164 # ping from an external host to the remote external EP
6167 Ether(src=eep1.mac, dst=str(self.router_mac))
6169 / IP(src="10.220.0.1", dst=rep.ip4)
6170 / UDP(sport=1234, dport=1234)
6171 / Raw(b"\xa5" * 100)
6174 rxs = self.send_and_expect(self.pg0, p * 1, self.pg7)
6177 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
6178 # self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
6179 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
6180 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
6181 self.assertEqual(rx[VXLAN].vni, 444)
6182 self.assertTrue(rx[VXLAN].flags.G)
6183 self.assertTrue(rx[VXLAN].flags.Instance)
6184 # the sclass of the ext-net the packet came from
6185 self.assertEqual(rx[VXLAN].gpid, 4220)
6186 # policy was applied to the original IP packet
6187 self.assertTrue(rx[VXLAN].gpflags.A)
6188 # since it's an external host the reciever should not learn it
6189 self.assertTrue(rx[VXLAN].gpflags.D)
6190 inner = rx[VXLAN].payload
6191 self.assertEqual(inner[IP].src, "10.220.0.1")
6192 self.assertEqual(inner[IP].dst, rep.ip4)
6195 # An external subnet reachable via the remote external EP
6199 # first the VXLAN-GBP tunnel over which it is reached
6201 vx_tun_r1 = VppVxlanGbpTunnel(
6204 self.pg7.remote_ip4,
6207 VppEnum.vl_api_vxlan_gbp_api_tunnel_mode_t.VXLAN_GBP_API_TUNNEL_MODE_L3
6210 vx_tun_r1.add_vpp_config()
6211 VppIpInterfaceBind(self, vx_tun_r1, t4).add_vpp_config()
6213 self.logger.info(self.vapi.cli("sh vxlan-gbp tunnel"))
6216 # then the special adj to resolve through on that tunnel
6219 self, vx_tun_r1.sw_if_index, "00:0c:0c:0c:0c:0c", self.pg7.remote_ip4
6224 # the route via the adj above
6226 ip_222 = VppIpRoute(
6230 [VppRoutePath(self.pg7.remote_ip4, vx_tun_r1.sw_if_index)],
6231 table_id=t4.table_id,
6233 ip_222.add_vpp_config()
6235 l3o_222 = VppGbpSubnet(
6240 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
6243 l3o_222.add_vpp_config()
6246 # ping between hosts in local and remote external subnets
6247 # dropped without a contract
6250 Ether(src=eep1.mac, dst=str(self.router_mac))
6252 / IP(src="10.220.0.1", dst="10.222.0.1")
6253 / UDP(sport=1234, dport=1234)
6254 / Raw(b"\xa5" * 100)
6257 rxs = self.send_and_assert_no_replies(self.pg0, p * 1)
6260 # Add contracts ext-nets for 220 -> 222
6262 c4 = VppGbpContract(
6270 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
6271 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
6275 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
6276 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
6280 [ETH_P_IP, ETH_P_IPV6],
6285 # ping from host in local to remote external subnets
6288 Ether(src=eep1.mac, dst=str(self.router_mac))
6290 / IP(src="10.220.0.1", dst="10.222.0.1")
6291 / UDP(sport=1234, dport=1234)
6292 / Raw(b"\xa5" * 100)
6295 rxs = self.send_and_expect(self.pg0, p * 3, self.pg7)
6298 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
6299 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
6300 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
6301 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
6302 self.assertEqual(rx[VXLAN].vni, 445)
6303 self.assertTrue(rx[VXLAN].flags.G)
6304 self.assertTrue(rx[VXLAN].flags.Instance)
6305 # the sclass of the ext-net the packet came from
6306 self.assertEqual(rx[VXLAN].gpid, 4220)
6307 # policy was applied to the original IP packet
6308 self.assertTrue(rx[VXLAN].gpflags.A)
6309 # since it's an external host the reciever should not learn it
6310 self.assertTrue(rx[VXLAN].gpflags.D)
6311 inner = rx[VXLAN].payload
6312 self.assertEqual(inner[Ether].dst, "00:0c:0c:0c:0c:0c")
6313 self.assertEqual(inner[IP].src, "10.220.0.1")
6314 self.assertEqual(inner[IP].dst, "10.222.0.1")
6317 # make the external subnet ECMP
6319 vx_tun_r2 = VppVxlanGbpTunnel(
6322 self.pg7.remote_ip4,
6325 VppEnum.vl_api_vxlan_gbp_api_tunnel_mode_t.VXLAN_GBP_API_TUNNEL_MODE_L3
6328 vx_tun_r2.add_vpp_config()
6329 VppIpInterfaceBind(self, vx_tun_r2, t4).add_vpp_config()
6331 self.logger.info(self.vapi.cli("sh vxlan-gbp tunnel"))
6334 self, vx_tun_r2.sw_if_index, "00:0c:0c:0c:0c:0c", self.pg7.remote_ip4
6340 VppRoutePath(self.pg7.remote_ip4, vx_tun_r1.sw_if_index),
6341 VppRoutePath(self.pg7.remote_ip4, vx_tun_r2.sw_if_index),
6346 # now expect load-balance
6350 Ether(src=eep1.mac, dst=str(self.router_mac))
6352 / IP(src="10.220.0.1", dst="10.222.0.1")
6353 / UDP(sport=1234, dport=1234)
6354 / Raw(b"\xa5" * 100)
6357 Ether(src=eep1.mac, dst=str(self.router_mac))
6359 / IP(src="10.220.0.1", dst="10.222.0.1")
6360 / UDP(sport=1222, dport=1235)
6361 / Raw(b"\xa5" * 100)
6365 rxs = self.send_and_expect(self.pg0, p, self.pg7)
6367 self.assertEqual(rxs[0][VXLAN].vni, 445)
6368 self.assertEqual(rxs[1][VXLAN].vni, 446)
6371 # Same LB test for v6
6374 self, vx_tun_r1.sw_if_index, "00:0c:0c:0c:0c:0c", self.pg7.remote_ip6
6378 self, vx_tun_r2.sw_if_index, "00:0c:0c:0c:0c:0c", self.pg7.remote_ip6
6382 ip_222_6 = VppIpRoute(
6387 VppRoutePath(self.pg7.remote_ip6, vx_tun_r1.sw_if_index),
6388 VppRoutePath(self.pg7.remote_ip6, vx_tun_r2.sw_if_index),
6390 table_id=t6.table_id,
6392 ip_222_6.add_vpp_config()
6394 l3o_222_6 = VppGbpSubnet(
6399 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
6402 l3o_222_6.add_vpp_config()
6406 Ether(src=eep1.mac, dst=str(self.router_mac))
6408 / IPv6(src="10:220::1", dst="10:222::1")
6409 / UDP(sport=1234, dport=1234)
6410 / Raw(b"\xa5" * 100)
6413 Ether(src=eep1.mac, dst=str(self.router_mac))
6415 / IPv6(src="10:220::1", dst="10:222::1")
6416 / UDP(sport=7777, dport=8881)
6417 / Raw(b"\xa5" * 100)
6421 self.logger.info(self.vapi.cli("sh ip6 fib 10:222::1"))
6422 rxs = self.send_and_expect(self.pg0, p, self.pg7)
6424 self.assertEqual(rxs[0][VXLAN].vni, 445)
6425 self.assertEqual(rxs[1][VXLAN].vni, 446)
6428 # ping from host in remote to local external subnets
6429 # there's no contract for this, but the A bit is set.
6432 Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac)
6433 / IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4)
6434 / UDP(sport=1234, dport=48879)
6435 / VXLAN(vni=445, gpid=4222, flags=0x88, gpflags="A")
6436 / Ether(src=self.pg0.remote_mac, dst=str(self.router_mac))
6437 / IP(src="10.222.0.1", dst="10.220.0.1")
6438 / UDP(sport=1234, dport=1234)
6439 / Raw(b"\xa5" * 100)
6442 rxs = self.send_and_expect(self.pg7, p * 3, self.pg0)
6443 self.assertFalse(find_gbp_endpoint(self, ip="10.222.0.1"))
6446 # ping from host in remote to remote external subnets
6447 # this is dropped by reflection check.
6450 Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac)
6451 / IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4)
6452 / UDP(sport=1234, dport=48879)
6453 / VXLAN(vni=445, gpid=4222, flags=0x88, gpflags="A")
6454 / Ether(src=self.pg0.remote_mac, dst=str(self.router_mac))
6455 / IP(src="10.222.0.1", dst="10.222.0.2")
6456 / UDP(sport=1234, dport=1234)
6457 / Raw(b"\xa5" * 100)
6460 rxs = self.send_and_assert_no_replies(self.pg7, p * 3)
6463 Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac)
6464 / IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4)
6465 / UDP(sport=1234, dport=48879)
6466 / VXLAN(vni=445, gpid=4222, flags=0x88, gpflags="A")
6467 / Ether(src=self.pg0.remote_mac, dst=str(self.router_mac))
6468 / IPv6(src="10:222::1", dst="10:222::2")
6469 / UDP(sport=1234, dport=1234)
6470 / Raw(b"\xa5" * 100)
6473 rxs = self.send_and_assert_no_replies(self.pg7, p * 3)
6478 lep1 = VppGbpEndpoint(
6488 lep1.add_vpp_config()
6491 # local EP to local ip4 external subnet
6494 Ether(src=lep1.mac, dst=str(self.router_mac))
6496 / IP(src=lep1.ip4, dst="10.220.0.1")
6497 / UDP(sport=1234, dport=1234)
6498 / Raw(b"\xa5" * 100)
6501 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
6504 self.assertEqual(rx[Ether].src, str(self.router_mac))
6505 self.assertEqual(rx[Ether].dst, eep1.mac)
6506 self.assertEqual(rx[Dot1Q].vlan, 100)
6509 # local EP to local ip6 external subnet
6512 Ether(src=lep1.mac, dst=str(self.router_mac))
6514 / IPv6(src=lep1.ip6, dst="10:220::1")
6515 / UDP(sport=1234, dport=1234)
6516 / Raw(b"\xa5" * 100)
6519 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
6522 self.assertEqual(rx[Ether].src, str(self.router_mac))
6523 self.assertEqual(rx[Ether].dst, eep1.mac)
6524 self.assertEqual(rx[Dot1Q].vlan, 100)
6527 # ip4 and ip6 subnets that load-balance
6534 VppRoutePath(eep1.ip4, eep1.epg.bvi.sw_if_index),
6535 VppRoutePath(eep2.ip4, eep2.epg.bvi.sw_if_index),
6537 table_id=t4.table_id,
6539 ip_20.add_vpp_config()
6541 l3o_20 = VppGbpSubnet(
6546 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
6549 l3o_20.add_vpp_config()
6551 ip6_20 = VppIpRoute(
6556 VppRoutePath(eep1.ip6, eep1.epg.bvi.sw_if_index),
6557 VppRoutePath(eep2.ip6, eep2.epg.bvi.sw_if_index),
6559 table_id=t6.table_id,
6561 ip6_20.add_vpp_config()
6563 l3o6_20 = VppGbpSubnet(
6568 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
6571 l3o6_20.add_vpp_config()
6573 self.logger.info(self.vapi.cli("sh ip fib 10.20.0.1"))
6574 self.logger.info(self.vapi.cli("sh ip6 fib 10:20::1"))
6576 # two ip6 packets whose port are chosen so they load-balance
6579 Ether(src=lep1.mac, dst=str(self.router_mac))
6581 / IPv6(src=lep1.ip6, dst="10:20::1")
6582 / UDP(sport=1234, dport=1234)
6583 / Raw(b"\xa5" * 100)
6586 Ether(src=lep1.mac, dst=str(self.router_mac))
6588 / IPv6(src=lep1.ip6, dst="10:20::1")
6589 / UDP(sport=124, dport=1230)
6590 / Raw(b"\xa5" * 100)
6594 rxs = self.send_and_expect(self.pg0, p, self.pg0, 2)
6596 self.assertEqual(rxs[0][Dot1Q].vlan, 101)
6597 self.assertEqual(rxs[1][Dot1Q].vlan, 100)
6599 # two ip4 packets whose port are chosen so they load-balance
6602 Ether(src=lep1.mac, dst=str(self.router_mac))
6604 / IP(src=lep1.ip4, dst="10.20.0.1")
6605 / UDP(sport=1235, dport=1235)
6606 / Raw(b"\xa5" * 100)
6609 Ether(src=lep1.mac, dst=str(self.router_mac))
6611 / IP(src=lep1.ip4, dst="10.20.0.1")
6612 / UDP(sport=124, dport=1230)
6613 / Raw(b"\xa5" * 100)
6617 rxs = self.send_and_expect(self.pg0, p, self.pg0, 2)
6619 self.assertEqual(rxs[0][Dot1Q].vlan, 101)
6620 self.assertEqual(rxs[1][Dot1Q].vlan, 100)
6625 ip_222.remove_vpp_config()
6626 self.pg7.unconfig_ip4()
6627 self.vlan_101.set_vtr(L2_VTR_OP.L2_DISABLED)
6628 self.vlan_100.set_vtr(L2_VTR_OP.L2_DISABLED)
6630 def test_gbp_anon_l3_out(self):
6631 """GBP Anonymous L3 Out"""
6633 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
6634 self.vapi.cli("set logging class gbp level debug")
6636 routed_dst_mac = "00:0c:0c:0c:0c:0c"
6637 routed_src_mac = "00:22:bd:f8:19:ff"
6642 t4 = VppIpTable(self, 1)
6644 t6 = VppIpTable(self, 1, True)
6647 rd1 = VppGbpRouteDomain(self, 2, 55, t4, t6)
6648 rd1.add_vpp_config()
6650 self.loop0.set_mac(self.router_mac)
6653 # Bind the BVI to the RD
6655 bind_l0_ip4 = VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
6656 bind_l0_ip6 = VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
6659 # Pg7 hosts a BD's BUM
6660 # Pg1 some other l3 interface
6662 self.pg7.config_ip4()
6663 self.pg7.resolve_arp()
6666 # a GBP external bridge domains for the EPs
6668 bd1 = VppBridgeDomain(self, 1)
6669 bd1.add_vpp_config()
6670 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0, None, None)
6671 gbd1.add_vpp_config()
6674 # The Endpoint-groups in which the external endpoints exist
6676 epg_220 = VppGbpEndpointGroup(
6686 VppGbpEndpointRetention(4),
6688 epg_220.add_vpp_config()
6690 # the BVIs have the subnet applied ...
6691 ip4_addr = VppIpInterfaceAddress(
6692 self, gbd1.bvi, "10.0.0.128", 24, bind=bind_l0_ip4
6695 # ... which is an Anonymous L3-out subnets
6696 l3o_1 = VppGbpSubnet(
6701 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_ANON_L3_OUT,
6704 l3o_1.add_vpp_config()
6707 # an external interface attached to the outside world and the
6710 VppL2Vtr(self, self.vlan_100, L2_VTR_OP.L2_POP_1).add_vpp_config()
6711 VppL2Vtr(self, self.vlan_101, L2_VTR_OP.L2_POP_1).add_vpp_config()
6714 # vlan_100 and vlan_101 are anonymous l3-out interfaces
6716 ext_itf = VppGbpExtItf(self, self.vlan_100, bd1, rd1, anon=True)
6717 ext_itf.add_vpp_config()
6718 ext_itf = VppGbpExtItf(self, self.vlan_101, bd1, rd1, anon=True)
6719 ext_itf.add_vpp_config()
6722 # an unicast vxlan-gbp for inter-RD traffic
6724 vx_tun_l3 = VppGbpVxlanTunnel(
6728 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
6731 vx_tun_l3.add_vpp_config()
6734 # A remote external endpoint
6736 rep = VppGbpEndpoint(
6745 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
6747 self.pg7.remote_ip4,
6750 rep.add_vpp_config()
6753 # ARP packet from host in external subnet are accepted, flooded and
6754 # replied to. We expect 2 packets:
6755 # - APR request flooded over the other vlan subif
6756 # - ARP reply from BVI
6759 Ether(src=self.vlan_100.remote_mac, dst="ff:ff:ff:ff:ff:ff")
6765 hwsrc=self.vlan_100.remote_mac,
6766 hwdst="ff:ff:ff:ff:ff:ff",
6769 rxs = self.send_and_expect(self.pg0, p_arp * 1, self.pg0, n_rx=2)
6772 Ether(src=self.vlan_101.remote_mac, dst="ff:ff:ff:ff:ff:ff")
6778 hwsrc=self.vlan_101.remote_mac,
6779 hwdst="ff:ff:ff:ff:ff:ff",
6782 rxs = self.send_and_expect(self.pg0, p_arp * 1, self.pg0, n_rx=2)
6785 # remote to external
6788 Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac)
6789 / IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4)
6790 / UDP(sport=1234, dport=48879)
6791 / VXLAN(vni=vx_tun_l3.vni, gpid=epg_220.sclass, flags=0x88)
6792 / Ether(src=self.pg0.remote_mac, dst=str(self.router_mac))
6793 / IP(src=str(rep.ip4), dst="10.0.0.100")
6794 / UDP(sport=1234, dport=1234)
6795 / Raw(b"\xa5" * 100)
6797 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
6800 # local EP pings router
6803 Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac))
6805 / IP(src="10.0.0.100", dst="10.0.0.128")
6806 / ICMP(type="echo-request")
6808 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
6811 self.assertEqual(rx[Ether].src, str(self.router_mac))
6812 self.assertEqual(rx[Ether].dst, self.vlan_100.remote_mac)
6813 self.assertEqual(rx[Dot1Q].vlan, 100)
6816 # local EP pings other local EP
6819 Ether(src=self.vlan_100.remote_mac, dst=self.vlan_101.remote_mac)
6821 / IP(src="10.0.0.100", dst="10.0.0.101")
6822 / ICMP(type="echo-request")
6824 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
6827 self.assertEqual(rx[Ether].src, self.vlan_100.remote_mac)
6828 self.assertEqual(rx[Ether].dst, self.vlan_101.remote_mac)
6829 self.assertEqual(rx[Dot1Q].vlan, 101)
6832 # A subnet reachable through an external router on vlan 100
6834 ip_220 = VppIpRoute(
6838 [VppRoutePath("10.0.0.100", epg_220.bvi.sw_if_index)],
6839 table_id=t4.table_id,
6841 ip_220.add_vpp_config()
6843 l3o_220 = VppGbpSubnet(
6848 # note: this a "regular" L3 out subnet (not connected)
6849 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
6852 l3o_220.add_vpp_config()
6855 # A subnet reachable through an external router on vlan 101
6857 ip_221 = VppIpRoute(
6861 [VppRoutePath("10.0.0.101", epg_220.bvi.sw_if_index)],
6862 table_id=t4.table_id,
6864 ip_221.add_vpp_config()
6866 l3o_221 = VppGbpSubnet(
6871 # note: this a "regular" L3 out subnet (not connected)
6872 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
6875 l3o_221.add_vpp_config()
6878 # ping between hosts in remote subnets
6879 # dropped without a contract
6882 Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac))
6884 / IP(src="10.220.0.1", dst="10.221.0.1")
6885 / ICMP(type="echo-request")
6888 rxs = self.send_and_assert_no_replies(self.pg0, p * 1)
6891 # contract for the external nets to communicate
6893 rule4 = AclRule(is_permit=1, proto=17)
6895 src_prefix=IPv6Network((0, 0)),
6896 dst_prefix=IPv6Network((0, 0)),
6900 acl = VppAcl(self, rules=[rule4, rule6])
6901 acl.add_vpp_config()
6903 c1 = 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],
6926 # Contracts allowing ext-net 200 to talk with external EPs
6928 c2 = VppGbpContract(
6936 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
6937 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
6941 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
6942 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
6946 [ETH_P_IP, ETH_P_IPV6],
6949 c3 = VppGbpContract(
6957 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
6958 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
6962 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
6963 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
6967 [ETH_P_IP, ETH_P_IPV6],
6972 # ping between hosts in remote subnets
6975 Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac))
6977 / IP(src="10.220.0.1", dst="10.221.0.1")
6978 / UDP(sport=1234, dport=1234)
6979 / Raw(b"\xa5" * 100)
6982 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
6985 self.assertEqual(rx[Ether].src, str(self.router_mac))
6986 self.assertEqual(rx[Ether].dst, self.vlan_101.remote_mac)
6987 self.assertEqual(rx[Dot1Q].vlan, 101)
6989 # we did not learn these external hosts
6990 self.assertFalse(find_gbp_endpoint(self, ip="10.220.0.1"))
6991 self.assertFalse(find_gbp_endpoint(self, ip="10.221.0.1"))
6994 # from remote external EP to local external EP
6997 Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac)
6998 / IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4)
6999 / UDP(sport=1234, dport=48879)
7000 / VXLAN(vni=444, gpid=113, flags=0x88)
7001 / Ether(src=self.pg0.remote_mac, dst=str(self.router_mac))
7002 / IP(src=rep.ip4, dst="10.220.0.1")
7003 / UDP(sport=1234, dport=1234)
7004 / Raw(b"\xa5" * 100)
7007 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
7010 # ping from an external host to the remote external EP
7013 Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac))
7015 / IP(src="10.220.0.1", dst=rep.ip4)
7016 / UDP(sport=1234, dport=1234)
7017 / Raw(b"\xa5" * 100)
7020 rxs = self.send_and_expect(self.pg0, p * 1, self.pg7)
7023 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
7024 # self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
7025 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
7026 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
7027 self.assertEqual(rx[VXLAN].vni, 444)
7028 self.assertTrue(rx[VXLAN].flags.G)
7029 self.assertTrue(rx[VXLAN].flags.Instance)
7030 # the sclass of the ext-net the packet came from
7031 self.assertEqual(rx[VXLAN].gpid, 4220)
7032 # policy was applied to the original IP packet
7033 self.assertTrue(rx[VXLAN].gpflags.A)
7034 # since it's an external host the reciever should not learn it
7035 self.assertTrue(rx[VXLAN].gpflags.D)
7036 inner = rx[VXLAN].payload
7037 self.assertEqual(inner[IP].src, "10.220.0.1")
7038 self.assertEqual(inner[IP].dst, rep.ip4)
7041 # An external subnet reachable via the remote external EP
7045 # first the VXLAN-GBP tunnel over which it is reached
7047 vx_tun_r = VppVxlanGbpTunnel(
7050 self.pg7.remote_ip4,
7053 VppEnum.vl_api_vxlan_gbp_api_tunnel_mode_t.VXLAN_GBP_API_TUNNEL_MODE_L3
7056 vx_tun_r.add_vpp_config()
7057 VppIpInterfaceBind(self, vx_tun_r, t4).add_vpp_config()
7059 self.logger.info(self.vapi.cli("sh vxlan-gbp tunnel"))
7062 # then the special adj to resolve through on that tunnel
7065 self, vx_tun_r.sw_if_index, "00:0c:0c:0c:0c:0c", self.pg7.remote_ip4
7070 # the route via the adj above
7072 ip_222 = VppIpRoute(
7076 [VppRoutePath(self.pg7.remote_ip4, vx_tun_r.sw_if_index)],
7077 table_id=t4.table_id,
7079 ip_222.add_vpp_config()
7081 l3o_222 = VppGbpSubnet(
7086 # note: this a "regular" l3out subnet (not connected)
7087 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
7090 l3o_222.add_vpp_config()
7093 # ping between hosts in local and remote external subnets
7094 # dropped without a contract
7097 Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac))
7099 / IP(src="10.220.0.1", dst="10.222.0.1")
7100 / UDP(sport=1234, dport=1234)
7101 / Raw(b"\xa5" * 100)
7104 rxs = self.send_and_assert_no_replies(self.pg0, p * 1)
7107 # Add contracts ext-nets for 220 -> 222
7109 c4 = VppGbpContract(
7117 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
7118 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
7122 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
7123 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
7127 [ETH_P_IP, ETH_P_IPV6],
7132 # ping from host in local to remote external subnets
7135 Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac))
7137 / IP(src="10.220.0.1", dst="10.222.0.1")
7138 / UDP(sport=1234, dport=1234)
7139 / Raw(b"\xa5" * 100)
7142 rxs = self.send_and_expect(self.pg0, p * 3, self.pg7)
7145 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
7146 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
7147 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
7148 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
7149 self.assertEqual(rx[VXLAN].vni, 445)
7150 self.assertTrue(rx[VXLAN].flags.G)
7151 self.assertTrue(rx[VXLAN].flags.Instance)
7152 # the sclass of the ext-net the packet came from
7153 self.assertEqual(rx[VXLAN].gpid, 4220)
7154 # policy was applied to the original IP packet
7155 self.assertTrue(rx[VXLAN].gpflags.A)
7156 # since it's an external host the reciever should not learn it
7157 self.assertTrue(rx[VXLAN].gpflags.D)
7158 inner = rx[VXLAN].payload
7159 self.assertEqual(inner[Ether].dst, "00:0c:0c:0c:0c:0c")
7160 self.assertEqual(inner[IP].src, "10.220.0.1")
7161 self.assertEqual(inner[IP].dst, "10.222.0.1")
7164 # ping from host in remote to local external subnets
7165 # there's no contract for this, but the A bit is set.
7168 Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac)
7169 / IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4)
7170 / UDP(sport=1234, dport=48879)
7171 / VXLAN(vni=445, gpid=4222, flags=0x88, gpflags="A")
7172 / Ether(src=self.pg0.remote_mac, dst=str(self.router_mac))
7173 / IP(src="10.222.0.1", dst="10.220.0.1")
7174 / UDP(sport=1234, dport=1234)
7175 / Raw(b"\xa5" * 100)
7178 rxs = self.send_and_expect(self.pg7, p * 3, self.pg0)
7179 self.assertFalse(find_gbp_endpoint(self, ip="10.222.0.1"))
7182 # ping from host in remote to remote external subnets
7183 # this is dropped by reflection check.
7186 Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac)
7187 / IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4)
7188 / UDP(sport=1234, dport=48879)
7189 / VXLAN(vni=445, gpid=4222, flags=0x88, gpflags="A")
7190 / Ether(src=self.pg0.remote_mac, dst=str(self.router_mac))
7191 / IP(src="10.222.0.1", dst="10.222.0.2")
7192 / UDP(sport=1234, dport=1234)
7193 / Raw(b"\xa5" * 100)
7196 rxs = self.send_and_assert_no_replies(self.pg7, p * 3)
7201 self.vlan_101.set_vtr(L2_VTR_OP.L2_DISABLED)
7202 self.vlan_100.set_vtr(L2_VTR_OP.L2_DISABLED)
7203 self.pg7.unconfig_ip4()
7204 # make sure the programmed EP is no longer learnt from DP
7205 self.wait_for_ep_timeout(sw_if_index=rep.itf.sw_if_index, ip=rep.ip4)
7208 if __name__ == "__main__":
7209 unittest.main(testRunner=VppTestRunner)