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 self._test.vapi.gbp_contract_add_del(
456 self.allowed_ethertypes)
457 self._test.registry.register(self, self._test.logger)
459 def remove_vpp_config(self):
460 self._test.vapi.gbp_contract_add_del(
466 self.allowed_ethertypes)
469 return "gbp-contract:[%d:%s:%d]" % (self.sclass,
473 def query_vpp_config(self):
474 cs = self._test.vapi.gbp_contract_dump()
476 if c.contract.sclass == self.sclass \
477 and c.contract.dclass == self.dclass:
482 class VppGbpVxlanTunnel(VppInterface):
487 def __init__(self, test, vni, bd_rd_id, mode, src):
488 super(VppGbpVxlanTunnel, self).__init__(test)
491 self.bd_rd_id = bd_rd_id
495 def add_vpp_config(self):
496 r = self._test.vapi.gbp_vxlan_tunnel_add(
501 self.set_sw_if_index(r.sw_if_index)
502 self._test.registry.register(self, self._test.logger)
504 def remove_vpp_config(self):
505 self._test.vapi.gbp_vxlan_tunnel_del(self.vni)
508 return "gbp-vxlan:%d" % (self.sw_if_index)
510 def query_vpp_config(self):
511 return find_gbp_vxlan(self._test, self.vni)
514 class VppGbpAcl(VppObject):
519 def __init__(self, test):
521 self.acl_index = 4294967295
523 def create_rule(self, is_ipv6=0, permit_deny=0, proto=-1,
524 s_prefix=0, s_ip=b'\x00\x00\x00\x00', sport_from=0,
525 sport_to=65535, d_prefix=0, d_ip=b'\x00\x00\x00\x00',
526 dport_from=0, dport_to=65535):
527 if proto == -1 or proto == 0:
530 elif proto == 1 or proto == 58:
533 rule = ({'is_permit': permit_deny, 'is_ipv6': is_ipv6, 'proto': proto,
534 'srcport_or_icmptype_first': sport_from,
535 'srcport_or_icmptype_last': sport_to,
536 'src_ip_prefix_len': s_prefix,
538 'dstport_or_icmpcode_first': dport_from,
539 'dstport_or_icmpcode_last': dport_to,
540 'dst_ip_prefix_len': d_prefix,
541 'dst_ip_addr': d_ip})
544 def add_vpp_config(self, rules):
546 reply = self._test.vapi.acl_add_replace(self.acl_index,
549 self.acl_index = reply.acl_index
550 return self.acl_index
552 def remove_vpp_config(self):
553 self._test.vapi.acl_del(self.acl_index)
556 return "gbp-acl:[%d]" % (self.acl_index)
558 def query_vpp_config(self):
559 cs = self._test.vapi.acl_dump()
561 if c.acl_index == self.acl_index:
566 class TestGBP(VppTestCase):
567 """ GBP Test Case """
570 super(TestGBP, self).setUp()
572 self.create_pg_interfaces(range(9))
573 self.create_loopback_interfaces(8)
575 self.router_mac = MACAddress("00:11:22:33:44:55")
577 for i in self.pg_interfaces:
579 for i in self.lo_interfaces:
583 for i in self.pg_interfaces:
586 super(TestGBP, self).tearDown()
588 def send_and_expect_bridged(self, src, tx, dst):
589 rx = self.send_and_expect(src, tx, dst)
592 self.assertEqual(r[Ether].src, tx[0][Ether].src)
593 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
594 self.assertEqual(r[IP].src, tx[0][IP].src)
595 self.assertEqual(r[IP].dst, tx[0][IP].dst)
598 def send_and_expect_bridged6(self, src, tx, dst):
599 rx = self.send_and_expect(src, tx, dst)
602 self.assertEqual(r[Ether].src, tx[0][Ether].src)
603 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
604 self.assertEqual(r[IPv6].src, tx[0][IPv6].src)
605 self.assertEqual(r[IPv6].dst, tx[0][IPv6].dst)
608 def send_and_expect_routed(self, src, tx, dst, src_mac):
609 rx = self.send_and_expect(src, tx, dst)
612 self.assertEqual(r[Ether].src, src_mac)
613 self.assertEqual(r[Ether].dst, dst.remote_mac)
614 self.assertEqual(r[IP].src, tx[0][IP].src)
615 self.assertEqual(r[IP].dst, tx[0][IP].dst)
618 def send_and_expect_natted(self, src, tx, dst, src_ip):
619 rx = self.send_and_expect(src, tx, dst)
622 self.assertEqual(r[Ether].src, tx[0][Ether].src)
623 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
624 self.assertEqual(r[IP].src, src_ip)
625 self.assertEqual(r[IP].dst, tx[0][IP].dst)
628 def send_and_expect_natted6(self, src, tx, dst, src_ip):
629 rx = self.send_and_expect(src, tx, dst)
632 self.assertEqual(r[Ether].src, tx[0][Ether].src)
633 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
634 self.assertEqual(r[IPv6].src, src_ip)
635 self.assertEqual(r[IPv6].dst, tx[0][IPv6].dst)
638 def send_and_expect_unnatted(self, src, tx, dst, dst_ip):
639 rx = self.send_and_expect(src, tx, dst)
642 self.assertEqual(r[Ether].src, tx[0][Ether].src)
643 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
644 self.assertEqual(r[IP].dst, dst_ip)
645 self.assertEqual(r[IP].src, tx[0][IP].src)
648 def send_and_expect_unnatted6(self, src, tx, dst, dst_ip):
649 rx = self.send_and_expect(src, tx, dst)
652 self.assertEqual(r[Ether].src, tx[0][Ether].src)
653 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
654 self.assertEqual(r[IPv6].dst, dst_ip)
655 self.assertEqual(r[IPv6].src, tx[0][IPv6].src)
658 def send_and_expect_double_natted(self, src, tx, dst, src_ip, dst_ip):
659 rx = self.send_and_expect(src, tx, dst)
662 self.assertEqual(r[Ether].src, str(self.router_mac))
663 self.assertEqual(r[Ether].dst, dst.remote_mac)
664 self.assertEqual(r[IP].dst, dst_ip)
665 self.assertEqual(r[IP].src, src_ip)
668 def send_and_expect_double_natted6(self, src, tx, dst, src_ip, dst_ip):
669 rx = self.send_and_expect(src, tx, dst)
672 self.assertEqual(r[Ether].src, str(self.router_mac))
673 self.assertEqual(r[Ether].dst, dst.remote_mac)
674 self.assertEqual(r[IPv6].dst, dst_ip)
675 self.assertEqual(r[IPv6].src, src_ip)
679 """ Group Based Policy """
681 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
686 bd1 = VppBridgeDomain(self, 1)
687 bd2 = VppBridgeDomain(self, 2)
688 bd20 = VppBridgeDomain(self, 20)
692 bd20.add_vpp_config()
694 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0)
695 gbd2 = VppGbpBridgeDomain(self, bd2, self.loop1)
696 gbd20 = VppGbpBridgeDomain(self, bd20, self.loop2)
698 gbd1.add_vpp_config()
699 gbd2.add_vpp_config()
700 gbd20.add_vpp_config()
705 gt4 = VppIpTable(self, 0)
707 gt6 = VppIpTable(self, 0, is_ip6=True)
709 nt4 = VppIpTable(self, 20)
711 nt6 = VppIpTable(self, 20, is_ip6=True)
714 rd0 = VppGbpRouteDomain(self, 0, gt4, gt6, None, None)
715 rd20 = VppGbpRouteDomain(self, 20, nt4, nt6, None, None)
718 rd20.add_vpp_config()
721 # 3 EPGs, 2 of which share a BD.
722 # 2 NAT EPGs, one for floating-IP subnets, the other for internet
724 epgs = [VppGbpEndpointGroup(self, 220, 1220, rd0, gbd1,
725 self.pg4, self.loop0,
726 "10.0.0.128", "2001:10::128"),
727 VppGbpEndpointGroup(self, 221, 1221, rd0, gbd1,
728 self.pg5, self.loop0,
729 "10.0.1.128", "2001:10:1::128"),
730 VppGbpEndpointGroup(self, 222, 1222, rd0, gbd2,
731 self.pg6, self.loop1,
732 "10.0.2.128", "2001:10:2::128"),
733 VppGbpEndpointGroup(self, 333, 1333, rd20, gbd20,
734 self.pg7, self.loop2,
735 "11.0.0.128", "3001::128"),
736 VppGbpEndpointGroup(self, 444, 1444, rd20, gbd20,
737 self.pg8, self.loop2,
738 "11.0.0.129", "3001::129")]
739 recircs = [VppGbpRecirc(self, epgs[0], self.loop3),
740 VppGbpRecirc(self, epgs[1], self.loop4),
741 VppGbpRecirc(self, epgs[2], self.loop5),
742 VppGbpRecirc(self, epgs[3], self.loop6, is_ext=True),
743 VppGbpRecirc(self, epgs[4], self.loop7, is_ext=True)]
746 recirc_nat = recircs[3]
749 # 4 end-points, 2 in the same subnet, 3 in the same BD
751 eps = [VppGbpEndpoint(self, self.pg0,
753 "10.0.0.1", "11.0.0.1",
754 "2001:10::1", "3001::1"),
755 VppGbpEndpoint(self, self.pg1,
757 "10.0.0.2", "11.0.0.2",
758 "2001:10::2", "3001::2"),
759 VppGbpEndpoint(self, self.pg2,
761 "10.0.1.1", "11.0.0.3",
762 "2001:10:1::1", "3001::3"),
763 VppGbpEndpoint(self, self.pg3,
765 "10.0.2.1", "11.0.0.4",
766 "2001:10:2::1", "3001::4")]
769 # Config related to each of the EPGs
772 # IP config on the BVI interfaces
773 if epg != epgs[1] and epg != epgs[4]:
774 VppIpInterfaceBind(self, epg.bvi, epg.rd.t4).add_vpp_config()
775 VppIpInterfaceBind(self, epg.bvi, epg.rd.t6).add_vpp_config()
776 self.vapi.sw_interface_set_mac_address(
778 self.router_mac.packed)
780 # The BVIs are NAT inside interfaces
781 self.vapi.nat44_interface_add_del_feature(epg.bvi.sw_if_index,
784 self.vapi.nat66_add_del_interface(epg.bvi.sw_if_index,
788 if_ip4 = VppIpInterfaceAddress(self, epg.bvi, epg.bvi_ip4, 32)
789 if_ip6 = VppIpInterfaceAddress(self, epg.bvi, epg.bvi_ip6, 128)
790 if_ip4.add_vpp_config()
791 if_ip6.add_vpp_config()
793 # EPG uplink interfaces in the RD
794 VppIpInterfaceBind(self, epg.uplink, epg.rd.t4).add_vpp_config()
795 VppIpInterfaceBind(self, epg.uplink, epg.rd.t6).add_vpp_config()
797 # add the BD ARP termination entry for BVI IP
798 epg.bd_arp_ip4 = VppBridgeDomainArpEntry(self, epg.bd.bd,
799 str(self.router_mac),
801 epg.bd_arp_ip6 = VppBridgeDomainArpEntry(self, epg.bd.bd,
802 str(self.router_mac),
804 epg.bd_arp_ip4.add_vpp_config()
805 epg.bd_arp_ip6.add_vpp_config()
810 for recirc in recircs:
811 # EPG's ingress recirculation interface maps to its RD
812 VppIpInterfaceBind(self, recirc.recirc,
813 recirc.epg.rd.t4).add_vpp_config()
814 VppIpInterfaceBind(self, recirc.recirc,
815 recirc.epg.rd.t6).add_vpp_config()
817 self.vapi.nat44_interface_add_del_feature(
818 recirc.recirc.sw_if_index,
821 self.vapi.nat66_add_del_interface(
822 recirc.recirc.sw_if_index,
826 recirc.add_vpp_config()
828 for recirc in recircs:
829 self.assertTrue(find_bridge_domain_port(self,
830 recirc.epg.bd.bd.bd_id,
831 recirc.recirc.sw_if_index))
834 self.pg_enable_capture(self.pg_interfaces)
837 # routes to the endpoints. We need these since there are no
838 # adj-fibs due to the fact the the BVI address has /32 and
839 # the subnet is not attached.
841 for (ip, fip) in zip(ep.ips, ep.fips):
842 # Add static mappings for each EP from the 10/8 to 11/8 network
844 self.vapi.nat44_add_del_static_mapping(ip.bytes,
849 self.vapi.nat66_add_del_static_mapping(ip.bytes,
856 self.logger.info(self.vapi.cli("sh gbp endpoint"))
858 # ... results in a Gratuitous ARP/ND on the EPG's uplink
859 rx = ep.epg.uplink.get_capture(len(ep.ips), timeout=0.2)
861 for ii, ip in enumerate(ep.ips):
865 self.assertTrue(p.haslayer(ICMPv6ND_NA))
866 self.assertEqual(p[ICMPv6ND_NA].tgt, ip.address)
868 self.assertTrue(p.haslayer(ARP))
869 self.assertEqual(p[ARP].psrc, ip.address)
870 self.assertEqual(p[ARP].pdst, ip.address)
872 # add the BD ARP termination entry for floating IP
874 ba = VppBridgeDomainArpEntry(self, epg_nat.bd.bd, ep.mac, fip)
877 # floating IPs route via EPG recirc
878 r = VppIpRoute(self, fip.address, fip.length,
879 [VppRoutePath(fip.address,
880 ep.recirc.recirc.sw_if_index,
882 proto=fip.dpo_proto)],
887 # L2 FIB entries in the NAT EPG BD to bridge the packets from
888 # the outside direct to the internal EPG
889 lf = VppL2FibEntry(self, epg_nat.bd.bd, ep.mac,
890 ep.recirc.recirc, bvi_mac=0)
894 # ARP packets for unknown IP are sent to the EPG uplink
896 pkt_arp = (Ether(dst="ff:ff:ff:ff:ff:ff",
897 src=self.pg0.remote_mac) /
899 hwdst="ff:ff:ff:ff:ff:ff",
900 hwsrc=self.pg0.remote_mac,
904 self.vapi.cli("clear trace")
905 self.pg0.add_stream(pkt_arp)
907 self.pg_enable_capture(self.pg_interfaces)
910 rxd = epgs[0].uplink.get_capture(1)
913 # ARP/ND packets get a response
915 pkt_arp = (Ether(dst="ff:ff:ff:ff:ff:ff",
916 src=self.pg0.remote_mac) /
918 hwdst="ff:ff:ff:ff:ff:ff",
919 hwsrc=self.pg0.remote_mac,
920 pdst=epgs[0].bvi_ip4.address,
921 psrc=eps[0].ip4.address))
923 self.send_and_expect(self.pg0, [pkt_arp], self.pg0)
925 nsma = in6_getnsma(inet_pton(AF_INET6, eps[0].ip6.address))
926 d = inet_ntop(AF_INET6, nsma)
927 pkt_nd = (Ether(dst=in6_getnsmac(nsma),
928 src=self.pg0.remote_mac) /
929 IPv6(dst=d, src=eps[0].ip6.address) /
930 ICMPv6ND_NS(tgt=epgs[0].bvi_ip6.address) /
931 ICMPv6NDOptSrcLLAddr(lladdr=self.pg0.remote_mac))
932 self.send_and_expect(self.pg0, [pkt_nd], self.pg0)
935 # broadcast packets are flooded
937 pkt_bcast = (Ether(dst="ff:ff:ff:ff:ff:ff",
938 src=self.pg0.remote_mac) /
939 IP(src=eps[0].ip4.address, dst="232.1.1.1") /
940 UDP(sport=1234, dport=1234) /
943 self.vapi.cli("clear trace")
944 self.pg0.add_stream(pkt_bcast)
946 self.pg_enable_capture(self.pg_interfaces)
949 rxd = eps[1].itf.get_capture(1)
950 self.assertEqual(rxd[0][Ether].dst, pkt_bcast[Ether].dst)
951 rxd = epgs[0].uplink.get_capture(1)
952 self.assertEqual(rxd[0][Ether].dst, pkt_bcast[Ether].dst)
955 # packets to non-local L3 destinations dropped
957 pkt_intra_epg_220_ip4 = (Ether(src=self.pg0.remote_mac,
958 dst=str(self.router_mac)) /
959 IP(src=eps[0].ip4.address,
961 UDP(sport=1234, dport=1234) /
963 pkt_inter_epg_222_ip4 = (Ether(src=self.pg0.remote_mac,
964 dst=str(self.router_mac)) /
965 IP(src=eps[0].ip4.address,
967 UDP(sport=1234, dport=1234) /
970 self.send_and_assert_no_replies(self.pg0, pkt_intra_epg_220_ip4 * 65)
972 pkt_inter_epg_222_ip6 = (Ether(src=self.pg0.remote_mac,
973 dst=str(self.router_mac)) /
974 IPv6(src=eps[0].ip6.address,
976 UDP(sport=1234, dport=1234) /
978 self.send_and_assert_no_replies(self.pg0, pkt_inter_epg_222_ip6 * 65)
981 # Add the subnet routes
984 self, rd0, "10.0.0.0", 24,
985 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
987 self, rd0, "10.0.1.0", 24,
988 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
990 self, rd0, "10.0.2.0", 24,
991 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
993 self, rd0, "2001:10::1", 64,
994 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
996 self, rd0, "2001:10:1::1", 64,
997 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
999 self, rd0, "2001:10:2::1", 64,
1000 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1001 s41.add_vpp_config()
1002 s42.add_vpp_config()
1003 s43.add_vpp_config()
1004 s61.add_vpp_config()
1005 s62.add_vpp_config()
1006 s63.add_vpp_config()
1008 self.send_and_expect_bridged(eps[0].itf,
1009 pkt_intra_epg_220_ip4 * 65,
1011 self.send_and_expect_bridged(eps[0].itf,
1012 pkt_inter_epg_222_ip4 * 65,
1014 self.send_and_expect_bridged6(eps[0].itf,
1015 pkt_inter_epg_222_ip6 * 65,
1018 self.logger.info(self.vapi.cli("sh ip fib 11.0.0.2"))
1019 self.logger.info(self.vapi.cli("sh gbp endpoint-group"))
1020 self.logger.info(self.vapi.cli("sh gbp endpoint"))
1021 self.logger.info(self.vapi.cli("sh gbp recirc"))
1022 self.logger.info(self.vapi.cli("sh int"))
1023 self.logger.info(self.vapi.cli("sh int addr"))
1024 self.logger.info(self.vapi.cli("sh int feat loop6"))
1025 self.logger.info(self.vapi.cli("sh vlib graph ip4-gbp-src-classify"))
1026 self.logger.info(self.vapi.cli("sh int feat loop3"))
1027 self.logger.info(self.vapi.cli("sh int feat pg0"))
1030 # Packet destined to unknown unicast is sent on the epg uplink ...
1032 pkt_intra_epg_220_to_uplink = (Ether(src=self.pg0.remote_mac,
1033 dst="00:00:00:33:44:55") /
1034 IP(src=eps[0].ip4.address,
1036 UDP(sport=1234, dport=1234) /
1039 self.send_and_expect_bridged(eps[0].itf,
1040 pkt_intra_epg_220_to_uplink * 65,
1042 # ... and nowhere else
1043 self.pg1.get_capture(0, timeout=0.1)
1044 self.pg1.assert_nothing_captured(remark="Flood onto other VMS")
1046 pkt_intra_epg_221_to_uplink = (Ether(src=self.pg2.remote_mac,
1047 dst="00:00:00:33:44:66") /
1048 IP(src=eps[0].ip4.address,
1050 UDP(sport=1234, dport=1234) /
1053 self.send_and_expect_bridged(eps[2].itf,
1054 pkt_intra_epg_221_to_uplink * 65,
1058 # Packets from the uplink are forwarded in the absence of a contract
1060 pkt_intra_epg_220_from_uplink = (Ether(src="00:00:00:33:44:55",
1061 dst=self.pg0.remote_mac) /
1062 IP(src=eps[0].ip4.address,
1064 UDP(sport=1234, dport=1234) /
1067 self.send_and_expect_bridged(self.pg4,
1068 pkt_intra_epg_220_from_uplink * 65,
1072 # in the absence of policy, endpoints in the same EPG
1075 pkt_intra_epg = (Ether(src=self.pg0.remote_mac,
1076 dst=self.pg1.remote_mac) /
1077 IP(src=eps[0].ip4.address,
1078 dst=eps[1].ip4.address) /
1079 UDP(sport=1234, dport=1234) /
1082 self.send_and_expect_bridged(self.pg0, pkt_intra_epg * 65, self.pg1)
1085 # in the absence of policy, endpoints in the different EPG
1086 # cannot communicate
1088 pkt_inter_epg_220_to_221 = (Ether(src=self.pg0.remote_mac,
1089 dst=self.pg2.remote_mac) /
1090 IP(src=eps[0].ip4.address,
1091 dst=eps[2].ip4.address) /
1092 UDP(sport=1234, dport=1234) /
1094 pkt_inter_epg_221_to_220 = (Ether(src=self.pg2.remote_mac,
1095 dst=self.pg0.remote_mac) /
1096 IP(src=eps[2].ip4.address,
1097 dst=eps[0].ip4.address) /
1098 UDP(sport=1234, dport=1234) /
1100 pkt_inter_epg_220_to_222 = (Ether(src=self.pg0.remote_mac,
1101 dst=str(self.router_mac)) /
1102 IP(src=eps[0].ip4.address,
1103 dst=eps[3].ip4.address) /
1104 UDP(sport=1234, dport=1234) /
1107 self.send_and_assert_no_replies(eps[0].itf,
1108 pkt_inter_epg_220_to_221 * 65)
1109 self.send_and_assert_no_replies(eps[0].itf,
1110 pkt_inter_epg_220_to_222 * 65)
1113 # A uni-directional contract from EPG 220 -> 221
1115 acl = VppGbpAcl(self)
1116 rule = acl.create_rule(permit_deny=1, proto=17)
1117 rule2 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
1118 acl_index = acl.add_vpp_config([rule, rule2])
1119 c1 = VppGbpContract(
1120 self, epgs[0].sclass, epgs[1].sclass, acl_index,
1121 [VppGbpContractRule(
1122 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1125 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1127 [ETH_P_IP, ETH_P_IPV6])
1130 self.send_and_expect_bridged(eps[0].itf,
1131 pkt_inter_epg_220_to_221 * 65,
1133 self.send_and_assert_no_replies(eps[0].itf,
1134 pkt_inter_epg_220_to_222 * 65)
1137 # contract for the return direction
1139 c2 = VppGbpContract(
1140 self, epgs[1].sclass, epgs[0].sclass, acl_index,
1141 [VppGbpContractRule(
1142 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1145 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1147 [ETH_P_IP, ETH_P_IPV6])
1150 self.send_and_expect_bridged(eps[0].itf,
1151 pkt_inter_epg_220_to_221 * 65,
1153 self.send_and_expect_bridged(eps[2].itf,
1154 pkt_inter_epg_221_to_220 * 65,
1158 # the contract does not allow non-IP
1160 pkt_non_ip_inter_epg_220_to_221 = (Ether(src=self.pg0.remote_mac,
1161 dst=self.pg2.remote_mac) /
1163 self.send_and_assert_no_replies(eps[0].itf,
1164 pkt_non_ip_inter_epg_220_to_221 * 17)
1167 # check that inter group is still disabled for the groups
1168 # not in the contract.
1170 self.send_and_assert_no_replies(eps[0].itf,
1171 pkt_inter_epg_220_to_222 * 65)
1174 # A uni-directional contract from EPG 220 -> 222 'L3 routed'
1176 c3 = VppGbpContract(
1177 self, epgs[0].sclass, epgs[2].sclass, acl_index,
1178 [VppGbpContractRule(
1179 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1182 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1184 [ETH_P_IP, ETH_P_IPV6])
1187 self.logger.info(self.vapi.cli("sh gbp contract"))
1189 self.send_and_expect_routed(eps[0].itf,
1190 pkt_inter_epg_220_to_222 * 65,
1192 str(self.router_mac))
1195 # remove both contracts, traffic stops in both directions
1197 c2.remove_vpp_config()
1198 c1.remove_vpp_config()
1199 c3.remove_vpp_config()
1200 acl.remove_vpp_config()
1202 self.send_and_assert_no_replies(eps[2].itf,
1203 pkt_inter_epg_221_to_220 * 65)
1204 self.send_and_assert_no_replies(eps[0].itf,
1205 pkt_inter_epg_220_to_221 * 65)
1206 self.send_and_expect_bridged(eps[0].itf,
1211 # EPs to the outside world
1214 # in the EP's RD an external subnet via the NAT EPG's recirc
1216 self, rd0, "0.0.0.0", 0,
1217 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1218 sw_if_index=recirc_nat.recirc.sw_if_index,
1219 sclass=epg_nat.sclass)
1221 self, rd0, "11.0.0.0", 8,
1222 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1223 sw_if_index=recirc_nat.recirc.sw_if_index,
1224 sclass=epg_nat.sclass)
1225 se16 = VppGbpSubnet(
1227 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1228 sw_if_index=recirc_nat.recirc.sw_if_index,
1229 sclass=epg_nat.sclass)
1230 # in the NAT RD an external subnet via the NAT EPG's uplink
1232 self, rd20, "0.0.0.0", 0,
1233 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1234 sw_if_index=epg_nat.uplink.sw_if_index,
1235 sclass=epg_nat.sclass)
1236 se36 = VppGbpSubnet(
1237 self, rd20, "::", 0,
1238 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1239 sw_if_index=epg_nat.uplink.sw_if_index,
1240 sclass=epg_nat.sclass)
1242 self, rd20, "11.0.0.0", 8,
1243 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1244 sw_if_index=epg_nat.uplink.sw_if_index,
1245 sclass=epg_nat.sclass)
1246 se1.add_vpp_config()
1247 se2.add_vpp_config()
1248 se16.add_vpp_config()
1249 se3.add_vpp_config()
1250 se36.add_vpp_config()
1251 se4.add_vpp_config()
1253 self.logger.info(self.vapi.cli("sh ip fib 0.0.0.0/0"))
1254 self.logger.info(self.vapi.cli("sh ip fib 11.0.0.1"))
1255 self.logger.info(self.vapi.cli("sh ip6 fib ::/0"))
1256 self.logger.info(self.vapi.cli("sh ip6 fib %s" %
1260 # From an EP to an outside address: IN2OUT
1262 pkt_inter_epg_220_to_global = (Ether(src=self.pg0.remote_mac,
1263 dst=str(self.router_mac)) /
1264 IP(src=eps[0].ip4.address,
1266 UDP(sport=1234, dport=1234) /
1270 self.send_and_assert_no_replies(eps[0].itf,
1271 pkt_inter_epg_220_to_global * 65)
1273 acl2 = VppGbpAcl(self)
1274 rule = acl2.create_rule(permit_deny=1, proto=17, sport_from=1234,
1275 sport_to=1234, dport_from=1234, dport_to=1234)
1276 rule2 = acl2.create_rule(is_ipv6=1, permit_deny=1, proto=17,
1277 sport_from=1234, sport_to=1234,
1278 dport_from=1234, dport_to=1234)
1280 acl_index2 = acl2.add_vpp_config([rule, rule2])
1281 c4 = VppGbpContract(
1282 self, epgs[0].sclass, epgs[3].sclass, acl_index2,
1283 [VppGbpContractRule(
1284 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1287 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1289 [ETH_P_IP, ETH_P_IPV6])
1292 self.send_and_expect_natted(eps[0].itf,
1293 pkt_inter_epg_220_to_global * 65,
1295 eps[0].fip4.address)
1297 pkt_inter_epg_220_to_global = (Ether(src=self.pg0.remote_mac,
1298 dst=str(self.router_mac)) /
1299 IPv6(src=eps[0].ip6.address,
1301 UDP(sport=1234, dport=1234) /
1304 self.send_and_expect_natted6(self.pg0,
1305 pkt_inter_epg_220_to_global * 65,
1307 eps[0].fip6.address)
1310 # From a global address to an EP: OUT2IN
1312 pkt_inter_epg_220_from_global = (Ether(src=str(self.router_mac),
1313 dst=self.pg0.remote_mac) /
1314 IP(dst=eps[0].fip4.address,
1316 UDP(sport=1234, dport=1234) /
1319 self.send_and_assert_no_replies(self.pg7,
1320 pkt_inter_epg_220_from_global * 65)
1322 c5 = VppGbpContract(
1323 self, epgs[3].sclass, epgs[0].sclass, acl_index2,
1324 [VppGbpContractRule(
1325 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1328 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1330 [ETH_P_IP, ETH_P_IPV6])
1333 self.send_and_expect_unnatted(self.pg7,
1334 pkt_inter_epg_220_from_global * 65,
1338 pkt_inter_epg_220_from_global = (Ether(src=str(self.router_mac),
1339 dst=self.pg0.remote_mac) /
1340 IPv6(dst=eps[0].fip6.address,
1342 UDP(sport=1234, dport=1234) /
1345 self.send_and_expect_unnatted6(self.pg7,
1346 pkt_inter_epg_220_from_global * 65,
1351 # From a local VM to another local VM using resp. public addresses:
1354 pkt_intra_epg_220_global = (Ether(src=self.pg0.remote_mac,
1355 dst=str(self.router_mac)) /
1356 IP(src=eps[0].ip4.address,
1357 dst=eps[1].fip4.address) /
1358 UDP(sport=1234, dport=1234) /
1361 self.send_and_expect_double_natted(eps[0].itf,
1362 pkt_intra_epg_220_global * 65,
1364 eps[0].fip4.address,
1367 pkt_intra_epg_220_global = (Ether(src=self.pg0.remote_mac,
1368 dst=str(self.router_mac)) /
1369 IPv6(src=eps[0].ip6.address,
1370 dst=eps[1].fip6.address) /
1371 UDP(sport=1234, dport=1234) /
1374 self.send_and_expect_double_natted6(eps[0].itf,
1375 pkt_intra_epg_220_global * 65,
1377 eps[0].fip6.address,
1384 # del static mappings for each EP from the 10/8 to 11/8 network
1385 self.vapi.nat44_add_del_static_mapping(ep.ip4.bytes,
1390 self.vapi.nat66_add_del_static_mapping(ep.ip6.bytes,
1396 # IP config on the BVI interfaces
1397 if epg != epgs[0] and epg != epgs[3]:
1398 self.vapi.nat44_interface_add_del_feature(epg.bvi.sw_if_index,
1401 self.vapi.nat66_add_del_interface(epg.bvi.sw_if_index,
1405 for recirc in recircs:
1406 self.vapi.nat44_interface_add_del_feature(
1407 recirc.recirc.sw_if_index,
1410 self.vapi.nat66_add_del_interface(
1411 recirc.recirc.sw_if_index,
1415 def wait_for_ep_timeout(self, sw_if_index=None, ip=None, mac=None,
1416 n_tries=100, s_time=1):
1418 if not find_gbp_endpoint(self, sw_if_index, ip, mac):
1420 n_tries = n_tries - 1
1422 self.assertFalse(find_gbp_endpoint(self, sw_if_index, ip, mac))
1425 def test_gbp_learn_l2(self):
1426 """ GBP L2 Endpoint Learning """
1428 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
1429 learnt = [{'mac': '00:00:11:11:11:01',
1431 'ip6': '2001:10::2'},
1432 {'mac': '00:00:11:11:11:02',
1434 'ip6': '2001:10::3'}]
1439 gt4 = VppIpTable(self, 1)
1440 gt4.add_vpp_config()
1441 gt6 = VppIpTable(self, 1, is_ip6=True)
1442 gt6.add_vpp_config()
1444 rd1 = VppGbpRouteDomain(self, 1, gt4, gt6)
1445 rd1.add_vpp_config()
1448 # Pg2 hosts the vxlan tunnel, hosts on pg2 to act as TEPs
1449 # Pg3 hosts the IP4 UU-flood VXLAN tunnel
1450 # Pg4 hosts the IP6 UU-flood VXLAN tunnel
1452 self.pg2.config_ip4()
1453 self.pg2.resolve_arp()
1454 self.pg2.generate_remote_hosts(4)
1455 self.pg2.configure_ipv4_neighbors()
1456 self.pg3.config_ip4()
1457 self.pg3.resolve_arp()
1458 self.pg4.config_ip4()
1459 self.pg4.resolve_arp()
1462 # Add a mcast destination VXLAN-GBP tunnel for B&M traffic
1464 tun_bm = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
1467 tun_bm.add_vpp_config()
1470 # a GBP bridge domain with a BVI and a UU-flood interface
1472 bd1 = VppBridgeDomain(self, 1)
1473 bd1.add_vpp_config()
1474 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0, self.pg3, tun_bm)
1475 gbd1.add_vpp_config()
1477 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1478 self.logger.info(self.vapi.cli("sh gbp bridge"))
1480 # ... and has a /32 applied
1481 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
1482 ip_addr.add_vpp_config()
1485 # The Endpoint-group in which we are learning endpoints
1487 epg_220 = VppGbpEndpointGroup(self, 220, 112, rd1, gbd1,
1491 VppGbpEndpointRetention(2))
1492 epg_220.add_vpp_config()
1493 epg_330 = VppGbpEndpointGroup(self, 330, 113, rd1, gbd1,
1497 VppGbpEndpointRetention(2))
1498 epg_330.add_vpp_config()
1501 # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
1504 vx_tun_l2_1 = VppGbpVxlanTunnel(
1505 self, 99, bd1.bd_id,
1506 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L2,
1508 vx_tun_l2_1.add_vpp_config()
1511 # A static endpoint that the learnt endpoints are trying to
1514 ep = VppGbpEndpoint(self, self.pg0,
1516 "10.0.0.127", "11.0.0.127",
1517 "2001:10::1", "3001::1")
1520 self.assertTrue(find_route(self, ep.ip4.address, 32, table_id=1))
1522 # a packet with an sclass from an unknown EPG
1523 p = (Ether(src=self.pg2.remote_mac,
1524 dst=self.pg2.local_mac) /
1525 IP(src=self.pg2.remote_hosts[0].ip4,
1526 dst=self.pg2.local_ip4) /
1527 UDP(sport=1234, dport=48879) /
1528 VXLAN(vni=99, gpid=88, flags=0x88) /
1529 Ether(src=learnt[0]["mac"], dst=ep.mac) /
1530 IP(src=learnt[0]["ip"], dst=ep.ip4.address) /
1531 UDP(sport=1234, dport=1234) /
1534 self.send_and_assert_no_replies(self.pg2, p)
1537 # we should not have learnt a new tunnel endpoint, since
1538 # the EPG was not learnt.
1540 self.assertEqual(INDEX_INVALID,
1541 find_vxlan_gbp_tunnel(self,
1543 self.pg2.remote_hosts[0].ip4,
1546 # epg is not learnt, because the EPG is unknwon
1547 self.assertEqual(len(self.vapi.gbp_endpoint_dump()), 1)
1550 # Learn new EPs from IP packets
1552 for ii, l in enumerate(learnt):
1553 # a packet with an sclass from a known EPG
1554 # arriving on an unknown TEP
1555 p = (Ether(src=self.pg2.remote_mac,
1556 dst=self.pg2.local_mac) /
1557 IP(src=self.pg2.remote_hosts[1].ip4,
1558 dst=self.pg2.local_ip4) /
1559 UDP(sport=1234, dport=48879) /
1560 VXLAN(vni=99, gpid=112, flags=0x88) /
1561 Ether(src=l['mac'], dst=ep.mac) /
1562 IP(src=l['ip'], dst=ep.ip4.address) /
1563 UDP(sport=1234, dport=1234) /
1566 rx = self.send_and_expect(self.pg2, [p], self.pg0)
1569 tep1_sw_if_index = find_vxlan_gbp_tunnel(
1572 self.pg2.remote_hosts[1].ip4,
1574 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
1577 # the EP is learnt via the learnt TEP
1578 # both from its MAC and its IP
1580 self.assertTrue(find_gbp_endpoint(self,
1581 vx_tun_l2_1.sw_if_index,
1583 self.assertTrue(find_gbp_endpoint(self,
1584 vx_tun_l2_1.sw_if_index,
1587 self.logger.info(self.vapi.cli("show gbp endpoint"))
1588 self.logger.info(self.vapi.cli("show gbp vxlan"))
1589 self.logger.info(self.vapi.cli("show ip mfib"))
1592 # If we sleep for the threshold time, the learnt endpoints should
1596 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1600 # Learn new EPs from GARP packets received on the BD's mcast tunnel
1602 for ii, l in enumerate(learnt):
1603 # a packet with an sclass from a known EPG
1604 # arriving on an unknown TEP
1605 p = (Ether(src=self.pg2.remote_mac,
1606 dst=self.pg2.local_mac) /
1607 IP(src=self.pg2.remote_hosts[1].ip4,
1609 UDP(sport=1234, dport=48879) /
1610 VXLAN(vni=88, gpid=112, flags=0x88) /
1611 Ether(src=l['mac'], dst="ff:ff:ff:ff:ff:ff") /
1613 psrc=l['ip'], pdst=l['ip'],
1614 hwsrc=l['mac'], hwdst="ff:ff:ff:ff:ff:ff"))
1616 rx = self.send_and_expect(self.pg4, [p], self.pg0)
1619 tep1_sw_if_index = find_vxlan_gbp_tunnel(
1622 self.pg2.remote_hosts[1].ip4,
1624 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
1627 # the EP is learnt via the learnt TEP
1628 # both from its MAC and its IP
1630 self.assertTrue(find_gbp_endpoint(self,
1631 vx_tun_l2_1.sw_if_index,
1633 self.assertTrue(find_gbp_endpoint(self,
1634 vx_tun_l2_1.sw_if_index,
1638 # wait for the learnt endpoints to age out
1641 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1645 # Learn new EPs from L2 packets
1647 for ii, l in enumerate(learnt):
1648 # a packet with an sclass from a known EPG
1649 # arriving on an unknown TEP
1650 p = (Ether(src=self.pg2.remote_mac,
1651 dst=self.pg2.local_mac) /
1652 IP(src=self.pg2.remote_hosts[1].ip4,
1653 dst=self.pg2.local_ip4) /
1654 UDP(sport=1234, dport=48879) /
1655 VXLAN(vni=99, gpid=112, flags=0x88) /
1656 Ether(src=l['mac'], dst=ep.mac) /
1659 rx = self.send_and_expect(self.pg2, [p], self.pg0)
1662 tep1_sw_if_index = find_vxlan_gbp_tunnel(
1665 self.pg2.remote_hosts[1].ip4,
1667 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
1670 # the EP is learnt via the learnt TEP
1671 # both from its MAC and its IP
1673 self.assertTrue(find_gbp_endpoint(self,
1674 vx_tun_l2_1.sw_if_index,
1677 self.logger.info(self.vapi.cli("show gbp endpoint"))
1678 self.logger.info(self.vapi.cli("show gbp vxlan"))
1679 self.logger.info(self.vapi.cli("show vxlan-gbp tunnel"))
1682 # wait for the learnt endpoints to age out
1685 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1689 # repeat. the do not learn bit is set so the EPs are not learnt
1692 # a packet with an sclass from a known EPG
1693 p = (Ether(src=self.pg2.remote_mac,
1694 dst=self.pg2.local_mac) /
1695 IP(src=self.pg2.remote_hosts[1].ip4,
1696 dst=self.pg2.local_ip4) /
1697 UDP(sport=1234, dport=48879) /
1698 VXLAN(vni=99, gpid=112, flags=0x88, gpflags="D") /
1699 Ether(src=l['mac'], dst=ep.mac) /
1700 IP(src=l['ip'], dst=ep.ip4.address) /
1701 UDP(sport=1234, dport=1234) /
1704 rx = self.send_and_expect(self.pg2, p*65, self.pg0)
1707 self.assertFalse(find_gbp_endpoint(self,
1708 vx_tun_l2_1.sw_if_index,
1715 # a packet with an sclass from a known EPG
1716 p = (Ether(src=self.pg2.remote_mac,
1717 dst=self.pg2.local_mac) /
1718 IP(src=self.pg2.remote_hosts[1].ip4,
1719 dst=self.pg2.local_ip4) /
1720 UDP(sport=1234, dport=48879) /
1721 VXLAN(vni=99, gpid=112, flags=0x88) /
1722 Ether(src=l['mac'], dst=ep.mac) /
1723 IP(src=l['ip'], dst=ep.ip4.address) /
1724 UDP(sport=1234, dport=1234) /
1727 rx = self.send_and_expect(self.pg2, p*65, self.pg0)
1729 self.assertTrue(find_gbp_endpoint(self,
1730 vx_tun_l2_1.sw_if_index,
1734 # Static EP replies to dynamics
1736 self.logger.info(self.vapi.cli("sh l2fib bd_id 1"))
1738 p = (Ether(src=ep.mac, dst=l['mac']) /
1739 IP(dst=l['ip'], src=ep.ip4.address) /
1740 UDP(sport=1234, dport=1234) /
1743 rxs = self.send_and_expect(self.pg0, p * 17, self.pg2)
1746 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
1747 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
1748 self.assertEqual(rx[UDP].dport, 48879)
1749 # the UDP source port is a random value for hashing
1750 self.assertEqual(rx[VXLAN].gpid, 112)
1751 self.assertEqual(rx[VXLAN].vni, 99)
1752 self.assertTrue(rx[VXLAN].flags.G)
1753 self.assertTrue(rx[VXLAN].flags.Instance)
1754 self.assertTrue(rx[VXLAN].gpflags.A)
1755 self.assertFalse(rx[VXLAN].gpflags.D)
1758 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1762 # repeat in the other EPG
1763 # there's no contract between 220 and 330, but the A-bit is set
1764 # so the packet is cleared for delivery
1767 # a packet with an sclass from a known EPG
1768 p = (Ether(src=self.pg2.remote_mac,
1769 dst=self.pg2.local_mac) /
1770 IP(src=self.pg2.remote_hosts[1].ip4,
1771 dst=self.pg2.local_ip4) /
1772 UDP(sport=1234, dport=48879) /
1773 VXLAN(vni=99, gpid=113, flags=0x88, gpflags='A') /
1774 Ether(src=l['mac'], dst=ep.mac) /
1775 IP(src=l['ip'], dst=ep.ip4.address) /
1776 UDP(sport=1234, dport=1234) /
1779 rx = self.send_and_expect(self.pg2, p*65, self.pg0)
1781 self.assertTrue(find_gbp_endpoint(self,
1782 vx_tun_l2_1.sw_if_index,
1786 # static EP cannot reach the learnt EPs since there is no contract
1787 # only test 1 EP as the others could timeout
1789 p = (Ether(src=ep.mac, dst=l['mac']) /
1790 IP(dst=learnt[0]['ip'], src=ep.ip4.address) /
1791 UDP(sport=1234, dport=1234) /
1794 self.send_and_assert_no_replies(self.pg0, [p])
1797 # refresh the entries after the check for no replies above
1800 # a packet with an sclass from a known EPG
1801 p = (Ether(src=self.pg2.remote_mac,
1802 dst=self.pg2.local_mac) /
1803 IP(src=self.pg2.remote_hosts[1].ip4,
1804 dst=self.pg2.local_ip4) /
1805 UDP(sport=1234, dport=48879) /
1806 VXLAN(vni=99, gpid=113, flags=0x88, gpflags='A') /
1807 Ether(src=l['mac'], dst=ep.mac) /
1808 IP(src=l['ip'], dst=ep.ip4.address) /
1809 UDP(sport=1234, dport=1234) /
1812 rx = self.send_and_expect(self.pg2, p*65, self.pg0)
1814 self.assertTrue(find_gbp_endpoint(self,
1815 vx_tun_l2_1.sw_if_index,
1819 # Add the contract so they can talk
1821 acl = VppGbpAcl(self)
1822 rule = acl.create_rule(permit_deny=1, proto=17)
1823 rule2 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
1824 acl_index = acl.add_vpp_config([rule, rule2])
1825 c1 = VppGbpContract(
1826 self, epg_220.sclass, epg_330.sclass, acl_index,
1827 [VppGbpContractRule(
1828 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1831 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1833 [ETH_P_IP, ETH_P_IPV6])
1837 p = (Ether(src=ep.mac, dst=l['mac']) /
1838 IP(dst=l['ip'], src=ep.ip4.address) /
1839 UDP(sport=1234, dport=1234) /
1842 self.send_and_expect(self.pg0, [p], self.pg2)
1845 # send UU packets from the local EP
1847 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1848 self.logger.info(self.vapi.cli("sh gbp bridge"))
1849 p_uu = (Ether(src=ep.mac, dst="00:11:11:11:11:11") /
1850 IP(dst="10.0.0.133", src=ep.ip4.address) /
1851 UDP(sport=1234, dport=1234) /
1853 rxs = self.send_and_expect(ep.itf, [p_uu], gbd1.uu_fwd)
1855 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1857 p_bm = (Ether(src=ep.mac, dst="ff:ff:ff:ff:ff:ff") /
1858 IP(dst="10.0.0.133", src=ep.ip4.address) /
1859 UDP(sport=1234, dport=1234) /
1861 rxs = self.send_and_expect_only(ep.itf, [p_bm], tun_bm.mcast_itf)
1864 self.assertEqual(rx[IP].src, self.pg4.local_ip4)
1865 self.assertEqual(rx[IP].dst, "239.1.1.1")
1866 self.assertEqual(rx[UDP].dport, 48879)
1867 # the UDP source port is a random value for hashing
1868 self.assertEqual(rx[VXLAN].gpid, 112)
1869 self.assertEqual(rx[VXLAN].vni, 88)
1870 self.assertTrue(rx[VXLAN].flags.G)
1871 self.assertTrue(rx[VXLAN].flags.Instance)
1872 self.assertFalse(rx[VXLAN].gpflags.A)
1873 self.assertFalse(rx[VXLAN].gpflags.D)
1876 # Check v6 Endpoints
1879 # a packet with an sclass from a known EPG
1880 p = (Ether(src=self.pg2.remote_mac,
1881 dst=self.pg2.local_mac) /
1882 IP(src=self.pg2.remote_hosts[1].ip4,
1883 dst=self.pg2.local_ip4) /
1884 UDP(sport=1234, dport=48879) /
1885 VXLAN(vni=99, gpid=113, flags=0x88, gpflags='A') /
1886 Ether(src=l['mac'], dst=ep.mac) /
1887 IPv6(src=l['ip6'], dst=ep.ip6.address) /
1888 UDP(sport=1234, dport=1234) /
1891 rx = self.send_and_expect(self.pg2, p*65, self.pg0)
1893 self.assertTrue(find_gbp_endpoint(self,
1894 vx_tun_l2_1.sw_if_index,
1898 # L3 Endpoint Learning
1899 # - configured on the bridge's BVI
1906 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1909 self.pg2.unconfig_ip4()
1910 self.pg3.unconfig_ip4()
1911 self.pg4.unconfig_ip4()
1913 self.logger.info(self.vapi.cli("sh int"))
1914 self.logger.info(self.vapi.cli("sh gbp vxlan"))
1916 def test_gbp_learn_vlan_l2(self):
1917 """ GBP L2 Endpoint w/ VLANs"""
1919 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
1920 learnt = [{'mac': '00:00:11:11:11:01',
1922 'ip6': '2001:10::2'},
1923 {'mac': '00:00:11:11:11:02',
1925 'ip6': '2001:10::3'}]
1930 gt4 = VppIpTable(self, 1)
1931 gt4.add_vpp_config()
1932 gt6 = VppIpTable(self, 1, is_ip6=True)
1933 gt6.add_vpp_config()
1935 rd1 = VppGbpRouteDomain(self, 1, gt4, gt6)
1936 rd1.add_vpp_config()
1939 # Pg2 hosts the vxlan tunnel, hosts on pg2 to act as TEPs
1941 self.pg2.config_ip4()
1942 self.pg2.resolve_arp()
1943 self.pg2.generate_remote_hosts(4)
1944 self.pg2.configure_ipv4_neighbors()
1945 self.pg3.config_ip4()
1946 self.pg3.resolve_arp()
1949 # The EP will be on a vlan sub-interface
1951 vlan_11 = VppDot1QSubint(self, self.pg0, 11)
1953 self.vapi.l2_interface_vlan_tag_rewrite(
1954 sw_if_index=vlan_11.sw_if_index, vtr_op=L2_VTR_OP.L2_POP_1,
1957 bd_uu_fwd = VppVxlanGbpTunnel(self, self.pg3.local_ip4,
1958 self.pg3.remote_ip4, 116)
1959 bd_uu_fwd.add_vpp_config()
1962 # a GBP bridge domain with a BVI and a UU-flood interface
1963 # The BD is marked as do not learn, so no endpoints are ever
1964 # learnt in this BD.
1966 bd1 = VppBridgeDomain(self, 1)
1967 bd1.add_vpp_config()
1968 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0, bd_uu_fwd,
1970 gbd1.add_vpp_config()
1972 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1973 self.logger.info(self.vapi.cli("sh gbp bridge"))
1975 # ... and has a /32 applied
1976 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
1977 ip_addr.add_vpp_config()
1980 # The Endpoint-group in which we are learning endpoints
1982 epg_220 = VppGbpEndpointGroup(self, 220, 441, rd1, gbd1,
1986 VppGbpEndpointRetention(2))
1987 epg_220.add_vpp_config()
1990 # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
1993 vx_tun_l2_1 = VppGbpVxlanTunnel(
1994 self, 99, bd1.bd_id,
1995 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L2,
1997 vx_tun_l2_1.add_vpp_config()
2000 # A static endpoint that the learnt endpoints are trying to
2003 ep = VppGbpEndpoint(self, vlan_11,
2005 "10.0.0.127", "11.0.0.127",
2006 "2001:10::1", "3001::1")
2009 self.assertTrue(find_route(self, ep.ip4.address, 32, table_id=1))
2012 # Send to the static EP
2014 for ii, l in enumerate(learnt):
2015 # a packet with an sclass from a known EPG
2016 # arriving on an unknown TEP
2017 p = (Ether(src=self.pg2.remote_mac,
2018 dst=self.pg2.local_mac) /
2019 IP(src=self.pg2.remote_hosts[1].ip4,
2020 dst=self.pg2.local_ip4) /
2021 UDP(sport=1234, dport=48879) /
2022 VXLAN(vni=99, gpid=441, flags=0x88) /
2023 Ether(src=l['mac'], dst=ep.mac) /
2024 IP(src=l['ip'], dst=ep.ip4.address) /
2025 UDP(sport=1234, dport=1234) /
2028 rxs = self.send_and_expect(self.pg2, [p], self.pg0)
2031 # packet to EP has the EP's vlan tag
2034 self.assertEqual(rx[Dot1Q].vlan, 11)
2037 # the EP is not learnt since the BD setting prevents it
2040 self.assertFalse(find_gbp_endpoint(self,
2041 vx_tun_l2_1.sw_if_index,
2043 self.assertEqual(INDEX_INVALID,
2044 find_vxlan_gbp_tunnel(
2047 self.pg2.remote_hosts[1].ip4,
2050 self.assertEqual(len(self.vapi.gbp_endpoint_dump()), 1)
2054 # we didn't learn the remotes so they are sent to the UU-fwd
2057 p = (Ether(src=ep.mac, dst=l['mac']) /
2059 IP(dst=l['ip'], src=ep.ip4.address) /
2060 UDP(sport=1234, dport=1234) /
2063 rxs = self.send_and_expect(self.pg0, p * 17, self.pg3)
2066 self.assertEqual(rx[IP].src, self.pg3.local_ip4)
2067 self.assertEqual(rx[IP].dst, self.pg3.remote_ip4)
2068 self.assertEqual(rx[UDP].dport, 48879)
2069 # the UDP source port is a random value for hashing
2070 self.assertEqual(rx[VXLAN].gpid, 441)
2071 self.assertEqual(rx[VXLAN].vni, 116)
2072 self.assertTrue(rx[VXLAN].flags.G)
2073 self.assertTrue(rx[VXLAN].flags.Instance)
2074 self.assertFalse(rx[VXLAN].gpflags.A)
2075 self.assertFalse(rx[VXLAN].gpflags.D)
2077 self.pg2.unconfig_ip4()
2078 self.pg3.unconfig_ip4()
2080 def test_gbp_learn_l3(self):
2081 """ GBP L3 Endpoint Learning """
2083 self.vapi.cli("set logging class gbp debug")
2085 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
2086 routed_dst_mac = "00:0c:0c:0c:0c:0c"
2087 routed_src_mac = "00:22:bd:f8:19:ff"
2089 learnt = [{'mac': '00:00:11:11:11:02',
2091 'ip6': '2001:10::2'},
2092 {'mac': '00:00:11:11:11:03',
2094 'ip6': '2001:10::3'}]
2099 t4 = VppIpTable(self, 1)
2101 t6 = VppIpTable(self, 1, True)
2104 tun_ip4_uu = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
2105 self.pg4.remote_ip4, 114)
2106 tun_ip6_uu = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
2107 self.pg4.remote_ip4, 116)
2108 tun_ip4_uu.add_vpp_config()
2109 tun_ip6_uu.add_vpp_config()
2111 rd1 = VppGbpRouteDomain(self, 2, t4, t6, tun_ip4_uu, tun_ip6_uu)
2112 rd1.add_vpp_config()
2114 self.loop0.set_mac(self.router_mac)
2117 # Bind the BVI to the RD
2119 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
2120 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
2123 # Pg2 hosts the vxlan tunnel
2124 # hosts on pg2 to act as TEPs
2128 self.pg2.config_ip4()
2129 self.pg2.resolve_arp()
2130 self.pg2.generate_remote_hosts(4)
2131 self.pg2.configure_ipv4_neighbors()
2132 self.pg3.config_ip4()
2133 self.pg3.resolve_arp()
2134 self.pg4.config_ip4()
2135 self.pg4.resolve_arp()
2138 # a GBP bridge domain with a BVI and a UU-flood interface
2140 bd1 = VppBridgeDomain(self, 1)
2141 bd1.add_vpp_config()
2142 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0, self.pg3)
2143 gbd1.add_vpp_config()
2145 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2146 self.logger.info(self.vapi.cli("sh gbp bridge"))
2147 self.logger.info(self.vapi.cli("sh gbp route"))
2149 # ... and has a /32 and /128 applied
2150 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2151 ip4_addr.add_vpp_config()
2152 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 128)
2153 ip6_addr.add_vpp_config()
2156 # The Endpoint-group in which we are learning endpoints
2158 epg_220 = VppGbpEndpointGroup(self, 220, 441, rd1, gbd1,
2162 VppGbpEndpointRetention(2))
2163 epg_220.add_vpp_config()
2166 # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
2169 vx_tun_l3 = VppGbpVxlanTunnel(
2170 self, 101, rd1.rd_id,
2171 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
2173 vx_tun_l3.add_vpp_config()
2176 # A static endpoint that the learnt endpoints are trying to
2179 ep = VppGbpEndpoint(self, self.pg0,
2181 "10.0.0.127", "11.0.0.127",
2182 "2001:10::1", "3001::1")
2186 # learn some remote IPv4 EPs
2188 for ii, l in enumerate(learnt):
2189 # a packet with an sclass from a known EPG
2190 # arriving on an unknown TEP
2191 p = (Ether(src=self.pg2.remote_mac,
2192 dst=self.pg2.local_mac) /
2193 IP(src=self.pg2.remote_hosts[1].ip4,
2194 dst=self.pg2.local_ip4) /
2195 UDP(sport=1234, dport=48879) /
2196 VXLAN(vni=101, gpid=441, flags=0x88) /
2197 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2198 IP(src=l['ip'], dst=ep.ip4.address) /
2199 UDP(sport=1234, dport=1234) /
2202 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2205 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2208 self.pg2.remote_hosts[1].ip4,
2210 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2212 # endpoint learnt via the parent GBP-vxlan interface
2213 self.assertTrue(find_gbp_endpoint(self,
2214 vx_tun_l3._sw_if_index,
2218 # Static IPv4 EP replies to learnt
2221 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2222 IP(dst=l['ip'], src=ep.ip4.address) /
2223 UDP(sport=1234, dport=1234) /
2226 rxs = self.send_and_expect(self.pg0, p*1, self.pg2)
2229 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2230 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2231 self.assertEqual(rx[UDP].dport, 48879)
2232 # the UDP source port is a random value for hashing
2233 self.assertEqual(rx[VXLAN].gpid, 441)
2234 self.assertEqual(rx[VXLAN].vni, 101)
2235 self.assertTrue(rx[VXLAN].flags.G)
2236 self.assertTrue(rx[VXLAN].flags.Instance)
2237 self.assertTrue(rx[VXLAN].gpflags.A)
2238 self.assertFalse(rx[VXLAN].gpflags.D)
2240 inner = rx[VXLAN].payload
2242 self.assertEqual(inner[Ether].src, routed_src_mac)
2243 self.assertEqual(inner[Ether].dst, routed_dst_mac)
2244 self.assertEqual(inner[IP].src, ep.ip4.address)
2245 self.assertEqual(inner[IP].dst, l['ip'])
2248 self.assertFalse(find_gbp_endpoint(self,
2253 # learn some remote IPv6 EPs
2255 for ii, l in enumerate(learnt):
2256 # a packet with an sclass from a known EPG
2257 # arriving on an unknown TEP
2258 p = (Ether(src=self.pg2.remote_mac,
2259 dst=self.pg2.local_mac) /
2260 IP(src=self.pg2.remote_hosts[1].ip4,
2261 dst=self.pg2.local_ip4) /
2262 UDP(sport=1234, dport=48879) /
2263 VXLAN(vni=101, gpid=441, flags=0x88) /
2264 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2265 IPv6(src=l['ip6'], dst=ep.ip6.address) /
2266 UDP(sport=1234, dport=1234) /
2269 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2272 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2275 self.pg2.remote_hosts[1].ip4,
2277 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2279 self.logger.info(self.vapi.cli("show gbp bridge"))
2280 self.logger.info(self.vapi.cli("show vxlan-gbp tunnel"))
2281 self.logger.info(self.vapi.cli("show gbp vxlan"))
2282 self.logger.info(self.vapi.cli("show int addr"))
2284 # endpoint learnt via the TEP
2285 self.assertTrue(find_gbp_endpoint(self, ip=l['ip6']))
2287 self.logger.info(self.vapi.cli("show gbp endpoint"))
2288 self.logger.info(self.vapi.cli("show ip fib index 1 %s" % l['ip']))
2291 # Static EP replies to learnt
2294 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2295 IPv6(dst=l['ip6'], src=ep.ip6.address) /
2296 UDP(sport=1234, dport=1234) /
2299 rxs = self.send_and_expect(self.pg0, p*65, self.pg2)
2302 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2303 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2304 self.assertEqual(rx[UDP].dport, 48879)
2305 # the UDP source port is a random value for hashing
2306 self.assertEqual(rx[VXLAN].gpid, 441)
2307 self.assertEqual(rx[VXLAN].vni, 101)
2308 self.assertTrue(rx[VXLAN].flags.G)
2309 self.assertTrue(rx[VXLAN].flags.Instance)
2310 self.assertTrue(rx[VXLAN].gpflags.A)
2311 self.assertFalse(rx[VXLAN].gpflags.D)
2313 inner = rx[VXLAN].payload
2315 self.assertEqual(inner[Ether].src, routed_src_mac)
2316 self.assertEqual(inner[Ether].dst, routed_dst_mac)
2317 self.assertEqual(inner[IPv6].src, ep.ip6.address)
2318 self.assertEqual(inner[IPv6].dst, l['ip6'])
2320 self.logger.info(self.vapi.cli("sh gbp endpoint"))
2322 self.wait_for_ep_timeout(ip=l['ip'])
2325 # Static sends to unknown EP with no route
2327 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2328 IP(dst="10.0.0.99", src=ep.ip4.address) /
2329 UDP(sport=1234, dport=1234) /
2332 self.send_and_assert_no_replies(self.pg0, [p])
2335 # Add a route to static EP's v4 and v6 subnet
2336 # packets should be sent on the v4/v6 uu=fwd interface resp.
2338 se_10_24 = VppGbpSubnet(
2339 self, rd1, "10.0.0.0", 24,
2340 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT)
2341 se_10_24.add_vpp_config()
2343 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2344 IP(dst="10.0.0.99", src=ep.ip4.address) /
2345 UDP(sport=1234, dport=1234) /
2348 rxs = self.send_and_expect(self.pg0, [p], self.pg4)
2350 self.assertEqual(rx[IP].src, self.pg4.local_ip4)
2351 self.assertEqual(rx[IP].dst, self.pg4.remote_ip4)
2352 self.assertEqual(rx[UDP].dport, 48879)
2353 # the UDP source port is a random value for hashing
2354 self.assertEqual(rx[VXLAN].gpid, 441)
2355 self.assertEqual(rx[VXLAN].vni, 114)
2356 self.assertTrue(rx[VXLAN].flags.G)
2357 self.assertTrue(rx[VXLAN].flags.Instance)
2358 # policy is not applied to packets sent to the uu-fwd interfaces
2359 self.assertFalse(rx[VXLAN].gpflags.A)
2360 self.assertFalse(rx[VXLAN].gpflags.D)
2363 # learn some remote IPv4 EPs
2365 for ii, l in enumerate(learnt):
2366 # a packet with an sclass from a known EPG
2367 # arriving on an unknown TEP
2368 p = (Ether(src=self.pg2.remote_mac,
2369 dst=self.pg2.local_mac) /
2370 IP(src=self.pg2.remote_hosts[2].ip4,
2371 dst=self.pg2.local_ip4) /
2372 UDP(sport=1234, dport=48879) /
2373 VXLAN(vni=101, gpid=441, flags=0x88) /
2374 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2375 IP(src=l['ip'], dst=ep.ip4.address) /
2376 UDP(sport=1234, dport=1234) /
2379 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2382 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2385 self.pg2.remote_hosts[2].ip4,
2387 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2389 # endpoint learnt via the parent GBP-vxlan interface
2390 self.assertTrue(find_gbp_endpoint(self,
2391 vx_tun_l3._sw_if_index,
2395 # Add a remote endpoint from the API
2397 rep_88 = VppGbpEndpoint(self, vx_tun_l3,
2399 "10.0.0.88", "11.0.0.88",
2400 "2001:10::88", "3001::88",
2401 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
2403 self.pg2.remote_hosts[1].ip4,
2405 rep_88.add_vpp_config()
2408 # Add a remote endpoint from the API that matches an existing one
2410 rep_2 = VppGbpEndpoint(self, vx_tun_l3,
2412 learnt[0]['ip'], "11.0.0.101",
2413 learnt[0]['ip6'], "3001::101",
2414 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
2416 self.pg2.remote_hosts[1].ip4,
2418 rep_2.add_vpp_config()
2421 # Add a route to the learned EP's v4 subnet
2422 # packets should be send on the v4/v6 uu=fwd interface resp.
2424 se_10_1_24 = VppGbpSubnet(
2425 self, rd1, "10.0.1.0", 24,
2426 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT)
2427 se_10_1_24.add_vpp_config()
2429 self.logger.info(self.vapi.cli("show gbp endpoint"))
2431 ips = ["10.0.0.88", learnt[0]['ip']]
2433 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2434 IP(dst=ip, src=ep.ip4.address) /
2435 UDP(sport=1234, dport=1234) /
2438 rxs = self.send_and_expect(self.pg0, p*65, self.pg2)
2441 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2442 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2443 self.assertEqual(rx[UDP].dport, 48879)
2444 # the UDP source port is a random value for hashing
2445 self.assertEqual(rx[VXLAN].gpid, 441)
2446 self.assertEqual(rx[VXLAN].vni, 101)
2447 self.assertTrue(rx[VXLAN].flags.G)
2448 self.assertTrue(rx[VXLAN].flags.Instance)
2449 self.assertTrue(rx[VXLAN].gpflags.A)
2450 self.assertFalse(rx[VXLAN].gpflags.D)
2452 inner = rx[VXLAN].payload
2454 self.assertEqual(inner[Ether].src, routed_src_mac)
2455 self.assertEqual(inner[Ether].dst, routed_dst_mac)
2456 self.assertEqual(inner[IP].src, ep.ip4.address)
2457 self.assertEqual(inner[IP].dst, ip)
2460 # remove the API remote EPs, only API sourced is gone, the DP
2461 # learnt one remains
2463 rep_88.remove_vpp_config()
2464 rep_2.remove_vpp_config()
2466 self.assertTrue(find_gbp_endpoint(self, ip=rep_2.ip4.address))
2468 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2469 IP(src=ep.ip4.address, dst=rep_2.ip4.address) /
2470 UDP(sport=1234, dport=1234) /
2472 rxs = self.send_and_expect(self.pg0, [p], self.pg2)
2474 self.assertFalse(find_gbp_endpoint(self, ip=rep_88.ip4.address))
2476 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2477 IP(src=ep.ip4.address, dst=rep_88.ip4.address) /
2478 UDP(sport=1234, dport=1234) /
2480 rxs = self.send_and_expect(self.pg0, [p], self.pg4)
2483 # to appease the testcase we cannot have the registered EP still
2484 # present (because it's DP learnt) when the TC ends so wait until
2487 self.wait_for_ep_timeout(ip=rep_88.ip4.address)
2488 self.wait_for_ep_timeout(ip=rep_2.ip4.address)
2491 # shutdown with learnt endpoint present
2493 p = (Ether(src=self.pg2.remote_mac,
2494 dst=self.pg2.local_mac) /
2495 IP(src=self.pg2.remote_hosts[1].ip4,
2496 dst=self.pg2.local_ip4) /
2497 UDP(sport=1234, dport=48879) /
2498 VXLAN(vni=101, gpid=441, flags=0x88) /
2499 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2500 IP(src=learnt[1]['ip'], dst=ep.ip4.address) /
2501 UDP(sport=1234, dport=1234) /
2504 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2506 # endpoint learnt via the parent GBP-vxlan interface
2507 self.assertTrue(find_gbp_endpoint(self,
2508 vx_tun_l3._sw_if_index,
2513 # remote endpoint becomes local
2515 self.pg2.unconfig_ip4()
2516 self.pg3.unconfig_ip4()
2517 self.pg4.unconfig_ip4()
2519 def test_gbp_redirect(self):
2520 """ GBP Endpoint Redirect """
2522 self.vapi.cli("set logging class gbp debug")
2524 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
2525 routed_dst_mac = "00:0c:0c:0c:0c:0c"
2526 routed_src_mac = "00:22:bd:f8:19:ff"
2528 learnt = [{'mac': '00:00:11:11:11:02',
2530 'ip6': '2001:10::2'},
2531 {'mac': '00:00:11:11:11:03',
2533 'ip6': '2001:10::3'}]
2538 t4 = VppIpTable(self, 1)
2540 t6 = VppIpTable(self, 1, True)
2543 rd1 = VppGbpRouteDomain(self, 2, t4, t6)
2544 rd1.add_vpp_config()
2546 self.loop0.set_mac(self.router_mac)
2549 # Bind the BVI to the RD
2551 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
2552 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
2555 # Pg7 hosts a BD's UU-fwd
2557 self.pg7.config_ip4()
2558 self.pg7.resolve_arp()
2561 # a GBP bridge domains for the EPs
2563 bd1 = VppBridgeDomain(self, 1)
2564 bd1.add_vpp_config()
2565 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0)
2566 gbd1.add_vpp_config()
2568 bd2 = VppBridgeDomain(self, 2)
2569 bd2.add_vpp_config()
2570 gbd2 = VppGbpBridgeDomain(self, bd2, self.loop1)
2571 gbd2.add_vpp_config()
2573 # ... and has a /32 and /128 applied
2574 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2575 ip4_addr.add_vpp_config()
2576 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 128)
2577 ip6_addr.add_vpp_config()
2578 ip4_addr = VppIpInterfaceAddress(self, gbd2.bvi, "10.0.1.128", 32)
2579 ip4_addr.add_vpp_config()
2580 ip6_addr = VppIpInterfaceAddress(self, gbd2.bvi, "2001:11::128", 128)
2581 ip6_addr.add_vpp_config()
2584 # The Endpoint-groups in which we are learning endpoints
2586 epg_220 = VppGbpEndpointGroup(self, 220, 440, rd1, gbd1,
2590 VppGbpEndpointRetention(2))
2591 epg_220.add_vpp_config()
2592 epg_221 = VppGbpEndpointGroup(self, 221, 441, rd1, gbd2,
2596 VppGbpEndpointRetention(2))
2597 epg_221.add_vpp_config()
2598 epg_222 = VppGbpEndpointGroup(self, 222, 442, rd1, gbd1,
2602 VppGbpEndpointRetention(2))
2603 epg_222.add_vpp_config()
2606 # a GBP bridge domains for the SEPs
2608 bd_uu1 = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
2609 self.pg7.remote_ip4, 116)
2610 bd_uu1.add_vpp_config()
2611 bd_uu2 = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
2612 self.pg7.remote_ip4, 117)
2613 bd_uu2.add_vpp_config()
2615 bd3 = VppBridgeDomain(self, 3)
2616 bd3.add_vpp_config()
2617 gbd3 = VppGbpBridgeDomain(self, bd3, self.loop2, bd_uu1, learn=False)
2618 gbd3.add_vpp_config()
2619 bd4 = VppBridgeDomain(self, 4)
2620 bd4.add_vpp_config()
2621 gbd4 = VppGbpBridgeDomain(self, bd4, self.loop3, bd_uu2, learn=False)
2622 gbd4.add_vpp_config()
2625 # EPGs in which the service endpoints exist
2627 epg_320 = VppGbpEndpointGroup(self, 320, 550, rd1, gbd3,
2631 VppGbpEndpointRetention(2))
2632 epg_320.add_vpp_config()
2633 epg_321 = VppGbpEndpointGroup(self, 321, 551, rd1, gbd4,
2637 VppGbpEndpointRetention(2))
2638 epg_321.add_vpp_config()
2641 # three local endpoints
2643 ep1 = VppGbpEndpoint(self, self.pg0,
2645 "10.0.0.1", "11.0.0.1",
2646 "2001:10::1", "3001:10::1")
2647 ep1.add_vpp_config()
2648 ep2 = VppGbpEndpoint(self, self.pg1,
2650 "10.0.1.1", "11.0.1.1",
2651 "2001:11::1", "3001:11::1")
2652 ep2.add_vpp_config()
2653 ep3 = VppGbpEndpoint(self, self.pg2,
2655 "10.0.2.2", "11.0.2.2",
2656 "2001:12::1", "3001:12::1")
2657 ep3.add_vpp_config()
2662 sep1 = VppGbpEndpoint(self, self.pg3,
2664 "12.0.0.1", "13.0.0.1",
2665 "4001:10::1", "5001:10::1")
2666 sep1.add_vpp_config()
2667 sep2 = VppGbpEndpoint(self, self.pg4,
2669 "12.0.0.2", "13.0.0.2",
2670 "4001:10::2", "5001:10::2")
2671 sep2.add_vpp_config()
2672 sep3 = VppGbpEndpoint(self, self.pg5,
2674 "12.0.1.1", "13.0.1.1",
2675 "4001:11::1", "5001:11::1")
2676 sep3.add_vpp_config()
2677 # this EP is not installed immediately
2678 sep4 = VppGbpEndpoint(self, self.pg6,
2680 "12.0.1.2", "13.0.1.2",
2681 "4001:11::2", "5001:11::2")
2684 # an L2 switch packet between local EPs in different EPGs
2685 # different dest ports on each so the are LB hashed differently
2687 p4 = [(Ether(src=ep1.mac, dst=ep3.mac) /
2688 IP(src=ep1.ip4.address, dst=ep3.ip4.address) /
2689 UDP(sport=1234, dport=1234) /
2691 (Ether(src=ep3.mac, dst=ep1.mac) /
2692 IP(src=ep3.ip4.address, dst=ep1.ip4.address) /
2693 UDP(sport=1234, dport=1234) /
2695 p6 = [(Ether(src=ep1.mac, dst=ep3.mac) /
2696 IPv6(src=ep1.ip6.address, dst=ep3.ip6.address) /
2697 UDP(sport=1234, dport=1234) /
2699 (Ether(src=ep3.mac, dst=ep1.mac) /
2700 IPv6(src=ep3.ip6.address, dst=ep1.ip6.address) /
2701 UDP(sport=1234, dport=1230) /
2704 # should be dropped since no contract yet
2705 self.send_and_assert_no_replies(self.pg0, [p4[0]])
2706 self.send_and_assert_no_replies(self.pg0, [p6[0]])
2709 # Add a contract with a rule to load-balance redirect via SEP1 and SEP2
2710 # one of the next-hops is via an EP that is not known
2712 acl = VppGbpAcl(self)
2713 rule4 = acl.create_rule(permit_deny=1, proto=17)
2714 rule6 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
2715 acl_index = acl.add_vpp_config([rule4, rule6])
2718 # test the src-ip hash mode
2720 c1 = VppGbpContract(
2721 self, epg_220.sclass, epg_222.sclass, acl_index,
2722 [VppGbpContractRule(
2723 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2724 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2725 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
2726 sep1.ip4, sep1.epg.rd),
2727 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
2728 sep2.ip4, sep2.epg.rd)]),
2730 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2731 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2732 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
2733 sep3.ip6, sep3.epg.rd),
2734 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
2735 sep4.ip6, sep4.epg.rd)])],
2736 [ETH_P_IP, ETH_P_IPV6])
2739 c2 = VppGbpContract(
2740 self, epg_222.sclass, epg_220.sclass, acl_index,
2741 [VppGbpContractRule(
2742 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2743 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2744 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
2745 sep1.ip4, sep1.epg.rd),
2746 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
2747 sep2.ip4, sep2.epg.rd)]),
2749 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2750 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2751 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
2752 sep3.ip6, sep3.epg.rd),
2753 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
2754 sep4.ip6, sep4.epg.rd)])],
2755 [ETH_P_IP, ETH_P_IPV6])
2759 # send again with the contract preset, now packets arrive
2760 # at SEP1 or SEP2 depending on the hashing
2762 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
2765 self.assertEqual(rx[Ether].src, routed_src_mac)
2766 self.assertEqual(rx[Ether].dst, sep1.mac)
2767 self.assertEqual(rx[IP].src, ep1.ip4.address)
2768 self.assertEqual(rx[IP].dst, ep3.ip4.address)
2770 rxs = self.send_and_expect(self.pg2, p4[1] * 17, sep2.itf)
2773 self.assertEqual(rx[Ether].src, routed_src_mac)
2774 self.assertEqual(rx[Ether].dst, sep2.mac)
2775 self.assertEqual(rx[IP].src, ep3.ip4.address)
2776 self.assertEqual(rx[IP].dst, ep1.ip4.address)
2778 rxs = self.send_and_expect(self.pg0, p6[0] * 17, self.pg7)
2781 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
2782 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
2783 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
2784 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
2785 self.assertEqual(rx[VXLAN].vni, 117)
2786 self.assertTrue(rx[VXLAN].flags.G)
2787 self.assertTrue(rx[VXLAN].flags.Instance)
2788 # redirect policy has been applied
2789 self.assertTrue(rx[VXLAN].gpflags.A)
2790 self.assertFalse(rx[VXLAN].gpflags.D)
2792 inner = rx[VXLAN].payload
2794 self.assertEqual(inner[Ether].src, routed_src_mac)
2795 self.assertEqual(inner[Ether].dst, sep4.mac)
2796 self.assertEqual(inner[IPv6].src, ep1.ip6.address)
2797 self.assertEqual(inner[IPv6].dst, ep3.ip6.address)
2799 rxs = self.send_and_expect(self.pg2, p6[1] * 17, sep3.itf)
2802 self.assertEqual(rx[Ether].src, routed_src_mac)
2803 self.assertEqual(rx[Ether].dst, sep3.mac)
2804 self.assertEqual(rx[IPv6].src, ep3.ip6.address)
2805 self.assertEqual(rx[IPv6].dst, ep1.ip6.address)
2808 # programme the unknown EP
2810 sep4.add_vpp_config()
2812 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep4.itf)
2815 self.assertEqual(rx[Ether].src, routed_src_mac)
2816 self.assertEqual(rx[Ether].dst, sep4.mac)
2817 self.assertEqual(rx[IPv6].src, ep1.ip6.address)
2818 self.assertEqual(rx[IPv6].dst, ep3.ip6.address)
2821 # and revert back to unprogrammed
2823 sep4.remove_vpp_config()
2825 rxs = self.send_and_expect(self.pg0, p6[0] * 17, self.pg7)
2828 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
2829 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
2830 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
2831 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
2832 self.assertEqual(rx[VXLAN].vni, 117)
2833 self.assertTrue(rx[VXLAN].flags.G)
2834 self.assertTrue(rx[VXLAN].flags.Instance)
2835 # redirect policy has been applied
2836 self.assertTrue(rx[VXLAN].gpflags.A)
2837 self.assertFalse(rx[VXLAN].gpflags.D)
2839 inner = rx[VXLAN].payload
2841 self.assertEqual(inner[Ether].src, routed_src_mac)
2842 self.assertEqual(inner[Ether].dst, sep4.mac)
2843 self.assertEqual(inner[IPv6].src, ep1.ip6.address)
2844 self.assertEqual(inner[IPv6].dst, ep3.ip6.address)
2846 c1.remove_vpp_config()
2847 c2.remove_vpp_config()
2850 # test the symmetric hash mode
2852 c1 = VppGbpContract(
2853 self, epg_220.sclass, epg_222.sclass, acl_index,
2854 [VppGbpContractRule(
2855 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2856 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
2857 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
2858 sep1.ip4, sep1.epg.rd),
2859 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
2860 sep2.ip4, sep2.epg.rd)]),
2862 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2863 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
2864 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
2865 sep3.ip6, sep3.epg.rd),
2866 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
2867 sep4.ip6, sep4.epg.rd)])],
2868 [ETH_P_IP, ETH_P_IPV6])
2871 c2 = VppGbpContract(
2872 self, epg_222.sclass, epg_220.sclass, acl_index,
2873 [VppGbpContractRule(
2874 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2875 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
2876 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
2877 sep1.ip4, sep1.epg.rd),
2878 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
2879 sep2.ip4, sep2.epg.rd)]),
2881 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2882 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
2883 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
2884 sep3.ip6, sep3.epg.rd),
2885 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
2886 sep4.ip6, sep4.epg.rd)])],
2887 [ETH_P_IP, ETH_P_IPV6])
2891 # send again with the contract preset, now packets arrive
2892 # at SEP1 for both directions
2894 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
2897 self.assertEqual(rx[Ether].src, routed_src_mac)
2898 self.assertEqual(rx[Ether].dst, sep1.mac)
2899 self.assertEqual(rx[IP].src, ep1.ip4.address)
2900 self.assertEqual(rx[IP].dst, ep3.ip4.address)
2902 rxs = self.send_and_expect(self.pg2, p4[1] * 17, sep1.itf)
2905 self.assertEqual(rx[Ether].src, routed_src_mac)
2906 self.assertEqual(rx[Ether].dst, sep1.mac)
2907 self.assertEqual(rx[IP].src, ep3.ip4.address)
2908 self.assertEqual(rx[IP].dst, ep1.ip4.address)
2911 # programme the unknown EP for the L3 tests
2913 sep4.add_vpp_config()
2916 # an L3 switch packet between local EPs in different EPGs
2917 # different dest ports on each so the are LB hashed differently
2919 p4 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
2920 IP(src=ep1.ip4.address, dst=ep2.ip4.address) /
2921 UDP(sport=1234, dport=1234) /
2923 (Ether(src=ep2.mac, dst=str(self.router_mac)) /
2924 IP(src=ep2.ip4.address, dst=ep1.ip4.address) /
2925 UDP(sport=1234, dport=1234) /
2927 p6 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
2928 IPv6(src=ep1.ip6.address, dst=ep2.ip6.address) /
2929 UDP(sport=1234, dport=1234) /
2931 (Ether(src=ep2.mac, dst=str(self.router_mac)) /
2932 IPv6(src=ep2.ip6.address, dst=ep1.ip6.address) /
2933 UDP(sport=1234, dport=1234) /
2936 c3 = VppGbpContract(
2937 self, epg_220.sclass, epg_221.sclass, acl_index,
2938 [VppGbpContractRule(
2939 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2940 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
2941 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
2942 sep1.ip4, sep1.epg.rd),
2943 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
2944 sep2.ip4, sep2.epg.rd)]),
2946 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2947 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
2948 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
2949 sep3.ip6, sep3.epg.rd),
2950 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
2951 sep4.ip6, sep4.epg.rd)])],
2952 [ETH_P_IP, ETH_P_IPV6])
2955 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
2958 self.assertEqual(rx[Ether].src, routed_src_mac)
2959 self.assertEqual(rx[Ether].dst, sep1.mac)
2960 self.assertEqual(rx[IP].src, ep1.ip4.address)
2961 self.assertEqual(rx[IP].dst, ep2.ip4.address)
2964 # learn a remote EP in EPG 221
2966 vx_tun_l3 = VppGbpVxlanTunnel(
2967 self, 444, rd1.rd_id,
2968 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
2970 vx_tun_l3.add_vpp_config()
2972 c4 = VppGbpContract(
2973 self, epg_221.sclass, epg_220.sclass, acl_index,
2974 [VppGbpContractRule(
2975 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2978 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2980 [ETH_P_IP, ETH_P_IPV6])
2983 p = (Ether(src=self.pg7.remote_mac,
2984 dst=self.pg7.local_mac) /
2985 IP(src=self.pg7.remote_ip4,
2986 dst=self.pg7.local_ip4) /
2987 UDP(sport=1234, dport=48879) /
2988 VXLAN(vni=444, gpid=441, flags=0x88) /
2989 Ether(src="00:22:22:22:22:33", dst=str(self.router_mac)) /
2990 IP(src="10.0.0.88", dst=ep1.ip4.address) /
2991 UDP(sport=1234, dport=1234) /
2994 rx = self.send_and_expect(self.pg7, [p], self.pg0)
2996 # endpoint learnt via the parent GBP-vxlan interface
2997 self.assertTrue(find_gbp_endpoint(self,
2998 vx_tun_l3._sw_if_index,
3001 p = (Ether(src=self.pg7.remote_mac,
3002 dst=self.pg7.local_mac) /
3003 IP(src=self.pg7.remote_ip4,
3004 dst=self.pg7.local_ip4) /
3005 UDP(sport=1234, dport=48879) /
3006 VXLAN(vni=444, gpid=441, flags=0x88) /
3007 Ether(src="00:22:22:22:22:33", dst=str(self.router_mac)) /
3008 IPv6(src="2001:10::88", dst=ep1.ip6.address) /
3009 UDP(sport=1234, dport=1234) /
3012 rx = self.send_and_expect(self.pg7, [p], self.pg0)
3014 # endpoint learnt via the parent GBP-vxlan interface
3015 self.assertTrue(find_gbp_endpoint(self,
3016 vx_tun_l3._sw_if_index,
3020 # L3 switch from local to remote EP
3022 p4 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3023 IP(src=ep1.ip4.address, dst="10.0.0.88") /
3024 UDP(sport=1234, dport=1234) /
3026 p6 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3027 IPv6(src=ep1.ip6.address, dst="2001:10::88") /
3028 UDP(sport=1234, dport=1234) /
3031 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3034 self.assertEqual(rx[Ether].src, routed_src_mac)
3035 self.assertEqual(rx[Ether].dst, sep1.mac)
3036 self.assertEqual(rx[IP].src, ep1.ip4.address)
3037 self.assertEqual(rx[IP].dst, "10.0.0.88")
3039 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep4.itf)
3042 self.assertEqual(rx[Ether].src, routed_src_mac)
3043 self.assertEqual(rx[Ether].dst, sep4.mac)
3044 self.assertEqual(rx[IPv6].src, ep1.ip6.address)
3045 self.assertEqual(rx[IPv6].dst, "2001:10::88")
3048 # test the dst-ip hash mode
3050 c5 = VppGbpContract(
3051 self, epg_220.sclass, epg_221.sclass, acl_index,
3052 [VppGbpContractRule(
3053 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3054 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
3055 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3056 sep1.ip4, sep1.epg.rd),
3057 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3058 sep2.ip4, sep2.epg.rd)]),
3060 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3061 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
3062 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3063 sep3.ip6, sep3.epg.rd),
3064 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3065 sep4.ip6, sep4.epg.rd)])],
3066 [ETH_P_IP, ETH_P_IPV6])
3069 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3072 self.assertEqual(rx[Ether].src, routed_src_mac)
3073 self.assertEqual(rx[Ether].dst, sep1.mac)
3074 self.assertEqual(rx[IP].src, ep1.ip4.address)
3075 self.assertEqual(rx[IP].dst, "10.0.0.88")
3077 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep3.itf)
3080 self.assertEqual(rx[Ether].src, routed_src_mac)
3081 self.assertEqual(rx[Ether].dst, sep3.mac)
3082 self.assertEqual(rx[IPv6].src, ep1.ip6.address)
3083 self.assertEqual(rx[IPv6].dst, "2001:10::88")
3088 self.pg7.unconfig_ip4()
3090 def test_gbp_l3_out(self):
3093 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
3094 self.vapi.cli("set logging class gbp debug")
3096 routed_dst_mac = "00:0c:0c:0c:0c:0c"
3097 routed_src_mac = "00:22:bd:f8:19:ff"
3102 t4 = VppIpTable(self, 1)
3104 t6 = VppIpTable(self, 1, True)
3107 rd1 = VppGbpRouteDomain(self, 2, t4, t6)
3108 rd1.add_vpp_config()
3110 self.loop0.set_mac(self.router_mac)
3113 # Bind the BVI to the RD
3115 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
3116 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
3119 # Pg7 hosts a BD's BUM
3120 # Pg1 some other l3 interface
3122 self.pg7.config_ip4()
3123 self.pg7.resolve_arp()
3126 # a multicast vxlan-gbp tunnel for broadcast in the BD
3128 tun_bm = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
3131 tun_bm.add_vpp_config()
3134 # a GBP external bridge domains for the EPs
3136 bd1 = VppBridgeDomain(self, 1)
3137 bd1.add_vpp_config()
3138 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0, None, tun_bm)
3139 gbd1.add_vpp_config()
3142 # The Endpoint-groups in which the external endpoints exist
3144 epg_220 = VppGbpEndpointGroup(self, 220, 113, rd1, gbd1,
3148 VppGbpEndpointRetention(2))
3149 epg_220.add_vpp_config()
3151 # the BVIs have the subnets applied ...
3152 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 24)
3153 ip4_addr.add_vpp_config()
3154 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 64)
3155 ip6_addr.add_vpp_config()
3157 # ... which are L3-out subnets
3158 l3o_1 = VppGbpSubnet(
3159 self, rd1, "10.0.0.0", 24,
3160 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3162 l3o_1.add_vpp_config()
3165 # an external interface attached to the outside world and the
3168 vlan_100 = VppDot1QSubint(self, self.pg0, 100)
3170 VppL2Vtr(self, vlan_100, L2_VTR_OP.L2_POP_1).add_vpp_config()
3171 vlan_101 = VppDot1QSubint(self, self.pg0, 101)
3173 VppL2Vtr(self, vlan_101, L2_VTR_OP.L2_POP_1).add_vpp_config()
3175 ext_itf = VppGbpExtItf(self, self.loop0, bd1, rd1)
3176 ext_itf.add_vpp_config()
3179 # an unicast vxlan-gbp for inter-RD traffic
3181 vx_tun_l3 = VppGbpVxlanTunnel(
3182 self, 444, rd1.rd_id,
3183 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
3185 vx_tun_l3.add_vpp_config()
3188 # External Endpoints
3190 eep1 = VppGbpEndpoint(self, vlan_100,
3192 "10.0.0.1", "11.0.0.1",
3193 "2001:10::1", "3001::1",
3194 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
3195 eep1.add_vpp_config()
3196 eep2 = VppGbpEndpoint(self, vlan_101,
3198 "10.0.0.2", "11.0.0.2",
3199 "2001:10::2", "3001::2",
3200 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
3201 eep2.add_vpp_config()
3204 # A remote external endpoint
3206 rep = VppGbpEndpoint(self, vx_tun_l3,
3208 "10.0.0.101", "11.0.0.101",
3209 "2001:10::101", "3001::101",
3210 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
3212 self.pg7.remote_ip4,
3214 rep.add_vpp_config()
3217 # ARP packet from External EPs are accepted and replied to
3219 p_arp = (Ether(src=eep1.mac, dst="ff:ff:ff:ff:ff:ff") /
3222 psrc=eep1.ip4.address, pdst="10.0.0.128",
3223 hwsrc=eep1.mac, hwdst="ff:ff:ff:ff:ff:ff"))
3224 rxs = self.send_and_expect(self.pg0, p_arp * 1, self.pg0)
3227 # packets destined to unknown addresses in the BVI's subnet
3230 p4 = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3232 IP(src="10.0.0.1", dst="10.0.0.88") /
3233 UDP(sport=1234, dport=1234) /
3235 p6 = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3237 IPv6(src="2001:10::1", dst="2001:10::88") /
3238 UDP(sport=1234, dport=1234) /
3241 rxs = self.send_and_expect(self.pg0, p4 * 1, self.pg7)
3244 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3245 # self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3246 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3247 self.assertEqual(rx[IP].dst, "239.1.1.1")
3248 self.assertEqual(rx[VXLAN].vni, 88)
3249 self.assertTrue(rx[VXLAN].flags.G)
3250 self.assertTrue(rx[VXLAN].flags.Instance)
3251 # policy was applied to the original IP packet
3252 self.assertEqual(rx[VXLAN].gpid, 113)
3253 self.assertTrue(rx[VXLAN].gpflags.A)
3254 self.assertFalse(rx[VXLAN].gpflags.D)
3256 inner = rx[VXLAN].payload
3258 self.assertTrue(inner.haslayer(ARP))
3261 # remote to external
3263 p = (Ether(src=self.pg7.remote_mac,
3264 dst=self.pg7.local_mac) /
3265 IP(src=self.pg7.remote_ip4,
3266 dst=self.pg7.local_ip4) /
3267 UDP(sport=1234, dport=48879) /
3268 VXLAN(vni=444, gpid=113, flags=0x88) /
3269 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
3270 IP(src="10.0.0.101", dst="10.0.0.1") /
3271 UDP(sport=1234, dport=1234) /
3274 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
3277 # local EP pings router
3279 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3281 IP(src=eep1.ip4.address, dst="10.0.0.128") /
3282 ICMP(type='echo-request'))
3284 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
3287 self.assertEqual(rx[Ether].src, str(self.router_mac))
3288 self.assertEqual(rx[Ether].dst, eep1.mac)
3289 self.assertEqual(rx[Dot1Q].vlan, 100)
3292 # local EP pings other local EP
3294 p = (Ether(src=eep1.mac, dst=eep2.mac) /
3296 IP(src=eep1.ip4.address, dst=eep2.ip4.address) /
3297 ICMP(type='echo-request'))
3299 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
3302 self.assertEqual(rx[Ether].src, eep1.mac)
3303 self.assertEqual(rx[Ether].dst, eep2.mac)
3304 self.assertEqual(rx[Dot1Q].vlan, 101)
3307 # A subnet reachable through the external EP1
3309 ip_220 = VppIpRoute(self, "10.220.0.0", 24,
3310 [VppRoutePath(eep1.ip4.address,
3311 eep1.epg.bvi.sw_if_index)],
3312 table_id=t4.table_id)
3313 ip_220.add_vpp_config()
3315 l3o_220 = VppGbpSubnet(
3316 self, rd1, "10.220.0.0", 24,
3317 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3319 l3o_220.add_vpp_config()
3322 # A subnet reachable through the external EP2
3324 ip_221 = VppIpRoute(self, "10.221.0.0", 24,
3325 [VppRoutePath(eep2.ip4.address,
3326 eep2.epg.bvi.sw_if_index)],
3327 table_id=t4.table_id)
3328 ip_221.add_vpp_config()
3330 l3o_221 = VppGbpSubnet(
3331 self, rd1, "10.221.0.0", 24,
3332 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3334 l3o_221.add_vpp_config()
3337 # ping between hosts in remote subnets
3338 # dropped without a contract
3340 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3342 IP(src="10.220.0.1", dst="10.221.0.1") /
3343 ICMP(type='echo-request'))
3345 rxs = self.send_and_assert_no_replies(self.pg0, p * 1)
3348 # contract for the external nets to communicate
3350 acl = VppGbpAcl(self)
3351 rule4 = acl.create_rule(permit_deny=1, proto=17)
3352 rule6 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
3353 acl_index = acl.add_vpp_config([rule4, rule6])
3355 c1 = VppGbpContract(
3356 self, 4220, 4221, acl_index,
3357 [VppGbpContractRule(
3358 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3361 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3363 [ETH_P_IP, ETH_P_IPV6])
3367 # Contracts allowing ext-net 200 to talk with external EPs
3369 c2 = VppGbpContract(
3370 self, 4220, 113, acl_index,
3371 [VppGbpContractRule(
3372 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3375 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3377 [ETH_P_IP, ETH_P_IPV6])
3379 c3 = VppGbpContract(
3380 self, 113, 4220, acl_index,
3381 [VppGbpContractRule(
3382 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3385 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3387 [ETH_P_IP, ETH_P_IPV6])
3391 # ping between hosts in remote subnets
3393 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3395 IP(src="10.220.0.1", dst="10.221.0.1") /
3396 UDP(sport=1234, dport=1234) /
3399 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
3402 self.assertEqual(rx[Ether].src, str(self.router_mac))
3403 self.assertEqual(rx[Ether].dst, eep2.mac)
3404 self.assertEqual(rx[Dot1Q].vlan, 101)
3406 # we did not learn these external hosts
3407 self.assertFalse(find_gbp_endpoint(self, ip="10.220.0.1"))
3408 self.assertFalse(find_gbp_endpoint(self, ip="10.221.0.1"))
3411 # from remote external EP to local external EP
3413 p = (Ether(src=self.pg7.remote_mac,
3414 dst=self.pg7.local_mac) /
3415 IP(src=self.pg7.remote_ip4,
3416 dst=self.pg7.local_ip4) /
3417 UDP(sport=1234, dport=48879) /
3418 VXLAN(vni=444, gpid=113, flags=0x88) /
3419 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
3420 IP(src="10.0.0.101", dst="10.220.0.1") /
3421 UDP(sport=1234, dport=1234) /
3424 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
3427 # ping from an external host to the remote external EP
3429 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3431 IP(src="10.220.0.1", dst=rep.ip4.address) /
3432 UDP(sport=1234, dport=1234) /
3435 rxs = self.send_and_expect(self.pg0, p * 1, self.pg7)
3438 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3439 # self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3440 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3441 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
3442 self.assertEqual(rx[VXLAN].vni, 444)
3443 self.assertTrue(rx[VXLAN].flags.G)
3444 self.assertTrue(rx[VXLAN].flags.Instance)
3445 # the sclass of the ext-net the packet came from
3446 self.assertEqual(rx[VXLAN].gpid, 4220)
3447 # policy was applied to the original IP packet
3448 self.assertTrue(rx[VXLAN].gpflags.A)
3449 # since it's an external host the reciever should not learn it
3450 self.assertTrue(rx[VXLAN].gpflags.D)
3451 inner = rx[VXLAN].payload
3452 self.assertEqual(inner[IP].src, "10.220.0.1")
3453 self.assertEqual(inner[IP].dst, rep.ip4.address)
3456 # An external subnet reachable via the remote external EP
3460 # first the VXLAN-GBP tunnel over which it is reached
3462 vx_tun_r = VppVxlanGbpTunnel(
3463 self, self.pg7.local_ip4,
3464 self.pg7.remote_ip4, 445,
3465 mode=(VppEnum.vl_api_vxlan_gbp_api_tunnel_mode_t.
3466 VXLAN_GBP_API_TUNNEL_MODE_L3))
3467 vx_tun_r.add_vpp_config()
3468 VppIpInterfaceBind(self, vx_tun_r, t4).add_vpp_config()
3470 self.logger.info(self.vapi.cli("sh vxlan-gbp tunnel"))
3473 # then the special adj to resolve through on that tunnel
3475 n1 = VppNeighbor(self,
3476 vx_tun_r.sw_if_index,
3477 "00:0c:0c:0c:0c:0c",
3478 self.pg7.remote_ip4)
3482 # the route via the adj above
3484 ip_222 = VppIpRoute(self, "10.222.0.0", 24,
3485 [VppRoutePath(self.pg7.remote_ip4,
3486 vx_tun_r.sw_if_index)],
3487 table_id=t4.table_id)
3488 ip_222.add_vpp_config()
3490 l3o_222 = VppGbpSubnet(
3491 self, rd1, "10.222.0.0", 24,
3492 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3494 l3o_222.add_vpp_config()
3497 # ping between hosts in local and remote external subnets
3498 # dropped without a contract
3500 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3502 IP(src="10.220.0.1", dst="10.222.0.1") /
3503 UDP(sport=1234, dport=1234) /
3506 rxs = self.send_and_assert_no_replies(self.pg0, p * 1)
3509 # Add contracts ext-nets for 220 -> 222
3511 c4 = VppGbpContract(
3512 self, 4220, 4222, acl_index,
3513 [VppGbpContractRule(
3514 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3517 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3519 [ETH_P_IP, ETH_P_IPV6])
3523 # ping from host in local to remote external subnets
3525 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3527 IP(src="10.220.0.1", dst="10.222.0.1") /
3528 UDP(sport=1234, dport=1234) /
3531 rxs = self.send_and_expect(self.pg0, p * 3, self.pg7)
3534 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3535 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3536 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3537 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
3538 self.assertEqual(rx[VXLAN].vni, 445)
3539 self.assertTrue(rx[VXLAN].flags.G)
3540 self.assertTrue(rx[VXLAN].flags.Instance)
3541 # the sclass of the ext-net the packet came from
3542 self.assertEqual(rx[VXLAN].gpid, 4220)
3543 # policy was applied to the original IP packet
3544 self.assertTrue(rx[VXLAN].gpflags.A)
3545 # since it's an external host the reciever should not learn it
3546 self.assertTrue(rx[VXLAN].gpflags.D)
3547 inner = rx[VXLAN].payload
3548 self.assertEqual(inner[Ether].dst, "00:0c:0c:0c:0c:0c")
3549 self.assertEqual(inner[IP].src, "10.220.0.1")
3550 self.assertEqual(inner[IP].dst, "10.222.0.1")
3553 # ping from host in remote to local external subnets
3554 # there's no contract for this, but the A bit is set.
3556 p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
3557 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
3558 UDP(sport=1234, dport=48879) /
3559 VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
3560 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
3561 IP(src="10.222.0.1", dst="10.220.0.1") /
3562 UDP(sport=1234, dport=1234) /
3565 rxs = self.send_and_expect(self.pg7, p * 3, self.pg0)
3566 self.assertFalse(find_gbp_endpoint(self, ip="10.222.0.1"))
3569 # ping from host in remote to remote external subnets
3570 # this is dropped by reflection check.
3572 p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
3573 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
3574 UDP(sport=1234, dport=48879) /
3575 VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
3576 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
3577 IP(src="10.222.0.1", dst="10.222.0.2") /
3578 UDP(sport=1234, dport=1234) /
3581 rxs = self.send_and_assert_no_replies(self.pg7, p * 3)
3586 self.pg7.unconfig_ip4()
3587 vlan_100.set_vtr(L2_VTR_OP.L2_DISABLED)
3590 if __name__ == '__main__':
3591 unittest.main(testRunner=VppTestRunner)