5 from framework import VppTestCase, VppTestRunner
6 from vpp_object import VppObject
7 from vpp_neighbor import VppNeighbor
8 from vpp_ip_route import VppIpRoute, VppRoutePath, VppIpTable, \
9 VppIpInterfaceAddress, VppIpInterfaceBind, find_route
10 from vpp_l2 import VppBridgeDomain, VppBridgeDomainPort, \
11 VppBridgeDomainArpEntry, VppL2FibEntry, find_bridge_domain_port
12 from vpp_vxlan_gbp_tunnel import *
16 from vpp_papi_provider import L2_PORT_TYPE
17 from vpp_papi import VppEnum
19 from scapy.packet import Raw
20 from scapy.layers.l2 import Ether, ARP
21 from scapy.layers.inet import IP, UDP
22 from scapy.layers.inet6 import IPv6, ICMPv6ND_NS, ICMPv6NDOptSrcLLAddr, \
24 from scapy.utils6 import in6_getnsma, in6_getnsmac
25 from scapy.layers.vxlan import VXLAN
27 from socket import AF_INET, AF_INET6
28 from scapy.utils import inet_pton, inet_ntop
29 from util import mactobinary
32 def find_gbp_endpoint(test, sw_if_index=None, ip=None, mac=None):
34 vip = VppIpAddress(ip)
36 vmac = VppMacAddress(mac)
38 eps = test.vapi.gbp_endpoint_dump()
42 if ep.endpoint.sw_if_index != sw_if_index:
45 for eip in ep.endpoint.ips:
49 if vmac == ep.endpoint.mac:
54 def find_gbp_vxlan(test, vni):
55 ts = test.vapi.gbp_vxlan_tunnel_dump()
57 if t.tunnel.vni == vni:
62 class VppGbpEndpoint(VppObject):
69 return self.vmac.bytes
73 return self.vmac.address
77 return self.itf.remote_mac
97 return [self.ip4, self.ip6]
101 return [self.fip4, self.fip6]
103 def __init__(self, test, itf, epg, recirc, ip4, fip4, ip6, fip6,
113 self._ip4 = VppIpAddress(ip4)
114 self._fip4 = VppIpAddress(fip4)
115 self._ip6 = VppIpAddress(ip6)
116 self._fip6 = VppIpAddress(fip6)
119 self.vmac = VppMacAddress(self.itf.remote_mac)
121 self.vmac = VppMacAddress("00:00:00:00:00:00")
124 self.tun_src = VppIpAddress(tun_src)
125 self.tun_dst = VppIpAddress(tun_dst)
127 def add_vpp_config(self):
128 res = self._test.vapi.gbp_endpoint_add(
129 self.itf.sw_if_index,
130 [self.ip4.encode(), self.ip6.encode()],
134 self.tun_src.encode(),
135 self.tun_dst.encode())
136 self.handle = res.handle
137 self._test.registry.register(self, self._test.logger)
139 def remove_vpp_config(self):
140 self._test.vapi.gbp_endpoint_del(self.handle)
143 return self.object_id()
146 return "gbp-endpoint:[%d==%d:%s:%d]" % (self.handle,
147 self.itf.sw_if_index,
151 def query_vpp_config(self):
152 return find_gbp_endpoint(self._test,
153 self.itf.sw_if_index,
157 class VppGbpRecirc(VppObject):
159 GBP Recirculation Interface
162 def __init__(self, test, epg, recirc, is_ext=False):
168 def add_vpp_config(self):
169 self._test.vapi.gbp_recirc_add_del(
171 self.recirc.sw_if_index,
174 self._test.registry.register(self, self._test.logger)
176 def remove_vpp_config(self):
177 self._test.vapi.gbp_recirc_add_del(
179 self.recirc.sw_if_index,
184 return self.object_id()
187 return "gbp-recirc:[%d]" % (self.recirc.sw_if_index)
189 def query_vpp_config(self):
190 rs = self._test.vapi.gbp_recirc_dump()
192 if r.recirc.sw_if_index == self.recirc.sw_if_index:
197 class VppGbpSubnet(VppObject):
201 def __init__(self, test, rd, address, address_len,
202 type, sw_if_index=None, epg=None):
204 self.rd_id = rd.rd_id
205 self.prefix = VppIpPrefix(address, address_len)
207 self.sw_if_index = sw_if_index
210 def add_vpp_config(self):
211 self._test.vapi.gbp_subnet_add_del(
214 self.prefix.encode(),
216 sw_if_index=self.sw_if_index if self.sw_if_index else 0xffffffff,
217 epg_id=self.epg if self.epg else 0xffff)
218 self._test.registry.register(self, self._test.logger)
220 def remove_vpp_config(self):
221 self._test.vapi.gbp_subnet_add_del(
224 self.prefix.encode(),
228 return self.object_id()
231 return "gbp-subnet:[%d-%s]" % (self.rd_id, self.prefix)
233 def query_vpp_config(self):
234 ss = self._test.vapi.gbp_subnet_dump()
236 if s.subnet.rd_id == self.rd_id and \
237 s.subnet.type == self.type and \
238 s.subnet.prefix == self.prefix:
243 class VppGbpEndpointGroup(VppObject):
248 def __init__(self, test, epg, rd, bd, uplink,
249 bvi, bvi_ip4, bvi_ip6=None):
253 self.bvi_ip4 = VppIpAddress(bvi_ip4)
254 self.bvi_ip6 = VppIpAddress(bvi_ip6)
259 def add_vpp_config(self):
260 self._test.vapi.gbp_endpoint_group_add(
264 self.uplink.sw_if_index if self.uplink else INDEX_INVALID)
265 self._test.registry.register(self, self._test.logger)
267 def remove_vpp_config(self):
268 self._test.vapi.gbp_endpoint_group_del(
272 return self.object_id()
275 return "gbp-endpoint-group:[%d]" % (self.epg)
277 def query_vpp_config(self):
278 epgs = self._test.vapi.gbp_endpoint_group_dump()
280 if epg.epg.epg_id == self.epg:
285 class VppGbpBridgeDomain(VppObject):
290 def __init__(self, test, bd, bvi, uu_flood=None):
293 self.uu_flood = uu_flood
296 def add_vpp_config(self):
297 self._test.vapi.gbp_bridge_domain_add(
299 self.bvi.sw_if_index,
300 self.uu_flood.sw_if_index if self.uu_flood else INDEX_INVALID)
301 self._test.registry.register(self, self._test.logger)
303 def remove_vpp_config(self):
304 self._test.vapi.gbp_bridge_domain_del(self.bd.bd_id)
307 return self.object_id()
310 return "gbp-bridge-domain:[%d]" % (self.bd.bd_id)
312 def query_vpp_config(self):
313 bds = self._test.vapi.gbp_bridge_domain_dump()
315 if bd.bd.bd_id == self.bd.bd_id:
320 class VppGbpRouteDomain(VppObject):
325 def __init__(self, test, rd_id, t4, t6, ip4_uu=None, ip6_uu=None):
333 def add_vpp_config(self):
334 self._test.vapi.gbp_route_domain_add(
338 self.ip4_uu.sw_if_index if self.ip4_uu else INDEX_INVALID,
339 self.ip6_uu.sw_if_index if self.ip6_uu else INDEX_INVALID)
340 self._test.registry.register(self, self._test.logger)
342 def remove_vpp_config(self):
343 self._test.vapi.gbp_route_domain_del(self.rd_id)
346 return self.object_id()
349 return "gbp-route-domain:[%d]" % (self.rd_id)
351 def query_vpp_config(self):
352 rds = self._test.vapi.gbp_route_domain_dump()
354 if rd.rd.rd_id == self.rd_id:
359 class VppGbpContract(VppObject):
364 def __init__(self, test, src_epg, dst_epg, acl_index):
366 self.acl_index = acl_index
367 self.src_epg = src_epg
368 self.dst_epg = dst_epg
370 def add_vpp_config(self):
371 self._test.vapi.gbp_contract_add_del(
376 self._test.registry.register(self, self._test.logger)
378 def remove_vpp_config(self):
379 self._test.vapi.gbp_contract_add_del(
386 return self.object_id()
389 return "gbp-contract:[%d:%s:%d]" % (self.src_epg,
393 def query_vpp_config(self):
394 cs = self._test.vapi.gbp_contract_dump()
396 if c.contract.src_epg == self.src_epg \
397 and c.contract.dst_epg == self.dst_epg:
402 class VppGbpVxlanTunnel(VppInterface):
407 def __init__(self, test, vni, bd_rd_id, mode):
408 super(VppGbpVxlanTunnel, self).__init__(test)
411 self.bd_rd_id = bd_rd_id
414 def add_vpp_config(self):
415 r = self._test.vapi.gbp_vxlan_tunnel_add(
419 self.set_sw_if_index(r.sw_if_index)
420 self._test.registry.register(self, self._test.logger)
422 def remove_vpp_config(self):
423 self._test.vapi.gbp_vxlan_tunnel_del(self.vni)
426 return self.object_id()
429 return "gbp-vxlan:%d" % (self.vni)
431 def query_vpp_config(self):
432 return find_gbp_vxlan(self._test, self.vni)
435 class VppGbpAcl(VppObject):
440 def __init__(self, test):
442 self.acl_index = 4294967295
444 def create_rule(self, is_ipv6=0, permit_deny=0, proto=-1,
445 s_prefix=0, s_ip='\x00\x00\x00\x00', sport_from=0,
446 sport_to=65535, d_prefix=0, d_ip='\x00\x00\x00\x00',
447 dport_from=0, dport_to=65535):
448 if proto == -1 or proto == 0:
451 elif proto == 1 or proto == 58:
454 rule = ({'is_permit': permit_deny, 'is_ipv6': is_ipv6, 'proto': proto,
455 'srcport_or_icmptype_first': sport_from,
456 'srcport_or_icmptype_last': sport_to,
457 'src_ip_prefix_len': s_prefix,
459 'dstport_or_icmpcode_first': dport_from,
460 'dstport_or_icmpcode_last': dport_to,
461 'dst_ip_prefix_len': d_prefix,
462 'dst_ip_addr': d_ip})
465 def add_vpp_config(self, rules):
467 reply = self._test.vapi.acl_add_replace(self.acl_index,
470 self.acl_index = reply.acl_index
471 return self.acl_index
473 def remove_vpp_config(self):
474 self._test.vapi.acl_del(self.acl_index)
477 return self.object_id()
480 return "gbp-acl:[%d]" % (self.acl_index)
482 def query_vpp_config(self):
483 cs = self._test.vapi.acl_dump()
485 if c.acl_index == self.acl_index:
490 class TestGBP(VppTestCase):
491 """ GBP Test Case """
494 super(TestGBP, self).setUp()
496 self.create_pg_interfaces(range(9))
497 self.create_loopback_interfaces(8)
499 self.router_mac = VppMacAddress("00:11:22:33:44:55")
501 for i in self.pg_interfaces:
503 for i in self.lo_interfaces:
507 for i in self.pg_interfaces:
510 super(TestGBP, self).tearDown()
512 def send_and_expect_bridged(self, src, tx, dst):
513 rx = self.send_and_expect(src, tx, dst)
516 self.assertEqual(r[Ether].src, tx[0][Ether].src)
517 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
518 self.assertEqual(r[IP].src, tx[0][IP].src)
519 self.assertEqual(r[IP].dst, tx[0][IP].dst)
522 def send_and_expect_bridged6(self, src, tx, dst):
523 rx = self.send_and_expect(src, tx, dst)
526 self.assertEqual(r[Ether].src, tx[0][Ether].src)
527 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
528 self.assertEqual(r[IPv6].src, tx[0][IPv6].src)
529 self.assertEqual(r[IPv6].dst, tx[0][IPv6].dst)
532 def send_and_expect_routed(self, src, tx, dst, src_mac):
533 rx = self.send_and_expect(src, tx, dst)
536 self.assertEqual(r[Ether].src, src_mac)
537 self.assertEqual(r[Ether].dst, dst.remote_mac)
538 self.assertEqual(r[IP].src, tx[0][IP].src)
539 self.assertEqual(r[IP].dst, tx[0][IP].dst)
542 def send_and_expect_natted(self, src, tx, dst, src_ip):
543 rx = self.send_and_expect(src, tx, dst)
546 self.assertEqual(r[Ether].src, tx[0][Ether].src)
547 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
548 self.assertEqual(r[IP].src, src_ip)
549 self.assertEqual(r[IP].dst, tx[0][IP].dst)
552 def send_and_expect_natted6(self, src, tx, dst, src_ip):
553 rx = self.send_and_expect(src, tx, dst)
556 self.assertEqual(r[Ether].src, tx[0][Ether].src)
557 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
558 self.assertEqual(r[IPv6].src, src_ip)
559 self.assertEqual(r[IPv6].dst, tx[0][IPv6].dst)
562 def send_and_expect_unnatted(self, src, tx, dst, dst_ip):
563 rx = self.send_and_expect(src, tx, dst)
566 self.assertEqual(r[Ether].src, tx[0][Ether].src)
567 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
568 self.assertEqual(r[IP].dst, dst_ip)
569 self.assertEqual(r[IP].src, tx[0][IP].src)
572 def send_and_expect_unnatted6(self, src, tx, dst, dst_ip):
573 rx = self.send_and_expect(src, tx, dst)
576 self.assertEqual(r[Ether].src, tx[0][Ether].src)
577 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
578 self.assertEqual(r[IPv6].dst, dst_ip)
579 self.assertEqual(r[IPv6].src, tx[0][IPv6].src)
582 def send_and_expect_double_natted(self, src, tx, dst, src_ip, dst_ip):
583 rx = self.send_and_expect(src, tx, dst)
586 self.assertEqual(r[Ether].src, self.router_mac.address)
587 self.assertEqual(r[Ether].dst, dst.remote_mac)
588 self.assertEqual(r[IP].dst, dst_ip)
589 self.assertEqual(r[IP].src, src_ip)
592 def send_and_expect_double_natted6(self, src, tx, dst, src_ip, dst_ip):
593 rx = self.send_and_expect(src, tx, dst)
596 self.assertEqual(r[Ether].src, self.router_mac.address)
597 self.assertEqual(r[Ether].dst, dst.remote_mac)
598 self.assertEqual(r[IPv6].dst, dst_ip)
599 self.assertEqual(r[IPv6].src, src_ip)
603 """ Group Based Policy """
608 bd1 = VppBridgeDomain(self, 1)
609 bd2 = VppBridgeDomain(self, 2)
610 bd20 = VppBridgeDomain(self, 20)
614 bd20.add_vpp_config()
616 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0)
617 gbd2 = VppGbpBridgeDomain(self, bd2, self.loop1)
618 gbd20 = VppGbpBridgeDomain(self, bd20, self.loop2)
620 gbd1.add_vpp_config()
621 gbd2.add_vpp_config()
622 gbd20.add_vpp_config()
627 gt4 = VppIpTable(self, 0)
629 gt6 = VppIpTable(self, 0, is_ip6=True)
631 nt4 = VppIpTable(self, 20)
633 nt6 = VppIpTable(self, 20, is_ip6=True)
636 rd0 = VppGbpRouteDomain(self, 0, gt4, gt6, None, None)
637 rd20 = VppGbpRouteDomain(self, 20, nt4, nt6, None, None)
640 rd20.add_vpp_config()
643 # 3 EPGs, 2 of which share a BD.
644 # 2 NAT EPGs, one for floating-IP subnets, the other for internet
646 epgs = [VppGbpEndpointGroup(self, 220, rd0, gbd1, self.pg4,
650 VppGbpEndpointGroup(self, 221, rd0, gbd1, self.pg5,
654 VppGbpEndpointGroup(self, 222, rd0, gbd2, self.pg6,
658 VppGbpEndpointGroup(self, 333, rd20, gbd20, self.pg7,
662 VppGbpEndpointGroup(self, 444, rd20, gbd20, self.pg8,
666 recircs = [VppGbpRecirc(self, epgs[0],
668 VppGbpRecirc(self, epgs[1],
670 VppGbpRecirc(self, epgs[2],
672 VppGbpRecirc(self, epgs[3],
673 self.loop6, is_ext=True),
674 VppGbpRecirc(self, epgs[4],
675 self.loop7, is_ext=True)]
678 recirc_nat = recircs[3]
681 # 4 end-points, 2 in the same subnet, 3 in the same BD
683 eps = [VppGbpEndpoint(self, self.pg0,
685 "10.0.0.1", "11.0.0.1",
686 "2001:10::1", "3001::1"),
687 VppGbpEndpoint(self, self.pg1,
689 "10.0.0.2", "11.0.0.2",
690 "2001:10::2", "3001::2"),
691 VppGbpEndpoint(self, self.pg2,
693 "10.0.1.1", "11.0.0.3",
694 "2001:10:1::1", "3001::3"),
695 VppGbpEndpoint(self, self.pg3,
697 "10.0.2.1", "11.0.0.4",
698 "2001:10:2::1", "3001::4")]
701 # Config related to each of the EPGs
704 # IP config on the BVI interfaces
705 if epg != epgs[1] and epg != epgs[4]:
706 VppIpInterfaceBind(self, epg.bvi, epg.rd.t4).add_vpp_config()
707 VppIpInterfaceBind(self, epg.bvi, epg.rd.t6).add_vpp_config()
708 self.vapi.sw_interface_set_mac_address(
710 self.router_mac.bytes)
712 # The BVIs are NAT inside interfaces
713 self.vapi.nat44_interface_add_del_feature(epg.bvi.sw_if_index,
716 self.vapi.nat66_add_del_interface(epg.bvi.sw_if_index,
720 if_ip4 = VppIpInterfaceAddress(self, epg.bvi, epg.bvi_ip4, 32)
721 if_ip6 = VppIpInterfaceAddress(self, epg.bvi, epg.bvi_ip6, 128)
722 if_ip4.add_vpp_config()
723 if_ip6.add_vpp_config()
725 # EPG uplink interfaces in the RD
726 VppIpInterfaceBind(self, epg.uplink, epg.rd.t4).add_vpp_config()
727 VppIpInterfaceBind(self, epg.uplink, epg.rd.t6).add_vpp_config()
729 # add the BD ARP termination entry for BVI IP
730 epg.bd_arp_ip4 = VppBridgeDomainArpEntry(self, epg.bd.bd,
731 self.router_mac.address,
733 epg.bd_arp_ip6 = VppBridgeDomainArpEntry(self, epg.bd.bd,
734 self.router_mac.address,
736 epg.bd_arp_ip4.add_vpp_config()
737 epg.bd_arp_ip6.add_vpp_config()
742 for recirc in recircs:
743 # EPG's ingress recirculation interface maps to its RD
744 VppIpInterfaceBind(self, recirc.recirc,
745 recirc.epg.rd.t4).add_vpp_config()
746 VppIpInterfaceBind(self, recirc.recirc,
747 recirc.epg.rd.t6).add_vpp_config()
749 self.vapi.sw_interface_set_l2_emulation(
750 recirc.recirc.sw_if_index)
751 self.vapi.nat44_interface_add_del_feature(
752 recirc.recirc.sw_if_index,
755 self.vapi.nat66_add_del_interface(
756 recirc.recirc.sw_if_index,
760 recirc.add_vpp_config()
762 for recirc in recircs:
763 self.assertTrue(find_bridge_domain_port(self,
764 recirc.epg.bd.bd.bd_id,
765 recirc.recirc.sw_if_index))
768 self.pg_enable_capture(self.pg_interfaces)
771 # routes to the endpoints. We need these since there are no
772 # adj-fibs due to the fact the the BVI address has /32 and
773 # the subnet is not attached.
775 for (ip, fip) in zip(ep.ips, ep.fips):
776 # Add static mappings for each EP from the 10/8 to 11/8 network
778 self.vapi.nat44_add_del_static_mapping(ip.bytes,
783 self.vapi.nat66_add_del_static_mapping(ip.bytes,
790 self.logger.info(self.vapi.cli("sh gbp endpoint"))
792 # ... results in a Gratuitous ARP/ND on the EPG's uplink
793 rx = ep.epg.uplink.get_capture(len(ep.ips), timeout=0.2)
795 for ii, ip in enumerate(ep.ips):
799 self.assertTrue(p.haslayer(ICMPv6ND_NA))
800 self.assertEqual(p[ICMPv6ND_NA].tgt, ip.address)
802 self.assertTrue(p.haslayer(ARP))
803 self.assertEqual(p[ARP].psrc, ip.address)
804 self.assertEqual(p[ARP].pdst, ip.address)
806 # add the BD ARP termination entry for floating IP
808 ba = VppBridgeDomainArpEntry(self, epg_nat.bd.bd, ep.mac, fip)
811 # floating IPs route via EPG recirc
812 r = VppIpRoute(self, fip.address, fip.length,
813 [VppRoutePath(fip.address,
814 ep.recirc.recirc.sw_if_index,
816 proto=fip.dpo_proto)],
821 # L2 FIB entries in the NAT EPG BD to bridge the packets from
822 # the outside direct to the internal EPG
823 lf = VppL2FibEntry(self, epg_nat.bd.bd, ep.mac,
824 ep.recirc.recirc, bvi_mac=0)
828 # ARP packets for unknown IP are sent to the EPG uplink
830 pkt_arp = (Ether(dst="ff:ff:ff:ff:ff:ff",
831 src=self.pg0.remote_mac) /
833 hwdst="ff:ff:ff:ff:ff:ff",
834 hwsrc=self.pg0.remote_mac,
838 self.vapi.cli("clear trace")
839 self.pg0.add_stream(pkt_arp)
841 self.pg_enable_capture(self.pg_interfaces)
844 rxd = epgs[0].uplink.get_capture(1)
847 # ARP/ND packets get a response
849 pkt_arp = (Ether(dst="ff:ff:ff:ff:ff:ff",
850 src=self.pg0.remote_mac) /
852 hwdst="ff:ff:ff:ff:ff:ff",
853 hwsrc=self.pg0.remote_mac,
854 pdst=epgs[0].bvi_ip4.address,
855 psrc=eps[0].ip4.address))
857 self.send_and_expect(self.pg0, [pkt_arp], self.pg0)
859 nsma = in6_getnsma(inet_pton(AF_INET6, eps[0].ip6.address))
860 d = inet_ntop(AF_INET6, nsma)
861 pkt_nd = (Ether(dst=in6_getnsmac(nsma),
862 src=self.pg0.remote_mac) /
863 IPv6(dst=d, src=eps[0].ip6.address) /
864 ICMPv6ND_NS(tgt=epgs[0].bvi_ip6.address) /
865 ICMPv6NDOptSrcLLAddr(lladdr=self.pg0.remote_mac))
866 self.send_and_expect(self.pg0, [pkt_nd], self.pg0)
869 # broadcast packets are flooded
871 pkt_bcast = (Ether(dst="ff:ff:ff:ff:ff:ff",
872 src=self.pg0.remote_mac) /
873 IP(src=eps[0].ip4.address, dst="232.1.1.1") /
874 UDP(sport=1234, dport=1234) /
877 self.vapi.cli("clear trace")
878 self.pg0.add_stream(pkt_bcast)
880 self.pg_enable_capture(self.pg_interfaces)
883 rxd = eps[1].itf.get_capture(1)
884 self.assertEqual(rxd[0][Ether].dst, pkt_bcast[Ether].dst)
885 rxd = epgs[0].uplink.get_capture(1)
886 self.assertEqual(rxd[0][Ether].dst, pkt_bcast[Ether].dst)
889 # packets to non-local L3 destinations dropped
891 pkt_intra_epg_220_ip4 = (Ether(src=self.pg0.remote_mac,
892 dst=self.router_mac.address) /
893 IP(src=eps[0].ip4.address,
895 UDP(sport=1234, dport=1234) /
897 pkt_inter_epg_222_ip4 = (Ether(src=self.pg0.remote_mac,
898 dst=self.router_mac.address) /
899 IP(src=eps[0].ip4.address,
901 UDP(sport=1234, dport=1234) /
904 self.send_and_assert_no_replies(self.pg0, pkt_intra_epg_220_ip4 * 65)
906 pkt_inter_epg_222_ip6 = (Ether(src=self.pg0.remote_mac,
907 dst=self.router_mac.address) /
908 IPv6(src=eps[0].ip6.address,
910 UDP(sport=1234, dport=1234) /
912 self.send_and_assert_no_replies(self.pg0, pkt_inter_epg_222_ip6 * 65)
915 # Add the subnet routes
918 self, rd0, "10.0.0.0", 24,
919 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
921 self, rd0, "10.0.1.0", 24,
922 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
924 self, rd0, "10.0.2.0", 24,
925 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
927 self, rd0, "2001:10::1", 64,
928 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
930 self, rd0, "2001:10:1::1", 64,
931 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
933 self, rd0, "2001:10:2::1", 64,
934 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
942 self.send_and_expect_bridged(eps[0].itf,
943 pkt_intra_epg_220_ip4 * 65,
945 self.send_and_expect_bridged(eps[0].itf,
946 pkt_inter_epg_222_ip4 * 65,
948 self.send_and_expect_bridged6(eps[0].itf,
949 pkt_inter_epg_222_ip6 * 65,
952 self.logger.info(self.vapi.cli("sh ip fib 11.0.0.2"))
953 self.logger.info(self.vapi.cli("sh gbp endpoint-group"))
954 self.logger.info(self.vapi.cli("sh gbp endpoint"))
955 self.logger.info(self.vapi.cli("sh gbp recirc"))
956 self.logger.info(self.vapi.cli("sh int"))
957 self.logger.info(self.vapi.cli("sh int addr"))
958 self.logger.info(self.vapi.cli("sh int feat loop6"))
959 self.logger.info(self.vapi.cli("sh vlib graph ip4-gbp-src-classify"))
960 self.logger.info(self.vapi.cli("sh int feat loop3"))
961 self.logger.info(self.vapi.cli("sh int feat pg0"))
964 # Packet destined to unknown unicast is sent on the epg uplink ...
966 pkt_intra_epg_220_to_uplink = (Ether(src=self.pg0.remote_mac,
967 dst="00:00:00:33:44:55") /
968 IP(src=eps[0].ip4.address,
970 UDP(sport=1234, dport=1234) /
973 self.send_and_expect_bridged(eps[0].itf,
974 pkt_intra_epg_220_to_uplink * 65,
976 # ... and nowhere else
977 self.pg1.get_capture(0, timeout=0.1)
978 self.pg1.assert_nothing_captured(remark="Flood onto other VMS")
980 pkt_intra_epg_221_to_uplink = (Ether(src=self.pg2.remote_mac,
981 dst="00:00:00:33:44:66") /
982 IP(src=eps[0].ip4.address,
984 UDP(sport=1234, dport=1234) /
987 self.send_and_expect_bridged(eps[2].itf,
988 pkt_intra_epg_221_to_uplink * 65,
992 # Packets from the uplink are forwarded in the absence of a contract
994 pkt_intra_epg_220_from_uplink = (Ether(src="00:00:00:33:44:55",
995 dst=self.pg0.remote_mac) /
996 IP(src=eps[0].ip4.address,
998 UDP(sport=1234, dport=1234) /
1001 self.send_and_expect_bridged(self.pg4,
1002 pkt_intra_epg_220_from_uplink * 65,
1006 # in the absence of policy, endpoints in the same EPG
1009 pkt_intra_epg = (Ether(src=self.pg0.remote_mac,
1010 dst=self.pg1.remote_mac) /
1011 IP(src=eps[0].ip4.address,
1012 dst=eps[1].ip4.address) /
1013 UDP(sport=1234, dport=1234) /
1016 self.send_and_expect_bridged(self.pg0, pkt_intra_epg * 65, self.pg1)
1019 # in the abscense of policy, endpoints in the different EPG
1020 # cannot communicate
1022 pkt_inter_epg_220_to_221 = (Ether(src=self.pg0.remote_mac,
1023 dst=self.pg2.remote_mac) /
1024 IP(src=eps[0].ip4.address,
1025 dst=eps[2].ip4.address) /
1026 UDP(sport=1234, dport=1234) /
1028 pkt_inter_epg_221_to_220 = (Ether(src=self.pg2.remote_mac,
1029 dst=self.pg0.remote_mac) /
1030 IP(src=eps[2].ip4.address,
1031 dst=eps[0].ip4.address) /
1032 UDP(sport=1234, dport=1234) /
1034 pkt_inter_epg_220_to_222 = (Ether(src=self.pg0.remote_mac,
1035 dst=self.router_mac.address) /
1036 IP(src=eps[0].ip4.address,
1037 dst=eps[3].ip4.address) /
1038 UDP(sport=1234, dport=1234) /
1041 self.send_and_assert_no_replies(eps[0].itf,
1042 pkt_inter_epg_220_to_221 * 65)
1043 self.send_and_assert_no_replies(eps[0].itf,
1044 pkt_inter_epg_220_to_222 * 65)
1047 # A uni-directional contract from EPG 220 -> 221
1049 acl = VppGbpAcl(self)
1050 rule = acl.create_rule(permit_deny=1, proto=17)
1051 rule2 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
1052 acl_index = acl.add_vpp_config([rule, rule2])
1053 c1 = VppGbpContract(self, 220, 221, acl_index)
1056 self.send_and_expect_bridged(eps[0].itf,
1057 pkt_inter_epg_220_to_221 * 65,
1059 self.send_and_assert_no_replies(eps[0].itf,
1060 pkt_inter_epg_220_to_222 * 65)
1063 # contract for the return direction
1065 c2 = VppGbpContract(self, 221, 220, acl_index)
1068 self.send_and_expect_bridged(eps[0].itf,
1069 pkt_inter_epg_220_to_221 * 65,
1071 self.send_and_expect_bridged(eps[2].itf,
1072 pkt_inter_epg_221_to_220 * 65,
1076 # check that inter group is still disabled for the groups
1077 # not in the contract.
1079 self.send_and_assert_no_replies(eps[0].itf,
1080 pkt_inter_epg_220_to_222 * 65)
1083 # A uni-directional contract from EPG 220 -> 222 'L3 routed'
1085 c3 = VppGbpContract(self, 220, 222, acl_index)
1088 self.logger.info(self.vapi.cli("sh gbp contract"))
1090 self.send_and_expect_routed(eps[0].itf,
1091 pkt_inter_epg_220_to_222 * 65,
1093 self.router_mac.address)
1096 # remove both contracts, traffic stops in both directions
1098 c2.remove_vpp_config()
1099 c1.remove_vpp_config()
1100 c3.remove_vpp_config()
1101 acl.remove_vpp_config()
1103 self.send_and_assert_no_replies(eps[2].itf,
1104 pkt_inter_epg_221_to_220 * 65)
1105 self.send_and_assert_no_replies(eps[0].itf,
1106 pkt_inter_epg_220_to_221 * 65)
1107 self.send_and_expect_bridged(eps[0].itf,
1112 # EPs to the outside world
1115 # in the EP's RD an external subnet via the NAT EPG's recirc
1117 self, rd0, "0.0.0.0", 0,
1118 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1119 sw_if_index=recirc_nat.recirc.sw_if_index,
1122 self, rd0, "11.0.0.0", 8,
1123 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1124 sw_if_index=recirc_nat.recirc.sw_if_index,
1126 se16 = VppGbpSubnet(
1128 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1129 sw_if_index=recirc_nat.recirc.sw_if_index,
1131 # in the NAT RD an external subnet via the NAT EPG's uplink
1133 self, rd20, "0.0.0.0", 0,
1134 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1135 sw_if_index=epg_nat.uplink.sw_if_index,
1137 se36 = VppGbpSubnet(
1138 self, rd20, "::", 0,
1139 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1140 sw_if_index=epg_nat.uplink.sw_if_index,
1143 self, rd20, "11.0.0.0", 8,
1144 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1145 sw_if_index=epg_nat.uplink.sw_if_index,
1147 se1.add_vpp_config()
1148 se2.add_vpp_config()
1149 se16.add_vpp_config()
1150 se3.add_vpp_config()
1151 se36.add_vpp_config()
1152 se4.add_vpp_config()
1154 self.logger.info(self.vapi.cli("sh ip fib 0.0.0.0/0"))
1155 self.logger.info(self.vapi.cli("sh ip fib 11.0.0.1"))
1156 self.logger.info(self.vapi.cli("sh ip6 fib ::/0"))
1157 self.logger.info(self.vapi.cli("sh ip6 fib %s" %
1161 # From an EP to an outside addess: IN2OUT
1163 pkt_inter_epg_220_to_global = (Ether(src=self.pg0.remote_mac,
1164 dst=self.router_mac.address) /
1165 IP(src=eps[0].ip4.address,
1167 UDP(sport=1234, dport=1234) /
1171 self.send_and_assert_no_replies(eps[0].itf,
1172 pkt_inter_epg_220_to_global * 65)
1174 acl2 = VppGbpAcl(self)
1175 rule = acl2.create_rule(permit_deny=1, proto=17, sport_from=1234,
1176 sport_to=1234, dport_from=1234, dport_to=1234)
1177 rule2 = acl2.create_rule(is_ipv6=1, permit_deny=1, proto=17,
1178 sport_from=1234, sport_to=1234,
1179 dport_from=1234, dport_to=1234)
1181 acl_index2 = acl2.add_vpp_config([rule, rule2])
1182 c4 = VppGbpContract(self, 220, 333, acl_index2)
1185 self.send_and_expect_natted(eps[0].itf,
1186 pkt_inter_epg_220_to_global * 65,
1188 eps[0].fip4.address)
1190 pkt_inter_epg_220_to_global = (Ether(src=self.pg0.remote_mac,
1191 dst=self.router_mac.address) /
1192 IPv6(src=eps[0].ip6.address,
1194 UDP(sport=1234, dport=1234) /
1197 self.send_and_expect_natted6(self.pg0,
1198 pkt_inter_epg_220_to_global * 65,
1200 eps[0].fip6.address)
1203 # From a global address to an EP: OUT2IN
1205 pkt_inter_epg_220_from_global = (Ether(src=self.router_mac.address,
1206 dst=self.pg0.remote_mac) /
1207 IP(dst=eps[0].fip4.address,
1209 UDP(sport=1234, dport=1234) /
1212 self.send_and_assert_no_replies(self.pg7,
1213 pkt_inter_epg_220_from_global * 65)
1215 c5 = VppGbpContract(self, 333, 220, acl_index2)
1218 self.send_and_expect_unnatted(self.pg7,
1219 pkt_inter_epg_220_from_global * 65,
1223 pkt_inter_epg_220_from_global = (Ether(src=self.router_mac.address,
1224 dst=self.pg0.remote_mac) /
1225 IPv6(dst=eps[0].fip6.address,
1227 UDP(sport=1234, dport=1234) /
1230 self.send_and_expect_unnatted6(self.pg7,
1231 pkt_inter_epg_220_from_global * 65,
1236 # From a local VM to another local VM using resp. public addresses:
1239 pkt_intra_epg_220_global = (Ether(src=self.pg0.remote_mac,
1240 dst=self.router_mac.address) /
1241 IP(src=eps[0].ip4.address,
1242 dst=eps[1].fip4.address) /
1243 UDP(sport=1234, dport=1234) /
1246 self.send_and_expect_double_natted(eps[0].itf,
1247 pkt_intra_epg_220_global * 65,
1249 eps[0].fip4.address,
1252 pkt_intra_epg_220_global = (Ether(src=self.pg0.remote_mac,
1253 dst=self.router_mac.address) /
1254 IPv6(src=eps[0].ip6.address,
1255 dst=eps[1].fip6.address) /
1256 UDP(sport=1234, dport=1234) /
1259 self.send_and_expect_double_natted6(eps[0].itf,
1260 pkt_intra_epg_220_global * 65,
1262 eps[0].fip6.address,
1269 # del static mappings for each EP from the 10/8 to 11/8 network
1270 self.vapi.nat44_add_del_static_mapping(ep.ip4.bytes,
1275 self.vapi.nat66_add_del_static_mapping(ep.ip6.bytes,
1281 # IP config on the BVI interfaces
1282 if epg != epgs[0] and epg != epgs[3]:
1283 self.vapi.nat44_interface_add_del_feature(epg.bvi.sw_if_index,
1286 self.vapi.nat66_add_del_interface(epg.bvi.sw_if_index,
1290 for recirc in recircs:
1291 self.vapi.sw_interface_set_l2_emulation(
1292 recirc.recirc.sw_if_index, enable=0)
1293 self.vapi.nat44_interface_add_del_feature(
1294 recirc.recirc.sw_if_index,
1297 self.vapi.nat66_add_del_interface(
1298 recirc.recirc.sw_if_index,
1302 def test_gbp_learn_l2(self):
1303 """ GBP L2 Endpoint Learning """
1305 learnt = [{'mac': '00:00:11:11:11:01',
1307 'ip6': '2001:10::2'},
1308 {'mac': '00:00:11:11:11:02',
1310 'ip6': '2001:10::3'}]
1313 # lower the inactive threshold so these tests pass in a
1314 # reasonable amount of time
1316 self.vapi.gbp_endpoint_learn_set_inactive_threshold(1)
1321 gt4 = VppIpTable(self, 1)
1322 gt4.add_vpp_config()
1323 gt6 = VppIpTable(self, 1, is_ip6=True)
1324 gt6.add_vpp_config()
1326 rd1 = VppGbpRouteDomain(self, 1, gt4, gt6)
1327 rd1.add_vpp_config()
1330 # Pg2 hosts the vxlan tunnel, hosts on pg2 to act as TEPs
1331 # Pg3 hosts the IP4 UU-flood VXLAN tunnel
1332 # Pg4 hosts the IP6 UU-flood VXLAN tunnel
1334 self.pg2.config_ip4()
1335 self.pg2.resolve_arp()
1336 self.pg2.generate_remote_hosts(4)
1337 self.pg2.configure_ipv4_neighbors()
1338 self.pg3.config_ip4()
1339 self.pg3.resolve_arp()
1340 self.pg4.config_ip4()
1341 self.pg4.resolve_arp()
1344 # a GBP bridge domain with a BVI and a UU-flood interface
1346 bd1 = VppBridgeDomain(self, 1)
1347 bd1.add_vpp_config()
1348 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0, self.pg3)
1349 gbd1.add_vpp_config()
1351 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1352 self.logger.info(self.vapi.cli("sh gbp bridge"))
1354 # ... and has a /32 applied
1355 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
1356 ip_addr.add_vpp_config()
1359 # The Endpoint-group in which we are learning endpoints
1361 epg_220 = VppGbpEndpointGroup(self, 220, rd1, gbd1,
1365 epg_220.add_vpp_config()
1366 epg_330 = VppGbpEndpointGroup(self, 330, rd1, gbd1,
1370 epg_330.add_vpp_config()
1373 # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
1376 vx_tun_l2_1 = VppGbpVxlanTunnel(
1377 self, 99, bd1.bd_id,
1378 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L2)
1379 vx_tun_l2_1.add_vpp_config()
1382 # A static endpoint that the learnt endpoints are trying to
1385 ep = VppGbpEndpoint(self, self.pg0,
1387 "10.0.0.127", "11.0.0.127",
1388 "2001:10::1", "3001::1")
1391 self.assertTrue(find_route(self, ep.ip4.address, 32, table_id=1))
1393 # a packet with an sclass from an unknwon EPG
1394 p = (Ether(src=self.pg2.remote_mac,
1395 dst=self.pg2.local_mac) /
1396 IP(src=self.pg2.remote_hosts[0].ip4,
1397 dst=self.pg2.local_ip4) /
1398 UDP(sport=1234, dport=48879) /
1399 VXLAN(vni=99, gpid=88, flags=0x88) /
1400 Ether(src=learnt[0]["mac"], dst=ep.mac) /
1401 IP(src=learnt[0]["ip"], dst=ep.ip4.address) /
1402 UDP(sport=1234, dport=1234) /
1405 self.send_and_assert_no_replies(self.pg2, p)
1408 # we should not have learnt a new tunnel endpoint, since
1409 # the EPG was not learnt.
1411 self.assertEqual(INDEX_INVALID,
1412 find_vxlan_gbp_tunnel(self,
1414 self.pg2.remote_hosts[0].ip4,
1417 # epg is not learnt, becasue the EPG is unknwon
1418 self.assertEqual(len(self.vapi.gbp_endpoint_dump()), 1)
1420 for ii, l in enumerate(learnt):
1421 # a packet with an sclass from a knwon EPG
1422 # arriving on an unknown TEP
1423 p = (Ether(src=self.pg2.remote_mac,
1424 dst=self.pg2.local_mac) /
1425 IP(src=self.pg2.remote_hosts[1].ip4,
1426 dst=self.pg2.local_ip4) /
1427 UDP(sport=1234, dport=48879) /
1428 VXLAN(vni=99, gpid=220, flags=0x88) /
1429 Ether(src=l['mac'], dst=ep.mac) /
1430 IP(src=l['ip'], dst=ep.ip4.address) /
1431 UDP(sport=1234, dport=1234) /
1434 rx = self.send_and_expect(self.pg2, [p], self.pg0)
1437 tep1_sw_if_index = find_vxlan_gbp_tunnel(
1440 self.pg2.remote_hosts[1].ip4,
1442 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
1445 # the EP is learnt via the learnt TEP
1446 # both from its MAC and its IP
1448 self.assertTrue(find_gbp_endpoint(self,
1449 vx_tun_l2_1.sw_if_index,
1451 self.assertTrue(find_gbp_endpoint(self,
1452 vx_tun_l2_1.sw_if_index,
1455 self.logger.info(self.vapi.cli("show gbp endpoint"))
1456 self.logger.info(self.vapi.cli("show gbp vxlan"))
1457 self.logger.info(self.vapi.cli("show vxlan-gbp tunnel"))
1460 # If we sleep for the threshold time, the learnt endpoints should
1465 self.assertFalse(find_gbp_endpoint(self,
1469 self.logger.info(self.vapi.cli("show gbp endpoint"))
1470 self.logger.info(self.vapi.cli("show gbp vxlan"))
1471 self.logger.info(self.vapi.cli("show vxlan-gbp tunnel"))
1474 # repeat. the do not learn bit is set so the EPs are not learnt
1477 # a packet with an sclass from a knwon EPG
1478 p = (Ether(src=self.pg2.remote_mac,
1479 dst=self.pg2.local_mac) /
1480 IP(src=self.pg2.remote_hosts[1].ip4,
1481 dst=self.pg2.local_ip4) /
1482 UDP(sport=1234, dport=48879) /
1483 VXLAN(vni=99, gpid=220, flags=0x88, gpflags="D") /
1484 Ether(src=l['mac'], dst=ep.mac) /
1485 IP(src=l['ip'], dst=ep.ip4.address) /
1486 UDP(sport=1234, dport=1234) /
1489 rx = self.send_and_expect(self.pg2, p*65, self.pg0)
1492 self.assertFalse(find_gbp_endpoint(self,
1493 vx_tun_l2_1.sw_if_index,
1500 # a packet with an sclass from a knwon EPG
1501 p = (Ether(src=self.pg2.remote_mac,
1502 dst=self.pg2.local_mac) /
1503 IP(src=self.pg2.remote_hosts[1].ip4,
1504 dst=self.pg2.local_ip4) /
1505 UDP(sport=1234, dport=48879) /
1506 VXLAN(vni=99, gpid=220, flags=0x88) /
1507 Ether(src=l['mac'], dst=ep.mac) /
1508 IP(src=l['ip'], dst=ep.ip4.address) /
1509 UDP(sport=1234, dport=1234) /
1512 rx = self.send_and_expect(self.pg2, p*65, self.pg0)
1514 self.assertTrue(find_gbp_endpoint(self,
1515 vx_tun_l2_1.sw_if_index,
1519 # Static EP replies to dynamics
1521 self.logger.info(self.vapi.cli("sh l2fib bd_id 1"))
1523 p = (Ether(src=ep.mac, dst=l['mac']) /
1524 IP(dst=l['ip'], src=ep.ip4.address) /
1525 UDP(sport=1234, dport=1234) /
1528 rxs = self.send_and_expect(self.pg0, p * 17, self.pg2)
1531 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
1532 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
1533 self.assertEqual(rx[UDP].dport, 48879)
1534 # the UDP source port is a random value for hashing
1535 self.assertEqual(rx[VXLAN].gpid, 220)
1536 self.assertEqual(rx[VXLAN].vni, 99)
1537 self.assertTrue(rx[VXLAN].flags.G)
1538 self.assertTrue(rx[VXLAN].flags.Instance)
1539 self.assertTrue(rx[VXLAN].gpflags.A)
1540 self.assertFalse(rx[VXLAN].gpflags.D)
1544 self.assertFalse(find_gbp_endpoint(self,
1545 vx_tun_l2_1.sw_if_index,
1549 # repeat in the other EPG
1550 # there's no contract between 220 and 330, but the A-bit is set
1551 # so the packet is cleared for delivery
1554 # a packet with an sclass from a knwon EPG
1555 p = (Ether(src=self.pg2.remote_mac,
1556 dst=self.pg2.local_mac) /
1557 IP(src=self.pg2.remote_hosts[1].ip4,
1558 dst=self.pg2.local_ip4) /
1559 UDP(sport=1234, dport=48879) /
1560 VXLAN(vni=99, gpid=330, flags=0x88, gpflags='A') /
1561 Ether(src=l['mac'], dst=ep.mac) /
1562 IP(src=l['ip'], dst=ep.ip4.address) /
1563 UDP(sport=1234, dport=1234) /
1566 rx = self.send_and_expect(self.pg2, p*65, self.pg0)
1568 self.assertTrue(find_gbp_endpoint(self,
1569 vx_tun_l2_1.sw_if_index,
1573 # static EP cannot reach the learnt EPs since there is no contract
1575 self.logger.info(self.vapi.cli("show gbp endpoint"))
1576 self.logger.info(self.vapi.cli("show l2fib all"))
1578 p = (Ether(src=ep.mac, dst=l['mac']) /
1579 IP(dst=l['ip'], src=ep.ip4.address) /
1580 UDP(sport=1234, dport=1234) /
1583 self.send_and_assert_no_replies(self.pg0, [p], timeout=0.2)
1586 # refresh the entries after the check for no replies above
1589 # a packet with an sclass from a knwon EPG
1590 p = (Ether(src=self.pg2.remote_mac,
1591 dst=self.pg2.local_mac) /
1592 IP(src=self.pg2.remote_hosts[1].ip4,
1593 dst=self.pg2.local_ip4) /
1594 UDP(sport=1234, dport=48879) /
1595 VXLAN(vni=99, gpid=330, flags=0x88, gpflags='A') /
1596 Ether(src=l['mac'], dst=ep.mac) /
1597 IP(src=l['ip'], dst=ep.ip4.address) /
1598 UDP(sport=1234, dport=1234) /
1601 rx = self.send_and_expect(self.pg2, p*65, self.pg0)
1603 self.assertTrue(find_gbp_endpoint(self,
1604 vx_tun_l2_1.sw_if_index,
1608 # Add the contract so they can talk
1610 acl = VppGbpAcl(self)
1611 rule = acl.create_rule(permit_deny=1, proto=17)
1612 rule2 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
1613 acl_index = acl.add_vpp_config([rule, rule2])
1614 c1 = VppGbpContract(self, 220, 330, acl_index)
1618 p = (Ether(src=ep.mac, dst=l['mac']) /
1619 IP(dst=l['ip'], src=ep.ip4.address) /
1620 UDP(sport=1234, dport=1234) /
1623 self.send_and_expect(self.pg0, [p], self.pg2)
1626 # send UU packets from the local EP
1628 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1629 self.logger.info(self.vapi.cli("sh gbp bridge"))
1630 p_uu = (Ether(src=ep.mac, dst="00:11:11:11:11:11") /
1631 IP(dst="10.0.0.133", src=ep.ip4.address) /
1632 UDP(sport=1234, dport=1234) /
1634 rxs = self.send_and_expect(ep.itf, [p_uu], gbd1.uu_flood)
1637 # Add a mcast destination VXLAN-GBP tunnel for B&M traffic
1639 tun_bm = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
1642 tun_bm.add_vpp_config()
1643 bp_bm = VppBridgeDomainPort(self, bd1, tun_bm,
1644 port_type=L2_PORT_TYPE.NORMAL)
1645 bp_bm.add_vpp_config()
1647 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1649 p_bm = (Ether(src=ep.mac, dst="ff:ff:ff:ff:ff:ff") /
1650 IP(dst="10.0.0.133", src=ep.ip4.address) /
1651 UDP(sport=1234, dport=1234) /
1653 rxs = self.send_and_expect_only(ep.itf, [p_bm], tun_bm.mcast_itf)
1656 # Check v6 Endpoints
1659 # a packet with an sclass from a knwon EPG
1660 p = (Ether(src=self.pg2.remote_mac,
1661 dst=self.pg2.local_mac) /
1662 IP(src=self.pg2.remote_hosts[1].ip4,
1663 dst=self.pg2.local_ip4) /
1664 UDP(sport=1234, dport=48879) /
1665 VXLAN(vni=99, gpid=330, flags=0x88, gpflags='A') /
1666 Ether(src=l['mac'], dst=ep.mac) /
1667 IPv6(src=l['ip6'], dst=ep.ip6.address) /
1668 UDP(sport=1234, dport=1234) /
1671 rx = self.send_and_expect(self.pg2, p*65, self.pg0)
1673 self.assertTrue(find_gbp_endpoint(self,
1674 vx_tun_l2_1.sw_if_index,
1678 # L3 Endpoint Learning
1679 # - configured on the bridge's BVI
1687 self.assertFalse(find_gbp_endpoint(self,
1688 vx_tun_l2_1.sw_if_index,
1691 self.pg2.unconfig_ip4()
1692 self.pg3.unconfig_ip4()
1693 self.pg4.unconfig_ip4()
1695 self.logger.info(self.vapi.cli("sh int"))
1696 self.logger.info(self.vapi.cli("sh gbp vxlan"))
1698 def test_gbp_learn_l3(self):
1699 """ GBP L3 Endpoint Learning """
1701 routed_dst_mac = "00:0c:0c:0c:0c:0c"
1702 routed_src_mac = "00:22:bd:f8:19:ff"
1704 learnt = [{'mac': '00:00:11:11:11:02',
1706 'ip6': '2001:10::2'},
1707 {'mac': '00:00:11:11:11:03',
1709 'ip6': '2001:10::3'}]
1712 # lower the inactive threshold so these tests pass in a
1713 # reasonable amount of time
1715 self.vapi.gbp_endpoint_learn_set_inactive_threshold(1)
1720 t4 = VppIpTable(self, 1)
1722 t6 = VppIpTable(self, 1, True)
1725 tun_ip4_uu = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
1726 self.pg4.remote_ip4, 114)
1727 tun_ip6_uu = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
1728 self.pg4.remote_ip4, 116)
1729 tun_ip4_uu.add_vpp_config()
1730 tun_ip6_uu.add_vpp_config()
1732 rd1 = VppGbpRouteDomain(self, 2, t4, t6, tun_ip4_uu, tun_ip6_uu)
1733 rd1.add_vpp_config()
1735 self.loop0.set_mac(self.router_mac.address)
1738 # Bind the BVI to the RD
1740 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
1741 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
1744 # Pg2 hosts the vxlan tunnel
1745 # hosts on pg2 to act as TEPs
1749 self.pg2.config_ip4()
1750 self.pg2.resolve_arp()
1751 self.pg2.generate_remote_hosts(4)
1752 self.pg2.configure_ipv4_neighbors()
1753 self.pg3.config_ip4()
1754 self.pg3.resolve_arp()
1755 self.pg4.config_ip4()
1756 self.pg4.resolve_arp()
1759 # a GBP bridge domain with a BVI and a UU-flood interface
1761 bd1 = VppBridgeDomain(self, 1)
1762 bd1.add_vpp_config()
1763 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0, self.pg3)
1764 gbd1.add_vpp_config()
1766 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1767 self.logger.info(self.vapi.cli("sh gbp bridge"))
1768 self.logger.info(self.vapi.cli("sh gbp route"))
1769 self.logger.info(self.vapi.cli("show l2fib all"))
1771 # ... and has a /32 and /128 applied
1772 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
1773 ip4_addr.add_vpp_config()
1774 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 128)
1775 ip6_addr.add_vpp_config()
1778 # The Endpoint-group in which we are learning endpoints
1780 epg_220 = VppGbpEndpointGroup(self, 220, rd1, gbd1,
1784 epg_220.add_vpp_config()
1787 # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
1790 vx_tun_l3 = VppGbpVxlanTunnel(
1791 self, 101, rd1.rd_id,
1792 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3)
1793 vx_tun_l3.add_vpp_config()
1796 # A static endpoint that the learnt endpoints are trying to
1799 ep = VppGbpEndpoint(self, self.pg0,
1801 "10.0.0.127", "11.0.0.127",
1802 "2001:10::1", "3001::1")
1806 # learn some remote IPv4 EPs
1808 for ii, l in enumerate(learnt):
1809 # a packet with an sclass from a knwon EPG
1810 # arriving on an unknown TEP
1811 p = (Ether(src=self.pg2.remote_mac,
1812 dst=self.pg2.local_mac) /
1813 IP(src=self.pg2.remote_hosts[1].ip4,
1814 dst=self.pg2.local_ip4) /
1815 UDP(sport=1234, dport=48879) /
1816 VXLAN(vni=101, gpid=220, flags=0x88) /
1817 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
1818 IP(src=l['ip'], dst=ep.ip4.address) /
1819 UDP(sport=1234, dport=1234) /
1822 rx = self.send_and_expect(self.pg2, [p], self.pg0)
1825 tep1_sw_if_index = find_vxlan_gbp_tunnel(
1828 self.pg2.remote_hosts[1].ip4,
1830 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
1832 # endpoint learnt via the parent GBP-vxlan interface
1833 self.assertTrue(find_gbp_endpoint(self,
1834 vx_tun_l3._sw_if_index,
1838 # Static IPv4 EP replies to learnt
1841 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
1842 IP(dst=l['ip'], src=ep.ip4.address) /
1843 UDP(sport=1234, dport=1234) /
1846 rxs = self.send_and_expect(self.pg0, p*1, self.pg2)
1849 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
1850 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
1851 self.assertEqual(rx[UDP].dport, 48879)
1852 # the UDP source port is a random value for hashing
1853 self.assertEqual(rx[VXLAN].gpid, 220)
1854 self.assertEqual(rx[VXLAN].vni, 101)
1855 self.assertTrue(rx[VXLAN].flags.G)
1856 self.assertTrue(rx[VXLAN].flags.Instance)
1857 self.assertTrue(rx[VXLAN].gpflags.A)
1858 self.assertFalse(rx[VXLAN].gpflags.D)
1860 inner = rx[VXLAN].payload
1862 self.assertEqual(inner[Ether].src, routed_src_mac)
1863 self.assertEqual(inner[Ether].dst, routed_dst_mac)
1864 self.assertEqual(inner[IP].src, ep.ip4.address)
1865 self.assertEqual(inner[IP].dst, l['ip'])
1869 self.assertFalse(find_gbp_endpoint(self,
1874 # learn some remote IPv6 EPs
1876 for ii, l in enumerate(learnt):
1877 # a packet with an sclass from a knwon EPG
1878 # arriving on an unknown TEP
1879 p = (Ether(src=self.pg2.remote_mac,
1880 dst=self.pg2.local_mac) /
1881 IP(src=self.pg2.remote_hosts[1].ip4,
1882 dst=self.pg2.local_ip4) /
1883 UDP(sport=1234, dport=48879) /
1884 VXLAN(vni=101, gpid=220, flags=0x88) /
1885 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
1886 IPv6(src=l['ip6'], dst=ep.ip6.address) /
1887 UDP(sport=1234, dport=1234) /
1890 rx = self.send_and_expect(self.pg2, [p], self.pg0)
1893 tep1_sw_if_index = find_vxlan_gbp_tunnel(
1896 self.pg2.remote_hosts[1].ip4,
1898 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
1900 self.logger.info(self.vapi.cli("show gbp bridge"))
1901 self.logger.info(self.vapi.cli("show vxlan-gbp tunnel"))
1902 self.logger.info(self.vapi.cli("show gbp vxlan"))
1903 self.logger.info(self.vapi.cli("show int addr"))
1905 # endpoint learnt via the TEP
1906 self.assertTrue(find_gbp_endpoint(self, ip=l['ip6']))
1908 self.logger.info(self.vapi.cli("show gbp endpoint"))
1909 self.logger.info(self.vapi.cli("show ip fib index 1 %s" % l['ip']))
1912 # Static EP replies to learnt
1915 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
1916 IPv6(dst=l['ip6'], src=ep.ip6.address) /
1917 UDP(sport=1234, dport=1234) /
1920 rxs = self.send_and_expect(self.pg0, p*65, self.pg2)
1923 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
1924 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
1925 self.assertEqual(rx[UDP].dport, 48879)
1926 # the UDP source port is a random value for hashing
1927 self.assertEqual(rx[VXLAN].gpid, 220)
1928 self.assertEqual(rx[VXLAN].vni, 101)
1929 self.assertTrue(rx[VXLAN].flags.G)
1930 self.assertTrue(rx[VXLAN].flags.Instance)
1931 self.assertTrue(rx[VXLAN].gpflags.A)
1932 self.assertFalse(rx[VXLAN].gpflags.D)
1934 inner = rx[VXLAN].payload
1936 self.assertEqual(inner[Ether].src, routed_src_mac)
1937 self.assertEqual(inner[Ether].dst, routed_dst_mac)
1938 self.assertEqual(inner[IPv6].src, ep.ip6.address)
1939 self.assertEqual(inner[IPv6].dst, l['ip6'])
1941 self.logger.info(self.vapi.cli("sh gbp endpoint"))
1944 self.assertFalse(find_gbp_endpoint(self,
1949 # Static sends to unknown EP with no route
1951 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
1952 IP(dst="10.0.0.99", src=ep.ip4.address) /
1953 UDP(sport=1234, dport=1234) /
1956 self.send_and_assert_no_replies(self.pg0, [p])
1959 # Add a route to static EP's v4 and v6 subnet
1960 # packets should be send on the v4/v6 uu=fwd interface resp.
1962 se_10_24 = VppGbpSubnet(
1963 self, rd1, "10.0.0.0", 24,
1964 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT)
1965 se_10_24.add_vpp_config()
1967 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
1968 IP(dst="10.0.0.99", src=ep.ip4.address) /
1969 UDP(sport=1234, dport=1234) /
1972 rxs = self.send_and_expect(self.pg0, [p], self.pg4)
1974 self.assertEqual(rx[IP].src, self.pg4.local_ip4)
1975 self.assertEqual(rx[IP].dst, self.pg4.remote_ip4)
1976 self.assertEqual(rx[UDP].dport, 48879)
1977 # the UDP source port is a random value for hashing
1978 self.assertEqual(rx[VXLAN].gpid, 220)
1979 self.assertEqual(rx[VXLAN].vni, 114)
1980 self.assertTrue(rx[VXLAN].flags.G)
1981 self.assertTrue(rx[VXLAN].flags.Instance)
1982 # policy is not applied to packets sent to the uu-fwd interfaces
1983 self.assertFalse(rx[VXLAN].gpflags.A)
1984 self.assertFalse(rx[VXLAN].gpflags.D)
1987 # learn some remote IPv4 EPs
1989 for ii, l in enumerate(learnt):
1990 # a packet with an sclass from a knwon EPG
1991 # arriving on an unknown TEP
1992 p = (Ether(src=self.pg2.remote_mac,
1993 dst=self.pg2.local_mac) /
1994 IP(src=self.pg2.remote_hosts[1].ip4,
1995 dst=self.pg2.local_ip4) /
1996 UDP(sport=1234, dport=48879) /
1997 VXLAN(vni=101, gpid=220, flags=0x88) /
1998 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
1999 IP(src=l['ip'], dst=ep.ip4.address) /
2000 UDP(sport=1234, dport=1234) /
2003 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2006 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2009 self.pg2.remote_hosts[1].ip4,
2011 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2013 # endpoint learnt via the parent GBP-vxlan interface
2014 self.assertTrue(find_gbp_endpoint(self,
2015 vx_tun_l3._sw_if_index,
2019 # Add a remote endpoint from the API
2021 rep_88 = VppGbpEndpoint(self, vx_tun_l3,
2023 "10.0.0.88", "11.0.0.88",
2024 "2001:10::88", "3001::88",
2025 VppEnum.vl_api_gbp_endpoint_flags_t.REMOTE,
2027 self.pg2.remote_hosts[1].ip4,
2029 rep_88.add_vpp_config()
2032 # Add a remote endpoint from the API that matches an existing one
2034 rep_2 = VppGbpEndpoint(self, vx_tun_l3,
2036 learnt[0]['ip'], "11.0.0.101",
2037 learnt[0]['ip6'], "3001::101",
2038 VppEnum.vl_api_gbp_endpoint_flags_t.REMOTE,
2040 self.pg2.remote_hosts[1].ip4,
2042 rep_2.add_vpp_config()
2045 # Add a route to the leanred EP's v4 subnet
2046 # packets should be send on the v4/v6 uu=fwd interface resp.
2048 se_10_1_24 = VppGbpSubnet(
2049 self, rd1, "10.0.1.0", 24,
2050 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT)
2051 se_10_1_24.add_vpp_config()
2053 self.logger.info(self.vapi.cli("show gbp endpoint"))
2055 ips = ["10.0.0.88", learnt[0]['ip']]
2057 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2058 IP(dst=ip, src=ep.ip4.address) /
2059 UDP(sport=1234, dport=1234) /
2062 rxs = self.send_and_expect(self.pg0, p*65, self.pg2)
2065 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2066 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2067 self.assertEqual(rx[UDP].dport, 48879)
2068 # the UDP source port is a random value for hashing
2069 self.assertEqual(rx[VXLAN].gpid, 220)
2070 self.assertEqual(rx[VXLAN].vni, 101)
2071 self.assertTrue(rx[VXLAN].flags.G)
2072 self.assertTrue(rx[VXLAN].flags.Instance)
2073 self.assertTrue(rx[VXLAN].gpflags.A)
2074 self.assertFalse(rx[VXLAN].gpflags.D)
2076 inner = rx[VXLAN].payload
2078 self.assertEqual(inner[Ether].src, routed_src_mac)
2079 self.assertEqual(inner[Ether].dst, routed_dst_mac)
2080 self.assertEqual(inner[IP].src, ep.ip4.address)
2081 self.assertEqual(inner[IP].dst, ip)
2084 # remove the API remote EPs, they are now UU-fwd
2086 rep_88.remove_vpp_config()
2087 rep_2.remove_vpp_config()
2089 self.logger.info(self.vapi.cli("show gbp endpoint"))
2092 self.assertFalse(find_gbp_endpoint(self, ip=ip))
2094 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2095 IP(dst=ip, src=ep.ip4.address) /
2096 UDP(sport=1234, dport=1234) /
2099 rxs = self.send_and_expect(self.pg0, [p], self.pg4)
2102 # shutdown with learnt endpoint present
2104 self.logger.info(self.vapi.cli("show gbp endpoint-group"))
2108 # remote endpoint becomes local
2110 self.pg2.unconfig_ip4()
2111 self.pg3.unconfig_ip4()
2112 self.pg4.unconfig_ip4()
2115 if __name__ == '__main__':
2116 unittest.main(testRunner=VppTestRunner)