3 from socket import AF_INET, AF_INET6
6 from scapy.packet import Raw
7 from scapy.layers.l2 import Ether, ARP, Dot1Q
8 from scapy.layers.inet import IP, UDP, ICMP
9 from scapy.layers.inet6 import IPv6, ICMPv6ND_NS, ICMPv6NDOptSrcLLAddr, \
11 from scapy.utils6 import in6_getnsma, in6_getnsmac
12 from scapy.layers.vxlan import VXLAN
13 from scapy.data import ETH_P_IP, ETH_P_IPV6
14 from scapy.utils import inet_pton, inet_ntop
16 from framework import VppTestCase, VppTestRunner
17 from vpp_object import VppObject
18 from vpp_interface import VppInterface
19 from vpp_ip_route import VppIpRoute, VppRoutePath, VppIpTable, \
20 VppIpInterfaceAddress, VppIpInterfaceBind, find_route
21 from vpp_l2 import VppBridgeDomain, VppBridgeDomainPort, \
22 VppBridgeDomainArpEntry, VppL2FibEntry, find_bridge_domain_port, VppL2Vtr
23 from vpp_sub_interface import VppDot1QSubint
24 from vpp_ip import VppIpAddress, VppIpPrefix
25 from vpp_papi import VppEnum, MACAddress
26 from vpp_papi_provider import L2_VTR_OP
27 from vpp_vxlan_gbp_tunnel import find_vxlan_gbp_tunnel, INDEX_INVALID, \
31 def find_gbp_endpoint(test, sw_if_index=None, ip=None, mac=None):
33 vip = VppIpAddress(ip)
35 vmac = MACAddress(mac)
37 eps = test.vapi.gbp_endpoint_dump()
41 if ep.endpoint.sw_if_index != sw_if_index:
44 for eip in ep.endpoint.ips:
48 if vmac.packed == ep.endpoint.mac:
53 def find_gbp_vxlan(test, vni):
54 ts = test.vapi.gbp_vxlan_tunnel_dump()
56 if t.tunnel.vni == vni:
61 class VppGbpEndpoint(VppObject):
88 return [self.ip4, self.ip6]
92 return [self.fip4, self.fip6]
94 def __init__(self, test, itf, epg, recirc, ip4, fip4, ip6, fip6,
104 self._ip4 = VppIpAddress(ip4)
105 self._fip4 = VppIpAddress(fip4)
106 self._ip6 = VppIpAddress(ip6)
107 self._fip6 = VppIpAddress(fip6)
110 self.vmac = MACAddress(self.itf.remote_mac)
112 self.vmac = MACAddress("00:00:00:00:00:00")
115 self.tun_src = VppIpAddress(tun_src)
116 self.tun_dst = VppIpAddress(tun_dst)
118 def add_vpp_config(self):
119 res = self._test.vapi.gbp_endpoint_add(
120 self.itf.sw_if_index,
121 [self.ip4.encode(), self.ip6.encode()],
125 self.tun_src.encode(),
126 self.tun_dst.encode())
127 self.handle = res.handle
128 self._test.registry.register(self, self._test.logger)
130 def remove_vpp_config(self):
131 self._test.vapi.gbp_endpoint_del(self.handle)
134 return self.object_id()
137 return "gbp-endpoint:[%d==%d:%s:%d]" % (self.handle,
138 self.itf.sw_if_index,
142 def query_vpp_config(self):
143 return find_gbp_endpoint(self._test,
144 self.itf.sw_if_index,
148 class VppGbpRecirc(VppObject):
150 GBP Recirculation Interface
153 def __init__(self, test, epg, recirc, is_ext=False):
159 def add_vpp_config(self):
160 self._test.vapi.gbp_recirc_add_del(
162 self.recirc.sw_if_index,
165 self._test.registry.register(self, self._test.logger)
167 def remove_vpp_config(self):
168 self._test.vapi.gbp_recirc_add_del(
170 self.recirc.sw_if_index,
175 return self.object_id()
178 return "gbp-recirc:[%d]" % (self.recirc.sw_if_index)
180 def query_vpp_config(self):
181 rs = self._test.vapi.gbp_recirc_dump()
183 if r.recirc.sw_if_index == self.recirc.sw_if_index:
188 class VppGbpExtItf(VppObject):
190 GBP ExtItfulation Interface
193 def __init__(self, test, itf, bd, rd):
199 def add_vpp_config(self):
200 self._test.vapi.gbp_ext_itf_add_del(
202 self.itf.sw_if_index,
205 self._test.registry.register(self, self._test.logger)
207 def remove_vpp_config(self):
208 self._test.vapi.gbp_ext_itf_add_del(
210 self.itf.sw_if_index,
215 return self.object_id()
218 return "gbp-ext-itf:[%d]" % (self.itf.sw_if_index)
220 def query_vpp_config(self):
221 rs = self._test.vapi.gbp_ext_itf_dump()
223 if r.ext_itf.sw_if_index == self.itf.sw_if_index:
228 class VppGbpSubnet(VppObject):
232 def __init__(self, test, rd, address, address_len,
233 type, sw_if_index=None, epg=None):
235 self.rd_id = rd.rd_id
236 self.prefix = VppIpPrefix(address, address_len)
238 self.sw_if_index = sw_if_index
241 def add_vpp_config(self):
242 self._test.vapi.gbp_subnet_add_del(
245 self.prefix.encode(),
247 sw_if_index=self.sw_if_index if self.sw_if_index else 0xffffffff,
248 sclass=self.epg.sclass if self.epg else 0xffff)
249 self._test.registry.register(self, self._test.logger)
251 def remove_vpp_config(self):
252 self._test.vapi.gbp_subnet_add_del(
255 self.prefix.encode(),
259 return self.object_id()
262 return "gbp-subnet:[%d-%s]" % (self.rd_id, self.prefix)
264 def query_vpp_config(self):
265 ss = self._test.vapi.gbp_subnet_dump()
267 if s.subnet.rd_id == self.rd_id and \
268 s.subnet.type == self.type and \
269 s.subnet.prefix == self.prefix:
274 class VppGbpEndpointRetention(object):
275 def __init__(self, remote_ep_timeout=0xffffffff):
276 self.remote_ep_timeout = remote_ep_timeout
279 return {'remote_ep_timeout': self.remote_ep_timeout}
282 class VppGbpEndpointGroup(VppObject):
287 def __init__(self, test, vnid, sclass, rd, bd, uplink,
288 bvi, bvi_ip4, bvi_ip6=None,
289 retention=VppGbpEndpointRetention()):
293 self.bvi_ip4 = VppIpAddress(bvi_ip4)
294 self.bvi_ip6 = VppIpAddress(bvi_ip6)
301 self.retention = retention
303 def add_vpp_config(self):
304 self._test.vapi.gbp_endpoint_group_add(
309 self.uplink.sw_if_index if self.uplink else INDEX_INVALID,
310 self.retention.encode())
311 self._test.registry.register(self, self._test.logger)
313 def remove_vpp_config(self):
314 self._test.vapi.gbp_endpoint_group_del(self.sclass)
317 return self.object_id()
320 return "gbp-endpoint-group:[%d]" % (self.vnid)
322 def query_vpp_config(self):
323 epgs = self._test.vapi.gbp_endpoint_group_dump()
325 if epg.epg.vnid == self.vnid:
330 class VppGbpBridgeDomain(VppObject):
335 def __init__(self, test, bd, bvi, uu_fwd=None,
336 bm_flood=None, learn=True):
340 self.bm_flood = bm_flood
343 e = VppEnum.vl_api_gbp_bridge_domain_flags_t
345 self.learn = e.GBP_BD_API_FLAG_NONE
347 self.learn = e.GBP_BD_API_FLAG_DO_NOT_LEARN
349 def add_vpp_config(self):
350 self._test.vapi.gbp_bridge_domain_add(
353 self.bvi.sw_if_index,
354 self.uu_fwd.sw_if_index if self.uu_fwd else INDEX_INVALID,
355 self.bm_flood.sw_if_index if self.bm_flood else INDEX_INVALID)
356 self._test.registry.register(self, self._test.logger)
358 def remove_vpp_config(self):
359 self._test.vapi.gbp_bridge_domain_del(self.bd.bd_id)
362 return self.object_id()
365 return "gbp-bridge-domain:[%d]" % (self.bd.bd_id)
367 def query_vpp_config(self):
368 bds = self._test.vapi.gbp_bridge_domain_dump()
370 if bd.bd.bd_id == self.bd.bd_id:
375 class VppGbpRouteDomain(VppObject):
380 def __init__(self, test, rd_id, t4, t6, ip4_uu=None, ip6_uu=None):
388 def add_vpp_config(self):
389 self._test.vapi.gbp_route_domain_add(
393 self.ip4_uu.sw_if_index if self.ip4_uu else INDEX_INVALID,
394 self.ip6_uu.sw_if_index if self.ip6_uu else INDEX_INVALID)
395 self._test.registry.register(self, self._test.logger)
397 def remove_vpp_config(self):
398 self._test.vapi.gbp_route_domain_del(self.rd_id)
401 return self.object_id()
404 return "gbp-route-domain:[%d]" % (self.rd_id)
406 def query_vpp_config(self):
407 rds = self._test.vapi.gbp_route_domain_dump()
409 if rd.rd.rd_id == self.rd_id:
414 class VppGbpContractNextHop():
415 def __init__(self, mac, bd, ip, rd):
422 return {'ip': self.ip.encode(),
423 'mac': self.mac.packed,
424 'bd_id': self.bd.bd.bd_id,
425 'rd_id': self.rd.rd_id}
428 class VppGbpContractRule():
429 def __init__(self, action, hash_mode, nhs=[]):
431 self.hash_mode = hash_mode
437 nhs.append(nh.encode())
440 return {'action': self.action,
442 'hash_mode': self.hash_mode,
443 'n_nhs': len(self.nhs),
447 class VppGbpContract(VppObject):
452 def __init__(self, test, src_epg, dst_epg, acl_index,
453 rules, allowed_ethertypes):
455 self.acl_index = acl_index
456 self.src_epg = src_epg
457 self.dst_epg = dst_epg
459 self.allowed_ethertypes = allowed_ethertypes
460 while (len(self.allowed_ethertypes) < 16):
461 self.allowed_ethertypes.append(0)
463 def add_vpp_config(self):
466 rules.append(r.encode())
467 self._test.vapi.gbp_contract_add_del(
473 self.allowed_ethertypes)
474 self._test.registry.register(self, self._test.logger)
476 def remove_vpp_config(self):
477 self._test.vapi.gbp_contract_add_del(
483 self.allowed_ethertypes)
486 return self.object_id()
489 return "gbp-contract:[%d:%s:%d]" % (self.src_epg.sclass,
493 def query_vpp_config(self):
494 cs = self._test.vapi.gbp_contract_dump()
496 if c.contract.sclass == self.src_epg.sclass \
497 and c.contract.dclass == self.dst_epg.sclass:
502 class VppGbpVxlanTunnel(VppInterface):
507 def __init__(self, test, vni, bd_rd_id, mode, src):
508 super(VppGbpVxlanTunnel, self).__init__(test)
511 self.bd_rd_id = bd_rd_id
515 def add_vpp_config(self):
516 r = self._test.vapi.gbp_vxlan_tunnel_add(
521 self.set_sw_if_index(r.sw_if_index)
522 self._test.registry.register(self, self._test.logger)
524 def remove_vpp_config(self):
525 self._test.vapi.gbp_vxlan_tunnel_del(self.vni)
528 return self.object_id()
531 return "gbp-vxlan:%d" % (self.sw_if_index)
533 def query_vpp_config(self):
534 return find_gbp_vxlan(self._test, self.vni)
537 class VppGbpAcl(VppObject):
542 def __init__(self, test):
544 self.acl_index = 4294967295
546 def create_rule(self, is_ipv6=0, permit_deny=0, proto=-1,
547 s_prefix=0, s_ip=b'\x00\x00\x00\x00', sport_from=0,
548 sport_to=65535, d_prefix=0, d_ip=b'\x00\x00\x00\x00',
549 dport_from=0, dport_to=65535):
550 if proto == -1 or proto == 0:
553 elif proto == 1 or proto == 58:
556 rule = ({'is_permit': permit_deny, 'is_ipv6': is_ipv6, 'proto': proto,
557 'srcport_or_icmptype_first': sport_from,
558 'srcport_or_icmptype_last': sport_to,
559 'src_ip_prefix_len': s_prefix,
561 'dstport_or_icmpcode_first': dport_from,
562 'dstport_or_icmpcode_last': dport_to,
563 'dst_ip_prefix_len': d_prefix,
564 'dst_ip_addr': d_ip})
567 def add_vpp_config(self, rules):
569 reply = self._test.vapi.acl_add_replace(self.acl_index,
572 self.acl_index = reply.acl_index
573 return self.acl_index
575 def remove_vpp_config(self):
576 self._test.vapi.acl_del(self.acl_index)
579 return self.object_id()
582 return "gbp-acl:[%d]" % (self.acl_index)
584 def query_vpp_config(self):
585 cs = self._test.vapi.acl_dump()
587 if c.acl_index == self.acl_index:
592 class TestGBP(VppTestCase):
593 """ GBP Test Case """
596 super(TestGBP, self).setUp()
598 self.create_pg_interfaces(range(9))
599 self.create_loopback_interfaces(8)
601 self.router_mac = MACAddress("00:11:22:33:44:55")
603 for i in self.pg_interfaces:
605 for i in self.lo_interfaces:
609 for i in self.pg_interfaces:
612 super(TestGBP, self).tearDown()
614 def send_and_expect_bridged(self, src, tx, dst):
615 rx = self.send_and_expect(src, tx, dst)
618 self.assertEqual(r[Ether].src, tx[0][Ether].src)
619 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
620 self.assertEqual(r[IP].src, tx[0][IP].src)
621 self.assertEqual(r[IP].dst, tx[0][IP].dst)
624 def send_and_expect_bridged6(self, src, tx, dst):
625 rx = self.send_and_expect(src, tx, dst)
628 self.assertEqual(r[Ether].src, tx[0][Ether].src)
629 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
630 self.assertEqual(r[IPv6].src, tx[0][IPv6].src)
631 self.assertEqual(r[IPv6].dst, tx[0][IPv6].dst)
634 def send_and_expect_routed(self, src, tx, dst, src_mac):
635 rx = self.send_and_expect(src, tx, dst)
638 self.assertEqual(r[Ether].src, src_mac)
639 self.assertEqual(r[Ether].dst, dst.remote_mac)
640 self.assertEqual(r[IP].src, tx[0][IP].src)
641 self.assertEqual(r[IP].dst, tx[0][IP].dst)
644 def send_and_expect_natted(self, src, tx, dst, src_ip):
645 rx = self.send_and_expect(src, tx, dst)
648 self.assertEqual(r[Ether].src, tx[0][Ether].src)
649 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
650 self.assertEqual(r[IP].src, src_ip)
651 self.assertEqual(r[IP].dst, tx[0][IP].dst)
654 def send_and_expect_natted6(self, src, tx, dst, src_ip):
655 rx = self.send_and_expect(src, tx, dst)
658 self.assertEqual(r[Ether].src, tx[0][Ether].src)
659 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
660 self.assertEqual(r[IPv6].src, src_ip)
661 self.assertEqual(r[IPv6].dst, tx[0][IPv6].dst)
664 def send_and_expect_unnatted(self, src, tx, dst, dst_ip):
665 rx = self.send_and_expect(src, tx, dst)
668 self.assertEqual(r[Ether].src, tx[0][Ether].src)
669 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
670 self.assertEqual(r[IP].dst, dst_ip)
671 self.assertEqual(r[IP].src, tx[0][IP].src)
674 def send_and_expect_unnatted6(self, src, tx, dst, dst_ip):
675 rx = self.send_and_expect(src, tx, dst)
678 self.assertEqual(r[Ether].src, tx[0][Ether].src)
679 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
680 self.assertEqual(r[IPv6].dst, dst_ip)
681 self.assertEqual(r[IPv6].src, tx[0][IPv6].src)
684 def send_and_expect_double_natted(self, src, tx, dst, src_ip, dst_ip):
685 rx = self.send_and_expect(src, tx, dst)
688 self.assertEqual(r[Ether].src, str(self.router_mac))
689 self.assertEqual(r[Ether].dst, dst.remote_mac)
690 self.assertEqual(r[IP].dst, dst_ip)
691 self.assertEqual(r[IP].src, src_ip)
694 def send_and_expect_double_natted6(self, src, tx, dst, src_ip, dst_ip):
695 rx = self.send_and_expect(src, tx, dst)
698 self.assertEqual(r[Ether].src, str(self.router_mac))
699 self.assertEqual(r[Ether].dst, dst.remote_mac)
700 self.assertEqual(r[IPv6].dst, dst_ip)
701 self.assertEqual(r[IPv6].src, src_ip)
705 """ Group Based Policy """
707 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
712 bd1 = VppBridgeDomain(self, 1)
713 bd2 = VppBridgeDomain(self, 2)
714 bd20 = VppBridgeDomain(self, 20)
718 bd20.add_vpp_config()
720 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0)
721 gbd2 = VppGbpBridgeDomain(self, bd2, self.loop1)
722 gbd20 = VppGbpBridgeDomain(self, bd20, self.loop2)
724 gbd1.add_vpp_config()
725 gbd2.add_vpp_config()
726 gbd20.add_vpp_config()
731 gt4 = VppIpTable(self, 0)
733 gt6 = VppIpTable(self, 0, is_ip6=True)
735 nt4 = VppIpTable(self, 20)
737 nt6 = VppIpTable(self, 20, is_ip6=True)
740 rd0 = VppGbpRouteDomain(self, 0, gt4, gt6, None, None)
741 rd20 = VppGbpRouteDomain(self, 20, nt4, nt6, None, None)
744 rd20.add_vpp_config()
747 # 3 EPGs, 2 of which share a BD.
748 # 2 NAT EPGs, one for floating-IP subnets, the other for internet
750 epgs = [VppGbpEndpointGroup(self, 220, 1220, rd0, gbd1,
751 self.pg4, self.loop0,
752 "10.0.0.128", "2001:10::128"),
753 VppGbpEndpointGroup(self, 221, 1221, rd0, gbd1,
754 self.pg5, self.loop0,
755 "10.0.1.128", "2001:10:1::128"),
756 VppGbpEndpointGroup(self, 222, 1222, rd0, gbd2,
757 self.pg6, self.loop1,
758 "10.0.2.128", "2001:10:2::128"),
759 VppGbpEndpointGroup(self, 333, 1333, rd20, gbd20,
760 self.pg7, self.loop2,
761 "11.0.0.128", "3001::128"),
762 VppGbpEndpointGroup(self, 444, 1444, rd20, gbd20,
763 self.pg8, self.loop2,
764 "11.0.0.129", "3001::129")]
765 recircs = [VppGbpRecirc(self, epgs[0], self.loop3),
766 VppGbpRecirc(self, epgs[1], self.loop4),
767 VppGbpRecirc(self, epgs[2], self.loop5),
768 VppGbpRecirc(self, epgs[3], self.loop6, is_ext=True),
769 VppGbpRecirc(self, epgs[4], self.loop7, is_ext=True)]
772 recirc_nat = recircs[3]
775 # 4 end-points, 2 in the same subnet, 3 in the same BD
777 eps = [VppGbpEndpoint(self, self.pg0,
779 "10.0.0.1", "11.0.0.1",
780 "2001:10::1", "3001::1"),
781 VppGbpEndpoint(self, self.pg1,
783 "10.0.0.2", "11.0.0.2",
784 "2001:10::2", "3001::2"),
785 VppGbpEndpoint(self, self.pg2,
787 "10.0.1.1", "11.0.0.3",
788 "2001:10:1::1", "3001::3"),
789 VppGbpEndpoint(self, self.pg3,
791 "10.0.2.1", "11.0.0.4",
792 "2001:10:2::1", "3001::4")]
795 # Config related to each of the EPGs
798 # IP config on the BVI interfaces
799 if epg != epgs[1] and epg != epgs[4]:
800 VppIpInterfaceBind(self, epg.bvi, epg.rd.t4).add_vpp_config()
801 VppIpInterfaceBind(self, epg.bvi, epg.rd.t6).add_vpp_config()
802 self.vapi.sw_interface_set_mac_address(
804 self.router_mac.packed)
806 # The BVIs are NAT inside interfaces
807 self.vapi.nat44_interface_add_del_feature(epg.bvi.sw_if_index,
810 self.vapi.nat66_add_del_interface(epg.bvi.sw_if_index,
814 if_ip4 = VppIpInterfaceAddress(self, epg.bvi, epg.bvi_ip4, 32)
815 if_ip6 = VppIpInterfaceAddress(self, epg.bvi, epg.bvi_ip6, 128)
816 if_ip4.add_vpp_config()
817 if_ip6.add_vpp_config()
819 # EPG uplink interfaces in the RD
820 VppIpInterfaceBind(self, epg.uplink, epg.rd.t4).add_vpp_config()
821 VppIpInterfaceBind(self, epg.uplink, epg.rd.t6).add_vpp_config()
823 # add the BD ARP termination entry for BVI IP
824 epg.bd_arp_ip4 = VppBridgeDomainArpEntry(self, epg.bd.bd,
825 str(self.router_mac),
827 epg.bd_arp_ip6 = VppBridgeDomainArpEntry(self, epg.bd.bd,
828 str(self.router_mac),
830 epg.bd_arp_ip4.add_vpp_config()
831 epg.bd_arp_ip6.add_vpp_config()
836 for recirc in recircs:
837 # EPG's ingress recirculation interface maps to its RD
838 VppIpInterfaceBind(self, recirc.recirc,
839 recirc.epg.rd.t4).add_vpp_config()
840 VppIpInterfaceBind(self, recirc.recirc,
841 recirc.epg.rd.t6).add_vpp_config()
843 self.vapi.nat44_interface_add_del_feature(
844 recirc.recirc.sw_if_index,
847 self.vapi.nat66_add_del_interface(
848 recirc.recirc.sw_if_index,
852 recirc.add_vpp_config()
854 for recirc in recircs:
855 self.assertTrue(find_bridge_domain_port(self,
856 recirc.epg.bd.bd.bd_id,
857 recirc.recirc.sw_if_index))
860 self.pg_enable_capture(self.pg_interfaces)
863 # routes to the endpoints. We need these since there are no
864 # adj-fibs due to the fact the the BVI address has /32 and
865 # the subnet is not attached.
867 for (ip, fip) in zip(ep.ips, ep.fips):
868 # Add static mappings for each EP from the 10/8 to 11/8 network
870 self.vapi.nat44_add_del_static_mapping(ip.bytes,
875 self.vapi.nat66_add_del_static_mapping(ip.bytes,
882 self.logger.info(self.vapi.cli("sh gbp endpoint"))
884 # ... results in a Gratuitous ARP/ND on the EPG's uplink
885 rx = ep.epg.uplink.get_capture(len(ep.ips), timeout=0.2)
887 for ii, ip in enumerate(ep.ips):
891 self.assertTrue(p.haslayer(ICMPv6ND_NA))
892 self.assertEqual(p[ICMPv6ND_NA].tgt, ip.address)
894 self.assertTrue(p.haslayer(ARP))
895 self.assertEqual(p[ARP].psrc, ip.address)
896 self.assertEqual(p[ARP].pdst, ip.address)
898 # add the BD ARP termination entry for floating IP
900 ba = VppBridgeDomainArpEntry(self, epg_nat.bd.bd, ep.mac, fip)
903 # floating IPs route via EPG recirc
904 r = VppIpRoute(self, fip.address, fip.length,
905 [VppRoutePath(fip.address,
906 ep.recirc.recirc.sw_if_index,
908 proto=fip.dpo_proto)],
913 # L2 FIB entries in the NAT EPG BD to bridge the packets from
914 # the outside direct to the internal EPG
915 lf = VppL2FibEntry(self, epg_nat.bd.bd, ep.mac,
916 ep.recirc.recirc, bvi_mac=0)
920 # ARP packets for unknown IP are sent to the EPG uplink
922 pkt_arp = (Ether(dst="ff:ff:ff:ff:ff:ff",
923 src=self.pg0.remote_mac) /
925 hwdst="ff:ff:ff:ff:ff:ff",
926 hwsrc=self.pg0.remote_mac,
930 self.vapi.cli("clear trace")
931 self.pg0.add_stream(pkt_arp)
933 self.pg_enable_capture(self.pg_interfaces)
936 rxd = epgs[0].uplink.get_capture(1)
939 # ARP/ND packets get a response
941 pkt_arp = (Ether(dst="ff:ff:ff:ff:ff:ff",
942 src=self.pg0.remote_mac) /
944 hwdst="ff:ff:ff:ff:ff:ff",
945 hwsrc=self.pg0.remote_mac,
946 pdst=epgs[0].bvi_ip4.address,
947 psrc=eps[0].ip4.address))
949 self.send_and_expect(self.pg0, [pkt_arp], self.pg0)
951 nsma = in6_getnsma(inet_pton(AF_INET6, eps[0].ip6.address))
952 d = inet_ntop(AF_INET6, nsma)
953 pkt_nd = (Ether(dst=in6_getnsmac(nsma),
954 src=self.pg0.remote_mac) /
955 IPv6(dst=d, src=eps[0].ip6.address) /
956 ICMPv6ND_NS(tgt=epgs[0].bvi_ip6.address) /
957 ICMPv6NDOptSrcLLAddr(lladdr=self.pg0.remote_mac))
958 self.send_and_expect(self.pg0, [pkt_nd], self.pg0)
961 # broadcast packets are flooded
963 pkt_bcast = (Ether(dst="ff:ff:ff:ff:ff:ff",
964 src=self.pg0.remote_mac) /
965 IP(src=eps[0].ip4.address, dst="232.1.1.1") /
966 UDP(sport=1234, dport=1234) /
969 self.vapi.cli("clear trace")
970 self.pg0.add_stream(pkt_bcast)
972 self.pg_enable_capture(self.pg_interfaces)
975 rxd = eps[1].itf.get_capture(1)
976 self.assertEqual(rxd[0][Ether].dst, pkt_bcast[Ether].dst)
977 rxd = epgs[0].uplink.get_capture(1)
978 self.assertEqual(rxd[0][Ether].dst, pkt_bcast[Ether].dst)
981 # packets to non-local L3 destinations dropped
983 pkt_intra_epg_220_ip4 = (Ether(src=self.pg0.remote_mac,
984 dst=str(self.router_mac)) /
985 IP(src=eps[0].ip4.address,
987 UDP(sport=1234, dport=1234) /
989 pkt_inter_epg_222_ip4 = (Ether(src=self.pg0.remote_mac,
990 dst=str(self.router_mac)) /
991 IP(src=eps[0].ip4.address,
993 UDP(sport=1234, dport=1234) /
996 self.send_and_assert_no_replies(self.pg0, pkt_intra_epg_220_ip4 * 65)
998 pkt_inter_epg_222_ip6 = (Ether(src=self.pg0.remote_mac,
999 dst=str(self.router_mac)) /
1000 IPv6(src=eps[0].ip6.address,
1001 dst="2001:10::99") /
1002 UDP(sport=1234, dport=1234) /
1004 self.send_and_assert_no_replies(self.pg0, pkt_inter_epg_222_ip6 * 65)
1007 # Add the subnet routes
1010 self, rd0, "10.0.0.0", 24,
1011 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1013 self, rd0, "10.0.1.0", 24,
1014 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1016 self, rd0, "10.0.2.0", 24,
1017 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1019 self, rd0, "2001:10::1", 64,
1020 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1022 self, rd0, "2001:10:1::1", 64,
1023 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1025 self, rd0, "2001:10:2::1", 64,
1026 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1027 s41.add_vpp_config()
1028 s42.add_vpp_config()
1029 s43.add_vpp_config()
1030 s61.add_vpp_config()
1031 s62.add_vpp_config()
1032 s63.add_vpp_config()
1034 self.send_and_expect_bridged(eps[0].itf,
1035 pkt_intra_epg_220_ip4 * 65,
1037 self.send_and_expect_bridged(eps[0].itf,
1038 pkt_inter_epg_222_ip4 * 65,
1040 self.send_and_expect_bridged6(eps[0].itf,
1041 pkt_inter_epg_222_ip6 * 65,
1044 self.logger.info(self.vapi.cli("sh ip fib 11.0.0.2"))
1045 self.logger.info(self.vapi.cli("sh gbp endpoint-group"))
1046 self.logger.info(self.vapi.cli("sh gbp endpoint"))
1047 self.logger.info(self.vapi.cli("sh gbp recirc"))
1048 self.logger.info(self.vapi.cli("sh int"))
1049 self.logger.info(self.vapi.cli("sh int addr"))
1050 self.logger.info(self.vapi.cli("sh int feat loop6"))
1051 self.logger.info(self.vapi.cli("sh vlib graph ip4-gbp-src-classify"))
1052 self.logger.info(self.vapi.cli("sh int feat loop3"))
1053 self.logger.info(self.vapi.cli("sh int feat pg0"))
1056 # Packet destined to unknown unicast is sent on the epg uplink ...
1058 pkt_intra_epg_220_to_uplink = (Ether(src=self.pg0.remote_mac,
1059 dst="00:00:00:33:44:55") /
1060 IP(src=eps[0].ip4.address,
1062 UDP(sport=1234, dport=1234) /
1065 self.send_and_expect_bridged(eps[0].itf,
1066 pkt_intra_epg_220_to_uplink * 65,
1068 # ... and nowhere else
1069 self.pg1.get_capture(0, timeout=0.1)
1070 self.pg1.assert_nothing_captured(remark="Flood onto other VMS")
1072 pkt_intra_epg_221_to_uplink = (Ether(src=self.pg2.remote_mac,
1073 dst="00:00:00:33:44:66") /
1074 IP(src=eps[0].ip4.address,
1076 UDP(sport=1234, dport=1234) /
1079 self.send_and_expect_bridged(eps[2].itf,
1080 pkt_intra_epg_221_to_uplink * 65,
1084 # Packets from the uplink are forwarded in the absence of a contract
1086 pkt_intra_epg_220_from_uplink = (Ether(src="00:00:00:33:44:55",
1087 dst=self.pg0.remote_mac) /
1088 IP(src=eps[0].ip4.address,
1090 UDP(sport=1234, dport=1234) /
1093 self.send_and_expect_bridged(self.pg4,
1094 pkt_intra_epg_220_from_uplink * 65,
1098 # in the absence of policy, endpoints in the same EPG
1101 pkt_intra_epg = (Ether(src=self.pg0.remote_mac,
1102 dst=self.pg1.remote_mac) /
1103 IP(src=eps[0].ip4.address,
1104 dst=eps[1].ip4.address) /
1105 UDP(sport=1234, dport=1234) /
1108 self.send_and_expect_bridged(self.pg0, pkt_intra_epg * 65, self.pg1)
1111 # in the abscense of policy, endpoints in the different EPG
1112 # cannot communicate
1114 pkt_inter_epg_220_to_221 = (Ether(src=self.pg0.remote_mac,
1115 dst=self.pg2.remote_mac) /
1116 IP(src=eps[0].ip4.address,
1117 dst=eps[2].ip4.address) /
1118 UDP(sport=1234, dport=1234) /
1120 pkt_inter_epg_221_to_220 = (Ether(src=self.pg2.remote_mac,
1121 dst=self.pg0.remote_mac) /
1122 IP(src=eps[2].ip4.address,
1123 dst=eps[0].ip4.address) /
1124 UDP(sport=1234, dport=1234) /
1126 pkt_inter_epg_220_to_222 = (Ether(src=self.pg0.remote_mac,
1127 dst=str(self.router_mac)) /
1128 IP(src=eps[0].ip4.address,
1129 dst=eps[3].ip4.address) /
1130 UDP(sport=1234, dport=1234) /
1133 self.send_and_assert_no_replies(eps[0].itf,
1134 pkt_inter_epg_220_to_221 * 65)
1135 self.send_and_assert_no_replies(eps[0].itf,
1136 pkt_inter_epg_220_to_222 * 65)
1139 # A uni-directional contract from EPG 220 -> 221
1141 acl = VppGbpAcl(self)
1142 rule = acl.create_rule(permit_deny=1, proto=17)
1143 rule2 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
1144 acl_index = acl.add_vpp_config([rule, rule2])
1145 c1 = VppGbpContract(
1146 self, epgs[0], epgs[1], acl_index,
1147 [VppGbpContractRule(
1148 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1151 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1153 [ETH_P_IP, ETH_P_IPV6])
1156 self.send_and_expect_bridged(eps[0].itf,
1157 pkt_inter_epg_220_to_221 * 65,
1159 self.send_and_assert_no_replies(eps[0].itf,
1160 pkt_inter_epg_220_to_222 * 65)
1163 # contract for the return direction
1165 c2 = VppGbpContract(
1166 self, epgs[1], epgs[0], acl_index,
1167 [VppGbpContractRule(
1168 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1171 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1173 [ETH_P_IP, ETH_P_IPV6])
1176 self.send_and_expect_bridged(eps[0].itf,
1177 pkt_inter_epg_220_to_221 * 65,
1179 self.send_and_expect_bridged(eps[2].itf,
1180 pkt_inter_epg_221_to_220 * 65,
1184 # the contract does not allow non-IP
1186 pkt_non_ip_inter_epg_220_to_221 = (Ether(src=self.pg0.remote_mac,
1187 dst=self.pg2.remote_mac) /
1189 self.send_and_assert_no_replies(eps[0].itf,
1190 pkt_non_ip_inter_epg_220_to_221 * 17)
1193 # check that inter group is still disabled for the groups
1194 # not in the contract.
1196 self.send_and_assert_no_replies(eps[0].itf,
1197 pkt_inter_epg_220_to_222 * 65)
1200 # A uni-directional contract from EPG 220 -> 222 'L3 routed'
1202 c3 = VppGbpContract(
1203 self, epgs[0], epgs[2], acl_index,
1204 [VppGbpContractRule(
1205 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1208 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1210 [ETH_P_IP, ETH_P_IPV6])
1213 self.logger.info(self.vapi.cli("sh gbp contract"))
1215 self.send_and_expect_routed(eps[0].itf,
1216 pkt_inter_epg_220_to_222 * 65,
1218 str(self.router_mac))
1221 # remove both contracts, traffic stops in both directions
1223 c2.remove_vpp_config()
1224 c1.remove_vpp_config()
1225 c3.remove_vpp_config()
1226 acl.remove_vpp_config()
1228 self.send_and_assert_no_replies(eps[2].itf,
1229 pkt_inter_epg_221_to_220 * 65)
1230 self.send_and_assert_no_replies(eps[0].itf,
1231 pkt_inter_epg_220_to_221 * 65)
1232 self.send_and_expect_bridged(eps[0].itf,
1237 # EPs to the outside world
1240 # in the EP's RD an external subnet via the NAT EPG's recirc
1242 self, rd0, "0.0.0.0", 0,
1243 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1244 sw_if_index=recirc_nat.recirc.sw_if_index,
1247 self, rd0, "11.0.0.0", 8,
1248 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1249 sw_if_index=recirc_nat.recirc.sw_if_index,
1251 se16 = VppGbpSubnet(
1253 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1254 sw_if_index=recirc_nat.recirc.sw_if_index,
1256 # in the NAT RD an external subnet via the NAT EPG's uplink
1258 self, rd20, "0.0.0.0", 0,
1259 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1260 sw_if_index=epg_nat.uplink.sw_if_index,
1262 se36 = VppGbpSubnet(
1263 self, rd20, "::", 0,
1264 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1265 sw_if_index=epg_nat.uplink.sw_if_index,
1268 self, rd20, "11.0.0.0", 8,
1269 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1270 sw_if_index=epg_nat.uplink.sw_if_index,
1272 se1.add_vpp_config()
1273 se2.add_vpp_config()
1274 se16.add_vpp_config()
1275 se3.add_vpp_config()
1276 se36.add_vpp_config()
1277 se4.add_vpp_config()
1279 self.logger.info(self.vapi.cli("sh ip fib 0.0.0.0/0"))
1280 self.logger.info(self.vapi.cli("sh ip fib 11.0.0.1"))
1281 self.logger.info(self.vapi.cli("sh ip6 fib ::/0"))
1282 self.logger.info(self.vapi.cli("sh ip6 fib %s" %
1286 # From an EP to an outside addess: IN2OUT
1288 pkt_inter_epg_220_to_global = (Ether(src=self.pg0.remote_mac,
1289 dst=str(self.router_mac)) /
1290 IP(src=eps[0].ip4.address,
1292 UDP(sport=1234, dport=1234) /
1296 self.send_and_assert_no_replies(eps[0].itf,
1297 pkt_inter_epg_220_to_global * 65)
1299 acl2 = VppGbpAcl(self)
1300 rule = acl2.create_rule(permit_deny=1, proto=17, sport_from=1234,
1301 sport_to=1234, dport_from=1234, dport_to=1234)
1302 rule2 = acl2.create_rule(is_ipv6=1, permit_deny=1, proto=17,
1303 sport_from=1234, sport_to=1234,
1304 dport_from=1234, dport_to=1234)
1306 acl_index2 = acl2.add_vpp_config([rule, rule2])
1307 c4 = VppGbpContract(
1308 self, epgs[0], epgs[3], acl_index2,
1309 [VppGbpContractRule(
1310 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1313 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1315 [ETH_P_IP, ETH_P_IPV6])
1318 self.send_and_expect_natted(eps[0].itf,
1319 pkt_inter_epg_220_to_global * 65,
1321 eps[0].fip4.address)
1323 pkt_inter_epg_220_to_global = (Ether(src=self.pg0.remote_mac,
1324 dst=str(self.router_mac)) /
1325 IPv6(src=eps[0].ip6.address,
1327 UDP(sport=1234, dport=1234) /
1330 self.send_and_expect_natted6(self.pg0,
1331 pkt_inter_epg_220_to_global * 65,
1333 eps[0].fip6.address)
1336 # From a global address to an EP: OUT2IN
1338 pkt_inter_epg_220_from_global = (Ether(src=str(self.router_mac),
1339 dst=self.pg0.remote_mac) /
1340 IP(dst=eps[0].fip4.address,
1342 UDP(sport=1234, dport=1234) /
1345 self.send_and_assert_no_replies(self.pg7,
1346 pkt_inter_epg_220_from_global * 65)
1348 c5 = VppGbpContract(
1349 self, epgs[3], epgs[0], acl_index2,
1350 [VppGbpContractRule(
1351 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1354 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1356 [ETH_P_IP, ETH_P_IPV6])
1359 self.send_and_expect_unnatted(self.pg7,
1360 pkt_inter_epg_220_from_global * 65,
1364 pkt_inter_epg_220_from_global = (Ether(src=str(self.router_mac),
1365 dst=self.pg0.remote_mac) /
1366 IPv6(dst=eps[0].fip6.address,
1368 UDP(sport=1234, dport=1234) /
1371 self.send_and_expect_unnatted6(self.pg7,
1372 pkt_inter_epg_220_from_global * 65,
1377 # From a local VM to another local VM using resp. public addresses:
1380 pkt_intra_epg_220_global = (Ether(src=self.pg0.remote_mac,
1381 dst=str(self.router_mac)) /
1382 IP(src=eps[0].ip4.address,
1383 dst=eps[1].fip4.address) /
1384 UDP(sport=1234, dport=1234) /
1387 self.send_and_expect_double_natted(eps[0].itf,
1388 pkt_intra_epg_220_global * 65,
1390 eps[0].fip4.address,
1393 pkt_intra_epg_220_global = (Ether(src=self.pg0.remote_mac,
1394 dst=str(self.router_mac)) /
1395 IPv6(src=eps[0].ip6.address,
1396 dst=eps[1].fip6.address) /
1397 UDP(sport=1234, dport=1234) /
1400 self.send_and_expect_double_natted6(eps[0].itf,
1401 pkt_intra_epg_220_global * 65,
1403 eps[0].fip6.address,
1410 # del static mappings for each EP from the 10/8 to 11/8 network
1411 self.vapi.nat44_add_del_static_mapping(ep.ip4.bytes,
1416 self.vapi.nat66_add_del_static_mapping(ep.ip6.bytes,
1422 # IP config on the BVI interfaces
1423 if epg != epgs[0] and epg != epgs[3]:
1424 self.vapi.nat44_interface_add_del_feature(epg.bvi.sw_if_index,
1427 self.vapi.nat66_add_del_interface(epg.bvi.sw_if_index,
1431 for recirc in recircs:
1432 self.vapi.nat44_interface_add_del_feature(
1433 recirc.recirc.sw_if_index,
1436 self.vapi.nat66_add_del_interface(
1437 recirc.recirc.sw_if_index,
1441 def wait_for_ep_timeout(self, sw_if_index=None, ip=None, mac=None,
1442 n_tries=100, s_time=1):
1444 if not find_gbp_endpoint(self, sw_if_index, ip, mac):
1446 n_tries = n_tries - 1
1448 self.assertFalse(find_gbp_endpoint(self, sw_if_index, ip, mac))
1451 def test_gbp_learn_l2(self):
1452 """ GBP L2 Endpoint Learning """
1454 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
1455 learnt = [{'mac': '00:00:11:11:11:01',
1457 'ip6': '2001:10::2'},
1458 {'mac': '00:00:11:11:11:02',
1460 'ip6': '2001:10::3'}]
1465 gt4 = VppIpTable(self, 1)
1466 gt4.add_vpp_config()
1467 gt6 = VppIpTable(self, 1, is_ip6=True)
1468 gt6.add_vpp_config()
1470 rd1 = VppGbpRouteDomain(self, 1, gt4, gt6)
1471 rd1.add_vpp_config()
1474 # Pg2 hosts the vxlan tunnel, hosts on pg2 to act as TEPs
1475 # Pg3 hosts the IP4 UU-flood VXLAN tunnel
1476 # Pg4 hosts the IP6 UU-flood VXLAN tunnel
1478 self.pg2.config_ip4()
1479 self.pg2.resolve_arp()
1480 self.pg2.generate_remote_hosts(4)
1481 self.pg2.configure_ipv4_neighbors()
1482 self.pg3.config_ip4()
1483 self.pg3.resolve_arp()
1484 self.pg4.config_ip4()
1485 self.pg4.resolve_arp()
1488 # Add a mcast destination VXLAN-GBP tunnel for B&M traffic
1490 tun_bm = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
1493 tun_bm.add_vpp_config()
1496 # a GBP bridge domain with a BVI and a UU-flood interface
1498 bd1 = VppBridgeDomain(self, 1)
1499 bd1.add_vpp_config()
1500 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0, self.pg3, tun_bm)
1501 gbd1.add_vpp_config()
1503 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1504 self.logger.info(self.vapi.cli("sh gbp bridge"))
1506 # ... and has a /32 applied
1507 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
1508 ip_addr.add_vpp_config()
1511 # The Endpoint-group in which we are learning endpoints
1513 epg_220 = VppGbpEndpointGroup(self, 220, 112, rd1, gbd1,
1517 VppGbpEndpointRetention(2))
1518 epg_220.add_vpp_config()
1519 epg_330 = VppGbpEndpointGroup(self, 330, 113, rd1, gbd1,
1523 VppGbpEndpointRetention(2))
1524 epg_330.add_vpp_config()
1527 # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
1530 vx_tun_l2_1 = VppGbpVxlanTunnel(
1531 self, 99, bd1.bd_id,
1532 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L2,
1534 vx_tun_l2_1.add_vpp_config()
1537 # A static endpoint that the learnt endpoints are trying to
1540 ep = VppGbpEndpoint(self, self.pg0,
1542 "10.0.0.127", "11.0.0.127",
1543 "2001:10::1", "3001::1")
1546 self.assertTrue(find_route(self, ep.ip4.address, 32, table_id=1))
1548 # a packet with an sclass from an unknwon EPG
1549 p = (Ether(src=self.pg2.remote_mac,
1550 dst=self.pg2.local_mac) /
1551 IP(src=self.pg2.remote_hosts[0].ip4,
1552 dst=self.pg2.local_ip4) /
1553 UDP(sport=1234, dport=48879) /
1554 VXLAN(vni=99, gpid=88, flags=0x88) /
1555 Ether(src=learnt[0]["mac"], dst=ep.mac) /
1556 IP(src=learnt[0]["ip"], dst=ep.ip4.address) /
1557 UDP(sport=1234, dport=1234) /
1560 self.send_and_assert_no_replies(self.pg2, p)
1563 # we should not have learnt a new tunnel endpoint, since
1564 # the EPG was not learnt.
1566 self.assertEqual(INDEX_INVALID,
1567 find_vxlan_gbp_tunnel(self,
1569 self.pg2.remote_hosts[0].ip4,
1572 # epg is not learnt, becasue the EPG is unknwon
1573 self.assertEqual(len(self.vapi.gbp_endpoint_dump()), 1)
1576 # Learn new EPs from IP packets
1578 for ii, l in enumerate(learnt):
1579 # a packet with an sclass from a knwon EPG
1580 # arriving on an unknown TEP
1581 p = (Ether(src=self.pg2.remote_mac,
1582 dst=self.pg2.local_mac) /
1583 IP(src=self.pg2.remote_hosts[1].ip4,
1584 dst=self.pg2.local_ip4) /
1585 UDP(sport=1234, dport=48879) /
1586 VXLAN(vni=99, gpid=112, flags=0x88) /
1587 Ether(src=l['mac'], dst=ep.mac) /
1588 IP(src=l['ip'], dst=ep.ip4.address) /
1589 UDP(sport=1234, dport=1234) /
1592 rx = self.send_and_expect(self.pg2, [p], self.pg0)
1595 tep1_sw_if_index = find_vxlan_gbp_tunnel(
1598 self.pg2.remote_hosts[1].ip4,
1600 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
1603 # the EP is learnt via the learnt TEP
1604 # both from its MAC and its IP
1606 self.assertTrue(find_gbp_endpoint(self,
1607 vx_tun_l2_1.sw_if_index,
1609 self.assertTrue(find_gbp_endpoint(self,
1610 vx_tun_l2_1.sw_if_index,
1613 self.logger.info(self.vapi.cli("show gbp endpoint"))
1614 self.logger.info(self.vapi.cli("show gbp vxlan"))
1615 self.logger.info(self.vapi.cli("show ip mfib"))
1618 # If we sleep for the threshold time, the learnt endpoints should
1622 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1626 # Learn new EPs from GARP packets received on the BD's mcast tunnel
1628 for ii, l in enumerate(learnt):
1629 # a packet with an sclass from a knwon EPG
1630 # arriving on an unknown TEP
1631 p = (Ether(src=self.pg2.remote_mac,
1632 dst=self.pg2.local_mac) /
1633 IP(src=self.pg2.remote_hosts[1].ip4,
1635 UDP(sport=1234, dport=48879) /
1636 VXLAN(vni=88, gpid=112, flags=0x88) /
1637 Ether(src=l['mac'], dst="ff:ff:ff:ff:ff:ff") /
1639 psrc=l['ip'], pdst=l['ip'],
1640 hwsrc=l['mac'], hwdst="ff:ff:ff:ff:ff:ff"))
1642 rx = self.send_and_expect(self.pg4, [p], self.pg0)
1645 tep1_sw_if_index = find_vxlan_gbp_tunnel(
1648 self.pg2.remote_hosts[1].ip4,
1650 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
1653 # the EP is learnt via the learnt TEP
1654 # both from its MAC and its IP
1656 self.assertTrue(find_gbp_endpoint(self,
1657 vx_tun_l2_1.sw_if_index,
1659 self.assertTrue(find_gbp_endpoint(self,
1660 vx_tun_l2_1.sw_if_index,
1664 # wait for the learnt endpoints to age out
1667 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1671 # Learn new EPs from L2 packets
1673 for ii, l in enumerate(learnt):
1674 # a packet with an sclass from a knwon EPG
1675 # arriving on an unknown TEP
1676 p = (Ether(src=self.pg2.remote_mac,
1677 dst=self.pg2.local_mac) /
1678 IP(src=self.pg2.remote_hosts[1].ip4,
1679 dst=self.pg2.local_ip4) /
1680 UDP(sport=1234, dport=48879) /
1681 VXLAN(vni=99, gpid=112, flags=0x88) /
1682 Ether(src=l['mac'], dst=ep.mac) /
1685 rx = self.send_and_expect(self.pg2, [p], self.pg0)
1688 tep1_sw_if_index = find_vxlan_gbp_tunnel(
1691 self.pg2.remote_hosts[1].ip4,
1693 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
1696 # the EP is learnt via the learnt TEP
1697 # both from its MAC and its IP
1699 self.assertTrue(find_gbp_endpoint(self,
1700 vx_tun_l2_1.sw_if_index,
1703 self.logger.info(self.vapi.cli("show gbp endpoint"))
1704 self.logger.info(self.vapi.cli("show gbp vxlan"))
1705 self.logger.info(self.vapi.cli("show vxlan-gbp tunnel"))
1708 # wait for the learnt endpoints to age out
1711 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1715 # repeat. the do not learn bit is set so the EPs are not learnt
1718 # a packet with an sclass from a knwon EPG
1719 p = (Ether(src=self.pg2.remote_mac,
1720 dst=self.pg2.local_mac) /
1721 IP(src=self.pg2.remote_hosts[1].ip4,
1722 dst=self.pg2.local_ip4) /
1723 UDP(sport=1234, dport=48879) /
1724 VXLAN(vni=99, gpid=112, flags=0x88, gpflags="D") /
1725 Ether(src=l['mac'], dst=ep.mac) /
1726 IP(src=l['ip'], dst=ep.ip4.address) /
1727 UDP(sport=1234, dport=1234) /
1730 rx = self.send_and_expect(self.pg2, p*65, self.pg0)
1733 self.assertFalse(find_gbp_endpoint(self,
1734 vx_tun_l2_1.sw_if_index,
1741 # a packet with an sclass from a knwon EPG
1742 p = (Ether(src=self.pg2.remote_mac,
1743 dst=self.pg2.local_mac) /
1744 IP(src=self.pg2.remote_hosts[1].ip4,
1745 dst=self.pg2.local_ip4) /
1746 UDP(sport=1234, dport=48879) /
1747 VXLAN(vni=99, gpid=112, flags=0x88) /
1748 Ether(src=l['mac'], dst=ep.mac) /
1749 IP(src=l['ip'], dst=ep.ip4.address) /
1750 UDP(sport=1234, dport=1234) /
1753 rx = self.send_and_expect(self.pg2, p*65, self.pg0)
1755 self.assertTrue(find_gbp_endpoint(self,
1756 vx_tun_l2_1.sw_if_index,
1760 # Static EP replies to dynamics
1762 self.logger.info(self.vapi.cli("sh l2fib bd_id 1"))
1764 p = (Ether(src=ep.mac, dst=l['mac']) /
1765 IP(dst=l['ip'], src=ep.ip4.address) /
1766 UDP(sport=1234, dport=1234) /
1769 rxs = self.send_and_expect(self.pg0, p * 17, self.pg2)
1772 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
1773 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
1774 self.assertEqual(rx[UDP].dport, 48879)
1775 # the UDP source port is a random value for hashing
1776 self.assertEqual(rx[VXLAN].gpid, 112)
1777 self.assertEqual(rx[VXLAN].vni, 99)
1778 self.assertTrue(rx[VXLAN].flags.G)
1779 self.assertTrue(rx[VXLAN].flags.Instance)
1780 self.assertTrue(rx[VXLAN].gpflags.A)
1781 self.assertFalse(rx[VXLAN].gpflags.D)
1784 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1788 # repeat in the other EPG
1789 # there's no contract between 220 and 330, but the A-bit is set
1790 # so the packet is cleared for delivery
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=113, flags=0x88, gpflags='A') /
1800 Ether(src=l['mac'], dst=ep.mac) /
1801 IP(src=l['ip'], dst=ep.ip4.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 # static EP cannot reach the learnt EPs since there is no contract
1813 # only test 1 EP as the others could timeout
1815 p = (Ether(src=ep.mac, dst=l['mac']) /
1816 IP(dst=learnt[0]['ip'], src=ep.ip4.address) /
1817 UDP(sport=1234, dport=1234) /
1820 self.send_and_assert_no_replies(self.pg0, [p])
1823 # refresh the entries after the check for no replies above
1826 # a packet with an sclass from a knwon EPG
1827 p = (Ether(src=self.pg2.remote_mac,
1828 dst=self.pg2.local_mac) /
1829 IP(src=self.pg2.remote_hosts[1].ip4,
1830 dst=self.pg2.local_ip4) /
1831 UDP(sport=1234, dport=48879) /
1832 VXLAN(vni=99, gpid=113, flags=0x88, gpflags='A') /
1833 Ether(src=l['mac'], dst=ep.mac) /
1834 IP(src=l['ip'], dst=ep.ip4.address) /
1835 UDP(sport=1234, dport=1234) /
1838 rx = self.send_and_expect(self.pg2, p*65, self.pg0)
1840 self.assertTrue(find_gbp_endpoint(self,
1841 vx_tun_l2_1.sw_if_index,
1845 # Add the contract so they can talk
1847 acl = VppGbpAcl(self)
1848 rule = acl.create_rule(permit_deny=1, proto=17)
1849 rule2 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
1850 acl_index = acl.add_vpp_config([rule, rule2])
1851 c1 = VppGbpContract(
1852 self, epg_220, epg_330, acl_index,
1853 [VppGbpContractRule(
1854 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1857 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1859 [ETH_P_IP, ETH_P_IPV6])
1863 p = (Ether(src=ep.mac, dst=l['mac']) /
1864 IP(dst=l['ip'], src=ep.ip4.address) /
1865 UDP(sport=1234, dport=1234) /
1868 self.send_and_expect(self.pg0, [p], self.pg2)
1871 # send UU packets from the local EP
1873 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1874 self.logger.info(self.vapi.cli("sh gbp bridge"))
1875 p_uu = (Ether(src=ep.mac, dst="00:11:11:11:11:11") /
1876 IP(dst="10.0.0.133", src=ep.ip4.address) /
1877 UDP(sport=1234, dport=1234) /
1879 rxs = self.send_and_expect(ep.itf, [p_uu], gbd1.uu_fwd)
1881 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1883 p_bm = (Ether(src=ep.mac, dst="ff:ff:ff:ff:ff:ff") /
1884 IP(dst="10.0.0.133", src=ep.ip4.address) /
1885 UDP(sport=1234, dport=1234) /
1887 rxs = self.send_and_expect_only(ep.itf, [p_bm], tun_bm.mcast_itf)
1890 self.assertEqual(rx[IP].src, self.pg4.local_ip4)
1891 self.assertEqual(rx[IP].dst, "239.1.1.1")
1892 self.assertEqual(rx[UDP].dport, 48879)
1893 # the UDP source port is a random value for hashing
1894 self.assertEqual(rx[VXLAN].gpid, 112)
1895 self.assertEqual(rx[VXLAN].vni, 88)
1896 self.assertTrue(rx[VXLAN].flags.G)
1897 self.assertTrue(rx[VXLAN].flags.Instance)
1898 self.assertFalse(rx[VXLAN].gpflags.A)
1899 self.assertFalse(rx[VXLAN].gpflags.D)
1902 # Check v6 Endpoints
1905 # a packet with an sclass from a knwon EPG
1906 p = (Ether(src=self.pg2.remote_mac,
1907 dst=self.pg2.local_mac) /
1908 IP(src=self.pg2.remote_hosts[1].ip4,
1909 dst=self.pg2.local_ip4) /
1910 UDP(sport=1234, dport=48879) /
1911 VXLAN(vni=99, gpid=113, flags=0x88, gpflags='A') /
1912 Ether(src=l['mac'], dst=ep.mac) /
1913 IPv6(src=l['ip6'], dst=ep.ip6.address) /
1914 UDP(sport=1234, dport=1234) /
1917 rx = self.send_and_expect(self.pg2, p*65, self.pg0)
1919 self.assertTrue(find_gbp_endpoint(self,
1920 vx_tun_l2_1.sw_if_index,
1924 # L3 Endpoint Learning
1925 # - configured on the bridge's BVI
1932 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1935 self.pg2.unconfig_ip4()
1936 self.pg3.unconfig_ip4()
1937 self.pg4.unconfig_ip4()
1939 self.logger.info(self.vapi.cli("sh int"))
1940 self.logger.info(self.vapi.cli("sh gbp vxlan"))
1942 def test_gbp_learn_vlan_l2(self):
1943 """ GBP L2 Endpoint w/ VLANs"""
1945 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
1946 learnt = [{'mac': '00:00:11:11:11:01',
1948 'ip6': '2001:10::2'},
1949 {'mac': '00:00:11:11:11:02',
1951 'ip6': '2001:10::3'}]
1956 gt4 = VppIpTable(self, 1)
1957 gt4.add_vpp_config()
1958 gt6 = VppIpTable(self, 1, is_ip6=True)
1959 gt6.add_vpp_config()
1961 rd1 = VppGbpRouteDomain(self, 1, gt4, gt6)
1962 rd1.add_vpp_config()
1965 # Pg2 hosts the vxlan tunnel, hosts on pg2 to act as TEPs
1967 self.pg2.config_ip4()
1968 self.pg2.resolve_arp()
1969 self.pg2.generate_remote_hosts(4)
1970 self.pg2.configure_ipv4_neighbors()
1971 self.pg3.config_ip4()
1972 self.pg3.resolve_arp()
1975 # The EP will be on a vlan sub-interface
1977 vlan_11 = VppDot1QSubint(self, self.pg0, 11)
1979 self.vapi.l2_interface_vlan_tag_rewrite(
1980 sw_if_index=vlan_11.sw_if_index, vtr_op=L2_VTR_OP.L2_POP_1,
1983 bd_uu_fwd = VppVxlanGbpTunnel(self, self.pg3.local_ip4,
1984 self.pg3.remote_ip4, 116)
1985 bd_uu_fwd.add_vpp_config()
1988 # a GBP bridge domain with a BVI and a UU-flood interface
1989 # The BD is marked as do not learn, so no endpoints are ever
1990 # learnt in this BD.
1992 bd1 = VppBridgeDomain(self, 1)
1993 bd1.add_vpp_config()
1994 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0, bd_uu_fwd,
1996 gbd1.add_vpp_config()
1998 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1999 self.logger.info(self.vapi.cli("sh gbp bridge"))
2001 # ... and has a /32 applied
2002 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2003 ip_addr.add_vpp_config()
2006 # The Endpoint-group in which we are learning endpoints
2008 epg_220 = VppGbpEndpointGroup(self, 220, 441, rd1, gbd1,
2012 VppGbpEndpointRetention(2))
2013 epg_220.add_vpp_config()
2016 # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
2019 vx_tun_l2_1 = VppGbpVxlanTunnel(
2020 self, 99, bd1.bd_id,
2021 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L2,
2023 vx_tun_l2_1.add_vpp_config()
2026 # A static endpoint that the learnt endpoints are trying to
2029 ep = VppGbpEndpoint(self, vlan_11,
2031 "10.0.0.127", "11.0.0.127",
2032 "2001:10::1", "3001::1")
2035 self.assertTrue(find_route(self, ep.ip4.address, 32, table_id=1))
2038 # Send to the static EP
2040 for ii, l in enumerate(learnt):
2041 # a packet with an sclass from a knwon EPG
2042 # arriving on an unknown TEP
2043 p = (Ether(src=self.pg2.remote_mac,
2044 dst=self.pg2.local_mac) /
2045 IP(src=self.pg2.remote_hosts[1].ip4,
2046 dst=self.pg2.local_ip4) /
2047 UDP(sport=1234, dport=48879) /
2048 VXLAN(vni=99, gpid=441, flags=0x88) /
2049 Ether(src=l['mac'], dst=ep.mac) /
2050 IP(src=l['ip'], dst=ep.ip4.address) /
2051 UDP(sport=1234, dport=1234) /
2054 rxs = self.send_and_expect(self.pg2, [p], self.pg0)
2057 # packet to EP has the EP's vlan tag
2060 self.assertEqual(rx[Dot1Q].vlan, 11)
2063 # the EP is not learnt since the BD setting prevents it
2066 self.assertFalse(find_gbp_endpoint(self,
2067 vx_tun_l2_1.sw_if_index,
2069 self.assertEqual(INDEX_INVALID,
2070 find_vxlan_gbp_tunnel(
2073 self.pg2.remote_hosts[1].ip4,
2076 self.assertEqual(len(self.vapi.gbp_endpoint_dump()), 1)
2080 # we didn't learn the remotes so they are sent to the UU-fwd
2083 p = (Ether(src=ep.mac, dst=l['mac']) /
2085 IP(dst=l['ip'], src=ep.ip4.address) /
2086 UDP(sport=1234, dport=1234) /
2089 rxs = self.send_and_expect(self.pg0, p * 17, self.pg3)
2092 self.assertEqual(rx[IP].src, self.pg3.local_ip4)
2093 self.assertEqual(rx[IP].dst, self.pg3.remote_ip4)
2094 self.assertEqual(rx[UDP].dport, 48879)
2095 # the UDP source port is a random value for hashing
2096 self.assertEqual(rx[VXLAN].gpid, 441)
2097 self.assertEqual(rx[VXLAN].vni, 116)
2098 self.assertTrue(rx[VXLAN].flags.G)
2099 self.assertTrue(rx[VXLAN].flags.Instance)
2100 self.assertFalse(rx[VXLAN].gpflags.A)
2101 self.assertFalse(rx[VXLAN].gpflags.D)
2103 self.pg2.unconfig_ip4()
2104 self.pg3.unconfig_ip4()
2106 def test_gbp_learn_l3(self):
2107 """ GBP L3 Endpoint Learning """
2109 self.vapi.cli("set logging class gbp debug")
2111 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
2112 routed_dst_mac = "00:0c:0c:0c:0c:0c"
2113 routed_src_mac = "00:22:bd:f8:19:ff"
2115 learnt = [{'mac': '00:00:11:11:11:02',
2117 'ip6': '2001:10::2'},
2118 {'mac': '00:00:11:11:11:03',
2120 'ip6': '2001:10::3'}]
2125 t4 = VppIpTable(self, 1)
2127 t6 = VppIpTable(self, 1, True)
2130 tun_ip4_uu = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
2131 self.pg4.remote_ip4, 114)
2132 tun_ip6_uu = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
2133 self.pg4.remote_ip4, 116)
2134 tun_ip4_uu.add_vpp_config()
2135 tun_ip6_uu.add_vpp_config()
2137 rd1 = VppGbpRouteDomain(self, 2, t4, t6, tun_ip4_uu, tun_ip6_uu)
2138 rd1.add_vpp_config()
2140 self.loop0.set_mac(self.router_mac)
2143 # Bind the BVI to the RD
2145 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
2146 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
2149 # Pg2 hosts the vxlan tunnel
2150 # hosts on pg2 to act as TEPs
2154 self.pg2.config_ip4()
2155 self.pg2.resolve_arp()
2156 self.pg2.generate_remote_hosts(4)
2157 self.pg2.configure_ipv4_neighbors()
2158 self.pg3.config_ip4()
2159 self.pg3.resolve_arp()
2160 self.pg4.config_ip4()
2161 self.pg4.resolve_arp()
2164 # a GBP bridge domain with a BVI and a UU-flood interface
2166 bd1 = VppBridgeDomain(self, 1)
2167 bd1.add_vpp_config()
2168 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0, self.pg3)
2169 gbd1.add_vpp_config()
2171 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2172 self.logger.info(self.vapi.cli("sh gbp bridge"))
2173 self.logger.info(self.vapi.cli("sh gbp route"))
2175 # ... and has a /32 and /128 applied
2176 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2177 ip4_addr.add_vpp_config()
2178 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 128)
2179 ip6_addr.add_vpp_config()
2182 # The Endpoint-group in which we are learning endpoints
2184 epg_220 = VppGbpEndpointGroup(self, 220, 441, rd1, gbd1,
2188 VppGbpEndpointRetention(2))
2189 epg_220.add_vpp_config()
2192 # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
2195 vx_tun_l3 = VppGbpVxlanTunnel(
2196 self, 101, rd1.rd_id,
2197 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
2199 vx_tun_l3.add_vpp_config()
2202 # A static endpoint that the learnt endpoints are trying to
2205 ep = VppGbpEndpoint(self, self.pg0,
2207 "10.0.0.127", "11.0.0.127",
2208 "2001:10::1", "3001::1")
2212 # learn some remote IPv4 EPs
2214 for ii, l in enumerate(learnt):
2215 # a packet with an sclass from a knwon EPG
2216 # arriving on an unknown TEP
2217 p = (Ether(src=self.pg2.remote_mac,
2218 dst=self.pg2.local_mac) /
2219 IP(src=self.pg2.remote_hosts[1].ip4,
2220 dst=self.pg2.local_ip4) /
2221 UDP(sport=1234, dport=48879) /
2222 VXLAN(vni=101, gpid=441, flags=0x88) /
2223 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2224 IP(src=l['ip'], dst=ep.ip4.address) /
2225 UDP(sport=1234, dport=1234) /
2228 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2231 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2234 self.pg2.remote_hosts[1].ip4,
2236 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2238 # endpoint learnt via the parent GBP-vxlan interface
2239 self.assertTrue(find_gbp_endpoint(self,
2240 vx_tun_l3._sw_if_index,
2244 # Static IPv4 EP replies to learnt
2247 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2248 IP(dst=l['ip'], src=ep.ip4.address) /
2249 UDP(sport=1234, dport=1234) /
2252 rxs = self.send_and_expect(self.pg0, p*1, self.pg2)
2255 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2256 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2257 self.assertEqual(rx[UDP].dport, 48879)
2258 # the UDP source port is a random value for hashing
2259 self.assertEqual(rx[VXLAN].gpid, 441)
2260 self.assertEqual(rx[VXLAN].vni, 101)
2261 self.assertTrue(rx[VXLAN].flags.G)
2262 self.assertTrue(rx[VXLAN].flags.Instance)
2263 self.assertTrue(rx[VXLAN].gpflags.A)
2264 self.assertFalse(rx[VXLAN].gpflags.D)
2266 inner = rx[VXLAN].payload
2268 self.assertEqual(inner[Ether].src, routed_src_mac)
2269 self.assertEqual(inner[Ether].dst, routed_dst_mac)
2270 self.assertEqual(inner[IP].src, ep.ip4.address)
2271 self.assertEqual(inner[IP].dst, l['ip'])
2274 self.assertFalse(find_gbp_endpoint(self,
2279 # learn some remote IPv6 EPs
2281 for ii, l in enumerate(learnt):
2282 # a packet with an sclass from a knwon EPG
2283 # arriving on an unknown TEP
2284 p = (Ether(src=self.pg2.remote_mac,
2285 dst=self.pg2.local_mac) /
2286 IP(src=self.pg2.remote_hosts[1].ip4,
2287 dst=self.pg2.local_ip4) /
2288 UDP(sport=1234, dport=48879) /
2289 VXLAN(vni=101, gpid=441, flags=0x88) /
2290 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2291 IPv6(src=l['ip6'], dst=ep.ip6.address) /
2292 UDP(sport=1234, dport=1234) /
2295 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2298 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2301 self.pg2.remote_hosts[1].ip4,
2303 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2305 self.logger.info(self.vapi.cli("show gbp bridge"))
2306 self.logger.info(self.vapi.cli("show vxlan-gbp tunnel"))
2307 self.logger.info(self.vapi.cli("show gbp vxlan"))
2308 self.logger.info(self.vapi.cli("show int addr"))
2310 # endpoint learnt via the TEP
2311 self.assertTrue(find_gbp_endpoint(self, ip=l['ip6']))
2313 self.logger.info(self.vapi.cli("show gbp endpoint"))
2314 self.logger.info(self.vapi.cli("show ip fib index 1 %s" % l['ip']))
2317 # Static EP replies to learnt
2320 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2321 IPv6(dst=l['ip6'], src=ep.ip6.address) /
2322 UDP(sport=1234, dport=1234) /
2325 rxs = self.send_and_expect(self.pg0, p*65, self.pg2)
2328 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2329 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2330 self.assertEqual(rx[UDP].dport, 48879)
2331 # the UDP source port is a random value for hashing
2332 self.assertEqual(rx[VXLAN].gpid, 441)
2333 self.assertEqual(rx[VXLAN].vni, 101)
2334 self.assertTrue(rx[VXLAN].flags.G)
2335 self.assertTrue(rx[VXLAN].flags.Instance)
2336 self.assertTrue(rx[VXLAN].gpflags.A)
2337 self.assertFalse(rx[VXLAN].gpflags.D)
2339 inner = rx[VXLAN].payload
2341 self.assertEqual(inner[Ether].src, routed_src_mac)
2342 self.assertEqual(inner[Ether].dst, routed_dst_mac)
2343 self.assertEqual(inner[IPv6].src, ep.ip6.address)
2344 self.assertEqual(inner[IPv6].dst, l['ip6'])
2346 self.logger.info(self.vapi.cli("sh gbp endpoint"))
2348 self.wait_for_ep_timeout(ip=l['ip'])
2351 # Static sends to unknown EP with no route
2353 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2354 IP(dst="10.0.0.99", src=ep.ip4.address) /
2355 UDP(sport=1234, dport=1234) /
2358 self.send_and_assert_no_replies(self.pg0, [p])
2361 # Add a route to static EP's v4 and v6 subnet
2362 # packets should be sent on the v4/v6 uu=fwd interface resp.
2364 se_10_24 = VppGbpSubnet(
2365 self, rd1, "10.0.0.0", 24,
2366 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT)
2367 se_10_24.add_vpp_config()
2369 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2370 IP(dst="10.0.0.99", src=ep.ip4.address) /
2371 UDP(sport=1234, dport=1234) /
2374 rxs = self.send_and_expect(self.pg0, [p], self.pg4)
2376 self.assertEqual(rx[IP].src, self.pg4.local_ip4)
2377 self.assertEqual(rx[IP].dst, self.pg4.remote_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, 441)
2381 self.assertEqual(rx[VXLAN].vni, 114)
2382 self.assertTrue(rx[VXLAN].flags.G)
2383 self.assertTrue(rx[VXLAN].flags.Instance)
2384 # policy is not applied to packets sent to the uu-fwd interfaces
2385 self.assertFalse(rx[VXLAN].gpflags.A)
2386 self.assertFalse(rx[VXLAN].gpflags.D)
2389 # learn some remote IPv4 EPs
2391 for ii, l in enumerate(learnt):
2392 # a packet with an sclass from a knwon EPG
2393 # arriving on an unknown TEP
2394 p = (Ether(src=self.pg2.remote_mac,
2395 dst=self.pg2.local_mac) /
2396 IP(src=self.pg2.remote_hosts[2].ip4,
2397 dst=self.pg2.local_ip4) /
2398 UDP(sport=1234, dport=48879) /
2399 VXLAN(vni=101, gpid=441, flags=0x88) /
2400 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2401 IP(src=l['ip'], dst=ep.ip4.address) /
2402 UDP(sport=1234, dport=1234) /
2405 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2408 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2411 self.pg2.remote_hosts[2].ip4,
2413 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2415 # endpoint learnt via the parent GBP-vxlan interface
2416 self.assertTrue(find_gbp_endpoint(self,
2417 vx_tun_l3._sw_if_index,
2421 # Add a remote endpoint from the API
2423 rep_88 = VppGbpEndpoint(self, vx_tun_l3,
2425 "10.0.0.88", "11.0.0.88",
2426 "2001:10::88", "3001::88",
2427 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
2429 self.pg2.remote_hosts[1].ip4,
2431 rep_88.add_vpp_config()
2434 # Add a remote endpoint from the API that matches an existing one
2436 rep_2 = VppGbpEndpoint(self, vx_tun_l3,
2438 learnt[0]['ip'], "11.0.0.101",
2439 learnt[0]['ip6'], "3001::101",
2440 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
2442 self.pg2.remote_hosts[1].ip4,
2444 rep_2.add_vpp_config()
2447 # Add a route to the leanred EP's v4 subnet
2448 # packets should be send on the v4/v6 uu=fwd interface resp.
2450 se_10_1_24 = VppGbpSubnet(
2451 self, rd1, "10.0.1.0", 24,
2452 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT)
2453 se_10_1_24.add_vpp_config()
2455 self.logger.info(self.vapi.cli("show gbp endpoint"))
2457 ips = ["10.0.0.88", learnt[0]['ip']]
2459 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2460 IP(dst=ip, src=ep.ip4.address) /
2461 UDP(sport=1234, dport=1234) /
2464 rxs = self.send_and_expect(self.pg0, p*65, self.pg2)
2467 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2468 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2469 self.assertEqual(rx[UDP].dport, 48879)
2470 # the UDP source port is a random value for hashing
2471 self.assertEqual(rx[VXLAN].gpid, 441)
2472 self.assertEqual(rx[VXLAN].vni, 101)
2473 self.assertTrue(rx[VXLAN].flags.G)
2474 self.assertTrue(rx[VXLAN].flags.Instance)
2475 self.assertTrue(rx[VXLAN].gpflags.A)
2476 self.assertFalse(rx[VXLAN].gpflags.D)
2478 inner = rx[VXLAN].payload
2480 self.assertEqual(inner[Ether].src, routed_src_mac)
2481 self.assertEqual(inner[Ether].dst, routed_dst_mac)
2482 self.assertEqual(inner[IP].src, ep.ip4.address)
2483 self.assertEqual(inner[IP].dst, ip)
2486 # remove the API remote EPs, only API sourced is gone, the DP
2487 # learnt one remains
2489 rep_88.remove_vpp_config()
2490 rep_2.remove_vpp_config()
2492 self.assertTrue(find_gbp_endpoint(self, ip=rep_2.ip4.address))
2494 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2495 IP(src=ep.ip4.address, dst=rep_2.ip4.address) /
2496 UDP(sport=1234, dport=1234) /
2498 rxs = self.send_and_expect(self.pg0, [p], self.pg2)
2500 self.assertFalse(find_gbp_endpoint(self, ip=rep_88.ip4.address))
2502 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2503 IP(src=ep.ip4.address, dst=rep_88.ip4.address) /
2504 UDP(sport=1234, dport=1234) /
2506 rxs = self.send_and_expect(self.pg0, [p], self.pg4)
2509 # to appease the testcase we cannot have the registered EP stll
2510 # present (because it's DP learnt) when the TC ends so wait until
2513 self.wait_for_ep_timeout(ip=rep_88.ip4.address)
2514 self.wait_for_ep_timeout(ip=rep_2.ip4.address)
2517 # shutdown with learnt endpoint present
2519 p = (Ether(src=self.pg2.remote_mac,
2520 dst=self.pg2.local_mac) /
2521 IP(src=self.pg2.remote_hosts[1].ip4,
2522 dst=self.pg2.local_ip4) /
2523 UDP(sport=1234, dport=48879) /
2524 VXLAN(vni=101, gpid=441, flags=0x88) /
2525 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2526 IP(src=learnt[1]['ip'], dst=ep.ip4.address) /
2527 UDP(sport=1234, dport=1234) /
2530 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2532 # endpoint learnt via the parent GBP-vxlan interface
2533 self.assertTrue(find_gbp_endpoint(self,
2534 vx_tun_l3._sw_if_index,
2539 # remote endpoint becomes local
2541 self.pg2.unconfig_ip4()
2542 self.pg3.unconfig_ip4()
2543 self.pg4.unconfig_ip4()
2545 def test_gbp_redirect(self):
2546 """ GBP Endpoint Redirect """
2548 self.vapi.cli("set logging class gbp debug")
2550 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
2551 routed_dst_mac = "00:0c:0c:0c:0c:0c"
2552 routed_src_mac = "00:22:bd:f8:19:ff"
2554 learnt = [{'mac': '00:00:11:11:11:02',
2556 'ip6': '2001:10::2'},
2557 {'mac': '00:00:11:11:11:03',
2559 'ip6': '2001:10::3'}]
2564 t4 = VppIpTable(self, 1)
2566 t6 = VppIpTable(self, 1, True)
2569 rd1 = VppGbpRouteDomain(self, 2, t4, t6)
2570 rd1.add_vpp_config()
2572 self.loop0.set_mac(self.router_mac)
2575 # Bind the BVI to the RD
2577 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
2578 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
2581 # Pg7 hosts a BD's UU-fwd
2583 self.pg7.config_ip4()
2584 self.pg7.resolve_arp()
2587 # a GBP bridge domains for the EPs
2589 bd1 = VppBridgeDomain(self, 1)
2590 bd1.add_vpp_config()
2591 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0)
2592 gbd1.add_vpp_config()
2594 bd2 = VppBridgeDomain(self, 2)
2595 bd2.add_vpp_config()
2596 gbd2 = VppGbpBridgeDomain(self, bd2, self.loop1)
2597 gbd2.add_vpp_config()
2599 # ... and has a /32 and /128 applied
2600 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2601 ip4_addr.add_vpp_config()
2602 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 128)
2603 ip6_addr.add_vpp_config()
2604 ip4_addr = VppIpInterfaceAddress(self, gbd2.bvi, "10.0.1.128", 32)
2605 ip4_addr.add_vpp_config()
2606 ip6_addr = VppIpInterfaceAddress(self, gbd2.bvi, "2001:11::128", 128)
2607 ip6_addr.add_vpp_config()
2610 # The Endpoint-groups in which we are learning endpoints
2612 epg_220 = VppGbpEndpointGroup(self, 220, 440, rd1, gbd1,
2616 VppGbpEndpointRetention(2))
2617 epg_220.add_vpp_config()
2618 epg_221 = VppGbpEndpointGroup(self, 221, 441, rd1, gbd2,
2622 VppGbpEndpointRetention(2))
2623 epg_221.add_vpp_config()
2624 epg_222 = VppGbpEndpointGroup(self, 222, 442, rd1, gbd1,
2628 VppGbpEndpointRetention(2))
2629 epg_222.add_vpp_config()
2632 # a GBP bridge domains for the SEPs
2634 bd_uu1 = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
2635 self.pg7.remote_ip4, 116)
2636 bd_uu1.add_vpp_config()
2637 bd_uu2 = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
2638 self.pg7.remote_ip4, 117)
2639 bd_uu2.add_vpp_config()
2641 bd3 = VppBridgeDomain(self, 3)
2642 bd3.add_vpp_config()
2643 gbd3 = VppGbpBridgeDomain(self, bd3, self.loop2, bd_uu1, learn=False)
2644 gbd3.add_vpp_config()
2645 bd4 = VppBridgeDomain(self, 4)
2646 bd4.add_vpp_config()
2647 gbd4 = VppGbpBridgeDomain(self, bd4, self.loop3, bd_uu2, learn=False)
2648 gbd4.add_vpp_config()
2651 # EPGs in which the service endpoints exist
2653 epg_320 = VppGbpEndpointGroup(self, 320, 550, rd1, gbd3,
2657 VppGbpEndpointRetention(2))
2658 epg_320.add_vpp_config()
2659 epg_321 = VppGbpEndpointGroup(self, 321, 551, rd1, gbd4,
2663 VppGbpEndpointRetention(2))
2664 epg_321.add_vpp_config()
2667 # three local endpoints
2669 ep1 = VppGbpEndpoint(self, self.pg0,
2671 "10.0.0.1", "11.0.0.1",
2672 "2001:10::1", "3001:10::1")
2673 ep1.add_vpp_config()
2674 ep2 = VppGbpEndpoint(self, self.pg1,
2676 "10.0.1.1", "11.0.1.1",
2677 "2001:11::1", "3001:11::1")
2678 ep2.add_vpp_config()
2679 ep3 = VppGbpEndpoint(self, self.pg2,
2681 "10.0.2.2", "11.0.2.2",
2682 "2001:12::1", "3001:12::1")
2683 ep3.add_vpp_config()
2688 sep1 = VppGbpEndpoint(self, self.pg3,
2690 "12.0.0.1", "13.0.0.1",
2691 "4001:10::1", "5001:10::1")
2692 sep1.add_vpp_config()
2693 sep2 = VppGbpEndpoint(self, self.pg4,
2695 "12.0.0.2", "13.0.0.2",
2696 "4001:10::2", "5001:10::2")
2697 sep2.add_vpp_config()
2698 sep3 = VppGbpEndpoint(self, self.pg5,
2700 "12.0.1.1", "13.0.1.1",
2701 "4001:11::1", "5001:11::1")
2702 sep3.add_vpp_config()
2703 # this EP is not installed immediately
2704 sep4 = VppGbpEndpoint(self, self.pg6,
2706 "12.0.1.2", "13.0.1.2",
2707 "4001:11::2", "5001:11::2")
2710 # an L2 switch packet between local EPs in different EPGs
2711 # different dest ports on each so the are LB hashed differently
2713 p4 = [(Ether(src=ep1.mac, dst=ep3.mac) /
2714 IP(src=ep1.ip4.address, dst=ep3.ip4.address) /
2715 UDP(sport=1234, dport=1234) /
2717 (Ether(src=ep3.mac, dst=ep1.mac) /
2718 IP(src=ep3.ip4.address, dst=ep1.ip4.address) /
2719 UDP(sport=1234, dport=1234) /
2721 p6 = [(Ether(src=ep1.mac, dst=ep3.mac) /
2722 IPv6(src=ep1.ip6.address, dst=ep3.ip6.address) /
2723 UDP(sport=1234, dport=1234) /
2725 (Ether(src=ep3.mac, dst=ep1.mac) /
2726 IPv6(src=ep3.ip6.address, dst=ep1.ip6.address) /
2727 UDP(sport=1234, dport=1230) /
2730 # should be dropped since no contract yet
2731 self.send_and_assert_no_replies(self.pg0, [p4[0]])
2732 self.send_and_assert_no_replies(self.pg0, [p6[0]])
2735 # Add a contract with a rule to load-balance redirect via SEP1 and SEP2
2736 # one of the next-hops is via an EP that is not known
2738 acl = VppGbpAcl(self)
2739 rule4 = acl.create_rule(permit_deny=1, proto=17)
2740 rule6 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
2741 acl_index = acl.add_vpp_config([rule4, rule6])
2744 # test the src-ip hash mode
2746 c1 = VppGbpContract(
2747 self, epg_220, epg_222, acl_index,
2748 [VppGbpContractRule(
2749 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2750 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2751 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
2752 sep1.ip4, sep1.epg.rd),
2753 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
2754 sep2.ip4, sep2.epg.rd)]),
2756 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2757 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2758 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
2759 sep3.ip6, sep3.epg.rd),
2760 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
2761 sep4.ip6, sep4.epg.rd)])],
2762 [ETH_P_IP, ETH_P_IPV6])
2765 c2 = VppGbpContract(
2766 self, epg_222, epg_220, acl_index,
2767 [VppGbpContractRule(
2768 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2769 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2770 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
2771 sep1.ip4, sep1.epg.rd),
2772 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
2773 sep2.ip4, sep2.epg.rd)]),
2775 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2776 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2777 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
2778 sep3.ip6, sep3.epg.rd),
2779 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
2780 sep4.ip6, sep4.epg.rd)])],
2781 [ETH_P_IP, ETH_P_IPV6])
2785 # send again with the contract preset, now packets arrive
2786 # at SEP1 or SEP2 depending on the hashing
2788 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
2791 self.assertEqual(rx[Ether].src, routed_src_mac)
2792 self.assertEqual(rx[Ether].dst, sep1.mac)
2793 self.assertEqual(rx[IP].src, ep1.ip4.address)
2794 self.assertEqual(rx[IP].dst, ep3.ip4.address)
2796 rxs = self.send_and_expect(self.pg2, p4[1] * 17, sep2.itf)
2799 self.assertEqual(rx[Ether].src, routed_src_mac)
2800 self.assertEqual(rx[Ether].dst, sep2.mac)
2801 self.assertEqual(rx[IP].src, ep3.ip4.address)
2802 self.assertEqual(rx[IP].dst, ep1.ip4.address)
2804 rxs = self.send_and_expect(self.pg0, p6[0] * 17, self.pg7)
2807 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
2808 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
2809 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
2810 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
2811 self.assertEqual(rx[VXLAN].vni, 117)
2812 self.assertTrue(rx[VXLAN].flags.G)
2813 self.assertTrue(rx[VXLAN].flags.Instance)
2814 # redirect policy has been applied
2815 self.assertTrue(rx[VXLAN].gpflags.A)
2816 self.assertFalse(rx[VXLAN].gpflags.D)
2818 inner = rx[VXLAN].payload
2820 self.assertEqual(inner[Ether].src, routed_src_mac)
2821 self.assertEqual(inner[Ether].dst, sep4.mac)
2822 self.assertEqual(inner[IPv6].src, ep1.ip6.address)
2823 self.assertEqual(inner[IPv6].dst, ep3.ip6.address)
2825 rxs = self.send_and_expect(self.pg2, p6[1] * 17, sep3.itf)
2828 self.assertEqual(rx[Ether].src, routed_src_mac)
2829 self.assertEqual(rx[Ether].dst, sep3.mac)
2830 self.assertEqual(rx[IPv6].src, ep3.ip6.address)
2831 self.assertEqual(rx[IPv6].dst, ep1.ip6.address)
2834 # programme the unknown EP
2836 sep4.add_vpp_config()
2838 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep4.itf)
2841 self.assertEqual(rx[Ether].src, routed_src_mac)
2842 self.assertEqual(rx[Ether].dst, sep4.mac)
2843 self.assertEqual(rx[IPv6].src, ep1.ip6.address)
2844 self.assertEqual(rx[IPv6].dst, ep3.ip6.address)
2847 # and revert back to unprogrammed
2849 sep4.remove_vpp_config()
2851 rxs = self.send_and_expect(self.pg0, p6[0] * 17, self.pg7)
2854 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
2855 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
2856 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
2857 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
2858 self.assertEqual(rx[VXLAN].vni, 117)
2859 self.assertTrue(rx[VXLAN].flags.G)
2860 self.assertTrue(rx[VXLAN].flags.Instance)
2861 # redirect policy has been applied
2862 self.assertTrue(rx[VXLAN].gpflags.A)
2863 self.assertFalse(rx[VXLAN].gpflags.D)
2865 inner = rx[VXLAN].payload
2867 self.assertEqual(inner[Ether].src, routed_src_mac)
2868 self.assertEqual(inner[Ether].dst, sep4.mac)
2869 self.assertEqual(inner[IPv6].src, ep1.ip6.address)
2870 self.assertEqual(inner[IPv6].dst, ep3.ip6.address)
2872 c1.remove_vpp_config()
2873 c2.remove_vpp_config()
2876 # test the symmetric hash mode
2878 c1 = VppGbpContract(
2879 self, epg_220, epg_222, acl_index,
2880 [VppGbpContractRule(
2881 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2882 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
2883 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
2884 sep1.ip4, sep1.epg.rd),
2885 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
2886 sep2.ip4, sep2.epg.rd)]),
2888 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2889 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
2890 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
2891 sep3.ip6, sep3.epg.rd),
2892 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
2893 sep4.ip6, sep4.epg.rd)])],
2894 [ETH_P_IP, ETH_P_IPV6])
2897 c2 = VppGbpContract(
2898 self, epg_222, epg_220, acl_index,
2899 [VppGbpContractRule(
2900 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2901 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
2902 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
2903 sep1.ip4, sep1.epg.rd),
2904 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
2905 sep2.ip4, sep2.epg.rd)]),
2907 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2908 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
2909 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
2910 sep3.ip6, sep3.epg.rd),
2911 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
2912 sep4.ip6, sep4.epg.rd)])],
2913 [ETH_P_IP, ETH_P_IPV6])
2917 # send again with the contract preset, now packets arrive
2918 # at SEP1 for both directions
2920 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
2923 self.assertEqual(rx[Ether].src, routed_src_mac)
2924 self.assertEqual(rx[Ether].dst, sep1.mac)
2925 self.assertEqual(rx[IP].src, ep1.ip4.address)
2926 self.assertEqual(rx[IP].dst, ep3.ip4.address)
2928 rxs = self.send_and_expect(self.pg2, p4[1] * 17, sep1.itf)
2931 self.assertEqual(rx[Ether].src, routed_src_mac)
2932 self.assertEqual(rx[Ether].dst, sep1.mac)
2933 self.assertEqual(rx[IP].src, ep3.ip4.address)
2934 self.assertEqual(rx[IP].dst, ep1.ip4.address)
2937 # programme the unknown EP for the L3 tests
2939 sep4.add_vpp_config()
2942 # an L3 switch packet between local EPs in different EPGs
2943 # different dest ports on each so the are LB hashed differently
2945 p4 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
2946 IP(src=ep1.ip4.address, dst=ep2.ip4.address) /
2947 UDP(sport=1234, dport=1234) /
2949 (Ether(src=ep2.mac, dst=str(self.router_mac)) /
2950 IP(src=ep2.ip4.address, dst=ep1.ip4.address) /
2951 UDP(sport=1234, dport=1234) /
2953 p6 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
2954 IPv6(src=ep1.ip6.address, dst=ep2.ip6.address) /
2955 UDP(sport=1234, dport=1234) /
2957 (Ether(src=ep2.mac, dst=str(self.router_mac)) /
2958 IPv6(src=ep2.ip6.address, dst=ep1.ip6.address) /
2959 UDP(sport=1234, dport=1234) /
2962 c3 = VppGbpContract(
2963 self, epg_220, epg_221, acl_index,
2964 [VppGbpContractRule(
2965 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2966 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
2967 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
2968 sep1.ip4, sep1.epg.rd),
2969 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
2970 sep2.ip4, sep2.epg.rd)]),
2972 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2973 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
2974 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
2975 sep3.ip6, sep3.epg.rd),
2976 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
2977 sep4.ip6, sep4.epg.rd)])],
2978 [ETH_P_IP, ETH_P_IPV6])
2981 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
2984 self.assertEqual(rx[Ether].src, routed_src_mac)
2985 self.assertEqual(rx[Ether].dst, sep1.mac)
2986 self.assertEqual(rx[IP].src, ep1.ip4.address)
2987 self.assertEqual(rx[IP].dst, ep2.ip4.address)
2990 # learn a remote EP in EPG 221
2992 vx_tun_l3 = VppGbpVxlanTunnel(
2993 self, 444, rd1.rd_id,
2994 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
2996 vx_tun_l3.add_vpp_config()
2998 c4 = VppGbpContract(
2999 self, epg_221, epg_220, acl_index,
3000 [VppGbpContractRule(
3001 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3004 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3006 [ETH_P_IP, ETH_P_IPV6])
3009 p = (Ether(src=self.pg7.remote_mac,
3010 dst=self.pg7.local_mac) /
3011 IP(src=self.pg7.remote_ip4,
3012 dst=self.pg7.local_ip4) /
3013 UDP(sport=1234, dport=48879) /
3014 VXLAN(vni=444, gpid=441, flags=0x88) /
3015 Ether(src="00:22:22:22:22:33", dst=str(self.router_mac)) /
3016 IP(src="10.0.0.88", dst=ep1.ip4.address) /
3017 UDP(sport=1234, dport=1234) /
3020 rx = self.send_and_expect(self.pg7, [p], self.pg0)
3022 # endpoint learnt via the parent GBP-vxlan interface
3023 self.assertTrue(find_gbp_endpoint(self,
3024 vx_tun_l3._sw_if_index,
3027 p = (Ether(src=self.pg7.remote_mac,
3028 dst=self.pg7.local_mac) /
3029 IP(src=self.pg7.remote_ip4,
3030 dst=self.pg7.local_ip4) /
3031 UDP(sport=1234, dport=48879) /
3032 VXLAN(vni=444, gpid=441, flags=0x88) /
3033 Ether(src="00:22:22:22:22:33", dst=str(self.router_mac)) /
3034 IPv6(src="2001:10::88", dst=ep1.ip6.address) /
3035 UDP(sport=1234, dport=1234) /
3038 rx = self.send_and_expect(self.pg7, [p], self.pg0)
3040 # endpoint learnt via the parent GBP-vxlan interface
3041 self.assertTrue(find_gbp_endpoint(self,
3042 vx_tun_l3._sw_if_index,
3046 # L3 switch from local to remote EP
3048 p4 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3049 IP(src=ep1.ip4.address, dst="10.0.0.88") /
3050 UDP(sport=1234, dport=1234) /
3052 p6 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3053 IPv6(src=ep1.ip6.address, dst="2001:10::88") /
3054 UDP(sport=1234, dport=1234) /
3057 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3060 self.assertEqual(rx[Ether].src, routed_src_mac)
3061 self.assertEqual(rx[Ether].dst, sep1.mac)
3062 self.assertEqual(rx[IP].src, ep1.ip4.address)
3063 self.assertEqual(rx[IP].dst, "10.0.0.88")
3065 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep4.itf)
3068 self.assertEqual(rx[Ether].src, routed_src_mac)
3069 self.assertEqual(rx[Ether].dst, sep4.mac)
3070 self.assertEqual(rx[IPv6].src, ep1.ip6.address)
3071 self.assertEqual(rx[IPv6].dst, "2001:10::88")
3074 # test the dst-ip hash mode
3076 c5 = VppGbpContract(
3077 self, epg_220, epg_221, acl_index,
3078 [VppGbpContractRule(
3079 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3080 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
3081 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3082 sep1.ip4, sep1.epg.rd),
3083 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3084 sep2.ip4, sep2.epg.rd)]),
3086 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3087 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
3088 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3089 sep3.ip6, sep3.epg.rd),
3090 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3091 sep4.ip6, sep4.epg.rd)])],
3092 [ETH_P_IP, ETH_P_IPV6])
3095 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3098 self.assertEqual(rx[Ether].src, routed_src_mac)
3099 self.assertEqual(rx[Ether].dst, sep1.mac)
3100 self.assertEqual(rx[IP].src, ep1.ip4.address)
3101 self.assertEqual(rx[IP].dst, "10.0.0.88")
3103 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep3.itf)
3106 self.assertEqual(rx[Ether].src, routed_src_mac)
3107 self.assertEqual(rx[Ether].dst, sep3.mac)
3108 self.assertEqual(rx[IPv6].src, ep1.ip6.address)
3109 self.assertEqual(rx[IPv6].dst, "2001:10::88")
3114 self.pg7.unconfig_ip4()
3116 def test_gbp_l3_out(self):
3119 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
3120 self.vapi.cli("set logging class gbp debug")
3122 routed_dst_mac = "00:0c:0c:0c:0c:0c"
3123 routed_src_mac = "00:22:bd:f8:19:ff"
3128 t4 = VppIpTable(self, 1)
3130 t6 = VppIpTable(self, 1, True)
3133 rd1 = VppGbpRouteDomain(self, 2, t4, t6)
3134 rd1.add_vpp_config()
3136 self.loop0.set_mac(self.router_mac)
3139 # Bind the BVI to the RD
3141 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
3142 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
3145 # Pg7 hosts a BD's BUM
3146 # Pg1 some other l3 interface
3148 self.pg7.config_ip4()
3149 self.pg7.resolve_arp()
3152 # a multicast vxlan-gbp tunnel for broadcast in the BD
3154 tun_bm = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
3157 tun_bm.add_vpp_config()
3160 # a GBP external bridge domains for the EPs
3162 bd1 = VppBridgeDomain(self, 1)
3163 bd1.add_vpp_config()
3164 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0, None, tun_bm)
3165 gbd1.add_vpp_config()
3168 # The Endpoint-groups in which the external endpoints exist
3170 epg_220 = VppGbpEndpointGroup(self, 220, 113, rd1, gbd1,
3174 VppGbpEndpointRetention(2))
3175 epg_220.add_vpp_config()
3177 # the BVIs have the subnets applied ...
3178 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 24)
3179 ip4_addr.add_vpp_config()
3180 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 64)
3181 ip6_addr.add_vpp_config()
3183 # ... which are L3-out subnets
3184 l3o_1 = VppGbpSubnet(
3185 self, rd1, "10.0.0.0", 24,
3186 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3188 l3o_1.add_vpp_config()
3191 # an external interface attached to the outside world and the
3194 vlan_100 = VppDot1QSubint(self, self.pg0, 100)
3196 VppL2Vtr(self, vlan_100, L2_VTR_OP.L2_POP_1).add_vpp_config()
3197 vlan_101 = VppDot1QSubint(self, self.pg0, 101)
3199 VppL2Vtr(self, vlan_101, L2_VTR_OP.L2_POP_1).add_vpp_config()
3201 ext_itf = VppGbpExtItf(self, self.loop0, bd1, rd1)
3202 ext_itf.add_vpp_config()
3205 # an unicast vxlan-gbp for inter-RD traffic
3207 vx_tun_l3 = VppGbpVxlanTunnel(
3208 self, 444, rd1.rd_id,
3209 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
3211 vx_tun_l3.add_vpp_config()
3214 # External Endpoints
3216 eep1 = VppGbpEndpoint(self, vlan_100,
3218 "10.0.0.1", "11.0.0.1",
3219 "2001:10::1", "3001::1",
3220 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
3221 eep1.add_vpp_config()
3222 eep2 = VppGbpEndpoint(self, vlan_101,
3224 "10.0.0.2", "11.0.0.2",
3225 "2001:10::2", "3001::2",
3226 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
3227 eep2.add_vpp_config()
3232 rep = VppGbpEndpoint(self, vx_tun_l3,
3234 "10.0.0.101", "11.0.0.101",
3235 "2001:10::101", "3001::101",
3236 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
3238 self.pg7.remote_ip4,
3240 rep.add_vpp_config()
3243 # ARP packet from External EPs are accpeted and replied to
3245 p_arp = (Ether(src=eep1.mac, dst="ff:ff:ff:ff:ff:ff") /
3248 psrc=eep1.ip4.address, pdst="10.0.0.128",
3249 hwsrc=eep1.mac, hwdst="ff:ff:ff:ff:ff:ff"))
3250 rxs = self.send_and_expect(self.pg0, p_arp * 1, self.pg0)
3253 # packets destined to unknown addresses in the BVI's subnet
3256 p4 = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3258 IP(src="10.0.0.1", dst="10.0.0.88") /
3259 UDP(sport=1234, dport=1234) /
3261 p6 = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3263 IPv6(src="2001:10::1", dst="2001:10::88") /
3264 UDP(sport=1234, dport=1234) /
3267 rxs = self.send_and_expect(self.pg0, p4 * 1, self.pg7)
3270 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3271 # self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3272 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3273 self.assertEqual(rx[IP].dst, "239.1.1.1")
3274 self.assertEqual(rx[VXLAN].vni, 88)
3275 self.assertTrue(rx[VXLAN].flags.G)
3276 self.assertTrue(rx[VXLAN].flags.Instance)
3277 # policy was applied to the original IP packet
3278 self.assertEqual(rx[VXLAN].gpid, 113)
3279 self.assertTrue(rx[VXLAN].gpflags.A)
3280 self.assertFalse(rx[VXLAN].gpflags.D)
3282 inner = rx[VXLAN].payload
3284 self.assertTrue(inner.haslayer(ARP))
3287 # remote to external
3289 p = (Ether(src=self.pg7.remote_mac,
3290 dst=self.pg7.local_mac) /
3291 IP(src=self.pg7.remote_ip4,
3292 dst=self.pg7.local_ip4) /
3293 UDP(sport=1234, dport=48879) /
3294 VXLAN(vni=444, gpid=113, flags=0x88) /
3295 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
3296 IP(src="10.0.0.101", dst="10.0.0.1") /
3297 UDP(sport=1234, dport=1234) /
3300 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
3303 # local EP pings router
3305 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3307 IP(src=eep1.ip4.address, dst="10.0.0.128") /
3308 ICMP(type='echo-request'))
3310 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
3313 self.assertEqual(rx[Ether].src, str(self.router_mac))
3314 self.assertEqual(rx[Ether].dst, eep1.mac)
3315 self.assertEqual(rx[Dot1Q].vlan, 100)
3318 # local EP pings other local EP
3320 p = (Ether(src=eep1.mac, dst=eep2.mac) /
3322 IP(src=eep1.ip4.address, dst=eep2.ip4.address) /
3323 ICMP(type='echo-request'))
3325 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
3328 self.assertEqual(rx[Ether].src, eep1.mac)
3329 self.assertEqual(rx[Ether].dst, eep2.mac)
3330 self.assertEqual(rx[Dot1Q].vlan, 101)
3333 # A subnet reachable through the external EP
3335 ip_220 = VppIpRoute(self, "10.220.0.0", 24,
3336 [VppRoutePath(eep1.ip4.address,
3337 eep1.epg.bvi.sw_if_index)],
3338 table_id=t4.table_id)
3339 ip_220.add_vpp_config()
3341 l3o_220 = VppGbpSubnet(
3342 self, rd1, "10.220.0.0", 24,
3343 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3345 l3o_220.add_vpp_config()
3347 p = (Ether(src=self.pg7.remote_mac,
3348 dst=self.pg7.local_mac) /
3349 IP(src=self.pg7.remote_ip4,
3350 dst=self.pg7.local_ip4) /
3351 UDP(sport=1234, dport=48879) /
3352 VXLAN(vni=444, gpid=113, flags=0x88) /
3353 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
3354 IP(src="10.0.0.101", dst="10.220.0.1") /
3355 UDP(sport=1234, dport=1234) /
3358 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
3361 # A subnet reachable through the external EP
3363 ip_221 = VppIpRoute(self, "10.221.0.0", 24,
3364 [VppRoutePath(eep2.ip4.address,
3365 eep2.epg.bvi.sw_if_index)],
3366 table_id=t4.table_id)
3367 ip_221.add_vpp_config()
3369 l3o_221 = VppGbpSubnet(
3370 self, rd1, "10.221.0.0", 24,
3371 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3373 l3o_221.add_vpp_config()
3376 # ping between hosts in remote subnets
3378 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3380 IP(src="10.220.0.1", dst="10.221.0.1") /
3381 ICMP(type='echo-request'))
3383 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
3386 self.assertEqual(rx[Ether].src, str(self.router_mac))
3387 self.assertEqual(rx[Ether].dst, eep2.mac)
3388 self.assertEqual(rx[Dot1Q].vlan, 101)
3393 self.pg7.unconfig_ip4()
3394 vlan_100.set_vtr(L2_VTR_OP.L2_DISABLED)
3397 if __name__ == '__main__':
3398 unittest.main(testRunner=VppTestRunner)