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 self.vlan_102.remove_vpp_config()
656 self.vlan_101.remove_vpp_config()
657 self.vlan_100.remove_vpp_config()
659 def send_and_expect_bridged(self, src, tx, dst):
660 rx = self.send_and_expect(src, tx, dst)
663 self.assertEqual(r[Ether].src, tx[0][Ether].src)
664 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
665 self.assertEqual(r[IP].src, tx[0][IP].src)
666 self.assertEqual(r[IP].dst, tx[0][IP].dst)
669 def send_and_expect_bridged6(self, src, tx, dst):
670 rx = self.send_and_expect(src, tx, dst)
673 self.assertEqual(r[Ether].src, tx[0][Ether].src)
674 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
675 self.assertEqual(r[IPv6].src, tx[0][IPv6].src)
676 self.assertEqual(r[IPv6].dst, tx[0][IPv6].dst)
679 def send_and_expect_routed(self, src, tx, dst, src_mac):
680 rx = self.send_and_expect(src, tx, dst)
683 self.assertEqual(r[Ether].src, src_mac)
684 self.assertEqual(r[Ether].dst, dst.remote_mac)
685 self.assertEqual(r[IP].src, tx[0][IP].src)
686 self.assertEqual(r[IP].dst, tx[0][IP].dst)
689 def send_and_expect_routed6(self, src, tx, dst, src_mac):
690 rx = self.send_and_expect(src, tx, dst)
693 self.assertEqual(r[Ether].src, src_mac)
694 self.assertEqual(r[Ether].dst, dst.remote_mac)
695 self.assertEqual(r[IPv6].src, tx[0][IPv6].src)
696 self.assertEqual(r[IPv6].dst, tx[0][IPv6].dst)
699 def send_and_expect_natted(self, src, tx, dst, src_ip):
700 rx = self.send_and_expect(src, tx, dst)
703 self.assertEqual(r[Ether].src, tx[0][Ether].src)
704 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
705 self.assertEqual(r[IP].src, src_ip)
706 self.assertEqual(r[IP].dst, tx[0][IP].dst)
709 def send_and_expect_natted6(self, src, tx, dst, src_ip):
710 rx = self.send_and_expect(src, tx, dst)
713 self.assertEqual(r[Ether].src, tx[0][Ether].src)
714 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
715 self.assertEqual(r[IPv6].src, src_ip)
716 self.assertEqual(r[IPv6].dst, tx[0][IPv6].dst)
719 def send_and_expect_unnatted(self, src, tx, dst, dst_ip):
720 rx = self.send_and_expect(src, tx, dst)
723 self.assertEqual(r[Ether].src, tx[0][Ether].src)
724 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
725 self.assertEqual(r[IP].dst, dst_ip)
726 self.assertEqual(r[IP].src, tx[0][IP].src)
729 def send_and_expect_unnatted6(self, src, tx, dst, dst_ip):
730 rx = self.send_and_expect(src, tx, dst)
733 self.assertEqual(r[Ether].src, tx[0][Ether].src)
734 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
735 self.assertEqual(r[IPv6].dst, dst_ip)
736 self.assertEqual(r[IPv6].src, tx[0][IPv6].src)
739 def send_and_expect_double_natted(self, src, tx, dst, src_ip, dst_ip):
740 rx = self.send_and_expect(src, tx, dst)
743 self.assertEqual(r[Ether].src, str(self.router_mac))
744 self.assertEqual(r[Ether].dst, dst.remote_mac)
745 self.assertEqual(r[IP].dst, dst_ip)
746 self.assertEqual(r[IP].src, src_ip)
749 def send_and_expect_double_natted6(self, src, tx, dst, src_ip, dst_ip):
750 rx = self.send_and_expect(src, tx, dst)
753 self.assertEqual(r[Ether].src, str(self.router_mac))
754 self.assertEqual(r[Ether].dst, dst.remote_mac)
755 self.assertEqual(r[IPv6].dst, dst_ip)
756 self.assertEqual(r[IPv6].src, src_ip)
759 def send_and_expect_no_arp(self, src, tx, dst):
760 self.pg_send(src, tx)
761 dst.get_capture(0, timeout=1)
762 dst.assert_nothing_captured(remark="")
765 def send_and_expect_arp(self, src, tx, dst):
766 rx = self.send_and_expect(src, tx, dst)
769 self.assertEqual(r[Ether].src, tx[0][Ether].src)
770 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
771 self.assertEqual(r[ARP].psrc, tx[0][ARP].psrc)
772 self.assertEqual(r[ARP].pdst, tx[0][ARP].pdst)
773 self.assertEqual(r[ARP].hwsrc, tx[0][ARP].hwsrc)
774 self.assertEqual(r[ARP].hwdst, tx[0][ARP].hwdst)
778 """ Group Based Policy """
780 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
785 gt4 = VppIpTable(self, 0)
787 gt6 = VppIpTable(self, 0, is_ip6=True)
789 nt4 = VppIpTable(self, 20)
791 nt6 = VppIpTable(self, 20, is_ip6=True)
794 rd0 = VppGbpRouteDomain(self, 0, 400, gt4, gt6, None, None)
795 rd20 = VppGbpRouteDomain(self, 20, 420, nt4, nt6, None, None)
798 rd20.add_vpp_config()
803 bd1 = VppBridgeDomain(self, 1)
804 bd2 = VppBridgeDomain(self, 2)
805 bd20 = VppBridgeDomain(self, 20)
809 bd20.add_vpp_config()
811 gbd1 = VppGbpBridgeDomain(self, bd1, rd0, self.loop0)
812 gbd2 = VppGbpBridgeDomain(self, bd2, rd0, self.loop1)
813 gbd20 = VppGbpBridgeDomain(self, bd20, rd20, self.loop2)
815 gbd1.add_vpp_config()
816 gbd2.add_vpp_config()
817 gbd20.add_vpp_config()
820 # 3 EPGs, 2 of which share a BD.
821 # 2 NAT EPGs, one for floating-IP subnets, the other for internet
823 epgs = [VppGbpEndpointGroup(self, 220, 1220, rd0, gbd1,
824 self.pg4, self.loop0,
825 "10.0.0.128", "2001:10::128"),
826 VppGbpEndpointGroup(self, 221, 1221, rd0, gbd1,
827 self.pg5, self.loop0,
828 "10.0.1.128", "2001:10:1::128"),
829 VppGbpEndpointGroup(self, 222, 1222, rd0, gbd2,
830 self.pg6, self.loop1,
831 "10.0.2.128", "2001:10:2::128"),
832 VppGbpEndpointGroup(self, 333, 1333, rd20, gbd20,
833 self.pg7, self.loop2,
834 "11.0.0.128", "3001::128"),
835 VppGbpEndpointGroup(self, 444, 1444, rd20, gbd20,
836 self.pg8, self.loop2,
837 "11.0.0.129", "3001::129")]
838 recircs = [VppGbpRecirc(self, epgs[0], self.loop3),
839 VppGbpRecirc(self, epgs[1], self.loop4),
840 VppGbpRecirc(self, epgs[2], self.loop5),
841 VppGbpRecirc(self, epgs[3], self.loop6, is_ext=True),
842 VppGbpRecirc(self, epgs[4], self.loop7, is_ext=True)]
845 recirc_nat = recircs[3]
848 # 4 end-points, 2 in the same subnet, 3 in the same BD
850 eps = [VppGbpEndpoint(self, self.pg0,
852 "10.0.0.1", "11.0.0.1",
853 "2001:10::1", "3001::1"),
854 VppGbpEndpoint(self, self.pg1,
856 "10.0.0.2", "11.0.0.2",
857 "2001:10::2", "3001::2"),
858 VppGbpEndpoint(self, self.pg2,
860 "10.0.1.1", "11.0.0.3",
861 "2001:10:1::1", "3001::3"),
862 VppGbpEndpoint(self, self.pg3,
864 "10.0.2.1", "11.0.0.4",
865 "2001:10:2::1", "3001::4")]
868 # Config related to each of the EPGs
871 # IP config on the BVI interfaces
872 if epg != epgs[1] and epg != epgs[4]:
873 VppIpInterfaceBind(self, epg.bvi, epg.rd.t4).add_vpp_config()
874 VppIpInterfaceBind(self, epg.bvi, epg.rd.t6).add_vpp_config()
875 epg.bvi.set_mac(self.router_mac)
877 # The BVIs are NAT inside interfaces
878 flags = self.config_flags.NAT_IS_INSIDE
879 self.vapi.nat44_interface_add_del_feature(
880 sw_if_index=epg.bvi.sw_if_index,
881 flags=flags, is_add=1)
882 self.vapi.nat66_add_del_interface(
883 is_add=1, flags=flags,
884 sw_if_index=epg.bvi.sw_if_index)
886 if_ip4 = VppIpInterfaceAddress(self, epg.bvi, epg.bvi_ip4, 32)
887 if_ip6 = VppIpInterfaceAddress(self, epg.bvi, epg.bvi_ip6, 128)
888 if_ip4.add_vpp_config()
889 if_ip6.add_vpp_config()
891 # EPG uplink interfaces in the RD
892 VppIpInterfaceBind(self, epg.uplink, epg.rd.t4).add_vpp_config()
893 VppIpInterfaceBind(self, epg.uplink, epg.rd.t6).add_vpp_config()
895 # add the BD ARP termination entry for BVI IP
896 epg.bd_arp_ip4 = VppBridgeDomainArpEntry(self, epg.bd.bd,
897 str(self.router_mac),
899 epg.bd_arp_ip6 = VppBridgeDomainArpEntry(self, epg.bd.bd,
900 str(self.router_mac),
902 epg.bd_arp_ip4.add_vpp_config()
903 epg.bd_arp_ip6.add_vpp_config()
908 for recirc in recircs:
909 # EPG's ingress recirculation interface maps to its RD
910 VppIpInterfaceBind(self, recirc.recirc,
911 recirc.epg.rd.t4).add_vpp_config()
912 VppIpInterfaceBind(self, recirc.recirc,
913 recirc.epg.rd.t6).add_vpp_config()
915 self.vapi.nat44_interface_add_del_feature(
916 sw_if_index=recirc.recirc.sw_if_index, is_add=1)
917 self.vapi.nat66_add_del_interface(
919 sw_if_index=recirc.recirc.sw_if_index)
921 recirc.add_vpp_config()
923 for recirc in recircs:
924 self.assertTrue(find_bridge_domain_port(self,
925 recirc.epg.bd.bd.bd_id,
926 recirc.recirc.sw_if_index))
929 self.pg_enable_capture(self.pg_interfaces)
932 # routes to the endpoints. We need these since there are no
933 # adj-fibs due to the fact the the BVI address has /32 and
934 # the subnet is not attached.
936 for (ip, fip) in zip(ep.ips, ep.fips):
937 # Add static mappings for each EP from the 10/8 to 11/8 network
939 flags = self.config_flags.NAT_IS_ADDR_ONLY
940 self.vapi.nat44_add_del_static_mapping(
942 local_ip_address=ip.bytes,
943 external_ip_address=fip.bytes,
944 external_sw_if_index=0xFFFFFFFF,
948 self.vapi.nat66_add_del_static_mapping(
949 local_ip_address=ip.bytes,
950 external_ip_address=fip.bytes,
956 self.logger.info(self.vapi.cli("sh gbp endpoint"))
958 # ... results in a Gratuitous ARP/ND on the EPG's uplink
959 rx = ep.epg.uplink.get_capture(len(ep.ips), timeout=0.2)
961 for ii, ip in enumerate(ep.ips):
965 self.assertTrue(p.haslayer(ICMPv6ND_NA))
966 self.assertEqual(p[ICMPv6ND_NA].tgt, ip.address)
968 self.assertTrue(p.haslayer(ARP))
969 self.assertEqual(p[ARP].psrc, ip.address)
970 self.assertEqual(p[ARP].pdst, ip.address)
972 # add the BD ARP termination entry for floating IP
974 ba = VppBridgeDomainArpEntry(self, epg_nat.bd.bd, ep.mac,
978 # floating IPs route via EPG recirc
980 self, fip.address, fip.length,
981 [VppRoutePath(fip.address,
982 ep.recirc.recirc.sw_if_index,
983 type=FibPathType.FIB_PATH_TYPE_DVR,
984 proto=fip.dpo_proto)],
988 # L2 FIB entries in the NAT EPG BD to bridge the packets from
989 # the outside direct to the internal EPG
990 lf = VppL2FibEntry(self, epg_nat.bd.bd, ep.mac,
991 ep.recirc.recirc, bvi_mac=0)
995 # ARP packets for unknown IP are sent to the EPG uplink
997 pkt_arp = (Ether(dst="ff:ff:ff:ff:ff:ff",
998 src=self.pg0.remote_mac) /
1000 hwdst="ff:ff:ff:ff:ff:ff",
1001 hwsrc=self.pg0.remote_mac,
1005 self.vapi.cli("clear trace")
1006 self.pg0.add_stream(pkt_arp)
1008 self.pg_enable_capture(self.pg_interfaces)
1011 rxd = epgs[0].uplink.get_capture(1)
1014 # ARP/ND packets get a response
1016 pkt_arp = (Ether(dst="ff:ff:ff:ff:ff:ff",
1017 src=self.pg0.remote_mac) /
1019 hwdst="ff:ff:ff:ff:ff:ff",
1020 hwsrc=self.pg0.remote_mac,
1021 pdst=epgs[0].bvi_ip4.address,
1022 psrc=eps[0].ip4.address))
1024 self.send_and_expect(self.pg0, [pkt_arp], self.pg0)
1026 nsma = in6_getnsma(inet_pton(AF_INET6, eps[0].ip6.address))
1027 d = inet_ntop(AF_INET6, nsma)
1028 pkt_nd = (Ether(dst=in6_getnsmac(nsma),
1029 src=self.pg0.remote_mac) /
1030 IPv6(dst=d, src=eps[0].ip6.address) /
1031 ICMPv6ND_NS(tgt=epgs[0].bvi_ip6.address) /
1032 ICMPv6NDOptSrcLLAddr(lladdr=self.pg0.remote_mac))
1033 self.send_and_expect(self.pg0, [pkt_nd], self.pg0)
1036 # broadcast packets are flooded
1038 pkt_bcast = (Ether(dst="ff:ff:ff:ff:ff:ff",
1039 src=self.pg0.remote_mac) /
1040 IP(src=eps[0].ip4.address, dst="232.1.1.1") /
1041 UDP(sport=1234, dport=1234) /
1044 self.vapi.cli("clear trace")
1045 self.pg0.add_stream(pkt_bcast)
1047 self.pg_enable_capture(self.pg_interfaces)
1050 rxd = eps[1].itf.get_capture(1)
1051 self.assertEqual(rxd[0][Ether].dst, pkt_bcast[Ether].dst)
1052 rxd = epgs[0].uplink.get_capture(1)
1053 self.assertEqual(rxd[0][Ether].dst, pkt_bcast[Ether].dst)
1056 # packets to non-local L3 destinations dropped
1058 pkt_intra_epg_220_ip4 = (Ether(src=self.pg0.remote_mac,
1059 dst=str(self.router_mac)) /
1060 IP(src=eps[0].ip4.address,
1062 UDP(sport=1234, dport=1234) /
1064 pkt_inter_epg_222_ip4 = (Ether(src=self.pg0.remote_mac,
1065 dst=str(self.router_mac)) /
1066 IP(src=eps[0].ip4.address,
1068 UDP(sport=1234, dport=1234) /
1071 self.send_and_assert_no_replies(self.pg0,
1072 pkt_intra_epg_220_ip4 * NUM_PKTS)
1074 pkt_inter_epg_222_ip6 = (Ether(src=self.pg0.remote_mac,
1075 dst=str(self.router_mac)) /
1076 IPv6(src=eps[0].ip6.address,
1077 dst="2001:10::99") /
1078 UDP(sport=1234, dport=1234) /
1080 self.send_and_assert_no_replies(self.pg0,
1081 pkt_inter_epg_222_ip6 * NUM_PKTS)
1084 # Add the subnet routes
1087 self, rd0, "10.0.0.0", 24,
1088 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1090 self, rd0, "10.0.1.0", 24,
1091 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1093 self, rd0, "10.0.2.0", 24,
1094 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1096 self, rd0, "2001:10::1", 64,
1097 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1099 self, rd0, "2001:10:1::1", 64,
1100 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1102 self, rd0, "2001:10:2::1", 64,
1103 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1104 s41.add_vpp_config()
1105 s42.add_vpp_config()
1106 s43.add_vpp_config()
1107 s61.add_vpp_config()
1108 s62.add_vpp_config()
1109 s63.add_vpp_config()
1111 self.send_and_expect_bridged(eps[0].itf,
1112 pkt_intra_epg_220_ip4 * NUM_PKTS,
1114 self.send_and_expect_bridged(eps[0].itf,
1115 pkt_inter_epg_222_ip4 * NUM_PKTS,
1117 self.send_and_expect_bridged6(eps[0].itf,
1118 pkt_inter_epg_222_ip6 * NUM_PKTS,
1121 self.logger.info(self.vapi.cli("sh ip fib 11.0.0.2"))
1122 self.logger.info(self.vapi.cli("sh gbp endpoint-group"))
1123 self.logger.info(self.vapi.cli("sh gbp endpoint"))
1124 self.logger.info(self.vapi.cli("sh gbp recirc"))
1125 self.logger.info(self.vapi.cli("sh int"))
1126 self.logger.info(self.vapi.cli("sh int addr"))
1127 self.logger.info(self.vapi.cli("sh int feat loop6"))
1128 self.logger.info(self.vapi.cli("sh vlib graph ip4-gbp-src-classify"))
1129 self.logger.info(self.vapi.cli("sh int feat loop3"))
1130 self.logger.info(self.vapi.cli("sh int feat pg0"))
1133 # Packet destined to unknown unicast is sent on the epg uplink ...
1135 pkt_intra_epg_220_to_uplink = (Ether(src=self.pg0.remote_mac,
1136 dst="00:00:00:33:44:55") /
1137 IP(src=eps[0].ip4.address,
1139 UDP(sport=1234, dport=1234) /
1142 self.send_and_expect_bridged(eps[0].itf,
1143 pkt_intra_epg_220_to_uplink * NUM_PKTS,
1145 # ... and nowhere else
1146 self.pg1.get_capture(0, timeout=0.1)
1147 self.pg1.assert_nothing_captured(remark="Flood onto other VMS")
1149 pkt_intra_epg_221_to_uplink = (Ether(src=self.pg2.remote_mac,
1150 dst="00:00:00:33:44:66") /
1151 IP(src=eps[0].ip4.address,
1153 UDP(sport=1234, dport=1234) /
1156 self.send_and_expect_bridged(eps[2].itf,
1157 pkt_intra_epg_221_to_uplink * NUM_PKTS,
1161 # Packets from the uplink are forwarded in the absence of a contract
1163 pkt_intra_epg_220_from_uplink = (Ether(src="00:00:00:33:44:55",
1164 dst=self.pg0.remote_mac) /
1165 IP(src=eps[0].ip4.address,
1167 UDP(sport=1234, dport=1234) /
1170 self.send_and_expect_bridged(self.pg4,
1171 pkt_intra_epg_220_from_uplink * NUM_PKTS,
1175 # in the absence of policy, endpoints in the same EPG
1178 pkt_intra_epg = (Ether(src=self.pg0.remote_mac,
1179 dst=self.pg1.remote_mac) /
1180 IP(src=eps[0].ip4.address,
1181 dst=eps[1].ip4.address) /
1182 UDP(sport=1234, dport=1234) /
1185 self.send_and_expect_bridged(self.pg0,
1186 pkt_intra_epg * NUM_PKTS,
1190 # in the absence of policy, endpoints in the different EPG
1191 # cannot communicate
1193 pkt_inter_epg_220_to_221 = (Ether(src=self.pg0.remote_mac,
1194 dst=self.pg2.remote_mac) /
1195 IP(src=eps[0].ip4.address,
1196 dst=eps[2].ip4.address) /
1197 UDP(sport=1234, dport=1234) /
1199 pkt_inter_epg_221_to_220 = (Ether(src=self.pg2.remote_mac,
1200 dst=self.pg0.remote_mac) /
1201 IP(src=eps[2].ip4.address,
1202 dst=eps[0].ip4.address) /
1203 UDP(sport=1234, dport=1234) /
1205 pkt_inter_epg_220_to_222 = (Ether(src=self.pg0.remote_mac,
1206 dst=str(self.router_mac)) /
1207 IP(src=eps[0].ip4.address,
1208 dst=eps[3].ip4.address) /
1209 UDP(sport=1234, dport=1234) /
1212 self.send_and_assert_no_replies(eps[0].itf,
1213 pkt_inter_epg_220_to_221 * NUM_PKTS)
1214 self.send_and_assert_no_replies(eps[0].itf,
1215 pkt_inter_epg_220_to_222 * NUM_PKTS)
1218 # A uni-directional contract from EPG 220 -> 221
1220 acl = VppGbpAcl(self)
1221 rule = acl.create_rule(permit_deny=1, proto=17)
1222 rule2 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
1223 acl_index = acl.add_vpp_config([rule, rule2])
1224 c1 = VppGbpContract(
1225 self, 400, epgs[0].sclass, epgs[1].sclass, acl_index,
1226 [VppGbpContractRule(
1227 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1228 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1231 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1232 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1234 [ETH_P_IP, ETH_P_IPV6])
1237 self.send_and_expect_bridged(eps[0].itf,
1238 pkt_inter_epg_220_to_221 * NUM_PKTS,
1240 self.send_and_assert_no_replies(eps[0].itf,
1241 pkt_inter_epg_220_to_222 * NUM_PKTS)
1244 # contract for the return direction
1246 c2 = VppGbpContract(
1247 self, 400, epgs[1].sclass, epgs[0].sclass, acl_index,
1248 [VppGbpContractRule(
1249 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1250 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1253 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1254 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1256 [ETH_P_IP, ETH_P_IPV6])
1259 self.send_and_expect_bridged(eps[0].itf,
1260 pkt_inter_epg_220_to_221 * NUM_PKTS,
1262 self.send_and_expect_bridged(eps[2].itf,
1263 pkt_inter_epg_221_to_220 * NUM_PKTS,
1266 ds = c2.get_drop_stats()
1267 self.assertEqual(ds['packets'], 0)
1268 ps = c2.get_permit_stats()
1269 self.assertEqual(ps['packets'], NUM_PKTS)
1272 # the contract does not allow non-IP
1274 pkt_non_ip_inter_epg_220_to_221 = (Ether(src=self.pg0.remote_mac,
1275 dst=self.pg2.remote_mac) /
1277 self.send_and_assert_no_replies(eps[0].itf,
1278 pkt_non_ip_inter_epg_220_to_221 * 17)
1281 # check that inter group is still disabled for the groups
1282 # not in the contract.
1284 self.send_and_assert_no_replies(eps[0].itf,
1285 pkt_inter_epg_220_to_222 * NUM_PKTS)
1288 # A uni-directional contract from EPG 220 -> 222 'L3 routed'
1290 c3 = VppGbpContract(
1291 self, 400, epgs[0].sclass, epgs[2].sclass, acl_index,
1292 [VppGbpContractRule(
1293 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1294 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1297 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1298 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1300 [ETH_P_IP, ETH_P_IPV6])
1303 self.logger.info(self.vapi.cli("sh gbp contract"))
1305 self.send_and_expect_routed(eps[0].itf,
1306 pkt_inter_epg_220_to_222 * NUM_PKTS,
1308 str(self.router_mac))
1311 # remove both contracts, traffic stops in both directions
1313 c2.remove_vpp_config()
1314 c1.remove_vpp_config()
1315 c3.remove_vpp_config()
1316 acl.remove_vpp_config()
1318 self.send_and_assert_no_replies(eps[2].itf,
1319 pkt_inter_epg_221_to_220 * NUM_PKTS)
1320 self.send_and_assert_no_replies(eps[0].itf,
1321 pkt_inter_epg_220_to_221 * NUM_PKTS)
1322 self.send_and_expect_bridged(eps[0].itf,
1323 pkt_intra_epg * NUM_PKTS,
1327 # EPs to the outside world
1330 # in the EP's RD an external subnet via the NAT EPG's recirc
1332 self, rd0, "0.0.0.0", 0,
1333 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1334 sw_if_index=recirc_nat.recirc.sw_if_index,
1335 sclass=epg_nat.sclass)
1337 self, rd0, "11.0.0.0", 8,
1338 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1339 sw_if_index=recirc_nat.recirc.sw_if_index,
1340 sclass=epg_nat.sclass)
1341 se16 = VppGbpSubnet(
1343 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1344 sw_if_index=recirc_nat.recirc.sw_if_index,
1345 sclass=epg_nat.sclass)
1346 # in the NAT RD an external subnet via the NAT EPG's uplink
1348 self, rd20, "0.0.0.0", 0,
1349 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1350 sw_if_index=epg_nat.uplink.sw_if_index,
1351 sclass=epg_nat.sclass)
1352 se36 = VppGbpSubnet(
1353 self, rd20, "::", 0,
1354 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1355 sw_if_index=epg_nat.uplink.sw_if_index,
1356 sclass=epg_nat.sclass)
1358 self, rd20, "11.0.0.0", 8,
1359 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1360 sw_if_index=epg_nat.uplink.sw_if_index,
1361 sclass=epg_nat.sclass)
1362 se1.add_vpp_config()
1363 se2.add_vpp_config()
1364 se16.add_vpp_config()
1365 se3.add_vpp_config()
1366 se36.add_vpp_config()
1367 se4.add_vpp_config()
1369 self.logger.info(self.vapi.cli("sh ip fib 0.0.0.0/0"))
1370 self.logger.info(self.vapi.cli("sh ip fib 11.0.0.1"))
1371 self.logger.info(self.vapi.cli("sh ip6 fib ::/0"))
1372 self.logger.info(self.vapi.cli("sh ip6 fib %s" %
1376 # From an EP to an outside address: IN2OUT
1378 pkt_inter_epg_220_to_global = (Ether(src=self.pg0.remote_mac,
1379 dst=str(self.router_mac)) /
1380 IP(src=eps[0].ip4.address,
1382 UDP(sport=1234, dport=1234) /
1386 self.send_and_assert_no_replies(eps[0].itf,
1387 pkt_inter_epg_220_to_global * NUM_PKTS)
1389 acl2 = VppGbpAcl(self)
1390 rule = acl2.create_rule(permit_deny=1, proto=17, sport_from=1234,
1391 sport_to=1234, dport_from=1234, dport_to=1234)
1392 rule2 = acl2.create_rule(is_ipv6=1, permit_deny=1, proto=17,
1393 sport_from=1234, sport_to=1234,
1394 dport_from=1234, dport_to=1234)
1396 acl_index2 = acl2.add_vpp_config([rule, rule2])
1397 c4 = VppGbpContract(
1398 self, 400, epgs[0].sclass, epgs[3].sclass, acl_index2,
1399 [VppGbpContractRule(
1400 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1401 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1404 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1405 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1407 [ETH_P_IP, ETH_P_IPV6])
1410 self.send_and_expect_natted(eps[0].itf,
1411 pkt_inter_epg_220_to_global * NUM_PKTS,
1413 eps[0].fip4.address)
1415 pkt_inter_epg_220_to_global = (Ether(src=self.pg0.remote_mac,
1416 dst=str(self.router_mac)) /
1417 IPv6(src=eps[0].ip6.address,
1419 UDP(sport=1234, dport=1234) /
1422 self.send_and_expect_natted6(self.pg0,
1423 pkt_inter_epg_220_to_global * NUM_PKTS,
1425 eps[0].fip6.address)
1428 # From a global address to an EP: OUT2IN
1430 pkt_inter_epg_220_from_global = (Ether(src=str(self.router_mac),
1431 dst=self.pg0.remote_mac) /
1432 IP(dst=eps[0].fip4.address,
1434 UDP(sport=1234, dport=1234) /
1437 self.send_and_assert_no_replies(
1438 self.pg7, pkt_inter_epg_220_from_global * NUM_PKTS)
1440 c5 = VppGbpContract(
1441 self, 400, epgs[3].sclass, epgs[0].sclass, acl_index2,
1442 [VppGbpContractRule(
1443 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1444 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1447 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1448 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1450 [ETH_P_IP, ETH_P_IPV6])
1453 self.send_and_expect_unnatted(self.pg7,
1454 pkt_inter_epg_220_from_global * NUM_PKTS,
1458 pkt_inter_epg_220_from_global = (Ether(src=str(self.router_mac),
1459 dst=self.pg0.remote_mac) /
1460 IPv6(dst=eps[0].fip6.address,
1462 UDP(sport=1234, dport=1234) /
1465 self.send_and_expect_unnatted6(
1467 pkt_inter_epg_220_from_global * NUM_PKTS,
1472 # From a local VM to another local VM using resp. public addresses:
1475 pkt_intra_epg_220_global = (Ether(src=self.pg0.remote_mac,
1476 dst=str(self.router_mac)) /
1477 IP(src=eps[0].ip4.address,
1478 dst=eps[1].fip4.address) /
1479 UDP(sport=1234, dport=1234) /
1482 self.send_and_expect_double_natted(eps[0].itf,
1483 pkt_intra_epg_220_global * NUM_PKTS,
1485 eps[0].fip4.address,
1488 pkt_intra_epg_220_global = (Ether(src=self.pg0.remote_mac,
1489 dst=str(self.router_mac)) /
1490 IPv6(src=eps[0].ip6.address,
1491 dst=eps[1].fip6.address) /
1492 UDP(sport=1234, dport=1234) /
1495 self.send_and_expect_double_natted6(
1497 pkt_intra_epg_220_global * NUM_PKTS,
1499 eps[0].fip6.address,
1506 # del static mappings for each EP from the 10/8 to 11/8 network
1507 flags = self.config_flags.NAT_IS_ADDR_ONLY
1508 self.vapi.nat44_add_del_static_mapping(
1510 local_ip_address=ep.ip4.bytes,
1511 external_ip_address=ep.fip4.bytes,
1512 external_sw_if_index=0xFFFFFFFF,
1515 self.vapi.nat66_add_del_static_mapping(
1516 local_ip_address=ep.ip6.bytes,
1517 external_ip_address=ep.fip6.bytes,
1521 # IP config on the BVI interfaces
1522 if epg != epgs[0] and epg != epgs[3]:
1523 flags = self.config_flags.NAT_IS_INSIDE
1524 self.vapi.nat44_interface_add_del_feature(
1525 sw_if_index=epg.bvi.sw_if_index,
1528 self.vapi.nat66_add_del_interface(
1529 is_add=0, flags=flags,
1530 sw_if_index=epg.bvi.sw_if_index)
1532 for recirc in recircs:
1533 self.vapi.nat44_interface_add_del_feature(
1534 sw_if_index=recirc.recirc.sw_if_index,
1536 self.vapi.nat66_add_del_interface(
1538 sw_if_index=recirc.recirc.sw_if_index)
1540 def wait_for_ep_timeout(self, sw_if_index=None, ip=None, mac=None,
1541 tep=None, n_tries=100, s_time=1):
1543 if not find_gbp_endpoint(self, sw_if_index, ip, mac, tep=tep):
1545 n_tries = n_tries - 1
1547 self.assertFalse(find_gbp_endpoint(self, sw_if_index, ip, mac))
1550 def test_gbp_learn_l2(self):
1551 """ GBP L2 Endpoint Learning """
1553 drop_no_contract = self.statistics.get_err_counter(
1554 '/err/gbp-policy-port/drop-no-contract')
1555 allow_intra_class = self.statistics.get_err_counter(
1556 '/err/gbp-policy-port/allow-intra-sclass')
1558 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
1559 learnt = [{'mac': '00:00:11:11:11:01',
1561 'ip6': '2001:10::2'},
1562 {'mac': '00:00:11:11:11:02',
1564 'ip6': '2001:10::3'}]
1569 gt4 = VppIpTable(self, 1)
1570 gt4.add_vpp_config()
1571 gt6 = VppIpTable(self, 1, is_ip6=True)
1572 gt6.add_vpp_config()
1574 rd1 = VppGbpRouteDomain(self, 1, 401, gt4, gt6)
1575 rd1.add_vpp_config()
1578 # Pg2 hosts the vxlan tunnel, hosts on pg2 to act as TEPs
1579 # Pg3 hosts the IP4 UU-flood VXLAN tunnel
1580 # Pg4 hosts the IP6 UU-flood VXLAN tunnel
1582 self.pg2.config_ip4()
1583 self.pg2.resolve_arp()
1584 self.pg2.generate_remote_hosts(4)
1585 self.pg2.configure_ipv4_neighbors()
1586 self.pg3.config_ip4()
1587 self.pg3.resolve_arp()
1588 self.pg4.config_ip4()
1589 self.pg4.resolve_arp()
1592 # Add a mcast destination VXLAN-GBP tunnel for B&M traffic
1594 tun_bm = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
1597 tun_bm.add_vpp_config()
1600 # a GBP bridge domain with a BVI and a UU-flood interface
1602 bd1 = VppBridgeDomain(self, 1)
1603 bd1.add_vpp_config()
1604 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0,
1606 gbd1.add_vpp_config()
1608 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1609 self.logger.info(self.vapi.cli("sh gbp bridge"))
1611 # ... and has a /32 applied
1612 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
1613 ip_addr.add_vpp_config()
1616 # The Endpoint-group in which we are learning endpoints
1618 epg_220 = VppGbpEndpointGroup(self, 220, 112, rd1, gbd1,
1622 VppGbpEndpointRetention(2))
1623 epg_220.add_vpp_config()
1624 epg_330 = VppGbpEndpointGroup(self, 330, 113, rd1, gbd1,
1628 VppGbpEndpointRetention(2))
1629 epg_330.add_vpp_config()
1632 # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
1635 vx_tun_l2_1 = VppGbpVxlanTunnel(
1636 self, 99, bd1.bd_id,
1637 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L2,
1639 vx_tun_l2_1.add_vpp_config()
1642 # A static endpoint that the learnt endpoints are trying to
1645 ep = VppGbpEndpoint(self, self.pg0,
1647 "10.0.0.127", "11.0.0.127",
1648 "2001:10::1", "3001::1")
1651 self.assertTrue(find_route(self, ep.ip4.address, 32, table_id=1))
1653 # a packet with an sclass from an unknown EPG
1654 p = (Ether(src=self.pg2.remote_mac,
1655 dst=self.pg2.local_mac) /
1656 IP(src=self.pg2.remote_hosts[0].ip4,
1657 dst=self.pg2.local_ip4) /
1658 UDP(sport=1234, dport=48879) /
1659 VXLAN(vni=99, gpid=88, flags=0x88) /
1660 Ether(src=learnt[0]["mac"], dst=ep.mac) /
1661 IP(src=learnt[0]["ip"], dst=ep.ip4.address) /
1662 UDP(sport=1234, dport=1234) /
1665 self.send_and_assert_no_replies(self.pg2, p)
1667 self.logger.info(self.vapi.cli("sh error"))
1668 self.assert_error_counter_equal(
1669 '/err/gbp-policy-port/drop-no-contract',
1670 drop_no_contract + 1)
1673 # we should not have learnt a new tunnel endpoint, since
1674 # the EPG was not learnt.
1676 self.assertEqual(INDEX_INVALID,
1677 find_vxlan_gbp_tunnel(self,
1679 self.pg2.remote_hosts[0].ip4,
1682 # ep is not learnt, because the EPG is unknown
1683 self.assertEqual(len(self.vapi.gbp_endpoint_dump()), 1)
1686 # Learn new EPs from IP packets
1688 for ii, l in enumerate(learnt):
1689 # a packet with an sclass from a known EPG
1690 # arriving on an unknown TEP
1691 p = (Ether(src=self.pg2.remote_mac,
1692 dst=self.pg2.local_mac) /
1693 IP(src=self.pg2.remote_hosts[1].ip4,
1694 dst=self.pg2.local_ip4) /
1695 UDP(sport=1234, dport=48879) /
1696 VXLAN(vni=99, gpid=112, flags=0x88) /
1697 Ether(src=l['mac'], dst=ep.mac) /
1698 IP(src=l['ip'], dst=ep.ip4.address) /
1699 UDP(sport=1234, dport=1234) /
1702 rx = self.send_and_expect(self.pg2, [p], self.pg0)
1705 tep1_sw_if_index = find_vxlan_gbp_tunnel(
1708 self.pg2.remote_hosts[1].ip4,
1710 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
1713 # the EP is learnt via the learnt TEP
1714 # both from its MAC and its IP
1716 self.assertTrue(find_gbp_endpoint(self,
1717 vx_tun_l2_1.sw_if_index,
1719 self.assertTrue(find_gbp_endpoint(self,
1720 vx_tun_l2_1.sw_if_index,
1723 self.assert_error_counter_equal(
1724 '/err/gbp-policy-port/allow-intra-sclass',
1725 allow_intra_class + 2)
1727 self.logger.info(self.vapi.cli("show gbp endpoint"))
1728 self.logger.info(self.vapi.cli("show gbp vxlan"))
1729 self.logger.info(self.vapi.cli("show ip mfib"))
1732 # If we sleep for the threshold time, the learnt endpoints should
1736 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1740 # Learn new EPs from GARP packets received on the BD's mcast tunnel
1742 for ii, l in enumerate(learnt):
1743 # add some junk in the reserved field of the vxlan-header
1744 # next to the VNI. we should accept since reserved bits are
1746 p = (Ether(src=self.pg2.remote_mac,
1747 dst=self.pg2.local_mac) /
1748 IP(src=self.pg2.remote_hosts[1].ip4,
1750 UDP(sport=1234, dport=48879) /
1751 VXLAN(vni=88, reserved2=0x80, gpid=112, flags=0x88) /
1752 Ether(src=l['mac'], dst="ff:ff:ff:ff:ff:ff") /
1754 psrc=l['ip'], pdst=l['ip'],
1755 hwsrc=l['mac'], hwdst="ff:ff:ff:ff:ff:ff"))
1757 rx = self.send_and_expect(self.pg4, [p], self.pg0)
1760 tep1_sw_if_index = find_vxlan_gbp_tunnel(
1763 self.pg2.remote_hosts[1].ip4,
1765 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
1768 # the EP is learnt via the learnt TEP
1769 # both from its MAC and its IP
1771 self.assertTrue(find_gbp_endpoint(self,
1772 vx_tun_l2_1.sw_if_index,
1774 self.assertTrue(find_gbp_endpoint(self,
1775 vx_tun_l2_1.sw_if_index,
1779 # wait for the learnt endpoints to age out
1782 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1786 # Learn new EPs from L2 packets
1788 for ii, l in enumerate(learnt):
1789 # a packet with an sclass from a known EPG
1790 # arriving on an unknown TEP
1791 p = (Ether(src=self.pg2.remote_mac,
1792 dst=self.pg2.local_mac) /
1793 IP(src=self.pg2.remote_hosts[1].ip4,
1794 dst=self.pg2.local_ip4) /
1795 UDP(sport=1234, dport=48879) /
1796 VXLAN(vni=99, gpid=112, flags=0x88) /
1797 Ether(src=l['mac'], dst=ep.mac) /
1800 rx = self.send_and_expect(self.pg2, [p], self.pg0)
1803 tep1_sw_if_index = find_vxlan_gbp_tunnel(
1806 self.pg2.remote_hosts[1].ip4,
1808 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
1811 # the EP is learnt via the learnt TEP
1812 # both from its MAC and its IP
1814 self.assertTrue(find_gbp_endpoint(self,
1815 vx_tun_l2_1.sw_if_index,
1818 self.logger.info(self.vapi.cli("show gbp endpoint"))
1819 self.logger.info(self.vapi.cli("show gbp vxlan"))
1820 self.logger.info(self.vapi.cli("show vxlan-gbp tunnel"))
1823 # wait for the learnt endpoints to age out
1826 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1830 # repeat. the do not learn bit is set so the EPs are not learnt
1833 # a packet with an sclass from a known EPG
1834 p = (Ether(src=self.pg2.remote_mac,
1835 dst=self.pg2.local_mac) /
1836 IP(src=self.pg2.remote_hosts[1].ip4,
1837 dst=self.pg2.local_ip4) /
1838 UDP(sport=1234, dport=48879) /
1839 VXLAN(vni=99, gpid=112, flags=0x88, gpflags="D") /
1840 Ether(src=l['mac'], dst=ep.mac) /
1841 IP(src=l['ip'], dst=ep.ip4.address) /
1842 UDP(sport=1234, dport=1234) /
1845 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
1848 self.assertFalse(find_gbp_endpoint(self,
1849 vx_tun_l2_1.sw_if_index,
1856 # a packet with an sclass from a known EPG
1857 # set a reserved bit in addition to the G and I
1858 # reserved bits should not be checked on rx.
1859 p = (Ether(src=self.pg2.remote_mac,
1860 dst=self.pg2.local_mac) /
1861 IP(src=self.pg2.remote_hosts[1].ip4,
1862 dst=self.pg2.local_ip4) /
1863 UDP(sport=1234, dport=48879) /
1864 VXLAN(vni=99, gpid=112, flags=0xc8) /
1865 Ether(src=l['mac'], dst=ep.mac) /
1866 IP(src=l['ip'], dst=ep.ip4.address) /
1867 UDP(sport=1234, dport=1234) /
1870 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
1872 self.assertTrue(find_gbp_endpoint(self,
1873 vx_tun_l2_1.sw_if_index,
1877 # Static EP replies to dynamics
1879 self.logger.info(self.vapi.cli("sh l2fib bd_id 1"))
1881 p = (Ether(src=ep.mac, dst=l['mac']) /
1882 IP(dst=l['ip'], src=ep.ip4.address) /
1883 UDP(sport=1234, dport=1234) /
1886 rxs = self.send_and_expect(self.pg0, p * 17, self.pg2)
1889 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
1890 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
1891 self.assertEqual(rx[UDP].dport, 48879)
1892 # the UDP source port is a random value for hashing
1893 self.assertEqual(rx[VXLAN].gpid, 112)
1894 self.assertEqual(rx[VXLAN].vni, 99)
1895 self.assertTrue(rx[VXLAN].flags.G)
1896 self.assertTrue(rx[VXLAN].flags.Instance)
1897 self.assertTrue(rx[VXLAN].gpflags.A)
1898 self.assertFalse(rx[VXLAN].gpflags.D)
1901 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1905 # repeat in the other EPG
1906 # there's no contract between 220 and 330, but the A-bit is set
1907 # so the packet is cleared for delivery
1910 # a packet with an sclass from a known EPG
1911 p = (Ether(src=self.pg2.remote_mac,
1912 dst=self.pg2.local_mac) /
1913 IP(src=self.pg2.remote_hosts[1].ip4,
1914 dst=self.pg2.local_ip4) /
1915 UDP(sport=1234, dport=48879) /
1916 VXLAN(vni=99, gpid=113, flags=0x88, gpflags='A') /
1917 Ether(src=l['mac'], dst=ep.mac) /
1918 IP(src=l['ip'], dst=ep.ip4.address) /
1919 UDP(sport=1234, dport=1234) /
1922 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
1924 self.assertTrue(find_gbp_endpoint(self,
1925 vx_tun_l2_1.sw_if_index,
1929 # static EP cannot reach the learnt EPs since there is no contract
1930 # only test 1 EP as the others could timeout
1932 p = (Ether(src=ep.mac, dst=l['mac']) /
1933 IP(dst=learnt[0]['ip'], src=ep.ip4.address) /
1934 UDP(sport=1234, dport=1234) /
1937 self.send_and_assert_no_replies(self.pg0, [p])
1940 # refresh the entries after the check for no replies above
1943 # a packet with an sclass from a known EPG
1944 p = (Ether(src=self.pg2.remote_mac,
1945 dst=self.pg2.local_mac) /
1946 IP(src=self.pg2.remote_hosts[1].ip4,
1947 dst=self.pg2.local_ip4) /
1948 UDP(sport=1234, dport=48879) /
1949 VXLAN(vni=99, gpid=113, flags=0x88, gpflags='A') /
1950 Ether(src=l['mac'], dst=ep.mac) /
1951 IP(src=l['ip'], dst=ep.ip4.address) /
1952 UDP(sport=1234, dport=1234) /
1955 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
1957 self.assertTrue(find_gbp_endpoint(self,
1958 vx_tun_l2_1.sw_if_index,
1962 # Add the contract so they can talk
1964 acl = VppGbpAcl(self)
1965 rule = acl.create_rule(permit_deny=1, proto=17)
1966 rule2 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
1967 acl_index = acl.add_vpp_config([rule, rule2])
1968 c1 = VppGbpContract(
1969 self, 401, epg_220.sclass, epg_330.sclass, acl_index,
1970 [VppGbpContractRule(
1971 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1972 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1975 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1976 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1978 [ETH_P_IP, ETH_P_IPV6])
1982 p = (Ether(src=ep.mac, dst=l['mac']) /
1983 IP(dst=l['ip'], src=ep.ip4.address) /
1984 UDP(sport=1234, dport=1234) /
1987 self.send_and_expect(self.pg0, [p], self.pg2)
1990 # send UU packets from the local EP
1992 self.logger.info(self.vapi.cli("sh gbp bridge"))
1993 self.logger.info(self.vapi.cli("sh bridge-domain 1 detail"))
1994 p_uu = (Ether(src=ep.mac, dst="00:11:11:11:11:11") /
1995 IP(dst="10.0.0.133", src=ep.ip4.address) /
1996 UDP(sport=1234, dport=1234) /
1998 rxs = self.send_and_expect(ep.itf, [p_uu], gbd1.uu_fwd)
2000 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2002 p_bm = (Ether(src=ep.mac, dst="ff:ff:ff:ff:ff:ff") /
2003 IP(dst="10.0.0.133", src=ep.ip4.address) /
2004 UDP(sport=1234, dport=1234) /
2006 rxs = self.send_and_expect_only(ep.itf, [p_bm], tun_bm.mcast_itf)
2009 self.assertEqual(rx[IP].src, self.pg4.local_ip4)
2010 self.assertEqual(rx[IP].dst, "239.1.1.1")
2011 self.assertEqual(rx[UDP].dport, 48879)
2012 # the UDP source port is a random value for hashing
2013 self.assertEqual(rx[VXLAN].gpid, 112)
2014 self.assertEqual(rx[VXLAN].vni, 88)
2015 self.assertTrue(rx[VXLAN].flags.G)
2016 self.assertTrue(rx[VXLAN].flags.Instance)
2017 self.assertFalse(rx[VXLAN].gpflags.A)
2018 self.assertFalse(rx[VXLAN].gpflags.D)
2020 acl = VppGbpAcl(self)
2021 rule = acl.create_rule(permit_deny=1, proto=17)
2022 rule2 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
2023 acl_index = acl.add_vpp_config([rule, rule2])
2024 c2 = VppGbpContract(
2025 self, 401, epg_330.sclass, epg_220.sclass, acl_index,
2026 [VppGbpContractRule(
2027 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2028 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2031 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2032 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2034 [ETH_P_IP, ETH_P_IPV6])
2038 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
2041 # Check v6 Endpoints learning
2044 # a packet with an sclass from a known EPG
2045 p = (Ether(src=self.pg2.remote_mac,
2046 dst=self.pg2.local_mac) /
2047 IP(src=self.pg2.remote_hosts[1].ip4,
2048 dst=self.pg2.local_ip4) /
2049 UDP(sport=1234, dport=48879) /
2050 VXLAN(vni=99, gpid=113, flags=0x88) /
2051 Ether(src=l['mac'], dst=ep.mac) /
2052 IPv6(src=l['ip6'], dst=ep.ip6.address) /
2053 UDP(sport=1234, dport=1234) /
2056 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
2057 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
2059 self.assertTrue(find_gbp_endpoint(
2061 vx_tun_l2_1.sw_if_index,
2063 tep=[self.pg2.local_ip4,
2064 self.pg2.remote_hosts[1].ip4]))
2066 self.logger.info(self.vapi.cli("sh int"))
2067 self.logger.info(self.vapi.cli("sh vxlan-gbp tunnel"))
2068 self.logger.info(self.vapi.cli("sh gbp vxlan"))
2069 self.logger.info(self.vapi.cli("sh gbp endpoint"))
2070 self.logger.info(self.vapi.cli("sh gbp interface"))
2073 # EP moves to a different TEP
2076 # a packet with an sclass from a known EPG
2077 p = (Ether(src=self.pg2.remote_mac,
2078 dst=self.pg2.local_mac) /
2079 IP(src=self.pg2.remote_hosts[2].ip4,
2080 dst=self.pg2.local_ip4) /
2081 UDP(sport=1234, dport=48879) /
2082 VXLAN(vni=99, gpid=113, flags=0x88) /
2083 Ether(src=l['mac'], dst=ep.mac) /
2084 IPv6(src=l['ip6'], dst=ep.ip6.address) /
2085 UDP(sport=1234, dport=1234) /
2088 rx = self.send_and_expect(self.pg2, p * 1, self.pg0)
2089 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
2091 self.assertTrue(find_gbp_endpoint(
2093 vx_tun_l2_1.sw_if_index,
2096 tep=[self.pg2.local_ip4,
2097 self.pg2.remote_hosts[2].ip4]))
2100 # v6 remote EP reachability
2103 p = (Ether(src=ep.mac, dst=l['mac']) /
2104 IPv6(dst=l['ip6'], src=ep.ip6.address) /
2105 UDP(sport=1234, dport=1234) /
2108 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
2111 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2112 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[2].ip4)
2113 self.assertEqual(rx[UDP].dport, 48879)
2114 # the UDP source port is a random value for hashing
2115 self.assertEqual(rx[VXLAN].gpid, 112)
2116 self.assertEqual(rx[VXLAN].vni, 99)
2117 self.assertTrue(rx[VXLAN].flags.G)
2118 self.assertTrue(rx[VXLAN].flags.Instance)
2119 self.assertTrue(rx[VXLAN].gpflags.A)
2120 self.assertFalse(rx[VXLAN].gpflags.D)
2121 self.assertEqual(rx[IPv6].dst, l['ip6'])
2127 # a packet with an sclass from a known EPG
2128 p = (Ether(src=self.pg2.remote_mac,
2129 dst=self.pg2.local_mac) /
2130 IP(src=self.pg2.remote_hosts[2].ip4,
2131 dst=self.pg2.local_ip4) /
2132 UDP(sport=1234, dport=48879) /
2133 VXLAN(vni=99, gpid=112, flags=0x88) /
2134 Ether(src=l['mac'], dst=ep.mac) /
2135 IPv6(src=l['ip6'], dst=ep.ip6.address) /
2136 UDP(sport=1234, dport=1234) /
2139 rx = self.send_and_expect(self.pg2, p * 1, self.pg0)
2140 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
2142 self.assertTrue(find_gbp_endpoint(
2144 vx_tun_l2_1.sw_if_index,
2147 tep=[self.pg2.local_ip4,
2148 self.pg2.remote_hosts[2].ip4]))
2151 # check reachability and contract intra-epg
2153 allow_intra_class = self.statistics.get_err_counter(
2154 '/err/gbp-policy-mac/allow-intra-sclass')
2157 p = (Ether(src=ep.mac, dst=l['mac']) /
2158 IPv6(dst=l['ip6'], src=ep.ip6.address) /
2159 UDP(sport=1234, dport=1234) /
2162 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
2165 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2166 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[2].ip4)
2167 self.assertEqual(rx[UDP].dport, 48879)
2168 self.assertEqual(rx[VXLAN].gpid, 112)
2169 self.assertEqual(rx[VXLAN].vni, 99)
2170 self.assertTrue(rx[VXLAN].flags.G)
2171 self.assertTrue(rx[VXLAN].flags.Instance)
2172 self.assertTrue(rx[VXLAN].gpflags.A)
2173 self.assertFalse(rx[VXLAN].gpflags.D)
2174 self.assertEqual(rx[IPv6].dst, l['ip6'])
2176 allow_intra_class += NUM_PKTS
2178 self.assert_error_counter_equal(
2179 '/err/gbp-policy-mac/allow-intra-sclass',
2186 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
2188 self.pg2.unconfig_ip4()
2189 self.pg3.unconfig_ip4()
2190 self.pg4.unconfig_ip4()
2192 def test_gbp_contract(self):
2193 """ GBP Contracts """
2198 gt4 = VppIpTable(self, 0)
2199 gt4.add_vpp_config()
2200 gt6 = VppIpTable(self, 0, is_ip6=True)
2201 gt6.add_vpp_config()
2203 rd0 = VppGbpRouteDomain(self, 0, 400, gt4, gt6, None, None)
2205 rd0.add_vpp_config()
2210 bd1 = VppBridgeDomain(self, 1, arp_term=0)
2211 bd2 = VppBridgeDomain(self, 2, arp_term=0)
2213 bd1.add_vpp_config()
2214 bd2.add_vpp_config()
2216 gbd1 = VppGbpBridgeDomain(self, bd1, rd0, self.loop0)
2217 gbd2 = VppGbpBridgeDomain(self, bd2, rd0, self.loop1)
2219 gbd1.add_vpp_config()
2220 gbd2.add_vpp_config()
2223 # 3 EPGs, 2 of which share a BD.
2225 epgs = [VppGbpEndpointGroup(self, 220, 1220, rd0, gbd1,
2227 "10.0.0.128", "2001:10::128"),
2228 VppGbpEndpointGroup(self, 221, 1221, rd0, gbd1,
2230 "10.0.1.128", "2001:10:1::128"),
2231 VppGbpEndpointGroup(self, 222, 1222, rd0, gbd2,
2233 "10.0.2.128", "2001:10:2::128")]
2235 # 4 end-points, 2 in the same subnet, 3 in the same BD
2237 eps = [VppGbpEndpoint(self, self.pg0,
2239 "10.0.0.1", "11.0.0.1",
2240 "2001:10::1", "3001::1"),
2241 VppGbpEndpoint(self, self.pg1,
2243 "10.0.0.2", "11.0.0.2",
2244 "2001:10::2", "3001::2"),
2245 VppGbpEndpoint(self, self.pg2,
2247 "10.0.1.1", "11.0.0.3",
2248 "2001:10:1::1", "3001::3"),
2249 VppGbpEndpoint(self, self.pg3,
2251 "10.0.2.1", "11.0.0.4",
2252 "2001:10:2::1", "3001::4")]
2255 # Config related to each of the EPGs
2258 # IP config on the BVI interfaces
2260 VppIpInterfaceBind(self, epg.bvi, epg.rd.t4).add_vpp_config()
2261 VppIpInterfaceBind(self, epg.bvi, epg.rd.t6).add_vpp_config()
2262 epg.bvi.set_mac(self.router_mac)
2264 if_ip4 = VppIpInterfaceAddress(self, epg.bvi, epg.bvi_ip4, 32)
2265 if_ip6 = VppIpInterfaceAddress(self, epg.bvi, epg.bvi_ip6, 128)
2266 if_ip4.add_vpp_config()
2267 if_ip6.add_vpp_config()
2269 # add the BD ARP termination entry for BVI IP
2270 epg.bd_arp_ip4 = VppBridgeDomainArpEntry(self, epg.bd.bd,
2271 str(self.router_mac),
2272 epg.bvi_ip4.address)
2273 epg.bd_arp_ip4.add_vpp_config()
2276 epg.add_vpp_config()
2284 self.logger.info(self.vapi.cli("show gbp endpoint"))
2285 self.logger.info(self.vapi.cli("show interface"))
2286 self.logger.info(self.vapi.cli("show br"))
2289 # Intra epg allowed without contract
2291 pkt_intra_epg_220_to_220 = (Ether(src=self.pg0.remote_mac,
2292 dst=self.pg1.remote_mac) /
2293 IP(src=eps[0].ip4.address,
2294 dst=eps[1].ip4.address) /
2295 UDP(sport=1234, dport=1234) /
2298 self.send_and_expect_bridged(self.pg0,
2299 pkt_intra_epg_220_to_220 * 65,
2302 pkt_intra_epg_220_to_220 = (Ether(src=self.pg0.remote_mac,
2303 dst=self.pg1.remote_mac) /
2304 IPv6(src=eps[0].ip6.address,
2305 dst=eps[1].ip6.address) /
2306 UDP(sport=1234, dport=1234) /
2309 self.send_and_expect_bridged6(self.pg0,
2310 pkt_intra_epg_220_to_220 * 65,
2314 # Inter epg denied without contract
2316 pkt_inter_epg_220_to_221 = (Ether(src=self.pg0.remote_mac,
2317 dst=self.pg2.remote_mac) /
2318 IP(src=eps[0].ip4.address,
2319 dst=eps[2].ip4.address) /
2320 UDP(sport=1234, dport=1234) /
2323 self.send_and_assert_no_replies(self.pg0, pkt_inter_epg_220_to_221)
2326 # A uni-directional contract from EPG 220 -> 221
2328 acl = VppGbpAcl(self)
2329 rule = acl.create_rule(permit_deny=1, proto=17)
2330 rule2 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
2331 rule3 = acl.create_rule(permit_deny=1, proto=1)
2332 acl_index = acl.add_vpp_config([rule, rule2, rule3])
2333 c1 = VppGbpContract(
2334 self, 400, epgs[0].sclass, epgs[1].sclass, acl_index,
2335 [VppGbpContractRule(
2336 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2337 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2340 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2341 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2344 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2345 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2347 [ETH_P_IP, ETH_P_IPV6])
2350 self.send_and_expect_bridged(eps[0].itf,
2351 pkt_inter_epg_220_to_221 * 65,
2354 pkt_inter_epg_220_to_222 = (Ether(src=self.pg0.remote_mac,
2355 dst=str(self.router_mac)) /
2356 IP(src=eps[0].ip4.address,
2357 dst=eps[3].ip4.address) /
2358 UDP(sport=1234, dport=1234) /
2360 self.send_and_assert_no_replies(eps[0].itf,
2361 pkt_inter_epg_220_to_222 * 65)
2364 # ping router IP in different BD
2366 pkt_router_ping_220_to_221 = (Ether(src=self.pg0.remote_mac,
2367 dst=str(self.router_mac)) /
2368 IP(src=eps[0].ip4.address,
2369 dst=epgs[1].bvi_ip4.address) /
2370 ICMP(type='echo-request'))
2372 self.send_and_expect(self.pg0, [pkt_router_ping_220_to_221], self.pg0)
2374 pkt_router_ping_220_to_221 = (Ether(src=self.pg0.remote_mac,
2375 dst=str(self.router_mac)) /
2376 IPv6(src=eps[0].ip6.address,
2377 dst=epgs[1].bvi_ip6.address) /
2378 ICMPv6EchoRequest())
2380 self.send_and_expect(self.pg0, [pkt_router_ping_220_to_221], self.pg0)
2383 # contract for the return direction
2385 c2 = VppGbpContract(
2386 self, 400, epgs[1].sclass, epgs[0].sclass, acl_index,
2387 [VppGbpContractRule(
2388 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2389 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2392 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2393 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2395 [ETH_P_IP, ETH_P_IPV6])
2398 self.send_and_expect_bridged(eps[0].itf,
2399 pkt_inter_epg_220_to_221 * 65,
2401 pkt_inter_epg_221_to_220 = (Ether(src=self.pg2.remote_mac,
2402 dst=self.pg0.remote_mac) /
2403 IP(src=eps[2].ip4.address,
2404 dst=eps[0].ip4.address) /
2405 UDP(sport=1234, dport=1234) /
2407 self.send_and_expect_bridged(eps[2].itf,
2408 pkt_inter_epg_221_to_220 * 65,
2410 pkt_inter_epg_221_to_220 = (Ether(src=self.pg2.remote_mac,
2411 dst=str(self.router_mac)) /
2412 IP(src=eps[2].ip4.address,
2413 dst=eps[0].ip4.address) /
2414 UDP(sport=1234, dport=1234) /
2416 self.send_and_expect_routed(eps[2].itf,
2417 pkt_inter_epg_221_to_220 * 65,
2419 str(self.router_mac))
2420 pkt_inter_epg_221_to_220 = (Ether(src=self.pg2.remote_mac,
2421 dst=str(self.router_mac)) /
2422 IPv6(src=eps[2].ip6.address,
2423 dst=eps[0].ip6.address) /
2424 UDP(sport=1234, dport=1234) /
2426 self.send_and_expect_routed6(eps[2].itf,
2427 pkt_inter_epg_221_to_220 * 65,
2429 str(self.router_mac))
2432 # contract between 220 and 222 uni-direction
2434 c3 = VppGbpContract(
2435 self, 400, epgs[0].sclass, epgs[2].sclass, acl_index,
2436 [VppGbpContractRule(
2437 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2438 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2441 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2442 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2444 [ETH_P_IP, ETH_P_IPV6])
2447 self.send_and_expect(eps[0].itf,
2448 pkt_inter_epg_220_to_222 * 65,
2451 c3.remove_vpp_config()
2452 c1.remove_vpp_config()
2453 c2.remove_vpp_config()
2454 acl.remove_vpp_config()
2456 def test_gbp_bd_drop_flags(self):
2457 """ GBP BD drop flags """
2462 gt4 = VppIpTable(self, 1)
2463 gt4.add_vpp_config()
2464 gt6 = VppIpTable(self, 1, is_ip6=True)
2465 gt6.add_vpp_config()
2467 rd1 = VppGbpRouteDomain(self, 1, 401, gt4, gt6)
2468 rd1.add_vpp_config()
2471 # a GBP bridge domain with a BVI only
2473 bd1 = VppBridgeDomain(self, 1)
2474 bd1.add_vpp_config()
2476 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0,
2478 uu_drop=True, bm_drop=True)
2479 gbd1.add_vpp_config()
2481 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2482 self.logger.info(self.vapi.cli("sh gbp bridge"))
2484 # ... and has a /32 applied
2485 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2486 ip_addr.add_vpp_config()
2489 # The Endpoint-group
2491 epg_220 = VppGbpEndpointGroup(self, 220, 112, rd1, gbd1,
2495 VppGbpEndpointRetention(2))
2496 epg_220.add_vpp_config()
2498 ep = VppGbpEndpoint(self, self.pg0,
2500 "10.0.0.127", "11.0.0.127",
2501 "2001:10::1", "3001::1")
2505 # send UU/BM packet from the local EP with UU drop and BM drop enabled
2508 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2509 self.logger.info(self.vapi.cli("sh gbp bridge"))
2510 p_uu = (Ether(src=ep.mac, dst="00:11:11:11:11:11") /
2511 IP(dst="10.0.0.133", src=ep.ip4.address) /
2512 UDP(sport=1234, dport=1234) /
2514 self.send_and_assert_no_replies(ep.itf, [p_uu])
2516 p_bm = (Ether(src=ep.mac, dst="ff:ff:ff:ff:ff:ff") /
2517 IP(dst="10.0.0.133", src=ep.ip4.address) /
2518 UDP(sport=1234, dport=1234) /
2520 self.send_and_assert_no_replies(ep.itf, [p_bm])
2522 self.pg3.unconfig_ip4()
2524 self.logger.info(self.vapi.cli("sh int"))
2526 def test_gbp_bd_arp_flags(self):
2527 """ GBP BD arp flags """
2532 gt4 = VppIpTable(self, 1)
2533 gt4.add_vpp_config()
2534 gt6 = VppIpTable(self, 1, is_ip6=True)
2535 gt6.add_vpp_config()
2537 rd1 = VppGbpRouteDomain(self, 1, 401, gt4, gt6)
2538 rd1.add_vpp_config()
2541 # Pg4 hosts the IP6 UU-flood VXLAN tunnel
2543 self.pg4.config_ip4()
2544 self.pg4.resolve_arp()
2547 # Add a mcast destination VXLAN-GBP tunnel for B&M traffic
2549 tun_uu = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
2552 tun_uu.add_vpp_config()
2555 # a GBP bridge domain with a BVI and a UU-flood interface
2557 bd1 = VppBridgeDomain(self, 1)
2558 bd1.add_vpp_config()
2560 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0,
2563 gbd1.add_vpp_config()
2565 # ... and has a /32 applied
2566 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2567 ip_addr.add_vpp_config()
2570 # The Endpoint-group
2572 epg_220 = VppGbpEndpointGroup(self, 220, 112, rd1, gbd1,
2576 VppGbpEndpointRetention(2))
2577 epg_220.add_vpp_config()
2579 ep = VppGbpEndpoint(self, self.pg0,
2581 "10.0.0.127", "11.0.0.127",
2582 "2001:10::1", "3001::1")
2586 # send ARP packet from the local EP expect it on the uu interface
2588 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2589 self.logger.info(self.vapi.cli("sh gbp bridge"))
2590 p_arp = (Ether(src=ep.mac, dst="ff:ff:ff:ff:ff:ff") /
2592 psrc=ep.ip4.address, pdst="10.0.0.99",
2594 hwdst="ff:ff:ff:ff:ff:ff"))
2595 self.send_and_expect(ep.itf, [p_arp], self.pg4)
2597 self.pg4.unconfig_ip4()
2599 def test_gbp_learn_vlan_l2(self):
2600 """ GBP L2 Endpoint w/ VLANs"""
2602 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
2603 learnt = [{'mac': '00:00:11:11:11:01',
2605 'ip6': '2001:10::2'},
2606 {'mac': '00:00:11:11:11:02',
2608 'ip6': '2001:10::3'}]
2613 gt4 = VppIpTable(self, 1)
2614 gt4.add_vpp_config()
2615 gt6 = VppIpTable(self, 1, is_ip6=True)
2616 gt6.add_vpp_config()
2618 rd1 = VppGbpRouteDomain(self, 1, 401, gt4, gt6)
2619 rd1.add_vpp_config()
2622 # Pg2 hosts the vxlan tunnel, hosts on pg2 to act as TEPs
2624 self.pg2.config_ip4()
2625 self.pg2.resolve_arp()
2626 self.pg2.generate_remote_hosts(4)
2627 self.pg2.configure_ipv4_neighbors()
2628 self.pg3.config_ip4()
2629 self.pg3.resolve_arp()
2632 # The EP will be on a vlan sub-interface
2634 vlan_11 = VppDot1QSubint(self, self.pg0, 11)
2636 self.vapi.l2_interface_vlan_tag_rewrite(
2637 sw_if_index=vlan_11.sw_if_index, vtr_op=L2_VTR_OP.L2_POP_1,
2640 bd_uu_fwd = VppVxlanGbpTunnel(self, self.pg3.local_ip4,
2641 self.pg3.remote_ip4, 116)
2642 bd_uu_fwd.add_vpp_config()
2645 # a GBP bridge domain with a BVI and a UU-flood interface
2646 # The BD is marked as do not learn, so no endpoints are ever
2647 # learnt in this BD.
2649 bd1 = VppBridgeDomain(self, 1)
2650 bd1.add_vpp_config()
2651 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0, bd_uu_fwd,
2653 gbd1.add_vpp_config()
2655 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2656 self.logger.info(self.vapi.cli("sh gbp bridge"))
2658 # ... and has a /32 applied
2659 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2660 ip_addr.add_vpp_config()
2663 # The Endpoint-group in which we are learning endpoints
2665 epg_220 = VppGbpEndpointGroup(self, 220, 441, rd1, gbd1,
2669 VppGbpEndpointRetention(2))
2670 epg_220.add_vpp_config()
2673 # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
2676 vx_tun_l2_1 = VppGbpVxlanTunnel(
2677 self, 99, bd1.bd_id,
2678 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L2,
2680 vx_tun_l2_1.add_vpp_config()
2683 # A static endpoint that the learnt endpoints are trying to
2686 ep = VppGbpEndpoint(self, vlan_11,
2688 "10.0.0.127", "11.0.0.127",
2689 "2001:10::1", "3001::1")
2692 self.assertTrue(find_route(self, ep.ip4.address, 32, table_id=1))
2695 # Send to the static EP
2697 for ii, l in enumerate(learnt):
2698 # a packet with an sclass from a known EPG
2699 # arriving on an unknown TEP
2700 p = (Ether(src=self.pg2.remote_mac,
2701 dst=self.pg2.local_mac) /
2702 IP(src=self.pg2.remote_hosts[1].ip4,
2703 dst=self.pg2.local_ip4) /
2704 UDP(sport=1234, dport=48879) /
2705 VXLAN(vni=99, gpid=441, flags=0x88) /
2706 Ether(src=l['mac'], dst=ep.mac) /
2707 IP(src=l['ip'], dst=ep.ip4.address) /
2708 UDP(sport=1234, dport=1234) /
2711 rxs = self.send_and_expect(self.pg2, [p], self.pg0)
2714 # packet to EP has the EP's vlan tag
2717 self.assertEqual(rx[Dot1Q].vlan, 11)
2720 # the EP is not learnt since the BD setting prevents it
2723 self.assertFalse(find_gbp_endpoint(self,
2724 vx_tun_l2_1.sw_if_index,
2726 self.assertEqual(INDEX_INVALID,
2727 find_vxlan_gbp_tunnel(
2730 self.pg2.remote_hosts[1].ip4,
2733 self.assertEqual(len(self.vapi.gbp_endpoint_dump()), 1)
2737 # we didn't learn the remotes so they are sent to the UU-fwd
2740 p = (Ether(src=ep.mac, dst=l['mac']) /
2742 IP(dst=l['ip'], src=ep.ip4.address) /
2743 UDP(sport=1234, dport=1234) /
2746 rxs = self.send_and_expect(self.pg0, p * 17, self.pg3)
2749 self.assertEqual(rx[IP].src, self.pg3.local_ip4)
2750 self.assertEqual(rx[IP].dst, self.pg3.remote_ip4)
2751 self.assertEqual(rx[UDP].dport, 48879)
2752 # the UDP source port is a random value for hashing
2753 self.assertEqual(rx[VXLAN].gpid, 441)
2754 self.assertEqual(rx[VXLAN].vni, 116)
2755 self.assertTrue(rx[VXLAN].flags.G)
2756 self.assertTrue(rx[VXLAN].flags.Instance)
2757 self.assertFalse(rx[VXLAN].gpflags.A)
2758 self.assertFalse(rx[VXLAN].gpflags.D)
2760 self.pg2.unconfig_ip4()
2761 self.pg3.unconfig_ip4()
2763 def test_gbp_learn_l3(self):
2764 """ GBP L3 Endpoint Learning """
2766 self.vapi.cli("set logging class gbp level debug")
2768 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
2769 routed_dst_mac = "00:0c:0c:0c:0c:0c"
2770 routed_src_mac = "00:22:bd:f8:19:ff"
2772 learnt = [{'mac': '00:00:11:11:11:02',
2774 'ip6': '2001:10::2'},
2775 {'mac': '00:00:11:11:11:03',
2777 'ip6': '2001:10::3'}]
2782 t4 = VppIpTable(self, 1)
2784 t6 = VppIpTable(self, 1, True)
2787 tun_ip4_uu = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
2788 self.pg4.remote_ip4, 114)
2789 tun_ip6_uu = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
2790 self.pg4.remote_ip4, 116)
2791 tun_ip4_uu.add_vpp_config()
2792 tun_ip6_uu.add_vpp_config()
2794 rd1 = VppGbpRouteDomain(self, 2, 401, t4, t6, tun_ip4_uu, tun_ip6_uu)
2795 rd1.add_vpp_config()
2797 self.loop0.set_mac(self.router_mac)
2800 # Bind the BVI to the RD
2802 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
2803 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
2806 # Pg2 hosts the vxlan tunnel
2807 # hosts on pg2 to act as TEPs
2811 self.pg2.config_ip4()
2812 self.pg2.resolve_arp()
2813 self.pg2.generate_remote_hosts(4)
2814 self.pg2.configure_ipv4_neighbors()
2815 self.pg3.config_ip4()
2816 self.pg3.resolve_arp()
2817 self.pg4.config_ip4()
2818 self.pg4.resolve_arp()
2821 # a GBP bridge domain with a BVI and a UU-flood interface
2823 bd1 = VppBridgeDomain(self, 1)
2824 bd1.add_vpp_config()
2825 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0, self.pg3)
2826 gbd1.add_vpp_config()
2828 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2829 self.logger.info(self.vapi.cli("sh gbp bridge"))
2830 self.logger.info(self.vapi.cli("sh gbp route"))
2832 # ... and has a /32 and /128 applied
2833 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2834 ip4_addr.add_vpp_config()
2835 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 128)
2836 ip6_addr.add_vpp_config()
2839 # The Endpoint-group in which we are learning endpoints
2841 epg_220 = VppGbpEndpointGroup(self, 220, 441, rd1, gbd1,
2845 VppGbpEndpointRetention(2))
2846 epg_220.add_vpp_config()
2849 # The VXLAN GBP tunnel is in L3 mode with learning enabled
2851 vx_tun_l3 = VppGbpVxlanTunnel(
2852 self, 101, rd1.rd_id,
2853 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
2855 vx_tun_l3.add_vpp_config()
2858 # A static endpoint that the learnt endpoints are trying to
2861 ep = VppGbpEndpoint(self, self.pg0,
2863 "10.0.0.127", "11.0.0.127",
2864 "2001:10::1", "3001::1")
2868 # learn some remote IPv4 EPs
2870 for ii, l in enumerate(learnt):
2871 # a packet with an sclass from a known EPG
2872 # arriving on an unknown TEP
2873 p = (Ether(src=self.pg2.remote_mac,
2874 dst=self.pg2.local_mac) /
2875 IP(src=self.pg2.remote_hosts[1].ip4,
2876 dst=self.pg2.local_ip4) /
2877 UDP(sport=1234, dport=48879) /
2878 VXLAN(vni=101, gpid=441, flags=0x88) /
2879 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2880 IP(src=l['ip'], dst=ep.ip4.address) /
2881 UDP(sport=1234, dport=1234) /
2884 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2887 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2890 self.pg2.remote_hosts[1].ip4,
2892 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2894 # endpoint learnt via the parent GBP-vxlan interface
2895 self.assertTrue(find_gbp_endpoint(self,
2896 vx_tun_l3._sw_if_index,
2900 # Static IPv4 EP replies to learnt
2903 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2904 IP(dst=l['ip'], src=ep.ip4.address) /
2905 UDP(sport=1234, dport=1234) /
2908 rxs = self.send_and_expect(self.pg0, p * 1, self.pg2)
2911 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2912 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2913 self.assertEqual(rx[UDP].dport, 48879)
2914 # the UDP source port is a random value for hashing
2915 self.assertEqual(rx[VXLAN].gpid, 441)
2916 self.assertEqual(rx[VXLAN].vni, 101)
2917 self.assertTrue(rx[VXLAN].flags.G)
2918 self.assertTrue(rx[VXLAN].flags.Instance)
2919 self.assertTrue(rx[VXLAN].gpflags.A)
2920 self.assertFalse(rx[VXLAN].gpflags.D)
2922 inner = rx[VXLAN].payload
2924 self.assertEqual(inner[Ether].src, routed_src_mac)
2925 self.assertEqual(inner[Ether].dst, routed_dst_mac)
2926 self.assertEqual(inner[IP].src, ep.ip4.address)
2927 self.assertEqual(inner[IP].dst, l['ip'])
2930 self.assertFalse(find_gbp_endpoint(self,
2935 # learn some remote IPv6 EPs
2937 for ii, l in enumerate(learnt):
2938 # a packet with an sclass from a known EPG
2939 # arriving on an unknown TEP
2940 p = (Ether(src=self.pg2.remote_mac,
2941 dst=self.pg2.local_mac) /
2942 IP(src=self.pg2.remote_hosts[1].ip4,
2943 dst=self.pg2.local_ip4) /
2944 UDP(sport=1234, dport=48879) /
2945 VXLAN(vni=101, gpid=441, flags=0x88) /
2946 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2947 IPv6(src=l['ip6'], dst=ep.ip6.address) /
2948 UDP(sport=1234, dport=1234) /
2951 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2954 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2957 self.pg2.remote_hosts[1].ip4,
2959 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2961 self.logger.info(self.vapi.cli("show gbp bridge"))
2962 self.logger.info(self.vapi.cli("show vxlan-gbp tunnel"))
2963 self.logger.info(self.vapi.cli("show gbp vxlan"))
2964 self.logger.info(self.vapi.cli("show int addr"))
2966 # endpoint learnt via the TEP
2967 self.assertTrue(find_gbp_endpoint(self, ip=l['ip6']))
2969 self.logger.info(self.vapi.cli("show gbp endpoint"))
2970 self.logger.info(self.vapi.cli("show ip fib index 1 %s" % l['ip']))
2973 # Static EP replies to learnt
2976 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2977 IPv6(dst=l['ip6'], src=ep.ip6.address) /
2978 UDP(sport=1234, dport=1234) /
2981 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
2984 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2985 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2986 self.assertEqual(rx[UDP].dport, 48879)
2987 # the UDP source port is a random value for hashing
2988 self.assertEqual(rx[VXLAN].gpid, 441)
2989 self.assertEqual(rx[VXLAN].vni, 101)
2990 self.assertTrue(rx[VXLAN].flags.G)
2991 self.assertTrue(rx[VXLAN].flags.Instance)
2992 self.assertTrue(rx[VXLAN].gpflags.A)
2993 self.assertFalse(rx[VXLAN].gpflags.D)
2995 inner = rx[VXLAN].payload
2997 self.assertEqual(inner[Ether].src, routed_src_mac)
2998 self.assertEqual(inner[Ether].dst, routed_dst_mac)
2999 self.assertEqual(inner[IPv6].src, ep.ip6.address)
3000 self.assertEqual(inner[IPv6].dst, l['ip6'])
3002 self.logger.info(self.vapi.cli("sh gbp endpoint"))
3004 self.wait_for_ep_timeout(ip=l['ip'])
3007 # Static sends to unknown EP with no route
3009 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
3010 IP(dst="10.0.0.99", src=ep.ip4.address) /
3011 UDP(sport=1234, dport=1234) /
3014 self.send_and_assert_no_replies(self.pg0, [p])
3017 # Add a route to static EP's v4 and v6 subnet
3019 se_10_24 = VppGbpSubnet(
3020 self, rd1, "10.0.0.0", 24,
3021 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT)
3022 se_10_24.add_vpp_config()
3025 # static pings router
3027 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
3028 IP(dst=epg_220.bvi_ip4.address, src=ep.ip4.address) /
3029 UDP(sport=1234, dport=1234) /
3032 self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg0)
3034 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
3035 IPv6(dst=epg_220.bvi_ip6.address, src=ep.ip6.address) /
3036 UDP(sport=1234, dport=1234) /
3039 self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg0)
3042 # packets to address in the subnet are sent on the uu-fwd
3044 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
3045 IP(dst="10.0.0.99", src=ep.ip4.address) /
3046 UDP(sport=1234, dport=1234) /
3049 rxs = self.send_and_expect(self.pg0, [p], self.pg4)
3051 self.assertEqual(rx[IP].src, self.pg4.local_ip4)
3052 self.assertEqual(rx[IP].dst, self.pg4.remote_ip4)
3053 self.assertEqual(rx[UDP].dport, 48879)
3054 # the UDP source port is a random value for hashing
3055 self.assertEqual(rx[VXLAN].gpid, 441)
3056 self.assertEqual(rx[VXLAN].vni, 114)
3057 self.assertTrue(rx[VXLAN].flags.G)
3058 self.assertTrue(rx[VXLAN].flags.Instance)
3059 # policy is not applied to packets sent to the uu-fwd interfaces
3060 self.assertFalse(rx[VXLAN].gpflags.A)
3061 self.assertFalse(rx[VXLAN].gpflags.D)
3064 # learn some remote IPv4 EPs
3066 for ii, l in enumerate(learnt):
3067 # a packet with an sclass from a known EPG
3068 # arriving on an unknown TEP
3069 p = (Ether(src=self.pg2.remote_mac,
3070 dst=self.pg2.local_mac) /
3071 IP(src=self.pg2.remote_hosts[2].ip4,
3072 dst=self.pg2.local_ip4) /
3073 UDP(sport=1234, dport=48879) /
3074 VXLAN(vni=101, gpid=441, flags=0x88) /
3075 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
3076 IP(src=l['ip'], dst=ep.ip4.address) /
3077 UDP(sport=1234, dport=1234) /
3080 rx = self.send_and_expect(self.pg2, [p], self.pg0)
3083 tep1_sw_if_index = find_vxlan_gbp_tunnel(
3086 self.pg2.remote_hosts[2].ip4,
3088 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
3090 # endpoint learnt via the parent GBP-vxlan interface
3091 self.assertTrue(find_gbp_endpoint(self,
3092 vx_tun_l3._sw_if_index,
3096 # Add a remote endpoint from the API
3098 rep_88 = VppGbpEndpoint(self, vx_tun_l3,
3100 "10.0.0.88", "11.0.0.88",
3101 "2001:10::88", "3001::88",
3102 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
3104 self.pg2.remote_hosts[2].ip4,
3106 rep_88.add_vpp_config()
3109 # Add a remote endpoint from the API that matches an existing one
3110 # this is a lower priority, hence the packet is sent to the DP leanrt
3113 rep_2 = VppGbpEndpoint(self, vx_tun_l3,
3115 learnt[0]['ip'], "11.0.0.101",
3116 learnt[0]['ip6'], "3001::101",
3117 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
3119 self.pg2.remote_hosts[1].ip4,
3121 rep_2.add_vpp_config()
3124 # Add a route to the learned EP's v4 subnet
3125 # packets should be send on the v4/v6 uu=fwd interface resp.
3127 se_10_1_24 = VppGbpSubnet(
3128 self, rd1, "10.0.1.0", 24,
3129 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT)
3130 se_10_1_24.add_vpp_config()
3132 self.logger.info(self.vapi.cli("show gbp endpoint"))
3134 ips = ["10.0.0.88", learnt[0]['ip']]
3136 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
3137 IP(dst=ip, src=ep.ip4.address) /
3138 UDP(sport=1234, dport=1234) /
3141 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
3144 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
3145 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[2].ip4)
3146 self.assertEqual(rx[UDP].dport, 48879)
3147 # the UDP source port is a random value for hashing
3148 self.assertEqual(rx[VXLAN].gpid, 441)
3149 self.assertEqual(rx[VXLAN].vni, 101)
3150 self.assertTrue(rx[VXLAN].flags.G)
3151 self.assertTrue(rx[VXLAN].flags.Instance)
3152 self.assertTrue(rx[VXLAN].gpflags.A)
3153 self.assertFalse(rx[VXLAN].gpflags.D)
3155 inner = rx[VXLAN].payload
3157 self.assertEqual(inner[Ether].src, routed_src_mac)
3158 self.assertEqual(inner[Ether].dst, routed_dst_mac)
3159 self.assertEqual(inner[IP].src, ep.ip4.address)
3160 self.assertEqual(inner[IP].dst, ip)
3163 # remove the API remote EPs, only API sourced is gone, the DP
3164 # learnt one remains
3166 rep_88.remove_vpp_config()
3167 rep_2.remove_vpp_config()
3169 self.assertTrue(find_gbp_endpoint(self, ip=rep_2.ip4.address))
3171 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
3172 IP(src=ep.ip4.address, dst=rep_2.ip4.address) /
3173 UDP(sport=1234, dport=1234) /
3175 rxs = self.send_and_expect(self.pg0, [p], self.pg2)
3177 self.assertFalse(find_gbp_endpoint(self, ip=rep_88.ip4.address))
3179 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
3180 IP(src=ep.ip4.address, dst=rep_88.ip4.address) /
3181 UDP(sport=1234, dport=1234) /
3183 rxs = self.send_and_expect(self.pg0, [p], self.pg4)
3186 # to appease the testcase we cannot have the registered EP still
3187 # present (because it's DP learnt) when the TC ends so wait until
3190 self.wait_for_ep_timeout(ip=rep_88.ip4.address)
3191 self.wait_for_ep_timeout(ip=rep_2.ip4.address)
3194 # Same as above, learn a remote EP via CP and DP
3195 # this time remove the DP one first. expect the CP data to remain
3197 rep_3 = VppGbpEndpoint(self, vx_tun_l3,
3199 "10.0.1.4", "11.0.0.103",
3200 "2001::10:3", "3001::103",
3201 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
3203 self.pg2.remote_hosts[1].ip4,
3205 rep_3.add_vpp_config()
3207 p = (Ether(src=self.pg2.remote_mac,
3208 dst=self.pg2.local_mac) /
3209 IP(src=self.pg2.remote_hosts[2].ip4,
3210 dst=self.pg2.local_ip4) /
3211 UDP(sport=1234, dport=48879) /
3212 VXLAN(vni=101, gpid=441, flags=0x88) /
3213 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
3214 IP(src="10.0.1.4", dst=ep.ip4.address) /
3215 UDP(sport=1234, dport=1234) /
3217 rxs = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
3219 self.assertTrue(find_gbp_endpoint(self,
3220 vx_tun_l3._sw_if_index,
3221 ip=rep_3.ip4.address,
3222 tep=[self.pg2.local_ip4,
3223 self.pg2.remote_hosts[2].ip4]))
3225 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
3226 IP(dst="10.0.1.4", src=ep.ip4.address) /
3227 UDP(sport=1234, dport=1234) /
3229 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
3231 # host 2 is the DP learned TEP
3233 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
3234 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[2].ip4)
3236 self.wait_for_ep_timeout(ip=rep_3.ip4.address,
3237 tep=[self.pg2.local_ip4,
3238 self.pg2.remote_hosts[2].ip4])
3240 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
3242 # host 1 is the CP learned TEP
3244 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
3245 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
3248 # shutdown with learnt endpoint present
3250 p = (Ether(src=self.pg2.remote_mac,
3251 dst=self.pg2.local_mac) /
3252 IP(src=self.pg2.remote_hosts[1].ip4,
3253 dst=self.pg2.local_ip4) /
3254 UDP(sport=1234, dport=48879) /
3255 VXLAN(vni=101, gpid=441, flags=0x88) /
3256 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
3257 IP(src=learnt[1]['ip'], dst=ep.ip4.address) /
3258 UDP(sport=1234, dport=1234) /
3261 rx = self.send_and_expect(self.pg2, [p], self.pg0)
3263 # endpoint learnt via the parent GBP-vxlan interface
3264 self.assertTrue(find_gbp_endpoint(self,
3265 vx_tun_l3._sw_if_index,
3270 # remote endpoint becomes local
3272 self.pg2.unconfig_ip4()
3273 self.pg3.unconfig_ip4()
3274 self.pg4.unconfig_ip4()
3276 def test_gbp_redirect(self):
3277 """ GBP Endpoint Redirect """
3279 self.vapi.cli("set logging class gbp level debug")
3281 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
3282 routed_dst_mac = "00:0c:0c:0c:0c:0c"
3283 routed_src_mac = "00:22:bd:f8:19:ff"
3285 learnt = [{'mac': '00:00:11:11:11:02',
3287 'ip6': '2001:10::2'},
3288 {'mac': '00:00:11:11:11:03',
3290 'ip6': '2001:10::3'}]
3295 t4 = VppIpTable(self, 1)
3297 t6 = VppIpTable(self, 1, True)
3300 rd1 = VppGbpRouteDomain(self, 2, 402, t4, t6)
3301 rd1.add_vpp_config()
3303 self.loop0.set_mac(self.router_mac)
3306 # Bind the BVI to the RD
3308 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
3309 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
3312 # Pg7 hosts a BD's UU-fwd
3314 self.pg7.config_ip4()
3315 self.pg7.resolve_arp()
3318 # a GBP bridge domains for the EPs
3320 bd1 = VppBridgeDomain(self, 1)
3321 bd1.add_vpp_config()
3322 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0)
3323 gbd1.add_vpp_config()
3325 bd2 = VppBridgeDomain(self, 2)
3326 bd2.add_vpp_config()
3327 gbd2 = VppGbpBridgeDomain(self, bd2, rd1, self.loop1)
3328 gbd2.add_vpp_config()
3330 # ... and has a /32 and /128 applied
3331 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
3332 ip4_addr.add_vpp_config()
3333 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 128)
3334 ip6_addr.add_vpp_config()
3335 ip4_addr = VppIpInterfaceAddress(self, gbd2.bvi, "10.0.1.128", 32)
3336 ip4_addr.add_vpp_config()
3337 ip6_addr = VppIpInterfaceAddress(self, gbd2.bvi, "2001:11::128", 128)
3338 ip6_addr.add_vpp_config()
3341 # The Endpoint-groups in which we are learning endpoints
3343 epg_220 = VppGbpEndpointGroup(self, 220, 440, rd1, gbd1,
3347 VppGbpEndpointRetention(2))
3348 epg_220.add_vpp_config()
3349 epg_221 = VppGbpEndpointGroup(self, 221, 441, rd1, gbd2,
3353 VppGbpEndpointRetention(2))
3354 epg_221.add_vpp_config()
3355 epg_222 = VppGbpEndpointGroup(self, 222, 442, rd1, gbd1,
3359 VppGbpEndpointRetention(2))
3360 epg_222.add_vpp_config()
3363 # a GBP bridge domains for the SEPs
3365 bd_uu1 = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
3366 self.pg7.remote_ip4, 116)
3367 bd_uu1.add_vpp_config()
3368 bd_uu2 = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
3369 self.pg7.remote_ip4, 117)
3370 bd_uu2.add_vpp_config()
3372 bd3 = VppBridgeDomain(self, 3)
3373 bd3.add_vpp_config()
3374 gbd3 = VppGbpBridgeDomain(self, bd3, rd1, self.loop2,
3375 bd_uu1, learn=False)
3376 gbd3.add_vpp_config()
3377 bd4 = VppBridgeDomain(self, 4)
3378 bd4.add_vpp_config()
3379 gbd4 = VppGbpBridgeDomain(self, bd4, rd1, self.loop3,
3380 bd_uu2, learn=False)
3381 gbd4.add_vpp_config()
3384 # EPGs in which the service endpoints exist
3386 epg_320 = VppGbpEndpointGroup(self, 320, 550, rd1, gbd3,
3390 VppGbpEndpointRetention(2))
3391 epg_320.add_vpp_config()
3392 epg_321 = VppGbpEndpointGroup(self, 321, 551, rd1, gbd4,
3396 VppGbpEndpointRetention(2))
3397 epg_321.add_vpp_config()
3400 # three local endpoints
3402 ep1 = VppGbpEndpoint(self, self.pg0,
3404 "10.0.0.1", "11.0.0.1",
3405 "2001:10::1", "3001:10::1")
3406 ep1.add_vpp_config()
3407 ep2 = VppGbpEndpoint(self, self.pg1,
3409 "10.0.1.1", "11.0.1.1",
3410 "2001:11::1", "3001:11::1")
3411 ep2.add_vpp_config()
3412 ep3 = VppGbpEndpoint(self, self.pg2,
3414 "10.0.2.2", "11.0.2.2",
3415 "2001:12::1", "3001:12::1")
3416 ep3.add_vpp_config()
3421 sep1 = VppGbpEndpoint(self, self.pg3,
3423 "12.0.0.1", "13.0.0.1",
3424 "4001:10::1", "5001:10::1")
3425 sep1.add_vpp_config()
3426 sep2 = VppGbpEndpoint(self, self.pg4,
3428 "12.0.0.2", "13.0.0.2",
3429 "4001:10::2", "5001:10::2")
3430 sep2.add_vpp_config()
3431 sep3 = VppGbpEndpoint(self, self.pg5,
3433 "12.0.1.1", "13.0.1.1",
3434 "4001:11::1", "5001:11::1")
3435 sep3.add_vpp_config()
3436 # this EP is not installed immediately
3437 sep4 = VppGbpEndpoint(self, self.pg6,
3439 "12.0.1.2", "13.0.1.2",
3440 "4001:11::2", "5001:11::2")
3443 # an L2 switch packet between local EPs in different EPGs
3444 # different dest ports on each so the are LB hashed differently
3446 p4 = [(Ether(src=ep1.mac, dst=ep3.mac) /
3447 IP(src=ep1.ip4.address, dst=ep3.ip4.address) /
3448 UDP(sport=1234, dport=1234) /
3450 (Ether(src=ep3.mac, dst=ep1.mac) /
3451 IP(src=ep3.ip4.address, dst=ep1.ip4.address) /
3452 UDP(sport=1234, dport=1234) /
3454 p6 = [(Ether(src=ep1.mac, dst=ep3.mac) /
3455 IPv6(src=ep1.ip6.address, dst=ep3.ip6.address) /
3456 UDP(sport=1234, dport=1234) /
3458 (Ether(src=ep3.mac, dst=ep1.mac) /
3459 IPv6(src=ep3.ip6.address, dst=ep1.ip6.address) /
3460 UDP(sport=1234, dport=1230) /
3463 # should be dropped since no contract yet
3464 self.send_and_assert_no_replies(self.pg0, [p4[0]])
3465 self.send_and_assert_no_replies(self.pg0, [p6[0]])
3468 # Add a contract with a rule to load-balance redirect via SEP1 and SEP2
3469 # one of the next-hops is via an EP that is not known
3471 acl = VppGbpAcl(self)
3472 rule4 = acl.create_rule(permit_deny=1, proto=17)
3473 rule6 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
3474 acl_index = acl.add_vpp_config([rule4, rule6])
3477 # test the src-ip hash mode
3479 c1 = VppGbpContract(
3480 self, 402, epg_220.sclass, epg_222.sclass, acl_index,
3481 [VppGbpContractRule(
3482 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3483 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3484 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3485 sep1.ip4, sep1.epg.rd),
3486 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3487 sep2.ip4, sep2.epg.rd)]),
3489 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3490 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3491 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3492 sep3.ip6, sep3.epg.rd),
3493 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3494 sep4.ip6, sep4.epg.rd)])],
3495 [ETH_P_IP, ETH_P_IPV6])
3498 c2 = VppGbpContract(
3499 self, 402, epg_222.sclass, epg_220.sclass, acl_index,
3500 [VppGbpContractRule(
3501 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3502 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3503 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3504 sep1.ip4, sep1.epg.rd),
3505 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3506 sep2.ip4, sep2.epg.rd)]),
3508 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3509 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3510 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3511 sep3.ip6, sep3.epg.rd),
3512 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3513 sep4.ip6, sep4.epg.rd)])],
3514 [ETH_P_IP, ETH_P_IPV6])
3518 # send again with the contract preset, now packets arrive
3519 # at SEP1 or SEP2 depending on the hashing
3521 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3524 self.assertEqual(rx[Ether].src, routed_src_mac)
3525 self.assertEqual(rx[Ether].dst, sep1.mac)
3526 self.assertEqual(rx[IP].src, ep1.ip4.address)
3527 self.assertEqual(rx[IP].dst, ep3.ip4.address)
3529 rxs = self.send_and_expect(self.pg2, p4[1] * 17, sep2.itf)
3532 self.assertEqual(rx[Ether].src, routed_src_mac)
3533 self.assertEqual(rx[Ether].dst, sep2.mac)
3534 self.assertEqual(rx[IP].src, ep3.ip4.address)
3535 self.assertEqual(rx[IP].dst, ep1.ip4.address)
3537 rxs = self.send_and_expect(self.pg0, p6[0] * 17, self.pg7)
3540 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3541 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3542 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3543 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
3544 self.assertEqual(rx[VXLAN].vni, 117)
3545 self.assertTrue(rx[VXLAN].flags.G)
3546 self.assertTrue(rx[VXLAN].flags.Instance)
3547 # redirect policy has been applied
3548 self.assertTrue(rx[VXLAN].gpflags.A)
3549 self.assertFalse(rx[VXLAN].gpflags.D)
3551 inner = rx[VXLAN].payload
3553 self.assertEqual(inner[Ether].src, routed_src_mac)
3554 self.assertEqual(inner[Ether].dst, sep4.mac)
3555 self.assertEqual(inner[IPv6].src, ep1.ip6.address)
3556 self.assertEqual(inner[IPv6].dst, ep3.ip6.address)
3558 rxs = self.send_and_expect(self.pg2, p6[1] * 17, sep3.itf)
3561 self.assertEqual(rx[Ether].src, routed_src_mac)
3562 self.assertEqual(rx[Ether].dst, sep3.mac)
3563 self.assertEqual(rx[IPv6].src, ep3.ip6.address)
3564 self.assertEqual(rx[IPv6].dst, ep1.ip6.address)
3567 # programme the unknown EP
3569 sep4.add_vpp_config()
3571 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep4.itf)
3574 self.assertEqual(rx[Ether].src, routed_src_mac)
3575 self.assertEqual(rx[Ether].dst, sep4.mac)
3576 self.assertEqual(rx[IPv6].src, ep1.ip6.address)
3577 self.assertEqual(rx[IPv6].dst, ep3.ip6.address)
3580 # and revert back to unprogrammed
3582 sep4.remove_vpp_config()
3584 rxs = self.send_and_expect(self.pg0, p6[0] * 17, self.pg7)
3587 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3588 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3589 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3590 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
3591 self.assertEqual(rx[VXLAN].vni, 117)
3592 self.assertTrue(rx[VXLAN].flags.G)
3593 self.assertTrue(rx[VXLAN].flags.Instance)
3594 # redirect policy has been applied
3595 self.assertTrue(rx[VXLAN].gpflags.A)
3596 self.assertFalse(rx[VXLAN].gpflags.D)
3598 inner = rx[VXLAN].payload
3600 self.assertEqual(inner[Ether].src, routed_src_mac)
3601 self.assertEqual(inner[Ether].dst, sep4.mac)
3602 self.assertEqual(inner[IPv6].src, ep1.ip6.address)
3603 self.assertEqual(inner[IPv6].dst, ep3.ip6.address)
3605 c1.remove_vpp_config()
3606 c2.remove_vpp_config()
3609 # test the symmetric hash mode
3611 c1 = VppGbpContract(
3612 self, 402, epg_220.sclass, epg_222.sclass, acl_index,
3613 [VppGbpContractRule(
3614 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3615 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3616 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3617 sep1.ip4, sep1.epg.rd),
3618 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3619 sep2.ip4, sep2.epg.rd)]),
3621 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3622 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3623 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3624 sep3.ip6, sep3.epg.rd),
3625 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3626 sep4.ip6, sep4.epg.rd)])],
3627 [ETH_P_IP, ETH_P_IPV6])
3630 c2 = VppGbpContract(
3631 self, 402, epg_222.sclass, epg_220.sclass, acl_index,
3632 [VppGbpContractRule(
3633 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3634 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3635 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3636 sep1.ip4, sep1.epg.rd),
3637 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3638 sep2.ip4, sep2.epg.rd)]),
3640 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3641 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3642 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3643 sep3.ip6, sep3.epg.rd),
3644 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3645 sep4.ip6, sep4.epg.rd)])],
3646 [ETH_P_IP, ETH_P_IPV6])
3650 # send again with the contract preset, now packets arrive
3651 # at SEP1 for both directions
3653 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3656 self.assertEqual(rx[Ether].src, routed_src_mac)
3657 self.assertEqual(rx[Ether].dst, sep1.mac)
3658 self.assertEqual(rx[IP].src, ep1.ip4.address)
3659 self.assertEqual(rx[IP].dst, ep3.ip4.address)
3661 rxs = self.send_and_expect(self.pg2, p4[1] * 17, sep1.itf)
3664 self.assertEqual(rx[Ether].src, routed_src_mac)
3665 self.assertEqual(rx[Ether].dst, sep1.mac)
3666 self.assertEqual(rx[IP].src, ep3.ip4.address)
3667 self.assertEqual(rx[IP].dst, ep1.ip4.address)
3670 # programme the unknown EP for the L3 tests
3672 sep4.add_vpp_config()
3675 # an L3 switch packet between local EPs in different EPGs
3676 # different dest ports on each so the are LB hashed differently
3678 p4 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3679 IP(src=ep1.ip4.address, dst=ep2.ip4.address) /
3680 UDP(sport=1234, dport=1234) /
3682 (Ether(src=ep2.mac, dst=str(self.router_mac)) /
3683 IP(src=ep2.ip4.address, dst=ep1.ip4.address) /
3684 UDP(sport=1234, dport=1234) /
3686 p6 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3687 IPv6(src=ep1.ip6.address, dst=ep2.ip6.address) /
3688 UDP(sport=1234, dport=1234) /
3690 (Ether(src=ep2.mac, dst=str(self.router_mac)) /
3691 IPv6(src=ep2.ip6.address, dst=ep1.ip6.address) /
3692 UDP(sport=1234, dport=1234) /
3695 c3 = VppGbpContract(
3696 self, 402, epg_220.sclass, epg_221.sclass, acl_index,
3697 [VppGbpContractRule(
3698 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3699 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3700 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3701 sep1.ip4, sep1.epg.rd),
3702 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3703 sep2.ip4, sep2.epg.rd)]),
3705 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3706 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3707 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3708 sep3.ip6, sep3.epg.rd),
3709 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3710 sep4.ip6, sep4.epg.rd)])],
3711 [ETH_P_IP, ETH_P_IPV6])
3714 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3717 self.assertEqual(rx[Ether].src, routed_src_mac)
3718 self.assertEqual(rx[Ether].dst, sep1.mac)
3719 self.assertEqual(rx[IP].src, ep1.ip4.address)
3720 self.assertEqual(rx[IP].dst, ep2.ip4.address)
3723 # learn a remote EP in EPG 221
3724 # packets coming from unknown remote EPs will be leant & redirected
3726 vx_tun_l3 = VppGbpVxlanTunnel(
3727 self, 444, rd1.rd_id,
3728 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
3730 vx_tun_l3.add_vpp_config()
3732 c4 = VppGbpContract(
3733 self, 402, epg_221.sclass, epg_220.sclass, acl_index,
3734 [VppGbpContractRule(
3735 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3736 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3737 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3738 sep1.ip4, sep1.epg.rd),
3739 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3740 sep2.ip4, sep2.epg.rd)]),
3742 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3743 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3744 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3745 sep3.ip6, sep3.epg.rd),
3746 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3747 sep4.ip6, sep4.epg.rd)])],
3748 [ETH_P_IP, ETH_P_IPV6])
3751 p = (Ether(src=self.pg7.remote_mac,
3752 dst=self.pg7.local_mac) /
3753 IP(src=self.pg7.remote_ip4,
3754 dst=self.pg7.local_ip4) /
3755 UDP(sport=1234, dport=48879) /
3756 VXLAN(vni=444, gpid=441, flags=0x88) /
3757 Ether(src="00:22:22:22:22:33", dst=str(self.router_mac)) /
3758 IP(src="10.0.0.88", dst=ep1.ip4.address) /
3759 UDP(sport=1234, dport=1234) /
3762 # unknown remote EP to local EP redirected
3763 rxs = self.send_and_expect(self.pg7, [p], sep1.itf)
3766 self.assertEqual(rx[Ether].src, routed_src_mac)
3767 self.assertEqual(rx[Ether].dst, sep1.mac)
3768 self.assertEqual(rx[IP].src, "10.0.0.88")
3769 self.assertEqual(rx[IP].dst, ep1.ip4.address)
3771 # endpoint learnt via the parent GBP-vxlan interface
3772 self.assertTrue(find_gbp_endpoint(self,
3773 vx_tun_l3._sw_if_index,
3776 p = (Ether(src=self.pg7.remote_mac,
3777 dst=self.pg7.local_mac) /
3778 IP(src=self.pg7.remote_ip4,
3779 dst=self.pg7.local_ip4) /
3780 UDP(sport=1234, dport=48879) /
3781 VXLAN(vni=444, gpid=441, flags=0x88) /
3782 Ether(src="00:22:22:22:22:33", dst=str(self.router_mac)) /
3783 IPv6(src="2001:10::88", dst=ep1.ip6.address) /
3784 UDP(sport=1234, dport=1234) /
3787 # unknown remote EP to local EP redirected (ipv6)
3788 rxs = self.send_and_expect(self.pg7, [p], sep3.itf)
3791 self.assertEqual(rx[Ether].src, routed_src_mac)
3792 self.assertEqual(rx[Ether].dst, sep3.mac)
3793 self.assertEqual(rx[IPv6].src, "2001:10::88")
3794 self.assertEqual(rx[IPv6].dst, ep1.ip6.address)
3796 # endpoint learnt via the parent GBP-vxlan interface
3797 self.assertTrue(find_gbp_endpoint(self,
3798 vx_tun_l3._sw_if_index,
3802 # L3 switch from local to remote EP
3804 p4 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3805 IP(src=ep1.ip4.address, dst="10.0.0.88") /
3806 UDP(sport=1234, dport=1234) /
3808 p6 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3809 IPv6(src=ep1.ip6.address, dst="2001:10::88") /
3810 UDP(sport=1234, dport=1234) /
3813 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3816 self.assertEqual(rx[Ether].src, routed_src_mac)
3817 self.assertEqual(rx[Ether].dst, sep1.mac)
3818 self.assertEqual(rx[IP].src, ep1.ip4.address)
3819 self.assertEqual(rx[IP].dst, "10.0.0.88")
3821 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep4.itf)
3824 self.assertEqual(rx[Ether].src, routed_src_mac)
3825 self.assertEqual(rx[Ether].dst, sep4.mac)
3826 self.assertEqual(rx[IPv6].src, ep1.ip6.address)
3827 self.assertEqual(rx[IPv6].dst, "2001:10::88")
3830 # test the dst-ip hash mode
3832 c5 = VppGbpContract(
3833 self, 402, epg_220.sclass, epg_221.sclass, acl_index,
3834 [VppGbpContractRule(
3835 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3836 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
3837 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3838 sep1.ip4, sep1.epg.rd),
3839 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3840 sep2.ip4, sep2.epg.rd)]),
3842 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3843 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
3844 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3845 sep3.ip6, sep3.epg.rd),
3846 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3847 sep4.ip6, sep4.epg.rd)])],
3848 [ETH_P_IP, ETH_P_IPV6])
3851 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3854 self.assertEqual(rx[Ether].src, routed_src_mac)
3855 self.assertEqual(rx[Ether].dst, sep1.mac)
3856 self.assertEqual(rx[IP].src, ep1.ip4.address)
3857 self.assertEqual(rx[IP].dst, "10.0.0.88")
3859 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep3.itf)
3862 self.assertEqual(rx[Ether].src, routed_src_mac)
3863 self.assertEqual(rx[Ether].dst, sep3.mac)
3864 self.assertEqual(rx[IPv6].src, ep1.ip6.address)
3865 self.assertEqual(rx[IPv6].dst, "2001:10::88")
3868 # a programmed remote SEP in EPG 320
3871 # gbp vxlan tunnel for the remote SEP
3872 vx_tun_l3_sep = VppGbpVxlanTunnel(
3873 self, 555, rd1.rd_id,
3874 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
3876 vx_tun_l3_sep.add_vpp_config()
3879 sep5 = VppGbpEndpoint(self, vx_tun_l3_sep,
3881 "12.0.0.10", "13.0.0.10",
3882 "4001:10::10", "5001:10::10",
3883 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
3885 self.pg7.remote_ip4,
3887 sep5.add_vpp_config()
3890 # local l3out redirect tests
3895 self.loop4.set_mac(self.router_mac)
3896 VppIpInterfaceBind(self, self.loop4, t4).add_vpp_config()
3897 VppIpInterfaceBind(self, self.loop4, t6).add_vpp_config()
3898 ebd = VppBridgeDomain(self, 100)
3899 ebd.add_vpp_config()
3900 gebd = VppGbpBridgeDomain(self, ebd, rd1, self.loop4, None, None)
3901 gebd.add_vpp_config()
3903 eepg = VppGbpEndpointGroup(self, 888, 765, rd1, gebd,
3907 VppGbpEndpointRetention(2))
3908 eepg.add_vpp_config()
3909 # add subnets to BVI
3910 VppIpInterfaceAddress(
3914 24).add_vpp_config()
3915 VppIpInterfaceAddress(
3919 64).add_vpp_config()
3920 # ... which are L3-out subnets
3921 VppGbpSubnet(self, rd1, "10.1.0.0", 24,
3922 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3923 sclass=765).add_vpp_config()
3924 VppGbpSubnet(self, rd1, "2001:10:1::128", 64,
3925 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3926 sclass=765).add_vpp_config()
3927 # external endpoints
3928 VppL2Vtr(self, self.vlan_100, L2_VTR_OP.L2_POP_1).add_vpp_config()
3929 eep1 = VppGbpEndpoint(self, self.vlan_100, eepg, None, "10.1.0.1",
3930 "11.1.0.1", "2001:10:1::1", "3001:10:1::1",
3931 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
3932 eep1.add_vpp_config()
3933 VppL2Vtr(self, self.vlan_101, L2_VTR_OP.L2_POP_1).add_vpp_config()
3934 eep2 = VppGbpEndpoint(self, self.vlan_101, eepg, None, "10.1.0.2",
3935 "11.1.0.2", "2001:10:1::2", "3001:10:1::2",
3936 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
3937 eep2.add_vpp_config()
3939 # external subnets reachable though eep1 and eep2 respectively
3940 VppIpRoute(self, "10.220.0.0", 24,
3941 [VppRoutePath(eep1.ip4.address, eep1.epg.bvi.sw_if_index)],
3942 table_id=t4.table_id).add_vpp_config()
3943 VppGbpSubnet(self, rd1, "10.220.0.0", 24,
3944 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3945 sclass=4220).add_vpp_config()
3946 VppIpRoute(self, "10:220::", 64,
3947 [VppRoutePath(eep1.ip6.address, eep1.epg.bvi.sw_if_index)],
3948 table_id=t6.table_id).add_vpp_config()
3949 VppGbpSubnet(self, rd1, "10:220::", 64,
3950 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3951 sclass=4220).add_vpp_config()
3952 VppIpRoute(self, "10.221.0.0", 24,
3953 [VppRoutePath(eep2.ip4.address, eep2.epg.bvi.sw_if_index)],
3954 table_id=t4.table_id).add_vpp_config()
3955 VppGbpSubnet(self, rd1, "10.221.0.0", 24,
3956 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3957 sclass=4221).add_vpp_config()
3958 VppIpRoute(self, "10:221::", 64,
3959 [VppRoutePath(eep2.ip6.address, eep2.epg.bvi.sw_if_index)],
3960 table_id=t6.table_id).add_vpp_config()
3961 VppGbpSubnet(self, rd1, "10:221::", 64,
3962 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3963 sclass=4221).add_vpp_config()
3966 # l3out redirect to remote (known, then unknown) SEP
3969 # packets from 1 external subnet to the other
3970 p = [(Ether(src=eep1.mac, dst=self.router_mac) /
3972 IP(src="10.220.0.17", dst="10.221.0.65") /
3973 UDP(sport=1234, dport=1234) /
3975 (Ether(src=eep1.mac, dst=self.router_mac) /
3977 IPv6(src="10:220::17", dst="10:221::65") /
3978 UDP(sport=1234, dport=1234) /
3981 # packets should be dropped in absence of contract
3982 self.send_and_assert_no_replies(self.pg0, p)
3984 # contract redirecting to sep5
3986 self, 402, 4220, 4221, acl_index,
3987 [VppGbpContractRule(
3988 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3989 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
3990 [VppGbpContractNextHop(sep5.vmac, sep5.epg.bd,
3991 sep5.ip4, sep5.epg.rd)]),
3993 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3994 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
3995 [VppGbpContractNextHop(sep5.vmac, sep5.epg.bd,
3996 sep5.ip6, sep5.epg.rd)])],
3997 [ETH_P_IP, ETH_P_IPV6]).add_vpp_config()
3999 rxs = self.send_and_expect(self.pg0, p, self.pg7)
4001 for rx, tx in zip(rxs, p):
4002 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4003 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4004 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4005 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4006 # this should use the programmed remote leaf TEP
4007 self.assertEqual(rx[VXLAN].vni, 555)
4008 self.assertEqual(rx[VXLAN].gpid, 4220)
4009 self.assertTrue(rx[VXLAN].flags.G)
4010 self.assertTrue(rx[VXLAN].flags.Instance)
4011 # redirect policy has been applied
4012 self.assertTrue(rx[VXLAN].gpflags.A)
4013 self.assertTrue(rx[VXLAN].gpflags.D)
4014 rxip = rx[VXLAN][Ether].payload
4015 txip = tx[Dot1Q].payload
4016 self.assertEqual(rxip.src, txip.src)
4017 self.assertEqual(rxip.dst, txip.dst)
4019 # remote SEP: it is now an unknown remote SEP and should go
4021 sep5.remove_vpp_config()
4023 rxs = self.send_and_expect(self.pg0, p, self.pg7)
4025 for rx, tx in zip(rxs, p):
4026 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4027 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4028 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4029 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4030 # this should use the spine proxy TEP
4031 self.assertEqual(rx[VXLAN].vni, epg_320.bd.uu_fwd.vni)
4032 self.assertEqual(rx[VXLAN].gpid, 4220)
4033 self.assertTrue(rx[VXLAN].flags.G)
4034 self.assertTrue(rx[VXLAN].flags.Instance)
4035 # redirect policy has been applied
4036 self.assertTrue(rx[VXLAN].gpflags.A)
4037 self.assertTrue(rx[VXLAN].gpflags.D)
4038 rxip = rx[VXLAN][Ether].payload
4039 txip = tx[Dot1Q].payload
4040 self.assertEqual(rxip.src, txip.src)
4041 self.assertEqual(rxip.dst, txip.dst)
4044 # l3out redirect to local SEP
4047 # change the contract between l3out to redirect to local SEPs
4048 # instead of remote SEP
4050 self, 402, 4220, 4221, acl_index,
4051 [VppGbpContractRule(
4052 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4053 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
4054 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
4055 sep1.ip4, sep1.epg.rd)]),
4057 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4058 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
4059 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
4060 sep1.ip6, sep1.epg.rd)])],
4061 [ETH_P_IP, ETH_P_IPV6]).add_vpp_config()
4063 rxs = self.send_and_expect(self.pg0, p, sep1.itf)
4064 for rx, tx in zip(rxs, p):
4065 self.assertEqual(rx[Ether].src, routed_src_mac)
4066 self.assertEqual(rx[Ether].dst, sep1.mac)
4067 rxip = rx[Ether].payload
4068 txip = tx[Ether].payload
4069 self.assertEqual(rxip.src, txip.src)
4070 self.assertEqual(rxip.dst, txip.dst)
4073 # redirect remote EP to remote (known then unknown) SEP
4076 # remote SEP known again
4077 sep5.add_vpp_config()
4079 # contract to redirect to learnt SEP
4081 self, 402, epg_221.sclass, epg_222.sclass, acl_index,
4082 [VppGbpContractRule(
4083 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4084 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
4085 [VppGbpContractNextHop(sep5.vmac, sep5.epg.bd,
4086 sep5.ip4, sep5.epg.rd)]),
4088 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4089 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
4090 [VppGbpContractNextHop(sep5.vmac, sep5.epg.bd,
4091 sep5.ip6, sep5.epg.rd)])],
4092 [ETH_P_IP, ETH_P_IPV6]).add_vpp_config()
4094 # packets from unknown EP 221 to known EP in EPG 222
4095 # should be redirected to known remote SEP
4096 base = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
4097 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
4098 UDP(sport=1234, dport=48879) /
4099 VXLAN(vni=444, gpid=441, flags=0x88) /
4100 Ether(src="00:22:22:22:22:44", dst=str(self.router_mac)))
4102 IP(src="10.0.1.100", dst=ep3.ip4.address) /
4103 UDP(sport=1234, dport=1234) /
4106 IPv6(src="2001:10::100", dst=ep3.ip6.address) /
4107 UDP(sport=1234, dport=1234) /
4110 # unknown remote EP to local EP redirected to known remote SEP
4111 rxs = self.send_and_expect(self.pg7, p, self.pg7)
4113 for rx, tx in zip(rxs, p):
4114 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4115 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4116 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4117 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4118 # this should use the programmed remote leaf TEP
4119 self.assertEqual(rx[VXLAN].vni, 555)
4120 self.assertEqual(rx[VXLAN].gpid, epg_221.sclass)
4121 self.assertTrue(rx[VXLAN].flags.G)
4122 self.assertTrue(rx[VXLAN].flags.Instance)
4123 # redirect policy has been applied
4124 self.assertTrue(rx[VXLAN].gpflags.A)
4125 self.assertFalse(rx[VXLAN].gpflags.D)
4126 rxip = rx[VXLAN][Ether].payload
4127 txip = tx[VXLAN][Ether].payload
4128 self.assertEqual(rxip.src, txip.src)
4129 self.assertEqual(rxip.dst, txip.dst)
4131 # endpoint learnt via the parent GBP-vxlan interface
4132 self.assertTrue(find_gbp_endpoint(self,
4133 vx_tun_l3._sw_if_index,
4135 self.assertTrue(find_gbp_endpoint(self,
4136 vx_tun_l3._sw_if_index,
4139 # remote SEP: it is now an unknown remote SEP and should go
4141 sep5.remove_vpp_config()
4143 # remote EP (coming from spine proxy) to local EP redirected to
4145 rxs = self.send_and_expect(self.pg7, p, self.pg7)
4147 for rx, tx in zip(rxs, p):
4148 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4149 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4150 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4151 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4152 # this should use the spine proxy TEP
4153 self.assertEqual(rx[VXLAN].vni, epg_320.bd.uu_fwd.vni)
4154 self.assertEqual(rx[VXLAN].gpid, epg_221.sclass)
4155 self.assertTrue(rx[VXLAN].flags.G)
4156 self.assertTrue(rx[VXLAN].flags.Instance)
4157 # redirect policy has been applied
4158 self.assertTrue(rx[VXLAN].gpflags.A)
4159 self.assertFalse(rx[VXLAN].gpflags.D)
4160 rxip = rx[VXLAN][Ether].payload
4161 txip = tx[VXLAN][Ether].payload
4162 self.assertEqual(rxip.src, txip.src)
4163 self.assertEqual(rxip.dst, txip.dst)
4168 self.pg7.unconfig_ip4()
4170 def test_gbp_l3_out(self):
4173 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
4174 self.vapi.cli("set logging class gbp level debug")
4176 routed_dst_mac = "00:0c:0c:0c:0c:0c"
4177 routed_src_mac = "00:22:bd:f8:19:ff"
4182 t4 = VppIpTable(self, 1)
4184 t6 = VppIpTable(self, 1, True)
4187 rd1 = VppGbpRouteDomain(self, 2, 55, t4, t6)
4188 rd1.add_vpp_config()
4190 self.loop0.set_mac(self.router_mac)
4193 # Bind the BVI to the RD
4195 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
4196 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
4199 # Pg7 hosts a BD's BUM
4200 # Pg1 some other l3 interface
4202 self.pg7.config_ip4()
4203 self.pg7.resolve_arp()
4206 # a multicast vxlan-gbp tunnel for broadcast in the BD
4208 tun_bm = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
4211 tun_bm.add_vpp_config()
4214 # a GBP external bridge domains for the EPs
4216 bd1 = VppBridgeDomain(self, 1)
4217 bd1.add_vpp_config()
4218 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0, None, tun_bm)
4219 gbd1.add_vpp_config()
4222 # The Endpoint-groups in which the external endpoints exist
4224 epg_220 = VppGbpEndpointGroup(self, 220, 113, rd1, gbd1,
4228 VppGbpEndpointRetention(2))
4229 epg_220.add_vpp_config()
4231 # the BVIs have the subnets applied ...
4232 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 24)
4233 ip4_addr.add_vpp_config()
4234 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 64)
4235 ip6_addr.add_vpp_config()
4237 # ... which are L3-out subnets
4238 l3o_1 = VppGbpSubnet(
4239 self, rd1, "10.0.0.0", 24,
4240 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
4242 l3o_1.add_vpp_config()
4245 # an external interface attached to the outside world and the
4248 VppL2Vtr(self, self.vlan_100, L2_VTR_OP.L2_POP_1).add_vpp_config()
4249 VppL2Vtr(self, self.vlan_101, L2_VTR_OP.L2_POP_1).add_vpp_config()
4250 vlan_144 = VppDot1QSubint(self, self.pg0, 144)
4252 # vlan_102 is not poped
4255 # an unicast vxlan-gbp for inter-RD traffic
4257 vx_tun_l3 = VppGbpVxlanTunnel(
4258 self, 444, rd1.rd_id,
4259 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
4261 vx_tun_l3.add_vpp_config()
4264 # External Endpoints
4266 eep1 = VppGbpEndpoint(self, self.vlan_100,
4268 "10.0.0.1", "11.0.0.1",
4269 "2001:10::1", "3001::1",
4270 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
4271 eep1.add_vpp_config()
4272 eep2 = VppGbpEndpoint(self, self.vlan_101,
4274 "10.0.0.2", "11.0.0.2",
4275 "2001:10::2", "3001::2",
4276 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
4277 eep2.add_vpp_config()
4278 eep3 = VppGbpEndpoint(self, self.vlan_102,
4280 "10.0.0.3", "11.0.0.3",
4281 "2001:10::3", "3001::3",
4282 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
4283 eep3.add_vpp_config()
4286 # A remote external endpoint
4288 rep = VppGbpEndpoint(self, vx_tun_l3,
4290 "10.0.0.101", "11.0.0.101",
4291 "2001:10::101", "3001::101",
4292 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
4294 self.pg7.remote_ip4,
4296 rep.add_vpp_config()
4299 # EP1 impersonating EP3 is dropped
4301 p = (Ether(src=eep1.mac, dst="ff:ff:ff:ff:ff:ff") /
4304 psrc="10.0.0.3", pdst="10.0.0.128",
4305 hwsrc=eep1.mac, hwdst="ff:ff:ff:ff:ff:ff"))
4306 self.send_and_assert_no_replies(self.pg0, p)
4309 # ARP packet from External EPs are accepted and replied to
4311 p_arp = (Ether(src=eep1.mac, dst="ff:ff:ff:ff:ff:ff") /
4314 psrc=eep1.ip4.address, pdst="10.0.0.128",
4315 hwsrc=eep1.mac, hwdst="ff:ff:ff:ff:ff:ff"))
4316 rxs = self.send_and_expect(self.pg0, p_arp * 1, self.pg0)
4319 # ARP packet from host in remote subnet are accepted and replied to
4321 p_arp = (Ether(src=eep3.mac, dst="ff:ff:ff:ff:ff:ff") /
4324 psrc=eep3.ip4.address, pdst="10.0.0.128",
4325 hwsrc=eep3.mac, hwdst="ff:ff:ff:ff:ff:ff"))
4326 rxs = self.send_and_expect(self.pg0, p_arp * 1, self.pg0)
4329 # packets destined to unknown addresses in the BVI's subnet
4332 p4 = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
4334 IP(src="10.0.0.1", dst="10.0.0.88") /
4335 UDP(sport=1234, dport=1234) /
4337 p6 = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
4339 IPv6(src="2001:10::1", dst="2001:10::88") /
4340 UDP(sport=1234, dport=1234) /
4343 rxs = self.send_and_expect(self.pg0, p4 * 1, self.pg7)
4346 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4347 # self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4348 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4349 self.assertEqual(rx[IP].dst, "239.1.1.1")
4350 self.assertEqual(rx[VXLAN].vni, 88)
4351 self.assertTrue(rx[VXLAN].flags.G)
4352 self.assertTrue(rx[VXLAN].flags.Instance)
4353 # policy was applied to the original IP packet
4354 self.assertEqual(rx[VXLAN].gpid, 113)
4355 self.assertTrue(rx[VXLAN].gpflags.A)
4356 self.assertFalse(rx[VXLAN].gpflags.D)
4358 inner = rx[VXLAN].payload
4360 self.assertTrue(inner.haslayer(ARP))
4363 # remote to external
4365 p = (Ether(src=self.pg7.remote_mac,
4366 dst=self.pg7.local_mac) /
4367 IP(src=self.pg7.remote_ip4,
4368 dst=self.pg7.local_ip4) /
4369 UDP(sport=1234, dport=48879) /
4370 VXLAN(vni=444, gpid=113, flags=0x88) /
4371 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
4372 IP(src="10.0.0.101", dst="10.0.0.1") /
4373 UDP(sport=1234, dport=1234) /
4376 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
4379 # local EP pings router
4381 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
4383 IP(src=eep1.ip4.address, dst="10.0.0.128") /
4384 ICMP(type='echo-request'))
4386 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
4389 self.assertEqual(rx[Ether].src, str(self.router_mac))
4390 self.assertEqual(rx[Ether].dst, eep1.mac)
4391 self.assertEqual(rx[Dot1Q].vlan, 100)
4394 # local EP pings other local EP
4396 p = (Ether(src=eep1.mac, dst=eep2.mac) /
4398 IP(src=eep1.ip4.address, dst=eep2.ip4.address) /
4399 ICMP(type='echo-request'))
4401 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
4404 self.assertEqual(rx[Ether].src, eep1.mac)
4405 self.assertEqual(rx[Ether].dst, eep2.mac)
4406 self.assertEqual(rx[Dot1Q].vlan, 101)
4409 # local EP pings router w/o vlan tag poped
4411 p = (Ether(src=eep3.mac, dst=str(self.router_mac)) /
4413 IP(src=eep3.ip4.address, dst="10.0.0.128") /
4414 ICMP(type='echo-request'))
4416 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
4419 self.assertEqual(rx[Ether].src, str(self.router_mac))
4420 self.assertEqual(rx[Ether].dst, self.vlan_102.remote_mac)
4423 # A ip4 subnet reachable through the external EP1
4425 ip_220 = VppIpRoute(self, "10.220.0.0", 24,
4426 [VppRoutePath(eep1.ip4.address,
4427 eep1.epg.bvi.sw_if_index)],
4428 table_id=t4.table_id)
4429 ip_220.add_vpp_config()
4431 l3o_220 = VppGbpSubnet(
4432 self, rd1, "10.220.0.0", 24,
4433 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
4435 l3o_220.add_vpp_config()
4438 # An ip6 subnet reachable through the external EP1
4440 ip6_220 = VppIpRoute(self, "10:220::", 64,
4441 [VppRoutePath(eep1.ip6.address,
4442 eep1.epg.bvi.sw_if_index)],
4443 table_id=t6.table_id)
4444 ip6_220.add_vpp_config()
4446 l3o6_220 = VppGbpSubnet(
4447 self, rd1, "10:220::", 64,
4448 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
4450 l3o6_220.add_vpp_config()
4453 # A subnet reachable through the external EP2
4455 ip_221 = VppIpRoute(self, "10.221.0.0", 24,
4456 [VppRoutePath(eep2.ip4.address,
4457 eep2.epg.bvi.sw_if_index)],
4458 table_id=t4.table_id)
4459 ip_221.add_vpp_config()
4461 l3o_221 = VppGbpSubnet(
4462 self, rd1, "10.221.0.0", 24,
4463 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
4465 l3o_221.add_vpp_config()
4468 # ping between hosts in remote subnets
4469 # dropped without a contract
4471 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
4473 IP(src="10.220.0.1", dst="10.221.0.1") /
4474 ICMP(type='echo-request'))
4476 self.send_and_assert_no_replies(self.pg0, p * 1)
4479 # contract for the external nets to communicate
4481 acl = VppGbpAcl(self)
4482 rule4 = acl.create_rule(permit_deny=1, proto=17)
4483 rule6 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
4484 acl_index = acl.add_vpp_config([rule4, rule6])
4487 # A contract with the wrong scope is not matched
4489 c_44 = VppGbpContract(
4490 self, 44, 4220, 4221, acl_index,
4491 [VppGbpContractRule(
4492 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4495 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4497 [ETH_P_IP, ETH_P_IPV6])
4498 c_44.add_vpp_config()
4499 self.send_and_assert_no_replies(self.pg0, p * 1)
4501 c1 = VppGbpContract(
4502 self, 55, 4220, 4221, acl_index,
4503 [VppGbpContractRule(
4504 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4505 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4508 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4509 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4511 [ETH_P_IP, ETH_P_IPV6])
4515 # Contracts allowing ext-net 200 to talk with external EPs
4517 c2 = VppGbpContract(
4518 self, 55, 4220, 113, acl_index,
4519 [VppGbpContractRule(
4520 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4521 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4524 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4525 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4527 [ETH_P_IP, ETH_P_IPV6])
4529 c3 = VppGbpContract(
4530 self, 55, 113, 4220, acl_index,
4531 [VppGbpContractRule(
4532 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4533 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4536 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4537 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4539 [ETH_P_IP, ETH_P_IPV6])
4543 # ping between hosts in remote subnets
4545 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
4547 IP(src="10.220.0.1", dst="10.221.0.1") /
4548 UDP(sport=1234, dport=1234) /
4551 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
4554 self.assertEqual(rx[Ether].src, str(self.router_mac))
4555 self.assertEqual(rx[Ether].dst, eep2.mac)
4556 self.assertEqual(rx[Dot1Q].vlan, 101)
4558 # we did not learn these external hosts
4559 self.assertFalse(find_gbp_endpoint(self, ip="10.220.0.1"))
4560 self.assertFalse(find_gbp_endpoint(self, ip="10.221.0.1"))
4563 # from remote external EP to local external EP
4565 p = (Ether(src=self.pg7.remote_mac,
4566 dst=self.pg7.local_mac) /
4567 IP(src=self.pg7.remote_ip4,
4568 dst=self.pg7.local_ip4) /
4569 UDP(sport=1234, dport=48879) /
4570 VXLAN(vni=444, gpid=113, flags=0x88) /
4571 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
4572 IP(src="10.0.0.101", dst="10.220.0.1") /
4573 UDP(sport=1234, dport=1234) /
4576 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
4579 # ping from an external host to the remote external EP
4581 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
4583 IP(src="10.220.0.1", dst=rep.ip4.address) /
4584 UDP(sport=1234, dport=1234) /
4587 rxs = self.send_and_expect(self.pg0, p * 1, self.pg7)
4590 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4591 # self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4592 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4593 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4594 self.assertEqual(rx[VXLAN].vni, 444)
4595 self.assertTrue(rx[VXLAN].flags.G)
4596 self.assertTrue(rx[VXLAN].flags.Instance)
4597 # the sclass of the ext-net the packet came from
4598 self.assertEqual(rx[VXLAN].gpid, 4220)
4599 # policy was applied to the original IP packet
4600 self.assertTrue(rx[VXLAN].gpflags.A)
4601 # since it's an external host the reciever should not learn it
4602 self.assertTrue(rx[VXLAN].gpflags.D)
4603 inner = rx[VXLAN].payload
4604 self.assertEqual(inner[IP].src, "10.220.0.1")
4605 self.assertEqual(inner[IP].dst, rep.ip4.address)
4608 # An external subnet reachable via the remote external EP
4612 # first the VXLAN-GBP tunnel over which it is reached
4614 vx_tun_r1 = VppVxlanGbpTunnel(
4615 self, self.pg7.local_ip4,
4616 self.pg7.remote_ip4, 445,
4617 mode=(VppEnum.vl_api_vxlan_gbp_api_tunnel_mode_t.
4618 VXLAN_GBP_API_TUNNEL_MODE_L3))
4619 vx_tun_r1.add_vpp_config()
4620 VppIpInterfaceBind(self, vx_tun_r1, t4).add_vpp_config()
4622 self.logger.info(self.vapi.cli("sh vxlan-gbp tunnel"))
4625 # then the special adj to resolve through on that tunnel
4627 n1 = VppNeighbor(self,
4628 vx_tun_r1.sw_if_index,
4629 "00:0c:0c:0c:0c:0c",
4630 self.pg7.remote_ip4)
4634 # the route via the adj above
4636 ip_222 = VppIpRoute(self, "10.222.0.0", 24,
4637 [VppRoutePath(self.pg7.remote_ip4,
4638 vx_tun_r1.sw_if_index)],
4639 table_id=t4.table_id)
4640 ip_222.add_vpp_config()
4642 l3o_222 = VppGbpSubnet(
4643 self, rd1, "10.222.0.0", 24,
4644 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
4646 l3o_222.add_vpp_config()
4649 # ping between hosts in local and remote external subnets
4650 # dropped without a contract
4652 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
4654 IP(src="10.220.0.1", dst="10.222.0.1") /
4655 UDP(sport=1234, dport=1234) /
4658 rxs = self.send_and_assert_no_replies(self.pg0, p * 1)
4661 # Add contracts ext-nets for 220 -> 222
4663 c4 = VppGbpContract(
4664 self, 55, 4220, 4222, acl_index,
4665 [VppGbpContractRule(
4666 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4667 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4670 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4671 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4673 [ETH_P_IP, ETH_P_IPV6])
4677 # ping from host in local to remote external subnets
4679 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
4681 IP(src="10.220.0.1", dst="10.222.0.1") /
4682 UDP(sport=1234, dport=1234) /
4685 rxs = self.send_and_expect(self.pg0, p * 3, self.pg7)
4688 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4689 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4690 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4691 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4692 self.assertEqual(rx[VXLAN].vni, 445)
4693 self.assertTrue(rx[VXLAN].flags.G)
4694 self.assertTrue(rx[VXLAN].flags.Instance)
4695 # the sclass of the ext-net the packet came from
4696 self.assertEqual(rx[VXLAN].gpid, 4220)
4697 # policy was applied to the original IP packet
4698 self.assertTrue(rx[VXLAN].gpflags.A)
4699 # since it's an external host the reciever should not learn it
4700 self.assertTrue(rx[VXLAN].gpflags.D)
4701 inner = rx[VXLAN].payload
4702 self.assertEqual(inner[Ether].dst, "00:0c:0c:0c:0c:0c")
4703 self.assertEqual(inner[IP].src, "10.220.0.1")
4704 self.assertEqual(inner[IP].dst, "10.222.0.1")
4707 # make the external subnet ECMP
4709 vx_tun_r2 = VppVxlanGbpTunnel(
4710 self, self.pg7.local_ip4,
4711 self.pg7.remote_ip4, 446,
4712 mode=(VppEnum.vl_api_vxlan_gbp_api_tunnel_mode_t.
4713 VXLAN_GBP_API_TUNNEL_MODE_L3))
4714 vx_tun_r2.add_vpp_config()
4715 VppIpInterfaceBind(self, vx_tun_r2, t4).add_vpp_config()
4717 self.logger.info(self.vapi.cli("sh vxlan-gbp tunnel"))
4719 n2 = VppNeighbor(self,
4720 vx_tun_r2.sw_if_index,
4721 "00:0c:0c:0c:0c:0c",
4722 self.pg7.remote_ip4)
4725 ip_222.modify([VppRoutePath(self.pg7.remote_ip4,
4726 vx_tun_r1.sw_if_index),
4727 VppRoutePath(self.pg7.remote_ip4,
4728 vx_tun_r2.sw_if_index)])
4731 # now expect load-balance
4733 p = [(Ether(src=eep1.mac, dst=str(self.router_mac)) /
4735 IP(src="10.220.0.1", dst="10.222.0.1") /
4736 UDP(sport=1234, dport=1234) /
4738 (Ether(src=eep1.mac, dst=str(self.router_mac)) /
4740 IP(src="10.220.0.1", dst="10.222.0.1") /
4741 UDP(sport=1222, dport=1235) /
4744 rxs = self.send_and_expect(self.pg0, p, self.pg7)
4746 self.assertEqual(rxs[0][VXLAN].vni, 445)
4747 self.assertEqual(rxs[1][VXLAN].vni, 446)
4750 # Same LB test for v6
4752 n3 = VppNeighbor(self,
4753 vx_tun_r1.sw_if_index,
4754 "00:0c:0c:0c:0c:0c",
4755 self.pg7.remote_ip6)
4757 n4 = VppNeighbor(self,
4758 vx_tun_r2.sw_if_index,
4759 "00:0c:0c:0c:0c:0c",
4760 self.pg7.remote_ip6)
4763 ip_222_6 = VppIpRoute(self, "10:222::", 64,
4764 [VppRoutePath(self.pg7.remote_ip6,
4765 vx_tun_r1.sw_if_index),
4766 VppRoutePath(self.pg7.remote_ip6,
4767 vx_tun_r2.sw_if_index)],
4768 table_id=t6.table_id)
4769 ip_222_6.add_vpp_config()
4771 l3o_222_6 = VppGbpSubnet(
4772 self, rd1, "10:222::", 64,
4773 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
4775 l3o_222_6.add_vpp_config()
4777 p = [(Ether(src=eep1.mac, dst=str(self.router_mac)) /
4779 IPv6(src="10:220::1", dst="10:222::1") /
4780 UDP(sport=1234, dport=1234) /
4782 (Ether(src=eep1.mac, dst=str(self.router_mac)) /
4784 IPv6(src="10:220::1", dst="10:222::1") /
4785 UDP(sport=7777, dport=8881) /
4788 self.logger.info(self.vapi.cli("sh ip6 fib 10:222::1"))
4789 rxs = self.send_and_expect(self.pg0, p, self.pg7)
4791 self.assertEqual(rxs[0][VXLAN].vni, 445)
4792 self.assertEqual(rxs[1][VXLAN].vni, 446)
4795 # ping from host in remote to local external subnets
4796 # there's no contract for this, but the A bit is set.
4798 p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
4799 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
4800 UDP(sport=1234, dport=48879) /
4801 VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
4802 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
4803 IP(src="10.222.0.1", dst="10.220.0.1") /
4804 UDP(sport=1234, dport=1234) /
4807 rxs = self.send_and_expect(self.pg7, p * 3, self.pg0)
4808 self.assertFalse(find_gbp_endpoint(self, ip="10.222.0.1"))
4811 # ping from host in remote to remote external subnets
4812 # this is dropped by reflection check.
4814 p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
4815 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
4816 UDP(sport=1234, dport=48879) /
4817 VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
4818 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
4819 IP(src="10.222.0.1", dst="10.222.0.2") /
4820 UDP(sport=1234, dport=1234) /
4823 rxs = self.send_and_assert_no_replies(self.pg7, p * 3)
4825 p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
4826 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
4827 UDP(sport=1234, dport=48879) /
4828 VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
4829 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
4830 IPv6(src="10:222::1", dst="10:222::2") /
4831 UDP(sport=1234, dport=1234) /
4834 rxs = self.send_and_assert_no_replies(self.pg7, p * 3)
4839 lep1 = VppGbpEndpoint(self, vlan_144,
4841 "10.0.0.44", "11.0.0.44",
4842 "2001:10::44", "3001::44")
4843 lep1.add_vpp_config()
4846 # local EP to local ip4 external subnet
4848 p = (Ether(src=lep1.mac, dst=str(self.router_mac)) /
4850 IP(src=lep1.ip4.address, dst="10.220.0.1") /
4851 UDP(sport=1234, dport=1234) /
4854 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
4857 self.assertEqual(rx[Ether].src, str(self.router_mac))
4858 self.assertEqual(rx[Ether].dst, eep1.mac)
4859 self.assertEqual(rx[Dot1Q].vlan, 100)
4862 # local EP to local ip6 external subnet
4864 p = (Ether(src=lep1.mac, dst=str(self.router_mac)) /
4866 IPv6(src=lep1.ip6.address, dst="10:220::1") /
4867 UDP(sport=1234, dport=1234) /
4870 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
4873 self.assertEqual(rx[Ether].src, str(self.router_mac))
4874 self.assertEqual(rx[Ether].dst, eep1.mac)
4875 self.assertEqual(rx[Dot1Q].vlan, 100)
4878 # ip4 and ip6 subnets that load-balance
4880 ip_20 = VppIpRoute(self, "10.20.0.0", 24,
4881 [VppRoutePath(eep1.ip4.address,
4882 eep1.epg.bvi.sw_if_index),
4883 VppRoutePath(eep2.ip4.address,
4884 eep2.epg.bvi.sw_if_index)],
4885 table_id=t4.table_id)
4886 ip_20.add_vpp_config()
4888 l3o_20 = VppGbpSubnet(
4889 self, rd1, "10.20.0.0", 24,
4890 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
4892 l3o_20.add_vpp_config()
4894 ip6_20 = VppIpRoute(self, "10:20::", 64,
4895 [VppRoutePath(eep1.ip6.address,
4896 eep1.epg.bvi.sw_if_index),
4897 VppRoutePath(eep2.ip6.address,
4898 eep2.epg.bvi.sw_if_index)],
4899 table_id=t6.table_id)
4900 ip6_20.add_vpp_config()
4902 l3o6_20 = VppGbpSubnet(
4903 self, rd1, "10:20::", 64,
4904 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
4906 l3o6_20.add_vpp_config()
4908 self.logger.info(self.vapi.cli("sh ip fib 10.20.0.1"))
4909 self.logger.info(self.vapi.cli("sh ip6 fib 10:20::1"))
4911 # two ip6 packets whose port are chosen so they load-balance
4912 p = [(Ether(src=lep1.mac, dst=str(self.router_mac)) /
4914 IPv6(src=lep1.ip6.address, dst="10:20::1") /
4915 UDP(sport=1234, dport=1234) /
4917 (Ether(src=lep1.mac, dst=str(self.router_mac)) /
4919 IPv6(src=lep1.ip6.address, dst="10:20::1") /
4920 UDP(sport=124, dport=1230) /
4923 rxs = self.send_and_expect(self.pg0, p, self.pg0, 2)
4925 self.assertEqual(rxs[0][Dot1Q].vlan, 101)
4926 self.assertEqual(rxs[1][Dot1Q].vlan, 100)
4928 # two ip4 packets whose port are chosen so they load-balance
4929 p = [(Ether(src=lep1.mac, dst=str(self.router_mac)) /
4931 IP(src=lep1.ip4.address, dst="10.20.0.1") /
4932 UDP(sport=1235, dport=1235) /
4934 (Ether(src=lep1.mac, dst=str(self.router_mac)) /
4936 IP(src=lep1.ip4.address, dst="10.20.0.1") /
4937 UDP(sport=124, dport=1230) /
4940 rxs = self.send_and_expect(self.pg0, p, self.pg0, 2)
4942 self.assertEqual(rxs[0][Dot1Q].vlan, 101)
4943 self.assertEqual(rxs[1][Dot1Q].vlan, 100)
4948 ip_222.remove_vpp_config()
4949 self.pg7.unconfig_ip4()
4950 self.vlan_101.set_vtr(L2_VTR_OP.L2_DISABLED)
4951 self.vlan_100.set_vtr(L2_VTR_OP.L2_DISABLED)
4953 def test_gbp_anon_l3_out(self):
4954 """ GBP Anonymous L3 Out """
4956 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
4957 self.vapi.cli("set logging class gbp level debug")
4959 routed_dst_mac = "00:0c:0c:0c:0c:0c"
4960 routed_src_mac = "00:22:bd:f8:19:ff"
4965 t4 = VppIpTable(self, 1)
4967 t6 = VppIpTable(self, 1, True)
4970 rd1 = VppGbpRouteDomain(self, 2, 55, t4, t6)
4971 rd1.add_vpp_config()
4973 self.loop0.set_mac(self.router_mac)
4976 # Bind the BVI to the RD
4978 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
4979 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
4982 # Pg7 hosts a BD's BUM
4983 # Pg1 some other l3 interface
4985 self.pg7.config_ip4()
4986 self.pg7.resolve_arp()
4989 # a GBP external bridge domains for the EPs
4991 bd1 = VppBridgeDomain(self, 1)
4992 bd1.add_vpp_config()
4993 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0, None, None)
4994 gbd1.add_vpp_config()
4997 # The Endpoint-groups in which the external endpoints exist
4999 epg_220 = VppGbpEndpointGroup(self, 220, 113, rd1, gbd1,
5003 VppGbpEndpointRetention(2))
5004 epg_220.add_vpp_config()
5006 # the BVIs have the subnet applied ...
5007 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 24)
5008 ip4_addr.add_vpp_config()
5010 # ... which is an Anonymous L3-out subnets
5011 l3o_1 = VppGbpSubnet(
5012 self, rd1, "10.0.0.0", 24,
5013 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_ANON_L3_OUT,
5015 l3o_1.add_vpp_config()
5018 # an external interface attached to the outside world and the
5021 VppL2Vtr(self, self.vlan_100, L2_VTR_OP.L2_POP_1).add_vpp_config()
5022 VppL2Vtr(self, self.vlan_101, L2_VTR_OP.L2_POP_1).add_vpp_config()
5025 # vlan_100 and vlan_101 are anonymous l3-out interfaces
5027 ext_itf = VppGbpExtItf(self, self.vlan_100, bd1, rd1, anon=True)
5028 ext_itf.add_vpp_config()
5029 ext_itf = VppGbpExtItf(self, self.vlan_101, bd1, rd1, anon=True)
5030 ext_itf.add_vpp_config()
5033 # an unicast vxlan-gbp for inter-RD traffic
5035 vx_tun_l3 = VppGbpVxlanTunnel(
5036 self, 444, rd1.rd_id,
5037 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
5039 vx_tun_l3.add_vpp_config()
5042 # A remote external endpoint
5044 rep = VppGbpEndpoint(self, vx_tun_l3,
5046 "10.0.0.201", "11.0.0.201",
5047 "2001:10::201", "3001::101",
5048 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
5050 self.pg7.remote_ip4,
5052 rep.add_vpp_config()
5055 # ARP packet from host in external subnet are accepted, flooded and
5056 # replied to. We expect 2 packets:
5057 # - APR request flooded over the other vlan subif
5058 # - ARP reply from BVI
5060 p_arp = (Ether(src=self.vlan_100.remote_mac,
5061 dst="ff:ff:ff:ff:ff:ff") /
5066 hwsrc=self.vlan_100.remote_mac,
5067 hwdst="ff:ff:ff:ff:ff:ff"))
5068 rxs = self.send_and_expect(self.pg0, p_arp * 1, self.pg0, n_rx=2)
5070 p_arp = (Ether(src=self.vlan_101.remote_mac,
5071 dst="ff:ff:ff:ff:ff:ff") /
5076 hwsrc=self.vlan_101.remote_mac,
5077 hwdst="ff:ff:ff:ff:ff:ff"))
5078 rxs = self.send_and_expect(self.pg0, p_arp * 1, self.pg0, n_rx=2)
5081 # remote to external
5083 p = (Ether(src=self.pg7.remote_mac,
5084 dst=self.pg7.local_mac) /
5085 IP(src=self.pg7.remote_ip4,
5086 dst=self.pg7.local_ip4) /
5087 UDP(sport=1234, dport=48879) /
5088 VXLAN(vni=vx_tun_l3.vni, gpid=epg_220.sclass, flags=0x88) /
5089 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
5090 IP(src=str(rep.ip4), dst="10.0.0.100") /
5091 UDP(sport=1234, dport=1234) /
5093 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
5096 # local EP pings router
5098 p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
5100 IP(src="10.0.0.100", dst="10.0.0.128") /
5101 ICMP(type='echo-request'))
5102 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
5105 self.assertEqual(rx[Ether].src, str(self.router_mac))
5106 self.assertEqual(rx[Ether].dst, self.vlan_100.remote_mac)
5107 self.assertEqual(rx[Dot1Q].vlan, 100)
5110 # local EP pings other local EP
5112 p = (Ether(src=self.vlan_100.remote_mac,
5113 dst=self.vlan_101.remote_mac) /
5115 IP(src="10.0.0.100", dst="10.0.0.101") /
5116 ICMP(type='echo-request'))
5117 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
5120 self.assertEqual(rx[Ether].src, self.vlan_100.remote_mac)
5121 self.assertEqual(rx[Ether].dst, self.vlan_101.remote_mac)
5122 self.assertEqual(rx[Dot1Q].vlan, 101)
5125 # A subnet reachable through an external router on vlan 100
5127 ip_220 = VppIpRoute(self, "10.220.0.0", 24,
5128 [VppRoutePath("10.0.0.100",
5129 epg_220.bvi.sw_if_index)],
5130 table_id=t4.table_id)
5131 ip_220.add_vpp_config()
5133 l3o_220 = VppGbpSubnet(
5134 self, rd1, "10.220.0.0", 24,
5135 # note: this a "regular" L3 out subnet (not connected)
5136 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
5138 l3o_220.add_vpp_config()
5141 # A subnet reachable through an external router on vlan 101
5143 ip_221 = VppIpRoute(self, "10.221.0.0", 24,
5144 [VppRoutePath("10.0.0.101",
5145 epg_220.bvi.sw_if_index)],
5146 table_id=t4.table_id)
5147 ip_221.add_vpp_config()
5149 l3o_221 = VppGbpSubnet(
5150 self, rd1, "10.221.0.0", 24,
5151 # note: this a "regular" L3 out subnet (not connected)
5152 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
5154 l3o_221.add_vpp_config()
5157 # ping between hosts in remote subnets
5158 # dropped without a contract
5160 p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
5162 IP(src="10.220.0.1", dst="10.221.0.1") /
5163 ICMP(type='echo-request'))
5165 rxs = self.send_and_assert_no_replies(self.pg0, p * 1)
5168 # contract for the external nets to communicate
5170 acl = VppGbpAcl(self)
5171 rule4 = acl.create_rule(permit_deny=1, proto=17)
5172 rule6 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
5173 acl_index = acl.add_vpp_config([rule4, rule6])
5175 c1 = VppGbpContract(
5176 self, 55, 4220, 4221, acl_index,
5177 [VppGbpContractRule(
5178 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5179 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5182 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5183 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5185 [ETH_P_IP, ETH_P_IPV6])
5189 # Contracts allowing ext-net 200 to talk with external EPs
5191 c2 = VppGbpContract(
5192 self, 55, 4220, 113, acl_index,
5193 [VppGbpContractRule(
5194 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5195 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5198 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5199 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5201 [ETH_P_IP, ETH_P_IPV6])
5203 c3 = VppGbpContract(
5204 self, 55, 113, 4220, acl_index,
5205 [VppGbpContractRule(
5206 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5207 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5210 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5211 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5213 [ETH_P_IP, ETH_P_IPV6])
5217 # ping between hosts in remote subnets
5219 p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
5221 IP(src="10.220.0.1", dst="10.221.0.1") /
5222 UDP(sport=1234, dport=1234) /
5225 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
5228 self.assertEqual(rx[Ether].src, str(self.router_mac))
5229 self.assertEqual(rx[Ether].dst, self.vlan_101.remote_mac)
5230 self.assertEqual(rx[Dot1Q].vlan, 101)
5232 # we did not learn these external hosts
5233 self.assertFalse(find_gbp_endpoint(self, ip="10.220.0.1"))
5234 self.assertFalse(find_gbp_endpoint(self, ip="10.221.0.1"))
5237 # from remote external EP to local external EP
5239 p = (Ether(src=self.pg7.remote_mac,
5240 dst=self.pg7.local_mac) /
5241 IP(src=self.pg7.remote_ip4,
5242 dst=self.pg7.local_ip4) /
5243 UDP(sport=1234, dport=48879) /
5244 VXLAN(vni=444, gpid=113, flags=0x88) /
5245 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
5246 IP(src=rep.ip4.address, dst="10.220.0.1") /
5247 UDP(sport=1234, dport=1234) /
5250 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
5253 # ping from an external host to the remote external EP
5255 p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
5257 IP(src="10.220.0.1", dst=rep.ip4.address) /
5258 UDP(sport=1234, dport=1234) /
5261 rxs = self.send_and_expect(self.pg0, p * 1, self.pg7)
5264 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
5265 # self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
5266 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
5267 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
5268 self.assertEqual(rx[VXLAN].vni, 444)
5269 self.assertTrue(rx[VXLAN].flags.G)
5270 self.assertTrue(rx[VXLAN].flags.Instance)
5271 # the sclass of the ext-net the packet came from
5272 self.assertEqual(rx[VXLAN].gpid, 4220)
5273 # policy was applied to the original IP packet
5274 self.assertTrue(rx[VXLAN].gpflags.A)
5275 # since it's an external host the reciever should not learn it
5276 self.assertTrue(rx[VXLAN].gpflags.D)
5277 inner = rx[VXLAN].payload
5278 self.assertEqual(inner[IP].src, "10.220.0.1")
5279 self.assertEqual(inner[IP].dst, rep.ip4.address)
5282 # An external subnet reachable via the remote external EP
5286 # first the VXLAN-GBP tunnel over which it is reached
5288 vx_tun_r = VppVxlanGbpTunnel(
5289 self, self.pg7.local_ip4,
5290 self.pg7.remote_ip4, 445,
5291 mode=(VppEnum.vl_api_vxlan_gbp_api_tunnel_mode_t.
5292 VXLAN_GBP_API_TUNNEL_MODE_L3))
5293 vx_tun_r.add_vpp_config()
5294 VppIpInterfaceBind(self, vx_tun_r, t4).add_vpp_config()
5296 self.logger.info(self.vapi.cli("sh vxlan-gbp tunnel"))
5299 # then the special adj to resolve through on that tunnel
5301 n1 = VppNeighbor(self,
5302 vx_tun_r.sw_if_index,
5303 "00:0c:0c:0c:0c:0c",
5304 self.pg7.remote_ip4)
5308 # the route via the adj above
5310 ip_222 = VppIpRoute(self, "10.222.0.0", 24,
5311 [VppRoutePath(self.pg7.remote_ip4,
5312 vx_tun_r.sw_if_index)],
5313 table_id=t4.table_id)
5314 ip_222.add_vpp_config()
5316 l3o_222 = VppGbpSubnet(
5317 self, rd1, "10.222.0.0", 24,
5318 # note: this a "regular" l3out subnet (not connected)
5319 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
5321 l3o_222.add_vpp_config()
5324 # ping between hosts in local and remote external subnets
5325 # dropped without a contract
5327 p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
5329 IP(src="10.220.0.1", dst="10.222.0.1") /
5330 UDP(sport=1234, dport=1234) /
5333 rxs = self.send_and_assert_no_replies(self.pg0, p * 1)
5336 # Add contracts ext-nets for 220 -> 222
5338 c4 = VppGbpContract(
5339 self, 55, 4220, 4222, acl_index,
5340 [VppGbpContractRule(
5341 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5342 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5345 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5346 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5348 [ETH_P_IP, ETH_P_IPV6])
5352 # ping from host in local to remote external subnets
5354 p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
5356 IP(src="10.220.0.1", dst="10.222.0.1") /
5357 UDP(sport=1234, dport=1234) /
5360 rxs = self.send_and_expect(self.pg0, p * 3, self.pg7)
5363 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
5364 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
5365 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
5366 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
5367 self.assertEqual(rx[VXLAN].vni, 445)
5368 self.assertTrue(rx[VXLAN].flags.G)
5369 self.assertTrue(rx[VXLAN].flags.Instance)
5370 # the sclass of the ext-net the packet came from
5371 self.assertEqual(rx[VXLAN].gpid, 4220)
5372 # policy was applied to the original IP packet
5373 self.assertTrue(rx[VXLAN].gpflags.A)
5374 # since it's an external host the reciever should not learn it
5375 self.assertTrue(rx[VXLAN].gpflags.D)
5376 inner = rx[VXLAN].payload
5377 self.assertEqual(inner[Ether].dst, "00:0c:0c:0c:0c:0c")
5378 self.assertEqual(inner[IP].src, "10.220.0.1")
5379 self.assertEqual(inner[IP].dst, "10.222.0.1")
5382 # ping from host in remote to local external subnets
5383 # there's no contract for this, but the A bit is set.
5385 p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
5386 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
5387 UDP(sport=1234, dport=48879) /
5388 VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
5389 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
5390 IP(src="10.222.0.1", dst="10.220.0.1") /
5391 UDP(sport=1234, dport=1234) /
5394 rxs = self.send_and_expect(self.pg7, p * 3, self.pg0)
5395 self.assertFalse(find_gbp_endpoint(self, ip="10.222.0.1"))
5398 # ping from host in remote to remote external subnets
5399 # this is dropped by reflection check.
5401 p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
5402 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
5403 UDP(sport=1234, dport=48879) /
5404 VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
5405 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
5406 IP(src="10.222.0.1", dst="10.222.0.2") /
5407 UDP(sport=1234, dport=1234) /
5410 rxs = self.send_and_assert_no_replies(self.pg7, p * 3)
5415 self.vlan_101.set_vtr(L2_VTR_OP.L2_DISABLED)
5416 self.vlan_100.set_vtr(L2_VTR_OP.L2_DISABLED)
5417 self.pg7.unconfig_ip4()
5420 if __name__ == '__main__':
5421 unittest.main(testRunner=VppTestRunner)