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, FibPathProto, \
22 from vpp_l2 import VppBridgeDomain, VppBridgeDomainPort, \
23 VppBridgeDomainArpEntry, VppL2FibEntry, find_bridge_domain_port, VppL2Vtr
24 from vpp_sub_interface import L2_VTR_OP, VppDot1QSubint
25 from vpp_ip import VppIpAddress, VppIpPrefix
26 from vpp_papi import VppEnum, MACAddress
27 from vpp_vxlan_gbp_tunnel import find_vxlan_gbp_tunnel, INDEX_INVALID, \
29 from vpp_neighbor import VppNeighbor
34 def find_gbp_endpoint(test, sw_if_index=None, ip=None, mac=None):
36 vip = VppIpAddress(ip)
38 vmac = MACAddress(mac)
40 eps = test.vapi.gbp_endpoint_dump()
44 if ep.endpoint.sw_if_index != sw_if_index:
47 for eip in ep.endpoint.ips:
51 if vmac.packed == ep.endpoint.mac:
56 def find_gbp_vxlan(test, vni):
57 ts = test.vapi.gbp_vxlan_tunnel_dump()
59 if t.tunnel.vni == vni:
64 class VppGbpEndpoint(VppObject):
91 return [self.ip4, self.ip6]
95 return [self.fip4, self.fip6]
97 def __init__(self, test, itf, epg, recirc, ip4, fip4, ip6, fip6,
107 self._ip4 = VppIpAddress(ip4)
108 self._fip4 = VppIpAddress(fip4)
109 self._ip6 = VppIpAddress(ip6)
110 self._fip6 = VppIpAddress(fip6)
113 self.vmac = MACAddress(self.itf.remote_mac)
115 self.vmac = MACAddress("00:00:00:00:00:00")
118 self.tun_src = VppIpAddress(tun_src)
119 self.tun_dst = VppIpAddress(tun_dst)
121 def add_vpp_config(self):
122 res = self._test.vapi.gbp_endpoint_add(
123 self.itf.sw_if_index,
124 [self.ip4.encode(), self.ip6.encode()],
128 self.tun_src.encode(),
129 self.tun_dst.encode())
130 self.handle = res.handle
131 self._test.registry.register(self, self._test.logger)
133 def remove_vpp_config(self):
134 self._test.vapi.gbp_endpoint_del(self.handle)
137 return "gbp-endpoint:[%d==%d:%s:%d]" % (self.handle,
138 self.itf.sw_if_index,
142 def query_vpp_config(self):
143 return find_gbp_endpoint(self._test,
144 self.itf.sw_if_index,
148 class VppGbpRecirc(VppObject):
150 GBP Recirculation Interface
153 def __init__(self, test, epg, recirc, is_ext=False):
159 def add_vpp_config(self):
160 self._test.vapi.gbp_recirc_add_del(
162 self.recirc.sw_if_index,
165 self._test.registry.register(self, self._test.logger)
167 def remove_vpp_config(self):
168 self._test.vapi.gbp_recirc_add_del(
170 self.recirc.sw_if_index,
175 return "gbp-recirc:[%d]" % (self.recirc.sw_if_index)
177 def query_vpp_config(self):
178 rs = self._test.vapi.gbp_recirc_dump()
180 if r.recirc.sw_if_index == self.recirc.sw_if_index:
185 class VppGbpExtItf(VppObject):
187 GBP ExtItfulation Interface
190 def __init__(self, test, itf, bd, rd):
196 def add_vpp_config(self):
197 self._test.vapi.gbp_ext_itf_add_del(
199 self.itf.sw_if_index,
202 self._test.registry.register(self, self._test.logger)
204 def remove_vpp_config(self):
205 self._test.vapi.gbp_ext_itf_add_del(
207 self.itf.sw_if_index,
212 return "gbp-ext-itf:[%d]" % (self.itf.sw_if_index)
214 def query_vpp_config(self):
215 rs = self._test.vapi.gbp_ext_itf_dump()
217 if r.ext_itf.sw_if_index == self.itf.sw_if_index:
222 class VppGbpSubnet(VppObject):
227 def __init__(self, test, rd, address, address_len,
228 type, sw_if_index=None, sclass=None):
230 self.rd_id = rd.rd_id
231 self.prefix = VppIpPrefix(address, address_len)
233 self.sw_if_index = sw_if_index
236 def add_vpp_config(self):
237 self._test.vapi.gbp_subnet_add_del(
240 self.prefix.encode(),
242 sw_if_index=self.sw_if_index if self.sw_if_index else 0xffffffff,
243 sclass=self.sclass if self.sclass else 0xffff)
244 self._test.registry.register(self, self._test.logger)
246 def remove_vpp_config(self):
247 self._test.vapi.gbp_subnet_add_del(
250 self.prefix.encode(),
254 return "gbp-subnet:[%d-%s]" % (self.rd_id, self.prefix)
256 def query_vpp_config(self):
257 ss = self._test.vapi.gbp_subnet_dump()
259 if s.subnet.rd_id == self.rd_id and \
260 s.subnet.type == self.type and \
261 s.subnet.prefix == self.prefix:
266 class VppGbpEndpointRetention(object):
267 def __init__(self, remote_ep_timeout=0xffffffff):
268 self.remote_ep_timeout = remote_ep_timeout
271 return {'remote_ep_timeout': self.remote_ep_timeout}
274 class VppGbpEndpointGroup(VppObject):
279 def __init__(self, test, vnid, sclass, rd, bd, uplink,
280 bvi, bvi_ip4, bvi_ip6=None,
281 retention=VppGbpEndpointRetention()):
285 self.bvi_ip4 = VppIpAddress(bvi_ip4)
286 self.bvi_ip6 = VppIpAddress(bvi_ip6)
293 self.retention = retention
295 def add_vpp_config(self):
296 self._test.vapi.gbp_endpoint_group_add(
301 self.uplink.sw_if_index if self.uplink else INDEX_INVALID,
302 self.retention.encode())
303 self._test.registry.register(self, self._test.logger)
305 def remove_vpp_config(self):
306 self._test.vapi.gbp_endpoint_group_del(self.sclass)
309 return "gbp-endpoint-group:[%d]" % (self.vnid)
311 def query_vpp_config(self):
312 epgs = self._test.vapi.gbp_endpoint_group_dump()
314 if epg.epg.vnid == self.vnid:
319 class VppGbpBridgeDomain(VppObject):
324 def __init__(self, test, bd, bvi, uu_fwd=None,
325 bm_flood=None, learn=True, uu_drop=False, bm_drop=False):
329 self.bm_flood = bm_flood
332 e = VppEnum.vl_api_gbp_bridge_domain_flags_t
334 self.learn = e.GBP_BD_API_FLAG_NONE
336 self.learn = e.GBP_BD_API_FLAG_DO_NOT_LEARN
338 self.learn |= e.GBP_BD_API_FLAG_UU_FWD_DROP
340 self.learn |= e.GBP_BD_API_FLAG_MCAST_DROP
342 def add_vpp_config(self):
343 self._test.vapi.gbp_bridge_domain_add(
346 self.bvi.sw_if_index,
347 self.uu_fwd.sw_if_index if self.uu_fwd else INDEX_INVALID,
348 self.bm_flood.sw_if_index if self.bm_flood else INDEX_INVALID)
349 self._test.registry.register(self, self._test.logger)
351 def remove_vpp_config(self):
352 self._test.vapi.gbp_bridge_domain_del(self.bd.bd_id)
355 return "gbp-bridge-domain:[%d]" % (self.bd.bd_id)
357 def query_vpp_config(self):
358 bds = self._test.vapi.gbp_bridge_domain_dump()
360 if bd.bd.bd_id == self.bd.bd_id:
365 class VppGbpRouteDomain(VppObject):
370 def __init__(self, test, rd_id, t4, t6, ip4_uu=None, ip6_uu=None):
378 def add_vpp_config(self):
379 self._test.vapi.gbp_route_domain_add(
383 self.ip4_uu.sw_if_index if self.ip4_uu else INDEX_INVALID,
384 self.ip6_uu.sw_if_index if self.ip6_uu else INDEX_INVALID)
385 self._test.registry.register(self, self._test.logger)
387 def remove_vpp_config(self):
388 self._test.vapi.gbp_route_domain_del(self.rd_id)
391 return "gbp-route-domain:[%d]" % (self.rd_id)
393 def query_vpp_config(self):
394 rds = self._test.vapi.gbp_route_domain_dump()
396 if rd.rd.rd_id == self.rd_id:
401 class VppGbpContractNextHop():
402 def __init__(self, mac, bd, ip, rd):
409 return {'ip': self.ip.encode(),
410 'mac': self.mac.packed,
411 'bd_id': self.bd.bd.bd_id,
412 'rd_id': self.rd.rd_id}
415 class VppGbpContractRule():
416 def __init__(self, action, hash_mode, nhs=[]):
418 self.hash_mode = hash_mode
424 nhs.append(nh.encode())
427 return {'action': self.action,
429 'hash_mode': self.hash_mode,
430 'n_nhs': len(self.nhs),
434 class VppGbpContract(VppObject):
439 def __init__(self, test, sclass, dclass, acl_index,
440 rules, allowed_ethertypes):
442 self.acl_index = acl_index
446 self.allowed_ethertypes = allowed_ethertypes
447 while (len(self.allowed_ethertypes) < 16):
448 self.allowed_ethertypes.append(0)
450 def add_vpp_config(self):
453 rules.append(r.encode())
454 r = self._test.vapi.gbp_contract_add_del(
460 self.allowed_ethertypes)
461 self.stats_index = r.stats_index
462 self._test.registry.register(self, self._test.logger)
464 def remove_vpp_config(self):
465 self._test.vapi.gbp_contract_add_del(
471 self.allowed_ethertypes)
474 return "gbp-contract:[%d:%s:%d]" % (self.sclass,
478 def query_vpp_config(self):
479 cs = self._test.vapi.gbp_contract_dump()
481 if c.contract.sclass == self.sclass \
482 and c.contract.dclass == self.dclass:
486 def get_drop_stats(self):
487 c = self._test.statistics.get_counter("/net/gbp/contract/drop")
488 return c[0][self.stats_index]
490 def get_permit_stats(self):
491 c = self._test.statistics.get_counter("/net/gbp/contract/permit")
492 return c[0][self.stats_index]
495 class VppGbpVxlanTunnel(VppInterface):
500 def __init__(self, test, vni, bd_rd_id, mode, src):
501 super(VppGbpVxlanTunnel, self).__init__(test)
504 self.bd_rd_id = bd_rd_id
508 def add_vpp_config(self):
509 r = self._test.vapi.gbp_vxlan_tunnel_add(
514 self.set_sw_if_index(r.sw_if_index)
515 self._test.registry.register(self, self._test.logger)
517 def remove_vpp_config(self):
518 self._test.vapi.gbp_vxlan_tunnel_del(self.vni)
521 return "gbp-vxlan:%d" % (self.sw_if_index)
523 def query_vpp_config(self):
524 return find_gbp_vxlan(self._test, self.vni)
527 class VppGbpAcl(VppObject):
532 def __init__(self, test):
534 self.acl_index = 4294967295
536 def create_rule(self, is_ipv6=0, permit_deny=0, proto=-1,
537 s_prefix=0, s_ip=b'\x00\x00\x00\x00', sport_from=0,
538 sport_to=65535, d_prefix=0, d_ip=b'\x00\x00\x00\x00',
539 dport_from=0, dport_to=65535):
540 if proto == -1 or proto == 0:
543 elif proto == 1 or proto == 58:
546 rule = ({'is_permit': permit_deny, 'is_ipv6': is_ipv6, 'proto': proto,
547 'srcport_or_icmptype_first': sport_from,
548 'srcport_or_icmptype_last': sport_to,
549 'src_ip_prefix_len': s_prefix,
551 'dstport_or_icmpcode_first': dport_from,
552 'dstport_or_icmpcode_last': dport_to,
553 'dst_ip_prefix_len': d_prefix,
554 'dst_ip_addr': d_ip})
557 def add_vpp_config(self, rules):
559 reply = self._test.vapi.acl_add_replace(self.acl_index,
562 self.acl_index = reply.acl_index
563 return self.acl_index
565 def remove_vpp_config(self):
566 self._test.vapi.acl_del(self.acl_index)
569 return "gbp-acl:[%d]" % (self.acl_index)
571 def query_vpp_config(self):
572 cs = self._test.vapi.acl_dump()
574 if c.acl_index == self.acl_index:
579 class TestGBP(VppTestCase):
580 """ GBP Test Case """
583 def config_flags(self):
584 return VppEnum.vl_api_nat_config_flags_t
588 super(TestGBP, cls).setUpClass()
591 def tearDownClass(cls):
592 super(TestGBP, cls).tearDownClass()
595 super(TestGBP, self).setUp()
597 self.create_pg_interfaces(range(9))
598 self.create_loopback_interfaces(8)
600 self.router_mac = MACAddress("00:11:22:33:44:55")
602 for i in self.pg_interfaces:
604 for i in self.lo_interfaces:
608 for i in self.pg_interfaces:
611 super(TestGBP, self).tearDown()
613 def send_and_expect_bridged(self, src, tx, dst):
614 rx = self.send_and_expect(src, tx, dst)
617 self.assertEqual(r[Ether].src, tx[0][Ether].src)
618 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
619 self.assertEqual(r[IP].src, tx[0][IP].src)
620 self.assertEqual(r[IP].dst, tx[0][IP].dst)
623 def send_and_expect_bridged6(self, src, tx, dst):
624 rx = self.send_and_expect(src, tx, dst)
627 self.assertEqual(r[Ether].src, tx[0][Ether].src)
628 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
629 self.assertEqual(r[IPv6].src, tx[0][IPv6].src)
630 self.assertEqual(r[IPv6].dst, tx[0][IPv6].dst)
633 def send_and_expect_routed(self, src, tx, dst, src_mac):
634 rx = self.send_and_expect(src, tx, dst)
637 self.assertEqual(r[Ether].src, src_mac)
638 self.assertEqual(r[Ether].dst, dst.remote_mac)
639 self.assertEqual(r[IP].src, tx[0][IP].src)
640 self.assertEqual(r[IP].dst, tx[0][IP].dst)
643 def send_and_expect_natted(self, src, tx, dst, src_ip):
644 rx = self.send_and_expect(src, tx, dst)
647 self.assertEqual(r[Ether].src, tx[0][Ether].src)
648 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
649 self.assertEqual(r[IP].src, src_ip)
650 self.assertEqual(r[IP].dst, tx[0][IP].dst)
653 def send_and_expect_natted6(self, src, tx, dst, src_ip):
654 rx = self.send_and_expect(src, tx, dst)
657 self.assertEqual(r[Ether].src, tx[0][Ether].src)
658 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
659 self.assertEqual(r[IPv6].src, src_ip)
660 self.assertEqual(r[IPv6].dst, tx[0][IPv6].dst)
663 def send_and_expect_unnatted(self, src, tx, dst, dst_ip):
664 rx = self.send_and_expect(src, tx, dst)
667 self.assertEqual(r[Ether].src, tx[0][Ether].src)
668 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
669 self.assertEqual(r[IP].dst, dst_ip)
670 self.assertEqual(r[IP].src, tx[0][IP].src)
673 def send_and_expect_unnatted6(self, src, tx, dst, dst_ip):
674 rx = self.send_and_expect(src, tx, dst)
677 self.assertEqual(r[Ether].src, tx[0][Ether].src)
678 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
679 self.assertEqual(r[IPv6].dst, dst_ip)
680 self.assertEqual(r[IPv6].src, tx[0][IPv6].src)
683 def send_and_expect_double_natted(self, src, tx, dst, src_ip, dst_ip):
684 rx = self.send_and_expect(src, tx, dst)
687 self.assertEqual(r[Ether].src, str(self.router_mac))
688 self.assertEqual(r[Ether].dst, dst.remote_mac)
689 self.assertEqual(r[IP].dst, dst_ip)
690 self.assertEqual(r[IP].src, src_ip)
693 def send_and_expect_double_natted6(self, src, tx, dst, src_ip, dst_ip):
694 rx = self.send_and_expect(src, tx, dst)
697 self.assertEqual(r[Ether].src, str(self.router_mac))
698 self.assertEqual(r[Ether].dst, dst.remote_mac)
699 self.assertEqual(r[IPv6].dst, dst_ip)
700 self.assertEqual(r[IPv6].src, src_ip)
703 def send_and_expect_no_arp(self, src, tx, dst):
704 self.pg_send(src, tx)
705 dst.get_capture(0, timeout=1)
706 dst.assert_nothing_captured(remark="")
709 def send_and_expect_arp(self, src, tx, dst):
710 rx = self.send_and_expect(src, tx, dst)
713 self.assertEqual(r[Ether].src, tx[0][Ether].src)
714 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
715 self.assertEqual(r[ARP].psrc, tx[0][ARP].psrc)
716 self.assertEqual(r[ARP].pdst, tx[0][ARP].pdst)
717 self.assertEqual(r[ARP].hwsrc, tx[0][ARP].hwsrc)
718 self.assertEqual(r[ARP].hwdst, tx[0][ARP].hwdst)
722 """ Group Based Policy """
724 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
729 bd1 = VppBridgeDomain(self, 1)
730 bd2 = VppBridgeDomain(self, 2)
731 bd20 = VppBridgeDomain(self, 20)
735 bd20.add_vpp_config()
737 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0)
738 gbd2 = VppGbpBridgeDomain(self, bd2, self.loop1)
739 gbd20 = VppGbpBridgeDomain(self, bd20, self.loop2)
741 gbd1.add_vpp_config()
742 gbd2.add_vpp_config()
743 gbd20.add_vpp_config()
748 gt4 = VppIpTable(self, 0)
750 gt6 = VppIpTable(self, 0, is_ip6=True)
752 nt4 = VppIpTable(self, 20)
754 nt6 = VppIpTable(self, 20, is_ip6=True)
757 rd0 = VppGbpRouteDomain(self, 0, gt4, gt6, None, None)
758 rd20 = VppGbpRouteDomain(self, 20, nt4, nt6, None, None)
761 rd20.add_vpp_config()
764 # 3 EPGs, 2 of which share a BD.
765 # 2 NAT EPGs, one for floating-IP subnets, the other for internet
767 epgs = [VppGbpEndpointGroup(self, 220, 1220, rd0, gbd1,
768 self.pg4, self.loop0,
769 "10.0.0.128", "2001:10::128"),
770 VppGbpEndpointGroup(self, 221, 1221, rd0, gbd1,
771 self.pg5, self.loop0,
772 "10.0.1.128", "2001:10:1::128"),
773 VppGbpEndpointGroup(self, 222, 1222, rd0, gbd2,
774 self.pg6, self.loop1,
775 "10.0.2.128", "2001:10:2::128"),
776 VppGbpEndpointGroup(self, 333, 1333, rd20, gbd20,
777 self.pg7, self.loop2,
778 "11.0.0.128", "3001::128"),
779 VppGbpEndpointGroup(self, 444, 1444, rd20, gbd20,
780 self.pg8, self.loop2,
781 "11.0.0.129", "3001::129")]
782 recircs = [VppGbpRecirc(self, epgs[0], self.loop3),
783 VppGbpRecirc(self, epgs[1], self.loop4),
784 VppGbpRecirc(self, epgs[2], self.loop5),
785 VppGbpRecirc(self, epgs[3], self.loop6, is_ext=True),
786 VppGbpRecirc(self, epgs[4], self.loop7, is_ext=True)]
789 recirc_nat = recircs[3]
792 # 4 end-points, 2 in the same subnet, 3 in the same BD
794 eps = [VppGbpEndpoint(self, self.pg0,
796 "10.0.0.1", "11.0.0.1",
797 "2001:10::1", "3001::1"),
798 VppGbpEndpoint(self, self.pg1,
800 "10.0.0.2", "11.0.0.2",
801 "2001:10::2", "3001::2"),
802 VppGbpEndpoint(self, self.pg2,
804 "10.0.1.1", "11.0.0.3",
805 "2001:10:1::1", "3001::3"),
806 VppGbpEndpoint(self, self.pg3,
808 "10.0.2.1", "11.0.0.4",
809 "2001:10:2::1", "3001::4")]
812 # Config related to each of the EPGs
815 # IP config on the BVI interfaces
816 if epg != epgs[1] and epg != epgs[4]:
817 VppIpInterfaceBind(self, epg.bvi, epg.rd.t4).add_vpp_config()
818 VppIpInterfaceBind(self, epg.bvi, epg.rd.t6).add_vpp_config()
819 self.vapi.sw_interface_set_mac_address(
821 self.router_mac.packed)
823 # The BVIs are NAT inside interfaces
824 flags = self.config_flags.NAT_IS_INSIDE
825 self.vapi.nat44_interface_add_del_feature(
826 sw_if_index=epg.bvi.sw_if_index,
827 flags=flags, is_add=1)
828 self.vapi.nat66_add_del_interface(
829 is_add=1, flags=flags,
830 sw_if_index=epg.bvi.sw_if_index)
832 if_ip4 = VppIpInterfaceAddress(self, epg.bvi, epg.bvi_ip4, 32)
833 if_ip6 = VppIpInterfaceAddress(self, epg.bvi, epg.bvi_ip6, 128)
834 if_ip4.add_vpp_config()
835 if_ip6.add_vpp_config()
837 # EPG uplink interfaces in the RD
838 VppIpInterfaceBind(self, epg.uplink, epg.rd.t4).add_vpp_config()
839 VppIpInterfaceBind(self, epg.uplink, epg.rd.t6).add_vpp_config()
841 # add the BD ARP termination entry for BVI IP
842 epg.bd_arp_ip4 = VppBridgeDomainArpEntry(self, epg.bd.bd,
843 str(self.router_mac),
845 epg.bd_arp_ip6 = VppBridgeDomainArpEntry(self, epg.bd.bd,
846 str(self.router_mac),
848 epg.bd_arp_ip4.add_vpp_config()
849 epg.bd_arp_ip6.add_vpp_config()
854 for recirc in recircs:
855 # EPG's ingress recirculation interface maps to its RD
856 VppIpInterfaceBind(self, recirc.recirc,
857 recirc.epg.rd.t4).add_vpp_config()
858 VppIpInterfaceBind(self, recirc.recirc,
859 recirc.epg.rd.t6).add_vpp_config()
861 self.vapi.nat44_interface_add_del_feature(
862 sw_if_index=recirc.recirc.sw_if_index, is_add=1)
863 self.vapi.nat66_add_del_interface(
865 sw_if_index=recirc.recirc.sw_if_index)
867 recirc.add_vpp_config()
869 for recirc in recircs:
870 self.assertTrue(find_bridge_domain_port(self,
871 recirc.epg.bd.bd.bd_id,
872 recirc.recirc.sw_if_index))
875 self.pg_enable_capture(self.pg_interfaces)
878 # routes to the endpoints. We need these since there are no
879 # adj-fibs due to the fact the the BVI address has /32 and
880 # the subnet is not attached.
882 for (ip, fip) in zip(ep.ips, ep.fips):
883 # Add static mappings for each EP from the 10/8 to 11/8 network
885 flags = self.config_flags.NAT_IS_ADDR_ONLY
886 self.vapi.nat44_add_del_static_mapping(
888 local_ip_address=ip.bytes,
889 external_ip_address=fip.bytes,
890 external_sw_if_index=0xFFFFFFFF,
894 self.vapi.nat66_add_del_static_mapping(
895 local_ip_address=ip.bytes,
896 external_ip_address=fip.bytes,
902 self.logger.info(self.vapi.cli("sh gbp endpoint"))
904 # ... results in a Gratuitous ARP/ND on the EPG's uplink
905 rx = ep.epg.uplink.get_capture(len(ep.ips), timeout=0.2)
907 for ii, ip in enumerate(ep.ips):
911 self.assertTrue(p.haslayer(ICMPv6ND_NA))
912 self.assertEqual(p[ICMPv6ND_NA].tgt, ip.address)
914 self.assertTrue(p.haslayer(ARP))
915 self.assertEqual(p[ARP].psrc, ip.address)
916 self.assertEqual(p[ARP].pdst, ip.address)
918 # add the BD ARP termination entry for floating IP
920 ba = VppBridgeDomainArpEntry(self, epg_nat.bd.bd, ep.mac,
924 # floating IPs route via EPG recirc
926 self, fip.address, fip.length,
927 [VppRoutePath(fip.address,
928 ep.recirc.recirc.sw_if_index,
929 type=FibPathType.FIB_PATH_TYPE_DVR,
930 proto=fip.dpo_proto)],
934 # L2 FIB entries in the NAT EPG BD to bridge the packets from
935 # the outside direct to the internal EPG
936 lf = VppL2FibEntry(self, epg_nat.bd.bd, ep.mac,
937 ep.recirc.recirc, bvi_mac=0)
941 # ARP packets for unknown IP are sent to the EPG uplink
943 pkt_arp = (Ether(dst="ff:ff:ff:ff:ff:ff",
944 src=self.pg0.remote_mac) /
946 hwdst="ff:ff:ff:ff:ff:ff",
947 hwsrc=self.pg0.remote_mac,
951 self.vapi.cli("clear trace")
952 self.pg0.add_stream(pkt_arp)
954 self.pg_enable_capture(self.pg_interfaces)
957 rxd = epgs[0].uplink.get_capture(1)
960 # ARP/ND packets get a response
962 pkt_arp = (Ether(dst="ff:ff:ff:ff:ff:ff",
963 src=self.pg0.remote_mac) /
965 hwdst="ff:ff:ff:ff:ff:ff",
966 hwsrc=self.pg0.remote_mac,
967 pdst=epgs[0].bvi_ip4.address,
968 psrc=eps[0].ip4.address))
970 self.send_and_expect(self.pg0, [pkt_arp], self.pg0)
972 nsma = in6_getnsma(inet_pton(AF_INET6, eps[0].ip6.address))
973 d = inet_ntop(AF_INET6, nsma)
974 pkt_nd = (Ether(dst=in6_getnsmac(nsma),
975 src=self.pg0.remote_mac) /
976 IPv6(dst=d, src=eps[0].ip6.address) /
977 ICMPv6ND_NS(tgt=epgs[0].bvi_ip6.address) /
978 ICMPv6NDOptSrcLLAddr(lladdr=self.pg0.remote_mac))
979 self.send_and_expect(self.pg0, [pkt_nd], self.pg0)
982 # broadcast packets are flooded
984 pkt_bcast = (Ether(dst="ff:ff:ff:ff:ff:ff",
985 src=self.pg0.remote_mac) /
986 IP(src=eps[0].ip4.address, dst="232.1.1.1") /
987 UDP(sport=1234, dport=1234) /
990 self.vapi.cli("clear trace")
991 self.pg0.add_stream(pkt_bcast)
993 self.pg_enable_capture(self.pg_interfaces)
996 rxd = eps[1].itf.get_capture(1)
997 self.assertEqual(rxd[0][Ether].dst, pkt_bcast[Ether].dst)
998 rxd = epgs[0].uplink.get_capture(1)
999 self.assertEqual(rxd[0][Ether].dst, pkt_bcast[Ether].dst)
1002 # packets to non-local L3 destinations dropped
1004 pkt_intra_epg_220_ip4 = (Ether(src=self.pg0.remote_mac,
1005 dst=str(self.router_mac)) /
1006 IP(src=eps[0].ip4.address,
1008 UDP(sport=1234, dport=1234) /
1010 pkt_inter_epg_222_ip4 = (Ether(src=self.pg0.remote_mac,
1011 dst=str(self.router_mac)) /
1012 IP(src=eps[0].ip4.address,
1014 UDP(sport=1234, dport=1234) /
1017 self.send_and_assert_no_replies(self.pg0,
1018 pkt_intra_epg_220_ip4 * NUM_PKTS)
1020 pkt_inter_epg_222_ip6 = (Ether(src=self.pg0.remote_mac,
1021 dst=str(self.router_mac)) /
1022 IPv6(src=eps[0].ip6.address,
1023 dst="2001:10::99") /
1024 UDP(sport=1234, dport=1234) /
1026 self.send_and_assert_no_replies(self.pg0,
1027 pkt_inter_epg_222_ip6 * NUM_PKTS)
1030 # Add the subnet routes
1033 self, rd0, "10.0.0.0", 24,
1034 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1036 self, rd0, "10.0.1.0", 24,
1037 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1039 self, rd0, "10.0.2.0", 24,
1040 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1042 self, rd0, "2001:10::1", 64,
1043 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1045 self, rd0, "2001:10:1::1", 64,
1046 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1048 self, rd0, "2001:10:2::1", 64,
1049 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1050 s41.add_vpp_config()
1051 s42.add_vpp_config()
1052 s43.add_vpp_config()
1053 s61.add_vpp_config()
1054 s62.add_vpp_config()
1055 s63.add_vpp_config()
1057 self.send_and_expect_bridged(eps[0].itf,
1058 pkt_intra_epg_220_ip4 * NUM_PKTS,
1060 self.send_and_expect_bridged(eps[0].itf,
1061 pkt_inter_epg_222_ip4 * NUM_PKTS,
1063 self.send_and_expect_bridged6(eps[0].itf,
1064 pkt_inter_epg_222_ip6 * NUM_PKTS,
1067 self.logger.info(self.vapi.cli("sh ip fib 11.0.0.2"))
1068 self.logger.info(self.vapi.cli("sh gbp endpoint-group"))
1069 self.logger.info(self.vapi.cli("sh gbp endpoint"))
1070 self.logger.info(self.vapi.cli("sh gbp recirc"))
1071 self.logger.info(self.vapi.cli("sh int"))
1072 self.logger.info(self.vapi.cli("sh int addr"))
1073 self.logger.info(self.vapi.cli("sh int feat loop6"))
1074 self.logger.info(self.vapi.cli("sh vlib graph ip4-gbp-src-classify"))
1075 self.logger.info(self.vapi.cli("sh int feat loop3"))
1076 self.logger.info(self.vapi.cli("sh int feat pg0"))
1079 # Packet destined to unknown unicast is sent on the epg uplink ...
1081 pkt_intra_epg_220_to_uplink = (Ether(src=self.pg0.remote_mac,
1082 dst="00:00:00:33:44:55") /
1083 IP(src=eps[0].ip4.address,
1085 UDP(sport=1234, dport=1234) /
1088 self.send_and_expect_bridged(eps[0].itf,
1089 pkt_intra_epg_220_to_uplink * NUM_PKTS,
1091 # ... and nowhere else
1092 self.pg1.get_capture(0, timeout=0.1)
1093 self.pg1.assert_nothing_captured(remark="Flood onto other VMS")
1095 pkt_intra_epg_221_to_uplink = (Ether(src=self.pg2.remote_mac,
1096 dst="00:00:00:33:44:66") /
1097 IP(src=eps[0].ip4.address,
1099 UDP(sport=1234, dport=1234) /
1102 self.send_and_expect_bridged(eps[2].itf,
1103 pkt_intra_epg_221_to_uplink * NUM_PKTS,
1107 # Packets from the uplink are forwarded in the absence of a contract
1109 pkt_intra_epg_220_from_uplink = (Ether(src="00:00:00:33:44:55",
1110 dst=self.pg0.remote_mac) /
1111 IP(src=eps[0].ip4.address,
1113 UDP(sport=1234, dport=1234) /
1116 self.send_and_expect_bridged(self.pg4,
1117 pkt_intra_epg_220_from_uplink * NUM_PKTS,
1121 # in the absence of policy, endpoints in the same EPG
1124 pkt_intra_epg = (Ether(src=self.pg0.remote_mac,
1125 dst=self.pg1.remote_mac) /
1126 IP(src=eps[0].ip4.address,
1127 dst=eps[1].ip4.address) /
1128 UDP(sport=1234, dport=1234) /
1131 self.send_and_expect_bridged(self.pg0,
1132 pkt_intra_epg * NUM_PKTS,
1136 # in the absence of policy, endpoints in the different EPG
1137 # cannot communicate
1139 pkt_inter_epg_220_to_221 = (Ether(src=self.pg0.remote_mac,
1140 dst=self.pg2.remote_mac) /
1141 IP(src=eps[0].ip4.address,
1142 dst=eps[2].ip4.address) /
1143 UDP(sport=1234, dport=1234) /
1145 pkt_inter_epg_221_to_220 = (Ether(src=self.pg2.remote_mac,
1146 dst=self.pg0.remote_mac) /
1147 IP(src=eps[2].ip4.address,
1148 dst=eps[0].ip4.address) /
1149 UDP(sport=1234, dport=1234) /
1151 pkt_inter_epg_220_to_222 = (Ether(src=self.pg0.remote_mac,
1152 dst=str(self.router_mac)) /
1153 IP(src=eps[0].ip4.address,
1154 dst=eps[3].ip4.address) /
1155 UDP(sport=1234, dport=1234) /
1158 self.send_and_assert_no_replies(eps[0].itf,
1159 pkt_inter_epg_220_to_221 * NUM_PKTS)
1160 self.send_and_assert_no_replies(eps[0].itf,
1161 pkt_inter_epg_220_to_222 * NUM_PKTS)
1164 # A uni-directional contract from EPG 220 -> 221
1166 acl = VppGbpAcl(self)
1167 rule = acl.create_rule(permit_deny=1, proto=17)
1168 rule2 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
1169 acl_index = acl.add_vpp_config([rule, rule2])
1170 c1 = VppGbpContract(
1171 self, epgs[0].sclass, epgs[1].sclass, acl_index,
1172 [VppGbpContractRule(
1173 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1176 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1178 [ETH_P_IP, ETH_P_IPV6])
1181 self.send_and_expect_bridged(eps[0].itf,
1182 pkt_inter_epg_220_to_221 * NUM_PKTS,
1184 self.send_and_assert_no_replies(eps[0].itf,
1185 pkt_inter_epg_220_to_222 * NUM_PKTS)
1188 # contract for the return direction
1190 c2 = VppGbpContract(
1191 self, epgs[1].sclass, epgs[0].sclass, acl_index,
1192 [VppGbpContractRule(
1193 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1196 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1198 [ETH_P_IP, ETH_P_IPV6])
1201 self.send_and_expect_bridged(eps[0].itf,
1202 pkt_inter_epg_220_to_221 * NUM_PKTS,
1204 self.send_and_expect_bridged(eps[2].itf,
1205 pkt_inter_epg_221_to_220 * NUM_PKTS,
1208 ds = c2.get_drop_stats()
1209 self.assertEqual(ds['packets'], 0)
1210 ps = c2.get_permit_stats()
1211 self.assertEqual(ps['packets'], NUM_PKTS)
1214 # the contract does not allow non-IP
1216 pkt_non_ip_inter_epg_220_to_221 = (Ether(src=self.pg0.remote_mac,
1217 dst=self.pg2.remote_mac) /
1219 self.send_and_assert_no_replies(eps[0].itf,
1220 pkt_non_ip_inter_epg_220_to_221 * 17)
1223 # check that inter group is still disabled for the groups
1224 # not in the contract.
1226 self.send_and_assert_no_replies(eps[0].itf,
1227 pkt_inter_epg_220_to_222 * NUM_PKTS)
1230 # A uni-directional contract from EPG 220 -> 222 'L3 routed'
1232 c3 = VppGbpContract(
1233 self, epgs[0].sclass, epgs[2].sclass, acl_index,
1234 [VppGbpContractRule(
1235 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1238 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1240 [ETH_P_IP, ETH_P_IPV6])
1243 self.logger.info(self.vapi.cli("sh gbp contract"))
1245 self.send_and_expect_routed(eps[0].itf,
1246 pkt_inter_epg_220_to_222 * NUM_PKTS,
1248 str(self.router_mac))
1251 # remove both contracts, traffic stops in both directions
1253 c2.remove_vpp_config()
1254 c1.remove_vpp_config()
1255 c3.remove_vpp_config()
1256 acl.remove_vpp_config()
1258 self.send_and_assert_no_replies(eps[2].itf,
1259 pkt_inter_epg_221_to_220 * NUM_PKTS)
1260 self.send_and_assert_no_replies(eps[0].itf,
1261 pkt_inter_epg_220_to_221 * NUM_PKTS)
1262 self.send_and_expect_bridged(eps[0].itf,
1263 pkt_intra_epg * NUM_PKTS,
1267 # EPs to the outside world
1270 # in the EP's RD an external subnet via the NAT EPG's recirc
1272 self, rd0, "0.0.0.0", 0,
1273 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1274 sw_if_index=recirc_nat.recirc.sw_if_index,
1275 sclass=epg_nat.sclass)
1277 self, rd0, "11.0.0.0", 8,
1278 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1279 sw_if_index=recirc_nat.recirc.sw_if_index,
1280 sclass=epg_nat.sclass)
1281 se16 = VppGbpSubnet(
1283 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1284 sw_if_index=recirc_nat.recirc.sw_if_index,
1285 sclass=epg_nat.sclass)
1286 # in the NAT RD an external subnet via the NAT EPG's uplink
1288 self, rd20, "0.0.0.0", 0,
1289 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1290 sw_if_index=epg_nat.uplink.sw_if_index,
1291 sclass=epg_nat.sclass)
1292 se36 = VppGbpSubnet(
1293 self, rd20, "::", 0,
1294 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1295 sw_if_index=epg_nat.uplink.sw_if_index,
1296 sclass=epg_nat.sclass)
1298 self, rd20, "11.0.0.0", 8,
1299 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1300 sw_if_index=epg_nat.uplink.sw_if_index,
1301 sclass=epg_nat.sclass)
1302 se1.add_vpp_config()
1303 se2.add_vpp_config()
1304 se16.add_vpp_config()
1305 se3.add_vpp_config()
1306 se36.add_vpp_config()
1307 se4.add_vpp_config()
1309 self.logger.info(self.vapi.cli("sh ip fib 0.0.0.0/0"))
1310 self.logger.info(self.vapi.cli("sh ip fib 11.0.0.1"))
1311 self.logger.info(self.vapi.cli("sh ip6 fib ::/0"))
1312 self.logger.info(self.vapi.cli("sh ip6 fib %s" %
1316 # From an EP to an outside address: IN2OUT
1318 pkt_inter_epg_220_to_global = (Ether(src=self.pg0.remote_mac,
1319 dst=str(self.router_mac)) /
1320 IP(src=eps[0].ip4.address,
1322 UDP(sport=1234, dport=1234) /
1326 self.send_and_assert_no_replies(eps[0].itf,
1327 pkt_inter_epg_220_to_global * NUM_PKTS)
1329 acl2 = VppGbpAcl(self)
1330 rule = acl2.create_rule(permit_deny=1, proto=17, sport_from=1234,
1331 sport_to=1234, dport_from=1234, dport_to=1234)
1332 rule2 = acl2.create_rule(is_ipv6=1, permit_deny=1, proto=17,
1333 sport_from=1234, sport_to=1234,
1334 dport_from=1234, dport_to=1234)
1336 acl_index2 = acl2.add_vpp_config([rule, rule2])
1337 c4 = VppGbpContract(
1338 self, epgs[0].sclass, epgs[3].sclass, acl_index2,
1339 [VppGbpContractRule(
1340 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1343 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1345 [ETH_P_IP, ETH_P_IPV6])
1348 self.send_and_expect_natted(eps[0].itf,
1349 pkt_inter_epg_220_to_global * NUM_PKTS,
1351 eps[0].fip4.address)
1353 pkt_inter_epg_220_to_global = (Ether(src=self.pg0.remote_mac,
1354 dst=str(self.router_mac)) /
1355 IPv6(src=eps[0].ip6.address,
1357 UDP(sport=1234, dport=1234) /
1360 self.send_and_expect_natted6(self.pg0,
1361 pkt_inter_epg_220_to_global * NUM_PKTS,
1363 eps[0].fip6.address)
1366 # From a global address to an EP: OUT2IN
1368 pkt_inter_epg_220_from_global = (Ether(src=str(self.router_mac),
1369 dst=self.pg0.remote_mac) /
1370 IP(dst=eps[0].fip4.address,
1372 UDP(sport=1234, dport=1234) /
1375 self.send_and_assert_no_replies(
1376 self.pg7, pkt_inter_epg_220_from_global * NUM_PKTS)
1378 c5 = VppGbpContract(
1379 self, epgs[3].sclass, epgs[0].sclass, acl_index2,
1380 [VppGbpContractRule(
1381 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1384 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1386 [ETH_P_IP, ETH_P_IPV6])
1389 self.send_and_expect_unnatted(self.pg7,
1390 pkt_inter_epg_220_from_global * NUM_PKTS,
1394 pkt_inter_epg_220_from_global = (Ether(src=str(self.router_mac),
1395 dst=self.pg0.remote_mac) /
1396 IPv6(dst=eps[0].fip6.address,
1398 UDP(sport=1234, dport=1234) /
1401 self.send_and_expect_unnatted6(
1403 pkt_inter_epg_220_from_global * NUM_PKTS,
1408 # From a local VM to another local VM using resp. public addresses:
1411 pkt_intra_epg_220_global = (Ether(src=self.pg0.remote_mac,
1412 dst=str(self.router_mac)) /
1413 IP(src=eps[0].ip4.address,
1414 dst=eps[1].fip4.address) /
1415 UDP(sport=1234, dport=1234) /
1418 self.send_and_expect_double_natted(eps[0].itf,
1419 pkt_intra_epg_220_global * NUM_PKTS,
1421 eps[0].fip4.address,
1424 pkt_intra_epg_220_global = (Ether(src=self.pg0.remote_mac,
1425 dst=str(self.router_mac)) /
1426 IPv6(src=eps[0].ip6.address,
1427 dst=eps[1].fip6.address) /
1428 UDP(sport=1234, dport=1234) /
1431 self.send_and_expect_double_natted6(
1433 pkt_intra_epg_220_global * NUM_PKTS,
1435 eps[0].fip6.address,
1442 # del static mappings for each EP from the 10/8 to 11/8 network
1443 flags = self.config_flags.NAT_IS_ADDR_ONLY
1444 self.vapi.nat44_add_del_static_mapping(
1446 local_ip_address=ep.ip4.bytes,
1447 external_ip_address=ep.fip4.bytes,
1448 external_sw_if_index=0xFFFFFFFF,
1451 self.vapi.nat66_add_del_static_mapping(
1452 local_ip_address=ep.ip6.bytes,
1453 external_ip_address=ep.fip6.bytes,
1457 # IP config on the BVI interfaces
1458 if epg != epgs[0] and epg != epgs[3]:
1459 flags = self.config_flags.NAT_IS_INSIDE
1460 self.vapi.nat44_interface_add_del_feature(
1461 sw_if_index=epg.bvi.sw_if_index,
1464 self.vapi.nat66_add_del_interface(
1465 is_add=0, flags=flags,
1466 sw_if_index=epg.bvi.sw_if_index)
1468 for recirc in recircs:
1469 self.vapi.nat44_interface_add_del_feature(
1470 sw_if_index=recirc.recirc.sw_if_index,
1472 self.vapi.nat66_add_del_interface(
1474 sw_if_index=recirc.recirc.sw_if_index)
1476 def wait_for_ep_timeout(self, sw_if_index=None, ip=None, mac=None,
1477 n_tries=100, s_time=1):
1479 if not find_gbp_endpoint(self, sw_if_index, ip, mac):
1481 n_tries = n_tries - 1
1483 self.assertFalse(find_gbp_endpoint(self, sw_if_index, ip, mac))
1486 def test_gbp_learn_l2(self):
1487 """ GBP L2 Endpoint Learning """
1489 self.vapi.cli("clear errors")
1491 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
1492 learnt = [{'mac': '00:00:11:11:11:01',
1494 'ip6': '2001:10::2'},
1495 {'mac': '00:00:11:11:11:02',
1497 'ip6': '2001:10::3'}]
1502 gt4 = VppIpTable(self, 1)
1503 gt4.add_vpp_config()
1504 gt6 = VppIpTable(self, 1, is_ip6=True)
1505 gt6.add_vpp_config()
1507 rd1 = VppGbpRouteDomain(self, 1, gt4, gt6)
1508 rd1.add_vpp_config()
1511 # Pg2 hosts the vxlan tunnel, hosts on pg2 to act as TEPs
1512 # Pg3 hosts the IP4 UU-flood VXLAN tunnel
1513 # Pg4 hosts the IP6 UU-flood VXLAN tunnel
1515 self.pg2.config_ip4()
1516 self.pg2.resolve_arp()
1517 self.pg2.generate_remote_hosts(4)
1518 self.pg2.configure_ipv4_neighbors()
1519 self.pg3.config_ip4()
1520 self.pg3.resolve_arp()
1521 self.pg4.config_ip4()
1522 self.pg4.resolve_arp()
1525 # Add a mcast destination VXLAN-GBP tunnel for B&M traffic
1527 tun_bm = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
1530 tun_bm.add_vpp_config()
1533 # a GBP bridge domain with a BVI and a UU-flood interface
1535 bd1 = VppBridgeDomain(self, 1)
1536 bd1.add_vpp_config()
1537 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0, self.pg3, tun_bm)
1538 gbd1.add_vpp_config()
1540 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1541 self.logger.info(self.vapi.cli("sh gbp bridge"))
1543 # ... and has a /32 applied
1544 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
1545 ip_addr.add_vpp_config()
1548 # The Endpoint-group in which we are learning endpoints
1550 epg_220 = VppGbpEndpointGroup(self, 220, 112, rd1, gbd1,
1554 VppGbpEndpointRetention(2))
1555 epg_220.add_vpp_config()
1556 epg_330 = VppGbpEndpointGroup(self, 330, 113, rd1, gbd1,
1560 VppGbpEndpointRetention(2))
1561 epg_330.add_vpp_config()
1564 # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
1567 vx_tun_l2_1 = VppGbpVxlanTunnel(
1568 self, 99, bd1.bd_id,
1569 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L2,
1571 vx_tun_l2_1.add_vpp_config()
1574 # A static endpoint that the learnt endpoints are trying to
1577 ep = VppGbpEndpoint(self, self.pg0,
1579 "10.0.0.127", "11.0.0.127",
1580 "2001:10::1", "3001::1")
1583 self.assertTrue(find_route(self, ep.ip4.address, 32, table_id=1))
1585 # a packet with an sclass from an unknown EPG
1586 p = (Ether(src=self.pg2.remote_mac,
1587 dst=self.pg2.local_mac) /
1588 IP(src=self.pg2.remote_hosts[0].ip4,
1589 dst=self.pg2.local_ip4) /
1590 UDP(sport=1234, dport=48879) /
1591 VXLAN(vni=99, gpid=88, flags=0x88) /
1592 Ether(src=learnt[0]["mac"], dst=ep.mac) /
1593 IP(src=learnt[0]["ip"], dst=ep.ip4.address) /
1594 UDP(sport=1234, dport=1234) /
1597 self.send_and_assert_no_replies(self.pg2, p)
1599 self.logger.info(self.vapi.cli("sh error"))
1600 # self.assert_packet_counter_equal(
1601 # '/err/gbp-policy-port/drop-no-contract', 1)
1604 # we should not have learnt a new tunnel endpoint, since
1605 # the EPG was not learnt.
1607 self.assertEqual(INDEX_INVALID,
1608 find_vxlan_gbp_tunnel(self,
1610 self.pg2.remote_hosts[0].ip4,
1613 # epg is not learnt, because the EPG is unknown
1614 self.assertEqual(len(self.vapi.gbp_endpoint_dump()), 1)
1617 # Learn new EPs from IP packets
1619 for ii, l in enumerate(learnt):
1620 # a packet with an sclass from a known EPG
1621 # arriving on an unknown TEP
1622 p = (Ether(src=self.pg2.remote_mac,
1623 dst=self.pg2.local_mac) /
1624 IP(src=self.pg2.remote_hosts[1].ip4,
1625 dst=self.pg2.local_ip4) /
1626 UDP(sport=1234, dport=48879) /
1627 VXLAN(vni=99, gpid=112, flags=0x88) /
1628 Ether(src=l['mac'], dst=ep.mac) /
1629 IP(src=l['ip'], dst=ep.ip4.address) /
1630 UDP(sport=1234, dport=1234) /
1633 rx = self.send_and_expect(self.pg2, [p], self.pg0)
1636 tep1_sw_if_index = find_vxlan_gbp_tunnel(
1639 self.pg2.remote_hosts[1].ip4,
1641 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
1644 # the EP is learnt via the learnt TEP
1645 # both from its MAC and its IP
1647 self.assertTrue(find_gbp_endpoint(self,
1648 vx_tun_l2_1.sw_if_index,
1650 self.assertTrue(find_gbp_endpoint(self,
1651 vx_tun_l2_1.sw_if_index,
1654 # self.assert_packet_counter_equal(
1655 # '/err/gbp-policy-port/allow-intra-sclass', 2)
1657 self.logger.info(self.vapi.cli("show gbp endpoint"))
1658 self.logger.info(self.vapi.cli("show gbp vxlan"))
1659 self.logger.info(self.vapi.cli("show ip mfib"))
1662 # If we sleep for the threshold time, the learnt endpoints should
1666 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1670 # Learn new EPs from GARP packets received on the BD's mcast tunnel
1672 for ii, l in enumerate(learnt):
1673 # a packet with an sclass from a known EPG
1674 # arriving on an unknown TEP
1675 p = (Ether(src=self.pg2.remote_mac,
1676 dst=self.pg2.local_mac) /
1677 IP(src=self.pg2.remote_hosts[1].ip4,
1679 UDP(sport=1234, dport=48879) /
1680 VXLAN(vni=88, gpid=112, flags=0x88) /
1681 Ether(src=l['mac'], dst="ff:ff:ff:ff:ff:ff") /
1683 psrc=l['ip'], pdst=l['ip'],
1684 hwsrc=l['mac'], hwdst="ff:ff:ff:ff:ff:ff"))
1686 rx = self.send_and_expect(self.pg4, [p], self.pg0)
1689 tep1_sw_if_index = find_vxlan_gbp_tunnel(
1692 self.pg2.remote_hosts[1].ip4,
1694 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
1697 # the EP is learnt via the learnt TEP
1698 # both from its MAC and its IP
1700 self.assertTrue(find_gbp_endpoint(self,
1701 vx_tun_l2_1.sw_if_index,
1703 self.assertTrue(find_gbp_endpoint(self,
1704 vx_tun_l2_1.sw_if_index,
1708 # wait for the learnt endpoints to age out
1711 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1715 # Learn new EPs from L2 packets
1717 for ii, l in enumerate(learnt):
1718 # a packet with an sclass from a known EPG
1719 # arriving on an unknown TEP
1720 p = (Ether(src=self.pg2.remote_mac,
1721 dst=self.pg2.local_mac) /
1722 IP(src=self.pg2.remote_hosts[1].ip4,
1723 dst=self.pg2.local_ip4) /
1724 UDP(sport=1234, dport=48879) /
1725 VXLAN(vni=99, gpid=112, flags=0x88) /
1726 Ether(src=l['mac'], dst=ep.mac) /
1729 rx = self.send_and_expect(self.pg2, [p], self.pg0)
1732 tep1_sw_if_index = find_vxlan_gbp_tunnel(
1735 self.pg2.remote_hosts[1].ip4,
1737 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
1740 # the EP is learnt via the learnt TEP
1741 # both from its MAC and its IP
1743 self.assertTrue(find_gbp_endpoint(self,
1744 vx_tun_l2_1.sw_if_index,
1747 self.logger.info(self.vapi.cli("show gbp endpoint"))
1748 self.logger.info(self.vapi.cli("show gbp vxlan"))
1749 self.logger.info(self.vapi.cli("show vxlan-gbp tunnel"))
1752 # wait for the learnt endpoints to age out
1755 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1759 # repeat. the do not learn bit is set so the EPs are not learnt
1762 # a packet with an sclass from a known EPG
1763 p = (Ether(src=self.pg2.remote_mac,
1764 dst=self.pg2.local_mac) /
1765 IP(src=self.pg2.remote_hosts[1].ip4,
1766 dst=self.pg2.local_ip4) /
1767 UDP(sport=1234, dport=48879) /
1768 VXLAN(vni=99, gpid=112, flags=0x88, gpflags="D") /
1769 Ether(src=l['mac'], dst=ep.mac) /
1770 IP(src=l['ip'], dst=ep.ip4.address) /
1771 UDP(sport=1234, dport=1234) /
1774 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
1777 self.assertFalse(find_gbp_endpoint(self,
1778 vx_tun_l2_1.sw_if_index,
1785 # a packet with an sclass from a known EPG
1786 p = (Ether(src=self.pg2.remote_mac,
1787 dst=self.pg2.local_mac) /
1788 IP(src=self.pg2.remote_hosts[1].ip4,
1789 dst=self.pg2.local_ip4) /
1790 UDP(sport=1234, dport=48879) /
1791 VXLAN(vni=99, gpid=112, flags=0x88) /
1792 Ether(src=l['mac'], dst=ep.mac) /
1793 IP(src=l['ip'], dst=ep.ip4.address) /
1794 UDP(sport=1234, dport=1234) /
1797 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
1799 self.assertTrue(find_gbp_endpoint(self,
1800 vx_tun_l2_1.sw_if_index,
1804 # Static EP replies to dynamics
1806 self.logger.info(self.vapi.cli("sh l2fib bd_id 1"))
1808 p = (Ether(src=ep.mac, dst=l['mac']) /
1809 IP(dst=l['ip'], src=ep.ip4.address) /
1810 UDP(sport=1234, dport=1234) /
1813 rxs = self.send_and_expect(self.pg0, p * 17, self.pg2)
1816 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
1817 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
1818 self.assertEqual(rx[UDP].dport, 48879)
1819 # the UDP source port is a random value for hashing
1820 self.assertEqual(rx[VXLAN].gpid, 112)
1821 self.assertEqual(rx[VXLAN].vni, 99)
1822 self.assertTrue(rx[VXLAN].flags.G)
1823 self.assertTrue(rx[VXLAN].flags.Instance)
1824 self.assertTrue(rx[VXLAN].gpflags.A)
1825 self.assertFalse(rx[VXLAN].gpflags.D)
1828 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1832 # repeat in the other EPG
1833 # there's no contract between 220 and 330, but the A-bit is set
1834 # so the packet is cleared for delivery
1837 # a packet with an sclass from a known EPG
1838 p = (Ether(src=self.pg2.remote_mac,
1839 dst=self.pg2.local_mac) /
1840 IP(src=self.pg2.remote_hosts[1].ip4,
1841 dst=self.pg2.local_ip4) /
1842 UDP(sport=1234, dport=48879) /
1843 VXLAN(vni=99, gpid=113, flags=0x88, gpflags='A') /
1844 Ether(src=l['mac'], dst=ep.mac) /
1845 IP(src=l['ip'], dst=ep.ip4.address) /
1846 UDP(sport=1234, dport=1234) /
1849 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
1851 self.assertTrue(find_gbp_endpoint(self,
1852 vx_tun_l2_1.sw_if_index,
1856 # static EP cannot reach the learnt EPs since there is no contract
1857 # only test 1 EP as the others could timeout
1859 p = (Ether(src=ep.mac, dst=l['mac']) /
1860 IP(dst=learnt[0]['ip'], src=ep.ip4.address) /
1861 UDP(sport=1234, dport=1234) /
1864 self.send_and_assert_no_replies(self.pg0, [p])
1867 # refresh the entries after the check for no replies above
1870 # a packet with an sclass from a known EPG
1871 p = (Ether(src=self.pg2.remote_mac,
1872 dst=self.pg2.local_mac) /
1873 IP(src=self.pg2.remote_hosts[1].ip4,
1874 dst=self.pg2.local_ip4) /
1875 UDP(sport=1234, dport=48879) /
1876 VXLAN(vni=99, gpid=113, flags=0x88, gpflags='A') /
1877 Ether(src=l['mac'], dst=ep.mac) /
1878 IP(src=l['ip'], dst=ep.ip4.address) /
1879 UDP(sport=1234, dport=1234) /
1882 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
1884 self.assertTrue(find_gbp_endpoint(self,
1885 vx_tun_l2_1.sw_if_index,
1889 # Add the contract so they can talk
1891 acl = VppGbpAcl(self)
1892 rule = acl.create_rule(permit_deny=1, proto=17)
1893 rule2 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
1894 acl_index = acl.add_vpp_config([rule, rule2])
1895 c1 = VppGbpContract(
1896 self, epg_220.sclass, epg_330.sclass, acl_index,
1897 [VppGbpContractRule(
1898 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1901 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1903 [ETH_P_IP, ETH_P_IPV6])
1907 p = (Ether(src=ep.mac, dst=l['mac']) /
1908 IP(dst=l['ip'], src=ep.ip4.address) /
1909 UDP(sport=1234, dport=1234) /
1912 self.send_and_expect(self.pg0, [p], self.pg2)
1915 # send UU packets from the local EP
1917 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1918 self.logger.info(self.vapi.cli("sh gbp bridge"))
1919 p_uu = (Ether(src=ep.mac, dst="00:11:11:11:11:11") /
1920 IP(dst="10.0.0.133", src=ep.ip4.address) /
1921 UDP(sport=1234, dport=1234) /
1923 rxs = self.send_and_expect(ep.itf, [p_uu], gbd1.uu_fwd)
1925 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1927 p_bm = (Ether(src=ep.mac, dst="ff:ff:ff:ff:ff:ff") /
1928 IP(dst="10.0.0.133", src=ep.ip4.address) /
1929 UDP(sport=1234, dport=1234) /
1931 rxs = self.send_and_expect_only(ep.itf, [p_bm], tun_bm.mcast_itf)
1934 self.assertEqual(rx[IP].src, self.pg4.local_ip4)
1935 self.assertEqual(rx[IP].dst, "239.1.1.1")
1936 self.assertEqual(rx[UDP].dport, 48879)
1937 # the UDP source port is a random value for hashing
1938 self.assertEqual(rx[VXLAN].gpid, 112)
1939 self.assertEqual(rx[VXLAN].vni, 88)
1940 self.assertTrue(rx[VXLAN].flags.G)
1941 self.assertTrue(rx[VXLAN].flags.Instance)
1942 self.assertFalse(rx[VXLAN].gpflags.A)
1943 self.assertFalse(rx[VXLAN].gpflags.D)
1946 # Check v6 Endpoints
1949 # a packet with an sclass from a known EPG
1950 p = (Ether(src=self.pg2.remote_mac,
1951 dst=self.pg2.local_mac) /
1952 IP(src=self.pg2.remote_hosts[1].ip4,
1953 dst=self.pg2.local_ip4) /
1954 UDP(sport=1234, dport=48879) /
1955 VXLAN(vni=99, gpid=113, flags=0x88, gpflags='A') /
1956 Ether(src=l['mac'], dst=ep.mac) /
1957 IPv6(src=l['ip6'], dst=ep.ip6.address) /
1958 UDP(sport=1234, dport=1234) /
1961 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
1963 self.assertTrue(find_gbp_endpoint(self,
1964 vx_tun_l2_1.sw_if_index,
1968 # L3 Endpoint Learning
1969 # - configured on the bridge's BVI
1976 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1978 self.pg2.unconfig_ip4()
1979 self.pg3.unconfig_ip4()
1980 self.pg4.unconfig_ip4()
1982 self.logger.info(self.vapi.cli("sh int"))
1983 self.logger.info(self.vapi.cli("sh gbp vxlan"))
1985 def test_gbp_contract(self):
1986 """ GBP CONTRACTS """
1991 bd1 = VppBridgeDomain(self, 1, arp_term=0)
1992 bd2 = VppBridgeDomain(self, 2, arp_term=0)
1994 bd1.add_vpp_config()
1995 bd2.add_vpp_config()
1997 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0)
1998 gbd2 = VppGbpBridgeDomain(self, bd2, self.loop1)
2000 gbd1.add_vpp_config()
2001 gbd2.add_vpp_config()
2006 gt4 = VppIpTable(self, 0)
2007 gt4.add_vpp_config()
2008 gt6 = VppIpTable(self, 0, is_ip6=True)
2009 gt6.add_vpp_config()
2011 rd0 = VppGbpRouteDomain(self, 0, gt4, gt6, None, None)
2013 rd0.add_vpp_config()
2016 # 3 EPGs, 2 of which share a BD.
2018 epgs = [VppGbpEndpointGroup(self, 220, 1220, rd0, gbd1,
2020 "10.0.0.128", "2001:10::128"),
2021 VppGbpEndpointGroup(self, 221, 1221, rd0, gbd1,
2023 "10.0.1.128", "2001:10:1::128"),
2024 VppGbpEndpointGroup(self, 222, 1222, rd0, gbd2,
2026 "10.0.2.128", "2001:10:2::128")]
2028 # 4 end-points, 2 in the same subnet, 3 in the same BD
2030 eps = [VppGbpEndpoint(self, self.pg0,
2032 "10.0.0.1", "11.0.0.1",
2033 "2001:10::1", "3001::1"),
2034 VppGbpEndpoint(self, self.pg1,
2036 "10.0.0.2", "11.0.0.2",
2037 "2001:10::2", "3001::2"),
2038 VppGbpEndpoint(self, self.pg2,
2040 "10.0.1.1", "11.0.0.3",
2041 "2001:10:1::1", "3001::3"),
2042 VppGbpEndpoint(self, self.pg3,
2044 "10.0.2.1", "11.0.0.4",
2045 "2001:10:2::1", "3001::4")]
2048 # Config related to each of the EPGs
2051 # IP config on the BVI interfaces
2053 VppIpInterfaceBind(self, epg.bvi, epg.rd.t4).add_vpp_config()
2054 VppIpInterfaceBind(self, epg.bvi, epg.rd.t6).add_vpp_config()
2055 self.vapi.sw_interface_set_mac_address(
2056 epg.bvi.sw_if_index,
2057 self.router_mac.packed)
2059 if_ip4 = VppIpInterfaceAddress(self, epg.bvi, epg.bvi_ip4, 32)
2060 if_ip6 = VppIpInterfaceAddress(self, epg.bvi, epg.bvi_ip6, 128)
2061 if_ip4.add_vpp_config()
2062 if_ip6.add_vpp_config()
2064 # add the BD ARP termination entry for BVI IP
2065 epg.bd_arp_ip4 = VppBridgeDomainArpEntry(self, epg.bd.bd,
2066 str(self.router_mac),
2067 epg.bvi_ip4.address)
2068 epg.bd_arp_ip4.add_vpp_config()
2071 epg.add_vpp_config()
2079 self.logger.info(self.vapi.cli("show gbp endpoint"))
2080 self.logger.info(self.vapi.cli("show interface"))
2081 self.logger.info(self.vapi.cli("show br"))
2084 # Intra epg allowed without contract
2086 pkt_intra_epg_220_to_220 = (Ether(src=self.pg0.remote_mac,
2087 dst=self.pg1.remote_mac) /
2088 IP(src=eps[0].ip4.address,
2089 dst=eps[1].ip4.address) /
2090 UDP(sport=1234, dport=1234) /
2093 self.send_and_expect_bridged(self.pg0,
2094 pkt_intra_epg_220_to_220 * 65,
2098 # Inter epg denied without contract
2100 pkt_inter_epg_220_to_221 = (Ether(src=self.pg0.remote_mac,
2101 dst=self.pg2.remote_mac) /
2102 IP(src=eps[0].ip4.address,
2103 dst=eps[2].ip4.address) /
2104 UDP(sport=1234, dport=1234) /
2107 self.send_and_assert_no_replies(self.pg0, pkt_inter_epg_220_to_221)
2110 # A uni-directional contract from EPG 220 -> 221
2112 acl = VppGbpAcl(self)
2113 rule = acl.create_rule(permit_deny=1, proto=17)
2114 rule2 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
2115 acl_index = acl.add_vpp_config([rule, rule2])
2116 c1 = VppGbpContract(
2117 self, epgs[0].sclass, epgs[1].sclass, acl_index,
2118 [VppGbpContractRule(
2119 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2122 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2124 [ETH_P_IP, ETH_P_IPV6])
2127 self.send_and_expect_bridged(eps[0].itf,
2128 pkt_inter_epg_220_to_221 * 65,
2131 pkt_inter_epg_220_to_222 = (Ether(src=self.pg0.remote_mac,
2132 dst=str(self.router_mac)) /
2133 IP(src=eps[0].ip4.address,
2134 dst=eps[3].ip4.address) /
2135 UDP(sport=1234, dport=1234) /
2137 self.send_and_assert_no_replies(eps[0].itf,
2138 pkt_inter_epg_220_to_222 * 65)
2141 # contract for the return direction
2143 c2 = VppGbpContract(
2144 self, epgs[1].sclass, epgs[0].sclass, acl_index,
2145 [VppGbpContractRule(
2146 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2149 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2151 [ETH_P_IP, ETH_P_IPV6])
2154 self.send_and_expect_bridged(eps[0].itf,
2155 pkt_inter_epg_220_to_221 * 65,
2157 pkt_inter_epg_221_to_220 = (Ether(src=self.pg2.remote_mac,
2158 dst=self.pg0.remote_mac) /
2159 IP(src=eps[2].ip4.address,
2160 dst=eps[0].ip4.address) /
2161 UDP(sport=1234, dport=1234) /
2163 self.send_and_expect_bridged(eps[2].itf,
2164 pkt_inter_epg_221_to_220 * 65,
2168 # contract between 220 and 222 uni-direction
2170 c3 = VppGbpContract(
2171 self, epgs[0].sclass, epgs[2].sclass, acl_index,
2172 [VppGbpContractRule(
2173 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2176 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2178 [ETH_P_IP, ETH_P_IPV6])
2181 self.send_and_expect(eps[0].itf,
2182 pkt_inter_epg_220_to_222 * 65,
2185 c3.remove_vpp_config()
2186 c1.remove_vpp_config()
2187 c2.remove_vpp_config()
2188 acl.remove_vpp_config()
2190 def test_gbp_bd_flags(self):
2191 """ GBP BD FLAGS """
2196 gt4 = VppIpTable(self, 1)
2197 gt4.add_vpp_config()
2198 gt6 = VppIpTable(self, 1, is_ip6=True)
2199 gt6.add_vpp_config()
2201 rd1 = VppGbpRouteDomain(self, 1, gt4, gt6)
2202 rd1.add_vpp_config()
2205 # Pg3 hosts the IP4 UU-flood VXLAN tunnel
2206 # Pg4 hosts the IP6 UU-flood VXLAN tunnel
2208 self.pg3.config_ip4()
2209 self.pg3.resolve_arp()
2210 self.pg4.config_ip4()
2211 self.pg4.resolve_arp()
2214 # Add a mcast destination VXLAN-GBP tunnel for B&M traffic
2216 tun_bm = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
2219 tun_bm.add_vpp_config()
2222 # a GBP bridge domain with a BVI and a UU-flood interface
2224 bd1 = VppBridgeDomain(self, 1)
2225 bd1.add_vpp_config()
2227 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0, self.pg3, tun_bm,
2228 uu_drop=True, bm_drop=True)
2229 gbd1.add_vpp_config()
2231 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2232 self.logger.info(self.vapi.cli("sh gbp bridge"))
2234 # ... and has a /32 applied
2235 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2236 ip_addr.add_vpp_config()
2239 # The Endpoint-group
2241 epg_220 = VppGbpEndpointGroup(self, 220, 112, rd1, gbd1,
2245 VppGbpEndpointRetention(2))
2246 epg_220.add_vpp_config()
2248 ep = VppGbpEndpoint(self, self.pg0,
2250 "10.0.0.127", "11.0.0.127",
2251 "2001:10::1", "3001::1")
2254 # send UU/BM packet from the local EP with UU drop and BM drop enabled
2257 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2258 self.logger.info(self.vapi.cli("sh gbp bridge"))
2259 p_uu = (Ether(src=ep.mac, dst="00:11:11:11:11:11") /
2260 IP(dst="10.0.0.133", src=ep.ip4.address) /
2261 UDP(sport=1234, dport=1234) /
2263 self.send_and_assert_no_replies(ep.itf, [p_uu])
2265 p_bm = (Ether(src=ep.mac, dst="ff:ff:ff:ff:ff:ff") /
2266 IP(dst="10.0.0.133", src=ep.ip4.address) /
2267 UDP(sport=1234, dport=1234) /
2269 self.send_and_assert_no_replies(ep.itf, [p_bm])
2271 self.pg3.unconfig_ip4()
2272 self.pg4.unconfig_ip4()
2274 self.logger.info(self.vapi.cli("sh int"))
2276 def test_gbp_learn_vlan_l2(self):
2277 """ GBP L2 Endpoint w/ VLANs"""
2279 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
2280 learnt = [{'mac': '00:00:11:11:11:01',
2282 'ip6': '2001:10::2'},
2283 {'mac': '00:00:11:11:11:02',
2285 'ip6': '2001:10::3'}]
2290 gt4 = VppIpTable(self, 1)
2291 gt4.add_vpp_config()
2292 gt6 = VppIpTable(self, 1, is_ip6=True)
2293 gt6.add_vpp_config()
2295 rd1 = VppGbpRouteDomain(self, 1, gt4, gt6)
2296 rd1.add_vpp_config()
2299 # Pg2 hosts the vxlan tunnel, hosts on pg2 to act as TEPs
2301 self.pg2.config_ip4()
2302 self.pg2.resolve_arp()
2303 self.pg2.generate_remote_hosts(4)
2304 self.pg2.configure_ipv4_neighbors()
2305 self.pg3.config_ip4()
2306 self.pg3.resolve_arp()
2309 # The EP will be on a vlan sub-interface
2311 vlan_11 = VppDot1QSubint(self, self.pg0, 11)
2313 self.vapi.l2_interface_vlan_tag_rewrite(
2314 sw_if_index=vlan_11.sw_if_index, vtr_op=L2_VTR_OP.L2_POP_1,
2317 bd_uu_fwd = VppVxlanGbpTunnel(self, self.pg3.local_ip4,
2318 self.pg3.remote_ip4, 116)
2319 bd_uu_fwd.add_vpp_config()
2322 # a GBP bridge domain with a BVI and a UU-flood interface
2323 # The BD is marked as do not learn, so no endpoints are ever
2324 # learnt in this BD.
2326 bd1 = VppBridgeDomain(self, 1)
2327 bd1.add_vpp_config()
2328 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0, bd_uu_fwd,
2330 gbd1.add_vpp_config()
2332 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2333 self.logger.info(self.vapi.cli("sh gbp bridge"))
2335 # ... and has a /32 applied
2336 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2337 ip_addr.add_vpp_config()
2340 # The Endpoint-group in which we are learning endpoints
2342 epg_220 = VppGbpEndpointGroup(self, 220, 441, rd1, gbd1,
2346 VppGbpEndpointRetention(2))
2347 epg_220.add_vpp_config()
2350 # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
2353 vx_tun_l2_1 = VppGbpVxlanTunnel(
2354 self, 99, bd1.bd_id,
2355 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L2,
2357 vx_tun_l2_1.add_vpp_config()
2360 # A static endpoint that the learnt endpoints are trying to
2363 ep = VppGbpEndpoint(self, vlan_11,
2365 "10.0.0.127", "11.0.0.127",
2366 "2001:10::1", "3001::1")
2369 self.assertTrue(find_route(self, ep.ip4.address, 32, table_id=1))
2372 # Send to the static EP
2374 for ii, l in enumerate(learnt):
2375 # a packet with an sclass from a known EPG
2376 # arriving on an unknown TEP
2377 p = (Ether(src=self.pg2.remote_mac,
2378 dst=self.pg2.local_mac) /
2379 IP(src=self.pg2.remote_hosts[1].ip4,
2380 dst=self.pg2.local_ip4) /
2381 UDP(sport=1234, dport=48879) /
2382 VXLAN(vni=99, gpid=441, flags=0x88) /
2383 Ether(src=l['mac'], dst=ep.mac) /
2384 IP(src=l['ip'], dst=ep.ip4.address) /
2385 UDP(sport=1234, dport=1234) /
2388 rxs = self.send_and_expect(self.pg2, [p], self.pg0)
2391 # packet to EP has the EP's vlan tag
2394 self.assertEqual(rx[Dot1Q].vlan, 11)
2397 # the EP is not learnt since the BD setting prevents it
2400 self.assertFalse(find_gbp_endpoint(self,
2401 vx_tun_l2_1.sw_if_index,
2403 self.assertEqual(INDEX_INVALID,
2404 find_vxlan_gbp_tunnel(
2407 self.pg2.remote_hosts[1].ip4,
2410 self.assertEqual(len(self.vapi.gbp_endpoint_dump()), 1)
2414 # we didn't learn the remotes so they are sent to the UU-fwd
2417 p = (Ether(src=ep.mac, dst=l['mac']) /
2419 IP(dst=l['ip'], src=ep.ip4.address) /
2420 UDP(sport=1234, dport=1234) /
2423 rxs = self.send_and_expect(self.pg0, p * 17, self.pg3)
2426 self.assertEqual(rx[IP].src, self.pg3.local_ip4)
2427 self.assertEqual(rx[IP].dst, self.pg3.remote_ip4)
2428 self.assertEqual(rx[UDP].dport, 48879)
2429 # the UDP source port is a random value for hashing
2430 self.assertEqual(rx[VXLAN].gpid, 441)
2431 self.assertEqual(rx[VXLAN].vni, 116)
2432 self.assertTrue(rx[VXLAN].flags.G)
2433 self.assertTrue(rx[VXLAN].flags.Instance)
2434 self.assertFalse(rx[VXLAN].gpflags.A)
2435 self.assertFalse(rx[VXLAN].gpflags.D)
2437 self.pg2.unconfig_ip4()
2438 self.pg3.unconfig_ip4()
2440 def test_gbp_learn_l3(self):
2441 """ GBP L3 Endpoint Learning """
2443 self.vapi.cli("set logging class gbp level debug")
2445 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
2446 routed_dst_mac = "00:0c:0c:0c:0c:0c"
2447 routed_src_mac = "00:22:bd:f8:19:ff"
2449 learnt = [{'mac': '00:00:11:11:11:02',
2451 'ip6': '2001:10::2'},
2452 {'mac': '00:00:11:11:11:03',
2454 'ip6': '2001:10::3'}]
2459 t4 = VppIpTable(self, 1)
2461 t6 = VppIpTable(self, 1, True)
2464 tun_ip4_uu = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
2465 self.pg4.remote_ip4, 114)
2466 tun_ip6_uu = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
2467 self.pg4.remote_ip4, 116)
2468 tun_ip4_uu.add_vpp_config()
2469 tun_ip6_uu.add_vpp_config()
2471 rd1 = VppGbpRouteDomain(self, 2, t4, t6, tun_ip4_uu, tun_ip6_uu)
2472 rd1.add_vpp_config()
2474 self.loop0.set_mac(self.router_mac)
2477 # Bind the BVI to the RD
2479 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
2480 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
2483 # Pg2 hosts the vxlan tunnel
2484 # hosts on pg2 to act as TEPs
2488 self.pg2.config_ip4()
2489 self.pg2.resolve_arp()
2490 self.pg2.generate_remote_hosts(4)
2491 self.pg2.configure_ipv4_neighbors()
2492 self.pg3.config_ip4()
2493 self.pg3.resolve_arp()
2494 self.pg4.config_ip4()
2495 self.pg4.resolve_arp()
2498 # a GBP bridge domain with a BVI and a UU-flood interface
2500 bd1 = VppBridgeDomain(self, 1)
2501 bd1.add_vpp_config()
2502 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0, self.pg3)
2503 gbd1.add_vpp_config()
2505 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2506 self.logger.info(self.vapi.cli("sh gbp bridge"))
2507 self.logger.info(self.vapi.cli("sh gbp route"))
2509 # ... and has a /32 and /128 applied
2510 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2511 ip4_addr.add_vpp_config()
2512 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 128)
2513 ip6_addr.add_vpp_config()
2516 # The Endpoint-group in which we are learning endpoints
2518 epg_220 = VppGbpEndpointGroup(self, 220, 441, rd1, gbd1,
2522 VppGbpEndpointRetention(2))
2523 epg_220.add_vpp_config()
2526 # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
2529 vx_tun_l3 = VppGbpVxlanTunnel(
2530 self, 101, rd1.rd_id,
2531 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
2533 vx_tun_l3.add_vpp_config()
2536 # A static endpoint that the learnt endpoints are trying to
2539 ep = VppGbpEndpoint(self, self.pg0,
2541 "10.0.0.127", "11.0.0.127",
2542 "2001:10::1", "3001::1")
2546 # learn some remote IPv4 EPs
2548 for ii, l in enumerate(learnt):
2549 # a packet with an sclass from a known EPG
2550 # arriving on an unknown TEP
2551 p = (Ether(src=self.pg2.remote_mac,
2552 dst=self.pg2.local_mac) /
2553 IP(src=self.pg2.remote_hosts[1].ip4,
2554 dst=self.pg2.local_ip4) /
2555 UDP(sport=1234, dport=48879) /
2556 VXLAN(vni=101, gpid=441, flags=0x88) /
2557 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2558 IP(src=l['ip'], dst=ep.ip4.address) /
2559 UDP(sport=1234, dport=1234) /
2562 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2565 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2568 self.pg2.remote_hosts[1].ip4,
2570 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2572 # endpoint learnt via the parent GBP-vxlan interface
2573 self.assertTrue(find_gbp_endpoint(self,
2574 vx_tun_l3._sw_if_index,
2578 # Static IPv4 EP replies to learnt
2581 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2582 IP(dst=l['ip'], src=ep.ip4.address) /
2583 UDP(sport=1234, dport=1234) /
2586 rxs = self.send_and_expect(self.pg0, p * 1, self.pg2)
2589 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2590 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2591 self.assertEqual(rx[UDP].dport, 48879)
2592 # the UDP source port is a random value for hashing
2593 self.assertEqual(rx[VXLAN].gpid, 441)
2594 self.assertEqual(rx[VXLAN].vni, 101)
2595 self.assertTrue(rx[VXLAN].flags.G)
2596 self.assertTrue(rx[VXLAN].flags.Instance)
2597 self.assertTrue(rx[VXLAN].gpflags.A)
2598 self.assertFalse(rx[VXLAN].gpflags.D)
2600 inner = rx[VXLAN].payload
2602 self.assertEqual(inner[Ether].src, routed_src_mac)
2603 self.assertEqual(inner[Ether].dst, routed_dst_mac)
2604 self.assertEqual(inner[IP].src, ep.ip4.address)
2605 self.assertEqual(inner[IP].dst, l['ip'])
2608 self.assertFalse(find_gbp_endpoint(self,
2613 # learn some remote IPv6 EPs
2615 for ii, l in enumerate(learnt):
2616 # a packet with an sclass from a known EPG
2617 # arriving on an unknown TEP
2618 p = (Ether(src=self.pg2.remote_mac,
2619 dst=self.pg2.local_mac) /
2620 IP(src=self.pg2.remote_hosts[1].ip4,
2621 dst=self.pg2.local_ip4) /
2622 UDP(sport=1234, dport=48879) /
2623 VXLAN(vni=101, gpid=441, flags=0x88) /
2624 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2625 IPv6(src=l['ip6'], dst=ep.ip6.address) /
2626 UDP(sport=1234, dport=1234) /
2629 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2632 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2635 self.pg2.remote_hosts[1].ip4,
2637 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2639 self.logger.info(self.vapi.cli("show gbp bridge"))
2640 self.logger.info(self.vapi.cli("show vxlan-gbp tunnel"))
2641 self.logger.info(self.vapi.cli("show gbp vxlan"))
2642 self.logger.info(self.vapi.cli("show int addr"))
2644 # endpoint learnt via the TEP
2645 self.assertTrue(find_gbp_endpoint(self, ip=l['ip6']))
2647 self.logger.info(self.vapi.cli("show gbp endpoint"))
2648 self.logger.info(self.vapi.cli("show ip fib index 1 %s" % l['ip']))
2651 # Static EP replies to learnt
2654 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2655 IPv6(dst=l['ip6'], src=ep.ip6.address) /
2656 UDP(sport=1234, dport=1234) /
2659 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
2662 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2663 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2664 self.assertEqual(rx[UDP].dport, 48879)
2665 # the UDP source port is a random value for hashing
2666 self.assertEqual(rx[VXLAN].gpid, 441)
2667 self.assertEqual(rx[VXLAN].vni, 101)
2668 self.assertTrue(rx[VXLAN].flags.G)
2669 self.assertTrue(rx[VXLAN].flags.Instance)
2670 self.assertTrue(rx[VXLAN].gpflags.A)
2671 self.assertFalse(rx[VXLAN].gpflags.D)
2673 inner = rx[VXLAN].payload
2675 self.assertEqual(inner[Ether].src, routed_src_mac)
2676 self.assertEqual(inner[Ether].dst, routed_dst_mac)
2677 self.assertEqual(inner[IPv6].src, ep.ip6.address)
2678 self.assertEqual(inner[IPv6].dst, l['ip6'])
2680 self.logger.info(self.vapi.cli("sh gbp endpoint"))
2682 self.wait_for_ep_timeout(ip=l['ip'])
2685 # Static sends to unknown EP with no route
2687 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2688 IP(dst="10.0.0.99", src=ep.ip4.address) /
2689 UDP(sport=1234, dport=1234) /
2692 self.send_and_assert_no_replies(self.pg0, [p])
2695 # Add a route to static EP's v4 and v6 subnet
2696 # packets should be sent on the v4/v6 uu=fwd interface resp.
2698 se_10_24 = VppGbpSubnet(
2699 self, rd1, "10.0.0.0", 24,
2700 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT)
2701 se_10_24.add_vpp_config()
2703 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2704 IP(dst="10.0.0.99", src=ep.ip4.address) /
2705 UDP(sport=1234, dport=1234) /
2708 rxs = self.send_and_expect(self.pg0, [p], self.pg4)
2710 self.assertEqual(rx[IP].src, self.pg4.local_ip4)
2711 self.assertEqual(rx[IP].dst, self.pg4.remote_ip4)
2712 self.assertEqual(rx[UDP].dport, 48879)
2713 # the UDP source port is a random value for hashing
2714 self.assertEqual(rx[VXLAN].gpid, 441)
2715 self.assertEqual(rx[VXLAN].vni, 114)
2716 self.assertTrue(rx[VXLAN].flags.G)
2717 self.assertTrue(rx[VXLAN].flags.Instance)
2718 # policy is not applied to packets sent to the uu-fwd interfaces
2719 self.assertFalse(rx[VXLAN].gpflags.A)
2720 self.assertFalse(rx[VXLAN].gpflags.D)
2723 # learn some remote IPv4 EPs
2725 for ii, l in enumerate(learnt):
2726 # a packet with an sclass from a known EPG
2727 # arriving on an unknown TEP
2728 p = (Ether(src=self.pg2.remote_mac,
2729 dst=self.pg2.local_mac) /
2730 IP(src=self.pg2.remote_hosts[2].ip4,
2731 dst=self.pg2.local_ip4) /
2732 UDP(sport=1234, dport=48879) /
2733 VXLAN(vni=101, gpid=441, flags=0x88) /
2734 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2735 IP(src=l['ip'], dst=ep.ip4.address) /
2736 UDP(sport=1234, dport=1234) /
2739 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2742 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2745 self.pg2.remote_hosts[2].ip4,
2747 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2749 # endpoint learnt via the parent GBP-vxlan interface
2750 self.assertTrue(find_gbp_endpoint(self,
2751 vx_tun_l3._sw_if_index,
2755 # Add a remote endpoint from the API
2757 rep_88 = VppGbpEndpoint(self, vx_tun_l3,
2759 "10.0.0.88", "11.0.0.88",
2760 "2001:10::88", "3001::88",
2761 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
2763 self.pg2.remote_hosts[1].ip4,
2765 rep_88.add_vpp_config()
2768 # Add a remote endpoint from the API that matches an existing one
2770 rep_2 = VppGbpEndpoint(self, vx_tun_l3,
2772 learnt[0]['ip'], "11.0.0.101",
2773 learnt[0]['ip6'], "3001::101",
2774 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
2776 self.pg2.remote_hosts[1].ip4,
2778 rep_2.add_vpp_config()
2781 # Add a route to the learned EP's v4 subnet
2782 # packets should be send on the v4/v6 uu=fwd interface resp.
2784 se_10_1_24 = VppGbpSubnet(
2785 self, rd1, "10.0.1.0", 24,
2786 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT)
2787 se_10_1_24.add_vpp_config()
2789 self.logger.info(self.vapi.cli("show gbp endpoint"))
2791 ips = ["10.0.0.88", learnt[0]['ip']]
2793 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2794 IP(dst=ip, src=ep.ip4.address) /
2795 UDP(sport=1234, dport=1234) /
2798 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
2801 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2802 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2803 self.assertEqual(rx[UDP].dport, 48879)
2804 # the UDP source port is a random value for hashing
2805 self.assertEqual(rx[VXLAN].gpid, 441)
2806 self.assertEqual(rx[VXLAN].vni, 101)
2807 self.assertTrue(rx[VXLAN].flags.G)
2808 self.assertTrue(rx[VXLAN].flags.Instance)
2809 self.assertTrue(rx[VXLAN].gpflags.A)
2810 self.assertFalse(rx[VXLAN].gpflags.D)
2812 inner = rx[VXLAN].payload
2814 self.assertEqual(inner[Ether].src, routed_src_mac)
2815 self.assertEqual(inner[Ether].dst, routed_dst_mac)
2816 self.assertEqual(inner[IP].src, ep.ip4.address)
2817 self.assertEqual(inner[IP].dst, ip)
2820 # remove the API remote EPs, only API sourced is gone, the DP
2821 # learnt one remains
2823 rep_88.remove_vpp_config()
2824 rep_2.remove_vpp_config()
2826 self.assertTrue(find_gbp_endpoint(self, ip=rep_2.ip4.address))
2828 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2829 IP(src=ep.ip4.address, dst=rep_2.ip4.address) /
2830 UDP(sport=1234, dport=1234) /
2832 rxs = self.send_and_expect(self.pg0, [p], self.pg2)
2834 self.assertFalse(find_gbp_endpoint(self, ip=rep_88.ip4.address))
2836 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2837 IP(src=ep.ip4.address, dst=rep_88.ip4.address) /
2838 UDP(sport=1234, dport=1234) /
2840 rxs = self.send_and_expect(self.pg0, [p], self.pg4)
2843 # to appease the testcase we cannot have the registered EP still
2844 # present (because it's DP learnt) when the TC ends so wait until
2847 self.wait_for_ep_timeout(ip=rep_88.ip4.address)
2848 self.wait_for_ep_timeout(ip=rep_2.ip4.address)
2851 # shutdown with learnt endpoint present
2853 p = (Ether(src=self.pg2.remote_mac,
2854 dst=self.pg2.local_mac) /
2855 IP(src=self.pg2.remote_hosts[1].ip4,
2856 dst=self.pg2.local_ip4) /
2857 UDP(sport=1234, dport=48879) /
2858 VXLAN(vni=101, gpid=441, flags=0x88) /
2859 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2860 IP(src=learnt[1]['ip'], dst=ep.ip4.address) /
2861 UDP(sport=1234, dport=1234) /
2864 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2866 # endpoint learnt via the parent GBP-vxlan interface
2867 self.assertTrue(find_gbp_endpoint(self,
2868 vx_tun_l3._sw_if_index,
2873 # remote endpoint becomes local
2875 self.pg2.unconfig_ip4()
2876 self.pg3.unconfig_ip4()
2877 self.pg4.unconfig_ip4()
2879 def test_gbp_redirect(self):
2880 """ GBP Endpoint Redirect """
2882 self.vapi.cli("set logging class gbp level debug")
2884 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
2885 routed_dst_mac = "00:0c:0c:0c:0c:0c"
2886 routed_src_mac = "00:22:bd:f8:19:ff"
2888 learnt = [{'mac': '00:00:11:11:11:02',
2890 'ip6': '2001:10::2'},
2891 {'mac': '00:00:11:11:11:03',
2893 'ip6': '2001:10::3'}]
2898 t4 = VppIpTable(self, 1)
2900 t6 = VppIpTable(self, 1, True)
2903 rd1 = VppGbpRouteDomain(self, 2, t4, t6)
2904 rd1.add_vpp_config()
2906 self.loop0.set_mac(self.router_mac)
2909 # Bind the BVI to the RD
2911 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
2912 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
2915 # Pg7 hosts a BD's UU-fwd
2917 self.pg7.config_ip4()
2918 self.pg7.resolve_arp()
2921 # a GBP bridge domains for the EPs
2923 bd1 = VppBridgeDomain(self, 1)
2924 bd1.add_vpp_config()
2925 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0)
2926 gbd1.add_vpp_config()
2928 bd2 = VppBridgeDomain(self, 2)
2929 bd2.add_vpp_config()
2930 gbd2 = VppGbpBridgeDomain(self, bd2, self.loop1)
2931 gbd2.add_vpp_config()
2933 # ... and has a /32 and /128 applied
2934 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2935 ip4_addr.add_vpp_config()
2936 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 128)
2937 ip6_addr.add_vpp_config()
2938 ip4_addr = VppIpInterfaceAddress(self, gbd2.bvi, "10.0.1.128", 32)
2939 ip4_addr.add_vpp_config()
2940 ip6_addr = VppIpInterfaceAddress(self, gbd2.bvi, "2001:11::128", 128)
2941 ip6_addr.add_vpp_config()
2944 # The Endpoint-groups in which we are learning endpoints
2946 epg_220 = VppGbpEndpointGroup(self, 220, 440, rd1, gbd1,
2950 VppGbpEndpointRetention(2))
2951 epg_220.add_vpp_config()
2952 epg_221 = VppGbpEndpointGroup(self, 221, 441, rd1, gbd2,
2956 VppGbpEndpointRetention(2))
2957 epg_221.add_vpp_config()
2958 epg_222 = VppGbpEndpointGroup(self, 222, 442, rd1, gbd1,
2962 VppGbpEndpointRetention(2))
2963 epg_222.add_vpp_config()
2966 # a GBP bridge domains for the SEPs
2968 bd_uu1 = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
2969 self.pg7.remote_ip4, 116)
2970 bd_uu1.add_vpp_config()
2971 bd_uu2 = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
2972 self.pg7.remote_ip4, 117)
2973 bd_uu2.add_vpp_config()
2975 bd3 = VppBridgeDomain(self, 3)
2976 bd3.add_vpp_config()
2977 gbd3 = VppGbpBridgeDomain(self, bd3, self.loop2, bd_uu1, learn=False)
2978 gbd3.add_vpp_config()
2979 bd4 = VppBridgeDomain(self, 4)
2980 bd4.add_vpp_config()
2981 gbd4 = VppGbpBridgeDomain(self, bd4, self.loop3, bd_uu2, learn=False)
2982 gbd4.add_vpp_config()
2985 # EPGs in which the service endpoints exist
2987 epg_320 = VppGbpEndpointGroup(self, 320, 550, rd1, gbd3,
2991 VppGbpEndpointRetention(2))
2992 epg_320.add_vpp_config()
2993 epg_321 = VppGbpEndpointGroup(self, 321, 551, rd1, gbd4,
2997 VppGbpEndpointRetention(2))
2998 epg_321.add_vpp_config()
3001 # three local endpoints
3003 ep1 = VppGbpEndpoint(self, self.pg0,
3005 "10.0.0.1", "11.0.0.1",
3006 "2001:10::1", "3001:10::1")
3007 ep1.add_vpp_config()
3008 ep2 = VppGbpEndpoint(self, self.pg1,
3010 "10.0.1.1", "11.0.1.1",
3011 "2001:11::1", "3001:11::1")
3012 ep2.add_vpp_config()
3013 ep3 = VppGbpEndpoint(self, self.pg2,
3015 "10.0.2.2", "11.0.2.2",
3016 "2001:12::1", "3001:12::1")
3017 ep3.add_vpp_config()
3022 sep1 = VppGbpEndpoint(self, self.pg3,
3024 "12.0.0.1", "13.0.0.1",
3025 "4001:10::1", "5001:10::1")
3026 sep1.add_vpp_config()
3027 sep2 = VppGbpEndpoint(self, self.pg4,
3029 "12.0.0.2", "13.0.0.2",
3030 "4001:10::2", "5001:10::2")
3031 sep2.add_vpp_config()
3032 sep3 = VppGbpEndpoint(self, self.pg5,
3034 "12.0.1.1", "13.0.1.1",
3035 "4001:11::1", "5001:11::1")
3036 sep3.add_vpp_config()
3037 # this EP is not installed immediately
3038 sep4 = VppGbpEndpoint(self, self.pg6,
3040 "12.0.1.2", "13.0.1.2",
3041 "4001:11::2", "5001:11::2")
3044 # an L2 switch packet between local EPs in different EPGs
3045 # different dest ports on each so the are LB hashed differently
3047 p4 = [(Ether(src=ep1.mac, dst=ep3.mac) /
3048 IP(src=ep1.ip4.address, dst=ep3.ip4.address) /
3049 UDP(sport=1234, dport=1234) /
3051 (Ether(src=ep3.mac, dst=ep1.mac) /
3052 IP(src=ep3.ip4.address, dst=ep1.ip4.address) /
3053 UDP(sport=1234, dport=1234) /
3055 p6 = [(Ether(src=ep1.mac, dst=ep3.mac) /
3056 IPv6(src=ep1.ip6.address, dst=ep3.ip6.address) /
3057 UDP(sport=1234, dport=1234) /
3059 (Ether(src=ep3.mac, dst=ep1.mac) /
3060 IPv6(src=ep3.ip6.address, dst=ep1.ip6.address) /
3061 UDP(sport=1234, dport=1230) /
3064 # should be dropped since no contract yet
3065 self.send_and_assert_no_replies(self.pg0, [p4[0]])
3066 self.send_and_assert_no_replies(self.pg0, [p6[0]])
3069 # Add a contract with a rule to load-balance redirect via SEP1 and SEP2
3070 # one of the next-hops is via an EP that is not known
3072 acl = VppGbpAcl(self)
3073 rule4 = acl.create_rule(permit_deny=1, proto=17)
3074 rule6 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
3075 acl_index = acl.add_vpp_config([rule4, rule6])
3078 # test the src-ip hash mode
3080 c1 = VppGbpContract(
3081 self, epg_220.sclass, epg_222.sclass, acl_index,
3082 [VppGbpContractRule(
3083 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3084 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3085 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3086 sep1.ip4, sep1.epg.rd),
3087 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3088 sep2.ip4, sep2.epg.rd)]),
3090 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3091 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3092 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3093 sep3.ip6, sep3.epg.rd),
3094 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3095 sep4.ip6, sep4.epg.rd)])],
3096 [ETH_P_IP, ETH_P_IPV6])
3099 c2 = VppGbpContract(
3100 self, epg_222.sclass, epg_220.sclass, acl_index,
3101 [VppGbpContractRule(
3102 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3103 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3104 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3105 sep1.ip4, sep1.epg.rd),
3106 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3107 sep2.ip4, sep2.epg.rd)]),
3109 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3110 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3111 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3112 sep3.ip6, sep3.epg.rd),
3113 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3114 sep4.ip6, sep4.epg.rd)])],
3115 [ETH_P_IP, ETH_P_IPV6])
3119 # send again with the contract preset, now packets arrive
3120 # at SEP1 or SEP2 depending on the hashing
3122 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3125 self.assertEqual(rx[Ether].src, routed_src_mac)
3126 self.assertEqual(rx[Ether].dst, sep1.mac)
3127 self.assertEqual(rx[IP].src, ep1.ip4.address)
3128 self.assertEqual(rx[IP].dst, ep3.ip4.address)
3130 rxs = self.send_and_expect(self.pg2, p4[1] * 17, sep2.itf)
3133 self.assertEqual(rx[Ether].src, routed_src_mac)
3134 self.assertEqual(rx[Ether].dst, sep2.mac)
3135 self.assertEqual(rx[IP].src, ep3.ip4.address)
3136 self.assertEqual(rx[IP].dst, ep1.ip4.address)
3138 rxs = self.send_and_expect(self.pg0, p6[0] * 17, self.pg7)
3141 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3142 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3143 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3144 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
3145 self.assertEqual(rx[VXLAN].vni, 117)
3146 self.assertTrue(rx[VXLAN].flags.G)
3147 self.assertTrue(rx[VXLAN].flags.Instance)
3148 # redirect policy has been applied
3149 self.assertTrue(rx[VXLAN].gpflags.A)
3150 self.assertFalse(rx[VXLAN].gpflags.D)
3152 inner = rx[VXLAN].payload
3154 self.assertEqual(inner[Ether].src, routed_src_mac)
3155 self.assertEqual(inner[Ether].dst, sep4.mac)
3156 self.assertEqual(inner[IPv6].src, ep1.ip6.address)
3157 self.assertEqual(inner[IPv6].dst, ep3.ip6.address)
3159 rxs = self.send_and_expect(self.pg2, p6[1] * 17, sep3.itf)
3162 self.assertEqual(rx[Ether].src, routed_src_mac)
3163 self.assertEqual(rx[Ether].dst, sep3.mac)
3164 self.assertEqual(rx[IPv6].src, ep3.ip6.address)
3165 self.assertEqual(rx[IPv6].dst, ep1.ip6.address)
3168 # programme the unknown EP
3170 sep4.add_vpp_config()
3172 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep4.itf)
3175 self.assertEqual(rx[Ether].src, routed_src_mac)
3176 self.assertEqual(rx[Ether].dst, sep4.mac)
3177 self.assertEqual(rx[IPv6].src, ep1.ip6.address)
3178 self.assertEqual(rx[IPv6].dst, ep3.ip6.address)
3181 # and revert back to unprogrammed
3183 sep4.remove_vpp_config()
3185 rxs = self.send_and_expect(self.pg0, p6[0] * 17, self.pg7)
3188 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3189 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3190 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3191 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
3192 self.assertEqual(rx[VXLAN].vni, 117)
3193 self.assertTrue(rx[VXLAN].flags.G)
3194 self.assertTrue(rx[VXLAN].flags.Instance)
3195 # redirect policy has been applied
3196 self.assertTrue(rx[VXLAN].gpflags.A)
3197 self.assertFalse(rx[VXLAN].gpflags.D)
3199 inner = rx[VXLAN].payload
3201 self.assertEqual(inner[Ether].src, routed_src_mac)
3202 self.assertEqual(inner[Ether].dst, sep4.mac)
3203 self.assertEqual(inner[IPv6].src, ep1.ip6.address)
3204 self.assertEqual(inner[IPv6].dst, ep3.ip6.address)
3206 c1.remove_vpp_config()
3207 c2.remove_vpp_config()
3210 # test the symmetric hash mode
3212 c1 = VppGbpContract(
3213 self, epg_220.sclass, epg_222.sclass, acl_index,
3214 [VppGbpContractRule(
3215 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3216 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3217 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3218 sep1.ip4, sep1.epg.rd),
3219 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3220 sep2.ip4, sep2.epg.rd)]),
3222 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3223 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3224 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3225 sep3.ip6, sep3.epg.rd),
3226 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3227 sep4.ip6, sep4.epg.rd)])],
3228 [ETH_P_IP, ETH_P_IPV6])
3231 c2 = VppGbpContract(
3232 self, epg_222.sclass, epg_220.sclass, acl_index,
3233 [VppGbpContractRule(
3234 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3235 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3236 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3237 sep1.ip4, sep1.epg.rd),
3238 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3239 sep2.ip4, sep2.epg.rd)]),
3241 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3242 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3243 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3244 sep3.ip6, sep3.epg.rd),
3245 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3246 sep4.ip6, sep4.epg.rd)])],
3247 [ETH_P_IP, ETH_P_IPV6])
3251 # send again with the contract preset, now packets arrive
3252 # at SEP1 for both directions
3254 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3257 self.assertEqual(rx[Ether].src, routed_src_mac)
3258 self.assertEqual(rx[Ether].dst, sep1.mac)
3259 self.assertEqual(rx[IP].src, ep1.ip4.address)
3260 self.assertEqual(rx[IP].dst, ep3.ip4.address)
3262 rxs = self.send_and_expect(self.pg2, p4[1] * 17, sep1.itf)
3265 self.assertEqual(rx[Ether].src, routed_src_mac)
3266 self.assertEqual(rx[Ether].dst, sep1.mac)
3267 self.assertEqual(rx[IP].src, ep3.ip4.address)
3268 self.assertEqual(rx[IP].dst, ep1.ip4.address)
3271 # programme the unknown EP for the L3 tests
3273 sep4.add_vpp_config()
3276 # an L3 switch packet between local EPs in different EPGs
3277 # different dest ports on each so the are LB hashed differently
3279 p4 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3280 IP(src=ep1.ip4.address, dst=ep2.ip4.address) /
3281 UDP(sport=1234, dport=1234) /
3283 (Ether(src=ep2.mac, dst=str(self.router_mac)) /
3284 IP(src=ep2.ip4.address, dst=ep1.ip4.address) /
3285 UDP(sport=1234, dport=1234) /
3287 p6 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3288 IPv6(src=ep1.ip6.address, dst=ep2.ip6.address) /
3289 UDP(sport=1234, dport=1234) /
3291 (Ether(src=ep2.mac, dst=str(self.router_mac)) /
3292 IPv6(src=ep2.ip6.address, dst=ep1.ip6.address) /
3293 UDP(sport=1234, dport=1234) /
3296 c3 = VppGbpContract(
3297 self, epg_220.sclass, epg_221.sclass, acl_index,
3298 [VppGbpContractRule(
3299 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3300 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3301 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3302 sep1.ip4, sep1.epg.rd),
3303 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3304 sep2.ip4, sep2.epg.rd)]),
3306 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3307 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3308 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3309 sep3.ip6, sep3.epg.rd),
3310 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3311 sep4.ip6, sep4.epg.rd)])],
3312 [ETH_P_IP, ETH_P_IPV6])
3315 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3318 self.assertEqual(rx[Ether].src, routed_src_mac)
3319 self.assertEqual(rx[Ether].dst, sep1.mac)
3320 self.assertEqual(rx[IP].src, ep1.ip4.address)
3321 self.assertEqual(rx[IP].dst, ep2.ip4.address)
3324 # learn a remote EP in EPG 221
3326 vx_tun_l3 = VppGbpVxlanTunnel(
3327 self, 444, rd1.rd_id,
3328 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
3330 vx_tun_l3.add_vpp_config()
3332 c4 = VppGbpContract(
3333 self, epg_221.sclass, epg_220.sclass, acl_index,
3334 [VppGbpContractRule(
3335 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3338 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3340 [ETH_P_IP, ETH_P_IPV6])
3343 p = (Ether(src=self.pg7.remote_mac,
3344 dst=self.pg7.local_mac) /
3345 IP(src=self.pg7.remote_ip4,
3346 dst=self.pg7.local_ip4) /
3347 UDP(sport=1234, dport=48879) /
3348 VXLAN(vni=444, gpid=441, flags=0x88) /
3349 Ether(src="00:22:22:22:22:33", dst=str(self.router_mac)) /
3350 IP(src="10.0.0.88", dst=ep1.ip4.address) /
3351 UDP(sport=1234, dport=1234) /
3354 rx = self.send_and_expect(self.pg7, [p], self.pg0)
3356 # endpoint learnt via the parent GBP-vxlan interface
3357 self.assertTrue(find_gbp_endpoint(self,
3358 vx_tun_l3._sw_if_index,
3361 p = (Ether(src=self.pg7.remote_mac,
3362 dst=self.pg7.local_mac) /
3363 IP(src=self.pg7.remote_ip4,
3364 dst=self.pg7.local_ip4) /
3365 UDP(sport=1234, dport=48879) /
3366 VXLAN(vni=444, gpid=441, flags=0x88) /
3367 Ether(src="00:22:22:22:22:33", dst=str(self.router_mac)) /
3368 IPv6(src="2001:10::88", dst=ep1.ip6.address) /
3369 UDP(sport=1234, dport=1234) /
3372 rx = self.send_and_expect(self.pg7, [p], self.pg0)
3374 # endpoint learnt via the parent GBP-vxlan interface
3375 self.assertTrue(find_gbp_endpoint(self,
3376 vx_tun_l3._sw_if_index,
3380 # L3 switch from local to remote EP
3382 p4 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3383 IP(src=ep1.ip4.address, dst="10.0.0.88") /
3384 UDP(sport=1234, dport=1234) /
3386 p6 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3387 IPv6(src=ep1.ip6.address, dst="2001:10::88") /
3388 UDP(sport=1234, dport=1234) /
3391 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3394 self.assertEqual(rx[Ether].src, routed_src_mac)
3395 self.assertEqual(rx[Ether].dst, sep1.mac)
3396 self.assertEqual(rx[IP].src, ep1.ip4.address)
3397 self.assertEqual(rx[IP].dst, "10.0.0.88")
3399 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep4.itf)
3402 self.assertEqual(rx[Ether].src, routed_src_mac)
3403 self.assertEqual(rx[Ether].dst, sep4.mac)
3404 self.assertEqual(rx[IPv6].src, ep1.ip6.address)
3405 self.assertEqual(rx[IPv6].dst, "2001:10::88")
3408 # test the dst-ip hash mode
3410 c5 = VppGbpContract(
3411 self, epg_220.sclass, epg_221.sclass, acl_index,
3412 [VppGbpContractRule(
3413 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3414 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
3415 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3416 sep1.ip4, sep1.epg.rd),
3417 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3418 sep2.ip4, sep2.epg.rd)]),
3420 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3421 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
3422 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3423 sep3.ip6, sep3.epg.rd),
3424 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3425 sep4.ip6, sep4.epg.rd)])],
3426 [ETH_P_IP, ETH_P_IPV6])
3429 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3432 self.assertEqual(rx[Ether].src, routed_src_mac)
3433 self.assertEqual(rx[Ether].dst, sep1.mac)
3434 self.assertEqual(rx[IP].src, ep1.ip4.address)
3435 self.assertEqual(rx[IP].dst, "10.0.0.88")
3437 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep3.itf)
3440 self.assertEqual(rx[Ether].src, routed_src_mac)
3441 self.assertEqual(rx[Ether].dst, sep3.mac)
3442 self.assertEqual(rx[IPv6].src, ep1.ip6.address)
3443 self.assertEqual(rx[IPv6].dst, "2001:10::88")
3448 self.pg7.unconfig_ip4()
3450 def test_gbp_l3_out(self):
3453 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
3454 self.vapi.cli("set logging class gbp level debug")
3456 routed_dst_mac = "00:0c:0c:0c:0c:0c"
3457 routed_src_mac = "00:22:bd:f8:19:ff"
3462 t4 = VppIpTable(self, 1)
3464 t6 = VppIpTable(self, 1, True)
3467 rd1 = VppGbpRouteDomain(self, 2, t4, t6)
3468 rd1.add_vpp_config()
3470 self.loop0.set_mac(self.router_mac)
3473 # Bind the BVI to the RD
3475 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
3476 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
3479 # Pg7 hosts a BD's BUM
3480 # Pg1 some other l3 interface
3482 self.pg7.config_ip4()
3483 self.pg7.resolve_arp()
3486 # a multicast vxlan-gbp tunnel for broadcast in the BD
3488 tun_bm = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
3491 tun_bm.add_vpp_config()
3494 # a GBP external bridge domains for the EPs
3496 bd1 = VppBridgeDomain(self, 1)
3497 bd1.add_vpp_config()
3498 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0, None, tun_bm)
3499 gbd1.add_vpp_config()
3502 # The Endpoint-groups in which the external endpoints exist
3504 epg_220 = VppGbpEndpointGroup(self, 220, 113, rd1, gbd1,
3508 VppGbpEndpointRetention(2))
3509 epg_220.add_vpp_config()
3511 # the BVIs have the subnets applied ...
3512 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 24)
3513 ip4_addr.add_vpp_config()
3514 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 64)
3515 ip6_addr.add_vpp_config()
3517 # ... which are L3-out subnets
3518 l3o_1 = VppGbpSubnet(
3519 self, rd1, "10.0.0.0", 24,
3520 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3522 l3o_1.add_vpp_config()
3525 # an external interface attached to the outside world and the
3528 vlan_100 = VppDot1QSubint(self, self.pg0, 100)
3530 VppL2Vtr(self, vlan_100, L2_VTR_OP.L2_POP_1).add_vpp_config()
3531 vlan_101 = VppDot1QSubint(self, self.pg0, 101)
3533 VppL2Vtr(self, vlan_101, L2_VTR_OP.L2_POP_1).add_vpp_config()
3534 # vlan_102 is not poped
3535 vlan_102 = VppDot1QSubint(self, self.pg0, 102)
3538 ext_itf = VppGbpExtItf(self, self.loop0, bd1, rd1)
3539 ext_itf.add_vpp_config()
3542 # an unicast vxlan-gbp for inter-RD traffic
3544 vx_tun_l3 = VppGbpVxlanTunnel(
3545 self, 444, rd1.rd_id,
3546 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
3548 vx_tun_l3.add_vpp_config()
3551 # External Endpoints
3553 eep1 = VppGbpEndpoint(self, vlan_100,
3555 "10.0.0.1", "11.0.0.1",
3556 "2001:10::1", "3001::1",
3557 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
3558 eep1.add_vpp_config()
3559 eep2 = VppGbpEndpoint(self, vlan_101,
3561 "10.0.0.2", "11.0.0.2",
3562 "2001:10::2", "3001::2",
3563 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
3564 eep2.add_vpp_config()
3565 eep3 = VppGbpEndpoint(self, vlan_102,
3567 "10.0.0.3", "11.0.0.3",
3568 "2001:10::3", "3001::3",
3569 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
3570 eep3.add_vpp_config()
3573 # A remote external endpoint
3575 rep = VppGbpEndpoint(self, vx_tun_l3,
3577 "10.0.0.101", "11.0.0.101",
3578 "2001:10::101", "3001::101",
3579 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
3581 self.pg7.remote_ip4,
3583 rep.add_vpp_config()
3586 # ARP packet from External EPs are accepted and replied to
3588 p_arp = (Ether(src=eep1.mac, dst="ff:ff:ff:ff:ff:ff") /
3591 psrc=eep1.ip4.address, pdst="10.0.0.128",
3592 hwsrc=eep1.mac, hwdst="ff:ff:ff:ff:ff:ff"))
3593 rxs = self.send_and_expect(self.pg0, p_arp * 1, self.pg0)
3596 # ARP packet from host in remote subnet are accepted and replied to
3598 p_arp = (Ether(src=vlan_102.remote_mac, dst="ff:ff:ff:ff:ff:ff") /
3601 psrc="10.0.0.17", pdst="10.0.0.128",
3602 hwsrc=vlan_102.remote_mac, hwdst="ff:ff:ff:ff:ff:ff"))
3603 rxs = self.send_and_expect(self.pg0, p_arp * 1, self.pg0)
3606 # packets destined to unknown addresses in the BVI's subnet
3609 p4 = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3611 IP(src="10.0.0.1", dst="10.0.0.88") /
3612 UDP(sport=1234, dport=1234) /
3614 p6 = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3616 IPv6(src="2001:10::1", dst="2001:10::88") /
3617 UDP(sport=1234, dport=1234) /
3620 rxs = self.send_and_expect(self.pg0, p4 * 1, self.pg7)
3623 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3624 # self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3625 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3626 self.assertEqual(rx[IP].dst, "239.1.1.1")
3627 self.assertEqual(rx[VXLAN].vni, 88)
3628 self.assertTrue(rx[VXLAN].flags.G)
3629 self.assertTrue(rx[VXLAN].flags.Instance)
3630 # policy was applied to the original IP packet
3631 self.assertEqual(rx[VXLAN].gpid, 113)
3632 self.assertTrue(rx[VXLAN].gpflags.A)
3633 self.assertFalse(rx[VXLAN].gpflags.D)
3635 inner = rx[VXLAN].payload
3637 self.assertTrue(inner.haslayer(ARP))
3640 # remote to external
3642 p = (Ether(src=self.pg7.remote_mac,
3643 dst=self.pg7.local_mac) /
3644 IP(src=self.pg7.remote_ip4,
3645 dst=self.pg7.local_ip4) /
3646 UDP(sport=1234, dport=48879) /
3647 VXLAN(vni=444, gpid=113, flags=0x88) /
3648 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
3649 IP(src="10.0.0.101", dst="10.0.0.1") /
3650 UDP(sport=1234, dport=1234) /
3653 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
3656 # local EP pings router
3658 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3660 IP(src=eep1.ip4.address, dst="10.0.0.128") /
3661 ICMP(type='echo-request'))
3663 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
3666 self.assertEqual(rx[Ether].src, str(self.router_mac))
3667 self.assertEqual(rx[Ether].dst, eep1.mac)
3668 self.assertEqual(rx[Dot1Q].vlan, 100)
3671 # local EP pings other local EP
3673 p = (Ether(src=eep1.mac, dst=eep2.mac) /
3675 IP(src=eep1.ip4.address, dst=eep2.ip4.address) /
3676 ICMP(type='echo-request'))
3678 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
3681 self.assertEqual(rx[Ether].src, eep1.mac)
3682 self.assertEqual(rx[Ether].dst, eep2.mac)
3683 self.assertEqual(rx[Dot1Q].vlan, 101)
3686 # local EP pings router w/o vlan tag poped
3688 p = (Ether(src=eep3.mac, dst=str(self.router_mac)) /
3690 IP(src=eep3.ip4.address, dst="10.0.0.128") /
3691 ICMP(type='echo-request'))
3693 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
3696 self.assertEqual(rx[Ether].src, str(self.router_mac))
3697 self.assertEqual(rx[Ether].dst, vlan_102.remote_mac)
3700 # A subnet reachable through the external EP1
3702 ip_220 = VppIpRoute(self, "10.220.0.0", 24,
3703 [VppRoutePath(eep1.ip4.address,
3704 eep1.epg.bvi.sw_if_index)],
3705 table_id=t4.table_id)
3706 ip_220.add_vpp_config()
3708 l3o_220 = VppGbpSubnet(
3709 self, rd1, "10.220.0.0", 24,
3710 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3712 l3o_220.add_vpp_config()
3715 # A subnet reachable through the external EP2
3717 ip_221 = VppIpRoute(self, "10.221.0.0", 24,
3718 [VppRoutePath(eep2.ip4.address,
3719 eep2.epg.bvi.sw_if_index)],
3720 table_id=t4.table_id)
3721 ip_221.add_vpp_config()
3723 l3o_221 = VppGbpSubnet(
3724 self, rd1, "10.221.0.0", 24,
3725 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3727 l3o_221.add_vpp_config()
3730 # ping between hosts in remote subnets
3731 # dropped without a contract
3733 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3735 IP(src="10.220.0.1", dst="10.221.0.1") /
3736 ICMP(type='echo-request'))
3738 rxs = self.send_and_assert_no_replies(self.pg0, p * 1)
3741 # contract for the external nets to communicate
3743 acl = VppGbpAcl(self)
3744 rule4 = acl.create_rule(permit_deny=1, proto=17)
3745 rule6 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
3746 acl_index = acl.add_vpp_config([rule4, rule6])
3748 c1 = VppGbpContract(
3749 self, 4220, 4221, acl_index,
3750 [VppGbpContractRule(
3751 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3754 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3756 [ETH_P_IP, ETH_P_IPV6])
3760 # Contracts allowing ext-net 200 to talk with external EPs
3762 c2 = VppGbpContract(
3763 self, 4220, 113, acl_index,
3764 [VppGbpContractRule(
3765 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3768 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3770 [ETH_P_IP, ETH_P_IPV6])
3772 c3 = VppGbpContract(
3773 self, 113, 4220, acl_index,
3774 [VppGbpContractRule(
3775 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3778 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3780 [ETH_P_IP, ETH_P_IPV6])
3784 # ping between hosts in remote subnets
3786 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3788 IP(src="10.220.0.1", dst="10.221.0.1") /
3789 UDP(sport=1234, dport=1234) /
3792 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
3795 self.assertEqual(rx[Ether].src, str(self.router_mac))
3796 self.assertEqual(rx[Ether].dst, eep2.mac)
3797 self.assertEqual(rx[Dot1Q].vlan, 101)
3799 # we did not learn these external hosts
3800 self.assertFalse(find_gbp_endpoint(self, ip="10.220.0.1"))
3801 self.assertFalse(find_gbp_endpoint(self, ip="10.221.0.1"))
3804 # from remote external EP to local external EP
3806 p = (Ether(src=self.pg7.remote_mac,
3807 dst=self.pg7.local_mac) /
3808 IP(src=self.pg7.remote_ip4,
3809 dst=self.pg7.local_ip4) /
3810 UDP(sport=1234, dport=48879) /
3811 VXLAN(vni=444, gpid=113, flags=0x88) /
3812 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
3813 IP(src="10.0.0.101", dst="10.220.0.1") /
3814 UDP(sport=1234, dport=1234) /
3817 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
3820 # ping from an external host to the remote external EP
3822 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3824 IP(src="10.220.0.1", dst=rep.ip4.address) /
3825 UDP(sport=1234, dport=1234) /
3828 rxs = self.send_and_expect(self.pg0, p * 1, self.pg7)
3831 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3832 # self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3833 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3834 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
3835 self.assertEqual(rx[VXLAN].vni, 444)
3836 self.assertTrue(rx[VXLAN].flags.G)
3837 self.assertTrue(rx[VXLAN].flags.Instance)
3838 # the sclass of the ext-net the packet came from
3839 self.assertEqual(rx[VXLAN].gpid, 4220)
3840 # policy was applied to the original IP packet
3841 self.assertTrue(rx[VXLAN].gpflags.A)
3842 # since it's an external host the reciever should not learn it
3843 self.assertTrue(rx[VXLAN].gpflags.D)
3844 inner = rx[VXLAN].payload
3845 self.assertEqual(inner[IP].src, "10.220.0.1")
3846 self.assertEqual(inner[IP].dst, rep.ip4.address)
3849 # An external subnet reachable via the remote external EP
3853 # first the VXLAN-GBP tunnel over which it is reached
3855 vx_tun_r = VppVxlanGbpTunnel(
3856 self, self.pg7.local_ip4,
3857 self.pg7.remote_ip4, 445,
3858 mode=(VppEnum.vl_api_vxlan_gbp_api_tunnel_mode_t.
3859 VXLAN_GBP_API_TUNNEL_MODE_L3))
3860 vx_tun_r.add_vpp_config()
3861 VppIpInterfaceBind(self, vx_tun_r, t4).add_vpp_config()
3863 self.logger.info(self.vapi.cli("sh vxlan-gbp tunnel"))
3866 # then the special adj to resolve through on that tunnel
3868 n1 = VppNeighbor(self,
3869 vx_tun_r.sw_if_index,
3870 "00:0c:0c:0c:0c:0c",
3871 self.pg7.remote_ip4)
3875 # the route via the adj above
3877 ip_222 = VppIpRoute(self, "10.222.0.0", 24,
3878 [VppRoutePath(self.pg7.remote_ip4,
3879 vx_tun_r.sw_if_index)],
3880 table_id=t4.table_id)
3881 ip_222.add_vpp_config()
3883 l3o_222 = VppGbpSubnet(
3884 self, rd1, "10.222.0.0", 24,
3885 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3887 l3o_222.add_vpp_config()
3890 # ping between hosts in local and remote external subnets
3891 # dropped without a contract
3893 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3895 IP(src="10.220.0.1", dst="10.222.0.1") /
3896 UDP(sport=1234, dport=1234) /
3899 rxs = self.send_and_assert_no_replies(self.pg0, p * 1)
3902 # Add contracts ext-nets for 220 -> 222
3904 c4 = VppGbpContract(
3905 self, 4220, 4222, acl_index,
3906 [VppGbpContractRule(
3907 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3910 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3912 [ETH_P_IP, ETH_P_IPV6])
3916 # ping from host in local to remote external subnets
3918 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3920 IP(src="10.220.0.1", dst="10.222.0.1") /
3921 UDP(sport=1234, dport=1234) /
3924 rxs = self.send_and_expect(self.pg0, p * 3, self.pg7)
3927 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3928 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3929 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3930 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
3931 self.assertEqual(rx[VXLAN].vni, 445)
3932 self.assertTrue(rx[VXLAN].flags.G)
3933 self.assertTrue(rx[VXLAN].flags.Instance)
3934 # the sclass of the ext-net the packet came from
3935 self.assertEqual(rx[VXLAN].gpid, 4220)
3936 # policy was applied to the original IP packet
3937 self.assertTrue(rx[VXLAN].gpflags.A)
3938 # since it's an external host the reciever should not learn it
3939 self.assertTrue(rx[VXLAN].gpflags.D)
3940 inner = rx[VXLAN].payload
3941 self.assertEqual(inner[Ether].dst, "00:0c:0c:0c:0c:0c")
3942 self.assertEqual(inner[IP].src, "10.220.0.1")
3943 self.assertEqual(inner[IP].dst, "10.222.0.1")
3946 # ping from host in remote to local external subnets
3947 # there's no contract for this, but the A bit is set.
3949 p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
3950 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
3951 UDP(sport=1234, dport=48879) /
3952 VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
3953 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
3954 IP(src="10.222.0.1", dst="10.220.0.1") /
3955 UDP(sport=1234, dport=1234) /
3958 rxs = self.send_and_expect(self.pg7, p * 3, self.pg0)
3959 self.assertFalse(find_gbp_endpoint(self, ip="10.222.0.1"))
3962 # ping from host in remote to remote external subnets
3963 # this is dropped by reflection check.
3965 p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
3966 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
3967 UDP(sport=1234, dport=48879) /
3968 VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
3969 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
3970 IP(src="10.222.0.1", dst="10.222.0.2") /
3971 UDP(sport=1234, dport=1234) /
3974 rxs = self.send_and_assert_no_replies(self.pg7, p * 3)
3979 self.pg7.unconfig_ip4()
3980 vlan_100.set_vtr(L2_VTR_OP.L2_DISABLED)
3983 if __name__ == '__main__':
3984 unittest.main(testRunner=VppTestRunner)