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 *
13 from vpp_sub_interface import VppDot1QSubint
17 from vpp_papi_provider import L2_PORT_TYPE
18 from vpp_papi import VppEnum
20 from scapy.packet import Raw
21 from scapy.layers.l2 import Ether, ARP, Dot1Q
22 from scapy.layers.inet import IP, UDP
23 from scapy.layers.inet6 import IPv6, ICMPv6ND_NS, ICMPv6NDOptSrcLLAddr, \
25 from scapy.utils6 import in6_getnsma, in6_getnsmac
26 from scapy.layers.vxlan import VXLAN
28 from socket import AF_INET, AF_INET6
29 from scapy.utils import inet_pton, inet_ntop
30 from util import mactobinary
31 from vpp_papi_provider import L2_VTR_OP
34 def find_gbp_endpoint(test, sw_if_index=None, ip=None, mac=None):
36 vip = VppIpAddress(ip)
38 vmac = VppMacAddress(mac)
40 eps = test.vapi.gbp_endpoint_dump()
44 if ep.endpoint.sw_if_index != sw_if_index:
47 for eip in ep.endpoint.ips:
51 if vmac == ep.endpoint.mac:
56 def find_gbp_vxlan(test, vni):
57 ts = test.vapi.gbp_vxlan_tunnel_dump()
59 if t.tunnel.vni == vni:
64 class VppGbpEndpoint(VppObject):
71 return self.vmac.bytes
75 return self.vmac.address
79 return self.itf.remote_mac
99 return [self.ip4, self.ip6]
103 return [self.fip4, self.fip6]
105 def __init__(self, test, itf, epg, recirc, ip4, fip4, ip6, fip6,
115 self._ip4 = VppIpAddress(ip4)
116 self._fip4 = VppIpAddress(fip4)
117 self._ip6 = VppIpAddress(ip6)
118 self._fip6 = VppIpAddress(fip6)
121 self.vmac = VppMacAddress(self.itf.remote_mac)
123 self.vmac = VppMacAddress("00:00:00:00:00:00")
126 self.tun_src = VppIpAddress(tun_src)
127 self.tun_dst = VppIpAddress(tun_dst)
129 def add_vpp_config(self):
130 res = self._test.vapi.gbp_endpoint_add(
131 self.itf.sw_if_index,
132 [self.ip4.encode(), self.ip6.encode()],
136 self.tun_src.encode(),
137 self.tun_dst.encode())
138 self.handle = res.handle
139 self._test.registry.register(self, self._test.logger)
141 def remove_vpp_config(self):
142 self._test.vapi.gbp_endpoint_del(self.handle)
145 return self.object_id()
148 return "gbp-endpoint:[%d==%d:%s:%d]" % (self.handle,
149 self.itf.sw_if_index,
153 def query_vpp_config(self):
154 return find_gbp_endpoint(self._test,
155 self.itf.sw_if_index,
159 class VppGbpRecirc(VppObject):
161 GBP Recirculation Interface
164 def __init__(self, test, epg, recirc, is_ext=False):
170 def add_vpp_config(self):
171 self._test.vapi.gbp_recirc_add_del(
173 self.recirc.sw_if_index,
176 self._test.registry.register(self, self._test.logger)
178 def remove_vpp_config(self):
179 self._test.vapi.gbp_recirc_add_del(
181 self.recirc.sw_if_index,
186 return self.object_id()
189 return "gbp-recirc:[%d]" % (self.recirc.sw_if_index)
191 def query_vpp_config(self):
192 rs = self._test.vapi.gbp_recirc_dump()
194 if r.recirc.sw_if_index == self.recirc.sw_if_index:
199 class VppGbpSubnet(VppObject):
203 def __init__(self, test, rd, address, address_len,
204 type, sw_if_index=None, epg=None):
206 self.rd_id = rd.rd_id
207 self.prefix = VppIpPrefix(address, address_len)
209 self.sw_if_index = sw_if_index
212 def add_vpp_config(self):
213 self._test.vapi.gbp_subnet_add_del(
216 self.prefix.encode(),
218 sw_if_index=self.sw_if_index if self.sw_if_index else 0xffffffff,
219 epg_id=self.epg if self.epg else 0xffff)
220 self._test.registry.register(self, self._test.logger)
222 def remove_vpp_config(self):
223 self._test.vapi.gbp_subnet_add_del(
226 self.prefix.encode(),
230 return self.object_id()
233 return "gbp-subnet:[%d-%s]" % (self.rd_id, self.prefix)
235 def query_vpp_config(self):
236 ss = self._test.vapi.gbp_subnet_dump()
238 if s.subnet.rd_id == self.rd_id and \
239 s.subnet.type == self.type and \
240 s.subnet.prefix == self.prefix:
245 class VppGbpEndpointGroup(VppObject):
250 def __init__(self, test, epg, rd, bd, uplink,
251 bvi, bvi_ip4, bvi_ip6=None):
255 self.bvi_ip4 = VppIpAddress(bvi_ip4)
256 self.bvi_ip6 = VppIpAddress(bvi_ip6)
261 def add_vpp_config(self):
262 self._test.vapi.gbp_endpoint_group_add(
266 self.uplink.sw_if_index if self.uplink else INDEX_INVALID)
267 self._test.registry.register(self, self._test.logger)
269 def remove_vpp_config(self):
270 self._test.vapi.gbp_endpoint_group_del(
274 return self.object_id()
277 return "gbp-endpoint-group:[%d]" % (self.epg)
279 def query_vpp_config(self):
280 epgs = self._test.vapi.gbp_endpoint_group_dump()
282 if epg.epg.epg_id == self.epg:
287 class VppGbpBridgeDomain(VppObject):
292 def __init__(self, test, bd, bvi, uu_flood=None, learn=True):
295 self.uu_flood = uu_flood
298 e = VppEnum.vl_api_gbp_bridge_domain_flags_t
300 self.learn = e.GBP_BD_API_FLAG_NONE
302 self.learn = e.GBP_BD_API_FLAG_DO_NOT_LEARN
304 def add_vpp_config(self):
305 self._test.vapi.gbp_bridge_domain_add(
308 self.bvi.sw_if_index,
309 self.uu_flood.sw_if_index if self.uu_flood else INDEX_INVALID)
310 self._test.registry.register(self, self._test.logger)
312 def remove_vpp_config(self):
313 self._test.vapi.gbp_bridge_domain_del(self.bd.bd_id)
316 return self.object_id()
319 return "gbp-bridge-domain:[%d]" % (self.bd.bd_id)
321 def query_vpp_config(self):
322 bds = self._test.vapi.gbp_bridge_domain_dump()
324 if bd.bd.bd_id == self.bd.bd_id:
329 class VppGbpRouteDomain(VppObject):
334 def __init__(self, test, rd_id, t4, t6, ip4_uu=None, ip6_uu=None):
342 def add_vpp_config(self):
343 self._test.vapi.gbp_route_domain_add(
347 self.ip4_uu.sw_if_index if self.ip4_uu else INDEX_INVALID,
348 self.ip6_uu.sw_if_index if self.ip6_uu else INDEX_INVALID)
349 self._test.registry.register(self, self._test.logger)
351 def remove_vpp_config(self):
352 self._test.vapi.gbp_route_domain_del(self.rd_id)
355 return self.object_id()
358 return "gbp-route-domain:[%d]" % (self.rd_id)
360 def query_vpp_config(self):
361 rds = self._test.vapi.gbp_route_domain_dump()
363 if rd.rd.rd_id == self.rd_id:
368 class VppGbpContractNextHop():
369 def __init__(self, mac, bd, ip, rd):
376 return {'ip': self.ip.encode(),
377 'mac': self.mac.encode(),
378 'bd_id': self.bd.bd.bd_id,
379 'rd_id': self.rd.rd_id}
382 class VppGbpContractRule():
383 def __init__(self, action, nhs=[]):
386 e = VppEnum.vl_api_gbp_hash_mode_t
387 self.hash_mode = e.GBP_API_HASH_MODE_SRC_IP
392 nhs.append(nh.encode())
395 return {'action': self.action,
397 'hash_mode': self.hash_mode,
398 'n_nhs': len(self.nhs),
402 class VppGbpContract(VppObject):
407 def __init__(self, test, src_epg, dst_epg, acl_index, rules=[]):
409 self.acl_index = acl_index
410 self.src_epg = src_epg
411 self.dst_epg = dst_epg
414 def add_vpp_config(self):
417 rules.append(r.encode())
418 self._test.vapi.gbp_contract_add_del(
424 self._test.registry.register(self, self._test.logger)
426 def remove_vpp_config(self):
427 self._test.vapi.gbp_contract_add_del(
435 return self.object_id()
438 return "gbp-contract:[%d:%s:%d]" % (self.src_epg,
442 def query_vpp_config(self):
443 cs = self._test.vapi.gbp_contract_dump()
445 if c.contract.src_epg == self.src_epg \
446 and c.contract.dst_epg == self.dst_epg:
451 class VppGbpVxlanTunnel(VppInterface):
456 def __init__(self, test, vni, bd_rd_id, mode):
457 super(VppGbpVxlanTunnel, self).__init__(test)
460 self.bd_rd_id = bd_rd_id
463 def add_vpp_config(self):
464 r = self._test.vapi.gbp_vxlan_tunnel_add(
468 self.set_sw_if_index(r.sw_if_index)
469 self._test.registry.register(self, self._test.logger)
471 def remove_vpp_config(self):
472 self._test.vapi.gbp_vxlan_tunnel_del(self.vni)
475 return self.object_id()
478 return "gbp-vxlan:%d" % (self.vni)
480 def query_vpp_config(self):
481 return find_gbp_vxlan(self._test, self.vni)
484 class VppGbpAcl(VppObject):
489 def __init__(self, test):
491 self.acl_index = 4294967295
493 def create_rule(self, is_ipv6=0, permit_deny=0, proto=-1,
494 s_prefix=0, s_ip='\x00\x00\x00\x00', sport_from=0,
495 sport_to=65535, d_prefix=0, d_ip='\x00\x00\x00\x00',
496 dport_from=0, dport_to=65535):
497 if proto == -1 or proto == 0:
500 elif proto == 1 or proto == 58:
503 rule = ({'is_permit': permit_deny, 'is_ipv6': is_ipv6, 'proto': proto,
504 'srcport_or_icmptype_first': sport_from,
505 'srcport_or_icmptype_last': sport_to,
506 'src_ip_prefix_len': s_prefix,
508 'dstport_or_icmpcode_first': dport_from,
509 'dstport_or_icmpcode_last': dport_to,
510 'dst_ip_prefix_len': d_prefix,
511 'dst_ip_addr': d_ip})
514 def add_vpp_config(self, rules):
516 reply = self._test.vapi.acl_add_replace(self.acl_index,
519 self.acl_index = reply.acl_index
520 return self.acl_index
522 def remove_vpp_config(self):
523 self._test.vapi.acl_del(self.acl_index)
526 return self.object_id()
529 return "gbp-acl:[%d]" % (self.acl_index)
531 def query_vpp_config(self):
532 cs = self._test.vapi.acl_dump()
534 if c.acl_index == self.acl_index:
539 class TestGBP(VppTestCase):
540 """ GBP Test Case """
543 super(TestGBP, self).setUp()
545 self.create_pg_interfaces(range(9))
546 self.create_loopback_interfaces(8)
548 self.router_mac = VppMacAddress("00:11:22:33:44:55")
550 for i in self.pg_interfaces:
552 for i in self.lo_interfaces:
556 for i in self.pg_interfaces:
559 super(TestGBP, self).tearDown()
561 def send_and_expect_bridged(self, src, tx, dst):
562 rx = self.send_and_expect(src, tx, dst)
565 self.assertEqual(r[Ether].src, tx[0][Ether].src)
566 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
567 self.assertEqual(r[IP].src, tx[0][IP].src)
568 self.assertEqual(r[IP].dst, tx[0][IP].dst)
571 def send_and_expect_bridged6(self, src, tx, dst):
572 rx = self.send_and_expect(src, tx, dst)
575 self.assertEqual(r[Ether].src, tx[0][Ether].src)
576 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
577 self.assertEqual(r[IPv6].src, tx[0][IPv6].src)
578 self.assertEqual(r[IPv6].dst, tx[0][IPv6].dst)
581 def send_and_expect_routed(self, src, tx, dst, src_mac):
582 rx = self.send_and_expect(src, tx, dst)
585 self.assertEqual(r[Ether].src, src_mac)
586 self.assertEqual(r[Ether].dst, dst.remote_mac)
587 self.assertEqual(r[IP].src, tx[0][IP].src)
588 self.assertEqual(r[IP].dst, tx[0][IP].dst)
591 def send_and_expect_natted(self, src, tx, dst, src_ip):
592 rx = self.send_and_expect(src, tx, dst)
595 self.assertEqual(r[Ether].src, tx[0][Ether].src)
596 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
597 self.assertEqual(r[IP].src, src_ip)
598 self.assertEqual(r[IP].dst, tx[0][IP].dst)
601 def send_and_expect_natted6(self, src, tx, dst, src_ip):
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[IPv6].src, src_ip)
608 self.assertEqual(r[IPv6].dst, tx[0][IPv6].dst)
611 def send_and_expect_unnatted(self, src, tx, dst, dst_ip):
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[IP].dst, dst_ip)
618 self.assertEqual(r[IP].src, tx[0][IP].src)
621 def send_and_expect_unnatted6(self, src, tx, dst, dst_ip):
622 rx = self.send_and_expect(src, tx, dst)
625 self.assertEqual(r[Ether].src, tx[0][Ether].src)
626 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
627 self.assertEqual(r[IPv6].dst, dst_ip)
628 self.assertEqual(r[IPv6].src, tx[0][IPv6].src)
631 def send_and_expect_double_natted(self, src, tx, dst, src_ip, dst_ip):
632 rx = self.send_and_expect(src, tx, dst)
635 self.assertEqual(r[Ether].src, self.router_mac.address)
636 self.assertEqual(r[Ether].dst, dst.remote_mac)
637 self.assertEqual(r[IP].dst, dst_ip)
638 self.assertEqual(r[IP].src, src_ip)
641 def send_and_expect_double_natted6(self, src, tx, dst, src_ip, dst_ip):
642 rx = self.send_and_expect(src, tx, dst)
645 self.assertEqual(r[Ether].src, self.router_mac.address)
646 self.assertEqual(r[Ether].dst, dst.remote_mac)
647 self.assertEqual(r[IPv6].dst, dst_ip)
648 self.assertEqual(r[IPv6].src, src_ip)
652 """ Group Based Policy """
657 bd1 = VppBridgeDomain(self, 1)
658 bd2 = VppBridgeDomain(self, 2)
659 bd20 = VppBridgeDomain(self, 20)
663 bd20.add_vpp_config()
665 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0)
666 gbd2 = VppGbpBridgeDomain(self, bd2, self.loop1)
667 gbd20 = VppGbpBridgeDomain(self, bd20, self.loop2)
669 gbd1.add_vpp_config()
670 gbd2.add_vpp_config()
671 gbd20.add_vpp_config()
676 gt4 = VppIpTable(self, 0)
678 gt6 = VppIpTable(self, 0, is_ip6=True)
680 nt4 = VppIpTable(self, 20)
682 nt6 = VppIpTable(self, 20, is_ip6=True)
685 rd0 = VppGbpRouteDomain(self, 0, gt4, gt6, None, None)
686 rd20 = VppGbpRouteDomain(self, 20, nt4, nt6, None, None)
689 rd20.add_vpp_config()
692 # 3 EPGs, 2 of which share a BD.
693 # 2 NAT EPGs, one for floating-IP subnets, the other for internet
695 epgs = [VppGbpEndpointGroup(self, 220, rd0, gbd1, self.pg4,
699 VppGbpEndpointGroup(self, 221, rd0, gbd1, self.pg5,
703 VppGbpEndpointGroup(self, 222, rd0, gbd2, self.pg6,
707 VppGbpEndpointGroup(self, 333, rd20, gbd20, self.pg7,
711 VppGbpEndpointGroup(self, 444, rd20, gbd20, self.pg8,
715 recircs = [VppGbpRecirc(self, epgs[0],
717 VppGbpRecirc(self, epgs[1],
719 VppGbpRecirc(self, epgs[2],
721 VppGbpRecirc(self, epgs[3],
722 self.loop6, is_ext=True),
723 VppGbpRecirc(self, epgs[4],
724 self.loop7, is_ext=True)]
727 recirc_nat = recircs[3]
730 # 4 end-points, 2 in the same subnet, 3 in the same BD
732 eps = [VppGbpEndpoint(self, self.pg0,
734 "10.0.0.1", "11.0.0.1",
735 "2001:10::1", "3001::1"),
736 VppGbpEndpoint(self, self.pg1,
738 "10.0.0.2", "11.0.0.2",
739 "2001:10::2", "3001::2"),
740 VppGbpEndpoint(self, self.pg2,
742 "10.0.1.1", "11.0.0.3",
743 "2001:10:1::1", "3001::3"),
744 VppGbpEndpoint(self, self.pg3,
746 "10.0.2.1", "11.0.0.4",
747 "2001:10:2::1", "3001::4")]
750 # Config related to each of the EPGs
753 # IP config on the BVI interfaces
754 if epg != epgs[1] and epg != epgs[4]:
755 VppIpInterfaceBind(self, epg.bvi, epg.rd.t4).add_vpp_config()
756 VppIpInterfaceBind(self, epg.bvi, epg.rd.t6).add_vpp_config()
757 self.vapi.sw_interface_set_mac_address(
759 self.router_mac.bytes)
761 # The BVIs are NAT inside interfaces
762 self.vapi.nat44_interface_add_del_feature(epg.bvi.sw_if_index,
765 self.vapi.nat66_add_del_interface(epg.bvi.sw_if_index,
769 if_ip4 = VppIpInterfaceAddress(self, epg.bvi, epg.bvi_ip4, 32)
770 if_ip6 = VppIpInterfaceAddress(self, epg.bvi, epg.bvi_ip6, 128)
771 if_ip4.add_vpp_config()
772 if_ip6.add_vpp_config()
774 # EPG uplink interfaces in the RD
775 VppIpInterfaceBind(self, epg.uplink, epg.rd.t4).add_vpp_config()
776 VppIpInterfaceBind(self, epg.uplink, epg.rd.t6).add_vpp_config()
778 # add the BD ARP termination entry for BVI IP
779 epg.bd_arp_ip4 = VppBridgeDomainArpEntry(self, epg.bd.bd,
780 self.router_mac.address,
782 epg.bd_arp_ip6 = VppBridgeDomainArpEntry(self, epg.bd.bd,
783 self.router_mac.address,
785 epg.bd_arp_ip4.add_vpp_config()
786 epg.bd_arp_ip6.add_vpp_config()
791 for recirc in recircs:
792 # EPG's ingress recirculation interface maps to its RD
793 VppIpInterfaceBind(self, recirc.recirc,
794 recirc.epg.rd.t4).add_vpp_config()
795 VppIpInterfaceBind(self, recirc.recirc,
796 recirc.epg.rd.t6).add_vpp_config()
798 self.vapi.sw_interface_set_l2_emulation(
799 recirc.recirc.sw_if_index)
800 self.vapi.nat44_interface_add_del_feature(
801 recirc.recirc.sw_if_index,
804 self.vapi.nat66_add_del_interface(
805 recirc.recirc.sw_if_index,
809 recirc.add_vpp_config()
811 for recirc in recircs:
812 self.assertTrue(find_bridge_domain_port(self,
813 recirc.epg.bd.bd.bd_id,
814 recirc.recirc.sw_if_index))
817 self.pg_enable_capture(self.pg_interfaces)
820 # routes to the endpoints. We need these since there are no
821 # adj-fibs due to the fact the the BVI address has /32 and
822 # the subnet is not attached.
824 for (ip, fip) in zip(ep.ips, ep.fips):
825 # Add static mappings for each EP from the 10/8 to 11/8 network
827 self.vapi.nat44_add_del_static_mapping(ip.bytes,
832 self.vapi.nat66_add_del_static_mapping(ip.bytes,
839 self.logger.info(self.vapi.cli("sh gbp endpoint"))
841 # ... results in a Gratuitous ARP/ND on the EPG's uplink
842 rx = ep.epg.uplink.get_capture(len(ep.ips), timeout=0.2)
844 for ii, ip in enumerate(ep.ips):
848 self.assertTrue(p.haslayer(ICMPv6ND_NA))
849 self.assertEqual(p[ICMPv6ND_NA].tgt, ip.address)
851 self.assertTrue(p.haslayer(ARP))
852 self.assertEqual(p[ARP].psrc, ip.address)
853 self.assertEqual(p[ARP].pdst, ip.address)
855 # add the BD ARP termination entry for floating IP
857 ba = VppBridgeDomainArpEntry(self, epg_nat.bd.bd, ep.mac, fip)
860 # floating IPs route via EPG recirc
861 r = VppIpRoute(self, fip.address, fip.length,
862 [VppRoutePath(fip.address,
863 ep.recirc.recirc.sw_if_index,
865 proto=fip.dpo_proto)],
870 # L2 FIB entries in the NAT EPG BD to bridge the packets from
871 # the outside direct to the internal EPG
872 lf = VppL2FibEntry(self, epg_nat.bd.bd, ep.mac,
873 ep.recirc.recirc, bvi_mac=0)
877 # ARP packets for unknown IP are sent to the EPG uplink
879 pkt_arp = (Ether(dst="ff:ff:ff:ff:ff:ff",
880 src=self.pg0.remote_mac) /
882 hwdst="ff:ff:ff:ff:ff:ff",
883 hwsrc=self.pg0.remote_mac,
887 self.vapi.cli("clear trace")
888 self.pg0.add_stream(pkt_arp)
890 self.pg_enable_capture(self.pg_interfaces)
893 rxd = epgs[0].uplink.get_capture(1)
896 # ARP/ND packets get a response
898 pkt_arp = (Ether(dst="ff:ff:ff:ff:ff:ff",
899 src=self.pg0.remote_mac) /
901 hwdst="ff:ff:ff:ff:ff:ff",
902 hwsrc=self.pg0.remote_mac,
903 pdst=epgs[0].bvi_ip4.address,
904 psrc=eps[0].ip4.address))
906 self.send_and_expect(self.pg0, [pkt_arp], self.pg0)
908 nsma = in6_getnsma(inet_pton(AF_INET6, eps[0].ip6.address))
909 d = inet_ntop(AF_INET6, nsma)
910 pkt_nd = (Ether(dst=in6_getnsmac(nsma),
911 src=self.pg0.remote_mac) /
912 IPv6(dst=d, src=eps[0].ip6.address) /
913 ICMPv6ND_NS(tgt=epgs[0].bvi_ip6.address) /
914 ICMPv6NDOptSrcLLAddr(lladdr=self.pg0.remote_mac))
915 self.send_and_expect(self.pg0, [pkt_nd], self.pg0)
918 # broadcast packets are flooded
920 pkt_bcast = (Ether(dst="ff:ff:ff:ff:ff:ff",
921 src=self.pg0.remote_mac) /
922 IP(src=eps[0].ip4.address, dst="232.1.1.1") /
923 UDP(sport=1234, dport=1234) /
926 self.vapi.cli("clear trace")
927 self.pg0.add_stream(pkt_bcast)
929 self.pg_enable_capture(self.pg_interfaces)
932 rxd = eps[1].itf.get_capture(1)
933 self.assertEqual(rxd[0][Ether].dst, pkt_bcast[Ether].dst)
934 rxd = epgs[0].uplink.get_capture(1)
935 self.assertEqual(rxd[0][Ether].dst, pkt_bcast[Ether].dst)
938 # packets to non-local L3 destinations dropped
940 pkt_intra_epg_220_ip4 = (Ether(src=self.pg0.remote_mac,
941 dst=self.router_mac.address) /
942 IP(src=eps[0].ip4.address,
944 UDP(sport=1234, dport=1234) /
946 pkt_inter_epg_222_ip4 = (Ether(src=self.pg0.remote_mac,
947 dst=self.router_mac.address) /
948 IP(src=eps[0].ip4.address,
950 UDP(sport=1234, dport=1234) /
953 self.send_and_assert_no_replies(self.pg0, pkt_intra_epg_220_ip4 * 65)
955 pkt_inter_epg_222_ip6 = (Ether(src=self.pg0.remote_mac,
956 dst=self.router_mac.address) /
957 IPv6(src=eps[0].ip6.address,
959 UDP(sport=1234, dport=1234) /
961 self.send_and_assert_no_replies(self.pg0, pkt_inter_epg_222_ip6 * 65)
964 # Add the subnet routes
967 self, rd0, "10.0.0.0", 24,
968 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
970 self, rd0, "10.0.1.0", 24,
971 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
973 self, rd0, "10.0.2.0", 24,
974 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
976 self, rd0, "2001:10::1", 64,
977 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
979 self, rd0, "2001:10:1::1", 64,
980 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
982 self, rd0, "2001:10:2::1", 64,
983 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
991 self.send_and_expect_bridged(eps[0].itf,
992 pkt_intra_epg_220_ip4 * 65,
994 self.send_and_expect_bridged(eps[0].itf,
995 pkt_inter_epg_222_ip4 * 65,
997 self.send_and_expect_bridged6(eps[0].itf,
998 pkt_inter_epg_222_ip6 * 65,
1001 self.logger.info(self.vapi.cli("sh ip fib 11.0.0.2"))
1002 self.logger.info(self.vapi.cli("sh gbp endpoint-group"))
1003 self.logger.info(self.vapi.cli("sh gbp endpoint"))
1004 self.logger.info(self.vapi.cli("sh gbp recirc"))
1005 self.logger.info(self.vapi.cli("sh int"))
1006 self.logger.info(self.vapi.cli("sh int addr"))
1007 self.logger.info(self.vapi.cli("sh int feat loop6"))
1008 self.logger.info(self.vapi.cli("sh vlib graph ip4-gbp-src-classify"))
1009 self.logger.info(self.vapi.cli("sh int feat loop3"))
1010 self.logger.info(self.vapi.cli("sh int feat pg0"))
1013 # Packet destined to unknown unicast is sent on the epg uplink ...
1015 pkt_intra_epg_220_to_uplink = (Ether(src=self.pg0.remote_mac,
1016 dst="00:00:00:33:44:55") /
1017 IP(src=eps[0].ip4.address,
1019 UDP(sport=1234, dport=1234) /
1022 self.send_and_expect_bridged(eps[0].itf,
1023 pkt_intra_epg_220_to_uplink * 65,
1025 # ... and nowhere else
1026 self.pg1.get_capture(0, timeout=0.1)
1027 self.pg1.assert_nothing_captured(remark="Flood onto other VMS")
1029 pkt_intra_epg_221_to_uplink = (Ether(src=self.pg2.remote_mac,
1030 dst="00:00:00:33:44:66") /
1031 IP(src=eps[0].ip4.address,
1033 UDP(sport=1234, dport=1234) /
1036 self.send_and_expect_bridged(eps[2].itf,
1037 pkt_intra_epg_221_to_uplink * 65,
1041 # Packets from the uplink are forwarded in the absence of a contract
1043 pkt_intra_epg_220_from_uplink = (Ether(src="00:00:00:33:44:55",
1044 dst=self.pg0.remote_mac) /
1045 IP(src=eps[0].ip4.address,
1047 UDP(sport=1234, dport=1234) /
1050 self.send_and_expect_bridged(self.pg4,
1051 pkt_intra_epg_220_from_uplink * 65,
1055 # in the absence of policy, endpoints in the same EPG
1058 pkt_intra_epg = (Ether(src=self.pg0.remote_mac,
1059 dst=self.pg1.remote_mac) /
1060 IP(src=eps[0].ip4.address,
1061 dst=eps[1].ip4.address) /
1062 UDP(sport=1234, dport=1234) /
1065 self.send_and_expect_bridged(self.pg0, pkt_intra_epg * 65, self.pg1)
1068 # in the abscense of policy, endpoints in the different EPG
1069 # cannot communicate
1071 pkt_inter_epg_220_to_221 = (Ether(src=self.pg0.remote_mac,
1072 dst=self.pg2.remote_mac) /
1073 IP(src=eps[0].ip4.address,
1074 dst=eps[2].ip4.address) /
1075 UDP(sport=1234, dport=1234) /
1077 pkt_inter_epg_221_to_220 = (Ether(src=self.pg2.remote_mac,
1078 dst=self.pg0.remote_mac) /
1079 IP(src=eps[2].ip4.address,
1080 dst=eps[0].ip4.address) /
1081 UDP(sport=1234, dport=1234) /
1083 pkt_inter_epg_220_to_222 = (Ether(src=self.pg0.remote_mac,
1084 dst=self.router_mac.address) /
1085 IP(src=eps[0].ip4.address,
1086 dst=eps[3].ip4.address) /
1087 UDP(sport=1234, dport=1234) /
1090 self.send_and_assert_no_replies(eps[0].itf,
1091 pkt_inter_epg_220_to_221 * 65)
1092 self.send_and_assert_no_replies(eps[0].itf,
1093 pkt_inter_epg_220_to_222 * 65)
1096 # A uni-directional contract from EPG 220 -> 221
1098 acl = VppGbpAcl(self)
1099 rule = acl.create_rule(permit_deny=1, proto=17)
1100 rule2 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
1101 acl_index = acl.add_vpp_config([rule, rule2])
1102 c1 = VppGbpContract(
1103 self, 220, 221, acl_index,
1104 [VppGbpContractRule(
1105 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1108 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1112 self.send_and_expect_bridged(eps[0].itf,
1113 pkt_inter_epg_220_to_221 * 65,
1115 self.send_and_assert_no_replies(eps[0].itf,
1116 pkt_inter_epg_220_to_222 * 65)
1119 # contract for the return direction
1121 c2 = VppGbpContract(
1122 self, 221, 220, acl_index,
1123 [VppGbpContractRule(
1124 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1127 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1132 self.send_and_expect_bridged(eps[0].itf,
1133 pkt_inter_epg_220_to_221 * 65,
1135 self.send_and_expect_bridged(eps[2].itf,
1136 pkt_inter_epg_221_to_220 * 65,
1140 # check that inter group is still disabled for the groups
1141 # not in the contract.
1143 self.send_and_assert_no_replies(eps[0].itf,
1144 pkt_inter_epg_220_to_222 * 65)
1147 # A uni-directional contract from EPG 220 -> 222 'L3 routed'
1149 c3 = VppGbpContract(
1150 self, 220, 222, acl_index,
1151 [VppGbpContractRule(
1152 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1155 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1160 self.logger.info(self.vapi.cli("sh gbp contract"))
1162 self.send_and_expect_routed(eps[0].itf,
1163 pkt_inter_epg_220_to_222 * 65,
1165 self.router_mac.address)
1168 # remove both contracts, traffic stops in both directions
1170 c2.remove_vpp_config()
1171 c1.remove_vpp_config()
1172 c3.remove_vpp_config()
1173 acl.remove_vpp_config()
1175 self.send_and_assert_no_replies(eps[2].itf,
1176 pkt_inter_epg_221_to_220 * 65)
1177 self.send_and_assert_no_replies(eps[0].itf,
1178 pkt_inter_epg_220_to_221 * 65)
1179 self.send_and_expect_bridged(eps[0].itf,
1184 # EPs to the outside world
1187 # in the EP's RD an external subnet via the NAT EPG's recirc
1189 self, rd0, "0.0.0.0", 0,
1190 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1191 sw_if_index=recirc_nat.recirc.sw_if_index,
1194 self, rd0, "11.0.0.0", 8,
1195 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1196 sw_if_index=recirc_nat.recirc.sw_if_index,
1198 se16 = VppGbpSubnet(
1200 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1201 sw_if_index=recirc_nat.recirc.sw_if_index,
1203 # in the NAT RD an external subnet via the NAT EPG's uplink
1205 self, rd20, "0.0.0.0", 0,
1206 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1207 sw_if_index=epg_nat.uplink.sw_if_index,
1209 se36 = VppGbpSubnet(
1210 self, rd20, "::", 0,
1211 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1212 sw_if_index=epg_nat.uplink.sw_if_index,
1215 self, rd20, "11.0.0.0", 8,
1216 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1217 sw_if_index=epg_nat.uplink.sw_if_index,
1219 se1.add_vpp_config()
1220 se2.add_vpp_config()
1221 se16.add_vpp_config()
1222 se3.add_vpp_config()
1223 se36.add_vpp_config()
1224 se4.add_vpp_config()
1226 self.logger.info(self.vapi.cli("sh ip fib 0.0.0.0/0"))
1227 self.logger.info(self.vapi.cli("sh ip fib 11.0.0.1"))
1228 self.logger.info(self.vapi.cli("sh ip6 fib ::/0"))
1229 self.logger.info(self.vapi.cli("sh ip6 fib %s" %
1233 # From an EP to an outside addess: IN2OUT
1235 pkt_inter_epg_220_to_global = (Ether(src=self.pg0.remote_mac,
1236 dst=self.router_mac.address) /
1237 IP(src=eps[0].ip4.address,
1239 UDP(sport=1234, dport=1234) /
1243 self.send_and_assert_no_replies(eps[0].itf,
1244 pkt_inter_epg_220_to_global * 65)
1246 acl2 = VppGbpAcl(self)
1247 rule = acl2.create_rule(permit_deny=1, proto=17, sport_from=1234,
1248 sport_to=1234, dport_from=1234, dport_to=1234)
1249 rule2 = acl2.create_rule(is_ipv6=1, permit_deny=1, proto=17,
1250 sport_from=1234, sport_to=1234,
1251 dport_from=1234, dport_to=1234)
1253 acl_index2 = acl2.add_vpp_config([rule, rule2])
1254 c4 = VppGbpContract(
1255 self, 220, 333, acl_index2,
1256 [VppGbpContractRule(
1257 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1260 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1265 self.send_and_expect_natted(eps[0].itf,
1266 pkt_inter_epg_220_to_global * 65,
1268 eps[0].fip4.address)
1270 pkt_inter_epg_220_to_global = (Ether(src=self.pg0.remote_mac,
1271 dst=self.router_mac.address) /
1272 IPv6(src=eps[0].ip6.address,
1274 UDP(sport=1234, dport=1234) /
1277 self.send_and_expect_natted6(self.pg0,
1278 pkt_inter_epg_220_to_global * 65,
1280 eps[0].fip6.address)
1283 # From a global address to an EP: OUT2IN
1285 pkt_inter_epg_220_from_global = (Ether(src=self.router_mac.address,
1286 dst=self.pg0.remote_mac) /
1287 IP(dst=eps[0].fip4.address,
1289 UDP(sport=1234, dport=1234) /
1292 self.send_and_assert_no_replies(self.pg7,
1293 pkt_inter_epg_220_from_global * 65)
1295 c5 = VppGbpContract(
1296 self, 333, 220, acl_index2,
1297 [VppGbpContractRule(
1298 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1301 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1306 self.send_and_expect_unnatted(self.pg7,
1307 pkt_inter_epg_220_from_global * 65,
1311 pkt_inter_epg_220_from_global = (Ether(src=self.router_mac.address,
1312 dst=self.pg0.remote_mac) /
1313 IPv6(dst=eps[0].fip6.address,
1315 UDP(sport=1234, dport=1234) /
1318 self.send_and_expect_unnatted6(self.pg7,
1319 pkt_inter_epg_220_from_global * 65,
1324 # From a local VM to another local VM using resp. public addresses:
1327 pkt_intra_epg_220_global = (Ether(src=self.pg0.remote_mac,
1328 dst=self.router_mac.address) /
1329 IP(src=eps[0].ip4.address,
1330 dst=eps[1].fip4.address) /
1331 UDP(sport=1234, dport=1234) /
1334 self.send_and_expect_double_natted(eps[0].itf,
1335 pkt_intra_epg_220_global * 65,
1337 eps[0].fip4.address,
1340 pkt_intra_epg_220_global = (Ether(src=self.pg0.remote_mac,
1341 dst=self.router_mac.address) /
1342 IPv6(src=eps[0].ip6.address,
1343 dst=eps[1].fip6.address) /
1344 UDP(sport=1234, dport=1234) /
1347 self.send_and_expect_double_natted6(eps[0].itf,
1348 pkt_intra_epg_220_global * 65,
1350 eps[0].fip6.address,
1357 # del static mappings for each EP from the 10/8 to 11/8 network
1358 self.vapi.nat44_add_del_static_mapping(ep.ip4.bytes,
1363 self.vapi.nat66_add_del_static_mapping(ep.ip6.bytes,
1369 # IP config on the BVI interfaces
1370 if epg != epgs[0] and epg != epgs[3]:
1371 self.vapi.nat44_interface_add_del_feature(epg.bvi.sw_if_index,
1374 self.vapi.nat66_add_del_interface(epg.bvi.sw_if_index,
1378 for recirc in recircs:
1379 self.vapi.sw_interface_set_l2_emulation(
1380 recirc.recirc.sw_if_index, enable=0)
1381 self.vapi.nat44_interface_add_del_feature(
1382 recirc.recirc.sw_if_index,
1385 self.vapi.nat66_add_del_interface(
1386 recirc.recirc.sw_if_index,
1390 def test_gbp_learn_l2(self):
1391 """ GBP L2 Endpoint Learning """
1393 learnt = [{'mac': '00:00:11:11:11:01',
1395 'ip6': '2001:10::2'},
1396 {'mac': '00:00:11:11:11:02',
1398 'ip6': '2001:10::3'}]
1401 # lower the inactive threshold so these tests pass in a
1402 # reasonable amount of time
1404 self.vapi.gbp_endpoint_learn_set_inactive_threshold(1)
1409 gt4 = VppIpTable(self, 1)
1410 gt4.add_vpp_config()
1411 gt6 = VppIpTable(self, 1, is_ip6=True)
1412 gt6.add_vpp_config()
1414 rd1 = VppGbpRouteDomain(self, 1, gt4, gt6)
1415 rd1.add_vpp_config()
1418 # Pg2 hosts the vxlan tunnel, hosts on pg2 to act as TEPs
1419 # Pg3 hosts the IP4 UU-flood VXLAN tunnel
1420 # Pg4 hosts the IP6 UU-flood VXLAN tunnel
1422 self.pg2.config_ip4()
1423 self.pg2.resolve_arp()
1424 self.pg2.generate_remote_hosts(4)
1425 self.pg2.configure_ipv4_neighbors()
1426 self.pg3.config_ip4()
1427 self.pg3.resolve_arp()
1428 self.pg4.config_ip4()
1429 self.pg4.resolve_arp()
1432 # a GBP bridge domain with a BVI and a UU-flood interface
1434 bd1 = VppBridgeDomain(self, 1)
1435 bd1.add_vpp_config()
1436 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0, self.pg3)
1437 gbd1.add_vpp_config()
1439 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1440 self.logger.info(self.vapi.cli("sh gbp bridge"))
1442 # ... and has a /32 applied
1443 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
1444 ip_addr.add_vpp_config()
1447 # The Endpoint-group in which we are learning endpoints
1449 epg_220 = VppGbpEndpointGroup(self, 220, rd1, gbd1,
1453 epg_220.add_vpp_config()
1454 epg_330 = VppGbpEndpointGroup(self, 330, rd1, gbd1,
1458 epg_330.add_vpp_config()
1461 # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
1464 vx_tun_l2_1 = VppGbpVxlanTunnel(
1465 self, 99, bd1.bd_id,
1466 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L2)
1467 vx_tun_l2_1.add_vpp_config()
1470 # A static endpoint that the learnt endpoints are trying to
1473 ep = VppGbpEndpoint(self, self.pg0,
1475 "10.0.0.127", "11.0.0.127",
1476 "2001:10::1", "3001::1")
1479 self.assertTrue(find_route(self, ep.ip4.address, 32, table_id=1))
1481 # a packet with an sclass from an unknwon EPG
1482 p = (Ether(src=self.pg2.remote_mac,
1483 dst=self.pg2.local_mac) /
1484 IP(src=self.pg2.remote_hosts[0].ip4,
1485 dst=self.pg2.local_ip4) /
1486 UDP(sport=1234, dport=48879) /
1487 VXLAN(vni=99, gpid=88, flags=0x88) /
1488 Ether(src=learnt[0]["mac"], dst=ep.mac) /
1489 IP(src=learnt[0]["ip"], dst=ep.ip4.address) /
1490 UDP(sport=1234, dport=1234) /
1493 self.send_and_assert_no_replies(self.pg2, p)
1496 # we should not have learnt a new tunnel endpoint, since
1497 # the EPG was not learnt.
1499 self.assertEqual(INDEX_INVALID,
1500 find_vxlan_gbp_tunnel(self,
1502 self.pg2.remote_hosts[0].ip4,
1505 # epg is not learnt, becasue the EPG is unknwon
1506 self.assertEqual(len(self.vapi.gbp_endpoint_dump()), 1)
1508 for ii, l in enumerate(learnt):
1509 # a packet with an sclass from a knwon EPG
1510 # arriving on an unknown TEP
1511 p = (Ether(src=self.pg2.remote_mac,
1512 dst=self.pg2.local_mac) /
1513 IP(src=self.pg2.remote_hosts[1].ip4,
1514 dst=self.pg2.local_ip4) /
1515 UDP(sport=1234, dport=48879) /
1516 VXLAN(vni=99, gpid=220, flags=0x88) /
1517 Ether(src=l['mac'], dst=ep.mac) /
1518 IP(src=l['ip'], dst=ep.ip4.address) /
1519 UDP(sport=1234, dport=1234) /
1522 rx = self.send_and_expect(self.pg2, [p], self.pg0)
1525 tep1_sw_if_index = find_vxlan_gbp_tunnel(
1528 self.pg2.remote_hosts[1].ip4,
1530 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
1533 # the EP is learnt via the learnt TEP
1534 # both from its MAC and its IP
1536 self.assertTrue(find_gbp_endpoint(self,
1537 vx_tun_l2_1.sw_if_index,
1539 self.assertTrue(find_gbp_endpoint(self,
1540 vx_tun_l2_1.sw_if_index,
1543 self.logger.info(self.vapi.cli("show gbp endpoint"))
1544 self.logger.info(self.vapi.cli("show gbp vxlan"))
1545 self.logger.info(self.vapi.cli("show vxlan-gbp tunnel"))
1548 # If we sleep for the threshold time, the learnt endpoints should
1553 self.assertFalse(find_gbp_endpoint(self,
1557 self.logger.info(self.vapi.cli("show gbp endpoint"))
1558 self.logger.info(self.vapi.cli("show gbp vxlan"))
1559 self.logger.info(self.vapi.cli("show vxlan-gbp tunnel"))
1562 # repeat. the do not learn bit is set so the EPs are not learnt
1565 # a packet with an sclass from a knwon EPG
1566 p = (Ether(src=self.pg2.remote_mac,
1567 dst=self.pg2.local_mac) /
1568 IP(src=self.pg2.remote_hosts[1].ip4,
1569 dst=self.pg2.local_ip4) /
1570 UDP(sport=1234, dport=48879) /
1571 VXLAN(vni=99, gpid=220, flags=0x88, gpflags="D") /
1572 Ether(src=l['mac'], dst=ep.mac) /
1573 IP(src=l['ip'], dst=ep.ip4.address) /
1574 UDP(sport=1234, dport=1234) /
1577 rx = self.send_and_expect(self.pg2, p*65, self.pg0)
1580 self.assertFalse(find_gbp_endpoint(self,
1581 vx_tun_l2_1.sw_if_index,
1588 # a packet with an sclass from a knwon EPG
1589 p = (Ether(src=self.pg2.remote_mac,
1590 dst=self.pg2.local_mac) /
1591 IP(src=self.pg2.remote_hosts[1].ip4,
1592 dst=self.pg2.local_ip4) /
1593 UDP(sport=1234, dport=48879) /
1594 VXLAN(vni=99, gpid=220, flags=0x88) /
1595 Ether(src=l['mac'], dst=ep.mac) /
1596 IP(src=l['ip'], dst=ep.ip4.address) /
1597 UDP(sport=1234, dport=1234) /
1600 rx = self.send_and_expect(self.pg2, p*65, self.pg0)
1602 self.assertTrue(find_gbp_endpoint(self,
1603 vx_tun_l2_1.sw_if_index,
1607 # Static EP replies to dynamics
1609 self.logger.info(self.vapi.cli("sh l2fib bd_id 1"))
1611 p = (Ether(src=ep.mac, dst=l['mac']) /
1612 IP(dst=l['ip'], src=ep.ip4.address) /
1613 UDP(sport=1234, dport=1234) /
1616 rxs = self.send_and_expect(self.pg0, p * 17, self.pg2)
1619 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
1620 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
1621 self.assertEqual(rx[UDP].dport, 48879)
1622 # the UDP source port is a random value for hashing
1623 self.assertEqual(rx[VXLAN].gpid, 220)
1624 self.assertEqual(rx[VXLAN].vni, 99)
1625 self.assertTrue(rx[VXLAN].flags.G)
1626 self.assertTrue(rx[VXLAN].flags.Instance)
1627 self.assertTrue(rx[VXLAN].gpflags.A)
1628 self.assertFalse(rx[VXLAN].gpflags.D)
1632 self.assertFalse(find_gbp_endpoint(self,
1633 vx_tun_l2_1.sw_if_index,
1637 # repeat in the other EPG
1638 # there's no contract between 220 and 330, but the A-bit is set
1639 # so the packet is cleared for delivery
1642 # a packet with an sclass from a knwon EPG
1643 p = (Ether(src=self.pg2.remote_mac,
1644 dst=self.pg2.local_mac) /
1645 IP(src=self.pg2.remote_hosts[1].ip4,
1646 dst=self.pg2.local_ip4) /
1647 UDP(sport=1234, dport=48879) /
1648 VXLAN(vni=99, gpid=330, flags=0x88, gpflags='A') /
1649 Ether(src=l['mac'], dst=ep.mac) /
1650 IP(src=l['ip'], dst=ep.ip4.address) /
1651 UDP(sport=1234, dport=1234) /
1654 rx = self.send_and_expect(self.pg2, p*65, self.pg0)
1656 self.assertTrue(find_gbp_endpoint(self,
1657 vx_tun_l2_1.sw_if_index,
1661 # static EP cannot reach the learnt EPs since there is no contract
1662 # only test 1 EP as the others could timeout
1664 p = (Ether(src=ep.mac, dst=l['mac']) /
1665 IP(dst=learnt[0]['ip'], src=ep.ip4.address) /
1666 UDP(sport=1234, dport=1234) /
1669 self.send_and_assert_no_replies(self.pg0, [p])
1672 # refresh the entries after the check for no replies above
1675 # a packet with an sclass from a knwon EPG
1676 p = (Ether(src=self.pg2.remote_mac,
1677 dst=self.pg2.local_mac) /
1678 IP(src=self.pg2.remote_hosts[1].ip4,
1679 dst=self.pg2.local_ip4) /
1680 UDP(sport=1234, dport=48879) /
1681 VXLAN(vni=99, gpid=330, flags=0x88, gpflags='A') /
1682 Ether(src=l['mac'], dst=ep.mac) /
1683 IP(src=l['ip'], dst=ep.ip4.address) /
1684 UDP(sport=1234, dport=1234) /
1687 rx = self.send_and_expect(self.pg2, p*65, self.pg0)
1689 self.assertTrue(find_gbp_endpoint(self,
1690 vx_tun_l2_1.sw_if_index,
1694 # Add the contract so they can talk
1696 acl = VppGbpAcl(self)
1697 rule = acl.create_rule(permit_deny=1, proto=17)
1698 rule2 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
1699 acl_index = acl.add_vpp_config([rule, rule2])
1700 c1 = VppGbpContract(
1701 self, 220, 330, acl_index,
1702 [VppGbpContractRule(
1703 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1706 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1712 p = (Ether(src=ep.mac, dst=l['mac']) /
1713 IP(dst=l['ip'], src=ep.ip4.address) /
1714 UDP(sport=1234, dport=1234) /
1717 self.send_and_expect(self.pg0, [p], self.pg2)
1720 # send UU packets from the local EP
1722 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1723 self.logger.info(self.vapi.cli("sh gbp bridge"))
1724 p_uu = (Ether(src=ep.mac, dst="00:11:11:11:11:11") /
1725 IP(dst="10.0.0.133", src=ep.ip4.address) /
1726 UDP(sport=1234, dport=1234) /
1728 rxs = self.send_and_expect(ep.itf, [p_uu], gbd1.uu_flood)
1731 # Add a mcast destination VXLAN-GBP tunnel for B&M traffic
1733 tun_bm = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
1736 tun_bm.add_vpp_config()
1737 bp_bm = VppBridgeDomainPort(self, bd1, tun_bm,
1738 port_type=L2_PORT_TYPE.NORMAL)
1739 bp_bm.add_vpp_config()
1741 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1743 p_bm = (Ether(src=ep.mac, dst="ff:ff:ff:ff:ff:ff") /
1744 IP(dst="10.0.0.133", src=ep.ip4.address) /
1745 UDP(sport=1234, dport=1234) /
1747 rxs = self.send_and_expect_only(ep.itf, [p_bm], tun_bm.mcast_itf)
1750 # Check v6 Endpoints
1753 # a packet with an sclass from a knwon EPG
1754 p = (Ether(src=self.pg2.remote_mac,
1755 dst=self.pg2.local_mac) /
1756 IP(src=self.pg2.remote_hosts[1].ip4,
1757 dst=self.pg2.local_ip4) /
1758 UDP(sport=1234, dport=48879) /
1759 VXLAN(vni=99, gpid=330, flags=0x88, gpflags='A') /
1760 Ether(src=l['mac'], dst=ep.mac) /
1761 IPv6(src=l['ip6'], dst=ep.ip6.address) /
1762 UDP(sport=1234, dport=1234) /
1765 rx = self.send_and_expect(self.pg2, p*65, self.pg0)
1767 self.assertTrue(find_gbp_endpoint(self,
1768 vx_tun_l2_1.sw_if_index,
1772 # L3 Endpoint Learning
1773 # - configured on the bridge's BVI
1781 self.assertFalse(find_gbp_endpoint(self,
1782 vx_tun_l2_1.sw_if_index,
1785 self.pg2.unconfig_ip4()
1786 self.pg3.unconfig_ip4()
1787 self.pg4.unconfig_ip4()
1789 self.logger.info(self.vapi.cli("sh int"))
1790 self.logger.info(self.vapi.cli("sh gbp vxlan"))
1792 def test_gbp_learn_vlan_l2(self):
1793 """ GBP L2 Endpoint w/ VLANs"""
1795 learnt = [{'mac': '00:00:11:11:11:01',
1797 'ip6': '2001:10::2'},
1798 {'mac': '00:00:11:11:11:02',
1800 'ip6': '2001:10::3'}]
1803 # lower the inactive threshold so these tests pass in a
1804 # reasonable amount of time
1806 self.vapi.gbp_endpoint_learn_set_inactive_threshold(1)
1811 gt4 = VppIpTable(self, 1)
1812 gt4.add_vpp_config()
1813 gt6 = VppIpTable(self, 1, is_ip6=True)
1814 gt6.add_vpp_config()
1816 rd1 = VppGbpRouteDomain(self, 1, gt4, gt6)
1817 rd1.add_vpp_config()
1820 # Pg2 hosts the vxlan tunnel, hosts on pg2 to act as TEPs
1822 self.pg2.config_ip4()
1823 self.pg2.resolve_arp()
1824 self.pg2.generate_remote_hosts(4)
1825 self.pg2.configure_ipv4_neighbors()
1826 self.pg3.config_ip4()
1827 self.pg3.resolve_arp()
1830 # The EP will be on a vlan sub-interface
1832 vlan_11 = VppDot1QSubint(self, self.pg0, 11)
1834 self.vapi.sw_interface_set_l2_tag_rewrite(vlan_11.sw_if_index,
1838 bd_uu_fwd = VppVxlanGbpTunnel(self, self.pg3.local_ip4,
1839 self.pg3.remote_ip4, 116)
1840 bd_uu_fwd.add_vpp_config()
1843 # a GBP bridge domain with a BVI and a UU-flood interface
1844 # The BD is marked as do not learn, so no endpoints are ever
1845 # learnt in this BD.
1847 bd1 = VppBridgeDomain(self, 1)
1848 bd1.add_vpp_config()
1849 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0, bd_uu_fwd,
1851 gbd1.add_vpp_config()
1853 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1854 self.logger.info(self.vapi.cli("sh gbp bridge"))
1856 # ... and has a /32 applied
1857 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
1858 ip_addr.add_vpp_config()
1861 # The Endpoint-group in which we are learning endpoints
1863 epg_220 = VppGbpEndpointGroup(self, 220, rd1, gbd1,
1867 epg_220.add_vpp_config()
1870 # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
1873 vx_tun_l2_1 = VppGbpVxlanTunnel(
1874 self, 99, bd1.bd_id,
1875 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L2)
1876 vx_tun_l2_1.add_vpp_config()
1879 # A static endpoint that the learnt endpoints are trying to
1882 ep = VppGbpEndpoint(self, vlan_11,
1884 "10.0.0.127", "11.0.0.127",
1885 "2001:10::1", "3001::1")
1888 self.assertTrue(find_route(self, ep.ip4.address, 32, table_id=1))
1891 # Send to the static EP
1893 for ii, l in enumerate(learnt):
1894 # a packet with an sclass from a knwon EPG
1895 # arriving on an unknown TEP
1896 p = (Ether(src=self.pg2.remote_mac,
1897 dst=self.pg2.local_mac) /
1898 IP(src=self.pg2.remote_hosts[1].ip4,
1899 dst=self.pg2.local_ip4) /
1900 UDP(sport=1234, dport=48879) /
1901 VXLAN(vni=99, gpid=220, flags=0x88) /
1902 Ether(src=l['mac'], dst=ep.mac) /
1903 IP(src=l['ip'], dst=ep.ip4.address) /
1904 UDP(sport=1234, dport=1234) /
1907 rxs = self.send_and_expect(self.pg2, [p], self.pg0)
1910 # packet to EP has the EP's vlan tag
1913 self.assertEqual(rx[Dot1Q].vlan, 11)
1916 # the EP is not learnt since the BD setting prevents it
1919 self.assertFalse(find_gbp_endpoint(self,
1920 vx_tun_l2_1.sw_if_index,
1922 self.assertEqual(INDEX_INVALID,
1923 find_vxlan_gbp_tunnel(
1926 self.pg2.remote_hosts[1].ip4,
1929 self.assertEqual(len(self.vapi.gbp_endpoint_dump()), 1)
1933 # we didn't learn the remotes so they are sent to the UU-fwd
1936 p = (Ether(src=ep.mac, dst=l['mac']) /
1938 IP(dst=l['ip'], src=ep.ip4.address) /
1939 UDP(sport=1234, dport=1234) /
1942 rxs = self.send_and_expect(self.pg0, p * 17, self.pg3)
1945 self.assertEqual(rx[IP].src, self.pg3.local_ip4)
1946 self.assertEqual(rx[IP].dst, self.pg3.remote_ip4)
1947 self.assertEqual(rx[UDP].dport, 48879)
1948 # the UDP source port is a random value for hashing
1949 self.assertEqual(rx[VXLAN].gpid, 220)
1950 self.assertEqual(rx[VXLAN].vni, 116)
1951 self.assertTrue(rx[VXLAN].flags.G)
1952 self.assertTrue(rx[VXLAN].flags.Instance)
1953 self.assertFalse(rx[VXLAN].gpflags.A)
1954 self.assertFalse(rx[VXLAN].gpflags.D)
1956 self.pg2.unconfig_ip4()
1957 self.pg3.unconfig_ip4()
1959 def test_gbp_learn_l3(self):
1960 """ GBP L3 Endpoint Learning """
1962 self.vapi.cli("set logging class gbp debug")
1964 routed_dst_mac = "00:0c:0c:0c:0c:0c"
1965 routed_src_mac = "00:22:bd:f8:19:ff"
1967 learnt = [{'mac': '00:00:11:11:11:02',
1969 'ip6': '2001:10::2'},
1970 {'mac': '00:00:11:11:11:03',
1972 'ip6': '2001:10::3'}]
1975 # lower the inactive threshold so these tests pass in a
1976 # reasonable amount of time
1978 self.vapi.gbp_endpoint_learn_set_inactive_threshold(1)
1983 t4 = VppIpTable(self, 1)
1985 t6 = VppIpTable(self, 1, True)
1988 tun_ip4_uu = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
1989 self.pg4.remote_ip4, 114)
1990 tun_ip6_uu = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
1991 self.pg4.remote_ip4, 116)
1992 tun_ip4_uu.add_vpp_config()
1993 tun_ip6_uu.add_vpp_config()
1995 rd1 = VppGbpRouteDomain(self, 2, t4, t6, tun_ip4_uu, tun_ip6_uu)
1996 rd1.add_vpp_config()
1998 self.loop0.set_mac(self.router_mac.address)
2001 # Bind the BVI to the RD
2003 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
2004 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
2007 # Pg2 hosts the vxlan tunnel
2008 # hosts on pg2 to act as TEPs
2012 self.pg2.config_ip4()
2013 self.pg2.resolve_arp()
2014 self.pg2.generate_remote_hosts(4)
2015 self.pg2.configure_ipv4_neighbors()
2016 self.pg3.config_ip4()
2017 self.pg3.resolve_arp()
2018 self.pg4.config_ip4()
2019 self.pg4.resolve_arp()
2022 # a GBP bridge domain with a BVI and a UU-flood interface
2024 bd1 = VppBridgeDomain(self, 1)
2025 bd1.add_vpp_config()
2026 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0, self.pg3)
2027 gbd1.add_vpp_config()
2029 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2030 self.logger.info(self.vapi.cli("sh gbp bridge"))
2031 self.logger.info(self.vapi.cli("sh gbp route"))
2033 # ... and has a /32 and /128 applied
2034 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2035 ip4_addr.add_vpp_config()
2036 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 128)
2037 ip6_addr.add_vpp_config()
2040 # The Endpoint-group in which we are learning endpoints
2042 epg_220 = VppGbpEndpointGroup(self, 220, rd1, gbd1,
2046 epg_220.add_vpp_config()
2049 # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
2052 vx_tun_l3 = VppGbpVxlanTunnel(
2053 self, 101, rd1.rd_id,
2054 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3)
2055 vx_tun_l3.add_vpp_config()
2058 # A static endpoint that the learnt endpoints are trying to
2061 ep = VppGbpEndpoint(self, self.pg0,
2063 "10.0.0.127", "11.0.0.127",
2064 "2001:10::1", "3001::1")
2068 # learn some remote IPv4 EPs
2070 for ii, l in enumerate(learnt):
2071 # a packet with an sclass from a knwon EPG
2072 # arriving on an unknown TEP
2073 p = (Ether(src=self.pg2.remote_mac,
2074 dst=self.pg2.local_mac) /
2075 IP(src=self.pg2.remote_hosts[1].ip4,
2076 dst=self.pg2.local_ip4) /
2077 UDP(sport=1234, dport=48879) /
2078 VXLAN(vni=101, gpid=220, flags=0x88) /
2079 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2080 IP(src=l['ip'], dst=ep.ip4.address) /
2081 UDP(sport=1234, dport=1234) /
2084 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2087 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2090 self.pg2.remote_hosts[1].ip4,
2092 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2094 # endpoint learnt via the parent GBP-vxlan interface
2095 self.assertTrue(find_gbp_endpoint(self,
2096 vx_tun_l3._sw_if_index,
2100 # Static IPv4 EP replies to learnt
2103 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2104 IP(dst=l['ip'], src=ep.ip4.address) /
2105 UDP(sport=1234, dport=1234) /
2108 rxs = self.send_and_expect(self.pg0, p*1, self.pg2)
2111 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2112 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2113 self.assertEqual(rx[UDP].dport, 48879)
2114 # the UDP source port is a random value for hashing
2115 self.assertEqual(rx[VXLAN].gpid, 220)
2116 self.assertEqual(rx[VXLAN].vni, 101)
2117 self.assertTrue(rx[VXLAN].flags.G)
2118 self.assertTrue(rx[VXLAN].flags.Instance)
2119 self.assertTrue(rx[VXLAN].gpflags.A)
2120 self.assertFalse(rx[VXLAN].gpflags.D)
2122 inner = rx[VXLAN].payload
2124 self.assertEqual(inner[Ether].src, routed_src_mac)
2125 self.assertEqual(inner[Ether].dst, routed_dst_mac)
2126 self.assertEqual(inner[IP].src, ep.ip4.address)
2127 self.assertEqual(inner[IP].dst, l['ip'])
2131 self.assertFalse(find_gbp_endpoint(self,
2136 # learn some remote IPv6 EPs
2138 for ii, l in enumerate(learnt):
2139 # a packet with an sclass from a knwon EPG
2140 # arriving on an unknown TEP
2141 p = (Ether(src=self.pg2.remote_mac,
2142 dst=self.pg2.local_mac) /
2143 IP(src=self.pg2.remote_hosts[1].ip4,
2144 dst=self.pg2.local_ip4) /
2145 UDP(sport=1234, dport=48879) /
2146 VXLAN(vni=101, gpid=220, flags=0x88) /
2147 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2148 IPv6(src=l['ip6'], dst=ep.ip6.address) /
2149 UDP(sport=1234, dport=1234) /
2152 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2155 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2158 self.pg2.remote_hosts[1].ip4,
2160 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2162 self.logger.info(self.vapi.cli("show gbp bridge"))
2163 self.logger.info(self.vapi.cli("show vxlan-gbp tunnel"))
2164 self.logger.info(self.vapi.cli("show gbp vxlan"))
2165 self.logger.info(self.vapi.cli("show int addr"))
2167 # endpoint learnt via the TEP
2168 self.assertTrue(find_gbp_endpoint(self, ip=l['ip6']))
2170 self.logger.info(self.vapi.cli("show gbp endpoint"))
2171 self.logger.info(self.vapi.cli("show ip fib index 1 %s" % l['ip']))
2174 # Static EP replies to learnt
2177 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2178 IPv6(dst=l['ip6'], src=ep.ip6.address) /
2179 UDP(sport=1234, dport=1234) /
2182 rxs = self.send_and_expect(self.pg0, p*65, self.pg2)
2185 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2186 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2187 self.assertEqual(rx[UDP].dport, 48879)
2188 # the UDP source port is a random value for hashing
2189 self.assertEqual(rx[VXLAN].gpid, 220)
2190 self.assertEqual(rx[VXLAN].vni, 101)
2191 self.assertTrue(rx[VXLAN].flags.G)
2192 self.assertTrue(rx[VXLAN].flags.Instance)
2193 self.assertTrue(rx[VXLAN].gpflags.A)
2194 self.assertFalse(rx[VXLAN].gpflags.D)
2196 inner = rx[VXLAN].payload
2198 self.assertEqual(inner[Ether].src, routed_src_mac)
2199 self.assertEqual(inner[Ether].dst, routed_dst_mac)
2200 self.assertEqual(inner[IPv6].src, ep.ip6.address)
2201 self.assertEqual(inner[IPv6].dst, l['ip6'])
2203 self.logger.info(self.vapi.cli("sh gbp endpoint"))
2206 self.assertFalse(find_gbp_endpoint(self,
2211 # Static sends to unknown EP with no route
2213 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2214 IP(dst="10.0.0.99", src=ep.ip4.address) /
2215 UDP(sport=1234, dport=1234) /
2218 self.send_and_assert_no_replies(self.pg0, [p])
2221 # Add a route to static EP's v4 and v6 subnet
2222 # packets should be send on the v4/v6 uu=fwd interface resp.
2224 se_10_24 = VppGbpSubnet(
2225 self, rd1, "10.0.0.0", 24,
2226 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT)
2227 se_10_24.add_vpp_config()
2229 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2230 IP(dst="10.0.0.99", src=ep.ip4.address) /
2231 UDP(sport=1234, dport=1234) /
2234 rxs = self.send_and_expect(self.pg0, [p], self.pg4)
2236 self.assertEqual(rx[IP].src, self.pg4.local_ip4)
2237 self.assertEqual(rx[IP].dst, self.pg4.remote_ip4)
2238 self.assertEqual(rx[UDP].dport, 48879)
2239 # the UDP source port is a random value for hashing
2240 self.assertEqual(rx[VXLAN].gpid, 220)
2241 self.assertEqual(rx[VXLAN].vni, 114)
2242 self.assertTrue(rx[VXLAN].flags.G)
2243 self.assertTrue(rx[VXLAN].flags.Instance)
2244 # policy is not applied to packets sent to the uu-fwd interfaces
2245 self.assertFalse(rx[VXLAN].gpflags.A)
2246 self.assertFalse(rx[VXLAN].gpflags.D)
2249 # learn some remote IPv4 EPs
2251 for ii, l in enumerate(learnt):
2252 # a packet with an sclass from a knwon EPG
2253 # arriving on an unknown TEP
2254 p = (Ether(src=self.pg2.remote_mac,
2255 dst=self.pg2.local_mac) /
2256 IP(src=self.pg2.remote_hosts[1].ip4,
2257 dst=self.pg2.local_ip4) /
2258 UDP(sport=1234, dport=48879) /
2259 VXLAN(vni=101, gpid=220, flags=0x88) /
2260 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2261 IP(src=l['ip'], dst=ep.ip4.address) /
2262 UDP(sport=1234, dport=1234) /
2265 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2268 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2271 self.pg2.remote_hosts[1].ip4,
2273 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2275 # endpoint learnt via the parent GBP-vxlan interface
2276 self.assertTrue(find_gbp_endpoint(self,
2277 vx_tun_l3._sw_if_index,
2281 # Add a remote endpoint from the API
2283 rep_88 = VppGbpEndpoint(self, vx_tun_l3,
2285 "10.0.0.88", "11.0.0.88",
2286 "2001:10::88", "3001::88",
2287 VppEnum.vl_api_gbp_endpoint_flags_t.REMOTE,
2289 self.pg2.remote_hosts[1].ip4,
2291 rep_88.add_vpp_config()
2294 # Add a remote endpoint from the API that matches an existing one
2296 rep_2 = VppGbpEndpoint(self, vx_tun_l3,
2298 learnt[0]['ip'], "11.0.0.101",
2299 learnt[0]['ip6'], "3001::101",
2300 VppEnum.vl_api_gbp_endpoint_flags_t.REMOTE,
2302 self.pg2.remote_hosts[1].ip4,
2304 rep_2.add_vpp_config()
2307 # Add a route to the leanred EP's v4 subnet
2308 # packets should be send on the v4/v6 uu=fwd interface resp.
2310 se_10_1_24 = VppGbpSubnet(
2311 self, rd1, "10.0.1.0", 24,
2312 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT)
2313 se_10_1_24.add_vpp_config()
2315 self.logger.info(self.vapi.cli("show gbp endpoint"))
2317 ips = ["10.0.0.88", learnt[0]['ip']]
2319 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2320 IP(dst=ip, src=ep.ip4.address) /
2321 UDP(sport=1234, dport=1234) /
2324 rxs = self.send_and_expect(self.pg0, p*65, self.pg2)
2327 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2328 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2329 self.assertEqual(rx[UDP].dport, 48879)
2330 # the UDP source port is a random value for hashing
2331 self.assertEqual(rx[VXLAN].gpid, 220)
2332 self.assertEqual(rx[VXLAN].vni, 101)
2333 self.assertTrue(rx[VXLAN].flags.G)
2334 self.assertTrue(rx[VXLAN].flags.Instance)
2335 self.assertTrue(rx[VXLAN].gpflags.A)
2336 self.assertFalse(rx[VXLAN].gpflags.D)
2338 inner = rx[VXLAN].payload
2340 self.assertEqual(inner[Ether].src, routed_src_mac)
2341 self.assertEqual(inner[Ether].dst, routed_dst_mac)
2342 self.assertEqual(inner[IP].src, ep.ip4.address)
2343 self.assertEqual(inner[IP].dst, ip)
2346 # remove the API remote EPs, only API sourced is gone, the DP
2347 # learnt one remains
2349 rep_88.remove_vpp_config()
2350 rep_2.remove_vpp_config()
2352 self.logger.info(self.vapi.cli("show gbp endpoint"))
2354 self.assertFalse(find_gbp_endpoint(self, ip=rep_88.ip4.address))
2356 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2357 IP(src=ep.ip4.address, dst=rep_88.ip4.address) /
2358 UDP(sport=1234, dport=1234) /
2360 rxs = self.send_and_expect(self.pg0, [p], self.pg4)
2362 self.assertTrue(find_gbp_endpoint(self, ip=rep_2.ip4.address))
2364 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2365 IP(src=ep.ip4.address, dst=rep_2.ip4.address) /
2366 UDP(sport=1234, dport=1234) /
2368 rxs = self.send_and_expect(self.pg0, [p], self.pg2)
2371 # to appease the testcase we cannot have the registered EP stll
2372 # present (because it's DP learnt) when the TC ends so wait until
2378 # shutdown with learnt endpoint present
2380 p = (Ether(src=self.pg2.remote_mac,
2381 dst=self.pg2.local_mac) /
2382 IP(src=self.pg2.remote_hosts[1].ip4,
2383 dst=self.pg2.local_ip4) /
2384 UDP(sport=1234, dport=48879) /
2385 VXLAN(vni=101, gpid=220, flags=0x88) /
2386 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2387 IP(src=learnt[1]['ip'], dst=ep.ip4.address) /
2388 UDP(sport=1234, dport=1234) /
2391 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2393 # endpoint learnt via the parent GBP-vxlan interface
2394 self.assertTrue(find_gbp_endpoint(self,
2395 vx_tun_l3._sw_if_index,
2400 # remote endpoint becomes local
2402 self.pg2.unconfig_ip4()
2403 self.pg3.unconfig_ip4()
2404 self.pg4.unconfig_ip4()
2406 def test_gbp_redirect(self):
2407 """ GBP Endpoint Redirect """
2409 self.vapi.cli("set logging class gbp debug")
2411 routed_dst_mac = "00:0c:0c:0c:0c:0c"
2412 routed_src_mac = "00:22:bd:f8:19:ff"
2414 learnt = [{'mac': '00:00:11:11:11:02',
2416 'ip6': '2001:10::2'},
2417 {'mac': '00:00:11:11:11:03',
2419 'ip6': '2001:10::3'}]
2422 # lower the inactive threshold so these tests pass in a
2423 # reasonable amount of time
2425 self.vapi.gbp_endpoint_learn_set_inactive_threshold(1)
2430 t4 = VppIpTable(self, 1)
2432 t6 = VppIpTable(self, 1, True)
2435 rd1 = VppGbpRouteDomain(self, 2, t4, t6)
2436 rd1.add_vpp_config()
2438 self.loop0.set_mac(self.router_mac.address)
2441 # Bind the BVI to the RD
2443 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
2444 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
2447 # Pg7 hosts a BD's UU-fwd
2449 self.pg7.config_ip4()
2450 self.pg7.resolve_arp()
2453 # a GBP bridge domains for the EPs
2455 bd1 = VppBridgeDomain(self, 1)
2456 bd1.add_vpp_config()
2457 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0)
2458 gbd1.add_vpp_config()
2460 bd2 = VppBridgeDomain(self, 2)
2461 bd2.add_vpp_config()
2462 gbd2 = VppGbpBridgeDomain(self, bd2, self.loop1)
2463 gbd2.add_vpp_config()
2465 # ... and has a /32 and /128 applied
2466 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2467 ip4_addr.add_vpp_config()
2468 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 128)
2469 ip6_addr.add_vpp_config()
2470 ip4_addr = VppIpInterfaceAddress(self, gbd2.bvi, "10.0.1.128", 32)
2471 ip4_addr.add_vpp_config()
2472 ip6_addr = VppIpInterfaceAddress(self, gbd2.bvi, "2001:11::128", 128)
2473 ip6_addr.add_vpp_config()
2476 # The Endpoint-groups in which we are learning endpoints
2478 epg_220 = VppGbpEndpointGroup(self, 220, rd1, gbd1,
2482 epg_220.add_vpp_config()
2483 epg_221 = VppGbpEndpointGroup(self, 221, rd1, gbd2,
2487 epg_221.add_vpp_config()
2488 epg_222 = VppGbpEndpointGroup(self, 222, rd1, gbd1,
2492 epg_222.add_vpp_config()
2495 # a GBP bridge domains for the SEPs
2497 bd_uu1 = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
2498 self.pg7.remote_ip4, 116)
2499 bd_uu1.add_vpp_config()
2500 bd_uu2 = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
2501 self.pg7.remote_ip4, 117)
2502 bd_uu2.add_vpp_config()
2504 bd3 = VppBridgeDomain(self, 3)
2505 bd3.add_vpp_config()
2506 gbd3 = VppGbpBridgeDomain(self, bd3, self.loop2, bd_uu1, learn=False)
2507 gbd3.add_vpp_config()
2508 bd4 = VppBridgeDomain(self, 4)
2509 bd4.add_vpp_config()
2510 gbd4 = VppGbpBridgeDomain(self, bd4, self.loop3, bd_uu2, learn=False)
2511 gbd4.add_vpp_config()
2514 # EPGs in which the service endpoints exist
2516 epg_320 = VppGbpEndpointGroup(self, 320, rd1, gbd3,
2520 epg_320.add_vpp_config()
2521 epg_321 = VppGbpEndpointGroup(self, 321, rd1, gbd4,
2525 epg_321.add_vpp_config()
2528 # three local endpoints
2530 ep1 = VppGbpEndpoint(self, self.pg0,
2532 "10.0.0.1", "11.0.0.1",
2533 "2001:10::1", "3001:10::1")
2534 ep1.add_vpp_config()
2535 ep2 = VppGbpEndpoint(self, self.pg1,
2537 "10.0.1.1", "11.0.1.1",
2538 "2001:11::1", "3001:11::1")
2539 ep2.add_vpp_config()
2540 ep3 = VppGbpEndpoint(self, self.pg2,
2542 "10.0.2.2", "11.0.2.2",
2543 "2001:12::1", "3001:12::1")
2544 ep3.add_vpp_config()
2549 sep1 = VppGbpEndpoint(self, self.pg3,
2551 "12.0.0.1", "13.0.0.1",
2552 "4001:10::1", "5001:10::1")
2553 sep1.add_vpp_config()
2554 sep2 = VppGbpEndpoint(self, self.pg4,
2556 "12.0.0.2", "13.0.0.2",
2557 "4001:10::2", "5001:10::2")
2558 sep2.add_vpp_config()
2559 sep3 = VppGbpEndpoint(self, self.pg5,
2561 "12.0.1.1", "13.0.1.1",
2562 "4001:11::1", "5001:11::1")
2563 sep3.add_vpp_config()
2564 # this EP is not installed immediately
2565 sep4 = VppGbpEndpoint(self, self.pg6,
2567 "12.0.1.2", "13.0.1.2",
2568 "4001:11::2", "5001:11::2")
2571 # an L2 switch packet between local EPs in different EPGs
2572 # different dest ports on each so the are LB hashed differently
2574 p4 = [(Ether(src=ep1.mac, dst=ep3.mac) /
2575 IP(src=ep1.ip4.address, dst=ep3.ip4.address) /
2576 UDP(sport=1234, dport=1234) /
2578 (Ether(src=ep1.mac, dst=ep3.mac) /
2579 IP(src=ep1.ip4.address, dst=ep3.ip4.address) /
2580 UDP(sport=1234, dport=1235) /
2582 p6 = [(Ether(src=ep1.mac, dst=ep3.mac) /
2583 IPv6(src=ep1.ip6.address, dst=ep3.ip6.address) /
2584 UDP(sport=1234, dport=1234) /
2586 (Ether(src=ep1.mac, dst=ep3.mac) /
2587 IPv6(src=ep1.ip6.address, dst=ep3.ip6.address) /
2588 UDP(sport=1234, dport=1230) /
2591 # should be dropped since no contract yet
2592 self.send_and_assert_no_replies(self.pg0, [p4[0]])
2593 self.send_and_assert_no_replies(self.pg0, [p6[0]])
2596 # Add a contract with a rule to load-balance redirect via SEP1 and SEP2
2597 # one of the next-hops is via an EP that is not known
2599 acl = VppGbpAcl(self)
2600 rule4 = acl.create_rule(permit_deny=1, proto=17)
2601 rule6 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
2602 acl_index = acl.add_vpp_config([rule4, rule6])
2604 c1 = VppGbpContract(
2605 self, 220, 222, acl_index,
2606 [VppGbpContractRule(
2607 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2608 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
2609 sep1.ip4, sep1.epg.rd),
2610 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
2611 sep2.ip4, sep2.epg.rd)]),
2613 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2614 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
2615 sep3.ip6, sep3.epg.rd),
2616 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
2617 sep4.ip6, sep4.epg.rd)])])
2621 # send again with the contract preset, now packets arrive
2622 # at SEP1 or SEP2 depending on the hashing
2624 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep2.itf)
2627 self.assertEqual(rx[Ether].src, routed_src_mac)
2628 self.assertEqual(rx[Ether].dst, sep2.mac)
2629 self.assertEqual(rx[IP].src, ep1.ip4.address)
2630 self.assertEqual(rx[IP].dst, ep3.ip4.address)
2632 rxs = self.send_and_expect(self.pg0, p4[1] * 17, sep1.itf)
2635 self.assertEqual(rx[Ether].src, routed_src_mac)
2636 self.assertEqual(rx[Ether].dst, sep1.mac)
2637 self.assertEqual(rx[IP].src, ep1.ip4.address)
2638 self.assertEqual(rx[IP].dst, ep3.ip4.address)
2640 rxs = self.send_and_expect(self.pg0, p6[0] * 17, self.pg7)
2643 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
2644 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
2645 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
2646 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
2647 self.assertEqual(rx[VXLAN].vni, 117)
2648 self.assertTrue(rx[VXLAN].flags.G)
2649 self.assertTrue(rx[VXLAN].flags.Instance)
2650 # redirect policy has been applied
2651 self.assertTrue(rx[VXLAN].gpflags.A)
2652 self.assertFalse(rx[VXLAN].gpflags.D)
2654 inner = rx[VXLAN].payload
2656 self.assertEqual(inner[Ether].src, routed_src_mac)
2657 self.assertEqual(inner[Ether].dst, sep4.mac)
2658 self.assertEqual(inner[IPv6].src, ep1.ip6.address)
2659 self.assertEqual(inner[IPv6].dst, ep3.ip6.address)
2661 rxs = self.send_and_expect(self.pg0, p6[1] * 17, sep3.itf)
2664 self.assertEqual(rx[Ether].src, routed_src_mac)
2665 self.assertEqual(rx[Ether].dst, sep3.mac)
2666 self.assertEqual(rx[IPv6].src, ep1.ip6.address)
2667 self.assertEqual(rx[IPv6].dst, ep3.ip6.address)
2670 # programme the unknown EP
2672 sep4.add_vpp_config()
2674 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep4.itf)
2677 self.assertEqual(rx[Ether].src, routed_src_mac)
2678 self.assertEqual(rx[Ether].dst, sep4.mac)
2679 self.assertEqual(rx[IPv6].src, ep1.ip6.address)
2680 self.assertEqual(rx[IPv6].dst, ep3.ip6.address)
2683 # and revert back to unprogrammed
2685 sep4.remove_vpp_config()
2687 rxs = self.send_and_expect(self.pg0, p6[0] * 17, self.pg7)
2690 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
2691 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
2692 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
2693 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
2694 self.assertEqual(rx[VXLAN].vni, 117)
2695 self.assertTrue(rx[VXLAN].flags.G)
2696 self.assertTrue(rx[VXLAN].flags.Instance)
2697 # redirect policy has been applied
2698 self.assertTrue(rx[VXLAN].gpflags.A)
2699 self.assertFalse(rx[VXLAN].gpflags.D)
2701 inner = rx[VXLAN].payload
2703 self.assertEqual(inner[Ether].src, routed_src_mac)
2704 self.assertEqual(inner[Ether].dst, sep4.mac)
2705 self.assertEqual(inner[IPv6].src, ep1.ip6.address)
2706 self.assertEqual(inner[IPv6].dst, ep3.ip6.address)
2709 # programme the unknown EP for the L3 tests
2711 sep4.add_vpp_config()
2714 # an L3 switch packet between local EPs in different EPGs
2715 # different dest ports on each so the are LB hashed differently
2717 p4 = [(Ether(src=ep1.mac, dst=self.router_mac.address) /
2718 IP(src=ep1.ip4.address, dst=ep2.ip4.address) /
2719 UDP(sport=1234, dport=1234) /
2721 (Ether(src=ep1.mac, dst=self.router_mac.address) /
2722 IP(src=ep1.ip4.address, dst=ep2.ip4.address) /
2723 UDP(sport=1234, dport=1235) /
2725 p6 = [(Ether(src=ep1.mac, dst=self.router_mac.address) /
2726 IPv6(src=ep1.ip6.address, dst=ep2.ip6.address) /
2727 UDP(sport=1234, dport=1234) /
2729 (Ether(src=ep1.mac, dst=self.router_mac.address) /
2730 IPv6(src=ep1.ip6.address, dst=ep2.ip6.address) /
2731 UDP(sport=1234, dport=1230) /
2734 c2 = VppGbpContract(
2735 self, 220, 221, acl_index,
2736 [VppGbpContractRule(
2737 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2738 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
2739 sep1.ip4, sep1.epg.rd),
2740 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
2741 sep2.ip4, sep2.epg.rd)]),
2743 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2744 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
2745 sep3.ip6, sep3.epg.rd),
2746 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
2747 sep4.ip6, sep4.epg.rd)])])
2750 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep2.itf)
2753 self.assertEqual(rx[Ether].src, routed_src_mac)
2754 self.assertEqual(rx[Ether].dst, sep2.mac)
2755 self.assertEqual(rx[IP].src, ep1.ip4.address)
2756 self.assertEqual(rx[IP].dst, ep2.ip4.address)
2759 # learn a remote EP in EPG 221
2761 vx_tun_l3 = VppGbpVxlanTunnel(
2762 self, 444, rd1.rd_id,
2763 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3)
2764 vx_tun_l3.add_vpp_config()
2766 c3 = VppGbpContract(
2767 self, 221, 220, acl_index,
2768 [VppGbpContractRule(
2769 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2772 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2776 p = (Ether(src=self.pg7.remote_mac,
2777 dst=self.pg7.local_mac) /
2778 IP(src=self.pg7.remote_ip4,
2779 dst=self.pg7.local_ip4) /
2780 UDP(sport=1234, dport=48879) /
2781 VXLAN(vni=444, gpid=221, flags=0x88) /
2782 Ether(src="00:22:22:22:22:33", dst=self.router_mac.address) /
2783 IP(src="10.0.0.88", dst=ep1.ip4.address) /
2784 UDP(sport=1234, dport=1234) /
2787 rx = self.send_and_expect(self.pg7, [p], self.pg0)
2789 # endpoint learnt via the parent GBP-vxlan interface
2790 self.assertTrue(find_gbp_endpoint(self,
2791 vx_tun_l3._sw_if_index,
2794 p = (Ether(src=self.pg7.remote_mac,
2795 dst=self.pg7.local_mac) /
2796 IP(src=self.pg7.remote_ip4,
2797 dst=self.pg7.local_ip4) /
2798 UDP(sport=1234, dport=48879) /
2799 VXLAN(vni=444, gpid=221, flags=0x88) /
2800 Ether(src="00:22:22:22:22:33", dst=self.router_mac.address) /
2801 IPv6(src="2001:10::88", dst=ep1.ip6.address) /
2802 UDP(sport=1234, dport=1234) /
2805 rx = self.send_and_expect(self.pg7, [p], self.pg0)
2807 # endpoint learnt via the parent GBP-vxlan interface
2808 self.assertTrue(find_gbp_endpoint(self,
2809 vx_tun_l3._sw_if_index,
2813 # L3 switch from local to remote EP
2815 p4 = [(Ether(src=ep1.mac, dst=self.router_mac.address) /
2816 IP(src=ep1.ip4.address, dst="10.0.0.88") /
2817 UDP(sport=1234, dport=1234) /
2819 (Ether(src=ep1.mac, dst=self.router_mac.address) /
2820 IP(src=ep1.ip4.address, dst="10.0.0.88") /
2821 UDP(sport=1234, dport=1235) /
2823 p6 = [(Ether(src=ep1.mac, dst=self.router_mac.address) /
2824 IPv6(src=ep1.ip6.address, dst="2001:10::88") /
2825 UDP(sport=1234, dport=1234) /
2827 (Ether(src=ep1.mac, dst=self.router_mac.address) /
2828 IPv6(src=ep1.ip6.address, dst="2001:10::88") /
2829 UDP(sport=1234, dport=123) /
2832 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep2.itf)
2835 self.assertEqual(rx[Ether].src, routed_src_mac)
2836 self.assertEqual(rx[Ether].dst, sep2.mac)
2837 self.assertEqual(rx[IP].src, ep1.ip4.address)
2838 self.assertEqual(rx[IP].dst, "10.0.0.88")
2840 rxs = self.send_and_expect(self.pg0, p4[1] * 17, sep1.itf)
2843 self.assertEqual(rx[Ether].src, routed_src_mac)
2844 self.assertEqual(rx[Ether].dst, sep1.mac)
2845 self.assertEqual(rx[IP].src, ep1.ip4.address)
2846 self.assertEqual(rx[IP].dst, "10.0.0.88")
2848 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep4.itf)
2851 self.assertEqual(rx[Ether].src, routed_src_mac)
2852 self.assertEqual(rx[Ether].dst, sep4.mac)
2853 self.assertEqual(rx[IPv6].src, ep1.ip6.address)
2854 self.assertEqual(rx[IPv6].dst, "2001:10::88")
2856 rxs = self.send_and_expect(self.pg0, p6[1] * 17, sep3.itf)
2859 self.assertEqual(rx[Ether].src, routed_src_mac)
2860 self.assertEqual(rx[Ether].dst, sep3.mac)
2861 self.assertEqual(rx[IPv6].src, ep1.ip6.address)
2862 self.assertEqual(rx[IPv6].dst, "2001:10::88")
2865 if __name__ == '__main__':
2866 unittest.main(testRunner=VppTestRunner)