3 from socket import AF_INET, AF_INET6
6 from scapy.packet import Raw
7 from scapy.layers.l2 import Ether, ARP, Dot1Q
8 from scapy.layers.inet import IP, UDP
9 from scapy.layers.inet6 import IPv6, ICMPv6ND_NS, ICMPv6NDOptSrcLLAddr, \
11 from scapy.utils6 import in6_getnsma, in6_getnsmac
12 from scapy.layers.vxlan import VXLAN
13 from scapy.data import ETH_P_IP, ETH_P_IPV6
14 from scapy.utils import inet_pton, inet_ntop
16 from framework import VppTestCase, VppTestRunner
17 from vpp_object import VppObject
18 from vpp_interface import VppInterface
19 from vpp_ip_route import VppIpRoute, VppRoutePath, VppIpTable, \
20 VppIpInterfaceAddress, VppIpInterfaceBind, find_route
21 from vpp_l2 import VppBridgeDomain, VppBridgeDomainPort, \
22 VppBridgeDomainArpEntry, VppL2FibEntry, find_bridge_domain_port
23 from vpp_sub_interface import VppDot1QSubint
24 from vpp_ip import VppIpAddress, VppIpPrefix
25 from vpp_papi import VppEnum, MACAddress
26 from vpp_papi_provider import L2_VTR_OP
27 from vpp_vxlan_gbp_tunnel import find_vxlan_gbp_tunnel, INDEX_INVALID, \
31 def find_gbp_endpoint(test, sw_if_index=None, ip=None, mac=None):
33 vip = VppIpAddress(ip)
35 vmac = MACAddress(mac)
37 eps = test.vapi.gbp_endpoint_dump()
41 if ep.endpoint.sw_if_index != sw_if_index:
44 for eip in ep.endpoint.ips:
48 if vmac.packed == ep.endpoint.mac:
53 def find_gbp_vxlan(test, vni):
54 ts = test.vapi.gbp_vxlan_tunnel_dump()
56 if t.tunnel.vni == vni:
61 class VppGbpEndpoint(VppObject):
72 return self.itf.remote_mac
92 return [self.ip4, self.ip6]
96 return [self.fip4, self.fip6]
98 def __init__(self, test, itf, epg, recirc, ip4, fip4, ip6, fip6,
108 self._ip4 = VppIpAddress(ip4)
109 self._fip4 = VppIpAddress(fip4)
110 self._ip6 = VppIpAddress(ip6)
111 self._fip6 = VppIpAddress(fip6)
114 self.vmac = MACAddress(self.itf.remote_mac)
116 self.vmac = MACAddress("00:00:00:00:00:00")
119 self.tun_src = VppIpAddress(tun_src)
120 self.tun_dst = VppIpAddress(tun_dst)
122 def add_vpp_config(self):
123 res = self._test.vapi.gbp_endpoint_add(
124 self.itf.sw_if_index,
125 [self.ip4.encode(), self.ip6.encode()],
129 self.tun_src.encode(),
130 self.tun_dst.encode())
131 self.handle = res.handle
132 self._test.registry.register(self, self._test.logger)
134 def remove_vpp_config(self):
135 self._test.vapi.gbp_endpoint_del(self.handle)
138 return self.object_id()
141 return "gbp-endpoint:[%d==%d:%s:%d]" % (self.handle,
142 self.itf.sw_if_index,
146 def query_vpp_config(self):
147 return find_gbp_endpoint(self._test,
148 self.itf.sw_if_index,
152 class VppGbpRecirc(VppObject):
154 GBP Recirculation Interface
157 def __init__(self, test, epg, recirc, is_ext=False):
163 def add_vpp_config(self):
164 self._test.vapi.gbp_recirc_add_del(
166 self.recirc.sw_if_index,
169 self._test.registry.register(self, self._test.logger)
171 def remove_vpp_config(self):
172 self._test.vapi.gbp_recirc_add_del(
174 self.recirc.sw_if_index,
179 return self.object_id()
182 return "gbp-recirc:[%d]" % (self.recirc.sw_if_index)
184 def query_vpp_config(self):
185 rs = self._test.vapi.gbp_recirc_dump()
187 if r.recirc.sw_if_index == self.recirc.sw_if_index:
192 class VppGbpExtItf(VppObject):
194 GBP ExtItfulation Interface
197 def __init__(self, test, itf, bd, rd):
203 def add_vpp_config(self):
204 self._test.vapi.gbp_ext_itf_add_del(
206 self.itf.sw_if_index,
209 self._test.registry.register(self, self._test.logger)
211 def remove_vpp_config(self):
212 self._test.vapi.gbp_ext_itf_add_del(
214 self.itf.sw_if_index,
219 return self.object_id()
222 return "gbp-ext-itf:[%d]" % (self.itf.sw_if_index)
224 def query_vpp_config(self):
225 rs = self._test.vapi.gbp_ext_itf_dump()
227 if r.ext_itf.sw_if_index == self.itf.sw_if_index:
232 class VppGbpSubnet(VppObject):
236 def __init__(self, test, rd, address, address_len,
237 type, sw_if_index=None, epg=None):
239 self.rd_id = rd.rd_id
240 self.prefix = VppIpPrefix(address, address_len)
242 self.sw_if_index = sw_if_index
245 def add_vpp_config(self):
246 self._test.vapi.gbp_subnet_add_del(
249 self.prefix.encode(),
251 sw_if_index=self.sw_if_index if self.sw_if_index else 0xffffffff,
252 epg_id=self.epg if self.epg else 0xffff)
253 self._test.registry.register(self, self._test.logger)
255 def remove_vpp_config(self):
256 self._test.vapi.gbp_subnet_add_del(
259 self.prefix.encode(),
263 return self.object_id()
266 return "gbp-subnet:[%d-%s]" % (self.rd_id, self.prefix)
268 def query_vpp_config(self):
269 ss = self._test.vapi.gbp_subnet_dump()
271 if s.subnet.rd_id == self.rd_id and \
272 s.subnet.type == self.type and \
273 s.subnet.prefix == self.prefix:
278 class VppGbpEndpointRetention(object):
279 def __init__(self, remote_ep_timeout=0xffffffff):
280 self.remote_ep_timeout = remote_ep_timeout
283 return {'remote_ep_timeout': self.remote_ep_timeout}
286 class VppGbpEndpointGroup(VppObject):
291 def __init__(self, test, epg, sclass, rd, bd, uplink,
292 bvi, bvi_ip4, bvi_ip6=None,
293 retention=VppGbpEndpointRetention()):
297 self.bvi_ip4 = VppIpAddress(bvi_ip4)
298 self.bvi_ip6 = VppIpAddress(bvi_ip6)
305 self.retention = retention
307 def add_vpp_config(self):
308 self._test.vapi.gbp_endpoint_group_add(
313 self.uplink.sw_if_index if self.uplink else INDEX_INVALID,
314 self.retention.encode())
315 self._test.registry.register(self, self._test.logger)
317 def remove_vpp_config(self):
318 self._test.vapi.gbp_endpoint_group_del(self.epg)
321 return self.object_id()
324 return "gbp-endpoint-group:[%d]" % (self.epg)
326 def query_vpp_config(self):
327 epgs = self._test.vapi.gbp_endpoint_group_dump()
329 if epg.epg.epg_id == self.epg:
334 class VppGbpBridgeDomain(VppObject):
339 def __init__(self, test, bd, bvi, uu_fwd=None,
340 bm_flood=None, learn=True):
344 self.bm_flood = bm_flood
347 e = VppEnum.vl_api_gbp_bridge_domain_flags_t
349 self.learn = e.GBP_BD_API_FLAG_NONE
351 self.learn = e.GBP_BD_API_FLAG_DO_NOT_LEARN
353 def add_vpp_config(self):
354 self._test.vapi.gbp_bridge_domain_add(
357 self.bvi.sw_if_index,
358 self.uu_fwd.sw_if_index if self.uu_fwd else INDEX_INVALID,
359 self.bm_flood.sw_if_index if self.bm_flood else INDEX_INVALID)
360 self._test.registry.register(self, self._test.logger)
362 def remove_vpp_config(self):
363 self._test.vapi.gbp_bridge_domain_del(self.bd.bd_id)
366 return self.object_id()
369 return "gbp-bridge-domain:[%d]" % (self.bd.bd_id)
371 def query_vpp_config(self):
372 bds = self._test.vapi.gbp_bridge_domain_dump()
374 if bd.bd.bd_id == self.bd.bd_id:
379 class VppGbpRouteDomain(VppObject):
384 def __init__(self, test, rd_id, t4, t6, ip4_uu=None, ip6_uu=None):
392 def add_vpp_config(self):
393 self._test.vapi.gbp_route_domain_add(
397 self.ip4_uu.sw_if_index if self.ip4_uu else INDEX_INVALID,
398 self.ip6_uu.sw_if_index if self.ip6_uu else INDEX_INVALID)
399 self._test.registry.register(self, self._test.logger)
401 def remove_vpp_config(self):
402 self._test.vapi.gbp_route_domain_del(self.rd_id)
405 return self.object_id()
408 return "gbp-route-domain:[%d]" % (self.rd_id)
410 def query_vpp_config(self):
411 rds = self._test.vapi.gbp_route_domain_dump()
413 if rd.rd.rd_id == self.rd_id:
418 class VppGbpContractNextHop():
419 def __init__(self, mac, bd, ip, rd):
426 return {'ip': self.ip.encode(),
427 'mac': self.mac.packed,
428 'bd_id': self.bd.bd.bd_id,
429 'rd_id': self.rd.rd_id}
432 class VppGbpContractRule():
433 def __init__(self, action, hash_mode, nhs=[]):
435 self.hash_mode = hash_mode
441 nhs.append(nh.encode())
444 return {'action': self.action,
446 'hash_mode': self.hash_mode,
447 'n_nhs': len(self.nhs),
451 class VppGbpContract(VppObject):
456 def __init__(self, test, src_epg, dst_epg, acl_index,
457 rules, allowed_ethertypes):
459 self.acl_index = acl_index
460 self.src_epg = src_epg
461 self.dst_epg = dst_epg
463 self.allowed_ethertypes = allowed_ethertypes
465 def add_vpp_config(self):
468 rules.append(r.encode())
469 self._test.vapi.gbp_contract_add_del(
475 self.allowed_ethertypes)
476 self._test.registry.register(self, self._test.logger)
478 def remove_vpp_config(self):
479 self._test.vapi.gbp_contract_add_del(
487 return self.object_id()
490 return "gbp-contract:[%d:%s:%d]" % (self.src_epg,
494 def query_vpp_config(self):
495 cs = self._test.vapi.gbp_contract_dump()
497 if c.contract.src_epg == self.src_epg \
498 and c.contract.dst_epg == self.dst_epg:
503 class VppGbpVxlanTunnel(VppInterface):
508 def __init__(self, test, vni, bd_rd_id, mode):
509 super(VppGbpVxlanTunnel, self).__init__(test)
512 self.bd_rd_id = bd_rd_id
515 def add_vpp_config(self):
516 r = self._test.vapi.gbp_vxlan_tunnel_add(
520 self.set_sw_if_index(r.sw_if_index)
521 self._test.registry.register(self, self._test.logger)
523 def remove_vpp_config(self):
524 self._test.vapi.gbp_vxlan_tunnel_del(self.vni)
527 return self.object_id()
530 return "gbp-vxlan:%d" % (self.vni)
532 def query_vpp_config(self):
533 return find_gbp_vxlan(self._test, self.vni)
536 class VppGbpAcl(VppObject):
541 def __init__(self, test):
543 self.acl_index = 4294967295
545 def create_rule(self, is_ipv6=0, permit_deny=0, proto=-1,
546 s_prefix=0, s_ip='\x00\x00\x00\x00', sport_from=0,
547 sport_to=65535, d_prefix=0, d_ip='\x00\x00\x00\x00',
548 dport_from=0, dport_to=65535):
549 if proto == -1 or proto == 0:
552 elif proto == 1 or proto == 58:
555 rule = ({'is_permit': permit_deny, 'is_ipv6': is_ipv6, 'proto': proto,
556 'srcport_or_icmptype_first': sport_from,
557 'srcport_or_icmptype_last': sport_to,
558 'src_ip_prefix_len': s_prefix,
560 'dstport_or_icmpcode_first': dport_from,
561 'dstport_or_icmpcode_last': dport_to,
562 'dst_ip_prefix_len': d_prefix,
563 'dst_ip_addr': d_ip})
566 def add_vpp_config(self, rules):
568 reply = self._test.vapi.acl_add_replace(self.acl_index,
571 self.acl_index = reply.acl_index
572 return self.acl_index
574 def remove_vpp_config(self):
575 self._test.vapi.acl_del(self.acl_index)
578 return self.object_id()
581 return "gbp-acl:[%d]" % (self.acl_index)
583 def query_vpp_config(self):
584 cs = self._test.vapi.acl_dump()
586 if c.acl_index == self.acl_index:
591 class TestGBP(VppTestCase):
592 """ GBP Test Case """
595 super(TestGBP, self).setUp()
597 self.create_pg_interfaces(range(9))
598 self.create_loopback_interfaces(8)
600 self.router_mac = MACAddress("00:11:22:33:44:55")
602 for i in self.pg_interfaces:
604 for i in self.lo_interfaces:
608 for i in self.pg_interfaces:
611 super(TestGBP, self).tearDown()
613 def send_and_expect_bridged(self, src, tx, dst):
614 rx = self.send_and_expect(src, tx, dst)
617 self.assertEqual(r[Ether].src, tx[0][Ether].src)
618 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
619 self.assertEqual(r[IP].src, tx[0][IP].src)
620 self.assertEqual(r[IP].dst, tx[0][IP].dst)
623 def send_and_expect_bridged6(self, src, tx, dst):
624 rx = self.send_and_expect(src, tx, dst)
627 self.assertEqual(r[Ether].src, tx[0][Ether].src)
628 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
629 self.assertEqual(r[IPv6].src, tx[0][IPv6].src)
630 self.assertEqual(r[IPv6].dst, tx[0][IPv6].dst)
633 def send_and_expect_routed(self, src, tx, dst, src_mac):
634 rx = self.send_and_expect(src, tx, dst)
637 self.assertEqual(r[Ether].src, src_mac)
638 self.assertEqual(r[Ether].dst, dst.remote_mac)
639 self.assertEqual(r[IP].src, tx[0][IP].src)
640 self.assertEqual(r[IP].dst, tx[0][IP].dst)
643 def send_and_expect_natted(self, src, tx, dst, src_ip):
644 rx = self.send_and_expect(src, tx, dst)
647 self.assertEqual(r[Ether].src, tx[0][Ether].src)
648 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
649 self.assertEqual(r[IP].src, src_ip)
650 self.assertEqual(r[IP].dst, tx[0][IP].dst)
653 def send_and_expect_natted6(self, src, tx, dst, src_ip):
654 rx = self.send_and_expect(src, tx, dst)
657 self.assertEqual(r[Ether].src, tx[0][Ether].src)
658 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
659 self.assertEqual(r[IPv6].src, src_ip)
660 self.assertEqual(r[IPv6].dst, tx[0][IPv6].dst)
663 def send_and_expect_unnatted(self, src, tx, dst, dst_ip):
664 rx = self.send_and_expect(src, tx, dst)
667 self.assertEqual(r[Ether].src, tx[0][Ether].src)
668 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
669 self.assertEqual(r[IP].dst, dst_ip)
670 self.assertEqual(r[IP].src, tx[0][IP].src)
673 def send_and_expect_unnatted6(self, src, tx, dst, dst_ip):
674 rx = self.send_and_expect(src, tx, dst)
677 self.assertEqual(r[Ether].src, tx[0][Ether].src)
678 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
679 self.assertEqual(r[IPv6].dst, dst_ip)
680 self.assertEqual(r[IPv6].src, tx[0][IPv6].src)
683 def send_and_expect_double_natted(self, src, tx, dst, src_ip, dst_ip):
684 rx = self.send_and_expect(src, tx, dst)
687 self.assertEqual(r[Ether].src, str(self.router_mac))
688 self.assertEqual(r[Ether].dst, dst.remote_mac)
689 self.assertEqual(r[IP].dst, dst_ip)
690 self.assertEqual(r[IP].src, src_ip)
693 def send_and_expect_double_natted6(self, src, tx, dst, src_ip, dst_ip):
694 rx = self.send_and_expect(src, tx, dst)
697 self.assertEqual(r[Ether].src, str(self.router_mac))
698 self.assertEqual(r[Ether].dst, dst.remote_mac)
699 self.assertEqual(r[IPv6].dst, dst_ip)
700 self.assertEqual(r[IPv6].src, src_ip)
704 """ Group Based Policy """
706 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
711 bd1 = VppBridgeDomain(self, 1)
712 bd2 = VppBridgeDomain(self, 2)
713 bd20 = VppBridgeDomain(self, 20)
717 bd20.add_vpp_config()
719 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0)
720 gbd2 = VppGbpBridgeDomain(self, bd2, self.loop1)
721 gbd20 = VppGbpBridgeDomain(self, bd20, self.loop2)
723 gbd1.add_vpp_config()
724 gbd2.add_vpp_config()
725 gbd20.add_vpp_config()
730 gt4 = VppIpTable(self, 0)
732 gt6 = VppIpTable(self, 0, is_ip6=True)
734 nt4 = VppIpTable(self, 20)
736 nt6 = VppIpTable(self, 20, is_ip6=True)
739 rd0 = VppGbpRouteDomain(self, 0, gt4, gt6, None, None)
740 rd20 = VppGbpRouteDomain(self, 20, nt4, nt6, None, None)
743 rd20.add_vpp_config()
746 # 3 EPGs, 2 of which share a BD.
747 # 2 NAT EPGs, one for floating-IP subnets, the other for internet
749 epgs = [VppGbpEndpointGroup(self, 220, 0, rd0, gbd1, self.pg4,
753 VppGbpEndpointGroup(self, 221, 0, rd0, gbd1, self.pg5,
757 VppGbpEndpointGroup(self, 222, 0, rd0, gbd2, self.pg6,
761 VppGbpEndpointGroup(self, 333, 0, rd20, gbd20, self.pg7,
765 VppGbpEndpointGroup(self, 444, 0, rd20, gbd20, self.pg8,
769 recircs = [VppGbpRecirc(self, epgs[0],
771 VppGbpRecirc(self, epgs[1],
773 VppGbpRecirc(self, epgs[2],
775 VppGbpRecirc(self, epgs[3],
776 self.loop6, is_ext=True),
777 VppGbpRecirc(self, epgs[4],
778 self.loop7, is_ext=True)]
781 recirc_nat = recircs[3]
784 # 4 end-points, 2 in the same subnet, 3 in the same BD
786 eps = [VppGbpEndpoint(self, self.pg0,
788 "10.0.0.1", "11.0.0.1",
789 "2001:10::1", "3001::1"),
790 VppGbpEndpoint(self, self.pg1,
792 "10.0.0.2", "11.0.0.2",
793 "2001:10::2", "3001::2"),
794 VppGbpEndpoint(self, self.pg2,
796 "10.0.1.1", "11.0.0.3",
797 "2001:10:1::1", "3001::3"),
798 VppGbpEndpoint(self, self.pg3,
800 "10.0.2.1", "11.0.0.4",
801 "2001:10:2::1", "3001::4")]
804 # Config related to each of the EPGs
807 # IP config on the BVI interfaces
808 if epg != epgs[1] and epg != epgs[4]:
809 VppIpInterfaceBind(self, epg.bvi, epg.rd.t4).add_vpp_config()
810 VppIpInterfaceBind(self, epg.bvi, epg.rd.t6).add_vpp_config()
811 self.vapi.sw_interface_set_mac_address(
813 self.router_mac.packed)
815 # The BVIs are NAT inside interfaces
816 self.vapi.nat44_interface_add_del_feature(epg.bvi.sw_if_index,
819 self.vapi.nat66_add_del_interface(epg.bvi.sw_if_index,
823 if_ip4 = VppIpInterfaceAddress(self, epg.bvi, epg.bvi_ip4, 32)
824 if_ip6 = VppIpInterfaceAddress(self, epg.bvi, epg.bvi_ip6, 128)
825 if_ip4.add_vpp_config()
826 if_ip6.add_vpp_config()
828 # EPG uplink interfaces in the RD
829 VppIpInterfaceBind(self, epg.uplink, epg.rd.t4).add_vpp_config()
830 VppIpInterfaceBind(self, epg.uplink, epg.rd.t6).add_vpp_config()
832 # add the BD ARP termination entry for BVI IP
833 epg.bd_arp_ip4 = VppBridgeDomainArpEntry(self, epg.bd.bd,
834 str(self.router_mac),
836 epg.bd_arp_ip6 = VppBridgeDomainArpEntry(self, epg.bd.bd,
837 str(self.router_mac),
839 epg.bd_arp_ip4.add_vpp_config()
840 epg.bd_arp_ip6.add_vpp_config()
845 for recirc in recircs:
846 # EPG's ingress recirculation interface maps to its RD
847 VppIpInterfaceBind(self, recirc.recirc,
848 recirc.epg.rd.t4).add_vpp_config()
849 VppIpInterfaceBind(self, recirc.recirc,
850 recirc.epg.rd.t6).add_vpp_config()
852 self.vapi.nat44_interface_add_del_feature(
853 recirc.recirc.sw_if_index,
856 self.vapi.nat66_add_del_interface(
857 recirc.recirc.sw_if_index,
861 recirc.add_vpp_config()
863 for recirc in recircs:
864 self.assertTrue(find_bridge_domain_port(self,
865 recirc.epg.bd.bd.bd_id,
866 recirc.recirc.sw_if_index))
869 self.pg_enable_capture(self.pg_interfaces)
872 # routes to the endpoints. We need these since there are no
873 # adj-fibs due to the fact the the BVI address has /32 and
874 # the subnet is not attached.
876 for (ip, fip) in zip(ep.ips, ep.fips):
877 # Add static mappings for each EP from the 10/8 to 11/8 network
879 self.vapi.nat44_add_del_static_mapping(ip.bytes,
884 self.vapi.nat66_add_del_static_mapping(ip.bytes,
891 self.logger.info(self.vapi.cli("sh gbp endpoint"))
893 # ... results in a Gratuitous ARP/ND on the EPG's uplink
894 rx = ep.epg.uplink.get_capture(len(ep.ips), timeout=0.2)
896 for ii, ip in enumerate(ep.ips):
900 self.assertTrue(p.haslayer(ICMPv6ND_NA))
901 self.assertEqual(p[ICMPv6ND_NA].tgt, ip.address)
903 self.assertTrue(p.haslayer(ARP))
904 self.assertEqual(p[ARP].psrc, ip.address)
905 self.assertEqual(p[ARP].pdst, ip.address)
907 # add the BD ARP termination entry for floating IP
909 ba = VppBridgeDomainArpEntry(self, epg_nat.bd.bd, ep.mac, fip)
912 # floating IPs route via EPG recirc
913 r = VppIpRoute(self, fip.address, fip.length,
914 [VppRoutePath(fip.address,
915 ep.recirc.recirc.sw_if_index,
917 proto=fip.dpo_proto)],
922 # L2 FIB entries in the NAT EPG BD to bridge the packets from
923 # the outside direct to the internal EPG
924 lf = VppL2FibEntry(self, epg_nat.bd.bd, ep.mac,
925 ep.recirc.recirc, bvi_mac=0)
929 # ARP packets for unknown IP are sent to the EPG uplink
931 pkt_arp = (Ether(dst="ff:ff:ff:ff:ff:ff",
932 src=self.pg0.remote_mac) /
934 hwdst="ff:ff:ff:ff:ff:ff",
935 hwsrc=self.pg0.remote_mac,
939 self.vapi.cli("clear trace")
940 self.pg0.add_stream(pkt_arp)
942 self.pg_enable_capture(self.pg_interfaces)
945 rxd = epgs[0].uplink.get_capture(1)
948 # ARP/ND packets get a response
950 pkt_arp = (Ether(dst="ff:ff:ff:ff:ff:ff",
951 src=self.pg0.remote_mac) /
953 hwdst="ff:ff:ff:ff:ff:ff",
954 hwsrc=self.pg0.remote_mac,
955 pdst=epgs[0].bvi_ip4.address,
956 psrc=eps[0].ip4.address))
958 self.send_and_expect(self.pg0, [pkt_arp], self.pg0)
960 nsma = in6_getnsma(inet_pton(AF_INET6, eps[0].ip6.address))
961 d = inet_ntop(AF_INET6, nsma)
962 pkt_nd = (Ether(dst=in6_getnsmac(nsma),
963 src=self.pg0.remote_mac) /
964 IPv6(dst=d, src=eps[0].ip6.address) /
965 ICMPv6ND_NS(tgt=epgs[0].bvi_ip6.address) /
966 ICMPv6NDOptSrcLLAddr(lladdr=self.pg0.remote_mac))
967 self.send_and_expect(self.pg0, [pkt_nd], self.pg0)
970 # broadcast packets are flooded
972 pkt_bcast = (Ether(dst="ff:ff:ff:ff:ff:ff",
973 src=self.pg0.remote_mac) /
974 IP(src=eps[0].ip4.address, dst="232.1.1.1") /
975 UDP(sport=1234, dport=1234) /
978 self.vapi.cli("clear trace")
979 self.pg0.add_stream(pkt_bcast)
981 self.pg_enable_capture(self.pg_interfaces)
984 rxd = eps[1].itf.get_capture(1)
985 self.assertEqual(rxd[0][Ether].dst, pkt_bcast[Ether].dst)
986 rxd = epgs[0].uplink.get_capture(1)
987 self.assertEqual(rxd[0][Ether].dst, pkt_bcast[Ether].dst)
990 # packets to non-local L3 destinations dropped
992 pkt_intra_epg_220_ip4 = (Ether(src=self.pg0.remote_mac,
993 dst=str(self.router_mac)) /
994 IP(src=eps[0].ip4.address,
996 UDP(sport=1234, dport=1234) /
998 pkt_inter_epg_222_ip4 = (Ether(src=self.pg0.remote_mac,
999 dst=str(self.router_mac)) /
1000 IP(src=eps[0].ip4.address,
1002 UDP(sport=1234, dport=1234) /
1005 self.send_and_assert_no_replies(self.pg0, pkt_intra_epg_220_ip4 * 65)
1007 pkt_inter_epg_222_ip6 = (Ether(src=self.pg0.remote_mac,
1008 dst=str(self.router_mac)) /
1009 IPv6(src=eps[0].ip6.address,
1010 dst="2001:10::99") /
1011 UDP(sport=1234, dport=1234) /
1013 self.send_and_assert_no_replies(self.pg0, pkt_inter_epg_222_ip6 * 65)
1016 # Add the subnet routes
1019 self, rd0, "10.0.0.0", 24,
1020 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1022 self, rd0, "10.0.1.0", 24,
1023 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1025 self, rd0, "10.0.2.0", 24,
1026 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1028 self, rd0, "2001:10::1", 64,
1029 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1031 self, rd0, "2001:10:1::1", 64,
1032 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1034 self, rd0, "2001:10:2::1", 64,
1035 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1036 s41.add_vpp_config()
1037 s42.add_vpp_config()
1038 s43.add_vpp_config()
1039 s61.add_vpp_config()
1040 s62.add_vpp_config()
1041 s63.add_vpp_config()
1043 self.send_and_expect_bridged(eps[0].itf,
1044 pkt_intra_epg_220_ip4 * 65,
1046 self.send_and_expect_bridged(eps[0].itf,
1047 pkt_inter_epg_222_ip4 * 65,
1049 self.send_and_expect_bridged6(eps[0].itf,
1050 pkt_inter_epg_222_ip6 * 65,
1053 self.logger.info(self.vapi.cli("sh ip fib 11.0.0.2"))
1054 self.logger.info(self.vapi.cli("sh gbp endpoint-group"))
1055 self.logger.info(self.vapi.cli("sh gbp endpoint"))
1056 self.logger.info(self.vapi.cli("sh gbp recirc"))
1057 self.logger.info(self.vapi.cli("sh int"))
1058 self.logger.info(self.vapi.cli("sh int addr"))
1059 self.logger.info(self.vapi.cli("sh int feat loop6"))
1060 self.logger.info(self.vapi.cli("sh vlib graph ip4-gbp-src-classify"))
1061 self.logger.info(self.vapi.cli("sh int feat loop3"))
1062 self.logger.info(self.vapi.cli("sh int feat pg0"))
1065 # Packet destined to unknown unicast is sent on the epg uplink ...
1067 pkt_intra_epg_220_to_uplink = (Ether(src=self.pg0.remote_mac,
1068 dst="00:00:00:33:44:55") /
1069 IP(src=eps[0].ip4.address,
1071 UDP(sport=1234, dport=1234) /
1074 self.send_and_expect_bridged(eps[0].itf,
1075 pkt_intra_epg_220_to_uplink * 65,
1077 # ... and nowhere else
1078 self.pg1.get_capture(0, timeout=0.1)
1079 self.pg1.assert_nothing_captured(remark="Flood onto other VMS")
1081 pkt_intra_epg_221_to_uplink = (Ether(src=self.pg2.remote_mac,
1082 dst="00:00:00:33:44:66") /
1083 IP(src=eps[0].ip4.address,
1085 UDP(sport=1234, dport=1234) /
1088 self.send_and_expect_bridged(eps[2].itf,
1089 pkt_intra_epg_221_to_uplink * 65,
1093 # Packets from the uplink are forwarded in the absence of a contract
1095 pkt_intra_epg_220_from_uplink = (Ether(src="00:00:00:33:44:55",
1096 dst=self.pg0.remote_mac) /
1097 IP(src=eps[0].ip4.address,
1099 UDP(sport=1234, dport=1234) /
1102 self.send_and_expect_bridged(self.pg4,
1103 pkt_intra_epg_220_from_uplink * 65,
1107 # in the absence of policy, endpoints in the same EPG
1110 pkt_intra_epg = (Ether(src=self.pg0.remote_mac,
1111 dst=self.pg1.remote_mac) /
1112 IP(src=eps[0].ip4.address,
1113 dst=eps[1].ip4.address) /
1114 UDP(sport=1234, dport=1234) /
1117 self.send_and_expect_bridged(self.pg0, pkt_intra_epg * 65, self.pg1)
1120 # in the abscense of policy, endpoints in the different EPG
1121 # cannot communicate
1123 pkt_inter_epg_220_to_221 = (Ether(src=self.pg0.remote_mac,
1124 dst=self.pg2.remote_mac) /
1125 IP(src=eps[0].ip4.address,
1126 dst=eps[2].ip4.address) /
1127 UDP(sport=1234, dport=1234) /
1129 pkt_inter_epg_221_to_220 = (Ether(src=self.pg2.remote_mac,
1130 dst=self.pg0.remote_mac) /
1131 IP(src=eps[2].ip4.address,
1132 dst=eps[0].ip4.address) /
1133 UDP(sport=1234, dport=1234) /
1135 pkt_inter_epg_220_to_222 = (Ether(src=self.pg0.remote_mac,
1136 dst=str(self.router_mac)) /
1137 IP(src=eps[0].ip4.address,
1138 dst=eps[3].ip4.address) /
1139 UDP(sport=1234, dport=1234) /
1142 self.send_and_assert_no_replies(eps[0].itf,
1143 pkt_inter_epg_220_to_221 * 65)
1144 self.send_and_assert_no_replies(eps[0].itf,
1145 pkt_inter_epg_220_to_222 * 65)
1148 # A uni-directional contract from EPG 220 -> 221
1150 acl = VppGbpAcl(self)
1151 rule = acl.create_rule(permit_deny=1, proto=17)
1152 rule2 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
1153 acl_index = acl.add_vpp_config([rule, rule2])
1154 c1 = VppGbpContract(
1155 self, 220, 221, acl_index,
1156 [VppGbpContractRule(
1157 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1160 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1162 [ETH_P_IP, ETH_P_IPV6])
1165 self.send_and_expect_bridged(eps[0].itf,
1166 pkt_inter_epg_220_to_221 * 65,
1168 self.send_and_assert_no_replies(eps[0].itf,
1169 pkt_inter_epg_220_to_222 * 65)
1172 # contract for the return direction
1174 c2 = VppGbpContract(
1175 self, 221, 220, acl_index,
1176 [VppGbpContractRule(
1177 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1180 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1182 [ETH_P_IP, ETH_P_IPV6])
1185 self.send_and_expect_bridged(eps[0].itf,
1186 pkt_inter_epg_220_to_221 * 65,
1188 self.send_and_expect_bridged(eps[2].itf,
1189 pkt_inter_epg_221_to_220 * 65,
1193 # the contract does not allow non-IP
1195 pkt_non_ip_inter_epg_220_to_221 = (Ether(src=self.pg0.remote_mac,
1196 dst=self.pg2.remote_mac) /
1198 self.send_and_assert_no_replies(eps[0].itf,
1199 pkt_non_ip_inter_epg_220_to_221 * 17)
1202 # check that inter group is still disabled for the groups
1203 # not in the contract.
1205 self.send_and_assert_no_replies(eps[0].itf,
1206 pkt_inter_epg_220_to_222 * 65)
1209 # A uni-directional contract from EPG 220 -> 222 'L3 routed'
1211 c3 = VppGbpContract(
1212 self, 220, 222, acl_index,
1213 [VppGbpContractRule(
1214 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1217 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1219 [ETH_P_IP, ETH_P_IPV6])
1222 self.logger.info(self.vapi.cli("sh gbp contract"))
1224 self.send_and_expect_routed(eps[0].itf,
1225 pkt_inter_epg_220_to_222 * 65,
1227 str(self.router_mac))
1230 # remove both contracts, traffic stops in both directions
1232 c2.remove_vpp_config()
1233 c1.remove_vpp_config()
1234 c3.remove_vpp_config()
1235 acl.remove_vpp_config()
1237 self.send_and_assert_no_replies(eps[2].itf,
1238 pkt_inter_epg_221_to_220 * 65)
1239 self.send_and_assert_no_replies(eps[0].itf,
1240 pkt_inter_epg_220_to_221 * 65)
1241 self.send_and_expect_bridged(eps[0].itf,
1246 # EPs to the outside world
1249 # in the EP's RD an external subnet via the NAT EPG's recirc
1251 self, rd0, "0.0.0.0", 0,
1252 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1253 sw_if_index=recirc_nat.recirc.sw_if_index,
1256 self, rd0, "11.0.0.0", 8,
1257 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1258 sw_if_index=recirc_nat.recirc.sw_if_index,
1260 se16 = VppGbpSubnet(
1262 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1263 sw_if_index=recirc_nat.recirc.sw_if_index,
1265 # in the NAT RD an external subnet via the NAT EPG's uplink
1267 self, rd20, "0.0.0.0", 0,
1268 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1269 sw_if_index=epg_nat.uplink.sw_if_index,
1271 se36 = VppGbpSubnet(
1272 self, rd20, "::", 0,
1273 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1274 sw_if_index=epg_nat.uplink.sw_if_index,
1277 self, rd20, "11.0.0.0", 8,
1278 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1279 sw_if_index=epg_nat.uplink.sw_if_index,
1281 se1.add_vpp_config()
1282 se2.add_vpp_config()
1283 se16.add_vpp_config()
1284 se3.add_vpp_config()
1285 se36.add_vpp_config()
1286 se4.add_vpp_config()
1288 self.logger.info(self.vapi.cli("sh ip fib 0.0.0.0/0"))
1289 self.logger.info(self.vapi.cli("sh ip fib 11.0.0.1"))
1290 self.logger.info(self.vapi.cli("sh ip6 fib ::/0"))
1291 self.logger.info(self.vapi.cli("sh ip6 fib %s" %
1295 # From an EP to an outside addess: IN2OUT
1297 pkt_inter_epg_220_to_global = (Ether(src=self.pg0.remote_mac,
1298 dst=str(self.router_mac)) /
1299 IP(src=eps[0].ip4.address,
1301 UDP(sport=1234, dport=1234) /
1305 self.send_and_assert_no_replies(eps[0].itf,
1306 pkt_inter_epg_220_to_global * 65)
1308 acl2 = VppGbpAcl(self)
1309 rule = acl2.create_rule(permit_deny=1, proto=17, sport_from=1234,
1310 sport_to=1234, dport_from=1234, dport_to=1234)
1311 rule2 = acl2.create_rule(is_ipv6=1, permit_deny=1, proto=17,
1312 sport_from=1234, sport_to=1234,
1313 dport_from=1234, dport_to=1234)
1315 acl_index2 = acl2.add_vpp_config([rule, rule2])
1316 c4 = VppGbpContract(
1317 self, 220, 333, acl_index2,
1318 [VppGbpContractRule(
1319 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1322 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1324 [ETH_P_IP, ETH_P_IPV6])
1327 self.send_and_expect_natted(eps[0].itf,
1328 pkt_inter_epg_220_to_global * 65,
1330 eps[0].fip4.address)
1332 pkt_inter_epg_220_to_global = (Ether(src=self.pg0.remote_mac,
1333 dst=str(self.router_mac)) /
1334 IPv6(src=eps[0].ip6.address,
1336 UDP(sport=1234, dport=1234) /
1339 self.send_and_expect_natted6(self.pg0,
1340 pkt_inter_epg_220_to_global * 65,
1342 eps[0].fip6.address)
1345 # From a global address to an EP: OUT2IN
1347 pkt_inter_epg_220_from_global = (Ether(src=str(self.router_mac),
1348 dst=self.pg0.remote_mac) /
1349 IP(dst=eps[0].fip4.address,
1351 UDP(sport=1234, dport=1234) /
1354 self.send_and_assert_no_replies(self.pg7,
1355 pkt_inter_epg_220_from_global * 65)
1357 c5 = VppGbpContract(
1358 self, 333, 220, acl_index2,
1359 [VppGbpContractRule(
1360 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1363 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1365 [ETH_P_IP, ETH_P_IPV6])
1368 self.send_and_expect_unnatted(self.pg7,
1369 pkt_inter_epg_220_from_global * 65,
1373 pkt_inter_epg_220_from_global = (Ether(src=str(self.router_mac),
1374 dst=self.pg0.remote_mac) /
1375 IPv6(dst=eps[0].fip6.address,
1377 UDP(sport=1234, dport=1234) /
1380 self.send_and_expect_unnatted6(self.pg7,
1381 pkt_inter_epg_220_from_global * 65,
1386 # From a local VM to another local VM using resp. public addresses:
1389 pkt_intra_epg_220_global = (Ether(src=self.pg0.remote_mac,
1390 dst=str(self.router_mac)) /
1391 IP(src=eps[0].ip4.address,
1392 dst=eps[1].fip4.address) /
1393 UDP(sport=1234, dport=1234) /
1396 self.send_and_expect_double_natted(eps[0].itf,
1397 pkt_intra_epg_220_global * 65,
1399 eps[0].fip4.address,
1402 pkt_intra_epg_220_global = (Ether(src=self.pg0.remote_mac,
1403 dst=str(self.router_mac)) /
1404 IPv6(src=eps[0].ip6.address,
1405 dst=eps[1].fip6.address) /
1406 UDP(sport=1234, dport=1234) /
1409 self.send_and_expect_double_natted6(eps[0].itf,
1410 pkt_intra_epg_220_global * 65,
1412 eps[0].fip6.address,
1419 # del static mappings for each EP from the 10/8 to 11/8 network
1420 self.vapi.nat44_add_del_static_mapping(ep.ip4.bytes,
1425 self.vapi.nat66_add_del_static_mapping(ep.ip6.bytes,
1431 # IP config on the BVI interfaces
1432 if epg != epgs[0] and epg != epgs[3]:
1433 self.vapi.nat44_interface_add_del_feature(epg.bvi.sw_if_index,
1436 self.vapi.nat66_add_del_interface(epg.bvi.sw_if_index,
1440 for recirc in recircs:
1441 self.vapi.nat44_interface_add_del_feature(
1442 recirc.recirc.sw_if_index,
1445 self.vapi.nat66_add_del_interface(
1446 recirc.recirc.sw_if_index,
1450 def wait_for_ep_timeout(self, sw_if_index=None, ip=None, mac=None,
1451 n_tries=100, s_time=1):
1453 if not find_gbp_endpoint(self, sw_if_index, ip, mac):
1455 n_tries = n_tries - 1
1457 self.assertFalse(find_gbp_endpoint(self, sw_if_index, ip, mac))
1460 def test_gbp_learn_l2(self):
1461 """ GBP L2 Endpoint Learning """
1463 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
1464 learnt = [{'mac': '00:00:11:11:11:01',
1466 'ip6': '2001:10::2'},
1467 {'mac': '00:00:11:11:11:02',
1469 'ip6': '2001:10::3'}]
1474 gt4 = VppIpTable(self, 1)
1475 gt4.add_vpp_config()
1476 gt6 = VppIpTable(self, 1, is_ip6=True)
1477 gt6.add_vpp_config()
1479 rd1 = VppGbpRouteDomain(self, 1, gt4, gt6)
1480 rd1.add_vpp_config()
1483 # Pg2 hosts the vxlan tunnel, hosts on pg2 to act as TEPs
1484 # Pg3 hosts the IP4 UU-flood VXLAN tunnel
1485 # Pg4 hosts the IP6 UU-flood VXLAN tunnel
1487 self.pg2.config_ip4()
1488 self.pg2.resolve_arp()
1489 self.pg2.generate_remote_hosts(4)
1490 self.pg2.configure_ipv4_neighbors()
1491 self.pg3.config_ip4()
1492 self.pg3.resolve_arp()
1493 self.pg4.config_ip4()
1494 self.pg4.resolve_arp()
1497 # Add a mcast destination VXLAN-GBP tunnel for B&M traffic
1499 tun_bm = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
1502 tun_bm.add_vpp_config()
1505 # a GBP bridge domain with a BVI and a UU-flood interface
1507 bd1 = VppBridgeDomain(self, 1)
1508 bd1.add_vpp_config()
1509 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0, self.pg3, tun_bm)
1510 gbd1.add_vpp_config()
1512 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1513 self.logger.info(self.vapi.cli("sh gbp bridge"))
1515 # ... and has a /32 applied
1516 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
1517 ip_addr.add_vpp_config()
1520 # The Endpoint-group in which we are learning endpoints
1522 epg_220 = VppGbpEndpointGroup(self, 220, 112, rd1, gbd1,
1526 VppGbpEndpointRetention(2))
1527 epg_220.add_vpp_config()
1528 epg_330 = VppGbpEndpointGroup(self, 330, 113, rd1, gbd1,
1532 VppGbpEndpointRetention(2))
1533 epg_330.add_vpp_config()
1536 # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
1539 vx_tun_l2_1 = VppGbpVxlanTunnel(
1540 self, 99, bd1.bd_id,
1541 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L2)
1542 vx_tun_l2_1.add_vpp_config()
1545 # A static endpoint that the learnt endpoints are trying to
1548 ep = VppGbpEndpoint(self, self.pg0,
1550 "10.0.0.127", "11.0.0.127",
1551 "2001:10::1", "3001::1")
1554 self.assertTrue(find_route(self, ep.ip4.address, 32, table_id=1))
1556 # a packet with an sclass from an unknwon EPG
1557 p = (Ether(src=self.pg2.remote_mac,
1558 dst=self.pg2.local_mac) /
1559 IP(src=self.pg2.remote_hosts[0].ip4,
1560 dst=self.pg2.local_ip4) /
1561 UDP(sport=1234, dport=48879) /
1562 VXLAN(vni=99, gpid=88, flags=0x88) /
1563 Ether(src=learnt[0]["mac"], dst=ep.mac) /
1564 IP(src=learnt[0]["ip"], dst=ep.ip4.address) /
1565 UDP(sport=1234, dport=1234) /
1568 self.send_and_assert_no_replies(self.pg2, p)
1571 # we should not have learnt a new tunnel endpoint, since
1572 # the EPG was not learnt.
1574 self.assertEqual(INDEX_INVALID,
1575 find_vxlan_gbp_tunnel(self,
1577 self.pg2.remote_hosts[0].ip4,
1580 # epg is not learnt, becasue the EPG is unknwon
1581 self.assertEqual(len(self.vapi.gbp_endpoint_dump()), 1)
1583 for ii, l in enumerate(learnt):
1584 # a packet with an sclass from a knwon EPG
1585 # arriving on an unknown TEP
1586 p = (Ether(src=self.pg2.remote_mac,
1587 dst=self.pg2.local_mac) /
1588 IP(src=self.pg2.remote_hosts[1].ip4,
1589 dst=self.pg2.local_ip4) /
1590 UDP(sport=1234, dport=48879) /
1591 VXLAN(vni=99, gpid=112, flags=0x88) /
1592 Ether(src=l['mac'], dst=ep.mac) /
1593 IP(src=l['ip'], dst=ep.ip4.address) /
1594 UDP(sport=1234, dport=1234) /
1597 rx = self.send_and_expect(self.pg2, [p], self.pg0)
1600 tep1_sw_if_index = find_vxlan_gbp_tunnel(
1603 self.pg2.remote_hosts[1].ip4,
1605 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
1608 # the EP is learnt via the learnt TEP
1609 # both from its MAC and its IP
1611 self.assertTrue(find_gbp_endpoint(self,
1612 vx_tun_l2_1.sw_if_index,
1614 self.assertTrue(find_gbp_endpoint(self,
1615 vx_tun_l2_1.sw_if_index,
1618 self.logger.info(self.vapi.cli("show gbp endpoint"))
1619 self.logger.info(self.vapi.cli("show gbp vxlan"))
1620 self.logger.info(self.vapi.cli("show vxlan-gbp tunnel"))
1623 # If we sleep for the threshold time, the learnt endpoints should
1627 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1631 # repeat. the do not learn bit is set so the EPs are not learnt
1634 # a packet with an sclass from a knwon EPG
1635 p = (Ether(src=self.pg2.remote_mac,
1636 dst=self.pg2.local_mac) /
1637 IP(src=self.pg2.remote_hosts[1].ip4,
1638 dst=self.pg2.local_ip4) /
1639 UDP(sport=1234, dport=48879) /
1640 VXLAN(vni=99, gpid=112, flags=0x88, gpflags="D") /
1641 Ether(src=l['mac'], dst=ep.mac) /
1642 IP(src=l['ip'], dst=ep.ip4.address) /
1643 UDP(sport=1234, dport=1234) /
1646 rx = self.send_and_expect(self.pg2, p*65, self.pg0)
1649 self.assertFalse(find_gbp_endpoint(self,
1650 vx_tun_l2_1.sw_if_index,
1657 # a packet with an sclass from a knwon EPG
1658 p = (Ether(src=self.pg2.remote_mac,
1659 dst=self.pg2.local_mac) /
1660 IP(src=self.pg2.remote_hosts[1].ip4,
1661 dst=self.pg2.local_ip4) /
1662 UDP(sport=1234, dport=48879) /
1663 VXLAN(vni=99, gpid=112, flags=0x88) /
1664 Ether(src=l['mac'], dst=ep.mac) /
1665 IP(src=l['ip'], dst=ep.ip4.address) /
1666 UDP(sport=1234, dport=1234) /
1669 rx = self.send_and_expect(self.pg2, p*65, self.pg0)
1671 self.assertTrue(find_gbp_endpoint(self,
1672 vx_tun_l2_1.sw_if_index,
1676 # Static EP replies to dynamics
1678 self.logger.info(self.vapi.cli("sh l2fib bd_id 1"))
1680 p = (Ether(src=ep.mac, dst=l['mac']) /
1681 IP(dst=l['ip'], src=ep.ip4.address) /
1682 UDP(sport=1234, dport=1234) /
1685 rxs = self.send_and_expect(self.pg0, p * 17, self.pg2)
1688 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
1689 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
1690 self.assertEqual(rx[UDP].dport, 48879)
1691 # the UDP source port is a random value for hashing
1692 self.assertEqual(rx[VXLAN].gpid, 112)
1693 self.assertEqual(rx[VXLAN].vni, 99)
1694 self.assertTrue(rx[VXLAN].flags.G)
1695 self.assertTrue(rx[VXLAN].flags.Instance)
1696 self.assertTrue(rx[VXLAN].gpflags.A)
1697 self.assertFalse(rx[VXLAN].gpflags.D)
1700 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1704 # repeat in the other EPG
1705 # there's no contract between 220 and 330, but the A-bit is set
1706 # so the packet is cleared for delivery
1709 # a packet with an sclass from a knwon EPG
1710 p = (Ether(src=self.pg2.remote_mac,
1711 dst=self.pg2.local_mac) /
1712 IP(src=self.pg2.remote_hosts[1].ip4,
1713 dst=self.pg2.local_ip4) /
1714 UDP(sport=1234, dport=48879) /
1715 VXLAN(vni=99, gpid=113, flags=0x88, gpflags='A') /
1716 Ether(src=l['mac'], dst=ep.mac) /
1717 IP(src=l['ip'], dst=ep.ip4.address) /
1718 UDP(sport=1234, dport=1234) /
1721 rx = self.send_and_expect(self.pg2, p*65, self.pg0)
1723 self.assertTrue(find_gbp_endpoint(self,
1724 vx_tun_l2_1.sw_if_index,
1728 # static EP cannot reach the learnt EPs since there is no contract
1729 # only test 1 EP as the others could timeout
1731 p = (Ether(src=ep.mac, dst=l['mac']) /
1732 IP(dst=learnt[0]['ip'], src=ep.ip4.address) /
1733 UDP(sport=1234, dport=1234) /
1736 self.send_and_assert_no_replies(self.pg0, [p])
1739 # refresh the entries after the check for no replies above
1742 # a packet with an sclass from a knwon EPG
1743 p = (Ether(src=self.pg2.remote_mac,
1744 dst=self.pg2.local_mac) /
1745 IP(src=self.pg2.remote_hosts[1].ip4,
1746 dst=self.pg2.local_ip4) /
1747 UDP(sport=1234, dport=48879) /
1748 VXLAN(vni=99, gpid=113, flags=0x88, gpflags='A') /
1749 Ether(src=l['mac'], dst=ep.mac) /
1750 IP(src=l['ip'], dst=ep.ip4.address) /
1751 UDP(sport=1234, dport=1234) /
1754 rx = self.send_and_expect(self.pg2, p*65, self.pg0)
1756 self.assertTrue(find_gbp_endpoint(self,
1757 vx_tun_l2_1.sw_if_index,
1761 # Add the contract so they can talk
1763 acl = VppGbpAcl(self)
1764 rule = acl.create_rule(permit_deny=1, proto=17)
1765 rule2 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
1766 acl_index = acl.add_vpp_config([rule, rule2])
1767 c1 = VppGbpContract(
1768 self, 220, 330, acl_index,
1769 [VppGbpContractRule(
1770 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1773 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1775 [ETH_P_IP, ETH_P_IPV6])
1779 p = (Ether(src=ep.mac, dst=l['mac']) /
1780 IP(dst=l['ip'], src=ep.ip4.address) /
1781 UDP(sport=1234, dport=1234) /
1784 self.send_and_expect(self.pg0, [p], self.pg2)
1787 # send UU packets from the local EP
1789 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1790 self.logger.info(self.vapi.cli("sh gbp bridge"))
1791 p_uu = (Ether(src=ep.mac, dst="00:11:11:11:11:11") /
1792 IP(dst="10.0.0.133", src=ep.ip4.address) /
1793 UDP(sport=1234, dport=1234) /
1795 rxs = self.send_and_expect(ep.itf, [p_uu], gbd1.uu_fwd)
1797 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1799 p_bm = (Ether(src=ep.mac, dst="ff:ff:ff:ff:ff:ff") /
1800 IP(dst="10.0.0.133", src=ep.ip4.address) /
1801 UDP(sport=1234, dport=1234) /
1803 rxs = self.send_and_expect_only(ep.itf, [p_bm], tun_bm.mcast_itf)
1806 self.assertEqual(rx[IP].src, self.pg4.local_ip4)
1807 self.assertEqual(rx[IP].dst, "239.1.1.1")
1808 self.assertEqual(rx[UDP].dport, 48879)
1809 # the UDP source port is a random value for hashing
1810 self.assertEqual(rx[VXLAN].gpid, 112)
1811 self.assertEqual(rx[VXLAN].vni, 88)
1812 self.assertTrue(rx[VXLAN].flags.G)
1813 self.assertTrue(rx[VXLAN].flags.Instance)
1814 self.assertFalse(rx[VXLAN].gpflags.A)
1815 self.assertFalse(rx[VXLAN].gpflags.D)
1818 # Check v6 Endpoints
1821 # a packet with an sclass from a knwon EPG
1822 p = (Ether(src=self.pg2.remote_mac,
1823 dst=self.pg2.local_mac) /
1824 IP(src=self.pg2.remote_hosts[1].ip4,
1825 dst=self.pg2.local_ip4) /
1826 UDP(sport=1234, dport=48879) /
1827 VXLAN(vni=99, gpid=113, flags=0x88, gpflags='A') /
1828 Ether(src=l['mac'], dst=ep.mac) /
1829 IPv6(src=l['ip6'], dst=ep.ip6.address) /
1830 UDP(sport=1234, dport=1234) /
1833 rx = self.send_and_expect(self.pg2, p*65, self.pg0)
1835 self.assertTrue(find_gbp_endpoint(self,
1836 vx_tun_l2_1.sw_if_index,
1840 # L3 Endpoint Learning
1841 # - configured on the bridge's BVI
1848 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1851 self.pg2.unconfig_ip4()
1852 self.pg3.unconfig_ip4()
1853 self.pg4.unconfig_ip4()
1855 self.logger.info(self.vapi.cli("sh int"))
1856 self.logger.info(self.vapi.cli("sh gbp vxlan"))
1858 def test_gbp_learn_vlan_l2(self):
1859 """ GBP L2 Endpoint w/ VLANs"""
1861 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
1862 learnt = [{'mac': '00:00:11:11:11:01',
1864 'ip6': '2001:10::2'},
1865 {'mac': '00:00:11:11:11:02',
1867 'ip6': '2001:10::3'}]
1872 gt4 = VppIpTable(self, 1)
1873 gt4.add_vpp_config()
1874 gt6 = VppIpTable(self, 1, is_ip6=True)
1875 gt6.add_vpp_config()
1877 rd1 = VppGbpRouteDomain(self, 1, gt4, gt6)
1878 rd1.add_vpp_config()
1881 # Pg2 hosts the vxlan tunnel, hosts on pg2 to act as TEPs
1883 self.pg2.config_ip4()
1884 self.pg2.resolve_arp()
1885 self.pg2.generate_remote_hosts(4)
1886 self.pg2.configure_ipv4_neighbors()
1887 self.pg3.config_ip4()
1888 self.pg3.resolve_arp()
1891 # The EP will be on a vlan sub-interface
1893 vlan_11 = VppDot1QSubint(self, self.pg0, 11)
1895 self.vapi.l2_interface_vlan_tag_rewrite(vlan_11.sw_if_index,
1899 bd_uu_fwd = VppVxlanGbpTunnel(self, self.pg3.local_ip4,
1900 self.pg3.remote_ip4, 116)
1901 bd_uu_fwd.add_vpp_config()
1904 # a GBP bridge domain with a BVI and a UU-flood interface
1905 # The BD is marked as do not learn, so no endpoints are ever
1906 # learnt in this BD.
1908 bd1 = VppBridgeDomain(self, 1)
1909 bd1.add_vpp_config()
1910 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0, bd_uu_fwd,
1912 gbd1.add_vpp_config()
1914 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1915 self.logger.info(self.vapi.cli("sh gbp bridge"))
1917 # ... and has a /32 applied
1918 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
1919 ip_addr.add_vpp_config()
1922 # The Endpoint-group in which we are learning endpoints
1924 epg_220 = VppGbpEndpointGroup(self, 220, 441, rd1, gbd1,
1928 VppGbpEndpointRetention(2))
1929 epg_220.add_vpp_config()
1932 # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
1935 vx_tun_l2_1 = VppGbpVxlanTunnel(
1936 self, 99, bd1.bd_id,
1937 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L2)
1938 vx_tun_l2_1.add_vpp_config()
1941 # A static endpoint that the learnt endpoints are trying to
1944 ep = VppGbpEndpoint(self, vlan_11,
1946 "10.0.0.127", "11.0.0.127",
1947 "2001:10::1", "3001::1")
1950 self.assertTrue(find_route(self, ep.ip4.address, 32, table_id=1))
1953 # Send to the static EP
1955 for ii, l in enumerate(learnt):
1956 # a packet with an sclass from a knwon EPG
1957 # arriving on an unknown TEP
1958 p = (Ether(src=self.pg2.remote_mac,
1959 dst=self.pg2.local_mac) /
1960 IP(src=self.pg2.remote_hosts[1].ip4,
1961 dst=self.pg2.local_ip4) /
1962 UDP(sport=1234, dport=48879) /
1963 VXLAN(vni=99, gpid=441, flags=0x88) /
1964 Ether(src=l['mac'], dst=ep.mac) /
1965 IP(src=l['ip'], dst=ep.ip4.address) /
1966 UDP(sport=1234, dport=1234) /
1969 rxs = self.send_and_expect(self.pg2, [p], self.pg0)
1972 # packet to EP has the EP's vlan tag
1975 self.assertEqual(rx[Dot1Q].vlan, 11)
1978 # the EP is not learnt since the BD setting prevents it
1981 self.assertFalse(find_gbp_endpoint(self,
1982 vx_tun_l2_1.sw_if_index,
1984 self.assertEqual(INDEX_INVALID,
1985 find_vxlan_gbp_tunnel(
1988 self.pg2.remote_hosts[1].ip4,
1991 self.assertEqual(len(self.vapi.gbp_endpoint_dump()), 1)
1995 # we didn't learn the remotes so they are sent to the UU-fwd
1998 p = (Ether(src=ep.mac, dst=l['mac']) /
2000 IP(dst=l['ip'], src=ep.ip4.address) /
2001 UDP(sport=1234, dport=1234) /
2004 rxs = self.send_and_expect(self.pg0, p * 17, self.pg3)
2007 self.assertEqual(rx[IP].src, self.pg3.local_ip4)
2008 self.assertEqual(rx[IP].dst, self.pg3.remote_ip4)
2009 self.assertEqual(rx[UDP].dport, 48879)
2010 # the UDP source port is a random value for hashing
2011 self.assertEqual(rx[VXLAN].gpid, 441)
2012 self.assertEqual(rx[VXLAN].vni, 116)
2013 self.assertTrue(rx[VXLAN].flags.G)
2014 self.assertTrue(rx[VXLAN].flags.Instance)
2015 self.assertFalse(rx[VXLAN].gpflags.A)
2016 self.assertFalse(rx[VXLAN].gpflags.D)
2018 self.pg2.unconfig_ip4()
2019 self.pg3.unconfig_ip4()
2021 def test_gbp_learn_l3(self):
2022 """ GBP L3 Endpoint Learning """
2024 self.vapi.cli("set logging class gbp debug")
2026 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
2027 routed_dst_mac = "00:0c:0c:0c:0c:0c"
2028 routed_src_mac = "00:22:bd:f8:19:ff"
2030 learnt = [{'mac': '00:00:11:11:11:02',
2032 'ip6': '2001:10::2'},
2033 {'mac': '00:00:11:11:11:03',
2035 'ip6': '2001:10::3'}]
2040 t4 = VppIpTable(self, 1)
2042 t6 = VppIpTable(self, 1, True)
2045 tun_ip4_uu = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
2046 self.pg4.remote_ip4, 114)
2047 tun_ip6_uu = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
2048 self.pg4.remote_ip4, 116)
2049 tun_ip4_uu.add_vpp_config()
2050 tun_ip6_uu.add_vpp_config()
2052 rd1 = VppGbpRouteDomain(self, 2, t4, t6, tun_ip4_uu, tun_ip6_uu)
2053 rd1.add_vpp_config()
2055 self.loop0.set_mac(self.router_mac)
2058 # Bind the BVI to the RD
2060 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
2061 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
2064 # Pg2 hosts the vxlan tunnel
2065 # hosts on pg2 to act as TEPs
2069 self.pg2.config_ip4()
2070 self.pg2.resolve_arp()
2071 self.pg2.generate_remote_hosts(4)
2072 self.pg2.configure_ipv4_neighbors()
2073 self.pg3.config_ip4()
2074 self.pg3.resolve_arp()
2075 self.pg4.config_ip4()
2076 self.pg4.resolve_arp()
2079 # a GBP bridge domain with a BVI and a UU-flood interface
2081 bd1 = VppBridgeDomain(self, 1)
2082 bd1.add_vpp_config()
2083 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0, self.pg3)
2084 gbd1.add_vpp_config()
2086 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2087 self.logger.info(self.vapi.cli("sh gbp bridge"))
2088 self.logger.info(self.vapi.cli("sh gbp route"))
2090 # ... and has a /32 and /128 applied
2091 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2092 ip4_addr.add_vpp_config()
2093 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 128)
2094 ip6_addr.add_vpp_config()
2097 # The Endpoint-group in which we are learning endpoints
2099 epg_220 = VppGbpEndpointGroup(self, 220, 441, rd1, gbd1,
2103 VppGbpEndpointRetention(2))
2104 epg_220.add_vpp_config()
2107 # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
2110 vx_tun_l3 = VppGbpVxlanTunnel(
2111 self, 101, rd1.rd_id,
2112 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3)
2113 vx_tun_l3.add_vpp_config()
2116 # A static endpoint that the learnt endpoints are trying to
2119 ep = VppGbpEndpoint(self, self.pg0,
2121 "10.0.0.127", "11.0.0.127",
2122 "2001:10::1", "3001::1")
2126 # learn some remote IPv4 EPs
2128 for ii, l in enumerate(learnt):
2129 # a packet with an sclass from a knwon EPG
2130 # arriving on an unknown TEP
2131 p = (Ether(src=self.pg2.remote_mac,
2132 dst=self.pg2.local_mac) /
2133 IP(src=self.pg2.remote_hosts[1].ip4,
2134 dst=self.pg2.local_ip4) /
2135 UDP(sport=1234, dport=48879) /
2136 VXLAN(vni=101, gpid=441, flags=0x88) /
2137 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2138 IP(src=l['ip'], dst=ep.ip4.address) /
2139 UDP(sport=1234, dport=1234) /
2142 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2145 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2148 self.pg2.remote_hosts[1].ip4,
2150 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2152 # endpoint learnt via the parent GBP-vxlan interface
2153 self.assertTrue(find_gbp_endpoint(self,
2154 vx_tun_l3._sw_if_index,
2158 # Static IPv4 EP replies to learnt
2161 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2162 IP(dst=l['ip'], src=ep.ip4.address) /
2163 UDP(sport=1234, dport=1234) /
2166 rxs = self.send_and_expect(self.pg0, p*1, self.pg2)
2169 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2170 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2171 self.assertEqual(rx[UDP].dport, 48879)
2172 # the UDP source port is a random value for hashing
2173 self.assertEqual(rx[VXLAN].gpid, 441)
2174 self.assertEqual(rx[VXLAN].vni, 101)
2175 self.assertTrue(rx[VXLAN].flags.G)
2176 self.assertTrue(rx[VXLAN].flags.Instance)
2177 self.assertTrue(rx[VXLAN].gpflags.A)
2178 self.assertFalse(rx[VXLAN].gpflags.D)
2180 inner = rx[VXLAN].payload
2182 self.assertEqual(inner[Ether].src, routed_src_mac)
2183 self.assertEqual(inner[Ether].dst, routed_dst_mac)
2184 self.assertEqual(inner[IP].src, ep.ip4.address)
2185 self.assertEqual(inner[IP].dst, l['ip'])
2188 self.assertFalse(find_gbp_endpoint(self,
2193 # learn some remote IPv6 EPs
2195 for ii, l in enumerate(learnt):
2196 # a packet with an sclass from a knwon EPG
2197 # arriving on an unknown TEP
2198 p = (Ether(src=self.pg2.remote_mac,
2199 dst=self.pg2.local_mac) /
2200 IP(src=self.pg2.remote_hosts[1].ip4,
2201 dst=self.pg2.local_ip4) /
2202 UDP(sport=1234, dport=48879) /
2203 VXLAN(vni=101, gpid=441, flags=0x88) /
2204 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2205 IPv6(src=l['ip6'], dst=ep.ip6.address) /
2206 UDP(sport=1234, dport=1234) /
2209 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2212 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2215 self.pg2.remote_hosts[1].ip4,
2217 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2219 self.logger.info(self.vapi.cli("show gbp bridge"))
2220 self.logger.info(self.vapi.cli("show vxlan-gbp tunnel"))
2221 self.logger.info(self.vapi.cli("show gbp vxlan"))
2222 self.logger.info(self.vapi.cli("show int addr"))
2224 # endpoint learnt via the TEP
2225 self.assertTrue(find_gbp_endpoint(self, ip=l['ip6']))
2227 self.logger.info(self.vapi.cli("show gbp endpoint"))
2228 self.logger.info(self.vapi.cli("show ip fib index 1 %s" % l['ip']))
2231 # Static EP replies to learnt
2234 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2235 IPv6(dst=l['ip6'], src=ep.ip6.address) /
2236 UDP(sport=1234, dport=1234) /
2239 rxs = self.send_and_expect(self.pg0, p*65, self.pg2)
2242 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2243 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2244 self.assertEqual(rx[UDP].dport, 48879)
2245 # the UDP source port is a random value for hashing
2246 self.assertEqual(rx[VXLAN].gpid, 441)
2247 self.assertEqual(rx[VXLAN].vni, 101)
2248 self.assertTrue(rx[VXLAN].flags.G)
2249 self.assertTrue(rx[VXLAN].flags.Instance)
2250 self.assertTrue(rx[VXLAN].gpflags.A)
2251 self.assertFalse(rx[VXLAN].gpflags.D)
2253 inner = rx[VXLAN].payload
2255 self.assertEqual(inner[Ether].src, routed_src_mac)
2256 self.assertEqual(inner[Ether].dst, routed_dst_mac)
2257 self.assertEqual(inner[IPv6].src, ep.ip6.address)
2258 self.assertEqual(inner[IPv6].dst, l['ip6'])
2260 self.logger.info(self.vapi.cli("sh gbp endpoint"))
2262 self.wait_for_ep_timeout(ip=l['ip'])
2265 # Static sends to unknown EP with no route
2267 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2268 IP(dst="10.0.0.99", src=ep.ip4.address) /
2269 UDP(sport=1234, dport=1234) /
2272 self.send_and_assert_no_replies(self.pg0, [p])
2275 # Add a route to static EP's v4 and v6 subnet
2276 # packets should be sent on the v4/v6 uu=fwd interface resp.
2278 se_10_24 = VppGbpSubnet(
2279 self, rd1, "10.0.0.0", 24,
2280 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT)
2281 se_10_24.add_vpp_config()
2283 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2284 IP(dst="10.0.0.99", src=ep.ip4.address) /
2285 UDP(sport=1234, dport=1234) /
2288 rxs = self.send_and_expect(self.pg0, [p], self.pg4)
2290 self.assertEqual(rx[IP].src, self.pg4.local_ip4)
2291 self.assertEqual(rx[IP].dst, self.pg4.remote_ip4)
2292 self.assertEqual(rx[UDP].dport, 48879)
2293 # the UDP source port is a random value for hashing
2294 self.assertEqual(rx[VXLAN].gpid, 441)
2295 self.assertEqual(rx[VXLAN].vni, 114)
2296 self.assertTrue(rx[VXLAN].flags.G)
2297 self.assertTrue(rx[VXLAN].flags.Instance)
2298 # policy is not applied to packets sent to the uu-fwd interfaces
2299 self.assertFalse(rx[VXLAN].gpflags.A)
2300 self.assertFalse(rx[VXLAN].gpflags.D)
2303 # learn some remote IPv4 EPs
2305 for ii, l in enumerate(learnt):
2306 # a packet with an sclass from a knwon EPG
2307 # arriving on an unknown TEP
2308 p = (Ether(src=self.pg2.remote_mac,
2309 dst=self.pg2.local_mac) /
2310 IP(src=self.pg2.remote_hosts[2].ip4,
2311 dst=self.pg2.local_ip4) /
2312 UDP(sport=1234, dport=48879) /
2313 VXLAN(vni=101, gpid=441, flags=0x88) /
2314 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2315 IP(src=l['ip'], dst=ep.ip4.address) /
2316 UDP(sport=1234, dport=1234) /
2319 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2322 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2325 self.pg2.remote_hosts[2].ip4,
2327 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2329 # endpoint learnt via the parent GBP-vxlan interface
2330 self.assertTrue(find_gbp_endpoint(self,
2331 vx_tun_l3._sw_if_index,
2335 # Add a remote endpoint from the API
2337 rep_88 = VppGbpEndpoint(self, vx_tun_l3,
2339 "10.0.0.88", "11.0.0.88",
2340 "2001:10::88", "3001::88",
2341 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
2343 self.pg2.remote_hosts[1].ip4,
2345 rep_88.add_vpp_config()
2348 # Add a remote endpoint from the API that matches an existing one
2350 rep_2 = VppGbpEndpoint(self, vx_tun_l3,
2352 learnt[0]['ip'], "11.0.0.101",
2353 learnt[0]['ip6'], "3001::101",
2354 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
2356 self.pg2.remote_hosts[1].ip4,
2358 rep_2.add_vpp_config()
2361 # Add a route to the leanred EP's v4 subnet
2362 # packets should be send on the v4/v6 uu=fwd interface resp.
2364 se_10_1_24 = VppGbpSubnet(
2365 self, rd1, "10.0.1.0", 24,
2366 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT)
2367 se_10_1_24.add_vpp_config()
2369 self.logger.info(self.vapi.cli("show gbp endpoint"))
2371 ips = ["10.0.0.88", learnt[0]['ip']]
2373 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2374 IP(dst=ip, src=ep.ip4.address) /
2375 UDP(sport=1234, dport=1234) /
2378 rxs = self.send_and_expect(self.pg0, p*65, self.pg2)
2381 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2382 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2383 self.assertEqual(rx[UDP].dport, 48879)
2384 # the UDP source port is a random value for hashing
2385 self.assertEqual(rx[VXLAN].gpid, 441)
2386 self.assertEqual(rx[VXLAN].vni, 101)
2387 self.assertTrue(rx[VXLAN].flags.G)
2388 self.assertTrue(rx[VXLAN].flags.Instance)
2389 self.assertTrue(rx[VXLAN].gpflags.A)
2390 self.assertFalse(rx[VXLAN].gpflags.D)
2392 inner = rx[VXLAN].payload
2394 self.assertEqual(inner[Ether].src, routed_src_mac)
2395 self.assertEqual(inner[Ether].dst, routed_dst_mac)
2396 self.assertEqual(inner[IP].src, ep.ip4.address)
2397 self.assertEqual(inner[IP].dst, ip)
2400 # remove the API remote EPs, only API sourced is gone, the DP
2401 # learnt one remains
2403 rep_88.remove_vpp_config()
2404 rep_2.remove_vpp_config()
2406 self.assertTrue(find_gbp_endpoint(self, ip=rep_2.ip4.address))
2408 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2409 IP(src=ep.ip4.address, dst=rep_2.ip4.address) /
2410 UDP(sport=1234, dport=1234) /
2412 rxs = self.send_and_expect(self.pg0, [p], self.pg2)
2414 self.assertFalse(find_gbp_endpoint(self, ip=rep_88.ip4.address))
2416 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2417 IP(src=ep.ip4.address, dst=rep_88.ip4.address) /
2418 UDP(sport=1234, dport=1234) /
2420 rxs = self.send_and_expect(self.pg0, [p], self.pg4)
2423 # to appease the testcase we cannot have the registered EP stll
2424 # present (because it's DP learnt) when the TC ends so wait until
2427 self.wait_for_ep_timeout(ip=rep_88.ip4.address)
2428 self.wait_for_ep_timeout(ip=rep_2.ip4.address)
2431 # shutdown with learnt endpoint present
2433 p = (Ether(src=self.pg2.remote_mac,
2434 dst=self.pg2.local_mac) /
2435 IP(src=self.pg2.remote_hosts[1].ip4,
2436 dst=self.pg2.local_ip4) /
2437 UDP(sport=1234, dport=48879) /
2438 VXLAN(vni=101, gpid=441, flags=0x88) /
2439 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2440 IP(src=learnt[1]['ip'], dst=ep.ip4.address) /
2441 UDP(sport=1234, dport=1234) /
2444 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2446 # endpoint learnt via the parent GBP-vxlan interface
2447 self.assertTrue(find_gbp_endpoint(self,
2448 vx_tun_l3._sw_if_index,
2453 # remote endpoint becomes local
2455 self.pg2.unconfig_ip4()
2456 self.pg3.unconfig_ip4()
2457 self.pg4.unconfig_ip4()
2459 def test_gbp_redirect(self):
2460 """ GBP Endpoint Redirect """
2462 self.vapi.cli("set logging class gbp debug")
2464 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
2465 routed_dst_mac = "00:0c:0c:0c:0c:0c"
2466 routed_src_mac = "00:22:bd:f8:19:ff"
2468 learnt = [{'mac': '00:00:11:11:11:02',
2470 'ip6': '2001:10::2'},
2471 {'mac': '00:00:11:11:11:03',
2473 'ip6': '2001:10::3'}]
2478 t4 = VppIpTable(self, 1)
2480 t6 = VppIpTable(self, 1, True)
2483 rd1 = VppGbpRouteDomain(self, 2, t4, t6)
2484 rd1.add_vpp_config()
2486 self.loop0.set_mac(self.router_mac)
2489 # Bind the BVI to the RD
2491 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
2492 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
2495 # Pg7 hosts a BD's UU-fwd
2497 self.pg7.config_ip4()
2498 self.pg7.resolve_arp()
2501 # a GBP bridge domains for the EPs
2503 bd1 = VppBridgeDomain(self, 1)
2504 bd1.add_vpp_config()
2505 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0)
2506 gbd1.add_vpp_config()
2508 bd2 = VppBridgeDomain(self, 2)
2509 bd2.add_vpp_config()
2510 gbd2 = VppGbpBridgeDomain(self, bd2, self.loop1)
2511 gbd2.add_vpp_config()
2513 # ... and has a /32 and /128 applied
2514 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2515 ip4_addr.add_vpp_config()
2516 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 128)
2517 ip6_addr.add_vpp_config()
2518 ip4_addr = VppIpInterfaceAddress(self, gbd2.bvi, "10.0.1.128", 32)
2519 ip4_addr.add_vpp_config()
2520 ip6_addr = VppIpInterfaceAddress(self, gbd2.bvi, "2001:11::128", 128)
2521 ip6_addr.add_vpp_config()
2524 # The Endpoint-groups in which we are learning endpoints
2526 epg_220 = VppGbpEndpointGroup(self, 220, 440, rd1, gbd1,
2530 VppGbpEndpointRetention(2))
2531 epg_220.add_vpp_config()
2532 epg_221 = VppGbpEndpointGroup(self, 221, 441, rd1, gbd2,
2536 VppGbpEndpointRetention(2))
2537 epg_221.add_vpp_config()
2538 epg_222 = VppGbpEndpointGroup(self, 222, 442, rd1, gbd1,
2542 VppGbpEndpointRetention(2))
2543 epg_222.add_vpp_config()
2546 # a GBP bridge domains for the SEPs
2548 bd_uu1 = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
2549 self.pg7.remote_ip4, 116)
2550 bd_uu1.add_vpp_config()
2551 bd_uu2 = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
2552 self.pg7.remote_ip4, 117)
2553 bd_uu2.add_vpp_config()
2555 bd3 = VppBridgeDomain(self, 3)
2556 bd3.add_vpp_config()
2557 gbd3 = VppGbpBridgeDomain(self, bd3, self.loop2, bd_uu1, learn=False)
2558 gbd3.add_vpp_config()
2559 bd4 = VppBridgeDomain(self, 4)
2560 bd4.add_vpp_config()
2561 gbd4 = VppGbpBridgeDomain(self, bd4, self.loop3, bd_uu2, learn=False)
2562 gbd4.add_vpp_config()
2565 # EPGs in which the service endpoints exist
2567 epg_320 = VppGbpEndpointGroup(self, 320, 550, rd1, gbd3,
2571 VppGbpEndpointRetention(2))
2572 epg_320.add_vpp_config()
2573 epg_321 = VppGbpEndpointGroup(self, 321, 551, rd1, gbd4,
2577 VppGbpEndpointRetention(2))
2578 epg_321.add_vpp_config()
2581 # three local endpoints
2583 ep1 = VppGbpEndpoint(self, self.pg0,
2585 "10.0.0.1", "11.0.0.1",
2586 "2001:10::1", "3001:10::1")
2587 ep1.add_vpp_config()
2588 ep2 = VppGbpEndpoint(self, self.pg1,
2590 "10.0.1.1", "11.0.1.1",
2591 "2001:11::1", "3001:11::1")
2592 ep2.add_vpp_config()
2593 ep3 = VppGbpEndpoint(self, self.pg2,
2595 "10.0.2.2", "11.0.2.2",
2596 "2001:12::1", "3001:12::1")
2597 ep3.add_vpp_config()
2602 sep1 = VppGbpEndpoint(self, self.pg3,
2604 "12.0.0.1", "13.0.0.1",
2605 "4001:10::1", "5001:10::1")
2606 sep1.add_vpp_config()
2607 sep2 = VppGbpEndpoint(self, self.pg4,
2609 "12.0.0.2", "13.0.0.2",
2610 "4001:10::2", "5001:10::2")
2611 sep2.add_vpp_config()
2612 sep3 = VppGbpEndpoint(self, self.pg5,
2614 "12.0.1.1", "13.0.1.1",
2615 "4001:11::1", "5001:11::1")
2616 sep3.add_vpp_config()
2617 # this EP is not installed immediately
2618 sep4 = VppGbpEndpoint(self, self.pg6,
2620 "12.0.1.2", "13.0.1.2",
2621 "4001:11::2", "5001:11::2")
2624 # an L2 switch packet between local EPs in different EPGs
2625 # different dest ports on each so the are LB hashed differently
2627 p4 = [(Ether(src=ep1.mac, dst=ep3.mac) /
2628 IP(src=ep1.ip4.address, dst=ep3.ip4.address) /
2629 UDP(sport=1234, dport=1234) /
2631 (Ether(src=ep3.mac, dst=ep1.mac) /
2632 IP(src=ep3.ip4.address, dst=ep1.ip4.address) /
2633 UDP(sport=1234, dport=1234) /
2635 p6 = [(Ether(src=ep1.mac, dst=ep3.mac) /
2636 IPv6(src=ep1.ip6.address, dst=ep3.ip6.address) /
2637 UDP(sport=1234, dport=1234) /
2639 (Ether(src=ep3.mac, dst=ep1.mac) /
2640 IPv6(src=ep3.ip6.address, dst=ep1.ip6.address) /
2641 UDP(sport=1234, dport=1230) /
2644 # should be dropped since no contract yet
2645 self.send_and_assert_no_replies(self.pg0, [p4[0]])
2646 self.send_and_assert_no_replies(self.pg0, [p6[0]])
2649 # Add a contract with a rule to load-balance redirect via SEP1 and SEP2
2650 # one of the next-hops is via an EP that is not known
2652 acl = VppGbpAcl(self)
2653 rule4 = acl.create_rule(permit_deny=1, proto=17)
2654 rule6 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
2655 acl_index = acl.add_vpp_config([rule4, rule6])
2658 # test the src-ip hash mode
2660 c1 = VppGbpContract(
2661 self, 220, 222, acl_index,
2662 [VppGbpContractRule(
2663 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2664 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2665 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
2666 sep1.ip4, sep1.epg.rd),
2667 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
2668 sep2.ip4, sep2.epg.rd)]),
2670 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2671 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2672 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
2673 sep3.ip6, sep3.epg.rd),
2674 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
2675 sep4.ip6, sep4.epg.rd)])],
2676 [ETH_P_IP, ETH_P_IPV6])
2679 c2 = VppGbpContract(
2680 self, 222, 220, acl_index,
2681 [VppGbpContractRule(
2682 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2683 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2684 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
2685 sep1.ip4, sep1.epg.rd),
2686 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
2687 sep2.ip4, sep2.epg.rd)]),
2689 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2690 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2691 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
2692 sep3.ip6, sep3.epg.rd),
2693 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
2694 sep4.ip6, sep4.epg.rd)])],
2695 [ETH_P_IP, ETH_P_IPV6])
2699 # send again with the contract preset, now packets arrive
2700 # at SEP1 or SEP2 depending on the hashing
2702 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
2705 self.assertEqual(rx[Ether].src, routed_src_mac)
2706 self.assertEqual(rx[Ether].dst, sep1.mac)
2707 self.assertEqual(rx[IP].src, ep1.ip4.address)
2708 self.assertEqual(rx[IP].dst, ep3.ip4.address)
2710 rxs = self.send_and_expect(self.pg2, p4[1] * 17, sep2.itf)
2713 self.assertEqual(rx[Ether].src, routed_src_mac)
2714 self.assertEqual(rx[Ether].dst, sep2.mac)
2715 self.assertEqual(rx[IP].src, ep3.ip4.address)
2716 self.assertEqual(rx[IP].dst, ep1.ip4.address)
2718 rxs = self.send_and_expect(self.pg0, p6[0] * 17, self.pg7)
2721 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
2722 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
2723 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
2724 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
2725 self.assertEqual(rx[VXLAN].vni, 117)
2726 self.assertTrue(rx[VXLAN].flags.G)
2727 self.assertTrue(rx[VXLAN].flags.Instance)
2728 # redirect policy has been applied
2729 self.assertTrue(rx[VXLAN].gpflags.A)
2730 self.assertFalse(rx[VXLAN].gpflags.D)
2732 inner = rx[VXLAN].payload
2734 self.assertEqual(inner[Ether].src, routed_src_mac)
2735 self.assertEqual(inner[Ether].dst, sep4.mac)
2736 self.assertEqual(inner[IPv6].src, ep1.ip6.address)
2737 self.assertEqual(inner[IPv6].dst, ep3.ip6.address)
2739 rxs = self.send_and_expect(self.pg2, p6[1] * 17, sep3.itf)
2742 self.assertEqual(rx[Ether].src, routed_src_mac)
2743 self.assertEqual(rx[Ether].dst, sep3.mac)
2744 self.assertEqual(rx[IPv6].src, ep3.ip6.address)
2745 self.assertEqual(rx[IPv6].dst, ep1.ip6.address)
2748 # programme the unknown EP
2750 sep4.add_vpp_config()
2752 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep4.itf)
2755 self.assertEqual(rx[Ether].src, routed_src_mac)
2756 self.assertEqual(rx[Ether].dst, sep4.mac)
2757 self.assertEqual(rx[IPv6].src, ep1.ip6.address)
2758 self.assertEqual(rx[IPv6].dst, ep3.ip6.address)
2761 # and revert back to unprogrammed
2763 sep4.remove_vpp_config()
2765 rxs = self.send_and_expect(self.pg0, p6[0] * 17, self.pg7)
2768 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
2769 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
2770 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
2771 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
2772 self.assertEqual(rx[VXLAN].vni, 117)
2773 self.assertTrue(rx[VXLAN].flags.G)
2774 self.assertTrue(rx[VXLAN].flags.Instance)
2775 # redirect policy has been applied
2776 self.assertTrue(rx[VXLAN].gpflags.A)
2777 self.assertFalse(rx[VXLAN].gpflags.D)
2779 inner = rx[VXLAN].payload
2781 self.assertEqual(inner[Ether].src, routed_src_mac)
2782 self.assertEqual(inner[Ether].dst, sep4.mac)
2783 self.assertEqual(inner[IPv6].src, ep1.ip6.address)
2784 self.assertEqual(inner[IPv6].dst, ep3.ip6.address)
2786 c1.remove_vpp_config()
2787 c2.remove_vpp_config()
2790 # test the symmetric hash mode
2792 c1 = VppGbpContract(
2793 self, 220, 222, acl_index,
2794 [VppGbpContractRule(
2795 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2796 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
2797 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
2798 sep1.ip4, sep1.epg.rd),
2799 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
2800 sep2.ip4, sep2.epg.rd)]),
2802 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2803 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
2804 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
2805 sep3.ip6, sep3.epg.rd),
2806 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
2807 sep4.ip6, sep4.epg.rd)])],
2808 [ETH_P_IP, ETH_P_IPV6])
2811 c2 = VppGbpContract(
2812 self, 222, 220, acl_index,
2813 [VppGbpContractRule(
2814 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2815 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
2816 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
2817 sep1.ip4, sep1.epg.rd),
2818 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
2819 sep2.ip4, sep2.epg.rd)]),
2821 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2822 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
2823 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
2824 sep3.ip6, sep3.epg.rd),
2825 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
2826 sep4.ip6, sep4.epg.rd)])],
2827 [ETH_P_IP, ETH_P_IPV6])
2831 # send again with the contract preset, now packets arrive
2832 # at SEP1 for both directions
2834 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
2837 self.assertEqual(rx[Ether].src, routed_src_mac)
2838 self.assertEqual(rx[Ether].dst, sep1.mac)
2839 self.assertEqual(rx[IP].src, ep1.ip4.address)
2840 self.assertEqual(rx[IP].dst, ep3.ip4.address)
2842 rxs = self.send_and_expect(self.pg2, p4[1] * 17, sep1.itf)
2845 self.assertEqual(rx[Ether].src, routed_src_mac)
2846 self.assertEqual(rx[Ether].dst, sep1.mac)
2847 self.assertEqual(rx[IP].src, ep3.ip4.address)
2848 self.assertEqual(rx[IP].dst, ep1.ip4.address)
2851 # programme the unknown EP for the L3 tests
2853 sep4.add_vpp_config()
2856 # an L3 switch packet between local EPs in different EPGs
2857 # different dest ports on each so the are LB hashed differently
2859 p4 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
2860 IP(src=ep1.ip4.address, dst=ep2.ip4.address) /
2861 UDP(sport=1234, dport=1234) /
2863 (Ether(src=ep2.mac, dst=str(self.router_mac)) /
2864 IP(src=ep2.ip4.address, dst=ep1.ip4.address) /
2865 UDP(sport=1234, dport=1234) /
2867 p6 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
2868 IPv6(src=ep1.ip6.address, dst=ep2.ip6.address) /
2869 UDP(sport=1234, dport=1234) /
2871 (Ether(src=ep2.mac, dst=str(self.router_mac)) /
2872 IPv6(src=ep2.ip6.address, dst=ep1.ip6.address) /
2873 UDP(sport=1234, dport=1234) /
2876 c3 = VppGbpContract(
2877 self, 220, 221, acl_index,
2878 [VppGbpContractRule(
2879 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2880 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
2881 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
2882 sep1.ip4, sep1.epg.rd),
2883 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
2884 sep2.ip4, sep2.epg.rd)]),
2886 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2887 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
2888 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
2889 sep3.ip6, sep3.epg.rd),
2890 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
2891 sep4.ip6, sep4.epg.rd)])],
2892 [ETH_P_IP, ETH_P_IPV6])
2895 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
2898 self.assertEqual(rx[Ether].src, routed_src_mac)
2899 self.assertEqual(rx[Ether].dst, sep1.mac)
2900 self.assertEqual(rx[IP].src, ep1.ip4.address)
2901 self.assertEqual(rx[IP].dst, ep2.ip4.address)
2904 # learn a remote EP in EPG 221
2906 vx_tun_l3 = VppGbpVxlanTunnel(
2907 self, 444, rd1.rd_id,
2908 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3)
2909 vx_tun_l3.add_vpp_config()
2911 c4 = VppGbpContract(
2912 self, 221, 220, acl_index,
2913 [VppGbpContractRule(
2914 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2917 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2919 [ETH_P_IP, ETH_P_IPV6])
2922 p = (Ether(src=self.pg7.remote_mac,
2923 dst=self.pg7.local_mac) /
2924 IP(src=self.pg7.remote_ip4,
2925 dst=self.pg7.local_ip4) /
2926 UDP(sport=1234, dport=48879) /
2927 VXLAN(vni=444, gpid=441, flags=0x88) /
2928 Ether(src="00:22:22:22:22:33", dst=str(self.router_mac)) /
2929 IP(src="10.0.0.88", dst=ep1.ip4.address) /
2930 UDP(sport=1234, dport=1234) /
2933 rx = self.send_and_expect(self.pg7, [p], self.pg0)
2935 # endpoint learnt via the parent GBP-vxlan interface
2936 self.assertTrue(find_gbp_endpoint(self,
2937 vx_tun_l3._sw_if_index,
2940 p = (Ether(src=self.pg7.remote_mac,
2941 dst=self.pg7.local_mac) /
2942 IP(src=self.pg7.remote_ip4,
2943 dst=self.pg7.local_ip4) /
2944 UDP(sport=1234, dport=48879) /
2945 VXLAN(vni=444, gpid=441, flags=0x88) /
2946 Ether(src="00:22:22:22:22:33", dst=str(self.router_mac)) /
2947 IPv6(src="2001:10::88", dst=ep1.ip6.address) /
2948 UDP(sport=1234, dport=1234) /
2951 rx = self.send_and_expect(self.pg7, [p], self.pg0)
2953 # endpoint learnt via the parent GBP-vxlan interface
2954 self.assertTrue(find_gbp_endpoint(self,
2955 vx_tun_l3._sw_if_index,
2959 # L3 switch from local to remote EP
2961 p4 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
2962 IP(src=ep1.ip4.address, dst="10.0.0.88") /
2963 UDP(sport=1234, dport=1234) /
2965 p6 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
2966 IPv6(src=ep1.ip6.address, dst="2001:10::88") /
2967 UDP(sport=1234, dport=1234) /
2970 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
2973 self.assertEqual(rx[Ether].src, routed_src_mac)
2974 self.assertEqual(rx[Ether].dst, sep1.mac)
2975 self.assertEqual(rx[IP].src, ep1.ip4.address)
2976 self.assertEqual(rx[IP].dst, "10.0.0.88")
2978 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep4.itf)
2981 self.assertEqual(rx[Ether].src, routed_src_mac)
2982 self.assertEqual(rx[Ether].dst, sep4.mac)
2983 self.assertEqual(rx[IPv6].src, ep1.ip6.address)
2984 self.assertEqual(rx[IPv6].dst, "2001:10::88")
2987 # test the dst-ip hash mode
2989 c5 = VppGbpContract(
2990 self, 220, 221, acl_index,
2991 [VppGbpContractRule(
2992 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2993 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
2994 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
2995 sep1.ip4, sep1.epg.rd),
2996 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
2997 sep2.ip4, sep2.epg.rd)]),
2999 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3000 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
3001 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3002 sep3.ip6, sep3.epg.rd),
3003 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3004 sep4.ip6, sep4.epg.rd)])],
3005 [ETH_P_IP, ETH_P_IPV6])
3008 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3011 self.assertEqual(rx[Ether].src, routed_src_mac)
3012 self.assertEqual(rx[Ether].dst, sep1.mac)
3013 self.assertEqual(rx[IP].src, ep1.ip4.address)
3014 self.assertEqual(rx[IP].dst, "10.0.0.88")
3016 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep3.itf)
3019 self.assertEqual(rx[Ether].src, routed_src_mac)
3020 self.assertEqual(rx[Ether].dst, sep3.mac)
3021 self.assertEqual(rx[IPv6].src, ep1.ip6.address)
3022 self.assertEqual(rx[IPv6].dst, "2001:10::88")
3027 self.pg7.unconfig_ip4()
3029 def test_gbp_l3_out(self):
3032 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
3033 self.vapi.cli("set logging class gbp debug")
3035 routed_dst_mac = "00:0c:0c:0c:0c:0c"
3036 routed_src_mac = "00:22:bd:f8:19:ff"
3041 t4 = VppIpTable(self, 1)
3043 t6 = VppIpTable(self, 1, True)
3046 rd1 = VppGbpRouteDomain(self, 2, t4, t6)
3047 rd1.add_vpp_config()
3049 self.loop0.set_mac(self.router_mac)
3052 # Bind the BVI to the RD
3054 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
3055 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
3058 # Pg7 hosts a BD's BUM
3059 # Pg1 some other l3 interface
3061 self.pg7.config_ip4()
3062 self.pg7.resolve_arp()
3065 # a multicast vxlan-gbp tunnel for broadcast in the BD
3067 tun_bm = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
3070 tun_bm.add_vpp_config()
3073 # a GBP external bridge domains for the EPs
3075 bd1 = VppBridgeDomain(self, 1)
3076 bd1.add_vpp_config()
3077 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0, None, tun_bm)
3078 gbd1.add_vpp_config()
3081 # The Endpoint-groups in which the external endpoints exist
3083 epg_220 = VppGbpEndpointGroup(self, 220, 113, rd1, gbd1,
3087 VppGbpEndpointRetention(2))
3088 epg_220.add_vpp_config()
3090 # the BVIs have the subnets applied ...
3091 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 24)
3092 ip4_addr.add_vpp_config()
3093 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 64)
3094 ip6_addr.add_vpp_config()
3096 # ... which are L3-out subnets
3097 l3o_1 = VppGbpSubnet(
3098 self, rd1, "10.0.0.0", 24,
3099 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3101 l3o_1.add_vpp_config()
3104 # an external interface attached to the outside world and the
3107 vlan_100 = VppDot1QSubint(self, self.pg0, 100)
3109 ext_itf = VppGbpExtItf(self, vlan_100, bd1, rd1)
3110 ext_itf.add_vpp_config()
3113 # an unicast vxlan-gbp for inter-RD traffic
3115 vx_tun_l3 = VppGbpVxlanTunnel(
3116 self, 444, rd1.rd_id,
3117 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3)
3118 vx_tun_l3.add_vpp_config()
3121 # packets destined to unkown addresses in the BVI's subnet
3124 p4 = (Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
3126 IP(src="10.0.0.1", dst="10.0.0.88") /
3127 UDP(sport=1234, dport=1234) /
3129 p6 = (Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
3131 IPv6(src="2001:10::1", dst="2001:10::88") /
3132 UDP(sport=1234, dport=1234) /
3135 rxs = self.send_and_expect(self.pg0, p4 * 1, self.pg7)
3138 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3139 # self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3140 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3141 self.assertEqual(rx[IP].dst, "239.1.1.1")
3142 self.assertEqual(rx[VXLAN].vni, 88)
3143 self.assertTrue(rx[VXLAN].flags.G)
3144 self.assertTrue(rx[VXLAN].flags.Instance)
3145 # policy was applied to the original IP packet
3146 self.assertEqual(rx[VXLAN].gpid, 113)
3147 self.assertTrue(rx[VXLAN].gpflags.A)
3148 self.assertFalse(rx[VXLAN].gpflags.D)
3150 inner = rx[VXLAN].payload
3152 self.assertTrue(inner.haslayer(ARP))
3155 # An external Endpoint
3157 eep = VppGbpEndpoint(self, vlan_100,
3159 "10.0.0.1", "11.0.0.1",
3160 "2001:10::1", "3001::1",
3161 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
3162 eep.add_vpp_config()
3167 rep = VppGbpEndpoint(self, vx_tun_l3,
3169 "10.0.0.101", "11.0.0.101",
3170 "2001:10::101", "3001::101",
3171 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
3173 self.pg7.remote_ip4,
3175 rep.add_vpp_config()
3178 # remote to external
3180 p = (Ether(src=self.pg7.remote_mac,
3181 dst=self.pg7.local_mac) /
3182 IP(src=self.pg7.remote_ip4,
3183 dst=self.pg7.local_ip4) /
3184 UDP(sport=1234, dport=48879) /
3185 VXLAN(vni=444, gpid=113, flags=0x88) /
3186 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
3187 IP(src="10.0.0.101", dst="10.0.0.1") /
3188 UDP(sport=1234, dport=1234) /
3191 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
3194 # A subnet reachable through the external EP
3196 ip_220 = VppIpRoute(self, "10.220.0.0", 24,
3197 [VppRoutePath(eep.ip4.address,
3198 eep.epg.bvi.sw_if_index)],
3199 table_id=t4.table_id)
3200 ip_220.add_vpp_config()
3202 l3o_220 = VppGbpSubnet(
3203 self, rd1, "10.220.0.0", 24,
3204 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3206 l3o_220.add_vpp_config()
3208 p = (Ether(src=self.pg7.remote_mac,
3209 dst=self.pg7.local_mac) /
3210 IP(src=self.pg7.remote_ip4,
3211 dst=self.pg7.local_ip4) /
3212 UDP(sport=1234, dport=48879) /
3213 VXLAN(vni=444, gpid=113, flags=0x88) /
3214 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
3215 IP(src="10.0.0.101", dst="10.220.0.1") /
3216 UDP(sport=1234, dport=1234) /
3219 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
3224 self.pg7.unconfig_ip4()
3227 if __name__ == '__main__':
3228 unittest.main(testRunner=VppTestRunner)