3 from socket import AF_INET, AF_INET6, inet_pton, inet_ntop
5 from ipaddress import ip_address, IPv4Network, IPv6Network
7 from scapy.packet import Raw
8 from scapy.layers.l2 import Ether, ARP, Dot1Q
9 from scapy.layers.inet import IP, UDP, ICMP
10 from scapy.layers.inet6 import IPv6, ICMPv6ND_NS, ICMPv6NDOptSrcLLAddr, \
11 ICMPv6ND_NA, ICMPv6EchoRequest
12 from scapy.utils6 import in6_getnsma, in6_getnsmac
13 from scapy.layers.vxlan import VXLAN
14 from scapy.data import ETH_P_IP, ETH_P_IPV6, ETH_P_ARP
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 DpoProto, get_dpo_proto
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
30 from vpp_acl import AclRule, VppAcl
39 def find_gbp_endpoint(test, sw_if_index=None, ip=None, mac=None,
40 tep=None, sclass=None, flags=None):
44 vmac = MACAddress(mac)
46 eps = test.vapi.gbp_endpoint_dump()
52 if src != str(ep.endpoint.tun.src) or \
53 dst != str(ep.endpoint.tun.dst):
56 if ep.endpoint.sw_if_index != sw_if_index:
59 if ep.endpoint.sclass != sclass:
62 if flags != (flags & ep.endpoint.flags):
65 for eip in ep.endpoint.ips:
69 if vmac == ep.endpoint.mac:
75 def find_gbp_vxlan(test, vni):
76 ts = test.vapi.gbp_vxlan_tunnel_dump()
78 if t.tunnel.vni == vni:
83 class VppGbpEndpoint(VppObject):
110 return [self.ip4, self.ip6]
114 return [self.fip4, self.fip6]
116 def __init__(self, test, itf, epg, recirc, ip4, fip4, ip6, fip6,
132 self.vmac = MACAddress(self.itf.remote_mac)
134 self.vmac = MACAddress("00:00:00:00:00:00")
137 self.tun_src = tun_src
138 self.tun_dst = tun_dst
140 def add_vpp_config(self):
141 res = self._test.vapi.gbp_endpoint_add(
142 self.itf.sw_if_index,
143 [self.ip4, self.ip6],
149 self.handle = res.handle
150 self._test.registry.register(self, self._test.logger)
152 def remove_vpp_config(self):
153 self._test.vapi.gbp_endpoint_del(self.handle)
156 return "gbp-endpoint:[%d==%d:%s:%d]" % (self.handle,
157 self.itf.sw_if_index,
161 def query_vpp_config(self):
162 return find_gbp_endpoint(self._test,
163 self.itf.sw_if_index,
167 class VppGbpRecirc(VppObject):
169 GBP Recirculation Interface
172 def __init__(self, test, epg, recirc, is_ext=False):
178 def add_vpp_config(self):
179 self._test.vapi.gbp_recirc_add_del(
181 self.recirc.sw_if_index,
184 self._test.registry.register(self, self._test.logger)
186 def remove_vpp_config(self):
187 self._test.vapi.gbp_recirc_add_del(
189 self.recirc.sw_if_index,
194 return "gbp-recirc:[%d]" % (self.recirc.sw_if_index)
196 def query_vpp_config(self):
197 rs = self._test.vapi.gbp_recirc_dump()
199 if r.recirc.sw_if_index == self.recirc.sw_if_index:
204 class VppGbpExtItf(VppObject):
206 GBP ExtItfulation Interface
209 def __init__(self, test, itf, bd, rd, anon=False):
214 self.flags = 1 if anon else 0
216 def add_vpp_config(self):
217 self._test.vapi.gbp_ext_itf_add_del(
218 1, self.itf.sw_if_index, self.bd.bd_id, self.rd.rd_id, self.flags)
219 self._test.registry.register(self, self._test.logger)
221 def remove_vpp_config(self):
222 self._test.vapi.gbp_ext_itf_add_del(
223 0, self.itf.sw_if_index, self.bd.bd_id, self.rd.rd_id, self.flags)
226 return "gbp-ext-itf:[%d]%s" % (self.itf.sw_if_index,
227 " [anon]" if self.flags else "")
229 def query_vpp_config(self):
230 rs = self._test.vapi.gbp_ext_itf_dump()
232 if r.ext_itf.sw_if_index == self.itf.sw_if_index:
237 class VppGbpSubnet(VppObject):
242 def __init__(self, test, rd, address, address_len,
243 type, sw_if_index=None, sclass=None):
245 self.rd_id = rd.rd_id
246 a = ip_address(address)
248 self.prefix = IPv4Network("%s/%d" % (address, address_len),
251 self.prefix = IPv6Network("%s/%d" % (address, address_len),
254 self.sw_if_index = sw_if_index
257 def add_vpp_config(self):
258 self._test.vapi.gbp_subnet_add_del(
263 sw_if_index=self.sw_if_index if self.sw_if_index else 0xffffffff,
264 sclass=self.sclass if self.sclass else 0xffff)
265 self._test.registry.register(self, self._test.logger)
267 def remove_vpp_config(self):
268 self._test.vapi.gbp_subnet_add_del(
275 return "gbp-subnet:[%d-%s]" % (self.rd_id, self.prefix)
277 def query_vpp_config(self):
278 ss = self._test.vapi.gbp_subnet_dump()
280 if s.subnet.rd_id == self.rd_id and \
281 s.subnet.type == self.type and \
282 s.subnet.prefix == self.prefix:
287 class VppGbpEndpointRetention(object):
288 def __init__(self, remote_ep_timeout=0xffffffff):
289 self.remote_ep_timeout = remote_ep_timeout
292 return {'remote_ep_timeout': self.remote_ep_timeout}
295 class VppGbpEndpointGroup(VppObject):
300 def __init__(self, test, vnid, sclass, rd, bd, uplink,
301 bvi, bvi_ip4, bvi_ip6=None,
302 retention=VppGbpEndpointRetention()):
306 self.bvi_ip4 = bvi_ip4
307 self.bvi_ip6 = bvi_ip6
314 self.retention = retention
316 def add_vpp_config(self):
317 self._test.vapi.gbp_endpoint_group_add(
322 self.uplink.sw_if_index if self.uplink else INDEX_INVALID,
323 self.retention.encode())
324 self._test.registry.register(self, self._test.logger)
326 def remove_vpp_config(self):
327 self._test.vapi.gbp_endpoint_group_del(self.sclass)
330 return "gbp-endpoint-group:[%d]" % (self.vnid)
332 def query_vpp_config(self):
333 epgs = self._test.vapi.gbp_endpoint_group_dump()
335 if epg.epg.vnid == self.vnid:
340 class VppGbpBridgeDomain(VppObject):
345 def __init__(self, test, bd, rd, bvi, uu_fwd=None,
346 bm_flood=None, learn=True,
347 uu_drop=False, bm_drop=False,
352 self.bm_flood = bm_flood
356 e = VppEnum.vl_api_gbp_bridge_domain_flags_t
358 self.flags = e.GBP_BD_API_FLAG_NONE
360 self.flags |= e.GBP_BD_API_FLAG_DO_NOT_LEARN
362 self.flags |= e.GBP_BD_API_FLAG_UU_FWD_DROP
364 self.flags |= e.GBP_BD_API_FLAG_MCAST_DROP
366 self.flags |= e.GBP_BD_API_FLAG_UCAST_ARP
368 def add_vpp_config(self):
369 self._test.vapi.gbp_bridge_domain_add(
373 self.bvi.sw_if_index,
374 self.uu_fwd.sw_if_index if self.uu_fwd else INDEX_INVALID,
375 self.bm_flood.sw_if_index if self.bm_flood else INDEX_INVALID)
376 self._test.registry.register(self, self._test.logger)
378 def remove_vpp_config(self):
379 self._test.vapi.gbp_bridge_domain_del(self.bd.bd_id)
382 return "gbp-bridge-domain:[%d]" % (self.bd.bd_id)
384 def query_vpp_config(self):
385 bds = self._test.vapi.gbp_bridge_domain_dump()
387 if bd.bd.bd_id == self.bd.bd_id:
392 class VppGbpRouteDomain(VppObject):
397 def __init__(self, test, rd_id, scope, t4, t6, ip4_uu=None, ip6_uu=None):
406 def add_vpp_config(self):
407 self._test.vapi.gbp_route_domain_add(
412 self.ip4_uu.sw_if_index if self.ip4_uu else INDEX_INVALID,
413 self.ip6_uu.sw_if_index if self.ip6_uu else INDEX_INVALID)
414 self._test.registry.register(self, self._test.logger)
416 def remove_vpp_config(self):
417 self._test.vapi.gbp_route_domain_del(self.rd_id)
420 return "gbp-route-domain:[%d]" % (self.rd_id)
422 def query_vpp_config(self):
423 rds = self._test.vapi.gbp_route_domain_dump()
425 if rd.rd.rd_id == self.rd_id:
430 class VppGbpContractNextHop():
431 def __init__(self, mac, bd, ip, rd):
438 return {'ip': self.ip,
439 'mac': self.mac.packed,
440 'bd_id': self.bd.bd.bd_id,
441 'rd_id': self.rd.rd_id}
444 class VppGbpContractRule():
445 def __init__(self, action, hash_mode, nhs=None):
447 self.hash_mode = hash_mode
448 self.nhs = [] if nhs is None else nhs
453 nhs.append(nh.encode())
456 return {'action': self.action,
458 'hash_mode': self.hash_mode,
459 'n_nhs': len(self.nhs),
463 return '<VppGbpContractRule action=%s, hash_mode=%s>' % (
464 self.action, self.hash_mode)
467 class VppGbpContract(VppObject):
472 def __init__(self, test, scope, sclass, dclass, acl_index,
473 rules, allowed_ethertypes):
475 if not isinstance(rules, list):
476 raise ValueError("'rules' must be a list.")
477 if not isinstance(allowed_ethertypes, list):
478 raise ValueError("'allowed_ethertypes' must be a list.")
480 self.acl_index = acl_index
484 self.allowed_ethertypes = allowed_ethertypes
485 while (len(self.allowed_ethertypes) < 16):
486 self.allowed_ethertypes.append(0)
488 def add_vpp_config(self):
491 rules.append(r.encode())
492 r = self._test.vapi.gbp_contract_add_del(
495 'acl_index': self.acl_index,
497 'sclass': self.sclass,
498 'dclass': self.dclass,
499 'n_rules': len(rules),
501 'n_ether_types': len(self.allowed_ethertypes),
502 'allowed_ethertypes': self.allowed_ethertypes})
503 self.stats_index = r.stats_index
504 self._test.registry.register(self, self._test.logger)
506 def remove_vpp_config(self):
507 self._test.vapi.gbp_contract_add_del(
510 'acl_index': self.acl_index,
512 'sclass': self.sclass,
513 'dclass': self.dclass,
516 'n_ether_types': len(self.allowed_ethertypes),
517 'allowed_ethertypes': self.allowed_ethertypes})
520 return "gbp-contract:[%d:%d:%d:%d]" % (self.scope,
525 def query_vpp_config(self):
526 cs = self._test.vapi.gbp_contract_dump()
528 if c.contract.scope == self.scope \
529 and c.contract.sclass == self.sclass \
530 and c.contract.dclass == self.dclass:
534 def get_drop_stats(self):
535 c = self._test.statistics.get_counter("/net/gbp/contract/drop")
536 return c[0][self.stats_index]
538 def get_permit_stats(self):
539 c = self._test.statistics.get_counter("/net/gbp/contract/permit")
540 return c[0][self.stats_index]
543 class VppGbpVxlanTunnel(VppInterface):
548 def __init__(self, test, vni, bd_rd_id, mode, src):
549 super(VppGbpVxlanTunnel, self).__init__(test)
552 self.bd_rd_id = bd_rd_id
556 def add_vpp_config(self):
557 r = self._test.vapi.gbp_vxlan_tunnel_add(
562 self.set_sw_if_index(r.sw_if_index)
563 self._test.registry.register(self, self._test.logger)
565 def remove_vpp_config(self):
566 self._test.vapi.gbp_vxlan_tunnel_del(self.vni)
569 return "gbp-vxlan:%d" % (self.sw_if_index)
571 def query_vpp_config(self):
572 return find_gbp_vxlan(self._test, self.vni)
575 class TestGBP(VppTestCase):
576 """ GBP Test Case """
579 def config_flags(self):
580 return VppEnum.vl_api_nat_config_flags_t
584 super(TestGBP, cls).setUpClass()
587 def tearDownClass(cls):
588 super(TestGBP, cls).tearDownClass()
591 super(TestGBP, self).setUp()
593 self.create_pg_interfaces(range(9))
594 self.create_loopback_interfaces(8)
596 self.router_mac = MACAddress("00:11:22:33:44:55")
598 for i in self.pg_interfaces:
600 for i in self.lo_interfaces:
603 self.vlan_100 = VppDot1QSubint(self, self.pg0, 100)
604 self.vlan_100.admin_up()
605 self.vlan_101 = VppDot1QSubint(self, self.pg0, 101)
606 self.vlan_101.admin_up()
607 self.vlan_102 = VppDot1QSubint(self, self.pg0, 102)
608 self.vlan_102.admin_up()
611 for i in self.pg_interfaces:
613 super(TestGBP, self).tearDown()
614 for i in self.lo_interfaces:
615 i.remove_vpp_config()
616 self.lo_interfaces = []
617 self.vlan_102.remove_vpp_config()
618 self.vlan_101.remove_vpp_config()
619 self.vlan_100.remove_vpp_config()
621 def send_and_expect_bridged(self, src, tx, dst):
622 rx = self.send_and_expect(src, tx, dst)
625 self.assertEqual(r[Ether].src, tx[0][Ether].src)
626 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
627 self.assertEqual(r[IP].src, tx[0][IP].src)
628 self.assertEqual(r[IP].dst, tx[0][IP].dst)
631 def send_and_expect_bridged6(self, src, tx, dst):
632 rx = self.send_and_expect(src, tx, dst)
635 self.assertEqual(r[Ether].src, tx[0][Ether].src)
636 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
637 self.assertEqual(r[IPv6].src, tx[0][IPv6].src)
638 self.assertEqual(r[IPv6].dst, tx[0][IPv6].dst)
641 def send_and_expect_routed(self, src, tx, dst, src_mac):
642 rx = self.send_and_expect(src, tx, dst)
645 self.assertEqual(r[Ether].src, src_mac)
646 self.assertEqual(r[Ether].dst, dst.remote_mac)
647 self.assertEqual(r[IP].src, tx[0][IP].src)
648 self.assertEqual(r[IP].dst, tx[0][IP].dst)
651 def send_and_expect_routed6(self, src, tx, dst, src_mac):
652 rx = self.send_and_expect(src, tx, dst)
655 self.assertEqual(r[Ether].src, src_mac)
656 self.assertEqual(r[Ether].dst, dst.remote_mac)
657 self.assertEqual(r[IPv6].src, tx[0][IPv6].src)
658 self.assertEqual(r[IPv6].dst, tx[0][IPv6].dst)
661 def send_and_expect_natted(self, src, tx, dst, src_ip):
662 rx = self.send_and_expect(src, tx, dst)
665 self.assertEqual(r[Ether].src, tx[0][Ether].src)
666 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
667 self.assertEqual(r[IP].src, src_ip)
668 self.assertEqual(r[IP].dst, tx[0][IP].dst)
671 def send_and_expect_natted6(self, src, tx, dst, src_ip):
672 rx = self.send_and_expect(src, tx, dst)
675 self.assertEqual(r[Ether].src, tx[0][Ether].src)
676 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
677 self.assertEqual(r[IPv6].src, src_ip)
678 self.assertEqual(r[IPv6].dst, tx[0][IPv6].dst)
681 def send_and_expect_unnatted(self, src, tx, dst, dst_ip):
682 rx = self.send_and_expect(src, tx, dst)
685 self.assertEqual(r[Ether].src, tx[0][Ether].src)
686 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
687 self.assertEqual(r[IP].dst, dst_ip)
688 self.assertEqual(r[IP].src, tx[0][IP].src)
691 def send_and_expect_unnatted6(self, src, tx, dst, dst_ip):
692 rx = self.send_and_expect(src, tx, dst)
695 self.assertEqual(r[Ether].src, tx[0][Ether].src)
696 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
697 self.assertEqual(r[IPv6].dst, dst_ip)
698 self.assertEqual(r[IPv6].src, tx[0][IPv6].src)
701 def send_and_expect_double_natted(self, src, tx, dst, src_ip, dst_ip):
702 rx = self.send_and_expect(src, tx, dst)
705 self.assertEqual(r[Ether].src, str(self.router_mac))
706 self.assertEqual(r[Ether].dst, dst.remote_mac)
707 self.assertEqual(r[IP].dst, dst_ip)
708 self.assertEqual(r[IP].src, src_ip)
711 def send_and_expect_double_natted6(self, src, tx, dst, src_ip, dst_ip):
712 rx = self.send_and_expect(src, tx, dst)
715 self.assertEqual(r[Ether].src, str(self.router_mac))
716 self.assertEqual(r[Ether].dst, dst.remote_mac)
717 self.assertEqual(r[IPv6].dst, dst_ip)
718 self.assertEqual(r[IPv6].src, src_ip)
721 def send_and_expect_no_arp(self, src, tx, dst):
722 self.pg_send(src, tx)
723 dst.get_capture(0, timeout=1)
724 dst.assert_nothing_captured(remark="")
727 def send_and_expect_arp(self, src, tx, dst):
728 rx = self.send_and_expect(src, tx, dst)
731 self.assertEqual(r[Ether].src, tx[0][Ether].src)
732 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
733 self.assertEqual(r[ARP].psrc, tx[0][ARP].psrc)
734 self.assertEqual(r[ARP].pdst, tx[0][ARP].pdst)
735 self.assertEqual(r[ARP].hwsrc, tx[0][ARP].hwsrc)
736 self.assertEqual(r[ARP].hwdst, tx[0][ARP].hwdst)
740 """ Group Based Policy """
742 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
747 gt4 = VppIpTable(self, 0)
749 gt6 = VppIpTable(self, 0, is_ip6=True)
751 nt4 = VppIpTable(self, 20)
753 nt6 = VppIpTable(self, 20, is_ip6=True)
756 rd0 = VppGbpRouteDomain(self, 0, 400, gt4, gt6, None, None)
757 rd20 = VppGbpRouteDomain(self, 20, 420, nt4, nt6, None, None)
760 rd20.add_vpp_config()
765 bd1 = VppBridgeDomain(self, 1)
766 bd2 = VppBridgeDomain(self, 2)
767 bd20 = VppBridgeDomain(self, 20)
771 bd20.add_vpp_config()
773 gbd1 = VppGbpBridgeDomain(self, bd1, rd0, self.loop0)
774 gbd2 = VppGbpBridgeDomain(self, bd2, rd0, self.loop1)
775 gbd20 = VppGbpBridgeDomain(self, bd20, rd20, self.loop2)
777 gbd1.add_vpp_config()
778 gbd2.add_vpp_config()
779 gbd20.add_vpp_config()
782 # 3 EPGs, 2 of which share a BD.
783 # 2 NAT EPGs, one for floating-IP subnets, the other for internet
785 epgs = [VppGbpEndpointGroup(self, 220, 1220, rd0, gbd1,
786 self.pg4, self.loop0,
787 "10.0.0.128", "2001:10::128"),
788 VppGbpEndpointGroup(self, 221, 1221, rd0, gbd1,
789 self.pg5, self.loop0,
790 "10.0.1.128", "2001:10:1::128"),
791 VppGbpEndpointGroup(self, 222, 1222, rd0, gbd2,
792 self.pg6, self.loop1,
793 "10.0.2.128", "2001:10:2::128"),
794 VppGbpEndpointGroup(self, 333, 1333, rd20, gbd20,
795 self.pg7, self.loop2,
796 "11.0.0.128", "3001::128"),
797 VppGbpEndpointGroup(self, 444, 1444, rd20, gbd20,
798 self.pg8, self.loop2,
799 "11.0.0.129", "3001::129")]
800 recircs = [VppGbpRecirc(self, epgs[0], self.loop3),
801 VppGbpRecirc(self, epgs[1], self.loop4),
802 VppGbpRecirc(self, epgs[2], self.loop5),
803 VppGbpRecirc(self, epgs[3], self.loop6, is_ext=True),
804 VppGbpRecirc(self, epgs[4], self.loop7, is_ext=True)]
807 recirc_nat = recircs[3]
810 # 4 end-points, 2 in the same subnet, 3 in the same BD
812 eps = [VppGbpEndpoint(self, self.pg0,
814 "10.0.0.1", "11.0.0.1",
815 "2001:10::1", "3001::1"),
816 VppGbpEndpoint(self, self.pg1,
818 "10.0.0.2", "11.0.0.2",
819 "2001:10::2", "3001::2"),
820 VppGbpEndpoint(self, self.pg2,
822 "10.0.1.1", "11.0.0.3",
823 "2001:10:1::1", "3001::3"),
824 VppGbpEndpoint(self, self.pg3,
826 "10.0.2.1", "11.0.0.4",
827 "2001:10:2::1", "3001::4")]
830 # Config related to each of the EPGs
833 # IP config on the BVI interfaces
834 if epg != epgs[1] and epg != epgs[4]:
835 b4 = VppIpInterfaceBind(self, epg.bvi,
836 epg.rd.t4).add_vpp_config()
837 b6 = VppIpInterfaceBind(self, epg.bvi,
838 epg.rd.t6).add_vpp_config()
839 epg.bvi.set_mac(self.router_mac)
841 # The BVIs are NAT inside interfaces
842 flags = self.config_flags.NAT_IS_INSIDE
843 self.vapi.nat44_interface_add_del_feature(
844 sw_if_index=epg.bvi.sw_if_index,
845 flags=flags, is_add=1)
846 self.vapi.nat66_add_del_interface(
847 is_add=1, flags=flags,
848 sw_if_index=epg.bvi.sw_if_index)
850 if_ip4 = VppIpInterfaceAddress(self, epg.bvi,
852 bind=b4).add_vpp_config()
853 if_ip6 = VppIpInterfaceAddress(self, epg.bvi,
855 bind=b6).add_vpp_config()
857 # EPG uplink interfaces in the RD
858 VppIpInterfaceBind(self, epg.uplink, epg.rd.t4).add_vpp_config()
859 VppIpInterfaceBind(self, epg.uplink, epg.rd.t6).add_vpp_config()
861 # add the BD ARP termination entry for BVI IP
862 epg.bd_arp_ip4 = VppBridgeDomainArpEntry(self, epg.bd.bd,
863 str(self.router_mac),
865 epg.bd_arp_ip6 = VppBridgeDomainArpEntry(self, epg.bd.bd,
866 str(self.router_mac),
868 epg.bd_arp_ip4.add_vpp_config()
869 epg.bd_arp_ip6.add_vpp_config()
874 for recirc in recircs:
875 # EPG's ingress recirculation interface maps to its RD
876 VppIpInterfaceBind(self, recirc.recirc,
877 recirc.epg.rd.t4).add_vpp_config()
878 VppIpInterfaceBind(self, recirc.recirc,
879 recirc.epg.rd.t6).add_vpp_config()
881 self.vapi.nat44_interface_add_del_feature(
882 sw_if_index=recirc.recirc.sw_if_index, is_add=1)
883 self.vapi.nat66_add_del_interface(
885 sw_if_index=recirc.recirc.sw_if_index)
887 recirc.add_vpp_config()
889 for recirc in recircs:
890 self.assertTrue(find_bridge_domain_port(self,
891 recirc.epg.bd.bd.bd_id,
892 recirc.recirc.sw_if_index))
895 self.pg_enable_capture(self.pg_interfaces)
898 # routes to the endpoints. We need these since there are no
899 # adj-fibs due to the fact the the BVI address has /32 and
900 # the subnet is not attached.
902 for (ip, fip) in zip(ep.ips, ep.fips):
903 # Add static mappings for each EP from the 10/8 to 11/8 network
904 if ip_address(ip).version == 4:
905 flags = self.config_flags.NAT_IS_ADDR_ONLY
906 self.vapi.nat44_add_del_static_mapping(
909 external_ip_address=fip,
910 external_sw_if_index=0xFFFFFFFF,
914 self.vapi.nat66_add_del_static_mapping(
916 external_ip_address=fip,
922 self.logger.info(self.vapi.cli("sh gbp endpoint"))
924 # ... results in a Gratuitous ARP/ND on the EPG's uplink
925 rx = ep.epg.uplink.get_capture(len(ep.ips), timeout=0.2)
927 for ii, ip in enumerate(ep.ips):
930 if ip_address(ip).version == 6:
931 self.assertTrue(p.haslayer(ICMPv6ND_NA))
932 self.assertEqual(p[ICMPv6ND_NA].tgt, ip)
934 self.assertTrue(p.haslayer(ARP))
935 self.assertEqual(p[ARP].psrc, ip)
936 self.assertEqual(p[ARP].pdst, ip)
938 # add the BD ARP termination entry for floating IP
940 ba = VppBridgeDomainArpEntry(self, epg_nat.bd.bd, ep.mac,
944 # floating IPs route via EPG recirc
946 self, fip, ip_address(fip).max_prefixlen,
948 ep.recirc.recirc.sw_if_index,
949 type=FibPathType.FIB_PATH_TYPE_DVR,
950 proto=get_dpo_proto(fip))],
954 # L2 FIB entries in the NAT EPG BD to bridge the packets from
955 # the outside direct to the internal EPG
956 lf = VppL2FibEntry(self, epg_nat.bd.bd, ep.mac,
957 ep.recirc.recirc, bvi_mac=0)
961 # ARP packets for unknown IP are sent to the EPG uplink
963 pkt_arp = (Ether(dst="ff:ff:ff:ff:ff:ff",
964 src=self.pg0.remote_mac) /
966 hwdst="ff:ff:ff:ff:ff:ff",
967 hwsrc=self.pg0.remote_mac,
971 self.vapi.cli("clear trace")
972 self.pg0.add_stream(pkt_arp)
974 self.pg_enable_capture(self.pg_interfaces)
977 rxd = epgs[0].uplink.get_capture(1)
980 # ARP/ND packets get a response
982 pkt_arp = (Ether(dst="ff:ff:ff:ff:ff:ff",
983 src=self.pg0.remote_mac) /
985 hwdst="ff:ff:ff:ff:ff:ff",
986 hwsrc=self.pg0.remote_mac,
987 pdst=epgs[0].bvi_ip4,
990 self.send_and_expect(self.pg0, [pkt_arp], self.pg0)
992 nsma = in6_getnsma(inet_pton(AF_INET6, eps[0].ip6))
993 d = inet_ntop(AF_INET6, nsma)
994 pkt_nd = (Ether(dst=in6_getnsmac(nsma),
995 src=self.pg0.remote_mac) /
996 IPv6(dst=d, src=eps[0].ip6) /
997 ICMPv6ND_NS(tgt=epgs[0].bvi_ip6) /
998 ICMPv6NDOptSrcLLAddr(lladdr=self.pg0.remote_mac))
999 self.send_and_expect(self.pg0, [pkt_nd], self.pg0)
1002 # broadcast packets are flooded
1004 pkt_bcast = (Ether(dst="ff:ff:ff:ff:ff:ff",
1005 src=self.pg0.remote_mac) /
1006 IP(src=eps[0].ip4, dst="232.1.1.1") /
1007 UDP(sport=1234, dport=1234) /
1010 self.vapi.cli("clear trace")
1011 self.pg0.add_stream(pkt_bcast)
1013 self.pg_enable_capture(self.pg_interfaces)
1016 rxd = eps[1].itf.get_capture(1)
1017 self.assertEqual(rxd[0][Ether].dst, pkt_bcast[Ether].dst)
1018 rxd = epgs[0].uplink.get_capture(1)
1019 self.assertEqual(rxd[0][Ether].dst, pkt_bcast[Ether].dst)
1022 # packets to non-local L3 destinations dropped
1024 pkt_intra_epg_220_ip4 = (Ether(src=self.pg0.remote_mac,
1025 dst=str(self.router_mac)) /
1028 UDP(sport=1234, dport=1234) /
1030 pkt_inter_epg_222_ip4 = (Ether(src=self.pg0.remote_mac,
1031 dst=str(self.router_mac)) /
1034 UDP(sport=1234, dport=1234) /
1037 self.send_and_assert_no_replies(self.pg0,
1038 pkt_intra_epg_220_ip4 * NUM_PKTS)
1040 pkt_inter_epg_222_ip6 = (Ether(src=self.pg0.remote_mac,
1041 dst=str(self.router_mac)) /
1042 IPv6(src=eps[0].ip6,
1043 dst="2001:10::99") /
1044 UDP(sport=1234, dport=1234) /
1046 self.send_and_assert_no_replies(self.pg0,
1047 pkt_inter_epg_222_ip6 * NUM_PKTS)
1050 # Add the subnet routes
1053 self, rd0, "10.0.0.0", 24,
1054 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1056 self, rd0, "10.0.1.0", 24,
1057 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1059 self, rd0, "10.0.2.0", 24,
1060 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1062 self, rd0, "2001:10::1", 64,
1063 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1065 self, rd0, "2001:10:1::1", 64,
1066 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1068 self, rd0, "2001:10:2::1", 64,
1069 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1070 s41.add_vpp_config()
1071 s42.add_vpp_config()
1072 s43.add_vpp_config()
1073 s61.add_vpp_config()
1074 s62.add_vpp_config()
1075 s63.add_vpp_config()
1077 self.send_and_expect_bridged(eps[0].itf,
1078 pkt_intra_epg_220_ip4 * NUM_PKTS,
1080 self.send_and_expect_bridged(eps[0].itf,
1081 pkt_inter_epg_222_ip4 * NUM_PKTS,
1083 self.send_and_expect_bridged6(eps[0].itf,
1084 pkt_inter_epg_222_ip6 * NUM_PKTS,
1087 self.logger.info(self.vapi.cli("sh ip fib 11.0.0.2"))
1088 self.logger.info(self.vapi.cli("sh gbp endpoint-group"))
1089 self.logger.info(self.vapi.cli("sh gbp endpoint"))
1090 self.logger.info(self.vapi.cli("sh gbp recirc"))
1091 self.logger.info(self.vapi.cli("sh int"))
1092 self.logger.info(self.vapi.cli("sh int addr"))
1093 self.logger.info(self.vapi.cli("sh int feat loop6"))
1094 self.logger.info(self.vapi.cli("sh vlib graph ip4-gbp-src-classify"))
1095 self.logger.info(self.vapi.cli("sh int feat loop3"))
1096 self.logger.info(self.vapi.cli("sh int feat pg0"))
1099 # Packet destined to unknown unicast is sent on the epg uplink ...
1101 pkt_intra_epg_220_to_uplink = (Ether(src=self.pg0.remote_mac,
1102 dst="00:00:00:33:44:55") /
1105 UDP(sport=1234, dport=1234) /
1108 self.send_and_expect_bridged(eps[0].itf,
1109 pkt_intra_epg_220_to_uplink * NUM_PKTS,
1111 # ... and nowhere else
1112 self.pg1.get_capture(0, timeout=0.1)
1113 self.pg1.assert_nothing_captured(remark="Flood onto other VMS")
1115 pkt_intra_epg_221_to_uplink = (Ether(src=self.pg2.remote_mac,
1116 dst="00:00:00:33:44:66") /
1119 UDP(sport=1234, dport=1234) /
1122 self.send_and_expect_bridged(eps[2].itf,
1123 pkt_intra_epg_221_to_uplink * NUM_PKTS,
1127 # Packets from the uplink are forwarded in the absence of a contract
1129 pkt_intra_epg_220_from_uplink = (Ether(src="00:00:00:33:44:55",
1130 dst=self.pg0.remote_mac) /
1133 UDP(sport=1234, dport=1234) /
1136 self.send_and_expect_bridged(self.pg4,
1137 pkt_intra_epg_220_from_uplink * NUM_PKTS,
1141 # in the absence of policy, endpoints in the same EPG
1144 pkt_intra_epg = (Ether(src=self.pg0.remote_mac,
1145 dst=self.pg1.remote_mac) /
1148 UDP(sport=1234, dport=1234) /
1151 self.send_and_expect_bridged(self.pg0,
1152 pkt_intra_epg * NUM_PKTS,
1156 # in the absence of policy, endpoints in the different EPG
1157 # cannot communicate
1159 pkt_inter_epg_220_to_221 = (Ether(src=self.pg0.remote_mac,
1160 dst=self.pg2.remote_mac) /
1163 UDP(sport=1234, dport=1234) /
1165 pkt_inter_epg_221_to_220 = (Ether(src=self.pg2.remote_mac,
1166 dst=self.pg0.remote_mac) /
1169 UDP(sport=1234, dport=1234) /
1171 pkt_inter_epg_220_to_222 = (Ether(src=self.pg0.remote_mac,
1172 dst=str(self.router_mac)) /
1175 UDP(sport=1234, dport=1234) /
1178 self.send_and_assert_no_replies(eps[0].itf,
1179 pkt_inter_epg_220_to_221 * NUM_PKTS)
1180 self.send_and_assert_no_replies(eps[0].itf,
1181 pkt_inter_epg_220_to_222 * NUM_PKTS)
1184 # A uni-directional contract from EPG 220 -> 221
1186 rule = AclRule(is_permit=1, proto=17)
1187 rule2 = AclRule(src_prefix=IPv6Network((0, 0)),
1188 dst_prefix=IPv6Network((0, 0)), is_permit=1, proto=17)
1189 acl = VppAcl(self, rules=[rule, rule2])
1190 acl.add_vpp_config()
1192 c1 = VppGbpContract(
1193 self, 400, epgs[0].sclass, epgs[1].sclass, acl.acl_index,
1194 [VppGbpContractRule(
1195 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1196 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1199 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1200 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1202 [ETH_P_IP, ETH_P_IPV6])
1205 self.send_and_expect_bridged(eps[0].itf,
1206 pkt_inter_epg_220_to_221 * NUM_PKTS,
1208 self.send_and_assert_no_replies(eps[0].itf,
1209 pkt_inter_epg_220_to_222 * NUM_PKTS)
1212 # contract for the return direction
1214 c2 = VppGbpContract(
1215 self, 400, epgs[1].sclass, epgs[0].sclass, acl.acl_index,
1216 [VppGbpContractRule(
1217 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1218 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1221 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1222 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1224 [ETH_P_IP, ETH_P_IPV6])
1227 self.send_and_expect_bridged(eps[0].itf,
1228 pkt_inter_epg_220_to_221 * NUM_PKTS,
1230 self.send_and_expect_bridged(eps[2].itf,
1231 pkt_inter_epg_221_to_220 * NUM_PKTS,
1234 ds = c2.get_drop_stats()
1235 self.assertEqual(ds['packets'], 0)
1236 ps = c2.get_permit_stats()
1237 self.assertEqual(ps['packets'], NUM_PKTS)
1240 # the contract does not allow non-IP
1242 pkt_non_ip_inter_epg_220_to_221 = (Ether(src=self.pg0.remote_mac,
1243 dst=self.pg2.remote_mac) /
1245 self.send_and_assert_no_replies(eps[0].itf,
1246 pkt_non_ip_inter_epg_220_to_221 * 17)
1249 # check that inter group is still disabled for the groups
1250 # not in the contract.
1252 self.send_and_assert_no_replies(eps[0].itf,
1253 pkt_inter_epg_220_to_222 * NUM_PKTS)
1256 # A uni-directional contract from EPG 220 -> 222 'L3 routed'
1258 c3 = VppGbpContract(
1259 self, 400, epgs[0].sclass, epgs[2].sclass, acl.acl_index,
1260 [VppGbpContractRule(
1261 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1262 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1265 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1266 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1268 [ETH_P_IP, ETH_P_IPV6])
1271 self.logger.info(self.vapi.cli("sh gbp contract"))
1273 self.send_and_expect_routed(eps[0].itf,
1274 pkt_inter_epg_220_to_222 * NUM_PKTS,
1276 str(self.router_mac))
1279 # remove both contracts, traffic stops in both directions
1281 c2.remove_vpp_config()
1282 c1.remove_vpp_config()
1283 c3.remove_vpp_config()
1284 acl.remove_vpp_config()
1286 self.send_and_assert_no_replies(eps[2].itf,
1287 pkt_inter_epg_221_to_220 * NUM_PKTS)
1288 self.send_and_assert_no_replies(eps[0].itf,
1289 pkt_inter_epg_220_to_221 * NUM_PKTS)
1290 self.send_and_expect_bridged(eps[0].itf,
1291 pkt_intra_epg * NUM_PKTS,
1295 # EPs to the outside world
1298 # in the EP's RD an external subnet via the NAT EPG's recirc
1300 self, rd0, "0.0.0.0", 0,
1301 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1302 sw_if_index=recirc_nat.recirc.sw_if_index,
1303 sclass=epg_nat.sclass)
1305 self, rd0, "11.0.0.0", 8,
1306 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1307 sw_if_index=recirc_nat.recirc.sw_if_index,
1308 sclass=epg_nat.sclass)
1309 se16 = VppGbpSubnet(
1311 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1312 sw_if_index=recirc_nat.recirc.sw_if_index,
1313 sclass=epg_nat.sclass)
1314 # in the NAT RD an external subnet via the NAT EPG's uplink
1316 self, rd20, "0.0.0.0", 0,
1317 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1318 sw_if_index=epg_nat.uplink.sw_if_index,
1319 sclass=epg_nat.sclass)
1320 se36 = VppGbpSubnet(
1321 self, rd20, "::", 0,
1322 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1323 sw_if_index=epg_nat.uplink.sw_if_index,
1324 sclass=epg_nat.sclass)
1326 self, rd20, "11.0.0.0", 8,
1327 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1328 sw_if_index=epg_nat.uplink.sw_if_index,
1329 sclass=epg_nat.sclass)
1330 se1.add_vpp_config()
1331 se2.add_vpp_config()
1332 se16.add_vpp_config()
1333 se3.add_vpp_config()
1334 se36.add_vpp_config()
1335 se4.add_vpp_config()
1337 self.logger.info(self.vapi.cli("sh ip fib 0.0.0.0/0"))
1338 self.logger.info(self.vapi.cli("sh ip fib 11.0.0.1"))
1339 self.logger.info(self.vapi.cli("sh ip6 fib ::/0"))
1340 self.logger.info(self.vapi.cli("sh ip6 fib %s" %
1344 # From an EP to an outside address: IN2OUT
1346 pkt_inter_epg_220_to_global = (Ether(src=self.pg0.remote_mac,
1347 dst=str(self.router_mac)) /
1350 UDP(sport=1234, dport=1234) /
1354 self.send_and_assert_no_replies(eps[0].itf,
1355 pkt_inter_epg_220_to_global * NUM_PKTS)
1356 rule = AclRule(is_permit=1, proto=17, ports=1234)
1357 rule2 = AclRule(is_permit=1, proto=17, ports=1234,
1358 src_prefix=IPv6Network((0, 0)),
1359 dst_prefix=IPv6Network((0, 0)))
1360 acl2 = VppAcl(self, rules=[rule, rule2])
1361 acl2.add_vpp_config()
1363 c4 = VppGbpContract(
1364 self, 400, epgs[0].sclass, epgs[3].sclass, acl2.acl_index,
1365 [VppGbpContractRule(
1366 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1367 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1370 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1371 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1373 [ETH_P_IP, ETH_P_IPV6])
1376 self.send_and_expect_natted(eps[0].itf,
1377 pkt_inter_epg_220_to_global * NUM_PKTS,
1381 pkt_inter_epg_220_to_global = (Ether(src=self.pg0.remote_mac,
1382 dst=str(self.router_mac)) /
1383 IPv6(src=eps[0].ip6,
1385 UDP(sport=1234, dport=1234) /
1388 self.send_and_expect_natted6(self.pg0,
1389 pkt_inter_epg_220_to_global * NUM_PKTS,
1394 # From a global address to an EP: OUT2IN
1396 pkt_inter_epg_220_from_global = (Ether(src=str(self.router_mac),
1397 dst=self.pg0.remote_mac) /
1400 UDP(sport=1234, dport=1234) /
1403 self.send_and_assert_no_replies(
1404 self.pg7, pkt_inter_epg_220_from_global * NUM_PKTS)
1406 c5 = VppGbpContract(
1407 self, 400, epgs[3].sclass, epgs[0].sclass, acl2.acl_index,
1408 [VppGbpContractRule(
1409 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1410 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1413 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1414 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1416 [ETH_P_IP, ETH_P_IPV6])
1419 self.send_and_expect_unnatted(self.pg7,
1420 pkt_inter_epg_220_from_global * NUM_PKTS,
1424 pkt_inter_epg_220_from_global = (Ether(src=str(self.router_mac),
1425 dst=self.pg0.remote_mac) /
1426 IPv6(dst=eps[0].fip6,
1428 UDP(sport=1234, dport=1234) /
1431 self.send_and_expect_unnatted6(
1433 pkt_inter_epg_220_from_global * NUM_PKTS,
1438 # From a local VM to another local VM using resp. public addresses:
1441 pkt_intra_epg_220_global = (Ether(src=self.pg0.remote_mac,
1442 dst=str(self.router_mac)) /
1445 UDP(sport=1234, dport=1234) /
1448 self.send_and_expect_double_natted(eps[0].itf,
1449 pkt_intra_epg_220_global * NUM_PKTS,
1454 pkt_intra_epg_220_global = (Ether(src=self.pg0.remote_mac,
1455 dst=str(self.router_mac)) /
1456 IPv6(src=eps[0].ip6,
1458 UDP(sport=1234, dport=1234) /
1461 self.send_and_expect_double_natted6(
1463 pkt_intra_epg_220_global * NUM_PKTS,
1472 # del static mappings for each EP from the 10/8 to 11/8 network
1473 flags = self.config_flags.NAT_IS_ADDR_ONLY
1474 self.vapi.nat44_add_del_static_mapping(
1476 local_ip_address=ep.ip4,
1477 external_ip_address=ep.fip4,
1478 external_sw_if_index=0xFFFFFFFF,
1481 self.vapi.nat66_add_del_static_mapping(
1482 local_ip_address=ep.ip6,
1483 external_ip_address=ep.fip6,
1487 # IP config on the BVI interfaces
1488 if epg != epgs[0] and epg != epgs[3]:
1489 flags = self.config_flags.NAT_IS_INSIDE
1490 self.vapi.nat44_interface_add_del_feature(
1491 sw_if_index=epg.bvi.sw_if_index,
1494 self.vapi.nat66_add_del_interface(
1495 is_add=0, flags=flags,
1496 sw_if_index=epg.bvi.sw_if_index)
1498 for recirc in recircs:
1499 self.vapi.nat44_interface_add_del_feature(
1500 sw_if_index=recirc.recirc.sw_if_index,
1502 self.vapi.nat66_add_del_interface(
1504 sw_if_index=recirc.recirc.sw_if_index)
1506 def wait_for_ep_timeout(self, sw_if_index=None, ip=None, mac=None,
1507 tep=None, n_tries=100, s_time=1):
1508 # only learnt EP can timeout
1509 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
1510 flags = ep_flags.GBP_API_ENDPOINT_FLAG_LEARNT
1512 if not find_gbp_endpoint(self, sw_if_index, ip, mac, tep=tep,
1515 n_tries = n_tries - 1
1517 self.assertFalse(find_gbp_endpoint(self, sw_if_index, ip, mac, tep=tep,
1521 def test_gbp_learn_l2(self):
1522 """ GBP L2 Endpoint Learning """
1524 drop_no_contract = self.statistics.get_err_counter(
1525 '/err/gbp-policy-port/drop-no-contract')
1526 allow_intra_class = self.statistics.get_err_counter(
1527 '/err/gbp-policy-port/allow-intra-sclass')
1529 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
1530 learnt = [{'mac': '00:00:11:11:11:01',
1532 'ip6': '2001:10::2'},
1533 {'mac': '00:00:11:11:11:02',
1535 'ip6': '2001:10::3'}]
1540 gt4 = VppIpTable(self, 1)
1541 gt4.add_vpp_config()
1542 gt6 = VppIpTable(self, 1, is_ip6=True)
1543 gt6.add_vpp_config()
1545 rd1 = VppGbpRouteDomain(self, 1, 401, gt4, gt6)
1546 rd1.add_vpp_config()
1549 # Pg2 hosts the vxlan tunnel, hosts on pg2 to act as TEPs
1550 # Pg3 hosts the IP4 UU-flood VXLAN tunnel
1551 # Pg4 hosts the IP6 UU-flood VXLAN tunnel
1553 self.pg2.config_ip4()
1554 self.pg2.resolve_arp()
1555 self.pg2.generate_remote_hosts(4)
1556 self.pg2.configure_ipv4_neighbors()
1557 self.pg3.config_ip4()
1558 self.pg3.resolve_arp()
1559 self.pg4.config_ip4()
1560 self.pg4.resolve_arp()
1563 # Add a mcast destination VXLAN-GBP tunnel for B&M traffic
1565 tun_bm = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
1568 tun_bm.add_vpp_config()
1571 # a GBP bridge domain with a BVI and a UU-flood interface
1573 bd1 = VppBridgeDomain(self, 1)
1574 bd1.add_vpp_config()
1575 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0,
1577 gbd1.add_vpp_config()
1579 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1580 self.logger.info(self.vapi.cli("sh gbp bridge"))
1582 # ... and has a /32 applied
1583 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
1584 ip_addr.add_vpp_config()
1587 # The Endpoint-group in which we are learning endpoints
1589 epg_220 = VppGbpEndpointGroup(self, 220, 112, rd1, gbd1,
1593 VppGbpEndpointRetention(4))
1594 epg_220.add_vpp_config()
1595 epg_330 = VppGbpEndpointGroup(self, 330, 113, rd1, gbd1,
1599 VppGbpEndpointRetention(4))
1600 epg_330.add_vpp_config()
1603 # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
1606 vx_tun_l2_1 = VppGbpVxlanTunnel(
1607 self, 99, bd1.bd_id,
1608 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L2,
1610 vx_tun_l2_1.add_vpp_config()
1613 # A static endpoint that the learnt endpoints are trying to
1616 ep = VppGbpEndpoint(self, self.pg0,
1618 "10.0.0.127", "11.0.0.127",
1619 "2001:10::1", "3001::1")
1622 self.assertTrue(find_route(self, ep.ip4, 32, table_id=1))
1624 # a packet with an sclass from an unknown EPG
1625 p = (Ether(src=self.pg2.remote_mac,
1626 dst=self.pg2.local_mac) /
1627 IP(src=self.pg2.remote_hosts[0].ip4,
1628 dst=self.pg2.local_ip4) /
1629 UDP(sport=1234, dport=48879) /
1630 VXLAN(vni=99, gpid=88, flags=0x88) /
1631 Ether(src=learnt[0]["mac"], dst=ep.mac) /
1632 IP(src=learnt[0]["ip"], dst=ep.ip4) /
1633 UDP(sport=1234, dport=1234) /
1636 self.send_and_assert_no_replies(self.pg2, p)
1638 self.logger.info(self.vapi.cli("sh error"))
1639 self.assert_error_counter_equal(
1640 '/err/gbp-policy-port/drop-no-contract',
1641 drop_no_contract + 1)
1644 # we should not have learnt a new tunnel endpoint, since
1645 # the EPG was not learnt.
1647 self.assertEqual(INDEX_INVALID,
1648 find_vxlan_gbp_tunnel(self,
1650 self.pg2.remote_hosts[0].ip4,
1653 # ep is not learnt, because the EPG is unknown
1654 self.assertEqual(len(self.vapi.gbp_endpoint_dump()), 1)
1657 # Learn new EPs from IP packets
1659 for ii, l in enumerate(learnt):
1660 # a packet with an sclass from a known EPG
1661 # arriving on an unknown TEP
1662 p = (Ether(src=self.pg2.remote_mac,
1663 dst=self.pg2.local_mac) /
1664 IP(src=self.pg2.remote_hosts[1].ip4,
1665 dst=self.pg2.local_ip4) /
1666 UDP(sport=1234, dport=48879) /
1667 VXLAN(vni=99, gpid=112, flags=0x88) /
1668 Ether(src=l['mac'], dst=ep.mac) /
1669 IP(src=l['ip'], dst=ep.ip4) /
1670 UDP(sport=1234, dport=1234) /
1673 rx = self.send_and_expect(self.pg2, [p], self.pg0)
1676 tep1_sw_if_index = find_vxlan_gbp_tunnel(
1679 self.pg2.remote_hosts[1].ip4,
1681 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
1684 # the EP is learnt via the learnt TEP
1685 # both from its MAC and its IP
1687 self.assertTrue(find_gbp_endpoint(self,
1688 vx_tun_l2_1.sw_if_index,
1690 self.assertTrue(find_gbp_endpoint(self,
1691 vx_tun_l2_1.sw_if_index,
1694 self.assert_error_counter_equal(
1695 '/err/gbp-policy-port/allow-intra-sclass',
1696 allow_intra_class + 2)
1698 self.logger.info(self.vapi.cli("show gbp endpoint"))
1699 self.logger.info(self.vapi.cli("show gbp vxlan"))
1700 self.logger.info(self.vapi.cli("show ip mfib"))
1703 # If we sleep for the threshold time, the learnt endpoints should
1707 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1711 # Learn new EPs from GARP packets received on the BD's mcast tunnel
1713 for ii, l in enumerate(learnt):
1714 # add some junk in the reserved field of the vxlan-header
1715 # next to the VNI. we should accept since reserved bits are
1717 p = (Ether(src=self.pg2.remote_mac,
1718 dst=self.pg2.local_mac) /
1719 IP(src=self.pg2.remote_hosts[1].ip4,
1721 UDP(sport=1234, dport=48879) /
1722 VXLAN(vni=88, reserved2=0x80, gpid=112, flags=0x88) /
1723 Ether(src=l['mac'], dst="ff:ff:ff:ff:ff:ff") /
1725 psrc=l['ip'], pdst=l['ip'],
1726 hwsrc=l['mac'], hwdst="ff:ff:ff:ff:ff:ff"))
1728 rx = self.send_and_expect(self.pg4, [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,
1745 self.assertTrue(find_gbp_endpoint(self,
1746 vx_tun_l2_1.sw_if_index,
1750 # wait for the learnt endpoints to age out
1753 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1757 # Learn new EPs from L2 packets
1759 for ii, l in enumerate(learnt):
1760 # a packet with an sclass from a known EPG
1761 # arriving on an unknown TEP
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) /
1768 Ether(src=l['mac'], dst=ep.mac) /
1771 rx = self.send_and_expect(self.pg2, [p], self.pg0)
1774 tep1_sw_if_index = find_vxlan_gbp_tunnel(
1777 self.pg2.remote_hosts[1].ip4,
1779 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
1782 # the EP is learnt via the learnt TEP
1783 # both from its MAC and its IP
1785 self.assertTrue(find_gbp_endpoint(self,
1786 vx_tun_l2_1.sw_if_index,
1789 self.logger.info(self.vapi.cli("show gbp endpoint"))
1790 self.logger.info(self.vapi.cli("show gbp vxlan"))
1791 self.logger.info(self.vapi.cli("show vxlan-gbp tunnel"))
1794 # wait for the learnt endpoints to age out
1797 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1801 # repeat. the do not learn bit is set so the EPs are not learnt
1804 # a packet with an sclass from a known EPG
1805 p = (Ether(src=self.pg2.remote_mac,
1806 dst=self.pg2.local_mac) /
1807 IP(src=self.pg2.remote_hosts[1].ip4,
1808 dst=self.pg2.local_ip4) /
1809 UDP(sport=1234, dport=48879) /
1810 VXLAN(vni=99, gpid=112, flags=0x88, gpflags="D") /
1811 Ether(src=l['mac'], dst=ep.mac) /
1812 IP(src=l['ip'], dst=ep.ip4) /
1813 UDP(sport=1234, dport=1234) /
1816 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
1819 self.assertFalse(find_gbp_endpoint(self,
1820 vx_tun_l2_1.sw_if_index,
1827 # a packet with an sclass from a known EPG
1828 # set a reserved bit in addition to the G and I
1829 # reserved bits should not be checked on rx.
1830 p = (Ether(src=self.pg2.remote_mac,
1831 dst=self.pg2.local_mac) /
1832 IP(src=self.pg2.remote_hosts[1].ip4,
1833 dst=self.pg2.local_ip4) /
1834 UDP(sport=1234, dport=48879) /
1835 VXLAN(vni=99, gpid=112, flags=0xc8) /
1836 Ether(src=l['mac'], dst=ep.mac) /
1837 IP(src=l['ip'], dst=ep.ip4) /
1838 UDP(sport=1234, dport=1234) /
1841 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
1843 self.assertTrue(find_gbp_endpoint(self,
1844 vx_tun_l2_1.sw_if_index,
1848 # Static EP replies to dynamics
1850 self.logger.info(self.vapi.cli("sh l2fib bd_id 1"))
1852 p = (Ether(src=ep.mac, dst=l['mac']) /
1853 IP(dst=l['ip'], src=ep.ip4) /
1854 UDP(sport=1234, dport=1234) /
1857 rxs = self.send_and_expect(self.pg0, p * 17, self.pg2)
1860 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
1861 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
1862 self.assertEqual(rx[UDP].dport, 48879)
1863 # the UDP source port is a random value for hashing
1864 self.assertEqual(rx[VXLAN].gpid, 112)
1865 self.assertEqual(rx[VXLAN].vni, 99)
1866 self.assertTrue(rx[VXLAN].flags.G)
1867 self.assertTrue(rx[VXLAN].flags.Instance)
1868 self.assertTrue(rx[VXLAN].gpflags.A)
1869 self.assertFalse(rx[VXLAN].gpflags.D)
1872 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1876 # repeat in the other EPG
1877 # there's no contract between 220 and 330, but the A-bit is set
1878 # so the packet is cleared for delivery
1881 # a packet with an sclass from a known EPG
1882 p = (Ether(src=self.pg2.remote_mac,
1883 dst=self.pg2.local_mac) /
1884 IP(src=self.pg2.remote_hosts[1].ip4,
1885 dst=self.pg2.local_ip4) /
1886 UDP(sport=1234, dport=48879) /
1887 VXLAN(vni=99, gpid=113, flags=0x88, gpflags='A') /
1888 Ether(src=l['mac'], dst=ep.mac) /
1889 IP(src=l['ip'], dst=ep.ip4) /
1890 UDP(sport=1234, dport=1234) /
1893 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
1895 self.assertTrue(find_gbp_endpoint(self,
1896 vx_tun_l2_1.sw_if_index,
1900 # static EP cannot reach the learnt EPs since there is no contract
1901 # only test 1 EP as the others could timeout
1903 p = (Ether(src=ep.mac, dst=l['mac']) /
1904 IP(dst=learnt[0]['ip'], src=ep.ip4) /
1905 UDP(sport=1234, dport=1234) /
1908 self.send_and_assert_no_replies(self.pg0, [p])
1911 # refresh the entries after the check for no replies above
1914 # a packet with an sclass from a known EPG
1915 p = (Ether(src=self.pg2.remote_mac,
1916 dst=self.pg2.local_mac) /
1917 IP(src=self.pg2.remote_hosts[1].ip4,
1918 dst=self.pg2.local_ip4) /
1919 UDP(sport=1234, dport=48879) /
1920 VXLAN(vni=99, gpid=113, flags=0x88, gpflags='A') /
1921 Ether(src=l['mac'], dst=ep.mac) /
1922 IP(src=l['ip'], dst=ep.ip4) /
1923 UDP(sport=1234, dport=1234) /
1926 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
1928 self.assertTrue(find_gbp_endpoint(self,
1929 vx_tun_l2_1.sw_if_index,
1933 # Add the contract so they can talk
1935 rule = AclRule(is_permit=1, proto=17)
1936 rule2 = AclRule(src_prefix=IPv6Network((0, 0)),
1937 dst_prefix=IPv6Network((0, 0)), is_permit=1, proto=17)
1938 acl = VppAcl(self, rules=[rule, rule2])
1939 acl.add_vpp_config()
1941 c1 = VppGbpContract(
1942 self, 401, epg_220.sclass, epg_330.sclass, acl.acl_index,
1943 [VppGbpContractRule(
1944 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1945 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1948 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1949 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1951 [ETH_P_IP, ETH_P_IPV6])
1955 p = (Ether(src=ep.mac, dst=l['mac']) /
1956 IP(dst=l['ip'], src=ep.ip4) /
1957 UDP(sport=1234, dport=1234) /
1960 self.send_and_expect(self.pg0, [p], self.pg2)
1963 # send UU packets from the local EP
1965 self.logger.info(self.vapi.cli("sh gbp bridge"))
1966 self.logger.info(self.vapi.cli("sh bridge-domain 1 detail"))
1967 p_uu = (Ether(src=ep.mac, dst="00:11:11:11:11:11") /
1968 IP(dst="10.0.0.133", src=ep.ip4) /
1969 UDP(sport=1234, dport=1234) /
1971 rxs = self.send_and_expect(ep.itf, [p_uu], gbd1.uu_fwd)
1973 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1975 p_bm = (Ether(src=ep.mac, dst="ff:ff:ff:ff:ff:ff") /
1976 IP(dst="10.0.0.133", src=ep.ip4) /
1977 UDP(sport=1234, dport=1234) /
1979 rxs = self.send_and_expect_only(ep.itf, [p_bm], tun_bm.mcast_itf)
1982 self.assertEqual(rx[IP].src, self.pg4.local_ip4)
1983 self.assertEqual(rx[IP].dst, "239.1.1.1")
1984 self.assertEqual(rx[UDP].dport, 48879)
1985 # the UDP source port is a random value for hashing
1986 self.assertEqual(rx[VXLAN].gpid, 112)
1987 self.assertEqual(rx[VXLAN].vni, 88)
1988 self.assertTrue(rx[VXLAN].flags.G)
1989 self.assertTrue(rx[VXLAN].flags.Instance)
1990 self.assertFalse(rx[VXLAN].gpflags.A)
1991 self.assertFalse(rx[VXLAN].gpflags.D)
1993 rule = AclRule(is_permit=1, proto=17)
1994 rule2 = AclRule(src_prefix=IPv6Network((0, 0)),
1995 dst_prefix=IPv6Network((0, 0)), is_permit=1, proto=17)
1996 acl = VppAcl(self, rules=[rule, rule2])
1997 acl.add_vpp_config()
1999 c2 = VppGbpContract(
2000 self, 401, epg_330.sclass, epg_220.sclass, acl.acl_index,
2001 [VppGbpContractRule(
2002 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2003 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2006 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2007 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2009 [ETH_P_IP, ETH_P_IPV6])
2013 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
2016 # Check v6 Endpoints learning
2019 # a packet with an sclass from a known EPG
2020 p = (Ether(src=self.pg2.remote_mac,
2021 dst=self.pg2.local_mac) /
2022 IP(src=self.pg2.remote_hosts[1].ip4,
2023 dst=self.pg2.local_ip4) /
2024 UDP(sport=1234, dport=48879) /
2025 VXLAN(vni=99, gpid=113, flags=0x88) /
2026 Ether(src=l['mac'], dst=ep.mac) /
2027 IPv6(src=l['ip6'], dst=ep.ip6) /
2028 UDP(sport=1234, dport=1234) /
2031 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
2032 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
2034 self.assertTrue(find_gbp_endpoint(
2036 vx_tun_l2_1.sw_if_index,
2038 tep=[self.pg2.local_ip4,
2039 self.pg2.remote_hosts[1].ip4]))
2041 self.logger.info(self.vapi.cli("sh int"))
2042 self.logger.info(self.vapi.cli("sh vxlan-gbp tunnel"))
2043 self.logger.info(self.vapi.cli("sh gbp vxlan"))
2044 self.logger.info(self.vapi.cli("sh gbp endpoint"))
2045 self.logger.info(self.vapi.cli("sh gbp interface"))
2048 # EP moves to a different TEP
2051 # a packet with an sclass from a known EPG
2052 p = (Ether(src=self.pg2.remote_mac,
2053 dst=self.pg2.local_mac) /
2054 IP(src=self.pg2.remote_hosts[2].ip4,
2055 dst=self.pg2.local_ip4) /
2056 UDP(sport=1234, dport=48879) /
2057 VXLAN(vni=99, gpid=113, flags=0x88) /
2058 Ether(src=l['mac'], dst=ep.mac) /
2059 IPv6(src=l['ip6'], dst=ep.ip6) /
2060 UDP(sport=1234, dport=1234) /
2063 rx = self.send_and_expect(self.pg2, p * 1, self.pg0)
2064 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
2066 self.assertTrue(find_gbp_endpoint(
2068 vx_tun_l2_1.sw_if_index,
2071 tep=[self.pg2.local_ip4,
2072 self.pg2.remote_hosts[2].ip4]))
2075 # v6 remote EP reachability
2078 p = (Ether(src=ep.mac, dst=l['mac']) /
2079 IPv6(dst=l['ip6'], src=ep.ip6) /
2080 UDP(sport=1234, dport=1234) /
2083 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
2086 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2087 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[2].ip4)
2088 self.assertEqual(rx[UDP].dport, 48879)
2089 # the UDP source port is a random value for hashing
2090 self.assertEqual(rx[VXLAN].gpid, 112)
2091 self.assertEqual(rx[VXLAN].vni, 99)
2092 self.assertTrue(rx[VXLAN].flags.G)
2093 self.assertTrue(rx[VXLAN].flags.Instance)
2094 self.assertTrue(rx[VXLAN].gpflags.A)
2095 self.assertFalse(rx[VXLAN].gpflags.D)
2096 self.assertEqual(rx[IPv6].dst, l['ip6'])
2102 # a packet with an sclass from a known EPG
2103 p = (Ether(src=self.pg2.remote_mac,
2104 dst=self.pg2.local_mac) /
2105 IP(src=self.pg2.remote_hosts[2].ip4,
2106 dst=self.pg2.local_ip4) /
2107 UDP(sport=1234, dport=48879) /
2108 VXLAN(vni=99, gpid=112, flags=0x88) /
2109 Ether(src=l['mac'], dst=ep.mac) /
2110 IPv6(src=l['ip6'], dst=ep.ip6) /
2111 UDP(sport=1234, dport=1234) /
2114 rx = self.send_and_expect(self.pg2, p * 1, self.pg0)
2115 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
2117 self.assertTrue(find_gbp_endpoint(
2119 vx_tun_l2_1.sw_if_index,
2122 tep=[self.pg2.local_ip4,
2123 self.pg2.remote_hosts[2].ip4]))
2126 # check reachability and contract intra-epg
2128 allow_intra_class = self.statistics.get_err_counter(
2129 '/err/gbp-policy-mac/allow-intra-sclass')
2132 p = (Ether(src=ep.mac, dst=l['mac']) /
2133 IPv6(dst=l['ip6'], src=ep.ip6) /
2134 UDP(sport=1234, dport=1234) /
2137 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
2140 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2141 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[2].ip4)
2142 self.assertEqual(rx[UDP].dport, 48879)
2143 self.assertEqual(rx[VXLAN].gpid, 112)
2144 self.assertEqual(rx[VXLAN].vni, 99)
2145 self.assertTrue(rx[VXLAN].flags.G)
2146 self.assertTrue(rx[VXLAN].flags.Instance)
2147 self.assertTrue(rx[VXLAN].gpflags.A)
2148 self.assertFalse(rx[VXLAN].gpflags.D)
2149 self.assertEqual(rx[IPv6].dst, l['ip6'])
2151 allow_intra_class += NUM_PKTS
2153 self.assert_error_counter_equal(
2154 '/err/gbp-policy-mac/allow-intra-sclass',
2161 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
2163 self.pg2.unconfig_ip4()
2164 self.pg3.unconfig_ip4()
2165 self.pg4.unconfig_ip4()
2167 def test_gbp_contract(self):
2168 """ GBP Contracts """
2173 gt4 = VppIpTable(self, 0)
2174 gt4.add_vpp_config()
2175 gt6 = VppIpTable(self, 0, is_ip6=True)
2176 gt6.add_vpp_config()
2178 rd0 = VppGbpRouteDomain(self, 0, 400, gt4, gt6, None, None)
2180 rd0.add_vpp_config()
2185 bd1 = VppBridgeDomain(self, 1, arp_term=0)
2186 bd2 = VppBridgeDomain(self, 2, arp_term=0)
2188 bd1.add_vpp_config()
2189 bd2.add_vpp_config()
2191 gbd1 = VppGbpBridgeDomain(self, bd1, rd0, self.loop0)
2192 gbd2 = VppGbpBridgeDomain(self, bd2, rd0, self.loop1)
2194 gbd1.add_vpp_config()
2195 gbd2.add_vpp_config()
2198 # 3 EPGs, 2 of which share a BD.
2200 epgs = [VppGbpEndpointGroup(self, 220, 1220, rd0, gbd1,
2202 "10.0.0.128", "2001:10::128"),
2203 VppGbpEndpointGroup(self, 221, 1221, rd0, gbd1,
2205 "10.0.1.128", "2001:10:1::128"),
2206 VppGbpEndpointGroup(self, 222, 1222, rd0, gbd2,
2208 "10.0.2.128", "2001:10:2::128")]
2210 # 4 end-points, 2 in the same subnet, 3 in the same BD
2212 eps = [VppGbpEndpoint(self, self.pg0,
2214 "10.0.0.1", "11.0.0.1",
2215 "2001:10::1", "3001::1"),
2216 VppGbpEndpoint(self, self.pg1,
2218 "10.0.0.2", "11.0.0.2",
2219 "2001:10::2", "3001::2"),
2220 VppGbpEndpoint(self, self.pg2,
2222 "10.0.1.1", "11.0.0.3",
2223 "2001:10:1::1", "3001::3"),
2224 VppGbpEndpoint(self, self.pg3,
2226 "10.0.2.1", "11.0.0.4",
2227 "2001:10:2::1", "3001::4")]
2230 # Config related to each of the EPGs
2233 # IP config on the BVI interfaces
2235 b4 = VppIpInterfaceBind(self, epg.bvi,
2236 epg.rd.t4).add_vpp_config()
2237 b6 = VppIpInterfaceBind(self, epg.bvi,
2238 epg.rd.t6).add_vpp_config()
2239 epg.bvi.set_mac(self.router_mac)
2241 if_ip4 = VppIpInterfaceAddress(self, epg.bvi,
2243 bind=b4).add_vpp_config()
2244 if_ip6 = VppIpInterfaceAddress(self, epg.bvi,
2246 bind=b6).add_vpp_config()
2248 # add the BD ARP termination entry for BVI IP
2249 epg.bd_arp_ip4 = VppBridgeDomainArpEntry(self, epg.bd.bd,
2250 str(self.router_mac),
2252 epg.bd_arp_ip4.add_vpp_config()
2255 epg.add_vpp_config()
2263 self.logger.info(self.vapi.cli("show gbp endpoint"))
2264 self.logger.info(self.vapi.cli("show interface"))
2265 self.logger.info(self.vapi.cli("show br"))
2268 # Intra epg allowed without contract
2270 pkt_intra_epg_220_to_220 = (Ether(src=self.pg0.remote_mac,
2271 dst=self.pg1.remote_mac) /
2274 UDP(sport=1234, dport=1234) /
2277 self.send_and_expect_bridged(self.pg0,
2278 pkt_intra_epg_220_to_220 * 65,
2281 pkt_intra_epg_220_to_220 = (Ether(src=self.pg0.remote_mac,
2282 dst=self.pg1.remote_mac) /
2283 IPv6(src=eps[0].ip6,
2285 UDP(sport=1234, dport=1234) /
2288 self.send_and_expect_bridged6(self.pg0,
2289 pkt_intra_epg_220_to_220 * 65,
2293 # Inter epg denied without contract
2295 pkt_inter_epg_220_to_221 = (Ether(src=self.pg0.remote_mac,
2296 dst=self.pg2.remote_mac) /
2299 UDP(sport=1234, dport=1234) /
2302 self.send_and_assert_no_replies(self.pg0, pkt_inter_epg_220_to_221)
2305 # A uni-directional contract from EPG 220 -> 221
2307 rule = AclRule(is_permit=1, proto=17)
2308 rule2 = AclRule(src_prefix=IPv6Network((0, 0)),
2309 dst_prefix=IPv6Network((0, 0)), is_permit=1, proto=17)
2310 rule3 = AclRule(is_permit=1, proto=1)
2311 acl = VppAcl(self, rules=[rule, rule2, rule3])
2312 acl.add_vpp_config()
2314 c1 = VppGbpContract(
2315 self, 400, epgs[0].sclass, epgs[1].sclass, acl.acl_index,
2316 [VppGbpContractRule(
2317 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2318 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2321 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2322 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2325 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2326 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2328 [ETH_P_IP, ETH_P_IPV6])
2331 self.send_and_expect_bridged(eps[0].itf,
2332 pkt_inter_epg_220_to_221 * 65,
2335 pkt_inter_epg_220_to_222 = (Ether(src=self.pg0.remote_mac,
2336 dst=str(self.router_mac)) /
2339 UDP(sport=1234, dport=1234) /
2341 self.send_and_assert_no_replies(eps[0].itf,
2342 pkt_inter_epg_220_to_222 * 65)
2345 # ping router IP in different BD
2347 pkt_router_ping_220_to_221 = (Ether(src=self.pg0.remote_mac,
2348 dst=str(self.router_mac)) /
2350 dst=epgs[1].bvi_ip4) /
2351 ICMP(type='echo-request'))
2353 self.send_and_expect(self.pg0, [pkt_router_ping_220_to_221], self.pg0)
2355 pkt_router_ping_220_to_221 = (Ether(src=self.pg0.remote_mac,
2356 dst=str(self.router_mac)) /
2357 IPv6(src=eps[0].ip6,
2358 dst=epgs[1].bvi_ip6) /
2359 ICMPv6EchoRequest())
2361 self.send_and_expect(self.pg0, [pkt_router_ping_220_to_221], self.pg0)
2364 # contract for the return direction
2366 c2 = VppGbpContract(
2367 self, 400, epgs[1].sclass, epgs[0].sclass, acl.acl_index,
2368 [VppGbpContractRule(
2369 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2370 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2373 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2374 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2376 [ETH_P_IP, ETH_P_IPV6])
2379 self.send_and_expect_bridged(eps[0].itf,
2380 pkt_inter_epg_220_to_221 * 65,
2382 pkt_inter_epg_221_to_220 = (Ether(src=self.pg2.remote_mac,
2383 dst=self.pg0.remote_mac) /
2386 UDP(sport=1234, dport=1234) /
2388 self.send_and_expect_bridged(eps[2].itf,
2389 pkt_inter_epg_221_to_220 * 65,
2391 pkt_inter_epg_221_to_220 = (Ether(src=self.pg2.remote_mac,
2392 dst=str(self.router_mac)) /
2395 UDP(sport=1234, dport=1234) /
2397 self.send_and_expect_routed(eps[2].itf,
2398 pkt_inter_epg_221_to_220 * 65,
2400 str(self.router_mac))
2401 pkt_inter_epg_221_to_220 = (Ether(src=self.pg2.remote_mac,
2402 dst=str(self.router_mac)) /
2403 IPv6(src=eps[2].ip6,
2405 UDP(sport=1234, dport=1234) /
2407 self.send_and_expect_routed6(eps[2].itf,
2408 pkt_inter_epg_221_to_220 * 65,
2410 str(self.router_mac))
2413 # contract between 220 and 222 uni-direction
2415 c3 = VppGbpContract(
2416 self, 400, epgs[0].sclass, epgs[2].sclass, acl.acl_index,
2417 [VppGbpContractRule(
2418 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2419 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2422 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2423 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2425 [ETH_P_IP, ETH_P_IPV6])
2428 self.send_and_expect(eps[0].itf,
2429 pkt_inter_epg_220_to_222 * 65,
2432 c3.remove_vpp_config()
2433 c1.remove_vpp_config()
2434 c2.remove_vpp_config()
2435 acl.remove_vpp_config()
2437 def test_gbp_bd_drop_flags(self):
2438 """ GBP BD drop flags """
2443 gt4 = VppIpTable(self, 1)
2444 gt4.add_vpp_config()
2445 gt6 = VppIpTable(self, 1, is_ip6=True)
2446 gt6.add_vpp_config()
2448 rd1 = VppGbpRouteDomain(self, 1, 401, gt4, gt6)
2449 rd1.add_vpp_config()
2452 # a GBP bridge domain with a BVI only
2454 bd1 = VppBridgeDomain(self, 1)
2455 bd1.add_vpp_config()
2457 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0,
2459 uu_drop=True, bm_drop=True)
2460 gbd1.add_vpp_config()
2462 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2463 self.logger.info(self.vapi.cli("sh gbp bridge"))
2465 # ... and has a /32 applied
2466 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi,
2467 "10.0.0.128", 32).add_vpp_config()
2470 # The Endpoint-group
2472 epg_220 = VppGbpEndpointGroup(self, 220, 112, rd1, gbd1,
2476 VppGbpEndpointRetention(3))
2477 epg_220.add_vpp_config()
2479 ep = VppGbpEndpoint(self, self.pg0,
2481 "10.0.0.127", "11.0.0.127",
2482 "2001:10::1", "3001::1")
2486 # send UU/BM packet from the local EP with UU drop and BM drop enabled
2489 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2490 self.logger.info(self.vapi.cli("sh gbp bridge"))
2491 p_uu = (Ether(src=ep.mac, dst="00:11:11:11:11:11") /
2492 IP(dst="10.0.0.133", src=ep.ip4) /
2493 UDP(sport=1234, dport=1234) /
2495 self.send_and_assert_no_replies(ep.itf, [p_uu])
2497 p_bm = (Ether(src=ep.mac, dst="ff:ff:ff:ff:ff:ff") /
2498 IP(dst="10.0.0.133", src=ep.ip4) /
2499 UDP(sport=1234, dport=1234) /
2501 self.send_and_assert_no_replies(ep.itf, [p_bm])
2503 self.pg3.unconfig_ip4()
2505 self.logger.info(self.vapi.cli("sh int"))
2507 def test_gbp_bd_arp_flags(self):
2508 """ GBP BD arp flags """
2513 gt4 = VppIpTable(self, 1)
2514 gt4.add_vpp_config()
2515 gt6 = VppIpTable(self, 1, is_ip6=True)
2516 gt6.add_vpp_config()
2518 rd1 = VppGbpRouteDomain(self, 1, 401, gt4, gt6)
2519 rd1.add_vpp_config()
2522 # Pg4 hosts the IP6 UU-flood VXLAN tunnel
2524 self.pg4.config_ip4()
2525 self.pg4.resolve_arp()
2528 # Add a mcast destination VXLAN-GBP tunnel for B&M traffic
2530 tun_uu = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
2533 tun_uu.add_vpp_config()
2536 # a GBP bridge domain with a BVI and a UU-flood interface
2538 bd1 = VppBridgeDomain(self, 1)
2539 bd1.add_vpp_config()
2541 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0,
2544 gbd1.add_vpp_config()
2546 # ... and has a /32 applied
2547 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi,
2548 "10.0.0.128", 32).add_vpp_config()
2551 # The Endpoint-group
2553 epg_220 = VppGbpEndpointGroup(self, 220, 112, rd1, gbd1,
2557 VppGbpEndpointRetention(2))
2558 epg_220.add_vpp_config()
2560 ep = VppGbpEndpoint(self, self.pg0,
2562 "10.0.0.127", "11.0.0.127",
2563 "2001:10::1", "3001::1")
2567 # send ARP packet from the local EP expect it on the uu interface
2569 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2570 self.logger.info(self.vapi.cli("sh gbp bridge"))
2571 p_arp = (Ether(src=ep.mac, dst="ff:ff:ff:ff:ff:ff") /
2573 psrc=ep.ip4, pdst="10.0.0.99",
2575 hwdst="ff:ff:ff:ff:ff:ff"))
2576 self.send_and_expect(ep.itf, [p_arp], self.pg4)
2578 self.pg4.unconfig_ip4()
2580 def test_gbp_learn_vlan_l2(self):
2581 """ GBP L2 Endpoint w/ VLANs"""
2583 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
2584 learnt = [{'mac': '00:00:11:11:11:01',
2586 'ip6': '2001:10::2'},
2587 {'mac': '00:00:11:11:11:02',
2589 'ip6': '2001:10::3'}]
2594 gt4 = VppIpTable(self, 1)
2595 gt4.add_vpp_config()
2596 gt6 = VppIpTable(self, 1, is_ip6=True)
2597 gt6.add_vpp_config()
2599 rd1 = VppGbpRouteDomain(self, 1, 401, gt4, gt6)
2600 rd1.add_vpp_config()
2603 # Pg2 hosts the vxlan tunnel, hosts on pg2 to act as TEPs
2605 self.pg2.config_ip4()
2606 self.pg2.resolve_arp()
2607 self.pg2.generate_remote_hosts(4)
2608 self.pg2.configure_ipv4_neighbors()
2609 self.pg3.config_ip4()
2610 self.pg3.resolve_arp()
2613 # The EP will be on a vlan sub-interface
2615 vlan_11 = VppDot1QSubint(self, self.pg0, 11)
2617 self.vapi.l2_interface_vlan_tag_rewrite(
2618 sw_if_index=vlan_11.sw_if_index, vtr_op=L2_VTR_OP.L2_POP_1,
2621 bd_uu_fwd = VppVxlanGbpTunnel(self, self.pg3.local_ip4,
2622 self.pg3.remote_ip4, 116)
2623 bd_uu_fwd.add_vpp_config()
2626 # a GBP bridge domain with a BVI and a UU-flood interface
2627 # The BD is marked as do not learn, so no endpoints are ever
2628 # learnt in this BD.
2630 bd1 = VppBridgeDomain(self, 1)
2631 bd1.add_vpp_config()
2632 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0, bd_uu_fwd,
2634 gbd1.add_vpp_config()
2636 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2637 self.logger.info(self.vapi.cli("sh gbp bridge"))
2639 # ... and has a /32 applied
2640 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi,
2641 "10.0.0.128", 32).add_vpp_config()
2644 # The Endpoint-group in which we are learning endpoints
2646 epg_220 = VppGbpEndpointGroup(self, 220, 441, rd1, gbd1,
2650 VppGbpEndpointRetention(4))
2651 epg_220.add_vpp_config()
2654 # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
2657 vx_tun_l2_1 = VppGbpVxlanTunnel(
2658 self, 99, bd1.bd_id,
2659 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L2,
2661 vx_tun_l2_1.add_vpp_config()
2664 # A static endpoint that the learnt endpoints are trying to
2667 ep = VppGbpEndpoint(self, vlan_11,
2669 "10.0.0.127", "11.0.0.127",
2670 "2001:10::1", "3001::1")
2673 self.assertTrue(find_route(self, ep.ip4, 32, table_id=1))
2676 # Send to the static EP
2678 for ii, l in enumerate(learnt):
2679 # a packet with an sclass from a known EPG
2680 # arriving on an unknown TEP
2681 p = (Ether(src=self.pg2.remote_mac,
2682 dst=self.pg2.local_mac) /
2683 IP(src=self.pg2.remote_hosts[1].ip4,
2684 dst=self.pg2.local_ip4) /
2685 UDP(sport=1234, dport=48879) /
2686 VXLAN(vni=99, gpid=441, flags=0x88) /
2687 Ether(src=l['mac'], dst=ep.mac) /
2688 IP(src=l['ip'], dst=ep.ip4) /
2689 UDP(sport=1234, dport=1234) /
2692 rxs = self.send_and_expect(self.pg2, [p], self.pg0)
2695 # packet to EP has the EP's vlan tag
2698 self.assertEqual(rx[Dot1Q].vlan, 11)
2701 # the EP is not learnt since the BD setting prevents it
2704 self.assertFalse(find_gbp_endpoint(self,
2705 vx_tun_l2_1.sw_if_index,
2707 self.assertEqual(INDEX_INVALID,
2708 find_vxlan_gbp_tunnel(
2711 self.pg2.remote_hosts[1].ip4,
2714 self.assertEqual(len(self.vapi.gbp_endpoint_dump()), 1)
2718 # we didn't learn the remotes so they are sent to the UU-fwd
2721 p = (Ether(src=ep.mac, dst=l['mac']) /
2723 IP(dst=l['ip'], src=ep.ip4) /
2724 UDP(sport=1234, dport=1234) /
2727 rxs = self.send_and_expect(self.pg0, p * 17, self.pg3)
2730 self.assertEqual(rx[IP].src, self.pg3.local_ip4)
2731 self.assertEqual(rx[IP].dst, self.pg3.remote_ip4)
2732 self.assertEqual(rx[UDP].dport, 48879)
2733 # the UDP source port is a random value for hashing
2734 self.assertEqual(rx[VXLAN].gpid, 441)
2735 self.assertEqual(rx[VXLAN].vni, 116)
2736 self.assertTrue(rx[VXLAN].flags.G)
2737 self.assertTrue(rx[VXLAN].flags.Instance)
2738 self.assertFalse(rx[VXLAN].gpflags.A)
2739 self.assertFalse(rx[VXLAN].gpflags.D)
2741 self.pg2.unconfig_ip4()
2742 self.pg3.unconfig_ip4()
2744 def test_gbp_learn_l3(self):
2745 """ GBP L3 Endpoint Learning """
2747 self.vapi.cli("set logging class gbp level debug")
2749 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
2750 routed_dst_mac = "00:0c:0c:0c:0c:0c"
2751 routed_src_mac = "00:22:bd:f8:19:ff"
2753 learnt = [{'mac': '00:00:11:11:11:02',
2755 'ip6': '2001:10::2'},
2756 {'mac': '00:00:11:11:11:03',
2758 'ip6': '2001:10::3'}]
2763 t4 = VppIpTable(self, 1)
2765 t6 = VppIpTable(self, 1, True)
2768 tun_ip4_uu = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
2769 self.pg4.remote_ip4, 114)
2770 tun_ip6_uu = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
2771 self.pg4.remote_ip4, 116)
2772 tun_ip4_uu.add_vpp_config()
2773 tun_ip6_uu.add_vpp_config()
2775 rd1 = VppGbpRouteDomain(self, 2, 401, t4, t6, tun_ip4_uu, tun_ip6_uu)
2776 rd1.add_vpp_config()
2778 self.loop0.set_mac(self.router_mac)
2781 # Bind the BVI to the RD
2783 b4 = VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
2784 b6 = VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
2787 # Pg2 hosts the vxlan tunnel
2788 # hosts on pg2 to act as TEPs
2792 self.pg2.config_ip4()
2793 self.pg2.resolve_arp()
2794 self.pg2.generate_remote_hosts(4)
2795 self.pg2.configure_ipv4_neighbors()
2796 self.pg3.config_ip4()
2797 self.pg3.resolve_arp()
2798 self.pg4.config_ip4()
2799 self.pg4.resolve_arp()
2802 # a GBP bridge domain with a BVI and a UU-flood interface
2804 bd1 = VppBridgeDomain(self, 1)
2805 bd1.add_vpp_config()
2806 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0, self.pg3)
2807 gbd1.add_vpp_config()
2809 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2810 self.logger.info(self.vapi.cli("sh gbp bridge"))
2811 self.logger.info(self.vapi.cli("sh gbp route"))
2813 # ... and has a /32 and /128 applied
2814 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi,
2816 bind=b4).add_vpp_config()
2817 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi,
2818 "2001:10::128", 128,
2819 bind=b6).add_vpp_config()
2822 # The Endpoint-group in which we are learning endpoints
2824 epg_220 = VppGbpEndpointGroup(self, 220, 441, rd1, gbd1,
2828 VppGbpEndpointRetention(4))
2829 epg_220.add_vpp_config()
2832 # The VXLAN GBP tunnel is in L3 mode with learning enabled
2834 vx_tun_l3 = VppGbpVxlanTunnel(
2835 self, 101, rd1.rd_id,
2836 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
2838 vx_tun_l3.add_vpp_config()
2841 # A static endpoint that the learnt endpoints are trying to
2844 ep = VppGbpEndpoint(self, self.pg0,
2846 "10.0.0.127", "11.0.0.127",
2847 "2001:10::1", "3001::1")
2851 # learn some remote IPv4 EPs
2853 for ii, l in enumerate(learnt):
2854 # a packet with an sclass from a known EPG
2855 # arriving on an unknown TEP
2856 p = (Ether(src=self.pg2.remote_mac,
2857 dst=self.pg2.local_mac) /
2858 IP(src=self.pg2.remote_hosts[1].ip4,
2859 dst=self.pg2.local_ip4) /
2860 UDP(sport=1234, dport=48879) /
2861 VXLAN(vni=101, gpid=441, flags=0x88) /
2862 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2863 IP(src=l['ip'], dst=ep.ip4) /
2864 UDP(sport=1234, dport=1234) /
2867 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2870 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2873 self.pg2.remote_hosts[1].ip4,
2875 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2877 # endpoint learnt via the parent GBP-vxlan interface
2878 self.assertTrue(find_gbp_endpoint(self,
2879 vx_tun_l3._sw_if_index,
2883 # Static IPv4 EP replies to learnt
2886 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2887 IP(dst=l['ip'], src=ep.ip4) /
2888 UDP(sport=1234, dport=1234) /
2891 rxs = self.send_and_expect(self.pg0, p * 1, self.pg2)
2894 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2895 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2896 self.assertEqual(rx[UDP].dport, 48879)
2897 # the UDP source port is a random value for hashing
2898 self.assertEqual(rx[VXLAN].gpid, 441)
2899 self.assertEqual(rx[VXLAN].vni, 101)
2900 self.assertTrue(rx[VXLAN].flags.G)
2901 self.assertTrue(rx[VXLAN].flags.Instance)
2902 self.assertTrue(rx[VXLAN].gpflags.A)
2903 self.assertFalse(rx[VXLAN].gpflags.D)
2905 inner = rx[VXLAN].payload
2907 self.assertEqual(inner[Ether].src, routed_src_mac)
2908 self.assertEqual(inner[Ether].dst, routed_dst_mac)
2909 self.assertEqual(inner[IP].src, ep.ip4)
2910 self.assertEqual(inner[IP].dst, l['ip'])
2913 self.assertFalse(find_gbp_endpoint(self,
2918 # learn some remote IPv6 EPs
2920 for ii, l in enumerate(learnt):
2921 # a packet with an sclass from a known EPG
2922 # arriving on an unknown TEP
2923 p = (Ether(src=self.pg2.remote_mac,
2924 dst=self.pg2.local_mac) /
2925 IP(src=self.pg2.remote_hosts[1].ip4,
2926 dst=self.pg2.local_ip4) /
2927 UDP(sport=1234, dport=48879) /
2928 VXLAN(vni=101, gpid=441, flags=0x88) /
2929 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2930 IPv6(src=l['ip6'], dst=ep.ip6) /
2931 UDP(sport=1234, dport=1234) /
2934 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2937 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2940 self.pg2.remote_hosts[1].ip4,
2942 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2944 self.logger.info(self.vapi.cli("show gbp bridge"))
2945 self.logger.info(self.vapi.cli("show vxlan-gbp tunnel"))
2946 self.logger.info(self.vapi.cli("show gbp vxlan"))
2947 self.logger.info(self.vapi.cli("show int addr"))
2949 # endpoint learnt via the TEP
2950 self.assertTrue(find_gbp_endpoint(self, ip=l['ip6']))
2952 self.logger.info(self.vapi.cli("show gbp endpoint"))
2953 self.logger.info(self.vapi.cli("show ip fib index 1 %s" % l['ip']))
2956 # Static EP replies to learnt
2959 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2960 IPv6(dst=l['ip6'], src=ep.ip6) /
2961 UDP(sport=1234, dport=1234) /
2964 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
2967 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2968 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2969 self.assertEqual(rx[UDP].dport, 48879)
2970 # the UDP source port is a random value for hashing
2971 self.assertEqual(rx[VXLAN].gpid, 441)
2972 self.assertEqual(rx[VXLAN].vni, 101)
2973 self.assertTrue(rx[VXLAN].flags.G)
2974 self.assertTrue(rx[VXLAN].flags.Instance)
2975 self.assertTrue(rx[VXLAN].gpflags.A)
2976 self.assertFalse(rx[VXLAN].gpflags.D)
2978 inner = rx[VXLAN].payload
2980 self.assertEqual(inner[Ether].src, routed_src_mac)
2981 self.assertEqual(inner[Ether].dst, routed_dst_mac)
2982 self.assertEqual(inner[IPv6].src, ep.ip6)
2983 self.assertEqual(inner[IPv6].dst, l['ip6'])
2985 self.logger.info(self.vapi.cli("sh gbp endpoint"))
2987 self.wait_for_ep_timeout(ip=l['ip'])
2990 # Static sends to unknown EP with no route
2992 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2993 IP(dst="10.0.0.99", src=ep.ip4) /
2994 UDP(sport=1234, dport=1234) /
2997 self.send_and_assert_no_replies(self.pg0, [p])
3000 # Add a route to static EP's v4 and v6 subnet
3002 se_10_24 = VppGbpSubnet(
3003 self, rd1, "10.0.0.0", 24,
3004 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT)
3005 se_10_24.add_vpp_config()
3008 # static pings router
3010 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
3011 IP(dst=epg_220.bvi_ip4, src=ep.ip4) /
3012 UDP(sport=1234, dport=1234) /
3015 self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg0)
3017 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
3018 IPv6(dst=epg_220.bvi_ip6, src=ep.ip6) /
3019 UDP(sport=1234, dport=1234) /
3022 self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg0)
3025 # packets to address in the subnet are sent on the uu-fwd
3027 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
3028 IP(dst="10.0.0.99", src=ep.ip4) /
3029 UDP(sport=1234, dport=1234) /
3032 rxs = self.send_and_expect(self.pg0, [p], self.pg4)
3034 self.assertEqual(rx[IP].src, self.pg4.local_ip4)
3035 self.assertEqual(rx[IP].dst, self.pg4.remote_ip4)
3036 self.assertEqual(rx[UDP].dport, 48879)
3037 # the UDP source port is a random value for hashing
3038 self.assertEqual(rx[VXLAN].gpid, 441)
3039 self.assertEqual(rx[VXLAN].vni, 114)
3040 self.assertTrue(rx[VXLAN].flags.G)
3041 self.assertTrue(rx[VXLAN].flags.Instance)
3042 # policy is not applied to packets sent to the uu-fwd interfaces
3043 self.assertFalse(rx[VXLAN].gpflags.A)
3044 self.assertFalse(rx[VXLAN].gpflags.D)
3047 # learn some remote IPv4 EPs
3049 for ii, l in enumerate(learnt):
3050 # a packet with an sclass from a known EPG
3051 # arriving on an unknown TEP
3052 p = (Ether(src=self.pg2.remote_mac,
3053 dst=self.pg2.local_mac) /
3054 IP(src=self.pg2.remote_hosts[2].ip4,
3055 dst=self.pg2.local_ip4) /
3056 UDP(sport=1234, dport=48879) /
3057 VXLAN(vni=101, gpid=441, flags=0x88) /
3058 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
3059 IP(src=l['ip'], dst=ep.ip4) /
3060 UDP(sport=1234, dport=1234) /
3063 rx = self.send_and_expect(self.pg2, [p], self.pg0)
3066 tep1_sw_if_index = find_vxlan_gbp_tunnel(
3069 self.pg2.remote_hosts[2].ip4,
3071 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
3073 # endpoint learnt via the parent GBP-vxlan interface
3074 self.assertTrue(find_gbp_endpoint(self,
3075 vx_tun_l3._sw_if_index,
3079 # Add a remote endpoint from the API
3081 rep_88 = VppGbpEndpoint(self, vx_tun_l3,
3083 "10.0.0.88", "11.0.0.88",
3084 "2001:10::88", "3001::88",
3085 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
3087 self.pg2.remote_hosts[2].ip4,
3089 rep_88.add_vpp_config()
3092 # Add a remote endpoint from the API that matches an existing one
3093 # this is a lower priority, hence the packet is sent to the DP leanrt
3096 rep_2 = VppGbpEndpoint(self, vx_tun_l3,
3098 learnt[0]['ip'], "11.0.0.101",
3099 learnt[0]['ip6'], "3001::101",
3100 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
3102 self.pg2.remote_hosts[1].ip4,
3104 rep_2.add_vpp_config()
3107 # Add a route to the learned EP's v4 subnet
3108 # packets should be send on the v4/v6 uu=fwd interface resp.
3110 se_10_1_24 = VppGbpSubnet(
3111 self, rd1, "10.0.1.0", 24,
3112 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT)
3113 se_10_1_24.add_vpp_config()
3115 self.logger.info(self.vapi.cli("show gbp endpoint"))
3117 ips = ["10.0.0.88", learnt[0]['ip']]
3119 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
3120 IP(dst=ip, src=ep.ip4) /
3121 UDP(sport=1234, dport=1234) /
3124 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
3127 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
3128 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[2].ip4)
3129 self.assertEqual(rx[UDP].dport, 48879)
3130 # the UDP source port is a random value for hashing
3131 self.assertEqual(rx[VXLAN].gpid, 441)
3132 self.assertEqual(rx[VXLAN].vni, 101)
3133 self.assertTrue(rx[VXLAN].flags.G)
3134 self.assertTrue(rx[VXLAN].flags.Instance)
3135 self.assertTrue(rx[VXLAN].gpflags.A)
3136 self.assertFalse(rx[VXLAN].gpflags.D)
3138 inner = rx[VXLAN].payload
3140 self.assertEqual(inner[Ether].src, routed_src_mac)
3141 self.assertEqual(inner[Ether].dst, routed_dst_mac)
3142 self.assertEqual(inner[IP].src, ep.ip4)
3143 self.assertEqual(inner[IP].dst, ip)
3146 # remove the API remote EPs, only API sourced is gone, the DP
3147 # learnt one remains
3149 rep_88.remove_vpp_config()
3150 rep_2.remove_vpp_config()
3152 self.assertTrue(find_gbp_endpoint(self, ip=rep_2.ip4))
3154 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
3155 IP(src=ep.ip4, dst=rep_2.ip4) /
3156 UDP(sport=1234, dport=1234) /
3158 rxs = self.send_and_expect(self.pg0, [p], self.pg2)
3160 self.assertFalse(find_gbp_endpoint(self, ip=rep_88.ip4))
3162 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
3163 IP(src=ep.ip4, dst=rep_88.ip4) /
3164 UDP(sport=1234, dport=1234) /
3166 rxs = self.send_and_expect(self.pg0, [p], self.pg4)
3169 # to appease the testcase we cannot have the registered EP still
3170 # present (because it's DP learnt) when the TC ends so wait until
3173 self.wait_for_ep_timeout(ip=rep_88.ip4)
3174 self.wait_for_ep_timeout(ip=rep_2.ip4)
3177 # Same as above, learn a remote EP via CP and DP
3178 # this time remove the DP one first. expect the CP data to remain
3180 rep_3 = VppGbpEndpoint(self, vx_tun_l3,
3182 "10.0.1.4", "11.0.0.103",
3183 "2001::10:3", "3001::103",
3184 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
3186 self.pg2.remote_hosts[1].ip4,
3188 rep_3.add_vpp_config()
3190 p = (Ether(src=self.pg2.remote_mac,
3191 dst=self.pg2.local_mac) /
3192 IP(src=self.pg2.remote_hosts[2].ip4,
3193 dst=self.pg2.local_ip4) /
3194 UDP(sport=1234, dport=48879) /
3195 VXLAN(vni=101, gpid=441, flags=0x88) /
3196 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
3197 IP(src="10.0.1.4", dst=ep.ip4) /
3198 UDP(sport=1234, dport=1234) /
3200 rxs = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
3202 self.assertTrue(find_gbp_endpoint(self,
3203 vx_tun_l3._sw_if_index,
3205 tep=[self.pg2.local_ip4,
3206 self.pg2.remote_hosts[2].ip4]))
3208 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
3209 IP(dst="10.0.1.4", src=ep.ip4) /
3210 UDP(sport=1234, dport=1234) /
3212 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
3214 # host 2 is the DP learned TEP
3216 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
3217 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[2].ip4)
3219 self.wait_for_ep_timeout(ip=rep_3.ip4,
3220 tep=[self.pg2.local_ip4,
3221 self.pg2.remote_hosts[2].ip4])
3223 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
3225 # host 1 is the CP learned TEP
3227 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
3228 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
3231 # shutdown with learnt endpoint present
3233 p = (Ether(src=self.pg2.remote_mac,
3234 dst=self.pg2.local_mac) /
3235 IP(src=self.pg2.remote_hosts[1].ip4,
3236 dst=self.pg2.local_ip4) /
3237 UDP(sport=1234, dport=48879) /
3238 VXLAN(vni=101, gpid=441, flags=0x88) /
3239 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
3240 IP(src=learnt[1]['ip'], dst=ep.ip4) /
3241 UDP(sport=1234, dport=1234) /
3244 rx = self.send_and_expect(self.pg2, [p], self.pg0)
3246 # endpoint learnt via the parent GBP-vxlan interface
3247 self.assertTrue(find_gbp_endpoint(self,
3248 vx_tun_l3._sw_if_index,
3253 # remote endpoint becomes local
3255 self.pg2.unconfig_ip4()
3256 self.pg3.unconfig_ip4()
3257 self.pg4.unconfig_ip4()
3259 def test_gbp_redirect(self):
3260 """ GBP Endpoint Redirect """
3262 self.vapi.cli("set logging class gbp level debug")
3264 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
3265 routed_dst_mac = "00:0c:0c:0c:0c:0c"
3266 routed_src_mac = "00:22:bd:f8:19:ff"
3268 learnt = [{'mac': '00:00:11:11:11:02',
3270 'ip6': '2001:10::2'},
3271 {'mac': '00:00:11:11:11:03',
3273 'ip6': '2001:10::3'}]
3278 t4 = VppIpTable(self, 1)
3280 t6 = VppIpTable(self, 1, True)
3283 rd1 = VppGbpRouteDomain(self, 2, 402, t4, t6)
3284 rd1.add_vpp_config()
3286 self.loop0.set_mac(self.router_mac)
3289 # Bind the BVI to the RD
3291 b_ip4 = VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
3292 b_ip6 = VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
3295 # Pg7 hosts a BD's UU-fwd
3297 self.pg7.config_ip4()
3298 self.pg7.resolve_arp()
3301 # a GBP bridge domains for the EPs
3303 bd1 = VppBridgeDomain(self, 1)
3304 bd1.add_vpp_config()
3305 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0)
3306 gbd1.add_vpp_config()
3308 bd2 = VppBridgeDomain(self, 2)
3309 bd2.add_vpp_config()
3310 gbd2 = VppGbpBridgeDomain(self, bd2, rd1, self.loop1)
3311 gbd2.add_vpp_config()
3313 # ... and has a /32 and /128 applied
3314 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi,
3316 bind=b_ip4).add_vpp_config()
3317 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi,
3318 "2001:10::128", 128,
3319 bind=b_ip6).add_vpp_config()
3320 ip4_addr = VppIpInterfaceAddress(self, gbd2.bvi,
3321 "10.0.1.128", 32).add_vpp_config()
3322 ip6_addr = VppIpInterfaceAddress(self, gbd2.bvi,
3323 "2001:11::128", 128).add_vpp_config()
3326 # The Endpoint-groups in which we are learning endpoints
3328 epg_220 = VppGbpEndpointGroup(self, 220, 440, rd1, gbd1,
3332 VppGbpEndpointRetention(60))
3333 epg_220.add_vpp_config()
3334 epg_221 = VppGbpEndpointGroup(self, 221, 441, rd1, gbd2,
3338 VppGbpEndpointRetention(60))
3339 epg_221.add_vpp_config()
3340 epg_222 = VppGbpEndpointGroup(self, 222, 442, rd1, gbd1,
3344 VppGbpEndpointRetention(60))
3345 epg_222.add_vpp_config()
3348 # a GBP bridge domains for the SEPs
3350 bd_uu1 = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
3351 self.pg7.remote_ip4, 116)
3352 bd_uu1.add_vpp_config()
3353 bd_uu2 = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
3354 self.pg7.remote_ip4, 117)
3355 bd_uu2.add_vpp_config()
3357 bd3 = VppBridgeDomain(self, 3)
3358 bd3.add_vpp_config()
3359 gbd3 = VppGbpBridgeDomain(self, bd3, rd1, self.loop2,
3360 bd_uu1, learn=False)
3361 gbd3.add_vpp_config()
3362 bd4 = VppBridgeDomain(self, 4)
3363 bd4.add_vpp_config()
3364 gbd4 = VppGbpBridgeDomain(self, bd4, rd1, self.loop3,
3365 bd_uu2, learn=False)
3366 gbd4.add_vpp_config()
3369 # EPGs in which the service endpoints exist
3371 epg_320 = VppGbpEndpointGroup(self, 320, 550, rd1, gbd3,
3375 VppGbpEndpointRetention(60))
3376 epg_320.add_vpp_config()
3377 epg_321 = VppGbpEndpointGroup(self, 321, 551, rd1, gbd4,
3381 VppGbpEndpointRetention(60))
3382 epg_321.add_vpp_config()
3385 # three local endpoints
3387 ep1 = VppGbpEndpoint(self, self.pg0,
3389 "10.0.0.1", "11.0.0.1",
3390 "2001:10::1", "3001:10::1")
3391 ep1.add_vpp_config()
3392 ep2 = VppGbpEndpoint(self, self.pg1,
3394 "10.0.1.1", "11.0.1.1",
3395 "2001:11::1", "3001:11::1")
3396 ep2.add_vpp_config()
3397 ep3 = VppGbpEndpoint(self, self.pg2,
3399 "10.0.2.2", "11.0.2.2",
3400 "2001:12::1", "3001:12::1")
3401 ep3.add_vpp_config()
3406 sep1 = VppGbpEndpoint(self, self.pg3,
3408 "12.0.0.1", "13.0.0.1",
3409 "4001:10::1", "5001:10::1")
3410 sep1.add_vpp_config()
3411 sep2 = VppGbpEndpoint(self, self.pg4,
3413 "12.0.0.2", "13.0.0.2",
3414 "4001:10::2", "5001:10::2")
3415 sep2.add_vpp_config()
3416 sep3 = VppGbpEndpoint(self, self.pg5,
3418 "12.0.1.1", "13.0.1.1",
3419 "4001:11::1", "5001:11::1")
3420 sep3.add_vpp_config()
3421 # this EP is not installed immediately
3422 sep4 = VppGbpEndpoint(self, self.pg6,
3424 "12.0.1.2", "13.0.1.2",
3425 "4001:11::2", "5001:11::2")
3428 # an L2 switch packet between local EPs in different EPGs
3429 # different dest ports on each so the are LB hashed differently
3431 p4 = [(Ether(src=ep1.mac, dst=ep3.mac) /
3432 IP(src=ep1.ip4, dst=ep3.ip4) /
3433 UDP(sport=1234, dport=1234) /
3434 Raw(b'\xa5' * 100)),
3435 (Ether(src=ep3.mac, dst=ep1.mac) /
3436 IP(src=ep3.ip4, dst=ep1.ip4) /
3437 UDP(sport=1234, dport=1234) /
3438 Raw(b'\xa5' * 100))]
3439 p6 = [(Ether(src=ep1.mac, dst=ep3.mac) /
3440 IPv6(src=ep1.ip6, dst=ep3.ip6) /
3441 UDP(sport=1234, dport=1234) /
3442 Raw(b'\xa5' * 100)),
3443 (Ether(src=ep3.mac, dst=ep1.mac) /
3444 IPv6(src=ep3.ip6, dst=ep1.ip6) /
3445 UDP(sport=1234, dport=1230) /
3446 Raw(b'\xa5' * 100))]
3448 # should be dropped since no contract yet
3449 self.send_and_assert_no_replies(self.pg0, [p4[0]])
3450 self.send_and_assert_no_replies(self.pg0, [p6[0]])
3453 # Add a contract with a rule to load-balance redirect via SEP1 and SEP2
3454 # one of the next-hops is via an EP that is not known
3456 rule4 = AclRule(is_permit=1, proto=17)
3457 rule6 = AclRule(src_prefix=IPv6Network((0, 0)),
3458 dst_prefix=IPv6Network((0, 0)), is_permit=1, proto=17)
3459 acl = VppAcl(self, rules=[rule4, rule6])
3460 acl.add_vpp_config()
3463 # test the src-ip hash mode
3465 c1 = VppGbpContract(
3466 self, 402, epg_220.sclass, epg_222.sclass, acl.acl_index,
3467 [VppGbpContractRule(
3468 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3469 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3470 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3471 sep1.ip4, sep1.epg.rd),
3472 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3473 sep2.ip4, sep2.epg.rd)]),
3475 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3476 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3477 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3478 sep3.ip6, sep3.epg.rd),
3479 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3480 sep4.ip6, sep4.epg.rd)])],
3481 [ETH_P_IP, ETH_P_IPV6])
3484 c2 = VppGbpContract(
3485 self, 402, epg_222.sclass, epg_220.sclass, acl.acl_index,
3486 [VppGbpContractRule(
3487 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3488 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3489 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3490 sep1.ip4, sep1.epg.rd),
3491 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3492 sep2.ip4, sep2.epg.rd)]),
3494 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3495 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3496 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3497 sep3.ip6, sep3.epg.rd),
3498 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3499 sep4.ip6, sep4.epg.rd)])],
3500 [ETH_P_IP, ETH_P_IPV6])
3504 # send again with the contract preset, now packets arrive
3505 # at SEP1 or SEP2 depending on the hashing
3507 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3510 self.assertEqual(rx[Ether].src, routed_src_mac)
3511 self.assertEqual(rx[Ether].dst, sep1.mac)
3512 self.assertEqual(rx[IP].src, ep1.ip4)
3513 self.assertEqual(rx[IP].dst, ep3.ip4)
3515 rxs = self.send_and_expect(self.pg2, p4[1] * 17, sep2.itf)
3518 self.assertEqual(rx[Ether].src, routed_src_mac)
3519 self.assertEqual(rx[Ether].dst, sep2.mac)
3520 self.assertEqual(rx[IP].src, ep3.ip4)
3521 self.assertEqual(rx[IP].dst, ep1.ip4)
3523 rxs = self.send_and_expect(self.pg0, p6[0] * 17, self.pg7)
3526 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3527 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3528 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3529 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
3530 self.assertEqual(rx[VXLAN].vni, 117)
3531 self.assertTrue(rx[VXLAN].flags.G)
3532 self.assertTrue(rx[VXLAN].flags.Instance)
3533 # redirect policy has been applied
3534 self.assertTrue(rx[VXLAN].gpflags.A)
3535 self.assertFalse(rx[VXLAN].gpflags.D)
3537 inner = rx[VXLAN].payload
3539 self.assertEqual(inner[Ether].src, routed_src_mac)
3540 self.assertEqual(inner[Ether].dst, sep4.mac)
3541 self.assertEqual(inner[IPv6].src, ep1.ip6)
3542 self.assertEqual(inner[IPv6].dst, ep3.ip6)
3544 rxs = self.send_and_expect(self.pg2, p6[1] * 17, sep3.itf)
3547 self.assertEqual(rx[Ether].src, routed_src_mac)
3548 self.assertEqual(rx[Ether].dst, sep3.mac)
3549 self.assertEqual(rx[IPv6].src, ep3.ip6)
3550 self.assertEqual(rx[IPv6].dst, ep1.ip6)
3553 # programme the unknown EP
3555 sep4.add_vpp_config()
3557 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep4.itf)
3560 self.assertEqual(rx[Ether].src, routed_src_mac)
3561 self.assertEqual(rx[Ether].dst, sep4.mac)
3562 self.assertEqual(rx[IPv6].src, ep1.ip6)
3563 self.assertEqual(rx[IPv6].dst, ep3.ip6)
3566 # and revert back to unprogrammed
3568 sep4.remove_vpp_config()
3570 rxs = self.send_and_expect(self.pg0, p6[0] * 17, self.pg7)
3573 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3574 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3575 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3576 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
3577 self.assertEqual(rx[VXLAN].vni, 117)
3578 self.assertTrue(rx[VXLAN].flags.G)
3579 self.assertTrue(rx[VXLAN].flags.Instance)
3580 # redirect policy has been applied
3581 self.assertTrue(rx[VXLAN].gpflags.A)
3582 self.assertFalse(rx[VXLAN].gpflags.D)
3584 inner = rx[VXLAN].payload
3586 self.assertEqual(inner[Ether].src, routed_src_mac)
3587 self.assertEqual(inner[Ether].dst, sep4.mac)
3588 self.assertEqual(inner[IPv6].src, ep1.ip6)
3589 self.assertEqual(inner[IPv6].dst, ep3.ip6)
3591 c1.remove_vpp_config()
3592 c2.remove_vpp_config()
3595 # test the symmetric hash mode
3597 c1 = VppGbpContract(
3598 self, 402, epg_220.sclass, epg_222.sclass, acl.acl_index,
3599 [VppGbpContractRule(
3600 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3601 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3602 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3603 sep1.ip4, sep1.epg.rd),
3604 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3605 sep2.ip4, sep2.epg.rd)]),
3607 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3608 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3609 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3610 sep3.ip6, sep3.epg.rd),
3611 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3612 sep4.ip6, sep4.epg.rd)])],
3613 [ETH_P_IP, ETH_P_IPV6])
3616 c2 = VppGbpContract(
3617 self, 402, epg_222.sclass, epg_220.sclass, acl.acl_index,
3618 [VppGbpContractRule(
3619 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3620 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3621 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3622 sep1.ip4, sep1.epg.rd),
3623 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3624 sep2.ip4, sep2.epg.rd)]),
3626 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3627 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3628 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3629 sep3.ip6, sep3.epg.rd),
3630 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3631 sep4.ip6, sep4.epg.rd)])],
3632 [ETH_P_IP, ETH_P_IPV6])
3636 # send again with the contract preset, now packets arrive
3637 # at SEP1 for both directions
3639 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3642 self.assertEqual(rx[Ether].src, routed_src_mac)
3643 self.assertEqual(rx[Ether].dst, sep1.mac)
3644 self.assertEqual(rx[IP].src, ep1.ip4)
3645 self.assertEqual(rx[IP].dst, ep3.ip4)
3647 rxs = self.send_and_expect(self.pg2, p4[1] * 17, sep1.itf)
3650 self.assertEqual(rx[Ether].src, routed_src_mac)
3651 self.assertEqual(rx[Ether].dst, sep1.mac)
3652 self.assertEqual(rx[IP].src, ep3.ip4)
3653 self.assertEqual(rx[IP].dst, ep1.ip4)
3656 # programme the unknown EP for the L3 tests
3658 sep4.add_vpp_config()
3661 # an L3 switch packet between local EPs in different EPGs
3662 # different dest ports on each so the are LB hashed differently
3664 p4 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3665 IP(src=ep1.ip4, dst=ep2.ip4) /
3666 UDP(sport=1234, dport=1234) /
3667 Raw(b'\xa5' * 100)),
3668 (Ether(src=ep2.mac, dst=str(self.router_mac)) /
3669 IP(src=ep2.ip4, dst=ep1.ip4) /
3670 UDP(sport=1234, dport=1234) /
3671 Raw(b'\xa5' * 100))]
3672 p6 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3673 IPv6(src=ep1.ip6, dst=ep2.ip6) /
3674 UDP(sport=1234, dport=1234) /
3675 Raw(b'\xa5' * 100)),
3676 (Ether(src=ep2.mac, dst=str(self.router_mac)) /
3677 IPv6(src=ep2.ip6, dst=ep1.ip6) /
3678 UDP(sport=1234, dport=1234) /
3679 Raw(b'\xa5' * 100))]
3681 c3 = VppGbpContract(
3682 self, 402, epg_220.sclass, epg_221.sclass, acl.acl_index,
3683 [VppGbpContractRule(
3684 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3685 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3686 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3687 sep1.ip4, sep1.epg.rd),
3688 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3689 sep2.ip4, sep2.epg.rd)]),
3691 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3692 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3693 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3694 sep3.ip6, sep3.epg.rd),
3695 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3696 sep4.ip6, sep4.epg.rd)])],
3697 [ETH_P_IP, ETH_P_IPV6])
3700 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3703 self.assertEqual(rx[Ether].src, routed_src_mac)
3704 self.assertEqual(rx[Ether].dst, sep1.mac)
3705 self.assertEqual(rx[IP].src, ep1.ip4)
3706 self.assertEqual(rx[IP].dst, ep2.ip4)
3709 # learn a remote EP in EPG 221
3710 # packets coming from unknown remote EPs will be leant & redirected
3712 vx_tun_l3 = VppGbpVxlanTunnel(
3713 self, 444, rd1.rd_id,
3714 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
3716 vx_tun_l3.add_vpp_config()
3718 c4 = VppGbpContract(
3719 self, 402, epg_221.sclass, epg_220.sclass, acl.acl_index,
3720 [VppGbpContractRule(
3721 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3722 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3723 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3724 sep1.ip4, sep1.epg.rd),
3725 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3726 sep2.ip4, sep2.epg.rd)]),
3728 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3729 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3730 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3731 sep3.ip6, sep3.epg.rd),
3732 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3733 sep4.ip6, sep4.epg.rd)])],
3734 [ETH_P_IP, ETH_P_IPV6])
3737 p = (Ether(src=self.pg7.remote_mac,
3738 dst=self.pg7.local_mac) /
3739 IP(src=self.pg7.remote_ip4,
3740 dst=self.pg7.local_ip4) /
3741 UDP(sport=1234, dport=48879) /
3742 VXLAN(vni=444, gpid=441, flags=0x88) /
3743 Ether(src="00:22:22:22:22:33", dst=str(self.router_mac)) /
3744 IP(src="10.0.0.88", dst=ep1.ip4) /
3745 UDP(sport=1234, dport=1234) /
3748 # unknown remote EP to local EP redirected
3749 rxs = self.send_and_expect(self.pg7, [p], sep1.itf)
3752 self.assertEqual(rx[Ether].src, routed_src_mac)
3753 self.assertEqual(rx[Ether].dst, sep1.mac)
3754 self.assertEqual(rx[IP].src, "10.0.0.88")
3755 self.assertEqual(rx[IP].dst, ep1.ip4)
3757 # endpoint learnt via the parent GBP-vxlan interface
3758 self.assertTrue(find_gbp_endpoint(self,
3759 vx_tun_l3._sw_if_index,
3762 p = (Ether(src=self.pg7.remote_mac,
3763 dst=self.pg7.local_mac) /
3764 IP(src=self.pg7.remote_ip4,
3765 dst=self.pg7.local_ip4) /
3766 UDP(sport=1234, dport=48879) /
3767 VXLAN(vni=444, gpid=441, flags=0x88) /
3768 Ether(src="00:22:22:22:22:33", dst=str(self.router_mac)) /
3769 IPv6(src="2001:10::88", dst=ep1.ip6) /
3770 UDP(sport=1234, dport=1234) /
3773 # unknown remote EP to local EP redirected (ipv6)
3774 rxs = self.send_and_expect(self.pg7, [p], sep3.itf)
3777 self.assertEqual(rx[Ether].src, routed_src_mac)
3778 self.assertEqual(rx[Ether].dst, sep3.mac)
3779 self.assertEqual(rx[IPv6].src, "2001:10::88")
3780 self.assertEqual(rx[IPv6].dst, ep1.ip6)
3782 # endpoint learnt via the parent GBP-vxlan interface
3783 self.assertTrue(find_gbp_endpoint(self,
3784 vx_tun_l3._sw_if_index,
3788 # L3 switch from local to remote EP
3790 p4 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3791 IP(src=ep1.ip4, dst="10.0.0.88") /
3792 UDP(sport=1234, dport=1234) /
3793 Raw(b'\xa5' * 100))]
3794 p6 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3795 IPv6(src=ep1.ip6, dst="2001:10::88") /
3796 UDP(sport=1234, dport=1234) /
3797 Raw(b'\xa5' * 100))]
3799 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3802 self.assertEqual(rx[Ether].src, routed_src_mac)
3803 self.assertEqual(rx[Ether].dst, sep1.mac)
3804 self.assertEqual(rx[IP].src, ep1.ip4)
3805 self.assertEqual(rx[IP].dst, "10.0.0.88")
3807 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep4.itf)
3810 self.assertEqual(rx[Ether].src, routed_src_mac)
3811 self.assertEqual(rx[Ether].dst, sep4.mac)
3812 self.assertEqual(rx[IPv6].src, ep1.ip6)
3813 self.assertEqual(rx[IPv6].dst, "2001:10::88")
3816 # test the dst-ip hash mode
3818 c5 = VppGbpContract(
3819 self, 402, epg_220.sclass, epg_221.sclass, acl.acl_index,
3820 [VppGbpContractRule(
3821 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3822 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
3823 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3824 sep1.ip4, sep1.epg.rd),
3825 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3826 sep2.ip4, sep2.epg.rd)]),
3828 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3829 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
3830 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3831 sep3.ip6, sep3.epg.rd),
3832 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3833 sep4.ip6, sep4.epg.rd)])],
3834 [ETH_P_IP, ETH_P_IPV6])
3837 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3840 self.assertEqual(rx[Ether].src, routed_src_mac)
3841 self.assertEqual(rx[Ether].dst, sep1.mac)
3842 self.assertEqual(rx[IP].src, ep1.ip4)
3843 self.assertEqual(rx[IP].dst, "10.0.0.88")
3845 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep3.itf)
3848 self.assertEqual(rx[Ether].src, routed_src_mac)
3849 self.assertEqual(rx[Ether].dst, sep3.mac)
3850 self.assertEqual(rx[IPv6].src, ep1.ip6)
3851 self.assertEqual(rx[IPv6].dst, "2001:10::88")
3854 # a programmed remote SEP in EPG 320
3857 # gbp vxlan tunnel for the remote SEP
3858 vx_tun_l3_sep = VppGbpVxlanTunnel(
3859 self, 555, rd1.rd_id,
3860 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
3862 vx_tun_l3_sep.add_vpp_config()
3865 sep5 = VppGbpEndpoint(self, vx_tun_l3_sep,
3867 "12.0.0.10", "13.0.0.10",
3868 "4001:10::10", "5001:10::10",
3869 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
3871 self.pg7.remote_ip4,
3873 sep5.add_vpp_config()
3876 # local l3out redirect tests
3881 self.loop4.set_mac(self.router_mac)
3882 b_lo4_ip4 = VppIpInterfaceBind(self, self.loop4, t4).add_vpp_config()
3883 b_lo4_ip6 = VppIpInterfaceBind(self, self.loop4, t6).add_vpp_config()
3884 ebd = VppBridgeDomain(self, 100)
3885 ebd.add_vpp_config()
3886 gebd = VppGbpBridgeDomain(self, ebd, rd1, self.loop4, None, None)
3887 gebd.add_vpp_config()
3889 eepg = VppGbpEndpointGroup(self, 888, 765, rd1, gebd,
3893 VppGbpEndpointRetention(60))
3894 eepg.add_vpp_config()
3895 # add subnets to BVI
3896 VppIpInterfaceAddress(
3900 24, bind=b_lo4_ip4).add_vpp_config()
3901 VppIpInterfaceAddress(
3905 64, bind=b_lo4_ip6).add_vpp_config()
3906 # ... which are L3-out subnets
3907 VppGbpSubnet(self, rd1, "10.1.0.0", 24,
3908 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3909 sclass=765).add_vpp_config()
3910 VppGbpSubnet(self, rd1, "2001:10:1::128", 64,
3911 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3912 sclass=765).add_vpp_config()
3913 # external endpoints
3914 VppL2Vtr(self, self.vlan_100, L2_VTR_OP.L2_POP_1).add_vpp_config()
3915 eep1 = VppGbpEndpoint(self, self.vlan_100, eepg, None, "10.1.0.1",
3916 "11.1.0.1", "2001:10:1::1", "3001:10:1::1",
3917 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
3918 eep1.add_vpp_config()
3919 VppL2Vtr(self, self.vlan_101, L2_VTR_OP.L2_POP_1).add_vpp_config()
3920 eep2 = VppGbpEndpoint(self, self.vlan_101, eepg, None, "10.1.0.2",
3921 "11.1.0.2", "2001:10:1::2", "3001:10:1::2",
3922 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
3923 eep2.add_vpp_config()
3925 # external subnets reachable though eep1 and eep2 respectively
3926 VppIpRoute(self, "10.220.0.0", 24,
3927 [VppRoutePath(eep1.ip4, eep1.epg.bvi.sw_if_index)],
3928 table_id=t4.table_id).add_vpp_config()
3929 VppGbpSubnet(self, rd1, "10.220.0.0", 24,
3930 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3931 sclass=4220).add_vpp_config()
3932 VppIpRoute(self, "10:220::", 64,
3933 [VppRoutePath(eep1.ip6, eep1.epg.bvi.sw_if_index)],
3934 table_id=t6.table_id).add_vpp_config()
3935 VppGbpSubnet(self, rd1, "10:220::", 64,
3936 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3937 sclass=4220).add_vpp_config()
3938 VppIpRoute(self, "10.221.0.0", 24,
3939 [VppRoutePath(eep2.ip4, eep2.epg.bvi.sw_if_index)],
3940 table_id=t4.table_id).add_vpp_config()
3941 VppGbpSubnet(self, rd1, "10.221.0.0", 24,
3942 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3943 sclass=4221).add_vpp_config()
3944 VppIpRoute(self, "10:221::", 64,
3945 [VppRoutePath(eep2.ip6, eep2.epg.bvi.sw_if_index)],
3946 table_id=t6.table_id).add_vpp_config()
3947 VppGbpSubnet(self, rd1, "10:221::", 64,
3948 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3949 sclass=4221).add_vpp_config()
3952 # l3out redirect to remote (known, then unknown) SEP
3955 # packets from 1 external subnet to the other
3956 p = [(Ether(src=eep1.mac, dst=self.router_mac) /
3958 IP(src="10.220.0.17", dst="10.221.0.65") /
3959 UDP(sport=1234, dport=1234) /
3960 Raw(b'\xa5' * 100)),
3961 (Ether(src=eep1.mac, dst=self.router_mac) /
3963 IPv6(src="10:220::17", dst="10:221::65") /
3964 UDP(sport=1234, dport=1234) /
3965 Raw(b'\xa5' * 100))]
3967 # packets should be dropped in absence of contract
3968 self.send_and_assert_no_replies(self.pg0, p)
3970 # contract redirecting to sep5
3972 self, 402, 4220, 4221, acl.acl_index,
3973 [VppGbpContractRule(
3974 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3975 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
3976 [VppGbpContractNextHop(sep5.vmac, sep5.epg.bd,
3977 sep5.ip4, sep5.epg.rd)]),
3979 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3980 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
3981 [VppGbpContractNextHop(sep5.vmac, sep5.epg.bd,
3982 sep5.ip6, sep5.epg.rd)])],
3983 [ETH_P_IP, ETH_P_IPV6]).add_vpp_config()
3985 rxs = self.send_and_expect(self.pg0, p, self.pg7)
3987 for rx, tx in zip(rxs, p):
3988 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3989 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3990 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3991 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
3992 # this should use the programmed remote leaf TEP
3993 self.assertEqual(rx[VXLAN].vni, 555)
3994 self.assertEqual(rx[VXLAN].gpid, 4220)
3995 self.assertTrue(rx[VXLAN].flags.G)
3996 self.assertTrue(rx[VXLAN].flags.Instance)
3997 # redirect policy has been applied
3998 self.assertTrue(rx[VXLAN].gpflags.A)
3999 self.assertTrue(rx[VXLAN].gpflags.D)
4000 rxip = rx[VXLAN][Ether].payload
4001 txip = tx[Dot1Q].payload
4002 self.assertEqual(rxip.src, txip.src)
4003 self.assertEqual(rxip.dst, txip.dst)
4005 # remote SEP: it is now an unknown remote SEP and should go
4007 sep5.remove_vpp_config()
4009 rxs = self.send_and_expect(self.pg0, p, self.pg7)
4011 for rx, tx in zip(rxs, p):
4012 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4013 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4014 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4015 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4016 # this should use the spine proxy TEP
4017 self.assertEqual(rx[VXLAN].vni, epg_320.bd.uu_fwd.vni)
4018 self.assertEqual(rx[VXLAN].gpid, 4220)
4019 self.assertTrue(rx[VXLAN].flags.G)
4020 self.assertTrue(rx[VXLAN].flags.Instance)
4021 # redirect policy has been applied
4022 self.assertTrue(rx[VXLAN].gpflags.A)
4023 self.assertTrue(rx[VXLAN].gpflags.D)
4024 rxip = rx[VXLAN][Ether].payload
4025 txip = tx[Dot1Q].payload
4026 self.assertEqual(rxip.src, txip.src)
4027 self.assertEqual(rxip.dst, txip.dst)
4030 # l3out redirect to local SEP
4033 # change the contract between l3out to redirect to local SEPs
4034 # instead of remote SEP
4036 self, 402, 4220, 4221, acl.acl_index,
4037 [VppGbpContractRule(
4038 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4039 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
4040 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
4041 sep1.ip4, sep1.epg.rd)]),
4043 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4044 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
4045 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
4046 sep1.ip6, sep1.epg.rd)])],
4047 [ETH_P_IP, ETH_P_IPV6]).add_vpp_config()
4049 rxs = self.send_and_expect(self.pg0, p, sep1.itf)
4050 for rx, tx in zip(rxs, p):
4051 self.assertEqual(rx[Ether].src, routed_src_mac)
4052 self.assertEqual(rx[Ether].dst, sep1.mac)
4053 rxip = rx[Ether].payload
4054 txip = tx[Ether].payload
4055 self.assertEqual(rxip.src, txip.src)
4056 self.assertEqual(rxip.dst, txip.dst)
4059 # redirect remote EP to remote (known then unknown) SEP
4062 # remote SEP known again
4063 sep5.add_vpp_config()
4065 # contract to redirect to learnt SEP
4067 self, 402, epg_221.sclass, epg_222.sclass, acl.acl_index,
4068 [VppGbpContractRule(
4069 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4070 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
4071 [VppGbpContractNextHop(sep5.vmac, sep5.epg.bd,
4072 sep5.ip4, sep5.epg.rd)]),
4074 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4075 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
4076 [VppGbpContractNextHop(sep5.vmac, sep5.epg.bd,
4077 sep5.ip6, sep5.epg.rd)])],
4078 [ETH_P_IP, ETH_P_IPV6]).add_vpp_config()
4080 # packets from unknown EP 221 to known EP in EPG 222
4081 # should be redirected to known remote SEP
4082 base = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
4083 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
4084 UDP(sport=1234, dport=48879) /
4085 VXLAN(vni=444, gpid=441, flags=0x88) /
4086 Ether(src="00:22:22:22:22:44", dst=str(self.router_mac)))
4088 IP(src="10.0.1.100", dst=ep3.ip4) /
4089 UDP(sport=1234, dport=1234) /
4090 Raw(b'\xa5' * 100)),
4092 IPv6(src="2001:10::100", dst=ep3.ip6) /
4093 UDP(sport=1234, dport=1234) /
4094 Raw(b'\xa5' * 100))]
4096 # unknown remote EP to local EP redirected to known remote SEP
4097 rxs = self.send_and_expect(self.pg7, p, self.pg7)
4099 for rx, tx in zip(rxs, p):
4100 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4101 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4102 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4103 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4104 # this should use the programmed remote leaf TEP
4105 self.assertEqual(rx[VXLAN].vni, 555)
4106 self.assertEqual(rx[VXLAN].gpid, epg_221.sclass)
4107 self.assertTrue(rx[VXLAN].flags.G)
4108 self.assertTrue(rx[VXLAN].flags.Instance)
4109 # redirect policy has been applied
4110 self.assertTrue(rx[VXLAN].gpflags.A)
4111 self.assertFalse(rx[VXLAN].gpflags.D)
4112 rxip = rx[VXLAN][Ether].payload
4113 txip = tx[VXLAN][Ether].payload
4114 self.assertEqual(rxip.src, txip.src)
4115 self.assertEqual(rxip.dst, txip.dst)
4117 # endpoint learnt via the parent GBP-vxlan interface
4118 self.assertTrue(find_gbp_endpoint(self,
4119 vx_tun_l3._sw_if_index,
4121 self.assertTrue(find_gbp_endpoint(self,
4122 vx_tun_l3._sw_if_index,
4125 # remote SEP: it is now an unknown remote SEP and should go
4127 sep5.remove_vpp_config()
4129 # remote EP (coming from spine proxy) to local EP redirected to
4131 rxs = self.send_and_expect(self.pg7, p, self.pg7)
4133 for rx, tx in zip(rxs, p):
4134 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4135 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4136 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4137 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4138 # this should use the spine proxy TEP
4139 self.assertEqual(rx[VXLAN].vni, epg_320.bd.uu_fwd.vni)
4140 self.assertEqual(rx[VXLAN].gpid, epg_221.sclass)
4141 self.assertTrue(rx[VXLAN].flags.G)
4142 self.assertTrue(rx[VXLAN].flags.Instance)
4143 # redirect policy has been applied
4144 self.assertTrue(rx[VXLAN].gpflags.A)
4145 self.assertFalse(rx[VXLAN].gpflags.D)
4146 rxip = rx[VXLAN][Ether].payload
4147 txip = tx[VXLAN][Ether].payload
4148 self.assertEqual(rxip.src, txip.src)
4149 self.assertEqual(rxip.dst, txip.dst)
4154 self.pg7.unconfig_ip4()
4156 def test_gbp_redirect_extended(self):
4157 """ GBP Endpoint Redirect Extended """
4159 self.vapi.cli("set logging class gbp level debug")
4161 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
4162 routed_dst_mac = "00:0c:0c:0c:0c:0c"
4163 routed_src_mac = "00:22:bd:f8:19:ff"
4165 learnt = [{'mac': '00:00:11:11:11:02',
4167 'ip6': '2001:10::2'},
4168 {'mac': '00:00:11:11:11:03',
4170 'ip6': '2001:10::3'}]
4175 t4 = VppIpTable(self, 1)
4177 t6 = VppIpTable(self, 1, True)
4180 # create IPv4 and IPv6 RD UU VxLAN-GBP TEP and bind them to the right
4182 rd_uu4 = VppVxlanGbpTunnel(
4185 self.pg7.remote_ip4,
4187 mode=(VppEnum.vl_api_vxlan_gbp_api_tunnel_mode_t.
4188 VXLAN_GBP_API_TUNNEL_MODE_L3))
4189 rd_uu4.add_vpp_config()
4190 VppIpInterfaceBind(self, rd_uu4, t4).add_vpp_config()
4192 rd_uu6 = VppVxlanGbpTunnel(
4195 self.pg7.remote_ip4,
4197 mode=(VppEnum.vl_api_vxlan_gbp_api_tunnel_mode_t.
4198 VXLAN_GBP_API_TUNNEL_MODE_L3))
4199 rd_uu6.add_vpp_config()
4200 VppIpInterfaceBind(self, rd_uu6, t4).add_vpp_config()
4202 rd1 = VppGbpRouteDomain(self, 2, 402, t4, t6, rd_uu4, rd_uu6)
4203 rd1.add_vpp_config()
4205 self.loop0.set_mac(self.router_mac)
4206 self.loop1.set_mac(self.router_mac)
4207 self.loop2.set_mac(self.router_mac)
4210 # Bind the BVI to the RD
4212 b_lo0_ip4 = VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
4213 b_lo0_ip6 = VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
4214 b_lo1_ip4 = VppIpInterfaceBind(self, self.loop1, t4).add_vpp_config()
4215 b_lo1_ip6 = VppIpInterfaceBind(self, self.loop1, t6).add_vpp_config()
4216 b_lo2_ip4 = VppIpInterfaceBind(self, self.loop2, t4).add_vpp_config()
4217 b_lo2_ip6 = VppIpInterfaceBind(self, self.loop2, t6).add_vpp_config()
4220 # Pg7 hosts a BD's UU-fwd
4222 self.pg7.config_ip4()
4223 self.pg7.resolve_arp()
4226 # a GBP bridge domains for the EPs
4228 bd1 = VppBridgeDomain(self, 1)
4229 bd1.add_vpp_config()
4230 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0)
4231 gbd1.add_vpp_config()
4233 bd2 = VppBridgeDomain(self, 2)
4234 bd2.add_vpp_config()
4235 gbd2 = VppGbpBridgeDomain(self, bd2, rd1, self.loop1)
4236 gbd2.add_vpp_config()
4238 # ... and has a /32 and /128 applied
4239 ip4_addr1 = VppIpInterfaceAddress(self, gbd1.bvi,
4241 bind=b_lo0_ip4).add_vpp_config()
4242 ip6_addr1 = VppIpInterfaceAddress(self, gbd1.bvi,
4243 "2001:10::128", 128,
4244 bind=b_lo0_ip6).add_vpp_config()
4245 ip4_addr2 = VppIpInterfaceAddress(self, gbd2.bvi,
4247 bind=b_lo1_ip4).add_vpp_config()
4248 ip6_addr2 = VppIpInterfaceAddress(self, gbd2.bvi,
4249 "2001:11::128", 128,
4250 bind=b_lo1_ip6).add_vpp_config()
4253 # The Endpoint-groups
4255 epg_220 = VppGbpEndpointGroup(self, 220, 440, rd1, gbd1,
4259 VppGbpEndpointRetention(60))
4260 epg_220.add_vpp_config()
4261 epg_221 = VppGbpEndpointGroup(self, 221, 441, rd1, gbd2,
4265 VppGbpEndpointRetention(60))
4266 epg_221.add_vpp_config()
4269 # a GBP bridge domains for the SEPs
4271 bd_uu3 = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
4272 self.pg7.remote_ip4, 116)
4273 bd_uu3.add_vpp_config()
4275 bd3 = VppBridgeDomain(self, 3)
4276 bd3.add_vpp_config()
4277 gbd3 = VppGbpBridgeDomain(self, bd3, rd1, self.loop2,
4278 bd_uu3, learn=False)
4279 gbd3.add_vpp_config()
4281 ip4_addr3 = VppIpInterfaceAddress(self, gbd3.bvi,
4283 bind=b_lo2_ip4).add_vpp_config()
4284 ip6_addr3 = VppIpInterfaceAddress(self, gbd3.bvi,
4285 "4001:10::128", 128,
4286 bind=b_lo2_ip6).add_vpp_config()
4289 # self.logger.info(self.vapi.cli("show gbp bridge"))
4290 # self.logger.info(self.vapi.cli("show vxlan-gbp tunnel"))
4291 # self.logger.info(self.vapi.cli("show gbp vxlan"))
4292 # self.logger.info(self.vapi.cli("show int addr"))
4296 # EPGs in which the service endpoints exist
4298 epg_320 = VppGbpEndpointGroup(self, 320, 550, rd1, gbd3,
4302 VppGbpEndpointRetention(60))
4303 epg_320.add_vpp_config()
4308 ep1 = VppGbpEndpoint(self, self.pg0,
4310 "10.0.0.1", "11.0.0.1",
4311 "2001:10::1", "3001:10::1")
4312 ep1.add_vpp_config()
4313 ep2 = VppGbpEndpoint(self, self.pg1,
4315 "10.0.1.1", "11.0.1.1",
4316 "2001:11::1", "3001:11::1")
4317 ep2.add_vpp_config()
4322 sep1 = VppGbpEndpoint(self, self.pg3,
4324 "12.0.0.1", "13.0.0.1",
4325 "4001:10::1", "5001:10::1")
4326 sep2 = VppGbpEndpoint(self, self.pg4,
4328 "12.0.0.2", "13.0.0.2",
4329 "4001:10::2", "5001:10::2")
4331 # sep1 and sep2 are not added to config yet
4332 # they are unknown for now
4335 # add routes to EPG subnets
4337 VppGbpSubnet(self, rd1, "10.0.0.0", 24,
4338 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT
4340 VppGbpSubnet(self, rd1, "10.0.1.0", 24,
4341 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT
4345 # Local host to known local host in different BD
4346 # with SFC contract (source and destination are in
4347 # one node and service endpoint in another node)
4349 p4 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
4350 IP(src=ep1.ip4, dst=ep2.ip4) /
4351 UDP(sport=1234, dport=1234) /
4352 Raw(b'\xa5' * 100)),
4353 (Ether(src=ep2.mac, dst=str(self.router_mac)) /
4354 IP(src=ep2.ip4, dst=ep1.ip4) /
4355 UDP(sport=1234, dport=1234) /
4356 Raw(b'\xa5' * 100))]
4357 p6 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
4358 IPv6(src=ep1.ip6, dst=ep2.ip6) /
4359 UDP(sport=1234, dport=1234) /
4360 Raw(b'\xa5' * 100)),
4361 (Ether(src=ep2.mac, dst=str(self.router_mac)) /
4362 IPv6(src=ep2.ip6, dst=ep1.ip6) /
4363 UDP(sport=1234, dport=1230) /
4364 Raw(b'\xa5' * 100))]
4366 # should be dropped since no contract yet
4367 self.send_and_assert_no_replies(self.pg0, [p4[0]])
4368 self.send_and_assert_no_replies(self.pg0, [p6[0]])
4371 # Add a contract with a rule to load-balance redirect via SEP1 and SEP2
4372 # one of the next-hops is via an EP that is not known
4374 rule4 = AclRule(is_permit=1, proto=17)
4375 rule6 = AclRule(src_prefix=IPv6Network((0, 0)),
4376 dst_prefix=IPv6Network((0, 0)), is_permit=1, proto=17)
4377 acl = VppAcl(self, rules=[rule4, rule6])
4378 acl.add_vpp_config()
4381 # test the src-ip hash mode
4383 c1 = VppGbpContract(
4384 self, 402, epg_220.sclass, epg_221.sclass, acl.acl_index,
4385 [VppGbpContractRule(
4386 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4387 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
4388 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
4389 sep1.ip4, sep1.epg.rd)]),
4391 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4392 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
4393 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
4394 sep1.ip6, sep1.epg.rd)])],
4395 [ETH_P_IP, ETH_P_IPV6])
4398 c2 = VppGbpContract(
4399 self, 402, epg_221.sclass, epg_220.sclass, acl.acl_index,
4400 [VppGbpContractRule(
4401 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4402 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
4403 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
4404 sep1.ip4, sep1.epg.rd)]),
4406 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4407 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
4408 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
4409 sep1.ip6, sep1.epg.rd)])],
4410 [ETH_P_IP, ETH_P_IPV6])
4413 # ep1 <--> ep2 redirected through sep1
4415 # packet is redirected to sep bd and then go through sep bd UU
4417 rxs = self.send_and_expect(self.pg0, p4[0] * 17, self.pg7)
4420 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4421 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4422 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4423 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4424 self.assertEqual(rx[VXLAN].vni, 116)
4425 self.assertTrue(rx[VXLAN].flags.G)
4426 self.assertTrue(rx[VXLAN].flags.Instance)
4427 # redirect policy has been applied
4428 self.assertTrue(rx[VXLAN].gpflags.A)
4429 self.assertFalse(rx[VXLAN].gpflags.D)
4431 inner = rx[VXLAN].payload
4433 self.assertEqual(inner[Ether].src, routed_src_mac)
4434 self.assertEqual(inner[Ether].dst, sep1.mac)
4435 self.assertEqual(inner[IP].src, ep1.ip4)
4436 self.assertEqual(inner[IP].dst, ep2.ip4)
4438 rxs = self.send_and_expect(self.pg1, p4[1] * 17, self.pg7)
4441 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4442 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4443 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4444 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4445 self.assertEqual(rx[VXLAN].vni, 116)
4446 self.assertTrue(rx[VXLAN].flags.G)
4447 self.assertTrue(rx[VXLAN].flags.Instance)
4448 # redirect policy has been applied
4449 self.assertTrue(rx[VXLAN].gpflags.A)
4450 self.assertFalse(rx[VXLAN].gpflags.D)
4452 inner = rx[VXLAN].payload
4454 self.assertEqual(inner[Ether].src, routed_src_mac)
4455 self.assertEqual(inner[Ether].dst, sep1.mac)
4456 self.assertEqual(inner[IP].src, ep2.ip4)
4457 self.assertEqual(inner[IP].dst, ep1.ip4)
4459 rxs = self.send_and_expect(self.pg0, p6[0] * 17, self.pg7)
4462 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4463 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4464 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4465 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4466 self.assertEqual(rx[VXLAN].vni, 116)
4467 self.assertTrue(rx[VXLAN].flags.G)
4468 self.assertTrue(rx[VXLAN].flags.Instance)
4469 # redirect policy has been applied
4470 inner = rx[VXLAN].payload
4472 self.assertEqual(inner[Ether].src, routed_src_mac)
4473 self.assertEqual(inner[Ether].dst, sep1.mac)
4474 self.assertEqual(inner[IPv6].src, ep1.ip6)
4475 self.assertEqual(inner[IPv6].dst, ep2.ip6)
4477 rxs = self.send_and_expect(self.pg1, p6[1] * 17, self.pg7)
4480 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4481 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4482 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4483 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4484 self.assertEqual(rx[VXLAN].vni, 116)
4485 self.assertTrue(rx[VXLAN].flags.G)
4486 self.assertTrue(rx[VXLAN].flags.Instance)
4487 # redirect policy has been applied
4488 self.assertTrue(rx[VXLAN].gpflags.A)
4489 self.assertFalse(rx[VXLAN].gpflags.D)
4491 inner = rx[VXLAN].payload
4493 self.assertEqual(inner[Ether].src, routed_src_mac)
4494 self.assertEqual(inner[Ether].dst, sep1.mac)
4495 self.assertEqual(inner[IPv6].src, ep2.ip6)
4496 self.assertEqual(inner[IPv6].dst, ep1.ip6)
4498 # configure sep1: it is now local
4499 # packets between ep1 and ep2 are redirected locally
4500 sep1.add_vpp_config()
4502 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
4505 self.assertEqual(rx[Ether].src, routed_src_mac)
4506 self.assertEqual(rx[Ether].dst, sep1.mac)
4507 self.assertEqual(rx[IP].src, ep1.ip4)
4508 self.assertEqual(rx[IP].dst, ep2.ip4)
4510 rxs = self.send_and_expect(self.pg1, p6[1] * 17, sep1.itf)
4513 self.assertEqual(rx[Ether].src, routed_src_mac)
4514 self.assertEqual(rx[Ether].dst, sep1.mac)
4515 self.assertEqual(rx[IPv6].src, ep2.ip6)
4516 self.assertEqual(rx[IPv6].dst, ep1.ip6)
4518 # packet coming from the l2 spine-proxy to sep1
4519 p = (Ether(src=self.pg7.remote_mac,
4520 dst=self.pg7.local_mac) /
4521 IP(src=self.pg7.remote_ip4,
4522 dst=self.pg7.local_ip4) /
4523 UDP(sport=1234, dport=48879) /
4524 VXLAN(vni=116, gpid=440, gpflags=0x08, flags=0x88) /
4525 Ether(src=str(self.router_mac), dst=sep1.mac) /
4526 IP(src=ep1.ip4, dst=ep2.ip4) /
4527 UDP(sport=1234, dport=1234) /
4530 rxs = self.send_and_expect(self.pg7, [p] * 17, sep1.itf)
4533 self.assertEqual(rx[Ether].src, str(self.router_mac))
4534 self.assertEqual(rx[Ether].dst, sep1.mac)
4535 self.assertEqual(rx[IP].src, ep1.ip4)
4536 self.assertEqual(rx[IP].dst, ep2.ip4)
4538 # contract for SEP to communicate with dst EP
4539 c3 = VppGbpContract(
4540 self, 402, epg_320.sclass, epg_221.sclass, acl.acl_index,
4541 [VppGbpContractRule(
4542 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4543 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC),
4545 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4546 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC)],
4547 [ETH_P_IP, ETH_P_IPV6])
4550 # temporarily remove ep2, so that ep2 is remote & unknown
4551 ep2.remove_vpp_config()
4553 # packet going back from sep1 to its original dest (ep2)
4554 # as ep2 is now unknown (see above), it must go through
4555 # the rd UU (packet is routed)
4557 p1 = (Ether(src=sep1.mac, dst=self.router_mac) /
4558 IP(src=ep1.ip4, dst=ep2.ip4) /
4559 UDP(sport=1234, dport=1234) /
4562 rxs = self.send_and_expect(self.pg3, [p1] * 17, self.pg7)
4565 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4566 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4567 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4568 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4569 self.assertEqual(rx[VXLAN].vni, 114)
4570 self.assertTrue(rx[VXLAN].flags.G)
4571 self.assertTrue(rx[VXLAN].flags.Instance)
4572 # redirect policy has been applied
4573 inner = rx[VXLAN].payload
4574 self.assertEqual(inner[Ether].src, routed_src_mac)
4575 self.assertEqual(inner[Ether].dst, routed_dst_mac)
4576 self.assertEqual(inner[IP].src, ep1.ip4)
4577 self.assertEqual(inner[IP].dst, ep2.ip4)
4579 self.logger.info(self.vapi.cli("show bridge 3 detail"))
4580 sep1.remove_vpp_config()
4582 self.logger.info(self.vapi.cli("show bridge 1 detail"))
4583 self.logger.info(self.vapi.cli("show bridge 2 detail"))
4585 # re-add ep2: it is local again :)
4586 ep2.add_vpp_config()
4588 # packet coming back from the remote sep through rd UU
4589 p2 = (Ether(src=self.pg7.remote_mac,
4590 dst=self.pg7.local_mac) /
4591 IP(src=self.pg7.remote_ip4,
4592 dst=self.pg7.local_ip4) /
4593 UDP(sport=1234, dport=48879) /
4594 VXLAN(vni=114, gpid=441, gpflags=0x09, flags=0x88) /
4595 Ether(src=str(self.router_mac), dst=self.router_mac) /
4596 IP(src=ep1.ip4, dst=ep2.ip4) /
4597 UDP(sport=1234, dport=1234) /
4600 rxs = self.send_and_expect(self.pg7, [p2], self.pg1)
4603 self.assertEqual(rx[Ether].src, str(self.router_mac))
4604 self.assertEqual(rx[Ether].dst, self.pg1.remote_mac)
4605 self.assertEqual(rx[IP].src, ep1.ip4)
4606 self.assertEqual(rx[IP].dst, ep2.ip4)
4609 # bd_uu2.add_vpp_config()
4615 c1.remove_vpp_config()
4616 c2.remove_vpp_config()
4617 c3.remove_vpp_config()
4618 self.pg7.unconfig_ip4()
4620 def test_gbp_l3_out(self):
4623 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
4624 self.vapi.cli("set logging class gbp level debug")
4626 routed_dst_mac = "00:0c:0c:0c:0c:0c"
4627 routed_src_mac = "00:22:bd:f8:19:ff"
4632 t4 = VppIpTable(self, 1)
4634 t6 = VppIpTable(self, 1, True)
4637 rd1 = VppGbpRouteDomain(self, 2, 55, t4, t6)
4638 rd1.add_vpp_config()
4640 self.loop0.set_mac(self.router_mac)
4643 # Bind the BVI to the RD
4645 b_ip4 = VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
4646 b_ip6 = VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
4649 # Pg7 hosts a BD's BUM
4650 # Pg1 some other l3 interface
4652 self.pg7.config_ip4()
4653 self.pg7.resolve_arp()
4656 # a multicast vxlan-gbp tunnel for broadcast in the BD
4658 tun_bm = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
4661 tun_bm.add_vpp_config()
4664 # a GBP external bridge domains for the EPs
4666 bd1 = VppBridgeDomain(self, 1)
4667 bd1.add_vpp_config()
4668 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0, None, tun_bm)
4669 gbd1.add_vpp_config()
4672 # The Endpoint-groups in which the external endpoints exist
4674 epg_220 = VppGbpEndpointGroup(self, 220, 113, rd1, gbd1,
4678 VppGbpEndpointRetention(4))
4679 epg_220.add_vpp_config()
4681 # the BVIs have the subnets applied ...
4682 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128",
4683 24, bind=b_ip4).add_vpp_config()
4684 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128",
4685 64, bind=b_ip6).add_vpp_config()
4687 # ... which are L3-out subnets
4688 l3o_1 = VppGbpSubnet(
4689 self, rd1, "10.0.0.0", 24,
4690 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
4692 l3o_1.add_vpp_config()
4695 # an external interface attached to the outside world and the
4698 VppL2Vtr(self, self.vlan_100, L2_VTR_OP.L2_POP_1).add_vpp_config()
4699 VppL2Vtr(self, self.vlan_101, L2_VTR_OP.L2_POP_1).add_vpp_config()
4700 vlan_144 = VppDot1QSubint(self, self.pg0, 144)
4702 # vlan_102 is not poped
4705 # an unicast vxlan-gbp for inter-RD traffic
4707 vx_tun_l3 = VppGbpVxlanTunnel(
4708 self, 444, rd1.rd_id,
4709 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
4711 vx_tun_l3.add_vpp_config()
4714 # External Endpoints
4716 eep1 = VppGbpEndpoint(self, self.vlan_100,
4718 "10.0.0.1", "11.0.0.1",
4719 "2001:10::1", "3001::1",
4720 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
4721 eep1.add_vpp_config()
4722 eep2 = VppGbpEndpoint(self, self.vlan_101,
4724 "10.0.0.2", "11.0.0.2",
4725 "2001:10::2", "3001::2",
4726 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
4727 eep2.add_vpp_config()
4728 eep3 = VppGbpEndpoint(self, self.vlan_102,
4730 "10.0.0.3", "11.0.0.3",
4731 "2001:10::3", "3001::3",
4732 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
4733 eep3.add_vpp_config()
4736 # A remote external endpoint
4738 rep = VppGbpEndpoint(self, vx_tun_l3,
4740 "10.0.0.101", "11.0.0.101",
4741 "2001:10::101", "3001::101",
4742 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
4744 self.pg7.remote_ip4,
4746 rep.add_vpp_config()
4749 # EP1 impersonating EP3 is dropped
4751 p = (Ether(src=eep1.mac, dst="ff:ff:ff:ff:ff:ff") /
4754 psrc="10.0.0.3", pdst="10.0.0.128",
4755 hwsrc=eep1.mac, hwdst="ff:ff:ff:ff:ff:ff"))
4756 self.send_and_assert_no_replies(self.pg0, p)
4759 # ARP packet from External EPs are accepted and replied to
4761 p_arp = (Ether(src=eep1.mac, dst="ff:ff:ff:ff:ff:ff") /
4764 psrc=eep1.ip4, pdst="10.0.0.128",
4765 hwsrc=eep1.mac, hwdst="ff:ff:ff:ff:ff:ff"))
4766 rxs = self.send_and_expect(self.pg0, p_arp * 1, self.pg0)
4769 # ARP packet from host in remote subnet are accepted and replied to
4771 p_arp = (Ether(src=eep3.mac, dst="ff:ff:ff:ff:ff:ff") /
4774 psrc=eep3.ip4, pdst="10.0.0.128",
4775 hwsrc=eep3.mac, hwdst="ff:ff:ff:ff:ff:ff"))
4776 rxs = self.send_and_expect(self.pg0, p_arp * 1, self.pg0)
4779 # packets destined to unknown addresses in the BVI's subnet
4782 p4 = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
4784 IP(src="10.0.0.1", dst="10.0.0.88") /
4785 UDP(sport=1234, dport=1234) /
4787 p6 = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
4789 IPv6(src="2001:10::1", dst="2001:10::88") /
4790 UDP(sport=1234, dport=1234) /
4793 rxs = self.send_and_expect(self.pg0, p4 * 1, self.pg7)
4796 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4797 # self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4798 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4799 self.assertEqual(rx[IP].dst, "239.1.1.1")
4800 self.assertEqual(rx[VXLAN].vni, 88)
4801 self.assertTrue(rx[VXLAN].flags.G)
4802 self.assertTrue(rx[VXLAN].flags.Instance)
4803 # policy was applied to the original IP packet
4804 self.assertEqual(rx[VXLAN].gpid, 113)
4805 self.assertTrue(rx[VXLAN].gpflags.A)
4806 self.assertFalse(rx[VXLAN].gpflags.D)
4808 inner = rx[VXLAN].payload
4810 self.assertTrue(inner.haslayer(ARP))
4813 # remote to external
4815 p = (Ether(src=self.pg7.remote_mac,
4816 dst=self.pg7.local_mac) /
4817 IP(src=self.pg7.remote_ip4,
4818 dst=self.pg7.local_ip4) /
4819 UDP(sport=1234, dport=48879) /
4820 VXLAN(vni=444, gpid=113, flags=0x88) /
4821 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
4822 IP(src="10.0.0.101", dst="10.0.0.1") /
4823 UDP(sport=1234, dport=1234) /
4826 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
4829 # local EP pings router
4831 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
4833 IP(src=eep1.ip4, dst="10.0.0.128") /
4834 ICMP(type='echo-request'))
4836 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
4839 self.assertEqual(rx[Ether].src, str(self.router_mac))
4840 self.assertEqual(rx[Ether].dst, eep1.mac)
4841 self.assertEqual(rx[Dot1Q].vlan, 100)
4844 # local EP pings other local EP
4846 p = (Ether(src=eep1.mac, dst=eep2.mac) /
4848 IP(src=eep1.ip4, dst=eep2.ip4) /
4849 ICMP(type='echo-request'))
4851 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
4854 self.assertEqual(rx[Ether].src, eep1.mac)
4855 self.assertEqual(rx[Ether].dst, eep2.mac)
4856 self.assertEqual(rx[Dot1Q].vlan, 101)
4859 # local EP pings router w/o vlan tag poped
4861 p = (Ether(src=eep3.mac, dst=str(self.router_mac)) /
4863 IP(src=eep3.ip4, dst="10.0.0.128") /
4864 ICMP(type='echo-request'))
4866 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
4869 self.assertEqual(rx[Ether].src, str(self.router_mac))
4870 self.assertEqual(rx[Ether].dst, self.vlan_102.remote_mac)
4873 # A ip4 subnet reachable through the external EP1
4875 ip_220 = VppIpRoute(self, "10.220.0.0", 24,
4876 [VppRoutePath(eep1.ip4,
4877 eep1.epg.bvi.sw_if_index)],
4878 table_id=t4.table_id)
4879 ip_220.add_vpp_config()
4881 l3o_220 = VppGbpSubnet(
4882 self, rd1, "10.220.0.0", 24,
4883 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
4885 l3o_220.add_vpp_config()
4888 # An ip6 subnet reachable through the external EP1
4890 ip6_220 = VppIpRoute(self, "10:220::", 64,
4891 [VppRoutePath(eep1.ip6,
4892 eep1.epg.bvi.sw_if_index)],
4893 table_id=t6.table_id)
4894 ip6_220.add_vpp_config()
4896 l3o6_220 = VppGbpSubnet(
4897 self, rd1, "10:220::", 64,
4898 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
4900 l3o6_220.add_vpp_config()
4903 # A subnet reachable through the external EP2
4905 ip_221 = VppIpRoute(self, "10.221.0.0", 24,
4906 [VppRoutePath(eep2.ip4,
4907 eep2.epg.bvi.sw_if_index)],
4908 table_id=t4.table_id)
4909 ip_221.add_vpp_config()
4911 l3o_221 = VppGbpSubnet(
4912 self, rd1, "10.221.0.0", 24,
4913 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
4915 l3o_221.add_vpp_config()
4918 # ping between hosts in remote subnets
4919 # dropped without a contract
4921 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
4923 IP(src="10.220.0.1", dst="10.221.0.1") /
4924 ICMP(type='echo-request'))
4926 self.send_and_assert_no_replies(self.pg0, p * 1)
4929 # contract for the external nets to communicate
4931 rule4 = AclRule(is_permit=1, proto=17)
4932 rule6 = AclRule(src_prefix=IPv6Network((0, 0)),
4933 dst_prefix=IPv6Network((0, 0)), is_permit=1, proto=17)
4934 acl = VppAcl(self, rules=[rule4, rule6])
4935 acl.add_vpp_config()
4938 # A contract with the wrong scope is not matched
4940 c_44 = VppGbpContract(
4941 self, 44, 4220, 4221, acl.acl_index,
4942 [VppGbpContractRule(
4943 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4944 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4947 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4948 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4950 [ETH_P_IP, ETH_P_IPV6])
4951 c_44.add_vpp_config()
4952 self.send_and_assert_no_replies(self.pg0, p * 1)
4954 c1 = VppGbpContract(
4955 self, 55, 4220, 4221, acl.acl_index,
4956 [VppGbpContractRule(
4957 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4958 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4961 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4962 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4964 [ETH_P_IP, ETH_P_IPV6])
4968 # Contracts allowing ext-net 200 to talk with external EPs
4970 c2 = VppGbpContract(
4971 self, 55, 4220, 113, acl.acl_index,
4972 [VppGbpContractRule(
4973 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4974 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4977 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4978 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4980 [ETH_P_IP, ETH_P_IPV6])
4982 c3 = VppGbpContract(
4983 self, 55, 113, 4220, acl.acl_index,
4984 [VppGbpContractRule(
4985 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4986 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4989 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4990 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4992 [ETH_P_IP, ETH_P_IPV6])
4996 # ping between hosts in remote subnets
4998 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
5000 IP(src="10.220.0.1", dst="10.221.0.1") /
5001 UDP(sport=1234, dport=1234) /
5004 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
5007 self.assertEqual(rx[Ether].src, str(self.router_mac))
5008 self.assertEqual(rx[Ether].dst, eep2.mac)
5009 self.assertEqual(rx[Dot1Q].vlan, 101)
5011 # we did not learn these external hosts
5012 self.assertFalse(find_gbp_endpoint(self, ip="10.220.0.1"))
5013 self.assertFalse(find_gbp_endpoint(self, ip="10.221.0.1"))
5016 # from remote external EP to local external EP
5018 p = (Ether(src=self.pg7.remote_mac,
5019 dst=self.pg7.local_mac) /
5020 IP(src=self.pg7.remote_ip4,
5021 dst=self.pg7.local_ip4) /
5022 UDP(sport=1234, dport=48879) /
5023 VXLAN(vni=444, gpid=113, flags=0x88) /
5024 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
5025 IP(src="10.0.0.101", dst="10.220.0.1") /
5026 UDP(sport=1234, dport=1234) /
5029 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
5032 # ping from an external host to the remote external EP
5034 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
5036 IP(src="10.220.0.1", dst=rep.ip4) /
5037 UDP(sport=1234, dport=1234) /
5040 rxs = self.send_and_expect(self.pg0, p * 1, self.pg7)
5043 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
5044 # self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
5045 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
5046 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
5047 self.assertEqual(rx[VXLAN].vni, 444)
5048 self.assertTrue(rx[VXLAN].flags.G)
5049 self.assertTrue(rx[VXLAN].flags.Instance)
5050 # the sclass of the ext-net the packet came from
5051 self.assertEqual(rx[VXLAN].gpid, 4220)
5052 # policy was applied to the original IP packet
5053 self.assertTrue(rx[VXLAN].gpflags.A)
5054 # since it's an external host the reciever should not learn it
5055 self.assertTrue(rx[VXLAN].gpflags.D)
5056 inner = rx[VXLAN].payload
5057 self.assertEqual(inner[IP].src, "10.220.0.1")
5058 self.assertEqual(inner[IP].dst, rep.ip4)
5061 # An external subnet reachable via the remote external EP
5065 # first the VXLAN-GBP tunnel over which it is reached
5067 vx_tun_r1 = VppVxlanGbpTunnel(
5068 self, self.pg7.local_ip4,
5069 self.pg7.remote_ip4, 445,
5070 mode=(VppEnum.vl_api_vxlan_gbp_api_tunnel_mode_t.
5071 VXLAN_GBP_API_TUNNEL_MODE_L3))
5072 vx_tun_r1.add_vpp_config()
5073 VppIpInterfaceBind(self, vx_tun_r1, t4).add_vpp_config()
5075 self.logger.info(self.vapi.cli("sh vxlan-gbp tunnel"))
5078 # then the special adj to resolve through on that tunnel
5080 n1 = VppNeighbor(self,
5081 vx_tun_r1.sw_if_index,
5082 "00:0c:0c:0c:0c:0c",
5083 self.pg7.remote_ip4)
5087 # the route via the adj above
5089 ip_222 = VppIpRoute(self, "10.222.0.0", 24,
5090 [VppRoutePath(self.pg7.remote_ip4,
5091 vx_tun_r1.sw_if_index)],
5092 table_id=t4.table_id)
5093 ip_222.add_vpp_config()
5095 l3o_222 = VppGbpSubnet(
5096 self, rd1, "10.222.0.0", 24,
5097 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
5099 l3o_222.add_vpp_config()
5102 # ping between hosts in local and remote external subnets
5103 # dropped without a contract
5105 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
5107 IP(src="10.220.0.1", dst="10.222.0.1") /
5108 UDP(sport=1234, dport=1234) /
5111 rxs = self.send_and_assert_no_replies(self.pg0, p * 1)
5114 # Add contracts ext-nets for 220 -> 222
5116 c4 = VppGbpContract(
5117 self, 55, 4220, 4222, acl.acl_index,
5118 [VppGbpContractRule(
5119 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5120 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5123 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5124 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5126 [ETH_P_IP, ETH_P_IPV6])
5130 # ping from host in local to remote external subnets
5132 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
5134 IP(src="10.220.0.1", dst="10.222.0.1") /
5135 UDP(sport=1234, dport=1234) /
5138 rxs = self.send_and_expect(self.pg0, p * 3, self.pg7)
5141 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
5142 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
5143 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
5144 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
5145 self.assertEqual(rx[VXLAN].vni, 445)
5146 self.assertTrue(rx[VXLAN].flags.G)
5147 self.assertTrue(rx[VXLAN].flags.Instance)
5148 # the sclass of the ext-net the packet came from
5149 self.assertEqual(rx[VXLAN].gpid, 4220)
5150 # policy was applied to the original IP packet
5151 self.assertTrue(rx[VXLAN].gpflags.A)
5152 # since it's an external host the reciever should not learn it
5153 self.assertTrue(rx[VXLAN].gpflags.D)
5154 inner = rx[VXLAN].payload
5155 self.assertEqual(inner[Ether].dst, "00:0c:0c:0c:0c:0c")
5156 self.assertEqual(inner[IP].src, "10.220.0.1")
5157 self.assertEqual(inner[IP].dst, "10.222.0.1")
5160 # make the external subnet ECMP
5162 vx_tun_r2 = VppVxlanGbpTunnel(
5163 self, self.pg7.local_ip4,
5164 self.pg7.remote_ip4, 446,
5165 mode=(VppEnum.vl_api_vxlan_gbp_api_tunnel_mode_t.
5166 VXLAN_GBP_API_TUNNEL_MODE_L3))
5167 vx_tun_r2.add_vpp_config()
5168 VppIpInterfaceBind(self, vx_tun_r2, t4).add_vpp_config()
5170 self.logger.info(self.vapi.cli("sh vxlan-gbp tunnel"))
5172 n2 = VppNeighbor(self,
5173 vx_tun_r2.sw_if_index,
5174 "00:0c:0c:0c:0c:0c",
5175 self.pg7.remote_ip4)
5178 ip_222.modify([VppRoutePath(self.pg7.remote_ip4,
5179 vx_tun_r1.sw_if_index),
5180 VppRoutePath(self.pg7.remote_ip4,
5181 vx_tun_r2.sw_if_index)])
5184 # now expect load-balance
5186 p = [(Ether(src=eep1.mac, dst=str(self.router_mac)) /
5188 IP(src="10.220.0.1", dst="10.222.0.1") /
5189 UDP(sport=1234, dport=1234) /
5190 Raw(b'\xa5' * 100)),
5191 (Ether(src=eep1.mac, dst=str(self.router_mac)) /
5193 IP(src="10.220.0.1", dst="10.222.0.1") /
5194 UDP(sport=1222, dport=1235) /
5195 Raw(b'\xa5' * 100))]
5197 rxs = self.send_and_expect(self.pg0, p, self.pg7)
5199 self.assertEqual(rxs[0][VXLAN].vni, 445)
5200 self.assertEqual(rxs[1][VXLAN].vni, 446)
5203 # Same LB test for v6
5205 n3 = VppNeighbor(self,
5206 vx_tun_r1.sw_if_index,
5207 "00:0c:0c:0c:0c:0c",
5208 self.pg7.remote_ip6)
5210 n4 = VppNeighbor(self,
5211 vx_tun_r2.sw_if_index,
5212 "00:0c:0c:0c:0c:0c",
5213 self.pg7.remote_ip6)
5216 ip_222_6 = VppIpRoute(self, "10:222::", 64,
5217 [VppRoutePath(self.pg7.remote_ip6,
5218 vx_tun_r1.sw_if_index),
5219 VppRoutePath(self.pg7.remote_ip6,
5220 vx_tun_r2.sw_if_index)],
5221 table_id=t6.table_id)
5222 ip_222_6.add_vpp_config()
5224 l3o_222_6 = VppGbpSubnet(
5225 self, rd1, "10:222::", 64,
5226 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
5228 l3o_222_6.add_vpp_config()
5230 p = [(Ether(src=eep1.mac, dst=str(self.router_mac)) /
5232 IPv6(src="10:220::1", dst="10:222::1") /
5233 UDP(sport=1234, dport=1234) /
5234 Raw(b'\xa5' * 100)),
5235 (Ether(src=eep1.mac, dst=str(self.router_mac)) /
5237 IPv6(src="10:220::1", dst="10:222::1") /
5238 UDP(sport=7777, dport=8881) /
5239 Raw(b'\xa5' * 100))]
5241 self.logger.info(self.vapi.cli("sh ip6 fib 10:222::1"))
5242 rxs = self.send_and_expect(self.pg0, p, self.pg7)
5244 self.assertEqual(rxs[0][VXLAN].vni, 445)
5245 self.assertEqual(rxs[1][VXLAN].vni, 446)
5248 # ping from host in remote to local external subnets
5249 # there's no contract for this, but the A bit is set.
5251 p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
5252 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
5253 UDP(sport=1234, dport=48879) /
5254 VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
5255 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
5256 IP(src="10.222.0.1", dst="10.220.0.1") /
5257 UDP(sport=1234, dport=1234) /
5260 rxs = self.send_and_expect(self.pg7, p * 3, self.pg0)
5261 self.assertFalse(find_gbp_endpoint(self, ip="10.222.0.1"))
5264 # ping from host in remote to remote external subnets
5265 # this is dropped by reflection check.
5267 p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
5268 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
5269 UDP(sport=1234, dport=48879) /
5270 VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
5271 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
5272 IP(src="10.222.0.1", dst="10.222.0.2") /
5273 UDP(sport=1234, dport=1234) /
5276 rxs = self.send_and_assert_no_replies(self.pg7, p * 3)
5278 p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
5279 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
5280 UDP(sport=1234, dport=48879) /
5281 VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
5282 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
5283 IPv6(src="10:222::1", dst="10:222::2") /
5284 UDP(sport=1234, dport=1234) /
5287 rxs = self.send_and_assert_no_replies(self.pg7, p * 3)
5292 lep1 = VppGbpEndpoint(self, vlan_144,
5294 "10.0.0.44", "11.0.0.44",
5295 "2001:10::44", "3001::44")
5296 lep1.add_vpp_config()
5299 # local EP to local ip4 external subnet
5301 p = (Ether(src=lep1.mac, dst=str(self.router_mac)) /
5303 IP(src=lep1.ip4, dst="10.220.0.1") /
5304 UDP(sport=1234, dport=1234) /
5307 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
5310 self.assertEqual(rx[Ether].src, str(self.router_mac))
5311 self.assertEqual(rx[Ether].dst, eep1.mac)
5312 self.assertEqual(rx[Dot1Q].vlan, 100)
5315 # local EP to local ip6 external subnet
5317 p = (Ether(src=lep1.mac, dst=str(self.router_mac)) /
5319 IPv6(src=lep1.ip6, dst="10:220::1") /
5320 UDP(sport=1234, dport=1234) /
5323 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
5326 self.assertEqual(rx[Ether].src, str(self.router_mac))
5327 self.assertEqual(rx[Ether].dst, eep1.mac)
5328 self.assertEqual(rx[Dot1Q].vlan, 100)
5331 # ip4 and ip6 subnets that load-balance
5333 ip_20 = VppIpRoute(self, "10.20.0.0", 24,
5334 [VppRoutePath(eep1.ip4,
5335 eep1.epg.bvi.sw_if_index),
5336 VppRoutePath(eep2.ip4,
5337 eep2.epg.bvi.sw_if_index)],
5338 table_id=t4.table_id)
5339 ip_20.add_vpp_config()
5341 l3o_20 = VppGbpSubnet(
5342 self, rd1, "10.20.0.0", 24,
5343 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
5345 l3o_20.add_vpp_config()
5347 ip6_20 = VppIpRoute(self, "10:20::", 64,
5348 [VppRoutePath(eep1.ip6,
5349 eep1.epg.bvi.sw_if_index),
5350 VppRoutePath(eep2.ip6,
5351 eep2.epg.bvi.sw_if_index)],
5352 table_id=t6.table_id)
5353 ip6_20.add_vpp_config()
5355 l3o6_20 = VppGbpSubnet(
5356 self, rd1, "10:20::", 64,
5357 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
5359 l3o6_20.add_vpp_config()
5361 self.logger.info(self.vapi.cli("sh ip fib 10.20.0.1"))
5362 self.logger.info(self.vapi.cli("sh ip6 fib 10:20::1"))
5364 # two ip6 packets whose port are chosen so they load-balance
5365 p = [(Ether(src=lep1.mac, dst=str(self.router_mac)) /
5367 IPv6(src=lep1.ip6, dst="10:20::1") /
5368 UDP(sport=1234, dport=1234) /
5369 Raw(b'\xa5' * 100)),
5370 (Ether(src=lep1.mac, dst=str(self.router_mac)) /
5372 IPv6(src=lep1.ip6, dst="10:20::1") /
5373 UDP(sport=124, dport=1230) /
5374 Raw(b'\xa5' * 100))]
5376 rxs = self.send_and_expect(self.pg0, p, self.pg0, 2)
5378 self.assertEqual(rxs[0][Dot1Q].vlan, 101)
5379 self.assertEqual(rxs[1][Dot1Q].vlan, 100)
5381 # two ip4 packets whose port are chosen so they load-balance
5382 p = [(Ether(src=lep1.mac, dst=str(self.router_mac)) /
5384 IP(src=lep1.ip4, dst="10.20.0.1") /
5385 UDP(sport=1235, dport=1235) /
5386 Raw(b'\xa5' * 100)),
5387 (Ether(src=lep1.mac, dst=str(self.router_mac)) /
5389 IP(src=lep1.ip4, dst="10.20.0.1") /
5390 UDP(sport=124, dport=1230) /
5391 Raw(b'\xa5' * 100))]
5393 rxs = self.send_and_expect(self.pg0, p, self.pg0, 2)
5395 self.assertEqual(rxs[0][Dot1Q].vlan, 101)
5396 self.assertEqual(rxs[1][Dot1Q].vlan, 100)
5401 ip_222.remove_vpp_config()
5402 self.pg7.unconfig_ip4()
5403 self.vlan_101.set_vtr(L2_VTR_OP.L2_DISABLED)
5404 self.vlan_100.set_vtr(L2_VTR_OP.L2_DISABLED)
5406 def test_gbp_anon_l3_out(self):
5407 """ GBP Anonymous L3 Out """
5409 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
5410 self.vapi.cli("set logging class gbp level debug")
5412 routed_dst_mac = "00:0c:0c:0c:0c:0c"
5413 routed_src_mac = "00:22:bd:f8:19:ff"
5418 t4 = VppIpTable(self, 1)
5420 t6 = VppIpTable(self, 1, True)
5423 rd1 = VppGbpRouteDomain(self, 2, 55, t4, t6)
5424 rd1.add_vpp_config()
5426 self.loop0.set_mac(self.router_mac)
5429 # Bind the BVI to the RD
5431 bind_l0_ip4 = VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
5432 bind_l0_ip6 = VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
5435 # Pg7 hosts a BD's BUM
5436 # Pg1 some other l3 interface
5438 self.pg7.config_ip4()
5439 self.pg7.resolve_arp()
5442 # a GBP external bridge domains for the EPs
5444 bd1 = VppBridgeDomain(self, 1)
5445 bd1.add_vpp_config()
5446 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0, None, None)
5447 gbd1.add_vpp_config()
5450 # The Endpoint-groups in which the external endpoints exist
5452 epg_220 = VppGbpEndpointGroup(self, 220, 113, rd1, gbd1,
5456 VppGbpEndpointRetention(4))
5457 epg_220.add_vpp_config()
5459 # the BVIs have the subnet applied ...
5460 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi,
5462 bind=bind_l0_ip4).add_vpp_config()
5464 # ... which is an Anonymous L3-out subnets
5465 l3o_1 = VppGbpSubnet(
5466 self, rd1, "10.0.0.0", 24,
5467 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_ANON_L3_OUT,
5469 l3o_1.add_vpp_config()
5472 # an external interface attached to the outside world and the
5475 VppL2Vtr(self, self.vlan_100, L2_VTR_OP.L2_POP_1).add_vpp_config()
5476 VppL2Vtr(self, self.vlan_101, L2_VTR_OP.L2_POP_1).add_vpp_config()
5479 # vlan_100 and vlan_101 are anonymous l3-out interfaces
5481 ext_itf = VppGbpExtItf(self, self.vlan_100, bd1, rd1, anon=True)
5482 ext_itf.add_vpp_config()
5483 ext_itf = VppGbpExtItf(self, self.vlan_101, bd1, rd1, anon=True)
5484 ext_itf.add_vpp_config()
5487 # an unicast vxlan-gbp for inter-RD traffic
5489 vx_tun_l3 = VppGbpVxlanTunnel(
5490 self, 444, rd1.rd_id,
5491 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
5493 vx_tun_l3.add_vpp_config()
5496 # A remote external endpoint
5498 rep = VppGbpEndpoint(self, vx_tun_l3,
5500 "10.0.0.201", "11.0.0.201",
5501 "2001:10::201", "3001::101",
5502 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
5504 self.pg7.remote_ip4,
5506 rep.add_vpp_config()
5509 # ARP packet from host in external subnet are accepted, flooded and
5510 # replied to. We expect 2 packets:
5511 # - APR request flooded over the other vlan subif
5512 # - ARP reply from BVI
5514 p_arp = (Ether(src=self.vlan_100.remote_mac,
5515 dst="ff:ff:ff:ff:ff:ff") /
5520 hwsrc=self.vlan_100.remote_mac,
5521 hwdst="ff:ff:ff:ff:ff:ff"))
5522 rxs = self.send_and_expect(self.pg0, p_arp * 1, self.pg0, n_rx=2)
5524 p_arp = (Ether(src=self.vlan_101.remote_mac,
5525 dst="ff:ff:ff:ff:ff:ff") /
5530 hwsrc=self.vlan_101.remote_mac,
5531 hwdst="ff:ff:ff:ff:ff:ff"))
5532 rxs = self.send_and_expect(self.pg0, p_arp * 1, self.pg0, n_rx=2)
5535 # remote to external
5537 p = (Ether(src=self.pg7.remote_mac,
5538 dst=self.pg7.local_mac) /
5539 IP(src=self.pg7.remote_ip4,
5540 dst=self.pg7.local_ip4) /
5541 UDP(sport=1234, dport=48879) /
5542 VXLAN(vni=vx_tun_l3.vni, gpid=epg_220.sclass, flags=0x88) /
5543 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
5544 IP(src=str(rep.ip4), dst="10.0.0.100") /
5545 UDP(sport=1234, dport=1234) /
5547 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
5550 # local EP pings router
5552 p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
5554 IP(src="10.0.0.100", dst="10.0.0.128") /
5555 ICMP(type='echo-request'))
5556 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
5559 self.assertEqual(rx[Ether].src, str(self.router_mac))
5560 self.assertEqual(rx[Ether].dst, self.vlan_100.remote_mac)
5561 self.assertEqual(rx[Dot1Q].vlan, 100)
5564 # local EP pings other local EP
5566 p = (Ether(src=self.vlan_100.remote_mac,
5567 dst=self.vlan_101.remote_mac) /
5569 IP(src="10.0.0.100", dst="10.0.0.101") /
5570 ICMP(type='echo-request'))
5571 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
5574 self.assertEqual(rx[Ether].src, self.vlan_100.remote_mac)
5575 self.assertEqual(rx[Ether].dst, self.vlan_101.remote_mac)
5576 self.assertEqual(rx[Dot1Q].vlan, 101)
5579 # A subnet reachable through an external router on vlan 100
5581 ip_220 = VppIpRoute(self, "10.220.0.0", 24,
5582 [VppRoutePath("10.0.0.100",
5583 epg_220.bvi.sw_if_index)],
5584 table_id=t4.table_id)
5585 ip_220.add_vpp_config()
5587 l3o_220 = VppGbpSubnet(
5588 self, rd1, "10.220.0.0", 24,
5589 # note: this a "regular" L3 out subnet (not connected)
5590 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
5592 l3o_220.add_vpp_config()
5595 # A subnet reachable through an external router on vlan 101
5597 ip_221 = VppIpRoute(self, "10.221.0.0", 24,
5598 [VppRoutePath("10.0.0.101",
5599 epg_220.bvi.sw_if_index)],
5600 table_id=t4.table_id)
5601 ip_221.add_vpp_config()
5603 l3o_221 = VppGbpSubnet(
5604 self, rd1, "10.221.0.0", 24,
5605 # note: this a "regular" L3 out subnet (not connected)
5606 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
5608 l3o_221.add_vpp_config()
5611 # ping between hosts in remote subnets
5612 # dropped without a contract
5614 p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
5616 IP(src="10.220.0.1", dst="10.221.0.1") /
5617 ICMP(type='echo-request'))
5619 rxs = self.send_and_assert_no_replies(self.pg0, p * 1)
5622 # contract for the external nets to communicate
5624 rule4 = AclRule(is_permit=1, proto=17)
5625 rule6 = AclRule(src_prefix=IPv6Network((0, 0)),
5626 dst_prefix=IPv6Network((0, 0)), is_permit=1, proto=17)
5627 acl = VppAcl(self, rules=[rule4, rule6])
5628 acl.add_vpp_config()
5630 c1 = VppGbpContract(
5631 self, 55, 4220, 4221, acl.acl_index,
5632 [VppGbpContractRule(
5633 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5634 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5637 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5638 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5640 [ETH_P_IP, ETH_P_IPV6])
5644 # Contracts allowing ext-net 200 to talk with external EPs
5646 c2 = VppGbpContract(
5647 self, 55, 4220, 113, acl.acl_index,
5648 [VppGbpContractRule(
5649 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5650 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5653 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5654 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5656 [ETH_P_IP, ETH_P_IPV6])
5658 c3 = VppGbpContract(
5659 self, 55, 113, 4220, acl.acl_index,
5660 [VppGbpContractRule(
5661 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5662 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5665 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5666 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5668 [ETH_P_IP, ETH_P_IPV6])
5672 # ping between hosts in remote subnets
5674 p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
5676 IP(src="10.220.0.1", dst="10.221.0.1") /
5677 UDP(sport=1234, dport=1234) /
5680 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
5683 self.assertEqual(rx[Ether].src, str(self.router_mac))
5684 self.assertEqual(rx[Ether].dst, self.vlan_101.remote_mac)
5685 self.assertEqual(rx[Dot1Q].vlan, 101)
5687 # we did not learn these external hosts
5688 self.assertFalse(find_gbp_endpoint(self, ip="10.220.0.1"))
5689 self.assertFalse(find_gbp_endpoint(self, ip="10.221.0.1"))
5692 # from remote external EP to local external EP
5694 p = (Ether(src=self.pg7.remote_mac,
5695 dst=self.pg7.local_mac) /
5696 IP(src=self.pg7.remote_ip4,
5697 dst=self.pg7.local_ip4) /
5698 UDP(sport=1234, dport=48879) /
5699 VXLAN(vni=444, gpid=113, flags=0x88) /
5700 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
5701 IP(src=rep.ip4, dst="10.220.0.1") /
5702 UDP(sport=1234, dport=1234) /
5705 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
5708 # ping from an external host to the remote external EP
5710 p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
5712 IP(src="10.220.0.1", dst=rep.ip4) /
5713 UDP(sport=1234, dport=1234) /
5716 rxs = self.send_and_expect(self.pg0, p * 1, self.pg7)
5719 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
5720 # self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
5721 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
5722 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
5723 self.assertEqual(rx[VXLAN].vni, 444)
5724 self.assertTrue(rx[VXLAN].flags.G)
5725 self.assertTrue(rx[VXLAN].flags.Instance)
5726 # the sclass of the ext-net the packet came from
5727 self.assertEqual(rx[VXLAN].gpid, 4220)
5728 # policy was applied to the original IP packet
5729 self.assertTrue(rx[VXLAN].gpflags.A)
5730 # since it's an external host the reciever should not learn it
5731 self.assertTrue(rx[VXLAN].gpflags.D)
5732 inner = rx[VXLAN].payload
5733 self.assertEqual(inner[IP].src, "10.220.0.1")
5734 self.assertEqual(inner[IP].dst, rep.ip4)
5737 # An external subnet reachable via the remote external EP
5741 # first the VXLAN-GBP tunnel over which it is reached
5743 vx_tun_r = VppVxlanGbpTunnel(
5744 self, self.pg7.local_ip4,
5745 self.pg7.remote_ip4, 445,
5746 mode=(VppEnum.vl_api_vxlan_gbp_api_tunnel_mode_t.
5747 VXLAN_GBP_API_TUNNEL_MODE_L3))
5748 vx_tun_r.add_vpp_config()
5749 VppIpInterfaceBind(self, vx_tun_r, t4).add_vpp_config()
5751 self.logger.info(self.vapi.cli("sh vxlan-gbp tunnel"))
5754 # then the special adj to resolve through on that tunnel
5756 n1 = VppNeighbor(self,
5757 vx_tun_r.sw_if_index,
5758 "00:0c:0c:0c:0c:0c",
5759 self.pg7.remote_ip4)
5763 # the route via the adj above
5765 ip_222 = VppIpRoute(self, "10.222.0.0", 24,
5766 [VppRoutePath(self.pg7.remote_ip4,
5767 vx_tun_r.sw_if_index)],
5768 table_id=t4.table_id)
5769 ip_222.add_vpp_config()
5771 l3o_222 = VppGbpSubnet(
5772 self, rd1, "10.222.0.0", 24,
5773 # note: this a "regular" l3out subnet (not connected)
5774 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
5776 l3o_222.add_vpp_config()
5779 # ping between hosts in local and remote external subnets
5780 # dropped without a contract
5782 p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
5784 IP(src="10.220.0.1", dst="10.222.0.1") /
5785 UDP(sport=1234, dport=1234) /
5788 rxs = self.send_and_assert_no_replies(self.pg0, p * 1)
5791 # Add contracts ext-nets for 220 -> 222
5793 c4 = VppGbpContract(
5794 self, 55, 4220, 4222, acl.acl_index,
5795 [VppGbpContractRule(
5796 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5797 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5800 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5801 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5803 [ETH_P_IP, ETH_P_IPV6])
5807 # ping from host in local to remote external subnets
5809 p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
5811 IP(src="10.220.0.1", dst="10.222.0.1") /
5812 UDP(sport=1234, dport=1234) /
5815 rxs = self.send_and_expect(self.pg0, p * 3, self.pg7)
5818 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
5819 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
5820 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
5821 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
5822 self.assertEqual(rx[VXLAN].vni, 445)
5823 self.assertTrue(rx[VXLAN].flags.G)
5824 self.assertTrue(rx[VXLAN].flags.Instance)
5825 # the sclass of the ext-net the packet came from
5826 self.assertEqual(rx[VXLAN].gpid, 4220)
5827 # policy was applied to the original IP packet
5828 self.assertTrue(rx[VXLAN].gpflags.A)
5829 # since it's an external host the reciever should not learn it
5830 self.assertTrue(rx[VXLAN].gpflags.D)
5831 inner = rx[VXLAN].payload
5832 self.assertEqual(inner[Ether].dst, "00:0c:0c:0c:0c:0c")
5833 self.assertEqual(inner[IP].src, "10.220.0.1")
5834 self.assertEqual(inner[IP].dst, "10.222.0.1")
5837 # ping from host in remote to local external subnets
5838 # there's no contract for this, but the A bit is set.
5840 p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
5841 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
5842 UDP(sport=1234, dport=48879) /
5843 VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
5844 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
5845 IP(src="10.222.0.1", dst="10.220.0.1") /
5846 UDP(sport=1234, dport=1234) /
5849 rxs = self.send_and_expect(self.pg7, p * 3, self.pg0)
5850 self.assertFalse(find_gbp_endpoint(self, ip="10.222.0.1"))
5853 # ping from host in remote to remote external subnets
5854 # this is dropped by reflection check.
5856 p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
5857 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
5858 UDP(sport=1234, dport=48879) /
5859 VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
5860 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
5861 IP(src="10.222.0.1", dst="10.222.0.2") /
5862 UDP(sport=1234, dport=1234) /
5865 rxs = self.send_and_assert_no_replies(self.pg7, p * 3)
5870 self.vlan_101.set_vtr(L2_VTR_OP.L2_DISABLED)
5871 self.vlan_100.set_vtr(L2_VTR_OP.L2_DISABLED)
5872 self.pg7.unconfig_ip4()
5873 # make sure the programmed EP is no longer learnt from DP
5874 self.wait_for_ep_timeout(sw_if_index=rep.itf.sw_if_index, ip=rep.ip4)
5877 if __name__ == '__main__':
5878 unittest.main(testRunner=VppTestRunner)