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, \
10 ICMPv6ND_NA, ICMPv6EchoRequest
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, ETH_P_ARP
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, FibPathProto, \
22 from vpp_l2 import VppBridgeDomain, VppBridgeDomainPort, \
23 VppBridgeDomainArpEntry, VppL2FibEntry, find_bridge_domain_port, VppL2Vtr
24 from vpp_sub_interface import L2_VTR_OP, VppDot1QSubint
25 from vpp_ip import VppIpAddress, VppIpPrefix, DpoProto
26 from vpp_papi import VppEnum, MACAddress
27 from vpp_vxlan_gbp_tunnel import find_vxlan_gbp_tunnel, INDEX_INVALID, \
29 from vpp_neighbor import VppNeighbor
38 def find_gbp_endpoint(test, sw_if_index=None, ip=None, mac=None,
39 tep=None, sclass=None):
41 vip = VppIpAddress(ip)
43 vmac = MACAddress(mac)
45 eps = test.vapi.gbp_endpoint_dump()
49 src = VppIpAddress(tep[0])
50 dst = VppIpAddress(tep[1])
51 if src != ep.endpoint.tun.src or dst != ep.endpoint.tun.dst:
54 if ep.endpoint.sw_if_index != sw_if_index:
57 if ep.endpoint.sclass != sclass:
60 for eip in ep.endpoint.ips:
64 if vmac.packed == ep.endpoint.mac:
70 def find_gbp_vxlan(test, vni):
71 ts = test.vapi.gbp_vxlan_tunnel_dump()
73 if t.tunnel.vni == vni:
78 class VppGbpEndpoint(VppObject):
105 return [self.ip4, self.ip6]
109 return [self.fip4, self.fip6]
111 def __init__(self, test, itf, epg, recirc, ip4, fip4, ip6, fip6,
121 self._ip4 = VppIpAddress(ip4)
122 self._fip4 = VppIpAddress(fip4)
123 self._ip6 = VppIpAddress(ip6)
124 self._fip6 = VppIpAddress(fip6)
127 self.vmac = MACAddress(self.itf.remote_mac)
129 self.vmac = MACAddress("00:00:00:00:00:00")
132 self.tun_src = VppIpAddress(tun_src)
133 self.tun_dst = VppIpAddress(tun_dst)
135 def add_vpp_config(self):
136 res = self._test.vapi.gbp_endpoint_add(
137 self.itf.sw_if_index,
138 [self.ip4.encode(), self.ip6.encode()],
142 self.tun_src.encode(),
143 self.tun_dst.encode())
144 self.handle = res.handle
145 self._test.registry.register(self, self._test.logger)
147 def remove_vpp_config(self):
148 self._test.vapi.gbp_endpoint_del(self.handle)
151 return "gbp-endpoint:[%d==%d:%s:%d]" % (self.handle,
152 self.itf.sw_if_index,
156 def query_vpp_config(self):
157 return find_gbp_endpoint(self._test,
158 self.itf.sw_if_index,
162 class VppGbpRecirc(VppObject):
164 GBP Recirculation Interface
167 def __init__(self, test, epg, recirc, is_ext=False):
173 def add_vpp_config(self):
174 self._test.vapi.gbp_recirc_add_del(
176 self.recirc.sw_if_index,
179 self._test.registry.register(self, self._test.logger)
181 def remove_vpp_config(self):
182 self._test.vapi.gbp_recirc_add_del(
184 self.recirc.sw_if_index,
189 return "gbp-recirc:[%d]" % (self.recirc.sw_if_index)
191 def query_vpp_config(self):
192 rs = self._test.vapi.gbp_recirc_dump()
194 if r.recirc.sw_if_index == self.recirc.sw_if_index:
199 class VppGbpExtItf(VppObject):
201 GBP ExtItfulation Interface
204 def __init__(self, test, itf, bd, rd, anon=False):
209 self.flags = 1 if anon else 0
211 def add_vpp_config(self):
212 self._test.vapi.gbp_ext_itf_add_del(
213 1, self.itf.sw_if_index, self.bd.bd_id, self.rd.rd_id, self.flags)
214 self._test.registry.register(self, self._test.logger)
216 def remove_vpp_config(self):
217 self._test.vapi.gbp_ext_itf_add_del(
218 0, self.itf.sw_if_index, self.bd.bd_id, self.rd.rd_id, self.flags)
221 return "gbp-ext-itf:[%d]%s" % (self.itf.sw_if_index,
222 " [anon]" if self.flags else "")
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):
237 def __init__(self, test, rd, address, address_len,
238 type, sw_if_index=None, sclass=None):
240 self.rd_id = rd.rd_id
241 self.prefix = VppIpPrefix(address, address_len)
243 self.sw_if_index = sw_if_index
246 def add_vpp_config(self):
247 self._test.vapi.gbp_subnet_add_del(
250 self.prefix.encode(),
252 sw_if_index=self.sw_if_index if self.sw_if_index else 0xffffffff,
253 sclass=self.sclass if self.sclass else 0xffff)
254 self._test.registry.register(self, self._test.logger)
256 def remove_vpp_config(self):
257 self._test.vapi.gbp_subnet_add_del(
260 self.prefix.encode(),
264 return "gbp-subnet:[%d-%s]" % (self.rd_id, self.prefix)
266 def query_vpp_config(self):
267 ss = self._test.vapi.gbp_subnet_dump()
269 if s.subnet.rd_id == self.rd_id and \
270 s.subnet.type == self.type and \
271 s.subnet.prefix == self.prefix:
276 class VppGbpEndpointRetention(object):
277 def __init__(self, remote_ep_timeout=0xffffffff):
278 self.remote_ep_timeout = remote_ep_timeout
281 return {'remote_ep_timeout': self.remote_ep_timeout}
284 class VppGbpEndpointGroup(VppObject):
289 def __init__(self, test, vnid, sclass, rd, bd, uplink,
290 bvi, bvi_ip4, bvi_ip6=None,
291 retention=VppGbpEndpointRetention()):
295 self.bvi_ip4 = VppIpAddress(bvi_ip4)
296 self.bvi_ip6 = VppIpAddress(bvi_ip6)
303 self.retention = retention
305 def add_vpp_config(self):
306 self._test.vapi.gbp_endpoint_group_add(
311 self.uplink.sw_if_index if self.uplink else INDEX_INVALID,
312 self.retention.encode())
313 self._test.registry.register(self, self._test.logger)
315 def remove_vpp_config(self):
316 self._test.vapi.gbp_endpoint_group_del(self.sclass)
319 return "gbp-endpoint-group:[%d]" % (self.vnid)
321 def query_vpp_config(self):
322 epgs = self._test.vapi.gbp_endpoint_group_dump()
324 if epg.epg.vnid == self.vnid:
329 class VppGbpBridgeDomain(VppObject):
334 def __init__(self, test, bd, rd, bvi, uu_fwd=None,
335 bm_flood=None, learn=True,
336 uu_drop=False, bm_drop=False,
341 self.bm_flood = bm_flood
345 e = VppEnum.vl_api_gbp_bridge_domain_flags_t
347 self.flags = e.GBP_BD_API_FLAG_NONE
349 self.flags |= e.GBP_BD_API_FLAG_DO_NOT_LEARN
351 self.flags |= e.GBP_BD_API_FLAG_UU_FWD_DROP
353 self.flags |= e.GBP_BD_API_FLAG_MCAST_DROP
355 self.flags |= e.GBP_BD_API_FLAG_UCAST_ARP
357 def add_vpp_config(self):
358 self._test.vapi.gbp_bridge_domain_add(
362 self.bvi.sw_if_index,
363 self.uu_fwd.sw_if_index if self.uu_fwd else INDEX_INVALID,
364 self.bm_flood.sw_if_index if self.bm_flood else INDEX_INVALID)
365 self._test.registry.register(self, self._test.logger)
367 def remove_vpp_config(self):
368 self._test.vapi.gbp_bridge_domain_del(self.bd.bd_id)
371 return "gbp-bridge-domain:[%d]" % (self.bd.bd_id)
373 def query_vpp_config(self):
374 bds = self._test.vapi.gbp_bridge_domain_dump()
376 if bd.bd.bd_id == self.bd.bd_id:
381 class VppGbpRouteDomain(VppObject):
386 def __init__(self, test, rd_id, scope, t4, t6, ip4_uu=None, ip6_uu=None):
395 def add_vpp_config(self):
396 self._test.vapi.gbp_route_domain_add(
401 self.ip4_uu.sw_if_index if self.ip4_uu else INDEX_INVALID,
402 self.ip6_uu.sw_if_index if self.ip6_uu else INDEX_INVALID)
403 self._test.registry.register(self, self._test.logger)
405 def remove_vpp_config(self):
406 self._test.vapi.gbp_route_domain_del(self.rd_id)
409 return "gbp-route-domain:[%d]" % (self.rd_id)
411 def query_vpp_config(self):
412 rds = self._test.vapi.gbp_route_domain_dump()
414 if rd.rd.rd_id == self.rd_id:
419 class VppGbpContractNextHop():
420 def __init__(self, mac, bd, ip, rd):
427 return {'ip': self.ip.encode(),
428 'mac': self.mac.packed,
429 'bd_id': self.bd.bd.bd_id,
430 'rd_id': self.rd.rd_id}
433 class VppGbpContractRule():
434 def __init__(self, action, hash_mode, nhs=None):
436 self.hash_mode = hash_mode
437 self.nhs = [] if nhs is None else nhs
442 nhs.append(nh.encode())
445 return {'action': self.action,
447 'hash_mode': self.hash_mode,
448 'n_nhs': len(self.nhs),
452 return '<VppGbpContractRule action=%s, hash_mode=%s>' % (
453 self.action, self.hash_mode)
456 class VppGbpContract(VppObject):
461 def __init__(self, test, scope, sclass, dclass, acl_index,
462 rules, allowed_ethertypes):
464 if not isinstance(rules, list):
465 raise ValueError("'rules' must be a list.")
466 if not isinstance(allowed_ethertypes, list):
467 raise ValueError("'allowed_ethertypes' must be a list.")
469 self.acl_index = acl_index
473 self.allowed_ethertypes = allowed_ethertypes
474 while (len(self.allowed_ethertypes) < 16):
475 self.allowed_ethertypes.append(0)
477 def add_vpp_config(self):
480 rules.append(r.encode())
481 r = self._test.vapi.gbp_contract_add_del(
484 'acl_index': self.acl_index,
486 'sclass': self.sclass,
487 'dclass': self.dclass,
488 'n_rules': len(rules),
490 'n_ether_types': len(self.allowed_ethertypes),
491 'allowed_ethertypes': self.allowed_ethertypes})
492 self.stats_index = r.stats_index
493 self._test.registry.register(self, self._test.logger)
495 def remove_vpp_config(self):
496 self._test.vapi.gbp_contract_add_del(
499 'acl_index': self.acl_index,
501 'sclass': self.sclass,
502 'dclass': self.dclass,
505 'n_ether_types': len(self.allowed_ethertypes),
506 'allowed_ethertypes': self.allowed_ethertypes})
509 return "gbp-contract:[%d:%d:%d:%d]" % (self.scope,
514 def query_vpp_config(self):
515 cs = self._test.vapi.gbp_contract_dump()
517 if c.contract.scope == self.scope \
518 and c.contract.sclass == self.sclass \
519 and c.contract.dclass == self.dclass:
523 def get_drop_stats(self):
524 c = self._test.statistics.get_counter("/net/gbp/contract/drop")
525 return c[0][self.stats_index]
527 def get_permit_stats(self):
528 c = self._test.statistics.get_counter("/net/gbp/contract/permit")
529 return c[0][self.stats_index]
532 class VppGbpVxlanTunnel(VppInterface):
537 def __init__(self, test, vni, bd_rd_id, mode, src):
538 super(VppGbpVxlanTunnel, self).__init__(test)
541 self.bd_rd_id = bd_rd_id
545 def add_vpp_config(self):
546 r = self._test.vapi.gbp_vxlan_tunnel_add(
551 self.set_sw_if_index(r.sw_if_index)
552 self._test.registry.register(self, self._test.logger)
554 def remove_vpp_config(self):
555 self._test.vapi.gbp_vxlan_tunnel_del(self.vni)
558 return "gbp-vxlan:%d" % (self.sw_if_index)
560 def query_vpp_config(self):
561 return find_gbp_vxlan(self._test, self.vni)
564 class VppGbpAcl(VppObject):
569 def __init__(self, test):
571 self.acl_index = 4294967295
573 def create_rule(self, is_ipv6=0, permit_deny=0, proto=-1,
574 s_prefix=0, s_ip=b'\x00\x00\x00\x00', sport_from=0,
575 sport_to=65535, d_prefix=0, d_ip=b'\x00\x00\x00\x00',
576 dport_from=0, dport_to=65535):
577 if proto == -1 or proto == 0:
580 elif proto == 1 or proto == 58:
583 rule = ({'is_permit': permit_deny, 'is_ipv6': is_ipv6, 'proto': proto,
584 'srcport_or_icmptype_first': sport_from,
585 'srcport_or_icmptype_last': sport_to,
586 'src_ip_prefix_len': s_prefix,
588 'dstport_or_icmpcode_first': dport_from,
589 'dstport_or_icmpcode_last': dport_to,
590 'dst_ip_prefix_len': d_prefix,
591 'dst_ip_addr': d_ip})
594 def add_vpp_config(self, rules):
596 reply = self._test.vapi.acl_add_replace(acl_index=self.acl_index,
599 self.acl_index = reply.acl_index
600 return self.acl_index
602 def remove_vpp_config(self):
603 self._test.vapi.acl_del(self.acl_index)
606 return "gbp-acl:[%d]" % (self.acl_index)
608 def query_vpp_config(self):
609 cs = self._test.vapi.acl_dump()
611 if c.acl_index == self.acl_index:
616 class TestGBP(VppTestCase):
617 """ GBP Test Case """
620 def config_flags(self):
621 return VppEnum.vl_api_nat_config_flags_t
625 super(TestGBP, cls).setUpClass()
628 def tearDownClass(cls):
629 super(TestGBP, cls).tearDownClass()
632 super(TestGBP, self).setUp()
634 self.create_pg_interfaces(range(9))
635 self.create_loopback_interfaces(8)
637 self.router_mac = MACAddress("00:11:22:33:44:55")
639 for i in self.pg_interfaces:
641 for i in self.lo_interfaces:
644 self.vlan_100 = VppDot1QSubint(self, self.pg0, 100)
645 self.vlan_100.admin_up()
646 self.vlan_101 = VppDot1QSubint(self, self.pg0, 101)
647 self.vlan_101.admin_up()
648 self.vlan_102 = VppDot1QSubint(self, self.pg0, 102)
649 self.vlan_102.admin_up()
652 for i in self.pg_interfaces:
654 super(TestGBP, self).tearDown()
655 for i in self.lo_interfaces:
656 i.remove_vpp_config()
657 self.lo_interfaces = []
658 self.vlan_102.remove_vpp_config()
659 self.vlan_101.remove_vpp_config()
660 self.vlan_100.remove_vpp_config()
662 def send_and_expect_bridged(self, src, tx, dst):
663 rx = self.send_and_expect(src, tx, dst)
666 self.assertEqual(r[Ether].src, tx[0][Ether].src)
667 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
668 self.assertEqual(r[IP].src, tx[0][IP].src)
669 self.assertEqual(r[IP].dst, tx[0][IP].dst)
672 def send_and_expect_bridged6(self, src, tx, dst):
673 rx = self.send_and_expect(src, tx, dst)
676 self.assertEqual(r[Ether].src, tx[0][Ether].src)
677 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
678 self.assertEqual(r[IPv6].src, tx[0][IPv6].src)
679 self.assertEqual(r[IPv6].dst, tx[0][IPv6].dst)
682 def send_and_expect_routed(self, src, tx, dst, src_mac):
683 rx = self.send_and_expect(src, tx, dst)
686 self.assertEqual(r[Ether].src, src_mac)
687 self.assertEqual(r[Ether].dst, dst.remote_mac)
688 self.assertEqual(r[IP].src, tx[0][IP].src)
689 self.assertEqual(r[IP].dst, tx[0][IP].dst)
692 def send_and_expect_routed6(self, src, tx, dst, src_mac):
693 rx = self.send_and_expect(src, tx, dst)
696 self.assertEqual(r[Ether].src, src_mac)
697 self.assertEqual(r[Ether].dst, dst.remote_mac)
698 self.assertEqual(r[IPv6].src, tx[0][IPv6].src)
699 self.assertEqual(r[IPv6].dst, tx[0][IPv6].dst)
702 def send_and_expect_natted(self, src, tx, dst, src_ip):
703 rx = self.send_and_expect(src, tx, dst)
706 self.assertEqual(r[Ether].src, tx[0][Ether].src)
707 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
708 self.assertEqual(r[IP].src, src_ip)
709 self.assertEqual(r[IP].dst, tx[0][IP].dst)
712 def send_and_expect_natted6(self, src, tx, dst, src_ip):
713 rx = self.send_and_expect(src, tx, dst)
716 self.assertEqual(r[Ether].src, tx[0][Ether].src)
717 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
718 self.assertEqual(r[IPv6].src, src_ip)
719 self.assertEqual(r[IPv6].dst, tx[0][IPv6].dst)
722 def send_and_expect_unnatted(self, src, tx, dst, dst_ip):
723 rx = self.send_and_expect(src, tx, dst)
726 self.assertEqual(r[Ether].src, tx[0][Ether].src)
727 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
728 self.assertEqual(r[IP].dst, dst_ip)
729 self.assertEqual(r[IP].src, tx[0][IP].src)
732 def send_and_expect_unnatted6(self, src, tx, dst, dst_ip):
733 rx = self.send_and_expect(src, tx, dst)
736 self.assertEqual(r[Ether].src, tx[0][Ether].src)
737 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
738 self.assertEqual(r[IPv6].dst, dst_ip)
739 self.assertEqual(r[IPv6].src, tx[0][IPv6].src)
742 def send_and_expect_double_natted(self, src, tx, dst, src_ip, dst_ip):
743 rx = self.send_and_expect(src, tx, dst)
746 self.assertEqual(r[Ether].src, str(self.router_mac))
747 self.assertEqual(r[Ether].dst, dst.remote_mac)
748 self.assertEqual(r[IP].dst, dst_ip)
749 self.assertEqual(r[IP].src, src_ip)
752 def send_and_expect_double_natted6(self, src, tx, dst, src_ip, dst_ip):
753 rx = self.send_and_expect(src, tx, dst)
756 self.assertEqual(r[Ether].src, str(self.router_mac))
757 self.assertEqual(r[Ether].dst, dst.remote_mac)
758 self.assertEqual(r[IPv6].dst, dst_ip)
759 self.assertEqual(r[IPv6].src, src_ip)
762 def send_and_expect_no_arp(self, src, tx, dst):
763 self.pg_send(src, tx)
764 dst.get_capture(0, timeout=1)
765 dst.assert_nothing_captured(remark="")
768 def send_and_expect_arp(self, src, tx, dst):
769 rx = self.send_and_expect(src, tx, dst)
772 self.assertEqual(r[Ether].src, tx[0][Ether].src)
773 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
774 self.assertEqual(r[ARP].psrc, tx[0][ARP].psrc)
775 self.assertEqual(r[ARP].pdst, tx[0][ARP].pdst)
776 self.assertEqual(r[ARP].hwsrc, tx[0][ARP].hwsrc)
777 self.assertEqual(r[ARP].hwdst, tx[0][ARP].hwdst)
781 """ Group Based Policy """
783 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
788 gt4 = VppIpTable(self, 0)
790 gt6 = VppIpTable(self, 0, is_ip6=True)
792 nt4 = VppIpTable(self, 20)
794 nt6 = VppIpTable(self, 20, is_ip6=True)
797 rd0 = VppGbpRouteDomain(self, 0, 400, gt4, gt6, None, None)
798 rd20 = VppGbpRouteDomain(self, 20, 420, nt4, nt6, None, None)
801 rd20.add_vpp_config()
806 bd1 = VppBridgeDomain(self, 1)
807 bd2 = VppBridgeDomain(self, 2)
808 bd20 = VppBridgeDomain(self, 20)
812 bd20.add_vpp_config()
814 gbd1 = VppGbpBridgeDomain(self, bd1, rd0, self.loop0)
815 gbd2 = VppGbpBridgeDomain(self, bd2, rd0, self.loop1)
816 gbd20 = VppGbpBridgeDomain(self, bd20, rd20, self.loop2)
818 gbd1.add_vpp_config()
819 gbd2.add_vpp_config()
820 gbd20.add_vpp_config()
823 # 3 EPGs, 2 of which share a BD.
824 # 2 NAT EPGs, one for floating-IP subnets, the other for internet
826 epgs = [VppGbpEndpointGroup(self, 220, 1220, rd0, gbd1,
827 self.pg4, self.loop0,
828 "10.0.0.128", "2001:10::128"),
829 VppGbpEndpointGroup(self, 221, 1221, rd0, gbd1,
830 self.pg5, self.loop0,
831 "10.0.1.128", "2001:10:1::128"),
832 VppGbpEndpointGroup(self, 222, 1222, rd0, gbd2,
833 self.pg6, self.loop1,
834 "10.0.2.128", "2001:10:2::128"),
835 VppGbpEndpointGroup(self, 333, 1333, rd20, gbd20,
836 self.pg7, self.loop2,
837 "11.0.0.128", "3001::128"),
838 VppGbpEndpointGroup(self, 444, 1444, rd20, gbd20,
839 self.pg8, self.loop2,
840 "11.0.0.129", "3001::129")]
841 recircs = [VppGbpRecirc(self, epgs[0], self.loop3),
842 VppGbpRecirc(self, epgs[1], self.loop4),
843 VppGbpRecirc(self, epgs[2], self.loop5),
844 VppGbpRecirc(self, epgs[3], self.loop6, is_ext=True),
845 VppGbpRecirc(self, epgs[4], self.loop7, is_ext=True)]
848 recirc_nat = recircs[3]
851 # 4 end-points, 2 in the same subnet, 3 in the same BD
853 eps = [VppGbpEndpoint(self, self.pg0,
855 "10.0.0.1", "11.0.0.1",
856 "2001:10::1", "3001::1"),
857 VppGbpEndpoint(self, self.pg1,
859 "10.0.0.2", "11.0.0.2",
860 "2001:10::2", "3001::2"),
861 VppGbpEndpoint(self, self.pg2,
863 "10.0.1.1", "11.0.0.3",
864 "2001:10:1::1", "3001::3"),
865 VppGbpEndpoint(self, self.pg3,
867 "10.0.2.1", "11.0.0.4",
868 "2001:10:2::1", "3001::4")]
871 # Config related to each of the EPGs
874 # IP config on the BVI interfaces
875 if epg != epgs[1] and epg != epgs[4]:
876 VppIpInterfaceBind(self, epg.bvi, epg.rd.t4).add_vpp_config()
877 VppIpInterfaceBind(self, epg.bvi, epg.rd.t6).add_vpp_config()
878 epg.bvi.set_mac(self.router_mac)
880 # The BVIs are NAT inside interfaces
881 flags = self.config_flags.NAT_IS_INSIDE
882 self.vapi.nat44_interface_add_del_feature(
883 sw_if_index=epg.bvi.sw_if_index,
884 flags=flags, is_add=1)
885 self.vapi.nat66_add_del_interface(
886 is_add=1, flags=flags,
887 sw_if_index=epg.bvi.sw_if_index)
889 if_ip4 = VppIpInterfaceAddress(self, epg.bvi, epg.bvi_ip4, 32)
890 if_ip6 = VppIpInterfaceAddress(self, epg.bvi, epg.bvi_ip6, 128)
891 if_ip4.add_vpp_config()
892 if_ip6.add_vpp_config()
894 # EPG uplink interfaces in the RD
895 VppIpInterfaceBind(self, epg.uplink, epg.rd.t4).add_vpp_config()
896 VppIpInterfaceBind(self, epg.uplink, epg.rd.t6).add_vpp_config()
898 # add the BD ARP termination entry for BVI IP
899 epg.bd_arp_ip4 = VppBridgeDomainArpEntry(self, epg.bd.bd,
900 str(self.router_mac),
902 epg.bd_arp_ip6 = VppBridgeDomainArpEntry(self, epg.bd.bd,
903 str(self.router_mac),
905 epg.bd_arp_ip4.add_vpp_config()
906 epg.bd_arp_ip6.add_vpp_config()
911 for recirc in recircs:
912 # EPG's ingress recirculation interface maps to its RD
913 VppIpInterfaceBind(self, recirc.recirc,
914 recirc.epg.rd.t4).add_vpp_config()
915 VppIpInterfaceBind(self, recirc.recirc,
916 recirc.epg.rd.t6).add_vpp_config()
918 self.vapi.nat44_interface_add_del_feature(
919 sw_if_index=recirc.recirc.sw_if_index, is_add=1)
920 self.vapi.nat66_add_del_interface(
922 sw_if_index=recirc.recirc.sw_if_index)
924 recirc.add_vpp_config()
926 for recirc in recircs:
927 self.assertTrue(find_bridge_domain_port(self,
928 recirc.epg.bd.bd.bd_id,
929 recirc.recirc.sw_if_index))
932 self.pg_enable_capture(self.pg_interfaces)
935 # routes to the endpoints. We need these since there are no
936 # adj-fibs due to the fact the the BVI address has /32 and
937 # the subnet is not attached.
939 for (ip, fip) in zip(ep.ips, ep.fips):
940 # Add static mappings for each EP from the 10/8 to 11/8 network
942 flags = self.config_flags.NAT_IS_ADDR_ONLY
943 self.vapi.nat44_add_del_static_mapping(
945 local_ip_address=ip.bytes,
946 external_ip_address=fip.bytes,
947 external_sw_if_index=0xFFFFFFFF,
951 self.vapi.nat66_add_del_static_mapping(
952 local_ip_address=ip.bytes,
953 external_ip_address=fip.bytes,
959 self.logger.info(self.vapi.cli("sh gbp endpoint"))
961 # ... results in a Gratuitous ARP/ND on the EPG's uplink
962 rx = ep.epg.uplink.get_capture(len(ep.ips), timeout=0.2)
964 for ii, ip in enumerate(ep.ips):
968 self.assertTrue(p.haslayer(ICMPv6ND_NA))
969 self.assertEqual(p[ICMPv6ND_NA].tgt, ip.address)
971 self.assertTrue(p.haslayer(ARP))
972 self.assertEqual(p[ARP].psrc, ip.address)
973 self.assertEqual(p[ARP].pdst, ip.address)
975 # add the BD ARP termination entry for floating IP
977 ba = VppBridgeDomainArpEntry(self, epg_nat.bd.bd, ep.mac,
981 # floating IPs route via EPG recirc
983 self, fip.address, fip.length,
984 [VppRoutePath(fip.address,
985 ep.recirc.recirc.sw_if_index,
986 type=FibPathType.FIB_PATH_TYPE_DVR,
987 proto=fip.dpo_proto)],
991 # L2 FIB entries in the NAT EPG BD to bridge the packets from
992 # the outside direct to the internal EPG
993 lf = VppL2FibEntry(self, epg_nat.bd.bd, ep.mac,
994 ep.recirc.recirc, bvi_mac=0)
998 # ARP packets for unknown IP are sent to the EPG uplink
1000 pkt_arp = (Ether(dst="ff:ff:ff:ff:ff:ff",
1001 src=self.pg0.remote_mac) /
1003 hwdst="ff:ff:ff:ff:ff:ff",
1004 hwsrc=self.pg0.remote_mac,
1008 self.vapi.cli("clear trace")
1009 self.pg0.add_stream(pkt_arp)
1011 self.pg_enable_capture(self.pg_interfaces)
1014 rxd = epgs[0].uplink.get_capture(1)
1017 # ARP/ND packets get a response
1019 pkt_arp = (Ether(dst="ff:ff:ff:ff:ff:ff",
1020 src=self.pg0.remote_mac) /
1022 hwdst="ff:ff:ff:ff:ff:ff",
1023 hwsrc=self.pg0.remote_mac,
1024 pdst=epgs[0].bvi_ip4.address,
1025 psrc=eps[0].ip4.address))
1027 self.send_and_expect(self.pg0, [pkt_arp], self.pg0)
1029 nsma = in6_getnsma(inet_pton(AF_INET6, eps[0].ip6.address))
1030 d = inet_ntop(AF_INET6, nsma)
1031 pkt_nd = (Ether(dst=in6_getnsmac(nsma),
1032 src=self.pg0.remote_mac) /
1033 IPv6(dst=d, src=eps[0].ip6.address) /
1034 ICMPv6ND_NS(tgt=epgs[0].bvi_ip6.address) /
1035 ICMPv6NDOptSrcLLAddr(lladdr=self.pg0.remote_mac))
1036 self.send_and_expect(self.pg0, [pkt_nd], self.pg0)
1039 # broadcast packets are flooded
1041 pkt_bcast = (Ether(dst="ff:ff:ff:ff:ff:ff",
1042 src=self.pg0.remote_mac) /
1043 IP(src=eps[0].ip4.address, dst="232.1.1.1") /
1044 UDP(sport=1234, dport=1234) /
1047 self.vapi.cli("clear trace")
1048 self.pg0.add_stream(pkt_bcast)
1050 self.pg_enable_capture(self.pg_interfaces)
1053 rxd = eps[1].itf.get_capture(1)
1054 self.assertEqual(rxd[0][Ether].dst, pkt_bcast[Ether].dst)
1055 rxd = epgs[0].uplink.get_capture(1)
1056 self.assertEqual(rxd[0][Ether].dst, pkt_bcast[Ether].dst)
1059 # packets to non-local L3 destinations dropped
1061 pkt_intra_epg_220_ip4 = (Ether(src=self.pg0.remote_mac,
1062 dst=str(self.router_mac)) /
1063 IP(src=eps[0].ip4.address,
1065 UDP(sport=1234, dport=1234) /
1067 pkt_inter_epg_222_ip4 = (Ether(src=self.pg0.remote_mac,
1068 dst=str(self.router_mac)) /
1069 IP(src=eps[0].ip4.address,
1071 UDP(sport=1234, dport=1234) /
1074 self.send_and_assert_no_replies(self.pg0,
1075 pkt_intra_epg_220_ip4 * NUM_PKTS)
1077 pkt_inter_epg_222_ip6 = (Ether(src=self.pg0.remote_mac,
1078 dst=str(self.router_mac)) /
1079 IPv6(src=eps[0].ip6.address,
1080 dst="2001:10::99") /
1081 UDP(sport=1234, dport=1234) /
1083 self.send_and_assert_no_replies(self.pg0,
1084 pkt_inter_epg_222_ip6 * NUM_PKTS)
1087 # Add the subnet routes
1090 self, rd0, "10.0.0.0", 24,
1091 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1093 self, rd0, "10.0.1.0", 24,
1094 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1096 self, rd0, "10.0.2.0", 24,
1097 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1099 self, rd0, "2001:10::1", 64,
1100 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1102 self, rd0, "2001:10:1::1", 64,
1103 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1105 self, rd0, "2001:10:2::1", 64,
1106 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1107 s41.add_vpp_config()
1108 s42.add_vpp_config()
1109 s43.add_vpp_config()
1110 s61.add_vpp_config()
1111 s62.add_vpp_config()
1112 s63.add_vpp_config()
1114 self.send_and_expect_bridged(eps[0].itf,
1115 pkt_intra_epg_220_ip4 * NUM_PKTS,
1117 self.send_and_expect_bridged(eps[0].itf,
1118 pkt_inter_epg_222_ip4 * NUM_PKTS,
1120 self.send_and_expect_bridged6(eps[0].itf,
1121 pkt_inter_epg_222_ip6 * NUM_PKTS,
1124 self.logger.info(self.vapi.cli("sh ip fib 11.0.0.2"))
1125 self.logger.info(self.vapi.cli("sh gbp endpoint-group"))
1126 self.logger.info(self.vapi.cli("sh gbp endpoint"))
1127 self.logger.info(self.vapi.cli("sh gbp recirc"))
1128 self.logger.info(self.vapi.cli("sh int"))
1129 self.logger.info(self.vapi.cli("sh int addr"))
1130 self.logger.info(self.vapi.cli("sh int feat loop6"))
1131 self.logger.info(self.vapi.cli("sh vlib graph ip4-gbp-src-classify"))
1132 self.logger.info(self.vapi.cli("sh int feat loop3"))
1133 self.logger.info(self.vapi.cli("sh int feat pg0"))
1136 # Packet destined to unknown unicast is sent on the epg uplink ...
1138 pkt_intra_epg_220_to_uplink = (Ether(src=self.pg0.remote_mac,
1139 dst="00:00:00:33:44:55") /
1140 IP(src=eps[0].ip4.address,
1142 UDP(sport=1234, dport=1234) /
1145 self.send_and_expect_bridged(eps[0].itf,
1146 pkt_intra_epg_220_to_uplink * NUM_PKTS,
1148 # ... and nowhere else
1149 self.pg1.get_capture(0, timeout=0.1)
1150 self.pg1.assert_nothing_captured(remark="Flood onto other VMS")
1152 pkt_intra_epg_221_to_uplink = (Ether(src=self.pg2.remote_mac,
1153 dst="00:00:00:33:44:66") /
1154 IP(src=eps[0].ip4.address,
1156 UDP(sport=1234, dport=1234) /
1159 self.send_and_expect_bridged(eps[2].itf,
1160 pkt_intra_epg_221_to_uplink * NUM_PKTS,
1164 # Packets from the uplink are forwarded in the absence of a contract
1166 pkt_intra_epg_220_from_uplink = (Ether(src="00:00:00:33:44:55",
1167 dst=self.pg0.remote_mac) /
1168 IP(src=eps[0].ip4.address,
1170 UDP(sport=1234, dport=1234) /
1173 self.send_and_expect_bridged(self.pg4,
1174 pkt_intra_epg_220_from_uplink * NUM_PKTS,
1178 # in the absence of policy, endpoints in the same EPG
1181 pkt_intra_epg = (Ether(src=self.pg0.remote_mac,
1182 dst=self.pg1.remote_mac) /
1183 IP(src=eps[0].ip4.address,
1184 dst=eps[1].ip4.address) /
1185 UDP(sport=1234, dport=1234) /
1188 self.send_and_expect_bridged(self.pg0,
1189 pkt_intra_epg * NUM_PKTS,
1193 # in the absence of policy, endpoints in the different EPG
1194 # cannot communicate
1196 pkt_inter_epg_220_to_221 = (Ether(src=self.pg0.remote_mac,
1197 dst=self.pg2.remote_mac) /
1198 IP(src=eps[0].ip4.address,
1199 dst=eps[2].ip4.address) /
1200 UDP(sport=1234, dport=1234) /
1202 pkt_inter_epg_221_to_220 = (Ether(src=self.pg2.remote_mac,
1203 dst=self.pg0.remote_mac) /
1204 IP(src=eps[2].ip4.address,
1205 dst=eps[0].ip4.address) /
1206 UDP(sport=1234, dport=1234) /
1208 pkt_inter_epg_220_to_222 = (Ether(src=self.pg0.remote_mac,
1209 dst=str(self.router_mac)) /
1210 IP(src=eps[0].ip4.address,
1211 dst=eps[3].ip4.address) /
1212 UDP(sport=1234, dport=1234) /
1215 self.send_and_assert_no_replies(eps[0].itf,
1216 pkt_inter_epg_220_to_221 * NUM_PKTS)
1217 self.send_and_assert_no_replies(eps[0].itf,
1218 pkt_inter_epg_220_to_222 * NUM_PKTS)
1221 # A uni-directional contract from EPG 220 -> 221
1223 acl = VppGbpAcl(self)
1224 rule = acl.create_rule(permit_deny=1, proto=17)
1225 rule2 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
1226 acl_index = acl.add_vpp_config([rule, rule2])
1227 c1 = VppGbpContract(
1228 self, 400, epgs[0].sclass, epgs[1].sclass, acl_index,
1229 [VppGbpContractRule(
1230 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1231 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1234 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1235 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1237 [ETH_P_IP, ETH_P_IPV6])
1240 self.send_and_expect_bridged(eps[0].itf,
1241 pkt_inter_epg_220_to_221 * NUM_PKTS,
1243 self.send_and_assert_no_replies(eps[0].itf,
1244 pkt_inter_epg_220_to_222 * NUM_PKTS)
1247 # contract for the return direction
1249 c2 = VppGbpContract(
1250 self, 400, epgs[1].sclass, epgs[0].sclass, acl_index,
1251 [VppGbpContractRule(
1252 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1253 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1256 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1257 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1259 [ETH_P_IP, ETH_P_IPV6])
1262 self.send_and_expect_bridged(eps[0].itf,
1263 pkt_inter_epg_220_to_221 * NUM_PKTS,
1265 self.send_and_expect_bridged(eps[2].itf,
1266 pkt_inter_epg_221_to_220 * NUM_PKTS,
1269 ds = c2.get_drop_stats()
1270 self.assertEqual(ds['packets'], 0)
1271 ps = c2.get_permit_stats()
1272 self.assertEqual(ps['packets'], NUM_PKTS)
1275 # the contract does not allow non-IP
1277 pkt_non_ip_inter_epg_220_to_221 = (Ether(src=self.pg0.remote_mac,
1278 dst=self.pg2.remote_mac) /
1280 self.send_and_assert_no_replies(eps[0].itf,
1281 pkt_non_ip_inter_epg_220_to_221 * 17)
1284 # check that inter group is still disabled for the groups
1285 # not in the contract.
1287 self.send_and_assert_no_replies(eps[0].itf,
1288 pkt_inter_epg_220_to_222 * NUM_PKTS)
1291 # A uni-directional contract from EPG 220 -> 222 'L3 routed'
1293 c3 = VppGbpContract(
1294 self, 400, epgs[0].sclass, epgs[2].sclass, acl_index,
1295 [VppGbpContractRule(
1296 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1297 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1300 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1301 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1303 [ETH_P_IP, ETH_P_IPV6])
1306 self.logger.info(self.vapi.cli("sh gbp contract"))
1308 self.send_and_expect_routed(eps[0].itf,
1309 pkt_inter_epg_220_to_222 * NUM_PKTS,
1311 str(self.router_mac))
1314 # remove both contracts, traffic stops in both directions
1316 c2.remove_vpp_config()
1317 c1.remove_vpp_config()
1318 c3.remove_vpp_config()
1319 acl.remove_vpp_config()
1321 self.send_and_assert_no_replies(eps[2].itf,
1322 pkt_inter_epg_221_to_220 * NUM_PKTS)
1323 self.send_and_assert_no_replies(eps[0].itf,
1324 pkt_inter_epg_220_to_221 * NUM_PKTS)
1325 self.send_and_expect_bridged(eps[0].itf,
1326 pkt_intra_epg * NUM_PKTS,
1330 # EPs to the outside world
1333 # in the EP's RD an external subnet via the NAT EPG's recirc
1335 self, rd0, "0.0.0.0", 0,
1336 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1337 sw_if_index=recirc_nat.recirc.sw_if_index,
1338 sclass=epg_nat.sclass)
1340 self, rd0, "11.0.0.0", 8,
1341 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1342 sw_if_index=recirc_nat.recirc.sw_if_index,
1343 sclass=epg_nat.sclass)
1344 se16 = VppGbpSubnet(
1346 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1347 sw_if_index=recirc_nat.recirc.sw_if_index,
1348 sclass=epg_nat.sclass)
1349 # in the NAT RD an external subnet via the NAT EPG's uplink
1351 self, rd20, "0.0.0.0", 0,
1352 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1353 sw_if_index=epg_nat.uplink.sw_if_index,
1354 sclass=epg_nat.sclass)
1355 se36 = VppGbpSubnet(
1356 self, rd20, "::", 0,
1357 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1358 sw_if_index=epg_nat.uplink.sw_if_index,
1359 sclass=epg_nat.sclass)
1361 self, rd20, "11.0.0.0", 8,
1362 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1363 sw_if_index=epg_nat.uplink.sw_if_index,
1364 sclass=epg_nat.sclass)
1365 se1.add_vpp_config()
1366 se2.add_vpp_config()
1367 se16.add_vpp_config()
1368 se3.add_vpp_config()
1369 se36.add_vpp_config()
1370 se4.add_vpp_config()
1372 self.logger.info(self.vapi.cli("sh ip fib 0.0.0.0/0"))
1373 self.logger.info(self.vapi.cli("sh ip fib 11.0.0.1"))
1374 self.logger.info(self.vapi.cli("sh ip6 fib ::/0"))
1375 self.logger.info(self.vapi.cli("sh ip6 fib %s" %
1379 # From an EP to an outside address: IN2OUT
1381 pkt_inter_epg_220_to_global = (Ether(src=self.pg0.remote_mac,
1382 dst=str(self.router_mac)) /
1383 IP(src=eps[0].ip4.address,
1385 UDP(sport=1234, dport=1234) /
1389 self.send_and_assert_no_replies(eps[0].itf,
1390 pkt_inter_epg_220_to_global * NUM_PKTS)
1392 acl2 = VppGbpAcl(self)
1393 rule = acl2.create_rule(permit_deny=1, proto=17, sport_from=1234,
1394 sport_to=1234, dport_from=1234, dport_to=1234)
1395 rule2 = acl2.create_rule(is_ipv6=1, permit_deny=1, proto=17,
1396 sport_from=1234, sport_to=1234,
1397 dport_from=1234, dport_to=1234)
1399 acl_index2 = acl2.add_vpp_config([rule, rule2])
1400 c4 = VppGbpContract(
1401 self, 400, epgs[0].sclass, epgs[3].sclass, acl_index2,
1402 [VppGbpContractRule(
1403 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1404 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1407 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1408 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1410 [ETH_P_IP, ETH_P_IPV6])
1413 self.send_and_expect_natted(eps[0].itf,
1414 pkt_inter_epg_220_to_global * NUM_PKTS,
1416 eps[0].fip4.address)
1418 pkt_inter_epg_220_to_global = (Ether(src=self.pg0.remote_mac,
1419 dst=str(self.router_mac)) /
1420 IPv6(src=eps[0].ip6.address,
1422 UDP(sport=1234, dport=1234) /
1425 self.send_and_expect_natted6(self.pg0,
1426 pkt_inter_epg_220_to_global * NUM_PKTS,
1428 eps[0].fip6.address)
1431 # From a global address to an EP: OUT2IN
1433 pkt_inter_epg_220_from_global = (Ether(src=str(self.router_mac),
1434 dst=self.pg0.remote_mac) /
1435 IP(dst=eps[0].fip4.address,
1437 UDP(sport=1234, dport=1234) /
1440 self.send_and_assert_no_replies(
1441 self.pg7, pkt_inter_epg_220_from_global * NUM_PKTS)
1443 c5 = VppGbpContract(
1444 self, 400, epgs[3].sclass, epgs[0].sclass, acl_index2,
1445 [VppGbpContractRule(
1446 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1447 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1450 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1451 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1453 [ETH_P_IP, ETH_P_IPV6])
1456 self.send_and_expect_unnatted(self.pg7,
1457 pkt_inter_epg_220_from_global * NUM_PKTS,
1461 pkt_inter_epg_220_from_global = (Ether(src=str(self.router_mac),
1462 dst=self.pg0.remote_mac) /
1463 IPv6(dst=eps[0].fip6.address,
1465 UDP(sport=1234, dport=1234) /
1468 self.send_and_expect_unnatted6(
1470 pkt_inter_epg_220_from_global * NUM_PKTS,
1475 # From a local VM to another local VM using resp. public addresses:
1478 pkt_intra_epg_220_global = (Ether(src=self.pg0.remote_mac,
1479 dst=str(self.router_mac)) /
1480 IP(src=eps[0].ip4.address,
1481 dst=eps[1].fip4.address) /
1482 UDP(sport=1234, dport=1234) /
1485 self.send_and_expect_double_natted(eps[0].itf,
1486 pkt_intra_epg_220_global * NUM_PKTS,
1488 eps[0].fip4.address,
1491 pkt_intra_epg_220_global = (Ether(src=self.pg0.remote_mac,
1492 dst=str(self.router_mac)) /
1493 IPv6(src=eps[0].ip6.address,
1494 dst=eps[1].fip6.address) /
1495 UDP(sport=1234, dport=1234) /
1498 self.send_and_expect_double_natted6(
1500 pkt_intra_epg_220_global * NUM_PKTS,
1502 eps[0].fip6.address,
1509 # del static mappings for each EP from the 10/8 to 11/8 network
1510 flags = self.config_flags.NAT_IS_ADDR_ONLY
1511 self.vapi.nat44_add_del_static_mapping(
1513 local_ip_address=ep.ip4.bytes,
1514 external_ip_address=ep.fip4.bytes,
1515 external_sw_if_index=0xFFFFFFFF,
1518 self.vapi.nat66_add_del_static_mapping(
1519 local_ip_address=ep.ip6.bytes,
1520 external_ip_address=ep.fip6.bytes,
1524 # IP config on the BVI interfaces
1525 if epg != epgs[0] and epg != epgs[3]:
1526 flags = self.config_flags.NAT_IS_INSIDE
1527 self.vapi.nat44_interface_add_del_feature(
1528 sw_if_index=epg.bvi.sw_if_index,
1531 self.vapi.nat66_add_del_interface(
1532 is_add=0, flags=flags,
1533 sw_if_index=epg.bvi.sw_if_index)
1535 for recirc in recircs:
1536 self.vapi.nat44_interface_add_del_feature(
1537 sw_if_index=recirc.recirc.sw_if_index,
1539 self.vapi.nat66_add_del_interface(
1541 sw_if_index=recirc.recirc.sw_if_index)
1543 def wait_for_ep_timeout(self, sw_if_index=None, ip=None, mac=None,
1544 tep=None, n_tries=100, s_time=1):
1546 if not find_gbp_endpoint(self, sw_if_index, ip, mac, tep=tep):
1548 n_tries = n_tries - 1
1550 self.assertFalse(find_gbp_endpoint(self, sw_if_index, ip, mac))
1553 def test_gbp_learn_l2(self):
1554 """ GBP L2 Endpoint Learning """
1556 drop_no_contract = self.statistics.get_err_counter(
1557 '/err/gbp-policy-port/drop-no-contract')
1558 allow_intra_class = self.statistics.get_err_counter(
1559 '/err/gbp-policy-port/allow-intra-sclass')
1561 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
1562 learnt = [{'mac': '00:00:11:11:11:01',
1564 'ip6': '2001:10::2'},
1565 {'mac': '00:00:11:11:11:02',
1567 'ip6': '2001:10::3'}]
1572 gt4 = VppIpTable(self, 1)
1573 gt4.add_vpp_config()
1574 gt6 = VppIpTable(self, 1, is_ip6=True)
1575 gt6.add_vpp_config()
1577 rd1 = VppGbpRouteDomain(self, 1, 401, gt4, gt6)
1578 rd1.add_vpp_config()
1581 # Pg2 hosts the vxlan tunnel, hosts on pg2 to act as TEPs
1582 # Pg3 hosts the IP4 UU-flood VXLAN tunnel
1583 # Pg4 hosts the IP6 UU-flood VXLAN tunnel
1585 self.pg2.config_ip4()
1586 self.pg2.resolve_arp()
1587 self.pg2.generate_remote_hosts(4)
1588 self.pg2.configure_ipv4_neighbors()
1589 self.pg3.config_ip4()
1590 self.pg3.resolve_arp()
1591 self.pg4.config_ip4()
1592 self.pg4.resolve_arp()
1595 # Add a mcast destination VXLAN-GBP tunnel for B&M traffic
1597 tun_bm = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
1600 tun_bm.add_vpp_config()
1603 # a GBP bridge domain with a BVI and a UU-flood interface
1605 bd1 = VppBridgeDomain(self, 1)
1606 bd1.add_vpp_config()
1607 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0,
1609 gbd1.add_vpp_config()
1611 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1612 self.logger.info(self.vapi.cli("sh gbp bridge"))
1614 # ... and has a /32 applied
1615 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
1616 ip_addr.add_vpp_config()
1619 # The Endpoint-group in which we are learning endpoints
1621 epg_220 = VppGbpEndpointGroup(self, 220, 112, rd1, gbd1,
1625 VppGbpEndpointRetention(2))
1626 epg_220.add_vpp_config()
1627 epg_330 = VppGbpEndpointGroup(self, 330, 113, rd1, gbd1,
1631 VppGbpEndpointRetention(2))
1632 epg_330.add_vpp_config()
1635 # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
1638 vx_tun_l2_1 = VppGbpVxlanTunnel(
1639 self, 99, bd1.bd_id,
1640 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L2,
1642 vx_tun_l2_1.add_vpp_config()
1645 # A static endpoint that the learnt endpoints are trying to
1648 ep = VppGbpEndpoint(self, self.pg0,
1650 "10.0.0.127", "11.0.0.127",
1651 "2001:10::1", "3001::1")
1654 self.assertTrue(find_route(self, ep.ip4.address, 32, table_id=1))
1656 # a packet with an sclass from an unknown EPG
1657 p = (Ether(src=self.pg2.remote_mac,
1658 dst=self.pg2.local_mac) /
1659 IP(src=self.pg2.remote_hosts[0].ip4,
1660 dst=self.pg2.local_ip4) /
1661 UDP(sport=1234, dport=48879) /
1662 VXLAN(vni=99, gpid=88, flags=0x88) /
1663 Ether(src=learnt[0]["mac"], dst=ep.mac) /
1664 IP(src=learnt[0]["ip"], dst=ep.ip4.address) /
1665 UDP(sport=1234, dport=1234) /
1668 self.send_and_assert_no_replies(self.pg2, p)
1670 self.logger.info(self.vapi.cli("sh error"))
1671 self.assert_error_counter_equal(
1672 '/err/gbp-policy-port/drop-no-contract',
1673 drop_no_contract + 1)
1676 # we should not have learnt a new tunnel endpoint, since
1677 # the EPG was not learnt.
1679 self.assertEqual(INDEX_INVALID,
1680 find_vxlan_gbp_tunnel(self,
1682 self.pg2.remote_hosts[0].ip4,
1685 # ep is not learnt, because the EPG is unknown
1686 self.assertEqual(len(self.vapi.gbp_endpoint_dump()), 1)
1689 # Learn new EPs from IP packets
1691 for ii, l in enumerate(learnt):
1692 # a packet with an sclass from a known EPG
1693 # arriving on an unknown TEP
1694 p = (Ether(src=self.pg2.remote_mac,
1695 dst=self.pg2.local_mac) /
1696 IP(src=self.pg2.remote_hosts[1].ip4,
1697 dst=self.pg2.local_ip4) /
1698 UDP(sport=1234, dport=48879) /
1699 VXLAN(vni=99, gpid=112, flags=0x88) /
1700 Ether(src=l['mac'], dst=ep.mac) /
1701 IP(src=l['ip'], dst=ep.ip4.address) /
1702 UDP(sport=1234, dport=1234) /
1705 rx = self.send_and_expect(self.pg2, [p], self.pg0)
1708 tep1_sw_if_index = find_vxlan_gbp_tunnel(
1711 self.pg2.remote_hosts[1].ip4,
1713 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
1716 # the EP is learnt via the learnt TEP
1717 # both from its MAC and its IP
1719 self.assertTrue(find_gbp_endpoint(self,
1720 vx_tun_l2_1.sw_if_index,
1722 self.assertTrue(find_gbp_endpoint(self,
1723 vx_tun_l2_1.sw_if_index,
1726 self.assert_error_counter_equal(
1727 '/err/gbp-policy-port/allow-intra-sclass',
1728 allow_intra_class + 2)
1730 self.logger.info(self.vapi.cli("show gbp endpoint"))
1731 self.logger.info(self.vapi.cli("show gbp vxlan"))
1732 self.logger.info(self.vapi.cli("show ip mfib"))
1735 # If we sleep for the threshold time, the learnt endpoints should
1739 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1743 # Learn new EPs from GARP packets received on the BD's mcast tunnel
1745 for ii, l in enumerate(learnt):
1746 # add some junk in the reserved field of the vxlan-header
1747 # next to the VNI. we should accept since reserved bits are
1749 p = (Ether(src=self.pg2.remote_mac,
1750 dst=self.pg2.local_mac) /
1751 IP(src=self.pg2.remote_hosts[1].ip4,
1753 UDP(sport=1234, dport=48879) /
1754 VXLAN(vni=88, reserved2=0x80, gpid=112, flags=0x88) /
1755 Ether(src=l['mac'], dst="ff:ff:ff:ff:ff:ff") /
1757 psrc=l['ip'], pdst=l['ip'],
1758 hwsrc=l['mac'], hwdst="ff:ff:ff:ff:ff:ff"))
1760 rx = self.send_and_expect(self.pg4, [p], self.pg0)
1763 tep1_sw_if_index = find_vxlan_gbp_tunnel(
1766 self.pg2.remote_hosts[1].ip4,
1768 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
1771 # the EP is learnt via the learnt TEP
1772 # both from its MAC and its IP
1774 self.assertTrue(find_gbp_endpoint(self,
1775 vx_tun_l2_1.sw_if_index,
1777 self.assertTrue(find_gbp_endpoint(self,
1778 vx_tun_l2_1.sw_if_index,
1782 # wait for the learnt endpoints to age out
1785 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1789 # Learn new EPs from L2 packets
1791 for ii, l in enumerate(learnt):
1792 # a packet with an sclass from a known EPG
1793 # arriving on an unknown TEP
1794 p = (Ether(src=self.pg2.remote_mac,
1795 dst=self.pg2.local_mac) /
1796 IP(src=self.pg2.remote_hosts[1].ip4,
1797 dst=self.pg2.local_ip4) /
1798 UDP(sport=1234, dport=48879) /
1799 VXLAN(vni=99, gpid=112, flags=0x88) /
1800 Ether(src=l['mac'], dst=ep.mac) /
1803 rx = self.send_and_expect(self.pg2, [p], self.pg0)
1806 tep1_sw_if_index = find_vxlan_gbp_tunnel(
1809 self.pg2.remote_hosts[1].ip4,
1811 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
1814 # the EP is learnt via the learnt TEP
1815 # both from its MAC and its IP
1817 self.assertTrue(find_gbp_endpoint(self,
1818 vx_tun_l2_1.sw_if_index,
1821 self.logger.info(self.vapi.cli("show gbp endpoint"))
1822 self.logger.info(self.vapi.cli("show gbp vxlan"))
1823 self.logger.info(self.vapi.cli("show vxlan-gbp tunnel"))
1826 # wait for the learnt endpoints to age out
1829 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1833 # repeat. the do not learn bit is set so the EPs are not learnt
1836 # a packet with an sclass from a known EPG
1837 p = (Ether(src=self.pg2.remote_mac,
1838 dst=self.pg2.local_mac) /
1839 IP(src=self.pg2.remote_hosts[1].ip4,
1840 dst=self.pg2.local_ip4) /
1841 UDP(sport=1234, dport=48879) /
1842 VXLAN(vni=99, gpid=112, flags=0x88, gpflags="D") /
1843 Ether(src=l['mac'], dst=ep.mac) /
1844 IP(src=l['ip'], dst=ep.ip4.address) /
1845 UDP(sport=1234, dport=1234) /
1848 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
1851 self.assertFalse(find_gbp_endpoint(self,
1852 vx_tun_l2_1.sw_if_index,
1859 # a packet with an sclass from a known EPG
1860 # set a reserved bit in addition to the G and I
1861 # reserved bits should not be checked on rx.
1862 p = (Ether(src=self.pg2.remote_mac,
1863 dst=self.pg2.local_mac) /
1864 IP(src=self.pg2.remote_hosts[1].ip4,
1865 dst=self.pg2.local_ip4) /
1866 UDP(sport=1234, dport=48879) /
1867 VXLAN(vni=99, gpid=112, flags=0xc8) /
1868 Ether(src=l['mac'], dst=ep.mac) /
1869 IP(src=l['ip'], dst=ep.ip4.address) /
1870 UDP(sport=1234, dport=1234) /
1873 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
1875 self.assertTrue(find_gbp_endpoint(self,
1876 vx_tun_l2_1.sw_if_index,
1880 # Static EP replies to dynamics
1882 self.logger.info(self.vapi.cli("sh l2fib bd_id 1"))
1884 p = (Ether(src=ep.mac, dst=l['mac']) /
1885 IP(dst=l['ip'], src=ep.ip4.address) /
1886 UDP(sport=1234, dport=1234) /
1889 rxs = self.send_and_expect(self.pg0, p * 17, self.pg2)
1892 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
1893 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
1894 self.assertEqual(rx[UDP].dport, 48879)
1895 # the UDP source port is a random value for hashing
1896 self.assertEqual(rx[VXLAN].gpid, 112)
1897 self.assertEqual(rx[VXLAN].vni, 99)
1898 self.assertTrue(rx[VXLAN].flags.G)
1899 self.assertTrue(rx[VXLAN].flags.Instance)
1900 self.assertTrue(rx[VXLAN].gpflags.A)
1901 self.assertFalse(rx[VXLAN].gpflags.D)
1904 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1908 # repeat in the other EPG
1909 # there's no contract between 220 and 330, but the A-bit is set
1910 # so the packet is cleared for delivery
1913 # a packet with an sclass from a known EPG
1914 p = (Ether(src=self.pg2.remote_mac,
1915 dst=self.pg2.local_mac) /
1916 IP(src=self.pg2.remote_hosts[1].ip4,
1917 dst=self.pg2.local_ip4) /
1918 UDP(sport=1234, dport=48879) /
1919 VXLAN(vni=99, gpid=113, flags=0x88, gpflags='A') /
1920 Ether(src=l['mac'], dst=ep.mac) /
1921 IP(src=l['ip'], dst=ep.ip4.address) /
1922 UDP(sport=1234, dport=1234) /
1925 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
1927 self.assertTrue(find_gbp_endpoint(self,
1928 vx_tun_l2_1.sw_if_index,
1932 # static EP cannot reach the learnt EPs since there is no contract
1933 # only test 1 EP as the others could timeout
1935 p = (Ether(src=ep.mac, dst=l['mac']) /
1936 IP(dst=learnt[0]['ip'], src=ep.ip4.address) /
1937 UDP(sport=1234, dport=1234) /
1940 self.send_and_assert_no_replies(self.pg0, [p])
1943 # refresh the entries after the check for no replies above
1946 # a packet with an sclass from a known EPG
1947 p = (Ether(src=self.pg2.remote_mac,
1948 dst=self.pg2.local_mac) /
1949 IP(src=self.pg2.remote_hosts[1].ip4,
1950 dst=self.pg2.local_ip4) /
1951 UDP(sport=1234, dport=48879) /
1952 VXLAN(vni=99, gpid=113, flags=0x88, gpflags='A') /
1953 Ether(src=l['mac'], dst=ep.mac) /
1954 IP(src=l['ip'], dst=ep.ip4.address) /
1955 UDP(sport=1234, dport=1234) /
1958 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
1960 self.assertTrue(find_gbp_endpoint(self,
1961 vx_tun_l2_1.sw_if_index,
1965 # Add the contract so they can talk
1967 acl = VppGbpAcl(self)
1968 rule = acl.create_rule(permit_deny=1, proto=17)
1969 rule2 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
1970 acl_index = acl.add_vpp_config([rule, rule2])
1971 c1 = VppGbpContract(
1972 self, 401, epg_220.sclass, epg_330.sclass, acl_index,
1973 [VppGbpContractRule(
1974 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1975 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1978 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1979 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1981 [ETH_P_IP, ETH_P_IPV6])
1985 p = (Ether(src=ep.mac, dst=l['mac']) /
1986 IP(dst=l['ip'], src=ep.ip4.address) /
1987 UDP(sport=1234, dport=1234) /
1990 self.send_and_expect(self.pg0, [p], self.pg2)
1993 # send UU packets from the local EP
1995 self.logger.info(self.vapi.cli("sh gbp bridge"))
1996 self.logger.info(self.vapi.cli("sh bridge-domain 1 detail"))
1997 p_uu = (Ether(src=ep.mac, dst="00:11:11:11:11:11") /
1998 IP(dst="10.0.0.133", src=ep.ip4.address) /
1999 UDP(sport=1234, dport=1234) /
2001 rxs = self.send_and_expect(ep.itf, [p_uu], gbd1.uu_fwd)
2003 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2005 p_bm = (Ether(src=ep.mac, dst="ff:ff:ff:ff:ff:ff") /
2006 IP(dst="10.0.0.133", src=ep.ip4.address) /
2007 UDP(sport=1234, dport=1234) /
2009 rxs = self.send_and_expect_only(ep.itf, [p_bm], tun_bm.mcast_itf)
2012 self.assertEqual(rx[IP].src, self.pg4.local_ip4)
2013 self.assertEqual(rx[IP].dst, "239.1.1.1")
2014 self.assertEqual(rx[UDP].dport, 48879)
2015 # the UDP source port is a random value for hashing
2016 self.assertEqual(rx[VXLAN].gpid, 112)
2017 self.assertEqual(rx[VXLAN].vni, 88)
2018 self.assertTrue(rx[VXLAN].flags.G)
2019 self.assertTrue(rx[VXLAN].flags.Instance)
2020 self.assertFalse(rx[VXLAN].gpflags.A)
2021 self.assertFalse(rx[VXLAN].gpflags.D)
2023 acl = VppGbpAcl(self)
2024 rule = acl.create_rule(permit_deny=1, proto=17)
2025 rule2 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
2026 acl_index = acl.add_vpp_config([rule, rule2])
2027 c2 = VppGbpContract(
2028 self, 401, epg_330.sclass, epg_220.sclass, acl_index,
2029 [VppGbpContractRule(
2030 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2031 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2034 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2035 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2037 [ETH_P_IP, ETH_P_IPV6])
2041 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
2044 # Check v6 Endpoints learning
2047 # a packet with an sclass from a known EPG
2048 p = (Ether(src=self.pg2.remote_mac,
2049 dst=self.pg2.local_mac) /
2050 IP(src=self.pg2.remote_hosts[1].ip4,
2051 dst=self.pg2.local_ip4) /
2052 UDP(sport=1234, dport=48879) /
2053 VXLAN(vni=99, gpid=113, flags=0x88) /
2054 Ether(src=l['mac'], dst=ep.mac) /
2055 IPv6(src=l['ip6'], dst=ep.ip6.address) /
2056 UDP(sport=1234, dport=1234) /
2059 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
2060 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
2062 self.assertTrue(find_gbp_endpoint(
2064 vx_tun_l2_1.sw_if_index,
2066 tep=[self.pg2.local_ip4,
2067 self.pg2.remote_hosts[1].ip4]))
2069 self.logger.info(self.vapi.cli("sh int"))
2070 self.logger.info(self.vapi.cli("sh vxlan-gbp tunnel"))
2071 self.logger.info(self.vapi.cli("sh gbp vxlan"))
2072 self.logger.info(self.vapi.cli("sh gbp endpoint"))
2073 self.logger.info(self.vapi.cli("sh gbp interface"))
2076 # EP moves to a different TEP
2079 # a packet with an sclass from a known EPG
2080 p = (Ether(src=self.pg2.remote_mac,
2081 dst=self.pg2.local_mac) /
2082 IP(src=self.pg2.remote_hosts[2].ip4,
2083 dst=self.pg2.local_ip4) /
2084 UDP(sport=1234, dport=48879) /
2085 VXLAN(vni=99, gpid=113, flags=0x88) /
2086 Ether(src=l['mac'], dst=ep.mac) /
2087 IPv6(src=l['ip6'], dst=ep.ip6.address) /
2088 UDP(sport=1234, dport=1234) /
2091 rx = self.send_and_expect(self.pg2, p * 1, self.pg0)
2092 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
2094 self.assertTrue(find_gbp_endpoint(
2096 vx_tun_l2_1.sw_if_index,
2099 tep=[self.pg2.local_ip4,
2100 self.pg2.remote_hosts[2].ip4]))
2103 # v6 remote EP reachability
2106 p = (Ether(src=ep.mac, dst=l['mac']) /
2107 IPv6(dst=l['ip6'], src=ep.ip6.address) /
2108 UDP(sport=1234, dport=1234) /
2111 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
2114 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2115 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[2].ip4)
2116 self.assertEqual(rx[UDP].dport, 48879)
2117 # the UDP source port is a random value for hashing
2118 self.assertEqual(rx[VXLAN].gpid, 112)
2119 self.assertEqual(rx[VXLAN].vni, 99)
2120 self.assertTrue(rx[VXLAN].flags.G)
2121 self.assertTrue(rx[VXLAN].flags.Instance)
2122 self.assertTrue(rx[VXLAN].gpflags.A)
2123 self.assertFalse(rx[VXLAN].gpflags.D)
2124 self.assertEqual(rx[IPv6].dst, l['ip6'])
2130 # a packet with an sclass from a known EPG
2131 p = (Ether(src=self.pg2.remote_mac,
2132 dst=self.pg2.local_mac) /
2133 IP(src=self.pg2.remote_hosts[2].ip4,
2134 dst=self.pg2.local_ip4) /
2135 UDP(sport=1234, dport=48879) /
2136 VXLAN(vni=99, gpid=112, flags=0x88) /
2137 Ether(src=l['mac'], dst=ep.mac) /
2138 IPv6(src=l['ip6'], dst=ep.ip6.address) /
2139 UDP(sport=1234, dport=1234) /
2142 rx = self.send_and_expect(self.pg2, p * 1, self.pg0)
2143 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
2145 self.assertTrue(find_gbp_endpoint(
2147 vx_tun_l2_1.sw_if_index,
2150 tep=[self.pg2.local_ip4,
2151 self.pg2.remote_hosts[2].ip4]))
2154 # check reachability and contract intra-epg
2156 allow_intra_class = self.statistics.get_err_counter(
2157 '/err/gbp-policy-mac/allow-intra-sclass')
2160 p = (Ether(src=ep.mac, dst=l['mac']) /
2161 IPv6(dst=l['ip6'], src=ep.ip6.address) /
2162 UDP(sport=1234, dport=1234) /
2165 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
2168 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2169 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[2].ip4)
2170 self.assertEqual(rx[UDP].dport, 48879)
2171 self.assertEqual(rx[VXLAN].gpid, 112)
2172 self.assertEqual(rx[VXLAN].vni, 99)
2173 self.assertTrue(rx[VXLAN].flags.G)
2174 self.assertTrue(rx[VXLAN].flags.Instance)
2175 self.assertTrue(rx[VXLAN].gpflags.A)
2176 self.assertFalse(rx[VXLAN].gpflags.D)
2177 self.assertEqual(rx[IPv6].dst, l['ip6'])
2179 allow_intra_class += NUM_PKTS
2181 self.assert_error_counter_equal(
2182 '/err/gbp-policy-mac/allow-intra-sclass',
2189 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
2191 self.pg2.unconfig_ip4()
2192 self.pg3.unconfig_ip4()
2193 self.pg4.unconfig_ip4()
2195 def test_gbp_contract(self):
2196 """ GBP Contracts """
2201 gt4 = VppIpTable(self, 0)
2202 gt4.add_vpp_config()
2203 gt6 = VppIpTable(self, 0, is_ip6=True)
2204 gt6.add_vpp_config()
2206 rd0 = VppGbpRouteDomain(self, 0, 400, gt4, gt6, None, None)
2208 rd0.add_vpp_config()
2213 bd1 = VppBridgeDomain(self, 1, arp_term=0)
2214 bd2 = VppBridgeDomain(self, 2, arp_term=0)
2216 bd1.add_vpp_config()
2217 bd2.add_vpp_config()
2219 gbd1 = VppGbpBridgeDomain(self, bd1, rd0, self.loop0)
2220 gbd2 = VppGbpBridgeDomain(self, bd2, rd0, self.loop1)
2222 gbd1.add_vpp_config()
2223 gbd2.add_vpp_config()
2226 # 3 EPGs, 2 of which share a BD.
2228 epgs = [VppGbpEndpointGroup(self, 220, 1220, rd0, gbd1,
2230 "10.0.0.128", "2001:10::128"),
2231 VppGbpEndpointGroup(self, 221, 1221, rd0, gbd1,
2233 "10.0.1.128", "2001:10:1::128"),
2234 VppGbpEndpointGroup(self, 222, 1222, rd0, gbd2,
2236 "10.0.2.128", "2001:10:2::128")]
2238 # 4 end-points, 2 in the same subnet, 3 in the same BD
2240 eps = [VppGbpEndpoint(self, self.pg0,
2242 "10.0.0.1", "11.0.0.1",
2243 "2001:10::1", "3001::1"),
2244 VppGbpEndpoint(self, self.pg1,
2246 "10.0.0.2", "11.0.0.2",
2247 "2001:10::2", "3001::2"),
2248 VppGbpEndpoint(self, self.pg2,
2250 "10.0.1.1", "11.0.0.3",
2251 "2001:10:1::1", "3001::3"),
2252 VppGbpEndpoint(self, self.pg3,
2254 "10.0.2.1", "11.0.0.4",
2255 "2001:10:2::1", "3001::4")]
2258 # Config related to each of the EPGs
2261 # IP config on the BVI interfaces
2263 VppIpInterfaceBind(self, epg.bvi, epg.rd.t4).add_vpp_config()
2264 VppIpInterfaceBind(self, epg.bvi, epg.rd.t6).add_vpp_config()
2265 epg.bvi.set_mac(self.router_mac)
2267 if_ip4 = VppIpInterfaceAddress(self, epg.bvi, epg.bvi_ip4, 32)
2268 if_ip6 = VppIpInterfaceAddress(self, epg.bvi, epg.bvi_ip6, 128)
2269 if_ip4.add_vpp_config()
2270 if_ip6.add_vpp_config()
2272 # add the BD ARP termination entry for BVI IP
2273 epg.bd_arp_ip4 = VppBridgeDomainArpEntry(self, epg.bd.bd,
2274 str(self.router_mac),
2275 epg.bvi_ip4.address)
2276 epg.bd_arp_ip4.add_vpp_config()
2279 epg.add_vpp_config()
2287 self.logger.info(self.vapi.cli("show gbp endpoint"))
2288 self.logger.info(self.vapi.cli("show interface"))
2289 self.logger.info(self.vapi.cli("show br"))
2292 # Intra epg allowed without contract
2294 pkt_intra_epg_220_to_220 = (Ether(src=self.pg0.remote_mac,
2295 dst=self.pg1.remote_mac) /
2296 IP(src=eps[0].ip4.address,
2297 dst=eps[1].ip4.address) /
2298 UDP(sport=1234, dport=1234) /
2301 self.send_and_expect_bridged(self.pg0,
2302 pkt_intra_epg_220_to_220 * 65,
2305 pkt_intra_epg_220_to_220 = (Ether(src=self.pg0.remote_mac,
2306 dst=self.pg1.remote_mac) /
2307 IPv6(src=eps[0].ip6.address,
2308 dst=eps[1].ip6.address) /
2309 UDP(sport=1234, dport=1234) /
2312 self.send_and_expect_bridged6(self.pg0,
2313 pkt_intra_epg_220_to_220 * 65,
2317 # Inter epg denied without contract
2319 pkt_inter_epg_220_to_221 = (Ether(src=self.pg0.remote_mac,
2320 dst=self.pg2.remote_mac) /
2321 IP(src=eps[0].ip4.address,
2322 dst=eps[2].ip4.address) /
2323 UDP(sport=1234, dport=1234) /
2326 self.send_and_assert_no_replies(self.pg0, pkt_inter_epg_220_to_221)
2329 # A uni-directional contract from EPG 220 -> 221
2331 acl = VppGbpAcl(self)
2332 rule = acl.create_rule(permit_deny=1, proto=17)
2333 rule2 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
2334 rule3 = acl.create_rule(permit_deny=1, proto=1)
2335 acl_index = acl.add_vpp_config([rule, rule2, rule3])
2336 c1 = VppGbpContract(
2337 self, 400, epgs[0].sclass, epgs[1].sclass, acl_index,
2338 [VppGbpContractRule(
2339 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2340 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2343 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2344 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2347 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2348 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2350 [ETH_P_IP, ETH_P_IPV6])
2353 self.send_and_expect_bridged(eps[0].itf,
2354 pkt_inter_epg_220_to_221 * 65,
2357 pkt_inter_epg_220_to_222 = (Ether(src=self.pg0.remote_mac,
2358 dst=str(self.router_mac)) /
2359 IP(src=eps[0].ip4.address,
2360 dst=eps[3].ip4.address) /
2361 UDP(sport=1234, dport=1234) /
2363 self.send_and_assert_no_replies(eps[0].itf,
2364 pkt_inter_epg_220_to_222 * 65)
2367 # ping router IP in different BD
2369 pkt_router_ping_220_to_221 = (Ether(src=self.pg0.remote_mac,
2370 dst=str(self.router_mac)) /
2371 IP(src=eps[0].ip4.address,
2372 dst=epgs[1].bvi_ip4.address) /
2373 ICMP(type='echo-request'))
2375 self.send_and_expect(self.pg0, [pkt_router_ping_220_to_221], self.pg0)
2377 pkt_router_ping_220_to_221 = (Ether(src=self.pg0.remote_mac,
2378 dst=str(self.router_mac)) /
2379 IPv6(src=eps[0].ip6.address,
2380 dst=epgs[1].bvi_ip6.address) /
2381 ICMPv6EchoRequest())
2383 self.send_and_expect(self.pg0, [pkt_router_ping_220_to_221], self.pg0)
2386 # contract for the return direction
2388 c2 = VppGbpContract(
2389 self, 400, epgs[1].sclass, epgs[0].sclass, acl_index,
2390 [VppGbpContractRule(
2391 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2392 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2395 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2396 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2398 [ETH_P_IP, ETH_P_IPV6])
2401 self.send_and_expect_bridged(eps[0].itf,
2402 pkt_inter_epg_220_to_221 * 65,
2404 pkt_inter_epg_221_to_220 = (Ether(src=self.pg2.remote_mac,
2405 dst=self.pg0.remote_mac) /
2406 IP(src=eps[2].ip4.address,
2407 dst=eps[0].ip4.address) /
2408 UDP(sport=1234, dport=1234) /
2410 self.send_and_expect_bridged(eps[2].itf,
2411 pkt_inter_epg_221_to_220 * 65,
2413 pkt_inter_epg_221_to_220 = (Ether(src=self.pg2.remote_mac,
2414 dst=str(self.router_mac)) /
2415 IP(src=eps[2].ip4.address,
2416 dst=eps[0].ip4.address) /
2417 UDP(sport=1234, dport=1234) /
2419 self.send_and_expect_routed(eps[2].itf,
2420 pkt_inter_epg_221_to_220 * 65,
2422 str(self.router_mac))
2423 pkt_inter_epg_221_to_220 = (Ether(src=self.pg2.remote_mac,
2424 dst=str(self.router_mac)) /
2425 IPv6(src=eps[2].ip6.address,
2426 dst=eps[0].ip6.address) /
2427 UDP(sport=1234, dport=1234) /
2429 self.send_and_expect_routed6(eps[2].itf,
2430 pkt_inter_epg_221_to_220 * 65,
2432 str(self.router_mac))
2435 # contract between 220 and 222 uni-direction
2437 c3 = VppGbpContract(
2438 self, 400, epgs[0].sclass, epgs[2].sclass, acl_index,
2439 [VppGbpContractRule(
2440 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2441 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2444 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2445 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2447 [ETH_P_IP, ETH_P_IPV6])
2450 self.send_and_expect(eps[0].itf,
2451 pkt_inter_epg_220_to_222 * 65,
2454 c3.remove_vpp_config()
2455 c1.remove_vpp_config()
2456 c2.remove_vpp_config()
2457 acl.remove_vpp_config()
2459 def test_gbp_bd_drop_flags(self):
2460 """ GBP BD drop flags """
2465 gt4 = VppIpTable(self, 1)
2466 gt4.add_vpp_config()
2467 gt6 = VppIpTable(self, 1, is_ip6=True)
2468 gt6.add_vpp_config()
2470 rd1 = VppGbpRouteDomain(self, 1, 401, gt4, gt6)
2471 rd1.add_vpp_config()
2474 # a GBP bridge domain with a BVI only
2476 bd1 = VppBridgeDomain(self, 1)
2477 bd1.add_vpp_config()
2479 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0,
2481 uu_drop=True, bm_drop=True)
2482 gbd1.add_vpp_config()
2484 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2485 self.logger.info(self.vapi.cli("sh gbp bridge"))
2487 # ... and has a /32 applied
2488 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2489 ip_addr.add_vpp_config()
2492 # The Endpoint-group
2494 epg_220 = VppGbpEndpointGroup(self, 220, 112, rd1, gbd1,
2498 VppGbpEndpointRetention(2))
2499 epg_220.add_vpp_config()
2501 ep = VppGbpEndpoint(self, self.pg0,
2503 "10.0.0.127", "11.0.0.127",
2504 "2001:10::1", "3001::1")
2508 # send UU/BM packet from the local EP with UU drop and BM drop enabled
2511 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2512 self.logger.info(self.vapi.cli("sh gbp bridge"))
2513 p_uu = (Ether(src=ep.mac, dst="00:11:11:11:11:11") /
2514 IP(dst="10.0.0.133", src=ep.ip4.address) /
2515 UDP(sport=1234, dport=1234) /
2517 self.send_and_assert_no_replies(ep.itf, [p_uu])
2519 p_bm = (Ether(src=ep.mac, dst="ff:ff:ff:ff:ff:ff") /
2520 IP(dst="10.0.0.133", src=ep.ip4.address) /
2521 UDP(sport=1234, dport=1234) /
2523 self.send_and_assert_no_replies(ep.itf, [p_bm])
2525 self.pg3.unconfig_ip4()
2527 self.logger.info(self.vapi.cli("sh int"))
2529 def test_gbp_bd_arp_flags(self):
2530 """ GBP BD arp flags """
2535 gt4 = VppIpTable(self, 1)
2536 gt4.add_vpp_config()
2537 gt6 = VppIpTable(self, 1, is_ip6=True)
2538 gt6.add_vpp_config()
2540 rd1 = VppGbpRouteDomain(self, 1, 401, gt4, gt6)
2541 rd1.add_vpp_config()
2544 # Pg4 hosts the IP6 UU-flood VXLAN tunnel
2546 self.pg4.config_ip4()
2547 self.pg4.resolve_arp()
2550 # Add a mcast destination VXLAN-GBP tunnel for B&M traffic
2552 tun_uu = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
2555 tun_uu.add_vpp_config()
2558 # a GBP bridge domain with a BVI and a UU-flood interface
2560 bd1 = VppBridgeDomain(self, 1)
2561 bd1.add_vpp_config()
2563 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0,
2566 gbd1.add_vpp_config()
2568 # ... and has a /32 applied
2569 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2570 ip_addr.add_vpp_config()
2573 # The Endpoint-group
2575 epg_220 = VppGbpEndpointGroup(self, 220, 112, rd1, gbd1,
2579 VppGbpEndpointRetention(2))
2580 epg_220.add_vpp_config()
2582 ep = VppGbpEndpoint(self, self.pg0,
2584 "10.0.0.127", "11.0.0.127",
2585 "2001:10::1", "3001::1")
2589 # send ARP packet from the local EP expect it on the uu interface
2591 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2592 self.logger.info(self.vapi.cli("sh gbp bridge"))
2593 p_arp = (Ether(src=ep.mac, dst="ff:ff:ff:ff:ff:ff") /
2595 psrc=ep.ip4.address, pdst="10.0.0.99",
2597 hwdst="ff:ff:ff:ff:ff:ff"))
2598 self.send_and_expect(ep.itf, [p_arp], self.pg4)
2600 self.pg4.unconfig_ip4()
2602 def test_gbp_learn_vlan_l2(self):
2603 """ GBP L2 Endpoint w/ VLANs"""
2605 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
2606 learnt = [{'mac': '00:00:11:11:11:01',
2608 'ip6': '2001:10::2'},
2609 {'mac': '00:00:11:11:11:02',
2611 'ip6': '2001:10::3'}]
2616 gt4 = VppIpTable(self, 1)
2617 gt4.add_vpp_config()
2618 gt6 = VppIpTable(self, 1, is_ip6=True)
2619 gt6.add_vpp_config()
2621 rd1 = VppGbpRouteDomain(self, 1, 401, gt4, gt6)
2622 rd1.add_vpp_config()
2625 # Pg2 hosts the vxlan tunnel, hosts on pg2 to act as TEPs
2627 self.pg2.config_ip4()
2628 self.pg2.resolve_arp()
2629 self.pg2.generate_remote_hosts(4)
2630 self.pg2.configure_ipv4_neighbors()
2631 self.pg3.config_ip4()
2632 self.pg3.resolve_arp()
2635 # The EP will be on a vlan sub-interface
2637 vlan_11 = VppDot1QSubint(self, self.pg0, 11)
2639 self.vapi.l2_interface_vlan_tag_rewrite(
2640 sw_if_index=vlan_11.sw_if_index, vtr_op=L2_VTR_OP.L2_POP_1,
2643 bd_uu_fwd = VppVxlanGbpTunnel(self, self.pg3.local_ip4,
2644 self.pg3.remote_ip4, 116)
2645 bd_uu_fwd.add_vpp_config()
2648 # a GBP bridge domain with a BVI and a UU-flood interface
2649 # The BD is marked as do not learn, so no endpoints are ever
2650 # learnt in this BD.
2652 bd1 = VppBridgeDomain(self, 1)
2653 bd1.add_vpp_config()
2654 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0, bd_uu_fwd,
2656 gbd1.add_vpp_config()
2658 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2659 self.logger.info(self.vapi.cli("sh gbp bridge"))
2661 # ... and has a /32 applied
2662 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2663 ip_addr.add_vpp_config()
2666 # The Endpoint-group in which we are learning endpoints
2668 epg_220 = VppGbpEndpointGroup(self, 220, 441, rd1, gbd1,
2672 VppGbpEndpointRetention(2))
2673 epg_220.add_vpp_config()
2676 # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
2679 vx_tun_l2_1 = VppGbpVxlanTunnel(
2680 self, 99, bd1.bd_id,
2681 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L2,
2683 vx_tun_l2_1.add_vpp_config()
2686 # A static endpoint that the learnt endpoints are trying to
2689 ep = VppGbpEndpoint(self, vlan_11,
2691 "10.0.0.127", "11.0.0.127",
2692 "2001:10::1", "3001::1")
2695 self.assertTrue(find_route(self, ep.ip4.address, 32, table_id=1))
2698 # Send to the static EP
2700 for ii, l in enumerate(learnt):
2701 # a packet with an sclass from a known EPG
2702 # arriving on an unknown TEP
2703 p = (Ether(src=self.pg2.remote_mac,
2704 dst=self.pg2.local_mac) /
2705 IP(src=self.pg2.remote_hosts[1].ip4,
2706 dst=self.pg2.local_ip4) /
2707 UDP(sport=1234, dport=48879) /
2708 VXLAN(vni=99, gpid=441, flags=0x88) /
2709 Ether(src=l['mac'], dst=ep.mac) /
2710 IP(src=l['ip'], dst=ep.ip4.address) /
2711 UDP(sport=1234, dport=1234) /
2714 rxs = self.send_and_expect(self.pg2, [p], self.pg0)
2717 # packet to EP has the EP's vlan tag
2720 self.assertEqual(rx[Dot1Q].vlan, 11)
2723 # the EP is not learnt since the BD setting prevents it
2726 self.assertFalse(find_gbp_endpoint(self,
2727 vx_tun_l2_1.sw_if_index,
2729 self.assertEqual(INDEX_INVALID,
2730 find_vxlan_gbp_tunnel(
2733 self.pg2.remote_hosts[1].ip4,
2736 self.assertEqual(len(self.vapi.gbp_endpoint_dump()), 1)
2740 # we didn't learn the remotes so they are sent to the UU-fwd
2743 p = (Ether(src=ep.mac, dst=l['mac']) /
2745 IP(dst=l['ip'], src=ep.ip4.address) /
2746 UDP(sport=1234, dport=1234) /
2749 rxs = self.send_and_expect(self.pg0, p * 17, self.pg3)
2752 self.assertEqual(rx[IP].src, self.pg3.local_ip4)
2753 self.assertEqual(rx[IP].dst, self.pg3.remote_ip4)
2754 self.assertEqual(rx[UDP].dport, 48879)
2755 # the UDP source port is a random value for hashing
2756 self.assertEqual(rx[VXLAN].gpid, 441)
2757 self.assertEqual(rx[VXLAN].vni, 116)
2758 self.assertTrue(rx[VXLAN].flags.G)
2759 self.assertTrue(rx[VXLAN].flags.Instance)
2760 self.assertFalse(rx[VXLAN].gpflags.A)
2761 self.assertFalse(rx[VXLAN].gpflags.D)
2763 self.pg2.unconfig_ip4()
2764 self.pg3.unconfig_ip4()
2766 def test_gbp_learn_l3(self):
2767 """ GBP L3 Endpoint Learning """
2769 self.vapi.cli("set logging class gbp level debug")
2771 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
2772 routed_dst_mac = "00:0c:0c:0c:0c:0c"
2773 routed_src_mac = "00:22:bd:f8:19:ff"
2775 learnt = [{'mac': '00:00:11:11:11:02',
2777 'ip6': '2001:10::2'},
2778 {'mac': '00:00:11:11:11:03',
2780 'ip6': '2001:10::3'}]
2785 t4 = VppIpTable(self, 1)
2787 t6 = VppIpTable(self, 1, True)
2790 tun_ip4_uu = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
2791 self.pg4.remote_ip4, 114)
2792 tun_ip6_uu = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
2793 self.pg4.remote_ip4, 116)
2794 tun_ip4_uu.add_vpp_config()
2795 tun_ip6_uu.add_vpp_config()
2797 rd1 = VppGbpRouteDomain(self, 2, 401, t4, t6, tun_ip4_uu, tun_ip6_uu)
2798 rd1.add_vpp_config()
2800 self.loop0.set_mac(self.router_mac)
2803 # Bind the BVI to the RD
2805 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
2806 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
2809 # Pg2 hosts the vxlan tunnel
2810 # hosts on pg2 to act as TEPs
2814 self.pg2.config_ip4()
2815 self.pg2.resolve_arp()
2816 self.pg2.generate_remote_hosts(4)
2817 self.pg2.configure_ipv4_neighbors()
2818 self.pg3.config_ip4()
2819 self.pg3.resolve_arp()
2820 self.pg4.config_ip4()
2821 self.pg4.resolve_arp()
2824 # a GBP bridge domain with a BVI and a UU-flood interface
2826 bd1 = VppBridgeDomain(self, 1)
2827 bd1.add_vpp_config()
2828 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0, self.pg3)
2829 gbd1.add_vpp_config()
2831 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2832 self.logger.info(self.vapi.cli("sh gbp bridge"))
2833 self.logger.info(self.vapi.cli("sh gbp route"))
2835 # ... and has a /32 and /128 applied
2836 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2837 ip4_addr.add_vpp_config()
2838 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 128)
2839 ip6_addr.add_vpp_config()
2842 # The Endpoint-group in which we are learning endpoints
2844 epg_220 = VppGbpEndpointGroup(self, 220, 441, rd1, gbd1,
2848 VppGbpEndpointRetention(2))
2849 epg_220.add_vpp_config()
2852 # The VXLAN GBP tunnel is in L3 mode with learning enabled
2854 vx_tun_l3 = VppGbpVxlanTunnel(
2855 self, 101, rd1.rd_id,
2856 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
2858 vx_tun_l3.add_vpp_config()
2861 # A static endpoint that the learnt endpoints are trying to
2864 ep = VppGbpEndpoint(self, self.pg0,
2866 "10.0.0.127", "11.0.0.127",
2867 "2001:10::1", "3001::1")
2871 # learn some remote IPv4 EPs
2873 for ii, l in enumerate(learnt):
2874 # a packet with an sclass from a known EPG
2875 # arriving on an unknown TEP
2876 p = (Ether(src=self.pg2.remote_mac,
2877 dst=self.pg2.local_mac) /
2878 IP(src=self.pg2.remote_hosts[1].ip4,
2879 dst=self.pg2.local_ip4) /
2880 UDP(sport=1234, dport=48879) /
2881 VXLAN(vni=101, gpid=441, flags=0x88) /
2882 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2883 IP(src=l['ip'], dst=ep.ip4.address) /
2884 UDP(sport=1234, dport=1234) /
2887 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2890 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2893 self.pg2.remote_hosts[1].ip4,
2895 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2897 # endpoint learnt via the parent GBP-vxlan interface
2898 self.assertTrue(find_gbp_endpoint(self,
2899 vx_tun_l3._sw_if_index,
2903 # Static IPv4 EP replies to learnt
2906 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2907 IP(dst=l['ip'], src=ep.ip4.address) /
2908 UDP(sport=1234, dport=1234) /
2911 rxs = self.send_and_expect(self.pg0, p * 1, self.pg2)
2914 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2915 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2916 self.assertEqual(rx[UDP].dport, 48879)
2917 # the UDP source port is a random value for hashing
2918 self.assertEqual(rx[VXLAN].gpid, 441)
2919 self.assertEqual(rx[VXLAN].vni, 101)
2920 self.assertTrue(rx[VXLAN].flags.G)
2921 self.assertTrue(rx[VXLAN].flags.Instance)
2922 self.assertTrue(rx[VXLAN].gpflags.A)
2923 self.assertFalse(rx[VXLAN].gpflags.D)
2925 inner = rx[VXLAN].payload
2927 self.assertEqual(inner[Ether].src, routed_src_mac)
2928 self.assertEqual(inner[Ether].dst, routed_dst_mac)
2929 self.assertEqual(inner[IP].src, ep.ip4.address)
2930 self.assertEqual(inner[IP].dst, l['ip'])
2933 self.assertFalse(find_gbp_endpoint(self,
2938 # learn some remote IPv6 EPs
2940 for ii, l in enumerate(learnt):
2941 # a packet with an sclass from a known EPG
2942 # arriving on an unknown TEP
2943 p = (Ether(src=self.pg2.remote_mac,
2944 dst=self.pg2.local_mac) /
2945 IP(src=self.pg2.remote_hosts[1].ip4,
2946 dst=self.pg2.local_ip4) /
2947 UDP(sport=1234, dport=48879) /
2948 VXLAN(vni=101, gpid=441, flags=0x88) /
2949 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2950 IPv6(src=l['ip6'], dst=ep.ip6.address) /
2951 UDP(sport=1234, dport=1234) /
2954 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2957 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2960 self.pg2.remote_hosts[1].ip4,
2962 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2964 self.logger.info(self.vapi.cli("show gbp bridge"))
2965 self.logger.info(self.vapi.cli("show vxlan-gbp tunnel"))
2966 self.logger.info(self.vapi.cli("show gbp vxlan"))
2967 self.logger.info(self.vapi.cli("show int addr"))
2969 # endpoint learnt via the TEP
2970 self.assertTrue(find_gbp_endpoint(self, ip=l['ip6']))
2972 self.logger.info(self.vapi.cli("show gbp endpoint"))
2973 self.logger.info(self.vapi.cli("show ip fib index 1 %s" % l['ip']))
2976 # Static EP replies to learnt
2979 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2980 IPv6(dst=l['ip6'], src=ep.ip6.address) /
2981 UDP(sport=1234, dport=1234) /
2984 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
2987 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2988 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2989 self.assertEqual(rx[UDP].dport, 48879)
2990 # the UDP source port is a random value for hashing
2991 self.assertEqual(rx[VXLAN].gpid, 441)
2992 self.assertEqual(rx[VXLAN].vni, 101)
2993 self.assertTrue(rx[VXLAN].flags.G)
2994 self.assertTrue(rx[VXLAN].flags.Instance)
2995 self.assertTrue(rx[VXLAN].gpflags.A)
2996 self.assertFalse(rx[VXLAN].gpflags.D)
2998 inner = rx[VXLAN].payload
3000 self.assertEqual(inner[Ether].src, routed_src_mac)
3001 self.assertEqual(inner[Ether].dst, routed_dst_mac)
3002 self.assertEqual(inner[IPv6].src, ep.ip6.address)
3003 self.assertEqual(inner[IPv6].dst, l['ip6'])
3005 self.logger.info(self.vapi.cli("sh gbp endpoint"))
3007 self.wait_for_ep_timeout(ip=l['ip'])
3010 # Static sends to unknown EP with no route
3012 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
3013 IP(dst="10.0.0.99", src=ep.ip4.address) /
3014 UDP(sport=1234, dport=1234) /
3017 self.send_and_assert_no_replies(self.pg0, [p])
3020 # Add a route to static EP's v4 and v6 subnet
3022 se_10_24 = VppGbpSubnet(
3023 self, rd1, "10.0.0.0", 24,
3024 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT)
3025 se_10_24.add_vpp_config()
3028 # static pings router
3030 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
3031 IP(dst=epg_220.bvi_ip4.address, src=ep.ip4.address) /
3032 UDP(sport=1234, dport=1234) /
3035 self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg0)
3037 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
3038 IPv6(dst=epg_220.bvi_ip6.address, src=ep.ip6.address) /
3039 UDP(sport=1234, dport=1234) /
3042 self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg0)
3045 # packets to address in the subnet are sent on the uu-fwd
3047 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
3048 IP(dst="10.0.0.99", src=ep.ip4.address) /
3049 UDP(sport=1234, dport=1234) /
3052 rxs = self.send_and_expect(self.pg0, [p], self.pg4)
3054 self.assertEqual(rx[IP].src, self.pg4.local_ip4)
3055 self.assertEqual(rx[IP].dst, self.pg4.remote_ip4)
3056 self.assertEqual(rx[UDP].dport, 48879)
3057 # the UDP source port is a random value for hashing
3058 self.assertEqual(rx[VXLAN].gpid, 441)
3059 self.assertEqual(rx[VXLAN].vni, 114)
3060 self.assertTrue(rx[VXLAN].flags.G)
3061 self.assertTrue(rx[VXLAN].flags.Instance)
3062 # policy is not applied to packets sent to the uu-fwd interfaces
3063 self.assertFalse(rx[VXLAN].gpflags.A)
3064 self.assertFalse(rx[VXLAN].gpflags.D)
3067 # learn some remote IPv4 EPs
3069 for ii, l in enumerate(learnt):
3070 # a packet with an sclass from a known EPG
3071 # arriving on an unknown TEP
3072 p = (Ether(src=self.pg2.remote_mac,
3073 dst=self.pg2.local_mac) /
3074 IP(src=self.pg2.remote_hosts[2].ip4,
3075 dst=self.pg2.local_ip4) /
3076 UDP(sport=1234, dport=48879) /
3077 VXLAN(vni=101, gpid=441, flags=0x88) /
3078 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
3079 IP(src=l['ip'], dst=ep.ip4.address) /
3080 UDP(sport=1234, dport=1234) /
3083 rx = self.send_and_expect(self.pg2, [p], self.pg0)
3086 tep1_sw_if_index = find_vxlan_gbp_tunnel(
3089 self.pg2.remote_hosts[2].ip4,
3091 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
3093 # endpoint learnt via the parent GBP-vxlan interface
3094 self.assertTrue(find_gbp_endpoint(self,
3095 vx_tun_l3._sw_if_index,
3099 # Add a remote endpoint from the API
3101 rep_88 = VppGbpEndpoint(self, vx_tun_l3,
3103 "10.0.0.88", "11.0.0.88",
3104 "2001:10::88", "3001::88",
3105 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
3107 self.pg2.remote_hosts[2].ip4,
3109 rep_88.add_vpp_config()
3112 # Add a remote endpoint from the API that matches an existing one
3113 # this is a lower priority, hence the packet is sent to the DP leanrt
3116 rep_2 = VppGbpEndpoint(self, vx_tun_l3,
3118 learnt[0]['ip'], "11.0.0.101",
3119 learnt[0]['ip6'], "3001::101",
3120 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
3122 self.pg2.remote_hosts[1].ip4,
3124 rep_2.add_vpp_config()
3127 # Add a route to the learned EP's v4 subnet
3128 # packets should be send on the v4/v6 uu=fwd interface resp.
3130 se_10_1_24 = VppGbpSubnet(
3131 self, rd1, "10.0.1.0", 24,
3132 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT)
3133 se_10_1_24.add_vpp_config()
3135 self.logger.info(self.vapi.cli("show gbp endpoint"))
3137 ips = ["10.0.0.88", learnt[0]['ip']]
3139 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
3140 IP(dst=ip, src=ep.ip4.address) /
3141 UDP(sport=1234, dport=1234) /
3144 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
3147 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
3148 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[2].ip4)
3149 self.assertEqual(rx[UDP].dport, 48879)
3150 # the UDP source port is a random value for hashing
3151 self.assertEqual(rx[VXLAN].gpid, 441)
3152 self.assertEqual(rx[VXLAN].vni, 101)
3153 self.assertTrue(rx[VXLAN].flags.G)
3154 self.assertTrue(rx[VXLAN].flags.Instance)
3155 self.assertTrue(rx[VXLAN].gpflags.A)
3156 self.assertFalse(rx[VXLAN].gpflags.D)
3158 inner = rx[VXLAN].payload
3160 self.assertEqual(inner[Ether].src, routed_src_mac)
3161 self.assertEqual(inner[Ether].dst, routed_dst_mac)
3162 self.assertEqual(inner[IP].src, ep.ip4.address)
3163 self.assertEqual(inner[IP].dst, ip)
3166 # remove the API remote EPs, only API sourced is gone, the DP
3167 # learnt one remains
3169 rep_88.remove_vpp_config()
3170 rep_2.remove_vpp_config()
3172 self.assertTrue(find_gbp_endpoint(self, ip=rep_2.ip4.address))
3174 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
3175 IP(src=ep.ip4.address, dst=rep_2.ip4.address) /
3176 UDP(sport=1234, dport=1234) /
3178 rxs = self.send_and_expect(self.pg0, [p], self.pg2)
3180 self.assertFalse(find_gbp_endpoint(self, ip=rep_88.ip4.address))
3182 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
3183 IP(src=ep.ip4.address, dst=rep_88.ip4.address) /
3184 UDP(sport=1234, dport=1234) /
3186 rxs = self.send_and_expect(self.pg0, [p], self.pg4)
3189 # to appease the testcase we cannot have the registered EP still
3190 # present (because it's DP learnt) when the TC ends so wait until
3193 self.wait_for_ep_timeout(ip=rep_88.ip4.address)
3194 self.wait_for_ep_timeout(ip=rep_2.ip4.address)
3197 # Same as above, learn a remote EP via CP and DP
3198 # this time remove the DP one first. expect the CP data to remain
3200 rep_3 = VppGbpEndpoint(self, vx_tun_l3,
3202 "10.0.1.4", "11.0.0.103",
3203 "2001::10:3", "3001::103",
3204 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
3206 self.pg2.remote_hosts[1].ip4,
3208 rep_3.add_vpp_config()
3210 p = (Ether(src=self.pg2.remote_mac,
3211 dst=self.pg2.local_mac) /
3212 IP(src=self.pg2.remote_hosts[2].ip4,
3213 dst=self.pg2.local_ip4) /
3214 UDP(sport=1234, dport=48879) /
3215 VXLAN(vni=101, gpid=441, flags=0x88) /
3216 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
3217 IP(src="10.0.1.4", dst=ep.ip4.address) /
3218 UDP(sport=1234, dport=1234) /
3220 rxs = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
3222 self.assertTrue(find_gbp_endpoint(self,
3223 vx_tun_l3._sw_if_index,
3224 ip=rep_3.ip4.address,
3225 tep=[self.pg2.local_ip4,
3226 self.pg2.remote_hosts[2].ip4]))
3228 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
3229 IP(dst="10.0.1.4", src=ep.ip4.address) /
3230 UDP(sport=1234, dport=1234) /
3232 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
3234 # host 2 is the DP learned TEP
3236 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
3237 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[2].ip4)
3239 self.wait_for_ep_timeout(ip=rep_3.ip4.address,
3240 tep=[self.pg2.local_ip4,
3241 self.pg2.remote_hosts[2].ip4])
3243 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
3245 # host 1 is the CP learned TEP
3247 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
3248 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
3251 # shutdown with learnt endpoint present
3253 p = (Ether(src=self.pg2.remote_mac,
3254 dst=self.pg2.local_mac) /
3255 IP(src=self.pg2.remote_hosts[1].ip4,
3256 dst=self.pg2.local_ip4) /
3257 UDP(sport=1234, dport=48879) /
3258 VXLAN(vni=101, gpid=441, flags=0x88) /
3259 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
3260 IP(src=learnt[1]['ip'], dst=ep.ip4.address) /
3261 UDP(sport=1234, dport=1234) /
3264 rx = self.send_and_expect(self.pg2, [p], self.pg0)
3266 # endpoint learnt via the parent GBP-vxlan interface
3267 self.assertTrue(find_gbp_endpoint(self,
3268 vx_tun_l3._sw_if_index,
3273 # remote endpoint becomes local
3275 self.pg2.unconfig_ip4()
3276 self.pg3.unconfig_ip4()
3277 self.pg4.unconfig_ip4()
3279 def test_gbp_redirect(self):
3280 """ GBP Endpoint Redirect """
3282 self.vapi.cli("set logging class gbp level debug")
3284 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
3285 routed_dst_mac = "00:0c:0c:0c:0c:0c"
3286 routed_src_mac = "00:22:bd:f8:19:ff"
3288 learnt = [{'mac': '00:00:11:11:11:02',
3290 'ip6': '2001:10::2'},
3291 {'mac': '00:00:11:11:11:03',
3293 'ip6': '2001:10::3'}]
3298 t4 = VppIpTable(self, 1)
3300 t6 = VppIpTable(self, 1, True)
3303 rd1 = VppGbpRouteDomain(self, 2, 402, t4, t6)
3304 rd1.add_vpp_config()
3306 self.loop0.set_mac(self.router_mac)
3309 # Bind the BVI to the RD
3311 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
3312 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
3315 # Pg7 hosts a BD's UU-fwd
3317 self.pg7.config_ip4()
3318 self.pg7.resolve_arp()
3321 # a GBP bridge domains for the EPs
3323 bd1 = VppBridgeDomain(self, 1)
3324 bd1.add_vpp_config()
3325 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0)
3326 gbd1.add_vpp_config()
3328 bd2 = VppBridgeDomain(self, 2)
3329 bd2.add_vpp_config()
3330 gbd2 = VppGbpBridgeDomain(self, bd2, rd1, self.loop1)
3331 gbd2.add_vpp_config()
3333 # ... and has a /32 and /128 applied
3334 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
3335 ip4_addr.add_vpp_config()
3336 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 128)
3337 ip6_addr.add_vpp_config()
3338 ip4_addr = VppIpInterfaceAddress(self, gbd2.bvi, "10.0.1.128", 32)
3339 ip4_addr.add_vpp_config()
3340 ip6_addr = VppIpInterfaceAddress(self, gbd2.bvi, "2001:11::128", 128)
3341 ip6_addr.add_vpp_config()
3344 # The Endpoint-groups in which we are learning endpoints
3346 epg_220 = VppGbpEndpointGroup(self, 220, 440, rd1, gbd1,
3350 VppGbpEndpointRetention(2))
3351 epg_220.add_vpp_config()
3352 epg_221 = VppGbpEndpointGroup(self, 221, 441, rd1, gbd2,
3356 VppGbpEndpointRetention(2))
3357 epg_221.add_vpp_config()
3358 epg_222 = VppGbpEndpointGroup(self, 222, 442, rd1, gbd1,
3362 VppGbpEndpointRetention(2))
3363 epg_222.add_vpp_config()
3366 # a GBP bridge domains for the SEPs
3368 bd_uu1 = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
3369 self.pg7.remote_ip4, 116)
3370 bd_uu1.add_vpp_config()
3371 bd_uu2 = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
3372 self.pg7.remote_ip4, 117)
3373 bd_uu2.add_vpp_config()
3375 bd3 = VppBridgeDomain(self, 3)
3376 bd3.add_vpp_config()
3377 gbd3 = VppGbpBridgeDomain(self, bd3, rd1, self.loop2,
3378 bd_uu1, learn=False)
3379 gbd3.add_vpp_config()
3380 bd4 = VppBridgeDomain(self, 4)
3381 bd4.add_vpp_config()
3382 gbd4 = VppGbpBridgeDomain(self, bd4, rd1, self.loop3,
3383 bd_uu2, learn=False)
3384 gbd4.add_vpp_config()
3387 # EPGs in which the service endpoints exist
3389 epg_320 = VppGbpEndpointGroup(self, 320, 550, rd1, gbd3,
3393 VppGbpEndpointRetention(2))
3394 epg_320.add_vpp_config()
3395 epg_321 = VppGbpEndpointGroup(self, 321, 551, rd1, gbd4,
3399 VppGbpEndpointRetention(2))
3400 epg_321.add_vpp_config()
3403 # three local endpoints
3405 ep1 = VppGbpEndpoint(self, self.pg0,
3407 "10.0.0.1", "11.0.0.1",
3408 "2001:10::1", "3001:10::1")
3409 ep1.add_vpp_config()
3410 ep2 = VppGbpEndpoint(self, self.pg1,
3412 "10.0.1.1", "11.0.1.1",
3413 "2001:11::1", "3001:11::1")
3414 ep2.add_vpp_config()
3415 ep3 = VppGbpEndpoint(self, self.pg2,
3417 "10.0.2.2", "11.0.2.2",
3418 "2001:12::1", "3001:12::1")
3419 ep3.add_vpp_config()
3424 sep1 = VppGbpEndpoint(self, self.pg3,
3426 "12.0.0.1", "13.0.0.1",
3427 "4001:10::1", "5001:10::1")
3428 sep1.add_vpp_config()
3429 sep2 = VppGbpEndpoint(self, self.pg4,
3431 "12.0.0.2", "13.0.0.2",
3432 "4001:10::2", "5001:10::2")
3433 sep2.add_vpp_config()
3434 sep3 = VppGbpEndpoint(self, self.pg5,
3436 "12.0.1.1", "13.0.1.1",
3437 "4001:11::1", "5001:11::1")
3438 sep3.add_vpp_config()
3439 # this EP is not installed immediately
3440 sep4 = VppGbpEndpoint(self, self.pg6,
3442 "12.0.1.2", "13.0.1.2",
3443 "4001:11::2", "5001:11::2")
3446 # an L2 switch packet between local EPs in different EPGs
3447 # different dest ports on each so the are LB hashed differently
3449 p4 = [(Ether(src=ep1.mac, dst=ep3.mac) /
3450 IP(src=ep1.ip4.address, dst=ep3.ip4.address) /
3451 UDP(sport=1234, dport=1234) /
3453 (Ether(src=ep3.mac, dst=ep1.mac) /
3454 IP(src=ep3.ip4.address, dst=ep1.ip4.address) /
3455 UDP(sport=1234, dport=1234) /
3457 p6 = [(Ether(src=ep1.mac, dst=ep3.mac) /
3458 IPv6(src=ep1.ip6.address, dst=ep3.ip6.address) /
3459 UDP(sport=1234, dport=1234) /
3461 (Ether(src=ep3.mac, dst=ep1.mac) /
3462 IPv6(src=ep3.ip6.address, dst=ep1.ip6.address) /
3463 UDP(sport=1234, dport=1230) /
3466 # should be dropped since no contract yet
3467 self.send_and_assert_no_replies(self.pg0, [p4[0]])
3468 self.send_and_assert_no_replies(self.pg0, [p6[0]])
3471 # Add a contract with a rule to load-balance redirect via SEP1 and SEP2
3472 # one of the next-hops is via an EP that is not known
3474 acl = VppGbpAcl(self)
3475 rule4 = acl.create_rule(permit_deny=1, proto=17)
3476 rule6 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
3477 acl_index = acl.add_vpp_config([rule4, rule6])
3480 # test the src-ip hash mode
3482 c1 = VppGbpContract(
3483 self, 402, epg_220.sclass, epg_222.sclass, acl_index,
3484 [VppGbpContractRule(
3485 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3486 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3487 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3488 sep1.ip4, sep1.epg.rd),
3489 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3490 sep2.ip4, sep2.epg.rd)]),
3492 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3493 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3494 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3495 sep3.ip6, sep3.epg.rd),
3496 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3497 sep4.ip6, sep4.epg.rd)])],
3498 [ETH_P_IP, ETH_P_IPV6])
3501 c2 = VppGbpContract(
3502 self, 402, epg_222.sclass, epg_220.sclass, acl_index,
3503 [VppGbpContractRule(
3504 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3505 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3506 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3507 sep1.ip4, sep1.epg.rd),
3508 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3509 sep2.ip4, sep2.epg.rd)]),
3511 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3512 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3513 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3514 sep3.ip6, sep3.epg.rd),
3515 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3516 sep4.ip6, sep4.epg.rd)])],
3517 [ETH_P_IP, ETH_P_IPV6])
3521 # send again with the contract preset, now packets arrive
3522 # at SEP1 or SEP2 depending on the hashing
3524 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3527 self.assertEqual(rx[Ether].src, routed_src_mac)
3528 self.assertEqual(rx[Ether].dst, sep1.mac)
3529 self.assertEqual(rx[IP].src, ep1.ip4.address)
3530 self.assertEqual(rx[IP].dst, ep3.ip4.address)
3532 rxs = self.send_and_expect(self.pg2, p4[1] * 17, sep2.itf)
3535 self.assertEqual(rx[Ether].src, routed_src_mac)
3536 self.assertEqual(rx[Ether].dst, sep2.mac)
3537 self.assertEqual(rx[IP].src, ep3.ip4.address)
3538 self.assertEqual(rx[IP].dst, ep1.ip4.address)
3540 rxs = self.send_and_expect(self.pg0, p6[0] * 17, self.pg7)
3543 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3544 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3545 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3546 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
3547 self.assertEqual(rx[VXLAN].vni, 117)
3548 self.assertTrue(rx[VXLAN].flags.G)
3549 self.assertTrue(rx[VXLAN].flags.Instance)
3550 # redirect policy has been applied
3551 self.assertTrue(rx[VXLAN].gpflags.A)
3552 self.assertFalse(rx[VXLAN].gpflags.D)
3554 inner = rx[VXLAN].payload
3556 self.assertEqual(inner[Ether].src, routed_src_mac)
3557 self.assertEqual(inner[Ether].dst, sep4.mac)
3558 self.assertEqual(inner[IPv6].src, ep1.ip6.address)
3559 self.assertEqual(inner[IPv6].dst, ep3.ip6.address)
3561 rxs = self.send_and_expect(self.pg2, p6[1] * 17, sep3.itf)
3564 self.assertEqual(rx[Ether].src, routed_src_mac)
3565 self.assertEqual(rx[Ether].dst, sep3.mac)
3566 self.assertEqual(rx[IPv6].src, ep3.ip6.address)
3567 self.assertEqual(rx[IPv6].dst, ep1.ip6.address)
3570 # programme the unknown EP
3572 sep4.add_vpp_config()
3574 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep4.itf)
3577 self.assertEqual(rx[Ether].src, routed_src_mac)
3578 self.assertEqual(rx[Ether].dst, sep4.mac)
3579 self.assertEqual(rx[IPv6].src, ep1.ip6.address)
3580 self.assertEqual(rx[IPv6].dst, ep3.ip6.address)
3583 # and revert back to unprogrammed
3585 sep4.remove_vpp_config()
3587 rxs = self.send_and_expect(self.pg0, p6[0] * 17, self.pg7)
3590 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3591 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3592 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3593 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
3594 self.assertEqual(rx[VXLAN].vni, 117)
3595 self.assertTrue(rx[VXLAN].flags.G)
3596 self.assertTrue(rx[VXLAN].flags.Instance)
3597 # redirect policy has been applied
3598 self.assertTrue(rx[VXLAN].gpflags.A)
3599 self.assertFalse(rx[VXLAN].gpflags.D)
3601 inner = rx[VXLAN].payload
3603 self.assertEqual(inner[Ether].src, routed_src_mac)
3604 self.assertEqual(inner[Ether].dst, sep4.mac)
3605 self.assertEqual(inner[IPv6].src, ep1.ip6.address)
3606 self.assertEqual(inner[IPv6].dst, ep3.ip6.address)
3608 c1.remove_vpp_config()
3609 c2.remove_vpp_config()
3612 # test the symmetric hash mode
3614 c1 = VppGbpContract(
3615 self, 402, epg_220.sclass, epg_222.sclass, acl_index,
3616 [VppGbpContractRule(
3617 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3618 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3619 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3620 sep1.ip4, sep1.epg.rd),
3621 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3622 sep2.ip4, sep2.epg.rd)]),
3624 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3625 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3626 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3627 sep3.ip6, sep3.epg.rd),
3628 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3629 sep4.ip6, sep4.epg.rd)])],
3630 [ETH_P_IP, ETH_P_IPV6])
3633 c2 = VppGbpContract(
3634 self, 402, epg_222.sclass, epg_220.sclass, acl_index,
3635 [VppGbpContractRule(
3636 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3637 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3638 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3639 sep1.ip4, sep1.epg.rd),
3640 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3641 sep2.ip4, sep2.epg.rd)]),
3643 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3644 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3645 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3646 sep3.ip6, sep3.epg.rd),
3647 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3648 sep4.ip6, sep4.epg.rd)])],
3649 [ETH_P_IP, ETH_P_IPV6])
3653 # send again with the contract preset, now packets arrive
3654 # at SEP1 for both directions
3656 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3659 self.assertEqual(rx[Ether].src, routed_src_mac)
3660 self.assertEqual(rx[Ether].dst, sep1.mac)
3661 self.assertEqual(rx[IP].src, ep1.ip4.address)
3662 self.assertEqual(rx[IP].dst, ep3.ip4.address)
3664 rxs = self.send_and_expect(self.pg2, p4[1] * 17, sep1.itf)
3667 self.assertEqual(rx[Ether].src, routed_src_mac)
3668 self.assertEqual(rx[Ether].dst, sep1.mac)
3669 self.assertEqual(rx[IP].src, ep3.ip4.address)
3670 self.assertEqual(rx[IP].dst, ep1.ip4.address)
3673 # programme the unknown EP for the L3 tests
3675 sep4.add_vpp_config()
3678 # an L3 switch packet between local EPs in different EPGs
3679 # different dest ports on each so the are LB hashed differently
3681 p4 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3682 IP(src=ep1.ip4.address, dst=ep2.ip4.address) /
3683 UDP(sport=1234, dport=1234) /
3685 (Ether(src=ep2.mac, dst=str(self.router_mac)) /
3686 IP(src=ep2.ip4.address, dst=ep1.ip4.address) /
3687 UDP(sport=1234, dport=1234) /
3689 p6 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3690 IPv6(src=ep1.ip6.address, dst=ep2.ip6.address) /
3691 UDP(sport=1234, dport=1234) /
3693 (Ether(src=ep2.mac, dst=str(self.router_mac)) /
3694 IPv6(src=ep2.ip6.address, dst=ep1.ip6.address) /
3695 UDP(sport=1234, dport=1234) /
3698 c3 = VppGbpContract(
3699 self, 402, epg_220.sclass, epg_221.sclass, acl_index,
3700 [VppGbpContractRule(
3701 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3702 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3703 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3704 sep1.ip4, sep1.epg.rd),
3705 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3706 sep2.ip4, sep2.epg.rd)]),
3708 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3709 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3710 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3711 sep3.ip6, sep3.epg.rd),
3712 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3713 sep4.ip6, sep4.epg.rd)])],
3714 [ETH_P_IP, ETH_P_IPV6])
3717 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3720 self.assertEqual(rx[Ether].src, routed_src_mac)
3721 self.assertEqual(rx[Ether].dst, sep1.mac)
3722 self.assertEqual(rx[IP].src, ep1.ip4.address)
3723 self.assertEqual(rx[IP].dst, ep2.ip4.address)
3726 # learn a remote EP in EPG 221
3727 # packets coming from unknown remote EPs will be leant & redirected
3729 vx_tun_l3 = VppGbpVxlanTunnel(
3730 self, 444, rd1.rd_id,
3731 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
3733 vx_tun_l3.add_vpp_config()
3735 c4 = VppGbpContract(
3736 self, 402, epg_221.sclass, epg_220.sclass, acl_index,
3737 [VppGbpContractRule(
3738 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3739 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3740 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3741 sep1.ip4, sep1.epg.rd),
3742 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3743 sep2.ip4, sep2.epg.rd)]),
3745 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3746 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3747 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3748 sep3.ip6, sep3.epg.rd),
3749 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3750 sep4.ip6, sep4.epg.rd)])],
3751 [ETH_P_IP, ETH_P_IPV6])
3754 p = (Ether(src=self.pg7.remote_mac,
3755 dst=self.pg7.local_mac) /
3756 IP(src=self.pg7.remote_ip4,
3757 dst=self.pg7.local_ip4) /
3758 UDP(sport=1234, dport=48879) /
3759 VXLAN(vni=444, gpid=441, flags=0x88) /
3760 Ether(src="00:22:22:22:22:33", dst=str(self.router_mac)) /
3761 IP(src="10.0.0.88", dst=ep1.ip4.address) /
3762 UDP(sport=1234, dport=1234) /
3765 # unknown remote EP to local EP redirected
3766 rxs = self.send_and_expect(self.pg7, [p], sep1.itf)
3769 self.assertEqual(rx[Ether].src, routed_src_mac)
3770 self.assertEqual(rx[Ether].dst, sep1.mac)
3771 self.assertEqual(rx[IP].src, "10.0.0.88")
3772 self.assertEqual(rx[IP].dst, ep1.ip4.address)
3774 # endpoint learnt via the parent GBP-vxlan interface
3775 self.assertTrue(find_gbp_endpoint(self,
3776 vx_tun_l3._sw_if_index,
3779 p = (Ether(src=self.pg7.remote_mac,
3780 dst=self.pg7.local_mac) /
3781 IP(src=self.pg7.remote_ip4,
3782 dst=self.pg7.local_ip4) /
3783 UDP(sport=1234, dport=48879) /
3784 VXLAN(vni=444, gpid=441, flags=0x88) /
3785 Ether(src="00:22:22:22:22:33", dst=str(self.router_mac)) /
3786 IPv6(src="2001:10::88", dst=ep1.ip6.address) /
3787 UDP(sport=1234, dport=1234) /
3790 # unknown remote EP to local EP redirected (ipv6)
3791 rxs = self.send_and_expect(self.pg7, [p], sep3.itf)
3794 self.assertEqual(rx[Ether].src, routed_src_mac)
3795 self.assertEqual(rx[Ether].dst, sep3.mac)
3796 self.assertEqual(rx[IPv6].src, "2001:10::88")
3797 self.assertEqual(rx[IPv6].dst, ep1.ip6.address)
3799 # endpoint learnt via the parent GBP-vxlan interface
3800 self.assertTrue(find_gbp_endpoint(self,
3801 vx_tun_l3._sw_if_index,
3805 # L3 switch from local to remote EP
3807 p4 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3808 IP(src=ep1.ip4.address, dst="10.0.0.88") /
3809 UDP(sport=1234, dport=1234) /
3811 p6 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3812 IPv6(src=ep1.ip6.address, dst="2001:10::88") /
3813 UDP(sport=1234, dport=1234) /
3816 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3819 self.assertEqual(rx[Ether].src, routed_src_mac)
3820 self.assertEqual(rx[Ether].dst, sep1.mac)
3821 self.assertEqual(rx[IP].src, ep1.ip4.address)
3822 self.assertEqual(rx[IP].dst, "10.0.0.88")
3824 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep4.itf)
3827 self.assertEqual(rx[Ether].src, routed_src_mac)
3828 self.assertEqual(rx[Ether].dst, sep4.mac)
3829 self.assertEqual(rx[IPv6].src, ep1.ip6.address)
3830 self.assertEqual(rx[IPv6].dst, "2001:10::88")
3833 # test the dst-ip hash mode
3835 c5 = VppGbpContract(
3836 self, 402, epg_220.sclass, epg_221.sclass, acl_index,
3837 [VppGbpContractRule(
3838 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3839 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
3840 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3841 sep1.ip4, sep1.epg.rd),
3842 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3843 sep2.ip4, sep2.epg.rd)]),
3845 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3846 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
3847 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3848 sep3.ip6, sep3.epg.rd),
3849 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3850 sep4.ip6, sep4.epg.rd)])],
3851 [ETH_P_IP, ETH_P_IPV6])
3854 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3857 self.assertEqual(rx[Ether].src, routed_src_mac)
3858 self.assertEqual(rx[Ether].dst, sep1.mac)
3859 self.assertEqual(rx[IP].src, ep1.ip4.address)
3860 self.assertEqual(rx[IP].dst, "10.0.0.88")
3862 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep3.itf)
3865 self.assertEqual(rx[Ether].src, routed_src_mac)
3866 self.assertEqual(rx[Ether].dst, sep3.mac)
3867 self.assertEqual(rx[IPv6].src, ep1.ip6.address)
3868 self.assertEqual(rx[IPv6].dst, "2001:10::88")
3871 # a programmed remote SEP in EPG 320
3874 # gbp vxlan tunnel for the remote SEP
3875 vx_tun_l3_sep = VppGbpVxlanTunnel(
3876 self, 555, rd1.rd_id,
3877 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
3879 vx_tun_l3_sep.add_vpp_config()
3882 sep5 = VppGbpEndpoint(self, vx_tun_l3_sep,
3884 "12.0.0.10", "13.0.0.10",
3885 "4001:10::10", "5001:10::10",
3886 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
3888 self.pg7.remote_ip4,
3890 sep5.add_vpp_config()
3893 # local l3out redirect tests
3898 self.loop4.set_mac(self.router_mac)
3899 VppIpInterfaceBind(self, self.loop4, t4).add_vpp_config()
3900 VppIpInterfaceBind(self, self.loop4, t6).add_vpp_config()
3901 ebd = VppBridgeDomain(self, 100)
3902 ebd.add_vpp_config()
3903 gebd = VppGbpBridgeDomain(self, ebd, rd1, self.loop4, None, None)
3904 gebd.add_vpp_config()
3906 eepg = VppGbpEndpointGroup(self, 888, 765, rd1, gebd,
3910 VppGbpEndpointRetention(2))
3911 eepg.add_vpp_config()
3912 # add subnets to BVI
3913 VppIpInterfaceAddress(
3917 24).add_vpp_config()
3918 VppIpInterfaceAddress(
3922 64).add_vpp_config()
3923 # ... which are L3-out subnets
3924 VppGbpSubnet(self, rd1, "10.1.0.0", 24,
3925 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3926 sclass=765).add_vpp_config()
3927 VppGbpSubnet(self, rd1, "2001:10:1::128", 64,
3928 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3929 sclass=765).add_vpp_config()
3930 # external endpoints
3931 VppL2Vtr(self, self.vlan_100, L2_VTR_OP.L2_POP_1).add_vpp_config()
3932 eep1 = VppGbpEndpoint(self, self.vlan_100, eepg, None, "10.1.0.1",
3933 "11.1.0.1", "2001:10:1::1", "3001:10:1::1",
3934 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
3935 eep1.add_vpp_config()
3936 VppL2Vtr(self, self.vlan_101, L2_VTR_OP.L2_POP_1).add_vpp_config()
3937 eep2 = VppGbpEndpoint(self, self.vlan_101, eepg, None, "10.1.0.2",
3938 "11.1.0.2", "2001:10:1::2", "3001:10:1::2",
3939 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
3940 eep2.add_vpp_config()
3942 # external subnets reachable though eep1 and eep2 respectively
3943 VppIpRoute(self, "10.220.0.0", 24,
3944 [VppRoutePath(eep1.ip4.address, eep1.epg.bvi.sw_if_index)],
3945 table_id=t4.table_id).add_vpp_config()
3946 VppGbpSubnet(self, rd1, "10.220.0.0", 24,
3947 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3948 sclass=4220).add_vpp_config()
3949 VppIpRoute(self, "10:220::", 64,
3950 [VppRoutePath(eep1.ip6.address, eep1.epg.bvi.sw_if_index)],
3951 table_id=t6.table_id).add_vpp_config()
3952 VppGbpSubnet(self, rd1, "10:220::", 64,
3953 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3954 sclass=4220).add_vpp_config()
3955 VppIpRoute(self, "10.221.0.0", 24,
3956 [VppRoutePath(eep2.ip4.address, eep2.epg.bvi.sw_if_index)],
3957 table_id=t4.table_id).add_vpp_config()
3958 VppGbpSubnet(self, rd1, "10.221.0.0", 24,
3959 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3960 sclass=4221).add_vpp_config()
3961 VppIpRoute(self, "10:221::", 64,
3962 [VppRoutePath(eep2.ip6.address, eep2.epg.bvi.sw_if_index)],
3963 table_id=t6.table_id).add_vpp_config()
3964 VppGbpSubnet(self, rd1, "10:221::", 64,
3965 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3966 sclass=4221).add_vpp_config()
3969 # l3out redirect to remote (known, then unknown) SEP
3972 # packets from 1 external subnet to the other
3973 p = [(Ether(src=eep1.mac, dst=self.router_mac) /
3975 IP(src="10.220.0.17", dst="10.221.0.65") /
3976 UDP(sport=1234, dport=1234) /
3978 (Ether(src=eep1.mac, dst=self.router_mac) /
3980 IPv6(src="10:220::17", dst="10:221::65") /
3981 UDP(sport=1234, dport=1234) /
3984 # packets should be dropped in absence of contract
3985 self.send_and_assert_no_replies(self.pg0, p)
3987 # contract redirecting to sep5
3989 self, 402, 4220, 4221, acl_index,
3990 [VppGbpContractRule(
3991 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3992 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
3993 [VppGbpContractNextHop(sep5.vmac, sep5.epg.bd,
3994 sep5.ip4, sep5.epg.rd)]),
3996 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3997 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
3998 [VppGbpContractNextHop(sep5.vmac, sep5.epg.bd,
3999 sep5.ip6, sep5.epg.rd)])],
4000 [ETH_P_IP, ETH_P_IPV6]).add_vpp_config()
4002 rxs = self.send_and_expect(self.pg0, p, self.pg7)
4004 for rx, tx in zip(rxs, p):
4005 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4006 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4007 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4008 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4009 # this should use the programmed remote leaf TEP
4010 self.assertEqual(rx[VXLAN].vni, 555)
4011 self.assertEqual(rx[VXLAN].gpid, 4220)
4012 self.assertTrue(rx[VXLAN].flags.G)
4013 self.assertTrue(rx[VXLAN].flags.Instance)
4014 # redirect policy has been applied
4015 self.assertTrue(rx[VXLAN].gpflags.A)
4016 self.assertTrue(rx[VXLAN].gpflags.D)
4017 rxip = rx[VXLAN][Ether].payload
4018 txip = tx[Dot1Q].payload
4019 self.assertEqual(rxip.src, txip.src)
4020 self.assertEqual(rxip.dst, txip.dst)
4022 # remote SEP: it is now an unknown remote SEP and should go
4024 sep5.remove_vpp_config()
4026 rxs = self.send_and_expect(self.pg0, p, self.pg7)
4028 for rx, tx in zip(rxs, p):
4029 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4030 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4031 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4032 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4033 # this should use the spine proxy TEP
4034 self.assertEqual(rx[VXLAN].vni, epg_320.bd.uu_fwd.vni)
4035 self.assertEqual(rx[VXLAN].gpid, 4220)
4036 self.assertTrue(rx[VXLAN].flags.G)
4037 self.assertTrue(rx[VXLAN].flags.Instance)
4038 # redirect policy has been applied
4039 self.assertTrue(rx[VXLAN].gpflags.A)
4040 self.assertTrue(rx[VXLAN].gpflags.D)
4041 rxip = rx[VXLAN][Ether].payload
4042 txip = tx[Dot1Q].payload
4043 self.assertEqual(rxip.src, txip.src)
4044 self.assertEqual(rxip.dst, txip.dst)
4047 # l3out redirect to local SEP
4050 # change the contract between l3out to redirect to local SEPs
4051 # instead of remote SEP
4053 self, 402, 4220, 4221, acl_index,
4054 [VppGbpContractRule(
4055 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4056 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
4057 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
4058 sep1.ip4, sep1.epg.rd)]),
4060 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4061 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
4062 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
4063 sep1.ip6, sep1.epg.rd)])],
4064 [ETH_P_IP, ETH_P_IPV6]).add_vpp_config()
4066 rxs = self.send_and_expect(self.pg0, p, sep1.itf)
4067 for rx, tx in zip(rxs, p):
4068 self.assertEqual(rx[Ether].src, routed_src_mac)
4069 self.assertEqual(rx[Ether].dst, sep1.mac)
4070 rxip = rx[Ether].payload
4071 txip = tx[Ether].payload
4072 self.assertEqual(rxip.src, txip.src)
4073 self.assertEqual(rxip.dst, txip.dst)
4076 # redirect remote EP to remote (known then unknown) SEP
4079 # remote SEP known again
4080 sep5.add_vpp_config()
4082 # contract to redirect to learnt SEP
4084 self, 402, epg_221.sclass, epg_222.sclass, acl_index,
4085 [VppGbpContractRule(
4086 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4087 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
4088 [VppGbpContractNextHop(sep5.vmac, sep5.epg.bd,
4089 sep5.ip4, sep5.epg.rd)]),
4091 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4092 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
4093 [VppGbpContractNextHop(sep5.vmac, sep5.epg.bd,
4094 sep5.ip6, sep5.epg.rd)])],
4095 [ETH_P_IP, ETH_P_IPV6]).add_vpp_config()
4097 # packets from unknown EP 221 to known EP in EPG 222
4098 # should be redirected to known remote SEP
4099 base = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
4100 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
4101 UDP(sport=1234, dport=48879) /
4102 VXLAN(vni=444, gpid=441, flags=0x88) /
4103 Ether(src="00:22:22:22:22:44", dst=str(self.router_mac)))
4105 IP(src="10.0.1.100", dst=ep3.ip4.address) /
4106 UDP(sport=1234, dport=1234) /
4109 IPv6(src="2001:10::100", dst=ep3.ip6.address) /
4110 UDP(sport=1234, dport=1234) /
4113 # unknown remote EP to local EP redirected to known remote SEP
4114 rxs = self.send_and_expect(self.pg7, p, self.pg7)
4116 for rx, tx in zip(rxs, p):
4117 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4118 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4119 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4120 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4121 # this should use the programmed remote leaf TEP
4122 self.assertEqual(rx[VXLAN].vni, 555)
4123 self.assertEqual(rx[VXLAN].gpid, epg_221.sclass)
4124 self.assertTrue(rx[VXLAN].flags.G)
4125 self.assertTrue(rx[VXLAN].flags.Instance)
4126 # redirect policy has been applied
4127 self.assertTrue(rx[VXLAN].gpflags.A)
4128 self.assertFalse(rx[VXLAN].gpflags.D)
4129 rxip = rx[VXLAN][Ether].payload
4130 txip = tx[VXLAN][Ether].payload
4131 self.assertEqual(rxip.src, txip.src)
4132 self.assertEqual(rxip.dst, txip.dst)
4134 # endpoint learnt via the parent GBP-vxlan interface
4135 self.assertTrue(find_gbp_endpoint(self,
4136 vx_tun_l3._sw_if_index,
4138 self.assertTrue(find_gbp_endpoint(self,
4139 vx_tun_l3._sw_if_index,
4142 # remote SEP: it is now an unknown remote SEP and should go
4144 sep5.remove_vpp_config()
4146 # remote EP (coming from spine proxy) to local EP redirected to
4148 rxs = self.send_and_expect(self.pg7, p, self.pg7)
4150 for rx, tx in zip(rxs, p):
4151 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4152 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4153 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4154 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4155 # this should use the spine proxy TEP
4156 self.assertEqual(rx[VXLAN].vni, epg_320.bd.uu_fwd.vni)
4157 self.assertEqual(rx[VXLAN].gpid, epg_221.sclass)
4158 self.assertTrue(rx[VXLAN].flags.G)
4159 self.assertTrue(rx[VXLAN].flags.Instance)
4160 # redirect policy has been applied
4161 self.assertTrue(rx[VXLAN].gpflags.A)
4162 self.assertFalse(rx[VXLAN].gpflags.D)
4163 rxip = rx[VXLAN][Ether].payload
4164 txip = tx[VXLAN][Ether].payload
4165 self.assertEqual(rxip.src, txip.src)
4166 self.assertEqual(rxip.dst, txip.dst)
4171 self.pg7.unconfig_ip4()
4173 def test_gbp_l3_out(self):
4176 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
4177 self.vapi.cli("set logging class gbp level debug")
4179 routed_dst_mac = "00:0c:0c:0c:0c:0c"
4180 routed_src_mac = "00:22:bd:f8:19:ff"
4185 t4 = VppIpTable(self, 1)
4187 t6 = VppIpTable(self, 1, True)
4190 rd1 = VppGbpRouteDomain(self, 2, 55, t4, t6)
4191 rd1.add_vpp_config()
4193 self.loop0.set_mac(self.router_mac)
4196 # Bind the BVI to the RD
4198 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
4199 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
4202 # Pg7 hosts a BD's BUM
4203 # Pg1 some other l3 interface
4205 self.pg7.config_ip4()
4206 self.pg7.resolve_arp()
4209 # a multicast vxlan-gbp tunnel for broadcast in the BD
4211 tun_bm = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
4214 tun_bm.add_vpp_config()
4217 # a GBP external bridge domains for the EPs
4219 bd1 = VppBridgeDomain(self, 1)
4220 bd1.add_vpp_config()
4221 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0, None, tun_bm)
4222 gbd1.add_vpp_config()
4225 # The Endpoint-groups in which the external endpoints exist
4227 epg_220 = VppGbpEndpointGroup(self, 220, 113, rd1, gbd1,
4231 VppGbpEndpointRetention(2))
4232 epg_220.add_vpp_config()
4234 # the BVIs have the subnets applied ...
4235 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 24)
4236 ip4_addr.add_vpp_config()
4237 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 64)
4238 ip6_addr.add_vpp_config()
4240 # ... which are L3-out subnets
4241 l3o_1 = VppGbpSubnet(
4242 self, rd1, "10.0.0.0", 24,
4243 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
4245 l3o_1.add_vpp_config()
4248 # an external interface attached to the outside world and the
4251 VppL2Vtr(self, self.vlan_100, L2_VTR_OP.L2_POP_1).add_vpp_config()
4252 VppL2Vtr(self, self.vlan_101, L2_VTR_OP.L2_POP_1).add_vpp_config()
4253 vlan_144 = VppDot1QSubint(self, self.pg0, 144)
4255 # vlan_102 is not poped
4258 # an unicast vxlan-gbp for inter-RD traffic
4260 vx_tun_l3 = VppGbpVxlanTunnel(
4261 self, 444, rd1.rd_id,
4262 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
4264 vx_tun_l3.add_vpp_config()
4267 # External Endpoints
4269 eep1 = VppGbpEndpoint(self, self.vlan_100,
4271 "10.0.0.1", "11.0.0.1",
4272 "2001:10::1", "3001::1",
4273 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
4274 eep1.add_vpp_config()
4275 eep2 = VppGbpEndpoint(self, self.vlan_101,
4277 "10.0.0.2", "11.0.0.2",
4278 "2001:10::2", "3001::2",
4279 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
4280 eep2.add_vpp_config()
4281 eep3 = VppGbpEndpoint(self, self.vlan_102,
4283 "10.0.0.3", "11.0.0.3",
4284 "2001:10::3", "3001::3",
4285 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
4286 eep3.add_vpp_config()
4289 # A remote external endpoint
4291 rep = VppGbpEndpoint(self, vx_tun_l3,
4293 "10.0.0.101", "11.0.0.101",
4294 "2001:10::101", "3001::101",
4295 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
4297 self.pg7.remote_ip4,
4299 rep.add_vpp_config()
4302 # EP1 impersonating EP3 is dropped
4304 p = (Ether(src=eep1.mac, dst="ff:ff:ff:ff:ff:ff") /
4307 psrc="10.0.0.3", pdst="10.0.0.128",
4308 hwsrc=eep1.mac, hwdst="ff:ff:ff:ff:ff:ff"))
4309 self.send_and_assert_no_replies(self.pg0, p)
4312 # ARP packet from External EPs are accepted and replied to
4314 p_arp = (Ether(src=eep1.mac, dst="ff:ff:ff:ff:ff:ff") /
4317 psrc=eep1.ip4.address, pdst="10.0.0.128",
4318 hwsrc=eep1.mac, hwdst="ff:ff:ff:ff:ff:ff"))
4319 rxs = self.send_and_expect(self.pg0, p_arp * 1, self.pg0)
4322 # ARP packet from host in remote subnet are accepted and replied to
4324 p_arp = (Ether(src=eep3.mac, dst="ff:ff:ff:ff:ff:ff") /
4327 psrc=eep3.ip4.address, pdst="10.0.0.128",
4328 hwsrc=eep3.mac, hwdst="ff:ff:ff:ff:ff:ff"))
4329 rxs = self.send_and_expect(self.pg0, p_arp * 1, self.pg0)
4332 # packets destined to unknown addresses in the BVI's subnet
4335 p4 = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
4337 IP(src="10.0.0.1", dst="10.0.0.88") /
4338 UDP(sport=1234, dport=1234) /
4340 p6 = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
4342 IPv6(src="2001:10::1", dst="2001:10::88") /
4343 UDP(sport=1234, dport=1234) /
4346 rxs = self.send_and_expect(self.pg0, p4 * 1, self.pg7)
4349 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4350 # self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4351 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4352 self.assertEqual(rx[IP].dst, "239.1.1.1")
4353 self.assertEqual(rx[VXLAN].vni, 88)
4354 self.assertTrue(rx[VXLAN].flags.G)
4355 self.assertTrue(rx[VXLAN].flags.Instance)
4356 # policy was applied to the original IP packet
4357 self.assertEqual(rx[VXLAN].gpid, 113)
4358 self.assertTrue(rx[VXLAN].gpflags.A)
4359 self.assertFalse(rx[VXLAN].gpflags.D)
4361 inner = rx[VXLAN].payload
4363 self.assertTrue(inner.haslayer(ARP))
4366 # remote to external
4368 p = (Ether(src=self.pg7.remote_mac,
4369 dst=self.pg7.local_mac) /
4370 IP(src=self.pg7.remote_ip4,
4371 dst=self.pg7.local_ip4) /
4372 UDP(sport=1234, dport=48879) /
4373 VXLAN(vni=444, gpid=113, flags=0x88) /
4374 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
4375 IP(src="10.0.0.101", dst="10.0.0.1") /
4376 UDP(sport=1234, dport=1234) /
4379 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
4382 # local EP pings router
4384 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
4386 IP(src=eep1.ip4.address, dst="10.0.0.128") /
4387 ICMP(type='echo-request'))
4389 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
4392 self.assertEqual(rx[Ether].src, str(self.router_mac))
4393 self.assertEqual(rx[Ether].dst, eep1.mac)
4394 self.assertEqual(rx[Dot1Q].vlan, 100)
4397 # local EP pings other local EP
4399 p = (Ether(src=eep1.mac, dst=eep2.mac) /
4401 IP(src=eep1.ip4.address, dst=eep2.ip4.address) /
4402 ICMP(type='echo-request'))
4404 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
4407 self.assertEqual(rx[Ether].src, eep1.mac)
4408 self.assertEqual(rx[Ether].dst, eep2.mac)
4409 self.assertEqual(rx[Dot1Q].vlan, 101)
4412 # local EP pings router w/o vlan tag poped
4414 p = (Ether(src=eep3.mac, dst=str(self.router_mac)) /
4416 IP(src=eep3.ip4.address, dst="10.0.0.128") /
4417 ICMP(type='echo-request'))
4419 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
4422 self.assertEqual(rx[Ether].src, str(self.router_mac))
4423 self.assertEqual(rx[Ether].dst, self.vlan_102.remote_mac)
4426 # A ip4 subnet reachable through the external EP1
4428 ip_220 = VppIpRoute(self, "10.220.0.0", 24,
4429 [VppRoutePath(eep1.ip4.address,
4430 eep1.epg.bvi.sw_if_index)],
4431 table_id=t4.table_id)
4432 ip_220.add_vpp_config()
4434 l3o_220 = VppGbpSubnet(
4435 self, rd1, "10.220.0.0", 24,
4436 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
4438 l3o_220.add_vpp_config()
4441 # An ip6 subnet reachable through the external EP1
4443 ip6_220 = VppIpRoute(self, "10:220::", 64,
4444 [VppRoutePath(eep1.ip6.address,
4445 eep1.epg.bvi.sw_if_index)],
4446 table_id=t6.table_id)
4447 ip6_220.add_vpp_config()
4449 l3o6_220 = VppGbpSubnet(
4450 self, rd1, "10:220::", 64,
4451 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
4453 l3o6_220.add_vpp_config()
4456 # A subnet reachable through the external EP2
4458 ip_221 = VppIpRoute(self, "10.221.0.0", 24,
4459 [VppRoutePath(eep2.ip4.address,
4460 eep2.epg.bvi.sw_if_index)],
4461 table_id=t4.table_id)
4462 ip_221.add_vpp_config()
4464 l3o_221 = VppGbpSubnet(
4465 self, rd1, "10.221.0.0", 24,
4466 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
4468 l3o_221.add_vpp_config()
4471 # ping between hosts in remote subnets
4472 # dropped without a contract
4474 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
4476 IP(src="10.220.0.1", dst="10.221.0.1") /
4477 ICMP(type='echo-request'))
4479 self.send_and_assert_no_replies(self.pg0, p * 1)
4482 # contract for the external nets to communicate
4484 acl = VppGbpAcl(self)
4485 rule4 = acl.create_rule(permit_deny=1, proto=17)
4486 rule6 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
4487 acl_index = acl.add_vpp_config([rule4, rule6])
4490 # A contract with the wrong scope is not matched
4492 c_44 = VppGbpContract(
4493 self, 44, 4220, 4221, acl_index,
4494 [VppGbpContractRule(
4495 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4498 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4500 [ETH_P_IP, ETH_P_IPV6])
4501 c_44.add_vpp_config()
4502 self.send_and_assert_no_replies(self.pg0, p * 1)
4504 c1 = VppGbpContract(
4505 self, 55, 4220, 4221, acl_index,
4506 [VppGbpContractRule(
4507 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4508 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4511 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4512 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4514 [ETH_P_IP, ETH_P_IPV6])
4518 # Contracts allowing ext-net 200 to talk with external EPs
4520 c2 = VppGbpContract(
4521 self, 55, 4220, 113, acl_index,
4522 [VppGbpContractRule(
4523 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4524 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4527 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4528 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4530 [ETH_P_IP, ETH_P_IPV6])
4532 c3 = VppGbpContract(
4533 self, 55, 113, 4220, acl_index,
4534 [VppGbpContractRule(
4535 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4536 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4539 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4540 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4542 [ETH_P_IP, ETH_P_IPV6])
4546 # ping between hosts in remote subnets
4548 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
4550 IP(src="10.220.0.1", dst="10.221.0.1") /
4551 UDP(sport=1234, dport=1234) /
4554 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
4557 self.assertEqual(rx[Ether].src, str(self.router_mac))
4558 self.assertEqual(rx[Ether].dst, eep2.mac)
4559 self.assertEqual(rx[Dot1Q].vlan, 101)
4561 # we did not learn these external hosts
4562 self.assertFalse(find_gbp_endpoint(self, ip="10.220.0.1"))
4563 self.assertFalse(find_gbp_endpoint(self, ip="10.221.0.1"))
4566 # from remote external EP to local external EP
4568 p = (Ether(src=self.pg7.remote_mac,
4569 dst=self.pg7.local_mac) /
4570 IP(src=self.pg7.remote_ip4,
4571 dst=self.pg7.local_ip4) /
4572 UDP(sport=1234, dport=48879) /
4573 VXLAN(vni=444, gpid=113, flags=0x88) /
4574 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
4575 IP(src="10.0.0.101", dst="10.220.0.1") /
4576 UDP(sport=1234, dport=1234) /
4579 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
4582 # ping from an external host to the remote external EP
4584 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
4586 IP(src="10.220.0.1", dst=rep.ip4.address) /
4587 UDP(sport=1234, dport=1234) /
4590 rxs = self.send_and_expect(self.pg0, p * 1, self.pg7)
4593 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4594 # self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4595 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4596 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4597 self.assertEqual(rx[VXLAN].vni, 444)
4598 self.assertTrue(rx[VXLAN].flags.G)
4599 self.assertTrue(rx[VXLAN].flags.Instance)
4600 # the sclass of the ext-net the packet came from
4601 self.assertEqual(rx[VXLAN].gpid, 4220)
4602 # policy was applied to the original IP packet
4603 self.assertTrue(rx[VXLAN].gpflags.A)
4604 # since it's an external host the reciever should not learn it
4605 self.assertTrue(rx[VXLAN].gpflags.D)
4606 inner = rx[VXLAN].payload
4607 self.assertEqual(inner[IP].src, "10.220.0.1")
4608 self.assertEqual(inner[IP].dst, rep.ip4.address)
4611 # An external subnet reachable via the remote external EP
4615 # first the VXLAN-GBP tunnel over which it is reached
4617 vx_tun_r1 = VppVxlanGbpTunnel(
4618 self, self.pg7.local_ip4,
4619 self.pg7.remote_ip4, 445,
4620 mode=(VppEnum.vl_api_vxlan_gbp_api_tunnel_mode_t.
4621 VXLAN_GBP_API_TUNNEL_MODE_L3))
4622 vx_tun_r1.add_vpp_config()
4623 VppIpInterfaceBind(self, vx_tun_r1, t4).add_vpp_config()
4625 self.logger.info(self.vapi.cli("sh vxlan-gbp tunnel"))
4628 # then the special adj to resolve through on that tunnel
4630 n1 = VppNeighbor(self,
4631 vx_tun_r1.sw_if_index,
4632 "00:0c:0c:0c:0c:0c",
4633 self.pg7.remote_ip4)
4637 # the route via the adj above
4639 ip_222 = VppIpRoute(self, "10.222.0.0", 24,
4640 [VppRoutePath(self.pg7.remote_ip4,
4641 vx_tun_r1.sw_if_index)],
4642 table_id=t4.table_id)
4643 ip_222.add_vpp_config()
4645 l3o_222 = VppGbpSubnet(
4646 self, rd1, "10.222.0.0", 24,
4647 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
4649 l3o_222.add_vpp_config()
4652 # ping between hosts in local and remote external subnets
4653 # dropped without a contract
4655 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
4657 IP(src="10.220.0.1", dst="10.222.0.1") /
4658 UDP(sport=1234, dport=1234) /
4661 rxs = self.send_and_assert_no_replies(self.pg0, p * 1)
4664 # Add contracts ext-nets for 220 -> 222
4666 c4 = VppGbpContract(
4667 self, 55, 4220, 4222, acl_index,
4668 [VppGbpContractRule(
4669 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4670 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4673 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4674 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4676 [ETH_P_IP, ETH_P_IPV6])
4680 # ping from host in local to remote external subnets
4682 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
4684 IP(src="10.220.0.1", dst="10.222.0.1") /
4685 UDP(sport=1234, dport=1234) /
4688 rxs = self.send_and_expect(self.pg0, p * 3, self.pg7)
4691 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4692 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4693 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4694 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4695 self.assertEqual(rx[VXLAN].vni, 445)
4696 self.assertTrue(rx[VXLAN].flags.G)
4697 self.assertTrue(rx[VXLAN].flags.Instance)
4698 # the sclass of the ext-net the packet came from
4699 self.assertEqual(rx[VXLAN].gpid, 4220)
4700 # policy was applied to the original IP packet
4701 self.assertTrue(rx[VXLAN].gpflags.A)
4702 # since it's an external host the reciever should not learn it
4703 self.assertTrue(rx[VXLAN].gpflags.D)
4704 inner = rx[VXLAN].payload
4705 self.assertEqual(inner[Ether].dst, "00:0c:0c:0c:0c:0c")
4706 self.assertEqual(inner[IP].src, "10.220.0.1")
4707 self.assertEqual(inner[IP].dst, "10.222.0.1")
4710 # make the external subnet ECMP
4712 vx_tun_r2 = VppVxlanGbpTunnel(
4713 self, self.pg7.local_ip4,
4714 self.pg7.remote_ip4, 446,
4715 mode=(VppEnum.vl_api_vxlan_gbp_api_tunnel_mode_t.
4716 VXLAN_GBP_API_TUNNEL_MODE_L3))
4717 vx_tun_r2.add_vpp_config()
4718 VppIpInterfaceBind(self, vx_tun_r2, t4).add_vpp_config()
4720 self.logger.info(self.vapi.cli("sh vxlan-gbp tunnel"))
4722 n2 = VppNeighbor(self,
4723 vx_tun_r2.sw_if_index,
4724 "00:0c:0c:0c:0c:0c",
4725 self.pg7.remote_ip4)
4728 ip_222.modify([VppRoutePath(self.pg7.remote_ip4,
4729 vx_tun_r1.sw_if_index),
4730 VppRoutePath(self.pg7.remote_ip4,
4731 vx_tun_r2.sw_if_index)])
4734 # now expect load-balance
4736 p = [(Ether(src=eep1.mac, dst=str(self.router_mac)) /
4738 IP(src="10.220.0.1", dst="10.222.0.1") /
4739 UDP(sport=1234, dport=1234) /
4741 (Ether(src=eep1.mac, dst=str(self.router_mac)) /
4743 IP(src="10.220.0.1", dst="10.222.0.1") /
4744 UDP(sport=1222, dport=1235) /
4747 rxs = self.send_and_expect(self.pg0, p, self.pg7)
4749 self.assertEqual(rxs[0][VXLAN].vni, 445)
4750 self.assertEqual(rxs[1][VXLAN].vni, 446)
4753 # Same LB test for v6
4755 n3 = VppNeighbor(self,
4756 vx_tun_r1.sw_if_index,
4757 "00:0c:0c:0c:0c:0c",
4758 self.pg7.remote_ip6)
4760 n4 = VppNeighbor(self,
4761 vx_tun_r2.sw_if_index,
4762 "00:0c:0c:0c:0c:0c",
4763 self.pg7.remote_ip6)
4766 ip_222_6 = VppIpRoute(self, "10:222::", 64,
4767 [VppRoutePath(self.pg7.remote_ip6,
4768 vx_tun_r1.sw_if_index),
4769 VppRoutePath(self.pg7.remote_ip6,
4770 vx_tun_r2.sw_if_index)],
4771 table_id=t6.table_id)
4772 ip_222_6.add_vpp_config()
4774 l3o_222_6 = VppGbpSubnet(
4775 self, rd1, "10:222::", 64,
4776 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
4778 l3o_222_6.add_vpp_config()
4780 p = [(Ether(src=eep1.mac, dst=str(self.router_mac)) /
4782 IPv6(src="10:220::1", dst="10:222::1") /
4783 UDP(sport=1234, dport=1234) /
4785 (Ether(src=eep1.mac, dst=str(self.router_mac)) /
4787 IPv6(src="10:220::1", dst="10:222::1") /
4788 UDP(sport=7777, dport=8881) /
4791 self.logger.info(self.vapi.cli("sh ip6 fib 10:222::1"))
4792 rxs = self.send_and_expect(self.pg0, p, self.pg7)
4794 self.assertEqual(rxs[0][VXLAN].vni, 445)
4795 self.assertEqual(rxs[1][VXLAN].vni, 446)
4798 # ping from host in remote to local external subnets
4799 # there's no contract for this, but the A bit is set.
4801 p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
4802 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
4803 UDP(sport=1234, dport=48879) /
4804 VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
4805 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
4806 IP(src="10.222.0.1", dst="10.220.0.1") /
4807 UDP(sport=1234, dport=1234) /
4810 rxs = self.send_and_expect(self.pg7, p * 3, self.pg0)
4811 self.assertFalse(find_gbp_endpoint(self, ip="10.222.0.1"))
4814 # ping from host in remote to remote external subnets
4815 # this is dropped by reflection check.
4817 p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
4818 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
4819 UDP(sport=1234, dport=48879) /
4820 VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
4821 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
4822 IP(src="10.222.0.1", dst="10.222.0.2") /
4823 UDP(sport=1234, dport=1234) /
4826 rxs = self.send_and_assert_no_replies(self.pg7, p * 3)
4828 p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
4829 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
4830 UDP(sport=1234, dport=48879) /
4831 VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
4832 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
4833 IPv6(src="10:222::1", dst="10:222::2") /
4834 UDP(sport=1234, dport=1234) /
4837 rxs = self.send_and_assert_no_replies(self.pg7, p * 3)
4842 lep1 = VppGbpEndpoint(self, vlan_144,
4844 "10.0.0.44", "11.0.0.44",
4845 "2001:10::44", "3001::44")
4846 lep1.add_vpp_config()
4849 # local EP to local ip4 external subnet
4851 p = (Ether(src=lep1.mac, dst=str(self.router_mac)) /
4853 IP(src=lep1.ip4.address, dst="10.220.0.1") /
4854 UDP(sport=1234, dport=1234) /
4857 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
4860 self.assertEqual(rx[Ether].src, str(self.router_mac))
4861 self.assertEqual(rx[Ether].dst, eep1.mac)
4862 self.assertEqual(rx[Dot1Q].vlan, 100)
4865 # local EP to local ip6 external subnet
4867 p = (Ether(src=lep1.mac, dst=str(self.router_mac)) /
4869 IPv6(src=lep1.ip6.address, dst="10:220::1") /
4870 UDP(sport=1234, dport=1234) /
4873 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
4876 self.assertEqual(rx[Ether].src, str(self.router_mac))
4877 self.assertEqual(rx[Ether].dst, eep1.mac)
4878 self.assertEqual(rx[Dot1Q].vlan, 100)
4881 # ip4 and ip6 subnets that load-balance
4883 ip_20 = VppIpRoute(self, "10.20.0.0", 24,
4884 [VppRoutePath(eep1.ip4.address,
4885 eep1.epg.bvi.sw_if_index),
4886 VppRoutePath(eep2.ip4.address,
4887 eep2.epg.bvi.sw_if_index)],
4888 table_id=t4.table_id)
4889 ip_20.add_vpp_config()
4891 l3o_20 = VppGbpSubnet(
4892 self, rd1, "10.20.0.0", 24,
4893 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
4895 l3o_20.add_vpp_config()
4897 ip6_20 = VppIpRoute(self, "10:20::", 64,
4898 [VppRoutePath(eep1.ip6.address,
4899 eep1.epg.bvi.sw_if_index),
4900 VppRoutePath(eep2.ip6.address,
4901 eep2.epg.bvi.sw_if_index)],
4902 table_id=t6.table_id)
4903 ip6_20.add_vpp_config()
4905 l3o6_20 = VppGbpSubnet(
4906 self, rd1, "10:20::", 64,
4907 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
4909 l3o6_20.add_vpp_config()
4911 self.logger.info(self.vapi.cli("sh ip fib 10.20.0.1"))
4912 self.logger.info(self.vapi.cli("sh ip6 fib 10:20::1"))
4914 # two ip6 packets whose port are chosen so they load-balance
4915 p = [(Ether(src=lep1.mac, dst=str(self.router_mac)) /
4917 IPv6(src=lep1.ip6.address, dst="10:20::1") /
4918 UDP(sport=1234, dport=1234) /
4920 (Ether(src=lep1.mac, dst=str(self.router_mac)) /
4922 IPv6(src=lep1.ip6.address, dst="10:20::1") /
4923 UDP(sport=124, dport=1230) /
4926 rxs = self.send_and_expect(self.pg0, p, self.pg0, 2)
4928 self.assertEqual(rxs[0][Dot1Q].vlan, 101)
4929 self.assertEqual(rxs[1][Dot1Q].vlan, 100)
4931 # two ip4 packets whose port are chosen so they load-balance
4932 p = [(Ether(src=lep1.mac, dst=str(self.router_mac)) /
4934 IP(src=lep1.ip4.address, dst="10.20.0.1") /
4935 UDP(sport=1235, dport=1235) /
4937 (Ether(src=lep1.mac, dst=str(self.router_mac)) /
4939 IP(src=lep1.ip4.address, dst="10.20.0.1") /
4940 UDP(sport=124, dport=1230) /
4943 rxs = self.send_and_expect(self.pg0, p, self.pg0, 2)
4945 self.assertEqual(rxs[0][Dot1Q].vlan, 101)
4946 self.assertEqual(rxs[1][Dot1Q].vlan, 100)
4951 ip_222.remove_vpp_config()
4952 self.pg7.unconfig_ip4()
4953 self.vlan_101.set_vtr(L2_VTR_OP.L2_DISABLED)
4954 self.vlan_100.set_vtr(L2_VTR_OP.L2_DISABLED)
4956 def test_gbp_anon_l3_out(self):
4957 """ GBP Anonymous L3 Out """
4959 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
4960 self.vapi.cli("set logging class gbp level debug")
4962 routed_dst_mac = "00:0c:0c:0c:0c:0c"
4963 routed_src_mac = "00:22:bd:f8:19:ff"
4968 t4 = VppIpTable(self, 1)
4970 t6 = VppIpTable(self, 1, True)
4973 rd1 = VppGbpRouteDomain(self, 2, 55, t4, t6)
4974 rd1.add_vpp_config()
4976 self.loop0.set_mac(self.router_mac)
4979 # Bind the BVI to the RD
4981 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
4982 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
4985 # Pg7 hosts a BD's BUM
4986 # Pg1 some other l3 interface
4988 self.pg7.config_ip4()
4989 self.pg7.resolve_arp()
4992 # a GBP external bridge domains for the EPs
4994 bd1 = VppBridgeDomain(self, 1)
4995 bd1.add_vpp_config()
4996 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0, None, None)
4997 gbd1.add_vpp_config()
5000 # The Endpoint-groups in which the external endpoints exist
5002 epg_220 = VppGbpEndpointGroup(self, 220, 113, rd1, gbd1,
5006 VppGbpEndpointRetention(2))
5007 epg_220.add_vpp_config()
5009 # the BVIs have the subnet applied ...
5010 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 24)
5011 ip4_addr.add_vpp_config()
5013 # ... which is an Anonymous L3-out subnets
5014 l3o_1 = VppGbpSubnet(
5015 self, rd1, "10.0.0.0", 24,
5016 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_ANON_L3_OUT,
5018 l3o_1.add_vpp_config()
5021 # an external interface attached to the outside world and the
5024 VppL2Vtr(self, self.vlan_100, L2_VTR_OP.L2_POP_1).add_vpp_config()
5025 VppL2Vtr(self, self.vlan_101, L2_VTR_OP.L2_POP_1).add_vpp_config()
5028 # vlan_100 and vlan_101 are anonymous l3-out interfaces
5030 ext_itf = VppGbpExtItf(self, self.vlan_100, bd1, rd1, anon=True)
5031 ext_itf.add_vpp_config()
5032 ext_itf = VppGbpExtItf(self, self.vlan_101, bd1, rd1, anon=True)
5033 ext_itf.add_vpp_config()
5036 # an unicast vxlan-gbp for inter-RD traffic
5038 vx_tun_l3 = VppGbpVxlanTunnel(
5039 self, 444, rd1.rd_id,
5040 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
5042 vx_tun_l3.add_vpp_config()
5045 # A remote external endpoint
5047 rep = VppGbpEndpoint(self, vx_tun_l3,
5049 "10.0.0.201", "11.0.0.201",
5050 "2001:10::201", "3001::101",
5051 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
5053 self.pg7.remote_ip4,
5055 rep.add_vpp_config()
5058 # ARP packet from host in external subnet are accepted, flooded and
5059 # replied to. We expect 2 packets:
5060 # - APR request flooded over the other vlan subif
5061 # - ARP reply from BVI
5063 p_arp = (Ether(src=self.vlan_100.remote_mac,
5064 dst="ff:ff:ff:ff:ff:ff") /
5069 hwsrc=self.vlan_100.remote_mac,
5070 hwdst="ff:ff:ff:ff:ff:ff"))
5071 rxs = self.send_and_expect(self.pg0, p_arp * 1, self.pg0, n_rx=2)
5073 p_arp = (Ether(src=self.vlan_101.remote_mac,
5074 dst="ff:ff:ff:ff:ff:ff") /
5079 hwsrc=self.vlan_101.remote_mac,
5080 hwdst="ff:ff:ff:ff:ff:ff"))
5081 rxs = self.send_and_expect(self.pg0, p_arp * 1, self.pg0, n_rx=2)
5084 # remote to external
5086 p = (Ether(src=self.pg7.remote_mac,
5087 dst=self.pg7.local_mac) /
5088 IP(src=self.pg7.remote_ip4,
5089 dst=self.pg7.local_ip4) /
5090 UDP(sport=1234, dport=48879) /
5091 VXLAN(vni=vx_tun_l3.vni, gpid=epg_220.sclass, flags=0x88) /
5092 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
5093 IP(src=str(rep.ip4), dst="10.0.0.100") /
5094 UDP(sport=1234, dport=1234) /
5096 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
5099 # local EP pings router
5101 p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
5103 IP(src="10.0.0.100", dst="10.0.0.128") /
5104 ICMP(type='echo-request'))
5105 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
5108 self.assertEqual(rx[Ether].src, str(self.router_mac))
5109 self.assertEqual(rx[Ether].dst, self.vlan_100.remote_mac)
5110 self.assertEqual(rx[Dot1Q].vlan, 100)
5113 # local EP pings other local EP
5115 p = (Ether(src=self.vlan_100.remote_mac,
5116 dst=self.vlan_101.remote_mac) /
5118 IP(src="10.0.0.100", dst="10.0.0.101") /
5119 ICMP(type='echo-request'))
5120 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
5123 self.assertEqual(rx[Ether].src, self.vlan_100.remote_mac)
5124 self.assertEqual(rx[Ether].dst, self.vlan_101.remote_mac)
5125 self.assertEqual(rx[Dot1Q].vlan, 101)
5128 # A subnet reachable through an external router on vlan 100
5130 ip_220 = VppIpRoute(self, "10.220.0.0", 24,
5131 [VppRoutePath("10.0.0.100",
5132 epg_220.bvi.sw_if_index)],
5133 table_id=t4.table_id)
5134 ip_220.add_vpp_config()
5136 l3o_220 = VppGbpSubnet(
5137 self, rd1, "10.220.0.0", 24,
5138 # note: this a "regular" L3 out subnet (not connected)
5139 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
5141 l3o_220.add_vpp_config()
5144 # A subnet reachable through an external router on vlan 101
5146 ip_221 = VppIpRoute(self, "10.221.0.0", 24,
5147 [VppRoutePath("10.0.0.101",
5148 epg_220.bvi.sw_if_index)],
5149 table_id=t4.table_id)
5150 ip_221.add_vpp_config()
5152 l3o_221 = VppGbpSubnet(
5153 self, rd1, "10.221.0.0", 24,
5154 # note: this a "regular" L3 out subnet (not connected)
5155 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
5157 l3o_221.add_vpp_config()
5160 # ping between hosts in remote subnets
5161 # dropped without a contract
5163 p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
5165 IP(src="10.220.0.1", dst="10.221.0.1") /
5166 ICMP(type='echo-request'))
5168 rxs = self.send_and_assert_no_replies(self.pg0, p * 1)
5171 # contract for the external nets to communicate
5173 acl = VppGbpAcl(self)
5174 rule4 = acl.create_rule(permit_deny=1, proto=17)
5175 rule6 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
5176 acl_index = acl.add_vpp_config([rule4, rule6])
5178 c1 = VppGbpContract(
5179 self, 55, 4220, 4221, acl_index,
5180 [VppGbpContractRule(
5181 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5182 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5185 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5186 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5188 [ETH_P_IP, ETH_P_IPV6])
5192 # Contracts allowing ext-net 200 to talk with external EPs
5194 c2 = VppGbpContract(
5195 self, 55, 4220, 113, acl_index,
5196 [VppGbpContractRule(
5197 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5198 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5201 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5202 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5204 [ETH_P_IP, ETH_P_IPV6])
5206 c3 = VppGbpContract(
5207 self, 55, 113, 4220, acl_index,
5208 [VppGbpContractRule(
5209 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5210 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5213 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5214 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5216 [ETH_P_IP, ETH_P_IPV6])
5220 # ping between hosts in remote subnets
5222 p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
5224 IP(src="10.220.0.1", dst="10.221.0.1") /
5225 UDP(sport=1234, dport=1234) /
5228 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
5231 self.assertEqual(rx[Ether].src, str(self.router_mac))
5232 self.assertEqual(rx[Ether].dst, self.vlan_101.remote_mac)
5233 self.assertEqual(rx[Dot1Q].vlan, 101)
5235 # we did not learn these external hosts
5236 self.assertFalse(find_gbp_endpoint(self, ip="10.220.0.1"))
5237 self.assertFalse(find_gbp_endpoint(self, ip="10.221.0.1"))
5240 # from remote external EP to local external EP
5242 p = (Ether(src=self.pg7.remote_mac,
5243 dst=self.pg7.local_mac) /
5244 IP(src=self.pg7.remote_ip4,
5245 dst=self.pg7.local_ip4) /
5246 UDP(sport=1234, dport=48879) /
5247 VXLAN(vni=444, gpid=113, flags=0x88) /
5248 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
5249 IP(src=rep.ip4.address, dst="10.220.0.1") /
5250 UDP(sport=1234, dport=1234) /
5253 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
5256 # ping from an external host to the remote external EP
5258 p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
5260 IP(src="10.220.0.1", dst=rep.ip4.address) /
5261 UDP(sport=1234, dport=1234) /
5264 rxs = self.send_and_expect(self.pg0, p * 1, self.pg7)
5267 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
5268 # self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
5269 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
5270 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
5271 self.assertEqual(rx[VXLAN].vni, 444)
5272 self.assertTrue(rx[VXLAN].flags.G)
5273 self.assertTrue(rx[VXLAN].flags.Instance)
5274 # the sclass of the ext-net the packet came from
5275 self.assertEqual(rx[VXLAN].gpid, 4220)
5276 # policy was applied to the original IP packet
5277 self.assertTrue(rx[VXLAN].gpflags.A)
5278 # since it's an external host the reciever should not learn it
5279 self.assertTrue(rx[VXLAN].gpflags.D)
5280 inner = rx[VXLAN].payload
5281 self.assertEqual(inner[IP].src, "10.220.0.1")
5282 self.assertEqual(inner[IP].dst, rep.ip4.address)
5285 # An external subnet reachable via the remote external EP
5289 # first the VXLAN-GBP tunnel over which it is reached
5291 vx_tun_r = VppVxlanGbpTunnel(
5292 self, self.pg7.local_ip4,
5293 self.pg7.remote_ip4, 445,
5294 mode=(VppEnum.vl_api_vxlan_gbp_api_tunnel_mode_t.
5295 VXLAN_GBP_API_TUNNEL_MODE_L3))
5296 vx_tun_r.add_vpp_config()
5297 VppIpInterfaceBind(self, vx_tun_r, t4).add_vpp_config()
5299 self.logger.info(self.vapi.cli("sh vxlan-gbp tunnel"))
5302 # then the special adj to resolve through on that tunnel
5304 n1 = VppNeighbor(self,
5305 vx_tun_r.sw_if_index,
5306 "00:0c:0c:0c:0c:0c",
5307 self.pg7.remote_ip4)
5311 # the route via the adj above
5313 ip_222 = VppIpRoute(self, "10.222.0.0", 24,
5314 [VppRoutePath(self.pg7.remote_ip4,
5315 vx_tun_r.sw_if_index)],
5316 table_id=t4.table_id)
5317 ip_222.add_vpp_config()
5319 l3o_222 = VppGbpSubnet(
5320 self, rd1, "10.222.0.0", 24,
5321 # note: this a "regular" l3out subnet (not connected)
5322 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
5324 l3o_222.add_vpp_config()
5327 # ping between hosts in local and remote external subnets
5328 # dropped without a contract
5330 p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
5332 IP(src="10.220.0.1", dst="10.222.0.1") /
5333 UDP(sport=1234, dport=1234) /
5336 rxs = self.send_and_assert_no_replies(self.pg0, p * 1)
5339 # Add contracts ext-nets for 220 -> 222
5341 c4 = VppGbpContract(
5342 self, 55, 4220, 4222, acl_index,
5343 [VppGbpContractRule(
5344 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5345 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5348 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5349 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5351 [ETH_P_IP, ETH_P_IPV6])
5355 # ping from host in local to remote external subnets
5357 p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
5359 IP(src="10.220.0.1", dst="10.222.0.1") /
5360 UDP(sport=1234, dport=1234) /
5363 rxs = self.send_and_expect(self.pg0, p * 3, self.pg7)
5366 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
5367 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
5368 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
5369 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
5370 self.assertEqual(rx[VXLAN].vni, 445)
5371 self.assertTrue(rx[VXLAN].flags.G)
5372 self.assertTrue(rx[VXLAN].flags.Instance)
5373 # the sclass of the ext-net the packet came from
5374 self.assertEqual(rx[VXLAN].gpid, 4220)
5375 # policy was applied to the original IP packet
5376 self.assertTrue(rx[VXLAN].gpflags.A)
5377 # since it's an external host the reciever should not learn it
5378 self.assertTrue(rx[VXLAN].gpflags.D)
5379 inner = rx[VXLAN].payload
5380 self.assertEqual(inner[Ether].dst, "00:0c:0c:0c:0c:0c")
5381 self.assertEqual(inner[IP].src, "10.220.0.1")
5382 self.assertEqual(inner[IP].dst, "10.222.0.1")
5385 # ping from host in remote to local external subnets
5386 # there's no contract for this, but the A bit is set.
5388 p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
5389 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
5390 UDP(sport=1234, dport=48879) /
5391 VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
5392 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
5393 IP(src="10.222.0.1", dst="10.220.0.1") /
5394 UDP(sport=1234, dport=1234) /
5397 rxs = self.send_and_expect(self.pg7, p * 3, self.pg0)
5398 self.assertFalse(find_gbp_endpoint(self, ip="10.222.0.1"))
5401 # ping from host in remote to remote external subnets
5402 # this is dropped by reflection check.
5404 p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
5405 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
5406 UDP(sport=1234, dport=48879) /
5407 VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
5408 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
5409 IP(src="10.222.0.1", dst="10.222.0.2") /
5410 UDP(sport=1234, dport=1234) /
5413 rxs = self.send_and_assert_no_replies(self.pg7, p * 3)
5418 self.vlan_101.set_vtr(L2_VTR_OP.L2_DISABLED)
5419 self.vlan_100.set_vtr(L2_VTR_OP.L2_DISABLED)
5420 self.pg7.unconfig_ip4()
5423 if __name__ == '__main__':
5424 unittest.main(testRunner=VppTestRunner)