5 from framework import VppTestCase, VppTestRunner, is_skip_aarch64_set, \
7 from vpp_object import VppObject
8 from vpp_neighbor import VppNeighbor
9 from vpp_ip_route import VppIpRoute, VppRoutePath, VppIpTable, \
10 VppIpInterfaceAddress, VppIpInterfaceBind, find_route
11 from vpp_l2 import VppBridgeDomain, VppBridgeDomainPort, \
12 VppBridgeDomainArpEntry, VppL2FibEntry, find_bridge_domain_port
13 from vpp_vxlan_gbp_tunnel import *
14 from vpp_sub_interface import VppDot1QSubint
17 from vpp_papi_provider import L2_PORT_TYPE
18 from vpp_papi import VppEnum, MACAddress
20 from scapy.packet import Raw
21 from scapy.layers.l2 import Ether, ARP, Dot1Q
22 from scapy.layers.inet import IP, UDP
23 from scapy.layers.inet6 import IPv6, ICMPv6ND_NS, ICMPv6NDOptSrcLLAddr, \
25 from scapy.utils6 import in6_getnsma, in6_getnsmac
26 from scapy.layers.vxlan import VXLAN
28 from socket import AF_INET, AF_INET6
29 from scapy.utils import inet_pton, inet_ntop
30 from vpp_papi_provider import L2_VTR_OP
33 def find_gbp_endpoint(test, sw_if_index=None, ip=None, mac=None):
35 vip = VppIpAddress(ip)
37 vmac = MACAddress(mac)
39 eps = test.vapi.gbp_endpoint_dump()
43 if ep.endpoint.sw_if_index != sw_if_index:
46 for eip in ep.endpoint.ips:
50 if vmac.packed == ep.endpoint.mac:
55 def find_gbp_vxlan(test, vni):
56 ts = test.vapi.gbp_vxlan_tunnel_dump()
58 if t.tunnel.vni == vni:
63 class VppGbpEndpoint(VppObject):
74 return self.itf.remote_mac
94 return [self.ip4, self.ip6]
98 return [self.fip4, self.fip6]
100 def __init__(self, test, itf, epg, recirc, ip4, fip4, ip6, fip6,
110 self._ip4 = VppIpAddress(ip4)
111 self._fip4 = VppIpAddress(fip4)
112 self._ip6 = VppIpAddress(ip6)
113 self._fip6 = VppIpAddress(fip6)
116 self.vmac = MACAddress(self.itf.remote_mac)
118 self.vmac = MACAddress("00:00:00:00:00:00")
121 self.tun_src = VppIpAddress(tun_src)
122 self.tun_dst = VppIpAddress(tun_dst)
124 def add_vpp_config(self):
125 res = self._test.vapi.gbp_endpoint_add(
126 self.itf.sw_if_index,
127 [self.ip4.encode(), self.ip6.encode()],
131 self.tun_src.encode(),
132 self.tun_dst.encode())
133 self.handle = res.handle
134 self._test.registry.register(self, self._test.logger)
136 def remove_vpp_config(self):
137 self._test.vapi.gbp_endpoint_del(self.handle)
140 return self.object_id()
143 return "gbp-endpoint:[%d==%d:%s:%d]" % (self.handle,
144 self.itf.sw_if_index,
148 def query_vpp_config(self):
149 return find_gbp_endpoint(self._test,
150 self.itf.sw_if_index,
154 class VppGbpRecirc(VppObject):
156 GBP Recirculation Interface
159 def __init__(self, test, epg, recirc, is_ext=False):
165 def add_vpp_config(self):
166 self._test.vapi.gbp_recirc_add_del(
168 self.recirc.sw_if_index,
171 self._test.registry.register(self, self._test.logger)
173 def remove_vpp_config(self):
174 self._test.vapi.gbp_recirc_add_del(
176 self.recirc.sw_if_index,
181 return self.object_id()
184 return "gbp-recirc:[%d]" % (self.recirc.sw_if_index)
186 def query_vpp_config(self):
187 rs = self._test.vapi.gbp_recirc_dump()
189 if r.recirc.sw_if_index == self.recirc.sw_if_index:
194 class VppGbpExtItf(VppObject):
196 GBP ExtItfulation Interface
199 def __init__(self, test, itf, bd, rd):
205 def add_vpp_config(self):
206 self._test.vapi.gbp_ext_itf_add_del(
208 self.itf.sw_if_index,
211 self._test.registry.register(self, self._test.logger)
213 def remove_vpp_config(self):
214 self._test.vapi.gbp_ext_itf_add_del(
216 self.itf.sw_if_index,
221 return self.object_id()
224 return "gbp-ext-itf:[%d]" % (self.itf.sw_if_index)
226 def query_vpp_config(self):
227 rs = self._test.vapi.gbp_ext_itf_dump()
229 if r.ext_itf.sw_if_index == self.itf.sw_if_index:
234 class VppGbpSubnet(VppObject):
238 def __init__(self, test, rd, address, address_len,
239 type, sw_if_index=None, epg=None):
241 self.rd_id = rd.rd_id
242 self.prefix = VppIpPrefix(address, address_len)
244 self.sw_if_index = sw_if_index
247 def add_vpp_config(self):
248 self._test.vapi.gbp_subnet_add_del(
251 self.prefix.encode(),
253 sw_if_index=self.sw_if_index if self.sw_if_index else 0xffffffff,
254 epg_id=self.epg if self.epg else 0xffff)
255 self._test.registry.register(self, self._test.logger)
257 def remove_vpp_config(self):
258 self._test.vapi.gbp_subnet_add_del(
261 self.prefix.encode(),
265 return self.object_id()
268 return "gbp-subnet:[%d-%s]" % (self.rd_id, self.prefix)
270 def query_vpp_config(self):
271 ss = self._test.vapi.gbp_subnet_dump()
273 if s.subnet.rd_id == self.rd_id and \
274 s.subnet.type == self.type and \
275 s.subnet.prefix == self.prefix:
280 class VppGbpEndpointGroup(VppObject):
285 def __init__(self, test, epg, rd, bd, uplink,
286 bvi, bvi_ip4, bvi_ip6=None):
290 self.bvi_ip4 = VppIpAddress(bvi_ip4)
291 self.bvi_ip6 = VppIpAddress(bvi_ip6)
296 def add_vpp_config(self):
297 self._test.vapi.gbp_endpoint_group_add(
301 self.uplink.sw_if_index if self.uplink else INDEX_INVALID)
302 self._test.registry.register(self, self._test.logger)
304 def remove_vpp_config(self):
305 self._test.vapi.gbp_endpoint_group_del(
309 return self.object_id()
312 return "gbp-endpoint-group:[%d]" % (self.epg)
314 def query_vpp_config(self):
315 epgs = self._test.vapi.gbp_endpoint_group_dump()
317 if epg.epg.epg_id == self.epg:
322 class VppGbpBridgeDomain(VppObject):
327 def __init__(self, test, bd, bvi, uu_flood=None, learn=True):
330 self.uu_flood = uu_flood
333 e = VppEnum.vl_api_gbp_bridge_domain_flags_t
335 self.learn = e.GBP_BD_API_FLAG_NONE
337 self.learn = e.GBP_BD_API_FLAG_DO_NOT_LEARN
339 def add_vpp_config(self):
340 self._test.vapi.gbp_bridge_domain_add(
343 self.bvi.sw_if_index,
344 self.uu_flood.sw_if_index if self.uu_flood else INDEX_INVALID)
345 self._test.registry.register(self, self._test.logger)
347 def remove_vpp_config(self):
348 self._test.vapi.gbp_bridge_domain_del(self.bd.bd_id)
351 return self.object_id()
354 return "gbp-bridge-domain:[%d]" % (self.bd.bd_id)
356 def query_vpp_config(self):
357 bds = self._test.vapi.gbp_bridge_domain_dump()
359 if bd.bd.bd_id == self.bd.bd_id:
364 class VppGbpRouteDomain(VppObject):
369 def __init__(self, test, rd_id, t4, t6, ip4_uu=None, ip6_uu=None):
377 def add_vpp_config(self):
378 self._test.vapi.gbp_route_domain_add(
382 self.ip4_uu.sw_if_index if self.ip4_uu else INDEX_INVALID,
383 self.ip6_uu.sw_if_index if self.ip6_uu else INDEX_INVALID)
384 self._test.registry.register(self, self._test.logger)
386 def remove_vpp_config(self):
387 self._test.vapi.gbp_route_domain_del(self.rd_id)
390 return self.object_id()
393 return "gbp-route-domain:[%d]" % (self.rd_id)
395 def query_vpp_config(self):
396 rds = self._test.vapi.gbp_route_domain_dump()
398 if rd.rd.rd_id == self.rd_id:
403 class VppGbpContractNextHop():
404 def __init__(self, mac, bd, ip, rd):
411 return {'ip': self.ip.encode(),
412 'mac': self.mac.packed,
413 'bd_id': self.bd.bd.bd_id,
414 'rd_id': self.rd.rd_id}
417 class VppGbpContractRule():
418 def __init__(self, action, hash_mode, nhs=[]):
420 self.hash_mode = hash_mode
426 nhs.append(nh.encode())
429 return {'action': self.action,
431 'hash_mode': self.hash_mode,
432 'n_nhs': len(self.nhs),
436 class VppGbpContract(VppObject):
441 def __init__(self, test, src_epg, dst_epg, acl_index, rules=[]):
443 self.acl_index = acl_index
444 self.src_epg = src_epg
445 self.dst_epg = dst_epg
448 def add_vpp_config(self):
451 rules.append(r.encode())
452 self._test.vapi.gbp_contract_add_del(
458 self._test.registry.register(self, self._test.logger)
460 def remove_vpp_config(self):
461 self._test.vapi.gbp_contract_add_del(
469 return self.object_id()
472 return "gbp-contract:[%d:%s:%d]" % (self.src_epg,
476 def query_vpp_config(self):
477 cs = self._test.vapi.gbp_contract_dump()
479 if c.contract.src_epg == self.src_epg \
480 and c.contract.dst_epg == self.dst_epg:
485 class VppGbpVxlanTunnel(VppInterface):
490 def __init__(self, test, vni, bd_rd_id, mode):
491 super(VppGbpVxlanTunnel, self).__init__(test)
494 self.bd_rd_id = bd_rd_id
497 def add_vpp_config(self):
498 r = self._test.vapi.gbp_vxlan_tunnel_add(
502 self.set_sw_if_index(r.sw_if_index)
503 self._test.registry.register(self, self._test.logger)
505 def remove_vpp_config(self):
506 self._test.vapi.gbp_vxlan_tunnel_del(self.vni)
509 return self.object_id()
512 return "gbp-vxlan:%d" % (self.vni)
514 def query_vpp_config(self):
515 return find_gbp_vxlan(self._test, self.vni)
518 class VppGbpAcl(VppObject):
523 def __init__(self, test):
525 self.acl_index = 4294967295
527 def create_rule(self, is_ipv6=0, permit_deny=0, proto=-1,
528 s_prefix=0, s_ip='\x00\x00\x00\x00', sport_from=0,
529 sport_to=65535, d_prefix=0, d_ip='\x00\x00\x00\x00',
530 dport_from=0, dport_to=65535):
531 if proto == -1 or proto == 0:
534 elif proto == 1 or proto == 58:
537 rule = ({'is_permit': permit_deny, 'is_ipv6': is_ipv6, 'proto': proto,
538 'srcport_or_icmptype_first': sport_from,
539 'srcport_or_icmptype_last': sport_to,
540 'src_ip_prefix_len': s_prefix,
542 'dstport_or_icmpcode_first': dport_from,
543 'dstport_or_icmpcode_last': dport_to,
544 'dst_ip_prefix_len': d_prefix,
545 'dst_ip_addr': d_ip})
548 def add_vpp_config(self, rules):
550 reply = self._test.vapi.acl_add_replace(self.acl_index,
553 self.acl_index = reply.acl_index
554 return self.acl_index
556 def remove_vpp_config(self):
557 self._test.vapi.acl_del(self.acl_index)
560 return self.object_id()
563 return "gbp-acl:[%d]" % (self.acl_index)
565 def query_vpp_config(self):
566 cs = self._test.vapi.acl_dump()
568 if c.acl_index == self.acl_index:
573 class TestGBP(VppTestCase):
574 """ GBP Test Case """
577 super(TestGBP, self).setUp()
579 self.create_pg_interfaces(range(9))
580 self.create_loopback_interfaces(8)
582 self.router_mac = MACAddress("00:11:22:33:44:55")
584 for i in self.pg_interfaces:
586 for i in self.lo_interfaces:
590 for i in self.pg_interfaces:
593 super(TestGBP, self).tearDown()
595 def send_and_expect_bridged(self, src, tx, dst):
596 rx = self.send_and_expect(src, tx, dst)
599 self.assertEqual(r[Ether].src, tx[0][Ether].src)
600 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
601 self.assertEqual(r[IP].src, tx[0][IP].src)
602 self.assertEqual(r[IP].dst, tx[0][IP].dst)
605 def send_and_expect_bridged6(self, src, tx, dst):
606 rx = self.send_and_expect(src, tx, dst)
609 self.assertEqual(r[Ether].src, tx[0][Ether].src)
610 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
611 self.assertEqual(r[IPv6].src, tx[0][IPv6].src)
612 self.assertEqual(r[IPv6].dst, tx[0][IPv6].dst)
615 def send_and_expect_routed(self, src, tx, dst, src_mac):
616 rx = self.send_and_expect(src, tx, dst)
619 self.assertEqual(r[Ether].src, src_mac)
620 self.assertEqual(r[Ether].dst, dst.remote_mac)
621 self.assertEqual(r[IP].src, tx[0][IP].src)
622 self.assertEqual(r[IP].dst, tx[0][IP].dst)
625 def send_and_expect_natted(self, src, tx, dst, src_ip):
626 rx = self.send_and_expect(src, tx, dst)
629 self.assertEqual(r[Ether].src, tx[0][Ether].src)
630 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
631 self.assertEqual(r[IP].src, src_ip)
632 self.assertEqual(r[IP].dst, tx[0][IP].dst)
635 def send_and_expect_natted6(self, src, tx, dst, src_ip):
636 rx = self.send_and_expect(src, tx, dst)
639 self.assertEqual(r[Ether].src, tx[0][Ether].src)
640 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
641 self.assertEqual(r[IPv6].src, src_ip)
642 self.assertEqual(r[IPv6].dst, tx[0][IPv6].dst)
645 def send_and_expect_unnatted(self, src, tx, dst, dst_ip):
646 rx = self.send_and_expect(src, tx, dst)
649 self.assertEqual(r[Ether].src, tx[0][Ether].src)
650 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
651 self.assertEqual(r[IP].dst, dst_ip)
652 self.assertEqual(r[IP].src, tx[0][IP].src)
655 def send_and_expect_unnatted6(self, src, tx, dst, dst_ip):
656 rx = self.send_and_expect(src, tx, dst)
659 self.assertEqual(r[Ether].src, tx[0][Ether].src)
660 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
661 self.assertEqual(r[IPv6].dst, dst_ip)
662 self.assertEqual(r[IPv6].src, tx[0][IPv6].src)
665 def send_and_expect_double_natted(self, src, tx, dst, src_ip, dst_ip):
666 rx = self.send_and_expect(src, tx, dst)
669 self.assertEqual(r[Ether].src, str(self.router_mac))
670 self.assertEqual(r[Ether].dst, dst.remote_mac)
671 self.assertEqual(r[IP].dst, dst_ip)
672 self.assertEqual(r[IP].src, src_ip)
675 def send_and_expect_double_natted6(self, src, tx, dst, src_ip, dst_ip):
676 rx = self.send_and_expect(src, tx, dst)
679 self.assertEqual(r[Ether].src, str(self.router_mac))
680 self.assertEqual(r[Ether].dst, dst.remote_mac)
681 self.assertEqual(r[IPv6].dst, dst_ip)
682 self.assertEqual(r[IPv6].src, src_ip)
686 """ Group Based Policy """
688 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
693 bd1 = VppBridgeDomain(self, 1)
694 bd2 = VppBridgeDomain(self, 2)
695 bd20 = VppBridgeDomain(self, 20)
699 bd20.add_vpp_config()
701 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0)
702 gbd2 = VppGbpBridgeDomain(self, bd2, self.loop1)
703 gbd20 = VppGbpBridgeDomain(self, bd20, self.loop2)
705 gbd1.add_vpp_config()
706 gbd2.add_vpp_config()
707 gbd20.add_vpp_config()
712 gt4 = VppIpTable(self, 0)
714 gt6 = VppIpTable(self, 0, is_ip6=True)
716 nt4 = VppIpTable(self, 20)
718 nt6 = VppIpTable(self, 20, is_ip6=True)
721 rd0 = VppGbpRouteDomain(self, 0, gt4, gt6, None, None)
722 rd20 = VppGbpRouteDomain(self, 20, nt4, nt6, None, None)
725 rd20.add_vpp_config()
728 # 3 EPGs, 2 of which share a BD.
729 # 2 NAT EPGs, one for floating-IP subnets, the other for internet
731 epgs = [VppGbpEndpointGroup(self, 220, rd0, gbd1, self.pg4,
735 VppGbpEndpointGroup(self, 221, rd0, gbd1, self.pg5,
739 VppGbpEndpointGroup(self, 222, rd0, gbd2, self.pg6,
743 VppGbpEndpointGroup(self, 333, rd20, gbd20, self.pg7,
747 VppGbpEndpointGroup(self, 444, rd20, gbd20, self.pg8,
751 recircs = [VppGbpRecirc(self, epgs[0],
753 VppGbpRecirc(self, epgs[1],
755 VppGbpRecirc(self, epgs[2],
757 VppGbpRecirc(self, epgs[3],
758 self.loop6, is_ext=True),
759 VppGbpRecirc(self, epgs[4],
760 self.loop7, is_ext=True)]
763 recirc_nat = recircs[3]
766 # 4 end-points, 2 in the same subnet, 3 in the same BD
768 eps = [VppGbpEndpoint(self, self.pg0,
770 "10.0.0.1", "11.0.0.1",
771 "2001:10::1", "3001::1"),
772 VppGbpEndpoint(self, self.pg1,
774 "10.0.0.2", "11.0.0.2",
775 "2001:10::2", "3001::2"),
776 VppGbpEndpoint(self, self.pg2,
778 "10.0.1.1", "11.0.0.3",
779 "2001:10:1::1", "3001::3"),
780 VppGbpEndpoint(self, self.pg3,
782 "10.0.2.1", "11.0.0.4",
783 "2001:10:2::1", "3001::4")]
786 # Config related to each of the EPGs
789 # IP config on the BVI interfaces
790 if epg != epgs[1] and epg != epgs[4]:
791 VppIpInterfaceBind(self, epg.bvi, epg.rd.t4).add_vpp_config()
792 VppIpInterfaceBind(self, epg.bvi, epg.rd.t6).add_vpp_config()
793 self.vapi.sw_interface_set_mac_address(
795 self.router_mac.packed)
797 # The BVIs are NAT inside interfaces
798 self.vapi.nat44_interface_add_del_feature(epg.bvi.sw_if_index,
801 self.vapi.nat66_add_del_interface(epg.bvi.sw_if_index,
805 if_ip4 = VppIpInterfaceAddress(self, epg.bvi, epg.bvi_ip4, 32)
806 if_ip6 = VppIpInterfaceAddress(self, epg.bvi, epg.bvi_ip6, 128)
807 if_ip4.add_vpp_config()
808 if_ip6.add_vpp_config()
810 # EPG uplink interfaces in the RD
811 VppIpInterfaceBind(self, epg.uplink, epg.rd.t4).add_vpp_config()
812 VppIpInterfaceBind(self, epg.uplink, epg.rd.t6).add_vpp_config()
814 # add the BD ARP termination entry for BVI IP
815 epg.bd_arp_ip4 = VppBridgeDomainArpEntry(self, epg.bd.bd,
816 str(self.router_mac),
818 epg.bd_arp_ip6 = VppBridgeDomainArpEntry(self, epg.bd.bd,
819 str(self.router_mac),
821 epg.bd_arp_ip4.add_vpp_config()
822 epg.bd_arp_ip6.add_vpp_config()
827 for recirc in recircs:
828 # EPG's ingress recirculation interface maps to its RD
829 VppIpInterfaceBind(self, recirc.recirc,
830 recirc.epg.rd.t4).add_vpp_config()
831 VppIpInterfaceBind(self, recirc.recirc,
832 recirc.epg.rd.t6).add_vpp_config()
834 self.vapi.nat44_interface_add_del_feature(
835 recirc.recirc.sw_if_index,
838 self.vapi.nat66_add_del_interface(
839 recirc.recirc.sw_if_index,
843 recirc.add_vpp_config()
845 for recirc in recircs:
846 self.assertTrue(find_bridge_domain_port(self,
847 recirc.epg.bd.bd.bd_id,
848 recirc.recirc.sw_if_index))
851 self.pg_enable_capture(self.pg_interfaces)
854 # routes to the endpoints. We need these since there are no
855 # adj-fibs due to the fact the the BVI address has /32 and
856 # the subnet is not attached.
858 for (ip, fip) in zip(ep.ips, ep.fips):
859 # Add static mappings for each EP from the 10/8 to 11/8 network
861 self.vapi.nat44_add_del_static_mapping(ip.bytes,
866 self.vapi.nat66_add_del_static_mapping(ip.bytes,
873 self.logger.info(self.vapi.cli("sh gbp endpoint"))
875 # ... results in a Gratuitous ARP/ND on the EPG's uplink
876 rx = ep.epg.uplink.get_capture(len(ep.ips), timeout=0.2)
878 for ii, ip in enumerate(ep.ips):
882 self.assertTrue(p.haslayer(ICMPv6ND_NA))
883 self.assertEqual(p[ICMPv6ND_NA].tgt, ip.address)
885 self.assertTrue(p.haslayer(ARP))
886 self.assertEqual(p[ARP].psrc, ip.address)
887 self.assertEqual(p[ARP].pdst, ip.address)
889 # add the BD ARP termination entry for floating IP
891 ba = VppBridgeDomainArpEntry(self, epg_nat.bd.bd, ep.mac, fip)
894 # floating IPs route via EPG recirc
895 r = VppIpRoute(self, fip.address, fip.length,
896 [VppRoutePath(fip.address,
897 ep.recirc.recirc.sw_if_index,
899 proto=fip.dpo_proto)],
904 # L2 FIB entries in the NAT EPG BD to bridge the packets from
905 # the outside direct to the internal EPG
906 lf = VppL2FibEntry(self, epg_nat.bd.bd, ep.mac,
907 ep.recirc.recirc, bvi_mac=0)
911 # ARP packets for unknown IP are sent to the EPG uplink
913 pkt_arp = (Ether(dst="ff:ff:ff:ff:ff:ff",
914 src=self.pg0.remote_mac) /
916 hwdst="ff:ff:ff:ff:ff:ff",
917 hwsrc=self.pg0.remote_mac,
921 self.vapi.cli("clear trace")
922 self.pg0.add_stream(pkt_arp)
924 self.pg_enable_capture(self.pg_interfaces)
927 rxd = epgs[0].uplink.get_capture(1)
930 # ARP/ND packets get a response
932 pkt_arp = (Ether(dst="ff:ff:ff:ff:ff:ff",
933 src=self.pg0.remote_mac) /
935 hwdst="ff:ff:ff:ff:ff:ff",
936 hwsrc=self.pg0.remote_mac,
937 pdst=epgs[0].bvi_ip4.address,
938 psrc=eps[0].ip4.address))
940 self.send_and_expect(self.pg0, [pkt_arp], self.pg0)
942 nsma = in6_getnsma(inet_pton(AF_INET6, eps[0].ip6.address))
943 d = inet_ntop(AF_INET6, nsma)
944 pkt_nd = (Ether(dst=in6_getnsmac(nsma),
945 src=self.pg0.remote_mac) /
946 IPv6(dst=d, src=eps[0].ip6.address) /
947 ICMPv6ND_NS(tgt=epgs[0].bvi_ip6.address) /
948 ICMPv6NDOptSrcLLAddr(lladdr=self.pg0.remote_mac))
949 self.send_and_expect(self.pg0, [pkt_nd], self.pg0)
952 # broadcast packets are flooded
954 pkt_bcast = (Ether(dst="ff:ff:ff:ff:ff:ff",
955 src=self.pg0.remote_mac) /
956 IP(src=eps[0].ip4.address, dst="232.1.1.1") /
957 UDP(sport=1234, dport=1234) /
960 self.vapi.cli("clear trace")
961 self.pg0.add_stream(pkt_bcast)
963 self.pg_enable_capture(self.pg_interfaces)
966 rxd = eps[1].itf.get_capture(1)
967 self.assertEqual(rxd[0][Ether].dst, pkt_bcast[Ether].dst)
968 rxd = epgs[0].uplink.get_capture(1)
969 self.assertEqual(rxd[0][Ether].dst, pkt_bcast[Ether].dst)
972 # packets to non-local L3 destinations dropped
974 pkt_intra_epg_220_ip4 = (Ether(src=self.pg0.remote_mac,
975 dst=str(self.router_mac)) /
976 IP(src=eps[0].ip4.address,
978 UDP(sport=1234, dport=1234) /
980 pkt_inter_epg_222_ip4 = (Ether(src=self.pg0.remote_mac,
981 dst=str(self.router_mac)) /
982 IP(src=eps[0].ip4.address,
984 UDP(sport=1234, dport=1234) /
987 self.send_and_assert_no_replies(self.pg0, pkt_intra_epg_220_ip4 * 65)
989 pkt_inter_epg_222_ip6 = (Ether(src=self.pg0.remote_mac,
990 dst=str(self.router_mac)) /
991 IPv6(src=eps[0].ip6.address,
993 UDP(sport=1234, dport=1234) /
995 self.send_and_assert_no_replies(self.pg0, pkt_inter_epg_222_ip6 * 65)
998 # Add the subnet routes
1001 self, rd0, "10.0.0.0", 24,
1002 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1004 self, rd0, "10.0.1.0", 24,
1005 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1007 self, rd0, "10.0.2.0", 24,
1008 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1010 self, rd0, "2001:10::1", 64,
1011 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1013 self, rd0, "2001:10:1::1", 64,
1014 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1016 self, rd0, "2001:10:2::1", 64,
1017 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1018 s41.add_vpp_config()
1019 s42.add_vpp_config()
1020 s43.add_vpp_config()
1021 s61.add_vpp_config()
1022 s62.add_vpp_config()
1023 s63.add_vpp_config()
1025 self.send_and_expect_bridged(eps[0].itf,
1026 pkt_intra_epg_220_ip4 * 65,
1028 self.send_and_expect_bridged(eps[0].itf,
1029 pkt_inter_epg_222_ip4 * 65,
1031 self.send_and_expect_bridged6(eps[0].itf,
1032 pkt_inter_epg_222_ip6 * 65,
1035 self.logger.info(self.vapi.cli("sh ip fib 11.0.0.2"))
1036 self.logger.info(self.vapi.cli("sh gbp endpoint-group"))
1037 self.logger.info(self.vapi.cli("sh gbp endpoint"))
1038 self.logger.info(self.vapi.cli("sh gbp recirc"))
1039 self.logger.info(self.vapi.cli("sh int"))
1040 self.logger.info(self.vapi.cli("sh int addr"))
1041 self.logger.info(self.vapi.cli("sh int feat loop6"))
1042 self.logger.info(self.vapi.cli("sh vlib graph ip4-gbp-src-classify"))
1043 self.logger.info(self.vapi.cli("sh int feat loop3"))
1044 self.logger.info(self.vapi.cli("sh int feat pg0"))
1047 # Packet destined to unknown unicast is sent on the epg uplink ...
1049 pkt_intra_epg_220_to_uplink = (Ether(src=self.pg0.remote_mac,
1050 dst="00:00:00:33:44:55") /
1051 IP(src=eps[0].ip4.address,
1053 UDP(sport=1234, dport=1234) /
1056 self.send_and_expect_bridged(eps[0].itf,
1057 pkt_intra_epg_220_to_uplink * 65,
1059 # ... and nowhere else
1060 self.pg1.get_capture(0, timeout=0.1)
1061 self.pg1.assert_nothing_captured(remark="Flood onto other VMS")
1063 pkt_intra_epg_221_to_uplink = (Ether(src=self.pg2.remote_mac,
1064 dst="00:00:00:33:44:66") /
1065 IP(src=eps[0].ip4.address,
1067 UDP(sport=1234, dport=1234) /
1070 self.send_and_expect_bridged(eps[2].itf,
1071 pkt_intra_epg_221_to_uplink * 65,
1075 # Packets from the uplink are forwarded in the absence of a contract
1077 pkt_intra_epg_220_from_uplink = (Ether(src="00:00:00:33:44:55",
1078 dst=self.pg0.remote_mac) /
1079 IP(src=eps[0].ip4.address,
1081 UDP(sport=1234, dport=1234) /
1084 self.send_and_expect_bridged(self.pg4,
1085 pkt_intra_epg_220_from_uplink * 65,
1089 # in the absence of policy, endpoints in the same EPG
1092 pkt_intra_epg = (Ether(src=self.pg0.remote_mac,
1093 dst=self.pg1.remote_mac) /
1094 IP(src=eps[0].ip4.address,
1095 dst=eps[1].ip4.address) /
1096 UDP(sport=1234, dport=1234) /
1099 self.send_and_expect_bridged(self.pg0, pkt_intra_epg * 65, self.pg1)
1102 # in the abscense of policy, endpoints in the different EPG
1103 # cannot communicate
1105 pkt_inter_epg_220_to_221 = (Ether(src=self.pg0.remote_mac,
1106 dst=self.pg2.remote_mac) /
1107 IP(src=eps[0].ip4.address,
1108 dst=eps[2].ip4.address) /
1109 UDP(sport=1234, dport=1234) /
1111 pkt_inter_epg_221_to_220 = (Ether(src=self.pg2.remote_mac,
1112 dst=self.pg0.remote_mac) /
1113 IP(src=eps[2].ip4.address,
1114 dst=eps[0].ip4.address) /
1115 UDP(sport=1234, dport=1234) /
1117 pkt_inter_epg_220_to_222 = (Ether(src=self.pg0.remote_mac,
1118 dst=str(self.router_mac)) /
1119 IP(src=eps[0].ip4.address,
1120 dst=eps[3].ip4.address) /
1121 UDP(sport=1234, dport=1234) /
1124 self.send_and_assert_no_replies(eps[0].itf,
1125 pkt_inter_epg_220_to_221 * 65)
1126 self.send_and_assert_no_replies(eps[0].itf,
1127 pkt_inter_epg_220_to_222 * 65)
1130 # A uni-directional contract from EPG 220 -> 221
1132 acl = VppGbpAcl(self)
1133 rule = acl.create_rule(permit_deny=1, proto=17)
1134 rule2 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
1135 acl_index = acl.add_vpp_config([rule, rule2])
1136 c1 = VppGbpContract(
1137 self, 220, 221, acl_index,
1138 [VppGbpContractRule(
1139 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1142 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1146 self.send_and_expect_bridged(eps[0].itf,
1147 pkt_inter_epg_220_to_221 * 65,
1149 self.send_and_assert_no_replies(eps[0].itf,
1150 pkt_inter_epg_220_to_222 * 65)
1153 # contract for the return direction
1155 c2 = VppGbpContract(
1156 self, 221, 220, acl_index,
1157 [VppGbpContractRule(
1158 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1161 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1166 self.send_and_expect_bridged(eps[0].itf,
1167 pkt_inter_epg_220_to_221 * 65,
1169 self.send_and_expect_bridged(eps[2].itf,
1170 pkt_inter_epg_221_to_220 * 65,
1174 # check that inter group is still disabled for the groups
1175 # not in the contract.
1177 self.send_and_assert_no_replies(eps[0].itf,
1178 pkt_inter_epg_220_to_222 * 65)
1181 # A uni-directional contract from EPG 220 -> 222 'L3 routed'
1183 c3 = VppGbpContract(
1184 self, 220, 222, acl_index,
1185 [VppGbpContractRule(
1186 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1189 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1194 self.logger.info(self.vapi.cli("sh gbp contract"))
1196 self.send_and_expect_routed(eps[0].itf,
1197 pkt_inter_epg_220_to_222 * 65,
1199 str(self.router_mac))
1202 # remove both contracts, traffic stops in both directions
1204 c2.remove_vpp_config()
1205 c1.remove_vpp_config()
1206 c3.remove_vpp_config()
1207 acl.remove_vpp_config()
1209 self.send_and_assert_no_replies(eps[2].itf,
1210 pkt_inter_epg_221_to_220 * 65)
1211 self.send_and_assert_no_replies(eps[0].itf,
1212 pkt_inter_epg_220_to_221 * 65)
1213 self.send_and_expect_bridged(eps[0].itf,
1218 # EPs to the outside world
1221 # in the EP's RD an external subnet via the NAT EPG's recirc
1223 self, rd0, "0.0.0.0", 0,
1224 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1225 sw_if_index=recirc_nat.recirc.sw_if_index,
1228 self, rd0, "11.0.0.0", 8,
1229 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1230 sw_if_index=recirc_nat.recirc.sw_if_index,
1232 se16 = VppGbpSubnet(
1234 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1235 sw_if_index=recirc_nat.recirc.sw_if_index,
1237 # in the NAT RD an external subnet via the NAT EPG's uplink
1239 self, rd20, "0.0.0.0", 0,
1240 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1241 sw_if_index=epg_nat.uplink.sw_if_index,
1243 se36 = VppGbpSubnet(
1244 self, rd20, "::", 0,
1245 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1246 sw_if_index=epg_nat.uplink.sw_if_index,
1249 self, rd20, "11.0.0.0", 8,
1250 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1251 sw_if_index=epg_nat.uplink.sw_if_index,
1253 se1.add_vpp_config()
1254 se2.add_vpp_config()
1255 se16.add_vpp_config()
1256 se3.add_vpp_config()
1257 se36.add_vpp_config()
1258 se4.add_vpp_config()
1260 self.logger.info(self.vapi.cli("sh ip fib 0.0.0.0/0"))
1261 self.logger.info(self.vapi.cli("sh ip fib 11.0.0.1"))
1262 self.logger.info(self.vapi.cli("sh ip6 fib ::/0"))
1263 self.logger.info(self.vapi.cli("sh ip6 fib %s" %
1267 # From an EP to an outside addess: IN2OUT
1269 pkt_inter_epg_220_to_global = (Ether(src=self.pg0.remote_mac,
1270 dst=str(self.router_mac)) /
1271 IP(src=eps[0].ip4.address,
1273 UDP(sport=1234, dport=1234) /
1277 self.send_and_assert_no_replies(eps[0].itf,
1278 pkt_inter_epg_220_to_global * 65)
1280 acl2 = VppGbpAcl(self)
1281 rule = acl2.create_rule(permit_deny=1, proto=17, sport_from=1234,
1282 sport_to=1234, dport_from=1234, dport_to=1234)
1283 rule2 = acl2.create_rule(is_ipv6=1, permit_deny=1, proto=17,
1284 sport_from=1234, sport_to=1234,
1285 dport_from=1234, dport_to=1234)
1287 acl_index2 = acl2.add_vpp_config([rule, rule2])
1288 c4 = VppGbpContract(
1289 self, 220, 333, acl_index2,
1290 [VppGbpContractRule(
1291 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1294 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1299 self.send_and_expect_natted(eps[0].itf,
1300 pkt_inter_epg_220_to_global * 65,
1302 eps[0].fip4.address)
1304 pkt_inter_epg_220_to_global = (Ether(src=self.pg0.remote_mac,
1305 dst=str(self.router_mac)) /
1306 IPv6(src=eps[0].ip6.address,
1308 UDP(sport=1234, dport=1234) /
1311 self.send_and_expect_natted6(self.pg0,
1312 pkt_inter_epg_220_to_global * 65,
1314 eps[0].fip6.address)
1317 # From a global address to an EP: OUT2IN
1319 pkt_inter_epg_220_from_global = (Ether(src=str(self.router_mac),
1320 dst=self.pg0.remote_mac) /
1321 IP(dst=eps[0].fip4.address,
1323 UDP(sport=1234, dport=1234) /
1326 self.send_and_assert_no_replies(self.pg7,
1327 pkt_inter_epg_220_from_global * 65)
1329 c5 = VppGbpContract(
1330 self, 333, 220, acl_index2,
1331 [VppGbpContractRule(
1332 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1335 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1340 self.send_and_expect_unnatted(self.pg7,
1341 pkt_inter_epg_220_from_global * 65,
1345 pkt_inter_epg_220_from_global = (Ether(src=str(self.router_mac),
1346 dst=self.pg0.remote_mac) /
1347 IPv6(dst=eps[0].fip6.address,
1349 UDP(sport=1234, dport=1234) /
1352 self.send_and_expect_unnatted6(self.pg7,
1353 pkt_inter_epg_220_from_global * 65,
1358 # From a local VM to another local VM using resp. public addresses:
1361 pkt_intra_epg_220_global = (Ether(src=self.pg0.remote_mac,
1362 dst=str(self.router_mac)) /
1363 IP(src=eps[0].ip4.address,
1364 dst=eps[1].fip4.address) /
1365 UDP(sport=1234, dport=1234) /
1368 self.send_and_expect_double_natted(eps[0].itf,
1369 pkt_intra_epg_220_global * 65,
1371 eps[0].fip4.address,
1374 pkt_intra_epg_220_global = (Ether(src=self.pg0.remote_mac,
1375 dst=str(self.router_mac)) /
1376 IPv6(src=eps[0].ip6.address,
1377 dst=eps[1].fip6.address) /
1378 UDP(sport=1234, dport=1234) /
1381 self.send_and_expect_double_natted6(eps[0].itf,
1382 pkt_intra_epg_220_global * 65,
1384 eps[0].fip6.address,
1391 # del static mappings for each EP from the 10/8 to 11/8 network
1392 self.vapi.nat44_add_del_static_mapping(ep.ip4.bytes,
1397 self.vapi.nat66_add_del_static_mapping(ep.ip6.bytes,
1403 # IP config on the BVI interfaces
1404 if epg != epgs[0] and epg != epgs[3]:
1405 self.vapi.nat44_interface_add_del_feature(epg.bvi.sw_if_index,
1408 self.vapi.nat66_add_del_interface(epg.bvi.sw_if_index,
1412 for recirc in recircs:
1413 self.vapi.nat44_interface_add_del_feature(
1414 recirc.recirc.sw_if_index,
1417 self.vapi.nat66_add_del_interface(
1418 recirc.recirc.sw_if_index,
1422 def wait_for_ep_timeout(self, sw_if_index=None, ip=None, mac=None,
1423 n_tries=100, s_time=1):
1425 if not find_gbp_endpoint(self, sw_if_index, ip, mac):
1427 n_tries = n_tries - 1
1429 self.assertFalse(find_gbp_endpoint(self, sw_if_index, ip, mac))
1432 def test_gbp_learn_l2(self):
1433 """ GBP L2 Endpoint Learning """
1435 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
1436 learnt = [{'mac': '00:00:11:11:11:01',
1438 'ip6': '2001:10::2'},
1439 {'mac': '00:00:11:11:11:02',
1441 'ip6': '2001:10::3'}]
1444 # lower the inactive threshold so these tests pass in a
1445 # reasonable amount of time
1447 self.vapi.gbp_endpoint_learn_set_inactive_threshold(2)
1452 gt4 = VppIpTable(self, 1)
1453 gt4.add_vpp_config()
1454 gt6 = VppIpTable(self, 1, is_ip6=True)
1455 gt6.add_vpp_config()
1457 rd1 = VppGbpRouteDomain(self, 1, gt4, gt6)
1458 rd1.add_vpp_config()
1461 # Pg2 hosts the vxlan tunnel, hosts on pg2 to act as TEPs
1462 # Pg3 hosts the IP4 UU-flood VXLAN tunnel
1463 # Pg4 hosts the IP6 UU-flood VXLAN tunnel
1465 self.pg2.config_ip4()
1466 self.pg2.resolve_arp()
1467 self.pg2.generate_remote_hosts(4)
1468 self.pg2.configure_ipv4_neighbors()
1469 self.pg3.config_ip4()
1470 self.pg3.resolve_arp()
1471 self.pg4.config_ip4()
1472 self.pg4.resolve_arp()
1475 # a GBP bridge domain with a BVI and a UU-flood interface
1477 bd1 = VppBridgeDomain(self, 1)
1478 bd1.add_vpp_config()
1479 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0, self.pg3)
1480 gbd1.add_vpp_config()
1482 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1483 self.logger.info(self.vapi.cli("sh gbp bridge"))
1485 # ... and has a /32 applied
1486 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
1487 ip_addr.add_vpp_config()
1490 # The Endpoint-group in which we are learning endpoints
1492 epg_220 = VppGbpEndpointGroup(self, 220, rd1, gbd1,
1496 epg_220.add_vpp_config()
1497 epg_330 = VppGbpEndpointGroup(self, 330, rd1, gbd1,
1501 epg_330.add_vpp_config()
1504 # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
1507 vx_tun_l2_1 = VppGbpVxlanTunnel(
1508 self, 99, bd1.bd_id,
1509 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L2)
1510 vx_tun_l2_1.add_vpp_config()
1513 # A static endpoint that the learnt endpoints are trying to
1516 ep = VppGbpEndpoint(self, self.pg0,
1518 "10.0.0.127", "11.0.0.127",
1519 "2001:10::1", "3001::1")
1522 self.assertTrue(find_route(self, ep.ip4.address, 32, table_id=1))
1524 # a packet with an sclass from an unknwon EPG
1525 p = (Ether(src=self.pg2.remote_mac,
1526 dst=self.pg2.local_mac) /
1527 IP(src=self.pg2.remote_hosts[0].ip4,
1528 dst=self.pg2.local_ip4) /
1529 UDP(sport=1234, dport=48879) /
1530 VXLAN(vni=99, gpid=88, flags=0x88) /
1531 Ether(src=learnt[0]["mac"], dst=ep.mac) /
1532 IP(src=learnt[0]["ip"], dst=ep.ip4.address) /
1533 UDP(sport=1234, dport=1234) /
1536 self.send_and_assert_no_replies(self.pg2, p)
1539 # we should not have learnt a new tunnel endpoint, since
1540 # the EPG was not learnt.
1542 self.assertEqual(INDEX_INVALID,
1543 find_vxlan_gbp_tunnel(self,
1545 self.pg2.remote_hosts[0].ip4,
1548 # epg is not learnt, becasue the EPG is unknwon
1549 self.assertEqual(len(self.vapi.gbp_endpoint_dump()), 1)
1551 for ii, l in enumerate(learnt):
1552 # a packet with an sclass from a knwon EPG
1553 # arriving on an unknown TEP
1554 p = (Ether(src=self.pg2.remote_mac,
1555 dst=self.pg2.local_mac) /
1556 IP(src=self.pg2.remote_hosts[1].ip4,
1557 dst=self.pg2.local_ip4) /
1558 UDP(sport=1234, dport=48879) /
1559 VXLAN(vni=99, gpid=220, flags=0x88) /
1560 Ether(src=l['mac'], dst=ep.mac) /
1561 IP(src=l['ip'], dst=ep.ip4.address) /
1562 UDP(sport=1234, dport=1234) /
1565 rx = self.send_and_expect(self.pg2, [p], self.pg0)
1568 tep1_sw_if_index = find_vxlan_gbp_tunnel(
1571 self.pg2.remote_hosts[1].ip4,
1573 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
1576 # the EP is learnt via the learnt TEP
1577 # both from its MAC and its IP
1579 self.assertTrue(find_gbp_endpoint(self,
1580 vx_tun_l2_1.sw_if_index,
1582 self.assertTrue(find_gbp_endpoint(self,
1583 vx_tun_l2_1.sw_if_index,
1586 self.logger.info(self.vapi.cli("show gbp endpoint"))
1587 self.logger.info(self.vapi.cli("show gbp vxlan"))
1588 self.logger.info(self.vapi.cli("show vxlan-gbp tunnel"))
1591 # If we sleep for the threshold time, the learnt endpoints should
1595 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1599 # repeat. the do not learn bit is set so the EPs are not learnt
1602 # a packet with an sclass from a knwon EPG
1603 p = (Ether(src=self.pg2.remote_mac,
1604 dst=self.pg2.local_mac) /
1605 IP(src=self.pg2.remote_hosts[1].ip4,
1606 dst=self.pg2.local_ip4) /
1607 UDP(sport=1234, dport=48879) /
1608 VXLAN(vni=99, gpid=220, flags=0x88, gpflags="D") /
1609 Ether(src=l['mac'], dst=ep.mac) /
1610 IP(src=l['ip'], dst=ep.ip4.address) /
1611 UDP(sport=1234, dport=1234) /
1614 rx = self.send_and_expect(self.pg2, p*65, self.pg0)
1617 self.assertFalse(find_gbp_endpoint(self,
1618 vx_tun_l2_1.sw_if_index,
1625 # a packet with an sclass from a knwon EPG
1626 p = (Ether(src=self.pg2.remote_mac,
1627 dst=self.pg2.local_mac) /
1628 IP(src=self.pg2.remote_hosts[1].ip4,
1629 dst=self.pg2.local_ip4) /
1630 UDP(sport=1234, dport=48879) /
1631 VXLAN(vni=99, gpid=220, flags=0x88) /
1632 Ether(src=l['mac'], dst=ep.mac) /
1633 IP(src=l['ip'], dst=ep.ip4.address) /
1634 UDP(sport=1234, dport=1234) /
1637 rx = self.send_and_expect(self.pg2, p*65, self.pg0)
1639 self.assertTrue(find_gbp_endpoint(self,
1640 vx_tun_l2_1.sw_if_index,
1644 # Static EP replies to dynamics
1646 self.logger.info(self.vapi.cli("sh l2fib bd_id 1"))
1648 p = (Ether(src=ep.mac, dst=l['mac']) /
1649 IP(dst=l['ip'], src=ep.ip4.address) /
1650 UDP(sport=1234, dport=1234) /
1653 rxs = self.send_and_expect(self.pg0, p * 17, self.pg2)
1656 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
1657 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
1658 self.assertEqual(rx[UDP].dport, 48879)
1659 # the UDP source port is a random value for hashing
1660 self.assertEqual(rx[VXLAN].gpid, 220)
1661 self.assertEqual(rx[VXLAN].vni, 99)
1662 self.assertTrue(rx[VXLAN].flags.G)
1663 self.assertTrue(rx[VXLAN].flags.Instance)
1664 self.assertTrue(rx[VXLAN].gpflags.A)
1665 self.assertFalse(rx[VXLAN].gpflags.D)
1668 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1672 # repeat in the other EPG
1673 # there's no contract between 220 and 330, but the A-bit is set
1674 # so the packet is cleared for delivery
1677 # a packet with an sclass from a knwon EPG
1678 p = (Ether(src=self.pg2.remote_mac,
1679 dst=self.pg2.local_mac) /
1680 IP(src=self.pg2.remote_hosts[1].ip4,
1681 dst=self.pg2.local_ip4) /
1682 UDP(sport=1234, dport=48879) /
1683 VXLAN(vni=99, gpid=330, flags=0x88, gpflags='A') /
1684 Ether(src=l['mac'], dst=ep.mac) /
1685 IP(src=l['ip'], dst=ep.ip4.address) /
1686 UDP(sport=1234, dport=1234) /
1689 rx = self.send_and_expect(self.pg2, p*65, self.pg0)
1691 self.assertTrue(find_gbp_endpoint(self,
1692 vx_tun_l2_1.sw_if_index,
1696 # static EP cannot reach the learnt EPs since there is no contract
1697 # only test 1 EP as the others could timeout
1699 p = (Ether(src=ep.mac, dst=l['mac']) /
1700 IP(dst=learnt[0]['ip'], src=ep.ip4.address) /
1701 UDP(sport=1234, dport=1234) /
1704 self.send_and_assert_no_replies(self.pg0, [p])
1707 # refresh the entries after the check for no replies above
1710 # a packet with an sclass from a knwon EPG
1711 p = (Ether(src=self.pg2.remote_mac,
1712 dst=self.pg2.local_mac) /
1713 IP(src=self.pg2.remote_hosts[1].ip4,
1714 dst=self.pg2.local_ip4) /
1715 UDP(sport=1234, dport=48879) /
1716 VXLAN(vni=99, gpid=330, flags=0x88, gpflags='A') /
1717 Ether(src=l['mac'], dst=ep.mac) /
1718 IP(src=l['ip'], dst=ep.ip4.address) /
1719 UDP(sport=1234, dport=1234) /
1722 rx = self.send_and_expect(self.pg2, p*65, self.pg0)
1724 self.assertTrue(find_gbp_endpoint(self,
1725 vx_tun_l2_1.sw_if_index,
1729 # Add the contract so they can talk
1731 acl = VppGbpAcl(self)
1732 rule = acl.create_rule(permit_deny=1, proto=17)
1733 rule2 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
1734 acl_index = acl.add_vpp_config([rule, rule2])
1735 c1 = VppGbpContract(
1736 self, 220, 330, acl_index,
1737 [VppGbpContractRule(
1738 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1741 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1747 p = (Ether(src=ep.mac, dst=l['mac']) /
1748 IP(dst=l['ip'], src=ep.ip4.address) /
1749 UDP(sport=1234, dport=1234) /
1752 self.send_and_expect(self.pg0, [p], self.pg2)
1755 # send UU packets from the local EP
1757 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1758 self.logger.info(self.vapi.cli("sh gbp bridge"))
1759 p_uu = (Ether(src=ep.mac, dst="00:11:11:11:11:11") /
1760 IP(dst="10.0.0.133", src=ep.ip4.address) /
1761 UDP(sport=1234, dport=1234) /
1763 rxs = self.send_and_expect(ep.itf, [p_uu], gbd1.uu_flood)
1766 # Add a mcast destination VXLAN-GBP tunnel for B&M traffic
1768 tun_bm = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
1771 tun_bm.add_vpp_config()
1772 bp_bm = VppBridgeDomainPort(self, bd1, tun_bm,
1773 port_type=L2_PORT_TYPE.NORMAL)
1774 bp_bm.add_vpp_config()
1776 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1778 p_bm = (Ether(src=ep.mac, dst="ff:ff:ff:ff:ff:ff") /
1779 IP(dst="10.0.0.133", src=ep.ip4.address) /
1780 UDP(sport=1234, dport=1234) /
1782 rxs = self.send_and_expect_only(ep.itf, [p_bm], tun_bm.mcast_itf)
1785 # Check v6 Endpoints
1788 # a packet with an sclass from a knwon EPG
1789 p = (Ether(src=self.pg2.remote_mac,
1790 dst=self.pg2.local_mac) /
1791 IP(src=self.pg2.remote_hosts[1].ip4,
1792 dst=self.pg2.local_ip4) /
1793 UDP(sport=1234, dport=48879) /
1794 VXLAN(vni=99, gpid=330, flags=0x88, gpflags='A') /
1795 Ether(src=l['mac'], dst=ep.mac) /
1796 IPv6(src=l['ip6'], dst=ep.ip6.address) /
1797 UDP(sport=1234, dport=1234) /
1800 rx = self.send_and_expect(self.pg2, p*65, self.pg0)
1802 self.assertTrue(find_gbp_endpoint(self,
1803 vx_tun_l2_1.sw_if_index,
1807 # L3 Endpoint Learning
1808 # - configured on the bridge's BVI
1815 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1818 self.pg2.unconfig_ip4()
1819 self.pg3.unconfig_ip4()
1820 self.pg4.unconfig_ip4()
1822 self.logger.info(self.vapi.cli("sh int"))
1823 self.logger.info(self.vapi.cli("sh gbp vxlan"))
1825 @unittest.skipIf(is_skip_aarch64_set and is_platform_aarch64,
1826 "test doesn't work on aarch64")
1827 def test_gbp_learn_vlan_l2(self):
1828 """ GBP L2 Endpoint w/ VLANs"""
1830 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
1831 learnt = [{'mac': '00:00:11:11:11:01',
1833 'ip6': '2001:10::2'},
1834 {'mac': '00:00:11:11:11:02',
1836 'ip6': '2001:10::3'}]
1839 # lower the inactive threshold so these tests pass in a
1840 # reasonable amount of time
1842 self.vapi.gbp_endpoint_learn_set_inactive_threshold(2)
1847 gt4 = VppIpTable(self, 1)
1848 gt4.add_vpp_config()
1849 gt6 = VppIpTable(self, 1, is_ip6=True)
1850 gt6.add_vpp_config()
1852 rd1 = VppGbpRouteDomain(self, 1, gt4, gt6)
1853 rd1.add_vpp_config()
1856 # Pg2 hosts the vxlan tunnel, hosts on pg2 to act as TEPs
1858 self.pg2.config_ip4()
1859 self.pg2.resolve_arp()
1860 self.pg2.generate_remote_hosts(4)
1861 self.pg2.configure_ipv4_neighbors()
1862 self.pg3.config_ip4()
1863 self.pg3.resolve_arp()
1866 # The EP will be on a vlan sub-interface
1868 vlan_11 = VppDot1QSubint(self, self.pg0, 11)
1870 self.vapi.sw_interface_set_l2_tag_rewrite(vlan_11.sw_if_index,
1874 bd_uu_fwd = VppVxlanGbpTunnel(self, self.pg3.local_ip4,
1875 self.pg3.remote_ip4, 116)
1876 bd_uu_fwd.add_vpp_config()
1879 # a GBP bridge domain with a BVI and a UU-flood interface
1880 # The BD is marked as do not learn, so no endpoints are ever
1881 # learnt in this BD.
1883 bd1 = VppBridgeDomain(self, 1)
1884 bd1.add_vpp_config()
1885 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0, bd_uu_fwd,
1887 gbd1.add_vpp_config()
1889 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1890 self.logger.info(self.vapi.cli("sh gbp bridge"))
1892 # ... and has a /32 applied
1893 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
1894 ip_addr.add_vpp_config()
1897 # The Endpoint-group in which we are learning endpoints
1899 epg_220 = VppGbpEndpointGroup(self, 220, rd1, gbd1,
1903 epg_220.add_vpp_config()
1906 # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
1909 vx_tun_l2_1 = VppGbpVxlanTunnel(
1910 self, 99, bd1.bd_id,
1911 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L2)
1912 vx_tun_l2_1.add_vpp_config()
1915 # A static endpoint that the learnt endpoints are trying to
1918 ep = VppGbpEndpoint(self, vlan_11,
1920 "10.0.0.127", "11.0.0.127",
1921 "2001:10::1", "3001::1")
1924 self.assertTrue(find_route(self, ep.ip4.address, 32, table_id=1))
1927 # Send to the static EP
1929 for ii, l in enumerate(learnt):
1930 # a packet with an sclass from a knwon EPG
1931 # arriving on an unknown TEP
1932 p = (Ether(src=self.pg2.remote_mac,
1933 dst=self.pg2.local_mac) /
1934 IP(src=self.pg2.remote_hosts[1].ip4,
1935 dst=self.pg2.local_ip4) /
1936 UDP(sport=1234, dport=48879) /
1937 VXLAN(vni=99, gpid=220, flags=0x88) /
1938 Ether(src=l['mac'], dst=ep.mac) /
1939 IP(src=l['ip'], dst=ep.ip4.address) /
1940 UDP(sport=1234, dport=1234) /
1943 rxs = self.send_and_expect(self.pg2, [p], self.pg0)
1946 # packet to EP has the EP's vlan tag
1949 self.assertEqual(rx[Dot1Q].vlan, 11)
1952 # the EP is not learnt since the BD setting prevents it
1955 self.assertFalse(find_gbp_endpoint(self,
1956 vx_tun_l2_1.sw_if_index,
1958 self.assertEqual(INDEX_INVALID,
1959 find_vxlan_gbp_tunnel(
1962 self.pg2.remote_hosts[1].ip4,
1965 self.assertEqual(len(self.vapi.gbp_endpoint_dump()), 1)
1969 # we didn't learn the remotes so they are sent to the UU-fwd
1972 p = (Ether(src=ep.mac, dst=l['mac']) /
1974 IP(dst=l['ip'], src=ep.ip4.address) /
1975 UDP(sport=1234, dport=1234) /
1978 rxs = self.send_and_expect(self.pg0, p * 17, self.pg3)
1981 self.assertEqual(rx[IP].src, self.pg3.local_ip4)
1982 self.assertEqual(rx[IP].dst, self.pg3.remote_ip4)
1983 self.assertEqual(rx[UDP].dport, 48879)
1984 # the UDP source port is a random value for hashing
1985 self.assertEqual(rx[VXLAN].gpid, 220)
1986 self.assertEqual(rx[VXLAN].vni, 116)
1987 self.assertTrue(rx[VXLAN].flags.G)
1988 self.assertTrue(rx[VXLAN].flags.Instance)
1989 self.assertFalse(rx[VXLAN].gpflags.A)
1990 self.assertFalse(rx[VXLAN].gpflags.D)
1992 self.pg2.unconfig_ip4()
1993 self.pg3.unconfig_ip4()
1995 @unittest.skipIf(is_skip_aarch64_set and is_platform_aarch64,
1996 "test doesn't work on aarch64")
1997 def test_gbp_learn_l3(self):
1998 """ GBP L3 Endpoint Learning """
2000 self.vapi.cli("set logging class gbp debug")
2002 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
2003 routed_dst_mac = "00:0c:0c:0c:0c:0c"
2004 routed_src_mac = "00:22:bd:f8:19:ff"
2006 learnt = [{'mac': '00:00:11:11:11:02',
2008 'ip6': '2001:10::2'},
2009 {'mac': '00:00:11:11:11:03',
2011 'ip6': '2001:10::3'}]
2014 # lower the inactive threshold so these tests pass in a
2015 # reasonable amount of time
2017 self.vapi.gbp_endpoint_learn_set_inactive_threshold(2)
2022 t4 = VppIpTable(self, 1)
2024 t6 = VppIpTable(self, 1, True)
2027 tun_ip4_uu = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
2028 self.pg4.remote_ip4, 114)
2029 tun_ip6_uu = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
2030 self.pg4.remote_ip4, 116)
2031 tun_ip4_uu.add_vpp_config()
2032 tun_ip6_uu.add_vpp_config()
2034 rd1 = VppGbpRouteDomain(self, 2, t4, t6, tun_ip4_uu, tun_ip6_uu)
2035 rd1.add_vpp_config()
2037 self.loop0.set_mac(self.router_mac)
2040 # Bind the BVI to the RD
2042 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
2043 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
2046 # Pg2 hosts the vxlan tunnel
2047 # hosts on pg2 to act as TEPs
2051 self.pg2.config_ip4()
2052 self.pg2.resolve_arp()
2053 self.pg2.generate_remote_hosts(4)
2054 self.pg2.configure_ipv4_neighbors()
2055 self.pg3.config_ip4()
2056 self.pg3.resolve_arp()
2057 self.pg4.config_ip4()
2058 self.pg4.resolve_arp()
2061 # a GBP bridge domain with a BVI and a UU-flood interface
2063 bd1 = VppBridgeDomain(self, 1)
2064 bd1.add_vpp_config()
2065 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0, self.pg3)
2066 gbd1.add_vpp_config()
2068 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2069 self.logger.info(self.vapi.cli("sh gbp bridge"))
2070 self.logger.info(self.vapi.cli("sh gbp route"))
2072 # ... and has a /32 and /128 applied
2073 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2074 ip4_addr.add_vpp_config()
2075 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 128)
2076 ip6_addr.add_vpp_config()
2079 # The Endpoint-group in which we are learning endpoints
2081 epg_220 = VppGbpEndpointGroup(self, 220, rd1, gbd1,
2085 epg_220.add_vpp_config()
2088 # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
2091 vx_tun_l3 = VppGbpVxlanTunnel(
2092 self, 101, rd1.rd_id,
2093 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3)
2094 vx_tun_l3.add_vpp_config()
2097 # A static endpoint that the learnt endpoints are trying to
2100 ep = VppGbpEndpoint(self, self.pg0,
2102 "10.0.0.127", "11.0.0.127",
2103 "2001:10::1", "3001::1")
2107 # learn some remote IPv4 EPs
2109 for ii, l in enumerate(learnt):
2110 # a packet with an sclass from a knwon EPG
2111 # arriving on an unknown TEP
2112 p = (Ether(src=self.pg2.remote_mac,
2113 dst=self.pg2.local_mac) /
2114 IP(src=self.pg2.remote_hosts[1].ip4,
2115 dst=self.pg2.local_ip4) /
2116 UDP(sport=1234, dport=48879) /
2117 VXLAN(vni=101, gpid=220, flags=0x88) /
2118 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2119 IP(src=l['ip'], dst=ep.ip4.address) /
2120 UDP(sport=1234, dport=1234) /
2123 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2126 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2129 self.pg2.remote_hosts[1].ip4,
2131 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2133 # endpoint learnt via the parent GBP-vxlan interface
2134 self.assertTrue(find_gbp_endpoint(self,
2135 vx_tun_l3._sw_if_index,
2139 # Static IPv4 EP replies to learnt
2142 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2143 IP(dst=l['ip'], src=ep.ip4.address) /
2144 UDP(sport=1234, dport=1234) /
2147 rxs = self.send_and_expect(self.pg0, p*1, self.pg2)
2150 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2151 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2152 self.assertEqual(rx[UDP].dport, 48879)
2153 # the UDP source port is a random value for hashing
2154 self.assertEqual(rx[VXLAN].gpid, 220)
2155 self.assertEqual(rx[VXLAN].vni, 101)
2156 self.assertTrue(rx[VXLAN].flags.G)
2157 self.assertTrue(rx[VXLAN].flags.Instance)
2158 self.assertTrue(rx[VXLAN].gpflags.A)
2159 self.assertFalse(rx[VXLAN].gpflags.D)
2161 inner = rx[VXLAN].payload
2163 self.assertEqual(inner[Ether].src, routed_src_mac)
2164 self.assertEqual(inner[Ether].dst, routed_dst_mac)
2165 self.assertEqual(inner[IP].src, ep.ip4.address)
2166 self.assertEqual(inner[IP].dst, l['ip'])
2169 self.assertFalse(find_gbp_endpoint(self,
2174 # learn some remote IPv6 EPs
2176 for ii, l in enumerate(learnt):
2177 # a packet with an sclass from a knwon EPG
2178 # arriving on an unknown TEP
2179 p = (Ether(src=self.pg2.remote_mac,
2180 dst=self.pg2.local_mac) /
2181 IP(src=self.pg2.remote_hosts[1].ip4,
2182 dst=self.pg2.local_ip4) /
2183 UDP(sport=1234, dport=48879) /
2184 VXLAN(vni=101, gpid=220, flags=0x88) /
2185 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2186 IPv6(src=l['ip6'], dst=ep.ip6.address) /
2187 UDP(sport=1234, dport=1234) /
2190 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2193 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2196 self.pg2.remote_hosts[1].ip4,
2198 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2200 self.logger.info(self.vapi.cli("show gbp bridge"))
2201 self.logger.info(self.vapi.cli("show vxlan-gbp tunnel"))
2202 self.logger.info(self.vapi.cli("show gbp vxlan"))
2203 self.logger.info(self.vapi.cli("show int addr"))
2205 # endpoint learnt via the TEP
2206 self.assertTrue(find_gbp_endpoint(self, ip=l['ip6']))
2208 self.logger.info(self.vapi.cli("show gbp endpoint"))
2209 self.logger.info(self.vapi.cli("show ip fib index 1 %s" % l['ip']))
2212 # Static EP replies to learnt
2215 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2216 IPv6(dst=l['ip6'], src=ep.ip6.address) /
2217 UDP(sport=1234, dport=1234) /
2220 rxs = self.send_and_expect(self.pg0, p*65, self.pg2)
2223 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2224 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2225 self.assertEqual(rx[UDP].dport, 48879)
2226 # the UDP source port is a random value for hashing
2227 self.assertEqual(rx[VXLAN].gpid, 220)
2228 self.assertEqual(rx[VXLAN].vni, 101)
2229 self.assertTrue(rx[VXLAN].flags.G)
2230 self.assertTrue(rx[VXLAN].flags.Instance)
2231 self.assertTrue(rx[VXLAN].gpflags.A)
2232 self.assertFalse(rx[VXLAN].gpflags.D)
2234 inner = rx[VXLAN].payload
2236 self.assertEqual(inner[Ether].src, routed_src_mac)
2237 self.assertEqual(inner[Ether].dst, routed_dst_mac)
2238 self.assertEqual(inner[IPv6].src, ep.ip6.address)
2239 self.assertEqual(inner[IPv6].dst, l['ip6'])
2241 self.logger.info(self.vapi.cli("sh gbp endpoint"))
2243 self.wait_for_ep_timeout(ip=l['ip'])
2246 # Static sends to unknown EP with no route
2248 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2249 IP(dst="10.0.0.99", src=ep.ip4.address) /
2250 UDP(sport=1234, dport=1234) /
2253 self.send_and_assert_no_replies(self.pg0, [p])
2256 # Add a route to static EP's v4 and v6 subnet
2257 # packets should be sent on the v4/v6 uu=fwd interface resp.
2259 se_10_24 = VppGbpSubnet(
2260 self, rd1, "10.0.0.0", 24,
2261 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT)
2262 se_10_24.add_vpp_config()
2264 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2265 IP(dst="10.0.0.99", src=ep.ip4.address) /
2266 UDP(sport=1234, dport=1234) /
2269 rxs = self.send_and_expect(self.pg0, [p], self.pg4)
2271 self.assertEqual(rx[IP].src, self.pg4.local_ip4)
2272 self.assertEqual(rx[IP].dst, self.pg4.remote_ip4)
2273 self.assertEqual(rx[UDP].dport, 48879)
2274 # the UDP source port is a random value for hashing
2275 self.assertEqual(rx[VXLAN].gpid, 220)
2276 self.assertEqual(rx[VXLAN].vni, 114)
2277 self.assertTrue(rx[VXLAN].flags.G)
2278 self.assertTrue(rx[VXLAN].flags.Instance)
2279 # policy is not applied to packets sent to the uu-fwd interfaces
2280 self.assertFalse(rx[VXLAN].gpflags.A)
2281 self.assertFalse(rx[VXLAN].gpflags.D)
2284 # learn some remote IPv4 EPs
2286 for ii, l in enumerate(learnt):
2287 # a packet with an sclass from a knwon EPG
2288 # arriving on an unknown TEP
2289 p = (Ether(src=self.pg2.remote_mac,
2290 dst=self.pg2.local_mac) /
2291 IP(src=self.pg2.remote_hosts[1].ip4,
2292 dst=self.pg2.local_ip4) /
2293 UDP(sport=1234, dport=48879) /
2294 VXLAN(vni=101, gpid=220, flags=0x88) /
2295 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2296 IP(src=l['ip'], dst=ep.ip4.address) /
2297 UDP(sport=1234, dport=1234) /
2300 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2303 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2306 self.pg2.remote_hosts[1].ip4,
2308 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2310 # endpoint learnt via the parent GBP-vxlan interface
2311 self.assertTrue(find_gbp_endpoint(self,
2312 vx_tun_l3._sw_if_index,
2316 # Add a remote endpoint from the API
2318 rep_88 = VppGbpEndpoint(self, vx_tun_l3,
2320 "10.0.0.88", "11.0.0.88",
2321 "2001:10::88", "3001::88",
2322 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
2324 self.pg2.remote_hosts[1].ip4,
2326 rep_88.add_vpp_config()
2329 # Add a remote endpoint from the API that matches an existing one
2331 rep_2 = VppGbpEndpoint(self, vx_tun_l3,
2333 learnt[0]['ip'], "11.0.0.101",
2334 learnt[0]['ip6'], "3001::101",
2335 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
2337 self.pg2.remote_hosts[1].ip4,
2339 rep_2.add_vpp_config()
2342 # Add a route to the leanred EP's v4 subnet
2343 # packets should be send on the v4/v6 uu=fwd interface resp.
2345 se_10_1_24 = VppGbpSubnet(
2346 self, rd1, "10.0.1.0", 24,
2347 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT)
2348 se_10_1_24.add_vpp_config()
2350 self.logger.info(self.vapi.cli("show gbp endpoint"))
2352 ips = ["10.0.0.88", learnt[0]['ip']]
2354 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2355 IP(dst=ip, src=ep.ip4.address) /
2356 UDP(sport=1234, dport=1234) /
2359 rxs = self.send_and_expect(self.pg0, p*65, self.pg2)
2362 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2363 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2364 self.assertEqual(rx[UDP].dport, 48879)
2365 # the UDP source port is a random value for hashing
2366 self.assertEqual(rx[VXLAN].gpid, 220)
2367 self.assertEqual(rx[VXLAN].vni, 101)
2368 self.assertTrue(rx[VXLAN].flags.G)
2369 self.assertTrue(rx[VXLAN].flags.Instance)
2370 self.assertTrue(rx[VXLAN].gpflags.A)
2371 self.assertFalse(rx[VXLAN].gpflags.D)
2373 inner = rx[VXLAN].payload
2375 self.assertEqual(inner[Ether].src, routed_src_mac)
2376 self.assertEqual(inner[Ether].dst, routed_dst_mac)
2377 self.assertEqual(inner[IP].src, ep.ip4.address)
2378 self.assertEqual(inner[IP].dst, ip)
2381 # remove the API remote EPs, only API sourced is gone, the DP
2382 # learnt one remains
2384 rep_88.remove_vpp_config()
2385 rep_2.remove_vpp_config()
2387 self.assertTrue(find_gbp_endpoint(self, ip=rep_2.ip4.address))
2389 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2390 IP(src=ep.ip4.address, dst=rep_2.ip4.address) /
2391 UDP(sport=1234, dport=1234) /
2393 rxs = self.send_and_expect(self.pg0, [p], self.pg2)
2395 self.assertFalse(find_gbp_endpoint(self, ip=rep_88.ip4.address))
2397 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2398 IP(src=ep.ip4.address, dst=rep_88.ip4.address) /
2399 UDP(sport=1234, dport=1234) /
2401 rxs = self.send_and_expect(self.pg0, [p], self.pg4)
2404 # to appease the testcase we cannot have the registered EP stll
2405 # present (because it's DP learnt) when the TC ends so wait until
2408 self.wait_for_ep_timeout(ip=rep_88.ip4.address)
2409 self.wait_for_ep_timeout(ip=rep_2.ip4.address)
2412 # shutdown with learnt endpoint present
2414 p = (Ether(src=self.pg2.remote_mac,
2415 dst=self.pg2.local_mac) /
2416 IP(src=self.pg2.remote_hosts[1].ip4,
2417 dst=self.pg2.local_ip4) /
2418 UDP(sport=1234, dport=48879) /
2419 VXLAN(vni=101, gpid=220, flags=0x88) /
2420 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2421 IP(src=learnt[1]['ip'], dst=ep.ip4.address) /
2422 UDP(sport=1234, dport=1234) /
2425 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2427 # endpoint learnt via the parent GBP-vxlan interface
2428 self.assertTrue(find_gbp_endpoint(self,
2429 vx_tun_l3._sw_if_index,
2434 # remote endpoint becomes local
2436 self.pg2.unconfig_ip4()
2437 self.pg3.unconfig_ip4()
2438 self.pg4.unconfig_ip4()
2440 def test_gbp_redirect(self):
2441 """ GBP Endpoint Redirect """
2443 self.vapi.cli("set logging class gbp debug")
2445 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
2446 routed_dst_mac = "00:0c:0c:0c:0c:0c"
2447 routed_src_mac = "00:22:bd:f8:19:ff"
2449 learnt = [{'mac': '00:00:11:11:11:02',
2451 'ip6': '2001:10::2'},
2452 {'mac': '00:00:11:11:11:03',
2454 'ip6': '2001:10::3'}]
2457 # lower the inactive threshold so these tests pass in a
2458 # reasonable amount of time
2460 self.vapi.gbp_endpoint_learn_set_inactive_threshold(2)
2465 t4 = VppIpTable(self, 1)
2467 t6 = VppIpTable(self, 1, True)
2470 rd1 = VppGbpRouteDomain(self, 2, t4, t6)
2471 rd1.add_vpp_config()
2473 self.loop0.set_mac(self.router_mac)
2476 # Bind the BVI to the RD
2478 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
2479 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
2482 # Pg7 hosts a BD's UU-fwd
2484 self.pg7.config_ip4()
2485 self.pg7.resolve_arp()
2488 # a GBP bridge domains for the EPs
2490 bd1 = VppBridgeDomain(self, 1)
2491 bd1.add_vpp_config()
2492 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0)
2493 gbd1.add_vpp_config()
2495 bd2 = VppBridgeDomain(self, 2)
2496 bd2.add_vpp_config()
2497 gbd2 = VppGbpBridgeDomain(self, bd2, self.loop1)
2498 gbd2.add_vpp_config()
2500 # ... and has a /32 and /128 applied
2501 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2502 ip4_addr.add_vpp_config()
2503 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 128)
2504 ip6_addr.add_vpp_config()
2505 ip4_addr = VppIpInterfaceAddress(self, gbd2.bvi, "10.0.1.128", 32)
2506 ip4_addr.add_vpp_config()
2507 ip6_addr = VppIpInterfaceAddress(self, gbd2.bvi, "2001:11::128", 128)
2508 ip6_addr.add_vpp_config()
2511 # The Endpoint-groups in which we are learning endpoints
2513 epg_220 = VppGbpEndpointGroup(self, 220, rd1, gbd1,
2517 epg_220.add_vpp_config()
2518 epg_221 = VppGbpEndpointGroup(self, 221, rd1, gbd2,
2522 epg_221.add_vpp_config()
2523 epg_222 = VppGbpEndpointGroup(self, 222, rd1, gbd1,
2527 epg_222.add_vpp_config()
2530 # a GBP bridge domains for the SEPs
2532 bd_uu1 = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
2533 self.pg7.remote_ip4, 116)
2534 bd_uu1.add_vpp_config()
2535 bd_uu2 = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
2536 self.pg7.remote_ip4, 117)
2537 bd_uu2.add_vpp_config()
2539 bd3 = VppBridgeDomain(self, 3)
2540 bd3.add_vpp_config()
2541 gbd3 = VppGbpBridgeDomain(self, bd3, self.loop2, bd_uu1, learn=False)
2542 gbd3.add_vpp_config()
2543 bd4 = VppBridgeDomain(self, 4)
2544 bd4.add_vpp_config()
2545 gbd4 = VppGbpBridgeDomain(self, bd4, self.loop3, bd_uu2, learn=False)
2546 gbd4.add_vpp_config()
2549 # EPGs in which the service endpoints exist
2551 epg_320 = VppGbpEndpointGroup(self, 320, rd1, gbd3,
2555 epg_320.add_vpp_config()
2556 epg_321 = VppGbpEndpointGroup(self, 321, rd1, gbd4,
2560 epg_321.add_vpp_config()
2563 # three local endpoints
2565 ep1 = VppGbpEndpoint(self, self.pg0,
2567 "10.0.0.1", "11.0.0.1",
2568 "2001:10::1", "3001:10::1")
2569 ep1.add_vpp_config()
2570 ep2 = VppGbpEndpoint(self, self.pg1,
2572 "10.0.1.1", "11.0.1.1",
2573 "2001:11::1", "3001:11::1")
2574 ep2.add_vpp_config()
2575 ep3 = VppGbpEndpoint(self, self.pg2,
2577 "10.0.2.2", "11.0.2.2",
2578 "2001:12::1", "3001:12::1")
2579 ep3.add_vpp_config()
2584 sep1 = VppGbpEndpoint(self, self.pg3,
2586 "12.0.0.1", "13.0.0.1",
2587 "4001:10::1", "5001:10::1")
2588 sep1.add_vpp_config()
2589 sep2 = VppGbpEndpoint(self, self.pg4,
2591 "12.0.0.2", "13.0.0.2",
2592 "4001:10::2", "5001:10::2")
2593 sep2.add_vpp_config()
2594 sep3 = VppGbpEndpoint(self, self.pg5,
2596 "12.0.1.1", "13.0.1.1",
2597 "4001:11::1", "5001:11::1")
2598 sep3.add_vpp_config()
2599 # this EP is not installed immediately
2600 sep4 = VppGbpEndpoint(self, self.pg6,
2602 "12.0.1.2", "13.0.1.2",
2603 "4001:11::2", "5001:11::2")
2606 # an L2 switch packet between local EPs in different EPGs
2607 # different dest ports on each so the are LB hashed differently
2609 p4 = [(Ether(src=ep1.mac, dst=ep3.mac) /
2610 IP(src=ep1.ip4.address, dst=ep3.ip4.address) /
2611 UDP(sport=1234, dport=1234) /
2613 (Ether(src=ep3.mac, dst=ep1.mac) /
2614 IP(src=ep3.ip4.address, dst=ep1.ip4.address) /
2615 UDP(sport=1234, dport=1234) /
2617 p6 = [(Ether(src=ep1.mac, dst=ep3.mac) /
2618 IPv6(src=ep1.ip6.address, dst=ep3.ip6.address) /
2619 UDP(sport=1234, dport=1234) /
2621 (Ether(src=ep3.mac, dst=ep1.mac) /
2622 IPv6(src=ep3.ip6.address, dst=ep1.ip6.address) /
2623 UDP(sport=1234, dport=1230) /
2626 # should be dropped since no contract yet
2627 self.send_and_assert_no_replies(self.pg0, [p4[0]])
2628 self.send_and_assert_no_replies(self.pg0, [p6[0]])
2631 # Add a contract with a rule to load-balance redirect via SEP1 and SEP2
2632 # one of the next-hops is via an EP that is not known
2634 acl = VppGbpAcl(self)
2635 rule4 = acl.create_rule(permit_deny=1, proto=17)
2636 rule6 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
2637 acl_index = acl.add_vpp_config([rule4, rule6])
2640 # test the src-ip hash mode
2642 c1 = VppGbpContract(
2643 self, 220, 222, acl_index,
2644 [VppGbpContractRule(
2645 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2646 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2647 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
2648 sep1.ip4, sep1.epg.rd),
2649 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
2650 sep2.ip4, sep2.epg.rd)]),
2652 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2653 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2654 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
2655 sep3.ip6, sep3.epg.rd),
2656 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
2657 sep4.ip6, sep4.epg.rd)])])
2660 c2 = VppGbpContract(
2661 self, 222, 220, acl_index,
2662 [VppGbpContractRule(
2663 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2664 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2665 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
2666 sep1.ip4, sep1.epg.rd),
2667 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
2668 sep2.ip4, sep2.epg.rd)]),
2670 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2671 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2672 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
2673 sep3.ip6, sep3.epg.rd),
2674 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
2675 sep4.ip6, sep4.epg.rd)])])
2679 # send again with the contract preset, now packets arrive
2680 # at SEP1 or SEP2 depending on the hashing
2682 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
2685 self.assertEqual(rx[Ether].src, routed_src_mac)
2686 self.assertEqual(rx[Ether].dst, sep1.mac)
2687 self.assertEqual(rx[IP].src, ep1.ip4.address)
2688 self.assertEqual(rx[IP].dst, ep3.ip4.address)
2690 rxs = self.send_and_expect(self.pg2, p4[1] * 17, sep2.itf)
2693 self.assertEqual(rx[Ether].src, routed_src_mac)
2694 self.assertEqual(rx[Ether].dst, sep2.mac)
2695 self.assertEqual(rx[IP].src, ep3.ip4.address)
2696 self.assertEqual(rx[IP].dst, ep1.ip4.address)
2698 rxs = self.send_and_expect(self.pg0, p6[0] * 17, self.pg7)
2701 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
2702 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
2703 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
2704 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
2705 self.assertEqual(rx[VXLAN].vni, 117)
2706 self.assertTrue(rx[VXLAN].flags.G)
2707 self.assertTrue(rx[VXLAN].flags.Instance)
2708 # redirect policy has been applied
2709 self.assertTrue(rx[VXLAN].gpflags.A)
2710 self.assertFalse(rx[VXLAN].gpflags.D)
2712 inner = rx[VXLAN].payload
2714 self.assertEqual(inner[Ether].src, routed_src_mac)
2715 self.assertEqual(inner[Ether].dst, sep4.mac)
2716 self.assertEqual(inner[IPv6].src, ep1.ip6.address)
2717 self.assertEqual(inner[IPv6].dst, ep3.ip6.address)
2719 rxs = self.send_and_expect(self.pg2, p6[1] * 17, sep3.itf)
2722 self.assertEqual(rx[Ether].src, routed_src_mac)
2723 self.assertEqual(rx[Ether].dst, sep3.mac)
2724 self.assertEqual(rx[IPv6].src, ep3.ip6.address)
2725 self.assertEqual(rx[IPv6].dst, ep1.ip6.address)
2728 # programme the unknown EP
2730 sep4.add_vpp_config()
2732 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep4.itf)
2735 self.assertEqual(rx[Ether].src, routed_src_mac)
2736 self.assertEqual(rx[Ether].dst, sep4.mac)
2737 self.assertEqual(rx[IPv6].src, ep1.ip6.address)
2738 self.assertEqual(rx[IPv6].dst, ep3.ip6.address)
2741 # and revert back to unprogrammed
2743 sep4.remove_vpp_config()
2745 rxs = self.send_and_expect(self.pg0, p6[0] * 17, self.pg7)
2748 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
2749 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
2750 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
2751 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
2752 self.assertEqual(rx[VXLAN].vni, 117)
2753 self.assertTrue(rx[VXLAN].flags.G)
2754 self.assertTrue(rx[VXLAN].flags.Instance)
2755 # redirect policy has been applied
2756 self.assertTrue(rx[VXLAN].gpflags.A)
2757 self.assertFalse(rx[VXLAN].gpflags.D)
2759 inner = rx[VXLAN].payload
2761 self.assertEqual(inner[Ether].src, routed_src_mac)
2762 self.assertEqual(inner[Ether].dst, sep4.mac)
2763 self.assertEqual(inner[IPv6].src, ep1.ip6.address)
2764 self.assertEqual(inner[IPv6].dst, ep3.ip6.address)
2766 c1.remove_vpp_config()
2767 c2.remove_vpp_config()
2770 # test the symmetric hash mode
2772 c1 = VppGbpContract(
2773 self, 220, 222, acl_index,
2774 [VppGbpContractRule(
2775 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2776 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
2777 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
2778 sep1.ip4, sep1.epg.rd),
2779 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
2780 sep2.ip4, sep2.epg.rd)]),
2782 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2783 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
2784 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
2785 sep3.ip6, sep3.epg.rd),
2786 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
2787 sep4.ip6, sep4.epg.rd)])])
2790 c2 = VppGbpContract(
2791 self, 222, 220, acl_index,
2792 [VppGbpContractRule(
2793 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2794 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
2795 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
2796 sep1.ip4, sep1.epg.rd),
2797 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
2798 sep2.ip4, sep2.epg.rd)]),
2800 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2801 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
2802 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
2803 sep3.ip6, sep3.epg.rd),
2804 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
2805 sep4.ip6, sep4.epg.rd)])])
2809 # send again with the contract preset, now packets arrive
2810 # at SEP1 for both directions
2812 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
2815 self.assertEqual(rx[Ether].src, routed_src_mac)
2816 self.assertEqual(rx[Ether].dst, sep1.mac)
2817 self.assertEqual(rx[IP].src, ep1.ip4.address)
2818 self.assertEqual(rx[IP].dst, ep3.ip4.address)
2820 rxs = self.send_and_expect(self.pg2, p4[1] * 17, sep1.itf)
2823 self.assertEqual(rx[Ether].src, routed_src_mac)
2824 self.assertEqual(rx[Ether].dst, sep1.mac)
2825 self.assertEqual(rx[IP].src, ep3.ip4.address)
2826 self.assertEqual(rx[IP].dst, ep1.ip4.address)
2829 # programme the unknown EP for the L3 tests
2831 sep4.add_vpp_config()
2834 # an L3 switch packet between local EPs in different EPGs
2835 # different dest ports on each so the are LB hashed differently
2837 p4 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
2838 IP(src=ep1.ip4.address, dst=ep2.ip4.address) /
2839 UDP(sport=1234, dport=1234) /
2841 (Ether(src=ep2.mac, dst=str(self.router_mac)) /
2842 IP(src=ep2.ip4.address, dst=ep1.ip4.address) /
2843 UDP(sport=1234, dport=1234) /
2845 p6 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
2846 IPv6(src=ep1.ip6.address, dst=ep2.ip6.address) /
2847 UDP(sport=1234, dport=1234) /
2849 (Ether(src=ep2.mac, dst=str(self.router_mac)) /
2850 IPv6(src=ep2.ip6.address, dst=ep1.ip6.address) /
2851 UDP(sport=1234, dport=1234) /
2854 c3 = VppGbpContract(
2855 self, 220, 221, acl_index,
2856 [VppGbpContractRule(
2857 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2858 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
2859 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
2860 sep1.ip4, sep1.epg.rd),
2861 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
2862 sep2.ip4, sep2.epg.rd)]),
2864 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2865 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
2866 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
2867 sep3.ip6, sep3.epg.rd),
2868 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
2869 sep4.ip6, sep4.epg.rd)])])
2872 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
2875 self.assertEqual(rx[Ether].src, routed_src_mac)
2876 self.assertEqual(rx[Ether].dst, sep1.mac)
2877 self.assertEqual(rx[IP].src, ep1.ip4.address)
2878 self.assertEqual(rx[IP].dst, ep2.ip4.address)
2881 # learn a remote EP in EPG 221
2883 vx_tun_l3 = VppGbpVxlanTunnel(
2884 self, 444, rd1.rd_id,
2885 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3)
2886 vx_tun_l3.add_vpp_config()
2888 c4 = VppGbpContract(
2889 self, 221, 220, acl_index,
2890 [VppGbpContractRule(
2891 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2894 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2898 p = (Ether(src=self.pg7.remote_mac,
2899 dst=self.pg7.local_mac) /
2900 IP(src=self.pg7.remote_ip4,
2901 dst=self.pg7.local_ip4) /
2902 UDP(sport=1234, dport=48879) /
2903 VXLAN(vni=444, gpid=221, flags=0x88) /
2904 Ether(src="00:22:22:22:22:33", dst=str(self.router_mac)) /
2905 IP(src="10.0.0.88", dst=ep1.ip4.address) /
2906 UDP(sport=1234, dport=1234) /
2909 rx = self.send_and_expect(self.pg7, [p], self.pg0)
2911 # endpoint learnt via the parent GBP-vxlan interface
2912 self.assertTrue(find_gbp_endpoint(self,
2913 vx_tun_l3._sw_if_index,
2916 p = (Ether(src=self.pg7.remote_mac,
2917 dst=self.pg7.local_mac) /
2918 IP(src=self.pg7.remote_ip4,
2919 dst=self.pg7.local_ip4) /
2920 UDP(sport=1234, dport=48879) /
2921 VXLAN(vni=444, gpid=221, flags=0x88) /
2922 Ether(src="00:22:22:22:22:33", dst=str(self.router_mac)) /
2923 IPv6(src="2001:10::88", dst=ep1.ip6.address) /
2924 UDP(sport=1234, dport=1234) /
2927 rx = self.send_and_expect(self.pg7, [p], self.pg0)
2929 # endpoint learnt via the parent GBP-vxlan interface
2930 self.assertTrue(find_gbp_endpoint(self,
2931 vx_tun_l3._sw_if_index,
2935 # L3 switch from local to remote EP
2937 p4 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
2938 IP(src=ep1.ip4.address, dst="10.0.0.88") /
2939 UDP(sport=1234, dport=1234) /
2941 p6 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
2942 IPv6(src=ep1.ip6.address, dst="2001:10::88") /
2943 UDP(sport=1234, dport=1234) /
2946 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
2949 self.assertEqual(rx[Ether].src, routed_src_mac)
2950 self.assertEqual(rx[Ether].dst, sep1.mac)
2951 self.assertEqual(rx[IP].src, ep1.ip4.address)
2952 self.assertEqual(rx[IP].dst, "10.0.0.88")
2954 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep4.itf)
2957 self.assertEqual(rx[Ether].src, routed_src_mac)
2958 self.assertEqual(rx[Ether].dst, sep4.mac)
2959 self.assertEqual(rx[IPv6].src, ep1.ip6.address)
2960 self.assertEqual(rx[IPv6].dst, "2001:10::88")
2963 # test the dst-ip hash mode
2965 c5 = VppGbpContract(
2966 self, 220, 221, acl_index,
2967 [VppGbpContractRule(
2968 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2969 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
2970 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
2971 sep1.ip4, sep1.epg.rd),
2972 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
2973 sep2.ip4, sep2.epg.rd)]),
2975 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2976 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
2977 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
2978 sep3.ip6, sep3.epg.rd),
2979 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
2980 sep4.ip6, sep4.epg.rd)])])
2983 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
2986 self.assertEqual(rx[Ether].src, routed_src_mac)
2987 self.assertEqual(rx[Ether].dst, sep1.mac)
2988 self.assertEqual(rx[IP].src, ep1.ip4.address)
2989 self.assertEqual(rx[IP].dst, "10.0.0.88")
2991 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep3.itf)
2994 self.assertEqual(rx[Ether].src, routed_src_mac)
2995 self.assertEqual(rx[Ether].dst, sep3.mac)
2996 self.assertEqual(rx[IPv6].src, ep1.ip6.address)
2997 self.assertEqual(rx[IPv6].dst, "2001:10::88")
3002 self.pg7.unconfig_ip4()
3004 def test_gbp_l3_out(self):
3007 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
3008 self.vapi.cli("set logging class gbp debug")
3010 routed_dst_mac = "00:0c:0c:0c:0c:0c"
3011 routed_src_mac = "00:22:bd:f8:19:ff"
3016 t4 = VppIpTable(self, 1)
3018 t6 = VppIpTable(self, 1, True)
3021 rd1 = VppGbpRouteDomain(self, 2, t4, t6)
3022 rd1.add_vpp_config()
3024 self.loop0.set_mac(self.router_mac)
3027 # Bind the BVI to the RD
3029 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
3030 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
3033 # Pg7 hosts a BD's BUM
3034 # Pg1 some other l3 interface
3036 self.pg7.config_ip4()
3037 self.pg7.resolve_arp()
3040 # a GBP external bridge domains for the EPs
3042 bd1 = VppBridgeDomain(self, 1)
3043 bd1.add_vpp_config()
3044 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0)
3045 gbd1.add_vpp_config()
3048 # The Endpoint-groups in which the external endpoints exist
3050 epg_220 = VppGbpEndpointGroup(self, 220, rd1, gbd1,
3054 epg_220.add_vpp_config()
3056 # the BVIs have the subnets applied ...
3057 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 24)
3058 ip4_addr.add_vpp_config()
3059 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 64)
3060 ip6_addr.add_vpp_config()
3062 # ... which are L3-out subnets
3063 l3o_1 = VppGbpSubnet(
3064 self, rd1, "10.0.0.0", 24,
3065 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3067 l3o_1.add_vpp_config()
3070 # an external interface attached to the outside world and the
3073 vlan_100 = VppDot1QSubint(self, self.pg0, 100)
3075 ext_itf = VppGbpExtItf(self, vlan_100, bd1, rd1)
3076 ext_itf.add_vpp_config()
3079 # a multicast vxlan-gbp tunnel for broadcast in the BD
3081 tun_bm = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
3084 tun_bm.add_vpp_config()
3085 bp_bm = VppBridgeDomainPort(self, bd1, tun_bm,
3086 port_type=L2_PORT_TYPE.NORMAL)
3087 bp_bm.add_vpp_config()
3090 # an unicast vxlan-gbp for inter-BD traffic
3092 vx_tun_l3 = VppGbpVxlanTunnel(
3093 self, 444, rd1.rd_id,
3094 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3)
3095 vx_tun_l3.add_vpp_config()
3098 # packets destined to unkown addresses in the BVI's subnet
3101 p4 = (Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
3103 IP(src="10.0.0.1", dst="10.0.0.88") /
3104 UDP(sport=1234, dport=1234) /
3106 p6 = (Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
3108 IPv6(src="2001:10::1", dst="2001:10::88") /
3109 UDP(sport=1234, dport=1234) /
3112 rxs = self.send_and_expect(self.pg0, p4 * 1, self.pg7)
3115 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3116 # self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3117 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3118 self.assertEqual(rx[IP].dst, "239.1.1.1")
3119 self.assertEqual(rx[VXLAN].vni, 88)
3120 self.assertTrue(rx[VXLAN].flags.G)
3121 self.assertTrue(rx[VXLAN].flags.Instance)
3122 # policy is not applied since we don't know where it's going
3123 self.assertFalse(rx[VXLAN].gpflags.A)
3124 self.assertFalse(rx[VXLAN].gpflags.D)
3126 inner = rx[VXLAN].payload
3128 self.assertTrue(inner.haslayer(ARP))
3131 # An external Endpoint
3133 eep = VppGbpEndpoint(self, vlan_100,
3135 "10.0.0.1", "11.0.0.1",
3136 "2001:10::1", "3001::1",
3137 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
3138 eep.add_vpp_config()
3143 rep = VppGbpEndpoint(self, vx_tun_l3,
3145 "10.0.0.101", "11.0.0.101",
3146 "2001:10::101", "3001::101",
3147 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
3149 self.pg7.remote_ip4,
3151 rep.add_vpp_config()
3154 # remote to external
3156 p = (Ether(src=self.pg7.remote_mac,
3157 dst=self.pg7.local_mac) /
3158 IP(src=self.pg7.remote_ip4,
3159 dst=self.pg7.local_ip4) /
3160 UDP(sport=1234, dport=48879) /
3161 VXLAN(vni=444, gpid=220, flags=0x88) /
3162 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
3163 IP(src="10.0.0.101", dst="10.0.0.1") /
3164 UDP(sport=1234, dport=1234) /
3167 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
3170 # A subnet reachable through the external EP
3172 ip_220 = VppIpRoute(self, "10.220.0.0", 24,
3173 [VppRoutePath(eep.ip4.address,
3174 eep.epg.bvi.sw_if_index)],
3175 table_id=t4.table_id)
3176 ip_220.add_vpp_config()
3178 l3o_220 = VppGbpSubnet(
3179 self, rd1, "10.220.0.0", 24,
3180 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3182 l3o_220.add_vpp_config()
3184 p = (Ether(src=self.pg7.remote_mac,
3185 dst=self.pg7.local_mac) /
3186 IP(src=self.pg7.remote_ip4,
3187 dst=self.pg7.local_ip4) /
3188 UDP(sport=1234, dport=48879) /
3189 VXLAN(vni=444, gpid=220, flags=0x88) /
3190 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
3191 IP(src="10.0.0.101", dst="10.220.0.1") /
3192 UDP(sport=1234, dport=1234) /
3195 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
3198 # another external subnet, this time in a different EPG
3200 ip_200 = VppIpRoute(self, "10.200.0.0", 24,
3201 [VppRoutePath(eep.ip4.address,
3202 eep.epg.bvi.sw_if_index)],
3203 table_id=t4.table_id)
3204 ip_200.add_vpp_config()
3206 l3o_200 = VppGbpSubnet(
3207 self, rd1, "10.200.0.0", 24,
3208 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3210 l3o_200.add_vpp_config()
3212 p = (Ether(src=self.pg7.remote_mac,
3213 dst=self.pg7.local_mac) /
3214 IP(src=self.pg7.remote_ip4,
3215 dst=self.pg7.local_ip4) /
3216 UDP(sport=1234, dport=48879) /
3217 VXLAN(vni=444, gpid=220, flags=0x88) /
3218 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
3219 IP(src="10.0.0.101", dst="10.200.0.1") /
3220 UDP(sport=1234, dport=1234) /
3224 # packets dropped due to lack of contract.
3226 rxs = self.send_and_assert_no_replies(self.pg7, p * 1)
3229 # from the the subnet in EPG 220 beyond the external to remote
3231 p4 = (Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
3233 IP(src="10.220.0.1", dst=rep.ip4.address) /
3234 UDP(sport=1234, dport=1234) /
3237 rxs = self.send_and_expect(self.pg0, p4 * 1, self.pg7)
3240 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3241 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3242 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3243 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
3244 self.assertEqual(rx[VXLAN].vni, 444)
3245 self.assertTrue(rx[VXLAN].flags.G)
3246 self.assertTrue(rx[VXLAN].flags.Instance)
3247 self.assertTrue(rx[VXLAN].gpflags.A)
3248 self.assertFalse(rx[VXLAN].gpflags.D)
3251 # from the the subnet in EPG 200 beyond the external to remote
3252 # dropped due to no contract
3254 p4 = (Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
3256 IP(src="10.200.0.1", dst=rep.ip4.address) /
3257 UDP(sport=1234, dport=1234) /
3260 rxs = self.send_and_assert_no_replies(self.pg0, p4 * 1)
3265 acl = VppGbpAcl(self)
3266 rule = acl.create_rule(permit_deny=1, proto=17)
3267 rule2 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
3268 acl_index = acl.add_vpp_config([rule, rule2])
3269 c1 = VppGbpContract(
3270 self, 200, 220, acl_index,
3271 [VppGbpContractRule(
3272 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3275 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3279 rxs = self.send_and_expect(self.pg0, p4 * 1, self.pg7)
3282 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3283 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3284 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3285 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
3286 self.assertEqual(rx[VXLAN].vni, 444)
3287 self.assertTrue(rx[VXLAN].flags.G)
3288 self.assertTrue(rx[VXLAN].flags.Instance)
3289 self.assertTrue(rx[VXLAN].gpflags.A)
3290 self.assertFalse(rx[VXLAN].gpflags.D)
3295 self.pg7.unconfig_ip4()
3298 if __name__ == '__main__':
3299 unittest.main(testRunner=VppTestRunner)