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):
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 def add_vpp_config(self):
335 self._test.vapi.gbp_bridge_domain_add(
338 self.bvi.sw_if_index,
339 self.uu_fwd.sw_if_index if self.uu_fwd else INDEX_INVALID,
340 self.bm_flood.sw_if_index if self.bm_flood else INDEX_INVALID)
341 self._test.registry.register(self, self._test.logger)
343 def remove_vpp_config(self):
344 self._test.vapi.gbp_bridge_domain_del(self.bd.bd_id)
347 return "gbp-bridge-domain:[%d]" % (self.bd.bd_id)
349 def query_vpp_config(self):
350 bds = self._test.vapi.gbp_bridge_domain_dump()
352 if bd.bd.bd_id == self.bd.bd_id:
357 class VppGbpRouteDomain(VppObject):
362 def __init__(self, test, rd_id, t4, t6, ip4_uu=None, ip6_uu=None):
370 def add_vpp_config(self):
371 self._test.vapi.gbp_route_domain_add(
375 self.ip4_uu.sw_if_index if self.ip4_uu else INDEX_INVALID,
376 self.ip6_uu.sw_if_index if self.ip6_uu else INDEX_INVALID)
377 self._test.registry.register(self, self._test.logger)
379 def remove_vpp_config(self):
380 self._test.vapi.gbp_route_domain_del(self.rd_id)
383 return "gbp-route-domain:[%d]" % (self.rd_id)
385 def query_vpp_config(self):
386 rds = self._test.vapi.gbp_route_domain_dump()
388 if rd.rd.rd_id == self.rd_id:
393 class VppGbpContractNextHop():
394 def __init__(self, mac, bd, ip, rd):
401 return {'ip': self.ip.encode(),
402 'mac': self.mac.packed,
403 'bd_id': self.bd.bd.bd_id,
404 'rd_id': self.rd.rd_id}
407 class VppGbpContractRule():
408 def __init__(self, action, hash_mode, nhs=[]):
410 self.hash_mode = hash_mode
416 nhs.append(nh.encode())
419 return {'action': self.action,
421 'hash_mode': self.hash_mode,
422 'n_nhs': len(self.nhs),
426 class VppGbpContract(VppObject):
431 def __init__(self, test, sclass, dclass, acl_index,
432 rules, allowed_ethertypes):
434 self.acl_index = acl_index
438 self.allowed_ethertypes = allowed_ethertypes
439 while (len(self.allowed_ethertypes) < 16):
440 self.allowed_ethertypes.append(0)
442 def add_vpp_config(self):
445 rules.append(r.encode())
446 self._test.vapi.gbp_contract_add_del(
452 self.allowed_ethertypes)
453 self._test.registry.register(self, self._test.logger)
455 def remove_vpp_config(self):
456 self._test.vapi.gbp_contract_add_del(
462 self.allowed_ethertypes)
465 return "gbp-contract:[%d:%s:%d]" % (self.sclass,
469 def query_vpp_config(self):
470 cs = self._test.vapi.gbp_contract_dump()
472 if c.contract.sclass == self.sclass \
473 and c.contract.dclass == self.dclass:
478 class VppGbpVxlanTunnel(VppInterface):
483 def __init__(self, test, vni, bd_rd_id, mode, src):
484 super(VppGbpVxlanTunnel, self).__init__(test)
487 self.bd_rd_id = bd_rd_id
491 def add_vpp_config(self):
492 r = self._test.vapi.gbp_vxlan_tunnel_add(
497 self.set_sw_if_index(r.sw_if_index)
498 self._test.registry.register(self, self._test.logger)
500 def remove_vpp_config(self):
501 self._test.vapi.gbp_vxlan_tunnel_del(self.vni)
504 return "gbp-vxlan:%d" % (self.sw_if_index)
506 def query_vpp_config(self):
507 return find_gbp_vxlan(self._test, self.vni)
510 class VppGbpAcl(VppObject):
515 def __init__(self, test):
517 self.acl_index = 4294967295
519 def create_rule(self, is_ipv6=0, permit_deny=0, proto=-1,
520 s_prefix=0, s_ip=b'\x00\x00\x00\x00', sport_from=0,
521 sport_to=65535, d_prefix=0, d_ip=b'\x00\x00\x00\x00',
522 dport_from=0, dport_to=65535):
523 if proto == -1 or proto == 0:
526 elif proto == 1 or proto == 58:
529 rule = ({'is_permit': permit_deny, 'is_ipv6': is_ipv6, 'proto': proto,
530 'srcport_or_icmptype_first': sport_from,
531 'srcport_or_icmptype_last': sport_to,
532 'src_ip_prefix_len': s_prefix,
534 'dstport_or_icmpcode_first': dport_from,
535 'dstport_or_icmpcode_last': dport_to,
536 'dst_ip_prefix_len': d_prefix,
537 'dst_ip_addr': d_ip})
540 def add_vpp_config(self, rules):
542 reply = self._test.vapi.acl_add_replace(self.acl_index,
545 self.acl_index = reply.acl_index
546 return self.acl_index
548 def remove_vpp_config(self):
549 self._test.vapi.acl_del(self.acl_index)
552 return "gbp-acl:[%d]" % (self.acl_index)
554 def query_vpp_config(self):
555 cs = self._test.vapi.acl_dump()
557 if c.acl_index == self.acl_index:
562 class TestGBP(VppTestCase):
563 """ GBP Test Case """
566 super(TestGBP, self).setUp()
568 self.create_pg_interfaces(range(9))
569 self.create_loopback_interfaces(8)
571 self.router_mac = MACAddress("00:11:22:33:44:55")
573 for i in self.pg_interfaces:
575 for i in self.lo_interfaces:
579 for i in self.pg_interfaces:
582 super(TestGBP, self).tearDown()
584 def send_and_expect_bridged(self, src, tx, dst):
585 rx = self.send_and_expect(src, tx, dst)
588 self.assertEqual(r[Ether].src, tx[0][Ether].src)
589 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
590 self.assertEqual(r[IP].src, tx[0][IP].src)
591 self.assertEqual(r[IP].dst, tx[0][IP].dst)
594 def send_and_expect_bridged6(self, src, tx, dst):
595 rx = self.send_and_expect(src, tx, dst)
598 self.assertEqual(r[Ether].src, tx[0][Ether].src)
599 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
600 self.assertEqual(r[IPv6].src, tx[0][IPv6].src)
601 self.assertEqual(r[IPv6].dst, tx[0][IPv6].dst)
604 def send_and_expect_routed(self, src, tx, dst, src_mac):
605 rx = self.send_and_expect(src, tx, dst)
608 self.assertEqual(r[Ether].src, src_mac)
609 self.assertEqual(r[Ether].dst, dst.remote_mac)
610 self.assertEqual(r[IP].src, tx[0][IP].src)
611 self.assertEqual(r[IP].dst, tx[0][IP].dst)
614 def send_and_expect_natted(self, src, tx, dst, src_ip):
615 rx = self.send_and_expect(src, tx, dst)
618 self.assertEqual(r[Ether].src, tx[0][Ether].src)
619 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
620 self.assertEqual(r[IP].src, src_ip)
621 self.assertEqual(r[IP].dst, tx[0][IP].dst)
624 def send_and_expect_natted6(self, src, tx, dst, src_ip):
625 rx = self.send_and_expect(src, tx, dst)
628 self.assertEqual(r[Ether].src, tx[0][Ether].src)
629 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
630 self.assertEqual(r[IPv6].src, src_ip)
631 self.assertEqual(r[IPv6].dst, tx[0][IPv6].dst)
634 def send_and_expect_unnatted(self, src, tx, dst, dst_ip):
635 rx = self.send_and_expect(src, tx, dst)
638 self.assertEqual(r[Ether].src, tx[0][Ether].src)
639 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
640 self.assertEqual(r[IP].dst, dst_ip)
641 self.assertEqual(r[IP].src, tx[0][IP].src)
644 def send_and_expect_unnatted6(self, src, tx, dst, dst_ip):
645 rx = self.send_and_expect(src, tx, dst)
648 self.assertEqual(r[Ether].src, tx[0][Ether].src)
649 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
650 self.assertEqual(r[IPv6].dst, dst_ip)
651 self.assertEqual(r[IPv6].src, tx[0][IPv6].src)
654 def send_and_expect_double_natted(self, src, tx, dst, src_ip, dst_ip):
655 rx = self.send_and_expect(src, tx, dst)
658 self.assertEqual(r[Ether].src, str(self.router_mac))
659 self.assertEqual(r[Ether].dst, dst.remote_mac)
660 self.assertEqual(r[IP].dst, dst_ip)
661 self.assertEqual(r[IP].src, src_ip)
664 def send_and_expect_double_natted6(self, src, tx, dst, src_ip, dst_ip):
665 rx = self.send_and_expect(src, tx, dst)
668 self.assertEqual(r[Ether].src, str(self.router_mac))
669 self.assertEqual(r[Ether].dst, dst.remote_mac)
670 self.assertEqual(r[IPv6].dst, dst_ip)
671 self.assertEqual(r[IPv6].src, src_ip)
675 """ Group Based Policy """
677 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
682 bd1 = VppBridgeDomain(self, 1)
683 bd2 = VppBridgeDomain(self, 2)
684 bd20 = VppBridgeDomain(self, 20)
688 bd20.add_vpp_config()
690 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0)
691 gbd2 = VppGbpBridgeDomain(self, bd2, self.loop1)
692 gbd20 = VppGbpBridgeDomain(self, bd20, self.loop2)
694 gbd1.add_vpp_config()
695 gbd2.add_vpp_config()
696 gbd20.add_vpp_config()
701 gt4 = VppIpTable(self, 0)
703 gt6 = VppIpTable(self, 0, is_ip6=True)
705 nt4 = VppIpTable(self, 20)
707 nt6 = VppIpTable(self, 20, is_ip6=True)
710 rd0 = VppGbpRouteDomain(self, 0, gt4, gt6, None, None)
711 rd20 = VppGbpRouteDomain(self, 20, nt4, nt6, None, None)
714 rd20.add_vpp_config()
717 # 3 EPGs, 2 of which share a BD.
718 # 2 NAT EPGs, one for floating-IP subnets, the other for internet
720 epgs = [VppGbpEndpointGroup(self, 220, 1220, rd0, gbd1,
721 self.pg4, self.loop0,
722 "10.0.0.128", "2001:10::128"),
723 VppGbpEndpointGroup(self, 221, 1221, rd0, gbd1,
724 self.pg5, self.loop0,
725 "10.0.1.128", "2001:10:1::128"),
726 VppGbpEndpointGroup(self, 222, 1222, rd0, gbd2,
727 self.pg6, self.loop1,
728 "10.0.2.128", "2001:10:2::128"),
729 VppGbpEndpointGroup(self, 333, 1333, rd20, gbd20,
730 self.pg7, self.loop2,
731 "11.0.0.128", "3001::128"),
732 VppGbpEndpointGroup(self, 444, 1444, rd20, gbd20,
733 self.pg8, self.loop2,
734 "11.0.0.129", "3001::129")]
735 recircs = [VppGbpRecirc(self, epgs[0], self.loop3),
736 VppGbpRecirc(self, epgs[1], self.loop4),
737 VppGbpRecirc(self, epgs[2], self.loop5),
738 VppGbpRecirc(self, epgs[3], self.loop6, is_ext=True),
739 VppGbpRecirc(self, epgs[4], self.loop7, is_ext=True)]
742 recirc_nat = recircs[3]
745 # 4 end-points, 2 in the same subnet, 3 in the same BD
747 eps = [VppGbpEndpoint(self, self.pg0,
749 "10.0.0.1", "11.0.0.1",
750 "2001:10::1", "3001::1"),
751 VppGbpEndpoint(self, self.pg1,
753 "10.0.0.2", "11.0.0.2",
754 "2001:10::2", "3001::2"),
755 VppGbpEndpoint(self, self.pg2,
757 "10.0.1.1", "11.0.0.3",
758 "2001:10:1::1", "3001::3"),
759 VppGbpEndpoint(self, self.pg3,
761 "10.0.2.1", "11.0.0.4",
762 "2001:10:2::1", "3001::4")]
765 # Config related to each of the EPGs
768 # IP config on the BVI interfaces
769 if epg != epgs[1] and epg != epgs[4]:
770 VppIpInterfaceBind(self, epg.bvi, epg.rd.t4).add_vpp_config()
771 VppIpInterfaceBind(self, epg.bvi, epg.rd.t6).add_vpp_config()
772 self.vapi.sw_interface_set_mac_address(
774 self.router_mac.packed)
776 # The BVIs are NAT inside interfaces
777 self.vapi.nat44_interface_add_del_feature(epg.bvi.sw_if_index,
780 self.vapi.nat66_add_del_interface(epg.bvi.sw_if_index,
784 if_ip4 = VppIpInterfaceAddress(self, epg.bvi, epg.bvi_ip4, 32)
785 if_ip6 = VppIpInterfaceAddress(self, epg.bvi, epg.bvi_ip6, 128)
786 if_ip4.add_vpp_config()
787 if_ip6.add_vpp_config()
789 # EPG uplink interfaces in the RD
790 VppIpInterfaceBind(self, epg.uplink, epg.rd.t4).add_vpp_config()
791 VppIpInterfaceBind(self, epg.uplink, epg.rd.t6).add_vpp_config()
793 # add the BD ARP termination entry for BVI IP
794 epg.bd_arp_ip4 = VppBridgeDomainArpEntry(self, epg.bd.bd,
795 str(self.router_mac),
797 epg.bd_arp_ip6 = VppBridgeDomainArpEntry(self, epg.bd.bd,
798 str(self.router_mac),
800 epg.bd_arp_ip4.add_vpp_config()
801 epg.bd_arp_ip6.add_vpp_config()
806 for recirc in recircs:
807 # EPG's ingress recirculation interface maps to its RD
808 VppIpInterfaceBind(self, recirc.recirc,
809 recirc.epg.rd.t4).add_vpp_config()
810 VppIpInterfaceBind(self, recirc.recirc,
811 recirc.epg.rd.t6).add_vpp_config()
813 self.vapi.nat44_interface_add_del_feature(
814 recirc.recirc.sw_if_index,
817 self.vapi.nat66_add_del_interface(
818 recirc.recirc.sw_if_index,
822 recirc.add_vpp_config()
824 for recirc in recircs:
825 self.assertTrue(find_bridge_domain_port(self,
826 recirc.epg.bd.bd.bd_id,
827 recirc.recirc.sw_if_index))
830 self.pg_enable_capture(self.pg_interfaces)
833 # routes to the endpoints. We need these since there are no
834 # adj-fibs due to the fact the the BVI address has /32 and
835 # the subnet is not attached.
837 for (ip, fip) in zip(ep.ips, ep.fips):
838 # Add static mappings for each EP from the 10/8 to 11/8 network
840 self.vapi.nat44_add_del_static_mapping(ip.bytes,
845 self.vapi.nat66_add_del_static_mapping(ip.bytes,
852 self.logger.info(self.vapi.cli("sh gbp endpoint"))
854 # ... results in a Gratuitous ARP/ND on the EPG's uplink
855 rx = ep.epg.uplink.get_capture(len(ep.ips), timeout=0.2)
857 for ii, ip in enumerate(ep.ips):
861 self.assertTrue(p.haslayer(ICMPv6ND_NA))
862 self.assertEqual(p[ICMPv6ND_NA].tgt, ip.address)
864 self.assertTrue(p.haslayer(ARP))
865 self.assertEqual(p[ARP].psrc, ip.address)
866 self.assertEqual(p[ARP].pdst, ip.address)
868 # add the BD ARP termination entry for floating IP
870 ba = VppBridgeDomainArpEntry(self, epg_nat.bd.bd, ep.mac, fip)
873 # floating IPs route via EPG recirc
874 r = VppIpRoute(self, fip.address, fip.length,
875 [VppRoutePath(fip.address,
876 ep.recirc.recirc.sw_if_index,
878 proto=fip.dpo_proto)],
883 # L2 FIB entries in the NAT EPG BD to bridge the packets from
884 # the outside direct to the internal EPG
885 lf = VppL2FibEntry(self, epg_nat.bd.bd, ep.mac,
886 ep.recirc.recirc, bvi_mac=0)
890 # ARP packets for unknown IP are sent to the EPG uplink
892 pkt_arp = (Ether(dst="ff:ff:ff:ff:ff:ff",
893 src=self.pg0.remote_mac) /
895 hwdst="ff:ff:ff:ff:ff:ff",
896 hwsrc=self.pg0.remote_mac,
900 self.vapi.cli("clear trace")
901 self.pg0.add_stream(pkt_arp)
903 self.pg_enable_capture(self.pg_interfaces)
906 rxd = epgs[0].uplink.get_capture(1)
909 # ARP/ND packets get a response
911 pkt_arp = (Ether(dst="ff:ff:ff:ff:ff:ff",
912 src=self.pg0.remote_mac) /
914 hwdst="ff:ff:ff:ff:ff:ff",
915 hwsrc=self.pg0.remote_mac,
916 pdst=epgs[0].bvi_ip4.address,
917 psrc=eps[0].ip4.address))
919 self.send_and_expect(self.pg0, [pkt_arp], self.pg0)
921 nsma = in6_getnsma(inet_pton(AF_INET6, eps[0].ip6.address))
922 d = inet_ntop(AF_INET6, nsma)
923 pkt_nd = (Ether(dst=in6_getnsmac(nsma),
924 src=self.pg0.remote_mac) /
925 IPv6(dst=d, src=eps[0].ip6.address) /
926 ICMPv6ND_NS(tgt=epgs[0].bvi_ip6.address) /
927 ICMPv6NDOptSrcLLAddr(lladdr=self.pg0.remote_mac))
928 self.send_and_expect(self.pg0, [pkt_nd], self.pg0)
931 # broadcast packets are flooded
933 pkt_bcast = (Ether(dst="ff:ff:ff:ff:ff:ff",
934 src=self.pg0.remote_mac) /
935 IP(src=eps[0].ip4.address, dst="232.1.1.1") /
936 UDP(sport=1234, dport=1234) /
939 self.vapi.cli("clear trace")
940 self.pg0.add_stream(pkt_bcast)
942 self.pg_enable_capture(self.pg_interfaces)
945 rxd = eps[1].itf.get_capture(1)
946 self.assertEqual(rxd[0][Ether].dst, pkt_bcast[Ether].dst)
947 rxd = epgs[0].uplink.get_capture(1)
948 self.assertEqual(rxd[0][Ether].dst, pkt_bcast[Ether].dst)
951 # packets to non-local L3 destinations dropped
953 pkt_intra_epg_220_ip4 = (Ether(src=self.pg0.remote_mac,
954 dst=str(self.router_mac)) /
955 IP(src=eps[0].ip4.address,
957 UDP(sport=1234, dport=1234) /
959 pkt_inter_epg_222_ip4 = (Ether(src=self.pg0.remote_mac,
960 dst=str(self.router_mac)) /
961 IP(src=eps[0].ip4.address,
963 UDP(sport=1234, dport=1234) /
966 self.send_and_assert_no_replies(self.pg0, pkt_intra_epg_220_ip4 * 65)
968 pkt_inter_epg_222_ip6 = (Ether(src=self.pg0.remote_mac,
969 dst=str(self.router_mac)) /
970 IPv6(src=eps[0].ip6.address,
972 UDP(sport=1234, dport=1234) /
974 self.send_and_assert_no_replies(self.pg0, pkt_inter_epg_222_ip6 * 65)
977 # Add the subnet routes
980 self, rd0, "10.0.0.0", 24,
981 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
983 self, rd0, "10.0.1.0", 24,
984 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
986 self, rd0, "10.0.2.0", 24,
987 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
989 self, rd0, "2001:10::1", 64,
990 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
992 self, rd0, "2001:10:1::1", 64,
993 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
995 self, rd0, "2001:10:2::1", 64,
996 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1000 s61.add_vpp_config()
1001 s62.add_vpp_config()
1002 s63.add_vpp_config()
1004 self.send_and_expect_bridged(eps[0].itf,
1005 pkt_intra_epg_220_ip4 * 65,
1007 self.send_and_expect_bridged(eps[0].itf,
1008 pkt_inter_epg_222_ip4 * 65,
1010 self.send_and_expect_bridged6(eps[0].itf,
1011 pkt_inter_epg_222_ip6 * 65,
1014 self.logger.info(self.vapi.cli("sh ip fib 11.0.0.2"))
1015 self.logger.info(self.vapi.cli("sh gbp endpoint-group"))
1016 self.logger.info(self.vapi.cli("sh gbp endpoint"))
1017 self.logger.info(self.vapi.cli("sh gbp recirc"))
1018 self.logger.info(self.vapi.cli("sh int"))
1019 self.logger.info(self.vapi.cli("sh int addr"))
1020 self.logger.info(self.vapi.cli("sh int feat loop6"))
1021 self.logger.info(self.vapi.cli("sh vlib graph ip4-gbp-src-classify"))
1022 self.logger.info(self.vapi.cli("sh int feat loop3"))
1023 self.logger.info(self.vapi.cli("sh int feat pg0"))
1026 # Packet destined to unknown unicast is sent on the epg uplink ...
1028 pkt_intra_epg_220_to_uplink = (Ether(src=self.pg0.remote_mac,
1029 dst="00:00:00:33:44:55") /
1030 IP(src=eps[0].ip4.address,
1032 UDP(sport=1234, dport=1234) /
1035 self.send_and_expect_bridged(eps[0].itf,
1036 pkt_intra_epg_220_to_uplink * 65,
1038 # ... and nowhere else
1039 self.pg1.get_capture(0, timeout=0.1)
1040 self.pg1.assert_nothing_captured(remark="Flood onto other VMS")
1042 pkt_intra_epg_221_to_uplink = (Ether(src=self.pg2.remote_mac,
1043 dst="00:00:00:33:44:66") /
1044 IP(src=eps[0].ip4.address,
1046 UDP(sport=1234, dport=1234) /
1049 self.send_and_expect_bridged(eps[2].itf,
1050 pkt_intra_epg_221_to_uplink * 65,
1054 # Packets from the uplink are forwarded in the absence of a contract
1056 pkt_intra_epg_220_from_uplink = (Ether(src="00:00:00:33:44:55",
1057 dst=self.pg0.remote_mac) /
1058 IP(src=eps[0].ip4.address,
1060 UDP(sport=1234, dport=1234) /
1063 self.send_and_expect_bridged(self.pg4,
1064 pkt_intra_epg_220_from_uplink * 65,
1068 # in the absence of policy, endpoints in the same EPG
1071 pkt_intra_epg = (Ether(src=self.pg0.remote_mac,
1072 dst=self.pg1.remote_mac) /
1073 IP(src=eps[0].ip4.address,
1074 dst=eps[1].ip4.address) /
1075 UDP(sport=1234, dport=1234) /
1078 self.send_and_expect_bridged(self.pg0, pkt_intra_epg * 65, self.pg1)
1081 # in the absence of policy, endpoints in the different EPG
1082 # cannot communicate
1084 pkt_inter_epg_220_to_221 = (Ether(src=self.pg0.remote_mac,
1085 dst=self.pg2.remote_mac) /
1086 IP(src=eps[0].ip4.address,
1087 dst=eps[2].ip4.address) /
1088 UDP(sport=1234, dport=1234) /
1090 pkt_inter_epg_221_to_220 = (Ether(src=self.pg2.remote_mac,
1091 dst=self.pg0.remote_mac) /
1092 IP(src=eps[2].ip4.address,
1093 dst=eps[0].ip4.address) /
1094 UDP(sport=1234, dport=1234) /
1096 pkt_inter_epg_220_to_222 = (Ether(src=self.pg0.remote_mac,
1097 dst=str(self.router_mac)) /
1098 IP(src=eps[0].ip4.address,
1099 dst=eps[3].ip4.address) /
1100 UDP(sport=1234, dport=1234) /
1103 self.send_and_assert_no_replies(eps[0].itf,
1104 pkt_inter_epg_220_to_221 * 65)
1105 self.send_and_assert_no_replies(eps[0].itf,
1106 pkt_inter_epg_220_to_222 * 65)
1109 # A uni-directional contract from EPG 220 -> 221
1111 acl = VppGbpAcl(self)
1112 rule = acl.create_rule(permit_deny=1, proto=17)
1113 rule2 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
1114 acl_index = acl.add_vpp_config([rule, rule2])
1115 c1 = VppGbpContract(
1116 self, epgs[0].sclass, epgs[1].sclass, acl_index,
1117 [VppGbpContractRule(
1118 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1121 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1123 [ETH_P_IP, ETH_P_IPV6])
1126 self.send_and_expect_bridged(eps[0].itf,
1127 pkt_inter_epg_220_to_221 * 65,
1129 self.send_and_assert_no_replies(eps[0].itf,
1130 pkt_inter_epg_220_to_222 * 65)
1133 # contract for the return direction
1135 c2 = VppGbpContract(
1136 self, epgs[1].sclass, epgs[0].sclass, acl_index,
1137 [VppGbpContractRule(
1138 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1141 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1143 [ETH_P_IP, ETH_P_IPV6])
1146 self.send_and_expect_bridged(eps[0].itf,
1147 pkt_inter_epg_220_to_221 * 65,
1149 self.send_and_expect_bridged(eps[2].itf,
1150 pkt_inter_epg_221_to_220 * 65,
1154 # the contract does not allow non-IP
1156 pkt_non_ip_inter_epg_220_to_221 = (Ether(src=self.pg0.remote_mac,
1157 dst=self.pg2.remote_mac) /
1159 self.send_and_assert_no_replies(eps[0].itf,
1160 pkt_non_ip_inter_epg_220_to_221 * 17)
1163 # check that inter group is still disabled for the groups
1164 # not in the contract.
1166 self.send_and_assert_no_replies(eps[0].itf,
1167 pkt_inter_epg_220_to_222 * 65)
1170 # A uni-directional contract from EPG 220 -> 222 'L3 routed'
1172 c3 = VppGbpContract(
1173 self, epgs[0].sclass, epgs[2].sclass, acl_index,
1174 [VppGbpContractRule(
1175 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1178 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1180 [ETH_P_IP, ETH_P_IPV6])
1183 self.logger.info(self.vapi.cli("sh gbp contract"))
1185 self.send_and_expect_routed(eps[0].itf,
1186 pkt_inter_epg_220_to_222 * 65,
1188 str(self.router_mac))
1191 # remove both contracts, traffic stops in both directions
1193 c2.remove_vpp_config()
1194 c1.remove_vpp_config()
1195 c3.remove_vpp_config()
1196 acl.remove_vpp_config()
1198 self.send_and_assert_no_replies(eps[2].itf,
1199 pkt_inter_epg_221_to_220 * 65)
1200 self.send_and_assert_no_replies(eps[0].itf,
1201 pkt_inter_epg_220_to_221 * 65)
1202 self.send_and_expect_bridged(eps[0].itf,
1207 # EPs to the outside world
1210 # in the EP's RD an external subnet via the NAT EPG's recirc
1212 self, rd0, "0.0.0.0", 0,
1213 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1214 sw_if_index=recirc_nat.recirc.sw_if_index,
1215 sclass=epg_nat.sclass)
1217 self, rd0, "11.0.0.0", 8,
1218 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1219 sw_if_index=recirc_nat.recirc.sw_if_index,
1220 sclass=epg_nat.sclass)
1221 se16 = VppGbpSubnet(
1223 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1224 sw_if_index=recirc_nat.recirc.sw_if_index,
1225 sclass=epg_nat.sclass)
1226 # in the NAT RD an external subnet via the NAT EPG's uplink
1228 self, rd20, "0.0.0.0", 0,
1229 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1230 sw_if_index=epg_nat.uplink.sw_if_index,
1231 sclass=epg_nat.sclass)
1232 se36 = VppGbpSubnet(
1233 self, rd20, "::", 0,
1234 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1235 sw_if_index=epg_nat.uplink.sw_if_index,
1236 sclass=epg_nat.sclass)
1238 self, rd20, "11.0.0.0", 8,
1239 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1240 sw_if_index=epg_nat.uplink.sw_if_index,
1241 sclass=epg_nat.sclass)
1242 se1.add_vpp_config()
1243 se2.add_vpp_config()
1244 se16.add_vpp_config()
1245 se3.add_vpp_config()
1246 se36.add_vpp_config()
1247 se4.add_vpp_config()
1249 self.logger.info(self.vapi.cli("sh ip fib 0.0.0.0/0"))
1250 self.logger.info(self.vapi.cli("sh ip fib 11.0.0.1"))
1251 self.logger.info(self.vapi.cli("sh ip6 fib ::/0"))
1252 self.logger.info(self.vapi.cli("sh ip6 fib %s" %
1256 # From an EP to an outside address: IN2OUT
1258 pkt_inter_epg_220_to_global = (Ether(src=self.pg0.remote_mac,
1259 dst=str(self.router_mac)) /
1260 IP(src=eps[0].ip4.address,
1262 UDP(sport=1234, dport=1234) /
1266 self.send_and_assert_no_replies(eps[0].itf,
1267 pkt_inter_epg_220_to_global * 65)
1269 acl2 = VppGbpAcl(self)
1270 rule = acl2.create_rule(permit_deny=1, proto=17, sport_from=1234,
1271 sport_to=1234, dport_from=1234, dport_to=1234)
1272 rule2 = acl2.create_rule(is_ipv6=1, permit_deny=1, proto=17,
1273 sport_from=1234, sport_to=1234,
1274 dport_from=1234, dport_to=1234)
1276 acl_index2 = acl2.add_vpp_config([rule, rule2])
1277 c4 = VppGbpContract(
1278 self, epgs[0].sclass, epgs[3].sclass, acl_index2,
1279 [VppGbpContractRule(
1280 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1283 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1285 [ETH_P_IP, ETH_P_IPV6])
1288 self.send_and_expect_natted(eps[0].itf,
1289 pkt_inter_epg_220_to_global * 65,
1291 eps[0].fip4.address)
1293 pkt_inter_epg_220_to_global = (Ether(src=self.pg0.remote_mac,
1294 dst=str(self.router_mac)) /
1295 IPv6(src=eps[0].ip6.address,
1297 UDP(sport=1234, dport=1234) /
1300 self.send_and_expect_natted6(self.pg0,
1301 pkt_inter_epg_220_to_global * 65,
1303 eps[0].fip6.address)
1306 # From a global address to an EP: OUT2IN
1308 pkt_inter_epg_220_from_global = (Ether(src=str(self.router_mac),
1309 dst=self.pg0.remote_mac) /
1310 IP(dst=eps[0].fip4.address,
1312 UDP(sport=1234, dport=1234) /
1315 self.send_and_assert_no_replies(self.pg7,
1316 pkt_inter_epg_220_from_global * 65)
1318 c5 = VppGbpContract(
1319 self, epgs[3].sclass, epgs[0].sclass, acl_index2,
1320 [VppGbpContractRule(
1321 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1324 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1326 [ETH_P_IP, ETH_P_IPV6])
1329 self.send_and_expect_unnatted(self.pg7,
1330 pkt_inter_epg_220_from_global * 65,
1334 pkt_inter_epg_220_from_global = (Ether(src=str(self.router_mac),
1335 dst=self.pg0.remote_mac) /
1336 IPv6(dst=eps[0].fip6.address,
1338 UDP(sport=1234, dport=1234) /
1341 self.send_and_expect_unnatted6(self.pg7,
1342 pkt_inter_epg_220_from_global * 65,
1347 # From a local VM to another local VM using resp. public addresses:
1350 pkt_intra_epg_220_global = (Ether(src=self.pg0.remote_mac,
1351 dst=str(self.router_mac)) /
1352 IP(src=eps[0].ip4.address,
1353 dst=eps[1].fip4.address) /
1354 UDP(sport=1234, dport=1234) /
1357 self.send_and_expect_double_natted(eps[0].itf,
1358 pkt_intra_epg_220_global * 65,
1360 eps[0].fip4.address,
1363 pkt_intra_epg_220_global = (Ether(src=self.pg0.remote_mac,
1364 dst=str(self.router_mac)) /
1365 IPv6(src=eps[0].ip6.address,
1366 dst=eps[1].fip6.address) /
1367 UDP(sport=1234, dport=1234) /
1370 self.send_and_expect_double_natted6(eps[0].itf,
1371 pkt_intra_epg_220_global * 65,
1373 eps[0].fip6.address,
1380 # del static mappings for each EP from the 10/8 to 11/8 network
1381 self.vapi.nat44_add_del_static_mapping(ep.ip4.bytes,
1386 self.vapi.nat66_add_del_static_mapping(ep.ip6.bytes,
1392 # IP config on the BVI interfaces
1393 if epg != epgs[0] and epg != epgs[3]:
1394 self.vapi.nat44_interface_add_del_feature(epg.bvi.sw_if_index,
1397 self.vapi.nat66_add_del_interface(epg.bvi.sw_if_index,
1401 for recirc in recircs:
1402 self.vapi.nat44_interface_add_del_feature(
1403 recirc.recirc.sw_if_index,
1406 self.vapi.nat66_add_del_interface(
1407 recirc.recirc.sw_if_index,
1411 def wait_for_ep_timeout(self, sw_if_index=None, ip=None, mac=None,
1412 n_tries=100, s_time=1):
1414 if not find_gbp_endpoint(self, sw_if_index, ip, mac):
1416 n_tries = n_tries - 1
1418 self.assertFalse(find_gbp_endpoint(self, sw_if_index, ip, mac))
1421 def test_gbp_learn_l2(self):
1422 """ GBP L2 Endpoint Learning """
1424 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
1425 learnt = [{'mac': '00:00:11:11:11:01',
1427 'ip6': '2001:10::2'},
1428 {'mac': '00:00:11:11:11:02',
1430 'ip6': '2001:10::3'}]
1435 gt4 = VppIpTable(self, 1)
1436 gt4.add_vpp_config()
1437 gt6 = VppIpTable(self, 1, is_ip6=True)
1438 gt6.add_vpp_config()
1440 rd1 = VppGbpRouteDomain(self, 1, gt4, gt6)
1441 rd1.add_vpp_config()
1444 # Pg2 hosts the vxlan tunnel, hosts on pg2 to act as TEPs
1445 # Pg3 hosts the IP4 UU-flood VXLAN tunnel
1446 # Pg4 hosts the IP6 UU-flood VXLAN tunnel
1448 self.pg2.config_ip4()
1449 self.pg2.resolve_arp()
1450 self.pg2.generate_remote_hosts(4)
1451 self.pg2.configure_ipv4_neighbors()
1452 self.pg3.config_ip4()
1453 self.pg3.resolve_arp()
1454 self.pg4.config_ip4()
1455 self.pg4.resolve_arp()
1458 # Add a mcast destination VXLAN-GBP tunnel for B&M traffic
1460 tun_bm = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
1463 tun_bm.add_vpp_config()
1466 # a GBP bridge domain with a BVI and a UU-flood interface
1468 bd1 = VppBridgeDomain(self, 1)
1469 bd1.add_vpp_config()
1470 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0, self.pg3, tun_bm)
1471 gbd1.add_vpp_config()
1473 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1474 self.logger.info(self.vapi.cli("sh gbp bridge"))
1476 # ... and has a /32 applied
1477 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
1478 ip_addr.add_vpp_config()
1481 # The Endpoint-group in which we are learning endpoints
1483 epg_220 = VppGbpEndpointGroup(self, 220, 112, rd1, gbd1,
1487 VppGbpEndpointRetention(2))
1488 epg_220.add_vpp_config()
1489 epg_330 = VppGbpEndpointGroup(self, 330, 113, rd1, gbd1,
1493 VppGbpEndpointRetention(2))
1494 epg_330.add_vpp_config()
1497 # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
1500 vx_tun_l2_1 = VppGbpVxlanTunnel(
1501 self, 99, bd1.bd_id,
1502 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L2,
1504 vx_tun_l2_1.add_vpp_config()
1507 # A static endpoint that the learnt endpoints are trying to
1510 ep = VppGbpEndpoint(self, self.pg0,
1512 "10.0.0.127", "11.0.0.127",
1513 "2001:10::1", "3001::1")
1516 self.assertTrue(find_route(self, ep.ip4.address, 32, table_id=1))
1518 # a packet with an sclass from an unknown EPG
1519 p = (Ether(src=self.pg2.remote_mac,
1520 dst=self.pg2.local_mac) /
1521 IP(src=self.pg2.remote_hosts[0].ip4,
1522 dst=self.pg2.local_ip4) /
1523 UDP(sport=1234, dport=48879) /
1524 VXLAN(vni=99, gpid=88, flags=0x88) /
1525 Ether(src=learnt[0]["mac"], dst=ep.mac) /
1526 IP(src=learnt[0]["ip"], dst=ep.ip4.address) /
1527 UDP(sport=1234, dport=1234) /
1530 self.send_and_assert_no_replies(self.pg2, p)
1533 # we should not have learnt a new tunnel endpoint, since
1534 # the EPG was not learnt.
1536 self.assertEqual(INDEX_INVALID,
1537 find_vxlan_gbp_tunnel(self,
1539 self.pg2.remote_hosts[0].ip4,
1542 # epg is not learnt, because the EPG is unknwon
1543 self.assertEqual(len(self.vapi.gbp_endpoint_dump()), 1)
1546 # Learn new EPs from IP packets
1548 for ii, l in enumerate(learnt):
1549 # a packet with an sclass from a known EPG
1550 # arriving on an unknown TEP
1551 p = (Ether(src=self.pg2.remote_mac,
1552 dst=self.pg2.local_mac) /
1553 IP(src=self.pg2.remote_hosts[1].ip4,
1554 dst=self.pg2.local_ip4) /
1555 UDP(sport=1234, dport=48879) /
1556 VXLAN(vni=99, gpid=112, flags=0x88) /
1557 Ether(src=l['mac'], dst=ep.mac) /
1558 IP(src=l['ip'], dst=ep.ip4.address) /
1559 UDP(sport=1234, dport=1234) /
1562 rx = self.send_and_expect(self.pg2, [p], self.pg0)
1565 tep1_sw_if_index = find_vxlan_gbp_tunnel(
1568 self.pg2.remote_hosts[1].ip4,
1570 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
1573 # the EP is learnt via the learnt TEP
1574 # both from its MAC and its IP
1576 self.assertTrue(find_gbp_endpoint(self,
1577 vx_tun_l2_1.sw_if_index,
1579 self.assertTrue(find_gbp_endpoint(self,
1580 vx_tun_l2_1.sw_if_index,
1583 self.logger.info(self.vapi.cli("show gbp endpoint"))
1584 self.logger.info(self.vapi.cli("show gbp vxlan"))
1585 self.logger.info(self.vapi.cli("show ip mfib"))
1588 # If we sleep for the threshold time, the learnt endpoints should
1592 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1596 # Learn new EPs from GARP packets received on the BD's mcast tunnel
1598 for ii, l in enumerate(learnt):
1599 # a packet with an sclass from a known EPG
1600 # arriving on an unknown TEP
1601 p = (Ether(src=self.pg2.remote_mac,
1602 dst=self.pg2.local_mac) /
1603 IP(src=self.pg2.remote_hosts[1].ip4,
1605 UDP(sport=1234, dport=48879) /
1606 VXLAN(vni=88, gpid=112, flags=0x88) /
1607 Ether(src=l['mac'], dst="ff:ff:ff:ff:ff:ff") /
1609 psrc=l['ip'], pdst=l['ip'],
1610 hwsrc=l['mac'], hwdst="ff:ff:ff:ff:ff:ff"))
1612 rx = self.send_and_expect(self.pg4, [p], self.pg0)
1615 tep1_sw_if_index = find_vxlan_gbp_tunnel(
1618 self.pg2.remote_hosts[1].ip4,
1620 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
1623 # the EP is learnt via the learnt TEP
1624 # both from its MAC and its IP
1626 self.assertTrue(find_gbp_endpoint(self,
1627 vx_tun_l2_1.sw_if_index,
1629 self.assertTrue(find_gbp_endpoint(self,
1630 vx_tun_l2_1.sw_if_index,
1634 # wait for the learnt endpoints to age out
1637 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1641 # Learn new EPs from L2 packets
1643 for ii, l in enumerate(learnt):
1644 # a packet with an sclass from a known EPG
1645 # arriving on an unknown TEP
1646 p = (Ether(src=self.pg2.remote_mac,
1647 dst=self.pg2.local_mac) /
1648 IP(src=self.pg2.remote_hosts[1].ip4,
1649 dst=self.pg2.local_ip4) /
1650 UDP(sport=1234, dport=48879) /
1651 VXLAN(vni=99, gpid=112, flags=0x88) /
1652 Ether(src=l['mac'], dst=ep.mac) /
1655 rx = self.send_and_expect(self.pg2, [p], self.pg0)
1658 tep1_sw_if_index = find_vxlan_gbp_tunnel(
1661 self.pg2.remote_hosts[1].ip4,
1663 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
1666 # the EP is learnt via the learnt TEP
1667 # both from its MAC and its IP
1669 self.assertTrue(find_gbp_endpoint(self,
1670 vx_tun_l2_1.sw_if_index,
1673 self.logger.info(self.vapi.cli("show gbp endpoint"))
1674 self.logger.info(self.vapi.cli("show gbp vxlan"))
1675 self.logger.info(self.vapi.cli("show vxlan-gbp tunnel"))
1678 # wait for the learnt endpoints to age out
1681 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1685 # repeat. the do not learn bit is set so the EPs are not learnt
1688 # a packet with an sclass from a known EPG
1689 p = (Ether(src=self.pg2.remote_mac,
1690 dst=self.pg2.local_mac) /
1691 IP(src=self.pg2.remote_hosts[1].ip4,
1692 dst=self.pg2.local_ip4) /
1693 UDP(sport=1234, dport=48879) /
1694 VXLAN(vni=99, gpid=112, flags=0x88, gpflags="D") /
1695 Ether(src=l['mac'], dst=ep.mac) /
1696 IP(src=l['ip'], dst=ep.ip4.address) /
1697 UDP(sport=1234, dport=1234) /
1700 rx = self.send_and_expect(self.pg2, p*65, self.pg0)
1703 self.assertFalse(find_gbp_endpoint(self,
1704 vx_tun_l2_1.sw_if_index,
1711 # a packet with an sclass from a known EPG
1712 p = (Ether(src=self.pg2.remote_mac,
1713 dst=self.pg2.local_mac) /
1714 IP(src=self.pg2.remote_hosts[1].ip4,
1715 dst=self.pg2.local_ip4) /
1716 UDP(sport=1234, dport=48879) /
1717 VXLAN(vni=99, gpid=112, flags=0x88) /
1718 Ether(src=l['mac'], dst=ep.mac) /
1719 IP(src=l['ip'], dst=ep.ip4.address) /
1720 UDP(sport=1234, dport=1234) /
1723 rx = self.send_and_expect(self.pg2, p*65, self.pg0)
1725 self.assertTrue(find_gbp_endpoint(self,
1726 vx_tun_l2_1.sw_if_index,
1730 # Static EP replies to dynamics
1732 self.logger.info(self.vapi.cli("sh l2fib bd_id 1"))
1734 p = (Ether(src=ep.mac, dst=l['mac']) /
1735 IP(dst=l['ip'], src=ep.ip4.address) /
1736 UDP(sport=1234, dport=1234) /
1739 rxs = self.send_and_expect(self.pg0, p * 17, self.pg2)
1742 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
1743 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
1744 self.assertEqual(rx[UDP].dport, 48879)
1745 # the UDP source port is a random value for hashing
1746 self.assertEqual(rx[VXLAN].gpid, 112)
1747 self.assertEqual(rx[VXLAN].vni, 99)
1748 self.assertTrue(rx[VXLAN].flags.G)
1749 self.assertTrue(rx[VXLAN].flags.Instance)
1750 self.assertTrue(rx[VXLAN].gpflags.A)
1751 self.assertFalse(rx[VXLAN].gpflags.D)
1754 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1758 # repeat in the other EPG
1759 # there's no contract between 220 and 330, but the A-bit is set
1760 # so the packet is cleared for delivery
1763 # a packet with an sclass from a known EPG
1764 p = (Ether(src=self.pg2.remote_mac,
1765 dst=self.pg2.local_mac) /
1766 IP(src=self.pg2.remote_hosts[1].ip4,
1767 dst=self.pg2.local_ip4) /
1768 UDP(sport=1234, dport=48879) /
1769 VXLAN(vni=99, gpid=113, flags=0x88, gpflags='A') /
1770 Ether(src=l['mac'], dst=ep.mac) /
1771 IP(src=l['ip'], dst=ep.ip4.address) /
1772 UDP(sport=1234, dport=1234) /
1775 rx = self.send_and_expect(self.pg2, p*65, self.pg0)
1777 self.assertTrue(find_gbp_endpoint(self,
1778 vx_tun_l2_1.sw_if_index,
1782 # static EP cannot reach the learnt EPs since there is no contract
1783 # only test 1 EP as the others could timeout
1785 p = (Ether(src=ep.mac, dst=l['mac']) /
1786 IP(dst=learnt[0]['ip'], src=ep.ip4.address) /
1787 UDP(sport=1234, dport=1234) /
1790 self.send_and_assert_no_replies(self.pg0, [p])
1793 # refresh the entries after the check for no replies above
1796 # a packet with an sclass from a known EPG
1797 p = (Ether(src=self.pg2.remote_mac,
1798 dst=self.pg2.local_mac) /
1799 IP(src=self.pg2.remote_hosts[1].ip4,
1800 dst=self.pg2.local_ip4) /
1801 UDP(sport=1234, dport=48879) /
1802 VXLAN(vni=99, gpid=113, flags=0x88, gpflags='A') /
1803 Ether(src=l['mac'], dst=ep.mac) /
1804 IP(src=l['ip'], dst=ep.ip4.address) /
1805 UDP(sport=1234, dport=1234) /
1808 rx = self.send_and_expect(self.pg2, p*65, self.pg0)
1810 self.assertTrue(find_gbp_endpoint(self,
1811 vx_tun_l2_1.sw_if_index,
1815 # Add the contract so they can talk
1817 acl = VppGbpAcl(self)
1818 rule = acl.create_rule(permit_deny=1, proto=17)
1819 rule2 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
1820 acl_index = acl.add_vpp_config([rule, rule2])
1821 c1 = VppGbpContract(
1822 self, epg_220.sclass, epg_330.sclass, acl_index,
1823 [VppGbpContractRule(
1824 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1827 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1829 [ETH_P_IP, ETH_P_IPV6])
1833 p = (Ether(src=ep.mac, dst=l['mac']) /
1834 IP(dst=l['ip'], src=ep.ip4.address) /
1835 UDP(sport=1234, dport=1234) /
1838 self.send_and_expect(self.pg0, [p], self.pg2)
1841 # send UU packets from the local EP
1843 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1844 self.logger.info(self.vapi.cli("sh gbp bridge"))
1845 p_uu = (Ether(src=ep.mac, dst="00:11:11:11:11:11") /
1846 IP(dst="10.0.0.133", src=ep.ip4.address) /
1847 UDP(sport=1234, dport=1234) /
1849 rxs = self.send_and_expect(ep.itf, [p_uu], gbd1.uu_fwd)
1851 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1853 p_bm = (Ether(src=ep.mac, dst="ff:ff:ff:ff:ff:ff") /
1854 IP(dst="10.0.0.133", src=ep.ip4.address) /
1855 UDP(sport=1234, dport=1234) /
1857 rxs = self.send_and_expect_only(ep.itf, [p_bm], tun_bm.mcast_itf)
1860 self.assertEqual(rx[IP].src, self.pg4.local_ip4)
1861 self.assertEqual(rx[IP].dst, "239.1.1.1")
1862 self.assertEqual(rx[UDP].dport, 48879)
1863 # the UDP source port is a random value for hashing
1864 self.assertEqual(rx[VXLAN].gpid, 112)
1865 self.assertEqual(rx[VXLAN].vni, 88)
1866 self.assertTrue(rx[VXLAN].flags.G)
1867 self.assertTrue(rx[VXLAN].flags.Instance)
1868 self.assertFalse(rx[VXLAN].gpflags.A)
1869 self.assertFalse(rx[VXLAN].gpflags.D)
1872 # Check v6 Endpoints
1875 # a packet with an sclass from a known EPG
1876 p = (Ether(src=self.pg2.remote_mac,
1877 dst=self.pg2.local_mac) /
1878 IP(src=self.pg2.remote_hosts[1].ip4,
1879 dst=self.pg2.local_ip4) /
1880 UDP(sport=1234, dport=48879) /
1881 VXLAN(vni=99, gpid=113, flags=0x88, gpflags='A') /
1882 Ether(src=l['mac'], dst=ep.mac) /
1883 IPv6(src=l['ip6'], dst=ep.ip6.address) /
1884 UDP(sport=1234, dport=1234) /
1887 rx = self.send_and_expect(self.pg2, p*65, self.pg0)
1889 self.assertTrue(find_gbp_endpoint(self,
1890 vx_tun_l2_1.sw_if_index,
1894 # L3 Endpoint Learning
1895 # - configured on the bridge's BVI
1902 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1905 self.pg2.unconfig_ip4()
1906 self.pg3.unconfig_ip4()
1907 self.pg4.unconfig_ip4()
1909 self.logger.info(self.vapi.cli("sh int"))
1910 self.logger.info(self.vapi.cli("sh gbp vxlan"))
1912 def test_gbp_learn_vlan_l2(self):
1913 """ GBP L2 Endpoint w/ VLANs"""
1915 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
1916 learnt = [{'mac': '00:00:11:11:11:01',
1918 'ip6': '2001:10::2'},
1919 {'mac': '00:00:11:11:11:02',
1921 'ip6': '2001:10::3'}]
1926 gt4 = VppIpTable(self, 1)
1927 gt4.add_vpp_config()
1928 gt6 = VppIpTable(self, 1, is_ip6=True)
1929 gt6.add_vpp_config()
1931 rd1 = VppGbpRouteDomain(self, 1, gt4, gt6)
1932 rd1.add_vpp_config()
1935 # Pg2 hosts the vxlan tunnel, hosts on pg2 to act as TEPs
1937 self.pg2.config_ip4()
1938 self.pg2.resolve_arp()
1939 self.pg2.generate_remote_hosts(4)
1940 self.pg2.configure_ipv4_neighbors()
1941 self.pg3.config_ip4()
1942 self.pg3.resolve_arp()
1945 # The EP will be on a vlan sub-interface
1947 vlan_11 = VppDot1QSubint(self, self.pg0, 11)
1949 self.vapi.l2_interface_vlan_tag_rewrite(
1950 sw_if_index=vlan_11.sw_if_index, vtr_op=L2_VTR_OP.L2_POP_1,
1953 bd_uu_fwd = VppVxlanGbpTunnel(self, self.pg3.local_ip4,
1954 self.pg3.remote_ip4, 116)
1955 bd_uu_fwd.add_vpp_config()
1958 # a GBP bridge domain with a BVI and a UU-flood interface
1959 # The BD is marked as do not learn, so no endpoints are ever
1960 # learnt in this BD.
1962 bd1 = VppBridgeDomain(self, 1)
1963 bd1.add_vpp_config()
1964 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0, bd_uu_fwd,
1966 gbd1.add_vpp_config()
1968 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1969 self.logger.info(self.vapi.cli("sh gbp bridge"))
1971 # ... and has a /32 applied
1972 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
1973 ip_addr.add_vpp_config()
1976 # The Endpoint-group in which we are learning endpoints
1978 epg_220 = VppGbpEndpointGroup(self, 220, 441, rd1, gbd1,
1982 VppGbpEndpointRetention(2))
1983 epg_220.add_vpp_config()
1986 # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
1989 vx_tun_l2_1 = VppGbpVxlanTunnel(
1990 self, 99, bd1.bd_id,
1991 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L2,
1993 vx_tun_l2_1.add_vpp_config()
1996 # A static endpoint that the learnt endpoints are trying to
1999 ep = VppGbpEndpoint(self, vlan_11,
2001 "10.0.0.127", "11.0.0.127",
2002 "2001:10::1", "3001::1")
2005 self.assertTrue(find_route(self, ep.ip4.address, 32, table_id=1))
2008 # Send to the static EP
2010 for ii, l in enumerate(learnt):
2011 # a packet with an sclass from a known EPG
2012 # arriving on an unknown TEP
2013 p = (Ether(src=self.pg2.remote_mac,
2014 dst=self.pg2.local_mac) /
2015 IP(src=self.pg2.remote_hosts[1].ip4,
2016 dst=self.pg2.local_ip4) /
2017 UDP(sport=1234, dport=48879) /
2018 VXLAN(vni=99, gpid=441, flags=0x88) /
2019 Ether(src=l['mac'], dst=ep.mac) /
2020 IP(src=l['ip'], dst=ep.ip4.address) /
2021 UDP(sport=1234, dport=1234) /
2024 rxs = self.send_and_expect(self.pg2, [p], self.pg0)
2027 # packet to EP has the EP's vlan tag
2030 self.assertEqual(rx[Dot1Q].vlan, 11)
2033 # the EP is not learnt since the BD setting prevents it
2036 self.assertFalse(find_gbp_endpoint(self,
2037 vx_tun_l2_1.sw_if_index,
2039 self.assertEqual(INDEX_INVALID,
2040 find_vxlan_gbp_tunnel(
2043 self.pg2.remote_hosts[1].ip4,
2046 self.assertEqual(len(self.vapi.gbp_endpoint_dump()), 1)
2050 # we didn't learn the remotes so they are sent to the UU-fwd
2053 p = (Ether(src=ep.mac, dst=l['mac']) /
2055 IP(dst=l['ip'], src=ep.ip4.address) /
2056 UDP(sport=1234, dport=1234) /
2059 rxs = self.send_and_expect(self.pg0, p * 17, self.pg3)
2062 self.assertEqual(rx[IP].src, self.pg3.local_ip4)
2063 self.assertEqual(rx[IP].dst, self.pg3.remote_ip4)
2064 self.assertEqual(rx[UDP].dport, 48879)
2065 # the UDP source port is a random value for hashing
2066 self.assertEqual(rx[VXLAN].gpid, 441)
2067 self.assertEqual(rx[VXLAN].vni, 116)
2068 self.assertTrue(rx[VXLAN].flags.G)
2069 self.assertTrue(rx[VXLAN].flags.Instance)
2070 self.assertFalse(rx[VXLAN].gpflags.A)
2071 self.assertFalse(rx[VXLAN].gpflags.D)
2073 self.pg2.unconfig_ip4()
2074 self.pg3.unconfig_ip4()
2076 def test_gbp_learn_l3(self):
2077 """ GBP L3 Endpoint Learning """
2079 self.vapi.cli("set logging class gbp debug")
2081 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
2082 routed_dst_mac = "00:0c:0c:0c:0c:0c"
2083 routed_src_mac = "00:22:bd:f8:19:ff"
2085 learnt = [{'mac': '00:00:11:11:11:02',
2087 'ip6': '2001:10::2'},
2088 {'mac': '00:00:11:11:11:03',
2090 'ip6': '2001:10::3'}]
2095 t4 = VppIpTable(self, 1)
2097 t6 = VppIpTable(self, 1, True)
2100 tun_ip4_uu = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
2101 self.pg4.remote_ip4, 114)
2102 tun_ip6_uu = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
2103 self.pg4.remote_ip4, 116)
2104 tun_ip4_uu.add_vpp_config()
2105 tun_ip6_uu.add_vpp_config()
2107 rd1 = VppGbpRouteDomain(self, 2, t4, t6, tun_ip4_uu, tun_ip6_uu)
2108 rd1.add_vpp_config()
2110 self.loop0.set_mac(self.router_mac)
2113 # Bind the BVI to the RD
2115 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
2116 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
2119 # Pg2 hosts the vxlan tunnel
2120 # hosts on pg2 to act as TEPs
2124 self.pg2.config_ip4()
2125 self.pg2.resolve_arp()
2126 self.pg2.generate_remote_hosts(4)
2127 self.pg2.configure_ipv4_neighbors()
2128 self.pg3.config_ip4()
2129 self.pg3.resolve_arp()
2130 self.pg4.config_ip4()
2131 self.pg4.resolve_arp()
2134 # a GBP bridge domain with a BVI and a UU-flood interface
2136 bd1 = VppBridgeDomain(self, 1)
2137 bd1.add_vpp_config()
2138 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0, self.pg3)
2139 gbd1.add_vpp_config()
2141 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2142 self.logger.info(self.vapi.cli("sh gbp bridge"))
2143 self.logger.info(self.vapi.cli("sh gbp route"))
2145 # ... and has a /32 and /128 applied
2146 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2147 ip4_addr.add_vpp_config()
2148 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 128)
2149 ip6_addr.add_vpp_config()
2152 # The Endpoint-group in which we are learning endpoints
2154 epg_220 = VppGbpEndpointGroup(self, 220, 441, rd1, gbd1,
2158 VppGbpEndpointRetention(2))
2159 epg_220.add_vpp_config()
2162 # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
2165 vx_tun_l3 = VppGbpVxlanTunnel(
2166 self, 101, rd1.rd_id,
2167 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
2169 vx_tun_l3.add_vpp_config()
2172 # A static endpoint that the learnt endpoints are trying to
2175 ep = VppGbpEndpoint(self, self.pg0,
2177 "10.0.0.127", "11.0.0.127",
2178 "2001:10::1", "3001::1")
2182 # learn some remote IPv4 EPs
2184 for ii, l in enumerate(learnt):
2185 # a packet with an sclass from a known EPG
2186 # arriving on an unknown TEP
2187 p = (Ether(src=self.pg2.remote_mac,
2188 dst=self.pg2.local_mac) /
2189 IP(src=self.pg2.remote_hosts[1].ip4,
2190 dst=self.pg2.local_ip4) /
2191 UDP(sport=1234, dport=48879) /
2192 VXLAN(vni=101, gpid=441, flags=0x88) /
2193 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2194 IP(src=l['ip'], dst=ep.ip4.address) /
2195 UDP(sport=1234, dport=1234) /
2198 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2201 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2204 self.pg2.remote_hosts[1].ip4,
2206 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2208 # endpoint learnt via the parent GBP-vxlan interface
2209 self.assertTrue(find_gbp_endpoint(self,
2210 vx_tun_l3._sw_if_index,
2214 # Static IPv4 EP replies to learnt
2217 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2218 IP(dst=l['ip'], src=ep.ip4.address) /
2219 UDP(sport=1234, dport=1234) /
2222 rxs = self.send_and_expect(self.pg0, p*1, self.pg2)
2225 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2226 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2227 self.assertEqual(rx[UDP].dport, 48879)
2228 # the UDP source port is a random value for hashing
2229 self.assertEqual(rx[VXLAN].gpid, 441)
2230 self.assertEqual(rx[VXLAN].vni, 101)
2231 self.assertTrue(rx[VXLAN].flags.G)
2232 self.assertTrue(rx[VXLAN].flags.Instance)
2233 self.assertTrue(rx[VXLAN].gpflags.A)
2234 self.assertFalse(rx[VXLAN].gpflags.D)
2236 inner = rx[VXLAN].payload
2238 self.assertEqual(inner[Ether].src, routed_src_mac)
2239 self.assertEqual(inner[Ether].dst, routed_dst_mac)
2240 self.assertEqual(inner[IP].src, ep.ip4.address)
2241 self.assertEqual(inner[IP].dst, l['ip'])
2244 self.assertFalse(find_gbp_endpoint(self,
2249 # learn some remote IPv6 EPs
2251 for ii, l in enumerate(learnt):
2252 # a packet with an sclass from a known EPG
2253 # arriving on an unknown TEP
2254 p = (Ether(src=self.pg2.remote_mac,
2255 dst=self.pg2.local_mac) /
2256 IP(src=self.pg2.remote_hosts[1].ip4,
2257 dst=self.pg2.local_ip4) /
2258 UDP(sport=1234, dport=48879) /
2259 VXLAN(vni=101, gpid=441, flags=0x88) /
2260 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2261 IPv6(src=l['ip6'], dst=ep.ip6.address) /
2262 UDP(sport=1234, dport=1234) /
2265 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2268 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2271 self.pg2.remote_hosts[1].ip4,
2273 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2275 self.logger.info(self.vapi.cli("show gbp bridge"))
2276 self.logger.info(self.vapi.cli("show vxlan-gbp tunnel"))
2277 self.logger.info(self.vapi.cli("show gbp vxlan"))
2278 self.logger.info(self.vapi.cli("show int addr"))
2280 # endpoint learnt via the TEP
2281 self.assertTrue(find_gbp_endpoint(self, ip=l['ip6']))
2283 self.logger.info(self.vapi.cli("show gbp endpoint"))
2284 self.logger.info(self.vapi.cli("show ip fib index 1 %s" % l['ip']))
2287 # Static EP replies to learnt
2290 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2291 IPv6(dst=l['ip6'], src=ep.ip6.address) /
2292 UDP(sport=1234, dport=1234) /
2295 rxs = self.send_and_expect(self.pg0, p*65, self.pg2)
2298 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2299 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2300 self.assertEqual(rx[UDP].dport, 48879)
2301 # the UDP source port is a random value for hashing
2302 self.assertEqual(rx[VXLAN].gpid, 441)
2303 self.assertEqual(rx[VXLAN].vni, 101)
2304 self.assertTrue(rx[VXLAN].flags.G)
2305 self.assertTrue(rx[VXLAN].flags.Instance)
2306 self.assertTrue(rx[VXLAN].gpflags.A)
2307 self.assertFalse(rx[VXLAN].gpflags.D)
2309 inner = rx[VXLAN].payload
2311 self.assertEqual(inner[Ether].src, routed_src_mac)
2312 self.assertEqual(inner[Ether].dst, routed_dst_mac)
2313 self.assertEqual(inner[IPv6].src, ep.ip6.address)
2314 self.assertEqual(inner[IPv6].dst, l['ip6'])
2316 self.logger.info(self.vapi.cli("sh gbp endpoint"))
2318 self.wait_for_ep_timeout(ip=l['ip'])
2321 # Static sends to unknown EP with no route
2323 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2324 IP(dst="10.0.0.99", src=ep.ip4.address) /
2325 UDP(sport=1234, dport=1234) /
2328 self.send_and_assert_no_replies(self.pg0, [p])
2331 # Add a route to static EP's v4 and v6 subnet
2332 # packets should be sent on the v4/v6 uu=fwd interface resp.
2334 se_10_24 = VppGbpSubnet(
2335 self, rd1, "10.0.0.0", 24,
2336 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT)
2337 se_10_24.add_vpp_config()
2339 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2340 IP(dst="10.0.0.99", src=ep.ip4.address) /
2341 UDP(sport=1234, dport=1234) /
2344 rxs = self.send_and_expect(self.pg0, [p], self.pg4)
2346 self.assertEqual(rx[IP].src, self.pg4.local_ip4)
2347 self.assertEqual(rx[IP].dst, self.pg4.remote_ip4)
2348 self.assertEqual(rx[UDP].dport, 48879)
2349 # the UDP source port is a random value for hashing
2350 self.assertEqual(rx[VXLAN].gpid, 441)
2351 self.assertEqual(rx[VXLAN].vni, 114)
2352 self.assertTrue(rx[VXLAN].flags.G)
2353 self.assertTrue(rx[VXLAN].flags.Instance)
2354 # policy is not applied to packets sent to the uu-fwd interfaces
2355 self.assertFalse(rx[VXLAN].gpflags.A)
2356 self.assertFalse(rx[VXLAN].gpflags.D)
2359 # learn some remote IPv4 EPs
2361 for ii, l in enumerate(learnt):
2362 # a packet with an sclass from a known EPG
2363 # arriving on an unknown TEP
2364 p = (Ether(src=self.pg2.remote_mac,
2365 dst=self.pg2.local_mac) /
2366 IP(src=self.pg2.remote_hosts[2].ip4,
2367 dst=self.pg2.local_ip4) /
2368 UDP(sport=1234, dport=48879) /
2369 VXLAN(vni=101, gpid=441, flags=0x88) /
2370 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2371 IP(src=l['ip'], dst=ep.ip4.address) /
2372 UDP(sport=1234, dport=1234) /
2375 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2378 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2381 self.pg2.remote_hosts[2].ip4,
2383 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2385 # endpoint learnt via the parent GBP-vxlan interface
2386 self.assertTrue(find_gbp_endpoint(self,
2387 vx_tun_l3._sw_if_index,
2391 # Add a remote endpoint from the API
2393 rep_88 = VppGbpEndpoint(self, vx_tun_l3,
2395 "10.0.0.88", "11.0.0.88",
2396 "2001:10::88", "3001::88",
2397 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
2399 self.pg2.remote_hosts[1].ip4,
2401 rep_88.add_vpp_config()
2404 # Add a remote endpoint from the API that matches an existing one
2406 rep_2 = VppGbpEndpoint(self, vx_tun_l3,
2408 learnt[0]['ip'], "11.0.0.101",
2409 learnt[0]['ip6'], "3001::101",
2410 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
2412 self.pg2.remote_hosts[1].ip4,
2414 rep_2.add_vpp_config()
2417 # Add a route to the learned EP's v4 subnet
2418 # packets should be send on the v4/v6 uu=fwd interface resp.
2420 se_10_1_24 = VppGbpSubnet(
2421 self, rd1, "10.0.1.0", 24,
2422 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT)
2423 se_10_1_24.add_vpp_config()
2425 self.logger.info(self.vapi.cli("show gbp endpoint"))
2427 ips = ["10.0.0.88", learnt[0]['ip']]
2429 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2430 IP(dst=ip, src=ep.ip4.address) /
2431 UDP(sport=1234, dport=1234) /
2434 rxs = self.send_and_expect(self.pg0, p*65, self.pg2)
2437 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2438 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2439 self.assertEqual(rx[UDP].dport, 48879)
2440 # the UDP source port is a random value for hashing
2441 self.assertEqual(rx[VXLAN].gpid, 441)
2442 self.assertEqual(rx[VXLAN].vni, 101)
2443 self.assertTrue(rx[VXLAN].flags.G)
2444 self.assertTrue(rx[VXLAN].flags.Instance)
2445 self.assertTrue(rx[VXLAN].gpflags.A)
2446 self.assertFalse(rx[VXLAN].gpflags.D)
2448 inner = rx[VXLAN].payload
2450 self.assertEqual(inner[Ether].src, routed_src_mac)
2451 self.assertEqual(inner[Ether].dst, routed_dst_mac)
2452 self.assertEqual(inner[IP].src, ep.ip4.address)
2453 self.assertEqual(inner[IP].dst, ip)
2456 # remove the API remote EPs, only API sourced is gone, the DP
2457 # learnt one remains
2459 rep_88.remove_vpp_config()
2460 rep_2.remove_vpp_config()
2462 self.assertTrue(find_gbp_endpoint(self, ip=rep_2.ip4.address))
2464 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2465 IP(src=ep.ip4.address, dst=rep_2.ip4.address) /
2466 UDP(sport=1234, dport=1234) /
2468 rxs = self.send_and_expect(self.pg0, [p], self.pg2)
2470 self.assertFalse(find_gbp_endpoint(self, ip=rep_88.ip4.address))
2472 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2473 IP(src=ep.ip4.address, dst=rep_88.ip4.address) /
2474 UDP(sport=1234, dport=1234) /
2476 rxs = self.send_and_expect(self.pg0, [p], self.pg4)
2479 # to appease the testcase we cannot have the registered EP still
2480 # present (because it's DP learnt) when the TC ends so wait until
2483 self.wait_for_ep_timeout(ip=rep_88.ip4.address)
2484 self.wait_for_ep_timeout(ip=rep_2.ip4.address)
2487 # shutdown with learnt endpoint present
2489 p = (Ether(src=self.pg2.remote_mac,
2490 dst=self.pg2.local_mac) /
2491 IP(src=self.pg2.remote_hosts[1].ip4,
2492 dst=self.pg2.local_ip4) /
2493 UDP(sport=1234, dport=48879) /
2494 VXLAN(vni=101, gpid=441, flags=0x88) /
2495 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2496 IP(src=learnt[1]['ip'], dst=ep.ip4.address) /
2497 UDP(sport=1234, dport=1234) /
2500 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2502 # endpoint learnt via the parent GBP-vxlan interface
2503 self.assertTrue(find_gbp_endpoint(self,
2504 vx_tun_l3._sw_if_index,
2509 # remote endpoint becomes local
2511 self.pg2.unconfig_ip4()
2512 self.pg3.unconfig_ip4()
2513 self.pg4.unconfig_ip4()
2515 def test_gbp_redirect(self):
2516 """ GBP Endpoint Redirect """
2518 self.vapi.cli("set logging class gbp debug")
2520 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
2521 routed_dst_mac = "00:0c:0c:0c:0c:0c"
2522 routed_src_mac = "00:22:bd:f8:19:ff"
2524 learnt = [{'mac': '00:00:11:11:11:02',
2526 'ip6': '2001:10::2'},
2527 {'mac': '00:00:11:11:11:03',
2529 'ip6': '2001:10::3'}]
2534 t4 = VppIpTable(self, 1)
2536 t6 = VppIpTable(self, 1, True)
2539 rd1 = VppGbpRouteDomain(self, 2, t4, t6)
2540 rd1.add_vpp_config()
2542 self.loop0.set_mac(self.router_mac)
2545 # Bind the BVI to the RD
2547 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
2548 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
2551 # Pg7 hosts a BD's UU-fwd
2553 self.pg7.config_ip4()
2554 self.pg7.resolve_arp()
2557 # a GBP bridge domains for the EPs
2559 bd1 = VppBridgeDomain(self, 1)
2560 bd1.add_vpp_config()
2561 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0)
2562 gbd1.add_vpp_config()
2564 bd2 = VppBridgeDomain(self, 2)
2565 bd2.add_vpp_config()
2566 gbd2 = VppGbpBridgeDomain(self, bd2, self.loop1)
2567 gbd2.add_vpp_config()
2569 # ... and has a /32 and /128 applied
2570 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2571 ip4_addr.add_vpp_config()
2572 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 128)
2573 ip6_addr.add_vpp_config()
2574 ip4_addr = VppIpInterfaceAddress(self, gbd2.bvi, "10.0.1.128", 32)
2575 ip4_addr.add_vpp_config()
2576 ip6_addr = VppIpInterfaceAddress(self, gbd2.bvi, "2001:11::128", 128)
2577 ip6_addr.add_vpp_config()
2580 # The Endpoint-groups in which we are learning endpoints
2582 epg_220 = VppGbpEndpointGroup(self, 220, 440, rd1, gbd1,
2586 VppGbpEndpointRetention(2))
2587 epg_220.add_vpp_config()
2588 epg_221 = VppGbpEndpointGroup(self, 221, 441, rd1, gbd2,
2592 VppGbpEndpointRetention(2))
2593 epg_221.add_vpp_config()
2594 epg_222 = VppGbpEndpointGroup(self, 222, 442, rd1, gbd1,
2598 VppGbpEndpointRetention(2))
2599 epg_222.add_vpp_config()
2602 # a GBP bridge domains for the SEPs
2604 bd_uu1 = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
2605 self.pg7.remote_ip4, 116)
2606 bd_uu1.add_vpp_config()
2607 bd_uu2 = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
2608 self.pg7.remote_ip4, 117)
2609 bd_uu2.add_vpp_config()
2611 bd3 = VppBridgeDomain(self, 3)
2612 bd3.add_vpp_config()
2613 gbd3 = VppGbpBridgeDomain(self, bd3, self.loop2, bd_uu1, learn=False)
2614 gbd3.add_vpp_config()
2615 bd4 = VppBridgeDomain(self, 4)
2616 bd4.add_vpp_config()
2617 gbd4 = VppGbpBridgeDomain(self, bd4, self.loop3, bd_uu2, learn=False)
2618 gbd4.add_vpp_config()
2621 # EPGs in which the service endpoints exist
2623 epg_320 = VppGbpEndpointGroup(self, 320, 550, rd1, gbd3,
2627 VppGbpEndpointRetention(2))
2628 epg_320.add_vpp_config()
2629 epg_321 = VppGbpEndpointGroup(self, 321, 551, rd1, gbd4,
2633 VppGbpEndpointRetention(2))
2634 epg_321.add_vpp_config()
2637 # three local endpoints
2639 ep1 = VppGbpEndpoint(self, self.pg0,
2641 "10.0.0.1", "11.0.0.1",
2642 "2001:10::1", "3001:10::1")
2643 ep1.add_vpp_config()
2644 ep2 = VppGbpEndpoint(self, self.pg1,
2646 "10.0.1.1", "11.0.1.1",
2647 "2001:11::1", "3001:11::1")
2648 ep2.add_vpp_config()
2649 ep3 = VppGbpEndpoint(self, self.pg2,
2651 "10.0.2.2", "11.0.2.2",
2652 "2001:12::1", "3001:12::1")
2653 ep3.add_vpp_config()
2658 sep1 = VppGbpEndpoint(self, self.pg3,
2660 "12.0.0.1", "13.0.0.1",
2661 "4001:10::1", "5001:10::1")
2662 sep1.add_vpp_config()
2663 sep2 = VppGbpEndpoint(self, self.pg4,
2665 "12.0.0.2", "13.0.0.2",
2666 "4001:10::2", "5001:10::2")
2667 sep2.add_vpp_config()
2668 sep3 = VppGbpEndpoint(self, self.pg5,
2670 "12.0.1.1", "13.0.1.1",
2671 "4001:11::1", "5001:11::1")
2672 sep3.add_vpp_config()
2673 # this EP is not installed immediately
2674 sep4 = VppGbpEndpoint(self, self.pg6,
2676 "12.0.1.2", "13.0.1.2",
2677 "4001:11::2", "5001:11::2")
2680 # an L2 switch packet between local EPs in different EPGs
2681 # different dest ports on each so the are LB hashed differently
2683 p4 = [(Ether(src=ep1.mac, dst=ep3.mac) /
2684 IP(src=ep1.ip4.address, dst=ep3.ip4.address) /
2685 UDP(sport=1234, dport=1234) /
2687 (Ether(src=ep3.mac, dst=ep1.mac) /
2688 IP(src=ep3.ip4.address, dst=ep1.ip4.address) /
2689 UDP(sport=1234, dport=1234) /
2691 p6 = [(Ether(src=ep1.mac, dst=ep3.mac) /
2692 IPv6(src=ep1.ip6.address, dst=ep3.ip6.address) /
2693 UDP(sport=1234, dport=1234) /
2695 (Ether(src=ep3.mac, dst=ep1.mac) /
2696 IPv6(src=ep3.ip6.address, dst=ep1.ip6.address) /
2697 UDP(sport=1234, dport=1230) /
2700 # should be dropped since no contract yet
2701 self.send_and_assert_no_replies(self.pg0, [p4[0]])
2702 self.send_and_assert_no_replies(self.pg0, [p6[0]])
2705 # Add a contract with a rule to load-balance redirect via SEP1 and SEP2
2706 # one of the next-hops is via an EP that is not known
2708 acl = VppGbpAcl(self)
2709 rule4 = acl.create_rule(permit_deny=1, proto=17)
2710 rule6 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
2711 acl_index = acl.add_vpp_config([rule4, rule6])
2714 # test the src-ip hash mode
2716 c1 = VppGbpContract(
2717 self, epg_220.sclass, epg_222.sclass, acl_index,
2718 [VppGbpContractRule(
2719 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2720 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2721 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
2722 sep1.ip4, sep1.epg.rd),
2723 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
2724 sep2.ip4, sep2.epg.rd)]),
2726 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2727 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2728 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
2729 sep3.ip6, sep3.epg.rd),
2730 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
2731 sep4.ip6, sep4.epg.rd)])],
2732 [ETH_P_IP, ETH_P_IPV6])
2735 c2 = VppGbpContract(
2736 self, epg_222.sclass, epg_220.sclass, acl_index,
2737 [VppGbpContractRule(
2738 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2739 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2740 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
2741 sep1.ip4, sep1.epg.rd),
2742 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
2743 sep2.ip4, sep2.epg.rd)]),
2745 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2746 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2747 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
2748 sep3.ip6, sep3.epg.rd),
2749 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
2750 sep4.ip6, sep4.epg.rd)])],
2751 [ETH_P_IP, ETH_P_IPV6])
2755 # send again with the contract preset, now packets arrive
2756 # at SEP1 or SEP2 depending on the hashing
2758 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
2761 self.assertEqual(rx[Ether].src, routed_src_mac)
2762 self.assertEqual(rx[Ether].dst, sep1.mac)
2763 self.assertEqual(rx[IP].src, ep1.ip4.address)
2764 self.assertEqual(rx[IP].dst, ep3.ip4.address)
2766 rxs = self.send_and_expect(self.pg2, p4[1] * 17, sep2.itf)
2769 self.assertEqual(rx[Ether].src, routed_src_mac)
2770 self.assertEqual(rx[Ether].dst, sep2.mac)
2771 self.assertEqual(rx[IP].src, ep3.ip4.address)
2772 self.assertEqual(rx[IP].dst, ep1.ip4.address)
2774 rxs = self.send_and_expect(self.pg0, p6[0] * 17, self.pg7)
2777 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
2778 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
2779 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
2780 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
2781 self.assertEqual(rx[VXLAN].vni, 117)
2782 self.assertTrue(rx[VXLAN].flags.G)
2783 self.assertTrue(rx[VXLAN].flags.Instance)
2784 # redirect policy has been applied
2785 self.assertTrue(rx[VXLAN].gpflags.A)
2786 self.assertFalse(rx[VXLAN].gpflags.D)
2788 inner = rx[VXLAN].payload
2790 self.assertEqual(inner[Ether].src, routed_src_mac)
2791 self.assertEqual(inner[Ether].dst, sep4.mac)
2792 self.assertEqual(inner[IPv6].src, ep1.ip6.address)
2793 self.assertEqual(inner[IPv6].dst, ep3.ip6.address)
2795 rxs = self.send_and_expect(self.pg2, p6[1] * 17, sep3.itf)
2798 self.assertEqual(rx[Ether].src, routed_src_mac)
2799 self.assertEqual(rx[Ether].dst, sep3.mac)
2800 self.assertEqual(rx[IPv6].src, ep3.ip6.address)
2801 self.assertEqual(rx[IPv6].dst, ep1.ip6.address)
2804 # programme the unknown EP
2806 sep4.add_vpp_config()
2808 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep4.itf)
2811 self.assertEqual(rx[Ether].src, routed_src_mac)
2812 self.assertEqual(rx[Ether].dst, sep4.mac)
2813 self.assertEqual(rx[IPv6].src, ep1.ip6.address)
2814 self.assertEqual(rx[IPv6].dst, ep3.ip6.address)
2817 # and revert back to unprogrammed
2819 sep4.remove_vpp_config()
2821 rxs = self.send_and_expect(self.pg0, p6[0] * 17, self.pg7)
2824 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
2825 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
2826 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
2827 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
2828 self.assertEqual(rx[VXLAN].vni, 117)
2829 self.assertTrue(rx[VXLAN].flags.G)
2830 self.assertTrue(rx[VXLAN].flags.Instance)
2831 # redirect policy has been applied
2832 self.assertTrue(rx[VXLAN].gpflags.A)
2833 self.assertFalse(rx[VXLAN].gpflags.D)
2835 inner = rx[VXLAN].payload
2837 self.assertEqual(inner[Ether].src, routed_src_mac)
2838 self.assertEqual(inner[Ether].dst, sep4.mac)
2839 self.assertEqual(inner[IPv6].src, ep1.ip6.address)
2840 self.assertEqual(inner[IPv6].dst, ep3.ip6.address)
2842 c1.remove_vpp_config()
2843 c2.remove_vpp_config()
2846 # test the symmetric hash mode
2848 c1 = VppGbpContract(
2849 self, epg_220.sclass, epg_222.sclass, acl_index,
2850 [VppGbpContractRule(
2851 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2852 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
2853 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
2854 sep1.ip4, sep1.epg.rd),
2855 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
2856 sep2.ip4, sep2.epg.rd)]),
2858 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2859 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
2860 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
2861 sep3.ip6, sep3.epg.rd),
2862 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
2863 sep4.ip6, sep4.epg.rd)])],
2864 [ETH_P_IP, ETH_P_IPV6])
2867 c2 = VppGbpContract(
2868 self, epg_222.sclass, epg_220.sclass, acl_index,
2869 [VppGbpContractRule(
2870 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2871 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
2872 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
2873 sep1.ip4, sep1.epg.rd),
2874 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
2875 sep2.ip4, sep2.epg.rd)]),
2877 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2878 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
2879 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
2880 sep3.ip6, sep3.epg.rd),
2881 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
2882 sep4.ip6, sep4.epg.rd)])],
2883 [ETH_P_IP, ETH_P_IPV6])
2887 # send again with the contract preset, now packets arrive
2888 # at SEP1 for both directions
2890 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
2893 self.assertEqual(rx[Ether].src, routed_src_mac)
2894 self.assertEqual(rx[Ether].dst, sep1.mac)
2895 self.assertEqual(rx[IP].src, ep1.ip4.address)
2896 self.assertEqual(rx[IP].dst, ep3.ip4.address)
2898 rxs = self.send_and_expect(self.pg2, p4[1] * 17, sep1.itf)
2901 self.assertEqual(rx[Ether].src, routed_src_mac)
2902 self.assertEqual(rx[Ether].dst, sep1.mac)
2903 self.assertEqual(rx[IP].src, ep3.ip4.address)
2904 self.assertEqual(rx[IP].dst, ep1.ip4.address)
2907 # programme the unknown EP for the L3 tests
2909 sep4.add_vpp_config()
2912 # an L3 switch packet between local EPs in different EPGs
2913 # different dest ports on each so the are LB hashed differently
2915 p4 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
2916 IP(src=ep1.ip4.address, dst=ep2.ip4.address) /
2917 UDP(sport=1234, dport=1234) /
2919 (Ether(src=ep2.mac, dst=str(self.router_mac)) /
2920 IP(src=ep2.ip4.address, dst=ep1.ip4.address) /
2921 UDP(sport=1234, dport=1234) /
2923 p6 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
2924 IPv6(src=ep1.ip6.address, dst=ep2.ip6.address) /
2925 UDP(sport=1234, dport=1234) /
2927 (Ether(src=ep2.mac, dst=str(self.router_mac)) /
2928 IPv6(src=ep2.ip6.address, dst=ep1.ip6.address) /
2929 UDP(sport=1234, dport=1234) /
2932 c3 = VppGbpContract(
2933 self, epg_220.sclass, epg_221.sclass, acl_index,
2934 [VppGbpContractRule(
2935 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2936 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
2937 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
2938 sep1.ip4, sep1.epg.rd),
2939 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
2940 sep2.ip4, sep2.epg.rd)]),
2942 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2943 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
2944 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
2945 sep3.ip6, sep3.epg.rd),
2946 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
2947 sep4.ip6, sep4.epg.rd)])],
2948 [ETH_P_IP, ETH_P_IPV6])
2951 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
2954 self.assertEqual(rx[Ether].src, routed_src_mac)
2955 self.assertEqual(rx[Ether].dst, sep1.mac)
2956 self.assertEqual(rx[IP].src, ep1.ip4.address)
2957 self.assertEqual(rx[IP].dst, ep2.ip4.address)
2960 # learn a remote EP in EPG 221
2962 vx_tun_l3 = VppGbpVxlanTunnel(
2963 self, 444, rd1.rd_id,
2964 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
2966 vx_tun_l3.add_vpp_config()
2968 c4 = VppGbpContract(
2969 self, epg_221.sclass, epg_220.sclass, acl_index,
2970 [VppGbpContractRule(
2971 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2974 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2976 [ETH_P_IP, ETH_P_IPV6])
2979 p = (Ether(src=self.pg7.remote_mac,
2980 dst=self.pg7.local_mac) /
2981 IP(src=self.pg7.remote_ip4,
2982 dst=self.pg7.local_ip4) /
2983 UDP(sport=1234, dport=48879) /
2984 VXLAN(vni=444, gpid=441, flags=0x88) /
2985 Ether(src="00:22:22:22:22:33", dst=str(self.router_mac)) /
2986 IP(src="10.0.0.88", dst=ep1.ip4.address) /
2987 UDP(sport=1234, dport=1234) /
2990 rx = self.send_and_expect(self.pg7, [p], self.pg0)
2992 # endpoint learnt via the parent GBP-vxlan interface
2993 self.assertTrue(find_gbp_endpoint(self,
2994 vx_tun_l3._sw_if_index,
2997 p = (Ether(src=self.pg7.remote_mac,
2998 dst=self.pg7.local_mac) /
2999 IP(src=self.pg7.remote_ip4,
3000 dst=self.pg7.local_ip4) /
3001 UDP(sport=1234, dport=48879) /
3002 VXLAN(vni=444, gpid=441, flags=0x88) /
3003 Ether(src="00:22:22:22:22:33", dst=str(self.router_mac)) /
3004 IPv6(src="2001:10::88", dst=ep1.ip6.address) /
3005 UDP(sport=1234, dport=1234) /
3008 rx = self.send_and_expect(self.pg7, [p], self.pg0)
3010 # endpoint learnt via the parent GBP-vxlan interface
3011 self.assertTrue(find_gbp_endpoint(self,
3012 vx_tun_l3._sw_if_index,
3016 # L3 switch from local to remote EP
3018 p4 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3019 IP(src=ep1.ip4.address, dst="10.0.0.88") /
3020 UDP(sport=1234, dport=1234) /
3022 p6 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3023 IPv6(src=ep1.ip6.address, dst="2001:10::88") /
3024 UDP(sport=1234, dport=1234) /
3027 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3030 self.assertEqual(rx[Ether].src, routed_src_mac)
3031 self.assertEqual(rx[Ether].dst, sep1.mac)
3032 self.assertEqual(rx[IP].src, ep1.ip4.address)
3033 self.assertEqual(rx[IP].dst, "10.0.0.88")
3035 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep4.itf)
3038 self.assertEqual(rx[Ether].src, routed_src_mac)
3039 self.assertEqual(rx[Ether].dst, sep4.mac)
3040 self.assertEqual(rx[IPv6].src, ep1.ip6.address)
3041 self.assertEqual(rx[IPv6].dst, "2001:10::88")
3044 # test the dst-ip hash mode
3046 c5 = VppGbpContract(
3047 self, epg_220.sclass, epg_221.sclass, acl_index,
3048 [VppGbpContractRule(
3049 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3050 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
3051 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3052 sep1.ip4, sep1.epg.rd),
3053 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3054 sep2.ip4, sep2.epg.rd)]),
3056 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3057 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
3058 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3059 sep3.ip6, sep3.epg.rd),
3060 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3061 sep4.ip6, sep4.epg.rd)])],
3062 [ETH_P_IP, ETH_P_IPV6])
3065 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3068 self.assertEqual(rx[Ether].src, routed_src_mac)
3069 self.assertEqual(rx[Ether].dst, sep1.mac)
3070 self.assertEqual(rx[IP].src, ep1.ip4.address)
3071 self.assertEqual(rx[IP].dst, "10.0.0.88")
3073 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep3.itf)
3076 self.assertEqual(rx[Ether].src, routed_src_mac)
3077 self.assertEqual(rx[Ether].dst, sep3.mac)
3078 self.assertEqual(rx[IPv6].src, ep1.ip6.address)
3079 self.assertEqual(rx[IPv6].dst, "2001:10::88")
3084 self.pg7.unconfig_ip4()
3086 def test_gbp_l3_out(self):
3089 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
3090 self.vapi.cli("set logging class gbp debug")
3092 routed_dst_mac = "00:0c:0c:0c:0c:0c"
3093 routed_src_mac = "00:22:bd:f8:19:ff"
3098 t4 = VppIpTable(self, 1)
3100 t6 = VppIpTable(self, 1, True)
3103 rd1 = VppGbpRouteDomain(self, 2, t4, t6)
3104 rd1.add_vpp_config()
3106 self.loop0.set_mac(self.router_mac)
3109 # Bind the BVI to the RD
3111 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
3112 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
3115 # Pg7 hosts a BD's BUM
3116 # Pg1 some other l3 interface
3118 self.pg7.config_ip4()
3119 self.pg7.resolve_arp()
3122 # a multicast vxlan-gbp tunnel for broadcast in the BD
3124 tun_bm = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
3127 tun_bm.add_vpp_config()
3130 # a GBP external bridge domains for the EPs
3132 bd1 = VppBridgeDomain(self, 1)
3133 bd1.add_vpp_config()
3134 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0, None, tun_bm)
3135 gbd1.add_vpp_config()
3138 # The Endpoint-groups in which the external endpoints exist
3140 epg_220 = VppGbpEndpointGroup(self, 220, 113, rd1, gbd1,
3144 VppGbpEndpointRetention(2))
3145 epg_220.add_vpp_config()
3147 # the BVIs have the subnets applied ...
3148 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 24)
3149 ip4_addr.add_vpp_config()
3150 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 64)
3151 ip6_addr.add_vpp_config()
3153 # ... which are L3-out subnets
3154 l3o_1 = VppGbpSubnet(
3155 self, rd1, "10.0.0.0", 24,
3156 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3158 l3o_1.add_vpp_config()
3161 # an external interface attached to the outside world and the
3164 vlan_100 = VppDot1QSubint(self, self.pg0, 100)
3166 VppL2Vtr(self, vlan_100, L2_VTR_OP.L2_POP_1).add_vpp_config()
3167 vlan_101 = VppDot1QSubint(self, self.pg0, 101)
3169 VppL2Vtr(self, vlan_101, L2_VTR_OP.L2_POP_1).add_vpp_config()
3171 ext_itf = VppGbpExtItf(self, self.loop0, bd1, rd1)
3172 ext_itf.add_vpp_config()
3175 # an unicast vxlan-gbp for inter-RD traffic
3177 vx_tun_l3 = VppGbpVxlanTunnel(
3178 self, 444, rd1.rd_id,
3179 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
3181 vx_tun_l3.add_vpp_config()
3184 # External Endpoints
3186 eep1 = VppGbpEndpoint(self, vlan_100,
3188 "10.0.0.1", "11.0.0.1",
3189 "2001:10::1", "3001::1",
3190 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
3191 eep1.add_vpp_config()
3192 eep2 = VppGbpEndpoint(self, vlan_101,
3194 "10.0.0.2", "11.0.0.2",
3195 "2001:10::2", "3001::2",
3196 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
3197 eep2.add_vpp_config()
3200 # A remote external endpoint
3202 rep = VppGbpEndpoint(self, vx_tun_l3,
3204 "10.0.0.101", "11.0.0.101",
3205 "2001:10::101", "3001::101",
3206 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
3208 self.pg7.remote_ip4,
3210 rep.add_vpp_config()
3213 # ARP packet from External EPs are accepted and replied to
3215 p_arp = (Ether(src=eep1.mac, dst="ff:ff:ff:ff:ff:ff") /
3218 psrc=eep1.ip4.address, pdst="10.0.0.128",
3219 hwsrc=eep1.mac, hwdst="ff:ff:ff:ff:ff:ff"))
3220 rxs = self.send_and_expect(self.pg0, p_arp * 1, self.pg0)
3223 # packets destined to unknown addresses in the BVI's subnet
3226 p4 = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3228 IP(src="10.0.0.1", dst="10.0.0.88") /
3229 UDP(sport=1234, dport=1234) /
3231 p6 = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3233 IPv6(src="2001:10::1", dst="2001:10::88") /
3234 UDP(sport=1234, dport=1234) /
3237 rxs = self.send_and_expect(self.pg0, p4 * 1, self.pg7)
3240 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3241 # self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3242 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3243 self.assertEqual(rx[IP].dst, "239.1.1.1")
3244 self.assertEqual(rx[VXLAN].vni, 88)
3245 self.assertTrue(rx[VXLAN].flags.G)
3246 self.assertTrue(rx[VXLAN].flags.Instance)
3247 # policy was applied to the original IP packet
3248 self.assertEqual(rx[VXLAN].gpid, 113)
3249 self.assertTrue(rx[VXLAN].gpflags.A)
3250 self.assertFalse(rx[VXLAN].gpflags.D)
3252 inner = rx[VXLAN].payload
3254 self.assertTrue(inner.haslayer(ARP))
3257 # remote to external
3259 p = (Ether(src=self.pg7.remote_mac,
3260 dst=self.pg7.local_mac) /
3261 IP(src=self.pg7.remote_ip4,
3262 dst=self.pg7.local_ip4) /
3263 UDP(sport=1234, dport=48879) /
3264 VXLAN(vni=444, gpid=113, flags=0x88) /
3265 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
3266 IP(src="10.0.0.101", dst="10.0.0.1") /
3267 UDP(sport=1234, dport=1234) /
3270 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
3273 # local EP pings router
3275 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3277 IP(src=eep1.ip4.address, dst="10.0.0.128") /
3278 ICMP(type='echo-request'))
3280 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
3283 self.assertEqual(rx[Ether].src, str(self.router_mac))
3284 self.assertEqual(rx[Ether].dst, eep1.mac)
3285 self.assertEqual(rx[Dot1Q].vlan, 100)
3288 # local EP pings other local EP
3290 p = (Ether(src=eep1.mac, dst=eep2.mac) /
3292 IP(src=eep1.ip4.address, dst=eep2.ip4.address) /
3293 ICMP(type='echo-request'))
3295 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
3298 self.assertEqual(rx[Ether].src, eep1.mac)
3299 self.assertEqual(rx[Ether].dst, eep2.mac)
3300 self.assertEqual(rx[Dot1Q].vlan, 101)
3303 # A subnet reachable through the external EP1
3305 ip_220 = VppIpRoute(self, "10.220.0.0", 24,
3306 [VppRoutePath(eep1.ip4.address,
3307 eep1.epg.bvi.sw_if_index)],
3308 table_id=t4.table_id)
3309 ip_220.add_vpp_config()
3311 l3o_220 = VppGbpSubnet(
3312 self, rd1, "10.220.0.0", 24,
3313 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3315 l3o_220.add_vpp_config()
3318 # A subnet reachable through the external EP2
3320 ip_221 = VppIpRoute(self, "10.221.0.0", 24,
3321 [VppRoutePath(eep2.ip4.address,
3322 eep2.epg.bvi.sw_if_index)],
3323 table_id=t4.table_id)
3324 ip_221.add_vpp_config()
3326 l3o_221 = VppGbpSubnet(
3327 self, rd1, "10.221.0.0", 24,
3328 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3330 l3o_221.add_vpp_config()
3333 # ping between hosts in remote subnets
3334 # dropped without a contract
3336 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3338 IP(src="10.220.0.1", dst="10.221.0.1") /
3339 ICMP(type='echo-request'))
3341 rxs = self.send_and_assert_no_replies(self.pg0, p * 1)
3344 # contract for the external nets to communicate
3346 acl = VppGbpAcl(self)
3347 rule4 = acl.create_rule(permit_deny=1, proto=17)
3348 rule6 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
3349 acl_index = acl.add_vpp_config([rule4, rule6])
3351 c1 = VppGbpContract(
3352 self, 4220, 4221, acl_index,
3353 [VppGbpContractRule(
3354 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3357 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3359 [ETH_P_IP, ETH_P_IPV6])
3363 # Contracts allowing ext-net 200 to talk with external EPs
3365 c2 = VppGbpContract(
3366 self, 4220, 113, acl_index,
3367 [VppGbpContractRule(
3368 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3371 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3373 [ETH_P_IP, ETH_P_IPV6])
3375 c3 = VppGbpContract(
3376 self, 113, 4220, acl_index,
3377 [VppGbpContractRule(
3378 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3381 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3383 [ETH_P_IP, ETH_P_IPV6])
3387 # ping between hosts in remote subnets
3389 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3391 IP(src="10.220.0.1", dst="10.221.0.1") /
3392 UDP(sport=1234, dport=1234) /
3395 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
3398 self.assertEqual(rx[Ether].src, str(self.router_mac))
3399 self.assertEqual(rx[Ether].dst, eep2.mac)
3400 self.assertEqual(rx[Dot1Q].vlan, 101)
3402 # we did not learn these external hosts
3403 self.assertFalse(find_gbp_endpoint(self, ip="10.220.0.1"))
3404 self.assertFalse(find_gbp_endpoint(self, ip="10.221.0.1"))
3407 # from remote external EP to local external EP
3409 p = (Ether(src=self.pg7.remote_mac,
3410 dst=self.pg7.local_mac) /
3411 IP(src=self.pg7.remote_ip4,
3412 dst=self.pg7.local_ip4) /
3413 UDP(sport=1234, dport=48879) /
3414 VXLAN(vni=444, gpid=113, flags=0x88) /
3415 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
3416 IP(src="10.0.0.101", dst="10.220.0.1") /
3417 UDP(sport=1234, dport=1234) /
3420 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
3423 # ping from an external host to the remote external EP
3425 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3427 IP(src="10.220.0.1", dst=rep.ip4.address) /
3428 UDP(sport=1234, dport=1234) /
3431 rxs = self.send_and_expect(self.pg0, p * 1, self.pg7)
3434 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3435 # self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3436 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3437 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
3438 self.assertEqual(rx[VXLAN].vni, 444)
3439 self.assertTrue(rx[VXLAN].flags.G)
3440 self.assertTrue(rx[VXLAN].flags.Instance)
3441 # the sclass of the ext-net the packet came from
3442 self.assertEqual(rx[VXLAN].gpid, 4220)
3443 # policy was applied to the original IP packet
3444 self.assertTrue(rx[VXLAN].gpflags.A)
3445 # since it's an external host the reciever should not learn it
3446 self.assertTrue(rx[VXLAN].gpflags.D)
3447 inner = rx[VXLAN].payload
3448 self.assertEqual(inner[IP].src, "10.220.0.1")
3449 self.assertEqual(inner[IP].dst, rep.ip4.address)
3452 # An external subnet reachable via the remote external EP
3456 # first the VXLAN-GBP tunnel over which it is reached
3458 vx_tun_r = VppVxlanGbpTunnel(
3459 self, self.pg7.local_ip4,
3460 self.pg7.remote_ip4, 445,
3461 mode=(VppEnum.vl_api_vxlan_gbp_api_tunnel_mode_t.
3462 VXLAN_GBP_API_TUNNEL_MODE_L3))
3463 vx_tun_r.add_vpp_config()
3464 VppIpInterfaceBind(self, vx_tun_r, t4).add_vpp_config()
3466 self.logger.info(self.vapi.cli("sh vxlan-gbp tunnel"))
3469 # then the special adj to resolve through on that tunnel
3471 n1 = VppNeighbor(self,
3472 vx_tun_r.sw_if_index,
3473 "00:0c:0c:0c:0c:0c",
3474 self.pg7.remote_ip4)
3478 # the route via the adj above
3480 ip_222 = VppIpRoute(self, "10.222.0.0", 24,
3481 [VppRoutePath(self.pg7.remote_ip4,
3482 vx_tun_r.sw_if_index)],
3483 table_id=t4.table_id)
3484 ip_222.add_vpp_config()
3486 l3o_222 = VppGbpSubnet(
3487 self, rd1, "10.222.0.0", 24,
3488 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3490 l3o_222.add_vpp_config()
3493 # ping between hosts in local and remote external subnets
3494 # dropped without a contract
3496 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3498 IP(src="10.220.0.1", dst="10.222.0.1") /
3499 UDP(sport=1234, dport=1234) /
3502 rxs = self.send_and_assert_no_replies(self.pg0, p * 1)
3505 # Add contracts ext-nets for 220 -> 222
3507 c4 = VppGbpContract(
3508 self, 4220, 4222, acl_index,
3509 [VppGbpContractRule(
3510 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3513 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3515 [ETH_P_IP, ETH_P_IPV6])
3519 # ping from host in local to remote external subnets
3521 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3523 IP(src="10.220.0.1", dst="10.222.0.1") /
3524 UDP(sport=1234, dport=1234) /
3527 rxs = self.send_and_expect(self.pg0, p * 3, self.pg7)
3530 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3531 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3532 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3533 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
3534 self.assertEqual(rx[VXLAN].vni, 445)
3535 self.assertTrue(rx[VXLAN].flags.G)
3536 self.assertTrue(rx[VXLAN].flags.Instance)
3537 # the sclass of the ext-net the packet came from
3538 self.assertEqual(rx[VXLAN].gpid, 4220)
3539 # policy was applied to the original IP packet
3540 self.assertTrue(rx[VXLAN].gpflags.A)
3541 # since it's an external host the reciever should not learn it
3542 self.assertTrue(rx[VXLAN].gpflags.D)
3543 inner = rx[VXLAN].payload
3544 self.assertEqual(inner[Ether].dst, "00:0c:0c:0c:0c:0c")
3545 self.assertEqual(inner[IP].src, "10.220.0.1")
3546 self.assertEqual(inner[IP].dst, "10.222.0.1")
3549 # ping from host in remote to local external subnets
3550 # there's no contract for this, but the A bit is set.
3552 p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
3553 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
3554 UDP(sport=1234, dport=48879) /
3555 VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
3556 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
3557 IP(src="10.222.0.1", dst="10.220.0.1") /
3558 UDP(sport=1234, dport=1234) /
3561 rxs = self.send_and_expect(self.pg7, p * 3, self.pg0)
3562 self.assertFalse(find_gbp_endpoint(self, ip="10.222.0.1"))
3565 # ping from host in remote to remote external subnets
3566 # this is dropped by reflection check.
3568 p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
3569 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
3570 UDP(sport=1234, dport=48879) /
3571 VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
3572 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
3573 IP(src="10.222.0.1", dst="10.222.0.2") /
3574 UDP(sport=1234, dport=1234) /
3577 rxs = self.send_and_assert_no_replies(self.pg7, p * 3)
3582 self.pg7.unconfig_ip4()
3583 vlan_100.set_vtr(L2_VTR_OP.L2_DISABLED)
3586 if __name__ == '__main__':
3587 unittest.main(testRunner=VppTestRunner)