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)
836 self.vapi.nat66_plugin_enable_disable(enable=1)
839 # Config related to each of the EPGs
842 # IP config on the BVI interfaces
843 if epg != epgs[1] and epg != epgs[4]:
844 b4 = VppIpInterfaceBind(self, epg.bvi,
845 epg.rd.t4).add_vpp_config()
846 b6 = VppIpInterfaceBind(self, epg.bvi,
847 epg.rd.t6).add_vpp_config()
848 epg.bvi.set_mac(self.router_mac)
850 # The BVIs are NAT inside interfaces
851 flags = self.nat_config_flags.NAT_IS_INSIDE
852 self.vapi.nat44_interface_add_del_feature(
853 sw_if_index=epg.bvi.sw_if_index,
854 flags=flags, is_add=1)
855 self.vapi.nat66_add_del_interface(
856 sw_if_index=epg.bvi.sw_if_index,
857 flags=flags, is_add=1)
859 if_ip4 = VppIpInterfaceAddress(self, epg.bvi,
861 bind=b4).add_vpp_config()
862 if_ip6 = VppIpInterfaceAddress(self, epg.bvi,
864 bind=b6).add_vpp_config()
866 # EPG uplink interfaces in the RD
867 VppIpInterfaceBind(self, epg.uplink, epg.rd.t4).add_vpp_config()
868 VppIpInterfaceBind(self, epg.uplink, epg.rd.t6).add_vpp_config()
870 # add the BD ARP termination entry for BVI IP
871 epg.bd_arp_ip4 = VppBridgeDomainArpEntry(self, epg.bd.bd,
872 str(self.router_mac),
874 epg.bd_arp_ip6 = VppBridgeDomainArpEntry(self, epg.bd.bd,
875 str(self.router_mac),
877 epg.bd_arp_ip4.add_vpp_config()
878 epg.bd_arp_ip6.add_vpp_config()
883 for recirc in recircs:
884 # EPG's ingress recirculation interface maps to its RD
885 VppIpInterfaceBind(self, recirc.recirc,
886 recirc.epg.rd.t4).add_vpp_config()
887 VppIpInterfaceBind(self, recirc.recirc,
888 recirc.epg.rd.t6).add_vpp_config()
890 self.vapi.nat44_interface_add_del_feature(
891 sw_if_index=recirc.recirc.sw_if_index, is_add=1)
892 self.vapi.nat66_add_del_interface(
893 sw_if_index=recirc.recirc.sw_if_index, is_add=1)
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))
1286 # remove both contracts, traffic stops in both directions
1288 c2.remove_vpp_config()
1289 c1.remove_vpp_config()
1290 c3.remove_vpp_config()
1291 acl.remove_vpp_config()
1293 self.send_and_assert_no_replies(eps[2].itf,
1294 pkt_inter_epg_221_to_220 * NUM_PKTS)
1295 self.send_and_assert_no_replies(eps[0].itf,
1296 pkt_inter_epg_220_to_221 * NUM_PKTS)
1297 self.send_and_expect_bridged(eps[0].itf,
1298 pkt_intra_epg * NUM_PKTS,
1302 # EPs to the outside world
1305 # in the EP's RD an external subnet via the NAT EPG's recirc
1307 self, rd0, "0.0.0.0", 0,
1308 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1309 sw_if_index=recirc_nat.recirc.sw_if_index,
1310 sclass=epg_nat.sclass)
1312 self, rd0, "11.0.0.0", 8,
1313 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1314 sw_if_index=recirc_nat.recirc.sw_if_index,
1315 sclass=epg_nat.sclass)
1316 se16 = VppGbpSubnet(
1318 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1319 sw_if_index=recirc_nat.recirc.sw_if_index,
1320 sclass=epg_nat.sclass)
1321 # in the NAT RD an external subnet via the NAT EPG's uplink
1323 self, rd20, "0.0.0.0", 0,
1324 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1325 sw_if_index=epg_nat.uplink.sw_if_index,
1326 sclass=epg_nat.sclass)
1327 se36 = VppGbpSubnet(
1328 self, rd20, "::", 0,
1329 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1330 sw_if_index=epg_nat.uplink.sw_if_index,
1331 sclass=epg_nat.sclass)
1333 self, rd20, "11.0.0.0", 8,
1334 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1335 sw_if_index=epg_nat.uplink.sw_if_index,
1336 sclass=epg_nat.sclass)
1337 se1.add_vpp_config()
1338 se2.add_vpp_config()
1339 se16.add_vpp_config()
1340 se3.add_vpp_config()
1341 se36.add_vpp_config()
1342 se4.add_vpp_config()
1344 self.logger.info(self.vapi.cli("sh ip fib 0.0.0.0/0"))
1345 self.logger.info(self.vapi.cli("sh ip fib 11.0.0.1"))
1346 self.logger.info(self.vapi.cli("sh ip6 fib ::/0"))
1347 self.logger.info(self.vapi.cli("sh ip6 fib %s" %
1351 # From an EP to an outside address: IN2OUT
1353 pkt_inter_epg_220_to_global = (Ether(src=self.pg0.remote_mac,
1354 dst=str(self.router_mac)) /
1357 UDP(sport=1234, dport=1234) /
1361 self.send_and_assert_no_replies(eps[0].itf,
1362 pkt_inter_epg_220_to_global * NUM_PKTS)
1363 rule = AclRule(is_permit=1, proto=17, ports=1234)
1364 rule2 = AclRule(is_permit=1, proto=17, ports=1234,
1365 src_prefix=IPv6Network((0, 0)),
1366 dst_prefix=IPv6Network((0, 0)))
1367 acl2 = VppAcl(self, rules=[rule, rule2])
1368 acl2.add_vpp_config()
1370 c4 = VppGbpContract(
1371 self, 400, epgs[0].sclass, epgs[3].sclass, acl2.acl_index,
1372 [VppGbpContractRule(
1373 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1374 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1377 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1378 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1380 [ETH_P_IP, ETH_P_IPV6])
1383 self.send_and_expect_natted(eps[0].itf,
1384 pkt_inter_epg_220_to_global * NUM_PKTS,
1388 pkt_inter_epg_220_to_global = (Ether(src=self.pg0.remote_mac,
1389 dst=str(self.router_mac)) /
1390 IPv6(src=eps[0].ip6,
1392 UDP(sport=1234, dport=1234) /
1395 self.send_and_expect_natted6(self.pg0,
1396 pkt_inter_epg_220_to_global * NUM_PKTS,
1400 # From a global address to an EP: OUT2IN
1402 pkt_inter_epg_220_from_global = (Ether(src=str(self.router_mac),
1403 dst=self.pg0.remote_mac) /
1406 UDP(sport=1234, dport=1234) /
1409 self.send_and_assert_no_replies(
1410 self.pg7, pkt_inter_epg_220_from_global * NUM_PKTS)
1412 c5 = VppGbpContract(
1413 self, 400, epgs[3].sclass, epgs[0].sclass, acl2.acl_index,
1414 [VppGbpContractRule(
1415 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1416 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1419 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1420 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1422 [ETH_P_IP, ETH_P_IPV6])
1425 self.send_and_expect_unnatted(self.pg7,
1426 pkt_inter_epg_220_from_global * NUM_PKTS,
1430 pkt_inter_epg_220_from_global = (Ether(src=str(self.router_mac),
1431 dst=self.pg0.remote_mac) /
1432 IPv6(dst=eps[0].fip6,
1434 UDP(sport=1234, dport=1234) /
1437 self.send_and_expect_unnatted6(
1439 pkt_inter_epg_220_from_global * NUM_PKTS,
1444 # From a local VM to another local VM using resp. public addresses:
1447 pkt_intra_epg_220_global = (Ether(src=self.pg0.remote_mac,
1448 dst=str(self.router_mac)) /
1451 UDP(sport=1234, dport=1234) /
1454 self.send_and_expect_double_natted(eps[0].itf,
1455 pkt_intra_epg_220_global * NUM_PKTS,
1460 pkt_intra_epg_220_global = (Ether(src=self.pg0.remote_mac,
1461 dst=str(self.router_mac)) /
1462 IPv6(src=eps[0].ip6,
1464 UDP(sport=1234, dport=1234) /
1467 self.send_and_expect_double_natted6(
1469 pkt_intra_epg_220_global * NUM_PKTS,
1477 self.vapi.nat44_ed_plugin_enable_disable(enable=0)
1478 self.vapi.nat66_plugin_enable_disable(enable=0)
1480 def wait_for_ep_timeout(self, sw_if_index=None, ip=None, mac=None,
1481 tep=None, n_tries=100, s_time=1):
1482 # only learnt EP can timeout
1483 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
1484 flags = ep_flags.GBP_API_ENDPOINT_FLAG_LEARNT
1486 if not find_gbp_endpoint(self, sw_if_index, ip, mac, tep=tep,
1489 n_tries = n_tries - 1
1491 self.assertFalse(find_gbp_endpoint(self, sw_if_index, ip, mac, tep=tep,
1495 def test_gbp_learn_l2(self):
1496 """ GBP L2 Endpoint Learning """
1498 drop_no_contract = self.statistics.get_err_counter(
1499 '/err/gbp-policy-port/drop-no-contract')
1500 allow_intra_class = self.statistics.get_err_counter(
1501 '/err/gbp-policy-port/allow-intra-sclass')
1503 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
1504 learnt = [{'mac': '00:00:11:11:11:01',
1506 'ip6': '2001:10::2'},
1507 {'mac': '00:00:11:11:11:02',
1509 'ip6': '2001:10::3'}]
1514 gt4 = VppIpTable(self, 1)
1515 gt4.add_vpp_config()
1516 gt6 = VppIpTable(self, 1, is_ip6=True)
1517 gt6.add_vpp_config()
1519 rd1 = VppGbpRouteDomain(self, 1, 401, gt4, gt6)
1520 rd1.add_vpp_config()
1523 # Pg2 hosts the vxlan tunnel, hosts on pg2 to act as TEPs
1524 # Pg3 hosts the IP4 UU-flood VXLAN tunnel
1525 # Pg4 hosts the IP6 UU-flood VXLAN tunnel
1527 self.pg2.config_ip4()
1528 self.pg2.resolve_arp()
1529 self.pg2.generate_remote_hosts(4)
1530 self.pg2.configure_ipv4_neighbors()
1531 self.pg3.config_ip4()
1532 self.pg3.resolve_arp()
1533 self.pg4.config_ip4()
1534 self.pg4.resolve_arp()
1537 # Add a mcast destination VXLAN-GBP tunnel for B&M traffic
1539 tun_bm = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
1542 tun_bm.add_vpp_config()
1545 # a GBP bridge domain with a BVI and a UU-flood interface
1547 bd1 = VppBridgeDomain(self, 1)
1548 bd1.add_vpp_config()
1549 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0,
1551 gbd1.add_vpp_config()
1553 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1554 self.logger.info(self.vapi.cli("sh gbp bridge"))
1556 # ... and has a /32 applied
1557 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
1558 ip_addr.add_vpp_config()
1561 # The Endpoint-group in which we are learning endpoints
1563 epg_220 = VppGbpEndpointGroup(self, 220, 112, rd1, gbd1,
1567 VppGbpEndpointRetention(4))
1568 epg_220.add_vpp_config()
1569 epg_330 = VppGbpEndpointGroup(self, 330, 113, rd1, gbd1,
1573 VppGbpEndpointRetention(4))
1574 epg_330.add_vpp_config()
1577 # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
1580 vx_tun_l2_1 = VppGbpVxlanTunnel(
1581 self, 99, bd1.bd_id,
1582 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L2,
1584 vx_tun_l2_1.add_vpp_config()
1587 # A static endpoint that the learnt endpoints are trying to
1590 ep = VppGbpEndpoint(self, self.pg0,
1592 "10.0.0.127", "11.0.0.127",
1593 "2001:10::1", "3001::1")
1596 self.assertTrue(find_route(self, ep.ip4, 32, table_id=1))
1598 # a packet with an sclass from an unknown EPG
1599 p = (Ether(src=self.pg2.remote_mac,
1600 dst=self.pg2.local_mac) /
1601 IP(src=self.pg2.remote_hosts[0].ip4,
1602 dst=self.pg2.local_ip4) /
1603 UDP(sport=1234, dport=48879) /
1604 VXLAN(vni=99, gpid=88, flags=0x88) /
1605 Ether(src=learnt[0]["mac"], dst=ep.mac) /
1606 IP(src=learnt[0]["ip"], dst=ep.ip4) /
1607 UDP(sport=1234, dport=1234) /
1610 self.send_and_assert_no_replies(self.pg2, p)
1612 self.logger.info(self.vapi.cli("sh error"))
1613 self.assert_error_counter_equal(
1614 '/err/gbp-policy-port/drop-no-contract',
1615 drop_no_contract + 1)
1618 # we should not have learnt a new tunnel endpoint, since
1619 # the EPG was not learnt.
1621 self.assertEqual(INDEX_INVALID,
1622 find_vxlan_gbp_tunnel(self,
1624 self.pg2.remote_hosts[0].ip4,
1627 # ep is not learnt, because the EPG is unknown
1628 self.assertEqual(len(self.vapi.gbp_endpoint_dump()), 1)
1631 # Learn new EPs from IP packets
1633 for ii, l in enumerate(learnt):
1634 # a packet with an sclass from a known EPG
1635 # arriving on an unknown TEP
1636 p = (Ether(src=self.pg2.remote_mac,
1637 dst=self.pg2.local_mac) /
1638 IP(src=self.pg2.remote_hosts[1].ip4,
1639 dst=self.pg2.local_ip4) /
1640 UDP(sport=1234, dport=48879) /
1641 VXLAN(vni=99, gpid=112, flags=0x88) /
1642 Ether(src=l['mac'], dst=ep.mac) /
1643 IP(src=l['ip'], dst=ep.ip4) /
1644 UDP(sport=1234, dport=1234) /
1647 rx = self.send_and_expect(self.pg2, [p], self.pg0)
1650 tep1_sw_if_index = find_vxlan_gbp_tunnel(
1653 self.pg2.remote_hosts[1].ip4,
1655 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
1658 # the EP is learnt via the learnt TEP
1659 # both from its MAC and its IP
1661 self.assertTrue(find_gbp_endpoint(self,
1662 vx_tun_l2_1.sw_if_index,
1664 self.assertTrue(find_gbp_endpoint(self,
1665 vx_tun_l2_1.sw_if_index,
1668 self.assert_error_counter_equal(
1669 '/err/gbp-policy-port/allow-intra-sclass',
1670 allow_intra_class + 2)
1672 self.logger.info(self.vapi.cli("show gbp endpoint"))
1673 self.logger.info(self.vapi.cli("show gbp vxlan"))
1674 self.logger.info(self.vapi.cli("show ip mfib"))
1677 # If we sleep for the threshold time, the learnt endpoints should
1681 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1685 # Learn new EPs from GARP packets received on the BD's mcast tunnel
1687 for ii, l in enumerate(learnt):
1688 # add some junk in the reserved field of the vxlan-header
1689 # next to the VNI. we should accept since reserved bits are
1691 p = (Ether(src=self.pg2.remote_mac,
1692 dst=self.pg2.local_mac) /
1693 IP(src=self.pg2.remote_hosts[1].ip4,
1695 UDP(sport=1234, dport=48879) /
1696 VXLAN(vni=88, reserved2=0x80, gpid=112, flags=0x88) /
1697 Ether(src=l['mac'], dst="ff:ff:ff:ff:ff:ff") /
1699 psrc=l['ip'], pdst=l['ip'],
1700 hwsrc=l['mac'], hwdst="ff:ff:ff:ff:ff:ff"))
1702 rx = self.send_and_expect(self.pg4, [p], self.pg0)
1705 tep1_sw_if_index = find_vxlan_gbp_tunnel(
1708 self.pg2.remote_hosts[1].ip4,
1710 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
1713 # the EP is learnt via the learnt TEP
1714 # both from its MAC and its IP
1716 self.assertTrue(find_gbp_endpoint(self,
1717 vx_tun_l2_1.sw_if_index,
1719 self.assertTrue(find_gbp_endpoint(self,
1720 vx_tun_l2_1.sw_if_index,
1724 # wait for the learnt endpoints to age out
1727 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1731 # Learn new EPs from L2 packets
1733 for ii, l in enumerate(learnt):
1734 # a packet with an sclass from a known EPG
1735 # arriving on an unknown TEP
1736 p = (Ether(src=self.pg2.remote_mac,
1737 dst=self.pg2.local_mac) /
1738 IP(src=self.pg2.remote_hosts[1].ip4,
1739 dst=self.pg2.local_ip4) /
1740 UDP(sport=1234, dport=48879) /
1741 VXLAN(vni=99, gpid=112, flags=0x88) /
1742 Ether(src=l['mac'], dst=ep.mac) /
1745 rx = self.send_and_expect(self.pg2, [p], self.pg0)
1748 tep1_sw_if_index = find_vxlan_gbp_tunnel(
1751 self.pg2.remote_hosts[1].ip4,
1753 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
1756 # the EP is learnt via the learnt TEP
1757 # both from its MAC and its IP
1759 self.assertTrue(find_gbp_endpoint(self,
1760 vx_tun_l2_1.sw_if_index,
1763 self.logger.info(self.vapi.cli("show gbp endpoint"))
1764 self.logger.info(self.vapi.cli("show gbp vxlan"))
1765 self.logger.info(self.vapi.cli("show vxlan-gbp tunnel"))
1768 # wait for the learnt endpoints to age out
1771 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1775 # repeat. the do not learn bit is set so the EPs are not learnt
1778 # a packet with an sclass from a known EPG
1779 p = (Ether(src=self.pg2.remote_mac,
1780 dst=self.pg2.local_mac) /
1781 IP(src=self.pg2.remote_hosts[1].ip4,
1782 dst=self.pg2.local_ip4) /
1783 UDP(sport=1234, dport=48879) /
1784 VXLAN(vni=99, gpid=112, flags=0x88, gpflags="D") /
1785 Ether(src=l['mac'], dst=ep.mac) /
1786 IP(src=l['ip'], dst=ep.ip4) /
1787 UDP(sport=1234, dport=1234) /
1790 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
1793 self.assertFalse(find_gbp_endpoint(self,
1794 vx_tun_l2_1.sw_if_index,
1801 # a packet with an sclass from a known EPG
1802 # set a reserved bit in addition to the G and I
1803 # reserved bits should not be checked on rx.
1804 p = (Ether(src=self.pg2.remote_mac,
1805 dst=self.pg2.local_mac) /
1806 IP(src=self.pg2.remote_hosts[1].ip4,
1807 dst=self.pg2.local_ip4) /
1808 UDP(sport=1234, dport=48879) /
1809 VXLAN(vni=99, gpid=112, flags=0xc8) /
1810 Ether(src=l['mac'], dst=ep.mac) /
1811 IP(src=l['ip'], dst=ep.ip4) /
1812 UDP(sport=1234, dport=1234) /
1815 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
1817 self.assertTrue(find_gbp_endpoint(self,
1818 vx_tun_l2_1.sw_if_index,
1822 # Static EP replies to dynamics
1824 self.logger.info(self.vapi.cli("sh l2fib bd_id 1"))
1826 p = (Ether(src=ep.mac, dst=l['mac']) /
1827 IP(dst=l['ip'], src=ep.ip4) /
1828 UDP(sport=1234, dport=1234) /
1831 rxs = self.send_and_expect(self.pg0, p * 17, self.pg2)
1834 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
1835 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
1836 self.assertEqual(rx[UDP].dport, 48879)
1837 # the UDP source port is a random value for hashing
1838 self.assertEqual(rx[VXLAN].gpid, 112)
1839 self.assertEqual(rx[VXLAN].vni, 99)
1840 self.assertTrue(rx[VXLAN].flags.G)
1841 self.assertTrue(rx[VXLAN].flags.Instance)
1842 self.assertTrue(rx[VXLAN].gpflags.A)
1843 self.assertFalse(rx[VXLAN].gpflags.D)
1846 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1850 # repeat in the other EPG
1851 # there's no contract between 220 and 330, but the A-bit is set
1852 # so the packet is cleared for delivery
1855 # a packet with an sclass from a known EPG
1856 p = (Ether(src=self.pg2.remote_mac,
1857 dst=self.pg2.local_mac) /
1858 IP(src=self.pg2.remote_hosts[1].ip4,
1859 dst=self.pg2.local_ip4) /
1860 UDP(sport=1234, dport=48879) /
1861 VXLAN(vni=99, gpid=113, flags=0x88, gpflags='A') /
1862 Ether(src=l['mac'], dst=ep.mac) /
1863 IP(src=l['ip'], dst=ep.ip4) /
1864 UDP(sport=1234, dport=1234) /
1867 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
1869 self.assertTrue(find_gbp_endpoint(self,
1870 vx_tun_l2_1.sw_if_index,
1874 # static EP cannot reach the learnt EPs since there is no contract
1875 # only test 1 EP as the others could timeout
1877 p = (Ether(src=ep.mac, dst=l['mac']) /
1878 IP(dst=learnt[0]['ip'], src=ep.ip4) /
1879 UDP(sport=1234, dport=1234) /
1882 self.send_and_assert_no_replies(self.pg0, [p])
1885 # refresh the entries after the check for no replies above
1888 # a packet with an sclass from a known EPG
1889 p = (Ether(src=self.pg2.remote_mac,
1890 dst=self.pg2.local_mac) /
1891 IP(src=self.pg2.remote_hosts[1].ip4,
1892 dst=self.pg2.local_ip4) /
1893 UDP(sport=1234, dport=48879) /
1894 VXLAN(vni=99, gpid=113, flags=0x88, gpflags='A') /
1895 Ether(src=l['mac'], dst=ep.mac) /
1896 IP(src=l['ip'], dst=ep.ip4) /
1897 UDP(sport=1234, dport=1234) /
1900 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
1902 self.assertTrue(find_gbp_endpoint(self,
1903 vx_tun_l2_1.sw_if_index,
1907 # Add the contract so they can talk
1909 rule = AclRule(is_permit=1, proto=17)
1910 rule2 = AclRule(src_prefix=IPv6Network((0, 0)),
1911 dst_prefix=IPv6Network((0, 0)), is_permit=1, proto=17)
1912 acl = VppAcl(self, rules=[rule, rule2])
1913 acl.add_vpp_config()
1915 c1 = VppGbpContract(
1916 self, 401, epg_220.sclass, epg_330.sclass, acl.acl_index,
1917 [VppGbpContractRule(
1918 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1919 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1922 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1923 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1925 [ETH_P_IP, ETH_P_IPV6])
1929 p = (Ether(src=ep.mac, dst=l['mac']) /
1930 IP(dst=l['ip'], src=ep.ip4) /
1931 UDP(sport=1234, dport=1234) /
1934 self.send_and_expect(self.pg0, [p], self.pg2)
1937 # send UU packets from the local EP
1939 self.logger.info(self.vapi.cli("sh gbp bridge"))
1940 self.logger.info(self.vapi.cli("sh bridge-domain 1 detail"))
1941 p_uu = (Ether(src=ep.mac, dst="00:11:11:11:11:11") /
1942 IP(dst="10.0.0.133", src=ep.ip4) /
1943 UDP(sport=1234, dport=1234) /
1945 rxs = self.send_and_expect(ep.itf, [p_uu], gbd1.uu_fwd)
1947 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1949 p_bm = (Ether(src=ep.mac, dst="ff:ff:ff:ff:ff:ff") /
1950 IP(dst="10.0.0.133", src=ep.ip4) /
1951 UDP(sport=1234, dport=1234) /
1953 rxs = self.send_and_expect_only(ep.itf, [p_bm], tun_bm.mcast_itf)
1956 self.assertEqual(rx[IP].src, self.pg4.local_ip4)
1957 self.assertEqual(rx[IP].dst, "239.1.1.1")
1958 self.assertEqual(rx[UDP].dport, 48879)
1959 # the UDP source port is a random value for hashing
1960 self.assertEqual(rx[VXLAN].gpid, 112)
1961 self.assertEqual(rx[VXLAN].vni, 88)
1962 self.assertTrue(rx[VXLAN].flags.G)
1963 self.assertTrue(rx[VXLAN].flags.Instance)
1964 self.assertFalse(rx[VXLAN].gpflags.A)
1965 self.assertFalse(rx[VXLAN].gpflags.D)
1967 rule = AclRule(is_permit=1, proto=17)
1968 rule2 = AclRule(src_prefix=IPv6Network((0, 0)),
1969 dst_prefix=IPv6Network((0, 0)), is_permit=1, proto=17)
1970 acl = VppAcl(self, rules=[rule, rule2])
1971 acl.add_vpp_config()
1973 c2 = VppGbpContract(
1974 self, 401, epg_330.sclass, epg_220.sclass, acl.acl_index,
1975 [VppGbpContractRule(
1976 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1977 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1980 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1981 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1983 [ETH_P_IP, ETH_P_IPV6])
1987 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1990 # Check v6 Endpoints learning
1993 # a packet with an sclass from a known EPG
1994 p = (Ether(src=self.pg2.remote_mac,
1995 dst=self.pg2.local_mac) /
1996 IP(src=self.pg2.remote_hosts[1].ip4,
1997 dst=self.pg2.local_ip4) /
1998 UDP(sport=1234, dport=48879) /
1999 VXLAN(vni=99, gpid=113, flags=0x88) /
2000 Ether(src=l['mac'], dst=ep.mac) /
2001 IPv6(src=l['ip6'], dst=ep.ip6) /
2002 UDP(sport=1234, dport=1234) /
2005 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
2006 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
2008 self.assertTrue(find_gbp_endpoint(
2010 vx_tun_l2_1.sw_if_index,
2012 tep=[self.pg2.local_ip4,
2013 self.pg2.remote_hosts[1].ip4]))
2015 self.logger.info(self.vapi.cli("sh int"))
2016 self.logger.info(self.vapi.cli("sh vxlan-gbp tunnel"))
2017 self.logger.info(self.vapi.cli("sh gbp vxlan"))
2018 self.logger.info(self.vapi.cli("sh gbp endpoint"))
2019 self.logger.info(self.vapi.cli("sh gbp interface"))
2022 # EP moves to a different TEP
2025 # a packet with an sclass from a known EPG
2026 p = (Ether(src=self.pg2.remote_mac,
2027 dst=self.pg2.local_mac) /
2028 IP(src=self.pg2.remote_hosts[2].ip4,
2029 dst=self.pg2.local_ip4) /
2030 UDP(sport=1234, dport=48879) /
2031 VXLAN(vni=99, gpid=113, flags=0x88) /
2032 Ether(src=l['mac'], dst=ep.mac) /
2033 IPv6(src=l['ip6'], dst=ep.ip6) /
2034 UDP(sport=1234, dport=1234) /
2037 rx = self.send_and_expect(self.pg2, p * 1, self.pg0)
2038 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
2040 self.assertTrue(find_gbp_endpoint(
2042 vx_tun_l2_1.sw_if_index,
2045 tep=[self.pg2.local_ip4,
2046 self.pg2.remote_hosts[2].ip4]))
2049 # v6 remote EP reachability
2052 p = (Ether(src=ep.mac, dst=l['mac']) /
2053 IPv6(dst=l['ip6'], src=ep.ip6) /
2054 UDP(sport=1234, dport=1234) /
2057 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
2060 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2061 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[2].ip4)
2062 self.assertEqual(rx[UDP].dport, 48879)
2063 # the UDP source port is a random value for hashing
2064 self.assertEqual(rx[VXLAN].gpid, 112)
2065 self.assertEqual(rx[VXLAN].vni, 99)
2066 self.assertTrue(rx[VXLAN].flags.G)
2067 self.assertTrue(rx[VXLAN].flags.Instance)
2068 self.assertTrue(rx[VXLAN].gpflags.A)
2069 self.assertFalse(rx[VXLAN].gpflags.D)
2070 self.assertEqual(rx[IPv6].dst, l['ip6'])
2076 # a packet with an sclass from a known EPG
2077 p = (Ether(src=self.pg2.remote_mac,
2078 dst=self.pg2.local_mac) /
2079 IP(src=self.pg2.remote_hosts[2].ip4,
2080 dst=self.pg2.local_ip4) /
2081 UDP(sport=1234, dport=48879) /
2082 VXLAN(vni=99, gpid=112, flags=0x88) /
2083 Ether(src=l['mac'], dst=ep.mac) /
2084 IPv6(src=l['ip6'], dst=ep.ip6) /
2085 UDP(sport=1234, dport=1234) /
2088 rx = self.send_and_expect(self.pg2, p * 1, self.pg0)
2089 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
2091 self.assertTrue(find_gbp_endpoint(
2093 vx_tun_l2_1.sw_if_index,
2096 tep=[self.pg2.local_ip4,
2097 self.pg2.remote_hosts[2].ip4]))
2100 # check reachability and contract intra-epg
2102 allow_intra_class = self.statistics.get_err_counter(
2103 '/err/gbp-policy-mac/allow-intra-sclass')
2106 p = (Ether(src=ep.mac, dst=l['mac']) /
2107 IPv6(dst=l['ip6'], src=ep.ip6) /
2108 UDP(sport=1234, dport=1234) /
2111 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
2114 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2115 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[2].ip4)
2116 self.assertEqual(rx[UDP].dport, 48879)
2117 self.assertEqual(rx[VXLAN].gpid, 112)
2118 self.assertEqual(rx[VXLAN].vni, 99)
2119 self.assertTrue(rx[VXLAN].flags.G)
2120 self.assertTrue(rx[VXLAN].flags.Instance)
2121 self.assertTrue(rx[VXLAN].gpflags.A)
2122 self.assertFalse(rx[VXLAN].gpflags.D)
2123 self.assertEqual(rx[IPv6].dst, l['ip6'])
2125 allow_intra_class += NUM_PKTS
2127 self.assert_error_counter_equal(
2128 '/err/gbp-policy-mac/allow-intra-sclass',
2135 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
2137 self.pg2.unconfig_ip4()
2138 self.pg3.unconfig_ip4()
2139 self.pg4.unconfig_ip4()
2141 def test_gbp_contract(self):
2142 """ GBP Contracts """
2147 gt4 = VppIpTable(self, 0)
2148 gt4.add_vpp_config()
2149 gt6 = VppIpTable(self, 0, is_ip6=True)
2150 gt6.add_vpp_config()
2152 rd0 = VppGbpRouteDomain(self, 0, 400, gt4, gt6, None, None)
2154 rd0.add_vpp_config()
2159 bd1 = VppBridgeDomain(self, 1, arp_term=0)
2160 bd2 = VppBridgeDomain(self, 2, arp_term=0)
2162 bd1.add_vpp_config()
2163 bd2.add_vpp_config()
2165 gbd1 = VppGbpBridgeDomain(self, bd1, rd0, self.loop0)
2166 gbd2 = VppGbpBridgeDomain(self, bd2, rd0, self.loop1)
2168 gbd1.add_vpp_config()
2169 gbd2.add_vpp_config()
2172 # 3 EPGs, 2 of which share a BD.
2174 epgs = [VppGbpEndpointGroup(self, 220, 1220, rd0, gbd1,
2176 "10.0.0.128", "2001:10::128"),
2177 VppGbpEndpointGroup(self, 221, 1221, rd0, gbd1,
2179 "10.0.1.128", "2001:10:1::128"),
2180 VppGbpEndpointGroup(self, 222, 1222, rd0, gbd2,
2182 "10.0.2.128", "2001:10:2::128")]
2184 # 4 end-points, 2 in the same subnet, 3 in the same BD
2186 eps = [VppGbpEndpoint(self, self.pg0,
2188 "10.0.0.1", "11.0.0.1",
2189 "2001:10::1", "3001::1"),
2190 VppGbpEndpoint(self, self.pg1,
2192 "10.0.0.2", "11.0.0.2",
2193 "2001:10::2", "3001::2"),
2194 VppGbpEndpoint(self, self.pg2,
2196 "10.0.1.1", "11.0.0.3",
2197 "2001:10:1::1", "3001::3"),
2198 VppGbpEndpoint(self, self.pg3,
2200 "10.0.2.1", "11.0.0.4",
2201 "2001:10:2::1", "3001::4")]
2204 # Config related to each of the EPGs
2207 # IP config on the BVI interfaces
2209 b4 = VppIpInterfaceBind(self, epg.bvi,
2210 epg.rd.t4).add_vpp_config()
2211 b6 = VppIpInterfaceBind(self, epg.bvi,
2212 epg.rd.t6).add_vpp_config()
2213 epg.bvi.set_mac(self.router_mac)
2215 if_ip4 = VppIpInterfaceAddress(self, epg.bvi,
2217 bind=b4).add_vpp_config()
2218 if_ip6 = VppIpInterfaceAddress(self, epg.bvi,
2220 bind=b6).add_vpp_config()
2222 # add the BD ARP termination entry for BVI IP
2223 epg.bd_arp_ip4 = VppBridgeDomainArpEntry(self, epg.bd.bd,
2224 str(self.router_mac),
2226 epg.bd_arp_ip4.add_vpp_config()
2229 epg.add_vpp_config()
2237 self.logger.info(self.vapi.cli("show gbp endpoint"))
2238 self.logger.info(self.vapi.cli("show interface"))
2239 self.logger.info(self.vapi.cli("show br"))
2242 # Intra epg allowed without contract
2244 pkt_intra_epg_220_to_220 = (Ether(src=self.pg0.remote_mac,
2245 dst=self.pg1.remote_mac) /
2248 UDP(sport=1234, dport=1234) /
2251 self.send_and_expect_bridged(self.pg0,
2252 pkt_intra_epg_220_to_220 * 65,
2255 pkt_intra_epg_220_to_220 = (Ether(src=self.pg0.remote_mac,
2256 dst=self.pg1.remote_mac) /
2257 IPv6(src=eps[0].ip6,
2259 UDP(sport=1234, dport=1234) /
2262 self.send_and_expect_bridged6(self.pg0,
2263 pkt_intra_epg_220_to_220 * 65,
2267 # Inter epg denied without contract
2269 pkt_inter_epg_220_to_221 = (Ether(src=self.pg0.remote_mac,
2270 dst=self.pg2.remote_mac) /
2273 UDP(sport=1234, dport=1234) /
2276 self.send_and_assert_no_replies(self.pg0, pkt_inter_epg_220_to_221)
2279 # A uni-directional contract from EPG 220 -> 221
2281 rule = AclRule(is_permit=1, proto=17)
2282 rule2 = AclRule(src_prefix=IPv6Network((0, 0)),
2283 dst_prefix=IPv6Network((0, 0)), is_permit=1, proto=17)
2284 rule3 = AclRule(is_permit=1, proto=1)
2285 acl = VppAcl(self, rules=[rule, rule2, rule3])
2286 acl.add_vpp_config()
2288 c1 = VppGbpContract(
2289 self, 400, epgs[0].sclass, epgs[1].sclass, acl.acl_index,
2290 [VppGbpContractRule(
2291 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2292 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2295 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2296 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2299 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2300 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2302 [ETH_P_IP, ETH_P_IPV6])
2305 self.send_and_expect_bridged(eps[0].itf,
2306 pkt_inter_epg_220_to_221 * 65,
2309 pkt_inter_epg_220_to_222 = (Ether(src=self.pg0.remote_mac,
2310 dst=str(self.router_mac)) /
2313 UDP(sport=1234, dport=1234) /
2315 self.send_and_assert_no_replies(eps[0].itf,
2316 pkt_inter_epg_220_to_222 * 65)
2319 # ping router IP in different BD
2321 pkt_router_ping_220_to_221 = (Ether(src=self.pg0.remote_mac,
2322 dst=str(self.router_mac)) /
2324 dst=epgs[1].bvi_ip4) /
2325 ICMP(type='echo-request'))
2327 self.send_and_expect(self.pg0, [pkt_router_ping_220_to_221], self.pg0)
2329 pkt_router_ping_220_to_221 = (Ether(src=self.pg0.remote_mac,
2330 dst=str(self.router_mac)) /
2331 IPv6(src=eps[0].ip6,
2332 dst=epgs[1].bvi_ip6) /
2333 ICMPv6EchoRequest())
2335 self.send_and_expect(self.pg0, [pkt_router_ping_220_to_221], self.pg0)
2338 # contract for the return direction
2340 c2 = VppGbpContract(
2341 self, 400, epgs[1].sclass, epgs[0].sclass, acl.acl_index,
2342 [VppGbpContractRule(
2343 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2344 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2347 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2348 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2350 [ETH_P_IP, ETH_P_IPV6])
2353 self.send_and_expect_bridged(eps[0].itf,
2354 pkt_inter_epg_220_to_221 * 65,
2356 pkt_inter_epg_221_to_220 = (Ether(src=self.pg2.remote_mac,
2357 dst=self.pg0.remote_mac) /
2360 UDP(sport=1234, dport=1234) /
2362 self.send_and_expect_bridged(eps[2].itf,
2363 pkt_inter_epg_221_to_220 * 65,
2365 pkt_inter_epg_221_to_220 = (Ether(src=self.pg2.remote_mac,
2366 dst=str(self.router_mac)) /
2369 UDP(sport=1234, dport=1234) /
2371 self.send_and_expect_routed(eps[2].itf,
2372 pkt_inter_epg_221_to_220 * 65,
2374 str(self.router_mac))
2375 pkt_inter_epg_221_to_220 = (Ether(src=self.pg2.remote_mac,
2376 dst=str(self.router_mac)) /
2377 IPv6(src=eps[2].ip6,
2379 UDP(sport=1234, dport=1234) /
2381 self.send_and_expect_routed6(eps[2].itf,
2382 pkt_inter_epg_221_to_220 * 65,
2384 str(self.router_mac))
2387 # contract between 220 and 222 uni-direction
2389 c3 = VppGbpContract(
2390 self, 400, epgs[0].sclass, epgs[2].sclass, acl.acl_index,
2391 [VppGbpContractRule(
2392 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2393 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2396 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2397 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2399 [ETH_P_IP, ETH_P_IPV6])
2402 self.send_and_expect(eps[0].itf,
2403 pkt_inter_epg_220_to_222 * 65,
2406 c3.remove_vpp_config()
2407 c1.remove_vpp_config()
2408 c2.remove_vpp_config()
2409 acl.remove_vpp_config()
2411 def test_gbp_bd_drop_flags(self):
2412 """ GBP BD drop flags """
2417 gt4 = VppIpTable(self, 1)
2418 gt4.add_vpp_config()
2419 gt6 = VppIpTable(self, 1, is_ip6=True)
2420 gt6.add_vpp_config()
2422 rd1 = VppGbpRouteDomain(self, 1, 401, gt4, gt6)
2423 rd1.add_vpp_config()
2426 # a GBP bridge domain with a BVI only
2428 bd1 = VppBridgeDomain(self, 1)
2429 bd1.add_vpp_config()
2431 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0,
2433 uu_drop=True, bm_drop=True)
2434 gbd1.add_vpp_config()
2436 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2437 self.logger.info(self.vapi.cli("sh gbp bridge"))
2439 # ... and has a /32 applied
2440 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi,
2441 "10.0.0.128", 32).add_vpp_config()
2444 # The Endpoint-group
2446 epg_220 = VppGbpEndpointGroup(self, 220, 112, rd1, gbd1,
2450 VppGbpEndpointRetention(3))
2451 epg_220.add_vpp_config()
2453 ep = VppGbpEndpoint(self, self.pg0,
2455 "10.0.0.127", "11.0.0.127",
2456 "2001:10::1", "3001::1")
2460 # send UU/BM packet from the local EP with UU drop and BM drop enabled
2463 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2464 self.logger.info(self.vapi.cli("sh gbp bridge"))
2465 p_uu = (Ether(src=ep.mac, dst="00:11:11:11:11:11") /
2466 IP(dst="10.0.0.133", src=ep.ip4) /
2467 UDP(sport=1234, dport=1234) /
2469 self.send_and_assert_no_replies(ep.itf, [p_uu])
2471 p_bm = (Ether(src=ep.mac, dst="ff:ff:ff:ff:ff:ff") /
2472 IP(dst="10.0.0.133", src=ep.ip4) /
2473 UDP(sport=1234, dport=1234) /
2475 self.send_and_assert_no_replies(ep.itf, [p_bm])
2477 self.pg3.unconfig_ip4()
2479 self.logger.info(self.vapi.cli("sh int"))
2481 def test_gbp_bd_arp_flags(self):
2482 """ GBP BD arp flags """
2487 gt4 = VppIpTable(self, 1)
2488 gt4.add_vpp_config()
2489 gt6 = VppIpTable(self, 1, is_ip6=True)
2490 gt6.add_vpp_config()
2492 rd1 = VppGbpRouteDomain(self, 1, 401, gt4, gt6)
2493 rd1.add_vpp_config()
2496 # Pg4 hosts the IP6 UU-flood VXLAN tunnel
2498 self.pg4.config_ip4()
2499 self.pg4.resolve_arp()
2502 # Add a mcast destination VXLAN-GBP tunnel for B&M traffic
2504 tun_uu = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
2507 tun_uu.add_vpp_config()
2510 # a GBP bridge domain with a BVI and a UU-flood interface
2512 bd1 = VppBridgeDomain(self, 1)
2513 bd1.add_vpp_config()
2515 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0,
2518 gbd1.add_vpp_config()
2520 # ... and has a /32 applied
2521 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi,
2522 "10.0.0.128", 32).add_vpp_config()
2525 # The Endpoint-group
2527 epg_220 = VppGbpEndpointGroup(self, 220, 112, rd1, gbd1,
2531 VppGbpEndpointRetention(2))
2532 epg_220.add_vpp_config()
2534 ep = VppGbpEndpoint(self, self.pg0,
2536 "10.0.0.127", "11.0.0.127",
2537 "2001:10::1", "3001::1")
2541 # send ARP packet from the local EP expect it on the uu interface
2543 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2544 self.logger.info(self.vapi.cli("sh gbp bridge"))
2545 p_arp = (Ether(src=ep.mac, dst="ff:ff:ff:ff:ff:ff") /
2547 psrc=ep.ip4, pdst="10.0.0.99",
2549 hwdst="ff:ff:ff:ff:ff:ff"))
2550 self.send_and_expect(ep.itf, [p_arp], self.pg4)
2552 self.pg4.unconfig_ip4()
2554 def test_gbp_learn_vlan_l2(self):
2555 """ GBP L2 Endpoint w/ VLANs"""
2557 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
2558 learnt = [{'mac': '00:00:11:11:11:01',
2560 'ip6': '2001:10::2'},
2561 {'mac': '00:00:11:11:11:02',
2563 'ip6': '2001:10::3'}]
2568 gt4 = VppIpTable(self, 1)
2569 gt4.add_vpp_config()
2570 gt6 = VppIpTable(self, 1, is_ip6=True)
2571 gt6.add_vpp_config()
2573 rd1 = VppGbpRouteDomain(self, 1, 401, gt4, gt6)
2574 rd1.add_vpp_config()
2577 # Pg2 hosts the vxlan tunnel, hosts on pg2 to act as TEPs
2579 self.pg2.config_ip4()
2580 self.pg2.resolve_arp()
2581 self.pg2.generate_remote_hosts(4)
2582 self.pg2.configure_ipv4_neighbors()
2583 self.pg3.config_ip4()
2584 self.pg3.resolve_arp()
2587 # The EP will be on a vlan sub-interface
2589 vlan_11 = VppDot1QSubint(self, self.pg0, 11)
2591 self.vapi.l2_interface_vlan_tag_rewrite(
2592 sw_if_index=vlan_11.sw_if_index, vtr_op=L2_VTR_OP.L2_POP_1,
2595 bd_uu_fwd = VppVxlanGbpTunnel(self, self.pg3.local_ip4,
2596 self.pg3.remote_ip4, 116)
2597 bd_uu_fwd.add_vpp_config()
2600 # a GBP bridge domain with a BVI and a UU-flood interface
2601 # The BD is marked as do not learn, so no endpoints are ever
2602 # learnt in this BD.
2604 bd1 = VppBridgeDomain(self, 1)
2605 bd1.add_vpp_config()
2606 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0, bd_uu_fwd,
2608 gbd1.add_vpp_config()
2610 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2611 self.logger.info(self.vapi.cli("sh gbp bridge"))
2613 # ... and has a /32 applied
2614 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi,
2615 "10.0.0.128", 32).add_vpp_config()
2618 # The Endpoint-group in which we are learning endpoints
2620 epg_220 = VppGbpEndpointGroup(self, 220, 441, rd1, gbd1,
2624 VppGbpEndpointRetention(4))
2625 epg_220.add_vpp_config()
2628 # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
2631 vx_tun_l2_1 = VppGbpVxlanTunnel(
2632 self, 99, bd1.bd_id,
2633 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L2,
2635 vx_tun_l2_1.add_vpp_config()
2638 # A static endpoint that the learnt endpoints are trying to
2641 ep = VppGbpEndpoint(self, vlan_11,
2643 "10.0.0.127", "11.0.0.127",
2644 "2001:10::1", "3001::1")
2647 self.assertTrue(find_route(self, ep.ip4, 32, table_id=1))
2650 # Send to the static EP
2652 for ii, l in enumerate(learnt):
2653 # a packet with an sclass from a known EPG
2654 # arriving on an unknown TEP
2655 p = (Ether(src=self.pg2.remote_mac,
2656 dst=self.pg2.local_mac) /
2657 IP(src=self.pg2.remote_hosts[1].ip4,
2658 dst=self.pg2.local_ip4) /
2659 UDP(sport=1234, dport=48879) /
2660 VXLAN(vni=99, gpid=441, flags=0x88) /
2661 Ether(src=l['mac'], dst=ep.mac) /
2662 IP(src=l['ip'], dst=ep.ip4) /
2663 UDP(sport=1234, dport=1234) /
2666 rxs = self.send_and_expect(self.pg2, [p], self.pg0)
2669 # packet to EP has the EP's vlan tag
2672 self.assertEqual(rx[Dot1Q].vlan, 11)
2675 # the EP is not learnt since the BD setting prevents it
2678 self.assertFalse(find_gbp_endpoint(self,
2679 vx_tun_l2_1.sw_if_index,
2681 self.assertEqual(INDEX_INVALID,
2682 find_vxlan_gbp_tunnel(
2685 self.pg2.remote_hosts[1].ip4,
2688 self.assertEqual(len(self.vapi.gbp_endpoint_dump()), 1)
2692 # we didn't learn the remotes so they are sent to the UU-fwd
2695 p = (Ether(src=ep.mac, dst=l['mac']) /
2697 IP(dst=l['ip'], src=ep.ip4) /
2698 UDP(sport=1234, dport=1234) /
2701 rxs = self.send_and_expect(self.pg0, p * 17, self.pg3)
2704 self.assertEqual(rx[IP].src, self.pg3.local_ip4)
2705 self.assertEqual(rx[IP].dst, self.pg3.remote_ip4)
2706 self.assertEqual(rx[UDP].dport, 48879)
2707 # the UDP source port is a random value for hashing
2708 self.assertEqual(rx[VXLAN].gpid, 441)
2709 self.assertEqual(rx[VXLAN].vni, 116)
2710 self.assertTrue(rx[VXLAN].flags.G)
2711 self.assertTrue(rx[VXLAN].flags.Instance)
2712 self.assertFalse(rx[VXLAN].gpflags.A)
2713 self.assertFalse(rx[VXLAN].gpflags.D)
2715 self.pg2.unconfig_ip4()
2716 self.pg3.unconfig_ip4()
2718 def test_gbp_learn_l3(self):
2719 """ GBP L3 Endpoint Learning """
2721 self.vapi.cli("set logging class gbp level debug")
2723 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
2724 routed_dst_mac = "00:0c:0c:0c:0c:0c"
2725 routed_src_mac = "00:22:bd:f8:19:ff"
2727 learnt = [{'mac': '00:00:11:11:11:02',
2729 'ip6': '2001:10::2'},
2730 {'mac': '00:00:11:11:11:03',
2732 'ip6': '2001:10::3'}]
2737 t4 = VppIpTable(self, 1)
2739 t6 = VppIpTable(self, 1, True)
2742 tun_ip4_uu = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
2743 self.pg4.remote_ip4, 114)
2744 tun_ip6_uu = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
2745 self.pg4.remote_ip4, 116)
2746 tun_ip4_uu.add_vpp_config()
2747 tun_ip6_uu.add_vpp_config()
2749 rd1 = VppGbpRouteDomain(self, 2, 401, t4, t6, tun_ip4_uu, tun_ip6_uu)
2750 rd1.add_vpp_config()
2752 self.loop0.set_mac(self.router_mac)
2755 # Bind the BVI to the RD
2757 b4 = VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
2758 b6 = VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
2761 # Pg2 hosts the vxlan tunnel
2762 # hosts on pg2 to act as TEPs
2766 self.pg2.config_ip4()
2767 self.pg2.resolve_arp()
2768 self.pg2.generate_remote_hosts(4)
2769 self.pg2.configure_ipv4_neighbors()
2770 self.pg3.config_ip4()
2771 self.pg3.resolve_arp()
2772 self.pg4.config_ip4()
2773 self.pg4.resolve_arp()
2776 # a GBP bridge domain with a BVI and a UU-flood interface
2778 bd1 = VppBridgeDomain(self, 1)
2779 bd1.add_vpp_config()
2780 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0, self.pg3)
2781 gbd1.add_vpp_config()
2783 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2784 self.logger.info(self.vapi.cli("sh gbp bridge"))
2785 self.logger.info(self.vapi.cli("sh gbp route"))
2787 # ... and has a /32 and /128 applied
2788 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi,
2790 bind=b4).add_vpp_config()
2791 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi,
2792 "2001:10::128", 128,
2793 bind=b6).add_vpp_config()
2796 # The Endpoint-group in which we are learning endpoints
2798 epg_220 = VppGbpEndpointGroup(self, 220, 441, rd1, gbd1,
2802 VppGbpEndpointRetention(4))
2803 epg_220.add_vpp_config()
2806 # The VXLAN GBP tunnel is in L3 mode with learning enabled
2808 vx_tun_l3 = VppGbpVxlanTunnel(
2809 self, 101, rd1.rd_id,
2810 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
2812 vx_tun_l3.add_vpp_config()
2815 # A static endpoint that the learnt endpoints are trying to
2818 ep = VppGbpEndpoint(self, self.pg0,
2820 "10.0.0.127", "11.0.0.127",
2821 "2001:10::1", "3001::1")
2825 # learn some remote IPv4 EPs
2827 for ii, l in enumerate(learnt):
2828 # a packet with an sclass from a known EPG
2829 # arriving on an unknown TEP
2830 p = (Ether(src=self.pg2.remote_mac,
2831 dst=self.pg2.local_mac) /
2832 IP(src=self.pg2.remote_hosts[1].ip4,
2833 dst=self.pg2.local_ip4) /
2834 UDP(sport=1234, dport=48879) /
2835 VXLAN(vni=101, gpid=441, flags=0x88) /
2836 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2837 IP(src=l['ip'], dst=ep.ip4) /
2838 UDP(sport=1234, dport=1234) /
2841 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2844 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2847 self.pg2.remote_hosts[1].ip4,
2849 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2851 # endpoint learnt via the parent GBP-vxlan interface
2852 self.assertTrue(find_gbp_endpoint(self,
2853 vx_tun_l3._sw_if_index,
2857 # Static IPv4 EP replies to learnt
2860 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2861 IP(dst=l['ip'], src=ep.ip4) /
2862 UDP(sport=1234, dport=1234) /
2865 rxs = self.send_and_expect(self.pg0, p * 1, self.pg2)
2868 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2869 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2870 self.assertEqual(rx[UDP].dport, 48879)
2871 # the UDP source port is a random value for hashing
2872 self.assertEqual(rx[VXLAN].gpid, 441)
2873 self.assertEqual(rx[VXLAN].vni, 101)
2874 self.assertTrue(rx[VXLAN].flags.G)
2875 self.assertTrue(rx[VXLAN].flags.Instance)
2876 self.assertTrue(rx[VXLAN].gpflags.A)
2877 self.assertFalse(rx[VXLAN].gpflags.D)
2879 inner = rx[VXLAN].payload
2881 self.assertEqual(inner[Ether].src, routed_src_mac)
2882 self.assertEqual(inner[Ether].dst, routed_dst_mac)
2883 self.assertEqual(inner[IP].src, ep.ip4)
2884 self.assertEqual(inner[IP].dst, l['ip'])
2887 self.assertFalse(find_gbp_endpoint(self,
2892 # learn some remote IPv6 EPs
2894 for ii, l in enumerate(learnt):
2895 # a packet with an sclass from a known EPG
2896 # arriving on an unknown TEP
2897 p = (Ether(src=self.pg2.remote_mac,
2898 dst=self.pg2.local_mac) /
2899 IP(src=self.pg2.remote_hosts[1].ip4,
2900 dst=self.pg2.local_ip4) /
2901 UDP(sport=1234, dport=48879) /
2902 VXLAN(vni=101, gpid=441, flags=0x88) /
2903 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2904 IPv6(src=l['ip6'], dst=ep.ip6) /
2905 UDP(sport=1234, dport=1234) /
2908 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2911 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2914 self.pg2.remote_hosts[1].ip4,
2916 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2918 self.logger.info(self.vapi.cli("show gbp bridge"))
2919 self.logger.info(self.vapi.cli("show vxlan-gbp tunnel"))
2920 self.logger.info(self.vapi.cli("show gbp vxlan"))
2921 self.logger.info(self.vapi.cli("show int addr"))
2923 # endpoint learnt via the TEP
2924 self.assertTrue(find_gbp_endpoint(self, ip=l['ip6']))
2926 self.logger.info(self.vapi.cli("show gbp endpoint"))
2927 self.logger.info(self.vapi.cli("show ip fib index 1 %s" % l['ip']))
2930 # Static EP replies to learnt
2933 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2934 IPv6(dst=l['ip6'], src=ep.ip6) /
2935 UDP(sport=1234, dport=1234) /
2938 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
2941 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2942 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2943 self.assertEqual(rx[UDP].dport, 48879)
2944 # the UDP source port is a random value for hashing
2945 self.assertEqual(rx[VXLAN].gpid, 441)
2946 self.assertEqual(rx[VXLAN].vni, 101)
2947 self.assertTrue(rx[VXLAN].flags.G)
2948 self.assertTrue(rx[VXLAN].flags.Instance)
2949 self.assertTrue(rx[VXLAN].gpflags.A)
2950 self.assertFalse(rx[VXLAN].gpflags.D)
2952 inner = rx[VXLAN].payload
2954 self.assertEqual(inner[Ether].src, routed_src_mac)
2955 self.assertEqual(inner[Ether].dst, routed_dst_mac)
2956 self.assertEqual(inner[IPv6].src, ep.ip6)
2957 self.assertEqual(inner[IPv6].dst, l['ip6'])
2959 self.logger.info(self.vapi.cli("sh gbp endpoint"))
2961 self.wait_for_ep_timeout(ip=l['ip'])
2964 # Static sends to unknown EP with no route
2966 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2967 IP(dst="10.0.0.99", src=ep.ip4) /
2968 UDP(sport=1234, dport=1234) /
2971 self.send_and_assert_no_replies(self.pg0, [p])
2974 # Add a route to static EP's v4 and v6 subnet
2976 se_10_24 = VppGbpSubnet(
2977 self, rd1, "10.0.0.0", 24,
2978 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT)
2979 se_10_24.add_vpp_config()
2982 # static pings router
2984 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2985 IP(dst=epg_220.bvi_ip4, src=ep.ip4) /
2986 UDP(sport=1234, dport=1234) /
2989 self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg0)
2991 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2992 IPv6(dst=epg_220.bvi_ip6, src=ep.ip6) /
2993 UDP(sport=1234, dport=1234) /
2996 self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg0)
2999 # packets to address in the subnet are sent on the uu-fwd
3001 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
3002 IP(dst="10.0.0.99", src=ep.ip4) /
3003 UDP(sport=1234, dport=1234) /
3006 rxs = self.send_and_expect(self.pg0, [p], self.pg4)
3008 self.assertEqual(rx[IP].src, self.pg4.local_ip4)
3009 self.assertEqual(rx[IP].dst, self.pg4.remote_ip4)
3010 self.assertEqual(rx[UDP].dport, 48879)
3011 # the UDP source port is a random value for hashing
3012 self.assertEqual(rx[VXLAN].gpid, 441)
3013 self.assertEqual(rx[VXLAN].vni, 114)
3014 self.assertTrue(rx[VXLAN].flags.G)
3015 self.assertTrue(rx[VXLAN].flags.Instance)
3016 # policy is not applied to packets sent to the uu-fwd interfaces
3017 self.assertFalse(rx[VXLAN].gpflags.A)
3018 self.assertFalse(rx[VXLAN].gpflags.D)
3021 # learn some remote IPv4 EPs
3023 for ii, l in enumerate(learnt):
3024 # a packet with an sclass from a known EPG
3025 # arriving on an unknown TEP
3026 p = (Ether(src=self.pg2.remote_mac,
3027 dst=self.pg2.local_mac) /
3028 IP(src=self.pg2.remote_hosts[2].ip4,
3029 dst=self.pg2.local_ip4) /
3030 UDP(sport=1234, dport=48879) /
3031 VXLAN(vni=101, gpid=441, flags=0x88) /
3032 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
3033 IP(src=l['ip'], dst=ep.ip4) /
3034 UDP(sport=1234, dport=1234) /
3037 rx = self.send_and_expect(self.pg2, [p], self.pg0)
3040 tep1_sw_if_index = find_vxlan_gbp_tunnel(
3043 self.pg2.remote_hosts[2].ip4,
3045 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
3047 # endpoint learnt via the parent GBP-vxlan interface
3048 self.assertTrue(find_gbp_endpoint(self,
3049 vx_tun_l3._sw_if_index,
3053 # Add a remote endpoint from the API
3055 rep_88 = VppGbpEndpoint(self, vx_tun_l3,
3057 "10.0.0.88", "11.0.0.88",
3058 "2001:10::88", "3001::88",
3059 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
3061 self.pg2.remote_hosts[2].ip4,
3063 rep_88.add_vpp_config()
3066 # Add a remote endpoint from the API that matches an existing one
3067 # this is a lower priority, hence the packet is sent to the DP leanrt
3070 rep_2 = VppGbpEndpoint(self, vx_tun_l3,
3072 learnt[0]['ip'], "11.0.0.101",
3073 learnt[0]['ip6'], "3001::101",
3074 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
3076 self.pg2.remote_hosts[1].ip4,
3078 rep_2.add_vpp_config()
3081 # Add a route to the learned EP's v4 subnet
3082 # packets should be send on the v4/v6 uu=fwd interface resp.
3084 se_10_1_24 = VppGbpSubnet(
3085 self, rd1, "10.0.1.0", 24,
3086 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT)
3087 se_10_1_24.add_vpp_config()
3089 self.logger.info(self.vapi.cli("show gbp endpoint"))
3091 ips = ["10.0.0.88", learnt[0]['ip']]
3093 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
3094 IP(dst=ip, src=ep.ip4) /
3095 UDP(sport=1234, dport=1234) /
3098 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
3101 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
3102 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[2].ip4)
3103 self.assertEqual(rx[UDP].dport, 48879)
3104 # the UDP source port is a random value for hashing
3105 self.assertEqual(rx[VXLAN].gpid, 441)
3106 self.assertEqual(rx[VXLAN].vni, 101)
3107 self.assertTrue(rx[VXLAN].flags.G)
3108 self.assertTrue(rx[VXLAN].flags.Instance)
3109 self.assertTrue(rx[VXLAN].gpflags.A)
3110 self.assertFalse(rx[VXLAN].gpflags.D)
3112 inner = rx[VXLAN].payload
3114 self.assertEqual(inner[Ether].src, routed_src_mac)
3115 self.assertEqual(inner[Ether].dst, routed_dst_mac)
3116 self.assertEqual(inner[IP].src, ep.ip4)
3117 self.assertEqual(inner[IP].dst, ip)
3120 # remove the API remote EPs, only API sourced is gone, the DP
3121 # learnt one remains
3123 rep_88.remove_vpp_config()
3124 rep_2.remove_vpp_config()
3126 self.assertTrue(find_gbp_endpoint(self, ip=rep_2.ip4))
3128 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
3129 IP(src=ep.ip4, dst=rep_2.ip4) /
3130 UDP(sport=1234, dport=1234) /
3132 rxs = self.send_and_expect(self.pg0, [p], self.pg2)
3134 self.assertFalse(find_gbp_endpoint(self, ip=rep_88.ip4))
3136 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
3137 IP(src=ep.ip4, dst=rep_88.ip4) /
3138 UDP(sport=1234, dport=1234) /
3140 rxs = self.send_and_expect(self.pg0, [p], self.pg4)
3143 # to appease the testcase we cannot have the registered EP still
3144 # present (because it's DP learnt) when the TC ends so wait until
3147 self.wait_for_ep_timeout(ip=rep_88.ip4)
3148 self.wait_for_ep_timeout(ip=rep_2.ip4)
3151 # Same as above, learn a remote EP via CP and DP
3152 # this time remove the DP one first. expect the CP data to remain
3154 rep_3 = VppGbpEndpoint(self, vx_tun_l3,
3156 "10.0.1.4", "11.0.0.103",
3157 "2001::10:3", "3001::103",
3158 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
3160 self.pg2.remote_hosts[1].ip4,
3162 rep_3.add_vpp_config()
3164 p = (Ether(src=self.pg2.remote_mac,
3165 dst=self.pg2.local_mac) /
3166 IP(src=self.pg2.remote_hosts[2].ip4,
3167 dst=self.pg2.local_ip4) /
3168 UDP(sport=1234, dport=48879) /
3169 VXLAN(vni=101, gpid=441, flags=0x88) /
3170 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
3171 IP(src="10.0.1.4", dst=ep.ip4) /
3172 UDP(sport=1234, dport=1234) /
3174 rxs = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
3176 self.assertTrue(find_gbp_endpoint(self,
3177 vx_tun_l3._sw_if_index,
3179 tep=[self.pg2.local_ip4,
3180 self.pg2.remote_hosts[2].ip4]))
3182 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
3183 IP(dst="10.0.1.4", src=ep.ip4) /
3184 UDP(sport=1234, dport=1234) /
3186 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
3188 # host 2 is the DP learned TEP
3190 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
3191 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[2].ip4)
3193 self.wait_for_ep_timeout(ip=rep_3.ip4,
3194 tep=[self.pg2.local_ip4,
3195 self.pg2.remote_hosts[2].ip4])
3197 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
3199 # host 1 is the CP learned TEP
3201 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
3202 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
3205 # shutdown with learnt endpoint present
3207 p = (Ether(src=self.pg2.remote_mac,
3208 dst=self.pg2.local_mac) /
3209 IP(src=self.pg2.remote_hosts[1].ip4,
3210 dst=self.pg2.local_ip4) /
3211 UDP(sport=1234, dport=48879) /
3212 VXLAN(vni=101, gpid=441, flags=0x88) /
3213 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
3214 IP(src=learnt[1]['ip'], dst=ep.ip4) /
3215 UDP(sport=1234, dport=1234) /
3218 rx = self.send_and_expect(self.pg2, [p], self.pg0)
3220 # endpoint learnt via the parent GBP-vxlan interface
3221 self.assertTrue(find_gbp_endpoint(self,
3222 vx_tun_l3._sw_if_index,
3227 # remote endpoint becomes local
3229 self.pg2.unconfig_ip4()
3230 self.pg3.unconfig_ip4()
3231 self.pg4.unconfig_ip4()
3233 def test_gbp_redirect(self):
3234 """ GBP Endpoint Redirect """
3236 self.vapi.cli("set logging class gbp level debug")
3238 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
3239 routed_dst_mac = "00:0c:0c:0c:0c:0c"
3240 routed_src_mac = "00:22:bd:f8:19:ff"
3242 learnt = [{'mac': '00:00:11:11:11:02',
3244 'ip6': '2001:10::2'},
3245 {'mac': '00:00:11:11:11:03',
3247 'ip6': '2001:10::3'}]
3252 t4 = VppIpTable(self, 1)
3254 t6 = VppIpTable(self, 1, True)
3257 rd1 = VppGbpRouteDomain(self, 2, 402, t4, t6)
3258 rd1.add_vpp_config()
3260 self.loop0.set_mac(self.router_mac)
3263 # Bind the BVI to the RD
3265 b_ip4 = VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
3266 b_ip6 = VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
3269 # Pg7 hosts a BD's UU-fwd
3271 self.pg7.config_ip4()
3272 self.pg7.resolve_arp()
3275 # a GBP bridge domains for the EPs
3277 bd1 = VppBridgeDomain(self, 1)
3278 bd1.add_vpp_config()
3279 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0)
3280 gbd1.add_vpp_config()
3282 bd2 = VppBridgeDomain(self, 2)
3283 bd2.add_vpp_config()
3284 gbd2 = VppGbpBridgeDomain(self, bd2, rd1, self.loop1)
3285 gbd2.add_vpp_config()
3287 # ... and has a /32 and /128 applied
3288 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi,
3290 bind=b_ip4).add_vpp_config()
3291 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi,
3292 "2001:10::128", 128,
3293 bind=b_ip6).add_vpp_config()
3294 ip4_addr = VppIpInterfaceAddress(self, gbd2.bvi,
3295 "10.0.1.128", 32).add_vpp_config()
3296 ip6_addr = VppIpInterfaceAddress(self, gbd2.bvi,
3297 "2001:11::128", 128).add_vpp_config()
3300 # The Endpoint-groups in which we are learning endpoints
3302 epg_220 = VppGbpEndpointGroup(self, 220, 440, rd1, gbd1,
3306 VppGbpEndpointRetention(60))
3307 epg_220.add_vpp_config()
3308 epg_221 = VppGbpEndpointGroup(self, 221, 441, rd1, gbd2,
3312 VppGbpEndpointRetention(60))
3313 epg_221.add_vpp_config()
3314 epg_222 = VppGbpEndpointGroup(self, 222, 442, rd1, gbd1,
3318 VppGbpEndpointRetention(60))
3319 epg_222.add_vpp_config()
3322 # a GBP bridge domains for the SEPs
3324 bd_uu1 = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
3325 self.pg7.remote_ip4, 116)
3326 bd_uu1.add_vpp_config()
3327 bd_uu2 = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
3328 self.pg7.remote_ip4, 117)
3329 bd_uu2.add_vpp_config()
3331 bd3 = VppBridgeDomain(self, 3)
3332 bd3.add_vpp_config()
3333 gbd3 = VppGbpBridgeDomain(self, bd3, rd1, self.loop2,
3334 bd_uu1, learn=False)
3335 gbd3.add_vpp_config()
3336 bd4 = VppBridgeDomain(self, 4)
3337 bd4.add_vpp_config()
3338 gbd4 = VppGbpBridgeDomain(self, bd4, rd1, self.loop3,
3339 bd_uu2, learn=False)
3340 gbd4.add_vpp_config()
3343 # EPGs in which the service endpoints exist
3345 epg_320 = VppGbpEndpointGroup(self, 320, 550, rd1, gbd3,
3349 VppGbpEndpointRetention(60))
3350 epg_320.add_vpp_config()
3351 epg_321 = VppGbpEndpointGroup(self, 321, 551, rd1, gbd4,
3355 VppGbpEndpointRetention(60))
3356 epg_321.add_vpp_config()
3359 # three local endpoints
3361 ep1 = VppGbpEndpoint(self, self.pg0,
3363 "10.0.0.1", "11.0.0.1",
3364 "2001:10::1", "3001:10::1")
3365 ep1.add_vpp_config()
3366 ep2 = VppGbpEndpoint(self, self.pg1,
3368 "10.0.1.1", "11.0.1.1",
3369 "2001:11::1", "3001:11::1")
3370 ep2.add_vpp_config()
3371 ep3 = VppGbpEndpoint(self, self.pg2,
3373 "10.0.2.2", "11.0.2.2",
3374 "2001:12::1", "3001:12::1")
3375 ep3.add_vpp_config()
3380 sep1 = VppGbpEndpoint(self, self.pg3,
3382 "12.0.0.1", "13.0.0.1",
3383 "4001:10::1", "5001:10::1")
3384 sep1.add_vpp_config()
3385 sep2 = VppGbpEndpoint(self, self.pg4,
3387 "12.0.0.2", "13.0.0.2",
3388 "4001:10::2", "5001:10::2")
3389 sep2.add_vpp_config()
3390 sep3 = VppGbpEndpoint(self, self.pg5,
3392 "12.0.1.1", "13.0.1.1",
3393 "4001:11::1", "5001:11::1")
3394 sep3.add_vpp_config()
3395 # this EP is not installed immediately
3396 sep4 = VppGbpEndpoint(self, self.pg6,
3398 "12.0.1.2", "13.0.1.2",
3399 "4001:11::2", "5001:11::2")
3402 # an L2 switch packet between local EPs in different EPGs
3403 # different dest ports on each so the are LB hashed differently
3405 p4 = [(Ether(src=ep1.mac, dst=ep3.mac) /
3406 IP(src=ep1.ip4, dst=ep3.ip4) /
3407 UDP(sport=1234, dport=1234) /
3408 Raw(b'\xa5' * 100)),
3409 (Ether(src=ep3.mac, dst=ep1.mac) /
3410 IP(src=ep3.ip4, dst=ep1.ip4) /
3411 UDP(sport=1234, dport=1234) /
3412 Raw(b'\xa5' * 100))]
3413 p6 = [(Ether(src=ep1.mac, dst=ep3.mac) /
3414 IPv6(src=ep1.ip6, dst=ep3.ip6) /
3415 UDP(sport=1234, dport=1234) /
3416 Raw(b'\xa5' * 100)),
3417 (Ether(src=ep3.mac, dst=ep1.mac) /
3418 IPv6(src=ep3.ip6, dst=ep1.ip6) /
3419 UDP(sport=1234, dport=1230) /
3420 Raw(b'\xa5' * 100))]
3422 # should be dropped since no contract yet
3423 self.send_and_assert_no_replies(self.pg0, [p4[0]])
3424 self.send_and_assert_no_replies(self.pg0, [p6[0]])
3427 # Add a contract with a rule to load-balance redirect via SEP1 and SEP2
3428 # one of the next-hops is via an EP that is not known
3430 rule4 = AclRule(is_permit=1, proto=17)
3431 rule6 = AclRule(src_prefix=IPv6Network((0, 0)),
3432 dst_prefix=IPv6Network((0, 0)), is_permit=1, proto=17)
3433 acl = VppAcl(self, rules=[rule4, rule6])
3434 acl.add_vpp_config()
3437 # test the src-ip hash mode
3439 c1 = VppGbpContract(
3440 self, 402, epg_220.sclass, epg_222.sclass, acl.acl_index,
3441 [VppGbpContractRule(
3442 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3443 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3444 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3445 sep1.ip4, sep1.epg.rd),
3446 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3447 sep2.ip4, sep2.epg.rd)]),
3449 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3450 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3451 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3452 sep3.ip6, sep3.epg.rd),
3453 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3454 sep4.ip6, sep4.epg.rd)])],
3455 [ETH_P_IP, ETH_P_IPV6])
3458 c2 = VppGbpContract(
3459 self, 402, epg_222.sclass, epg_220.sclass, acl.acl_index,
3460 [VppGbpContractRule(
3461 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3462 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3463 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3464 sep1.ip4, sep1.epg.rd),
3465 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3466 sep2.ip4, sep2.epg.rd)]),
3468 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3469 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3470 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3471 sep3.ip6, sep3.epg.rd),
3472 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3473 sep4.ip6, sep4.epg.rd)])],
3474 [ETH_P_IP, ETH_P_IPV6])
3478 # send again with the contract preset, now packets arrive
3479 # at SEP1 or SEP2 depending on the hashing
3481 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3484 self.assertEqual(rx[Ether].src, routed_src_mac)
3485 self.assertEqual(rx[Ether].dst, sep1.mac)
3486 self.assertEqual(rx[IP].src, ep1.ip4)
3487 self.assertEqual(rx[IP].dst, ep3.ip4)
3489 rxs = self.send_and_expect(self.pg2, p4[1] * 17, sep2.itf)
3492 self.assertEqual(rx[Ether].src, routed_src_mac)
3493 self.assertEqual(rx[Ether].dst, sep2.mac)
3494 self.assertEqual(rx[IP].src, ep3.ip4)
3495 self.assertEqual(rx[IP].dst, ep1.ip4)
3497 rxs = self.send_and_expect(self.pg0, p6[0] * 17, self.pg7)
3500 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3501 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3502 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3503 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
3504 self.assertEqual(rx[VXLAN].vni, 117)
3505 self.assertTrue(rx[VXLAN].flags.G)
3506 self.assertTrue(rx[VXLAN].flags.Instance)
3507 # redirect policy has been applied
3508 self.assertTrue(rx[VXLAN].gpflags.A)
3509 self.assertFalse(rx[VXLAN].gpflags.D)
3511 inner = rx[VXLAN].payload
3513 self.assertEqual(inner[Ether].src, routed_src_mac)
3514 self.assertEqual(inner[Ether].dst, sep4.mac)
3515 self.assertEqual(inner[IPv6].src, ep1.ip6)
3516 self.assertEqual(inner[IPv6].dst, ep3.ip6)
3518 rxs = self.send_and_expect(self.pg2, p6[1] * 17, sep3.itf)
3521 self.assertEqual(rx[Ether].src, routed_src_mac)
3522 self.assertEqual(rx[Ether].dst, sep3.mac)
3523 self.assertEqual(rx[IPv6].src, ep3.ip6)
3524 self.assertEqual(rx[IPv6].dst, ep1.ip6)
3527 # programme the unknown EP
3529 sep4.add_vpp_config()
3531 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep4.itf)
3534 self.assertEqual(rx[Ether].src, routed_src_mac)
3535 self.assertEqual(rx[Ether].dst, sep4.mac)
3536 self.assertEqual(rx[IPv6].src, ep1.ip6)
3537 self.assertEqual(rx[IPv6].dst, ep3.ip6)
3540 # and revert back to unprogrammed
3542 sep4.remove_vpp_config()
3544 rxs = self.send_and_expect(self.pg0, p6[0] * 17, self.pg7)
3547 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3548 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3549 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3550 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
3551 self.assertEqual(rx[VXLAN].vni, 117)
3552 self.assertTrue(rx[VXLAN].flags.G)
3553 self.assertTrue(rx[VXLAN].flags.Instance)
3554 # redirect policy has been applied
3555 self.assertTrue(rx[VXLAN].gpflags.A)
3556 self.assertFalse(rx[VXLAN].gpflags.D)
3558 inner = rx[VXLAN].payload
3560 self.assertEqual(inner[Ether].src, routed_src_mac)
3561 self.assertEqual(inner[Ether].dst, sep4.mac)
3562 self.assertEqual(inner[IPv6].src, ep1.ip6)
3563 self.assertEqual(inner[IPv6].dst, ep3.ip6)
3565 c1.remove_vpp_config()
3566 c2.remove_vpp_config()
3569 # test the symmetric hash mode
3571 c1 = VppGbpContract(
3572 self, 402, epg_220.sclass, epg_222.sclass, acl.acl_index,
3573 [VppGbpContractRule(
3574 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3575 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3576 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3577 sep1.ip4, sep1.epg.rd),
3578 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3579 sep2.ip4, sep2.epg.rd)]),
3581 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3582 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3583 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3584 sep3.ip6, sep3.epg.rd),
3585 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3586 sep4.ip6, sep4.epg.rd)])],
3587 [ETH_P_IP, ETH_P_IPV6])
3590 c2 = VppGbpContract(
3591 self, 402, epg_222.sclass, epg_220.sclass, acl.acl_index,
3592 [VppGbpContractRule(
3593 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3594 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3595 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3596 sep1.ip4, sep1.epg.rd),
3597 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3598 sep2.ip4, sep2.epg.rd)]),
3600 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3601 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3602 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3603 sep3.ip6, sep3.epg.rd),
3604 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3605 sep4.ip6, sep4.epg.rd)])],
3606 [ETH_P_IP, ETH_P_IPV6])
3610 # send again with the contract preset, now packets arrive
3611 # at SEP1 for both directions
3613 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3616 self.assertEqual(rx[Ether].src, routed_src_mac)
3617 self.assertEqual(rx[Ether].dst, sep1.mac)
3618 self.assertEqual(rx[IP].src, ep1.ip4)
3619 self.assertEqual(rx[IP].dst, ep3.ip4)
3621 rxs = self.send_and_expect(self.pg2, p4[1] * 17, sep1.itf)
3624 self.assertEqual(rx[Ether].src, routed_src_mac)
3625 self.assertEqual(rx[Ether].dst, sep1.mac)
3626 self.assertEqual(rx[IP].src, ep3.ip4)
3627 self.assertEqual(rx[IP].dst, ep1.ip4)
3630 # programme the unknown EP for the L3 tests
3632 sep4.add_vpp_config()
3635 # an L3 switch packet between local EPs in different EPGs
3636 # different dest ports on each so the are LB hashed differently
3638 p4 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3639 IP(src=ep1.ip4, dst=ep2.ip4) /
3640 UDP(sport=1234, dport=1234) /
3641 Raw(b'\xa5' * 100)),
3642 (Ether(src=ep2.mac, dst=str(self.router_mac)) /
3643 IP(src=ep2.ip4, dst=ep1.ip4) /
3644 UDP(sport=1234, dport=1234) /
3645 Raw(b'\xa5' * 100))]
3646 p6 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3647 IPv6(src=ep1.ip6, dst=ep2.ip6) /
3648 UDP(sport=1234, dport=1234) /
3649 Raw(b'\xa5' * 100)),
3650 (Ether(src=ep2.mac, dst=str(self.router_mac)) /
3651 IPv6(src=ep2.ip6, dst=ep1.ip6) /
3652 UDP(sport=1234, dport=1234) /
3653 Raw(b'\xa5' * 100))]
3655 c3 = VppGbpContract(
3656 self, 402, epg_220.sclass, epg_221.sclass, acl.acl_index,
3657 [VppGbpContractRule(
3658 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3659 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3660 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3661 sep1.ip4, sep1.epg.rd),
3662 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3663 sep2.ip4, sep2.epg.rd)]),
3665 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3666 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3667 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3668 sep3.ip6, sep3.epg.rd),
3669 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3670 sep4.ip6, sep4.epg.rd)])],
3671 [ETH_P_IP, ETH_P_IPV6])
3674 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3677 self.assertEqual(rx[Ether].src, routed_src_mac)
3678 self.assertEqual(rx[Ether].dst, sep1.mac)
3679 self.assertEqual(rx[IP].src, ep1.ip4)
3680 self.assertEqual(rx[IP].dst, ep2.ip4)
3683 # learn a remote EP in EPG 221
3684 # packets coming from unknown remote EPs will be leant & redirected
3686 vx_tun_l3 = VppGbpVxlanTunnel(
3687 self, 444, rd1.rd_id,
3688 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
3690 vx_tun_l3.add_vpp_config()
3692 c4 = VppGbpContract(
3693 self, 402, epg_221.sclass, epg_220.sclass, acl.acl_index,
3694 [VppGbpContractRule(
3695 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3696 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3697 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3698 sep1.ip4, sep1.epg.rd),
3699 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3700 sep2.ip4, sep2.epg.rd)]),
3702 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3703 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3704 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3705 sep3.ip6, sep3.epg.rd),
3706 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3707 sep4.ip6, sep4.epg.rd)])],
3708 [ETH_P_IP, ETH_P_IPV6])
3711 p = (Ether(src=self.pg7.remote_mac,
3712 dst=self.pg7.local_mac) /
3713 IP(src=self.pg7.remote_ip4,
3714 dst=self.pg7.local_ip4) /
3715 UDP(sport=1234, dport=48879) /
3716 VXLAN(vni=444, gpid=441, flags=0x88) /
3717 Ether(src="00:22:22:22:22:33", dst=str(self.router_mac)) /
3718 IP(src="10.0.0.88", dst=ep1.ip4) /
3719 UDP(sport=1234, dport=1234) /
3722 # unknown remote EP to local EP redirected
3723 rxs = self.send_and_expect(self.pg7, [p], sep1.itf)
3726 self.assertEqual(rx[Ether].src, routed_src_mac)
3727 self.assertEqual(rx[Ether].dst, sep1.mac)
3728 self.assertEqual(rx[IP].src, "10.0.0.88")
3729 self.assertEqual(rx[IP].dst, ep1.ip4)
3731 # endpoint learnt via the parent GBP-vxlan interface
3732 self.assertTrue(find_gbp_endpoint(self,
3733 vx_tun_l3._sw_if_index,
3736 p = (Ether(src=self.pg7.remote_mac,
3737 dst=self.pg7.local_mac) /
3738 IP(src=self.pg7.remote_ip4,
3739 dst=self.pg7.local_ip4) /
3740 UDP(sport=1234, dport=48879) /
3741 VXLAN(vni=444, gpid=441, flags=0x88) /
3742 Ether(src="00:22:22:22:22:33", dst=str(self.router_mac)) /
3743 IPv6(src="2001:10::88", dst=ep1.ip6) /
3744 UDP(sport=1234, dport=1234) /
3747 # unknown remote EP to local EP redirected (ipv6)
3748 rxs = self.send_and_expect(self.pg7, [p], sep3.itf)
3751 self.assertEqual(rx[Ether].src, routed_src_mac)
3752 self.assertEqual(rx[Ether].dst, sep3.mac)
3753 self.assertEqual(rx[IPv6].src, "2001:10::88")
3754 self.assertEqual(rx[IPv6].dst, ep1.ip6)
3756 # endpoint learnt via the parent GBP-vxlan interface
3757 self.assertTrue(find_gbp_endpoint(self,
3758 vx_tun_l3._sw_if_index,
3762 # L3 switch from local to remote EP
3764 p4 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3765 IP(src=ep1.ip4, dst="10.0.0.88") /
3766 UDP(sport=1234, dport=1234) /
3767 Raw(b'\xa5' * 100))]
3768 p6 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3769 IPv6(src=ep1.ip6, dst="2001:10::88") /
3770 UDP(sport=1234, dport=1234) /
3771 Raw(b'\xa5' * 100))]
3773 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3776 self.assertEqual(rx[Ether].src, routed_src_mac)
3777 self.assertEqual(rx[Ether].dst, sep1.mac)
3778 self.assertEqual(rx[IP].src, ep1.ip4)
3779 self.assertEqual(rx[IP].dst, "10.0.0.88")
3781 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep4.itf)
3784 self.assertEqual(rx[Ether].src, routed_src_mac)
3785 self.assertEqual(rx[Ether].dst, sep4.mac)
3786 self.assertEqual(rx[IPv6].src, ep1.ip6)
3787 self.assertEqual(rx[IPv6].dst, "2001:10::88")
3790 # test the dst-ip hash mode
3792 c5 = VppGbpContract(
3793 self, 402, epg_220.sclass, epg_221.sclass, acl.acl_index,
3794 [VppGbpContractRule(
3795 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3796 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
3797 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3798 sep1.ip4, sep1.epg.rd),
3799 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3800 sep2.ip4, sep2.epg.rd)]),
3802 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3803 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
3804 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3805 sep3.ip6, sep3.epg.rd),
3806 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3807 sep4.ip6, sep4.epg.rd)])],
3808 [ETH_P_IP, ETH_P_IPV6])
3811 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3814 self.assertEqual(rx[Ether].src, routed_src_mac)
3815 self.assertEqual(rx[Ether].dst, sep1.mac)
3816 self.assertEqual(rx[IP].src, ep1.ip4)
3817 self.assertEqual(rx[IP].dst, "10.0.0.88")
3819 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep3.itf)
3822 self.assertEqual(rx[Ether].src, routed_src_mac)
3823 self.assertEqual(rx[Ether].dst, sep3.mac)
3824 self.assertEqual(rx[IPv6].src, ep1.ip6)
3825 self.assertEqual(rx[IPv6].dst, "2001:10::88")
3828 # a programmed remote SEP in EPG 320
3831 # gbp vxlan tunnel for the remote SEP
3832 vx_tun_l3_sep = VppGbpVxlanTunnel(
3833 self, 555, rd1.rd_id,
3834 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
3836 vx_tun_l3_sep.add_vpp_config()
3839 sep5 = VppGbpEndpoint(self, vx_tun_l3_sep,
3841 "12.0.0.10", "13.0.0.10",
3842 "4001:10::10", "5001:10::10",
3843 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
3845 self.pg7.remote_ip4,
3847 sep5.add_vpp_config()
3850 # local l3out redirect tests
3855 self.loop4.set_mac(self.router_mac)
3856 b_lo4_ip4 = VppIpInterfaceBind(self, self.loop4, t4).add_vpp_config()
3857 b_lo4_ip6 = VppIpInterfaceBind(self, self.loop4, t6).add_vpp_config()
3858 ebd = VppBridgeDomain(self, 100)
3859 ebd.add_vpp_config()
3860 gebd = VppGbpBridgeDomain(self, ebd, rd1, self.loop4, None, None)
3861 gebd.add_vpp_config()
3863 eepg = VppGbpEndpointGroup(self, 888, 765, rd1, gebd,
3867 VppGbpEndpointRetention(60))
3868 eepg.add_vpp_config()
3869 # add subnets to BVI
3870 VppIpInterfaceAddress(
3874 24, bind=b_lo4_ip4).add_vpp_config()
3875 VppIpInterfaceAddress(
3879 64, bind=b_lo4_ip6).add_vpp_config()
3880 # ... which are L3-out subnets
3881 VppGbpSubnet(self, rd1, "10.1.0.0", 24,
3882 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3883 sclass=765).add_vpp_config()
3884 VppGbpSubnet(self, rd1, "2001:10:1::128", 64,
3885 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3886 sclass=765).add_vpp_config()
3887 # external endpoints
3888 VppL2Vtr(self, self.vlan_100, L2_VTR_OP.L2_POP_1).add_vpp_config()
3889 eep1 = VppGbpEndpoint(self, self.vlan_100, eepg, None, "10.1.0.1",
3890 "11.1.0.1", "2001:10:1::1", "3001:10:1::1",
3891 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
3892 eep1.add_vpp_config()
3893 VppL2Vtr(self, self.vlan_101, L2_VTR_OP.L2_POP_1).add_vpp_config()
3894 eep2 = VppGbpEndpoint(self, self.vlan_101, eepg, None, "10.1.0.2",
3895 "11.1.0.2", "2001:10:1::2", "3001:10:1::2",
3896 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
3897 eep2.add_vpp_config()
3899 # external subnets reachable though eep1 and eep2 respectively
3900 VppIpRoute(self, "10.220.0.0", 24,
3901 [VppRoutePath(eep1.ip4, eep1.epg.bvi.sw_if_index)],
3902 table_id=t4.table_id).add_vpp_config()
3903 VppGbpSubnet(self, rd1, "10.220.0.0", 24,
3904 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3905 sclass=4220).add_vpp_config()
3906 VppIpRoute(self, "10:220::", 64,
3907 [VppRoutePath(eep1.ip6, eep1.epg.bvi.sw_if_index)],
3908 table_id=t6.table_id).add_vpp_config()
3909 VppGbpSubnet(self, rd1, "10:220::", 64,
3910 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3911 sclass=4220).add_vpp_config()
3912 VppIpRoute(self, "10.221.0.0", 24,
3913 [VppRoutePath(eep2.ip4, eep2.epg.bvi.sw_if_index)],
3914 table_id=t4.table_id).add_vpp_config()
3915 VppGbpSubnet(self, rd1, "10.221.0.0", 24,
3916 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3917 sclass=4221).add_vpp_config()
3918 VppIpRoute(self, "10:221::", 64,
3919 [VppRoutePath(eep2.ip6, eep2.epg.bvi.sw_if_index)],
3920 table_id=t6.table_id).add_vpp_config()
3921 VppGbpSubnet(self, rd1, "10:221::", 64,
3922 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3923 sclass=4221).add_vpp_config()
3926 # l3out redirect to remote (known, then unknown) SEP
3929 # packets from 1 external subnet to the other
3930 p = [(Ether(src=eep1.mac, dst=self.router_mac) /
3932 IP(src="10.220.0.17", dst="10.221.0.65") /
3933 UDP(sport=1234, dport=1234) /
3934 Raw(b'\xa5' * 100)),
3935 (Ether(src=eep1.mac, dst=self.router_mac) /
3937 IPv6(src="10:220::17", dst="10:221::65") /
3938 UDP(sport=1234, dport=1234) /
3939 Raw(b'\xa5' * 100))]
3941 # packets should be dropped in absence of contract
3942 self.send_and_assert_no_replies(self.pg0, p)
3944 # contract redirecting to sep5
3946 self, 402, 4220, 4221, acl.acl_index,
3947 [VppGbpContractRule(
3948 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3949 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
3950 [VppGbpContractNextHop(sep5.vmac, sep5.epg.bd,
3951 sep5.ip4, sep5.epg.rd)]),
3953 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3954 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
3955 [VppGbpContractNextHop(sep5.vmac, sep5.epg.bd,
3956 sep5.ip6, sep5.epg.rd)])],
3957 [ETH_P_IP, ETH_P_IPV6]).add_vpp_config()
3959 rxs = self.send_and_expect(self.pg0, p, self.pg7)
3961 for rx, tx in zip(rxs, p):
3962 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3963 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3964 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3965 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
3966 # this should use the programmed remote leaf TEP
3967 self.assertEqual(rx[VXLAN].vni, 555)
3968 self.assertEqual(rx[VXLAN].gpid, 4220)
3969 self.assertTrue(rx[VXLAN].flags.G)
3970 self.assertTrue(rx[VXLAN].flags.Instance)
3971 # redirect policy has been applied
3972 self.assertTrue(rx[VXLAN].gpflags.A)
3973 self.assertTrue(rx[VXLAN].gpflags.D)
3974 rxip = rx[VXLAN][Ether].payload
3975 txip = tx[Dot1Q].payload
3976 self.assertEqual(rxip.src, txip.src)
3977 self.assertEqual(rxip.dst, txip.dst)
3979 # remote SEP: it is now an unknown remote SEP and should go
3981 sep5.remove_vpp_config()
3983 rxs = self.send_and_expect(self.pg0, p, self.pg7)
3985 for rx, tx in zip(rxs, p):
3986 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3987 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3988 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3989 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
3990 # this should use the spine proxy TEP
3991 self.assertEqual(rx[VXLAN].vni, epg_320.bd.uu_fwd.vni)
3992 self.assertEqual(rx[VXLAN].gpid, 4220)
3993 self.assertTrue(rx[VXLAN].flags.G)
3994 self.assertTrue(rx[VXLAN].flags.Instance)
3995 # redirect policy has been applied
3996 self.assertTrue(rx[VXLAN].gpflags.A)
3997 self.assertTrue(rx[VXLAN].gpflags.D)
3998 rxip = rx[VXLAN][Ether].payload
3999 txip = tx[Dot1Q].payload
4000 self.assertEqual(rxip.src, txip.src)
4001 self.assertEqual(rxip.dst, txip.dst)
4004 # l3out redirect to local SEP
4007 # change the contract between l3out to redirect to local SEPs
4008 # instead of remote SEP
4010 self, 402, 4220, 4221, acl.acl_index,
4011 [VppGbpContractRule(
4012 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4013 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
4014 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
4015 sep1.ip4, sep1.epg.rd)]),
4017 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4018 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
4019 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
4020 sep1.ip6, sep1.epg.rd)])],
4021 [ETH_P_IP, ETH_P_IPV6]).add_vpp_config()
4023 rxs = self.send_and_expect(self.pg0, p, sep1.itf)
4024 for rx, tx in zip(rxs, p):
4025 self.assertEqual(rx[Ether].src, routed_src_mac)
4026 self.assertEqual(rx[Ether].dst, sep1.mac)
4027 rxip = rx[Ether].payload
4028 txip = tx[Ether].payload
4029 self.assertEqual(rxip.src, txip.src)
4030 self.assertEqual(rxip.dst, txip.dst)
4033 # redirect remote EP to remote (known then unknown) SEP
4036 # remote SEP known again
4037 sep5.add_vpp_config()
4039 # contract to redirect to learnt SEP
4041 self, 402, epg_221.sclass, epg_222.sclass, acl.acl_index,
4042 [VppGbpContractRule(
4043 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4044 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
4045 [VppGbpContractNextHop(sep5.vmac, sep5.epg.bd,
4046 sep5.ip4, sep5.epg.rd)]),
4048 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4049 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
4050 [VppGbpContractNextHop(sep5.vmac, sep5.epg.bd,
4051 sep5.ip6, sep5.epg.rd)])],
4052 [ETH_P_IP, ETH_P_IPV6]).add_vpp_config()
4054 # packets from unknown EP 221 to known EP in EPG 222
4055 # should be redirected to known remote SEP
4056 base = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
4057 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
4058 UDP(sport=1234, dport=48879) /
4059 VXLAN(vni=444, gpid=441, flags=0x88) /
4060 Ether(src="00:22:22:22:22:44", dst=str(self.router_mac)))
4062 IP(src="10.0.1.100", dst=ep3.ip4) /
4063 UDP(sport=1234, dport=1234) /
4064 Raw(b'\xa5' * 100)),
4066 IPv6(src="2001:10::100", dst=ep3.ip6) /
4067 UDP(sport=1234, dport=1234) /
4068 Raw(b'\xa5' * 100))]
4070 # unknown remote EP to local EP redirected to known remote SEP
4071 rxs = self.send_and_expect(self.pg7, p, self.pg7)
4073 for rx, tx in zip(rxs, p):
4074 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4075 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4076 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4077 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4078 # this should use the programmed remote leaf TEP
4079 self.assertEqual(rx[VXLAN].vni, 555)
4080 self.assertEqual(rx[VXLAN].gpid, epg_221.sclass)
4081 self.assertTrue(rx[VXLAN].flags.G)
4082 self.assertTrue(rx[VXLAN].flags.Instance)
4083 # redirect policy has been applied
4084 self.assertTrue(rx[VXLAN].gpflags.A)
4085 self.assertFalse(rx[VXLAN].gpflags.D)
4086 rxip = rx[VXLAN][Ether].payload
4087 txip = tx[VXLAN][Ether].payload
4088 self.assertEqual(rxip.src, txip.src)
4089 self.assertEqual(rxip.dst, txip.dst)
4091 # endpoint learnt via the parent GBP-vxlan interface
4092 self.assertTrue(find_gbp_endpoint(self,
4093 vx_tun_l3._sw_if_index,
4095 self.assertTrue(find_gbp_endpoint(self,
4096 vx_tun_l3._sw_if_index,
4099 # remote SEP: it is now an unknown remote SEP and should go
4101 sep5.remove_vpp_config()
4103 # remote EP (coming from spine proxy) to local EP redirected to
4105 rxs = self.send_and_expect(self.pg7, p, self.pg7)
4107 for rx, tx in zip(rxs, p):
4108 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4109 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4110 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4111 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4112 # this should use the spine proxy TEP
4113 self.assertEqual(rx[VXLAN].vni, epg_320.bd.uu_fwd.vni)
4114 self.assertEqual(rx[VXLAN].gpid, epg_221.sclass)
4115 self.assertTrue(rx[VXLAN].flags.G)
4116 self.assertTrue(rx[VXLAN].flags.Instance)
4117 # redirect policy has been applied
4118 self.assertTrue(rx[VXLAN].gpflags.A)
4119 self.assertFalse(rx[VXLAN].gpflags.D)
4120 rxip = rx[VXLAN][Ether].payload
4121 txip = tx[VXLAN][Ether].payload
4122 self.assertEqual(rxip.src, txip.src)
4123 self.assertEqual(rxip.dst, txip.dst)
4128 self.pg7.unconfig_ip4()
4130 def test_gbp_redirect_extended(self):
4131 """ GBP Endpoint Redirect Extended """
4133 self.vapi.cli("set logging class gbp level debug")
4135 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
4136 routed_dst_mac = "00:0c:0c:0c:0c:0c"
4137 routed_src_mac = "00:22:bd:f8:19:ff"
4139 learnt = [{'mac': '00:00:11:11:11:02',
4141 'ip6': '2001:10::2'},
4142 {'mac': '00:00:11:11:11:03',
4144 'ip6': '2001:10::3'}]
4149 t4 = VppIpTable(self, 1)
4151 t6 = VppIpTable(self, 1, True)
4154 # create IPv4 and IPv6 RD UU VxLAN-GBP TEP and bind them to the right
4156 rd_uu4 = VppVxlanGbpTunnel(
4159 self.pg7.remote_ip4,
4161 mode=(VppEnum.vl_api_vxlan_gbp_api_tunnel_mode_t.
4162 VXLAN_GBP_API_TUNNEL_MODE_L3))
4163 rd_uu4.add_vpp_config()
4164 VppIpInterfaceBind(self, rd_uu4, t4).add_vpp_config()
4166 rd_uu6 = VppVxlanGbpTunnel(
4169 self.pg7.remote_ip4,
4171 mode=(VppEnum.vl_api_vxlan_gbp_api_tunnel_mode_t.
4172 VXLAN_GBP_API_TUNNEL_MODE_L3))
4173 rd_uu6.add_vpp_config()
4174 VppIpInterfaceBind(self, rd_uu6, t4).add_vpp_config()
4176 rd1 = VppGbpRouteDomain(self, 2, 402, t4, t6, rd_uu4, rd_uu6)
4177 rd1.add_vpp_config()
4179 self.loop0.set_mac(self.router_mac)
4180 self.loop1.set_mac(self.router_mac)
4181 self.loop2.set_mac(self.router_mac)
4184 # Bind the BVI to the RD
4186 b_lo0_ip4 = VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
4187 b_lo0_ip6 = VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
4188 b_lo1_ip4 = VppIpInterfaceBind(self, self.loop1, t4).add_vpp_config()
4189 b_lo1_ip6 = VppIpInterfaceBind(self, self.loop1, t6).add_vpp_config()
4190 b_lo2_ip4 = VppIpInterfaceBind(self, self.loop2, t4).add_vpp_config()
4191 b_lo2_ip6 = VppIpInterfaceBind(self, self.loop2, t6).add_vpp_config()
4194 # Pg7 hosts a BD's UU-fwd
4196 self.pg7.config_ip4()
4197 self.pg7.resolve_arp()
4200 # a GBP bridge domains for the EPs
4202 bd1 = VppBridgeDomain(self, 1)
4203 bd1.add_vpp_config()
4204 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0)
4205 gbd1.add_vpp_config()
4207 bd2 = VppBridgeDomain(self, 2)
4208 bd2.add_vpp_config()
4209 gbd2 = VppGbpBridgeDomain(self, bd2, rd1, self.loop1)
4210 gbd2.add_vpp_config()
4212 # ... and has a /32 and /128 applied
4213 ip4_addr1 = VppIpInterfaceAddress(self, gbd1.bvi,
4215 bind=b_lo0_ip4).add_vpp_config()
4216 ip6_addr1 = VppIpInterfaceAddress(self, gbd1.bvi,
4217 "2001:10::128", 128,
4218 bind=b_lo0_ip6).add_vpp_config()
4219 ip4_addr2 = VppIpInterfaceAddress(self, gbd2.bvi,
4221 bind=b_lo1_ip4).add_vpp_config()
4222 ip6_addr2 = VppIpInterfaceAddress(self, gbd2.bvi,
4223 "2001:11::128", 128,
4224 bind=b_lo1_ip6).add_vpp_config()
4227 # The Endpoint-groups
4229 epg_220 = VppGbpEndpointGroup(self, 220, 440, rd1, gbd1,
4233 VppGbpEndpointRetention(60))
4234 epg_220.add_vpp_config()
4235 epg_221 = VppGbpEndpointGroup(self, 221, 441, rd1, gbd2,
4239 VppGbpEndpointRetention(60))
4240 epg_221.add_vpp_config()
4243 # a GBP bridge domains for the SEPs
4245 bd_uu3 = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
4246 self.pg7.remote_ip4, 116)
4247 bd_uu3.add_vpp_config()
4249 bd3 = VppBridgeDomain(self, 3)
4250 bd3.add_vpp_config()
4251 gbd3 = VppGbpBridgeDomain(self, bd3, rd1, self.loop2,
4252 bd_uu3, learn=False)
4253 gbd3.add_vpp_config()
4255 ip4_addr3 = VppIpInterfaceAddress(self, gbd3.bvi,
4257 bind=b_lo2_ip4).add_vpp_config()
4258 ip6_addr3 = VppIpInterfaceAddress(self, gbd3.bvi,
4259 "4001:10::128", 128,
4260 bind=b_lo2_ip6).add_vpp_config()
4263 # self.logger.info(self.vapi.cli("show gbp bridge"))
4264 # self.logger.info(self.vapi.cli("show vxlan-gbp tunnel"))
4265 # self.logger.info(self.vapi.cli("show gbp vxlan"))
4266 # self.logger.info(self.vapi.cli("show int addr"))
4270 # EPGs in which the service endpoints exist
4272 epg_320 = VppGbpEndpointGroup(self, 320, 550, rd1, gbd3,
4276 VppGbpEndpointRetention(60))
4277 epg_320.add_vpp_config()
4282 ep1 = VppGbpEndpoint(self, self.pg0,
4284 "10.0.0.1", "11.0.0.1",
4285 "2001:10::1", "3001:10::1")
4286 ep1.add_vpp_config()
4287 ep2 = VppGbpEndpoint(self, self.pg1,
4289 "10.0.1.1", "11.0.1.1",
4290 "2001:11::1", "3001:11::1")
4291 ep2.add_vpp_config()
4296 sep1 = VppGbpEndpoint(self, self.pg3,
4298 "12.0.0.1", "13.0.0.1",
4299 "4001:10::1", "5001:10::1")
4300 sep2 = VppGbpEndpoint(self, self.pg4,
4302 "12.0.0.2", "13.0.0.2",
4303 "4001:10::2", "5001:10::2")
4305 # sep1 and sep2 are not added to config yet
4306 # they are unknown for now
4309 # add routes to EPG subnets
4311 VppGbpSubnet(self, rd1, "10.0.0.0", 24,
4312 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT
4314 VppGbpSubnet(self, rd1, "10.0.1.0", 24,
4315 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT
4319 # Local host to known local host in different BD
4320 # with SFC contract (source and destination are in
4321 # one node and service endpoint in another node)
4323 p4 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
4324 IP(src=ep1.ip4, dst=ep2.ip4) /
4325 UDP(sport=1234, dport=1234) /
4326 Raw(b'\xa5' * 100)),
4327 (Ether(src=ep2.mac, dst=str(self.router_mac)) /
4328 IP(src=ep2.ip4, dst=ep1.ip4) /
4329 UDP(sport=1234, dport=1234) /
4330 Raw(b'\xa5' * 100))]
4331 p6 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
4332 IPv6(src=ep1.ip6, dst=ep2.ip6) /
4333 UDP(sport=1234, dport=1234) /
4334 Raw(b'\xa5' * 100)),
4335 (Ether(src=ep2.mac, dst=str(self.router_mac)) /
4336 IPv6(src=ep2.ip6, dst=ep1.ip6) /
4337 UDP(sport=1234, dport=1230) /
4338 Raw(b'\xa5' * 100))]
4340 # should be dropped since no contract yet
4341 self.send_and_assert_no_replies(self.pg0, [p4[0]])
4342 self.send_and_assert_no_replies(self.pg0, [p6[0]])
4345 # Add a contract with a rule to load-balance redirect via SEP1 and SEP2
4346 # one of the next-hops is via an EP that is not known
4348 rule4 = AclRule(is_permit=1, proto=17)
4349 rule6 = AclRule(src_prefix=IPv6Network((0, 0)),
4350 dst_prefix=IPv6Network((0, 0)), is_permit=1, proto=17)
4351 acl = VppAcl(self, rules=[rule4, rule6])
4352 acl.add_vpp_config()
4355 # test the src-ip hash mode
4357 c1 = VppGbpContract(
4358 self, 402, epg_220.sclass, epg_221.sclass, acl.acl_index,
4359 [VppGbpContractRule(
4360 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4361 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
4362 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
4363 sep1.ip4, sep1.epg.rd)]),
4365 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4366 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
4367 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
4368 sep1.ip6, sep1.epg.rd)])],
4369 [ETH_P_IP, ETH_P_IPV6])
4372 c2 = VppGbpContract(
4373 self, 402, epg_221.sclass, epg_220.sclass, acl.acl_index,
4374 [VppGbpContractRule(
4375 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4376 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
4377 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
4378 sep1.ip4, sep1.epg.rd)]),
4380 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4381 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
4382 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
4383 sep1.ip6, sep1.epg.rd)])],
4384 [ETH_P_IP, ETH_P_IPV6])
4387 # ep1 <--> ep2 redirected through sep1
4389 # packet is redirected to sep bd and then go through sep bd UU
4391 rxs = self.send_and_expect(self.pg0, p4[0] * 17, self.pg7)
4394 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4395 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4396 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4397 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4398 self.assertEqual(rx[VXLAN].vni, 116)
4399 self.assertTrue(rx[VXLAN].flags.G)
4400 self.assertTrue(rx[VXLAN].flags.Instance)
4401 # redirect policy has been applied
4402 self.assertTrue(rx[VXLAN].gpflags.A)
4403 self.assertFalse(rx[VXLAN].gpflags.D)
4405 inner = rx[VXLAN].payload
4407 self.assertEqual(inner[Ether].src, routed_src_mac)
4408 self.assertEqual(inner[Ether].dst, sep1.mac)
4409 self.assertEqual(inner[IP].src, ep1.ip4)
4410 self.assertEqual(inner[IP].dst, ep2.ip4)
4412 rxs = self.send_and_expect(self.pg1, p4[1] * 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, ep2.ip4)
4431 self.assertEqual(inner[IP].dst, ep1.ip4)
4433 rxs = self.send_and_expect(self.pg0, p6[0] * 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 inner = rx[VXLAN].payload
4446 self.assertEqual(inner[Ether].src, routed_src_mac)
4447 self.assertEqual(inner[Ether].dst, sep1.mac)
4448 self.assertEqual(inner[IPv6].src, ep1.ip6)
4449 self.assertEqual(inner[IPv6].dst, ep2.ip6)
4451 rxs = self.send_and_expect(self.pg1, p6[1] * 17, self.pg7)
4454 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4455 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4456 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4457 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4458 self.assertEqual(rx[VXLAN].vni, 116)
4459 self.assertTrue(rx[VXLAN].flags.G)
4460 self.assertTrue(rx[VXLAN].flags.Instance)
4461 # redirect policy has been applied
4462 self.assertTrue(rx[VXLAN].gpflags.A)
4463 self.assertFalse(rx[VXLAN].gpflags.D)
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, ep2.ip6)
4470 self.assertEqual(inner[IPv6].dst, ep1.ip6)
4472 # configure sep1: it is now local
4473 # packets between ep1 and ep2 are redirected locally
4474 sep1.add_vpp_config()
4476 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
4479 self.assertEqual(rx[Ether].src, routed_src_mac)
4480 self.assertEqual(rx[Ether].dst, sep1.mac)
4481 self.assertEqual(rx[IP].src, ep1.ip4)
4482 self.assertEqual(rx[IP].dst, ep2.ip4)
4484 rxs = self.send_and_expect(self.pg1, p6[1] * 17, sep1.itf)
4487 self.assertEqual(rx[Ether].src, routed_src_mac)
4488 self.assertEqual(rx[Ether].dst, sep1.mac)
4489 self.assertEqual(rx[IPv6].src, ep2.ip6)
4490 self.assertEqual(rx[IPv6].dst, ep1.ip6)
4492 # packet coming from the l2 spine-proxy to sep1
4493 p = (Ether(src=self.pg7.remote_mac,
4494 dst=self.pg7.local_mac) /
4495 IP(src=self.pg7.remote_ip4,
4496 dst=self.pg7.local_ip4) /
4497 UDP(sport=1234, dport=48879) /
4498 VXLAN(vni=116, gpid=440, gpflags=0x08, flags=0x88) /
4499 Ether(src=str(self.router_mac), dst=sep1.mac) /
4500 IP(src=ep1.ip4, dst=ep2.ip4) /
4501 UDP(sport=1234, dport=1234) /
4504 rxs = self.send_and_expect(self.pg7, [p] * 17, sep1.itf)
4507 self.assertEqual(rx[Ether].src, str(self.router_mac))
4508 self.assertEqual(rx[Ether].dst, sep1.mac)
4509 self.assertEqual(rx[IP].src, ep1.ip4)
4510 self.assertEqual(rx[IP].dst, ep2.ip4)
4512 # contract for SEP to communicate with dst EP
4513 c3 = VppGbpContract(
4514 self, 402, epg_320.sclass, epg_221.sclass, acl.acl_index,
4515 [VppGbpContractRule(
4516 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4517 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC),
4519 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4520 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC)],
4521 [ETH_P_IP, ETH_P_IPV6])
4524 # temporarily remove ep2, so that ep2 is remote & unknown
4525 ep2.remove_vpp_config()
4527 # packet going back from sep1 to its original dest (ep2)
4528 # as ep2 is now unknown (see above), it must go through
4529 # the rd UU (packet is routed)
4531 p1 = (Ether(src=sep1.mac, dst=self.router_mac) /
4532 IP(src=ep1.ip4, dst=ep2.ip4) /
4533 UDP(sport=1234, dport=1234) /
4536 rxs = self.send_and_expect(self.pg3, [p1] * 17, self.pg7)
4539 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4540 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4541 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4542 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4543 self.assertEqual(rx[VXLAN].vni, 114)
4544 self.assertTrue(rx[VXLAN].flags.G)
4545 self.assertTrue(rx[VXLAN].flags.Instance)
4546 # redirect policy has been applied
4547 inner = rx[VXLAN].payload
4548 self.assertEqual(inner[Ether].src, routed_src_mac)
4549 self.assertEqual(inner[Ether].dst, routed_dst_mac)
4550 self.assertEqual(inner[IP].src, ep1.ip4)
4551 self.assertEqual(inner[IP].dst, ep2.ip4)
4553 self.logger.info(self.vapi.cli("show bridge 3 detail"))
4554 sep1.remove_vpp_config()
4556 self.logger.info(self.vapi.cli("show bridge 1 detail"))
4557 self.logger.info(self.vapi.cli("show bridge 2 detail"))
4559 # re-add ep2: it is local again :)
4560 ep2.add_vpp_config()
4562 # packet coming back from the remote sep through rd UU
4563 p2 = (Ether(src=self.pg7.remote_mac,
4564 dst=self.pg7.local_mac) /
4565 IP(src=self.pg7.remote_ip4,
4566 dst=self.pg7.local_ip4) /
4567 UDP(sport=1234, dport=48879) /
4568 VXLAN(vni=114, gpid=441, gpflags=0x09, flags=0x88) /
4569 Ether(src=str(self.router_mac), dst=self.router_mac) /
4570 IP(src=ep1.ip4, dst=ep2.ip4) /
4571 UDP(sport=1234, dport=1234) /
4574 rxs = self.send_and_expect(self.pg7, [p2], self.pg1)
4577 self.assertEqual(rx[Ether].src, str(self.router_mac))
4578 self.assertEqual(rx[Ether].dst, self.pg1.remote_mac)
4579 self.assertEqual(rx[IP].src, ep1.ip4)
4580 self.assertEqual(rx[IP].dst, ep2.ip4)
4583 # bd_uu2.add_vpp_config()
4589 c1.remove_vpp_config()
4590 c2.remove_vpp_config()
4591 c3.remove_vpp_config()
4592 self.pg7.unconfig_ip4()
4594 def test_gbp_l3_out(self):
4597 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
4598 self.vapi.cli("set logging class gbp level debug")
4600 routed_dst_mac = "00:0c:0c:0c:0c:0c"
4601 routed_src_mac = "00:22:bd:f8:19:ff"
4606 t4 = VppIpTable(self, 1)
4608 t6 = VppIpTable(self, 1, True)
4611 rd1 = VppGbpRouteDomain(self, 2, 55, t4, t6)
4612 rd1.add_vpp_config()
4614 self.loop0.set_mac(self.router_mac)
4617 # Bind the BVI to the RD
4619 b_ip4 = VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
4620 b_ip6 = VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
4623 # Pg7 hosts a BD's BUM
4624 # Pg1 some other l3 interface
4626 self.pg7.config_ip4()
4627 self.pg7.resolve_arp()
4630 # a multicast vxlan-gbp tunnel for broadcast in the BD
4632 tun_bm = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
4635 tun_bm.add_vpp_config()
4638 # a GBP external bridge domains for the EPs
4640 bd1 = VppBridgeDomain(self, 1)
4641 bd1.add_vpp_config()
4642 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0, None, tun_bm)
4643 gbd1.add_vpp_config()
4646 # The Endpoint-groups in which the external endpoints exist
4648 epg_220 = VppGbpEndpointGroup(self, 220, 113, rd1, gbd1,
4652 VppGbpEndpointRetention(4))
4653 epg_220.add_vpp_config()
4655 # the BVIs have the subnets applied ...
4656 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128",
4657 24, bind=b_ip4).add_vpp_config()
4658 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128",
4659 64, bind=b_ip6).add_vpp_config()
4661 # ... which are L3-out subnets
4662 l3o_1 = VppGbpSubnet(
4663 self, rd1, "10.0.0.0", 24,
4664 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
4666 l3o_1.add_vpp_config()
4669 # an external interface attached to the outside world and the
4672 VppL2Vtr(self, self.vlan_100, L2_VTR_OP.L2_POP_1).add_vpp_config()
4673 VppL2Vtr(self, self.vlan_101, L2_VTR_OP.L2_POP_1).add_vpp_config()
4674 vlan_144 = VppDot1QSubint(self, self.pg0, 144)
4676 # vlan_102 is not poped
4679 # an unicast vxlan-gbp for inter-RD traffic
4681 vx_tun_l3 = VppGbpVxlanTunnel(
4682 self, 444, rd1.rd_id,
4683 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
4685 vx_tun_l3.add_vpp_config()
4688 # External Endpoints
4690 eep1 = VppGbpEndpoint(self, self.vlan_100,
4692 "10.0.0.1", "11.0.0.1",
4693 "2001:10::1", "3001::1",
4694 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
4695 eep1.add_vpp_config()
4696 eep2 = VppGbpEndpoint(self, self.vlan_101,
4698 "10.0.0.2", "11.0.0.2",
4699 "2001:10::2", "3001::2",
4700 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
4701 eep2.add_vpp_config()
4702 eep3 = VppGbpEndpoint(self, self.vlan_102,
4704 "10.0.0.3", "11.0.0.3",
4705 "2001:10::3", "3001::3",
4706 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
4707 eep3.add_vpp_config()
4710 # A remote external endpoint
4712 rep = VppGbpEndpoint(self, vx_tun_l3,
4714 "10.0.0.101", "11.0.0.101",
4715 "2001:10::101", "3001::101",
4716 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
4718 self.pg7.remote_ip4,
4720 rep.add_vpp_config()
4723 # EP1 impersonating EP3 is dropped
4725 p = (Ether(src=eep1.mac, dst="ff:ff:ff:ff:ff:ff") /
4728 psrc="10.0.0.3", pdst="10.0.0.128",
4729 hwsrc=eep1.mac, hwdst="ff:ff:ff:ff:ff:ff"))
4730 self.send_and_assert_no_replies(self.pg0, p)
4733 # ARP packet from External EPs are accepted and replied to
4735 p_arp = (Ether(src=eep1.mac, dst="ff:ff:ff:ff:ff:ff") /
4738 psrc=eep1.ip4, pdst="10.0.0.128",
4739 hwsrc=eep1.mac, hwdst="ff:ff:ff:ff:ff:ff"))
4740 rxs = self.send_and_expect(self.pg0, p_arp * 1, self.pg0)
4743 # ARP packet from host in remote subnet are accepted and replied to
4745 p_arp = (Ether(src=eep3.mac, dst="ff:ff:ff:ff:ff:ff") /
4748 psrc=eep3.ip4, pdst="10.0.0.128",
4749 hwsrc=eep3.mac, hwdst="ff:ff:ff:ff:ff:ff"))
4750 rxs = self.send_and_expect(self.pg0, p_arp * 1, self.pg0)
4753 # packets destined to unknown addresses in the BVI's subnet
4756 p4 = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
4758 IP(src="10.0.0.1", dst="10.0.0.88") /
4759 UDP(sport=1234, dport=1234) /
4761 p6 = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
4763 IPv6(src="2001:10::1", dst="2001:10::88") /
4764 UDP(sport=1234, dport=1234) /
4767 rxs = self.send_and_expect(self.pg0, p4 * 1, self.pg7)
4770 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4771 # self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4772 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4773 self.assertEqual(rx[IP].dst, "239.1.1.1")
4774 self.assertEqual(rx[VXLAN].vni, 88)
4775 self.assertTrue(rx[VXLAN].flags.G)
4776 self.assertTrue(rx[VXLAN].flags.Instance)
4777 # policy was applied to the original IP packet
4778 self.assertEqual(rx[VXLAN].gpid, 113)
4779 self.assertTrue(rx[VXLAN].gpflags.A)
4780 self.assertFalse(rx[VXLAN].gpflags.D)
4782 inner = rx[VXLAN].payload
4784 self.assertTrue(inner.haslayer(ARP))
4787 # remote to external
4789 p = (Ether(src=self.pg7.remote_mac,
4790 dst=self.pg7.local_mac) /
4791 IP(src=self.pg7.remote_ip4,
4792 dst=self.pg7.local_ip4) /
4793 UDP(sport=1234, dport=48879) /
4794 VXLAN(vni=444, gpid=113, flags=0x88) /
4795 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
4796 IP(src="10.0.0.101", dst="10.0.0.1") /
4797 UDP(sport=1234, dport=1234) /
4800 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
4803 # local EP pings router
4805 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
4807 IP(src=eep1.ip4, dst="10.0.0.128") /
4808 ICMP(type='echo-request'))
4810 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
4813 self.assertEqual(rx[Ether].src, str(self.router_mac))
4814 self.assertEqual(rx[Ether].dst, eep1.mac)
4815 self.assertEqual(rx[Dot1Q].vlan, 100)
4818 # local EP pings other local EP
4820 p = (Ether(src=eep1.mac, dst=eep2.mac) /
4822 IP(src=eep1.ip4, dst=eep2.ip4) /
4823 ICMP(type='echo-request'))
4825 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
4828 self.assertEqual(rx[Ether].src, eep1.mac)
4829 self.assertEqual(rx[Ether].dst, eep2.mac)
4830 self.assertEqual(rx[Dot1Q].vlan, 101)
4833 # local EP pings router w/o vlan tag poped
4835 p = (Ether(src=eep3.mac, dst=str(self.router_mac)) /
4837 IP(src=eep3.ip4, dst="10.0.0.128") /
4838 ICMP(type='echo-request'))
4840 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
4843 self.assertEqual(rx[Ether].src, str(self.router_mac))
4844 self.assertEqual(rx[Ether].dst, self.vlan_102.remote_mac)
4847 # A ip4 subnet reachable through the external EP1
4849 ip_220 = VppIpRoute(self, "10.220.0.0", 24,
4850 [VppRoutePath(eep1.ip4,
4851 eep1.epg.bvi.sw_if_index)],
4852 table_id=t4.table_id)
4853 ip_220.add_vpp_config()
4855 l3o_220 = VppGbpSubnet(
4856 self, rd1, "10.220.0.0", 24,
4857 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
4859 l3o_220.add_vpp_config()
4862 # An ip6 subnet reachable through the external EP1
4864 ip6_220 = VppIpRoute(self, "10:220::", 64,
4865 [VppRoutePath(eep1.ip6,
4866 eep1.epg.bvi.sw_if_index)],
4867 table_id=t6.table_id)
4868 ip6_220.add_vpp_config()
4870 l3o6_220 = VppGbpSubnet(
4871 self, rd1, "10:220::", 64,
4872 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
4874 l3o6_220.add_vpp_config()
4877 # A subnet reachable through the external EP2
4879 ip_221 = VppIpRoute(self, "10.221.0.0", 24,
4880 [VppRoutePath(eep2.ip4,
4881 eep2.epg.bvi.sw_if_index)],
4882 table_id=t4.table_id)
4883 ip_221.add_vpp_config()
4885 l3o_221 = VppGbpSubnet(
4886 self, rd1, "10.221.0.0", 24,
4887 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
4889 l3o_221.add_vpp_config()
4892 # ping between hosts in remote subnets
4893 # dropped without a contract
4895 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
4897 IP(src="10.220.0.1", dst="10.221.0.1") /
4898 ICMP(type='echo-request'))
4900 self.send_and_assert_no_replies(self.pg0, p * 1)
4903 # contract for the external nets to communicate
4905 rule4 = AclRule(is_permit=1, proto=17)
4906 rule6 = AclRule(src_prefix=IPv6Network((0, 0)),
4907 dst_prefix=IPv6Network((0, 0)), is_permit=1, proto=17)
4908 acl = VppAcl(self, rules=[rule4, rule6])
4909 acl.add_vpp_config()
4912 # A contract with the wrong scope is not matched
4914 c_44 = VppGbpContract(
4915 self, 44, 4220, 4221, acl.acl_index,
4916 [VppGbpContractRule(
4917 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4918 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4921 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4922 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4924 [ETH_P_IP, ETH_P_IPV6])
4925 c_44.add_vpp_config()
4926 self.send_and_assert_no_replies(self.pg0, p * 1)
4928 c1 = VppGbpContract(
4929 self, 55, 4220, 4221, acl.acl_index,
4930 [VppGbpContractRule(
4931 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4932 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4935 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4936 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4938 [ETH_P_IP, ETH_P_IPV6])
4942 # Contracts allowing ext-net 200 to talk with external EPs
4944 c2 = VppGbpContract(
4945 self, 55, 4220, 113, acl.acl_index,
4946 [VppGbpContractRule(
4947 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4948 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4951 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4952 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4954 [ETH_P_IP, ETH_P_IPV6])
4956 c3 = VppGbpContract(
4957 self, 55, 113, 4220, acl.acl_index,
4958 [VppGbpContractRule(
4959 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4960 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4963 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4964 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4966 [ETH_P_IP, ETH_P_IPV6])
4970 # ping between hosts in remote subnets
4972 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
4974 IP(src="10.220.0.1", dst="10.221.0.1") /
4975 UDP(sport=1234, dport=1234) /
4978 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
4981 self.assertEqual(rx[Ether].src, str(self.router_mac))
4982 self.assertEqual(rx[Ether].dst, eep2.mac)
4983 self.assertEqual(rx[Dot1Q].vlan, 101)
4985 # we did not learn these external hosts
4986 self.assertFalse(find_gbp_endpoint(self, ip="10.220.0.1"))
4987 self.assertFalse(find_gbp_endpoint(self, ip="10.221.0.1"))
4990 # from remote external EP to local external EP
4992 p = (Ether(src=self.pg7.remote_mac,
4993 dst=self.pg7.local_mac) /
4994 IP(src=self.pg7.remote_ip4,
4995 dst=self.pg7.local_ip4) /
4996 UDP(sport=1234, dport=48879) /
4997 VXLAN(vni=444, gpid=113, flags=0x88) /
4998 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
4999 IP(src="10.0.0.101", dst="10.220.0.1") /
5000 UDP(sport=1234, dport=1234) /
5003 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
5006 # ping from an external host to the remote external EP
5008 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
5010 IP(src="10.220.0.1", dst=rep.ip4) /
5011 UDP(sport=1234, dport=1234) /
5014 rxs = self.send_and_expect(self.pg0, p * 1, self.pg7)
5017 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
5018 # self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
5019 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
5020 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
5021 self.assertEqual(rx[VXLAN].vni, 444)
5022 self.assertTrue(rx[VXLAN].flags.G)
5023 self.assertTrue(rx[VXLAN].flags.Instance)
5024 # the sclass of the ext-net the packet came from
5025 self.assertEqual(rx[VXLAN].gpid, 4220)
5026 # policy was applied to the original IP packet
5027 self.assertTrue(rx[VXLAN].gpflags.A)
5028 # since it's an external host the reciever should not learn it
5029 self.assertTrue(rx[VXLAN].gpflags.D)
5030 inner = rx[VXLAN].payload
5031 self.assertEqual(inner[IP].src, "10.220.0.1")
5032 self.assertEqual(inner[IP].dst, rep.ip4)
5035 # An external subnet reachable via the remote external EP
5039 # first the VXLAN-GBP tunnel over which it is reached
5041 vx_tun_r1 = VppVxlanGbpTunnel(
5042 self, self.pg7.local_ip4,
5043 self.pg7.remote_ip4, 445,
5044 mode=(VppEnum.vl_api_vxlan_gbp_api_tunnel_mode_t.
5045 VXLAN_GBP_API_TUNNEL_MODE_L3))
5046 vx_tun_r1.add_vpp_config()
5047 VppIpInterfaceBind(self, vx_tun_r1, t4).add_vpp_config()
5049 self.logger.info(self.vapi.cli("sh vxlan-gbp tunnel"))
5052 # then the special adj to resolve through on that tunnel
5054 n1 = VppNeighbor(self,
5055 vx_tun_r1.sw_if_index,
5056 "00:0c:0c:0c:0c:0c",
5057 self.pg7.remote_ip4)
5061 # the route via the adj above
5063 ip_222 = VppIpRoute(self, "10.222.0.0", 24,
5064 [VppRoutePath(self.pg7.remote_ip4,
5065 vx_tun_r1.sw_if_index)],
5066 table_id=t4.table_id)
5067 ip_222.add_vpp_config()
5069 l3o_222 = VppGbpSubnet(
5070 self, rd1, "10.222.0.0", 24,
5071 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
5073 l3o_222.add_vpp_config()
5076 # ping between hosts in local and remote external subnets
5077 # dropped without a contract
5079 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
5081 IP(src="10.220.0.1", dst="10.222.0.1") /
5082 UDP(sport=1234, dport=1234) /
5085 rxs = self.send_and_assert_no_replies(self.pg0, p * 1)
5088 # Add contracts ext-nets for 220 -> 222
5090 c4 = VppGbpContract(
5091 self, 55, 4220, 4222, acl.acl_index,
5092 [VppGbpContractRule(
5093 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5094 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5097 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5098 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5100 [ETH_P_IP, ETH_P_IPV6])
5104 # ping from host in local to remote external subnets
5106 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
5108 IP(src="10.220.0.1", dst="10.222.0.1") /
5109 UDP(sport=1234, dport=1234) /
5112 rxs = self.send_and_expect(self.pg0, p * 3, self.pg7)
5115 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
5116 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
5117 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
5118 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
5119 self.assertEqual(rx[VXLAN].vni, 445)
5120 self.assertTrue(rx[VXLAN].flags.G)
5121 self.assertTrue(rx[VXLAN].flags.Instance)
5122 # the sclass of the ext-net the packet came from
5123 self.assertEqual(rx[VXLAN].gpid, 4220)
5124 # policy was applied to the original IP packet
5125 self.assertTrue(rx[VXLAN].gpflags.A)
5126 # since it's an external host the reciever should not learn it
5127 self.assertTrue(rx[VXLAN].gpflags.D)
5128 inner = rx[VXLAN].payload
5129 self.assertEqual(inner[Ether].dst, "00:0c:0c:0c:0c:0c")
5130 self.assertEqual(inner[IP].src, "10.220.0.1")
5131 self.assertEqual(inner[IP].dst, "10.222.0.1")
5134 # make the external subnet ECMP
5136 vx_tun_r2 = VppVxlanGbpTunnel(
5137 self, self.pg7.local_ip4,
5138 self.pg7.remote_ip4, 446,
5139 mode=(VppEnum.vl_api_vxlan_gbp_api_tunnel_mode_t.
5140 VXLAN_GBP_API_TUNNEL_MODE_L3))
5141 vx_tun_r2.add_vpp_config()
5142 VppIpInterfaceBind(self, vx_tun_r2, t4).add_vpp_config()
5144 self.logger.info(self.vapi.cli("sh vxlan-gbp tunnel"))
5146 n2 = VppNeighbor(self,
5147 vx_tun_r2.sw_if_index,
5148 "00:0c:0c:0c:0c:0c",
5149 self.pg7.remote_ip4)
5152 ip_222.modify([VppRoutePath(self.pg7.remote_ip4,
5153 vx_tun_r1.sw_if_index),
5154 VppRoutePath(self.pg7.remote_ip4,
5155 vx_tun_r2.sw_if_index)])
5158 # now expect load-balance
5160 p = [(Ether(src=eep1.mac, dst=str(self.router_mac)) /
5162 IP(src="10.220.0.1", dst="10.222.0.1") /
5163 UDP(sport=1234, dport=1234) /
5164 Raw(b'\xa5' * 100)),
5165 (Ether(src=eep1.mac, dst=str(self.router_mac)) /
5167 IP(src="10.220.0.1", dst="10.222.0.1") /
5168 UDP(sport=1222, dport=1235) /
5169 Raw(b'\xa5' * 100))]
5171 rxs = self.send_and_expect(self.pg0, p, self.pg7)
5173 self.assertEqual(rxs[0][VXLAN].vni, 445)
5174 self.assertEqual(rxs[1][VXLAN].vni, 446)
5177 # Same LB test for v6
5179 n3 = VppNeighbor(self,
5180 vx_tun_r1.sw_if_index,
5181 "00:0c:0c:0c:0c:0c",
5182 self.pg7.remote_ip6)
5184 n4 = VppNeighbor(self,
5185 vx_tun_r2.sw_if_index,
5186 "00:0c:0c:0c:0c:0c",
5187 self.pg7.remote_ip6)
5190 ip_222_6 = VppIpRoute(self, "10:222::", 64,
5191 [VppRoutePath(self.pg7.remote_ip6,
5192 vx_tun_r1.sw_if_index),
5193 VppRoutePath(self.pg7.remote_ip6,
5194 vx_tun_r2.sw_if_index)],
5195 table_id=t6.table_id)
5196 ip_222_6.add_vpp_config()
5198 l3o_222_6 = VppGbpSubnet(
5199 self, rd1, "10:222::", 64,
5200 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
5202 l3o_222_6.add_vpp_config()
5204 p = [(Ether(src=eep1.mac, dst=str(self.router_mac)) /
5206 IPv6(src="10:220::1", dst="10:222::1") /
5207 UDP(sport=1234, dport=1234) /
5208 Raw(b'\xa5' * 100)),
5209 (Ether(src=eep1.mac, dst=str(self.router_mac)) /
5211 IPv6(src="10:220::1", dst="10:222::1") /
5212 UDP(sport=7777, dport=8881) /
5213 Raw(b'\xa5' * 100))]
5215 self.logger.info(self.vapi.cli("sh ip6 fib 10:222::1"))
5216 rxs = self.send_and_expect(self.pg0, p, self.pg7)
5218 self.assertEqual(rxs[0][VXLAN].vni, 445)
5219 self.assertEqual(rxs[1][VXLAN].vni, 446)
5222 # ping from host in remote to local external subnets
5223 # there's no contract for this, but the A bit is set.
5225 p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
5226 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
5227 UDP(sport=1234, dport=48879) /
5228 VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
5229 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
5230 IP(src="10.222.0.1", dst="10.220.0.1") /
5231 UDP(sport=1234, dport=1234) /
5234 rxs = self.send_and_expect(self.pg7, p * 3, self.pg0)
5235 self.assertFalse(find_gbp_endpoint(self, ip="10.222.0.1"))
5238 # ping from host in remote to remote external subnets
5239 # this is dropped by reflection check.
5241 p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
5242 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
5243 UDP(sport=1234, dport=48879) /
5244 VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
5245 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
5246 IP(src="10.222.0.1", dst="10.222.0.2") /
5247 UDP(sport=1234, dport=1234) /
5250 rxs = self.send_and_assert_no_replies(self.pg7, p * 3)
5252 p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
5253 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
5254 UDP(sport=1234, dport=48879) /
5255 VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
5256 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
5257 IPv6(src="10:222::1", dst="10:222::2") /
5258 UDP(sport=1234, dport=1234) /
5261 rxs = self.send_and_assert_no_replies(self.pg7, p * 3)
5266 lep1 = VppGbpEndpoint(self, vlan_144,
5268 "10.0.0.44", "11.0.0.44",
5269 "2001:10::44", "3001::44")
5270 lep1.add_vpp_config()
5273 # local EP to local ip4 external subnet
5275 p = (Ether(src=lep1.mac, dst=str(self.router_mac)) /
5277 IP(src=lep1.ip4, dst="10.220.0.1") /
5278 UDP(sport=1234, dport=1234) /
5281 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
5284 self.assertEqual(rx[Ether].src, str(self.router_mac))
5285 self.assertEqual(rx[Ether].dst, eep1.mac)
5286 self.assertEqual(rx[Dot1Q].vlan, 100)
5289 # local EP to local ip6 external subnet
5291 p = (Ether(src=lep1.mac, dst=str(self.router_mac)) /
5293 IPv6(src=lep1.ip6, dst="10:220::1") /
5294 UDP(sport=1234, dport=1234) /
5297 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
5300 self.assertEqual(rx[Ether].src, str(self.router_mac))
5301 self.assertEqual(rx[Ether].dst, eep1.mac)
5302 self.assertEqual(rx[Dot1Q].vlan, 100)
5305 # ip4 and ip6 subnets that load-balance
5307 ip_20 = VppIpRoute(self, "10.20.0.0", 24,
5308 [VppRoutePath(eep1.ip4,
5309 eep1.epg.bvi.sw_if_index),
5310 VppRoutePath(eep2.ip4,
5311 eep2.epg.bvi.sw_if_index)],
5312 table_id=t4.table_id)
5313 ip_20.add_vpp_config()
5315 l3o_20 = VppGbpSubnet(
5316 self, rd1, "10.20.0.0", 24,
5317 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
5319 l3o_20.add_vpp_config()
5321 ip6_20 = VppIpRoute(self, "10:20::", 64,
5322 [VppRoutePath(eep1.ip6,
5323 eep1.epg.bvi.sw_if_index),
5324 VppRoutePath(eep2.ip6,
5325 eep2.epg.bvi.sw_if_index)],
5326 table_id=t6.table_id)
5327 ip6_20.add_vpp_config()
5329 l3o6_20 = VppGbpSubnet(
5330 self, rd1, "10:20::", 64,
5331 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
5333 l3o6_20.add_vpp_config()
5335 self.logger.info(self.vapi.cli("sh ip fib 10.20.0.1"))
5336 self.logger.info(self.vapi.cli("sh ip6 fib 10:20::1"))
5338 # two ip6 packets whose port are chosen so they load-balance
5339 p = [(Ether(src=lep1.mac, dst=str(self.router_mac)) /
5341 IPv6(src=lep1.ip6, dst="10:20::1") /
5342 UDP(sport=1234, dport=1234) /
5343 Raw(b'\xa5' * 100)),
5344 (Ether(src=lep1.mac, dst=str(self.router_mac)) /
5346 IPv6(src=lep1.ip6, dst="10:20::1") /
5347 UDP(sport=124, dport=1230) /
5348 Raw(b'\xa5' * 100))]
5350 rxs = self.send_and_expect(self.pg0, p, self.pg0, 2)
5352 self.assertEqual(rxs[0][Dot1Q].vlan, 101)
5353 self.assertEqual(rxs[1][Dot1Q].vlan, 100)
5355 # two ip4 packets whose port are chosen so they load-balance
5356 p = [(Ether(src=lep1.mac, dst=str(self.router_mac)) /
5358 IP(src=lep1.ip4, dst="10.20.0.1") /
5359 UDP(sport=1235, dport=1235) /
5360 Raw(b'\xa5' * 100)),
5361 (Ether(src=lep1.mac, dst=str(self.router_mac)) /
5363 IP(src=lep1.ip4, dst="10.20.0.1") /
5364 UDP(sport=124, dport=1230) /
5365 Raw(b'\xa5' * 100))]
5367 rxs = self.send_and_expect(self.pg0, p, self.pg0, 2)
5369 self.assertEqual(rxs[0][Dot1Q].vlan, 101)
5370 self.assertEqual(rxs[1][Dot1Q].vlan, 100)
5375 ip_222.remove_vpp_config()
5376 self.pg7.unconfig_ip4()
5377 self.vlan_101.set_vtr(L2_VTR_OP.L2_DISABLED)
5378 self.vlan_100.set_vtr(L2_VTR_OP.L2_DISABLED)
5380 def test_gbp_anon_l3_out(self):
5381 """ GBP Anonymous L3 Out """
5383 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
5384 self.vapi.cli("set logging class gbp level debug")
5386 routed_dst_mac = "00:0c:0c:0c:0c:0c"
5387 routed_src_mac = "00:22:bd:f8:19:ff"
5392 t4 = VppIpTable(self, 1)
5394 t6 = VppIpTable(self, 1, True)
5397 rd1 = VppGbpRouteDomain(self, 2, 55, t4, t6)
5398 rd1.add_vpp_config()
5400 self.loop0.set_mac(self.router_mac)
5403 # Bind the BVI to the RD
5405 bind_l0_ip4 = VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
5406 bind_l0_ip6 = VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
5409 # Pg7 hosts a BD's BUM
5410 # Pg1 some other l3 interface
5412 self.pg7.config_ip4()
5413 self.pg7.resolve_arp()
5416 # a GBP external bridge domains for the EPs
5418 bd1 = VppBridgeDomain(self, 1)
5419 bd1.add_vpp_config()
5420 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0, None, None)
5421 gbd1.add_vpp_config()
5424 # The Endpoint-groups in which the external endpoints exist
5426 epg_220 = VppGbpEndpointGroup(self, 220, 113, rd1, gbd1,
5430 VppGbpEndpointRetention(4))
5431 epg_220.add_vpp_config()
5433 # the BVIs have the subnet applied ...
5434 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi,
5436 bind=bind_l0_ip4).add_vpp_config()
5438 # ... which is an Anonymous L3-out subnets
5439 l3o_1 = VppGbpSubnet(
5440 self, rd1, "10.0.0.0", 24,
5441 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_ANON_L3_OUT,
5443 l3o_1.add_vpp_config()
5446 # an external interface attached to the outside world and the
5449 VppL2Vtr(self, self.vlan_100, L2_VTR_OP.L2_POP_1).add_vpp_config()
5450 VppL2Vtr(self, self.vlan_101, L2_VTR_OP.L2_POP_1).add_vpp_config()
5453 # vlan_100 and vlan_101 are anonymous l3-out interfaces
5455 ext_itf = VppGbpExtItf(self, self.vlan_100, bd1, rd1, anon=True)
5456 ext_itf.add_vpp_config()
5457 ext_itf = VppGbpExtItf(self, self.vlan_101, bd1, rd1, anon=True)
5458 ext_itf.add_vpp_config()
5461 # an unicast vxlan-gbp for inter-RD traffic
5463 vx_tun_l3 = VppGbpVxlanTunnel(
5464 self, 444, rd1.rd_id,
5465 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
5467 vx_tun_l3.add_vpp_config()
5470 # A remote external endpoint
5472 rep = VppGbpEndpoint(self, vx_tun_l3,
5474 "10.0.0.201", "11.0.0.201",
5475 "2001:10::201", "3001::101",
5476 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
5478 self.pg7.remote_ip4,
5480 rep.add_vpp_config()
5483 # ARP packet from host in external subnet are accepted, flooded and
5484 # replied to. We expect 2 packets:
5485 # - APR request flooded over the other vlan subif
5486 # - ARP reply from BVI
5488 p_arp = (Ether(src=self.vlan_100.remote_mac,
5489 dst="ff:ff:ff:ff:ff:ff") /
5494 hwsrc=self.vlan_100.remote_mac,
5495 hwdst="ff:ff:ff:ff:ff:ff"))
5496 rxs = self.send_and_expect(self.pg0, p_arp * 1, self.pg0, n_rx=2)
5498 p_arp = (Ether(src=self.vlan_101.remote_mac,
5499 dst="ff:ff:ff:ff:ff:ff") /
5504 hwsrc=self.vlan_101.remote_mac,
5505 hwdst="ff:ff:ff:ff:ff:ff"))
5506 rxs = self.send_and_expect(self.pg0, p_arp * 1, self.pg0, n_rx=2)
5509 # remote to external
5511 p = (Ether(src=self.pg7.remote_mac,
5512 dst=self.pg7.local_mac) /
5513 IP(src=self.pg7.remote_ip4,
5514 dst=self.pg7.local_ip4) /
5515 UDP(sport=1234, dport=48879) /
5516 VXLAN(vni=vx_tun_l3.vni, gpid=epg_220.sclass, flags=0x88) /
5517 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
5518 IP(src=str(rep.ip4), dst="10.0.0.100") /
5519 UDP(sport=1234, dport=1234) /
5521 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
5524 # local EP pings router
5526 p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
5528 IP(src="10.0.0.100", dst="10.0.0.128") /
5529 ICMP(type='echo-request'))
5530 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
5533 self.assertEqual(rx[Ether].src, str(self.router_mac))
5534 self.assertEqual(rx[Ether].dst, self.vlan_100.remote_mac)
5535 self.assertEqual(rx[Dot1Q].vlan, 100)
5538 # local EP pings other local EP
5540 p = (Ether(src=self.vlan_100.remote_mac,
5541 dst=self.vlan_101.remote_mac) /
5543 IP(src="10.0.0.100", dst="10.0.0.101") /
5544 ICMP(type='echo-request'))
5545 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
5548 self.assertEqual(rx[Ether].src, self.vlan_100.remote_mac)
5549 self.assertEqual(rx[Ether].dst, self.vlan_101.remote_mac)
5550 self.assertEqual(rx[Dot1Q].vlan, 101)
5553 # A subnet reachable through an external router on vlan 100
5555 ip_220 = VppIpRoute(self, "10.220.0.0", 24,
5556 [VppRoutePath("10.0.0.100",
5557 epg_220.bvi.sw_if_index)],
5558 table_id=t4.table_id)
5559 ip_220.add_vpp_config()
5561 l3o_220 = VppGbpSubnet(
5562 self, rd1, "10.220.0.0", 24,
5563 # note: this a "regular" L3 out subnet (not connected)
5564 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
5566 l3o_220.add_vpp_config()
5569 # A subnet reachable through an external router on vlan 101
5571 ip_221 = VppIpRoute(self, "10.221.0.0", 24,
5572 [VppRoutePath("10.0.0.101",
5573 epg_220.bvi.sw_if_index)],
5574 table_id=t4.table_id)
5575 ip_221.add_vpp_config()
5577 l3o_221 = VppGbpSubnet(
5578 self, rd1, "10.221.0.0", 24,
5579 # note: this a "regular" L3 out subnet (not connected)
5580 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
5582 l3o_221.add_vpp_config()
5585 # ping between hosts in remote subnets
5586 # dropped without a contract
5588 p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
5590 IP(src="10.220.0.1", dst="10.221.0.1") /
5591 ICMP(type='echo-request'))
5593 rxs = self.send_and_assert_no_replies(self.pg0, p * 1)
5596 # contract for the external nets to communicate
5598 rule4 = AclRule(is_permit=1, proto=17)
5599 rule6 = AclRule(src_prefix=IPv6Network((0, 0)),
5600 dst_prefix=IPv6Network((0, 0)), is_permit=1, proto=17)
5601 acl = VppAcl(self, rules=[rule4, rule6])
5602 acl.add_vpp_config()
5604 c1 = VppGbpContract(
5605 self, 55, 4220, 4221, acl.acl_index,
5606 [VppGbpContractRule(
5607 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5608 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5611 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5612 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5614 [ETH_P_IP, ETH_P_IPV6])
5618 # Contracts allowing ext-net 200 to talk with external EPs
5620 c2 = VppGbpContract(
5621 self, 55, 4220, 113, acl.acl_index,
5622 [VppGbpContractRule(
5623 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5624 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5627 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5628 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5630 [ETH_P_IP, ETH_P_IPV6])
5632 c3 = VppGbpContract(
5633 self, 55, 113, 4220, acl.acl_index,
5634 [VppGbpContractRule(
5635 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5636 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5639 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5640 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5642 [ETH_P_IP, ETH_P_IPV6])
5646 # ping between hosts in remote subnets
5648 p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
5650 IP(src="10.220.0.1", dst="10.221.0.1") /
5651 UDP(sport=1234, dport=1234) /
5654 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
5657 self.assertEqual(rx[Ether].src, str(self.router_mac))
5658 self.assertEqual(rx[Ether].dst, self.vlan_101.remote_mac)
5659 self.assertEqual(rx[Dot1Q].vlan, 101)
5661 # we did not learn these external hosts
5662 self.assertFalse(find_gbp_endpoint(self, ip="10.220.0.1"))
5663 self.assertFalse(find_gbp_endpoint(self, ip="10.221.0.1"))
5666 # from remote external EP to local external EP
5668 p = (Ether(src=self.pg7.remote_mac,
5669 dst=self.pg7.local_mac) /
5670 IP(src=self.pg7.remote_ip4,
5671 dst=self.pg7.local_ip4) /
5672 UDP(sport=1234, dport=48879) /
5673 VXLAN(vni=444, gpid=113, flags=0x88) /
5674 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
5675 IP(src=rep.ip4, dst="10.220.0.1") /
5676 UDP(sport=1234, dport=1234) /
5679 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
5682 # ping from an external host to the remote external EP
5684 p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
5686 IP(src="10.220.0.1", dst=rep.ip4) /
5687 UDP(sport=1234, dport=1234) /
5690 rxs = self.send_and_expect(self.pg0, p * 1, self.pg7)
5693 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
5694 # self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
5695 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
5696 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
5697 self.assertEqual(rx[VXLAN].vni, 444)
5698 self.assertTrue(rx[VXLAN].flags.G)
5699 self.assertTrue(rx[VXLAN].flags.Instance)
5700 # the sclass of the ext-net the packet came from
5701 self.assertEqual(rx[VXLAN].gpid, 4220)
5702 # policy was applied to the original IP packet
5703 self.assertTrue(rx[VXLAN].gpflags.A)
5704 # since it's an external host the reciever should not learn it
5705 self.assertTrue(rx[VXLAN].gpflags.D)
5706 inner = rx[VXLAN].payload
5707 self.assertEqual(inner[IP].src, "10.220.0.1")
5708 self.assertEqual(inner[IP].dst, rep.ip4)
5711 # An external subnet reachable via the remote external EP
5715 # first the VXLAN-GBP tunnel over which it is reached
5717 vx_tun_r = VppVxlanGbpTunnel(
5718 self, self.pg7.local_ip4,
5719 self.pg7.remote_ip4, 445,
5720 mode=(VppEnum.vl_api_vxlan_gbp_api_tunnel_mode_t.
5721 VXLAN_GBP_API_TUNNEL_MODE_L3))
5722 vx_tun_r.add_vpp_config()
5723 VppIpInterfaceBind(self, vx_tun_r, t4).add_vpp_config()
5725 self.logger.info(self.vapi.cli("sh vxlan-gbp tunnel"))
5728 # then the special adj to resolve through on that tunnel
5730 n1 = VppNeighbor(self,
5731 vx_tun_r.sw_if_index,
5732 "00:0c:0c:0c:0c:0c",
5733 self.pg7.remote_ip4)
5737 # the route via the adj above
5739 ip_222 = VppIpRoute(self, "10.222.0.0", 24,
5740 [VppRoutePath(self.pg7.remote_ip4,
5741 vx_tun_r.sw_if_index)],
5742 table_id=t4.table_id)
5743 ip_222.add_vpp_config()
5745 l3o_222 = VppGbpSubnet(
5746 self, rd1, "10.222.0.0", 24,
5747 # note: this a "regular" l3out subnet (not connected)
5748 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
5750 l3o_222.add_vpp_config()
5753 # ping between hosts in local and remote external subnets
5754 # dropped without a contract
5756 p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
5758 IP(src="10.220.0.1", dst="10.222.0.1") /
5759 UDP(sport=1234, dport=1234) /
5762 rxs = self.send_and_assert_no_replies(self.pg0, p * 1)
5765 # Add contracts ext-nets for 220 -> 222
5767 c4 = VppGbpContract(
5768 self, 55, 4220, 4222, acl.acl_index,
5769 [VppGbpContractRule(
5770 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5771 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5774 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5775 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5777 [ETH_P_IP, ETH_P_IPV6])
5781 # ping from host in local to remote external subnets
5783 p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
5785 IP(src="10.220.0.1", dst="10.222.0.1") /
5786 UDP(sport=1234, dport=1234) /
5789 rxs = self.send_and_expect(self.pg0, p * 3, self.pg7)
5792 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
5793 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
5794 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
5795 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
5796 self.assertEqual(rx[VXLAN].vni, 445)
5797 self.assertTrue(rx[VXLAN].flags.G)
5798 self.assertTrue(rx[VXLAN].flags.Instance)
5799 # the sclass of the ext-net the packet came from
5800 self.assertEqual(rx[VXLAN].gpid, 4220)
5801 # policy was applied to the original IP packet
5802 self.assertTrue(rx[VXLAN].gpflags.A)
5803 # since it's an external host the reciever should not learn it
5804 self.assertTrue(rx[VXLAN].gpflags.D)
5805 inner = rx[VXLAN].payload
5806 self.assertEqual(inner[Ether].dst, "00:0c:0c:0c:0c:0c")
5807 self.assertEqual(inner[IP].src, "10.220.0.1")
5808 self.assertEqual(inner[IP].dst, "10.222.0.1")
5811 # ping from host in remote to local external subnets
5812 # there's no contract for this, but the A bit is set.
5814 p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
5815 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
5816 UDP(sport=1234, dport=48879) /
5817 VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
5818 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
5819 IP(src="10.222.0.1", dst="10.220.0.1") /
5820 UDP(sport=1234, dport=1234) /
5823 rxs = self.send_and_expect(self.pg7, p * 3, self.pg0)
5824 self.assertFalse(find_gbp_endpoint(self, ip="10.222.0.1"))
5827 # ping from host in remote to remote external subnets
5828 # this is dropped by reflection check.
5830 p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
5831 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
5832 UDP(sport=1234, dport=48879) /
5833 VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
5834 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
5835 IP(src="10.222.0.1", dst="10.222.0.2") /
5836 UDP(sport=1234, dport=1234) /
5839 rxs = self.send_and_assert_no_replies(self.pg7, p * 3)
5844 self.vlan_101.set_vtr(L2_VTR_OP.L2_DISABLED)
5845 self.vlan_100.set_vtr(L2_VTR_OP.L2_DISABLED)
5846 self.pg7.unconfig_ip4()
5847 # make sure the programmed EP is no longer learnt from DP
5848 self.wait_for_ep_timeout(sw_if_index=rep.itf.sw_if_index, ip=rep.ip4)
5851 if __name__ == '__main__':
5852 unittest.main(testRunner=VppTestRunner)