5 from framework import VppTestCase, VppTestRunner, is_skip_aarch64_set, \
7 from vpp_object import VppObject
8 from vpp_neighbor import VppNeighbor
9 from vpp_ip_route import VppIpRoute, VppRoutePath, VppIpTable, \
10 VppIpInterfaceAddress, VppIpInterfaceBind, find_route
11 from vpp_l2 import VppBridgeDomain, VppBridgeDomainPort, \
12 VppBridgeDomainArpEntry, VppL2FibEntry, find_bridge_domain_port
13 from vpp_vxlan_gbp_tunnel import *
14 from vpp_sub_interface import VppDot1QSubint
18 from vpp_papi_provider import L2_PORT_TYPE
19 from vpp_papi import VppEnum
21 from scapy.packet import Raw
22 from scapy.layers.l2 import Ether, ARP, Dot1Q
23 from scapy.layers.inet import IP, UDP
24 from scapy.layers.inet6 import IPv6, ICMPv6ND_NS, ICMPv6NDOptSrcLLAddr, \
26 from scapy.utils6 import in6_getnsma, in6_getnsmac
27 from scapy.layers.vxlan import VXLAN
29 from socket import AF_INET, AF_INET6
30 from scapy.utils import inet_pton, inet_ntop
31 from util import mactobinary
32 from vpp_papi_provider import L2_VTR_OP
35 def find_gbp_endpoint(test, sw_if_index=None, ip=None, mac=None):
37 vip = VppIpAddress(ip)
39 vmac = VppMacAddress(mac)
41 eps = test.vapi.gbp_endpoint_dump()
45 if ep.endpoint.sw_if_index != sw_if_index:
48 for eip in ep.endpoint.ips:
52 if vmac == ep.endpoint.mac:
57 def find_gbp_vxlan(test, vni):
58 ts = test.vapi.gbp_vxlan_tunnel_dump()
60 if t.tunnel.vni == vni:
65 class VppGbpEndpoint(VppObject):
72 return self.vmac.bytes
76 return self.vmac.address
80 return self.itf.remote_mac
100 return [self.ip4, self.ip6]
104 return [self.fip4, self.fip6]
106 def __init__(self, test, itf, epg, recirc, ip4, fip4, ip6, fip6,
116 self._ip4 = VppIpAddress(ip4)
117 self._fip4 = VppIpAddress(fip4)
118 self._ip6 = VppIpAddress(ip6)
119 self._fip6 = VppIpAddress(fip6)
122 self.vmac = VppMacAddress(self.itf.remote_mac)
124 self.vmac = VppMacAddress("00:00:00:00:00:00")
127 self.tun_src = VppIpAddress(tun_src)
128 self.tun_dst = VppIpAddress(tun_dst)
130 def add_vpp_config(self):
131 res = self._test.vapi.gbp_endpoint_add(
132 self.itf.sw_if_index,
133 [self.ip4.encode(), self.ip6.encode()],
137 self.tun_src.encode(),
138 self.tun_dst.encode())
139 self.handle = res.handle
140 self._test.registry.register(self, self._test.logger)
142 def remove_vpp_config(self):
143 self._test.vapi.gbp_endpoint_del(self.handle)
146 return self.object_id()
149 return "gbp-endpoint:[%d==%d:%s:%d]" % (self.handle,
150 self.itf.sw_if_index,
154 def query_vpp_config(self):
155 return find_gbp_endpoint(self._test,
156 self.itf.sw_if_index,
160 class VppGbpRecirc(VppObject):
162 GBP Recirculation Interface
165 def __init__(self, test, epg, recirc, is_ext=False):
171 def add_vpp_config(self):
172 self._test.vapi.gbp_recirc_add_del(
174 self.recirc.sw_if_index,
177 self._test.registry.register(self, self._test.logger)
179 def remove_vpp_config(self):
180 self._test.vapi.gbp_recirc_add_del(
182 self.recirc.sw_if_index,
187 return self.object_id()
190 return "gbp-recirc:[%d]" % (self.recirc.sw_if_index)
192 def query_vpp_config(self):
193 rs = self._test.vapi.gbp_recirc_dump()
195 if r.recirc.sw_if_index == self.recirc.sw_if_index:
200 class VppGbpExtItf(VppObject):
202 GBP ExtItfulation Interface
205 def __init__(self, test, itf, bd, rd):
211 def add_vpp_config(self):
212 self._test.vapi.gbp_ext_itf_add_del(
214 self.itf.sw_if_index,
217 self._test.registry.register(self, self._test.logger)
219 def remove_vpp_config(self):
220 self._test.vapi.gbp_ext_itf_add_del(
222 self.itf.sw_if_index,
227 return self.object_id()
230 return "gbp-ext-itf:[%d]" % (self.itf.sw_if_index)
232 def query_vpp_config(self):
233 rs = self._test.vapi.gbp_ext_itf_dump()
235 if r.ext_itf.sw_if_index == self.itf.sw_if_index:
240 class VppGbpSubnet(VppObject):
244 def __init__(self, test, rd, address, address_len,
245 type, sw_if_index=None, epg=None):
247 self.rd_id = rd.rd_id
248 self.prefix = VppIpPrefix(address, address_len)
250 self.sw_if_index = sw_if_index
253 def add_vpp_config(self):
254 self._test.vapi.gbp_subnet_add_del(
257 self.prefix.encode(),
259 sw_if_index=self.sw_if_index if self.sw_if_index else 0xffffffff,
260 epg_id=self.epg if self.epg else 0xffff)
261 self._test.registry.register(self, self._test.logger)
263 def remove_vpp_config(self):
264 self._test.vapi.gbp_subnet_add_del(
267 self.prefix.encode(),
271 return self.object_id()
274 return "gbp-subnet:[%d-%s]" % (self.rd_id, self.prefix)
276 def query_vpp_config(self):
277 ss = self._test.vapi.gbp_subnet_dump()
279 if s.subnet.rd_id == self.rd_id and \
280 s.subnet.type == self.type and \
281 s.subnet.prefix == self.prefix:
286 class VppGbpEndpointGroup(VppObject):
291 def __init__(self, test, epg, rd, bd, uplink,
292 bvi, bvi_ip4, bvi_ip6=None):
296 self.bvi_ip4 = VppIpAddress(bvi_ip4)
297 self.bvi_ip6 = VppIpAddress(bvi_ip6)
302 def add_vpp_config(self):
303 self._test.vapi.gbp_endpoint_group_add(
307 self.uplink.sw_if_index if self.uplink else INDEX_INVALID)
308 self._test.registry.register(self, self._test.logger)
310 def remove_vpp_config(self):
311 self._test.vapi.gbp_endpoint_group_del(
315 return self.object_id()
318 return "gbp-endpoint-group:[%d]" % (self.epg)
320 def query_vpp_config(self):
321 epgs = self._test.vapi.gbp_endpoint_group_dump()
323 if epg.epg.epg_id == self.epg:
328 class VppGbpBridgeDomain(VppObject):
333 def __init__(self, test, bd, bvi, uu_flood=None, learn=True):
336 self.uu_flood = uu_flood
339 e = VppEnum.vl_api_gbp_bridge_domain_flags_t
341 self.learn = e.GBP_BD_API_FLAG_NONE
343 self.learn = e.GBP_BD_API_FLAG_DO_NOT_LEARN
345 def add_vpp_config(self):
346 self._test.vapi.gbp_bridge_domain_add(
349 self.bvi.sw_if_index,
350 self.uu_flood.sw_if_index if self.uu_flood else INDEX_INVALID)
351 self._test.registry.register(self, self._test.logger)
353 def remove_vpp_config(self):
354 self._test.vapi.gbp_bridge_domain_del(self.bd.bd_id)
357 return self.object_id()
360 return "gbp-bridge-domain:[%d]" % (self.bd.bd_id)
362 def query_vpp_config(self):
363 bds = self._test.vapi.gbp_bridge_domain_dump()
365 if bd.bd.bd_id == self.bd.bd_id:
370 class VppGbpRouteDomain(VppObject):
375 def __init__(self, test, rd_id, t4, t6, ip4_uu=None, ip6_uu=None):
383 def add_vpp_config(self):
384 self._test.vapi.gbp_route_domain_add(
388 self.ip4_uu.sw_if_index if self.ip4_uu else INDEX_INVALID,
389 self.ip6_uu.sw_if_index if self.ip6_uu else INDEX_INVALID)
390 self._test.registry.register(self, self._test.logger)
392 def remove_vpp_config(self):
393 self._test.vapi.gbp_route_domain_del(self.rd_id)
396 return self.object_id()
399 return "gbp-route-domain:[%d]" % (self.rd_id)
401 def query_vpp_config(self):
402 rds = self._test.vapi.gbp_route_domain_dump()
404 if rd.rd.rd_id == self.rd_id:
409 class VppGbpContractNextHop():
410 def __init__(self, mac, bd, ip, rd):
417 return {'ip': self.ip.encode(),
418 'mac': self.mac.encode(),
419 'bd_id': self.bd.bd.bd_id,
420 'rd_id': self.rd.rd_id}
423 class VppGbpContractRule():
424 def __init__(self, action, hash_mode, nhs=[]):
426 self.hash_mode = hash_mode
432 nhs.append(nh.encode())
435 return {'action': self.action,
437 'hash_mode': self.hash_mode,
438 'n_nhs': len(self.nhs),
442 class VppGbpContract(VppObject):
447 def __init__(self, test, src_epg, dst_epg, acl_index, rules=[]):
449 self.acl_index = acl_index
450 self.src_epg = src_epg
451 self.dst_epg = dst_epg
454 def add_vpp_config(self):
457 rules.append(r.encode())
458 self._test.vapi.gbp_contract_add_del(
464 self._test.registry.register(self, self._test.logger)
466 def remove_vpp_config(self):
467 self._test.vapi.gbp_contract_add_del(
475 return self.object_id()
478 return "gbp-contract:[%d:%s:%d]" % (self.src_epg,
482 def query_vpp_config(self):
483 cs = self._test.vapi.gbp_contract_dump()
485 if c.contract.src_epg == self.src_epg \
486 and c.contract.dst_epg == self.dst_epg:
491 class VppGbpVxlanTunnel(VppInterface):
496 def __init__(self, test, vni, bd_rd_id, mode):
497 super(VppGbpVxlanTunnel, self).__init__(test)
500 self.bd_rd_id = bd_rd_id
503 def add_vpp_config(self):
504 r = self._test.vapi.gbp_vxlan_tunnel_add(
508 self.set_sw_if_index(r.sw_if_index)
509 self._test.registry.register(self, self._test.logger)
511 def remove_vpp_config(self):
512 self._test.vapi.gbp_vxlan_tunnel_del(self.vni)
515 return self.object_id()
518 return "gbp-vxlan:%d" % (self.vni)
520 def query_vpp_config(self):
521 return find_gbp_vxlan(self._test, self.vni)
524 class VppGbpAcl(VppObject):
529 def __init__(self, test):
531 self.acl_index = 4294967295
533 def create_rule(self, is_ipv6=0, permit_deny=0, proto=-1,
534 s_prefix=0, s_ip='\x00\x00\x00\x00', sport_from=0,
535 sport_to=65535, d_prefix=0, d_ip='\x00\x00\x00\x00',
536 dport_from=0, dport_to=65535):
537 if proto == -1 or proto == 0:
540 elif proto == 1 or proto == 58:
543 rule = ({'is_permit': permit_deny, 'is_ipv6': is_ipv6, 'proto': proto,
544 'srcport_or_icmptype_first': sport_from,
545 'srcport_or_icmptype_last': sport_to,
546 'src_ip_prefix_len': s_prefix,
548 'dstport_or_icmpcode_first': dport_from,
549 'dstport_or_icmpcode_last': dport_to,
550 'dst_ip_prefix_len': d_prefix,
551 'dst_ip_addr': d_ip})
554 def add_vpp_config(self, rules):
556 reply = self._test.vapi.acl_add_replace(self.acl_index,
559 self.acl_index = reply.acl_index
560 return self.acl_index
562 def remove_vpp_config(self):
563 self._test.vapi.acl_del(self.acl_index)
566 return self.object_id()
569 return "gbp-acl:[%d]" % (self.acl_index)
571 def query_vpp_config(self):
572 cs = self._test.vapi.acl_dump()
574 if c.acl_index == self.acl_index:
579 class TestGBP(VppTestCase):
580 """ GBP Test Case """
583 super(TestGBP, self).setUp()
585 self.create_pg_interfaces(range(9))
586 self.create_loopback_interfaces(8)
588 self.router_mac = VppMacAddress("00:11:22:33:44:55")
590 for i in self.pg_interfaces:
592 for i in self.lo_interfaces:
596 for i in self.pg_interfaces:
599 super(TestGBP, self).tearDown()
601 def send_and_expect_bridged(self, src, tx, dst):
602 rx = self.send_and_expect(src, tx, dst)
605 self.assertEqual(r[Ether].src, tx[0][Ether].src)
606 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
607 self.assertEqual(r[IP].src, tx[0][IP].src)
608 self.assertEqual(r[IP].dst, tx[0][IP].dst)
611 def send_and_expect_bridged6(self, src, tx, dst):
612 rx = self.send_and_expect(src, tx, dst)
615 self.assertEqual(r[Ether].src, tx[0][Ether].src)
616 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
617 self.assertEqual(r[IPv6].src, tx[0][IPv6].src)
618 self.assertEqual(r[IPv6].dst, tx[0][IPv6].dst)
621 def send_and_expect_routed(self, src, tx, dst, src_mac):
622 rx = self.send_and_expect(src, tx, dst)
625 self.assertEqual(r[Ether].src, src_mac)
626 self.assertEqual(r[Ether].dst, dst.remote_mac)
627 self.assertEqual(r[IP].src, tx[0][IP].src)
628 self.assertEqual(r[IP].dst, tx[0][IP].dst)
631 def send_and_expect_natted(self, src, tx, dst, src_ip):
632 rx = self.send_and_expect(src, tx, dst)
635 self.assertEqual(r[Ether].src, tx[0][Ether].src)
636 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
637 self.assertEqual(r[IP].src, src_ip)
638 self.assertEqual(r[IP].dst, tx[0][IP].dst)
641 def send_and_expect_natted6(self, src, tx, dst, src_ip):
642 rx = self.send_and_expect(src, tx, dst)
645 self.assertEqual(r[Ether].src, tx[0][Ether].src)
646 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
647 self.assertEqual(r[IPv6].src, src_ip)
648 self.assertEqual(r[IPv6].dst, tx[0][IPv6].dst)
651 def send_and_expect_unnatted(self, src, tx, dst, dst_ip):
652 rx = self.send_and_expect(src, tx, dst)
655 self.assertEqual(r[Ether].src, tx[0][Ether].src)
656 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
657 self.assertEqual(r[IP].dst, dst_ip)
658 self.assertEqual(r[IP].src, tx[0][IP].src)
661 def send_and_expect_unnatted6(self, src, tx, dst, dst_ip):
662 rx = self.send_and_expect(src, tx, dst)
665 self.assertEqual(r[Ether].src, tx[0][Ether].src)
666 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
667 self.assertEqual(r[IPv6].dst, dst_ip)
668 self.assertEqual(r[IPv6].src, tx[0][IPv6].src)
671 def send_and_expect_double_natted(self, src, tx, dst, src_ip, dst_ip):
672 rx = self.send_and_expect(src, tx, dst)
675 self.assertEqual(r[Ether].src, self.router_mac.address)
676 self.assertEqual(r[Ether].dst, dst.remote_mac)
677 self.assertEqual(r[IP].dst, dst_ip)
678 self.assertEqual(r[IP].src, src_ip)
681 def send_and_expect_double_natted6(self, src, tx, dst, src_ip, dst_ip):
682 rx = self.send_and_expect(src, tx, dst)
685 self.assertEqual(r[Ether].src, self.router_mac.address)
686 self.assertEqual(r[Ether].dst, dst.remote_mac)
687 self.assertEqual(r[IPv6].dst, dst_ip)
688 self.assertEqual(r[IPv6].src, src_ip)
692 """ Group Based Policy """
694 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
699 bd1 = VppBridgeDomain(self, 1)
700 bd2 = VppBridgeDomain(self, 2)
701 bd20 = VppBridgeDomain(self, 20)
705 bd20.add_vpp_config()
707 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0)
708 gbd2 = VppGbpBridgeDomain(self, bd2, self.loop1)
709 gbd20 = VppGbpBridgeDomain(self, bd20, self.loop2)
711 gbd1.add_vpp_config()
712 gbd2.add_vpp_config()
713 gbd20.add_vpp_config()
718 gt4 = VppIpTable(self, 0)
720 gt6 = VppIpTable(self, 0, is_ip6=True)
722 nt4 = VppIpTable(self, 20)
724 nt6 = VppIpTable(self, 20, is_ip6=True)
727 rd0 = VppGbpRouteDomain(self, 0, gt4, gt6, None, None)
728 rd20 = VppGbpRouteDomain(self, 20, nt4, nt6, None, None)
731 rd20.add_vpp_config()
734 # 3 EPGs, 2 of which share a BD.
735 # 2 NAT EPGs, one for floating-IP subnets, the other for internet
737 epgs = [VppGbpEndpointGroup(self, 220, rd0, gbd1, self.pg4,
741 VppGbpEndpointGroup(self, 221, rd0, gbd1, self.pg5,
745 VppGbpEndpointGroup(self, 222, rd0, gbd2, self.pg6,
749 VppGbpEndpointGroup(self, 333, rd20, gbd20, self.pg7,
753 VppGbpEndpointGroup(self, 444, rd20, gbd20, self.pg8,
757 recircs = [VppGbpRecirc(self, epgs[0],
759 VppGbpRecirc(self, epgs[1],
761 VppGbpRecirc(self, epgs[2],
763 VppGbpRecirc(self, epgs[3],
764 self.loop6, is_ext=True),
765 VppGbpRecirc(self, epgs[4],
766 self.loop7, is_ext=True)]
769 recirc_nat = recircs[3]
772 # 4 end-points, 2 in the same subnet, 3 in the same BD
774 eps = [VppGbpEndpoint(self, self.pg0,
776 "10.0.0.1", "11.0.0.1",
777 "2001:10::1", "3001::1"),
778 VppGbpEndpoint(self, self.pg1,
780 "10.0.0.2", "11.0.0.2",
781 "2001:10::2", "3001::2"),
782 VppGbpEndpoint(self, self.pg2,
784 "10.0.1.1", "11.0.0.3",
785 "2001:10:1::1", "3001::3"),
786 VppGbpEndpoint(self, self.pg3,
788 "10.0.2.1", "11.0.0.4",
789 "2001:10:2::1", "3001::4")]
792 # Config related to each of the EPGs
795 # IP config on the BVI interfaces
796 if epg != epgs[1] and epg != epgs[4]:
797 VppIpInterfaceBind(self, epg.bvi, epg.rd.t4).add_vpp_config()
798 VppIpInterfaceBind(self, epg.bvi, epg.rd.t6).add_vpp_config()
799 self.vapi.sw_interface_set_mac_address(
801 self.router_mac.bytes)
803 # The BVIs are NAT inside interfaces
804 self.vapi.nat44_interface_add_del_feature(epg.bvi.sw_if_index,
807 self.vapi.nat66_add_del_interface(epg.bvi.sw_if_index,
811 if_ip4 = VppIpInterfaceAddress(self, epg.bvi, epg.bvi_ip4, 32)
812 if_ip6 = VppIpInterfaceAddress(self, epg.bvi, epg.bvi_ip6, 128)
813 if_ip4.add_vpp_config()
814 if_ip6.add_vpp_config()
816 # EPG uplink interfaces in the RD
817 VppIpInterfaceBind(self, epg.uplink, epg.rd.t4).add_vpp_config()
818 VppIpInterfaceBind(self, epg.uplink, epg.rd.t6).add_vpp_config()
820 # add the BD ARP termination entry for BVI IP
821 epg.bd_arp_ip4 = VppBridgeDomainArpEntry(self, epg.bd.bd,
822 self.router_mac.address,
824 epg.bd_arp_ip6 = VppBridgeDomainArpEntry(self, epg.bd.bd,
825 self.router_mac.address,
827 epg.bd_arp_ip4.add_vpp_config()
828 epg.bd_arp_ip6.add_vpp_config()
833 for recirc in recircs:
834 # EPG's ingress recirculation interface maps to its RD
835 VppIpInterfaceBind(self, recirc.recirc,
836 recirc.epg.rd.t4).add_vpp_config()
837 VppIpInterfaceBind(self, recirc.recirc,
838 recirc.epg.rd.t6).add_vpp_config()
840 self.vapi.nat44_interface_add_del_feature(
841 recirc.recirc.sw_if_index,
844 self.vapi.nat66_add_del_interface(
845 recirc.recirc.sw_if_index,
849 recirc.add_vpp_config()
851 for recirc in recircs:
852 self.assertTrue(find_bridge_domain_port(self,
853 recirc.epg.bd.bd.bd_id,
854 recirc.recirc.sw_if_index))
857 self.pg_enable_capture(self.pg_interfaces)
860 # routes to the endpoints. We need these since there are no
861 # adj-fibs due to the fact the the BVI address has /32 and
862 # the subnet is not attached.
864 for (ip, fip) in zip(ep.ips, ep.fips):
865 # Add static mappings for each EP from the 10/8 to 11/8 network
867 self.vapi.nat44_add_del_static_mapping(ip.bytes,
872 self.vapi.nat66_add_del_static_mapping(ip.bytes,
879 self.logger.info(self.vapi.cli("sh gbp endpoint"))
881 # ... results in a Gratuitous ARP/ND on the EPG's uplink
882 rx = ep.epg.uplink.get_capture(len(ep.ips), timeout=0.2)
884 for ii, ip in enumerate(ep.ips):
888 self.assertTrue(p.haslayer(ICMPv6ND_NA))
889 self.assertEqual(p[ICMPv6ND_NA].tgt, ip.address)
891 self.assertTrue(p.haslayer(ARP))
892 self.assertEqual(p[ARP].psrc, ip.address)
893 self.assertEqual(p[ARP].pdst, ip.address)
895 # add the BD ARP termination entry for floating IP
897 ba = VppBridgeDomainArpEntry(self, epg_nat.bd.bd, ep.mac, fip)
900 # floating IPs route via EPG recirc
901 r = VppIpRoute(self, fip.address, fip.length,
902 [VppRoutePath(fip.address,
903 ep.recirc.recirc.sw_if_index,
905 proto=fip.dpo_proto)],
910 # L2 FIB entries in the NAT EPG BD to bridge the packets from
911 # the outside direct to the internal EPG
912 lf = VppL2FibEntry(self, epg_nat.bd.bd, ep.mac,
913 ep.recirc.recirc, bvi_mac=0)
917 # ARP packets for unknown IP are sent to the EPG uplink
919 pkt_arp = (Ether(dst="ff:ff:ff:ff:ff:ff",
920 src=self.pg0.remote_mac) /
922 hwdst="ff:ff:ff:ff:ff:ff",
923 hwsrc=self.pg0.remote_mac,
927 self.vapi.cli("clear trace")
928 self.pg0.add_stream(pkt_arp)
930 self.pg_enable_capture(self.pg_interfaces)
933 rxd = epgs[0].uplink.get_capture(1)
936 # ARP/ND packets get a response
938 pkt_arp = (Ether(dst="ff:ff:ff:ff:ff:ff",
939 src=self.pg0.remote_mac) /
941 hwdst="ff:ff:ff:ff:ff:ff",
942 hwsrc=self.pg0.remote_mac,
943 pdst=epgs[0].bvi_ip4.address,
944 psrc=eps[0].ip4.address))
946 self.send_and_expect(self.pg0, [pkt_arp], self.pg0)
948 nsma = in6_getnsma(inet_pton(AF_INET6, eps[0].ip6.address))
949 d = inet_ntop(AF_INET6, nsma)
950 pkt_nd = (Ether(dst=in6_getnsmac(nsma),
951 src=self.pg0.remote_mac) /
952 IPv6(dst=d, src=eps[0].ip6.address) /
953 ICMPv6ND_NS(tgt=epgs[0].bvi_ip6.address) /
954 ICMPv6NDOptSrcLLAddr(lladdr=self.pg0.remote_mac))
955 self.send_and_expect(self.pg0, [pkt_nd], self.pg0)
958 # broadcast packets are flooded
960 pkt_bcast = (Ether(dst="ff:ff:ff:ff:ff:ff",
961 src=self.pg0.remote_mac) /
962 IP(src=eps[0].ip4.address, dst="232.1.1.1") /
963 UDP(sport=1234, dport=1234) /
966 self.vapi.cli("clear trace")
967 self.pg0.add_stream(pkt_bcast)
969 self.pg_enable_capture(self.pg_interfaces)
972 rxd = eps[1].itf.get_capture(1)
973 self.assertEqual(rxd[0][Ether].dst, pkt_bcast[Ether].dst)
974 rxd = epgs[0].uplink.get_capture(1)
975 self.assertEqual(rxd[0][Ether].dst, pkt_bcast[Ether].dst)
978 # packets to non-local L3 destinations dropped
980 pkt_intra_epg_220_ip4 = (Ether(src=self.pg0.remote_mac,
981 dst=self.router_mac.address) /
982 IP(src=eps[0].ip4.address,
984 UDP(sport=1234, dport=1234) /
986 pkt_inter_epg_222_ip4 = (Ether(src=self.pg0.remote_mac,
987 dst=self.router_mac.address) /
988 IP(src=eps[0].ip4.address,
990 UDP(sport=1234, dport=1234) /
993 self.send_and_assert_no_replies(self.pg0, pkt_intra_epg_220_ip4 * 65)
995 pkt_inter_epg_222_ip6 = (Ether(src=self.pg0.remote_mac,
996 dst=self.router_mac.address) /
997 IPv6(src=eps[0].ip6.address,
999 UDP(sport=1234, dport=1234) /
1001 self.send_and_assert_no_replies(self.pg0, pkt_inter_epg_222_ip6 * 65)
1004 # Add the subnet routes
1007 self, rd0, "10.0.0.0", 24,
1008 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1010 self, rd0, "10.0.1.0", 24,
1011 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1013 self, rd0, "10.0.2.0", 24,
1014 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1016 self, rd0, "2001:10::1", 64,
1017 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1019 self, rd0, "2001:10:1::1", 64,
1020 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1022 self, rd0, "2001:10:2::1", 64,
1023 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1024 s41.add_vpp_config()
1025 s42.add_vpp_config()
1026 s43.add_vpp_config()
1027 s61.add_vpp_config()
1028 s62.add_vpp_config()
1029 s63.add_vpp_config()
1031 self.send_and_expect_bridged(eps[0].itf,
1032 pkt_intra_epg_220_ip4 * 65,
1034 self.send_and_expect_bridged(eps[0].itf,
1035 pkt_inter_epg_222_ip4 * 65,
1037 self.send_and_expect_bridged6(eps[0].itf,
1038 pkt_inter_epg_222_ip6 * 65,
1041 self.logger.info(self.vapi.cli("sh ip fib 11.0.0.2"))
1042 self.logger.info(self.vapi.cli("sh gbp endpoint-group"))
1043 self.logger.info(self.vapi.cli("sh gbp endpoint"))
1044 self.logger.info(self.vapi.cli("sh gbp recirc"))
1045 self.logger.info(self.vapi.cli("sh int"))
1046 self.logger.info(self.vapi.cli("sh int addr"))
1047 self.logger.info(self.vapi.cli("sh int feat loop6"))
1048 self.logger.info(self.vapi.cli("sh vlib graph ip4-gbp-src-classify"))
1049 self.logger.info(self.vapi.cli("sh int feat loop3"))
1050 self.logger.info(self.vapi.cli("sh int feat pg0"))
1053 # Packet destined to unknown unicast is sent on the epg uplink ...
1055 pkt_intra_epg_220_to_uplink = (Ether(src=self.pg0.remote_mac,
1056 dst="00:00:00:33:44:55") /
1057 IP(src=eps[0].ip4.address,
1059 UDP(sport=1234, dport=1234) /
1062 self.send_and_expect_bridged(eps[0].itf,
1063 pkt_intra_epg_220_to_uplink * 65,
1065 # ... and nowhere else
1066 self.pg1.get_capture(0, timeout=0.1)
1067 self.pg1.assert_nothing_captured(remark="Flood onto other VMS")
1069 pkt_intra_epg_221_to_uplink = (Ether(src=self.pg2.remote_mac,
1070 dst="00:00:00:33:44:66") /
1071 IP(src=eps[0].ip4.address,
1073 UDP(sport=1234, dport=1234) /
1076 self.send_and_expect_bridged(eps[2].itf,
1077 pkt_intra_epg_221_to_uplink * 65,
1081 # Packets from the uplink are forwarded in the absence of a contract
1083 pkt_intra_epg_220_from_uplink = (Ether(src="00:00:00:33:44:55",
1084 dst=self.pg0.remote_mac) /
1085 IP(src=eps[0].ip4.address,
1087 UDP(sport=1234, dport=1234) /
1090 self.send_and_expect_bridged(self.pg4,
1091 pkt_intra_epg_220_from_uplink * 65,
1095 # in the absence of policy, endpoints in the same EPG
1098 pkt_intra_epg = (Ether(src=self.pg0.remote_mac,
1099 dst=self.pg1.remote_mac) /
1100 IP(src=eps[0].ip4.address,
1101 dst=eps[1].ip4.address) /
1102 UDP(sport=1234, dport=1234) /
1105 self.send_and_expect_bridged(self.pg0, pkt_intra_epg * 65, self.pg1)
1108 # in the abscense of policy, endpoints in the different EPG
1109 # cannot communicate
1111 pkt_inter_epg_220_to_221 = (Ether(src=self.pg0.remote_mac,
1112 dst=self.pg2.remote_mac) /
1113 IP(src=eps[0].ip4.address,
1114 dst=eps[2].ip4.address) /
1115 UDP(sport=1234, dport=1234) /
1117 pkt_inter_epg_221_to_220 = (Ether(src=self.pg2.remote_mac,
1118 dst=self.pg0.remote_mac) /
1119 IP(src=eps[2].ip4.address,
1120 dst=eps[0].ip4.address) /
1121 UDP(sport=1234, dport=1234) /
1123 pkt_inter_epg_220_to_222 = (Ether(src=self.pg0.remote_mac,
1124 dst=self.router_mac.address) /
1125 IP(src=eps[0].ip4.address,
1126 dst=eps[3].ip4.address) /
1127 UDP(sport=1234, dport=1234) /
1130 self.send_and_assert_no_replies(eps[0].itf,
1131 pkt_inter_epg_220_to_221 * 65)
1132 self.send_and_assert_no_replies(eps[0].itf,
1133 pkt_inter_epg_220_to_222 * 65)
1136 # A uni-directional contract from EPG 220 -> 221
1138 acl = VppGbpAcl(self)
1139 rule = acl.create_rule(permit_deny=1, proto=17)
1140 rule2 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
1141 acl_index = acl.add_vpp_config([rule, rule2])
1142 c1 = VppGbpContract(
1143 self, 220, 221, acl_index,
1144 [VppGbpContractRule(
1145 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1148 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1152 self.send_and_expect_bridged(eps[0].itf,
1153 pkt_inter_epg_220_to_221 * 65,
1155 self.send_and_assert_no_replies(eps[0].itf,
1156 pkt_inter_epg_220_to_222 * 65)
1159 # contract for the return direction
1161 c2 = VppGbpContract(
1162 self, 221, 220, acl_index,
1163 [VppGbpContractRule(
1164 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1167 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1172 self.send_and_expect_bridged(eps[0].itf,
1173 pkt_inter_epg_220_to_221 * 65,
1175 self.send_and_expect_bridged(eps[2].itf,
1176 pkt_inter_epg_221_to_220 * 65,
1180 # check that inter group is still disabled for the groups
1181 # not in the contract.
1183 self.send_and_assert_no_replies(eps[0].itf,
1184 pkt_inter_epg_220_to_222 * 65)
1187 # A uni-directional contract from EPG 220 -> 222 'L3 routed'
1189 c3 = VppGbpContract(
1190 self, 220, 222, acl_index,
1191 [VppGbpContractRule(
1192 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1195 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1200 self.logger.info(self.vapi.cli("sh gbp contract"))
1202 self.send_and_expect_routed(eps[0].itf,
1203 pkt_inter_epg_220_to_222 * 65,
1205 self.router_mac.address)
1208 # remove both contracts, traffic stops in both directions
1210 c2.remove_vpp_config()
1211 c1.remove_vpp_config()
1212 c3.remove_vpp_config()
1213 acl.remove_vpp_config()
1215 self.send_and_assert_no_replies(eps[2].itf,
1216 pkt_inter_epg_221_to_220 * 65)
1217 self.send_and_assert_no_replies(eps[0].itf,
1218 pkt_inter_epg_220_to_221 * 65)
1219 self.send_and_expect_bridged(eps[0].itf,
1224 # EPs to the outside world
1227 # in the EP's RD an external subnet via the NAT EPG's recirc
1229 self, rd0, "0.0.0.0", 0,
1230 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1231 sw_if_index=recirc_nat.recirc.sw_if_index,
1234 self, rd0, "11.0.0.0", 8,
1235 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1236 sw_if_index=recirc_nat.recirc.sw_if_index,
1238 se16 = VppGbpSubnet(
1240 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1241 sw_if_index=recirc_nat.recirc.sw_if_index,
1243 # in the NAT RD an external subnet via the NAT EPG's uplink
1245 self, rd20, "0.0.0.0", 0,
1246 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1247 sw_if_index=epg_nat.uplink.sw_if_index,
1249 se36 = VppGbpSubnet(
1250 self, rd20, "::", 0,
1251 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1252 sw_if_index=epg_nat.uplink.sw_if_index,
1255 self, rd20, "11.0.0.0", 8,
1256 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1257 sw_if_index=epg_nat.uplink.sw_if_index,
1259 se1.add_vpp_config()
1260 se2.add_vpp_config()
1261 se16.add_vpp_config()
1262 se3.add_vpp_config()
1263 se36.add_vpp_config()
1264 se4.add_vpp_config()
1266 self.logger.info(self.vapi.cli("sh ip fib 0.0.0.0/0"))
1267 self.logger.info(self.vapi.cli("sh ip fib 11.0.0.1"))
1268 self.logger.info(self.vapi.cli("sh ip6 fib ::/0"))
1269 self.logger.info(self.vapi.cli("sh ip6 fib %s" %
1273 # From an EP to an outside addess: IN2OUT
1275 pkt_inter_epg_220_to_global = (Ether(src=self.pg0.remote_mac,
1276 dst=self.router_mac.address) /
1277 IP(src=eps[0].ip4.address,
1279 UDP(sport=1234, dport=1234) /
1283 self.send_and_assert_no_replies(eps[0].itf,
1284 pkt_inter_epg_220_to_global * 65)
1286 acl2 = VppGbpAcl(self)
1287 rule = acl2.create_rule(permit_deny=1, proto=17, sport_from=1234,
1288 sport_to=1234, dport_from=1234, dport_to=1234)
1289 rule2 = acl2.create_rule(is_ipv6=1, permit_deny=1, proto=17,
1290 sport_from=1234, sport_to=1234,
1291 dport_from=1234, dport_to=1234)
1293 acl_index2 = acl2.add_vpp_config([rule, rule2])
1294 c4 = VppGbpContract(
1295 self, 220, 333, acl_index2,
1296 [VppGbpContractRule(
1297 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1300 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1305 self.send_and_expect_natted(eps[0].itf,
1306 pkt_inter_epg_220_to_global * 65,
1308 eps[0].fip4.address)
1310 pkt_inter_epg_220_to_global = (Ether(src=self.pg0.remote_mac,
1311 dst=self.router_mac.address) /
1312 IPv6(src=eps[0].ip6.address,
1314 UDP(sport=1234, dport=1234) /
1317 self.send_and_expect_natted6(self.pg0,
1318 pkt_inter_epg_220_to_global * 65,
1320 eps[0].fip6.address)
1323 # From a global address to an EP: OUT2IN
1325 pkt_inter_epg_220_from_global = (Ether(src=self.router_mac.address,
1326 dst=self.pg0.remote_mac) /
1327 IP(dst=eps[0].fip4.address,
1329 UDP(sport=1234, dport=1234) /
1332 self.send_and_assert_no_replies(self.pg7,
1333 pkt_inter_epg_220_from_global * 65)
1335 c5 = VppGbpContract(
1336 self, 333, 220, acl_index2,
1337 [VppGbpContractRule(
1338 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1341 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1346 self.send_and_expect_unnatted(self.pg7,
1347 pkt_inter_epg_220_from_global * 65,
1351 pkt_inter_epg_220_from_global = (Ether(src=self.router_mac.address,
1352 dst=self.pg0.remote_mac) /
1353 IPv6(dst=eps[0].fip6.address,
1355 UDP(sport=1234, dport=1234) /
1358 self.send_and_expect_unnatted6(self.pg7,
1359 pkt_inter_epg_220_from_global * 65,
1364 # From a local VM to another local VM using resp. public addresses:
1367 pkt_intra_epg_220_global = (Ether(src=self.pg0.remote_mac,
1368 dst=self.router_mac.address) /
1369 IP(src=eps[0].ip4.address,
1370 dst=eps[1].fip4.address) /
1371 UDP(sport=1234, dport=1234) /
1374 self.send_and_expect_double_natted(eps[0].itf,
1375 pkt_intra_epg_220_global * 65,
1377 eps[0].fip4.address,
1380 pkt_intra_epg_220_global = (Ether(src=self.pg0.remote_mac,
1381 dst=self.router_mac.address) /
1382 IPv6(src=eps[0].ip6.address,
1383 dst=eps[1].fip6.address) /
1384 UDP(sport=1234, dport=1234) /
1387 self.send_and_expect_double_natted6(eps[0].itf,
1388 pkt_intra_epg_220_global * 65,
1390 eps[0].fip6.address,
1397 # del static mappings for each EP from the 10/8 to 11/8 network
1398 self.vapi.nat44_add_del_static_mapping(ep.ip4.bytes,
1403 self.vapi.nat66_add_del_static_mapping(ep.ip6.bytes,
1409 # IP config on the BVI interfaces
1410 if epg != epgs[0] and epg != epgs[3]:
1411 self.vapi.nat44_interface_add_del_feature(epg.bvi.sw_if_index,
1414 self.vapi.nat66_add_del_interface(epg.bvi.sw_if_index,
1418 for recirc in recircs:
1419 self.vapi.nat44_interface_add_del_feature(
1420 recirc.recirc.sw_if_index,
1423 self.vapi.nat66_add_del_interface(
1424 recirc.recirc.sw_if_index,
1428 def wait_for_ep_timeout(self, sw_if_index=None, ip=None, mac=None,
1429 n_tries=100, s_time=1):
1431 if not find_gbp_endpoint(self, sw_if_index, ip, mac):
1433 n_tries = n_tries - 1
1435 self.assertFalse(find_gbp_endpoint(self, sw_if_index, ip, mac))
1438 def test_gbp_learn_l2(self):
1439 """ GBP L2 Endpoint Learning """
1441 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
1442 learnt = [{'mac': '00:00:11:11:11:01',
1444 'ip6': '2001:10::2'},
1445 {'mac': '00:00:11:11:11:02',
1447 'ip6': '2001:10::3'}]
1450 # lower the inactive threshold so these tests pass in a
1451 # reasonable amount of time
1453 self.vapi.gbp_endpoint_learn_set_inactive_threshold(1)
1458 gt4 = VppIpTable(self, 1)
1459 gt4.add_vpp_config()
1460 gt6 = VppIpTable(self, 1, is_ip6=True)
1461 gt6.add_vpp_config()
1463 rd1 = VppGbpRouteDomain(self, 1, gt4, gt6)
1464 rd1.add_vpp_config()
1467 # Pg2 hosts the vxlan tunnel, hosts on pg2 to act as TEPs
1468 # Pg3 hosts the IP4 UU-flood VXLAN tunnel
1469 # Pg4 hosts the IP6 UU-flood VXLAN tunnel
1471 self.pg2.config_ip4()
1472 self.pg2.resolve_arp()
1473 self.pg2.generate_remote_hosts(4)
1474 self.pg2.configure_ipv4_neighbors()
1475 self.pg3.config_ip4()
1476 self.pg3.resolve_arp()
1477 self.pg4.config_ip4()
1478 self.pg4.resolve_arp()
1481 # a GBP bridge domain with a BVI and a UU-flood interface
1483 bd1 = VppBridgeDomain(self, 1)
1484 bd1.add_vpp_config()
1485 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0, self.pg3)
1486 gbd1.add_vpp_config()
1488 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1489 self.logger.info(self.vapi.cli("sh gbp bridge"))
1491 # ... and has a /32 applied
1492 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
1493 ip_addr.add_vpp_config()
1496 # The Endpoint-group in which we are learning endpoints
1498 epg_220 = VppGbpEndpointGroup(self, 220, rd1, gbd1,
1502 epg_220.add_vpp_config()
1503 epg_330 = VppGbpEndpointGroup(self, 330, rd1, gbd1,
1507 epg_330.add_vpp_config()
1510 # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
1513 vx_tun_l2_1 = VppGbpVxlanTunnel(
1514 self, 99, bd1.bd_id,
1515 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L2)
1516 vx_tun_l2_1.add_vpp_config()
1519 # A static endpoint that the learnt endpoints are trying to
1522 ep = VppGbpEndpoint(self, self.pg0,
1524 "10.0.0.127", "11.0.0.127",
1525 "2001:10::1", "3001::1")
1528 self.assertTrue(find_route(self, ep.ip4.address, 32, table_id=1))
1530 # a packet with an sclass from an unknwon EPG
1531 p = (Ether(src=self.pg2.remote_mac,
1532 dst=self.pg2.local_mac) /
1533 IP(src=self.pg2.remote_hosts[0].ip4,
1534 dst=self.pg2.local_ip4) /
1535 UDP(sport=1234, dport=48879) /
1536 VXLAN(vni=99, gpid=88, flags=0x88) /
1537 Ether(src=learnt[0]["mac"], dst=ep.mac) /
1538 IP(src=learnt[0]["ip"], dst=ep.ip4.address) /
1539 UDP(sport=1234, dport=1234) /
1542 self.send_and_assert_no_replies(self.pg2, p)
1545 # we should not have learnt a new tunnel endpoint, since
1546 # the EPG was not learnt.
1548 self.assertEqual(INDEX_INVALID,
1549 find_vxlan_gbp_tunnel(self,
1551 self.pg2.remote_hosts[0].ip4,
1554 # epg is not learnt, becasue the EPG is unknwon
1555 self.assertEqual(len(self.vapi.gbp_endpoint_dump()), 1)
1557 for ii, l in enumerate(learnt):
1558 # a packet with an sclass from a knwon EPG
1559 # arriving on an unknown TEP
1560 p = (Ether(src=self.pg2.remote_mac,
1561 dst=self.pg2.local_mac) /
1562 IP(src=self.pg2.remote_hosts[1].ip4,
1563 dst=self.pg2.local_ip4) /
1564 UDP(sport=1234, dport=48879) /
1565 VXLAN(vni=99, gpid=220, flags=0x88) /
1566 Ether(src=l['mac'], dst=ep.mac) /
1567 IP(src=l['ip'], dst=ep.ip4.address) /
1568 UDP(sport=1234, dport=1234) /
1571 rx = self.send_and_expect(self.pg2, [p], self.pg0)
1574 tep1_sw_if_index = find_vxlan_gbp_tunnel(
1577 self.pg2.remote_hosts[1].ip4,
1579 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
1582 # the EP is learnt via the learnt TEP
1583 # both from its MAC and its IP
1585 self.assertTrue(find_gbp_endpoint(self,
1586 vx_tun_l2_1.sw_if_index,
1588 self.assertTrue(find_gbp_endpoint(self,
1589 vx_tun_l2_1.sw_if_index,
1592 self.logger.info(self.vapi.cli("show gbp endpoint"))
1593 self.logger.info(self.vapi.cli("show gbp vxlan"))
1594 self.logger.info(self.vapi.cli("show vxlan-gbp tunnel"))
1597 # If we sleep for the threshold time, the learnt endpoints should
1601 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1605 # repeat. the do not learn bit is set so the EPs are not learnt
1608 # a packet with an sclass from a knwon EPG
1609 p = (Ether(src=self.pg2.remote_mac,
1610 dst=self.pg2.local_mac) /
1611 IP(src=self.pg2.remote_hosts[1].ip4,
1612 dst=self.pg2.local_ip4) /
1613 UDP(sport=1234, dport=48879) /
1614 VXLAN(vni=99, gpid=220, flags=0x88, gpflags="D") /
1615 Ether(src=l['mac'], dst=ep.mac) /
1616 IP(src=l['ip'], dst=ep.ip4.address) /
1617 UDP(sport=1234, dport=1234) /
1620 rx = self.send_and_expect(self.pg2, p*65, self.pg0)
1623 self.assertFalse(find_gbp_endpoint(self,
1624 vx_tun_l2_1.sw_if_index,
1631 # a packet with an sclass from a knwon EPG
1632 p = (Ether(src=self.pg2.remote_mac,
1633 dst=self.pg2.local_mac) /
1634 IP(src=self.pg2.remote_hosts[1].ip4,
1635 dst=self.pg2.local_ip4) /
1636 UDP(sport=1234, dport=48879) /
1637 VXLAN(vni=99, gpid=220, flags=0x88) /
1638 Ether(src=l['mac'], dst=ep.mac) /
1639 IP(src=l['ip'], dst=ep.ip4.address) /
1640 UDP(sport=1234, dport=1234) /
1643 rx = self.send_and_expect(self.pg2, p*65, self.pg0)
1645 self.assertTrue(find_gbp_endpoint(self,
1646 vx_tun_l2_1.sw_if_index,
1650 # Static EP replies to dynamics
1652 self.logger.info(self.vapi.cli("sh l2fib bd_id 1"))
1654 p = (Ether(src=ep.mac, dst=l['mac']) /
1655 IP(dst=l['ip'], src=ep.ip4.address) /
1656 UDP(sport=1234, dport=1234) /
1659 rxs = self.send_and_expect(self.pg0, p * 17, self.pg2)
1662 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
1663 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
1664 self.assertEqual(rx[UDP].dport, 48879)
1665 # the UDP source port is a random value for hashing
1666 self.assertEqual(rx[VXLAN].gpid, 220)
1667 self.assertEqual(rx[VXLAN].vni, 99)
1668 self.assertTrue(rx[VXLAN].flags.G)
1669 self.assertTrue(rx[VXLAN].flags.Instance)
1670 self.assertTrue(rx[VXLAN].gpflags.A)
1671 self.assertFalse(rx[VXLAN].gpflags.D)
1674 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1678 # repeat in the other EPG
1679 # there's no contract between 220 and 330, but the A-bit is set
1680 # so the packet is cleared for delivery
1683 # a packet with an sclass from a knwon EPG
1684 p = (Ether(src=self.pg2.remote_mac,
1685 dst=self.pg2.local_mac) /
1686 IP(src=self.pg2.remote_hosts[1].ip4,
1687 dst=self.pg2.local_ip4) /
1688 UDP(sport=1234, dport=48879) /
1689 VXLAN(vni=99, gpid=330, flags=0x88, gpflags='A') /
1690 Ether(src=l['mac'], dst=ep.mac) /
1691 IP(src=l['ip'], dst=ep.ip4.address) /
1692 UDP(sport=1234, dport=1234) /
1695 rx = self.send_and_expect(self.pg2, p*65, self.pg0)
1697 self.assertTrue(find_gbp_endpoint(self,
1698 vx_tun_l2_1.sw_if_index,
1702 # static EP cannot reach the learnt EPs since there is no contract
1703 # only test 1 EP as the others could timeout
1705 p = (Ether(src=ep.mac, dst=l['mac']) /
1706 IP(dst=learnt[0]['ip'], src=ep.ip4.address) /
1707 UDP(sport=1234, dport=1234) /
1710 self.send_and_assert_no_replies(self.pg0, [p])
1713 # refresh the entries after the check for no replies above
1716 # a packet with an sclass from a knwon EPG
1717 p = (Ether(src=self.pg2.remote_mac,
1718 dst=self.pg2.local_mac) /
1719 IP(src=self.pg2.remote_hosts[1].ip4,
1720 dst=self.pg2.local_ip4) /
1721 UDP(sport=1234, dport=48879) /
1722 VXLAN(vni=99, gpid=330, flags=0x88, gpflags='A') /
1723 Ether(src=l['mac'], dst=ep.mac) /
1724 IP(src=l['ip'], dst=ep.ip4.address) /
1725 UDP(sport=1234, dport=1234) /
1728 rx = self.send_and_expect(self.pg2, p*65, self.pg0)
1730 self.assertTrue(find_gbp_endpoint(self,
1731 vx_tun_l2_1.sw_if_index,
1735 # Add the contract so they can talk
1737 acl = VppGbpAcl(self)
1738 rule = acl.create_rule(permit_deny=1, proto=17)
1739 rule2 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
1740 acl_index = acl.add_vpp_config([rule, rule2])
1741 c1 = VppGbpContract(
1742 self, 220, 330, acl_index,
1743 [VppGbpContractRule(
1744 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1747 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1753 p = (Ether(src=ep.mac, dst=l['mac']) /
1754 IP(dst=l['ip'], src=ep.ip4.address) /
1755 UDP(sport=1234, dport=1234) /
1758 self.send_and_expect(self.pg0, [p], self.pg2)
1761 # send UU packets from the local EP
1763 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1764 self.logger.info(self.vapi.cli("sh gbp bridge"))
1765 p_uu = (Ether(src=ep.mac, dst="00:11:11:11:11:11") /
1766 IP(dst="10.0.0.133", src=ep.ip4.address) /
1767 UDP(sport=1234, dport=1234) /
1769 rxs = self.send_and_expect(ep.itf, [p_uu], gbd1.uu_flood)
1772 # Add a mcast destination VXLAN-GBP tunnel for B&M traffic
1774 tun_bm = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
1777 tun_bm.add_vpp_config()
1778 bp_bm = VppBridgeDomainPort(self, bd1, tun_bm,
1779 port_type=L2_PORT_TYPE.NORMAL)
1780 bp_bm.add_vpp_config()
1782 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1784 p_bm = (Ether(src=ep.mac, dst="ff:ff:ff:ff:ff:ff") /
1785 IP(dst="10.0.0.133", src=ep.ip4.address) /
1786 UDP(sport=1234, dport=1234) /
1788 rxs = self.send_and_expect_only(ep.itf, [p_bm], tun_bm.mcast_itf)
1791 # Check v6 Endpoints
1794 # a packet with an sclass from a knwon EPG
1795 p = (Ether(src=self.pg2.remote_mac,
1796 dst=self.pg2.local_mac) /
1797 IP(src=self.pg2.remote_hosts[1].ip4,
1798 dst=self.pg2.local_ip4) /
1799 UDP(sport=1234, dport=48879) /
1800 VXLAN(vni=99, gpid=330, flags=0x88, gpflags='A') /
1801 Ether(src=l['mac'], dst=ep.mac) /
1802 IPv6(src=l['ip6'], dst=ep.ip6.address) /
1803 UDP(sport=1234, dport=1234) /
1806 rx = self.send_and_expect(self.pg2, p*65, self.pg0)
1808 self.assertTrue(find_gbp_endpoint(self,
1809 vx_tun_l2_1.sw_if_index,
1813 # L3 Endpoint Learning
1814 # - configured on the bridge's BVI
1821 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1824 self.pg2.unconfig_ip4()
1825 self.pg3.unconfig_ip4()
1826 self.pg4.unconfig_ip4()
1828 self.logger.info(self.vapi.cli("sh int"))
1829 self.logger.info(self.vapi.cli("sh gbp vxlan"))
1831 @unittest.skipIf(is_skip_aarch64_set() and is_platform_aarch64(),
1832 "test doesn't work on aarch64")
1833 def test_gbp_learn_vlan_l2(self):
1834 """ GBP L2 Endpoint w/ VLANs"""
1836 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
1837 learnt = [{'mac': '00:00:11:11:11:01',
1839 'ip6': '2001:10::2'},
1840 {'mac': '00:00:11:11:11:02',
1842 'ip6': '2001:10::3'}]
1845 # lower the inactive threshold so these tests pass in a
1846 # reasonable amount of time
1848 self.vapi.gbp_endpoint_learn_set_inactive_threshold(1)
1853 gt4 = VppIpTable(self, 1)
1854 gt4.add_vpp_config()
1855 gt6 = VppIpTable(self, 1, is_ip6=True)
1856 gt6.add_vpp_config()
1858 rd1 = VppGbpRouteDomain(self, 1, gt4, gt6)
1859 rd1.add_vpp_config()
1862 # Pg2 hosts the vxlan tunnel, hosts on pg2 to act as TEPs
1864 self.pg2.config_ip4()
1865 self.pg2.resolve_arp()
1866 self.pg2.generate_remote_hosts(4)
1867 self.pg2.configure_ipv4_neighbors()
1868 self.pg3.config_ip4()
1869 self.pg3.resolve_arp()
1872 # The EP will be on a vlan sub-interface
1874 vlan_11 = VppDot1QSubint(self, self.pg0, 11)
1876 self.vapi.sw_interface_set_l2_tag_rewrite(vlan_11.sw_if_index,
1880 bd_uu_fwd = VppVxlanGbpTunnel(self, self.pg3.local_ip4,
1881 self.pg3.remote_ip4, 116)
1882 bd_uu_fwd.add_vpp_config()
1885 # a GBP bridge domain with a BVI and a UU-flood interface
1886 # The BD is marked as do not learn, so no endpoints are ever
1887 # learnt in this BD.
1889 bd1 = VppBridgeDomain(self, 1)
1890 bd1.add_vpp_config()
1891 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0, bd_uu_fwd,
1893 gbd1.add_vpp_config()
1895 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1896 self.logger.info(self.vapi.cli("sh gbp bridge"))
1898 # ... and has a /32 applied
1899 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
1900 ip_addr.add_vpp_config()
1903 # The Endpoint-group in which we are learning endpoints
1905 epg_220 = VppGbpEndpointGroup(self, 220, rd1, gbd1,
1909 epg_220.add_vpp_config()
1912 # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
1915 vx_tun_l2_1 = VppGbpVxlanTunnel(
1916 self, 99, bd1.bd_id,
1917 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L2)
1918 vx_tun_l2_1.add_vpp_config()
1921 # A static endpoint that the learnt endpoints are trying to
1924 ep = VppGbpEndpoint(self, vlan_11,
1926 "10.0.0.127", "11.0.0.127",
1927 "2001:10::1", "3001::1")
1930 self.assertTrue(find_route(self, ep.ip4.address, 32, table_id=1))
1933 # Send to the static EP
1935 for ii, l in enumerate(learnt):
1936 # a packet with an sclass from a knwon EPG
1937 # arriving on an unknown TEP
1938 p = (Ether(src=self.pg2.remote_mac,
1939 dst=self.pg2.local_mac) /
1940 IP(src=self.pg2.remote_hosts[1].ip4,
1941 dst=self.pg2.local_ip4) /
1942 UDP(sport=1234, dport=48879) /
1943 VXLAN(vni=99, gpid=220, flags=0x88) /
1944 Ether(src=l['mac'], dst=ep.mac) /
1945 IP(src=l['ip'], dst=ep.ip4.address) /
1946 UDP(sport=1234, dport=1234) /
1949 rxs = self.send_and_expect(self.pg2, [p], self.pg0)
1952 # packet to EP has the EP's vlan tag
1955 self.assertEqual(rx[Dot1Q].vlan, 11)
1958 # the EP is not learnt since the BD setting prevents it
1961 self.assertFalse(find_gbp_endpoint(self,
1962 vx_tun_l2_1.sw_if_index,
1964 self.assertEqual(INDEX_INVALID,
1965 find_vxlan_gbp_tunnel(
1968 self.pg2.remote_hosts[1].ip4,
1971 self.assertEqual(len(self.vapi.gbp_endpoint_dump()), 1)
1975 # we didn't learn the remotes so they are sent to the UU-fwd
1978 p = (Ether(src=ep.mac, dst=l['mac']) /
1980 IP(dst=l['ip'], src=ep.ip4.address) /
1981 UDP(sport=1234, dport=1234) /
1984 rxs = self.send_and_expect(self.pg0, p * 17, self.pg3)
1987 self.assertEqual(rx[IP].src, self.pg3.local_ip4)
1988 self.assertEqual(rx[IP].dst, self.pg3.remote_ip4)
1989 self.assertEqual(rx[UDP].dport, 48879)
1990 # the UDP source port is a random value for hashing
1991 self.assertEqual(rx[VXLAN].gpid, 220)
1992 self.assertEqual(rx[VXLAN].vni, 116)
1993 self.assertTrue(rx[VXLAN].flags.G)
1994 self.assertTrue(rx[VXLAN].flags.Instance)
1995 self.assertFalse(rx[VXLAN].gpflags.A)
1996 self.assertFalse(rx[VXLAN].gpflags.D)
1998 self.pg2.unconfig_ip4()
1999 self.pg3.unconfig_ip4()
2001 @unittest.skipIf(is_skip_aarch64_set() and is_platform_aarch64(),
2002 "test doesn't work on aarch64")
2003 def test_gbp_learn_l3(self):
2004 """ GBP L3 Endpoint Learning """
2006 self.vapi.cli("set logging class gbp debug")
2008 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
2009 routed_dst_mac = "00:0c:0c:0c:0c:0c"
2010 routed_src_mac = "00:22:bd:f8:19:ff"
2012 learnt = [{'mac': '00:00:11:11:11:02',
2014 'ip6': '2001:10::2'},
2015 {'mac': '00:00:11:11:11:03',
2017 'ip6': '2001:10::3'}]
2020 # lower the inactive threshold so these tests pass in a
2021 # reasonable amount of time
2023 self.vapi.gbp_endpoint_learn_set_inactive_threshold(1)
2028 t4 = VppIpTable(self, 1)
2030 t6 = VppIpTable(self, 1, True)
2033 tun_ip4_uu = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
2034 self.pg4.remote_ip4, 114)
2035 tun_ip6_uu = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
2036 self.pg4.remote_ip4, 116)
2037 tun_ip4_uu.add_vpp_config()
2038 tun_ip6_uu.add_vpp_config()
2040 rd1 = VppGbpRouteDomain(self, 2, t4, t6, tun_ip4_uu, tun_ip6_uu)
2041 rd1.add_vpp_config()
2043 self.loop0.set_mac(self.router_mac.address)
2046 # Bind the BVI to the RD
2048 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
2049 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
2052 # Pg2 hosts the vxlan tunnel
2053 # hosts on pg2 to act as TEPs
2057 self.pg2.config_ip4()
2058 self.pg2.resolve_arp()
2059 self.pg2.generate_remote_hosts(4)
2060 self.pg2.configure_ipv4_neighbors()
2061 self.pg3.config_ip4()
2062 self.pg3.resolve_arp()
2063 self.pg4.config_ip4()
2064 self.pg4.resolve_arp()
2067 # a GBP bridge domain with a BVI and a UU-flood interface
2069 bd1 = VppBridgeDomain(self, 1)
2070 bd1.add_vpp_config()
2071 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0, self.pg3)
2072 gbd1.add_vpp_config()
2074 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2075 self.logger.info(self.vapi.cli("sh gbp bridge"))
2076 self.logger.info(self.vapi.cli("sh gbp route"))
2078 # ... and has a /32 and /128 applied
2079 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2080 ip4_addr.add_vpp_config()
2081 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 128)
2082 ip6_addr.add_vpp_config()
2085 # The Endpoint-group in which we are learning endpoints
2087 epg_220 = VppGbpEndpointGroup(self, 220, rd1, gbd1,
2091 epg_220.add_vpp_config()
2094 # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
2097 vx_tun_l3 = VppGbpVxlanTunnel(
2098 self, 101, rd1.rd_id,
2099 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3)
2100 vx_tun_l3.add_vpp_config()
2103 # A static endpoint that the learnt endpoints are trying to
2106 ep = VppGbpEndpoint(self, self.pg0,
2108 "10.0.0.127", "11.0.0.127",
2109 "2001:10::1", "3001::1")
2113 # learn some remote IPv4 EPs
2115 for ii, l in enumerate(learnt):
2116 # a packet with an sclass from a knwon EPG
2117 # arriving on an unknown TEP
2118 p = (Ether(src=self.pg2.remote_mac,
2119 dst=self.pg2.local_mac) /
2120 IP(src=self.pg2.remote_hosts[1].ip4,
2121 dst=self.pg2.local_ip4) /
2122 UDP(sport=1234, dport=48879) /
2123 VXLAN(vni=101, gpid=220, flags=0x88) /
2124 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2125 IP(src=l['ip'], dst=ep.ip4.address) /
2126 UDP(sport=1234, dport=1234) /
2129 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2132 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2135 self.pg2.remote_hosts[1].ip4,
2137 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2139 # endpoint learnt via the parent GBP-vxlan interface
2140 self.assertTrue(find_gbp_endpoint(self,
2141 vx_tun_l3._sw_if_index,
2145 # Static IPv4 EP replies to learnt
2148 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2149 IP(dst=l['ip'], src=ep.ip4.address) /
2150 UDP(sport=1234, dport=1234) /
2153 rxs = self.send_and_expect(self.pg0, p*1, self.pg2)
2156 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2157 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2158 self.assertEqual(rx[UDP].dport, 48879)
2159 # the UDP source port is a random value for hashing
2160 self.assertEqual(rx[VXLAN].gpid, 220)
2161 self.assertEqual(rx[VXLAN].vni, 101)
2162 self.assertTrue(rx[VXLAN].flags.G)
2163 self.assertTrue(rx[VXLAN].flags.Instance)
2164 self.assertTrue(rx[VXLAN].gpflags.A)
2165 self.assertFalse(rx[VXLAN].gpflags.D)
2167 inner = rx[VXLAN].payload
2169 self.assertEqual(inner[Ether].src, routed_src_mac)
2170 self.assertEqual(inner[Ether].dst, routed_dst_mac)
2171 self.assertEqual(inner[IP].src, ep.ip4.address)
2172 self.assertEqual(inner[IP].dst, l['ip'])
2175 self.assertFalse(find_gbp_endpoint(self,
2180 # learn some remote IPv6 EPs
2182 for ii, l in enumerate(learnt):
2183 # a packet with an sclass from a knwon EPG
2184 # arriving on an unknown TEP
2185 p = (Ether(src=self.pg2.remote_mac,
2186 dst=self.pg2.local_mac) /
2187 IP(src=self.pg2.remote_hosts[1].ip4,
2188 dst=self.pg2.local_ip4) /
2189 UDP(sport=1234, dport=48879) /
2190 VXLAN(vni=101, gpid=220, flags=0x88) /
2191 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2192 IPv6(src=l['ip6'], dst=ep.ip6.address) /
2193 UDP(sport=1234, dport=1234) /
2196 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2199 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2202 self.pg2.remote_hosts[1].ip4,
2204 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2206 self.logger.info(self.vapi.cli("show gbp bridge"))
2207 self.logger.info(self.vapi.cli("show vxlan-gbp tunnel"))
2208 self.logger.info(self.vapi.cli("show gbp vxlan"))
2209 self.logger.info(self.vapi.cli("show int addr"))
2211 # endpoint learnt via the TEP
2212 self.assertTrue(find_gbp_endpoint(self, ip=l['ip6']))
2214 self.logger.info(self.vapi.cli("show gbp endpoint"))
2215 self.logger.info(self.vapi.cli("show ip fib index 1 %s" % l['ip']))
2218 # Static EP replies to learnt
2221 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2222 IPv6(dst=l['ip6'], src=ep.ip6.address) /
2223 UDP(sport=1234, dport=1234) /
2226 rxs = self.send_and_expect(self.pg0, p*65, self.pg2)
2229 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2230 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2231 self.assertEqual(rx[UDP].dport, 48879)
2232 # the UDP source port is a random value for hashing
2233 self.assertEqual(rx[VXLAN].gpid, 220)
2234 self.assertEqual(rx[VXLAN].vni, 101)
2235 self.assertTrue(rx[VXLAN].flags.G)
2236 self.assertTrue(rx[VXLAN].flags.Instance)
2237 self.assertTrue(rx[VXLAN].gpflags.A)
2238 self.assertFalse(rx[VXLAN].gpflags.D)
2240 inner = rx[VXLAN].payload
2242 self.assertEqual(inner[Ether].src, routed_src_mac)
2243 self.assertEqual(inner[Ether].dst, routed_dst_mac)
2244 self.assertEqual(inner[IPv6].src, ep.ip6.address)
2245 self.assertEqual(inner[IPv6].dst, l['ip6'])
2247 self.logger.info(self.vapi.cli("sh gbp endpoint"))
2249 self.wait_for_ep_timeout(ip=l['ip'])
2252 # Static sends to unknown EP with no route
2254 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2255 IP(dst="10.0.0.99", src=ep.ip4.address) /
2256 UDP(sport=1234, dport=1234) /
2259 self.send_and_assert_no_replies(self.pg0, [p])
2262 # Add a route to static EP's v4 and v6 subnet
2263 # packets should be sent on the v4/v6 uu=fwd interface resp.
2265 se_10_24 = VppGbpSubnet(
2266 self, rd1, "10.0.0.0", 24,
2267 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT)
2268 se_10_24.add_vpp_config()
2270 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2271 IP(dst="10.0.0.99", src=ep.ip4.address) /
2272 UDP(sport=1234, dport=1234) /
2275 rxs = self.send_and_expect(self.pg0, [p], self.pg4)
2277 self.assertEqual(rx[IP].src, self.pg4.local_ip4)
2278 self.assertEqual(rx[IP].dst, self.pg4.remote_ip4)
2279 self.assertEqual(rx[UDP].dport, 48879)
2280 # the UDP source port is a random value for hashing
2281 self.assertEqual(rx[VXLAN].gpid, 220)
2282 self.assertEqual(rx[VXLAN].vni, 114)
2283 self.assertTrue(rx[VXLAN].flags.G)
2284 self.assertTrue(rx[VXLAN].flags.Instance)
2285 # policy is not applied to packets sent to the uu-fwd interfaces
2286 self.assertFalse(rx[VXLAN].gpflags.A)
2287 self.assertFalse(rx[VXLAN].gpflags.D)
2290 # learn some remote IPv4 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=220, flags=0x88) /
2301 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2302 IP(src=l['ip'], dst=ep.ip4.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 # endpoint learnt via the parent GBP-vxlan interface
2317 self.assertTrue(find_gbp_endpoint(self,
2318 vx_tun_l3._sw_if_index,
2322 # Add a remote endpoint from the API
2324 rep_88 = VppGbpEndpoint(self, vx_tun_l3,
2326 "10.0.0.88", "11.0.0.88",
2327 "2001:10::88", "3001::88",
2328 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
2330 self.pg2.remote_hosts[1].ip4,
2332 rep_88.add_vpp_config()
2335 # Add a remote endpoint from the API that matches an existing one
2337 rep_2 = VppGbpEndpoint(self, vx_tun_l3,
2339 learnt[0]['ip'], "11.0.0.101",
2340 learnt[0]['ip6'], "3001::101",
2341 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
2343 self.pg2.remote_hosts[1].ip4,
2345 rep_2.add_vpp_config()
2348 # Add a route to the leanred EP's v4 subnet
2349 # packets should be send on the v4/v6 uu=fwd interface resp.
2351 se_10_1_24 = VppGbpSubnet(
2352 self, rd1, "10.0.1.0", 24,
2353 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT)
2354 se_10_1_24.add_vpp_config()
2356 self.logger.info(self.vapi.cli("show gbp endpoint"))
2358 ips = ["10.0.0.88", learnt[0]['ip']]
2360 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2361 IP(dst=ip, src=ep.ip4.address) /
2362 UDP(sport=1234, dport=1234) /
2365 rxs = self.send_and_expect(self.pg0, p*65, self.pg2)
2368 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2369 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2370 self.assertEqual(rx[UDP].dport, 48879)
2371 # the UDP source port is a random value for hashing
2372 self.assertEqual(rx[VXLAN].gpid, 220)
2373 self.assertEqual(rx[VXLAN].vni, 101)
2374 self.assertTrue(rx[VXLAN].flags.G)
2375 self.assertTrue(rx[VXLAN].flags.Instance)
2376 self.assertTrue(rx[VXLAN].gpflags.A)
2377 self.assertFalse(rx[VXLAN].gpflags.D)
2379 inner = rx[VXLAN].payload
2381 self.assertEqual(inner[Ether].src, routed_src_mac)
2382 self.assertEqual(inner[Ether].dst, routed_dst_mac)
2383 self.assertEqual(inner[IP].src, ep.ip4.address)
2384 self.assertEqual(inner[IP].dst, ip)
2387 # remove the API remote EPs, only API sourced is gone, the DP
2388 # learnt one remains
2390 rep_88.remove_vpp_config()
2391 rep_2.remove_vpp_config()
2393 self.logger.info(self.vapi.cli("show gbp endpoint"))
2395 self.assertFalse(find_gbp_endpoint(self, ip=rep_88.ip4.address))
2397 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2398 IP(src=ep.ip4.address, dst=rep_88.ip4.address) /
2399 UDP(sport=1234, dport=1234) /
2401 rxs = self.send_and_expect(self.pg0, [p], self.pg4)
2403 self.assertTrue(find_gbp_endpoint(self, ip=rep_2.ip4.address))
2405 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2406 IP(src=ep.ip4.address, dst=rep_2.ip4.address) /
2407 UDP(sport=1234, dport=1234) /
2409 rxs = self.send_and_expect(self.pg0, [p], self.pg2)
2412 # to appease the testcase we cannot have the registered EP stll
2413 # present (because it's DP learnt) when the TC ends so wait until
2419 # shutdown with learnt endpoint present
2421 p = (Ether(src=self.pg2.remote_mac,
2422 dst=self.pg2.local_mac) /
2423 IP(src=self.pg2.remote_hosts[1].ip4,
2424 dst=self.pg2.local_ip4) /
2425 UDP(sport=1234, dport=48879) /
2426 VXLAN(vni=101, gpid=220, flags=0x88) /
2427 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2428 IP(src=learnt[1]['ip'], dst=ep.ip4.address) /
2429 UDP(sport=1234, dport=1234) /
2432 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2434 # endpoint learnt via the parent GBP-vxlan interface
2435 self.assertTrue(find_gbp_endpoint(self,
2436 vx_tun_l3._sw_if_index,
2441 # remote endpoint becomes local
2443 self.pg2.unconfig_ip4()
2444 self.pg3.unconfig_ip4()
2445 self.pg4.unconfig_ip4()
2447 def test_gbp_redirect(self):
2448 """ GBP Endpoint Redirect """
2450 self.vapi.cli("set logging class gbp debug")
2452 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
2453 routed_dst_mac = "00:0c:0c:0c:0c:0c"
2454 routed_src_mac = "00:22:bd:f8:19:ff"
2456 learnt = [{'mac': '00:00:11:11:11:02',
2458 'ip6': '2001:10::2'},
2459 {'mac': '00:00:11:11:11:03',
2461 'ip6': '2001:10::3'}]
2464 # lower the inactive threshold so these tests pass in a
2465 # reasonable amount of time
2467 self.vapi.gbp_endpoint_learn_set_inactive_threshold(1)
2472 t4 = VppIpTable(self, 1)
2474 t6 = VppIpTable(self, 1, True)
2477 rd1 = VppGbpRouteDomain(self, 2, t4, t6)
2478 rd1.add_vpp_config()
2480 self.loop0.set_mac(self.router_mac.address)
2483 # Bind the BVI to the RD
2485 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
2486 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
2489 # Pg7 hosts a BD's UU-fwd
2491 self.pg7.config_ip4()
2492 self.pg7.resolve_arp()
2495 # a GBP bridge domains for the EPs
2497 bd1 = VppBridgeDomain(self, 1)
2498 bd1.add_vpp_config()
2499 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0)
2500 gbd1.add_vpp_config()
2502 bd2 = VppBridgeDomain(self, 2)
2503 bd2.add_vpp_config()
2504 gbd2 = VppGbpBridgeDomain(self, bd2, self.loop1)
2505 gbd2.add_vpp_config()
2507 # ... and has a /32 and /128 applied
2508 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2509 ip4_addr.add_vpp_config()
2510 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 128)
2511 ip6_addr.add_vpp_config()
2512 ip4_addr = VppIpInterfaceAddress(self, gbd2.bvi, "10.0.1.128", 32)
2513 ip4_addr.add_vpp_config()
2514 ip6_addr = VppIpInterfaceAddress(self, gbd2.bvi, "2001:11::128", 128)
2515 ip6_addr.add_vpp_config()
2518 # The Endpoint-groups in which we are learning endpoints
2520 epg_220 = VppGbpEndpointGroup(self, 220, rd1, gbd1,
2524 epg_220.add_vpp_config()
2525 epg_221 = VppGbpEndpointGroup(self, 221, rd1, gbd2,
2529 epg_221.add_vpp_config()
2530 epg_222 = VppGbpEndpointGroup(self, 222, rd1, gbd1,
2534 epg_222.add_vpp_config()
2537 # a GBP bridge domains for the SEPs
2539 bd_uu1 = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
2540 self.pg7.remote_ip4, 116)
2541 bd_uu1.add_vpp_config()
2542 bd_uu2 = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
2543 self.pg7.remote_ip4, 117)
2544 bd_uu2.add_vpp_config()
2546 bd3 = VppBridgeDomain(self, 3)
2547 bd3.add_vpp_config()
2548 gbd3 = VppGbpBridgeDomain(self, bd3, self.loop2, bd_uu1, learn=False)
2549 gbd3.add_vpp_config()
2550 bd4 = VppBridgeDomain(self, 4)
2551 bd4.add_vpp_config()
2552 gbd4 = VppGbpBridgeDomain(self, bd4, self.loop3, bd_uu2, learn=False)
2553 gbd4.add_vpp_config()
2556 # EPGs in which the service endpoints exist
2558 epg_320 = VppGbpEndpointGroup(self, 320, rd1, gbd3,
2562 epg_320.add_vpp_config()
2563 epg_321 = VppGbpEndpointGroup(self, 321, rd1, gbd4,
2567 epg_321.add_vpp_config()
2570 # three local endpoints
2572 ep1 = VppGbpEndpoint(self, self.pg0,
2574 "10.0.0.1", "11.0.0.1",
2575 "2001:10::1", "3001:10::1")
2576 ep1.add_vpp_config()
2577 ep2 = VppGbpEndpoint(self, self.pg1,
2579 "10.0.1.1", "11.0.1.1",
2580 "2001:11::1", "3001:11::1")
2581 ep2.add_vpp_config()
2582 ep3 = VppGbpEndpoint(self, self.pg2,
2584 "10.0.2.2", "11.0.2.2",
2585 "2001:12::1", "3001:12::1")
2586 ep3.add_vpp_config()
2591 sep1 = VppGbpEndpoint(self, self.pg3,
2593 "12.0.0.1", "13.0.0.1",
2594 "4001:10::1", "5001:10::1")
2595 sep1.add_vpp_config()
2596 sep2 = VppGbpEndpoint(self, self.pg4,
2598 "12.0.0.2", "13.0.0.2",
2599 "4001:10::2", "5001:10::2")
2600 sep2.add_vpp_config()
2601 sep3 = VppGbpEndpoint(self, self.pg5,
2603 "12.0.1.1", "13.0.1.1",
2604 "4001:11::1", "5001:11::1")
2605 sep3.add_vpp_config()
2606 # this EP is not installed immediately
2607 sep4 = VppGbpEndpoint(self, self.pg6,
2609 "12.0.1.2", "13.0.1.2",
2610 "4001:11::2", "5001:11::2")
2613 # an L2 switch packet between local EPs in different EPGs
2614 # different dest ports on each so the are LB hashed differently
2616 p4 = [(Ether(src=ep1.mac, dst=ep3.mac) /
2617 IP(src=ep1.ip4.address, dst=ep3.ip4.address) /
2618 UDP(sport=1234, dport=1234) /
2620 (Ether(src=ep3.mac, dst=ep1.mac) /
2621 IP(src=ep3.ip4.address, dst=ep1.ip4.address) /
2622 UDP(sport=1234, dport=1234) /
2624 p6 = [(Ether(src=ep1.mac, dst=ep3.mac) /
2625 IPv6(src=ep1.ip6.address, dst=ep3.ip6.address) /
2626 UDP(sport=1234, dport=1234) /
2628 (Ether(src=ep3.mac, dst=ep1.mac) /
2629 IPv6(src=ep3.ip6.address, dst=ep1.ip6.address) /
2630 UDP(sport=1234, dport=1230) /
2633 # should be dropped since no contract yet
2634 self.send_and_assert_no_replies(self.pg0, [p4[0]])
2635 self.send_and_assert_no_replies(self.pg0, [p6[0]])
2638 # Add a contract with a rule to load-balance redirect via SEP1 and SEP2
2639 # one of the next-hops is via an EP that is not known
2641 acl = VppGbpAcl(self)
2642 rule4 = acl.create_rule(permit_deny=1, proto=17)
2643 rule6 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
2644 acl_index = acl.add_vpp_config([rule4, rule6])
2647 # test the src-ip hash mode
2649 c1 = VppGbpContract(
2650 self, 220, 222, acl_index,
2651 [VppGbpContractRule(
2652 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2653 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2654 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
2655 sep1.ip4, sep1.epg.rd),
2656 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
2657 sep2.ip4, sep2.epg.rd)]),
2659 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2660 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2661 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
2662 sep3.ip6, sep3.epg.rd),
2663 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
2664 sep4.ip6, sep4.epg.rd)])])
2667 c2 = VppGbpContract(
2668 self, 222, 220, acl_index,
2669 [VppGbpContractRule(
2670 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2671 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2672 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
2673 sep1.ip4, sep1.epg.rd),
2674 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
2675 sep2.ip4, sep2.epg.rd)]),
2677 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2678 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2679 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
2680 sep3.ip6, sep3.epg.rd),
2681 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
2682 sep4.ip6, sep4.epg.rd)])])
2686 # send again with the contract preset, now packets arrive
2687 # at SEP1 or SEP2 depending on the hashing
2689 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
2692 self.assertEqual(rx[Ether].src, routed_src_mac)
2693 self.assertEqual(rx[Ether].dst, sep1.mac)
2694 self.assertEqual(rx[IP].src, ep1.ip4.address)
2695 self.assertEqual(rx[IP].dst, ep3.ip4.address)
2697 rxs = self.send_and_expect(self.pg2, p4[1] * 17, sep2.itf)
2700 self.assertEqual(rx[Ether].src, routed_src_mac)
2701 self.assertEqual(rx[Ether].dst, sep2.mac)
2702 self.assertEqual(rx[IP].src, ep3.ip4.address)
2703 self.assertEqual(rx[IP].dst, ep1.ip4.address)
2705 rxs = self.send_and_expect(self.pg0, p6[0] * 17, self.pg7)
2708 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
2709 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
2710 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
2711 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
2712 self.assertEqual(rx[VXLAN].vni, 117)
2713 self.assertTrue(rx[VXLAN].flags.G)
2714 self.assertTrue(rx[VXLAN].flags.Instance)
2715 # redirect policy has been applied
2716 self.assertTrue(rx[VXLAN].gpflags.A)
2717 self.assertFalse(rx[VXLAN].gpflags.D)
2719 inner = rx[VXLAN].payload
2721 self.assertEqual(inner[Ether].src, routed_src_mac)
2722 self.assertEqual(inner[Ether].dst, sep4.mac)
2723 self.assertEqual(inner[IPv6].src, ep1.ip6.address)
2724 self.assertEqual(inner[IPv6].dst, ep3.ip6.address)
2726 rxs = self.send_and_expect(self.pg2, p6[1] * 17, sep3.itf)
2729 self.assertEqual(rx[Ether].src, routed_src_mac)
2730 self.assertEqual(rx[Ether].dst, sep3.mac)
2731 self.assertEqual(rx[IPv6].src, ep3.ip6.address)
2732 self.assertEqual(rx[IPv6].dst, ep1.ip6.address)
2735 # programme the unknown EP
2737 sep4.add_vpp_config()
2739 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep4.itf)
2742 self.assertEqual(rx[Ether].src, routed_src_mac)
2743 self.assertEqual(rx[Ether].dst, sep4.mac)
2744 self.assertEqual(rx[IPv6].src, ep1.ip6.address)
2745 self.assertEqual(rx[IPv6].dst, ep3.ip6.address)
2748 # and revert back to unprogrammed
2750 sep4.remove_vpp_config()
2752 rxs = self.send_and_expect(self.pg0, p6[0] * 17, self.pg7)
2755 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
2756 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
2757 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
2758 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
2759 self.assertEqual(rx[VXLAN].vni, 117)
2760 self.assertTrue(rx[VXLAN].flags.G)
2761 self.assertTrue(rx[VXLAN].flags.Instance)
2762 # redirect policy has been applied
2763 self.assertTrue(rx[VXLAN].gpflags.A)
2764 self.assertFalse(rx[VXLAN].gpflags.D)
2766 inner = rx[VXLAN].payload
2768 self.assertEqual(inner[Ether].src, routed_src_mac)
2769 self.assertEqual(inner[Ether].dst, sep4.mac)
2770 self.assertEqual(inner[IPv6].src, ep1.ip6.address)
2771 self.assertEqual(inner[IPv6].dst, ep3.ip6.address)
2773 c1.remove_vpp_config()
2774 c2.remove_vpp_config()
2777 # test the symmetric hash mode
2779 c1 = VppGbpContract(
2780 self, 220, 222, acl_index,
2781 [VppGbpContractRule(
2782 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2783 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
2784 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
2785 sep1.ip4, sep1.epg.rd),
2786 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
2787 sep2.ip4, sep2.epg.rd)]),
2789 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2790 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
2791 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
2792 sep3.ip6, sep3.epg.rd),
2793 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
2794 sep4.ip6, sep4.epg.rd)])])
2797 c2 = VppGbpContract(
2798 self, 222, 220, acl_index,
2799 [VppGbpContractRule(
2800 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2801 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
2802 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
2803 sep1.ip4, sep1.epg.rd),
2804 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
2805 sep2.ip4, sep2.epg.rd)]),
2807 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2808 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
2809 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
2810 sep3.ip6, sep3.epg.rd),
2811 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
2812 sep4.ip6, sep4.epg.rd)])])
2816 # send again with the contract preset, now packets arrive
2817 # at SEP1 for both directions
2819 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
2822 self.assertEqual(rx[Ether].src, routed_src_mac)
2823 self.assertEqual(rx[Ether].dst, sep1.mac)
2824 self.assertEqual(rx[IP].src, ep1.ip4.address)
2825 self.assertEqual(rx[IP].dst, ep3.ip4.address)
2827 rxs = self.send_and_expect(self.pg2, p4[1] * 17, sep1.itf)
2830 self.assertEqual(rx[Ether].src, routed_src_mac)
2831 self.assertEqual(rx[Ether].dst, sep1.mac)
2832 self.assertEqual(rx[IP].src, ep3.ip4.address)
2833 self.assertEqual(rx[IP].dst, ep1.ip4.address)
2836 # programme the unknown EP for the L3 tests
2838 sep4.add_vpp_config()
2841 # an L3 switch packet between local EPs in different EPGs
2842 # different dest ports on each so the are LB hashed differently
2844 p4 = [(Ether(src=ep1.mac, dst=self.router_mac.address) /
2845 IP(src=ep1.ip4.address, dst=ep2.ip4.address) /
2846 UDP(sport=1234, dport=1234) /
2848 (Ether(src=ep2.mac, dst=self.router_mac.address) /
2849 IP(src=ep2.ip4.address, dst=ep1.ip4.address) /
2850 UDP(sport=1234, dport=1234) /
2852 p6 = [(Ether(src=ep1.mac, dst=self.router_mac.address) /
2853 IPv6(src=ep1.ip6.address, dst=ep2.ip6.address) /
2854 UDP(sport=1234, dport=1234) /
2856 (Ether(src=ep2.mac, dst=self.router_mac.address) /
2857 IPv6(src=ep2.ip6.address, dst=ep1.ip6.address) /
2858 UDP(sport=1234, dport=1234) /
2861 c3 = VppGbpContract(
2862 self, 220, 221, acl_index,
2863 [VppGbpContractRule(
2864 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2865 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
2866 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
2867 sep1.ip4, sep1.epg.rd),
2868 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
2869 sep2.ip4, sep2.epg.rd)]),
2871 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2872 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
2873 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
2874 sep3.ip6, sep3.epg.rd),
2875 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
2876 sep4.ip6, sep4.epg.rd)])])
2879 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
2882 self.assertEqual(rx[Ether].src, routed_src_mac)
2883 self.assertEqual(rx[Ether].dst, sep1.mac)
2884 self.assertEqual(rx[IP].src, ep1.ip4.address)
2885 self.assertEqual(rx[IP].dst, ep2.ip4.address)
2888 # learn a remote EP in EPG 221
2890 vx_tun_l3 = VppGbpVxlanTunnel(
2891 self, 444, rd1.rd_id,
2892 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3)
2893 vx_tun_l3.add_vpp_config()
2895 c4 = VppGbpContract(
2896 self, 221, 220, acl_index,
2897 [VppGbpContractRule(
2898 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2901 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2905 p = (Ether(src=self.pg7.remote_mac,
2906 dst=self.pg7.local_mac) /
2907 IP(src=self.pg7.remote_ip4,
2908 dst=self.pg7.local_ip4) /
2909 UDP(sport=1234, dport=48879) /
2910 VXLAN(vni=444, gpid=221, flags=0x88) /
2911 Ether(src="00:22:22:22:22:33", dst=self.router_mac.address) /
2912 IP(src="10.0.0.88", dst=ep1.ip4.address) /
2913 UDP(sport=1234, dport=1234) /
2916 rx = self.send_and_expect(self.pg7, [p], self.pg0)
2918 # endpoint learnt via the parent GBP-vxlan interface
2919 self.assertTrue(find_gbp_endpoint(self,
2920 vx_tun_l3._sw_if_index,
2923 p = (Ether(src=self.pg7.remote_mac,
2924 dst=self.pg7.local_mac) /
2925 IP(src=self.pg7.remote_ip4,
2926 dst=self.pg7.local_ip4) /
2927 UDP(sport=1234, dport=48879) /
2928 VXLAN(vni=444, gpid=221, flags=0x88) /
2929 Ether(src="00:22:22:22:22:33", dst=self.router_mac.address) /
2930 IPv6(src="2001:10::88", dst=ep1.ip6.address) /
2931 UDP(sport=1234, dport=1234) /
2934 rx = self.send_and_expect(self.pg7, [p], self.pg0)
2936 # endpoint learnt via the parent GBP-vxlan interface
2937 self.assertTrue(find_gbp_endpoint(self,
2938 vx_tun_l3._sw_if_index,
2942 # L3 switch from local to remote EP
2944 p4 = [(Ether(src=ep1.mac, dst=self.router_mac.address) /
2945 IP(src=ep1.ip4.address, dst="10.0.0.88") /
2946 UDP(sport=1234, dport=1234) /
2948 p6 = [(Ether(src=ep1.mac, dst=self.router_mac.address) /
2949 IPv6(src=ep1.ip6.address, dst="2001:10::88") /
2950 UDP(sport=1234, dport=1234) /
2953 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
2956 self.assertEqual(rx[Ether].src, routed_src_mac)
2957 self.assertEqual(rx[Ether].dst, sep1.mac)
2958 self.assertEqual(rx[IP].src, ep1.ip4.address)
2959 self.assertEqual(rx[IP].dst, "10.0.0.88")
2961 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep4.itf)
2964 self.assertEqual(rx[Ether].src, routed_src_mac)
2965 self.assertEqual(rx[Ether].dst, sep4.mac)
2966 self.assertEqual(rx[IPv6].src, ep1.ip6.address)
2967 self.assertEqual(rx[IPv6].dst, "2001:10::88")
2970 # test the dst-ip hash mode
2972 c5 = VppGbpContract(
2973 self, 220, 221, acl_index,
2974 [VppGbpContractRule(
2975 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2976 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
2977 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
2978 sep1.ip4, sep1.epg.rd),
2979 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
2980 sep2.ip4, sep2.epg.rd)]),
2982 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2983 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
2984 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
2985 sep3.ip6, sep3.epg.rd),
2986 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
2987 sep4.ip6, sep4.epg.rd)])])
2990 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
2993 self.assertEqual(rx[Ether].src, routed_src_mac)
2994 self.assertEqual(rx[Ether].dst, sep1.mac)
2995 self.assertEqual(rx[IP].src, ep1.ip4.address)
2996 self.assertEqual(rx[IP].dst, "10.0.0.88")
2998 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep3.itf)
3001 self.assertEqual(rx[Ether].src, routed_src_mac)
3002 self.assertEqual(rx[Ether].dst, sep3.mac)
3003 self.assertEqual(rx[IPv6].src, ep1.ip6.address)
3004 self.assertEqual(rx[IPv6].dst, "2001:10::88")
3009 self.pg7.unconfig_ip4()
3011 def test_gbp_l3_out(self):
3014 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
3015 self.vapi.cli("set logging class gbp debug")
3017 routed_dst_mac = "00:0c:0c:0c:0c:0c"
3018 routed_src_mac = "00:22:bd:f8:19:ff"
3023 t4 = VppIpTable(self, 1)
3025 t6 = VppIpTable(self, 1, True)
3028 rd1 = VppGbpRouteDomain(self, 2, t4, t6)
3029 rd1.add_vpp_config()
3031 self.loop0.set_mac(self.router_mac.address)
3034 # Bind the BVI to the RD
3036 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
3037 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
3040 # Pg7 hosts a BD's BUM
3041 # Pg1 some other l3 interface
3043 self.pg7.config_ip4()
3044 self.pg7.resolve_arp()
3047 # a GBP external bridge domains for the EPs
3049 bd1 = VppBridgeDomain(self, 1)
3050 bd1.add_vpp_config()
3051 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0)
3052 gbd1.add_vpp_config()
3055 # The Endpoint-groups in which the external endpoints exist
3057 epg_220 = VppGbpEndpointGroup(self, 220, rd1, gbd1,
3061 epg_220.add_vpp_config()
3063 # the BVIs have the subnets applied ...
3064 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 24)
3065 ip4_addr.add_vpp_config()
3066 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 64)
3067 ip6_addr.add_vpp_config()
3069 # ... which are L3-out subnets
3070 l3o_1 = VppGbpSubnet(
3071 self, rd1, "10.0.0.0", 24,
3072 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3074 l3o_1.add_vpp_config()
3077 # an external interface attached to the outside world and the
3080 vlan_100 = VppDot1QSubint(self, self.pg0, 100)
3082 ext_itf = VppGbpExtItf(self, vlan_100, bd1, rd1)
3083 ext_itf.add_vpp_config()
3086 # a multicast vxlan-gbp tunnel for broadcast in the BD
3088 tun_bm = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
3091 tun_bm.add_vpp_config()
3092 bp_bm = VppBridgeDomainPort(self, bd1, tun_bm,
3093 port_type=L2_PORT_TYPE.NORMAL)
3094 bp_bm.add_vpp_config()
3097 # an unicast vxlan-gbp for inter-BD traffic
3099 vx_tun_l3 = VppGbpVxlanTunnel(
3100 self, 444, rd1.rd_id,
3101 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3)
3102 vx_tun_l3.add_vpp_config()
3105 # packets destined to unkown addresses in the BVI's subnet
3108 p4 = (Ether(src=self.pg0.remote_mac, dst=self.router_mac.address) /
3110 IP(src="10.0.0.1", dst="10.0.0.88") /
3111 UDP(sport=1234, dport=1234) /
3113 p6 = (Ether(src=self.pg0.remote_mac, dst=self.router_mac.address) /
3115 IPv6(src="2001:10::1", dst="2001:10::88") /
3116 UDP(sport=1234, dport=1234) /
3119 rxs = self.send_and_expect(self.pg0, p4 * 1, self.pg7)
3122 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3123 # self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3124 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3125 self.assertEqual(rx[IP].dst, "239.1.1.1")
3126 self.assertEqual(rx[VXLAN].vni, 88)
3127 self.assertTrue(rx[VXLAN].flags.G)
3128 self.assertTrue(rx[VXLAN].flags.Instance)
3129 # policy is not applied since we don't know where it's going
3130 self.assertFalse(rx[VXLAN].gpflags.A)
3131 self.assertFalse(rx[VXLAN].gpflags.D)
3133 inner = rx[VXLAN].payload
3135 self.assertTrue(inner.haslayer(ARP))
3138 # An external Endpoint
3140 eep = VppGbpEndpoint(self, vlan_100,
3142 "10.0.0.1", "11.0.0.1",
3143 "2001:10::1", "3001::1",
3144 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
3145 eep.add_vpp_config()
3150 rep = VppGbpEndpoint(self, vx_tun_l3,
3152 "10.0.0.101", "11.0.0.101",
3153 "2001:10::101", "3001::101",
3154 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
3156 self.pg7.remote_ip4,
3158 rep.add_vpp_config()
3161 # remote to external
3163 p = (Ether(src=self.pg7.remote_mac,
3164 dst=self.pg7.local_mac) /
3165 IP(src=self.pg7.remote_ip4,
3166 dst=self.pg7.local_ip4) /
3167 UDP(sport=1234, dport=48879) /
3168 VXLAN(vni=444, gpid=220, flags=0x88) /
3169 Ether(src=self.pg0.remote_mac, dst=self.router_mac.address) /
3170 IP(src="10.0.0.101", dst="10.0.0.1") /
3171 UDP(sport=1234, dport=1234) /
3174 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
3177 # A subnet reachable through the external EP
3179 ip_220 = VppIpRoute(self, "10.220.0.0", 24,
3180 [VppRoutePath(eep.ip4.address,
3181 eep.epg.bvi.sw_if_index)],
3182 table_id=t4.table_id)
3183 ip_220.add_vpp_config()
3185 l3o_220 = VppGbpSubnet(
3186 self, rd1, "10.220.0.0", 24,
3187 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3189 l3o_220.add_vpp_config()
3191 p = (Ether(src=self.pg7.remote_mac,
3192 dst=self.pg7.local_mac) /
3193 IP(src=self.pg7.remote_ip4,
3194 dst=self.pg7.local_ip4) /
3195 UDP(sport=1234, dport=48879) /
3196 VXLAN(vni=444, gpid=220, flags=0x88) /
3197 Ether(src=self.pg0.remote_mac, dst=self.router_mac.address) /
3198 IP(src="10.0.0.101", dst="10.220.0.1") /
3199 UDP(sport=1234, dport=1234) /
3202 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
3205 # another external subnet, this time in a different EPG
3207 ip_200 = VppIpRoute(self, "10.200.0.0", 24,
3208 [VppRoutePath(eep.ip4.address,
3209 eep.epg.bvi.sw_if_index)],
3210 table_id=t4.table_id)
3211 ip_200.add_vpp_config()
3213 l3o_200 = VppGbpSubnet(
3214 self, rd1, "10.200.0.0", 24,
3215 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3217 l3o_200.add_vpp_config()
3219 p = (Ether(src=self.pg7.remote_mac,
3220 dst=self.pg7.local_mac) /
3221 IP(src=self.pg7.remote_ip4,
3222 dst=self.pg7.local_ip4) /
3223 UDP(sport=1234, dport=48879) /
3224 VXLAN(vni=444, gpid=220, flags=0x88) /
3225 Ether(src=self.pg0.remote_mac, dst=self.router_mac.address) /
3226 IP(src="10.0.0.101", dst="10.200.0.1") /
3227 UDP(sport=1234, dport=1234) /
3231 # packets dropped due to lack of contract.
3233 rxs = self.send_and_assert_no_replies(self.pg7, p * 1)
3236 # from the the subnet in EPG 220 beyond the external to remote
3238 p4 = (Ether(src=self.pg0.remote_mac, dst=self.router_mac.address) /
3240 IP(src="10.220.0.1", dst=rep.ip4.address) /
3241 UDP(sport=1234, dport=1234) /
3244 rxs = self.send_and_expect(self.pg0, p4 * 1, self.pg7)
3247 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3248 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3249 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3250 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
3251 self.assertEqual(rx[VXLAN].vni, 444)
3252 self.assertTrue(rx[VXLAN].flags.G)
3253 self.assertTrue(rx[VXLAN].flags.Instance)
3254 self.assertTrue(rx[VXLAN].gpflags.A)
3255 self.assertFalse(rx[VXLAN].gpflags.D)
3258 # from the the subnet in EPG 200 beyond the external to remote
3259 # dropped due to no contract
3261 p4 = (Ether(src=self.pg0.remote_mac, dst=self.router_mac.address) /
3263 IP(src="10.200.0.1", dst=rep.ip4.address) /
3264 UDP(sport=1234, dport=1234) /
3267 rxs = self.send_and_assert_no_replies(self.pg0, p4 * 1)
3272 acl = VppGbpAcl(self)
3273 rule = acl.create_rule(permit_deny=1, proto=17)
3274 rule2 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
3275 acl_index = acl.add_vpp_config([rule, rule2])
3276 c1 = VppGbpContract(
3277 self, 200, 220, acl_index,
3278 [VppGbpContractRule(
3279 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3282 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3286 rxs = self.send_and_expect(self.pg0, p4 * 1, self.pg7)
3289 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3290 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3291 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3292 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
3293 self.assertEqual(rx[VXLAN].vni, 444)
3294 self.assertTrue(rx[VXLAN].flags.G)
3295 self.assertTrue(rx[VXLAN].flags.Instance)
3296 self.assertTrue(rx[VXLAN].gpflags.A)
3297 self.assertFalse(rx[VXLAN].gpflags.D)
3302 self.pg7.unconfig_ip4()
3305 if __name__ == '__main__':
3306 unittest.main(testRunner=VppTestRunner)