3 from socket import AF_INET, AF_INET6
6 from scapy.packet import Raw
7 from scapy.layers.l2 import Ether, ARP, Dot1Q
8 from scapy.layers.inet import IP, UDP, ICMP
9 from scapy.layers.inet6 import IPv6, ICMPv6ND_NS, ICMPv6NDOptSrcLLAddr, \
11 from scapy.utils6 import in6_getnsma, in6_getnsmac
12 from scapy.layers.vxlan import VXLAN
13 from scapy.data import ETH_P_IP, ETH_P_IPV6, ETH_P_ARP
14 from scapy.utils import inet_pton, inet_ntop
16 from framework import VppTestCase, VppTestRunner
17 from vpp_object import VppObject
18 from vpp_interface import VppInterface
19 from vpp_ip_route import VppIpRoute, VppRoutePath, VppIpTable, \
20 VppIpInterfaceAddress, VppIpInterfaceBind, find_route, FibPathProto, \
22 from vpp_l2 import VppBridgeDomain, VppBridgeDomainPort, \
23 VppBridgeDomainArpEntry, VppL2FibEntry, find_bridge_domain_port, VppL2Vtr
24 from vpp_sub_interface import L2_VTR_OP, VppDot1QSubint
25 from vpp_ip import VppIpAddress, VppIpPrefix
26 from vpp_papi import VppEnum, MACAddress
27 from vpp_vxlan_gbp_tunnel import find_vxlan_gbp_tunnel, INDEX_INVALID, \
29 from vpp_neighbor import VppNeighbor
38 def find_gbp_endpoint(test, sw_if_index=None, ip=None, mac=None, tep=None):
40 vip = VppIpAddress(ip)
42 vmac = MACAddress(mac)
44 eps = test.vapi.gbp_endpoint_dump()
48 src = VppIpAddress(tep[0])
49 dst = VppIpAddress(tep[1])
50 if src != ep.endpoint.tun.src or dst != ep.endpoint.tun.dst:
53 if ep.endpoint.sw_if_index != sw_if_index:
56 for eip in ep.endpoint.ips:
60 if vmac.packed == ep.endpoint.mac:
66 def find_gbp_vxlan(test, vni):
67 ts = test.vapi.gbp_vxlan_tunnel_dump()
69 if t.tunnel.vni == vni:
74 class VppGbpEndpoint(VppObject):
101 return [self.ip4, self.ip6]
105 return [self.fip4, self.fip6]
107 def __init__(self, test, itf, epg, recirc, ip4, fip4, ip6, fip6,
117 self._ip4 = VppIpAddress(ip4)
118 self._fip4 = VppIpAddress(fip4)
119 self._ip6 = VppIpAddress(ip6)
120 self._fip6 = VppIpAddress(fip6)
123 self.vmac = MACAddress(self.itf.remote_mac)
125 self.vmac = MACAddress("00:00:00:00:00:00")
128 self.tun_src = VppIpAddress(tun_src)
129 self.tun_dst = VppIpAddress(tun_dst)
131 def add_vpp_config(self):
132 res = self._test.vapi.gbp_endpoint_add(
133 self.itf.sw_if_index,
134 [self.ip4.encode(), self.ip6.encode()],
138 self.tun_src.encode(),
139 self.tun_dst.encode())
140 self.handle = res.handle
141 self._test.registry.register(self, self._test.logger)
143 def remove_vpp_config(self):
144 self._test.vapi.gbp_endpoint_del(self.handle)
147 return "gbp-endpoint:[%d==%d:%s:%d]" % (self.handle,
148 self.itf.sw_if_index,
152 def query_vpp_config(self):
153 return find_gbp_endpoint(self._test,
154 self.itf.sw_if_index,
158 class VppGbpRecirc(VppObject):
160 GBP Recirculation Interface
163 def __init__(self, test, epg, recirc, is_ext=False):
169 def add_vpp_config(self):
170 self._test.vapi.gbp_recirc_add_del(
172 self.recirc.sw_if_index,
175 self._test.registry.register(self, self._test.logger)
177 def remove_vpp_config(self):
178 self._test.vapi.gbp_recirc_add_del(
180 self.recirc.sw_if_index,
185 return "gbp-recirc:[%d]" % (self.recirc.sw_if_index)
187 def query_vpp_config(self):
188 rs = self._test.vapi.gbp_recirc_dump()
190 if r.recirc.sw_if_index == self.recirc.sw_if_index:
195 class VppGbpExtItf(VppObject):
197 GBP ExtItfulation Interface
200 def __init__(self, test, itf, bd, rd):
206 def add_vpp_config(self):
207 self._test.vapi.gbp_ext_itf_add_del(
209 self.itf.sw_if_index,
212 self._test.registry.register(self, self._test.logger)
214 def remove_vpp_config(self):
215 self._test.vapi.gbp_ext_itf_add_del(
217 self.itf.sw_if_index,
222 return "gbp-ext-itf:[%d]" % (self.itf.sw_if_index)
224 def query_vpp_config(self):
225 rs = self._test.vapi.gbp_ext_itf_dump()
227 if r.ext_itf.sw_if_index == self.itf.sw_if_index:
232 class VppGbpSubnet(VppObject):
237 def __init__(self, test, rd, address, address_len,
238 type, sw_if_index=None, sclass=None):
240 self.rd_id = rd.rd_id
241 self.prefix = VppIpPrefix(address, address_len)
243 self.sw_if_index = sw_if_index
246 def add_vpp_config(self):
247 self._test.vapi.gbp_subnet_add_del(
250 self.prefix.encode(),
252 sw_if_index=self.sw_if_index if self.sw_if_index else 0xffffffff,
253 sclass=self.sclass if self.sclass else 0xffff)
254 self._test.registry.register(self, self._test.logger)
256 def remove_vpp_config(self):
257 self._test.vapi.gbp_subnet_add_del(
260 self.prefix.encode(),
264 return "gbp-subnet:[%d-%s]" % (self.rd_id, self.prefix)
266 def query_vpp_config(self):
267 ss = self._test.vapi.gbp_subnet_dump()
269 if s.subnet.rd_id == self.rd_id and \
270 s.subnet.type == self.type and \
271 s.subnet.prefix == self.prefix:
276 class VppGbpEndpointRetention(object):
277 def __init__(self, remote_ep_timeout=0xffffffff):
278 self.remote_ep_timeout = remote_ep_timeout
281 return {'remote_ep_timeout': self.remote_ep_timeout}
284 class VppGbpEndpointGroup(VppObject):
289 def __init__(self, test, vnid, sclass, rd, bd, uplink,
290 bvi, bvi_ip4, bvi_ip6=None,
291 retention=VppGbpEndpointRetention()):
295 self.bvi_ip4 = VppIpAddress(bvi_ip4)
296 self.bvi_ip6 = VppIpAddress(bvi_ip6)
303 self.retention = retention
305 def add_vpp_config(self):
306 self._test.vapi.gbp_endpoint_group_add(
311 self.uplink.sw_if_index if self.uplink else INDEX_INVALID,
312 self.retention.encode())
313 self._test.registry.register(self, self._test.logger)
315 def remove_vpp_config(self):
316 self._test.vapi.gbp_endpoint_group_del(self.sclass)
319 return "gbp-endpoint-group:[%d]" % (self.vnid)
321 def query_vpp_config(self):
322 epgs = self._test.vapi.gbp_endpoint_group_dump()
324 if epg.epg.vnid == self.vnid:
329 class VppGbpBridgeDomain(VppObject):
334 def __init__(self, test, bd, rd, bvi, uu_fwd=None,
335 bm_flood=None, learn=True, uu_drop=False, bm_drop=False):
339 self.bm_flood = bm_flood
343 e = VppEnum.vl_api_gbp_bridge_domain_flags_t
345 self.learn = e.GBP_BD_API_FLAG_NONE
347 self.learn = e.GBP_BD_API_FLAG_DO_NOT_LEARN
349 self.learn |= e.GBP_BD_API_FLAG_UU_FWD_DROP
351 self.learn |= e.GBP_BD_API_FLAG_MCAST_DROP
353 def add_vpp_config(self):
354 self._test.vapi.gbp_bridge_domain_add(
358 self.bvi.sw_if_index,
359 self.uu_fwd.sw_if_index if self.uu_fwd else INDEX_INVALID,
360 self.bm_flood.sw_if_index if self.bm_flood else INDEX_INVALID)
361 self._test.registry.register(self, self._test.logger)
363 def remove_vpp_config(self):
364 self._test.vapi.gbp_bridge_domain_del(self.bd.bd_id)
367 return "gbp-bridge-domain:[%d]" % (self.bd.bd_id)
369 def query_vpp_config(self):
370 bds = self._test.vapi.gbp_bridge_domain_dump()
372 if bd.bd.bd_id == self.bd.bd_id:
377 class VppGbpRouteDomain(VppObject):
382 def __init__(self, test, rd_id, scope, t4, t6, ip4_uu=None, ip6_uu=None):
391 def add_vpp_config(self):
392 self._test.vapi.gbp_route_domain_add(
397 self.ip4_uu.sw_if_index if self.ip4_uu else INDEX_INVALID,
398 self.ip6_uu.sw_if_index if self.ip6_uu else INDEX_INVALID)
399 self._test.registry.register(self, self._test.logger)
401 def remove_vpp_config(self):
402 self._test.vapi.gbp_route_domain_del(self.rd_id)
405 return "gbp-route-domain:[%d]" % (self.rd_id)
407 def query_vpp_config(self):
408 rds = self._test.vapi.gbp_route_domain_dump()
410 if rd.rd.rd_id == self.rd_id:
415 class VppGbpContractNextHop():
416 def __init__(self, mac, bd, ip, rd):
423 return {'ip': self.ip.encode(),
424 'mac': self.mac.packed,
425 'bd_id': self.bd.bd.bd_id,
426 'rd_id': self.rd.rd_id}
429 class VppGbpContractRule():
430 def __init__(self, action, hash_mode, nhs=None):
432 self.hash_mode = hash_mode
433 self.nhs = [] if nhs is None else nhs
438 nhs.append(nh.encode())
441 return {'action': self.action,
443 'hash_mode': self.hash_mode,
444 'n_nhs': len(self.nhs),
448 return '<VppGbpContractRule action=%s, hash_mode=%s>' % (
449 self.action, self.hash_mode)
452 class VppGbpContract(VppObject):
457 def __init__(self, test, scope, sclass, dclass, acl_index,
458 rules, allowed_ethertypes):
460 if not isinstance(rules, list):
461 raise ValueError("'rules' must be a list.")
462 if not isinstance(allowed_ethertypes, list):
463 raise ValueError("'allowed_ethertypes' must be a list.")
465 self.acl_index = acl_index
469 self.allowed_ethertypes = allowed_ethertypes
470 while (len(self.allowed_ethertypes) < 16):
471 self.allowed_ethertypes.append(0)
473 def add_vpp_config(self):
476 rules.append(r.encode())
477 r = self._test.vapi.gbp_contract_add_del(
480 'acl_index': self.acl_index,
482 'sclass': self.sclass,
483 'dclass': self.dclass,
484 'n_rules': len(rules),
486 'n_ether_types': len(self.allowed_ethertypes),
487 'allowed_ethertypes': self.allowed_ethertypes})
488 self.stats_index = r.stats_index
489 self._test.registry.register(self, self._test.logger)
491 def remove_vpp_config(self):
492 self._test.vapi.gbp_contract_add_del(
495 'acl_index': self.acl_index,
497 'sclass': self.sclass,
498 'dclass': self.dclass,
501 'n_ether_types': len(self.allowed_ethertypes),
502 'allowed_ethertypes': self.allowed_ethertypes})
505 return "gbp-contract:[%d:%d:%d:%d]" % (self.scope,
510 def query_vpp_config(self):
511 cs = self._test.vapi.gbp_contract_dump()
513 if c.contract.scope == self.scope \
514 and c.contract.sclass == self.sclass \
515 and c.contract.dclass == self.dclass:
519 def get_drop_stats(self):
520 c = self._test.statistics.get_counter("/net/gbp/contract/drop")
521 return c[0][self.stats_index]
523 def get_permit_stats(self):
524 c = self._test.statistics.get_counter("/net/gbp/contract/permit")
525 return c[0][self.stats_index]
528 class VppGbpVxlanTunnel(VppInterface):
533 def __init__(self, test, vni, bd_rd_id, mode, src):
534 super(VppGbpVxlanTunnel, self).__init__(test)
537 self.bd_rd_id = bd_rd_id
541 def add_vpp_config(self):
542 r = self._test.vapi.gbp_vxlan_tunnel_add(
547 self.set_sw_if_index(r.sw_if_index)
548 self._test.registry.register(self, self._test.logger)
550 def remove_vpp_config(self):
551 self._test.vapi.gbp_vxlan_tunnel_del(self.vni)
554 return "gbp-vxlan:%d" % (self.sw_if_index)
556 def query_vpp_config(self):
557 return find_gbp_vxlan(self._test, self.vni)
560 class VppGbpAcl(VppObject):
565 def __init__(self, test):
567 self.acl_index = 4294967295
569 def create_rule(self, is_ipv6=0, permit_deny=0, proto=-1,
570 s_prefix=0, s_ip=b'\x00\x00\x00\x00', sport_from=0,
571 sport_to=65535, d_prefix=0, d_ip=b'\x00\x00\x00\x00',
572 dport_from=0, dport_to=65535):
573 if proto == -1 or proto == 0:
576 elif proto == 1 or proto == 58:
579 rule = ({'is_permit': permit_deny, 'is_ipv6': is_ipv6, 'proto': proto,
580 'srcport_or_icmptype_first': sport_from,
581 'srcport_or_icmptype_last': sport_to,
582 'src_ip_prefix_len': s_prefix,
584 'dstport_or_icmpcode_first': dport_from,
585 'dstport_or_icmpcode_last': dport_to,
586 'dst_ip_prefix_len': d_prefix,
587 'dst_ip_addr': d_ip})
590 def add_vpp_config(self, rules):
592 reply = self._test.vapi.acl_add_replace(acl_index=self.acl_index,
595 self.acl_index = reply.acl_index
596 return self.acl_index
598 def remove_vpp_config(self):
599 self._test.vapi.acl_del(self.acl_index)
602 return "gbp-acl:[%d]" % (self.acl_index)
604 def query_vpp_config(self):
605 cs = self._test.vapi.acl_dump()
607 if c.acl_index == self.acl_index:
612 class TestGBP(VppTestCase):
613 """ GBP Test Case """
616 def config_flags(self):
617 return VppEnum.vl_api_nat_config_flags_t
621 super(TestGBP, cls).setUpClass()
624 def tearDownClass(cls):
625 super(TestGBP, cls).tearDownClass()
628 super(TestGBP, self).setUp()
630 self.create_pg_interfaces(range(9))
631 self.create_loopback_interfaces(8)
633 self.router_mac = MACAddress("00:11:22:33:44:55")
635 for i in self.pg_interfaces:
637 for i in self.lo_interfaces:
641 for i in self.pg_interfaces:
644 super(TestGBP, self).tearDown()
646 def send_and_expect_bridged(self, src, tx, dst):
647 rx = self.send_and_expect(src, tx, dst)
650 self.assertEqual(r[Ether].src, tx[0][Ether].src)
651 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
652 self.assertEqual(r[IP].src, tx[0][IP].src)
653 self.assertEqual(r[IP].dst, tx[0][IP].dst)
656 def send_and_expect_bridged6(self, src, tx, dst):
657 rx = self.send_and_expect(src, tx, dst)
660 self.assertEqual(r[Ether].src, tx[0][Ether].src)
661 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
662 self.assertEqual(r[IPv6].src, tx[0][IPv6].src)
663 self.assertEqual(r[IPv6].dst, tx[0][IPv6].dst)
666 def send_and_expect_routed(self, src, tx, dst, src_mac):
667 rx = self.send_and_expect(src, tx, dst)
670 self.assertEqual(r[Ether].src, src_mac)
671 self.assertEqual(r[Ether].dst, dst.remote_mac)
672 self.assertEqual(r[IP].src, tx[0][IP].src)
673 self.assertEqual(r[IP].dst, tx[0][IP].dst)
676 def send_and_expect_natted(self, src, tx, dst, src_ip):
677 rx = self.send_and_expect(src, tx, dst)
680 self.assertEqual(r[Ether].src, tx[0][Ether].src)
681 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
682 self.assertEqual(r[IP].src, src_ip)
683 self.assertEqual(r[IP].dst, tx[0][IP].dst)
686 def send_and_expect_natted6(self, src, tx, dst, src_ip):
687 rx = self.send_and_expect(src, tx, dst)
690 self.assertEqual(r[Ether].src, tx[0][Ether].src)
691 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
692 self.assertEqual(r[IPv6].src, src_ip)
693 self.assertEqual(r[IPv6].dst, tx[0][IPv6].dst)
696 def send_and_expect_unnatted(self, src, tx, dst, dst_ip):
697 rx = self.send_and_expect(src, tx, dst)
700 self.assertEqual(r[Ether].src, tx[0][Ether].src)
701 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
702 self.assertEqual(r[IP].dst, dst_ip)
703 self.assertEqual(r[IP].src, tx[0][IP].src)
706 def send_and_expect_unnatted6(self, src, tx, dst, dst_ip):
707 rx = self.send_and_expect(src, tx, dst)
710 self.assertEqual(r[Ether].src, tx[0][Ether].src)
711 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
712 self.assertEqual(r[IPv6].dst, dst_ip)
713 self.assertEqual(r[IPv6].src, tx[0][IPv6].src)
716 def send_and_expect_double_natted(self, src, tx, dst, src_ip, dst_ip):
717 rx = self.send_and_expect(src, tx, dst)
720 self.assertEqual(r[Ether].src, str(self.router_mac))
721 self.assertEqual(r[Ether].dst, dst.remote_mac)
722 self.assertEqual(r[IP].dst, dst_ip)
723 self.assertEqual(r[IP].src, src_ip)
726 def send_and_expect_double_natted6(self, src, tx, dst, src_ip, dst_ip):
727 rx = self.send_and_expect(src, tx, dst)
730 self.assertEqual(r[Ether].src, str(self.router_mac))
731 self.assertEqual(r[Ether].dst, dst.remote_mac)
732 self.assertEqual(r[IPv6].dst, dst_ip)
733 self.assertEqual(r[IPv6].src, src_ip)
736 def send_and_expect_no_arp(self, src, tx, dst):
737 self.pg_send(src, tx)
738 dst.get_capture(0, timeout=1)
739 dst.assert_nothing_captured(remark="")
742 def send_and_expect_arp(self, src, tx, dst):
743 rx = self.send_and_expect(src, tx, dst)
746 self.assertEqual(r[Ether].src, tx[0][Ether].src)
747 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
748 self.assertEqual(r[ARP].psrc, tx[0][ARP].psrc)
749 self.assertEqual(r[ARP].pdst, tx[0][ARP].pdst)
750 self.assertEqual(r[ARP].hwsrc, tx[0][ARP].hwsrc)
751 self.assertEqual(r[ARP].hwdst, tx[0][ARP].hwdst)
755 """ Group Based Policy """
757 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
762 gt4 = VppIpTable(self, 0)
764 gt6 = VppIpTable(self, 0, is_ip6=True)
766 nt4 = VppIpTable(self, 20)
768 nt6 = VppIpTable(self, 20, is_ip6=True)
771 rd0 = VppGbpRouteDomain(self, 0, 400, gt4, gt6, None, None)
772 rd20 = VppGbpRouteDomain(self, 20, 420, nt4, nt6, None, None)
775 rd20.add_vpp_config()
780 bd1 = VppBridgeDomain(self, 1)
781 bd2 = VppBridgeDomain(self, 2)
782 bd20 = VppBridgeDomain(self, 20)
786 bd20.add_vpp_config()
788 gbd1 = VppGbpBridgeDomain(self, bd1, rd0, self.loop0)
789 gbd2 = VppGbpBridgeDomain(self, bd2, rd0, self.loop1)
790 gbd20 = VppGbpBridgeDomain(self, bd20, rd20, self.loop2)
792 gbd1.add_vpp_config()
793 gbd2.add_vpp_config()
794 gbd20.add_vpp_config()
797 # 3 EPGs, 2 of which share a BD.
798 # 2 NAT EPGs, one for floating-IP subnets, the other for internet
800 epgs = [VppGbpEndpointGroup(self, 220, 1220, rd0, gbd1,
801 self.pg4, self.loop0,
802 "10.0.0.128", "2001:10::128"),
803 VppGbpEndpointGroup(self, 221, 1221, rd0, gbd1,
804 self.pg5, self.loop0,
805 "10.0.1.128", "2001:10:1::128"),
806 VppGbpEndpointGroup(self, 222, 1222, rd0, gbd2,
807 self.pg6, self.loop1,
808 "10.0.2.128", "2001:10:2::128"),
809 VppGbpEndpointGroup(self, 333, 1333, rd20, gbd20,
810 self.pg7, self.loop2,
811 "11.0.0.128", "3001::128"),
812 VppGbpEndpointGroup(self, 444, 1444, rd20, gbd20,
813 self.pg8, self.loop2,
814 "11.0.0.129", "3001::129")]
815 recircs = [VppGbpRecirc(self, epgs[0], self.loop3),
816 VppGbpRecirc(self, epgs[1], self.loop4),
817 VppGbpRecirc(self, epgs[2], self.loop5),
818 VppGbpRecirc(self, epgs[3], self.loop6, is_ext=True),
819 VppGbpRecirc(self, epgs[4], self.loop7, is_ext=True)]
822 recirc_nat = recircs[3]
825 # 4 end-points, 2 in the same subnet, 3 in the same BD
827 eps = [VppGbpEndpoint(self, self.pg0,
829 "10.0.0.1", "11.0.0.1",
830 "2001:10::1", "3001::1"),
831 VppGbpEndpoint(self, self.pg1,
833 "10.0.0.2", "11.0.0.2",
834 "2001:10::2", "3001::2"),
835 VppGbpEndpoint(self, self.pg2,
837 "10.0.1.1", "11.0.0.3",
838 "2001:10:1::1", "3001::3"),
839 VppGbpEndpoint(self, self.pg3,
841 "10.0.2.1", "11.0.0.4",
842 "2001:10:2::1", "3001::4")]
845 # Config related to each of the EPGs
848 # IP config on the BVI interfaces
849 if epg != epgs[1] and epg != epgs[4]:
850 VppIpInterfaceBind(self, epg.bvi, epg.rd.t4).add_vpp_config()
851 VppIpInterfaceBind(self, epg.bvi, epg.rd.t6).add_vpp_config()
852 self.vapi.sw_interface_set_mac_address(
854 self.router_mac.packed)
856 # The BVIs are NAT inside interfaces
857 flags = self.config_flags.NAT_IS_INSIDE
858 self.vapi.nat44_interface_add_del_feature(
859 sw_if_index=epg.bvi.sw_if_index,
860 flags=flags, is_add=1)
861 self.vapi.nat66_add_del_interface(
862 is_add=1, flags=flags,
863 sw_if_index=epg.bvi.sw_if_index)
865 if_ip4 = VppIpInterfaceAddress(self, epg.bvi, epg.bvi_ip4, 32)
866 if_ip6 = VppIpInterfaceAddress(self, epg.bvi, epg.bvi_ip6, 128)
867 if_ip4.add_vpp_config()
868 if_ip6.add_vpp_config()
870 # EPG uplink interfaces in the RD
871 VppIpInterfaceBind(self, epg.uplink, epg.rd.t4).add_vpp_config()
872 VppIpInterfaceBind(self, epg.uplink, epg.rd.t6).add_vpp_config()
874 # add the BD ARP termination entry for BVI IP
875 epg.bd_arp_ip4 = VppBridgeDomainArpEntry(self, epg.bd.bd,
876 str(self.router_mac),
878 epg.bd_arp_ip6 = VppBridgeDomainArpEntry(self, epg.bd.bd,
879 str(self.router_mac),
881 epg.bd_arp_ip4.add_vpp_config()
882 epg.bd_arp_ip6.add_vpp_config()
887 for recirc in recircs:
888 # EPG's ingress recirculation interface maps to its RD
889 VppIpInterfaceBind(self, recirc.recirc,
890 recirc.epg.rd.t4).add_vpp_config()
891 VppIpInterfaceBind(self, recirc.recirc,
892 recirc.epg.rd.t6).add_vpp_config()
894 self.vapi.nat44_interface_add_del_feature(
895 sw_if_index=recirc.recirc.sw_if_index, is_add=1)
896 self.vapi.nat66_add_del_interface(
898 sw_if_index=recirc.recirc.sw_if_index)
900 recirc.add_vpp_config()
902 for recirc in recircs:
903 self.assertTrue(find_bridge_domain_port(self,
904 recirc.epg.bd.bd.bd_id,
905 recirc.recirc.sw_if_index))
908 self.pg_enable_capture(self.pg_interfaces)
911 # routes to the endpoints. We need these since there are no
912 # adj-fibs due to the fact the the BVI address has /32 and
913 # the subnet is not attached.
915 for (ip, fip) in zip(ep.ips, ep.fips):
916 # Add static mappings for each EP from the 10/8 to 11/8 network
918 flags = self.config_flags.NAT_IS_ADDR_ONLY
919 self.vapi.nat44_add_del_static_mapping(
921 local_ip_address=ip.bytes,
922 external_ip_address=fip.bytes,
923 external_sw_if_index=0xFFFFFFFF,
927 self.vapi.nat66_add_del_static_mapping(
928 local_ip_address=ip.bytes,
929 external_ip_address=fip.bytes,
935 self.logger.info(self.vapi.cli("sh gbp endpoint"))
937 # ... results in a Gratuitous ARP/ND on the EPG's uplink
938 rx = ep.epg.uplink.get_capture(len(ep.ips), timeout=0.2)
940 for ii, ip in enumerate(ep.ips):
944 self.assertTrue(p.haslayer(ICMPv6ND_NA))
945 self.assertEqual(p[ICMPv6ND_NA].tgt, ip.address)
947 self.assertTrue(p.haslayer(ARP))
948 self.assertEqual(p[ARP].psrc, ip.address)
949 self.assertEqual(p[ARP].pdst, ip.address)
951 # add the BD ARP termination entry for floating IP
953 ba = VppBridgeDomainArpEntry(self, epg_nat.bd.bd, ep.mac,
957 # floating IPs route via EPG recirc
959 self, fip.address, fip.length,
960 [VppRoutePath(fip.address,
961 ep.recirc.recirc.sw_if_index,
962 type=FibPathType.FIB_PATH_TYPE_DVR,
963 proto=fip.dpo_proto)],
967 # L2 FIB entries in the NAT EPG BD to bridge the packets from
968 # the outside direct to the internal EPG
969 lf = VppL2FibEntry(self, epg_nat.bd.bd, ep.mac,
970 ep.recirc.recirc, bvi_mac=0)
974 # ARP packets for unknown IP are sent to the EPG uplink
976 pkt_arp = (Ether(dst="ff:ff:ff:ff:ff:ff",
977 src=self.pg0.remote_mac) /
979 hwdst="ff:ff:ff:ff:ff:ff",
980 hwsrc=self.pg0.remote_mac,
984 self.vapi.cli("clear trace")
985 self.pg0.add_stream(pkt_arp)
987 self.pg_enable_capture(self.pg_interfaces)
990 rxd = epgs[0].uplink.get_capture(1)
993 # ARP/ND packets get a response
995 pkt_arp = (Ether(dst="ff:ff:ff:ff:ff:ff",
996 src=self.pg0.remote_mac) /
998 hwdst="ff:ff:ff:ff:ff:ff",
999 hwsrc=self.pg0.remote_mac,
1000 pdst=epgs[0].bvi_ip4.address,
1001 psrc=eps[0].ip4.address))
1003 self.send_and_expect(self.pg0, [pkt_arp], self.pg0)
1005 nsma = in6_getnsma(inet_pton(AF_INET6, eps[0].ip6.address))
1006 d = inet_ntop(AF_INET6, nsma)
1007 pkt_nd = (Ether(dst=in6_getnsmac(nsma),
1008 src=self.pg0.remote_mac) /
1009 IPv6(dst=d, src=eps[0].ip6.address) /
1010 ICMPv6ND_NS(tgt=epgs[0].bvi_ip6.address) /
1011 ICMPv6NDOptSrcLLAddr(lladdr=self.pg0.remote_mac))
1012 self.send_and_expect(self.pg0, [pkt_nd], self.pg0)
1015 # broadcast packets are flooded
1017 pkt_bcast = (Ether(dst="ff:ff:ff:ff:ff:ff",
1018 src=self.pg0.remote_mac) /
1019 IP(src=eps[0].ip4.address, dst="232.1.1.1") /
1020 UDP(sport=1234, dport=1234) /
1023 self.vapi.cli("clear trace")
1024 self.pg0.add_stream(pkt_bcast)
1026 self.pg_enable_capture(self.pg_interfaces)
1029 rxd = eps[1].itf.get_capture(1)
1030 self.assertEqual(rxd[0][Ether].dst, pkt_bcast[Ether].dst)
1031 rxd = epgs[0].uplink.get_capture(1)
1032 self.assertEqual(rxd[0][Ether].dst, pkt_bcast[Ether].dst)
1035 # packets to non-local L3 destinations dropped
1037 pkt_intra_epg_220_ip4 = (Ether(src=self.pg0.remote_mac,
1038 dst=str(self.router_mac)) /
1039 IP(src=eps[0].ip4.address,
1041 UDP(sport=1234, dport=1234) /
1043 pkt_inter_epg_222_ip4 = (Ether(src=self.pg0.remote_mac,
1044 dst=str(self.router_mac)) /
1045 IP(src=eps[0].ip4.address,
1047 UDP(sport=1234, dport=1234) /
1050 self.send_and_assert_no_replies(self.pg0,
1051 pkt_intra_epg_220_ip4 * NUM_PKTS)
1053 pkt_inter_epg_222_ip6 = (Ether(src=self.pg0.remote_mac,
1054 dst=str(self.router_mac)) /
1055 IPv6(src=eps[0].ip6.address,
1056 dst="2001:10::99") /
1057 UDP(sport=1234, dport=1234) /
1059 self.send_and_assert_no_replies(self.pg0,
1060 pkt_inter_epg_222_ip6 * NUM_PKTS)
1063 # Add the subnet routes
1066 self, rd0, "10.0.0.0", 24,
1067 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1069 self, rd0, "10.0.1.0", 24,
1070 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1072 self, rd0, "10.0.2.0", 24,
1073 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1075 self, rd0, "2001:10::1", 64,
1076 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1078 self, rd0, "2001:10:1::1", 64,
1079 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1081 self, rd0, "2001:10:2::1", 64,
1082 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1083 s41.add_vpp_config()
1084 s42.add_vpp_config()
1085 s43.add_vpp_config()
1086 s61.add_vpp_config()
1087 s62.add_vpp_config()
1088 s63.add_vpp_config()
1090 self.send_and_expect_bridged(eps[0].itf,
1091 pkt_intra_epg_220_ip4 * NUM_PKTS,
1093 self.send_and_expect_bridged(eps[0].itf,
1094 pkt_inter_epg_222_ip4 * NUM_PKTS,
1096 self.send_and_expect_bridged6(eps[0].itf,
1097 pkt_inter_epg_222_ip6 * NUM_PKTS,
1100 self.logger.info(self.vapi.cli("sh ip fib 11.0.0.2"))
1101 self.logger.info(self.vapi.cli("sh gbp endpoint-group"))
1102 self.logger.info(self.vapi.cli("sh gbp endpoint"))
1103 self.logger.info(self.vapi.cli("sh gbp recirc"))
1104 self.logger.info(self.vapi.cli("sh int"))
1105 self.logger.info(self.vapi.cli("sh int addr"))
1106 self.logger.info(self.vapi.cli("sh int feat loop6"))
1107 self.logger.info(self.vapi.cli("sh vlib graph ip4-gbp-src-classify"))
1108 self.logger.info(self.vapi.cli("sh int feat loop3"))
1109 self.logger.info(self.vapi.cli("sh int feat pg0"))
1112 # Packet destined to unknown unicast is sent on the epg uplink ...
1114 pkt_intra_epg_220_to_uplink = (Ether(src=self.pg0.remote_mac,
1115 dst="00:00:00:33:44:55") /
1116 IP(src=eps[0].ip4.address,
1118 UDP(sport=1234, dport=1234) /
1121 self.send_and_expect_bridged(eps[0].itf,
1122 pkt_intra_epg_220_to_uplink * NUM_PKTS,
1124 # ... and nowhere else
1125 self.pg1.get_capture(0, timeout=0.1)
1126 self.pg1.assert_nothing_captured(remark="Flood onto other VMS")
1128 pkt_intra_epg_221_to_uplink = (Ether(src=self.pg2.remote_mac,
1129 dst="00:00:00:33:44:66") /
1130 IP(src=eps[0].ip4.address,
1132 UDP(sport=1234, dport=1234) /
1135 self.send_and_expect_bridged(eps[2].itf,
1136 pkt_intra_epg_221_to_uplink * NUM_PKTS,
1140 # Packets from the uplink are forwarded in the absence of a contract
1142 pkt_intra_epg_220_from_uplink = (Ether(src="00:00:00:33:44:55",
1143 dst=self.pg0.remote_mac) /
1144 IP(src=eps[0].ip4.address,
1146 UDP(sport=1234, dport=1234) /
1149 self.send_and_expect_bridged(self.pg4,
1150 pkt_intra_epg_220_from_uplink * NUM_PKTS,
1154 # in the absence of policy, endpoints in the same EPG
1157 pkt_intra_epg = (Ether(src=self.pg0.remote_mac,
1158 dst=self.pg1.remote_mac) /
1159 IP(src=eps[0].ip4.address,
1160 dst=eps[1].ip4.address) /
1161 UDP(sport=1234, dport=1234) /
1164 self.send_and_expect_bridged(self.pg0,
1165 pkt_intra_epg * NUM_PKTS,
1169 # in the absence of policy, endpoints in the different EPG
1170 # cannot communicate
1172 pkt_inter_epg_220_to_221 = (Ether(src=self.pg0.remote_mac,
1173 dst=self.pg2.remote_mac) /
1174 IP(src=eps[0].ip4.address,
1175 dst=eps[2].ip4.address) /
1176 UDP(sport=1234, dport=1234) /
1178 pkt_inter_epg_221_to_220 = (Ether(src=self.pg2.remote_mac,
1179 dst=self.pg0.remote_mac) /
1180 IP(src=eps[2].ip4.address,
1181 dst=eps[0].ip4.address) /
1182 UDP(sport=1234, dport=1234) /
1184 pkt_inter_epg_220_to_222 = (Ether(src=self.pg0.remote_mac,
1185 dst=str(self.router_mac)) /
1186 IP(src=eps[0].ip4.address,
1187 dst=eps[3].ip4.address) /
1188 UDP(sport=1234, dport=1234) /
1191 self.send_and_assert_no_replies(eps[0].itf,
1192 pkt_inter_epg_220_to_221 * NUM_PKTS)
1193 self.send_and_assert_no_replies(eps[0].itf,
1194 pkt_inter_epg_220_to_222 * NUM_PKTS)
1197 # A uni-directional contract from EPG 220 -> 221
1199 acl = VppGbpAcl(self)
1200 rule = acl.create_rule(permit_deny=1, proto=17)
1201 rule2 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
1202 acl_index = acl.add_vpp_config([rule, rule2])
1203 c1 = VppGbpContract(
1204 self, 400, epgs[0].sclass, epgs[1].sclass, acl_index,
1205 [VppGbpContractRule(
1206 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1207 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1210 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1211 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1213 [ETH_P_IP, ETH_P_IPV6])
1216 self.send_and_expect_bridged(eps[0].itf,
1217 pkt_inter_epg_220_to_221 * NUM_PKTS,
1219 self.send_and_assert_no_replies(eps[0].itf,
1220 pkt_inter_epg_220_to_222 * NUM_PKTS)
1223 # contract for the return direction
1225 c2 = VppGbpContract(
1226 self, 400, epgs[1].sclass, epgs[0].sclass, acl_index,
1227 [VppGbpContractRule(
1228 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1229 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1232 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1233 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1235 [ETH_P_IP, ETH_P_IPV6])
1238 self.send_and_expect_bridged(eps[0].itf,
1239 pkt_inter_epg_220_to_221 * NUM_PKTS,
1241 self.send_and_expect_bridged(eps[2].itf,
1242 pkt_inter_epg_221_to_220 * NUM_PKTS,
1245 ds = c2.get_drop_stats()
1246 self.assertEqual(ds['packets'], 0)
1247 ps = c2.get_permit_stats()
1248 self.assertEqual(ps['packets'], NUM_PKTS)
1251 # the contract does not allow non-IP
1253 pkt_non_ip_inter_epg_220_to_221 = (Ether(src=self.pg0.remote_mac,
1254 dst=self.pg2.remote_mac) /
1256 self.send_and_assert_no_replies(eps[0].itf,
1257 pkt_non_ip_inter_epg_220_to_221 * 17)
1260 # check that inter group is still disabled for the groups
1261 # not in the contract.
1263 self.send_and_assert_no_replies(eps[0].itf,
1264 pkt_inter_epg_220_to_222 * NUM_PKTS)
1267 # A uni-directional contract from EPG 220 -> 222 'L3 routed'
1269 c3 = VppGbpContract(
1270 self, 400, epgs[0].sclass, epgs[2].sclass, acl_index,
1271 [VppGbpContractRule(
1272 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1273 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1276 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1277 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1279 [ETH_P_IP, ETH_P_IPV6])
1282 self.logger.info(self.vapi.cli("sh gbp contract"))
1284 self.send_and_expect_routed(eps[0].itf,
1285 pkt_inter_epg_220_to_222 * NUM_PKTS,
1287 str(self.router_mac))
1290 # remove both contracts, traffic stops in both directions
1292 c2.remove_vpp_config()
1293 c1.remove_vpp_config()
1294 c3.remove_vpp_config()
1295 acl.remove_vpp_config()
1297 self.send_and_assert_no_replies(eps[2].itf,
1298 pkt_inter_epg_221_to_220 * NUM_PKTS)
1299 self.send_and_assert_no_replies(eps[0].itf,
1300 pkt_inter_epg_220_to_221 * NUM_PKTS)
1301 self.send_and_expect_bridged(eps[0].itf,
1302 pkt_intra_epg * NUM_PKTS,
1306 # EPs to the outside world
1309 # in the EP's RD an external subnet via the NAT EPG's recirc
1311 self, rd0, "0.0.0.0", 0,
1312 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1313 sw_if_index=recirc_nat.recirc.sw_if_index,
1314 sclass=epg_nat.sclass)
1316 self, rd0, "11.0.0.0", 8,
1317 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1318 sw_if_index=recirc_nat.recirc.sw_if_index,
1319 sclass=epg_nat.sclass)
1320 se16 = VppGbpSubnet(
1322 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1323 sw_if_index=recirc_nat.recirc.sw_if_index,
1324 sclass=epg_nat.sclass)
1325 # in the NAT RD an external subnet via the NAT EPG's uplink
1327 self, rd20, "0.0.0.0", 0,
1328 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1329 sw_if_index=epg_nat.uplink.sw_if_index,
1330 sclass=epg_nat.sclass)
1331 se36 = VppGbpSubnet(
1332 self, rd20, "::", 0,
1333 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1334 sw_if_index=epg_nat.uplink.sw_if_index,
1335 sclass=epg_nat.sclass)
1337 self, rd20, "11.0.0.0", 8,
1338 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1339 sw_if_index=epg_nat.uplink.sw_if_index,
1340 sclass=epg_nat.sclass)
1341 se1.add_vpp_config()
1342 se2.add_vpp_config()
1343 se16.add_vpp_config()
1344 se3.add_vpp_config()
1345 se36.add_vpp_config()
1346 se4.add_vpp_config()
1348 self.logger.info(self.vapi.cli("sh ip fib 0.0.0.0/0"))
1349 self.logger.info(self.vapi.cli("sh ip fib 11.0.0.1"))
1350 self.logger.info(self.vapi.cli("sh ip6 fib ::/0"))
1351 self.logger.info(self.vapi.cli("sh ip6 fib %s" %
1355 # From an EP to an outside address: IN2OUT
1357 pkt_inter_epg_220_to_global = (Ether(src=self.pg0.remote_mac,
1358 dst=str(self.router_mac)) /
1359 IP(src=eps[0].ip4.address,
1361 UDP(sport=1234, dport=1234) /
1365 self.send_and_assert_no_replies(eps[0].itf,
1366 pkt_inter_epg_220_to_global * NUM_PKTS)
1368 acl2 = VppGbpAcl(self)
1369 rule = acl2.create_rule(permit_deny=1, proto=17, sport_from=1234,
1370 sport_to=1234, dport_from=1234, dport_to=1234)
1371 rule2 = acl2.create_rule(is_ipv6=1, permit_deny=1, proto=17,
1372 sport_from=1234, sport_to=1234,
1373 dport_from=1234, dport_to=1234)
1375 acl_index2 = acl2.add_vpp_config([rule, rule2])
1376 c4 = VppGbpContract(
1377 self, 400, epgs[0].sclass, epgs[3].sclass, acl_index2,
1378 [VppGbpContractRule(
1379 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1380 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1383 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1384 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1386 [ETH_P_IP, ETH_P_IPV6])
1389 self.send_and_expect_natted(eps[0].itf,
1390 pkt_inter_epg_220_to_global * NUM_PKTS,
1392 eps[0].fip4.address)
1394 pkt_inter_epg_220_to_global = (Ether(src=self.pg0.remote_mac,
1395 dst=str(self.router_mac)) /
1396 IPv6(src=eps[0].ip6.address,
1398 UDP(sport=1234, dport=1234) /
1401 self.send_and_expect_natted6(self.pg0,
1402 pkt_inter_epg_220_to_global * NUM_PKTS,
1404 eps[0].fip6.address)
1407 # From a global address to an EP: OUT2IN
1409 pkt_inter_epg_220_from_global = (Ether(src=str(self.router_mac),
1410 dst=self.pg0.remote_mac) /
1411 IP(dst=eps[0].fip4.address,
1413 UDP(sport=1234, dport=1234) /
1416 self.send_and_assert_no_replies(
1417 self.pg7, pkt_inter_epg_220_from_global * NUM_PKTS)
1419 c5 = VppGbpContract(
1420 self, 400, epgs[3].sclass, epgs[0].sclass, acl_index2,
1421 [VppGbpContractRule(
1422 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1423 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1426 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1427 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1429 [ETH_P_IP, ETH_P_IPV6])
1432 self.send_and_expect_unnatted(self.pg7,
1433 pkt_inter_epg_220_from_global * NUM_PKTS,
1437 pkt_inter_epg_220_from_global = (Ether(src=str(self.router_mac),
1438 dst=self.pg0.remote_mac) /
1439 IPv6(dst=eps[0].fip6.address,
1441 UDP(sport=1234, dport=1234) /
1444 self.send_and_expect_unnatted6(
1446 pkt_inter_epg_220_from_global * NUM_PKTS,
1451 # From a local VM to another local VM using resp. public addresses:
1454 pkt_intra_epg_220_global = (Ether(src=self.pg0.remote_mac,
1455 dst=str(self.router_mac)) /
1456 IP(src=eps[0].ip4.address,
1457 dst=eps[1].fip4.address) /
1458 UDP(sport=1234, dport=1234) /
1461 self.send_and_expect_double_natted(eps[0].itf,
1462 pkt_intra_epg_220_global * NUM_PKTS,
1464 eps[0].fip4.address,
1467 pkt_intra_epg_220_global = (Ether(src=self.pg0.remote_mac,
1468 dst=str(self.router_mac)) /
1469 IPv6(src=eps[0].ip6.address,
1470 dst=eps[1].fip6.address) /
1471 UDP(sport=1234, dport=1234) /
1474 self.send_and_expect_double_natted6(
1476 pkt_intra_epg_220_global * NUM_PKTS,
1478 eps[0].fip6.address,
1485 # del static mappings for each EP from the 10/8 to 11/8 network
1486 flags = self.config_flags.NAT_IS_ADDR_ONLY
1487 self.vapi.nat44_add_del_static_mapping(
1489 local_ip_address=ep.ip4.bytes,
1490 external_ip_address=ep.fip4.bytes,
1491 external_sw_if_index=0xFFFFFFFF,
1494 self.vapi.nat66_add_del_static_mapping(
1495 local_ip_address=ep.ip6.bytes,
1496 external_ip_address=ep.fip6.bytes,
1500 # IP config on the BVI interfaces
1501 if epg != epgs[0] and epg != epgs[3]:
1502 flags = self.config_flags.NAT_IS_INSIDE
1503 self.vapi.nat44_interface_add_del_feature(
1504 sw_if_index=epg.bvi.sw_if_index,
1507 self.vapi.nat66_add_del_interface(
1508 is_add=0, flags=flags,
1509 sw_if_index=epg.bvi.sw_if_index)
1511 for recirc in recircs:
1512 self.vapi.nat44_interface_add_del_feature(
1513 sw_if_index=recirc.recirc.sw_if_index,
1515 self.vapi.nat66_add_del_interface(
1517 sw_if_index=recirc.recirc.sw_if_index)
1519 def wait_for_ep_timeout(self, sw_if_index=None, ip=None, mac=None,
1520 tep=None, n_tries=100, s_time=1):
1522 if not find_gbp_endpoint(self, sw_if_index, ip, mac, tep=tep):
1524 n_tries = n_tries - 1
1526 self.assertFalse(find_gbp_endpoint(self, sw_if_index, ip, mac))
1529 def test_gbp_learn_l2(self):
1530 """ GBP L2 Endpoint Learning """
1532 self.vapi.cli("clear errors")
1534 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
1535 learnt = [{'mac': '00:00:11:11:11:01',
1537 'ip6': '2001:10::2'},
1538 {'mac': '00:00:11:11:11:02',
1540 'ip6': '2001:10::3'}]
1545 gt4 = VppIpTable(self, 1)
1546 gt4.add_vpp_config()
1547 gt6 = VppIpTable(self, 1, is_ip6=True)
1548 gt6.add_vpp_config()
1550 rd1 = VppGbpRouteDomain(self, 1, 401, gt4, gt6)
1551 rd1.add_vpp_config()
1554 # Pg2 hosts the vxlan tunnel, hosts on pg2 to act as TEPs
1555 # Pg3 hosts the IP4 UU-flood VXLAN tunnel
1556 # Pg4 hosts the IP6 UU-flood VXLAN tunnel
1558 self.pg2.config_ip4()
1559 self.pg2.resolve_arp()
1560 self.pg2.generate_remote_hosts(4)
1561 self.pg2.configure_ipv4_neighbors()
1562 self.pg3.config_ip4()
1563 self.pg3.resolve_arp()
1564 self.pg4.config_ip4()
1565 self.pg4.resolve_arp()
1568 # Add a mcast destination VXLAN-GBP tunnel for B&M traffic
1570 tun_bm = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
1573 tun_bm.add_vpp_config()
1576 # a GBP bridge domain with a BVI and a UU-flood interface
1578 bd1 = VppBridgeDomain(self, 1)
1579 bd1.add_vpp_config()
1580 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0,
1582 gbd1.add_vpp_config()
1584 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1585 self.logger.info(self.vapi.cli("sh gbp bridge"))
1587 # ... and has a /32 applied
1588 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
1589 ip_addr.add_vpp_config()
1592 # The Endpoint-group in which we are learning endpoints
1594 epg_220 = VppGbpEndpointGroup(self, 220, 112, rd1, gbd1,
1598 VppGbpEndpointRetention(2))
1599 epg_220.add_vpp_config()
1600 epg_330 = VppGbpEndpointGroup(self, 330, 113, rd1, gbd1,
1604 VppGbpEndpointRetention(2))
1605 epg_330.add_vpp_config()
1608 # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
1611 vx_tun_l2_1 = VppGbpVxlanTunnel(
1612 self, 99, bd1.bd_id,
1613 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L2,
1615 vx_tun_l2_1.add_vpp_config()
1618 # A static endpoint that the learnt endpoints are trying to
1621 ep = VppGbpEndpoint(self, self.pg0,
1623 "10.0.0.127", "11.0.0.127",
1624 "2001:10::1", "3001::1")
1627 self.assertTrue(find_route(self, ep.ip4.address, 32, table_id=1))
1629 # a packet with an sclass from an unknown EPG
1630 p = (Ether(src=self.pg2.remote_mac,
1631 dst=self.pg2.local_mac) /
1632 IP(src=self.pg2.remote_hosts[0].ip4,
1633 dst=self.pg2.local_ip4) /
1634 UDP(sport=1234, dport=48879) /
1635 VXLAN(vni=99, gpid=88, flags=0x88) /
1636 Ether(src=learnt[0]["mac"], dst=ep.mac) /
1637 IP(src=learnt[0]["ip"], dst=ep.ip4.address) /
1638 UDP(sport=1234, dport=1234) /
1641 self.send_and_assert_no_replies(self.pg2, p)
1643 self.logger.info(self.vapi.cli("sh error"))
1644 # self.assert_packet_counter_equal(
1645 # '/err/gbp-policy-port/drop-no-contract', 1)
1648 # we should not have learnt a new tunnel endpoint, since
1649 # the EPG was not learnt.
1651 self.assertEqual(INDEX_INVALID,
1652 find_vxlan_gbp_tunnel(self,
1654 self.pg2.remote_hosts[0].ip4,
1657 # epg is not learnt, because the EPG is unknown
1658 self.assertEqual(len(self.vapi.gbp_endpoint_dump()), 1)
1661 # Learn new EPs from IP packets
1663 for ii, l in enumerate(learnt):
1664 # a packet with an sclass from a known EPG
1665 # arriving on an unknown TEP
1666 p = (Ether(src=self.pg2.remote_mac,
1667 dst=self.pg2.local_mac) /
1668 IP(src=self.pg2.remote_hosts[1].ip4,
1669 dst=self.pg2.local_ip4) /
1670 UDP(sport=1234, dport=48879) /
1671 VXLAN(vni=99, gpid=112, flags=0x88) /
1672 Ether(src=l['mac'], dst=ep.mac) /
1673 IP(src=l['ip'], dst=ep.ip4.address) /
1674 UDP(sport=1234, dport=1234) /
1677 rx = self.send_and_expect(self.pg2, [p], self.pg0)
1680 tep1_sw_if_index = find_vxlan_gbp_tunnel(
1683 self.pg2.remote_hosts[1].ip4,
1685 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
1688 # the EP is learnt via the learnt TEP
1689 # both from its MAC and its IP
1691 self.assertTrue(find_gbp_endpoint(self,
1692 vx_tun_l2_1.sw_if_index,
1694 self.assertTrue(find_gbp_endpoint(self,
1695 vx_tun_l2_1.sw_if_index,
1698 # self.assert_packet_counter_equal(
1699 # '/err/gbp-policy-port/allow-intra-sclass', 2)
1701 self.logger.info(self.vapi.cli("show gbp endpoint"))
1702 self.logger.info(self.vapi.cli("show gbp vxlan"))
1703 self.logger.info(self.vapi.cli("show ip mfib"))
1706 # If we sleep for the threshold time, the learnt endpoints should
1710 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1714 # Learn new EPs from GARP packets received on the BD's mcast tunnel
1716 for ii, l in enumerate(learnt):
1717 # a packet with an sclass from a known EPG
1718 # arriving on an unknown TEP
1719 p = (Ether(src=self.pg2.remote_mac,
1720 dst=self.pg2.local_mac) /
1721 IP(src=self.pg2.remote_hosts[1].ip4,
1723 UDP(sport=1234, dport=48879) /
1724 VXLAN(vni=88, gpid=112, flags=0x88) /
1725 Ether(src=l['mac'], dst="ff:ff:ff:ff:ff:ff") /
1727 psrc=l['ip'], pdst=l['ip'],
1728 hwsrc=l['mac'], hwdst="ff:ff:ff:ff:ff:ff"))
1730 rx = self.send_and_expect(self.pg4, [p], self.pg0)
1733 tep1_sw_if_index = find_vxlan_gbp_tunnel(
1736 self.pg2.remote_hosts[1].ip4,
1738 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
1741 # the EP is learnt via the learnt TEP
1742 # both from its MAC and its IP
1744 self.assertTrue(find_gbp_endpoint(self,
1745 vx_tun_l2_1.sw_if_index,
1747 self.assertTrue(find_gbp_endpoint(self,
1748 vx_tun_l2_1.sw_if_index,
1752 # wait for the learnt endpoints to age out
1755 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1759 # Learn new EPs from L2 packets
1761 for ii, l in enumerate(learnt):
1762 # a packet with an sclass from a known EPG
1763 # arriving on an unknown TEP
1764 p = (Ether(src=self.pg2.remote_mac,
1765 dst=self.pg2.local_mac) /
1766 IP(src=self.pg2.remote_hosts[1].ip4,
1767 dst=self.pg2.local_ip4) /
1768 UDP(sport=1234, dport=48879) /
1769 VXLAN(vni=99, gpid=112, flags=0x88) /
1770 Ether(src=l['mac'], dst=ep.mac) /
1773 rx = self.send_and_expect(self.pg2, [p], self.pg0)
1776 tep1_sw_if_index = find_vxlan_gbp_tunnel(
1779 self.pg2.remote_hosts[1].ip4,
1781 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
1784 # the EP is learnt via the learnt TEP
1785 # both from its MAC and its IP
1787 self.assertTrue(find_gbp_endpoint(self,
1788 vx_tun_l2_1.sw_if_index,
1791 self.logger.info(self.vapi.cli("show gbp endpoint"))
1792 self.logger.info(self.vapi.cli("show gbp vxlan"))
1793 self.logger.info(self.vapi.cli("show vxlan-gbp tunnel"))
1796 # wait for the learnt endpoints to age out
1799 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1803 # repeat. the do not learn bit is set so the EPs are not learnt
1806 # a packet with an sclass from a known EPG
1807 p = (Ether(src=self.pg2.remote_mac,
1808 dst=self.pg2.local_mac) /
1809 IP(src=self.pg2.remote_hosts[1].ip4,
1810 dst=self.pg2.local_ip4) /
1811 UDP(sport=1234, dport=48879) /
1812 VXLAN(vni=99, gpid=112, flags=0x88, gpflags="D") /
1813 Ether(src=l['mac'], dst=ep.mac) /
1814 IP(src=l['ip'], dst=ep.ip4.address) /
1815 UDP(sport=1234, dport=1234) /
1818 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
1821 self.assertFalse(find_gbp_endpoint(self,
1822 vx_tun_l2_1.sw_if_index,
1829 # a packet with an sclass from a known EPG
1830 p = (Ether(src=self.pg2.remote_mac,
1831 dst=self.pg2.local_mac) /
1832 IP(src=self.pg2.remote_hosts[1].ip4,
1833 dst=self.pg2.local_ip4) /
1834 UDP(sport=1234, dport=48879) /
1835 VXLAN(vni=99, gpid=112, flags=0x88) /
1836 Ether(src=l['mac'], dst=ep.mac) /
1837 IP(src=l['ip'], dst=ep.ip4.address) /
1838 UDP(sport=1234, dport=1234) /
1841 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
1843 self.assertTrue(find_gbp_endpoint(self,
1844 vx_tun_l2_1.sw_if_index,
1848 # Static EP replies to dynamics
1850 self.logger.info(self.vapi.cli("sh l2fib bd_id 1"))
1852 p = (Ether(src=ep.mac, dst=l['mac']) /
1853 IP(dst=l['ip'], src=ep.ip4.address) /
1854 UDP(sport=1234, dport=1234) /
1857 rxs = self.send_and_expect(self.pg0, p * 17, self.pg2)
1860 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
1861 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
1862 self.assertEqual(rx[UDP].dport, 48879)
1863 # the UDP source port is a random value for hashing
1864 self.assertEqual(rx[VXLAN].gpid, 112)
1865 self.assertEqual(rx[VXLAN].vni, 99)
1866 self.assertTrue(rx[VXLAN].flags.G)
1867 self.assertTrue(rx[VXLAN].flags.Instance)
1868 self.assertTrue(rx[VXLAN].gpflags.A)
1869 self.assertFalse(rx[VXLAN].gpflags.D)
1872 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1876 # repeat in the other EPG
1877 # there's no contract between 220 and 330, but the A-bit is set
1878 # so the packet is cleared for delivery
1881 # a packet with an sclass from a known EPG
1882 p = (Ether(src=self.pg2.remote_mac,
1883 dst=self.pg2.local_mac) /
1884 IP(src=self.pg2.remote_hosts[1].ip4,
1885 dst=self.pg2.local_ip4) /
1886 UDP(sport=1234, dport=48879) /
1887 VXLAN(vni=99, gpid=113, flags=0x88, gpflags='A') /
1888 Ether(src=l['mac'], dst=ep.mac) /
1889 IP(src=l['ip'], dst=ep.ip4.address) /
1890 UDP(sport=1234, dport=1234) /
1893 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
1895 self.assertTrue(find_gbp_endpoint(self,
1896 vx_tun_l2_1.sw_if_index,
1900 # static EP cannot reach the learnt EPs since there is no contract
1901 # only test 1 EP as the others could timeout
1903 p = (Ether(src=ep.mac, dst=l['mac']) /
1904 IP(dst=learnt[0]['ip'], src=ep.ip4.address) /
1905 UDP(sport=1234, dport=1234) /
1908 self.send_and_assert_no_replies(self.pg0, [p])
1911 # refresh the entries after the check for no replies above
1914 # a packet with an sclass from a known EPG
1915 p = (Ether(src=self.pg2.remote_mac,
1916 dst=self.pg2.local_mac) /
1917 IP(src=self.pg2.remote_hosts[1].ip4,
1918 dst=self.pg2.local_ip4) /
1919 UDP(sport=1234, dport=48879) /
1920 VXLAN(vni=99, gpid=113, flags=0x88, gpflags='A') /
1921 Ether(src=l['mac'], dst=ep.mac) /
1922 IP(src=l['ip'], dst=ep.ip4.address) /
1923 UDP(sport=1234, dport=1234) /
1926 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
1928 self.assertTrue(find_gbp_endpoint(self,
1929 vx_tun_l2_1.sw_if_index,
1933 # Add the contract so they can talk
1935 acl = VppGbpAcl(self)
1936 rule = acl.create_rule(permit_deny=1, proto=17)
1937 rule2 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
1938 acl_index = acl.add_vpp_config([rule, rule2])
1939 c1 = VppGbpContract(
1940 self, 401, epg_220.sclass, epg_330.sclass, acl_index,
1941 [VppGbpContractRule(
1942 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1943 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1946 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1947 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1949 [ETH_P_IP, ETH_P_IPV6])
1953 p = (Ether(src=ep.mac, dst=l['mac']) /
1954 IP(dst=l['ip'], src=ep.ip4.address) /
1955 UDP(sport=1234, dport=1234) /
1958 self.send_and_expect(self.pg0, [p], self.pg2)
1961 # send UU packets from the local EP
1963 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1964 self.logger.info(self.vapi.cli("sh gbp bridge"))
1965 p_uu = (Ether(src=ep.mac, dst="00:11:11:11:11:11") /
1966 IP(dst="10.0.0.133", src=ep.ip4.address) /
1967 UDP(sport=1234, dport=1234) /
1969 rxs = self.send_and_expect(ep.itf, [p_uu], gbd1.uu_fwd)
1971 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1973 p_bm = (Ether(src=ep.mac, dst="ff:ff:ff:ff:ff:ff") /
1974 IP(dst="10.0.0.133", src=ep.ip4.address) /
1975 UDP(sport=1234, dport=1234) /
1977 rxs = self.send_and_expect_only(ep.itf, [p_bm], tun_bm.mcast_itf)
1980 self.assertEqual(rx[IP].src, self.pg4.local_ip4)
1981 self.assertEqual(rx[IP].dst, "239.1.1.1")
1982 self.assertEqual(rx[UDP].dport, 48879)
1983 # the UDP source port is a random value for hashing
1984 self.assertEqual(rx[VXLAN].gpid, 112)
1985 self.assertEqual(rx[VXLAN].vni, 88)
1986 self.assertTrue(rx[VXLAN].flags.G)
1987 self.assertTrue(rx[VXLAN].flags.Instance)
1988 self.assertFalse(rx[VXLAN].gpflags.A)
1989 self.assertFalse(rx[VXLAN].gpflags.D)
1992 # Check v6 Endpoints
1995 # a packet with an sclass from a known EPG
1996 p = (Ether(src=self.pg2.remote_mac,
1997 dst=self.pg2.local_mac) /
1998 IP(src=self.pg2.remote_hosts[1].ip4,
1999 dst=self.pg2.local_ip4) /
2000 UDP(sport=1234, dport=48879) /
2001 VXLAN(vni=99, gpid=113, flags=0x88, gpflags='A') /
2002 Ether(src=l['mac'], dst=ep.mac) /
2003 IPv6(src=l['ip6'], dst=ep.ip6.address) /
2004 UDP(sport=1234, dport=1234) /
2007 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
2009 self.assertTrue(find_gbp_endpoint(self,
2010 vx_tun_l2_1.sw_if_index,
2014 # L3 Endpoint Learning
2015 # - configured on the bridge's BVI
2022 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
2024 self.pg2.unconfig_ip4()
2025 self.pg3.unconfig_ip4()
2026 self.pg4.unconfig_ip4()
2028 self.logger.info(self.vapi.cli("sh int"))
2029 self.logger.info(self.vapi.cli("sh gbp vxlan"))
2031 def test_gbp_contract(self):
2032 """ GBP CONTRACTS """
2037 gt4 = VppIpTable(self, 0)
2038 gt4.add_vpp_config()
2039 gt6 = VppIpTable(self, 0, is_ip6=True)
2040 gt6.add_vpp_config()
2042 rd0 = VppGbpRouteDomain(self, 0, 400, gt4, gt6, None, None)
2044 rd0.add_vpp_config()
2049 bd1 = VppBridgeDomain(self, 1, arp_term=0)
2050 bd2 = VppBridgeDomain(self, 2, arp_term=0)
2052 bd1.add_vpp_config()
2053 bd2.add_vpp_config()
2055 gbd1 = VppGbpBridgeDomain(self, bd1, rd0, self.loop0)
2056 gbd2 = VppGbpBridgeDomain(self, bd2, rd0, self.loop1)
2058 gbd1.add_vpp_config()
2059 gbd2.add_vpp_config()
2062 # 3 EPGs, 2 of which share a BD.
2064 epgs = [VppGbpEndpointGroup(self, 220, 1220, rd0, gbd1,
2066 "10.0.0.128", "2001:10::128"),
2067 VppGbpEndpointGroup(self, 221, 1221, rd0, gbd1,
2069 "10.0.1.128", "2001:10:1::128"),
2070 VppGbpEndpointGroup(self, 222, 1222, rd0, gbd2,
2072 "10.0.2.128", "2001:10:2::128")]
2074 # 4 end-points, 2 in the same subnet, 3 in the same BD
2076 eps = [VppGbpEndpoint(self, self.pg0,
2078 "10.0.0.1", "11.0.0.1",
2079 "2001:10::1", "3001::1"),
2080 VppGbpEndpoint(self, self.pg1,
2082 "10.0.0.2", "11.0.0.2",
2083 "2001:10::2", "3001::2"),
2084 VppGbpEndpoint(self, self.pg2,
2086 "10.0.1.1", "11.0.0.3",
2087 "2001:10:1::1", "3001::3"),
2088 VppGbpEndpoint(self, self.pg3,
2090 "10.0.2.1", "11.0.0.4",
2091 "2001:10:2::1", "3001::4")]
2094 # Config related to each of the EPGs
2097 # IP config on the BVI interfaces
2099 VppIpInterfaceBind(self, epg.bvi, epg.rd.t4).add_vpp_config()
2100 VppIpInterfaceBind(self, epg.bvi, epg.rd.t6).add_vpp_config()
2101 self.vapi.sw_interface_set_mac_address(
2102 epg.bvi.sw_if_index,
2103 self.router_mac.packed)
2105 if_ip4 = VppIpInterfaceAddress(self, epg.bvi, epg.bvi_ip4, 32)
2106 if_ip6 = VppIpInterfaceAddress(self, epg.bvi, epg.bvi_ip6, 128)
2107 if_ip4.add_vpp_config()
2108 if_ip6.add_vpp_config()
2110 # add the BD ARP termination entry for BVI IP
2111 epg.bd_arp_ip4 = VppBridgeDomainArpEntry(self, epg.bd.bd,
2112 str(self.router_mac),
2113 epg.bvi_ip4.address)
2114 epg.bd_arp_ip4.add_vpp_config()
2117 epg.add_vpp_config()
2125 self.logger.info(self.vapi.cli("show gbp endpoint"))
2126 self.logger.info(self.vapi.cli("show interface"))
2127 self.logger.info(self.vapi.cli("show br"))
2130 # Intra epg allowed without contract
2132 pkt_intra_epg_220_to_220 = (Ether(src=self.pg0.remote_mac,
2133 dst=self.pg1.remote_mac) /
2134 IP(src=eps[0].ip4.address,
2135 dst=eps[1].ip4.address) /
2136 UDP(sport=1234, dport=1234) /
2139 self.send_and_expect_bridged(self.pg0,
2140 pkt_intra_epg_220_to_220 * 65,
2144 # Inter epg denied without contract
2146 pkt_inter_epg_220_to_221 = (Ether(src=self.pg0.remote_mac,
2147 dst=self.pg2.remote_mac) /
2148 IP(src=eps[0].ip4.address,
2149 dst=eps[2].ip4.address) /
2150 UDP(sport=1234, dport=1234) /
2153 self.send_and_assert_no_replies(self.pg0, pkt_inter_epg_220_to_221)
2156 # A uni-directional contract from EPG 220 -> 221
2158 acl = VppGbpAcl(self)
2159 rule = acl.create_rule(permit_deny=1, proto=17)
2160 rule2 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
2161 acl_index = acl.add_vpp_config([rule, rule2])
2162 c1 = VppGbpContract(
2163 self, 400, epgs[0].sclass, epgs[1].sclass, acl_index,
2164 [VppGbpContractRule(
2165 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2166 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2169 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2170 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2172 [ETH_P_IP, ETH_P_IPV6])
2175 self.send_and_expect_bridged(eps[0].itf,
2176 pkt_inter_epg_220_to_221 * 65,
2179 pkt_inter_epg_220_to_222 = (Ether(src=self.pg0.remote_mac,
2180 dst=str(self.router_mac)) /
2181 IP(src=eps[0].ip4.address,
2182 dst=eps[3].ip4.address) /
2183 UDP(sport=1234, dport=1234) /
2185 self.send_and_assert_no_replies(eps[0].itf,
2186 pkt_inter_epg_220_to_222 * 65)
2189 # contract for the return direction
2191 c2 = VppGbpContract(
2192 self, 400, epgs[1].sclass, epgs[0].sclass, acl_index,
2193 [VppGbpContractRule(
2194 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2195 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2198 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2199 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2201 [ETH_P_IP, ETH_P_IPV6])
2204 self.send_and_expect_bridged(eps[0].itf,
2205 pkt_inter_epg_220_to_221 * 65,
2207 pkt_inter_epg_221_to_220 = (Ether(src=self.pg2.remote_mac,
2208 dst=self.pg0.remote_mac) /
2209 IP(src=eps[2].ip4.address,
2210 dst=eps[0].ip4.address) /
2211 UDP(sport=1234, dport=1234) /
2213 self.send_and_expect_bridged(eps[2].itf,
2214 pkt_inter_epg_221_to_220 * 65,
2218 # contract between 220 and 222 uni-direction
2220 c3 = VppGbpContract(
2221 self, 400, epgs[0].sclass, epgs[2].sclass, acl_index,
2222 [VppGbpContractRule(
2223 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2224 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2227 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2228 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2230 [ETH_P_IP, ETH_P_IPV6])
2233 self.send_and_expect(eps[0].itf,
2234 pkt_inter_epg_220_to_222 * 65,
2237 c3.remove_vpp_config()
2238 c1.remove_vpp_config()
2239 c2.remove_vpp_config()
2240 acl.remove_vpp_config()
2242 def test_gbp_bd_flags(self):
2243 """ GBP BD FLAGS """
2248 gt4 = VppIpTable(self, 1)
2249 gt4.add_vpp_config()
2250 gt6 = VppIpTable(self, 1, is_ip6=True)
2251 gt6.add_vpp_config()
2253 rd1 = VppGbpRouteDomain(self, 1, 401, gt4, gt6)
2254 rd1.add_vpp_config()
2257 # Pg3 hosts the IP4 UU-flood VXLAN tunnel
2258 # Pg4 hosts the IP6 UU-flood VXLAN tunnel
2260 self.pg3.config_ip4()
2261 self.pg3.resolve_arp()
2262 self.pg4.config_ip4()
2263 self.pg4.resolve_arp()
2266 # Add a mcast destination VXLAN-GBP tunnel for B&M traffic
2268 tun_bm = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
2271 tun_bm.add_vpp_config()
2274 # a GBP bridge domain with a BVI and a UU-flood interface
2276 bd1 = VppBridgeDomain(self, 1)
2277 bd1.add_vpp_config()
2279 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0, self.pg3,
2280 tun_bm, uu_drop=True, bm_drop=True)
2281 gbd1.add_vpp_config()
2283 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2284 self.logger.info(self.vapi.cli("sh gbp bridge"))
2286 # ... and has a /32 applied
2287 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2288 ip_addr.add_vpp_config()
2291 # The Endpoint-group
2293 epg_220 = VppGbpEndpointGroup(self, 220, 112, rd1, gbd1,
2297 VppGbpEndpointRetention(2))
2298 epg_220.add_vpp_config()
2300 ep = VppGbpEndpoint(self, self.pg0,
2302 "10.0.0.127", "11.0.0.127",
2303 "2001:10::1", "3001::1")
2306 # send UU/BM packet from the local EP with UU drop and BM drop enabled
2309 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2310 self.logger.info(self.vapi.cli("sh gbp bridge"))
2311 p_uu = (Ether(src=ep.mac, dst="00:11:11:11:11:11") /
2312 IP(dst="10.0.0.133", src=ep.ip4.address) /
2313 UDP(sport=1234, dport=1234) /
2315 self.send_and_assert_no_replies(ep.itf, [p_uu])
2317 p_bm = (Ether(src=ep.mac, dst="ff:ff:ff:ff:ff:ff") /
2318 IP(dst="10.0.0.133", src=ep.ip4.address) /
2319 UDP(sport=1234, dport=1234) /
2321 self.send_and_assert_no_replies(ep.itf, [p_bm])
2323 self.pg3.unconfig_ip4()
2324 self.pg4.unconfig_ip4()
2326 self.logger.info(self.vapi.cli("sh int"))
2328 def test_gbp_learn_vlan_l2(self):
2329 """ GBP L2 Endpoint w/ VLANs"""
2331 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
2332 learnt = [{'mac': '00:00:11:11:11:01',
2334 'ip6': '2001:10::2'},
2335 {'mac': '00:00:11:11:11:02',
2337 'ip6': '2001:10::3'}]
2342 gt4 = VppIpTable(self, 1)
2343 gt4.add_vpp_config()
2344 gt6 = VppIpTable(self, 1, is_ip6=True)
2345 gt6.add_vpp_config()
2347 rd1 = VppGbpRouteDomain(self, 1, 401, gt4, gt6)
2348 rd1.add_vpp_config()
2351 # Pg2 hosts the vxlan tunnel, hosts on pg2 to act as TEPs
2353 self.pg2.config_ip4()
2354 self.pg2.resolve_arp()
2355 self.pg2.generate_remote_hosts(4)
2356 self.pg2.configure_ipv4_neighbors()
2357 self.pg3.config_ip4()
2358 self.pg3.resolve_arp()
2361 # The EP will be on a vlan sub-interface
2363 vlan_11 = VppDot1QSubint(self, self.pg0, 11)
2365 self.vapi.l2_interface_vlan_tag_rewrite(
2366 sw_if_index=vlan_11.sw_if_index, vtr_op=L2_VTR_OP.L2_POP_1,
2369 bd_uu_fwd = VppVxlanGbpTunnel(self, self.pg3.local_ip4,
2370 self.pg3.remote_ip4, 116)
2371 bd_uu_fwd.add_vpp_config()
2374 # a GBP bridge domain with a BVI and a UU-flood interface
2375 # The BD is marked as do not learn, so no endpoints are ever
2376 # learnt in this BD.
2378 bd1 = VppBridgeDomain(self, 1)
2379 bd1.add_vpp_config()
2380 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0, bd_uu_fwd,
2382 gbd1.add_vpp_config()
2384 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2385 self.logger.info(self.vapi.cli("sh gbp bridge"))
2387 # ... and has a /32 applied
2388 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2389 ip_addr.add_vpp_config()
2392 # The Endpoint-group in which we are learning endpoints
2394 epg_220 = VppGbpEndpointGroup(self, 220, 441, rd1, gbd1,
2398 VppGbpEndpointRetention(2))
2399 epg_220.add_vpp_config()
2402 # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
2405 vx_tun_l2_1 = VppGbpVxlanTunnel(
2406 self, 99, bd1.bd_id,
2407 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L2,
2409 vx_tun_l2_1.add_vpp_config()
2412 # A static endpoint that the learnt endpoints are trying to
2415 ep = VppGbpEndpoint(self, vlan_11,
2417 "10.0.0.127", "11.0.0.127",
2418 "2001:10::1", "3001::1")
2421 self.assertTrue(find_route(self, ep.ip4.address, 32, table_id=1))
2424 # Send to the static EP
2426 for ii, l in enumerate(learnt):
2427 # a packet with an sclass from a known EPG
2428 # arriving on an unknown TEP
2429 p = (Ether(src=self.pg2.remote_mac,
2430 dst=self.pg2.local_mac) /
2431 IP(src=self.pg2.remote_hosts[1].ip4,
2432 dst=self.pg2.local_ip4) /
2433 UDP(sport=1234, dport=48879) /
2434 VXLAN(vni=99, gpid=441, flags=0x88) /
2435 Ether(src=l['mac'], dst=ep.mac) /
2436 IP(src=l['ip'], dst=ep.ip4.address) /
2437 UDP(sport=1234, dport=1234) /
2440 rxs = self.send_and_expect(self.pg2, [p], self.pg0)
2443 # packet to EP has the EP's vlan tag
2446 self.assertEqual(rx[Dot1Q].vlan, 11)
2449 # the EP is not learnt since the BD setting prevents it
2452 self.assertFalse(find_gbp_endpoint(self,
2453 vx_tun_l2_1.sw_if_index,
2455 self.assertEqual(INDEX_INVALID,
2456 find_vxlan_gbp_tunnel(
2459 self.pg2.remote_hosts[1].ip4,
2462 self.assertEqual(len(self.vapi.gbp_endpoint_dump()), 1)
2466 # we didn't learn the remotes so they are sent to the UU-fwd
2469 p = (Ether(src=ep.mac, dst=l['mac']) /
2471 IP(dst=l['ip'], src=ep.ip4.address) /
2472 UDP(sport=1234, dport=1234) /
2475 rxs = self.send_and_expect(self.pg0, p * 17, self.pg3)
2478 self.assertEqual(rx[IP].src, self.pg3.local_ip4)
2479 self.assertEqual(rx[IP].dst, self.pg3.remote_ip4)
2480 self.assertEqual(rx[UDP].dport, 48879)
2481 # the UDP source port is a random value for hashing
2482 self.assertEqual(rx[VXLAN].gpid, 441)
2483 self.assertEqual(rx[VXLAN].vni, 116)
2484 self.assertTrue(rx[VXLAN].flags.G)
2485 self.assertTrue(rx[VXLAN].flags.Instance)
2486 self.assertFalse(rx[VXLAN].gpflags.A)
2487 self.assertFalse(rx[VXLAN].gpflags.D)
2489 self.pg2.unconfig_ip4()
2490 self.pg3.unconfig_ip4()
2492 def test_gbp_learn_l3(self):
2493 """ GBP L3 Endpoint Learning """
2495 self.vapi.cli("set logging class gbp level debug")
2497 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
2498 routed_dst_mac = "00:0c:0c:0c:0c:0c"
2499 routed_src_mac = "00:22:bd:f8:19:ff"
2501 learnt = [{'mac': '00:00:11:11:11:02',
2503 'ip6': '2001:10::2'},
2504 {'mac': '00:00:11:11:11:03',
2506 'ip6': '2001:10::3'}]
2511 t4 = VppIpTable(self, 1)
2513 t6 = VppIpTable(self, 1, True)
2516 tun_ip4_uu = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
2517 self.pg4.remote_ip4, 114)
2518 tun_ip6_uu = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
2519 self.pg4.remote_ip4, 116)
2520 tun_ip4_uu.add_vpp_config()
2521 tun_ip6_uu.add_vpp_config()
2523 rd1 = VppGbpRouteDomain(self, 2, 401, t4, t6, tun_ip4_uu, tun_ip6_uu)
2524 rd1.add_vpp_config()
2526 self.loop0.set_mac(self.router_mac)
2529 # Bind the BVI to the RD
2531 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
2532 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
2535 # Pg2 hosts the vxlan tunnel
2536 # hosts on pg2 to act as TEPs
2540 self.pg2.config_ip4()
2541 self.pg2.resolve_arp()
2542 self.pg2.generate_remote_hosts(4)
2543 self.pg2.configure_ipv4_neighbors()
2544 self.pg3.config_ip4()
2545 self.pg3.resolve_arp()
2546 self.pg4.config_ip4()
2547 self.pg4.resolve_arp()
2550 # a GBP bridge domain with a BVI and a UU-flood interface
2552 bd1 = VppBridgeDomain(self, 1)
2553 bd1.add_vpp_config()
2554 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0, self.pg3)
2555 gbd1.add_vpp_config()
2557 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2558 self.logger.info(self.vapi.cli("sh gbp bridge"))
2559 self.logger.info(self.vapi.cli("sh gbp route"))
2561 # ... and has a /32 and /128 applied
2562 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2563 ip4_addr.add_vpp_config()
2564 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 128)
2565 ip6_addr.add_vpp_config()
2568 # The Endpoint-group in which we are learning endpoints
2570 epg_220 = VppGbpEndpointGroup(self, 220, 441, rd1, gbd1,
2574 VppGbpEndpointRetention(2))
2575 epg_220.add_vpp_config()
2578 # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
2581 vx_tun_l3 = VppGbpVxlanTunnel(
2582 self, 101, rd1.rd_id,
2583 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
2585 vx_tun_l3.add_vpp_config()
2588 # A static endpoint that the learnt endpoints are trying to
2591 ep = VppGbpEndpoint(self, self.pg0,
2593 "10.0.0.127", "11.0.0.127",
2594 "2001:10::1", "3001::1")
2598 # learn some remote IPv4 EPs
2600 for ii, l in enumerate(learnt):
2601 # a packet with an sclass from a known EPG
2602 # arriving on an unknown TEP
2603 p = (Ether(src=self.pg2.remote_mac,
2604 dst=self.pg2.local_mac) /
2605 IP(src=self.pg2.remote_hosts[1].ip4,
2606 dst=self.pg2.local_ip4) /
2607 UDP(sport=1234, dport=48879) /
2608 VXLAN(vni=101, gpid=441, flags=0x88) /
2609 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2610 IP(src=l['ip'], dst=ep.ip4.address) /
2611 UDP(sport=1234, dport=1234) /
2614 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2617 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2620 self.pg2.remote_hosts[1].ip4,
2622 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2624 # endpoint learnt via the parent GBP-vxlan interface
2625 self.assertTrue(find_gbp_endpoint(self,
2626 vx_tun_l3._sw_if_index,
2630 # Static IPv4 EP replies to learnt
2633 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2634 IP(dst=l['ip'], src=ep.ip4.address) /
2635 UDP(sport=1234, dport=1234) /
2638 rxs = self.send_and_expect(self.pg0, p * 1, self.pg2)
2641 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2642 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2643 self.assertEqual(rx[UDP].dport, 48879)
2644 # the UDP source port is a random value for hashing
2645 self.assertEqual(rx[VXLAN].gpid, 441)
2646 self.assertEqual(rx[VXLAN].vni, 101)
2647 self.assertTrue(rx[VXLAN].flags.G)
2648 self.assertTrue(rx[VXLAN].flags.Instance)
2649 self.assertTrue(rx[VXLAN].gpflags.A)
2650 self.assertFalse(rx[VXLAN].gpflags.D)
2652 inner = rx[VXLAN].payload
2654 self.assertEqual(inner[Ether].src, routed_src_mac)
2655 self.assertEqual(inner[Ether].dst, routed_dst_mac)
2656 self.assertEqual(inner[IP].src, ep.ip4.address)
2657 self.assertEqual(inner[IP].dst, l['ip'])
2660 self.assertFalse(find_gbp_endpoint(self,
2665 # learn some remote IPv6 EPs
2667 for ii, l in enumerate(learnt):
2668 # a packet with an sclass from a known EPG
2669 # arriving on an unknown TEP
2670 p = (Ether(src=self.pg2.remote_mac,
2671 dst=self.pg2.local_mac) /
2672 IP(src=self.pg2.remote_hosts[1].ip4,
2673 dst=self.pg2.local_ip4) /
2674 UDP(sport=1234, dport=48879) /
2675 VXLAN(vni=101, gpid=441, flags=0x88) /
2676 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2677 IPv6(src=l['ip6'], dst=ep.ip6.address) /
2678 UDP(sport=1234, dport=1234) /
2681 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2684 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2687 self.pg2.remote_hosts[1].ip4,
2689 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2691 self.logger.info(self.vapi.cli("show gbp bridge"))
2692 self.logger.info(self.vapi.cli("show vxlan-gbp tunnel"))
2693 self.logger.info(self.vapi.cli("show gbp vxlan"))
2694 self.logger.info(self.vapi.cli("show int addr"))
2696 # endpoint learnt via the TEP
2697 self.assertTrue(find_gbp_endpoint(self, ip=l['ip6']))
2699 self.logger.info(self.vapi.cli("show gbp endpoint"))
2700 self.logger.info(self.vapi.cli("show ip fib index 1 %s" % l['ip']))
2703 # Static EP replies to learnt
2706 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2707 IPv6(dst=l['ip6'], src=ep.ip6.address) /
2708 UDP(sport=1234, dport=1234) /
2711 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
2714 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2715 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2716 self.assertEqual(rx[UDP].dport, 48879)
2717 # the UDP source port is a random value for hashing
2718 self.assertEqual(rx[VXLAN].gpid, 441)
2719 self.assertEqual(rx[VXLAN].vni, 101)
2720 self.assertTrue(rx[VXLAN].flags.G)
2721 self.assertTrue(rx[VXLAN].flags.Instance)
2722 self.assertTrue(rx[VXLAN].gpflags.A)
2723 self.assertFalse(rx[VXLAN].gpflags.D)
2725 inner = rx[VXLAN].payload
2727 self.assertEqual(inner[Ether].src, routed_src_mac)
2728 self.assertEqual(inner[Ether].dst, routed_dst_mac)
2729 self.assertEqual(inner[IPv6].src, ep.ip6.address)
2730 self.assertEqual(inner[IPv6].dst, l['ip6'])
2732 self.logger.info(self.vapi.cli("sh gbp endpoint"))
2734 self.wait_for_ep_timeout(ip=l['ip'])
2737 # Static sends to unknown EP with no route
2739 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2740 IP(dst="10.0.0.99", src=ep.ip4.address) /
2741 UDP(sport=1234, dport=1234) /
2744 self.send_and_assert_no_replies(self.pg0, [p])
2747 # Add a route to static EP's v4 and v6 subnet
2748 # packets should be sent on the v4/v6 uu=fwd interface resp.
2750 se_10_24 = VppGbpSubnet(
2751 self, rd1, "10.0.0.0", 24,
2752 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT)
2753 se_10_24.add_vpp_config()
2755 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2756 IP(dst="10.0.0.99", src=ep.ip4.address) /
2757 UDP(sport=1234, dport=1234) /
2760 rxs = self.send_and_expect(self.pg0, [p], self.pg4)
2762 self.assertEqual(rx[IP].src, self.pg4.local_ip4)
2763 self.assertEqual(rx[IP].dst, self.pg4.remote_ip4)
2764 self.assertEqual(rx[UDP].dport, 48879)
2765 # the UDP source port is a random value for hashing
2766 self.assertEqual(rx[VXLAN].gpid, 441)
2767 self.assertEqual(rx[VXLAN].vni, 114)
2768 self.assertTrue(rx[VXLAN].flags.G)
2769 self.assertTrue(rx[VXLAN].flags.Instance)
2770 # policy is not applied to packets sent to the uu-fwd interfaces
2771 self.assertFalse(rx[VXLAN].gpflags.A)
2772 self.assertFalse(rx[VXLAN].gpflags.D)
2775 # learn some remote IPv4 EPs
2777 for ii, l in enumerate(learnt):
2778 # a packet with an sclass from a known EPG
2779 # arriving on an unknown TEP
2780 p = (Ether(src=self.pg2.remote_mac,
2781 dst=self.pg2.local_mac) /
2782 IP(src=self.pg2.remote_hosts[2].ip4,
2783 dst=self.pg2.local_ip4) /
2784 UDP(sport=1234, dport=48879) /
2785 VXLAN(vni=101, gpid=441, flags=0x88) /
2786 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2787 IP(src=l['ip'], dst=ep.ip4.address) /
2788 UDP(sport=1234, dport=1234) /
2791 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2794 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2797 self.pg2.remote_hosts[2].ip4,
2799 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2801 # endpoint learnt via the parent GBP-vxlan interface
2802 self.assertTrue(find_gbp_endpoint(self,
2803 vx_tun_l3._sw_if_index,
2807 # Add a remote endpoint from the API
2809 rep_88 = VppGbpEndpoint(self, vx_tun_l3,
2811 "10.0.0.88", "11.0.0.88",
2812 "2001:10::88", "3001::88",
2813 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
2815 self.pg2.remote_hosts[2].ip4,
2817 rep_88.add_vpp_config()
2820 # Add a remote endpoint from the API that matches an existing one
2821 # this is a lower priority, hence the packet is sent to the DP leanrt
2824 rep_2 = VppGbpEndpoint(self, vx_tun_l3,
2826 learnt[0]['ip'], "11.0.0.101",
2827 learnt[0]['ip6'], "3001::101",
2828 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
2830 self.pg2.remote_hosts[1].ip4,
2832 rep_2.add_vpp_config()
2835 # Add a route to the learned EP's v4 subnet
2836 # packets should be send on the v4/v6 uu=fwd interface resp.
2838 se_10_1_24 = VppGbpSubnet(
2839 self, rd1, "10.0.1.0", 24,
2840 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT)
2841 se_10_1_24.add_vpp_config()
2843 self.logger.info(self.vapi.cli("show gbp endpoint"))
2845 ips = ["10.0.0.88", learnt[0]['ip']]
2847 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2848 IP(dst=ip, src=ep.ip4.address) /
2849 UDP(sport=1234, dport=1234) /
2852 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
2855 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2856 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[2].ip4)
2857 self.assertEqual(rx[UDP].dport, 48879)
2858 # the UDP source port is a random value for hashing
2859 self.assertEqual(rx[VXLAN].gpid, 441)
2860 self.assertEqual(rx[VXLAN].vni, 101)
2861 self.assertTrue(rx[VXLAN].flags.G)
2862 self.assertTrue(rx[VXLAN].flags.Instance)
2863 self.assertTrue(rx[VXLAN].gpflags.A)
2864 self.assertFalse(rx[VXLAN].gpflags.D)
2866 inner = rx[VXLAN].payload
2868 self.assertEqual(inner[Ether].src, routed_src_mac)
2869 self.assertEqual(inner[Ether].dst, routed_dst_mac)
2870 self.assertEqual(inner[IP].src, ep.ip4.address)
2871 self.assertEqual(inner[IP].dst, ip)
2874 # remove the API remote EPs, only API sourced is gone, the DP
2875 # learnt one remains
2877 rep_88.remove_vpp_config()
2878 rep_2.remove_vpp_config()
2880 self.assertTrue(find_gbp_endpoint(self, ip=rep_2.ip4.address))
2882 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2883 IP(src=ep.ip4.address, dst=rep_2.ip4.address) /
2884 UDP(sport=1234, dport=1234) /
2886 rxs = self.send_and_expect(self.pg0, [p], self.pg2)
2888 self.assertFalse(find_gbp_endpoint(self, ip=rep_88.ip4.address))
2890 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2891 IP(src=ep.ip4.address, dst=rep_88.ip4.address) /
2892 UDP(sport=1234, dport=1234) /
2894 rxs = self.send_and_expect(self.pg0, [p], self.pg4)
2897 # to appease the testcase we cannot have the registered EP still
2898 # present (because it's DP learnt) when the TC ends so wait until
2901 self.wait_for_ep_timeout(ip=rep_88.ip4.address)
2902 self.wait_for_ep_timeout(ip=rep_2.ip4.address)
2905 # Same as above, learn a remote EP via CP and DP
2906 # this time remove the DP one first. expect the CP data to remain
2908 rep_3 = VppGbpEndpoint(self, vx_tun_l3,
2910 "10.0.1.4", "11.0.0.103",
2911 "2001::10:3", "3001::103",
2912 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
2914 self.pg2.remote_hosts[1].ip4,
2916 rep_3.add_vpp_config()
2918 p = (Ether(src=self.pg2.remote_mac,
2919 dst=self.pg2.local_mac) /
2920 IP(src=self.pg2.remote_hosts[2].ip4,
2921 dst=self.pg2.local_ip4) /
2922 UDP(sport=1234, dport=48879) /
2923 VXLAN(vni=101, gpid=441, flags=0x88) /
2924 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2925 IP(src="10.0.1.4", dst=ep.ip4.address) /
2926 UDP(sport=1234, dport=1234) /
2928 rxs = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
2930 self.assertTrue(find_gbp_endpoint(self,
2931 vx_tun_l3._sw_if_index,
2932 ip=rep_3.ip4.address,
2933 tep=[self.pg2.local_ip4,
2934 self.pg2.remote_hosts[2].ip4]))
2936 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2937 IP(dst="10.0.1.4", src=ep.ip4.address) /
2938 UDP(sport=1234, dport=1234) /
2940 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
2942 # host 2 is the DP learned TEP
2944 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2945 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[2].ip4)
2947 self.wait_for_ep_timeout(ip=rep_3.ip4.address,
2948 tep=[self.pg2.local_ip4,
2949 self.pg2.remote_hosts[2].ip4])
2951 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
2953 # host 1 is the CP learned TEP
2955 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2956 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2959 # shutdown with learnt endpoint present
2961 p = (Ether(src=self.pg2.remote_mac,
2962 dst=self.pg2.local_mac) /
2963 IP(src=self.pg2.remote_hosts[1].ip4,
2964 dst=self.pg2.local_ip4) /
2965 UDP(sport=1234, dport=48879) /
2966 VXLAN(vni=101, gpid=441, flags=0x88) /
2967 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2968 IP(src=learnt[1]['ip'], dst=ep.ip4.address) /
2969 UDP(sport=1234, dport=1234) /
2972 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2974 # endpoint learnt via the parent GBP-vxlan interface
2975 self.assertTrue(find_gbp_endpoint(self,
2976 vx_tun_l3._sw_if_index,
2981 # remote endpoint becomes local
2983 self.pg2.unconfig_ip4()
2984 self.pg3.unconfig_ip4()
2985 self.pg4.unconfig_ip4()
2987 def test_gbp_redirect(self):
2988 """ GBP Endpoint Redirect """
2990 self.vapi.cli("set logging class gbp level debug")
2992 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
2993 routed_dst_mac = "00:0c:0c:0c:0c:0c"
2994 routed_src_mac = "00:22:bd:f8:19:ff"
2996 learnt = [{'mac': '00:00:11:11:11:02',
2998 'ip6': '2001:10::2'},
2999 {'mac': '00:00:11:11:11:03',
3001 'ip6': '2001:10::3'}]
3006 t4 = VppIpTable(self, 1)
3008 t6 = VppIpTable(self, 1, True)
3011 rd1 = VppGbpRouteDomain(self, 2, 402, t4, t6)
3012 rd1.add_vpp_config()
3014 self.loop0.set_mac(self.router_mac)
3017 # Bind the BVI to the RD
3019 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
3020 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
3023 # Pg7 hosts a BD's UU-fwd
3025 self.pg7.config_ip4()
3026 self.pg7.resolve_arp()
3029 # a GBP bridge domains for the EPs
3031 bd1 = VppBridgeDomain(self, 1)
3032 bd1.add_vpp_config()
3033 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0)
3034 gbd1.add_vpp_config()
3036 bd2 = VppBridgeDomain(self, 2)
3037 bd2.add_vpp_config()
3038 gbd2 = VppGbpBridgeDomain(self, bd2, rd1, self.loop1)
3039 gbd2.add_vpp_config()
3041 # ... and has a /32 and /128 applied
3042 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
3043 ip4_addr.add_vpp_config()
3044 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 128)
3045 ip6_addr.add_vpp_config()
3046 ip4_addr = VppIpInterfaceAddress(self, gbd2.bvi, "10.0.1.128", 32)
3047 ip4_addr.add_vpp_config()
3048 ip6_addr = VppIpInterfaceAddress(self, gbd2.bvi, "2001:11::128", 128)
3049 ip6_addr.add_vpp_config()
3052 # The Endpoint-groups in which we are learning endpoints
3054 epg_220 = VppGbpEndpointGroup(self, 220, 440, rd1, gbd1,
3058 VppGbpEndpointRetention(2))
3059 epg_220.add_vpp_config()
3060 epg_221 = VppGbpEndpointGroup(self, 221, 441, rd1, gbd2,
3064 VppGbpEndpointRetention(2))
3065 epg_221.add_vpp_config()
3066 epg_222 = VppGbpEndpointGroup(self, 222, 442, rd1, gbd1,
3070 VppGbpEndpointRetention(2))
3071 epg_222.add_vpp_config()
3074 # a GBP bridge domains for the SEPs
3076 bd_uu1 = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
3077 self.pg7.remote_ip4, 116)
3078 bd_uu1.add_vpp_config()
3079 bd_uu2 = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
3080 self.pg7.remote_ip4, 117)
3081 bd_uu2.add_vpp_config()
3083 bd3 = VppBridgeDomain(self, 3)
3084 bd3.add_vpp_config()
3085 gbd3 = VppGbpBridgeDomain(self, bd3, rd1, self.loop2,
3086 bd_uu1, learn=False)
3087 gbd3.add_vpp_config()
3088 bd4 = VppBridgeDomain(self, 4)
3089 bd4.add_vpp_config()
3090 gbd4 = VppGbpBridgeDomain(self, bd4, rd1, self.loop3,
3091 bd_uu2, learn=False)
3092 gbd4.add_vpp_config()
3095 # EPGs in which the service endpoints exist
3097 epg_320 = VppGbpEndpointGroup(self, 320, 550, rd1, gbd3,
3101 VppGbpEndpointRetention(2))
3102 epg_320.add_vpp_config()
3103 epg_321 = VppGbpEndpointGroup(self, 321, 551, rd1, gbd4,
3107 VppGbpEndpointRetention(2))
3108 epg_321.add_vpp_config()
3111 # three local endpoints
3113 ep1 = VppGbpEndpoint(self, self.pg0,
3115 "10.0.0.1", "11.0.0.1",
3116 "2001:10::1", "3001:10::1")
3117 ep1.add_vpp_config()
3118 ep2 = VppGbpEndpoint(self, self.pg1,
3120 "10.0.1.1", "11.0.1.1",
3121 "2001:11::1", "3001:11::1")
3122 ep2.add_vpp_config()
3123 ep3 = VppGbpEndpoint(self, self.pg2,
3125 "10.0.2.2", "11.0.2.2",
3126 "2001:12::1", "3001:12::1")
3127 ep3.add_vpp_config()
3132 sep1 = VppGbpEndpoint(self, self.pg3,
3134 "12.0.0.1", "13.0.0.1",
3135 "4001:10::1", "5001:10::1")
3136 sep1.add_vpp_config()
3137 sep2 = VppGbpEndpoint(self, self.pg4,
3139 "12.0.0.2", "13.0.0.2",
3140 "4001:10::2", "5001:10::2")
3141 sep2.add_vpp_config()
3142 sep3 = VppGbpEndpoint(self, self.pg5,
3144 "12.0.1.1", "13.0.1.1",
3145 "4001:11::1", "5001:11::1")
3146 sep3.add_vpp_config()
3147 # this EP is not installed immediately
3148 sep4 = VppGbpEndpoint(self, self.pg6,
3150 "12.0.1.2", "13.0.1.2",
3151 "4001:11::2", "5001:11::2")
3154 # an L2 switch packet between local EPs in different EPGs
3155 # different dest ports on each so the are LB hashed differently
3157 p4 = [(Ether(src=ep1.mac, dst=ep3.mac) /
3158 IP(src=ep1.ip4.address, dst=ep3.ip4.address) /
3159 UDP(sport=1234, dport=1234) /
3161 (Ether(src=ep3.mac, dst=ep1.mac) /
3162 IP(src=ep3.ip4.address, dst=ep1.ip4.address) /
3163 UDP(sport=1234, dport=1234) /
3165 p6 = [(Ether(src=ep1.mac, dst=ep3.mac) /
3166 IPv6(src=ep1.ip6.address, dst=ep3.ip6.address) /
3167 UDP(sport=1234, dport=1234) /
3169 (Ether(src=ep3.mac, dst=ep1.mac) /
3170 IPv6(src=ep3.ip6.address, dst=ep1.ip6.address) /
3171 UDP(sport=1234, dport=1230) /
3174 # should be dropped since no contract yet
3175 self.send_and_assert_no_replies(self.pg0, [p4[0]])
3176 self.send_and_assert_no_replies(self.pg0, [p6[0]])
3179 # Add a contract with a rule to load-balance redirect via SEP1 and SEP2
3180 # one of the next-hops is via an EP that is not known
3182 acl = VppGbpAcl(self)
3183 rule4 = acl.create_rule(permit_deny=1, proto=17)
3184 rule6 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
3185 acl_index = acl.add_vpp_config([rule4, rule6])
3188 # test the src-ip hash mode
3190 c1 = VppGbpContract(
3191 self, 402, epg_220.sclass, epg_222.sclass, acl_index,
3192 [VppGbpContractRule(
3193 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3194 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3195 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3196 sep1.ip4, sep1.epg.rd),
3197 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3198 sep2.ip4, sep2.epg.rd)]),
3200 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3201 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3202 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3203 sep3.ip6, sep3.epg.rd),
3204 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3205 sep4.ip6, sep4.epg.rd)])],
3206 [ETH_P_IP, ETH_P_IPV6])
3209 c2 = VppGbpContract(
3210 self, 402, epg_222.sclass, epg_220.sclass, acl_index,
3211 [VppGbpContractRule(
3212 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3213 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3214 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3215 sep1.ip4, sep1.epg.rd),
3216 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3217 sep2.ip4, sep2.epg.rd)]),
3219 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3220 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3221 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3222 sep3.ip6, sep3.epg.rd),
3223 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3224 sep4.ip6, sep4.epg.rd)])],
3225 [ETH_P_IP, ETH_P_IPV6])
3229 # send again with the contract preset, now packets arrive
3230 # at SEP1 or SEP2 depending on the hashing
3232 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3235 self.assertEqual(rx[Ether].src, routed_src_mac)
3236 self.assertEqual(rx[Ether].dst, sep1.mac)
3237 self.assertEqual(rx[IP].src, ep1.ip4.address)
3238 self.assertEqual(rx[IP].dst, ep3.ip4.address)
3240 rxs = self.send_and_expect(self.pg2, p4[1] * 17, sep2.itf)
3243 self.assertEqual(rx[Ether].src, routed_src_mac)
3244 self.assertEqual(rx[Ether].dst, sep2.mac)
3245 self.assertEqual(rx[IP].src, ep3.ip4.address)
3246 self.assertEqual(rx[IP].dst, ep1.ip4.address)
3248 rxs = self.send_and_expect(self.pg0, p6[0] * 17, self.pg7)
3251 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3252 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3253 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3254 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
3255 self.assertEqual(rx[VXLAN].vni, 117)
3256 self.assertTrue(rx[VXLAN].flags.G)
3257 self.assertTrue(rx[VXLAN].flags.Instance)
3258 # redirect policy has been applied
3259 self.assertTrue(rx[VXLAN].gpflags.A)
3260 self.assertFalse(rx[VXLAN].gpflags.D)
3262 inner = rx[VXLAN].payload
3264 self.assertEqual(inner[Ether].src, routed_src_mac)
3265 self.assertEqual(inner[Ether].dst, sep4.mac)
3266 self.assertEqual(inner[IPv6].src, ep1.ip6.address)
3267 self.assertEqual(inner[IPv6].dst, ep3.ip6.address)
3269 rxs = self.send_and_expect(self.pg2, p6[1] * 17, sep3.itf)
3272 self.assertEqual(rx[Ether].src, routed_src_mac)
3273 self.assertEqual(rx[Ether].dst, sep3.mac)
3274 self.assertEqual(rx[IPv6].src, ep3.ip6.address)
3275 self.assertEqual(rx[IPv6].dst, ep1.ip6.address)
3278 # programme the unknown EP
3280 sep4.add_vpp_config()
3282 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep4.itf)
3285 self.assertEqual(rx[Ether].src, routed_src_mac)
3286 self.assertEqual(rx[Ether].dst, sep4.mac)
3287 self.assertEqual(rx[IPv6].src, ep1.ip6.address)
3288 self.assertEqual(rx[IPv6].dst, ep3.ip6.address)
3291 # and revert back to unprogrammed
3293 sep4.remove_vpp_config()
3295 rxs = self.send_and_expect(self.pg0, p6[0] * 17, self.pg7)
3298 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3299 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3300 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3301 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
3302 self.assertEqual(rx[VXLAN].vni, 117)
3303 self.assertTrue(rx[VXLAN].flags.G)
3304 self.assertTrue(rx[VXLAN].flags.Instance)
3305 # redirect policy has been applied
3306 self.assertTrue(rx[VXLAN].gpflags.A)
3307 self.assertFalse(rx[VXLAN].gpflags.D)
3309 inner = rx[VXLAN].payload
3311 self.assertEqual(inner[Ether].src, routed_src_mac)
3312 self.assertEqual(inner[Ether].dst, sep4.mac)
3313 self.assertEqual(inner[IPv6].src, ep1.ip6.address)
3314 self.assertEqual(inner[IPv6].dst, ep3.ip6.address)
3316 c1.remove_vpp_config()
3317 c2.remove_vpp_config()
3320 # test the symmetric hash mode
3322 c1 = VppGbpContract(
3323 self, 402, epg_220.sclass, epg_222.sclass, acl_index,
3324 [VppGbpContractRule(
3325 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3326 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3327 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3328 sep1.ip4, sep1.epg.rd),
3329 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3330 sep2.ip4, sep2.epg.rd)]),
3332 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3333 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3334 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3335 sep3.ip6, sep3.epg.rd),
3336 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3337 sep4.ip6, sep4.epg.rd)])],
3338 [ETH_P_IP, ETH_P_IPV6])
3341 c2 = VppGbpContract(
3342 self, 402, epg_222.sclass, epg_220.sclass, acl_index,
3343 [VppGbpContractRule(
3344 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3345 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3346 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3347 sep1.ip4, sep1.epg.rd),
3348 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3349 sep2.ip4, sep2.epg.rd)]),
3351 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3352 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3353 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3354 sep3.ip6, sep3.epg.rd),
3355 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3356 sep4.ip6, sep4.epg.rd)])],
3357 [ETH_P_IP, ETH_P_IPV6])
3361 # send again with the contract preset, now packets arrive
3362 # at SEP1 for both directions
3364 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3367 self.assertEqual(rx[Ether].src, routed_src_mac)
3368 self.assertEqual(rx[Ether].dst, sep1.mac)
3369 self.assertEqual(rx[IP].src, ep1.ip4.address)
3370 self.assertEqual(rx[IP].dst, ep3.ip4.address)
3372 rxs = self.send_and_expect(self.pg2, p4[1] * 17, sep1.itf)
3375 self.assertEqual(rx[Ether].src, routed_src_mac)
3376 self.assertEqual(rx[Ether].dst, sep1.mac)
3377 self.assertEqual(rx[IP].src, ep3.ip4.address)
3378 self.assertEqual(rx[IP].dst, ep1.ip4.address)
3381 # programme the unknown EP for the L3 tests
3383 sep4.add_vpp_config()
3386 # an L3 switch packet between local EPs in different EPGs
3387 # different dest ports on each so the are LB hashed differently
3389 p4 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3390 IP(src=ep1.ip4.address, dst=ep2.ip4.address) /
3391 UDP(sport=1234, dport=1234) /
3393 (Ether(src=ep2.mac, dst=str(self.router_mac)) /
3394 IP(src=ep2.ip4.address, dst=ep1.ip4.address) /
3395 UDP(sport=1234, dport=1234) /
3397 p6 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3398 IPv6(src=ep1.ip6.address, dst=ep2.ip6.address) /
3399 UDP(sport=1234, dport=1234) /
3401 (Ether(src=ep2.mac, dst=str(self.router_mac)) /
3402 IPv6(src=ep2.ip6.address, dst=ep1.ip6.address) /
3403 UDP(sport=1234, dport=1234) /
3406 c3 = VppGbpContract(
3407 self, 402, epg_220.sclass, epg_221.sclass, acl_index,
3408 [VppGbpContractRule(
3409 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3410 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3411 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3412 sep1.ip4, sep1.epg.rd),
3413 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3414 sep2.ip4, sep2.epg.rd)]),
3416 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3417 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3418 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3419 sep3.ip6, sep3.epg.rd),
3420 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3421 sep4.ip6, sep4.epg.rd)])],
3422 [ETH_P_IP, ETH_P_IPV6])
3425 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3428 self.assertEqual(rx[Ether].src, routed_src_mac)
3429 self.assertEqual(rx[Ether].dst, sep1.mac)
3430 self.assertEqual(rx[IP].src, ep1.ip4.address)
3431 self.assertEqual(rx[IP].dst, ep2.ip4.address)
3434 # learn a remote EP in EPG 221
3436 vx_tun_l3 = VppGbpVxlanTunnel(
3437 self, 444, rd1.rd_id,
3438 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
3440 vx_tun_l3.add_vpp_config()
3442 c4 = VppGbpContract(
3443 self, 402, epg_221.sclass, epg_220.sclass, acl_index,
3444 [VppGbpContractRule(
3445 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3446 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3449 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3450 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3452 [ETH_P_IP, ETH_P_IPV6])
3455 p = (Ether(src=self.pg7.remote_mac,
3456 dst=self.pg7.local_mac) /
3457 IP(src=self.pg7.remote_ip4,
3458 dst=self.pg7.local_ip4) /
3459 UDP(sport=1234, dport=48879) /
3460 VXLAN(vni=444, gpid=441, flags=0x88) /
3461 Ether(src="00:22:22:22:22:33", dst=str(self.router_mac)) /
3462 IP(src="10.0.0.88", dst=ep1.ip4.address) /
3463 UDP(sport=1234, dport=1234) /
3466 rx = self.send_and_expect(self.pg7, [p], self.pg0)
3468 # endpoint learnt via the parent GBP-vxlan interface
3469 self.assertTrue(find_gbp_endpoint(self,
3470 vx_tun_l3._sw_if_index,
3473 p = (Ether(src=self.pg7.remote_mac,
3474 dst=self.pg7.local_mac) /
3475 IP(src=self.pg7.remote_ip4,
3476 dst=self.pg7.local_ip4) /
3477 UDP(sport=1234, dport=48879) /
3478 VXLAN(vni=444, gpid=441, flags=0x88) /
3479 Ether(src="00:22:22:22:22:33", dst=str(self.router_mac)) /
3480 IPv6(src="2001:10::88", dst=ep1.ip6.address) /
3481 UDP(sport=1234, dport=1234) /
3484 rx = self.send_and_expect(self.pg7, [p], self.pg0)
3486 # endpoint learnt via the parent GBP-vxlan interface
3487 self.assertTrue(find_gbp_endpoint(self,
3488 vx_tun_l3._sw_if_index,
3492 # L3 switch from local to remote EP
3494 p4 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3495 IP(src=ep1.ip4.address, dst="10.0.0.88") /
3496 UDP(sport=1234, dport=1234) /
3498 p6 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3499 IPv6(src=ep1.ip6.address, dst="2001:10::88") /
3500 UDP(sport=1234, dport=1234) /
3503 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3506 self.assertEqual(rx[Ether].src, routed_src_mac)
3507 self.assertEqual(rx[Ether].dst, sep1.mac)
3508 self.assertEqual(rx[IP].src, ep1.ip4.address)
3509 self.assertEqual(rx[IP].dst, "10.0.0.88")
3511 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep4.itf)
3514 self.assertEqual(rx[Ether].src, routed_src_mac)
3515 self.assertEqual(rx[Ether].dst, sep4.mac)
3516 self.assertEqual(rx[IPv6].src, ep1.ip6.address)
3517 self.assertEqual(rx[IPv6].dst, "2001:10::88")
3520 # test the dst-ip hash mode
3522 c5 = VppGbpContract(
3523 self, 402, epg_220.sclass, epg_221.sclass, acl_index,
3524 [VppGbpContractRule(
3525 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3526 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
3527 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3528 sep1.ip4, sep1.epg.rd),
3529 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3530 sep2.ip4, sep2.epg.rd)]),
3532 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3533 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
3534 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3535 sep3.ip6, sep3.epg.rd),
3536 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3537 sep4.ip6, sep4.epg.rd)])],
3538 [ETH_P_IP, ETH_P_IPV6])
3541 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3544 self.assertEqual(rx[Ether].src, routed_src_mac)
3545 self.assertEqual(rx[Ether].dst, sep1.mac)
3546 self.assertEqual(rx[IP].src, ep1.ip4.address)
3547 self.assertEqual(rx[IP].dst, "10.0.0.88")
3549 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep3.itf)
3552 self.assertEqual(rx[Ether].src, routed_src_mac)
3553 self.assertEqual(rx[Ether].dst, sep3.mac)
3554 self.assertEqual(rx[IPv6].src, ep1.ip6.address)
3555 self.assertEqual(rx[IPv6].dst, "2001:10::88")
3560 self.pg7.unconfig_ip4()
3562 def test_gbp_l3_out(self):
3565 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
3566 self.vapi.cli("set logging class gbp level debug")
3568 routed_dst_mac = "00:0c:0c:0c:0c:0c"
3569 routed_src_mac = "00:22:bd:f8:19:ff"
3574 t4 = VppIpTable(self, 1)
3576 t6 = VppIpTable(self, 1, True)
3579 rd1 = VppGbpRouteDomain(self, 2, 55, t4, t6)
3580 rd1.add_vpp_config()
3582 self.loop0.set_mac(self.router_mac)
3585 # Bind the BVI to the RD
3587 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
3588 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
3591 # Pg7 hosts a BD's BUM
3592 # Pg1 some other l3 interface
3594 self.pg7.config_ip4()
3595 self.pg7.resolve_arp()
3598 # a multicast vxlan-gbp tunnel for broadcast in the BD
3600 tun_bm = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
3603 tun_bm.add_vpp_config()
3606 # a GBP external bridge domains for the EPs
3608 bd1 = VppBridgeDomain(self, 1)
3609 bd1.add_vpp_config()
3610 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0, None, tun_bm)
3611 gbd1.add_vpp_config()
3614 # The Endpoint-groups in which the external endpoints exist
3616 epg_220 = VppGbpEndpointGroup(self, 220, 113, rd1, gbd1,
3620 VppGbpEndpointRetention(2))
3621 epg_220.add_vpp_config()
3623 # the BVIs have the subnets applied ...
3624 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 24)
3625 ip4_addr.add_vpp_config()
3626 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 64)
3627 ip6_addr.add_vpp_config()
3629 # ... which are L3-out subnets
3630 l3o_1 = VppGbpSubnet(
3631 self, rd1, "10.0.0.0", 24,
3632 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3634 l3o_1.add_vpp_config()
3637 # an external interface attached to the outside world and the
3640 vlan_100 = VppDot1QSubint(self, self.pg0, 100)
3642 VppL2Vtr(self, vlan_100, L2_VTR_OP.L2_POP_1).add_vpp_config()
3643 vlan_101 = VppDot1QSubint(self, self.pg0, 101)
3645 VppL2Vtr(self, vlan_101, L2_VTR_OP.L2_POP_1).add_vpp_config()
3646 # vlan_102 is not poped
3647 vlan_102 = VppDot1QSubint(self, self.pg0, 102)
3650 ext_itf = VppGbpExtItf(self, self.loop0, bd1, rd1)
3651 ext_itf.add_vpp_config()
3654 # an unicast vxlan-gbp for inter-RD traffic
3656 vx_tun_l3 = VppGbpVxlanTunnel(
3657 self, 444, rd1.rd_id,
3658 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
3660 vx_tun_l3.add_vpp_config()
3663 # External Endpoints
3665 eep1 = VppGbpEndpoint(self, vlan_100,
3667 "10.0.0.1", "11.0.0.1",
3668 "2001:10::1", "3001::1",
3669 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
3670 eep1.add_vpp_config()
3671 eep2 = VppGbpEndpoint(self, vlan_101,
3673 "10.0.0.2", "11.0.0.2",
3674 "2001:10::2", "3001::2",
3675 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
3676 eep2.add_vpp_config()
3677 eep3 = VppGbpEndpoint(self, vlan_102,
3679 "10.0.0.3", "11.0.0.3",
3680 "2001:10::3", "3001::3",
3681 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
3682 eep3.add_vpp_config()
3685 # A remote external endpoint
3687 rep = VppGbpEndpoint(self, vx_tun_l3,
3689 "10.0.0.101", "11.0.0.101",
3690 "2001:10::101", "3001::101",
3691 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
3693 self.pg7.remote_ip4,
3695 rep.add_vpp_config()
3698 # EP1 impersonating EP3 is dropped
3700 p = (Ether(src=eep1.mac, dst="ff:ff:ff:ff:ff:ff") /
3703 psrc="10.0.0.3", pdst="10.0.0.128",
3704 hwsrc=eep1.mac, hwdst="ff:ff:ff:ff:ff:ff"))
3705 self.send_and_assert_no_replies(self.pg0, p)
3708 # ARP packet from External EPs are accepted and replied to
3710 p_arp = (Ether(src=eep1.mac, dst="ff:ff:ff:ff:ff:ff") /
3713 psrc=eep1.ip4.address, pdst="10.0.0.128",
3714 hwsrc=eep1.mac, hwdst="ff:ff:ff:ff:ff:ff"))
3715 rxs = self.send_and_expect(self.pg0, p_arp * 1, self.pg0)
3718 # ARP packet from host in remote subnet are accepted and replied to
3720 p_arp = (Ether(src=eep3.mac, dst="ff:ff:ff:ff:ff:ff") /
3723 psrc=eep3.ip4.address, pdst="10.0.0.128",
3724 hwsrc=eep3.mac, hwdst="ff:ff:ff:ff:ff:ff"))
3725 rxs = self.send_and_expect(self.pg0, p_arp * 1, self.pg0)
3728 # packets destined to unknown addresses in the BVI's subnet
3731 p4 = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3733 IP(src="10.0.0.1", dst="10.0.0.88") /
3734 UDP(sport=1234, dport=1234) /
3736 p6 = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3738 IPv6(src="2001:10::1", dst="2001:10::88") /
3739 UDP(sport=1234, dport=1234) /
3742 rxs = self.send_and_expect(self.pg0, p4 * 1, self.pg7)
3745 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3746 # self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3747 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3748 self.assertEqual(rx[IP].dst, "239.1.1.1")
3749 self.assertEqual(rx[VXLAN].vni, 88)
3750 self.assertTrue(rx[VXLAN].flags.G)
3751 self.assertTrue(rx[VXLAN].flags.Instance)
3752 # policy was applied to the original IP packet
3753 self.assertEqual(rx[VXLAN].gpid, 113)
3754 self.assertTrue(rx[VXLAN].gpflags.A)
3755 self.assertFalse(rx[VXLAN].gpflags.D)
3757 inner = rx[VXLAN].payload
3759 self.assertTrue(inner.haslayer(ARP))
3762 # remote to external
3764 p = (Ether(src=self.pg7.remote_mac,
3765 dst=self.pg7.local_mac) /
3766 IP(src=self.pg7.remote_ip4,
3767 dst=self.pg7.local_ip4) /
3768 UDP(sport=1234, dport=48879) /
3769 VXLAN(vni=444, gpid=113, flags=0x88) /
3770 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
3771 IP(src="10.0.0.101", dst="10.0.0.1") /
3772 UDP(sport=1234, dport=1234) /
3775 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
3778 # local EP pings router
3780 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3782 IP(src=eep1.ip4.address, dst="10.0.0.128") /
3783 ICMP(type='echo-request'))
3785 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
3788 self.assertEqual(rx[Ether].src, str(self.router_mac))
3789 self.assertEqual(rx[Ether].dst, eep1.mac)
3790 self.assertEqual(rx[Dot1Q].vlan, 100)
3793 # local EP pings other local EP
3795 p = (Ether(src=eep1.mac, dst=eep2.mac) /
3797 IP(src=eep1.ip4.address, dst=eep2.ip4.address) /
3798 ICMP(type='echo-request'))
3800 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
3803 self.assertEqual(rx[Ether].src, eep1.mac)
3804 self.assertEqual(rx[Ether].dst, eep2.mac)
3805 self.assertEqual(rx[Dot1Q].vlan, 101)
3808 # local EP pings router w/o vlan tag poped
3810 p = (Ether(src=eep3.mac, dst=str(self.router_mac)) /
3812 IP(src=eep3.ip4.address, dst="10.0.0.128") /
3813 ICMP(type='echo-request'))
3815 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
3818 self.assertEqual(rx[Ether].src, str(self.router_mac))
3819 self.assertEqual(rx[Ether].dst, vlan_102.remote_mac)
3822 # A subnet reachable through the external EP1
3824 ip_220 = VppIpRoute(self, "10.220.0.0", 24,
3825 [VppRoutePath(eep1.ip4.address,
3826 eep1.epg.bvi.sw_if_index)],
3827 table_id=t4.table_id)
3828 ip_220.add_vpp_config()
3830 l3o_220 = VppGbpSubnet(
3831 self, rd1, "10.220.0.0", 24,
3832 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3834 l3o_220.add_vpp_config()
3837 # A subnet reachable through the external EP2
3839 ip_221 = VppIpRoute(self, "10.221.0.0", 24,
3840 [VppRoutePath(eep2.ip4.address,
3841 eep2.epg.bvi.sw_if_index)],
3842 table_id=t4.table_id)
3843 ip_221.add_vpp_config()
3845 l3o_221 = VppGbpSubnet(
3846 self, rd1, "10.221.0.0", 24,
3847 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3849 l3o_221.add_vpp_config()
3852 # ping between hosts in remote subnets
3853 # dropped without a contract
3855 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3857 IP(src="10.220.0.1", dst="10.221.0.1") /
3858 ICMP(type='echo-request'))
3860 self.send_and_assert_no_replies(self.pg0, p * 1)
3863 # contract for the external nets to communicate
3865 acl = VppGbpAcl(self)
3866 rule4 = acl.create_rule(permit_deny=1, proto=17)
3867 rule6 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
3868 acl_index = acl.add_vpp_config([rule4, rule6])
3871 # A contract with the wrong scope is not matched
3873 c_44 = VppGbpContract(
3874 self, 44, 4220, 4221, acl_index,
3875 [VppGbpContractRule(
3876 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3879 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3881 [ETH_P_IP, ETH_P_IPV6])
3882 c_44.add_vpp_config()
3883 self.send_and_assert_no_replies(self.pg0, p * 1)
3885 c1 = VppGbpContract(
3886 self, 55, 4220, 4221, acl_index,
3887 [VppGbpContractRule(
3888 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3889 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3892 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3893 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3895 [ETH_P_IP, ETH_P_IPV6])
3899 # Contracts allowing ext-net 200 to talk with external EPs
3901 c2 = VppGbpContract(
3902 self, 55, 4220, 113, acl_index,
3903 [VppGbpContractRule(
3904 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3905 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3908 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3909 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3911 [ETH_P_IP, ETH_P_IPV6])
3913 c3 = VppGbpContract(
3914 self, 55, 113, 4220, acl_index,
3915 [VppGbpContractRule(
3916 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3917 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3920 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3921 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3923 [ETH_P_IP, ETH_P_IPV6])
3927 # ping between hosts in remote subnets
3929 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3931 IP(src="10.220.0.1", dst="10.221.0.1") /
3932 UDP(sport=1234, dport=1234) /
3935 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
3938 self.assertEqual(rx[Ether].src, str(self.router_mac))
3939 self.assertEqual(rx[Ether].dst, eep2.mac)
3940 self.assertEqual(rx[Dot1Q].vlan, 101)
3942 # we did not learn these external hosts
3943 self.assertFalse(find_gbp_endpoint(self, ip="10.220.0.1"))
3944 self.assertFalse(find_gbp_endpoint(self, ip="10.221.0.1"))
3947 # from remote external EP to local external EP
3949 p = (Ether(src=self.pg7.remote_mac,
3950 dst=self.pg7.local_mac) /
3951 IP(src=self.pg7.remote_ip4,
3952 dst=self.pg7.local_ip4) /
3953 UDP(sport=1234, dport=48879) /
3954 VXLAN(vni=444, gpid=113, flags=0x88) /
3955 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
3956 IP(src="10.0.0.101", dst="10.220.0.1") /
3957 UDP(sport=1234, dport=1234) /
3960 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
3963 # ping from an external host to the remote external EP
3965 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3967 IP(src="10.220.0.1", dst=rep.ip4.address) /
3968 UDP(sport=1234, dport=1234) /
3971 rxs = self.send_and_expect(self.pg0, p * 1, self.pg7)
3974 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3975 # self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3976 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3977 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
3978 self.assertEqual(rx[VXLAN].vni, 444)
3979 self.assertTrue(rx[VXLAN].flags.G)
3980 self.assertTrue(rx[VXLAN].flags.Instance)
3981 # the sclass of the ext-net the packet came from
3982 self.assertEqual(rx[VXLAN].gpid, 4220)
3983 # policy was applied to the original IP packet
3984 self.assertTrue(rx[VXLAN].gpflags.A)
3985 # since it's an external host the reciever should not learn it
3986 self.assertTrue(rx[VXLAN].gpflags.D)
3987 inner = rx[VXLAN].payload
3988 self.assertEqual(inner[IP].src, "10.220.0.1")
3989 self.assertEqual(inner[IP].dst, rep.ip4.address)
3992 # An external subnet reachable via the remote external EP
3996 # first the VXLAN-GBP tunnel over which it is reached
3998 vx_tun_r = VppVxlanGbpTunnel(
3999 self, self.pg7.local_ip4,
4000 self.pg7.remote_ip4, 445,
4001 mode=(VppEnum.vl_api_vxlan_gbp_api_tunnel_mode_t.
4002 VXLAN_GBP_API_TUNNEL_MODE_L3))
4003 vx_tun_r.add_vpp_config()
4004 VppIpInterfaceBind(self, vx_tun_r, t4).add_vpp_config()
4006 self.logger.info(self.vapi.cli("sh vxlan-gbp tunnel"))
4009 # then the special adj to resolve through on that tunnel
4011 n1 = VppNeighbor(self,
4012 vx_tun_r.sw_if_index,
4013 "00:0c:0c:0c:0c:0c",
4014 self.pg7.remote_ip4)
4018 # the route via the adj above
4020 ip_222 = VppIpRoute(self, "10.222.0.0", 24,
4021 [VppRoutePath(self.pg7.remote_ip4,
4022 vx_tun_r.sw_if_index)],
4023 table_id=t4.table_id)
4024 ip_222.add_vpp_config()
4026 l3o_222 = VppGbpSubnet(
4027 self, rd1, "10.222.0.0", 24,
4028 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
4030 l3o_222.add_vpp_config()
4033 # ping between hosts in local and remote external subnets
4034 # dropped without a contract
4036 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
4038 IP(src="10.220.0.1", dst="10.222.0.1") /
4039 UDP(sport=1234, dport=1234) /
4042 rxs = self.send_and_assert_no_replies(self.pg0, p * 1)
4045 # Add contracts ext-nets for 220 -> 222
4047 c4 = VppGbpContract(
4048 self, 55, 4220, 4222, acl_index,
4049 [VppGbpContractRule(
4050 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4051 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4054 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4055 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4057 [ETH_P_IP, ETH_P_IPV6])
4061 # ping from host in local to remote external subnets
4063 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
4065 IP(src="10.220.0.1", dst="10.222.0.1") /
4066 UDP(sport=1234, dport=1234) /
4069 rxs = self.send_and_expect(self.pg0, p * 3, self.pg7)
4072 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4073 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4074 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4075 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4076 self.assertEqual(rx[VXLAN].vni, 445)
4077 self.assertTrue(rx[VXLAN].flags.G)
4078 self.assertTrue(rx[VXLAN].flags.Instance)
4079 # the sclass of the ext-net the packet came from
4080 self.assertEqual(rx[VXLAN].gpid, 4220)
4081 # policy was applied to the original IP packet
4082 self.assertTrue(rx[VXLAN].gpflags.A)
4083 # since it's an external host the reciever should not learn it
4084 self.assertTrue(rx[VXLAN].gpflags.D)
4085 inner = rx[VXLAN].payload
4086 self.assertEqual(inner[Ether].dst, "00:0c:0c:0c:0c:0c")
4087 self.assertEqual(inner[IP].src, "10.220.0.1")
4088 self.assertEqual(inner[IP].dst, "10.222.0.1")
4091 # ping from host in remote to local external subnets
4092 # there's no contract for this, but the A bit is set.
4094 p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
4095 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
4096 UDP(sport=1234, dport=48879) /
4097 VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
4098 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
4099 IP(src="10.222.0.1", dst="10.220.0.1") /
4100 UDP(sport=1234, dport=1234) /
4103 rxs = self.send_and_expect(self.pg7, p * 3, self.pg0)
4104 self.assertFalse(find_gbp_endpoint(self, ip="10.222.0.1"))
4107 # ping from host in remote to remote external subnets
4108 # this is dropped by reflection check.
4110 p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
4111 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
4112 UDP(sport=1234, dport=48879) /
4113 VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
4114 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
4115 IP(src="10.222.0.1", dst="10.222.0.2") /
4116 UDP(sport=1234, dport=1234) /
4119 rxs = self.send_and_assert_no_replies(self.pg7, p * 3)
4124 self.pg7.unconfig_ip4()
4125 vlan_100.set_vtr(L2_VTR_OP.L2_DISABLED)
4128 if __name__ == '__main__':
4129 unittest.main(testRunner=VppTestRunner)