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
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
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):
72 return self.itf.remote_mac
92 return [self.ip4, self.ip6]
96 return [self.fip4, self.fip6]
98 def __init__(self, test, itf, epg, recirc, ip4, fip4, ip6, fip6,
108 self._ip4 = VppIpAddress(ip4)
109 self._fip4 = VppIpAddress(fip4)
110 self._ip6 = VppIpAddress(ip6)
111 self._fip6 = VppIpAddress(fip6)
114 self.vmac = MACAddress(self.itf.remote_mac)
116 self.vmac = MACAddress("00:00:00:00:00:00")
119 self.tun_src = VppIpAddress(tun_src)
120 self.tun_dst = VppIpAddress(tun_dst)
122 def add_vpp_config(self):
123 res = self._test.vapi.gbp_endpoint_add(
124 self.itf.sw_if_index,
125 [self.ip4.encode(), self.ip6.encode()],
129 self.tun_src.encode(),
130 self.tun_dst.encode())
131 self.handle = res.handle
132 self._test.registry.register(self, self._test.logger)
134 def remove_vpp_config(self):
135 self._test.vapi.gbp_endpoint_del(self.handle)
138 return self.object_id()
141 return "gbp-endpoint:[%d==%d:%s:%d]" % (self.handle,
142 self.itf.sw_if_index,
146 def query_vpp_config(self):
147 return find_gbp_endpoint(self._test,
148 self.itf.sw_if_index,
152 class VppGbpRecirc(VppObject):
154 GBP Recirculation Interface
157 def __init__(self, test, epg, recirc, is_ext=False):
163 def add_vpp_config(self):
164 self._test.vapi.gbp_recirc_add_del(
166 self.recirc.sw_if_index,
169 self._test.registry.register(self, self._test.logger)
171 def remove_vpp_config(self):
172 self._test.vapi.gbp_recirc_add_del(
174 self.recirc.sw_if_index,
179 return self.object_id()
182 return "gbp-recirc:[%d]" % (self.recirc.sw_if_index)
184 def query_vpp_config(self):
185 rs = self._test.vapi.gbp_recirc_dump()
187 if r.recirc.sw_if_index == self.recirc.sw_if_index:
192 class VppGbpExtItf(VppObject):
194 GBP ExtItfulation Interface
197 def __init__(self, test, itf, bd, rd):
203 def add_vpp_config(self):
204 self._test.vapi.gbp_ext_itf_add_del(
206 self.itf.sw_if_index,
209 self._test.registry.register(self, self._test.logger)
211 def remove_vpp_config(self):
212 self._test.vapi.gbp_ext_itf_add_del(
214 self.itf.sw_if_index,
219 return self.object_id()
222 return "gbp-ext-itf:[%d]" % (self.itf.sw_if_index)
224 def query_vpp_config(self):
225 rs = self._test.vapi.gbp_ext_itf_dump()
227 if r.ext_itf.sw_if_index == self.itf.sw_if_index:
232 class VppGbpSubnet(VppObject):
236 def __init__(self, test, rd, address, address_len,
237 type, sw_if_index=None, epg=None):
239 self.rd_id = rd.rd_id
240 self.prefix = VppIpPrefix(address, address_len)
242 self.sw_if_index = sw_if_index
245 def add_vpp_config(self):
246 self._test.vapi.gbp_subnet_add_del(
249 self.prefix.encode(),
251 sw_if_index=self.sw_if_index if self.sw_if_index else 0xffffffff,
252 epg_id=self.epg if self.epg else 0xffff)
253 self._test.registry.register(self, self._test.logger)
255 def remove_vpp_config(self):
256 self._test.vapi.gbp_subnet_add_del(
259 self.prefix.encode(),
263 return self.object_id()
266 return "gbp-subnet:[%d-%s]" % (self.rd_id, self.prefix)
268 def query_vpp_config(self):
269 ss = self._test.vapi.gbp_subnet_dump()
271 if s.subnet.rd_id == self.rd_id and \
272 s.subnet.type == self.type and \
273 s.subnet.prefix == self.prefix:
278 class VppGbpEndpointGroup(VppObject):
283 def __init__(self, test, epg, sclass, rd, bd, uplink,
284 bvi, bvi_ip4, bvi_ip6=None):
288 self.bvi_ip4 = VppIpAddress(bvi_ip4)
289 self.bvi_ip6 = VppIpAddress(bvi_ip6)
297 def add_vpp_config(self):
298 self._test.vapi.gbp_endpoint_group_add(
303 self.uplink.sw_if_index if self.uplink else INDEX_INVALID)
304 self._test.registry.register(self, self._test.logger)
306 def remove_vpp_config(self):
307 self._test.vapi.gbp_endpoint_group_del(
311 return self.object_id()
314 return "gbp-endpoint-group:[%d]" % (self.epg)
316 def query_vpp_config(self):
317 epgs = self._test.vapi.gbp_endpoint_group_dump()
319 if epg.epg.epg_id == self.epg:
324 class VppGbpBridgeDomain(VppObject):
329 def __init__(self, test, bd, bvi, uu_fwd=None,
330 bm_flood=None, learn=True):
334 self.bm_flood = bm_flood
337 e = VppEnum.vl_api_gbp_bridge_domain_flags_t
339 self.learn = e.GBP_BD_API_FLAG_NONE
341 self.learn = e.GBP_BD_API_FLAG_DO_NOT_LEARN
343 def add_vpp_config(self):
344 self._test.vapi.gbp_bridge_domain_add(
347 self.bvi.sw_if_index,
348 self.uu_fwd.sw_if_index if self.uu_fwd else INDEX_INVALID,
349 self.bm_flood.sw_if_index if self.bm_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.packed,
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,
447 rules, allowed_ethertypes):
449 self.acl_index = acl_index
450 self.src_epg = src_epg
451 self.dst_epg = dst_epg
453 self.allowed_ethertypes = allowed_ethertypes
455 def add_vpp_config(self):
458 rules.append(r.encode())
459 self._test.vapi.gbp_contract_add_del(
465 self.allowed_ethertypes)
466 self._test.registry.register(self, self._test.logger)
468 def remove_vpp_config(self):
469 self._test.vapi.gbp_contract_add_del(
477 return self.object_id()
480 return "gbp-contract:[%d:%s:%d]" % (self.src_epg,
484 def query_vpp_config(self):
485 cs = self._test.vapi.gbp_contract_dump()
487 if c.contract.src_epg == self.src_epg \
488 and c.contract.dst_epg == self.dst_epg:
493 class VppGbpVxlanTunnel(VppInterface):
498 def __init__(self, test, vni, bd_rd_id, mode):
499 super(VppGbpVxlanTunnel, self).__init__(test)
502 self.bd_rd_id = bd_rd_id
505 def add_vpp_config(self):
506 r = self._test.vapi.gbp_vxlan_tunnel_add(
510 self.set_sw_if_index(r.sw_if_index)
511 self._test.registry.register(self, self._test.logger)
513 def remove_vpp_config(self):
514 self._test.vapi.gbp_vxlan_tunnel_del(self.vni)
517 return self.object_id()
520 return "gbp-vxlan:%d" % (self.vni)
522 def query_vpp_config(self):
523 return find_gbp_vxlan(self._test, self.vni)
526 class VppGbpAcl(VppObject):
531 def __init__(self, test):
533 self.acl_index = 4294967295
535 def create_rule(self, is_ipv6=0, permit_deny=0, proto=-1,
536 s_prefix=0, s_ip='\x00\x00\x00\x00', sport_from=0,
537 sport_to=65535, d_prefix=0, d_ip='\x00\x00\x00\x00',
538 dport_from=0, dport_to=65535):
539 if proto == -1 or proto == 0:
542 elif proto == 1 or proto == 58:
545 rule = ({'is_permit': permit_deny, 'is_ipv6': is_ipv6, 'proto': proto,
546 'srcport_or_icmptype_first': sport_from,
547 'srcport_or_icmptype_last': sport_to,
548 'src_ip_prefix_len': s_prefix,
550 'dstport_or_icmpcode_first': dport_from,
551 'dstport_or_icmpcode_last': dport_to,
552 'dst_ip_prefix_len': d_prefix,
553 'dst_ip_addr': d_ip})
556 def add_vpp_config(self, rules):
558 reply = self._test.vapi.acl_add_replace(self.acl_index,
561 self.acl_index = reply.acl_index
562 return self.acl_index
564 def remove_vpp_config(self):
565 self._test.vapi.acl_del(self.acl_index)
568 return self.object_id()
571 return "gbp-acl:[%d]" % (self.acl_index)
573 def query_vpp_config(self):
574 cs = self._test.vapi.acl_dump()
576 if c.acl_index == self.acl_index:
581 class TestGBP(VppTestCase):
582 """ GBP Test Case """
585 super(TestGBP, self).setUp()
587 self.create_pg_interfaces(range(9))
588 self.create_loopback_interfaces(8)
590 self.router_mac = MACAddress("00:11:22:33:44:55")
592 for i in self.pg_interfaces:
594 for i in self.lo_interfaces:
598 for i in self.pg_interfaces:
601 super(TestGBP, self).tearDown()
603 def send_and_expect_bridged(self, src, tx, dst):
604 rx = self.send_and_expect(src, tx, dst)
607 self.assertEqual(r[Ether].src, tx[0][Ether].src)
608 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
609 self.assertEqual(r[IP].src, tx[0][IP].src)
610 self.assertEqual(r[IP].dst, tx[0][IP].dst)
613 def send_and_expect_bridged6(self, src, tx, dst):
614 rx = self.send_and_expect(src, tx, dst)
617 self.assertEqual(r[Ether].src, tx[0][Ether].src)
618 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
619 self.assertEqual(r[IPv6].src, tx[0][IPv6].src)
620 self.assertEqual(r[IPv6].dst, tx[0][IPv6].dst)
623 def send_and_expect_routed(self, src, tx, dst, src_mac):
624 rx = self.send_and_expect(src, tx, dst)
627 self.assertEqual(r[Ether].src, src_mac)
628 self.assertEqual(r[Ether].dst, dst.remote_mac)
629 self.assertEqual(r[IP].src, tx[0][IP].src)
630 self.assertEqual(r[IP].dst, tx[0][IP].dst)
633 def send_and_expect_natted(self, src, tx, dst, src_ip):
634 rx = self.send_and_expect(src, tx, dst)
637 self.assertEqual(r[Ether].src, tx[0][Ether].src)
638 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
639 self.assertEqual(r[IP].src, src_ip)
640 self.assertEqual(r[IP].dst, tx[0][IP].dst)
643 def send_and_expect_natted6(self, src, tx, dst, src_ip):
644 rx = self.send_and_expect(src, tx, dst)
647 self.assertEqual(r[Ether].src, tx[0][Ether].src)
648 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
649 self.assertEqual(r[IPv6].src, src_ip)
650 self.assertEqual(r[IPv6].dst, tx[0][IPv6].dst)
653 def send_and_expect_unnatted(self, src, tx, dst, dst_ip):
654 rx = self.send_and_expect(src, tx, dst)
657 self.assertEqual(r[Ether].src, tx[0][Ether].src)
658 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
659 self.assertEqual(r[IP].dst, dst_ip)
660 self.assertEqual(r[IP].src, tx[0][IP].src)
663 def send_and_expect_unnatted6(self, src, tx, dst, dst_ip):
664 rx = self.send_and_expect(src, tx, dst)
667 self.assertEqual(r[Ether].src, tx[0][Ether].src)
668 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
669 self.assertEqual(r[IPv6].dst, dst_ip)
670 self.assertEqual(r[IPv6].src, tx[0][IPv6].src)
673 def send_and_expect_double_natted(self, src, tx, dst, src_ip, dst_ip):
674 rx = self.send_and_expect(src, tx, dst)
677 self.assertEqual(r[Ether].src, str(self.router_mac))
678 self.assertEqual(r[Ether].dst, dst.remote_mac)
679 self.assertEqual(r[IP].dst, dst_ip)
680 self.assertEqual(r[IP].src, src_ip)
683 def send_and_expect_double_natted6(self, src, tx, dst, src_ip, dst_ip):
684 rx = self.send_and_expect(src, tx, dst)
687 self.assertEqual(r[Ether].src, str(self.router_mac))
688 self.assertEqual(r[Ether].dst, dst.remote_mac)
689 self.assertEqual(r[IPv6].dst, dst_ip)
690 self.assertEqual(r[IPv6].src, src_ip)
694 """ Group Based Policy """
696 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
701 bd1 = VppBridgeDomain(self, 1)
702 bd2 = VppBridgeDomain(self, 2)
703 bd20 = VppBridgeDomain(self, 20)
707 bd20.add_vpp_config()
709 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0)
710 gbd2 = VppGbpBridgeDomain(self, bd2, self.loop1)
711 gbd20 = VppGbpBridgeDomain(self, bd20, self.loop2)
713 gbd1.add_vpp_config()
714 gbd2.add_vpp_config()
715 gbd20.add_vpp_config()
720 gt4 = VppIpTable(self, 0)
722 gt6 = VppIpTable(self, 0, is_ip6=True)
724 nt4 = VppIpTable(self, 20)
726 nt6 = VppIpTable(self, 20, is_ip6=True)
729 rd0 = VppGbpRouteDomain(self, 0, gt4, gt6, None, None)
730 rd20 = VppGbpRouteDomain(self, 20, nt4, nt6, None, None)
733 rd20.add_vpp_config()
736 # 3 EPGs, 2 of which share a BD.
737 # 2 NAT EPGs, one for floating-IP subnets, the other for internet
739 epgs = [VppGbpEndpointGroup(self, 220, 0, rd0, gbd1, self.pg4,
743 VppGbpEndpointGroup(self, 221, 0, rd0, gbd1, self.pg5,
747 VppGbpEndpointGroup(self, 222, 0, rd0, gbd2, self.pg6,
751 VppGbpEndpointGroup(self, 333, 0, rd20, gbd20, self.pg7,
755 VppGbpEndpointGroup(self, 444, 0, rd20, gbd20, self.pg8,
759 recircs = [VppGbpRecirc(self, epgs[0],
761 VppGbpRecirc(self, epgs[1],
763 VppGbpRecirc(self, epgs[2],
765 VppGbpRecirc(self, epgs[3],
766 self.loop6, is_ext=True),
767 VppGbpRecirc(self, epgs[4],
768 self.loop7, is_ext=True)]
771 recirc_nat = recircs[3]
774 # 4 end-points, 2 in the same subnet, 3 in the same BD
776 eps = [VppGbpEndpoint(self, self.pg0,
778 "10.0.0.1", "11.0.0.1",
779 "2001:10::1", "3001::1"),
780 VppGbpEndpoint(self, self.pg1,
782 "10.0.0.2", "11.0.0.2",
783 "2001:10::2", "3001::2"),
784 VppGbpEndpoint(self, self.pg2,
786 "10.0.1.1", "11.0.0.3",
787 "2001:10:1::1", "3001::3"),
788 VppGbpEndpoint(self, self.pg3,
790 "10.0.2.1", "11.0.0.4",
791 "2001:10:2::1", "3001::4")]
794 # Config related to each of the EPGs
797 # IP config on the BVI interfaces
798 if epg != epgs[1] and epg != epgs[4]:
799 VppIpInterfaceBind(self, epg.bvi, epg.rd.t4).add_vpp_config()
800 VppIpInterfaceBind(self, epg.bvi, epg.rd.t6).add_vpp_config()
801 self.vapi.sw_interface_set_mac_address(
803 self.router_mac.packed)
805 # The BVIs are NAT inside interfaces
806 self.vapi.nat44_interface_add_del_feature(epg.bvi.sw_if_index,
809 self.vapi.nat66_add_del_interface(epg.bvi.sw_if_index,
813 if_ip4 = VppIpInterfaceAddress(self, epg.bvi, epg.bvi_ip4, 32)
814 if_ip6 = VppIpInterfaceAddress(self, epg.bvi, epg.bvi_ip6, 128)
815 if_ip4.add_vpp_config()
816 if_ip6.add_vpp_config()
818 # EPG uplink interfaces in the RD
819 VppIpInterfaceBind(self, epg.uplink, epg.rd.t4).add_vpp_config()
820 VppIpInterfaceBind(self, epg.uplink, epg.rd.t6).add_vpp_config()
822 # add the BD ARP termination entry for BVI IP
823 epg.bd_arp_ip4 = VppBridgeDomainArpEntry(self, epg.bd.bd,
824 str(self.router_mac),
826 epg.bd_arp_ip6 = VppBridgeDomainArpEntry(self, epg.bd.bd,
827 str(self.router_mac),
829 epg.bd_arp_ip4.add_vpp_config()
830 epg.bd_arp_ip6.add_vpp_config()
835 for recirc in recircs:
836 # EPG's ingress recirculation interface maps to its RD
837 VppIpInterfaceBind(self, recirc.recirc,
838 recirc.epg.rd.t4).add_vpp_config()
839 VppIpInterfaceBind(self, recirc.recirc,
840 recirc.epg.rd.t6).add_vpp_config()
842 self.vapi.nat44_interface_add_del_feature(
843 recirc.recirc.sw_if_index,
846 self.vapi.nat66_add_del_interface(
847 recirc.recirc.sw_if_index,
851 recirc.add_vpp_config()
853 for recirc in recircs:
854 self.assertTrue(find_bridge_domain_port(self,
855 recirc.epg.bd.bd.bd_id,
856 recirc.recirc.sw_if_index))
859 self.pg_enable_capture(self.pg_interfaces)
862 # routes to the endpoints. We need these since there are no
863 # adj-fibs due to the fact the the BVI address has /32 and
864 # the subnet is not attached.
866 for (ip, fip) in zip(ep.ips, ep.fips):
867 # Add static mappings for each EP from the 10/8 to 11/8 network
869 self.vapi.nat44_add_del_static_mapping(ip.bytes,
874 self.vapi.nat66_add_del_static_mapping(ip.bytes,
881 self.logger.info(self.vapi.cli("sh gbp endpoint"))
883 # ... results in a Gratuitous ARP/ND on the EPG's uplink
884 rx = ep.epg.uplink.get_capture(len(ep.ips), timeout=0.2)
886 for ii, ip in enumerate(ep.ips):
890 self.assertTrue(p.haslayer(ICMPv6ND_NA))
891 self.assertEqual(p[ICMPv6ND_NA].tgt, ip.address)
893 self.assertTrue(p.haslayer(ARP))
894 self.assertEqual(p[ARP].psrc, ip.address)
895 self.assertEqual(p[ARP].pdst, ip.address)
897 # add the BD ARP termination entry for floating IP
899 ba = VppBridgeDomainArpEntry(self, epg_nat.bd.bd, ep.mac, fip)
902 # floating IPs route via EPG recirc
903 r = VppIpRoute(self, fip.address, fip.length,
904 [VppRoutePath(fip.address,
905 ep.recirc.recirc.sw_if_index,
907 proto=fip.dpo_proto)],
912 # L2 FIB entries in the NAT EPG BD to bridge the packets from
913 # the outside direct to the internal EPG
914 lf = VppL2FibEntry(self, epg_nat.bd.bd, ep.mac,
915 ep.recirc.recirc, bvi_mac=0)
919 # ARP packets for unknown IP are sent to the EPG uplink
921 pkt_arp = (Ether(dst="ff:ff:ff:ff:ff:ff",
922 src=self.pg0.remote_mac) /
924 hwdst="ff:ff:ff:ff:ff:ff",
925 hwsrc=self.pg0.remote_mac,
929 self.vapi.cli("clear trace")
930 self.pg0.add_stream(pkt_arp)
932 self.pg_enable_capture(self.pg_interfaces)
935 rxd = epgs[0].uplink.get_capture(1)
938 # ARP/ND packets get a response
940 pkt_arp = (Ether(dst="ff:ff:ff:ff:ff:ff",
941 src=self.pg0.remote_mac) /
943 hwdst="ff:ff:ff:ff:ff:ff",
944 hwsrc=self.pg0.remote_mac,
945 pdst=epgs[0].bvi_ip4.address,
946 psrc=eps[0].ip4.address))
948 self.send_and_expect(self.pg0, [pkt_arp], self.pg0)
950 nsma = in6_getnsma(inet_pton(AF_INET6, eps[0].ip6.address))
951 d = inet_ntop(AF_INET6, nsma)
952 pkt_nd = (Ether(dst=in6_getnsmac(nsma),
953 src=self.pg0.remote_mac) /
954 IPv6(dst=d, src=eps[0].ip6.address) /
955 ICMPv6ND_NS(tgt=epgs[0].bvi_ip6.address) /
956 ICMPv6NDOptSrcLLAddr(lladdr=self.pg0.remote_mac))
957 self.send_and_expect(self.pg0, [pkt_nd], self.pg0)
960 # broadcast packets are flooded
962 pkt_bcast = (Ether(dst="ff:ff:ff:ff:ff:ff",
963 src=self.pg0.remote_mac) /
964 IP(src=eps[0].ip4.address, dst="232.1.1.1") /
965 UDP(sport=1234, dport=1234) /
968 self.vapi.cli("clear trace")
969 self.pg0.add_stream(pkt_bcast)
971 self.pg_enable_capture(self.pg_interfaces)
974 rxd = eps[1].itf.get_capture(1)
975 self.assertEqual(rxd[0][Ether].dst, pkt_bcast[Ether].dst)
976 rxd = epgs[0].uplink.get_capture(1)
977 self.assertEqual(rxd[0][Ether].dst, pkt_bcast[Ether].dst)
980 # packets to non-local L3 destinations dropped
982 pkt_intra_epg_220_ip4 = (Ether(src=self.pg0.remote_mac,
983 dst=str(self.router_mac)) /
984 IP(src=eps[0].ip4.address,
986 UDP(sport=1234, dport=1234) /
988 pkt_inter_epg_222_ip4 = (Ether(src=self.pg0.remote_mac,
989 dst=str(self.router_mac)) /
990 IP(src=eps[0].ip4.address,
992 UDP(sport=1234, dport=1234) /
995 self.send_and_assert_no_replies(self.pg0, pkt_intra_epg_220_ip4 * 65)
997 pkt_inter_epg_222_ip6 = (Ether(src=self.pg0.remote_mac,
998 dst=str(self.router_mac)) /
999 IPv6(src=eps[0].ip6.address,
1000 dst="2001:10::99") /
1001 UDP(sport=1234, dport=1234) /
1003 self.send_and_assert_no_replies(self.pg0, pkt_inter_epg_222_ip6 * 65)
1006 # Add the subnet routes
1009 self, rd0, "10.0.0.0", 24,
1010 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1012 self, rd0, "10.0.1.0", 24,
1013 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1015 self, rd0, "10.0.2.0", 24,
1016 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1018 self, rd0, "2001:10::1", 64,
1019 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1021 self, rd0, "2001:10:1::1", 64,
1022 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1024 self, rd0, "2001:10:2::1", 64,
1025 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1026 s41.add_vpp_config()
1027 s42.add_vpp_config()
1028 s43.add_vpp_config()
1029 s61.add_vpp_config()
1030 s62.add_vpp_config()
1031 s63.add_vpp_config()
1033 self.send_and_expect_bridged(eps[0].itf,
1034 pkt_intra_epg_220_ip4 * 65,
1036 self.send_and_expect_bridged(eps[0].itf,
1037 pkt_inter_epg_222_ip4 * 65,
1039 self.send_and_expect_bridged6(eps[0].itf,
1040 pkt_inter_epg_222_ip6 * 65,
1043 self.logger.info(self.vapi.cli("sh ip fib 11.0.0.2"))
1044 self.logger.info(self.vapi.cli("sh gbp endpoint-group"))
1045 self.logger.info(self.vapi.cli("sh gbp endpoint"))
1046 self.logger.info(self.vapi.cli("sh gbp recirc"))
1047 self.logger.info(self.vapi.cli("sh int"))
1048 self.logger.info(self.vapi.cli("sh int addr"))
1049 self.logger.info(self.vapi.cli("sh int feat loop6"))
1050 self.logger.info(self.vapi.cli("sh vlib graph ip4-gbp-src-classify"))
1051 self.logger.info(self.vapi.cli("sh int feat loop3"))
1052 self.logger.info(self.vapi.cli("sh int feat pg0"))
1055 # Packet destined to unknown unicast is sent on the epg uplink ...
1057 pkt_intra_epg_220_to_uplink = (Ether(src=self.pg0.remote_mac,
1058 dst="00:00:00:33:44:55") /
1059 IP(src=eps[0].ip4.address,
1061 UDP(sport=1234, dport=1234) /
1064 self.send_and_expect_bridged(eps[0].itf,
1065 pkt_intra_epg_220_to_uplink * 65,
1067 # ... and nowhere else
1068 self.pg1.get_capture(0, timeout=0.1)
1069 self.pg1.assert_nothing_captured(remark="Flood onto other VMS")
1071 pkt_intra_epg_221_to_uplink = (Ether(src=self.pg2.remote_mac,
1072 dst="00:00:00:33:44:66") /
1073 IP(src=eps[0].ip4.address,
1075 UDP(sport=1234, dport=1234) /
1078 self.send_and_expect_bridged(eps[2].itf,
1079 pkt_intra_epg_221_to_uplink * 65,
1083 # Packets from the uplink are forwarded in the absence of a contract
1085 pkt_intra_epg_220_from_uplink = (Ether(src="00:00:00:33:44:55",
1086 dst=self.pg0.remote_mac) /
1087 IP(src=eps[0].ip4.address,
1089 UDP(sport=1234, dport=1234) /
1092 self.send_and_expect_bridged(self.pg4,
1093 pkt_intra_epg_220_from_uplink * 65,
1097 # in the absence of policy, endpoints in the same EPG
1100 pkt_intra_epg = (Ether(src=self.pg0.remote_mac,
1101 dst=self.pg1.remote_mac) /
1102 IP(src=eps[0].ip4.address,
1103 dst=eps[1].ip4.address) /
1104 UDP(sport=1234, dport=1234) /
1107 self.send_and_expect_bridged(self.pg0, pkt_intra_epg * 65, self.pg1)
1110 # in the abscense of policy, endpoints in the different EPG
1111 # cannot communicate
1113 pkt_inter_epg_220_to_221 = (Ether(src=self.pg0.remote_mac,
1114 dst=self.pg2.remote_mac) /
1115 IP(src=eps[0].ip4.address,
1116 dst=eps[2].ip4.address) /
1117 UDP(sport=1234, dport=1234) /
1119 pkt_inter_epg_221_to_220 = (Ether(src=self.pg2.remote_mac,
1120 dst=self.pg0.remote_mac) /
1121 IP(src=eps[2].ip4.address,
1122 dst=eps[0].ip4.address) /
1123 UDP(sport=1234, dport=1234) /
1125 pkt_inter_epg_220_to_222 = (Ether(src=self.pg0.remote_mac,
1126 dst=str(self.router_mac)) /
1127 IP(src=eps[0].ip4.address,
1128 dst=eps[3].ip4.address) /
1129 UDP(sport=1234, dport=1234) /
1132 self.send_and_assert_no_replies(eps[0].itf,
1133 pkt_inter_epg_220_to_221 * 65)
1134 self.send_and_assert_no_replies(eps[0].itf,
1135 pkt_inter_epg_220_to_222 * 65)
1138 # A uni-directional contract from EPG 220 -> 221
1140 acl = VppGbpAcl(self)
1141 rule = acl.create_rule(permit_deny=1, proto=17)
1142 rule2 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
1143 acl_index = acl.add_vpp_config([rule, rule2])
1144 c1 = VppGbpContract(
1145 self, 220, 221, acl_index,
1146 [VppGbpContractRule(
1147 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1150 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1152 [ETH_P_IP, ETH_P_IPV6])
1155 self.send_and_expect_bridged(eps[0].itf,
1156 pkt_inter_epg_220_to_221 * 65,
1158 self.send_and_assert_no_replies(eps[0].itf,
1159 pkt_inter_epg_220_to_222 * 65)
1162 # contract for the return direction
1164 c2 = VppGbpContract(
1165 self, 221, 220, acl_index,
1166 [VppGbpContractRule(
1167 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1170 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1172 [ETH_P_IP, ETH_P_IPV6])
1175 self.send_and_expect_bridged(eps[0].itf,
1176 pkt_inter_epg_220_to_221 * 65,
1178 self.send_and_expect_bridged(eps[2].itf,
1179 pkt_inter_epg_221_to_220 * 65,
1183 # the contract does not allow non-IP
1185 pkt_non_ip_inter_epg_220_to_221 = (Ether(src=self.pg0.remote_mac,
1186 dst=self.pg2.remote_mac) /
1188 self.send_and_assert_no_replies(eps[0].itf,
1189 pkt_non_ip_inter_epg_220_to_221 * 17)
1192 # check that inter group is still disabled for the groups
1193 # not in the contract.
1195 self.send_and_assert_no_replies(eps[0].itf,
1196 pkt_inter_epg_220_to_222 * 65)
1199 # A uni-directional contract from EPG 220 -> 222 'L3 routed'
1201 c3 = VppGbpContract(
1202 self, 220, 222, acl_index,
1203 [VppGbpContractRule(
1204 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1207 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1209 [ETH_P_IP, ETH_P_IPV6])
1212 self.logger.info(self.vapi.cli("sh gbp contract"))
1214 self.send_and_expect_routed(eps[0].itf,
1215 pkt_inter_epg_220_to_222 * 65,
1217 str(self.router_mac))
1220 # remove both contracts, traffic stops in both directions
1222 c2.remove_vpp_config()
1223 c1.remove_vpp_config()
1224 c3.remove_vpp_config()
1225 acl.remove_vpp_config()
1227 self.send_and_assert_no_replies(eps[2].itf,
1228 pkt_inter_epg_221_to_220 * 65)
1229 self.send_and_assert_no_replies(eps[0].itf,
1230 pkt_inter_epg_220_to_221 * 65)
1231 self.send_and_expect_bridged(eps[0].itf,
1236 # EPs to the outside world
1239 # in the EP's RD an external subnet via the NAT EPG's recirc
1241 self, rd0, "0.0.0.0", 0,
1242 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1243 sw_if_index=recirc_nat.recirc.sw_if_index,
1246 self, rd0, "11.0.0.0", 8,
1247 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1248 sw_if_index=recirc_nat.recirc.sw_if_index,
1250 se16 = VppGbpSubnet(
1252 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1253 sw_if_index=recirc_nat.recirc.sw_if_index,
1255 # in the NAT RD an external subnet via the NAT EPG's uplink
1257 self, rd20, "0.0.0.0", 0,
1258 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1259 sw_if_index=epg_nat.uplink.sw_if_index,
1261 se36 = VppGbpSubnet(
1262 self, rd20, "::", 0,
1263 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1264 sw_if_index=epg_nat.uplink.sw_if_index,
1267 self, rd20, "11.0.0.0", 8,
1268 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1269 sw_if_index=epg_nat.uplink.sw_if_index,
1271 se1.add_vpp_config()
1272 se2.add_vpp_config()
1273 se16.add_vpp_config()
1274 se3.add_vpp_config()
1275 se36.add_vpp_config()
1276 se4.add_vpp_config()
1278 self.logger.info(self.vapi.cli("sh ip fib 0.0.0.0/0"))
1279 self.logger.info(self.vapi.cli("sh ip fib 11.0.0.1"))
1280 self.logger.info(self.vapi.cli("sh ip6 fib ::/0"))
1281 self.logger.info(self.vapi.cli("sh ip6 fib %s" %
1285 # From an EP to an outside addess: IN2OUT
1287 pkt_inter_epg_220_to_global = (Ether(src=self.pg0.remote_mac,
1288 dst=str(self.router_mac)) /
1289 IP(src=eps[0].ip4.address,
1291 UDP(sport=1234, dport=1234) /
1295 self.send_and_assert_no_replies(eps[0].itf,
1296 pkt_inter_epg_220_to_global * 65)
1298 acl2 = VppGbpAcl(self)
1299 rule = acl2.create_rule(permit_deny=1, proto=17, sport_from=1234,
1300 sport_to=1234, dport_from=1234, dport_to=1234)
1301 rule2 = acl2.create_rule(is_ipv6=1, permit_deny=1, proto=17,
1302 sport_from=1234, sport_to=1234,
1303 dport_from=1234, dport_to=1234)
1305 acl_index2 = acl2.add_vpp_config([rule, rule2])
1306 c4 = VppGbpContract(
1307 self, 220, 333, acl_index2,
1308 [VppGbpContractRule(
1309 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1312 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1314 [ETH_P_IP, ETH_P_IPV6])
1317 self.send_and_expect_natted(eps[0].itf,
1318 pkt_inter_epg_220_to_global * 65,
1320 eps[0].fip4.address)
1322 pkt_inter_epg_220_to_global = (Ether(src=self.pg0.remote_mac,
1323 dst=str(self.router_mac)) /
1324 IPv6(src=eps[0].ip6.address,
1326 UDP(sport=1234, dport=1234) /
1329 self.send_and_expect_natted6(self.pg0,
1330 pkt_inter_epg_220_to_global * 65,
1332 eps[0].fip6.address)
1335 # From a global address to an EP: OUT2IN
1337 pkt_inter_epg_220_from_global = (Ether(src=str(self.router_mac),
1338 dst=self.pg0.remote_mac) /
1339 IP(dst=eps[0].fip4.address,
1341 UDP(sport=1234, dport=1234) /
1344 self.send_and_assert_no_replies(self.pg7,
1345 pkt_inter_epg_220_from_global * 65)
1347 c5 = VppGbpContract(
1348 self, 333, 220, acl_index2,
1349 [VppGbpContractRule(
1350 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1353 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1355 [ETH_P_IP, ETH_P_IPV6])
1358 self.send_and_expect_unnatted(self.pg7,
1359 pkt_inter_epg_220_from_global * 65,
1363 pkt_inter_epg_220_from_global = (Ether(src=str(self.router_mac),
1364 dst=self.pg0.remote_mac) /
1365 IPv6(dst=eps[0].fip6.address,
1367 UDP(sport=1234, dport=1234) /
1370 self.send_and_expect_unnatted6(self.pg7,
1371 pkt_inter_epg_220_from_global * 65,
1376 # From a local VM to another local VM using resp. public addresses:
1379 pkt_intra_epg_220_global = (Ether(src=self.pg0.remote_mac,
1380 dst=str(self.router_mac)) /
1381 IP(src=eps[0].ip4.address,
1382 dst=eps[1].fip4.address) /
1383 UDP(sport=1234, dport=1234) /
1386 self.send_and_expect_double_natted(eps[0].itf,
1387 pkt_intra_epg_220_global * 65,
1389 eps[0].fip4.address,
1392 pkt_intra_epg_220_global = (Ether(src=self.pg0.remote_mac,
1393 dst=str(self.router_mac)) /
1394 IPv6(src=eps[0].ip6.address,
1395 dst=eps[1].fip6.address) /
1396 UDP(sport=1234, dport=1234) /
1399 self.send_and_expect_double_natted6(eps[0].itf,
1400 pkt_intra_epg_220_global * 65,
1402 eps[0].fip6.address,
1409 # del static mappings for each EP from the 10/8 to 11/8 network
1410 self.vapi.nat44_add_del_static_mapping(ep.ip4.bytes,
1415 self.vapi.nat66_add_del_static_mapping(ep.ip6.bytes,
1421 # IP config on the BVI interfaces
1422 if epg != epgs[0] and epg != epgs[3]:
1423 self.vapi.nat44_interface_add_del_feature(epg.bvi.sw_if_index,
1426 self.vapi.nat66_add_del_interface(epg.bvi.sw_if_index,
1430 for recirc in recircs:
1431 self.vapi.nat44_interface_add_del_feature(
1432 recirc.recirc.sw_if_index,
1435 self.vapi.nat66_add_del_interface(
1436 recirc.recirc.sw_if_index,
1440 def wait_for_ep_timeout(self, sw_if_index=None, ip=None, mac=None,
1441 n_tries=100, s_time=1):
1443 if not find_gbp_endpoint(self, sw_if_index, ip, mac):
1445 n_tries = n_tries - 1
1447 self.assertFalse(find_gbp_endpoint(self, sw_if_index, ip, mac))
1450 def test_gbp_learn_l2(self):
1451 """ GBP L2 Endpoint Learning """
1453 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
1454 learnt = [{'mac': '00:00:11:11:11:01',
1456 'ip6': '2001:10::2'},
1457 {'mac': '00:00:11:11:11:02',
1459 'ip6': '2001:10::3'}]
1462 # lower the inactive threshold so these tests pass in a
1463 # reasonable amount of time
1465 self.vapi.gbp_endpoint_learn_set_inactive_threshold(2)
1470 gt4 = VppIpTable(self, 1)
1471 gt4.add_vpp_config()
1472 gt6 = VppIpTable(self, 1, is_ip6=True)
1473 gt6.add_vpp_config()
1475 rd1 = VppGbpRouteDomain(self, 1, gt4, gt6)
1476 rd1.add_vpp_config()
1479 # Pg2 hosts the vxlan tunnel, hosts on pg2 to act as TEPs
1480 # Pg3 hosts the IP4 UU-flood VXLAN tunnel
1481 # Pg4 hosts the IP6 UU-flood VXLAN tunnel
1483 self.pg2.config_ip4()
1484 self.pg2.resolve_arp()
1485 self.pg2.generate_remote_hosts(4)
1486 self.pg2.configure_ipv4_neighbors()
1487 self.pg3.config_ip4()
1488 self.pg3.resolve_arp()
1489 self.pg4.config_ip4()
1490 self.pg4.resolve_arp()
1493 # Add a mcast destination VXLAN-GBP tunnel for B&M traffic
1495 tun_bm = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
1498 tun_bm.add_vpp_config()
1501 # a GBP bridge domain with a BVI and a UU-flood interface
1503 bd1 = VppBridgeDomain(self, 1)
1504 bd1.add_vpp_config()
1505 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0, self.pg3, tun_bm)
1506 gbd1.add_vpp_config()
1508 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1509 self.logger.info(self.vapi.cli("sh gbp bridge"))
1511 # ... and has a /32 applied
1512 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
1513 ip_addr.add_vpp_config()
1516 # The Endpoint-group in which we are learning endpoints
1518 epg_220 = VppGbpEndpointGroup(self, 220, 112, rd1, gbd1,
1522 epg_220.add_vpp_config()
1523 epg_330 = VppGbpEndpointGroup(self, 330, 113, rd1, gbd1,
1527 epg_330.add_vpp_config()
1530 # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
1533 vx_tun_l2_1 = VppGbpVxlanTunnel(
1534 self, 99, bd1.bd_id,
1535 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L2)
1536 vx_tun_l2_1.add_vpp_config()
1539 # A static endpoint that the learnt endpoints are trying to
1542 ep = VppGbpEndpoint(self, self.pg0,
1544 "10.0.0.127", "11.0.0.127",
1545 "2001:10::1", "3001::1")
1548 self.assertTrue(find_route(self, ep.ip4.address, 32, table_id=1))
1550 # a packet with an sclass from an unknwon EPG
1551 p = (Ether(src=self.pg2.remote_mac,
1552 dst=self.pg2.local_mac) /
1553 IP(src=self.pg2.remote_hosts[0].ip4,
1554 dst=self.pg2.local_ip4) /
1555 UDP(sport=1234, dport=48879) /
1556 VXLAN(vni=99, gpid=88, flags=0x88) /
1557 Ether(src=learnt[0]["mac"], dst=ep.mac) /
1558 IP(src=learnt[0]["ip"], dst=ep.ip4.address) /
1559 UDP(sport=1234, dport=1234) /
1562 self.send_and_assert_no_replies(self.pg2, p)
1565 # we should not have learnt a new tunnel endpoint, since
1566 # the EPG was not learnt.
1568 self.assertEqual(INDEX_INVALID,
1569 find_vxlan_gbp_tunnel(self,
1571 self.pg2.remote_hosts[0].ip4,
1574 # epg is not learnt, becasue the EPG is unknwon
1575 self.assertEqual(len(self.vapi.gbp_endpoint_dump()), 1)
1577 for ii, l in enumerate(learnt):
1578 # a packet with an sclass from a knwon EPG
1579 # arriving on an unknown TEP
1580 p = (Ether(src=self.pg2.remote_mac,
1581 dst=self.pg2.local_mac) /
1582 IP(src=self.pg2.remote_hosts[1].ip4,
1583 dst=self.pg2.local_ip4) /
1584 UDP(sport=1234, dport=48879) /
1585 VXLAN(vni=99, gpid=112, flags=0x88) /
1586 Ether(src=l['mac'], dst=ep.mac) /
1587 IP(src=l['ip'], dst=ep.ip4.address) /
1588 UDP(sport=1234, dport=1234) /
1591 rx = self.send_and_expect(self.pg2, [p], self.pg0)
1594 tep1_sw_if_index = find_vxlan_gbp_tunnel(
1597 self.pg2.remote_hosts[1].ip4,
1599 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
1602 # the EP is learnt via the learnt TEP
1603 # both from its MAC and its IP
1605 self.assertTrue(find_gbp_endpoint(self,
1606 vx_tun_l2_1.sw_if_index,
1608 self.assertTrue(find_gbp_endpoint(self,
1609 vx_tun_l2_1.sw_if_index,
1612 self.logger.info(self.vapi.cli("show gbp endpoint"))
1613 self.logger.info(self.vapi.cli("show gbp vxlan"))
1614 self.logger.info(self.vapi.cli("show vxlan-gbp tunnel"))
1617 # If we sleep for the threshold time, the learnt endpoints should
1621 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1625 # repeat. the do not learn bit is set so the EPs are not learnt
1628 # a packet with an sclass from a knwon EPG
1629 p = (Ether(src=self.pg2.remote_mac,
1630 dst=self.pg2.local_mac) /
1631 IP(src=self.pg2.remote_hosts[1].ip4,
1632 dst=self.pg2.local_ip4) /
1633 UDP(sport=1234, dport=48879) /
1634 VXLAN(vni=99, gpid=112, flags=0x88, gpflags="D") /
1635 Ether(src=l['mac'], dst=ep.mac) /
1636 IP(src=l['ip'], dst=ep.ip4.address) /
1637 UDP(sport=1234, dport=1234) /
1640 rx = self.send_and_expect(self.pg2, p*65, self.pg0)
1643 self.assertFalse(find_gbp_endpoint(self,
1644 vx_tun_l2_1.sw_if_index,
1651 # a packet with an sclass from a knwon EPG
1652 p = (Ether(src=self.pg2.remote_mac,
1653 dst=self.pg2.local_mac) /
1654 IP(src=self.pg2.remote_hosts[1].ip4,
1655 dst=self.pg2.local_ip4) /
1656 UDP(sport=1234, dport=48879) /
1657 VXLAN(vni=99, gpid=112, flags=0x88) /
1658 Ether(src=l['mac'], dst=ep.mac) /
1659 IP(src=l['ip'], dst=ep.ip4.address) /
1660 UDP(sport=1234, dport=1234) /
1663 rx = self.send_and_expect(self.pg2, p*65, self.pg0)
1665 self.assertTrue(find_gbp_endpoint(self,
1666 vx_tun_l2_1.sw_if_index,
1670 # Static EP replies to dynamics
1672 self.logger.info(self.vapi.cli("sh l2fib bd_id 1"))
1674 p = (Ether(src=ep.mac, dst=l['mac']) /
1675 IP(dst=l['ip'], src=ep.ip4.address) /
1676 UDP(sport=1234, dport=1234) /
1679 rxs = self.send_and_expect(self.pg0, p * 17, self.pg2)
1682 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
1683 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
1684 self.assertEqual(rx[UDP].dport, 48879)
1685 # the UDP source port is a random value for hashing
1686 self.assertEqual(rx[VXLAN].gpid, 112)
1687 self.assertEqual(rx[VXLAN].vni, 99)
1688 self.assertTrue(rx[VXLAN].flags.G)
1689 self.assertTrue(rx[VXLAN].flags.Instance)
1690 self.assertTrue(rx[VXLAN].gpflags.A)
1691 self.assertFalse(rx[VXLAN].gpflags.D)
1694 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1698 # repeat in the other EPG
1699 # there's no contract between 220 and 330, but the A-bit is set
1700 # so the packet is cleared for delivery
1703 # a packet with an sclass from a knwon EPG
1704 p = (Ether(src=self.pg2.remote_mac,
1705 dst=self.pg2.local_mac) /
1706 IP(src=self.pg2.remote_hosts[1].ip4,
1707 dst=self.pg2.local_ip4) /
1708 UDP(sport=1234, dport=48879) /
1709 VXLAN(vni=99, gpid=113, flags=0x88, gpflags='A') /
1710 Ether(src=l['mac'], dst=ep.mac) /
1711 IP(src=l['ip'], dst=ep.ip4.address) /
1712 UDP(sport=1234, dport=1234) /
1715 rx = self.send_and_expect(self.pg2, p*65, self.pg0)
1717 self.assertTrue(find_gbp_endpoint(self,
1718 vx_tun_l2_1.sw_if_index,
1722 # static EP cannot reach the learnt EPs since there is no contract
1723 # only test 1 EP as the others could timeout
1725 p = (Ether(src=ep.mac, dst=l['mac']) /
1726 IP(dst=learnt[0]['ip'], src=ep.ip4.address) /
1727 UDP(sport=1234, dport=1234) /
1730 self.send_and_assert_no_replies(self.pg0, [p])
1733 # refresh the entries after the check for no replies above
1736 # a packet with an sclass from a knwon EPG
1737 p = (Ether(src=self.pg2.remote_mac,
1738 dst=self.pg2.local_mac) /
1739 IP(src=self.pg2.remote_hosts[1].ip4,
1740 dst=self.pg2.local_ip4) /
1741 UDP(sport=1234, dport=48879) /
1742 VXLAN(vni=99, gpid=113, flags=0x88, gpflags='A') /
1743 Ether(src=l['mac'], dst=ep.mac) /
1744 IP(src=l['ip'], dst=ep.ip4.address) /
1745 UDP(sport=1234, dport=1234) /
1748 rx = self.send_and_expect(self.pg2, p*65, self.pg0)
1750 self.assertTrue(find_gbp_endpoint(self,
1751 vx_tun_l2_1.sw_if_index,
1755 # Add the contract so they can talk
1757 acl = VppGbpAcl(self)
1758 rule = acl.create_rule(permit_deny=1, proto=17)
1759 rule2 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
1760 acl_index = acl.add_vpp_config([rule, rule2])
1761 c1 = VppGbpContract(
1762 self, 220, 330, acl_index,
1763 [VppGbpContractRule(
1764 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1767 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1769 [ETH_P_IP, ETH_P_IPV6])
1773 p = (Ether(src=ep.mac, dst=l['mac']) /
1774 IP(dst=l['ip'], src=ep.ip4.address) /
1775 UDP(sport=1234, dport=1234) /
1778 self.send_and_expect(self.pg0, [p], self.pg2)
1781 # send UU packets from the local EP
1783 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1784 self.logger.info(self.vapi.cli("sh gbp bridge"))
1785 p_uu = (Ether(src=ep.mac, dst="00:11:11:11:11:11") /
1786 IP(dst="10.0.0.133", src=ep.ip4.address) /
1787 UDP(sport=1234, dport=1234) /
1789 rxs = self.send_and_expect(ep.itf, [p_uu], gbd1.uu_fwd)
1791 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1793 p_bm = (Ether(src=ep.mac, dst="ff:ff:ff:ff:ff:ff") /
1794 IP(dst="10.0.0.133", src=ep.ip4.address) /
1795 UDP(sport=1234, dport=1234) /
1797 rxs = self.send_and_expect_only(ep.itf, [p_bm], tun_bm.mcast_itf)
1800 self.assertEqual(rx[IP].src, self.pg4.local_ip4)
1801 self.assertEqual(rx[IP].dst, "239.1.1.1")
1802 self.assertEqual(rx[UDP].dport, 48879)
1803 # the UDP source port is a random value for hashing
1804 self.assertEqual(rx[VXLAN].gpid, 112)
1805 self.assertEqual(rx[VXLAN].vni, 88)
1806 self.assertTrue(rx[VXLAN].flags.G)
1807 self.assertTrue(rx[VXLAN].flags.Instance)
1808 self.assertFalse(rx[VXLAN].gpflags.A)
1809 self.assertFalse(rx[VXLAN].gpflags.D)
1812 # Check v6 Endpoints
1815 # a packet with an sclass from a knwon EPG
1816 p = (Ether(src=self.pg2.remote_mac,
1817 dst=self.pg2.local_mac) /
1818 IP(src=self.pg2.remote_hosts[1].ip4,
1819 dst=self.pg2.local_ip4) /
1820 UDP(sport=1234, dport=48879) /
1821 VXLAN(vni=99, gpid=113, flags=0x88, gpflags='A') /
1822 Ether(src=l['mac'], dst=ep.mac) /
1823 IPv6(src=l['ip6'], dst=ep.ip6.address) /
1824 UDP(sport=1234, dport=1234) /
1827 rx = self.send_and_expect(self.pg2, p*65, self.pg0)
1829 self.assertTrue(find_gbp_endpoint(self,
1830 vx_tun_l2_1.sw_if_index,
1834 # L3 Endpoint Learning
1835 # - configured on the bridge's BVI
1842 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1845 self.pg2.unconfig_ip4()
1846 self.pg3.unconfig_ip4()
1847 self.pg4.unconfig_ip4()
1849 self.logger.info(self.vapi.cli("sh int"))
1850 self.logger.info(self.vapi.cli("sh gbp vxlan"))
1852 def test_gbp_learn_vlan_l2(self):
1853 """ GBP L2 Endpoint w/ VLANs"""
1855 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
1856 learnt = [{'mac': '00:00:11:11:11:01',
1858 'ip6': '2001:10::2'},
1859 {'mac': '00:00:11:11:11:02',
1861 'ip6': '2001:10::3'}]
1864 # lower the inactive threshold so these tests pass in a
1865 # reasonable amount of time
1867 self.vapi.gbp_endpoint_learn_set_inactive_threshold(2)
1872 gt4 = VppIpTable(self, 1)
1873 gt4.add_vpp_config()
1874 gt6 = VppIpTable(self, 1, is_ip6=True)
1875 gt6.add_vpp_config()
1877 rd1 = VppGbpRouteDomain(self, 1, gt4, gt6)
1878 rd1.add_vpp_config()
1881 # Pg2 hosts the vxlan tunnel, hosts on pg2 to act as TEPs
1883 self.pg2.config_ip4()
1884 self.pg2.resolve_arp()
1885 self.pg2.generate_remote_hosts(4)
1886 self.pg2.configure_ipv4_neighbors()
1887 self.pg3.config_ip4()
1888 self.pg3.resolve_arp()
1891 # The EP will be on a vlan sub-interface
1893 vlan_11 = VppDot1QSubint(self, self.pg0, 11)
1895 self.vapi.sw_interface_set_l2_tag_rewrite(vlan_11.sw_if_index,
1899 bd_uu_fwd = VppVxlanGbpTunnel(self, self.pg3.local_ip4,
1900 self.pg3.remote_ip4, 116)
1901 bd_uu_fwd.add_vpp_config()
1904 # a GBP bridge domain with a BVI and a UU-flood interface
1905 # The BD is marked as do not learn, so no endpoints are ever
1906 # learnt in this BD.
1908 bd1 = VppBridgeDomain(self, 1)
1909 bd1.add_vpp_config()
1910 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0, bd_uu_fwd,
1912 gbd1.add_vpp_config()
1914 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1915 self.logger.info(self.vapi.cli("sh gbp bridge"))
1917 # ... and has a /32 applied
1918 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
1919 ip_addr.add_vpp_config()
1922 # The Endpoint-group in which we are learning endpoints
1924 epg_220 = VppGbpEndpointGroup(self, 220, 441, rd1, gbd1,
1928 epg_220.add_vpp_config()
1931 # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
1934 vx_tun_l2_1 = VppGbpVxlanTunnel(
1935 self, 99, bd1.bd_id,
1936 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L2)
1937 vx_tun_l2_1.add_vpp_config()
1940 # A static endpoint that the learnt endpoints are trying to
1943 ep = VppGbpEndpoint(self, vlan_11,
1945 "10.0.0.127", "11.0.0.127",
1946 "2001:10::1", "3001::1")
1949 self.assertTrue(find_route(self, ep.ip4.address, 32, table_id=1))
1952 # Send to the static EP
1954 for ii, l in enumerate(learnt):
1955 # a packet with an sclass from a knwon EPG
1956 # arriving on an unknown TEP
1957 p = (Ether(src=self.pg2.remote_mac,
1958 dst=self.pg2.local_mac) /
1959 IP(src=self.pg2.remote_hosts[1].ip4,
1960 dst=self.pg2.local_ip4) /
1961 UDP(sport=1234, dport=48879) /
1962 VXLAN(vni=99, gpid=441, flags=0x88) /
1963 Ether(src=l['mac'], dst=ep.mac) /
1964 IP(src=l['ip'], dst=ep.ip4.address) /
1965 UDP(sport=1234, dport=1234) /
1968 rxs = self.send_and_expect(self.pg2, [p], self.pg0)
1971 # packet to EP has the EP's vlan tag
1974 self.assertEqual(rx[Dot1Q].vlan, 11)
1977 # the EP is not learnt since the BD setting prevents it
1980 self.assertFalse(find_gbp_endpoint(self,
1981 vx_tun_l2_1.sw_if_index,
1983 self.assertEqual(INDEX_INVALID,
1984 find_vxlan_gbp_tunnel(
1987 self.pg2.remote_hosts[1].ip4,
1990 self.assertEqual(len(self.vapi.gbp_endpoint_dump()), 1)
1994 # we didn't learn the remotes so they are sent to the UU-fwd
1997 p = (Ether(src=ep.mac, dst=l['mac']) /
1999 IP(dst=l['ip'], src=ep.ip4.address) /
2000 UDP(sport=1234, dport=1234) /
2003 rxs = self.send_and_expect(self.pg0, p * 17, self.pg3)
2006 self.assertEqual(rx[IP].src, self.pg3.local_ip4)
2007 self.assertEqual(rx[IP].dst, self.pg3.remote_ip4)
2008 self.assertEqual(rx[UDP].dport, 48879)
2009 # the UDP source port is a random value for hashing
2010 self.assertEqual(rx[VXLAN].gpid, 441)
2011 self.assertEqual(rx[VXLAN].vni, 116)
2012 self.assertTrue(rx[VXLAN].flags.G)
2013 self.assertTrue(rx[VXLAN].flags.Instance)
2014 self.assertFalse(rx[VXLAN].gpflags.A)
2015 self.assertFalse(rx[VXLAN].gpflags.D)
2017 self.pg2.unconfig_ip4()
2018 self.pg3.unconfig_ip4()
2020 def test_gbp_learn_l3(self):
2021 """ GBP L3 Endpoint Learning """
2023 self.vapi.cli("set logging class gbp debug")
2025 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
2026 routed_dst_mac = "00:0c:0c:0c:0c:0c"
2027 routed_src_mac = "00:22:bd:f8:19:ff"
2029 learnt = [{'mac': '00:00:11:11:11:02',
2031 'ip6': '2001:10::2'},
2032 {'mac': '00:00:11:11:11:03',
2034 'ip6': '2001:10::3'}]
2037 # lower the inactive threshold so these tests pass in a
2038 # reasonable amount of time
2040 self.vapi.gbp_endpoint_learn_set_inactive_threshold(2)
2045 t4 = VppIpTable(self, 1)
2047 t6 = VppIpTable(self, 1, True)
2050 tun_ip4_uu = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
2051 self.pg4.remote_ip4, 114)
2052 tun_ip6_uu = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
2053 self.pg4.remote_ip4, 116)
2054 tun_ip4_uu.add_vpp_config()
2055 tun_ip6_uu.add_vpp_config()
2057 rd1 = VppGbpRouteDomain(self, 2, t4, t6, tun_ip4_uu, tun_ip6_uu)
2058 rd1.add_vpp_config()
2060 self.loop0.set_mac(self.router_mac)
2063 # Bind the BVI to the RD
2065 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
2066 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
2069 # Pg2 hosts the vxlan tunnel
2070 # hosts on pg2 to act as TEPs
2074 self.pg2.config_ip4()
2075 self.pg2.resolve_arp()
2076 self.pg2.generate_remote_hosts(4)
2077 self.pg2.configure_ipv4_neighbors()
2078 self.pg3.config_ip4()
2079 self.pg3.resolve_arp()
2080 self.pg4.config_ip4()
2081 self.pg4.resolve_arp()
2084 # a GBP bridge domain with a BVI and a UU-flood interface
2086 bd1 = VppBridgeDomain(self, 1)
2087 bd1.add_vpp_config()
2088 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0, self.pg3)
2089 gbd1.add_vpp_config()
2091 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2092 self.logger.info(self.vapi.cli("sh gbp bridge"))
2093 self.logger.info(self.vapi.cli("sh gbp route"))
2095 # ... and has a /32 and /128 applied
2096 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2097 ip4_addr.add_vpp_config()
2098 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 128)
2099 ip6_addr.add_vpp_config()
2102 # The Endpoint-group in which we are learning endpoints
2104 epg_220 = VppGbpEndpointGroup(self, 220, 441, rd1, gbd1,
2108 epg_220.add_vpp_config()
2111 # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
2114 vx_tun_l3 = VppGbpVxlanTunnel(
2115 self, 101, rd1.rd_id,
2116 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3)
2117 vx_tun_l3.add_vpp_config()
2120 # A static endpoint that the learnt endpoints are trying to
2123 ep = VppGbpEndpoint(self, self.pg0,
2125 "10.0.0.127", "11.0.0.127",
2126 "2001:10::1", "3001::1")
2130 # learn some remote IPv4 EPs
2132 for ii, l in enumerate(learnt):
2133 # a packet with an sclass from a knwon EPG
2134 # arriving on an unknown TEP
2135 p = (Ether(src=self.pg2.remote_mac,
2136 dst=self.pg2.local_mac) /
2137 IP(src=self.pg2.remote_hosts[1].ip4,
2138 dst=self.pg2.local_ip4) /
2139 UDP(sport=1234, dport=48879) /
2140 VXLAN(vni=101, gpid=441, flags=0x88) /
2141 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2142 IP(src=l['ip'], dst=ep.ip4.address) /
2143 UDP(sport=1234, dport=1234) /
2146 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2149 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2152 self.pg2.remote_hosts[1].ip4,
2154 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2156 # endpoint learnt via the parent GBP-vxlan interface
2157 self.assertTrue(find_gbp_endpoint(self,
2158 vx_tun_l3._sw_if_index,
2162 # Static IPv4 EP replies to learnt
2165 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2166 IP(dst=l['ip'], src=ep.ip4.address) /
2167 UDP(sport=1234, dport=1234) /
2170 rxs = self.send_and_expect(self.pg0, p*1, self.pg2)
2173 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2174 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2175 self.assertEqual(rx[UDP].dport, 48879)
2176 # the UDP source port is a random value for hashing
2177 self.assertEqual(rx[VXLAN].gpid, 441)
2178 self.assertEqual(rx[VXLAN].vni, 101)
2179 self.assertTrue(rx[VXLAN].flags.G)
2180 self.assertTrue(rx[VXLAN].flags.Instance)
2181 self.assertTrue(rx[VXLAN].gpflags.A)
2182 self.assertFalse(rx[VXLAN].gpflags.D)
2184 inner = rx[VXLAN].payload
2186 self.assertEqual(inner[Ether].src, routed_src_mac)
2187 self.assertEqual(inner[Ether].dst, routed_dst_mac)
2188 self.assertEqual(inner[IP].src, ep.ip4.address)
2189 self.assertEqual(inner[IP].dst, l['ip'])
2192 self.assertFalse(find_gbp_endpoint(self,
2197 # learn some remote IPv6 EPs
2199 for ii, l in enumerate(learnt):
2200 # a packet with an sclass from a knwon EPG
2201 # arriving on an unknown TEP
2202 p = (Ether(src=self.pg2.remote_mac,
2203 dst=self.pg2.local_mac) /
2204 IP(src=self.pg2.remote_hosts[1].ip4,
2205 dst=self.pg2.local_ip4) /
2206 UDP(sport=1234, dport=48879) /
2207 VXLAN(vni=101, gpid=441, flags=0x88) /
2208 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2209 IPv6(src=l['ip6'], dst=ep.ip6.address) /
2210 UDP(sport=1234, dport=1234) /
2213 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2216 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2219 self.pg2.remote_hosts[1].ip4,
2221 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2223 self.logger.info(self.vapi.cli("show gbp bridge"))
2224 self.logger.info(self.vapi.cli("show vxlan-gbp tunnel"))
2225 self.logger.info(self.vapi.cli("show gbp vxlan"))
2226 self.logger.info(self.vapi.cli("show int addr"))
2228 # endpoint learnt via the TEP
2229 self.assertTrue(find_gbp_endpoint(self, ip=l['ip6']))
2231 self.logger.info(self.vapi.cli("show gbp endpoint"))
2232 self.logger.info(self.vapi.cli("show ip fib index 1 %s" % l['ip']))
2235 # Static EP replies to learnt
2238 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2239 IPv6(dst=l['ip6'], src=ep.ip6.address) /
2240 UDP(sport=1234, dport=1234) /
2243 rxs = self.send_and_expect(self.pg0, p*65, self.pg2)
2246 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2247 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2248 self.assertEqual(rx[UDP].dport, 48879)
2249 # the UDP source port is a random value for hashing
2250 self.assertEqual(rx[VXLAN].gpid, 441)
2251 self.assertEqual(rx[VXLAN].vni, 101)
2252 self.assertTrue(rx[VXLAN].flags.G)
2253 self.assertTrue(rx[VXLAN].flags.Instance)
2254 self.assertTrue(rx[VXLAN].gpflags.A)
2255 self.assertFalse(rx[VXLAN].gpflags.D)
2257 inner = rx[VXLAN].payload
2259 self.assertEqual(inner[Ether].src, routed_src_mac)
2260 self.assertEqual(inner[Ether].dst, routed_dst_mac)
2261 self.assertEqual(inner[IPv6].src, ep.ip6.address)
2262 self.assertEqual(inner[IPv6].dst, l['ip6'])
2264 self.logger.info(self.vapi.cli("sh gbp endpoint"))
2266 self.wait_for_ep_timeout(ip=l['ip'])
2269 # Static sends to unknown EP with no route
2271 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2272 IP(dst="10.0.0.99", src=ep.ip4.address) /
2273 UDP(sport=1234, dport=1234) /
2276 self.send_and_assert_no_replies(self.pg0, [p])
2279 # Add a route to static EP's v4 and v6 subnet
2280 # packets should be sent on the v4/v6 uu=fwd interface resp.
2282 se_10_24 = VppGbpSubnet(
2283 self, rd1, "10.0.0.0", 24,
2284 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT)
2285 se_10_24.add_vpp_config()
2287 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2288 IP(dst="10.0.0.99", src=ep.ip4.address) /
2289 UDP(sport=1234, dport=1234) /
2292 rxs = self.send_and_expect(self.pg0, [p], self.pg4)
2294 self.assertEqual(rx[IP].src, self.pg4.local_ip4)
2295 self.assertEqual(rx[IP].dst, self.pg4.remote_ip4)
2296 self.assertEqual(rx[UDP].dport, 48879)
2297 # the UDP source port is a random value for hashing
2298 self.assertEqual(rx[VXLAN].gpid, 441)
2299 self.assertEqual(rx[VXLAN].vni, 114)
2300 self.assertTrue(rx[VXLAN].flags.G)
2301 self.assertTrue(rx[VXLAN].flags.Instance)
2302 # policy is not applied to packets sent to the uu-fwd interfaces
2303 self.assertFalse(rx[VXLAN].gpflags.A)
2304 self.assertFalse(rx[VXLAN].gpflags.D)
2307 # learn some remote IPv4 EPs
2309 for ii, l in enumerate(learnt):
2310 # a packet with an sclass from a knwon EPG
2311 # arriving on an unknown TEP
2312 p = (Ether(src=self.pg2.remote_mac,
2313 dst=self.pg2.local_mac) /
2314 IP(src=self.pg2.remote_hosts[2].ip4,
2315 dst=self.pg2.local_ip4) /
2316 UDP(sport=1234, dport=48879) /
2317 VXLAN(vni=101, gpid=441, flags=0x88) /
2318 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2319 IP(src=l['ip'], dst=ep.ip4.address) /
2320 UDP(sport=1234, dport=1234) /
2323 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2326 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2329 self.pg2.remote_hosts[2].ip4,
2331 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2333 # endpoint learnt via the parent GBP-vxlan interface
2334 self.assertTrue(find_gbp_endpoint(self,
2335 vx_tun_l3._sw_if_index,
2339 # Add a remote endpoint from the API
2341 rep_88 = VppGbpEndpoint(self, vx_tun_l3,
2343 "10.0.0.88", "11.0.0.88",
2344 "2001:10::88", "3001::88",
2345 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
2347 self.pg2.remote_hosts[1].ip4,
2349 rep_88.add_vpp_config()
2352 # Add a remote endpoint from the API that matches an existing one
2354 rep_2 = VppGbpEndpoint(self, vx_tun_l3,
2356 learnt[0]['ip'], "11.0.0.101",
2357 learnt[0]['ip6'], "3001::101",
2358 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
2360 self.pg2.remote_hosts[1].ip4,
2362 rep_2.add_vpp_config()
2365 # Add a route to the leanred EP's v4 subnet
2366 # packets should be send on the v4/v6 uu=fwd interface resp.
2368 se_10_1_24 = VppGbpSubnet(
2369 self, rd1, "10.0.1.0", 24,
2370 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT)
2371 se_10_1_24.add_vpp_config()
2373 self.logger.info(self.vapi.cli("show gbp endpoint"))
2375 ips = ["10.0.0.88", learnt[0]['ip']]
2377 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2378 IP(dst=ip, src=ep.ip4.address) /
2379 UDP(sport=1234, dport=1234) /
2382 rxs = self.send_and_expect(self.pg0, p*65, self.pg2)
2385 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2386 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2387 self.assertEqual(rx[UDP].dport, 48879)
2388 # the UDP source port is a random value for hashing
2389 self.assertEqual(rx[VXLAN].gpid, 441)
2390 self.assertEqual(rx[VXLAN].vni, 101)
2391 self.assertTrue(rx[VXLAN].flags.G)
2392 self.assertTrue(rx[VXLAN].flags.Instance)
2393 self.assertTrue(rx[VXLAN].gpflags.A)
2394 self.assertFalse(rx[VXLAN].gpflags.D)
2396 inner = rx[VXLAN].payload
2398 self.assertEqual(inner[Ether].src, routed_src_mac)
2399 self.assertEqual(inner[Ether].dst, routed_dst_mac)
2400 self.assertEqual(inner[IP].src, ep.ip4.address)
2401 self.assertEqual(inner[IP].dst, ip)
2404 # remove the API remote EPs, only API sourced is gone, the DP
2405 # learnt one remains
2407 rep_88.remove_vpp_config()
2408 rep_2.remove_vpp_config()
2410 self.assertTrue(find_gbp_endpoint(self, ip=rep_2.ip4.address))
2412 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2413 IP(src=ep.ip4.address, dst=rep_2.ip4.address) /
2414 UDP(sport=1234, dport=1234) /
2416 rxs = self.send_and_expect(self.pg0, [p], self.pg2)
2418 self.assertFalse(find_gbp_endpoint(self, ip=rep_88.ip4.address))
2420 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2421 IP(src=ep.ip4.address, dst=rep_88.ip4.address) /
2422 UDP(sport=1234, dport=1234) /
2424 rxs = self.send_and_expect(self.pg0, [p], self.pg4)
2427 # to appease the testcase we cannot have the registered EP stll
2428 # present (because it's DP learnt) when the TC ends so wait until
2431 self.wait_for_ep_timeout(ip=rep_88.ip4.address)
2432 self.wait_for_ep_timeout(ip=rep_2.ip4.address)
2435 # shutdown with learnt endpoint present
2437 p = (Ether(src=self.pg2.remote_mac,
2438 dst=self.pg2.local_mac) /
2439 IP(src=self.pg2.remote_hosts[1].ip4,
2440 dst=self.pg2.local_ip4) /
2441 UDP(sport=1234, dport=48879) /
2442 VXLAN(vni=101, gpid=441, flags=0x88) /
2443 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2444 IP(src=learnt[1]['ip'], dst=ep.ip4.address) /
2445 UDP(sport=1234, dport=1234) /
2448 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2450 # endpoint learnt via the parent GBP-vxlan interface
2451 self.assertTrue(find_gbp_endpoint(self,
2452 vx_tun_l3._sw_if_index,
2457 # remote endpoint becomes local
2459 self.pg2.unconfig_ip4()
2460 self.pg3.unconfig_ip4()
2461 self.pg4.unconfig_ip4()
2463 def test_gbp_redirect(self):
2464 """ GBP Endpoint Redirect """
2466 self.vapi.cli("set logging class gbp debug")
2468 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
2469 routed_dst_mac = "00:0c:0c:0c:0c:0c"
2470 routed_src_mac = "00:22:bd:f8:19:ff"
2472 learnt = [{'mac': '00:00:11:11:11:02',
2474 'ip6': '2001:10::2'},
2475 {'mac': '00:00:11:11:11:03',
2477 'ip6': '2001:10::3'}]
2480 # lower the inactive threshold so these tests pass in a
2481 # reasonable amount of time
2483 self.vapi.gbp_endpoint_learn_set_inactive_threshold(2)
2488 t4 = VppIpTable(self, 1)
2490 t6 = VppIpTable(self, 1, True)
2493 rd1 = VppGbpRouteDomain(self, 2, t4, t6)
2494 rd1.add_vpp_config()
2496 self.loop0.set_mac(self.router_mac)
2499 # Bind the BVI to the RD
2501 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
2502 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
2505 # Pg7 hosts a BD's UU-fwd
2507 self.pg7.config_ip4()
2508 self.pg7.resolve_arp()
2511 # a GBP bridge domains for the EPs
2513 bd1 = VppBridgeDomain(self, 1)
2514 bd1.add_vpp_config()
2515 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0)
2516 gbd1.add_vpp_config()
2518 bd2 = VppBridgeDomain(self, 2)
2519 bd2.add_vpp_config()
2520 gbd2 = VppGbpBridgeDomain(self, bd2, self.loop1)
2521 gbd2.add_vpp_config()
2523 # ... and has a /32 and /128 applied
2524 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2525 ip4_addr.add_vpp_config()
2526 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 128)
2527 ip6_addr.add_vpp_config()
2528 ip4_addr = VppIpInterfaceAddress(self, gbd2.bvi, "10.0.1.128", 32)
2529 ip4_addr.add_vpp_config()
2530 ip6_addr = VppIpInterfaceAddress(self, gbd2.bvi, "2001:11::128", 128)
2531 ip6_addr.add_vpp_config()
2534 # The Endpoint-groups in which we are learning endpoints
2536 epg_220 = VppGbpEndpointGroup(self, 220, 440, rd1, gbd1,
2540 epg_220.add_vpp_config()
2541 epg_221 = VppGbpEndpointGroup(self, 221, 441, rd1, gbd2,
2545 epg_221.add_vpp_config()
2546 epg_222 = VppGbpEndpointGroup(self, 222, 442, rd1, gbd1,
2550 epg_222.add_vpp_config()
2553 # a GBP bridge domains for the SEPs
2555 bd_uu1 = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
2556 self.pg7.remote_ip4, 116)
2557 bd_uu1.add_vpp_config()
2558 bd_uu2 = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
2559 self.pg7.remote_ip4, 117)
2560 bd_uu2.add_vpp_config()
2562 bd3 = VppBridgeDomain(self, 3)
2563 bd3.add_vpp_config()
2564 gbd3 = VppGbpBridgeDomain(self, bd3, self.loop2, bd_uu1, learn=False)
2565 gbd3.add_vpp_config()
2566 bd4 = VppBridgeDomain(self, 4)
2567 bd4.add_vpp_config()
2568 gbd4 = VppGbpBridgeDomain(self, bd4, self.loop3, bd_uu2, learn=False)
2569 gbd4.add_vpp_config()
2572 # EPGs in which the service endpoints exist
2574 epg_320 = VppGbpEndpointGroup(self, 320, 550, rd1, gbd3,
2578 epg_320.add_vpp_config()
2579 epg_321 = VppGbpEndpointGroup(self, 321, 551, rd1, gbd4,
2583 epg_321.add_vpp_config()
2586 # three local endpoints
2588 ep1 = VppGbpEndpoint(self, self.pg0,
2590 "10.0.0.1", "11.0.0.1",
2591 "2001:10::1", "3001:10::1")
2592 ep1.add_vpp_config()
2593 ep2 = VppGbpEndpoint(self, self.pg1,
2595 "10.0.1.1", "11.0.1.1",
2596 "2001:11::1", "3001:11::1")
2597 ep2.add_vpp_config()
2598 ep3 = VppGbpEndpoint(self, self.pg2,
2600 "10.0.2.2", "11.0.2.2",
2601 "2001:12::1", "3001:12::1")
2602 ep3.add_vpp_config()
2607 sep1 = VppGbpEndpoint(self, self.pg3,
2609 "12.0.0.1", "13.0.0.1",
2610 "4001:10::1", "5001:10::1")
2611 sep1.add_vpp_config()
2612 sep2 = VppGbpEndpoint(self, self.pg4,
2614 "12.0.0.2", "13.0.0.2",
2615 "4001:10::2", "5001:10::2")
2616 sep2.add_vpp_config()
2617 sep3 = VppGbpEndpoint(self, self.pg5,
2619 "12.0.1.1", "13.0.1.1",
2620 "4001:11::1", "5001:11::1")
2621 sep3.add_vpp_config()
2622 # this EP is not installed immediately
2623 sep4 = VppGbpEndpoint(self, self.pg6,
2625 "12.0.1.2", "13.0.1.2",
2626 "4001:11::2", "5001:11::2")
2629 # an L2 switch packet between local EPs in different EPGs
2630 # different dest ports on each so the are LB hashed differently
2632 p4 = [(Ether(src=ep1.mac, dst=ep3.mac) /
2633 IP(src=ep1.ip4.address, dst=ep3.ip4.address) /
2634 UDP(sport=1234, dport=1234) /
2636 (Ether(src=ep3.mac, dst=ep1.mac) /
2637 IP(src=ep3.ip4.address, dst=ep1.ip4.address) /
2638 UDP(sport=1234, dport=1234) /
2640 p6 = [(Ether(src=ep1.mac, dst=ep3.mac) /
2641 IPv6(src=ep1.ip6.address, dst=ep3.ip6.address) /
2642 UDP(sport=1234, dport=1234) /
2644 (Ether(src=ep3.mac, dst=ep1.mac) /
2645 IPv6(src=ep3.ip6.address, dst=ep1.ip6.address) /
2646 UDP(sport=1234, dport=1230) /
2649 # should be dropped since no contract yet
2650 self.send_and_assert_no_replies(self.pg0, [p4[0]])
2651 self.send_and_assert_no_replies(self.pg0, [p6[0]])
2654 # Add a contract with a rule to load-balance redirect via SEP1 and SEP2
2655 # one of the next-hops is via an EP that is not known
2657 acl = VppGbpAcl(self)
2658 rule4 = acl.create_rule(permit_deny=1, proto=17)
2659 rule6 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
2660 acl_index = acl.add_vpp_config([rule4, rule6])
2663 # test the src-ip hash mode
2665 c1 = VppGbpContract(
2666 self, 220, 222, acl_index,
2667 [VppGbpContractRule(
2668 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2669 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2670 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
2671 sep1.ip4, sep1.epg.rd),
2672 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
2673 sep2.ip4, sep2.epg.rd)]),
2675 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2676 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2677 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
2678 sep3.ip6, sep3.epg.rd),
2679 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
2680 sep4.ip6, sep4.epg.rd)])],
2681 [ETH_P_IP, ETH_P_IPV6])
2684 c2 = VppGbpContract(
2685 self, 222, 220, acl_index,
2686 [VppGbpContractRule(
2687 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2688 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2689 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
2690 sep1.ip4, sep1.epg.rd),
2691 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
2692 sep2.ip4, sep2.epg.rd)]),
2694 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2695 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2696 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
2697 sep3.ip6, sep3.epg.rd),
2698 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
2699 sep4.ip6, sep4.epg.rd)])],
2700 [ETH_P_IP, ETH_P_IPV6])
2704 # send again with the contract preset, now packets arrive
2705 # at SEP1 or SEP2 depending on the hashing
2707 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
2710 self.assertEqual(rx[Ether].src, routed_src_mac)
2711 self.assertEqual(rx[Ether].dst, sep1.mac)
2712 self.assertEqual(rx[IP].src, ep1.ip4.address)
2713 self.assertEqual(rx[IP].dst, ep3.ip4.address)
2715 rxs = self.send_and_expect(self.pg2, p4[1] * 17, sep2.itf)
2718 self.assertEqual(rx[Ether].src, routed_src_mac)
2719 self.assertEqual(rx[Ether].dst, sep2.mac)
2720 self.assertEqual(rx[IP].src, ep3.ip4.address)
2721 self.assertEqual(rx[IP].dst, ep1.ip4.address)
2723 rxs = self.send_and_expect(self.pg0, p6[0] * 17, self.pg7)
2726 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
2727 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
2728 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
2729 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
2730 self.assertEqual(rx[VXLAN].vni, 117)
2731 self.assertTrue(rx[VXLAN].flags.G)
2732 self.assertTrue(rx[VXLAN].flags.Instance)
2733 # redirect policy has been applied
2734 self.assertTrue(rx[VXLAN].gpflags.A)
2735 self.assertFalse(rx[VXLAN].gpflags.D)
2737 inner = rx[VXLAN].payload
2739 self.assertEqual(inner[Ether].src, routed_src_mac)
2740 self.assertEqual(inner[Ether].dst, sep4.mac)
2741 self.assertEqual(inner[IPv6].src, ep1.ip6.address)
2742 self.assertEqual(inner[IPv6].dst, ep3.ip6.address)
2744 rxs = self.send_and_expect(self.pg2, p6[1] * 17, sep3.itf)
2747 self.assertEqual(rx[Ether].src, routed_src_mac)
2748 self.assertEqual(rx[Ether].dst, sep3.mac)
2749 self.assertEqual(rx[IPv6].src, ep3.ip6.address)
2750 self.assertEqual(rx[IPv6].dst, ep1.ip6.address)
2753 # programme the unknown EP
2755 sep4.add_vpp_config()
2757 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep4.itf)
2760 self.assertEqual(rx[Ether].src, routed_src_mac)
2761 self.assertEqual(rx[Ether].dst, sep4.mac)
2762 self.assertEqual(rx[IPv6].src, ep1.ip6.address)
2763 self.assertEqual(rx[IPv6].dst, ep3.ip6.address)
2766 # and revert back to unprogrammed
2768 sep4.remove_vpp_config()
2770 rxs = self.send_and_expect(self.pg0, p6[0] * 17, self.pg7)
2773 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
2774 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
2775 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
2776 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
2777 self.assertEqual(rx[VXLAN].vni, 117)
2778 self.assertTrue(rx[VXLAN].flags.G)
2779 self.assertTrue(rx[VXLAN].flags.Instance)
2780 # redirect policy has been applied
2781 self.assertTrue(rx[VXLAN].gpflags.A)
2782 self.assertFalse(rx[VXLAN].gpflags.D)
2784 inner = rx[VXLAN].payload
2786 self.assertEqual(inner[Ether].src, routed_src_mac)
2787 self.assertEqual(inner[Ether].dst, sep4.mac)
2788 self.assertEqual(inner[IPv6].src, ep1.ip6.address)
2789 self.assertEqual(inner[IPv6].dst, ep3.ip6.address)
2791 c1.remove_vpp_config()
2792 c2.remove_vpp_config()
2795 # test the symmetric hash mode
2797 c1 = VppGbpContract(
2798 self, 220, 222, acl_index,
2799 [VppGbpContractRule(
2800 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2801 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
2802 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
2803 sep1.ip4, sep1.epg.rd),
2804 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
2805 sep2.ip4, sep2.epg.rd)]),
2807 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2808 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
2809 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
2810 sep3.ip6, sep3.epg.rd),
2811 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
2812 sep4.ip6, sep4.epg.rd)])],
2813 [ETH_P_IP, ETH_P_IPV6])
2816 c2 = VppGbpContract(
2817 self, 222, 220, acl_index,
2818 [VppGbpContractRule(
2819 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2820 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
2821 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
2822 sep1.ip4, sep1.epg.rd),
2823 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
2824 sep2.ip4, sep2.epg.rd)]),
2826 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2827 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
2828 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
2829 sep3.ip6, sep3.epg.rd),
2830 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
2831 sep4.ip6, sep4.epg.rd)])],
2832 [ETH_P_IP, ETH_P_IPV6])
2836 # send again with the contract preset, now packets arrive
2837 # at SEP1 for both directions
2839 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
2842 self.assertEqual(rx[Ether].src, routed_src_mac)
2843 self.assertEqual(rx[Ether].dst, sep1.mac)
2844 self.assertEqual(rx[IP].src, ep1.ip4.address)
2845 self.assertEqual(rx[IP].dst, ep3.ip4.address)
2847 rxs = self.send_and_expect(self.pg2, p4[1] * 17, sep1.itf)
2850 self.assertEqual(rx[Ether].src, routed_src_mac)
2851 self.assertEqual(rx[Ether].dst, sep1.mac)
2852 self.assertEqual(rx[IP].src, ep3.ip4.address)
2853 self.assertEqual(rx[IP].dst, ep1.ip4.address)
2856 # programme the unknown EP for the L3 tests
2858 sep4.add_vpp_config()
2861 # an L3 switch packet between local EPs in different EPGs
2862 # different dest ports on each so the are LB hashed differently
2864 p4 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
2865 IP(src=ep1.ip4.address, dst=ep2.ip4.address) /
2866 UDP(sport=1234, dport=1234) /
2868 (Ether(src=ep2.mac, dst=str(self.router_mac)) /
2869 IP(src=ep2.ip4.address, dst=ep1.ip4.address) /
2870 UDP(sport=1234, dport=1234) /
2872 p6 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
2873 IPv6(src=ep1.ip6.address, dst=ep2.ip6.address) /
2874 UDP(sport=1234, dport=1234) /
2876 (Ether(src=ep2.mac, dst=str(self.router_mac)) /
2877 IPv6(src=ep2.ip6.address, dst=ep1.ip6.address) /
2878 UDP(sport=1234, dport=1234) /
2881 c3 = VppGbpContract(
2882 self, 220, 221, acl_index,
2883 [VppGbpContractRule(
2884 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2885 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
2886 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
2887 sep1.ip4, sep1.epg.rd),
2888 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
2889 sep2.ip4, sep2.epg.rd)]),
2891 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2892 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
2893 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
2894 sep3.ip6, sep3.epg.rd),
2895 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
2896 sep4.ip6, sep4.epg.rd)])],
2897 [ETH_P_IP, ETH_P_IPV6])
2900 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
2903 self.assertEqual(rx[Ether].src, routed_src_mac)
2904 self.assertEqual(rx[Ether].dst, sep1.mac)
2905 self.assertEqual(rx[IP].src, ep1.ip4.address)
2906 self.assertEqual(rx[IP].dst, ep2.ip4.address)
2909 # learn a remote EP in EPG 221
2911 vx_tun_l3 = VppGbpVxlanTunnel(
2912 self, 444, rd1.rd_id,
2913 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3)
2914 vx_tun_l3.add_vpp_config()
2916 c4 = VppGbpContract(
2917 self, 221, 220, acl_index,
2918 [VppGbpContractRule(
2919 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2922 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2924 [ETH_P_IP, ETH_P_IPV6])
2927 p = (Ether(src=self.pg7.remote_mac,
2928 dst=self.pg7.local_mac) /
2929 IP(src=self.pg7.remote_ip4,
2930 dst=self.pg7.local_ip4) /
2931 UDP(sport=1234, dport=48879) /
2932 VXLAN(vni=444, gpid=441, flags=0x88) /
2933 Ether(src="00:22:22:22:22:33", dst=str(self.router_mac)) /
2934 IP(src="10.0.0.88", dst=ep1.ip4.address) /
2935 UDP(sport=1234, dport=1234) /
2938 rx = self.send_and_expect(self.pg7, [p], self.pg0)
2940 # endpoint learnt via the parent GBP-vxlan interface
2941 self.assertTrue(find_gbp_endpoint(self,
2942 vx_tun_l3._sw_if_index,
2945 p = (Ether(src=self.pg7.remote_mac,
2946 dst=self.pg7.local_mac) /
2947 IP(src=self.pg7.remote_ip4,
2948 dst=self.pg7.local_ip4) /
2949 UDP(sport=1234, dport=48879) /
2950 VXLAN(vni=444, gpid=441, flags=0x88) /
2951 Ether(src="00:22:22:22:22:33", dst=str(self.router_mac)) /
2952 IPv6(src="2001:10::88", dst=ep1.ip6.address) /
2953 UDP(sport=1234, dport=1234) /
2956 rx = self.send_and_expect(self.pg7, [p], self.pg0)
2958 # endpoint learnt via the parent GBP-vxlan interface
2959 self.assertTrue(find_gbp_endpoint(self,
2960 vx_tun_l3._sw_if_index,
2964 # L3 switch from local to remote EP
2966 p4 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
2967 IP(src=ep1.ip4.address, dst="10.0.0.88") /
2968 UDP(sport=1234, dport=1234) /
2970 p6 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
2971 IPv6(src=ep1.ip6.address, dst="2001:10::88") /
2972 UDP(sport=1234, dport=1234) /
2975 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
2978 self.assertEqual(rx[Ether].src, routed_src_mac)
2979 self.assertEqual(rx[Ether].dst, sep1.mac)
2980 self.assertEqual(rx[IP].src, ep1.ip4.address)
2981 self.assertEqual(rx[IP].dst, "10.0.0.88")
2983 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep4.itf)
2986 self.assertEqual(rx[Ether].src, routed_src_mac)
2987 self.assertEqual(rx[Ether].dst, sep4.mac)
2988 self.assertEqual(rx[IPv6].src, ep1.ip6.address)
2989 self.assertEqual(rx[IPv6].dst, "2001:10::88")
2992 # test the dst-ip hash mode
2994 c5 = VppGbpContract(
2995 self, 220, 221, acl_index,
2996 [VppGbpContractRule(
2997 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2998 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
2999 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3000 sep1.ip4, sep1.epg.rd),
3001 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3002 sep2.ip4, sep2.epg.rd)]),
3004 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3005 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
3006 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3007 sep3.ip6, sep3.epg.rd),
3008 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3009 sep4.ip6, sep4.epg.rd)])],
3010 [ETH_P_IP, ETH_P_IPV6])
3013 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3016 self.assertEqual(rx[Ether].src, routed_src_mac)
3017 self.assertEqual(rx[Ether].dst, sep1.mac)
3018 self.assertEqual(rx[IP].src, ep1.ip4.address)
3019 self.assertEqual(rx[IP].dst, "10.0.0.88")
3021 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep3.itf)
3024 self.assertEqual(rx[Ether].src, routed_src_mac)
3025 self.assertEqual(rx[Ether].dst, sep3.mac)
3026 self.assertEqual(rx[IPv6].src, ep1.ip6.address)
3027 self.assertEqual(rx[IPv6].dst, "2001:10::88")
3032 self.pg7.unconfig_ip4()
3034 def test_gbp_l3_out(self):
3037 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
3038 self.vapi.cli("set logging class gbp debug")
3040 routed_dst_mac = "00:0c:0c:0c:0c:0c"
3041 routed_src_mac = "00:22:bd:f8:19:ff"
3046 t4 = VppIpTable(self, 1)
3048 t6 = VppIpTable(self, 1, True)
3051 rd1 = VppGbpRouteDomain(self, 2, t4, t6)
3052 rd1.add_vpp_config()
3054 self.loop0.set_mac(self.router_mac)
3057 # Bind the BVI to the RD
3059 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
3060 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
3063 # Pg7 hosts a BD's BUM
3064 # Pg1 some other l3 interface
3066 self.pg7.config_ip4()
3067 self.pg7.resolve_arp()
3070 # a multicast vxlan-gbp tunnel for broadcast in the BD
3072 tun_bm = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
3075 tun_bm.add_vpp_config()
3078 # a GBP external bridge domains for the EPs
3080 bd1 = VppBridgeDomain(self, 1)
3081 bd1.add_vpp_config()
3082 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0, None, tun_bm)
3083 gbd1.add_vpp_config()
3086 # The Endpoint-groups in which the external endpoints exist
3088 epg_220 = VppGbpEndpointGroup(self, 220, 113, rd1, gbd1,
3092 epg_220.add_vpp_config()
3094 # the BVIs have the subnets applied ...
3095 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 24)
3096 ip4_addr.add_vpp_config()
3097 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 64)
3098 ip6_addr.add_vpp_config()
3100 # ... which are L3-out subnets
3101 l3o_1 = VppGbpSubnet(
3102 self, rd1, "10.0.0.0", 24,
3103 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3105 l3o_1.add_vpp_config()
3108 # an external interface attached to the outside world and the
3111 vlan_100 = VppDot1QSubint(self, self.pg0, 100)
3113 ext_itf = VppGbpExtItf(self, vlan_100, bd1, rd1)
3114 ext_itf.add_vpp_config()
3117 # an unicast vxlan-gbp for inter-RD traffic
3119 vx_tun_l3 = VppGbpVxlanTunnel(
3120 self, 444, rd1.rd_id,
3121 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3)
3122 vx_tun_l3.add_vpp_config()
3125 # packets destined to unkown addresses in the BVI's subnet
3128 p4 = (Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
3130 IP(src="10.0.0.1", dst="10.0.0.88") /
3131 UDP(sport=1234, dport=1234) /
3133 p6 = (Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
3135 IPv6(src="2001:10::1", dst="2001:10::88") /
3136 UDP(sport=1234, dport=1234) /
3139 rxs = self.send_and_expect(self.pg0, p4 * 1, self.pg7)
3142 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3143 # self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3144 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3145 self.assertEqual(rx[IP].dst, "239.1.1.1")
3146 self.assertEqual(rx[VXLAN].vni, 88)
3147 self.assertTrue(rx[VXLAN].flags.G)
3148 self.assertTrue(rx[VXLAN].flags.Instance)
3149 # policy was applied to the original IP packet
3150 self.assertEqual(rx[VXLAN].gpid, 113)
3151 self.assertTrue(rx[VXLAN].gpflags.A)
3152 self.assertFalse(rx[VXLAN].gpflags.D)
3154 inner = rx[VXLAN].payload
3156 self.assertTrue(inner.haslayer(ARP))
3159 # An external Endpoint
3161 eep = VppGbpEndpoint(self, vlan_100,
3163 "10.0.0.1", "11.0.0.1",
3164 "2001:10::1", "3001::1",
3165 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
3166 eep.add_vpp_config()
3171 rep = VppGbpEndpoint(self, vx_tun_l3,
3173 "10.0.0.101", "11.0.0.101",
3174 "2001:10::101", "3001::101",
3175 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
3177 self.pg7.remote_ip4,
3179 rep.add_vpp_config()
3182 # remote to external
3184 p = (Ether(src=self.pg7.remote_mac,
3185 dst=self.pg7.local_mac) /
3186 IP(src=self.pg7.remote_ip4,
3187 dst=self.pg7.local_ip4) /
3188 UDP(sport=1234, dport=48879) /
3189 VXLAN(vni=444, gpid=113, flags=0x88) /
3190 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
3191 IP(src="10.0.0.101", dst="10.0.0.1") /
3192 UDP(sport=1234, dport=1234) /
3195 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
3198 # A subnet reachable through the external EP
3200 ip_220 = VppIpRoute(self, "10.220.0.0", 24,
3201 [VppRoutePath(eep.ip4.address,
3202 eep.epg.bvi.sw_if_index)],
3203 table_id=t4.table_id)
3204 ip_220.add_vpp_config()
3206 l3o_220 = VppGbpSubnet(
3207 self, rd1, "10.220.0.0", 24,
3208 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3210 l3o_220.add_vpp_config()
3212 p = (Ether(src=self.pg7.remote_mac,
3213 dst=self.pg7.local_mac) /
3214 IP(src=self.pg7.remote_ip4,
3215 dst=self.pg7.local_ip4) /
3216 UDP(sport=1234, dport=48879) /
3217 VXLAN(vni=444, gpid=113, flags=0x88) /
3218 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
3219 IP(src="10.0.0.101", dst="10.220.0.1") /
3220 UDP(sport=1234, dport=1234) /
3223 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
3228 self.pg7.unconfig_ip4()
3231 if __name__ == '__main__':
3232 unittest.main(testRunner=VppTestRunner)