3 from socket import AF_INET, AF_INET6
6 from scapy.packet import Raw
7 from scapy.layers.l2 import Ether, ARP, Dot1Q
8 from scapy.layers.inet import IP, UDP, ICMP
9 from scapy.layers.inet6 import IPv6, ICMPv6ND_NS, ICMPv6NDOptSrcLLAddr, \
11 from scapy.utils6 import in6_getnsma, in6_getnsmac
12 from scapy.layers.vxlan import VXLAN
13 from scapy.data import ETH_P_IP, ETH_P_IPV6
14 from scapy.utils import inet_pton, inet_ntop
16 from framework import VppTestCase, VppTestRunner
17 from vpp_object import VppObject
18 from vpp_interface import VppInterface
19 from vpp_ip_route import VppIpRoute, VppRoutePath, VppIpTable, \
20 VppIpInterfaceAddress, VppIpInterfaceBind, find_route
21 from vpp_l2 import VppBridgeDomain, VppBridgeDomainPort, \
22 VppBridgeDomainArpEntry, VppL2FibEntry, find_bridge_domain_port, VppL2Vtr
23 from vpp_sub_interface import L2_VTR_OP, VppDot1QSubint
24 from vpp_ip import VppIpAddress, VppIpPrefix
25 from vpp_papi import VppEnum, MACAddress
26 from vpp_vxlan_gbp_tunnel import find_vxlan_gbp_tunnel, INDEX_INVALID, \
28 from vpp_neighbor import VppNeighbor
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):
90 return [self.ip4, self.ip6]
94 return [self.fip4, self.fip6]
96 def __init__(self, test, itf, epg, recirc, ip4, fip4, ip6, fip6,
106 self._ip4 = VppIpAddress(ip4)
107 self._fip4 = VppIpAddress(fip4)
108 self._ip6 = VppIpAddress(ip6)
109 self._fip6 = VppIpAddress(fip6)
112 self.vmac = MACAddress(self.itf.remote_mac)
114 self.vmac = MACAddress("00:00:00:00:00:00")
117 self.tun_src = VppIpAddress(tun_src)
118 self.tun_dst = VppIpAddress(tun_dst)
120 def add_vpp_config(self):
121 res = self._test.vapi.gbp_endpoint_add(
122 self.itf.sw_if_index,
123 [self.ip4.encode(), self.ip6.encode()],
127 self.tun_src.encode(),
128 self.tun_dst.encode())
129 self.handle = res.handle
130 self._test.registry.register(self, self._test.logger)
132 def remove_vpp_config(self):
133 self._test.vapi.gbp_endpoint_del(self.handle)
136 return "gbp-endpoint:[%d==%d:%s:%d]" % (self.handle,
137 self.itf.sw_if_index,
141 def query_vpp_config(self):
142 return find_gbp_endpoint(self._test,
143 self.itf.sw_if_index,
147 class VppGbpRecirc(VppObject):
149 GBP Recirculation Interface
152 def __init__(self, test, epg, recirc, is_ext=False):
158 def add_vpp_config(self):
159 self._test.vapi.gbp_recirc_add_del(
161 self.recirc.sw_if_index,
164 self._test.registry.register(self, self._test.logger)
166 def remove_vpp_config(self):
167 self._test.vapi.gbp_recirc_add_del(
169 self.recirc.sw_if_index,
174 return "gbp-recirc:[%d]" % (self.recirc.sw_if_index)
176 def query_vpp_config(self):
177 rs = self._test.vapi.gbp_recirc_dump()
179 if r.recirc.sw_if_index == self.recirc.sw_if_index:
184 class VppGbpExtItf(VppObject):
186 GBP ExtItfulation Interface
189 def __init__(self, test, itf, bd, rd):
195 def add_vpp_config(self):
196 self._test.vapi.gbp_ext_itf_add_del(
198 self.itf.sw_if_index,
201 self._test.registry.register(self, self._test.logger)
203 def remove_vpp_config(self):
204 self._test.vapi.gbp_ext_itf_add_del(
206 self.itf.sw_if_index,
211 return "gbp-ext-itf:[%d]" % (self.itf.sw_if_index)
213 def query_vpp_config(self):
214 rs = self._test.vapi.gbp_ext_itf_dump()
216 if r.ext_itf.sw_if_index == self.itf.sw_if_index:
221 class VppGbpSubnet(VppObject):
226 def __init__(self, test, rd, address, address_len,
227 type, sw_if_index=None, sclass=None):
229 self.rd_id = rd.rd_id
230 self.prefix = VppIpPrefix(address, address_len)
232 self.sw_if_index = sw_if_index
235 def add_vpp_config(self):
236 self._test.vapi.gbp_subnet_add_del(
239 self.prefix.encode(),
241 sw_if_index=self.sw_if_index if self.sw_if_index else 0xffffffff,
242 sclass=self.sclass if self.sclass else 0xffff)
243 self._test.registry.register(self, self._test.logger)
245 def remove_vpp_config(self):
246 self._test.vapi.gbp_subnet_add_del(
249 self.prefix.encode(),
253 return "gbp-subnet:[%d-%s]" % (self.rd_id, self.prefix)
255 def query_vpp_config(self):
256 ss = self._test.vapi.gbp_subnet_dump()
258 if s.subnet.rd_id == self.rd_id and \
259 s.subnet.type == self.type and \
260 s.subnet.prefix == self.prefix:
265 class VppGbpEndpointRetention(object):
266 def __init__(self, remote_ep_timeout=0xffffffff):
267 self.remote_ep_timeout = remote_ep_timeout
270 return {'remote_ep_timeout': self.remote_ep_timeout}
273 class VppGbpEndpointGroup(VppObject):
278 def __init__(self, test, vnid, sclass, rd, bd, uplink,
279 bvi, bvi_ip4, bvi_ip6=None,
280 retention=VppGbpEndpointRetention()):
284 self.bvi_ip4 = VppIpAddress(bvi_ip4)
285 self.bvi_ip6 = VppIpAddress(bvi_ip6)
292 self.retention = retention
294 def add_vpp_config(self):
295 self._test.vapi.gbp_endpoint_group_add(
300 self.uplink.sw_if_index if self.uplink else INDEX_INVALID,
301 self.retention.encode())
302 self._test.registry.register(self, self._test.logger)
304 def remove_vpp_config(self):
305 self._test.vapi.gbp_endpoint_group_del(self.sclass)
308 return "gbp-endpoint-group:[%d]" % (self.vnid)
310 def query_vpp_config(self):
311 epgs = self._test.vapi.gbp_endpoint_group_dump()
313 if epg.epg.vnid == self.vnid:
318 class VppGbpBridgeDomain(VppObject):
323 def __init__(self, test, bd, bvi, uu_fwd=None,
324 bm_flood=None, learn=True, uu_drop=False, bm_drop=False):
328 self.bm_flood = bm_flood
331 e = VppEnum.vl_api_gbp_bridge_domain_flags_t
333 self.learn = e.GBP_BD_API_FLAG_NONE
335 self.learn = e.GBP_BD_API_FLAG_DO_NOT_LEARN
337 self.learn |= e.GBP_BD_API_FLAG_UU_FWD_DROP
339 self.learn |= e.GBP_BD_API_FLAG_MCAST_DROP
341 def add_vpp_config(self):
342 self._test.vapi.gbp_bridge_domain_add(
345 self.bvi.sw_if_index,
346 self.uu_fwd.sw_if_index if self.uu_fwd else INDEX_INVALID,
347 self.bm_flood.sw_if_index if self.bm_flood else INDEX_INVALID)
348 self._test.registry.register(self, self._test.logger)
350 def remove_vpp_config(self):
351 self._test.vapi.gbp_bridge_domain_del(self.bd.bd_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 "gbp-route-domain:[%d]" % (self.rd_id)
392 def query_vpp_config(self):
393 rds = self._test.vapi.gbp_route_domain_dump()
395 if rd.rd.rd_id == self.rd_id:
400 class VppGbpContractNextHop():
401 def __init__(self, mac, bd, ip, rd):
408 return {'ip': self.ip.encode(),
409 'mac': self.mac.packed,
410 'bd_id': self.bd.bd.bd_id,
411 'rd_id': self.rd.rd_id}
414 class VppGbpContractRule():
415 def __init__(self, action, hash_mode, nhs=[]):
417 self.hash_mode = hash_mode
423 nhs.append(nh.encode())
426 return {'action': self.action,
428 'hash_mode': self.hash_mode,
429 'n_nhs': len(self.nhs),
433 class VppGbpContract(VppObject):
438 def __init__(self, test, sclass, dclass, acl_index,
439 rules, allowed_ethertypes):
441 self.acl_index = acl_index
445 self.allowed_ethertypes = allowed_ethertypes
446 while (len(self.allowed_ethertypes) < 16):
447 self.allowed_ethertypes.append(0)
449 def add_vpp_config(self):
452 rules.append(r.encode())
453 r = self._test.vapi.gbp_contract_add_del(
459 self.allowed_ethertypes)
460 self.stats_index = r.stats_index
461 self._test.registry.register(self, self._test.logger)
463 def remove_vpp_config(self):
464 self._test.vapi.gbp_contract_add_del(
470 self.allowed_ethertypes)
473 return "gbp-contract:[%d:%s:%d]" % (self.sclass,
477 def query_vpp_config(self):
478 cs = self._test.vapi.gbp_contract_dump()
480 if c.contract.sclass == self.sclass \
481 and c.contract.dclass == self.dclass:
485 def get_drop_stats(self):
486 c = self._test.statistics.get_counter("/net/gbp/contract/drop")
487 return c[0][self.stats_index]
489 def get_permit_stats(self):
490 c = self._test.statistics.get_counter("/net/gbp/contract/permit")
491 return c[0][self.stats_index]
494 class VppGbpVxlanTunnel(VppInterface):
499 def __init__(self, test, vni, bd_rd_id, mode, src):
500 super(VppGbpVxlanTunnel, self).__init__(test)
503 self.bd_rd_id = bd_rd_id
507 def add_vpp_config(self):
508 r = self._test.vapi.gbp_vxlan_tunnel_add(
513 self.set_sw_if_index(r.sw_if_index)
514 self._test.registry.register(self, self._test.logger)
516 def remove_vpp_config(self):
517 self._test.vapi.gbp_vxlan_tunnel_del(self.vni)
520 return "gbp-vxlan:%d" % (self.sw_if_index)
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=b'\x00\x00\x00\x00', sport_from=0,
537 sport_to=65535, d_prefix=0, d_ip=b'\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 "gbp-acl:[%d]" % (self.acl_index)
570 def query_vpp_config(self):
571 cs = self._test.vapi.acl_dump()
573 if c.acl_index == self.acl_index:
578 class TestGBP(VppTestCase):
579 """ GBP Test Case """
582 def config_flags(self):
583 return VppEnum.vl_api_nat_config_flags_t
587 super(TestGBP, cls).setUpClass()
590 def tearDownClass(cls):
591 super(TestGBP, cls).tearDownClass()
594 super(TestGBP, self).setUp()
596 self.create_pg_interfaces(range(9))
597 self.create_loopback_interfaces(8)
599 self.router_mac = MACAddress("00:11:22:33:44:55")
601 for i in self.pg_interfaces:
603 for i in self.lo_interfaces:
607 for i in self.pg_interfaces:
610 super(TestGBP, self).tearDown()
612 def send_and_expect_bridged(self, src, tx, dst):
613 rx = self.send_and_expect(src, tx, dst)
616 self.assertEqual(r[Ether].src, tx[0][Ether].src)
617 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
618 self.assertEqual(r[IP].src, tx[0][IP].src)
619 self.assertEqual(r[IP].dst, tx[0][IP].dst)
622 def send_and_expect_bridged6(self, src, tx, dst):
623 rx = self.send_and_expect(src, tx, dst)
626 self.assertEqual(r[Ether].src, tx[0][Ether].src)
627 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
628 self.assertEqual(r[IPv6].src, tx[0][IPv6].src)
629 self.assertEqual(r[IPv6].dst, tx[0][IPv6].dst)
632 def send_and_expect_routed(self, src, tx, dst, src_mac):
633 rx = self.send_and_expect(src, tx, dst)
636 self.assertEqual(r[Ether].src, src_mac)
637 self.assertEqual(r[Ether].dst, dst.remote_mac)
638 self.assertEqual(r[IP].src, tx[0][IP].src)
639 self.assertEqual(r[IP].dst, tx[0][IP].dst)
642 def send_and_expect_natted(self, src, tx, dst, src_ip):
643 rx = self.send_and_expect(src, tx, dst)
646 self.assertEqual(r[Ether].src, tx[0][Ether].src)
647 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
648 self.assertEqual(r[IP].src, src_ip)
649 self.assertEqual(r[IP].dst, tx[0][IP].dst)
652 def send_and_expect_natted6(self, src, tx, dst, src_ip):
653 rx = self.send_and_expect(src, tx, dst)
656 self.assertEqual(r[Ether].src, tx[0][Ether].src)
657 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
658 self.assertEqual(r[IPv6].src, src_ip)
659 self.assertEqual(r[IPv6].dst, tx[0][IPv6].dst)
662 def send_and_expect_unnatted(self, src, tx, dst, dst_ip):
663 rx = self.send_and_expect(src, tx, dst)
666 self.assertEqual(r[Ether].src, tx[0][Ether].src)
667 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
668 self.assertEqual(r[IP].dst, dst_ip)
669 self.assertEqual(r[IP].src, tx[0][IP].src)
672 def send_and_expect_unnatted6(self, src, tx, dst, dst_ip):
673 rx = self.send_and_expect(src, tx, dst)
676 self.assertEqual(r[Ether].src, tx[0][Ether].src)
677 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
678 self.assertEqual(r[IPv6].dst, dst_ip)
679 self.assertEqual(r[IPv6].src, tx[0][IPv6].src)
682 def send_and_expect_double_natted(self, src, tx, dst, src_ip, dst_ip):
683 rx = self.send_and_expect(src, tx, dst)
686 self.assertEqual(r[Ether].src, str(self.router_mac))
687 self.assertEqual(r[Ether].dst, dst.remote_mac)
688 self.assertEqual(r[IP].dst, dst_ip)
689 self.assertEqual(r[IP].src, src_ip)
692 def send_and_expect_double_natted6(self, src, tx, dst, src_ip, dst_ip):
693 rx = self.send_and_expect(src, tx, dst)
696 self.assertEqual(r[Ether].src, str(self.router_mac))
697 self.assertEqual(r[Ether].dst, dst.remote_mac)
698 self.assertEqual(r[IPv6].dst, dst_ip)
699 self.assertEqual(r[IPv6].src, src_ip)
703 """ Group Based Policy """
705 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
710 bd1 = VppBridgeDomain(self, 1)
711 bd2 = VppBridgeDomain(self, 2)
712 bd20 = VppBridgeDomain(self, 20)
716 bd20.add_vpp_config()
718 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0)
719 gbd2 = VppGbpBridgeDomain(self, bd2, self.loop1)
720 gbd20 = VppGbpBridgeDomain(self, bd20, self.loop2)
722 gbd1.add_vpp_config()
723 gbd2.add_vpp_config()
724 gbd20.add_vpp_config()
729 gt4 = VppIpTable(self, 0)
731 gt6 = VppIpTable(self, 0, is_ip6=True)
733 nt4 = VppIpTable(self, 20)
735 nt6 = VppIpTable(self, 20, is_ip6=True)
738 rd0 = VppGbpRouteDomain(self, 0, gt4, gt6, None, None)
739 rd20 = VppGbpRouteDomain(self, 20, nt4, nt6, None, None)
742 rd20.add_vpp_config()
745 # 3 EPGs, 2 of which share a BD.
746 # 2 NAT EPGs, one for floating-IP subnets, the other for internet
748 epgs = [VppGbpEndpointGroup(self, 220, 1220, rd0, gbd1,
749 self.pg4, self.loop0,
750 "10.0.0.128", "2001:10::128"),
751 VppGbpEndpointGroup(self, 221, 1221, rd0, gbd1,
752 self.pg5, self.loop0,
753 "10.0.1.128", "2001:10:1::128"),
754 VppGbpEndpointGroup(self, 222, 1222, rd0, gbd2,
755 self.pg6, self.loop1,
756 "10.0.2.128", "2001:10:2::128"),
757 VppGbpEndpointGroup(self, 333, 1333, rd20, gbd20,
758 self.pg7, self.loop2,
759 "11.0.0.128", "3001::128"),
760 VppGbpEndpointGroup(self, 444, 1444, rd20, gbd20,
761 self.pg8, self.loop2,
762 "11.0.0.129", "3001::129")]
763 recircs = [VppGbpRecirc(self, epgs[0], self.loop3),
764 VppGbpRecirc(self, epgs[1], self.loop4),
765 VppGbpRecirc(self, epgs[2], self.loop5),
766 VppGbpRecirc(self, epgs[3], self.loop6, is_ext=True),
767 VppGbpRecirc(self, epgs[4], self.loop7, is_ext=True)]
770 recirc_nat = recircs[3]
773 # 4 end-points, 2 in the same subnet, 3 in the same BD
775 eps = [VppGbpEndpoint(self, self.pg0,
777 "10.0.0.1", "11.0.0.1",
778 "2001:10::1", "3001::1"),
779 VppGbpEndpoint(self, self.pg1,
781 "10.0.0.2", "11.0.0.2",
782 "2001:10::2", "3001::2"),
783 VppGbpEndpoint(self, self.pg2,
785 "10.0.1.1", "11.0.0.3",
786 "2001:10:1::1", "3001::3"),
787 VppGbpEndpoint(self, self.pg3,
789 "10.0.2.1", "11.0.0.4",
790 "2001:10:2::1", "3001::4")]
793 # Config related to each of the EPGs
796 # IP config on the BVI interfaces
797 if epg != epgs[1] and epg != epgs[4]:
798 VppIpInterfaceBind(self, epg.bvi, epg.rd.t4).add_vpp_config()
799 VppIpInterfaceBind(self, epg.bvi, epg.rd.t6).add_vpp_config()
800 self.vapi.sw_interface_set_mac_address(
802 self.router_mac.packed)
804 # The BVIs are NAT inside interfaces
805 flags = self.config_flags.NAT_IS_INSIDE
806 self.vapi.nat44_interface_add_del_feature(
807 sw_if_index=epg.bvi.sw_if_index,
808 flags=flags, is_add=1)
809 self.vapi.nat66_add_del_interface(
810 is_add=1, flags=flags,
811 sw_if_index=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 sw_if_index=recirc.recirc.sw_if_index, is_add=1)
844 self.vapi.nat66_add_del_interface(
846 sw_if_index=recirc.recirc.sw_if_index)
848 recirc.add_vpp_config()
850 for recirc in recircs:
851 self.assertTrue(find_bridge_domain_port(self,
852 recirc.epg.bd.bd.bd_id,
853 recirc.recirc.sw_if_index))
856 self.pg_enable_capture(self.pg_interfaces)
859 # routes to the endpoints. We need these since there are no
860 # adj-fibs due to the fact the the BVI address has /32 and
861 # the subnet is not attached.
863 for (ip, fip) in zip(ep.ips, ep.fips):
864 # Add static mappings for each EP from the 10/8 to 11/8 network
866 flags = self.config_flags.NAT_IS_ADDR_ONLY
867 self.vapi.nat44_add_del_static_mapping(
869 local_ip_address=ip.bytes,
870 external_ip_address=fip.bytes,
871 external_sw_if_index=0xFFFFFFFF,
875 self.vapi.nat66_add_del_static_mapping(
876 local_ip_address=ip.bytes,
877 external_ip_address=fip.bytes,
883 self.logger.info(self.vapi.cli("sh gbp endpoint"))
885 # ... results in a Gratuitous ARP/ND on the EPG's uplink
886 rx = ep.epg.uplink.get_capture(len(ep.ips), timeout=0.2)
888 for ii, ip in enumerate(ep.ips):
892 self.assertTrue(p.haslayer(ICMPv6ND_NA))
893 self.assertEqual(p[ICMPv6ND_NA].tgt, ip.address)
895 self.assertTrue(p.haslayer(ARP))
896 self.assertEqual(p[ARP].psrc, ip.address)
897 self.assertEqual(p[ARP].pdst, ip.address)
899 # add the BD ARP termination entry for floating IP
901 ba = VppBridgeDomainArpEntry(self, epg_nat.bd.bd, ep.mac, fip)
904 # floating IPs route via EPG recirc
905 r = VppIpRoute(self, fip.address, fip.length,
906 [VppRoutePath(fip.address,
907 ep.recirc.recirc.sw_if_index,
909 proto=fip.dpo_proto)],
914 # L2 FIB entries in the NAT EPG BD to bridge the packets from
915 # the outside direct to the internal EPG
916 lf = VppL2FibEntry(self, epg_nat.bd.bd, ep.mac,
917 ep.recirc.recirc, bvi_mac=0)
921 # ARP packets for unknown IP are sent to the EPG uplink
923 pkt_arp = (Ether(dst="ff:ff:ff:ff:ff:ff",
924 src=self.pg0.remote_mac) /
926 hwdst="ff:ff:ff:ff:ff:ff",
927 hwsrc=self.pg0.remote_mac,
931 self.vapi.cli("clear trace")
932 self.pg0.add_stream(pkt_arp)
934 self.pg_enable_capture(self.pg_interfaces)
937 rxd = epgs[0].uplink.get_capture(1)
940 # ARP/ND packets get a response
942 pkt_arp = (Ether(dst="ff:ff:ff:ff:ff:ff",
943 src=self.pg0.remote_mac) /
945 hwdst="ff:ff:ff:ff:ff:ff",
946 hwsrc=self.pg0.remote_mac,
947 pdst=epgs[0].bvi_ip4.address,
948 psrc=eps[0].ip4.address))
950 self.send_and_expect(self.pg0, [pkt_arp], self.pg0)
952 nsma = in6_getnsma(inet_pton(AF_INET6, eps[0].ip6.address))
953 d = inet_ntop(AF_INET6, nsma)
954 pkt_nd = (Ether(dst=in6_getnsmac(nsma),
955 src=self.pg0.remote_mac) /
956 IPv6(dst=d, src=eps[0].ip6.address) /
957 ICMPv6ND_NS(tgt=epgs[0].bvi_ip6.address) /
958 ICMPv6NDOptSrcLLAddr(lladdr=self.pg0.remote_mac))
959 self.send_and_expect(self.pg0, [pkt_nd], self.pg0)
962 # broadcast packets are flooded
964 pkt_bcast = (Ether(dst="ff:ff:ff:ff:ff:ff",
965 src=self.pg0.remote_mac) /
966 IP(src=eps[0].ip4.address, dst="232.1.1.1") /
967 UDP(sport=1234, dport=1234) /
970 self.vapi.cli("clear trace")
971 self.pg0.add_stream(pkt_bcast)
973 self.pg_enable_capture(self.pg_interfaces)
976 rxd = eps[1].itf.get_capture(1)
977 self.assertEqual(rxd[0][Ether].dst, pkt_bcast[Ether].dst)
978 rxd = epgs[0].uplink.get_capture(1)
979 self.assertEqual(rxd[0][Ether].dst, pkt_bcast[Ether].dst)
982 # packets to non-local L3 destinations dropped
984 pkt_intra_epg_220_ip4 = (Ether(src=self.pg0.remote_mac,
985 dst=str(self.router_mac)) /
986 IP(src=eps[0].ip4.address,
988 UDP(sport=1234, dport=1234) /
990 pkt_inter_epg_222_ip4 = (Ether(src=self.pg0.remote_mac,
991 dst=str(self.router_mac)) /
992 IP(src=eps[0].ip4.address,
994 UDP(sport=1234, dport=1234) /
997 self.send_and_assert_no_replies(self.pg0,
998 pkt_intra_epg_220_ip4 * NUM_PKTS)
1000 pkt_inter_epg_222_ip6 = (Ether(src=self.pg0.remote_mac,
1001 dst=str(self.router_mac)) /
1002 IPv6(src=eps[0].ip6.address,
1003 dst="2001:10::99") /
1004 UDP(sport=1234, dport=1234) /
1006 self.send_and_assert_no_replies(self.pg0,
1007 pkt_inter_epg_222_ip6 * NUM_PKTS)
1010 # Add the subnet routes
1013 self, rd0, "10.0.0.0", 24,
1014 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1016 self, rd0, "10.0.1.0", 24,
1017 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1019 self, rd0, "10.0.2.0", 24,
1020 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1022 self, rd0, "2001:10::1", 64,
1023 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1025 self, rd0, "2001:10:1::1", 64,
1026 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1028 self, rd0, "2001:10:2::1", 64,
1029 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1030 s41.add_vpp_config()
1031 s42.add_vpp_config()
1032 s43.add_vpp_config()
1033 s61.add_vpp_config()
1034 s62.add_vpp_config()
1035 s63.add_vpp_config()
1037 self.send_and_expect_bridged(eps[0].itf,
1038 pkt_intra_epg_220_ip4 * NUM_PKTS,
1040 self.send_and_expect_bridged(eps[0].itf,
1041 pkt_inter_epg_222_ip4 * NUM_PKTS,
1043 self.send_and_expect_bridged6(eps[0].itf,
1044 pkt_inter_epg_222_ip6 * NUM_PKTS,
1047 self.logger.info(self.vapi.cli("sh ip fib 11.0.0.2"))
1048 self.logger.info(self.vapi.cli("sh gbp endpoint-group"))
1049 self.logger.info(self.vapi.cli("sh gbp endpoint"))
1050 self.logger.info(self.vapi.cli("sh gbp recirc"))
1051 self.logger.info(self.vapi.cli("sh int"))
1052 self.logger.info(self.vapi.cli("sh int addr"))
1053 self.logger.info(self.vapi.cli("sh int feat loop6"))
1054 self.logger.info(self.vapi.cli("sh vlib graph ip4-gbp-src-classify"))
1055 self.logger.info(self.vapi.cli("sh int feat loop3"))
1056 self.logger.info(self.vapi.cli("sh int feat pg0"))
1059 # Packet destined to unknown unicast is sent on the epg uplink ...
1061 pkt_intra_epg_220_to_uplink = (Ether(src=self.pg0.remote_mac,
1062 dst="00:00:00:33:44:55") /
1063 IP(src=eps[0].ip4.address,
1065 UDP(sport=1234, dport=1234) /
1068 self.send_and_expect_bridged(eps[0].itf,
1069 pkt_intra_epg_220_to_uplink * NUM_PKTS,
1071 # ... and nowhere else
1072 self.pg1.get_capture(0, timeout=0.1)
1073 self.pg1.assert_nothing_captured(remark="Flood onto other VMS")
1075 pkt_intra_epg_221_to_uplink = (Ether(src=self.pg2.remote_mac,
1076 dst="00:00:00:33:44:66") /
1077 IP(src=eps[0].ip4.address,
1079 UDP(sport=1234, dport=1234) /
1082 self.send_and_expect_bridged(eps[2].itf,
1083 pkt_intra_epg_221_to_uplink * NUM_PKTS,
1087 # Packets from the uplink are forwarded in the absence of a contract
1089 pkt_intra_epg_220_from_uplink = (Ether(src="00:00:00:33:44:55",
1090 dst=self.pg0.remote_mac) /
1091 IP(src=eps[0].ip4.address,
1093 UDP(sport=1234, dport=1234) /
1096 self.send_and_expect_bridged(self.pg4,
1097 pkt_intra_epg_220_from_uplink * NUM_PKTS,
1101 # in the absence of policy, endpoints in the same EPG
1104 pkt_intra_epg = (Ether(src=self.pg0.remote_mac,
1105 dst=self.pg1.remote_mac) /
1106 IP(src=eps[0].ip4.address,
1107 dst=eps[1].ip4.address) /
1108 UDP(sport=1234, dport=1234) /
1111 self.send_and_expect_bridged(self.pg0,
1112 pkt_intra_epg * NUM_PKTS,
1116 # in the absence of policy, endpoints in the different EPG
1117 # cannot communicate
1119 pkt_inter_epg_220_to_221 = (Ether(src=self.pg0.remote_mac,
1120 dst=self.pg2.remote_mac) /
1121 IP(src=eps[0].ip4.address,
1122 dst=eps[2].ip4.address) /
1123 UDP(sport=1234, dport=1234) /
1125 pkt_inter_epg_221_to_220 = (Ether(src=self.pg2.remote_mac,
1126 dst=self.pg0.remote_mac) /
1127 IP(src=eps[2].ip4.address,
1128 dst=eps[0].ip4.address) /
1129 UDP(sport=1234, dport=1234) /
1131 pkt_inter_epg_220_to_222 = (Ether(src=self.pg0.remote_mac,
1132 dst=str(self.router_mac)) /
1133 IP(src=eps[0].ip4.address,
1134 dst=eps[3].ip4.address) /
1135 UDP(sport=1234, dport=1234) /
1138 self.send_and_assert_no_replies(eps[0].itf,
1139 pkt_inter_epg_220_to_221 * NUM_PKTS)
1140 self.send_and_assert_no_replies(eps[0].itf,
1141 pkt_inter_epg_220_to_222 * NUM_PKTS)
1144 # A uni-directional contract from EPG 220 -> 221
1146 acl = VppGbpAcl(self)
1147 rule = acl.create_rule(permit_deny=1, proto=17)
1148 rule2 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
1149 acl_index = acl.add_vpp_config([rule, rule2])
1150 c1 = VppGbpContract(
1151 self, epgs[0].sclass, epgs[1].sclass, acl_index,
1152 [VppGbpContractRule(
1153 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1156 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1158 [ETH_P_IP, ETH_P_IPV6])
1161 self.send_and_expect_bridged(eps[0].itf,
1162 pkt_inter_epg_220_to_221 * NUM_PKTS,
1164 self.send_and_assert_no_replies(eps[0].itf,
1165 pkt_inter_epg_220_to_222 * NUM_PKTS)
1168 # contract for the return direction
1170 c2 = VppGbpContract(
1171 self, epgs[1].sclass, epgs[0].sclass, acl_index,
1172 [VppGbpContractRule(
1173 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1176 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1178 [ETH_P_IP, ETH_P_IPV6])
1181 self.send_and_expect_bridged(eps[0].itf,
1182 pkt_inter_epg_220_to_221 * NUM_PKTS,
1184 self.send_and_expect_bridged(eps[2].itf,
1185 pkt_inter_epg_221_to_220 * NUM_PKTS,
1188 ds = c2.get_drop_stats()
1189 self.assertEqual(ds['packets'], 0)
1190 ps = c2.get_permit_stats()
1191 self.assertEqual(ps['packets'], NUM_PKTS)
1194 # the contract does not allow non-IP
1196 pkt_non_ip_inter_epg_220_to_221 = (Ether(src=self.pg0.remote_mac,
1197 dst=self.pg2.remote_mac) /
1199 self.send_and_assert_no_replies(eps[0].itf,
1200 pkt_non_ip_inter_epg_220_to_221 * 17)
1203 # check that inter group is still disabled for the groups
1204 # not in the contract.
1206 self.send_and_assert_no_replies(eps[0].itf,
1207 pkt_inter_epg_220_to_222 * NUM_PKTS)
1210 # A uni-directional contract from EPG 220 -> 222 'L3 routed'
1212 c3 = VppGbpContract(
1213 self, epgs[0].sclass, epgs[2].sclass, acl_index,
1214 [VppGbpContractRule(
1215 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1218 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1220 [ETH_P_IP, ETH_P_IPV6])
1223 self.logger.info(self.vapi.cli("sh gbp contract"))
1225 self.send_and_expect_routed(eps[0].itf,
1226 pkt_inter_epg_220_to_222 * NUM_PKTS,
1228 str(self.router_mac))
1231 # remove both contracts, traffic stops in both directions
1233 c2.remove_vpp_config()
1234 c1.remove_vpp_config()
1235 c3.remove_vpp_config()
1236 acl.remove_vpp_config()
1238 self.send_and_assert_no_replies(eps[2].itf,
1239 pkt_inter_epg_221_to_220 * NUM_PKTS)
1240 self.send_and_assert_no_replies(eps[0].itf,
1241 pkt_inter_epg_220_to_221 * NUM_PKTS)
1242 self.send_and_expect_bridged(eps[0].itf,
1243 pkt_intra_epg * NUM_PKTS,
1247 # EPs to the outside world
1250 # in the EP's RD an external subnet via the NAT EPG's recirc
1252 self, rd0, "0.0.0.0", 0,
1253 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1254 sw_if_index=recirc_nat.recirc.sw_if_index,
1255 sclass=epg_nat.sclass)
1257 self, rd0, "11.0.0.0", 8,
1258 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1259 sw_if_index=recirc_nat.recirc.sw_if_index,
1260 sclass=epg_nat.sclass)
1261 se16 = VppGbpSubnet(
1263 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1264 sw_if_index=recirc_nat.recirc.sw_if_index,
1265 sclass=epg_nat.sclass)
1266 # in the NAT RD an external subnet via the NAT EPG's uplink
1268 self, rd20, "0.0.0.0", 0,
1269 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1270 sw_if_index=epg_nat.uplink.sw_if_index,
1271 sclass=epg_nat.sclass)
1272 se36 = VppGbpSubnet(
1273 self, rd20, "::", 0,
1274 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1275 sw_if_index=epg_nat.uplink.sw_if_index,
1276 sclass=epg_nat.sclass)
1278 self, rd20, "11.0.0.0", 8,
1279 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1280 sw_if_index=epg_nat.uplink.sw_if_index,
1281 sclass=epg_nat.sclass)
1282 se1.add_vpp_config()
1283 se2.add_vpp_config()
1284 se16.add_vpp_config()
1285 se3.add_vpp_config()
1286 se36.add_vpp_config()
1287 se4.add_vpp_config()
1289 self.logger.info(self.vapi.cli("sh ip fib 0.0.0.0/0"))
1290 self.logger.info(self.vapi.cli("sh ip fib 11.0.0.1"))
1291 self.logger.info(self.vapi.cli("sh ip6 fib ::/0"))
1292 self.logger.info(self.vapi.cli("sh ip6 fib %s" %
1296 # From an EP to an outside address: IN2OUT
1298 pkt_inter_epg_220_to_global = (Ether(src=self.pg0.remote_mac,
1299 dst=str(self.router_mac)) /
1300 IP(src=eps[0].ip4.address,
1302 UDP(sport=1234, dport=1234) /
1306 self.send_and_assert_no_replies(eps[0].itf,
1307 pkt_inter_epg_220_to_global * NUM_PKTS)
1309 acl2 = VppGbpAcl(self)
1310 rule = acl2.create_rule(permit_deny=1, proto=17, sport_from=1234,
1311 sport_to=1234, dport_from=1234, dport_to=1234)
1312 rule2 = acl2.create_rule(is_ipv6=1, permit_deny=1, proto=17,
1313 sport_from=1234, sport_to=1234,
1314 dport_from=1234, dport_to=1234)
1316 acl_index2 = acl2.add_vpp_config([rule, rule2])
1317 c4 = VppGbpContract(
1318 self, epgs[0].sclass, epgs[3].sclass, acl_index2,
1319 [VppGbpContractRule(
1320 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1323 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1325 [ETH_P_IP, ETH_P_IPV6])
1328 self.send_and_expect_natted(eps[0].itf,
1329 pkt_inter_epg_220_to_global * NUM_PKTS,
1331 eps[0].fip4.address)
1333 pkt_inter_epg_220_to_global = (Ether(src=self.pg0.remote_mac,
1334 dst=str(self.router_mac)) /
1335 IPv6(src=eps[0].ip6.address,
1337 UDP(sport=1234, dport=1234) /
1340 self.send_and_expect_natted6(self.pg0,
1341 pkt_inter_epg_220_to_global * NUM_PKTS,
1343 eps[0].fip6.address)
1346 # From a global address to an EP: OUT2IN
1348 pkt_inter_epg_220_from_global = (Ether(src=str(self.router_mac),
1349 dst=self.pg0.remote_mac) /
1350 IP(dst=eps[0].fip4.address,
1352 UDP(sport=1234, dport=1234) /
1355 self.send_and_assert_no_replies(
1356 self.pg7, pkt_inter_epg_220_from_global * NUM_PKTS)
1358 c5 = VppGbpContract(
1359 self, epgs[3].sclass, epgs[0].sclass, acl_index2,
1360 [VppGbpContractRule(
1361 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1364 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1366 [ETH_P_IP, ETH_P_IPV6])
1369 self.send_and_expect_unnatted(self.pg7,
1370 pkt_inter_epg_220_from_global * NUM_PKTS,
1374 pkt_inter_epg_220_from_global = (Ether(src=str(self.router_mac),
1375 dst=self.pg0.remote_mac) /
1376 IPv6(dst=eps[0].fip6.address,
1378 UDP(sport=1234, dport=1234) /
1381 self.send_and_expect_unnatted6(
1383 pkt_inter_epg_220_from_global * NUM_PKTS,
1388 # From a local VM to another local VM using resp. public addresses:
1391 pkt_intra_epg_220_global = (Ether(src=self.pg0.remote_mac,
1392 dst=str(self.router_mac)) /
1393 IP(src=eps[0].ip4.address,
1394 dst=eps[1].fip4.address) /
1395 UDP(sport=1234, dport=1234) /
1398 self.send_and_expect_double_natted(eps[0].itf,
1399 pkt_intra_epg_220_global * NUM_PKTS,
1401 eps[0].fip4.address,
1404 pkt_intra_epg_220_global = (Ether(src=self.pg0.remote_mac,
1405 dst=str(self.router_mac)) /
1406 IPv6(src=eps[0].ip6.address,
1407 dst=eps[1].fip6.address) /
1408 UDP(sport=1234, dport=1234) /
1411 self.send_and_expect_double_natted6(
1413 pkt_intra_epg_220_global * NUM_PKTS,
1415 eps[0].fip6.address,
1422 # del static mappings for each EP from the 10/8 to 11/8 network
1423 flags = self.config_flags.NAT_IS_ADDR_ONLY
1424 self.vapi.nat44_add_del_static_mapping(
1426 local_ip_address=ep.ip4.bytes,
1427 external_ip_address=ep.fip4.bytes,
1428 external_sw_if_index=0xFFFFFFFF,
1431 self.vapi.nat66_add_del_static_mapping(
1432 local_ip_address=ep.ip6.bytes,
1433 external_ip_address=ep.fip6.bytes,
1437 # IP config on the BVI interfaces
1438 if epg != epgs[0] and epg != epgs[3]:
1439 flags = self.config_flags.NAT_IS_INSIDE
1440 self.vapi.nat44_interface_add_del_feature(
1441 sw_if_index=epg.bvi.sw_if_index,
1444 self.vapi.nat66_add_del_interface(
1445 is_add=0, flags=flags,
1446 sw_if_index=epg.bvi.sw_if_index)
1448 for recirc in recircs:
1449 self.vapi.nat44_interface_add_del_feature(
1450 sw_if_index=recirc.recirc.sw_if_index,
1452 self.vapi.nat66_add_del_interface(
1454 sw_if_index=recirc.recirc.sw_if_index)
1456 def wait_for_ep_timeout(self, sw_if_index=None, ip=None, mac=None,
1457 n_tries=100, s_time=1):
1459 if not find_gbp_endpoint(self, sw_if_index, ip, mac):
1461 n_tries = n_tries - 1
1463 self.assertFalse(find_gbp_endpoint(self, sw_if_index, ip, mac))
1466 def test_gbp_learn_l2(self):
1467 """ GBP L2 Endpoint Learning """
1469 self.vapi.cli("clear errors")
1471 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
1472 learnt = [{'mac': '00:00:11:11:11:01',
1474 'ip6': '2001:10::2'},
1475 {'mac': '00:00:11:11:11:02',
1477 'ip6': '2001:10::3'}]
1482 gt4 = VppIpTable(self, 1)
1483 gt4.add_vpp_config()
1484 gt6 = VppIpTable(self, 1, is_ip6=True)
1485 gt6.add_vpp_config()
1487 rd1 = VppGbpRouteDomain(self, 1, gt4, gt6)
1488 rd1.add_vpp_config()
1491 # Pg2 hosts the vxlan tunnel, hosts on pg2 to act as TEPs
1492 # Pg3 hosts the IP4 UU-flood VXLAN tunnel
1493 # Pg4 hosts the IP6 UU-flood VXLAN tunnel
1495 self.pg2.config_ip4()
1496 self.pg2.resolve_arp()
1497 self.pg2.generate_remote_hosts(4)
1498 self.pg2.configure_ipv4_neighbors()
1499 self.pg3.config_ip4()
1500 self.pg3.resolve_arp()
1501 self.pg4.config_ip4()
1502 self.pg4.resolve_arp()
1505 # Add a mcast destination VXLAN-GBP tunnel for B&M traffic
1507 tun_bm = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
1510 tun_bm.add_vpp_config()
1513 # a GBP bridge domain with a BVI and a UU-flood interface
1515 bd1 = VppBridgeDomain(self, 1)
1516 bd1.add_vpp_config()
1517 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0, self.pg3, tun_bm)
1518 gbd1.add_vpp_config()
1520 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1521 self.logger.info(self.vapi.cli("sh gbp bridge"))
1523 # ... and has a /32 applied
1524 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
1525 ip_addr.add_vpp_config()
1528 # The Endpoint-group in which we are learning endpoints
1530 epg_220 = VppGbpEndpointGroup(self, 220, 112, rd1, gbd1,
1534 VppGbpEndpointRetention(2))
1535 epg_220.add_vpp_config()
1536 epg_330 = VppGbpEndpointGroup(self, 330, 113, rd1, gbd1,
1540 VppGbpEndpointRetention(2))
1541 epg_330.add_vpp_config()
1544 # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
1547 vx_tun_l2_1 = VppGbpVxlanTunnel(
1548 self, 99, bd1.bd_id,
1549 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L2,
1551 vx_tun_l2_1.add_vpp_config()
1554 # A static endpoint that the learnt endpoints are trying to
1557 ep = VppGbpEndpoint(self, self.pg0,
1559 "10.0.0.127", "11.0.0.127",
1560 "2001:10::1", "3001::1")
1563 self.assertTrue(find_route(self, ep.ip4.address, 32, table_id=1))
1565 # a packet with an sclass from an unknown EPG
1566 p = (Ether(src=self.pg2.remote_mac,
1567 dst=self.pg2.local_mac) /
1568 IP(src=self.pg2.remote_hosts[0].ip4,
1569 dst=self.pg2.local_ip4) /
1570 UDP(sport=1234, dport=48879) /
1571 VXLAN(vni=99, gpid=88, flags=0x88) /
1572 Ether(src=learnt[0]["mac"], dst=ep.mac) /
1573 IP(src=learnt[0]["ip"], dst=ep.ip4.address) /
1574 UDP(sport=1234, dport=1234) /
1577 self.send_and_assert_no_replies(self.pg2, p)
1579 self.logger.info(self.vapi.cli("sh error"))
1580 # self.assert_packet_counter_equal(
1581 # '/err/gbp-policy-port/drop-no-contract', 1)
1584 # we should not have learnt a new tunnel endpoint, since
1585 # the EPG was not learnt.
1587 self.assertEqual(INDEX_INVALID,
1588 find_vxlan_gbp_tunnel(self,
1590 self.pg2.remote_hosts[0].ip4,
1593 # epg is not learnt, because the EPG is unknown
1594 self.assertEqual(len(self.vapi.gbp_endpoint_dump()), 1)
1597 # Learn new EPs from IP packets
1599 for ii, l in enumerate(learnt):
1600 # a packet with an sclass from a known EPG
1601 # arriving on an unknown TEP
1602 p = (Ether(src=self.pg2.remote_mac,
1603 dst=self.pg2.local_mac) /
1604 IP(src=self.pg2.remote_hosts[1].ip4,
1605 dst=self.pg2.local_ip4) /
1606 UDP(sport=1234, dport=48879) /
1607 VXLAN(vni=99, gpid=112, flags=0x88) /
1608 Ether(src=l['mac'], dst=ep.mac) /
1609 IP(src=l['ip'], dst=ep.ip4.address) /
1610 UDP(sport=1234, dport=1234) /
1613 rx = self.send_and_expect(self.pg2, [p], self.pg0)
1616 tep1_sw_if_index = find_vxlan_gbp_tunnel(
1619 self.pg2.remote_hosts[1].ip4,
1621 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
1624 # the EP is learnt via the learnt TEP
1625 # both from its MAC and its IP
1627 self.assertTrue(find_gbp_endpoint(self,
1628 vx_tun_l2_1.sw_if_index,
1630 self.assertTrue(find_gbp_endpoint(self,
1631 vx_tun_l2_1.sw_if_index,
1634 # self.assert_packet_counter_equal(
1635 # '/err/gbp-policy-port/allow-intra-sclass', 2)
1637 self.logger.info(self.vapi.cli("show gbp endpoint"))
1638 self.logger.info(self.vapi.cli("show gbp vxlan"))
1639 self.logger.info(self.vapi.cli("show ip mfib"))
1642 # If we sleep for the threshold time, the learnt endpoints should
1646 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1650 # Learn new EPs from GARP packets received on the BD's mcast tunnel
1652 for ii, l in enumerate(learnt):
1653 # a packet with an sclass from a known EPG
1654 # arriving on an unknown TEP
1655 p = (Ether(src=self.pg2.remote_mac,
1656 dst=self.pg2.local_mac) /
1657 IP(src=self.pg2.remote_hosts[1].ip4,
1659 UDP(sport=1234, dport=48879) /
1660 VXLAN(vni=88, gpid=112, flags=0x88) /
1661 Ether(src=l['mac'], dst="ff:ff:ff:ff:ff:ff") /
1663 psrc=l['ip'], pdst=l['ip'],
1664 hwsrc=l['mac'], hwdst="ff:ff:ff:ff:ff:ff"))
1666 rx = self.send_and_expect(self.pg4, [p], self.pg0)
1669 tep1_sw_if_index = find_vxlan_gbp_tunnel(
1672 self.pg2.remote_hosts[1].ip4,
1674 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
1677 # the EP is learnt via the learnt TEP
1678 # both from its MAC and its IP
1680 self.assertTrue(find_gbp_endpoint(self,
1681 vx_tun_l2_1.sw_if_index,
1683 self.assertTrue(find_gbp_endpoint(self,
1684 vx_tun_l2_1.sw_if_index,
1688 # wait for the learnt endpoints to age out
1691 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1695 # Learn new EPs from L2 packets
1697 for ii, l in enumerate(learnt):
1698 # a packet with an sclass from a known EPG
1699 # arriving on an unknown TEP
1700 p = (Ether(src=self.pg2.remote_mac,
1701 dst=self.pg2.local_mac) /
1702 IP(src=self.pg2.remote_hosts[1].ip4,
1703 dst=self.pg2.local_ip4) /
1704 UDP(sport=1234, dport=48879) /
1705 VXLAN(vni=99, gpid=112, flags=0x88) /
1706 Ether(src=l['mac'], dst=ep.mac) /
1709 rx = self.send_and_expect(self.pg2, [p], self.pg0)
1712 tep1_sw_if_index = find_vxlan_gbp_tunnel(
1715 self.pg2.remote_hosts[1].ip4,
1717 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
1720 # the EP is learnt via the learnt TEP
1721 # both from its MAC and its IP
1723 self.assertTrue(find_gbp_endpoint(self,
1724 vx_tun_l2_1.sw_if_index,
1727 self.logger.info(self.vapi.cli("show gbp endpoint"))
1728 self.logger.info(self.vapi.cli("show gbp vxlan"))
1729 self.logger.info(self.vapi.cli("show vxlan-gbp tunnel"))
1732 # wait for the learnt endpoints to age out
1735 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1739 # repeat. the do not learn bit is set so the EPs are not learnt
1742 # a packet with an sclass from a known EPG
1743 p = (Ether(src=self.pg2.remote_mac,
1744 dst=self.pg2.local_mac) /
1745 IP(src=self.pg2.remote_hosts[1].ip4,
1746 dst=self.pg2.local_ip4) /
1747 UDP(sport=1234, dport=48879) /
1748 VXLAN(vni=99, gpid=112, flags=0x88, gpflags="D") /
1749 Ether(src=l['mac'], dst=ep.mac) /
1750 IP(src=l['ip'], dst=ep.ip4.address) /
1751 UDP(sport=1234, dport=1234) /
1754 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
1757 self.assertFalse(find_gbp_endpoint(self,
1758 vx_tun_l2_1.sw_if_index,
1765 # a packet with an sclass from a known EPG
1766 p = (Ether(src=self.pg2.remote_mac,
1767 dst=self.pg2.local_mac) /
1768 IP(src=self.pg2.remote_hosts[1].ip4,
1769 dst=self.pg2.local_ip4) /
1770 UDP(sport=1234, dport=48879) /
1771 VXLAN(vni=99, gpid=112, flags=0x88) /
1772 Ether(src=l['mac'], dst=ep.mac) /
1773 IP(src=l['ip'], dst=ep.ip4.address) /
1774 UDP(sport=1234, dport=1234) /
1777 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
1779 self.assertTrue(find_gbp_endpoint(self,
1780 vx_tun_l2_1.sw_if_index,
1784 # Static EP replies to dynamics
1786 self.logger.info(self.vapi.cli("sh l2fib bd_id 1"))
1788 p = (Ether(src=ep.mac, dst=l['mac']) /
1789 IP(dst=l['ip'], src=ep.ip4.address) /
1790 UDP(sport=1234, dport=1234) /
1793 rxs = self.send_and_expect(self.pg0, p * 17, self.pg2)
1796 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
1797 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
1798 self.assertEqual(rx[UDP].dport, 48879)
1799 # the UDP source port is a random value for hashing
1800 self.assertEqual(rx[VXLAN].gpid, 112)
1801 self.assertEqual(rx[VXLAN].vni, 99)
1802 self.assertTrue(rx[VXLAN].flags.G)
1803 self.assertTrue(rx[VXLAN].flags.Instance)
1804 self.assertTrue(rx[VXLAN].gpflags.A)
1805 self.assertFalse(rx[VXLAN].gpflags.D)
1808 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1812 # repeat in the other EPG
1813 # there's no contract between 220 and 330, but the A-bit is set
1814 # so the packet is cleared for delivery
1817 # a packet with an sclass from a known EPG
1818 p = (Ether(src=self.pg2.remote_mac,
1819 dst=self.pg2.local_mac) /
1820 IP(src=self.pg2.remote_hosts[1].ip4,
1821 dst=self.pg2.local_ip4) /
1822 UDP(sport=1234, dport=48879) /
1823 VXLAN(vni=99, gpid=113, flags=0x88, gpflags='A') /
1824 Ether(src=l['mac'], dst=ep.mac) /
1825 IP(src=l['ip'], dst=ep.ip4.address) /
1826 UDP(sport=1234, dport=1234) /
1829 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
1831 self.assertTrue(find_gbp_endpoint(self,
1832 vx_tun_l2_1.sw_if_index,
1836 # static EP cannot reach the learnt EPs since there is no contract
1837 # only test 1 EP as the others could timeout
1839 p = (Ether(src=ep.mac, dst=l['mac']) /
1840 IP(dst=learnt[0]['ip'], src=ep.ip4.address) /
1841 UDP(sport=1234, dport=1234) /
1844 self.send_and_assert_no_replies(self.pg0, [p])
1847 # refresh the entries after the check for no replies above
1850 # a packet with an sclass from a known EPG
1851 p = (Ether(src=self.pg2.remote_mac,
1852 dst=self.pg2.local_mac) /
1853 IP(src=self.pg2.remote_hosts[1].ip4,
1854 dst=self.pg2.local_ip4) /
1855 UDP(sport=1234, dport=48879) /
1856 VXLAN(vni=99, gpid=113, flags=0x88, gpflags='A') /
1857 Ether(src=l['mac'], dst=ep.mac) /
1858 IP(src=l['ip'], dst=ep.ip4.address) /
1859 UDP(sport=1234, dport=1234) /
1862 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
1864 self.assertTrue(find_gbp_endpoint(self,
1865 vx_tun_l2_1.sw_if_index,
1869 # Add the contract so they can talk
1871 acl = VppGbpAcl(self)
1872 rule = acl.create_rule(permit_deny=1, proto=17)
1873 rule2 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
1874 acl_index = acl.add_vpp_config([rule, rule2])
1875 c1 = VppGbpContract(
1876 self, epg_220.sclass, epg_330.sclass, acl_index,
1877 [VppGbpContractRule(
1878 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1881 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1883 [ETH_P_IP, ETH_P_IPV6])
1887 p = (Ether(src=ep.mac, dst=l['mac']) /
1888 IP(dst=l['ip'], src=ep.ip4.address) /
1889 UDP(sport=1234, dport=1234) /
1892 self.send_and_expect(self.pg0, [p], self.pg2)
1895 # send UU packets from the local EP
1897 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1898 self.logger.info(self.vapi.cli("sh gbp bridge"))
1899 p_uu = (Ether(src=ep.mac, dst="00:11:11:11:11:11") /
1900 IP(dst="10.0.0.133", src=ep.ip4.address) /
1901 UDP(sport=1234, dport=1234) /
1903 rxs = self.send_and_expect(ep.itf, [p_uu], gbd1.uu_fwd)
1905 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1907 p_bm = (Ether(src=ep.mac, dst="ff:ff:ff:ff:ff:ff") /
1908 IP(dst="10.0.0.133", src=ep.ip4.address) /
1909 UDP(sport=1234, dport=1234) /
1911 rxs = self.send_and_expect_only(ep.itf, [p_bm], tun_bm.mcast_itf)
1914 self.assertEqual(rx[IP].src, self.pg4.local_ip4)
1915 self.assertEqual(rx[IP].dst, "239.1.1.1")
1916 self.assertEqual(rx[UDP].dport, 48879)
1917 # the UDP source port is a random value for hashing
1918 self.assertEqual(rx[VXLAN].gpid, 112)
1919 self.assertEqual(rx[VXLAN].vni, 88)
1920 self.assertTrue(rx[VXLAN].flags.G)
1921 self.assertTrue(rx[VXLAN].flags.Instance)
1922 self.assertFalse(rx[VXLAN].gpflags.A)
1923 self.assertFalse(rx[VXLAN].gpflags.D)
1926 # Check v6 Endpoints
1929 # a packet with an sclass from a known EPG
1930 p = (Ether(src=self.pg2.remote_mac,
1931 dst=self.pg2.local_mac) /
1932 IP(src=self.pg2.remote_hosts[1].ip4,
1933 dst=self.pg2.local_ip4) /
1934 UDP(sport=1234, dport=48879) /
1935 VXLAN(vni=99, gpid=113, flags=0x88, gpflags='A') /
1936 Ether(src=l['mac'], dst=ep.mac) /
1937 IPv6(src=l['ip6'], dst=ep.ip6.address) /
1938 UDP(sport=1234, dport=1234) /
1941 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
1943 self.assertTrue(find_gbp_endpoint(self,
1944 vx_tun_l2_1.sw_if_index,
1948 # L3 Endpoint Learning
1949 # - configured on the bridge's BVI
1956 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1958 self.pg2.unconfig_ip4()
1959 self.pg3.unconfig_ip4()
1960 self.pg4.unconfig_ip4()
1962 self.logger.info(self.vapi.cli("sh int"))
1963 self.logger.info(self.vapi.cli("sh gbp vxlan"))
1965 def test_gbp_bd_flags(self):
1966 """ GBP BD FLAGS """
1971 gt4 = VppIpTable(self, 1)
1972 gt4.add_vpp_config()
1973 gt6 = VppIpTable(self, 1, is_ip6=True)
1974 gt6.add_vpp_config()
1976 rd1 = VppGbpRouteDomain(self, 1, gt4, gt6)
1977 rd1.add_vpp_config()
1980 # Pg3 hosts the IP4 UU-flood VXLAN tunnel
1981 # Pg4 hosts the IP6 UU-flood VXLAN tunnel
1983 self.pg3.config_ip4()
1984 self.pg3.resolve_arp()
1985 self.pg4.config_ip4()
1986 self.pg4.resolve_arp()
1989 # Add a mcast destination VXLAN-GBP tunnel for B&M traffic
1991 tun_bm = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
1994 tun_bm.add_vpp_config()
1997 # a GBP bridge domain with a BVI and a UU-flood interface
1999 bd1 = VppBridgeDomain(self, 1)
2000 bd1.add_vpp_config()
2002 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0, self.pg3, tun_bm,
2003 uu_drop=True, bm_drop=True)
2004 gbd1.add_vpp_config()
2006 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2007 self.logger.info(self.vapi.cli("sh gbp bridge"))
2009 # ... and has a /32 applied
2010 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2011 ip_addr.add_vpp_config()
2014 # The Endpoint-group
2016 epg_220 = VppGbpEndpointGroup(self, 220, 112, rd1, gbd1,
2020 VppGbpEndpointRetention(2))
2021 epg_220.add_vpp_config()
2023 ep = VppGbpEndpoint(self, self.pg0,
2025 "10.0.0.127", "11.0.0.127",
2026 "2001:10::1", "3001::1")
2029 # send UU/BM packet from the local EP with UU drop and BM drop enabled
2032 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2033 self.logger.info(self.vapi.cli("sh gbp bridge"))
2034 p_uu = (Ether(src=ep.mac, dst="00:11:11:11:11:11") /
2035 IP(dst="10.0.0.133", src=ep.ip4.address) /
2036 UDP(sport=1234, dport=1234) /
2038 self.send_and_assert_no_replies(ep.itf, [p_uu])
2040 p_bm = (Ether(src=ep.mac, dst="ff:ff:ff:ff:ff:ff") /
2041 IP(dst="10.0.0.133", src=ep.ip4.address) /
2042 UDP(sport=1234, dport=1234) /
2044 self.send_and_assert_no_replies(ep.itf, [p_bm])
2046 self.pg3.unconfig_ip4()
2047 self.pg4.unconfig_ip4()
2049 self.logger.info(self.vapi.cli("sh int"))
2051 def test_gbp_learn_vlan_l2(self):
2052 """ GBP L2 Endpoint w/ VLANs"""
2054 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
2055 learnt = [{'mac': '00:00:11:11:11:01',
2057 'ip6': '2001:10::2'},
2058 {'mac': '00:00:11:11:11:02',
2060 'ip6': '2001:10::3'}]
2065 gt4 = VppIpTable(self, 1)
2066 gt4.add_vpp_config()
2067 gt6 = VppIpTable(self, 1, is_ip6=True)
2068 gt6.add_vpp_config()
2070 rd1 = VppGbpRouteDomain(self, 1, gt4, gt6)
2071 rd1.add_vpp_config()
2074 # Pg2 hosts the vxlan tunnel, hosts on pg2 to act as TEPs
2076 self.pg2.config_ip4()
2077 self.pg2.resolve_arp()
2078 self.pg2.generate_remote_hosts(4)
2079 self.pg2.configure_ipv4_neighbors()
2080 self.pg3.config_ip4()
2081 self.pg3.resolve_arp()
2084 # The EP will be on a vlan sub-interface
2086 vlan_11 = VppDot1QSubint(self, self.pg0, 11)
2088 self.vapi.l2_interface_vlan_tag_rewrite(
2089 sw_if_index=vlan_11.sw_if_index, vtr_op=L2_VTR_OP.L2_POP_1,
2092 bd_uu_fwd = VppVxlanGbpTunnel(self, self.pg3.local_ip4,
2093 self.pg3.remote_ip4, 116)
2094 bd_uu_fwd.add_vpp_config()
2097 # a GBP bridge domain with a BVI and a UU-flood interface
2098 # The BD is marked as do not learn, so no endpoints are ever
2099 # learnt in this BD.
2101 bd1 = VppBridgeDomain(self, 1)
2102 bd1.add_vpp_config()
2103 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0, bd_uu_fwd,
2105 gbd1.add_vpp_config()
2107 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2108 self.logger.info(self.vapi.cli("sh gbp bridge"))
2110 # ... and has a /32 applied
2111 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2112 ip_addr.add_vpp_config()
2115 # The Endpoint-group in which we are learning endpoints
2117 epg_220 = VppGbpEndpointGroup(self, 220, 441, rd1, gbd1,
2121 VppGbpEndpointRetention(2))
2122 epg_220.add_vpp_config()
2125 # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
2128 vx_tun_l2_1 = VppGbpVxlanTunnel(
2129 self, 99, bd1.bd_id,
2130 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L2,
2132 vx_tun_l2_1.add_vpp_config()
2135 # A static endpoint that the learnt endpoints are trying to
2138 ep = VppGbpEndpoint(self, vlan_11,
2140 "10.0.0.127", "11.0.0.127",
2141 "2001:10::1", "3001::1")
2144 self.assertTrue(find_route(self, ep.ip4.address, 32, table_id=1))
2147 # Send to the static EP
2149 for ii, l in enumerate(learnt):
2150 # a packet with an sclass from a known EPG
2151 # arriving on an unknown TEP
2152 p = (Ether(src=self.pg2.remote_mac,
2153 dst=self.pg2.local_mac) /
2154 IP(src=self.pg2.remote_hosts[1].ip4,
2155 dst=self.pg2.local_ip4) /
2156 UDP(sport=1234, dport=48879) /
2157 VXLAN(vni=99, gpid=441, flags=0x88) /
2158 Ether(src=l['mac'], dst=ep.mac) /
2159 IP(src=l['ip'], dst=ep.ip4.address) /
2160 UDP(sport=1234, dport=1234) /
2163 rxs = self.send_and_expect(self.pg2, [p], self.pg0)
2166 # packet to EP has the EP's vlan tag
2169 self.assertEqual(rx[Dot1Q].vlan, 11)
2172 # the EP is not learnt since the BD setting prevents it
2175 self.assertFalse(find_gbp_endpoint(self,
2176 vx_tun_l2_1.sw_if_index,
2178 self.assertEqual(INDEX_INVALID,
2179 find_vxlan_gbp_tunnel(
2182 self.pg2.remote_hosts[1].ip4,
2185 self.assertEqual(len(self.vapi.gbp_endpoint_dump()), 1)
2189 # we didn't learn the remotes so they are sent to the UU-fwd
2192 p = (Ether(src=ep.mac, dst=l['mac']) /
2194 IP(dst=l['ip'], src=ep.ip4.address) /
2195 UDP(sport=1234, dport=1234) /
2198 rxs = self.send_and_expect(self.pg0, p * 17, self.pg3)
2201 self.assertEqual(rx[IP].src, self.pg3.local_ip4)
2202 self.assertEqual(rx[IP].dst, self.pg3.remote_ip4)
2203 self.assertEqual(rx[UDP].dport, 48879)
2204 # the UDP source port is a random value for hashing
2205 self.assertEqual(rx[VXLAN].gpid, 441)
2206 self.assertEqual(rx[VXLAN].vni, 116)
2207 self.assertTrue(rx[VXLAN].flags.G)
2208 self.assertTrue(rx[VXLAN].flags.Instance)
2209 self.assertFalse(rx[VXLAN].gpflags.A)
2210 self.assertFalse(rx[VXLAN].gpflags.D)
2212 self.pg2.unconfig_ip4()
2213 self.pg3.unconfig_ip4()
2215 def test_gbp_learn_l3(self):
2216 """ GBP L3 Endpoint Learning """
2218 self.vapi.cli("set logging class gbp debug")
2220 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
2221 routed_dst_mac = "00:0c:0c:0c:0c:0c"
2222 routed_src_mac = "00:22:bd:f8:19:ff"
2224 learnt = [{'mac': '00:00:11:11:11:02',
2226 'ip6': '2001:10::2'},
2227 {'mac': '00:00:11:11:11:03',
2229 'ip6': '2001:10::3'}]
2234 t4 = VppIpTable(self, 1)
2236 t6 = VppIpTable(self, 1, True)
2239 tun_ip4_uu = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
2240 self.pg4.remote_ip4, 114)
2241 tun_ip6_uu = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
2242 self.pg4.remote_ip4, 116)
2243 tun_ip4_uu.add_vpp_config()
2244 tun_ip6_uu.add_vpp_config()
2246 rd1 = VppGbpRouteDomain(self, 2, t4, t6, tun_ip4_uu, tun_ip6_uu)
2247 rd1.add_vpp_config()
2249 self.loop0.set_mac(self.router_mac)
2252 # Bind the BVI to the RD
2254 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
2255 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
2258 # Pg2 hosts the vxlan tunnel
2259 # hosts on pg2 to act as TEPs
2263 self.pg2.config_ip4()
2264 self.pg2.resolve_arp()
2265 self.pg2.generate_remote_hosts(4)
2266 self.pg2.configure_ipv4_neighbors()
2267 self.pg3.config_ip4()
2268 self.pg3.resolve_arp()
2269 self.pg4.config_ip4()
2270 self.pg4.resolve_arp()
2273 # a GBP bridge domain with a BVI and a UU-flood interface
2275 bd1 = VppBridgeDomain(self, 1)
2276 bd1.add_vpp_config()
2277 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0, self.pg3)
2278 gbd1.add_vpp_config()
2280 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2281 self.logger.info(self.vapi.cli("sh gbp bridge"))
2282 self.logger.info(self.vapi.cli("sh gbp route"))
2284 # ... and has a /32 and /128 applied
2285 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2286 ip4_addr.add_vpp_config()
2287 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 128)
2288 ip6_addr.add_vpp_config()
2291 # The Endpoint-group in which we are learning endpoints
2293 epg_220 = VppGbpEndpointGroup(self, 220, 441, rd1, gbd1,
2297 VppGbpEndpointRetention(2))
2298 epg_220.add_vpp_config()
2301 # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
2304 vx_tun_l3 = VppGbpVxlanTunnel(
2305 self, 101, rd1.rd_id,
2306 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
2308 vx_tun_l3.add_vpp_config()
2311 # A static endpoint that the learnt endpoints are trying to
2314 ep = VppGbpEndpoint(self, self.pg0,
2316 "10.0.0.127", "11.0.0.127",
2317 "2001:10::1", "3001::1")
2321 # learn some remote IPv4 EPs
2323 for ii, l in enumerate(learnt):
2324 # a packet with an sclass from a known EPG
2325 # arriving on an unknown TEP
2326 p = (Ether(src=self.pg2.remote_mac,
2327 dst=self.pg2.local_mac) /
2328 IP(src=self.pg2.remote_hosts[1].ip4,
2329 dst=self.pg2.local_ip4) /
2330 UDP(sport=1234, dport=48879) /
2331 VXLAN(vni=101, gpid=441, flags=0x88) /
2332 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2333 IP(src=l['ip'], dst=ep.ip4.address) /
2334 UDP(sport=1234, dport=1234) /
2337 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2340 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2343 self.pg2.remote_hosts[1].ip4,
2345 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2347 # endpoint learnt via the parent GBP-vxlan interface
2348 self.assertTrue(find_gbp_endpoint(self,
2349 vx_tun_l3._sw_if_index,
2353 # Static IPv4 EP replies to learnt
2356 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2357 IP(dst=l['ip'], src=ep.ip4.address) /
2358 UDP(sport=1234, dport=1234) /
2361 rxs = self.send_and_expect(self.pg0, p * 1, self.pg2)
2364 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2365 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2366 self.assertEqual(rx[UDP].dport, 48879)
2367 # the UDP source port is a random value for hashing
2368 self.assertEqual(rx[VXLAN].gpid, 441)
2369 self.assertEqual(rx[VXLAN].vni, 101)
2370 self.assertTrue(rx[VXLAN].flags.G)
2371 self.assertTrue(rx[VXLAN].flags.Instance)
2372 self.assertTrue(rx[VXLAN].gpflags.A)
2373 self.assertFalse(rx[VXLAN].gpflags.D)
2375 inner = rx[VXLAN].payload
2377 self.assertEqual(inner[Ether].src, routed_src_mac)
2378 self.assertEqual(inner[Ether].dst, routed_dst_mac)
2379 self.assertEqual(inner[IP].src, ep.ip4.address)
2380 self.assertEqual(inner[IP].dst, l['ip'])
2383 self.assertFalse(find_gbp_endpoint(self,
2388 # learn some remote IPv6 EPs
2390 for ii, l in enumerate(learnt):
2391 # a packet with an sclass from a known EPG
2392 # arriving on an unknown TEP
2393 p = (Ether(src=self.pg2.remote_mac,
2394 dst=self.pg2.local_mac) /
2395 IP(src=self.pg2.remote_hosts[1].ip4,
2396 dst=self.pg2.local_ip4) /
2397 UDP(sport=1234, dport=48879) /
2398 VXLAN(vni=101, gpid=441, flags=0x88) /
2399 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2400 IPv6(src=l['ip6'], dst=ep.ip6.address) /
2401 UDP(sport=1234, dport=1234) /
2404 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2407 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2410 self.pg2.remote_hosts[1].ip4,
2412 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2414 self.logger.info(self.vapi.cli("show gbp bridge"))
2415 self.logger.info(self.vapi.cli("show vxlan-gbp tunnel"))
2416 self.logger.info(self.vapi.cli("show gbp vxlan"))
2417 self.logger.info(self.vapi.cli("show int addr"))
2419 # endpoint learnt via the TEP
2420 self.assertTrue(find_gbp_endpoint(self, ip=l['ip6']))
2422 self.logger.info(self.vapi.cli("show gbp endpoint"))
2423 self.logger.info(self.vapi.cli("show ip fib index 1 %s" % l['ip']))
2426 # Static EP replies to learnt
2429 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2430 IPv6(dst=l['ip6'], src=ep.ip6.address) /
2431 UDP(sport=1234, dport=1234) /
2434 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
2437 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2438 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2439 self.assertEqual(rx[UDP].dport, 48879)
2440 # the UDP source port is a random value for hashing
2441 self.assertEqual(rx[VXLAN].gpid, 441)
2442 self.assertEqual(rx[VXLAN].vni, 101)
2443 self.assertTrue(rx[VXLAN].flags.G)
2444 self.assertTrue(rx[VXLAN].flags.Instance)
2445 self.assertTrue(rx[VXLAN].gpflags.A)
2446 self.assertFalse(rx[VXLAN].gpflags.D)
2448 inner = rx[VXLAN].payload
2450 self.assertEqual(inner[Ether].src, routed_src_mac)
2451 self.assertEqual(inner[Ether].dst, routed_dst_mac)
2452 self.assertEqual(inner[IPv6].src, ep.ip6.address)
2453 self.assertEqual(inner[IPv6].dst, l['ip6'])
2455 self.logger.info(self.vapi.cli("sh gbp endpoint"))
2457 self.wait_for_ep_timeout(ip=l['ip'])
2460 # Static sends to unknown EP with no route
2462 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2463 IP(dst="10.0.0.99", src=ep.ip4.address) /
2464 UDP(sport=1234, dport=1234) /
2467 self.send_and_assert_no_replies(self.pg0, [p])
2470 # Add a route to static EP's v4 and v6 subnet
2471 # packets should be sent on the v4/v6 uu=fwd interface resp.
2473 se_10_24 = VppGbpSubnet(
2474 self, rd1, "10.0.0.0", 24,
2475 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT)
2476 se_10_24.add_vpp_config()
2478 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2479 IP(dst="10.0.0.99", src=ep.ip4.address) /
2480 UDP(sport=1234, dport=1234) /
2483 rxs = self.send_and_expect(self.pg0, [p], self.pg4)
2485 self.assertEqual(rx[IP].src, self.pg4.local_ip4)
2486 self.assertEqual(rx[IP].dst, self.pg4.remote_ip4)
2487 self.assertEqual(rx[UDP].dport, 48879)
2488 # the UDP source port is a random value for hashing
2489 self.assertEqual(rx[VXLAN].gpid, 441)
2490 self.assertEqual(rx[VXLAN].vni, 114)
2491 self.assertTrue(rx[VXLAN].flags.G)
2492 self.assertTrue(rx[VXLAN].flags.Instance)
2493 # policy is not applied to packets sent to the uu-fwd interfaces
2494 self.assertFalse(rx[VXLAN].gpflags.A)
2495 self.assertFalse(rx[VXLAN].gpflags.D)
2498 # learn some remote IPv4 EPs
2500 for ii, l in enumerate(learnt):
2501 # a packet with an sclass from a known EPG
2502 # arriving on an unknown TEP
2503 p = (Ether(src=self.pg2.remote_mac,
2504 dst=self.pg2.local_mac) /
2505 IP(src=self.pg2.remote_hosts[2].ip4,
2506 dst=self.pg2.local_ip4) /
2507 UDP(sport=1234, dport=48879) /
2508 VXLAN(vni=101, gpid=441, flags=0x88) /
2509 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2510 IP(src=l['ip'], dst=ep.ip4.address) /
2511 UDP(sport=1234, dport=1234) /
2514 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2517 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2520 self.pg2.remote_hosts[2].ip4,
2522 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2524 # endpoint learnt via the parent GBP-vxlan interface
2525 self.assertTrue(find_gbp_endpoint(self,
2526 vx_tun_l3._sw_if_index,
2530 # Add a remote endpoint from the API
2532 rep_88 = VppGbpEndpoint(self, vx_tun_l3,
2534 "10.0.0.88", "11.0.0.88",
2535 "2001:10::88", "3001::88",
2536 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
2538 self.pg2.remote_hosts[1].ip4,
2540 rep_88.add_vpp_config()
2543 # Add a remote endpoint from the API that matches an existing one
2545 rep_2 = VppGbpEndpoint(self, vx_tun_l3,
2547 learnt[0]['ip'], "11.0.0.101",
2548 learnt[0]['ip6'], "3001::101",
2549 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
2551 self.pg2.remote_hosts[1].ip4,
2553 rep_2.add_vpp_config()
2556 # Add a route to the learned EP's v4 subnet
2557 # packets should be send on the v4/v6 uu=fwd interface resp.
2559 se_10_1_24 = VppGbpSubnet(
2560 self, rd1, "10.0.1.0", 24,
2561 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT)
2562 se_10_1_24.add_vpp_config()
2564 self.logger.info(self.vapi.cli("show gbp endpoint"))
2566 ips = ["10.0.0.88", learnt[0]['ip']]
2568 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2569 IP(dst=ip, src=ep.ip4.address) /
2570 UDP(sport=1234, dport=1234) /
2573 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
2576 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2577 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2578 self.assertEqual(rx[UDP].dport, 48879)
2579 # the UDP source port is a random value for hashing
2580 self.assertEqual(rx[VXLAN].gpid, 441)
2581 self.assertEqual(rx[VXLAN].vni, 101)
2582 self.assertTrue(rx[VXLAN].flags.G)
2583 self.assertTrue(rx[VXLAN].flags.Instance)
2584 self.assertTrue(rx[VXLAN].gpflags.A)
2585 self.assertFalse(rx[VXLAN].gpflags.D)
2587 inner = rx[VXLAN].payload
2589 self.assertEqual(inner[Ether].src, routed_src_mac)
2590 self.assertEqual(inner[Ether].dst, routed_dst_mac)
2591 self.assertEqual(inner[IP].src, ep.ip4.address)
2592 self.assertEqual(inner[IP].dst, ip)
2595 # remove the API remote EPs, only API sourced is gone, the DP
2596 # learnt one remains
2598 rep_88.remove_vpp_config()
2599 rep_2.remove_vpp_config()
2601 self.assertTrue(find_gbp_endpoint(self, ip=rep_2.ip4.address))
2603 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2604 IP(src=ep.ip4.address, dst=rep_2.ip4.address) /
2605 UDP(sport=1234, dport=1234) /
2607 rxs = self.send_and_expect(self.pg0, [p], self.pg2)
2609 self.assertFalse(find_gbp_endpoint(self, ip=rep_88.ip4.address))
2611 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2612 IP(src=ep.ip4.address, dst=rep_88.ip4.address) /
2613 UDP(sport=1234, dport=1234) /
2615 rxs = self.send_and_expect(self.pg0, [p], self.pg4)
2618 # to appease the testcase we cannot have the registered EP still
2619 # present (because it's DP learnt) when the TC ends so wait until
2622 self.wait_for_ep_timeout(ip=rep_88.ip4.address)
2623 self.wait_for_ep_timeout(ip=rep_2.ip4.address)
2626 # shutdown with learnt endpoint present
2628 p = (Ether(src=self.pg2.remote_mac,
2629 dst=self.pg2.local_mac) /
2630 IP(src=self.pg2.remote_hosts[1].ip4,
2631 dst=self.pg2.local_ip4) /
2632 UDP(sport=1234, dport=48879) /
2633 VXLAN(vni=101, gpid=441, flags=0x88) /
2634 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2635 IP(src=learnt[1]['ip'], dst=ep.ip4.address) /
2636 UDP(sport=1234, dport=1234) /
2639 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2641 # endpoint learnt via the parent GBP-vxlan interface
2642 self.assertTrue(find_gbp_endpoint(self,
2643 vx_tun_l3._sw_if_index,
2648 # remote endpoint becomes local
2650 self.pg2.unconfig_ip4()
2651 self.pg3.unconfig_ip4()
2652 self.pg4.unconfig_ip4()
2654 def test_gbp_redirect(self):
2655 """ GBP Endpoint Redirect """
2657 self.vapi.cli("set logging class gbp debug")
2659 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
2660 routed_dst_mac = "00:0c:0c:0c:0c:0c"
2661 routed_src_mac = "00:22:bd:f8:19:ff"
2663 learnt = [{'mac': '00:00:11:11:11:02',
2665 'ip6': '2001:10::2'},
2666 {'mac': '00:00:11:11:11:03',
2668 'ip6': '2001:10::3'}]
2673 t4 = VppIpTable(self, 1)
2675 t6 = VppIpTable(self, 1, True)
2678 rd1 = VppGbpRouteDomain(self, 2, t4, t6)
2679 rd1.add_vpp_config()
2681 self.loop0.set_mac(self.router_mac)
2684 # Bind the BVI to the RD
2686 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
2687 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
2690 # Pg7 hosts a BD's UU-fwd
2692 self.pg7.config_ip4()
2693 self.pg7.resolve_arp()
2696 # a GBP bridge domains for the EPs
2698 bd1 = VppBridgeDomain(self, 1)
2699 bd1.add_vpp_config()
2700 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0)
2701 gbd1.add_vpp_config()
2703 bd2 = VppBridgeDomain(self, 2)
2704 bd2.add_vpp_config()
2705 gbd2 = VppGbpBridgeDomain(self, bd2, self.loop1)
2706 gbd2.add_vpp_config()
2708 # ... and has a /32 and /128 applied
2709 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2710 ip4_addr.add_vpp_config()
2711 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 128)
2712 ip6_addr.add_vpp_config()
2713 ip4_addr = VppIpInterfaceAddress(self, gbd2.bvi, "10.0.1.128", 32)
2714 ip4_addr.add_vpp_config()
2715 ip6_addr = VppIpInterfaceAddress(self, gbd2.bvi, "2001:11::128", 128)
2716 ip6_addr.add_vpp_config()
2719 # The Endpoint-groups in which we are learning endpoints
2721 epg_220 = VppGbpEndpointGroup(self, 220, 440, rd1, gbd1,
2725 VppGbpEndpointRetention(2))
2726 epg_220.add_vpp_config()
2727 epg_221 = VppGbpEndpointGroup(self, 221, 441, rd1, gbd2,
2731 VppGbpEndpointRetention(2))
2732 epg_221.add_vpp_config()
2733 epg_222 = VppGbpEndpointGroup(self, 222, 442, rd1, gbd1,
2737 VppGbpEndpointRetention(2))
2738 epg_222.add_vpp_config()
2741 # a GBP bridge domains for the SEPs
2743 bd_uu1 = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
2744 self.pg7.remote_ip4, 116)
2745 bd_uu1.add_vpp_config()
2746 bd_uu2 = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
2747 self.pg7.remote_ip4, 117)
2748 bd_uu2.add_vpp_config()
2750 bd3 = VppBridgeDomain(self, 3)
2751 bd3.add_vpp_config()
2752 gbd3 = VppGbpBridgeDomain(self, bd3, self.loop2, bd_uu1, learn=False)
2753 gbd3.add_vpp_config()
2754 bd4 = VppBridgeDomain(self, 4)
2755 bd4.add_vpp_config()
2756 gbd4 = VppGbpBridgeDomain(self, bd4, self.loop3, bd_uu2, learn=False)
2757 gbd4.add_vpp_config()
2760 # EPGs in which the service endpoints exist
2762 epg_320 = VppGbpEndpointGroup(self, 320, 550, rd1, gbd3,
2766 VppGbpEndpointRetention(2))
2767 epg_320.add_vpp_config()
2768 epg_321 = VppGbpEndpointGroup(self, 321, 551, rd1, gbd4,
2772 VppGbpEndpointRetention(2))
2773 epg_321.add_vpp_config()
2776 # three local endpoints
2778 ep1 = VppGbpEndpoint(self, self.pg0,
2780 "10.0.0.1", "11.0.0.1",
2781 "2001:10::1", "3001:10::1")
2782 ep1.add_vpp_config()
2783 ep2 = VppGbpEndpoint(self, self.pg1,
2785 "10.0.1.1", "11.0.1.1",
2786 "2001:11::1", "3001:11::1")
2787 ep2.add_vpp_config()
2788 ep3 = VppGbpEndpoint(self, self.pg2,
2790 "10.0.2.2", "11.0.2.2",
2791 "2001:12::1", "3001:12::1")
2792 ep3.add_vpp_config()
2797 sep1 = VppGbpEndpoint(self, self.pg3,
2799 "12.0.0.1", "13.0.0.1",
2800 "4001:10::1", "5001:10::1")
2801 sep1.add_vpp_config()
2802 sep2 = VppGbpEndpoint(self, self.pg4,
2804 "12.0.0.2", "13.0.0.2",
2805 "4001:10::2", "5001:10::2")
2806 sep2.add_vpp_config()
2807 sep3 = VppGbpEndpoint(self, self.pg5,
2809 "12.0.1.1", "13.0.1.1",
2810 "4001:11::1", "5001:11::1")
2811 sep3.add_vpp_config()
2812 # this EP is not installed immediately
2813 sep4 = VppGbpEndpoint(self, self.pg6,
2815 "12.0.1.2", "13.0.1.2",
2816 "4001:11::2", "5001:11::2")
2819 # an L2 switch packet between local EPs in different EPGs
2820 # different dest ports on each so the are LB hashed differently
2822 p4 = [(Ether(src=ep1.mac, dst=ep3.mac) /
2823 IP(src=ep1.ip4.address, dst=ep3.ip4.address) /
2824 UDP(sport=1234, dport=1234) /
2826 (Ether(src=ep3.mac, dst=ep1.mac) /
2827 IP(src=ep3.ip4.address, dst=ep1.ip4.address) /
2828 UDP(sport=1234, dport=1234) /
2830 p6 = [(Ether(src=ep1.mac, dst=ep3.mac) /
2831 IPv6(src=ep1.ip6.address, dst=ep3.ip6.address) /
2832 UDP(sport=1234, dport=1234) /
2834 (Ether(src=ep3.mac, dst=ep1.mac) /
2835 IPv6(src=ep3.ip6.address, dst=ep1.ip6.address) /
2836 UDP(sport=1234, dport=1230) /
2839 # should be dropped since no contract yet
2840 self.send_and_assert_no_replies(self.pg0, [p4[0]])
2841 self.send_and_assert_no_replies(self.pg0, [p6[0]])
2844 # Add a contract with a rule to load-balance redirect via SEP1 and SEP2
2845 # one of the next-hops is via an EP that is not known
2847 acl = VppGbpAcl(self)
2848 rule4 = acl.create_rule(permit_deny=1, proto=17)
2849 rule6 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
2850 acl_index = acl.add_vpp_config([rule4, rule6])
2853 # test the src-ip hash mode
2855 c1 = VppGbpContract(
2856 self, epg_220.sclass, epg_222.sclass, acl_index,
2857 [VppGbpContractRule(
2858 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2859 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2860 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
2861 sep1.ip4, sep1.epg.rd),
2862 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
2863 sep2.ip4, sep2.epg.rd)]),
2865 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2866 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2867 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
2868 sep3.ip6, sep3.epg.rd),
2869 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
2870 sep4.ip6, sep4.epg.rd)])],
2871 [ETH_P_IP, ETH_P_IPV6])
2874 c2 = VppGbpContract(
2875 self, epg_222.sclass, epg_220.sclass, acl_index,
2876 [VppGbpContractRule(
2877 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2878 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2879 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
2880 sep1.ip4, sep1.epg.rd),
2881 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
2882 sep2.ip4, sep2.epg.rd)]),
2884 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2885 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2886 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
2887 sep3.ip6, sep3.epg.rd),
2888 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
2889 sep4.ip6, sep4.epg.rd)])],
2890 [ETH_P_IP, ETH_P_IPV6])
2894 # send again with the contract preset, now packets arrive
2895 # at SEP1 or SEP2 depending on the hashing
2897 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
2900 self.assertEqual(rx[Ether].src, routed_src_mac)
2901 self.assertEqual(rx[Ether].dst, sep1.mac)
2902 self.assertEqual(rx[IP].src, ep1.ip4.address)
2903 self.assertEqual(rx[IP].dst, ep3.ip4.address)
2905 rxs = self.send_and_expect(self.pg2, p4[1] * 17, sep2.itf)
2908 self.assertEqual(rx[Ether].src, routed_src_mac)
2909 self.assertEqual(rx[Ether].dst, sep2.mac)
2910 self.assertEqual(rx[IP].src, ep3.ip4.address)
2911 self.assertEqual(rx[IP].dst, ep1.ip4.address)
2913 rxs = self.send_and_expect(self.pg0, p6[0] * 17, self.pg7)
2916 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
2917 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
2918 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
2919 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
2920 self.assertEqual(rx[VXLAN].vni, 117)
2921 self.assertTrue(rx[VXLAN].flags.G)
2922 self.assertTrue(rx[VXLAN].flags.Instance)
2923 # redirect policy has been applied
2924 self.assertTrue(rx[VXLAN].gpflags.A)
2925 self.assertFalse(rx[VXLAN].gpflags.D)
2927 inner = rx[VXLAN].payload
2929 self.assertEqual(inner[Ether].src, routed_src_mac)
2930 self.assertEqual(inner[Ether].dst, sep4.mac)
2931 self.assertEqual(inner[IPv6].src, ep1.ip6.address)
2932 self.assertEqual(inner[IPv6].dst, ep3.ip6.address)
2934 rxs = self.send_and_expect(self.pg2, p6[1] * 17, sep3.itf)
2937 self.assertEqual(rx[Ether].src, routed_src_mac)
2938 self.assertEqual(rx[Ether].dst, sep3.mac)
2939 self.assertEqual(rx[IPv6].src, ep3.ip6.address)
2940 self.assertEqual(rx[IPv6].dst, ep1.ip6.address)
2943 # programme the unknown EP
2945 sep4.add_vpp_config()
2947 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep4.itf)
2950 self.assertEqual(rx[Ether].src, routed_src_mac)
2951 self.assertEqual(rx[Ether].dst, sep4.mac)
2952 self.assertEqual(rx[IPv6].src, ep1.ip6.address)
2953 self.assertEqual(rx[IPv6].dst, ep3.ip6.address)
2956 # and revert back to unprogrammed
2958 sep4.remove_vpp_config()
2960 rxs = self.send_and_expect(self.pg0, p6[0] * 17, self.pg7)
2963 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
2964 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
2965 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
2966 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
2967 self.assertEqual(rx[VXLAN].vni, 117)
2968 self.assertTrue(rx[VXLAN].flags.G)
2969 self.assertTrue(rx[VXLAN].flags.Instance)
2970 # redirect policy has been applied
2971 self.assertTrue(rx[VXLAN].gpflags.A)
2972 self.assertFalse(rx[VXLAN].gpflags.D)
2974 inner = rx[VXLAN].payload
2976 self.assertEqual(inner[Ether].src, routed_src_mac)
2977 self.assertEqual(inner[Ether].dst, sep4.mac)
2978 self.assertEqual(inner[IPv6].src, ep1.ip6.address)
2979 self.assertEqual(inner[IPv6].dst, ep3.ip6.address)
2981 c1.remove_vpp_config()
2982 c2.remove_vpp_config()
2985 # test the symmetric hash mode
2987 c1 = VppGbpContract(
2988 self, epg_220.sclass, epg_222.sclass, acl_index,
2989 [VppGbpContractRule(
2990 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2991 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
2992 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
2993 sep1.ip4, sep1.epg.rd),
2994 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
2995 sep2.ip4, sep2.epg.rd)]),
2997 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2998 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
2999 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3000 sep3.ip6, sep3.epg.rd),
3001 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3002 sep4.ip6, sep4.epg.rd)])],
3003 [ETH_P_IP, ETH_P_IPV6])
3006 c2 = VppGbpContract(
3007 self, epg_222.sclass, epg_220.sclass, acl_index,
3008 [VppGbpContractRule(
3009 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3010 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3011 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3012 sep1.ip4, sep1.epg.rd),
3013 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3014 sep2.ip4, sep2.epg.rd)]),
3016 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3017 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3018 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3019 sep3.ip6, sep3.epg.rd),
3020 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3021 sep4.ip6, sep4.epg.rd)])],
3022 [ETH_P_IP, ETH_P_IPV6])
3026 # send again with the contract preset, now packets arrive
3027 # at SEP1 for both directions
3029 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3032 self.assertEqual(rx[Ether].src, routed_src_mac)
3033 self.assertEqual(rx[Ether].dst, sep1.mac)
3034 self.assertEqual(rx[IP].src, ep1.ip4.address)
3035 self.assertEqual(rx[IP].dst, ep3.ip4.address)
3037 rxs = self.send_and_expect(self.pg2, p4[1] * 17, sep1.itf)
3040 self.assertEqual(rx[Ether].src, routed_src_mac)
3041 self.assertEqual(rx[Ether].dst, sep1.mac)
3042 self.assertEqual(rx[IP].src, ep3.ip4.address)
3043 self.assertEqual(rx[IP].dst, ep1.ip4.address)
3046 # programme the unknown EP for the L3 tests
3048 sep4.add_vpp_config()
3051 # an L3 switch packet between local EPs in different EPGs
3052 # different dest ports on each so the are LB hashed differently
3054 p4 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3055 IP(src=ep1.ip4.address, dst=ep2.ip4.address) /
3056 UDP(sport=1234, dport=1234) /
3058 (Ether(src=ep2.mac, dst=str(self.router_mac)) /
3059 IP(src=ep2.ip4.address, dst=ep1.ip4.address) /
3060 UDP(sport=1234, dport=1234) /
3062 p6 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3063 IPv6(src=ep1.ip6.address, dst=ep2.ip6.address) /
3064 UDP(sport=1234, dport=1234) /
3066 (Ether(src=ep2.mac, dst=str(self.router_mac)) /
3067 IPv6(src=ep2.ip6.address, dst=ep1.ip6.address) /
3068 UDP(sport=1234, dport=1234) /
3071 c3 = VppGbpContract(
3072 self, epg_220.sclass, epg_221.sclass, acl_index,
3073 [VppGbpContractRule(
3074 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3075 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3076 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3077 sep1.ip4, sep1.epg.rd),
3078 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3079 sep2.ip4, sep2.epg.rd)]),
3081 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3082 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3083 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3084 sep3.ip6, sep3.epg.rd),
3085 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3086 sep4.ip6, sep4.epg.rd)])],
3087 [ETH_P_IP, ETH_P_IPV6])
3090 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3093 self.assertEqual(rx[Ether].src, routed_src_mac)
3094 self.assertEqual(rx[Ether].dst, sep1.mac)
3095 self.assertEqual(rx[IP].src, ep1.ip4.address)
3096 self.assertEqual(rx[IP].dst, ep2.ip4.address)
3099 # learn a remote EP in EPG 221
3101 vx_tun_l3 = VppGbpVxlanTunnel(
3102 self, 444, rd1.rd_id,
3103 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
3105 vx_tun_l3.add_vpp_config()
3107 c4 = VppGbpContract(
3108 self, epg_221.sclass, epg_220.sclass, acl_index,
3109 [VppGbpContractRule(
3110 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3113 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3115 [ETH_P_IP, ETH_P_IPV6])
3118 p = (Ether(src=self.pg7.remote_mac,
3119 dst=self.pg7.local_mac) /
3120 IP(src=self.pg7.remote_ip4,
3121 dst=self.pg7.local_ip4) /
3122 UDP(sport=1234, dport=48879) /
3123 VXLAN(vni=444, gpid=441, flags=0x88) /
3124 Ether(src="00:22:22:22:22:33", dst=str(self.router_mac)) /
3125 IP(src="10.0.0.88", dst=ep1.ip4.address) /
3126 UDP(sport=1234, dport=1234) /
3129 rx = self.send_and_expect(self.pg7, [p], self.pg0)
3131 # endpoint learnt via the parent GBP-vxlan interface
3132 self.assertTrue(find_gbp_endpoint(self,
3133 vx_tun_l3._sw_if_index,
3136 p = (Ether(src=self.pg7.remote_mac,
3137 dst=self.pg7.local_mac) /
3138 IP(src=self.pg7.remote_ip4,
3139 dst=self.pg7.local_ip4) /
3140 UDP(sport=1234, dport=48879) /
3141 VXLAN(vni=444, gpid=441, flags=0x88) /
3142 Ether(src="00:22:22:22:22:33", dst=str(self.router_mac)) /
3143 IPv6(src="2001:10::88", dst=ep1.ip6.address) /
3144 UDP(sport=1234, dport=1234) /
3147 rx = self.send_and_expect(self.pg7, [p], self.pg0)
3149 # endpoint learnt via the parent GBP-vxlan interface
3150 self.assertTrue(find_gbp_endpoint(self,
3151 vx_tun_l3._sw_if_index,
3155 # L3 switch from local to remote EP
3157 p4 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3158 IP(src=ep1.ip4.address, dst="10.0.0.88") /
3159 UDP(sport=1234, dport=1234) /
3161 p6 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3162 IPv6(src=ep1.ip6.address, dst="2001:10::88") /
3163 UDP(sport=1234, dport=1234) /
3166 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3169 self.assertEqual(rx[Ether].src, routed_src_mac)
3170 self.assertEqual(rx[Ether].dst, sep1.mac)
3171 self.assertEqual(rx[IP].src, ep1.ip4.address)
3172 self.assertEqual(rx[IP].dst, "10.0.0.88")
3174 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep4.itf)
3177 self.assertEqual(rx[Ether].src, routed_src_mac)
3178 self.assertEqual(rx[Ether].dst, sep4.mac)
3179 self.assertEqual(rx[IPv6].src, ep1.ip6.address)
3180 self.assertEqual(rx[IPv6].dst, "2001:10::88")
3183 # test the dst-ip hash mode
3185 c5 = VppGbpContract(
3186 self, epg_220.sclass, epg_221.sclass, acl_index,
3187 [VppGbpContractRule(
3188 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3189 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
3190 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3191 sep1.ip4, sep1.epg.rd),
3192 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3193 sep2.ip4, sep2.epg.rd)]),
3195 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3196 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
3197 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3198 sep3.ip6, sep3.epg.rd),
3199 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3200 sep4.ip6, sep4.epg.rd)])],
3201 [ETH_P_IP, ETH_P_IPV6])
3204 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3207 self.assertEqual(rx[Ether].src, routed_src_mac)
3208 self.assertEqual(rx[Ether].dst, sep1.mac)
3209 self.assertEqual(rx[IP].src, ep1.ip4.address)
3210 self.assertEqual(rx[IP].dst, "10.0.0.88")
3212 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep3.itf)
3215 self.assertEqual(rx[Ether].src, routed_src_mac)
3216 self.assertEqual(rx[Ether].dst, sep3.mac)
3217 self.assertEqual(rx[IPv6].src, ep1.ip6.address)
3218 self.assertEqual(rx[IPv6].dst, "2001:10::88")
3223 self.pg7.unconfig_ip4()
3225 def test_gbp_l3_out(self):
3228 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
3229 self.vapi.cli("set logging class gbp debug")
3231 routed_dst_mac = "00:0c:0c:0c:0c:0c"
3232 routed_src_mac = "00:22:bd:f8:19:ff"
3237 t4 = VppIpTable(self, 1)
3239 t6 = VppIpTable(self, 1, True)
3242 rd1 = VppGbpRouteDomain(self, 2, t4, t6)
3243 rd1.add_vpp_config()
3245 self.loop0.set_mac(self.router_mac)
3248 # Bind the BVI to the RD
3250 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
3251 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
3254 # Pg7 hosts a BD's BUM
3255 # Pg1 some other l3 interface
3257 self.pg7.config_ip4()
3258 self.pg7.resolve_arp()
3261 # a multicast vxlan-gbp tunnel for broadcast in the BD
3263 tun_bm = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
3266 tun_bm.add_vpp_config()
3269 # a GBP external bridge domains for the EPs
3271 bd1 = VppBridgeDomain(self, 1)
3272 bd1.add_vpp_config()
3273 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0, None, tun_bm)
3274 gbd1.add_vpp_config()
3277 # The Endpoint-groups in which the external endpoints exist
3279 epg_220 = VppGbpEndpointGroup(self, 220, 113, rd1, gbd1,
3283 VppGbpEndpointRetention(2))
3284 epg_220.add_vpp_config()
3286 # the BVIs have the subnets applied ...
3287 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 24)
3288 ip4_addr.add_vpp_config()
3289 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 64)
3290 ip6_addr.add_vpp_config()
3292 # ... which are L3-out subnets
3293 l3o_1 = VppGbpSubnet(
3294 self, rd1, "10.0.0.0", 24,
3295 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3297 l3o_1.add_vpp_config()
3300 # an external interface attached to the outside world and the
3303 vlan_100 = VppDot1QSubint(self, self.pg0, 100)
3305 VppL2Vtr(self, vlan_100, L2_VTR_OP.L2_POP_1).add_vpp_config()
3306 vlan_101 = VppDot1QSubint(self, self.pg0, 101)
3308 VppL2Vtr(self, vlan_101, L2_VTR_OP.L2_POP_1).add_vpp_config()
3310 ext_itf = VppGbpExtItf(self, self.loop0, bd1, rd1)
3311 ext_itf.add_vpp_config()
3314 # an unicast vxlan-gbp for inter-RD traffic
3316 vx_tun_l3 = VppGbpVxlanTunnel(
3317 self, 444, rd1.rd_id,
3318 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
3320 vx_tun_l3.add_vpp_config()
3323 # External Endpoints
3325 eep1 = VppGbpEndpoint(self, vlan_100,
3327 "10.0.0.1", "11.0.0.1",
3328 "2001:10::1", "3001::1",
3329 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
3330 eep1.add_vpp_config()
3331 eep2 = VppGbpEndpoint(self, vlan_101,
3333 "10.0.0.2", "11.0.0.2",
3334 "2001:10::2", "3001::2",
3335 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
3336 eep2.add_vpp_config()
3339 # A remote external endpoint
3341 rep = VppGbpEndpoint(self, vx_tun_l3,
3343 "10.0.0.101", "11.0.0.101",
3344 "2001:10::101", "3001::101",
3345 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
3347 self.pg7.remote_ip4,
3349 rep.add_vpp_config()
3352 # ARP packet from External EPs are accepted and replied to
3354 p_arp = (Ether(src=eep1.mac, dst="ff:ff:ff:ff:ff:ff") /
3357 psrc=eep1.ip4.address, pdst="10.0.0.128",
3358 hwsrc=eep1.mac, hwdst="ff:ff:ff:ff:ff:ff"))
3359 rxs = self.send_and_expect(self.pg0, p_arp * 1, self.pg0)
3362 # packets destined to unknown addresses in the BVI's subnet
3365 p4 = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3367 IP(src="10.0.0.1", dst="10.0.0.88") /
3368 UDP(sport=1234, dport=1234) /
3370 p6 = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3372 IPv6(src="2001:10::1", dst="2001:10::88") /
3373 UDP(sport=1234, dport=1234) /
3376 rxs = self.send_and_expect(self.pg0, p4 * 1, self.pg7)
3379 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3380 # self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3381 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3382 self.assertEqual(rx[IP].dst, "239.1.1.1")
3383 self.assertEqual(rx[VXLAN].vni, 88)
3384 self.assertTrue(rx[VXLAN].flags.G)
3385 self.assertTrue(rx[VXLAN].flags.Instance)
3386 # policy was applied to the original IP packet
3387 self.assertEqual(rx[VXLAN].gpid, 113)
3388 self.assertTrue(rx[VXLAN].gpflags.A)
3389 self.assertFalse(rx[VXLAN].gpflags.D)
3391 inner = rx[VXLAN].payload
3393 self.assertTrue(inner.haslayer(ARP))
3396 # remote to external
3398 p = (Ether(src=self.pg7.remote_mac,
3399 dst=self.pg7.local_mac) /
3400 IP(src=self.pg7.remote_ip4,
3401 dst=self.pg7.local_ip4) /
3402 UDP(sport=1234, dport=48879) /
3403 VXLAN(vni=444, gpid=113, flags=0x88) /
3404 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
3405 IP(src="10.0.0.101", dst="10.0.0.1") /
3406 UDP(sport=1234, dport=1234) /
3409 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
3412 # local EP pings router
3414 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3416 IP(src=eep1.ip4.address, dst="10.0.0.128") /
3417 ICMP(type='echo-request'))
3419 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
3422 self.assertEqual(rx[Ether].src, str(self.router_mac))
3423 self.assertEqual(rx[Ether].dst, eep1.mac)
3424 self.assertEqual(rx[Dot1Q].vlan, 100)
3427 # local EP pings other local EP
3429 p = (Ether(src=eep1.mac, dst=eep2.mac) /
3431 IP(src=eep1.ip4.address, dst=eep2.ip4.address) /
3432 ICMP(type='echo-request'))
3434 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
3437 self.assertEqual(rx[Ether].src, eep1.mac)
3438 self.assertEqual(rx[Ether].dst, eep2.mac)
3439 self.assertEqual(rx[Dot1Q].vlan, 101)
3442 # A subnet reachable through the external EP1
3444 ip_220 = VppIpRoute(self, "10.220.0.0", 24,
3445 [VppRoutePath(eep1.ip4.address,
3446 eep1.epg.bvi.sw_if_index)],
3447 table_id=t4.table_id)
3448 ip_220.add_vpp_config()
3450 l3o_220 = VppGbpSubnet(
3451 self, rd1, "10.220.0.0", 24,
3452 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3454 l3o_220.add_vpp_config()
3457 # A subnet reachable through the external EP2
3459 ip_221 = VppIpRoute(self, "10.221.0.0", 24,
3460 [VppRoutePath(eep2.ip4.address,
3461 eep2.epg.bvi.sw_if_index)],
3462 table_id=t4.table_id)
3463 ip_221.add_vpp_config()
3465 l3o_221 = VppGbpSubnet(
3466 self, rd1, "10.221.0.0", 24,
3467 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3469 l3o_221.add_vpp_config()
3472 # ping between hosts in remote subnets
3473 # dropped without a contract
3475 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3477 IP(src="10.220.0.1", dst="10.221.0.1") /
3478 ICMP(type='echo-request'))
3480 rxs = self.send_and_assert_no_replies(self.pg0, p * 1)
3483 # contract for the external nets to communicate
3485 acl = VppGbpAcl(self)
3486 rule4 = acl.create_rule(permit_deny=1, proto=17)
3487 rule6 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
3488 acl_index = acl.add_vpp_config([rule4, rule6])
3490 c1 = VppGbpContract(
3491 self, 4220, 4221, acl_index,
3492 [VppGbpContractRule(
3493 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3496 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3498 [ETH_P_IP, ETH_P_IPV6])
3502 # Contracts allowing ext-net 200 to talk with external EPs
3504 c2 = VppGbpContract(
3505 self, 4220, 113, acl_index,
3506 [VppGbpContractRule(
3507 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3510 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3512 [ETH_P_IP, ETH_P_IPV6])
3514 c3 = VppGbpContract(
3515 self, 113, 4220, acl_index,
3516 [VppGbpContractRule(
3517 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3520 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3522 [ETH_P_IP, ETH_P_IPV6])
3526 # ping between hosts in remote subnets
3528 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3530 IP(src="10.220.0.1", dst="10.221.0.1") /
3531 UDP(sport=1234, dport=1234) /
3534 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
3537 self.assertEqual(rx[Ether].src, str(self.router_mac))
3538 self.assertEqual(rx[Ether].dst, eep2.mac)
3539 self.assertEqual(rx[Dot1Q].vlan, 101)
3541 # we did not learn these external hosts
3542 self.assertFalse(find_gbp_endpoint(self, ip="10.220.0.1"))
3543 self.assertFalse(find_gbp_endpoint(self, ip="10.221.0.1"))
3546 # from remote external EP to local external EP
3548 p = (Ether(src=self.pg7.remote_mac,
3549 dst=self.pg7.local_mac) /
3550 IP(src=self.pg7.remote_ip4,
3551 dst=self.pg7.local_ip4) /
3552 UDP(sport=1234, dport=48879) /
3553 VXLAN(vni=444, gpid=113, flags=0x88) /
3554 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
3555 IP(src="10.0.0.101", dst="10.220.0.1") /
3556 UDP(sport=1234, dport=1234) /
3559 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
3562 # ping from an external host to the remote external EP
3564 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3566 IP(src="10.220.0.1", dst=rep.ip4.address) /
3567 UDP(sport=1234, dport=1234) /
3570 rxs = self.send_and_expect(self.pg0, p * 1, self.pg7)
3573 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3574 # self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3575 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3576 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
3577 self.assertEqual(rx[VXLAN].vni, 444)
3578 self.assertTrue(rx[VXLAN].flags.G)
3579 self.assertTrue(rx[VXLAN].flags.Instance)
3580 # the sclass of the ext-net the packet came from
3581 self.assertEqual(rx[VXLAN].gpid, 4220)
3582 # policy was applied to the original IP packet
3583 self.assertTrue(rx[VXLAN].gpflags.A)
3584 # since it's an external host the reciever should not learn it
3585 self.assertTrue(rx[VXLAN].gpflags.D)
3586 inner = rx[VXLAN].payload
3587 self.assertEqual(inner[IP].src, "10.220.0.1")
3588 self.assertEqual(inner[IP].dst, rep.ip4.address)
3591 # An external subnet reachable via the remote external EP
3595 # first the VXLAN-GBP tunnel over which it is reached
3597 vx_tun_r = VppVxlanGbpTunnel(
3598 self, self.pg7.local_ip4,
3599 self.pg7.remote_ip4, 445,
3600 mode=(VppEnum.vl_api_vxlan_gbp_api_tunnel_mode_t.
3601 VXLAN_GBP_API_TUNNEL_MODE_L3))
3602 vx_tun_r.add_vpp_config()
3603 VppIpInterfaceBind(self, vx_tun_r, t4).add_vpp_config()
3605 self.logger.info(self.vapi.cli("sh vxlan-gbp tunnel"))
3608 # then the special adj to resolve through on that tunnel
3610 n1 = VppNeighbor(self,
3611 vx_tun_r.sw_if_index,
3612 "00:0c:0c:0c:0c:0c",
3613 self.pg7.remote_ip4)
3617 # the route via the adj above
3619 ip_222 = VppIpRoute(self, "10.222.0.0", 24,
3620 [VppRoutePath(self.pg7.remote_ip4,
3621 vx_tun_r.sw_if_index)],
3622 table_id=t4.table_id)
3623 ip_222.add_vpp_config()
3625 l3o_222 = VppGbpSubnet(
3626 self, rd1, "10.222.0.0", 24,
3627 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3629 l3o_222.add_vpp_config()
3632 # ping between hosts in local and remote external subnets
3633 # dropped without a contract
3635 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3637 IP(src="10.220.0.1", dst="10.222.0.1") /
3638 UDP(sport=1234, dport=1234) /
3641 rxs = self.send_and_assert_no_replies(self.pg0, p * 1)
3644 # Add contracts ext-nets for 220 -> 222
3646 c4 = VppGbpContract(
3647 self, 4220, 4222, acl_index,
3648 [VppGbpContractRule(
3649 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3652 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3654 [ETH_P_IP, ETH_P_IPV6])
3658 # ping from host in local to remote external subnets
3660 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3662 IP(src="10.220.0.1", dst="10.222.0.1") /
3663 UDP(sport=1234, dport=1234) /
3666 rxs = self.send_and_expect(self.pg0, p * 3, self.pg7)
3669 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3670 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3671 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3672 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
3673 self.assertEqual(rx[VXLAN].vni, 445)
3674 self.assertTrue(rx[VXLAN].flags.G)
3675 self.assertTrue(rx[VXLAN].flags.Instance)
3676 # the sclass of the ext-net the packet came from
3677 self.assertEqual(rx[VXLAN].gpid, 4220)
3678 # policy was applied to the original IP packet
3679 self.assertTrue(rx[VXLAN].gpflags.A)
3680 # since it's an external host the reciever should not learn it
3681 self.assertTrue(rx[VXLAN].gpflags.D)
3682 inner = rx[VXLAN].payload
3683 self.assertEqual(inner[Ether].dst, "00:0c:0c:0c:0c:0c")
3684 self.assertEqual(inner[IP].src, "10.220.0.1")
3685 self.assertEqual(inner[IP].dst, "10.222.0.1")
3688 # ping from host in remote to local external subnets
3689 # there's no contract for this, but the A bit is set.
3691 p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
3692 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
3693 UDP(sport=1234, dport=48879) /
3694 VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
3695 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
3696 IP(src="10.222.0.1", dst="10.220.0.1") /
3697 UDP(sport=1234, dport=1234) /
3700 rxs = self.send_and_expect(self.pg7, p * 3, self.pg0)
3701 self.assertFalse(find_gbp_endpoint(self, ip="10.222.0.1"))
3704 # ping from host in remote to remote external subnets
3705 # this is dropped by reflection check.
3707 p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
3708 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
3709 UDP(sport=1234, dport=48879) /
3710 VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
3711 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
3712 IP(src="10.222.0.1", dst="10.222.0.2") /
3713 UDP(sport=1234, dport=1234) /
3716 rxs = self.send_and_assert_no_replies(self.pg7, p * 3)
3721 self.pg7.unconfig_ip4()
3722 vlan_100.set_vtr(L2_VTR_OP.L2_DISABLED)
3725 if __name__ == '__main__':
3726 unittest.main(testRunner=VppTestRunner)