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 sclass=self.epg.sclass 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, vnid, 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.sclass)
321 return self.object_id()
324 return "gbp-endpoint-group:[%d]" % (self.vnid)
326 def query_vpp_config(self):
327 epgs = self._test.vapi.gbp_endpoint_group_dump()
329 if epg.epg.vnid == self.vnid:
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
464 while (len(self.allowed_ethertypes) < 16):
465 self.allowed_ethertypes.append(0)
467 def add_vpp_config(self):
470 rules.append(r.encode())
471 self._test.vapi.gbp_contract_add_del(
477 self.allowed_ethertypes)
478 self._test.registry.register(self, self._test.logger)
480 def remove_vpp_config(self):
481 self._test.vapi.gbp_contract_add_del(
487 self.allowed_ethertypes)
490 return self.object_id()
493 return "gbp-contract:[%d:%s:%d]" % (self.src_epg.sclass,
497 def query_vpp_config(self):
498 cs = self._test.vapi.gbp_contract_dump()
500 if c.contract.sclass == self.src_epg.sclass \
501 and c.contract.dclass == self.dst_epg.sclass:
506 class VppGbpVxlanTunnel(VppInterface):
511 def __init__(self, test, vni, bd_rd_id, mode, src):
512 super(VppGbpVxlanTunnel, self).__init__(test)
515 self.bd_rd_id = bd_rd_id
519 def add_vpp_config(self):
520 r = self._test.vapi.gbp_vxlan_tunnel_add(
525 self.set_sw_if_index(r.sw_if_index)
526 self._test.registry.register(self, self._test.logger)
528 def remove_vpp_config(self):
529 self._test.vapi.gbp_vxlan_tunnel_del(self.vni)
532 return self.object_id()
535 return "gbp-vxlan:%d" % (self.sw_if_index)
537 def query_vpp_config(self):
538 return find_gbp_vxlan(self._test, self.vni)
541 class VppGbpAcl(VppObject):
546 def __init__(self, test):
548 self.acl_index = 4294967295
550 def create_rule(self, is_ipv6=0, permit_deny=0, proto=-1,
551 s_prefix=0, s_ip=b'\x00\x00\x00\x00', sport_from=0,
552 sport_to=65535, d_prefix=0, d_ip=b'\x00\x00\x00\x00',
553 dport_from=0, dport_to=65535):
554 if proto == -1 or proto == 0:
557 elif proto == 1 or proto == 58:
560 rule = ({'is_permit': permit_deny, 'is_ipv6': is_ipv6, 'proto': proto,
561 'srcport_or_icmptype_first': sport_from,
562 'srcport_or_icmptype_last': sport_to,
563 'src_ip_prefix_len': s_prefix,
565 'dstport_or_icmpcode_first': dport_from,
566 'dstport_or_icmpcode_last': dport_to,
567 'dst_ip_prefix_len': d_prefix,
568 'dst_ip_addr': d_ip})
571 def add_vpp_config(self, rules):
573 reply = self._test.vapi.acl_add_replace(self.acl_index,
576 self.acl_index = reply.acl_index
577 return self.acl_index
579 def remove_vpp_config(self):
580 self._test.vapi.acl_del(self.acl_index)
583 return self.object_id()
586 return "gbp-acl:[%d]" % (self.acl_index)
588 def query_vpp_config(self):
589 cs = self._test.vapi.acl_dump()
591 if c.acl_index == self.acl_index:
596 class TestGBP(VppTestCase):
597 """ GBP Test Case """
600 super(TestGBP, self).setUp()
602 self.create_pg_interfaces(range(9))
603 self.create_loopback_interfaces(8)
605 self.router_mac = MACAddress("00:11:22:33:44:55")
607 for i in self.pg_interfaces:
609 for i in self.lo_interfaces:
613 for i in self.pg_interfaces:
616 super(TestGBP, self).tearDown()
618 def send_and_expect_bridged(self, src, tx, dst):
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, tx[0][IP].src)
625 self.assertEqual(r[IP].dst, tx[0][IP].dst)
628 def send_and_expect_bridged6(self, src, tx, dst):
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, tx[0][IPv6].src)
635 self.assertEqual(r[IPv6].dst, tx[0][IPv6].dst)
638 def send_and_expect_routed(self, src, tx, dst, src_mac):
639 rx = self.send_and_expect(src, tx, dst)
642 self.assertEqual(r[Ether].src, src_mac)
643 self.assertEqual(r[Ether].dst, dst.remote_mac)
644 self.assertEqual(r[IP].src, tx[0][IP].src)
645 self.assertEqual(r[IP].dst, tx[0][IP].dst)
648 def send_and_expect_natted(self, src, tx, dst, src_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[IP].src, src_ip)
655 self.assertEqual(r[IP].dst, tx[0][IP].dst)
658 def send_and_expect_natted6(self, src, tx, dst, src_ip):
659 rx = self.send_and_expect(src, tx, dst)
662 self.assertEqual(r[Ether].src, tx[0][Ether].src)
663 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
664 self.assertEqual(r[IPv6].src, src_ip)
665 self.assertEqual(r[IPv6].dst, tx[0][IPv6].dst)
668 def send_and_expect_unnatted(self, src, tx, dst, dst_ip):
669 rx = self.send_and_expect(src, tx, dst)
672 self.assertEqual(r[Ether].src, tx[0][Ether].src)
673 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
674 self.assertEqual(r[IP].dst, dst_ip)
675 self.assertEqual(r[IP].src, tx[0][IP].src)
678 def send_and_expect_unnatted6(self, src, tx, dst, dst_ip):
679 rx = self.send_and_expect(src, tx, dst)
682 self.assertEqual(r[Ether].src, tx[0][Ether].src)
683 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
684 self.assertEqual(r[IPv6].dst, dst_ip)
685 self.assertEqual(r[IPv6].src, tx[0][IPv6].src)
688 def send_and_expect_double_natted(self, src, tx, dst, src_ip, dst_ip):
689 rx = self.send_and_expect(src, tx, dst)
692 self.assertEqual(r[Ether].src, str(self.router_mac))
693 self.assertEqual(r[Ether].dst, dst.remote_mac)
694 self.assertEqual(r[IP].dst, dst_ip)
695 self.assertEqual(r[IP].src, src_ip)
698 def send_and_expect_double_natted6(self, src, tx, dst, src_ip, dst_ip):
699 rx = self.send_and_expect(src, tx, dst)
702 self.assertEqual(r[Ether].src, str(self.router_mac))
703 self.assertEqual(r[Ether].dst, dst.remote_mac)
704 self.assertEqual(r[IPv6].dst, dst_ip)
705 self.assertEqual(r[IPv6].src, src_ip)
709 """ Group Based Policy """
711 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
716 bd1 = VppBridgeDomain(self, 1)
717 bd2 = VppBridgeDomain(self, 2)
718 bd20 = VppBridgeDomain(self, 20)
722 bd20.add_vpp_config()
724 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0)
725 gbd2 = VppGbpBridgeDomain(self, bd2, self.loop1)
726 gbd20 = VppGbpBridgeDomain(self, bd20, self.loop2)
728 gbd1.add_vpp_config()
729 gbd2.add_vpp_config()
730 gbd20.add_vpp_config()
735 gt4 = VppIpTable(self, 0)
737 gt6 = VppIpTable(self, 0, is_ip6=True)
739 nt4 = VppIpTable(self, 20)
741 nt6 = VppIpTable(self, 20, is_ip6=True)
744 rd0 = VppGbpRouteDomain(self, 0, gt4, gt6, None, None)
745 rd20 = VppGbpRouteDomain(self, 20, nt4, nt6, None, None)
748 rd20.add_vpp_config()
751 # 3 EPGs, 2 of which share a BD.
752 # 2 NAT EPGs, one for floating-IP subnets, the other for internet
754 epgs = [VppGbpEndpointGroup(self, 220, 1220, rd0, gbd1,
755 self.pg4, self.loop0,
756 "10.0.0.128", "2001:10::128"),
757 VppGbpEndpointGroup(self, 221, 1221, rd0, gbd1,
758 self.pg5, self.loop0,
759 "10.0.1.128", "2001:10:1::128"),
760 VppGbpEndpointGroup(self, 222, 1222, rd0, gbd2,
761 self.pg6, self.loop1,
762 "10.0.2.128", "2001:10:2::128"),
763 VppGbpEndpointGroup(self, 333, 1333, rd20, gbd20,
764 self.pg7, self.loop2,
765 "11.0.0.128", "3001::128"),
766 VppGbpEndpointGroup(self, 444, 1444, rd20, gbd20,
767 self.pg8, self.loop2,
768 "11.0.0.129", "3001::129")]
769 recircs = [VppGbpRecirc(self, epgs[0], self.loop3),
770 VppGbpRecirc(self, epgs[1], self.loop4),
771 VppGbpRecirc(self, epgs[2], self.loop5),
772 VppGbpRecirc(self, epgs[3], self.loop6, is_ext=True),
773 VppGbpRecirc(self, epgs[4], self.loop7, is_ext=True)]
776 recirc_nat = recircs[3]
779 # 4 end-points, 2 in the same subnet, 3 in the same BD
781 eps = [VppGbpEndpoint(self, self.pg0,
783 "10.0.0.1", "11.0.0.1",
784 "2001:10::1", "3001::1"),
785 VppGbpEndpoint(self, self.pg1,
787 "10.0.0.2", "11.0.0.2",
788 "2001:10::2", "3001::2"),
789 VppGbpEndpoint(self, self.pg2,
791 "10.0.1.1", "11.0.0.3",
792 "2001:10:1::1", "3001::3"),
793 VppGbpEndpoint(self, self.pg3,
795 "10.0.2.1", "11.0.0.4",
796 "2001:10:2::1", "3001::4")]
799 # Config related to each of the EPGs
802 # IP config on the BVI interfaces
803 if epg != epgs[1] and epg != epgs[4]:
804 VppIpInterfaceBind(self, epg.bvi, epg.rd.t4).add_vpp_config()
805 VppIpInterfaceBind(self, epg.bvi, epg.rd.t6).add_vpp_config()
806 self.vapi.sw_interface_set_mac_address(
808 self.router_mac.packed)
810 # The BVIs are NAT inside interfaces
811 self.vapi.nat44_interface_add_del_feature(epg.bvi.sw_if_index,
814 self.vapi.nat66_add_del_interface(epg.bvi.sw_if_index,
818 if_ip4 = VppIpInterfaceAddress(self, epg.bvi, epg.bvi_ip4, 32)
819 if_ip6 = VppIpInterfaceAddress(self, epg.bvi, epg.bvi_ip6, 128)
820 if_ip4.add_vpp_config()
821 if_ip6.add_vpp_config()
823 # EPG uplink interfaces in the RD
824 VppIpInterfaceBind(self, epg.uplink, epg.rd.t4).add_vpp_config()
825 VppIpInterfaceBind(self, epg.uplink, epg.rd.t6).add_vpp_config()
827 # add the BD ARP termination entry for BVI IP
828 epg.bd_arp_ip4 = VppBridgeDomainArpEntry(self, epg.bd.bd,
829 str(self.router_mac),
831 epg.bd_arp_ip6 = VppBridgeDomainArpEntry(self, epg.bd.bd,
832 str(self.router_mac),
834 epg.bd_arp_ip4.add_vpp_config()
835 epg.bd_arp_ip6.add_vpp_config()
840 for recirc in recircs:
841 # EPG's ingress recirculation interface maps to its RD
842 VppIpInterfaceBind(self, recirc.recirc,
843 recirc.epg.rd.t4).add_vpp_config()
844 VppIpInterfaceBind(self, recirc.recirc,
845 recirc.epg.rd.t6).add_vpp_config()
847 self.vapi.nat44_interface_add_del_feature(
848 recirc.recirc.sw_if_index,
851 self.vapi.nat66_add_del_interface(
852 recirc.recirc.sw_if_index,
856 recirc.add_vpp_config()
858 for recirc in recircs:
859 self.assertTrue(find_bridge_domain_port(self,
860 recirc.epg.bd.bd.bd_id,
861 recirc.recirc.sw_if_index))
864 self.pg_enable_capture(self.pg_interfaces)
867 # routes to the endpoints. We need these since there are no
868 # adj-fibs due to the fact the the BVI address has /32 and
869 # the subnet is not attached.
871 for (ip, fip) in zip(ep.ips, ep.fips):
872 # Add static mappings for each EP from the 10/8 to 11/8 network
874 self.vapi.nat44_add_del_static_mapping(ip.bytes,
879 self.vapi.nat66_add_del_static_mapping(ip.bytes,
886 self.logger.info(self.vapi.cli("sh gbp endpoint"))
888 # ... results in a Gratuitous ARP/ND on the EPG's uplink
889 rx = ep.epg.uplink.get_capture(len(ep.ips), timeout=0.2)
891 for ii, ip in enumerate(ep.ips):
895 self.assertTrue(p.haslayer(ICMPv6ND_NA))
896 self.assertEqual(p[ICMPv6ND_NA].tgt, ip.address)
898 self.assertTrue(p.haslayer(ARP))
899 self.assertEqual(p[ARP].psrc, ip.address)
900 self.assertEqual(p[ARP].pdst, ip.address)
902 # add the BD ARP termination entry for floating IP
904 ba = VppBridgeDomainArpEntry(self, epg_nat.bd.bd, ep.mac, fip)
907 # floating IPs route via EPG recirc
908 r = VppIpRoute(self, fip.address, fip.length,
909 [VppRoutePath(fip.address,
910 ep.recirc.recirc.sw_if_index,
912 proto=fip.dpo_proto)],
917 # L2 FIB entries in the NAT EPG BD to bridge the packets from
918 # the outside direct to the internal EPG
919 lf = VppL2FibEntry(self, epg_nat.bd.bd, ep.mac,
920 ep.recirc.recirc, bvi_mac=0)
924 # ARP packets for unknown IP are sent to the EPG uplink
926 pkt_arp = (Ether(dst="ff:ff:ff:ff:ff:ff",
927 src=self.pg0.remote_mac) /
929 hwdst="ff:ff:ff:ff:ff:ff",
930 hwsrc=self.pg0.remote_mac,
934 self.vapi.cli("clear trace")
935 self.pg0.add_stream(pkt_arp)
937 self.pg_enable_capture(self.pg_interfaces)
940 rxd = epgs[0].uplink.get_capture(1)
943 # ARP/ND packets get a response
945 pkt_arp = (Ether(dst="ff:ff:ff:ff:ff:ff",
946 src=self.pg0.remote_mac) /
948 hwdst="ff:ff:ff:ff:ff:ff",
949 hwsrc=self.pg0.remote_mac,
950 pdst=epgs[0].bvi_ip4.address,
951 psrc=eps[0].ip4.address))
953 self.send_and_expect(self.pg0, [pkt_arp], self.pg0)
955 nsma = in6_getnsma(inet_pton(AF_INET6, eps[0].ip6.address))
956 d = inet_ntop(AF_INET6, nsma)
957 pkt_nd = (Ether(dst=in6_getnsmac(nsma),
958 src=self.pg0.remote_mac) /
959 IPv6(dst=d, src=eps[0].ip6.address) /
960 ICMPv6ND_NS(tgt=epgs[0].bvi_ip6.address) /
961 ICMPv6NDOptSrcLLAddr(lladdr=self.pg0.remote_mac))
962 self.send_and_expect(self.pg0, [pkt_nd], self.pg0)
965 # broadcast packets are flooded
967 pkt_bcast = (Ether(dst="ff:ff:ff:ff:ff:ff",
968 src=self.pg0.remote_mac) /
969 IP(src=eps[0].ip4.address, dst="232.1.1.1") /
970 UDP(sport=1234, dport=1234) /
973 self.vapi.cli("clear trace")
974 self.pg0.add_stream(pkt_bcast)
976 self.pg_enable_capture(self.pg_interfaces)
979 rxd = eps[1].itf.get_capture(1)
980 self.assertEqual(rxd[0][Ether].dst, pkt_bcast[Ether].dst)
981 rxd = epgs[0].uplink.get_capture(1)
982 self.assertEqual(rxd[0][Ether].dst, pkt_bcast[Ether].dst)
985 # packets to non-local L3 destinations dropped
987 pkt_intra_epg_220_ip4 = (Ether(src=self.pg0.remote_mac,
988 dst=str(self.router_mac)) /
989 IP(src=eps[0].ip4.address,
991 UDP(sport=1234, dport=1234) /
993 pkt_inter_epg_222_ip4 = (Ether(src=self.pg0.remote_mac,
994 dst=str(self.router_mac)) /
995 IP(src=eps[0].ip4.address,
997 UDP(sport=1234, dport=1234) /
1000 self.send_and_assert_no_replies(self.pg0, pkt_intra_epg_220_ip4 * 65)
1002 pkt_inter_epg_222_ip6 = (Ether(src=self.pg0.remote_mac,
1003 dst=str(self.router_mac)) /
1004 IPv6(src=eps[0].ip6.address,
1005 dst="2001:10::99") /
1006 UDP(sport=1234, dport=1234) /
1008 self.send_and_assert_no_replies(self.pg0, pkt_inter_epg_222_ip6 * 65)
1011 # Add the subnet routes
1014 self, rd0, "10.0.0.0", 24,
1015 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1017 self, rd0, "10.0.1.0", 24,
1018 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1020 self, rd0, "10.0.2.0", 24,
1021 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1023 self, rd0, "2001:10::1", 64,
1024 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1026 self, rd0, "2001:10:1::1", 64,
1027 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1029 self, rd0, "2001:10:2::1", 64,
1030 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1031 s41.add_vpp_config()
1032 s42.add_vpp_config()
1033 s43.add_vpp_config()
1034 s61.add_vpp_config()
1035 s62.add_vpp_config()
1036 s63.add_vpp_config()
1038 self.send_and_expect_bridged(eps[0].itf,
1039 pkt_intra_epg_220_ip4 * 65,
1041 self.send_and_expect_bridged(eps[0].itf,
1042 pkt_inter_epg_222_ip4 * 65,
1044 self.send_and_expect_bridged6(eps[0].itf,
1045 pkt_inter_epg_222_ip6 * 65,
1048 self.logger.info(self.vapi.cli("sh ip fib 11.0.0.2"))
1049 self.logger.info(self.vapi.cli("sh gbp endpoint-group"))
1050 self.logger.info(self.vapi.cli("sh gbp endpoint"))
1051 self.logger.info(self.vapi.cli("sh gbp recirc"))
1052 self.logger.info(self.vapi.cli("sh int"))
1053 self.logger.info(self.vapi.cli("sh int addr"))
1054 self.logger.info(self.vapi.cli("sh int feat loop6"))
1055 self.logger.info(self.vapi.cli("sh vlib graph ip4-gbp-src-classify"))
1056 self.logger.info(self.vapi.cli("sh int feat loop3"))
1057 self.logger.info(self.vapi.cli("sh int feat pg0"))
1060 # Packet destined to unknown unicast is sent on the epg uplink ...
1062 pkt_intra_epg_220_to_uplink = (Ether(src=self.pg0.remote_mac,
1063 dst="00:00:00:33:44:55") /
1064 IP(src=eps[0].ip4.address,
1066 UDP(sport=1234, dport=1234) /
1069 self.send_and_expect_bridged(eps[0].itf,
1070 pkt_intra_epg_220_to_uplink * 65,
1072 # ... and nowhere else
1073 self.pg1.get_capture(0, timeout=0.1)
1074 self.pg1.assert_nothing_captured(remark="Flood onto other VMS")
1076 pkt_intra_epg_221_to_uplink = (Ether(src=self.pg2.remote_mac,
1077 dst="00:00:00:33:44:66") /
1078 IP(src=eps[0].ip4.address,
1080 UDP(sport=1234, dport=1234) /
1083 self.send_and_expect_bridged(eps[2].itf,
1084 pkt_intra_epg_221_to_uplink * 65,
1088 # Packets from the uplink are forwarded in the absence of a contract
1090 pkt_intra_epg_220_from_uplink = (Ether(src="00:00:00:33:44:55",
1091 dst=self.pg0.remote_mac) /
1092 IP(src=eps[0].ip4.address,
1094 UDP(sport=1234, dport=1234) /
1097 self.send_and_expect_bridged(self.pg4,
1098 pkt_intra_epg_220_from_uplink * 65,
1102 # in the absence of policy, endpoints in the same EPG
1105 pkt_intra_epg = (Ether(src=self.pg0.remote_mac,
1106 dst=self.pg1.remote_mac) /
1107 IP(src=eps[0].ip4.address,
1108 dst=eps[1].ip4.address) /
1109 UDP(sport=1234, dport=1234) /
1112 self.send_and_expect_bridged(self.pg0, pkt_intra_epg * 65, self.pg1)
1115 # in the abscense of policy, endpoints in the different EPG
1116 # cannot communicate
1118 pkt_inter_epg_220_to_221 = (Ether(src=self.pg0.remote_mac,
1119 dst=self.pg2.remote_mac) /
1120 IP(src=eps[0].ip4.address,
1121 dst=eps[2].ip4.address) /
1122 UDP(sport=1234, dport=1234) /
1124 pkt_inter_epg_221_to_220 = (Ether(src=self.pg2.remote_mac,
1125 dst=self.pg0.remote_mac) /
1126 IP(src=eps[2].ip4.address,
1127 dst=eps[0].ip4.address) /
1128 UDP(sport=1234, dport=1234) /
1130 pkt_inter_epg_220_to_222 = (Ether(src=self.pg0.remote_mac,
1131 dst=str(self.router_mac)) /
1132 IP(src=eps[0].ip4.address,
1133 dst=eps[3].ip4.address) /
1134 UDP(sport=1234, dport=1234) /
1137 self.send_and_assert_no_replies(eps[0].itf,
1138 pkt_inter_epg_220_to_221 * 65)
1139 self.send_and_assert_no_replies(eps[0].itf,
1140 pkt_inter_epg_220_to_222 * 65)
1143 # A uni-directional contract from EPG 220 -> 221
1145 acl = VppGbpAcl(self)
1146 rule = acl.create_rule(permit_deny=1, proto=17)
1147 rule2 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
1148 acl_index = acl.add_vpp_config([rule, rule2])
1149 c1 = VppGbpContract(
1150 self, epgs[0], epgs[1], acl_index,
1151 [VppGbpContractRule(
1152 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1155 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1157 [ETH_P_IP, ETH_P_IPV6])
1160 self.send_and_expect_bridged(eps[0].itf,
1161 pkt_inter_epg_220_to_221 * 65,
1163 self.send_and_assert_no_replies(eps[0].itf,
1164 pkt_inter_epg_220_to_222 * 65)
1167 # contract for the return direction
1169 c2 = VppGbpContract(
1170 self, epgs[1], epgs[0], acl_index,
1171 [VppGbpContractRule(
1172 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1175 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1177 [ETH_P_IP, ETH_P_IPV6])
1180 self.send_and_expect_bridged(eps[0].itf,
1181 pkt_inter_epg_220_to_221 * 65,
1183 self.send_and_expect_bridged(eps[2].itf,
1184 pkt_inter_epg_221_to_220 * 65,
1188 # the contract does not allow non-IP
1190 pkt_non_ip_inter_epg_220_to_221 = (Ether(src=self.pg0.remote_mac,
1191 dst=self.pg2.remote_mac) /
1193 self.send_and_assert_no_replies(eps[0].itf,
1194 pkt_non_ip_inter_epg_220_to_221 * 17)
1197 # check that inter group is still disabled for the groups
1198 # not in the contract.
1200 self.send_and_assert_no_replies(eps[0].itf,
1201 pkt_inter_epg_220_to_222 * 65)
1204 # A uni-directional contract from EPG 220 -> 222 'L3 routed'
1206 c3 = VppGbpContract(
1207 self, epgs[0], epgs[2], acl_index,
1208 [VppGbpContractRule(
1209 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1212 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1214 [ETH_P_IP, ETH_P_IPV6])
1217 self.logger.info(self.vapi.cli("sh gbp contract"))
1219 self.send_and_expect_routed(eps[0].itf,
1220 pkt_inter_epg_220_to_222 * 65,
1222 str(self.router_mac))
1225 # remove both contracts, traffic stops in both directions
1227 c2.remove_vpp_config()
1228 c1.remove_vpp_config()
1229 c3.remove_vpp_config()
1230 acl.remove_vpp_config()
1232 self.send_and_assert_no_replies(eps[2].itf,
1233 pkt_inter_epg_221_to_220 * 65)
1234 self.send_and_assert_no_replies(eps[0].itf,
1235 pkt_inter_epg_220_to_221 * 65)
1236 self.send_and_expect_bridged(eps[0].itf,
1241 # EPs to the outside world
1244 # in the EP's RD an external subnet via the NAT EPG's recirc
1246 self, rd0, "0.0.0.0", 0,
1247 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1248 sw_if_index=recirc_nat.recirc.sw_if_index,
1251 self, rd0, "11.0.0.0", 8,
1252 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1253 sw_if_index=recirc_nat.recirc.sw_if_index,
1255 se16 = VppGbpSubnet(
1257 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1258 sw_if_index=recirc_nat.recirc.sw_if_index,
1260 # in the NAT RD an external subnet via the NAT EPG's uplink
1262 self, rd20, "0.0.0.0", 0,
1263 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1264 sw_if_index=epg_nat.uplink.sw_if_index,
1266 se36 = VppGbpSubnet(
1267 self, rd20, "::", 0,
1268 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1269 sw_if_index=epg_nat.uplink.sw_if_index,
1272 self, rd20, "11.0.0.0", 8,
1273 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1274 sw_if_index=epg_nat.uplink.sw_if_index,
1276 se1.add_vpp_config()
1277 se2.add_vpp_config()
1278 se16.add_vpp_config()
1279 se3.add_vpp_config()
1280 se36.add_vpp_config()
1281 se4.add_vpp_config()
1283 self.logger.info(self.vapi.cli("sh ip fib 0.0.0.0/0"))
1284 self.logger.info(self.vapi.cli("sh ip fib 11.0.0.1"))
1285 self.logger.info(self.vapi.cli("sh ip6 fib ::/0"))
1286 self.logger.info(self.vapi.cli("sh ip6 fib %s" %
1290 # From an EP to an outside addess: IN2OUT
1292 pkt_inter_epg_220_to_global = (Ether(src=self.pg0.remote_mac,
1293 dst=str(self.router_mac)) /
1294 IP(src=eps[0].ip4.address,
1296 UDP(sport=1234, dport=1234) /
1300 self.send_and_assert_no_replies(eps[0].itf,
1301 pkt_inter_epg_220_to_global * 65)
1303 acl2 = VppGbpAcl(self)
1304 rule = acl2.create_rule(permit_deny=1, proto=17, sport_from=1234,
1305 sport_to=1234, dport_from=1234, dport_to=1234)
1306 rule2 = acl2.create_rule(is_ipv6=1, permit_deny=1, proto=17,
1307 sport_from=1234, sport_to=1234,
1308 dport_from=1234, dport_to=1234)
1310 acl_index2 = acl2.add_vpp_config([rule, rule2])
1311 c4 = VppGbpContract(
1312 self, epgs[0], epgs[3], acl_index2,
1313 [VppGbpContractRule(
1314 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1317 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1319 [ETH_P_IP, ETH_P_IPV6])
1322 self.send_and_expect_natted(eps[0].itf,
1323 pkt_inter_epg_220_to_global * 65,
1325 eps[0].fip4.address)
1327 pkt_inter_epg_220_to_global = (Ether(src=self.pg0.remote_mac,
1328 dst=str(self.router_mac)) /
1329 IPv6(src=eps[0].ip6.address,
1331 UDP(sport=1234, dport=1234) /
1334 self.send_and_expect_natted6(self.pg0,
1335 pkt_inter_epg_220_to_global * 65,
1337 eps[0].fip6.address)
1340 # From a global address to an EP: OUT2IN
1342 pkt_inter_epg_220_from_global = (Ether(src=str(self.router_mac),
1343 dst=self.pg0.remote_mac) /
1344 IP(dst=eps[0].fip4.address,
1346 UDP(sport=1234, dport=1234) /
1349 self.send_and_assert_no_replies(self.pg7,
1350 pkt_inter_epg_220_from_global * 65)
1352 c5 = VppGbpContract(
1353 self, epgs[3], epgs[0], acl_index2,
1354 [VppGbpContractRule(
1355 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1358 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1360 [ETH_P_IP, ETH_P_IPV6])
1363 self.send_and_expect_unnatted(self.pg7,
1364 pkt_inter_epg_220_from_global * 65,
1368 pkt_inter_epg_220_from_global = (Ether(src=str(self.router_mac),
1369 dst=self.pg0.remote_mac) /
1370 IPv6(dst=eps[0].fip6.address,
1372 UDP(sport=1234, dport=1234) /
1375 self.send_and_expect_unnatted6(self.pg7,
1376 pkt_inter_epg_220_from_global * 65,
1381 # From a local VM to another local VM using resp. public addresses:
1384 pkt_intra_epg_220_global = (Ether(src=self.pg0.remote_mac,
1385 dst=str(self.router_mac)) /
1386 IP(src=eps[0].ip4.address,
1387 dst=eps[1].fip4.address) /
1388 UDP(sport=1234, dport=1234) /
1391 self.send_and_expect_double_natted(eps[0].itf,
1392 pkt_intra_epg_220_global * 65,
1394 eps[0].fip4.address,
1397 pkt_intra_epg_220_global = (Ether(src=self.pg0.remote_mac,
1398 dst=str(self.router_mac)) /
1399 IPv6(src=eps[0].ip6.address,
1400 dst=eps[1].fip6.address) /
1401 UDP(sport=1234, dport=1234) /
1404 self.send_and_expect_double_natted6(eps[0].itf,
1405 pkt_intra_epg_220_global * 65,
1407 eps[0].fip6.address,
1414 # del static mappings for each EP from the 10/8 to 11/8 network
1415 self.vapi.nat44_add_del_static_mapping(ep.ip4.bytes,
1420 self.vapi.nat66_add_del_static_mapping(ep.ip6.bytes,
1426 # IP config on the BVI interfaces
1427 if epg != epgs[0] and epg != epgs[3]:
1428 self.vapi.nat44_interface_add_del_feature(epg.bvi.sw_if_index,
1431 self.vapi.nat66_add_del_interface(epg.bvi.sw_if_index,
1435 for recirc in recircs:
1436 self.vapi.nat44_interface_add_del_feature(
1437 recirc.recirc.sw_if_index,
1440 self.vapi.nat66_add_del_interface(
1441 recirc.recirc.sw_if_index,
1445 def wait_for_ep_timeout(self, sw_if_index=None, ip=None, mac=None,
1446 n_tries=100, s_time=1):
1448 if not find_gbp_endpoint(self, sw_if_index, ip, mac):
1450 n_tries = n_tries - 1
1452 self.assertFalse(find_gbp_endpoint(self, sw_if_index, ip, mac))
1455 def test_gbp_learn_l2(self):
1456 """ GBP L2 Endpoint Learning """
1458 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
1459 learnt = [{'mac': '00:00:11:11:11:01',
1461 'ip6': '2001:10::2'},
1462 {'mac': '00:00:11:11:11:02',
1464 'ip6': '2001:10::3'}]
1469 gt4 = VppIpTable(self, 1)
1470 gt4.add_vpp_config()
1471 gt6 = VppIpTable(self, 1, is_ip6=True)
1472 gt6.add_vpp_config()
1474 rd1 = VppGbpRouteDomain(self, 1, gt4, gt6)
1475 rd1.add_vpp_config()
1478 # Pg2 hosts the vxlan tunnel, hosts on pg2 to act as TEPs
1479 # Pg3 hosts the IP4 UU-flood VXLAN tunnel
1480 # Pg4 hosts the IP6 UU-flood VXLAN tunnel
1482 self.pg2.config_ip4()
1483 self.pg2.resolve_arp()
1484 self.pg2.generate_remote_hosts(4)
1485 self.pg2.configure_ipv4_neighbors()
1486 self.pg3.config_ip4()
1487 self.pg3.resolve_arp()
1488 self.pg4.config_ip4()
1489 self.pg4.resolve_arp()
1492 # Add a mcast destination VXLAN-GBP tunnel for B&M traffic
1494 tun_bm = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
1497 tun_bm.add_vpp_config()
1500 # a GBP bridge domain with a BVI and a UU-flood interface
1502 bd1 = VppBridgeDomain(self, 1)
1503 bd1.add_vpp_config()
1504 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0, self.pg3, tun_bm)
1505 gbd1.add_vpp_config()
1507 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1508 self.logger.info(self.vapi.cli("sh gbp bridge"))
1510 # ... and has a /32 applied
1511 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
1512 ip_addr.add_vpp_config()
1515 # The Endpoint-group in which we are learning endpoints
1517 epg_220 = VppGbpEndpointGroup(self, 220, 112, rd1, gbd1,
1521 VppGbpEndpointRetention(2))
1522 epg_220.add_vpp_config()
1523 epg_330 = VppGbpEndpointGroup(self, 330, 113, rd1, gbd1,
1527 VppGbpEndpointRetention(2))
1528 epg_330.add_vpp_config()
1531 # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
1534 vx_tun_l2_1 = VppGbpVxlanTunnel(
1535 self, 99, bd1.bd_id,
1536 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L2,
1538 vx_tun_l2_1.add_vpp_config()
1541 # A static endpoint that the learnt endpoints are trying to
1544 ep = VppGbpEndpoint(self, self.pg0,
1546 "10.0.0.127", "11.0.0.127",
1547 "2001:10::1", "3001::1")
1550 self.assertTrue(find_route(self, ep.ip4.address, 32, table_id=1))
1552 # a packet with an sclass from an unknwon EPG
1553 p = (Ether(src=self.pg2.remote_mac,
1554 dst=self.pg2.local_mac) /
1555 IP(src=self.pg2.remote_hosts[0].ip4,
1556 dst=self.pg2.local_ip4) /
1557 UDP(sport=1234, dport=48879) /
1558 VXLAN(vni=99, gpid=88, flags=0x88) /
1559 Ether(src=learnt[0]["mac"], dst=ep.mac) /
1560 IP(src=learnt[0]["ip"], dst=ep.ip4.address) /
1561 UDP(sport=1234, dport=1234) /
1564 self.send_and_assert_no_replies(self.pg2, p)
1567 # we should not have learnt a new tunnel endpoint, since
1568 # the EPG was not learnt.
1570 self.assertEqual(INDEX_INVALID,
1571 find_vxlan_gbp_tunnel(self,
1573 self.pg2.remote_hosts[0].ip4,
1576 # epg is not learnt, becasue the EPG is unknwon
1577 self.assertEqual(len(self.vapi.gbp_endpoint_dump()), 1)
1580 # Learn new EPs from IP packets
1582 for ii, l in enumerate(learnt):
1583 # a packet with an sclass from a knwon EPG
1584 # arriving on an unknown TEP
1585 p = (Ether(src=self.pg2.remote_mac,
1586 dst=self.pg2.local_mac) /
1587 IP(src=self.pg2.remote_hosts[1].ip4,
1588 dst=self.pg2.local_ip4) /
1589 UDP(sport=1234, dport=48879) /
1590 VXLAN(vni=99, gpid=112, flags=0x88) /
1591 Ether(src=l['mac'], dst=ep.mac) /
1592 IP(src=l['ip'], dst=ep.ip4.address) /
1593 UDP(sport=1234, dport=1234) /
1596 rx = self.send_and_expect(self.pg2, [p], self.pg0)
1599 tep1_sw_if_index = find_vxlan_gbp_tunnel(
1602 self.pg2.remote_hosts[1].ip4,
1604 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
1607 # the EP is learnt via the learnt TEP
1608 # both from its MAC and its IP
1610 self.assertTrue(find_gbp_endpoint(self,
1611 vx_tun_l2_1.sw_if_index,
1613 self.assertTrue(find_gbp_endpoint(self,
1614 vx_tun_l2_1.sw_if_index,
1617 self.logger.info(self.vapi.cli("show gbp endpoint"))
1618 self.logger.info(self.vapi.cli("show gbp vxlan"))
1619 self.logger.info(self.vapi.cli("show ip mfib"))
1622 # If we sleep for the threshold time, the learnt endpoints should
1626 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1630 # Learn new EPs from GARP packets received on the BD's mcast tunnel
1632 for ii, l in enumerate(learnt):
1633 # a packet with an sclass from a knwon EPG
1634 # arriving on an unknown TEP
1635 p = (Ether(src=self.pg2.remote_mac,
1636 dst=self.pg2.local_mac) /
1637 IP(src=self.pg2.remote_hosts[1].ip4,
1639 UDP(sport=1234, dport=48879) /
1640 VXLAN(vni=88, gpid=112, flags=0x88) /
1641 Ether(src=l['mac'], dst="ff:ff:ff:ff:ff:ff") /
1643 psrc=l['ip'], pdst=l['ip'],
1644 hwsrc=l['mac'], hwdst="ff:ff:ff:ff:ff:ff"))
1646 rx = self.send_and_expect(self.pg4, [p], self.pg0)
1649 tep1_sw_if_index = find_vxlan_gbp_tunnel(
1652 self.pg2.remote_hosts[1].ip4,
1654 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
1657 # the EP is learnt via the learnt TEP
1658 # both from its MAC and its IP
1660 self.assertTrue(find_gbp_endpoint(self,
1661 vx_tun_l2_1.sw_if_index,
1663 self.assertTrue(find_gbp_endpoint(self,
1664 vx_tun_l2_1.sw_if_index,
1668 # wait for the learnt endpoints to age out
1671 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1675 # Learn new EPs from L2 packets
1677 for ii, l in enumerate(learnt):
1678 # a packet with an sclass from a knwon EPG
1679 # arriving on an unknown TEP
1680 p = (Ether(src=self.pg2.remote_mac,
1681 dst=self.pg2.local_mac) /
1682 IP(src=self.pg2.remote_hosts[1].ip4,
1683 dst=self.pg2.local_ip4) /
1684 UDP(sport=1234, dport=48879) /
1685 VXLAN(vni=99, gpid=112, flags=0x88) /
1686 Ether(src=l['mac'], dst=ep.mac) /
1689 rx = self.send_and_expect(self.pg2, [p], self.pg0)
1692 tep1_sw_if_index = find_vxlan_gbp_tunnel(
1695 self.pg2.remote_hosts[1].ip4,
1697 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
1700 # the EP is learnt via the learnt TEP
1701 # both from its MAC and its IP
1703 self.assertTrue(find_gbp_endpoint(self,
1704 vx_tun_l2_1.sw_if_index,
1707 self.logger.info(self.vapi.cli("show gbp endpoint"))
1708 self.logger.info(self.vapi.cli("show gbp vxlan"))
1709 self.logger.info(self.vapi.cli("show vxlan-gbp tunnel"))
1712 # wait for the learnt endpoints to age out
1715 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1719 # repeat. the do not learn bit is set so the EPs are not learnt
1722 # a packet with an sclass from a knwon EPG
1723 p = (Ether(src=self.pg2.remote_mac,
1724 dst=self.pg2.local_mac) /
1725 IP(src=self.pg2.remote_hosts[1].ip4,
1726 dst=self.pg2.local_ip4) /
1727 UDP(sport=1234, dport=48879) /
1728 VXLAN(vni=99, gpid=112, flags=0x88, gpflags="D") /
1729 Ether(src=l['mac'], dst=ep.mac) /
1730 IP(src=l['ip'], dst=ep.ip4.address) /
1731 UDP(sport=1234, dport=1234) /
1734 rx = self.send_and_expect(self.pg2, p*65, self.pg0)
1737 self.assertFalse(find_gbp_endpoint(self,
1738 vx_tun_l2_1.sw_if_index,
1745 # a packet with an sclass from a knwon EPG
1746 p = (Ether(src=self.pg2.remote_mac,
1747 dst=self.pg2.local_mac) /
1748 IP(src=self.pg2.remote_hosts[1].ip4,
1749 dst=self.pg2.local_ip4) /
1750 UDP(sport=1234, dport=48879) /
1751 VXLAN(vni=99, gpid=112, flags=0x88) /
1752 Ether(src=l['mac'], dst=ep.mac) /
1753 IP(src=l['ip'], dst=ep.ip4.address) /
1754 UDP(sport=1234, dport=1234) /
1757 rx = self.send_and_expect(self.pg2, p*65, self.pg0)
1759 self.assertTrue(find_gbp_endpoint(self,
1760 vx_tun_l2_1.sw_if_index,
1764 # Static EP replies to dynamics
1766 self.logger.info(self.vapi.cli("sh l2fib bd_id 1"))
1768 p = (Ether(src=ep.mac, dst=l['mac']) /
1769 IP(dst=l['ip'], src=ep.ip4.address) /
1770 UDP(sport=1234, dport=1234) /
1773 rxs = self.send_and_expect(self.pg0, p * 17, self.pg2)
1776 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
1777 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
1778 self.assertEqual(rx[UDP].dport, 48879)
1779 # the UDP source port is a random value for hashing
1780 self.assertEqual(rx[VXLAN].gpid, 112)
1781 self.assertEqual(rx[VXLAN].vni, 99)
1782 self.assertTrue(rx[VXLAN].flags.G)
1783 self.assertTrue(rx[VXLAN].flags.Instance)
1784 self.assertTrue(rx[VXLAN].gpflags.A)
1785 self.assertFalse(rx[VXLAN].gpflags.D)
1788 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1792 # repeat in the other EPG
1793 # there's no contract between 220 and 330, but the A-bit is set
1794 # so the packet is cleared for delivery
1797 # a packet with an sclass from a knwon EPG
1798 p = (Ether(src=self.pg2.remote_mac,
1799 dst=self.pg2.local_mac) /
1800 IP(src=self.pg2.remote_hosts[1].ip4,
1801 dst=self.pg2.local_ip4) /
1802 UDP(sport=1234, dport=48879) /
1803 VXLAN(vni=99, gpid=113, flags=0x88, gpflags='A') /
1804 Ether(src=l['mac'], dst=ep.mac) /
1805 IP(src=l['ip'], dst=ep.ip4.address) /
1806 UDP(sport=1234, dport=1234) /
1809 rx = self.send_and_expect(self.pg2, p*65, self.pg0)
1811 self.assertTrue(find_gbp_endpoint(self,
1812 vx_tun_l2_1.sw_if_index,
1816 # static EP cannot reach the learnt EPs since there is no contract
1817 # only test 1 EP as the others could timeout
1819 p = (Ether(src=ep.mac, dst=l['mac']) /
1820 IP(dst=learnt[0]['ip'], src=ep.ip4.address) /
1821 UDP(sport=1234, dport=1234) /
1824 self.send_and_assert_no_replies(self.pg0, [p])
1827 # refresh the entries after the check for no replies above
1830 # a packet with an sclass from a knwon EPG
1831 p = (Ether(src=self.pg2.remote_mac,
1832 dst=self.pg2.local_mac) /
1833 IP(src=self.pg2.remote_hosts[1].ip4,
1834 dst=self.pg2.local_ip4) /
1835 UDP(sport=1234, dport=48879) /
1836 VXLAN(vni=99, gpid=113, flags=0x88, gpflags='A') /
1837 Ether(src=l['mac'], dst=ep.mac) /
1838 IP(src=l['ip'], dst=ep.ip4.address) /
1839 UDP(sport=1234, dport=1234) /
1842 rx = self.send_and_expect(self.pg2, p*65, self.pg0)
1844 self.assertTrue(find_gbp_endpoint(self,
1845 vx_tun_l2_1.sw_if_index,
1849 # Add the contract so they can talk
1851 acl = VppGbpAcl(self)
1852 rule = acl.create_rule(permit_deny=1, proto=17)
1853 rule2 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
1854 acl_index = acl.add_vpp_config([rule, rule2])
1855 c1 = VppGbpContract(
1856 self, epg_220, epg_330, acl_index,
1857 [VppGbpContractRule(
1858 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1861 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1863 [ETH_P_IP, ETH_P_IPV6])
1867 p = (Ether(src=ep.mac, dst=l['mac']) /
1868 IP(dst=l['ip'], src=ep.ip4.address) /
1869 UDP(sport=1234, dport=1234) /
1872 self.send_and_expect(self.pg0, [p], self.pg2)
1875 # send UU packets from the local EP
1877 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1878 self.logger.info(self.vapi.cli("sh gbp bridge"))
1879 p_uu = (Ether(src=ep.mac, dst="00:11:11:11:11:11") /
1880 IP(dst="10.0.0.133", src=ep.ip4.address) /
1881 UDP(sport=1234, dport=1234) /
1883 rxs = self.send_and_expect(ep.itf, [p_uu], gbd1.uu_fwd)
1885 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1887 p_bm = (Ether(src=ep.mac, dst="ff:ff:ff:ff:ff:ff") /
1888 IP(dst="10.0.0.133", src=ep.ip4.address) /
1889 UDP(sport=1234, dport=1234) /
1891 rxs = self.send_and_expect_only(ep.itf, [p_bm], tun_bm.mcast_itf)
1894 self.assertEqual(rx[IP].src, self.pg4.local_ip4)
1895 self.assertEqual(rx[IP].dst, "239.1.1.1")
1896 self.assertEqual(rx[UDP].dport, 48879)
1897 # the UDP source port is a random value for hashing
1898 self.assertEqual(rx[VXLAN].gpid, 112)
1899 self.assertEqual(rx[VXLAN].vni, 88)
1900 self.assertTrue(rx[VXLAN].flags.G)
1901 self.assertTrue(rx[VXLAN].flags.Instance)
1902 self.assertFalse(rx[VXLAN].gpflags.A)
1903 self.assertFalse(rx[VXLAN].gpflags.D)
1906 # Check v6 Endpoints
1909 # a packet with an sclass from a knwon EPG
1910 p = (Ether(src=self.pg2.remote_mac,
1911 dst=self.pg2.local_mac) /
1912 IP(src=self.pg2.remote_hosts[1].ip4,
1913 dst=self.pg2.local_ip4) /
1914 UDP(sport=1234, dport=48879) /
1915 VXLAN(vni=99, gpid=113, flags=0x88, gpflags='A') /
1916 Ether(src=l['mac'], dst=ep.mac) /
1917 IPv6(src=l['ip6'], dst=ep.ip6.address) /
1918 UDP(sport=1234, dport=1234) /
1921 rx = self.send_and_expect(self.pg2, p*65, self.pg0)
1923 self.assertTrue(find_gbp_endpoint(self,
1924 vx_tun_l2_1.sw_if_index,
1928 # L3 Endpoint Learning
1929 # - configured on the bridge's BVI
1936 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1939 self.pg2.unconfig_ip4()
1940 self.pg3.unconfig_ip4()
1941 self.pg4.unconfig_ip4()
1943 self.logger.info(self.vapi.cli("sh int"))
1944 self.logger.info(self.vapi.cli("sh gbp vxlan"))
1946 def test_gbp_learn_vlan_l2(self):
1947 """ GBP L2 Endpoint w/ VLANs"""
1949 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
1950 learnt = [{'mac': '00:00:11:11:11:01',
1952 'ip6': '2001:10::2'},
1953 {'mac': '00:00:11:11:11:02',
1955 'ip6': '2001:10::3'}]
1960 gt4 = VppIpTable(self, 1)
1961 gt4.add_vpp_config()
1962 gt6 = VppIpTable(self, 1, is_ip6=True)
1963 gt6.add_vpp_config()
1965 rd1 = VppGbpRouteDomain(self, 1, gt4, gt6)
1966 rd1.add_vpp_config()
1969 # Pg2 hosts the vxlan tunnel, hosts on pg2 to act as TEPs
1971 self.pg2.config_ip4()
1972 self.pg2.resolve_arp()
1973 self.pg2.generate_remote_hosts(4)
1974 self.pg2.configure_ipv4_neighbors()
1975 self.pg3.config_ip4()
1976 self.pg3.resolve_arp()
1979 # The EP will be on a vlan sub-interface
1981 vlan_11 = VppDot1QSubint(self, self.pg0, 11)
1983 self.vapi.l2_interface_vlan_tag_rewrite(
1984 sw_if_index=vlan_11.sw_if_index, vtr_op=L2_VTR_OP.L2_POP_1,
1987 bd_uu_fwd = VppVxlanGbpTunnel(self, self.pg3.local_ip4,
1988 self.pg3.remote_ip4, 116)
1989 bd_uu_fwd.add_vpp_config()
1992 # a GBP bridge domain with a BVI and a UU-flood interface
1993 # The BD is marked as do not learn, so no endpoints are ever
1994 # learnt in this BD.
1996 bd1 = VppBridgeDomain(self, 1)
1997 bd1.add_vpp_config()
1998 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0, bd_uu_fwd,
2000 gbd1.add_vpp_config()
2002 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2003 self.logger.info(self.vapi.cli("sh gbp bridge"))
2005 # ... and has a /32 applied
2006 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2007 ip_addr.add_vpp_config()
2010 # The Endpoint-group in which we are learning endpoints
2012 epg_220 = VppGbpEndpointGroup(self, 220, 441, rd1, gbd1,
2016 VppGbpEndpointRetention(2))
2017 epg_220.add_vpp_config()
2020 # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
2023 vx_tun_l2_1 = VppGbpVxlanTunnel(
2024 self, 99, bd1.bd_id,
2025 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L2,
2027 vx_tun_l2_1.add_vpp_config()
2030 # A static endpoint that the learnt endpoints are trying to
2033 ep = VppGbpEndpoint(self, vlan_11,
2035 "10.0.0.127", "11.0.0.127",
2036 "2001:10::1", "3001::1")
2039 self.assertTrue(find_route(self, ep.ip4.address, 32, table_id=1))
2042 # Send to the static EP
2044 for ii, l in enumerate(learnt):
2045 # a packet with an sclass from a knwon EPG
2046 # arriving on an unknown TEP
2047 p = (Ether(src=self.pg2.remote_mac,
2048 dst=self.pg2.local_mac) /
2049 IP(src=self.pg2.remote_hosts[1].ip4,
2050 dst=self.pg2.local_ip4) /
2051 UDP(sport=1234, dport=48879) /
2052 VXLAN(vni=99, gpid=441, flags=0x88) /
2053 Ether(src=l['mac'], dst=ep.mac) /
2054 IP(src=l['ip'], dst=ep.ip4.address) /
2055 UDP(sport=1234, dport=1234) /
2058 rxs = self.send_and_expect(self.pg2, [p], self.pg0)
2061 # packet to EP has the EP's vlan tag
2064 self.assertEqual(rx[Dot1Q].vlan, 11)
2067 # the EP is not learnt since the BD setting prevents it
2070 self.assertFalse(find_gbp_endpoint(self,
2071 vx_tun_l2_1.sw_if_index,
2073 self.assertEqual(INDEX_INVALID,
2074 find_vxlan_gbp_tunnel(
2077 self.pg2.remote_hosts[1].ip4,
2080 self.assertEqual(len(self.vapi.gbp_endpoint_dump()), 1)
2084 # we didn't learn the remotes so they are sent to the UU-fwd
2087 p = (Ether(src=ep.mac, dst=l['mac']) /
2089 IP(dst=l['ip'], src=ep.ip4.address) /
2090 UDP(sport=1234, dport=1234) /
2093 rxs = self.send_and_expect(self.pg0, p * 17, self.pg3)
2096 self.assertEqual(rx[IP].src, self.pg3.local_ip4)
2097 self.assertEqual(rx[IP].dst, self.pg3.remote_ip4)
2098 self.assertEqual(rx[UDP].dport, 48879)
2099 # the UDP source port is a random value for hashing
2100 self.assertEqual(rx[VXLAN].gpid, 441)
2101 self.assertEqual(rx[VXLAN].vni, 116)
2102 self.assertTrue(rx[VXLAN].flags.G)
2103 self.assertTrue(rx[VXLAN].flags.Instance)
2104 self.assertFalse(rx[VXLAN].gpflags.A)
2105 self.assertFalse(rx[VXLAN].gpflags.D)
2107 self.pg2.unconfig_ip4()
2108 self.pg3.unconfig_ip4()
2110 def test_gbp_learn_l3(self):
2111 """ GBP L3 Endpoint Learning """
2113 self.vapi.cli("set logging class gbp debug")
2115 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
2116 routed_dst_mac = "00:0c:0c:0c:0c:0c"
2117 routed_src_mac = "00:22:bd:f8:19:ff"
2119 learnt = [{'mac': '00:00:11:11:11:02',
2121 'ip6': '2001:10::2'},
2122 {'mac': '00:00:11:11:11:03',
2124 'ip6': '2001:10::3'}]
2129 t4 = VppIpTable(self, 1)
2131 t6 = VppIpTable(self, 1, True)
2134 tun_ip4_uu = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
2135 self.pg4.remote_ip4, 114)
2136 tun_ip6_uu = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
2137 self.pg4.remote_ip4, 116)
2138 tun_ip4_uu.add_vpp_config()
2139 tun_ip6_uu.add_vpp_config()
2141 rd1 = VppGbpRouteDomain(self, 2, t4, t6, tun_ip4_uu, tun_ip6_uu)
2142 rd1.add_vpp_config()
2144 self.loop0.set_mac(self.router_mac)
2147 # Bind the BVI to the RD
2149 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
2150 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
2153 # Pg2 hosts the vxlan tunnel
2154 # hosts on pg2 to act as TEPs
2158 self.pg2.config_ip4()
2159 self.pg2.resolve_arp()
2160 self.pg2.generate_remote_hosts(4)
2161 self.pg2.configure_ipv4_neighbors()
2162 self.pg3.config_ip4()
2163 self.pg3.resolve_arp()
2164 self.pg4.config_ip4()
2165 self.pg4.resolve_arp()
2168 # a GBP bridge domain with a BVI and a UU-flood interface
2170 bd1 = VppBridgeDomain(self, 1)
2171 bd1.add_vpp_config()
2172 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0, self.pg3)
2173 gbd1.add_vpp_config()
2175 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2176 self.logger.info(self.vapi.cli("sh gbp bridge"))
2177 self.logger.info(self.vapi.cli("sh gbp route"))
2179 # ... and has a /32 and /128 applied
2180 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2181 ip4_addr.add_vpp_config()
2182 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 128)
2183 ip6_addr.add_vpp_config()
2186 # The Endpoint-group in which we are learning endpoints
2188 epg_220 = VppGbpEndpointGroup(self, 220, 441, rd1, gbd1,
2192 VppGbpEndpointRetention(2))
2193 epg_220.add_vpp_config()
2196 # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
2199 vx_tun_l3 = VppGbpVxlanTunnel(
2200 self, 101, rd1.rd_id,
2201 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
2203 vx_tun_l3.add_vpp_config()
2206 # A static endpoint that the learnt endpoints are trying to
2209 ep = VppGbpEndpoint(self, self.pg0,
2211 "10.0.0.127", "11.0.0.127",
2212 "2001:10::1", "3001::1")
2216 # learn some remote IPv4 EPs
2218 for ii, l in enumerate(learnt):
2219 # a packet with an sclass from a knwon EPG
2220 # arriving on an unknown TEP
2221 p = (Ether(src=self.pg2.remote_mac,
2222 dst=self.pg2.local_mac) /
2223 IP(src=self.pg2.remote_hosts[1].ip4,
2224 dst=self.pg2.local_ip4) /
2225 UDP(sport=1234, dport=48879) /
2226 VXLAN(vni=101, gpid=441, flags=0x88) /
2227 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2228 IP(src=l['ip'], dst=ep.ip4.address) /
2229 UDP(sport=1234, dport=1234) /
2232 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2235 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2238 self.pg2.remote_hosts[1].ip4,
2240 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2242 # endpoint learnt via the parent GBP-vxlan interface
2243 self.assertTrue(find_gbp_endpoint(self,
2244 vx_tun_l3._sw_if_index,
2248 # Static IPv4 EP replies to learnt
2251 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2252 IP(dst=l['ip'], src=ep.ip4.address) /
2253 UDP(sport=1234, dport=1234) /
2256 rxs = self.send_and_expect(self.pg0, p*1, self.pg2)
2259 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2260 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2261 self.assertEqual(rx[UDP].dport, 48879)
2262 # the UDP source port is a random value for hashing
2263 self.assertEqual(rx[VXLAN].gpid, 441)
2264 self.assertEqual(rx[VXLAN].vni, 101)
2265 self.assertTrue(rx[VXLAN].flags.G)
2266 self.assertTrue(rx[VXLAN].flags.Instance)
2267 self.assertTrue(rx[VXLAN].gpflags.A)
2268 self.assertFalse(rx[VXLAN].gpflags.D)
2270 inner = rx[VXLAN].payload
2272 self.assertEqual(inner[Ether].src, routed_src_mac)
2273 self.assertEqual(inner[Ether].dst, routed_dst_mac)
2274 self.assertEqual(inner[IP].src, ep.ip4.address)
2275 self.assertEqual(inner[IP].dst, l['ip'])
2278 self.assertFalse(find_gbp_endpoint(self,
2283 # learn some remote IPv6 EPs
2285 for ii, l in enumerate(learnt):
2286 # a packet with an sclass from a knwon EPG
2287 # arriving on an unknown TEP
2288 p = (Ether(src=self.pg2.remote_mac,
2289 dst=self.pg2.local_mac) /
2290 IP(src=self.pg2.remote_hosts[1].ip4,
2291 dst=self.pg2.local_ip4) /
2292 UDP(sport=1234, dport=48879) /
2293 VXLAN(vni=101, gpid=441, flags=0x88) /
2294 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2295 IPv6(src=l['ip6'], dst=ep.ip6.address) /
2296 UDP(sport=1234, dport=1234) /
2299 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2302 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2305 self.pg2.remote_hosts[1].ip4,
2307 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2309 self.logger.info(self.vapi.cli("show gbp bridge"))
2310 self.logger.info(self.vapi.cli("show vxlan-gbp tunnel"))
2311 self.logger.info(self.vapi.cli("show gbp vxlan"))
2312 self.logger.info(self.vapi.cli("show int addr"))
2314 # endpoint learnt via the TEP
2315 self.assertTrue(find_gbp_endpoint(self, ip=l['ip6']))
2317 self.logger.info(self.vapi.cli("show gbp endpoint"))
2318 self.logger.info(self.vapi.cli("show ip fib index 1 %s" % l['ip']))
2321 # Static EP replies to learnt
2324 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2325 IPv6(dst=l['ip6'], src=ep.ip6.address) /
2326 UDP(sport=1234, dport=1234) /
2329 rxs = self.send_and_expect(self.pg0, p*65, self.pg2)
2332 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2333 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2334 self.assertEqual(rx[UDP].dport, 48879)
2335 # the UDP source port is a random value for hashing
2336 self.assertEqual(rx[VXLAN].gpid, 441)
2337 self.assertEqual(rx[VXLAN].vni, 101)
2338 self.assertTrue(rx[VXLAN].flags.G)
2339 self.assertTrue(rx[VXLAN].flags.Instance)
2340 self.assertTrue(rx[VXLAN].gpflags.A)
2341 self.assertFalse(rx[VXLAN].gpflags.D)
2343 inner = rx[VXLAN].payload
2345 self.assertEqual(inner[Ether].src, routed_src_mac)
2346 self.assertEqual(inner[Ether].dst, routed_dst_mac)
2347 self.assertEqual(inner[IPv6].src, ep.ip6.address)
2348 self.assertEqual(inner[IPv6].dst, l['ip6'])
2350 self.logger.info(self.vapi.cli("sh gbp endpoint"))
2352 self.wait_for_ep_timeout(ip=l['ip'])
2355 # Static sends to unknown EP with no route
2357 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2358 IP(dst="10.0.0.99", src=ep.ip4.address) /
2359 UDP(sport=1234, dport=1234) /
2362 self.send_and_assert_no_replies(self.pg0, [p])
2365 # Add a route to static EP's v4 and v6 subnet
2366 # packets should be sent on the v4/v6 uu=fwd interface resp.
2368 se_10_24 = VppGbpSubnet(
2369 self, rd1, "10.0.0.0", 24,
2370 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT)
2371 se_10_24.add_vpp_config()
2373 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2374 IP(dst="10.0.0.99", src=ep.ip4.address) /
2375 UDP(sport=1234, dport=1234) /
2378 rxs = self.send_and_expect(self.pg0, [p], self.pg4)
2380 self.assertEqual(rx[IP].src, self.pg4.local_ip4)
2381 self.assertEqual(rx[IP].dst, self.pg4.remote_ip4)
2382 self.assertEqual(rx[UDP].dport, 48879)
2383 # the UDP source port is a random value for hashing
2384 self.assertEqual(rx[VXLAN].gpid, 441)
2385 self.assertEqual(rx[VXLAN].vni, 114)
2386 self.assertTrue(rx[VXLAN].flags.G)
2387 self.assertTrue(rx[VXLAN].flags.Instance)
2388 # policy is not applied to packets sent to the uu-fwd interfaces
2389 self.assertFalse(rx[VXLAN].gpflags.A)
2390 self.assertFalse(rx[VXLAN].gpflags.D)
2393 # learn some remote IPv4 EPs
2395 for ii, l in enumerate(learnt):
2396 # a packet with an sclass from a knwon EPG
2397 # arriving on an unknown TEP
2398 p = (Ether(src=self.pg2.remote_mac,
2399 dst=self.pg2.local_mac) /
2400 IP(src=self.pg2.remote_hosts[2].ip4,
2401 dst=self.pg2.local_ip4) /
2402 UDP(sport=1234, dport=48879) /
2403 VXLAN(vni=101, gpid=441, flags=0x88) /
2404 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2405 IP(src=l['ip'], dst=ep.ip4.address) /
2406 UDP(sport=1234, dport=1234) /
2409 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2412 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2415 self.pg2.remote_hosts[2].ip4,
2417 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2419 # endpoint learnt via the parent GBP-vxlan interface
2420 self.assertTrue(find_gbp_endpoint(self,
2421 vx_tun_l3._sw_if_index,
2425 # Add a remote endpoint from the API
2427 rep_88 = VppGbpEndpoint(self, vx_tun_l3,
2429 "10.0.0.88", "11.0.0.88",
2430 "2001:10::88", "3001::88",
2431 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
2433 self.pg2.remote_hosts[1].ip4,
2435 rep_88.add_vpp_config()
2438 # Add a remote endpoint from the API that matches an existing one
2440 rep_2 = VppGbpEndpoint(self, vx_tun_l3,
2442 learnt[0]['ip'], "11.0.0.101",
2443 learnt[0]['ip6'], "3001::101",
2444 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
2446 self.pg2.remote_hosts[1].ip4,
2448 rep_2.add_vpp_config()
2451 # Add a route to the leanred EP's v4 subnet
2452 # packets should be send on the v4/v6 uu=fwd interface resp.
2454 se_10_1_24 = VppGbpSubnet(
2455 self, rd1, "10.0.1.0", 24,
2456 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT)
2457 se_10_1_24.add_vpp_config()
2459 self.logger.info(self.vapi.cli("show gbp endpoint"))
2461 ips = ["10.0.0.88", learnt[0]['ip']]
2463 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2464 IP(dst=ip, src=ep.ip4.address) /
2465 UDP(sport=1234, dport=1234) /
2468 rxs = self.send_and_expect(self.pg0, p*65, self.pg2)
2471 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2472 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2473 self.assertEqual(rx[UDP].dport, 48879)
2474 # the UDP source port is a random value for hashing
2475 self.assertEqual(rx[VXLAN].gpid, 441)
2476 self.assertEqual(rx[VXLAN].vni, 101)
2477 self.assertTrue(rx[VXLAN].flags.G)
2478 self.assertTrue(rx[VXLAN].flags.Instance)
2479 self.assertTrue(rx[VXLAN].gpflags.A)
2480 self.assertFalse(rx[VXLAN].gpflags.D)
2482 inner = rx[VXLAN].payload
2484 self.assertEqual(inner[Ether].src, routed_src_mac)
2485 self.assertEqual(inner[Ether].dst, routed_dst_mac)
2486 self.assertEqual(inner[IP].src, ep.ip4.address)
2487 self.assertEqual(inner[IP].dst, ip)
2490 # remove the API remote EPs, only API sourced is gone, the DP
2491 # learnt one remains
2493 rep_88.remove_vpp_config()
2494 rep_2.remove_vpp_config()
2496 self.assertTrue(find_gbp_endpoint(self, ip=rep_2.ip4.address))
2498 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2499 IP(src=ep.ip4.address, dst=rep_2.ip4.address) /
2500 UDP(sport=1234, dport=1234) /
2502 rxs = self.send_and_expect(self.pg0, [p], self.pg2)
2504 self.assertFalse(find_gbp_endpoint(self, ip=rep_88.ip4.address))
2506 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2507 IP(src=ep.ip4.address, dst=rep_88.ip4.address) /
2508 UDP(sport=1234, dport=1234) /
2510 rxs = self.send_and_expect(self.pg0, [p], self.pg4)
2513 # to appease the testcase we cannot have the registered EP stll
2514 # present (because it's DP learnt) when the TC ends so wait until
2517 self.wait_for_ep_timeout(ip=rep_88.ip4.address)
2518 self.wait_for_ep_timeout(ip=rep_2.ip4.address)
2521 # shutdown with learnt endpoint present
2523 p = (Ether(src=self.pg2.remote_mac,
2524 dst=self.pg2.local_mac) /
2525 IP(src=self.pg2.remote_hosts[1].ip4,
2526 dst=self.pg2.local_ip4) /
2527 UDP(sport=1234, dport=48879) /
2528 VXLAN(vni=101, gpid=441, flags=0x88) /
2529 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2530 IP(src=learnt[1]['ip'], dst=ep.ip4.address) /
2531 UDP(sport=1234, dport=1234) /
2534 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2536 # endpoint learnt via the parent GBP-vxlan interface
2537 self.assertTrue(find_gbp_endpoint(self,
2538 vx_tun_l3._sw_if_index,
2543 # remote endpoint becomes local
2545 self.pg2.unconfig_ip4()
2546 self.pg3.unconfig_ip4()
2547 self.pg4.unconfig_ip4()
2549 def test_gbp_redirect(self):
2550 """ GBP Endpoint Redirect """
2552 self.vapi.cli("set logging class gbp debug")
2554 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
2555 routed_dst_mac = "00:0c:0c:0c:0c:0c"
2556 routed_src_mac = "00:22:bd:f8:19:ff"
2558 learnt = [{'mac': '00:00:11:11:11:02',
2560 'ip6': '2001:10::2'},
2561 {'mac': '00:00:11:11:11:03',
2563 'ip6': '2001:10::3'}]
2568 t4 = VppIpTable(self, 1)
2570 t6 = VppIpTable(self, 1, True)
2573 rd1 = VppGbpRouteDomain(self, 2, t4, t6)
2574 rd1.add_vpp_config()
2576 self.loop0.set_mac(self.router_mac)
2579 # Bind the BVI to the RD
2581 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
2582 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
2585 # Pg7 hosts a BD's UU-fwd
2587 self.pg7.config_ip4()
2588 self.pg7.resolve_arp()
2591 # a GBP bridge domains for the EPs
2593 bd1 = VppBridgeDomain(self, 1)
2594 bd1.add_vpp_config()
2595 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0)
2596 gbd1.add_vpp_config()
2598 bd2 = VppBridgeDomain(self, 2)
2599 bd2.add_vpp_config()
2600 gbd2 = VppGbpBridgeDomain(self, bd2, self.loop1)
2601 gbd2.add_vpp_config()
2603 # ... and has a /32 and /128 applied
2604 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2605 ip4_addr.add_vpp_config()
2606 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 128)
2607 ip6_addr.add_vpp_config()
2608 ip4_addr = VppIpInterfaceAddress(self, gbd2.bvi, "10.0.1.128", 32)
2609 ip4_addr.add_vpp_config()
2610 ip6_addr = VppIpInterfaceAddress(self, gbd2.bvi, "2001:11::128", 128)
2611 ip6_addr.add_vpp_config()
2614 # The Endpoint-groups in which we are learning endpoints
2616 epg_220 = VppGbpEndpointGroup(self, 220, 440, rd1, gbd1,
2620 VppGbpEndpointRetention(2))
2621 epg_220.add_vpp_config()
2622 epg_221 = VppGbpEndpointGroup(self, 221, 441, rd1, gbd2,
2626 VppGbpEndpointRetention(2))
2627 epg_221.add_vpp_config()
2628 epg_222 = VppGbpEndpointGroup(self, 222, 442, rd1, gbd1,
2632 VppGbpEndpointRetention(2))
2633 epg_222.add_vpp_config()
2636 # a GBP bridge domains for the SEPs
2638 bd_uu1 = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
2639 self.pg7.remote_ip4, 116)
2640 bd_uu1.add_vpp_config()
2641 bd_uu2 = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
2642 self.pg7.remote_ip4, 117)
2643 bd_uu2.add_vpp_config()
2645 bd3 = VppBridgeDomain(self, 3)
2646 bd3.add_vpp_config()
2647 gbd3 = VppGbpBridgeDomain(self, bd3, self.loop2, bd_uu1, learn=False)
2648 gbd3.add_vpp_config()
2649 bd4 = VppBridgeDomain(self, 4)
2650 bd4.add_vpp_config()
2651 gbd4 = VppGbpBridgeDomain(self, bd4, self.loop3, bd_uu2, learn=False)
2652 gbd4.add_vpp_config()
2655 # EPGs in which the service endpoints exist
2657 epg_320 = VppGbpEndpointGroup(self, 320, 550, rd1, gbd3,
2661 VppGbpEndpointRetention(2))
2662 epg_320.add_vpp_config()
2663 epg_321 = VppGbpEndpointGroup(self, 321, 551, rd1, gbd4,
2667 VppGbpEndpointRetention(2))
2668 epg_321.add_vpp_config()
2671 # three local endpoints
2673 ep1 = VppGbpEndpoint(self, self.pg0,
2675 "10.0.0.1", "11.0.0.1",
2676 "2001:10::1", "3001:10::1")
2677 ep1.add_vpp_config()
2678 ep2 = VppGbpEndpoint(self, self.pg1,
2680 "10.0.1.1", "11.0.1.1",
2681 "2001:11::1", "3001:11::1")
2682 ep2.add_vpp_config()
2683 ep3 = VppGbpEndpoint(self, self.pg2,
2685 "10.0.2.2", "11.0.2.2",
2686 "2001:12::1", "3001:12::1")
2687 ep3.add_vpp_config()
2692 sep1 = VppGbpEndpoint(self, self.pg3,
2694 "12.0.0.1", "13.0.0.1",
2695 "4001:10::1", "5001:10::1")
2696 sep1.add_vpp_config()
2697 sep2 = VppGbpEndpoint(self, self.pg4,
2699 "12.0.0.2", "13.0.0.2",
2700 "4001:10::2", "5001:10::2")
2701 sep2.add_vpp_config()
2702 sep3 = VppGbpEndpoint(self, self.pg5,
2704 "12.0.1.1", "13.0.1.1",
2705 "4001:11::1", "5001:11::1")
2706 sep3.add_vpp_config()
2707 # this EP is not installed immediately
2708 sep4 = VppGbpEndpoint(self, self.pg6,
2710 "12.0.1.2", "13.0.1.2",
2711 "4001:11::2", "5001:11::2")
2714 # an L2 switch packet between local EPs in different EPGs
2715 # different dest ports on each so the are LB hashed differently
2717 p4 = [(Ether(src=ep1.mac, dst=ep3.mac) /
2718 IP(src=ep1.ip4.address, dst=ep3.ip4.address) /
2719 UDP(sport=1234, dport=1234) /
2721 (Ether(src=ep3.mac, dst=ep1.mac) /
2722 IP(src=ep3.ip4.address, dst=ep1.ip4.address) /
2723 UDP(sport=1234, dport=1234) /
2725 p6 = [(Ether(src=ep1.mac, dst=ep3.mac) /
2726 IPv6(src=ep1.ip6.address, dst=ep3.ip6.address) /
2727 UDP(sport=1234, dport=1234) /
2729 (Ether(src=ep3.mac, dst=ep1.mac) /
2730 IPv6(src=ep3.ip6.address, dst=ep1.ip6.address) /
2731 UDP(sport=1234, dport=1230) /
2734 # should be dropped since no contract yet
2735 self.send_and_assert_no_replies(self.pg0, [p4[0]])
2736 self.send_and_assert_no_replies(self.pg0, [p6[0]])
2739 # Add a contract with a rule to load-balance redirect via SEP1 and SEP2
2740 # one of the next-hops is via an EP that is not known
2742 acl = VppGbpAcl(self)
2743 rule4 = acl.create_rule(permit_deny=1, proto=17)
2744 rule6 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
2745 acl_index = acl.add_vpp_config([rule4, rule6])
2748 # test the src-ip hash mode
2750 c1 = VppGbpContract(
2751 self, epg_220, epg_222, acl_index,
2752 [VppGbpContractRule(
2753 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2754 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2755 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
2756 sep1.ip4, sep1.epg.rd),
2757 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
2758 sep2.ip4, sep2.epg.rd)]),
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(sep3.vmac, sep3.epg.bd,
2763 sep3.ip6, sep3.epg.rd),
2764 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
2765 sep4.ip6, sep4.epg.rd)])],
2766 [ETH_P_IP, ETH_P_IPV6])
2769 c2 = VppGbpContract(
2770 self, epg_222, epg_220, acl_index,
2771 [VppGbpContractRule(
2772 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2773 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2774 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
2775 sep1.ip4, sep1.epg.rd),
2776 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
2777 sep2.ip4, sep2.epg.rd)]),
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(sep3.vmac, sep3.epg.bd,
2782 sep3.ip6, sep3.epg.rd),
2783 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
2784 sep4.ip6, sep4.epg.rd)])],
2785 [ETH_P_IP, ETH_P_IPV6])
2789 # send again with the contract preset, now packets arrive
2790 # at SEP1 or SEP2 depending on the hashing
2792 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
2795 self.assertEqual(rx[Ether].src, routed_src_mac)
2796 self.assertEqual(rx[Ether].dst, sep1.mac)
2797 self.assertEqual(rx[IP].src, ep1.ip4.address)
2798 self.assertEqual(rx[IP].dst, ep3.ip4.address)
2800 rxs = self.send_and_expect(self.pg2, p4[1] * 17, sep2.itf)
2803 self.assertEqual(rx[Ether].src, routed_src_mac)
2804 self.assertEqual(rx[Ether].dst, sep2.mac)
2805 self.assertEqual(rx[IP].src, ep3.ip4.address)
2806 self.assertEqual(rx[IP].dst, ep1.ip4.address)
2808 rxs = self.send_and_expect(self.pg0, p6[0] * 17, self.pg7)
2811 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
2812 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
2813 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
2814 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
2815 self.assertEqual(rx[VXLAN].vni, 117)
2816 self.assertTrue(rx[VXLAN].flags.G)
2817 self.assertTrue(rx[VXLAN].flags.Instance)
2818 # redirect policy has been applied
2819 self.assertTrue(rx[VXLAN].gpflags.A)
2820 self.assertFalse(rx[VXLAN].gpflags.D)
2822 inner = rx[VXLAN].payload
2824 self.assertEqual(inner[Ether].src, routed_src_mac)
2825 self.assertEqual(inner[Ether].dst, sep4.mac)
2826 self.assertEqual(inner[IPv6].src, ep1.ip6.address)
2827 self.assertEqual(inner[IPv6].dst, ep3.ip6.address)
2829 rxs = self.send_and_expect(self.pg2, p6[1] * 17, sep3.itf)
2832 self.assertEqual(rx[Ether].src, routed_src_mac)
2833 self.assertEqual(rx[Ether].dst, sep3.mac)
2834 self.assertEqual(rx[IPv6].src, ep3.ip6.address)
2835 self.assertEqual(rx[IPv6].dst, ep1.ip6.address)
2838 # programme the unknown EP
2840 sep4.add_vpp_config()
2842 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep4.itf)
2845 self.assertEqual(rx[Ether].src, routed_src_mac)
2846 self.assertEqual(rx[Ether].dst, sep4.mac)
2847 self.assertEqual(rx[IPv6].src, ep1.ip6.address)
2848 self.assertEqual(rx[IPv6].dst, ep3.ip6.address)
2851 # and revert back to unprogrammed
2853 sep4.remove_vpp_config()
2855 rxs = self.send_and_expect(self.pg0, p6[0] * 17, self.pg7)
2858 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
2859 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
2860 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
2861 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
2862 self.assertEqual(rx[VXLAN].vni, 117)
2863 self.assertTrue(rx[VXLAN].flags.G)
2864 self.assertTrue(rx[VXLAN].flags.Instance)
2865 # redirect policy has been applied
2866 self.assertTrue(rx[VXLAN].gpflags.A)
2867 self.assertFalse(rx[VXLAN].gpflags.D)
2869 inner = rx[VXLAN].payload
2871 self.assertEqual(inner[Ether].src, routed_src_mac)
2872 self.assertEqual(inner[Ether].dst, sep4.mac)
2873 self.assertEqual(inner[IPv6].src, ep1.ip6.address)
2874 self.assertEqual(inner[IPv6].dst, ep3.ip6.address)
2876 c1.remove_vpp_config()
2877 c2.remove_vpp_config()
2880 # test the symmetric hash mode
2882 c1 = VppGbpContract(
2883 self, epg_220, epg_222, acl_index,
2884 [VppGbpContractRule(
2885 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2886 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
2887 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
2888 sep1.ip4, sep1.epg.rd),
2889 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
2890 sep2.ip4, sep2.epg.rd)]),
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(sep3.vmac, sep3.epg.bd,
2895 sep3.ip6, sep3.epg.rd),
2896 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
2897 sep4.ip6, sep4.epg.rd)])],
2898 [ETH_P_IP, ETH_P_IPV6])
2901 c2 = VppGbpContract(
2902 self, epg_222, epg_220, acl_index,
2903 [VppGbpContractRule(
2904 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2905 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
2906 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
2907 sep1.ip4, sep1.epg.rd),
2908 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
2909 sep2.ip4, sep2.epg.rd)]),
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(sep3.vmac, sep3.epg.bd,
2914 sep3.ip6, sep3.epg.rd),
2915 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
2916 sep4.ip6, sep4.epg.rd)])],
2917 [ETH_P_IP, ETH_P_IPV6])
2921 # send again with the contract preset, now packets arrive
2922 # at SEP1 for both directions
2924 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
2927 self.assertEqual(rx[Ether].src, routed_src_mac)
2928 self.assertEqual(rx[Ether].dst, sep1.mac)
2929 self.assertEqual(rx[IP].src, ep1.ip4.address)
2930 self.assertEqual(rx[IP].dst, ep3.ip4.address)
2932 rxs = self.send_and_expect(self.pg2, p4[1] * 17, sep1.itf)
2935 self.assertEqual(rx[Ether].src, routed_src_mac)
2936 self.assertEqual(rx[Ether].dst, sep1.mac)
2937 self.assertEqual(rx[IP].src, ep3.ip4.address)
2938 self.assertEqual(rx[IP].dst, ep1.ip4.address)
2941 # programme the unknown EP for the L3 tests
2943 sep4.add_vpp_config()
2946 # an L3 switch packet between local EPs in different EPGs
2947 # different dest ports on each so the are LB hashed differently
2949 p4 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
2950 IP(src=ep1.ip4.address, dst=ep2.ip4.address) /
2951 UDP(sport=1234, dport=1234) /
2953 (Ether(src=ep2.mac, dst=str(self.router_mac)) /
2954 IP(src=ep2.ip4.address, dst=ep1.ip4.address) /
2955 UDP(sport=1234, dport=1234) /
2957 p6 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
2958 IPv6(src=ep1.ip6.address, dst=ep2.ip6.address) /
2959 UDP(sport=1234, dport=1234) /
2961 (Ether(src=ep2.mac, dst=str(self.router_mac)) /
2962 IPv6(src=ep2.ip6.address, dst=ep1.ip6.address) /
2963 UDP(sport=1234, dport=1234) /
2966 c3 = VppGbpContract(
2967 self, epg_220, epg_221, acl_index,
2968 [VppGbpContractRule(
2969 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2970 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
2971 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
2972 sep1.ip4, sep1.epg.rd),
2973 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
2974 sep2.ip4, sep2.epg.rd)]),
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(sep3.vmac, sep3.epg.bd,
2979 sep3.ip6, sep3.epg.rd),
2980 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
2981 sep4.ip6, sep4.epg.rd)])],
2982 [ETH_P_IP, ETH_P_IPV6])
2985 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
2988 self.assertEqual(rx[Ether].src, routed_src_mac)
2989 self.assertEqual(rx[Ether].dst, sep1.mac)
2990 self.assertEqual(rx[IP].src, ep1.ip4.address)
2991 self.assertEqual(rx[IP].dst, ep2.ip4.address)
2994 # learn a remote EP in EPG 221
2996 vx_tun_l3 = VppGbpVxlanTunnel(
2997 self, 444, rd1.rd_id,
2998 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
3000 vx_tun_l3.add_vpp_config()
3002 c4 = VppGbpContract(
3003 self, epg_221, epg_220, acl_index,
3004 [VppGbpContractRule(
3005 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3008 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3010 [ETH_P_IP, ETH_P_IPV6])
3013 p = (Ether(src=self.pg7.remote_mac,
3014 dst=self.pg7.local_mac) /
3015 IP(src=self.pg7.remote_ip4,
3016 dst=self.pg7.local_ip4) /
3017 UDP(sport=1234, dport=48879) /
3018 VXLAN(vni=444, gpid=441, flags=0x88) /
3019 Ether(src="00:22:22:22:22:33", dst=str(self.router_mac)) /
3020 IP(src="10.0.0.88", dst=ep1.ip4.address) /
3021 UDP(sport=1234, dport=1234) /
3024 rx = self.send_and_expect(self.pg7, [p], self.pg0)
3026 # endpoint learnt via the parent GBP-vxlan interface
3027 self.assertTrue(find_gbp_endpoint(self,
3028 vx_tun_l3._sw_if_index,
3031 p = (Ether(src=self.pg7.remote_mac,
3032 dst=self.pg7.local_mac) /
3033 IP(src=self.pg7.remote_ip4,
3034 dst=self.pg7.local_ip4) /
3035 UDP(sport=1234, dport=48879) /
3036 VXLAN(vni=444, gpid=441, flags=0x88) /
3037 Ether(src="00:22:22:22:22:33", dst=str(self.router_mac)) /
3038 IPv6(src="2001:10::88", dst=ep1.ip6.address) /
3039 UDP(sport=1234, dport=1234) /
3042 rx = self.send_and_expect(self.pg7, [p], self.pg0)
3044 # endpoint learnt via the parent GBP-vxlan interface
3045 self.assertTrue(find_gbp_endpoint(self,
3046 vx_tun_l3._sw_if_index,
3050 # L3 switch from local to remote EP
3052 p4 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3053 IP(src=ep1.ip4.address, dst="10.0.0.88") /
3054 UDP(sport=1234, dport=1234) /
3056 p6 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3057 IPv6(src=ep1.ip6.address, dst="2001:10::88") /
3058 UDP(sport=1234, dport=1234) /
3061 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3064 self.assertEqual(rx[Ether].src, routed_src_mac)
3065 self.assertEqual(rx[Ether].dst, sep1.mac)
3066 self.assertEqual(rx[IP].src, ep1.ip4.address)
3067 self.assertEqual(rx[IP].dst, "10.0.0.88")
3069 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep4.itf)
3072 self.assertEqual(rx[Ether].src, routed_src_mac)
3073 self.assertEqual(rx[Ether].dst, sep4.mac)
3074 self.assertEqual(rx[IPv6].src, ep1.ip6.address)
3075 self.assertEqual(rx[IPv6].dst, "2001:10::88")
3078 # test the dst-ip hash mode
3080 c5 = VppGbpContract(
3081 self, epg_220, epg_221, acl_index,
3082 [VppGbpContractRule(
3083 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3084 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
3085 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3086 sep1.ip4, sep1.epg.rd),
3087 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3088 sep2.ip4, sep2.epg.rd)]),
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(sep3.vmac, sep3.epg.bd,
3093 sep3.ip6, sep3.epg.rd),
3094 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3095 sep4.ip6, sep4.epg.rd)])],
3096 [ETH_P_IP, ETH_P_IPV6])
3099 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3102 self.assertEqual(rx[Ether].src, routed_src_mac)
3103 self.assertEqual(rx[Ether].dst, sep1.mac)
3104 self.assertEqual(rx[IP].src, ep1.ip4.address)
3105 self.assertEqual(rx[IP].dst, "10.0.0.88")
3107 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep3.itf)
3110 self.assertEqual(rx[Ether].src, routed_src_mac)
3111 self.assertEqual(rx[Ether].dst, sep3.mac)
3112 self.assertEqual(rx[IPv6].src, ep1.ip6.address)
3113 self.assertEqual(rx[IPv6].dst, "2001:10::88")
3118 self.pg7.unconfig_ip4()
3120 def test_gbp_l3_out(self):
3123 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
3124 self.vapi.cli("set logging class gbp debug")
3126 routed_dst_mac = "00:0c:0c:0c:0c:0c"
3127 routed_src_mac = "00:22:bd:f8:19:ff"
3132 t4 = VppIpTable(self, 1)
3134 t6 = VppIpTable(self, 1, True)
3137 rd1 = VppGbpRouteDomain(self, 2, t4, t6)
3138 rd1.add_vpp_config()
3140 self.loop0.set_mac(self.router_mac)
3143 # Bind the BVI to the RD
3145 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
3146 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
3149 # Pg7 hosts a BD's BUM
3150 # Pg1 some other l3 interface
3152 self.pg7.config_ip4()
3153 self.pg7.resolve_arp()
3156 # a multicast vxlan-gbp tunnel for broadcast in the BD
3158 tun_bm = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
3161 tun_bm.add_vpp_config()
3164 # a GBP external bridge domains for the EPs
3166 bd1 = VppBridgeDomain(self, 1)
3167 bd1.add_vpp_config()
3168 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0, None, tun_bm)
3169 gbd1.add_vpp_config()
3172 # The Endpoint-groups in which the external endpoints exist
3174 epg_220 = VppGbpEndpointGroup(self, 220, 113, rd1, gbd1,
3178 VppGbpEndpointRetention(2))
3179 epg_220.add_vpp_config()
3181 # the BVIs have the subnets applied ...
3182 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 24)
3183 ip4_addr.add_vpp_config()
3184 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 64)
3185 ip6_addr.add_vpp_config()
3187 # ... which are L3-out subnets
3188 l3o_1 = VppGbpSubnet(
3189 self, rd1, "10.0.0.0", 24,
3190 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3192 l3o_1.add_vpp_config()
3195 # an external interface attached to the outside world and the
3198 vlan_100 = VppDot1QSubint(self, self.pg0, 100)
3200 ext_itf = VppGbpExtItf(self, vlan_100, bd1, rd1)
3201 ext_itf.add_vpp_config()
3204 # an unicast vxlan-gbp for inter-RD traffic
3206 vx_tun_l3 = VppGbpVxlanTunnel(
3207 self, 444, rd1.rd_id,
3208 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
3210 vx_tun_l3.add_vpp_config()
3213 # packets destined to unknown addresses in the BVI's subnet
3216 p4 = (Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
3218 IP(src="10.0.0.1", dst="10.0.0.88") /
3219 UDP(sport=1234, dport=1234) /
3221 p6 = (Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
3223 IPv6(src="2001:10::1", dst="2001:10::88") /
3224 UDP(sport=1234, dport=1234) /
3227 rxs = self.send_and_expect(self.pg0, p4 * 1, self.pg7)
3230 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3231 # self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3232 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3233 self.assertEqual(rx[IP].dst, "239.1.1.1")
3234 self.assertEqual(rx[VXLAN].vni, 88)
3235 self.assertTrue(rx[VXLAN].flags.G)
3236 self.assertTrue(rx[VXLAN].flags.Instance)
3237 # policy was applied to the original IP packet
3238 self.assertEqual(rx[VXLAN].gpid, 113)
3239 self.assertTrue(rx[VXLAN].gpflags.A)
3240 self.assertFalse(rx[VXLAN].gpflags.D)
3242 inner = rx[VXLAN].payload
3244 self.assertTrue(inner.haslayer(ARP))
3247 # An external Endpoint
3249 eep = VppGbpEndpoint(self, vlan_100,
3251 "10.0.0.1", "11.0.0.1",
3252 "2001:10::1", "3001::1",
3253 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
3254 eep.add_vpp_config()
3259 rep = VppGbpEndpoint(self, vx_tun_l3,
3261 "10.0.0.101", "11.0.0.101",
3262 "2001:10::101", "3001::101",
3263 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
3265 self.pg7.remote_ip4,
3267 rep.add_vpp_config()
3270 # remote to external
3272 p = (Ether(src=self.pg7.remote_mac,
3273 dst=self.pg7.local_mac) /
3274 IP(src=self.pg7.remote_ip4,
3275 dst=self.pg7.local_ip4) /
3276 UDP(sport=1234, dport=48879) /
3277 VXLAN(vni=444, gpid=113, flags=0x88) /
3278 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
3279 IP(src="10.0.0.101", dst="10.0.0.1") /
3280 UDP(sport=1234, dport=1234) /
3283 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
3286 # A subnet reachable through the external EP
3288 ip_220 = VppIpRoute(self, "10.220.0.0", 24,
3289 [VppRoutePath(eep.ip4.address,
3290 eep.epg.bvi.sw_if_index)],
3291 table_id=t4.table_id)
3292 ip_220.add_vpp_config()
3294 l3o_220 = VppGbpSubnet(
3295 self, rd1, "10.220.0.0", 24,
3296 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3298 l3o_220.add_vpp_config()
3300 p = (Ether(src=self.pg7.remote_mac,
3301 dst=self.pg7.local_mac) /
3302 IP(src=self.pg7.remote_ip4,
3303 dst=self.pg7.local_ip4) /
3304 UDP(sport=1234, dport=48879) /
3305 VXLAN(vni=444, gpid=113, flags=0x88) /
3306 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
3307 IP(src="10.0.0.101", dst="10.220.0.1") /
3308 UDP(sport=1234, dport=1234) /
3311 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
3316 self.pg7.unconfig_ip4()
3319 if __name__ == '__main__':
3320 unittest.main(testRunner=VppTestRunner)