5 from framework import VppTestCase, VppTestRunner
6 from vpp_object import VppObject
7 from vpp_neighbor import VppNeighbor
8 from vpp_ip_route import VppIpRoute, VppRoutePath, VppIpTable, \
9 VppIpInterfaceAddress, VppIpInterfaceBind, find_route
10 from vpp_l2 import VppBridgeDomain, VppBridgeDomainPort, \
11 VppBridgeDomainArpEntry, VppL2FibEntry, find_bridge_domain_port
12 from vpp_vxlan_gbp_tunnel import *
13 from vpp_sub_interface import VppDot1QSubint
16 from vpp_papi_provider import L2_PORT_TYPE
17 from vpp_papi import VppEnum, MACAddress
19 from scapy.packet import Raw
20 from scapy.layers.l2 import Ether, ARP, Dot1Q
21 from scapy.layers.inet import IP, UDP
22 from scapy.layers.inet6 import IPv6, ICMPv6ND_NS, ICMPv6NDOptSrcLLAddr, \
24 from scapy.utils6 import in6_getnsma, in6_getnsmac
25 from scapy.layers.vxlan import VXLAN
26 from scapy.data import ETH_P_IP, ETH_P_IPV6
28 from socket import AF_INET, AF_INET6
29 from scapy.utils import inet_pton, inet_ntop
30 from vpp_papi_provider import L2_VTR_OP
33 def find_gbp_endpoint(test, sw_if_index=None, ip=None, mac=None):
35 vip = VppIpAddress(ip)
37 vmac = MACAddress(mac)
39 eps = test.vapi.gbp_endpoint_dump()
43 if ep.endpoint.sw_if_index != sw_if_index:
46 for eip in ep.endpoint.ips:
50 if vmac.packed == ep.endpoint.mac:
55 def find_gbp_vxlan(test, vni):
56 ts = test.vapi.gbp_vxlan_tunnel_dump()
58 if t.tunnel.vni == vni:
63 class VppGbpEndpoint(VppObject):
74 return self.itf.remote_mac
94 return [self.ip4, self.ip6]
98 return [self.fip4, self.fip6]
100 def __init__(self, test, itf, epg, recirc, ip4, fip4, ip6, fip6,
110 self._ip4 = VppIpAddress(ip4)
111 self._fip4 = VppIpAddress(fip4)
112 self._ip6 = VppIpAddress(ip6)
113 self._fip6 = VppIpAddress(fip6)
116 self.vmac = MACAddress(self.itf.remote_mac)
118 self.vmac = MACAddress("00:00:00:00:00:00")
121 self.tun_src = VppIpAddress(tun_src)
122 self.tun_dst = VppIpAddress(tun_dst)
124 def add_vpp_config(self):
125 res = self._test.vapi.gbp_endpoint_add(
126 self.itf.sw_if_index,
127 [self.ip4.encode(), self.ip6.encode()],
131 self.tun_src.encode(),
132 self.tun_dst.encode())
133 self.handle = res.handle
134 self._test.registry.register(self, self._test.logger)
136 def remove_vpp_config(self):
137 self._test.vapi.gbp_endpoint_del(self.handle)
140 return self.object_id()
143 return "gbp-endpoint:[%d==%d:%s:%d]" % (self.handle,
144 self.itf.sw_if_index,
148 def query_vpp_config(self):
149 return find_gbp_endpoint(self._test,
150 self.itf.sw_if_index,
154 class VppGbpRecirc(VppObject):
156 GBP Recirculation Interface
159 def __init__(self, test, epg, recirc, is_ext=False):
165 def add_vpp_config(self):
166 self._test.vapi.gbp_recirc_add_del(
168 self.recirc.sw_if_index,
171 self._test.registry.register(self, self._test.logger)
173 def remove_vpp_config(self):
174 self._test.vapi.gbp_recirc_add_del(
176 self.recirc.sw_if_index,
181 return self.object_id()
184 return "gbp-recirc:[%d]" % (self.recirc.sw_if_index)
186 def query_vpp_config(self):
187 rs = self._test.vapi.gbp_recirc_dump()
189 if r.recirc.sw_if_index == self.recirc.sw_if_index:
194 class VppGbpExtItf(VppObject):
196 GBP ExtItfulation Interface
199 def __init__(self, test, itf, bd, rd):
205 def add_vpp_config(self):
206 self._test.vapi.gbp_ext_itf_add_del(
208 self.itf.sw_if_index,
211 self._test.registry.register(self, self._test.logger)
213 def remove_vpp_config(self):
214 self._test.vapi.gbp_ext_itf_add_del(
216 self.itf.sw_if_index,
221 return self.object_id()
224 return "gbp-ext-itf:[%d]" % (self.itf.sw_if_index)
226 def query_vpp_config(self):
227 rs = self._test.vapi.gbp_ext_itf_dump()
229 if r.ext_itf.sw_if_index == self.itf.sw_if_index:
234 class VppGbpSubnet(VppObject):
238 def __init__(self, test, rd, address, address_len,
239 type, sw_if_index=None, epg=None):
241 self.rd_id = rd.rd_id
242 self.prefix = VppIpPrefix(address, address_len)
244 self.sw_if_index = sw_if_index
247 def add_vpp_config(self):
248 self._test.vapi.gbp_subnet_add_del(
251 self.prefix.encode(),
253 sw_if_index=self.sw_if_index if self.sw_if_index else 0xffffffff,
254 epg_id=self.epg if self.epg else 0xffff)
255 self._test.registry.register(self, self._test.logger)
257 def remove_vpp_config(self):
258 self._test.vapi.gbp_subnet_add_del(
261 self.prefix.encode(),
265 return self.object_id()
268 return "gbp-subnet:[%d-%s]" % (self.rd_id, self.prefix)
270 def query_vpp_config(self):
271 ss = self._test.vapi.gbp_subnet_dump()
273 if s.subnet.rd_id == self.rd_id and \
274 s.subnet.type == self.type and \
275 s.subnet.prefix == self.prefix:
280 class VppGbpEndpointGroup(VppObject):
285 def __init__(self, test, epg, rd, bd, uplink,
286 bvi, bvi_ip4, bvi_ip6=None):
290 self.bvi_ip4 = VppIpAddress(bvi_ip4)
291 self.bvi_ip6 = VppIpAddress(bvi_ip6)
296 def add_vpp_config(self):
297 self._test.vapi.gbp_endpoint_group_add(
301 self.uplink.sw_if_index if self.uplink else INDEX_INVALID)
302 self._test.registry.register(self, self._test.logger)
304 def remove_vpp_config(self):
305 self._test.vapi.gbp_endpoint_group_del(
309 return self.object_id()
312 return "gbp-endpoint-group:[%d]" % (self.epg)
314 def query_vpp_config(self):
315 epgs = self._test.vapi.gbp_endpoint_group_dump()
317 if epg.epg.epg_id == self.epg:
322 class VppGbpBridgeDomain(VppObject):
327 def __init__(self, test, bd, bvi, uu_flood=None, learn=True):
330 self.uu_flood = uu_flood
333 e = VppEnum.vl_api_gbp_bridge_domain_flags_t
335 self.learn = e.GBP_BD_API_FLAG_NONE
337 self.learn = e.GBP_BD_API_FLAG_DO_NOT_LEARN
339 def add_vpp_config(self):
340 self._test.vapi.gbp_bridge_domain_add(
343 self.bvi.sw_if_index,
344 self.uu_flood.sw_if_index if self.uu_flood else INDEX_INVALID)
345 self._test.registry.register(self, self._test.logger)
347 def remove_vpp_config(self):
348 self._test.vapi.gbp_bridge_domain_del(self.bd.bd_id)
351 return self.object_id()
354 return "gbp-bridge-domain:[%d]" % (self.bd.bd_id)
356 def query_vpp_config(self):
357 bds = self._test.vapi.gbp_bridge_domain_dump()
359 if bd.bd.bd_id == self.bd.bd_id:
364 class VppGbpRouteDomain(VppObject):
369 def __init__(self, test, rd_id, t4, t6, ip4_uu=None, ip6_uu=None):
377 def add_vpp_config(self):
378 self._test.vapi.gbp_route_domain_add(
382 self.ip4_uu.sw_if_index if self.ip4_uu else INDEX_INVALID,
383 self.ip6_uu.sw_if_index if self.ip6_uu else INDEX_INVALID)
384 self._test.registry.register(self, self._test.logger)
386 def remove_vpp_config(self):
387 self._test.vapi.gbp_route_domain_del(self.rd_id)
390 return self.object_id()
393 return "gbp-route-domain:[%d]" % (self.rd_id)
395 def query_vpp_config(self):
396 rds = self._test.vapi.gbp_route_domain_dump()
398 if rd.rd.rd_id == self.rd_id:
403 class VppGbpContractNextHop():
404 def __init__(self, mac, bd, ip, rd):
411 return {'ip': self.ip.encode(),
412 'mac': self.mac.packed,
413 'bd_id': self.bd.bd.bd_id,
414 'rd_id': self.rd.rd_id}
417 class VppGbpContractRule():
418 def __init__(self, action, hash_mode, nhs=[]):
420 self.hash_mode = hash_mode
426 nhs.append(nh.encode())
429 return {'action': self.action,
431 'hash_mode': self.hash_mode,
432 'n_nhs': len(self.nhs),
436 class VppGbpContract(VppObject):
441 def __init__(self, test, src_epg, dst_epg, acl_index,
442 rules, allowed_ethertypes):
444 self.acl_index = acl_index
445 self.src_epg = src_epg
446 self.dst_epg = dst_epg
448 self.allowed_ethertypes = allowed_ethertypes
450 def add_vpp_config(self):
453 rules.append(r.encode())
454 self._test.vapi.gbp_contract_add_del(
460 self.allowed_ethertypes)
461 self._test.registry.register(self, self._test.logger)
463 def remove_vpp_config(self):
464 self._test.vapi.gbp_contract_add_del(
472 return self.object_id()
475 return "gbp-contract:[%d:%s:%d]" % (self.src_epg,
479 def query_vpp_config(self):
480 cs = self._test.vapi.gbp_contract_dump()
482 if c.contract.src_epg == self.src_epg \
483 and c.contract.dst_epg == self.dst_epg:
488 class VppGbpVxlanTunnel(VppInterface):
493 def __init__(self, test, vni, bd_rd_id, mode):
494 super(VppGbpVxlanTunnel, self).__init__(test)
497 self.bd_rd_id = bd_rd_id
500 def add_vpp_config(self):
501 r = self._test.vapi.gbp_vxlan_tunnel_add(
505 self.set_sw_if_index(r.sw_if_index)
506 self._test.registry.register(self, self._test.logger)
508 def remove_vpp_config(self):
509 self._test.vapi.gbp_vxlan_tunnel_del(self.vni)
512 return self.object_id()
515 return "gbp-vxlan:%d" % (self.vni)
517 def query_vpp_config(self):
518 return find_gbp_vxlan(self._test, self.vni)
521 class VppGbpAcl(VppObject):
526 def __init__(self, test):
528 self.acl_index = 4294967295
530 def create_rule(self, is_ipv6=0, permit_deny=0, proto=-1,
531 s_prefix=0, s_ip='\x00\x00\x00\x00', sport_from=0,
532 sport_to=65535, d_prefix=0, d_ip='\x00\x00\x00\x00',
533 dport_from=0, dport_to=65535):
534 if proto == -1 or proto == 0:
537 elif proto == 1 or proto == 58:
540 rule = ({'is_permit': permit_deny, 'is_ipv6': is_ipv6, 'proto': proto,
541 'srcport_or_icmptype_first': sport_from,
542 'srcport_or_icmptype_last': sport_to,
543 'src_ip_prefix_len': s_prefix,
545 'dstport_or_icmpcode_first': dport_from,
546 'dstport_or_icmpcode_last': dport_to,
547 'dst_ip_prefix_len': d_prefix,
548 'dst_ip_addr': d_ip})
551 def add_vpp_config(self, rules):
553 reply = self._test.vapi.acl_add_replace(self.acl_index,
556 self.acl_index = reply.acl_index
557 return self.acl_index
559 def remove_vpp_config(self):
560 self._test.vapi.acl_del(self.acl_index)
563 return self.object_id()
566 return "gbp-acl:[%d]" % (self.acl_index)
568 def query_vpp_config(self):
569 cs = self._test.vapi.acl_dump()
571 if c.acl_index == self.acl_index:
576 class TestGBP(VppTestCase):
577 """ GBP Test Case """
580 super(TestGBP, self).setUp()
582 self.create_pg_interfaces(range(9))
583 self.create_loopback_interfaces(8)
585 self.router_mac = MACAddress("00:11:22:33:44:55")
587 for i in self.pg_interfaces:
589 for i in self.lo_interfaces:
593 for i in self.pg_interfaces:
596 super(TestGBP, self).tearDown()
598 def send_and_expect_bridged(self, src, tx, dst):
599 rx = self.send_and_expect(src, tx, dst)
602 self.assertEqual(r[Ether].src, tx[0][Ether].src)
603 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
604 self.assertEqual(r[IP].src, tx[0][IP].src)
605 self.assertEqual(r[IP].dst, tx[0][IP].dst)
608 def send_and_expect_bridged6(self, src, tx, dst):
609 rx = self.send_and_expect(src, tx, dst)
612 self.assertEqual(r[Ether].src, tx[0][Ether].src)
613 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
614 self.assertEqual(r[IPv6].src, tx[0][IPv6].src)
615 self.assertEqual(r[IPv6].dst, tx[0][IPv6].dst)
618 def send_and_expect_routed(self, src, tx, dst, src_mac):
619 rx = self.send_and_expect(src, tx, dst)
622 self.assertEqual(r[Ether].src, src_mac)
623 self.assertEqual(r[Ether].dst, dst.remote_mac)
624 self.assertEqual(r[IP].src, tx[0][IP].src)
625 self.assertEqual(r[IP].dst, tx[0][IP].dst)
628 def send_and_expect_natted(self, src, tx, dst, src_ip):
629 rx = self.send_and_expect(src, tx, dst)
632 self.assertEqual(r[Ether].src, tx[0][Ether].src)
633 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
634 self.assertEqual(r[IP].src, src_ip)
635 self.assertEqual(r[IP].dst, tx[0][IP].dst)
638 def send_and_expect_natted6(self, src, tx, dst, src_ip):
639 rx = self.send_and_expect(src, tx, dst)
642 self.assertEqual(r[Ether].src, tx[0][Ether].src)
643 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
644 self.assertEqual(r[IPv6].src, src_ip)
645 self.assertEqual(r[IPv6].dst, tx[0][IPv6].dst)
648 def send_and_expect_unnatted(self, src, tx, dst, dst_ip):
649 rx = self.send_and_expect(src, tx, dst)
652 self.assertEqual(r[Ether].src, tx[0][Ether].src)
653 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
654 self.assertEqual(r[IP].dst, dst_ip)
655 self.assertEqual(r[IP].src, tx[0][IP].src)
658 def send_and_expect_unnatted6(self, src, tx, dst, dst_ip):
659 rx = self.send_and_expect(src, tx, dst)
662 self.assertEqual(r[Ether].src, tx[0][Ether].src)
663 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
664 self.assertEqual(r[IPv6].dst, dst_ip)
665 self.assertEqual(r[IPv6].src, tx[0][IPv6].src)
668 def send_and_expect_double_natted(self, src, tx, dst, src_ip, dst_ip):
669 rx = self.send_and_expect(src, tx, dst)
672 self.assertEqual(r[Ether].src, str(self.router_mac))
673 self.assertEqual(r[Ether].dst, dst.remote_mac)
674 self.assertEqual(r[IP].dst, dst_ip)
675 self.assertEqual(r[IP].src, src_ip)
678 def send_and_expect_double_natted6(self, src, tx, dst, src_ip, dst_ip):
679 rx = self.send_and_expect(src, tx, dst)
682 self.assertEqual(r[Ether].src, str(self.router_mac))
683 self.assertEqual(r[Ether].dst, dst.remote_mac)
684 self.assertEqual(r[IPv6].dst, dst_ip)
685 self.assertEqual(r[IPv6].src, src_ip)
689 """ Group Based Policy """
691 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
696 bd1 = VppBridgeDomain(self, 1)
697 bd2 = VppBridgeDomain(self, 2)
698 bd20 = VppBridgeDomain(self, 20)
702 bd20.add_vpp_config()
704 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0)
705 gbd2 = VppGbpBridgeDomain(self, bd2, self.loop1)
706 gbd20 = VppGbpBridgeDomain(self, bd20, self.loop2)
708 gbd1.add_vpp_config()
709 gbd2.add_vpp_config()
710 gbd20.add_vpp_config()
715 gt4 = VppIpTable(self, 0)
717 gt6 = VppIpTable(self, 0, is_ip6=True)
719 nt4 = VppIpTable(self, 20)
721 nt6 = VppIpTable(self, 20, is_ip6=True)
724 rd0 = VppGbpRouteDomain(self, 0, gt4, gt6, None, None)
725 rd20 = VppGbpRouteDomain(self, 20, nt4, nt6, None, None)
728 rd20.add_vpp_config()
731 # 3 EPGs, 2 of which share a BD.
732 # 2 NAT EPGs, one for floating-IP subnets, the other for internet
734 epgs = [VppGbpEndpointGroup(self, 220, rd0, gbd1, self.pg4,
738 VppGbpEndpointGroup(self, 221, rd0, gbd1, self.pg5,
742 VppGbpEndpointGroup(self, 222, rd0, gbd2, self.pg6,
746 VppGbpEndpointGroup(self, 333, rd20, gbd20, self.pg7,
750 VppGbpEndpointGroup(self, 444, rd20, gbd20, self.pg8,
754 recircs = [VppGbpRecirc(self, epgs[0],
756 VppGbpRecirc(self, epgs[1],
758 VppGbpRecirc(self, epgs[2],
760 VppGbpRecirc(self, epgs[3],
761 self.loop6, is_ext=True),
762 VppGbpRecirc(self, epgs[4],
763 self.loop7, is_ext=True)]
766 recirc_nat = recircs[3]
769 # 4 end-points, 2 in the same subnet, 3 in the same BD
771 eps = [VppGbpEndpoint(self, self.pg0,
773 "10.0.0.1", "11.0.0.1",
774 "2001:10::1", "3001::1"),
775 VppGbpEndpoint(self, self.pg1,
777 "10.0.0.2", "11.0.0.2",
778 "2001:10::2", "3001::2"),
779 VppGbpEndpoint(self, self.pg2,
781 "10.0.1.1", "11.0.0.3",
782 "2001:10:1::1", "3001::3"),
783 VppGbpEndpoint(self, self.pg3,
785 "10.0.2.1", "11.0.0.4",
786 "2001:10:2::1", "3001::4")]
789 # Config related to each of the EPGs
792 # IP config on the BVI interfaces
793 if epg != epgs[1] and epg != epgs[4]:
794 VppIpInterfaceBind(self, epg.bvi, epg.rd.t4).add_vpp_config()
795 VppIpInterfaceBind(self, epg.bvi, epg.rd.t6).add_vpp_config()
796 self.vapi.sw_interface_set_mac_address(
798 self.router_mac.packed)
800 # The BVIs are NAT inside interfaces
801 self.vapi.nat44_interface_add_del_feature(epg.bvi.sw_if_index,
804 self.vapi.nat66_add_del_interface(epg.bvi.sw_if_index,
808 if_ip4 = VppIpInterfaceAddress(self, epg.bvi, epg.bvi_ip4, 32)
809 if_ip6 = VppIpInterfaceAddress(self, epg.bvi, epg.bvi_ip6, 128)
810 if_ip4.add_vpp_config()
811 if_ip6.add_vpp_config()
813 # EPG uplink interfaces in the RD
814 VppIpInterfaceBind(self, epg.uplink, epg.rd.t4).add_vpp_config()
815 VppIpInterfaceBind(self, epg.uplink, epg.rd.t6).add_vpp_config()
817 # add the BD ARP termination entry for BVI IP
818 epg.bd_arp_ip4 = VppBridgeDomainArpEntry(self, epg.bd.bd,
819 str(self.router_mac),
821 epg.bd_arp_ip6 = VppBridgeDomainArpEntry(self, epg.bd.bd,
822 str(self.router_mac),
824 epg.bd_arp_ip4.add_vpp_config()
825 epg.bd_arp_ip6.add_vpp_config()
830 for recirc in recircs:
831 # EPG's ingress recirculation interface maps to its RD
832 VppIpInterfaceBind(self, recirc.recirc,
833 recirc.epg.rd.t4).add_vpp_config()
834 VppIpInterfaceBind(self, recirc.recirc,
835 recirc.epg.rd.t6).add_vpp_config()
837 self.vapi.nat44_interface_add_del_feature(
838 recirc.recirc.sw_if_index,
841 self.vapi.nat66_add_del_interface(
842 recirc.recirc.sw_if_index,
846 recirc.add_vpp_config()
848 for recirc in recircs:
849 self.assertTrue(find_bridge_domain_port(self,
850 recirc.epg.bd.bd.bd_id,
851 recirc.recirc.sw_if_index))
854 self.pg_enable_capture(self.pg_interfaces)
857 # routes to the endpoints. We need these since there are no
858 # adj-fibs due to the fact the the BVI address has /32 and
859 # the subnet is not attached.
861 for (ip, fip) in zip(ep.ips, ep.fips):
862 # Add static mappings for each EP from the 10/8 to 11/8 network
864 self.vapi.nat44_add_del_static_mapping(ip.bytes,
869 self.vapi.nat66_add_del_static_mapping(ip.bytes,
876 self.logger.info(self.vapi.cli("sh gbp endpoint"))
878 # ... results in a Gratuitous ARP/ND on the EPG's uplink
879 rx = ep.epg.uplink.get_capture(len(ep.ips), timeout=0.2)
881 for ii, ip in enumerate(ep.ips):
885 self.assertTrue(p.haslayer(ICMPv6ND_NA))
886 self.assertEqual(p[ICMPv6ND_NA].tgt, ip.address)
888 self.assertTrue(p.haslayer(ARP))
889 self.assertEqual(p[ARP].psrc, ip.address)
890 self.assertEqual(p[ARP].pdst, ip.address)
892 # add the BD ARP termination entry for floating IP
894 ba = VppBridgeDomainArpEntry(self, epg_nat.bd.bd, ep.mac, fip)
897 # floating IPs route via EPG recirc
898 r = VppIpRoute(self, fip.address, fip.length,
899 [VppRoutePath(fip.address,
900 ep.recirc.recirc.sw_if_index,
902 proto=fip.dpo_proto)],
907 # L2 FIB entries in the NAT EPG BD to bridge the packets from
908 # the outside direct to the internal EPG
909 lf = VppL2FibEntry(self, epg_nat.bd.bd, ep.mac,
910 ep.recirc.recirc, bvi_mac=0)
914 # ARP packets for unknown IP are sent to the EPG uplink
916 pkt_arp = (Ether(dst="ff:ff:ff:ff:ff:ff",
917 src=self.pg0.remote_mac) /
919 hwdst="ff:ff:ff:ff:ff:ff",
920 hwsrc=self.pg0.remote_mac,
924 self.vapi.cli("clear trace")
925 self.pg0.add_stream(pkt_arp)
927 self.pg_enable_capture(self.pg_interfaces)
930 rxd = epgs[0].uplink.get_capture(1)
933 # ARP/ND packets get a response
935 pkt_arp = (Ether(dst="ff:ff:ff:ff:ff:ff",
936 src=self.pg0.remote_mac) /
938 hwdst="ff:ff:ff:ff:ff:ff",
939 hwsrc=self.pg0.remote_mac,
940 pdst=epgs[0].bvi_ip4.address,
941 psrc=eps[0].ip4.address))
943 self.send_and_expect(self.pg0, [pkt_arp], self.pg0)
945 nsma = in6_getnsma(inet_pton(AF_INET6, eps[0].ip6.address))
946 d = inet_ntop(AF_INET6, nsma)
947 pkt_nd = (Ether(dst=in6_getnsmac(nsma),
948 src=self.pg0.remote_mac) /
949 IPv6(dst=d, src=eps[0].ip6.address) /
950 ICMPv6ND_NS(tgt=epgs[0].bvi_ip6.address) /
951 ICMPv6NDOptSrcLLAddr(lladdr=self.pg0.remote_mac))
952 self.send_and_expect(self.pg0, [pkt_nd], self.pg0)
955 # broadcast packets are flooded
957 pkt_bcast = (Ether(dst="ff:ff:ff:ff:ff:ff",
958 src=self.pg0.remote_mac) /
959 IP(src=eps[0].ip4.address, dst="232.1.1.1") /
960 UDP(sport=1234, dport=1234) /
963 self.vapi.cli("clear trace")
964 self.pg0.add_stream(pkt_bcast)
966 self.pg_enable_capture(self.pg_interfaces)
969 rxd = eps[1].itf.get_capture(1)
970 self.assertEqual(rxd[0][Ether].dst, pkt_bcast[Ether].dst)
971 rxd = epgs[0].uplink.get_capture(1)
972 self.assertEqual(rxd[0][Ether].dst, pkt_bcast[Ether].dst)
975 # packets to non-local L3 destinations dropped
977 pkt_intra_epg_220_ip4 = (Ether(src=self.pg0.remote_mac,
978 dst=str(self.router_mac)) /
979 IP(src=eps[0].ip4.address,
981 UDP(sport=1234, dport=1234) /
983 pkt_inter_epg_222_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) /
990 self.send_and_assert_no_replies(self.pg0, pkt_intra_epg_220_ip4 * 65)
992 pkt_inter_epg_222_ip6 = (Ether(src=self.pg0.remote_mac,
993 dst=str(self.router_mac)) /
994 IPv6(src=eps[0].ip6.address,
996 UDP(sport=1234, dport=1234) /
998 self.send_and_assert_no_replies(self.pg0, pkt_inter_epg_222_ip6 * 65)
1001 # Add the subnet routes
1004 self, rd0, "10.0.0.0", 24,
1005 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1007 self, rd0, "10.0.1.0", 24,
1008 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1010 self, rd0, "10.0.2.0", 24,
1011 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1013 self, rd0, "2001:10::1", 64,
1014 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1016 self, rd0, "2001:10:1::1", 64,
1017 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1019 self, rd0, "2001:10:2::1", 64,
1020 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1021 s41.add_vpp_config()
1022 s42.add_vpp_config()
1023 s43.add_vpp_config()
1024 s61.add_vpp_config()
1025 s62.add_vpp_config()
1026 s63.add_vpp_config()
1028 self.send_and_expect_bridged(eps[0].itf,
1029 pkt_intra_epg_220_ip4 * 65,
1031 self.send_and_expect_bridged(eps[0].itf,
1032 pkt_inter_epg_222_ip4 * 65,
1034 self.send_and_expect_bridged6(eps[0].itf,
1035 pkt_inter_epg_222_ip6 * 65,
1038 self.logger.info(self.vapi.cli("sh ip fib 11.0.0.2"))
1039 self.logger.info(self.vapi.cli("sh gbp endpoint-group"))
1040 self.logger.info(self.vapi.cli("sh gbp endpoint"))
1041 self.logger.info(self.vapi.cli("sh gbp recirc"))
1042 self.logger.info(self.vapi.cli("sh int"))
1043 self.logger.info(self.vapi.cli("sh int addr"))
1044 self.logger.info(self.vapi.cli("sh int feat loop6"))
1045 self.logger.info(self.vapi.cli("sh vlib graph ip4-gbp-src-classify"))
1046 self.logger.info(self.vapi.cli("sh int feat loop3"))
1047 self.logger.info(self.vapi.cli("sh int feat pg0"))
1050 # Packet destined to unknown unicast is sent on the epg uplink ...
1052 pkt_intra_epg_220_to_uplink = (Ether(src=self.pg0.remote_mac,
1053 dst="00:00:00:33:44:55") /
1054 IP(src=eps[0].ip4.address,
1056 UDP(sport=1234, dport=1234) /
1059 self.send_and_expect_bridged(eps[0].itf,
1060 pkt_intra_epg_220_to_uplink * 65,
1062 # ... and nowhere else
1063 self.pg1.get_capture(0, timeout=0.1)
1064 self.pg1.assert_nothing_captured(remark="Flood onto other VMS")
1066 pkt_intra_epg_221_to_uplink = (Ether(src=self.pg2.remote_mac,
1067 dst="00:00:00:33:44:66") /
1068 IP(src=eps[0].ip4.address,
1070 UDP(sport=1234, dport=1234) /
1073 self.send_and_expect_bridged(eps[2].itf,
1074 pkt_intra_epg_221_to_uplink * 65,
1078 # Packets from the uplink are forwarded in the absence of a contract
1080 pkt_intra_epg_220_from_uplink = (Ether(src="00:00:00:33:44:55",
1081 dst=self.pg0.remote_mac) /
1082 IP(src=eps[0].ip4.address,
1084 UDP(sport=1234, dport=1234) /
1087 self.send_and_expect_bridged(self.pg4,
1088 pkt_intra_epg_220_from_uplink * 65,
1092 # in the absence of policy, endpoints in the same EPG
1095 pkt_intra_epg = (Ether(src=self.pg0.remote_mac,
1096 dst=self.pg1.remote_mac) /
1097 IP(src=eps[0].ip4.address,
1098 dst=eps[1].ip4.address) /
1099 UDP(sport=1234, dport=1234) /
1102 self.send_and_expect_bridged(self.pg0, pkt_intra_epg * 65, self.pg1)
1105 # in the abscense of policy, endpoints in the different EPG
1106 # cannot communicate
1108 pkt_inter_epg_220_to_221 = (Ether(src=self.pg0.remote_mac,
1109 dst=self.pg2.remote_mac) /
1110 IP(src=eps[0].ip4.address,
1111 dst=eps[2].ip4.address) /
1112 UDP(sport=1234, dport=1234) /
1114 pkt_inter_epg_221_to_220 = (Ether(src=self.pg2.remote_mac,
1115 dst=self.pg0.remote_mac) /
1116 IP(src=eps[2].ip4.address,
1117 dst=eps[0].ip4.address) /
1118 UDP(sport=1234, dport=1234) /
1120 pkt_inter_epg_220_to_222 = (Ether(src=self.pg0.remote_mac,
1121 dst=str(self.router_mac)) /
1122 IP(src=eps[0].ip4.address,
1123 dst=eps[3].ip4.address) /
1124 UDP(sport=1234, dport=1234) /
1127 self.send_and_assert_no_replies(eps[0].itf,
1128 pkt_inter_epg_220_to_221 * 65)
1129 self.send_and_assert_no_replies(eps[0].itf,
1130 pkt_inter_epg_220_to_222 * 65)
1133 # A uni-directional contract from EPG 220 -> 221
1135 acl = VppGbpAcl(self)
1136 rule = acl.create_rule(permit_deny=1, proto=17)
1137 rule2 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
1138 acl_index = acl.add_vpp_config([rule, rule2])
1139 c1 = VppGbpContract(
1140 self, 220, 221, acl_index,
1141 [VppGbpContractRule(
1142 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1145 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1147 [ETH_P_IP, ETH_P_IPV6])
1150 self.send_and_expect_bridged(eps[0].itf,
1151 pkt_inter_epg_220_to_221 * 65,
1153 self.send_and_assert_no_replies(eps[0].itf,
1154 pkt_inter_epg_220_to_222 * 65)
1157 # contract for the return direction
1159 c2 = VppGbpContract(
1160 self, 221, 220, acl_index,
1161 [VppGbpContractRule(
1162 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1165 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1167 [ETH_P_IP, ETH_P_IPV6])
1170 self.send_and_expect_bridged(eps[0].itf,
1171 pkt_inter_epg_220_to_221 * 65,
1173 self.send_and_expect_bridged(eps[2].itf,
1174 pkt_inter_epg_221_to_220 * 65,
1178 # the contract does not allow non-IP
1180 pkt_non_ip_inter_epg_220_to_221 = (Ether(src=self.pg0.remote_mac,
1181 dst=self.pg2.remote_mac) /
1183 self.send_and_assert_no_replies(eps[0].itf,
1184 pkt_non_ip_inter_epg_220_to_221 * 17)
1187 # check that inter group is still disabled for the groups
1188 # not in the contract.
1190 self.send_and_assert_no_replies(eps[0].itf,
1191 pkt_inter_epg_220_to_222 * 65)
1194 # A uni-directional contract from EPG 220 -> 222 'L3 routed'
1196 c3 = VppGbpContract(
1197 self, 220, 222, acl_index,
1198 [VppGbpContractRule(
1199 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1202 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1204 [ETH_P_IP, ETH_P_IPV6])
1207 self.logger.info(self.vapi.cli("sh gbp contract"))
1209 self.send_and_expect_routed(eps[0].itf,
1210 pkt_inter_epg_220_to_222 * 65,
1212 str(self.router_mac))
1215 # remove both contracts, traffic stops in both directions
1217 c2.remove_vpp_config()
1218 c1.remove_vpp_config()
1219 c3.remove_vpp_config()
1220 acl.remove_vpp_config()
1222 self.send_and_assert_no_replies(eps[2].itf,
1223 pkt_inter_epg_221_to_220 * 65)
1224 self.send_and_assert_no_replies(eps[0].itf,
1225 pkt_inter_epg_220_to_221 * 65)
1226 self.send_and_expect_bridged(eps[0].itf,
1231 # EPs to the outside world
1234 # in the EP's RD an external subnet via the NAT EPG's recirc
1236 self, rd0, "0.0.0.0", 0,
1237 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1238 sw_if_index=recirc_nat.recirc.sw_if_index,
1241 self, rd0, "11.0.0.0", 8,
1242 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1243 sw_if_index=recirc_nat.recirc.sw_if_index,
1245 se16 = VppGbpSubnet(
1247 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1248 sw_if_index=recirc_nat.recirc.sw_if_index,
1250 # in the NAT RD an external subnet via the NAT EPG's uplink
1252 self, rd20, "0.0.0.0", 0,
1253 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1254 sw_if_index=epg_nat.uplink.sw_if_index,
1256 se36 = VppGbpSubnet(
1257 self, rd20, "::", 0,
1258 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1259 sw_if_index=epg_nat.uplink.sw_if_index,
1262 self, rd20, "11.0.0.0", 8,
1263 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1264 sw_if_index=epg_nat.uplink.sw_if_index,
1266 se1.add_vpp_config()
1267 se2.add_vpp_config()
1268 se16.add_vpp_config()
1269 se3.add_vpp_config()
1270 se36.add_vpp_config()
1271 se4.add_vpp_config()
1273 self.logger.info(self.vapi.cli("sh ip fib 0.0.0.0/0"))
1274 self.logger.info(self.vapi.cli("sh ip fib 11.0.0.1"))
1275 self.logger.info(self.vapi.cli("sh ip6 fib ::/0"))
1276 self.logger.info(self.vapi.cli("sh ip6 fib %s" %
1280 # From an EP to an outside addess: IN2OUT
1282 pkt_inter_epg_220_to_global = (Ether(src=self.pg0.remote_mac,
1283 dst=str(self.router_mac)) /
1284 IP(src=eps[0].ip4.address,
1286 UDP(sport=1234, dport=1234) /
1290 self.send_and_assert_no_replies(eps[0].itf,
1291 pkt_inter_epg_220_to_global * 65)
1293 acl2 = VppGbpAcl(self)
1294 rule = acl2.create_rule(permit_deny=1, proto=17, sport_from=1234,
1295 sport_to=1234, dport_from=1234, dport_to=1234)
1296 rule2 = acl2.create_rule(is_ipv6=1, permit_deny=1, proto=17,
1297 sport_from=1234, sport_to=1234,
1298 dport_from=1234, dport_to=1234)
1300 acl_index2 = acl2.add_vpp_config([rule, rule2])
1301 c4 = VppGbpContract(
1302 self, 220, 333, acl_index2,
1303 [VppGbpContractRule(
1304 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1307 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1309 [ETH_P_IP, ETH_P_IPV6])
1312 self.send_and_expect_natted(eps[0].itf,
1313 pkt_inter_epg_220_to_global * 65,
1315 eps[0].fip4.address)
1317 pkt_inter_epg_220_to_global = (Ether(src=self.pg0.remote_mac,
1318 dst=str(self.router_mac)) /
1319 IPv6(src=eps[0].ip6.address,
1321 UDP(sport=1234, dport=1234) /
1324 self.send_and_expect_natted6(self.pg0,
1325 pkt_inter_epg_220_to_global * 65,
1327 eps[0].fip6.address)
1330 # From a global address to an EP: OUT2IN
1332 pkt_inter_epg_220_from_global = (Ether(src=str(self.router_mac),
1333 dst=self.pg0.remote_mac) /
1334 IP(dst=eps[0].fip4.address,
1336 UDP(sport=1234, dport=1234) /
1339 self.send_and_assert_no_replies(self.pg7,
1340 pkt_inter_epg_220_from_global * 65)
1342 c5 = VppGbpContract(
1343 self, 333, 220, acl_index2,
1344 [VppGbpContractRule(
1345 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1348 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1350 [ETH_P_IP, ETH_P_IPV6])
1353 self.send_and_expect_unnatted(self.pg7,
1354 pkt_inter_epg_220_from_global * 65,
1358 pkt_inter_epg_220_from_global = (Ether(src=str(self.router_mac),
1359 dst=self.pg0.remote_mac) /
1360 IPv6(dst=eps[0].fip6.address,
1362 UDP(sport=1234, dport=1234) /
1365 self.send_and_expect_unnatted6(self.pg7,
1366 pkt_inter_epg_220_from_global * 65,
1371 # From a local VM to another local VM using resp. public addresses:
1374 pkt_intra_epg_220_global = (Ether(src=self.pg0.remote_mac,
1375 dst=str(self.router_mac)) /
1376 IP(src=eps[0].ip4.address,
1377 dst=eps[1].fip4.address) /
1378 UDP(sport=1234, dport=1234) /
1381 self.send_and_expect_double_natted(eps[0].itf,
1382 pkt_intra_epg_220_global * 65,
1384 eps[0].fip4.address,
1387 pkt_intra_epg_220_global = (Ether(src=self.pg0.remote_mac,
1388 dst=str(self.router_mac)) /
1389 IPv6(src=eps[0].ip6.address,
1390 dst=eps[1].fip6.address) /
1391 UDP(sport=1234, dport=1234) /
1394 self.send_and_expect_double_natted6(eps[0].itf,
1395 pkt_intra_epg_220_global * 65,
1397 eps[0].fip6.address,
1404 # del static mappings for each EP from the 10/8 to 11/8 network
1405 self.vapi.nat44_add_del_static_mapping(ep.ip4.bytes,
1410 self.vapi.nat66_add_del_static_mapping(ep.ip6.bytes,
1416 # IP config on the BVI interfaces
1417 if epg != epgs[0] and epg != epgs[3]:
1418 self.vapi.nat44_interface_add_del_feature(epg.bvi.sw_if_index,
1421 self.vapi.nat66_add_del_interface(epg.bvi.sw_if_index,
1425 for recirc in recircs:
1426 self.vapi.nat44_interface_add_del_feature(
1427 recirc.recirc.sw_if_index,
1430 self.vapi.nat66_add_del_interface(
1431 recirc.recirc.sw_if_index,
1435 def wait_for_ep_timeout(self, sw_if_index=None, ip=None, mac=None,
1436 n_tries=100, s_time=1):
1438 if not find_gbp_endpoint(self, sw_if_index, ip, mac):
1440 n_tries = n_tries - 1
1442 self.assertFalse(find_gbp_endpoint(self, sw_if_index, ip, mac))
1445 def test_gbp_learn_l2(self):
1446 """ GBP L2 Endpoint Learning """
1448 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
1449 learnt = [{'mac': '00:00:11:11:11:01',
1451 'ip6': '2001:10::2'},
1452 {'mac': '00:00:11:11:11:02',
1454 'ip6': '2001:10::3'}]
1457 # lower the inactive threshold so these tests pass in a
1458 # reasonable amount of time
1460 self.vapi.gbp_endpoint_learn_set_inactive_threshold(2)
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 # a GBP bridge domain with a BVI and a UU-flood interface
1490 bd1 = VppBridgeDomain(self, 1)
1491 bd1.add_vpp_config()
1492 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0, self.pg3)
1493 gbd1.add_vpp_config()
1495 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1496 self.logger.info(self.vapi.cli("sh gbp bridge"))
1498 # ... and has a /32 applied
1499 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
1500 ip_addr.add_vpp_config()
1503 # The Endpoint-group in which we are learning endpoints
1505 epg_220 = VppGbpEndpointGroup(self, 220, rd1, gbd1,
1509 epg_220.add_vpp_config()
1510 epg_330 = VppGbpEndpointGroup(self, 330, rd1, gbd1,
1514 epg_330.add_vpp_config()
1517 # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
1520 vx_tun_l2_1 = VppGbpVxlanTunnel(
1521 self, 99, bd1.bd_id,
1522 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L2)
1523 vx_tun_l2_1.add_vpp_config()
1526 # A static endpoint that the learnt endpoints are trying to
1529 ep = VppGbpEndpoint(self, self.pg0,
1531 "10.0.0.127", "11.0.0.127",
1532 "2001:10::1", "3001::1")
1535 self.assertTrue(find_route(self, ep.ip4.address, 32, table_id=1))
1537 # a packet with an sclass from an unknwon EPG
1538 p = (Ether(src=self.pg2.remote_mac,
1539 dst=self.pg2.local_mac) /
1540 IP(src=self.pg2.remote_hosts[0].ip4,
1541 dst=self.pg2.local_ip4) /
1542 UDP(sport=1234, dport=48879) /
1543 VXLAN(vni=99, gpid=88, flags=0x88) /
1544 Ether(src=learnt[0]["mac"], dst=ep.mac) /
1545 IP(src=learnt[0]["ip"], dst=ep.ip4.address) /
1546 UDP(sport=1234, dport=1234) /
1549 self.send_and_assert_no_replies(self.pg2, p)
1552 # we should not have learnt a new tunnel endpoint, since
1553 # the EPG was not learnt.
1555 self.assertEqual(INDEX_INVALID,
1556 find_vxlan_gbp_tunnel(self,
1558 self.pg2.remote_hosts[0].ip4,
1561 # epg is not learnt, becasue the EPG is unknwon
1562 self.assertEqual(len(self.vapi.gbp_endpoint_dump()), 1)
1564 for ii, l in enumerate(learnt):
1565 # a packet with an sclass from a knwon EPG
1566 # arriving on an unknown TEP
1567 p = (Ether(src=self.pg2.remote_mac,
1568 dst=self.pg2.local_mac) /
1569 IP(src=self.pg2.remote_hosts[1].ip4,
1570 dst=self.pg2.local_ip4) /
1571 UDP(sport=1234, dport=48879) /
1572 VXLAN(vni=99, gpid=220, flags=0x88) /
1573 Ether(src=l['mac'], dst=ep.mac) /
1574 IP(src=l['ip'], dst=ep.ip4.address) /
1575 UDP(sport=1234, dport=1234) /
1578 rx = self.send_and_expect(self.pg2, [p], self.pg0)
1581 tep1_sw_if_index = find_vxlan_gbp_tunnel(
1584 self.pg2.remote_hosts[1].ip4,
1586 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
1589 # the EP is learnt via the learnt TEP
1590 # both from its MAC and its IP
1592 self.assertTrue(find_gbp_endpoint(self,
1593 vx_tun_l2_1.sw_if_index,
1595 self.assertTrue(find_gbp_endpoint(self,
1596 vx_tun_l2_1.sw_if_index,
1599 self.logger.info(self.vapi.cli("show gbp endpoint"))
1600 self.logger.info(self.vapi.cli("show gbp vxlan"))
1601 self.logger.info(self.vapi.cli("show vxlan-gbp tunnel"))
1604 # If we sleep for the threshold time, the learnt endpoints should
1608 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1612 # repeat. the do not learn bit is set so the EPs are not learnt
1615 # a packet with an sclass from a knwon EPG
1616 p = (Ether(src=self.pg2.remote_mac,
1617 dst=self.pg2.local_mac) /
1618 IP(src=self.pg2.remote_hosts[1].ip4,
1619 dst=self.pg2.local_ip4) /
1620 UDP(sport=1234, dport=48879) /
1621 VXLAN(vni=99, gpid=220, flags=0x88, gpflags="D") /
1622 Ether(src=l['mac'], dst=ep.mac) /
1623 IP(src=l['ip'], dst=ep.ip4.address) /
1624 UDP(sport=1234, dport=1234) /
1627 rx = self.send_and_expect(self.pg2, p*65, self.pg0)
1630 self.assertFalse(find_gbp_endpoint(self,
1631 vx_tun_l2_1.sw_if_index,
1638 # a packet with an sclass from a knwon EPG
1639 p = (Ether(src=self.pg2.remote_mac,
1640 dst=self.pg2.local_mac) /
1641 IP(src=self.pg2.remote_hosts[1].ip4,
1642 dst=self.pg2.local_ip4) /
1643 UDP(sport=1234, dport=48879) /
1644 VXLAN(vni=99, gpid=220, flags=0x88) /
1645 Ether(src=l['mac'], dst=ep.mac) /
1646 IP(src=l['ip'], dst=ep.ip4.address) /
1647 UDP(sport=1234, dport=1234) /
1650 rx = self.send_and_expect(self.pg2, p*65, self.pg0)
1652 self.assertTrue(find_gbp_endpoint(self,
1653 vx_tun_l2_1.sw_if_index,
1657 # Static EP replies to dynamics
1659 self.logger.info(self.vapi.cli("sh l2fib bd_id 1"))
1661 p = (Ether(src=ep.mac, dst=l['mac']) /
1662 IP(dst=l['ip'], src=ep.ip4.address) /
1663 UDP(sport=1234, dport=1234) /
1666 rxs = self.send_and_expect(self.pg0, p * 17, self.pg2)
1669 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
1670 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
1671 self.assertEqual(rx[UDP].dport, 48879)
1672 # the UDP source port is a random value for hashing
1673 self.assertEqual(rx[VXLAN].gpid, 220)
1674 self.assertEqual(rx[VXLAN].vni, 99)
1675 self.assertTrue(rx[VXLAN].flags.G)
1676 self.assertTrue(rx[VXLAN].flags.Instance)
1677 self.assertTrue(rx[VXLAN].gpflags.A)
1678 self.assertFalse(rx[VXLAN].gpflags.D)
1681 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1685 # repeat in the other EPG
1686 # there's no contract between 220 and 330, but the A-bit is set
1687 # so the packet is cleared for delivery
1690 # a packet with an sclass from a knwon EPG
1691 p = (Ether(src=self.pg2.remote_mac,
1692 dst=self.pg2.local_mac) /
1693 IP(src=self.pg2.remote_hosts[1].ip4,
1694 dst=self.pg2.local_ip4) /
1695 UDP(sport=1234, dport=48879) /
1696 VXLAN(vni=99, gpid=330, flags=0x88, gpflags='A') /
1697 Ether(src=l['mac'], dst=ep.mac) /
1698 IP(src=l['ip'], dst=ep.ip4.address) /
1699 UDP(sport=1234, dport=1234) /
1702 rx = self.send_and_expect(self.pg2, p*65, self.pg0)
1704 self.assertTrue(find_gbp_endpoint(self,
1705 vx_tun_l2_1.sw_if_index,
1709 # static EP cannot reach the learnt EPs since there is no contract
1710 # only test 1 EP as the others could timeout
1712 p = (Ether(src=ep.mac, dst=l['mac']) /
1713 IP(dst=learnt[0]['ip'], src=ep.ip4.address) /
1714 UDP(sport=1234, dport=1234) /
1717 self.send_and_assert_no_replies(self.pg0, [p])
1720 # refresh the entries after the check for no replies above
1723 # a packet with an sclass from a knwon EPG
1724 p = (Ether(src=self.pg2.remote_mac,
1725 dst=self.pg2.local_mac) /
1726 IP(src=self.pg2.remote_hosts[1].ip4,
1727 dst=self.pg2.local_ip4) /
1728 UDP(sport=1234, dport=48879) /
1729 VXLAN(vni=99, gpid=330, flags=0x88, gpflags='A') /
1730 Ether(src=l['mac'], dst=ep.mac) /
1731 IP(src=l['ip'], dst=ep.ip4.address) /
1732 UDP(sport=1234, dport=1234) /
1735 rx = self.send_and_expect(self.pg2, p*65, self.pg0)
1737 self.assertTrue(find_gbp_endpoint(self,
1738 vx_tun_l2_1.sw_if_index,
1742 # Add the contract so they can talk
1744 acl = VppGbpAcl(self)
1745 rule = acl.create_rule(permit_deny=1, proto=17)
1746 rule2 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
1747 acl_index = acl.add_vpp_config([rule, rule2])
1748 c1 = VppGbpContract(
1749 self, 220, 330, acl_index,
1750 [VppGbpContractRule(
1751 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1754 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1756 [ETH_P_IP, ETH_P_IPV6])
1760 p = (Ether(src=ep.mac, dst=l['mac']) /
1761 IP(dst=l['ip'], src=ep.ip4.address) /
1762 UDP(sport=1234, dport=1234) /
1765 self.send_and_expect(self.pg0, [p], self.pg2)
1768 # send UU packets from the local EP
1770 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1771 self.logger.info(self.vapi.cli("sh gbp bridge"))
1772 p_uu = (Ether(src=ep.mac, dst="00:11:11:11:11:11") /
1773 IP(dst="10.0.0.133", src=ep.ip4.address) /
1774 UDP(sport=1234, dport=1234) /
1776 rxs = self.send_and_expect(ep.itf, [p_uu], gbd1.uu_flood)
1779 # Add a mcast destination VXLAN-GBP tunnel for B&M traffic
1781 tun_bm = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
1784 tun_bm.add_vpp_config()
1785 bp_bm = VppBridgeDomainPort(self, bd1, tun_bm,
1786 port_type=L2_PORT_TYPE.NORMAL)
1787 bp_bm.add_vpp_config()
1789 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1791 p_bm = (Ether(src=ep.mac, dst="ff:ff:ff:ff:ff:ff") /
1792 IP(dst="10.0.0.133", src=ep.ip4.address) /
1793 UDP(sport=1234, dport=1234) /
1795 rxs = self.send_and_expect_only(ep.itf, [p_bm], tun_bm.mcast_itf)
1798 # Check v6 Endpoints
1801 # a packet with an sclass from a knwon EPG
1802 p = (Ether(src=self.pg2.remote_mac,
1803 dst=self.pg2.local_mac) /
1804 IP(src=self.pg2.remote_hosts[1].ip4,
1805 dst=self.pg2.local_ip4) /
1806 UDP(sport=1234, dport=48879) /
1807 VXLAN(vni=99, gpid=330, flags=0x88, gpflags='A') /
1808 Ether(src=l['mac'], dst=ep.mac) /
1809 IPv6(src=l['ip6'], dst=ep.ip6.address) /
1810 UDP(sport=1234, dport=1234) /
1813 rx = self.send_and_expect(self.pg2, p*65, self.pg0)
1815 self.assertTrue(find_gbp_endpoint(self,
1816 vx_tun_l2_1.sw_if_index,
1820 # L3 Endpoint Learning
1821 # - configured on the bridge's BVI
1828 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1831 self.pg2.unconfig_ip4()
1832 self.pg3.unconfig_ip4()
1833 self.pg4.unconfig_ip4()
1835 self.logger.info(self.vapi.cli("sh int"))
1836 self.logger.info(self.vapi.cli("sh gbp vxlan"))
1838 def test_gbp_learn_vlan_l2(self):
1839 """ GBP L2 Endpoint w/ VLANs"""
1841 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
1842 learnt = [{'mac': '00:00:11:11:11:01',
1844 'ip6': '2001:10::2'},
1845 {'mac': '00:00:11:11:11:02',
1847 'ip6': '2001:10::3'}]
1850 # lower the inactive threshold so these tests pass in a
1851 # reasonable amount of time
1853 self.vapi.gbp_endpoint_learn_set_inactive_threshold(2)
1858 gt4 = VppIpTable(self, 1)
1859 gt4.add_vpp_config()
1860 gt6 = VppIpTable(self, 1, is_ip6=True)
1861 gt6.add_vpp_config()
1863 rd1 = VppGbpRouteDomain(self, 1, gt4, gt6)
1864 rd1.add_vpp_config()
1867 # Pg2 hosts the vxlan tunnel, hosts on pg2 to act as TEPs
1869 self.pg2.config_ip4()
1870 self.pg2.resolve_arp()
1871 self.pg2.generate_remote_hosts(4)
1872 self.pg2.configure_ipv4_neighbors()
1873 self.pg3.config_ip4()
1874 self.pg3.resolve_arp()
1877 # The EP will be on a vlan sub-interface
1879 vlan_11 = VppDot1QSubint(self, self.pg0, 11)
1881 self.vapi.sw_interface_set_l2_tag_rewrite(vlan_11.sw_if_index,
1885 bd_uu_fwd = VppVxlanGbpTunnel(self, self.pg3.local_ip4,
1886 self.pg3.remote_ip4, 116)
1887 bd_uu_fwd.add_vpp_config()
1890 # a GBP bridge domain with a BVI and a UU-flood interface
1891 # The BD is marked as do not learn, so no endpoints are ever
1892 # learnt in this BD.
1894 bd1 = VppBridgeDomain(self, 1)
1895 bd1.add_vpp_config()
1896 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0, bd_uu_fwd,
1898 gbd1.add_vpp_config()
1900 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1901 self.logger.info(self.vapi.cli("sh gbp bridge"))
1903 # ... and has a /32 applied
1904 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
1905 ip_addr.add_vpp_config()
1908 # The Endpoint-group in which we are learning endpoints
1910 epg_220 = VppGbpEndpointGroup(self, 220, rd1, gbd1,
1914 epg_220.add_vpp_config()
1917 # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
1920 vx_tun_l2_1 = VppGbpVxlanTunnel(
1921 self, 99, bd1.bd_id,
1922 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L2)
1923 vx_tun_l2_1.add_vpp_config()
1926 # A static endpoint that the learnt endpoints are trying to
1929 ep = VppGbpEndpoint(self, vlan_11,
1931 "10.0.0.127", "11.0.0.127",
1932 "2001:10::1", "3001::1")
1935 self.assertTrue(find_route(self, ep.ip4.address, 32, table_id=1))
1938 # Send to the static EP
1940 for ii, l in enumerate(learnt):
1941 # a packet with an sclass from a knwon EPG
1942 # arriving on an unknown TEP
1943 p = (Ether(src=self.pg2.remote_mac,
1944 dst=self.pg2.local_mac) /
1945 IP(src=self.pg2.remote_hosts[1].ip4,
1946 dst=self.pg2.local_ip4) /
1947 UDP(sport=1234, dport=48879) /
1948 VXLAN(vni=99, gpid=220, flags=0x88) /
1949 Ether(src=l['mac'], dst=ep.mac) /
1950 IP(src=l['ip'], dst=ep.ip4.address) /
1951 UDP(sport=1234, dport=1234) /
1954 rxs = self.send_and_expect(self.pg2, [p], self.pg0)
1957 # packet to EP has the EP's vlan tag
1960 self.assertEqual(rx[Dot1Q].vlan, 11)
1963 # the EP is not learnt since the BD setting prevents it
1966 self.assertFalse(find_gbp_endpoint(self,
1967 vx_tun_l2_1.sw_if_index,
1969 self.assertEqual(INDEX_INVALID,
1970 find_vxlan_gbp_tunnel(
1973 self.pg2.remote_hosts[1].ip4,
1976 self.assertEqual(len(self.vapi.gbp_endpoint_dump()), 1)
1980 # we didn't learn the remotes so they are sent to the UU-fwd
1983 p = (Ether(src=ep.mac, dst=l['mac']) /
1985 IP(dst=l['ip'], src=ep.ip4.address) /
1986 UDP(sport=1234, dport=1234) /
1989 rxs = self.send_and_expect(self.pg0, p * 17, self.pg3)
1992 self.assertEqual(rx[IP].src, self.pg3.local_ip4)
1993 self.assertEqual(rx[IP].dst, self.pg3.remote_ip4)
1994 self.assertEqual(rx[UDP].dport, 48879)
1995 # the UDP source port is a random value for hashing
1996 self.assertEqual(rx[VXLAN].gpid, 220)
1997 self.assertEqual(rx[VXLAN].vni, 116)
1998 self.assertTrue(rx[VXLAN].flags.G)
1999 self.assertTrue(rx[VXLAN].flags.Instance)
2000 self.assertFalse(rx[VXLAN].gpflags.A)
2001 self.assertFalse(rx[VXLAN].gpflags.D)
2003 self.pg2.unconfig_ip4()
2004 self.pg3.unconfig_ip4()
2006 def test_gbp_learn_l3(self):
2007 """ GBP L3 Endpoint Learning """
2009 self.vapi.cli("set logging class gbp debug")
2011 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
2012 routed_dst_mac = "00:0c:0c:0c:0c:0c"
2013 routed_src_mac = "00:22:bd:f8:19:ff"
2015 learnt = [{'mac': '00:00:11:11:11:02',
2017 'ip6': '2001:10::2'},
2018 {'mac': '00:00:11:11:11:03',
2020 'ip6': '2001:10::3'}]
2023 # lower the inactive threshold so these tests pass in a
2024 # reasonable amount of time
2026 self.vapi.gbp_endpoint_learn_set_inactive_threshold(2)
2031 t4 = VppIpTable(self, 1)
2033 t6 = VppIpTable(self, 1, True)
2036 tun_ip4_uu = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
2037 self.pg4.remote_ip4, 114)
2038 tun_ip6_uu = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
2039 self.pg4.remote_ip4, 116)
2040 tun_ip4_uu.add_vpp_config()
2041 tun_ip6_uu.add_vpp_config()
2043 rd1 = VppGbpRouteDomain(self, 2, t4, t6, tun_ip4_uu, tun_ip6_uu)
2044 rd1.add_vpp_config()
2046 self.loop0.set_mac(self.router_mac)
2049 # Bind the BVI to the RD
2051 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
2052 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
2055 # Pg2 hosts the vxlan tunnel
2056 # hosts on pg2 to act as TEPs
2060 self.pg2.config_ip4()
2061 self.pg2.resolve_arp()
2062 self.pg2.generate_remote_hosts(4)
2063 self.pg2.configure_ipv4_neighbors()
2064 self.pg3.config_ip4()
2065 self.pg3.resolve_arp()
2066 self.pg4.config_ip4()
2067 self.pg4.resolve_arp()
2070 # a GBP bridge domain with a BVI and a UU-flood interface
2072 bd1 = VppBridgeDomain(self, 1)
2073 bd1.add_vpp_config()
2074 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0, self.pg3)
2075 gbd1.add_vpp_config()
2077 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2078 self.logger.info(self.vapi.cli("sh gbp bridge"))
2079 self.logger.info(self.vapi.cli("sh gbp route"))
2081 # ... and has a /32 and /128 applied
2082 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2083 ip4_addr.add_vpp_config()
2084 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 128)
2085 ip6_addr.add_vpp_config()
2088 # The Endpoint-group in which we are learning endpoints
2090 epg_220 = VppGbpEndpointGroup(self, 220, rd1, gbd1,
2094 epg_220.add_vpp_config()
2097 # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
2100 vx_tun_l3 = VppGbpVxlanTunnel(
2101 self, 101, rd1.rd_id,
2102 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3)
2103 vx_tun_l3.add_vpp_config()
2106 # A static endpoint that the learnt endpoints are trying to
2109 ep = VppGbpEndpoint(self, self.pg0,
2111 "10.0.0.127", "11.0.0.127",
2112 "2001:10::1", "3001::1")
2116 # learn some remote IPv4 EPs
2118 for ii, l in enumerate(learnt):
2119 # a packet with an sclass from a knwon EPG
2120 # arriving on an unknown TEP
2121 p = (Ether(src=self.pg2.remote_mac,
2122 dst=self.pg2.local_mac) /
2123 IP(src=self.pg2.remote_hosts[1].ip4,
2124 dst=self.pg2.local_ip4) /
2125 UDP(sport=1234, dport=48879) /
2126 VXLAN(vni=101, gpid=220, flags=0x88) /
2127 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2128 IP(src=l['ip'], dst=ep.ip4.address) /
2129 UDP(sport=1234, dport=1234) /
2132 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2135 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2138 self.pg2.remote_hosts[1].ip4,
2140 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2142 # endpoint learnt via the parent GBP-vxlan interface
2143 self.assertTrue(find_gbp_endpoint(self,
2144 vx_tun_l3._sw_if_index,
2148 # Static IPv4 EP replies to learnt
2151 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2152 IP(dst=l['ip'], src=ep.ip4.address) /
2153 UDP(sport=1234, dport=1234) /
2156 rxs = self.send_and_expect(self.pg0, p*1, self.pg2)
2159 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2160 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2161 self.assertEqual(rx[UDP].dport, 48879)
2162 # the UDP source port is a random value for hashing
2163 self.assertEqual(rx[VXLAN].gpid, 220)
2164 self.assertEqual(rx[VXLAN].vni, 101)
2165 self.assertTrue(rx[VXLAN].flags.G)
2166 self.assertTrue(rx[VXLAN].flags.Instance)
2167 self.assertTrue(rx[VXLAN].gpflags.A)
2168 self.assertFalse(rx[VXLAN].gpflags.D)
2170 inner = rx[VXLAN].payload
2172 self.assertEqual(inner[Ether].src, routed_src_mac)
2173 self.assertEqual(inner[Ether].dst, routed_dst_mac)
2174 self.assertEqual(inner[IP].src, ep.ip4.address)
2175 self.assertEqual(inner[IP].dst, l['ip'])
2178 self.assertFalse(find_gbp_endpoint(self,
2183 # learn some remote IPv6 EPs
2185 for ii, l in enumerate(learnt):
2186 # a packet with an sclass from a knwon EPG
2187 # arriving on an unknown TEP
2188 p = (Ether(src=self.pg2.remote_mac,
2189 dst=self.pg2.local_mac) /
2190 IP(src=self.pg2.remote_hosts[1].ip4,
2191 dst=self.pg2.local_ip4) /
2192 UDP(sport=1234, dport=48879) /
2193 VXLAN(vni=101, gpid=220, flags=0x88) /
2194 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2195 IPv6(src=l['ip6'], dst=ep.ip6.address) /
2196 UDP(sport=1234, dport=1234) /
2199 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2202 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2205 self.pg2.remote_hosts[1].ip4,
2207 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2209 self.logger.info(self.vapi.cli("show gbp bridge"))
2210 self.logger.info(self.vapi.cli("show vxlan-gbp tunnel"))
2211 self.logger.info(self.vapi.cli("show gbp vxlan"))
2212 self.logger.info(self.vapi.cli("show int addr"))
2214 # endpoint learnt via the TEP
2215 self.assertTrue(find_gbp_endpoint(self, ip=l['ip6']))
2217 self.logger.info(self.vapi.cli("show gbp endpoint"))
2218 self.logger.info(self.vapi.cli("show ip fib index 1 %s" % l['ip']))
2221 # Static EP replies to learnt
2224 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2225 IPv6(dst=l['ip6'], src=ep.ip6.address) /
2226 UDP(sport=1234, dport=1234) /
2229 rxs = self.send_and_expect(self.pg0, p*65, self.pg2)
2232 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2233 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2234 self.assertEqual(rx[UDP].dport, 48879)
2235 # the UDP source port is a random value for hashing
2236 self.assertEqual(rx[VXLAN].gpid, 220)
2237 self.assertEqual(rx[VXLAN].vni, 101)
2238 self.assertTrue(rx[VXLAN].flags.G)
2239 self.assertTrue(rx[VXLAN].flags.Instance)
2240 self.assertTrue(rx[VXLAN].gpflags.A)
2241 self.assertFalse(rx[VXLAN].gpflags.D)
2243 inner = rx[VXLAN].payload
2245 self.assertEqual(inner[Ether].src, routed_src_mac)
2246 self.assertEqual(inner[Ether].dst, routed_dst_mac)
2247 self.assertEqual(inner[IPv6].src, ep.ip6.address)
2248 self.assertEqual(inner[IPv6].dst, l['ip6'])
2250 self.logger.info(self.vapi.cli("sh gbp endpoint"))
2252 self.wait_for_ep_timeout(ip=l['ip'])
2255 # Static sends to unknown EP with no route
2257 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2258 IP(dst="10.0.0.99", src=ep.ip4.address) /
2259 UDP(sport=1234, dport=1234) /
2262 self.send_and_assert_no_replies(self.pg0, [p])
2265 # Add a route to static EP's v4 and v6 subnet
2266 # packets should be sent on the v4/v6 uu=fwd interface resp.
2268 se_10_24 = VppGbpSubnet(
2269 self, rd1, "10.0.0.0", 24,
2270 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT)
2271 se_10_24.add_vpp_config()
2273 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2274 IP(dst="10.0.0.99", src=ep.ip4.address) /
2275 UDP(sport=1234, dport=1234) /
2278 rxs = self.send_and_expect(self.pg0, [p], self.pg4)
2280 self.assertEqual(rx[IP].src, self.pg4.local_ip4)
2281 self.assertEqual(rx[IP].dst, self.pg4.remote_ip4)
2282 self.assertEqual(rx[UDP].dport, 48879)
2283 # the UDP source port is a random value for hashing
2284 self.assertEqual(rx[VXLAN].gpid, 220)
2285 self.assertEqual(rx[VXLAN].vni, 114)
2286 self.assertTrue(rx[VXLAN].flags.G)
2287 self.assertTrue(rx[VXLAN].flags.Instance)
2288 # policy is not applied to packets sent to the uu-fwd interfaces
2289 self.assertFalse(rx[VXLAN].gpflags.A)
2290 self.assertFalse(rx[VXLAN].gpflags.D)
2293 # learn some remote IPv4 EPs
2295 for ii, l in enumerate(learnt):
2296 # a packet with an sclass from a knwon EPG
2297 # arriving on an unknown TEP
2298 p = (Ether(src=self.pg2.remote_mac,
2299 dst=self.pg2.local_mac) /
2300 IP(src=self.pg2.remote_hosts[1].ip4,
2301 dst=self.pg2.local_ip4) /
2302 UDP(sport=1234, dport=48879) /
2303 VXLAN(vni=101, gpid=220, flags=0x88) /
2304 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2305 IP(src=l['ip'], dst=ep.ip4.address) /
2306 UDP(sport=1234, dport=1234) /
2309 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2312 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2315 self.pg2.remote_hosts[1].ip4,
2317 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2319 # endpoint learnt via the parent GBP-vxlan interface
2320 self.assertTrue(find_gbp_endpoint(self,
2321 vx_tun_l3._sw_if_index,
2325 # Add a remote endpoint from the API
2327 rep_88 = VppGbpEndpoint(self, vx_tun_l3,
2329 "10.0.0.88", "11.0.0.88",
2330 "2001:10::88", "3001::88",
2331 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
2333 self.pg2.remote_hosts[1].ip4,
2335 rep_88.add_vpp_config()
2338 # Add a remote endpoint from the API that matches an existing one
2340 rep_2 = VppGbpEndpoint(self, vx_tun_l3,
2342 learnt[0]['ip'], "11.0.0.101",
2343 learnt[0]['ip6'], "3001::101",
2344 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
2346 self.pg2.remote_hosts[1].ip4,
2348 rep_2.add_vpp_config()
2351 # Add a route to the leanred EP's v4 subnet
2352 # packets should be send on the v4/v6 uu=fwd interface resp.
2354 se_10_1_24 = VppGbpSubnet(
2355 self, rd1, "10.0.1.0", 24,
2356 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT)
2357 se_10_1_24.add_vpp_config()
2359 self.logger.info(self.vapi.cli("show gbp endpoint"))
2361 ips = ["10.0.0.88", learnt[0]['ip']]
2363 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2364 IP(dst=ip, src=ep.ip4.address) /
2365 UDP(sport=1234, dport=1234) /
2368 rxs = self.send_and_expect(self.pg0, p*65, self.pg2)
2371 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2372 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2373 self.assertEqual(rx[UDP].dport, 48879)
2374 # the UDP source port is a random value for hashing
2375 self.assertEqual(rx[VXLAN].gpid, 220)
2376 self.assertEqual(rx[VXLAN].vni, 101)
2377 self.assertTrue(rx[VXLAN].flags.G)
2378 self.assertTrue(rx[VXLAN].flags.Instance)
2379 self.assertTrue(rx[VXLAN].gpflags.A)
2380 self.assertFalse(rx[VXLAN].gpflags.D)
2382 inner = rx[VXLAN].payload
2384 self.assertEqual(inner[Ether].src, routed_src_mac)
2385 self.assertEqual(inner[Ether].dst, routed_dst_mac)
2386 self.assertEqual(inner[IP].src, ep.ip4.address)
2387 self.assertEqual(inner[IP].dst, ip)
2390 # remove the API remote EPs, only API sourced is gone, the DP
2391 # learnt one remains
2393 rep_88.remove_vpp_config()
2394 rep_2.remove_vpp_config()
2396 self.assertTrue(find_gbp_endpoint(self, ip=rep_2.ip4.address))
2398 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2399 IP(src=ep.ip4.address, dst=rep_2.ip4.address) /
2400 UDP(sport=1234, dport=1234) /
2402 rxs = self.send_and_expect(self.pg0, [p], self.pg2)
2404 self.assertFalse(find_gbp_endpoint(self, ip=rep_88.ip4.address))
2406 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2407 IP(src=ep.ip4.address, dst=rep_88.ip4.address) /
2408 UDP(sport=1234, dport=1234) /
2410 rxs = self.send_and_expect(self.pg0, [p], self.pg4)
2413 # to appease the testcase we cannot have the registered EP stll
2414 # present (because it's DP learnt) when the TC ends so wait until
2417 self.wait_for_ep_timeout(ip=rep_88.ip4.address)
2418 self.wait_for_ep_timeout(ip=rep_2.ip4.address)
2421 # shutdown with learnt endpoint present
2423 p = (Ether(src=self.pg2.remote_mac,
2424 dst=self.pg2.local_mac) /
2425 IP(src=self.pg2.remote_hosts[1].ip4,
2426 dst=self.pg2.local_ip4) /
2427 UDP(sport=1234, dport=48879) /
2428 VXLAN(vni=101, gpid=220, flags=0x88) /
2429 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2430 IP(src=learnt[1]['ip'], dst=ep.ip4.address) /
2431 UDP(sport=1234, dport=1234) /
2434 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2436 # endpoint learnt via the parent GBP-vxlan interface
2437 self.assertTrue(find_gbp_endpoint(self,
2438 vx_tun_l3._sw_if_index,
2443 # remote endpoint becomes local
2445 self.pg2.unconfig_ip4()
2446 self.pg3.unconfig_ip4()
2447 self.pg4.unconfig_ip4()
2449 def test_gbp_redirect(self):
2450 """ GBP Endpoint Redirect """
2452 self.vapi.cli("set logging class gbp debug")
2454 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
2455 routed_dst_mac = "00:0c:0c:0c:0c:0c"
2456 routed_src_mac = "00:22:bd:f8:19:ff"
2458 learnt = [{'mac': '00:00:11:11:11:02',
2460 'ip6': '2001:10::2'},
2461 {'mac': '00:00:11:11:11:03',
2463 'ip6': '2001:10::3'}]
2466 # lower the inactive threshold so these tests pass in a
2467 # reasonable amount of time
2469 self.vapi.gbp_endpoint_learn_set_inactive_threshold(2)
2474 t4 = VppIpTable(self, 1)
2476 t6 = VppIpTable(self, 1, True)
2479 rd1 = VppGbpRouteDomain(self, 2, t4, t6)
2480 rd1.add_vpp_config()
2482 self.loop0.set_mac(self.router_mac)
2485 # Bind the BVI to the RD
2487 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
2488 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
2491 # Pg7 hosts a BD's UU-fwd
2493 self.pg7.config_ip4()
2494 self.pg7.resolve_arp()
2497 # a GBP bridge domains for the EPs
2499 bd1 = VppBridgeDomain(self, 1)
2500 bd1.add_vpp_config()
2501 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0)
2502 gbd1.add_vpp_config()
2504 bd2 = VppBridgeDomain(self, 2)
2505 bd2.add_vpp_config()
2506 gbd2 = VppGbpBridgeDomain(self, bd2, self.loop1)
2507 gbd2.add_vpp_config()
2509 # ... and has a /32 and /128 applied
2510 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2511 ip4_addr.add_vpp_config()
2512 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 128)
2513 ip6_addr.add_vpp_config()
2514 ip4_addr = VppIpInterfaceAddress(self, gbd2.bvi, "10.0.1.128", 32)
2515 ip4_addr.add_vpp_config()
2516 ip6_addr = VppIpInterfaceAddress(self, gbd2.bvi, "2001:11::128", 128)
2517 ip6_addr.add_vpp_config()
2520 # The Endpoint-groups in which we are learning endpoints
2522 epg_220 = VppGbpEndpointGroup(self, 220, rd1, gbd1,
2526 epg_220.add_vpp_config()
2527 epg_221 = VppGbpEndpointGroup(self, 221, rd1, gbd2,
2531 epg_221.add_vpp_config()
2532 epg_222 = VppGbpEndpointGroup(self, 222, rd1, gbd1,
2536 epg_222.add_vpp_config()
2539 # a GBP bridge domains for the SEPs
2541 bd_uu1 = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
2542 self.pg7.remote_ip4, 116)
2543 bd_uu1.add_vpp_config()
2544 bd_uu2 = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
2545 self.pg7.remote_ip4, 117)
2546 bd_uu2.add_vpp_config()
2548 bd3 = VppBridgeDomain(self, 3)
2549 bd3.add_vpp_config()
2550 gbd3 = VppGbpBridgeDomain(self, bd3, self.loop2, bd_uu1, learn=False)
2551 gbd3.add_vpp_config()
2552 bd4 = VppBridgeDomain(self, 4)
2553 bd4.add_vpp_config()
2554 gbd4 = VppGbpBridgeDomain(self, bd4, self.loop3, bd_uu2, learn=False)
2555 gbd4.add_vpp_config()
2558 # EPGs in which the service endpoints exist
2560 epg_320 = VppGbpEndpointGroup(self, 320, rd1, gbd3,
2564 epg_320.add_vpp_config()
2565 epg_321 = VppGbpEndpointGroup(self, 321, rd1, gbd4,
2569 epg_321.add_vpp_config()
2572 # three local endpoints
2574 ep1 = VppGbpEndpoint(self, self.pg0,
2576 "10.0.0.1", "11.0.0.1",
2577 "2001:10::1", "3001:10::1")
2578 ep1.add_vpp_config()
2579 ep2 = VppGbpEndpoint(self, self.pg1,
2581 "10.0.1.1", "11.0.1.1",
2582 "2001:11::1", "3001:11::1")
2583 ep2.add_vpp_config()
2584 ep3 = VppGbpEndpoint(self, self.pg2,
2586 "10.0.2.2", "11.0.2.2",
2587 "2001:12::1", "3001:12::1")
2588 ep3.add_vpp_config()
2593 sep1 = VppGbpEndpoint(self, self.pg3,
2595 "12.0.0.1", "13.0.0.1",
2596 "4001:10::1", "5001:10::1")
2597 sep1.add_vpp_config()
2598 sep2 = VppGbpEndpoint(self, self.pg4,
2600 "12.0.0.2", "13.0.0.2",
2601 "4001:10::2", "5001:10::2")
2602 sep2.add_vpp_config()
2603 sep3 = VppGbpEndpoint(self, self.pg5,
2605 "12.0.1.1", "13.0.1.1",
2606 "4001:11::1", "5001:11::1")
2607 sep3.add_vpp_config()
2608 # this EP is not installed immediately
2609 sep4 = VppGbpEndpoint(self, self.pg6,
2611 "12.0.1.2", "13.0.1.2",
2612 "4001:11::2", "5001:11::2")
2615 # an L2 switch packet between local EPs in different EPGs
2616 # different dest ports on each so the are LB hashed differently
2618 p4 = [(Ether(src=ep1.mac, dst=ep3.mac) /
2619 IP(src=ep1.ip4.address, dst=ep3.ip4.address) /
2620 UDP(sport=1234, dport=1234) /
2622 (Ether(src=ep3.mac, dst=ep1.mac) /
2623 IP(src=ep3.ip4.address, dst=ep1.ip4.address) /
2624 UDP(sport=1234, dport=1234) /
2626 p6 = [(Ether(src=ep1.mac, dst=ep3.mac) /
2627 IPv6(src=ep1.ip6.address, dst=ep3.ip6.address) /
2628 UDP(sport=1234, dport=1234) /
2630 (Ether(src=ep3.mac, dst=ep1.mac) /
2631 IPv6(src=ep3.ip6.address, dst=ep1.ip6.address) /
2632 UDP(sport=1234, dport=1230) /
2635 # should be dropped since no contract yet
2636 self.send_and_assert_no_replies(self.pg0, [p4[0]])
2637 self.send_and_assert_no_replies(self.pg0, [p6[0]])
2640 # Add a contract with a rule to load-balance redirect via SEP1 and SEP2
2641 # one of the next-hops is via an EP that is not known
2643 acl = VppGbpAcl(self)
2644 rule4 = acl.create_rule(permit_deny=1, proto=17)
2645 rule6 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
2646 acl_index = acl.add_vpp_config([rule4, rule6])
2649 # test the src-ip hash mode
2651 c1 = VppGbpContract(
2652 self, 220, 222, acl_index,
2653 [VppGbpContractRule(
2654 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2655 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2656 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
2657 sep1.ip4, sep1.epg.rd),
2658 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
2659 sep2.ip4, sep2.epg.rd)]),
2661 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2662 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2663 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
2664 sep3.ip6, sep3.epg.rd),
2665 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
2666 sep4.ip6, sep4.epg.rd)])],
2667 [ETH_P_IP, ETH_P_IPV6])
2670 c2 = VppGbpContract(
2671 self, 222, 220, acl_index,
2672 [VppGbpContractRule(
2673 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2674 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2675 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
2676 sep1.ip4, sep1.epg.rd),
2677 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
2678 sep2.ip4, sep2.epg.rd)]),
2680 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2681 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2682 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
2683 sep3.ip6, sep3.epg.rd),
2684 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
2685 sep4.ip6, sep4.epg.rd)])],
2686 [ETH_P_IP, ETH_P_IPV6])
2690 # send again with the contract preset, now packets arrive
2691 # at SEP1 or SEP2 depending on the hashing
2693 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
2696 self.assertEqual(rx[Ether].src, routed_src_mac)
2697 self.assertEqual(rx[Ether].dst, sep1.mac)
2698 self.assertEqual(rx[IP].src, ep1.ip4.address)
2699 self.assertEqual(rx[IP].dst, ep3.ip4.address)
2701 rxs = self.send_and_expect(self.pg2, p4[1] * 17, sep2.itf)
2704 self.assertEqual(rx[Ether].src, routed_src_mac)
2705 self.assertEqual(rx[Ether].dst, sep2.mac)
2706 self.assertEqual(rx[IP].src, ep3.ip4.address)
2707 self.assertEqual(rx[IP].dst, ep1.ip4.address)
2709 rxs = self.send_and_expect(self.pg0, p6[0] * 17, self.pg7)
2712 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
2713 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
2714 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
2715 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
2716 self.assertEqual(rx[VXLAN].vni, 117)
2717 self.assertTrue(rx[VXLAN].flags.G)
2718 self.assertTrue(rx[VXLAN].flags.Instance)
2719 # redirect policy has been applied
2720 self.assertTrue(rx[VXLAN].gpflags.A)
2721 self.assertFalse(rx[VXLAN].gpflags.D)
2723 inner = rx[VXLAN].payload
2725 self.assertEqual(inner[Ether].src, routed_src_mac)
2726 self.assertEqual(inner[Ether].dst, sep4.mac)
2727 self.assertEqual(inner[IPv6].src, ep1.ip6.address)
2728 self.assertEqual(inner[IPv6].dst, ep3.ip6.address)
2730 rxs = self.send_and_expect(self.pg2, p6[1] * 17, sep3.itf)
2733 self.assertEqual(rx[Ether].src, routed_src_mac)
2734 self.assertEqual(rx[Ether].dst, sep3.mac)
2735 self.assertEqual(rx[IPv6].src, ep3.ip6.address)
2736 self.assertEqual(rx[IPv6].dst, ep1.ip6.address)
2739 # programme the unknown EP
2741 sep4.add_vpp_config()
2743 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep4.itf)
2746 self.assertEqual(rx[Ether].src, routed_src_mac)
2747 self.assertEqual(rx[Ether].dst, sep4.mac)
2748 self.assertEqual(rx[IPv6].src, ep1.ip6.address)
2749 self.assertEqual(rx[IPv6].dst, ep3.ip6.address)
2752 # and revert back to unprogrammed
2754 sep4.remove_vpp_config()
2756 rxs = self.send_and_expect(self.pg0, p6[0] * 17, self.pg7)
2759 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
2760 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
2761 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
2762 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
2763 self.assertEqual(rx[VXLAN].vni, 117)
2764 self.assertTrue(rx[VXLAN].flags.G)
2765 self.assertTrue(rx[VXLAN].flags.Instance)
2766 # redirect policy has been applied
2767 self.assertTrue(rx[VXLAN].gpflags.A)
2768 self.assertFalse(rx[VXLAN].gpflags.D)
2770 inner = rx[VXLAN].payload
2772 self.assertEqual(inner[Ether].src, routed_src_mac)
2773 self.assertEqual(inner[Ether].dst, sep4.mac)
2774 self.assertEqual(inner[IPv6].src, ep1.ip6.address)
2775 self.assertEqual(inner[IPv6].dst, ep3.ip6.address)
2777 c1.remove_vpp_config()
2778 c2.remove_vpp_config()
2781 # test the symmetric hash mode
2783 c1 = VppGbpContract(
2784 self, 220, 222, acl_index,
2785 [VppGbpContractRule(
2786 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2787 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
2788 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
2789 sep1.ip4, sep1.epg.rd),
2790 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
2791 sep2.ip4, sep2.epg.rd)]),
2793 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2794 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
2795 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
2796 sep3.ip6, sep3.epg.rd),
2797 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
2798 sep4.ip6, sep4.epg.rd)])],
2799 [ETH_P_IP, ETH_P_IPV6])
2802 c2 = VppGbpContract(
2803 self, 222, 220, acl_index,
2804 [VppGbpContractRule(
2805 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2806 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
2807 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
2808 sep1.ip4, sep1.epg.rd),
2809 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
2810 sep2.ip4, sep2.epg.rd)]),
2812 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2813 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
2814 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
2815 sep3.ip6, sep3.epg.rd),
2816 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
2817 sep4.ip6, sep4.epg.rd)])],
2818 [ETH_P_IP, ETH_P_IPV6])
2822 # send again with the contract preset, now packets arrive
2823 # at SEP1 for both directions
2825 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
2828 self.assertEqual(rx[Ether].src, routed_src_mac)
2829 self.assertEqual(rx[Ether].dst, sep1.mac)
2830 self.assertEqual(rx[IP].src, ep1.ip4.address)
2831 self.assertEqual(rx[IP].dst, ep3.ip4.address)
2833 rxs = self.send_and_expect(self.pg2, p4[1] * 17, sep1.itf)
2836 self.assertEqual(rx[Ether].src, routed_src_mac)
2837 self.assertEqual(rx[Ether].dst, sep1.mac)
2838 self.assertEqual(rx[IP].src, ep3.ip4.address)
2839 self.assertEqual(rx[IP].dst, ep1.ip4.address)
2842 # programme the unknown EP for the L3 tests
2844 sep4.add_vpp_config()
2847 # an L3 switch packet between local EPs in different EPGs
2848 # different dest ports on each so the are LB hashed differently
2850 p4 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
2851 IP(src=ep1.ip4.address, dst=ep2.ip4.address) /
2852 UDP(sport=1234, dport=1234) /
2854 (Ether(src=ep2.mac, dst=str(self.router_mac)) /
2855 IP(src=ep2.ip4.address, dst=ep1.ip4.address) /
2856 UDP(sport=1234, dport=1234) /
2858 p6 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
2859 IPv6(src=ep1.ip6.address, dst=ep2.ip6.address) /
2860 UDP(sport=1234, dport=1234) /
2862 (Ether(src=ep2.mac, dst=str(self.router_mac)) /
2863 IPv6(src=ep2.ip6.address, dst=ep1.ip6.address) /
2864 UDP(sport=1234, dport=1234) /
2867 c3 = VppGbpContract(
2868 self, 220, 221, acl_index,
2869 [VppGbpContractRule(
2870 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2871 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
2872 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
2873 sep1.ip4, sep1.epg.rd),
2874 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
2875 sep2.ip4, sep2.epg.rd)]),
2877 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2878 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
2879 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
2880 sep3.ip6, sep3.epg.rd),
2881 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
2882 sep4.ip6, sep4.epg.rd)])],
2883 [ETH_P_IP, ETH_P_IPV6])
2886 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
2889 self.assertEqual(rx[Ether].src, routed_src_mac)
2890 self.assertEqual(rx[Ether].dst, sep1.mac)
2891 self.assertEqual(rx[IP].src, ep1.ip4.address)
2892 self.assertEqual(rx[IP].dst, ep2.ip4.address)
2895 # learn a remote EP in EPG 221
2897 vx_tun_l3 = VppGbpVxlanTunnel(
2898 self, 444, rd1.rd_id,
2899 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3)
2900 vx_tun_l3.add_vpp_config()
2902 c4 = VppGbpContract(
2903 self, 221, 220, acl_index,
2904 [VppGbpContractRule(
2905 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2908 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2910 [ETH_P_IP, ETH_P_IPV6])
2913 p = (Ether(src=self.pg7.remote_mac,
2914 dst=self.pg7.local_mac) /
2915 IP(src=self.pg7.remote_ip4,
2916 dst=self.pg7.local_ip4) /
2917 UDP(sport=1234, dport=48879) /
2918 VXLAN(vni=444, gpid=221, flags=0x88) /
2919 Ether(src="00:22:22:22:22:33", dst=str(self.router_mac)) /
2920 IP(src="10.0.0.88", dst=ep1.ip4.address) /
2921 UDP(sport=1234, dport=1234) /
2924 rx = self.send_and_expect(self.pg7, [p], self.pg0)
2926 # endpoint learnt via the parent GBP-vxlan interface
2927 self.assertTrue(find_gbp_endpoint(self,
2928 vx_tun_l3._sw_if_index,
2931 p = (Ether(src=self.pg7.remote_mac,
2932 dst=self.pg7.local_mac) /
2933 IP(src=self.pg7.remote_ip4,
2934 dst=self.pg7.local_ip4) /
2935 UDP(sport=1234, dport=48879) /
2936 VXLAN(vni=444, gpid=221, flags=0x88) /
2937 Ether(src="00:22:22:22:22:33", dst=str(self.router_mac)) /
2938 IPv6(src="2001:10::88", dst=ep1.ip6.address) /
2939 UDP(sport=1234, dport=1234) /
2942 rx = self.send_and_expect(self.pg7, [p], self.pg0)
2944 # endpoint learnt via the parent GBP-vxlan interface
2945 self.assertTrue(find_gbp_endpoint(self,
2946 vx_tun_l3._sw_if_index,
2950 # L3 switch from local to remote EP
2952 p4 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
2953 IP(src=ep1.ip4.address, dst="10.0.0.88") /
2954 UDP(sport=1234, dport=1234) /
2956 p6 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
2957 IPv6(src=ep1.ip6.address, dst="2001:10::88") /
2958 UDP(sport=1234, dport=1234) /
2961 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
2964 self.assertEqual(rx[Ether].src, routed_src_mac)
2965 self.assertEqual(rx[Ether].dst, sep1.mac)
2966 self.assertEqual(rx[IP].src, ep1.ip4.address)
2967 self.assertEqual(rx[IP].dst, "10.0.0.88")
2969 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep4.itf)
2972 self.assertEqual(rx[Ether].src, routed_src_mac)
2973 self.assertEqual(rx[Ether].dst, sep4.mac)
2974 self.assertEqual(rx[IPv6].src, ep1.ip6.address)
2975 self.assertEqual(rx[IPv6].dst, "2001:10::88")
2978 # test the dst-ip hash mode
2980 c5 = VppGbpContract(
2981 self, 220, 221, acl_index,
2982 [VppGbpContractRule(
2983 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2984 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
2985 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
2986 sep1.ip4, sep1.epg.rd),
2987 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
2988 sep2.ip4, sep2.epg.rd)]),
2990 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2991 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
2992 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
2993 sep3.ip6, sep3.epg.rd),
2994 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
2995 sep4.ip6, sep4.epg.rd)])],
2996 [ETH_P_IP, ETH_P_IPV6])
2999 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3002 self.assertEqual(rx[Ether].src, routed_src_mac)
3003 self.assertEqual(rx[Ether].dst, sep1.mac)
3004 self.assertEqual(rx[IP].src, ep1.ip4.address)
3005 self.assertEqual(rx[IP].dst, "10.0.0.88")
3007 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep3.itf)
3010 self.assertEqual(rx[Ether].src, routed_src_mac)
3011 self.assertEqual(rx[Ether].dst, sep3.mac)
3012 self.assertEqual(rx[IPv6].src, ep1.ip6.address)
3013 self.assertEqual(rx[IPv6].dst, "2001:10::88")
3018 self.pg7.unconfig_ip4()
3020 def test_gbp_l3_out(self):
3023 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
3024 self.vapi.cli("set logging class gbp debug")
3026 routed_dst_mac = "00:0c:0c:0c:0c:0c"
3027 routed_src_mac = "00:22:bd:f8:19:ff"
3032 t4 = VppIpTable(self, 1)
3034 t6 = VppIpTable(self, 1, True)
3037 rd1 = VppGbpRouteDomain(self, 2, t4, t6)
3038 rd1.add_vpp_config()
3040 self.loop0.set_mac(self.router_mac)
3043 # Bind the BVI to the RD
3045 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
3046 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
3049 # Pg7 hosts a BD's BUM
3050 # Pg1 some other l3 interface
3052 self.pg7.config_ip4()
3053 self.pg7.resolve_arp()
3056 # a GBP external bridge domains for the EPs
3058 bd1 = VppBridgeDomain(self, 1)
3059 bd1.add_vpp_config()
3060 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0)
3061 gbd1.add_vpp_config()
3064 # The Endpoint-groups in which the external endpoints exist
3066 epg_220 = VppGbpEndpointGroup(self, 220, rd1, gbd1,
3070 epg_220.add_vpp_config()
3072 # the BVIs have the subnets applied ...
3073 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 24)
3074 ip4_addr.add_vpp_config()
3075 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 64)
3076 ip6_addr.add_vpp_config()
3078 # ... which are L3-out subnets
3079 l3o_1 = VppGbpSubnet(
3080 self, rd1, "10.0.0.0", 24,
3081 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3083 l3o_1.add_vpp_config()
3086 # an external interface attached to the outside world and the
3089 vlan_100 = VppDot1QSubint(self, self.pg0, 100)
3091 ext_itf = VppGbpExtItf(self, vlan_100, bd1, rd1)
3092 ext_itf.add_vpp_config()
3095 # a multicast vxlan-gbp tunnel for broadcast in the BD
3097 tun_bm = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
3100 tun_bm.add_vpp_config()
3101 bp_bm = VppBridgeDomainPort(self, bd1, tun_bm,
3102 port_type=L2_PORT_TYPE.NORMAL)
3103 bp_bm.add_vpp_config()
3106 # an unicast vxlan-gbp for inter-BD traffic
3108 vx_tun_l3 = VppGbpVxlanTunnel(
3109 self, 444, rd1.rd_id,
3110 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3)
3111 vx_tun_l3.add_vpp_config()
3114 # packets destined to unkown addresses in the BVI's subnet
3117 p4 = (Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
3119 IP(src="10.0.0.1", dst="10.0.0.88") /
3120 UDP(sport=1234, dport=1234) /
3122 p6 = (Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
3124 IPv6(src="2001:10::1", dst="2001:10::88") /
3125 UDP(sport=1234, dport=1234) /
3128 rxs = self.send_and_expect(self.pg0, p4 * 1, self.pg7)
3131 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3132 # self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3133 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3134 self.assertEqual(rx[IP].dst, "239.1.1.1")
3135 self.assertEqual(rx[VXLAN].vni, 88)
3136 self.assertTrue(rx[VXLAN].flags.G)
3137 self.assertTrue(rx[VXLAN].flags.Instance)
3138 # policy was applied to the original IP packet
3139 self.assertEqual(rx[VXLAN].gpid, 200)
3140 self.assertTrue(rx[VXLAN].gpflags.A)
3141 self.assertFalse(rx[VXLAN].gpflags.D)
3143 inner = rx[VXLAN].payload
3145 self.assertTrue(inner.haslayer(ARP))
3148 # An external Endpoint
3150 eep = VppGbpEndpoint(self, vlan_100,
3152 "10.0.0.1", "11.0.0.1",
3153 "2001:10::1", "3001::1",
3154 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
3155 eep.add_vpp_config()
3160 rep = VppGbpEndpoint(self, vx_tun_l3,
3162 "10.0.0.101", "11.0.0.101",
3163 "2001:10::101", "3001::101",
3164 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
3166 self.pg7.remote_ip4,
3168 rep.add_vpp_config()
3171 # remote to external
3173 p = (Ether(src=self.pg7.remote_mac,
3174 dst=self.pg7.local_mac) /
3175 IP(src=self.pg7.remote_ip4,
3176 dst=self.pg7.local_ip4) /
3177 UDP(sport=1234, dport=48879) /
3178 VXLAN(vni=444, gpid=220, flags=0x88) /
3179 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
3180 IP(src="10.0.0.101", dst="10.0.0.1") /
3181 UDP(sport=1234, dport=1234) /
3184 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
3187 # A subnet reachable through the external EP
3189 ip_220 = VppIpRoute(self, "10.220.0.0", 24,
3190 [VppRoutePath(eep.ip4.address,
3191 eep.epg.bvi.sw_if_index)],
3192 table_id=t4.table_id)
3193 ip_220.add_vpp_config()
3195 l3o_220 = VppGbpSubnet(
3196 self, rd1, "10.220.0.0", 24,
3197 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3199 l3o_220.add_vpp_config()
3201 p = (Ether(src=self.pg7.remote_mac,
3202 dst=self.pg7.local_mac) /
3203 IP(src=self.pg7.remote_ip4,
3204 dst=self.pg7.local_ip4) /
3205 UDP(sport=1234, dport=48879) /
3206 VXLAN(vni=444, gpid=220, flags=0x88) /
3207 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
3208 IP(src="10.0.0.101", dst="10.220.0.1") /
3209 UDP(sport=1234, dport=1234) /
3212 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
3215 # another external subnet, this time in a different EPG
3217 ip_200 = VppIpRoute(self, "10.200.0.0", 24,
3218 [VppRoutePath(eep.ip4.address,
3219 eep.epg.bvi.sw_if_index)],
3220 table_id=t4.table_id)
3221 ip_200.add_vpp_config()
3223 l3o_200 = VppGbpSubnet(
3224 self, rd1, "10.200.0.0", 24,
3225 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3227 l3o_200.add_vpp_config()
3229 p = (Ether(src=self.pg7.remote_mac,
3230 dst=self.pg7.local_mac) /
3231 IP(src=self.pg7.remote_ip4,
3232 dst=self.pg7.local_ip4) /
3233 UDP(sport=1234, dport=48879) /
3234 VXLAN(vni=444, gpid=220, flags=0x88) /
3235 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
3236 IP(src="10.0.0.101", dst="10.200.0.1") /
3237 UDP(sport=1234, dport=1234) /
3241 # packets dropped due to lack of contract.
3243 rxs = self.send_and_assert_no_replies(self.pg7, p * 1)
3246 # from the the subnet in EPG 220 beyond the external to remote
3248 p4 = (Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
3250 IP(src="10.220.0.1", dst=rep.ip4.address) /
3251 UDP(sport=1234, dport=1234) /
3254 rxs = self.send_and_expect(self.pg0, p4 * 1, self.pg7)
3257 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3258 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3259 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3260 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
3261 self.assertEqual(rx[VXLAN].vni, 444)
3262 self.assertTrue(rx[VXLAN].flags.G)
3263 self.assertTrue(rx[VXLAN].flags.Instance)
3264 self.assertTrue(rx[VXLAN].gpflags.A)
3265 self.assertFalse(rx[VXLAN].gpflags.D)
3268 # from the the subnet in EPG 200 beyond the external to remote
3269 # dropped due to no contract
3271 p4 = (Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
3273 IP(src="10.200.0.1", dst=rep.ip4.address) /
3274 UDP(sport=1234, dport=1234) /
3277 rxs = self.send_and_assert_no_replies(self.pg0, p4 * 1)
3282 acl = VppGbpAcl(self)
3283 rule = acl.create_rule(permit_deny=1, proto=17)
3284 rule2 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
3285 acl_index = acl.add_vpp_config([rule, rule2])
3286 c1 = VppGbpContract(
3287 self, 200, 220, acl_index,
3288 [VppGbpContractRule(
3289 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3292 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3294 [ETH_P_IP, ETH_P_IPV6])
3297 rxs = self.send_and_expect(self.pg0, p4 * 1, self.pg7)
3300 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3301 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3302 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3303 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
3304 self.assertEqual(rx[VXLAN].vni, 444)
3305 self.assertTrue(rx[VXLAN].flags.G)
3306 self.assertTrue(rx[VXLAN].flags.Instance)
3307 self.assertTrue(rx[VXLAN].gpflags.A)
3308 self.assertFalse(rx[VXLAN].gpflags.D)
3313 self.pg7.unconfig_ip4()
3316 if __name__ == '__main__':
3317 unittest.main(testRunner=VppTestRunner)