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, \
48 from vpp_neighbor import VppNeighbor
49 from vpp_acl import AclRule, VppAcl
54 def find_gbp_endpoint(test, sw_if_index=None, ip=None, mac=None,
55 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 \
68 dst != str(ep.endpoint.tun.dst):
71 if ep.endpoint.sw_if_index != sw_if_index:
74 if ep.endpoint.sclass != sclass:
77 if flags != (flags & ep.endpoint.flags):
80 for eip in ep.endpoint.ips:
84 if vmac == ep.endpoint.mac:
90 def find_gbp_vxlan(test: VppTestCase, vni):
91 ts = test.vapi.gbp_vxlan_tunnel_dump()
93 if t.tunnel.vni == vni:
98 class VppGbpEndpoint(VppObject):
105 return str(self.vmac)
125 return [self.ip4, self.ip6]
129 return [self.fip4, self.fip6]
131 def __init__(self, test, itf, epg, recirc, ip4, fip4, ip6, fip6,
148 self.vmac = MACAddress(self.itf.remote_mac)
150 self.vmac = MACAddress("00:00:00:00:00:00")
153 self.tun_src = tun_src
154 self.tun_dst = tun_dst
157 ips = [self.ip4, self.ip6]
159 "sw_if_index": self.itf.sw_if_index,
162 "mac": self.vmac.packed,
163 "sclass": self.epg.sclass,
171 def add_vpp_config(self):
172 res = self._test.vapi.gbp_endpoint_add(
173 endpoint=self.encode(),
175 self.handle = res.handle
176 self._test.registry.register(self, self._test.logger)
178 def remove_vpp_config(self):
179 self._test.vapi.gbp_endpoint_del(handle=self.handle)
182 return "gbp-endpoint:[%d==%d:%s:%d]" % (self.handle,
183 self.itf.sw_if_index,
187 def query_vpp_config(self):
188 return find_gbp_endpoint(self._test,
189 self.itf.sw_if_index,
193 class VppGbpRecirc(VppObject):
195 GBP Recirculation Interface
198 def __init__(self, test, epg, recirc, is_ext=False):
206 "is_ext": self.is_ext,
207 "sw_if_index": self.recirc.sw_if_index,
208 "sclass": self.epg.sclass,
211 def add_vpp_config(self):
212 self._test.vapi.gbp_recirc_add_del(
214 recirc=self.encode(),
216 self._test.registry.register(self, self._test.logger)
218 def remove_vpp_config(self):
219 self._test.vapi.gbp_recirc_add_del(
221 recirc=self.encode(),
225 return "gbp-recirc:[%d]" % (self.recirc.sw_if_index)
227 def query_vpp_config(self):
228 rs = self._test.vapi.gbp_recirc_dump()
230 if r.recirc.sw_if_index == self.recirc.sw_if_index:
235 class VppGbpExtItf(VppObject):
237 GBP ExtItfulation Interface
240 def __init__(self, test, itf, bd, rd, anon=False):
245 self.flags = 1 if anon else 0
249 "sw_if_index": self.itf.sw_if_index,
250 "bd_id": self.bd.bd_id,
251 "rd_id": self.rd.rd_id,
255 def add_vpp_config(self):
256 self._test.vapi.gbp_ext_itf_add_del(
258 ext_itf=self.encode(),
260 self._test.registry.register(self, self._test.logger)
262 def remove_vpp_config(self):
263 self._test.vapi.gbp_ext_itf_add_del(
265 ext_itf=self.encode(),
269 return "gbp-ext-itf:[%d]%s" % (self.itf.sw_if_index,
270 " [anon]" if self.flags else "")
272 def query_vpp_config(self):
273 rs = self._test.vapi.gbp_ext_itf_dump()
275 if r.ext_itf.sw_if_index == self.itf.sw_if_index:
280 class VppGbpSubnet(VppObject):
285 def __init__(self, test, rd, address, address_len,
286 type, sw_if_index=0xffffffff, sclass=0xffff):
287 # TODO: replace hardcoded defaults when vpp_papi supports
288 # defaults in typedefs
290 self.rd_id = rd.rd_id
291 a = ip_address(address)
293 self.prefix = IPv4Network("%s/%d" % (address, address_len),
296 self.prefix = IPv6Network("%s/%d" % (address, address_len),
299 self.sw_if_index = sw_if_index
305 "sw_if_index": self.sw_if_index,
306 "sclass": self.sclass,
307 "prefix": self.prefix,
311 def add_vpp_config(self):
312 self._test.vapi.gbp_subnet_add_del(
314 subnet=self.encode(),
316 self._test.registry.register(self, self._test.logger)
318 def remove_vpp_config(self):
319 self._test.vapi.gbp_subnet_add_del(
325 return "gbp-subnet:[%d-%s]" % (self.rd_id, self.prefix)
327 def query_vpp_config(self):
328 ss = self._test.vapi.gbp_subnet_dump()
330 if s.subnet.rd_id == self.rd_id and \
331 s.subnet.type == self.type and \
332 s.subnet.prefix == self.prefix:
337 class VppGbpEndpointRetention(object):
338 def __init__(self, remote_ep_timeout=0xffffffff):
339 self.remote_ep_timeout = remote_ep_timeout
342 return {'remote_ep_timeout': self.remote_ep_timeout}
345 class VppGbpEndpointGroup(VppObject):
350 def __init__(self, test, vnid, sclass, rd, bd, uplink,
351 bvi, bvi_ip4, bvi_ip6=None,
352 retention=VppGbpEndpointRetention()):
356 self.bvi_ip4 = bvi_ip4
357 self.bvi_ip6 = bvi_ip6
359 self.bd = bd # VppGbpBridgeDomain
364 self.retention = retention
366 def encode(self) -> dict:
368 "uplink_sw_if_index": self.uplink.sw_if_index
369 if self.uplink else INDEX_INVALID,
370 "bd_id": self.bd.bd.bd_id,
371 "rd_id": self.rd.rd_id,
373 "sclass": self.sclass,
374 "retention": self.retention.encode(),
377 def add_vpp_config(self):
378 self._test.vapi.gbp_endpoint_group_add(epg=self.encode())
379 self._test.registry.register(self, self._test.logger)
381 def remove_vpp_config(self):
382 self._test.vapi.gbp_endpoint_group_del(sclass=self.sclass)
384 def object_id(self) -> str:
385 return "gbp-endpoint-group:[%d]" % (self.vnid)
387 def query_vpp_config(self) -> bool:
388 epgs = self._test.vapi.gbp_endpoint_group_dump()
390 if epg.epg.vnid == self.vnid:
395 class VppGbpBridgeDomain(VppObject):
400 def __init__(self, test, bd, rd, bvi,
401 uu_fwd: typing.Optional[VppVxlanGbpTunnel] = None,
402 bm_flood=None, learn=True,
403 uu_drop=False, bm_drop=False,
408 self.bm_flood = bm_flood
412 e = VppEnum.vl_api_gbp_bridge_domain_flags_t
414 self.flags = e.GBP_BD_API_FLAG_NONE
416 self.flags |= e.GBP_BD_API_FLAG_DO_NOT_LEARN
418 self.flags |= e.GBP_BD_API_FLAG_UU_FWD_DROP
420 self.flags |= e.GBP_BD_API_FLAG_MCAST_DROP
422 self.flags |= e.GBP_BD_API_FLAG_UCAST_ARP
424 def encode(self) -> dict:
427 "bvi_sw_if_index": self.bvi.sw_if_index,
428 "uu_fwd_sw_if_index": self.uu_fwd.sw_if_index
429 if self.uu_fwd else INDEX_INVALID,
430 "bm_flood_sw_if_index": self.bm_flood.sw_if_index
431 if self.bm_flood else INDEX_INVALID,
432 "bd_id": self.bd.bd_id,
433 "rd_id": self.rd.rd_id,
436 def add_vpp_config(self):
437 self._test.vapi.gbp_bridge_domain_add(
440 self._test.registry.register(self, self._test.logger)
442 def remove_vpp_config(self):
443 self._test.vapi.gbp_bridge_domain_del(bd_id=self.bd.bd_id)
445 def object_id(self) -> str:
446 return "gbp-bridge-domain:[%d]" % (self.bd.bd_id)
448 def query_vpp_config(self) -> bool:
449 bds = self._test.vapi.gbp_bridge_domain_dump()
451 if bd.bd.bd_id == self.bd.bd_id:
456 class VppGbpRouteDomain(VppObject):
461 def __init__(self, test, rd_id, scope, t4, t6, ip4_uu=None, ip6_uu=None):
470 def encode(self) -> dict:
474 "ip4_table_id": self.t4.table_id,
475 "ip6_table_id": self.t6.table_id,
476 "ip4_uu_sw_if_index": self.ip4_uu.sw_if_index
477 if self.ip4_uu else INDEX_INVALID,
478 "ip6_uu_sw_if_index": self.ip6_uu.sw_if_index
479 if self.ip6_uu else INDEX_INVALID,
483 def add_vpp_config(self):
484 self._test.vapi.gbp_route_domain_add(
487 self._test.registry.register(self, self._test.logger)
489 def remove_vpp_config(self):
490 self._test.vapi.gbp_route_domain_del(rd_id=self.rd_id)
493 return "gbp-route-domain:[%d]" % (self.rd_id)
495 def query_vpp_config(self):
496 rds = self._test.vapi.gbp_route_domain_dump()
498 if rd.rd.rd_id == self.rd_id:
503 class VppGbpContractNextHop:
504 def __init__(self, mac, bd, ip, rd):
510 def encode(self) -> dict:
513 "mac": self.mac.packed,
514 "bd_id": self.bd.bd.bd_id,
515 "rd_id": self.rd.rd_id,
519 class VppGbpContractRule:
520 def __init__(self, action, hash_mode, nhs=None):
522 self.hash_mode = hash_mode
523 self.nhs = [] if nhs is None else nhs
525 def encode(self) -> dict:
528 nhs.append(nh.encode())
531 return {'action': self.action,
533 'hash_mode': self.hash_mode,
534 'n_nhs': len(self.nhs),
538 return '<VppGbpContractRule action=%s, hash_mode=%s>' % (
539 self.action, self.hash_mode)
542 class VppGbpContract(VppObject):
547 def __init__(self, test, scope, sclass, dclass, acl_index,
548 rules: list, allowed_ethertypes: list):
551 self.acl_index = acl_index
555 self.allowed_ethertypes = allowed_ethertypes
556 while (len(self.allowed_ethertypes) < 16):
557 self.allowed_ethertypes.append(0)
559 def encode(self) -> dict:
562 rules.append(r.encode())
564 'acl_index': self.acl_index,
566 'sclass': self.sclass,
567 'dclass': self.dclass,
568 'n_rules': len(rules),
570 'n_ether_types': len(self.allowed_ethertypes),
571 'allowed_ethertypes': self.allowed_ethertypes,
574 def add_vpp_config(self):
575 r = self._test.vapi.gbp_contract_add_del(
577 contract=self.encode()
580 self.stats_index = r.stats_index
581 self._test.registry.register(self, self._test.logger)
583 def remove_vpp_config(self):
584 self._test.vapi.gbp_contract_add_del(
586 contract=self.encode(),
590 return "gbp-contract:[%d:%d:%d:%d]" % (self.scope,
595 def query_vpp_config(self):
596 cs = self._test.vapi.gbp_contract_dump()
598 if c.contract.scope == self.scope \
599 and c.contract.sclass == self.sclass \
600 and c.contract.dclass == self.dclass:
604 def get_drop_stats(self):
605 c = self._test.statistics.get_counter("/net/gbp/contract/drop")
606 return c[0][self.stats_index]
608 def get_permit_stats(self):
609 c = self._test.statistics.get_counter("/net/gbp/contract/permit")
610 return c[0][self.stats_index]
613 class VppGbpVxlanTunnel(VppInterface):
618 def __init__(self, test, vni, bd_rd_id, mode, src):
619 super(VppGbpVxlanTunnel, self).__init__(test)
622 self.bd_rd_id = bd_rd_id
626 def encode(self) -> dict:
630 "bd_rd_id": self.bd_rd_id,
634 def add_vpp_config(self):
635 r = self._test.vapi.gbp_vxlan_tunnel_add(
636 tunnel=self.encode(),
638 self.set_sw_if_index(r.sw_if_index)
639 self._test.registry.register(self, self._test.logger)
641 def remove_vpp_config(self):
642 self._test.vapi.gbp_vxlan_tunnel_del(vni=self.vni)
645 return "gbp-vxlan:%d" % (self.sw_if_index)
647 def query_vpp_config(self):
648 return find_gbp_vxlan(self._test, self.vni)
651 @tag_fixme_vpp_workers
652 class TestGBP(VppTestCase):
653 """ GBP Test Case """
656 def nat_config_flags(self):
657 return VppEnum.vl_api_nat_config_flags_t
660 def nat44_config_flags(self):
661 return VppEnum.vl_api_nat44_config_flags_t
665 super(TestGBP, cls).setUpClass()
668 def tearDownClass(cls):
669 super(TestGBP, cls).tearDownClass()
672 super(TestGBP, self).setUp()
674 self.create_pg_interfaces(range(9))
675 self.create_loopback_interfaces(8)
677 self.router_mac = MACAddress("00:11:22:33:44:55")
679 for i in self.pg_interfaces:
681 for i in self.lo_interfaces:
684 self.vlan_100 = VppDot1QSubint(self, self.pg0, 100)
685 self.vlan_100.admin_up()
686 self.vlan_101 = VppDot1QSubint(self, self.pg0, 101)
687 self.vlan_101.admin_up()
688 self.vlan_102 = VppDot1QSubint(self, self.pg0, 102)
689 self.vlan_102.admin_up()
692 for i in self.pg_interfaces:
694 super(TestGBP, self).tearDown()
695 for i in self.lo_interfaces:
696 i.remove_vpp_config()
697 self.lo_interfaces = []
698 self.vlan_102.remove_vpp_config()
699 self.vlan_101.remove_vpp_config()
700 self.vlan_100.remove_vpp_config()
702 def send_and_expect_bridged(self, src, tx, dst):
703 rx = self.send_and_expect(src, tx, dst)
706 self.assertEqual(r[Ether].src, tx[0][Ether].src)
707 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
708 self.assertEqual(r[IP].src, tx[0][IP].src)
709 self.assertEqual(r[IP].dst, tx[0][IP].dst)
712 def send_and_expect_bridged6(self, src, tx, dst):
713 rx = self.send_and_expect(src, tx, dst)
716 self.assertEqual(r[Ether].src, tx[0][Ether].src)
717 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
718 self.assertEqual(r[IPv6].src, tx[0][IPv6].src)
719 self.assertEqual(r[IPv6].dst, tx[0][IPv6].dst)
722 def send_and_expect_routed(self, src, tx, dst, src_mac):
723 rx = self.send_and_expect(src, tx, dst)
726 self.assertEqual(r[Ether].src, src_mac)
727 self.assertEqual(r[Ether].dst, dst.remote_mac)
728 self.assertEqual(r[IP].src, tx[0][IP].src)
729 self.assertEqual(r[IP].dst, tx[0][IP].dst)
732 def send_and_expect_routed6(self, src, tx, dst, src_mac):
733 rx = self.send_and_expect(src, tx, dst)
736 self.assertEqual(r[Ether].src, src_mac)
737 self.assertEqual(r[Ether].dst, dst.remote_mac)
738 self.assertEqual(r[IPv6].src, tx[0][IPv6].src)
739 self.assertEqual(r[IPv6].dst, tx[0][IPv6].dst)
742 def send_and_expect_natted(self, src, tx, dst, src_ip):
743 rx = self.send_and_expect(src, tx, dst)
746 self.assertEqual(r[Ether].src, tx[0][Ether].src)
747 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
748 self.assertEqual(r[IP].src, src_ip)
749 self.assertEqual(r[IP].dst, tx[0][IP].dst)
752 def send_and_expect_natted6(self, src, tx, dst, src_ip):
753 rx = self.send_and_expect(src, tx, dst)
756 self.assertEqual(r[Ether].src, tx[0][Ether].src)
757 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
758 self.assertEqual(r[IPv6].src, src_ip)
759 self.assertEqual(r[IPv6].dst, tx[0][IPv6].dst)
762 def send_and_expect_unnatted(self, src, tx, dst, dst_ip):
763 rx = self.send_and_expect(src, tx, dst)
766 self.assertEqual(r[Ether].src, tx[0][Ether].src)
767 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
768 self.assertEqual(r[IP].dst, dst_ip)
769 self.assertEqual(r[IP].src, tx[0][IP].src)
772 def send_and_expect_unnatted6(self, src, tx, dst, dst_ip):
773 rx = self.send_and_expect(src, tx, dst)
776 self.assertEqual(r[Ether].src, tx[0][Ether].src)
777 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
778 self.assertEqual(r[IPv6].dst, dst_ip)
779 self.assertEqual(r[IPv6].src, tx[0][IPv6].src)
782 def send_and_expect_double_natted(self, src, tx, dst, src_ip, dst_ip):
783 rx = self.send_and_expect(src, tx, dst)
786 self.assertEqual(r[Ether].src, str(self.router_mac))
787 self.assertEqual(r[Ether].dst, dst.remote_mac)
788 self.assertEqual(r[IP].dst, dst_ip)
789 self.assertEqual(r[IP].src, src_ip)
792 def send_and_expect_double_natted6(self, src, tx, dst, src_ip, dst_ip):
793 rx = self.send_and_expect(src, tx, dst)
796 self.assertEqual(r[Ether].src, str(self.router_mac))
797 self.assertEqual(r[Ether].dst, dst.remote_mac)
798 self.assertEqual(r[IPv6].dst, dst_ip)
799 self.assertEqual(r[IPv6].src, src_ip)
802 def send_and_expect_no_arp(self, src, tx, dst):
803 self.pg_send(src, tx)
804 dst.get_capture(0, timeout=1)
805 dst.assert_nothing_captured(remark="")
807 def send_and_expect_arp(self, src, tx, dst):
808 rx = self.send_and_expect(src, tx, dst)
811 self.assertEqual(r[Ether].src, tx[0][Ether].src)
812 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
813 self.assertEqual(r[ARP].psrc, tx[0][ARP].psrc)
814 self.assertEqual(r[ARP].pdst, tx[0][ARP].pdst)
815 self.assertEqual(r[ARP].hwsrc, tx[0][ARP].hwsrc)
816 self.assertEqual(r[ARP].hwdst, tx[0][ARP].hwdst)
820 """ Group Based Policy """
822 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
827 gt4 = VppIpTable(self, 0)
829 gt6 = VppIpTable(self, 0, is_ip6=True)
831 nt4 = VppIpTable(self, 20)
833 nt6 = VppIpTable(self, 20, is_ip6=True)
836 rd0 = VppGbpRouteDomain(self, 0, 400, gt4, gt6, None, None)
837 rd20 = VppGbpRouteDomain(self, 20, 420, nt4, nt6, None, None)
840 rd20.add_vpp_config()
845 bd1 = VppBridgeDomain(self, 1)
846 bd2 = VppBridgeDomain(self, 2)
847 bd20 = VppBridgeDomain(self, 20)
851 bd20.add_vpp_config()
853 gbd1 = VppGbpBridgeDomain(self, bd1, rd0, self.loop0)
854 gbd2 = VppGbpBridgeDomain(self, bd2, rd0, self.loop1)
855 gbd20 = VppGbpBridgeDomain(self, bd20, rd20, self.loop2)
857 gbd1.add_vpp_config()
858 gbd2.add_vpp_config()
859 gbd20.add_vpp_config()
862 # 3 EPGs, 2 of which share a BD.
863 # 2 NAT EPGs, one for floating-IP subnets, the other for internet
865 epgs = [VppGbpEndpointGroup(self, 220, 1220, rd0, gbd1,
866 self.pg4, self.loop0,
867 "10.0.0.128", "2001:10::128"),
868 VppGbpEndpointGroup(self, 221, 1221, rd0, gbd1,
869 self.pg5, self.loop0,
870 "10.0.1.128", "2001:10:1::128"),
871 VppGbpEndpointGroup(self, 222, 1222, rd0, gbd2,
872 self.pg6, self.loop1,
873 "10.0.2.128", "2001:10:2::128"),
874 VppGbpEndpointGroup(self, 333, 1333, rd20, gbd20,
875 self.pg7, self.loop2,
876 "11.0.0.128", "3001::128"),
877 VppGbpEndpointGroup(self, 444, 1444, rd20, gbd20,
878 self.pg8, self.loop2,
879 "11.0.0.129", "3001::129")]
880 recircs = [VppGbpRecirc(self, epgs[0], self.loop3),
881 VppGbpRecirc(self, epgs[1], self.loop4),
882 VppGbpRecirc(self, epgs[2], self.loop5),
883 VppGbpRecirc(self, epgs[3], self.loop6, is_ext=True),
884 VppGbpRecirc(self, epgs[4], self.loop7, is_ext=True)]
887 recirc_nat = recircs[3]
890 # 4 end-points, 2 in the same subnet, 3 in the same BD
892 eps = [VppGbpEndpoint(self, self.pg0,
894 "10.0.0.1", "11.0.0.1",
895 "2001:10::1", "3001::1"),
896 VppGbpEndpoint(self, self.pg1,
898 "10.0.0.2", "11.0.0.2",
899 "2001:10::2", "3001::2"),
900 VppGbpEndpoint(self, self.pg2,
902 "10.0.1.1", "11.0.0.3",
903 "2001:10:1::1", "3001::3"),
904 VppGbpEndpoint(self, self.pg3,
906 "10.0.2.1", "11.0.0.4",
907 "2001:10:2::1", "3001::4")]
909 self.vapi.nat44_ed_plugin_enable_disable(enable=1)
910 self.vapi.nat66_plugin_enable_disable(enable=1)
913 # Config related to each of the EPGs
916 # IP config on the BVI interfaces
917 if epg != epgs[1] and epg != epgs[4]:
918 b4 = VppIpInterfaceBind(self, epg.bvi,
919 epg.rd.t4).add_vpp_config()
920 b6 = VppIpInterfaceBind(self, epg.bvi,
921 epg.rd.t6).add_vpp_config()
922 epg.bvi.set_mac(self.router_mac)
924 # The BVIs are NAT inside interfaces
925 flags = self.nat_config_flags.NAT_IS_INSIDE
926 self.vapi.nat44_interface_add_del_feature(
927 sw_if_index=epg.bvi.sw_if_index,
928 flags=flags, is_add=1)
929 self.vapi.nat66_add_del_interface(
930 sw_if_index=epg.bvi.sw_if_index,
931 flags=flags, is_add=1)
933 if_ip4 = VppIpInterfaceAddress(self, epg.bvi,
935 bind=b4).add_vpp_config()
936 if_ip6 = VppIpInterfaceAddress(self, epg.bvi,
938 bind=b6).add_vpp_config()
940 # EPG uplink interfaces in the RD
941 VppIpInterfaceBind(self, epg.uplink, epg.rd.t4).add_vpp_config()
942 VppIpInterfaceBind(self, epg.uplink, epg.rd.t6).add_vpp_config()
944 # add the BD ARP termination entry for BVI IP
945 epg.bd_arp_ip4 = VppBridgeDomainArpEntry(self, epg.bd.bd,
946 str(self.router_mac),
948 epg.bd_arp_ip6 = VppBridgeDomainArpEntry(self, epg.bd.bd,
949 str(self.router_mac),
951 epg.bd_arp_ip4.add_vpp_config()
952 epg.bd_arp_ip6.add_vpp_config()
957 for recirc in recircs:
958 # EPG's ingress recirculation interface maps to its RD
959 VppIpInterfaceBind(self, recirc.recirc,
960 recirc.epg.rd.t4).add_vpp_config()
961 VppIpInterfaceBind(self, recirc.recirc,
962 recirc.epg.rd.t6).add_vpp_config()
964 self.vapi.nat44_interface_add_del_feature(
965 sw_if_index=recirc.recirc.sw_if_index, is_add=1)
966 self.vapi.nat66_add_del_interface(
967 sw_if_index=recirc.recirc.sw_if_index, is_add=1)
969 recirc.add_vpp_config()
971 for recirc in recircs:
972 self.assertTrue(find_bridge_domain_port(self,
973 recirc.epg.bd.bd.bd_id,
974 recirc.recirc.sw_if_index))
977 self.pg_enable_capture(self.pg_interfaces)
980 # routes to the endpoints. We need these since there are no
981 # adj-fibs due to the fact the the BVI address has /32 and
982 # the subnet is not attached.
984 for (ip, fip) in zip(ep.ips, ep.fips):
985 # Add static mappings for each EP from the 10/8 to 11/8 network
986 if ip_address(ip).version == 4:
987 flags = self.nat_config_flags.NAT_IS_ADDR_ONLY
988 self.vapi.nat44_add_del_static_mapping(
991 external_ip_address=fip,
992 external_sw_if_index=0xFFFFFFFF,
996 self.vapi.nat66_add_del_static_mapping(
998 external_ip_address=fip,
1004 self.logger.info(self.vapi.cli("sh gbp endpoint"))
1006 # ... results in a Gratuitous ARP/ND on the EPG's uplink
1007 rx = ep.epg.uplink.get_capture(len(ep.ips) + 1, timeout=0.2)
1009 for ii, ip in enumerate(ep.ips):
1012 if ip_address(ip).version == 6:
1013 self.assertTrue(p.haslayer(ICMPv6ND_NA))
1014 self.assertEqual(p[ICMPv6ND_NA].tgt, ip)
1016 self.assertTrue(p.haslayer(ARP))
1017 self.assertEqual(p[ARP].psrc, ip)
1018 self.assertEqual(p[ARP].pdst, ip)
1020 # add the BD ARP termination entry for floating IP
1022 ba = VppBridgeDomainArpEntry(self, epg_nat.bd.bd, ep.mac,
1026 # floating IPs route via EPG recirc
1028 self, fip, ip_address(fip).max_prefixlen,
1030 ep.recirc.recirc.sw_if_index,
1031 type=FibPathType.FIB_PATH_TYPE_DVR,
1032 proto=get_dpo_proto(fip))],
1036 # L2 FIB entries in the NAT EPG BD to bridge the packets from
1037 # the outside direct to the internal EPG
1038 lf = VppL2FibEntry(self, epg_nat.bd.bd, ep.mac,
1039 ep.recirc.recirc, bvi_mac=0)
1043 # ARP packets for unknown IP are sent to the EPG uplink
1045 pkt_arp = (Ether(dst="ff:ff:ff:ff:ff:ff",
1046 src=self.pg0.remote_mac) /
1048 hwdst="ff:ff:ff:ff:ff:ff",
1049 hwsrc=self.pg0.remote_mac,
1053 self.vapi.cli("clear trace")
1054 self.pg0.add_stream(pkt_arp)
1056 self.pg_enable_capture(self.pg_interfaces)
1059 rxd = epgs[0].uplink.get_capture(1)
1062 # ARP/ND packets get a response
1064 pkt_arp = (Ether(dst="ff:ff:ff:ff:ff:ff",
1065 src=self.pg0.remote_mac) /
1067 hwdst="ff:ff:ff:ff:ff:ff",
1068 hwsrc=self.pg0.remote_mac,
1069 pdst=epgs[0].bvi_ip4,
1072 self.send_and_expect(self.pg0, [pkt_arp], self.pg0)
1074 nsma = in6_getnsma(inet_pton(AF_INET6, eps[0].ip6))
1075 d = inet_ntop(AF_INET6, nsma)
1076 pkt_nd = (Ether(dst=in6_getnsmac(nsma),
1077 src=self.pg0.remote_mac) /
1078 IPv6(dst=d, src=eps[0].ip6) /
1079 ICMPv6ND_NS(tgt=epgs[0].bvi_ip6) /
1080 ICMPv6NDOptSrcLLAddr(lladdr=self.pg0.remote_mac))
1081 self.send_and_expect(self.pg0, [pkt_nd], self.pg0)
1084 # broadcast packets are flooded
1086 pkt_bcast = (Ether(dst="ff:ff:ff:ff:ff:ff",
1087 src=self.pg0.remote_mac) /
1088 IP(src=eps[0].ip4, dst="232.1.1.1") /
1089 UDP(sport=1234, dport=1234) /
1092 self.vapi.cli("clear trace")
1093 self.pg0.add_stream(pkt_bcast)
1095 self.pg_enable_capture(self.pg_interfaces)
1098 rxd = eps[1].itf.get_capture(1)
1099 self.assertEqual(rxd[0][Ether].dst, pkt_bcast[Ether].dst)
1100 rxd = epgs[0].uplink.get_capture(1)
1101 self.assertEqual(rxd[0][Ether].dst, pkt_bcast[Ether].dst)
1104 # packets to non-local L3 destinations dropped
1106 pkt_intra_epg_220_ip4 = (Ether(src=self.pg0.remote_mac,
1107 dst=str(self.router_mac)) /
1110 UDP(sport=1234, dport=1234) /
1112 pkt_inter_epg_222_ip4 = (Ether(src=self.pg0.remote_mac,
1113 dst=str(self.router_mac)) /
1116 UDP(sport=1234, dport=1234) /
1119 self.send_and_assert_no_replies(self.pg0,
1120 pkt_intra_epg_220_ip4 * NUM_PKTS)
1122 pkt_inter_epg_222_ip6 = (Ether(src=self.pg0.remote_mac,
1123 dst=str(self.router_mac)) /
1124 IPv6(src=eps[0].ip6,
1125 dst="2001:10::99") /
1126 UDP(sport=1234, dport=1234) /
1128 self.send_and_assert_no_replies(self.pg0,
1129 pkt_inter_epg_222_ip6 * NUM_PKTS)
1132 # Add the subnet routes
1135 self, rd0, "10.0.0.0", 24,
1136 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1138 self, rd0, "10.0.1.0", 24,
1139 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1141 self, rd0, "10.0.2.0", 24,
1142 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1144 self, rd0, "2001:10::1", 64,
1145 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1147 self, rd0, "2001:10:1::1", 64,
1148 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1150 self, rd0, "2001:10:2::1", 64,
1151 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1152 s41.add_vpp_config()
1153 s42.add_vpp_config()
1154 s43.add_vpp_config()
1155 s61.add_vpp_config()
1156 s62.add_vpp_config()
1157 s63.add_vpp_config()
1159 self.send_and_expect_bridged(eps[0].itf,
1160 pkt_intra_epg_220_ip4 * NUM_PKTS,
1162 self.send_and_expect_bridged(eps[0].itf,
1163 pkt_inter_epg_222_ip4 * NUM_PKTS,
1165 self.send_and_expect_bridged6(eps[0].itf,
1166 pkt_inter_epg_222_ip6 * NUM_PKTS,
1169 self.logger.info(self.vapi.cli("sh ip fib 11.0.0.2"))
1170 self.logger.info(self.vapi.cli("sh gbp endpoint-group"))
1171 self.logger.info(self.vapi.cli("sh gbp endpoint"))
1172 self.logger.info(self.vapi.cli("sh gbp recirc"))
1173 self.logger.info(self.vapi.cli("sh int"))
1174 self.logger.info(self.vapi.cli("sh int addr"))
1175 self.logger.info(self.vapi.cli("sh int feat loop6"))
1176 self.logger.info(self.vapi.cli("sh vlib graph ip4-gbp-src-classify"))
1177 self.logger.info(self.vapi.cli("sh int feat loop3"))
1178 self.logger.info(self.vapi.cli("sh int feat pg0"))
1181 # Packet destined to unknown unicast is sent on the epg uplink ...
1183 pkt_intra_epg_220_to_uplink = (Ether(src=self.pg0.remote_mac,
1184 dst="00:00:00:33:44:55") /
1187 UDP(sport=1234, dport=1234) /
1190 self.send_and_expect_bridged(eps[0].itf,
1191 pkt_intra_epg_220_to_uplink * NUM_PKTS,
1193 # ... and nowhere else
1194 self.pg1.get_capture(0, timeout=0.1)
1195 self.pg1.assert_nothing_captured(remark="Flood onto other VMS")
1197 pkt_intra_epg_221_to_uplink = (Ether(src=self.pg2.remote_mac,
1198 dst="00:00:00:33:44:66") /
1201 UDP(sport=1234, dport=1234) /
1204 self.send_and_expect_bridged(eps[2].itf,
1205 pkt_intra_epg_221_to_uplink * NUM_PKTS,
1209 # Packets from the uplink are forwarded in the absence of a contract
1211 pkt_intra_epg_220_from_uplink = (Ether(src="00:00:00:33:44:55",
1212 dst=self.pg0.remote_mac) /
1215 UDP(sport=1234, dport=1234) /
1218 self.send_and_expect_bridged(self.pg4,
1219 pkt_intra_epg_220_from_uplink * NUM_PKTS,
1223 # in the absence of policy, endpoints in the same EPG
1226 pkt_intra_epg = (Ether(src=self.pg0.remote_mac,
1227 dst=self.pg1.remote_mac) /
1230 UDP(sport=1234, dport=1234) /
1233 self.send_and_expect_bridged(self.pg0,
1234 pkt_intra_epg * NUM_PKTS,
1238 # in the absence of policy, endpoints in the different EPG
1239 # cannot communicate
1241 pkt_inter_epg_220_to_221 = (Ether(src=self.pg0.remote_mac,
1242 dst=self.pg2.remote_mac) /
1245 UDP(sport=1234, dport=1234) /
1247 pkt_inter_epg_221_to_220 = (Ether(src=self.pg2.remote_mac,
1248 dst=self.pg0.remote_mac) /
1251 UDP(sport=1234, dport=1234) /
1253 pkt_inter_epg_220_to_222 = (Ether(src=self.pg0.remote_mac,
1254 dst=str(self.router_mac)) /
1257 UDP(sport=1234, dport=1234) /
1260 self.send_and_assert_no_replies(eps[0].itf,
1261 pkt_inter_epg_220_to_221 * NUM_PKTS)
1262 self.send_and_assert_no_replies(eps[0].itf,
1263 pkt_inter_epg_220_to_222 * NUM_PKTS)
1266 # A uni-directional contract from EPG 220 -> 221
1268 rule = AclRule(is_permit=1, proto=17)
1269 rule2 = AclRule(src_prefix=IPv6Network((0, 0)),
1270 dst_prefix=IPv6Network((0, 0)), is_permit=1, proto=17)
1271 acl = VppAcl(self, rules=[rule, rule2])
1272 acl.add_vpp_config()
1274 c1 = VppGbpContract(
1275 self, 400, epgs[0].sclass, epgs[1].sclass, acl.acl_index,
1276 [VppGbpContractRule(
1277 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1278 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1281 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1282 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1284 [ETH_P_IP, ETH_P_IPV6])
1287 self.send_and_expect_bridged(eps[0].itf,
1288 pkt_inter_epg_220_to_221 * NUM_PKTS,
1290 self.send_and_assert_no_replies(eps[0].itf,
1291 pkt_inter_epg_220_to_222 * NUM_PKTS)
1294 # contract for the return direction
1296 c2 = VppGbpContract(
1297 self, 400, epgs[1].sclass, epgs[0].sclass, acl.acl_index,
1298 [VppGbpContractRule(
1299 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1300 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1303 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1304 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1306 [ETH_P_IP, ETH_P_IPV6])
1309 self.send_and_expect_bridged(eps[0].itf,
1310 pkt_inter_epg_220_to_221 * NUM_PKTS,
1312 self.send_and_expect_bridged(eps[2].itf,
1313 pkt_inter_epg_221_to_220 * NUM_PKTS,
1316 ds = c2.get_drop_stats()
1317 self.assertEqual(ds['packets'], 0)
1318 ps = c2.get_permit_stats()
1319 self.assertEqual(ps['packets'], NUM_PKTS)
1322 # the contract does not allow non-IP
1324 pkt_non_ip_inter_epg_220_to_221 = (Ether(src=self.pg0.remote_mac,
1325 dst=self.pg2.remote_mac) /
1327 self.send_and_assert_no_replies(eps[0].itf,
1328 pkt_non_ip_inter_epg_220_to_221 * 17)
1331 # check that inter group is still disabled for the groups
1332 # not in the contract.
1334 self.send_and_assert_no_replies(eps[0].itf,
1335 pkt_inter_epg_220_to_222 * NUM_PKTS)
1338 # A uni-directional contract from EPG 220 -> 222 'L3 routed'
1340 c3 = VppGbpContract(
1341 self, 400, epgs[0].sclass, epgs[2].sclass, acl.acl_index,
1342 [VppGbpContractRule(
1343 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1344 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1347 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1348 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1350 [ETH_P_IP, ETH_P_IPV6])
1353 self.logger.info(self.vapi.cli("sh gbp contract"))
1355 self.send_and_expect_routed(eps[0].itf,
1356 pkt_inter_epg_220_to_222 * NUM_PKTS,
1358 str(self.router_mac))
1360 # remove both contracts, traffic stops in both directions
1362 c2.remove_vpp_config()
1363 c1.remove_vpp_config()
1364 c3.remove_vpp_config()
1365 acl.remove_vpp_config()
1367 self.send_and_assert_no_replies(eps[2].itf,
1368 pkt_inter_epg_221_to_220 * NUM_PKTS)
1369 self.send_and_assert_no_replies(eps[0].itf,
1370 pkt_inter_epg_220_to_221 * NUM_PKTS)
1371 self.send_and_expect_bridged(eps[0].itf,
1372 pkt_intra_epg * NUM_PKTS,
1376 # EPs to the outside world
1379 # in the EP's RD an external subnet via the NAT EPG's recirc
1381 self, rd0, "0.0.0.0", 0,
1382 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1383 sw_if_index=recirc_nat.recirc.sw_if_index,
1384 sclass=epg_nat.sclass)
1386 self, rd0, "11.0.0.0", 8,
1387 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1388 sw_if_index=recirc_nat.recirc.sw_if_index,
1389 sclass=epg_nat.sclass)
1390 se16 = VppGbpSubnet(
1392 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1393 sw_if_index=recirc_nat.recirc.sw_if_index,
1394 sclass=epg_nat.sclass)
1395 # in the NAT RD an external subnet via the NAT EPG's uplink
1397 self, rd20, "0.0.0.0", 0,
1398 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1399 sw_if_index=epg_nat.uplink.sw_if_index,
1400 sclass=epg_nat.sclass)
1401 se36 = VppGbpSubnet(
1402 self, rd20, "::", 0,
1403 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1404 sw_if_index=epg_nat.uplink.sw_if_index,
1405 sclass=epg_nat.sclass)
1407 self, rd20, "11.0.0.0", 8,
1408 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1409 sw_if_index=epg_nat.uplink.sw_if_index,
1410 sclass=epg_nat.sclass)
1411 se1.add_vpp_config()
1412 se2.add_vpp_config()
1413 se16.add_vpp_config()
1414 se3.add_vpp_config()
1415 se36.add_vpp_config()
1416 se4.add_vpp_config()
1418 self.logger.info(self.vapi.cli("sh ip fib 0.0.0.0/0"))
1419 self.logger.info(self.vapi.cli("sh ip fib 11.0.0.1"))
1420 self.logger.info(self.vapi.cli("sh ip6 fib ::/0"))
1421 self.logger.info(self.vapi.cli("sh ip6 fib %s" %
1425 # From an EP to an outside address: IN2OUT
1427 pkt_inter_epg_220_to_global = (Ether(src=self.pg0.remote_mac,
1428 dst=str(self.router_mac)) /
1431 UDP(sport=1234, dport=1234) /
1435 self.send_and_assert_no_replies(eps[0].itf,
1436 pkt_inter_epg_220_to_global * NUM_PKTS)
1437 rule = AclRule(is_permit=1, proto=17, ports=1234)
1438 rule2 = AclRule(is_permit=1, proto=17, ports=1234,
1439 src_prefix=IPv6Network((0, 0)),
1440 dst_prefix=IPv6Network((0, 0)))
1441 acl2 = VppAcl(self, rules=[rule, rule2])
1442 acl2.add_vpp_config()
1444 c4 = VppGbpContract(
1445 self, 400, epgs[0].sclass, epgs[3].sclass, acl2.acl_index,
1446 [VppGbpContractRule(
1447 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1448 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1451 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1452 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1454 [ETH_P_IP, ETH_P_IPV6])
1457 self.send_and_expect_natted(eps[0].itf,
1458 pkt_inter_epg_220_to_global * NUM_PKTS,
1462 pkt_inter_epg_220_to_global = (Ether(src=self.pg0.remote_mac,
1463 dst=str(self.router_mac)) /
1464 IPv6(src=eps[0].ip6,
1466 UDP(sport=1234, dport=1234) /
1469 self.send_and_expect_natted6(self.pg0,
1470 pkt_inter_epg_220_to_global * NUM_PKTS,
1474 # From a global address to an EP: OUT2IN
1476 pkt_inter_epg_220_from_global = (Ether(src=str(self.router_mac),
1477 dst=self.pg0.remote_mac) /
1480 UDP(sport=1234, dport=1234) /
1483 self.send_and_assert_no_replies(
1484 self.pg7, pkt_inter_epg_220_from_global * NUM_PKTS)
1486 c5 = VppGbpContract(
1487 self, 400, epgs[3].sclass, epgs[0].sclass, acl2.acl_index,
1488 [VppGbpContractRule(
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,
1493 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1494 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1496 [ETH_P_IP, ETH_P_IPV6])
1499 self.send_and_expect_unnatted(self.pg7,
1500 pkt_inter_epg_220_from_global * NUM_PKTS,
1504 pkt_inter_epg_220_from_global = (Ether(src=str(self.router_mac),
1505 dst=self.pg0.remote_mac) /
1506 IPv6(dst=eps[0].fip6,
1508 UDP(sport=1234, dport=1234) /
1511 self.send_and_expect_unnatted6(
1513 pkt_inter_epg_220_from_global * NUM_PKTS,
1518 # From a local VM to another local VM using resp. public addresses:
1521 pkt_intra_epg_220_global = (Ether(src=self.pg0.remote_mac,
1522 dst=str(self.router_mac)) /
1525 UDP(sport=1234, dport=1234) /
1528 self.send_and_expect_double_natted(eps[0].itf,
1529 pkt_intra_epg_220_global * NUM_PKTS,
1534 pkt_intra_epg_220_global = (Ether(src=self.pg0.remote_mac,
1535 dst=str(self.router_mac)) /
1536 IPv6(src=eps[0].ip6,
1538 UDP(sport=1234, dport=1234) /
1541 self.send_and_expect_double_natted6(
1543 pkt_intra_epg_220_global * NUM_PKTS,
1551 self.vapi.nat44_ed_plugin_enable_disable(enable=0)
1552 self.vapi.nat66_plugin_enable_disable(enable=0)
1554 def wait_for_ep_timeout(self, sw_if_index=None, ip=None, mac=None,
1555 tep=None, n_tries=100, s_time=1):
1556 # only learnt EP can timeout
1557 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
1558 flags = ep_flags.GBP_API_ENDPOINT_FLAG_LEARNT
1560 if not find_gbp_endpoint(self, sw_if_index, ip, mac, tep=tep,
1563 n_tries = n_tries - 1
1565 self.assertFalse(find_gbp_endpoint(self, sw_if_index, ip, mac, tep=tep,
1569 def test_gbp_learn_l2(self):
1570 """ GBP L2 Endpoint Learning """
1572 drop_no_contract = self.statistics.get_err_counter(
1573 '/err/gbp-policy-port/drop-no-contract')
1574 allow_intra_class = self.statistics.get_err_counter(
1575 '/err/gbp-policy-port/allow-intra-sclass')
1577 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
1578 learnt = [{'mac': '00:00:11:11:11:01',
1580 'ip6': '2001:10::2'},
1581 {'mac': '00:00:11:11:11:02',
1583 'ip6': '2001:10::3'}]
1588 gt4 = VppIpTable(self, 1)
1589 gt4.add_vpp_config()
1590 gt6 = VppIpTable(self, 1, is_ip6=True)
1591 gt6.add_vpp_config()
1593 rd1 = VppGbpRouteDomain(self, 1, 401, gt4, gt6)
1594 rd1.add_vpp_config()
1597 # Pg2 hosts the vxlan tunnel, hosts on pg2 to act as TEPs
1598 # Pg3 hosts the IP4 UU-flood VXLAN tunnel
1599 # Pg4 hosts the IP6 UU-flood VXLAN tunnel
1601 self.pg2.config_ip4()
1602 self.pg2.resolve_arp()
1603 self.pg2.generate_remote_hosts(4)
1604 self.pg2.configure_ipv4_neighbors()
1605 self.pg3.config_ip4()
1606 self.pg3.resolve_arp()
1607 self.pg4.config_ip4()
1608 self.pg4.resolve_arp()
1611 # Add a mcast destination VXLAN-GBP tunnel for B&M traffic
1613 tun_bm = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
1616 tun_bm.add_vpp_config()
1619 # a GBP bridge domain with a BVI and a UU-flood interface
1621 bd1 = VppBridgeDomain(self, 1)
1622 bd1.add_vpp_config()
1623 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0,
1625 gbd1.add_vpp_config()
1627 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1628 self.logger.info(self.vapi.cli("sh gbp bridge"))
1630 # ... and has a /32 applied
1631 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
1632 ip_addr.add_vpp_config()
1635 # The Endpoint-group in which we are learning endpoints
1637 epg_220 = VppGbpEndpointGroup(self, 220, 112, rd1, gbd1,
1641 VppGbpEndpointRetention(4))
1642 epg_220.add_vpp_config()
1643 epg_330 = VppGbpEndpointGroup(self, 330, 113, rd1, gbd1,
1647 VppGbpEndpointRetention(4))
1648 epg_330.add_vpp_config()
1651 # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
1654 vx_tun_l2_1 = VppGbpVxlanTunnel(
1655 self, 99, bd1.bd_id,
1656 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L2,
1658 vx_tun_l2_1.add_vpp_config()
1661 # A static endpoint that the learnt endpoints are trying to
1664 ep = VppGbpEndpoint(self, self.pg0,
1666 "10.0.0.127", "11.0.0.127",
1667 "2001:10::1", "3001::1")
1670 self.assertTrue(find_route(self, ep.ip4, 32, table_id=1))
1672 # a packet with an sclass from an unknown EPG
1673 p = (Ether(src=self.pg2.remote_mac,
1674 dst=self.pg2.local_mac) /
1675 IP(src=self.pg2.remote_hosts[0].ip4,
1676 dst=self.pg2.local_ip4) /
1677 UDP(sport=1234, dport=48879) /
1678 VXLAN(vni=99, gpid=88, flags=0x88) /
1679 Ether(src=learnt[0]["mac"], dst=ep.mac) /
1680 IP(src=learnt[0]["ip"], dst=ep.ip4) /
1681 UDP(sport=1234, dport=1234) /
1684 self.send_and_assert_no_replies(self.pg2, p)
1686 self.logger.info(self.vapi.cli("sh error"))
1687 self.assert_error_counter_equal(
1688 '/err/gbp-policy-port/drop-no-contract',
1689 drop_no_contract + 1)
1692 # we should not have learnt a new tunnel endpoint, since
1693 # the EPG was not learnt.
1695 self.assertEqual(INDEX_INVALID,
1696 find_vxlan_gbp_tunnel(self,
1698 self.pg2.remote_hosts[0].ip4,
1701 # ep is not learnt, because the EPG is unknown
1702 self.assertEqual(len(self.vapi.gbp_endpoint_dump()), 1)
1705 # Learn new EPs from IP packets
1707 for ii, l in enumerate(learnt):
1708 # a packet with an sclass from a known EPG
1709 # arriving on an unknown TEP
1710 p = (Ether(src=self.pg2.remote_mac,
1711 dst=self.pg2.local_mac) /
1712 IP(src=self.pg2.remote_hosts[1].ip4,
1713 dst=self.pg2.local_ip4) /
1714 UDP(sport=1234, dport=48879) /
1715 VXLAN(vni=99, gpid=112, flags=0x88) /
1716 Ether(src=l['mac'], dst=ep.mac) /
1717 IP(src=l['ip'], dst=ep.ip4) /
1718 UDP(sport=1234, dport=1234) /
1721 rx = self.send_and_expect(self.pg2, [p], self.pg0)
1724 tep1_sw_if_index = find_vxlan_gbp_tunnel(
1727 self.pg2.remote_hosts[1].ip4,
1729 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
1732 # the EP is learnt via the learnt TEP
1733 # both from its MAC and its IP
1735 self.assertTrue(find_gbp_endpoint(self,
1736 vx_tun_l2_1.sw_if_index,
1738 self.assertTrue(find_gbp_endpoint(self,
1739 vx_tun_l2_1.sw_if_index,
1742 self.assert_error_counter_equal(
1743 '/err/gbp-policy-port/allow-intra-sclass',
1744 allow_intra_class + 2)
1746 self.logger.info(self.vapi.cli("show gbp endpoint"))
1747 self.logger.info(self.vapi.cli("show gbp vxlan"))
1748 self.logger.info(self.vapi.cli("show ip mfib"))
1751 # If we sleep for the threshold time, the learnt endpoints should
1755 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1759 # Learn new EPs from GARP packets received on the BD's mcast tunnel
1761 for ii, l in enumerate(learnt):
1762 # add some junk in the reserved field of the vxlan-header
1763 # next to the VNI. we should accept since reserved bits are
1765 p = (Ether(src=self.pg2.remote_mac,
1766 dst=self.pg2.local_mac) /
1767 IP(src=self.pg2.remote_hosts[1].ip4,
1769 UDP(sport=1234, dport=48879) /
1770 VXLAN(vni=88, reserved2=0x80, gpid=112, flags=0x88) /
1771 Ether(src=l['mac'], dst="ff:ff:ff:ff:ff:ff") /
1773 psrc=l['ip'], pdst=l['ip'],
1774 hwsrc=l['mac'], hwdst="ff:ff:ff:ff:ff:ff"))
1776 rx = self.send_and_expect(self.pg4, [p], self.pg0)
1779 tep1_sw_if_index = find_vxlan_gbp_tunnel(
1782 self.pg2.remote_hosts[1].ip4,
1784 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
1787 # the EP is learnt via the learnt TEP
1788 # both from its MAC and its IP
1790 self.assertTrue(find_gbp_endpoint(self,
1791 vx_tun_l2_1.sw_if_index,
1793 self.assertTrue(find_gbp_endpoint(self,
1794 vx_tun_l2_1.sw_if_index,
1798 # wait for the learnt endpoints to age out
1801 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1805 # Learn new EPs from L2 packets
1807 for ii, l in enumerate(learnt):
1808 # a packet with an sclass from a known EPG
1809 # arriving on an unknown TEP
1810 p = (Ether(src=self.pg2.remote_mac,
1811 dst=self.pg2.local_mac) /
1812 IP(src=self.pg2.remote_hosts[1].ip4,
1813 dst=self.pg2.local_ip4) /
1814 UDP(sport=1234, dport=48879) /
1815 VXLAN(vni=99, gpid=112, flags=0x88) /
1816 Ether(src=l['mac'], dst=ep.mac) /
1819 rx = self.send_and_expect(self.pg2, [p], self.pg0)
1822 tep1_sw_if_index = find_vxlan_gbp_tunnel(
1825 self.pg2.remote_hosts[1].ip4,
1827 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
1830 # the EP is learnt via the learnt TEP
1831 # both from its MAC and its IP
1833 self.assertTrue(find_gbp_endpoint(self,
1834 vx_tun_l2_1.sw_if_index,
1837 self.logger.info(self.vapi.cli("show gbp endpoint"))
1838 self.logger.info(self.vapi.cli("show gbp vxlan"))
1839 self.logger.info(self.vapi.cli("show vxlan-gbp tunnel"))
1842 # wait for the learnt endpoints to age out
1845 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1849 # repeat. the do not learn bit is set so the EPs are not learnt
1852 # a packet with an sclass from a known EPG
1853 p = (Ether(src=self.pg2.remote_mac,
1854 dst=self.pg2.local_mac) /
1855 IP(src=self.pg2.remote_hosts[1].ip4,
1856 dst=self.pg2.local_ip4) /
1857 UDP(sport=1234, dport=48879) /
1858 VXLAN(vni=99, gpid=112, flags=0x88, gpflags="D") /
1859 Ether(src=l['mac'], dst=ep.mac) /
1860 IP(src=l['ip'], dst=ep.ip4) /
1861 UDP(sport=1234, dport=1234) /
1864 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
1867 self.assertFalse(find_gbp_endpoint(self,
1868 vx_tun_l2_1.sw_if_index,
1875 # a packet with an sclass from a known EPG
1876 # set a reserved bit in addition to the G and I
1877 # reserved bits should not be checked on rx.
1878 p = (Ether(src=self.pg2.remote_mac,
1879 dst=self.pg2.local_mac) /
1880 IP(src=self.pg2.remote_hosts[1].ip4,
1881 dst=self.pg2.local_ip4) /
1882 UDP(sport=1234, dport=48879) /
1883 VXLAN(vni=99, gpid=112, flags=0xc8) /
1884 Ether(src=l['mac'], dst=ep.mac) /
1885 IP(src=l['ip'], dst=ep.ip4) /
1886 UDP(sport=1234, dport=1234) /
1889 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
1891 self.assertTrue(find_gbp_endpoint(self,
1892 vx_tun_l2_1.sw_if_index,
1896 # Static EP replies to dynamics
1898 self.logger.info(self.vapi.cli("sh l2fib bd_id 1"))
1900 p = (Ether(src=ep.mac, dst=l['mac']) /
1901 IP(dst=l['ip'], src=ep.ip4) /
1902 UDP(sport=1234, dport=1234) /
1905 rxs = self.send_and_expect(self.pg0, p * 17, self.pg2)
1908 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
1909 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
1910 self.assertEqual(rx[UDP].dport, 48879)
1911 # the UDP source port is a random value for hashing
1912 self.assertEqual(rx[VXLAN].gpid, 112)
1913 self.assertEqual(rx[VXLAN].vni, 99)
1914 self.assertTrue(rx[VXLAN].flags.G)
1915 self.assertTrue(rx[VXLAN].flags.Instance)
1916 self.assertTrue(rx[VXLAN].gpflags.A)
1917 self.assertFalse(rx[VXLAN].gpflags.D)
1920 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1924 # repeat in the other EPG
1925 # there's no contract between 220 and 330, but the A-bit is set
1926 # so the packet is cleared for delivery
1929 # a packet with an sclass from a known EPG
1930 p = (Ether(src=self.pg2.remote_mac,
1931 dst=self.pg2.local_mac) /
1932 IP(src=self.pg2.remote_hosts[1].ip4,
1933 dst=self.pg2.local_ip4) /
1934 UDP(sport=1234, dport=48879) /
1935 VXLAN(vni=99, gpid=113, flags=0x88, gpflags='A') /
1936 Ether(src=l['mac'], dst=ep.mac) /
1937 IP(src=l['ip'], dst=ep.ip4) /
1938 UDP(sport=1234, dport=1234) /
1941 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
1943 self.assertTrue(find_gbp_endpoint(self,
1944 vx_tun_l2_1.sw_if_index,
1948 # static EP cannot reach the learnt EPs since there is no contract
1949 # only test 1 EP as the others could timeout
1951 p = (Ether(src=ep.mac, dst=l['mac']) /
1952 IP(dst=learnt[0]['ip'], src=ep.ip4) /
1953 UDP(sport=1234, dport=1234) /
1956 self.send_and_assert_no_replies(self.pg0, [p])
1959 # refresh the entries after the check for no replies above
1962 # a packet with an sclass from a known EPG
1963 p = (Ether(src=self.pg2.remote_mac,
1964 dst=self.pg2.local_mac) /
1965 IP(src=self.pg2.remote_hosts[1].ip4,
1966 dst=self.pg2.local_ip4) /
1967 UDP(sport=1234, dport=48879) /
1968 VXLAN(vni=99, gpid=113, flags=0x88, gpflags='A') /
1969 Ether(src=l['mac'], dst=ep.mac) /
1970 IP(src=l['ip'], dst=ep.ip4) /
1971 UDP(sport=1234, dport=1234) /
1974 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
1976 self.assertTrue(find_gbp_endpoint(self,
1977 vx_tun_l2_1.sw_if_index,
1981 # Add the contract so they can talk
1983 rule = AclRule(is_permit=1, proto=17)
1984 rule2 = AclRule(src_prefix=IPv6Network((0, 0)),
1985 dst_prefix=IPv6Network((0, 0)), is_permit=1, proto=17)
1986 acl = VppAcl(self, rules=[rule, rule2])
1987 acl.add_vpp_config()
1989 c1 = VppGbpContract(
1990 self, 401, epg_220.sclass, epg_330.sclass, acl.acl_index,
1991 [VppGbpContractRule(
1992 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1993 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1996 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1997 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1999 [ETH_P_IP, ETH_P_IPV6])
2003 p = (Ether(src=ep.mac, dst=l['mac']) /
2004 IP(dst=l['ip'], src=ep.ip4) /
2005 UDP(sport=1234, dport=1234) /
2008 self.send_and_expect(self.pg0, [p], self.pg2)
2011 # send UU packets from the local EP
2013 self.logger.info(self.vapi.cli("sh gbp bridge"))
2014 self.logger.info(self.vapi.cli("sh bridge-domain 1 detail"))
2015 p_uu = (Ether(src=ep.mac, dst="00:11:11:11:11:11") /
2016 IP(dst="10.0.0.133", src=ep.ip4) /
2017 UDP(sport=1234, dport=1234) /
2019 rxs = self.send_and_expect(ep.itf, [p_uu], gbd1.uu_fwd)
2021 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2023 p_bm = (Ether(src=ep.mac, dst="ff:ff:ff:ff:ff:ff") /
2024 IP(dst="10.0.0.133", src=ep.ip4) /
2025 UDP(sport=1234, dport=1234) /
2027 rxs = self.send_and_expect_only(ep.itf, [p_bm], tun_bm.mcast_itf)
2030 self.assertEqual(rx[IP].src, self.pg4.local_ip4)
2031 self.assertEqual(rx[IP].dst, "239.1.1.1")
2032 self.assertEqual(rx[UDP].dport, 48879)
2033 # the UDP source port is a random value for hashing
2034 self.assertEqual(rx[VXLAN].gpid, 112)
2035 self.assertEqual(rx[VXLAN].vni, 88)
2036 self.assertTrue(rx[VXLAN].flags.G)
2037 self.assertTrue(rx[VXLAN].flags.Instance)
2038 self.assertFalse(rx[VXLAN].gpflags.A)
2039 self.assertFalse(rx[VXLAN].gpflags.D)
2041 rule = AclRule(is_permit=1, proto=17)
2042 rule2 = AclRule(src_prefix=IPv6Network((0, 0)),
2043 dst_prefix=IPv6Network((0, 0)), is_permit=1, proto=17)
2044 acl = VppAcl(self, rules=[rule, rule2])
2045 acl.add_vpp_config()
2047 c2 = VppGbpContract(
2048 self, 401, epg_330.sclass, epg_220.sclass, acl.acl_index,
2049 [VppGbpContractRule(
2050 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2051 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2054 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2055 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2057 [ETH_P_IP, ETH_P_IPV6])
2061 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
2064 # Check v6 Endpoints learning
2067 # a packet with an sclass from a known EPG
2068 p = (Ether(src=self.pg2.remote_mac,
2069 dst=self.pg2.local_mac) /
2070 IP(src=self.pg2.remote_hosts[1].ip4,
2071 dst=self.pg2.local_ip4) /
2072 UDP(sport=1234, dport=48879) /
2073 VXLAN(vni=99, gpid=113, flags=0x88) /
2074 Ether(src=l['mac'], dst=ep.mac) /
2075 IPv6(src=l['ip6'], dst=ep.ip6) /
2076 UDP(sport=1234, dport=1234) /
2079 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
2080 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
2082 self.assertTrue(find_gbp_endpoint(
2084 vx_tun_l2_1.sw_if_index,
2086 tep=[self.pg2.local_ip4,
2087 self.pg2.remote_hosts[1].ip4]))
2089 self.logger.info(self.vapi.cli("sh int"))
2090 self.logger.info(self.vapi.cli("sh vxlan-gbp tunnel"))
2091 self.logger.info(self.vapi.cli("sh gbp vxlan"))
2092 self.logger.info(self.vapi.cli("sh gbp endpoint"))
2093 self.logger.info(self.vapi.cli("sh gbp interface"))
2096 # EP moves to a different TEP
2099 # a packet with an sclass from a known EPG
2100 p = (Ether(src=self.pg2.remote_mac,
2101 dst=self.pg2.local_mac) /
2102 IP(src=self.pg2.remote_hosts[2].ip4,
2103 dst=self.pg2.local_ip4) /
2104 UDP(sport=1234, dport=48879) /
2105 VXLAN(vni=99, gpid=113, flags=0x88) /
2106 Ether(src=l['mac'], dst=ep.mac) /
2107 IPv6(src=l['ip6'], dst=ep.ip6) /
2108 UDP(sport=1234, dport=1234) /
2111 rx = self.send_and_expect(self.pg2, p * 1, self.pg0)
2112 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
2114 self.assertTrue(find_gbp_endpoint(
2116 vx_tun_l2_1.sw_if_index,
2119 tep=[self.pg2.local_ip4,
2120 self.pg2.remote_hosts[2].ip4]))
2123 # v6 remote EP reachability
2126 p = (Ether(src=ep.mac, dst=l['mac']) /
2127 IPv6(dst=l['ip6'], src=ep.ip6) /
2128 UDP(sport=1234, dport=1234) /
2131 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
2134 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2135 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[2].ip4)
2136 self.assertEqual(rx[UDP].dport, 48879)
2137 # the UDP source port is a random value for hashing
2138 self.assertEqual(rx[VXLAN].gpid, 112)
2139 self.assertEqual(rx[VXLAN].vni, 99)
2140 self.assertTrue(rx[VXLAN].flags.G)
2141 self.assertTrue(rx[VXLAN].flags.Instance)
2142 self.assertTrue(rx[VXLAN].gpflags.A)
2143 self.assertFalse(rx[VXLAN].gpflags.D)
2144 self.assertEqual(rx[IPv6].dst, l['ip6'])
2150 # a packet with an sclass from a known EPG
2151 p = (Ether(src=self.pg2.remote_mac,
2152 dst=self.pg2.local_mac) /
2153 IP(src=self.pg2.remote_hosts[2].ip4,
2154 dst=self.pg2.local_ip4) /
2155 UDP(sport=1234, dport=48879) /
2156 VXLAN(vni=99, gpid=112, flags=0x88) /
2157 Ether(src=l['mac'], dst=ep.mac) /
2158 IPv6(src=l['ip6'], dst=ep.ip6) /
2159 UDP(sport=1234, dport=1234) /
2162 rx = self.send_and_expect(self.pg2, p * 1, self.pg0)
2163 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
2165 self.assertTrue(find_gbp_endpoint(
2167 vx_tun_l2_1.sw_if_index,
2170 tep=[self.pg2.local_ip4,
2171 self.pg2.remote_hosts[2].ip4]))
2174 # check reachability and contract intra-epg
2176 allow_intra_class = self.statistics.get_err_counter(
2177 '/err/gbp-policy-mac/allow-intra-sclass')
2180 p = (Ether(src=ep.mac, dst=l['mac']) /
2181 IPv6(dst=l['ip6'], src=ep.ip6) /
2182 UDP(sport=1234, dport=1234) /
2185 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
2188 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2189 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[2].ip4)
2190 self.assertEqual(rx[UDP].dport, 48879)
2191 self.assertEqual(rx[VXLAN].gpid, 112)
2192 self.assertEqual(rx[VXLAN].vni, 99)
2193 self.assertTrue(rx[VXLAN].flags.G)
2194 self.assertTrue(rx[VXLAN].flags.Instance)
2195 self.assertTrue(rx[VXLAN].gpflags.A)
2196 self.assertFalse(rx[VXLAN].gpflags.D)
2197 self.assertEqual(rx[IPv6].dst, l['ip6'])
2199 allow_intra_class += NUM_PKTS
2201 self.assert_error_counter_equal(
2202 '/err/gbp-policy-mac/allow-intra-sclass',
2209 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
2211 self.pg2.unconfig_ip4()
2212 self.pg3.unconfig_ip4()
2213 self.pg4.unconfig_ip4()
2215 def test_gbp_contract(self):
2216 """ GBP Contracts """
2221 gt4 = VppIpTable(self, 0)
2222 gt4.add_vpp_config()
2223 gt6 = VppIpTable(self, 0, is_ip6=True)
2224 gt6.add_vpp_config()
2226 rd0 = VppGbpRouteDomain(self, 0, 400, gt4, gt6, None, None)
2228 rd0.add_vpp_config()
2233 bd1 = VppBridgeDomain(self, 1, arp_term=0)
2234 bd2 = VppBridgeDomain(self, 2, arp_term=0)
2236 bd1.add_vpp_config()
2237 bd2.add_vpp_config()
2239 gbd1 = VppGbpBridgeDomain(self, bd1, rd0, self.loop0)
2240 gbd2 = VppGbpBridgeDomain(self, bd2, rd0, self.loop1)
2242 gbd1.add_vpp_config()
2243 gbd2.add_vpp_config()
2246 # 3 EPGs, 2 of which share a BD.
2248 epgs = [VppGbpEndpointGroup(self, 220, 1220, rd0, gbd1,
2250 "10.0.0.128", "2001:10::128"),
2251 VppGbpEndpointGroup(self, 221, 1221, rd0, gbd1,
2253 "10.0.1.128", "2001:10:1::128"),
2254 VppGbpEndpointGroup(self, 222, 1222, rd0, gbd2,
2256 "10.0.2.128", "2001:10:2::128")]
2258 # 4 end-points, 2 in the same subnet, 3 in the same BD
2260 eps = [VppGbpEndpoint(self, self.pg0,
2262 "10.0.0.1", "11.0.0.1",
2263 "2001:10::1", "3001::1"),
2264 VppGbpEndpoint(self, self.pg1,
2266 "10.0.0.2", "11.0.0.2",
2267 "2001:10::2", "3001::2"),
2268 VppGbpEndpoint(self, self.pg2,
2270 "10.0.1.1", "11.0.0.3",
2271 "2001:10:1::1", "3001::3"),
2272 VppGbpEndpoint(self, self.pg3,
2274 "10.0.2.1", "11.0.0.4",
2275 "2001:10:2::1", "3001::4")]
2278 # Config related to each of the EPGs
2281 # IP config on the BVI interfaces
2283 b4 = VppIpInterfaceBind(self, epg.bvi,
2284 epg.rd.t4).add_vpp_config()
2285 b6 = VppIpInterfaceBind(self, epg.bvi,
2286 epg.rd.t6).add_vpp_config()
2287 epg.bvi.set_mac(self.router_mac)
2289 if_ip4 = VppIpInterfaceAddress(self, epg.bvi,
2291 bind=b4).add_vpp_config()
2292 if_ip6 = VppIpInterfaceAddress(self, epg.bvi,
2294 bind=b6).add_vpp_config()
2296 # add the BD ARP termination entry for BVI IP
2297 epg.bd_arp_ip4 = VppBridgeDomainArpEntry(self, epg.bd.bd,
2298 str(self.router_mac),
2300 epg.bd_arp_ip4.add_vpp_config()
2303 epg.add_vpp_config()
2311 self.logger.info(self.vapi.cli("show gbp endpoint"))
2312 self.logger.info(self.vapi.cli("show interface"))
2313 self.logger.info(self.vapi.cli("show br"))
2316 # Intra epg allowed without contract
2318 pkt_intra_epg_220_to_220 = (Ether(src=self.pg0.remote_mac,
2319 dst=self.pg1.remote_mac) /
2322 UDP(sport=1234, dport=1234) /
2325 self.send_and_expect_bridged(self.pg0,
2326 pkt_intra_epg_220_to_220 * 65,
2329 pkt_intra_epg_220_to_220 = (Ether(src=self.pg0.remote_mac,
2330 dst=self.pg1.remote_mac) /
2331 IPv6(src=eps[0].ip6,
2333 UDP(sport=1234, dport=1234) /
2336 self.send_and_expect_bridged6(self.pg0,
2337 pkt_intra_epg_220_to_220 * 65,
2341 # Inter epg denied without contract
2343 pkt_inter_epg_220_to_221 = (Ether(src=self.pg0.remote_mac,
2344 dst=self.pg2.remote_mac) /
2347 UDP(sport=1234, dport=1234) /
2350 self.send_and_assert_no_replies(self.pg0, pkt_inter_epg_220_to_221)
2353 # A uni-directional contract from EPG 220 -> 221
2355 rule = AclRule(is_permit=1, proto=17)
2356 rule2 = AclRule(src_prefix=IPv6Network((0, 0)),
2357 dst_prefix=IPv6Network((0, 0)), is_permit=1, proto=17)
2358 rule3 = AclRule(is_permit=1, proto=1)
2359 acl = VppAcl(self, rules=[rule, rule2, rule3])
2360 acl.add_vpp_config()
2362 c1 = VppGbpContract(
2363 self, 400, epgs[0].sclass, epgs[1].sclass, acl.acl_index,
2364 [VppGbpContractRule(
2365 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2366 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2369 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2370 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2373 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2374 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2376 [ETH_P_IP, ETH_P_IPV6])
2379 self.send_and_expect_bridged(eps[0].itf,
2380 pkt_inter_epg_220_to_221 * 65,
2383 pkt_inter_epg_220_to_222 = (Ether(src=self.pg0.remote_mac,
2384 dst=str(self.router_mac)) /
2387 UDP(sport=1234, dport=1234) /
2389 self.send_and_assert_no_replies(eps[0].itf,
2390 pkt_inter_epg_220_to_222 * 65)
2393 # ping router IP in different BD
2395 pkt_router_ping_220_to_221 = (Ether(src=self.pg0.remote_mac,
2396 dst=str(self.router_mac)) /
2398 dst=epgs[1].bvi_ip4) /
2399 ICMP(type='echo-request'))
2401 self.send_and_expect(self.pg0, [pkt_router_ping_220_to_221], self.pg0)
2403 pkt_router_ping_220_to_221 = (Ether(src=self.pg0.remote_mac,
2404 dst=str(self.router_mac)) /
2405 IPv6(src=eps[0].ip6,
2406 dst=epgs[1].bvi_ip6) /
2407 ICMPv6EchoRequest())
2409 self.send_and_expect(self.pg0, [pkt_router_ping_220_to_221], self.pg0)
2412 # contract for the return direction
2414 c2 = VppGbpContract(
2415 self, 400, epgs[1].sclass, epgs[0].sclass, acl.acl_index,
2416 [VppGbpContractRule(
2417 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2418 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2421 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2422 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2424 [ETH_P_IP, ETH_P_IPV6])
2427 self.send_and_expect_bridged(eps[0].itf,
2428 pkt_inter_epg_220_to_221 * 65,
2430 pkt_inter_epg_221_to_220 = (Ether(src=self.pg2.remote_mac,
2431 dst=self.pg0.remote_mac) /
2434 UDP(sport=1234, dport=1234) /
2436 self.send_and_expect_bridged(eps[2].itf,
2437 pkt_inter_epg_221_to_220 * 65,
2439 pkt_inter_epg_221_to_220 = (Ether(src=self.pg2.remote_mac,
2440 dst=str(self.router_mac)) /
2443 UDP(sport=1234, dport=1234) /
2445 self.send_and_expect_routed(eps[2].itf,
2446 pkt_inter_epg_221_to_220 * 65,
2448 str(self.router_mac))
2449 pkt_inter_epg_221_to_220 = (Ether(src=self.pg2.remote_mac,
2450 dst=str(self.router_mac)) /
2451 IPv6(src=eps[2].ip6,
2453 UDP(sport=1234, dport=1234) /
2455 self.send_and_expect_routed6(eps[2].itf,
2456 pkt_inter_epg_221_to_220 * 65,
2458 str(self.router_mac))
2461 # contract between 220 and 222 uni-direction
2463 c3 = VppGbpContract(
2464 self, 400, epgs[0].sclass, epgs[2].sclass, acl.acl_index,
2465 [VppGbpContractRule(
2466 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2467 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2470 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2471 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2473 [ETH_P_IP, ETH_P_IPV6])
2476 self.send_and_expect(eps[0].itf,
2477 pkt_inter_epg_220_to_222 * 65,
2480 c3.remove_vpp_config()
2481 c1.remove_vpp_config()
2482 c2.remove_vpp_config()
2483 acl.remove_vpp_config()
2485 def test_gbp_bd_drop_flags(self):
2486 """ GBP BD drop flags """
2491 gt4 = VppIpTable(self, 1)
2492 gt4.add_vpp_config()
2493 gt6 = VppIpTable(self, 1, is_ip6=True)
2494 gt6.add_vpp_config()
2496 rd1 = VppGbpRouteDomain(self, 1, 401, gt4, gt6)
2497 rd1.add_vpp_config()
2500 # a GBP bridge domain with a BVI only
2502 bd1 = VppBridgeDomain(self, 1)
2503 bd1.add_vpp_config()
2505 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0,
2507 uu_drop=True, bm_drop=True)
2508 gbd1.add_vpp_config()
2510 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2511 self.logger.info(self.vapi.cli("sh gbp bridge"))
2513 # ... and has a /32 applied
2514 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi,
2515 "10.0.0.128", 32).add_vpp_config()
2518 # The Endpoint-group
2520 epg_220 = VppGbpEndpointGroup(self, 220, 112, rd1, gbd1,
2524 VppGbpEndpointRetention(3))
2525 epg_220.add_vpp_config()
2527 ep = VppGbpEndpoint(self, self.pg0,
2529 "10.0.0.127", "11.0.0.127",
2530 "2001:10::1", "3001::1")
2534 # send UU/BM packet from the local EP with UU drop and BM drop enabled
2537 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2538 self.logger.info(self.vapi.cli("sh gbp bridge"))
2539 p_uu = (Ether(src=ep.mac, dst="00:11:11:11:11:11") /
2540 IP(dst="10.0.0.133", src=ep.ip4) /
2541 UDP(sport=1234, dport=1234) /
2543 self.send_and_assert_no_replies(ep.itf, [p_uu])
2545 p_bm = (Ether(src=ep.mac, dst="ff:ff:ff:ff:ff:ff") /
2546 IP(dst="10.0.0.133", src=ep.ip4) /
2547 UDP(sport=1234, dport=1234) /
2549 self.send_and_assert_no_replies(ep.itf, [p_bm])
2551 self.pg3.unconfig_ip4()
2553 self.logger.info(self.vapi.cli("sh int"))
2555 def test_gbp_bd_arp_flags(self):
2556 """ GBP BD arp flags """
2561 gt4 = VppIpTable(self, 1)
2562 gt4.add_vpp_config()
2563 gt6 = VppIpTable(self, 1, is_ip6=True)
2564 gt6.add_vpp_config()
2566 rd1 = VppGbpRouteDomain(self, 1, 401, gt4, gt6)
2567 rd1.add_vpp_config()
2570 # Pg4 hosts the IP6 UU-flood VXLAN tunnel
2572 self.pg4.config_ip4()
2573 self.pg4.resolve_arp()
2576 # Add a mcast destination VXLAN-GBP tunnel for B&M traffic
2578 tun_uu = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
2581 tun_uu.add_vpp_config()
2584 # a GBP bridge domain with a BVI and a UU-flood interface
2586 bd1 = VppBridgeDomain(self, 1)
2587 bd1.add_vpp_config()
2589 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0,
2592 gbd1.add_vpp_config()
2594 # ... and has a /32 applied
2595 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi,
2596 "10.0.0.128", 32).add_vpp_config()
2599 # The Endpoint-group
2601 epg_220 = VppGbpEndpointGroup(self, 220, 112, rd1, gbd1,
2605 VppGbpEndpointRetention(2))
2606 epg_220.add_vpp_config()
2608 ep = VppGbpEndpoint(self, self.pg0,
2610 "10.0.0.127", "11.0.0.127",
2611 "2001:10::1", "3001::1")
2615 # send ARP packet from the local EP expect it on the uu interface
2617 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2618 self.logger.info(self.vapi.cli("sh gbp bridge"))
2619 p_arp = (Ether(src=ep.mac, dst="ff:ff:ff:ff:ff:ff") /
2621 psrc=ep.ip4, pdst="10.0.0.99",
2623 hwdst="ff:ff:ff:ff:ff:ff"))
2624 self.send_and_expect(ep.itf, [p_arp], self.pg4)
2626 self.pg4.unconfig_ip4()
2628 def test_gbp_learn_vlan_l2(self):
2629 """ GBP L2 Endpoint w/ VLANs"""
2631 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
2632 learnt = [{'mac': '00:00:11:11:11:01',
2634 'ip6': '2001:10::2'},
2635 {'mac': '00:00:11:11:11:02',
2637 'ip6': '2001:10::3'}]
2642 gt4 = VppIpTable(self, 1)
2643 gt4.add_vpp_config()
2644 gt6 = VppIpTable(self, 1, is_ip6=True)
2645 gt6.add_vpp_config()
2647 rd1 = VppGbpRouteDomain(self, 1, 401, gt4, gt6)
2648 rd1.add_vpp_config()
2651 # Pg2 hosts the vxlan tunnel, hosts on pg2 to act as TEPs
2653 self.pg2.config_ip4()
2654 self.pg2.resolve_arp()
2655 self.pg2.generate_remote_hosts(4)
2656 self.pg2.configure_ipv4_neighbors()
2657 self.pg3.config_ip4()
2658 self.pg3.resolve_arp()
2661 # The EP will be on a vlan sub-interface
2663 vlan_11 = VppDot1QSubint(self, self.pg0, 11)
2665 self.vapi.l2_interface_vlan_tag_rewrite(
2666 sw_if_index=vlan_11.sw_if_index, vtr_op=L2_VTR_OP.L2_POP_1,
2669 bd_uu_fwd = VppVxlanGbpTunnel(self, self.pg3.local_ip4,
2670 self.pg3.remote_ip4, 116)
2671 bd_uu_fwd.add_vpp_config()
2674 # a GBP bridge domain with a BVI and a UU-flood interface
2675 # The BD is marked as do not learn, so no endpoints are ever
2676 # learnt in this BD.
2678 bd1 = VppBridgeDomain(self, 1)
2679 bd1.add_vpp_config()
2680 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0, bd_uu_fwd,
2682 gbd1.add_vpp_config()
2684 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2685 self.logger.info(self.vapi.cli("sh gbp bridge"))
2687 # ... and has a /32 applied
2688 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi,
2689 "10.0.0.128", 32).add_vpp_config()
2692 # The Endpoint-group in which we are learning endpoints
2694 epg_220 = VppGbpEndpointGroup(self, 220, 441, rd1, gbd1,
2698 VppGbpEndpointRetention(4))
2699 epg_220.add_vpp_config()
2702 # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
2705 vx_tun_l2_1 = VppGbpVxlanTunnel(
2706 self, 99, bd1.bd_id,
2707 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L2,
2709 vx_tun_l2_1.add_vpp_config()
2712 # A static endpoint that the learnt endpoints are trying to
2715 ep = VppGbpEndpoint(self, vlan_11,
2717 "10.0.0.127", "11.0.0.127",
2718 "2001:10::1", "3001::1")
2721 self.assertTrue(find_route(self, ep.ip4, 32, table_id=1))
2724 # Send to the static EP
2726 for ii, l in enumerate(learnt):
2727 # a packet with an sclass from a known EPG
2728 # arriving on an unknown TEP
2729 p = (Ether(src=self.pg2.remote_mac,
2730 dst=self.pg2.local_mac) /
2731 IP(src=self.pg2.remote_hosts[1].ip4,
2732 dst=self.pg2.local_ip4) /
2733 UDP(sport=1234, dport=48879) /
2734 VXLAN(vni=99, gpid=441, flags=0x88) /
2735 Ether(src=l['mac'], dst=ep.mac) /
2736 IP(src=l['ip'], dst=ep.ip4) /
2737 UDP(sport=1234, dport=1234) /
2740 rxs = self.send_and_expect(self.pg2, [p], self.pg0)
2743 # packet to EP has the EP's vlan tag
2746 self.assertEqual(rx[Dot1Q].vlan, 11)
2749 # the EP is not learnt since the BD setting prevents it
2752 self.assertFalse(find_gbp_endpoint(self,
2753 vx_tun_l2_1.sw_if_index,
2755 self.assertEqual(INDEX_INVALID,
2756 find_vxlan_gbp_tunnel(
2759 self.pg2.remote_hosts[1].ip4,
2762 self.assertEqual(len(self.vapi.gbp_endpoint_dump()), 1)
2766 # we didn't learn the remotes so they are sent to the UU-fwd
2769 p = (Ether(src=ep.mac, dst=l['mac']) /
2771 IP(dst=l['ip'], src=ep.ip4) /
2772 UDP(sport=1234, dport=1234) /
2775 rxs = self.send_and_expect(self.pg0, p * 17, self.pg3)
2778 self.assertEqual(rx[IP].src, self.pg3.local_ip4)
2779 self.assertEqual(rx[IP].dst, self.pg3.remote_ip4)
2780 self.assertEqual(rx[UDP].dport, 48879)
2781 # the UDP source port is a random value for hashing
2782 self.assertEqual(rx[VXLAN].gpid, 441)
2783 self.assertEqual(rx[VXLAN].vni, 116)
2784 self.assertTrue(rx[VXLAN].flags.G)
2785 self.assertTrue(rx[VXLAN].flags.Instance)
2786 self.assertFalse(rx[VXLAN].gpflags.A)
2787 self.assertFalse(rx[VXLAN].gpflags.D)
2789 self.pg2.unconfig_ip4()
2790 self.pg3.unconfig_ip4()
2792 def test_gbp_learn_l3(self):
2793 """ GBP L3 Endpoint Learning """
2795 self.vapi.cli("set logging class gbp level debug")
2797 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
2798 routed_dst_mac = "00:0c:0c:0c:0c:0c"
2799 routed_src_mac = "00:22:bd:f8:19:ff"
2801 learnt = [{'mac': '00:00:11:11:11:02',
2803 'ip6': '2001:10::2'},
2804 {'mac': '00:00:11:11:11:03',
2806 'ip6': '2001:10::3'}]
2811 t4 = VppIpTable(self, 1)
2813 t6 = VppIpTable(self, 1, True)
2816 tun_ip4_uu = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
2817 self.pg4.remote_ip4, 114)
2818 tun_ip6_uu = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
2819 self.pg4.remote_ip4, 116)
2820 tun_ip4_uu.add_vpp_config()
2821 tun_ip6_uu.add_vpp_config()
2823 rd1 = VppGbpRouteDomain(self, 2, 401, t4, t6, tun_ip4_uu, tun_ip6_uu)
2824 rd1.add_vpp_config()
2826 self.loop0.set_mac(self.router_mac)
2829 # Bind the BVI to the RD
2831 b4 = VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
2832 b6 = VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
2835 # Pg2 hosts the vxlan tunnel
2836 # hosts on pg2 to act as TEPs
2840 self.pg2.config_ip4()
2841 self.pg2.resolve_arp()
2842 self.pg2.generate_remote_hosts(4)
2843 self.pg2.configure_ipv4_neighbors()
2844 self.pg3.config_ip4()
2845 self.pg3.resolve_arp()
2846 self.pg4.config_ip4()
2847 self.pg4.resolve_arp()
2850 # a GBP bridge domain with a BVI and a UU-flood interface
2852 bd1 = VppBridgeDomain(self, 1)
2853 bd1.add_vpp_config()
2854 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0, self.pg3)
2855 gbd1.add_vpp_config()
2857 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2858 self.logger.info(self.vapi.cli("sh gbp bridge"))
2859 self.logger.info(self.vapi.cli("sh gbp route"))
2861 # ... and has a /32 and /128 applied
2862 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi,
2864 bind=b4).add_vpp_config()
2865 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi,
2866 "2001:10::128", 128,
2867 bind=b6).add_vpp_config()
2870 # The Endpoint-group in which we are learning endpoints
2872 epg_220 = VppGbpEndpointGroup(self, 220, 441, rd1, gbd1,
2876 VppGbpEndpointRetention(4))
2877 epg_220.add_vpp_config()
2880 # The VXLAN GBP tunnel is in L3 mode with learning enabled
2882 vx_tun_l3 = VppGbpVxlanTunnel(
2883 self, 101, rd1.rd_id,
2884 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
2886 vx_tun_l3.add_vpp_config()
2889 # A static endpoint that the learnt endpoints are trying to
2892 ep = VppGbpEndpoint(self, self.pg0,
2894 "10.0.0.127", "11.0.0.127",
2895 "2001:10::1", "3001::1")
2899 # learn some remote IPv4 EPs
2901 for ii, l in enumerate(learnt):
2902 # a packet with an sclass from a known EPG
2903 # arriving on an unknown TEP
2904 p = (Ether(src=self.pg2.remote_mac,
2905 dst=self.pg2.local_mac) /
2906 IP(src=self.pg2.remote_hosts[1].ip4,
2907 dst=self.pg2.local_ip4) /
2908 UDP(sport=1234, dport=48879) /
2909 VXLAN(vni=101, gpid=441, flags=0x88) /
2910 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2911 IP(src=l['ip'], dst=ep.ip4) /
2912 UDP(sport=1234, dport=1234) /
2915 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2918 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2921 self.pg2.remote_hosts[1].ip4,
2923 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2925 # endpoint learnt via the parent GBP-vxlan interface
2926 self.assertTrue(find_gbp_endpoint(self,
2927 vx_tun_l3._sw_if_index,
2931 # Static IPv4 EP replies to learnt
2934 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2935 IP(dst=l['ip'], src=ep.ip4) /
2936 UDP(sport=1234, dport=1234) /
2939 rxs = self.send_and_expect(self.pg0, p * 1, self.pg2)
2942 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2943 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2944 self.assertEqual(rx[UDP].dport, 48879)
2945 # the UDP source port is a random value for hashing
2946 self.assertEqual(rx[VXLAN].gpid, 441)
2947 self.assertEqual(rx[VXLAN].vni, 101)
2948 self.assertTrue(rx[VXLAN].flags.G)
2949 self.assertTrue(rx[VXLAN].flags.Instance)
2950 self.assertTrue(rx[VXLAN].gpflags.A)
2951 self.assertFalse(rx[VXLAN].gpflags.D)
2953 inner = rx[VXLAN].payload
2955 self.assertEqual(inner[Ether].src, routed_src_mac)
2956 self.assertEqual(inner[Ether].dst, routed_dst_mac)
2957 self.assertEqual(inner[IP].src, ep.ip4)
2958 self.assertEqual(inner[IP].dst, l['ip'])
2961 self.assertFalse(find_gbp_endpoint(self,
2966 # learn some remote IPv6 EPs
2968 for ii, l in enumerate(learnt):
2969 # a packet with an sclass from a known EPG
2970 # arriving on an unknown TEP
2971 p = (Ether(src=self.pg2.remote_mac,
2972 dst=self.pg2.local_mac) /
2973 IP(src=self.pg2.remote_hosts[1].ip4,
2974 dst=self.pg2.local_ip4) /
2975 UDP(sport=1234, dport=48879) /
2976 VXLAN(vni=101, gpid=441, flags=0x88) /
2977 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2978 IPv6(src=l['ip6'], dst=ep.ip6) /
2979 UDP(sport=1234, dport=1234) /
2982 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2985 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2988 self.pg2.remote_hosts[1].ip4,
2990 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2992 self.logger.info(self.vapi.cli("show gbp bridge"))
2993 self.logger.info(self.vapi.cli("show vxlan-gbp tunnel"))
2994 self.logger.info(self.vapi.cli("show gbp vxlan"))
2995 self.logger.info(self.vapi.cli("show int addr"))
2997 # endpoint learnt via the TEP
2998 self.assertTrue(find_gbp_endpoint(self, ip=l['ip6']))
3000 self.logger.info(self.vapi.cli("show gbp endpoint"))
3001 self.logger.info(self.vapi.cli("show ip fib index 1 %s" % l['ip']))
3004 # Static EP replies to learnt
3007 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
3008 IPv6(dst=l['ip6'], src=ep.ip6) /
3009 UDP(sport=1234, dport=1234) /
3012 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
3015 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
3016 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
3017 self.assertEqual(rx[UDP].dport, 48879)
3018 # the UDP source port is a random value for hashing
3019 self.assertEqual(rx[VXLAN].gpid, 441)
3020 self.assertEqual(rx[VXLAN].vni, 101)
3021 self.assertTrue(rx[VXLAN].flags.G)
3022 self.assertTrue(rx[VXLAN].flags.Instance)
3023 self.assertTrue(rx[VXLAN].gpflags.A)
3024 self.assertFalse(rx[VXLAN].gpflags.D)
3026 inner = rx[VXLAN].payload
3028 self.assertEqual(inner[Ether].src, routed_src_mac)
3029 self.assertEqual(inner[Ether].dst, routed_dst_mac)
3030 self.assertEqual(inner[IPv6].src, ep.ip6)
3031 self.assertEqual(inner[IPv6].dst, l['ip6'])
3033 self.logger.info(self.vapi.cli("sh gbp endpoint"))
3035 self.wait_for_ep_timeout(ip=l['ip'])
3038 # Static sends to unknown EP with no route
3040 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
3041 IP(dst="10.0.0.99", src=ep.ip4) /
3042 UDP(sport=1234, dport=1234) /
3045 self.send_and_assert_no_replies(self.pg0, [p])
3048 # Add a route to static EP's v4 and v6 subnet
3050 se_10_24 = VppGbpSubnet(
3051 self, rd1, "10.0.0.0", 24,
3052 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT)
3053 se_10_24.add_vpp_config()
3056 # static pings router
3058 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
3059 IP(dst=epg_220.bvi_ip4, src=ep.ip4) /
3060 UDP(sport=1234, dport=1234) /
3063 self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg0)
3065 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
3066 IPv6(dst=epg_220.bvi_ip6, src=ep.ip6) /
3067 UDP(sport=1234, dport=1234) /
3070 self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg0)
3073 # packets to address in the subnet are sent on the uu-fwd
3075 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
3076 IP(dst="10.0.0.99", src=ep.ip4) /
3077 UDP(sport=1234, dport=1234) /
3080 rxs = self.send_and_expect(self.pg0, [p], self.pg4)
3082 self.assertEqual(rx[IP].src, self.pg4.local_ip4)
3083 self.assertEqual(rx[IP].dst, self.pg4.remote_ip4)
3084 self.assertEqual(rx[UDP].dport, 48879)
3085 # the UDP source port is a random value for hashing
3086 self.assertEqual(rx[VXLAN].gpid, 441)
3087 self.assertEqual(rx[VXLAN].vni, 114)
3088 self.assertTrue(rx[VXLAN].flags.G)
3089 self.assertTrue(rx[VXLAN].flags.Instance)
3090 # policy is not applied to packets sent to the uu-fwd interfaces
3091 self.assertFalse(rx[VXLAN].gpflags.A)
3092 self.assertFalse(rx[VXLAN].gpflags.D)
3095 # learn some remote IPv4 EPs
3097 for ii, l in enumerate(learnt):
3098 # a packet with an sclass from a known EPG
3099 # arriving on an unknown TEP
3100 p = (Ether(src=self.pg2.remote_mac,
3101 dst=self.pg2.local_mac) /
3102 IP(src=self.pg2.remote_hosts[2].ip4,
3103 dst=self.pg2.local_ip4) /
3104 UDP(sport=1234, dport=48879) /
3105 VXLAN(vni=101, gpid=441, flags=0x88) /
3106 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
3107 IP(src=l['ip'], dst=ep.ip4) /
3108 UDP(sport=1234, dport=1234) /
3111 rx = self.send_and_expect(self.pg2, [p], self.pg0)
3114 tep1_sw_if_index = find_vxlan_gbp_tunnel(
3117 self.pg2.remote_hosts[2].ip4,
3119 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
3121 # endpoint learnt via the parent GBP-vxlan interface
3122 self.assertTrue(find_gbp_endpoint(self,
3123 vx_tun_l3._sw_if_index,
3127 # Add a remote endpoint from the API
3129 rep_88 = VppGbpEndpoint(self, vx_tun_l3,
3131 "10.0.0.88", "11.0.0.88",
3132 "2001:10::88", "3001::88",
3133 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
3135 self.pg2.remote_hosts[2].ip4,
3137 rep_88.add_vpp_config()
3140 # Add a remote endpoint from the API that matches an existing one
3141 # this is a lower priority, hence the packet is sent to the DP leanrt
3144 rep_2 = VppGbpEndpoint(self, vx_tun_l3,
3146 learnt[0]['ip'], "11.0.0.101",
3147 learnt[0]['ip6'], "3001::101",
3148 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
3150 self.pg2.remote_hosts[1].ip4,
3152 rep_2.add_vpp_config()
3155 # Add a route to the learned EP's v4 subnet
3156 # packets should be send on the v4/v6 uu=fwd interface resp.
3158 se_10_1_24 = VppGbpSubnet(
3159 self, rd1, "10.0.1.0", 24,
3160 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT)
3161 se_10_1_24.add_vpp_config()
3163 self.logger.info(self.vapi.cli("show gbp endpoint"))
3165 ips = ["10.0.0.88", learnt[0]['ip']]
3167 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
3168 IP(dst=ip, src=ep.ip4) /
3169 UDP(sport=1234, dport=1234) /
3172 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
3175 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
3176 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[2].ip4)
3177 self.assertEqual(rx[UDP].dport, 48879)
3178 # the UDP source port is a random value for hashing
3179 self.assertEqual(rx[VXLAN].gpid, 441)
3180 self.assertEqual(rx[VXLAN].vni, 101)
3181 self.assertTrue(rx[VXLAN].flags.G)
3182 self.assertTrue(rx[VXLAN].flags.Instance)
3183 self.assertTrue(rx[VXLAN].gpflags.A)
3184 self.assertFalse(rx[VXLAN].gpflags.D)
3186 inner = rx[VXLAN].payload
3188 self.assertEqual(inner[Ether].src, routed_src_mac)
3189 self.assertEqual(inner[Ether].dst, routed_dst_mac)
3190 self.assertEqual(inner[IP].src, ep.ip4)
3191 self.assertEqual(inner[IP].dst, ip)
3194 # remove the API remote EPs, only API sourced is gone, the DP
3195 # learnt one remains
3197 rep_88.remove_vpp_config()
3198 rep_2.remove_vpp_config()
3200 self.assertTrue(find_gbp_endpoint(self, ip=rep_2.ip4))
3202 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
3203 IP(src=ep.ip4, dst=rep_2.ip4) /
3204 UDP(sport=1234, dport=1234) /
3206 rxs = self.send_and_expect(self.pg0, [p], self.pg2)
3208 self.assertFalse(find_gbp_endpoint(self, ip=rep_88.ip4))
3210 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
3211 IP(src=ep.ip4, dst=rep_88.ip4) /
3212 UDP(sport=1234, dport=1234) /
3214 rxs = self.send_and_expect(self.pg0, [p], self.pg4)
3217 # to appease the testcase we cannot have the registered EP still
3218 # present (because it's DP learnt) when the TC ends so wait until
3221 self.wait_for_ep_timeout(ip=rep_88.ip4)
3222 self.wait_for_ep_timeout(ip=rep_2.ip4)
3225 # Same as above, learn a remote EP via CP and DP
3226 # this time remove the DP one first. expect the CP data to remain
3228 rep_3 = VppGbpEndpoint(self, vx_tun_l3,
3230 "10.0.1.4", "11.0.0.103",
3231 "2001::10:3", "3001::103",
3232 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
3234 self.pg2.remote_hosts[1].ip4,
3236 rep_3.add_vpp_config()
3238 p = (Ether(src=self.pg2.remote_mac,
3239 dst=self.pg2.local_mac) /
3240 IP(src=self.pg2.remote_hosts[2].ip4,
3241 dst=self.pg2.local_ip4) /
3242 UDP(sport=1234, dport=48879) /
3243 VXLAN(vni=101, gpid=441, flags=0x88) /
3244 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
3245 IP(src="10.0.1.4", dst=ep.ip4) /
3246 UDP(sport=1234, dport=1234) /
3248 rxs = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
3250 self.assertTrue(find_gbp_endpoint(self,
3251 vx_tun_l3._sw_if_index,
3253 tep=[self.pg2.local_ip4,
3254 self.pg2.remote_hosts[2].ip4]))
3256 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
3257 IP(dst="10.0.1.4", src=ep.ip4) /
3258 UDP(sport=1234, dport=1234) /
3260 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
3262 # host 2 is the DP learned TEP
3264 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
3265 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[2].ip4)
3267 self.wait_for_ep_timeout(ip=rep_3.ip4,
3268 tep=[self.pg2.local_ip4,
3269 self.pg2.remote_hosts[2].ip4])
3271 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
3273 # host 1 is the CP learned TEP
3275 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
3276 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
3279 # shutdown with learnt endpoint present
3281 p = (Ether(src=self.pg2.remote_mac,
3282 dst=self.pg2.local_mac) /
3283 IP(src=self.pg2.remote_hosts[1].ip4,
3284 dst=self.pg2.local_ip4) /
3285 UDP(sport=1234, dport=48879) /
3286 VXLAN(vni=101, gpid=441, flags=0x88) /
3287 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
3288 IP(src=learnt[1]['ip'], dst=ep.ip4) /
3289 UDP(sport=1234, dport=1234) /
3292 rx = self.send_and_expect(self.pg2, [p], self.pg0)
3294 # endpoint learnt via the parent GBP-vxlan interface
3295 self.assertTrue(find_gbp_endpoint(self,
3296 vx_tun_l3._sw_if_index,
3301 # remote endpoint becomes local
3303 self.pg2.unconfig_ip4()
3304 self.pg3.unconfig_ip4()
3305 self.pg4.unconfig_ip4()
3307 def test_gbp_redirect(self):
3308 """ GBP Endpoint Redirect """
3310 self.vapi.cli("set logging class gbp level debug")
3312 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
3313 routed_dst_mac = "00:0c:0c:0c:0c:0c"
3314 routed_src_mac = "00:22:bd:f8:19:ff"
3316 learnt = [{'mac': '00:00:11:11:11:02',
3318 'ip6': '2001:10::2'},
3319 {'mac': '00:00:11:11:11:03',
3321 'ip6': '2001:10::3'}]
3326 t4 = VppIpTable(self, 1)
3328 t6 = VppIpTable(self, 1, True)
3331 rd1 = VppGbpRouteDomain(self, 2, 402, t4, t6)
3332 rd1.add_vpp_config()
3334 self.loop0.set_mac(self.router_mac)
3337 # Bind the BVI to the RD
3339 b_ip4 = VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
3340 b_ip6 = VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
3343 # Pg7 hosts a BD's UU-fwd
3345 self.pg7.config_ip4()
3346 self.pg7.resolve_arp()
3349 # a GBP bridge domains for the EPs
3351 bd1 = VppBridgeDomain(self, 1)
3352 bd1.add_vpp_config()
3353 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0)
3354 gbd1.add_vpp_config()
3356 bd2 = VppBridgeDomain(self, 2)
3357 bd2.add_vpp_config()
3358 gbd2 = VppGbpBridgeDomain(self, bd2, rd1, self.loop1)
3359 gbd2.add_vpp_config()
3361 # ... and has a /32 and /128 applied
3362 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi,
3364 bind=b_ip4).add_vpp_config()
3365 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi,
3366 "2001:10::128", 128,
3367 bind=b_ip6).add_vpp_config()
3368 ip4_addr = VppIpInterfaceAddress(self, gbd2.bvi,
3369 "10.0.1.128", 32).add_vpp_config()
3370 ip6_addr = VppIpInterfaceAddress(self, gbd2.bvi,
3371 "2001:11::128", 128).add_vpp_config()
3374 # The Endpoint-groups in which we are learning endpoints
3376 epg_220 = VppGbpEndpointGroup(self, 220, 440, rd1, gbd1,
3380 VppGbpEndpointRetention(60))
3381 epg_220.add_vpp_config()
3382 epg_221 = VppGbpEndpointGroup(self, 221, 441, rd1, gbd2,
3386 VppGbpEndpointRetention(60))
3387 epg_221.add_vpp_config()
3388 epg_222 = VppGbpEndpointGroup(self, 222, 442, rd1, gbd1,
3392 VppGbpEndpointRetention(60))
3393 epg_222.add_vpp_config()
3396 # a GBP bridge domains for the SEPs
3398 bd_uu1 = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
3399 self.pg7.remote_ip4, 116)
3400 bd_uu1.add_vpp_config()
3401 bd_uu2 = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
3402 self.pg7.remote_ip4, 117)
3403 bd_uu2.add_vpp_config()
3405 bd3 = VppBridgeDomain(self, 3)
3406 bd3.add_vpp_config()
3407 gbd3 = VppGbpBridgeDomain(self, bd3, rd1, self.loop2,
3408 bd_uu1, learn=False)
3409 gbd3.add_vpp_config()
3410 bd4 = VppBridgeDomain(self, 4)
3411 bd4.add_vpp_config()
3412 gbd4 = VppGbpBridgeDomain(self, bd4, rd1, self.loop3,
3413 bd_uu2, learn=False)
3414 gbd4.add_vpp_config()
3417 # EPGs in which the service endpoints exist
3419 epg_320 = VppGbpEndpointGroup(self, 320, 550, rd1, gbd3,
3423 VppGbpEndpointRetention(60))
3424 epg_320.add_vpp_config()
3425 epg_321 = VppGbpEndpointGroup(self, 321, 551, rd1, gbd4,
3429 VppGbpEndpointRetention(60))
3430 epg_321.add_vpp_config()
3433 # three local endpoints
3435 ep1 = VppGbpEndpoint(self, self.pg0,
3437 "10.0.0.1", "11.0.0.1",
3438 "2001:10::1", "3001:10::1")
3439 ep1.add_vpp_config()
3440 ep2 = VppGbpEndpoint(self, self.pg1,
3442 "10.0.1.1", "11.0.1.1",
3443 "2001:11::1", "3001:11::1")
3444 ep2.add_vpp_config()
3445 ep3 = VppGbpEndpoint(self, self.pg2,
3447 "10.0.2.2", "11.0.2.2",
3448 "2001:12::1", "3001:12::1")
3449 ep3.add_vpp_config()
3454 sep1 = VppGbpEndpoint(self, self.pg3,
3456 "12.0.0.1", "13.0.0.1",
3457 "4001:10::1", "5001:10::1")
3458 sep1.add_vpp_config()
3459 sep2 = VppGbpEndpoint(self, self.pg4,
3461 "12.0.0.2", "13.0.0.2",
3462 "4001:10::2", "5001:10::2")
3463 sep2.add_vpp_config()
3464 sep3 = VppGbpEndpoint(self, self.pg5,
3466 "12.0.1.1", "13.0.1.1",
3467 "4001:11::1", "5001:11::1")
3468 sep3.add_vpp_config()
3469 # this EP is not installed immediately
3470 sep4 = VppGbpEndpoint(self, self.pg6,
3472 "12.0.1.2", "13.0.1.2",
3473 "4001:11::2", "5001:11::2")
3476 # an L2 switch packet between local EPs in different EPGs
3477 # different dest ports on each so the are LB hashed differently
3479 p4 = [(Ether(src=ep1.mac, dst=ep3.mac) /
3480 IP(src=ep1.ip4, dst=ep3.ip4) /
3481 UDP(sport=1234, dport=1234) /
3482 Raw(b'\xa5' * 100)),
3483 (Ether(src=ep3.mac, dst=ep1.mac) /
3484 IP(src=ep3.ip4, dst=ep1.ip4) /
3485 UDP(sport=1234, dport=1234) /
3486 Raw(b'\xa5' * 100))]
3487 p6 = [(Ether(src=ep1.mac, dst=ep3.mac) /
3488 IPv6(src=ep1.ip6, dst=ep3.ip6) /
3489 UDP(sport=1234, dport=1234) /
3490 Raw(b'\xa5' * 100)),
3491 (Ether(src=ep3.mac, dst=ep1.mac) /
3492 IPv6(src=ep3.ip6, dst=ep1.ip6) /
3493 UDP(sport=1234, dport=1230) /
3494 Raw(b'\xa5' * 100))]
3496 # should be dropped since no contract yet
3497 self.send_and_assert_no_replies(self.pg0, [p4[0]])
3498 self.send_and_assert_no_replies(self.pg0, [p6[0]])
3501 # Add a contract with a rule to load-balance redirect via SEP1 and SEP2
3502 # one of the next-hops is via an EP that is not known
3504 rule4 = AclRule(is_permit=1, proto=17)
3505 rule6 = AclRule(src_prefix=IPv6Network((0, 0)),
3506 dst_prefix=IPv6Network((0, 0)), is_permit=1, proto=17)
3507 acl = VppAcl(self, rules=[rule4, rule6])
3508 acl.add_vpp_config()
3511 # test the src-ip hash mode
3513 c1 = VppGbpContract(
3514 self, 402, epg_220.sclass, epg_222.sclass, acl.acl_index,
3515 [VppGbpContractRule(
3516 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3517 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3518 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3519 sep1.ip4, sep1.epg.rd),
3520 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3521 sep2.ip4, sep2.epg.rd)]),
3523 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3524 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3525 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3526 sep3.ip6, sep3.epg.rd),
3527 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3528 sep4.ip6, sep4.epg.rd)])],
3529 [ETH_P_IP, ETH_P_IPV6])
3532 c2 = VppGbpContract(
3533 self, 402, epg_222.sclass, epg_220.sclass, acl.acl_index,
3534 [VppGbpContractRule(
3535 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3536 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3537 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3538 sep1.ip4, sep1.epg.rd),
3539 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3540 sep2.ip4, sep2.epg.rd)]),
3542 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3543 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3544 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3545 sep3.ip6, sep3.epg.rd),
3546 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3547 sep4.ip6, sep4.epg.rd)])],
3548 [ETH_P_IP, ETH_P_IPV6])
3552 # send again with the contract preset, now packets arrive
3553 # at SEP1 or SEP2 depending on the hashing
3555 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3558 self.assertEqual(rx[Ether].src, routed_src_mac)
3559 self.assertEqual(rx[Ether].dst, sep1.mac)
3560 self.assertEqual(rx[IP].src, ep1.ip4)
3561 self.assertEqual(rx[IP].dst, ep3.ip4)
3563 rxs = self.send_and_expect(self.pg2, p4[1] * 17, sep2.itf)
3566 self.assertEqual(rx[Ether].src, routed_src_mac)
3567 self.assertEqual(rx[Ether].dst, sep2.mac)
3568 self.assertEqual(rx[IP].src, ep3.ip4)
3569 self.assertEqual(rx[IP].dst, ep1.ip4)
3571 rxs = self.send_and_expect(self.pg0, p6[0] * 17, self.pg7)
3574 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3575 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3576 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3577 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
3578 self.assertEqual(rx[VXLAN].vni, 117)
3579 self.assertTrue(rx[VXLAN].flags.G)
3580 self.assertTrue(rx[VXLAN].flags.Instance)
3581 # redirect policy has been applied
3582 self.assertTrue(rx[VXLAN].gpflags.A)
3583 self.assertFalse(rx[VXLAN].gpflags.D)
3585 inner = rx[VXLAN].payload
3587 self.assertEqual(inner[Ether].src, routed_src_mac)
3588 self.assertEqual(inner[Ether].dst, sep4.mac)
3589 self.assertEqual(inner[IPv6].src, ep1.ip6)
3590 self.assertEqual(inner[IPv6].dst, ep3.ip6)
3592 rxs = self.send_and_expect(self.pg2, p6[1] * 17, sep3.itf)
3595 self.assertEqual(rx[Ether].src, routed_src_mac)
3596 self.assertEqual(rx[Ether].dst, sep3.mac)
3597 self.assertEqual(rx[IPv6].src, ep3.ip6)
3598 self.assertEqual(rx[IPv6].dst, ep1.ip6)
3601 # programme the unknown EP
3603 sep4.add_vpp_config()
3605 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep4.itf)
3608 self.assertEqual(rx[Ether].src, routed_src_mac)
3609 self.assertEqual(rx[Ether].dst, sep4.mac)
3610 self.assertEqual(rx[IPv6].src, ep1.ip6)
3611 self.assertEqual(rx[IPv6].dst, ep3.ip6)
3614 # and revert back to unprogrammed
3616 sep4.remove_vpp_config()
3618 rxs = self.send_and_expect(self.pg0, p6[0] * 17, self.pg7)
3621 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3622 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3623 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3624 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
3625 self.assertEqual(rx[VXLAN].vni, 117)
3626 self.assertTrue(rx[VXLAN].flags.G)
3627 self.assertTrue(rx[VXLAN].flags.Instance)
3628 # redirect policy has been applied
3629 self.assertTrue(rx[VXLAN].gpflags.A)
3630 self.assertFalse(rx[VXLAN].gpflags.D)
3632 inner = rx[VXLAN].payload
3634 self.assertEqual(inner[Ether].src, routed_src_mac)
3635 self.assertEqual(inner[Ether].dst, sep4.mac)
3636 self.assertEqual(inner[IPv6].src, ep1.ip6)
3637 self.assertEqual(inner[IPv6].dst, ep3.ip6)
3639 c1.remove_vpp_config()
3640 c2.remove_vpp_config()
3643 # test the symmetric hash mode
3645 c1 = VppGbpContract(
3646 self, 402, epg_220.sclass, epg_222.sclass, acl.acl_index,
3647 [VppGbpContractRule(
3648 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3649 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3650 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3651 sep1.ip4, sep1.epg.rd),
3652 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3653 sep2.ip4, sep2.epg.rd)]),
3655 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3656 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3657 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3658 sep3.ip6, sep3.epg.rd),
3659 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3660 sep4.ip6, sep4.epg.rd)])],
3661 [ETH_P_IP, ETH_P_IPV6])
3664 c2 = VppGbpContract(
3665 self, 402, epg_222.sclass, epg_220.sclass, acl.acl_index,
3666 [VppGbpContractRule(
3667 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3668 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3669 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3670 sep1.ip4, sep1.epg.rd),
3671 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3672 sep2.ip4, sep2.epg.rd)]),
3674 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3675 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3676 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3677 sep3.ip6, sep3.epg.rd),
3678 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3679 sep4.ip6, sep4.epg.rd)])],
3680 [ETH_P_IP, ETH_P_IPV6])
3684 # send again with the contract preset, now packets arrive
3685 # at SEP1 for both directions
3687 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3690 self.assertEqual(rx[Ether].src, routed_src_mac)
3691 self.assertEqual(rx[Ether].dst, sep1.mac)
3692 self.assertEqual(rx[IP].src, ep1.ip4)
3693 self.assertEqual(rx[IP].dst, ep3.ip4)
3695 rxs = self.send_and_expect(self.pg2, p4[1] * 17, sep1.itf)
3698 self.assertEqual(rx[Ether].src, routed_src_mac)
3699 self.assertEqual(rx[Ether].dst, sep1.mac)
3700 self.assertEqual(rx[IP].src, ep3.ip4)
3701 self.assertEqual(rx[IP].dst, ep1.ip4)
3704 # programme the unknown EP for the L3 tests
3706 sep4.add_vpp_config()
3709 # an L3 switch packet between local EPs in different EPGs
3710 # different dest ports on each so the are LB hashed differently
3712 p4 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3713 IP(src=ep1.ip4, dst=ep2.ip4) /
3714 UDP(sport=1234, dport=1234) /
3715 Raw(b'\xa5' * 100)),
3716 (Ether(src=ep2.mac, dst=str(self.router_mac)) /
3717 IP(src=ep2.ip4, dst=ep1.ip4) /
3718 UDP(sport=1234, dport=1234) /
3719 Raw(b'\xa5' * 100))]
3720 p6 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3721 IPv6(src=ep1.ip6, dst=ep2.ip6) /
3722 UDP(sport=1234, dport=1234) /
3723 Raw(b'\xa5' * 100)),
3724 (Ether(src=ep2.mac, dst=str(self.router_mac)) /
3725 IPv6(src=ep2.ip6, dst=ep1.ip6) /
3726 UDP(sport=1234, dport=1234) /
3727 Raw(b'\xa5' * 100))]
3729 c3 = VppGbpContract(
3730 self, 402, epg_220.sclass, epg_221.sclass, acl.acl_index,
3731 [VppGbpContractRule(
3732 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3733 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3734 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3735 sep1.ip4, sep1.epg.rd),
3736 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3737 sep2.ip4, sep2.epg.rd)]),
3739 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3740 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3741 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3742 sep3.ip6, sep3.epg.rd),
3743 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3744 sep4.ip6, sep4.epg.rd)])],
3745 [ETH_P_IP, ETH_P_IPV6])
3748 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3751 self.assertEqual(rx[Ether].src, routed_src_mac)
3752 self.assertEqual(rx[Ether].dst, sep1.mac)
3753 self.assertEqual(rx[IP].src, ep1.ip4)
3754 self.assertEqual(rx[IP].dst, ep2.ip4)
3757 # learn a remote EP in EPG 221
3758 # packets coming from unknown remote EPs will be leant & redirected
3760 vx_tun_l3 = VppGbpVxlanTunnel(
3761 self, 444, rd1.rd_id,
3762 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
3764 vx_tun_l3.add_vpp_config()
3766 c4 = VppGbpContract(
3767 self, 402, epg_221.sclass, epg_220.sclass, acl.acl_index,
3768 [VppGbpContractRule(
3769 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3770 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3771 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3772 sep1.ip4, sep1.epg.rd),
3773 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3774 sep2.ip4, sep2.epg.rd)]),
3776 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3777 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3778 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3779 sep3.ip6, sep3.epg.rd),
3780 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3781 sep4.ip6, sep4.epg.rd)])],
3782 [ETH_P_IP, ETH_P_IPV6])
3785 p = (Ether(src=self.pg7.remote_mac,
3786 dst=self.pg7.local_mac) /
3787 IP(src=self.pg7.remote_ip4,
3788 dst=self.pg7.local_ip4) /
3789 UDP(sport=1234, dport=48879) /
3790 VXLAN(vni=444, gpid=441, flags=0x88) /
3791 Ether(src="00:22:22:22:22:33", dst=str(self.router_mac)) /
3792 IP(src="10.0.0.88", dst=ep1.ip4) /
3793 UDP(sport=1234, dport=1234) /
3796 # unknown remote EP to local EP redirected
3797 rxs = self.send_and_expect(self.pg7, [p], sep1.itf)
3800 self.assertEqual(rx[Ether].src, routed_src_mac)
3801 self.assertEqual(rx[Ether].dst, sep1.mac)
3802 self.assertEqual(rx[IP].src, "10.0.0.88")
3803 self.assertEqual(rx[IP].dst, ep1.ip4)
3805 # endpoint learnt via the parent GBP-vxlan interface
3806 self.assertTrue(find_gbp_endpoint(self,
3807 vx_tun_l3._sw_if_index,
3810 p = (Ether(src=self.pg7.remote_mac,
3811 dst=self.pg7.local_mac) /
3812 IP(src=self.pg7.remote_ip4,
3813 dst=self.pg7.local_ip4) /
3814 UDP(sport=1234, dport=48879) /
3815 VXLAN(vni=444, gpid=441, flags=0x88) /
3816 Ether(src="00:22:22:22:22:33", dst=str(self.router_mac)) /
3817 IPv6(src="2001:10::88", dst=ep1.ip6) /
3818 UDP(sport=1234, dport=1234) /
3821 # unknown remote EP to local EP redirected (ipv6)
3822 rxs = self.send_and_expect(self.pg7, [p], sep3.itf)
3825 self.assertEqual(rx[Ether].src, routed_src_mac)
3826 self.assertEqual(rx[Ether].dst, sep3.mac)
3827 self.assertEqual(rx[IPv6].src, "2001:10::88")
3828 self.assertEqual(rx[IPv6].dst, ep1.ip6)
3830 # endpoint learnt via the parent GBP-vxlan interface
3831 self.assertTrue(find_gbp_endpoint(self,
3832 vx_tun_l3._sw_if_index,
3836 # L3 switch from local to remote EP
3838 p4 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3839 IP(src=ep1.ip4, dst="10.0.0.88") /
3840 UDP(sport=1234, dport=1234) /
3841 Raw(b'\xa5' * 100))]
3842 p6 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3843 IPv6(src=ep1.ip6, dst="2001:10::88") /
3844 UDP(sport=1234, dport=1234) /
3845 Raw(b'\xa5' * 100))]
3847 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3850 self.assertEqual(rx[Ether].src, routed_src_mac)
3851 self.assertEqual(rx[Ether].dst, sep1.mac)
3852 self.assertEqual(rx[IP].src, ep1.ip4)
3853 self.assertEqual(rx[IP].dst, "10.0.0.88")
3855 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep4.itf)
3858 self.assertEqual(rx[Ether].src, routed_src_mac)
3859 self.assertEqual(rx[Ether].dst, sep4.mac)
3860 self.assertEqual(rx[IPv6].src, ep1.ip6)
3861 self.assertEqual(rx[IPv6].dst, "2001:10::88")
3864 # test the dst-ip hash mode
3866 c5 = VppGbpContract(
3867 self, 402, epg_220.sclass, epg_221.sclass, acl.acl_index,
3868 [VppGbpContractRule(
3869 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3870 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
3871 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3872 sep1.ip4, sep1.epg.rd),
3873 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3874 sep2.ip4, sep2.epg.rd)]),
3876 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3877 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
3878 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3879 sep3.ip6, sep3.epg.rd),
3880 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3881 sep4.ip6, sep4.epg.rd)])],
3882 [ETH_P_IP, ETH_P_IPV6])
3885 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3888 self.assertEqual(rx[Ether].src, routed_src_mac)
3889 self.assertEqual(rx[Ether].dst, sep1.mac)
3890 self.assertEqual(rx[IP].src, ep1.ip4)
3891 self.assertEqual(rx[IP].dst, "10.0.0.88")
3893 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep3.itf)
3896 self.assertEqual(rx[Ether].src, routed_src_mac)
3897 self.assertEqual(rx[Ether].dst, sep3.mac)
3898 self.assertEqual(rx[IPv6].src, ep1.ip6)
3899 self.assertEqual(rx[IPv6].dst, "2001:10::88")
3902 # a programmed remote SEP in EPG 320
3905 # gbp vxlan tunnel for the remote SEP
3906 vx_tun_l3_sep = VppGbpVxlanTunnel(
3907 self, 555, rd1.rd_id,
3908 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
3910 vx_tun_l3_sep.add_vpp_config()
3913 sep5 = VppGbpEndpoint(self, vx_tun_l3_sep,
3915 "12.0.0.10", "13.0.0.10",
3916 "4001:10::10", "5001:10::10",
3917 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
3919 self.pg7.remote_ip4,
3921 sep5.add_vpp_config()
3924 # local l3out redirect tests
3929 self.loop4.set_mac(self.router_mac)
3930 b_lo4_ip4 = VppIpInterfaceBind(self, self.loop4, t4).add_vpp_config()
3931 b_lo4_ip6 = VppIpInterfaceBind(self, self.loop4, t6).add_vpp_config()
3932 ebd = VppBridgeDomain(self, 100)
3933 ebd.add_vpp_config()
3934 gebd = VppGbpBridgeDomain(self, ebd, rd1, self.loop4, None, None)
3935 gebd.add_vpp_config()
3937 eepg = VppGbpEndpointGroup(self, 888, 765, rd1, gebd,
3941 VppGbpEndpointRetention(60))
3942 eepg.add_vpp_config()
3943 # add subnets to BVI
3944 VppIpInterfaceAddress(
3948 24, bind=b_lo4_ip4).add_vpp_config()
3949 VppIpInterfaceAddress(
3953 64, bind=b_lo4_ip6).add_vpp_config()
3954 # ... which are L3-out subnets
3955 VppGbpSubnet(self, rd1, "10.1.0.0", 24,
3956 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3957 sclass=765).add_vpp_config()
3958 VppGbpSubnet(self, rd1, "2001:10:1::128", 64,
3959 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3960 sclass=765).add_vpp_config()
3961 # external endpoints
3962 VppL2Vtr(self, self.vlan_100, L2_VTR_OP.L2_POP_1).add_vpp_config()
3963 eep1 = VppGbpEndpoint(self, self.vlan_100, eepg, None, "10.1.0.1",
3964 "11.1.0.1", "2001:10:1::1", "3001:10:1::1",
3965 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
3966 eep1.add_vpp_config()
3967 VppL2Vtr(self, self.vlan_101, L2_VTR_OP.L2_POP_1).add_vpp_config()
3968 eep2 = VppGbpEndpoint(self, self.vlan_101, eepg, None, "10.1.0.2",
3969 "11.1.0.2", "2001:10:1::2", "3001:10:1::2",
3970 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
3971 eep2.add_vpp_config()
3973 # external subnets reachable though eep1 and eep2 respectively
3974 VppIpRoute(self, "10.220.0.0", 24,
3975 [VppRoutePath(eep1.ip4, eep1.epg.bvi.sw_if_index)],
3976 table_id=t4.table_id).add_vpp_config()
3977 VppGbpSubnet(self, rd1, "10.220.0.0", 24,
3978 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3979 sclass=4220).add_vpp_config()
3980 VppIpRoute(self, "10:220::", 64,
3981 [VppRoutePath(eep1.ip6, eep1.epg.bvi.sw_if_index)],
3982 table_id=t6.table_id).add_vpp_config()
3983 VppGbpSubnet(self, rd1, "10:220::", 64,
3984 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3985 sclass=4220).add_vpp_config()
3986 VppIpRoute(self, "10.221.0.0", 24,
3987 [VppRoutePath(eep2.ip4, eep2.epg.bvi.sw_if_index)],
3988 table_id=t4.table_id).add_vpp_config()
3989 VppGbpSubnet(self, rd1, "10.221.0.0", 24,
3990 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3991 sclass=4221).add_vpp_config()
3992 VppIpRoute(self, "10:221::", 64,
3993 [VppRoutePath(eep2.ip6, eep2.epg.bvi.sw_if_index)],
3994 table_id=t6.table_id).add_vpp_config()
3995 VppGbpSubnet(self, rd1, "10:221::", 64,
3996 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3997 sclass=4221).add_vpp_config()
4000 # l3out redirect to remote (known, then unknown) SEP
4003 # packets from 1 external subnet to the other
4004 p = [(Ether(src=eep1.mac, dst=self.router_mac) /
4006 IP(src="10.220.0.17", dst="10.221.0.65") /
4007 UDP(sport=1234, dport=1234) /
4008 Raw(b'\xa5' * 100)),
4009 (Ether(src=eep1.mac, dst=self.router_mac) /
4011 IPv6(src="10:220::17", dst="10:221::65") /
4012 UDP(sport=1234, dport=1234) /
4013 Raw(b'\xa5' * 100))]
4015 # packets should be dropped in absence of contract
4016 self.send_and_assert_no_replies(self.pg0, p)
4018 # contract redirecting to sep5
4020 self, 402, 4220, 4221, acl.acl_index,
4021 [VppGbpContractRule(
4022 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4023 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
4024 [VppGbpContractNextHop(sep5.vmac, sep5.epg.bd,
4025 sep5.ip4, sep5.epg.rd)]),
4027 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4028 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
4029 [VppGbpContractNextHop(sep5.vmac, sep5.epg.bd,
4030 sep5.ip6, sep5.epg.rd)])],
4031 [ETH_P_IP, ETH_P_IPV6]).add_vpp_config()
4033 rxs = self.send_and_expect(self.pg0, p, self.pg7)
4035 for rx, tx in zip(rxs, p):
4036 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4037 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4038 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4039 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4040 # this should use the programmed remote leaf TEP
4041 self.assertEqual(rx[VXLAN].vni, 555)
4042 self.assertEqual(rx[VXLAN].gpid, 4220)
4043 self.assertTrue(rx[VXLAN].flags.G)
4044 self.assertTrue(rx[VXLAN].flags.Instance)
4045 # redirect policy has been applied
4046 self.assertTrue(rx[VXLAN].gpflags.A)
4047 self.assertTrue(rx[VXLAN].gpflags.D)
4048 rxip = rx[VXLAN][Ether].payload
4049 txip = tx[Dot1Q].payload
4050 self.assertEqual(rxip.src, txip.src)
4051 self.assertEqual(rxip.dst, txip.dst)
4053 # remote SEP: it is now an unknown remote SEP and should go
4055 sep5.remove_vpp_config()
4057 rxs = self.send_and_expect(self.pg0, p, self.pg7)
4059 for rx, tx in zip(rxs, p):
4060 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4061 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4062 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4063 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4064 # this should use the spine proxy TEP
4065 self.assertEqual(rx[VXLAN].vni, epg_320.bd.uu_fwd.vni)
4066 self.assertEqual(rx[VXLAN].gpid, 4220)
4067 self.assertTrue(rx[VXLAN].flags.G)
4068 self.assertTrue(rx[VXLAN].flags.Instance)
4069 # redirect policy has been applied
4070 self.assertTrue(rx[VXLAN].gpflags.A)
4071 self.assertTrue(rx[VXLAN].gpflags.D)
4072 rxip = rx[VXLAN][Ether].payload
4073 txip = tx[Dot1Q].payload
4074 self.assertEqual(rxip.src, txip.src)
4075 self.assertEqual(rxip.dst, txip.dst)
4078 # l3out redirect to local SEP
4081 # change the contract between l3out to redirect to local SEPs
4082 # instead of remote SEP
4084 self, 402, 4220, 4221, acl.acl_index,
4085 [VppGbpContractRule(
4086 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4087 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
4088 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
4089 sep1.ip4, sep1.epg.rd)]),
4091 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4092 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
4093 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
4094 sep1.ip6, sep1.epg.rd)])],
4095 [ETH_P_IP, ETH_P_IPV6]).add_vpp_config()
4097 rxs = self.send_and_expect(self.pg0, p, sep1.itf)
4098 for rx, tx in zip(rxs, p):
4099 self.assertEqual(rx[Ether].src, routed_src_mac)
4100 self.assertEqual(rx[Ether].dst, sep1.mac)
4101 rxip = rx[Ether].payload
4102 txip = tx[Ether].payload
4103 self.assertEqual(rxip.src, txip.src)
4104 self.assertEqual(rxip.dst, txip.dst)
4107 # redirect remote EP to remote (known then unknown) SEP
4110 # remote SEP known again
4111 sep5.add_vpp_config()
4113 # contract to redirect to learnt SEP
4115 self, 402, epg_221.sclass, epg_222.sclass, acl.acl_index,
4116 [VppGbpContractRule(
4117 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4118 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
4119 [VppGbpContractNextHop(sep5.vmac, sep5.epg.bd,
4120 sep5.ip4, sep5.epg.rd)]),
4122 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4123 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
4124 [VppGbpContractNextHop(sep5.vmac, sep5.epg.bd,
4125 sep5.ip6, sep5.epg.rd)])],
4126 [ETH_P_IP, ETH_P_IPV6]).add_vpp_config()
4128 # packets from unknown EP 221 to known EP in EPG 222
4129 # should be redirected to known remote SEP
4130 base = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
4131 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
4132 UDP(sport=1234, dport=48879) /
4133 VXLAN(vni=444, gpid=441, flags=0x88) /
4134 Ether(src="00:22:22:22:22:44", dst=str(self.router_mac)))
4136 IP(src="10.0.1.100", dst=ep3.ip4) /
4137 UDP(sport=1234, dport=1234) /
4138 Raw(b'\xa5' * 100)),
4140 IPv6(src="2001:10::100", dst=ep3.ip6) /
4141 UDP(sport=1234, dport=1234) /
4142 Raw(b'\xa5' * 100))]
4144 # unknown remote EP to local EP redirected to known remote SEP
4145 rxs = self.send_and_expect(self.pg7, p, self.pg7)
4147 for rx, tx in zip(rxs, p):
4148 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4149 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4150 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4151 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4152 # this should use the programmed remote leaf TEP
4153 self.assertEqual(rx[VXLAN].vni, 555)
4154 self.assertEqual(rx[VXLAN].gpid, epg_221.sclass)
4155 self.assertTrue(rx[VXLAN].flags.G)
4156 self.assertTrue(rx[VXLAN].flags.Instance)
4157 # redirect policy has been applied
4158 self.assertTrue(rx[VXLAN].gpflags.A)
4159 self.assertFalse(rx[VXLAN].gpflags.D)
4160 rxip = rx[VXLAN][Ether].payload
4161 txip = tx[VXLAN][Ether].payload
4162 self.assertEqual(rxip.src, txip.src)
4163 self.assertEqual(rxip.dst, txip.dst)
4165 # endpoint learnt via the parent GBP-vxlan interface
4166 self.assertTrue(find_gbp_endpoint(self,
4167 vx_tun_l3._sw_if_index,
4169 self.assertTrue(find_gbp_endpoint(self,
4170 vx_tun_l3._sw_if_index,
4173 # remote SEP: it is now an unknown remote SEP and should go
4175 sep5.remove_vpp_config()
4177 # remote EP (coming from spine proxy) to local EP redirected to
4179 rxs = self.send_and_expect(self.pg7, p, self.pg7)
4181 for rx, tx in zip(rxs, p):
4182 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4183 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4184 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4185 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4186 # this should use the spine proxy TEP
4187 self.assertEqual(rx[VXLAN].vni, epg_320.bd.uu_fwd.vni)
4188 self.assertEqual(rx[VXLAN].gpid, epg_221.sclass)
4189 self.assertTrue(rx[VXLAN].flags.G)
4190 self.assertTrue(rx[VXLAN].flags.Instance)
4191 # redirect policy has been applied
4192 self.assertTrue(rx[VXLAN].gpflags.A)
4193 self.assertFalse(rx[VXLAN].gpflags.D)
4194 rxip = rx[VXLAN][Ether].payload
4195 txip = tx[VXLAN][Ether].payload
4196 self.assertEqual(rxip.src, txip.src)
4197 self.assertEqual(rxip.dst, txip.dst)
4202 self.pg7.unconfig_ip4()
4204 def test_gbp_redirect_extended(self):
4205 """ GBP Endpoint Redirect Extended """
4207 self.vapi.cli("set logging class gbp level debug")
4209 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
4210 routed_dst_mac = "00:0c:0c:0c:0c:0c"
4211 routed_src_mac = "00:22:bd:f8:19:ff"
4213 learnt = [{'mac': '00:00:11:11:11:02',
4215 'ip6': '2001:10::2'},
4216 {'mac': '00:00:11:11:11:03',
4218 'ip6': '2001:10::3'}]
4223 t4 = VppIpTable(self, 1)
4225 t6 = VppIpTable(self, 1, True)
4228 # create IPv4 and IPv6 RD UU VxLAN-GBP TEP and bind them to the right
4230 rd_uu4 = VppVxlanGbpTunnel(
4233 self.pg7.remote_ip4,
4235 mode=(VppEnum.vl_api_vxlan_gbp_api_tunnel_mode_t.
4236 VXLAN_GBP_API_TUNNEL_MODE_L3))
4237 rd_uu4.add_vpp_config()
4238 VppIpInterfaceBind(self, rd_uu4, t4).add_vpp_config()
4240 rd_uu6 = VppVxlanGbpTunnel(
4243 self.pg7.remote_ip4,
4245 mode=(VppEnum.vl_api_vxlan_gbp_api_tunnel_mode_t.
4246 VXLAN_GBP_API_TUNNEL_MODE_L3))
4247 rd_uu6.add_vpp_config()
4248 VppIpInterfaceBind(self, rd_uu6, t4).add_vpp_config()
4250 rd1 = VppGbpRouteDomain(self, 2, 402, t4, t6, rd_uu4, rd_uu6)
4251 rd1.add_vpp_config()
4253 self.loop0.set_mac(self.router_mac)
4254 self.loop1.set_mac(self.router_mac)
4255 self.loop2.set_mac(self.router_mac)
4258 # Bind the BVI to the RD
4260 b_lo0_ip4 = VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
4261 b_lo0_ip6 = VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
4262 b_lo1_ip4 = VppIpInterfaceBind(self, self.loop1, t4).add_vpp_config()
4263 b_lo1_ip6 = VppIpInterfaceBind(self, self.loop1, t6).add_vpp_config()
4264 b_lo2_ip4 = VppIpInterfaceBind(self, self.loop2, t4).add_vpp_config()
4265 b_lo2_ip6 = VppIpInterfaceBind(self, self.loop2, t6).add_vpp_config()
4268 # Pg7 hosts a BD's UU-fwd
4270 self.pg7.config_ip4()
4271 self.pg7.resolve_arp()
4274 # a GBP bridge domains for the EPs
4276 bd1 = VppBridgeDomain(self, 1)
4277 bd1.add_vpp_config()
4278 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0)
4279 gbd1.add_vpp_config()
4281 bd2 = VppBridgeDomain(self, 2)
4282 bd2.add_vpp_config()
4283 gbd2 = VppGbpBridgeDomain(self, bd2, rd1, self.loop1)
4284 gbd2.add_vpp_config()
4286 # ... and has a /32 and /128 applied
4287 ip4_addr1 = VppIpInterfaceAddress(self, gbd1.bvi,
4289 bind=b_lo0_ip4).add_vpp_config()
4290 ip6_addr1 = VppIpInterfaceAddress(self, gbd1.bvi,
4291 "2001:10::128", 128,
4292 bind=b_lo0_ip6).add_vpp_config()
4293 ip4_addr2 = VppIpInterfaceAddress(self, gbd2.bvi,
4295 bind=b_lo1_ip4).add_vpp_config()
4296 ip6_addr2 = VppIpInterfaceAddress(self, gbd2.bvi,
4297 "2001:11::128", 128,
4298 bind=b_lo1_ip6).add_vpp_config()
4301 # The Endpoint-groups
4303 epg_220 = VppGbpEndpointGroup(self, 220, 440, rd1, gbd1,
4307 VppGbpEndpointRetention(60))
4308 epg_220.add_vpp_config()
4309 epg_221 = VppGbpEndpointGroup(self, 221, 441, rd1, gbd2,
4313 VppGbpEndpointRetention(60))
4314 epg_221.add_vpp_config()
4317 # a GBP bridge domains for the SEPs
4319 bd_uu3 = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
4320 self.pg7.remote_ip4, 116)
4321 bd_uu3.add_vpp_config()
4323 bd3 = VppBridgeDomain(self, 3)
4324 bd3.add_vpp_config()
4325 gbd3 = VppGbpBridgeDomain(self, bd3, rd1, self.loop2,
4326 bd_uu3, learn=False)
4327 gbd3.add_vpp_config()
4329 ip4_addr3 = VppIpInterfaceAddress(self, gbd3.bvi,
4331 bind=b_lo2_ip4).add_vpp_config()
4332 ip6_addr3 = VppIpInterfaceAddress(self, gbd3.bvi,
4333 "4001:10::128", 128,
4334 bind=b_lo2_ip6).add_vpp_config()
4337 # self.logger.info(self.vapi.cli("show gbp bridge"))
4338 # self.logger.info(self.vapi.cli("show vxlan-gbp tunnel"))
4339 # self.logger.info(self.vapi.cli("show gbp vxlan"))
4340 # self.logger.info(self.vapi.cli("show int addr"))
4344 # EPGs in which the service endpoints exist
4346 epg_320 = VppGbpEndpointGroup(self, 320, 550, rd1, gbd3,
4350 VppGbpEndpointRetention(60))
4351 epg_320.add_vpp_config()
4356 ep1 = VppGbpEndpoint(self, self.pg0,
4358 "10.0.0.1", "11.0.0.1",
4359 "2001:10::1", "3001:10::1")
4360 ep1.add_vpp_config()
4361 ep2 = VppGbpEndpoint(self, self.pg1,
4363 "10.0.1.1", "11.0.1.1",
4364 "2001:11::1", "3001:11::1")
4365 ep2.add_vpp_config()
4370 sep1 = VppGbpEndpoint(self, self.pg3,
4372 "12.0.0.1", "13.0.0.1",
4373 "4001:10::1", "5001:10::1")
4374 sep2 = VppGbpEndpoint(self, self.pg4,
4376 "12.0.0.2", "13.0.0.2",
4377 "4001:10::2", "5001:10::2")
4379 # sep1 and sep2 are not added to config yet
4380 # they are unknown for now
4383 # add routes to EPG subnets
4385 VppGbpSubnet(self, rd1, "10.0.0.0", 24,
4386 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT
4388 VppGbpSubnet(self, rd1, "10.0.1.0", 24,
4389 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT
4393 # Local host to known local host in different BD
4394 # with SFC contract (source and destination are in
4395 # one node and service endpoint in another node)
4397 p4 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
4398 IP(src=ep1.ip4, dst=ep2.ip4) /
4399 UDP(sport=1234, dport=1234) /
4400 Raw(b'\xa5' * 100)),
4401 (Ether(src=ep2.mac, dst=str(self.router_mac)) /
4402 IP(src=ep2.ip4, dst=ep1.ip4) /
4403 UDP(sport=1234, dport=1234) /
4404 Raw(b'\xa5' * 100))]
4405 p6 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
4406 IPv6(src=ep1.ip6, dst=ep2.ip6) /
4407 UDP(sport=1234, dport=1234) /
4408 Raw(b'\xa5' * 100)),
4409 (Ether(src=ep2.mac, dst=str(self.router_mac)) /
4410 IPv6(src=ep2.ip6, dst=ep1.ip6) /
4411 UDP(sport=1234, dport=1230) /
4412 Raw(b'\xa5' * 100))]
4414 # should be dropped since no contract yet
4415 self.send_and_assert_no_replies(self.pg0, [p4[0]])
4416 self.send_and_assert_no_replies(self.pg0, [p6[0]])
4419 # Add a contract with a rule to load-balance redirect via SEP1 and SEP2
4420 # one of the next-hops is via an EP that is not known
4422 rule4 = AclRule(is_permit=1, proto=17)
4423 rule6 = AclRule(src_prefix=IPv6Network((0, 0)),
4424 dst_prefix=IPv6Network((0, 0)), is_permit=1, proto=17)
4425 acl = VppAcl(self, rules=[rule4, rule6])
4426 acl.add_vpp_config()
4429 # test the src-ip hash mode
4431 c1 = VppGbpContract(
4432 self, 402, epg_220.sclass, epg_221.sclass, acl.acl_index,
4433 [VppGbpContractRule(
4434 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4435 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
4436 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
4437 sep1.ip4, sep1.epg.rd)]),
4439 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4440 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
4441 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
4442 sep1.ip6, sep1.epg.rd)])],
4443 [ETH_P_IP, ETH_P_IPV6])
4446 c2 = VppGbpContract(
4447 self, 402, epg_221.sclass, epg_220.sclass, acl.acl_index,
4448 [VppGbpContractRule(
4449 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4450 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
4451 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
4452 sep1.ip4, sep1.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_SYMMETRIC,
4456 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
4457 sep1.ip6, sep1.epg.rd)])],
4458 [ETH_P_IP, ETH_P_IPV6])
4461 # ep1 <--> ep2 redirected through sep1
4463 # packet is redirected to sep bd and then go through sep bd UU
4465 rxs = self.send_and_expect(self.pg0, p4[0] * 17, self.pg7)
4468 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4469 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4470 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4471 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4472 self.assertEqual(rx[VXLAN].vni, 116)
4473 self.assertTrue(rx[VXLAN].flags.G)
4474 self.assertTrue(rx[VXLAN].flags.Instance)
4475 # redirect policy has been applied
4476 self.assertTrue(rx[VXLAN].gpflags.A)
4477 self.assertFalse(rx[VXLAN].gpflags.D)
4479 inner = rx[VXLAN].payload
4481 self.assertEqual(inner[Ether].src, routed_src_mac)
4482 self.assertEqual(inner[Ether].dst, sep1.mac)
4483 self.assertEqual(inner[IP].src, ep1.ip4)
4484 self.assertEqual(inner[IP].dst, ep2.ip4)
4486 rxs = self.send_and_expect(self.pg1, p4[1] * 17, self.pg7)
4489 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4490 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4491 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4492 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4493 self.assertEqual(rx[VXLAN].vni, 116)
4494 self.assertTrue(rx[VXLAN].flags.G)
4495 self.assertTrue(rx[VXLAN].flags.Instance)
4496 # redirect policy has been applied
4497 self.assertTrue(rx[VXLAN].gpflags.A)
4498 self.assertFalse(rx[VXLAN].gpflags.D)
4500 inner = rx[VXLAN].payload
4502 self.assertEqual(inner[Ether].src, routed_src_mac)
4503 self.assertEqual(inner[Ether].dst, sep1.mac)
4504 self.assertEqual(inner[IP].src, ep2.ip4)
4505 self.assertEqual(inner[IP].dst, ep1.ip4)
4507 rxs = self.send_and_expect(self.pg0, p6[0] * 17, self.pg7)
4510 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4511 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4512 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4513 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4514 self.assertEqual(rx[VXLAN].vni, 116)
4515 self.assertTrue(rx[VXLAN].flags.G)
4516 self.assertTrue(rx[VXLAN].flags.Instance)
4517 # redirect policy has been applied
4518 inner = rx[VXLAN].payload
4520 self.assertEqual(inner[Ether].src, routed_src_mac)
4521 self.assertEqual(inner[Ether].dst, sep1.mac)
4522 self.assertEqual(inner[IPv6].src, ep1.ip6)
4523 self.assertEqual(inner[IPv6].dst, ep2.ip6)
4525 rxs = self.send_and_expect(self.pg1, p6[1] * 17, self.pg7)
4528 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4529 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4530 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4531 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4532 self.assertEqual(rx[VXLAN].vni, 116)
4533 self.assertTrue(rx[VXLAN].flags.G)
4534 self.assertTrue(rx[VXLAN].flags.Instance)
4535 # redirect policy has been applied
4536 self.assertTrue(rx[VXLAN].gpflags.A)
4537 self.assertFalse(rx[VXLAN].gpflags.D)
4539 inner = rx[VXLAN].payload
4541 self.assertEqual(inner[Ether].src, routed_src_mac)
4542 self.assertEqual(inner[Ether].dst, sep1.mac)
4543 self.assertEqual(inner[IPv6].src, ep2.ip6)
4544 self.assertEqual(inner[IPv6].dst, ep1.ip6)
4546 # configure sep1: it is now local
4547 # packets between ep1 and ep2 are redirected locally
4548 sep1.add_vpp_config()
4550 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
4553 self.assertEqual(rx[Ether].src, routed_src_mac)
4554 self.assertEqual(rx[Ether].dst, sep1.mac)
4555 self.assertEqual(rx[IP].src, ep1.ip4)
4556 self.assertEqual(rx[IP].dst, ep2.ip4)
4558 rxs = self.send_and_expect(self.pg1, p6[1] * 17, sep1.itf)
4561 self.assertEqual(rx[Ether].src, routed_src_mac)
4562 self.assertEqual(rx[Ether].dst, sep1.mac)
4563 self.assertEqual(rx[IPv6].src, ep2.ip6)
4564 self.assertEqual(rx[IPv6].dst, ep1.ip6)
4566 # packet coming from the l2 spine-proxy to sep1
4567 p = (Ether(src=self.pg7.remote_mac,
4568 dst=self.pg7.local_mac) /
4569 IP(src=self.pg7.remote_ip4,
4570 dst=self.pg7.local_ip4) /
4571 UDP(sport=1234, dport=48879) /
4572 VXLAN(vni=116, gpid=440, gpflags=0x08, flags=0x88) /
4573 Ether(src=str(self.router_mac), dst=sep1.mac) /
4574 IP(src=ep1.ip4, dst=ep2.ip4) /
4575 UDP(sport=1234, dport=1234) /
4578 rxs = self.send_and_expect(self.pg7, [p] * 17, sep1.itf)
4581 self.assertEqual(rx[Ether].src, str(self.router_mac))
4582 self.assertEqual(rx[Ether].dst, sep1.mac)
4583 self.assertEqual(rx[IP].src, ep1.ip4)
4584 self.assertEqual(rx[IP].dst, ep2.ip4)
4586 # contract for SEP to communicate with dst EP
4587 c3 = VppGbpContract(
4588 self, 402, epg_320.sclass, epg_221.sclass, acl.acl_index,
4589 [VppGbpContractRule(
4590 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4591 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC),
4593 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4594 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC)],
4595 [ETH_P_IP, ETH_P_IPV6])
4598 # temporarily remove ep2, so that ep2 is remote & unknown
4599 ep2.remove_vpp_config()
4601 # packet going back from sep1 to its original dest (ep2)
4602 # as ep2 is now unknown (see above), it must go through
4603 # the rd UU (packet is routed)
4605 p1 = (Ether(src=sep1.mac, dst=self.router_mac) /
4606 IP(src=ep1.ip4, dst=ep2.ip4) /
4607 UDP(sport=1234, dport=1234) /
4610 rxs = self.send_and_expect(self.pg3, [p1] * 17, self.pg7)
4613 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4614 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4615 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4616 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4617 self.assertEqual(rx[VXLAN].vni, 114)
4618 self.assertTrue(rx[VXLAN].flags.G)
4619 self.assertTrue(rx[VXLAN].flags.Instance)
4620 # redirect policy has been applied
4621 inner = rx[VXLAN].payload
4622 self.assertEqual(inner[Ether].src, routed_src_mac)
4623 self.assertEqual(inner[Ether].dst, routed_dst_mac)
4624 self.assertEqual(inner[IP].src, ep1.ip4)
4625 self.assertEqual(inner[IP].dst, ep2.ip4)
4627 self.logger.info(self.vapi.cli("show bridge 3 detail"))
4628 sep1.remove_vpp_config()
4630 self.logger.info(self.vapi.cli("show bridge 1 detail"))
4631 self.logger.info(self.vapi.cli("show bridge 2 detail"))
4633 # re-add ep2: it is local again :)
4634 ep2.add_vpp_config()
4636 # packet coming back from the remote sep through rd UU
4637 p2 = (Ether(src=self.pg7.remote_mac,
4638 dst=self.pg7.local_mac) /
4639 IP(src=self.pg7.remote_ip4,
4640 dst=self.pg7.local_ip4) /
4641 UDP(sport=1234, dport=48879) /
4642 VXLAN(vni=114, gpid=441, gpflags=0x09, flags=0x88) /
4643 Ether(src=str(self.router_mac), dst=self.router_mac) /
4644 IP(src=ep1.ip4, dst=ep2.ip4) /
4645 UDP(sport=1234, dport=1234) /
4648 rxs = self.send_and_expect(self.pg7, [p2], self.pg1)
4651 self.assertEqual(rx[Ether].src, str(self.router_mac))
4652 self.assertEqual(rx[Ether].dst, self.pg1.remote_mac)
4653 self.assertEqual(rx[IP].src, ep1.ip4)
4654 self.assertEqual(rx[IP].dst, ep2.ip4)
4657 # bd_uu2.add_vpp_config()
4663 c1.remove_vpp_config()
4664 c2.remove_vpp_config()
4665 c3.remove_vpp_config()
4666 self.pg7.unconfig_ip4()
4668 def test_gbp_l3_out(self):
4671 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
4672 self.vapi.cli("set logging class gbp level debug")
4674 routed_dst_mac = "00:0c:0c:0c:0c:0c"
4675 routed_src_mac = "00:22:bd:f8:19:ff"
4680 t4 = VppIpTable(self, 1)
4682 t6 = VppIpTable(self, 1, True)
4685 rd1 = VppGbpRouteDomain(self, 2, 55, t4, t6)
4686 rd1.add_vpp_config()
4688 self.loop0.set_mac(self.router_mac)
4691 # Bind the BVI to the RD
4693 b_ip4 = VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
4694 b_ip6 = VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
4697 # Pg7 hosts a BD's BUM
4698 # Pg1 some other l3 interface
4700 self.pg7.config_ip4()
4701 self.pg7.resolve_arp()
4704 # a multicast vxlan-gbp tunnel for broadcast in the BD
4706 tun_bm = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
4709 tun_bm.add_vpp_config()
4712 # a GBP external bridge domains for the EPs
4714 bd1 = VppBridgeDomain(self, 1)
4715 bd1.add_vpp_config()
4716 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0, None, tun_bm)
4717 gbd1.add_vpp_config()
4720 # The Endpoint-groups in which the external endpoints exist
4722 epg_220 = VppGbpEndpointGroup(self, 220, 113, rd1, gbd1,
4726 VppGbpEndpointRetention(4))
4727 epg_220.add_vpp_config()
4729 # the BVIs have the subnets applied ...
4730 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128",
4731 24, bind=b_ip4).add_vpp_config()
4732 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128",
4733 64, bind=b_ip6).add_vpp_config()
4735 # ... which are L3-out subnets
4736 l3o_1 = VppGbpSubnet(
4737 self, rd1, "10.0.0.0", 24,
4738 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
4740 l3o_1.add_vpp_config()
4743 # an external interface attached to the outside world and the
4746 VppL2Vtr(self, self.vlan_100, L2_VTR_OP.L2_POP_1).add_vpp_config()
4747 VppL2Vtr(self, self.vlan_101, L2_VTR_OP.L2_POP_1).add_vpp_config()
4748 vlan_144 = VppDot1QSubint(self, self.pg0, 144)
4750 # vlan_102 is not poped
4753 # an unicast vxlan-gbp for inter-RD traffic
4755 vx_tun_l3 = VppGbpVxlanTunnel(
4756 self, 444, rd1.rd_id,
4757 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
4759 vx_tun_l3.add_vpp_config()
4762 # External Endpoints
4764 eep1 = VppGbpEndpoint(self, self.vlan_100,
4766 "10.0.0.1", "11.0.0.1",
4767 "2001:10::1", "3001::1",
4768 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
4769 eep1.add_vpp_config()
4770 eep2 = VppGbpEndpoint(self, self.vlan_101,
4772 "10.0.0.2", "11.0.0.2",
4773 "2001:10::2", "3001::2",
4774 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
4775 eep2.add_vpp_config()
4776 eep3 = VppGbpEndpoint(self, self.vlan_102,
4778 "10.0.0.3", "11.0.0.3",
4779 "2001:10::3", "3001::3",
4780 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
4781 eep3.add_vpp_config()
4784 # A remote external endpoint
4786 rep = VppGbpEndpoint(self, vx_tun_l3,
4788 "10.0.0.101", "11.0.0.101",
4789 "2001:10::101", "3001::101",
4790 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
4792 self.pg7.remote_ip4,
4794 rep.add_vpp_config()
4797 # EP1 impersonating EP3 is dropped
4799 p = (Ether(src=eep1.mac, dst="ff:ff:ff:ff:ff:ff") /
4802 psrc="10.0.0.3", pdst="10.0.0.128",
4803 hwsrc=eep1.mac, hwdst="ff:ff:ff:ff:ff:ff"))
4804 self.send_and_assert_no_replies(self.pg0, p)
4807 # ARP packet from External EPs are accepted and replied to
4809 p_arp = (Ether(src=eep1.mac, dst="ff:ff:ff:ff:ff:ff") /
4812 psrc=eep1.ip4, pdst="10.0.0.128",
4813 hwsrc=eep1.mac, hwdst="ff:ff:ff:ff:ff:ff"))
4814 rxs = self.send_and_expect(self.pg0, p_arp * 1, self.pg0)
4817 # ARP packet from host in remote subnet are accepted and replied to
4819 p_arp = (Ether(src=eep3.mac, dst="ff:ff:ff:ff:ff:ff") /
4822 psrc=eep3.ip4, pdst="10.0.0.128",
4823 hwsrc=eep3.mac, hwdst="ff:ff:ff:ff:ff:ff"))
4824 rxs = self.send_and_expect(self.pg0, p_arp * 1, self.pg0)
4827 # packets destined to unknown addresses in the BVI's subnet
4830 p4 = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
4832 IP(src="10.0.0.1", dst="10.0.0.88") /
4833 UDP(sport=1234, dport=1234) /
4835 p6 = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
4837 IPv6(src="2001:10::1", dst="2001:10::88") /
4838 UDP(sport=1234, dport=1234) /
4841 rxs = self.send_and_expect(self.pg0, p4 * 1, self.pg7)
4844 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4845 # self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4846 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4847 self.assertEqual(rx[IP].dst, "239.1.1.1")
4848 self.assertEqual(rx[VXLAN].vni, 88)
4849 self.assertTrue(rx[VXLAN].flags.G)
4850 self.assertTrue(rx[VXLAN].flags.Instance)
4851 # policy was applied to the original IP packet
4852 self.assertEqual(rx[VXLAN].gpid, 113)
4853 self.assertTrue(rx[VXLAN].gpflags.A)
4854 self.assertFalse(rx[VXLAN].gpflags.D)
4856 inner = rx[VXLAN].payload
4858 self.assertTrue(inner.haslayer(ARP))
4861 # remote to external
4863 p = (Ether(src=self.pg7.remote_mac,
4864 dst=self.pg7.local_mac) /
4865 IP(src=self.pg7.remote_ip4,
4866 dst=self.pg7.local_ip4) /
4867 UDP(sport=1234, dport=48879) /
4868 VXLAN(vni=444, gpid=113, flags=0x88) /
4869 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
4870 IP(src="10.0.0.101", dst="10.0.0.1") /
4871 UDP(sport=1234, dport=1234) /
4874 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
4877 # local EP pings router
4879 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
4881 IP(src=eep1.ip4, dst="10.0.0.128") /
4882 ICMP(type='echo-request'))
4884 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
4887 self.assertEqual(rx[Ether].src, str(self.router_mac))
4888 self.assertEqual(rx[Ether].dst, eep1.mac)
4889 self.assertEqual(rx[Dot1Q].vlan, 100)
4892 # local EP pings other local EP
4894 p = (Ether(src=eep1.mac, dst=eep2.mac) /
4896 IP(src=eep1.ip4, dst=eep2.ip4) /
4897 ICMP(type='echo-request'))
4899 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
4902 self.assertEqual(rx[Ether].src, eep1.mac)
4903 self.assertEqual(rx[Ether].dst, eep2.mac)
4904 self.assertEqual(rx[Dot1Q].vlan, 101)
4907 # local EP pings router w/o vlan tag poped
4909 p = (Ether(src=eep3.mac, dst=str(self.router_mac)) /
4911 IP(src=eep3.ip4, dst="10.0.0.128") /
4912 ICMP(type='echo-request'))
4914 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
4917 self.assertEqual(rx[Ether].src, str(self.router_mac))
4918 self.assertEqual(rx[Ether].dst, self.vlan_102.remote_mac)
4921 # A ip4 subnet reachable through the external EP1
4923 ip_220 = VppIpRoute(self, "10.220.0.0", 24,
4924 [VppRoutePath(eep1.ip4,
4925 eep1.epg.bvi.sw_if_index)],
4926 table_id=t4.table_id)
4927 ip_220.add_vpp_config()
4929 l3o_220 = VppGbpSubnet(
4930 self, rd1, "10.220.0.0", 24,
4931 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
4933 l3o_220.add_vpp_config()
4936 # An ip6 subnet reachable through the external EP1
4938 ip6_220 = VppIpRoute(self, "10:220::", 64,
4939 [VppRoutePath(eep1.ip6,
4940 eep1.epg.bvi.sw_if_index)],
4941 table_id=t6.table_id)
4942 ip6_220.add_vpp_config()
4944 l3o6_220 = VppGbpSubnet(
4945 self, rd1, "10:220::", 64,
4946 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
4948 l3o6_220.add_vpp_config()
4951 # A subnet reachable through the external EP2
4953 ip_221 = VppIpRoute(self, "10.221.0.0", 24,
4954 [VppRoutePath(eep2.ip4,
4955 eep2.epg.bvi.sw_if_index)],
4956 table_id=t4.table_id)
4957 ip_221.add_vpp_config()
4959 l3o_221 = VppGbpSubnet(
4960 self, rd1, "10.221.0.0", 24,
4961 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
4963 l3o_221.add_vpp_config()
4966 # ping between hosts in remote subnets
4967 # dropped without a contract
4969 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
4971 IP(src="10.220.0.1", dst="10.221.0.1") /
4972 ICMP(type='echo-request'))
4974 self.send_and_assert_no_replies(self.pg0, p * 1)
4977 # contract for the external nets to communicate
4979 rule4 = AclRule(is_permit=1, proto=17)
4980 rule6 = AclRule(src_prefix=IPv6Network((0, 0)),
4981 dst_prefix=IPv6Network((0, 0)), is_permit=1, proto=17)
4982 acl = VppAcl(self, rules=[rule4, rule6])
4983 acl.add_vpp_config()
4986 # A contract with the wrong scope is not matched
4988 c_44 = VppGbpContract(
4989 self, 44, 4220, 4221, acl.acl_index,
4990 [VppGbpContractRule(
4991 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4992 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4995 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4996 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4998 [ETH_P_IP, ETH_P_IPV6])
4999 c_44.add_vpp_config()
5000 self.send_and_assert_no_replies(self.pg0, p * 1)
5002 c1 = VppGbpContract(
5003 self, 55, 4220, 4221, acl.acl_index,
5004 [VppGbpContractRule(
5005 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5006 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5009 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5010 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5012 [ETH_P_IP, ETH_P_IPV6])
5016 # Contracts allowing ext-net 200 to talk with external EPs
5018 c2 = VppGbpContract(
5019 self, 55, 4220, 113, acl.acl_index,
5020 [VppGbpContractRule(
5021 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5022 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5025 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5026 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5028 [ETH_P_IP, ETH_P_IPV6])
5030 c3 = VppGbpContract(
5031 self, 55, 113, 4220, acl.acl_index,
5032 [VppGbpContractRule(
5033 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5034 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5037 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5038 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5040 [ETH_P_IP, ETH_P_IPV6])
5044 # ping between hosts in remote subnets
5046 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
5048 IP(src="10.220.0.1", dst="10.221.0.1") /
5049 UDP(sport=1234, dport=1234) /
5052 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
5055 self.assertEqual(rx[Ether].src, str(self.router_mac))
5056 self.assertEqual(rx[Ether].dst, eep2.mac)
5057 self.assertEqual(rx[Dot1Q].vlan, 101)
5059 # we did not learn these external hosts
5060 self.assertFalse(find_gbp_endpoint(self, ip="10.220.0.1"))
5061 self.assertFalse(find_gbp_endpoint(self, ip="10.221.0.1"))
5064 # from remote external EP to local external EP
5066 p = (Ether(src=self.pg7.remote_mac,
5067 dst=self.pg7.local_mac) /
5068 IP(src=self.pg7.remote_ip4,
5069 dst=self.pg7.local_ip4) /
5070 UDP(sport=1234, dport=48879) /
5071 VXLAN(vni=444, gpid=113, flags=0x88) /
5072 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
5073 IP(src="10.0.0.101", dst="10.220.0.1") /
5074 UDP(sport=1234, dport=1234) /
5077 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
5080 # ping from an external host to the remote external EP
5082 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
5084 IP(src="10.220.0.1", dst=rep.ip4) /
5085 UDP(sport=1234, dport=1234) /
5088 rxs = self.send_and_expect(self.pg0, p * 1, self.pg7)
5091 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
5092 # self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
5093 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
5094 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
5095 self.assertEqual(rx[VXLAN].vni, 444)
5096 self.assertTrue(rx[VXLAN].flags.G)
5097 self.assertTrue(rx[VXLAN].flags.Instance)
5098 # the sclass of the ext-net the packet came from
5099 self.assertEqual(rx[VXLAN].gpid, 4220)
5100 # policy was applied to the original IP packet
5101 self.assertTrue(rx[VXLAN].gpflags.A)
5102 # since it's an external host the reciever should not learn it
5103 self.assertTrue(rx[VXLAN].gpflags.D)
5104 inner = rx[VXLAN].payload
5105 self.assertEqual(inner[IP].src, "10.220.0.1")
5106 self.assertEqual(inner[IP].dst, rep.ip4)
5109 # An external subnet reachable via the remote external EP
5113 # first the VXLAN-GBP tunnel over which it is reached
5115 vx_tun_r1 = VppVxlanGbpTunnel(
5116 self, self.pg7.local_ip4,
5117 self.pg7.remote_ip4, 445,
5118 mode=(VppEnum.vl_api_vxlan_gbp_api_tunnel_mode_t.
5119 VXLAN_GBP_API_TUNNEL_MODE_L3))
5120 vx_tun_r1.add_vpp_config()
5121 VppIpInterfaceBind(self, vx_tun_r1, t4).add_vpp_config()
5123 self.logger.info(self.vapi.cli("sh vxlan-gbp tunnel"))
5126 # then the special adj to resolve through on that tunnel
5128 n1 = VppNeighbor(self,
5129 vx_tun_r1.sw_if_index,
5130 "00:0c:0c:0c:0c:0c",
5131 self.pg7.remote_ip4)
5135 # the route via the adj above
5137 ip_222 = VppIpRoute(self, "10.222.0.0", 24,
5138 [VppRoutePath(self.pg7.remote_ip4,
5139 vx_tun_r1.sw_if_index)],
5140 table_id=t4.table_id)
5141 ip_222.add_vpp_config()
5143 l3o_222 = VppGbpSubnet(
5144 self, rd1, "10.222.0.0", 24,
5145 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
5147 l3o_222.add_vpp_config()
5150 # ping between hosts in local and remote external subnets
5151 # dropped without a contract
5153 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
5155 IP(src="10.220.0.1", dst="10.222.0.1") /
5156 UDP(sport=1234, dport=1234) /
5159 rxs = self.send_and_assert_no_replies(self.pg0, p * 1)
5162 # Add contracts ext-nets for 220 -> 222
5164 c4 = VppGbpContract(
5165 self, 55, 4220, 4222, acl.acl_index,
5166 [VppGbpContractRule(
5167 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5168 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5171 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5172 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5174 [ETH_P_IP, ETH_P_IPV6])
5178 # ping from host in local to remote external subnets
5180 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
5182 IP(src="10.220.0.1", dst="10.222.0.1") /
5183 UDP(sport=1234, dport=1234) /
5186 rxs = self.send_and_expect(self.pg0, p * 3, self.pg7)
5189 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
5190 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
5191 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
5192 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
5193 self.assertEqual(rx[VXLAN].vni, 445)
5194 self.assertTrue(rx[VXLAN].flags.G)
5195 self.assertTrue(rx[VXLAN].flags.Instance)
5196 # the sclass of the ext-net the packet came from
5197 self.assertEqual(rx[VXLAN].gpid, 4220)
5198 # policy was applied to the original IP packet
5199 self.assertTrue(rx[VXLAN].gpflags.A)
5200 # since it's an external host the reciever should not learn it
5201 self.assertTrue(rx[VXLAN].gpflags.D)
5202 inner = rx[VXLAN].payload
5203 self.assertEqual(inner[Ether].dst, "00:0c:0c:0c:0c:0c")
5204 self.assertEqual(inner[IP].src, "10.220.0.1")
5205 self.assertEqual(inner[IP].dst, "10.222.0.1")
5208 # make the external subnet ECMP
5210 vx_tun_r2 = VppVxlanGbpTunnel(
5211 self, self.pg7.local_ip4,
5212 self.pg7.remote_ip4, 446,
5213 mode=(VppEnum.vl_api_vxlan_gbp_api_tunnel_mode_t.
5214 VXLAN_GBP_API_TUNNEL_MODE_L3))
5215 vx_tun_r2.add_vpp_config()
5216 VppIpInterfaceBind(self, vx_tun_r2, t4).add_vpp_config()
5218 self.logger.info(self.vapi.cli("sh vxlan-gbp tunnel"))
5220 n2 = VppNeighbor(self,
5221 vx_tun_r2.sw_if_index,
5222 "00:0c:0c:0c:0c:0c",
5223 self.pg7.remote_ip4)
5226 ip_222.modify([VppRoutePath(self.pg7.remote_ip4,
5227 vx_tun_r1.sw_if_index),
5228 VppRoutePath(self.pg7.remote_ip4,
5229 vx_tun_r2.sw_if_index)])
5232 # now expect load-balance
5234 p = [(Ether(src=eep1.mac, dst=str(self.router_mac)) /
5236 IP(src="10.220.0.1", dst="10.222.0.1") /
5237 UDP(sport=1234, dport=1234) /
5238 Raw(b'\xa5' * 100)),
5239 (Ether(src=eep1.mac, dst=str(self.router_mac)) /
5241 IP(src="10.220.0.1", dst="10.222.0.1") /
5242 UDP(sport=1222, dport=1235) /
5243 Raw(b'\xa5' * 100))]
5245 rxs = self.send_and_expect(self.pg0, p, self.pg7)
5247 self.assertEqual(rxs[0][VXLAN].vni, 445)
5248 self.assertEqual(rxs[1][VXLAN].vni, 446)
5251 # Same LB test for v6
5253 n3 = VppNeighbor(self,
5254 vx_tun_r1.sw_if_index,
5255 "00:0c:0c:0c:0c:0c",
5256 self.pg7.remote_ip6)
5258 n4 = VppNeighbor(self,
5259 vx_tun_r2.sw_if_index,
5260 "00:0c:0c:0c:0c:0c",
5261 self.pg7.remote_ip6)
5264 ip_222_6 = VppIpRoute(self, "10:222::", 64,
5265 [VppRoutePath(self.pg7.remote_ip6,
5266 vx_tun_r1.sw_if_index),
5267 VppRoutePath(self.pg7.remote_ip6,
5268 vx_tun_r2.sw_if_index)],
5269 table_id=t6.table_id)
5270 ip_222_6.add_vpp_config()
5272 l3o_222_6 = VppGbpSubnet(
5273 self, rd1, "10:222::", 64,
5274 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
5276 l3o_222_6.add_vpp_config()
5278 p = [(Ether(src=eep1.mac, dst=str(self.router_mac)) /
5280 IPv6(src="10:220::1", dst="10:222::1") /
5281 UDP(sport=1234, dport=1234) /
5282 Raw(b'\xa5' * 100)),
5283 (Ether(src=eep1.mac, dst=str(self.router_mac)) /
5285 IPv6(src="10:220::1", dst="10:222::1") /
5286 UDP(sport=7777, dport=8881) /
5287 Raw(b'\xa5' * 100))]
5289 self.logger.info(self.vapi.cli("sh ip6 fib 10:222::1"))
5290 rxs = self.send_and_expect(self.pg0, p, self.pg7)
5292 self.assertEqual(rxs[0][VXLAN].vni, 445)
5293 self.assertEqual(rxs[1][VXLAN].vni, 446)
5296 # ping from host in remote to local external subnets
5297 # there's no contract for this, but the A bit is set.
5299 p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
5300 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
5301 UDP(sport=1234, dport=48879) /
5302 VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
5303 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
5304 IP(src="10.222.0.1", dst="10.220.0.1") /
5305 UDP(sport=1234, dport=1234) /
5308 rxs = self.send_and_expect(self.pg7, p * 3, self.pg0)
5309 self.assertFalse(find_gbp_endpoint(self, ip="10.222.0.1"))
5312 # ping from host in remote to remote external subnets
5313 # this is dropped by reflection check.
5315 p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
5316 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
5317 UDP(sport=1234, dport=48879) /
5318 VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
5319 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
5320 IP(src="10.222.0.1", dst="10.222.0.2") /
5321 UDP(sport=1234, dport=1234) /
5324 rxs = self.send_and_assert_no_replies(self.pg7, p * 3)
5326 p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
5327 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
5328 UDP(sport=1234, dport=48879) /
5329 VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
5330 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
5331 IPv6(src="10:222::1", dst="10:222::2") /
5332 UDP(sport=1234, dport=1234) /
5335 rxs = self.send_and_assert_no_replies(self.pg7, p * 3)
5340 lep1 = VppGbpEndpoint(self, vlan_144,
5342 "10.0.0.44", "11.0.0.44",
5343 "2001:10::44", "3001::44")
5344 lep1.add_vpp_config()
5347 # local EP to local ip4 external subnet
5349 p = (Ether(src=lep1.mac, dst=str(self.router_mac)) /
5351 IP(src=lep1.ip4, dst="10.220.0.1") /
5352 UDP(sport=1234, dport=1234) /
5355 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
5358 self.assertEqual(rx[Ether].src, str(self.router_mac))
5359 self.assertEqual(rx[Ether].dst, eep1.mac)
5360 self.assertEqual(rx[Dot1Q].vlan, 100)
5363 # local EP to local ip6 external subnet
5365 p = (Ether(src=lep1.mac, dst=str(self.router_mac)) /
5367 IPv6(src=lep1.ip6, dst="10:220::1") /
5368 UDP(sport=1234, dport=1234) /
5371 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
5374 self.assertEqual(rx[Ether].src, str(self.router_mac))
5375 self.assertEqual(rx[Ether].dst, eep1.mac)
5376 self.assertEqual(rx[Dot1Q].vlan, 100)
5379 # ip4 and ip6 subnets that load-balance
5381 ip_20 = VppIpRoute(self, "10.20.0.0", 24,
5382 [VppRoutePath(eep1.ip4,
5383 eep1.epg.bvi.sw_if_index),
5384 VppRoutePath(eep2.ip4,
5385 eep2.epg.bvi.sw_if_index)],
5386 table_id=t4.table_id)
5387 ip_20.add_vpp_config()
5389 l3o_20 = VppGbpSubnet(
5390 self, rd1, "10.20.0.0", 24,
5391 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
5393 l3o_20.add_vpp_config()
5395 ip6_20 = VppIpRoute(self, "10:20::", 64,
5396 [VppRoutePath(eep1.ip6,
5397 eep1.epg.bvi.sw_if_index),
5398 VppRoutePath(eep2.ip6,
5399 eep2.epg.bvi.sw_if_index)],
5400 table_id=t6.table_id)
5401 ip6_20.add_vpp_config()
5403 l3o6_20 = VppGbpSubnet(
5404 self, rd1, "10:20::", 64,
5405 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
5407 l3o6_20.add_vpp_config()
5409 self.logger.info(self.vapi.cli("sh ip fib 10.20.0.1"))
5410 self.logger.info(self.vapi.cli("sh ip6 fib 10:20::1"))
5412 # two ip6 packets whose port are chosen so they load-balance
5413 p = [(Ether(src=lep1.mac, dst=str(self.router_mac)) /
5415 IPv6(src=lep1.ip6, dst="10:20::1") /
5416 UDP(sport=1234, dport=1234) /
5417 Raw(b'\xa5' * 100)),
5418 (Ether(src=lep1.mac, dst=str(self.router_mac)) /
5420 IPv6(src=lep1.ip6, dst="10:20::1") /
5421 UDP(sport=124, dport=1230) /
5422 Raw(b'\xa5' * 100))]
5424 rxs = self.send_and_expect(self.pg0, p, self.pg0, 2)
5426 self.assertEqual(rxs[0][Dot1Q].vlan, 101)
5427 self.assertEqual(rxs[1][Dot1Q].vlan, 100)
5429 # two ip4 packets whose port are chosen so they load-balance
5430 p = [(Ether(src=lep1.mac, dst=str(self.router_mac)) /
5432 IP(src=lep1.ip4, dst="10.20.0.1") /
5433 UDP(sport=1235, dport=1235) /
5434 Raw(b'\xa5' * 100)),
5435 (Ether(src=lep1.mac, dst=str(self.router_mac)) /
5437 IP(src=lep1.ip4, dst="10.20.0.1") /
5438 UDP(sport=124, dport=1230) /
5439 Raw(b'\xa5' * 100))]
5441 rxs = self.send_and_expect(self.pg0, p, self.pg0, 2)
5443 self.assertEqual(rxs[0][Dot1Q].vlan, 101)
5444 self.assertEqual(rxs[1][Dot1Q].vlan, 100)
5449 ip_222.remove_vpp_config()
5450 self.pg7.unconfig_ip4()
5451 self.vlan_101.set_vtr(L2_VTR_OP.L2_DISABLED)
5452 self.vlan_100.set_vtr(L2_VTR_OP.L2_DISABLED)
5454 def test_gbp_anon_l3_out(self):
5455 """ GBP Anonymous L3 Out """
5457 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
5458 self.vapi.cli("set logging class gbp level debug")
5460 routed_dst_mac = "00:0c:0c:0c:0c:0c"
5461 routed_src_mac = "00:22:bd:f8:19:ff"
5466 t4 = VppIpTable(self, 1)
5468 t6 = VppIpTable(self, 1, True)
5471 rd1 = VppGbpRouteDomain(self, 2, 55, t4, t6)
5472 rd1.add_vpp_config()
5474 self.loop0.set_mac(self.router_mac)
5477 # Bind the BVI to the RD
5479 bind_l0_ip4 = VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
5480 bind_l0_ip6 = VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
5483 # Pg7 hosts a BD's BUM
5484 # Pg1 some other l3 interface
5486 self.pg7.config_ip4()
5487 self.pg7.resolve_arp()
5490 # a GBP external bridge domains for the EPs
5492 bd1 = VppBridgeDomain(self, 1)
5493 bd1.add_vpp_config()
5494 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0, None, None)
5495 gbd1.add_vpp_config()
5498 # The Endpoint-groups in which the external endpoints exist
5500 epg_220 = VppGbpEndpointGroup(self, 220, 113, rd1, gbd1,
5504 VppGbpEndpointRetention(4))
5505 epg_220.add_vpp_config()
5507 # the BVIs have the subnet applied ...
5508 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi,
5510 bind=bind_l0_ip4).add_vpp_config()
5512 # ... which is an Anonymous L3-out subnets
5513 l3o_1 = VppGbpSubnet(
5514 self, rd1, "10.0.0.0", 24,
5515 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_ANON_L3_OUT,
5517 l3o_1.add_vpp_config()
5520 # an external interface attached to the outside world and the
5523 VppL2Vtr(self, self.vlan_100, L2_VTR_OP.L2_POP_1).add_vpp_config()
5524 VppL2Vtr(self, self.vlan_101, L2_VTR_OP.L2_POP_1).add_vpp_config()
5527 # vlan_100 and vlan_101 are anonymous l3-out interfaces
5529 ext_itf = VppGbpExtItf(self, self.vlan_100, bd1, rd1, anon=True)
5530 ext_itf.add_vpp_config()
5531 ext_itf = VppGbpExtItf(self, self.vlan_101, bd1, rd1, anon=True)
5532 ext_itf.add_vpp_config()
5535 # an unicast vxlan-gbp for inter-RD traffic
5537 vx_tun_l3 = VppGbpVxlanTunnel(
5538 self, 444, rd1.rd_id,
5539 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
5541 vx_tun_l3.add_vpp_config()
5544 # A remote external endpoint
5546 rep = VppGbpEndpoint(self, vx_tun_l3,
5548 "10.0.0.201", "11.0.0.201",
5549 "2001:10::201", "3001::101",
5550 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
5552 self.pg7.remote_ip4,
5554 rep.add_vpp_config()
5557 # ARP packet from host in external subnet are accepted, flooded and
5558 # replied to. We expect 2 packets:
5559 # - APR request flooded over the other vlan subif
5560 # - ARP reply from BVI
5562 p_arp = (Ether(src=self.vlan_100.remote_mac,
5563 dst="ff:ff:ff:ff:ff:ff") /
5568 hwsrc=self.vlan_100.remote_mac,
5569 hwdst="ff:ff:ff:ff:ff:ff"))
5570 rxs = self.send_and_expect(self.pg0, p_arp * 1, self.pg0, n_rx=2)
5572 p_arp = (Ether(src=self.vlan_101.remote_mac,
5573 dst="ff:ff:ff:ff:ff:ff") /
5578 hwsrc=self.vlan_101.remote_mac,
5579 hwdst="ff:ff:ff:ff:ff:ff"))
5580 rxs = self.send_and_expect(self.pg0, p_arp * 1, self.pg0, n_rx=2)
5583 # remote to external
5585 p = (Ether(src=self.pg7.remote_mac,
5586 dst=self.pg7.local_mac) /
5587 IP(src=self.pg7.remote_ip4,
5588 dst=self.pg7.local_ip4) /
5589 UDP(sport=1234, dport=48879) /
5590 VXLAN(vni=vx_tun_l3.vni, gpid=epg_220.sclass, flags=0x88) /
5591 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
5592 IP(src=str(rep.ip4), dst="10.0.0.100") /
5593 UDP(sport=1234, dport=1234) /
5595 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
5598 # local EP pings router
5600 p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
5602 IP(src="10.0.0.100", dst="10.0.0.128") /
5603 ICMP(type='echo-request'))
5604 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
5607 self.assertEqual(rx[Ether].src, str(self.router_mac))
5608 self.assertEqual(rx[Ether].dst, self.vlan_100.remote_mac)
5609 self.assertEqual(rx[Dot1Q].vlan, 100)
5612 # local EP pings other local EP
5614 p = (Ether(src=self.vlan_100.remote_mac,
5615 dst=self.vlan_101.remote_mac) /
5617 IP(src="10.0.0.100", dst="10.0.0.101") /
5618 ICMP(type='echo-request'))
5619 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
5622 self.assertEqual(rx[Ether].src, self.vlan_100.remote_mac)
5623 self.assertEqual(rx[Ether].dst, self.vlan_101.remote_mac)
5624 self.assertEqual(rx[Dot1Q].vlan, 101)
5627 # A subnet reachable through an external router on vlan 100
5629 ip_220 = VppIpRoute(self, "10.220.0.0", 24,
5630 [VppRoutePath("10.0.0.100",
5631 epg_220.bvi.sw_if_index)],
5632 table_id=t4.table_id)
5633 ip_220.add_vpp_config()
5635 l3o_220 = VppGbpSubnet(
5636 self, rd1, "10.220.0.0", 24,
5637 # note: this a "regular" L3 out subnet (not connected)
5638 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
5640 l3o_220.add_vpp_config()
5643 # A subnet reachable through an external router on vlan 101
5645 ip_221 = VppIpRoute(self, "10.221.0.0", 24,
5646 [VppRoutePath("10.0.0.101",
5647 epg_220.bvi.sw_if_index)],
5648 table_id=t4.table_id)
5649 ip_221.add_vpp_config()
5651 l3o_221 = VppGbpSubnet(
5652 self, rd1, "10.221.0.0", 24,
5653 # note: this a "regular" L3 out subnet (not connected)
5654 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
5656 l3o_221.add_vpp_config()
5659 # ping between hosts in remote subnets
5660 # dropped without a contract
5662 p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
5664 IP(src="10.220.0.1", dst="10.221.0.1") /
5665 ICMP(type='echo-request'))
5667 rxs = self.send_and_assert_no_replies(self.pg0, p * 1)
5670 # contract for the external nets to communicate
5672 rule4 = AclRule(is_permit=1, proto=17)
5673 rule6 = AclRule(src_prefix=IPv6Network((0, 0)),
5674 dst_prefix=IPv6Network((0, 0)), is_permit=1, proto=17)
5675 acl = VppAcl(self, rules=[rule4, rule6])
5676 acl.add_vpp_config()
5678 c1 = VppGbpContract(
5679 self, 55, 4220, 4221, acl.acl_index,
5680 [VppGbpContractRule(
5681 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5682 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5685 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5686 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5688 [ETH_P_IP, ETH_P_IPV6])
5692 # Contracts allowing ext-net 200 to talk with external EPs
5694 c2 = VppGbpContract(
5695 self, 55, 4220, 113, acl.acl_index,
5696 [VppGbpContractRule(
5697 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5698 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5701 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5702 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5704 [ETH_P_IP, ETH_P_IPV6])
5706 c3 = VppGbpContract(
5707 self, 55, 113, 4220, acl.acl_index,
5708 [VppGbpContractRule(
5709 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5710 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5713 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5714 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5716 [ETH_P_IP, ETH_P_IPV6])
5720 # ping between hosts in remote subnets
5722 p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
5724 IP(src="10.220.0.1", dst="10.221.0.1") /
5725 UDP(sport=1234, dport=1234) /
5728 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
5731 self.assertEqual(rx[Ether].src, str(self.router_mac))
5732 self.assertEqual(rx[Ether].dst, self.vlan_101.remote_mac)
5733 self.assertEqual(rx[Dot1Q].vlan, 101)
5735 # we did not learn these external hosts
5736 self.assertFalse(find_gbp_endpoint(self, ip="10.220.0.1"))
5737 self.assertFalse(find_gbp_endpoint(self, ip="10.221.0.1"))
5740 # from remote external EP to local external EP
5742 p = (Ether(src=self.pg7.remote_mac,
5743 dst=self.pg7.local_mac) /
5744 IP(src=self.pg7.remote_ip4,
5745 dst=self.pg7.local_ip4) /
5746 UDP(sport=1234, dport=48879) /
5747 VXLAN(vni=444, gpid=113, flags=0x88) /
5748 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
5749 IP(src=rep.ip4, dst="10.220.0.1") /
5750 UDP(sport=1234, dport=1234) /
5753 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
5756 # ping from an external host to the remote external EP
5758 p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
5760 IP(src="10.220.0.1", dst=rep.ip4) /
5761 UDP(sport=1234, dport=1234) /
5764 rxs = self.send_and_expect(self.pg0, p * 1, self.pg7)
5767 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
5768 # self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
5769 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
5770 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
5771 self.assertEqual(rx[VXLAN].vni, 444)
5772 self.assertTrue(rx[VXLAN].flags.G)
5773 self.assertTrue(rx[VXLAN].flags.Instance)
5774 # the sclass of the ext-net the packet came from
5775 self.assertEqual(rx[VXLAN].gpid, 4220)
5776 # policy was applied to the original IP packet
5777 self.assertTrue(rx[VXLAN].gpflags.A)
5778 # since it's an external host the reciever should not learn it
5779 self.assertTrue(rx[VXLAN].gpflags.D)
5780 inner = rx[VXLAN].payload
5781 self.assertEqual(inner[IP].src, "10.220.0.1")
5782 self.assertEqual(inner[IP].dst, rep.ip4)
5785 # An external subnet reachable via the remote external EP
5789 # first the VXLAN-GBP tunnel over which it is reached
5791 vx_tun_r = VppVxlanGbpTunnel(
5792 self, self.pg7.local_ip4,
5793 self.pg7.remote_ip4, 445,
5794 mode=(VppEnum.vl_api_vxlan_gbp_api_tunnel_mode_t.
5795 VXLAN_GBP_API_TUNNEL_MODE_L3))
5796 vx_tun_r.add_vpp_config()
5797 VppIpInterfaceBind(self, vx_tun_r, t4).add_vpp_config()
5799 self.logger.info(self.vapi.cli("sh vxlan-gbp tunnel"))
5802 # then the special adj to resolve through on that tunnel
5804 n1 = VppNeighbor(self,
5805 vx_tun_r.sw_if_index,
5806 "00:0c:0c:0c:0c:0c",
5807 self.pg7.remote_ip4)
5811 # the route via the adj above
5813 ip_222 = VppIpRoute(self, "10.222.0.0", 24,
5814 [VppRoutePath(self.pg7.remote_ip4,
5815 vx_tun_r.sw_if_index)],
5816 table_id=t4.table_id)
5817 ip_222.add_vpp_config()
5819 l3o_222 = VppGbpSubnet(
5820 self, rd1, "10.222.0.0", 24,
5821 # note: this a "regular" l3out subnet (not connected)
5822 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
5824 l3o_222.add_vpp_config()
5827 # ping between hosts in local and remote external subnets
5828 # dropped without a contract
5830 p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
5832 IP(src="10.220.0.1", dst="10.222.0.1") /
5833 UDP(sport=1234, dport=1234) /
5836 rxs = self.send_and_assert_no_replies(self.pg0, p * 1)
5839 # Add contracts ext-nets for 220 -> 222
5841 c4 = VppGbpContract(
5842 self, 55, 4220, 4222, acl.acl_index,
5843 [VppGbpContractRule(
5844 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5845 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5848 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5849 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5851 [ETH_P_IP, ETH_P_IPV6])
5855 # ping from host in local to remote external subnets
5857 p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
5859 IP(src="10.220.0.1", dst="10.222.0.1") /
5860 UDP(sport=1234, dport=1234) /
5863 rxs = self.send_and_expect(self.pg0, p * 3, self.pg7)
5866 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
5867 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
5868 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
5869 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
5870 self.assertEqual(rx[VXLAN].vni, 445)
5871 self.assertTrue(rx[VXLAN].flags.G)
5872 self.assertTrue(rx[VXLAN].flags.Instance)
5873 # the sclass of the ext-net the packet came from
5874 self.assertEqual(rx[VXLAN].gpid, 4220)
5875 # policy was applied to the original IP packet
5876 self.assertTrue(rx[VXLAN].gpflags.A)
5877 # since it's an external host the reciever should not learn it
5878 self.assertTrue(rx[VXLAN].gpflags.D)
5879 inner = rx[VXLAN].payload
5880 self.assertEqual(inner[Ether].dst, "00:0c:0c:0c:0c:0c")
5881 self.assertEqual(inner[IP].src, "10.220.0.1")
5882 self.assertEqual(inner[IP].dst, "10.222.0.1")
5885 # ping from host in remote to local external subnets
5886 # there's no contract for this, but the A bit is set.
5888 p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
5889 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
5890 UDP(sport=1234, dport=48879) /
5891 VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
5892 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
5893 IP(src="10.222.0.1", dst="10.220.0.1") /
5894 UDP(sport=1234, dport=1234) /
5897 rxs = self.send_and_expect(self.pg7, p * 3, self.pg0)
5898 self.assertFalse(find_gbp_endpoint(self, ip="10.222.0.1"))
5901 # ping from host in remote to remote external subnets
5902 # this is dropped by reflection check.
5904 p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
5905 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
5906 UDP(sport=1234, dport=48879) /
5907 VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
5908 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
5909 IP(src="10.222.0.1", dst="10.222.0.2") /
5910 UDP(sport=1234, dport=1234) /
5913 rxs = self.send_and_assert_no_replies(self.pg7, p * 3)
5918 self.vlan_101.set_vtr(L2_VTR_OP.L2_DISABLED)
5919 self.vlan_100.set_vtr(L2_VTR_OP.L2_DISABLED)
5920 self.pg7.unconfig_ip4()
5921 # make sure the programmed EP is no longer learnt from DP
5922 self.wait_for_ep_timeout(sw_if_index=rep.itf.sw_if_index, ip=rep.ip4)
5925 if __name__ == '__main__':
5926 unittest.main(testRunner=VppTestRunner)