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, ICMP
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, VppL2Vtr
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, \
29 from vpp_neighbor import VppNeighbor
32 def find_gbp_endpoint(test, sw_if_index=None, ip=None, mac=None):
34 vip = VppIpAddress(ip)
36 vmac = MACAddress(mac)
38 eps = test.vapi.gbp_endpoint_dump()
42 if ep.endpoint.sw_if_index != sw_if_index:
45 for eip in ep.endpoint.ips:
49 if vmac.packed == ep.endpoint.mac:
54 def find_gbp_vxlan(test, vni):
55 ts = test.vapi.gbp_vxlan_tunnel_dump()
57 if t.tunnel.vni == vni:
62 class VppGbpEndpoint(VppObject):
89 return [self.ip4, self.ip6]
93 return [self.fip4, self.fip6]
95 def __init__(self, test, itf, epg, recirc, ip4, fip4, ip6, fip6,
105 self._ip4 = VppIpAddress(ip4)
106 self._fip4 = VppIpAddress(fip4)
107 self._ip6 = VppIpAddress(ip6)
108 self._fip6 = VppIpAddress(fip6)
111 self.vmac = MACAddress(self.itf.remote_mac)
113 self.vmac = MACAddress("00:00:00:00:00:00")
116 self.tun_src = VppIpAddress(tun_src)
117 self.tun_dst = VppIpAddress(tun_dst)
119 def add_vpp_config(self):
120 res = self._test.vapi.gbp_endpoint_add(
121 self.itf.sw_if_index,
122 [self.ip4.encode(), self.ip6.encode()],
126 self.tun_src.encode(),
127 self.tun_dst.encode())
128 self.handle = res.handle
129 self._test.registry.register(self, self._test.logger)
131 def remove_vpp_config(self):
132 self._test.vapi.gbp_endpoint_del(self.handle)
135 return "gbp-endpoint:[%d==%d:%s:%d]" % (self.handle,
136 self.itf.sw_if_index,
140 def query_vpp_config(self):
141 return find_gbp_endpoint(self._test,
142 self.itf.sw_if_index,
146 class VppGbpRecirc(VppObject):
148 GBP Recirculation Interface
151 def __init__(self, test, epg, recirc, is_ext=False):
157 def add_vpp_config(self):
158 self._test.vapi.gbp_recirc_add_del(
160 self.recirc.sw_if_index,
163 self._test.registry.register(self, self._test.logger)
165 def remove_vpp_config(self):
166 self._test.vapi.gbp_recirc_add_del(
168 self.recirc.sw_if_index,
173 return "gbp-recirc:[%d]" % (self.recirc.sw_if_index)
175 def query_vpp_config(self):
176 rs = self._test.vapi.gbp_recirc_dump()
178 if r.recirc.sw_if_index == self.recirc.sw_if_index:
183 class VppGbpExtItf(VppObject):
185 GBP ExtItfulation Interface
188 def __init__(self, test, itf, bd, rd):
194 def add_vpp_config(self):
195 self._test.vapi.gbp_ext_itf_add_del(
197 self.itf.sw_if_index,
200 self._test.registry.register(self, self._test.logger)
202 def remove_vpp_config(self):
203 self._test.vapi.gbp_ext_itf_add_del(
205 self.itf.sw_if_index,
210 return "gbp-ext-itf:[%d]" % (self.itf.sw_if_index)
212 def query_vpp_config(self):
213 rs = self._test.vapi.gbp_ext_itf_dump()
215 if r.ext_itf.sw_if_index == self.itf.sw_if_index:
220 class VppGbpSubnet(VppObject):
224 def __init__(self, test, rd, address, address_len,
225 type, sw_if_index=None, sclass=None):
227 self.rd_id = rd.rd_id
228 self.prefix = VppIpPrefix(address, address_len)
230 self.sw_if_index = sw_if_index
233 def add_vpp_config(self):
234 self._test.vapi.gbp_subnet_add_del(
237 self.prefix.encode(),
239 sw_if_index=self.sw_if_index if self.sw_if_index else 0xffffffff,
240 sclass=self.sclass if self.sclass else 0xffff)
241 self._test.registry.register(self, self._test.logger)
243 def remove_vpp_config(self):
244 self._test.vapi.gbp_subnet_add_del(
247 self.prefix.encode(),
251 return "gbp-subnet:[%d-%s]" % (self.rd_id, self.prefix)
253 def query_vpp_config(self):
254 ss = self._test.vapi.gbp_subnet_dump()
256 if s.subnet.rd_id == self.rd_id and \
257 s.subnet.type == self.type and \
258 s.subnet.prefix == self.prefix:
263 class VppGbpEndpointRetention(object):
264 def __init__(self, remote_ep_timeout=0xffffffff):
265 self.remote_ep_timeout = remote_ep_timeout
268 return {'remote_ep_timeout': self.remote_ep_timeout}
271 class VppGbpEndpointGroup(VppObject):
276 def __init__(self, test, vnid, sclass, rd, bd, uplink,
277 bvi, bvi_ip4, bvi_ip6=None,
278 retention=VppGbpEndpointRetention()):
282 self.bvi_ip4 = VppIpAddress(bvi_ip4)
283 self.bvi_ip6 = VppIpAddress(bvi_ip6)
290 self.retention = retention
292 def add_vpp_config(self):
293 self._test.vapi.gbp_endpoint_group_add(
298 self.uplink.sw_if_index if self.uplink else INDEX_INVALID,
299 self.retention.encode())
300 self._test.registry.register(self, self._test.logger)
302 def remove_vpp_config(self):
303 self._test.vapi.gbp_endpoint_group_del(self.sclass)
306 return "gbp-endpoint-group:[%d]" % (self.vnid)
308 def query_vpp_config(self):
309 epgs = self._test.vapi.gbp_endpoint_group_dump()
311 if epg.epg.vnid == self.vnid:
316 class VppGbpBridgeDomain(VppObject):
321 def __init__(self, test, bd, bvi, uu_fwd=None,
322 bm_flood=None, learn=True):
326 self.bm_flood = bm_flood
329 e = VppEnum.vl_api_gbp_bridge_domain_flags_t
331 self.learn = e.GBP_BD_API_FLAG_NONE
333 self.learn = e.GBP_BD_API_FLAG_DO_NOT_LEARN
335 def add_vpp_config(self):
336 self._test.vapi.gbp_bridge_domain_add(
339 self.bvi.sw_if_index,
340 self.uu_fwd.sw_if_index if self.uu_fwd else INDEX_INVALID,
341 self.bm_flood.sw_if_index if self.bm_flood else INDEX_INVALID)
342 self._test.registry.register(self, self._test.logger)
344 def remove_vpp_config(self):
345 self._test.vapi.gbp_bridge_domain_del(self.bd.bd_id)
348 return "gbp-bridge-domain:[%d]" % (self.bd.bd_id)
350 def query_vpp_config(self):
351 bds = self._test.vapi.gbp_bridge_domain_dump()
353 if bd.bd.bd_id == self.bd.bd_id:
358 class VppGbpRouteDomain(VppObject):
363 def __init__(self, test, rd_id, t4, t6, ip4_uu=None, ip6_uu=None):
371 def add_vpp_config(self):
372 self._test.vapi.gbp_route_domain_add(
376 self.ip4_uu.sw_if_index if self.ip4_uu else INDEX_INVALID,
377 self.ip6_uu.sw_if_index if self.ip6_uu else INDEX_INVALID)
378 self._test.registry.register(self, self._test.logger)
380 def remove_vpp_config(self):
381 self._test.vapi.gbp_route_domain_del(self.rd_id)
384 return "gbp-route-domain:[%d]" % (self.rd_id)
386 def query_vpp_config(self):
387 rds = self._test.vapi.gbp_route_domain_dump()
389 if rd.rd.rd_id == self.rd_id:
394 class VppGbpContractNextHop():
395 def __init__(self, mac, bd, ip, rd):
402 return {'ip': self.ip.encode(),
403 'mac': self.mac.packed,
404 'bd_id': self.bd.bd.bd_id,
405 'rd_id': self.rd.rd_id}
408 class VppGbpContractRule():
409 def __init__(self, action, hash_mode, nhs=[]):
411 self.hash_mode = hash_mode
417 nhs.append(nh.encode())
420 return {'action': self.action,
422 'hash_mode': self.hash_mode,
423 'n_nhs': len(self.nhs),
427 class VppGbpContract(VppObject):
432 def __init__(self, test, sclass, dclass, acl_index,
433 rules, allowed_ethertypes):
435 self.acl_index = acl_index
439 self.allowed_ethertypes = allowed_ethertypes
440 while (len(self.allowed_ethertypes) < 16):
441 self.allowed_ethertypes.append(0)
443 def add_vpp_config(self):
446 rules.append(r.encode())
447 self._test.vapi.gbp_contract_add_del(
453 self.allowed_ethertypes)
454 self._test.registry.register(self, self._test.logger)
456 def remove_vpp_config(self):
457 self._test.vapi.gbp_contract_add_del(
463 self.allowed_ethertypes)
466 return "gbp-contract:[%d:%s:%d]" % (self.sclass,
470 def query_vpp_config(self):
471 cs = self._test.vapi.gbp_contract_dump()
473 if c.contract.sclass == self.sclass \
474 and c.contract.dclass == self.dclass:
479 class VppGbpVxlanTunnel(VppInterface):
484 def __init__(self, test, vni, bd_rd_id, mode, src):
485 super(VppGbpVxlanTunnel, self).__init__(test)
488 self.bd_rd_id = bd_rd_id
492 def add_vpp_config(self):
493 r = self._test.vapi.gbp_vxlan_tunnel_add(
498 self.set_sw_if_index(r.sw_if_index)
499 self._test.registry.register(self, self._test.logger)
501 def remove_vpp_config(self):
502 self._test.vapi.gbp_vxlan_tunnel_del(self.vni)
505 return "gbp-vxlan:%d" % (self.sw_if_index)
507 def query_vpp_config(self):
508 return find_gbp_vxlan(self._test, self.vni)
511 class VppGbpAcl(VppObject):
516 def __init__(self, test):
518 self.acl_index = 4294967295
520 def create_rule(self, is_ipv6=0, permit_deny=0, proto=-1,
521 s_prefix=0, s_ip=b'\x00\x00\x00\x00', sport_from=0,
522 sport_to=65535, d_prefix=0, d_ip=b'\x00\x00\x00\x00',
523 dport_from=0, dport_to=65535):
524 if proto == -1 or proto == 0:
527 elif proto == 1 or proto == 58:
530 rule = ({'is_permit': permit_deny, 'is_ipv6': is_ipv6, 'proto': proto,
531 'srcport_or_icmptype_first': sport_from,
532 'srcport_or_icmptype_last': sport_to,
533 'src_ip_prefix_len': s_prefix,
535 'dstport_or_icmpcode_first': dport_from,
536 'dstport_or_icmpcode_last': dport_to,
537 'dst_ip_prefix_len': d_prefix,
538 'dst_ip_addr': d_ip})
541 def add_vpp_config(self, rules):
543 reply = self._test.vapi.acl_add_replace(self.acl_index,
546 self.acl_index = reply.acl_index
547 return self.acl_index
549 def remove_vpp_config(self):
550 self._test.vapi.acl_del(self.acl_index)
553 return "gbp-acl:[%d]" % (self.acl_index)
555 def query_vpp_config(self):
556 cs = self._test.vapi.acl_dump()
558 if c.acl_index == self.acl_index:
563 class TestGBP(VppTestCase):
564 """ GBP Test Case """
567 super(TestGBP, self).setUp()
569 self.create_pg_interfaces(range(9))
570 self.create_loopback_interfaces(8)
572 self.router_mac = MACAddress("00:11:22:33:44:55")
574 for i in self.pg_interfaces:
576 for i in self.lo_interfaces:
580 for i in self.pg_interfaces:
583 super(TestGBP, self).tearDown()
585 def send_and_expect_bridged(self, src, tx, dst):
586 rx = self.send_and_expect(src, tx, dst)
589 self.assertEqual(r[Ether].src, tx[0][Ether].src)
590 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
591 self.assertEqual(r[IP].src, tx[0][IP].src)
592 self.assertEqual(r[IP].dst, tx[0][IP].dst)
595 def send_and_expect_bridged6(self, src, tx, dst):
596 rx = self.send_and_expect(src, tx, dst)
599 self.assertEqual(r[Ether].src, tx[0][Ether].src)
600 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
601 self.assertEqual(r[IPv6].src, tx[0][IPv6].src)
602 self.assertEqual(r[IPv6].dst, tx[0][IPv6].dst)
605 def send_and_expect_routed(self, src, tx, dst, src_mac):
606 rx = self.send_and_expect(src, tx, dst)
609 self.assertEqual(r[Ether].src, src_mac)
610 self.assertEqual(r[Ether].dst, dst.remote_mac)
611 self.assertEqual(r[IP].src, tx[0][IP].src)
612 self.assertEqual(r[IP].dst, tx[0][IP].dst)
615 def send_and_expect_natted(self, src, tx, dst, src_ip):
616 rx = self.send_and_expect(src, tx, dst)
619 self.assertEqual(r[Ether].src, tx[0][Ether].src)
620 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
621 self.assertEqual(r[IP].src, src_ip)
622 self.assertEqual(r[IP].dst, tx[0][IP].dst)
625 def send_and_expect_natted6(self, src, tx, dst, src_ip):
626 rx = self.send_and_expect(src, tx, dst)
629 self.assertEqual(r[Ether].src, tx[0][Ether].src)
630 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
631 self.assertEqual(r[IPv6].src, src_ip)
632 self.assertEqual(r[IPv6].dst, tx[0][IPv6].dst)
635 def send_and_expect_unnatted(self, src, tx, dst, dst_ip):
636 rx = self.send_and_expect(src, tx, dst)
639 self.assertEqual(r[Ether].src, tx[0][Ether].src)
640 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
641 self.assertEqual(r[IP].dst, dst_ip)
642 self.assertEqual(r[IP].src, tx[0][IP].src)
645 def send_and_expect_unnatted6(self, src, tx, dst, dst_ip):
646 rx = self.send_and_expect(src, tx, dst)
649 self.assertEqual(r[Ether].src, tx[0][Ether].src)
650 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
651 self.assertEqual(r[IPv6].dst, dst_ip)
652 self.assertEqual(r[IPv6].src, tx[0][IPv6].src)
655 def send_and_expect_double_natted(self, src, tx, dst, src_ip, dst_ip):
656 rx = self.send_and_expect(src, tx, dst)
659 self.assertEqual(r[Ether].src, str(self.router_mac))
660 self.assertEqual(r[Ether].dst, dst.remote_mac)
661 self.assertEqual(r[IP].dst, dst_ip)
662 self.assertEqual(r[IP].src, src_ip)
665 def send_and_expect_double_natted6(self, src, tx, dst, src_ip, dst_ip):
666 rx = self.send_and_expect(src, tx, dst)
669 self.assertEqual(r[Ether].src, str(self.router_mac))
670 self.assertEqual(r[Ether].dst, dst.remote_mac)
671 self.assertEqual(r[IPv6].dst, dst_ip)
672 self.assertEqual(r[IPv6].src, src_ip)
676 """ Group Based Policy """
678 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
683 bd1 = VppBridgeDomain(self, 1)
684 bd2 = VppBridgeDomain(self, 2)
685 bd20 = VppBridgeDomain(self, 20)
689 bd20.add_vpp_config()
691 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0)
692 gbd2 = VppGbpBridgeDomain(self, bd2, self.loop1)
693 gbd20 = VppGbpBridgeDomain(self, bd20, self.loop2)
695 gbd1.add_vpp_config()
696 gbd2.add_vpp_config()
697 gbd20.add_vpp_config()
702 gt4 = VppIpTable(self, 0)
704 gt6 = VppIpTable(self, 0, is_ip6=True)
706 nt4 = VppIpTable(self, 20)
708 nt6 = VppIpTable(self, 20, is_ip6=True)
711 rd0 = VppGbpRouteDomain(self, 0, gt4, gt6, None, None)
712 rd20 = VppGbpRouteDomain(self, 20, nt4, nt6, None, None)
715 rd20.add_vpp_config()
718 # 3 EPGs, 2 of which share a BD.
719 # 2 NAT EPGs, one for floating-IP subnets, the other for internet
721 epgs = [VppGbpEndpointGroup(self, 220, 1220, rd0, gbd1,
722 self.pg4, self.loop0,
723 "10.0.0.128", "2001:10::128"),
724 VppGbpEndpointGroup(self, 221, 1221, rd0, gbd1,
725 self.pg5, self.loop0,
726 "10.0.1.128", "2001:10:1::128"),
727 VppGbpEndpointGroup(self, 222, 1222, rd0, gbd2,
728 self.pg6, self.loop1,
729 "10.0.2.128", "2001:10:2::128"),
730 VppGbpEndpointGroup(self, 333, 1333, rd20, gbd20,
731 self.pg7, self.loop2,
732 "11.0.0.128", "3001::128"),
733 VppGbpEndpointGroup(self, 444, 1444, rd20, gbd20,
734 self.pg8, self.loop2,
735 "11.0.0.129", "3001::129")]
736 recircs = [VppGbpRecirc(self, epgs[0], self.loop3),
737 VppGbpRecirc(self, epgs[1], self.loop4),
738 VppGbpRecirc(self, epgs[2], self.loop5),
739 VppGbpRecirc(self, epgs[3], self.loop6, is_ext=True),
740 VppGbpRecirc(self, epgs[4], self.loop7, is_ext=True)]
743 recirc_nat = recircs[3]
746 # 4 end-points, 2 in the same subnet, 3 in the same BD
748 eps = [VppGbpEndpoint(self, self.pg0,
750 "10.0.0.1", "11.0.0.1",
751 "2001:10::1", "3001::1"),
752 VppGbpEndpoint(self, self.pg1,
754 "10.0.0.2", "11.0.0.2",
755 "2001:10::2", "3001::2"),
756 VppGbpEndpoint(self, self.pg2,
758 "10.0.1.1", "11.0.0.3",
759 "2001:10:1::1", "3001::3"),
760 VppGbpEndpoint(self, self.pg3,
762 "10.0.2.1", "11.0.0.4",
763 "2001:10:2::1", "3001::4")]
766 # Config related to each of the EPGs
769 # IP config on the BVI interfaces
770 if epg != epgs[1] and epg != epgs[4]:
771 VppIpInterfaceBind(self, epg.bvi, epg.rd.t4).add_vpp_config()
772 VppIpInterfaceBind(self, epg.bvi, epg.rd.t6).add_vpp_config()
773 self.vapi.sw_interface_set_mac_address(
775 self.router_mac.packed)
777 # The BVIs are NAT inside interfaces
778 self.vapi.nat44_interface_add_del_feature(epg.bvi.sw_if_index,
781 self.vapi.nat66_add_del_interface(epg.bvi.sw_if_index,
785 if_ip4 = VppIpInterfaceAddress(self, epg.bvi, epg.bvi_ip4, 32)
786 if_ip6 = VppIpInterfaceAddress(self, epg.bvi, epg.bvi_ip6, 128)
787 if_ip4.add_vpp_config()
788 if_ip6.add_vpp_config()
790 # EPG uplink interfaces in the RD
791 VppIpInterfaceBind(self, epg.uplink, epg.rd.t4).add_vpp_config()
792 VppIpInterfaceBind(self, epg.uplink, epg.rd.t6).add_vpp_config()
794 # add the BD ARP termination entry for BVI IP
795 epg.bd_arp_ip4 = VppBridgeDomainArpEntry(self, epg.bd.bd,
796 str(self.router_mac),
798 epg.bd_arp_ip6 = VppBridgeDomainArpEntry(self, epg.bd.bd,
799 str(self.router_mac),
801 epg.bd_arp_ip4.add_vpp_config()
802 epg.bd_arp_ip6.add_vpp_config()
807 for recirc in recircs:
808 # EPG's ingress recirculation interface maps to its RD
809 VppIpInterfaceBind(self, recirc.recirc,
810 recirc.epg.rd.t4).add_vpp_config()
811 VppIpInterfaceBind(self, recirc.recirc,
812 recirc.epg.rd.t6).add_vpp_config()
814 self.vapi.nat44_interface_add_del_feature(
815 recirc.recirc.sw_if_index,
818 self.vapi.nat66_add_del_interface(
819 recirc.recirc.sw_if_index,
823 recirc.add_vpp_config()
825 for recirc in recircs:
826 self.assertTrue(find_bridge_domain_port(self,
827 recirc.epg.bd.bd.bd_id,
828 recirc.recirc.sw_if_index))
831 self.pg_enable_capture(self.pg_interfaces)
834 # routes to the endpoints. We need these since there are no
835 # adj-fibs due to the fact the the BVI address has /32 and
836 # the subnet is not attached.
838 for (ip, fip) in zip(ep.ips, ep.fips):
839 # Add static mappings for each EP from the 10/8 to 11/8 network
841 self.vapi.nat44_add_del_static_mapping(ip.bytes,
846 self.vapi.nat66_add_del_static_mapping(ip.bytes,
853 self.logger.info(self.vapi.cli("sh gbp endpoint"))
855 # ... results in a Gratuitous ARP/ND on the EPG's uplink
856 rx = ep.epg.uplink.get_capture(len(ep.ips), timeout=0.2)
858 for ii, ip in enumerate(ep.ips):
862 self.assertTrue(p.haslayer(ICMPv6ND_NA))
863 self.assertEqual(p[ICMPv6ND_NA].tgt, ip.address)
865 self.assertTrue(p.haslayer(ARP))
866 self.assertEqual(p[ARP].psrc, ip.address)
867 self.assertEqual(p[ARP].pdst, ip.address)
869 # add the BD ARP termination entry for floating IP
871 ba = VppBridgeDomainArpEntry(self, epg_nat.bd.bd, ep.mac, fip)
874 # floating IPs route via EPG recirc
875 r = VppIpRoute(self, fip.address, fip.length,
876 [VppRoutePath(fip.address,
877 ep.recirc.recirc.sw_if_index,
879 proto=fip.dpo_proto)],
884 # L2 FIB entries in the NAT EPG BD to bridge the packets from
885 # the outside direct to the internal EPG
886 lf = VppL2FibEntry(self, epg_nat.bd.bd, ep.mac,
887 ep.recirc.recirc, bvi_mac=0)
891 # ARP packets for unknown IP are sent to the EPG uplink
893 pkt_arp = (Ether(dst="ff:ff:ff:ff:ff:ff",
894 src=self.pg0.remote_mac) /
896 hwdst="ff:ff:ff:ff:ff:ff",
897 hwsrc=self.pg0.remote_mac,
901 self.vapi.cli("clear trace")
902 self.pg0.add_stream(pkt_arp)
904 self.pg_enable_capture(self.pg_interfaces)
907 rxd = epgs[0].uplink.get_capture(1)
910 # ARP/ND packets get a response
912 pkt_arp = (Ether(dst="ff:ff:ff:ff:ff:ff",
913 src=self.pg0.remote_mac) /
915 hwdst="ff:ff:ff:ff:ff:ff",
916 hwsrc=self.pg0.remote_mac,
917 pdst=epgs[0].bvi_ip4.address,
918 psrc=eps[0].ip4.address))
920 self.send_and_expect(self.pg0, [pkt_arp], self.pg0)
922 nsma = in6_getnsma(inet_pton(AF_INET6, eps[0].ip6.address))
923 d = inet_ntop(AF_INET6, nsma)
924 pkt_nd = (Ether(dst=in6_getnsmac(nsma),
925 src=self.pg0.remote_mac) /
926 IPv6(dst=d, src=eps[0].ip6.address) /
927 ICMPv6ND_NS(tgt=epgs[0].bvi_ip6.address) /
928 ICMPv6NDOptSrcLLAddr(lladdr=self.pg0.remote_mac))
929 self.send_and_expect(self.pg0, [pkt_nd], self.pg0)
932 # broadcast packets are flooded
934 pkt_bcast = (Ether(dst="ff:ff:ff:ff:ff:ff",
935 src=self.pg0.remote_mac) /
936 IP(src=eps[0].ip4.address, dst="232.1.1.1") /
937 UDP(sport=1234, dport=1234) /
940 self.vapi.cli("clear trace")
941 self.pg0.add_stream(pkt_bcast)
943 self.pg_enable_capture(self.pg_interfaces)
946 rxd = eps[1].itf.get_capture(1)
947 self.assertEqual(rxd[0][Ether].dst, pkt_bcast[Ether].dst)
948 rxd = epgs[0].uplink.get_capture(1)
949 self.assertEqual(rxd[0][Ether].dst, pkt_bcast[Ether].dst)
952 # packets to non-local L3 destinations dropped
954 pkt_intra_epg_220_ip4 = (Ether(src=self.pg0.remote_mac,
955 dst=str(self.router_mac)) /
956 IP(src=eps[0].ip4.address,
958 UDP(sport=1234, dport=1234) /
960 pkt_inter_epg_222_ip4 = (Ether(src=self.pg0.remote_mac,
961 dst=str(self.router_mac)) /
962 IP(src=eps[0].ip4.address,
964 UDP(sport=1234, dport=1234) /
967 self.send_and_assert_no_replies(self.pg0, pkt_intra_epg_220_ip4 * 65)
969 pkt_inter_epg_222_ip6 = (Ether(src=self.pg0.remote_mac,
970 dst=str(self.router_mac)) /
971 IPv6(src=eps[0].ip6.address,
973 UDP(sport=1234, dport=1234) /
975 self.send_and_assert_no_replies(self.pg0, pkt_inter_epg_222_ip6 * 65)
978 # Add the subnet routes
981 self, rd0, "10.0.0.0", 24,
982 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
984 self, rd0, "10.0.1.0", 24,
985 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
987 self, rd0, "10.0.2.0", 24,
988 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
990 self, rd0, "2001:10::1", 64,
991 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
993 self, rd0, "2001:10:1::1", 64,
994 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
996 self, rd0, "2001:10:2::1", 64,
997 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1000 s43.add_vpp_config()
1001 s61.add_vpp_config()
1002 s62.add_vpp_config()
1003 s63.add_vpp_config()
1005 self.send_and_expect_bridged(eps[0].itf,
1006 pkt_intra_epg_220_ip4 * 65,
1008 self.send_and_expect_bridged(eps[0].itf,
1009 pkt_inter_epg_222_ip4 * 65,
1011 self.send_and_expect_bridged6(eps[0].itf,
1012 pkt_inter_epg_222_ip6 * 65,
1015 self.logger.info(self.vapi.cli("sh ip fib 11.0.0.2"))
1016 self.logger.info(self.vapi.cli("sh gbp endpoint-group"))
1017 self.logger.info(self.vapi.cli("sh gbp endpoint"))
1018 self.logger.info(self.vapi.cli("sh gbp recirc"))
1019 self.logger.info(self.vapi.cli("sh int"))
1020 self.logger.info(self.vapi.cli("sh int addr"))
1021 self.logger.info(self.vapi.cli("sh int feat loop6"))
1022 self.logger.info(self.vapi.cli("sh vlib graph ip4-gbp-src-classify"))
1023 self.logger.info(self.vapi.cli("sh int feat loop3"))
1024 self.logger.info(self.vapi.cli("sh int feat pg0"))
1027 # Packet destined to unknown unicast is sent on the epg uplink ...
1029 pkt_intra_epg_220_to_uplink = (Ether(src=self.pg0.remote_mac,
1030 dst="00:00:00:33:44:55") /
1031 IP(src=eps[0].ip4.address,
1033 UDP(sport=1234, dport=1234) /
1036 self.send_and_expect_bridged(eps[0].itf,
1037 pkt_intra_epg_220_to_uplink * 65,
1039 # ... and nowhere else
1040 self.pg1.get_capture(0, timeout=0.1)
1041 self.pg1.assert_nothing_captured(remark="Flood onto other VMS")
1043 pkt_intra_epg_221_to_uplink = (Ether(src=self.pg2.remote_mac,
1044 dst="00:00:00:33:44:66") /
1045 IP(src=eps[0].ip4.address,
1047 UDP(sport=1234, dport=1234) /
1050 self.send_and_expect_bridged(eps[2].itf,
1051 pkt_intra_epg_221_to_uplink * 65,
1055 # Packets from the uplink are forwarded in the absence of a contract
1057 pkt_intra_epg_220_from_uplink = (Ether(src="00:00:00:33:44:55",
1058 dst=self.pg0.remote_mac) /
1059 IP(src=eps[0].ip4.address,
1061 UDP(sport=1234, dport=1234) /
1064 self.send_and_expect_bridged(self.pg4,
1065 pkt_intra_epg_220_from_uplink * 65,
1069 # in the absence of policy, endpoints in the same EPG
1072 pkt_intra_epg = (Ether(src=self.pg0.remote_mac,
1073 dst=self.pg1.remote_mac) /
1074 IP(src=eps[0].ip4.address,
1075 dst=eps[1].ip4.address) /
1076 UDP(sport=1234, dport=1234) /
1079 self.send_and_expect_bridged(self.pg0, pkt_intra_epg * 65, self.pg1)
1082 # in the absence of policy, endpoints in the different EPG
1083 # cannot communicate
1085 pkt_inter_epg_220_to_221 = (Ether(src=self.pg0.remote_mac,
1086 dst=self.pg2.remote_mac) /
1087 IP(src=eps[0].ip4.address,
1088 dst=eps[2].ip4.address) /
1089 UDP(sport=1234, dport=1234) /
1091 pkt_inter_epg_221_to_220 = (Ether(src=self.pg2.remote_mac,
1092 dst=self.pg0.remote_mac) /
1093 IP(src=eps[2].ip4.address,
1094 dst=eps[0].ip4.address) /
1095 UDP(sport=1234, dport=1234) /
1097 pkt_inter_epg_220_to_222 = (Ether(src=self.pg0.remote_mac,
1098 dst=str(self.router_mac)) /
1099 IP(src=eps[0].ip4.address,
1100 dst=eps[3].ip4.address) /
1101 UDP(sport=1234, dport=1234) /
1104 self.send_and_assert_no_replies(eps[0].itf,
1105 pkt_inter_epg_220_to_221 * 65)
1106 self.send_and_assert_no_replies(eps[0].itf,
1107 pkt_inter_epg_220_to_222 * 65)
1110 # A uni-directional contract from EPG 220 -> 221
1112 acl = VppGbpAcl(self)
1113 rule = acl.create_rule(permit_deny=1, proto=17)
1114 rule2 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
1115 acl_index = acl.add_vpp_config([rule, rule2])
1116 c1 = VppGbpContract(
1117 self, epgs[0].sclass, epgs[1].sclass, acl_index,
1118 [VppGbpContractRule(
1119 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1122 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1124 [ETH_P_IP, ETH_P_IPV6])
1127 self.send_and_expect_bridged(eps[0].itf,
1128 pkt_inter_epg_220_to_221 * 65,
1130 self.send_and_assert_no_replies(eps[0].itf,
1131 pkt_inter_epg_220_to_222 * 65)
1134 # contract for the return direction
1136 c2 = VppGbpContract(
1137 self, epgs[1].sclass, epgs[0].sclass, acl_index,
1138 [VppGbpContractRule(
1139 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1142 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1144 [ETH_P_IP, ETH_P_IPV6])
1147 self.send_and_expect_bridged(eps[0].itf,
1148 pkt_inter_epg_220_to_221 * 65,
1150 self.send_and_expect_bridged(eps[2].itf,
1151 pkt_inter_epg_221_to_220 * 65,
1155 # the contract does not allow non-IP
1157 pkt_non_ip_inter_epg_220_to_221 = (Ether(src=self.pg0.remote_mac,
1158 dst=self.pg2.remote_mac) /
1160 self.send_and_assert_no_replies(eps[0].itf,
1161 pkt_non_ip_inter_epg_220_to_221 * 17)
1164 # check that inter group is still disabled for the groups
1165 # not in the contract.
1167 self.send_and_assert_no_replies(eps[0].itf,
1168 pkt_inter_epg_220_to_222 * 65)
1171 # A uni-directional contract from EPG 220 -> 222 'L3 routed'
1173 c3 = VppGbpContract(
1174 self, epgs[0].sclass, epgs[2].sclass, acl_index,
1175 [VppGbpContractRule(
1176 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1179 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1181 [ETH_P_IP, ETH_P_IPV6])
1184 self.logger.info(self.vapi.cli("sh gbp contract"))
1186 self.send_and_expect_routed(eps[0].itf,
1187 pkt_inter_epg_220_to_222 * 65,
1189 str(self.router_mac))
1192 # remove both contracts, traffic stops in both directions
1194 c2.remove_vpp_config()
1195 c1.remove_vpp_config()
1196 c3.remove_vpp_config()
1197 acl.remove_vpp_config()
1199 self.send_and_assert_no_replies(eps[2].itf,
1200 pkt_inter_epg_221_to_220 * 65)
1201 self.send_and_assert_no_replies(eps[0].itf,
1202 pkt_inter_epg_220_to_221 * 65)
1203 self.send_and_expect_bridged(eps[0].itf,
1208 # EPs to the outside world
1211 # in the EP's RD an external subnet via the NAT EPG's recirc
1213 self, rd0, "0.0.0.0", 0,
1214 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1215 sw_if_index=recirc_nat.recirc.sw_if_index,
1216 sclass=epg_nat.sclass)
1218 self, rd0, "11.0.0.0", 8,
1219 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1220 sw_if_index=recirc_nat.recirc.sw_if_index,
1221 sclass=epg_nat.sclass)
1222 se16 = VppGbpSubnet(
1224 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1225 sw_if_index=recirc_nat.recirc.sw_if_index,
1226 sclass=epg_nat.sclass)
1227 # in the NAT RD an external subnet via the NAT EPG's uplink
1229 self, rd20, "0.0.0.0", 0,
1230 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1231 sw_if_index=epg_nat.uplink.sw_if_index,
1232 sclass=epg_nat.sclass)
1233 se36 = VppGbpSubnet(
1234 self, rd20, "::", 0,
1235 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1236 sw_if_index=epg_nat.uplink.sw_if_index,
1237 sclass=epg_nat.sclass)
1239 self, rd20, "11.0.0.0", 8,
1240 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1241 sw_if_index=epg_nat.uplink.sw_if_index,
1242 sclass=epg_nat.sclass)
1243 se1.add_vpp_config()
1244 se2.add_vpp_config()
1245 se16.add_vpp_config()
1246 se3.add_vpp_config()
1247 se36.add_vpp_config()
1248 se4.add_vpp_config()
1250 self.logger.info(self.vapi.cli("sh ip fib 0.0.0.0/0"))
1251 self.logger.info(self.vapi.cli("sh ip fib 11.0.0.1"))
1252 self.logger.info(self.vapi.cli("sh ip6 fib ::/0"))
1253 self.logger.info(self.vapi.cli("sh ip6 fib %s" %
1257 # From an EP to an outside address: IN2OUT
1259 pkt_inter_epg_220_to_global = (Ether(src=self.pg0.remote_mac,
1260 dst=str(self.router_mac)) /
1261 IP(src=eps[0].ip4.address,
1263 UDP(sport=1234, dport=1234) /
1267 self.send_and_assert_no_replies(eps[0].itf,
1268 pkt_inter_epg_220_to_global * 65)
1270 acl2 = VppGbpAcl(self)
1271 rule = acl2.create_rule(permit_deny=1, proto=17, sport_from=1234,
1272 sport_to=1234, dport_from=1234, dport_to=1234)
1273 rule2 = acl2.create_rule(is_ipv6=1, permit_deny=1, proto=17,
1274 sport_from=1234, sport_to=1234,
1275 dport_from=1234, dport_to=1234)
1277 acl_index2 = acl2.add_vpp_config([rule, rule2])
1278 c4 = VppGbpContract(
1279 self, epgs[0].sclass, epgs[3].sclass, acl_index2,
1280 [VppGbpContractRule(
1281 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1284 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1286 [ETH_P_IP, ETH_P_IPV6])
1289 self.send_and_expect_natted(eps[0].itf,
1290 pkt_inter_epg_220_to_global * 65,
1292 eps[0].fip4.address)
1294 pkt_inter_epg_220_to_global = (Ether(src=self.pg0.remote_mac,
1295 dst=str(self.router_mac)) /
1296 IPv6(src=eps[0].ip6.address,
1298 UDP(sport=1234, dport=1234) /
1301 self.send_and_expect_natted6(self.pg0,
1302 pkt_inter_epg_220_to_global * 65,
1304 eps[0].fip6.address)
1307 # From a global address to an EP: OUT2IN
1309 pkt_inter_epg_220_from_global = (Ether(src=str(self.router_mac),
1310 dst=self.pg0.remote_mac) /
1311 IP(dst=eps[0].fip4.address,
1313 UDP(sport=1234, dport=1234) /
1316 self.send_and_assert_no_replies(self.pg7,
1317 pkt_inter_epg_220_from_global * 65)
1319 c5 = VppGbpContract(
1320 self, epgs[3].sclass, epgs[0].sclass, acl_index2,
1321 [VppGbpContractRule(
1322 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1325 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1327 [ETH_P_IP, ETH_P_IPV6])
1330 self.send_and_expect_unnatted(self.pg7,
1331 pkt_inter_epg_220_from_global * 65,
1335 pkt_inter_epg_220_from_global = (Ether(src=str(self.router_mac),
1336 dst=self.pg0.remote_mac) /
1337 IPv6(dst=eps[0].fip6.address,
1339 UDP(sport=1234, dport=1234) /
1342 self.send_and_expect_unnatted6(self.pg7,
1343 pkt_inter_epg_220_from_global * 65,
1348 # From a local VM to another local VM using resp. public addresses:
1351 pkt_intra_epg_220_global = (Ether(src=self.pg0.remote_mac,
1352 dst=str(self.router_mac)) /
1353 IP(src=eps[0].ip4.address,
1354 dst=eps[1].fip4.address) /
1355 UDP(sport=1234, dport=1234) /
1358 self.send_and_expect_double_natted(eps[0].itf,
1359 pkt_intra_epg_220_global * 65,
1361 eps[0].fip4.address,
1364 pkt_intra_epg_220_global = (Ether(src=self.pg0.remote_mac,
1365 dst=str(self.router_mac)) /
1366 IPv6(src=eps[0].ip6.address,
1367 dst=eps[1].fip6.address) /
1368 UDP(sport=1234, dport=1234) /
1371 self.send_and_expect_double_natted6(eps[0].itf,
1372 pkt_intra_epg_220_global * 65,
1374 eps[0].fip6.address,
1381 # del static mappings for each EP from the 10/8 to 11/8 network
1382 self.vapi.nat44_add_del_static_mapping(ep.ip4.bytes,
1387 self.vapi.nat66_add_del_static_mapping(ep.ip6.bytes,
1393 # IP config on the BVI interfaces
1394 if epg != epgs[0] and epg != epgs[3]:
1395 self.vapi.nat44_interface_add_del_feature(epg.bvi.sw_if_index,
1398 self.vapi.nat66_add_del_interface(epg.bvi.sw_if_index,
1402 for recirc in recircs:
1403 self.vapi.nat44_interface_add_del_feature(
1404 recirc.recirc.sw_if_index,
1407 self.vapi.nat66_add_del_interface(
1408 recirc.recirc.sw_if_index,
1412 def wait_for_ep_timeout(self, sw_if_index=None, ip=None, mac=None,
1413 n_tries=100, s_time=1):
1415 if not find_gbp_endpoint(self, sw_if_index, ip, mac):
1417 n_tries = n_tries - 1
1419 self.assertFalse(find_gbp_endpoint(self, sw_if_index, ip, mac))
1422 def test_gbp_learn_l2(self):
1423 """ GBP L2 Endpoint Learning """
1425 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
1426 learnt = [{'mac': '00:00:11:11:11:01',
1428 'ip6': '2001:10::2'},
1429 {'mac': '00:00:11:11:11:02',
1431 'ip6': '2001:10::3'}]
1436 gt4 = VppIpTable(self, 1)
1437 gt4.add_vpp_config()
1438 gt6 = VppIpTable(self, 1, is_ip6=True)
1439 gt6.add_vpp_config()
1441 rd1 = VppGbpRouteDomain(self, 1, gt4, gt6)
1442 rd1.add_vpp_config()
1445 # Pg2 hosts the vxlan tunnel, hosts on pg2 to act as TEPs
1446 # Pg3 hosts the IP4 UU-flood VXLAN tunnel
1447 # Pg4 hosts the IP6 UU-flood VXLAN tunnel
1449 self.pg2.config_ip4()
1450 self.pg2.resolve_arp()
1451 self.pg2.generate_remote_hosts(4)
1452 self.pg2.configure_ipv4_neighbors()
1453 self.pg3.config_ip4()
1454 self.pg3.resolve_arp()
1455 self.pg4.config_ip4()
1456 self.pg4.resolve_arp()
1459 # Add a mcast destination VXLAN-GBP tunnel for B&M traffic
1461 tun_bm = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
1464 tun_bm.add_vpp_config()
1467 # a GBP bridge domain with a BVI and a UU-flood interface
1469 bd1 = VppBridgeDomain(self, 1)
1470 bd1.add_vpp_config()
1471 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0, self.pg3, tun_bm)
1472 gbd1.add_vpp_config()
1474 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1475 self.logger.info(self.vapi.cli("sh gbp bridge"))
1477 # ... and has a /32 applied
1478 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
1479 ip_addr.add_vpp_config()
1482 # The Endpoint-group in which we are learning endpoints
1484 epg_220 = VppGbpEndpointGroup(self, 220, 112, rd1, gbd1,
1488 VppGbpEndpointRetention(2))
1489 epg_220.add_vpp_config()
1490 epg_330 = VppGbpEndpointGroup(self, 330, 113, rd1, gbd1,
1494 VppGbpEndpointRetention(2))
1495 epg_330.add_vpp_config()
1498 # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
1501 vx_tun_l2_1 = VppGbpVxlanTunnel(
1502 self, 99, bd1.bd_id,
1503 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L2,
1505 vx_tun_l2_1.add_vpp_config()
1508 # A static endpoint that the learnt endpoints are trying to
1511 ep = VppGbpEndpoint(self, self.pg0,
1513 "10.0.0.127", "11.0.0.127",
1514 "2001:10::1", "3001::1")
1517 self.assertTrue(find_route(self, ep.ip4.address, 32, table_id=1))
1519 # a packet with an sclass from an unknown EPG
1520 p = (Ether(src=self.pg2.remote_mac,
1521 dst=self.pg2.local_mac) /
1522 IP(src=self.pg2.remote_hosts[0].ip4,
1523 dst=self.pg2.local_ip4) /
1524 UDP(sport=1234, dport=48879) /
1525 VXLAN(vni=99, gpid=88, flags=0x88) /
1526 Ether(src=learnt[0]["mac"], dst=ep.mac) /
1527 IP(src=learnt[0]["ip"], dst=ep.ip4.address) /
1528 UDP(sport=1234, dport=1234) /
1531 self.send_and_assert_no_replies(self.pg2, p)
1534 # we should not have learnt a new tunnel endpoint, since
1535 # the EPG was not learnt.
1537 self.assertEqual(INDEX_INVALID,
1538 find_vxlan_gbp_tunnel(self,
1540 self.pg2.remote_hosts[0].ip4,
1543 # epg is not learnt, because the EPG is unknwon
1544 self.assertEqual(len(self.vapi.gbp_endpoint_dump()), 1)
1547 # Learn new EPs from IP packets
1549 for ii, l in enumerate(learnt):
1550 # a packet with an sclass from a known EPG
1551 # arriving on an unknown TEP
1552 p = (Ether(src=self.pg2.remote_mac,
1553 dst=self.pg2.local_mac) /
1554 IP(src=self.pg2.remote_hosts[1].ip4,
1555 dst=self.pg2.local_ip4) /
1556 UDP(sport=1234, dport=48879) /
1557 VXLAN(vni=99, gpid=112, flags=0x88) /
1558 Ether(src=l['mac'], dst=ep.mac) /
1559 IP(src=l['ip'], dst=ep.ip4.address) /
1560 UDP(sport=1234, dport=1234) /
1563 rx = self.send_and_expect(self.pg2, [p], self.pg0)
1566 tep1_sw_if_index = find_vxlan_gbp_tunnel(
1569 self.pg2.remote_hosts[1].ip4,
1571 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
1574 # the EP is learnt via the learnt TEP
1575 # both from its MAC and its IP
1577 self.assertTrue(find_gbp_endpoint(self,
1578 vx_tun_l2_1.sw_if_index,
1580 self.assertTrue(find_gbp_endpoint(self,
1581 vx_tun_l2_1.sw_if_index,
1584 self.logger.info(self.vapi.cli("show gbp endpoint"))
1585 self.logger.info(self.vapi.cli("show gbp vxlan"))
1586 self.logger.info(self.vapi.cli("show ip mfib"))
1589 # If we sleep for the threshold time, the learnt endpoints should
1593 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1597 # Learn new EPs from GARP packets received on the BD's mcast tunnel
1599 for ii, l in enumerate(learnt):
1600 # a packet with an sclass from a known EPG
1601 # arriving on an unknown TEP
1602 p = (Ether(src=self.pg2.remote_mac,
1603 dst=self.pg2.local_mac) /
1604 IP(src=self.pg2.remote_hosts[1].ip4,
1606 UDP(sport=1234, dport=48879) /
1607 VXLAN(vni=88, gpid=112, flags=0x88) /
1608 Ether(src=l['mac'], dst="ff:ff:ff:ff:ff:ff") /
1610 psrc=l['ip'], pdst=l['ip'],
1611 hwsrc=l['mac'], hwdst="ff:ff:ff:ff:ff:ff"))
1613 rx = self.send_and_expect(self.pg4, [p], self.pg0)
1616 tep1_sw_if_index = find_vxlan_gbp_tunnel(
1619 self.pg2.remote_hosts[1].ip4,
1621 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
1624 # the EP is learnt via the learnt TEP
1625 # both from its MAC and its IP
1627 self.assertTrue(find_gbp_endpoint(self,
1628 vx_tun_l2_1.sw_if_index,
1630 self.assertTrue(find_gbp_endpoint(self,
1631 vx_tun_l2_1.sw_if_index,
1635 # wait for the learnt endpoints to age out
1638 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1642 # Learn new EPs from L2 packets
1644 for ii, l in enumerate(learnt):
1645 # a packet with an sclass from a known EPG
1646 # arriving on an unknown TEP
1647 p = (Ether(src=self.pg2.remote_mac,
1648 dst=self.pg2.local_mac) /
1649 IP(src=self.pg2.remote_hosts[1].ip4,
1650 dst=self.pg2.local_ip4) /
1651 UDP(sport=1234, dport=48879) /
1652 VXLAN(vni=99, gpid=112, flags=0x88) /
1653 Ether(src=l['mac'], dst=ep.mac) /
1656 rx = self.send_and_expect(self.pg2, [p], self.pg0)
1659 tep1_sw_if_index = find_vxlan_gbp_tunnel(
1662 self.pg2.remote_hosts[1].ip4,
1664 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
1667 # the EP is learnt via the learnt TEP
1668 # both from its MAC and its IP
1670 self.assertTrue(find_gbp_endpoint(self,
1671 vx_tun_l2_1.sw_if_index,
1674 self.logger.info(self.vapi.cli("show gbp endpoint"))
1675 self.logger.info(self.vapi.cli("show gbp vxlan"))
1676 self.logger.info(self.vapi.cli("show vxlan-gbp tunnel"))
1679 # wait for the learnt endpoints to age out
1682 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1686 # repeat. the do not learn bit is set so the EPs are not learnt
1689 # a packet with an sclass from a known EPG
1690 p = (Ether(src=self.pg2.remote_mac,
1691 dst=self.pg2.local_mac) /
1692 IP(src=self.pg2.remote_hosts[1].ip4,
1693 dst=self.pg2.local_ip4) /
1694 UDP(sport=1234, dport=48879) /
1695 VXLAN(vni=99, gpid=112, flags=0x88, gpflags="D") /
1696 Ether(src=l['mac'], dst=ep.mac) /
1697 IP(src=l['ip'], dst=ep.ip4.address) /
1698 UDP(sport=1234, dport=1234) /
1701 rx = self.send_and_expect(self.pg2, p*65, self.pg0)
1704 self.assertFalse(find_gbp_endpoint(self,
1705 vx_tun_l2_1.sw_if_index,
1712 # a packet with an sclass from a known EPG
1713 p = (Ether(src=self.pg2.remote_mac,
1714 dst=self.pg2.local_mac) /
1715 IP(src=self.pg2.remote_hosts[1].ip4,
1716 dst=self.pg2.local_ip4) /
1717 UDP(sport=1234, dport=48879) /
1718 VXLAN(vni=99, gpid=112, flags=0x88) /
1719 Ether(src=l['mac'], dst=ep.mac) /
1720 IP(src=l['ip'], dst=ep.ip4.address) /
1721 UDP(sport=1234, dport=1234) /
1724 rx = self.send_and_expect(self.pg2, p*65, self.pg0)
1726 self.assertTrue(find_gbp_endpoint(self,
1727 vx_tun_l2_1.sw_if_index,
1731 # Static EP replies to dynamics
1733 self.logger.info(self.vapi.cli("sh l2fib bd_id 1"))
1735 p = (Ether(src=ep.mac, dst=l['mac']) /
1736 IP(dst=l['ip'], src=ep.ip4.address) /
1737 UDP(sport=1234, dport=1234) /
1740 rxs = self.send_and_expect(self.pg0, p * 17, self.pg2)
1743 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
1744 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
1745 self.assertEqual(rx[UDP].dport, 48879)
1746 # the UDP source port is a random value for hashing
1747 self.assertEqual(rx[VXLAN].gpid, 112)
1748 self.assertEqual(rx[VXLAN].vni, 99)
1749 self.assertTrue(rx[VXLAN].flags.G)
1750 self.assertTrue(rx[VXLAN].flags.Instance)
1751 self.assertTrue(rx[VXLAN].gpflags.A)
1752 self.assertFalse(rx[VXLAN].gpflags.D)
1755 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1759 # repeat in the other EPG
1760 # there's no contract between 220 and 330, but the A-bit is set
1761 # so the packet is cleared for delivery
1764 # a packet with an sclass from a known EPG
1765 p = (Ether(src=self.pg2.remote_mac,
1766 dst=self.pg2.local_mac) /
1767 IP(src=self.pg2.remote_hosts[1].ip4,
1768 dst=self.pg2.local_ip4) /
1769 UDP(sport=1234, dport=48879) /
1770 VXLAN(vni=99, gpid=113, flags=0x88, gpflags='A') /
1771 Ether(src=l['mac'], dst=ep.mac) /
1772 IP(src=l['ip'], dst=ep.ip4.address) /
1773 UDP(sport=1234, dport=1234) /
1776 rx = self.send_and_expect(self.pg2, p*65, self.pg0)
1778 self.assertTrue(find_gbp_endpoint(self,
1779 vx_tun_l2_1.sw_if_index,
1783 # static EP cannot reach the learnt EPs since there is no contract
1784 # only test 1 EP as the others could timeout
1786 p = (Ether(src=ep.mac, dst=l['mac']) /
1787 IP(dst=learnt[0]['ip'], src=ep.ip4.address) /
1788 UDP(sport=1234, dport=1234) /
1791 self.send_and_assert_no_replies(self.pg0, [p])
1794 # refresh the entries after the check for no replies above
1797 # a packet with an sclass from a known EPG
1798 p = (Ether(src=self.pg2.remote_mac,
1799 dst=self.pg2.local_mac) /
1800 IP(src=self.pg2.remote_hosts[1].ip4,
1801 dst=self.pg2.local_ip4) /
1802 UDP(sport=1234, dport=48879) /
1803 VXLAN(vni=99, gpid=113, flags=0x88, gpflags='A') /
1804 Ether(src=l['mac'], dst=ep.mac) /
1805 IP(src=l['ip'], dst=ep.ip4.address) /
1806 UDP(sport=1234, dport=1234) /
1809 rx = self.send_and_expect(self.pg2, p*65, self.pg0)
1811 self.assertTrue(find_gbp_endpoint(self,
1812 vx_tun_l2_1.sw_if_index,
1816 # Add the contract so they can talk
1818 acl = VppGbpAcl(self)
1819 rule = acl.create_rule(permit_deny=1, proto=17)
1820 rule2 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
1821 acl_index = acl.add_vpp_config([rule, rule2])
1822 c1 = VppGbpContract(
1823 self, epg_220.sclass, epg_330.sclass, acl_index,
1824 [VppGbpContractRule(
1825 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1828 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1830 [ETH_P_IP, ETH_P_IPV6])
1834 p = (Ether(src=ep.mac, dst=l['mac']) /
1835 IP(dst=l['ip'], src=ep.ip4.address) /
1836 UDP(sport=1234, dport=1234) /
1839 self.send_and_expect(self.pg0, [p], self.pg2)
1842 # send UU packets from the local EP
1844 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1845 self.logger.info(self.vapi.cli("sh gbp bridge"))
1846 p_uu = (Ether(src=ep.mac, dst="00:11:11:11:11:11") /
1847 IP(dst="10.0.0.133", src=ep.ip4.address) /
1848 UDP(sport=1234, dport=1234) /
1850 rxs = self.send_and_expect(ep.itf, [p_uu], gbd1.uu_fwd)
1852 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1854 p_bm = (Ether(src=ep.mac, dst="ff:ff:ff:ff:ff:ff") /
1855 IP(dst="10.0.0.133", src=ep.ip4.address) /
1856 UDP(sport=1234, dport=1234) /
1858 rxs = self.send_and_expect_only(ep.itf, [p_bm], tun_bm.mcast_itf)
1861 self.assertEqual(rx[IP].src, self.pg4.local_ip4)
1862 self.assertEqual(rx[IP].dst, "239.1.1.1")
1863 self.assertEqual(rx[UDP].dport, 48879)
1864 # the UDP source port is a random value for hashing
1865 self.assertEqual(rx[VXLAN].gpid, 112)
1866 self.assertEqual(rx[VXLAN].vni, 88)
1867 self.assertTrue(rx[VXLAN].flags.G)
1868 self.assertTrue(rx[VXLAN].flags.Instance)
1869 self.assertFalse(rx[VXLAN].gpflags.A)
1870 self.assertFalse(rx[VXLAN].gpflags.D)
1873 # Check v6 Endpoints
1876 # a packet with an sclass from a known EPG
1877 p = (Ether(src=self.pg2.remote_mac,
1878 dst=self.pg2.local_mac) /
1879 IP(src=self.pg2.remote_hosts[1].ip4,
1880 dst=self.pg2.local_ip4) /
1881 UDP(sport=1234, dport=48879) /
1882 VXLAN(vni=99, gpid=113, flags=0x88, gpflags='A') /
1883 Ether(src=l['mac'], dst=ep.mac) /
1884 IPv6(src=l['ip6'], dst=ep.ip6.address) /
1885 UDP(sport=1234, dport=1234) /
1888 rx = self.send_and_expect(self.pg2, p*65, self.pg0)
1890 self.assertTrue(find_gbp_endpoint(self,
1891 vx_tun_l2_1.sw_if_index,
1895 # L3 Endpoint Learning
1896 # - configured on the bridge's BVI
1903 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1906 self.pg2.unconfig_ip4()
1907 self.pg3.unconfig_ip4()
1908 self.pg4.unconfig_ip4()
1910 self.logger.info(self.vapi.cli("sh int"))
1911 self.logger.info(self.vapi.cli("sh gbp vxlan"))
1913 def test_gbp_learn_vlan_l2(self):
1914 """ GBP L2 Endpoint w/ VLANs"""
1916 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
1917 learnt = [{'mac': '00:00:11:11:11:01',
1919 'ip6': '2001:10::2'},
1920 {'mac': '00:00:11:11:11:02',
1922 'ip6': '2001:10::3'}]
1927 gt4 = VppIpTable(self, 1)
1928 gt4.add_vpp_config()
1929 gt6 = VppIpTable(self, 1, is_ip6=True)
1930 gt6.add_vpp_config()
1932 rd1 = VppGbpRouteDomain(self, 1, gt4, gt6)
1933 rd1.add_vpp_config()
1936 # Pg2 hosts the vxlan tunnel, hosts on pg2 to act as TEPs
1938 self.pg2.config_ip4()
1939 self.pg2.resolve_arp()
1940 self.pg2.generate_remote_hosts(4)
1941 self.pg2.configure_ipv4_neighbors()
1942 self.pg3.config_ip4()
1943 self.pg3.resolve_arp()
1946 # The EP will be on a vlan sub-interface
1948 vlan_11 = VppDot1QSubint(self, self.pg0, 11)
1950 self.vapi.l2_interface_vlan_tag_rewrite(
1951 sw_if_index=vlan_11.sw_if_index, vtr_op=L2_VTR_OP.L2_POP_1,
1954 bd_uu_fwd = VppVxlanGbpTunnel(self, self.pg3.local_ip4,
1955 self.pg3.remote_ip4, 116)
1956 bd_uu_fwd.add_vpp_config()
1959 # a GBP bridge domain with a BVI and a UU-flood interface
1960 # The BD is marked as do not learn, so no endpoints are ever
1961 # learnt in this BD.
1963 bd1 = VppBridgeDomain(self, 1)
1964 bd1.add_vpp_config()
1965 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0, bd_uu_fwd,
1967 gbd1.add_vpp_config()
1969 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1970 self.logger.info(self.vapi.cli("sh gbp bridge"))
1972 # ... and has a /32 applied
1973 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
1974 ip_addr.add_vpp_config()
1977 # The Endpoint-group in which we are learning endpoints
1979 epg_220 = VppGbpEndpointGroup(self, 220, 441, rd1, gbd1,
1983 VppGbpEndpointRetention(2))
1984 epg_220.add_vpp_config()
1987 # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
1990 vx_tun_l2_1 = VppGbpVxlanTunnel(
1991 self, 99, bd1.bd_id,
1992 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L2,
1994 vx_tun_l2_1.add_vpp_config()
1997 # A static endpoint that the learnt endpoints are trying to
2000 ep = VppGbpEndpoint(self, vlan_11,
2002 "10.0.0.127", "11.0.0.127",
2003 "2001:10::1", "3001::1")
2006 self.assertTrue(find_route(self, ep.ip4.address, 32, table_id=1))
2009 # Send to the static EP
2011 for ii, l in enumerate(learnt):
2012 # a packet with an sclass from a known EPG
2013 # arriving on an unknown TEP
2014 p = (Ether(src=self.pg2.remote_mac,
2015 dst=self.pg2.local_mac) /
2016 IP(src=self.pg2.remote_hosts[1].ip4,
2017 dst=self.pg2.local_ip4) /
2018 UDP(sport=1234, dport=48879) /
2019 VXLAN(vni=99, gpid=441, flags=0x88) /
2020 Ether(src=l['mac'], dst=ep.mac) /
2021 IP(src=l['ip'], dst=ep.ip4.address) /
2022 UDP(sport=1234, dport=1234) /
2025 rxs = self.send_and_expect(self.pg2, [p], self.pg0)
2028 # packet to EP has the EP's vlan tag
2031 self.assertEqual(rx[Dot1Q].vlan, 11)
2034 # the EP is not learnt since the BD setting prevents it
2037 self.assertFalse(find_gbp_endpoint(self,
2038 vx_tun_l2_1.sw_if_index,
2040 self.assertEqual(INDEX_INVALID,
2041 find_vxlan_gbp_tunnel(
2044 self.pg2.remote_hosts[1].ip4,
2047 self.assertEqual(len(self.vapi.gbp_endpoint_dump()), 1)
2051 # we didn't learn the remotes so they are sent to the UU-fwd
2054 p = (Ether(src=ep.mac, dst=l['mac']) /
2056 IP(dst=l['ip'], src=ep.ip4.address) /
2057 UDP(sport=1234, dport=1234) /
2060 rxs = self.send_and_expect(self.pg0, p * 17, self.pg3)
2063 self.assertEqual(rx[IP].src, self.pg3.local_ip4)
2064 self.assertEqual(rx[IP].dst, self.pg3.remote_ip4)
2065 self.assertEqual(rx[UDP].dport, 48879)
2066 # the UDP source port is a random value for hashing
2067 self.assertEqual(rx[VXLAN].gpid, 441)
2068 self.assertEqual(rx[VXLAN].vni, 116)
2069 self.assertTrue(rx[VXLAN].flags.G)
2070 self.assertTrue(rx[VXLAN].flags.Instance)
2071 self.assertFalse(rx[VXLAN].gpflags.A)
2072 self.assertFalse(rx[VXLAN].gpflags.D)
2074 self.pg2.unconfig_ip4()
2075 self.pg3.unconfig_ip4()
2077 def test_gbp_learn_l3(self):
2078 """ GBP L3 Endpoint Learning """
2080 self.vapi.cli("set logging class gbp debug")
2082 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
2083 routed_dst_mac = "00:0c:0c:0c:0c:0c"
2084 routed_src_mac = "00:22:bd:f8:19:ff"
2086 learnt = [{'mac': '00:00:11:11:11:02',
2088 'ip6': '2001:10::2'},
2089 {'mac': '00:00:11:11:11:03',
2091 'ip6': '2001:10::3'}]
2096 t4 = VppIpTable(self, 1)
2098 t6 = VppIpTable(self, 1, True)
2101 tun_ip4_uu = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
2102 self.pg4.remote_ip4, 114)
2103 tun_ip6_uu = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
2104 self.pg4.remote_ip4, 116)
2105 tun_ip4_uu.add_vpp_config()
2106 tun_ip6_uu.add_vpp_config()
2108 rd1 = VppGbpRouteDomain(self, 2, t4, t6, tun_ip4_uu, tun_ip6_uu)
2109 rd1.add_vpp_config()
2111 self.loop0.set_mac(self.router_mac)
2114 # Bind the BVI to the RD
2116 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
2117 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
2120 # Pg2 hosts the vxlan tunnel
2121 # hosts on pg2 to act as TEPs
2125 self.pg2.config_ip4()
2126 self.pg2.resolve_arp()
2127 self.pg2.generate_remote_hosts(4)
2128 self.pg2.configure_ipv4_neighbors()
2129 self.pg3.config_ip4()
2130 self.pg3.resolve_arp()
2131 self.pg4.config_ip4()
2132 self.pg4.resolve_arp()
2135 # a GBP bridge domain with a BVI and a UU-flood interface
2137 bd1 = VppBridgeDomain(self, 1)
2138 bd1.add_vpp_config()
2139 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0, self.pg3)
2140 gbd1.add_vpp_config()
2142 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2143 self.logger.info(self.vapi.cli("sh gbp bridge"))
2144 self.logger.info(self.vapi.cli("sh gbp route"))
2146 # ... and has a /32 and /128 applied
2147 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2148 ip4_addr.add_vpp_config()
2149 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 128)
2150 ip6_addr.add_vpp_config()
2153 # The Endpoint-group in which we are learning endpoints
2155 epg_220 = VppGbpEndpointGroup(self, 220, 441, rd1, gbd1,
2159 VppGbpEndpointRetention(2))
2160 epg_220.add_vpp_config()
2163 # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
2166 vx_tun_l3 = VppGbpVxlanTunnel(
2167 self, 101, rd1.rd_id,
2168 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
2170 vx_tun_l3.add_vpp_config()
2173 # A static endpoint that the learnt endpoints are trying to
2176 ep = VppGbpEndpoint(self, self.pg0,
2178 "10.0.0.127", "11.0.0.127",
2179 "2001:10::1", "3001::1")
2183 # learn some remote IPv4 EPs
2185 for ii, l in enumerate(learnt):
2186 # a packet with an sclass from a known EPG
2187 # arriving on an unknown TEP
2188 p = (Ether(src=self.pg2.remote_mac,
2189 dst=self.pg2.local_mac) /
2190 IP(src=self.pg2.remote_hosts[1].ip4,
2191 dst=self.pg2.local_ip4) /
2192 UDP(sport=1234, dport=48879) /
2193 VXLAN(vni=101, gpid=441, flags=0x88) /
2194 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2195 IP(src=l['ip'], dst=ep.ip4.address) /
2196 UDP(sport=1234, dport=1234) /
2199 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2202 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2205 self.pg2.remote_hosts[1].ip4,
2207 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2209 # endpoint learnt via the parent GBP-vxlan interface
2210 self.assertTrue(find_gbp_endpoint(self,
2211 vx_tun_l3._sw_if_index,
2215 # Static IPv4 EP replies to learnt
2218 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2219 IP(dst=l['ip'], src=ep.ip4.address) /
2220 UDP(sport=1234, dport=1234) /
2223 rxs = self.send_and_expect(self.pg0, p*1, self.pg2)
2226 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2227 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2228 self.assertEqual(rx[UDP].dport, 48879)
2229 # the UDP source port is a random value for hashing
2230 self.assertEqual(rx[VXLAN].gpid, 441)
2231 self.assertEqual(rx[VXLAN].vni, 101)
2232 self.assertTrue(rx[VXLAN].flags.G)
2233 self.assertTrue(rx[VXLAN].flags.Instance)
2234 self.assertTrue(rx[VXLAN].gpflags.A)
2235 self.assertFalse(rx[VXLAN].gpflags.D)
2237 inner = rx[VXLAN].payload
2239 self.assertEqual(inner[Ether].src, routed_src_mac)
2240 self.assertEqual(inner[Ether].dst, routed_dst_mac)
2241 self.assertEqual(inner[IP].src, ep.ip4.address)
2242 self.assertEqual(inner[IP].dst, l['ip'])
2245 self.assertFalse(find_gbp_endpoint(self,
2250 # learn some remote IPv6 EPs
2252 for ii, l in enumerate(learnt):
2253 # a packet with an sclass from a known EPG
2254 # arriving on an unknown TEP
2255 p = (Ether(src=self.pg2.remote_mac,
2256 dst=self.pg2.local_mac) /
2257 IP(src=self.pg2.remote_hosts[1].ip4,
2258 dst=self.pg2.local_ip4) /
2259 UDP(sport=1234, dport=48879) /
2260 VXLAN(vni=101, gpid=441, flags=0x88) /
2261 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2262 IPv6(src=l['ip6'], dst=ep.ip6.address) /
2263 UDP(sport=1234, dport=1234) /
2266 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2269 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2272 self.pg2.remote_hosts[1].ip4,
2274 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2276 self.logger.info(self.vapi.cli("show gbp bridge"))
2277 self.logger.info(self.vapi.cli("show vxlan-gbp tunnel"))
2278 self.logger.info(self.vapi.cli("show gbp vxlan"))
2279 self.logger.info(self.vapi.cli("show int addr"))
2281 # endpoint learnt via the TEP
2282 self.assertTrue(find_gbp_endpoint(self, ip=l['ip6']))
2284 self.logger.info(self.vapi.cli("show gbp endpoint"))
2285 self.logger.info(self.vapi.cli("show ip fib index 1 %s" % l['ip']))
2288 # Static EP replies to learnt
2291 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2292 IPv6(dst=l['ip6'], src=ep.ip6.address) /
2293 UDP(sport=1234, dport=1234) /
2296 rxs = self.send_and_expect(self.pg0, p*65, self.pg2)
2299 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2300 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2301 self.assertEqual(rx[UDP].dport, 48879)
2302 # the UDP source port is a random value for hashing
2303 self.assertEqual(rx[VXLAN].gpid, 441)
2304 self.assertEqual(rx[VXLAN].vni, 101)
2305 self.assertTrue(rx[VXLAN].flags.G)
2306 self.assertTrue(rx[VXLAN].flags.Instance)
2307 self.assertTrue(rx[VXLAN].gpflags.A)
2308 self.assertFalse(rx[VXLAN].gpflags.D)
2310 inner = rx[VXLAN].payload
2312 self.assertEqual(inner[Ether].src, routed_src_mac)
2313 self.assertEqual(inner[Ether].dst, routed_dst_mac)
2314 self.assertEqual(inner[IPv6].src, ep.ip6.address)
2315 self.assertEqual(inner[IPv6].dst, l['ip6'])
2317 self.logger.info(self.vapi.cli("sh gbp endpoint"))
2319 self.wait_for_ep_timeout(ip=l['ip'])
2322 # Static sends to unknown EP with no route
2324 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2325 IP(dst="10.0.0.99", src=ep.ip4.address) /
2326 UDP(sport=1234, dport=1234) /
2329 self.send_and_assert_no_replies(self.pg0, [p])
2332 # Add a route to static EP's v4 and v6 subnet
2333 # packets should be sent on the v4/v6 uu=fwd interface resp.
2335 se_10_24 = VppGbpSubnet(
2336 self, rd1, "10.0.0.0", 24,
2337 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT)
2338 se_10_24.add_vpp_config()
2340 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2341 IP(dst="10.0.0.99", src=ep.ip4.address) /
2342 UDP(sport=1234, dport=1234) /
2345 rxs = self.send_and_expect(self.pg0, [p], self.pg4)
2347 self.assertEqual(rx[IP].src, self.pg4.local_ip4)
2348 self.assertEqual(rx[IP].dst, self.pg4.remote_ip4)
2349 self.assertEqual(rx[UDP].dport, 48879)
2350 # the UDP source port is a random value for hashing
2351 self.assertEqual(rx[VXLAN].gpid, 441)
2352 self.assertEqual(rx[VXLAN].vni, 114)
2353 self.assertTrue(rx[VXLAN].flags.G)
2354 self.assertTrue(rx[VXLAN].flags.Instance)
2355 # policy is not applied to packets sent to the uu-fwd interfaces
2356 self.assertFalse(rx[VXLAN].gpflags.A)
2357 self.assertFalse(rx[VXLAN].gpflags.D)
2360 # learn some remote IPv4 EPs
2362 for ii, l in enumerate(learnt):
2363 # a packet with an sclass from a known EPG
2364 # arriving on an unknown TEP
2365 p = (Ether(src=self.pg2.remote_mac,
2366 dst=self.pg2.local_mac) /
2367 IP(src=self.pg2.remote_hosts[2].ip4,
2368 dst=self.pg2.local_ip4) /
2369 UDP(sport=1234, dport=48879) /
2370 VXLAN(vni=101, gpid=441, flags=0x88) /
2371 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2372 IP(src=l['ip'], dst=ep.ip4.address) /
2373 UDP(sport=1234, dport=1234) /
2376 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2379 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2382 self.pg2.remote_hosts[2].ip4,
2384 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2386 # endpoint learnt via the parent GBP-vxlan interface
2387 self.assertTrue(find_gbp_endpoint(self,
2388 vx_tun_l3._sw_if_index,
2392 # Add a remote endpoint from the API
2394 rep_88 = VppGbpEndpoint(self, vx_tun_l3,
2396 "10.0.0.88", "11.0.0.88",
2397 "2001:10::88", "3001::88",
2398 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
2400 self.pg2.remote_hosts[1].ip4,
2402 rep_88.add_vpp_config()
2405 # Add a remote endpoint from the API that matches an existing one
2407 rep_2 = VppGbpEndpoint(self, vx_tun_l3,
2409 learnt[0]['ip'], "11.0.0.101",
2410 learnt[0]['ip6'], "3001::101",
2411 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
2413 self.pg2.remote_hosts[1].ip4,
2415 rep_2.add_vpp_config()
2418 # Add a route to the learned EP's v4 subnet
2419 # packets should be send on the v4/v6 uu=fwd interface resp.
2421 se_10_1_24 = VppGbpSubnet(
2422 self, rd1, "10.0.1.0", 24,
2423 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT)
2424 se_10_1_24.add_vpp_config()
2426 self.logger.info(self.vapi.cli("show gbp endpoint"))
2428 ips = ["10.0.0.88", learnt[0]['ip']]
2430 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2431 IP(dst=ip, src=ep.ip4.address) /
2432 UDP(sport=1234, dport=1234) /
2435 rxs = self.send_and_expect(self.pg0, p*65, self.pg2)
2438 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2439 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2440 self.assertEqual(rx[UDP].dport, 48879)
2441 # the UDP source port is a random value for hashing
2442 self.assertEqual(rx[VXLAN].gpid, 441)
2443 self.assertEqual(rx[VXLAN].vni, 101)
2444 self.assertTrue(rx[VXLAN].flags.G)
2445 self.assertTrue(rx[VXLAN].flags.Instance)
2446 self.assertTrue(rx[VXLAN].gpflags.A)
2447 self.assertFalse(rx[VXLAN].gpflags.D)
2449 inner = rx[VXLAN].payload
2451 self.assertEqual(inner[Ether].src, routed_src_mac)
2452 self.assertEqual(inner[Ether].dst, routed_dst_mac)
2453 self.assertEqual(inner[IP].src, ep.ip4.address)
2454 self.assertEqual(inner[IP].dst, ip)
2457 # remove the API remote EPs, only API sourced is gone, the DP
2458 # learnt one remains
2460 rep_88.remove_vpp_config()
2461 rep_2.remove_vpp_config()
2463 self.assertTrue(find_gbp_endpoint(self, ip=rep_2.ip4.address))
2465 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2466 IP(src=ep.ip4.address, dst=rep_2.ip4.address) /
2467 UDP(sport=1234, dport=1234) /
2469 rxs = self.send_and_expect(self.pg0, [p], self.pg2)
2471 self.assertFalse(find_gbp_endpoint(self, ip=rep_88.ip4.address))
2473 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2474 IP(src=ep.ip4.address, dst=rep_88.ip4.address) /
2475 UDP(sport=1234, dport=1234) /
2477 rxs = self.send_and_expect(self.pg0, [p], self.pg4)
2480 # to appease the testcase we cannot have the registered EP still
2481 # present (because it's DP learnt) when the TC ends so wait until
2484 self.wait_for_ep_timeout(ip=rep_88.ip4.address)
2485 self.wait_for_ep_timeout(ip=rep_2.ip4.address)
2488 # shutdown with learnt endpoint present
2490 p = (Ether(src=self.pg2.remote_mac,
2491 dst=self.pg2.local_mac) /
2492 IP(src=self.pg2.remote_hosts[1].ip4,
2493 dst=self.pg2.local_ip4) /
2494 UDP(sport=1234, dport=48879) /
2495 VXLAN(vni=101, gpid=441, flags=0x88) /
2496 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2497 IP(src=learnt[1]['ip'], dst=ep.ip4.address) /
2498 UDP(sport=1234, dport=1234) /
2501 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2503 # endpoint learnt via the parent GBP-vxlan interface
2504 self.assertTrue(find_gbp_endpoint(self,
2505 vx_tun_l3._sw_if_index,
2510 # remote endpoint becomes local
2512 self.pg2.unconfig_ip4()
2513 self.pg3.unconfig_ip4()
2514 self.pg4.unconfig_ip4()
2516 def test_gbp_redirect(self):
2517 """ GBP Endpoint Redirect """
2519 self.vapi.cli("set logging class gbp debug")
2521 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
2522 routed_dst_mac = "00:0c:0c:0c:0c:0c"
2523 routed_src_mac = "00:22:bd:f8:19:ff"
2525 learnt = [{'mac': '00:00:11:11:11:02',
2527 'ip6': '2001:10::2'},
2528 {'mac': '00:00:11:11:11:03',
2530 'ip6': '2001:10::3'}]
2535 t4 = VppIpTable(self, 1)
2537 t6 = VppIpTable(self, 1, True)
2540 rd1 = VppGbpRouteDomain(self, 2, t4, t6)
2541 rd1.add_vpp_config()
2543 self.loop0.set_mac(self.router_mac)
2546 # Bind the BVI to the RD
2548 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
2549 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
2552 # Pg7 hosts a BD's UU-fwd
2554 self.pg7.config_ip4()
2555 self.pg7.resolve_arp()
2558 # a GBP bridge domains for the EPs
2560 bd1 = VppBridgeDomain(self, 1)
2561 bd1.add_vpp_config()
2562 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0)
2563 gbd1.add_vpp_config()
2565 bd2 = VppBridgeDomain(self, 2)
2566 bd2.add_vpp_config()
2567 gbd2 = VppGbpBridgeDomain(self, bd2, self.loop1)
2568 gbd2.add_vpp_config()
2570 # ... and has a /32 and /128 applied
2571 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2572 ip4_addr.add_vpp_config()
2573 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 128)
2574 ip6_addr.add_vpp_config()
2575 ip4_addr = VppIpInterfaceAddress(self, gbd2.bvi, "10.0.1.128", 32)
2576 ip4_addr.add_vpp_config()
2577 ip6_addr = VppIpInterfaceAddress(self, gbd2.bvi, "2001:11::128", 128)
2578 ip6_addr.add_vpp_config()
2581 # The Endpoint-groups in which we are learning endpoints
2583 epg_220 = VppGbpEndpointGroup(self, 220, 440, rd1, gbd1,
2587 VppGbpEndpointRetention(2))
2588 epg_220.add_vpp_config()
2589 epg_221 = VppGbpEndpointGroup(self, 221, 441, rd1, gbd2,
2593 VppGbpEndpointRetention(2))
2594 epg_221.add_vpp_config()
2595 epg_222 = VppGbpEndpointGroup(self, 222, 442, rd1, gbd1,
2599 VppGbpEndpointRetention(2))
2600 epg_222.add_vpp_config()
2603 # a GBP bridge domains for the SEPs
2605 bd_uu1 = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
2606 self.pg7.remote_ip4, 116)
2607 bd_uu1.add_vpp_config()
2608 bd_uu2 = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
2609 self.pg7.remote_ip4, 117)
2610 bd_uu2.add_vpp_config()
2612 bd3 = VppBridgeDomain(self, 3)
2613 bd3.add_vpp_config()
2614 gbd3 = VppGbpBridgeDomain(self, bd3, self.loop2, bd_uu1, learn=False)
2615 gbd3.add_vpp_config()
2616 bd4 = VppBridgeDomain(self, 4)
2617 bd4.add_vpp_config()
2618 gbd4 = VppGbpBridgeDomain(self, bd4, self.loop3, bd_uu2, learn=False)
2619 gbd4.add_vpp_config()
2622 # EPGs in which the service endpoints exist
2624 epg_320 = VppGbpEndpointGroup(self, 320, 550, rd1, gbd3,
2628 VppGbpEndpointRetention(2))
2629 epg_320.add_vpp_config()
2630 epg_321 = VppGbpEndpointGroup(self, 321, 551, rd1, gbd4,
2634 VppGbpEndpointRetention(2))
2635 epg_321.add_vpp_config()
2638 # three local endpoints
2640 ep1 = VppGbpEndpoint(self, self.pg0,
2642 "10.0.0.1", "11.0.0.1",
2643 "2001:10::1", "3001:10::1")
2644 ep1.add_vpp_config()
2645 ep2 = VppGbpEndpoint(self, self.pg1,
2647 "10.0.1.1", "11.0.1.1",
2648 "2001:11::1", "3001:11::1")
2649 ep2.add_vpp_config()
2650 ep3 = VppGbpEndpoint(self, self.pg2,
2652 "10.0.2.2", "11.0.2.2",
2653 "2001:12::1", "3001:12::1")
2654 ep3.add_vpp_config()
2659 sep1 = VppGbpEndpoint(self, self.pg3,
2661 "12.0.0.1", "13.0.0.1",
2662 "4001:10::1", "5001:10::1")
2663 sep1.add_vpp_config()
2664 sep2 = VppGbpEndpoint(self, self.pg4,
2666 "12.0.0.2", "13.0.0.2",
2667 "4001:10::2", "5001:10::2")
2668 sep2.add_vpp_config()
2669 sep3 = VppGbpEndpoint(self, self.pg5,
2671 "12.0.1.1", "13.0.1.1",
2672 "4001:11::1", "5001:11::1")
2673 sep3.add_vpp_config()
2674 # this EP is not installed immediately
2675 sep4 = VppGbpEndpoint(self, self.pg6,
2677 "12.0.1.2", "13.0.1.2",
2678 "4001:11::2", "5001:11::2")
2681 # an L2 switch packet between local EPs in different EPGs
2682 # different dest ports on each so the are LB hashed differently
2684 p4 = [(Ether(src=ep1.mac, dst=ep3.mac) /
2685 IP(src=ep1.ip4.address, dst=ep3.ip4.address) /
2686 UDP(sport=1234, dport=1234) /
2688 (Ether(src=ep3.mac, dst=ep1.mac) /
2689 IP(src=ep3.ip4.address, dst=ep1.ip4.address) /
2690 UDP(sport=1234, dport=1234) /
2692 p6 = [(Ether(src=ep1.mac, dst=ep3.mac) /
2693 IPv6(src=ep1.ip6.address, dst=ep3.ip6.address) /
2694 UDP(sport=1234, dport=1234) /
2696 (Ether(src=ep3.mac, dst=ep1.mac) /
2697 IPv6(src=ep3.ip6.address, dst=ep1.ip6.address) /
2698 UDP(sport=1234, dport=1230) /
2701 # should be dropped since no contract yet
2702 self.send_and_assert_no_replies(self.pg0, [p4[0]])
2703 self.send_and_assert_no_replies(self.pg0, [p6[0]])
2706 # Add a contract with a rule to load-balance redirect via SEP1 and SEP2
2707 # one of the next-hops is via an EP that is not known
2709 acl = VppGbpAcl(self)
2710 rule4 = acl.create_rule(permit_deny=1, proto=17)
2711 rule6 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
2712 acl_index = acl.add_vpp_config([rule4, rule6])
2715 # test the src-ip hash mode
2717 c1 = VppGbpContract(
2718 self, epg_220.sclass, epg_222.sclass, acl_index,
2719 [VppGbpContractRule(
2720 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2721 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2722 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
2723 sep1.ip4, sep1.epg.rd),
2724 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
2725 sep2.ip4, sep2.epg.rd)]),
2727 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2728 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2729 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
2730 sep3.ip6, sep3.epg.rd),
2731 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
2732 sep4.ip6, sep4.epg.rd)])],
2733 [ETH_P_IP, ETH_P_IPV6])
2736 c2 = VppGbpContract(
2737 self, epg_222.sclass, epg_220.sclass, acl_index,
2738 [VppGbpContractRule(
2739 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2740 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2741 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
2742 sep1.ip4, sep1.epg.rd),
2743 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
2744 sep2.ip4, sep2.epg.rd)]),
2746 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2747 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2748 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
2749 sep3.ip6, sep3.epg.rd),
2750 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
2751 sep4.ip6, sep4.epg.rd)])],
2752 [ETH_P_IP, ETH_P_IPV6])
2756 # send again with the contract preset, now packets arrive
2757 # at SEP1 or SEP2 depending on the hashing
2759 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
2762 self.assertEqual(rx[Ether].src, routed_src_mac)
2763 self.assertEqual(rx[Ether].dst, sep1.mac)
2764 self.assertEqual(rx[IP].src, ep1.ip4.address)
2765 self.assertEqual(rx[IP].dst, ep3.ip4.address)
2767 rxs = self.send_and_expect(self.pg2, p4[1] * 17, sep2.itf)
2770 self.assertEqual(rx[Ether].src, routed_src_mac)
2771 self.assertEqual(rx[Ether].dst, sep2.mac)
2772 self.assertEqual(rx[IP].src, ep3.ip4.address)
2773 self.assertEqual(rx[IP].dst, ep1.ip4.address)
2775 rxs = self.send_and_expect(self.pg0, p6[0] * 17, self.pg7)
2778 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
2779 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
2780 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
2781 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
2782 self.assertEqual(rx[VXLAN].vni, 117)
2783 self.assertTrue(rx[VXLAN].flags.G)
2784 self.assertTrue(rx[VXLAN].flags.Instance)
2785 # redirect policy has been applied
2786 self.assertTrue(rx[VXLAN].gpflags.A)
2787 self.assertFalse(rx[VXLAN].gpflags.D)
2789 inner = rx[VXLAN].payload
2791 self.assertEqual(inner[Ether].src, routed_src_mac)
2792 self.assertEqual(inner[Ether].dst, sep4.mac)
2793 self.assertEqual(inner[IPv6].src, ep1.ip6.address)
2794 self.assertEqual(inner[IPv6].dst, ep3.ip6.address)
2796 rxs = self.send_and_expect(self.pg2, p6[1] * 17, sep3.itf)
2799 self.assertEqual(rx[Ether].src, routed_src_mac)
2800 self.assertEqual(rx[Ether].dst, sep3.mac)
2801 self.assertEqual(rx[IPv6].src, ep3.ip6.address)
2802 self.assertEqual(rx[IPv6].dst, ep1.ip6.address)
2805 # programme the unknown EP
2807 sep4.add_vpp_config()
2809 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep4.itf)
2812 self.assertEqual(rx[Ether].src, routed_src_mac)
2813 self.assertEqual(rx[Ether].dst, sep4.mac)
2814 self.assertEqual(rx[IPv6].src, ep1.ip6.address)
2815 self.assertEqual(rx[IPv6].dst, ep3.ip6.address)
2818 # and revert back to unprogrammed
2820 sep4.remove_vpp_config()
2822 rxs = self.send_and_expect(self.pg0, p6[0] * 17, self.pg7)
2825 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
2826 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
2827 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
2828 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
2829 self.assertEqual(rx[VXLAN].vni, 117)
2830 self.assertTrue(rx[VXLAN].flags.G)
2831 self.assertTrue(rx[VXLAN].flags.Instance)
2832 # redirect policy has been applied
2833 self.assertTrue(rx[VXLAN].gpflags.A)
2834 self.assertFalse(rx[VXLAN].gpflags.D)
2836 inner = rx[VXLAN].payload
2838 self.assertEqual(inner[Ether].src, routed_src_mac)
2839 self.assertEqual(inner[Ether].dst, sep4.mac)
2840 self.assertEqual(inner[IPv6].src, ep1.ip6.address)
2841 self.assertEqual(inner[IPv6].dst, ep3.ip6.address)
2843 c1.remove_vpp_config()
2844 c2.remove_vpp_config()
2847 # test the symmetric hash mode
2849 c1 = VppGbpContract(
2850 self, epg_220.sclass, epg_222.sclass, acl_index,
2851 [VppGbpContractRule(
2852 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2853 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
2854 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
2855 sep1.ip4, sep1.epg.rd),
2856 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
2857 sep2.ip4, sep2.epg.rd)]),
2859 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2860 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
2861 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
2862 sep3.ip6, sep3.epg.rd),
2863 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
2864 sep4.ip6, sep4.epg.rd)])],
2865 [ETH_P_IP, ETH_P_IPV6])
2868 c2 = VppGbpContract(
2869 self, epg_222.sclass, epg_220.sclass, acl_index,
2870 [VppGbpContractRule(
2871 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2872 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
2873 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
2874 sep1.ip4, sep1.epg.rd),
2875 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
2876 sep2.ip4, sep2.epg.rd)]),
2878 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2879 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
2880 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
2881 sep3.ip6, sep3.epg.rd),
2882 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
2883 sep4.ip6, sep4.epg.rd)])],
2884 [ETH_P_IP, ETH_P_IPV6])
2888 # send again with the contract preset, now packets arrive
2889 # at SEP1 for both directions
2891 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
2894 self.assertEqual(rx[Ether].src, routed_src_mac)
2895 self.assertEqual(rx[Ether].dst, sep1.mac)
2896 self.assertEqual(rx[IP].src, ep1.ip4.address)
2897 self.assertEqual(rx[IP].dst, ep3.ip4.address)
2899 rxs = self.send_and_expect(self.pg2, p4[1] * 17, sep1.itf)
2902 self.assertEqual(rx[Ether].src, routed_src_mac)
2903 self.assertEqual(rx[Ether].dst, sep1.mac)
2904 self.assertEqual(rx[IP].src, ep3.ip4.address)
2905 self.assertEqual(rx[IP].dst, ep1.ip4.address)
2908 # programme the unknown EP for the L3 tests
2910 sep4.add_vpp_config()
2913 # an L3 switch packet between local EPs in different EPGs
2914 # different dest ports on each so the are LB hashed differently
2916 p4 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
2917 IP(src=ep1.ip4.address, dst=ep2.ip4.address) /
2918 UDP(sport=1234, dport=1234) /
2920 (Ether(src=ep2.mac, dst=str(self.router_mac)) /
2921 IP(src=ep2.ip4.address, dst=ep1.ip4.address) /
2922 UDP(sport=1234, dport=1234) /
2924 p6 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
2925 IPv6(src=ep1.ip6.address, dst=ep2.ip6.address) /
2926 UDP(sport=1234, dport=1234) /
2928 (Ether(src=ep2.mac, dst=str(self.router_mac)) /
2929 IPv6(src=ep2.ip6.address, dst=ep1.ip6.address) /
2930 UDP(sport=1234, dport=1234) /
2933 c3 = VppGbpContract(
2934 self, epg_220.sclass, epg_221.sclass, acl_index,
2935 [VppGbpContractRule(
2936 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2937 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
2938 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
2939 sep1.ip4, sep1.epg.rd),
2940 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
2941 sep2.ip4, sep2.epg.rd)]),
2943 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2944 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
2945 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
2946 sep3.ip6, sep3.epg.rd),
2947 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
2948 sep4.ip6, sep4.epg.rd)])],
2949 [ETH_P_IP, ETH_P_IPV6])
2952 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
2955 self.assertEqual(rx[Ether].src, routed_src_mac)
2956 self.assertEqual(rx[Ether].dst, sep1.mac)
2957 self.assertEqual(rx[IP].src, ep1.ip4.address)
2958 self.assertEqual(rx[IP].dst, ep2.ip4.address)
2961 # learn a remote EP in EPG 221
2963 vx_tun_l3 = VppGbpVxlanTunnel(
2964 self, 444, rd1.rd_id,
2965 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
2967 vx_tun_l3.add_vpp_config()
2969 c4 = VppGbpContract(
2970 self, epg_221.sclass, epg_220.sclass, acl_index,
2971 [VppGbpContractRule(
2972 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2975 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2977 [ETH_P_IP, ETH_P_IPV6])
2980 p = (Ether(src=self.pg7.remote_mac,
2981 dst=self.pg7.local_mac) /
2982 IP(src=self.pg7.remote_ip4,
2983 dst=self.pg7.local_ip4) /
2984 UDP(sport=1234, dport=48879) /
2985 VXLAN(vni=444, gpid=441, flags=0x88) /
2986 Ether(src="00:22:22:22:22:33", dst=str(self.router_mac)) /
2987 IP(src="10.0.0.88", dst=ep1.ip4.address) /
2988 UDP(sport=1234, dport=1234) /
2991 rx = self.send_and_expect(self.pg7, [p], self.pg0)
2993 # endpoint learnt via the parent GBP-vxlan interface
2994 self.assertTrue(find_gbp_endpoint(self,
2995 vx_tun_l3._sw_if_index,
2998 p = (Ether(src=self.pg7.remote_mac,
2999 dst=self.pg7.local_mac) /
3000 IP(src=self.pg7.remote_ip4,
3001 dst=self.pg7.local_ip4) /
3002 UDP(sport=1234, dport=48879) /
3003 VXLAN(vni=444, gpid=441, flags=0x88) /
3004 Ether(src="00:22:22:22:22:33", dst=str(self.router_mac)) /
3005 IPv6(src="2001:10::88", dst=ep1.ip6.address) /
3006 UDP(sport=1234, dport=1234) /
3009 rx = self.send_and_expect(self.pg7, [p], self.pg0)
3011 # endpoint learnt via the parent GBP-vxlan interface
3012 self.assertTrue(find_gbp_endpoint(self,
3013 vx_tun_l3._sw_if_index,
3017 # L3 switch from local to remote EP
3019 p4 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3020 IP(src=ep1.ip4.address, dst="10.0.0.88") /
3021 UDP(sport=1234, dport=1234) /
3023 p6 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3024 IPv6(src=ep1.ip6.address, dst="2001:10::88") /
3025 UDP(sport=1234, dport=1234) /
3028 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3031 self.assertEqual(rx[Ether].src, routed_src_mac)
3032 self.assertEqual(rx[Ether].dst, sep1.mac)
3033 self.assertEqual(rx[IP].src, ep1.ip4.address)
3034 self.assertEqual(rx[IP].dst, "10.0.0.88")
3036 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep4.itf)
3039 self.assertEqual(rx[Ether].src, routed_src_mac)
3040 self.assertEqual(rx[Ether].dst, sep4.mac)
3041 self.assertEqual(rx[IPv6].src, ep1.ip6.address)
3042 self.assertEqual(rx[IPv6].dst, "2001:10::88")
3045 # test the dst-ip hash mode
3047 c5 = VppGbpContract(
3048 self, epg_220.sclass, epg_221.sclass, acl_index,
3049 [VppGbpContractRule(
3050 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3051 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
3052 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3053 sep1.ip4, sep1.epg.rd),
3054 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3055 sep2.ip4, sep2.epg.rd)]),
3057 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3058 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
3059 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3060 sep3.ip6, sep3.epg.rd),
3061 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3062 sep4.ip6, sep4.epg.rd)])],
3063 [ETH_P_IP, ETH_P_IPV6])
3066 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3069 self.assertEqual(rx[Ether].src, routed_src_mac)
3070 self.assertEqual(rx[Ether].dst, sep1.mac)
3071 self.assertEqual(rx[IP].src, ep1.ip4.address)
3072 self.assertEqual(rx[IP].dst, "10.0.0.88")
3074 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep3.itf)
3077 self.assertEqual(rx[Ether].src, routed_src_mac)
3078 self.assertEqual(rx[Ether].dst, sep3.mac)
3079 self.assertEqual(rx[IPv6].src, ep1.ip6.address)
3080 self.assertEqual(rx[IPv6].dst, "2001:10::88")
3085 self.pg7.unconfig_ip4()
3087 def test_gbp_l3_out(self):
3090 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
3091 self.vapi.cli("set logging class gbp debug")
3093 routed_dst_mac = "00:0c:0c:0c:0c:0c"
3094 routed_src_mac = "00:22:bd:f8:19:ff"
3099 t4 = VppIpTable(self, 1)
3101 t6 = VppIpTable(self, 1, True)
3104 rd1 = VppGbpRouteDomain(self, 2, t4, t6)
3105 rd1.add_vpp_config()
3107 self.loop0.set_mac(self.router_mac)
3110 # Bind the BVI to the RD
3112 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
3113 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
3116 # Pg7 hosts a BD's BUM
3117 # Pg1 some other l3 interface
3119 self.pg7.config_ip4()
3120 self.pg7.resolve_arp()
3123 # a multicast vxlan-gbp tunnel for broadcast in the BD
3125 tun_bm = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
3128 tun_bm.add_vpp_config()
3131 # a GBP external bridge domains for the EPs
3133 bd1 = VppBridgeDomain(self, 1)
3134 bd1.add_vpp_config()
3135 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0, None, tun_bm)
3136 gbd1.add_vpp_config()
3139 # The Endpoint-groups in which the external endpoints exist
3141 epg_220 = VppGbpEndpointGroup(self, 220, 113, rd1, gbd1,
3145 VppGbpEndpointRetention(2))
3146 epg_220.add_vpp_config()
3148 # the BVIs have the subnets applied ...
3149 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 24)
3150 ip4_addr.add_vpp_config()
3151 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 64)
3152 ip6_addr.add_vpp_config()
3154 # ... which are L3-out subnets
3155 l3o_1 = VppGbpSubnet(
3156 self, rd1, "10.0.0.0", 24,
3157 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3159 l3o_1.add_vpp_config()
3162 # an external interface attached to the outside world and the
3165 vlan_100 = VppDot1QSubint(self, self.pg0, 100)
3167 VppL2Vtr(self, vlan_100, L2_VTR_OP.L2_POP_1).add_vpp_config()
3168 vlan_101 = VppDot1QSubint(self, self.pg0, 101)
3170 VppL2Vtr(self, vlan_101, L2_VTR_OP.L2_POP_1).add_vpp_config()
3172 ext_itf = VppGbpExtItf(self, self.loop0, bd1, rd1)
3173 ext_itf.add_vpp_config()
3176 # an unicast vxlan-gbp for inter-RD traffic
3178 vx_tun_l3 = VppGbpVxlanTunnel(
3179 self, 444, rd1.rd_id,
3180 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
3182 vx_tun_l3.add_vpp_config()
3185 # External Endpoints
3187 eep1 = VppGbpEndpoint(self, vlan_100,
3189 "10.0.0.1", "11.0.0.1",
3190 "2001:10::1", "3001::1",
3191 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
3192 eep1.add_vpp_config()
3193 eep2 = VppGbpEndpoint(self, vlan_101,
3195 "10.0.0.2", "11.0.0.2",
3196 "2001:10::2", "3001::2",
3197 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
3198 eep2.add_vpp_config()
3201 # A remote external endpoint
3203 rep = VppGbpEndpoint(self, vx_tun_l3,
3205 "10.0.0.101", "11.0.0.101",
3206 "2001:10::101", "3001::101",
3207 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
3209 self.pg7.remote_ip4,
3211 rep.add_vpp_config()
3214 # ARP packet from External EPs are accepted and replied to
3216 p_arp = (Ether(src=eep1.mac, dst="ff:ff:ff:ff:ff:ff") /
3219 psrc=eep1.ip4.address, pdst="10.0.0.128",
3220 hwsrc=eep1.mac, hwdst="ff:ff:ff:ff:ff:ff"))
3221 rxs = self.send_and_expect(self.pg0, p_arp * 1, self.pg0)
3224 # packets destined to unknown addresses in the BVI's subnet
3227 p4 = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3229 IP(src="10.0.0.1", dst="10.0.0.88") /
3230 UDP(sport=1234, dport=1234) /
3232 p6 = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3234 IPv6(src="2001:10::1", dst="2001:10::88") /
3235 UDP(sport=1234, dport=1234) /
3238 rxs = self.send_and_expect(self.pg0, p4 * 1, self.pg7)
3241 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3242 # self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3243 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3244 self.assertEqual(rx[IP].dst, "239.1.1.1")
3245 self.assertEqual(rx[VXLAN].vni, 88)
3246 self.assertTrue(rx[VXLAN].flags.G)
3247 self.assertTrue(rx[VXLAN].flags.Instance)
3248 # policy was applied to the original IP packet
3249 self.assertEqual(rx[VXLAN].gpid, 113)
3250 self.assertTrue(rx[VXLAN].gpflags.A)
3251 self.assertFalse(rx[VXLAN].gpflags.D)
3253 inner = rx[VXLAN].payload
3255 self.assertTrue(inner.haslayer(ARP))
3258 # remote to external
3260 p = (Ether(src=self.pg7.remote_mac,
3261 dst=self.pg7.local_mac) /
3262 IP(src=self.pg7.remote_ip4,
3263 dst=self.pg7.local_ip4) /
3264 UDP(sport=1234, dport=48879) /
3265 VXLAN(vni=444, gpid=113, flags=0x88) /
3266 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
3267 IP(src="10.0.0.101", dst="10.0.0.1") /
3268 UDP(sport=1234, dport=1234) /
3271 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
3274 # local EP pings router
3276 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3278 IP(src=eep1.ip4.address, dst="10.0.0.128") /
3279 ICMP(type='echo-request'))
3281 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
3284 self.assertEqual(rx[Ether].src, str(self.router_mac))
3285 self.assertEqual(rx[Ether].dst, eep1.mac)
3286 self.assertEqual(rx[Dot1Q].vlan, 100)
3289 # local EP pings other local EP
3291 p = (Ether(src=eep1.mac, dst=eep2.mac) /
3293 IP(src=eep1.ip4.address, dst=eep2.ip4.address) /
3294 ICMP(type='echo-request'))
3296 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
3299 self.assertEqual(rx[Ether].src, eep1.mac)
3300 self.assertEqual(rx[Ether].dst, eep2.mac)
3301 self.assertEqual(rx[Dot1Q].vlan, 101)
3304 # A subnet reachable through the external EP1
3306 ip_220 = VppIpRoute(self, "10.220.0.0", 24,
3307 [VppRoutePath(eep1.ip4.address,
3308 eep1.epg.bvi.sw_if_index)],
3309 table_id=t4.table_id)
3310 ip_220.add_vpp_config()
3312 l3o_220 = VppGbpSubnet(
3313 self, rd1, "10.220.0.0", 24,
3314 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3316 l3o_220.add_vpp_config()
3319 # A subnet reachable through the external EP2
3321 ip_221 = VppIpRoute(self, "10.221.0.0", 24,
3322 [VppRoutePath(eep2.ip4.address,
3323 eep2.epg.bvi.sw_if_index)],
3324 table_id=t4.table_id)
3325 ip_221.add_vpp_config()
3327 l3o_221 = VppGbpSubnet(
3328 self, rd1, "10.221.0.0", 24,
3329 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3331 l3o_221.add_vpp_config()
3334 # ping between hosts in remote subnets
3335 # dropped without a contract
3337 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3339 IP(src="10.220.0.1", dst="10.221.0.1") /
3340 ICMP(type='echo-request'))
3342 rxs = self.send_and_assert_no_replies(self.pg0, p * 1)
3345 # contract for the external nets to communicate
3347 acl = VppGbpAcl(self)
3348 rule4 = acl.create_rule(permit_deny=1, proto=17)
3349 rule6 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
3350 acl_index = acl.add_vpp_config([rule4, rule6])
3352 c1 = VppGbpContract(
3353 self, 4220, 4221, acl_index,
3354 [VppGbpContractRule(
3355 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3358 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3360 [ETH_P_IP, ETH_P_IPV6])
3364 # Contracts allowing ext-net 200 to talk with external EPs
3366 c2 = VppGbpContract(
3367 self, 4220, 113, acl_index,
3368 [VppGbpContractRule(
3369 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3372 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3374 [ETH_P_IP, ETH_P_IPV6])
3376 c3 = VppGbpContract(
3377 self, 113, 4220, acl_index,
3378 [VppGbpContractRule(
3379 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3382 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3384 [ETH_P_IP, ETH_P_IPV6])
3388 # ping between hosts in remote subnets
3390 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3392 IP(src="10.220.0.1", dst="10.221.0.1") /
3393 UDP(sport=1234, dport=1234) /
3396 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
3399 self.assertEqual(rx[Ether].src, str(self.router_mac))
3400 self.assertEqual(rx[Ether].dst, eep2.mac)
3401 self.assertEqual(rx[Dot1Q].vlan, 101)
3403 # we did not learn these external hosts
3404 self.assertFalse(find_gbp_endpoint(self, ip="10.220.0.1"))
3405 self.assertFalse(find_gbp_endpoint(self, ip="10.221.0.1"))
3408 # from remote external EP to local external EP
3410 p = (Ether(src=self.pg7.remote_mac,
3411 dst=self.pg7.local_mac) /
3412 IP(src=self.pg7.remote_ip4,
3413 dst=self.pg7.local_ip4) /
3414 UDP(sport=1234, dport=48879) /
3415 VXLAN(vni=444, gpid=113, flags=0x88) /
3416 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
3417 IP(src="10.0.0.101", dst="10.220.0.1") /
3418 UDP(sport=1234, dport=1234) /
3421 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
3424 # ping from an external host to the remote external EP
3426 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3428 IP(src="10.220.0.1", dst=rep.ip4.address) /
3429 UDP(sport=1234, dport=1234) /
3432 rxs = self.send_and_expect(self.pg0, p * 1, self.pg7)
3435 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3436 # self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3437 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3438 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
3439 self.assertEqual(rx[VXLAN].vni, 444)
3440 self.assertTrue(rx[VXLAN].flags.G)
3441 self.assertTrue(rx[VXLAN].flags.Instance)
3442 # the sclass of the ext-net the packet came from
3443 self.assertEqual(rx[VXLAN].gpid, 4220)
3444 # policy was applied to the original IP packet
3445 self.assertTrue(rx[VXLAN].gpflags.A)
3446 # since it's an external host the reciever should not learn it
3447 self.assertTrue(rx[VXLAN].gpflags.D)
3448 inner = rx[VXLAN].payload
3449 self.assertEqual(inner[IP].src, "10.220.0.1")
3450 self.assertEqual(inner[IP].dst, rep.ip4.address)
3453 # An external subnet reachable via the remote external EP
3457 # first the VXLAN-GBP tunnel over which it is reached
3459 vx_tun_r = VppVxlanGbpTunnel(
3460 self, self.pg7.local_ip4,
3461 self.pg7.remote_ip4, 445,
3462 mode=(VppEnum.vl_api_vxlan_gbp_api_tunnel_mode_t.
3463 VXLAN_GBP_API_TUNNEL_MODE_L3))
3464 vx_tun_r.add_vpp_config()
3465 VppIpInterfaceBind(self, vx_tun_r, t4).add_vpp_config()
3467 self.logger.info(self.vapi.cli("sh vxlan-gbp tunnel"))
3470 # then the special adj to resolve through on that tunnel
3472 n1 = VppNeighbor(self,
3473 vx_tun_r.sw_if_index,
3474 "00:0c:0c:0c:0c:0c",
3475 self.pg7.remote_ip4)
3479 # the route via the adj above
3481 ip_222 = VppIpRoute(self, "10.222.0.0", 24,
3482 [VppRoutePath(self.pg7.remote_ip4,
3483 vx_tun_r.sw_if_index)],
3484 table_id=t4.table_id)
3485 ip_222.add_vpp_config()
3487 l3o_222 = VppGbpSubnet(
3488 self, rd1, "10.222.0.0", 24,
3489 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3491 l3o_222.add_vpp_config()
3494 # ping between hosts in local and remote external subnets
3495 # dropped without a contract
3497 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3499 IP(src="10.220.0.1", dst="10.222.0.1") /
3500 UDP(sport=1234, dport=1234) /
3503 rxs = self.send_and_assert_no_replies(self.pg0, p * 1)
3506 # Add contracts ext-nets for 220 -> 222
3508 c4 = VppGbpContract(
3509 self, 4220, 4222, acl_index,
3510 [VppGbpContractRule(
3511 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3514 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3516 [ETH_P_IP, ETH_P_IPV6])
3520 # ping from host in local to remote external subnets
3522 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3524 IP(src="10.220.0.1", dst="10.222.0.1") /
3525 UDP(sport=1234, dport=1234) /
3528 rxs = self.send_and_expect(self.pg0, p * 3, self.pg7)
3531 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3532 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3533 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3534 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
3535 self.assertEqual(rx[VXLAN].vni, 445)
3536 self.assertTrue(rx[VXLAN].flags.G)
3537 self.assertTrue(rx[VXLAN].flags.Instance)
3538 # the sclass of the ext-net the packet came from
3539 self.assertEqual(rx[VXLAN].gpid, 4220)
3540 # policy was applied to the original IP packet
3541 self.assertTrue(rx[VXLAN].gpflags.A)
3542 # since it's an external host the reciever should not learn it
3543 self.assertTrue(rx[VXLAN].gpflags.D)
3544 inner = rx[VXLAN].payload
3545 self.assertEqual(inner[Ether].dst, "00:0c:0c:0c:0c:0c")
3546 self.assertEqual(inner[IP].src, "10.220.0.1")
3547 self.assertEqual(inner[IP].dst, "10.222.0.1")
3550 # ping from host in remote to local external subnets
3551 # there's no contract for this, but the A bit is set.
3553 p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
3554 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
3555 UDP(sport=1234, dport=48879) /
3556 VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
3557 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
3558 IP(src="10.222.0.1", dst="10.220.0.1") /
3559 UDP(sport=1234, dport=1234) /
3562 rxs = self.send_and_expect(self.pg7, p * 3, self.pg0)
3563 self.assertFalse(find_gbp_endpoint(self, ip="10.222.0.1"))
3568 self.pg7.unconfig_ip4()
3569 vlan_100.set_vtr(L2_VTR_OP.L2_DISABLED)
3572 if __name__ == '__main__':
3573 unittest.main(testRunner=VppTestRunner)