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 tag_fixme_vpp_workers
17 from framework import VppTestCase, VppTestRunner
18 from vpp_object import VppObject
19 from vpp_interface import VppInterface
20 from vpp_ip_route import VppIpRoute, VppRoutePath, VppIpTable, \
21 VppIpInterfaceAddress, VppIpInterfaceBind, find_route, FibPathProto, \
23 from vpp_l2 import VppBridgeDomain, VppBridgeDomainPort, \
24 VppBridgeDomainArpEntry, VppL2FibEntry, find_bridge_domain_port, VppL2Vtr
25 from vpp_sub_interface import L2_VTR_OP, VppDot1QSubint
26 from vpp_ip import DpoProto, get_dpo_proto
27 from vpp_papi import VppEnum, MACAddress
28 from vpp_vxlan_gbp_tunnel import find_vxlan_gbp_tunnel, INDEX_INVALID, \
30 from vpp_neighbor import VppNeighbor
31 from vpp_acl import AclRule, VppAcl
40 def find_gbp_endpoint(test, sw_if_index=None, ip=None, mac=None,
41 tep=None, sclass=None, flags=None):
45 vmac = MACAddress(mac)
47 eps = test.vapi.gbp_endpoint_dump()
53 if src != str(ep.endpoint.tun.src) or \
54 dst != str(ep.endpoint.tun.dst):
57 if ep.endpoint.sw_if_index != sw_if_index:
60 if ep.endpoint.sclass != sclass:
63 if flags != (flags & ep.endpoint.flags):
66 for eip in ep.endpoint.ips:
70 if vmac == ep.endpoint.mac:
76 def find_gbp_vxlan(test, vni):
77 ts = test.vapi.gbp_vxlan_tunnel_dump()
79 if t.tunnel.vni == vni:
84 class VppGbpEndpoint(VppObject):
111 return [self.ip4, self.ip6]
115 return [self.fip4, self.fip6]
117 def __init__(self, test, itf, epg, recirc, ip4, fip4, ip6, fip6,
133 self.vmac = MACAddress(self.itf.remote_mac)
135 self.vmac = MACAddress("00:00:00:00:00:00")
138 self.tun_src = tun_src
139 self.tun_dst = tun_dst
141 def add_vpp_config(self):
142 res = self._test.vapi.gbp_endpoint_add(
143 self.itf.sw_if_index,
144 [self.ip4, self.ip6],
150 self.handle = res.handle
151 self._test.registry.register(self, self._test.logger)
153 def remove_vpp_config(self):
154 self._test.vapi.gbp_endpoint_del(self.handle)
157 return "gbp-endpoint:[%d==%d:%s:%d]" % (self.handle,
158 self.itf.sw_if_index,
162 def query_vpp_config(self):
163 return find_gbp_endpoint(self._test,
164 self.itf.sw_if_index,
168 class VppGbpRecirc(VppObject):
170 GBP Recirculation Interface
173 def __init__(self, test, epg, recirc, is_ext=False):
179 def add_vpp_config(self):
180 self._test.vapi.gbp_recirc_add_del(
182 self.recirc.sw_if_index,
185 self._test.registry.register(self, self._test.logger)
187 def remove_vpp_config(self):
188 self._test.vapi.gbp_recirc_add_del(
190 self.recirc.sw_if_index,
195 return "gbp-recirc:[%d]" % (self.recirc.sw_if_index)
197 def query_vpp_config(self):
198 rs = self._test.vapi.gbp_recirc_dump()
200 if r.recirc.sw_if_index == self.recirc.sw_if_index:
205 class VppGbpExtItf(VppObject):
207 GBP ExtItfulation Interface
210 def __init__(self, test, itf, bd, rd, anon=False):
215 self.flags = 1 if anon else 0
217 def add_vpp_config(self):
218 self._test.vapi.gbp_ext_itf_add_del(
219 1, self.itf.sw_if_index, self.bd.bd_id, self.rd.rd_id, self.flags)
220 self._test.registry.register(self, self._test.logger)
222 def remove_vpp_config(self):
223 self._test.vapi.gbp_ext_itf_add_del(
224 0, self.itf.sw_if_index, self.bd.bd_id, self.rd.rd_id, self.flags)
227 return "gbp-ext-itf:[%d]%s" % (self.itf.sw_if_index,
228 " [anon]" if self.flags else "")
230 def query_vpp_config(self):
231 rs = self._test.vapi.gbp_ext_itf_dump()
233 if r.ext_itf.sw_if_index == self.itf.sw_if_index:
238 class VppGbpSubnet(VppObject):
243 def __init__(self, test, rd, address, address_len,
244 type, sw_if_index=None, sclass=None):
246 self.rd_id = rd.rd_id
247 a = ip_address(address)
249 self.prefix = IPv4Network("%s/%d" % (address, address_len),
252 self.prefix = IPv6Network("%s/%d" % (address, address_len),
255 self.sw_if_index = sw_if_index
258 def add_vpp_config(self):
259 self._test.vapi.gbp_subnet_add_del(
264 sw_if_index=self.sw_if_index if self.sw_if_index else 0xffffffff,
265 sclass=self.sclass if self.sclass else 0xffff)
266 self._test.registry.register(self, self._test.logger)
268 def remove_vpp_config(self):
269 self._test.vapi.gbp_subnet_add_del(
276 return "gbp-subnet:[%d-%s]" % (self.rd_id, self.prefix)
278 def query_vpp_config(self):
279 ss = self._test.vapi.gbp_subnet_dump()
281 if s.subnet.rd_id == self.rd_id and \
282 s.subnet.type == self.type and \
283 s.subnet.prefix == self.prefix:
288 class VppGbpEndpointRetention(object):
289 def __init__(self, remote_ep_timeout=0xffffffff):
290 self.remote_ep_timeout = remote_ep_timeout
293 return {'remote_ep_timeout': self.remote_ep_timeout}
296 class VppGbpEndpointGroup(VppObject):
301 def __init__(self, test, vnid, sclass, rd, bd, uplink,
302 bvi, bvi_ip4, bvi_ip6=None,
303 retention=VppGbpEndpointRetention()):
307 self.bvi_ip4 = bvi_ip4
308 self.bvi_ip6 = bvi_ip6
315 self.retention = retention
317 def add_vpp_config(self):
318 self._test.vapi.gbp_endpoint_group_add(
323 self.uplink.sw_if_index if self.uplink else INDEX_INVALID,
324 self.retention.encode())
325 self._test.registry.register(self, self._test.logger)
327 def remove_vpp_config(self):
328 self._test.vapi.gbp_endpoint_group_del(self.sclass)
331 return "gbp-endpoint-group:[%d]" % (self.vnid)
333 def query_vpp_config(self):
334 epgs = self._test.vapi.gbp_endpoint_group_dump()
336 if epg.epg.vnid == self.vnid:
341 class VppGbpBridgeDomain(VppObject):
346 def __init__(self, test, bd, rd, bvi, uu_fwd=None,
347 bm_flood=None, learn=True,
348 uu_drop=False, bm_drop=False,
353 self.bm_flood = bm_flood
357 e = VppEnum.vl_api_gbp_bridge_domain_flags_t
359 self.flags = e.GBP_BD_API_FLAG_NONE
361 self.flags |= e.GBP_BD_API_FLAG_DO_NOT_LEARN
363 self.flags |= e.GBP_BD_API_FLAG_UU_FWD_DROP
365 self.flags |= e.GBP_BD_API_FLAG_MCAST_DROP
367 self.flags |= e.GBP_BD_API_FLAG_UCAST_ARP
369 def add_vpp_config(self):
370 self._test.vapi.gbp_bridge_domain_add(
374 self.bvi.sw_if_index,
375 self.uu_fwd.sw_if_index if self.uu_fwd else INDEX_INVALID,
376 self.bm_flood.sw_if_index if self.bm_flood else INDEX_INVALID)
377 self._test.registry.register(self, self._test.logger)
379 def remove_vpp_config(self):
380 self._test.vapi.gbp_bridge_domain_del(self.bd.bd_id)
383 return "gbp-bridge-domain:[%d]" % (self.bd.bd_id)
385 def query_vpp_config(self):
386 bds = self._test.vapi.gbp_bridge_domain_dump()
388 if bd.bd.bd_id == self.bd.bd_id:
393 class VppGbpRouteDomain(VppObject):
398 def __init__(self, test, rd_id, scope, t4, t6, ip4_uu=None, ip6_uu=None):
407 def add_vpp_config(self):
408 self._test.vapi.gbp_route_domain_add(
413 self.ip4_uu.sw_if_index if self.ip4_uu else INDEX_INVALID,
414 self.ip6_uu.sw_if_index if self.ip6_uu else INDEX_INVALID)
415 self._test.registry.register(self, self._test.logger)
417 def remove_vpp_config(self):
418 self._test.vapi.gbp_route_domain_del(self.rd_id)
421 return "gbp-route-domain:[%d]" % (self.rd_id)
423 def query_vpp_config(self):
424 rds = self._test.vapi.gbp_route_domain_dump()
426 if rd.rd.rd_id == self.rd_id:
431 class VppGbpContractNextHop():
432 def __init__(self, mac, bd, ip, rd):
439 return {'ip': self.ip,
440 'mac': self.mac.packed,
441 'bd_id': self.bd.bd.bd_id,
442 'rd_id': self.rd.rd_id}
445 class VppGbpContractRule():
446 def __init__(self, action, hash_mode, nhs=None):
448 self.hash_mode = hash_mode
449 self.nhs = [] if nhs is None else nhs
454 nhs.append(nh.encode())
457 return {'action': self.action,
459 'hash_mode': self.hash_mode,
460 'n_nhs': len(self.nhs),
464 return '<VppGbpContractRule action=%s, hash_mode=%s>' % (
465 self.action, self.hash_mode)
468 class VppGbpContract(VppObject):
473 def __init__(self, test, scope, sclass, dclass, acl_index,
474 rules, allowed_ethertypes):
476 if not isinstance(rules, list):
477 raise ValueError("'rules' must be a list.")
478 if not isinstance(allowed_ethertypes, list):
479 raise ValueError("'allowed_ethertypes' must be a list.")
481 self.acl_index = acl_index
485 self.allowed_ethertypes = allowed_ethertypes
486 while (len(self.allowed_ethertypes) < 16):
487 self.allowed_ethertypes.append(0)
489 def add_vpp_config(self):
492 rules.append(r.encode())
493 r = self._test.vapi.gbp_contract_add_del(
496 'acl_index': self.acl_index,
498 'sclass': self.sclass,
499 'dclass': self.dclass,
500 'n_rules': len(rules),
502 'n_ether_types': len(self.allowed_ethertypes),
503 'allowed_ethertypes': self.allowed_ethertypes})
504 self.stats_index = r.stats_index
505 self._test.registry.register(self, self._test.logger)
507 def remove_vpp_config(self):
508 self._test.vapi.gbp_contract_add_del(
511 'acl_index': self.acl_index,
513 'sclass': self.sclass,
514 'dclass': self.dclass,
517 'n_ether_types': len(self.allowed_ethertypes),
518 'allowed_ethertypes': self.allowed_ethertypes})
521 return "gbp-contract:[%d:%d:%d:%d]" % (self.scope,
526 def query_vpp_config(self):
527 cs = self._test.vapi.gbp_contract_dump()
529 if c.contract.scope == self.scope \
530 and c.contract.sclass == self.sclass \
531 and c.contract.dclass == self.dclass:
535 def get_drop_stats(self):
536 c = self._test.statistics.get_counter("/net/gbp/contract/drop")
537 return c[0][self.stats_index]
539 def get_permit_stats(self):
540 c = self._test.statistics.get_counter("/net/gbp/contract/permit")
541 return c[0][self.stats_index]
544 class VppGbpVxlanTunnel(VppInterface):
549 def __init__(self, test, vni, bd_rd_id, mode, src):
550 super(VppGbpVxlanTunnel, self).__init__(test)
553 self.bd_rd_id = bd_rd_id
557 def add_vpp_config(self):
558 r = self._test.vapi.gbp_vxlan_tunnel_add(
563 self.set_sw_if_index(r.sw_if_index)
564 self._test.registry.register(self, self._test.logger)
566 def remove_vpp_config(self):
567 self._test.vapi.gbp_vxlan_tunnel_del(self.vni)
570 return "gbp-vxlan:%d" % (self.sw_if_index)
572 def query_vpp_config(self):
573 return find_gbp_vxlan(self._test, self.vni)
576 @tag_fixme_vpp_workers
577 class TestGBP(VppTestCase):
578 """ GBP Test Case """
581 def nat_config_flags(self):
582 return VppEnum.vl_api_nat_config_flags_t
585 def nat44_config_flags(self):
586 return VppEnum.vl_api_nat44_config_flags_t
590 super(TestGBP, cls).setUpClass()
593 def tearDownClass(cls):
594 super(TestGBP, cls).tearDownClass()
597 super(TestGBP, self).setUp()
599 self.create_pg_interfaces(range(9))
600 self.create_loopback_interfaces(8)
602 self.router_mac = MACAddress("00:11:22:33:44:55")
604 for i in self.pg_interfaces:
606 for i in self.lo_interfaces:
609 self.vlan_100 = VppDot1QSubint(self, self.pg0, 100)
610 self.vlan_100.admin_up()
611 self.vlan_101 = VppDot1QSubint(self, self.pg0, 101)
612 self.vlan_101.admin_up()
613 self.vlan_102 = VppDot1QSubint(self, self.pg0, 102)
614 self.vlan_102.admin_up()
617 for i in self.pg_interfaces:
619 super(TestGBP, self).tearDown()
620 for i in self.lo_interfaces:
621 i.remove_vpp_config()
622 self.lo_interfaces = []
623 self.vlan_102.remove_vpp_config()
624 self.vlan_101.remove_vpp_config()
625 self.vlan_100.remove_vpp_config()
627 def send_and_expect_bridged(self, src, tx, dst):
628 rx = self.send_and_expect(src, tx, dst)
631 self.assertEqual(r[Ether].src, tx[0][Ether].src)
632 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
633 self.assertEqual(r[IP].src, tx[0][IP].src)
634 self.assertEqual(r[IP].dst, tx[0][IP].dst)
637 def send_and_expect_bridged6(self, src, tx, dst):
638 rx = self.send_and_expect(src, tx, dst)
641 self.assertEqual(r[Ether].src, tx[0][Ether].src)
642 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
643 self.assertEqual(r[IPv6].src, tx[0][IPv6].src)
644 self.assertEqual(r[IPv6].dst, tx[0][IPv6].dst)
647 def send_and_expect_routed(self, src, tx, dst, src_mac):
648 rx = self.send_and_expect(src, tx, dst)
651 self.assertEqual(r[Ether].src, src_mac)
652 self.assertEqual(r[Ether].dst, dst.remote_mac)
653 self.assertEqual(r[IP].src, tx[0][IP].src)
654 self.assertEqual(r[IP].dst, tx[0][IP].dst)
657 def send_and_expect_routed6(self, src, tx, dst, src_mac):
658 rx = self.send_and_expect(src, tx, dst)
661 self.assertEqual(r[Ether].src, src_mac)
662 self.assertEqual(r[Ether].dst, dst.remote_mac)
663 self.assertEqual(r[IPv6].src, tx[0][IPv6].src)
664 self.assertEqual(r[IPv6].dst, tx[0][IPv6].dst)
667 def send_and_expect_natted(self, src, tx, dst, src_ip):
668 rx = self.send_and_expect(src, tx, dst)
671 self.assertEqual(r[Ether].src, tx[0][Ether].src)
672 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
673 self.assertEqual(r[IP].src, src_ip)
674 self.assertEqual(r[IP].dst, tx[0][IP].dst)
677 def send_and_expect_natted6(self, src, tx, dst, src_ip):
678 rx = self.send_and_expect(src, tx, dst)
681 self.assertEqual(r[Ether].src, tx[0][Ether].src)
682 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
683 self.assertEqual(r[IPv6].src, src_ip)
684 self.assertEqual(r[IPv6].dst, tx[0][IPv6].dst)
687 def send_and_expect_unnatted(self, src, tx, dst, dst_ip):
688 rx = self.send_and_expect(src, tx, dst)
691 self.assertEqual(r[Ether].src, tx[0][Ether].src)
692 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
693 self.assertEqual(r[IP].dst, dst_ip)
694 self.assertEqual(r[IP].src, tx[0][IP].src)
697 def send_and_expect_unnatted6(self, src, tx, dst, dst_ip):
698 rx = self.send_and_expect(src, tx, dst)
701 self.assertEqual(r[Ether].src, tx[0][Ether].src)
702 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
703 self.assertEqual(r[IPv6].dst, dst_ip)
704 self.assertEqual(r[IPv6].src, tx[0][IPv6].src)
707 def send_and_expect_double_natted(self, src, tx, dst, src_ip, dst_ip):
708 rx = self.send_and_expect(src, tx, dst)
711 self.assertEqual(r[Ether].src, str(self.router_mac))
712 self.assertEqual(r[Ether].dst, dst.remote_mac)
713 self.assertEqual(r[IP].dst, dst_ip)
714 self.assertEqual(r[IP].src, src_ip)
717 def send_and_expect_double_natted6(self, src, tx, dst, src_ip, dst_ip):
718 rx = self.send_and_expect(src, tx, dst)
721 self.assertEqual(r[Ether].src, str(self.router_mac))
722 self.assertEqual(r[Ether].dst, dst.remote_mac)
723 self.assertEqual(r[IPv6].dst, dst_ip)
724 self.assertEqual(r[IPv6].src, src_ip)
727 def send_and_expect_no_arp(self, src, tx, dst):
728 self.pg_send(src, tx)
729 dst.get_capture(0, timeout=1)
730 dst.assert_nothing_captured(remark="")
733 def send_and_expect_arp(self, src, tx, dst):
734 rx = self.send_and_expect(src, tx, dst)
737 self.assertEqual(r[Ether].src, tx[0][Ether].src)
738 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
739 self.assertEqual(r[ARP].psrc, tx[0][ARP].psrc)
740 self.assertEqual(r[ARP].pdst, tx[0][ARP].pdst)
741 self.assertEqual(r[ARP].hwsrc, tx[0][ARP].hwsrc)
742 self.assertEqual(r[ARP].hwdst, tx[0][ARP].hwdst)
746 """ Group Based Policy """
748 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
753 gt4 = VppIpTable(self, 0)
755 gt6 = VppIpTable(self, 0, is_ip6=True)
757 nt4 = VppIpTable(self, 20)
759 nt6 = VppIpTable(self, 20, is_ip6=True)
762 rd0 = VppGbpRouteDomain(self, 0, 400, gt4, gt6, None, None)
763 rd20 = VppGbpRouteDomain(self, 20, 420, nt4, nt6, None, None)
766 rd20.add_vpp_config()
771 bd1 = VppBridgeDomain(self, 1)
772 bd2 = VppBridgeDomain(self, 2)
773 bd20 = VppBridgeDomain(self, 20)
777 bd20.add_vpp_config()
779 gbd1 = VppGbpBridgeDomain(self, bd1, rd0, self.loop0)
780 gbd2 = VppGbpBridgeDomain(self, bd2, rd0, self.loop1)
781 gbd20 = VppGbpBridgeDomain(self, bd20, rd20, self.loop2)
783 gbd1.add_vpp_config()
784 gbd2.add_vpp_config()
785 gbd20.add_vpp_config()
788 # 3 EPGs, 2 of which share a BD.
789 # 2 NAT EPGs, one for floating-IP subnets, the other for internet
791 epgs = [VppGbpEndpointGroup(self, 220, 1220, rd0, gbd1,
792 self.pg4, self.loop0,
793 "10.0.0.128", "2001:10::128"),
794 VppGbpEndpointGroup(self, 221, 1221, rd0, gbd1,
795 self.pg5, self.loop0,
796 "10.0.1.128", "2001:10:1::128"),
797 VppGbpEndpointGroup(self, 222, 1222, rd0, gbd2,
798 self.pg6, self.loop1,
799 "10.0.2.128", "2001:10:2::128"),
800 VppGbpEndpointGroup(self, 333, 1333, rd20, gbd20,
801 self.pg7, self.loop2,
802 "11.0.0.128", "3001::128"),
803 VppGbpEndpointGroup(self, 444, 1444, rd20, gbd20,
804 self.pg8, self.loop2,
805 "11.0.0.129", "3001::129")]
806 recircs = [VppGbpRecirc(self, epgs[0], self.loop3),
807 VppGbpRecirc(self, epgs[1], self.loop4),
808 VppGbpRecirc(self, epgs[2], self.loop5),
809 VppGbpRecirc(self, epgs[3], self.loop6, is_ext=True),
810 VppGbpRecirc(self, epgs[4], self.loop7, is_ext=True)]
813 recirc_nat = recircs[3]
816 # 4 end-points, 2 in the same subnet, 3 in the same BD
818 eps = [VppGbpEndpoint(self, self.pg0,
820 "10.0.0.1", "11.0.0.1",
821 "2001:10::1", "3001::1"),
822 VppGbpEndpoint(self, self.pg1,
824 "10.0.0.2", "11.0.0.2",
825 "2001:10::2", "3001::2"),
826 VppGbpEndpoint(self, self.pg2,
828 "10.0.1.1", "11.0.0.3",
829 "2001:10:1::1", "3001::3"),
830 VppGbpEndpoint(self, self.pg3,
832 "10.0.2.1", "11.0.0.4",
833 "2001:10:2::1", "3001::4")]
835 self.vapi.nat44_ed_plugin_enable_disable(enable=1)
838 # Config related to each of the EPGs
841 # IP config on the BVI interfaces
842 if epg != epgs[1] and epg != epgs[4]:
843 b4 = VppIpInterfaceBind(self, epg.bvi,
844 epg.rd.t4).add_vpp_config()
845 b6 = VppIpInterfaceBind(self, epg.bvi,
846 epg.rd.t6).add_vpp_config()
847 epg.bvi.set_mac(self.router_mac)
849 # The BVIs are NAT inside interfaces
850 flags = self.nat_config_flags.NAT_IS_INSIDE
851 self.vapi.nat44_interface_add_del_feature(
852 sw_if_index=epg.bvi.sw_if_index,
853 flags=flags, is_add=1)
854 self.vapi.nat66_add_del_interface(
855 is_add=1, flags=flags,
856 sw_if_index=epg.bvi.sw_if_index)
858 if_ip4 = VppIpInterfaceAddress(self, epg.bvi,
860 bind=b4).add_vpp_config()
861 if_ip6 = VppIpInterfaceAddress(self, epg.bvi,
863 bind=b6).add_vpp_config()
865 # EPG uplink interfaces in the RD
866 VppIpInterfaceBind(self, epg.uplink, epg.rd.t4).add_vpp_config()
867 VppIpInterfaceBind(self, epg.uplink, epg.rd.t6).add_vpp_config()
869 # add the BD ARP termination entry for BVI IP
870 epg.bd_arp_ip4 = VppBridgeDomainArpEntry(self, epg.bd.bd,
871 str(self.router_mac),
873 epg.bd_arp_ip6 = VppBridgeDomainArpEntry(self, epg.bd.bd,
874 str(self.router_mac),
876 epg.bd_arp_ip4.add_vpp_config()
877 epg.bd_arp_ip6.add_vpp_config()
882 for recirc in recircs:
883 # EPG's ingress recirculation interface maps to its RD
884 VppIpInterfaceBind(self, recirc.recirc,
885 recirc.epg.rd.t4).add_vpp_config()
886 VppIpInterfaceBind(self, recirc.recirc,
887 recirc.epg.rd.t6).add_vpp_config()
889 self.vapi.nat44_interface_add_del_feature(
890 sw_if_index=recirc.recirc.sw_if_index, is_add=1)
891 self.vapi.nat66_add_del_interface(
893 sw_if_index=recirc.recirc.sw_if_index)
895 recirc.add_vpp_config()
897 for recirc in recircs:
898 self.assertTrue(find_bridge_domain_port(self,
899 recirc.epg.bd.bd.bd_id,
900 recirc.recirc.sw_if_index))
903 self.pg_enable_capture(self.pg_interfaces)
906 # routes to the endpoints. We need these since there are no
907 # adj-fibs due to the fact the the BVI address has /32 and
908 # the subnet is not attached.
910 for (ip, fip) in zip(ep.ips, ep.fips):
911 # Add static mappings for each EP from the 10/8 to 11/8 network
912 if ip_address(ip).version == 4:
913 flags = self.nat_config_flags.NAT_IS_ADDR_ONLY
914 self.vapi.nat44_add_del_static_mapping(
917 external_ip_address=fip,
918 external_sw_if_index=0xFFFFFFFF,
922 self.vapi.nat66_add_del_static_mapping(
924 external_ip_address=fip,
930 self.logger.info(self.vapi.cli("sh gbp endpoint"))
932 # ... results in a Gratuitous ARP/ND on the EPG's uplink
933 rx = ep.epg.uplink.get_capture(len(ep.ips), timeout=0.2)
935 for ii, ip in enumerate(ep.ips):
938 if ip_address(ip).version == 6:
939 self.assertTrue(p.haslayer(ICMPv6ND_NA))
940 self.assertEqual(p[ICMPv6ND_NA].tgt, ip)
942 self.assertTrue(p.haslayer(ARP))
943 self.assertEqual(p[ARP].psrc, ip)
944 self.assertEqual(p[ARP].pdst, ip)
946 # add the BD ARP termination entry for floating IP
948 ba = VppBridgeDomainArpEntry(self, epg_nat.bd.bd, ep.mac,
952 # floating IPs route via EPG recirc
954 self, fip, ip_address(fip).max_prefixlen,
956 ep.recirc.recirc.sw_if_index,
957 type=FibPathType.FIB_PATH_TYPE_DVR,
958 proto=get_dpo_proto(fip))],
962 # L2 FIB entries in the NAT EPG BD to bridge the packets from
963 # the outside direct to the internal EPG
964 lf = VppL2FibEntry(self, epg_nat.bd.bd, ep.mac,
965 ep.recirc.recirc, bvi_mac=0)
969 # ARP packets for unknown IP are sent to the EPG uplink
971 pkt_arp = (Ether(dst="ff:ff:ff:ff:ff:ff",
972 src=self.pg0.remote_mac) /
974 hwdst="ff:ff:ff:ff:ff:ff",
975 hwsrc=self.pg0.remote_mac,
979 self.vapi.cli("clear trace")
980 self.pg0.add_stream(pkt_arp)
982 self.pg_enable_capture(self.pg_interfaces)
985 rxd = epgs[0].uplink.get_capture(1)
988 # ARP/ND packets get a response
990 pkt_arp = (Ether(dst="ff:ff:ff:ff:ff:ff",
991 src=self.pg0.remote_mac) /
993 hwdst="ff:ff:ff:ff:ff:ff",
994 hwsrc=self.pg0.remote_mac,
995 pdst=epgs[0].bvi_ip4,
998 self.send_and_expect(self.pg0, [pkt_arp], self.pg0)
1000 nsma = in6_getnsma(inet_pton(AF_INET6, eps[0].ip6))
1001 d = inet_ntop(AF_INET6, nsma)
1002 pkt_nd = (Ether(dst=in6_getnsmac(nsma),
1003 src=self.pg0.remote_mac) /
1004 IPv6(dst=d, src=eps[0].ip6) /
1005 ICMPv6ND_NS(tgt=epgs[0].bvi_ip6) /
1006 ICMPv6NDOptSrcLLAddr(lladdr=self.pg0.remote_mac))
1007 self.send_and_expect(self.pg0, [pkt_nd], self.pg0)
1010 # broadcast packets are flooded
1012 pkt_bcast = (Ether(dst="ff:ff:ff:ff:ff:ff",
1013 src=self.pg0.remote_mac) /
1014 IP(src=eps[0].ip4, dst="232.1.1.1") /
1015 UDP(sport=1234, dport=1234) /
1018 self.vapi.cli("clear trace")
1019 self.pg0.add_stream(pkt_bcast)
1021 self.pg_enable_capture(self.pg_interfaces)
1024 rxd = eps[1].itf.get_capture(1)
1025 self.assertEqual(rxd[0][Ether].dst, pkt_bcast[Ether].dst)
1026 rxd = epgs[0].uplink.get_capture(1)
1027 self.assertEqual(rxd[0][Ether].dst, pkt_bcast[Ether].dst)
1030 # packets to non-local L3 destinations dropped
1032 pkt_intra_epg_220_ip4 = (Ether(src=self.pg0.remote_mac,
1033 dst=str(self.router_mac)) /
1036 UDP(sport=1234, dport=1234) /
1038 pkt_inter_epg_222_ip4 = (Ether(src=self.pg0.remote_mac,
1039 dst=str(self.router_mac)) /
1042 UDP(sport=1234, dport=1234) /
1045 self.send_and_assert_no_replies(self.pg0,
1046 pkt_intra_epg_220_ip4 * NUM_PKTS)
1048 pkt_inter_epg_222_ip6 = (Ether(src=self.pg0.remote_mac,
1049 dst=str(self.router_mac)) /
1050 IPv6(src=eps[0].ip6,
1051 dst="2001:10::99") /
1052 UDP(sport=1234, dport=1234) /
1054 self.send_and_assert_no_replies(self.pg0,
1055 pkt_inter_epg_222_ip6 * NUM_PKTS)
1058 # Add the subnet routes
1061 self, rd0, "10.0.0.0", 24,
1062 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1064 self, rd0, "10.0.1.0", 24,
1065 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1067 self, rd0, "10.0.2.0", 24,
1068 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1070 self, rd0, "2001:10::1", 64,
1071 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1073 self, rd0, "2001:10:1::1", 64,
1074 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1076 self, rd0, "2001:10:2::1", 64,
1077 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1078 s41.add_vpp_config()
1079 s42.add_vpp_config()
1080 s43.add_vpp_config()
1081 s61.add_vpp_config()
1082 s62.add_vpp_config()
1083 s63.add_vpp_config()
1085 self.send_and_expect_bridged(eps[0].itf,
1086 pkt_intra_epg_220_ip4 * NUM_PKTS,
1088 self.send_and_expect_bridged(eps[0].itf,
1089 pkt_inter_epg_222_ip4 * NUM_PKTS,
1091 self.send_and_expect_bridged6(eps[0].itf,
1092 pkt_inter_epg_222_ip6 * NUM_PKTS,
1095 self.logger.info(self.vapi.cli("sh ip fib 11.0.0.2"))
1096 self.logger.info(self.vapi.cli("sh gbp endpoint-group"))
1097 self.logger.info(self.vapi.cli("sh gbp endpoint"))
1098 self.logger.info(self.vapi.cli("sh gbp recirc"))
1099 self.logger.info(self.vapi.cli("sh int"))
1100 self.logger.info(self.vapi.cli("sh int addr"))
1101 self.logger.info(self.vapi.cli("sh int feat loop6"))
1102 self.logger.info(self.vapi.cli("sh vlib graph ip4-gbp-src-classify"))
1103 self.logger.info(self.vapi.cli("sh int feat loop3"))
1104 self.logger.info(self.vapi.cli("sh int feat pg0"))
1107 # Packet destined to unknown unicast is sent on the epg uplink ...
1109 pkt_intra_epg_220_to_uplink = (Ether(src=self.pg0.remote_mac,
1110 dst="00:00:00:33:44:55") /
1113 UDP(sport=1234, dport=1234) /
1116 self.send_and_expect_bridged(eps[0].itf,
1117 pkt_intra_epg_220_to_uplink * NUM_PKTS,
1119 # ... and nowhere else
1120 self.pg1.get_capture(0, timeout=0.1)
1121 self.pg1.assert_nothing_captured(remark="Flood onto other VMS")
1123 pkt_intra_epg_221_to_uplink = (Ether(src=self.pg2.remote_mac,
1124 dst="00:00:00:33:44:66") /
1127 UDP(sport=1234, dport=1234) /
1130 self.send_and_expect_bridged(eps[2].itf,
1131 pkt_intra_epg_221_to_uplink * NUM_PKTS,
1135 # Packets from the uplink are forwarded in the absence of a contract
1137 pkt_intra_epg_220_from_uplink = (Ether(src="00:00:00:33:44:55",
1138 dst=self.pg0.remote_mac) /
1141 UDP(sport=1234, dport=1234) /
1144 self.send_and_expect_bridged(self.pg4,
1145 pkt_intra_epg_220_from_uplink * NUM_PKTS,
1149 # in the absence of policy, endpoints in the same EPG
1152 pkt_intra_epg = (Ether(src=self.pg0.remote_mac,
1153 dst=self.pg1.remote_mac) /
1156 UDP(sport=1234, dport=1234) /
1159 self.send_and_expect_bridged(self.pg0,
1160 pkt_intra_epg * NUM_PKTS,
1164 # in the absence of policy, endpoints in the different EPG
1165 # cannot communicate
1167 pkt_inter_epg_220_to_221 = (Ether(src=self.pg0.remote_mac,
1168 dst=self.pg2.remote_mac) /
1171 UDP(sport=1234, dport=1234) /
1173 pkt_inter_epg_221_to_220 = (Ether(src=self.pg2.remote_mac,
1174 dst=self.pg0.remote_mac) /
1177 UDP(sport=1234, dport=1234) /
1179 pkt_inter_epg_220_to_222 = (Ether(src=self.pg0.remote_mac,
1180 dst=str(self.router_mac)) /
1183 UDP(sport=1234, dport=1234) /
1186 self.send_and_assert_no_replies(eps[0].itf,
1187 pkt_inter_epg_220_to_221 * NUM_PKTS)
1188 self.send_and_assert_no_replies(eps[0].itf,
1189 pkt_inter_epg_220_to_222 * NUM_PKTS)
1192 # A uni-directional contract from EPG 220 -> 221
1194 rule = AclRule(is_permit=1, proto=17)
1195 rule2 = AclRule(src_prefix=IPv6Network((0, 0)),
1196 dst_prefix=IPv6Network((0, 0)), is_permit=1, proto=17)
1197 acl = VppAcl(self, rules=[rule, rule2])
1198 acl.add_vpp_config()
1200 c1 = VppGbpContract(
1201 self, 400, epgs[0].sclass, epgs[1].sclass, acl.acl_index,
1202 [VppGbpContractRule(
1203 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1204 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1207 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1208 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1210 [ETH_P_IP, ETH_P_IPV6])
1213 self.send_and_expect_bridged(eps[0].itf,
1214 pkt_inter_epg_220_to_221 * NUM_PKTS,
1216 self.send_and_assert_no_replies(eps[0].itf,
1217 pkt_inter_epg_220_to_222 * NUM_PKTS)
1220 # contract for the return direction
1222 c2 = VppGbpContract(
1223 self, 400, epgs[1].sclass, epgs[0].sclass, acl.acl_index,
1224 [VppGbpContractRule(
1225 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1226 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1229 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1230 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1232 [ETH_P_IP, ETH_P_IPV6])
1235 self.send_and_expect_bridged(eps[0].itf,
1236 pkt_inter_epg_220_to_221 * NUM_PKTS,
1238 self.send_and_expect_bridged(eps[2].itf,
1239 pkt_inter_epg_221_to_220 * NUM_PKTS,
1242 ds = c2.get_drop_stats()
1243 self.assertEqual(ds['packets'], 0)
1244 ps = c2.get_permit_stats()
1245 self.assertEqual(ps['packets'], NUM_PKTS)
1248 # the contract does not allow non-IP
1250 pkt_non_ip_inter_epg_220_to_221 = (Ether(src=self.pg0.remote_mac,
1251 dst=self.pg2.remote_mac) /
1253 self.send_and_assert_no_replies(eps[0].itf,
1254 pkt_non_ip_inter_epg_220_to_221 * 17)
1257 # check that inter group is still disabled for the groups
1258 # not in the contract.
1260 self.send_and_assert_no_replies(eps[0].itf,
1261 pkt_inter_epg_220_to_222 * NUM_PKTS)
1264 # A uni-directional contract from EPG 220 -> 222 'L3 routed'
1266 c3 = VppGbpContract(
1267 self, 400, epgs[0].sclass, epgs[2].sclass, acl.acl_index,
1268 [VppGbpContractRule(
1269 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1270 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1273 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1274 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1276 [ETH_P_IP, ETH_P_IPV6])
1279 self.logger.info(self.vapi.cli("sh gbp contract"))
1281 self.send_and_expect_routed(eps[0].itf,
1282 pkt_inter_epg_220_to_222 * NUM_PKTS,
1284 str(self.router_mac))
1287 # remove both contracts, traffic stops in both directions
1289 c2.remove_vpp_config()
1290 c1.remove_vpp_config()
1291 c3.remove_vpp_config()
1292 acl.remove_vpp_config()
1294 self.send_and_assert_no_replies(eps[2].itf,
1295 pkt_inter_epg_221_to_220 * NUM_PKTS)
1296 self.send_and_assert_no_replies(eps[0].itf,
1297 pkt_inter_epg_220_to_221 * NUM_PKTS)
1298 self.send_and_expect_bridged(eps[0].itf,
1299 pkt_intra_epg * NUM_PKTS,
1303 # EPs to the outside world
1306 # in the EP's RD an external subnet via the NAT EPG's recirc
1308 self, rd0, "0.0.0.0", 0,
1309 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1310 sw_if_index=recirc_nat.recirc.sw_if_index,
1311 sclass=epg_nat.sclass)
1313 self, rd0, "11.0.0.0", 8,
1314 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1315 sw_if_index=recirc_nat.recirc.sw_if_index,
1316 sclass=epg_nat.sclass)
1317 se16 = VppGbpSubnet(
1319 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1320 sw_if_index=recirc_nat.recirc.sw_if_index,
1321 sclass=epg_nat.sclass)
1322 # in the NAT RD an external subnet via the NAT EPG's uplink
1324 self, rd20, "0.0.0.0", 0,
1325 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1326 sw_if_index=epg_nat.uplink.sw_if_index,
1327 sclass=epg_nat.sclass)
1328 se36 = VppGbpSubnet(
1329 self, rd20, "::", 0,
1330 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1331 sw_if_index=epg_nat.uplink.sw_if_index,
1332 sclass=epg_nat.sclass)
1334 self, rd20, "11.0.0.0", 8,
1335 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1336 sw_if_index=epg_nat.uplink.sw_if_index,
1337 sclass=epg_nat.sclass)
1338 se1.add_vpp_config()
1339 se2.add_vpp_config()
1340 se16.add_vpp_config()
1341 se3.add_vpp_config()
1342 se36.add_vpp_config()
1343 se4.add_vpp_config()
1345 self.logger.info(self.vapi.cli("sh ip fib 0.0.0.0/0"))
1346 self.logger.info(self.vapi.cli("sh ip fib 11.0.0.1"))
1347 self.logger.info(self.vapi.cli("sh ip6 fib ::/0"))
1348 self.logger.info(self.vapi.cli("sh ip6 fib %s" %
1352 # From an EP to an outside address: IN2OUT
1354 pkt_inter_epg_220_to_global = (Ether(src=self.pg0.remote_mac,
1355 dst=str(self.router_mac)) /
1358 UDP(sport=1234, dport=1234) /
1362 self.send_and_assert_no_replies(eps[0].itf,
1363 pkt_inter_epg_220_to_global * NUM_PKTS)
1364 rule = AclRule(is_permit=1, proto=17, ports=1234)
1365 rule2 = AclRule(is_permit=1, proto=17, ports=1234,
1366 src_prefix=IPv6Network((0, 0)),
1367 dst_prefix=IPv6Network((0, 0)))
1368 acl2 = VppAcl(self, rules=[rule, rule2])
1369 acl2.add_vpp_config()
1371 c4 = VppGbpContract(
1372 self, 400, epgs[0].sclass, epgs[3].sclass, acl2.acl_index,
1373 [VppGbpContractRule(
1374 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1375 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1378 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1379 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1381 [ETH_P_IP, ETH_P_IPV6])
1384 self.send_and_expect_natted(eps[0].itf,
1385 pkt_inter_epg_220_to_global * NUM_PKTS,
1389 pkt_inter_epg_220_to_global = (Ether(src=self.pg0.remote_mac,
1390 dst=str(self.router_mac)) /
1391 IPv6(src=eps[0].ip6,
1393 UDP(sport=1234, dport=1234) /
1396 self.send_and_expect_natted6(self.pg0,
1397 pkt_inter_epg_220_to_global * NUM_PKTS,
1402 # From a global address to an EP: OUT2IN
1404 pkt_inter_epg_220_from_global = (Ether(src=str(self.router_mac),
1405 dst=self.pg0.remote_mac) /
1408 UDP(sport=1234, dport=1234) /
1411 self.send_and_assert_no_replies(
1412 self.pg7, pkt_inter_epg_220_from_global * NUM_PKTS)
1414 c5 = VppGbpContract(
1415 self, 400, epgs[3].sclass, epgs[0].sclass, acl2.acl_index,
1416 [VppGbpContractRule(
1417 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1418 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1421 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1422 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1424 [ETH_P_IP, ETH_P_IPV6])
1427 self.send_and_expect_unnatted(self.pg7,
1428 pkt_inter_epg_220_from_global * NUM_PKTS,
1432 pkt_inter_epg_220_from_global = (Ether(src=str(self.router_mac),
1433 dst=self.pg0.remote_mac) /
1434 IPv6(dst=eps[0].fip6,
1436 UDP(sport=1234, dport=1234) /
1439 self.send_and_expect_unnatted6(
1441 pkt_inter_epg_220_from_global * NUM_PKTS,
1446 # From a local VM to another local VM using resp. public addresses:
1449 pkt_intra_epg_220_global = (Ether(src=self.pg0.remote_mac,
1450 dst=str(self.router_mac)) /
1453 UDP(sport=1234, dport=1234) /
1456 self.send_and_expect_double_natted(eps[0].itf,
1457 pkt_intra_epg_220_global * NUM_PKTS,
1462 pkt_intra_epg_220_global = (Ether(src=self.pg0.remote_mac,
1463 dst=str(self.router_mac)) /
1464 IPv6(src=eps[0].ip6,
1466 UDP(sport=1234, dport=1234) /
1469 self.send_and_expect_double_natted6(
1471 pkt_intra_epg_220_global * NUM_PKTS,
1479 self.vapi.nat44_ed_plugin_enable_disable(enable=0)
1482 # del static mappings for each EP from the 10/8 to 11/8 network
1483 flags = self.nat_config_flags.NAT_IS_ADDR_ONLY
1484 self.vapi.nat66_add_del_static_mapping(
1485 local_ip_address=ep.ip6,
1486 external_ip_address=ep.fip6,
1490 # IP config on the BVI interfaces
1491 if epg != epgs[0] and epg != epgs[3]:
1492 flags = self.nat_config_flags.NAT_IS_INSIDE
1493 self.vapi.nat66_add_del_interface(
1494 sw_if_index=epg.bvi.sw_if_index,
1495 flags=flags, is_add=0)
1497 for recirc in recircs:
1498 self.vapi.nat66_add_del_interface(
1499 sw_if_index=recirc.recirc.sw_if_index, is_add=0)
1501 def wait_for_ep_timeout(self, sw_if_index=None, ip=None, mac=None,
1502 tep=None, n_tries=100, s_time=1):
1503 # only learnt EP can timeout
1504 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
1505 flags = ep_flags.GBP_API_ENDPOINT_FLAG_LEARNT
1507 if not find_gbp_endpoint(self, sw_if_index, ip, mac, tep=tep,
1510 n_tries = n_tries - 1
1512 self.assertFalse(find_gbp_endpoint(self, sw_if_index, ip, mac, tep=tep,
1516 def test_gbp_learn_l2(self):
1517 """ GBP L2 Endpoint Learning """
1519 drop_no_contract = self.statistics.get_err_counter(
1520 '/err/gbp-policy-port/drop-no-contract')
1521 allow_intra_class = self.statistics.get_err_counter(
1522 '/err/gbp-policy-port/allow-intra-sclass')
1524 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
1525 learnt = [{'mac': '00:00:11:11:11:01',
1527 'ip6': '2001:10::2'},
1528 {'mac': '00:00:11:11:11:02',
1530 'ip6': '2001:10::3'}]
1535 gt4 = VppIpTable(self, 1)
1536 gt4.add_vpp_config()
1537 gt6 = VppIpTable(self, 1, is_ip6=True)
1538 gt6.add_vpp_config()
1540 rd1 = VppGbpRouteDomain(self, 1, 401, gt4, gt6)
1541 rd1.add_vpp_config()
1544 # Pg2 hosts the vxlan tunnel, hosts on pg2 to act as TEPs
1545 # Pg3 hosts the IP4 UU-flood VXLAN tunnel
1546 # Pg4 hosts the IP6 UU-flood VXLAN tunnel
1548 self.pg2.config_ip4()
1549 self.pg2.resolve_arp()
1550 self.pg2.generate_remote_hosts(4)
1551 self.pg2.configure_ipv4_neighbors()
1552 self.pg3.config_ip4()
1553 self.pg3.resolve_arp()
1554 self.pg4.config_ip4()
1555 self.pg4.resolve_arp()
1558 # Add a mcast destination VXLAN-GBP tunnel for B&M traffic
1560 tun_bm = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
1563 tun_bm.add_vpp_config()
1566 # a GBP bridge domain with a BVI and a UU-flood interface
1568 bd1 = VppBridgeDomain(self, 1)
1569 bd1.add_vpp_config()
1570 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0,
1572 gbd1.add_vpp_config()
1574 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1575 self.logger.info(self.vapi.cli("sh gbp bridge"))
1577 # ... and has a /32 applied
1578 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
1579 ip_addr.add_vpp_config()
1582 # The Endpoint-group in which we are learning endpoints
1584 epg_220 = VppGbpEndpointGroup(self, 220, 112, rd1, gbd1,
1588 VppGbpEndpointRetention(4))
1589 epg_220.add_vpp_config()
1590 epg_330 = VppGbpEndpointGroup(self, 330, 113, rd1, gbd1,
1594 VppGbpEndpointRetention(4))
1595 epg_330.add_vpp_config()
1598 # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
1601 vx_tun_l2_1 = VppGbpVxlanTunnel(
1602 self, 99, bd1.bd_id,
1603 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L2,
1605 vx_tun_l2_1.add_vpp_config()
1608 # A static endpoint that the learnt endpoints are trying to
1611 ep = VppGbpEndpoint(self, self.pg0,
1613 "10.0.0.127", "11.0.0.127",
1614 "2001:10::1", "3001::1")
1617 self.assertTrue(find_route(self, ep.ip4, 32, table_id=1))
1619 # a packet with an sclass from an unknown EPG
1620 p = (Ether(src=self.pg2.remote_mac,
1621 dst=self.pg2.local_mac) /
1622 IP(src=self.pg2.remote_hosts[0].ip4,
1623 dst=self.pg2.local_ip4) /
1624 UDP(sport=1234, dport=48879) /
1625 VXLAN(vni=99, gpid=88, flags=0x88) /
1626 Ether(src=learnt[0]["mac"], dst=ep.mac) /
1627 IP(src=learnt[0]["ip"], dst=ep.ip4) /
1628 UDP(sport=1234, dport=1234) /
1631 self.send_and_assert_no_replies(self.pg2, p)
1633 self.logger.info(self.vapi.cli("sh error"))
1634 self.assert_error_counter_equal(
1635 '/err/gbp-policy-port/drop-no-contract',
1636 drop_no_contract + 1)
1639 # we should not have learnt a new tunnel endpoint, since
1640 # the EPG was not learnt.
1642 self.assertEqual(INDEX_INVALID,
1643 find_vxlan_gbp_tunnel(self,
1645 self.pg2.remote_hosts[0].ip4,
1648 # ep is not learnt, because the EPG is unknown
1649 self.assertEqual(len(self.vapi.gbp_endpoint_dump()), 1)
1652 # Learn new EPs from IP packets
1654 for ii, l in enumerate(learnt):
1655 # a packet with an sclass from a known EPG
1656 # arriving on an unknown TEP
1657 p = (Ether(src=self.pg2.remote_mac,
1658 dst=self.pg2.local_mac) /
1659 IP(src=self.pg2.remote_hosts[1].ip4,
1660 dst=self.pg2.local_ip4) /
1661 UDP(sport=1234, dport=48879) /
1662 VXLAN(vni=99, gpid=112, flags=0x88) /
1663 Ether(src=l['mac'], dst=ep.mac) /
1664 IP(src=l['ip'], dst=ep.ip4) /
1665 UDP(sport=1234, dport=1234) /
1668 rx = self.send_and_expect(self.pg2, [p], self.pg0)
1671 tep1_sw_if_index = find_vxlan_gbp_tunnel(
1674 self.pg2.remote_hosts[1].ip4,
1676 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
1679 # the EP is learnt via the learnt TEP
1680 # both from its MAC and its IP
1682 self.assertTrue(find_gbp_endpoint(self,
1683 vx_tun_l2_1.sw_if_index,
1685 self.assertTrue(find_gbp_endpoint(self,
1686 vx_tun_l2_1.sw_if_index,
1689 self.assert_error_counter_equal(
1690 '/err/gbp-policy-port/allow-intra-sclass',
1691 allow_intra_class + 2)
1693 self.logger.info(self.vapi.cli("show gbp endpoint"))
1694 self.logger.info(self.vapi.cli("show gbp vxlan"))
1695 self.logger.info(self.vapi.cli("show ip mfib"))
1698 # If we sleep for the threshold time, the learnt endpoints should
1702 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1706 # Learn new EPs from GARP packets received on the BD's mcast tunnel
1708 for ii, l in enumerate(learnt):
1709 # add some junk in the reserved field of the vxlan-header
1710 # next to the VNI. we should accept since reserved bits are
1712 p = (Ether(src=self.pg2.remote_mac,
1713 dst=self.pg2.local_mac) /
1714 IP(src=self.pg2.remote_hosts[1].ip4,
1716 UDP(sport=1234, dport=48879) /
1717 VXLAN(vni=88, reserved2=0x80, gpid=112, flags=0x88) /
1718 Ether(src=l['mac'], dst="ff:ff:ff:ff:ff:ff") /
1720 psrc=l['ip'], pdst=l['ip'],
1721 hwsrc=l['mac'], hwdst="ff:ff:ff:ff:ff:ff"))
1723 rx = self.send_and_expect(self.pg4, [p], self.pg0)
1726 tep1_sw_if_index = find_vxlan_gbp_tunnel(
1729 self.pg2.remote_hosts[1].ip4,
1731 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
1734 # the EP is learnt via the learnt TEP
1735 # both from its MAC and its IP
1737 self.assertTrue(find_gbp_endpoint(self,
1738 vx_tun_l2_1.sw_if_index,
1740 self.assertTrue(find_gbp_endpoint(self,
1741 vx_tun_l2_1.sw_if_index,
1745 # wait for the learnt endpoints to age out
1748 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1752 # Learn new EPs from L2 packets
1754 for ii, l in enumerate(learnt):
1755 # a packet with an sclass from a known EPG
1756 # arriving on an unknown TEP
1757 p = (Ether(src=self.pg2.remote_mac,
1758 dst=self.pg2.local_mac) /
1759 IP(src=self.pg2.remote_hosts[1].ip4,
1760 dst=self.pg2.local_ip4) /
1761 UDP(sport=1234, dport=48879) /
1762 VXLAN(vni=99, gpid=112, flags=0x88) /
1763 Ether(src=l['mac'], dst=ep.mac) /
1766 rx = self.send_and_expect(self.pg2, [p], self.pg0)
1769 tep1_sw_if_index = find_vxlan_gbp_tunnel(
1772 self.pg2.remote_hosts[1].ip4,
1774 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
1777 # the EP is learnt via the learnt TEP
1778 # both from its MAC and its IP
1780 self.assertTrue(find_gbp_endpoint(self,
1781 vx_tun_l2_1.sw_if_index,
1784 self.logger.info(self.vapi.cli("show gbp endpoint"))
1785 self.logger.info(self.vapi.cli("show gbp vxlan"))
1786 self.logger.info(self.vapi.cli("show vxlan-gbp tunnel"))
1789 # wait for the learnt endpoints to age out
1792 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1796 # repeat. the do not learn bit is set so the EPs are not learnt
1799 # a packet with an sclass from a known EPG
1800 p = (Ether(src=self.pg2.remote_mac,
1801 dst=self.pg2.local_mac) /
1802 IP(src=self.pg2.remote_hosts[1].ip4,
1803 dst=self.pg2.local_ip4) /
1804 UDP(sport=1234, dport=48879) /
1805 VXLAN(vni=99, gpid=112, flags=0x88, gpflags="D") /
1806 Ether(src=l['mac'], dst=ep.mac) /
1807 IP(src=l['ip'], dst=ep.ip4) /
1808 UDP(sport=1234, dport=1234) /
1811 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
1814 self.assertFalse(find_gbp_endpoint(self,
1815 vx_tun_l2_1.sw_if_index,
1822 # a packet with an sclass from a known EPG
1823 # set a reserved bit in addition to the G and I
1824 # reserved bits should not be checked on rx.
1825 p = (Ether(src=self.pg2.remote_mac,
1826 dst=self.pg2.local_mac) /
1827 IP(src=self.pg2.remote_hosts[1].ip4,
1828 dst=self.pg2.local_ip4) /
1829 UDP(sport=1234, dport=48879) /
1830 VXLAN(vni=99, gpid=112, flags=0xc8) /
1831 Ether(src=l['mac'], dst=ep.mac) /
1832 IP(src=l['ip'], dst=ep.ip4) /
1833 UDP(sport=1234, dport=1234) /
1836 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
1838 self.assertTrue(find_gbp_endpoint(self,
1839 vx_tun_l2_1.sw_if_index,
1843 # Static EP replies to dynamics
1845 self.logger.info(self.vapi.cli("sh l2fib bd_id 1"))
1847 p = (Ether(src=ep.mac, dst=l['mac']) /
1848 IP(dst=l['ip'], src=ep.ip4) /
1849 UDP(sport=1234, dport=1234) /
1852 rxs = self.send_and_expect(self.pg0, p * 17, self.pg2)
1855 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
1856 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
1857 self.assertEqual(rx[UDP].dport, 48879)
1858 # the UDP source port is a random value for hashing
1859 self.assertEqual(rx[VXLAN].gpid, 112)
1860 self.assertEqual(rx[VXLAN].vni, 99)
1861 self.assertTrue(rx[VXLAN].flags.G)
1862 self.assertTrue(rx[VXLAN].flags.Instance)
1863 self.assertTrue(rx[VXLAN].gpflags.A)
1864 self.assertFalse(rx[VXLAN].gpflags.D)
1867 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1871 # repeat in the other EPG
1872 # there's no contract between 220 and 330, but the A-bit is set
1873 # so the packet is cleared for delivery
1876 # a packet with an sclass from a known EPG
1877 p = (Ether(src=self.pg2.remote_mac,
1878 dst=self.pg2.local_mac) /
1879 IP(src=self.pg2.remote_hosts[1].ip4,
1880 dst=self.pg2.local_ip4) /
1881 UDP(sport=1234, dport=48879) /
1882 VXLAN(vni=99, gpid=113, flags=0x88, gpflags='A') /
1883 Ether(src=l['mac'], dst=ep.mac) /
1884 IP(src=l['ip'], dst=ep.ip4) /
1885 UDP(sport=1234, dport=1234) /
1888 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
1890 self.assertTrue(find_gbp_endpoint(self,
1891 vx_tun_l2_1.sw_if_index,
1895 # static EP cannot reach the learnt EPs since there is no contract
1896 # only test 1 EP as the others could timeout
1898 p = (Ether(src=ep.mac, dst=l['mac']) /
1899 IP(dst=learnt[0]['ip'], src=ep.ip4) /
1900 UDP(sport=1234, dport=1234) /
1903 self.send_and_assert_no_replies(self.pg0, [p])
1906 # refresh the entries after the check for no replies above
1909 # a packet with an sclass from a known EPG
1910 p = (Ether(src=self.pg2.remote_mac,
1911 dst=self.pg2.local_mac) /
1912 IP(src=self.pg2.remote_hosts[1].ip4,
1913 dst=self.pg2.local_ip4) /
1914 UDP(sport=1234, dport=48879) /
1915 VXLAN(vni=99, gpid=113, flags=0x88, gpflags='A') /
1916 Ether(src=l['mac'], dst=ep.mac) /
1917 IP(src=l['ip'], dst=ep.ip4) /
1918 UDP(sport=1234, dport=1234) /
1921 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
1923 self.assertTrue(find_gbp_endpoint(self,
1924 vx_tun_l2_1.sw_if_index,
1928 # Add the contract so they can talk
1930 rule = AclRule(is_permit=1, proto=17)
1931 rule2 = AclRule(src_prefix=IPv6Network((0, 0)),
1932 dst_prefix=IPv6Network((0, 0)), is_permit=1, proto=17)
1933 acl = VppAcl(self, rules=[rule, rule2])
1934 acl.add_vpp_config()
1936 c1 = VppGbpContract(
1937 self, 401, epg_220.sclass, epg_330.sclass, acl.acl_index,
1938 [VppGbpContractRule(
1939 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1940 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1943 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1944 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1946 [ETH_P_IP, ETH_P_IPV6])
1950 p = (Ether(src=ep.mac, dst=l['mac']) /
1951 IP(dst=l['ip'], src=ep.ip4) /
1952 UDP(sport=1234, dport=1234) /
1955 self.send_and_expect(self.pg0, [p], self.pg2)
1958 # send UU packets from the local EP
1960 self.logger.info(self.vapi.cli("sh gbp bridge"))
1961 self.logger.info(self.vapi.cli("sh bridge-domain 1 detail"))
1962 p_uu = (Ether(src=ep.mac, dst="00:11:11:11:11:11") /
1963 IP(dst="10.0.0.133", src=ep.ip4) /
1964 UDP(sport=1234, dport=1234) /
1966 rxs = self.send_and_expect(ep.itf, [p_uu], gbd1.uu_fwd)
1968 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1970 p_bm = (Ether(src=ep.mac, dst="ff:ff:ff:ff:ff:ff") /
1971 IP(dst="10.0.0.133", src=ep.ip4) /
1972 UDP(sport=1234, dport=1234) /
1974 rxs = self.send_and_expect_only(ep.itf, [p_bm], tun_bm.mcast_itf)
1977 self.assertEqual(rx[IP].src, self.pg4.local_ip4)
1978 self.assertEqual(rx[IP].dst, "239.1.1.1")
1979 self.assertEqual(rx[UDP].dport, 48879)
1980 # the UDP source port is a random value for hashing
1981 self.assertEqual(rx[VXLAN].gpid, 112)
1982 self.assertEqual(rx[VXLAN].vni, 88)
1983 self.assertTrue(rx[VXLAN].flags.G)
1984 self.assertTrue(rx[VXLAN].flags.Instance)
1985 self.assertFalse(rx[VXLAN].gpflags.A)
1986 self.assertFalse(rx[VXLAN].gpflags.D)
1988 rule = AclRule(is_permit=1, proto=17)
1989 rule2 = AclRule(src_prefix=IPv6Network((0, 0)),
1990 dst_prefix=IPv6Network((0, 0)), is_permit=1, proto=17)
1991 acl = VppAcl(self, rules=[rule, rule2])
1992 acl.add_vpp_config()
1994 c2 = VppGbpContract(
1995 self, 401, epg_330.sclass, epg_220.sclass, acl.acl_index,
1996 [VppGbpContractRule(
1997 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1998 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2001 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2002 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2004 [ETH_P_IP, ETH_P_IPV6])
2008 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
2011 # Check v6 Endpoints learning
2014 # a packet with an sclass from a known EPG
2015 p = (Ether(src=self.pg2.remote_mac,
2016 dst=self.pg2.local_mac) /
2017 IP(src=self.pg2.remote_hosts[1].ip4,
2018 dst=self.pg2.local_ip4) /
2019 UDP(sport=1234, dport=48879) /
2020 VXLAN(vni=99, gpid=113, flags=0x88) /
2021 Ether(src=l['mac'], dst=ep.mac) /
2022 IPv6(src=l['ip6'], dst=ep.ip6) /
2023 UDP(sport=1234, dport=1234) /
2026 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
2027 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
2029 self.assertTrue(find_gbp_endpoint(
2031 vx_tun_l2_1.sw_if_index,
2033 tep=[self.pg2.local_ip4,
2034 self.pg2.remote_hosts[1].ip4]))
2036 self.logger.info(self.vapi.cli("sh int"))
2037 self.logger.info(self.vapi.cli("sh vxlan-gbp tunnel"))
2038 self.logger.info(self.vapi.cli("sh gbp vxlan"))
2039 self.logger.info(self.vapi.cli("sh gbp endpoint"))
2040 self.logger.info(self.vapi.cli("sh gbp interface"))
2043 # EP moves to a different TEP
2046 # a packet with an sclass from a known EPG
2047 p = (Ether(src=self.pg2.remote_mac,
2048 dst=self.pg2.local_mac) /
2049 IP(src=self.pg2.remote_hosts[2].ip4,
2050 dst=self.pg2.local_ip4) /
2051 UDP(sport=1234, dport=48879) /
2052 VXLAN(vni=99, gpid=113, flags=0x88) /
2053 Ether(src=l['mac'], dst=ep.mac) /
2054 IPv6(src=l['ip6'], dst=ep.ip6) /
2055 UDP(sport=1234, dport=1234) /
2058 rx = self.send_and_expect(self.pg2, p * 1, self.pg0)
2059 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
2061 self.assertTrue(find_gbp_endpoint(
2063 vx_tun_l2_1.sw_if_index,
2066 tep=[self.pg2.local_ip4,
2067 self.pg2.remote_hosts[2].ip4]))
2070 # v6 remote EP reachability
2073 p = (Ether(src=ep.mac, dst=l['mac']) /
2074 IPv6(dst=l['ip6'], src=ep.ip6) /
2075 UDP(sport=1234, dport=1234) /
2078 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
2081 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2082 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[2].ip4)
2083 self.assertEqual(rx[UDP].dport, 48879)
2084 # the UDP source port is a random value for hashing
2085 self.assertEqual(rx[VXLAN].gpid, 112)
2086 self.assertEqual(rx[VXLAN].vni, 99)
2087 self.assertTrue(rx[VXLAN].flags.G)
2088 self.assertTrue(rx[VXLAN].flags.Instance)
2089 self.assertTrue(rx[VXLAN].gpflags.A)
2090 self.assertFalse(rx[VXLAN].gpflags.D)
2091 self.assertEqual(rx[IPv6].dst, l['ip6'])
2097 # a packet with an sclass from a known EPG
2098 p = (Ether(src=self.pg2.remote_mac,
2099 dst=self.pg2.local_mac) /
2100 IP(src=self.pg2.remote_hosts[2].ip4,
2101 dst=self.pg2.local_ip4) /
2102 UDP(sport=1234, dport=48879) /
2103 VXLAN(vni=99, gpid=112, flags=0x88) /
2104 Ether(src=l['mac'], dst=ep.mac) /
2105 IPv6(src=l['ip6'], dst=ep.ip6) /
2106 UDP(sport=1234, dport=1234) /
2109 rx = self.send_and_expect(self.pg2, p * 1, self.pg0)
2110 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
2112 self.assertTrue(find_gbp_endpoint(
2114 vx_tun_l2_1.sw_if_index,
2117 tep=[self.pg2.local_ip4,
2118 self.pg2.remote_hosts[2].ip4]))
2121 # check reachability and contract intra-epg
2123 allow_intra_class = self.statistics.get_err_counter(
2124 '/err/gbp-policy-mac/allow-intra-sclass')
2127 p = (Ether(src=ep.mac, dst=l['mac']) /
2128 IPv6(dst=l['ip6'], src=ep.ip6) /
2129 UDP(sport=1234, dport=1234) /
2132 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
2135 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2136 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[2].ip4)
2137 self.assertEqual(rx[UDP].dport, 48879)
2138 self.assertEqual(rx[VXLAN].gpid, 112)
2139 self.assertEqual(rx[VXLAN].vni, 99)
2140 self.assertTrue(rx[VXLAN].flags.G)
2141 self.assertTrue(rx[VXLAN].flags.Instance)
2142 self.assertTrue(rx[VXLAN].gpflags.A)
2143 self.assertFalse(rx[VXLAN].gpflags.D)
2144 self.assertEqual(rx[IPv6].dst, l['ip6'])
2146 allow_intra_class += NUM_PKTS
2148 self.assert_error_counter_equal(
2149 '/err/gbp-policy-mac/allow-intra-sclass',
2156 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
2158 self.pg2.unconfig_ip4()
2159 self.pg3.unconfig_ip4()
2160 self.pg4.unconfig_ip4()
2162 def test_gbp_contract(self):
2163 """ GBP Contracts """
2168 gt4 = VppIpTable(self, 0)
2169 gt4.add_vpp_config()
2170 gt6 = VppIpTable(self, 0, is_ip6=True)
2171 gt6.add_vpp_config()
2173 rd0 = VppGbpRouteDomain(self, 0, 400, gt4, gt6, None, None)
2175 rd0.add_vpp_config()
2180 bd1 = VppBridgeDomain(self, 1, arp_term=0)
2181 bd2 = VppBridgeDomain(self, 2, arp_term=0)
2183 bd1.add_vpp_config()
2184 bd2.add_vpp_config()
2186 gbd1 = VppGbpBridgeDomain(self, bd1, rd0, self.loop0)
2187 gbd2 = VppGbpBridgeDomain(self, bd2, rd0, self.loop1)
2189 gbd1.add_vpp_config()
2190 gbd2.add_vpp_config()
2193 # 3 EPGs, 2 of which share a BD.
2195 epgs = [VppGbpEndpointGroup(self, 220, 1220, rd0, gbd1,
2197 "10.0.0.128", "2001:10::128"),
2198 VppGbpEndpointGroup(self, 221, 1221, rd0, gbd1,
2200 "10.0.1.128", "2001:10:1::128"),
2201 VppGbpEndpointGroup(self, 222, 1222, rd0, gbd2,
2203 "10.0.2.128", "2001:10:2::128")]
2205 # 4 end-points, 2 in the same subnet, 3 in the same BD
2207 eps = [VppGbpEndpoint(self, self.pg0,
2209 "10.0.0.1", "11.0.0.1",
2210 "2001:10::1", "3001::1"),
2211 VppGbpEndpoint(self, self.pg1,
2213 "10.0.0.2", "11.0.0.2",
2214 "2001:10::2", "3001::2"),
2215 VppGbpEndpoint(self, self.pg2,
2217 "10.0.1.1", "11.0.0.3",
2218 "2001:10:1::1", "3001::3"),
2219 VppGbpEndpoint(self, self.pg3,
2221 "10.0.2.1", "11.0.0.4",
2222 "2001:10:2::1", "3001::4")]
2225 # Config related to each of the EPGs
2228 # IP config on the BVI interfaces
2230 b4 = VppIpInterfaceBind(self, epg.bvi,
2231 epg.rd.t4).add_vpp_config()
2232 b6 = VppIpInterfaceBind(self, epg.bvi,
2233 epg.rd.t6).add_vpp_config()
2234 epg.bvi.set_mac(self.router_mac)
2236 if_ip4 = VppIpInterfaceAddress(self, epg.bvi,
2238 bind=b4).add_vpp_config()
2239 if_ip6 = VppIpInterfaceAddress(self, epg.bvi,
2241 bind=b6).add_vpp_config()
2243 # add the BD ARP termination entry for BVI IP
2244 epg.bd_arp_ip4 = VppBridgeDomainArpEntry(self, epg.bd.bd,
2245 str(self.router_mac),
2247 epg.bd_arp_ip4.add_vpp_config()
2250 epg.add_vpp_config()
2258 self.logger.info(self.vapi.cli("show gbp endpoint"))
2259 self.logger.info(self.vapi.cli("show interface"))
2260 self.logger.info(self.vapi.cli("show br"))
2263 # Intra epg allowed without contract
2265 pkt_intra_epg_220_to_220 = (Ether(src=self.pg0.remote_mac,
2266 dst=self.pg1.remote_mac) /
2269 UDP(sport=1234, dport=1234) /
2272 self.send_and_expect_bridged(self.pg0,
2273 pkt_intra_epg_220_to_220 * 65,
2276 pkt_intra_epg_220_to_220 = (Ether(src=self.pg0.remote_mac,
2277 dst=self.pg1.remote_mac) /
2278 IPv6(src=eps[0].ip6,
2280 UDP(sport=1234, dport=1234) /
2283 self.send_and_expect_bridged6(self.pg0,
2284 pkt_intra_epg_220_to_220 * 65,
2288 # Inter epg denied without contract
2290 pkt_inter_epg_220_to_221 = (Ether(src=self.pg0.remote_mac,
2291 dst=self.pg2.remote_mac) /
2294 UDP(sport=1234, dport=1234) /
2297 self.send_and_assert_no_replies(self.pg0, pkt_inter_epg_220_to_221)
2300 # A uni-directional contract from EPG 220 -> 221
2302 rule = AclRule(is_permit=1, proto=17)
2303 rule2 = AclRule(src_prefix=IPv6Network((0, 0)),
2304 dst_prefix=IPv6Network((0, 0)), is_permit=1, proto=17)
2305 rule3 = AclRule(is_permit=1, proto=1)
2306 acl = VppAcl(self, rules=[rule, rule2, rule3])
2307 acl.add_vpp_config()
2309 c1 = VppGbpContract(
2310 self, 400, epgs[0].sclass, epgs[1].sclass, acl.acl_index,
2311 [VppGbpContractRule(
2312 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2313 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2316 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2317 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2320 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2321 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2323 [ETH_P_IP, ETH_P_IPV6])
2326 self.send_and_expect_bridged(eps[0].itf,
2327 pkt_inter_epg_220_to_221 * 65,
2330 pkt_inter_epg_220_to_222 = (Ether(src=self.pg0.remote_mac,
2331 dst=str(self.router_mac)) /
2334 UDP(sport=1234, dport=1234) /
2336 self.send_and_assert_no_replies(eps[0].itf,
2337 pkt_inter_epg_220_to_222 * 65)
2340 # ping router IP in different BD
2342 pkt_router_ping_220_to_221 = (Ether(src=self.pg0.remote_mac,
2343 dst=str(self.router_mac)) /
2345 dst=epgs[1].bvi_ip4) /
2346 ICMP(type='echo-request'))
2348 self.send_and_expect(self.pg0, [pkt_router_ping_220_to_221], self.pg0)
2350 pkt_router_ping_220_to_221 = (Ether(src=self.pg0.remote_mac,
2351 dst=str(self.router_mac)) /
2352 IPv6(src=eps[0].ip6,
2353 dst=epgs[1].bvi_ip6) /
2354 ICMPv6EchoRequest())
2356 self.send_and_expect(self.pg0, [pkt_router_ping_220_to_221], self.pg0)
2359 # contract for the return direction
2361 c2 = VppGbpContract(
2362 self, 400, epgs[1].sclass, epgs[0].sclass, acl.acl_index,
2363 [VppGbpContractRule(
2364 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2365 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2368 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2369 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2371 [ETH_P_IP, ETH_P_IPV6])
2374 self.send_and_expect_bridged(eps[0].itf,
2375 pkt_inter_epg_220_to_221 * 65,
2377 pkt_inter_epg_221_to_220 = (Ether(src=self.pg2.remote_mac,
2378 dst=self.pg0.remote_mac) /
2381 UDP(sport=1234, dport=1234) /
2383 self.send_and_expect_bridged(eps[2].itf,
2384 pkt_inter_epg_221_to_220 * 65,
2386 pkt_inter_epg_221_to_220 = (Ether(src=self.pg2.remote_mac,
2387 dst=str(self.router_mac)) /
2390 UDP(sport=1234, dport=1234) /
2392 self.send_and_expect_routed(eps[2].itf,
2393 pkt_inter_epg_221_to_220 * 65,
2395 str(self.router_mac))
2396 pkt_inter_epg_221_to_220 = (Ether(src=self.pg2.remote_mac,
2397 dst=str(self.router_mac)) /
2398 IPv6(src=eps[2].ip6,
2400 UDP(sport=1234, dport=1234) /
2402 self.send_and_expect_routed6(eps[2].itf,
2403 pkt_inter_epg_221_to_220 * 65,
2405 str(self.router_mac))
2408 # contract between 220 and 222 uni-direction
2410 c3 = VppGbpContract(
2411 self, 400, epgs[0].sclass, epgs[2].sclass, acl.acl_index,
2412 [VppGbpContractRule(
2413 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2414 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2417 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2418 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2420 [ETH_P_IP, ETH_P_IPV6])
2423 self.send_and_expect(eps[0].itf,
2424 pkt_inter_epg_220_to_222 * 65,
2427 c3.remove_vpp_config()
2428 c1.remove_vpp_config()
2429 c2.remove_vpp_config()
2430 acl.remove_vpp_config()
2432 def test_gbp_bd_drop_flags(self):
2433 """ GBP BD drop flags """
2438 gt4 = VppIpTable(self, 1)
2439 gt4.add_vpp_config()
2440 gt6 = VppIpTable(self, 1, is_ip6=True)
2441 gt6.add_vpp_config()
2443 rd1 = VppGbpRouteDomain(self, 1, 401, gt4, gt6)
2444 rd1.add_vpp_config()
2447 # a GBP bridge domain with a BVI only
2449 bd1 = VppBridgeDomain(self, 1)
2450 bd1.add_vpp_config()
2452 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0,
2454 uu_drop=True, bm_drop=True)
2455 gbd1.add_vpp_config()
2457 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2458 self.logger.info(self.vapi.cli("sh gbp bridge"))
2460 # ... and has a /32 applied
2461 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi,
2462 "10.0.0.128", 32).add_vpp_config()
2465 # The Endpoint-group
2467 epg_220 = VppGbpEndpointGroup(self, 220, 112, rd1, gbd1,
2471 VppGbpEndpointRetention(3))
2472 epg_220.add_vpp_config()
2474 ep = VppGbpEndpoint(self, self.pg0,
2476 "10.0.0.127", "11.0.0.127",
2477 "2001:10::1", "3001::1")
2481 # send UU/BM packet from the local EP with UU drop and BM drop enabled
2484 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2485 self.logger.info(self.vapi.cli("sh gbp bridge"))
2486 p_uu = (Ether(src=ep.mac, dst="00:11:11:11:11:11") /
2487 IP(dst="10.0.0.133", src=ep.ip4) /
2488 UDP(sport=1234, dport=1234) /
2490 self.send_and_assert_no_replies(ep.itf, [p_uu])
2492 p_bm = (Ether(src=ep.mac, dst="ff:ff:ff:ff:ff:ff") /
2493 IP(dst="10.0.0.133", src=ep.ip4) /
2494 UDP(sport=1234, dport=1234) /
2496 self.send_and_assert_no_replies(ep.itf, [p_bm])
2498 self.pg3.unconfig_ip4()
2500 self.logger.info(self.vapi.cli("sh int"))
2502 def test_gbp_bd_arp_flags(self):
2503 """ GBP BD arp flags """
2508 gt4 = VppIpTable(self, 1)
2509 gt4.add_vpp_config()
2510 gt6 = VppIpTable(self, 1, is_ip6=True)
2511 gt6.add_vpp_config()
2513 rd1 = VppGbpRouteDomain(self, 1, 401, gt4, gt6)
2514 rd1.add_vpp_config()
2517 # Pg4 hosts the IP6 UU-flood VXLAN tunnel
2519 self.pg4.config_ip4()
2520 self.pg4.resolve_arp()
2523 # Add a mcast destination VXLAN-GBP tunnel for B&M traffic
2525 tun_uu = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
2528 tun_uu.add_vpp_config()
2531 # a GBP bridge domain with a BVI and a UU-flood interface
2533 bd1 = VppBridgeDomain(self, 1)
2534 bd1.add_vpp_config()
2536 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0,
2539 gbd1.add_vpp_config()
2541 # ... and has a /32 applied
2542 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi,
2543 "10.0.0.128", 32).add_vpp_config()
2546 # The Endpoint-group
2548 epg_220 = VppGbpEndpointGroup(self, 220, 112, rd1, gbd1,
2552 VppGbpEndpointRetention(2))
2553 epg_220.add_vpp_config()
2555 ep = VppGbpEndpoint(self, self.pg0,
2557 "10.0.0.127", "11.0.0.127",
2558 "2001:10::1", "3001::1")
2562 # send ARP packet from the local EP expect it on the uu interface
2564 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2565 self.logger.info(self.vapi.cli("sh gbp bridge"))
2566 p_arp = (Ether(src=ep.mac, dst="ff:ff:ff:ff:ff:ff") /
2568 psrc=ep.ip4, pdst="10.0.0.99",
2570 hwdst="ff:ff:ff:ff:ff:ff"))
2571 self.send_and_expect(ep.itf, [p_arp], self.pg4)
2573 self.pg4.unconfig_ip4()
2575 def test_gbp_learn_vlan_l2(self):
2576 """ GBP L2 Endpoint w/ VLANs"""
2578 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
2579 learnt = [{'mac': '00:00:11:11:11:01',
2581 'ip6': '2001:10::2'},
2582 {'mac': '00:00:11:11:11:02',
2584 'ip6': '2001:10::3'}]
2589 gt4 = VppIpTable(self, 1)
2590 gt4.add_vpp_config()
2591 gt6 = VppIpTable(self, 1, is_ip6=True)
2592 gt6.add_vpp_config()
2594 rd1 = VppGbpRouteDomain(self, 1, 401, gt4, gt6)
2595 rd1.add_vpp_config()
2598 # Pg2 hosts the vxlan tunnel, hosts on pg2 to act as TEPs
2600 self.pg2.config_ip4()
2601 self.pg2.resolve_arp()
2602 self.pg2.generate_remote_hosts(4)
2603 self.pg2.configure_ipv4_neighbors()
2604 self.pg3.config_ip4()
2605 self.pg3.resolve_arp()
2608 # The EP will be on a vlan sub-interface
2610 vlan_11 = VppDot1QSubint(self, self.pg0, 11)
2612 self.vapi.l2_interface_vlan_tag_rewrite(
2613 sw_if_index=vlan_11.sw_if_index, vtr_op=L2_VTR_OP.L2_POP_1,
2616 bd_uu_fwd = VppVxlanGbpTunnel(self, self.pg3.local_ip4,
2617 self.pg3.remote_ip4, 116)
2618 bd_uu_fwd.add_vpp_config()
2621 # a GBP bridge domain with a BVI and a UU-flood interface
2622 # The BD is marked as do not learn, so no endpoints are ever
2623 # learnt in this BD.
2625 bd1 = VppBridgeDomain(self, 1)
2626 bd1.add_vpp_config()
2627 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0, bd_uu_fwd,
2629 gbd1.add_vpp_config()
2631 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2632 self.logger.info(self.vapi.cli("sh gbp bridge"))
2634 # ... and has a /32 applied
2635 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi,
2636 "10.0.0.128", 32).add_vpp_config()
2639 # The Endpoint-group in which we are learning endpoints
2641 epg_220 = VppGbpEndpointGroup(self, 220, 441, rd1, gbd1,
2645 VppGbpEndpointRetention(4))
2646 epg_220.add_vpp_config()
2649 # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
2652 vx_tun_l2_1 = VppGbpVxlanTunnel(
2653 self, 99, bd1.bd_id,
2654 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L2,
2656 vx_tun_l2_1.add_vpp_config()
2659 # A static endpoint that the learnt endpoints are trying to
2662 ep = VppGbpEndpoint(self, vlan_11,
2664 "10.0.0.127", "11.0.0.127",
2665 "2001:10::1", "3001::1")
2668 self.assertTrue(find_route(self, ep.ip4, 32, table_id=1))
2671 # Send to the static EP
2673 for ii, l in enumerate(learnt):
2674 # a packet with an sclass from a known EPG
2675 # arriving on an unknown TEP
2676 p = (Ether(src=self.pg2.remote_mac,
2677 dst=self.pg2.local_mac) /
2678 IP(src=self.pg2.remote_hosts[1].ip4,
2679 dst=self.pg2.local_ip4) /
2680 UDP(sport=1234, dport=48879) /
2681 VXLAN(vni=99, gpid=441, flags=0x88) /
2682 Ether(src=l['mac'], dst=ep.mac) /
2683 IP(src=l['ip'], dst=ep.ip4) /
2684 UDP(sport=1234, dport=1234) /
2687 rxs = self.send_and_expect(self.pg2, [p], self.pg0)
2690 # packet to EP has the EP's vlan tag
2693 self.assertEqual(rx[Dot1Q].vlan, 11)
2696 # the EP is not learnt since the BD setting prevents it
2699 self.assertFalse(find_gbp_endpoint(self,
2700 vx_tun_l2_1.sw_if_index,
2702 self.assertEqual(INDEX_INVALID,
2703 find_vxlan_gbp_tunnel(
2706 self.pg2.remote_hosts[1].ip4,
2709 self.assertEqual(len(self.vapi.gbp_endpoint_dump()), 1)
2713 # we didn't learn the remotes so they are sent to the UU-fwd
2716 p = (Ether(src=ep.mac, dst=l['mac']) /
2718 IP(dst=l['ip'], src=ep.ip4) /
2719 UDP(sport=1234, dport=1234) /
2722 rxs = self.send_and_expect(self.pg0, p * 17, self.pg3)
2725 self.assertEqual(rx[IP].src, self.pg3.local_ip4)
2726 self.assertEqual(rx[IP].dst, self.pg3.remote_ip4)
2727 self.assertEqual(rx[UDP].dport, 48879)
2728 # the UDP source port is a random value for hashing
2729 self.assertEqual(rx[VXLAN].gpid, 441)
2730 self.assertEqual(rx[VXLAN].vni, 116)
2731 self.assertTrue(rx[VXLAN].flags.G)
2732 self.assertTrue(rx[VXLAN].flags.Instance)
2733 self.assertFalse(rx[VXLAN].gpflags.A)
2734 self.assertFalse(rx[VXLAN].gpflags.D)
2736 self.pg2.unconfig_ip4()
2737 self.pg3.unconfig_ip4()
2739 def test_gbp_learn_l3(self):
2740 """ GBP L3 Endpoint Learning """
2742 self.vapi.cli("set logging class gbp level debug")
2744 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
2745 routed_dst_mac = "00:0c:0c:0c:0c:0c"
2746 routed_src_mac = "00:22:bd:f8:19:ff"
2748 learnt = [{'mac': '00:00:11:11:11:02',
2750 'ip6': '2001:10::2'},
2751 {'mac': '00:00:11:11:11:03',
2753 'ip6': '2001:10::3'}]
2758 t4 = VppIpTable(self, 1)
2760 t6 = VppIpTable(self, 1, True)
2763 tun_ip4_uu = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
2764 self.pg4.remote_ip4, 114)
2765 tun_ip6_uu = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
2766 self.pg4.remote_ip4, 116)
2767 tun_ip4_uu.add_vpp_config()
2768 tun_ip6_uu.add_vpp_config()
2770 rd1 = VppGbpRouteDomain(self, 2, 401, t4, t6, tun_ip4_uu, tun_ip6_uu)
2771 rd1.add_vpp_config()
2773 self.loop0.set_mac(self.router_mac)
2776 # Bind the BVI to the RD
2778 b4 = VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
2779 b6 = VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
2782 # Pg2 hosts the vxlan tunnel
2783 # hosts on pg2 to act as TEPs
2787 self.pg2.config_ip4()
2788 self.pg2.resolve_arp()
2789 self.pg2.generate_remote_hosts(4)
2790 self.pg2.configure_ipv4_neighbors()
2791 self.pg3.config_ip4()
2792 self.pg3.resolve_arp()
2793 self.pg4.config_ip4()
2794 self.pg4.resolve_arp()
2797 # a GBP bridge domain with a BVI and a UU-flood interface
2799 bd1 = VppBridgeDomain(self, 1)
2800 bd1.add_vpp_config()
2801 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0, self.pg3)
2802 gbd1.add_vpp_config()
2804 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2805 self.logger.info(self.vapi.cli("sh gbp bridge"))
2806 self.logger.info(self.vapi.cli("sh gbp route"))
2808 # ... and has a /32 and /128 applied
2809 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi,
2811 bind=b4).add_vpp_config()
2812 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi,
2813 "2001:10::128", 128,
2814 bind=b6).add_vpp_config()
2817 # The Endpoint-group in which we are learning endpoints
2819 epg_220 = VppGbpEndpointGroup(self, 220, 441, rd1, gbd1,
2823 VppGbpEndpointRetention(4))
2824 epg_220.add_vpp_config()
2827 # The VXLAN GBP tunnel is in L3 mode with learning enabled
2829 vx_tun_l3 = VppGbpVxlanTunnel(
2830 self, 101, rd1.rd_id,
2831 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
2833 vx_tun_l3.add_vpp_config()
2836 # A static endpoint that the learnt endpoints are trying to
2839 ep = VppGbpEndpoint(self, self.pg0,
2841 "10.0.0.127", "11.0.0.127",
2842 "2001:10::1", "3001::1")
2846 # learn some remote IPv4 EPs
2848 for ii, l in enumerate(learnt):
2849 # a packet with an sclass from a known EPG
2850 # arriving on an unknown TEP
2851 p = (Ether(src=self.pg2.remote_mac,
2852 dst=self.pg2.local_mac) /
2853 IP(src=self.pg2.remote_hosts[1].ip4,
2854 dst=self.pg2.local_ip4) /
2855 UDP(sport=1234, dport=48879) /
2856 VXLAN(vni=101, gpid=441, flags=0x88) /
2857 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2858 IP(src=l['ip'], dst=ep.ip4) /
2859 UDP(sport=1234, dport=1234) /
2862 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2865 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2868 self.pg2.remote_hosts[1].ip4,
2870 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2872 # endpoint learnt via the parent GBP-vxlan interface
2873 self.assertTrue(find_gbp_endpoint(self,
2874 vx_tun_l3._sw_if_index,
2878 # Static IPv4 EP replies to learnt
2881 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2882 IP(dst=l['ip'], src=ep.ip4) /
2883 UDP(sport=1234, dport=1234) /
2886 rxs = self.send_and_expect(self.pg0, p * 1, self.pg2)
2889 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2890 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2891 self.assertEqual(rx[UDP].dport, 48879)
2892 # the UDP source port is a random value for hashing
2893 self.assertEqual(rx[VXLAN].gpid, 441)
2894 self.assertEqual(rx[VXLAN].vni, 101)
2895 self.assertTrue(rx[VXLAN].flags.G)
2896 self.assertTrue(rx[VXLAN].flags.Instance)
2897 self.assertTrue(rx[VXLAN].gpflags.A)
2898 self.assertFalse(rx[VXLAN].gpflags.D)
2900 inner = rx[VXLAN].payload
2902 self.assertEqual(inner[Ether].src, routed_src_mac)
2903 self.assertEqual(inner[Ether].dst, routed_dst_mac)
2904 self.assertEqual(inner[IP].src, ep.ip4)
2905 self.assertEqual(inner[IP].dst, l['ip'])
2908 self.assertFalse(find_gbp_endpoint(self,
2913 # learn some remote IPv6 EPs
2915 for ii, l in enumerate(learnt):
2916 # a packet with an sclass from a known EPG
2917 # arriving on an unknown TEP
2918 p = (Ether(src=self.pg2.remote_mac,
2919 dst=self.pg2.local_mac) /
2920 IP(src=self.pg2.remote_hosts[1].ip4,
2921 dst=self.pg2.local_ip4) /
2922 UDP(sport=1234, dport=48879) /
2923 VXLAN(vni=101, gpid=441, flags=0x88) /
2924 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2925 IPv6(src=l['ip6'], dst=ep.ip6) /
2926 UDP(sport=1234, dport=1234) /
2929 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2932 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2935 self.pg2.remote_hosts[1].ip4,
2937 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2939 self.logger.info(self.vapi.cli("show gbp bridge"))
2940 self.logger.info(self.vapi.cli("show vxlan-gbp tunnel"))
2941 self.logger.info(self.vapi.cli("show gbp vxlan"))
2942 self.logger.info(self.vapi.cli("show int addr"))
2944 # endpoint learnt via the TEP
2945 self.assertTrue(find_gbp_endpoint(self, ip=l['ip6']))
2947 self.logger.info(self.vapi.cli("show gbp endpoint"))
2948 self.logger.info(self.vapi.cli("show ip fib index 1 %s" % l['ip']))
2951 # Static EP replies to learnt
2954 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2955 IPv6(dst=l['ip6'], src=ep.ip6) /
2956 UDP(sport=1234, dport=1234) /
2959 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
2962 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2963 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2964 self.assertEqual(rx[UDP].dport, 48879)
2965 # the UDP source port is a random value for hashing
2966 self.assertEqual(rx[VXLAN].gpid, 441)
2967 self.assertEqual(rx[VXLAN].vni, 101)
2968 self.assertTrue(rx[VXLAN].flags.G)
2969 self.assertTrue(rx[VXLAN].flags.Instance)
2970 self.assertTrue(rx[VXLAN].gpflags.A)
2971 self.assertFalse(rx[VXLAN].gpflags.D)
2973 inner = rx[VXLAN].payload
2975 self.assertEqual(inner[Ether].src, routed_src_mac)
2976 self.assertEqual(inner[Ether].dst, routed_dst_mac)
2977 self.assertEqual(inner[IPv6].src, ep.ip6)
2978 self.assertEqual(inner[IPv6].dst, l['ip6'])
2980 self.logger.info(self.vapi.cli("sh gbp endpoint"))
2982 self.wait_for_ep_timeout(ip=l['ip'])
2985 # Static sends to unknown EP with no route
2987 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2988 IP(dst="10.0.0.99", src=ep.ip4) /
2989 UDP(sport=1234, dport=1234) /
2992 self.send_and_assert_no_replies(self.pg0, [p])
2995 # Add a route to static EP's v4 and v6 subnet
2997 se_10_24 = VppGbpSubnet(
2998 self, rd1, "10.0.0.0", 24,
2999 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT)
3000 se_10_24.add_vpp_config()
3003 # static pings router
3005 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
3006 IP(dst=epg_220.bvi_ip4, src=ep.ip4) /
3007 UDP(sport=1234, dport=1234) /
3010 self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg0)
3012 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
3013 IPv6(dst=epg_220.bvi_ip6, src=ep.ip6) /
3014 UDP(sport=1234, dport=1234) /
3017 self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg0)
3020 # packets to address in the subnet are sent on the uu-fwd
3022 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
3023 IP(dst="10.0.0.99", src=ep.ip4) /
3024 UDP(sport=1234, dport=1234) /
3027 rxs = self.send_and_expect(self.pg0, [p], self.pg4)
3029 self.assertEqual(rx[IP].src, self.pg4.local_ip4)
3030 self.assertEqual(rx[IP].dst, self.pg4.remote_ip4)
3031 self.assertEqual(rx[UDP].dport, 48879)
3032 # the UDP source port is a random value for hashing
3033 self.assertEqual(rx[VXLAN].gpid, 441)
3034 self.assertEqual(rx[VXLAN].vni, 114)
3035 self.assertTrue(rx[VXLAN].flags.G)
3036 self.assertTrue(rx[VXLAN].flags.Instance)
3037 # policy is not applied to packets sent to the uu-fwd interfaces
3038 self.assertFalse(rx[VXLAN].gpflags.A)
3039 self.assertFalse(rx[VXLAN].gpflags.D)
3042 # learn some remote IPv4 EPs
3044 for ii, l in enumerate(learnt):
3045 # a packet with an sclass from a known EPG
3046 # arriving on an unknown TEP
3047 p = (Ether(src=self.pg2.remote_mac,
3048 dst=self.pg2.local_mac) /
3049 IP(src=self.pg2.remote_hosts[2].ip4,
3050 dst=self.pg2.local_ip4) /
3051 UDP(sport=1234, dport=48879) /
3052 VXLAN(vni=101, gpid=441, flags=0x88) /
3053 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
3054 IP(src=l['ip'], dst=ep.ip4) /
3055 UDP(sport=1234, dport=1234) /
3058 rx = self.send_and_expect(self.pg2, [p], self.pg0)
3061 tep1_sw_if_index = find_vxlan_gbp_tunnel(
3064 self.pg2.remote_hosts[2].ip4,
3066 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
3068 # endpoint learnt via the parent GBP-vxlan interface
3069 self.assertTrue(find_gbp_endpoint(self,
3070 vx_tun_l3._sw_if_index,
3074 # Add a remote endpoint from the API
3076 rep_88 = VppGbpEndpoint(self, vx_tun_l3,
3078 "10.0.0.88", "11.0.0.88",
3079 "2001:10::88", "3001::88",
3080 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
3082 self.pg2.remote_hosts[2].ip4,
3084 rep_88.add_vpp_config()
3087 # Add a remote endpoint from the API that matches an existing one
3088 # this is a lower priority, hence the packet is sent to the DP leanrt
3091 rep_2 = VppGbpEndpoint(self, vx_tun_l3,
3093 learnt[0]['ip'], "11.0.0.101",
3094 learnt[0]['ip6'], "3001::101",
3095 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
3097 self.pg2.remote_hosts[1].ip4,
3099 rep_2.add_vpp_config()
3102 # Add a route to the learned EP's v4 subnet
3103 # packets should be send on the v4/v6 uu=fwd interface resp.
3105 se_10_1_24 = VppGbpSubnet(
3106 self, rd1, "10.0.1.0", 24,
3107 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT)
3108 se_10_1_24.add_vpp_config()
3110 self.logger.info(self.vapi.cli("show gbp endpoint"))
3112 ips = ["10.0.0.88", learnt[0]['ip']]
3114 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
3115 IP(dst=ip, src=ep.ip4) /
3116 UDP(sport=1234, dport=1234) /
3119 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
3122 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
3123 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[2].ip4)
3124 self.assertEqual(rx[UDP].dport, 48879)
3125 # the UDP source port is a random value for hashing
3126 self.assertEqual(rx[VXLAN].gpid, 441)
3127 self.assertEqual(rx[VXLAN].vni, 101)
3128 self.assertTrue(rx[VXLAN].flags.G)
3129 self.assertTrue(rx[VXLAN].flags.Instance)
3130 self.assertTrue(rx[VXLAN].gpflags.A)
3131 self.assertFalse(rx[VXLAN].gpflags.D)
3133 inner = rx[VXLAN].payload
3135 self.assertEqual(inner[Ether].src, routed_src_mac)
3136 self.assertEqual(inner[Ether].dst, routed_dst_mac)
3137 self.assertEqual(inner[IP].src, ep.ip4)
3138 self.assertEqual(inner[IP].dst, ip)
3141 # remove the API remote EPs, only API sourced is gone, the DP
3142 # learnt one remains
3144 rep_88.remove_vpp_config()
3145 rep_2.remove_vpp_config()
3147 self.assertTrue(find_gbp_endpoint(self, ip=rep_2.ip4))
3149 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
3150 IP(src=ep.ip4, dst=rep_2.ip4) /
3151 UDP(sport=1234, dport=1234) /
3153 rxs = self.send_and_expect(self.pg0, [p], self.pg2)
3155 self.assertFalse(find_gbp_endpoint(self, ip=rep_88.ip4))
3157 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
3158 IP(src=ep.ip4, dst=rep_88.ip4) /
3159 UDP(sport=1234, dport=1234) /
3161 rxs = self.send_and_expect(self.pg0, [p], self.pg4)
3164 # to appease the testcase we cannot have the registered EP still
3165 # present (because it's DP learnt) when the TC ends so wait until
3168 self.wait_for_ep_timeout(ip=rep_88.ip4)
3169 self.wait_for_ep_timeout(ip=rep_2.ip4)
3172 # Same as above, learn a remote EP via CP and DP
3173 # this time remove the DP one first. expect the CP data to remain
3175 rep_3 = VppGbpEndpoint(self, vx_tun_l3,
3177 "10.0.1.4", "11.0.0.103",
3178 "2001::10:3", "3001::103",
3179 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
3181 self.pg2.remote_hosts[1].ip4,
3183 rep_3.add_vpp_config()
3185 p = (Ether(src=self.pg2.remote_mac,
3186 dst=self.pg2.local_mac) /
3187 IP(src=self.pg2.remote_hosts[2].ip4,
3188 dst=self.pg2.local_ip4) /
3189 UDP(sport=1234, dport=48879) /
3190 VXLAN(vni=101, gpid=441, flags=0x88) /
3191 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
3192 IP(src="10.0.1.4", dst=ep.ip4) /
3193 UDP(sport=1234, dport=1234) /
3195 rxs = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
3197 self.assertTrue(find_gbp_endpoint(self,
3198 vx_tun_l3._sw_if_index,
3200 tep=[self.pg2.local_ip4,
3201 self.pg2.remote_hosts[2].ip4]))
3203 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
3204 IP(dst="10.0.1.4", src=ep.ip4) /
3205 UDP(sport=1234, dport=1234) /
3207 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
3209 # host 2 is the DP learned TEP
3211 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
3212 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[2].ip4)
3214 self.wait_for_ep_timeout(ip=rep_3.ip4,
3215 tep=[self.pg2.local_ip4,
3216 self.pg2.remote_hosts[2].ip4])
3218 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
3220 # host 1 is the CP learned TEP
3222 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
3223 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
3226 # shutdown with learnt endpoint present
3228 p = (Ether(src=self.pg2.remote_mac,
3229 dst=self.pg2.local_mac) /
3230 IP(src=self.pg2.remote_hosts[1].ip4,
3231 dst=self.pg2.local_ip4) /
3232 UDP(sport=1234, dport=48879) /
3233 VXLAN(vni=101, gpid=441, flags=0x88) /
3234 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
3235 IP(src=learnt[1]['ip'], dst=ep.ip4) /
3236 UDP(sport=1234, dport=1234) /
3239 rx = self.send_and_expect(self.pg2, [p], self.pg0)
3241 # endpoint learnt via the parent GBP-vxlan interface
3242 self.assertTrue(find_gbp_endpoint(self,
3243 vx_tun_l3._sw_if_index,
3248 # remote endpoint becomes local
3250 self.pg2.unconfig_ip4()
3251 self.pg3.unconfig_ip4()
3252 self.pg4.unconfig_ip4()
3254 def test_gbp_redirect(self):
3255 """ GBP Endpoint Redirect """
3257 self.vapi.cli("set logging class gbp level debug")
3259 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
3260 routed_dst_mac = "00:0c:0c:0c:0c:0c"
3261 routed_src_mac = "00:22:bd:f8:19:ff"
3263 learnt = [{'mac': '00:00:11:11:11:02',
3265 'ip6': '2001:10::2'},
3266 {'mac': '00:00:11:11:11:03',
3268 'ip6': '2001:10::3'}]
3273 t4 = VppIpTable(self, 1)
3275 t6 = VppIpTable(self, 1, True)
3278 rd1 = VppGbpRouteDomain(self, 2, 402, t4, t6)
3279 rd1.add_vpp_config()
3281 self.loop0.set_mac(self.router_mac)
3284 # Bind the BVI to the RD
3286 b_ip4 = VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
3287 b_ip6 = VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
3290 # Pg7 hosts a BD's UU-fwd
3292 self.pg7.config_ip4()
3293 self.pg7.resolve_arp()
3296 # a GBP bridge domains for the EPs
3298 bd1 = VppBridgeDomain(self, 1)
3299 bd1.add_vpp_config()
3300 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0)
3301 gbd1.add_vpp_config()
3303 bd2 = VppBridgeDomain(self, 2)
3304 bd2.add_vpp_config()
3305 gbd2 = VppGbpBridgeDomain(self, bd2, rd1, self.loop1)
3306 gbd2.add_vpp_config()
3308 # ... and has a /32 and /128 applied
3309 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi,
3311 bind=b_ip4).add_vpp_config()
3312 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi,
3313 "2001:10::128", 128,
3314 bind=b_ip6).add_vpp_config()
3315 ip4_addr = VppIpInterfaceAddress(self, gbd2.bvi,
3316 "10.0.1.128", 32).add_vpp_config()
3317 ip6_addr = VppIpInterfaceAddress(self, gbd2.bvi,
3318 "2001:11::128", 128).add_vpp_config()
3321 # The Endpoint-groups in which we are learning endpoints
3323 epg_220 = VppGbpEndpointGroup(self, 220, 440, rd1, gbd1,
3327 VppGbpEndpointRetention(60))
3328 epg_220.add_vpp_config()
3329 epg_221 = VppGbpEndpointGroup(self, 221, 441, rd1, gbd2,
3333 VppGbpEndpointRetention(60))
3334 epg_221.add_vpp_config()
3335 epg_222 = VppGbpEndpointGroup(self, 222, 442, rd1, gbd1,
3339 VppGbpEndpointRetention(60))
3340 epg_222.add_vpp_config()
3343 # a GBP bridge domains for the SEPs
3345 bd_uu1 = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
3346 self.pg7.remote_ip4, 116)
3347 bd_uu1.add_vpp_config()
3348 bd_uu2 = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
3349 self.pg7.remote_ip4, 117)
3350 bd_uu2.add_vpp_config()
3352 bd3 = VppBridgeDomain(self, 3)
3353 bd3.add_vpp_config()
3354 gbd3 = VppGbpBridgeDomain(self, bd3, rd1, self.loop2,
3355 bd_uu1, learn=False)
3356 gbd3.add_vpp_config()
3357 bd4 = VppBridgeDomain(self, 4)
3358 bd4.add_vpp_config()
3359 gbd4 = VppGbpBridgeDomain(self, bd4, rd1, self.loop3,
3360 bd_uu2, learn=False)
3361 gbd4.add_vpp_config()
3364 # EPGs in which the service endpoints exist
3366 epg_320 = VppGbpEndpointGroup(self, 320, 550, rd1, gbd3,
3370 VppGbpEndpointRetention(60))
3371 epg_320.add_vpp_config()
3372 epg_321 = VppGbpEndpointGroup(self, 321, 551, rd1, gbd4,
3376 VppGbpEndpointRetention(60))
3377 epg_321.add_vpp_config()
3380 # three local endpoints
3382 ep1 = VppGbpEndpoint(self, self.pg0,
3384 "10.0.0.1", "11.0.0.1",
3385 "2001:10::1", "3001:10::1")
3386 ep1.add_vpp_config()
3387 ep2 = VppGbpEndpoint(self, self.pg1,
3389 "10.0.1.1", "11.0.1.1",
3390 "2001:11::1", "3001:11::1")
3391 ep2.add_vpp_config()
3392 ep3 = VppGbpEndpoint(self, self.pg2,
3394 "10.0.2.2", "11.0.2.2",
3395 "2001:12::1", "3001:12::1")
3396 ep3.add_vpp_config()
3401 sep1 = VppGbpEndpoint(self, self.pg3,
3403 "12.0.0.1", "13.0.0.1",
3404 "4001:10::1", "5001:10::1")
3405 sep1.add_vpp_config()
3406 sep2 = VppGbpEndpoint(self, self.pg4,
3408 "12.0.0.2", "13.0.0.2",
3409 "4001:10::2", "5001:10::2")
3410 sep2.add_vpp_config()
3411 sep3 = VppGbpEndpoint(self, self.pg5,
3413 "12.0.1.1", "13.0.1.1",
3414 "4001:11::1", "5001:11::1")
3415 sep3.add_vpp_config()
3416 # this EP is not installed immediately
3417 sep4 = VppGbpEndpoint(self, self.pg6,
3419 "12.0.1.2", "13.0.1.2",
3420 "4001:11::2", "5001:11::2")
3423 # an L2 switch packet between local EPs in different EPGs
3424 # different dest ports on each so the are LB hashed differently
3426 p4 = [(Ether(src=ep1.mac, dst=ep3.mac) /
3427 IP(src=ep1.ip4, dst=ep3.ip4) /
3428 UDP(sport=1234, dport=1234) /
3429 Raw(b'\xa5' * 100)),
3430 (Ether(src=ep3.mac, dst=ep1.mac) /
3431 IP(src=ep3.ip4, dst=ep1.ip4) /
3432 UDP(sport=1234, dport=1234) /
3433 Raw(b'\xa5' * 100))]
3434 p6 = [(Ether(src=ep1.mac, dst=ep3.mac) /
3435 IPv6(src=ep1.ip6, dst=ep3.ip6) /
3436 UDP(sport=1234, dport=1234) /
3437 Raw(b'\xa5' * 100)),
3438 (Ether(src=ep3.mac, dst=ep1.mac) /
3439 IPv6(src=ep3.ip6, dst=ep1.ip6) /
3440 UDP(sport=1234, dport=1230) /
3441 Raw(b'\xa5' * 100))]
3443 # should be dropped since no contract yet
3444 self.send_and_assert_no_replies(self.pg0, [p4[0]])
3445 self.send_and_assert_no_replies(self.pg0, [p6[0]])
3448 # Add a contract with a rule to load-balance redirect via SEP1 and SEP2
3449 # one of the next-hops is via an EP that is not known
3451 rule4 = AclRule(is_permit=1, proto=17)
3452 rule6 = AclRule(src_prefix=IPv6Network((0, 0)),
3453 dst_prefix=IPv6Network((0, 0)), is_permit=1, proto=17)
3454 acl = VppAcl(self, rules=[rule4, rule6])
3455 acl.add_vpp_config()
3458 # test the src-ip hash mode
3460 c1 = VppGbpContract(
3461 self, 402, epg_220.sclass, epg_222.sclass, acl.acl_index,
3462 [VppGbpContractRule(
3463 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3464 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3465 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3466 sep1.ip4, sep1.epg.rd),
3467 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3468 sep2.ip4, sep2.epg.rd)]),
3470 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3471 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3472 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3473 sep3.ip6, sep3.epg.rd),
3474 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3475 sep4.ip6, sep4.epg.rd)])],
3476 [ETH_P_IP, ETH_P_IPV6])
3479 c2 = VppGbpContract(
3480 self, 402, epg_222.sclass, epg_220.sclass, acl.acl_index,
3481 [VppGbpContractRule(
3482 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3483 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3484 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3485 sep1.ip4, sep1.epg.rd),
3486 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3487 sep2.ip4, sep2.epg.rd)]),
3489 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3490 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3491 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3492 sep3.ip6, sep3.epg.rd),
3493 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3494 sep4.ip6, sep4.epg.rd)])],
3495 [ETH_P_IP, ETH_P_IPV6])
3499 # send again with the contract preset, now packets arrive
3500 # at SEP1 or SEP2 depending on the hashing
3502 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3505 self.assertEqual(rx[Ether].src, routed_src_mac)
3506 self.assertEqual(rx[Ether].dst, sep1.mac)
3507 self.assertEqual(rx[IP].src, ep1.ip4)
3508 self.assertEqual(rx[IP].dst, ep3.ip4)
3510 rxs = self.send_and_expect(self.pg2, p4[1] * 17, sep2.itf)
3513 self.assertEqual(rx[Ether].src, routed_src_mac)
3514 self.assertEqual(rx[Ether].dst, sep2.mac)
3515 self.assertEqual(rx[IP].src, ep3.ip4)
3516 self.assertEqual(rx[IP].dst, ep1.ip4)
3518 rxs = self.send_and_expect(self.pg0, p6[0] * 17, self.pg7)
3521 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3522 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3523 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3524 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
3525 self.assertEqual(rx[VXLAN].vni, 117)
3526 self.assertTrue(rx[VXLAN].flags.G)
3527 self.assertTrue(rx[VXLAN].flags.Instance)
3528 # redirect policy has been applied
3529 self.assertTrue(rx[VXLAN].gpflags.A)
3530 self.assertFalse(rx[VXLAN].gpflags.D)
3532 inner = rx[VXLAN].payload
3534 self.assertEqual(inner[Ether].src, routed_src_mac)
3535 self.assertEqual(inner[Ether].dst, sep4.mac)
3536 self.assertEqual(inner[IPv6].src, ep1.ip6)
3537 self.assertEqual(inner[IPv6].dst, ep3.ip6)
3539 rxs = self.send_and_expect(self.pg2, p6[1] * 17, sep3.itf)
3542 self.assertEqual(rx[Ether].src, routed_src_mac)
3543 self.assertEqual(rx[Ether].dst, sep3.mac)
3544 self.assertEqual(rx[IPv6].src, ep3.ip6)
3545 self.assertEqual(rx[IPv6].dst, ep1.ip6)
3548 # programme the unknown EP
3550 sep4.add_vpp_config()
3552 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep4.itf)
3555 self.assertEqual(rx[Ether].src, routed_src_mac)
3556 self.assertEqual(rx[Ether].dst, sep4.mac)
3557 self.assertEqual(rx[IPv6].src, ep1.ip6)
3558 self.assertEqual(rx[IPv6].dst, ep3.ip6)
3561 # and revert back to unprogrammed
3563 sep4.remove_vpp_config()
3565 rxs = self.send_and_expect(self.pg0, p6[0] * 17, self.pg7)
3568 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3569 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3570 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3571 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
3572 self.assertEqual(rx[VXLAN].vni, 117)
3573 self.assertTrue(rx[VXLAN].flags.G)
3574 self.assertTrue(rx[VXLAN].flags.Instance)
3575 # redirect policy has been applied
3576 self.assertTrue(rx[VXLAN].gpflags.A)
3577 self.assertFalse(rx[VXLAN].gpflags.D)
3579 inner = rx[VXLAN].payload
3581 self.assertEqual(inner[Ether].src, routed_src_mac)
3582 self.assertEqual(inner[Ether].dst, sep4.mac)
3583 self.assertEqual(inner[IPv6].src, ep1.ip6)
3584 self.assertEqual(inner[IPv6].dst, ep3.ip6)
3586 c1.remove_vpp_config()
3587 c2.remove_vpp_config()
3590 # test the symmetric hash mode
3592 c1 = VppGbpContract(
3593 self, 402, epg_220.sclass, epg_222.sclass, acl.acl_index,
3594 [VppGbpContractRule(
3595 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3596 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3597 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3598 sep1.ip4, sep1.epg.rd),
3599 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3600 sep2.ip4, sep2.epg.rd)]),
3602 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3603 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3604 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3605 sep3.ip6, sep3.epg.rd),
3606 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3607 sep4.ip6, sep4.epg.rd)])],
3608 [ETH_P_IP, ETH_P_IPV6])
3611 c2 = VppGbpContract(
3612 self, 402, epg_222.sclass, epg_220.sclass, acl.acl_index,
3613 [VppGbpContractRule(
3614 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3615 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3616 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3617 sep1.ip4, sep1.epg.rd),
3618 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3619 sep2.ip4, sep2.epg.rd)]),
3621 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3622 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3623 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3624 sep3.ip6, sep3.epg.rd),
3625 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3626 sep4.ip6, sep4.epg.rd)])],
3627 [ETH_P_IP, ETH_P_IPV6])
3631 # send again with the contract preset, now packets arrive
3632 # at SEP1 for both directions
3634 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3637 self.assertEqual(rx[Ether].src, routed_src_mac)
3638 self.assertEqual(rx[Ether].dst, sep1.mac)
3639 self.assertEqual(rx[IP].src, ep1.ip4)
3640 self.assertEqual(rx[IP].dst, ep3.ip4)
3642 rxs = self.send_and_expect(self.pg2, p4[1] * 17, sep1.itf)
3645 self.assertEqual(rx[Ether].src, routed_src_mac)
3646 self.assertEqual(rx[Ether].dst, sep1.mac)
3647 self.assertEqual(rx[IP].src, ep3.ip4)
3648 self.assertEqual(rx[IP].dst, ep1.ip4)
3651 # programme the unknown EP for the L3 tests
3653 sep4.add_vpp_config()
3656 # an L3 switch packet between local EPs in different EPGs
3657 # different dest ports on each so the are LB hashed differently
3659 p4 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3660 IP(src=ep1.ip4, dst=ep2.ip4) /
3661 UDP(sport=1234, dport=1234) /
3662 Raw(b'\xa5' * 100)),
3663 (Ether(src=ep2.mac, dst=str(self.router_mac)) /
3664 IP(src=ep2.ip4, dst=ep1.ip4) /
3665 UDP(sport=1234, dport=1234) /
3666 Raw(b'\xa5' * 100))]
3667 p6 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3668 IPv6(src=ep1.ip6, dst=ep2.ip6) /
3669 UDP(sport=1234, dport=1234) /
3670 Raw(b'\xa5' * 100)),
3671 (Ether(src=ep2.mac, dst=str(self.router_mac)) /
3672 IPv6(src=ep2.ip6, dst=ep1.ip6) /
3673 UDP(sport=1234, dport=1234) /
3674 Raw(b'\xa5' * 100))]
3676 c3 = VppGbpContract(
3677 self, 402, epg_220.sclass, epg_221.sclass, acl.acl_index,
3678 [VppGbpContractRule(
3679 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3680 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3681 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3682 sep1.ip4, sep1.epg.rd),
3683 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3684 sep2.ip4, sep2.epg.rd)]),
3686 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3687 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3688 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3689 sep3.ip6, sep3.epg.rd),
3690 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3691 sep4.ip6, sep4.epg.rd)])],
3692 [ETH_P_IP, ETH_P_IPV6])
3695 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3698 self.assertEqual(rx[Ether].src, routed_src_mac)
3699 self.assertEqual(rx[Ether].dst, sep1.mac)
3700 self.assertEqual(rx[IP].src, ep1.ip4)
3701 self.assertEqual(rx[IP].dst, ep2.ip4)
3704 # learn a remote EP in EPG 221
3705 # packets coming from unknown remote EPs will be leant & redirected
3707 vx_tun_l3 = VppGbpVxlanTunnel(
3708 self, 444, rd1.rd_id,
3709 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
3711 vx_tun_l3.add_vpp_config()
3713 c4 = VppGbpContract(
3714 self, 402, epg_221.sclass, epg_220.sclass, acl.acl_index,
3715 [VppGbpContractRule(
3716 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3717 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3718 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3719 sep1.ip4, sep1.epg.rd),
3720 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3721 sep2.ip4, sep2.epg.rd)]),
3723 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3724 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3725 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3726 sep3.ip6, sep3.epg.rd),
3727 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3728 sep4.ip6, sep4.epg.rd)])],
3729 [ETH_P_IP, ETH_P_IPV6])
3732 p = (Ether(src=self.pg7.remote_mac,
3733 dst=self.pg7.local_mac) /
3734 IP(src=self.pg7.remote_ip4,
3735 dst=self.pg7.local_ip4) /
3736 UDP(sport=1234, dport=48879) /
3737 VXLAN(vni=444, gpid=441, flags=0x88) /
3738 Ether(src="00:22:22:22:22:33", dst=str(self.router_mac)) /
3739 IP(src="10.0.0.88", dst=ep1.ip4) /
3740 UDP(sport=1234, dport=1234) /
3743 # unknown remote EP to local EP redirected
3744 rxs = self.send_and_expect(self.pg7, [p], sep1.itf)
3747 self.assertEqual(rx[Ether].src, routed_src_mac)
3748 self.assertEqual(rx[Ether].dst, sep1.mac)
3749 self.assertEqual(rx[IP].src, "10.0.0.88")
3750 self.assertEqual(rx[IP].dst, ep1.ip4)
3752 # endpoint learnt via the parent GBP-vxlan interface
3753 self.assertTrue(find_gbp_endpoint(self,
3754 vx_tun_l3._sw_if_index,
3757 p = (Ether(src=self.pg7.remote_mac,
3758 dst=self.pg7.local_mac) /
3759 IP(src=self.pg7.remote_ip4,
3760 dst=self.pg7.local_ip4) /
3761 UDP(sport=1234, dport=48879) /
3762 VXLAN(vni=444, gpid=441, flags=0x88) /
3763 Ether(src="00:22:22:22:22:33", dst=str(self.router_mac)) /
3764 IPv6(src="2001:10::88", dst=ep1.ip6) /
3765 UDP(sport=1234, dport=1234) /
3768 # unknown remote EP to local EP redirected (ipv6)
3769 rxs = self.send_and_expect(self.pg7, [p], sep3.itf)
3772 self.assertEqual(rx[Ether].src, routed_src_mac)
3773 self.assertEqual(rx[Ether].dst, sep3.mac)
3774 self.assertEqual(rx[IPv6].src, "2001:10::88")
3775 self.assertEqual(rx[IPv6].dst, ep1.ip6)
3777 # endpoint learnt via the parent GBP-vxlan interface
3778 self.assertTrue(find_gbp_endpoint(self,
3779 vx_tun_l3._sw_if_index,
3783 # L3 switch from local to remote EP
3785 p4 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3786 IP(src=ep1.ip4, dst="10.0.0.88") /
3787 UDP(sport=1234, dport=1234) /
3788 Raw(b'\xa5' * 100))]
3789 p6 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3790 IPv6(src=ep1.ip6, dst="2001:10::88") /
3791 UDP(sport=1234, dport=1234) /
3792 Raw(b'\xa5' * 100))]
3794 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3797 self.assertEqual(rx[Ether].src, routed_src_mac)
3798 self.assertEqual(rx[Ether].dst, sep1.mac)
3799 self.assertEqual(rx[IP].src, ep1.ip4)
3800 self.assertEqual(rx[IP].dst, "10.0.0.88")
3802 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep4.itf)
3805 self.assertEqual(rx[Ether].src, routed_src_mac)
3806 self.assertEqual(rx[Ether].dst, sep4.mac)
3807 self.assertEqual(rx[IPv6].src, ep1.ip6)
3808 self.assertEqual(rx[IPv6].dst, "2001:10::88")
3811 # test the dst-ip hash mode
3813 c5 = VppGbpContract(
3814 self, 402, epg_220.sclass, epg_221.sclass, acl.acl_index,
3815 [VppGbpContractRule(
3816 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3817 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
3818 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3819 sep1.ip4, sep1.epg.rd),
3820 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3821 sep2.ip4, sep2.epg.rd)]),
3823 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3824 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
3825 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3826 sep3.ip6, sep3.epg.rd),
3827 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3828 sep4.ip6, sep4.epg.rd)])],
3829 [ETH_P_IP, ETH_P_IPV6])
3832 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3835 self.assertEqual(rx[Ether].src, routed_src_mac)
3836 self.assertEqual(rx[Ether].dst, sep1.mac)
3837 self.assertEqual(rx[IP].src, ep1.ip4)
3838 self.assertEqual(rx[IP].dst, "10.0.0.88")
3840 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep3.itf)
3843 self.assertEqual(rx[Ether].src, routed_src_mac)
3844 self.assertEqual(rx[Ether].dst, sep3.mac)
3845 self.assertEqual(rx[IPv6].src, ep1.ip6)
3846 self.assertEqual(rx[IPv6].dst, "2001:10::88")
3849 # a programmed remote SEP in EPG 320
3852 # gbp vxlan tunnel for the remote SEP
3853 vx_tun_l3_sep = VppGbpVxlanTunnel(
3854 self, 555, rd1.rd_id,
3855 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
3857 vx_tun_l3_sep.add_vpp_config()
3860 sep5 = VppGbpEndpoint(self, vx_tun_l3_sep,
3862 "12.0.0.10", "13.0.0.10",
3863 "4001:10::10", "5001:10::10",
3864 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
3866 self.pg7.remote_ip4,
3868 sep5.add_vpp_config()
3871 # local l3out redirect tests
3876 self.loop4.set_mac(self.router_mac)
3877 b_lo4_ip4 = VppIpInterfaceBind(self, self.loop4, t4).add_vpp_config()
3878 b_lo4_ip6 = VppIpInterfaceBind(self, self.loop4, t6).add_vpp_config()
3879 ebd = VppBridgeDomain(self, 100)
3880 ebd.add_vpp_config()
3881 gebd = VppGbpBridgeDomain(self, ebd, rd1, self.loop4, None, None)
3882 gebd.add_vpp_config()
3884 eepg = VppGbpEndpointGroup(self, 888, 765, rd1, gebd,
3888 VppGbpEndpointRetention(60))
3889 eepg.add_vpp_config()
3890 # add subnets to BVI
3891 VppIpInterfaceAddress(
3895 24, bind=b_lo4_ip4).add_vpp_config()
3896 VppIpInterfaceAddress(
3900 64, bind=b_lo4_ip6).add_vpp_config()
3901 # ... which are L3-out subnets
3902 VppGbpSubnet(self, rd1, "10.1.0.0", 24,
3903 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3904 sclass=765).add_vpp_config()
3905 VppGbpSubnet(self, rd1, "2001:10:1::128", 64,
3906 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3907 sclass=765).add_vpp_config()
3908 # external endpoints
3909 VppL2Vtr(self, self.vlan_100, L2_VTR_OP.L2_POP_1).add_vpp_config()
3910 eep1 = VppGbpEndpoint(self, self.vlan_100, eepg, None, "10.1.0.1",
3911 "11.1.0.1", "2001:10:1::1", "3001:10:1::1",
3912 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
3913 eep1.add_vpp_config()
3914 VppL2Vtr(self, self.vlan_101, L2_VTR_OP.L2_POP_1).add_vpp_config()
3915 eep2 = VppGbpEndpoint(self, self.vlan_101, eepg, None, "10.1.0.2",
3916 "11.1.0.2", "2001:10:1::2", "3001:10:1::2",
3917 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
3918 eep2.add_vpp_config()
3920 # external subnets reachable though eep1 and eep2 respectively
3921 VppIpRoute(self, "10.220.0.0", 24,
3922 [VppRoutePath(eep1.ip4, eep1.epg.bvi.sw_if_index)],
3923 table_id=t4.table_id).add_vpp_config()
3924 VppGbpSubnet(self, rd1, "10.220.0.0", 24,
3925 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3926 sclass=4220).add_vpp_config()
3927 VppIpRoute(self, "10:220::", 64,
3928 [VppRoutePath(eep1.ip6, eep1.epg.bvi.sw_if_index)],
3929 table_id=t6.table_id).add_vpp_config()
3930 VppGbpSubnet(self, rd1, "10:220::", 64,
3931 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3932 sclass=4220).add_vpp_config()
3933 VppIpRoute(self, "10.221.0.0", 24,
3934 [VppRoutePath(eep2.ip4, eep2.epg.bvi.sw_if_index)],
3935 table_id=t4.table_id).add_vpp_config()
3936 VppGbpSubnet(self, rd1, "10.221.0.0", 24,
3937 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3938 sclass=4221).add_vpp_config()
3939 VppIpRoute(self, "10:221::", 64,
3940 [VppRoutePath(eep2.ip6, eep2.epg.bvi.sw_if_index)],
3941 table_id=t6.table_id).add_vpp_config()
3942 VppGbpSubnet(self, rd1, "10:221::", 64,
3943 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3944 sclass=4221).add_vpp_config()
3947 # l3out redirect to remote (known, then unknown) SEP
3950 # packets from 1 external subnet to the other
3951 p = [(Ether(src=eep1.mac, dst=self.router_mac) /
3953 IP(src="10.220.0.17", dst="10.221.0.65") /
3954 UDP(sport=1234, dport=1234) /
3955 Raw(b'\xa5' * 100)),
3956 (Ether(src=eep1.mac, dst=self.router_mac) /
3958 IPv6(src="10:220::17", dst="10:221::65") /
3959 UDP(sport=1234, dport=1234) /
3960 Raw(b'\xa5' * 100))]
3962 # packets should be dropped in absence of contract
3963 self.send_and_assert_no_replies(self.pg0, p)
3965 # contract redirecting to sep5
3967 self, 402, 4220, 4221, acl.acl_index,
3968 [VppGbpContractRule(
3969 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3970 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
3971 [VppGbpContractNextHop(sep5.vmac, sep5.epg.bd,
3972 sep5.ip4, sep5.epg.rd)]),
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.ip6, sep5.epg.rd)])],
3978 [ETH_P_IP, ETH_P_IPV6]).add_vpp_config()
3980 rxs = self.send_and_expect(self.pg0, p, self.pg7)
3982 for rx, tx in zip(rxs, p):
3983 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3984 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3985 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3986 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
3987 # this should use the programmed remote leaf TEP
3988 self.assertEqual(rx[VXLAN].vni, 555)
3989 self.assertEqual(rx[VXLAN].gpid, 4220)
3990 self.assertTrue(rx[VXLAN].flags.G)
3991 self.assertTrue(rx[VXLAN].flags.Instance)
3992 # redirect policy has been applied
3993 self.assertTrue(rx[VXLAN].gpflags.A)
3994 self.assertTrue(rx[VXLAN].gpflags.D)
3995 rxip = rx[VXLAN][Ether].payload
3996 txip = tx[Dot1Q].payload
3997 self.assertEqual(rxip.src, txip.src)
3998 self.assertEqual(rxip.dst, txip.dst)
4000 # remote SEP: it is now an unknown remote SEP and should go
4002 sep5.remove_vpp_config()
4004 rxs = self.send_and_expect(self.pg0, p, self.pg7)
4006 for rx, tx in zip(rxs, p):
4007 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4008 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4009 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4010 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4011 # this should use the spine proxy TEP
4012 self.assertEqual(rx[VXLAN].vni, epg_320.bd.uu_fwd.vni)
4013 self.assertEqual(rx[VXLAN].gpid, 4220)
4014 self.assertTrue(rx[VXLAN].flags.G)
4015 self.assertTrue(rx[VXLAN].flags.Instance)
4016 # redirect policy has been applied
4017 self.assertTrue(rx[VXLAN].gpflags.A)
4018 self.assertTrue(rx[VXLAN].gpflags.D)
4019 rxip = rx[VXLAN][Ether].payload
4020 txip = tx[Dot1Q].payload
4021 self.assertEqual(rxip.src, txip.src)
4022 self.assertEqual(rxip.dst, txip.dst)
4025 # l3out redirect to local SEP
4028 # change the contract between l3out to redirect to local SEPs
4029 # instead of remote SEP
4031 self, 402, 4220, 4221, acl.acl_index,
4032 [VppGbpContractRule(
4033 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4034 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
4035 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
4036 sep1.ip4, sep1.epg.rd)]),
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.ip6, sep1.epg.rd)])],
4042 [ETH_P_IP, ETH_P_IPV6]).add_vpp_config()
4044 rxs = self.send_and_expect(self.pg0, p, sep1.itf)
4045 for rx, tx in zip(rxs, p):
4046 self.assertEqual(rx[Ether].src, routed_src_mac)
4047 self.assertEqual(rx[Ether].dst, sep1.mac)
4048 rxip = rx[Ether].payload
4049 txip = tx[Ether].payload
4050 self.assertEqual(rxip.src, txip.src)
4051 self.assertEqual(rxip.dst, txip.dst)
4054 # redirect remote EP to remote (known then unknown) SEP
4057 # remote SEP known again
4058 sep5.add_vpp_config()
4060 # contract to redirect to learnt SEP
4062 self, 402, epg_221.sclass, epg_222.sclass, acl.acl_index,
4063 [VppGbpContractRule(
4064 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4065 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
4066 [VppGbpContractNextHop(sep5.vmac, sep5.epg.bd,
4067 sep5.ip4, sep5.epg.rd)]),
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.ip6, sep5.epg.rd)])],
4073 [ETH_P_IP, ETH_P_IPV6]).add_vpp_config()
4075 # packets from unknown EP 221 to known EP in EPG 222
4076 # should be redirected to known remote SEP
4077 base = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
4078 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
4079 UDP(sport=1234, dport=48879) /
4080 VXLAN(vni=444, gpid=441, flags=0x88) /
4081 Ether(src="00:22:22:22:22:44", dst=str(self.router_mac)))
4083 IP(src="10.0.1.100", dst=ep3.ip4) /
4084 UDP(sport=1234, dport=1234) /
4085 Raw(b'\xa5' * 100)),
4087 IPv6(src="2001:10::100", dst=ep3.ip6) /
4088 UDP(sport=1234, dport=1234) /
4089 Raw(b'\xa5' * 100))]
4091 # unknown remote EP to local EP redirected to known remote SEP
4092 rxs = self.send_and_expect(self.pg7, p, self.pg7)
4094 for rx, tx in zip(rxs, p):
4095 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4096 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4097 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4098 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4099 # this should use the programmed remote leaf TEP
4100 self.assertEqual(rx[VXLAN].vni, 555)
4101 self.assertEqual(rx[VXLAN].gpid, epg_221.sclass)
4102 self.assertTrue(rx[VXLAN].flags.G)
4103 self.assertTrue(rx[VXLAN].flags.Instance)
4104 # redirect policy has been applied
4105 self.assertTrue(rx[VXLAN].gpflags.A)
4106 self.assertFalse(rx[VXLAN].gpflags.D)
4107 rxip = rx[VXLAN][Ether].payload
4108 txip = tx[VXLAN][Ether].payload
4109 self.assertEqual(rxip.src, txip.src)
4110 self.assertEqual(rxip.dst, txip.dst)
4112 # endpoint learnt via the parent GBP-vxlan interface
4113 self.assertTrue(find_gbp_endpoint(self,
4114 vx_tun_l3._sw_if_index,
4116 self.assertTrue(find_gbp_endpoint(self,
4117 vx_tun_l3._sw_if_index,
4120 # remote SEP: it is now an unknown remote SEP and should go
4122 sep5.remove_vpp_config()
4124 # remote EP (coming from spine proxy) to local EP redirected to
4126 rxs = self.send_and_expect(self.pg7, p, self.pg7)
4128 for rx, tx in zip(rxs, p):
4129 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4130 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4131 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4132 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4133 # this should use the spine proxy TEP
4134 self.assertEqual(rx[VXLAN].vni, epg_320.bd.uu_fwd.vni)
4135 self.assertEqual(rx[VXLAN].gpid, epg_221.sclass)
4136 self.assertTrue(rx[VXLAN].flags.G)
4137 self.assertTrue(rx[VXLAN].flags.Instance)
4138 # redirect policy has been applied
4139 self.assertTrue(rx[VXLAN].gpflags.A)
4140 self.assertFalse(rx[VXLAN].gpflags.D)
4141 rxip = rx[VXLAN][Ether].payload
4142 txip = tx[VXLAN][Ether].payload
4143 self.assertEqual(rxip.src, txip.src)
4144 self.assertEqual(rxip.dst, txip.dst)
4149 self.pg7.unconfig_ip4()
4151 def test_gbp_redirect_extended(self):
4152 """ GBP Endpoint Redirect Extended """
4154 self.vapi.cli("set logging class gbp level debug")
4156 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
4157 routed_dst_mac = "00:0c:0c:0c:0c:0c"
4158 routed_src_mac = "00:22:bd:f8:19:ff"
4160 learnt = [{'mac': '00:00:11:11:11:02',
4162 'ip6': '2001:10::2'},
4163 {'mac': '00:00:11:11:11:03',
4165 'ip6': '2001:10::3'}]
4170 t4 = VppIpTable(self, 1)
4172 t6 = VppIpTable(self, 1, True)
4175 # create IPv4 and IPv6 RD UU VxLAN-GBP TEP and bind them to the right
4177 rd_uu4 = VppVxlanGbpTunnel(
4180 self.pg7.remote_ip4,
4182 mode=(VppEnum.vl_api_vxlan_gbp_api_tunnel_mode_t.
4183 VXLAN_GBP_API_TUNNEL_MODE_L3))
4184 rd_uu4.add_vpp_config()
4185 VppIpInterfaceBind(self, rd_uu4, t4).add_vpp_config()
4187 rd_uu6 = VppVxlanGbpTunnel(
4190 self.pg7.remote_ip4,
4192 mode=(VppEnum.vl_api_vxlan_gbp_api_tunnel_mode_t.
4193 VXLAN_GBP_API_TUNNEL_MODE_L3))
4194 rd_uu6.add_vpp_config()
4195 VppIpInterfaceBind(self, rd_uu6, t4).add_vpp_config()
4197 rd1 = VppGbpRouteDomain(self, 2, 402, t4, t6, rd_uu4, rd_uu6)
4198 rd1.add_vpp_config()
4200 self.loop0.set_mac(self.router_mac)
4201 self.loop1.set_mac(self.router_mac)
4202 self.loop2.set_mac(self.router_mac)
4205 # Bind the BVI to the RD
4207 b_lo0_ip4 = VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
4208 b_lo0_ip6 = VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
4209 b_lo1_ip4 = VppIpInterfaceBind(self, self.loop1, t4).add_vpp_config()
4210 b_lo1_ip6 = VppIpInterfaceBind(self, self.loop1, t6).add_vpp_config()
4211 b_lo2_ip4 = VppIpInterfaceBind(self, self.loop2, t4).add_vpp_config()
4212 b_lo2_ip6 = VppIpInterfaceBind(self, self.loop2, t6).add_vpp_config()
4215 # Pg7 hosts a BD's UU-fwd
4217 self.pg7.config_ip4()
4218 self.pg7.resolve_arp()
4221 # a GBP bridge domains for the EPs
4223 bd1 = VppBridgeDomain(self, 1)
4224 bd1.add_vpp_config()
4225 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0)
4226 gbd1.add_vpp_config()
4228 bd2 = VppBridgeDomain(self, 2)
4229 bd2.add_vpp_config()
4230 gbd2 = VppGbpBridgeDomain(self, bd2, rd1, self.loop1)
4231 gbd2.add_vpp_config()
4233 # ... and has a /32 and /128 applied
4234 ip4_addr1 = VppIpInterfaceAddress(self, gbd1.bvi,
4236 bind=b_lo0_ip4).add_vpp_config()
4237 ip6_addr1 = VppIpInterfaceAddress(self, gbd1.bvi,
4238 "2001:10::128", 128,
4239 bind=b_lo0_ip6).add_vpp_config()
4240 ip4_addr2 = VppIpInterfaceAddress(self, gbd2.bvi,
4242 bind=b_lo1_ip4).add_vpp_config()
4243 ip6_addr2 = VppIpInterfaceAddress(self, gbd2.bvi,
4244 "2001:11::128", 128,
4245 bind=b_lo1_ip6).add_vpp_config()
4248 # The Endpoint-groups
4250 epg_220 = VppGbpEndpointGroup(self, 220, 440, rd1, gbd1,
4254 VppGbpEndpointRetention(60))
4255 epg_220.add_vpp_config()
4256 epg_221 = VppGbpEndpointGroup(self, 221, 441, rd1, gbd2,
4260 VppGbpEndpointRetention(60))
4261 epg_221.add_vpp_config()
4264 # a GBP bridge domains for the SEPs
4266 bd_uu3 = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
4267 self.pg7.remote_ip4, 116)
4268 bd_uu3.add_vpp_config()
4270 bd3 = VppBridgeDomain(self, 3)
4271 bd3.add_vpp_config()
4272 gbd3 = VppGbpBridgeDomain(self, bd3, rd1, self.loop2,
4273 bd_uu3, learn=False)
4274 gbd3.add_vpp_config()
4276 ip4_addr3 = VppIpInterfaceAddress(self, gbd3.bvi,
4278 bind=b_lo2_ip4).add_vpp_config()
4279 ip6_addr3 = VppIpInterfaceAddress(self, gbd3.bvi,
4280 "4001:10::128", 128,
4281 bind=b_lo2_ip6).add_vpp_config()
4284 # self.logger.info(self.vapi.cli("show gbp bridge"))
4285 # self.logger.info(self.vapi.cli("show vxlan-gbp tunnel"))
4286 # self.logger.info(self.vapi.cli("show gbp vxlan"))
4287 # self.logger.info(self.vapi.cli("show int addr"))
4291 # EPGs in which the service endpoints exist
4293 epg_320 = VppGbpEndpointGroup(self, 320, 550, rd1, gbd3,
4297 VppGbpEndpointRetention(60))
4298 epg_320.add_vpp_config()
4303 ep1 = VppGbpEndpoint(self, self.pg0,
4305 "10.0.0.1", "11.0.0.1",
4306 "2001:10::1", "3001:10::1")
4307 ep1.add_vpp_config()
4308 ep2 = VppGbpEndpoint(self, self.pg1,
4310 "10.0.1.1", "11.0.1.1",
4311 "2001:11::1", "3001:11::1")
4312 ep2.add_vpp_config()
4317 sep1 = VppGbpEndpoint(self, self.pg3,
4319 "12.0.0.1", "13.0.0.1",
4320 "4001:10::1", "5001:10::1")
4321 sep2 = VppGbpEndpoint(self, self.pg4,
4323 "12.0.0.2", "13.0.0.2",
4324 "4001:10::2", "5001:10::2")
4326 # sep1 and sep2 are not added to config yet
4327 # they are unknown for now
4330 # add routes to EPG subnets
4332 VppGbpSubnet(self, rd1, "10.0.0.0", 24,
4333 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT
4335 VppGbpSubnet(self, rd1, "10.0.1.0", 24,
4336 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT
4340 # Local host to known local host in different BD
4341 # with SFC contract (source and destination are in
4342 # one node and service endpoint in another node)
4344 p4 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
4345 IP(src=ep1.ip4, dst=ep2.ip4) /
4346 UDP(sport=1234, dport=1234) /
4347 Raw(b'\xa5' * 100)),
4348 (Ether(src=ep2.mac, dst=str(self.router_mac)) /
4349 IP(src=ep2.ip4, dst=ep1.ip4) /
4350 UDP(sport=1234, dport=1234) /
4351 Raw(b'\xa5' * 100))]
4352 p6 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
4353 IPv6(src=ep1.ip6, dst=ep2.ip6) /
4354 UDP(sport=1234, dport=1234) /
4355 Raw(b'\xa5' * 100)),
4356 (Ether(src=ep2.mac, dst=str(self.router_mac)) /
4357 IPv6(src=ep2.ip6, dst=ep1.ip6) /
4358 UDP(sport=1234, dport=1230) /
4359 Raw(b'\xa5' * 100))]
4361 # should be dropped since no contract yet
4362 self.send_and_assert_no_replies(self.pg0, [p4[0]])
4363 self.send_and_assert_no_replies(self.pg0, [p6[0]])
4366 # Add a contract with a rule to load-balance redirect via SEP1 and SEP2
4367 # one of the next-hops is via an EP that is not known
4369 rule4 = AclRule(is_permit=1, proto=17)
4370 rule6 = AclRule(src_prefix=IPv6Network((0, 0)),
4371 dst_prefix=IPv6Network((0, 0)), is_permit=1, proto=17)
4372 acl = VppAcl(self, rules=[rule4, rule6])
4373 acl.add_vpp_config()
4376 # test the src-ip hash mode
4378 c1 = VppGbpContract(
4379 self, 402, epg_220.sclass, epg_221.sclass, acl.acl_index,
4380 [VppGbpContractRule(
4381 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4382 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
4383 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
4384 sep1.ip4, sep1.epg.rd)]),
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.ip6, sep1.epg.rd)])],
4390 [ETH_P_IP, ETH_P_IPV6])
4393 c2 = VppGbpContract(
4394 self, 402, epg_221.sclass, epg_220.sclass, acl.acl_index,
4395 [VppGbpContractRule(
4396 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4397 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
4398 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
4399 sep1.ip4, sep1.epg.rd)]),
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.ip6, sep1.epg.rd)])],
4405 [ETH_P_IP, ETH_P_IPV6])
4408 # ep1 <--> ep2 redirected through sep1
4410 # packet is redirected to sep bd and then go through sep bd UU
4412 rxs = self.send_and_expect(self.pg0, p4[0] * 17, self.pg7)
4415 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4416 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4417 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4418 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4419 self.assertEqual(rx[VXLAN].vni, 116)
4420 self.assertTrue(rx[VXLAN].flags.G)
4421 self.assertTrue(rx[VXLAN].flags.Instance)
4422 # redirect policy has been applied
4423 self.assertTrue(rx[VXLAN].gpflags.A)
4424 self.assertFalse(rx[VXLAN].gpflags.D)
4426 inner = rx[VXLAN].payload
4428 self.assertEqual(inner[Ether].src, routed_src_mac)
4429 self.assertEqual(inner[Ether].dst, sep1.mac)
4430 self.assertEqual(inner[IP].src, ep1.ip4)
4431 self.assertEqual(inner[IP].dst, ep2.ip4)
4433 rxs = self.send_and_expect(self.pg1, p4[1] * 17, self.pg7)
4436 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4437 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4438 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4439 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4440 self.assertEqual(rx[VXLAN].vni, 116)
4441 self.assertTrue(rx[VXLAN].flags.G)
4442 self.assertTrue(rx[VXLAN].flags.Instance)
4443 # redirect policy has been applied
4444 self.assertTrue(rx[VXLAN].gpflags.A)
4445 self.assertFalse(rx[VXLAN].gpflags.D)
4447 inner = rx[VXLAN].payload
4449 self.assertEqual(inner[Ether].src, routed_src_mac)
4450 self.assertEqual(inner[Ether].dst, sep1.mac)
4451 self.assertEqual(inner[IP].src, ep2.ip4)
4452 self.assertEqual(inner[IP].dst, ep1.ip4)
4454 rxs = self.send_and_expect(self.pg0, p6[0] * 17, self.pg7)
4457 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4458 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4459 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4460 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4461 self.assertEqual(rx[VXLAN].vni, 116)
4462 self.assertTrue(rx[VXLAN].flags.G)
4463 self.assertTrue(rx[VXLAN].flags.Instance)
4464 # redirect policy has been applied
4465 inner = rx[VXLAN].payload
4467 self.assertEqual(inner[Ether].src, routed_src_mac)
4468 self.assertEqual(inner[Ether].dst, sep1.mac)
4469 self.assertEqual(inner[IPv6].src, ep1.ip6)
4470 self.assertEqual(inner[IPv6].dst, ep2.ip6)
4472 rxs = self.send_and_expect(self.pg1, p6[1] * 17, self.pg7)
4475 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4476 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4477 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4478 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4479 self.assertEqual(rx[VXLAN].vni, 116)
4480 self.assertTrue(rx[VXLAN].flags.G)
4481 self.assertTrue(rx[VXLAN].flags.Instance)
4482 # redirect policy has been applied
4483 self.assertTrue(rx[VXLAN].gpflags.A)
4484 self.assertFalse(rx[VXLAN].gpflags.D)
4486 inner = rx[VXLAN].payload
4488 self.assertEqual(inner[Ether].src, routed_src_mac)
4489 self.assertEqual(inner[Ether].dst, sep1.mac)
4490 self.assertEqual(inner[IPv6].src, ep2.ip6)
4491 self.assertEqual(inner[IPv6].dst, ep1.ip6)
4493 # configure sep1: it is now local
4494 # packets between ep1 and ep2 are redirected locally
4495 sep1.add_vpp_config()
4497 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
4500 self.assertEqual(rx[Ether].src, routed_src_mac)
4501 self.assertEqual(rx[Ether].dst, sep1.mac)
4502 self.assertEqual(rx[IP].src, ep1.ip4)
4503 self.assertEqual(rx[IP].dst, ep2.ip4)
4505 rxs = self.send_and_expect(self.pg1, p6[1] * 17, sep1.itf)
4508 self.assertEqual(rx[Ether].src, routed_src_mac)
4509 self.assertEqual(rx[Ether].dst, sep1.mac)
4510 self.assertEqual(rx[IPv6].src, ep2.ip6)
4511 self.assertEqual(rx[IPv6].dst, ep1.ip6)
4513 # packet coming from the l2 spine-proxy to sep1
4514 p = (Ether(src=self.pg7.remote_mac,
4515 dst=self.pg7.local_mac) /
4516 IP(src=self.pg7.remote_ip4,
4517 dst=self.pg7.local_ip4) /
4518 UDP(sport=1234, dport=48879) /
4519 VXLAN(vni=116, gpid=440, gpflags=0x08, flags=0x88) /
4520 Ether(src=str(self.router_mac), dst=sep1.mac) /
4521 IP(src=ep1.ip4, dst=ep2.ip4) /
4522 UDP(sport=1234, dport=1234) /
4525 rxs = self.send_and_expect(self.pg7, [p] * 17, sep1.itf)
4528 self.assertEqual(rx[Ether].src, str(self.router_mac))
4529 self.assertEqual(rx[Ether].dst, sep1.mac)
4530 self.assertEqual(rx[IP].src, ep1.ip4)
4531 self.assertEqual(rx[IP].dst, ep2.ip4)
4533 # contract for SEP to communicate with dst EP
4534 c3 = VppGbpContract(
4535 self, 402, epg_320.sclass, epg_221.sclass, acl.acl_index,
4536 [VppGbpContractRule(
4537 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4538 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC),
4540 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4541 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC)],
4542 [ETH_P_IP, ETH_P_IPV6])
4545 # temporarily remove ep2, so that ep2 is remote & unknown
4546 ep2.remove_vpp_config()
4548 # packet going back from sep1 to its original dest (ep2)
4549 # as ep2 is now unknown (see above), it must go through
4550 # the rd UU (packet is routed)
4552 p1 = (Ether(src=sep1.mac, dst=self.router_mac) /
4553 IP(src=ep1.ip4, dst=ep2.ip4) /
4554 UDP(sport=1234, dport=1234) /
4557 rxs = self.send_and_expect(self.pg3, [p1] * 17, self.pg7)
4560 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4561 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4562 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4563 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4564 self.assertEqual(rx[VXLAN].vni, 114)
4565 self.assertTrue(rx[VXLAN].flags.G)
4566 self.assertTrue(rx[VXLAN].flags.Instance)
4567 # redirect policy has been applied
4568 inner = rx[VXLAN].payload
4569 self.assertEqual(inner[Ether].src, routed_src_mac)
4570 self.assertEqual(inner[Ether].dst, routed_dst_mac)
4571 self.assertEqual(inner[IP].src, ep1.ip4)
4572 self.assertEqual(inner[IP].dst, ep2.ip4)
4574 self.logger.info(self.vapi.cli("show bridge 3 detail"))
4575 sep1.remove_vpp_config()
4577 self.logger.info(self.vapi.cli("show bridge 1 detail"))
4578 self.logger.info(self.vapi.cli("show bridge 2 detail"))
4580 # re-add ep2: it is local again :)
4581 ep2.add_vpp_config()
4583 # packet coming back from the remote sep through rd UU
4584 p2 = (Ether(src=self.pg7.remote_mac,
4585 dst=self.pg7.local_mac) /
4586 IP(src=self.pg7.remote_ip4,
4587 dst=self.pg7.local_ip4) /
4588 UDP(sport=1234, dport=48879) /
4589 VXLAN(vni=114, gpid=441, gpflags=0x09, flags=0x88) /
4590 Ether(src=str(self.router_mac), dst=self.router_mac) /
4591 IP(src=ep1.ip4, dst=ep2.ip4) /
4592 UDP(sport=1234, dport=1234) /
4595 rxs = self.send_and_expect(self.pg7, [p2], self.pg1)
4598 self.assertEqual(rx[Ether].src, str(self.router_mac))
4599 self.assertEqual(rx[Ether].dst, self.pg1.remote_mac)
4600 self.assertEqual(rx[IP].src, ep1.ip4)
4601 self.assertEqual(rx[IP].dst, ep2.ip4)
4604 # bd_uu2.add_vpp_config()
4610 c1.remove_vpp_config()
4611 c2.remove_vpp_config()
4612 c3.remove_vpp_config()
4613 self.pg7.unconfig_ip4()
4615 def test_gbp_l3_out(self):
4618 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
4619 self.vapi.cli("set logging class gbp level debug")
4621 routed_dst_mac = "00:0c:0c:0c:0c:0c"
4622 routed_src_mac = "00:22:bd:f8:19:ff"
4627 t4 = VppIpTable(self, 1)
4629 t6 = VppIpTable(self, 1, True)
4632 rd1 = VppGbpRouteDomain(self, 2, 55, t4, t6)
4633 rd1.add_vpp_config()
4635 self.loop0.set_mac(self.router_mac)
4638 # Bind the BVI to the RD
4640 b_ip4 = VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
4641 b_ip6 = VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
4644 # Pg7 hosts a BD's BUM
4645 # Pg1 some other l3 interface
4647 self.pg7.config_ip4()
4648 self.pg7.resolve_arp()
4651 # a multicast vxlan-gbp tunnel for broadcast in the BD
4653 tun_bm = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
4656 tun_bm.add_vpp_config()
4659 # a GBP external bridge domains for the EPs
4661 bd1 = VppBridgeDomain(self, 1)
4662 bd1.add_vpp_config()
4663 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0, None, tun_bm)
4664 gbd1.add_vpp_config()
4667 # The Endpoint-groups in which the external endpoints exist
4669 epg_220 = VppGbpEndpointGroup(self, 220, 113, rd1, gbd1,
4673 VppGbpEndpointRetention(4))
4674 epg_220.add_vpp_config()
4676 # the BVIs have the subnets applied ...
4677 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128",
4678 24, bind=b_ip4).add_vpp_config()
4679 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128",
4680 64, bind=b_ip6).add_vpp_config()
4682 # ... which are L3-out subnets
4683 l3o_1 = VppGbpSubnet(
4684 self, rd1, "10.0.0.0", 24,
4685 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
4687 l3o_1.add_vpp_config()
4690 # an external interface attached to the outside world and the
4693 VppL2Vtr(self, self.vlan_100, L2_VTR_OP.L2_POP_1).add_vpp_config()
4694 VppL2Vtr(self, self.vlan_101, L2_VTR_OP.L2_POP_1).add_vpp_config()
4695 vlan_144 = VppDot1QSubint(self, self.pg0, 144)
4697 # vlan_102 is not poped
4700 # an unicast vxlan-gbp for inter-RD traffic
4702 vx_tun_l3 = VppGbpVxlanTunnel(
4703 self, 444, rd1.rd_id,
4704 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
4706 vx_tun_l3.add_vpp_config()
4709 # External Endpoints
4711 eep1 = VppGbpEndpoint(self, self.vlan_100,
4713 "10.0.0.1", "11.0.0.1",
4714 "2001:10::1", "3001::1",
4715 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
4716 eep1.add_vpp_config()
4717 eep2 = VppGbpEndpoint(self, self.vlan_101,
4719 "10.0.0.2", "11.0.0.2",
4720 "2001:10::2", "3001::2",
4721 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
4722 eep2.add_vpp_config()
4723 eep3 = VppGbpEndpoint(self, self.vlan_102,
4725 "10.0.0.3", "11.0.0.3",
4726 "2001:10::3", "3001::3",
4727 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
4728 eep3.add_vpp_config()
4731 # A remote external endpoint
4733 rep = VppGbpEndpoint(self, vx_tun_l3,
4735 "10.0.0.101", "11.0.0.101",
4736 "2001:10::101", "3001::101",
4737 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
4739 self.pg7.remote_ip4,
4741 rep.add_vpp_config()
4744 # EP1 impersonating EP3 is dropped
4746 p = (Ether(src=eep1.mac, dst="ff:ff:ff:ff:ff:ff") /
4749 psrc="10.0.0.3", pdst="10.0.0.128",
4750 hwsrc=eep1.mac, hwdst="ff:ff:ff:ff:ff:ff"))
4751 self.send_and_assert_no_replies(self.pg0, p)
4754 # ARP packet from External EPs are accepted and replied to
4756 p_arp = (Ether(src=eep1.mac, dst="ff:ff:ff:ff:ff:ff") /
4759 psrc=eep1.ip4, pdst="10.0.0.128",
4760 hwsrc=eep1.mac, hwdst="ff:ff:ff:ff:ff:ff"))
4761 rxs = self.send_and_expect(self.pg0, p_arp * 1, self.pg0)
4764 # ARP packet from host in remote subnet are accepted and replied to
4766 p_arp = (Ether(src=eep3.mac, dst="ff:ff:ff:ff:ff:ff") /
4769 psrc=eep3.ip4, pdst="10.0.0.128",
4770 hwsrc=eep3.mac, hwdst="ff:ff:ff:ff:ff:ff"))
4771 rxs = self.send_and_expect(self.pg0, p_arp * 1, self.pg0)
4774 # packets destined to unknown addresses in the BVI's subnet
4777 p4 = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
4779 IP(src="10.0.0.1", dst="10.0.0.88") /
4780 UDP(sport=1234, dport=1234) /
4782 p6 = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
4784 IPv6(src="2001:10::1", dst="2001:10::88") /
4785 UDP(sport=1234, dport=1234) /
4788 rxs = self.send_and_expect(self.pg0, p4 * 1, self.pg7)
4791 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4792 # self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4793 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4794 self.assertEqual(rx[IP].dst, "239.1.1.1")
4795 self.assertEqual(rx[VXLAN].vni, 88)
4796 self.assertTrue(rx[VXLAN].flags.G)
4797 self.assertTrue(rx[VXLAN].flags.Instance)
4798 # policy was applied to the original IP packet
4799 self.assertEqual(rx[VXLAN].gpid, 113)
4800 self.assertTrue(rx[VXLAN].gpflags.A)
4801 self.assertFalse(rx[VXLAN].gpflags.D)
4803 inner = rx[VXLAN].payload
4805 self.assertTrue(inner.haslayer(ARP))
4808 # remote to external
4810 p = (Ether(src=self.pg7.remote_mac,
4811 dst=self.pg7.local_mac) /
4812 IP(src=self.pg7.remote_ip4,
4813 dst=self.pg7.local_ip4) /
4814 UDP(sport=1234, dport=48879) /
4815 VXLAN(vni=444, gpid=113, flags=0x88) /
4816 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
4817 IP(src="10.0.0.101", dst="10.0.0.1") /
4818 UDP(sport=1234, dport=1234) /
4821 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
4824 # local EP pings router
4826 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
4828 IP(src=eep1.ip4, dst="10.0.0.128") /
4829 ICMP(type='echo-request'))
4831 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
4834 self.assertEqual(rx[Ether].src, str(self.router_mac))
4835 self.assertEqual(rx[Ether].dst, eep1.mac)
4836 self.assertEqual(rx[Dot1Q].vlan, 100)
4839 # local EP pings other local EP
4841 p = (Ether(src=eep1.mac, dst=eep2.mac) /
4843 IP(src=eep1.ip4, dst=eep2.ip4) /
4844 ICMP(type='echo-request'))
4846 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
4849 self.assertEqual(rx[Ether].src, eep1.mac)
4850 self.assertEqual(rx[Ether].dst, eep2.mac)
4851 self.assertEqual(rx[Dot1Q].vlan, 101)
4854 # local EP pings router w/o vlan tag poped
4856 p = (Ether(src=eep3.mac, dst=str(self.router_mac)) /
4858 IP(src=eep3.ip4, dst="10.0.0.128") /
4859 ICMP(type='echo-request'))
4861 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
4864 self.assertEqual(rx[Ether].src, str(self.router_mac))
4865 self.assertEqual(rx[Ether].dst, self.vlan_102.remote_mac)
4868 # A ip4 subnet reachable through the external EP1
4870 ip_220 = VppIpRoute(self, "10.220.0.0", 24,
4871 [VppRoutePath(eep1.ip4,
4872 eep1.epg.bvi.sw_if_index)],
4873 table_id=t4.table_id)
4874 ip_220.add_vpp_config()
4876 l3o_220 = VppGbpSubnet(
4877 self, rd1, "10.220.0.0", 24,
4878 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
4880 l3o_220.add_vpp_config()
4883 # An ip6 subnet reachable through the external EP1
4885 ip6_220 = VppIpRoute(self, "10:220::", 64,
4886 [VppRoutePath(eep1.ip6,
4887 eep1.epg.bvi.sw_if_index)],
4888 table_id=t6.table_id)
4889 ip6_220.add_vpp_config()
4891 l3o6_220 = VppGbpSubnet(
4892 self, rd1, "10:220::", 64,
4893 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
4895 l3o6_220.add_vpp_config()
4898 # A subnet reachable through the external EP2
4900 ip_221 = VppIpRoute(self, "10.221.0.0", 24,
4901 [VppRoutePath(eep2.ip4,
4902 eep2.epg.bvi.sw_if_index)],
4903 table_id=t4.table_id)
4904 ip_221.add_vpp_config()
4906 l3o_221 = VppGbpSubnet(
4907 self, rd1, "10.221.0.0", 24,
4908 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
4910 l3o_221.add_vpp_config()
4913 # ping between hosts in remote subnets
4914 # dropped without a contract
4916 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
4918 IP(src="10.220.0.1", dst="10.221.0.1") /
4919 ICMP(type='echo-request'))
4921 self.send_and_assert_no_replies(self.pg0, p * 1)
4924 # contract for the external nets to communicate
4926 rule4 = AclRule(is_permit=1, proto=17)
4927 rule6 = AclRule(src_prefix=IPv6Network((0, 0)),
4928 dst_prefix=IPv6Network((0, 0)), is_permit=1, proto=17)
4929 acl = VppAcl(self, rules=[rule4, rule6])
4930 acl.add_vpp_config()
4933 # A contract with the wrong scope is not matched
4935 c_44 = VppGbpContract(
4936 self, 44, 4220, 4221, acl.acl_index,
4937 [VppGbpContractRule(
4938 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4939 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4942 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4943 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4945 [ETH_P_IP, ETH_P_IPV6])
4946 c_44.add_vpp_config()
4947 self.send_and_assert_no_replies(self.pg0, p * 1)
4949 c1 = VppGbpContract(
4950 self, 55, 4220, 4221, acl.acl_index,
4951 [VppGbpContractRule(
4952 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4953 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4956 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4957 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4959 [ETH_P_IP, ETH_P_IPV6])
4963 # Contracts allowing ext-net 200 to talk with external EPs
4965 c2 = VppGbpContract(
4966 self, 55, 4220, 113, acl.acl_index,
4967 [VppGbpContractRule(
4968 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4969 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4972 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4973 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4975 [ETH_P_IP, ETH_P_IPV6])
4977 c3 = VppGbpContract(
4978 self, 55, 113, 4220, acl.acl_index,
4979 [VppGbpContractRule(
4980 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4981 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4984 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4985 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4987 [ETH_P_IP, ETH_P_IPV6])
4991 # ping between hosts in remote subnets
4993 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
4995 IP(src="10.220.0.1", dst="10.221.0.1") /
4996 UDP(sport=1234, dport=1234) /
4999 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
5002 self.assertEqual(rx[Ether].src, str(self.router_mac))
5003 self.assertEqual(rx[Ether].dst, eep2.mac)
5004 self.assertEqual(rx[Dot1Q].vlan, 101)
5006 # we did not learn these external hosts
5007 self.assertFalse(find_gbp_endpoint(self, ip="10.220.0.1"))
5008 self.assertFalse(find_gbp_endpoint(self, ip="10.221.0.1"))
5011 # from remote external EP to local external EP
5013 p = (Ether(src=self.pg7.remote_mac,
5014 dst=self.pg7.local_mac) /
5015 IP(src=self.pg7.remote_ip4,
5016 dst=self.pg7.local_ip4) /
5017 UDP(sport=1234, dport=48879) /
5018 VXLAN(vni=444, gpid=113, flags=0x88) /
5019 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
5020 IP(src="10.0.0.101", dst="10.220.0.1") /
5021 UDP(sport=1234, dport=1234) /
5024 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
5027 # ping from an external host to the remote external EP
5029 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
5031 IP(src="10.220.0.1", dst=rep.ip4) /
5032 UDP(sport=1234, dport=1234) /
5035 rxs = self.send_and_expect(self.pg0, p * 1, self.pg7)
5038 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
5039 # self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
5040 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
5041 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
5042 self.assertEqual(rx[VXLAN].vni, 444)
5043 self.assertTrue(rx[VXLAN].flags.G)
5044 self.assertTrue(rx[VXLAN].flags.Instance)
5045 # the sclass of the ext-net the packet came from
5046 self.assertEqual(rx[VXLAN].gpid, 4220)
5047 # policy was applied to the original IP packet
5048 self.assertTrue(rx[VXLAN].gpflags.A)
5049 # since it's an external host the reciever should not learn it
5050 self.assertTrue(rx[VXLAN].gpflags.D)
5051 inner = rx[VXLAN].payload
5052 self.assertEqual(inner[IP].src, "10.220.0.1")
5053 self.assertEqual(inner[IP].dst, rep.ip4)
5056 # An external subnet reachable via the remote external EP
5060 # first the VXLAN-GBP tunnel over which it is reached
5062 vx_tun_r1 = VppVxlanGbpTunnel(
5063 self, self.pg7.local_ip4,
5064 self.pg7.remote_ip4, 445,
5065 mode=(VppEnum.vl_api_vxlan_gbp_api_tunnel_mode_t.
5066 VXLAN_GBP_API_TUNNEL_MODE_L3))
5067 vx_tun_r1.add_vpp_config()
5068 VppIpInterfaceBind(self, vx_tun_r1, t4).add_vpp_config()
5070 self.logger.info(self.vapi.cli("sh vxlan-gbp tunnel"))
5073 # then the special adj to resolve through on that tunnel
5075 n1 = VppNeighbor(self,
5076 vx_tun_r1.sw_if_index,
5077 "00:0c:0c:0c:0c:0c",
5078 self.pg7.remote_ip4)
5082 # the route via the adj above
5084 ip_222 = VppIpRoute(self, "10.222.0.0", 24,
5085 [VppRoutePath(self.pg7.remote_ip4,
5086 vx_tun_r1.sw_if_index)],
5087 table_id=t4.table_id)
5088 ip_222.add_vpp_config()
5090 l3o_222 = VppGbpSubnet(
5091 self, rd1, "10.222.0.0", 24,
5092 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
5094 l3o_222.add_vpp_config()
5097 # ping between hosts in local and remote external subnets
5098 # dropped without a contract
5100 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
5102 IP(src="10.220.0.1", dst="10.222.0.1") /
5103 UDP(sport=1234, dport=1234) /
5106 rxs = self.send_and_assert_no_replies(self.pg0, p * 1)
5109 # Add contracts ext-nets for 220 -> 222
5111 c4 = VppGbpContract(
5112 self, 55, 4220, 4222, acl.acl_index,
5113 [VppGbpContractRule(
5114 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5115 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5118 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5119 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5121 [ETH_P_IP, ETH_P_IPV6])
5125 # ping from host in local to remote external subnets
5127 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
5129 IP(src="10.220.0.1", dst="10.222.0.1") /
5130 UDP(sport=1234, dport=1234) /
5133 rxs = self.send_and_expect(self.pg0, p * 3, self.pg7)
5136 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
5137 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
5138 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
5139 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
5140 self.assertEqual(rx[VXLAN].vni, 445)
5141 self.assertTrue(rx[VXLAN].flags.G)
5142 self.assertTrue(rx[VXLAN].flags.Instance)
5143 # the sclass of the ext-net the packet came from
5144 self.assertEqual(rx[VXLAN].gpid, 4220)
5145 # policy was applied to the original IP packet
5146 self.assertTrue(rx[VXLAN].gpflags.A)
5147 # since it's an external host the reciever should not learn it
5148 self.assertTrue(rx[VXLAN].gpflags.D)
5149 inner = rx[VXLAN].payload
5150 self.assertEqual(inner[Ether].dst, "00:0c:0c:0c:0c:0c")
5151 self.assertEqual(inner[IP].src, "10.220.0.1")
5152 self.assertEqual(inner[IP].dst, "10.222.0.1")
5155 # make the external subnet ECMP
5157 vx_tun_r2 = VppVxlanGbpTunnel(
5158 self, self.pg7.local_ip4,
5159 self.pg7.remote_ip4, 446,
5160 mode=(VppEnum.vl_api_vxlan_gbp_api_tunnel_mode_t.
5161 VXLAN_GBP_API_TUNNEL_MODE_L3))
5162 vx_tun_r2.add_vpp_config()
5163 VppIpInterfaceBind(self, vx_tun_r2, t4).add_vpp_config()
5165 self.logger.info(self.vapi.cli("sh vxlan-gbp tunnel"))
5167 n2 = VppNeighbor(self,
5168 vx_tun_r2.sw_if_index,
5169 "00:0c:0c:0c:0c:0c",
5170 self.pg7.remote_ip4)
5173 ip_222.modify([VppRoutePath(self.pg7.remote_ip4,
5174 vx_tun_r1.sw_if_index),
5175 VppRoutePath(self.pg7.remote_ip4,
5176 vx_tun_r2.sw_if_index)])
5179 # now expect load-balance
5181 p = [(Ether(src=eep1.mac, dst=str(self.router_mac)) /
5183 IP(src="10.220.0.1", dst="10.222.0.1") /
5184 UDP(sport=1234, dport=1234) /
5185 Raw(b'\xa5' * 100)),
5186 (Ether(src=eep1.mac, dst=str(self.router_mac)) /
5188 IP(src="10.220.0.1", dst="10.222.0.1") /
5189 UDP(sport=1222, dport=1235) /
5190 Raw(b'\xa5' * 100))]
5192 rxs = self.send_and_expect(self.pg0, p, self.pg7)
5194 self.assertEqual(rxs[0][VXLAN].vni, 445)
5195 self.assertEqual(rxs[1][VXLAN].vni, 446)
5198 # Same LB test for v6
5200 n3 = VppNeighbor(self,
5201 vx_tun_r1.sw_if_index,
5202 "00:0c:0c:0c:0c:0c",
5203 self.pg7.remote_ip6)
5205 n4 = VppNeighbor(self,
5206 vx_tun_r2.sw_if_index,
5207 "00:0c:0c:0c:0c:0c",
5208 self.pg7.remote_ip6)
5211 ip_222_6 = VppIpRoute(self, "10:222::", 64,
5212 [VppRoutePath(self.pg7.remote_ip6,
5213 vx_tun_r1.sw_if_index),
5214 VppRoutePath(self.pg7.remote_ip6,
5215 vx_tun_r2.sw_if_index)],
5216 table_id=t6.table_id)
5217 ip_222_6.add_vpp_config()
5219 l3o_222_6 = VppGbpSubnet(
5220 self, rd1, "10:222::", 64,
5221 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
5223 l3o_222_6.add_vpp_config()
5225 p = [(Ether(src=eep1.mac, dst=str(self.router_mac)) /
5227 IPv6(src="10:220::1", dst="10:222::1") /
5228 UDP(sport=1234, dport=1234) /
5229 Raw(b'\xa5' * 100)),
5230 (Ether(src=eep1.mac, dst=str(self.router_mac)) /
5232 IPv6(src="10:220::1", dst="10:222::1") /
5233 UDP(sport=7777, dport=8881) /
5234 Raw(b'\xa5' * 100))]
5236 self.logger.info(self.vapi.cli("sh ip6 fib 10:222::1"))
5237 rxs = self.send_and_expect(self.pg0, p, self.pg7)
5239 self.assertEqual(rxs[0][VXLAN].vni, 445)
5240 self.assertEqual(rxs[1][VXLAN].vni, 446)
5243 # ping from host in remote to local external subnets
5244 # there's no contract for this, but the A bit is set.
5246 p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
5247 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
5248 UDP(sport=1234, dport=48879) /
5249 VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
5250 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
5251 IP(src="10.222.0.1", dst="10.220.0.1") /
5252 UDP(sport=1234, dport=1234) /
5255 rxs = self.send_and_expect(self.pg7, p * 3, self.pg0)
5256 self.assertFalse(find_gbp_endpoint(self, ip="10.222.0.1"))
5259 # ping from host in remote to remote external subnets
5260 # this is dropped by reflection check.
5262 p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
5263 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
5264 UDP(sport=1234, dport=48879) /
5265 VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
5266 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
5267 IP(src="10.222.0.1", dst="10.222.0.2") /
5268 UDP(sport=1234, dport=1234) /
5271 rxs = self.send_and_assert_no_replies(self.pg7, p * 3)
5273 p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
5274 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
5275 UDP(sport=1234, dport=48879) /
5276 VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
5277 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
5278 IPv6(src="10:222::1", dst="10:222::2") /
5279 UDP(sport=1234, dport=1234) /
5282 rxs = self.send_and_assert_no_replies(self.pg7, p * 3)
5287 lep1 = VppGbpEndpoint(self, vlan_144,
5289 "10.0.0.44", "11.0.0.44",
5290 "2001:10::44", "3001::44")
5291 lep1.add_vpp_config()
5294 # local EP to local ip4 external subnet
5296 p = (Ether(src=lep1.mac, dst=str(self.router_mac)) /
5298 IP(src=lep1.ip4, dst="10.220.0.1") /
5299 UDP(sport=1234, dport=1234) /
5302 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
5305 self.assertEqual(rx[Ether].src, str(self.router_mac))
5306 self.assertEqual(rx[Ether].dst, eep1.mac)
5307 self.assertEqual(rx[Dot1Q].vlan, 100)
5310 # local EP to local ip6 external subnet
5312 p = (Ether(src=lep1.mac, dst=str(self.router_mac)) /
5314 IPv6(src=lep1.ip6, dst="10:220::1") /
5315 UDP(sport=1234, dport=1234) /
5318 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
5321 self.assertEqual(rx[Ether].src, str(self.router_mac))
5322 self.assertEqual(rx[Ether].dst, eep1.mac)
5323 self.assertEqual(rx[Dot1Q].vlan, 100)
5326 # ip4 and ip6 subnets that load-balance
5328 ip_20 = VppIpRoute(self, "10.20.0.0", 24,
5329 [VppRoutePath(eep1.ip4,
5330 eep1.epg.bvi.sw_if_index),
5331 VppRoutePath(eep2.ip4,
5332 eep2.epg.bvi.sw_if_index)],
5333 table_id=t4.table_id)
5334 ip_20.add_vpp_config()
5336 l3o_20 = VppGbpSubnet(
5337 self, rd1, "10.20.0.0", 24,
5338 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
5340 l3o_20.add_vpp_config()
5342 ip6_20 = VppIpRoute(self, "10:20::", 64,
5343 [VppRoutePath(eep1.ip6,
5344 eep1.epg.bvi.sw_if_index),
5345 VppRoutePath(eep2.ip6,
5346 eep2.epg.bvi.sw_if_index)],
5347 table_id=t6.table_id)
5348 ip6_20.add_vpp_config()
5350 l3o6_20 = VppGbpSubnet(
5351 self, rd1, "10:20::", 64,
5352 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
5354 l3o6_20.add_vpp_config()
5356 self.logger.info(self.vapi.cli("sh ip fib 10.20.0.1"))
5357 self.logger.info(self.vapi.cli("sh ip6 fib 10:20::1"))
5359 # two ip6 packets whose port are chosen so they load-balance
5360 p = [(Ether(src=lep1.mac, dst=str(self.router_mac)) /
5362 IPv6(src=lep1.ip6, dst="10:20::1") /
5363 UDP(sport=1234, dport=1234) /
5364 Raw(b'\xa5' * 100)),
5365 (Ether(src=lep1.mac, dst=str(self.router_mac)) /
5367 IPv6(src=lep1.ip6, dst="10:20::1") /
5368 UDP(sport=124, dport=1230) /
5369 Raw(b'\xa5' * 100))]
5371 rxs = self.send_and_expect(self.pg0, p, self.pg0, 2)
5373 self.assertEqual(rxs[0][Dot1Q].vlan, 101)
5374 self.assertEqual(rxs[1][Dot1Q].vlan, 100)
5376 # two ip4 packets whose port are chosen so they load-balance
5377 p = [(Ether(src=lep1.mac, dst=str(self.router_mac)) /
5379 IP(src=lep1.ip4, dst="10.20.0.1") /
5380 UDP(sport=1235, dport=1235) /
5381 Raw(b'\xa5' * 100)),
5382 (Ether(src=lep1.mac, dst=str(self.router_mac)) /
5384 IP(src=lep1.ip4, dst="10.20.0.1") /
5385 UDP(sport=124, dport=1230) /
5386 Raw(b'\xa5' * 100))]
5388 rxs = self.send_and_expect(self.pg0, p, self.pg0, 2)
5390 self.assertEqual(rxs[0][Dot1Q].vlan, 101)
5391 self.assertEqual(rxs[1][Dot1Q].vlan, 100)
5396 ip_222.remove_vpp_config()
5397 self.pg7.unconfig_ip4()
5398 self.vlan_101.set_vtr(L2_VTR_OP.L2_DISABLED)
5399 self.vlan_100.set_vtr(L2_VTR_OP.L2_DISABLED)
5401 def test_gbp_anon_l3_out(self):
5402 """ GBP Anonymous L3 Out """
5404 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
5405 self.vapi.cli("set logging class gbp level debug")
5407 routed_dst_mac = "00:0c:0c:0c:0c:0c"
5408 routed_src_mac = "00:22:bd:f8:19:ff"
5413 t4 = VppIpTable(self, 1)
5415 t6 = VppIpTable(self, 1, True)
5418 rd1 = VppGbpRouteDomain(self, 2, 55, t4, t6)
5419 rd1.add_vpp_config()
5421 self.loop0.set_mac(self.router_mac)
5424 # Bind the BVI to the RD
5426 bind_l0_ip4 = VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
5427 bind_l0_ip6 = VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
5430 # Pg7 hosts a BD's BUM
5431 # Pg1 some other l3 interface
5433 self.pg7.config_ip4()
5434 self.pg7.resolve_arp()
5437 # a GBP external bridge domains for the EPs
5439 bd1 = VppBridgeDomain(self, 1)
5440 bd1.add_vpp_config()
5441 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0, None, None)
5442 gbd1.add_vpp_config()
5445 # The Endpoint-groups in which the external endpoints exist
5447 epg_220 = VppGbpEndpointGroup(self, 220, 113, rd1, gbd1,
5451 VppGbpEndpointRetention(4))
5452 epg_220.add_vpp_config()
5454 # the BVIs have the subnet applied ...
5455 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi,
5457 bind=bind_l0_ip4).add_vpp_config()
5459 # ... which is an Anonymous L3-out subnets
5460 l3o_1 = VppGbpSubnet(
5461 self, rd1, "10.0.0.0", 24,
5462 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_ANON_L3_OUT,
5464 l3o_1.add_vpp_config()
5467 # an external interface attached to the outside world and the
5470 VppL2Vtr(self, self.vlan_100, L2_VTR_OP.L2_POP_1).add_vpp_config()
5471 VppL2Vtr(self, self.vlan_101, L2_VTR_OP.L2_POP_1).add_vpp_config()
5474 # vlan_100 and vlan_101 are anonymous l3-out interfaces
5476 ext_itf = VppGbpExtItf(self, self.vlan_100, bd1, rd1, anon=True)
5477 ext_itf.add_vpp_config()
5478 ext_itf = VppGbpExtItf(self, self.vlan_101, bd1, rd1, anon=True)
5479 ext_itf.add_vpp_config()
5482 # an unicast vxlan-gbp for inter-RD traffic
5484 vx_tun_l3 = VppGbpVxlanTunnel(
5485 self, 444, rd1.rd_id,
5486 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
5488 vx_tun_l3.add_vpp_config()
5491 # A remote external endpoint
5493 rep = VppGbpEndpoint(self, vx_tun_l3,
5495 "10.0.0.201", "11.0.0.201",
5496 "2001:10::201", "3001::101",
5497 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
5499 self.pg7.remote_ip4,
5501 rep.add_vpp_config()
5504 # ARP packet from host in external subnet are accepted, flooded and
5505 # replied to. We expect 2 packets:
5506 # - APR request flooded over the other vlan subif
5507 # - ARP reply from BVI
5509 p_arp = (Ether(src=self.vlan_100.remote_mac,
5510 dst="ff:ff:ff:ff:ff:ff") /
5515 hwsrc=self.vlan_100.remote_mac,
5516 hwdst="ff:ff:ff:ff:ff:ff"))
5517 rxs = self.send_and_expect(self.pg0, p_arp * 1, self.pg0, n_rx=2)
5519 p_arp = (Ether(src=self.vlan_101.remote_mac,
5520 dst="ff:ff:ff:ff:ff:ff") /
5525 hwsrc=self.vlan_101.remote_mac,
5526 hwdst="ff:ff:ff:ff:ff:ff"))
5527 rxs = self.send_and_expect(self.pg0, p_arp * 1, self.pg0, n_rx=2)
5530 # remote to external
5532 p = (Ether(src=self.pg7.remote_mac,
5533 dst=self.pg7.local_mac) /
5534 IP(src=self.pg7.remote_ip4,
5535 dst=self.pg7.local_ip4) /
5536 UDP(sport=1234, dport=48879) /
5537 VXLAN(vni=vx_tun_l3.vni, gpid=epg_220.sclass, flags=0x88) /
5538 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
5539 IP(src=str(rep.ip4), dst="10.0.0.100") /
5540 UDP(sport=1234, dport=1234) /
5542 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
5545 # local EP pings router
5547 p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
5549 IP(src="10.0.0.100", dst="10.0.0.128") /
5550 ICMP(type='echo-request'))
5551 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
5554 self.assertEqual(rx[Ether].src, str(self.router_mac))
5555 self.assertEqual(rx[Ether].dst, self.vlan_100.remote_mac)
5556 self.assertEqual(rx[Dot1Q].vlan, 100)
5559 # local EP pings other local EP
5561 p = (Ether(src=self.vlan_100.remote_mac,
5562 dst=self.vlan_101.remote_mac) /
5564 IP(src="10.0.0.100", dst="10.0.0.101") /
5565 ICMP(type='echo-request'))
5566 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
5569 self.assertEqual(rx[Ether].src, self.vlan_100.remote_mac)
5570 self.assertEqual(rx[Ether].dst, self.vlan_101.remote_mac)
5571 self.assertEqual(rx[Dot1Q].vlan, 101)
5574 # A subnet reachable through an external router on vlan 100
5576 ip_220 = VppIpRoute(self, "10.220.0.0", 24,
5577 [VppRoutePath("10.0.0.100",
5578 epg_220.bvi.sw_if_index)],
5579 table_id=t4.table_id)
5580 ip_220.add_vpp_config()
5582 l3o_220 = VppGbpSubnet(
5583 self, rd1, "10.220.0.0", 24,
5584 # note: this a "regular" L3 out subnet (not connected)
5585 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
5587 l3o_220.add_vpp_config()
5590 # A subnet reachable through an external router on vlan 101
5592 ip_221 = VppIpRoute(self, "10.221.0.0", 24,
5593 [VppRoutePath("10.0.0.101",
5594 epg_220.bvi.sw_if_index)],
5595 table_id=t4.table_id)
5596 ip_221.add_vpp_config()
5598 l3o_221 = VppGbpSubnet(
5599 self, rd1, "10.221.0.0", 24,
5600 # note: this a "regular" L3 out subnet (not connected)
5601 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
5603 l3o_221.add_vpp_config()
5606 # ping between hosts in remote subnets
5607 # dropped without a contract
5609 p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
5611 IP(src="10.220.0.1", dst="10.221.0.1") /
5612 ICMP(type='echo-request'))
5614 rxs = self.send_and_assert_no_replies(self.pg0, p * 1)
5617 # contract for the external nets to communicate
5619 rule4 = AclRule(is_permit=1, proto=17)
5620 rule6 = AclRule(src_prefix=IPv6Network((0, 0)),
5621 dst_prefix=IPv6Network((0, 0)), is_permit=1, proto=17)
5622 acl = VppAcl(self, rules=[rule4, rule6])
5623 acl.add_vpp_config()
5625 c1 = VppGbpContract(
5626 self, 55, 4220, 4221, acl.acl_index,
5627 [VppGbpContractRule(
5628 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5629 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5632 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5633 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5635 [ETH_P_IP, ETH_P_IPV6])
5639 # Contracts allowing ext-net 200 to talk with external EPs
5641 c2 = VppGbpContract(
5642 self, 55, 4220, 113, acl.acl_index,
5643 [VppGbpContractRule(
5644 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5645 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5648 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5649 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5651 [ETH_P_IP, ETH_P_IPV6])
5653 c3 = VppGbpContract(
5654 self, 55, 113, 4220, acl.acl_index,
5655 [VppGbpContractRule(
5656 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5657 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5660 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5661 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5663 [ETH_P_IP, ETH_P_IPV6])
5667 # ping between hosts in remote subnets
5669 p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
5671 IP(src="10.220.0.1", dst="10.221.0.1") /
5672 UDP(sport=1234, dport=1234) /
5675 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
5678 self.assertEqual(rx[Ether].src, str(self.router_mac))
5679 self.assertEqual(rx[Ether].dst, self.vlan_101.remote_mac)
5680 self.assertEqual(rx[Dot1Q].vlan, 101)
5682 # we did not learn these external hosts
5683 self.assertFalse(find_gbp_endpoint(self, ip="10.220.0.1"))
5684 self.assertFalse(find_gbp_endpoint(self, ip="10.221.0.1"))
5687 # from remote external EP to local external EP
5689 p = (Ether(src=self.pg7.remote_mac,
5690 dst=self.pg7.local_mac) /
5691 IP(src=self.pg7.remote_ip4,
5692 dst=self.pg7.local_ip4) /
5693 UDP(sport=1234, dport=48879) /
5694 VXLAN(vni=444, gpid=113, flags=0x88) /
5695 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
5696 IP(src=rep.ip4, dst="10.220.0.1") /
5697 UDP(sport=1234, dport=1234) /
5700 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
5703 # ping from an external host to the remote external EP
5705 p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
5707 IP(src="10.220.0.1", dst=rep.ip4) /
5708 UDP(sport=1234, dport=1234) /
5711 rxs = self.send_and_expect(self.pg0, p * 1, self.pg7)
5714 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
5715 # self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
5716 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
5717 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
5718 self.assertEqual(rx[VXLAN].vni, 444)
5719 self.assertTrue(rx[VXLAN].flags.G)
5720 self.assertTrue(rx[VXLAN].flags.Instance)
5721 # the sclass of the ext-net the packet came from
5722 self.assertEqual(rx[VXLAN].gpid, 4220)
5723 # policy was applied to the original IP packet
5724 self.assertTrue(rx[VXLAN].gpflags.A)
5725 # since it's an external host the reciever should not learn it
5726 self.assertTrue(rx[VXLAN].gpflags.D)
5727 inner = rx[VXLAN].payload
5728 self.assertEqual(inner[IP].src, "10.220.0.1")
5729 self.assertEqual(inner[IP].dst, rep.ip4)
5732 # An external subnet reachable via the remote external EP
5736 # first the VXLAN-GBP tunnel over which it is reached
5738 vx_tun_r = VppVxlanGbpTunnel(
5739 self, self.pg7.local_ip4,
5740 self.pg7.remote_ip4, 445,
5741 mode=(VppEnum.vl_api_vxlan_gbp_api_tunnel_mode_t.
5742 VXLAN_GBP_API_TUNNEL_MODE_L3))
5743 vx_tun_r.add_vpp_config()
5744 VppIpInterfaceBind(self, vx_tun_r, t4).add_vpp_config()
5746 self.logger.info(self.vapi.cli("sh vxlan-gbp tunnel"))
5749 # then the special adj to resolve through on that tunnel
5751 n1 = VppNeighbor(self,
5752 vx_tun_r.sw_if_index,
5753 "00:0c:0c:0c:0c:0c",
5754 self.pg7.remote_ip4)
5758 # the route via the adj above
5760 ip_222 = VppIpRoute(self, "10.222.0.0", 24,
5761 [VppRoutePath(self.pg7.remote_ip4,
5762 vx_tun_r.sw_if_index)],
5763 table_id=t4.table_id)
5764 ip_222.add_vpp_config()
5766 l3o_222 = VppGbpSubnet(
5767 self, rd1, "10.222.0.0", 24,
5768 # note: this a "regular" l3out subnet (not connected)
5769 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
5771 l3o_222.add_vpp_config()
5774 # ping between hosts in local and remote external subnets
5775 # dropped without a contract
5777 p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
5779 IP(src="10.220.0.1", dst="10.222.0.1") /
5780 UDP(sport=1234, dport=1234) /
5783 rxs = self.send_and_assert_no_replies(self.pg0, p * 1)
5786 # Add contracts ext-nets for 220 -> 222
5788 c4 = VppGbpContract(
5789 self, 55, 4220, 4222, acl.acl_index,
5790 [VppGbpContractRule(
5791 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5792 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5795 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5796 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5798 [ETH_P_IP, ETH_P_IPV6])
5802 # ping from host in local to remote external subnets
5804 p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
5806 IP(src="10.220.0.1", dst="10.222.0.1") /
5807 UDP(sport=1234, dport=1234) /
5810 rxs = self.send_and_expect(self.pg0, p * 3, self.pg7)
5813 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
5814 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
5815 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
5816 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
5817 self.assertEqual(rx[VXLAN].vni, 445)
5818 self.assertTrue(rx[VXLAN].flags.G)
5819 self.assertTrue(rx[VXLAN].flags.Instance)
5820 # the sclass of the ext-net the packet came from
5821 self.assertEqual(rx[VXLAN].gpid, 4220)
5822 # policy was applied to the original IP packet
5823 self.assertTrue(rx[VXLAN].gpflags.A)
5824 # since it's an external host the reciever should not learn it
5825 self.assertTrue(rx[VXLAN].gpflags.D)
5826 inner = rx[VXLAN].payload
5827 self.assertEqual(inner[Ether].dst, "00:0c:0c:0c:0c:0c")
5828 self.assertEqual(inner[IP].src, "10.220.0.1")
5829 self.assertEqual(inner[IP].dst, "10.222.0.1")
5832 # ping from host in remote to local external subnets
5833 # there's no contract for this, but the A bit is set.
5835 p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
5836 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
5837 UDP(sport=1234, dport=48879) /
5838 VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
5839 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
5840 IP(src="10.222.0.1", dst="10.220.0.1") /
5841 UDP(sport=1234, dport=1234) /
5844 rxs = self.send_and_expect(self.pg7, p * 3, self.pg0)
5845 self.assertFalse(find_gbp_endpoint(self, ip="10.222.0.1"))
5848 # ping from host in remote to remote external subnets
5849 # this is dropped by reflection check.
5851 p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
5852 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
5853 UDP(sport=1234, dport=48879) /
5854 VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
5855 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
5856 IP(src="10.222.0.1", dst="10.222.0.2") /
5857 UDP(sport=1234, dport=1234) /
5860 rxs = self.send_and_assert_no_replies(self.pg7, p * 3)
5865 self.vlan_101.set_vtr(L2_VTR_OP.L2_DISABLED)
5866 self.vlan_100.set_vtr(L2_VTR_OP.L2_DISABLED)
5867 self.pg7.unconfig_ip4()
5868 # make sure the programmed EP is no longer learnt from DP
5869 self.wait_for_ep_timeout(sw_if_index=rep.itf.sw_if_index, ip=rep.ip4)
5872 if __name__ == '__main__':
5873 unittest.main(testRunner=VppTestRunner)