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
18 from vpp_papi_provider import L2_PORT_TYPE
19 from vpp_papi import VppEnum
21 from scapy.packet import Raw
22 from scapy.layers.l2 import Ether, ARP, Dot1Q
23 from scapy.layers.inet import IP, UDP
24 from scapy.layers.inet6 import IPv6, ICMPv6ND_NS, ICMPv6NDOptSrcLLAddr, \
26 from scapy.utils6 import in6_getnsma, in6_getnsmac
27 from scapy.layers.vxlan import VXLAN
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 = VppMacAddress(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 == 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):
71 return self.vmac.bytes
75 return self.vmac.address
79 return self.itf.remote_mac
99 return [self.ip4, self.ip6]
103 return [self.fip4, self.fip6]
105 def __init__(self, test, itf, epg, recirc, ip4, fip4, ip6, fip6,
115 self._ip4 = VppIpAddress(ip4)
116 self._fip4 = VppIpAddress(fip4)
117 self._ip6 = VppIpAddress(ip6)
118 self._fip6 = VppIpAddress(fip6)
121 self.vmac = VppMacAddress(self.itf.remote_mac)
123 self.vmac = VppMacAddress("00:00:00:00:00:00")
126 self.tun_src = VppIpAddress(tun_src)
127 self.tun_dst = VppIpAddress(tun_dst)
129 def add_vpp_config(self):
130 res = self._test.vapi.gbp_endpoint_add(
131 self.itf.sw_if_index,
132 [self.ip4.encode(), self.ip6.encode()],
136 self.tun_src.encode(),
137 self.tun_dst.encode())
138 self.handle = res.handle
139 self._test.registry.register(self, self._test.logger)
141 def remove_vpp_config(self):
142 self._test.vapi.gbp_endpoint_del(self.handle)
145 return self.object_id()
148 return "gbp-endpoint:[%d==%d:%s:%d]" % (self.handle,
149 self.itf.sw_if_index,
153 def query_vpp_config(self):
154 return find_gbp_endpoint(self._test,
155 self.itf.sw_if_index,
159 class VppGbpRecirc(VppObject):
161 GBP Recirculation Interface
164 def __init__(self, test, epg, recirc, is_ext=False):
170 def add_vpp_config(self):
171 self._test.vapi.gbp_recirc_add_del(
173 self.recirc.sw_if_index,
176 self._test.registry.register(self, self._test.logger)
178 def remove_vpp_config(self):
179 self._test.vapi.gbp_recirc_add_del(
181 self.recirc.sw_if_index,
186 return self.object_id()
189 return "gbp-recirc:[%d]" % (self.recirc.sw_if_index)
191 def query_vpp_config(self):
192 rs = self._test.vapi.gbp_recirc_dump()
194 if r.recirc.sw_if_index == self.recirc.sw_if_index:
199 class VppGbpExtItf(VppObject):
201 GBP ExtItfulation Interface
204 def __init__(self, test, itf, bd, rd):
210 def add_vpp_config(self):
211 self._test.vapi.gbp_ext_itf_add_del(
213 self.itf.sw_if_index,
216 self._test.registry.register(self, self._test.logger)
218 def remove_vpp_config(self):
219 self._test.vapi.gbp_ext_itf_add_del(
221 self.itf.sw_if_index,
226 return self.object_id()
229 return "gbp-ext-itf:[%d]" % (self.itf.sw_if_index)
231 def query_vpp_config(self):
232 rs = self._test.vapi.gbp_ext_itf_dump()
234 if r.ext_itf.sw_if_index == self.itf.sw_if_index:
239 class VppGbpSubnet(VppObject):
243 def __init__(self, test, rd, address, address_len,
244 type, sw_if_index=None, epg=None):
246 self.rd_id = rd.rd_id
247 self.prefix = VppIpPrefix(address, address_len)
249 self.sw_if_index = sw_if_index
252 def add_vpp_config(self):
253 self._test.vapi.gbp_subnet_add_del(
256 self.prefix.encode(),
258 sw_if_index=self.sw_if_index if self.sw_if_index else 0xffffffff,
259 epg_id=self.epg if self.epg else 0xffff)
260 self._test.registry.register(self, self._test.logger)
262 def remove_vpp_config(self):
263 self._test.vapi.gbp_subnet_add_del(
266 self.prefix.encode(),
270 return self.object_id()
273 return "gbp-subnet:[%d-%s]" % (self.rd_id, self.prefix)
275 def query_vpp_config(self):
276 ss = self._test.vapi.gbp_subnet_dump()
278 if s.subnet.rd_id == self.rd_id and \
279 s.subnet.type == self.type and \
280 s.subnet.prefix == self.prefix:
285 class VppGbpEndpointGroup(VppObject):
290 def __init__(self, test, epg, rd, bd, uplink,
291 bvi, bvi_ip4, bvi_ip6=None):
295 self.bvi_ip4 = VppIpAddress(bvi_ip4)
296 self.bvi_ip6 = VppIpAddress(bvi_ip6)
301 def add_vpp_config(self):
302 self._test.vapi.gbp_endpoint_group_add(
306 self.uplink.sw_if_index if self.uplink else INDEX_INVALID)
307 self._test.registry.register(self, self._test.logger)
309 def remove_vpp_config(self):
310 self._test.vapi.gbp_endpoint_group_del(
314 return self.object_id()
317 return "gbp-endpoint-group:[%d]" % (self.epg)
319 def query_vpp_config(self):
320 epgs = self._test.vapi.gbp_endpoint_group_dump()
322 if epg.epg.epg_id == self.epg:
327 class VppGbpBridgeDomain(VppObject):
332 def __init__(self, test, bd, bvi, uu_flood=None, learn=True):
335 self.uu_flood = uu_flood
338 e = VppEnum.vl_api_gbp_bridge_domain_flags_t
340 self.learn = e.GBP_BD_API_FLAG_NONE
342 self.learn = e.GBP_BD_API_FLAG_DO_NOT_LEARN
344 def add_vpp_config(self):
345 self._test.vapi.gbp_bridge_domain_add(
348 self.bvi.sw_if_index,
349 self.uu_flood.sw_if_index if self.uu_flood else INDEX_INVALID)
350 self._test.registry.register(self, self._test.logger)
352 def remove_vpp_config(self):
353 self._test.vapi.gbp_bridge_domain_del(self.bd.bd_id)
356 return self.object_id()
359 return "gbp-bridge-domain:[%d]" % (self.bd.bd_id)
361 def query_vpp_config(self):
362 bds = self._test.vapi.gbp_bridge_domain_dump()
364 if bd.bd.bd_id == self.bd.bd_id:
369 class VppGbpRouteDomain(VppObject):
374 def __init__(self, test, rd_id, t4, t6, ip4_uu=None, ip6_uu=None):
382 def add_vpp_config(self):
383 self._test.vapi.gbp_route_domain_add(
387 self.ip4_uu.sw_if_index if self.ip4_uu else INDEX_INVALID,
388 self.ip6_uu.sw_if_index if self.ip6_uu else INDEX_INVALID)
389 self._test.registry.register(self, self._test.logger)
391 def remove_vpp_config(self):
392 self._test.vapi.gbp_route_domain_del(self.rd_id)
395 return self.object_id()
398 return "gbp-route-domain:[%d]" % (self.rd_id)
400 def query_vpp_config(self):
401 rds = self._test.vapi.gbp_route_domain_dump()
403 if rd.rd.rd_id == self.rd_id:
408 class VppGbpContractNextHop():
409 def __init__(self, mac, bd, ip, rd):
416 return {'ip': self.ip.encode(),
417 'mac': self.mac.encode(),
418 'bd_id': self.bd.bd.bd_id,
419 'rd_id': self.rd.rd_id}
422 class VppGbpContractRule():
423 def __init__(self, action, hash_mode, nhs=[]):
425 self.hash_mode = hash_mode
431 nhs.append(nh.encode())
434 return {'action': self.action,
436 'hash_mode': self.hash_mode,
437 'n_nhs': len(self.nhs),
441 class VppGbpContract(VppObject):
446 def __init__(self, test, src_epg, dst_epg, acl_index, rules=[]):
448 self.acl_index = acl_index
449 self.src_epg = src_epg
450 self.dst_epg = dst_epg
453 def add_vpp_config(self):
456 rules.append(r.encode())
457 self._test.vapi.gbp_contract_add_del(
463 self._test.registry.register(self, self._test.logger)
465 def remove_vpp_config(self):
466 self._test.vapi.gbp_contract_add_del(
474 return self.object_id()
477 return "gbp-contract:[%d:%s:%d]" % (self.src_epg,
481 def query_vpp_config(self):
482 cs = self._test.vapi.gbp_contract_dump()
484 if c.contract.src_epg == self.src_epg \
485 and c.contract.dst_epg == self.dst_epg:
490 class VppGbpVxlanTunnel(VppInterface):
495 def __init__(self, test, vni, bd_rd_id, mode):
496 super(VppGbpVxlanTunnel, self).__init__(test)
499 self.bd_rd_id = bd_rd_id
502 def add_vpp_config(self):
503 r = self._test.vapi.gbp_vxlan_tunnel_add(
507 self.set_sw_if_index(r.sw_if_index)
508 self._test.registry.register(self, self._test.logger)
510 def remove_vpp_config(self):
511 self._test.vapi.gbp_vxlan_tunnel_del(self.vni)
514 return self.object_id()
517 return "gbp-vxlan:%d" % (self.vni)
519 def query_vpp_config(self):
520 return find_gbp_vxlan(self._test, self.vni)
523 class VppGbpAcl(VppObject):
528 def __init__(self, test):
530 self.acl_index = 4294967295
532 def create_rule(self, is_ipv6=0, permit_deny=0, proto=-1,
533 s_prefix=0, s_ip='\x00\x00\x00\x00', sport_from=0,
534 sport_to=65535, d_prefix=0, d_ip='\x00\x00\x00\x00',
535 dport_from=0, dport_to=65535):
536 if proto == -1 or proto == 0:
539 elif proto == 1 or proto == 58:
542 rule = ({'is_permit': permit_deny, 'is_ipv6': is_ipv6, 'proto': proto,
543 'srcport_or_icmptype_first': sport_from,
544 'srcport_or_icmptype_last': sport_to,
545 'src_ip_prefix_len': s_prefix,
547 'dstport_or_icmpcode_first': dport_from,
548 'dstport_or_icmpcode_last': dport_to,
549 'dst_ip_prefix_len': d_prefix,
550 'dst_ip_addr': d_ip})
553 def add_vpp_config(self, rules):
555 reply = self._test.vapi.acl_add_replace(self.acl_index,
558 self.acl_index = reply.acl_index
559 return self.acl_index
561 def remove_vpp_config(self):
562 self._test.vapi.acl_del(self.acl_index)
565 return self.object_id()
568 return "gbp-acl:[%d]" % (self.acl_index)
570 def query_vpp_config(self):
571 cs = self._test.vapi.acl_dump()
573 if c.acl_index == self.acl_index:
578 class TestGBP(VppTestCase):
579 """ GBP Test Case """
582 super(TestGBP, self).setUp()
584 self.create_pg_interfaces(range(9))
585 self.create_loopback_interfaces(8)
587 self.router_mac = VppMacAddress("00:11:22:33:44:55")
589 for i in self.pg_interfaces:
591 for i in self.lo_interfaces:
595 for i in self.pg_interfaces:
598 super(TestGBP, self).tearDown()
600 def send_and_expect_bridged(self, src, tx, dst):
601 rx = self.send_and_expect(src, tx, dst)
604 self.assertEqual(r[Ether].src, tx[0][Ether].src)
605 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
606 self.assertEqual(r[IP].src, tx[0][IP].src)
607 self.assertEqual(r[IP].dst, tx[0][IP].dst)
610 def send_and_expect_bridged6(self, src, tx, dst):
611 rx = self.send_and_expect(src, tx, dst)
614 self.assertEqual(r[Ether].src, tx[0][Ether].src)
615 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
616 self.assertEqual(r[IPv6].src, tx[0][IPv6].src)
617 self.assertEqual(r[IPv6].dst, tx[0][IPv6].dst)
620 def send_and_expect_routed(self, src, tx, dst, src_mac):
621 rx = self.send_and_expect(src, tx, dst)
624 self.assertEqual(r[Ether].src, src_mac)
625 self.assertEqual(r[Ether].dst, dst.remote_mac)
626 self.assertEqual(r[IP].src, tx[0][IP].src)
627 self.assertEqual(r[IP].dst, tx[0][IP].dst)
630 def send_and_expect_natted(self, src, tx, dst, src_ip):
631 rx = self.send_and_expect(src, tx, dst)
634 self.assertEqual(r[Ether].src, tx[0][Ether].src)
635 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
636 self.assertEqual(r[IP].src, src_ip)
637 self.assertEqual(r[IP].dst, tx[0][IP].dst)
640 def send_and_expect_natted6(self, src, tx, dst, src_ip):
641 rx = self.send_and_expect(src, tx, dst)
644 self.assertEqual(r[Ether].src, tx[0][Ether].src)
645 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
646 self.assertEqual(r[IPv6].src, src_ip)
647 self.assertEqual(r[IPv6].dst, tx[0][IPv6].dst)
650 def send_and_expect_unnatted(self, src, tx, dst, dst_ip):
651 rx = self.send_and_expect(src, tx, dst)
654 self.assertEqual(r[Ether].src, tx[0][Ether].src)
655 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
656 self.assertEqual(r[IP].dst, dst_ip)
657 self.assertEqual(r[IP].src, tx[0][IP].src)
660 def send_and_expect_unnatted6(self, src, tx, dst, dst_ip):
661 rx = self.send_and_expect(src, tx, dst)
664 self.assertEqual(r[Ether].src, tx[0][Ether].src)
665 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
666 self.assertEqual(r[IPv6].dst, dst_ip)
667 self.assertEqual(r[IPv6].src, tx[0][IPv6].src)
670 def send_and_expect_double_natted(self, src, tx, dst, src_ip, dst_ip):
671 rx = self.send_and_expect(src, tx, dst)
674 self.assertEqual(r[Ether].src, self.router_mac.address)
675 self.assertEqual(r[Ether].dst, dst.remote_mac)
676 self.assertEqual(r[IP].dst, dst_ip)
677 self.assertEqual(r[IP].src, src_ip)
680 def send_and_expect_double_natted6(self, src, tx, dst, src_ip, dst_ip):
681 rx = self.send_and_expect(src, tx, dst)
684 self.assertEqual(r[Ether].src, self.router_mac.address)
685 self.assertEqual(r[Ether].dst, dst.remote_mac)
686 self.assertEqual(r[IPv6].dst, dst_ip)
687 self.assertEqual(r[IPv6].src, src_ip)
691 """ Group Based Policy """
693 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
698 bd1 = VppBridgeDomain(self, 1)
699 bd2 = VppBridgeDomain(self, 2)
700 bd20 = VppBridgeDomain(self, 20)
704 bd20.add_vpp_config()
706 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0)
707 gbd2 = VppGbpBridgeDomain(self, bd2, self.loop1)
708 gbd20 = VppGbpBridgeDomain(self, bd20, self.loop2)
710 gbd1.add_vpp_config()
711 gbd2.add_vpp_config()
712 gbd20.add_vpp_config()
717 gt4 = VppIpTable(self, 0)
719 gt6 = VppIpTable(self, 0, is_ip6=True)
721 nt4 = VppIpTable(self, 20)
723 nt6 = VppIpTable(self, 20, is_ip6=True)
726 rd0 = VppGbpRouteDomain(self, 0, gt4, gt6, None, None)
727 rd20 = VppGbpRouteDomain(self, 20, nt4, nt6, None, None)
730 rd20.add_vpp_config()
733 # 3 EPGs, 2 of which share a BD.
734 # 2 NAT EPGs, one for floating-IP subnets, the other for internet
736 epgs = [VppGbpEndpointGroup(self, 220, rd0, gbd1, self.pg4,
740 VppGbpEndpointGroup(self, 221, rd0, gbd1, self.pg5,
744 VppGbpEndpointGroup(self, 222, rd0, gbd2, self.pg6,
748 VppGbpEndpointGroup(self, 333, rd20, gbd20, self.pg7,
752 VppGbpEndpointGroup(self, 444, rd20, gbd20, self.pg8,
756 recircs = [VppGbpRecirc(self, epgs[0],
758 VppGbpRecirc(self, epgs[1],
760 VppGbpRecirc(self, epgs[2],
762 VppGbpRecirc(self, epgs[3],
763 self.loop6, is_ext=True),
764 VppGbpRecirc(self, epgs[4],
765 self.loop7, is_ext=True)]
768 recirc_nat = recircs[3]
771 # 4 end-points, 2 in the same subnet, 3 in the same BD
773 eps = [VppGbpEndpoint(self, self.pg0,
775 "10.0.0.1", "11.0.0.1",
776 "2001:10::1", "3001::1"),
777 VppGbpEndpoint(self, self.pg1,
779 "10.0.0.2", "11.0.0.2",
780 "2001:10::2", "3001::2"),
781 VppGbpEndpoint(self, self.pg2,
783 "10.0.1.1", "11.0.0.3",
784 "2001:10:1::1", "3001::3"),
785 VppGbpEndpoint(self, self.pg3,
787 "10.0.2.1", "11.0.0.4",
788 "2001:10:2::1", "3001::4")]
791 # Config related to each of the EPGs
794 # IP config on the BVI interfaces
795 if epg != epgs[1] and epg != epgs[4]:
796 VppIpInterfaceBind(self, epg.bvi, epg.rd.t4).add_vpp_config()
797 VppIpInterfaceBind(self, epg.bvi, epg.rd.t6).add_vpp_config()
798 self.vapi.sw_interface_set_mac_address(
800 self.router_mac.bytes)
802 # The BVIs are NAT inside interfaces
803 self.vapi.nat44_interface_add_del_feature(epg.bvi.sw_if_index,
806 self.vapi.nat66_add_del_interface(epg.bvi.sw_if_index,
810 if_ip4 = VppIpInterfaceAddress(self, epg.bvi, epg.bvi_ip4, 32)
811 if_ip6 = VppIpInterfaceAddress(self, epg.bvi, epg.bvi_ip6, 128)
812 if_ip4.add_vpp_config()
813 if_ip6.add_vpp_config()
815 # EPG uplink interfaces in the RD
816 VppIpInterfaceBind(self, epg.uplink, epg.rd.t4).add_vpp_config()
817 VppIpInterfaceBind(self, epg.uplink, epg.rd.t6).add_vpp_config()
819 # add the BD ARP termination entry for BVI IP
820 epg.bd_arp_ip4 = VppBridgeDomainArpEntry(self, epg.bd.bd,
821 self.router_mac.address,
823 epg.bd_arp_ip6 = VppBridgeDomainArpEntry(self, epg.bd.bd,
824 self.router_mac.address,
826 epg.bd_arp_ip4.add_vpp_config()
827 epg.bd_arp_ip6.add_vpp_config()
832 for recirc in recircs:
833 # EPG's ingress recirculation interface maps to its RD
834 VppIpInterfaceBind(self, recirc.recirc,
835 recirc.epg.rd.t4).add_vpp_config()
836 VppIpInterfaceBind(self, recirc.recirc,
837 recirc.epg.rd.t6).add_vpp_config()
839 self.vapi.nat44_interface_add_del_feature(
840 recirc.recirc.sw_if_index,
843 self.vapi.nat66_add_del_interface(
844 recirc.recirc.sw_if_index,
848 recirc.add_vpp_config()
850 for recirc in recircs:
851 self.assertTrue(find_bridge_domain_port(self,
852 recirc.epg.bd.bd.bd_id,
853 recirc.recirc.sw_if_index))
856 self.pg_enable_capture(self.pg_interfaces)
859 # routes to the endpoints. We need these since there are no
860 # adj-fibs due to the fact the the BVI address has /32 and
861 # the subnet is not attached.
863 for (ip, fip) in zip(ep.ips, ep.fips):
864 # Add static mappings for each EP from the 10/8 to 11/8 network
866 self.vapi.nat44_add_del_static_mapping(ip.bytes,
871 self.vapi.nat66_add_del_static_mapping(ip.bytes,
878 self.logger.info(self.vapi.cli("sh gbp endpoint"))
880 # ... results in a Gratuitous ARP/ND on the EPG's uplink
881 rx = ep.epg.uplink.get_capture(len(ep.ips), timeout=0.2)
883 for ii, ip in enumerate(ep.ips):
887 self.assertTrue(p.haslayer(ICMPv6ND_NA))
888 self.assertEqual(p[ICMPv6ND_NA].tgt, ip.address)
890 self.assertTrue(p.haslayer(ARP))
891 self.assertEqual(p[ARP].psrc, ip.address)
892 self.assertEqual(p[ARP].pdst, ip.address)
894 # add the BD ARP termination entry for floating IP
896 ba = VppBridgeDomainArpEntry(self, epg_nat.bd.bd, ep.mac, fip)
899 # floating IPs route via EPG recirc
900 r = VppIpRoute(self, fip.address, fip.length,
901 [VppRoutePath(fip.address,
902 ep.recirc.recirc.sw_if_index,
904 proto=fip.dpo_proto)],
909 # L2 FIB entries in the NAT EPG BD to bridge the packets from
910 # the outside direct to the internal EPG
911 lf = VppL2FibEntry(self, epg_nat.bd.bd, ep.mac,
912 ep.recirc.recirc, bvi_mac=0)
916 # ARP packets for unknown IP are sent to the EPG uplink
918 pkt_arp = (Ether(dst="ff:ff:ff:ff:ff:ff",
919 src=self.pg0.remote_mac) /
921 hwdst="ff:ff:ff:ff:ff:ff",
922 hwsrc=self.pg0.remote_mac,
926 self.vapi.cli("clear trace")
927 self.pg0.add_stream(pkt_arp)
929 self.pg_enable_capture(self.pg_interfaces)
932 rxd = epgs[0].uplink.get_capture(1)
935 # ARP/ND packets get a response
937 pkt_arp = (Ether(dst="ff:ff:ff:ff:ff:ff",
938 src=self.pg0.remote_mac) /
940 hwdst="ff:ff:ff:ff:ff:ff",
941 hwsrc=self.pg0.remote_mac,
942 pdst=epgs[0].bvi_ip4.address,
943 psrc=eps[0].ip4.address))
945 self.send_and_expect(self.pg0, [pkt_arp], self.pg0)
947 nsma = in6_getnsma(inet_pton(AF_INET6, eps[0].ip6.address))
948 d = inet_ntop(AF_INET6, nsma)
949 pkt_nd = (Ether(dst=in6_getnsmac(nsma),
950 src=self.pg0.remote_mac) /
951 IPv6(dst=d, src=eps[0].ip6.address) /
952 ICMPv6ND_NS(tgt=epgs[0].bvi_ip6.address) /
953 ICMPv6NDOptSrcLLAddr(lladdr=self.pg0.remote_mac))
954 self.send_and_expect(self.pg0, [pkt_nd], self.pg0)
957 # broadcast packets are flooded
959 pkt_bcast = (Ether(dst="ff:ff:ff:ff:ff:ff",
960 src=self.pg0.remote_mac) /
961 IP(src=eps[0].ip4.address, dst="232.1.1.1") /
962 UDP(sport=1234, dport=1234) /
965 self.vapi.cli("clear trace")
966 self.pg0.add_stream(pkt_bcast)
968 self.pg_enable_capture(self.pg_interfaces)
971 rxd = eps[1].itf.get_capture(1)
972 self.assertEqual(rxd[0][Ether].dst, pkt_bcast[Ether].dst)
973 rxd = epgs[0].uplink.get_capture(1)
974 self.assertEqual(rxd[0][Ether].dst, pkt_bcast[Ether].dst)
977 # packets to non-local L3 destinations dropped
979 pkt_intra_epg_220_ip4 = (Ether(src=self.pg0.remote_mac,
980 dst=self.router_mac.address) /
981 IP(src=eps[0].ip4.address,
983 UDP(sport=1234, dport=1234) /
985 pkt_inter_epg_222_ip4 = (Ether(src=self.pg0.remote_mac,
986 dst=self.router_mac.address) /
987 IP(src=eps[0].ip4.address,
989 UDP(sport=1234, dport=1234) /
992 self.send_and_assert_no_replies(self.pg0, pkt_intra_epg_220_ip4 * 65)
994 pkt_inter_epg_222_ip6 = (Ether(src=self.pg0.remote_mac,
995 dst=self.router_mac.address) /
996 IPv6(src=eps[0].ip6.address,
998 UDP(sport=1234, dport=1234) /
1000 self.send_and_assert_no_replies(self.pg0, pkt_inter_epg_222_ip6 * 65)
1003 # Add the subnet routes
1006 self, rd0, "10.0.0.0", 24,
1007 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1009 self, rd0, "10.0.1.0", 24,
1010 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1012 self, rd0, "10.0.2.0", 24,
1013 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1015 self, rd0, "2001:10::1", 64,
1016 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1018 self, rd0, "2001:10:1::1", 64,
1019 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1021 self, rd0, "2001:10:2::1", 64,
1022 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1023 s41.add_vpp_config()
1024 s42.add_vpp_config()
1025 s43.add_vpp_config()
1026 s61.add_vpp_config()
1027 s62.add_vpp_config()
1028 s63.add_vpp_config()
1030 self.send_and_expect_bridged(eps[0].itf,
1031 pkt_intra_epg_220_ip4 * 65,
1033 self.send_and_expect_bridged(eps[0].itf,
1034 pkt_inter_epg_222_ip4 * 65,
1036 self.send_and_expect_bridged6(eps[0].itf,
1037 pkt_inter_epg_222_ip6 * 65,
1040 self.logger.info(self.vapi.cli("sh ip fib 11.0.0.2"))
1041 self.logger.info(self.vapi.cli("sh gbp endpoint-group"))
1042 self.logger.info(self.vapi.cli("sh gbp endpoint"))
1043 self.logger.info(self.vapi.cli("sh gbp recirc"))
1044 self.logger.info(self.vapi.cli("sh int"))
1045 self.logger.info(self.vapi.cli("sh int addr"))
1046 self.logger.info(self.vapi.cli("sh int feat loop6"))
1047 self.logger.info(self.vapi.cli("sh vlib graph ip4-gbp-src-classify"))
1048 self.logger.info(self.vapi.cli("sh int feat loop3"))
1049 self.logger.info(self.vapi.cli("sh int feat pg0"))
1052 # Packet destined to unknown unicast is sent on the epg uplink ...
1054 pkt_intra_epg_220_to_uplink = (Ether(src=self.pg0.remote_mac,
1055 dst="00:00:00:33:44:55") /
1056 IP(src=eps[0].ip4.address,
1058 UDP(sport=1234, dport=1234) /
1061 self.send_and_expect_bridged(eps[0].itf,
1062 pkt_intra_epg_220_to_uplink * 65,
1064 # ... and nowhere else
1065 self.pg1.get_capture(0, timeout=0.1)
1066 self.pg1.assert_nothing_captured(remark="Flood onto other VMS")
1068 pkt_intra_epg_221_to_uplink = (Ether(src=self.pg2.remote_mac,
1069 dst="00:00:00:33:44:66") /
1070 IP(src=eps[0].ip4.address,
1072 UDP(sport=1234, dport=1234) /
1075 self.send_and_expect_bridged(eps[2].itf,
1076 pkt_intra_epg_221_to_uplink * 65,
1080 # Packets from the uplink are forwarded in the absence of a contract
1082 pkt_intra_epg_220_from_uplink = (Ether(src="00:00:00:33:44:55",
1083 dst=self.pg0.remote_mac) /
1084 IP(src=eps[0].ip4.address,
1086 UDP(sport=1234, dport=1234) /
1089 self.send_and_expect_bridged(self.pg4,
1090 pkt_intra_epg_220_from_uplink * 65,
1094 # in the absence of policy, endpoints in the same EPG
1097 pkt_intra_epg = (Ether(src=self.pg0.remote_mac,
1098 dst=self.pg1.remote_mac) /
1099 IP(src=eps[0].ip4.address,
1100 dst=eps[1].ip4.address) /
1101 UDP(sport=1234, dport=1234) /
1104 self.send_and_expect_bridged(self.pg0, pkt_intra_epg * 65, self.pg1)
1107 # in the abscense of policy, endpoints in the different EPG
1108 # cannot communicate
1110 pkt_inter_epg_220_to_221 = (Ether(src=self.pg0.remote_mac,
1111 dst=self.pg2.remote_mac) /
1112 IP(src=eps[0].ip4.address,
1113 dst=eps[2].ip4.address) /
1114 UDP(sport=1234, dport=1234) /
1116 pkt_inter_epg_221_to_220 = (Ether(src=self.pg2.remote_mac,
1117 dst=self.pg0.remote_mac) /
1118 IP(src=eps[2].ip4.address,
1119 dst=eps[0].ip4.address) /
1120 UDP(sport=1234, dport=1234) /
1122 pkt_inter_epg_220_to_222 = (Ether(src=self.pg0.remote_mac,
1123 dst=self.router_mac.address) /
1124 IP(src=eps[0].ip4.address,
1125 dst=eps[3].ip4.address) /
1126 UDP(sport=1234, dport=1234) /
1129 self.send_and_assert_no_replies(eps[0].itf,
1130 pkt_inter_epg_220_to_221 * 65)
1131 self.send_and_assert_no_replies(eps[0].itf,
1132 pkt_inter_epg_220_to_222 * 65)
1135 # A uni-directional contract from EPG 220 -> 221
1137 acl = VppGbpAcl(self)
1138 rule = acl.create_rule(permit_deny=1, proto=17)
1139 rule2 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
1140 acl_index = acl.add_vpp_config([rule, rule2])
1141 c1 = VppGbpContract(
1142 self, 220, 221, acl_index,
1143 [VppGbpContractRule(
1144 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1147 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
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,
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 # check that inter group is still disabled for the groups
1180 # not in the contract.
1182 self.send_and_assert_no_replies(eps[0].itf,
1183 pkt_inter_epg_220_to_222 * 65)
1186 # A uni-directional contract from EPG 220 -> 222 'L3 routed'
1188 c3 = VppGbpContract(
1189 self, 220, 222, acl_index,
1190 [VppGbpContractRule(
1191 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1194 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1199 self.logger.info(self.vapi.cli("sh gbp contract"))
1201 self.send_and_expect_routed(eps[0].itf,
1202 pkt_inter_epg_220_to_222 * 65,
1204 self.router_mac.address)
1207 # remove both contracts, traffic stops in both directions
1209 c2.remove_vpp_config()
1210 c1.remove_vpp_config()
1211 c3.remove_vpp_config()
1212 acl.remove_vpp_config()
1214 self.send_and_assert_no_replies(eps[2].itf,
1215 pkt_inter_epg_221_to_220 * 65)
1216 self.send_and_assert_no_replies(eps[0].itf,
1217 pkt_inter_epg_220_to_221 * 65)
1218 self.send_and_expect_bridged(eps[0].itf,
1223 # EPs to the outside world
1226 # in the EP's RD an external subnet via the NAT EPG's recirc
1228 self, rd0, "0.0.0.0", 0,
1229 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1230 sw_if_index=recirc_nat.recirc.sw_if_index,
1233 self, rd0, "11.0.0.0", 8,
1234 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1235 sw_if_index=recirc_nat.recirc.sw_if_index,
1237 se16 = VppGbpSubnet(
1239 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1240 sw_if_index=recirc_nat.recirc.sw_if_index,
1242 # in the NAT RD an external subnet via the NAT EPG's uplink
1244 self, rd20, "0.0.0.0", 0,
1245 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1246 sw_if_index=epg_nat.uplink.sw_if_index,
1248 se36 = VppGbpSubnet(
1249 self, rd20, "::", 0,
1250 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1251 sw_if_index=epg_nat.uplink.sw_if_index,
1254 self, rd20, "11.0.0.0", 8,
1255 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1256 sw_if_index=epg_nat.uplink.sw_if_index,
1258 se1.add_vpp_config()
1259 se2.add_vpp_config()
1260 se16.add_vpp_config()
1261 se3.add_vpp_config()
1262 se36.add_vpp_config()
1263 se4.add_vpp_config()
1265 self.logger.info(self.vapi.cli("sh ip fib 0.0.0.0/0"))
1266 self.logger.info(self.vapi.cli("sh ip fib 11.0.0.1"))
1267 self.logger.info(self.vapi.cli("sh ip6 fib ::/0"))
1268 self.logger.info(self.vapi.cli("sh ip6 fib %s" %
1272 # From an EP to an outside addess: IN2OUT
1274 pkt_inter_epg_220_to_global = (Ether(src=self.pg0.remote_mac,
1275 dst=self.router_mac.address) /
1276 IP(src=eps[0].ip4.address,
1278 UDP(sport=1234, dport=1234) /
1282 self.send_and_assert_no_replies(eps[0].itf,
1283 pkt_inter_epg_220_to_global * 65)
1285 acl2 = VppGbpAcl(self)
1286 rule = acl2.create_rule(permit_deny=1, proto=17, sport_from=1234,
1287 sport_to=1234, dport_from=1234, dport_to=1234)
1288 rule2 = acl2.create_rule(is_ipv6=1, permit_deny=1, proto=17,
1289 sport_from=1234, sport_to=1234,
1290 dport_from=1234, dport_to=1234)
1292 acl_index2 = acl2.add_vpp_config([rule, rule2])
1293 c4 = VppGbpContract(
1294 self, 220, 333, acl_index2,
1295 [VppGbpContractRule(
1296 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1299 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1304 self.send_and_expect_natted(eps[0].itf,
1305 pkt_inter_epg_220_to_global * 65,
1307 eps[0].fip4.address)
1309 pkt_inter_epg_220_to_global = (Ether(src=self.pg0.remote_mac,
1310 dst=self.router_mac.address) /
1311 IPv6(src=eps[0].ip6.address,
1313 UDP(sport=1234, dport=1234) /
1316 self.send_and_expect_natted6(self.pg0,
1317 pkt_inter_epg_220_to_global * 65,
1319 eps[0].fip6.address)
1322 # From a global address to an EP: OUT2IN
1324 pkt_inter_epg_220_from_global = (Ether(src=self.router_mac.address,
1325 dst=self.pg0.remote_mac) /
1326 IP(dst=eps[0].fip4.address,
1328 UDP(sport=1234, dport=1234) /
1331 self.send_and_assert_no_replies(self.pg7,
1332 pkt_inter_epg_220_from_global * 65)
1334 c5 = VppGbpContract(
1335 self, 333, 220, acl_index2,
1336 [VppGbpContractRule(
1337 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1340 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1345 self.send_and_expect_unnatted(self.pg7,
1346 pkt_inter_epg_220_from_global * 65,
1350 pkt_inter_epg_220_from_global = (Ether(src=self.router_mac.address,
1351 dst=self.pg0.remote_mac) /
1352 IPv6(dst=eps[0].fip6.address,
1354 UDP(sport=1234, dport=1234) /
1357 self.send_and_expect_unnatted6(self.pg7,
1358 pkt_inter_epg_220_from_global * 65,
1363 # From a local VM to another local VM using resp. public addresses:
1366 pkt_intra_epg_220_global = (Ether(src=self.pg0.remote_mac,
1367 dst=self.router_mac.address) /
1368 IP(src=eps[0].ip4.address,
1369 dst=eps[1].fip4.address) /
1370 UDP(sport=1234, dport=1234) /
1373 self.send_and_expect_double_natted(eps[0].itf,
1374 pkt_intra_epg_220_global * 65,
1376 eps[0].fip4.address,
1379 pkt_intra_epg_220_global = (Ether(src=self.pg0.remote_mac,
1380 dst=self.router_mac.address) /
1381 IPv6(src=eps[0].ip6.address,
1382 dst=eps[1].fip6.address) /
1383 UDP(sport=1234, dport=1234) /
1386 self.send_and_expect_double_natted6(eps[0].itf,
1387 pkt_intra_epg_220_global * 65,
1389 eps[0].fip6.address,
1396 # del static mappings for each EP from the 10/8 to 11/8 network
1397 self.vapi.nat44_add_del_static_mapping(ep.ip4.bytes,
1402 self.vapi.nat66_add_del_static_mapping(ep.ip6.bytes,
1408 # IP config on the BVI interfaces
1409 if epg != epgs[0] and epg != epgs[3]:
1410 self.vapi.nat44_interface_add_del_feature(epg.bvi.sw_if_index,
1413 self.vapi.nat66_add_del_interface(epg.bvi.sw_if_index,
1417 for recirc in recircs:
1418 self.vapi.nat44_interface_add_del_feature(
1419 recirc.recirc.sw_if_index,
1422 self.vapi.nat66_add_del_interface(
1423 recirc.recirc.sw_if_index,
1427 def wait_for_ep_timeout(self, sw_if_index=None, ip=None, mac=None,
1428 n_tries=100, s_time=1):
1430 if not find_gbp_endpoint(self, sw_if_index, ip, mac):
1432 n_tries = n_tries - 1
1434 self.assertFalse(find_gbp_endpoint(self, sw_if_index, ip, mac))
1437 def test_gbp_learn_l2(self):
1438 """ GBP L2 Endpoint Learning """
1440 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
1441 learnt = [{'mac': '00:00:11:11:11:01',
1443 'ip6': '2001:10::2'},
1444 {'mac': '00:00:11:11:11:02',
1446 'ip6': '2001:10::3'}]
1449 # lower the inactive threshold so these tests pass in a
1450 # reasonable amount of time
1452 self.vapi.gbp_endpoint_learn_set_inactive_threshold(1)
1457 gt4 = VppIpTable(self, 1)
1458 gt4.add_vpp_config()
1459 gt6 = VppIpTable(self, 1, is_ip6=True)
1460 gt6.add_vpp_config()
1462 rd1 = VppGbpRouteDomain(self, 1, gt4, gt6)
1463 rd1.add_vpp_config()
1466 # Pg2 hosts the vxlan tunnel, hosts on pg2 to act as TEPs
1467 # Pg3 hosts the IP4 UU-flood VXLAN tunnel
1468 # Pg4 hosts the IP6 UU-flood VXLAN tunnel
1470 self.pg2.config_ip4()
1471 self.pg2.resolve_arp()
1472 self.pg2.generate_remote_hosts(4)
1473 self.pg2.configure_ipv4_neighbors()
1474 self.pg3.config_ip4()
1475 self.pg3.resolve_arp()
1476 self.pg4.config_ip4()
1477 self.pg4.resolve_arp()
1480 # a GBP bridge domain with a BVI and a UU-flood interface
1482 bd1 = VppBridgeDomain(self, 1)
1483 bd1.add_vpp_config()
1484 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0, self.pg3)
1485 gbd1.add_vpp_config()
1487 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1488 self.logger.info(self.vapi.cli("sh gbp bridge"))
1490 # ... and has a /32 applied
1491 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
1492 ip_addr.add_vpp_config()
1495 # The Endpoint-group in which we are learning endpoints
1497 epg_220 = VppGbpEndpointGroup(self, 220, rd1, gbd1,
1501 epg_220.add_vpp_config()
1502 epg_330 = VppGbpEndpointGroup(self, 330, rd1, gbd1,
1506 epg_330.add_vpp_config()
1509 # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
1512 vx_tun_l2_1 = VppGbpVxlanTunnel(
1513 self, 99, bd1.bd_id,
1514 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L2)
1515 vx_tun_l2_1.add_vpp_config()
1518 # A static endpoint that the learnt endpoints are trying to
1521 ep = VppGbpEndpoint(self, self.pg0,
1523 "10.0.0.127", "11.0.0.127",
1524 "2001:10::1", "3001::1")
1527 self.assertTrue(find_route(self, ep.ip4.address, 32, table_id=1))
1529 # a packet with an sclass from an unknwon EPG
1530 p = (Ether(src=self.pg2.remote_mac,
1531 dst=self.pg2.local_mac) /
1532 IP(src=self.pg2.remote_hosts[0].ip4,
1533 dst=self.pg2.local_ip4) /
1534 UDP(sport=1234, dport=48879) /
1535 VXLAN(vni=99, gpid=88, flags=0x88) /
1536 Ether(src=learnt[0]["mac"], dst=ep.mac) /
1537 IP(src=learnt[0]["ip"], dst=ep.ip4.address) /
1538 UDP(sport=1234, dport=1234) /
1541 self.send_and_assert_no_replies(self.pg2, p)
1544 # we should not have learnt a new tunnel endpoint, since
1545 # the EPG was not learnt.
1547 self.assertEqual(INDEX_INVALID,
1548 find_vxlan_gbp_tunnel(self,
1550 self.pg2.remote_hosts[0].ip4,
1553 # epg is not learnt, becasue the EPG is unknwon
1554 self.assertEqual(len(self.vapi.gbp_endpoint_dump()), 1)
1556 for ii, l in enumerate(learnt):
1557 # a packet with an sclass from a knwon EPG
1558 # arriving on an unknown TEP
1559 p = (Ether(src=self.pg2.remote_mac,
1560 dst=self.pg2.local_mac) /
1561 IP(src=self.pg2.remote_hosts[1].ip4,
1562 dst=self.pg2.local_ip4) /
1563 UDP(sport=1234, dport=48879) /
1564 VXLAN(vni=99, gpid=220, flags=0x88) /
1565 Ether(src=l['mac'], dst=ep.mac) /
1566 IP(src=l['ip'], dst=ep.ip4.address) /
1567 UDP(sport=1234, dport=1234) /
1570 rx = self.send_and_expect(self.pg2, [p], self.pg0)
1573 tep1_sw_if_index = find_vxlan_gbp_tunnel(
1576 self.pg2.remote_hosts[1].ip4,
1578 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
1581 # the EP is learnt via the learnt TEP
1582 # both from its MAC and its IP
1584 self.assertTrue(find_gbp_endpoint(self,
1585 vx_tun_l2_1.sw_if_index,
1587 self.assertTrue(find_gbp_endpoint(self,
1588 vx_tun_l2_1.sw_if_index,
1591 self.logger.info(self.vapi.cli("show gbp endpoint"))
1592 self.logger.info(self.vapi.cli("show gbp vxlan"))
1593 self.logger.info(self.vapi.cli("show vxlan-gbp tunnel"))
1596 # If we sleep for the threshold time, the learnt endpoints should
1600 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1604 # repeat. the do not learn bit is set so the EPs are not learnt
1607 # a packet with an sclass from a knwon EPG
1608 p = (Ether(src=self.pg2.remote_mac,
1609 dst=self.pg2.local_mac) /
1610 IP(src=self.pg2.remote_hosts[1].ip4,
1611 dst=self.pg2.local_ip4) /
1612 UDP(sport=1234, dport=48879) /
1613 VXLAN(vni=99, gpid=220, flags=0x88, gpflags="D") /
1614 Ether(src=l['mac'], dst=ep.mac) /
1615 IP(src=l['ip'], dst=ep.ip4.address) /
1616 UDP(sport=1234, dport=1234) /
1619 rx = self.send_and_expect(self.pg2, p*65, self.pg0)
1622 self.assertFalse(find_gbp_endpoint(self,
1623 vx_tun_l2_1.sw_if_index,
1630 # a packet with an sclass from a knwon EPG
1631 p = (Ether(src=self.pg2.remote_mac,
1632 dst=self.pg2.local_mac) /
1633 IP(src=self.pg2.remote_hosts[1].ip4,
1634 dst=self.pg2.local_ip4) /
1635 UDP(sport=1234, dport=48879) /
1636 VXLAN(vni=99, gpid=220, flags=0x88) /
1637 Ether(src=l['mac'], dst=ep.mac) /
1638 IP(src=l['ip'], dst=ep.ip4.address) /
1639 UDP(sport=1234, dport=1234) /
1642 rx = self.send_and_expect(self.pg2, p*65, self.pg0)
1644 self.assertTrue(find_gbp_endpoint(self,
1645 vx_tun_l2_1.sw_if_index,
1649 # Static EP replies to dynamics
1651 self.logger.info(self.vapi.cli("sh l2fib bd_id 1"))
1653 p = (Ether(src=ep.mac, dst=l['mac']) /
1654 IP(dst=l['ip'], src=ep.ip4.address) /
1655 UDP(sport=1234, dport=1234) /
1658 rxs = self.send_and_expect(self.pg0, p * 17, self.pg2)
1661 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
1662 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
1663 self.assertEqual(rx[UDP].dport, 48879)
1664 # the UDP source port is a random value for hashing
1665 self.assertEqual(rx[VXLAN].gpid, 220)
1666 self.assertEqual(rx[VXLAN].vni, 99)
1667 self.assertTrue(rx[VXLAN].flags.G)
1668 self.assertTrue(rx[VXLAN].flags.Instance)
1669 self.assertTrue(rx[VXLAN].gpflags.A)
1670 self.assertFalse(rx[VXLAN].gpflags.D)
1673 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1677 # repeat in the other EPG
1678 # there's no contract between 220 and 330, but the A-bit is set
1679 # so the packet is cleared for delivery
1682 # a packet with an sclass from a knwon EPG
1683 p = (Ether(src=self.pg2.remote_mac,
1684 dst=self.pg2.local_mac) /
1685 IP(src=self.pg2.remote_hosts[1].ip4,
1686 dst=self.pg2.local_ip4) /
1687 UDP(sport=1234, dport=48879) /
1688 VXLAN(vni=99, gpid=330, flags=0x88, gpflags='A') /
1689 Ether(src=l['mac'], dst=ep.mac) /
1690 IP(src=l['ip'], dst=ep.ip4.address) /
1691 UDP(sport=1234, dport=1234) /
1694 rx = self.send_and_expect(self.pg2, p*65, self.pg0)
1696 self.assertTrue(find_gbp_endpoint(self,
1697 vx_tun_l2_1.sw_if_index,
1701 # static EP cannot reach the learnt EPs since there is no contract
1702 # only test 1 EP as the others could timeout
1704 p = (Ether(src=ep.mac, dst=l['mac']) /
1705 IP(dst=learnt[0]['ip'], src=ep.ip4.address) /
1706 UDP(sport=1234, dport=1234) /
1709 self.send_and_assert_no_replies(self.pg0, [p])
1712 # refresh the entries after the check for no replies above
1715 # a packet with an sclass from a knwon EPG
1716 p = (Ether(src=self.pg2.remote_mac,
1717 dst=self.pg2.local_mac) /
1718 IP(src=self.pg2.remote_hosts[1].ip4,
1719 dst=self.pg2.local_ip4) /
1720 UDP(sport=1234, dport=48879) /
1721 VXLAN(vni=99, gpid=330, flags=0x88, gpflags='A') /
1722 Ether(src=l['mac'], dst=ep.mac) /
1723 IP(src=l['ip'], dst=ep.ip4.address) /
1724 UDP(sport=1234, dport=1234) /
1727 rx = self.send_and_expect(self.pg2, p*65, self.pg0)
1729 self.assertTrue(find_gbp_endpoint(self,
1730 vx_tun_l2_1.sw_if_index,
1734 # Add the contract so they can talk
1736 acl = VppGbpAcl(self)
1737 rule = acl.create_rule(permit_deny=1, proto=17)
1738 rule2 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
1739 acl_index = acl.add_vpp_config([rule, rule2])
1740 c1 = VppGbpContract(
1741 self, 220, 330, acl_index,
1742 [VppGbpContractRule(
1743 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1746 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1752 p = (Ether(src=ep.mac, dst=l['mac']) /
1753 IP(dst=l['ip'], src=ep.ip4.address) /
1754 UDP(sport=1234, dport=1234) /
1757 self.send_and_expect(self.pg0, [p], self.pg2)
1760 # send UU packets from the local EP
1762 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1763 self.logger.info(self.vapi.cli("sh gbp bridge"))
1764 p_uu = (Ether(src=ep.mac, dst="00:11:11:11:11:11") /
1765 IP(dst="10.0.0.133", src=ep.ip4.address) /
1766 UDP(sport=1234, dport=1234) /
1768 rxs = self.send_and_expect(ep.itf, [p_uu], gbd1.uu_flood)
1771 # Add a mcast destination VXLAN-GBP tunnel for B&M traffic
1773 tun_bm = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
1776 tun_bm.add_vpp_config()
1777 bp_bm = VppBridgeDomainPort(self, bd1, tun_bm,
1778 port_type=L2_PORT_TYPE.NORMAL)
1779 bp_bm.add_vpp_config()
1781 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1783 p_bm = (Ether(src=ep.mac, dst="ff:ff:ff:ff:ff:ff") /
1784 IP(dst="10.0.0.133", src=ep.ip4.address) /
1785 UDP(sport=1234, dport=1234) /
1787 rxs = self.send_and_expect_only(ep.itf, [p_bm], tun_bm.mcast_itf)
1790 # Check v6 Endpoints
1793 # a packet with an sclass from a knwon EPG
1794 p = (Ether(src=self.pg2.remote_mac,
1795 dst=self.pg2.local_mac) /
1796 IP(src=self.pg2.remote_hosts[1].ip4,
1797 dst=self.pg2.local_ip4) /
1798 UDP(sport=1234, dport=48879) /
1799 VXLAN(vni=99, gpid=330, flags=0x88, gpflags='A') /
1800 Ether(src=l['mac'], dst=ep.mac) /
1801 IPv6(src=l['ip6'], dst=ep.ip6.address) /
1802 UDP(sport=1234, dport=1234) /
1805 rx = self.send_and_expect(self.pg2, p*65, self.pg0)
1807 self.assertTrue(find_gbp_endpoint(self,
1808 vx_tun_l2_1.sw_if_index,
1812 # L3 Endpoint Learning
1813 # - configured on the bridge's BVI
1820 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1823 self.pg2.unconfig_ip4()
1824 self.pg3.unconfig_ip4()
1825 self.pg4.unconfig_ip4()
1827 self.logger.info(self.vapi.cli("sh int"))
1828 self.logger.info(self.vapi.cli("sh gbp vxlan"))
1830 @unittest.skipIf(is_skip_aarch64_set() and is_platform_aarch64(),
1831 "test doesn't work on aarch64")
1832 def test_gbp_learn_vlan_l2(self):
1833 """ GBP L2 Endpoint w/ VLANs"""
1835 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
1836 learnt = [{'mac': '00:00:11:11:11:01',
1838 'ip6': '2001:10::2'},
1839 {'mac': '00:00:11:11:11:02',
1841 'ip6': '2001:10::3'}]
1844 # lower the inactive threshold so these tests pass in a
1845 # reasonable amount of time
1847 self.vapi.gbp_endpoint_learn_set_inactive_threshold(1)
1852 gt4 = VppIpTable(self, 1)
1853 gt4.add_vpp_config()
1854 gt6 = VppIpTable(self, 1, is_ip6=True)
1855 gt6.add_vpp_config()
1857 rd1 = VppGbpRouteDomain(self, 1, gt4, gt6)
1858 rd1.add_vpp_config()
1861 # Pg2 hosts the vxlan tunnel, hosts on pg2 to act as TEPs
1863 self.pg2.config_ip4()
1864 self.pg2.resolve_arp()
1865 self.pg2.generate_remote_hosts(4)
1866 self.pg2.configure_ipv4_neighbors()
1867 self.pg3.config_ip4()
1868 self.pg3.resolve_arp()
1871 # The EP will be on a vlan sub-interface
1873 vlan_11 = VppDot1QSubint(self, self.pg0, 11)
1875 self.vapi.sw_interface_set_l2_tag_rewrite(vlan_11.sw_if_index,
1879 bd_uu_fwd = VppVxlanGbpTunnel(self, self.pg3.local_ip4,
1880 self.pg3.remote_ip4, 116)
1881 bd_uu_fwd.add_vpp_config()
1884 # a GBP bridge domain with a BVI and a UU-flood interface
1885 # The BD is marked as do not learn, so no endpoints are ever
1886 # learnt in this BD.
1888 bd1 = VppBridgeDomain(self, 1)
1889 bd1.add_vpp_config()
1890 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0, bd_uu_fwd,
1892 gbd1.add_vpp_config()
1894 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1895 self.logger.info(self.vapi.cli("sh gbp bridge"))
1897 # ... and has a /32 applied
1898 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
1899 ip_addr.add_vpp_config()
1902 # The Endpoint-group in which we are learning endpoints
1904 epg_220 = VppGbpEndpointGroup(self, 220, rd1, gbd1,
1908 epg_220.add_vpp_config()
1911 # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
1914 vx_tun_l2_1 = VppGbpVxlanTunnel(
1915 self, 99, bd1.bd_id,
1916 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L2)
1917 vx_tun_l2_1.add_vpp_config()
1920 # A static endpoint that the learnt endpoints are trying to
1923 ep = VppGbpEndpoint(self, vlan_11,
1925 "10.0.0.127", "11.0.0.127",
1926 "2001:10::1", "3001::1")
1929 self.assertTrue(find_route(self, ep.ip4.address, 32, table_id=1))
1932 # Send to the static EP
1934 for ii, l in enumerate(learnt):
1935 # a packet with an sclass from a knwon EPG
1936 # arriving on an unknown TEP
1937 p = (Ether(src=self.pg2.remote_mac,
1938 dst=self.pg2.local_mac) /
1939 IP(src=self.pg2.remote_hosts[1].ip4,
1940 dst=self.pg2.local_ip4) /
1941 UDP(sport=1234, dport=48879) /
1942 VXLAN(vni=99, gpid=220, flags=0x88) /
1943 Ether(src=l['mac'], dst=ep.mac) /
1944 IP(src=l['ip'], dst=ep.ip4.address) /
1945 UDP(sport=1234, dport=1234) /
1948 rxs = self.send_and_expect(self.pg2, [p], self.pg0)
1951 # packet to EP has the EP's vlan tag
1954 self.assertEqual(rx[Dot1Q].vlan, 11)
1957 # the EP is not learnt since the BD setting prevents it
1960 self.assertFalse(find_gbp_endpoint(self,
1961 vx_tun_l2_1.sw_if_index,
1963 self.assertEqual(INDEX_INVALID,
1964 find_vxlan_gbp_tunnel(
1967 self.pg2.remote_hosts[1].ip4,
1970 self.assertEqual(len(self.vapi.gbp_endpoint_dump()), 1)
1974 # we didn't learn the remotes so they are sent to the UU-fwd
1977 p = (Ether(src=ep.mac, dst=l['mac']) /
1979 IP(dst=l['ip'], src=ep.ip4.address) /
1980 UDP(sport=1234, dport=1234) /
1983 rxs = self.send_and_expect(self.pg0, p * 17, self.pg3)
1986 self.assertEqual(rx[IP].src, self.pg3.local_ip4)
1987 self.assertEqual(rx[IP].dst, self.pg3.remote_ip4)
1988 self.assertEqual(rx[UDP].dport, 48879)
1989 # the UDP source port is a random value for hashing
1990 self.assertEqual(rx[VXLAN].gpid, 220)
1991 self.assertEqual(rx[VXLAN].vni, 116)
1992 self.assertTrue(rx[VXLAN].flags.G)
1993 self.assertTrue(rx[VXLAN].flags.Instance)
1994 self.assertFalse(rx[VXLAN].gpflags.A)
1995 self.assertFalse(rx[VXLAN].gpflags.D)
1997 self.pg2.unconfig_ip4()
1998 self.pg3.unconfig_ip4()
2000 @unittest.skipIf(is_skip_aarch64_set() and is_platform_aarch64(),
2001 "test doesn't work on aarch64")
2002 def test_gbp_learn_l3(self):
2003 """ GBP L3 Endpoint Learning """
2005 self.vapi.cli("set logging class gbp debug")
2007 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
2008 routed_dst_mac = "00:0c:0c:0c:0c:0c"
2009 routed_src_mac = "00:22:bd:f8:19:ff"
2011 learnt = [{'mac': '00:00:11:11:11:02',
2013 'ip6': '2001:10::2'},
2014 {'mac': '00:00:11:11:11:03',
2016 'ip6': '2001:10::3'}]
2019 # lower the inactive threshold so these tests pass in a
2020 # reasonable amount of time
2022 self.vapi.gbp_endpoint_learn_set_inactive_threshold(1)
2027 t4 = VppIpTable(self, 1)
2029 t6 = VppIpTable(self, 1, True)
2032 tun_ip4_uu = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
2033 self.pg4.remote_ip4, 114)
2034 tun_ip6_uu = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
2035 self.pg4.remote_ip4, 116)
2036 tun_ip4_uu.add_vpp_config()
2037 tun_ip6_uu.add_vpp_config()
2039 rd1 = VppGbpRouteDomain(self, 2, t4, t6, tun_ip4_uu, tun_ip6_uu)
2040 rd1.add_vpp_config()
2042 self.loop0.set_mac(self.router_mac.address)
2045 # Bind the BVI to the RD
2047 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
2048 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
2051 # Pg2 hosts the vxlan tunnel
2052 # hosts on pg2 to act as TEPs
2056 self.pg2.config_ip4()
2057 self.pg2.resolve_arp()
2058 self.pg2.generate_remote_hosts(4)
2059 self.pg2.configure_ipv4_neighbors()
2060 self.pg3.config_ip4()
2061 self.pg3.resolve_arp()
2062 self.pg4.config_ip4()
2063 self.pg4.resolve_arp()
2066 # a GBP bridge domain with a BVI and a UU-flood interface
2068 bd1 = VppBridgeDomain(self, 1)
2069 bd1.add_vpp_config()
2070 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0, self.pg3)
2071 gbd1.add_vpp_config()
2073 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2074 self.logger.info(self.vapi.cli("sh gbp bridge"))
2075 self.logger.info(self.vapi.cli("sh gbp route"))
2077 # ... and has a /32 and /128 applied
2078 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2079 ip4_addr.add_vpp_config()
2080 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 128)
2081 ip6_addr.add_vpp_config()
2084 # The Endpoint-group in which we are learning endpoints
2086 epg_220 = VppGbpEndpointGroup(self, 220, rd1, gbd1,
2090 epg_220.add_vpp_config()
2093 # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
2096 vx_tun_l3 = VppGbpVxlanTunnel(
2097 self, 101, rd1.rd_id,
2098 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3)
2099 vx_tun_l3.add_vpp_config()
2102 # A static endpoint that the learnt endpoints are trying to
2105 ep = VppGbpEndpoint(self, self.pg0,
2107 "10.0.0.127", "11.0.0.127",
2108 "2001:10::1", "3001::1")
2112 # learn some remote IPv4 EPs
2114 for ii, l in enumerate(learnt):
2115 # a packet with an sclass from a knwon EPG
2116 # arriving on an unknown TEP
2117 p = (Ether(src=self.pg2.remote_mac,
2118 dst=self.pg2.local_mac) /
2119 IP(src=self.pg2.remote_hosts[1].ip4,
2120 dst=self.pg2.local_ip4) /
2121 UDP(sport=1234, dport=48879) /
2122 VXLAN(vni=101, gpid=220, flags=0x88) /
2123 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2124 IP(src=l['ip'], dst=ep.ip4.address) /
2125 UDP(sport=1234, dport=1234) /
2128 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2131 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2134 self.pg2.remote_hosts[1].ip4,
2136 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2138 # endpoint learnt via the parent GBP-vxlan interface
2139 self.assertTrue(find_gbp_endpoint(self,
2140 vx_tun_l3._sw_if_index,
2144 # Static IPv4 EP replies to learnt
2147 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2148 IP(dst=l['ip'], src=ep.ip4.address) /
2149 UDP(sport=1234, dport=1234) /
2152 rxs = self.send_and_expect(self.pg0, p*1, self.pg2)
2155 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2156 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2157 self.assertEqual(rx[UDP].dport, 48879)
2158 # the UDP source port is a random value for hashing
2159 self.assertEqual(rx[VXLAN].gpid, 220)
2160 self.assertEqual(rx[VXLAN].vni, 101)
2161 self.assertTrue(rx[VXLAN].flags.G)
2162 self.assertTrue(rx[VXLAN].flags.Instance)
2163 self.assertTrue(rx[VXLAN].gpflags.A)
2164 self.assertFalse(rx[VXLAN].gpflags.D)
2166 inner = rx[VXLAN].payload
2168 self.assertEqual(inner[Ether].src, routed_src_mac)
2169 self.assertEqual(inner[Ether].dst, routed_dst_mac)
2170 self.assertEqual(inner[IP].src, ep.ip4.address)
2171 self.assertEqual(inner[IP].dst, l['ip'])
2174 self.assertFalse(find_gbp_endpoint(self,
2179 # learn some remote IPv6 EPs
2181 for ii, l in enumerate(learnt):
2182 # a packet with an sclass from a knwon EPG
2183 # arriving on an unknown TEP
2184 p = (Ether(src=self.pg2.remote_mac,
2185 dst=self.pg2.local_mac) /
2186 IP(src=self.pg2.remote_hosts[1].ip4,
2187 dst=self.pg2.local_ip4) /
2188 UDP(sport=1234, dport=48879) /
2189 VXLAN(vni=101, gpid=220, flags=0x88) /
2190 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2191 IPv6(src=l['ip6'], dst=ep.ip6.address) /
2192 UDP(sport=1234, dport=1234) /
2195 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2198 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2201 self.pg2.remote_hosts[1].ip4,
2203 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2205 self.logger.info(self.vapi.cli("show gbp bridge"))
2206 self.logger.info(self.vapi.cli("show vxlan-gbp tunnel"))
2207 self.logger.info(self.vapi.cli("show gbp vxlan"))
2208 self.logger.info(self.vapi.cli("show int addr"))
2210 # endpoint learnt via the TEP
2211 self.assertTrue(find_gbp_endpoint(self, ip=l['ip6']))
2213 self.logger.info(self.vapi.cli("show gbp endpoint"))
2214 self.logger.info(self.vapi.cli("show ip fib index 1 %s" % l['ip']))
2217 # Static EP replies to learnt
2220 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2221 IPv6(dst=l['ip6'], src=ep.ip6.address) /
2222 UDP(sport=1234, dport=1234) /
2225 rxs = self.send_and_expect(self.pg0, p*65, self.pg2)
2228 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2229 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2230 self.assertEqual(rx[UDP].dport, 48879)
2231 # the UDP source port is a random value for hashing
2232 self.assertEqual(rx[VXLAN].gpid, 220)
2233 self.assertEqual(rx[VXLAN].vni, 101)
2234 self.assertTrue(rx[VXLAN].flags.G)
2235 self.assertTrue(rx[VXLAN].flags.Instance)
2236 self.assertTrue(rx[VXLAN].gpflags.A)
2237 self.assertFalse(rx[VXLAN].gpflags.D)
2239 inner = rx[VXLAN].payload
2241 self.assertEqual(inner[Ether].src, routed_src_mac)
2242 self.assertEqual(inner[Ether].dst, routed_dst_mac)
2243 self.assertEqual(inner[IPv6].src, ep.ip6.address)
2244 self.assertEqual(inner[IPv6].dst, l['ip6'])
2246 self.logger.info(self.vapi.cli("sh gbp endpoint"))
2248 self.wait_for_ep_timeout(ip=l['ip'])
2251 # Static sends to unknown EP with no route
2253 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2254 IP(dst="10.0.0.99", src=ep.ip4.address) /
2255 UDP(sport=1234, dport=1234) /
2258 self.send_and_assert_no_replies(self.pg0, [p])
2261 # Add a route to static EP's v4 and v6 subnet
2262 # packets should be sent on the v4/v6 uu=fwd interface resp.
2264 se_10_24 = VppGbpSubnet(
2265 self, rd1, "10.0.0.0", 24,
2266 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT)
2267 se_10_24.add_vpp_config()
2269 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2270 IP(dst="10.0.0.99", src=ep.ip4.address) /
2271 UDP(sport=1234, dport=1234) /
2274 rxs = self.send_and_expect(self.pg0, [p], self.pg4)
2276 self.assertEqual(rx[IP].src, self.pg4.local_ip4)
2277 self.assertEqual(rx[IP].dst, self.pg4.remote_ip4)
2278 self.assertEqual(rx[UDP].dport, 48879)
2279 # the UDP source port is a random value for hashing
2280 self.assertEqual(rx[VXLAN].gpid, 220)
2281 self.assertEqual(rx[VXLAN].vni, 114)
2282 self.assertTrue(rx[VXLAN].flags.G)
2283 self.assertTrue(rx[VXLAN].flags.Instance)
2284 # policy is not applied to packets sent to the uu-fwd interfaces
2285 self.assertFalse(rx[VXLAN].gpflags.A)
2286 self.assertFalse(rx[VXLAN].gpflags.D)
2289 # learn some remote IPv4 EPs
2291 for ii, l in enumerate(learnt):
2292 # a packet with an sclass from a knwon EPG
2293 # arriving on an unknown TEP
2294 p = (Ether(src=self.pg2.remote_mac,
2295 dst=self.pg2.local_mac) /
2296 IP(src=self.pg2.remote_hosts[1].ip4,
2297 dst=self.pg2.local_ip4) /
2298 UDP(sport=1234, dport=48879) /
2299 VXLAN(vni=101, gpid=220, flags=0x88) /
2300 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2301 IP(src=l['ip'], dst=ep.ip4.address) /
2302 UDP(sport=1234, dport=1234) /
2305 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2308 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2311 self.pg2.remote_hosts[1].ip4,
2313 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2315 # endpoint learnt via the parent GBP-vxlan interface
2316 self.assertTrue(find_gbp_endpoint(self,
2317 vx_tun_l3._sw_if_index,
2321 # Add a remote endpoint from the API
2323 rep_88 = VppGbpEndpoint(self, vx_tun_l3,
2325 "10.0.0.88", "11.0.0.88",
2326 "2001:10::88", "3001::88",
2327 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
2329 self.pg2.remote_hosts[1].ip4,
2331 rep_88.add_vpp_config()
2334 # Add a remote endpoint from the API that matches an existing one
2336 rep_2 = VppGbpEndpoint(self, vx_tun_l3,
2338 learnt[0]['ip'], "11.0.0.101",
2339 learnt[0]['ip6'], "3001::101",
2340 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
2342 self.pg2.remote_hosts[1].ip4,
2344 rep_2.add_vpp_config()
2347 # Add a route to the leanred EP's v4 subnet
2348 # packets should be send on the v4/v6 uu=fwd interface resp.
2350 se_10_1_24 = VppGbpSubnet(
2351 self, rd1, "10.0.1.0", 24,
2352 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT)
2353 se_10_1_24.add_vpp_config()
2355 self.logger.info(self.vapi.cli("show gbp endpoint"))
2357 ips = ["10.0.0.88", learnt[0]['ip']]
2359 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2360 IP(dst=ip, src=ep.ip4.address) /
2361 UDP(sport=1234, dport=1234) /
2364 rxs = self.send_and_expect(self.pg0, p*65, self.pg2)
2367 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2368 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2369 self.assertEqual(rx[UDP].dport, 48879)
2370 # the UDP source port is a random value for hashing
2371 self.assertEqual(rx[VXLAN].gpid, 220)
2372 self.assertEqual(rx[VXLAN].vni, 101)
2373 self.assertTrue(rx[VXLAN].flags.G)
2374 self.assertTrue(rx[VXLAN].flags.Instance)
2375 self.assertTrue(rx[VXLAN].gpflags.A)
2376 self.assertFalse(rx[VXLAN].gpflags.D)
2378 inner = rx[VXLAN].payload
2380 self.assertEqual(inner[Ether].src, routed_src_mac)
2381 self.assertEqual(inner[Ether].dst, routed_dst_mac)
2382 self.assertEqual(inner[IP].src, ep.ip4.address)
2383 self.assertEqual(inner[IP].dst, ip)
2386 # remove the API remote EPs, only API sourced is gone, the DP
2387 # learnt one remains
2389 rep_88.remove_vpp_config()
2390 rep_2.remove_vpp_config()
2392 self.logger.info(self.vapi.cli("show gbp endpoint"))
2394 self.assertFalse(find_gbp_endpoint(self, ip=rep_88.ip4.address))
2396 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2397 IP(src=ep.ip4.address, dst=rep_88.ip4.address) /
2398 UDP(sport=1234, dport=1234) /
2400 rxs = self.send_and_expect(self.pg0, [p], self.pg4)
2402 self.assertTrue(find_gbp_endpoint(self, ip=rep_2.ip4.address))
2404 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2405 IP(src=ep.ip4.address, dst=rep_2.ip4.address) /
2406 UDP(sport=1234, dport=1234) /
2408 rxs = self.send_and_expect(self.pg0, [p], self.pg2)
2411 # to appease the testcase we cannot have the registered EP stll
2412 # present (because it's DP learnt) when the TC ends so wait until
2418 # shutdown with learnt endpoint present
2420 p = (Ether(src=self.pg2.remote_mac,
2421 dst=self.pg2.local_mac) /
2422 IP(src=self.pg2.remote_hosts[1].ip4,
2423 dst=self.pg2.local_ip4) /
2424 UDP(sport=1234, dport=48879) /
2425 VXLAN(vni=101, gpid=220, flags=0x88) /
2426 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2427 IP(src=learnt[1]['ip'], dst=ep.ip4.address) /
2428 UDP(sport=1234, dport=1234) /
2431 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2433 # endpoint learnt via the parent GBP-vxlan interface
2434 self.assertTrue(find_gbp_endpoint(self,
2435 vx_tun_l3._sw_if_index,
2440 # remote endpoint becomes local
2442 self.pg2.unconfig_ip4()
2443 self.pg3.unconfig_ip4()
2444 self.pg4.unconfig_ip4()
2446 def test_gbp_redirect(self):
2447 """ GBP Endpoint Redirect """
2449 self.vapi.cli("set logging class gbp debug")
2451 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
2452 routed_dst_mac = "00:0c:0c:0c:0c:0c"
2453 routed_src_mac = "00:22:bd:f8:19:ff"
2455 learnt = [{'mac': '00:00:11:11:11:02',
2457 'ip6': '2001:10::2'},
2458 {'mac': '00:00:11:11:11:03',
2460 'ip6': '2001:10::3'}]
2463 # lower the inactive threshold so these tests pass in a
2464 # reasonable amount of time
2466 self.vapi.gbp_endpoint_learn_set_inactive_threshold(1)
2471 t4 = VppIpTable(self, 1)
2473 t6 = VppIpTable(self, 1, True)
2476 rd1 = VppGbpRouteDomain(self, 2, t4, t6)
2477 rd1.add_vpp_config()
2479 self.loop0.set_mac(self.router_mac.address)
2482 # Bind the BVI to the RD
2484 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
2485 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
2488 # Pg7 hosts a BD's UU-fwd
2490 self.pg7.config_ip4()
2491 self.pg7.resolve_arp()
2494 # a GBP bridge domains for the EPs
2496 bd1 = VppBridgeDomain(self, 1)
2497 bd1.add_vpp_config()
2498 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0)
2499 gbd1.add_vpp_config()
2501 bd2 = VppBridgeDomain(self, 2)
2502 bd2.add_vpp_config()
2503 gbd2 = VppGbpBridgeDomain(self, bd2, self.loop1)
2504 gbd2.add_vpp_config()
2506 # ... and has a /32 and /128 applied
2507 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2508 ip4_addr.add_vpp_config()
2509 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 128)
2510 ip6_addr.add_vpp_config()
2511 ip4_addr = VppIpInterfaceAddress(self, gbd2.bvi, "10.0.1.128", 32)
2512 ip4_addr.add_vpp_config()
2513 ip6_addr = VppIpInterfaceAddress(self, gbd2.bvi, "2001:11::128", 128)
2514 ip6_addr.add_vpp_config()
2517 # The Endpoint-groups in which we are learning endpoints
2519 epg_220 = VppGbpEndpointGroup(self, 220, rd1, gbd1,
2523 epg_220.add_vpp_config()
2524 epg_221 = VppGbpEndpointGroup(self, 221, rd1, gbd2,
2528 epg_221.add_vpp_config()
2529 epg_222 = VppGbpEndpointGroup(self, 222, rd1, gbd1,
2533 epg_222.add_vpp_config()
2536 # a GBP bridge domains for the SEPs
2538 bd_uu1 = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
2539 self.pg7.remote_ip4, 116)
2540 bd_uu1.add_vpp_config()
2541 bd_uu2 = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
2542 self.pg7.remote_ip4, 117)
2543 bd_uu2.add_vpp_config()
2545 bd3 = VppBridgeDomain(self, 3)
2546 bd3.add_vpp_config()
2547 gbd3 = VppGbpBridgeDomain(self, bd3, self.loop2, bd_uu1, learn=False)
2548 gbd3.add_vpp_config()
2549 bd4 = VppBridgeDomain(self, 4)
2550 bd4.add_vpp_config()
2551 gbd4 = VppGbpBridgeDomain(self, bd4, self.loop3, bd_uu2, learn=False)
2552 gbd4.add_vpp_config()
2555 # EPGs in which the service endpoints exist
2557 epg_320 = VppGbpEndpointGroup(self, 320, rd1, gbd3,
2561 epg_320.add_vpp_config()
2562 epg_321 = VppGbpEndpointGroup(self, 321, rd1, gbd4,
2566 epg_321.add_vpp_config()
2569 # three local endpoints
2571 ep1 = VppGbpEndpoint(self, self.pg0,
2573 "10.0.0.1", "11.0.0.1",
2574 "2001:10::1", "3001:10::1")
2575 ep1.add_vpp_config()
2576 ep2 = VppGbpEndpoint(self, self.pg1,
2578 "10.0.1.1", "11.0.1.1",
2579 "2001:11::1", "3001:11::1")
2580 ep2.add_vpp_config()
2581 ep3 = VppGbpEndpoint(self, self.pg2,
2583 "10.0.2.2", "11.0.2.2",
2584 "2001:12::1", "3001:12::1")
2585 ep3.add_vpp_config()
2590 sep1 = VppGbpEndpoint(self, self.pg3,
2592 "12.0.0.1", "13.0.0.1",
2593 "4001:10::1", "5001:10::1")
2594 sep1.add_vpp_config()
2595 sep2 = VppGbpEndpoint(self, self.pg4,
2597 "12.0.0.2", "13.0.0.2",
2598 "4001:10::2", "5001:10::2")
2599 sep2.add_vpp_config()
2600 sep3 = VppGbpEndpoint(self, self.pg5,
2602 "12.0.1.1", "13.0.1.1",
2603 "4001:11::1", "5001:11::1")
2604 sep3.add_vpp_config()
2605 # this EP is not installed immediately
2606 sep4 = VppGbpEndpoint(self, self.pg6,
2608 "12.0.1.2", "13.0.1.2",
2609 "4001:11::2", "5001:11::2")
2612 # an L2 switch packet between local EPs in different EPGs
2613 # different dest ports on each so the are LB hashed differently
2615 p4 = [(Ether(src=ep1.mac, dst=ep3.mac) /
2616 IP(src=ep1.ip4.address, dst=ep3.ip4.address) /
2617 UDP(sport=1234, dport=1234) /
2619 (Ether(src=ep3.mac, dst=ep1.mac) /
2620 IP(src=ep3.ip4.address, dst=ep1.ip4.address) /
2621 UDP(sport=1234, dport=1234) /
2623 p6 = [(Ether(src=ep1.mac, dst=ep3.mac) /
2624 IPv6(src=ep1.ip6.address, dst=ep3.ip6.address) /
2625 UDP(sport=1234, dport=1234) /
2627 (Ether(src=ep3.mac, dst=ep1.mac) /
2628 IPv6(src=ep3.ip6.address, dst=ep1.ip6.address) /
2629 UDP(sport=1234, dport=1230) /
2632 # should be dropped since no contract yet
2633 self.send_and_assert_no_replies(self.pg0, [p4[0]])
2634 self.send_and_assert_no_replies(self.pg0, [p6[0]])
2637 # Add a contract with a rule to load-balance redirect via SEP1 and SEP2
2638 # one of the next-hops is via an EP that is not known
2640 acl = VppGbpAcl(self)
2641 rule4 = acl.create_rule(permit_deny=1, proto=17)
2642 rule6 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
2643 acl_index = acl.add_vpp_config([rule4, rule6])
2646 # test the src-ip hash mode
2648 c1 = VppGbpContract(
2649 self, 220, 222, acl_index,
2650 [VppGbpContractRule(
2651 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2652 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2653 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
2654 sep1.ip4, sep1.epg.rd),
2655 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
2656 sep2.ip4, sep2.epg.rd)]),
2658 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2659 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2660 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
2661 sep3.ip6, sep3.epg.rd),
2662 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
2663 sep4.ip6, sep4.epg.rd)])])
2666 c2 = VppGbpContract(
2667 self, 222, 220, acl_index,
2668 [VppGbpContractRule(
2669 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2670 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2671 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
2672 sep1.ip4, sep1.epg.rd),
2673 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
2674 sep2.ip4, sep2.epg.rd)]),
2676 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2677 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2678 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
2679 sep3.ip6, sep3.epg.rd),
2680 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
2681 sep4.ip6, sep4.epg.rd)])])
2685 # send again with the contract preset, now packets arrive
2686 # at SEP1 or SEP2 depending on the hashing
2688 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
2691 self.assertEqual(rx[Ether].src, routed_src_mac)
2692 self.assertEqual(rx[Ether].dst, sep1.mac)
2693 self.assertEqual(rx[IP].src, ep1.ip4.address)
2694 self.assertEqual(rx[IP].dst, ep3.ip4.address)
2696 rxs = self.send_and_expect(self.pg2, p4[1] * 17, sep2.itf)
2699 self.assertEqual(rx[Ether].src, routed_src_mac)
2700 self.assertEqual(rx[Ether].dst, sep2.mac)
2701 self.assertEqual(rx[IP].src, ep3.ip4.address)
2702 self.assertEqual(rx[IP].dst, ep1.ip4.address)
2704 rxs = self.send_and_expect(self.pg0, p6[0] * 17, self.pg7)
2707 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
2708 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
2709 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
2710 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
2711 self.assertEqual(rx[VXLAN].vni, 117)
2712 self.assertTrue(rx[VXLAN].flags.G)
2713 self.assertTrue(rx[VXLAN].flags.Instance)
2714 # redirect policy has been applied
2715 self.assertTrue(rx[VXLAN].gpflags.A)
2716 self.assertFalse(rx[VXLAN].gpflags.D)
2718 inner = rx[VXLAN].payload
2720 self.assertEqual(inner[Ether].src, routed_src_mac)
2721 self.assertEqual(inner[Ether].dst, sep4.mac)
2722 self.assertEqual(inner[IPv6].src, ep1.ip6.address)
2723 self.assertEqual(inner[IPv6].dst, ep3.ip6.address)
2725 rxs = self.send_and_expect(self.pg2, p6[1] * 17, sep3.itf)
2728 self.assertEqual(rx[Ether].src, routed_src_mac)
2729 self.assertEqual(rx[Ether].dst, sep3.mac)
2730 self.assertEqual(rx[IPv6].src, ep3.ip6.address)
2731 self.assertEqual(rx[IPv6].dst, ep1.ip6.address)
2734 # programme the unknown EP
2736 sep4.add_vpp_config()
2738 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep4.itf)
2741 self.assertEqual(rx[Ether].src, routed_src_mac)
2742 self.assertEqual(rx[Ether].dst, sep4.mac)
2743 self.assertEqual(rx[IPv6].src, ep1.ip6.address)
2744 self.assertEqual(rx[IPv6].dst, ep3.ip6.address)
2747 # and revert back to unprogrammed
2749 sep4.remove_vpp_config()
2751 rxs = self.send_and_expect(self.pg0, p6[0] * 17, self.pg7)
2754 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
2755 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
2756 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
2757 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
2758 self.assertEqual(rx[VXLAN].vni, 117)
2759 self.assertTrue(rx[VXLAN].flags.G)
2760 self.assertTrue(rx[VXLAN].flags.Instance)
2761 # redirect policy has been applied
2762 self.assertTrue(rx[VXLAN].gpflags.A)
2763 self.assertFalse(rx[VXLAN].gpflags.D)
2765 inner = rx[VXLAN].payload
2767 self.assertEqual(inner[Ether].src, routed_src_mac)
2768 self.assertEqual(inner[Ether].dst, sep4.mac)
2769 self.assertEqual(inner[IPv6].src, ep1.ip6.address)
2770 self.assertEqual(inner[IPv6].dst, ep3.ip6.address)
2772 c1.remove_vpp_config()
2773 c2.remove_vpp_config()
2776 # test the symmetric hash mode
2778 c1 = VppGbpContract(
2779 self, 220, 222, acl_index,
2780 [VppGbpContractRule(
2781 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2782 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
2783 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
2784 sep1.ip4, sep1.epg.rd),
2785 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
2786 sep2.ip4, sep2.epg.rd)]),
2788 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2789 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
2790 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
2791 sep3.ip6, sep3.epg.rd),
2792 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
2793 sep4.ip6, sep4.epg.rd)])])
2796 c2 = VppGbpContract(
2797 self, 222, 220, acl_index,
2798 [VppGbpContractRule(
2799 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2800 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
2801 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
2802 sep1.ip4, sep1.epg.rd),
2803 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
2804 sep2.ip4, sep2.epg.rd)]),
2806 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2807 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
2808 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
2809 sep3.ip6, sep3.epg.rd),
2810 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
2811 sep4.ip6, sep4.epg.rd)])])
2815 # send again with the contract preset, now packets arrive
2816 # at SEP1 for both directions
2818 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
2821 self.assertEqual(rx[Ether].src, routed_src_mac)
2822 self.assertEqual(rx[Ether].dst, sep1.mac)
2823 self.assertEqual(rx[IP].src, ep1.ip4.address)
2824 self.assertEqual(rx[IP].dst, ep3.ip4.address)
2826 rxs = self.send_and_expect(self.pg2, p4[1] * 17, sep1.itf)
2829 self.assertEqual(rx[Ether].src, routed_src_mac)
2830 self.assertEqual(rx[Ether].dst, sep1.mac)
2831 self.assertEqual(rx[IP].src, ep3.ip4.address)
2832 self.assertEqual(rx[IP].dst, ep1.ip4.address)
2835 # programme the unknown EP for the L3 tests
2837 sep4.add_vpp_config()
2840 # an L3 switch packet between local EPs in different EPGs
2841 # different dest ports on each so the are LB hashed differently
2843 p4 = [(Ether(src=ep1.mac, dst=self.router_mac.address) /
2844 IP(src=ep1.ip4.address, dst=ep2.ip4.address) /
2845 UDP(sport=1234, dport=1234) /
2847 (Ether(src=ep2.mac, dst=self.router_mac.address) /
2848 IP(src=ep2.ip4.address, dst=ep1.ip4.address) /
2849 UDP(sport=1234, dport=1234) /
2851 p6 = [(Ether(src=ep1.mac, dst=self.router_mac.address) /
2852 IPv6(src=ep1.ip6.address, dst=ep2.ip6.address) /
2853 UDP(sport=1234, dport=1234) /
2855 (Ether(src=ep2.mac, dst=self.router_mac.address) /
2856 IPv6(src=ep2.ip6.address, dst=ep1.ip6.address) /
2857 UDP(sport=1234, dport=1234) /
2860 c3 = VppGbpContract(
2861 self, 220, 221, acl_index,
2862 [VppGbpContractRule(
2863 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2864 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
2865 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
2866 sep1.ip4, sep1.epg.rd),
2867 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
2868 sep2.ip4, sep2.epg.rd)]),
2870 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2871 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
2872 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
2873 sep3.ip6, sep3.epg.rd),
2874 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
2875 sep4.ip6, sep4.epg.rd)])])
2878 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
2881 self.assertEqual(rx[Ether].src, routed_src_mac)
2882 self.assertEqual(rx[Ether].dst, sep1.mac)
2883 self.assertEqual(rx[IP].src, ep1.ip4.address)
2884 self.assertEqual(rx[IP].dst, ep2.ip4.address)
2887 # learn a remote EP in EPG 221
2889 vx_tun_l3 = VppGbpVxlanTunnel(
2890 self, 444, rd1.rd_id,
2891 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3)
2892 vx_tun_l3.add_vpp_config()
2894 c4 = VppGbpContract(
2895 self, 221, 220, acl_index,
2896 [VppGbpContractRule(
2897 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2900 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2904 p = (Ether(src=self.pg7.remote_mac,
2905 dst=self.pg7.local_mac) /
2906 IP(src=self.pg7.remote_ip4,
2907 dst=self.pg7.local_ip4) /
2908 UDP(sport=1234, dport=48879) /
2909 VXLAN(vni=444, gpid=221, flags=0x88) /
2910 Ether(src="00:22:22:22:22:33", dst=self.router_mac.address) /
2911 IP(src="10.0.0.88", dst=ep1.ip4.address) /
2912 UDP(sport=1234, dport=1234) /
2915 rx = self.send_and_expect(self.pg7, [p], self.pg0)
2917 # endpoint learnt via the parent GBP-vxlan interface
2918 self.assertTrue(find_gbp_endpoint(self,
2919 vx_tun_l3._sw_if_index,
2922 p = (Ether(src=self.pg7.remote_mac,
2923 dst=self.pg7.local_mac) /
2924 IP(src=self.pg7.remote_ip4,
2925 dst=self.pg7.local_ip4) /
2926 UDP(sport=1234, dport=48879) /
2927 VXLAN(vni=444, gpid=221, flags=0x88) /
2928 Ether(src="00:22:22:22:22:33", dst=self.router_mac.address) /
2929 IPv6(src="2001:10::88", dst=ep1.ip6.address) /
2930 UDP(sport=1234, dport=1234) /
2933 rx = self.send_and_expect(self.pg7, [p], self.pg0)
2935 # endpoint learnt via the parent GBP-vxlan interface
2936 self.assertTrue(find_gbp_endpoint(self,
2937 vx_tun_l3._sw_if_index,
2941 # L3 switch from local to remote EP
2943 p4 = [(Ether(src=ep1.mac, dst=self.router_mac.address) /
2944 IP(src=ep1.ip4.address, dst="10.0.0.88") /
2945 UDP(sport=1234, dport=1234) /
2947 p6 = [(Ether(src=ep1.mac, dst=self.router_mac.address) /
2948 IPv6(src=ep1.ip6.address, dst="2001:10::88") /
2949 UDP(sport=1234, dport=1234) /
2952 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
2955 self.assertEqual(rx[Ether].src, routed_src_mac)
2956 self.assertEqual(rx[Ether].dst, sep1.mac)
2957 self.assertEqual(rx[IP].src, ep1.ip4.address)
2958 self.assertEqual(rx[IP].dst, "10.0.0.88")
2960 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep4.itf)
2963 self.assertEqual(rx[Ether].src, routed_src_mac)
2964 self.assertEqual(rx[Ether].dst, sep4.mac)
2965 self.assertEqual(rx[IPv6].src, ep1.ip6.address)
2966 self.assertEqual(rx[IPv6].dst, "2001:10::88")
2969 # test the dst-ip hash mode
2971 c5 = VppGbpContract(
2972 self, 220, 221, acl_index,
2973 [VppGbpContractRule(
2974 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2975 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
2976 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
2977 sep1.ip4, sep1.epg.rd),
2978 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
2979 sep2.ip4, sep2.epg.rd)]),
2981 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2982 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
2983 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
2984 sep3.ip6, sep3.epg.rd),
2985 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
2986 sep4.ip6, sep4.epg.rd)])])
2989 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
2992 self.assertEqual(rx[Ether].src, routed_src_mac)
2993 self.assertEqual(rx[Ether].dst, sep1.mac)
2994 self.assertEqual(rx[IP].src, ep1.ip4.address)
2995 self.assertEqual(rx[IP].dst, "10.0.0.88")
2997 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep3.itf)
3000 self.assertEqual(rx[Ether].src, routed_src_mac)
3001 self.assertEqual(rx[Ether].dst, sep3.mac)
3002 self.assertEqual(rx[IPv6].src, ep1.ip6.address)
3003 self.assertEqual(rx[IPv6].dst, "2001:10::88")
3008 self.pg7.unconfig_ip4()
3010 def test_gbp_l3_out(self):
3013 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
3014 self.vapi.cli("set logging class gbp debug")
3016 routed_dst_mac = "00:0c:0c:0c:0c:0c"
3017 routed_src_mac = "00:22:bd:f8:19:ff"
3022 t4 = VppIpTable(self, 1)
3024 t6 = VppIpTable(self, 1, True)
3027 rd1 = VppGbpRouteDomain(self, 2, t4, t6)
3028 rd1.add_vpp_config()
3030 self.loop0.set_mac(self.router_mac.address)
3033 # Bind the BVI to the RD
3035 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
3036 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
3039 # Pg7 hosts a BD's BUM
3040 # Pg1 some other l3 interface
3042 self.pg7.config_ip4()
3043 self.pg7.resolve_arp()
3046 # a GBP external bridge domains for the EPs
3048 bd1 = VppBridgeDomain(self, 1)
3049 bd1.add_vpp_config()
3050 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0)
3051 gbd1.add_vpp_config()
3054 # The Endpoint-groups in which the external endpoints exist
3056 epg_220 = VppGbpEndpointGroup(self, 220, rd1, gbd1,
3060 epg_220.add_vpp_config()
3062 # the BVIs have the subnets applied ...
3063 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 24)
3064 ip4_addr.add_vpp_config()
3065 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 64)
3066 ip6_addr.add_vpp_config()
3068 # ... which are L3-out subnets
3069 l3o_1 = VppGbpSubnet(
3070 self, rd1, "10.0.0.0", 24,
3071 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3073 l3o_1.add_vpp_config()
3076 # an external interface attached to the outside world and the
3079 vlan_100 = VppDot1QSubint(self, self.pg0, 100)
3081 ext_itf = VppGbpExtItf(self, vlan_100, bd1, rd1)
3082 ext_itf.add_vpp_config()
3085 # a multicast vxlan-gbp tunnel for broadcast in the BD
3087 tun_bm = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
3090 tun_bm.add_vpp_config()
3091 bp_bm = VppBridgeDomainPort(self, bd1, tun_bm,
3092 port_type=L2_PORT_TYPE.NORMAL)
3093 bp_bm.add_vpp_config()
3096 # an unicast vxlan-gbp for inter-BD traffic
3098 vx_tun_l3 = VppGbpVxlanTunnel(
3099 self, 444, rd1.rd_id,
3100 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3)
3101 vx_tun_l3.add_vpp_config()
3104 # packets destined to unkown addresses in the BVI's subnet
3107 p4 = (Ether(src=self.pg0.remote_mac, dst=self.router_mac.address) /
3109 IP(src="10.0.0.1", dst="10.0.0.88") /
3110 UDP(sport=1234, dport=1234) /
3112 p6 = (Ether(src=self.pg0.remote_mac, dst=self.router_mac.address) /
3114 IPv6(src="2001:10::1", dst="2001:10::88") /
3115 UDP(sport=1234, dport=1234) /
3118 rxs = self.send_and_expect(self.pg0, p4 * 1, self.pg7)
3121 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3122 # self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3123 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3124 self.assertEqual(rx[IP].dst, "239.1.1.1")
3125 self.assertEqual(rx[VXLAN].vni, 88)
3126 self.assertTrue(rx[VXLAN].flags.G)
3127 self.assertTrue(rx[VXLAN].flags.Instance)
3128 # policy is not applied since we don't know where it's going
3129 self.assertFalse(rx[VXLAN].gpflags.A)
3130 self.assertFalse(rx[VXLAN].gpflags.D)
3132 inner = rx[VXLAN].payload
3134 self.assertTrue(inner.haslayer(ARP))
3137 # An external Endpoint
3139 eep = VppGbpEndpoint(self, vlan_100,
3141 "10.0.0.1", "11.0.0.1",
3142 "2001:10::1", "3001::1",
3143 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
3144 eep.add_vpp_config()
3149 rep = VppGbpEndpoint(self, vx_tun_l3,
3151 "10.0.0.101", "11.0.0.101",
3152 "2001:10::101", "3001::101",
3153 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
3155 self.pg7.remote_ip4,
3157 rep.add_vpp_config()
3160 # remote to external
3162 p = (Ether(src=self.pg7.remote_mac,
3163 dst=self.pg7.local_mac) /
3164 IP(src=self.pg7.remote_ip4,
3165 dst=self.pg7.local_ip4) /
3166 UDP(sport=1234, dport=48879) /
3167 VXLAN(vni=444, gpid=220, flags=0x88) /
3168 Ether(src=self.pg0.remote_mac, dst=self.router_mac.address) /
3169 IP(src="10.0.0.101", dst="10.0.0.1") /
3170 UDP(sport=1234, dport=1234) /
3173 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
3176 # A subnet reachable through the external EP
3178 ip_220 = VppIpRoute(self, "10.220.0.0", 24,
3179 [VppRoutePath(eep.ip4.address,
3180 eep.epg.bvi.sw_if_index)],
3181 table_id=t4.table_id)
3182 ip_220.add_vpp_config()
3184 l3o_220 = VppGbpSubnet(
3185 self, rd1, "10.220.0.0", 24,
3186 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3188 l3o_220.add_vpp_config()
3190 p = (Ether(src=self.pg7.remote_mac,
3191 dst=self.pg7.local_mac) /
3192 IP(src=self.pg7.remote_ip4,
3193 dst=self.pg7.local_ip4) /
3194 UDP(sport=1234, dport=48879) /
3195 VXLAN(vni=444, gpid=220, flags=0x88) /
3196 Ether(src=self.pg0.remote_mac, dst=self.router_mac.address) /
3197 IP(src="10.0.0.101", dst="10.220.0.1") /
3198 UDP(sport=1234, dport=1234) /
3201 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
3204 # another external subnet, this time in a different EPG
3206 ip_200 = VppIpRoute(self, "10.200.0.0", 24,
3207 [VppRoutePath(eep.ip4.address,
3208 eep.epg.bvi.sw_if_index)],
3209 table_id=t4.table_id)
3210 ip_200.add_vpp_config()
3212 l3o_200 = VppGbpSubnet(
3213 self, rd1, "10.200.0.0", 24,
3214 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3216 l3o_200.add_vpp_config()
3218 p = (Ether(src=self.pg7.remote_mac,
3219 dst=self.pg7.local_mac) /
3220 IP(src=self.pg7.remote_ip4,
3221 dst=self.pg7.local_ip4) /
3222 UDP(sport=1234, dport=48879) /
3223 VXLAN(vni=444, gpid=220, flags=0x88) /
3224 Ether(src=self.pg0.remote_mac, dst=self.router_mac.address) /
3225 IP(src="10.0.0.101", dst="10.200.0.1") /
3226 UDP(sport=1234, dport=1234) /
3230 # packets dropped due to lack of contract.
3232 rxs = self.send_and_assert_no_replies(self.pg7, p * 1)
3235 # from the the subnet in EPG 220 beyond the external to remote
3237 p4 = (Ether(src=self.pg0.remote_mac, dst=self.router_mac.address) /
3239 IP(src="10.220.0.1", dst=rep.ip4.address) /
3240 UDP(sport=1234, dport=1234) /
3243 rxs = self.send_and_expect(self.pg0, p4 * 1, self.pg7)
3246 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3247 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3248 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3249 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
3250 self.assertEqual(rx[VXLAN].vni, 444)
3251 self.assertTrue(rx[VXLAN].flags.G)
3252 self.assertTrue(rx[VXLAN].flags.Instance)
3253 self.assertTrue(rx[VXLAN].gpflags.A)
3254 self.assertFalse(rx[VXLAN].gpflags.D)
3257 # from the the subnet in EPG 200 beyond the external to remote
3258 # dropped due to no contract
3260 p4 = (Ether(src=self.pg0.remote_mac, dst=self.router_mac.address) /
3262 IP(src="10.200.0.1", dst=rep.ip4.address) /
3263 UDP(sport=1234, dport=1234) /
3266 rxs = self.send_and_assert_no_replies(self.pg0, p4 * 1)
3271 acl = VppGbpAcl(self)
3272 rule = acl.create_rule(permit_deny=1, proto=17)
3273 rule2 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
3274 acl_index = acl.add_vpp_config([rule, rule2])
3275 c1 = VppGbpContract(
3276 self, 200, 220, acl_index,
3277 [VppGbpContractRule(
3278 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3281 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3285 rxs = self.send_and_expect(self.pg0, p4 * 1, self.pg7)
3288 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3289 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3290 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3291 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
3292 self.assertEqual(rx[VXLAN].vni, 444)
3293 self.assertTrue(rx[VXLAN].flags.G)
3294 self.assertTrue(rx[VXLAN].flags.Instance)
3295 self.assertTrue(rx[VXLAN].gpflags.A)
3296 self.assertFalse(rx[VXLAN].gpflags.D)
3301 self.pg7.unconfig_ip4()
3304 if __name__ == '__main__':
3305 unittest.main(testRunner=VppTestRunner)