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,
1908 self.pg2.unconfig_ip4()
1909 self.pg3.unconfig_ip4()
1910 self.pg4.unconfig_ip4()
1912 self.logger.info(self.vapi.cli("sh int"))
1913 self.logger.info(self.vapi.cli("sh gbp vxlan"))
1915 def test_gbp_bd_flags(self):
1916 """ GBP BD FLAGS """
1921 gt4 = VppIpTable(self, 1)
1922 gt4.add_vpp_config()
1923 gt6 = VppIpTable(self, 1, is_ip6=True)
1924 gt6.add_vpp_config()
1926 rd1 = VppGbpRouteDomain(self, 1, gt4, gt6)
1927 rd1.add_vpp_config()
1930 # Pg3 hosts the IP4 UU-flood VXLAN tunnel
1931 # Pg4 hosts the IP6 UU-flood VXLAN tunnel
1933 self.pg3.config_ip4()
1934 self.pg3.resolve_arp()
1935 self.pg4.config_ip4()
1936 self.pg4.resolve_arp()
1939 # Add a mcast destination VXLAN-GBP tunnel for B&M traffic
1941 tun_bm = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
1944 tun_bm.add_vpp_config()
1947 # a GBP bridge domain with a BVI and a UU-flood interface
1949 bd1 = VppBridgeDomain(self, 1)
1950 bd1.add_vpp_config()
1952 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0, self.pg3, tun_bm,
1953 uu_drop=True, bm_drop=True)
1954 gbd1.add_vpp_config()
1956 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1957 self.logger.info(self.vapi.cli("sh gbp bridge"))
1959 # ... and has a /32 applied
1960 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
1961 ip_addr.add_vpp_config()
1964 # The Endpoint-group
1966 epg_220 = VppGbpEndpointGroup(self, 220, 112, rd1, gbd1,
1970 VppGbpEndpointRetention(2))
1971 epg_220.add_vpp_config()
1973 ep = VppGbpEndpoint(self, self.pg0,
1975 "10.0.0.127", "11.0.0.127",
1976 "2001:10::1", "3001::1")
1979 # send UU/BM packet from the local EP with UU drop and BM drop enabled
1982 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1983 self.logger.info(self.vapi.cli("sh gbp bridge"))
1984 p_uu = (Ether(src=ep.mac, dst="00:11:11:11:11:11") /
1985 IP(dst="10.0.0.133", src=ep.ip4.address) /
1986 UDP(sport=1234, dport=1234) /
1988 self.send_and_assert_no_replies(ep.itf, [p_uu])
1990 p_bm = (Ether(src=ep.mac, dst="ff:ff:ff:ff:ff:ff") /
1991 IP(dst="10.0.0.133", src=ep.ip4.address) /
1992 UDP(sport=1234, dport=1234) /
1994 self.send_and_assert_no_replies(ep.itf, [p_bm])
1996 self.pg3.unconfig_ip4()
1997 self.pg4.unconfig_ip4()
1999 self.logger.info(self.vapi.cli("sh int"))
2001 def test_gbp_learn_vlan_l2(self):
2002 """ GBP L2 Endpoint w/ VLANs"""
2004 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
2005 learnt = [{'mac': '00:00:11:11:11:01',
2007 'ip6': '2001:10::2'},
2008 {'mac': '00:00:11:11:11:02',
2010 'ip6': '2001:10::3'}]
2015 gt4 = VppIpTable(self, 1)
2016 gt4.add_vpp_config()
2017 gt6 = VppIpTable(self, 1, is_ip6=True)
2018 gt6.add_vpp_config()
2020 rd1 = VppGbpRouteDomain(self, 1, gt4, gt6)
2021 rd1.add_vpp_config()
2024 # Pg2 hosts the vxlan tunnel, hosts on pg2 to act as TEPs
2026 self.pg2.config_ip4()
2027 self.pg2.resolve_arp()
2028 self.pg2.generate_remote_hosts(4)
2029 self.pg2.configure_ipv4_neighbors()
2030 self.pg3.config_ip4()
2031 self.pg3.resolve_arp()
2034 # The EP will be on a vlan sub-interface
2036 vlan_11 = VppDot1QSubint(self, self.pg0, 11)
2038 self.vapi.l2_interface_vlan_tag_rewrite(
2039 sw_if_index=vlan_11.sw_if_index, vtr_op=L2_VTR_OP.L2_POP_1,
2042 bd_uu_fwd = VppVxlanGbpTunnel(self, self.pg3.local_ip4,
2043 self.pg3.remote_ip4, 116)
2044 bd_uu_fwd.add_vpp_config()
2047 # a GBP bridge domain with a BVI and a UU-flood interface
2048 # The BD is marked as do not learn, so no endpoints are ever
2049 # learnt in this BD.
2051 bd1 = VppBridgeDomain(self, 1)
2052 bd1.add_vpp_config()
2053 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0, bd_uu_fwd,
2055 gbd1.add_vpp_config()
2057 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2058 self.logger.info(self.vapi.cli("sh gbp bridge"))
2060 # ... and has a /32 applied
2061 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2062 ip_addr.add_vpp_config()
2065 # The Endpoint-group in which we are learning endpoints
2067 epg_220 = VppGbpEndpointGroup(self, 220, 441, rd1, gbd1,
2071 VppGbpEndpointRetention(2))
2072 epg_220.add_vpp_config()
2075 # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
2078 vx_tun_l2_1 = VppGbpVxlanTunnel(
2079 self, 99, bd1.bd_id,
2080 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L2,
2082 vx_tun_l2_1.add_vpp_config()
2085 # A static endpoint that the learnt endpoints are trying to
2088 ep = VppGbpEndpoint(self, vlan_11,
2090 "10.0.0.127", "11.0.0.127",
2091 "2001:10::1", "3001::1")
2094 self.assertTrue(find_route(self, ep.ip4.address, 32, table_id=1))
2097 # Send to the static EP
2099 for ii, l in enumerate(learnt):
2100 # a packet with an sclass from a known EPG
2101 # arriving on an unknown TEP
2102 p = (Ether(src=self.pg2.remote_mac,
2103 dst=self.pg2.local_mac) /
2104 IP(src=self.pg2.remote_hosts[1].ip4,
2105 dst=self.pg2.local_ip4) /
2106 UDP(sport=1234, dport=48879) /
2107 VXLAN(vni=99, gpid=441, flags=0x88) /
2108 Ether(src=l['mac'], dst=ep.mac) /
2109 IP(src=l['ip'], dst=ep.ip4.address) /
2110 UDP(sport=1234, dport=1234) /
2113 rxs = self.send_and_expect(self.pg2, [p], self.pg0)
2116 # packet to EP has the EP's vlan tag
2119 self.assertEqual(rx[Dot1Q].vlan, 11)
2122 # the EP is not learnt since the BD setting prevents it
2125 self.assertFalse(find_gbp_endpoint(self,
2126 vx_tun_l2_1.sw_if_index,
2128 self.assertEqual(INDEX_INVALID,
2129 find_vxlan_gbp_tunnel(
2132 self.pg2.remote_hosts[1].ip4,
2135 self.assertEqual(len(self.vapi.gbp_endpoint_dump()), 1)
2139 # we didn't learn the remotes so they are sent to the UU-fwd
2142 p = (Ether(src=ep.mac, dst=l['mac']) /
2144 IP(dst=l['ip'], src=ep.ip4.address) /
2145 UDP(sport=1234, dport=1234) /
2148 rxs = self.send_and_expect(self.pg0, p * 17, self.pg3)
2151 self.assertEqual(rx[IP].src, self.pg3.local_ip4)
2152 self.assertEqual(rx[IP].dst, self.pg3.remote_ip4)
2153 self.assertEqual(rx[UDP].dport, 48879)
2154 # the UDP source port is a random value for hashing
2155 self.assertEqual(rx[VXLAN].gpid, 441)
2156 self.assertEqual(rx[VXLAN].vni, 116)
2157 self.assertTrue(rx[VXLAN].flags.G)
2158 self.assertTrue(rx[VXLAN].flags.Instance)
2159 self.assertFalse(rx[VXLAN].gpflags.A)
2160 self.assertFalse(rx[VXLAN].gpflags.D)
2162 self.pg2.unconfig_ip4()
2163 self.pg3.unconfig_ip4()
2165 def test_gbp_learn_l3(self):
2166 """ GBP L3 Endpoint Learning """
2168 self.vapi.cli("set logging class gbp debug")
2170 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
2171 routed_dst_mac = "00:0c:0c:0c:0c:0c"
2172 routed_src_mac = "00:22:bd:f8:19:ff"
2174 learnt = [{'mac': '00:00:11:11:11:02',
2176 'ip6': '2001:10::2'},
2177 {'mac': '00:00:11:11:11:03',
2179 'ip6': '2001:10::3'}]
2184 t4 = VppIpTable(self, 1)
2186 t6 = VppIpTable(self, 1, True)
2189 tun_ip4_uu = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
2190 self.pg4.remote_ip4, 114)
2191 tun_ip6_uu = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
2192 self.pg4.remote_ip4, 116)
2193 tun_ip4_uu.add_vpp_config()
2194 tun_ip6_uu.add_vpp_config()
2196 rd1 = VppGbpRouteDomain(self, 2, t4, t6, tun_ip4_uu, tun_ip6_uu)
2197 rd1.add_vpp_config()
2199 self.loop0.set_mac(self.router_mac)
2202 # Bind the BVI to the RD
2204 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
2205 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
2208 # Pg2 hosts the vxlan tunnel
2209 # hosts on pg2 to act as TEPs
2213 self.pg2.config_ip4()
2214 self.pg2.resolve_arp()
2215 self.pg2.generate_remote_hosts(4)
2216 self.pg2.configure_ipv4_neighbors()
2217 self.pg3.config_ip4()
2218 self.pg3.resolve_arp()
2219 self.pg4.config_ip4()
2220 self.pg4.resolve_arp()
2223 # a GBP bridge domain with a BVI and a UU-flood interface
2225 bd1 = VppBridgeDomain(self, 1)
2226 bd1.add_vpp_config()
2227 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0, self.pg3)
2228 gbd1.add_vpp_config()
2230 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2231 self.logger.info(self.vapi.cli("sh gbp bridge"))
2232 self.logger.info(self.vapi.cli("sh gbp route"))
2234 # ... and has a /32 and /128 applied
2235 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2236 ip4_addr.add_vpp_config()
2237 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 128)
2238 ip6_addr.add_vpp_config()
2241 # The Endpoint-group in which we are learning endpoints
2243 epg_220 = VppGbpEndpointGroup(self, 220, 441, rd1, gbd1,
2247 VppGbpEndpointRetention(2))
2248 epg_220.add_vpp_config()
2251 # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
2254 vx_tun_l3 = VppGbpVxlanTunnel(
2255 self, 101, rd1.rd_id,
2256 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
2258 vx_tun_l3.add_vpp_config()
2261 # A static endpoint that the learnt endpoints are trying to
2264 ep = VppGbpEndpoint(self, self.pg0,
2266 "10.0.0.127", "11.0.0.127",
2267 "2001:10::1", "3001::1")
2271 # learn some remote IPv4 EPs
2273 for ii, l in enumerate(learnt):
2274 # a packet with an sclass from a known EPG
2275 # arriving on an unknown TEP
2276 p = (Ether(src=self.pg2.remote_mac,
2277 dst=self.pg2.local_mac) /
2278 IP(src=self.pg2.remote_hosts[1].ip4,
2279 dst=self.pg2.local_ip4) /
2280 UDP(sport=1234, dport=48879) /
2281 VXLAN(vni=101, gpid=441, flags=0x88) /
2282 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2283 IP(src=l['ip'], dst=ep.ip4.address) /
2284 UDP(sport=1234, dport=1234) /
2287 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2290 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2293 self.pg2.remote_hosts[1].ip4,
2295 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2297 # endpoint learnt via the parent GBP-vxlan interface
2298 self.assertTrue(find_gbp_endpoint(self,
2299 vx_tun_l3._sw_if_index,
2303 # Static IPv4 EP replies to learnt
2306 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2307 IP(dst=l['ip'], src=ep.ip4.address) /
2308 UDP(sport=1234, dport=1234) /
2311 rxs = self.send_and_expect(self.pg0, p*1, self.pg2)
2314 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2315 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2316 self.assertEqual(rx[UDP].dport, 48879)
2317 # the UDP source port is a random value for hashing
2318 self.assertEqual(rx[VXLAN].gpid, 441)
2319 self.assertEqual(rx[VXLAN].vni, 101)
2320 self.assertTrue(rx[VXLAN].flags.G)
2321 self.assertTrue(rx[VXLAN].flags.Instance)
2322 self.assertTrue(rx[VXLAN].gpflags.A)
2323 self.assertFalse(rx[VXLAN].gpflags.D)
2325 inner = rx[VXLAN].payload
2327 self.assertEqual(inner[Ether].src, routed_src_mac)
2328 self.assertEqual(inner[Ether].dst, routed_dst_mac)
2329 self.assertEqual(inner[IP].src, ep.ip4.address)
2330 self.assertEqual(inner[IP].dst, l['ip'])
2333 self.assertFalse(find_gbp_endpoint(self,
2338 # learn some remote IPv6 EPs
2340 for ii, l in enumerate(learnt):
2341 # a packet with an sclass from a known EPG
2342 # arriving on an unknown TEP
2343 p = (Ether(src=self.pg2.remote_mac,
2344 dst=self.pg2.local_mac) /
2345 IP(src=self.pg2.remote_hosts[1].ip4,
2346 dst=self.pg2.local_ip4) /
2347 UDP(sport=1234, dport=48879) /
2348 VXLAN(vni=101, gpid=441, flags=0x88) /
2349 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2350 IPv6(src=l['ip6'], dst=ep.ip6.address) /
2351 UDP(sport=1234, dport=1234) /
2354 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2357 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2360 self.pg2.remote_hosts[1].ip4,
2362 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2364 self.logger.info(self.vapi.cli("show gbp bridge"))
2365 self.logger.info(self.vapi.cli("show vxlan-gbp tunnel"))
2366 self.logger.info(self.vapi.cli("show gbp vxlan"))
2367 self.logger.info(self.vapi.cli("show int addr"))
2369 # endpoint learnt via the TEP
2370 self.assertTrue(find_gbp_endpoint(self, ip=l['ip6']))
2372 self.logger.info(self.vapi.cli("show gbp endpoint"))
2373 self.logger.info(self.vapi.cli("show ip fib index 1 %s" % l['ip']))
2376 # Static EP replies to learnt
2379 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2380 IPv6(dst=l['ip6'], src=ep.ip6.address) /
2381 UDP(sport=1234, dport=1234) /
2384 rxs = self.send_and_expect(self.pg0, p*65, self.pg2)
2387 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2388 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2389 self.assertEqual(rx[UDP].dport, 48879)
2390 # the UDP source port is a random value for hashing
2391 self.assertEqual(rx[VXLAN].gpid, 441)
2392 self.assertEqual(rx[VXLAN].vni, 101)
2393 self.assertTrue(rx[VXLAN].flags.G)
2394 self.assertTrue(rx[VXLAN].flags.Instance)
2395 self.assertTrue(rx[VXLAN].gpflags.A)
2396 self.assertFalse(rx[VXLAN].gpflags.D)
2398 inner = rx[VXLAN].payload
2400 self.assertEqual(inner[Ether].src, routed_src_mac)
2401 self.assertEqual(inner[Ether].dst, routed_dst_mac)
2402 self.assertEqual(inner[IPv6].src, ep.ip6.address)
2403 self.assertEqual(inner[IPv6].dst, l['ip6'])
2405 self.logger.info(self.vapi.cli("sh gbp endpoint"))
2407 self.wait_for_ep_timeout(ip=l['ip'])
2410 # Static sends to unknown EP with no route
2412 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2413 IP(dst="10.0.0.99", src=ep.ip4.address) /
2414 UDP(sport=1234, dport=1234) /
2417 self.send_and_assert_no_replies(self.pg0, [p])
2420 # Add a route to static EP's v4 and v6 subnet
2421 # packets should be sent on the v4/v6 uu=fwd interface resp.
2423 se_10_24 = VppGbpSubnet(
2424 self, rd1, "10.0.0.0", 24,
2425 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT)
2426 se_10_24.add_vpp_config()
2428 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2429 IP(dst="10.0.0.99", src=ep.ip4.address) /
2430 UDP(sport=1234, dport=1234) /
2433 rxs = self.send_and_expect(self.pg0, [p], self.pg4)
2435 self.assertEqual(rx[IP].src, self.pg4.local_ip4)
2436 self.assertEqual(rx[IP].dst, self.pg4.remote_ip4)
2437 self.assertEqual(rx[UDP].dport, 48879)
2438 # the UDP source port is a random value for hashing
2439 self.assertEqual(rx[VXLAN].gpid, 441)
2440 self.assertEqual(rx[VXLAN].vni, 114)
2441 self.assertTrue(rx[VXLAN].flags.G)
2442 self.assertTrue(rx[VXLAN].flags.Instance)
2443 # policy is not applied to packets sent to the uu-fwd interfaces
2444 self.assertFalse(rx[VXLAN].gpflags.A)
2445 self.assertFalse(rx[VXLAN].gpflags.D)
2448 # learn some remote IPv4 EPs
2450 for ii, l in enumerate(learnt):
2451 # a packet with an sclass from a known EPG
2452 # arriving on an unknown TEP
2453 p = (Ether(src=self.pg2.remote_mac,
2454 dst=self.pg2.local_mac) /
2455 IP(src=self.pg2.remote_hosts[2].ip4,
2456 dst=self.pg2.local_ip4) /
2457 UDP(sport=1234, dport=48879) /
2458 VXLAN(vni=101, gpid=441, flags=0x88) /
2459 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2460 IP(src=l['ip'], dst=ep.ip4.address) /
2461 UDP(sport=1234, dport=1234) /
2464 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2467 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2470 self.pg2.remote_hosts[2].ip4,
2472 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2474 # endpoint learnt via the parent GBP-vxlan interface
2475 self.assertTrue(find_gbp_endpoint(self,
2476 vx_tun_l3._sw_if_index,
2480 # Add a remote endpoint from the API
2482 rep_88 = VppGbpEndpoint(self, vx_tun_l3,
2484 "10.0.0.88", "11.0.0.88",
2485 "2001:10::88", "3001::88",
2486 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
2488 self.pg2.remote_hosts[1].ip4,
2490 rep_88.add_vpp_config()
2493 # Add a remote endpoint from the API that matches an existing one
2495 rep_2 = VppGbpEndpoint(self, vx_tun_l3,
2497 learnt[0]['ip'], "11.0.0.101",
2498 learnt[0]['ip6'], "3001::101",
2499 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
2501 self.pg2.remote_hosts[1].ip4,
2503 rep_2.add_vpp_config()
2506 # Add a route to the learned EP's v4 subnet
2507 # packets should be send on the v4/v6 uu=fwd interface resp.
2509 se_10_1_24 = VppGbpSubnet(
2510 self, rd1, "10.0.1.0", 24,
2511 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT)
2512 se_10_1_24.add_vpp_config()
2514 self.logger.info(self.vapi.cli("show gbp endpoint"))
2516 ips = ["10.0.0.88", learnt[0]['ip']]
2518 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2519 IP(dst=ip, src=ep.ip4.address) /
2520 UDP(sport=1234, dport=1234) /
2523 rxs = self.send_and_expect(self.pg0, p*65, self.pg2)
2526 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2527 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2528 self.assertEqual(rx[UDP].dport, 48879)
2529 # the UDP source port is a random value for hashing
2530 self.assertEqual(rx[VXLAN].gpid, 441)
2531 self.assertEqual(rx[VXLAN].vni, 101)
2532 self.assertTrue(rx[VXLAN].flags.G)
2533 self.assertTrue(rx[VXLAN].flags.Instance)
2534 self.assertTrue(rx[VXLAN].gpflags.A)
2535 self.assertFalse(rx[VXLAN].gpflags.D)
2537 inner = rx[VXLAN].payload
2539 self.assertEqual(inner[Ether].src, routed_src_mac)
2540 self.assertEqual(inner[Ether].dst, routed_dst_mac)
2541 self.assertEqual(inner[IP].src, ep.ip4.address)
2542 self.assertEqual(inner[IP].dst, ip)
2545 # remove the API remote EPs, only API sourced is gone, the DP
2546 # learnt one remains
2548 rep_88.remove_vpp_config()
2549 rep_2.remove_vpp_config()
2551 self.assertTrue(find_gbp_endpoint(self, ip=rep_2.ip4.address))
2553 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2554 IP(src=ep.ip4.address, dst=rep_2.ip4.address) /
2555 UDP(sport=1234, dport=1234) /
2557 rxs = self.send_and_expect(self.pg0, [p], self.pg2)
2559 self.assertFalse(find_gbp_endpoint(self, ip=rep_88.ip4.address))
2561 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2562 IP(src=ep.ip4.address, dst=rep_88.ip4.address) /
2563 UDP(sport=1234, dport=1234) /
2565 rxs = self.send_and_expect(self.pg0, [p], self.pg4)
2568 # to appease the testcase we cannot have the registered EP still
2569 # present (because it's DP learnt) when the TC ends so wait until
2572 self.wait_for_ep_timeout(ip=rep_88.ip4.address)
2573 self.wait_for_ep_timeout(ip=rep_2.ip4.address)
2576 # shutdown with learnt endpoint present
2578 p = (Ether(src=self.pg2.remote_mac,
2579 dst=self.pg2.local_mac) /
2580 IP(src=self.pg2.remote_hosts[1].ip4,
2581 dst=self.pg2.local_ip4) /
2582 UDP(sport=1234, dport=48879) /
2583 VXLAN(vni=101, gpid=441, flags=0x88) /
2584 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2585 IP(src=learnt[1]['ip'], dst=ep.ip4.address) /
2586 UDP(sport=1234, dport=1234) /
2589 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2591 # endpoint learnt via the parent GBP-vxlan interface
2592 self.assertTrue(find_gbp_endpoint(self,
2593 vx_tun_l3._sw_if_index,
2598 # remote endpoint becomes local
2600 self.pg2.unconfig_ip4()
2601 self.pg3.unconfig_ip4()
2602 self.pg4.unconfig_ip4()
2604 def test_gbp_redirect(self):
2605 """ GBP Endpoint Redirect """
2607 self.vapi.cli("set logging class gbp debug")
2609 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
2610 routed_dst_mac = "00:0c:0c:0c:0c:0c"
2611 routed_src_mac = "00:22:bd:f8:19:ff"
2613 learnt = [{'mac': '00:00:11:11:11:02',
2615 'ip6': '2001:10::2'},
2616 {'mac': '00:00:11:11:11:03',
2618 'ip6': '2001:10::3'}]
2623 t4 = VppIpTable(self, 1)
2625 t6 = VppIpTable(self, 1, True)
2628 rd1 = VppGbpRouteDomain(self, 2, t4, t6)
2629 rd1.add_vpp_config()
2631 self.loop0.set_mac(self.router_mac)
2634 # Bind the BVI to the RD
2636 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
2637 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
2640 # Pg7 hosts a BD's UU-fwd
2642 self.pg7.config_ip4()
2643 self.pg7.resolve_arp()
2646 # a GBP bridge domains for the EPs
2648 bd1 = VppBridgeDomain(self, 1)
2649 bd1.add_vpp_config()
2650 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0)
2651 gbd1.add_vpp_config()
2653 bd2 = VppBridgeDomain(self, 2)
2654 bd2.add_vpp_config()
2655 gbd2 = VppGbpBridgeDomain(self, bd2, self.loop1)
2656 gbd2.add_vpp_config()
2658 # ... and has a /32 and /128 applied
2659 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2660 ip4_addr.add_vpp_config()
2661 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 128)
2662 ip6_addr.add_vpp_config()
2663 ip4_addr = VppIpInterfaceAddress(self, gbd2.bvi, "10.0.1.128", 32)
2664 ip4_addr.add_vpp_config()
2665 ip6_addr = VppIpInterfaceAddress(self, gbd2.bvi, "2001:11::128", 128)
2666 ip6_addr.add_vpp_config()
2669 # The Endpoint-groups in which we are learning endpoints
2671 epg_220 = VppGbpEndpointGroup(self, 220, 440, rd1, gbd1,
2675 VppGbpEndpointRetention(2))
2676 epg_220.add_vpp_config()
2677 epg_221 = VppGbpEndpointGroup(self, 221, 441, rd1, gbd2,
2681 VppGbpEndpointRetention(2))
2682 epg_221.add_vpp_config()
2683 epg_222 = VppGbpEndpointGroup(self, 222, 442, rd1, gbd1,
2687 VppGbpEndpointRetention(2))
2688 epg_222.add_vpp_config()
2691 # a GBP bridge domains for the SEPs
2693 bd_uu1 = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
2694 self.pg7.remote_ip4, 116)
2695 bd_uu1.add_vpp_config()
2696 bd_uu2 = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
2697 self.pg7.remote_ip4, 117)
2698 bd_uu2.add_vpp_config()
2700 bd3 = VppBridgeDomain(self, 3)
2701 bd3.add_vpp_config()
2702 gbd3 = VppGbpBridgeDomain(self, bd3, self.loop2, bd_uu1, learn=False)
2703 gbd3.add_vpp_config()
2704 bd4 = VppBridgeDomain(self, 4)
2705 bd4.add_vpp_config()
2706 gbd4 = VppGbpBridgeDomain(self, bd4, self.loop3, bd_uu2, learn=False)
2707 gbd4.add_vpp_config()
2710 # EPGs in which the service endpoints exist
2712 epg_320 = VppGbpEndpointGroup(self, 320, 550, rd1, gbd3,
2716 VppGbpEndpointRetention(2))
2717 epg_320.add_vpp_config()
2718 epg_321 = VppGbpEndpointGroup(self, 321, 551, rd1, gbd4,
2722 VppGbpEndpointRetention(2))
2723 epg_321.add_vpp_config()
2726 # three local endpoints
2728 ep1 = VppGbpEndpoint(self, self.pg0,
2730 "10.0.0.1", "11.0.0.1",
2731 "2001:10::1", "3001:10::1")
2732 ep1.add_vpp_config()
2733 ep2 = VppGbpEndpoint(self, self.pg1,
2735 "10.0.1.1", "11.0.1.1",
2736 "2001:11::1", "3001:11::1")
2737 ep2.add_vpp_config()
2738 ep3 = VppGbpEndpoint(self, self.pg2,
2740 "10.0.2.2", "11.0.2.2",
2741 "2001:12::1", "3001:12::1")
2742 ep3.add_vpp_config()
2747 sep1 = VppGbpEndpoint(self, self.pg3,
2749 "12.0.0.1", "13.0.0.1",
2750 "4001:10::1", "5001:10::1")
2751 sep1.add_vpp_config()
2752 sep2 = VppGbpEndpoint(self, self.pg4,
2754 "12.0.0.2", "13.0.0.2",
2755 "4001:10::2", "5001:10::2")
2756 sep2.add_vpp_config()
2757 sep3 = VppGbpEndpoint(self, self.pg5,
2759 "12.0.1.1", "13.0.1.1",
2760 "4001:11::1", "5001:11::1")
2761 sep3.add_vpp_config()
2762 # this EP is not installed immediately
2763 sep4 = VppGbpEndpoint(self, self.pg6,
2765 "12.0.1.2", "13.0.1.2",
2766 "4001:11::2", "5001:11::2")
2769 # an L2 switch packet between local EPs in different EPGs
2770 # different dest ports on each so the are LB hashed differently
2772 p4 = [(Ether(src=ep1.mac, dst=ep3.mac) /
2773 IP(src=ep1.ip4.address, dst=ep3.ip4.address) /
2774 UDP(sport=1234, dport=1234) /
2776 (Ether(src=ep3.mac, dst=ep1.mac) /
2777 IP(src=ep3.ip4.address, dst=ep1.ip4.address) /
2778 UDP(sport=1234, dport=1234) /
2780 p6 = [(Ether(src=ep1.mac, dst=ep3.mac) /
2781 IPv6(src=ep1.ip6.address, dst=ep3.ip6.address) /
2782 UDP(sport=1234, dport=1234) /
2784 (Ether(src=ep3.mac, dst=ep1.mac) /
2785 IPv6(src=ep3.ip6.address, dst=ep1.ip6.address) /
2786 UDP(sport=1234, dport=1230) /
2789 # should be dropped since no contract yet
2790 self.send_and_assert_no_replies(self.pg0, [p4[0]])
2791 self.send_and_assert_no_replies(self.pg0, [p6[0]])
2794 # Add a contract with a rule to load-balance redirect via SEP1 and SEP2
2795 # one of the next-hops is via an EP that is not known
2797 acl = VppGbpAcl(self)
2798 rule4 = acl.create_rule(permit_deny=1, proto=17)
2799 rule6 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
2800 acl_index = acl.add_vpp_config([rule4, rule6])
2803 # test the src-ip hash mode
2805 c1 = VppGbpContract(
2806 self, epg_220.sclass, epg_222.sclass, acl_index,
2807 [VppGbpContractRule(
2808 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2809 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2810 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
2811 sep1.ip4, sep1.epg.rd),
2812 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
2813 sep2.ip4, sep2.epg.rd)]),
2815 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2816 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2817 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
2818 sep3.ip6, sep3.epg.rd),
2819 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
2820 sep4.ip6, sep4.epg.rd)])],
2821 [ETH_P_IP, ETH_P_IPV6])
2824 c2 = VppGbpContract(
2825 self, epg_222.sclass, epg_220.sclass, acl_index,
2826 [VppGbpContractRule(
2827 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2828 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2829 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
2830 sep1.ip4, sep1.epg.rd),
2831 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
2832 sep2.ip4, sep2.epg.rd)]),
2834 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2835 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2836 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
2837 sep3.ip6, sep3.epg.rd),
2838 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
2839 sep4.ip6, sep4.epg.rd)])],
2840 [ETH_P_IP, ETH_P_IPV6])
2844 # send again with the contract preset, now packets arrive
2845 # at SEP1 or SEP2 depending on the hashing
2847 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
2850 self.assertEqual(rx[Ether].src, routed_src_mac)
2851 self.assertEqual(rx[Ether].dst, sep1.mac)
2852 self.assertEqual(rx[IP].src, ep1.ip4.address)
2853 self.assertEqual(rx[IP].dst, ep3.ip4.address)
2855 rxs = self.send_and_expect(self.pg2, p4[1] * 17, sep2.itf)
2858 self.assertEqual(rx[Ether].src, routed_src_mac)
2859 self.assertEqual(rx[Ether].dst, sep2.mac)
2860 self.assertEqual(rx[IP].src, ep3.ip4.address)
2861 self.assertEqual(rx[IP].dst, ep1.ip4.address)
2863 rxs = self.send_and_expect(self.pg0, p6[0] * 17, self.pg7)
2866 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
2867 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
2868 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
2869 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
2870 self.assertEqual(rx[VXLAN].vni, 117)
2871 self.assertTrue(rx[VXLAN].flags.G)
2872 self.assertTrue(rx[VXLAN].flags.Instance)
2873 # redirect policy has been applied
2874 self.assertTrue(rx[VXLAN].gpflags.A)
2875 self.assertFalse(rx[VXLAN].gpflags.D)
2877 inner = rx[VXLAN].payload
2879 self.assertEqual(inner[Ether].src, routed_src_mac)
2880 self.assertEqual(inner[Ether].dst, sep4.mac)
2881 self.assertEqual(inner[IPv6].src, ep1.ip6.address)
2882 self.assertEqual(inner[IPv6].dst, ep3.ip6.address)
2884 rxs = self.send_and_expect(self.pg2, p6[1] * 17, sep3.itf)
2887 self.assertEqual(rx[Ether].src, routed_src_mac)
2888 self.assertEqual(rx[Ether].dst, sep3.mac)
2889 self.assertEqual(rx[IPv6].src, ep3.ip6.address)
2890 self.assertEqual(rx[IPv6].dst, ep1.ip6.address)
2893 # programme the unknown EP
2895 sep4.add_vpp_config()
2897 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep4.itf)
2900 self.assertEqual(rx[Ether].src, routed_src_mac)
2901 self.assertEqual(rx[Ether].dst, sep4.mac)
2902 self.assertEqual(rx[IPv6].src, ep1.ip6.address)
2903 self.assertEqual(rx[IPv6].dst, ep3.ip6.address)
2906 # and revert back to unprogrammed
2908 sep4.remove_vpp_config()
2910 rxs = self.send_and_expect(self.pg0, p6[0] * 17, self.pg7)
2913 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
2914 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
2915 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
2916 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
2917 self.assertEqual(rx[VXLAN].vni, 117)
2918 self.assertTrue(rx[VXLAN].flags.G)
2919 self.assertTrue(rx[VXLAN].flags.Instance)
2920 # redirect policy has been applied
2921 self.assertTrue(rx[VXLAN].gpflags.A)
2922 self.assertFalse(rx[VXLAN].gpflags.D)
2924 inner = rx[VXLAN].payload
2926 self.assertEqual(inner[Ether].src, routed_src_mac)
2927 self.assertEqual(inner[Ether].dst, sep4.mac)
2928 self.assertEqual(inner[IPv6].src, ep1.ip6.address)
2929 self.assertEqual(inner[IPv6].dst, ep3.ip6.address)
2931 c1.remove_vpp_config()
2932 c2.remove_vpp_config()
2935 # test the symmetric hash mode
2937 c1 = VppGbpContract(
2938 self, epg_220.sclass, epg_222.sclass, acl_index,
2939 [VppGbpContractRule(
2940 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2941 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
2942 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
2943 sep1.ip4, sep1.epg.rd),
2944 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
2945 sep2.ip4, sep2.epg.rd)]),
2947 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2948 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
2949 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
2950 sep3.ip6, sep3.epg.rd),
2951 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
2952 sep4.ip6, sep4.epg.rd)])],
2953 [ETH_P_IP, ETH_P_IPV6])
2956 c2 = VppGbpContract(
2957 self, epg_222.sclass, epg_220.sclass, acl_index,
2958 [VppGbpContractRule(
2959 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2960 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
2961 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
2962 sep1.ip4, sep1.epg.rd),
2963 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
2964 sep2.ip4, sep2.epg.rd)]),
2966 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2967 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
2968 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
2969 sep3.ip6, sep3.epg.rd),
2970 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
2971 sep4.ip6, sep4.epg.rd)])],
2972 [ETH_P_IP, ETH_P_IPV6])
2976 # send again with the contract preset, now packets arrive
2977 # at SEP1 for both directions
2979 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
2982 self.assertEqual(rx[Ether].src, routed_src_mac)
2983 self.assertEqual(rx[Ether].dst, sep1.mac)
2984 self.assertEqual(rx[IP].src, ep1.ip4.address)
2985 self.assertEqual(rx[IP].dst, ep3.ip4.address)
2987 rxs = self.send_and_expect(self.pg2, p4[1] * 17, sep1.itf)
2990 self.assertEqual(rx[Ether].src, routed_src_mac)
2991 self.assertEqual(rx[Ether].dst, sep1.mac)
2992 self.assertEqual(rx[IP].src, ep3.ip4.address)
2993 self.assertEqual(rx[IP].dst, ep1.ip4.address)
2996 # programme the unknown EP for the L3 tests
2998 sep4.add_vpp_config()
3001 # an L3 switch packet between local EPs in different EPGs
3002 # different dest ports on each so the are LB hashed differently
3004 p4 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3005 IP(src=ep1.ip4.address, dst=ep2.ip4.address) /
3006 UDP(sport=1234, dport=1234) /
3008 (Ether(src=ep2.mac, dst=str(self.router_mac)) /
3009 IP(src=ep2.ip4.address, dst=ep1.ip4.address) /
3010 UDP(sport=1234, dport=1234) /
3012 p6 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3013 IPv6(src=ep1.ip6.address, dst=ep2.ip6.address) /
3014 UDP(sport=1234, dport=1234) /
3016 (Ether(src=ep2.mac, dst=str(self.router_mac)) /
3017 IPv6(src=ep2.ip6.address, dst=ep1.ip6.address) /
3018 UDP(sport=1234, dport=1234) /
3021 c3 = VppGbpContract(
3022 self, epg_220.sclass, epg_221.sclass, acl_index,
3023 [VppGbpContractRule(
3024 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3025 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3026 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3027 sep1.ip4, sep1.epg.rd),
3028 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3029 sep2.ip4, sep2.epg.rd)]),
3031 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3032 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3033 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3034 sep3.ip6, sep3.epg.rd),
3035 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3036 sep4.ip6, sep4.epg.rd)])],
3037 [ETH_P_IP, ETH_P_IPV6])
3040 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3043 self.assertEqual(rx[Ether].src, routed_src_mac)
3044 self.assertEqual(rx[Ether].dst, sep1.mac)
3045 self.assertEqual(rx[IP].src, ep1.ip4.address)
3046 self.assertEqual(rx[IP].dst, ep2.ip4.address)
3049 # learn a remote EP in EPG 221
3051 vx_tun_l3 = VppGbpVxlanTunnel(
3052 self, 444, rd1.rd_id,
3053 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
3055 vx_tun_l3.add_vpp_config()
3057 c4 = VppGbpContract(
3058 self, epg_221.sclass, epg_220.sclass, acl_index,
3059 [VppGbpContractRule(
3060 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3063 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3065 [ETH_P_IP, ETH_P_IPV6])
3068 p = (Ether(src=self.pg7.remote_mac,
3069 dst=self.pg7.local_mac) /
3070 IP(src=self.pg7.remote_ip4,
3071 dst=self.pg7.local_ip4) /
3072 UDP(sport=1234, dport=48879) /
3073 VXLAN(vni=444, gpid=441, flags=0x88) /
3074 Ether(src="00:22:22:22:22:33", dst=str(self.router_mac)) /
3075 IP(src="10.0.0.88", dst=ep1.ip4.address) /
3076 UDP(sport=1234, dport=1234) /
3079 rx = self.send_and_expect(self.pg7, [p], self.pg0)
3081 # endpoint learnt via the parent GBP-vxlan interface
3082 self.assertTrue(find_gbp_endpoint(self,
3083 vx_tun_l3._sw_if_index,
3086 p = (Ether(src=self.pg7.remote_mac,
3087 dst=self.pg7.local_mac) /
3088 IP(src=self.pg7.remote_ip4,
3089 dst=self.pg7.local_ip4) /
3090 UDP(sport=1234, dport=48879) /
3091 VXLAN(vni=444, gpid=441, flags=0x88) /
3092 Ether(src="00:22:22:22:22:33", dst=str(self.router_mac)) /
3093 IPv6(src="2001:10::88", dst=ep1.ip6.address) /
3094 UDP(sport=1234, dport=1234) /
3097 rx = self.send_and_expect(self.pg7, [p], self.pg0)
3099 # endpoint learnt via the parent GBP-vxlan interface
3100 self.assertTrue(find_gbp_endpoint(self,
3101 vx_tun_l3._sw_if_index,
3105 # L3 switch from local to remote EP
3107 p4 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3108 IP(src=ep1.ip4.address, dst="10.0.0.88") /
3109 UDP(sport=1234, dport=1234) /
3111 p6 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3112 IPv6(src=ep1.ip6.address, dst="2001:10::88") /
3113 UDP(sport=1234, dport=1234) /
3116 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3119 self.assertEqual(rx[Ether].src, routed_src_mac)
3120 self.assertEqual(rx[Ether].dst, sep1.mac)
3121 self.assertEqual(rx[IP].src, ep1.ip4.address)
3122 self.assertEqual(rx[IP].dst, "10.0.0.88")
3124 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep4.itf)
3127 self.assertEqual(rx[Ether].src, routed_src_mac)
3128 self.assertEqual(rx[Ether].dst, sep4.mac)
3129 self.assertEqual(rx[IPv6].src, ep1.ip6.address)
3130 self.assertEqual(rx[IPv6].dst, "2001:10::88")
3133 # test the dst-ip hash mode
3135 c5 = VppGbpContract(
3136 self, epg_220.sclass, epg_221.sclass, acl_index,
3137 [VppGbpContractRule(
3138 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3139 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
3140 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3141 sep1.ip4, sep1.epg.rd),
3142 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3143 sep2.ip4, sep2.epg.rd)]),
3145 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3146 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
3147 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3148 sep3.ip6, sep3.epg.rd),
3149 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3150 sep4.ip6, sep4.epg.rd)])],
3151 [ETH_P_IP, ETH_P_IPV6])
3154 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3157 self.assertEqual(rx[Ether].src, routed_src_mac)
3158 self.assertEqual(rx[Ether].dst, sep1.mac)
3159 self.assertEqual(rx[IP].src, ep1.ip4.address)
3160 self.assertEqual(rx[IP].dst, "10.0.0.88")
3162 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep3.itf)
3165 self.assertEqual(rx[Ether].src, routed_src_mac)
3166 self.assertEqual(rx[Ether].dst, sep3.mac)
3167 self.assertEqual(rx[IPv6].src, ep1.ip6.address)
3168 self.assertEqual(rx[IPv6].dst, "2001:10::88")
3173 self.pg7.unconfig_ip4()
3175 def test_gbp_l3_out(self):
3178 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
3179 self.vapi.cli("set logging class gbp debug")
3181 routed_dst_mac = "00:0c:0c:0c:0c:0c"
3182 routed_src_mac = "00:22:bd:f8:19:ff"
3187 t4 = VppIpTable(self, 1)
3189 t6 = VppIpTable(self, 1, True)
3192 rd1 = VppGbpRouteDomain(self, 2, t4, t6)
3193 rd1.add_vpp_config()
3195 self.loop0.set_mac(self.router_mac)
3198 # Bind the BVI to the RD
3200 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
3201 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
3204 # Pg7 hosts a BD's BUM
3205 # Pg1 some other l3 interface
3207 self.pg7.config_ip4()
3208 self.pg7.resolve_arp()
3211 # a multicast vxlan-gbp tunnel for broadcast in the BD
3213 tun_bm = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
3216 tun_bm.add_vpp_config()
3219 # a GBP external bridge domains for the EPs
3221 bd1 = VppBridgeDomain(self, 1)
3222 bd1.add_vpp_config()
3223 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0, None, tun_bm)
3224 gbd1.add_vpp_config()
3227 # The Endpoint-groups in which the external endpoints exist
3229 epg_220 = VppGbpEndpointGroup(self, 220, 113, rd1, gbd1,
3233 VppGbpEndpointRetention(2))
3234 epg_220.add_vpp_config()
3236 # the BVIs have the subnets applied ...
3237 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 24)
3238 ip4_addr.add_vpp_config()
3239 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 64)
3240 ip6_addr.add_vpp_config()
3242 # ... which are L3-out subnets
3243 l3o_1 = VppGbpSubnet(
3244 self, rd1, "10.0.0.0", 24,
3245 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3247 l3o_1.add_vpp_config()
3250 # an external interface attached to the outside world and the
3253 vlan_100 = VppDot1QSubint(self, self.pg0, 100)
3255 VppL2Vtr(self, vlan_100, L2_VTR_OP.L2_POP_1).add_vpp_config()
3256 vlan_101 = VppDot1QSubint(self, self.pg0, 101)
3258 VppL2Vtr(self, vlan_101, L2_VTR_OP.L2_POP_1).add_vpp_config()
3260 ext_itf = VppGbpExtItf(self, self.loop0, bd1, rd1)
3261 ext_itf.add_vpp_config()
3264 # an unicast vxlan-gbp for inter-RD traffic
3266 vx_tun_l3 = VppGbpVxlanTunnel(
3267 self, 444, rd1.rd_id,
3268 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
3270 vx_tun_l3.add_vpp_config()
3273 # External Endpoints
3275 eep1 = VppGbpEndpoint(self, vlan_100,
3277 "10.0.0.1", "11.0.0.1",
3278 "2001:10::1", "3001::1",
3279 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
3280 eep1.add_vpp_config()
3281 eep2 = VppGbpEndpoint(self, vlan_101,
3283 "10.0.0.2", "11.0.0.2",
3284 "2001:10::2", "3001::2",
3285 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
3286 eep2.add_vpp_config()
3289 # A remote external endpoint
3291 rep = VppGbpEndpoint(self, vx_tun_l3,
3293 "10.0.0.101", "11.0.0.101",
3294 "2001:10::101", "3001::101",
3295 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
3297 self.pg7.remote_ip4,
3299 rep.add_vpp_config()
3302 # ARP packet from External EPs are accepted and replied to
3304 p_arp = (Ether(src=eep1.mac, dst="ff:ff:ff:ff:ff:ff") /
3307 psrc=eep1.ip4.address, pdst="10.0.0.128",
3308 hwsrc=eep1.mac, hwdst="ff:ff:ff:ff:ff:ff"))
3309 rxs = self.send_and_expect(self.pg0, p_arp * 1, self.pg0)
3312 # packets destined to unknown addresses in the BVI's subnet
3315 p4 = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3317 IP(src="10.0.0.1", dst="10.0.0.88") /
3318 UDP(sport=1234, dport=1234) /
3320 p6 = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3322 IPv6(src="2001:10::1", dst="2001:10::88") /
3323 UDP(sport=1234, dport=1234) /
3326 rxs = self.send_and_expect(self.pg0, p4 * 1, self.pg7)
3329 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3330 # self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3331 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3332 self.assertEqual(rx[IP].dst, "239.1.1.1")
3333 self.assertEqual(rx[VXLAN].vni, 88)
3334 self.assertTrue(rx[VXLAN].flags.G)
3335 self.assertTrue(rx[VXLAN].flags.Instance)
3336 # policy was applied to the original IP packet
3337 self.assertEqual(rx[VXLAN].gpid, 113)
3338 self.assertTrue(rx[VXLAN].gpflags.A)
3339 self.assertFalse(rx[VXLAN].gpflags.D)
3341 inner = rx[VXLAN].payload
3343 self.assertTrue(inner.haslayer(ARP))
3346 # remote to external
3348 p = (Ether(src=self.pg7.remote_mac,
3349 dst=self.pg7.local_mac) /
3350 IP(src=self.pg7.remote_ip4,
3351 dst=self.pg7.local_ip4) /
3352 UDP(sport=1234, dport=48879) /
3353 VXLAN(vni=444, gpid=113, flags=0x88) /
3354 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
3355 IP(src="10.0.0.101", dst="10.0.0.1") /
3356 UDP(sport=1234, dport=1234) /
3359 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
3362 # local EP pings router
3364 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3366 IP(src=eep1.ip4.address, dst="10.0.0.128") /
3367 ICMP(type='echo-request'))
3369 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
3372 self.assertEqual(rx[Ether].src, str(self.router_mac))
3373 self.assertEqual(rx[Ether].dst, eep1.mac)
3374 self.assertEqual(rx[Dot1Q].vlan, 100)
3377 # local EP pings other local EP
3379 p = (Ether(src=eep1.mac, dst=eep2.mac) /
3381 IP(src=eep1.ip4.address, dst=eep2.ip4.address) /
3382 ICMP(type='echo-request'))
3384 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
3387 self.assertEqual(rx[Ether].src, eep1.mac)
3388 self.assertEqual(rx[Ether].dst, eep2.mac)
3389 self.assertEqual(rx[Dot1Q].vlan, 101)
3392 # A subnet reachable through the external EP1
3394 ip_220 = VppIpRoute(self, "10.220.0.0", 24,
3395 [VppRoutePath(eep1.ip4.address,
3396 eep1.epg.bvi.sw_if_index)],
3397 table_id=t4.table_id)
3398 ip_220.add_vpp_config()
3400 l3o_220 = VppGbpSubnet(
3401 self, rd1, "10.220.0.0", 24,
3402 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3404 l3o_220.add_vpp_config()
3407 # A subnet reachable through the external EP2
3409 ip_221 = VppIpRoute(self, "10.221.0.0", 24,
3410 [VppRoutePath(eep2.ip4.address,
3411 eep2.epg.bvi.sw_if_index)],
3412 table_id=t4.table_id)
3413 ip_221.add_vpp_config()
3415 l3o_221 = VppGbpSubnet(
3416 self, rd1, "10.221.0.0", 24,
3417 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3419 l3o_221.add_vpp_config()
3422 # ping between hosts in remote subnets
3423 # dropped without a contract
3425 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3427 IP(src="10.220.0.1", dst="10.221.0.1") /
3428 ICMP(type='echo-request'))
3430 rxs = self.send_and_assert_no_replies(self.pg0, p * 1)
3433 # contract for the external nets to communicate
3435 acl = VppGbpAcl(self)
3436 rule4 = acl.create_rule(permit_deny=1, proto=17)
3437 rule6 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
3438 acl_index = acl.add_vpp_config([rule4, rule6])
3440 c1 = VppGbpContract(
3441 self, 4220, 4221, acl_index,
3442 [VppGbpContractRule(
3443 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3446 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3448 [ETH_P_IP, ETH_P_IPV6])
3452 # Contracts allowing ext-net 200 to talk with external EPs
3454 c2 = VppGbpContract(
3455 self, 4220, 113, acl_index,
3456 [VppGbpContractRule(
3457 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3460 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3462 [ETH_P_IP, ETH_P_IPV6])
3464 c3 = VppGbpContract(
3465 self, 113, 4220, acl_index,
3466 [VppGbpContractRule(
3467 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3470 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3472 [ETH_P_IP, ETH_P_IPV6])
3476 # ping between hosts in remote subnets
3478 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3480 IP(src="10.220.0.1", dst="10.221.0.1") /
3481 UDP(sport=1234, dport=1234) /
3484 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
3487 self.assertEqual(rx[Ether].src, str(self.router_mac))
3488 self.assertEqual(rx[Ether].dst, eep2.mac)
3489 self.assertEqual(rx[Dot1Q].vlan, 101)
3491 # we did not learn these external hosts
3492 self.assertFalse(find_gbp_endpoint(self, ip="10.220.0.1"))
3493 self.assertFalse(find_gbp_endpoint(self, ip="10.221.0.1"))
3496 # from remote external EP to local external EP
3498 p = (Ether(src=self.pg7.remote_mac,
3499 dst=self.pg7.local_mac) /
3500 IP(src=self.pg7.remote_ip4,
3501 dst=self.pg7.local_ip4) /
3502 UDP(sport=1234, dport=48879) /
3503 VXLAN(vni=444, gpid=113, flags=0x88) /
3504 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
3505 IP(src="10.0.0.101", dst="10.220.0.1") /
3506 UDP(sport=1234, dport=1234) /
3509 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
3512 # ping from an external host to the remote external EP
3514 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3516 IP(src="10.220.0.1", dst=rep.ip4.address) /
3517 UDP(sport=1234, dport=1234) /
3520 rxs = self.send_and_expect(self.pg0, p * 1, self.pg7)
3523 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3524 # self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3525 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3526 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
3527 self.assertEqual(rx[VXLAN].vni, 444)
3528 self.assertTrue(rx[VXLAN].flags.G)
3529 self.assertTrue(rx[VXLAN].flags.Instance)
3530 # the sclass of the ext-net the packet came from
3531 self.assertEqual(rx[VXLAN].gpid, 4220)
3532 # policy was applied to the original IP packet
3533 self.assertTrue(rx[VXLAN].gpflags.A)
3534 # since it's an external host the reciever should not learn it
3535 self.assertTrue(rx[VXLAN].gpflags.D)
3536 inner = rx[VXLAN].payload
3537 self.assertEqual(inner[IP].src, "10.220.0.1")
3538 self.assertEqual(inner[IP].dst, rep.ip4.address)
3541 # An external subnet reachable via the remote external EP
3545 # first the VXLAN-GBP tunnel over which it is reached
3547 vx_tun_r = VppVxlanGbpTunnel(
3548 self, self.pg7.local_ip4,
3549 self.pg7.remote_ip4, 445,
3550 mode=(VppEnum.vl_api_vxlan_gbp_api_tunnel_mode_t.
3551 VXLAN_GBP_API_TUNNEL_MODE_L3))
3552 vx_tun_r.add_vpp_config()
3553 VppIpInterfaceBind(self, vx_tun_r, t4).add_vpp_config()
3555 self.logger.info(self.vapi.cli("sh vxlan-gbp tunnel"))
3558 # then the special adj to resolve through on that tunnel
3560 n1 = VppNeighbor(self,
3561 vx_tun_r.sw_if_index,
3562 "00:0c:0c:0c:0c:0c",
3563 self.pg7.remote_ip4)
3567 # the route via the adj above
3569 ip_222 = VppIpRoute(self, "10.222.0.0", 24,
3570 [VppRoutePath(self.pg7.remote_ip4,
3571 vx_tun_r.sw_if_index)],
3572 table_id=t4.table_id)
3573 ip_222.add_vpp_config()
3575 l3o_222 = VppGbpSubnet(
3576 self, rd1, "10.222.0.0", 24,
3577 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3579 l3o_222.add_vpp_config()
3582 # ping between hosts in local and remote external subnets
3583 # dropped without a contract
3585 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3587 IP(src="10.220.0.1", dst="10.222.0.1") /
3588 UDP(sport=1234, dport=1234) /
3591 rxs = self.send_and_assert_no_replies(self.pg0, p * 1)
3594 # Add contracts ext-nets for 220 -> 222
3596 c4 = VppGbpContract(
3597 self, 4220, 4222, acl_index,
3598 [VppGbpContractRule(
3599 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3602 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3604 [ETH_P_IP, ETH_P_IPV6])
3608 # ping from host in local to remote external subnets
3610 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3612 IP(src="10.220.0.1", dst="10.222.0.1") /
3613 UDP(sport=1234, dport=1234) /
3616 rxs = self.send_and_expect(self.pg0, p * 3, self.pg7)
3619 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3620 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3621 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3622 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
3623 self.assertEqual(rx[VXLAN].vni, 445)
3624 self.assertTrue(rx[VXLAN].flags.G)
3625 self.assertTrue(rx[VXLAN].flags.Instance)
3626 # the sclass of the ext-net the packet came from
3627 self.assertEqual(rx[VXLAN].gpid, 4220)
3628 # policy was applied to the original IP packet
3629 self.assertTrue(rx[VXLAN].gpflags.A)
3630 # since it's an external host the reciever should not learn it
3631 self.assertTrue(rx[VXLAN].gpflags.D)
3632 inner = rx[VXLAN].payload
3633 self.assertEqual(inner[Ether].dst, "00:0c:0c:0c:0c:0c")
3634 self.assertEqual(inner[IP].src, "10.220.0.1")
3635 self.assertEqual(inner[IP].dst, "10.222.0.1")
3638 # ping from host in remote to local external subnets
3639 # there's no contract for this, but the A bit is set.
3641 p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
3642 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
3643 UDP(sport=1234, dport=48879) /
3644 VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
3645 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
3646 IP(src="10.222.0.1", dst="10.220.0.1") /
3647 UDP(sport=1234, dport=1234) /
3650 rxs = self.send_and_expect(self.pg7, p * 3, self.pg0)
3651 self.assertFalse(find_gbp_endpoint(self, ip="10.222.0.1"))
3654 # ping from host in remote to remote external subnets
3655 # this is dropped by reflection check.
3657 p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
3658 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
3659 UDP(sport=1234, dport=48879) /
3660 VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
3661 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
3662 IP(src="10.222.0.1", dst="10.222.0.2") /
3663 UDP(sport=1234, dport=1234) /
3666 rxs = self.send_and_assert_no_replies(self.pg7, p * 3)
3671 self.pg7.unconfig_ip4()
3672 vlan_100.set_vtr(L2_VTR_OP.L2_DISABLED)
3675 if __name__ == '__main__':
3676 unittest.main(testRunner=VppTestRunner)