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
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
21 from vpp_l2 import VppBridgeDomain, VppBridgeDomainPort, \
22 VppBridgeDomainArpEntry, VppL2FibEntry, find_bridge_domain_port, VppL2Vtr
23 from vpp_sub_interface import L2_VTR_OP, VppDot1QSubint
24 from vpp_ip import VppIpAddress, VppIpPrefix
25 from vpp_papi import VppEnum, MACAddress
26 from vpp_vxlan_gbp_tunnel import find_vxlan_gbp_tunnel, INDEX_INVALID, \
28 from vpp_neighbor import VppNeighbor
31 def find_gbp_endpoint(test, sw_if_index=None, ip=None, mac=None):
33 vip = VppIpAddress(ip)
35 vmac = MACAddress(mac)
37 eps = test.vapi.gbp_endpoint_dump()
41 if ep.endpoint.sw_if_index != sw_if_index:
44 for eip in ep.endpoint.ips:
48 if vmac.packed == ep.endpoint.mac:
53 def find_gbp_vxlan(test, vni):
54 ts = test.vapi.gbp_vxlan_tunnel_dump()
56 if t.tunnel.vni == vni:
61 class VppGbpEndpoint(VppObject):
88 return [self.ip4, self.ip6]
92 return [self.fip4, self.fip6]
94 def __init__(self, test, itf, epg, recirc, ip4, fip4, ip6, fip6,
104 self._ip4 = VppIpAddress(ip4)
105 self._fip4 = VppIpAddress(fip4)
106 self._ip6 = VppIpAddress(ip6)
107 self._fip6 = VppIpAddress(fip6)
110 self.vmac = MACAddress(self.itf.remote_mac)
112 self.vmac = MACAddress("00:00:00:00:00:00")
115 self.tun_src = VppIpAddress(tun_src)
116 self.tun_dst = VppIpAddress(tun_dst)
118 def add_vpp_config(self):
119 res = self._test.vapi.gbp_endpoint_add(
120 self.itf.sw_if_index,
121 [self.ip4.encode(), self.ip6.encode()],
125 self.tun_src.encode(),
126 self.tun_dst.encode())
127 self.handle = res.handle
128 self._test.registry.register(self, self._test.logger)
130 def remove_vpp_config(self):
131 self._test.vapi.gbp_endpoint_del(self.handle)
134 return "gbp-endpoint:[%d==%d:%s:%d]" % (self.handle,
135 self.itf.sw_if_index,
139 def query_vpp_config(self):
140 return find_gbp_endpoint(self._test,
141 self.itf.sw_if_index,
145 class VppGbpRecirc(VppObject):
147 GBP Recirculation Interface
150 def __init__(self, test, epg, recirc, is_ext=False):
156 def add_vpp_config(self):
157 self._test.vapi.gbp_recirc_add_del(
159 self.recirc.sw_if_index,
162 self._test.registry.register(self, self._test.logger)
164 def remove_vpp_config(self):
165 self._test.vapi.gbp_recirc_add_del(
167 self.recirc.sw_if_index,
172 return "gbp-recirc:[%d]" % (self.recirc.sw_if_index)
174 def query_vpp_config(self):
175 rs = self._test.vapi.gbp_recirc_dump()
177 if r.recirc.sw_if_index == self.recirc.sw_if_index:
182 class VppGbpExtItf(VppObject):
184 GBP ExtItfulation Interface
187 def __init__(self, test, itf, bd, rd):
193 def add_vpp_config(self):
194 self._test.vapi.gbp_ext_itf_add_del(
196 self.itf.sw_if_index,
199 self._test.registry.register(self, self._test.logger)
201 def remove_vpp_config(self):
202 self._test.vapi.gbp_ext_itf_add_del(
204 self.itf.sw_if_index,
209 return "gbp-ext-itf:[%d]" % (self.itf.sw_if_index)
211 def query_vpp_config(self):
212 rs = self._test.vapi.gbp_ext_itf_dump()
214 if r.ext_itf.sw_if_index == self.itf.sw_if_index:
219 class VppGbpSubnet(VppObject):
223 def __init__(self, test, rd, address, address_len,
224 type, sw_if_index=None, sclass=None):
226 self.rd_id = rd.rd_id
227 self.prefix = VppIpPrefix(address, address_len)
229 self.sw_if_index = sw_if_index
232 def add_vpp_config(self):
233 self._test.vapi.gbp_subnet_add_del(
236 self.prefix.encode(),
238 sw_if_index=self.sw_if_index if self.sw_if_index else 0xffffffff,
239 sclass=self.sclass if self.sclass else 0xffff)
240 self._test.registry.register(self, self._test.logger)
242 def remove_vpp_config(self):
243 self._test.vapi.gbp_subnet_add_del(
246 self.prefix.encode(),
250 return "gbp-subnet:[%d-%s]" % (self.rd_id, self.prefix)
252 def query_vpp_config(self):
253 ss = self._test.vapi.gbp_subnet_dump()
255 if s.subnet.rd_id == self.rd_id and \
256 s.subnet.type == self.type and \
257 s.subnet.prefix == self.prefix:
262 class VppGbpEndpointRetention(object):
263 def __init__(self, remote_ep_timeout=0xffffffff):
264 self.remote_ep_timeout = remote_ep_timeout
267 return {'remote_ep_timeout': self.remote_ep_timeout}
270 class VppGbpEndpointGroup(VppObject):
275 def __init__(self, test, vnid, sclass, rd, bd, uplink,
276 bvi, bvi_ip4, bvi_ip6=None,
277 retention=VppGbpEndpointRetention()):
281 self.bvi_ip4 = VppIpAddress(bvi_ip4)
282 self.bvi_ip6 = VppIpAddress(bvi_ip6)
289 self.retention = retention
291 def add_vpp_config(self):
292 self._test.vapi.gbp_endpoint_group_add(
297 self.uplink.sw_if_index if self.uplink else INDEX_INVALID,
298 self.retention.encode())
299 self._test.registry.register(self, self._test.logger)
301 def remove_vpp_config(self):
302 self._test.vapi.gbp_endpoint_group_del(self.sclass)
305 return "gbp-endpoint-group:[%d]" % (self.vnid)
307 def query_vpp_config(self):
308 epgs = self._test.vapi.gbp_endpoint_group_dump()
310 if epg.epg.vnid == self.vnid:
315 class VppGbpBridgeDomain(VppObject):
320 def __init__(self, test, bd, bvi, uu_fwd=None,
321 bm_flood=None, learn=True, uu_drop=False, bm_drop=False):
325 self.bm_flood = bm_flood
328 e = VppEnum.vl_api_gbp_bridge_domain_flags_t
330 self.learn = e.GBP_BD_API_FLAG_NONE
332 self.learn = e.GBP_BD_API_FLAG_DO_NOT_LEARN
334 self.learn |= e.GBP_BD_API_FLAG_UU_FWD_DROP
336 self.learn |= e.GBP_BD_API_FLAG_MCAST_DROP
338 def add_vpp_config(self):
339 self._test.vapi.gbp_bridge_domain_add(
342 self.bvi.sw_if_index,
343 self.uu_fwd.sw_if_index if self.uu_fwd else INDEX_INVALID,
344 self.bm_flood.sw_if_index if self.bm_flood else INDEX_INVALID)
345 self._test.registry.register(self, self._test.logger)
347 def remove_vpp_config(self):
348 self._test.vapi.gbp_bridge_domain_del(self.bd.bd_id)
351 return "gbp-bridge-domain:[%d]" % (self.bd.bd_id)
353 def query_vpp_config(self):
354 bds = self._test.vapi.gbp_bridge_domain_dump()
356 if bd.bd.bd_id == self.bd.bd_id:
361 class VppGbpRouteDomain(VppObject):
366 def __init__(self, test, rd_id, t4, t6, ip4_uu=None, ip6_uu=None):
374 def add_vpp_config(self):
375 self._test.vapi.gbp_route_domain_add(
379 self.ip4_uu.sw_if_index if self.ip4_uu else INDEX_INVALID,
380 self.ip6_uu.sw_if_index if self.ip6_uu else INDEX_INVALID)
381 self._test.registry.register(self, self._test.logger)
383 def remove_vpp_config(self):
384 self._test.vapi.gbp_route_domain_del(self.rd_id)
387 return "gbp-route-domain:[%d]" % (self.rd_id)
389 def query_vpp_config(self):
390 rds = self._test.vapi.gbp_route_domain_dump()
392 if rd.rd.rd_id == self.rd_id:
397 class VppGbpContractNextHop():
398 def __init__(self, mac, bd, ip, rd):
405 return {'ip': self.ip.encode(),
406 'mac': self.mac.packed,
407 'bd_id': self.bd.bd.bd_id,
408 'rd_id': self.rd.rd_id}
411 class VppGbpContractRule():
412 def __init__(self, action, hash_mode, nhs=[]):
414 self.hash_mode = hash_mode
420 nhs.append(nh.encode())
423 return {'action': self.action,
425 'hash_mode': self.hash_mode,
426 'n_nhs': len(self.nhs),
430 class VppGbpContract(VppObject):
435 def __init__(self, test, sclass, dclass, acl_index,
436 rules, allowed_ethertypes):
438 self.acl_index = acl_index
442 self.allowed_ethertypes = allowed_ethertypes
443 while (len(self.allowed_ethertypes) < 16):
444 self.allowed_ethertypes.append(0)
446 def add_vpp_config(self):
449 rules.append(r.encode())
450 r = self._test.vapi.gbp_contract_add_del(
456 self.allowed_ethertypes)
457 self.stats_index = r.stats_index
458 self._test.registry.register(self, self._test.logger)
460 def remove_vpp_config(self):
461 self._test.vapi.gbp_contract_add_del(
467 self.allowed_ethertypes)
470 return "gbp-contract:[%d:%s:%d]" % (self.sclass,
474 def query_vpp_config(self):
475 cs = self._test.vapi.gbp_contract_dump()
477 if c.contract.sclass == self.sclass \
478 and c.contract.dclass == self.dclass:
482 def get_drop_stats(self):
483 c = self._test.statistics.get_counter("/net/gbp/contract/drop")
484 return c[0][self.stats_index]
486 def get_permit_stats(self):
487 c = self._test.statistics.get_counter("/net/gbp/contract/permit")
488 return c[0][self.stats_index]
491 class VppGbpVxlanTunnel(VppInterface):
496 def __init__(self, test, vni, bd_rd_id, mode, src):
497 super(VppGbpVxlanTunnel, self).__init__(test)
500 self.bd_rd_id = bd_rd_id
504 def add_vpp_config(self):
505 r = self._test.vapi.gbp_vxlan_tunnel_add(
510 self.set_sw_if_index(r.sw_if_index)
511 self._test.registry.register(self, self._test.logger)
513 def remove_vpp_config(self):
514 self._test.vapi.gbp_vxlan_tunnel_del(self.vni)
517 return "gbp-vxlan:%d" % (self.sw_if_index)
519 def query_vpp_config(self):
520 return find_gbp_vxlan(self._test, self.vni)
523 class VppGbpAcl(VppObject):
528 def __init__(self, test):
530 self.acl_index = 4294967295
532 def create_rule(self, is_ipv6=0, permit_deny=0, proto=-1,
533 s_prefix=0, s_ip=b'\x00\x00\x00\x00', sport_from=0,
534 sport_to=65535, d_prefix=0, d_ip=b'\x00\x00\x00\x00',
535 dport_from=0, dport_to=65535):
536 if proto == -1 or proto == 0:
539 elif proto == 1 or proto == 58:
542 rule = ({'is_permit': permit_deny, 'is_ipv6': is_ipv6, 'proto': proto,
543 'srcport_or_icmptype_first': sport_from,
544 'srcport_or_icmptype_last': sport_to,
545 'src_ip_prefix_len': s_prefix,
547 'dstport_or_icmpcode_first': dport_from,
548 'dstport_or_icmpcode_last': dport_to,
549 'dst_ip_prefix_len': d_prefix,
550 'dst_ip_addr': d_ip})
553 def add_vpp_config(self, rules):
555 reply = self._test.vapi.acl_add_replace(self.acl_index,
558 self.acl_index = reply.acl_index
559 return self.acl_index
561 def remove_vpp_config(self):
562 self._test.vapi.acl_del(self.acl_index)
565 return "gbp-acl:[%d]" % (self.acl_index)
567 def query_vpp_config(self):
568 cs = self._test.vapi.acl_dump()
570 if c.acl_index == self.acl_index:
575 class TestGBP(VppTestCase):
576 """ GBP Test Case """
580 super(TestGBP, cls).setUpClass()
583 def tearDownClass(cls):
584 super(TestGBP, cls).tearDownClass()
587 super(TestGBP, self).setUp()
589 self.create_pg_interfaces(range(9))
590 self.create_loopback_interfaces(8)
592 self.router_mac = MACAddress("00:11:22:33:44:55")
594 for i in self.pg_interfaces:
596 for i in self.lo_interfaces:
600 for i in self.pg_interfaces:
603 super(TestGBP, self).tearDown()
605 def send_and_expect_bridged(self, src, tx, dst):
606 rx = self.send_and_expect(src, tx, dst)
609 self.assertEqual(r[Ether].src, tx[0][Ether].src)
610 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
611 self.assertEqual(r[IP].src, tx[0][IP].src)
612 self.assertEqual(r[IP].dst, tx[0][IP].dst)
615 def send_and_expect_bridged6(self, src, tx, dst):
616 rx = self.send_and_expect(src, tx, dst)
619 self.assertEqual(r[Ether].src, tx[0][Ether].src)
620 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
621 self.assertEqual(r[IPv6].src, tx[0][IPv6].src)
622 self.assertEqual(r[IPv6].dst, tx[0][IPv6].dst)
625 def send_and_expect_routed(self, src, tx, dst, src_mac):
626 rx = self.send_and_expect(src, tx, dst)
629 self.assertEqual(r[Ether].src, src_mac)
630 self.assertEqual(r[Ether].dst, dst.remote_mac)
631 self.assertEqual(r[IP].src, tx[0][IP].src)
632 self.assertEqual(r[IP].dst, tx[0][IP].dst)
635 def send_and_expect_natted(self, src, tx, dst, src_ip):
636 rx = self.send_and_expect(src, tx, dst)
639 self.assertEqual(r[Ether].src, tx[0][Ether].src)
640 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
641 self.assertEqual(r[IP].src, src_ip)
642 self.assertEqual(r[IP].dst, tx[0][IP].dst)
645 def send_and_expect_natted6(self, src, tx, dst, src_ip):
646 rx = self.send_and_expect(src, tx, dst)
649 self.assertEqual(r[Ether].src, tx[0][Ether].src)
650 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
651 self.assertEqual(r[IPv6].src, src_ip)
652 self.assertEqual(r[IPv6].dst, tx[0][IPv6].dst)
655 def send_and_expect_unnatted(self, src, tx, dst, dst_ip):
656 rx = self.send_and_expect(src, tx, dst)
659 self.assertEqual(r[Ether].src, tx[0][Ether].src)
660 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
661 self.assertEqual(r[IP].dst, dst_ip)
662 self.assertEqual(r[IP].src, tx[0][IP].src)
665 def send_and_expect_unnatted6(self, src, tx, dst, dst_ip):
666 rx = self.send_and_expect(src, tx, dst)
669 self.assertEqual(r[Ether].src, tx[0][Ether].src)
670 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
671 self.assertEqual(r[IPv6].dst, dst_ip)
672 self.assertEqual(r[IPv6].src, tx[0][IPv6].src)
675 def send_and_expect_double_natted(self, src, tx, dst, src_ip, dst_ip):
676 rx = self.send_and_expect(src, tx, dst)
679 self.assertEqual(r[Ether].src, str(self.router_mac))
680 self.assertEqual(r[Ether].dst, dst.remote_mac)
681 self.assertEqual(r[IP].dst, dst_ip)
682 self.assertEqual(r[IP].src, src_ip)
685 def send_and_expect_double_natted6(self, src, tx, dst, src_ip, dst_ip):
686 rx = self.send_and_expect(src, tx, dst)
689 self.assertEqual(r[Ether].src, str(self.router_mac))
690 self.assertEqual(r[Ether].dst, dst.remote_mac)
691 self.assertEqual(r[IPv6].dst, dst_ip)
692 self.assertEqual(r[IPv6].src, src_ip)
696 """ Group Based Policy """
698 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
703 bd1 = VppBridgeDomain(self, 1)
704 bd2 = VppBridgeDomain(self, 2)
705 bd20 = VppBridgeDomain(self, 20)
709 bd20.add_vpp_config()
711 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0)
712 gbd2 = VppGbpBridgeDomain(self, bd2, self.loop1)
713 gbd20 = VppGbpBridgeDomain(self, bd20, self.loop2)
715 gbd1.add_vpp_config()
716 gbd2.add_vpp_config()
717 gbd20.add_vpp_config()
722 gt4 = VppIpTable(self, 0)
724 gt6 = VppIpTable(self, 0, is_ip6=True)
726 nt4 = VppIpTable(self, 20)
728 nt6 = VppIpTable(self, 20, is_ip6=True)
731 rd0 = VppGbpRouteDomain(self, 0, gt4, gt6, None, None)
732 rd20 = VppGbpRouteDomain(self, 20, nt4, nt6, None, None)
735 rd20.add_vpp_config()
738 # 3 EPGs, 2 of which share a BD.
739 # 2 NAT EPGs, one for floating-IP subnets, the other for internet
741 epgs = [VppGbpEndpointGroup(self, 220, 1220, rd0, gbd1,
742 self.pg4, self.loop0,
743 "10.0.0.128", "2001:10::128"),
744 VppGbpEndpointGroup(self, 221, 1221, rd0, gbd1,
745 self.pg5, self.loop0,
746 "10.0.1.128", "2001:10:1::128"),
747 VppGbpEndpointGroup(self, 222, 1222, rd0, gbd2,
748 self.pg6, self.loop1,
749 "10.0.2.128", "2001:10:2::128"),
750 VppGbpEndpointGroup(self, 333, 1333, rd20, gbd20,
751 self.pg7, self.loop2,
752 "11.0.0.128", "3001::128"),
753 VppGbpEndpointGroup(self, 444, 1444, rd20, gbd20,
754 self.pg8, self.loop2,
755 "11.0.0.129", "3001::129")]
756 recircs = [VppGbpRecirc(self, epgs[0], self.loop3),
757 VppGbpRecirc(self, epgs[1], self.loop4),
758 VppGbpRecirc(self, epgs[2], self.loop5),
759 VppGbpRecirc(self, epgs[3], self.loop6, is_ext=True),
760 VppGbpRecirc(self, epgs[4], self.loop7, is_ext=True)]
763 recirc_nat = recircs[3]
766 # 4 end-points, 2 in the same subnet, 3 in the same BD
768 eps = [VppGbpEndpoint(self, self.pg0,
770 "10.0.0.1", "11.0.0.1",
771 "2001:10::1", "3001::1"),
772 VppGbpEndpoint(self, self.pg1,
774 "10.0.0.2", "11.0.0.2",
775 "2001:10::2", "3001::2"),
776 VppGbpEndpoint(self, self.pg2,
778 "10.0.1.1", "11.0.0.3",
779 "2001:10:1::1", "3001::3"),
780 VppGbpEndpoint(self, self.pg3,
782 "10.0.2.1", "11.0.0.4",
783 "2001:10:2::1", "3001::4")]
786 # Config related to each of the EPGs
789 # IP config on the BVI interfaces
790 if epg != epgs[1] and epg != epgs[4]:
791 VppIpInterfaceBind(self, epg.bvi, epg.rd.t4).add_vpp_config()
792 VppIpInterfaceBind(self, epg.bvi, epg.rd.t6).add_vpp_config()
793 self.vapi.sw_interface_set_mac_address(
795 self.router_mac.packed)
797 # The BVIs are NAT inside interfaces
798 self.vapi.nat44_interface_add_del_feature(epg.bvi.sw_if_index,
801 self.vapi.nat66_add_del_interface(epg.bvi.sw_if_index,
805 if_ip4 = VppIpInterfaceAddress(self, epg.bvi, epg.bvi_ip4, 32)
806 if_ip6 = VppIpInterfaceAddress(self, epg.bvi, epg.bvi_ip6, 128)
807 if_ip4.add_vpp_config()
808 if_ip6.add_vpp_config()
810 # EPG uplink interfaces in the RD
811 VppIpInterfaceBind(self, epg.uplink, epg.rd.t4).add_vpp_config()
812 VppIpInterfaceBind(self, epg.uplink, epg.rd.t6).add_vpp_config()
814 # add the BD ARP termination entry for BVI IP
815 epg.bd_arp_ip4 = VppBridgeDomainArpEntry(self, epg.bd.bd,
816 str(self.router_mac),
818 epg.bd_arp_ip6 = VppBridgeDomainArpEntry(self, epg.bd.bd,
819 str(self.router_mac),
821 epg.bd_arp_ip4.add_vpp_config()
822 epg.bd_arp_ip6.add_vpp_config()
827 for recirc in recircs:
828 # EPG's ingress recirculation interface maps to its RD
829 VppIpInterfaceBind(self, recirc.recirc,
830 recirc.epg.rd.t4).add_vpp_config()
831 VppIpInterfaceBind(self, recirc.recirc,
832 recirc.epg.rd.t6).add_vpp_config()
834 self.vapi.nat44_interface_add_del_feature(
835 recirc.recirc.sw_if_index,
838 self.vapi.nat66_add_del_interface(
839 recirc.recirc.sw_if_index,
843 recirc.add_vpp_config()
845 for recirc in recircs:
846 self.assertTrue(find_bridge_domain_port(self,
847 recirc.epg.bd.bd.bd_id,
848 recirc.recirc.sw_if_index))
851 self.pg_enable_capture(self.pg_interfaces)
854 # routes to the endpoints. We need these since there are no
855 # adj-fibs due to the fact the the BVI address has /32 and
856 # the subnet is not attached.
858 for (ip, fip) in zip(ep.ips, ep.fips):
859 # Add static mappings for each EP from the 10/8 to 11/8 network
861 self.vapi.nat44_add_del_static_mapping(ip.bytes,
866 self.vapi.nat66_add_del_static_mapping(ip.bytes,
873 self.logger.info(self.vapi.cli("sh gbp endpoint"))
875 # ... results in a Gratuitous ARP/ND on the EPG's uplink
876 rx = ep.epg.uplink.get_capture(len(ep.ips), timeout=0.2)
878 for ii, ip in enumerate(ep.ips):
882 self.assertTrue(p.haslayer(ICMPv6ND_NA))
883 self.assertEqual(p[ICMPv6ND_NA].tgt, ip.address)
885 self.assertTrue(p.haslayer(ARP))
886 self.assertEqual(p[ARP].psrc, ip.address)
887 self.assertEqual(p[ARP].pdst, ip.address)
889 # add the BD ARP termination entry for floating IP
891 ba = VppBridgeDomainArpEntry(self, epg_nat.bd.bd, ep.mac, fip)
894 # floating IPs route via EPG recirc
895 r = VppIpRoute(self, fip.address, fip.length,
896 [VppRoutePath(fip.address,
897 ep.recirc.recirc.sw_if_index,
899 proto=fip.dpo_proto)],
904 # L2 FIB entries in the NAT EPG BD to bridge the packets from
905 # the outside direct to the internal EPG
906 lf = VppL2FibEntry(self, epg_nat.bd.bd, ep.mac,
907 ep.recirc.recirc, bvi_mac=0)
911 # ARP packets for unknown IP are sent to the EPG uplink
913 pkt_arp = (Ether(dst="ff:ff:ff:ff:ff:ff",
914 src=self.pg0.remote_mac) /
916 hwdst="ff:ff:ff:ff:ff:ff",
917 hwsrc=self.pg0.remote_mac,
921 self.vapi.cli("clear trace")
922 self.pg0.add_stream(pkt_arp)
924 self.pg_enable_capture(self.pg_interfaces)
927 rxd = epgs[0].uplink.get_capture(1)
930 # ARP/ND packets get a response
932 pkt_arp = (Ether(dst="ff:ff:ff:ff:ff:ff",
933 src=self.pg0.remote_mac) /
935 hwdst="ff:ff:ff:ff:ff:ff",
936 hwsrc=self.pg0.remote_mac,
937 pdst=epgs[0].bvi_ip4.address,
938 psrc=eps[0].ip4.address))
940 self.send_and_expect(self.pg0, [pkt_arp], self.pg0)
942 nsma = in6_getnsma(inet_pton(AF_INET6, eps[0].ip6.address))
943 d = inet_ntop(AF_INET6, nsma)
944 pkt_nd = (Ether(dst=in6_getnsmac(nsma),
945 src=self.pg0.remote_mac) /
946 IPv6(dst=d, src=eps[0].ip6.address) /
947 ICMPv6ND_NS(tgt=epgs[0].bvi_ip6.address) /
948 ICMPv6NDOptSrcLLAddr(lladdr=self.pg0.remote_mac))
949 self.send_and_expect(self.pg0, [pkt_nd], self.pg0)
952 # broadcast packets are flooded
954 pkt_bcast = (Ether(dst="ff:ff:ff:ff:ff:ff",
955 src=self.pg0.remote_mac) /
956 IP(src=eps[0].ip4.address, dst="232.1.1.1") /
957 UDP(sport=1234, dport=1234) /
960 self.vapi.cli("clear trace")
961 self.pg0.add_stream(pkt_bcast)
963 self.pg_enable_capture(self.pg_interfaces)
966 rxd = eps[1].itf.get_capture(1)
967 self.assertEqual(rxd[0][Ether].dst, pkt_bcast[Ether].dst)
968 rxd = epgs[0].uplink.get_capture(1)
969 self.assertEqual(rxd[0][Ether].dst, pkt_bcast[Ether].dst)
972 # packets to non-local L3 destinations dropped
974 pkt_intra_epg_220_ip4 = (Ether(src=self.pg0.remote_mac,
975 dst=str(self.router_mac)) /
976 IP(src=eps[0].ip4.address,
978 UDP(sport=1234, dport=1234) /
980 pkt_inter_epg_222_ip4 = (Ether(src=self.pg0.remote_mac,
981 dst=str(self.router_mac)) /
982 IP(src=eps[0].ip4.address,
984 UDP(sport=1234, dport=1234) /
987 self.send_and_assert_no_replies(self.pg0, pkt_intra_epg_220_ip4 * 65)
989 pkt_inter_epg_222_ip6 = (Ether(src=self.pg0.remote_mac,
990 dst=str(self.router_mac)) /
991 IPv6(src=eps[0].ip6.address,
993 UDP(sport=1234, dport=1234) /
995 self.send_and_assert_no_replies(self.pg0, pkt_inter_epg_222_ip6 * 65)
998 # Add the subnet routes
1001 self, rd0, "10.0.0.0", 24,
1002 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1004 self, rd0, "10.0.1.0", 24,
1005 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1007 self, rd0, "10.0.2.0", 24,
1008 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1010 self, rd0, "2001:10::1", 64,
1011 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1013 self, rd0, "2001:10:1::1", 64,
1014 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1016 self, rd0, "2001:10:2::1", 64,
1017 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1018 s41.add_vpp_config()
1019 s42.add_vpp_config()
1020 s43.add_vpp_config()
1021 s61.add_vpp_config()
1022 s62.add_vpp_config()
1023 s63.add_vpp_config()
1025 self.send_and_expect_bridged(eps[0].itf,
1026 pkt_intra_epg_220_ip4 * 65,
1028 self.send_and_expect_bridged(eps[0].itf,
1029 pkt_inter_epg_222_ip4 * 65,
1031 self.send_and_expect_bridged6(eps[0].itf,
1032 pkt_inter_epg_222_ip6 * 65,
1035 self.logger.info(self.vapi.cli("sh ip fib 11.0.0.2"))
1036 self.logger.info(self.vapi.cli("sh gbp endpoint-group"))
1037 self.logger.info(self.vapi.cli("sh gbp endpoint"))
1038 self.logger.info(self.vapi.cli("sh gbp recirc"))
1039 self.logger.info(self.vapi.cli("sh int"))
1040 self.logger.info(self.vapi.cli("sh int addr"))
1041 self.logger.info(self.vapi.cli("sh int feat loop6"))
1042 self.logger.info(self.vapi.cli("sh vlib graph ip4-gbp-src-classify"))
1043 self.logger.info(self.vapi.cli("sh int feat loop3"))
1044 self.logger.info(self.vapi.cli("sh int feat pg0"))
1047 # Packet destined to unknown unicast is sent on the epg uplink ...
1049 pkt_intra_epg_220_to_uplink = (Ether(src=self.pg0.remote_mac,
1050 dst="00:00:00:33:44:55") /
1051 IP(src=eps[0].ip4.address,
1053 UDP(sport=1234, dport=1234) /
1056 self.send_and_expect_bridged(eps[0].itf,
1057 pkt_intra_epg_220_to_uplink * 65,
1059 # ... and nowhere else
1060 self.pg1.get_capture(0, timeout=0.1)
1061 self.pg1.assert_nothing_captured(remark="Flood onto other VMS")
1063 pkt_intra_epg_221_to_uplink = (Ether(src=self.pg2.remote_mac,
1064 dst="00:00:00:33:44:66") /
1065 IP(src=eps[0].ip4.address,
1067 UDP(sport=1234, dport=1234) /
1070 self.send_and_expect_bridged(eps[2].itf,
1071 pkt_intra_epg_221_to_uplink * 65,
1075 # Packets from the uplink are forwarded in the absence of a contract
1077 pkt_intra_epg_220_from_uplink = (Ether(src="00:00:00:33:44:55",
1078 dst=self.pg0.remote_mac) /
1079 IP(src=eps[0].ip4.address,
1081 UDP(sport=1234, dport=1234) /
1084 self.send_and_expect_bridged(self.pg4,
1085 pkt_intra_epg_220_from_uplink * 65,
1089 # in the absence of policy, endpoints in the same EPG
1092 pkt_intra_epg = (Ether(src=self.pg0.remote_mac,
1093 dst=self.pg1.remote_mac) /
1094 IP(src=eps[0].ip4.address,
1095 dst=eps[1].ip4.address) /
1096 UDP(sport=1234, dport=1234) /
1099 self.send_and_expect_bridged(self.pg0, pkt_intra_epg * 65, self.pg1)
1102 # in the absence of policy, endpoints in the different EPG
1103 # cannot communicate
1105 pkt_inter_epg_220_to_221 = (Ether(src=self.pg0.remote_mac,
1106 dst=self.pg2.remote_mac) /
1107 IP(src=eps[0].ip4.address,
1108 dst=eps[2].ip4.address) /
1109 UDP(sport=1234, dport=1234) /
1111 pkt_inter_epg_221_to_220 = (Ether(src=self.pg2.remote_mac,
1112 dst=self.pg0.remote_mac) /
1113 IP(src=eps[2].ip4.address,
1114 dst=eps[0].ip4.address) /
1115 UDP(sport=1234, dport=1234) /
1117 pkt_inter_epg_220_to_222 = (Ether(src=self.pg0.remote_mac,
1118 dst=str(self.router_mac)) /
1119 IP(src=eps[0].ip4.address,
1120 dst=eps[3].ip4.address) /
1121 UDP(sport=1234, dport=1234) /
1124 self.send_and_assert_no_replies(eps[0].itf,
1125 pkt_inter_epg_220_to_221 * 65)
1126 self.send_and_assert_no_replies(eps[0].itf,
1127 pkt_inter_epg_220_to_222 * 65)
1130 # A uni-directional contract from EPG 220 -> 221
1132 acl = VppGbpAcl(self)
1133 rule = acl.create_rule(permit_deny=1, proto=17)
1134 rule2 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
1135 acl_index = acl.add_vpp_config([rule, rule2])
1136 c1 = VppGbpContract(
1137 self, epgs[0].sclass, epgs[1].sclass, acl_index,
1138 [VppGbpContractRule(
1139 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1142 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1144 [ETH_P_IP, ETH_P_IPV6])
1147 self.send_and_expect_bridged(eps[0].itf,
1148 pkt_inter_epg_220_to_221 * 65,
1150 self.send_and_assert_no_replies(eps[0].itf,
1151 pkt_inter_epg_220_to_222 * 65)
1154 # contract for the return direction
1156 c2 = VppGbpContract(
1157 self, epgs[1].sclass, epgs[0].sclass, acl_index,
1158 [VppGbpContractRule(
1159 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1162 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1164 [ETH_P_IP, ETH_P_IPV6])
1167 self.send_and_expect_bridged(eps[0].itf,
1168 pkt_inter_epg_220_to_221 * 65,
1170 self.send_and_expect_bridged(eps[2].itf,
1171 pkt_inter_epg_221_to_220 * 65,
1174 ds = c2.get_drop_stats()
1175 self.assertEqual(ds['packets'], 0)
1176 ps = c2.get_permit_stats()
1177 self.assertEqual(ps['packets'], 65)
1180 # the contract does not allow non-IP
1182 pkt_non_ip_inter_epg_220_to_221 = (Ether(src=self.pg0.remote_mac,
1183 dst=self.pg2.remote_mac) /
1185 self.send_and_assert_no_replies(eps[0].itf,
1186 pkt_non_ip_inter_epg_220_to_221 * 17)
1189 # check that inter group is still disabled for the groups
1190 # not in the contract.
1192 self.send_and_assert_no_replies(eps[0].itf,
1193 pkt_inter_epg_220_to_222 * 65)
1196 # A uni-directional contract from EPG 220 -> 222 'L3 routed'
1198 c3 = VppGbpContract(
1199 self, epgs[0].sclass, epgs[2].sclass, acl_index,
1200 [VppGbpContractRule(
1201 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1204 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1206 [ETH_P_IP, ETH_P_IPV6])
1209 self.logger.info(self.vapi.cli("sh gbp contract"))
1211 self.send_and_expect_routed(eps[0].itf,
1212 pkt_inter_epg_220_to_222 * 65,
1214 str(self.router_mac))
1217 # remove both contracts, traffic stops in both directions
1219 c2.remove_vpp_config()
1220 c1.remove_vpp_config()
1221 c3.remove_vpp_config()
1222 acl.remove_vpp_config()
1224 self.send_and_assert_no_replies(eps[2].itf,
1225 pkt_inter_epg_221_to_220 * 65)
1226 self.send_and_assert_no_replies(eps[0].itf,
1227 pkt_inter_epg_220_to_221 * 65)
1228 self.send_and_expect_bridged(eps[0].itf,
1233 # EPs to the outside world
1236 # in the EP's RD an external subnet via the NAT EPG's recirc
1238 self, rd0, "0.0.0.0", 0,
1239 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1240 sw_if_index=recirc_nat.recirc.sw_if_index,
1241 sclass=epg_nat.sclass)
1243 self, rd0, "11.0.0.0", 8,
1244 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1245 sw_if_index=recirc_nat.recirc.sw_if_index,
1246 sclass=epg_nat.sclass)
1247 se16 = VppGbpSubnet(
1249 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1250 sw_if_index=recirc_nat.recirc.sw_if_index,
1251 sclass=epg_nat.sclass)
1252 # in the NAT RD an external subnet via the NAT EPG's uplink
1254 self, rd20, "0.0.0.0", 0,
1255 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1256 sw_if_index=epg_nat.uplink.sw_if_index,
1257 sclass=epg_nat.sclass)
1258 se36 = VppGbpSubnet(
1259 self, rd20, "::", 0,
1260 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1261 sw_if_index=epg_nat.uplink.sw_if_index,
1262 sclass=epg_nat.sclass)
1264 self, rd20, "11.0.0.0", 8,
1265 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1266 sw_if_index=epg_nat.uplink.sw_if_index,
1267 sclass=epg_nat.sclass)
1268 se1.add_vpp_config()
1269 se2.add_vpp_config()
1270 se16.add_vpp_config()
1271 se3.add_vpp_config()
1272 se36.add_vpp_config()
1273 se4.add_vpp_config()
1275 self.logger.info(self.vapi.cli("sh ip fib 0.0.0.0/0"))
1276 self.logger.info(self.vapi.cli("sh ip fib 11.0.0.1"))
1277 self.logger.info(self.vapi.cli("sh ip6 fib ::/0"))
1278 self.logger.info(self.vapi.cli("sh ip6 fib %s" %
1282 # From an EP to an outside address: IN2OUT
1284 pkt_inter_epg_220_to_global = (Ether(src=self.pg0.remote_mac,
1285 dst=str(self.router_mac)) /
1286 IP(src=eps[0].ip4.address,
1288 UDP(sport=1234, dport=1234) /
1292 self.send_and_assert_no_replies(eps[0].itf,
1293 pkt_inter_epg_220_to_global * 65)
1295 acl2 = VppGbpAcl(self)
1296 rule = acl2.create_rule(permit_deny=1, proto=17, sport_from=1234,
1297 sport_to=1234, dport_from=1234, dport_to=1234)
1298 rule2 = acl2.create_rule(is_ipv6=1, permit_deny=1, proto=17,
1299 sport_from=1234, sport_to=1234,
1300 dport_from=1234, dport_to=1234)
1302 acl_index2 = acl2.add_vpp_config([rule, rule2])
1303 c4 = VppGbpContract(
1304 self, epgs[0].sclass, epgs[3].sclass, acl_index2,
1305 [VppGbpContractRule(
1306 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1309 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1311 [ETH_P_IP, ETH_P_IPV6])
1314 self.send_and_expect_natted(eps[0].itf,
1315 pkt_inter_epg_220_to_global * 65,
1317 eps[0].fip4.address)
1319 pkt_inter_epg_220_to_global = (Ether(src=self.pg0.remote_mac,
1320 dst=str(self.router_mac)) /
1321 IPv6(src=eps[0].ip6.address,
1323 UDP(sport=1234, dport=1234) /
1326 self.send_and_expect_natted6(self.pg0,
1327 pkt_inter_epg_220_to_global * 65,
1329 eps[0].fip6.address)
1332 # From a global address to an EP: OUT2IN
1334 pkt_inter_epg_220_from_global = (Ether(src=str(self.router_mac),
1335 dst=self.pg0.remote_mac) /
1336 IP(dst=eps[0].fip4.address,
1338 UDP(sport=1234, dport=1234) /
1341 self.send_and_assert_no_replies(self.pg7,
1342 pkt_inter_epg_220_from_global * 65)
1344 c5 = VppGbpContract(
1345 self, epgs[3].sclass, epgs[0].sclass, acl_index2,
1346 [VppGbpContractRule(
1347 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1350 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1352 [ETH_P_IP, ETH_P_IPV6])
1355 self.send_and_expect_unnatted(self.pg7,
1356 pkt_inter_epg_220_from_global * 65,
1360 pkt_inter_epg_220_from_global = (Ether(src=str(self.router_mac),
1361 dst=self.pg0.remote_mac) /
1362 IPv6(dst=eps[0].fip6.address,
1364 UDP(sport=1234, dport=1234) /
1367 self.send_and_expect_unnatted6(self.pg7,
1368 pkt_inter_epg_220_from_global * 65,
1373 # From a local VM to another local VM using resp. public addresses:
1376 pkt_intra_epg_220_global = (Ether(src=self.pg0.remote_mac,
1377 dst=str(self.router_mac)) /
1378 IP(src=eps[0].ip4.address,
1379 dst=eps[1].fip4.address) /
1380 UDP(sport=1234, dport=1234) /
1383 self.send_and_expect_double_natted(eps[0].itf,
1384 pkt_intra_epg_220_global * 65,
1386 eps[0].fip4.address,
1389 pkt_intra_epg_220_global = (Ether(src=self.pg0.remote_mac,
1390 dst=str(self.router_mac)) /
1391 IPv6(src=eps[0].ip6.address,
1392 dst=eps[1].fip6.address) /
1393 UDP(sport=1234, dport=1234) /
1396 self.send_and_expect_double_natted6(eps[0].itf,
1397 pkt_intra_epg_220_global * 65,
1399 eps[0].fip6.address,
1406 # del static mappings for each EP from the 10/8 to 11/8 network
1407 self.vapi.nat44_add_del_static_mapping(ep.ip4.bytes,
1412 self.vapi.nat66_add_del_static_mapping(ep.ip6.bytes,
1418 # IP config on the BVI interfaces
1419 if epg != epgs[0] and epg != epgs[3]:
1420 self.vapi.nat44_interface_add_del_feature(epg.bvi.sw_if_index,
1423 self.vapi.nat66_add_del_interface(epg.bvi.sw_if_index,
1427 for recirc in recircs:
1428 self.vapi.nat44_interface_add_del_feature(
1429 recirc.recirc.sw_if_index,
1432 self.vapi.nat66_add_del_interface(
1433 recirc.recirc.sw_if_index,
1437 def wait_for_ep_timeout(self, sw_if_index=None, ip=None, mac=None,
1438 n_tries=100, s_time=1):
1440 if not find_gbp_endpoint(self, sw_if_index, ip, mac):
1442 n_tries = n_tries - 1
1444 self.assertFalse(find_gbp_endpoint(self, sw_if_index, ip, mac))
1447 def test_gbp_learn_l2(self):
1448 """ GBP L2 Endpoint Learning """
1450 self.vapi.cli("clear errors")
1452 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
1453 learnt = [{'mac': '00:00:11:11:11:01',
1455 'ip6': '2001:10::2'},
1456 {'mac': '00:00:11:11:11:02',
1458 'ip6': '2001:10::3'}]
1463 gt4 = VppIpTable(self, 1)
1464 gt4.add_vpp_config()
1465 gt6 = VppIpTable(self, 1, is_ip6=True)
1466 gt6.add_vpp_config()
1468 rd1 = VppGbpRouteDomain(self, 1, gt4, gt6)
1469 rd1.add_vpp_config()
1472 # Pg2 hosts the vxlan tunnel, hosts on pg2 to act as TEPs
1473 # Pg3 hosts the IP4 UU-flood VXLAN tunnel
1474 # Pg4 hosts the IP6 UU-flood VXLAN tunnel
1476 self.pg2.config_ip4()
1477 self.pg2.resolve_arp()
1478 self.pg2.generate_remote_hosts(4)
1479 self.pg2.configure_ipv4_neighbors()
1480 self.pg3.config_ip4()
1481 self.pg3.resolve_arp()
1482 self.pg4.config_ip4()
1483 self.pg4.resolve_arp()
1486 # Add a mcast destination VXLAN-GBP tunnel for B&M traffic
1488 tun_bm = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
1491 tun_bm.add_vpp_config()
1494 # a GBP bridge domain with a BVI and a UU-flood interface
1496 bd1 = VppBridgeDomain(self, 1)
1497 bd1.add_vpp_config()
1498 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0, self.pg3, tun_bm)
1499 gbd1.add_vpp_config()
1501 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1502 self.logger.info(self.vapi.cli("sh gbp bridge"))
1504 # ... and has a /32 applied
1505 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
1506 ip_addr.add_vpp_config()
1509 # The Endpoint-group in which we are learning endpoints
1511 epg_220 = VppGbpEndpointGroup(self, 220, 112, rd1, gbd1,
1515 VppGbpEndpointRetention(2))
1516 epg_220.add_vpp_config()
1517 epg_330 = VppGbpEndpointGroup(self, 330, 113, rd1, gbd1,
1521 VppGbpEndpointRetention(2))
1522 epg_330.add_vpp_config()
1525 # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
1528 vx_tun_l2_1 = VppGbpVxlanTunnel(
1529 self, 99, bd1.bd_id,
1530 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L2,
1532 vx_tun_l2_1.add_vpp_config()
1535 # A static endpoint that the learnt endpoints are trying to
1538 ep = VppGbpEndpoint(self, self.pg0,
1540 "10.0.0.127", "11.0.0.127",
1541 "2001:10::1", "3001::1")
1544 self.assertTrue(find_route(self, ep.ip4.address, 32, table_id=1))
1546 # a packet with an sclass from an unknown EPG
1547 p = (Ether(src=self.pg2.remote_mac,
1548 dst=self.pg2.local_mac) /
1549 IP(src=self.pg2.remote_hosts[0].ip4,
1550 dst=self.pg2.local_ip4) /
1551 UDP(sport=1234, dport=48879) /
1552 VXLAN(vni=99, gpid=88, flags=0x88) /
1553 Ether(src=learnt[0]["mac"], dst=ep.mac) /
1554 IP(src=learnt[0]["ip"], dst=ep.ip4.address) /
1555 UDP(sport=1234, dport=1234) /
1558 self.send_and_assert_no_replies(self.pg2, p)
1560 self.logger.info(self.vapi.cli("sh error"))
1561 # self.assert_packet_counter_equal(
1562 # '/err/gbp-policy-port/drop-no-contract', 1)
1565 # we should not have learnt a new tunnel endpoint, since
1566 # the EPG was not learnt.
1568 self.assertEqual(INDEX_INVALID,
1569 find_vxlan_gbp_tunnel(self,
1571 self.pg2.remote_hosts[0].ip4,
1574 # epg is not learnt, because the EPG is unknown
1575 self.assertEqual(len(self.vapi.gbp_endpoint_dump()), 1)
1578 # Learn new EPs from IP packets
1580 for ii, l in enumerate(learnt):
1581 # a packet with an sclass from a known EPG
1582 # arriving on an unknown TEP
1583 p = (Ether(src=self.pg2.remote_mac,
1584 dst=self.pg2.local_mac) /
1585 IP(src=self.pg2.remote_hosts[1].ip4,
1586 dst=self.pg2.local_ip4) /
1587 UDP(sport=1234, dport=48879) /
1588 VXLAN(vni=99, gpid=112, flags=0x88) /
1589 Ether(src=l['mac'], dst=ep.mac) /
1590 IP(src=l['ip'], dst=ep.ip4.address) /
1591 UDP(sport=1234, dport=1234) /
1594 rx = self.send_and_expect(self.pg2, [p], self.pg0)
1597 tep1_sw_if_index = find_vxlan_gbp_tunnel(
1600 self.pg2.remote_hosts[1].ip4,
1602 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
1605 # the EP is learnt via the learnt TEP
1606 # both from its MAC and its IP
1608 self.assertTrue(find_gbp_endpoint(self,
1609 vx_tun_l2_1.sw_if_index,
1611 self.assertTrue(find_gbp_endpoint(self,
1612 vx_tun_l2_1.sw_if_index,
1615 # self.assert_packet_counter_equal(
1616 # '/err/gbp-policy-port/allow-intra-sclass', 2)
1618 self.logger.info(self.vapi.cli("show gbp endpoint"))
1619 self.logger.info(self.vapi.cli("show gbp vxlan"))
1620 self.logger.info(self.vapi.cli("show ip mfib"))
1623 # If we sleep for the threshold time, the learnt endpoints should
1627 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1631 # Learn new EPs from GARP packets received on the BD's mcast tunnel
1633 for ii, l in enumerate(learnt):
1634 # a packet with an sclass from a known EPG
1635 # arriving on an unknown TEP
1636 p = (Ether(src=self.pg2.remote_mac,
1637 dst=self.pg2.local_mac) /
1638 IP(src=self.pg2.remote_hosts[1].ip4,
1640 UDP(sport=1234, dport=48879) /
1641 VXLAN(vni=88, gpid=112, flags=0x88) /
1642 Ether(src=l['mac'], dst="ff:ff:ff:ff:ff:ff") /
1644 psrc=l['ip'], pdst=l['ip'],
1645 hwsrc=l['mac'], hwdst="ff:ff:ff:ff:ff:ff"))
1647 rx = self.send_and_expect(self.pg4, [p], self.pg0)
1650 tep1_sw_if_index = find_vxlan_gbp_tunnel(
1653 self.pg2.remote_hosts[1].ip4,
1655 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
1658 # the EP is learnt via the learnt TEP
1659 # both from its MAC and its IP
1661 self.assertTrue(find_gbp_endpoint(self,
1662 vx_tun_l2_1.sw_if_index,
1664 self.assertTrue(find_gbp_endpoint(self,
1665 vx_tun_l2_1.sw_if_index,
1669 # wait for the learnt endpoints to age out
1672 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1676 # Learn new EPs from L2 packets
1678 for ii, l in enumerate(learnt):
1679 # a packet with an sclass from a known EPG
1680 # arriving on an unknown TEP
1681 p = (Ether(src=self.pg2.remote_mac,
1682 dst=self.pg2.local_mac) /
1683 IP(src=self.pg2.remote_hosts[1].ip4,
1684 dst=self.pg2.local_ip4) /
1685 UDP(sport=1234, dport=48879) /
1686 VXLAN(vni=99, gpid=112, flags=0x88) /
1687 Ether(src=l['mac'], dst=ep.mac) /
1690 rx = self.send_and_expect(self.pg2, [p], self.pg0)
1693 tep1_sw_if_index = find_vxlan_gbp_tunnel(
1696 self.pg2.remote_hosts[1].ip4,
1698 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
1701 # the EP is learnt via the learnt TEP
1702 # both from its MAC and its IP
1704 self.assertTrue(find_gbp_endpoint(self,
1705 vx_tun_l2_1.sw_if_index,
1708 self.logger.info(self.vapi.cli("show gbp endpoint"))
1709 self.logger.info(self.vapi.cli("show gbp vxlan"))
1710 self.logger.info(self.vapi.cli("show vxlan-gbp tunnel"))
1713 # wait for the learnt endpoints to age out
1716 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1720 # repeat. the do not learn bit is set so the EPs are not learnt
1723 # a packet with an sclass from a known EPG
1724 p = (Ether(src=self.pg2.remote_mac,
1725 dst=self.pg2.local_mac) /
1726 IP(src=self.pg2.remote_hosts[1].ip4,
1727 dst=self.pg2.local_ip4) /
1728 UDP(sport=1234, dport=48879) /
1729 VXLAN(vni=99, gpid=112, flags=0x88, gpflags="D") /
1730 Ether(src=l['mac'], dst=ep.mac) /
1731 IP(src=l['ip'], dst=ep.ip4.address) /
1732 UDP(sport=1234, dport=1234) /
1735 rx = self.send_and_expect(self.pg2, p*65, self.pg0)
1738 self.assertFalse(find_gbp_endpoint(self,
1739 vx_tun_l2_1.sw_if_index,
1746 # a packet with an sclass from a known EPG
1747 p = (Ether(src=self.pg2.remote_mac,
1748 dst=self.pg2.local_mac) /
1749 IP(src=self.pg2.remote_hosts[1].ip4,
1750 dst=self.pg2.local_ip4) /
1751 UDP(sport=1234, dport=48879) /
1752 VXLAN(vni=99, gpid=112, flags=0x88) /
1753 Ether(src=l['mac'], dst=ep.mac) /
1754 IP(src=l['ip'], dst=ep.ip4.address) /
1755 UDP(sport=1234, dport=1234) /
1758 rx = self.send_and_expect(self.pg2, p*65, self.pg0)
1760 self.assertTrue(find_gbp_endpoint(self,
1761 vx_tun_l2_1.sw_if_index,
1765 # Static EP replies to dynamics
1767 self.logger.info(self.vapi.cli("sh l2fib bd_id 1"))
1769 p = (Ether(src=ep.mac, dst=l['mac']) /
1770 IP(dst=l['ip'], src=ep.ip4.address) /
1771 UDP(sport=1234, dport=1234) /
1774 rxs = self.send_and_expect(self.pg0, p * 17, self.pg2)
1777 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
1778 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
1779 self.assertEqual(rx[UDP].dport, 48879)
1780 # the UDP source port is a random value for hashing
1781 self.assertEqual(rx[VXLAN].gpid, 112)
1782 self.assertEqual(rx[VXLAN].vni, 99)
1783 self.assertTrue(rx[VXLAN].flags.G)
1784 self.assertTrue(rx[VXLAN].flags.Instance)
1785 self.assertTrue(rx[VXLAN].gpflags.A)
1786 self.assertFalse(rx[VXLAN].gpflags.D)
1789 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1793 # repeat in the other EPG
1794 # there's no contract between 220 and 330, but the A-bit is set
1795 # so the packet is cleared for delivery
1798 # a packet with an sclass from a known EPG
1799 p = (Ether(src=self.pg2.remote_mac,
1800 dst=self.pg2.local_mac) /
1801 IP(src=self.pg2.remote_hosts[1].ip4,
1802 dst=self.pg2.local_ip4) /
1803 UDP(sport=1234, dport=48879) /
1804 VXLAN(vni=99, gpid=113, flags=0x88, gpflags='A') /
1805 Ether(src=l['mac'], dst=ep.mac) /
1806 IP(src=l['ip'], dst=ep.ip4.address) /
1807 UDP(sport=1234, dport=1234) /
1810 rx = self.send_and_expect(self.pg2, p*65, self.pg0)
1812 self.assertTrue(find_gbp_endpoint(self,
1813 vx_tun_l2_1.sw_if_index,
1817 # static EP cannot reach the learnt EPs since there is no contract
1818 # only test 1 EP as the others could timeout
1820 p = (Ether(src=ep.mac, dst=l['mac']) /
1821 IP(dst=learnt[0]['ip'], src=ep.ip4.address) /
1822 UDP(sport=1234, dport=1234) /
1825 self.send_and_assert_no_replies(self.pg0, [p])
1828 # refresh the entries after the check for no replies above
1831 # a packet with an sclass from a known EPG
1832 p = (Ether(src=self.pg2.remote_mac,
1833 dst=self.pg2.local_mac) /
1834 IP(src=self.pg2.remote_hosts[1].ip4,
1835 dst=self.pg2.local_ip4) /
1836 UDP(sport=1234, dport=48879) /
1837 VXLAN(vni=99, gpid=113, flags=0x88, gpflags='A') /
1838 Ether(src=l['mac'], dst=ep.mac) /
1839 IP(src=l['ip'], dst=ep.ip4.address) /
1840 UDP(sport=1234, dport=1234) /
1843 rx = self.send_and_expect(self.pg2, p*65, self.pg0)
1845 self.assertTrue(find_gbp_endpoint(self,
1846 vx_tun_l2_1.sw_if_index,
1850 # Add the contract so they can talk
1852 acl = VppGbpAcl(self)
1853 rule = acl.create_rule(permit_deny=1, proto=17)
1854 rule2 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
1855 acl_index = acl.add_vpp_config([rule, rule2])
1856 c1 = VppGbpContract(
1857 self, epg_220.sclass, epg_330.sclass, acl_index,
1858 [VppGbpContractRule(
1859 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1862 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1864 [ETH_P_IP, ETH_P_IPV6])
1868 p = (Ether(src=ep.mac, dst=l['mac']) /
1869 IP(dst=l['ip'], src=ep.ip4.address) /
1870 UDP(sport=1234, dport=1234) /
1873 self.send_and_expect(self.pg0, [p], self.pg2)
1876 # send UU packets from the local EP
1878 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1879 self.logger.info(self.vapi.cli("sh gbp bridge"))
1880 p_uu = (Ether(src=ep.mac, dst="00:11:11:11:11:11") /
1881 IP(dst="10.0.0.133", src=ep.ip4.address) /
1882 UDP(sport=1234, dport=1234) /
1884 rxs = self.send_and_expect(ep.itf, [p_uu], gbd1.uu_fwd)
1886 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1888 p_bm = (Ether(src=ep.mac, dst="ff:ff:ff:ff:ff:ff") /
1889 IP(dst="10.0.0.133", src=ep.ip4.address) /
1890 UDP(sport=1234, dport=1234) /
1892 rxs = self.send_and_expect_only(ep.itf, [p_bm], tun_bm.mcast_itf)
1895 self.assertEqual(rx[IP].src, self.pg4.local_ip4)
1896 self.assertEqual(rx[IP].dst, "239.1.1.1")
1897 self.assertEqual(rx[UDP].dport, 48879)
1898 # the UDP source port is a random value for hashing
1899 self.assertEqual(rx[VXLAN].gpid, 112)
1900 self.assertEqual(rx[VXLAN].vni, 88)
1901 self.assertTrue(rx[VXLAN].flags.G)
1902 self.assertTrue(rx[VXLAN].flags.Instance)
1903 self.assertFalse(rx[VXLAN].gpflags.A)
1904 self.assertFalse(rx[VXLAN].gpflags.D)
1907 # Check v6 Endpoints
1910 # a packet with an sclass from a known EPG
1911 p = (Ether(src=self.pg2.remote_mac,
1912 dst=self.pg2.local_mac) /
1913 IP(src=self.pg2.remote_hosts[1].ip4,
1914 dst=self.pg2.local_ip4) /
1915 UDP(sport=1234, dport=48879) /
1916 VXLAN(vni=99, gpid=113, flags=0x88, gpflags='A') /
1917 Ether(src=l['mac'], dst=ep.mac) /
1918 IPv6(src=l['ip6'], dst=ep.ip6.address) /
1919 UDP(sport=1234, dport=1234) /
1922 rx = self.send_and_expect(self.pg2, p*65, self.pg0)
1924 self.assertTrue(find_gbp_endpoint(self,
1925 vx_tun_l2_1.sw_if_index,
1929 # L3 Endpoint Learning
1930 # - configured on the bridge's BVI
1937 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1939 self.pg2.unconfig_ip4()
1940 self.pg3.unconfig_ip4()
1941 self.pg4.unconfig_ip4()
1943 self.logger.info(self.vapi.cli("sh int"))
1944 self.logger.info(self.vapi.cli("sh gbp vxlan"))
1946 def test_gbp_bd_flags(self):
1947 """ GBP BD FLAGS """
1952 gt4 = VppIpTable(self, 1)
1953 gt4.add_vpp_config()
1954 gt6 = VppIpTable(self, 1, is_ip6=True)
1955 gt6.add_vpp_config()
1957 rd1 = VppGbpRouteDomain(self, 1, gt4, gt6)
1958 rd1.add_vpp_config()
1961 # Pg3 hosts the IP4 UU-flood VXLAN tunnel
1962 # Pg4 hosts the IP6 UU-flood VXLAN tunnel
1964 self.pg3.config_ip4()
1965 self.pg3.resolve_arp()
1966 self.pg4.config_ip4()
1967 self.pg4.resolve_arp()
1970 # Add a mcast destination VXLAN-GBP tunnel for B&M traffic
1972 tun_bm = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
1975 tun_bm.add_vpp_config()
1978 # a GBP bridge domain with a BVI and a UU-flood interface
1980 bd1 = VppBridgeDomain(self, 1)
1981 bd1.add_vpp_config()
1983 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0, self.pg3, tun_bm,
1984 uu_drop=True, bm_drop=True)
1985 gbd1.add_vpp_config()
1987 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1988 self.logger.info(self.vapi.cli("sh gbp bridge"))
1990 # ... and has a /32 applied
1991 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
1992 ip_addr.add_vpp_config()
1995 # The Endpoint-group
1997 epg_220 = VppGbpEndpointGroup(self, 220, 112, rd1, gbd1,
2001 VppGbpEndpointRetention(2))
2002 epg_220.add_vpp_config()
2004 ep = VppGbpEndpoint(self, self.pg0,
2006 "10.0.0.127", "11.0.0.127",
2007 "2001:10::1", "3001::1")
2010 # send UU/BM packet from the local EP with UU drop and BM drop enabled
2013 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2014 self.logger.info(self.vapi.cli("sh gbp bridge"))
2015 p_uu = (Ether(src=ep.mac, dst="00:11:11:11:11:11") /
2016 IP(dst="10.0.0.133", src=ep.ip4.address) /
2017 UDP(sport=1234, dport=1234) /
2019 self.send_and_assert_no_replies(ep.itf, [p_uu])
2021 p_bm = (Ether(src=ep.mac, dst="ff:ff:ff:ff:ff:ff") /
2022 IP(dst="10.0.0.133", src=ep.ip4.address) /
2023 UDP(sport=1234, dport=1234) /
2025 self.send_and_assert_no_replies(ep.itf, [p_bm])
2027 self.pg3.unconfig_ip4()
2028 self.pg4.unconfig_ip4()
2030 self.logger.info(self.vapi.cli("sh int"))
2032 def test_gbp_learn_vlan_l2(self):
2033 """ GBP L2 Endpoint w/ VLANs"""
2035 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
2036 learnt = [{'mac': '00:00:11:11:11:01',
2038 'ip6': '2001:10::2'},
2039 {'mac': '00:00:11:11:11:02',
2041 'ip6': '2001:10::3'}]
2046 gt4 = VppIpTable(self, 1)
2047 gt4.add_vpp_config()
2048 gt6 = VppIpTable(self, 1, is_ip6=True)
2049 gt6.add_vpp_config()
2051 rd1 = VppGbpRouteDomain(self, 1, gt4, gt6)
2052 rd1.add_vpp_config()
2055 # Pg2 hosts the vxlan tunnel, hosts on pg2 to act as TEPs
2057 self.pg2.config_ip4()
2058 self.pg2.resolve_arp()
2059 self.pg2.generate_remote_hosts(4)
2060 self.pg2.configure_ipv4_neighbors()
2061 self.pg3.config_ip4()
2062 self.pg3.resolve_arp()
2065 # The EP will be on a vlan sub-interface
2067 vlan_11 = VppDot1QSubint(self, self.pg0, 11)
2069 self.vapi.l2_interface_vlan_tag_rewrite(
2070 sw_if_index=vlan_11.sw_if_index, vtr_op=L2_VTR_OP.L2_POP_1,
2073 bd_uu_fwd = VppVxlanGbpTunnel(self, self.pg3.local_ip4,
2074 self.pg3.remote_ip4, 116)
2075 bd_uu_fwd.add_vpp_config()
2078 # a GBP bridge domain with a BVI and a UU-flood interface
2079 # The BD is marked as do not learn, so no endpoints are ever
2080 # learnt in this BD.
2082 bd1 = VppBridgeDomain(self, 1)
2083 bd1.add_vpp_config()
2084 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0, bd_uu_fwd,
2086 gbd1.add_vpp_config()
2088 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2089 self.logger.info(self.vapi.cli("sh gbp bridge"))
2091 # ... and has a /32 applied
2092 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2093 ip_addr.add_vpp_config()
2096 # The Endpoint-group in which we are learning endpoints
2098 epg_220 = VppGbpEndpointGroup(self, 220, 441, rd1, gbd1,
2102 VppGbpEndpointRetention(2))
2103 epg_220.add_vpp_config()
2106 # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
2109 vx_tun_l2_1 = VppGbpVxlanTunnel(
2110 self, 99, bd1.bd_id,
2111 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L2,
2113 vx_tun_l2_1.add_vpp_config()
2116 # A static endpoint that the learnt endpoints are trying to
2119 ep = VppGbpEndpoint(self, vlan_11,
2121 "10.0.0.127", "11.0.0.127",
2122 "2001:10::1", "3001::1")
2125 self.assertTrue(find_route(self, ep.ip4.address, 32, table_id=1))
2128 # Send to the static EP
2130 for ii, l in enumerate(learnt):
2131 # a packet with an sclass from a known EPG
2132 # arriving on an unknown TEP
2133 p = (Ether(src=self.pg2.remote_mac,
2134 dst=self.pg2.local_mac) /
2135 IP(src=self.pg2.remote_hosts[1].ip4,
2136 dst=self.pg2.local_ip4) /
2137 UDP(sport=1234, dport=48879) /
2138 VXLAN(vni=99, gpid=441, flags=0x88) /
2139 Ether(src=l['mac'], dst=ep.mac) /
2140 IP(src=l['ip'], dst=ep.ip4.address) /
2141 UDP(sport=1234, dport=1234) /
2144 rxs = self.send_and_expect(self.pg2, [p], self.pg0)
2147 # packet to EP has the EP's vlan tag
2150 self.assertEqual(rx[Dot1Q].vlan, 11)
2153 # the EP is not learnt since the BD setting prevents it
2156 self.assertFalse(find_gbp_endpoint(self,
2157 vx_tun_l2_1.sw_if_index,
2159 self.assertEqual(INDEX_INVALID,
2160 find_vxlan_gbp_tunnel(
2163 self.pg2.remote_hosts[1].ip4,
2166 self.assertEqual(len(self.vapi.gbp_endpoint_dump()), 1)
2170 # we didn't learn the remotes so they are sent to the UU-fwd
2173 p = (Ether(src=ep.mac, dst=l['mac']) /
2175 IP(dst=l['ip'], src=ep.ip4.address) /
2176 UDP(sport=1234, dport=1234) /
2179 rxs = self.send_and_expect(self.pg0, p * 17, self.pg3)
2182 self.assertEqual(rx[IP].src, self.pg3.local_ip4)
2183 self.assertEqual(rx[IP].dst, self.pg3.remote_ip4)
2184 self.assertEqual(rx[UDP].dport, 48879)
2185 # the UDP source port is a random value for hashing
2186 self.assertEqual(rx[VXLAN].gpid, 441)
2187 self.assertEqual(rx[VXLAN].vni, 116)
2188 self.assertTrue(rx[VXLAN].flags.G)
2189 self.assertTrue(rx[VXLAN].flags.Instance)
2190 self.assertFalse(rx[VXLAN].gpflags.A)
2191 self.assertFalse(rx[VXLAN].gpflags.D)
2193 self.pg2.unconfig_ip4()
2194 self.pg3.unconfig_ip4()
2196 def test_gbp_learn_l3(self):
2197 """ GBP L3 Endpoint Learning """
2199 self.vapi.cli("set logging class gbp debug")
2201 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
2202 routed_dst_mac = "00:0c:0c:0c:0c:0c"
2203 routed_src_mac = "00:22:bd:f8:19:ff"
2205 learnt = [{'mac': '00:00:11:11:11:02',
2207 'ip6': '2001:10::2'},
2208 {'mac': '00:00:11:11:11:03',
2210 'ip6': '2001:10::3'}]
2215 t4 = VppIpTable(self, 1)
2217 t6 = VppIpTable(self, 1, True)
2220 tun_ip4_uu = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
2221 self.pg4.remote_ip4, 114)
2222 tun_ip6_uu = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
2223 self.pg4.remote_ip4, 116)
2224 tun_ip4_uu.add_vpp_config()
2225 tun_ip6_uu.add_vpp_config()
2227 rd1 = VppGbpRouteDomain(self, 2, t4, t6, tun_ip4_uu, tun_ip6_uu)
2228 rd1.add_vpp_config()
2230 self.loop0.set_mac(self.router_mac)
2233 # Bind the BVI to the RD
2235 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
2236 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
2239 # Pg2 hosts the vxlan tunnel
2240 # hosts on pg2 to act as TEPs
2244 self.pg2.config_ip4()
2245 self.pg2.resolve_arp()
2246 self.pg2.generate_remote_hosts(4)
2247 self.pg2.configure_ipv4_neighbors()
2248 self.pg3.config_ip4()
2249 self.pg3.resolve_arp()
2250 self.pg4.config_ip4()
2251 self.pg4.resolve_arp()
2254 # a GBP bridge domain with a BVI and a UU-flood interface
2256 bd1 = VppBridgeDomain(self, 1)
2257 bd1.add_vpp_config()
2258 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0, self.pg3)
2259 gbd1.add_vpp_config()
2261 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2262 self.logger.info(self.vapi.cli("sh gbp bridge"))
2263 self.logger.info(self.vapi.cli("sh gbp route"))
2265 # ... and has a /32 and /128 applied
2266 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2267 ip4_addr.add_vpp_config()
2268 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 128)
2269 ip6_addr.add_vpp_config()
2272 # The Endpoint-group in which we are learning endpoints
2274 epg_220 = VppGbpEndpointGroup(self, 220, 441, rd1, gbd1,
2278 VppGbpEndpointRetention(2))
2279 epg_220.add_vpp_config()
2282 # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
2285 vx_tun_l3 = VppGbpVxlanTunnel(
2286 self, 101, rd1.rd_id,
2287 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
2289 vx_tun_l3.add_vpp_config()
2292 # A static endpoint that the learnt endpoints are trying to
2295 ep = VppGbpEndpoint(self, self.pg0,
2297 "10.0.0.127", "11.0.0.127",
2298 "2001:10::1", "3001::1")
2302 # learn some remote IPv4 EPs
2304 for ii, l in enumerate(learnt):
2305 # a packet with an sclass from a known EPG
2306 # arriving on an unknown TEP
2307 p = (Ether(src=self.pg2.remote_mac,
2308 dst=self.pg2.local_mac) /
2309 IP(src=self.pg2.remote_hosts[1].ip4,
2310 dst=self.pg2.local_ip4) /
2311 UDP(sport=1234, dport=48879) /
2312 VXLAN(vni=101, gpid=441, flags=0x88) /
2313 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2314 IP(src=l['ip'], dst=ep.ip4.address) /
2315 UDP(sport=1234, dport=1234) /
2318 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2321 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2324 self.pg2.remote_hosts[1].ip4,
2326 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2328 # endpoint learnt via the parent GBP-vxlan interface
2329 self.assertTrue(find_gbp_endpoint(self,
2330 vx_tun_l3._sw_if_index,
2334 # Static IPv4 EP replies to learnt
2337 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2338 IP(dst=l['ip'], src=ep.ip4.address) /
2339 UDP(sport=1234, dport=1234) /
2342 rxs = self.send_and_expect(self.pg0, p*1, self.pg2)
2345 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2346 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2347 self.assertEqual(rx[UDP].dport, 48879)
2348 # the UDP source port is a random value for hashing
2349 self.assertEqual(rx[VXLAN].gpid, 441)
2350 self.assertEqual(rx[VXLAN].vni, 101)
2351 self.assertTrue(rx[VXLAN].flags.G)
2352 self.assertTrue(rx[VXLAN].flags.Instance)
2353 self.assertTrue(rx[VXLAN].gpflags.A)
2354 self.assertFalse(rx[VXLAN].gpflags.D)
2356 inner = rx[VXLAN].payload
2358 self.assertEqual(inner[Ether].src, routed_src_mac)
2359 self.assertEqual(inner[Ether].dst, routed_dst_mac)
2360 self.assertEqual(inner[IP].src, ep.ip4.address)
2361 self.assertEqual(inner[IP].dst, l['ip'])
2364 self.assertFalse(find_gbp_endpoint(self,
2369 # learn some remote IPv6 EPs
2371 for ii, l in enumerate(learnt):
2372 # a packet with an sclass from a known EPG
2373 # arriving on an unknown TEP
2374 p = (Ether(src=self.pg2.remote_mac,
2375 dst=self.pg2.local_mac) /
2376 IP(src=self.pg2.remote_hosts[1].ip4,
2377 dst=self.pg2.local_ip4) /
2378 UDP(sport=1234, dport=48879) /
2379 VXLAN(vni=101, gpid=441, flags=0x88) /
2380 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2381 IPv6(src=l['ip6'], dst=ep.ip6.address) /
2382 UDP(sport=1234, dport=1234) /
2385 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2388 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2391 self.pg2.remote_hosts[1].ip4,
2393 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2395 self.logger.info(self.vapi.cli("show gbp bridge"))
2396 self.logger.info(self.vapi.cli("show vxlan-gbp tunnel"))
2397 self.logger.info(self.vapi.cli("show gbp vxlan"))
2398 self.logger.info(self.vapi.cli("show int addr"))
2400 # endpoint learnt via the TEP
2401 self.assertTrue(find_gbp_endpoint(self, ip=l['ip6']))
2403 self.logger.info(self.vapi.cli("show gbp endpoint"))
2404 self.logger.info(self.vapi.cli("show ip fib index 1 %s" % l['ip']))
2407 # Static EP replies to learnt
2410 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2411 IPv6(dst=l['ip6'], src=ep.ip6.address) /
2412 UDP(sport=1234, dport=1234) /
2415 rxs = self.send_and_expect(self.pg0, p*65, self.pg2)
2418 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2419 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2420 self.assertEqual(rx[UDP].dport, 48879)
2421 # the UDP source port is a random value for hashing
2422 self.assertEqual(rx[VXLAN].gpid, 441)
2423 self.assertEqual(rx[VXLAN].vni, 101)
2424 self.assertTrue(rx[VXLAN].flags.G)
2425 self.assertTrue(rx[VXLAN].flags.Instance)
2426 self.assertTrue(rx[VXLAN].gpflags.A)
2427 self.assertFalse(rx[VXLAN].gpflags.D)
2429 inner = rx[VXLAN].payload
2431 self.assertEqual(inner[Ether].src, routed_src_mac)
2432 self.assertEqual(inner[Ether].dst, routed_dst_mac)
2433 self.assertEqual(inner[IPv6].src, ep.ip6.address)
2434 self.assertEqual(inner[IPv6].dst, l['ip6'])
2436 self.logger.info(self.vapi.cli("sh gbp endpoint"))
2438 self.wait_for_ep_timeout(ip=l['ip'])
2441 # Static sends to unknown EP with no route
2443 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2444 IP(dst="10.0.0.99", src=ep.ip4.address) /
2445 UDP(sport=1234, dport=1234) /
2448 self.send_and_assert_no_replies(self.pg0, [p])
2451 # Add a route to static EP's v4 and v6 subnet
2452 # packets should be sent on the v4/v6 uu=fwd interface resp.
2454 se_10_24 = VppGbpSubnet(
2455 self, rd1, "10.0.0.0", 24,
2456 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT)
2457 se_10_24.add_vpp_config()
2459 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2460 IP(dst="10.0.0.99", src=ep.ip4.address) /
2461 UDP(sport=1234, dport=1234) /
2464 rxs = self.send_and_expect(self.pg0, [p], self.pg4)
2466 self.assertEqual(rx[IP].src, self.pg4.local_ip4)
2467 self.assertEqual(rx[IP].dst, self.pg4.remote_ip4)
2468 self.assertEqual(rx[UDP].dport, 48879)
2469 # the UDP source port is a random value for hashing
2470 self.assertEqual(rx[VXLAN].gpid, 441)
2471 self.assertEqual(rx[VXLAN].vni, 114)
2472 self.assertTrue(rx[VXLAN].flags.G)
2473 self.assertTrue(rx[VXLAN].flags.Instance)
2474 # policy is not applied to packets sent to the uu-fwd interfaces
2475 self.assertFalse(rx[VXLAN].gpflags.A)
2476 self.assertFalse(rx[VXLAN].gpflags.D)
2479 # learn some remote IPv4 EPs
2481 for ii, l in enumerate(learnt):
2482 # a packet with an sclass from a known EPG
2483 # arriving on an unknown TEP
2484 p = (Ether(src=self.pg2.remote_mac,
2485 dst=self.pg2.local_mac) /
2486 IP(src=self.pg2.remote_hosts[2].ip4,
2487 dst=self.pg2.local_ip4) /
2488 UDP(sport=1234, dport=48879) /
2489 VXLAN(vni=101, gpid=441, flags=0x88) /
2490 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2491 IP(src=l['ip'], dst=ep.ip4.address) /
2492 UDP(sport=1234, dport=1234) /
2495 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2498 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2501 self.pg2.remote_hosts[2].ip4,
2503 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2505 # endpoint learnt via the parent GBP-vxlan interface
2506 self.assertTrue(find_gbp_endpoint(self,
2507 vx_tun_l3._sw_if_index,
2511 # Add a remote endpoint from the API
2513 rep_88 = VppGbpEndpoint(self, vx_tun_l3,
2515 "10.0.0.88", "11.0.0.88",
2516 "2001:10::88", "3001::88",
2517 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
2519 self.pg2.remote_hosts[1].ip4,
2521 rep_88.add_vpp_config()
2524 # Add a remote endpoint from the API that matches an existing one
2526 rep_2 = VppGbpEndpoint(self, vx_tun_l3,
2528 learnt[0]['ip'], "11.0.0.101",
2529 learnt[0]['ip6'], "3001::101",
2530 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
2532 self.pg2.remote_hosts[1].ip4,
2534 rep_2.add_vpp_config()
2537 # Add a route to the learned EP's v4 subnet
2538 # packets should be send on the v4/v6 uu=fwd interface resp.
2540 se_10_1_24 = VppGbpSubnet(
2541 self, rd1, "10.0.1.0", 24,
2542 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT)
2543 se_10_1_24.add_vpp_config()
2545 self.logger.info(self.vapi.cli("show gbp endpoint"))
2547 ips = ["10.0.0.88", learnt[0]['ip']]
2549 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2550 IP(dst=ip, src=ep.ip4.address) /
2551 UDP(sport=1234, dport=1234) /
2554 rxs = self.send_and_expect(self.pg0, p*65, self.pg2)
2557 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2558 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2559 self.assertEqual(rx[UDP].dport, 48879)
2560 # the UDP source port is a random value for hashing
2561 self.assertEqual(rx[VXLAN].gpid, 441)
2562 self.assertEqual(rx[VXLAN].vni, 101)
2563 self.assertTrue(rx[VXLAN].flags.G)
2564 self.assertTrue(rx[VXLAN].flags.Instance)
2565 self.assertTrue(rx[VXLAN].gpflags.A)
2566 self.assertFalse(rx[VXLAN].gpflags.D)
2568 inner = rx[VXLAN].payload
2570 self.assertEqual(inner[Ether].src, routed_src_mac)
2571 self.assertEqual(inner[Ether].dst, routed_dst_mac)
2572 self.assertEqual(inner[IP].src, ep.ip4.address)
2573 self.assertEqual(inner[IP].dst, ip)
2576 # remove the API remote EPs, only API sourced is gone, the DP
2577 # learnt one remains
2579 rep_88.remove_vpp_config()
2580 rep_2.remove_vpp_config()
2582 self.assertTrue(find_gbp_endpoint(self, ip=rep_2.ip4.address))
2584 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2585 IP(src=ep.ip4.address, dst=rep_2.ip4.address) /
2586 UDP(sport=1234, dport=1234) /
2588 rxs = self.send_and_expect(self.pg0, [p], self.pg2)
2590 self.assertFalse(find_gbp_endpoint(self, ip=rep_88.ip4.address))
2592 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2593 IP(src=ep.ip4.address, dst=rep_88.ip4.address) /
2594 UDP(sport=1234, dport=1234) /
2596 rxs = self.send_and_expect(self.pg0, [p], self.pg4)
2599 # to appease the testcase we cannot have the registered EP still
2600 # present (because it's DP learnt) when the TC ends so wait until
2603 self.wait_for_ep_timeout(ip=rep_88.ip4.address)
2604 self.wait_for_ep_timeout(ip=rep_2.ip4.address)
2607 # shutdown with learnt endpoint present
2609 p = (Ether(src=self.pg2.remote_mac,
2610 dst=self.pg2.local_mac) /
2611 IP(src=self.pg2.remote_hosts[1].ip4,
2612 dst=self.pg2.local_ip4) /
2613 UDP(sport=1234, dport=48879) /
2614 VXLAN(vni=101, gpid=441, flags=0x88) /
2615 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2616 IP(src=learnt[1]['ip'], dst=ep.ip4.address) /
2617 UDP(sport=1234, dport=1234) /
2620 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2622 # endpoint learnt via the parent GBP-vxlan interface
2623 self.assertTrue(find_gbp_endpoint(self,
2624 vx_tun_l3._sw_if_index,
2629 # remote endpoint becomes local
2631 self.pg2.unconfig_ip4()
2632 self.pg3.unconfig_ip4()
2633 self.pg4.unconfig_ip4()
2635 def test_gbp_redirect(self):
2636 """ GBP Endpoint Redirect """
2638 self.vapi.cli("set logging class gbp debug")
2640 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
2641 routed_dst_mac = "00:0c:0c:0c:0c:0c"
2642 routed_src_mac = "00:22:bd:f8:19:ff"
2644 learnt = [{'mac': '00:00:11:11:11:02',
2646 'ip6': '2001:10::2'},
2647 {'mac': '00:00:11:11:11:03',
2649 'ip6': '2001:10::3'}]
2654 t4 = VppIpTable(self, 1)
2656 t6 = VppIpTable(self, 1, True)
2659 rd1 = VppGbpRouteDomain(self, 2, t4, t6)
2660 rd1.add_vpp_config()
2662 self.loop0.set_mac(self.router_mac)
2665 # Bind the BVI to the RD
2667 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
2668 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
2671 # Pg7 hosts a BD's UU-fwd
2673 self.pg7.config_ip4()
2674 self.pg7.resolve_arp()
2677 # a GBP bridge domains for the EPs
2679 bd1 = VppBridgeDomain(self, 1)
2680 bd1.add_vpp_config()
2681 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0)
2682 gbd1.add_vpp_config()
2684 bd2 = VppBridgeDomain(self, 2)
2685 bd2.add_vpp_config()
2686 gbd2 = VppGbpBridgeDomain(self, bd2, self.loop1)
2687 gbd2.add_vpp_config()
2689 # ... and has a /32 and /128 applied
2690 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2691 ip4_addr.add_vpp_config()
2692 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 128)
2693 ip6_addr.add_vpp_config()
2694 ip4_addr = VppIpInterfaceAddress(self, gbd2.bvi, "10.0.1.128", 32)
2695 ip4_addr.add_vpp_config()
2696 ip6_addr = VppIpInterfaceAddress(self, gbd2.bvi, "2001:11::128", 128)
2697 ip6_addr.add_vpp_config()
2700 # The Endpoint-groups in which we are learning endpoints
2702 epg_220 = VppGbpEndpointGroup(self, 220, 440, rd1, gbd1,
2706 VppGbpEndpointRetention(2))
2707 epg_220.add_vpp_config()
2708 epg_221 = VppGbpEndpointGroup(self, 221, 441, rd1, gbd2,
2712 VppGbpEndpointRetention(2))
2713 epg_221.add_vpp_config()
2714 epg_222 = VppGbpEndpointGroup(self, 222, 442, rd1, gbd1,
2718 VppGbpEndpointRetention(2))
2719 epg_222.add_vpp_config()
2722 # a GBP bridge domains for the SEPs
2724 bd_uu1 = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
2725 self.pg7.remote_ip4, 116)
2726 bd_uu1.add_vpp_config()
2727 bd_uu2 = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
2728 self.pg7.remote_ip4, 117)
2729 bd_uu2.add_vpp_config()
2731 bd3 = VppBridgeDomain(self, 3)
2732 bd3.add_vpp_config()
2733 gbd3 = VppGbpBridgeDomain(self, bd3, self.loop2, bd_uu1, learn=False)
2734 gbd3.add_vpp_config()
2735 bd4 = VppBridgeDomain(self, 4)
2736 bd4.add_vpp_config()
2737 gbd4 = VppGbpBridgeDomain(self, bd4, self.loop3, bd_uu2, learn=False)
2738 gbd4.add_vpp_config()
2741 # EPGs in which the service endpoints exist
2743 epg_320 = VppGbpEndpointGroup(self, 320, 550, rd1, gbd3,
2747 VppGbpEndpointRetention(2))
2748 epg_320.add_vpp_config()
2749 epg_321 = VppGbpEndpointGroup(self, 321, 551, rd1, gbd4,
2753 VppGbpEndpointRetention(2))
2754 epg_321.add_vpp_config()
2757 # three local endpoints
2759 ep1 = VppGbpEndpoint(self, self.pg0,
2761 "10.0.0.1", "11.0.0.1",
2762 "2001:10::1", "3001:10::1")
2763 ep1.add_vpp_config()
2764 ep2 = VppGbpEndpoint(self, self.pg1,
2766 "10.0.1.1", "11.0.1.1",
2767 "2001:11::1", "3001:11::1")
2768 ep2.add_vpp_config()
2769 ep3 = VppGbpEndpoint(self, self.pg2,
2771 "10.0.2.2", "11.0.2.2",
2772 "2001:12::1", "3001:12::1")
2773 ep3.add_vpp_config()
2778 sep1 = VppGbpEndpoint(self, self.pg3,
2780 "12.0.0.1", "13.0.0.1",
2781 "4001:10::1", "5001:10::1")
2782 sep1.add_vpp_config()
2783 sep2 = VppGbpEndpoint(self, self.pg4,
2785 "12.0.0.2", "13.0.0.2",
2786 "4001:10::2", "5001:10::2")
2787 sep2.add_vpp_config()
2788 sep3 = VppGbpEndpoint(self, self.pg5,
2790 "12.0.1.1", "13.0.1.1",
2791 "4001:11::1", "5001:11::1")
2792 sep3.add_vpp_config()
2793 # this EP is not installed immediately
2794 sep4 = VppGbpEndpoint(self, self.pg6,
2796 "12.0.1.2", "13.0.1.2",
2797 "4001:11::2", "5001:11::2")
2800 # an L2 switch packet between local EPs in different EPGs
2801 # different dest ports on each so the are LB hashed differently
2803 p4 = [(Ether(src=ep1.mac, dst=ep3.mac) /
2804 IP(src=ep1.ip4.address, dst=ep3.ip4.address) /
2805 UDP(sport=1234, dport=1234) /
2807 (Ether(src=ep3.mac, dst=ep1.mac) /
2808 IP(src=ep3.ip4.address, dst=ep1.ip4.address) /
2809 UDP(sport=1234, dport=1234) /
2811 p6 = [(Ether(src=ep1.mac, dst=ep3.mac) /
2812 IPv6(src=ep1.ip6.address, dst=ep3.ip6.address) /
2813 UDP(sport=1234, dport=1234) /
2815 (Ether(src=ep3.mac, dst=ep1.mac) /
2816 IPv6(src=ep3.ip6.address, dst=ep1.ip6.address) /
2817 UDP(sport=1234, dport=1230) /
2820 # should be dropped since no contract yet
2821 self.send_and_assert_no_replies(self.pg0, [p4[0]])
2822 self.send_and_assert_no_replies(self.pg0, [p6[0]])
2825 # Add a contract with a rule to load-balance redirect via SEP1 and SEP2
2826 # one of the next-hops is via an EP that is not known
2828 acl = VppGbpAcl(self)
2829 rule4 = acl.create_rule(permit_deny=1, proto=17)
2830 rule6 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
2831 acl_index = acl.add_vpp_config([rule4, rule6])
2834 # test the src-ip hash mode
2836 c1 = VppGbpContract(
2837 self, epg_220.sclass, epg_222.sclass, acl_index,
2838 [VppGbpContractRule(
2839 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2840 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2841 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
2842 sep1.ip4, sep1.epg.rd),
2843 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
2844 sep2.ip4, sep2.epg.rd)]),
2846 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2847 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2848 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
2849 sep3.ip6, sep3.epg.rd),
2850 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
2851 sep4.ip6, sep4.epg.rd)])],
2852 [ETH_P_IP, ETH_P_IPV6])
2855 c2 = VppGbpContract(
2856 self, epg_222.sclass, epg_220.sclass, acl_index,
2857 [VppGbpContractRule(
2858 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2859 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2860 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
2861 sep1.ip4, sep1.epg.rd),
2862 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
2863 sep2.ip4, sep2.epg.rd)]),
2865 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2866 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2867 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
2868 sep3.ip6, sep3.epg.rd),
2869 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
2870 sep4.ip6, sep4.epg.rd)])],
2871 [ETH_P_IP, ETH_P_IPV6])
2875 # send again with the contract preset, now packets arrive
2876 # at SEP1 or SEP2 depending on the hashing
2878 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
2881 self.assertEqual(rx[Ether].src, routed_src_mac)
2882 self.assertEqual(rx[Ether].dst, sep1.mac)
2883 self.assertEqual(rx[IP].src, ep1.ip4.address)
2884 self.assertEqual(rx[IP].dst, ep3.ip4.address)
2886 rxs = self.send_and_expect(self.pg2, p4[1] * 17, sep2.itf)
2889 self.assertEqual(rx[Ether].src, routed_src_mac)
2890 self.assertEqual(rx[Ether].dst, sep2.mac)
2891 self.assertEqual(rx[IP].src, ep3.ip4.address)
2892 self.assertEqual(rx[IP].dst, ep1.ip4.address)
2894 rxs = self.send_and_expect(self.pg0, p6[0] * 17, self.pg7)
2897 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
2898 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
2899 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
2900 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
2901 self.assertEqual(rx[VXLAN].vni, 117)
2902 self.assertTrue(rx[VXLAN].flags.G)
2903 self.assertTrue(rx[VXLAN].flags.Instance)
2904 # redirect policy has been applied
2905 self.assertTrue(rx[VXLAN].gpflags.A)
2906 self.assertFalse(rx[VXLAN].gpflags.D)
2908 inner = rx[VXLAN].payload
2910 self.assertEqual(inner[Ether].src, routed_src_mac)
2911 self.assertEqual(inner[Ether].dst, sep4.mac)
2912 self.assertEqual(inner[IPv6].src, ep1.ip6.address)
2913 self.assertEqual(inner[IPv6].dst, ep3.ip6.address)
2915 rxs = self.send_and_expect(self.pg2, p6[1] * 17, sep3.itf)
2918 self.assertEqual(rx[Ether].src, routed_src_mac)
2919 self.assertEqual(rx[Ether].dst, sep3.mac)
2920 self.assertEqual(rx[IPv6].src, ep3.ip6.address)
2921 self.assertEqual(rx[IPv6].dst, ep1.ip6.address)
2924 # programme the unknown EP
2926 sep4.add_vpp_config()
2928 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep4.itf)
2931 self.assertEqual(rx[Ether].src, routed_src_mac)
2932 self.assertEqual(rx[Ether].dst, sep4.mac)
2933 self.assertEqual(rx[IPv6].src, ep1.ip6.address)
2934 self.assertEqual(rx[IPv6].dst, ep3.ip6.address)
2937 # and revert back to unprogrammed
2939 sep4.remove_vpp_config()
2941 rxs = self.send_and_expect(self.pg0, p6[0] * 17, self.pg7)
2944 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
2945 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
2946 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
2947 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
2948 self.assertEqual(rx[VXLAN].vni, 117)
2949 self.assertTrue(rx[VXLAN].flags.G)
2950 self.assertTrue(rx[VXLAN].flags.Instance)
2951 # redirect policy has been applied
2952 self.assertTrue(rx[VXLAN].gpflags.A)
2953 self.assertFalse(rx[VXLAN].gpflags.D)
2955 inner = rx[VXLAN].payload
2957 self.assertEqual(inner[Ether].src, routed_src_mac)
2958 self.assertEqual(inner[Ether].dst, sep4.mac)
2959 self.assertEqual(inner[IPv6].src, ep1.ip6.address)
2960 self.assertEqual(inner[IPv6].dst, ep3.ip6.address)
2962 c1.remove_vpp_config()
2963 c2.remove_vpp_config()
2966 # test the symmetric hash mode
2968 c1 = VppGbpContract(
2969 self, epg_220.sclass, epg_222.sclass, acl_index,
2970 [VppGbpContractRule(
2971 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2972 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
2973 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
2974 sep1.ip4, sep1.epg.rd),
2975 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
2976 sep2.ip4, sep2.epg.rd)]),
2978 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2979 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
2980 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
2981 sep3.ip6, sep3.epg.rd),
2982 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
2983 sep4.ip6, sep4.epg.rd)])],
2984 [ETH_P_IP, ETH_P_IPV6])
2987 c2 = VppGbpContract(
2988 self, epg_222.sclass, epg_220.sclass, acl_index,
2989 [VppGbpContractRule(
2990 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2991 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
2992 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
2993 sep1.ip4, sep1.epg.rd),
2994 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
2995 sep2.ip4, sep2.epg.rd)]),
2997 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2998 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
2999 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3000 sep3.ip6, sep3.epg.rd),
3001 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3002 sep4.ip6, sep4.epg.rd)])],
3003 [ETH_P_IP, ETH_P_IPV6])
3007 # send again with the contract preset, now packets arrive
3008 # at SEP1 for both directions
3010 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3013 self.assertEqual(rx[Ether].src, routed_src_mac)
3014 self.assertEqual(rx[Ether].dst, sep1.mac)
3015 self.assertEqual(rx[IP].src, ep1.ip4.address)
3016 self.assertEqual(rx[IP].dst, ep3.ip4.address)
3018 rxs = self.send_and_expect(self.pg2, p4[1] * 17, sep1.itf)
3021 self.assertEqual(rx[Ether].src, routed_src_mac)
3022 self.assertEqual(rx[Ether].dst, sep1.mac)
3023 self.assertEqual(rx[IP].src, ep3.ip4.address)
3024 self.assertEqual(rx[IP].dst, ep1.ip4.address)
3027 # programme the unknown EP for the L3 tests
3029 sep4.add_vpp_config()
3032 # an L3 switch packet between local EPs in different EPGs
3033 # different dest ports on each so the are LB hashed differently
3035 p4 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3036 IP(src=ep1.ip4.address, dst=ep2.ip4.address) /
3037 UDP(sport=1234, dport=1234) /
3039 (Ether(src=ep2.mac, dst=str(self.router_mac)) /
3040 IP(src=ep2.ip4.address, dst=ep1.ip4.address) /
3041 UDP(sport=1234, dport=1234) /
3043 p6 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3044 IPv6(src=ep1.ip6.address, dst=ep2.ip6.address) /
3045 UDP(sport=1234, dport=1234) /
3047 (Ether(src=ep2.mac, dst=str(self.router_mac)) /
3048 IPv6(src=ep2.ip6.address, dst=ep1.ip6.address) /
3049 UDP(sport=1234, dport=1234) /
3052 c3 = VppGbpContract(
3053 self, epg_220.sclass, epg_221.sclass, acl_index,
3054 [VppGbpContractRule(
3055 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3056 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3057 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3058 sep1.ip4, sep1.epg.rd),
3059 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3060 sep2.ip4, sep2.epg.rd)]),
3062 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3063 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3064 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3065 sep3.ip6, sep3.epg.rd),
3066 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3067 sep4.ip6, sep4.epg.rd)])],
3068 [ETH_P_IP, ETH_P_IPV6])
3071 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3074 self.assertEqual(rx[Ether].src, routed_src_mac)
3075 self.assertEqual(rx[Ether].dst, sep1.mac)
3076 self.assertEqual(rx[IP].src, ep1.ip4.address)
3077 self.assertEqual(rx[IP].dst, ep2.ip4.address)
3080 # learn a remote EP in EPG 221
3082 vx_tun_l3 = VppGbpVxlanTunnel(
3083 self, 444, rd1.rd_id,
3084 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
3086 vx_tun_l3.add_vpp_config()
3088 c4 = VppGbpContract(
3089 self, epg_221.sclass, epg_220.sclass, acl_index,
3090 [VppGbpContractRule(
3091 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3094 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3096 [ETH_P_IP, ETH_P_IPV6])
3099 p = (Ether(src=self.pg7.remote_mac,
3100 dst=self.pg7.local_mac) /
3101 IP(src=self.pg7.remote_ip4,
3102 dst=self.pg7.local_ip4) /
3103 UDP(sport=1234, dport=48879) /
3104 VXLAN(vni=444, gpid=441, flags=0x88) /
3105 Ether(src="00:22:22:22:22:33", dst=str(self.router_mac)) /
3106 IP(src="10.0.0.88", dst=ep1.ip4.address) /
3107 UDP(sport=1234, dport=1234) /
3110 rx = self.send_and_expect(self.pg7, [p], self.pg0)
3112 # endpoint learnt via the parent GBP-vxlan interface
3113 self.assertTrue(find_gbp_endpoint(self,
3114 vx_tun_l3._sw_if_index,
3117 p = (Ether(src=self.pg7.remote_mac,
3118 dst=self.pg7.local_mac) /
3119 IP(src=self.pg7.remote_ip4,
3120 dst=self.pg7.local_ip4) /
3121 UDP(sport=1234, dport=48879) /
3122 VXLAN(vni=444, gpid=441, flags=0x88) /
3123 Ether(src="00:22:22:22:22:33", dst=str(self.router_mac)) /
3124 IPv6(src="2001:10::88", dst=ep1.ip6.address) /
3125 UDP(sport=1234, dport=1234) /
3128 rx = self.send_and_expect(self.pg7, [p], self.pg0)
3130 # endpoint learnt via the parent GBP-vxlan interface
3131 self.assertTrue(find_gbp_endpoint(self,
3132 vx_tun_l3._sw_if_index,
3136 # L3 switch from local to remote EP
3138 p4 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3139 IP(src=ep1.ip4.address, dst="10.0.0.88") /
3140 UDP(sport=1234, dport=1234) /
3142 p6 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3143 IPv6(src=ep1.ip6.address, dst="2001:10::88") /
3144 UDP(sport=1234, dport=1234) /
3147 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3150 self.assertEqual(rx[Ether].src, routed_src_mac)
3151 self.assertEqual(rx[Ether].dst, sep1.mac)
3152 self.assertEqual(rx[IP].src, ep1.ip4.address)
3153 self.assertEqual(rx[IP].dst, "10.0.0.88")
3155 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep4.itf)
3158 self.assertEqual(rx[Ether].src, routed_src_mac)
3159 self.assertEqual(rx[Ether].dst, sep4.mac)
3160 self.assertEqual(rx[IPv6].src, ep1.ip6.address)
3161 self.assertEqual(rx[IPv6].dst, "2001:10::88")
3164 # test the dst-ip hash mode
3166 c5 = VppGbpContract(
3167 self, epg_220.sclass, epg_221.sclass, acl_index,
3168 [VppGbpContractRule(
3169 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3170 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
3171 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3172 sep1.ip4, sep1.epg.rd),
3173 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3174 sep2.ip4, sep2.epg.rd)]),
3176 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3177 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
3178 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3179 sep3.ip6, sep3.epg.rd),
3180 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3181 sep4.ip6, sep4.epg.rd)])],
3182 [ETH_P_IP, ETH_P_IPV6])
3185 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3188 self.assertEqual(rx[Ether].src, routed_src_mac)
3189 self.assertEqual(rx[Ether].dst, sep1.mac)
3190 self.assertEqual(rx[IP].src, ep1.ip4.address)
3191 self.assertEqual(rx[IP].dst, "10.0.0.88")
3193 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep3.itf)
3196 self.assertEqual(rx[Ether].src, routed_src_mac)
3197 self.assertEqual(rx[Ether].dst, sep3.mac)
3198 self.assertEqual(rx[IPv6].src, ep1.ip6.address)
3199 self.assertEqual(rx[IPv6].dst, "2001:10::88")
3204 self.pg7.unconfig_ip4()
3206 def test_gbp_l3_out(self):
3209 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
3210 self.vapi.cli("set logging class gbp debug")
3212 routed_dst_mac = "00:0c:0c:0c:0c:0c"
3213 routed_src_mac = "00:22:bd:f8:19:ff"
3218 t4 = VppIpTable(self, 1)
3220 t6 = VppIpTable(self, 1, True)
3223 rd1 = VppGbpRouteDomain(self, 2, t4, t6)
3224 rd1.add_vpp_config()
3226 self.loop0.set_mac(self.router_mac)
3229 # Bind the BVI to the RD
3231 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
3232 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
3235 # Pg7 hosts a BD's BUM
3236 # Pg1 some other l3 interface
3238 self.pg7.config_ip4()
3239 self.pg7.resolve_arp()
3242 # a multicast vxlan-gbp tunnel for broadcast in the BD
3244 tun_bm = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
3247 tun_bm.add_vpp_config()
3250 # a GBP external bridge domains for the EPs
3252 bd1 = VppBridgeDomain(self, 1)
3253 bd1.add_vpp_config()
3254 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0, None, tun_bm)
3255 gbd1.add_vpp_config()
3258 # The Endpoint-groups in which the external endpoints exist
3260 epg_220 = VppGbpEndpointGroup(self, 220, 113, rd1, gbd1,
3264 VppGbpEndpointRetention(2))
3265 epg_220.add_vpp_config()
3267 # the BVIs have the subnets applied ...
3268 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 24)
3269 ip4_addr.add_vpp_config()
3270 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 64)
3271 ip6_addr.add_vpp_config()
3273 # ... which are L3-out subnets
3274 l3o_1 = VppGbpSubnet(
3275 self, rd1, "10.0.0.0", 24,
3276 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3278 l3o_1.add_vpp_config()
3281 # an external interface attached to the outside world and the
3284 vlan_100 = VppDot1QSubint(self, self.pg0, 100)
3286 VppL2Vtr(self, vlan_100, L2_VTR_OP.L2_POP_1).add_vpp_config()
3287 vlan_101 = VppDot1QSubint(self, self.pg0, 101)
3289 VppL2Vtr(self, vlan_101, L2_VTR_OP.L2_POP_1).add_vpp_config()
3291 ext_itf = VppGbpExtItf(self, self.loop0, bd1, rd1)
3292 ext_itf.add_vpp_config()
3295 # an unicast vxlan-gbp for inter-RD traffic
3297 vx_tun_l3 = VppGbpVxlanTunnel(
3298 self, 444, rd1.rd_id,
3299 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
3301 vx_tun_l3.add_vpp_config()
3304 # External Endpoints
3306 eep1 = VppGbpEndpoint(self, vlan_100,
3308 "10.0.0.1", "11.0.0.1",
3309 "2001:10::1", "3001::1",
3310 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
3311 eep1.add_vpp_config()
3312 eep2 = VppGbpEndpoint(self, vlan_101,
3314 "10.0.0.2", "11.0.0.2",
3315 "2001:10::2", "3001::2",
3316 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
3317 eep2.add_vpp_config()
3320 # A remote external endpoint
3322 rep = VppGbpEndpoint(self, vx_tun_l3,
3324 "10.0.0.101", "11.0.0.101",
3325 "2001:10::101", "3001::101",
3326 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
3328 self.pg7.remote_ip4,
3330 rep.add_vpp_config()
3333 # ARP packet from External EPs are accepted and replied to
3335 p_arp = (Ether(src=eep1.mac, dst="ff:ff:ff:ff:ff:ff") /
3338 psrc=eep1.ip4.address, pdst="10.0.0.128",
3339 hwsrc=eep1.mac, hwdst="ff:ff:ff:ff:ff:ff"))
3340 rxs = self.send_and_expect(self.pg0, p_arp * 1, self.pg0)
3343 # packets destined to unknown addresses in the BVI's subnet
3346 p4 = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3348 IP(src="10.0.0.1", dst="10.0.0.88") /
3349 UDP(sport=1234, dport=1234) /
3351 p6 = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3353 IPv6(src="2001:10::1", dst="2001:10::88") /
3354 UDP(sport=1234, dport=1234) /
3357 rxs = self.send_and_expect(self.pg0, p4 * 1, self.pg7)
3360 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3361 # self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3362 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3363 self.assertEqual(rx[IP].dst, "239.1.1.1")
3364 self.assertEqual(rx[VXLAN].vni, 88)
3365 self.assertTrue(rx[VXLAN].flags.G)
3366 self.assertTrue(rx[VXLAN].flags.Instance)
3367 # policy was applied to the original IP packet
3368 self.assertEqual(rx[VXLAN].gpid, 113)
3369 self.assertTrue(rx[VXLAN].gpflags.A)
3370 self.assertFalse(rx[VXLAN].gpflags.D)
3372 inner = rx[VXLAN].payload
3374 self.assertTrue(inner.haslayer(ARP))
3377 # remote to external
3379 p = (Ether(src=self.pg7.remote_mac,
3380 dst=self.pg7.local_mac) /
3381 IP(src=self.pg7.remote_ip4,
3382 dst=self.pg7.local_ip4) /
3383 UDP(sport=1234, dport=48879) /
3384 VXLAN(vni=444, gpid=113, flags=0x88) /
3385 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
3386 IP(src="10.0.0.101", dst="10.0.0.1") /
3387 UDP(sport=1234, dport=1234) /
3390 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
3393 # local EP pings router
3395 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3397 IP(src=eep1.ip4.address, dst="10.0.0.128") /
3398 ICMP(type='echo-request'))
3400 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
3403 self.assertEqual(rx[Ether].src, str(self.router_mac))
3404 self.assertEqual(rx[Ether].dst, eep1.mac)
3405 self.assertEqual(rx[Dot1Q].vlan, 100)
3408 # local EP pings other local EP
3410 p = (Ether(src=eep1.mac, dst=eep2.mac) /
3412 IP(src=eep1.ip4.address, dst=eep2.ip4.address) /
3413 ICMP(type='echo-request'))
3415 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
3418 self.assertEqual(rx[Ether].src, eep1.mac)
3419 self.assertEqual(rx[Ether].dst, eep2.mac)
3420 self.assertEqual(rx[Dot1Q].vlan, 101)
3423 # A subnet reachable through the external EP1
3425 ip_220 = VppIpRoute(self, "10.220.0.0", 24,
3426 [VppRoutePath(eep1.ip4.address,
3427 eep1.epg.bvi.sw_if_index)],
3428 table_id=t4.table_id)
3429 ip_220.add_vpp_config()
3431 l3o_220 = VppGbpSubnet(
3432 self, rd1, "10.220.0.0", 24,
3433 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3435 l3o_220.add_vpp_config()
3438 # A subnet reachable through the external EP2
3440 ip_221 = VppIpRoute(self, "10.221.0.0", 24,
3441 [VppRoutePath(eep2.ip4.address,
3442 eep2.epg.bvi.sw_if_index)],
3443 table_id=t4.table_id)
3444 ip_221.add_vpp_config()
3446 l3o_221 = VppGbpSubnet(
3447 self, rd1, "10.221.0.0", 24,
3448 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3450 l3o_221.add_vpp_config()
3453 # ping between hosts in remote subnets
3454 # dropped without a contract
3456 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3458 IP(src="10.220.0.1", dst="10.221.0.1") /
3459 ICMP(type='echo-request'))
3461 rxs = self.send_and_assert_no_replies(self.pg0, p * 1)
3464 # contract for the external nets to communicate
3466 acl = VppGbpAcl(self)
3467 rule4 = acl.create_rule(permit_deny=1, proto=17)
3468 rule6 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
3469 acl_index = acl.add_vpp_config([rule4, rule6])
3471 c1 = VppGbpContract(
3472 self, 4220, 4221, acl_index,
3473 [VppGbpContractRule(
3474 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3477 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3479 [ETH_P_IP, ETH_P_IPV6])
3483 # Contracts allowing ext-net 200 to talk with external EPs
3485 c2 = VppGbpContract(
3486 self, 4220, 113, acl_index,
3487 [VppGbpContractRule(
3488 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3491 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3493 [ETH_P_IP, ETH_P_IPV6])
3495 c3 = VppGbpContract(
3496 self, 113, 4220, acl_index,
3497 [VppGbpContractRule(
3498 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3501 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3503 [ETH_P_IP, ETH_P_IPV6])
3507 # ping between hosts in remote subnets
3509 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3511 IP(src="10.220.0.1", dst="10.221.0.1") /
3512 UDP(sport=1234, dport=1234) /
3515 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
3518 self.assertEqual(rx[Ether].src, str(self.router_mac))
3519 self.assertEqual(rx[Ether].dst, eep2.mac)
3520 self.assertEqual(rx[Dot1Q].vlan, 101)
3522 # we did not learn these external hosts
3523 self.assertFalse(find_gbp_endpoint(self, ip="10.220.0.1"))
3524 self.assertFalse(find_gbp_endpoint(self, ip="10.221.0.1"))
3527 # from remote external EP to local external EP
3529 p = (Ether(src=self.pg7.remote_mac,
3530 dst=self.pg7.local_mac) /
3531 IP(src=self.pg7.remote_ip4,
3532 dst=self.pg7.local_ip4) /
3533 UDP(sport=1234, dport=48879) /
3534 VXLAN(vni=444, gpid=113, flags=0x88) /
3535 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
3536 IP(src="10.0.0.101", dst="10.220.0.1") /
3537 UDP(sport=1234, dport=1234) /
3540 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
3543 # ping from an external host to the remote external EP
3545 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3547 IP(src="10.220.0.1", dst=rep.ip4.address) /
3548 UDP(sport=1234, dport=1234) /
3551 rxs = self.send_and_expect(self.pg0, p * 1, self.pg7)
3554 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3555 # self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3556 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3557 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
3558 self.assertEqual(rx[VXLAN].vni, 444)
3559 self.assertTrue(rx[VXLAN].flags.G)
3560 self.assertTrue(rx[VXLAN].flags.Instance)
3561 # the sclass of the ext-net the packet came from
3562 self.assertEqual(rx[VXLAN].gpid, 4220)
3563 # policy was applied to the original IP packet
3564 self.assertTrue(rx[VXLAN].gpflags.A)
3565 # since it's an external host the reciever should not learn it
3566 self.assertTrue(rx[VXLAN].gpflags.D)
3567 inner = rx[VXLAN].payload
3568 self.assertEqual(inner[IP].src, "10.220.0.1")
3569 self.assertEqual(inner[IP].dst, rep.ip4.address)
3572 # An external subnet reachable via the remote external EP
3576 # first the VXLAN-GBP tunnel over which it is reached
3578 vx_tun_r = VppVxlanGbpTunnel(
3579 self, self.pg7.local_ip4,
3580 self.pg7.remote_ip4, 445,
3581 mode=(VppEnum.vl_api_vxlan_gbp_api_tunnel_mode_t.
3582 VXLAN_GBP_API_TUNNEL_MODE_L3))
3583 vx_tun_r.add_vpp_config()
3584 VppIpInterfaceBind(self, vx_tun_r, t4).add_vpp_config()
3586 self.logger.info(self.vapi.cli("sh vxlan-gbp tunnel"))
3589 # then the special adj to resolve through on that tunnel
3591 n1 = VppNeighbor(self,
3592 vx_tun_r.sw_if_index,
3593 "00:0c:0c:0c:0c:0c",
3594 self.pg7.remote_ip4)
3598 # the route via the adj above
3600 ip_222 = VppIpRoute(self, "10.222.0.0", 24,
3601 [VppRoutePath(self.pg7.remote_ip4,
3602 vx_tun_r.sw_if_index)],
3603 table_id=t4.table_id)
3604 ip_222.add_vpp_config()
3606 l3o_222 = VppGbpSubnet(
3607 self, rd1, "10.222.0.0", 24,
3608 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3610 l3o_222.add_vpp_config()
3613 # ping between hosts in local and remote external subnets
3614 # dropped without a contract
3616 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3618 IP(src="10.220.0.1", dst="10.222.0.1") /
3619 UDP(sport=1234, dport=1234) /
3622 rxs = self.send_and_assert_no_replies(self.pg0, p * 1)
3625 # Add contracts ext-nets for 220 -> 222
3627 c4 = VppGbpContract(
3628 self, 4220, 4222, acl_index,
3629 [VppGbpContractRule(
3630 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3633 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3635 [ETH_P_IP, ETH_P_IPV6])
3639 # ping from host in local to remote external subnets
3641 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3643 IP(src="10.220.0.1", dst="10.222.0.1") /
3644 UDP(sport=1234, dport=1234) /
3647 rxs = self.send_and_expect(self.pg0, p * 3, self.pg7)
3650 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3651 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3652 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3653 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
3654 self.assertEqual(rx[VXLAN].vni, 445)
3655 self.assertTrue(rx[VXLAN].flags.G)
3656 self.assertTrue(rx[VXLAN].flags.Instance)
3657 # the sclass of the ext-net the packet came from
3658 self.assertEqual(rx[VXLAN].gpid, 4220)
3659 # policy was applied to the original IP packet
3660 self.assertTrue(rx[VXLAN].gpflags.A)
3661 # since it's an external host the reciever should not learn it
3662 self.assertTrue(rx[VXLAN].gpflags.D)
3663 inner = rx[VXLAN].payload
3664 self.assertEqual(inner[Ether].dst, "00:0c:0c:0c:0c:0c")
3665 self.assertEqual(inner[IP].src, "10.220.0.1")
3666 self.assertEqual(inner[IP].dst, "10.222.0.1")
3669 # ping from host in remote to local external subnets
3670 # there's no contract for this, but the A bit is set.
3672 p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
3673 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
3674 UDP(sport=1234, dport=48879) /
3675 VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
3676 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
3677 IP(src="10.222.0.1", dst="10.220.0.1") /
3678 UDP(sport=1234, dport=1234) /
3681 rxs = self.send_and_expect(self.pg7, p * 3, self.pg0)
3682 self.assertFalse(find_gbp_endpoint(self, ip="10.222.0.1"))
3685 # ping from host in remote to remote external subnets
3686 # this is dropped by reflection check.
3688 p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
3689 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
3690 UDP(sport=1234, dport=48879) /
3691 VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
3692 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
3693 IP(src="10.222.0.1", dst="10.222.0.2") /
3694 UDP(sport=1234, dport=1234) /
3697 rxs = self.send_and_assert_no_replies(self.pg7, p * 3)
3702 self.pg7.unconfig_ip4()
3703 vlan_100.set_vtr(L2_VTR_OP.L2_DISABLED)
3706 if __name__ == '__main__':
3707 unittest.main(testRunner=VppTestRunner)