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
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
23 from vpp_sub_interface import VppDot1QSubint
24 from vpp_ip import VppIpAddress, VppIpPrefix
25 from vpp_papi import VppEnum, MACAddress
26 from vpp_papi_provider import L2_VTR_OP
27 from vpp_vxlan_gbp_tunnel import find_vxlan_gbp_tunnel, INDEX_INVALID, \
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):
72 return self.itf.remote_mac
92 return [self.ip4, self.ip6]
96 return [self.fip4, self.fip6]
98 def __init__(self, test, itf, epg, recirc, ip4, fip4, ip6, fip6,
108 self._ip4 = VppIpAddress(ip4)
109 self._fip4 = VppIpAddress(fip4)
110 self._ip6 = VppIpAddress(ip6)
111 self._fip6 = VppIpAddress(fip6)
114 self.vmac = MACAddress(self.itf.remote_mac)
116 self.vmac = MACAddress("00:00:00:00:00:00")
119 self.tun_src = VppIpAddress(tun_src)
120 self.tun_dst = VppIpAddress(tun_dst)
122 def add_vpp_config(self):
123 res = self._test.vapi.gbp_endpoint_add(
124 self.itf.sw_if_index,
125 [self.ip4.encode(), self.ip6.encode()],
129 self.tun_src.encode(),
130 self.tun_dst.encode())
131 self.handle = res.handle
132 self._test.registry.register(self, self._test.logger)
134 def remove_vpp_config(self):
135 self._test.vapi.gbp_endpoint_del(self.handle)
138 return self.object_id()
141 return "gbp-endpoint:[%d==%d:%s:%d]" % (self.handle,
142 self.itf.sw_if_index,
146 def query_vpp_config(self):
147 return find_gbp_endpoint(self._test,
148 self.itf.sw_if_index,
152 class VppGbpRecirc(VppObject):
154 GBP Recirculation Interface
157 def __init__(self, test, epg, recirc, is_ext=False):
163 def add_vpp_config(self):
164 self._test.vapi.gbp_recirc_add_del(
166 self.recirc.sw_if_index,
169 self._test.registry.register(self, self._test.logger)
171 def remove_vpp_config(self):
172 self._test.vapi.gbp_recirc_add_del(
174 self.recirc.sw_if_index,
179 return self.object_id()
182 return "gbp-recirc:[%d]" % (self.recirc.sw_if_index)
184 def query_vpp_config(self):
185 rs = self._test.vapi.gbp_recirc_dump()
187 if r.recirc.sw_if_index == self.recirc.sw_if_index:
192 class VppGbpExtItf(VppObject):
194 GBP ExtItfulation Interface
197 def __init__(self, test, itf, bd, rd):
203 def add_vpp_config(self):
204 self._test.vapi.gbp_ext_itf_add_del(
206 self.itf.sw_if_index,
209 self._test.registry.register(self, self._test.logger)
211 def remove_vpp_config(self):
212 self._test.vapi.gbp_ext_itf_add_del(
214 self.itf.sw_if_index,
219 return self.object_id()
222 return "gbp-ext-itf:[%d]" % (self.itf.sw_if_index)
224 def query_vpp_config(self):
225 rs = self._test.vapi.gbp_ext_itf_dump()
227 if r.ext_itf.sw_if_index == self.itf.sw_if_index:
232 class VppGbpSubnet(VppObject):
236 def __init__(self, test, rd, address, address_len,
237 type, sw_if_index=None, epg=None):
239 self.rd_id = rd.rd_id
240 self.prefix = VppIpPrefix(address, address_len)
242 self.sw_if_index = sw_if_index
245 def add_vpp_config(self):
246 self._test.vapi.gbp_subnet_add_del(
249 self.prefix.encode(),
251 sw_if_index=self.sw_if_index if self.sw_if_index else 0xffffffff,
252 epg_id=self.epg if self.epg else 0xffff)
253 self._test.registry.register(self, self._test.logger)
255 def remove_vpp_config(self):
256 self._test.vapi.gbp_subnet_add_del(
259 self.prefix.encode(),
263 return self.object_id()
266 return "gbp-subnet:[%d-%s]" % (self.rd_id, self.prefix)
268 def query_vpp_config(self):
269 ss = self._test.vapi.gbp_subnet_dump()
271 if s.subnet.rd_id == self.rd_id and \
272 s.subnet.type == self.type and \
273 s.subnet.prefix == self.prefix:
278 class VppGbpEndpointRetention(object):
279 def __init__(self, remote_ep_timeout=0xffffffff):
280 self.remote_ep_timeout = remote_ep_timeout
283 return {'remote_ep_timeout': self.remote_ep_timeout}
286 class VppGbpEndpointGroup(VppObject):
291 def __init__(self, test, epg, sclass, rd, bd, uplink,
292 bvi, bvi_ip4, bvi_ip6=None,
293 retention=VppGbpEndpointRetention()):
297 self.bvi_ip4 = VppIpAddress(bvi_ip4)
298 self.bvi_ip6 = VppIpAddress(bvi_ip6)
305 self.retention = retention
307 def add_vpp_config(self):
308 self._test.vapi.gbp_endpoint_group_add(
313 self.uplink.sw_if_index if self.uplink else INDEX_INVALID,
314 self.retention.encode())
315 self._test.registry.register(self, self._test.logger)
317 def remove_vpp_config(self):
318 self._test.vapi.gbp_endpoint_group_del(self.epg)
321 return self.object_id()
324 return "gbp-endpoint-group:[%d]" % (self.epg)
326 def query_vpp_config(self):
327 epgs = self._test.vapi.gbp_endpoint_group_dump()
329 if epg.epg.epg_id == self.epg:
334 class VppGbpBridgeDomain(VppObject):
339 def __init__(self, test, bd, bvi, uu_fwd=None,
340 bm_flood=None, learn=True):
344 self.bm_flood = bm_flood
347 e = VppEnum.vl_api_gbp_bridge_domain_flags_t
349 self.learn = e.GBP_BD_API_FLAG_NONE
351 self.learn = e.GBP_BD_API_FLAG_DO_NOT_LEARN
353 def add_vpp_config(self):
354 self._test.vapi.gbp_bridge_domain_add(
357 self.bvi.sw_if_index,
358 self.uu_fwd.sw_if_index if self.uu_fwd else INDEX_INVALID,
359 self.bm_flood.sw_if_index if self.bm_flood else INDEX_INVALID)
360 self._test.registry.register(self, self._test.logger)
362 def remove_vpp_config(self):
363 self._test.vapi.gbp_bridge_domain_del(self.bd.bd_id)
366 return self.object_id()
369 return "gbp-bridge-domain:[%d]" % (self.bd.bd_id)
371 def query_vpp_config(self):
372 bds = self._test.vapi.gbp_bridge_domain_dump()
374 if bd.bd.bd_id == self.bd.bd_id:
379 class VppGbpRouteDomain(VppObject):
384 def __init__(self, test, rd_id, t4, t6, ip4_uu=None, ip6_uu=None):
392 def add_vpp_config(self):
393 self._test.vapi.gbp_route_domain_add(
397 self.ip4_uu.sw_if_index if self.ip4_uu else INDEX_INVALID,
398 self.ip6_uu.sw_if_index if self.ip6_uu else INDEX_INVALID)
399 self._test.registry.register(self, self._test.logger)
401 def remove_vpp_config(self):
402 self._test.vapi.gbp_route_domain_del(self.rd_id)
405 return self.object_id()
408 return "gbp-route-domain:[%d]" % (self.rd_id)
410 def query_vpp_config(self):
411 rds = self._test.vapi.gbp_route_domain_dump()
413 if rd.rd.rd_id == self.rd_id:
418 class VppGbpContractNextHop():
419 def __init__(self, mac, bd, ip, rd):
426 return {'ip': self.ip.encode(),
427 'mac': self.mac.packed,
428 'bd_id': self.bd.bd.bd_id,
429 'rd_id': self.rd.rd_id}
432 class VppGbpContractRule():
433 def __init__(self, action, hash_mode, nhs=[]):
435 self.hash_mode = hash_mode
441 nhs.append(nh.encode())
444 return {'action': self.action,
446 'hash_mode': self.hash_mode,
447 'n_nhs': len(self.nhs),
451 class VppGbpContract(VppObject):
456 def __init__(self, test, src_epg, dst_epg, acl_index,
457 rules, allowed_ethertypes):
459 self.acl_index = acl_index
460 self.src_epg = src_epg
461 self.dst_epg = dst_epg
463 self.allowed_ethertypes = allowed_ethertypes
465 def add_vpp_config(self):
468 rules.append(r.encode())
469 self._test.vapi.gbp_contract_add_del(
475 self.allowed_ethertypes)
476 self._test.registry.register(self, self._test.logger)
478 def remove_vpp_config(self):
479 self._test.vapi.gbp_contract_add_del(
487 return self.object_id()
490 return "gbp-contract:[%d:%s:%d]" % (self.src_epg,
494 def query_vpp_config(self):
495 cs = self._test.vapi.gbp_contract_dump()
497 if c.contract.src_epg == self.src_epg \
498 and c.contract.dst_epg == self.dst_epg:
503 class VppGbpVxlanTunnel(VppInterface):
508 def __init__(self, test, vni, bd_rd_id, mode, src):
509 super(VppGbpVxlanTunnel, self).__init__(test)
512 self.bd_rd_id = bd_rd_id
516 def add_vpp_config(self):
517 r = self._test.vapi.gbp_vxlan_tunnel_add(
522 self.set_sw_if_index(r.sw_if_index)
523 self._test.registry.register(self, self._test.logger)
525 def remove_vpp_config(self):
526 self._test.vapi.gbp_vxlan_tunnel_del(self.vni)
529 return self.object_id()
532 return "gbp-vxlan:%d" % (self.sw_if_index)
534 def query_vpp_config(self):
535 return find_gbp_vxlan(self._test, self.vni)
538 class VppGbpAcl(VppObject):
543 def __init__(self, test):
545 self.acl_index = 4294967295
547 def create_rule(self, is_ipv6=0, permit_deny=0, proto=-1,
548 s_prefix=0, s_ip='\x00\x00\x00\x00', sport_from=0,
549 sport_to=65535, d_prefix=0, d_ip='\x00\x00\x00\x00',
550 dport_from=0, dport_to=65535):
551 if proto == -1 or proto == 0:
554 elif proto == 1 or proto == 58:
557 rule = ({'is_permit': permit_deny, 'is_ipv6': is_ipv6, 'proto': proto,
558 'srcport_or_icmptype_first': sport_from,
559 'srcport_or_icmptype_last': sport_to,
560 'src_ip_prefix_len': s_prefix,
562 'dstport_or_icmpcode_first': dport_from,
563 'dstport_or_icmpcode_last': dport_to,
564 'dst_ip_prefix_len': d_prefix,
565 'dst_ip_addr': d_ip})
568 def add_vpp_config(self, rules):
570 reply = self._test.vapi.acl_add_replace(self.acl_index,
573 self.acl_index = reply.acl_index
574 return self.acl_index
576 def remove_vpp_config(self):
577 self._test.vapi.acl_del(self.acl_index)
580 return self.object_id()
583 return "gbp-acl:[%d]" % (self.acl_index)
585 def query_vpp_config(self):
586 cs = self._test.vapi.acl_dump()
588 if c.acl_index == self.acl_index:
593 class TestGBP(VppTestCase):
594 """ GBP Test Case """
597 super(TestGBP, self).setUp()
599 self.create_pg_interfaces(range(9))
600 self.create_loopback_interfaces(8)
602 self.router_mac = MACAddress("00:11:22:33:44:55")
604 for i in self.pg_interfaces:
606 for i in self.lo_interfaces:
610 for i in self.pg_interfaces:
613 super(TestGBP, self).tearDown()
615 def send_and_expect_bridged(self, src, tx, dst):
616 rx = self.send_and_expect(src, tx, dst)
619 self.assertEqual(r[Ether].src, tx[0][Ether].src)
620 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
621 self.assertEqual(r[IP].src, tx[0][IP].src)
622 self.assertEqual(r[IP].dst, tx[0][IP].dst)
625 def send_and_expect_bridged6(self, src, tx, dst):
626 rx = self.send_and_expect(src, tx, dst)
629 self.assertEqual(r[Ether].src, tx[0][Ether].src)
630 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
631 self.assertEqual(r[IPv6].src, tx[0][IPv6].src)
632 self.assertEqual(r[IPv6].dst, tx[0][IPv6].dst)
635 def send_and_expect_routed(self, src, tx, dst, src_mac):
636 rx = self.send_and_expect(src, tx, dst)
639 self.assertEqual(r[Ether].src, src_mac)
640 self.assertEqual(r[Ether].dst, dst.remote_mac)
641 self.assertEqual(r[IP].src, tx[0][IP].src)
642 self.assertEqual(r[IP].dst, tx[0][IP].dst)
645 def send_and_expect_natted(self, src, tx, dst, src_ip):
646 rx = self.send_and_expect(src, tx, dst)
649 self.assertEqual(r[Ether].src, tx[0][Ether].src)
650 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
651 self.assertEqual(r[IP].src, src_ip)
652 self.assertEqual(r[IP].dst, tx[0][IP].dst)
655 def send_and_expect_natted6(self, src, tx, dst, src_ip):
656 rx = self.send_and_expect(src, tx, dst)
659 self.assertEqual(r[Ether].src, tx[0][Ether].src)
660 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
661 self.assertEqual(r[IPv6].src, src_ip)
662 self.assertEqual(r[IPv6].dst, tx[0][IPv6].dst)
665 def send_and_expect_unnatted(self, src, tx, dst, dst_ip):
666 rx = self.send_and_expect(src, tx, dst)
669 self.assertEqual(r[Ether].src, tx[0][Ether].src)
670 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
671 self.assertEqual(r[IP].dst, dst_ip)
672 self.assertEqual(r[IP].src, tx[0][IP].src)
675 def send_and_expect_unnatted6(self, src, tx, dst, dst_ip):
676 rx = self.send_and_expect(src, tx, dst)
679 self.assertEqual(r[Ether].src, tx[0][Ether].src)
680 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
681 self.assertEqual(r[IPv6].dst, dst_ip)
682 self.assertEqual(r[IPv6].src, tx[0][IPv6].src)
685 def send_and_expect_double_natted(self, src, tx, dst, src_ip, dst_ip):
686 rx = self.send_and_expect(src, tx, dst)
689 self.assertEqual(r[Ether].src, str(self.router_mac))
690 self.assertEqual(r[Ether].dst, dst.remote_mac)
691 self.assertEqual(r[IP].dst, dst_ip)
692 self.assertEqual(r[IP].src, src_ip)
695 def send_and_expect_double_natted6(self, src, tx, dst, src_ip, dst_ip):
696 rx = self.send_and_expect(src, tx, dst)
699 self.assertEqual(r[Ether].src, str(self.router_mac))
700 self.assertEqual(r[Ether].dst, dst.remote_mac)
701 self.assertEqual(r[IPv6].dst, dst_ip)
702 self.assertEqual(r[IPv6].src, src_ip)
706 """ Group Based Policy """
708 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
713 bd1 = VppBridgeDomain(self, 1)
714 bd2 = VppBridgeDomain(self, 2)
715 bd20 = VppBridgeDomain(self, 20)
719 bd20.add_vpp_config()
721 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0)
722 gbd2 = VppGbpBridgeDomain(self, bd2, self.loop1)
723 gbd20 = VppGbpBridgeDomain(self, bd20, self.loop2)
725 gbd1.add_vpp_config()
726 gbd2.add_vpp_config()
727 gbd20.add_vpp_config()
732 gt4 = VppIpTable(self, 0)
734 gt6 = VppIpTable(self, 0, is_ip6=True)
736 nt4 = VppIpTable(self, 20)
738 nt6 = VppIpTable(self, 20, is_ip6=True)
741 rd0 = VppGbpRouteDomain(self, 0, gt4, gt6, None, None)
742 rd20 = VppGbpRouteDomain(self, 20, nt4, nt6, None, None)
745 rd20.add_vpp_config()
748 # 3 EPGs, 2 of which share a BD.
749 # 2 NAT EPGs, one for floating-IP subnets, the other for internet
751 epgs = [VppGbpEndpointGroup(self, 220, 0, rd0, gbd1, self.pg4,
755 VppGbpEndpointGroup(self, 221, 0, rd0, gbd1, self.pg5,
759 VppGbpEndpointGroup(self, 222, 0, rd0, gbd2, self.pg6,
763 VppGbpEndpointGroup(self, 333, 0, rd20, gbd20, self.pg7,
767 VppGbpEndpointGroup(self, 444, 0, rd20, gbd20, self.pg8,
771 recircs = [VppGbpRecirc(self, epgs[0],
773 VppGbpRecirc(self, epgs[1],
775 VppGbpRecirc(self, epgs[2],
777 VppGbpRecirc(self, epgs[3],
778 self.loop6, is_ext=True),
779 VppGbpRecirc(self, epgs[4],
780 self.loop7, is_ext=True)]
783 recirc_nat = recircs[3]
786 # 4 end-points, 2 in the same subnet, 3 in the same BD
788 eps = [VppGbpEndpoint(self, self.pg0,
790 "10.0.0.1", "11.0.0.1",
791 "2001:10::1", "3001::1"),
792 VppGbpEndpoint(self, self.pg1,
794 "10.0.0.2", "11.0.0.2",
795 "2001:10::2", "3001::2"),
796 VppGbpEndpoint(self, self.pg2,
798 "10.0.1.1", "11.0.0.3",
799 "2001:10:1::1", "3001::3"),
800 VppGbpEndpoint(self, self.pg3,
802 "10.0.2.1", "11.0.0.4",
803 "2001:10:2::1", "3001::4")]
806 # Config related to each of the EPGs
809 # IP config on the BVI interfaces
810 if epg != epgs[1] and epg != epgs[4]:
811 VppIpInterfaceBind(self, epg.bvi, epg.rd.t4).add_vpp_config()
812 VppIpInterfaceBind(self, epg.bvi, epg.rd.t6).add_vpp_config()
813 self.vapi.sw_interface_set_mac_address(
815 self.router_mac.packed)
817 # The BVIs are NAT inside interfaces
818 self.vapi.nat44_interface_add_del_feature(epg.bvi.sw_if_index,
821 self.vapi.nat66_add_del_interface(epg.bvi.sw_if_index,
825 if_ip4 = VppIpInterfaceAddress(self, epg.bvi, epg.bvi_ip4, 32)
826 if_ip6 = VppIpInterfaceAddress(self, epg.bvi, epg.bvi_ip6, 128)
827 if_ip4.add_vpp_config()
828 if_ip6.add_vpp_config()
830 # EPG uplink interfaces in the RD
831 VppIpInterfaceBind(self, epg.uplink, epg.rd.t4).add_vpp_config()
832 VppIpInterfaceBind(self, epg.uplink, epg.rd.t6).add_vpp_config()
834 # add the BD ARP termination entry for BVI IP
835 epg.bd_arp_ip4 = VppBridgeDomainArpEntry(self, epg.bd.bd,
836 str(self.router_mac),
838 epg.bd_arp_ip6 = VppBridgeDomainArpEntry(self, epg.bd.bd,
839 str(self.router_mac),
841 epg.bd_arp_ip4.add_vpp_config()
842 epg.bd_arp_ip6.add_vpp_config()
847 for recirc in recircs:
848 # EPG's ingress recirculation interface maps to its RD
849 VppIpInterfaceBind(self, recirc.recirc,
850 recirc.epg.rd.t4).add_vpp_config()
851 VppIpInterfaceBind(self, recirc.recirc,
852 recirc.epg.rd.t6).add_vpp_config()
854 self.vapi.nat44_interface_add_del_feature(
855 recirc.recirc.sw_if_index,
858 self.vapi.nat66_add_del_interface(
859 recirc.recirc.sw_if_index,
863 recirc.add_vpp_config()
865 for recirc in recircs:
866 self.assertTrue(find_bridge_domain_port(self,
867 recirc.epg.bd.bd.bd_id,
868 recirc.recirc.sw_if_index))
871 self.pg_enable_capture(self.pg_interfaces)
874 # routes to the endpoints. We need these since there are no
875 # adj-fibs due to the fact the the BVI address has /32 and
876 # the subnet is not attached.
878 for (ip, fip) in zip(ep.ips, ep.fips):
879 # Add static mappings for each EP from the 10/8 to 11/8 network
881 self.vapi.nat44_add_del_static_mapping(ip.bytes,
886 self.vapi.nat66_add_del_static_mapping(ip.bytes,
893 self.logger.info(self.vapi.cli("sh gbp endpoint"))
895 # ... results in a Gratuitous ARP/ND on the EPG's uplink
896 rx = ep.epg.uplink.get_capture(len(ep.ips), timeout=0.2)
898 for ii, ip in enumerate(ep.ips):
902 self.assertTrue(p.haslayer(ICMPv6ND_NA))
903 self.assertEqual(p[ICMPv6ND_NA].tgt, ip.address)
905 self.assertTrue(p.haslayer(ARP))
906 self.assertEqual(p[ARP].psrc, ip.address)
907 self.assertEqual(p[ARP].pdst, ip.address)
909 # add the BD ARP termination entry for floating IP
911 ba = VppBridgeDomainArpEntry(self, epg_nat.bd.bd, ep.mac, fip)
914 # floating IPs route via EPG recirc
915 r = VppIpRoute(self, fip.address, fip.length,
916 [VppRoutePath(fip.address,
917 ep.recirc.recirc.sw_if_index,
919 proto=fip.dpo_proto)],
924 # L2 FIB entries in the NAT EPG BD to bridge the packets from
925 # the outside direct to the internal EPG
926 lf = VppL2FibEntry(self, epg_nat.bd.bd, ep.mac,
927 ep.recirc.recirc, bvi_mac=0)
931 # ARP packets for unknown IP are sent to the EPG uplink
933 pkt_arp = (Ether(dst="ff:ff:ff:ff:ff:ff",
934 src=self.pg0.remote_mac) /
936 hwdst="ff:ff:ff:ff:ff:ff",
937 hwsrc=self.pg0.remote_mac,
941 self.vapi.cli("clear trace")
942 self.pg0.add_stream(pkt_arp)
944 self.pg_enable_capture(self.pg_interfaces)
947 rxd = epgs[0].uplink.get_capture(1)
950 # ARP/ND packets get a response
952 pkt_arp = (Ether(dst="ff:ff:ff:ff:ff:ff",
953 src=self.pg0.remote_mac) /
955 hwdst="ff:ff:ff:ff:ff:ff",
956 hwsrc=self.pg0.remote_mac,
957 pdst=epgs[0].bvi_ip4.address,
958 psrc=eps[0].ip4.address))
960 self.send_and_expect(self.pg0, [pkt_arp], self.pg0)
962 nsma = in6_getnsma(inet_pton(AF_INET6, eps[0].ip6.address))
963 d = inet_ntop(AF_INET6, nsma)
964 pkt_nd = (Ether(dst=in6_getnsmac(nsma),
965 src=self.pg0.remote_mac) /
966 IPv6(dst=d, src=eps[0].ip6.address) /
967 ICMPv6ND_NS(tgt=epgs[0].bvi_ip6.address) /
968 ICMPv6NDOptSrcLLAddr(lladdr=self.pg0.remote_mac))
969 self.send_and_expect(self.pg0, [pkt_nd], self.pg0)
972 # broadcast packets are flooded
974 pkt_bcast = (Ether(dst="ff:ff:ff:ff:ff:ff",
975 src=self.pg0.remote_mac) /
976 IP(src=eps[0].ip4.address, dst="232.1.1.1") /
977 UDP(sport=1234, dport=1234) /
980 self.vapi.cli("clear trace")
981 self.pg0.add_stream(pkt_bcast)
983 self.pg_enable_capture(self.pg_interfaces)
986 rxd = eps[1].itf.get_capture(1)
987 self.assertEqual(rxd[0][Ether].dst, pkt_bcast[Ether].dst)
988 rxd = epgs[0].uplink.get_capture(1)
989 self.assertEqual(rxd[0][Ether].dst, pkt_bcast[Ether].dst)
992 # packets to non-local L3 destinations dropped
994 pkt_intra_epg_220_ip4 = (Ether(src=self.pg0.remote_mac,
995 dst=str(self.router_mac)) /
996 IP(src=eps[0].ip4.address,
998 UDP(sport=1234, dport=1234) /
1000 pkt_inter_epg_222_ip4 = (Ether(src=self.pg0.remote_mac,
1001 dst=str(self.router_mac)) /
1002 IP(src=eps[0].ip4.address,
1004 UDP(sport=1234, dport=1234) /
1007 self.send_and_assert_no_replies(self.pg0, pkt_intra_epg_220_ip4 * 65)
1009 pkt_inter_epg_222_ip6 = (Ether(src=self.pg0.remote_mac,
1010 dst=str(self.router_mac)) /
1011 IPv6(src=eps[0].ip6.address,
1012 dst="2001:10::99") /
1013 UDP(sport=1234, dport=1234) /
1015 self.send_and_assert_no_replies(self.pg0, pkt_inter_epg_222_ip6 * 65)
1018 # Add the subnet routes
1021 self, rd0, "10.0.0.0", 24,
1022 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1024 self, rd0, "10.0.1.0", 24,
1025 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1027 self, rd0, "10.0.2.0", 24,
1028 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1030 self, rd0, "2001:10::1", 64,
1031 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1033 self, rd0, "2001:10:1::1", 64,
1034 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1036 self, rd0, "2001:10:2::1", 64,
1037 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1038 s41.add_vpp_config()
1039 s42.add_vpp_config()
1040 s43.add_vpp_config()
1041 s61.add_vpp_config()
1042 s62.add_vpp_config()
1043 s63.add_vpp_config()
1045 self.send_and_expect_bridged(eps[0].itf,
1046 pkt_intra_epg_220_ip4 * 65,
1048 self.send_and_expect_bridged(eps[0].itf,
1049 pkt_inter_epg_222_ip4 * 65,
1051 self.send_and_expect_bridged6(eps[0].itf,
1052 pkt_inter_epg_222_ip6 * 65,
1055 self.logger.info(self.vapi.cli("sh ip fib 11.0.0.2"))
1056 self.logger.info(self.vapi.cli("sh gbp endpoint-group"))
1057 self.logger.info(self.vapi.cli("sh gbp endpoint"))
1058 self.logger.info(self.vapi.cli("sh gbp recirc"))
1059 self.logger.info(self.vapi.cli("sh int"))
1060 self.logger.info(self.vapi.cli("sh int addr"))
1061 self.logger.info(self.vapi.cli("sh int feat loop6"))
1062 self.logger.info(self.vapi.cli("sh vlib graph ip4-gbp-src-classify"))
1063 self.logger.info(self.vapi.cli("sh int feat loop3"))
1064 self.logger.info(self.vapi.cli("sh int feat pg0"))
1067 # Packet destined to unknown unicast is sent on the epg uplink ...
1069 pkt_intra_epg_220_to_uplink = (Ether(src=self.pg0.remote_mac,
1070 dst="00:00:00:33:44:55") /
1071 IP(src=eps[0].ip4.address,
1073 UDP(sport=1234, dport=1234) /
1076 self.send_and_expect_bridged(eps[0].itf,
1077 pkt_intra_epg_220_to_uplink * 65,
1079 # ... and nowhere else
1080 self.pg1.get_capture(0, timeout=0.1)
1081 self.pg1.assert_nothing_captured(remark="Flood onto other VMS")
1083 pkt_intra_epg_221_to_uplink = (Ether(src=self.pg2.remote_mac,
1084 dst="00:00:00:33:44:66") /
1085 IP(src=eps[0].ip4.address,
1087 UDP(sport=1234, dport=1234) /
1090 self.send_and_expect_bridged(eps[2].itf,
1091 pkt_intra_epg_221_to_uplink * 65,
1095 # Packets from the uplink are forwarded in the absence of a contract
1097 pkt_intra_epg_220_from_uplink = (Ether(src="00:00:00:33:44:55",
1098 dst=self.pg0.remote_mac) /
1099 IP(src=eps[0].ip4.address,
1101 UDP(sport=1234, dport=1234) /
1104 self.send_and_expect_bridged(self.pg4,
1105 pkt_intra_epg_220_from_uplink * 65,
1109 # in the absence of policy, endpoints in the same EPG
1112 pkt_intra_epg = (Ether(src=self.pg0.remote_mac,
1113 dst=self.pg1.remote_mac) /
1114 IP(src=eps[0].ip4.address,
1115 dst=eps[1].ip4.address) /
1116 UDP(sport=1234, dport=1234) /
1119 self.send_and_expect_bridged(self.pg0, pkt_intra_epg * 65, self.pg1)
1122 # in the abscense of policy, endpoints in the different EPG
1123 # cannot communicate
1125 pkt_inter_epg_220_to_221 = (Ether(src=self.pg0.remote_mac,
1126 dst=self.pg2.remote_mac) /
1127 IP(src=eps[0].ip4.address,
1128 dst=eps[2].ip4.address) /
1129 UDP(sport=1234, dport=1234) /
1131 pkt_inter_epg_221_to_220 = (Ether(src=self.pg2.remote_mac,
1132 dst=self.pg0.remote_mac) /
1133 IP(src=eps[2].ip4.address,
1134 dst=eps[0].ip4.address) /
1135 UDP(sport=1234, dport=1234) /
1137 pkt_inter_epg_220_to_222 = (Ether(src=self.pg0.remote_mac,
1138 dst=str(self.router_mac)) /
1139 IP(src=eps[0].ip4.address,
1140 dst=eps[3].ip4.address) /
1141 UDP(sport=1234, dport=1234) /
1144 self.send_and_assert_no_replies(eps[0].itf,
1145 pkt_inter_epg_220_to_221 * 65)
1146 self.send_and_assert_no_replies(eps[0].itf,
1147 pkt_inter_epg_220_to_222 * 65)
1150 # A uni-directional contract from EPG 220 -> 221
1152 acl = VppGbpAcl(self)
1153 rule = acl.create_rule(permit_deny=1, proto=17)
1154 rule2 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
1155 acl_index = acl.add_vpp_config([rule, rule2])
1156 c1 = VppGbpContract(
1157 self, 220, 221, acl_index,
1158 [VppGbpContractRule(
1159 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1162 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1164 [ETH_P_IP, ETH_P_IPV6])
1167 self.send_and_expect_bridged(eps[0].itf,
1168 pkt_inter_epg_220_to_221 * 65,
1170 self.send_and_assert_no_replies(eps[0].itf,
1171 pkt_inter_epg_220_to_222 * 65)
1174 # contract for the return direction
1176 c2 = VppGbpContract(
1177 self, 221, 220, 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.send_and_expect_bridged(eps[0].itf,
1188 pkt_inter_epg_220_to_221 * 65,
1190 self.send_and_expect_bridged(eps[2].itf,
1191 pkt_inter_epg_221_to_220 * 65,
1195 # the contract does not allow non-IP
1197 pkt_non_ip_inter_epg_220_to_221 = (Ether(src=self.pg0.remote_mac,
1198 dst=self.pg2.remote_mac) /
1200 self.send_and_assert_no_replies(eps[0].itf,
1201 pkt_non_ip_inter_epg_220_to_221 * 17)
1204 # check that inter group is still disabled for the groups
1205 # not in the contract.
1207 self.send_and_assert_no_replies(eps[0].itf,
1208 pkt_inter_epg_220_to_222 * 65)
1211 # A uni-directional contract from EPG 220 -> 222 'L3 routed'
1213 c3 = VppGbpContract(
1214 self, 220, 222, acl_index,
1215 [VppGbpContractRule(
1216 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1219 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1221 [ETH_P_IP, ETH_P_IPV6])
1224 self.logger.info(self.vapi.cli("sh gbp contract"))
1226 self.send_and_expect_routed(eps[0].itf,
1227 pkt_inter_epg_220_to_222 * 65,
1229 str(self.router_mac))
1232 # remove both contracts, traffic stops in both directions
1234 c2.remove_vpp_config()
1235 c1.remove_vpp_config()
1236 c3.remove_vpp_config()
1237 acl.remove_vpp_config()
1239 self.send_and_assert_no_replies(eps[2].itf,
1240 pkt_inter_epg_221_to_220 * 65)
1241 self.send_and_assert_no_replies(eps[0].itf,
1242 pkt_inter_epg_220_to_221 * 65)
1243 self.send_and_expect_bridged(eps[0].itf,
1248 # EPs to the outside world
1251 # in the EP's RD an external subnet via the NAT EPG's recirc
1253 self, rd0, "0.0.0.0", 0,
1254 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1255 sw_if_index=recirc_nat.recirc.sw_if_index,
1258 self, rd0, "11.0.0.0", 8,
1259 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1260 sw_if_index=recirc_nat.recirc.sw_if_index,
1262 se16 = VppGbpSubnet(
1264 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1265 sw_if_index=recirc_nat.recirc.sw_if_index,
1267 # in the NAT RD an external subnet via the NAT EPG's uplink
1269 self, rd20, "0.0.0.0", 0,
1270 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1271 sw_if_index=epg_nat.uplink.sw_if_index,
1273 se36 = VppGbpSubnet(
1274 self, rd20, "::", 0,
1275 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1276 sw_if_index=epg_nat.uplink.sw_if_index,
1279 self, rd20, "11.0.0.0", 8,
1280 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1281 sw_if_index=epg_nat.uplink.sw_if_index,
1283 se1.add_vpp_config()
1284 se2.add_vpp_config()
1285 se16.add_vpp_config()
1286 se3.add_vpp_config()
1287 se36.add_vpp_config()
1288 se4.add_vpp_config()
1290 self.logger.info(self.vapi.cli("sh ip fib 0.0.0.0/0"))
1291 self.logger.info(self.vapi.cli("sh ip fib 11.0.0.1"))
1292 self.logger.info(self.vapi.cli("sh ip6 fib ::/0"))
1293 self.logger.info(self.vapi.cli("sh ip6 fib %s" %
1297 # From an EP to an outside addess: IN2OUT
1299 pkt_inter_epg_220_to_global = (Ether(src=self.pg0.remote_mac,
1300 dst=str(self.router_mac)) /
1301 IP(src=eps[0].ip4.address,
1303 UDP(sport=1234, dport=1234) /
1307 self.send_and_assert_no_replies(eps[0].itf,
1308 pkt_inter_epg_220_to_global * 65)
1310 acl2 = VppGbpAcl(self)
1311 rule = acl2.create_rule(permit_deny=1, proto=17, sport_from=1234,
1312 sport_to=1234, dport_from=1234, dport_to=1234)
1313 rule2 = acl2.create_rule(is_ipv6=1, permit_deny=1, proto=17,
1314 sport_from=1234, sport_to=1234,
1315 dport_from=1234, dport_to=1234)
1317 acl_index2 = acl2.add_vpp_config([rule, rule2])
1318 c4 = VppGbpContract(
1319 self, 220, 333, acl_index2,
1320 [VppGbpContractRule(
1321 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1324 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1326 [ETH_P_IP, ETH_P_IPV6])
1329 self.send_and_expect_natted(eps[0].itf,
1330 pkt_inter_epg_220_to_global * 65,
1332 eps[0].fip4.address)
1334 pkt_inter_epg_220_to_global = (Ether(src=self.pg0.remote_mac,
1335 dst=str(self.router_mac)) /
1336 IPv6(src=eps[0].ip6.address,
1338 UDP(sport=1234, dport=1234) /
1341 self.send_and_expect_natted6(self.pg0,
1342 pkt_inter_epg_220_to_global * 65,
1344 eps[0].fip6.address)
1347 # From a global address to an EP: OUT2IN
1349 pkt_inter_epg_220_from_global = (Ether(src=str(self.router_mac),
1350 dst=self.pg0.remote_mac) /
1351 IP(dst=eps[0].fip4.address,
1353 UDP(sport=1234, dport=1234) /
1356 self.send_and_assert_no_replies(self.pg7,
1357 pkt_inter_epg_220_from_global * 65)
1359 c5 = VppGbpContract(
1360 self, 333, 220, acl_index2,
1361 [VppGbpContractRule(
1362 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1365 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1367 [ETH_P_IP, ETH_P_IPV6])
1370 self.send_and_expect_unnatted(self.pg7,
1371 pkt_inter_epg_220_from_global * 65,
1375 pkt_inter_epg_220_from_global = (Ether(src=str(self.router_mac),
1376 dst=self.pg0.remote_mac) /
1377 IPv6(dst=eps[0].fip6.address,
1379 UDP(sport=1234, dport=1234) /
1382 self.send_and_expect_unnatted6(self.pg7,
1383 pkt_inter_epg_220_from_global * 65,
1388 # From a local VM to another local VM using resp. public addresses:
1391 pkt_intra_epg_220_global = (Ether(src=self.pg0.remote_mac,
1392 dst=str(self.router_mac)) /
1393 IP(src=eps[0].ip4.address,
1394 dst=eps[1].fip4.address) /
1395 UDP(sport=1234, dport=1234) /
1398 self.send_and_expect_double_natted(eps[0].itf,
1399 pkt_intra_epg_220_global * 65,
1401 eps[0].fip4.address,
1404 pkt_intra_epg_220_global = (Ether(src=self.pg0.remote_mac,
1405 dst=str(self.router_mac)) /
1406 IPv6(src=eps[0].ip6.address,
1407 dst=eps[1].fip6.address) /
1408 UDP(sport=1234, dport=1234) /
1411 self.send_and_expect_double_natted6(eps[0].itf,
1412 pkt_intra_epg_220_global * 65,
1414 eps[0].fip6.address,
1421 # del static mappings for each EP from the 10/8 to 11/8 network
1422 self.vapi.nat44_add_del_static_mapping(ep.ip4.bytes,
1427 self.vapi.nat66_add_del_static_mapping(ep.ip6.bytes,
1433 # IP config on the BVI interfaces
1434 if epg != epgs[0] and epg != epgs[3]:
1435 self.vapi.nat44_interface_add_del_feature(epg.bvi.sw_if_index,
1438 self.vapi.nat66_add_del_interface(epg.bvi.sw_if_index,
1442 for recirc in recircs:
1443 self.vapi.nat44_interface_add_del_feature(
1444 recirc.recirc.sw_if_index,
1447 self.vapi.nat66_add_del_interface(
1448 recirc.recirc.sw_if_index,
1452 def wait_for_ep_timeout(self, sw_if_index=None, ip=None, mac=None,
1453 n_tries=100, s_time=1):
1455 if not find_gbp_endpoint(self, sw_if_index, ip, mac):
1457 n_tries = n_tries - 1
1459 self.assertFalse(find_gbp_endpoint(self, sw_if_index, ip, mac))
1462 def test_gbp_learn_l2(self):
1463 """ GBP L2 Endpoint Learning """
1465 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
1466 learnt = [{'mac': '00:00:11:11:11:01',
1468 'ip6': '2001:10::2'},
1469 {'mac': '00:00:11:11:11:02',
1471 'ip6': '2001:10::3'}]
1476 gt4 = VppIpTable(self, 1)
1477 gt4.add_vpp_config()
1478 gt6 = VppIpTable(self, 1, is_ip6=True)
1479 gt6.add_vpp_config()
1481 rd1 = VppGbpRouteDomain(self, 1, gt4, gt6)
1482 rd1.add_vpp_config()
1485 # Pg2 hosts the vxlan tunnel, hosts on pg2 to act as TEPs
1486 # Pg3 hosts the IP4 UU-flood VXLAN tunnel
1487 # Pg4 hosts the IP6 UU-flood VXLAN tunnel
1489 self.pg2.config_ip4()
1490 self.pg2.resolve_arp()
1491 self.pg2.generate_remote_hosts(4)
1492 self.pg2.configure_ipv4_neighbors()
1493 self.pg3.config_ip4()
1494 self.pg3.resolve_arp()
1495 self.pg4.config_ip4()
1496 self.pg4.resolve_arp()
1499 # Add a mcast destination VXLAN-GBP tunnel for B&M traffic
1501 tun_bm = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
1504 tun_bm.add_vpp_config()
1507 # a GBP bridge domain with a BVI and a UU-flood interface
1509 bd1 = VppBridgeDomain(self, 1)
1510 bd1.add_vpp_config()
1511 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0, self.pg3, tun_bm)
1512 gbd1.add_vpp_config()
1514 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1515 self.logger.info(self.vapi.cli("sh gbp bridge"))
1517 # ... and has a /32 applied
1518 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
1519 ip_addr.add_vpp_config()
1522 # The Endpoint-group in which we are learning endpoints
1524 epg_220 = VppGbpEndpointGroup(self, 220, 112, rd1, gbd1,
1528 VppGbpEndpointRetention(2))
1529 epg_220.add_vpp_config()
1530 epg_330 = VppGbpEndpointGroup(self, 330, 113, rd1, gbd1,
1534 VppGbpEndpointRetention(2))
1535 epg_330.add_vpp_config()
1538 # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
1541 vx_tun_l2_1 = VppGbpVxlanTunnel(
1542 self, 99, bd1.bd_id,
1543 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L2,
1545 vx_tun_l2_1.add_vpp_config()
1548 # A static endpoint that the learnt endpoints are trying to
1551 ep = VppGbpEndpoint(self, self.pg0,
1553 "10.0.0.127", "11.0.0.127",
1554 "2001:10::1", "3001::1")
1557 self.assertTrue(find_route(self, ep.ip4.address, 32, table_id=1))
1559 # a packet with an sclass from an unknwon EPG
1560 p = (Ether(src=self.pg2.remote_mac,
1561 dst=self.pg2.local_mac) /
1562 IP(src=self.pg2.remote_hosts[0].ip4,
1563 dst=self.pg2.local_ip4) /
1564 UDP(sport=1234, dport=48879) /
1565 VXLAN(vni=99, gpid=88, flags=0x88) /
1566 Ether(src=learnt[0]["mac"], dst=ep.mac) /
1567 IP(src=learnt[0]["ip"], dst=ep.ip4.address) /
1568 UDP(sport=1234, dport=1234) /
1571 self.send_and_assert_no_replies(self.pg2, p)
1574 # we should not have learnt a new tunnel endpoint, since
1575 # the EPG was not learnt.
1577 self.assertEqual(INDEX_INVALID,
1578 find_vxlan_gbp_tunnel(self,
1580 self.pg2.remote_hosts[0].ip4,
1583 # epg is not learnt, becasue the EPG is unknwon
1584 self.assertEqual(len(self.vapi.gbp_endpoint_dump()), 1)
1587 # Learn new EPs from IP packets
1589 for ii, l in enumerate(learnt):
1590 # a packet with an sclass from a knwon EPG
1591 # arriving on an unknown TEP
1592 p = (Ether(src=self.pg2.remote_mac,
1593 dst=self.pg2.local_mac) /
1594 IP(src=self.pg2.remote_hosts[1].ip4,
1595 dst=self.pg2.local_ip4) /
1596 UDP(sport=1234, dport=48879) /
1597 VXLAN(vni=99, gpid=112, flags=0x88) /
1598 Ether(src=l['mac'], dst=ep.mac) /
1599 IP(src=l['ip'], dst=ep.ip4.address) /
1600 UDP(sport=1234, dport=1234) /
1603 rx = self.send_and_expect(self.pg2, [p], self.pg0)
1606 tep1_sw_if_index = find_vxlan_gbp_tunnel(
1609 self.pg2.remote_hosts[1].ip4,
1611 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
1614 # the EP is learnt via the learnt TEP
1615 # both from its MAC and its IP
1617 self.assertTrue(find_gbp_endpoint(self,
1618 vx_tun_l2_1.sw_if_index,
1620 self.assertTrue(find_gbp_endpoint(self,
1621 vx_tun_l2_1.sw_if_index,
1624 self.logger.info(self.vapi.cli("show gbp endpoint"))
1625 self.logger.info(self.vapi.cli("show gbp vxlan"))
1626 self.logger.info(self.vapi.cli("show ip mfib"))
1629 # If we sleep for the threshold time, the learnt endpoints should
1633 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1637 # Learn new EPs from GARP packets received on the BD's mcast tunnel
1639 for ii, l in enumerate(learnt):
1640 # a packet with an sclass from a knwon EPG
1641 # arriving on an unknown TEP
1642 p = (Ether(src=self.pg2.remote_mac,
1643 dst=self.pg2.local_mac) /
1644 IP(src=self.pg2.remote_hosts[1].ip4,
1646 UDP(sport=1234, dport=48879) /
1647 VXLAN(vni=88, gpid=112, flags=0x88) /
1648 Ether(src=l['mac'], dst="ff:ff:ff:ff:ff:ff") /
1650 psrc=l['ip'], pdst=l['ip'],
1651 hwsrc=l['mac'], hwdst="ff:ff:ff:ff:ff:ff"))
1653 rx = self.send_and_expect(self.pg4, [p], self.pg0)
1656 tep1_sw_if_index = find_vxlan_gbp_tunnel(
1659 self.pg2.remote_hosts[1].ip4,
1661 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
1664 # the EP is learnt via the learnt TEP
1665 # both from its MAC and its IP
1667 self.assertTrue(find_gbp_endpoint(self,
1668 vx_tun_l2_1.sw_if_index,
1670 self.assertTrue(find_gbp_endpoint(self,
1671 vx_tun_l2_1.sw_if_index,
1675 # wait for the learnt endpoints to age out
1678 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1682 # Learn new EPs from L2 packets
1684 for ii, l in enumerate(learnt):
1685 # a packet with an sclass from a knwon EPG
1686 # arriving on an unknown TEP
1687 p = (Ether(src=self.pg2.remote_mac,
1688 dst=self.pg2.local_mac) /
1689 IP(src=self.pg2.remote_hosts[1].ip4,
1690 dst=self.pg2.local_ip4) /
1691 UDP(sport=1234, dport=48879) /
1692 VXLAN(vni=99, gpid=112, flags=0x88) /
1693 Ether(src=l['mac'], dst=ep.mac) /
1696 rx = self.send_and_expect(self.pg2, [p], self.pg0)
1699 tep1_sw_if_index = find_vxlan_gbp_tunnel(
1702 self.pg2.remote_hosts[1].ip4,
1704 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
1707 # the EP is learnt via the learnt TEP
1708 # both from its MAC and its IP
1710 self.assertTrue(find_gbp_endpoint(self,
1711 vx_tun_l2_1.sw_if_index,
1714 self.logger.info(self.vapi.cli("show gbp endpoint"))
1715 self.logger.info(self.vapi.cli("show gbp vxlan"))
1716 self.logger.info(self.vapi.cli("show vxlan-gbp tunnel"))
1719 # wait for the learnt endpoints to age out
1722 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1726 # repeat. the do not learn bit is set so the EPs are not learnt
1729 # a packet with an sclass from a knwon EPG
1730 p = (Ether(src=self.pg2.remote_mac,
1731 dst=self.pg2.local_mac) /
1732 IP(src=self.pg2.remote_hosts[1].ip4,
1733 dst=self.pg2.local_ip4) /
1734 UDP(sport=1234, dport=48879) /
1735 VXLAN(vni=99, gpid=112, flags=0x88, gpflags="D") /
1736 Ether(src=l['mac'], dst=ep.mac) /
1737 IP(src=l['ip'], dst=ep.ip4.address) /
1738 UDP(sport=1234, dport=1234) /
1741 rx = self.send_and_expect(self.pg2, p*65, self.pg0)
1744 self.assertFalse(find_gbp_endpoint(self,
1745 vx_tun_l2_1.sw_if_index,
1752 # a packet with an sclass from a knwon EPG
1753 p = (Ether(src=self.pg2.remote_mac,
1754 dst=self.pg2.local_mac) /
1755 IP(src=self.pg2.remote_hosts[1].ip4,
1756 dst=self.pg2.local_ip4) /
1757 UDP(sport=1234, dport=48879) /
1758 VXLAN(vni=99, gpid=112, flags=0x88) /
1759 Ether(src=l['mac'], dst=ep.mac) /
1760 IP(src=l['ip'], dst=ep.ip4.address) /
1761 UDP(sport=1234, dport=1234) /
1764 rx = self.send_and_expect(self.pg2, p*65, self.pg0)
1766 self.assertTrue(find_gbp_endpoint(self,
1767 vx_tun_l2_1.sw_if_index,
1771 # Static EP replies to dynamics
1773 self.logger.info(self.vapi.cli("sh l2fib bd_id 1"))
1775 p = (Ether(src=ep.mac, dst=l['mac']) /
1776 IP(dst=l['ip'], src=ep.ip4.address) /
1777 UDP(sport=1234, dport=1234) /
1780 rxs = self.send_and_expect(self.pg0, p * 17, self.pg2)
1783 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
1784 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
1785 self.assertEqual(rx[UDP].dport, 48879)
1786 # the UDP source port is a random value for hashing
1787 self.assertEqual(rx[VXLAN].gpid, 112)
1788 self.assertEqual(rx[VXLAN].vni, 99)
1789 self.assertTrue(rx[VXLAN].flags.G)
1790 self.assertTrue(rx[VXLAN].flags.Instance)
1791 self.assertTrue(rx[VXLAN].gpflags.A)
1792 self.assertFalse(rx[VXLAN].gpflags.D)
1795 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1799 # repeat in the other EPG
1800 # there's no contract between 220 and 330, but the A-bit is set
1801 # so the packet is cleared for delivery
1804 # a packet with an sclass from a knwon EPG
1805 p = (Ether(src=self.pg2.remote_mac,
1806 dst=self.pg2.local_mac) /
1807 IP(src=self.pg2.remote_hosts[1].ip4,
1808 dst=self.pg2.local_ip4) /
1809 UDP(sport=1234, dport=48879) /
1810 VXLAN(vni=99, gpid=113, flags=0x88, gpflags='A') /
1811 Ether(src=l['mac'], dst=ep.mac) /
1812 IP(src=l['ip'], dst=ep.ip4.address) /
1813 UDP(sport=1234, dport=1234) /
1816 rx = self.send_and_expect(self.pg2, p*65, self.pg0)
1818 self.assertTrue(find_gbp_endpoint(self,
1819 vx_tun_l2_1.sw_if_index,
1823 # static EP cannot reach the learnt EPs since there is no contract
1824 # only test 1 EP as the others could timeout
1826 p = (Ether(src=ep.mac, dst=l['mac']) /
1827 IP(dst=learnt[0]['ip'], src=ep.ip4.address) /
1828 UDP(sport=1234, dport=1234) /
1831 self.send_and_assert_no_replies(self.pg0, [p])
1834 # refresh the entries after the check for no replies above
1837 # a packet with an sclass from a knwon EPG
1838 p = (Ether(src=self.pg2.remote_mac,
1839 dst=self.pg2.local_mac) /
1840 IP(src=self.pg2.remote_hosts[1].ip4,
1841 dst=self.pg2.local_ip4) /
1842 UDP(sport=1234, dport=48879) /
1843 VXLAN(vni=99, gpid=113, flags=0x88, gpflags='A') /
1844 Ether(src=l['mac'], dst=ep.mac) /
1845 IP(src=l['ip'], dst=ep.ip4.address) /
1846 UDP(sport=1234, dport=1234) /
1849 rx = self.send_and_expect(self.pg2, p*65, self.pg0)
1851 self.assertTrue(find_gbp_endpoint(self,
1852 vx_tun_l2_1.sw_if_index,
1856 # Add the contract so they can talk
1858 acl = VppGbpAcl(self)
1859 rule = acl.create_rule(permit_deny=1, proto=17)
1860 rule2 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
1861 acl_index = acl.add_vpp_config([rule, rule2])
1862 c1 = VppGbpContract(
1863 self, 220, 330, acl_index,
1864 [VppGbpContractRule(
1865 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1868 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1870 [ETH_P_IP, ETH_P_IPV6])
1874 p = (Ether(src=ep.mac, dst=l['mac']) /
1875 IP(dst=l['ip'], src=ep.ip4.address) /
1876 UDP(sport=1234, dport=1234) /
1879 self.send_and_expect(self.pg0, [p], self.pg2)
1882 # send UU packets from the local EP
1884 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1885 self.logger.info(self.vapi.cli("sh gbp bridge"))
1886 p_uu = (Ether(src=ep.mac, dst="00:11:11:11:11:11") /
1887 IP(dst="10.0.0.133", src=ep.ip4.address) /
1888 UDP(sport=1234, dport=1234) /
1890 rxs = self.send_and_expect(ep.itf, [p_uu], gbd1.uu_fwd)
1892 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1894 p_bm = (Ether(src=ep.mac, dst="ff:ff:ff:ff:ff:ff") /
1895 IP(dst="10.0.0.133", src=ep.ip4.address) /
1896 UDP(sport=1234, dport=1234) /
1898 rxs = self.send_and_expect_only(ep.itf, [p_bm], tun_bm.mcast_itf)
1901 self.assertEqual(rx[IP].src, self.pg4.local_ip4)
1902 self.assertEqual(rx[IP].dst, "239.1.1.1")
1903 self.assertEqual(rx[UDP].dport, 48879)
1904 # the UDP source port is a random value for hashing
1905 self.assertEqual(rx[VXLAN].gpid, 112)
1906 self.assertEqual(rx[VXLAN].vni, 88)
1907 self.assertTrue(rx[VXLAN].flags.G)
1908 self.assertTrue(rx[VXLAN].flags.Instance)
1909 self.assertFalse(rx[VXLAN].gpflags.A)
1910 self.assertFalse(rx[VXLAN].gpflags.D)
1913 # Check v6 Endpoints
1916 # a packet with an sclass from a knwon EPG
1917 p = (Ether(src=self.pg2.remote_mac,
1918 dst=self.pg2.local_mac) /
1919 IP(src=self.pg2.remote_hosts[1].ip4,
1920 dst=self.pg2.local_ip4) /
1921 UDP(sport=1234, dport=48879) /
1922 VXLAN(vni=99, gpid=113, flags=0x88, gpflags='A') /
1923 Ether(src=l['mac'], dst=ep.mac) /
1924 IPv6(src=l['ip6'], dst=ep.ip6.address) /
1925 UDP(sport=1234, dport=1234) /
1928 rx = self.send_and_expect(self.pg2, p*65, self.pg0)
1930 self.assertTrue(find_gbp_endpoint(self,
1931 vx_tun_l2_1.sw_if_index,
1935 # L3 Endpoint Learning
1936 # - configured on the bridge's BVI
1943 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1946 self.pg2.unconfig_ip4()
1947 self.pg3.unconfig_ip4()
1948 self.pg4.unconfig_ip4()
1950 self.logger.info(self.vapi.cli("sh int"))
1951 self.logger.info(self.vapi.cli("sh gbp vxlan"))
1953 def test_gbp_learn_vlan_l2(self):
1954 """ GBP L2 Endpoint w/ VLANs"""
1956 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
1957 learnt = [{'mac': '00:00:11:11:11:01',
1959 'ip6': '2001:10::2'},
1960 {'mac': '00:00:11:11:11:02',
1962 'ip6': '2001:10::3'}]
1967 gt4 = VppIpTable(self, 1)
1968 gt4.add_vpp_config()
1969 gt6 = VppIpTable(self, 1, is_ip6=True)
1970 gt6.add_vpp_config()
1972 rd1 = VppGbpRouteDomain(self, 1, gt4, gt6)
1973 rd1.add_vpp_config()
1976 # Pg2 hosts the vxlan tunnel, hosts on pg2 to act as TEPs
1978 self.pg2.config_ip4()
1979 self.pg2.resolve_arp()
1980 self.pg2.generate_remote_hosts(4)
1981 self.pg2.configure_ipv4_neighbors()
1982 self.pg3.config_ip4()
1983 self.pg3.resolve_arp()
1986 # The EP will be on a vlan sub-interface
1988 vlan_11 = VppDot1QSubint(self, self.pg0, 11)
1990 self.vapi.l2_interface_vlan_tag_rewrite(vlan_11.sw_if_index,
1994 bd_uu_fwd = VppVxlanGbpTunnel(self, self.pg3.local_ip4,
1995 self.pg3.remote_ip4, 116)
1996 bd_uu_fwd.add_vpp_config()
1999 # a GBP bridge domain with a BVI and a UU-flood interface
2000 # The BD is marked as do not learn, so no endpoints are ever
2001 # learnt in this BD.
2003 bd1 = VppBridgeDomain(self, 1)
2004 bd1.add_vpp_config()
2005 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0, bd_uu_fwd,
2007 gbd1.add_vpp_config()
2009 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2010 self.logger.info(self.vapi.cli("sh gbp bridge"))
2012 # ... and has a /32 applied
2013 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2014 ip_addr.add_vpp_config()
2017 # The Endpoint-group in which we are learning endpoints
2019 epg_220 = VppGbpEndpointGroup(self, 220, 441, rd1, gbd1,
2023 VppGbpEndpointRetention(2))
2024 epg_220.add_vpp_config()
2027 # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
2030 vx_tun_l2_1 = VppGbpVxlanTunnel(
2031 self, 99, bd1.bd_id,
2032 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L2,
2034 vx_tun_l2_1.add_vpp_config()
2037 # A static endpoint that the learnt endpoints are trying to
2040 ep = VppGbpEndpoint(self, vlan_11,
2042 "10.0.0.127", "11.0.0.127",
2043 "2001:10::1", "3001::1")
2046 self.assertTrue(find_route(self, ep.ip4.address, 32, table_id=1))
2049 # Send to the static EP
2051 for ii, l in enumerate(learnt):
2052 # a packet with an sclass from a knwon EPG
2053 # arriving on an unknown TEP
2054 p = (Ether(src=self.pg2.remote_mac,
2055 dst=self.pg2.local_mac) /
2056 IP(src=self.pg2.remote_hosts[1].ip4,
2057 dst=self.pg2.local_ip4) /
2058 UDP(sport=1234, dport=48879) /
2059 VXLAN(vni=99, gpid=441, flags=0x88) /
2060 Ether(src=l['mac'], dst=ep.mac) /
2061 IP(src=l['ip'], dst=ep.ip4.address) /
2062 UDP(sport=1234, dport=1234) /
2065 rxs = self.send_and_expect(self.pg2, [p], self.pg0)
2068 # packet to EP has the EP's vlan tag
2071 self.assertEqual(rx[Dot1Q].vlan, 11)
2074 # the EP is not learnt since the BD setting prevents it
2077 self.assertFalse(find_gbp_endpoint(self,
2078 vx_tun_l2_1.sw_if_index,
2080 self.assertEqual(INDEX_INVALID,
2081 find_vxlan_gbp_tunnel(
2084 self.pg2.remote_hosts[1].ip4,
2087 self.assertEqual(len(self.vapi.gbp_endpoint_dump()), 1)
2091 # we didn't learn the remotes so they are sent to the UU-fwd
2094 p = (Ether(src=ep.mac, dst=l['mac']) /
2096 IP(dst=l['ip'], src=ep.ip4.address) /
2097 UDP(sport=1234, dport=1234) /
2100 rxs = self.send_and_expect(self.pg0, p * 17, self.pg3)
2103 self.assertEqual(rx[IP].src, self.pg3.local_ip4)
2104 self.assertEqual(rx[IP].dst, self.pg3.remote_ip4)
2105 self.assertEqual(rx[UDP].dport, 48879)
2106 # the UDP source port is a random value for hashing
2107 self.assertEqual(rx[VXLAN].gpid, 441)
2108 self.assertEqual(rx[VXLAN].vni, 116)
2109 self.assertTrue(rx[VXLAN].flags.G)
2110 self.assertTrue(rx[VXLAN].flags.Instance)
2111 self.assertFalse(rx[VXLAN].gpflags.A)
2112 self.assertFalse(rx[VXLAN].gpflags.D)
2114 self.pg2.unconfig_ip4()
2115 self.pg3.unconfig_ip4()
2117 def test_gbp_learn_l3(self):
2118 """ GBP L3 Endpoint Learning """
2120 self.vapi.cli("set logging class gbp debug")
2122 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
2123 routed_dst_mac = "00:0c:0c:0c:0c:0c"
2124 routed_src_mac = "00:22:bd:f8:19:ff"
2126 learnt = [{'mac': '00:00:11:11:11:02',
2128 'ip6': '2001:10::2'},
2129 {'mac': '00:00:11:11:11:03',
2131 'ip6': '2001:10::3'}]
2136 t4 = VppIpTable(self, 1)
2138 t6 = VppIpTable(self, 1, True)
2141 tun_ip4_uu = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
2142 self.pg4.remote_ip4, 114)
2143 tun_ip6_uu = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
2144 self.pg4.remote_ip4, 116)
2145 tun_ip4_uu.add_vpp_config()
2146 tun_ip6_uu.add_vpp_config()
2148 rd1 = VppGbpRouteDomain(self, 2, t4, t6, tun_ip4_uu, tun_ip6_uu)
2149 rd1.add_vpp_config()
2151 self.loop0.set_mac(self.router_mac)
2154 # Bind the BVI to the RD
2156 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
2157 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
2160 # Pg2 hosts the vxlan tunnel
2161 # hosts on pg2 to act as TEPs
2165 self.pg2.config_ip4()
2166 self.pg2.resolve_arp()
2167 self.pg2.generate_remote_hosts(4)
2168 self.pg2.configure_ipv4_neighbors()
2169 self.pg3.config_ip4()
2170 self.pg3.resolve_arp()
2171 self.pg4.config_ip4()
2172 self.pg4.resolve_arp()
2175 # a GBP bridge domain with a BVI and a UU-flood interface
2177 bd1 = VppBridgeDomain(self, 1)
2178 bd1.add_vpp_config()
2179 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0, self.pg3)
2180 gbd1.add_vpp_config()
2182 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2183 self.logger.info(self.vapi.cli("sh gbp bridge"))
2184 self.logger.info(self.vapi.cli("sh gbp route"))
2186 # ... and has a /32 and /128 applied
2187 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2188 ip4_addr.add_vpp_config()
2189 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 128)
2190 ip6_addr.add_vpp_config()
2193 # The Endpoint-group in which we are learning endpoints
2195 epg_220 = VppGbpEndpointGroup(self, 220, 441, rd1, gbd1,
2199 VppGbpEndpointRetention(2))
2200 epg_220.add_vpp_config()
2203 # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
2206 vx_tun_l3 = VppGbpVxlanTunnel(
2207 self, 101, rd1.rd_id,
2208 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
2210 vx_tun_l3.add_vpp_config()
2213 # A static endpoint that the learnt endpoints are trying to
2216 ep = VppGbpEndpoint(self, self.pg0,
2218 "10.0.0.127", "11.0.0.127",
2219 "2001:10::1", "3001::1")
2223 # learn some remote IPv4 EPs
2225 for ii, l in enumerate(learnt):
2226 # a packet with an sclass from a knwon EPG
2227 # arriving on an unknown TEP
2228 p = (Ether(src=self.pg2.remote_mac,
2229 dst=self.pg2.local_mac) /
2230 IP(src=self.pg2.remote_hosts[1].ip4,
2231 dst=self.pg2.local_ip4) /
2232 UDP(sport=1234, dport=48879) /
2233 VXLAN(vni=101, gpid=441, flags=0x88) /
2234 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2235 IP(src=l['ip'], dst=ep.ip4.address) /
2236 UDP(sport=1234, dport=1234) /
2239 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2242 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2245 self.pg2.remote_hosts[1].ip4,
2247 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2249 # endpoint learnt via the parent GBP-vxlan interface
2250 self.assertTrue(find_gbp_endpoint(self,
2251 vx_tun_l3._sw_if_index,
2255 # Static IPv4 EP replies to learnt
2258 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2259 IP(dst=l['ip'], src=ep.ip4.address) /
2260 UDP(sport=1234, dport=1234) /
2263 rxs = self.send_and_expect(self.pg0, p*1, self.pg2)
2266 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2267 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2268 self.assertEqual(rx[UDP].dport, 48879)
2269 # the UDP source port is a random value for hashing
2270 self.assertEqual(rx[VXLAN].gpid, 441)
2271 self.assertEqual(rx[VXLAN].vni, 101)
2272 self.assertTrue(rx[VXLAN].flags.G)
2273 self.assertTrue(rx[VXLAN].flags.Instance)
2274 self.assertTrue(rx[VXLAN].gpflags.A)
2275 self.assertFalse(rx[VXLAN].gpflags.D)
2277 inner = rx[VXLAN].payload
2279 self.assertEqual(inner[Ether].src, routed_src_mac)
2280 self.assertEqual(inner[Ether].dst, routed_dst_mac)
2281 self.assertEqual(inner[IP].src, ep.ip4.address)
2282 self.assertEqual(inner[IP].dst, l['ip'])
2285 self.assertFalse(find_gbp_endpoint(self,
2290 # learn some remote IPv6 EPs
2292 for ii, l in enumerate(learnt):
2293 # a packet with an sclass from a knwon EPG
2294 # arriving on an unknown TEP
2295 p = (Ether(src=self.pg2.remote_mac,
2296 dst=self.pg2.local_mac) /
2297 IP(src=self.pg2.remote_hosts[1].ip4,
2298 dst=self.pg2.local_ip4) /
2299 UDP(sport=1234, dport=48879) /
2300 VXLAN(vni=101, gpid=441, flags=0x88) /
2301 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2302 IPv6(src=l['ip6'], dst=ep.ip6.address) /
2303 UDP(sport=1234, dport=1234) /
2306 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2309 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2312 self.pg2.remote_hosts[1].ip4,
2314 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2316 self.logger.info(self.vapi.cli("show gbp bridge"))
2317 self.logger.info(self.vapi.cli("show vxlan-gbp tunnel"))
2318 self.logger.info(self.vapi.cli("show gbp vxlan"))
2319 self.logger.info(self.vapi.cli("show int addr"))
2321 # endpoint learnt via the TEP
2322 self.assertTrue(find_gbp_endpoint(self, ip=l['ip6']))
2324 self.logger.info(self.vapi.cli("show gbp endpoint"))
2325 self.logger.info(self.vapi.cli("show ip fib index 1 %s" % l['ip']))
2328 # Static EP replies to learnt
2331 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2332 IPv6(dst=l['ip6'], src=ep.ip6.address) /
2333 UDP(sport=1234, dport=1234) /
2336 rxs = self.send_and_expect(self.pg0, p*65, self.pg2)
2339 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2340 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2341 self.assertEqual(rx[UDP].dport, 48879)
2342 # the UDP source port is a random value for hashing
2343 self.assertEqual(rx[VXLAN].gpid, 441)
2344 self.assertEqual(rx[VXLAN].vni, 101)
2345 self.assertTrue(rx[VXLAN].flags.G)
2346 self.assertTrue(rx[VXLAN].flags.Instance)
2347 self.assertTrue(rx[VXLAN].gpflags.A)
2348 self.assertFalse(rx[VXLAN].gpflags.D)
2350 inner = rx[VXLAN].payload
2352 self.assertEqual(inner[Ether].src, routed_src_mac)
2353 self.assertEqual(inner[Ether].dst, routed_dst_mac)
2354 self.assertEqual(inner[IPv6].src, ep.ip6.address)
2355 self.assertEqual(inner[IPv6].dst, l['ip6'])
2357 self.logger.info(self.vapi.cli("sh gbp endpoint"))
2359 self.wait_for_ep_timeout(ip=l['ip'])
2362 # Static sends to unknown EP with no route
2364 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2365 IP(dst="10.0.0.99", src=ep.ip4.address) /
2366 UDP(sport=1234, dport=1234) /
2369 self.send_and_assert_no_replies(self.pg0, [p])
2372 # Add a route to static EP's v4 and v6 subnet
2373 # packets should be sent on the v4/v6 uu=fwd interface resp.
2375 se_10_24 = VppGbpSubnet(
2376 self, rd1, "10.0.0.0", 24,
2377 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT)
2378 se_10_24.add_vpp_config()
2380 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2381 IP(dst="10.0.0.99", src=ep.ip4.address) /
2382 UDP(sport=1234, dport=1234) /
2385 rxs = self.send_and_expect(self.pg0, [p], self.pg4)
2387 self.assertEqual(rx[IP].src, self.pg4.local_ip4)
2388 self.assertEqual(rx[IP].dst, self.pg4.remote_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, 114)
2393 self.assertTrue(rx[VXLAN].flags.G)
2394 self.assertTrue(rx[VXLAN].flags.Instance)
2395 # policy is not applied to packets sent to the uu-fwd interfaces
2396 self.assertFalse(rx[VXLAN].gpflags.A)
2397 self.assertFalse(rx[VXLAN].gpflags.D)
2400 # learn some remote IPv4 EPs
2402 for ii, l in enumerate(learnt):
2403 # a packet with an sclass from a knwon EPG
2404 # arriving on an unknown TEP
2405 p = (Ether(src=self.pg2.remote_mac,
2406 dst=self.pg2.local_mac) /
2407 IP(src=self.pg2.remote_hosts[2].ip4,
2408 dst=self.pg2.local_ip4) /
2409 UDP(sport=1234, dport=48879) /
2410 VXLAN(vni=101, gpid=441, flags=0x88) /
2411 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2412 IP(src=l['ip'], dst=ep.ip4.address) /
2413 UDP(sport=1234, dport=1234) /
2416 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2419 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2422 self.pg2.remote_hosts[2].ip4,
2424 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2426 # endpoint learnt via the parent GBP-vxlan interface
2427 self.assertTrue(find_gbp_endpoint(self,
2428 vx_tun_l3._sw_if_index,
2432 # Add a remote endpoint from the API
2434 rep_88 = VppGbpEndpoint(self, vx_tun_l3,
2436 "10.0.0.88", "11.0.0.88",
2437 "2001:10::88", "3001::88",
2438 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
2440 self.pg2.remote_hosts[1].ip4,
2442 rep_88.add_vpp_config()
2445 # Add a remote endpoint from the API that matches an existing one
2447 rep_2 = VppGbpEndpoint(self, vx_tun_l3,
2449 learnt[0]['ip'], "11.0.0.101",
2450 learnt[0]['ip6'], "3001::101",
2451 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
2453 self.pg2.remote_hosts[1].ip4,
2455 rep_2.add_vpp_config()
2458 # Add a route to the leanred EP's v4 subnet
2459 # packets should be send on the v4/v6 uu=fwd interface resp.
2461 se_10_1_24 = VppGbpSubnet(
2462 self, rd1, "10.0.1.0", 24,
2463 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT)
2464 se_10_1_24.add_vpp_config()
2466 self.logger.info(self.vapi.cli("show gbp endpoint"))
2468 ips = ["10.0.0.88", learnt[0]['ip']]
2470 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2471 IP(dst=ip, src=ep.ip4.address) /
2472 UDP(sport=1234, dport=1234) /
2475 rxs = self.send_and_expect(self.pg0, p*65, self.pg2)
2478 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2479 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2480 self.assertEqual(rx[UDP].dport, 48879)
2481 # the UDP source port is a random value for hashing
2482 self.assertEqual(rx[VXLAN].gpid, 441)
2483 self.assertEqual(rx[VXLAN].vni, 101)
2484 self.assertTrue(rx[VXLAN].flags.G)
2485 self.assertTrue(rx[VXLAN].flags.Instance)
2486 self.assertTrue(rx[VXLAN].gpflags.A)
2487 self.assertFalse(rx[VXLAN].gpflags.D)
2489 inner = rx[VXLAN].payload
2491 self.assertEqual(inner[Ether].src, routed_src_mac)
2492 self.assertEqual(inner[Ether].dst, routed_dst_mac)
2493 self.assertEqual(inner[IP].src, ep.ip4.address)
2494 self.assertEqual(inner[IP].dst, ip)
2497 # remove the API remote EPs, only API sourced is gone, the DP
2498 # learnt one remains
2500 rep_88.remove_vpp_config()
2501 rep_2.remove_vpp_config()
2503 self.assertTrue(find_gbp_endpoint(self, ip=rep_2.ip4.address))
2505 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2506 IP(src=ep.ip4.address, dst=rep_2.ip4.address) /
2507 UDP(sport=1234, dport=1234) /
2509 rxs = self.send_and_expect(self.pg0, [p], self.pg2)
2511 self.assertFalse(find_gbp_endpoint(self, ip=rep_88.ip4.address))
2513 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2514 IP(src=ep.ip4.address, dst=rep_88.ip4.address) /
2515 UDP(sport=1234, dport=1234) /
2517 rxs = self.send_and_expect(self.pg0, [p], self.pg4)
2520 # to appease the testcase we cannot have the registered EP stll
2521 # present (because it's DP learnt) when the TC ends so wait until
2524 self.wait_for_ep_timeout(ip=rep_88.ip4.address)
2525 self.wait_for_ep_timeout(ip=rep_2.ip4.address)
2528 # shutdown with learnt endpoint present
2530 p = (Ether(src=self.pg2.remote_mac,
2531 dst=self.pg2.local_mac) /
2532 IP(src=self.pg2.remote_hosts[1].ip4,
2533 dst=self.pg2.local_ip4) /
2534 UDP(sport=1234, dport=48879) /
2535 VXLAN(vni=101, gpid=441, flags=0x88) /
2536 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2537 IP(src=learnt[1]['ip'], dst=ep.ip4.address) /
2538 UDP(sport=1234, dport=1234) /
2541 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2543 # endpoint learnt via the parent GBP-vxlan interface
2544 self.assertTrue(find_gbp_endpoint(self,
2545 vx_tun_l3._sw_if_index,
2550 # remote endpoint becomes local
2552 self.pg2.unconfig_ip4()
2553 self.pg3.unconfig_ip4()
2554 self.pg4.unconfig_ip4()
2556 def test_gbp_redirect(self):
2557 """ GBP Endpoint Redirect """
2559 self.vapi.cli("set logging class gbp debug")
2561 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
2562 routed_dst_mac = "00:0c:0c:0c:0c:0c"
2563 routed_src_mac = "00:22:bd:f8:19:ff"
2565 learnt = [{'mac': '00:00:11:11:11:02',
2567 'ip6': '2001:10::2'},
2568 {'mac': '00:00:11:11:11:03',
2570 'ip6': '2001:10::3'}]
2575 t4 = VppIpTable(self, 1)
2577 t6 = VppIpTable(self, 1, True)
2580 rd1 = VppGbpRouteDomain(self, 2, t4, t6)
2581 rd1.add_vpp_config()
2583 self.loop0.set_mac(self.router_mac)
2586 # Bind the BVI to the RD
2588 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
2589 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
2592 # Pg7 hosts a BD's UU-fwd
2594 self.pg7.config_ip4()
2595 self.pg7.resolve_arp()
2598 # a GBP bridge domains for the EPs
2600 bd1 = VppBridgeDomain(self, 1)
2601 bd1.add_vpp_config()
2602 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0)
2603 gbd1.add_vpp_config()
2605 bd2 = VppBridgeDomain(self, 2)
2606 bd2.add_vpp_config()
2607 gbd2 = VppGbpBridgeDomain(self, bd2, self.loop1)
2608 gbd2.add_vpp_config()
2610 # ... and has a /32 and /128 applied
2611 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2612 ip4_addr.add_vpp_config()
2613 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 128)
2614 ip6_addr.add_vpp_config()
2615 ip4_addr = VppIpInterfaceAddress(self, gbd2.bvi, "10.0.1.128", 32)
2616 ip4_addr.add_vpp_config()
2617 ip6_addr = VppIpInterfaceAddress(self, gbd2.bvi, "2001:11::128", 128)
2618 ip6_addr.add_vpp_config()
2621 # The Endpoint-groups in which we are learning endpoints
2623 epg_220 = VppGbpEndpointGroup(self, 220, 440, rd1, gbd1,
2627 VppGbpEndpointRetention(2))
2628 epg_220.add_vpp_config()
2629 epg_221 = VppGbpEndpointGroup(self, 221, 441, rd1, gbd2,
2633 VppGbpEndpointRetention(2))
2634 epg_221.add_vpp_config()
2635 epg_222 = VppGbpEndpointGroup(self, 222, 442, rd1, gbd1,
2639 VppGbpEndpointRetention(2))
2640 epg_222.add_vpp_config()
2643 # a GBP bridge domains for the SEPs
2645 bd_uu1 = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
2646 self.pg7.remote_ip4, 116)
2647 bd_uu1.add_vpp_config()
2648 bd_uu2 = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
2649 self.pg7.remote_ip4, 117)
2650 bd_uu2.add_vpp_config()
2652 bd3 = VppBridgeDomain(self, 3)
2653 bd3.add_vpp_config()
2654 gbd3 = VppGbpBridgeDomain(self, bd3, self.loop2, bd_uu1, learn=False)
2655 gbd3.add_vpp_config()
2656 bd4 = VppBridgeDomain(self, 4)
2657 bd4.add_vpp_config()
2658 gbd4 = VppGbpBridgeDomain(self, bd4, self.loop3, bd_uu2, learn=False)
2659 gbd4.add_vpp_config()
2662 # EPGs in which the service endpoints exist
2664 epg_320 = VppGbpEndpointGroup(self, 320, 550, rd1, gbd3,
2668 VppGbpEndpointRetention(2))
2669 epg_320.add_vpp_config()
2670 epg_321 = VppGbpEndpointGroup(self, 321, 551, rd1, gbd4,
2674 VppGbpEndpointRetention(2))
2675 epg_321.add_vpp_config()
2678 # three local endpoints
2680 ep1 = VppGbpEndpoint(self, self.pg0,
2682 "10.0.0.1", "11.0.0.1",
2683 "2001:10::1", "3001:10::1")
2684 ep1.add_vpp_config()
2685 ep2 = VppGbpEndpoint(self, self.pg1,
2687 "10.0.1.1", "11.0.1.1",
2688 "2001:11::1", "3001:11::1")
2689 ep2.add_vpp_config()
2690 ep3 = VppGbpEndpoint(self, self.pg2,
2692 "10.0.2.2", "11.0.2.2",
2693 "2001:12::1", "3001:12::1")
2694 ep3.add_vpp_config()
2699 sep1 = VppGbpEndpoint(self, self.pg3,
2701 "12.0.0.1", "13.0.0.1",
2702 "4001:10::1", "5001:10::1")
2703 sep1.add_vpp_config()
2704 sep2 = VppGbpEndpoint(self, self.pg4,
2706 "12.0.0.2", "13.0.0.2",
2707 "4001:10::2", "5001:10::2")
2708 sep2.add_vpp_config()
2709 sep3 = VppGbpEndpoint(self, self.pg5,
2711 "12.0.1.1", "13.0.1.1",
2712 "4001:11::1", "5001:11::1")
2713 sep3.add_vpp_config()
2714 # this EP is not installed immediately
2715 sep4 = VppGbpEndpoint(self, self.pg6,
2717 "12.0.1.2", "13.0.1.2",
2718 "4001:11::2", "5001:11::2")
2721 # an L2 switch packet between local EPs in different EPGs
2722 # different dest ports on each so the are LB hashed differently
2724 p4 = [(Ether(src=ep1.mac, dst=ep3.mac) /
2725 IP(src=ep1.ip4.address, dst=ep3.ip4.address) /
2726 UDP(sport=1234, dport=1234) /
2728 (Ether(src=ep3.mac, dst=ep1.mac) /
2729 IP(src=ep3.ip4.address, dst=ep1.ip4.address) /
2730 UDP(sport=1234, dport=1234) /
2732 p6 = [(Ether(src=ep1.mac, dst=ep3.mac) /
2733 IPv6(src=ep1.ip6.address, dst=ep3.ip6.address) /
2734 UDP(sport=1234, dport=1234) /
2736 (Ether(src=ep3.mac, dst=ep1.mac) /
2737 IPv6(src=ep3.ip6.address, dst=ep1.ip6.address) /
2738 UDP(sport=1234, dport=1230) /
2741 # should be dropped since no contract yet
2742 self.send_and_assert_no_replies(self.pg0, [p4[0]])
2743 self.send_and_assert_no_replies(self.pg0, [p6[0]])
2746 # Add a contract with a rule to load-balance redirect via SEP1 and SEP2
2747 # one of the next-hops is via an EP that is not known
2749 acl = VppGbpAcl(self)
2750 rule4 = acl.create_rule(permit_deny=1, proto=17)
2751 rule6 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
2752 acl_index = acl.add_vpp_config([rule4, rule6])
2755 # test the src-ip hash mode
2757 c1 = VppGbpContract(
2758 self, 220, 222, acl_index,
2759 [VppGbpContractRule(
2760 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2761 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2762 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
2763 sep1.ip4, sep1.epg.rd),
2764 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
2765 sep2.ip4, sep2.epg.rd)]),
2767 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2768 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2769 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
2770 sep3.ip6, sep3.epg.rd),
2771 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
2772 sep4.ip6, sep4.epg.rd)])],
2773 [ETH_P_IP, ETH_P_IPV6])
2776 c2 = VppGbpContract(
2777 self, 222, 220, acl_index,
2778 [VppGbpContractRule(
2779 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2780 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2781 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
2782 sep1.ip4, sep1.epg.rd),
2783 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
2784 sep2.ip4, sep2.epg.rd)]),
2786 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2787 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2788 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
2789 sep3.ip6, sep3.epg.rd),
2790 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
2791 sep4.ip6, sep4.epg.rd)])],
2792 [ETH_P_IP, ETH_P_IPV6])
2796 # send again with the contract preset, now packets arrive
2797 # at SEP1 or SEP2 depending on the hashing
2799 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
2802 self.assertEqual(rx[Ether].src, routed_src_mac)
2803 self.assertEqual(rx[Ether].dst, sep1.mac)
2804 self.assertEqual(rx[IP].src, ep1.ip4.address)
2805 self.assertEqual(rx[IP].dst, ep3.ip4.address)
2807 rxs = self.send_and_expect(self.pg2, p4[1] * 17, sep2.itf)
2810 self.assertEqual(rx[Ether].src, routed_src_mac)
2811 self.assertEqual(rx[Ether].dst, sep2.mac)
2812 self.assertEqual(rx[IP].src, ep3.ip4.address)
2813 self.assertEqual(rx[IP].dst, ep1.ip4.address)
2815 rxs = self.send_and_expect(self.pg0, p6[0] * 17, self.pg7)
2818 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
2819 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
2820 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
2821 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
2822 self.assertEqual(rx[VXLAN].vni, 117)
2823 self.assertTrue(rx[VXLAN].flags.G)
2824 self.assertTrue(rx[VXLAN].flags.Instance)
2825 # redirect policy has been applied
2826 self.assertTrue(rx[VXLAN].gpflags.A)
2827 self.assertFalse(rx[VXLAN].gpflags.D)
2829 inner = rx[VXLAN].payload
2831 self.assertEqual(inner[Ether].src, routed_src_mac)
2832 self.assertEqual(inner[Ether].dst, sep4.mac)
2833 self.assertEqual(inner[IPv6].src, ep1.ip6.address)
2834 self.assertEqual(inner[IPv6].dst, ep3.ip6.address)
2836 rxs = self.send_and_expect(self.pg2, p6[1] * 17, sep3.itf)
2839 self.assertEqual(rx[Ether].src, routed_src_mac)
2840 self.assertEqual(rx[Ether].dst, sep3.mac)
2841 self.assertEqual(rx[IPv6].src, ep3.ip6.address)
2842 self.assertEqual(rx[IPv6].dst, ep1.ip6.address)
2845 # programme the unknown EP
2847 sep4.add_vpp_config()
2849 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep4.itf)
2852 self.assertEqual(rx[Ether].src, routed_src_mac)
2853 self.assertEqual(rx[Ether].dst, sep4.mac)
2854 self.assertEqual(rx[IPv6].src, ep1.ip6.address)
2855 self.assertEqual(rx[IPv6].dst, ep3.ip6.address)
2858 # and revert back to unprogrammed
2860 sep4.remove_vpp_config()
2862 rxs = self.send_and_expect(self.pg0, p6[0] * 17, self.pg7)
2865 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
2866 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
2867 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
2868 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
2869 self.assertEqual(rx[VXLAN].vni, 117)
2870 self.assertTrue(rx[VXLAN].flags.G)
2871 self.assertTrue(rx[VXLAN].flags.Instance)
2872 # redirect policy has been applied
2873 self.assertTrue(rx[VXLAN].gpflags.A)
2874 self.assertFalse(rx[VXLAN].gpflags.D)
2876 inner = rx[VXLAN].payload
2878 self.assertEqual(inner[Ether].src, routed_src_mac)
2879 self.assertEqual(inner[Ether].dst, sep4.mac)
2880 self.assertEqual(inner[IPv6].src, ep1.ip6.address)
2881 self.assertEqual(inner[IPv6].dst, ep3.ip6.address)
2883 c1.remove_vpp_config()
2884 c2.remove_vpp_config()
2887 # test the symmetric hash mode
2889 c1 = VppGbpContract(
2890 self, 220, 222, acl_index,
2891 [VppGbpContractRule(
2892 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2893 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
2894 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
2895 sep1.ip4, sep1.epg.rd),
2896 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
2897 sep2.ip4, sep2.epg.rd)]),
2899 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2900 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
2901 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
2902 sep3.ip6, sep3.epg.rd),
2903 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
2904 sep4.ip6, sep4.epg.rd)])],
2905 [ETH_P_IP, ETH_P_IPV6])
2908 c2 = VppGbpContract(
2909 self, 222, 220, acl_index,
2910 [VppGbpContractRule(
2911 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2912 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
2913 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
2914 sep1.ip4, sep1.epg.rd),
2915 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
2916 sep2.ip4, sep2.epg.rd)]),
2918 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2919 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
2920 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
2921 sep3.ip6, sep3.epg.rd),
2922 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
2923 sep4.ip6, sep4.epg.rd)])],
2924 [ETH_P_IP, ETH_P_IPV6])
2928 # send again with the contract preset, now packets arrive
2929 # at SEP1 for both directions
2931 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
2934 self.assertEqual(rx[Ether].src, routed_src_mac)
2935 self.assertEqual(rx[Ether].dst, sep1.mac)
2936 self.assertEqual(rx[IP].src, ep1.ip4.address)
2937 self.assertEqual(rx[IP].dst, ep3.ip4.address)
2939 rxs = self.send_and_expect(self.pg2, p4[1] * 17, sep1.itf)
2942 self.assertEqual(rx[Ether].src, routed_src_mac)
2943 self.assertEqual(rx[Ether].dst, sep1.mac)
2944 self.assertEqual(rx[IP].src, ep3.ip4.address)
2945 self.assertEqual(rx[IP].dst, ep1.ip4.address)
2948 # programme the unknown EP for the L3 tests
2950 sep4.add_vpp_config()
2953 # an L3 switch packet between local EPs in different EPGs
2954 # different dest ports on each so the are LB hashed differently
2956 p4 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
2957 IP(src=ep1.ip4.address, dst=ep2.ip4.address) /
2958 UDP(sport=1234, dport=1234) /
2960 (Ether(src=ep2.mac, dst=str(self.router_mac)) /
2961 IP(src=ep2.ip4.address, dst=ep1.ip4.address) /
2962 UDP(sport=1234, dport=1234) /
2964 p6 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
2965 IPv6(src=ep1.ip6.address, dst=ep2.ip6.address) /
2966 UDP(sport=1234, dport=1234) /
2968 (Ether(src=ep2.mac, dst=str(self.router_mac)) /
2969 IPv6(src=ep2.ip6.address, dst=ep1.ip6.address) /
2970 UDP(sport=1234, dport=1234) /
2973 c3 = VppGbpContract(
2974 self, 220, 221, acl_index,
2975 [VppGbpContractRule(
2976 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2977 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
2978 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
2979 sep1.ip4, sep1.epg.rd),
2980 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
2981 sep2.ip4, sep2.epg.rd)]),
2983 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2984 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
2985 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
2986 sep3.ip6, sep3.epg.rd),
2987 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
2988 sep4.ip6, sep4.epg.rd)])],
2989 [ETH_P_IP, ETH_P_IPV6])
2992 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
2995 self.assertEqual(rx[Ether].src, routed_src_mac)
2996 self.assertEqual(rx[Ether].dst, sep1.mac)
2997 self.assertEqual(rx[IP].src, ep1.ip4.address)
2998 self.assertEqual(rx[IP].dst, ep2.ip4.address)
3001 # learn a remote EP in EPG 221
3003 vx_tun_l3 = VppGbpVxlanTunnel(
3004 self, 444, rd1.rd_id,
3005 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
3007 vx_tun_l3.add_vpp_config()
3009 c4 = VppGbpContract(
3010 self, 221, 220, acl_index,
3011 [VppGbpContractRule(
3012 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3015 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3017 [ETH_P_IP, ETH_P_IPV6])
3020 p = (Ether(src=self.pg7.remote_mac,
3021 dst=self.pg7.local_mac) /
3022 IP(src=self.pg7.remote_ip4,
3023 dst=self.pg7.local_ip4) /
3024 UDP(sport=1234, dport=48879) /
3025 VXLAN(vni=444, gpid=441, flags=0x88) /
3026 Ether(src="00:22:22:22:22:33", dst=str(self.router_mac)) /
3027 IP(src="10.0.0.88", dst=ep1.ip4.address) /
3028 UDP(sport=1234, dport=1234) /
3031 rx = self.send_and_expect(self.pg7, [p], self.pg0)
3033 # endpoint learnt via the parent GBP-vxlan interface
3034 self.assertTrue(find_gbp_endpoint(self,
3035 vx_tun_l3._sw_if_index,
3038 p = (Ether(src=self.pg7.remote_mac,
3039 dst=self.pg7.local_mac) /
3040 IP(src=self.pg7.remote_ip4,
3041 dst=self.pg7.local_ip4) /
3042 UDP(sport=1234, dport=48879) /
3043 VXLAN(vni=444, gpid=441, flags=0x88) /
3044 Ether(src="00:22:22:22:22:33", dst=str(self.router_mac)) /
3045 IPv6(src="2001:10::88", dst=ep1.ip6.address) /
3046 UDP(sport=1234, dport=1234) /
3049 rx = self.send_and_expect(self.pg7, [p], self.pg0)
3051 # endpoint learnt via the parent GBP-vxlan interface
3052 self.assertTrue(find_gbp_endpoint(self,
3053 vx_tun_l3._sw_if_index,
3057 # L3 switch from local to remote EP
3059 p4 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3060 IP(src=ep1.ip4.address, dst="10.0.0.88") /
3061 UDP(sport=1234, dport=1234) /
3063 p6 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3064 IPv6(src=ep1.ip6.address, dst="2001:10::88") /
3065 UDP(sport=1234, dport=1234) /
3068 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3071 self.assertEqual(rx[Ether].src, routed_src_mac)
3072 self.assertEqual(rx[Ether].dst, sep1.mac)
3073 self.assertEqual(rx[IP].src, ep1.ip4.address)
3074 self.assertEqual(rx[IP].dst, "10.0.0.88")
3076 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep4.itf)
3079 self.assertEqual(rx[Ether].src, routed_src_mac)
3080 self.assertEqual(rx[Ether].dst, sep4.mac)
3081 self.assertEqual(rx[IPv6].src, ep1.ip6.address)
3082 self.assertEqual(rx[IPv6].dst, "2001:10::88")
3085 # test the dst-ip hash mode
3087 c5 = VppGbpContract(
3088 self, 220, 221, acl_index,
3089 [VppGbpContractRule(
3090 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3091 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
3092 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3093 sep1.ip4, sep1.epg.rd),
3094 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3095 sep2.ip4, sep2.epg.rd)]),
3097 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3098 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
3099 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3100 sep3.ip6, sep3.epg.rd),
3101 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3102 sep4.ip6, sep4.epg.rd)])],
3103 [ETH_P_IP, ETH_P_IPV6])
3106 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3109 self.assertEqual(rx[Ether].src, routed_src_mac)
3110 self.assertEqual(rx[Ether].dst, sep1.mac)
3111 self.assertEqual(rx[IP].src, ep1.ip4.address)
3112 self.assertEqual(rx[IP].dst, "10.0.0.88")
3114 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep3.itf)
3117 self.assertEqual(rx[Ether].src, routed_src_mac)
3118 self.assertEqual(rx[Ether].dst, sep3.mac)
3119 self.assertEqual(rx[IPv6].src, ep1.ip6.address)
3120 self.assertEqual(rx[IPv6].dst, "2001:10::88")
3125 self.pg7.unconfig_ip4()
3127 def test_gbp_l3_out(self):
3130 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
3131 self.vapi.cli("set logging class gbp debug")
3133 routed_dst_mac = "00:0c:0c:0c:0c:0c"
3134 routed_src_mac = "00:22:bd:f8:19:ff"
3139 t4 = VppIpTable(self, 1)
3141 t6 = VppIpTable(self, 1, True)
3144 rd1 = VppGbpRouteDomain(self, 2, t4, t6)
3145 rd1.add_vpp_config()
3147 self.loop0.set_mac(self.router_mac)
3150 # Bind the BVI to the RD
3152 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
3153 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
3156 # Pg7 hosts a BD's BUM
3157 # Pg1 some other l3 interface
3159 self.pg7.config_ip4()
3160 self.pg7.resolve_arp()
3163 # a multicast vxlan-gbp tunnel for broadcast in the BD
3165 tun_bm = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
3168 tun_bm.add_vpp_config()
3171 # a GBP external bridge domains for the EPs
3173 bd1 = VppBridgeDomain(self, 1)
3174 bd1.add_vpp_config()
3175 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0, None, tun_bm)
3176 gbd1.add_vpp_config()
3179 # The Endpoint-groups in which the external endpoints exist
3181 epg_220 = VppGbpEndpointGroup(self, 220, 113, rd1, gbd1,
3185 VppGbpEndpointRetention(2))
3186 epg_220.add_vpp_config()
3188 # the BVIs have the subnets applied ...
3189 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 24)
3190 ip4_addr.add_vpp_config()
3191 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 64)
3192 ip6_addr.add_vpp_config()
3194 # ... which are L3-out subnets
3195 l3o_1 = VppGbpSubnet(
3196 self, rd1, "10.0.0.0", 24,
3197 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3199 l3o_1.add_vpp_config()
3202 # an external interface attached to the outside world and the
3205 vlan_100 = VppDot1QSubint(self, self.pg0, 100)
3207 ext_itf = VppGbpExtItf(self, vlan_100, bd1, rd1)
3208 ext_itf.add_vpp_config()
3211 # an unicast vxlan-gbp for inter-RD traffic
3213 vx_tun_l3 = VppGbpVxlanTunnel(
3214 self, 444, rd1.rd_id,
3215 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
3217 vx_tun_l3.add_vpp_config()
3220 # packets destined to unkown addresses in the BVI's subnet
3223 p4 = (Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
3225 IP(src="10.0.0.1", dst="10.0.0.88") /
3226 UDP(sport=1234, dport=1234) /
3228 p6 = (Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
3230 IPv6(src="2001:10::1", dst="2001:10::88") /
3231 UDP(sport=1234, dport=1234) /
3234 rxs = self.send_and_expect(self.pg0, p4 * 1, self.pg7)
3237 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3238 # self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3239 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3240 self.assertEqual(rx[IP].dst, "239.1.1.1")
3241 self.assertEqual(rx[VXLAN].vni, 88)
3242 self.assertTrue(rx[VXLAN].flags.G)
3243 self.assertTrue(rx[VXLAN].flags.Instance)
3244 # policy was applied to the original IP packet
3245 self.assertEqual(rx[VXLAN].gpid, 113)
3246 self.assertTrue(rx[VXLAN].gpflags.A)
3247 self.assertFalse(rx[VXLAN].gpflags.D)
3249 inner = rx[VXLAN].payload
3251 self.assertTrue(inner.haslayer(ARP))
3254 # An external Endpoint
3256 eep = VppGbpEndpoint(self, vlan_100,
3258 "10.0.0.1", "11.0.0.1",
3259 "2001:10::1", "3001::1",
3260 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
3261 eep.add_vpp_config()
3266 rep = VppGbpEndpoint(self, vx_tun_l3,
3268 "10.0.0.101", "11.0.0.101",
3269 "2001:10::101", "3001::101",
3270 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
3272 self.pg7.remote_ip4,
3274 rep.add_vpp_config()
3277 # remote to external
3279 p = (Ether(src=self.pg7.remote_mac,
3280 dst=self.pg7.local_mac) /
3281 IP(src=self.pg7.remote_ip4,
3282 dst=self.pg7.local_ip4) /
3283 UDP(sport=1234, dport=48879) /
3284 VXLAN(vni=444, gpid=113, flags=0x88) /
3285 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
3286 IP(src="10.0.0.101", dst="10.0.0.1") /
3287 UDP(sport=1234, dport=1234) /
3290 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
3293 # A subnet reachable through the external EP
3295 ip_220 = VppIpRoute(self, "10.220.0.0", 24,
3296 [VppRoutePath(eep.ip4.address,
3297 eep.epg.bvi.sw_if_index)],
3298 table_id=t4.table_id)
3299 ip_220.add_vpp_config()
3301 l3o_220 = VppGbpSubnet(
3302 self, rd1, "10.220.0.0", 24,
3303 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3305 l3o_220.add_vpp_config()
3307 p = (Ether(src=self.pg7.remote_mac,
3308 dst=self.pg7.local_mac) /
3309 IP(src=self.pg7.remote_ip4,
3310 dst=self.pg7.local_ip4) /
3311 UDP(sport=1234, dport=48879) /
3312 VXLAN(vni=444, gpid=113, flags=0x88) /
3313 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
3314 IP(src="10.0.0.101", dst="10.220.0.1") /
3315 UDP(sport=1234, dport=1234) /
3318 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
3323 self.pg7.unconfig_ip4()
3326 if __name__ == '__main__':
3327 unittest.main(testRunner=VppTestRunner)