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
27 from scapy.data import ETH_P_IP, ETH_P_IPV6
29 from socket import AF_INET, AF_INET6
30 from scapy.utils import inet_pton, inet_ntop
31 from vpp_papi_provider import L2_VTR_OP
34 def find_gbp_endpoint(test, sw_if_index=None, ip=None, mac=None):
36 vip = VppIpAddress(ip)
38 vmac = MACAddress(mac)
40 eps = test.vapi.gbp_endpoint_dump()
44 if ep.endpoint.sw_if_index != sw_if_index:
47 for eip in ep.endpoint.ips:
51 if vmac.packed == ep.endpoint.mac:
56 def find_gbp_vxlan(test, vni):
57 ts = test.vapi.gbp_vxlan_tunnel_dump()
59 if t.tunnel.vni == vni:
64 class VppGbpEndpoint(VppObject):
75 return self.itf.remote_mac
95 return [self.ip4, self.ip6]
99 return [self.fip4, self.fip6]
101 def __init__(self, test, itf, epg, recirc, ip4, fip4, ip6, fip6,
111 self._ip4 = VppIpAddress(ip4)
112 self._fip4 = VppIpAddress(fip4)
113 self._ip6 = VppIpAddress(ip6)
114 self._fip6 = VppIpAddress(fip6)
117 self.vmac = MACAddress(self.itf.remote_mac)
119 self.vmac = MACAddress("00:00:00:00:00:00")
122 self.tun_src = VppIpAddress(tun_src)
123 self.tun_dst = VppIpAddress(tun_dst)
125 def add_vpp_config(self):
126 res = self._test.vapi.gbp_endpoint_add(
127 self.itf.sw_if_index,
128 [self.ip4.encode(), self.ip6.encode()],
132 self.tun_src.encode(),
133 self.tun_dst.encode())
134 self.handle = res.handle
135 self._test.registry.register(self, self._test.logger)
137 def remove_vpp_config(self):
138 self._test.vapi.gbp_endpoint_del(self.handle)
141 return self.object_id()
144 return "gbp-endpoint:[%d==%d:%s:%d]" % (self.handle,
145 self.itf.sw_if_index,
149 def query_vpp_config(self):
150 return find_gbp_endpoint(self._test,
151 self.itf.sw_if_index,
155 class VppGbpRecirc(VppObject):
157 GBP Recirculation Interface
160 def __init__(self, test, epg, recirc, is_ext=False):
166 def add_vpp_config(self):
167 self._test.vapi.gbp_recirc_add_del(
169 self.recirc.sw_if_index,
172 self._test.registry.register(self, self._test.logger)
174 def remove_vpp_config(self):
175 self._test.vapi.gbp_recirc_add_del(
177 self.recirc.sw_if_index,
182 return self.object_id()
185 return "gbp-recirc:[%d]" % (self.recirc.sw_if_index)
187 def query_vpp_config(self):
188 rs = self._test.vapi.gbp_recirc_dump()
190 if r.recirc.sw_if_index == self.recirc.sw_if_index:
195 class VppGbpExtItf(VppObject):
197 GBP ExtItfulation Interface
200 def __init__(self, test, itf, bd, rd):
206 def add_vpp_config(self):
207 self._test.vapi.gbp_ext_itf_add_del(
209 self.itf.sw_if_index,
212 self._test.registry.register(self, self._test.logger)
214 def remove_vpp_config(self):
215 self._test.vapi.gbp_ext_itf_add_del(
217 self.itf.sw_if_index,
222 return self.object_id()
225 return "gbp-ext-itf:[%d]" % (self.itf.sw_if_index)
227 def query_vpp_config(self):
228 rs = self._test.vapi.gbp_ext_itf_dump()
230 if r.ext_itf.sw_if_index == self.itf.sw_if_index:
235 class VppGbpSubnet(VppObject):
239 def __init__(self, test, rd, address, address_len,
240 type, sw_if_index=None, epg=None):
242 self.rd_id = rd.rd_id
243 self.prefix = VppIpPrefix(address, address_len)
245 self.sw_if_index = sw_if_index
248 def add_vpp_config(self):
249 self._test.vapi.gbp_subnet_add_del(
252 self.prefix.encode(),
254 sw_if_index=self.sw_if_index if self.sw_if_index else 0xffffffff,
255 epg_id=self.epg if self.epg else 0xffff)
256 self._test.registry.register(self, self._test.logger)
258 def remove_vpp_config(self):
259 self._test.vapi.gbp_subnet_add_del(
262 self.prefix.encode(),
266 return self.object_id()
269 return "gbp-subnet:[%d-%s]" % (self.rd_id, self.prefix)
271 def query_vpp_config(self):
272 ss = self._test.vapi.gbp_subnet_dump()
274 if s.subnet.rd_id == self.rd_id and \
275 s.subnet.type == self.type and \
276 s.subnet.prefix == self.prefix:
281 class VppGbpEndpointGroup(VppObject):
286 def __init__(self, test, epg, rd, bd, uplink,
287 bvi, bvi_ip4, bvi_ip6=None):
291 self.bvi_ip4 = VppIpAddress(bvi_ip4)
292 self.bvi_ip6 = VppIpAddress(bvi_ip6)
297 def add_vpp_config(self):
298 self._test.vapi.gbp_endpoint_group_add(
302 self.uplink.sw_if_index if self.uplink else INDEX_INVALID)
303 self._test.registry.register(self, self._test.logger)
305 def remove_vpp_config(self):
306 self._test.vapi.gbp_endpoint_group_del(
310 return self.object_id()
313 return "gbp-endpoint-group:[%d]" % (self.epg)
315 def query_vpp_config(self):
316 epgs = self._test.vapi.gbp_endpoint_group_dump()
318 if epg.epg.epg_id == self.epg:
323 class VppGbpBridgeDomain(VppObject):
328 def __init__(self, test, bd, bvi, uu_flood=None, learn=True):
331 self.uu_flood = uu_flood
334 e = VppEnum.vl_api_gbp_bridge_domain_flags_t
336 self.learn = e.GBP_BD_API_FLAG_NONE
338 self.learn = e.GBP_BD_API_FLAG_DO_NOT_LEARN
340 def add_vpp_config(self):
341 self._test.vapi.gbp_bridge_domain_add(
344 self.bvi.sw_if_index,
345 self.uu_flood.sw_if_index if self.uu_flood else INDEX_INVALID)
346 self._test.registry.register(self, self._test.logger)
348 def remove_vpp_config(self):
349 self._test.vapi.gbp_bridge_domain_del(self.bd.bd_id)
352 return self.object_id()
355 return "gbp-bridge-domain:[%d]" % (self.bd.bd_id)
357 def query_vpp_config(self):
358 bds = self._test.vapi.gbp_bridge_domain_dump()
360 if bd.bd.bd_id == self.bd.bd_id:
365 class VppGbpRouteDomain(VppObject):
370 def __init__(self, test, rd_id, t4, t6, ip4_uu=None, ip6_uu=None):
378 def add_vpp_config(self):
379 self._test.vapi.gbp_route_domain_add(
383 self.ip4_uu.sw_if_index if self.ip4_uu else INDEX_INVALID,
384 self.ip6_uu.sw_if_index if self.ip6_uu else INDEX_INVALID)
385 self._test.registry.register(self, self._test.logger)
387 def remove_vpp_config(self):
388 self._test.vapi.gbp_route_domain_del(self.rd_id)
391 return self.object_id()
394 return "gbp-route-domain:[%d]" % (self.rd_id)
396 def query_vpp_config(self):
397 rds = self._test.vapi.gbp_route_domain_dump()
399 if rd.rd.rd_id == self.rd_id:
404 class VppGbpContractNextHop():
405 def __init__(self, mac, bd, ip, rd):
412 return {'ip': self.ip.encode(),
413 'mac': self.mac.packed,
414 'bd_id': self.bd.bd.bd_id,
415 'rd_id': self.rd.rd_id}
418 class VppGbpContractRule():
419 def __init__(self, action, hash_mode, nhs=[]):
421 self.hash_mode = hash_mode
427 nhs.append(nh.encode())
430 return {'action': self.action,
432 'hash_mode': self.hash_mode,
433 'n_nhs': len(self.nhs),
437 class VppGbpContract(VppObject):
442 def __init__(self, test, src_epg, dst_epg, acl_index,
443 rules, allowed_ethertypes):
445 self.acl_index = acl_index
446 self.src_epg = src_epg
447 self.dst_epg = dst_epg
449 self.allowed_ethertypes = allowed_ethertypes
451 def add_vpp_config(self):
454 rules.append(r.encode())
455 self._test.vapi.gbp_contract_add_del(
461 self.allowed_ethertypes)
462 self._test.registry.register(self, self._test.logger)
464 def remove_vpp_config(self):
465 self._test.vapi.gbp_contract_add_del(
473 return self.object_id()
476 return "gbp-contract:[%d:%s:%d]" % (self.src_epg,
480 def query_vpp_config(self):
481 cs = self._test.vapi.gbp_contract_dump()
483 if c.contract.src_epg == self.src_epg \
484 and c.contract.dst_epg == self.dst_epg:
489 class VppGbpVxlanTunnel(VppInterface):
494 def __init__(self, test, vni, bd_rd_id, mode):
495 super(VppGbpVxlanTunnel, self).__init__(test)
498 self.bd_rd_id = bd_rd_id
501 def add_vpp_config(self):
502 r = self._test.vapi.gbp_vxlan_tunnel_add(
506 self.set_sw_if_index(r.sw_if_index)
507 self._test.registry.register(self, self._test.logger)
509 def remove_vpp_config(self):
510 self._test.vapi.gbp_vxlan_tunnel_del(self.vni)
513 return self.object_id()
516 return "gbp-vxlan:%d" % (self.vni)
518 def query_vpp_config(self):
519 return find_gbp_vxlan(self._test, self.vni)
522 class VppGbpAcl(VppObject):
527 def __init__(self, test):
529 self.acl_index = 4294967295
531 def create_rule(self, is_ipv6=0, permit_deny=0, proto=-1,
532 s_prefix=0, s_ip='\x00\x00\x00\x00', sport_from=0,
533 sport_to=65535, d_prefix=0, d_ip='\x00\x00\x00\x00',
534 dport_from=0, dport_to=65535):
535 if proto == -1 or proto == 0:
538 elif proto == 1 or proto == 58:
541 rule = ({'is_permit': permit_deny, 'is_ipv6': is_ipv6, 'proto': proto,
542 'srcport_or_icmptype_first': sport_from,
543 'srcport_or_icmptype_last': sport_to,
544 'src_ip_prefix_len': s_prefix,
546 'dstport_or_icmpcode_first': dport_from,
547 'dstport_or_icmpcode_last': dport_to,
548 'dst_ip_prefix_len': d_prefix,
549 'dst_ip_addr': d_ip})
552 def add_vpp_config(self, rules):
554 reply = self._test.vapi.acl_add_replace(self.acl_index,
557 self.acl_index = reply.acl_index
558 return self.acl_index
560 def remove_vpp_config(self):
561 self._test.vapi.acl_del(self.acl_index)
564 return self.object_id()
567 return "gbp-acl:[%d]" % (self.acl_index)
569 def query_vpp_config(self):
570 cs = self._test.vapi.acl_dump()
572 if c.acl_index == self.acl_index:
577 class TestGBP(VppTestCase):
578 """ GBP Test Case """
581 super(TestGBP, self).setUp()
583 self.create_pg_interfaces(range(9))
584 self.create_loopback_interfaces(8)
586 self.router_mac = MACAddress("00:11:22:33:44:55")
588 for i in self.pg_interfaces:
590 for i in self.lo_interfaces:
594 for i in self.pg_interfaces:
597 super(TestGBP, self).tearDown()
599 def send_and_expect_bridged(self, src, tx, dst):
600 rx = self.send_and_expect(src, tx, dst)
603 self.assertEqual(r[Ether].src, tx[0][Ether].src)
604 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
605 self.assertEqual(r[IP].src, tx[0][IP].src)
606 self.assertEqual(r[IP].dst, tx[0][IP].dst)
609 def send_and_expect_bridged6(self, src, tx, dst):
610 rx = self.send_and_expect(src, tx, dst)
613 self.assertEqual(r[Ether].src, tx[0][Ether].src)
614 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
615 self.assertEqual(r[IPv6].src, tx[0][IPv6].src)
616 self.assertEqual(r[IPv6].dst, tx[0][IPv6].dst)
619 def send_and_expect_routed(self, src, tx, dst, src_mac):
620 rx = self.send_and_expect(src, tx, dst)
623 self.assertEqual(r[Ether].src, src_mac)
624 self.assertEqual(r[Ether].dst, dst.remote_mac)
625 self.assertEqual(r[IP].src, tx[0][IP].src)
626 self.assertEqual(r[IP].dst, tx[0][IP].dst)
629 def send_and_expect_natted(self, src, tx, dst, src_ip):
630 rx = self.send_and_expect(src, tx, dst)
633 self.assertEqual(r[Ether].src, tx[0][Ether].src)
634 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
635 self.assertEqual(r[IP].src, src_ip)
636 self.assertEqual(r[IP].dst, tx[0][IP].dst)
639 def send_and_expect_natted6(self, src, tx, dst, src_ip):
640 rx = self.send_and_expect(src, tx, dst)
643 self.assertEqual(r[Ether].src, tx[0][Ether].src)
644 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
645 self.assertEqual(r[IPv6].src, src_ip)
646 self.assertEqual(r[IPv6].dst, tx[0][IPv6].dst)
649 def send_and_expect_unnatted(self, src, tx, dst, dst_ip):
650 rx = self.send_and_expect(src, tx, dst)
653 self.assertEqual(r[Ether].src, tx[0][Ether].src)
654 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
655 self.assertEqual(r[IP].dst, dst_ip)
656 self.assertEqual(r[IP].src, tx[0][IP].src)
659 def send_and_expect_unnatted6(self, src, tx, dst, dst_ip):
660 rx = self.send_and_expect(src, tx, dst)
663 self.assertEqual(r[Ether].src, tx[0][Ether].src)
664 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
665 self.assertEqual(r[IPv6].dst, dst_ip)
666 self.assertEqual(r[IPv6].src, tx[0][IPv6].src)
669 def send_and_expect_double_natted(self, src, tx, dst, src_ip, dst_ip):
670 rx = self.send_and_expect(src, tx, dst)
673 self.assertEqual(r[Ether].src, str(self.router_mac))
674 self.assertEqual(r[Ether].dst, dst.remote_mac)
675 self.assertEqual(r[IP].dst, dst_ip)
676 self.assertEqual(r[IP].src, src_ip)
679 def send_and_expect_double_natted6(self, src, tx, dst, src_ip, dst_ip):
680 rx = self.send_and_expect(src, tx, dst)
683 self.assertEqual(r[Ether].src, str(self.router_mac))
684 self.assertEqual(r[Ether].dst, dst.remote_mac)
685 self.assertEqual(r[IPv6].dst, dst_ip)
686 self.assertEqual(r[IPv6].src, src_ip)
690 """ Group Based Policy """
692 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
697 bd1 = VppBridgeDomain(self, 1)
698 bd2 = VppBridgeDomain(self, 2)
699 bd20 = VppBridgeDomain(self, 20)
703 bd20.add_vpp_config()
705 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0)
706 gbd2 = VppGbpBridgeDomain(self, bd2, self.loop1)
707 gbd20 = VppGbpBridgeDomain(self, bd20, self.loop2)
709 gbd1.add_vpp_config()
710 gbd2.add_vpp_config()
711 gbd20.add_vpp_config()
716 gt4 = VppIpTable(self, 0)
718 gt6 = VppIpTable(self, 0, is_ip6=True)
720 nt4 = VppIpTable(self, 20)
722 nt6 = VppIpTable(self, 20, is_ip6=True)
725 rd0 = VppGbpRouteDomain(self, 0, gt4, gt6, None, None)
726 rd20 = VppGbpRouteDomain(self, 20, nt4, nt6, None, None)
729 rd20.add_vpp_config()
732 # 3 EPGs, 2 of which share a BD.
733 # 2 NAT EPGs, one for floating-IP subnets, the other for internet
735 epgs = [VppGbpEndpointGroup(self, 220, rd0, gbd1, self.pg4,
739 VppGbpEndpointGroup(self, 221, rd0, gbd1, self.pg5,
743 VppGbpEndpointGroup(self, 222, rd0, gbd2, self.pg6,
747 VppGbpEndpointGroup(self, 333, rd20, gbd20, self.pg7,
751 VppGbpEndpointGroup(self, 444, rd20, gbd20, self.pg8,
755 recircs = [VppGbpRecirc(self, epgs[0],
757 VppGbpRecirc(self, epgs[1],
759 VppGbpRecirc(self, epgs[2],
761 VppGbpRecirc(self, epgs[3],
762 self.loop6, is_ext=True),
763 VppGbpRecirc(self, epgs[4],
764 self.loop7, is_ext=True)]
767 recirc_nat = recircs[3]
770 # 4 end-points, 2 in the same subnet, 3 in the same BD
772 eps = [VppGbpEndpoint(self, self.pg0,
774 "10.0.0.1", "11.0.0.1",
775 "2001:10::1", "3001::1"),
776 VppGbpEndpoint(self, self.pg1,
778 "10.0.0.2", "11.0.0.2",
779 "2001:10::2", "3001::2"),
780 VppGbpEndpoint(self, self.pg2,
782 "10.0.1.1", "11.0.0.3",
783 "2001:10:1::1", "3001::3"),
784 VppGbpEndpoint(self, self.pg3,
786 "10.0.2.1", "11.0.0.4",
787 "2001:10:2::1", "3001::4")]
790 # Config related to each of the EPGs
793 # IP config on the BVI interfaces
794 if epg != epgs[1] and epg != epgs[4]:
795 VppIpInterfaceBind(self, epg.bvi, epg.rd.t4).add_vpp_config()
796 VppIpInterfaceBind(self, epg.bvi, epg.rd.t6).add_vpp_config()
797 self.vapi.sw_interface_set_mac_address(
799 self.router_mac.packed)
801 # The BVIs are NAT inside interfaces
802 self.vapi.nat44_interface_add_del_feature(epg.bvi.sw_if_index,
805 self.vapi.nat66_add_del_interface(epg.bvi.sw_if_index,
809 if_ip4 = VppIpInterfaceAddress(self, epg.bvi, epg.bvi_ip4, 32)
810 if_ip6 = VppIpInterfaceAddress(self, epg.bvi, epg.bvi_ip6, 128)
811 if_ip4.add_vpp_config()
812 if_ip6.add_vpp_config()
814 # EPG uplink interfaces in the RD
815 VppIpInterfaceBind(self, epg.uplink, epg.rd.t4).add_vpp_config()
816 VppIpInterfaceBind(self, epg.uplink, epg.rd.t6).add_vpp_config()
818 # add the BD ARP termination entry for BVI IP
819 epg.bd_arp_ip4 = VppBridgeDomainArpEntry(self, epg.bd.bd,
820 str(self.router_mac),
822 epg.bd_arp_ip6 = VppBridgeDomainArpEntry(self, epg.bd.bd,
823 str(self.router_mac),
825 epg.bd_arp_ip4.add_vpp_config()
826 epg.bd_arp_ip6.add_vpp_config()
831 for recirc in recircs:
832 # EPG's ingress recirculation interface maps to its RD
833 VppIpInterfaceBind(self, recirc.recirc,
834 recirc.epg.rd.t4).add_vpp_config()
835 VppIpInterfaceBind(self, recirc.recirc,
836 recirc.epg.rd.t6).add_vpp_config()
838 self.vapi.nat44_interface_add_del_feature(
839 recirc.recirc.sw_if_index,
842 self.vapi.nat66_add_del_interface(
843 recirc.recirc.sw_if_index,
847 recirc.add_vpp_config()
849 for recirc in recircs:
850 self.assertTrue(find_bridge_domain_port(self,
851 recirc.epg.bd.bd.bd_id,
852 recirc.recirc.sw_if_index))
855 self.pg_enable_capture(self.pg_interfaces)
858 # routes to the endpoints. We need these since there are no
859 # adj-fibs due to the fact the the BVI address has /32 and
860 # the subnet is not attached.
862 for (ip, fip) in zip(ep.ips, ep.fips):
863 # Add static mappings for each EP from the 10/8 to 11/8 network
865 self.vapi.nat44_add_del_static_mapping(ip.bytes,
870 self.vapi.nat66_add_del_static_mapping(ip.bytes,
877 self.logger.info(self.vapi.cli("sh gbp endpoint"))
879 # ... results in a Gratuitous ARP/ND on the EPG's uplink
880 rx = ep.epg.uplink.get_capture(len(ep.ips), timeout=0.2)
882 for ii, ip in enumerate(ep.ips):
886 self.assertTrue(p.haslayer(ICMPv6ND_NA))
887 self.assertEqual(p[ICMPv6ND_NA].tgt, ip.address)
889 self.assertTrue(p.haslayer(ARP))
890 self.assertEqual(p[ARP].psrc, ip.address)
891 self.assertEqual(p[ARP].pdst, ip.address)
893 # add the BD ARP termination entry for floating IP
895 ba = VppBridgeDomainArpEntry(self, epg_nat.bd.bd, ep.mac, fip)
898 # floating IPs route via EPG recirc
899 r = VppIpRoute(self, fip.address, fip.length,
900 [VppRoutePath(fip.address,
901 ep.recirc.recirc.sw_if_index,
903 proto=fip.dpo_proto)],
908 # L2 FIB entries in the NAT EPG BD to bridge the packets from
909 # the outside direct to the internal EPG
910 lf = VppL2FibEntry(self, epg_nat.bd.bd, ep.mac,
911 ep.recirc.recirc, bvi_mac=0)
915 # ARP packets for unknown IP are sent to the EPG uplink
917 pkt_arp = (Ether(dst="ff:ff:ff:ff:ff:ff",
918 src=self.pg0.remote_mac) /
920 hwdst="ff:ff:ff:ff:ff:ff",
921 hwsrc=self.pg0.remote_mac,
925 self.vapi.cli("clear trace")
926 self.pg0.add_stream(pkt_arp)
928 self.pg_enable_capture(self.pg_interfaces)
931 rxd = epgs[0].uplink.get_capture(1)
934 # ARP/ND packets get a response
936 pkt_arp = (Ether(dst="ff:ff:ff:ff:ff:ff",
937 src=self.pg0.remote_mac) /
939 hwdst="ff:ff:ff:ff:ff:ff",
940 hwsrc=self.pg0.remote_mac,
941 pdst=epgs[0].bvi_ip4.address,
942 psrc=eps[0].ip4.address))
944 self.send_and_expect(self.pg0, [pkt_arp], self.pg0)
946 nsma = in6_getnsma(inet_pton(AF_INET6, eps[0].ip6.address))
947 d = inet_ntop(AF_INET6, nsma)
948 pkt_nd = (Ether(dst=in6_getnsmac(nsma),
949 src=self.pg0.remote_mac) /
950 IPv6(dst=d, src=eps[0].ip6.address) /
951 ICMPv6ND_NS(tgt=epgs[0].bvi_ip6.address) /
952 ICMPv6NDOptSrcLLAddr(lladdr=self.pg0.remote_mac))
953 self.send_and_expect(self.pg0, [pkt_nd], self.pg0)
956 # broadcast packets are flooded
958 pkt_bcast = (Ether(dst="ff:ff:ff:ff:ff:ff",
959 src=self.pg0.remote_mac) /
960 IP(src=eps[0].ip4.address, dst="232.1.1.1") /
961 UDP(sport=1234, dport=1234) /
964 self.vapi.cli("clear trace")
965 self.pg0.add_stream(pkt_bcast)
967 self.pg_enable_capture(self.pg_interfaces)
970 rxd = eps[1].itf.get_capture(1)
971 self.assertEqual(rxd[0][Ether].dst, pkt_bcast[Ether].dst)
972 rxd = epgs[0].uplink.get_capture(1)
973 self.assertEqual(rxd[0][Ether].dst, pkt_bcast[Ether].dst)
976 # packets to non-local L3 destinations dropped
978 pkt_intra_epg_220_ip4 = (Ether(src=self.pg0.remote_mac,
979 dst=str(self.router_mac)) /
980 IP(src=eps[0].ip4.address,
982 UDP(sport=1234, dport=1234) /
984 pkt_inter_epg_222_ip4 = (Ether(src=self.pg0.remote_mac,
985 dst=str(self.router_mac)) /
986 IP(src=eps[0].ip4.address,
988 UDP(sport=1234, dport=1234) /
991 self.send_and_assert_no_replies(self.pg0, pkt_intra_epg_220_ip4 * 65)
993 pkt_inter_epg_222_ip6 = (Ether(src=self.pg0.remote_mac,
994 dst=str(self.router_mac)) /
995 IPv6(src=eps[0].ip6.address,
997 UDP(sport=1234, dport=1234) /
999 self.send_and_assert_no_replies(self.pg0, pkt_inter_epg_222_ip6 * 65)
1002 # Add the subnet routes
1005 self, rd0, "10.0.0.0", 24,
1006 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1008 self, rd0, "10.0.1.0", 24,
1009 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1011 self, rd0, "10.0.2.0", 24,
1012 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1014 self, rd0, "2001:10::1", 64,
1015 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1017 self, rd0, "2001:10:1::1", 64,
1018 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1020 self, rd0, "2001:10:2::1", 64,
1021 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1022 s41.add_vpp_config()
1023 s42.add_vpp_config()
1024 s43.add_vpp_config()
1025 s61.add_vpp_config()
1026 s62.add_vpp_config()
1027 s63.add_vpp_config()
1029 self.send_and_expect_bridged(eps[0].itf,
1030 pkt_intra_epg_220_ip4 * 65,
1032 self.send_and_expect_bridged(eps[0].itf,
1033 pkt_inter_epg_222_ip4 * 65,
1035 self.send_and_expect_bridged6(eps[0].itf,
1036 pkt_inter_epg_222_ip6 * 65,
1039 self.logger.info(self.vapi.cli("sh ip fib 11.0.0.2"))
1040 self.logger.info(self.vapi.cli("sh gbp endpoint-group"))
1041 self.logger.info(self.vapi.cli("sh gbp endpoint"))
1042 self.logger.info(self.vapi.cli("sh gbp recirc"))
1043 self.logger.info(self.vapi.cli("sh int"))
1044 self.logger.info(self.vapi.cli("sh int addr"))
1045 self.logger.info(self.vapi.cli("sh int feat loop6"))
1046 self.logger.info(self.vapi.cli("sh vlib graph ip4-gbp-src-classify"))
1047 self.logger.info(self.vapi.cli("sh int feat loop3"))
1048 self.logger.info(self.vapi.cli("sh int feat pg0"))
1051 # Packet destined to unknown unicast is sent on the epg uplink ...
1053 pkt_intra_epg_220_to_uplink = (Ether(src=self.pg0.remote_mac,
1054 dst="00:00:00:33:44:55") /
1055 IP(src=eps[0].ip4.address,
1057 UDP(sport=1234, dport=1234) /
1060 self.send_and_expect_bridged(eps[0].itf,
1061 pkt_intra_epg_220_to_uplink * 65,
1063 # ... and nowhere else
1064 self.pg1.get_capture(0, timeout=0.1)
1065 self.pg1.assert_nothing_captured(remark="Flood onto other VMS")
1067 pkt_intra_epg_221_to_uplink = (Ether(src=self.pg2.remote_mac,
1068 dst="00:00:00:33:44:66") /
1069 IP(src=eps[0].ip4.address,
1071 UDP(sport=1234, dport=1234) /
1074 self.send_and_expect_bridged(eps[2].itf,
1075 pkt_intra_epg_221_to_uplink * 65,
1079 # Packets from the uplink are forwarded in the absence of a contract
1081 pkt_intra_epg_220_from_uplink = (Ether(src="00:00:00:33:44:55",
1082 dst=self.pg0.remote_mac) /
1083 IP(src=eps[0].ip4.address,
1085 UDP(sport=1234, dport=1234) /
1088 self.send_and_expect_bridged(self.pg4,
1089 pkt_intra_epg_220_from_uplink * 65,
1093 # in the absence of policy, endpoints in the same EPG
1096 pkt_intra_epg = (Ether(src=self.pg0.remote_mac,
1097 dst=self.pg1.remote_mac) /
1098 IP(src=eps[0].ip4.address,
1099 dst=eps[1].ip4.address) /
1100 UDP(sport=1234, dport=1234) /
1103 self.send_and_expect_bridged(self.pg0, pkt_intra_epg * 65, self.pg1)
1106 # in the abscense of policy, endpoints in the different EPG
1107 # cannot communicate
1109 pkt_inter_epg_220_to_221 = (Ether(src=self.pg0.remote_mac,
1110 dst=self.pg2.remote_mac) /
1111 IP(src=eps[0].ip4.address,
1112 dst=eps[2].ip4.address) /
1113 UDP(sport=1234, dport=1234) /
1115 pkt_inter_epg_221_to_220 = (Ether(src=self.pg2.remote_mac,
1116 dst=self.pg0.remote_mac) /
1117 IP(src=eps[2].ip4.address,
1118 dst=eps[0].ip4.address) /
1119 UDP(sport=1234, dport=1234) /
1121 pkt_inter_epg_220_to_222 = (Ether(src=self.pg0.remote_mac,
1122 dst=str(self.router_mac)) /
1123 IP(src=eps[0].ip4.address,
1124 dst=eps[3].ip4.address) /
1125 UDP(sport=1234, dport=1234) /
1128 self.send_and_assert_no_replies(eps[0].itf,
1129 pkt_inter_epg_220_to_221 * 65)
1130 self.send_and_assert_no_replies(eps[0].itf,
1131 pkt_inter_epg_220_to_222 * 65)
1134 # A uni-directional contract from EPG 220 -> 221
1136 acl = VppGbpAcl(self)
1137 rule = acl.create_rule(permit_deny=1, proto=17)
1138 rule2 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
1139 acl_index = acl.add_vpp_config([rule, rule2])
1140 c1 = VppGbpContract(
1141 self, 220, 221, acl_index,
1142 [VppGbpContractRule(
1143 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1146 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1148 [ETH_P_IP, ETH_P_IPV6])
1151 self.send_and_expect_bridged(eps[0].itf,
1152 pkt_inter_epg_220_to_221 * 65,
1154 self.send_and_assert_no_replies(eps[0].itf,
1155 pkt_inter_epg_220_to_222 * 65)
1158 # contract for the return direction
1160 c2 = VppGbpContract(
1161 self, 221, 220, acl_index,
1162 [VppGbpContractRule(
1163 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1166 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1168 [ETH_P_IP, ETH_P_IPV6])
1171 self.send_and_expect_bridged(eps[0].itf,
1172 pkt_inter_epg_220_to_221 * 65,
1174 self.send_and_expect_bridged(eps[2].itf,
1175 pkt_inter_epg_221_to_220 * 65,
1179 # the contract does not allow non-IP
1181 pkt_non_ip_inter_epg_220_to_221 = (Ether(src=self.pg0.remote_mac,
1182 dst=self.pg2.remote_mac) /
1184 self.send_and_assert_no_replies(eps[0].itf,
1185 pkt_non_ip_inter_epg_220_to_221 * 17)
1188 # check that inter group is still disabled for the groups
1189 # not in the contract.
1191 self.send_and_assert_no_replies(eps[0].itf,
1192 pkt_inter_epg_220_to_222 * 65)
1195 # A uni-directional contract from EPG 220 -> 222 'L3 routed'
1197 c3 = VppGbpContract(
1198 self, 220, 222, acl_index,
1199 [VppGbpContractRule(
1200 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1203 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1205 [ETH_P_IP, ETH_P_IPV6])
1208 self.logger.info(self.vapi.cli("sh gbp contract"))
1210 self.send_and_expect_routed(eps[0].itf,
1211 pkt_inter_epg_220_to_222 * 65,
1213 str(self.router_mac))
1216 # remove both contracts, traffic stops in both directions
1218 c2.remove_vpp_config()
1219 c1.remove_vpp_config()
1220 c3.remove_vpp_config()
1221 acl.remove_vpp_config()
1223 self.send_and_assert_no_replies(eps[2].itf,
1224 pkt_inter_epg_221_to_220 * 65)
1225 self.send_and_assert_no_replies(eps[0].itf,
1226 pkt_inter_epg_220_to_221 * 65)
1227 self.send_and_expect_bridged(eps[0].itf,
1232 # EPs to the outside world
1235 # in the EP's RD an external subnet via the NAT EPG's recirc
1237 self, rd0, "0.0.0.0", 0,
1238 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1239 sw_if_index=recirc_nat.recirc.sw_if_index,
1242 self, rd0, "11.0.0.0", 8,
1243 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1244 sw_if_index=recirc_nat.recirc.sw_if_index,
1246 se16 = VppGbpSubnet(
1248 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1249 sw_if_index=recirc_nat.recirc.sw_if_index,
1251 # in the NAT RD an external subnet via the NAT EPG's uplink
1253 self, rd20, "0.0.0.0", 0,
1254 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1255 sw_if_index=epg_nat.uplink.sw_if_index,
1257 se36 = VppGbpSubnet(
1258 self, rd20, "::", 0,
1259 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1260 sw_if_index=epg_nat.uplink.sw_if_index,
1263 self, rd20, "11.0.0.0", 8,
1264 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1265 sw_if_index=epg_nat.uplink.sw_if_index,
1267 se1.add_vpp_config()
1268 se2.add_vpp_config()
1269 se16.add_vpp_config()
1270 se3.add_vpp_config()
1271 se36.add_vpp_config()
1272 se4.add_vpp_config()
1274 self.logger.info(self.vapi.cli("sh ip fib 0.0.0.0/0"))
1275 self.logger.info(self.vapi.cli("sh ip fib 11.0.0.1"))
1276 self.logger.info(self.vapi.cli("sh ip6 fib ::/0"))
1277 self.logger.info(self.vapi.cli("sh ip6 fib %s" %
1281 # From an EP to an outside addess: IN2OUT
1283 pkt_inter_epg_220_to_global = (Ether(src=self.pg0.remote_mac,
1284 dst=str(self.router_mac)) /
1285 IP(src=eps[0].ip4.address,
1287 UDP(sport=1234, dport=1234) /
1291 self.send_and_assert_no_replies(eps[0].itf,
1292 pkt_inter_epg_220_to_global * 65)
1294 acl2 = VppGbpAcl(self)
1295 rule = acl2.create_rule(permit_deny=1, proto=17, sport_from=1234,
1296 sport_to=1234, dport_from=1234, dport_to=1234)
1297 rule2 = acl2.create_rule(is_ipv6=1, permit_deny=1, proto=17,
1298 sport_from=1234, sport_to=1234,
1299 dport_from=1234, dport_to=1234)
1301 acl_index2 = acl2.add_vpp_config([rule, rule2])
1302 c4 = VppGbpContract(
1303 self, 220, 333, acl_index2,
1304 [VppGbpContractRule(
1305 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1308 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1310 [ETH_P_IP, ETH_P_IPV6])
1313 self.send_and_expect_natted(eps[0].itf,
1314 pkt_inter_epg_220_to_global * 65,
1316 eps[0].fip4.address)
1318 pkt_inter_epg_220_to_global = (Ether(src=self.pg0.remote_mac,
1319 dst=str(self.router_mac)) /
1320 IPv6(src=eps[0].ip6.address,
1322 UDP(sport=1234, dport=1234) /
1325 self.send_and_expect_natted6(self.pg0,
1326 pkt_inter_epg_220_to_global * 65,
1328 eps[0].fip6.address)
1331 # From a global address to an EP: OUT2IN
1333 pkt_inter_epg_220_from_global = (Ether(src=str(self.router_mac),
1334 dst=self.pg0.remote_mac) /
1335 IP(dst=eps[0].fip4.address,
1337 UDP(sport=1234, dport=1234) /
1340 self.send_and_assert_no_replies(self.pg7,
1341 pkt_inter_epg_220_from_global * 65)
1343 c5 = VppGbpContract(
1344 self, 333, 220, acl_index2,
1345 [VppGbpContractRule(
1346 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1349 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1351 [ETH_P_IP, ETH_P_IPV6])
1354 self.send_and_expect_unnatted(self.pg7,
1355 pkt_inter_epg_220_from_global * 65,
1359 pkt_inter_epg_220_from_global = (Ether(src=str(self.router_mac),
1360 dst=self.pg0.remote_mac) /
1361 IPv6(dst=eps[0].fip6.address,
1363 UDP(sport=1234, dport=1234) /
1366 self.send_and_expect_unnatted6(self.pg7,
1367 pkt_inter_epg_220_from_global * 65,
1372 # From a local VM to another local VM using resp. public addresses:
1375 pkt_intra_epg_220_global = (Ether(src=self.pg0.remote_mac,
1376 dst=str(self.router_mac)) /
1377 IP(src=eps[0].ip4.address,
1378 dst=eps[1].fip4.address) /
1379 UDP(sport=1234, dport=1234) /
1382 self.send_and_expect_double_natted(eps[0].itf,
1383 pkt_intra_epg_220_global * 65,
1385 eps[0].fip4.address,
1388 pkt_intra_epg_220_global = (Ether(src=self.pg0.remote_mac,
1389 dst=str(self.router_mac)) /
1390 IPv6(src=eps[0].ip6.address,
1391 dst=eps[1].fip6.address) /
1392 UDP(sport=1234, dport=1234) /
1395 self.send_and_expect_double_natted6(eps[0].itf,
1396 pkt_intra_epg_220_global * 65,
1398 eps[0].fip6.address,
1405 # del static mappings for each EP from the 10/8 to 11/8 network
1406 self.vapi.nat44_add_del_static_mapping(ep.ip4.bytes,
1411 self.vapi.nat66_add_del_static_mapping(ep.ip6.bytes,
1417 # IP config on the BVI interfaces
1418 if epg != epgs[0] and epg != epgs[3]:
1419 self.vapi.nat44_interface_add_del_feature(epg.bvi.sw_if_index,
1422 self.vapi.nat66_add_del_interface(epg.bvi.sw_if_index,
1426 for recirc in recircs:
1427 self.vapi.nat44_interface_add_del_feature(
1428 recirc.recirc.sw_if_index,
1431 self.vapi.nat66_add_del_interface(
1432 recirc.recirc.sw_if_index,
1436 def wait_for_ep_timeout(self, sw_if_index=None, ip=None, mac=None,
1437 n_tries=100, s_time=1):
1439 if not find_gbp_endpoint(self, sw_if_index, ip, mac):
1441 n_tries = n_tries - 1
1443 self.assertFalse(find_gbp_endpoint(self, sw_if_index, ip, mac))
1446 def test_gbp_learn_l2(self):
1447 """ GBP L2 Endpoint Learning """
1449 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
1450 learnt = [{'mac': '00:00:11:11:11:01',
1452 'ip6': '2001:10::2'},
1453 {'mac': '00:00:11:11:11:02',
1455 'ip6': '2001:10::3'}]
1458 # lower the inactive threshold so these tests pass in a
1459 # reasonable amount of time
1461 self.vapi.gbp_endpoint_learn_set_inactive_threshold(2)
1466 gt4 = VppIpTable(self, 1)
1467 gt4.add_vpp_config()
1468 gt6 = VppIpTable(self, 1, is_ip6=True)
1469 gt6.add_vpp_config()
1471 rd1 = VppGbpRouteDomain(self, 1, gt4, gt6)
1472 rd1.add_vpp_config()
1475 # Pg2 hosts the vxlan tunnel, hosts on pg2 to act as TEPs
1476 # Pg3 hosts the IP4 UU-flood VXLAN tunnel
1477 # Pg4 hosts the IP6 UU-flood VXLAN tunnel
1479 self.pg2.config_ip4()
1480 self.pg2.resolve_arp()
1481 self.pg2.generate_remote_hosts(4)
1482 self.pg2.configure_ipv4_neighbors()
1483 self.pg3.config_ip4()
1484 self.pg3.resolve_arp()
1485 self.pg4.config_ip4()
1486 self.pg4.resolve_arp()
1489 # a GBP bridge domain with a BVI and a UU-flood interface
1491 bd1 = VppBridgeDomain(self, 1)
1492 bd1.add_vpp_config()
1493 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0, self.pg3)
1494 gbd1.add_vpp_config()
1496 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1497 self.logger.info(self.vapi.cli("sh gbp bridge"))
1499 # ... and has a /32 applied
1500 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
1501 ip_addr.add_vpp_config()
1504 # The Endpoint-group in which we are learning endpoints
1506 epg_220 = VppGbpEndpointGroup(self, 220, rd1, gbd1,
1510 epg_220.add_vpp_config()
1511 epg_330 = VppGbpEndpointGroup(self, 330, rd1, gbd1,
1515 epg_330.add_vpp_config()
1518 # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
1521 vx_tun_l2_1 = VppGbpVxlanTunnel(
1522 self, 99, bd1.bd_id,
1523 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L2)
1524 vx_tun_l2_1.add_vpp_config()
1527 # A static endpoint that the learnt endpoints are trying to
1530 ep = VppGbpEndpoint(self, self.pg0,
1532 "10.0.0.127", "11.0.0.127",
1533 "2001:10::1", "3001::1")
1536 self.assertTrue(find_route(self, ep.ip4.address, 32, table_id=1))
1538 # a packet with an sclass from an unknwon EPG
1539 p = (Ether(src=self.pg2.remote_mac,
1540 dst=self.pg2.local_mac) /
1541 IP(src=self.pg2.remote_hosts[0].ip4,
1542 dst=self.pg2.local_ip4) /
1543 UDP(sport=1234, dport=48879) /
1544 VXLAN(vni=99, gpid=88, flags=0x88) /
1545 Ether(src=learnt[0]["mac"], dst=ep.mac) /
1546 IP(src=learnt[0]["ip"], dst=ep.ip4.address) /
1547 UDP(sport=1234, dport=1234) /
1550 self.send_and_assert_no_replies(self.pg2, p)
1553 # we should not have learnt a new tunnel endpoint, since
1554 # the EPG was not learnt.
1556 self.assertEqual(INDEX_INVALID,
1557 find_vxlan_gbp_tunnel(self,
1559 self.pg2.remote_hosts[0].ip4,
1562 # epg is not learnt, becasue the EPG is unknwon
1563 self.assertEqual(len(self.vapi.gbp_endpoint_dump()), 1)
1565 for ii, l in enumerate(learnt):
1566 # a packet with an sclass from a knwon EPG
1567 # arriving on an unknown TEP
1568 p = (Ether(src=self.pg2.remote_mac,
1569 dst=self.pg2.local_mac) /
1570 IP(src=self.pg2.remote_hosts[1].ip4,
1571 dst=self.pg2.local_ip4) /
1572 UDP(sport=1234, dport=48879) /
1573 VXLAN(vni=99, gpid=220, flags=0x88) /
1574 Ether(src=l['mac'], dst=ep.mac) /
1575 IP(src=l['ip'], dst=ep.ip4.address) /
1576 UDP(sport=1234, dport=1234) /
1579 rx = self.send_and_expect(self.pg2, [p], self.pg0)
1582 tep1_sw_if_index = find_vxlan_gbp_tunnel(
1585 self.pg2.remote_hosts[1].ip4,
1587 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
1590 # the EP is learnt via the learnt TEP
1591 # both from its MAC and its IP
1593 self.assertTrue(find_gbp_endpoint(self,
1594 vx_tun_l2_1.sw_if_index,
1596 self.assertTrue(find_gbp_endpoint(self,
1597 vx_tun_l2_1.sw_if_index,
1600 self.logger.info(self.vapi.cli("show gbp endpoint"))
1601 self.logger.info(self.vapi.cli("show gbp vxlan"))
1602 self.logger.info(self.vapi.cli("show vxlan-gbp tunnel"))
1605 # If we sleep for the threshold time, the learnt endpoints should
1609 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1613 # repeat. the do not learn bit is set so the EPs are not learnt
1616 # a packet with an sclass from a knwon EPG
1617 p = (Ether(src=self.pg2.remote_mac,
1618 dst=self.pg2.local_mac) /
1619 IP(src=self.pg2.remote_hosts[1].ip4,
1620 dst=self.pg2.local_ip4) /
1621 UDP(sport=1234, dport=48879) /
1622 VXLAN(vni=99, gpid=220, flags=0x88, gpflags="D") /
1623 Ether(src=l['mac'], dst=ep.mac) /
1624 IP(src=l['ip'], dst=ep.ip4.address) /
1625 UDP(sport=1234, dport=1234) /
1628 rx = self.send_and_expect(self.pg2, p*65, self.pg0)
1631 self.assertFalse(find_gbp_endpoint(self,
1632 vx_tun_l2_1.sw_if_index,
1639 # a packet with an sclass from a knwon EPG
1640 p = (Ether(src=self.pg2.remote_mac,
1641 dst=self.pg2.local_mac) /
1642 IP(src=self.pg2.remote_hosts[1].ip4,
1643 dst=self.pg2.local_ip4) /
1644 UDP(sport=1234, dport=48879) /
1645 VXLAN(vni=99, gpid=220, flags=0x88) /
1646 Ether(src=l['mac'], dst=ep.mac) /
1647 IP(src=l['ip'], dst=ep.ip4.address) /
1648 UDP(sport=1234, dport=1234) /
1651 rx = self.send_and_expect(self.pg2, p*65, self.pg0)
1653 self.assertTrue(find_gbp_endpoint(self,
1654 vx_tun_l2_1.sw_if_index,
1658 # Static EP replies to dynamics
1660 self.logger.info(self.vapi.cli("sh l2fib bd_id 1"))
1662 p = (Ether(src=ep.mac, dst=l['mac']) /
1663 IP(dst=l['ip'], src=ep.ip4.address) /
1664 UDP(sport=1234, dport=1234) /
1667 rxs = self.send_and_expect(self.pg0, p * 17, self.pg2)
1670 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
1671 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
1672 self.assertEqual(rx[UDP].dport, 48879)
1673 # the UDP source port is a random value for hashing
1674 self.assertEqual(rx[VXLAN].gpid, 220)
1675 self.assertEqual(rx[VXLAN].vni, 99)
1676 self.assertTrue(rx[VXLAN].flags.G)
1677 self.assertTrue(rx[VXLAN].flags.Instance)
1678 self.assertTrue(rx[VXLAN].gpflags.A)
1679 self.assertFalse(rx[VXLAN].gpflags.D)
1682 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1686 # repeat in the other EPG
1687 # there's no contract between 220 and 330, but the A-bit is set
1688 # so the packet is cleared for delivery
1691 # a packet with an sclass from a knwon EPG
1692 p = (Ether(src=self.pg2.remote_mac,
1693 dst=self.pg2.local_mac) /
1694 IP(src=self.pg2.remote_hosts[1].ip4,
1695 dst=self.pg2.local_ip4) /
1696 UDP(sport=1234, dport=48879) /
1697 VXLAN(vni=99, gpid=330, flags=0x88, gpflags='A') /
1698 Ether(src=l['mac'], dst=ep.mac) /
1699 IP(src=l['ip'], dst=ep.ip4.address) /
1700 UDP(sport=1234, dport=1234) /
1703 rx = self.send_and_expect(self.pg2, p*65, self.pg0)
1705 self.assertTrue(find_gbp_endpoint(self,
1706 vx_tun_l2_1.sw_if_index,
1710 # static EP cannot reach the learnt EPs since there is no contract
1711 # only test 1 EP as the others could timeout
1713 p = (Ether(src=ep.mac, dst=l['mac']) /
1714 IP(dst=learnt[0]['ip'], src=ep.ip4.address) /
1715 UDP(sport=1234, dport=1234) /
1718 self.send_and_assert_no_replies(self.pg0, [p])
1721 # refresh the entries after the check for no replies above
1724 # a packet with an sclass from a knwon EPG
1725 p = (Ether(src=self.pg2.remote_mac,
1726 dst=self.pg2.local_mac) /
1727 IP(src=self.pg2.remote_hosts[1].ip4,
1728 dst=self.pg2.local_ip4) /
1729 UDP(sport=1234, dport=48879) /
1730 VXLAN(vni=99, gpid=330, flags=0x88, gpflags='A') /
1731 Ether(src=l['mac'], dst=ep.mac) /
1732 IP(src=l['ip'], dst=ep.ip4.address) /
1733 UDP(sport=1234, dport=1234) /
1736 rx = self.send_and_expect(self.pg2, p*65, self.pg0)
1738 self.assertTrue(find_gbp_endpoint(self,
1739 vx_tun_l2_1.sw_if_index,
1743 # Add the contract so they can talk
1745 acl = VppGbpAcl(self)
1746 rule = acl.create_rule(permit_deny=1, proto=17)
1747 rule2 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
1748 acl_index = acl.add_vpp_config([rule, rule2])
1749 c1 = VppGbpContract(
1750 self, 220, 330, acl_index,
1751 [VppGbpContractRule(
1752 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1755 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1757 [ETH_P_IP, ETH_P_IPV6])
1761 p = (Ether(src=ep.mac, dst=l['mac']) /
1762 IP(dst=l['ip'], src=ep.ip4.address) /
1763 UDP(sport=1234, dport=1234) /
1766 self.send_and_expect(self.pg0, [p], self.pg2)
1769 # send UU packets from the local EP
1771 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1772 self.logger.info(self.vapi.cli("sh gbp bridge"))
1773 p_uu = (Ether(src=ep.mac, dst="00:11:11:11:11:11") /
1774 IP(dst="10.0.0.133", src=ep.ip4.address) /
1775 UDP(sport=1234, dport=1234) /
1777 rxs = self.send_and_expect(ep.itf, [p_uu], gbd1.uu_flood)
1780 # Add a mcast destination VXLAN-GBP tunnel for B&M traffic
1782 tun_bm = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
1785 tun_bm.add_vpp_config()
1786 bp_bm = VppBridgeDomainPort(self, bd1, tun_bm,
1787 port_type=L2_PORT_TYPE.NORMAL)
1788 bp_bm.add_vpp_config()
1790 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1792 p_bm = (Ether(src=ep.mac, dst="ff:ff:ff:ff:ff:ff") /
1793 IP(dst="10.0.0.133", src=ep.ip4.address) /
1794 UDP(sport=1234, dport=1234) /
1796 rxs = self.send_and_expect_only(ep.itf, [p_bm], tun_bm.mcast_itf)
1799 # Check v6 Endpoints
1802 # a packet with an sclass from a knwon EPG
1803 p = (Ether(src=self.pg2.remote_mac,
1804 dst=self.pg2.local_mac) /
1805 IP(src=self.pg2.remote_hosts[1].ip4,
1806 dst=self.pg2.local_ip4) /
1807 UDP(sport=1234, dport=48879) /
1808 VXLAN(vni=99, gpid=330, flags=0x88, gpflags='A') /
1809 Ether(src=l['mac'], dst=ep.mac) /
1810 IPv6(src=l['ip6'], dst=ep.ip6.address) /
1811 UDP(sport=1234, dport=1234) /
1814 rx = self.send_and_expect(self.pg2, p*65, self.pg0)
1816 self.assertTrue(find_gbp_endpoint(self,
1817 vx_tun_l2_1.sw_if_index,
1821 # L3 Endpoint Learning
1822 # - configured on the bridge's BVI
1829 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1832 self.pg2.unconfig_ip4()
1833 self.pg3.unconfig_ip4()
1834 self.pg4.unconfig_ip4()
1836 self.logger.info(self.vapi.cli("sh int"))
1837 self.logger.info(self.vapi.cli("sh gbp vxlan"))
1839 @unittest.skipIf(is_skip_aarch64_set and is_platform_aarch64,
1840 "test doesn't work on aarch64")
1841 def test_gbp_learn_vlan_l2(self):
1842 """ GBP L2 Endpoint w/ VLANs"""
1844 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
1845 learnt = [{'mac': '00:00:11:11:11:01',
1847 'ip6': '2001:10::2'},
1848 {'mac': '00:00:11:11:11:02',
1850 'ip6': '2001:10::3'}]
1853 # lower the inactive threshold so these tests pass in a
1854 # reasonable amount of time
1856 self.vapi.gbp_endpoint_learn_set_inactive_threshold(2)
1861 gt4 = VppIpTable(self, 1)
1862 gt4.add_vpp_config()
1863 gt6 = VppIpTable(self, 1, is_ip6=True)
1864 gt6.add_vpp_config()
1866 rd1 = VppGbpRouteDomain(self, 1, gt4, gt6)
1867 rd1.add_vpp_config()
1870 # Pg2 hosts the vxlan tunnel, hosts on pg2 to act as TEPs
1872 self.pg2.config_ip4()
1873 self.pg2.resolve_arp()
1874 self.pg2.generate_remote_hosts(4)
1875 self.pg2.configure_ipv4_neighbors()
1876 self.pg3.config_ip4()
1877 self.pg3.resolve_arp()
1880 # The EP will be on a vlan sub-interface
1882 vlan_11 = VppDot1QSubint(self, self.pg0, 11)
1884 self.vapi.sw_interface_set_l2_tag_rewrite(vlan_11.sw_if_index,
1888 bd_uu_fwd = VppVxlanGbpTunnel(self, self.pg3.local_ip4,
1889 self.pg3.remote_ip4, 116)
1890 bd_uu_fwd.add_vpp_config()
1893 # a GBP bridge domain with a BVI and a UU-flood interface
1894 # The BD is marked as do not learn, so no endpoints are ever
1895 # learnt in this BD.
1897 bd1 = VppBridgeDomain(self, 1)
1898 bd1.add_vpp_config()
1899 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0, bd_uu_fwd,
1901 gbd1.add_vpp_config()
1903 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1904 self.logger.info(self.vapi.cli("sh gbp bridge"))
1906 # ... and has a /32 applied
1907 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
1908 ip_addr.add_vpp_config()
1911 # The Endpoint-group in which we are learning endpoints
1913 epg_220 = VppGbpEndpointGroup(self, 220, rd1, gbd1,
1917 epg_220.add_vpp_config()
1920 # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
1923 vx_tun_l2_1 = VppGbpVxlanTunnel(
1924 self, 99, bd1.bd_id,
1925 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L2)
1926 vx_tun_l2_1.add_vpp_config()
1929 # A static endpoint that the learnt endpoints are trying to
1932 ep = VppGbpEndpoint(self, vlan_11,
1934 "10.0.0.127", "11.0.0.127",
1935 "2001:10::1", "3001::1")
1938 self.assertTrue(find_route(self, ep.ip4.address, 32, table_id=1))
1941 # Send to the static EP
1943 for ii, l in enumerate(learnt):
1944 # a packet with an sclass from a knwon EPG
1945 # arriving on an unknown TEP
1946 p = (Ether(src=self.pg2.remote_mac,
1947 dst=self.pg2.local_mac) /
1948 IP(src=self.pg2.remote_hosts[1].ip4,
1949 dst=self.pg2.local_ip4) /
1950 UDP(sport=1234, dport=48879) /
1951 VXLAN(vni=99, gpid=220, flags=0x88) /
1952 Ether(src=l['mac'], dst=ep.mac) /
1953 IP(src=l['ip'], dst=ep.ip4.address) /
1954 UDP(sport=1234, dport=1234) /
1957 rxs = self.send_and_expect(self.pg2, [p], self.pg0)
1960 # packet to EP has the EP's vlan tag
1963 self.assertEqual(rx[Dot1Q].vlan, 11)
1966 # the EP is not learnt since the BD setting prevents it
1969 self.assertFalse(find_gbp_endpoint(self,
1970 vx_tun_l2_1.sw_if_index,
1972 self.assertEqual(INDEX_INVALID,
1973 find_vxlan_gbp_tunnel(
1976 self.pg2.remote_hosts[1].ip4,
1979 self.assertEqual(len(self.vapi.gbp_endpoint_dump()), 1)
1983 # we didn't learn the remotes so they are sent to the UU-fwd
1986 p = (Ether(src=ep.mac, dst=l['mac']) /
1988 IP(dst=l['ip'], src=ep.ip4.address) /
1989 UDP(sport=1234, dport=1234) /
1992 rxs = self.send_and_expect(self.pg0, p * 17, self.pg3)
1995 self.assertEqual(rx[IP].src, self.pg3.local_ip4)
1996 self.assertEqual(rx[IP].dst, self.pg3.remote_ip4)
1997 self.assertEqual(rx[UDP].dport, 48879)
1998 # the UDP source port is a random value for hashing
1999 self.assertEqual(rx[VXLAN].gpid, 220)
2000 self.assertEqual(rx[VXLAN].vni, 116)
2001 self.assertTrue(rx[VXLAN].flags.G)
2002 self.assertTrue(rx[VXLAN].flags.Instance)
2003 self.assertFalse(rx[VXLAN].gpflags.A)
2004 self.assertFalse(rx[VXLAN].gpflags.D)
2006 self.pg2.unconfig_ip4()
2007 self.pg3.unconfig_ip4()
2009 @unittest.skipIf(is_skip_aarch64_set and is_platform_aarch64,
2010 "test doesn't work on aarch64")
2011 def test_gbp_learn_l3(self):
2012 """ GBP L3 Endpoint Learning """
2014 self.vapi.cli("set logging class gbp debug")
2016 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
2017 routed_dst_mac = "00:0c:0c:0c:0c:0c"
2018 routed_src_mac = "00:22:bd:f8:19:ff"
2020 learnt = [{'mac': '00:00:11:11:11:02',
2022 'ip6': '2001:10::2'},
2023 {'mac': '00:00:11:11:11:03',
2025 'ip6': '2001:10::3'}]
2028 # lower the inactive threshold so these tests pass in a
2029 # reasonable amount of time
2031 self.vapi.gbp_endpoint_learn_set_inactive_threshold(2)
2036 t4 = VppIpTable(self, 1)
2038 t6 = VppIpTable(self, 1, True)
2041 tun_ip4_uu = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
2042 self.pg4.remote_ip4, 114)
2043 tun_ip6_uu = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
2044 self.pg4.remote_ip4, 116)
2045 tun_ip4_uu.add_vpp_config()
2046 tun_ip6_uu.add_vpp_config()
2048 rd1 = VppGbpRouteDomain(self, 2, t4, t6, tun_ip4_uu, tun_ip6_uu)
2049 rd1.add_vpp_config()
2051 self.loop0.set_mac(self.router_mac)
2054 # Bind the BVI to the RD
2056 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
2057 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
2060 # Pg2 hosts the vxlan tunnel
2061 # hosts on pg2 to act as TEPs
2065 self.pg2.config_ip4()
2066 self.pg2.resolve_arp()
2067 self.pg2.generate_remote_hosts(4)
2068 self.pg2.configure_ipv4_neighbors()
2069 self.pg3.config_ip4()
2070 self.pg3.resolve_arp()
2071 self.pg4.config_ip4()
2072 self.pg4.resolve_arp()
2075 # a GBP bridge domain with a BVI and a UU-flood interface
2077 bd1 = VppBridgeDomain(self, 1)
2078 bd1.add_vpp_config()
2079 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0, self.pg3)
2080 gbd1.add_vpp_config()
2082 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2083 self.logger.info(self.vapi.cli("sh gbp bridge"))
2084 self.logger.info(self.vapi.cli("sh gbp route"))
2086 # ... and has a /32 and /128 applied
2087 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2088 ip4_addr.add_vpp_config()
2089 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 128)
2090 ip6_addr.add_vpp_config()
2093 # The Endpoint-group in which we are learning endpoints
2095 epg_220 = VppGbpEndpointGroup(self, 220, rd1, gbd1,
2099 epg_220.add_vpp_config()
2102 # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
2105 vx_tun_l3 = VppGbpVxlanTunnel(
2106 self, 101, rd1.rd_id,
2107 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3)
2108 vx_tun_l3.add_vpp_config()
2111 # A static endpoint that the learnt endpoints are trying to
2114 ep = VppGbpEndpoint(self, self.pg0,
2116 "10.0.0.127", "11.0.0.127",
2117 "2001:10::1", "3001::1")
2121 # learn some remote IPv4 EPs
2123 for ii, l in enumerate(learnt):
2124 # a packet with an sclass from a knwon EPG
2125 # arriving on an unknown TEP
2126 p = (Ether(src=self.pg2.remote_mac,
2127 dst=self.pg2.local_mac) /
2128 IP(src=self.pg2.remote_hosts[1].ip4,
2129 dst=self.pg2.local_ip4) /
2130 UDP(sport=1234, dport=48879) /
2131 VXLAN(vni=101, gpid=220, flags=0x88) /
2132 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2133 IP(src=l['ip'], dst=ep.ip4.address) /
2134 UDP(sport=1234, dport=1234) /
2137 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2140 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2143 self.pg2.remote_hosts[1].ip4,
2145 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2147 # endpoint learnt via the parent GBP-vxlan interface
2148 self.assertTrue(find_gbp_endpoint(self,
2149 vx_tun_l3._sw_if_index,
2153 # Static IPv4 EP replies to learnt
2156 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2157 IP(dst=l['ip'], src=ep.ip4.address) /
2158 UDP(sport=1234, dport=1234) /
2161 rxs = self.send_and_expect(self.pg0, p*1, self.pg2)
2164 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2165 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2166 self.assertEqual(rx[UDP].dport, 48879)
2167 # the UDP source port is a random value for hashing
2168 self.assertEqual(rx[VXLAN].gpid, 220)
2169 self.assertEqual(rx[VXLAN].vni, 101)
2170 self.assertTrue(rx[VXLAN].flags.G)
2171 self.assertTrue(rx[VXLAN].flags.Instance)
2172 self.assertTrue(rx[VXLAN].gpflags.A)
2173 self.assertFalse(rx[VXLAN].gpflags.D)
2175 inner = rx[VXLAN].payload
2177 self.assertEqual(inner[Ether].src, routed_src_mac)
2178 self.assertEqual(inner[Ether].dst, routed_dst_mac)
2179 self.assertEqual(inner[IP].src, ep.ip4.address)
2180 self.assertEqual(inner[IP].dst, l['ip'])
2183 self.assertFalse(find_gbp_endpoint(self,
2188 # learn some remote IPv6 EPs
2190 for ii, l in enumerate(learnt):
2191 # a packet with an sclass from a knwon EPG
2192 # arriving on an unknown TEP
2193 p = (Ether(src=self.pg2.remote_mac,
2194 dst=self.pg2.local_mac) /
2195 IP(src=self.pg2.remote_hosts[1].ip4,
2196 dst=self.pg2.local_ip4) /
2197 UDP(sport=1234, dport=48879) /
2198 VXLAN(vni=101, gpid=220, flags=0x88) /
2199 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2200 IPv6(src=l['ip6'], dst=ep.ip6.address) /
2201 UDP(sport=1234, dport=1234) /
2204 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2207 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2210 self.pg2.remote_hosts[1].ip4,
2212 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2214 self.logger.info(self.vapi.cli("show gbp bridge"))
2215 self.logger.info(self.vapi.cli("show vxlan-gbp tunnel"))
2216 self.logger.info(self.vapi.cli("show gbp vxlan"))
2217 self.logger.info(self.vapi.cli("show int addr"))
2219 # endpoint learnt via the TEP
2220 self.assertTrue(find_gbp_endpoint(self, ip=l['ip6']))
2222 self.logger.info(self.vapi.cli("show gbp endpoint"))
2223 self.logger.info(self.vapi.cli("show ip fib index 1 %s" % l['ip']))
2226 # Static EP replies to learnt
2229 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2230 IPv6(dst=l['ip6'], src=ep.ip6.address) /
2231 UDP(sport=1234, dport=1234) /
2234 rxs = self.send_and_expect(self.pg0, p*65, self.pg2)
2237 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2238 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2239 self.assertEqual(rx[UDP].dport, 48879)
2240 # the UDP source port is a random value for hashing
2241 self.assertEqual(rx[VXLAN].gpid, 220)
2242 self.assertEqual(rx[VXLAN].vni, 101)
2243 self.assertTrue(rx[VXLAN].flags.G)
2244 self.assertTrue(rx[VXLAN].flags.Instance)
2245 self.assertTrue(rx[VXLAN].gpflags.A)
2246 self.assertFalse(rx[VXLAN].gpflags.D)
2248 inner = rx[VXLAN].payload
2250 self.assertEqual(inner[Ether].src, routed_src_mac)
2251 self.assertEqual(inner[Ether].dst, routed_dst_mac)
2252 self.assertEqual(inner[IPv6].src, ep.ip6.address)
2253 self.assertEqual(inner[IPv6].dst, l['ip6'])
2255 self.logger.info(self.vapi.cli("sh gbp endpoint"))
2257 self.wait_for_ep_timeout(ip=l['ip'])
2260 # Static sends to unknown EP with no route
2262 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2263 IP(dst="10.0.0.99", src=ep.ip4.address) /
2264 UDP(sport=1234, dport=1234) /
2267 self.send_and_assert_no_replies(self.pg0, [p])
2270 # Add a route to static EP's v4 and v6 subnet
2271 # packets should be sent on the v4/v6 uu=fwd interface resp.
2273 se_10_24 = VppGbpSubnet(
2274 self, rd1, "10.0.0.0", 24,
2275 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT)
2276 se_10_24.add_vpp_config()
2278 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2279 IP(dst="10.0.0.99", src=ep.ip4.address) /
2280 UDP(sport=1234, dport=1234) /
2283 rxs = self.send_and_expect(self.pg0, [p], self.pg4)
2285 self.assertEqual(rx[IP].src, self.pg4.local_ip4)
2286 self.assertEqual(rx[IP].dst, self.pg4.remote_ip4)
2287 self.assertEqual(rx[UDP].dport, 48879)
2288 # the UDP source port is a random value for hashing
2289 self.assertEqual(rx[VXLAN].gpid, 220)
2290 self.assertEqual(rx[VXLAN].vni, 114)
2291 self.assertTrue(rx[VXLAN].flags.G)
2292 self.assertTrue(rx[VXLAN].flags.Instance)
2293 # policy is not applied to packets sent to the uu-fwd interfaces
2294 self.assertFalse(rx[VXLAN].gpflags.A)
2295 self.assertFalse(rx[VXLAN].gpflags.D)
2298 # learn some remote IPv4 EPs
2300 for ii, l in enumerate(learnt):
2301 # a packet with an sclass from a knwon EPG
2302 # arriving on an unknown TEP
2303 p = (Ether(src=self.pg2.remote_mac,
2304 dst=self.pg2.local_mac) /
2305 IP(src=self.pg2.remote_hosts[1].ip4,
2306 dst=self.pg2.local_ip4) /
2307 UDP(sport=1234, dport=48879) /
2308 VXLAN(vni=101, gpid=220, flags=0x88) /
2309 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2310 IP(src=l['ip'], dst=ep.ip4.address) /
2311 UDP(sport=1234, dport=1234) /
2314 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2317 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2320 self.pg2.remote_hosts[1].ip4,
2322 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2324 # endpoint learnt via the parent GBP-vxlan interface
2325 self.assertTrue(find_gbp_endpoint(self,
2326 vx_tun_l3._sw_if_index,
2330 # Add a remote endpoint from the API
2332 rep_88 = VppGbpEndpoint(self, vx_tun_l3,
2334 "10.0.0.88", "11.0.0.88",
2335 "2001:10::88", "3001::88",
2336 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
2338 self.pg2.remote_hosts[1].ip4,
2340 rep_88.add_vpp_config()
2343 # Add a remote endpoint from the API that matches an existing one
2345 rep_2 = VppGbpEndpoint(self, vx_tun_l3,
2347 learnt[0]['ip'], "11.0.0.101",
2348 learnt[0]['ip6'], "3001::101",
2349 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
2351 self.pg2.remote_hosts[1].ip4,
2353 rep_2.add_vpp_config()
2356 # Add a route to the leanred EP's v4 subnet
2357 # packets should be send on the v4/v6 uu=fwd interface resp.
2359 se_10_1_24 = VppGbpSubnet(
2360 self, rd1, "10.0.1.0", 24,
2361 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT)
2362 se_10_1_24.add_vpp_config()
2364 self.logger.info(self.vapi.cli("show gbp endpoint"))
2366 ips = ["10.0.0.88", learnt[0]['ip']]
2368 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2369 IP(dst=ip, src=ep.ip4.address) /
2370 UDP(sport=1234, dport=1234) /
2373 rxs = self.send_and_expect(self.pg0, p*65, self.pg2)
2376 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2377 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2378 self.assertEqual(rx[UDP].dport, 48879)
2379 # the UDP source port is a random value for hashing
2380 self.assertEqual(rx[VXLAN].gpid, 220)
2381 self.assertEqual(rx[VXLAN].vni, 101)
2382 self.assertTrue(rx[VXLAN].flags.G)
2383 self.assertTrue(rx[VXLAN].flags.Instance)
2384 self.assertTrue(rx[VXLAN].gpflags.A)
2385 self.assertFalse(rx[VXLAN].gpflags.D)
2387 inner = rx[VXLAN].payload
2389 self.assertEqual(inner[Ether].src, routed_src_mac)
2390 self.assertEqual(inner[Ether].dst, routed_dst_mac)
2391 self.assertEqual(inner[IP].src, ep.ip4.address)
2392 self.assertEqual(inner[IP].dst, ip)
2395 # remove the API remote EPs, only API sourced is gone, the DP
2396 # learnt one remains
2398 rep_88.remove_vpp_config()
2399 rep_2.remove_vpp_config()
2401 self.assertTrue(find_gbp_endpoint(self, ip=rep_2.ip4.address))
2403 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2404 IP(src=ep.ip4.address, dst=rep_2.ip4.address) /
2405 UDP(sport=1234, dport=1234) /
2407 rxs = self.send_and_expect(self.pg0, [p], self.pg2)
2409 self.assertFalse(find_gbp_endpoint(self, ip=rep_88.ip4.address))
2411 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2412 IP(src=ep.ip4.address, dst=rep_88.ip4.address) /
2413 UDP(sport=1234, dport=1234) /
2415 rxs = self.send_and_expect(self.pg0, [p], self.pg4)
2418 # to appease the testcase we cannot have the registered EP stll
2419 # present (because it's DP learnt) when the TC ends so wait until
2422 self.wait_for_ep_timeout(ip=rep_88.ip4.address)
2423 self.wait_for_ep_timeout(ip=rep_2.ip4.address)
2426 # shutdown with learnt endpoint present
2428 p = (Ether(src=self.pg2.remote_mac,
2429 dst=self.pg2.local_mac) /
2430 IP(src=self.pg2.remote_hosts[1].ip4,
2431 dst=self.pg2.local_ip4) /
2432 UDP(sport=1234, dport=48879) /
2433 VXLAN(vni=101, gpid=220, flags=0x88) /
2434 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2435 IP(src=learnt[1]['ip'], dst=ep.ip4.address) /
2436 UDP(sport=1234, dport=1234) /
2439 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2441 # endpoint learnt via the parent GBP-vxlan interface
2442 self.assertTrue(find_gbp_endpoint(self,
2443 vx_tun_l3._sw_if_index,
2448 # remote endpoint becomes local
2450 self.pg2.unconfig_ip4()
2451 self.pg3.unconfig_ip4()
2452 self.pg4.unconfig_ip4()
2454 def test_gbp_redirect(self):
2455 """ GBP Endpoint Redirect """
2457 self.vapi.cli("set logging class gbp debug")
2459 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
2460 routed_dst_mac = "00:0c:0c:0c:0c:0c"
2461 routed_src_mac = "00:22:bd:f8:19:ff"
2463 learnt = [{'mac': '00:00:11:11:11:02',
2465 'ip6': '2001:10::2'},
2466 {'mac': '00:00:11:11:11:03',
2468 'ip6': '2001:10::3'}]
2471 # lower the inactive threshold so these tests pass in a
2472 # reasonable amount of time
2474 self.vapi.gbp_endpoint_learn_set_inactive_threshold(2)
2479 t4 = VppIpTable(self, 1)
2481 t6 = VppIpTable(self, 1, True)
2484 rd1 = VppGbpRouteDomain(self, 2, t4, t6)
2485 rd1.add_vpp_config()
2487 self.loop0.set_mac(self.router_mac)
2490 # Bind the BVI to the RD
2492 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
2493 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
2496 # Pg7 hosts a BD's UU-fwd
2498 self.pg7.config_ip4()
2499 self.pg7.resolve_arp()
2502 # a GBP bridge domains for the EPs
2504 bd1 = VppBridgeDomain(self, 1)
2505 bd1.add_vpp_config()
2506 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0)
2507 gbd1.add_vpp_config()
2509 bd2 = VppBridgeDomain(self, 2)
2510 bd2.add_vpp_config()
2511 gbd2 = VppGbpBridgeDomain(self, bd2, self.loop1)
2512 gbd2.add_vpp_config()
2514 # ... and has a /32 and /128 applied
2515 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2516 ip4_addr.add_vpp_config()
2517 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 128)
2518 ip6_addr.add_vpp_config()
2519 ip4_addr = VppIpInterfaceAddress(self, gbd2.bvi, "10.0.1.128", 32)
2520 ip4_addr.add_vpp_config()
2521 ip6_addr = VppIpInterfaceAddress(self, gbd2.bvi, "2001:11::128", 128)
2522 ip6_addr.add_vpp_config()
2525 # The Endpoint-groups in which we are learning endpoints
2527 epg_220 = VppGbpEndpointGroup(self, 220, rd1, gbd1,
2531 epg_220.add_vpp_config()
2532 epg_221 = VppGbpEndpointGroup(self, 221, rd1, gbd2,
2536 epg_221.add_vpp_config()
2537 epg_222 = VppGbpEndpointGroup(self, 222, rd1, gbd1,
2541 epg_222.add_vpp_config()
2544 # a GBP bridge domains for the SEPs
2546 bd_uu1 = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
2547 self.pg7.remote_ip4, 116)
2548 bd_uu1.add_vpp_config()
2549 bd_uu2 = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
2550 self.pg7.remote_ip4, 117)
2551 bd_uu2.add_vpp_config()
2553 bd3 = VppBridgeDomain(self, 3)
2554 bd3.add_vpp_config()
2555 gbd3 = VppGbpBridgeDomain(self, bd3, self.loop2, bd_uu1, learn=False)
2556 gbd3.add_vpp_config()
2557 bd4 = VppBridgeDomain(self, 4)
2558 bd4.add_vpp_config()
2559 gbd4 = VppGbpBridgeDomain(self, bd4, self.loop3, bd_uu2, learn=False)
2560 gbd4.add_vpp_config()
2563 # EPGs in which the service endpoints exist
2565 epg_320 = VppGbpEndpointGroup(self, 320, rd1, gbd3,
2569 epg_320.add_vpp_config()
2570 epg_321 = VppGbpEndpointGroup(self, 321, rd1, gbd4,
2574 epg_321.add_vpp_config()
2577 # three local endpoints
2579 ep1 = VppGbpEndpoint(self, self.pg0,
2581 "10.0.0.1", "11.0.0.1",
2582 "2001:10::1", "3001:10::1")
2583 ep1.add_vpp_config()
2584 ep2 = VppGbpEndpoint(self, self.pg1,
2586 "10.0.1.1", "11.0.1.1",
2587 "2001:11::1", "3001:11::1")
2588 ep2.add_vpp_config()
2589 ep3 = VppGbpEndpoint(self, self.pg2,
2591 "10.0.2.2", "11.0.2.2",
2592 "2001:12::1", "3001:12::1")
2593 ep3.add_vpp_config()
2598 sep1 = VppGbpEndpoint(self, self.pg3,
2600 "12.0.0.1", "13.0.0.1",
2601 "4001:10::1", "5001:10::1")
2602 sep1.add_vpp_config()
2603 sep2 = VppGbpEndpoint(self, self.pg4,
2605 "12.0.0.2", "13.0.0.2",
2606 "4001:10::2", "5001:10::2")
2607 sep2.add_vpp_config()
2608 sep3 = VppGbpEndpoint(self, self.pg5,
2610 "12.0.1.1", "13.0.1.1",
2611 "4001:11::1", "5001:11::1")
2612 sep3.add_vpp_config()
2613 # this EP is not installed immediately
2614 sep4 = VppGbpEndpoint(self, self.pg6,
2616 "12.0.1.2", "13.0.1.2",
2617 "4001:11::2", "5001:11::2")
2620 # an L2 switch packet between local EPs in different EPGs
2621 # different dest ports on each so the are LB hashed differently
2623 p4 = [(Ether(src=ep1.mac, dst=ep3.mac) /
2624 IP(src=ep1.ip4.address, dst=ep3.ip4.address) /
2625 UDP(sport=1234, dport=1234) /
2627 (Ether(src=ep3.mac, dst=ep1.mac) /
2628 IP(src=ep3.ip4.address, dst=ep1.ip4.address) /
2629 UDP(sport=1234, dport=1234) /
2631 p6 = [(Ether(src=ep1.mac, dst=ep3.mac) /
2632 IPv6(src=ep1.ip6.address, dst=ep3.ip6.address) /
2633 UDP(sport=1234, dport=1234) /
2635 (Ether(src=ep3.mac, dst=ep1.mac) /
2636 IPv6(src=ep3.ip6.address, dst=ep1.ip6.address) /
2637 UDP(sport=1234, dport=1230) /
2640 # should be dropped since no contract yet
2641 self.send_and_assert_no_replies(self.pg0, [p4[0]])
2642 self.send_and_assert_no_replies(self.pg0, [p6[0]])
2645 # Add a contract with a rule to load-balance redirect via SEP1 and SEP2
2646 # one of the next-hops is via an EP that is not known
2648 acl = VppGbpAcl(self)
2649 rule4 = acl.create_rule(permit_deny=1, proto=17)
2650 rule6 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
2651 acl_index = acl.add_vpp_config([rule4, rule6])
2654 # test the src-ip hash mode
2656 c1 = VppGbpContract(
2657 self, 220, 222, acl_index,
2658 [VppGbpContractRule(
2659 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2660 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2661 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
2662 sep1.ip4, sep1.epg.rd),
2663 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
2664 sep2.ip4, sep2.epg.rd)]),
2666 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2667 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2668 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
2669 sep3.ip6, sep3.epg.rd),
2670 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
2671 sep4.ip6, sep4.epg.rd)])],
2672 [ETH_P_IP, ETH_P_IPV6])
2675 c2 = VppGbpContract(
2676 self, 222, 220, acl_index,
2677 [VppGbpContractRule(
2678 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2679 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2680 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
2681 sep1.ip4, sep1.epg.rd),
2682 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
2683 sep2.ip4, sep2.epg.rd)]),
2685 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2686 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2687 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
2688 sep3.ip6, sep3.epg.rd),
2689 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
2690 sep4.ip6, sep4.epg.rd)])],
2691 [ETH_P_IP, ETH_P_IPV6])
2695 # send again with the contract preset, now packets arrive
2696 # at SEP1 or SEP2 depending on the hashing
2698 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
2701 self.assertEqual(rx[Ether].src, routed_src_mac)
2702 self.assertEqual(rx[Ether].dst, sep1.mac)
2703 self.assertEqual(rx[IP].src, ep1.ip4.address)
2704 self.assertEqual(rx[IP].dst, ep3.ip4.address)
2706 rxs = self.send_and_expect(self.pg2, p4[1] * 17, sep2.itf)
2709 self.assertEqual(rx[Ether].src, routed_src_mac)
2710 self.assertEqual(rx[Ether].dst, sep2.mac)
2711 self.assertEqual(rx[IP].src, ep3.ip4.address)
2712 self.assertEqual(rx[IP].dst, ep1.ip4.address)
2714 rxs = self.send_and_expect(self.pg0, p6[0] * 17, self.pg7)
2717 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
2718 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
2719 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
2720 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
2721 self.assertEqual(rx[VXLAN].vni, 117)
2722 self.assertTrue(rx[VXLAN].flags.G)
2723 self.assertTrue(rx[VXLAN].flags.Instance)
2724 # redirect policy has been applied
2725 self.assertTrue(rx[VXLAN].gpflags.A)
2726 self.assertFalse(rx[VXLAN].gpflags.D)
2728 inner = rx[VXLAN].payload
2730 self.assertEqual(inner[Ether].src, routed_src_mac)
2731 self.assertEqual(inner[Ether].dst, sep4.mac)
2732 self.assertEqual(inner[IPv6].src, ep1.ip6.address)
2733 self.assertEqual(inner[IPv6].dst, ep3.ip6.address)
2735 rxs = self.send_and_expect(self.pg2, p6[1] * 17, sep3.itf)
2738 self.assertEqual(rx[Ether].src, routed_src_mac)
2739 self.assertEqual(rx[Ether].dst, sep3.mac)
2740 self.assertEqual(rx[IPv6].src, ep3.ip6.address)
2741 self.assertEqual(rx[IPv6].dst, ep1.ip6.address)
2744 # programme the unknown EP
2746 sep4.add_vpp_config()
2748 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep4.itf)
2751 self.assertEqual(rx[Ether].src, routed_src_mac)
2752 self.assertEqual(rx[Ether].dst, sep4.mac)
2753 self.assertEqual(rx[IPv6].src, ep1.ip6.address)
2754 self.assertEqual(rx[IPv6].dst, ep3.ip6.address)
2757 # and revert back to unprogrammed
2759 sep4.remove_vpp_config()
2761 rxs = self.send_and_expect(self.pg0, p6[0] * 17, self.pg7)
2764 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
2765 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
2766 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
2767 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
2768 self.assertEqual(rx[VXLAN].vni, 117)
2769 self.assertTrue(rx[VXLAN].flags.G)
2770 self.assertTrue(rx[VXLAN].flags.Instance)
2771 # redirect policy has been applied
2772 self.assertTrue(rx[VXLAN].gpflags.A)
2773 self.assertFalse(rx[VXLAN].gpflags.D)
2775 inner = rx[VXLAN].payload
2777 self.assertEqual(inner[Ether].src, routed_src_mac)
2778 self.assertEqual(inner[Ether].dst, sep4.mac)
2779 self.assertEqual(inner[IPv6].src, ep1.ip6.address)
2780 self.assertEqual(inner[IPv6].dst, ep3.ip6.address)
2782 c1.remove_vpp_config()
2783 c2.remove_vpp_config()
2786 # test the symmetric hash mode
2788 c1 = VppGbpContract(
2789 self, 220, 222, acl_index,
2790 [VppGbpContractRule(
2791 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2792 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
2793 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
2794 sep1.ip4, sep1.epg.rd),
2795 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
2796 sep2.ip4, sep2.epg.rd)]),
2798 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2799 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
2800 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
2801 sep3.ip6, sep3.epg.rd),
2802 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
2803 sep4.ip6, sep4.epg.rd)])],
2804 [ETH_P_IP, ETH_P_IPV6])
2807 c2 = VppGbpContract(
2808 self, 222, 220, acl_index,
2809 [VppGbpContractRule(
2810 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2811 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
2812 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
2813 sep1.ip4, sep1.epg.rd),
2814 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
2815 sep2.ip4, sep2.epg.rd)]),
2817 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2818 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
2819 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
2820 sep3.ip6, sep3.epg.rd),
2821 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
2822 sep4.ip6, sep4.epg.rd)])],
2823 [ETH_P_IP, ETH_P_IPV6])
2827 # send again with the contract preset, now packets arrive
2828 # at SEP1 for both directions
2830 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
2833 self.assertEqual(rx[Ether].src, routed_src_mac)
2834 self.assertEqual(rx[Ether].dst, sep1.mac)
2835 self.assertEqual(rx[IP].src, ep1.ip4.address)
2836 self.assertEqual(rx[IP].dst, ep3.ip4.address)
2838 rxs = self.send_and_expect(self.pg2, p4[1] * 17, sep1.itf)
2841 self.assertEqual(rx[Ether].src, routed_src_mac)
2842 self.assertEqual(rx[Ether].dst, sep1.mac)
2843 self.assertEqual(rx[IP].src, ep3.ip4.address)
2844 self.assertEqual(rx[IP].dst, ep1.ip4.address)
2847 # programme the unknown EP for the L3 tests
2849 sep4.add_vpp_config()
2852 # an L3 switch packet between local EPs in different EPGs
2853 # different dest ports on each so the are LB hashed differently
2855 p4 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
2856 IP(src=ep1.ip4.address, dst=ep2.ip4.address) /
2857 UDP(sport=1234, dport=1234) /
2859 (Ether(src=ep2.mac, dst=str(self.router_mac)) /
2860 IP(src=ep2.ip4.address, dst=ep1.ip4.address) /
2861 UDP(sport=1234, dport=1234) /
2863 p6 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
2864 IPv6(src=ep1.ip6.address, dst=ep2.ip6.address) /
2865 UDP(sport=1234, dport=1234) /
2867 (Ether(src=ep2.mac, dst=str(self.router_mac)) /
2868 IPv6(src=ep2.ip6.address, dst=ep1.ip6.address) /
2869 UDP(sport=1234, dport=1234) /
2872 c3 = VppGbpContract(
2873 self, 220, 221, acl_index,
2874 [VppGbpContractRule(
2875 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2876 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
2877 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
2878 sep1.ip4, sep1.epg.rd),
2879 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
2880 sep2.ip4, sep2.epg.rd)]),
2882 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2883 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
2884 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
2885 sep3.ip6, sep3.epg.rd),
2886 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
2887 sep4.ip6, sep4.epg.rd)])],
2888 [ETH_P_IP, ETH_P_IPV6])
2891 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
2894 self.assertEqual(rx[Ether].src, routed_src_mac)
2895 self.assertEqual(rx[Ether].dst, sep1.mac)
2896 self.assertEqual(rx[IP].src, ep1.ip4.address)
2897 self.assertEqual(rx[IP].dst, ep2.ip4.address)
2900 # learn a remote EP in EPG 221
2902 vx_tun_l3 = VppGbpVxlanTunnel(
2903 self, 444, rd1.rd_id,
2904 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3)
2905 vx_tun_l3.add_vpp_config()
2907 c4 = VppGbpContract(
2908 self, 221, 220, acl_index,
2909 [VppGbpContractRule(
2910 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2913 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2915 [ETH_P_IP, ETH_P_IPV6])
2918 p = (Ether(src=self.pg7.remote_mac,
2919 dst=self.pg7.local_mac) /
2920 IP(src=self.pg7.remote_ip4,
2921 dst=self.pg7.local_ip4) /
2922 UDP(sport=1234, dport=48879) /
2923 VXLAN(vni=444, gpid=221, flags=0x88) /
2924 Ether(src="00:22:22:22:22:33", dst=str(self.router_mac)) /
2925 IP(src="10.0.0.88", dst=ep1.ip4.address) /
2926 UDP(sport=1234, dport=1234) /
2929 rx = self.send_and_expect(self.pg7, [p], self.pg0)
2931 # endpoint learnt via the parent GBP-vxlan interface
2932 self.assertTrue(find_gbp_endpoint(self,
2933 vx_tun_l3._sw_if_index,
2936 p = (Ether(src=self.pg7.remote_mac,
2937 dst=self.pg7.local_mac) /
2938 IP(src=self.pg7.remote_ip4,
2939 dst=self.pg7.local_ip4) /
2940 UDP(sport=1234, dport=48879) /
2941 VXLAN(vni=444, gpid=221, flags=0x88) /
2942 Ether(src="00:22:22:22:22:33", dst=str(self.router_mac)) /
2943 IPv6(src="2001:10::88", dst=ep1.ip6.address) /
2944 UDP(sport=1234, dport=1234) /
2947 rx = self.send_and_expect(self.pg7, [p], self.pg0)
2949 # endpoint learnt via the parent GBP-vxlan interface
2950 self.assertTrue(find_gbp_endpoint(self,
2951 vx_tun_l3._sw_if_index,
2955 # L3 switch from local to remote EP
2957 p4 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
2958 IP(src=ep1.ip4.address, dst="10.0.0.88") /
2959 UDP(sport=1234, dport=1234) /
2961 p6 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
2962 IPv6(src=ep1.ip6.address, dst="2001:10::88") /
2963 UDP(sport=1234, dport=1234) /
2966 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
2969 self.assertEqual(rx[Ether].src, routed_src_mac)
2970 self.assertEqual(rx[Ether].dst, sep1.mac)
2971 self.assertEqual(rx[IP].src, ep1.ip4.address)
2972 self.assertEqual(rx[IP].dst, "10.0.0.88")
2974 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep4.itf)
2977 self.assertEqual(rx[Ether].src, routed_src_mac)
2978 self.assertEqual(rx[Ether].dst, sep4.mac)
2979 self.assertEqual(rx[IPv6].src, ep1.ip6.address)
2980 self.assertEqual(rx[IPv6].dst, "2001:10::88")
2983 # test the dst-ip hash mode
2985 c5 = VppGbpContract(
2986 self, 220, 221, acl_index,
2987 [VppGbpContractRule(
2988 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2989 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
2990 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
2991 sep1.ip4, sep1.epg.rd),
2992 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
2993 sep2.ip4, sep2.epg.rd)]),
2995 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2996 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
2997 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
2998 sep3.ip6, sep3.epg.rd),
2999 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3000 sep4.ip6, sep4.epg.rd)])],
3001 [ETH_P_IP, ETH_P_IPV6])
3004 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3007 self.assertEqual(rx[Ether].src, routed_src_mac)
3008 self.assertEqual(rx[Ether].dst, sep1.mac)
3009 self.assertEqual(rx[IP].src, ep1.ip4.address)
3010 self.assertEqual(rx[IP].dst, "10.0.0.88")
3012 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep3.itf)
3015 self.assertEqual(rx[Ether].src, routed_src_mac)
3016 self.assertEqual(rx[Ether].dst, sep3.mac)
3017 self.assertEqual(rx[IPv6].src, ep1.ip6.address)
3018 self.assertEqual(rx[IPv6].dst, "2001:10::88")
3023 self.pg7.unconfig_ip4()
3025 def test_gbp_l3_out(self):
3028 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
3029 self.vapi.cli("set logging class gbp debug")
3031 routed_dst_mac = "00:0c:0c:0c:0c:0c"
3032 routed_src_mac = "00:22:bd:f8:19:ff"
3037 t4 = VppIpTable(self, 1)
3039 t6 = VppIpTable(self, 1, True)
3042 rd1 = VppGbpRouteDomain(self, 2, t4, t6)
3043 rd1.add_vpp_config()
3045 self.loop0.set_mac(self.router_mac)
3048 # Bind the BVI to the RD
3050 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
3051 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
3054 # Pg7 hosts a BD's BUM
3055 # Pg1 some other l3 interface
3057 self.pg7.config_ip4()
3058 self.pg7.resolve_arp()
3061 # a GBP external bridge domains for the EPs
3063 bd1 = VppBridgeDomain(self, 1)
3064 bd1.add_vpp_config()
3065 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0)
3066 gbd1.add_vpp_config()
3069 # The Endpoint-groups in which the external endpoints exist
3071 epg_220 = VppGbpEndpointGroup(self, 220, rd1, gbd1,
3075 epg_220.add_vpp_config()
3077 # the BVIs have the subnets applied ...
3078 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 24)
3079 ip4_addr.add_vpp_config()
3080 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 64)
3081 ip6_addr.add_vpp_config()
3083 # ... which are L3-out subnets
3084 l3o_1 = VppGbpSubnet(
3085 self, rd1, "10.0.0.0", 24,
3086 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3088 l3o_1.add_vpp_config()
3091 # an external interface attached to the outside world and the
3094 vlan_100 = VppDot1QSubint(self, self.pg0, 100)
3096 ext_itf = VppGbpExtItf(self, vlan_100, bd1, rd1)
3097 ext_itf.add_vpp_config()
3100 # a multicast vxlan-gbp tunnel for broadcast in the BD
3102 tun_bm = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
3105 tun_bm.add_vpp_config()
3106 bp_bm = VppBridgeDomainPort(self, bd1, tun_bm,
3107 port_type=L2_PORT_TYPE.NORMAL)
3108 bp_bm.add_vpp_config()
3111 # an unicast vxlan-gbp for inter-BD traffic
3113 vx_tun_l3 = VppGbpVxlanTunnel(
3114 self, 444, rd1.rd_id,
3115 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3)
3116 vx_tun_l3.add_vpp_config()
3119 # packets destined to unkown addresses in the BVI's subnet
3122 p4 = (Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
3124 IP(src="10.0.0.1", dst="10.0.0.88") /
3125 UDP(sport=1234, dport=1234) /
3127 p6 = (Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
3129 IPv6(src="2001:10::1", dst="2001:10::88") /
3130 UDP(sport=1234, dport=1234) /
3133 rxs = self.send_and_expect(self.pg0, p4 * 1, self.pg7)
3136 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3137 # self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3138 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3139 self.assertEqual(rx[IP].dst, "239.1.1.1")
3140 self.assertEqual(rx[VXLAN].vni, 88)
3141 self.assertTrue(rx[VXLAN].flags.G)
3142 self.assertTrue(rx[VXLAN].flags.Instance)
3143 # policy is not applied since we don't know where it's going
3144 self.assertFalse(rx[VXLAN].gpflags.A)
3145 self.assertFalse(rx[VXLAN].gpflags.D)
3147 inner = rx[VXLAN].payload
3149 self.assertTrue(inner.haslayer(ARP))
3152 # An external Endpoint
3154 eep = VppGbpEndpoint(self, vlan_100,
3156 "10.0.0.1", "11.0.0.1",
3157 "2001:10::1", "3001::1",
3158 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
3159 eep.add_vpp_config()
3164 rep = VppGbpEndpoint(self, vx_tun_l3,
3166 "10.0.0.101", "11.0.0.101",
3167 "2001:10::101", "3001::101",
3168 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
3170 self.pg7.remote_ip4,
3172 rep.add_vpp_config()
3175 # remote to external
3177 p = (Ether(src=self.pg7.remote_mac,
3178 dst=self.pg7.local_mac) /
3179 IP(src=self.pg7.remote_ip4,
3180 dst=self.pg7.local_ip4) /
3181 UDP(sport=1234, dport=48879) /
3182 VXLAN(vni=444, gpid=220, flags=0x88) /
3183 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
3184 IP(src="10.0.0.101", dst="10.0.0.1") /
3185 UDP(sport=1234, dport=1234) /
3188 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
3191 # A subnet reachable through the external EP
3193 ip_220 = VppIpRoute(self, "10.220.0.0", 24,
3194 [VppRoutePath(eep.ip4.address,
3195 eep.epg.bvi.sw_if_index)],
3196 table_id=t4.table_id)
3197 ip_220.add_vpp_config()
3199 l3o_220 = VppGbpSubnet(
3200 self, rd1, "10.220.0.0", 24,
3201 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3203 l3o_220.add_vpp_config()
3205 p = (Ether(src=self.pg7.remote_mac,
3206 dst=self.pg7.local_mac) /
3207 IP(src=self.pg7.remote_ip4,
3208 dst=self.pg7.local_ip4) /
3209 UDP(sport=1234, dport=48879) /
3210 VXLAN(vni=444, gpid=220, flags=0x88) /
3211 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
3212 IP(src="10.0.0.101", dst="10.220.0.1") /
3213 UDP(sport=1234, dport=1234) /
3216 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
3219 # another external subnet, this time in a different EPG
3221 ip_200 = VppIpRoute(self, "10.200.0.0", 24,
3222 [VppRoutePath(eep.ip4.address,
3223 eep.epg.bvi.sw_if_index)],
3224 table_id=t4.table_id)
3225 ip_200.add_vpp_config()
3227 l3o_200 = VppGbpSubnet(
3228 self, rd1, "10.200.0.0", 24,
3229 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3231 l3o_200.add_vpp_config()
3233 p = (Ether(src=self.pg7.remote_mac,
3234 dst=self.pg7.local_mac) /
3235 IP(src=self.pg7.remote_ip4,
3236 dst=self.pg7.local_ip4) /
3237 UDP(sport=1234, dport=48879) /
3238 VXLAN(vni=444, gpid=220, flags=0x88) /
3239 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
3240 IP(src="10.0.0.101", dst="10.200.0.1") /
3241 UDP(sport=1234, dport=1234) /
3245 # packets dropped due to lack of contract.
3247 rxs = self.send_and_assert_no_replies(self.pg7, p * 1)
3250 # from the the subnet in EPG 220 beyond the external to remote
3252 p4 = (Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
3254 IP(src="10.220.0.1", dst=rep.ip4.address) /
3255 UDP(sport=1234, dport=1234) /
3258 rxs = self.send_and_expect(self.pg0, p4 * 1, self.pg7)
3261 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3262 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3263 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3264 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
3265 self.assertEqual(rx[VXLAN].vni, 444)
3266 self.assertTrue(rx[VXLAN].flags.G)
3267 self.assertTrue(rx[VXLAN].flags.Instance)
3268 self.assertTrue(rx[VXLAN].gpflags.A)
3269 self.assertFalse(rx[VXLAN].gpflags.D)
3272 # from the the subnet in EPG 200 beyond the external to remote
3273 # dropped due to no contract
3275 p4 = (Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
3277 IP(src="10.200.0.1", dst=rep.ip4.address) /
3278 UDP(sport=1234, dport=1234) /
3281 rxs = self.send_and_assert_no_replies(self.pg0, p4 * 1)
3286 acl = VppGbpAcl(self)
3287 rule = acl.create_rule(permit_deny=1, proto=17)
3288 rule2 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
3289 acl_index = acl.add_vpp_config([rule, rule2])
3290 c1 = VppGbpContract(
3291 self, 200, 220, acl_index,
3292 [VppGbpContractRule(
3293 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3296 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3298 [ETH_P_IP, ETH_P_IPV6])
3301 rxs = self.send_and_expect(self.pg0, p4 * 1, self.pg7)
3304 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3305 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3306 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3307 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
3308 self.assertEqual(rx[VXLAN].vni, 444)
3309 self.assertTrue(rx[VXLAN].flags.G)
3310 self.assertTrue(rx[VXLAN].flags.Instance)
3311 self.assertTrue(rx[VXLAN].gpflags.A)
3312 self.assertFalse(rx[VXLAN].gpflags.D)
3317 self.pg7.unconfig_ip4()
3320 if __name__ == '__main__':
3321 unittest.main(testRunner=VppTestRunner)