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, ETH_P_ARP
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)
702 def send_and_expect_no_arp(self, src, tx, dst):
703 self.pg_send(src, tx)
704 dst.get_capture(0, timeout=1)
705 dst.assert_nothing_captured(remark="")
708 def send_and_expect_arp(self, src, tx, dst):
709 rx = self.send_and_expect(src, tx, dst)
712 self.assertEqual(r[Ether].src, tx[0][Ether].src)
713 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
714 self.assertEqual(r[ARP].psrc, tx[0][ARP].psrc)
715 self.assertEqual(r[ARP].pdst, tx[0][ARP].pdst)
716 self.assertEqual(r[ARP].hwsrc, tx[0][ARP].hwsrc)
717 self.assertEqual(r[ARP].hwdst, tx[0][ARP].hwdst)
721 """ Group Based Policy """
723 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
728 bd1 = VppBridgeDomain(self, 1)
729 bd2 = VppBridgeDomain(self, 2)
730 bd20 = VppBridgeDomain(self, 20)
734 bd20.add_vpp_config()
736 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0)
737 gbd2 = VppGbpBridgeDomain(self, bd2, self.loop1)
738 gbd20 = VppGbpBridgeDomain(self, bd20, self.loop2)
740 gbd1.add_vpp_config()
741 gbd2.add_vpp_config()
742 gbd20.add_vpp_config()
747 gt4 = VppIpTable(self, 0)
749 gt6 = VppIpTable(self, 0, is_ip6=True)
751 nt4 = VppIpTable(self, 20)
753 nt6 = VppIpTable(self, 20, is_ip6=True)
756 rd0 = VppGbpRouteDomain(self, 0, gt4, gt6, None, None)
757 rd20 = VppGbpRouteDomain(self, 20, nt4, nt6, None, None)
760 rd20.add_vpp_config()
763 # 3 EPGs, 2 of which share a BD.
764 # 2 NAT EPGs, one for floating-IP subnets, the other for internet
766 epgs = [VppGbpEndpointGroup(self, 220, 1220, rd0, gbd1,
767 self.pg4, self.loop0,
768 "10.0.0.128", "2001:10::128"),
769 VppGbpEndpointGroup(self, 221, 1221, rd0, gbd1,
770 self.pg5, self.loop0,
771 "10.0.1.128", "2001:10:1::128"),
772 VppGbpEndpointGroup(self, 222, 1222, rd0, gbd2,
773 self.pg6, self.loop1,
774 "10.0.2.128", "2001:10:2::128"),
775 VppGbpEndpointGroup(self, 333, 1333, rd20, gbd20,
776 self.pg7, self.loop2,
777 "11.0.0.128", "3001::128"),
778 VppGbpEndpointGroup(self, 444, 1444, rd20, gbd20,
779 self.pg8, self.loop2,
780 "11.0.0.129", "3001::129")]
781 recircs = [VppGbpRecirc(self, epgs[0], self.loop3),
782 VppGbpRecirc(self, epgs[1], self.loop4),
783 VppGbpRecirc(self, epgs[2], self.loop5),
784 VppGbpRecirc(self, epgs[3], self.loop6, is_ext=True),
785 VppGbpRecirc(self, epgs[4], self.loop7, is_ext=True)]
788 recirc_nat = recircs[3]
791 # 4 end-points, 2 in the same subnet, 3 in the same BD
793 eps = [VppGbpEndpoint(self, self.pg0,
795 "10.0.0.1", "11.0.0.1",
796 "2001:10::1", "3001::1"),
797 VppGbpEndpoint(self, self.pg1,
799 "10.0.0.2", "11.0.0.2",
800 "2001:10::2", "3001::2"),
801 VppGbpEndpoint(self, self.pg2,
803 "10.0.1.1", "11.0.0.3",
804 "2001:10:1::1", "3001::3"),
805 VppGbpEndpoint(self, self.pg3,
807 "10.0.2.1", "11.0.0.4",
808 "2001:10:2::1", "3001::4")]
811 # Config related to each of the EPGs
814 # IP config on the BVI interfaces
815 if epg != epgs[1] and epg != epgs[4]:
816 VppIpInterfaceBind(self, epg.bvi, epg.rd.t4).add_vpp_config()
817 VppIpInterfaceBind(self, epg.bvi, epg.rd.t6).add_vpp_config()
818 self.vapi.sw_interface_set_mac_address(
820 self.router_mac.packed)
822 # The BVIs are NAT inside interfaces
823 flags = self.config_flags.NAT_IS_INSIDE
824 self.vapi.nat44_interface_add_del_feature(
825 sw_if_index=epg.bvi.sw_if_index,
826 flags=flags, is_add=1)
827 self.vapi.nat66_add_del_interface(
828 is_add=1, flags=flags,
829 sw_if_index=epg.bvi.sw_if_index)
831 if_ip4 = VppIpInterfaceAddress(self, epg.bvi, epg.bvi_ip4, 32)
832 if_ip6 = VppIpInterfaceAddress(self, epg.bvi, epg.bvi_ip6, 128)
833 if_ip4.add_vpp_config()
834 if_ip6.add_vpp_config()
836 # EPG uplink interfaces in the RD
837 VppIpInterfaceBind(self, epg.uplink, epg.rd.t4).add_vpp_config()
838 VppIpInterfaceBind(self, epg.uplink, epg.rd.t6).add_vpp_config()
840 # add the BD ARP termination entry for BVI IP
841 epg.bd_arp_ip4 = VppBridgeDomainArpEntry(self, epg.bd.bd,
842 str(self.router_mac),
844 epg.bd_arp_ip6 = VppBridgeDomainArpEntry(self, epg.bd.bd,
845 str(self.router_mac),
847 epg.bd_arp_ip4.add_vpp_config()
848 epg.bd_arp_ip6.add_vpp_config()
853 for recirc in recircs:
854 # EPG's ingress recirculation interface maps to its RD
855 VppIpInterfaceBind(self, recirc.recirc,
856 recirc.epg.rd.t4).add_vpp_config()
857 VppIpInterfaceBind(self, recirc.recirc,
858 recirc.epg.rd.t6).add_vpp_config()
860 self.vapi.nat44_interface_add_del_feature(
861 sw_if_index=recirc.recirc.sw_if_index, is_add=1)
862 self.vapi.nat66_add_del_interface(
864 sw_if_index=recirc.recirc.sw_if_index)
866 recirc.add_vpp_config()
868 for recirc in recircs:
869 self.assertTrue(find_bridge_domain_port(self,
870 recirc.epg.bd.bd.bd_id,
871 recirc.recirc.sw_if_index))
874 self.pg_enable_capture(self.pg_interfaces)
877 # routes to the endpoints. We need these since there are no
878 # adj-fibs due to the fact the the BVI address has /32 and
879 # the subnet is not attached.
881 for (ip, fip) in zip(ep.ips, ep.fips):
882 # Add static mappings for each EP from the 10/8 to 11/8 network
884 flags = self.config_flags.NAT_IS_ADDR_ONLY
885 self.vapi.nat44_add_del_static_mapping(
887 local_ip_address=ip.bytes,
888 external_ip_address=fip.bytes,
889 external_sw_if_index=0xFFFFFFFF,
893 self.vapi.nat66_add_del_static_mapping(
894 local_ip_address=ip.bytes,
895 external_ip_address=fip.bytes,
901 self.logger.info(self.vapi.cli("sh gbp endpoint"))
903 # ... results in a Gratuitous ARP/ND on the EPG's uplink
904 rx = ep.epg.uplink.get_capture(len(ep.ips), timeout=0.2)
906 for ii, ip in enumerate(ep.ips):
910 self.assertTrue(p.haslayer(ICMPv6ND_NA))
911 self.assertEqual(p[ICMPv6ND_NA].tgt, ip.address)
913 self.assertTrue(p.haslayer(ARP))
914 self.assertEqual(p[ARP].psrc, ip.address)
915 self.assertEqual(p[ARP].pdst, ip.address)
917 # add the BD ARP termination entry for floating IP
919 ba = VppBridgeDomainArpEntry(self, epg_nat.bd.bd, ep.mac, fip)
922 # floating IPs route via EPG recirc
923 r = VppIpRoute(self, fip.address, fip.length,
924 [VppRoutePath(fip.address,
925 ep.recirc.recirc.sw_if_index,
927 proto=fip.dpo_proto)],
932 # L2 FIB entries in the NAT EPG BD to bridge the packets from
933 # the outside direct to the internal EPG
934 lf = VppL2FibEntry(self, epg_nat.bd.bd, ep.mac,
935 ep.recirc.recirc, bvi_mac=0)
939 # ARP packets for unknown IP are sent to the EPG uplink
941 pkt_arp = (Ether(dst="ff:ff:ff:ff:ff:ff",
942 src=self.pg0.remote_mac) /
944 hwdst="ff:ff:ff:ff:ff:ff",
945 hwsrc=self.pg0.remote_mac,
949 self.vapi.cli("clear trace")
950 self.pg0.add_stream(pkt_arp)
952 self.pg_enable_capture(self.pg_interfaces)
955 rxd = epgs[0].uplink.get_capture(1)
958 # ARP/ND packets get a response
960 pkt_arp = (Ether(dst="ff:ff:ff:ff:ff:ff",
961 src=self.pg0.remote_mac) /
963 hwdst="ff:ff:ff:ff:ff:ff",
964 hwsrc=self.pg0.remote_mac,
965 pdst=epgs[0].bvi_ip4.address,
966 psrc=eps[0].ip4.address))
968 self.send_and_expect(self.pg0, [pkt_arp], self.pg0)
970 nsma = in6_getnsma(inet_pton(AF_INET6, eps[0].ip6.address))
971 d = inet_ntop(AF_INET6, nsma)
972 pkt_nd = (Ether(dst=in6_getnsmac(nsma),
973 src=self.pg0.remote_mac) /
974 IPv6(dst=d, src=eps[0].ip6.address) /
975 ICMPv6ND_NS(tgt=epgs[0].bvi_ip6.address) /
976 ICMPv6NDOptSrcLLAddr(lladdr=self.pg0.remote_mac))
977 self.send_and_expect(self.pg0, [pkt_nd], self.pg0)
980 # broadcast packets are flooded
982 pkt_bcast = (Ether(dst="ff:ff:ff:ff:ff:ff",
983 src=self.pg0.remote_mac) /
984 IP(src=eps[0].ip4.address, dst="232.1.1.1") /
985 UDP(sport=1234, dport=1234) /
988 self.vapi.cli("clear trace")
989 self.pg0.add_stream(pkt_bcast)
991 self.pg_enable_capture(self.pg_interfaces)
994 rxd = eps[1].itf.get_capture(1)
995 self.assertEqual(rxd[0][Ether].dst, pkt_bcast[Ether].dst)
996 rxd = epgs[0].uplink.get_capture(1)
997 self.assertEqual(rxd[0][Ether].dst, pkt_bcast[Ether].dst)
1000 # packets to non-local L3 destinations dropped
1002 pkt_intra_epg_220_ip4 = (Ether(src=self.pg0.remote_mac,
1003 dst=str(self.router_mac)) /
1004 IP(src=eps[0].ip4.address,
1006 UDP(sport=1234, dport=1234) /
1008 pkt_inter_epg_222_ip4 = (Ether(src=self.pg0.remote_mac,
1009 dst=str(self.router_mac)) /
1010 IP(src=eps[0].ip4.address,
1012 UDP(sport=1234, dport=1234) /
1015 self.send_and_assert_no_replies(self.pg0,
1016 pkt_intra_epg_220_ip4 * NUM_PKTS)
1018 pkt_inter_epg_222_ip6 = (Ether(src=self.pg0.remote_mac,
1019 dst=str(self.router_mac)) /
1020 IPv6(src=eps[0].ip6.address,
1021 dst="2001:10::99") /
1022 UDP(sport=1234, dport=1234) /
1024 self.send_and_assert_no_replies(self.pg0,
1025 pkt_inter_epg_222_ip6 * NUM_PKTS)
1028 # Add the subnet routes
1031 self, rd0, "10.0.0.0", 24,
1032 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1034 self, rd0, "10.0.1.0", 24,
1035 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1037 self, rd0, "10.0.2.0", 24,
1038 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1040 self, rd0, "2001:10::1", 64,
1041 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1043 self, rd0, "2001:10:1::1", 64,
1044 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1046 self, rd0, "2001:10:2::1", 64,
1047 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1048 s41.add_vpp_config()
1049 s42.add_vpp_config()
1050 s43.add_vpp_config()
1051 s61.add_vpp_config()
1052 s62.add_vpp_config()
1053 s63.add_vpp_config()
1055 self.send_and_expect_bridged(eps[0].itf,
1056 pkt_intra_epg_220_ip4 * NUM_PKTS,
1058 self.send_and_expect_bridged(eps[0].itf,
1059 pkt_inter_epg_222_ip4 * NUM_PKTS,
1061 self.send_and_expect_bridged6(eps[0].itf,
1062 pkt_inter_epg_222_ip6 * NUM_PKTS,
1065 self.logger.info(self.vapi.cli("sh ip fib 11.0.0.2"))
1066 self.logger.info(self.vapi.cli("sh gbp endpoint-group"))
1067 self.logger.info(self.vapi.cli("sh gbp endpoint"))
1068 self.logger.info(self.vapi.cli("sh gbp recirc"))
1069 self.logger.info(self.vapi.cli("sh int"))
1070 self.logger.info(self.vapi.cli("sh int addr"))
1071 self.logger.info(self.vapi.cli("sh int feat loop6"))
1072 self.logger.info(self.vapi.cli("sh vlib graph ip4-gbp-src-classify"))
1073 self.logger.info(self.vapi.cli("sh int feat loop3"))
1074 self.logger.info(self.vapi.cli("sh int feat pg0"))
1077 # Packet destined to unknown unicast is sent on the epg uplink ...
1079 pkt_intra_epg_220_to_uplink = (Ether(src=self.pg0.remote_mac,
1080 dst="00:00:00:33:44:55") /
1081 IP(src=eps[0].ip4.address,
1083 UDP(sport=1234, dport=1234) /
1086 self.send_and_expect_bridged(eps[0].itf,
1087 pkt_intra_epg_220_to_uplink * NUM_PKTS,
1089 # ... and nowhere else
1090 self.pg1.get_capture(0, timeout=0.1)
1091 self.pg1.assert_nothing_captured(remark="Flood onto other VMS")
1093 pkt_intra_epg_221_to_uplink = (Ether(src=self.pg2.remote_mac,
1094 dst="00:00:00:33:44:66") /
1095 IP(src=eps[0].ip4.address,
1097 UDP(sport=1234, dport=1234) /
1100 self.send_and_expect_bridged(eps[2].itf,
1101 pkt_intra_epg_221_to_uplink * NUM_PKTS,
1105 # Packets from the uplink are forwarded in the absence of a contract
1107 pkt_intra_epg_220_from_uplink = (Ether(src="00:00:00:33:44:55",
1108 dst=self.pg0.remote_mac) /
1109 IP(src=eps[0].ip4.address,
1111 UDP(sport=1234, dport=1234) /
1114 self.send_and_expect_bridged(self.pg4,
1115 pkt_intra_epg_220_from_uplink * NUM_PKTS,
1119 # in the absence of policy, endpoints in the same EPG
1122 pkt_intra_epg = (Ether(src=self.pg0.remote_mac,
1123 dst=self.pg1.remote_mac) /
1124 IP(src=eps[0].ip4.address,
1125 dst=eps[1].ip4.address) /
1126 UDP(sport=1234, dport=1234) /
1129 self.send_and_expect_bridged(self.pg0,
1130 pkt_intra_epg * NUM_PKTS,
1134 # in the absence of policy, endpoints in the different EPG
1135 # cannot communicate
1137 pkt_inter_epg_220_to_221 = (Ether(src=self.pg0.remote_mac,
1138 dst=self.pg2.remote_mac) /
1139 IP(src=eps[0].ip4.address,
1140 dst=eps[2].ip4.address) /
1141 UDP(sport=1234, dport=1234) /
1143 pkt_inter_epg_221_to_220 = (Ether(src=self.pg2.remote_mac,
1144 dst=self.pg0.remote_mac) /
1145 IP(src=eps[2].ip4.address,
1146 dst=eps[0].ip4.address) /
1147 UDP(sport=1234, dport=1234) /
1149 pkt_inter_epg_220_to_222 = (Ether(src=self.pg0.remote_mac,
1150 dst=str(self.router_mac)) /
1151 IP(src=eps[0].ip4.address,
1152 dst=eps[3].ip4.address) /
1153 UDP(sport=1234, dport=1234) /
1156 self.send_and_assert_no_replies(eps[0].itf,
1157 pkt_inter_epg_220_to_221 * NUM_PKTS)
1158 self.send_and_assert_no_replies(eps[0].itf,
1159 pkt_inter_epg_220_to_222 * NUM_PKTS)
1162 # A uni-directional contract from EPG 220 -> 221
1164 acl = VppGbpAcl(self)
1165 rule = acl.create_rule(permit_deny=1, proto=17)
1166 rule2 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
1167 acl_index = acl.add_vpp_config([rule, rule2])
1168 c1 = VppGbpContract(
1169 self, epgs[0].sclass, epgs[1].sclass, acl_index,
1170 [VppGbpContractRule(
1171 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1174 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1176 [ETH_P_IP, ETH_P_IPV6])
1179 self.send_and_expect_bridged(eps[0].itf,
1180 pkt_inter_epg_220_to_221 * NUM_PKTS,
1182 self.send_and_assert_no_replies(eps[0].itf,
1183 pkt_inter_epg_220_to_222 * NUM_PKTS)
1186 # contract for the return direction
1188 c2 = VppGbpContract(
1189 self, epgs[1].sclass, epgs[0].sclass, acl_index,
1190 [VppGbpContractRule(
1191 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1194 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1196 [ETH_P_IP, ETH_P_IPV6])
1199 self.send_and_expect_bridged(eps[0].itf,
1200 pkt_inter_epg_220_to_221 * NUM_PKTS,
1202 self.send_and_expect_bridged(eps[2].itf,
1203 pkt_inter_epg_221_to_220 * NUM_PKTS,
1206 ds = c2.get_drop_stats()
1207 self.assertEqual(ds['packets'], 0)
1208 ps = c2.get_permit_stats()
1209 self.assertEqual(ps['packets'], NUM_PKTS)
1212 # the contract does not allow non-IP
1214 pkt_non_ip_inter_epg_220_to_221 = (Ether(src=self.pg0.remote_mac,
1215 dst=self.pg2.remote_mac) /
1217 self.send_and_assert_no_replies(eps[0].itf,
1218 pkt_non_ip_inter_epg_220_to_221 * 17)
1221 # check that inter group is still disabled for the groups
1222 # not in the contract.
1224 self.send_and_assert_no_replies(eps[0].itf,
1225 pkt_inter_epg_220_to_222 * NUM_PKTS)
1228 # A uni-directional contract from EPG 220 -> 222 'L3 routed'
1230 c3 = VppGbpContract(
1231 self, epgs[0].sclass, epgs[2].sclass, acl_index,
1232 [VppGbpContractRule(
1233 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1236 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1238 [ETH_P_IP, ETH_P_IPV6])
1241 self.logger.info(self.vapi.cli("sh gbp contract"))
1243 self.send_and_expect_routed(eps[0].itf,
1244 pkt_inter_epg_220_to_222 * NUM_PKTS,
1246 str(self.router_mac))
1249 # remove both contracts, traffic stops in both directions
1251 c2.remove_vpp_config()
1252 c1.remove_vpp_config()
1253 c3.remove_vpp_config()
1254 acl.remove_vpp_config()
1256 self.send_and_assert_no_replies(eps[2].itf,
1257 pkt_inter_epg_221_to_220 * NUM_PKTS)
1258 self.send_and_assert_no_replies(eps[0].itf,
1259 pkt_inter_epg_220_to_221 * NUM_PKTS)
1260 self.send_and_expect_bridged(eps[0].itf,
1261 pkt_intra_epg * NUM_PKTS,
1265 # EPs to the outside world
1268 # in the EP's RD an external subnet via the NAT EPG's recirc
1270 self, rd0, "0.0.0.0", 0,
1271 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1272 sw_if_index=recirc_nat.recirc.sw_if_index,
1273 sclass=epg_nat.sclass)
1275 self, rd0, "11.0.0.0", 8,
1276 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1277 sw_if_index=recirc_nat.recirc.sw_if_index,
1278 sclass=epg_nat.sclass)
1279 se16 = VppGbpSubnet(
1281 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1282 sw_if_index=recirc_nat.recirc.sw_if_index,
1283 sclass=epg_nat.sclass)
1284 # in the NAT RD an external subnet via the NAT EPG's uplink
1286 self, rd20, "0.0.0.0", 0,
1287 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1288 sw_if_index=epg_nat.uplink.sw_if_index,
1289 sclass=epg_nat.sclass)
1290 se36 = VppGbpSubnet(
1291 self, rd20, "::", 0,
1292 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1293 sw_if_index=epg_nat.uplink.sw_if_index,
1294 sclass=epg_nat.sclass)
1296 self, rd20, "11.0.0.0", 8,
1297 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1298 sw_if_index=epg_nat.uplink.sw_if_index,
1299 sclass=epg_nat.sclass)
1300 se1.add_vpp_config()
1301 se2.add_vpp_config()
1302 se16.add_vpp_config()
1303 se3.add_vpp_config()
1304 se36.add_vpp_config()
1305 se4.add_vpp_config()
1307 self.logger.info(self.vapi.cli("sh ip fib 0.0.0.0/0"))
1308 self.logger.info(self.vapi.cli("sh ip fib 11.0.0.1"))
1309 self.logger.info(self.vapi.cli("sh ip6 fib ::/0"))
1310 self.logger.info(self.vapi.cli("sh ip6 fib %s" %
1314 # From an EP to an outside address: IN2OUT
1316 pkt_inter_epg_220_to_global = (Ether(src=self.pg0.remote_mac,
1317 dst=str(self.router_mac)) /
1318 IP(src=eps[0].ip4.address,
1320 UDP(sport=1234, dport=1234) /
1324 self.send_and_assert_no_replies(eps[0].itf,
1325 pkt_inter_epg_220_to_global * NUM_PKTS)
1327 acl2 = VppGbpAcl(self)
1328 rule = acl2.create_rule(permit_deny=1, proto=17, sport_from=1234,
1329 sport_to=1234, dport_from=1234, dport_to=1234)
1330 rule2 = acl2.create_rule(is_ipv6=1, permit_deny=1, proto=17,
1331 sport_from=1234, sport_to=1234,
1332 dport_from=1234, dport_to=1234)
1334 acl_index2 = acl2.add_vpp_config([rule, rule2])
1335 c4 = VppGbpContract(
1336 self, epgs[0].sclass, epgs[3].sclass, acl_index2,
1337 [VppGbpContractRule(
1338 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1341 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1343 [ETH_P_IP, ETH_P_IPV6])
1346 self.send_and_expect_natted(eps[0].itf,
1347 pkt_inter_epg_220_to_global * NUM_PKTS,
1349 eps[0].fip4.address)
1351 pkt_inter_epg_220_to_global = (Ether(src=self.pg0.remote_mac,
1352 dst=str(self.router_mac)) /
1353 IPv6(src=eps[0].ip6.address,
1355 UDP(sport=1234, dport=1234) /
1358 self.send_and_expect_natted6(self.pg0,
1359 pkt_inter_epg_220_to_global * NUM_PKTS,
1361 eps[0].fip6.address)
1364 # From a global address to an EP: OUT2IN
1366 pkt_inter_epg_220_from_global = (Ether(src=str(self.router_mac),
1367 dst=self.pg0.remote_mac) /
1368 IP(dst=eps[0].fip4.address,
1370 UDP(sport=1234, dport=1234) /
1373 self.send_and_assert_no_replies(
1374 self.pg7, pkt_inter_epg_220_from_global * NUM_PKTS)
1376 c5 = VppGbpContract(
1377 self, epgs[3].sclass, epgs[0].sclass, acl_index2,
1378 [VppGbpContractRule(
1379 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1382 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1384 [ETH_P_IP, ETH_P_IPV6])
1387 self.send_and_expect_unnatted(self.pg7,
1388 pkt_inter_epg_220_from_global * NUM_PKTS,
1392 pkt_inter_epg_220_from_global = (Ether(src=str(self.router_mac),
1393 dst=self.pg0.remote_mac) /
1394 IPv6(dst=eps[0].fip6.address,
1396 UDP(sport=1234, dport=1234) /
1399 self.send_and_expect_unnatted6(
1401 pkt_inter_epg_220_from_global * NUM_PKTS,
1406 # From a local VM to another local VM using resp. public addresses:
1409 pkt_intra_epg_220_global = (Ether(src=self.pg0.remote_mac,
1410 dst=str(self.router_mac)) /
1411 IP(src=eps[0].ip4.address,
1412 dst=eps[1].fip4.address) /
1413 UDP(sport=1234, dport=1234) /
1416 self.send_and_expect_double_natted(eps[0].itf,
1417 pkt_intra_epg_220_global * NUM_PKTS,
1419 eps[0].fip4.address,
1422 pkt_intra_epg_220_global = (Ether(src=self.pg0.remote_mac,
1423 dst=str(self.router_mac)) /
1424 IPv6(src=eps[0].ip6.address,
1425 dst=eps[1].fip6.address) /
1426 UDP(sport=1234, dport=1234) /
1429 self.send_and_expect_double_natted6(
1431 pkt_intra_epg_220_global * NUM_PKTS,
1433 eps[0].fip6.address,
1440 # del static mappings for each EP from the 10/8 to 11/8 network
1441 flags = self.config_flags.NAT_IS_ADDR_ONLY
1442 self.vapi.nat44_add_del_static_mapping(
1444 local_ip_address=ep.ip4.bytes,
1445 external_ip_address=ep.fip4.bytes,
1446 external_sw_if_index=0xFFFFFFFF,
1449 self.vapi.nat66_add_del_static_mapping(
1450 local_ip_address=ep.ip6.bytes,
1451 external_ip_address=ep.fip6.bytes,
1455 # IP config on the BVI interfaces
1456 if epg != epgs[0] and epg != epgs[3]:
1457 flags = self.config_flags.NAT_IS_INSIDE
1458 self.vapi.nat44_interface_add_del_feature(
1459 sw_if_index=epg.bvi.sw_if_index,
1462 self.vapi.nat66_add_del_interface(
1463 is_add=0, flags=flags,
1464 sw_if_index=epg.bvi.sw_if_index)
1466 for recirc in recircs:
1467 self.vapi.nat44_interface_add_del_feature(
1468 sw_if_index=recirc.recirc.sw_if_index,
1470 self.vapi.nat66_add_del_interface(
1472 sw_if_index=recirc.recirc.sw_if_index)
1474 def wait_for_ep_timeout(self, sw_if_index=None, ip=None, mac=None,
1475 n_tries=100, s_time=1):
1477 if not find_gbp_endpoint(self, sw_if_index, ip, mac):
1479 n_tries = n_tries - 1
1481 self.assertFalse(find_gbp_endpoint(self, sw_if_index, ip, mac))
1484 def test_gbp_learn_l2(self):
1485 """ GBP L2 Endpoint Learning """
1487 self.vapi.cli("clear errors")
1489 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
1490 learnt = [{'mac': '00:00:11:11:11:01',
1492 'ip6': '2001:10::2'},
1493 {'mac': '00:00:11:11:11:02',
1495 'ip6': '2001:10::3'}]
1500 gt4 = VppIpTable(self, 1)
1501 gt4.add_vpp_config()
1502 gt6 = VppIpTable(self, 1, is_ip6=True)
1503 gt6.add_vpp_config()
1505 rd1 = VppGbpRouteDomain(self, 1, gt4, gt6)
1506 rd1.add_vpp_config()
1509 # Pg2 hosts the vxlan tunnel, hosts on pg2 to act as TEPs
1510 # Pg3 hosts the IP4 UU-flood VXLAN tunnel
1511 # Pg4 hosts the IP6 UU-flood VXLAN tunnel
1513 self.pg2.config_ip4()
1514 self.pg2.resolve_arp()
1515 self.pg2.generate_remote_hosts(4)
1516 self.pg2.configure_ipv4_neighbors()
1517 self.pg3.config_ip4()
1518 self.pg3.resolve_arp()
1519 self.pg4.config_ip4()
1520 self.pg4.resolve_arp()
1523 # Add a mcast destination VXLAN-GBP tunnel for B&M traffic
1525 tun_bm = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
1528 tun_bm.add_vpp_config()
1531 # a GBP bridge domain with a BVI and a UU-flood interface
1533 bd1 = VppBridgeDomain(self, 1)
1534 bd1.add_vpp_config()
1535 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0, self.pg3, tun_bm)
1536 gbd1.add_vpp_config()
1538 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1539 self.logger.info(self.vapi.cli("sh gbp bridge"))
1541 # ... and has a /32 applied
1542 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
1543 ip_addr.add_vpp_config()
1546 # The Endpoint-group in which we are learning endpoints
1548 epg_220 = VppGbpEndpointGroup(self, 220, 112, rd1, gbd1,
1552 VppGbpEndpointRetention(2))
1553 epg_220.add_vpp_config()
1554 epg_330 = VppGbpEndpointGroup(self, 330, 113, rd1, gbd1,
1558 VppGbpEndpointRetention(2))
1559 epg_330.add_vpp_config()
1562 # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
1565 vx_tun_l2_1 = VppGbpVxlanTunnel(
1566 self, 99, bd1.bd_id,
1567 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L2,
1569 vx_tun_l2_1.add_vpp_config()
1572 # A static endpoint that the learnt endpoints are trying to
1575 ep = VppGbpEndpoint(self, self.pg0,
1577 "10.0.0.127", "11.0.0.127",
1578 "2001:10::1", "3001::1")
1581 self.assertTrue(find_route(self, ep.ip4.address, 32, table_id=1))
1583 # a packet with an sclass from an unknown EPG
1584 p = (Ether(src=self.pg2.remote_mac,
1585 dst=self.pg2.local_mac) /
1586 IP(src=self.pg2.remote_hosts[0].ip4,
1587 dst=self.pg2.local_ip4) /
1588 UDP(sport=1234, dport=48879) /
1589 VXLAN(vni=99, gpid=88, flags=0x88) /
1590 Ether(src=learnt[0]["mac"], dst=ep.mac) /
1591 IP(src=learnt[0]["ip"], dst=ep.ip4.address) /
1592 UDP(sport=1234, dport=1234) /
1595 self.send_and_assert_no_replies(self.pg2, p)
1597 self.logger.info(self.vapi.cli("sh error"))
1598 # self.assert_packet_counter_equal(
1599 # '/err/gbp-policy-port/drop-no-contract', 1)
1602 # we should not have learnt a new tunnel endpoint, since
1603 # the EPG was not learnt.
1605 self.assertEqual(INDEX_INVALID,
1606 find_vxlan_gbp_tunnel(self,
1608 self.pg2.remote_hosts[0].ip4,
1611 # epg is not learnt, because the EPG is unknown
1612 self.assertEqual(len(self.vapi.gbp_endpoint_dump()), 1)
1615 # Learn new EPs from IP packets
1617 for ii, l in enumerate(learnt):
1618 # a packet with an sclass from a known EPG
1619 # arriving on an unknown TEP
1620 p = (Ether(src=self.pg2.remote_mac,
1621 dst=self.pg2.local_mac) /
1622 IP(src=self.pg2.remote_hosts[1].ip4,
1623 dst=self.pg2.local_ip4) /
1624 UDP(sport=1234, dport=48879) /
1625 VXLAN(vni=99, gpid=112, flags=0x88) /
1626 Ether(src=l['mac'], dst=ep.mac) /
1627 IP(src=l['ip'], dst=ep.ip4.address) /
1628 UDP(sport=1234, dport=1234) /
1631 rx = self.send_and_expect(self.pg2, [p], self.pg0)
1634 tep1_sw_if_index = find_vxlan_gbp_tunnel(
1637 self.pg2.remote_hosts[1].ip4,
1639 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
1642 # the EP is learnt via the learnt TEP
1643 # both from its MAC and its IP
1645 self.assertTrue(find_gbp_endpoint(self,
1646 vx_tun_l2_1.sw_if_index,
1648 self.assertTrue(find_gbp_endpoint(self,
1649 vx_tun_l2_1.sw_if_index,
1652 # self.assert_packet_counter_equal(
1653 # '/err/gbp-policy-port/allow-intra-sclass', 2)
1655 self.logger.info(self.vapi.cli("show gbp endpoint"))
1656 self.logger.info(self.vapi.cli("show gbp vxlan"))
1657 self.logger.info(self.vapi.cli("show ip mfib"))
1660 # If we sleep for the threshold time, the learnt endpoints should
1664 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1668 # Learn new EPs from GARP packets received on the BD's mcast tunnel
1670 for ii, l in enumerate(learnt):
1671 # a packet with an sclass from a known EPG
1672 # arriving on an unknown TEP
1673 p = (Ether(src=self.pg2.remote_mac,
1674 dst=self.pg2.local_mac) /
1675 IP(src=self.pg2.remote_hosts[1].ip4,
1677 UDP(sport=1234, dport=48879) /
1678 VXLAN(vni=88, gpid=112, flags=0x88) /
1679 Ether(src=l['mac'], dst="ff:ff:ff:ff:ff:ff") /
1681 psrc=l['ip'], pdst=l['ip'],
1682 hwsrc=l['mac'], hwdst="ff:ff:ff:ff:ff:ff"))
1684 rx = self.send_and_expect(self.pg4, [p], self.pg0)
1687 tep1_sw_if_index = find_vxlan_gbp_tunnel(
1690 self.pg2.remote_hosts[1].ip4,
1692 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
1695 # the EP is learnt via the learnt TEP
1696 # both from its MAC and its IP
1698 self.assertTrue(find_gbp_endpoint(self,
1699 vx_tun_l2_1.sw_if_index,
1701 self.assertTrue(find_gbp_endpoint(self,
1702 vx_tun_l2_1.sw_if_index,
1706 # wait for the learnt endpoints to age out
1709 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1713 # Learn new EPs from L2 packets
1715 for ii, l in enumerate(learnt):
1716 # a packet with an sclass from a known EPG
1717 # arriving on an unknown TEP
1718 p = (Ether(src=self.pg2.remote_mac,
1719 dst=self.pg2.local_mac) /
1720 IP(src=self.pg2.remote_hosts[1].ip4,
1721 dst=self.pg2.local_ip4) /
1722 UDP(sport=1234, dport=48879) /
1723 VXLAN(vni=99, gpid=112, flags=0x88) /
1724 Ether(src=l['mac'], dst=ep.mac) /
1727 rx = self.send_and_expect(self.pg2, [p], self.pg0)
1730 tep1_sw_if_index = find_vxlan_gbp_tunnel(
1733 self.pg2.remote_hosts[1].ip4,
1735 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
1738 # the EP is learnt via the learnt TEP
1739 # both from its MAC and its IP
1741 self.assertTrue(find_gbp_endpoint(self,
1742 vx_tun_l2_1.sw_if_index,
1745 self.logger.info(self.vapi.cli("show gbp endpoint"))
1746 self.logger.info(self.vapi.cli("show gbp vxlan"))
1747 self.logger.info(self.vapi.cli("show vxlan-gbp tunnel"))
1750 # wait for the learnt endpoints to age out
1753 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1757 # repeat. the do not learn bit is set so the EPs are not learnt
1760 # a packet with an sclass from a known EPG
1761 p = (Ether(src=self.pg2.remote_mac,
1762 dst=self.pg2.local_mac) /
1763 IP(src=self.pg2.remote_hosts[1].ip4,
1764 dst=self.pg2.local_ip4) /
1765 UDP(sport=1234, dport=48879) /
1766 VXLAN(vni=99, gpid=112, flags=0x88, gpflags="D") /
1767 Ether(src=l['mac'], dst=ep.mac) /
1768 IP(src=l['ip'], dst=ep.ip4.address) /
1769 UDP(sport=1234, dport=1234) /
1772 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
1775 self.assertFalse(find_gbp_endpoint(self,
1776 vx_tun_l2_1.sw_if_index,
1783 # a packet with an sclass from a known EPG
1784 p = (Ether(src=self.pg2.remote_mac,
1785 dst=self.pg2.local_mac) /
1786 IP(src=self.pg2.remote_hosts[1].ip4,
1787 dst=self.pg2.local_ip4) /
1788 UDP(sport=1234, dport=48879) /
1789 VXLAN(vni=99, gpid=112, flags=0x88) /
1790 Ether(src=l['mac'], dst=ep.mac) /
1791 IP(src=l['ip'], dst=ep.ip4.address) /
1792 UDP(sport=1234, dport=1234) /
1795 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
1797 self.assertTrue(find_gbp_endpoint(self,
1798 vx_tun_l2_1.sw_if_index,
1802 # Static EP replies to dynamics
1804 self.logger.info(self.vapi.cli("sh l2fib bd_id 1"))
1806 p = (Ether(src=ep.mac, dst=l['mac']) /
1807 IP(dst=l['ip'], src=ep.ip4.address) /
1808 UDP(sport=1234, dport=1234) /
1811 rxs = self.send_and_expect(self.pg0, p * 17, self.pg2)
1814 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
1815 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
1816 self.assertEqual(rx[UDP].dport, 48879)
1817 # the UDP source port is a random value for hashing
1818 self.assertEqual(rx[VXLAN].gpid, 112)
1819 self.assertEqual(rx[VXLAN].vni, 99)
1820 self.assertTrue(rx[VXLAN].flags.G)
1821 self.assertTrue(rx[VXLAN].flags.Instance)
1822 self.assertTrue(rx[VXLAN].gpflags.A)
1823 self.assertFalse(rx[VXLAN].gpflags.D)
1826 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1830 # repeat in the other EPG
1831 # there's no contract between 220 and 330, but the A-bit is set
1832 # so the packet is cleared for delivery
1835 # a packet with an sclass from a known EPG
1836 p = (Ether(src=self.pg2.remote_mac,
1837 dst=self.pg2.local_mac) /
1838 IP(src=self.pg2.remote_hosts[1].ip4,
1839 dst=self.pg2.local_ip4) /
1840 UDP(sport=1234, dport=48879) /
1841 VXLAN(vni=99, gpid=113, flags=0x88, gpflags='A') /
1842 Ether(src=l['mac'], dst=ep.mac) /
1843 IP(src=l['ip'], dst=ep.ip4.address) /
1844 UDP(sport=1234, dport=1234) /
1847 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
1849 self.assertTrue(find_gbp_endpoint(self,
1850 vx_tun_l2_1.sw_if_index,
1854 # static EP cannot reach the learnt EPs since there is no contract
1855 # only test 1 EP as the others could timeout
1857 p = (Ether(src=ep.mac, dst=l['mac']) /
1858 IP(dst=learnt[0]['ip'], src=ep.ip4.address) /
1859 UDP(sport=1234, dport=1234) /
1862 self.send_and_assert_no_replies(self.pg0, [p])
1865 # refresh the entries after the check for no replies above
1868 # a packet with an sclass from a known EPG
1869 p = (Ether(src=self.pg2.remote_mac,
1870 dst=self.pg2.local_mac) /
1871 IP(src=self.pg2.remote_hosts[1].ip4,
1872 dst=self.pg2.local_ip4) /
1873 UDP(sport=1234, dport=48879) /
1874 VXLAN(vni=99, gpid=113, flags=0x88, gpflags='A') /
1875 Ether(src=l['mac'], dst=ep.mac) /
1876 IP(src=l['ip'], dst=ep.ip4.address) /
1877 UDP(sport=1234, dport=1234) /
1880 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
1882 self.assertTrue(find_gbp_endpoint(self,
1883 vx_tun_l2_1.sw_if_index,
1887 # Add the contract so they can talk
1889 acl = VppGbpAcl(self)
1890 rule = acl.create_rule(permit_deny=1, proto=17)
1891 rule2 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
1892 acl_index = acl.add_vpp_config([rule, rule2])
1893 c1 = VppGbpContract(
1894 self, epg_220.sclass, epg_330.sclass, acl_index,
1895 [VppGbpContractRule(
1896 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1899 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1901 [ETH_P_IP, ETH_P_IPV6])
1905 p = (Ether(src=ep.mac, dst=l['mac']) /
1906 IP(dst=l['ip'], src=ep.ip4.address) /
1907 UDP(sport=1234, dport=1234) /
1910 self.send_and_expect(self.pg0, [p], self.pg2)
1913 # send UU packets from the local EP
1915 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1916 self.logger.info(self.vapi.cli("sh gbp bridge"))
1917 p_uu = (Ether(src=ep.mac, dst="00:11:11:11:11:11") /
1918 IP(dst="10.0.0.133", src=ep.ip4.address) /
1919 UDP(sport=1234, dport=1234) /
1921 rxs = self.send_and_expect(ep.itf, [p_uu], gbd1.uu_fwd)
1923 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1925 p_bm = (Ether(src=ep.mac, dst="ff:ff:ff:ff:ff:ff") /
1926 IP(dst="10.0.0.133", src=ep.ip4.address) /
1927 UDP(sport=1234, dport=1234) /
1929 rxs = self.send_and_expect_only(ep.itf, [p_bm], tun_bm.mcast_itf)
1932 self.assertEqual(rx[IP].src, self.pg4.local_ip4)
1933 self.assertEqual(rx[IP].dst, "239.1.1.1")
1934 self.assertEqual(rx[UDP].dport, 48879)
1935 # the UDP source port is a random value for hashing
1936 self.assertEqual(rx[VXLAN].gpid, 112)
1937 self.assertEqual(rx[VXLAN].vni, 88)
1938 self.assertTrue(rx[VXLAN].flags.G)
1939 self.assertTrue(rx[VXLAN].flags.Instance)
1940 self.assertFalse(rx[VXLAN].gpflags.A)
1941 self.assertFalse(rx[VXLAN].gpflags.D)
1944 # Check v6 Endpoints
1947 # a packet with an sclass from a known EPG
1948 p = (Ether(src=self.pg2.remote_mac,
1949 dst=self.pg2.local_mac) /
1950 IP(src=self.pg2.remote_hosts[1].ip4,
1951 dst=self.pg2.local_ip4) /
1952 UDP(sport=1234, dport=48879) /
1953 VXLAN(vni=99, gpid=113, flags=0x88, gpflags='A') /
1954 Ether(src=l['mac'], dst=ep.mac) /
1955 IPv6(src=l['ip6'], dst=ep.ip6.address) /
1956 UDP(sport=1234, dport=1234) /
1959 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
1961 self.assertTrue(find_gbp_endpoint(self,
1962 vx_tun_l2_1.sw_if_index,
1966 # L3 Endpoint Learning
1967 # - configured on the bridge's BVI
1974 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1976 self.pg2.unconfig_ip4()
1977 self.pg3.unconfig_ip4()
1978 self.pg4.unconfig_ip4()
1980 self.logger.info(self.vapi.cli("sh int"))
1981 self.logger.info(self.vapi.cli("sh gbp vxlan"))
1983 def test_gbp_contract(self):
1984 """ GBP CONTRACTS """
1989 bd1 = VppBridgeDomain(self, 1, arp_term=0)
1990 bd2 = VppBridgeDomain(self, 2, arp_term=0)
1992 bd1.add_vpp_config()
1993 bd2.add_vpp_config()
1995 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0)
1996 gbd2 = VppGbpBridgeDomain(self, bd2, self.loop1)
1998 gbd1.add_vpp_config()
1999 gbd2.add_vpp_config()
2004 gt4 = VppIpTable(self, 0)
2005 gt4.add_vpp_config()
2006 gt6 = VppIpTable(self, 0, is_ip6=True)
2007 gt6.add_vpp_config()
2009 rd0 = VppGbpRouteDomain(self, 0, gt4, gt6, None, None)
2011 rd0.add_vpp_config()
2014 # 3 EPGs, 2 of which share a BD.
2016 epgs = [VppGbpEndpointGroup(self, 220, 1220, rd0, gbd1,
2018 "10.0.0.128", "2001:10::128"),
2019 VppGbpEndpointGroup(self, 221, 1221, rd0, gbd1,
2021 "10.0.1.128", "2001:10:1::128"),
2022 VppGbpEndpointGroup(self, 222, 1222, rd0, gbd2,
2024 "10.0.2.128", "2001:10:2::128")]
2026 # 4 end-points, 2 in the same subnet, 3 in the same BD
2028 eps = [VppGbpEndpoint(self, self.pg0,
2030 "10.0.0.1", "11.0.0.1",
2031 "2001:10::1", "3001::1"),
2032 VppGbpEndpoint(self, self.pg1,
2034 "10.0.0.2", "11.0.0.2",
2035 "2001:10::2", "3001::2"),
2036 VppGbpEndpoint(self, self.pg2,
2038 "10.0.1.1", "11.0.0.3",
2039 "2001:10:1::1", "3001::3"),
2040 VppGbpEndpoint(self, self.pg3,
2042 "10.0.2.1", "11.0.0.4",
2043 "2001:10:2::1", "3001::4")]
2046 # Config related to each of the EPGs
2049 # IP config on the BVI interfaces
2051 VppIpInterfaceBind(self, epg.bvi, epg.rd.t4).add_vpp_config()
2052 VppIpInterfaceBind(self, epg.bvi, epg.rd.t6).add_vpp_config()
2053 self.vapi.sw_interface_set_mac_address(
2054 epg.bvi.sw_if_index,
2055 self.router_mac.packed)
2057 if_ip4 = VppIpInterfaceAddress(self, epg.bvi, epg.bvi_ip4, 32)
2058 if_ip6 = VppIpInterfaceAddress(self, epg.bvi, epg.bvi_ip6, 128)
2059 if_ip4.add_vpp_config()
2060 if_ip6.add_vpp_config()
2062 # add the BD ARP termination entry for BVI IP
2063 epg.bd_arp_ip4 = VppBridgeDomainArpEntry(self, epg.bd.bd,
2064 str(self.router_mac),
2066 epg.bd_arp_ip4.add_vpp_config()
2069 epg.add_vpp_config()
2077 self.logger.info(self.vapi.cli("show gbp endpoint"))
2078 self.logger.info(self.vapi.cli("show interface"))
2079 self.logger.info(self.vapi.cli("show br"))
2082 # Intra epg allowed without contract
2084 pkt_intra_epg_220_to_220 = (Ether(src=self.pg0.remote_mac,
2085 dst=self.pg1.remote_mac) /
2086 IP(src=eps[0].ip4.address,
2087 dst=eps[1].ip4.address) /
2088 UDP(sport=1234, dport=1234) /
2091 self.send_and_expect_bridged(self.pg0,
2092 pkt_intra_epg_220_to_220 * 65,
2096 # Inter epg denied without contract
2098 pkt_inter_epg_220_to_221 = (Ether(src=self.pg0.remote_mac,
2099 dst=self.pg2.remote_mac) /
2100 IP(src=eps[0].ip4.address,
2101 dst=eps[2].ip4.address) /
2102 UDP(sport=1234, dport=1234) /
2105 self.send_and_assert_no_replies(self.pg0, pkt_inter_epg_220_to_221)
2108 # A uni-directional contract from EPG 220 -> 221
2110 acl = VppGbpAcl(self)
2111 rule = acl.create_rule(permit_deny=1, proto=17)
2112 rule2 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
2113 acl_index = acl.add_vpp_config([rule, rule2])
2114 c1 = VppGbpContract(
2115 self, epgs[0].sclass, epgs[1].sclass, acl_index,
2116 [VppGbpContractRule(
2117 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2120 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2122 [ETH_P_IP, ETH_P_IPV6])
2125 self.send_and_expect_bridged(eps[0].itf,
2126 pkt_inter_epg_220_to_221 * 65,
2129 pkt_inter_epg_220_to_222 = (Ether(src=self.pg0.remote_mac,
2130 dst=str(self.router_mac)) /
2131 IP(src=eps[0].ip4.address,
2132 dst=eps[3].ip4.address) /
2133 UDP(sport=1234, dport=1234) /
2135 self.send_and_assert_no_replies(eps[0].itf,
2136 pkt_inter_epg_220_to_222 * 65)
2139 # contract for the return direction
2141 c2 = VppGbpContract(
2142 self, epgs[1].sclass, epgs[0].sclass, acl_index,
2143 [VppGbpContractRule(
2144 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2147 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2149 [ETH_P_IP, ETH_P_IPV6])
2152 self.send_and_expect_bridged(eps[0].itf,
2153 pkt_inter_epg_220_to_221 * 65,
2155 pkt_inter_epg_221_to_220 = (Ether(src=self.pg2.remote_mac,
2156 dst=self.pg0.remote_mac) /
2157 IP(src=eps[2].ip4.address,
2158 dst=eps[0].ip4.address) /
2159 UDP(sport=1234, dport=1234) /
2161 self.send_and_expect_bridged(eps[2].itf,
2162 pkt_inter_epg_221_to_220 * 65,
2166 # contract between 220 and 222 uni-direction
2168 c3 = VppGbpContract(
2169 self, epgs[0].sclass, epgs[2].sclass, acl_index,
2170 [VppGbpContractRule(
2171 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2174 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2176 [ETH_P_IP, ETH_P_IPV6])
2179 self.send_and_expect(eps[0].itf,
2180 pkt_inter_epg_220_to_222 * 65,
2183 c3.remove_vpp_config()
2184 c1.remove_vpp_config()
2185 c2.remove_vpp_config()
2186 acl.remove_vpp_config()
2188 def test_gbp_bd_flags(self):
2189 """ GBP BD FLAGS """
2194 gt4 = VppIpTable(self, 1)
2195 gt4.add_vpp_config()
2196 gt6 = VppIpTable(self, 1, is_ip6=True)
2197 gt6.add_vpp_config()
2199 rd1 = VppGbpRouteDomain(self, 1, gt4, gt6)
2200 rd1.add_vpp_config()
2203 # Pg3 hosts the IP4 UU-flood VXLAN tunnel
2204 # Pg4 hosts the IP6 UU-flood VXLAN tunnel
2206 self.pg3.config_ip4()
2207 self.pg3.resolve_arp()
2208 self.pg4.config_ip4()
2209 self.pg4.resolve_arp()
2212 # Add a mcast destination VXLAN-GBP tunnel for B&M traffic
2214 tun_bm = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
2217 tun_bm.add_vpp_config()
2220 # a GBP bridge domain with a BVI and a UU-flood interface
2222 bd1 = VppBridgeDomain(self, 1)
2223 bd1.add_vpp_config()
2225 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0, self.pg3, tun_bm,
2226 uu_drop=True, bm_drop=True)
2227 gbd1.add_vpp_config()
2229 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2230 self.logger.info(self.vapi.cli("sh gbp bridge"))
2232 # ... and has a /32 applied
2233 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2234 ip_addr.add_vpp_config()
2237 # The Endpoint-group
2239 epg_220 = VppGbpEndpointGroup(self, 220, 112, rd1, gbd1,
2243 VppGbpEndpointRetention(2))
2244 epg_220.add_vpp_config()
2246 ep = VppGbpEndpoint(self, self.pg0,
2248 "10.0.0.127", "11.0.0.127",
2249 "2001:10::1", "3001::1")
2252 # send UU/BM packet from the local EP with UU drop and BM drop enabled
2255 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2256 self.logger.info(self.vapi.cli("sh gbp bridge"))
2257 p_uu = (Ether(src=ep.mac, dst="00:11:11:11:11:11") /
2258 IP(dst="10.0.0.133", src=ep.ip4.address) /
2259 UDP(sport=1234, dport=1234) /
2261 self.send_and_assert_no_replies(ep.itf, [p_uu])
2263 p_bm = (Ether(src=ep.mac, dst="ff:ff:ff:ff:ff:ff") /
2264 IP(dst="10.0.0.133", src=ep.ip4.address) /
2265 UDP(sport=1234, dport=1234) /
2267 self.send_and_assert_no_replies(ep.itf, [p_bm])
2269 self.pg3.unconfig_ip4()
2270 self.pg4.unconfig_ip4()
2272 self.logger.info(self.vapi.cli("sh int"))
2274 def test_gbp_learn_vlan_l2(self):
2275 """ GBP L2 Endpoint w/ VLANs"""
2277 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
2278 learnt = [{'mac': '00:00:11:11:11:01',
2280 'ip6': '2001:10::2'},
2281 {'mac': '00:00:11:11:11:02',
2283 'ip6': '2001:10::3'}]
2288 gt4 = VppIpTable(self, 1)
2289 gt4.add_vpp_config()
2290 gt6 = VppIpTable(self, 1, is_ip6=True)
2291 gt6.add_vpp_config()
2293 rd1 = VppGbpRouteDomain(self, 1, gt4, gt6)
2294 rd1.add_vpp_config()
2297 # Pg2 hosts the vxlan tunnel, hosts on pg2 to act as TEPs
2299 self.pg2.config_ip4()
2300 self.pg2.resolve_arp()
2301 self.pg2.generate_remote_hosts(4)
2302 self.pg2.configure_ipv4_neighbors()
2303 self.pg3.config_ip4()
2304 self.pg3.resolve_arp()
2307 # The EP will be on a vlan sub-interface
2309 vlan_11 = VppDot1QSubint(self, self.pg0, 11)
2311 self.vapi.l2_interface_vlan_tag_rewrite(
2312 sw_if_index=vlan_11.sw_if_index, vtr_op=L2_VTR_OP.L2_POP_1,
2315 bd_uu_fwd = VppVxlanGbpTunnel(self, self.pg3.local_ip4,
2316 self.pg3.remote_ip4, 116)
2317 bd_uu_fwd.add_vpp_config()
2320 # a GBP bridge domain with a BVI and a UU-flood interface
2321 # The BD is marked as do not learn, so no endpoints are ever
2322 # learnt in this BD.
2324 bd1 = VppBridgeDomain(self, 1)
2325 bd1.add_vpp_config()
2326 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0, bd_uu_fwd,
2328 gbd1.add_vpp_config()
2330 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2331 self.logger.info(self.vapi.cli("sh gbp bridge"))
2333 # ... and has a /32 applied
2334 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2335 ip_addr.add_vpp_config()
2338 # The Endpoint-group in which we are learning endpoints
2340 epg_220 = VppGbpEndpointGroup(self, 220, 441, rd1, gbd1,
2344 VppGbpEndpointRetention(2))
2345 epg_220.add_vpp_config()
2348 # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
2351 vx_tun_l2_1 = VppGbpVxlanTunnel(
2352 self, 99, bd1.bd_id,
2353 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L2,
2355 vx_tun_l2_1.add_vpp_config()
2358 # A static endpoint that the learnt endpoints are trying to
2361 ep = VppGbpEndpoint(self, vlan_11,
2363 "10.0.0.127", "11.0.0.127",
2364 "2001:10::1", "3001::1")
2367 self.assertTrue(find_route(self, ep.ip4.address, 32, table_id=1))
2370 # Send to the static EP
2372 for ii, l in enumerate(learnt):
2373 # a packet with an sclass from a known EPG
2374 # arriving on an unknown TEP
2375 p = (Ether(src=self.pg2.remote_mac,
2376 dst=self.pg2.local_mac) /
2377 IP(src=self.pg2.remote_hosts[1].ip4,
2378 dst=self.pg2.local_ip4) /
2379 UDP(sport=1234, dport=48879) /
2380 VXLAN(vni=99, gpid=441, flags=0x88) /
2381 Ether(src=l['mac'], dst=ep.mac) /
2382 IP(src=l['ip'], dst=ep.ip4.address) /
2383 UDP(sport=1234, dport=1234) /
2386 rxs = self.send_and_expect(self.pg2, [p], self.pg0)
2389 # packet to EP has the EP's vlan tag
2392 self.assertEqual(rx[Dot1Q].vlan, 11)
2395 # the EP is not learnt since the BD setting prevents it
2398 self.assertFalse(find_gbp_endpoint(self,
2399 vx_tun_l2_1.sw_if_index,
2401 self.assertEqual(INDEX_INVALID,
2402 find_vxlan_gbp_tunnel(
2405 self.pg2.remote_hosts[1].ip4,
2408 self.assertEqual(len(self.vapi.gbp_endpoint_dump()), 1)
2412 # we didn't learn the remotes so they are sent to the UU-fwd
2415 p = (Ether(src=ep.mac, dst=l['mac']) /
2417 IP(dst=l['ip'], src=ep.ip4.address) /
2418 UDP(sport=1234, dport=1234) /
2421 rxs = self.send_and_expect(self.pg0, p * 17, self.pg3)
2424 self.assertEqual(rx[IP].src, self.pg3.local_ip4)
2425 self.assertEqual(rx[IP].dst, self.pg3.remote_ip4)
2426 self.assertEqual(rx[UDP].dport, 48879)
2427 # the UDP source port is a random value for hashing
2428 self.assertEqual(rx[VXLAN].gpid, 441)
2429 self.assertEqual(rx[VXLAN].vni, 116)
2430 self.assertTrue(rx[VXLAN].flags.G)
2431 self.assertTrue(rx[VXLAN].flags.Instance)
2432 self.assertFalse(rx[VXLAN].gpflags.A)
2433 self.assertFalse(rx[VXLAN].gpflags.D)
2435 self.pg2.unconfig_ip4()
2436 self.pg3.unconfig_ip4()
2438 def test_gbp_learn_l3(self):
2439 """ GBP L3 Endpoint Learning """
2441 self.vapi.cli("set logging class gbp level debug")
2443 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
2444 routed_dst_mac = "00:0c:0c:0c:0c:0c"
2445 routed_src_mac = "00:22:bd:f8:19:ff"
2447 learnt = [{'mac': '00:00:11:11:11:02',
2449 'ip6': '2001:10::2'},
2450 {'mac': '00:00:11:11:11:03',
2452 'ip6': '2001:10::3'}]
2457 t4 = VppIpTable(self, 1)
2459 t6 = VppIpTable(self, 1, True)
2462 tun_ip4_uu = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
2463 self.pg4.remote_ip4, 114)
2464 tun_ip6_uu = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
2465 self.pg4.remote_ip4, 116)
2466 tun_ip4_uu.add_vpp_config()
2467 tun_ip6_uu.add_vpp_config()
2469 rd1 = VppGbpRouteDomain(self, 2, t4, t6, tun_ip4_uu, tun_ip6_uu)
2470 rd1.add_vpp_config()
2472 self.loop0.set_mac(self.router_mac)
2475 # Bind the BVI to the RD
2477 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
2478 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
2481 # Pg2 hosts the vxlan tunnel
2482 # hosts on pg2 to act as TEPs
2486 self.pg2.config_ip4()
2487 self.pg2.resolve_arp()
2488 self.pg2.generate_remote_hosts(4)
2489 self.pg2.configure_ipv4_neighbors()
2490 self.pg3.config_ip4()
2491 self.pg3.resolve_arp()
2492 self.pg4.config_ip4()
2493 self.pg4.resolve_arp()
2496 # a GBP bridge domain with a BVI and a UU-flood interface
2498 bd1 = VppBridgeDomain(self, 1)
2499 bd1.add_vpp_config()
2500 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0, self.pg3)
2501 gbd1.add_vpp_config()
2503 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2504 self.logger.info(self.vapi.cli("sh gbp bridge"))
2505 self.logger.info(self.vapi.cli("sh gbp route"))
2507 # ... and has a /32 and /128 applied
2508 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2509 ip4_addr.add_vpp_config()
2510 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 128)
2511 ip6_addr.add_vpp_config()
2514 # The Endpoint-group in which we are learning endpoints
2516 epg_220 = VppGbpEndpointGroup(self, 220, 441, rd1, gbd1,
2520 VppGbpEndpointRetention(2))
2521 epg_220.add_vpp_config()
2524 # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
2527 vx_tun_l3 = VppGbpVxlanTunnel(
2528 self, 101, rd1.rd_id,
2529 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
2531 vx_tun_l3.add_vpp_config()
2534 # A static endpoint that the learnt endpoints are trying to
2537 ep = VppGbpEndpoint(self, self.pg0,
2539 "10.0.0.127", "11.0.0.127",
2540 "2001:10::1", "3001::1")
2544 # learn some remote IPv4 EPs
2546 for ii, l in enumerate(learnt):
2547 # a packet with an sclass from a known EPG
2548 # arriving on an unknown TEP
2549 p = (Ether(src=self.pg2.remote_mac,
2550 dst=self.pg2.local_mac) /
2551 IP(src=self.pg2.remote_hosts[1].ip4,
2552 dst=self.pg2.local_ip4) /
2553 UDP(sport=1234, dport=48879) /
2554 VXLAN(vni=101, gpid=441, flags=0x88) /
2555 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2556 IP(src=l['ip'], dst=ep.ip4.address) /
2557 UDP(sport=1234, dport=1234) /
2560 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2563 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2566 self.pg2.remote_hosts[1].ip4,
2568 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2570 # endpoint learnt via the parent GBP-vxlan interface
2571 self.assertTrue(find_gbp_endpoint(self,
2572 vx_tun_l3._sw_if_index,
2576 # Static IPv4 EP replies to learnt
2579 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2580 IP(dst=l['ip'], src=ep.ip4.address) /
2581 UDP(sport=1234, dport=1234) /
2584 rxs = self.send_and_expect(self.pg0, p * 1, self.pg2)
2587 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2588 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2589 self.assertEqual(rx[UDP].dport, 48879)
2590 # the UDP source port is a random value for hashing
2591 self.assertEqual(rx[VXLAN].gpid, 441)
2592 self.assertEqual(rx[VXLAN].vni, 101)
2593 self.assertTrue(rx[VXLAN].flags.G)
2594 self.assertTrue(rx[VXLAN].flags.Instance)
2595 self.assertTrue(rx[VXLAN].gpflags.A)
2596 self.assertFalse(rx[VXLAN].gpflags.D)
2598 inner = rx[VXLAN].payload
2600 self.assertEqual(inner[Ether].src, routed_src_mac)
2601 self.assertEqual(inner[Ether].dst, routed_dst_mac)
2602 self.assertEqual(inner[IP].src, ep.ip4.address)
2603 self.assertEqual(inner[IP].dst, l['ip'])
2606 self.assertFalse(find_gbp_endpoint(self,
2611 # learn some remote IPv6 EPs
2613 for ii, l in enumerate(learnt):
2614 # a packet with an sclass from a known EPG
2615 # arriving on an unknown TEP
2616 p = (Ether(src=self.pg2.remote_mac,
2617 dst=self.pg2.local_mac) /
2618 IP(src=self.pg2.remote_hosts[1].ip4,
2619 dst=self.pg2.local_ip4) /
2620 UDP(sport=1234, dport=48879) /
2621 VXLAN(vni=101, gpid=441, flags=0x88) /
2622 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2623 IPv6(src=l['ip6'], dst=ep.ip6.address) /
2624 UDP(sport=1234, dport=1234) /
2627 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2630 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2633 self.pg2.remote_hosts[1].ip4,
2635 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2637 self.logger.info(self.vapi.cli("show gbp bridge"))
2638 self.logger.info(self.vapi.cli("show vxlan-gbp tunnel"))
2639 self.logger.info(self.vapi.cli("show gbp vxlan"))
2640 self.logger.info(self.vapi.cli("show int addr"))
2642 # endpoint learnt via the TEP
2643 self.assertTrue(find_gbp_endpoint(self, ip=l['ip6']))
2645 self.logger.info(self.vapi.cli("show gbp endpoint"))
2646 self.logger.info(self.vapi.cli("show ip fib index 1 %s" % l['ip']))
2649 # Static EP replies to learnt
2652 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2653 IPv6(dst=l['ip6'], src=ep.ip6.address) /
2654 UDP(sport=1234, dport=1234) /
2657 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
2660 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2661 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2662 self.assertEqual(rx[UDP].dport, 48879)
2663 # the UDP source port is a random value for hashing
2664 self.assertEqual(rx[VXLAN].gpid, 441)
2665 self.assertEqual(rx[VXLAN].vni, 101)
2666 self.assertTrue(rx[VXLAN].flags.G)
2667 self.assertTrue(rx[VXLAN].flags.Instance)
2668 self.assertTrue(rx[VXLAN].gpflags.A)
2669 self.assertFalse(rx[VXLAN].gpflags.D)
2671 inner = rx[VXLAN].payload
2673 self.assertEqual(inner[Ether].src, routed_src_mac)
2674 self.assertEqual(inner[Ether].dst, routed_dst_mac)
2675 self.assertEqual(inner[IPv6].src, ep.ip6.address)
2676 self.assertEqual(inner[IPv6].dst, l['ip6'])
2678 self.logger.info(self.vapi.cli("sh gbp endpoint"))
2680 self.wait_for_ep_timeout(ip=l['ip'])
2683 # Static sends to unknown EP with no route
2685 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2686 IP(dst="10.0.0.99", src=ep.ip4.address) /
2687 UDP(sport=1234, dport=1234) /
2690 self.send_and_assert_no_replies(self.pg0, [p])
2693 # Add a route to static EP's v4 and v6 subnet
2694 # packets should be sent on the v4/v6 uu=fwd interface resp.
2696 se_10_24 = VppGbpSubnet(
2697 self, rd1, "10.0.0.0", 24,
2698 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT)
2699 se_10_24.add_vpp_config()
2701 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2702 IP(dst="10.0.0.99", src=ep.ip4.address) /
2703 UDP(sport=1234, dport=1234) /
2706 rxs = self.send_and_expect(self.pg0, [p], self.pg4)
2708 self.assertEqual(rx[IP].src, self.pg4.local_ip4)
2709 self.assertEqual(rx[IP].dst, self.pg4.remote_ip4)
2710 self.assertEqual(rx[UDP].dport, 48879)
2711 # the UDP source port is a random value for hashing
2712 self.assertEqual(rx[VXLAN].gpid, 441)
2713 self.assertEqual(rx[VXLAN].vni, 114)
2714 self.assertTrue(rx[VXLAN].flags.G)
2715 self.assertTrue(rx[VXLAN].flags.Instance)
2716 # policy is not applied to packets sent to the uu-fwd interfaces
2717 self.assertFalse(rx[VXLAN].gpflags.A)
2718 self.assertFalse(rx[VXLAN].gpflags.D)
2721 # learn some remote IPv4 EPs
2723 for ii, l in enumerate(learnt):
2724 # a packet with an sclass from a known EPG
2725 # arriving on an unknown TEP
2726 p = (Ether(src=self.pg2.remote_mac,
2727 dst=self.pg2.local_mac) /
2728 IP(src=self.pg2.remote_hosts[2].ip4,
2729 dst=self.pg2.local_ip4) /
2730 UDP(sport=1234, dport=48879) /
2731 VXLAN(vni=101, gpid=441, flags=0x88) /
2732 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2733 IP(src=l['ip'], dst=ep.ip4.address) /
2734 UDP(sport=1234, dport=1234) /
2737 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2740 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2743 self.pg2.remote_hosts[2].ip4,
2745 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2747 # endpoint learnt via the parent GBP-vxlan interface
2748 self.assertTrue(find_gbp_endpoint(self,
2749 vx_tun_l3._sw_if_index,
2753 # Add a remote endpoint from the API
2755 rep_88 = VppGbpEndpoint(self, vx_tun_l3,
2757 "10.0.0.88", "11.0.0.88",
2758 "2001:10::88", "3001::88",
2759 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
2761 self.pg2.remote_hosts[1].ip4,
2763 rep_88.add_vpp_config()
2766 # Add a remote endpoint from the API that matches an existing one
2768 rep_2 = VppGbpEndpoint(self, vx_tun_l3,
2770 learnt[0]['ip'], "11.0.0.101",
2771 learnt[0]['ip6'], "3001::101",
2772 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
2774 self.pg2.remote_hosts[1].ip4,
2776 rep_2.add_vpp_config()
2779 # Add a route to the learned EP's v4 subnet
2780 # packets should be send on the v4/v6 uu=fwd interface resp.
2782 se_10_1_24 = VppGbpSubnet(
2783 self, rd1, "10.0.1.0", 24,
2784 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT)
2785 se_10_1_24.add_vpp_config()
2787 self.logger.info(self.vapi.cli("show gbp endpoint"))
2789 ips = ["10.0.0.88", learnt[0]['ip']]
2791 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2792 IP(dst=ip, src=ep.ip4.address) /
2793 UDP(sport=1234, dport=1234) /
2796 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
2799 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2800 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2801 self.assertEqual(rx[UDP].dport, 48879)
2802 # the UDP source port is a random value for hashing
2803 self.assertEqual(rx[VXLAN].gpid, 441)
2804 self.assertEqual(rx[VXLAN].vni, 101)
2805 self.assertTrue(rx[VXLAN].flags.G)
2806 self.assertTrue(rx[VXLAN].flags.Instance)
2807 self.assertTrue(rx[VXLAN].gpflags.A)
2808 self.assertFalse(rx[VXLAN].gpflags.D)
2810 inner = rx[VXLAN].payload
2812 self.assertEqual(inner[Ether].src, routed_src_mac)
2813 self.assertEqual(inner[Ether].dst, routed_dst_mac)
2814 self.assertEqual(inner[IP].src, ep.ip4.address)
2815 self.assertEqual(inner[IP].dst, ip)
2818 # remove the API remote EPs, only API sourced is gone, the DP
2819 # learnt one remains
2821 rep_88.remove_vpp_config()
2822 rep_2.remove_vpp_config()
2824 self.assertTrue(find_gbp_endpoint(self, ip=rep_2.ip4.address))
2826 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2827 IP(src=ep.ip4.address, dst=rep_2.ip4.address) /
2828 UDP(sport=1234, dport=1234) /
2830 rxs = self.send_and_expect(self.pg0, [p], self.pg2)
2832 self.assertFalse(find_gbp_endpoint(self, ip=rep_88.ip4.address))
2834 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2835 IP(src=ep.ip4.address, dst=rep_88.ip4.address) /
2836 UDP(sport=1234, dport=1234) /
2838 rxs = self.send_and_expect(self.pg0, [p], self.pg4)
2841 # to appease the testcase we cannot have the registered EP still
2842 # present (because it's DP learnt) when the TC ends so wait until
2845 self.wait_for_ep_timeout(ip=rep_88.ip4.address)
2846 self.wait_for_ep_timeout(ip=rep_2.ip4.address)
2849 # shutdown with learnt endpoint present
2851 p = (Ether(src=self.pg2.remote_mac,
2852 dst=self.pg2.local_mac) /
2853 IP(src=self.pg2.remote_hosts[1].ip4,
2854 dst=self.pg2.local_ip4) /
2855 UDP(sport=1234, dport=48879) /
2856 VXLAN(vni=101, gpid=441, flags=0x88) /
2857 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2858 IP(src=learnt[1]['ip'], dst=ep.ip4.address) /
2859 UDP(sport=1234, dport=1234) /
2862 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2864 # endpoint learnt via the parent GBP-vxlan interface
2865 self.assertTrue(find_gbp_endpoint(self,
2866 vx_tun_l3._sw_if_index,
2871 # remote endpoint becomes local
2873 self.pg2.unconfig_ip4()
2874 self.pg3.unconfig_ip4()
2875 self.pg4.unconfig_ip4()
2877 def test_gbp_redirect(self):
2878 """ GBP Endpoint Redirect """
2880 self.vapi.cli("set logging class gbp level debug")
2882 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
2883 routed_dst_mac = "00:0c:0c:0c:0c:0c"
2884 routed_src_mac = "00:22:bd:f8:19:ff"
2886 learnt = [{'mac': '00:00:11:11:11:02',
2888 'ip6': '2001:10::2'},
2889 {'mac': '00:00:11:11:11:03',
2891 'ip6': '2001:10::3'}]
2896 t4 = VppIpTable(self, 1)
2898 t6 = VppIpTable(self, 1, True)
2901 rd1 = VppGbpRouteDomain(self, 2, t4, t6)
2902 rd1.add_vpp_config()
2904 self.loop0.set_mac(self.router_mac)
2907 # Bind the BVI to the RD
2909 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
2910 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
2913 # Pg7 hosts a BD's UU-fwd
2915 self.pg7.config_ip4()
2916 self.pg7.resolve_arp()
2919 # a GBP bridge domains for the EPs
2921 bd1 = VppBridgeDomain(self, 1)
2922 bd1.add_vpp_config()
2923 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0)
2924 gbd1.add_vpp_config()
2926 bd2 = VppBridgeDomain(self, 2)
2927 bd2.add_vpp_config()
2928 gbd2 = VppGbpBridgeDomain(self, bd2, self.loop1)
2929 gbd2.add_vpp_config()
2931 # ... and has a /32 and /128 applied
2932 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2933 ip4_addr.add_vpp_config()
2934 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 128)
2935 ip6_addr.add_vpp_config()
2936 ip4_addr = VppIpInterfaceAddress(self, gbd2.bvi, "10.0.1.128", 32)
2937 ip4_addr.add_vpp_config()
2938 ip6_addr = VppIpInterfaceAddress(self, gbd2.bvi, "2001:11::128", 128)
2939 ip6_addr.add_vpp_config()
2942 # The Endpoint-groups in which we are learning endpoints
2944 epg_220 = VppGbpEndpointGroup(self, 220, 440, rd1, gbd1,
2948 VppGbpEndpointRetention(2))
2949 epg_220.add_vpp_config()
2950 epg_221 = VppGbpEndpointGroup(self, 221, 441, rd1, gbd2,
2954 VppGbpEndpointRetention(2))
2955 epg_221.add_vpp_config()
2956 epg_222 = VppGbpEndpointGroup(self, 222, 442, rd1, gbd1,
2960 VppGbpEndpointRetention(2))
2961 epg_222.add_vpp_config()
2964 # a GBP bridge domains for the SEPs
2966 bd_uu1 = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
2967 self.pg7.remote_ip4, 116)
2968 bd_uu1.add_vpp_config()
2969 bd_uu2 = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
2970 self.pg7.remote_ip4, 117)
2971 bd_uu2.add_vpp_config()
2973 bd3 = VppBridgeDomain(self, 3)
2974 bd3.add_vpp_config()
2975 gbd3 = VppGbpBridgeDomain(self, bd3, self.loop2, bd_uu1, learn=False)
2976 gbd3.add_vpp_config()
2977 bd4 = VppBridgeDomain(self, 4)
2978 bd4.add_vpp_config()
2979 gbd4 = VppGbpBridgeDomain(self, bd4, self.loop3, bd_uu2, learn=False)
2980 gbd4.add_vpp_config()
2983 # EPGs in which the service endpoints exist
2985 epg_320 = VppGbpEndpointGroup(self, 320, 550, rd1, gbd3,
2989 VppGbpEndpointRetention(2))
2990 epg_320.add_vpp_config()
2991 epg_321 = VppGbpEndpointGroup(self, 321, 551, rd1, gbd4,
2995 VppGbpEndpointRetention(2))
2996 epg_321.add_vpp_config()
2999 # three local endpoints
3001 ep1 = VppGbpEndpoint(self, self.pg0,
3003 "10.0.0.1", "11.0.0.1",
3004 "2001:10::1", "3001:10::1")
3005 ep1.add_vpp_config()
3006 ep2 = VppGbpEndpoint(self, self.pg1,
3008 "10.0.1.1", "11.0.1.1",
3009 "2001:11::1", "3001:11::1")
3010 ep2.add_vpp_config()
3011 ep3 = VppGbpEndpoint(self, self.pg2,
3013 "10.0.2.2", "11.0.2.2",
3014 "2001:12::1", "3001:12::1")
3015 ep3.add_vpp_config()
3020 sep1 = VppGbpEndpoint(self, self.pg3,
3022 "12.0.0.1", "13.0.0.1",
3023 "4001:10::1", "5001:10::1")
3024 sep1.add_vpp_config()
3025 sep2 = VppGbpEndpoint(self, self.pg4,
3027 "12.0.0.2", "13.0.0.2",
3028 "4001:10::2", "5001:10::2")
3029 sep2.add_vpp_config()
3030 sep3 = VppGbpEndpoint(self, self.pg5,
3032 "12.0.1.1", "13.0.1.1",
3033 "4001:11::1", "5001:11::1")
3034 sep3.add_vpp_config()
3035 # this EP is not installed immediately
3036 sep4 = VppGbpEndpoint(self, self.pg6,
3038 "12.0.1.2", "13.0.1.2",
3039 "4001:11::2", "5001:11::2")
3042 # an L2 switch packet between local EPs in different EPGs
3043 # different dest ports on each so the are LB hashed differently
3045 p4 = [(Ether(src=ep1.mac, dst=ep3.mac) /
3046 IP(src=ep1.ip4.address, dst=ep3.ip4.address) /
3047 UDP(sport=1234, dport=1234) /
3049 (Ether(src=ep3.mac, dst=ep1.mac) /
3050 IP(src=ep3.ip4.address, dst=ep1.ip4.address) /
3051 UDP(sport=1234, dport=1234) /
3053 p6 = [(Ether(src=ep1.mac, dst=ep3.mac) /
3054 IPv6(src=ep1.ip6.address, dst=ep3.ip6.address) /
3055 UDP(sport=1234, dport=1234) /
3057 (Ether(src=ep3.mac, dst=ep1.mac) /
3058 IPv6(src=ep3.ip6.address, dst=ep1.ip6.address) /
3059 UDP(sport=1234, dport=1230) /
3062 # should be dropped since no contract yet
3063 self.send_and_assert_no_replies(self.pg0, [p4[0]])
3064 self.send_and_assert_no_replies(self.pg0, [p6[0]])
3067 # Add a contract with a rule to load-balance redirect via SEP1 and SEP2
3068 # one of the next-hops is via an EP that is not known
3070 acl = VppGbpAcl(self)
3071 rule4 = acl.create_rule(permit_deny=1, proto=17)
3072 rule6 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
3073 acl_index = acl.add_vpp_config([rule4, rule6])
3076 # test the src-ip hash mode
3078 c1 = VppGbpContract(
3079 self, epg_220.sclass, epg_222.sclass, acl_index,
3080 [VppGbpContractRule(
3081 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3082 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3083 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3084 sep1.ip4, sep1.epg.rd),
3085 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3086 sep2.ip4, sep2.epg.rd)]),
3088 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3089 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3090 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3091 sep3.ip6, sep3.epg.rd),
3092 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3093 sep4.ip6, sep4.epg.rd)])],
3094 [ETH_P_IP, ETH_P_IPV6])
3097 c2 = VppGbpContract(
3098 self, epg_222.sclass, epg_220.sclass, acl_index,
3099 [VppGbpContractRule(
3100 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3101 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3102 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3103 sep1.ip4, sep1.epg.rd),
3104 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3105 sep2.ip4, sep2.epg.rd)]),
3107 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3108 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3109 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3110 sep3.ip6, sep3.epg.rd),
3111 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3112 sep4.ip6, sep4.epg.rd)])],
3113 [ETH_P_IP, ETH_P_IPV6])
3117 # send again with the contract preset, now packets arrive
3118 # at SEP1 or SEP2 depending on the hashing
3120 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3123 self.assertEqual(rx[Ether].src, routed_src_mac)
3124 self.assertEqual(rx[Ether].dst, sep1.mac)
3125 self.assertEqual(rx[IP].src, ep1.ip4.address)
3126 self.assertEqual(rx[IP].dst, ep3.ip4.address)
3128 rxs = self.send_and_expect(self.pg2, p4[1] * 17, sep2.itf)
3131 self.assertEqual(rx[Ether].src, routed_src_mac)
3132 self.assertEqual(rx[Ether].dst, sep2.mac)
3133 self.assertEqual(rx[IP].src, ep3.ip4.address)
3134 self.assertEqual(rx[IP].dst, ep1.ip4.address)
3136 rxs = self.send_and_expect(self.pg0, p6[0] * 17, self.pg7)
3139 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3140 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3141 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3142 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
3143 self.assertEqual(rx[VXLAN].vni, 117)
3144 self.assertTrue(rx[VXLAN].flags.G)
3145 self.assertTrue(rx[VXLAN].flags.Instance)
3146 # redirect policy has been applied
3147 self.assertTrue(rx[VXLAN].gpflags.A)
3148 self.assertFalse(rx[VXLAN].gpflags.D)
3150 inner = rx[VXLAN].payload
3152 self.assertEqual(inner[Ether].src, routed_src_mac)
3153 self.assertEqual(inner[Ether].dst, sep4.mac)
3154 self.assertEqual(inner[IPv6].src, ep1.ip6.address)
3155 self.assertEqual(inner[IPv6].dst, ep3.ip6.address)
3157 rxs = self.send_and_expect(self.pg2, p6[1] * 17, sep3.itf)
3160 self.assertEqual(rx[Ether].src, routed_src_mac)
3161 self.assertEqual(rx[Ether].dst, sep3.mac)
3162 self.assertEqual(rx[IPv6].src, ep3.ip6.address)
3163 self.assertEqual(rx[IPv6].dst, ep1.ip6.address)
3166 # programme the unknown EP
3168 sep4.add_vpp_config()
3170 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep4.itf)
3173 self.assertEqual(rx[Ether].src, routed_src_mac)
3174 self.assertEqual(rx[Ether].dst, sep4.mac)
3175 self.assertEqual(rx[IPv6].src, ep1.ip6.address)
3176 self.assertEqual(rx[IPv6].dst, ep3.ip6.address)
3179 # and revert back to unprogrammed
3181 sep4.remove_vpp_config()
3183 rxs = self.send_and_expect(self.pg0, p6[0] * 17, self.pg7)
3186 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3187 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3188 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3189 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
3190 self.assertEqual(rx[VXLAN].vni, 117)
3191 self.assertTrue(rx[VXLAN].flags.G)
3192 self.assertTrue(rx[VXLAN].flags.Instance)
3193 # redirect policy has been applied
3194 self.assertTrue(rx[VXLAN].gpflags.A)
3195 self.assertFalse(rx[VXLAN].gpflags.D)
3197 inner = rx[VXLAN].payload
3199 self.assertEqual(inner[Ether].src, routed_src_mac)
3200 self.assertEqual(inner[Ether].dst, sep4.mac)
3201 self.assertEqual(inner[IPv6].src, ep1.ip6.address)
3202 self.assertEqual(inner[IPv6].dst, ep3.ip6.address)
3204 c1.remove_vpp_config()
3205 c2.remove_vpp_config()
3208 # test the symmetric hash mode
3210 c1 = VppGbpContract(
3211 self, epg_220.sclass, epg_222.sclass, acl_index,
3212 [VppGbpContractRule(
3213 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3214 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3215 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3216 sep1.ip4, sep1.epg.rd),
3217 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3218 sep2.ip4, sep2.epg.rd)]),
3220 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3221 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3222 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3223 sep3.ip6, sep3.epg.rd),
3224 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3225 sep4.ip6, sep4.epg.rd)])],
3226 [ETH_P_IP, ETH_P_IPV6])
3229 c2 = VppGbpContract(
3230 self, epg_222.sclass, epg_220.sclass, acl_index,
3231 [VppGbpContractRule(
3232 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3233 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3234 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3235 sep1.ip4, sep1.epg.rd),
3236 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3237 sep2.ip4, sep2.epg.rd)]),
3239 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3240 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3241 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3242 sep3.ip6, sep3.epg.rd),
3243 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3244 sep4.ip6, sep4.epg.rd)])],
3245 [ETH_P_IP, ETH_P_IPV6])
3249 # send again with the contract preset, now packets arrive
3250 # at SEP1 for both directions
3252 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3255 self.assertEqual(rx[Ether].src, routed_src_mac)
3256 self.assertEqual(rx[Ether].dst, sep1.mac)
3257 self.assertEqual(rx[IP].src, ep1.ip4.address)
3258 self.assertEqual(rx[IP].dst, ep3.ip4.address)
3260 rxs = self.send_and_expect(self.pg2, p4[1] * 17, sep1.itf)
3263 self.assertEqual(rx[Ether].src, routed_src_mac)
3264 self.assertEqual(rx[Ether].dst, sep1.mac)
3265 self.assertEqual(rx[IP].src, ep3.ip4.address)
3266 self.assertEqual(rx[IP].dst, ep1.ip4.address)
3269 # programme the unknown EP for the L3 tests
3271 sep4.add_vpp_config()
3274 # an L3 switch packet between local EPs in different EPGs
3275 # different dest ports on each so the are LB hashed differently
3277 p4 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3278 IP(src=ep1.ip4.address, dst=ep2.ip4.address) /
3279 UDP(sport=1234, dport=1234) /
3281 (Ether(src=ep2.mac, dst=str(self.router_mac)) /
3282 IP(src=ep2.ip4.address, dst=ep1.ip4.address) /
3283 UDP(sport=1234, dport=1234) /
3285 p6 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3286 IPv6(src=ep1.ip6.address, dst=ep2.ip6.address) /
3287 UDP(sport=1234, dport=1234) /
3289 (Ether(src=ep2.mac, dst=str(self.router_mac)) /
3290 IPv6(src=ep2.ip6.address, dst=ep1.ip6.address) /
3291 UDP(sport=1234, dport=1234) /
3294 c3 = VppGbpContract(
3295 self, epg_220.sclass, epg_221.sclass, acl_index,
3296 [VppGbpContractRule(
3297 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3298 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3299 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3300 sep1.ip4, sep1.epg.rd),
3301 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3302 sep2.ip4, sep2.epg.rd)]),
3304 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3305 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3306 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3307 sep3.ip6, sep3.epg.rd),
3308 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3309 sep4.ip6, sep4.epg.rd)])],
3310 [ETH_P_IP, ETH_P_IPV6])
3313 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3316 self.assertEqual(rx[Ether].src, routed_src_mac)
3317 self.assertEqual(rx[Ether].dst, sep1.mac)
3318 self.assertEqual(rx[IP].src, ep1.ip4.address)
3319 self.assertEqual(rx[IP].dst, ep2.ip4.address)
3322 # learn a remote EP in EPG 221
3324 vx_tun_l3 = VppGbpVxlanTunnel(
3325 self, 444, rd1.rd_id,
3326 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
3328 vx_tun_l3.add_vpp_config()
3330 c4 = VppGbpContract(
3331 self, epg_221.sclass, epg_220.sclass, acl_index,
3332 [VppGbpContractRule(
3333 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3336 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3338 [ETH_P_IP, ETH_P_IPV6])
3341 p = (Ether(src=self.pg7.remote_mac,
3342 dst=self.pg7.local_mac) /
3343 IP(src=self.pg7.remote_ip4,
3344 dst=self.pg7.local_ip4) /
3345 UDP(sport=1234, dport=48879) /
3346 VXLAN(vni=444, gpid=441, flags=0x88) /
3347 Ether(src="00:22:22:22:22:33", dst=str(self.router_mac)) /
3348 IP(src="10.0.0.88", dst=ep1.ip4.address) /
3349 UDP(sport=1234, dport=1234) /
3352 rx = self.send_and_expect(self.pg7, [p], self.pg0)
3354 # endpoint learnt via the parent GBP-vxlan interface
3355 self.assertTrue(find_gbp_endpoint(self,
3356 vx_tun_l3._sw_if_index,
3359 p = (Ether(src=self.pg7.remote_mac,
3360 dst=self.pg7.local_mac) /
3361 IP(src=self.pg7.remote_ip4,
3362 dst=self.pg7.local_ip4) /
3363 UDP(sport=1234, dport=48879) /
3364 VXLAN(vni=444, gpid=441, flags=0x88) /
3365 Ether(src="00:22:22:22:22:33", dst=str(self.router_mac)) /
3366 IPv6(src="2001:10::88", dst=ep1.ip6.address) /
3367 UDP(sport=1234, dport=1234) /
3370 rx = self.send_and_expect(self.pg7, [p], self.pg0)
3372 # endpoint learnt via the parent GBP-vxlan interface
3373 self.assertTrue(find_gbp_endpoint(self,
3374 vx_tun_l3._sw_if_index,
3378 # L3 switch from local to remote EP
3380 p4 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3381 IP(src=ep1.ip4.address, dst="10.0.0.88") /
3382 UDP(sport=1234, dport=1234) /
3384 p6 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3385 IPv6(src=ep1.ip6.address, dst="2001:10::88") /
3386 UDP(sport=1234, dport=1234) /
3389 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3392 self.assertEqual(rx[Ether].src, routed_src_mac)
3393 self.assertEqual(rx[Ether].dst, sep1.mac)
3394 self.assertEqual(rx[IP].src, ep1.ip4.address)
3395 self.assertEqual(rx[IP].dst, "10.0.0.88")
3397 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep4.itf)
3400 self.assertEqual(rx[Ether].src, routed_src_mac)
3401 self.assertEqual(rx[Ether].dst, sep4.mac)
3402 self.assertEqual(rx[IPv6].src, ep1.ip6.address)
3403 self.assertEqual(rx[IPv6].dst, "2001:10::88")
3406 # test the dst-ip hash mode
3408 c5 = VppGbpContract(
3409 self, epg_220.sclass, epg_221.sclass, acl_index,
3410 [VppGbpContractRule(
3411 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3412 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
3413 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3414 sep1.ip4, sep1.epg.rd),
3415 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3416 sep2.ip4, sep2.epg.rd)]),
3418 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3419 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
3420 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3421 sep3.ip6, sep3.epg.rd),
3422 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3423 sep4.ip6, sep4.epg.rd)])],
3424 [ETH_P_IP, ETH_P_IPV6])
3427 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3430 self.assertEqual(rx[Ether].src, routed_src_mac)
3431 self.assertEqual(rx[Ether].dst, sep1.mac)
3432 self.assertEqual(rx[IP].src, ep1.ip4.address)
3433 self.assertEqual(rx[IP].dst, "10.0.0.88")
3435 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep3.itf)
3438 self.assertEqual(rx[Ether].src, routed_src_mac)
3439 self.assertEqual(rx[Ether].dst, sep3.mac)
3440 self.assertEqual(rx[IPv6].src, ep1.ip6.address)
3441 self.assertEqual(rx[IPv6].dst, "2001:10::88")
3446 self.pg7.unconfig_ip4()
3448 def test_gbp_l3_out(self):
3451 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
3452 self.vapi.cli("set logging class gbp level debug")
3454 routed_dst_mac = "00:0c:0c:0c:0c:0c"
3455 routed_src_mac = "00:22:bd:f8:19:ff"
3460 t4 = VppIpTable(self, 1)
3462 t6 = VppIpTable(self, 1, True)
3465 rd1 = VppGbpRouteDomain(self, 2, t4, t6)
3466 rd1.add_vpp_config()
3468 self.loop0.set_mac(self.router_mac)
3471 # Bind the BVI to the RD
3473 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
3474 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
3477 # Pg7 hosts a BD's BUM
3478 # Pg1 some other l3 interface
3480 self.pg7.config_ip4()
3481 self.pg7.resolve_arp()
3484 # a multicast vxlan-gbp tunnel for broadcast in the BD
3486 tun_bm = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
3489 tun_bm.add_vpp_config()
3492 # a GBP external bridge domains for the EPs
3494 bd1 = VppBridgeDomain(self, 1)
3495 bd1.add_vpp_config()
3496 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0, None, tun_bm)
3497 gbd1.add_vpp_config()
3500 # The Endpoint-groups in which the external endpoints exist
3502 epg_220 = VppGbpEndpointGroup(self, 220, 113, rd1, gbd1,
3506 VppGbpEndpointRetention(2))
3507 epg_220.add_vpp_config()
3509 # the BVIs have the subnets applied ...
3510 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 24)
3511 ip4_addr.add_vpp_config()
3512 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 64)
3513 ip6_addr.add_vpp_config()
3515 # ... which are L3-out subnets
3516 l3o_1 = VppGbpSubnet(
3517 self, rd1, "10.0.0.0", 24,
3518 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3520 l3o_1.add_vpp_config()
3523 # an external interface attached to the outside world and the
3526 vlan_100 = VppDot1QSubint(self, self.pg0, 100)
3528 VppL2Vtr(self, vlan_100, L2_VTR_OP.L2_POP_1).add_vpp_config()
3529 vlan_101 = VppDot1QSubint(self, self.pg0, 101)
3531 VppL2Vtr(self, vlan_101, L2_VTR_OP.L2_POP_1).add_vpp_config()
3533 ext_itf = VppGbpExtItf(self, self.loop0, bd1, rd1)
3534 ext_itf.add_vpp_config()
3537 # an unicast vxlan-gbp for inter-RD traffic
3539 vx_tun_l3 = VppGbpVxlanTunnel(
3540 self, 444, rd1.rd_id,
3541 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
3543 vx_tun_l3.add_vpp_config()
3546 # External Endpoints
3548 eep1 = VppGbpEndpoint(self, vlan_100,
3550 "10.0.0.1", "11.0.0.1",
3551 "2001:10::1", "3001::1",
3552 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
3553 eep1.add_vpp_config()
3554 eep2 = VppGbpEndpoint(self, vlan_101,
3556 "10.0.0.2", "11.0.0.2",
3557 "2001:10::2", "3001::2",
3558 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
3559 eep2.add_vpp_config()
3562 # A remote external endpoint
3564 rep = VppGbpEndpoint(self, vx_tun_l3,
3566 "10.0.0.101", "11.0.0.101",
3567 "2001:10::101", "3001::101",
3568 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
3570 self.pg7.remote_ip4,
3572 rep.add_vpp_config()
3575 # ARP packet from External EPs are accepted and replied to
3577 p_arp = (Ether(src=eep1.mac, dst="ff:ff:ff:ff:ff:ff") /
3580 psrc=eep1.ip4.address, pdst="10.0.0.128",
3581 hwsrc=eep1.mac, hwdst="ff:ff:ff:ff:ff:ff"))
3582 rxs = self.send_and_expect(self.pg0, p_arp * 1, self.pg0)
3585 # packets destined to unknown addresses in the BVI's subnet
3588 p4 = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3590 IP(src="10.0.0.1", dst="10.0.0.88") /
3591 UDP(sport=1234, dport=1234) /
3593 p6 = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3595 IPv6(src="2001:10::1", dst="2001:10::88") /
3596 UDP(sport=1234, dport=1234) /
3599 rxs = self.send_and_expect(self.pg0, p4 * 1, self.pg7)
3602 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3603 # self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3604 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3605 self.assertEqual(rx[IP].dst, "239.1.1.1")
3606 self.assertEqual(rx[VXLAN].vni, 88)
3607 self.assertTrue(rx[VXLAN].flags.G)
3608 self.assertTrue(rx[VXLAN].flags.Instance)
3609 # policy was applied to the original IP packet
3610 self.assertEqual(rx[VXLAN].gpid, 113)
3611 self.assertTrue(rx[VXLAN].gpflags.A)
3612 self.assertFalse(rx[VXLAN].gpflags.D)
3614 inner = rx[VXLAN].payload
3616 self.assertTrue(inner.haslayer(ARP))
3619 # remote to external
3621 p = (Ether(src=self.pg7.remote_mac,
3622 dst=self.pg7.local_mac) /
3623 IP(src=self.pg7.remote_ip4,
3624 dst=self.pg7.local_ip4) /
3625 UDP(sport=1234, dport=48879) /
3626 VXLAN(vni=444, gpid=113, flags=0x88) /
3627 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
3628 IP(src="10.0.0.101", dst="10.0.0.1") /
3629 UDP(sport=1234, dport=1234) /
3632 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
3635 # local EP pings router
3637 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3639 IP(src=eep1.ip4.address, dst="10.0.0.128") /
3640 ICMP(type='echo-request'))
3642 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
3645 self.assertEqual(rx[Ether].src, str(self.router_mac))
3646 self.assertEqual(rx[Ether].dst, eep1.mac)
3647 self.assertEqual(rx[Dot1Q].vlan, 100)
3650 # local EP pings other local EP
3652 p = (Ether(src=eep1.mac, dst=eep2.mac) /
3654 IP(src=eep1.ip4.address, dst=eep2.ip4.address) /
3655 ICMP(type='echo-request'))
3657 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
3660 self.assertEqual(rx[Ether].src, eep1.mac)
3661 self.assertEqual(rx[Ether].dst, eep2.mac)
3662 self.assertEqual(rx[Dot1Q].vlan, 101)
3665 # A subnet reachable through the external EP1
3667 ip_220 = VppIpRoute(self, "10.220.0.0", 24,
3668 [VppRoutePath(eep1.ip4.address,
3669 eep1.epg.bvi.sw_if_index)],
3670 table_id=t4.table_id)
3671 ip_220.add_vpp_config()
3673 l3o_220 = VppGbpSubnet(
3674 self, rd1, "10.220.0.0", 24,
3675 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3677 l3o_220.add_vpp_config()
3680 # A subnet reachable through the external EP2
3682 ip_221 = VppIpRoute(self, "10.221.0.0", 24,
3683 [VppRoutePath(eep2.ip4.address,
3684 eep2.epg.bvi.sw_if_index)],
3685 table_id=t4.table_id)
3686 ip_221.add_vpp_config()
3688 l3o_221 = VppGbpSubnet(
3689 self, rd1, "10.221.0.0", 24,
3690 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3692 l3o_221.add_vpp_config()
3695 # ping between hosts in remote subnets
3696 # dropped without a contract
3698 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3700 IP(src="10.220.0.1", dst="10.221.0.1") /
3701 ICMP(type='echo-request'))
3703 rxs = self.send_and_assert_no_replies(self.pg0, p * 1)
3706 # contract for the external nets to communicate
3708 acl = VppGbpAcl(self)
3709 rule4 = acl.create_rule(permit_deny=1, proto=17)
3710 rule6 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
3711 acl_index = acl.add_vpp_config([rule4, rule6])
3713 c1 = VppGbpContract(
3714 self, 4220, 4221, acl_index,
3715 [VppGbpContractRule(
3716 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3719 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3721 [ETH_P_IP, ETH_P_IPV6])
3725 # Contracts allowing ext-net 200 to talk with external EPs
3727 c2 = VppGbpContract(
3728 self, 4220, 113, acl_index,
3729 [VppGbpContractRule(
3730 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3733 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3735 [ETH_P_IP, ETH_P_IPV6])
3737 c3 = VppGbpContract(
3738 self, 113, 4220, acl_index,
3739 [VppGbpContractRule(
3740 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3743 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3745 [ETH_P_IP, ETH_P_IPV6])
3749 # ping between hosts in remote subnets
3751 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3753 IP(src="10.220.0.1", dst="10.221.0.1") /
3754 UDP(sport=1234, dport=1234) /
3757 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
3760 self.assertEqual(rx[Ether].src, str(self.router_mac))
3761 self.assertEqual(rx[Ether].dst, eep2.mac)
3762 self.assertEqual(rx[Dot1Q].vlan, 101)
3764 # we did not learn these external hosts
3765 self.assertFalse(find_gbp_endpoint(self, ip="10.220.0.1"))
3766 self.assertFalse(find_gbp_endpoint(self, ip="10.221.0.1"))
3769 # from remote external EP to local external EP
3771 p = (Ether(src=self.pg7.remote_mac,
3772 dst=self.pg7.local_mac) /
3773 IP(src=self.pg7.remote_ip4,
3774 dst=self.pg7.local_ip4) /
3775 UDP(sport=1234, dport=48879) /
3776 VXLAN(vni=444, gpid=113, flags=0x88) /
3777 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
3778 IP(src="10.0.0.101", dst="10.220.0.1") /
3779 UDP(sport=1234, dport=1234) /
3782 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
3785 # ping from an external host to the remote external EP
3787 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3789 IP(src="10.220.0.1", dst=rep.ip4.address) /
3790 UDP(sport=1234, dport=1234) /
3793 rxs = self.send_and_expect(self.pg0, p * 1, self.pg7)
3796 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3797 # self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3798 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3799 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
3800 self.assertEqual(rx[VXLAN].vni, 444)
3801 self.assertTrue(rx[VXLAN].flags.G)
3802 self.assertTrue(rx[VXLAN].flags.Instance)
3803 # the sclass of the ext-net the packet came from
3804 self.assertEqual(rx[VXLAN].gpid, 4220)
3805 # policy was applied to the original IP packet
3806 self.assertTrue(rx[VXLAN].gpflags.A)
3807 # since it's an external host the reciever should not learn it
3808 self.assertTrue(rx[VXLAN].gpflags.D)
3809 inner = rx[VXLAN].payload
3810 self.assertEqual(inner[IP].src, "10.220.0.1")
3811 self.assertEqual(inner[IP].dst, rep.ip4.address)
3814 # An external subnet reachable via the remote external EP
3818 # first the VXLAN-GBP tunnel over which it is reached
3820 vx_tun_r = VppVxlanGbpTunnel(
3821 self, self.pg7.local_ip4,
3822 self.pg7.remote_ip4, 445,
3823 mode=(VppEnum.vl_api_vxlan_gbp_api_tunnel_mode_t.
3824 VXLAN_GBP_API_TUNNEL_MODE_L3))
3825 vx_tun_r.add_vpp_config()
3826 VppIpInterfaceBind(self, vx_tun_r, t4).add_vpp_config()
3828 self.logger.info(self.vapi.cli("sh vxlan-gbp tunnel"))
3831 # then the special adj to resolve through on that tunnel
3833 n1 = VppNeighbor(self,
3834 vx_tun_r.sw_if_index,
3835 "00:0c:0c:0c:0c:0c",
3836 self.pg7.remote_ip4)
3840 # the route via the adj above
3842 ip_222 = VppIpRoute(self, "10.222.0.0", 24,
3843 [VppRoutePath(self.pg7.remote_ip4,
3844 vx_tun_r.sw_if_index)],
3845 table_id=t4.table_id)
3846 ip_222.add_vpp_config()
3848 l3o_222 = VppGbpSubnet(
3849 self, rd1, "10.222.0.0", 24,
3850 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3852 l3o_222.add_vpp_config()
3855 # ping between hosts in local and remote external subnets
3856 # dropped without a contract
3858 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3860 IP(src="10.220.0.1", dst="10.222.0.1") /
3861 UDP(sport=1234, dport=1234) /
3864 rxs = self.send_and_assert_no_replies(self.pg0, p * 1)
3867 # Add contracts ext-nets for 220 -> 222
3869 c4 = VppGbpContract(
3870 self, 4220, 4222, acl_index,
3871 [VppGbpContractRule(
3872 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3875 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3877 [ETH_P_IP, ETH_P_IPV6])
3881 # ping from host in local to remote external subnets
3883 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3885 IP(src="10.220.0.1", dst="10.222.0.1") /
3886 UDP(sport=1234, dport=1234) /
3889 rxs = self.send_and_expect(self.pg0, p * 3, self.pg7)
3892 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3893 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3894 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3895 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
3896 self.assertEqual(rx[VXLAN].vni, 445)
3897 self.assertTrue(rx[VXLAN].flags.G)
3898 self.assertTrue(rx[VXLAN].flags.Instance)
3899 # the sclass of the ext-net the packet came from
3900 self.assertEqual(rx[VXLAN].gpid, 4220)
3901 # policy was applied to the original IP packet
3902 self.assertTrue(rx[VXLAN].gpflags.A)
3903 # since it's an external host the reciever should not learn it
3904 self.assertTrue(rx[VXLAN].gpflags.D)
3905 inner = rx[VXLAN].payload
3906 self.assertEqual(inner[Ether].dst, "00:0c:0c:0c:0c:0c")
3907 self.assertEqual(inner[IP].src, "10.220.0.1")
3908 self.assertEqual(inner[IP].dst, "10.222.0.1")
3911 # ping from host in remote to local external subnets
3912 # there's no contract for this, but the A bit is set.
3914 p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
3915 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
3916 UDP(sport=1234, dport=48879) /
3917 VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
3918 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
3919 IP(src="10.222.0.1", dst="10.220.0.1") /
3920 UDP(sport=1234, dport=1234) /
3923 rxs = self.send_and_expect(self.pg7, p * 3, self.pg0)
3924 self.assertFalse(find_gbp_endpoint(self, ip="10.222.0.1"))
3927 # ping from host in remote to remote external subnets
3928 # this is dropped by reflection check.
3930 p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
3931 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
3932 UDP(sport=1234, dport=48879) /
3933 VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
3934 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
3935 IP(src="10.222.0.1", dst="10.222.0.2") /
3936 UDP(sport=1234, dport=1234) /
3939 rxs = self.send_and_assert_no_replies(self.pg7, p * 3)
3944 self.pg7.unconfig_ip4()
3945 vlan_100.set_vtr(L2_VTR_OP.L2_DISABLED)
3948 if __name__ == '__main__':
3949 unittest.main(testRunner=VppTestRunner)