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, fip)
923 # floating IPs route via EPG recirc
925 self, fip.address, fip.length,
926 [VppRoutePath(fip.address,
927 ep.recirc.recirc.sw_if_index,
928 type=FibPathType.FIB_PATH_TYPE_DVR,
929 proto=fip.dpo_proto)],
933 # L2 FIB entries in the NAT EPG BD to bridge the packets from
934 # the outside direct to the internal EPG
935 lf = VppL2FibEntry(self, epg_nat.bd.bd, ep.mac,
936 ep.recirc.recirc, bvi_mac=0)
940 # ARP packets for unknown IP are sent to the EPG uplink
942 pkt_arp = (Ether(dst="ff:ff:ff:ff:ff:ff",
943 src=self.pg0.remote_mac) /
945 hwdst="ff:ff:ff:ff:ff:ff",
946 hwsrc=self.pg0.remote_mac,
950 self.vapi.cli("clear trace")
951 self.pg0.add_stream(pkt_arp)
953 self.pg_enable_capture(self.pg_interfaces)
956 rxd = epgs[0].uplink.get_capture(1)
959 # ARP/ND packets get a response
961 pkt_arp = (Ether(dst="ff:ff:ff:ff:ff:ff",
962 src=self.pg0.remote_mac) /
964 hwdst="ff:ff:ff:ff:ff:ff",
965 hwsrc=self.pg0.remote_mac,
966 pdst=epgs[0].bvi_ip4.address,
967 psrc=eps[0].ip4.address))
969 self.send_and_expect(self.pg0, [pkt_arp], self.pg0)
971 nsma = in6_getnsma(inet_pton(AF_INET6, eps[0].ip6.address))
972 d = inet_ntop(AF_INET6, nsma)
973 pkt_nd = (Ether(dst=in6_getnsmac(nsma),
974 src=self.pg0.remote_mac) /
975 IPv6(dst=d, src=eps[0].ip6.address) /
976 ICMPv6ND_NS(tgt=epgs[0].bvi_ip6.address) /
977 ICMPv6NDOptSrcLLAddr(lladdr=self.pg0.remote_mac))
978 self.send_and_expect(self.pg0, [pkt_nd], self.pg0)
981 # broadcast packets are flooded
983 pkt_bcast = (Ether(dst="ff:ff:ff:ff:ff:ff",
984 src=self.pg0.remote_mac) /
985 IP(src=eps[0].ip4.address, dst="232.1.1.1") /
986 UDP(sport=1234, dport=1234) /
989 self.vapi.cli("clear trace")
990 self.pg0.add_stream(pkt_bcast)
992 self.pg_enable_capture(self.pg_interfaces)
995 rxd = eps[1].itf.get_capture(1)
996 self.assertEqual(rxd[0][Ether].dst, pkt_bcast[Ether].dst)
997 rxd = epgs[0].uplink.get_capture(1)
998 self.assertEqual(rxd[0][Ether].dst, pkt_bcast[Ether].dst)
1001 # packets to non-local L3 destinations dropped
1003 pkt_intra_epg_220_ip4 = (Ether(src=self.pg0.remote_mac,
1004 dst=str(self.router_mac)) /
1005 IP(src=eps[0].ip4.address,
1007 UDP(sport=1234, dport=1234) /
1009 pkt_inter_epg_222_ip4 = (Ether(src=self.pg0.remote_mac,
1010 dst=str(self.router_mac)) /
1011 IP(src=eps[0].ip4.address,
1013 UDP(sport=1234, dport=1234) /
1016 self.send_and_assert_no_replies(self.pg0,
1017 pkt_intra_epg_220_ip4 * NUM_PKTS)
1019 pkt_inter_epg_222_ip6 = (Ether(src=self.pg0.remote_mac,
1020 dst=str(self.router_mac)) /
1021 IPv6(src=eps[0].ip6.address,
1022 dst="2001:10::99") /
1023 UDP(sport=1234, dport=1234) /
1025 self.send_and_assert_no_replies(self.pg0,
1026 pkt_inter_epg_222_ip6 * NUM_PKTS)
1029 # Add the subnet routes
1032 self, rd0, "10.0.0.0", 24,
1033 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1035 self, rd0, "10.0.1.0", 24,
1036 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1038 self, rd0, "10.0.2.0", 24,
1039 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1041 self, rd0, "2001:10::1", 64,
1042 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1044 self, rd0, "2001:10:1::1", 64,
1045 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1047 self, rd0, "2001:10:2::1", 64,
1048 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1049 s41.add_vpp_config()
1050 s42.add_vpp_config()
1051 s43.add_vpp_config()
1052 s61.add_vpp_config()
1053 s62.add_vpp_config()
1054 s63.add_vpp_config()
1056 self.send_and_expect_bridged(eps[0].itf,
1057 pkt_intra_epg_220_ip4 * NUM_PKTS,
1059 self.send_and_expect_bridged(eps[0].itf,
1060 pkt_inter_epg_222_ip4 * NUM_PKTS,
1062 self.send_and_expect_bridged6(eps[0].itf,
1063 pkt_inter_epg_222_ip6 * NUM_PKTS,
1066 self.logger.info(self.vapi.cli("sh ip fib 11.0.0.2"))
1067 self.logger.info(self.vapi.cli("sh gbp endpoint-group"))
1068 self.logger.info(self.vapi.cli("sh gbp endpoint"))
1069 self.logger.info(self.vapi.cli("sh gbp recirc"))
1070 self.logger.info(self.vapi.cli("sh int"))
1071 self.logger.info(self.vapi.cli("sh int addr"))
1072 self.logger.info(self.vapi.cli("sh int feat loop6"))
1073 self.logger.info(self.vapi.cli("sh vlib graph ip4-gbp-src-classify"))
1074 self.logger.info(self.vapi.cli("sh int feat loop3"))
1075 self.logger.info(self.vapi.cli("sh int feat pg0"))
1078 # Packet destined to unknown unicast is sent on the epg uplink ...
1080 pkt_intra_epg_220_to_uplink = (Ether(src=self.pg0.remote_mac,
1081 dst="00:00:00:33:44:55") /
1082 IP(src=eps[0].ip4.address,
1084 UDP(sport=1234, dport=1234) /
1087 self.send_and_expect_bridged(eps[0].itf,
1088 pkt_intra_epg_220_to_uplink * NUM_PKTS,
1090 # ... and nowhere else
1091 self.pg1.get_capture(0, timeout=0.1)
1092 self.pg1.assert_nothing_captured(remark="Flood onto other VMS")
1094 pkt_intra_epg_221_to_uplink = (Ether(src=self.pg2.remote_mac,
1095 dst="00:00:00:33:44:66") /
1096 IP(src=eps[0].ip4.address,
1098 UDP(sport=1234, dport=1234) /
1101 self.send_and_expect_bridged(eps[2].itf,
1102 pkt_intra_epg_221_to_uplink * NUM_PKTS,
1106 # Packets from the uplink are forwarded in the absence of a contract
1108 pkt_intra_epg_220_from_uplink = (Ether(src="00:00:00:33:44:55",
1109 dst=self.pg0.remote_mac) /
1110 IP(src=eps[0].ip4.address,
1112 UDP(sport=1234, dport=1234) /
1115 self.send_and_expect_bridged(self.pg4,
1116 pkt_intra_epg_220_from_uplink * NUM_PKTS,
1120 # in the absence of policy, endpoints in the same EPG
1123 pkt_intra_epg = (Ether(src=self.pg0.remote_mac,
1124 dst=self.pg1.remote_mac) /
1125 IP(src=eps[0].ip4.address,
1126 dst=eps[1].ip4.address) /
1127 UDP(sport=1234, dport=1234) /
1130 self.send_and_expect_bridged(self.pg0,
1131 pkt_intra_epg * NUM_PKTS,
1135 # in the absence of policy, endpoints in the different EPG
1136 # cannot communicate
1138 pkt_inter_epg_220_to_221 = (Ether(src=self.pg0.remote_mac,
1139 dst=self.pg2.remote_mac) /
1140 IP(src=eps[0].ip4.address,
1141 dst=eps[2].ip4.address) /
1142 UDP(sport=1234, dport=1234) /
1144 pkt_inter_epg_221_to_220 = (Ether(src=self.pg2.remote_mac,
1145 dst=self.pg0.remote_mac) /
1146 IP(src=eps[2].ip4.address,
1147 dst=eps[0].ip4.address) /
1148 UDP(sport=1234, dport=1234) /
1150 pkt_inter_epg_220_to_222 = (Ether(src=self.pg0.remote_mac,
1151 dst=str(self.router_mac)) /
1152 IP(src=eps[0].ip4.address,
1153 dst=eps[3].ip4.address) /
1154 UDP(sport=1234, dport=1234) /
1157 self.send_and_assert_no_replies(eps[0].itf,
1158 pkt_inter_epg_220_to_221 * NUM_PKTS)
1159 self.send_and_assert_no_replies(eps[0].itf,
1160 pkt_inter_epg_220_to_222 * NUM_PKTS)
1163 # A uni-directional contract from EPG 220 -> 221
1165 acl = VppGbpAcl(self)
1166 rule = acl.create_rule(permit_deny=1, proto=17)
1167 rule2 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
1168 acl_index = acl.add_vpp_config([rule, rule2])
1169 c1 = VppGbpContract(
1170 self, epgs[0].sclass, epgs[1].sclass, acl_index,
1171 [VppGbpContractRule(
1172 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1175 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1177 [ETH_P_IP, ETH_P_IPV6])
1180 self.send_and_expect_bridged(eps[0].itf,
1181 pkt_inter_epg_220_to_221 * NUM_PKTS,
1183 self.send_and_assert_no_replies(eps[0].itf,
1184 pkt_inter_epg_220_to_222 * NUM_PKTS)
1187 # contract for the return direction
1189 c2 = VppGbpContract(
1190 self, epgs[1].sclass, epgs[0].sclass, acl_index,
1191 [VppGbpContractRule(
1192 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1195 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1197 [ETH_P_IP, ETH_P_IPV6])
1200 self.send_and_expect_bridged(eps[0].itf,
1201 pkt_inter_epg_220_to_221 * NUM_PKTS,
1203 self.send_and_expect_bridged(eps[2].itf,
1204 pkt_inter_epg_221_to_220 * NUM_PKTS,
1207 ds = c2.get_drop_stats()
1208 self.assertEqual(ds['packets'], 0)
1209 ps = c2.get_permit_stats()
1210 self.assertEqual(ps['packets'], NUM_PKTS)
1213 # the contract does not allow non-IP
1215 pkt_non_ip_inter_epg_220_to_221 = (Ether(src=self.pg0.remote_mac,
1216 dst=self.pg2.remote_mac) /
1218 self.send_and_assert_no_replies(eps[0].itf,
1219 pkt_non_ip_inter_epg_220_to_221 * 17)
1222 # check that inter group is still disabled for the groups
1223 # not in the contract.
1225 self.send_and_assert_no_replies(eps[0].itf,
1226 pkt_inter_epg_220_to_222 * NUM_PKTS)
1229 # A uni-directional contract from EPG 220 -> 222 'L3 routed'
1231 c3 = VppGbpContract(
1232 self, epgs[0].sclass, epgs[2].sclass, acl_index,
1233 [VppGbpContractRule(
1234 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1237 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1239 [ETH_P_IP, ETH_P_IPV6])
1242 self.logger.info(self.vapi.cli("sh gbp contract"))
1244 self.send_and_expect_routed(eps[0].itf,
1245 pkt_inter_epg_220_to_222 * NUM_PKTS,
1247 str(self.router_mac))
1250 # remove both contracts, traffic stops in both directions
1252 c2.remove_vpp_config()
1253 c1.remove_vpp_config()
1254 c3.remove_vpp_config()
1255 acl.remove_vpp_config()
1257 self.send_and_assert_no_replies(eps[2].itf,
1258 pkt_inter_epg_221_to_220 * NUM_PKTS)
1259 self.send_and_assert_no_replies(eps[0].itf,
1260 pkt_inter_epg_220_to_221 * NUM_PKTS)
1261 self.send_and_expect_bridged(eps[0].itf,
1262 pkt_intra_epg * NUM_PKTS,
1266 # EPs to the outside world
1269 # in the EP's RD an external subnet via the NAT EPG's recirc
1271 self, rd0, "0.0.0.0", 0,
1272 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1273 sw_if_index=recirc_nat.recirc.sw_if_index,
1274 sclass=epg_nat.sclass)
1276 self, rd0, "11.0.0.0", 8,
1277 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1278 sw_if_index=recirc_nat.recirc.sw_if_index,
1279 sclass=epg_nat.sclass)
1280 se16 = VppGbpSubnet(
1282 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1283 sw_if_index=recirc_nat.recirc.sw_if_index,
1284 sclass=epg_nat.sclass)
1285 # in the NAT RD an external subnet via the NAT EPG's uplink
1287 self, rd20, "0.0.0.0", 0,
1288 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1289 sw_if_index=epg_nat.uplink.sw_if_index,
1290 sclass=epg_nat.sclass)
1291 se36 = VppGbpSubnet(
1292 self, rd20, "::", 0,
1293 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1294 sw_if_index=epg_nat.uplink.sw_if_index,
1295 sclass=epg_nat.sclass)
1297 self, rd20, "11.0.0.0", 8,
1298 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1299 sw_if_index=epg_nat.uplink.sw_if_index,
1300 sclass=epg_nat.sclass)
1301 se1.add_vpp_config()
1302 se2.add_vpp_config()
1303 se16.add_vpp_config()
1304 se3.add_vpp_config()
1305 se36.add_vpp_config()
1306 se4.add_vpp_config()
1308 self.logger.info(self.vapi.cli("sh ip fib 0.0.0.0/0"))
1309 self.logger.info(self.vapi.cli("sh ip fib 11.0.0.1"))
1310 self.logger.info(self.vapi.cli("sh ip6 fib ::/0"))
1311 self.logger.info(self.vapi.cli("sh ip6 fib %s" %
1315 # From an EP to an outside address: IN2OUT
1317 pkt_inter_epg_220_to_global = (Ether(src=self.pg0.remote_mac,
1318 dst=str(self.router_mac)) /
1319 IP(src=eps[0].ip4.address,
1321 UDP(sport=1234, dport=1234) /
1325 self.send_and_assert_no_replies(eps[0].itf,
1326 pkt_inter_epg_220_to_global * NUM_PKTS)
1328 acl2 = VppGbpAcl(self)
1329 rule = acl2.create_rule(permit_deny=1, proto=17, sport_from=1234,
1330 sport_to=1234, dport_from=1234, dport_to=1234)
1331 rule2 = acl2.create_rule(is_ipv6=1, permit_deny=1, proto=17,
1332 sport_from=1234, sport_to=1234,
1333 dport_from=1234, dport_to=1234)
1335 acl_index2 = acl2.add_vpp_config([rule, rule2])
1336 c4 = VppGbpContract(
1337 self, epgs[0].sclass, epgs[3].sclass, acl_index2,
1338 [VppGbpContractRule(
1339 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1342 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1344 [ETH_P_IP, ETH_P_IPV6])
1347 self.send_and_expect_natted(eps[0].itf,
1348 pkt_inter_epg_220_to_global * NUM_PKTS,
1350 eps[0].fip4.address)
1352 pkt_inter_epg_220_to_global = (Ether(src=self.pg0.remote_mac,
1353 dst=str(self.router_mac)) /
1354 IPv6(src=eps[0].ip6.address,
1356 UDP(sport=1234, dport=1234) /
1359 self.send_and_expect_natted6(self.pg0,
1360 pkt_inter_epg_220_to_global * NUM_PKTS,
1362 eps[0].fip6.address)
1365 # From a global address to an EP: OUT2IN
1367 pkt_inter_epg_220_from_global = (Ether(src=str(self.router_mac),
1368 dst=self.pg0.remote_mac) /
1369 IP(dst=eps[0].fip4.address,
1371 UDP(sport=1234, dport=1234) /
1374 self.send_and_assert_no_replies(
1375 self.pg7, pkt_inter_epg_220_from_global * NUM_PKTS)
1377 c5 = VppGbpContract(
1378 self, epgs[3].sclass, epgs[0].sclass, acl_index2,
1379 [VppGbpContractRule(
1380 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1383 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1385 [ETH_P_IP, ETH_P_IPV6])
1388 self.send_and_expect_unnatted(self.pg7,
1389 pkt_inter_epg_220_from_global * NUM_PKTS,
1393 pkt_inter_epg_220_from_global = (Ether(src=str(self.router_mac),
1394 dst=self.pg0.remote_mac) /
1395 IPv6(dst=eps[0].fip6.address,
1397 UDP(sport=1234, dport=1234) /
1400 self.send_and_expect_unnatted6(
1402 pkt_inter_epg_220_from_global * NUM_PKTS,
1407 # From a local VM to another local VM using resp. public addresses:
1410 pkt_intra_epg_220_global = (Ether(src=self.pg0.remote_mac,
1411 dst=str(self.router_mac)) /
1412 IP(src=eps[0].ip4.address,
1413 dst=eps[1].fip4.address) /
1414 UDP(sport=1234, dport=1234) /
1417 self.send_and_expect_double_natted(eps[0].itf,
1418 pkt_intra_epg_220_global * NUM_PKTS,
1420 eps[0].fip4.address,
1423 pkt_intra_epg_220_global = (Ether(src=self.pg0.remote_mac,
1424 dst=str(self.router_mac)) /
1425 IPv6(src=eps[0].ip6.address,
1426 dst=eps[1].fip6.address) /
1427 UDP(sport=1234, dport=1234) /
1430 self.send_and_expect_double_natted6(
1432 pkt_intra_epg_220_global * NUM_PKTS,
1434 eps[0].fip6.address,
1441 # del static mappings for each EP from the 10/8 to 11/8 network
1442 flags = self.config_flags.NAT_IS_ADDR_ONLY
1443 self.vapi.nat44_add_del_static_mapping(
1445 local_ip_address=ep.ip4.bytes,
1446 external_ip_address=ep.fip4.bytes,
1447 external_sw_if_index=0xFFFFFFFF,
1450 self.vapi.nat66_add_del_static_mapping(
1451 local_ip_address=ep.ip6.bytes,
1452 external_ip_address=ep.fip6.bytes,
1456 # IP config on the BVI interfaces
1457 if epg != epgs[0] and epg != epgs[3]:
1458 flags = self.config_flags.NAT_IS_INSIDE
1459 self.vapi.nat44_interface_add_del_feature(
1460 sw_if_index=epg.bvi.sw_if_index,
1463 self.vapi.nat66_add_del_interface(
1464 is_add=0, flags=flags,
1465 sw_if_index=epg.bvi.sw_if_index)
1467 for recirc in recircs:
1468 self.vapi.nat44_interface_add_del_feature(
1469 sw_if_index=recirc.recirc.sw_if_index,
1471 self.vapi.nat66_add_del_interface(
1473 sw_if_index=recirc.recirc.sw_if_index)
1475 def wait_for_ep_timeout(self, sw_if_index=None, ip=None, mac=None,
1476 n_tries=100, s_time=1):
1478 if not find_gbp_endpoint(self, sw_if_index, ip, mac):
1480 n_tries = n_tries - 1
1482 self.assertFalse(find_gbp_endpoint(self, sw_if_index, ip, mac))
1485 def test_gbp_learn_l2(self):
1486 """ GBP L2 Endpoint Learning """
1488 self.vapi.cli("clear errors")
1490 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
1491 learnt = [{'mac': '00:00:11:11:11:01',
1493 'ip6': '2001:10::2'},
1494 {'mac': '00:00:11:11:11:02',
1496 'ip6': '2001:10::3'}]
1501 gt4 = VppIpTable(self, 1)
1502 gt4.add_vpp_config()
1503 gt6 = VppIpTable(self, 1, is_ip6=True)
1504 gt6.add_vpp_config()
1506 rd1 = VppGbpRouteDomain(self, 1, gt4, gt6)
1507 rd1.add_vpp_config()
1510 # Pg2 hosts the vxlan tunnel, hosts on pg2 to act as TEPs
1511 # Pg3 hosts the IP4 UU-flood VXLAN tunnel
1512 # Pg4 hosts the IP6 UU-flood VXLAN tunnel
1514 self.pg2.config_ip4()
1515 self.pg2.resolve_arp()
1516 self.pg2.generate_remote_hosts(4)
1517 self.pg2.configure_ipv4_neighbors()
1518 self.pg3.config_ip4()
1519 self.pg3.resolve_arp()
1520 self.pg4.config_ip4()
1521 self.pg4.resolve_arp()
1524 # Add a mcast destination VXLAN-GBP tunnel for B&M traffic
1526 tun_bm = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
1529 tun_bm.add_vpp_config()
1532 # a GBP bridge domain with a BVI and a UU-flood interface
1534 bd1 = VppBridgeDomain(self, 1)
1535 bd1.add_vpp_config()
1536 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0, self.pg3, tun_bm)
1537 gbd1.add_vpp_config()
1539 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1540 self.logger.info(self.vapi.cli("sh gbp bridge"))
1542 # ... and has a /32 applied
1543 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
1544 ip_addr.add_vpp_config()
1547 # The Endpoint-group in which we are learning endpoints
1549 epg_220 = VppGbpEndpointGroup(self, 220, 112, rd1, gbd1,
1553 VppGbpEndpointRetention(2))
1554 epg_220.add_vpp_config()
1555 epg_330 = VppGbpEndpointGroup(self, 330, 113, rd1, gbd1,
1559 VppGbpEndpointRetention(2))
1560 epg_330.add_vpp_config()
1563 # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
1566 vx_tun_l2_1 = VppGbpVxlanTunnel(
1567 self, 99, bd1.bd_id,
1568 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L2,
1570 vx_tun_l2_1.add_vpp_config()
1573 # A static endpoint that the learnt endpoints are trying to
1576 ep = VppGbpEndpoint(self, self.pg0,
1578 "10.0.0.127", "11.0.0.127",
1579 "2001:10::1", "3001::1")
1582 self.assertTrue(find_route(self, ep.ip4.address, 32, table_id=1))
1584 # a packet with an sclass from an unknown EPG
1585 p = (Ether(src=self.pg2.remote_mac,
1586 dst=self.pg2.local_mac) /
1587 IP(src=self.pg2.remote_hosts[0].ip4,
1588 dst=self.pg2.local_ip4) /
1589 UDP(sport=1234, dport=48879) /
1590 VXLAN(vni=99, gpid=88, flags=0x88) /
1591 Ether(src=learnt[0]["mac"], dst=ep.mac) /
1592 IP(src=learnt[0]["ip"], dst=ep.ip4.address) /
1593 UDP(sport=1234, dport=1234) /
1596 self.send_and_assert_no_replies(self.pg2, p)
1598 self.logger.info(self.vapi.cli("sh error"))
1599 # self.assert_packet_counter_equal(
1600 # '/err/gbp-policy-port/drop-no-contract', 1)
1603 # we should not have learnt a new tunnel endpoint, since
1604 # the EPG was not learnt.
1606 self.assertEqual(INDEX_INVALID,
1607 find_vxlan_gbp_tunnel(self,
1609 self.pg2.remote_hosts[0].ip4,
1612 # epg is not learnt, because the EPG is unknown
1613 self.assertEqual(len(self.vapi.gbp_endpoint_dump()), 1)
1616 # Learn new EPs from IP packets
1618 for ii, l in enumerate(learnt):
1619 # a packet with an sclass from a known EPG
1620 # arriving on an unknown TEP
1621 p = (Ether(src=self.pg2.remote_mac,
1622 dst=self.pg2.local_mac) /
1623 IP(src=self.pg2.remote_hosts[1].ip4,
1624 dst=self.pg2.local_ip4) /
1625 UDP(sport=1234, dport=48879) /
1626 VXLAN(vni=99, gpid=112, flags=0x88) /
1627 Ether(src=l['mac'], dst=ep.mac) /
1628 IP(src=l['ip'], dst=ep.ip4.address) /
1629 UDP(sport=1234, dport=1234) /
1632 rx = self.send_and_expect(self.pg2, [p], self.pg0)
1635 tep1_sw_if_index = find_vxlan_gbp_tunnel(
1638 self.pg2.remote_hosts[1].ip4,
1640 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
1643 # the EP is learnt via the learnt TEP
1644 # both from its MAC and its IP
1646 self.assertTrue(find_gbp_endpoint(self,
1647 vx_tun_l2_1.sw_if_index,
1649 self.assertTrue(find_gbp_endpoint(self,
1650 vx_tun_l2_1.sw_if_index,
1653 # self.assert_packet_counter_equal(
1654 # '/err/gbp-policy-port/allow-intra-sclass', 2)
1656 self.logger.info(self.vapi.cli("show gbp endpoint"))
1657 self.logger.info(self.vapi.cli("show gbp vxlan"))
1658 self.logger.info(self.vapi.cli("show ip mfib"))
1661 # If we sleep for the threshold time, the learnt endpoints should
1665 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1669 # Learn new EPs from GARP packets received on the BD's mcast tunnel
1671 for ii, l in enumerate(learnt):
1672 # a packet with an sclass from a known EPG
1673 # arriving on an unknown TEP
1674 p = (Ether(src=self.pg2.remote_mac,
1675 dst=self.pg2.local_mac) /
1676 IP(src=self.pg2.remote_hosts[1].ip4,
1678 UDP(sport=1234, dport=48879) /
1679 VXLAN(vni=88, gpid=112, flags=0x88) /
1680 Ether(src=l['mac'], dst="ff:ff:ff:ff:ff:ff") /
1682 psrc=l['ip'], pdst=l['ip'],
1683 hwsrc=l['mac'], hwdst="ff:ff:ff:ff:ff:ff"))
1685 rx = self.send_and_expect(self.pg4, [p], self.pg0)
1688 tep1_sw_if_index = find_vxlan_gbp_tunnel(
1691 self.pg2.remote_hosts[1].ip4,
1693 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
1696 # the EP is learnt via the learnt TEP
1697 # both from its MAC and its IP
1699 self.assertTrue(find_gbp_endpoint(self,
1700 vx_tun_l2_1.sw_if_index,
1702 self.assertTrue(find_gbp_endpoint(self,
1703 vx_tun_l2_1.sw_if_index,
1707 # wait for the learnt endpoints to age out
1710 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1714 # Learn new EPs from L2 packets
1716 for ii, l in enumerate(learnt):
1717 # a packet with an sclass from a known EPG
1718 # arriving on an unknown TEP
1719 p = (Ether(src=self.pg2.remote_mac,
1720 dst=self.pg2.local_mac) /
1721 IP(src=self.pg2.remote_hosts[1].ip4,
1722 dst=self.pg2.local_ip4) /
1723 UDP(sport=1234, dport=48879) /
1724 VXLAN(vni=99, gpid=112, flags=0x88) /
1725 Ether(src=l['mac'], dst=ep.mac) /
1728 rx = self.send_and_expect(self.pg2, [p], self.pg0)
1731 tep1_sw_if_index = find_vxlan_gbp_tunnel(
1734 self.pg2.remote_hosts[1].ip4,
1736 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
1739 # the EP is learnt via the learnt TEP
1740 # both from its MAC and its IP
1742 self.assertTrue(find_gbp_endpoint(self,
1743 vx_tun_l2_1.sw_if_index,
1746 self.logger.info(self.vapi.cli("show gbp endpoint"))
1747 self.logger.info(self.vapi.cli("show gbp vxlan"))
1748 self.logger.info(self.vapi.cli("show vxlan-gbp tunnel"))
1751 # wait for the learnt endpoints to age out
1754 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1758 # repeat. the do not learn bit is set so the EPs are not learnt
1761 # a packet with an sclass from a known EPG
1762 p = (Ether(src=self.pg2.remote_mac,
1763 dst=self.pg2.local_mac) /
1764 IP(src=self.pg2.remote_hosts[1].ip4,
1765 dst=self.pg2.local_ip4) /
1766 UDP(sport=1234, dport=48879) /
1767 VXLAN(vni=99, gpid=112, flags=0x88, gpflags="D") /
1768 Ether(src=l['mac'], dst=ep.mac) /
1769 IP(src=l['ip'], dst=ep.ip4.address) /
1770 UDP(sport=1234, dport=1234) /
1773 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
1776 self.assertFalse(find_gbp_endpoint(self,
1777 vx_tun_l2_1.sw_if_index,
1784 # a packet with an sclass from a known EPG
1785 p = (Ether(src=self.pg2.remote_mac,
1786 dst=self.pg2.local_mac) /
1787 IP(src=self.pg2.remote_hosts[1].ip4,
1788 dst=self.pg2.local_ip4) /
1789 UDP(sport=1234, dport=48879) /
1790 VXLAN(vni=99, gpid=112, flags=0x88) /
1791 Ether(src=l['mac'], dst=ep.mac) /
1792 IP(src=l['ip'], dst=ep.ip4.address) /
1793 UDP(sport=1234, dport=1234) /
1796 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
1798 self.assertTrue(find_gbp_endpoint(self,
1799 vx_tun_l2_1.sw_if_index,
1803 # Static EP replies to dynamics
1805 self.logger.info(self.vapi.cli("sh l2fib bd_id 1"))
1807 p = (Ether(src=ep.mac, dst=l['mac']) /
1808 IP(dst=l['ip'], src=ep.ip4.address) /
1809 UDP(sport=1234, dport=1234) /
1812 rxs = self.send_and_expect(self.pg0, p * 17, self.pg2)
1815 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
1816 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
1817 self.assertEqual(rx[UDP].dport, 48879)
1818 # the UDP source port is a random value for hashing
1819 self.assertEqual(rx[VXLAN].gpid, 112)
1820 self.assertEqual(rx[VXLAN].vni, 99)
1821 self.assertTrue(rx[VXLAN].flags.G)
1822 self.assertTrue(rx[VXLAN].flags.Instance)
1823 self.assertTrue(rx[VXLAN].gpflags.A)
1824 self.assertFalse(rx[VXLAN].gpflags.D)
1827 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1831 # repeat in the other EPG
1832 # there's no contract between 220 and 330, but the A-bit is set
1833 # so the packet is cleared for delivery
1836 # a packet with an sclass from a known EPG
1837 p = (Ether(src=self.pg2.remote_mac,
1838 dst=self.pg2.local_mac) /
1839 IP(src=self.pg2.remote_hosts[1].ip4,
1840 dst=self.pg2.local_ip4) /
1841 UDP(sport=1234, dport=48879) /
1842 VXLAN(vni=99, gpid=113, flags=0x88, gpflags='A') /
1843 Ether(src=l['mac'], dst=ep.mac) /
1844 IP(src=l['ip'], dst=ep.ip4.address) /
1845 UDP(sport=1234, dport=1234) /
1848 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
1850 self.assertTrue(find_gbp_endpoint(self,
1851 vx_tun_l2_1.sw_if_index,
1855 # static EP cannot reach the learnt EPs since there is no contract
1856 # only test 1 EP as the others could timeout
1858 p = (Ether(src=ep.mac, dst=l['mac']) /
1859 IP(dst=learnt[0]['ip'], src=ep.ip4.address) /
1860 UDP(sport=1234, dport=1234) /
1863 self.send_and_assert_no_replies(self.pg0, [p])
1866 # refresh the entries after the check for no replies above
1869 # a packet with an sclass from a known EPG
1870 p = (Ether(src=self.pg2.remote_mac,
1871 dst=self.pg2.local_mac) /
1872 IP(src=self.pg2.remote_hosts[1].ip4,
1873 dst=self.pg2.local_ip4) /
1874 UDP(sport=1234, dport=48879) /
1875 VXLAN(vni=99, gpid=113, flags=0x88, gpflags='A') /
1876 Ether(src=l['mac'], dst=ep.mac) /
1877 IP(src=l['ip'], dst=ep.ip4.address) /
1878 UDP(sport=1234, dport=1234) /
1881 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
1883 self.assertTrue(find_gbp_endpoint(self,
1884 vx_tun_l2_1.sw_if_index,
1888 # Add the contract so they can talk
1890 acl = VppGbpAcl(self)
1891 rule = acl.create_rule(permit_deny=1, proto=17)
1892 rule2 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
1893 acl_index = acl.add_vpp_config([rule, rule2])
1894 c1 = VppGbpContract(
1895 self, epg_220.sclass, epg_330.sclass, acl_index,
1896 [VppGbpContractRule(
1897 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1900 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1902 [ETH_P_IP, ETH_P_IPV6])
1906 p = (Ether(src=ep.mac, dst=l['mac']) /
1907 IP(dst=l['ip'], src=ep.ip4.address) /
1908 UDP(sport=1234, dport=1234) /
1911 self.send_and_expect(self.pg0, [p], self.pg2)
1914 # send UU packets from the local EP
1916 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1917 self.logger.info(self.vapi.cli("sh gbp bridge"))
1918 p_uu = (Ether(src=ep.mac, dst="00:11:11:11:11:11") /
1919 IP(dst="10.0.0.133", src=ep.ip4.address) /
1920 UDP(sport=1234, dport=1234) /
1922 rxs = self.send_and_expect(ep.itf, [p_uu], gbd1.uu_fwd)
1924 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1926 p_bm = (Ether(src=ep.mac, dst="ff:ff:ff:ff:ff:ff") /
1927 IP(dst="10.0.0.133", src=ep.ip4.address) /
1928 UDP(sport=1234, dport=1234) /
1930 rxs = self.send_and_expect_only(ep.itf, [p_bm], tun_bm.mcast_itf)
1933 self.assertEqual(rx[IP].src, self.pg4.local_ip4)
1934 self.assertEqual(rx[IP].dst, "239.1.1.1")
1935 self.assertEqual(rx[UDP].dport, 48879)
1936 # the UDP source port is a random value for hashing
1937 self.assertEqual(rx[VXLAN].gpid, 112)
1938 self.assertEqual(rx[VXLAN].vni, 88)
1939 self.assertTrue(rx[VXLAN].flags.G)
1940 self.assertTrue(rx[VXLAN].flags.Instance)
1941 self.assertFalse(rx[VXLAN].gpflags.A)
1942 self.assertFalse(rx[VXLAN].gpflags.D)
1945 # Check v6 Endpoints
1948 # a packet with an sclass from a known EPG
1949 p = (Ether(src=self.pg2.remote_mac,
1950 dst=self.pg2.local_mac) /
1951 IP(src=self.pg2.remote_hosts[1].ip4,
1952 dst=self.pg2.local_ip4) /
1953 UDP(sport=1234, dport=48879) /
1954 VXLAN(vni=99, gpid=113, flags=0x88, gpflags='A') /
1955 Ether(src=l['mac'], dst=ep.mac) /
1956 IPv6(src=l['ip6'], dst=ep.ip6.address) /
1957 UDP(sport=1234, dport=1234) /
1960 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
1962 self.assertTrue(find_gbp_endpoint(self,
1963 vx_tun_l2_1.sw_if_index,
1967 # L3 Endpoint Learning
1968 # - configured on the bridge's BVI
1975 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1977 self.pg2.unconfig_ip4()
1978 self.pg3.unconfig_ip4()
1979 self.pg4.unconfig_ip4()
1981 self.logger.info(self.vapi.cli("sh int"))
1982 self.logger.info(self.vapi.cli("sh gbp vxlan"))
1984 def test_gbp_contract(self):
1985 """ GBP CONTRACTS """
1990 bd1 = VppBridgeDomain(self, 1, arp_term=0)
1991 bd2 = VppBridgeDomain(self, 2, arp_term=0)
1993 bd1.add_vpp_config()
1994 bd2.add_vpp_config()
1996 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0)
1997 gbd2 = VppGbpBridgeDomain(self, bd2, self.loop1)
1999 gbd1.add_vpp_config()
2000 gbd2.add_vpp_config()
2005 gt4 = VppIpTable(self, 0)
2006 gt4.add_vpp_config()
2007 gt6 = VppIpTable(self, 0, is_ip6=True)
2008 gt6.add_vpp_config()
2010 rd0 = VppGbpRouteDomain(self, 0, gt4, gt6, None, None)
2012 rd0.add_vpp_config()
2015 # 3 EPGs, 2 of which share a BD.
2017 epgs = [VppGbpEndpointGroup(self, 220, 1220, rd0, gbd1,
2019 "10.0.0.128", "2001:10::128"),
2020 VppGbpEndpointGroup(self, 221, 1221, rd0, gbd1,
2022 "10.0.1.128", "2001:10:1::128"),
2023 VppGbpEndpointGroup(self, 222, 1222, rd0, gbd2,
2025 "10.0.2.128", "2001:10:2::128")]
2027 # 4 end-points, 2 in the same subnet, 3 in the same BD
2029 eps = [VppGbpEndpoint(self, self.pg0,
2031 "10.0.0.1", "11.0.0.1",
2032 "2001:10::1", "3001::1"),
2033 VppGbpEndpoint(self, self.pg1,
2035 "10.0.0.2", "11.0.0.2",
2036 "2001:10::2", "3001::2"),
2037 VppGbpEndpoint(self, self.pg2,
2039 "10.0.1.1", "11.0.0.3",
2040 "2001:10:1::1", "3001::3"),
2041 VppGbpEndpoint(self, self.pg3,
2043 "10.0.2.1", "11.0.0.4",
2044 "2001:10:2::1", "3001::4")]
2047 # Config related to each of the EPGs
2050 # IP config on the BVI interfaces
2052 VppIpInterfaceBind(self, epg.bvi, epg.rd.t4).add_vpp_config()
2053 VppIpInterfaceBind(self, epg.bvi, epg.rd.t6).add_vpp_config()
2054 self.vapi.sw_interface_set_mac_address(
2055 epg.bvi.sw_if_index,
2056 self.router_mac.packed)
2058 if_ip4 = VppIpInterfaceAddress(self, epg.bvi, epg.bvi_ip4, 32)
2059 if_ip6 = VppIpInterfaceAddress(self, epg.bvi, epg.bvi_ip6, 128)
2060 if_ip4.add_vpp_config()
2061 if_ip6.add_vpp_config()
2063 # add the BD ARP termination entry for BVI IP
2064 epg.bd_arp_ip4 = VppBridgeDomainArpEntry(self, epg.bd.bd,
2065 str(self.router_mac),
2067 epg.bd_arp_ip4.add_vpp_config()
2070 epg.add_vpp_config()
2078 self.logger.info(self.vapi.cli("show gbp endpoint"))
2079 self.logger.info(self.vapi.cli("show interface"))
2080 self.logger.info(self.vapi.cli("show br"))
2083 # Intra epg allowed without contract
2085 pkt_intra_epg_220_to_220 = (Ether(src=self.pg0.remote_mac,
2086 dst=self.pg1.remote_mac) /
2087 IP(src=eps[0].ip4.address,
2088 dst=eps[1].ip4.address) /
2089 UDP(sport=1234, dport=1234) /
2092 self.send_and_expect_bridged(self.pg0,
2093 pkt_intra_epg_220_to_220 * 65,
2097 # Inter epg denied without contract
2099 pkt_inter_epg_220_to_221 = (Ether(src=self.pg0.remote_mac,
2100 dst=self.pg2.remote_mac) /
2101 IP(src=eps[0].ip4.address,
2102 dst=eps[2].ip4.address) /
2103 UDP(sport=1234, dport=1234) /
2106 self.send_and_assert_no_replies(self.pg0, pkt_inter_epg_220_to_221)
2109 # A uni-directional contract from EPG 220 -> 221
2111 acl = VppGbpAcl(self)
2112 rule = acl.create_rule(permit_deny=1, proto=17)
2113 rule2 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
2114 acl_index = acl.add_vpp_config([rule, rule2])
2115 c1 = VppGbpContract(
2116 self, epgs[0].sclass, epgs[1].sclass, acl_index,
2117 [VppGbpContractRule(
2118 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2121 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2123 [ETH_P_IP, ETH_P_IPV6])
2126 self.send_and_expect_bridged(eps[0].itf,
2127 pkt_inter_epg_220_to_221 * 65,
2130 pkt_inter_epg_220_to_222 = (Ether(src=self.pg0.remote_mac,
2131 dst=str(self.router_mac)) /
2132 IP(src=eps[0].ip4.address,
2133 dst=eps[3].ip4.address) /
2134 UDP(sport=1234, dport=1234) /
2136 self.send_and_assert_no_replies(eps[0].itf,
2137 pkt_inter_epg_220_to_222 * 65)
2140 # contract for the return direction
2142 c2 = VppGbpContract(
2143 self, epgs[1].sclass, epgs[0].sclass, acl_index,
2144 [VppGbpContractRule(
2145 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2148 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2150 [ETH_P_IP, ETH_P_IPV6])
2153 self.send_and_expect_bridged(eps[0].itf,
2154 pkt_inter_epg_220_to_221 * 65,
2156 pkt_inter_epg_221_to_220 = (Ether(src=self.pg2.remote_mac,
2157 dst=self.pg0.remote_mac) /
2158 IP(src=eps[2].ip4.address,
2159 dst=eps[0].ip4.address) /
2160 UDP(sport=1234, dport=1234) /
2162 self.send_and_expect_bridged(eps[2].itf,
2163 pkt_inter_epg_221_to_220 * 65,
2167 # contract between 220 and 222 uni-direction
2169 c3 = VppGbpContract(
2170 self, epgs[0].sclass, epgs[2].sclass, acl_index,
2171 [VppGbpContractRule(
2172 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2175 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2177 [ETH_P_IP, ETH_P_IPV6])
2180 self.send_and_expect(eps[0].itf,
2181 pkt_inter_epg_220_to_222 * 65,
2184 c3.remove_vpp_config()
2185 c1.remove_vpp_config()
2186 c2.remove_vpp_config()
2187 acl.remove_vpp_config()
2189 def test_gbp_bd_flags(self):
2190 """ GBP BD FLAGS """
2195 gt4 = VppIpTable(self, 1)
2196 gt4.add_vpp_config()
2197 gt6 = VppIpTable(self, 1, is_ip6=True)
2198 gt6.add_vpp_config()
2200 rd1 = VppGbpRouteDomain(self, 1, gt4, gt6)
2201 rd1.add_vpp_config()
2204 # Pg3 hosts the IP4 UU-flood VXLAN tunnel
2205 # Pg4 hosts the IP6 UU-flood VXLAN tunnel
2207 self.pg3.config_ip4()
2208 self.pg3.resolve_arp()
2209 self.pg4.config_ip4()
2210 self.pg4.resolve_arp()
2213 # Add a mcast destination VXLAN-GBP tunnel for B&M traffic
2215 tun_bm = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
2218 tun_bm.add_vpp_config()
2221 # a GBP bridge domain with a BVI and a UU-flood interface
2223 bd1 = VppBridgeDomain(self, 1)
2224 bd1.add_vpp_config()
2226 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0, self.pg3, tun_bm,
2227 uu_drop=True, bm_drop=True)
2228 gbd1.add_vpp_config()
2230 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2231 self.logger.info(self.vapi.cli("sh gbp bridge"))
2233 # ... and has a /32 applied
2234 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2235 ip_addr.add_vpp_config()
2238 # The Endpoint-group
2240 epg_220 = VppGbpEndpointGroup(self, 220, 112, rd1, gbd1,
2244 VppGbpEndpointRetention(2))
2245 epg_220.add_vpp_config()
2247 ep = VppGbpEndpoint(self, self.pg0,
2249 "10.0.0.127", "11.0.0.127",
2250 "2001:10::1", "3001::1")
2253 # send UU/BM packet from the local EP with UU drop and BM drop enabled
2256 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2257 self.logger.info(self.vapi.cli("sh gbp bridge"))
2258 p_uu = (Ether(src=ep.mac, dst="00:11:11:11:11:11") /
2259 IP(dst="10.0.0.133", src=ep.ip4.address) /
2260 UDP(sport=1234, dport=1234) /
2262 self.send_and_assert_no_replies(ep.itf, [p_uu])
2264 p_bm = (Ether(src=ep.mac, dst="ff:ff:ff:ff:ff:ff") /
2265 IP(dst="10.0.0.133", src=ep.ip4.address) /
2266 UDP(sport=1234, dport=1234) /
2268 self.send_and_assert_no_replies(ep.itf, [p_bm])
2270 self.pg3.unconfig_ip4()
2271 self.pg4.unconfig_ip4()
2273 self.logger.info(self.vapi.cli("sh int"))
2275 def test_gbp_learn_vlan_l2(self):
2276 """ GBP L2 Endpoint w/ VLANs"""
2278 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
2279 learnt = [{'mac': '00:00:11:11:11:01',
2281 'ip6': '2001:10::2'},
2282 {'mac': '00:00:11:11:11:02',
2284 'ip6': '2001:10::3'}]
2289 gt4 = VppIpTable(self, 1)
2290 gt4.add_vpp_config()
2291 gt6 = VppIpTable(self, 1, is_ip6=True)
2292 gt6.add_vpp_config()
2294 rd1 = VppGbpRouteDomain(self, 1, gt4, gt6)
2295 rd1.add_vpp_config()
2298 # Pg2 hosts the vxlan tunnel, hosts on pg2 to act as TEPs
2300 self.pg2.config_ip4()
2301 self.pg2.resolve_arp()
2302 self.pg2.generate_remote_hosts(4)
2303 self.pg2.configure_ipv4_neighbors()
2304 self.pg3.config_ip4()
2305 self.pg3.resolve_arp()
2308 # The EP will be on a vlan sub-interface
2310 vlan_11 = VppDot1QSubint(self, self.pg0, 11)
2312 self.vapi.l2_interface_vlan_tag_rewrite(
2313 sw_if_index=vlan_11.sw_if_index, vtr_op=L2_VTR_OP.L2_POP_1,
2316 bd_uu_fwd = VppVxlanGbpTunnel(self, self.pg3.local_ip4,
2317 self.pg3.remote_ip4, 116)
2318 bd_uu_fwd.add_vpp_config()
2321 # a GBP bridge domain with a BVI and a UU-flood interface
2322 # The BD is marked as do not learn, so no endpoints are ever
2323 # learnt in this BD.
2325 bd1 = VppBridgeDomain(self, 1)
2326 bd1.add_vpp_config()
2327 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0, bd_uu_fwd,
2329 gbd1.add_vpp_config()
2331 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2332 self.logger.info(self.vapi.cli("sh gbp bridge"))
2334 # ... and has a /32 applied
2335 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2336 ip_addr.add_vpp_config()
2339 # The Endpoint-group in which we are learning endpoints
2341 epg_220 = VppGbpEndpointGroup(self, 220, 441, rd1, gbd1,
2345 VppGbpEndpointRetention(2))
2346 epg_220.add_vpp_config()
2349 # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
2352 vx_tun_l2_1 = VppGbpVxlanTunnel(
2353 self, 99, bd1.bd_id,
2354 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L2,
2356 vx_tun_l2_1.add_vpp_config()
2359 # A static endpoint that the learnt endpoints are trying to
2362 ep = VppGbpEndpoint(self, vlan_11,
2364 "10.0.0.127", "11.0.0.127",
2365 "2001:10::1", "3001::1")
2368 self.assertTrue(find_route(self, ep.ip4.address, 32, table_id=1))
2371 # Send to the static EP
2373 for ii, l in enumerate(learnt):
2374 # a packet with an sclass from a known EPG
2375 # arriving on an unknown TEP
2376 p = (Ether(src=self.pg2.remote_mac,
2377 dst=self.pg2.local_mac) /
2378 IP(src=self.pg2.remote_hosts[1].ip4,
2379 dst=self.pg2.local_ip4) /
2380 UDP(sport=1234, dport=48879) /
2381 VXLAN(vni=99, gpid=441, flags=0x88) /
2382 Ether(src=l['mac'], dst=ep.mac) /
2383 IP(src=l['ip'], dst=ep.ip4.address) /
2384 UDP(sport=1234, dport=1234) /
2387 rxs = self.send_and_expect(self.pg2, [p], self.pg0)
2390 # packet to EP has the EP's vlan tag
2393 self.assertEqual(rx[Dot1Q].vlan, 11)
2396 # the EP is not learnt since the BD setting prevents it
2399 self.assertFalse(find_gbp_endpoint(self,
2400 vx_tun_l2_1.sw_if_index,
2402 self.assertEqual(INDEX_INVALID,
2403 find_vxlan_gbp_tunnel(
2406 self.pg2.remote_hosts[1].ip4,
2409 self.assertEqual(len(self.vapi.gbp_endpoint_dump()), 1)
2413 # we didn't learn the remotes so they are sent to the UU-fwd
2416 p = (Ether(src=ep.mac, dst=l['mac']) /
2418 IP(dst=l['ip'], src=ep.ip4.address) /
2419 UDP(sport=1234, dport=1234) /
2422 rxs = self.send_and_expect(self.pg0, p * 17, self.pg3)
2425 self.assertEqual(rx[IP].src, self.pg3.local_ip4)
2426 self.assertEqual(rx[IP].dst, self.pg3.remote_ip4)
2427 self.assertEqual(rx[UDP].dport, 48879)
2428 # the UDP source port is a random value for hashing
2429 self.assertEqual(rx[VXLAN].gpid, 441)
2430 self.assertEqual(rx[VXLAN].vni, 116)
2431 self.assertTrue(rx[VXLAN].flags.G)
2432 self.assertTrue(rx[VXLAN].flags.Instance)
2433 self.assertFalse(rx[VXLAN].gpflags.A)
2434 self.assertFalse(rx[VXLAN].gpflags.D)
2436 self.pg2.unconfig_ip4()
2437 self.pg3.unconfig_ip4()
2439 def test_gbp_learn_l3(self):
2440 """ GBP L3 Endpoint Learning """
2442 self.vapi.cli("set logging class gbp level debug")
2444 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
2445 routed_dst_mac = "00:0c:0c:0c:0c:0c"
2446 routed_src_mac = "00:22:bd:f8:19:ff"
2448 learnt = [{'mac': '00:00:11:11:11:02',
2450 'ip6': '2001:10::2'},
2451 {'mac': '00:00:11:11:11:03',
2453 'ip6': '2001:10::3'}]
2458 t4 = VppIpTable(self, 1)
2460 t6 = VppIpTable(self, 1, True)
2463 tun_ip4_uu = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
2464 self.pg4.remote_ip4, 114)
2465 tun_ip6_uu = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
2466 self.pg4.remote_ip4, 116)
2467 tun_ip4_uu.add_vpp_config()
2468 tun_ip6_uu.add_vpp_config()
2470 rd1 = VppGbpRouteDomain(self, 2, t4, t6, tun_ip4_uu, tun_ip6_uu)
2471 rd1.add_vpp_config()
2473 self.loop0.set_mac(self.router_mac)
2476 # Bind the BVI to the RD
2478 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
2479 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
2482 # Pg2 hosts the vxlan tunnel
2483 # hosts on pg2 to act as TEPs
2487 self.pg2.config_ip4()
2488 self.pg2.resolve_arp()
2489 self.pg2.generate_remote_hosts(4)
2490 self.pg2.configure_ipv4_neighbors()
2491 self.pg3.config_ip4()
2492 self.pg3.resolve_arp()
2493 self.pg4.config_ip4()
2494 self.pg4.resolve_arp()
2497 # a GBP bridge domain with a BVI and a UU-flood interface
2499 bd1 = VppBridgeDomain(self, 1)
2500 bd1.add_vpp_config()
2501 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0, self.pg3)
2502 gbd1.add_vpp_config()
2504 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2505 self.logger.info(self.vapi.cli("sh gbp bridge"))
2506 self.logger.info(self.vapi.cli("sh gbp route"))
2508 # ... and has a /32 and /128 applied
2509 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2510 ip4_addr.add_vpp_config()
2511 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 128)
2512 ip6_addr.add_vpp_config()
2515 # The Endpoint-group in which we are learning endpoints
2517 epg_220 = VppGbpEndpointGroup(self, 220, 441, rd1, gbd1,
2521 VppGbpEndpointRetention(2))
2522 epg_220.add_vpp_config()
2525 # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
2528 vx_tun_l3 = VppGbpVxlanTunnel(
2529 self, 101, rd1.rd_id,
2530 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
2532 vx_tun_l3.add_vpp_config()
2535 # A static endpoint that the learnt endpoints are trying to
2538 ep = VppGbpEndpoint(self, self.pg0,
2540 "10.0.0.127", "11.0.0.127",
2541 "2001:10::1", "3001::1")
2545 # learn some remote IPv4 EPs
2547 for ii, l in enumerate(learnt):
2548 # a packet with an sclass from a known EPG
2549 # arriving on an unknown TEP
2550 p = (Ether(src=self.pg2.remote_mac,
2551 dst=self.pg2.local_mac) /
2552 IP(src=self.pg2.remote_hosts[1].ip4,
2553 dst=self.pg2.local_ip4) /
2554 UDP(sport=1234, dport=48879) /
2555 VXLAN(vni=101, gpid=441, flags=0x88) /
2556 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2557 IP(src=l['ip'], dst=ep.ip4.address) /
2558 UDP(sport=1234, dport=1234) /
2561 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2564 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2567 self.pg2.remote_hosts[1].ip4,
2569 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2571 # endpoint learnt via the parent GBP-vxlan interface
2572 self.assertTrue(find_gbp_endpoint(self,
2573 vx_tun_l3._sw_if_index,
2577 # Static IPv4 EP replies to learnt
2580 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2581 IP(dst=l['ip'], src=ep.ip4.address) /
2582 UDP(sport=1234, dport=1234) /
2585 rxs = self.send_and_expect(self.pg0, p * 1, self.pg2)
2588 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2589 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2590 self.assertEqual(rx[UDP].dport, 48879)
2591 # the UDP source port is a random value for hashing
2592 self.assertEqual(rx[VXLAN].gpid, 441)
2593 self.assertEqual(rx[VXLAN].vni, 101)
2594 self.assertTrue(rx[VXLAN].flags.G)
2595 self.assertTrue(rx[VXLAN].flags.Instance)
2596 self.assertTrue(rx[VXLAN].gpflags.A)
2597 self.assertFalse(rx[VXLAN].gpflags.D)
2599 inner = rx[VXLAN].payload
2601 self.assertEqual(inner[Ether].src, routed_src_mac)
2602 self.assertEqual(inner[Ether].dst, routed_dst_mac)
2603 self.assertEqual(inner[IP].src, ep.ip4.address)
2604 self.assertEqual(inner[IP].dst, l['ip'])
2607 self.assertFalse(find_gbp_endpoint(self,
2612 # learn some remote IPv6 EPs
2614 for ii, l in enumerate(learnt):
2615 # a packet with an sclass from a known EPG
2616 # arriving on an unknown TEP
2617 p = (Ether(src=self.pg2.remote_mac,
2618 dst=self.pg2.local_mac) /
2619 IP(src=self.pg2.remote_hosts[1].ip4,
2620 dst=self.pg2.local_ip4) /
2621 UDP(sport=1234, dport=48879) /
2622 VXLAN(vni=101, gpid=441, flags=0x88) /
2623 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2624 IPv6(src=l['ip6'], dst=ep.ip6.address) /
2625 UDP(sport=1234, dport=1234) /
2628 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2631 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2634 self.pg2.remote_hosts[1].ip4,
2636 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2638 self.logger.info(self.vapi.cli("show gbp bridge"))
2639 self.logger.info(self.vapi.cli("show vxlan-gbp tunnel"))
2640 self.logger.info(self.vapi.cli("show gbp vxlan"))
2641 self.logger.info(self.vapi.cli("show int addr"))
2643 # endpoint learnt via the TEP
2644 self.assertTrue(find_gbp_endpoint(self, ip=l['ip6']))
2646 self.logger.info(self.vapi.cli("show gbp endpoint"))
2647 self.logger.info(self.vapi.cli("show ip fib index 1 %s" % l['ip']))
2650 # Static EP replies to learnt
2653 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2654 IPv6(dst=l['ip6'], src=ep.ip6.address) /
2655 UDP(sport=1234, dport=1234) /
2658 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
2661 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2662 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2663 self.assertEqual(rx[UDP].dport, 48879)
2664 # the UDP source port is a random value for hashing
2665 self.assertEqual(rx[VXLAN].gpid, 441)
2666 self.assertEqual(rx[VXLAN].vni, 101)
2667 self.assertTrue(rx[VXLAN].flags.G)
2668 self.assertTrue(rx[VXLAN].flags.Instance)
2669 self.assertTrue(rx[VXLAN].gpflags.A)
2670 self.assertFalse(rx[VXLAN].gpflags.D)
2672 inner = rx[VXLAN].payload
2674 self.assertEqual(inner[Ether].src, routed_src_mac)
2675 self.assertEqual(inner[Ether].dst, routed_dst_mac)
2676 self.assertEqual(inner[IPv6].src, ep.ip6.address)
2677 self.assertEqual(inner[IPv6].dst, l['ip6'])
2679 self.logger.info(self.vapi.cli("sh gbp endpoint"))
2681 self.wait_for_ep_timeout(ip=l['ip'])
2684 # Static sends to unknown EP with no route
2686 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2687 IP(dst="10.0.0.99", src=ep.ip4.address) /
2688 UDP(sport=1234, dport=1234) /
2691 self.send_and_assert_no_replies(self.pg0, [p])
2694 # Add a route to static EP's v4 and v6 subnet
2695 # packets should be sent on the v4/v6 uu=fwd interface resp.
2697 se_10_24 = VppGbpSubnet(
2698 self, rd1, "10.0.0.0", 24,
2699 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT)
2700 se_10_24.add_vpp_config()
2702 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2703 IP(dst="10.0.0.99", src=ep.ip4.address) /
2704 UDP(sport=1234, dport=1234) /
2707 rxs = self.send_and_expect(self.pg0, [p], self.pg4)
2709 self.assertEqual(rx[IP].src, self.pg4.local_ip4)
2710 self.assertEqual(rx[IP].dst, self.pg4.remote_ip4)
2711 self.assertEqual(rx[UDP].dport, 48879)
2712 # the UDP source port is a random value for hashing
2713 self.assertEqual(rx[VXLAN].gpid, 441)
2714 self.assertEqual(rx[VXLAN].vni, 114)
2715 self.assertTrue(rx[VXLAN].flags.G)
2716 self.assertTrue(rx[VXLAN].flags.Instance)
2717 # policy is not applied to packets sent to the uu-fwd interfaces
2718 self.assertFalse(rx[VXLAN].gpflags.A)
2719 self.assertFalse(rx[VXLAN].gpflags.D)
2722 # learn some remote IPv4 EPs
2724 for ii, l in enumerate(learnt):
2725 # a packet with an sclass from a known EPG
2726 # arriving on an unknown TEP
2727 p = (Ether(src=self.pg2.remote_mac,
2728 dst=self.pg2.local_mac) /
2729 IP(src=self.pg2.remote_hosts[2].ip4,
2730 dst=self.pg2.local_ip4) /
2731 UDP(sport=1234, dport=48879) /
2732 VXLAN(vni=101, gpid=441, flags=0x88) /
2733 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2734 IP(src=l['ip'], dst=ep.ip4.address) /
2735 UDP(sport=1234, dport=1234) /
2738 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2741 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2744 self.pg2.remote_hosts[2].ip4,
2746 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2748 # endpoint learnt via the parent GBP-vxlan interface
2749 self.assertTrue(find_gbp_endpoint(self,
2750 vx_tun_l3._sw_if_index,
2754 # Add a remote endpoint from the API
2756 rep_88 = VppGbpEndpoint(self, vx_tun_l3,
2758 "10.0.0.88", "11.0.0.88",
2759 "2001:10::88", "3001::88",
2760 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
2762 self.pg2.remote_hosts[1].ip4,
2764 rep_88.add_vpp_config()
2767 # Add a remote endpoint from the API that matches an existing one
2769 rep_2 = VppGbpEndpoint(self, vx_tun_l3,
2771 learnt[0]['ip'], "11.0.0.101",
2772 learnt[0]['ip6'], "3001::101",
2773 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
2775 self.pg2.remote_hosts[1].ip4,
2777 rep_2.add_vpp_config()
2780 # Add a route to the learned EP's v4 subnet
2781 # packets should be send on the v4/v6 uu=fwd interface resp.
2783 se_10_1_24 = VppGbpSubnet(
2784 self, rd1, "10.0.1.0", 24,
2785 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT)
2786 se_10_1_24.add_vpp_config()
2788 self.logger.info(self.vapi.cli("show gbp endpoint"))
2790 ips = ["10.0.0.88", learnt[0]['ip']]
2792 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2793 IP(dst=ip, src=ep.ip4.address) /
2794 UDP(sport=1234, dport=1234) /
2797 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
2800 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2801 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2802 self.assertEqual(rx[UDP].dport, 48879)
2803 # the UDP source port is a random value for hashing
2804 self.assertEqual(rx[VXLAN].gpid, 441)
2805 self.assertEqual(rx[VXLAN].vni, 101)
2806 self.assertTrue(rx[VXLAN].flags.G)
2807 self.assertTrue(rx[VXLAN].flags.Instance)
2808 self.assertTrue(rx[VXLAN].gpflags.A)
2809 self.assertFalse(rx[VXLAN].gpflags.D)
2811 inner = rx[VXLAN].payload
2813 self.assertEqual(inner[Ether].src, routed_src_mac)
2814 self.assertEqual(inner[Ether].dst, routed_dst_mac)
2815 self.assertEqual(inner[IP].src, ep.ip4.address)
2816 self.assertEqual(inner[IP].dst, ip)
2819 # remove the API remote EPs, only API sourced is gone, the DP
2820 # learnt one remains
2822 rep_88.remove_vpp_config()
2823 rep_2.remove_vpp_config()
2825 self.assertTrue(find_gbp_endpoint(self, ip=rep_2.ip4.address))
2827 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2828 IP(src=ep.ip4.address, dst=rep_2.ip4.address) /
2829 UDP(sport=1234, dport=1234) /
2831 rxs = self.send_and_expect(self.pg0, [p], self.pg2)
2833 self.assertFalse(find_gbp_endpoint(self, ip=rep_88.ip4.address))
2835 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2836 IP(src=ep.ip4.address, dst=rep_88.ip4.address) /
2837 UDP(sport=1234, dport=1234) /
2839 rxs = self.send_and_expect(self.pg0, [p], self.pg4)
2842 # to appease the testcase we cannot have the registered EP still
2843 # present (because it's DP learnt) when the TC ends so wait until
2846 self.wait_for_ep_timeout(ip=rep_88.ip4.address)
2847 self.wait_for_ep_timeout(ip=rep_2.ip4.address)
2850 # shutdown with learnt endpoint present
2852 p = (Ether(src=self.pg2.remote_mac,
2853 dst=self.pg2.local_mac) /
2854 IP(src=self.pg2.remote_hosts[1].ip4,
2855 dst=self.pg2.local_ip4) /
2856 UDP(sport=1234, dport=48879) /
2857 VXLAN(vni=101, gpid=441, flags=0x88) /
2858 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2859 IP(src=learnt[1]['ip'], dst=ep.ip4.address) /
2860 UDP(sport=1234, dport=1234) /
2863 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2865 # endpoint learnt via the parent GBP-vxlan interface
2866 self.assertTrue(find_gbp_endpoint(self,
2867 vx_tun_l3._sw_if_index,
2872 # remote endpoint becomes local
2874 self.pg2.unconfig_ip4()
2875 self.pg3.unconfig_ip4()
2876 self.pg4.unconfig_ip4()
2878 def test_gbp_redirect(self):
2879 """ GBP Endpoint Redirect """
2881 self.vapi.cli("set logging class gbp level debug")
2883 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
2884 routed_dst_mac = "00:0c:0c:0c:0c:0c"
2885 routed_src_mac = "00:22:bd:f8:19:ff"
2887 learnt = [{'mac': '00:00:11:11:11:02',
2889 'ip6': '2001:10::2'},
2890 {'mac': '00:00:11:11:11:03',
2892 'ip6': '2001:10::3'}]
2897 t4 = VppIpTable(self, 1)
2899 t6 = VppIpTable(self, 1, True)
2902 rd1 = VppGbpRouteDomain(self, 2, t4, t6)
2903 rd1.add_vpp_config()
2905 self.loop0.set_mac(self.router_mac)
2908 # Bind the BVI to the RD
2910 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
2911 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
2914 # Pg7 hosts a BD's UU-fwd
2916 self.pg7.config_ip4()
2917 self.pg7.resolve_arp()
2920 # a GBP bridge domains for the EPs
2922 bd1 = VppBridgeDomain(self, 1)
2923 bd1.add_vpp_config()
2924 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0)
2925 gbd1.add_vpp_config()
2927 bd2 = VppBridgeDomain(self, 2)
2928 bd2.add_vpp_config()
2929 gbd2 = VppGbpBridgeDomain(self, bd2, self.loop1)
2930 gbd2.add_vpp_config()
2932 # ... and has a /32 and /128 applied
2933 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2934 ip4_addr.add_vpp_config()
2935 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 128)
2936 ip6_addr.add_vpp_config()
2937 ip4_addr = VppIpInterfaceAddress(self, gbd2.bvi, "10.0.1.128", 32)
2938 ip4_addr.add_vpp_config()
2939 ip6_addr = VppIpInterfaceAddress(self, gbd2.bvi, "2001:11::128", 128)
2940 ip6_addr.add_vpp_config()
2943 # The Endpoint-groups in which we are learning endpoints
2945 epg_220 = VppGbpEndpointGroup(self, 220, 440, rd1, gbd1,
2949 VppGbpEndpointRetention(2))
2950 epg_220.add_vpp_config()
2951 epg_221 = VppGbpEndpointGroup(self, 221, 441, rd1, gbd2,
2955 VppGbpEndpointRetention(2))
2956 epg_221.add_vpp_config()
2957 epg_222 = VppGbpEndpointGroup(self, 222, 442, rd1, gbd1,
2961 VppGbpEndpointRetention(2))
2962 epg_222.add_vpp_config()
2965 # a GBP bridge domains for the SEPs
2967 bd_uu1 = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
2968 self.pg7.remote_ip4, 116)
2969 bd_uu1.add_vpp_config()
2970 bd_uu2 = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
2971 self.pg7.remote_ip4, 117)
2972 bd_uu2.add_vpp_config()
2974 bd3 = VppBridgeDomain(self, 3)
2975 bd3.add_vpp_config()
2976 gbd3 = VppGbpBridgeDomain(self, bd3, self.loop2, bd_uu1, learn=False)
2977 gbd3.add_vpp_config()
2978 bd4 = VppBridgeDomain(self, 4)
2979 bd4.add_vpp_config()
2980 gbd4 = VppGbpBridgeDomain(self, bd4, self.loop3, bd_uu2, learn=False)
2981 gbd4.add_vpp_config()
2984 # EPGs in which the service endpoints exist
2986 epg_320 = VppGbpEndpointGroup(self, 320, 550, rd1, gbd3,
2990 VppGbpEndpointRetention(2))
2991 epg_320.add_vpp_config()
2992 epg_321 = VppGbpEndpointGroup(self, 321, 551, rd1, gbd4,
2996 VppGbpEndpointRetention(2))
2997 epg_321.add_vpp_config()
3000 # three local endpoints
3002 ep1 = VppGbpEndpoint(self, self.pg0,
3004 "10.0.0.1", "11.0.0.1",
3005 "2001:10::1", "3001:10::1")
3006 ep1.add_vpp_config()
3007 ep2 = VppGbpEndpoint(self, self.pg1,
3009 "10.0.1.1", "11.0.1.1",
3010 "2001:11::1", "3001:11::1")
3011 ep2.add_vpp_config()
3012 ep3 = VppGbpEndpoint(self, self.pg2,
3014 "10.0.2.2", "11.0.2.2",
3015 "2001:12::1", "3001:12::1")
3016 ep3.add_vpp_config()
3021 sep1 = VppGbpEndpoint(self, self.pg3,
3023 "12.0.0.1", "13.0.0.1",
3024 "4001:10::1", "5001:10::1")
3025 sep1.add_vpp_config()
3026 sep2 = VppGbpEndpoint(self, self.pg4,
3028 "12.0.0.2", "13.0.0.2",
3029 "4001:10::2", "5001:10::2")
3030 sep2.add_vpp_config()
3031 sep3 = VppGbpEndpoint(self, self.pg5,
3033 "12.0.1.1", "13.0.1.1",
3034 "4001:11::1", "5001:11::1")
3035 sep3.add_vpp_config()
3036 # this EP is not installed immediately
3037 sep4 = VppGbpEndpoint(self, self.pg6,
3039 "12.0.1.2", "13.0.1.2",
3040 "4001:11::2", "5001:11::2")
3043 # an L2 switch packet between local EPs in different EPGs
3044 # different dest ports on each so the are LB hashed differently
3046 p4 = [(Ether(src=ep1.mac, dst=ep3.mac) /
3047 IP(src=ep1.ip4.address, dst=ep3.ip4.address) /
3048 UDP(sport=1234, dport=1234) /
3050 (Ether(src=ep3.mac, dst=ep1.mac) /
3051 IP(src=ep3.ip4.address, dst=ep1.ip4.address) /
3052 UDP(sport=1234, dport=1234) /
3054 p6 = [(Ether(src=ep1.mac, dst=ep3.mac) /
3055 IPv6(src=ep1.ip6.address, dst=ep3.ip6.address) /
3056 UDP(sport=1234, dport=1234) /
3058 (Ether(src=ep3.mac, dst=ep1.mac) /
3059 IPv6(src=ep3.ip6.address, dst=ep1.ip6.address) /
3060 UDP(sport=1234, dport=1230) /
3063 # should be dropped since no contract yet
3064 self.send_and_assert_no_replies(self.pg0, [p4[0]])
3065 self.send_and_assert_no_replies(self.pg0, [p6[0]])
3068 # Add a contract with a rule to load-balance redirect via SEP1 and SEP2
3069 # one of the next-hops is via an EP that is not known
3071 acl = VppGbpAcl(self)
3072 rule4 = acl.create_rule(permit_deny=1, proto=17)
3073 rule6 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
3074 acl_index = acl.add_vpp_config([rule4, rule6])
3077 # test the src-ip hash mode
3079 c1 = VppGbpContract(
3080 self, epg_220.sclass, epg_222.sclass, acl_index,
3081 [VppGbpContractRule(
3082 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3083 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3084 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3085 sep1.ip4, sep1.epg.rd),
3086 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3087 sep2.ip4, sep2.epg.rd)]),
3089 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3090 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3091 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3092 sep3.ip6, sep3.epg.rd),
3093 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3094 sep4.ip6, sep4.epg.rd)])],
3095 [ETH_P_IP, ETH_P_IPV6])
3098 c2 = VppGbpContract(
3099 self, epg_222.sclass, epg_220.sclass, acl_index,
3100 [VppGbpContractRule(
3101 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3102 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3103 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3104 sep1.ip4, sep1.epg.rd),
3105 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3106 sep2.ip4, sep2.epg.rd)]),
3108 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3109 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3110 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3111 sep3.ip6, sep3.epg.rd),
3112 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3113 sep4.ip6, sep4.epg.rd)])],
3114 [ETH_P_IP, ETH_P_IPV6])
3118 # send again with the contract preset, now packets arrive
3119 # at SEP1 or SEP2 depending on the hashing
3121 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3124 self.assertEqual(rx[Ether].src, routed_src_mac)
3125 self.assertEqual(rx[Ether].dst, sep1.mac)
3126 self.assertEqual(rx[IP].src, ep1.ip4.address)
3127 self.assertEqual(rx[IP].dst, ep3.ip4.address)
3129 rxs = self.send_and_expect(self.pg2, p4[1] * 17, sep2.itf)
3132 self.assertEqual(rx[Ether].src, routed_src_mac)
3133 self.assertEqual(rx[Ether].dst, sep2.mac)
3134 self.assertEqual(rx[IP].src, ep3.ip4.address)
3135 self.assertEqual(rx[IP].dst, ep1.ip4.address)
3137 rxs = self.send_and_expect(self.pg0, p6[0] * 17, self.pg7)
3140 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3141 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3142 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3143 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
3144 self.assertEqual(rx[VXLAN].vni, 117)
3145 self.assertTrue(rx[VXLAN].flags.G)
3146 self.assertTrue(rx[VXLAN].flags.Instance)
3147 # redirect policy has been applied
3148 self.assertTrue(rx[VXLAN].gpflags.A)
3149 self.assertFalse(rx[VXLAN].gpflags.D)
3151 inner = rx[VXLAN].payload
3153 self.assertEqual(inner[Ether].src, routed_src_mac)
3154 self.assertEqual(inner[Ether].dst, sep4.mac)
3155 self.assertEqual(inner[IPv6].src, ep1.ip6.address)
3156 self.assertEqual(inner[IPv6].dst, ep3.ip6.address)
3158 rxs = self.send_and_expect(self.pg2, p6[1] * 17, sep3.itf)
3161 self.assertEqual(rx[Ether].src, routed_src_mac)
3162 self.assertEqual(rx[Ether].dst, sep3.mac)
3163 self.assertEqual(rx[IPv6].src, ep3.ip6.address)
3164 self.assertEqual(rx[IPv6].dst, ep1.ip6.address)
3167 # programme the unknown EP
3169 sep4.add_vpp_config()
3171 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep4.itf)
3174 self.assertEqual(rx[Ether].src, routed_src_mac)
3175 self.assertEqual(rx[Ether].dst, sep4.mac)
3176 self.assertEqual(rx[IPv6].src, ep1.ip6.address)
3177 self.assertEqual(rx[IPv6].dst, ep3.ip6.address)
3180 # and revert back to unprogrammed
3182 sep4.remove_vpp_config()
3184 rxs = self.send_and_expect(self.pg0, p6[0] * 17, self.pg7)
3187 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3188 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3189 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3190 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
3191 self.assertEqual(rx[VXLAN].vni, 117)
3192 self.assertTrue(rx[VXLAN].flags.G)
3193 self.assertTrue(rx[VXLAN].flags.Instance)
3194 # redirect policy has been applied
3195 self.assertTrue(rx[VXLAN].gpflags.A)
3196 self.assertFalse(rx[VXLAN].gpflags.D)
3198 inner = rx[VXLAN].payload
3200 self.assertEqual(inner[Ether].src, routed_src_mac)
3201 self.assertEqual(inner[Ether].dst, sep4.mac)
3202 self.assertEqual(inner[IPv6].src, ep1.ip6.address)
3203 self.assertEqual(inner[IPv6].dst, ep3.ip6.address)
3205 c1.remove_vpp_config()
3206 c2.remove_vpp_config()
3209 # test the symmetric hash mode
3211 c1 = VppGbpContract(
3212 self, epg_220.sclass, epg_222.sclass, acl_index,
3213 [VppGbpContractRule(
3214 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3215 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3216 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3217 sep1.ip4, sep1.epg.rd),
3218 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3219 sep2.ip4, sep2.epg.rd)]),
3221 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3222 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3223 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3224 sep3.ip6, sep3.epg.rd),
3225 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3226 sep4.ip6, sep4.epg.rd)])],
3227 [ETH_P_IP, ETH_P_IPV6])
3230 c2 = VppGbpContract(
3231 self, epg_222.sclass, epg_220.sclass, acl_index,
3232 [VppGbpContractRule(
3233 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3234 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3235 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3236 sep1.ip4, sep1.epg.rd),
3237 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3238 sep2.ip4, sep2.epg.rd)]),
3240 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3241 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3242 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3243 sep3.ip6, sep3.epg.rd),
3244 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3245 sep4.ip6, sep4.epg.rd)])],
3246 [ETH_P_IP, ETH_P_IPV6])
3250 # send again with the contract preset, now packets arrive
3251 # at SEP1 for both directions
3253 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3256 self.assertEqual(rx[Ether].src, routed_src_mac)
3257 self.assertEqual(rx[Ether].dst, sep1.mac)
3258 self.assertEqual(rx[IP].src, ep1.ip4.address)
3259 self.assertEqual(rx[IP].dst, ep3.ip4.address)
3261 rxs = self.send_and_expect(self.pg2, p4[1] * 17, sep1.itf)
3264 self.assertEqual(rx[Ether].src, routed_src_mac)
3265 self.assertEqual(rx[Ether].dst, sep1.mac)
3266 self.assertEqual(rx[IP].src, ep3.ip4.address)
3267 self.assertEqual(rx[IP].dst, ep1.ip4.address)
3270 # programme the unknown EP for the L3 tests
3272 sep4.add_vpp_config()
3275 # an L3 switch packet between local EPs in different EPGs
3276 # different dest ports on each so the are LB hashed differently
3278 p4 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3279 IP(src=ep1.ip4.address, dst=ep2.ip4.address) /
3280 UDP(sport=1234, dport=1234) /
3282 (Ether(src=ep2.mac, dst=str(self.router_mac)) /
3283 IP(src=ep2.ip4.address, dst=ep1.ip4.address) /
3284 UDP(sport=1234, dport=1234) /
3286 p6 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3287 IPv6(src=ep1.ip6.address, dst=ep2.ip6.address) /
3288 UDP(sport=1234, dport=1234) /
3290 (Ether(src=ep2.mac, dst=str(self.router_mac)) /
3291 IPv6(src=ep2.ip6.address, dst=ep1.ip6.address) /
3292 UDP(sport=1234, dport=1234) /
3295 c3 = VppGbpContract(
3296 self, epg_220.sclass, epg_221.sclass, acl_index,
3297 [VppGbpContractRule(
3298 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3299 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3300 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3301 sep1.ip4, sep1.epg.rd),
3302 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3303 sep2.ip4, sep2.epg.rd)]),
3305 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3306 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3307 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3308 sep3.ip6, sep3.epg.rd),
3309 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3310 sep4.ip6, sep4.epg.rd)])],
3311 [ETH_P_IP, ETH_P_IPV6])
3314 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3317 self.assertEqual(rx[Ether].src, routed_src_mac)
3318 self.assertEqual(rx[Ether].dst, sep1.mac)
3319 self.assertEqual(rx[IP].src, ep1.ip4.address)
3320 self.assertEqual(rx[IP].dst, ep2.ip4.address)
3323 # learn a remote EP in EPG 221
3325 vx_tun_l3 = VppGbpVxlanTunnel(
3326 self, 444, rd1.rd_id,
3327 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
3329 vx_tun_l3.add_vpp_config()
3331 c4 = VppGbpContract(
3332 self, epg_221.sclass, epg_220.sclass, acl_index,
3333 [VppGbpContractRule(
3334 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3337 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3339 [ETH_P_IP, ETH_P_IPV6])
3342 p = (Ether(src=self.pg7.remote_mac,
3343 dst=self.pg7.local_mac) /
3344 IP(src=self.pg7.remote_ip4,
3345 dst=self.pg7.local_ip4) /
3346 UDP(sport=1234, dport=48879) /
3347 VXLAN(vni=444, gpid=441, flags=0x88) /
3348 Ether(src="00:22:22:22:22:33", dst=str(self.router_mac)) /
3349 IP(src="10.0.0.88", dst=ep1.ip4.address) /
3350 UDP(sport=1234, dport=1234) /
3353 rx = self.send_and_expect(self.pg7, [p], self.pg0)
3355 # endpoint learnt via the parent GBP-vxlan interface
3356 self.assertTrue(find_gbp_endpoint(self,
3357 vx_tun_l3._sw_if_index,
3360 p = (Ether(src=self.pg7.remote_mac,
3361 dst=self.pg7.local_mac) /
3362 IP(src=self.pg7.remote_ip4,
3363 dst=self.pg7.local_ip4) /
3364 UDP(sport=1234, dport=48879) /
3365 VXLAN(vni=444, gpid=441, flags=0x88) /
3366 Ether(src="00:22:22:22:22:33", dst=str(self.router_mac)) /
3367 IPv6(src="2001:10::88", dst=ep1.ip6.address) /
3368 UDP(sport=1234, dport=1234) /
3371 rx = self.send_and_expect(self.pg7, [p], self.pg0)
3373 # endpoint learnt via the parent GBP-vxlan interface
3374 self.assertTrue(find_gbp_endpoint(self,
3375 vx_tun_l3._sw_if_index,
3379 # L3 switch from local to remote EP
3381 p4 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3382 IP(src=ep1.ip4.address, dst="10.0.0.88") /
3383 UDP(sport=1234, dport=1234) /
3385 p6 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3386 IPv6(src=ep1.ip6.address, dst="2001:10::88") /
3387 UDP(sport=1234, dport=1234) /
3390 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3393 self.assertEqual(rx[Ether].src, routed_src_mac)
3394 self.assertEqual(rx[Ether].dst, sep1.mac)
3395 self.assertEqual(rx[IP].src, ep1.ip4.address)
3396 self.assertEqual(rx[IP].dst, "10.0.0.88")
3398 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep4.itf)
3401 self.assertEqual(rx[Ether].src, routed_src_mac)
3402 self.assertEqual(rx[Ether].dst, sep4.mac)
3403 self.assertEqual(rx[IPv6].src, ep1.ip6.address)
3404 self.assertEqual(rx[IPv6].dst, "2001:10::88")
3407 # test the dst-ip hash mode
3409 c5 = VppGbpContract(
3410 self, epg_220.sclass, epg_221.sclass, acl_index,
3411 [VppGbpContractRule(
3412 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3413 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
3414 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3415 sep1.ip4, sep1.epg.rd),
3416 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3417 sep2.ip4, sep2.epg.rd)]),
3419 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3420 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
3421 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3422 sep3.ip6, sep3.epg.rd),
3423 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3424 sep4.ip6, sep4.epg.rd)])],
3425 [ETH_P_IP, ETH_P_IPV6])
3428 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3431 self.assertEqual(rx[Ether].src, routed_src_mac)
3432 self.assertEqual(rx[Ether].dst, sep1.mac)
3433 self.assertEqual(rx[IP].src, ep1.ip4.address)
3434 self.assertEqual(rx[IP].dst, "10.0.0.88")
3436 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep3.itf)
3439 self.assertEqual(rx[Ether].src, routed_src_mac)
3440 self.assertEqual(rx[Ether].dst, sep3.mac)
3441 self.assertEqual(rx[IPv6].src, ep1.ip6.address)
3442 self.assertEqual(rx[IPv6].dst, "2001:10::88")
3447 self.pg7.unconfig_ip4()
3449 def test_gbp_l3_out(self):
3452 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
3453 self.vapi.cli("set logging class gbp level debug")
3455 routed_dst_mac = "00:0c:0c:0c:0c:0c"
3456 routed_src_mac = "00:22:bd:f8:19:ff"
3461 t4 = VppIpTable(self, 1)
3463 t6 = VppIpTable(self, 1, True)
3466 rd1 = VppGbpRouteDomain(self, 2, t4, t6)
3467 rd1.add_vpp_config()
3469 self.loop0.set_mac(self.router_mac)
3472 # Bind the BVI to the RD
3474 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
3475 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
3478 # Pg7 hosts a BD's BUM
3479 # Pg1 some other l3 interface
3481 self.pg7.config_ip4()
3482 self.pg7.resolve_arp()
3485 # a multicast vxlan-gbp tunnel for broadcast in the BD
3487 tun_bm = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
3490 tun_bm.add_vpp_config()
3493 # a GBP external bridge domains for the EPs
3495 bd1 = VppBridgeDomain(self, 1)
3496 bd1.add_vpp_config()
3497 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0, None, tun_bm)
3498 gbd1.add_vpp_config()
3501 # The Endpoint-groups in which the external endpoints exist
3503 epg_220 = VppGbpEndpointGroup(self, 220, 113, rd1, gbd1,
3507 VppGbpEndpointRetention(2))
3508 epg_220.add_vpp_config()
3510 # the BVIs have the subnets applied ...
3511 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 24)
3512 ip4_addr.add_vpp_config()
3513 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 64)
3514 ip6_addr.add_vpp_config()
3516 # ... which are L3-out subnets
3517 l3o_1 = VppGbpSubnet(
3518 self, rd1, "10.0.0.0", 24,
3519 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3521 l3o_1.add_vpp_config()
3524 # an external interface attached to the outside world and the
3527 vlan_100 = VppDot1QSubint(self, self.pg0, 100)
3529 VppL2Vtr(self, vlan_100, L2_VTR_OP.L2_POP_1).add_vpp_config()
3530 vlan_101 = VppDot1QSubint(self, self.pg0, 101)
3532 VppL2Vtr(self, vlan_101, L2_VTR_OP.L2_POP_1).add_vpp_config()
3533 # vlan_102 is not poped
3534 vlan_102 = VppDot1QSubint(self, self.pg0, 102)
3537 ext_itf = VppGbpExtItf(self, self.loop0, bd1, rd1)
3538 ext_itf.add_vpp_config()
3541 # an unicast vxlan-gbp for inter-RD traffic
3543 vx_tun_l3 = VppGbpVxlanTunnel(
3544 self, 444, rd1.rd_id,
3545 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
3547 vx_tun_l3.add_vpp_config()
3550 # External Endpoints
3552 eep1 = VppGbpEndpoint(self, vlan_100,
3554 "10.0.0.1", "11.0.0.1",
3555 "2001:10::1", "3001::1",
3556 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
3557 eep1.add_vpp_config()
3558 eep2 = VppGbpEndpoint(self, vlan_101,
3560 "10.0.0.2", "11.0.0.2",
3561 "2001:10::2", "3001::2",
3562 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
3563 eep2.add_vpp_config()
3564 eep3 = VppGbpEndpoint(self, vlan_102,
3566 "10.0.0.3", "11.0.0.3",
3567 "2001:10::3", "3001::3",
3568 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
3569 eep3.add_vpp_config()
3572 # A remote external endpoint
3574 rep = VppGbpEndpoint(self, vx_tun_l3,
3576 "10.0.0.101", "11.0.0.101",
3577 "2001:10::101", "3001::101",
3578 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
3580 self.pg7.remote_ip4,
3582 rep.add_vpp_config()
3585 # ARP packet from External EPs are accepted and replied to
3587 p_arp = (Ether(src=eep1.mac, dst="ff:ff:ff:ff:ff:ff") /
3590 psrc=eep1.ip4.address, pdst="10.0.0.128",
3591 hwsrc=eep1.mac, hwdst="ff:ff:ff:ff:ff:ff"))
3592 rxs = self.send_and_expect(self.pg0, p_arp * 1, self.pg0)
3595 # ARP packet from host in remote subnet are accepted and replied to
3597 p_arp = (Ether(src=vlan_102.remote_mac, dst="ff:ff:ff:ff:ff:ff") /
3600 psrc="10.0.0.17", pdst="10.0.0.128",
3601 hwsrc=vlan_102.remote_mac, hwdst="ff:ff:ff:ff:ff:ff"))
3602 rxs = self.send_and_expect(self.pg0, p_arp * 1, self.pg0)
3605 # packets destined to unknown addresses in the BVI's subnet
3608 p4 = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3610 IP(src="10.0.0.1", dst="10.0.0.88") /
3611 UDP(sport=1234, dport=1234) /
3613 p6 = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3615 IPv6(src="2001:10::1", dst="2001:10::88") /
3616 UDP(sport=1234, dport=1234) /
3619 rxs = self.send_and_expect(self.pg0, p4 * 1, self.pg7)
3622 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3623 # self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3624 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3625 self.assertEqual(rx[IP].dst, "239.1.1.1")
3626 self.assertEqual(rx[VXLAN].vni, 88)
3627 self.assertTrue(rx[VXLAN].flags.G)
3628 self.assertTrue(rx[VXLAN].flags.Instance)
3629 # policy was applied to the original IP packet
3630 self.assertEqual(rx[VXLAN].gpid, 113)
3631 self.assertTrue(rx[VXLAN].gpflags.A)
3632 self.assertFalse(rx[VXLAN].gpflags.D)
3634 inner = rx[VXLAN].payload
3636 self.assertTrue(inner.haslayer(ARP))
3639 # remote to external
3641 p = (Ether(src=self.pg7.remote_mac,
3642 dst=self.pg7.local_mac) /
3643 IP(src=self.pg7.remote_ip4,
3644 dst=self.pg7.local_ip4) /
3645 UDP(sport=1234, dport=48879) /
3646 VXLAN(vni=444, gpid=113, flags=0x88) /
3647 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
3648 IP(src="10.0.0.101", dst="10.0.0.1") /
3649 UDP(sport=1234, dport=1234) /
3652 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
3655 # local EP pings router
3657 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3659 IP(src=eep1.ip4.address, dst="10.0.0.128") /
3660 ICMP(type='echo-request'))
3662 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
3665 self.assertEqual(rx[Ether].src, str(self.router_mac))
3666 self.assertEqual(rx[Ether].dst, eep1.mac)
3667 self.assertEqual(rx[Dot1Q].vlan, 100)
3670 # local EP pings other local EP
3672 p = (Ether(src=eep1.mac, dst=eep2.mac) /
3674 IP(src=eep1.ip4.address, dst=eep2.ip4.address) /
3675 ICMP(type='echo-request'))
3677 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
3680 self.assertEqual(rx[Ether].src, eep1.mac)
3681 self.assertEqual(rx[Ether].dst, eep2.mac)
3682 self.assertEqual(rx[Dot1Q].vlan, 101)
3685 # local EP pings router w/o vlan tag poped
3687 p = (Ether(src=eep3.mac, dst=str(self.router_mac)) /
3689 IP(src=eep3.ip4.address, dst="10.0.0.128") /
3690 ICMP(type='echo-request'))
3692 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
3695 self.assertEqual(rx[Ether].src, str(self.router_mac))
3696 self.assertEqual(rx[Ether].dst, vlan_102.remote_mac)
3699 # A subnet reachable through the external EP1
3701 ip_220 = VppIpRoute(self, "10.220.0.0", 24,
3702 [VppRoutePath(eep1.ip4.address,
3703 eep1.epg.bvi.sw_if_index)],
3704 table_id=t4.table_id)
3705 ip_220.add_vpp_config()
3707 l3o_220 = VppGbpSubnet(
3708 self, rd1, "10.220.0.0", 24,
3709 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3711 l3o_220.add_vpp_config()
3714 # A subnet reachable through the external EP2
3716 ip_221 = VppIpRoute(self, "10.221.0.0", 24,
3717 [VppRoutePath(eep2.ip4.address,
3718 eep2.epg.bvi.sw_if_index)],
3719 table_id=t4.table_id)
3720 ip_221.add_vpp_config()
3722 l3o_221 = VppGbpSubnet(
3723 self, rd1, "10.221.0.0", 24,
3724 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3726 l3o_221.add_vpp_config()
3729 # ping between hosts in remote subnets
3730 # dropped without a contract
3732 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3734 IP(src="10.220.0.1", dst="10.221.0.1") /
3735 ICMP(type='echo-request'))
3737 rxs = self.send_and_assert_no_replies(self.pg0, p * 1)
3740 # contract for the external nets to communicate
3742 acl = VppGbpAcl(self)
3743 rule4 = acl.create_rule(permit_deny=1, proto=17)
3744 rule6 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
3745 acl_index = acl.add_vpp_config([rule4, rule6])
3747 c1 = VppGbpContract(
3748 self, 4220, 4221, acl_index,
3749 [VppGbpContractRule(
3750 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3753 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3755 [ETH_P_IP, ETH_P_IPV6])
3759 # Contracts allowing ext-net 200 to talk with external EPs
3761 c2 = VppGbpContract(
3762 self, 4220, 113, acl_index,
3763 [VppGbpContractRule(
3764 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3767 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3769 [ETH_P_IP, ETH_P_IPV6])
3771 c3 = VppGbpContract(
3772 self, 113, 4220, acl_index,
3773 [VppGbpContractRule(
3774 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3777 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3779 [ETH_P_IP, ETH_P_IPV6])
3783 # ping between hosts in remote subnets
3785 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3787 IP(src="10.220.0.1", dst="10.221.0.1") /
3788 UDP(sport=1234, dport=1234) /
3791 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
3794 self.assertEqual(rx[Ether].src, str(self.router_mac))
3795 self.assertEqual(rx[Ether].dst, eep2.mac)
3796 self.assertEqual(rx[Dot1Q].vlan, 101)
3798 # we did not learn these external hosts
3799 self.assertFalse(find_gbp_endpoint(self, ip="10.220.0.1"))
3800 self.assertFalse(find_gbp_endpoint(self, ip="10.221.0.1"))
3803 # from remote external EP to local external EP
3805 p = (Ether(src=self.pg7.remote_mac,
3806 dst=self.pg7.local_mac) /
3807 IP(src=self.pg7.remote_ip4,
3808 dst=self.pg7.local_ip4) /
3809 UDP(sport=1234, dport=48879) /
3810 VXLAN(vni=444, gpid=113, flags=0x88) /
3811 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
3812 IP(src="10.0.0.101", dst="10.220.0.1") /
3813 UDP(sport=1234, dport=1234) /
3816 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
3819 # ping from an external host to the remote external EP
3821 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3823 IP(src="10.220.0.1", dst=rep.ip4.address) /
3824 UDP(sport=1234, dport=1234) /
3827 rxs = self.send_and_expect(self.pg0, p * 1, self.pg7)
3830 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3831 # self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3832 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3833 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
3834 self.assertEqual(rx[VXLAN].vni, 444)
3835 self.assertTrue(rx[VXLAN].flags.G)
3836 self.assertTrue(rx[VXLAN].flags.Instance)
3837 # the sclass of the ext-net the packet came from
3838 self.assertEqual(rx[VXLAN].gpid, 4220)
3839 # policy was applied to the original IP packet
3840 self.assertTrue(rx[VXLAN].gpflags.A)
3841 # since it's an external host the reciever should not learn it
3842 self.assertTrue(rx[VXLAN].gpflags.D)
3843 inner = rx[VXLAN].payload
3844 self.assertEqual(inner[IP].src, "10.220.0.1")
3845 self.assertEqual(inner[IP].dst, rep.ip4.address)
3848 # An external subnet reachable via the remote external EP
3852 # first the VXLAN-GBP tunnel over which it is reached
3854 vx_tun_r = VppVxlanGbpTunnel(
3855 self, self.pg7.local_ip4,
3856 self.pg7.remote_ip4, 445,
3857 mode=(VppEnum.vl_api_vxlan_gbp_api_tunnel_mode_t.
3858 VXLAN_GBP_API_TUNNEL_MODE_L3))
3859 vx_tun_r.add_vpp_config()
3860 VppIpInterfaceBind(self, vx_tun_r, t4).add_vpp_config()
3862 self.logger.info(self.vapi.cli("sh vxlan-gbp tunnel"))
3865 # then the special adj to resolve through on that tunnel
3867 n1 = VppNeighbor(self,
3868 vx_tun_r.sw_if_index,
3869 "00:0c:0c:0c:0c:0c",
3870 self.pg7.remote_ip4)
3874 # the route via the adj above
3876 ip_222 = VppIpRoute(self, "10.222.0.0", 24,
3877 [VppRoutePath(self.pg7.remote_ip4,
3878 vx_tun_r.sw_if_index)],
3879 table_id=t4.table_id)
3880 ip_222.add_vpp_config()
3882 l3o_222 = VppGbpSubnet(
3883 self, rd1, "10.222.0.0", 24,
3884 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3886 l3o_222.add_vpp_config()
3889 # ping between hosts in local and remote external subnets
3890 # dropped without a contract
3892 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3894 IP(src="10.220.0.1", dst="10.222.0.1") /
3895 UDP(sport=1234, dport=1234) /
3898 rxs = self.send_and_assert_no_replies(self.pg0, p * 1)
3901 # Add contracts ext-nets for 220 -> 222
3903 c4 = VppGbpContract(
3904 self, 4220, 4222, acl_index,
3905 [VppGbpContractRule(
3906 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3909 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3911 [ETH_P_IP, ETH_P_IPV6])
3915 # ping from host in local to remote external subnets
3917 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3919 IP(src="10.220.0.1", dst="10.222.0.1") /
3920 UDP(sport=1234, dport=1234) /
3923 rxs = self.send_and_expect(self.pg0, p * 3, self.pg7)
3926 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3927 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3928 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3929 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
3930 self.assertEqual(rx[VXLAN].vni, 445)
3931 self.assertTrue(rx[VXLAN].flags.G)
3932 self.assertTrue(rx[VXLAN].flags.Instance)
3933 # the sclass of the ext-net the packet came from
3934 self.assertEqual(rx[VXLAN].gpid, 4220)
3935 # policy was applied to the original IP packet
3936 self.assertTrue(rx[VXLAN].gpflags.A)
3937 # since it's an external host the reciever should not learn it
3938 self.assertTrue(rx[VXLAN].gpflags.D)
3939 inner = rx[VXLAN].payload
3940 self.assertEqual(inner[Ether].dst, "00:0c:0c:0c:0c:0c")
3941 self.assertEqual(inner[IP].src, "10.220.0.1")
3942 self.assertEqual(inner[IP].dst, "10.222.0.1")
3945 # ping from host in remote to local external subnets
3946 # there's no contract for this, but the A bit is set.
3948 p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
3949 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
3950 UDP(sport=1234, dport=48879) /
3951 VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
3952 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
3953 IP(src="10.222.0.1", dst="10.220.0.1") /
3954 UDP(sport=1234, dport=1234) /
3957 rxs = self.send_and_expect(self.pg7, p * 3, self.pg0)
3958 self.assertFalse(find_gbp_endpoint(self, ip="10.222.0.1"))
3961 # ping from host in remote to remote external subnets
3962 # this is dropped by reflection check.
3964 p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
3965 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
3966 UDP(sport=1234, dport=48879) /
3967 VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
3968 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
3969 IP(src="10.222.0.1", dst="10.222.0.2") /
3970 UDP(sport=1234, dport=1234) /
3973 rxs = self.send_and_assert_no_replies(self.pg7, p * 3)
3978 self.pg7.unconfig_ip4()
3979 vlan_100.set_vtr(L2_VTR_OP.L2_DISABLED)
3982 if __name__ == '__main__':
3983 unittest.main(testRunner=VppTestRunner)