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 self.vapi.sw_interface_set_mac_address(
877 self.router_mac.packed)
879 # The BVIs are NAT inside interfaces
880 flags = self.config_flags.NAT_IS_INSIDE
881 self.vapi.nat44_interface_add_del_feature(
882 sw_if_index=epg.bvi.sw_if_index,
883 flags=flags, is_add=1)
884 self.vapi.nat66_add_del_interface(
885 is_add=1, flags=flags,
886 sw_if_index=epg.bvi.sw_if_index)
888 if_ip4 = VppIpInterfaceAddress(self, epg.bvi, epg.bvi_ip4, 32)
889 if_ip6 = VppIpInterfaceAddress(self, epg.bvi, epg.bvi_ip6, 128)
890 if_ip4.add_vpp_config()
891 if_ip6.add_vpp_config()
893 # EPG uplink interfaces in the RD
894 VppIpInterfaceBind(self, epg.uplink, epg.rd.t4).add_vpp_config()
895 VppIpInterfaceBind(self, epg.uplink, epg.rd.t6).add_vpp_config()
897 # add the BD ARP termination entry for BVI IP
898 epg.bd_arp_ip4 = VppBridgeDomainArpEntry(self, epg.bd.bd,
899 str(self.router_mac),
901 epg.bd_arp_ip6 = VppBridgeDomainArpEntry(self, epg.bd.bd,
902 str(self.router_mac),
904 epg.bd_arp_ip4.add_vpp_config()
905 epg.bd_arp_ip6.add_vpp_config()
910 for recirc in recircs:
911 # EPG's ingress recirculation interface maps to its RD
912 VppIpInterfaceBind(self, recirc.recirc,
913 recirc.epg.rd.t4).add_vpp_config()
914 VppIpInterfaceBind(self, recirc.recirc,
915 recirc.epg.rd.t6).add_vpp_config()
917 self.vapi.nat44_interface_add_del_feature(
918 sw_if_index=recirc.recirc.sw_if_index, is_add=1)
919 self.vapi.nat66_add_del_interface(
921 sw_if_index=recirc.recirc.sw_if_index)
923 recirc.add_vpp_config()
925 for recirc in recircs:
926 self.assertTrue(find_bridge_domain_port(self,
927 recirc.epg.bd.bd.bd_id,
928 recirc.recirc.sw_if_index))
931 self.pg_enable_capture(self.pg_interfaces)
934 # routes to the endpoints. We need these since there are no
935 # adj-fibs due to the fact the the BVI address has /32 and
936 # the subnet is not attached.
938 for (ip, fip) in zip(ep.ips, ep.fips):
939 # Add static mappings for each EP from the 10/8 to 11/8 network
941 flags = self.config_flags.NAT_IS_ADDR_ONLY
942 self.vapi.nat44_add_del_static_mapping(
944 local_ip_address=ip.bytes,
945 external_ip_address=fip.bytes,
946 external_sw_if_index=0xFFFFFFFF,
950 self.vapi.nat66_add_del_static_mapping(
951 local_ip_address=ip.bytes,
952 external_ip_address=fip.bytes,
958 self.logger.info(self.vapi.cli("sh gbp endpoint"))
960 # ... results in a Gratuitous ARP/ND on the EPG's uplink
961 rx = ep.epg.uplink.get_capture(len(ep.ips), timeout=0.2)
963 for ii, ip in enumerate(ep.ips):
967 self.assertTrue(p.haslayer(ICMPv6ND_NA))
968 self.assertEqual(p[ICMPv6ND_NA].tgt, ip.address)
970 self.assertTrue(p.haslayer(ARP))
971 self.assertEqual(p[ARP].psrc, ip.address)
972 self.assertEqual(p[ARP].pdst, ip.address)
974 # add the BD ARP termination entry for floating IP
976 ba = VppBridgeDomainArpEntry(self, epg_nat.bd.bd, ep.mac,
980 # floating IPs route via EPG recirc
982 self, fip.address, fip.length,
983 [VppRoutePath(fip.address,
984 ep.recirc.recirc.sw_if_index,
985 type=FibPathType.FIB_PATH_TYPE_DVR,
986 proto=fip.dpo_proto)],
990 # L2 FIB entries in the NAT EPG BD to bridge the packets from
991 # the outside direct to the internal EPG
992 lf = VppL2FibEntry(self, epg_nat.bd.bd, ep.mac,
993 ep.recirc.recirc, bvi_mac=0)
997 # ARP packets for unknown IP are sent to the EPG uplink
999 pkt_arp = (Ether(dst="ff:ff:ff:ff:ff:ff",
1000 src=self.pg0.remote_mac) /
1002 hwdst="ff:ff:ff:ff:ff:ff",
1003 hwsrc=self.pg0.remote_mac,
1007 self.vapi.cli("clear trace")
1008 self.pg0.add_stream(pkt_arp)
1010 self.pg_enable_capture(self.pg_interfaces)
1013 rxd = epgs[0].uplink.get_capture(1)
1016 # ARP/ND packets get a response
1018 pkt_arp = (Ether(dst="ff:ff:ff:ff:ff:ff",
1019 src=self.pg0.remote_mac) /
1021 hwdst="ff:ff:ff:ff:ff:ff",
1022 hwsrc=self.pg0.remote_mac,
1023 pdst=epgs[0].bvi_ip4.address,
1024 psrc=eps[0].ip4.address))
1026 self.send_and_expect(self.pg0, [pkt_arp], self.pg0)
1028 nsma = in6_getnsma(inet_pton(AF_INET6, eps[0].ip6.address))
1029 d = inet_ntop(AF_INET6, nsma)
1030 pkt_nd = (Ether(dst=in6_getnsmac(nsma),
1031 src=self.pg0.remote_mac) /
1032 IPv6(dst=d, src=eps[0].ip6.address) /
1033 ICMPv6ND_NS(tgt=epgs[0].bvi_ip6.address) /
1034 ICMPv6NDOptSrcLLAddr(lladdr=self.pg0.remote_mac))
1035 self.send_and_expect(self.pg0, [pkt_nd], self.pg0)
1038 # broadcast packets are flooded
1040 pkt_bcast = (Ether(dst="ff:ff:ff:ff:ff:ff",
1041 src=self.pg0.remote_mac) /
1042 IP(src=eps[0].ip4.address, dst="232.1.1.1") /
1043 UDP(sport=1234, dport=1234) /
1046 self.vapi.cli("clear trace")
1047 self.pg0.add_stream(pkt_bcast)
1049 self.pg_enable_capture(self.pg_interfaces)
1052 rxd = eps[1].itf.get_capture(1)
1053 self.assertEqual(rxd[0][Ether].dst, pkt_bcast[Ether].dst)
1054 rxd = epgs[0].uplink.get_capture(1)
1055 self.assertEqual(rxd[0][Ether].dst, pkt_bcast[Ether].dst)
1058 # packets to non-local L3 destinations dropped
1060 pkt_intra_epg_220_ip4 = (Ether(src=self.pg0.remote_mac,
1061 dst=str(self.router_mac)) /
1062 IP(src=eps[0].ip4.address,
1064 UDP(sport=1234, dport=1234) /
1066 pkt_inter_epg_222_ip4 = (Ether(src=self.pg0.remote_mac,
1067 dst=str(self.router_mac)) /
1068 IP(src=eps[0].ip4.address,
1070 UDP(sport=1234, dport=1234) /
1073 self.send_and_assert_no_replies(self.pg0,
1074 pkt_intra_epg_220_ip4 * NUM_PKTS)
1076 pkt_inter_epg_222_ip6 = (Ether(src=self.pg0.remote_mac,
1077 dst=str(self.router_mac)) /
1078 IPv6(src=eps[0].ip6.address,
1079 dst="2001:10::99") /
1080 UDP(sport=1234, dport=1234) /
1082 self.send_and_assert_no_replies(self.pg0,
1083 pkt_inter_epg_222_ip6 * NUM_PKTS)
1086 # Add the subnet routes
1089 self, rd0, "10.0.0.0", 24,
1090 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1092 self, rd0, "10.0.1.0", 24,
1093 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1095 self, rd0, "10.0.2.0", 24,
1096 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1098 self, rd0, "2001:10::1", 64,
1099 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1101 self, rd0, "2001:10:1::1", 64,
1102 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1104 self, rd0, "2001:10:2::1", 64,
1105 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1106 s41.add_vpp_config()
1107 s42.add_vpp_config()
1108 s43.add_vpp_config()
1109 s61.add_vpp_config()
1110 s62.add_vpp_config()
1111 s63.add_vpp_config()
1113 self.send_and_expect_bridged(eps[0].itf,
1114 pkt_intra_epg_220_ip4 * NUM_PKTS,
1116 self.send_and_expect_bridged(eps[0].itf,
1117 pkt_inter_epg_222_ip4 * NUM_PKTS,
1119 self.send_and_expect_bridged6(eps[0].itf,
1120 pkt_inter_epg_222_ip6 * NUM_PKTS,
1123 self.logger.info(self.vapi.cli("sh ip fib 11.0.0.2"))
1124 self.logger.info(self.vapi.cli("sh gbp endpoint-group"))
1125 self.logger.info(self.vapi.cli("sh gbp endpoint"))
1126 self.logger.info(self.vapi.cli("sh gbp recirc"))
1127 self.logger.info(self.vapi.cli("sh int"))
1128 self.logger.info(self.vapi.cli("sh int addr"))
1129 self.logger.info(self.vapi.cli("sh int feat loop6"))
1130 self.logger.info(self.vapi.cli("sh vlib graph ip4-gbp-src-classify"))
1131 self.logger.info(self.vapi.cli("sh int feat loop3"))
1132 self.logger.info(self.vapi.cli("sh int feat pg0"))
1135 # Packet destined to unknown unicast is sent on the epg uplink ...
1137 pkt_intra_epg_220_to_uplink = (Ether(src=self.pg0.remote_mac,
1138 dst="00:00:00:33:44:55") /
1139 IP(src=eps[0].ip4.address,
1141 UDP(sport=1234, dport=1234) /
1144 self.send_and_expect_bridged(eps[0].itf,
1145 pkt_intra_epg_220_to_uplink * NUM_PKTS,
1147 # ... and nowhere else
1148 self.pg1.get_capture(0, timeout=0.1)
1149 self.pg1.assert_nothing_captured(remark="Flood onto other VMS")
1151 pkt_intra_epg_221_to_uplink = (Ether(src=self.pg2.remote_mac,
1152 dst="00:00:00:33:44:66") /
1153 IP(src=eps[0].ip4.address,
1155 UDP(sport=1234, dport=1234) /
1158 self.send_and_expect_bridged(eps[2].itf,
1159 pkt_intra_epg_221_to_uplink * NUM_PKTS,
1163 # Packets from the uplink are forwarded in the absence of a contract
1165 pkt_intra_epg_220_from_uplink = (Ether(src="00:00:00:33:44:55",
1166 dst=self.pg0.remote_mac) /
1167 IP(src=eps[0].ip4.address,
1169 UDP(sport=1234, dport=1234) /
1172 self.send_and_expect_bridged(self.pg4,
1173 pkt_intra_epg_220_from_uplink * NUM_PKTS,
1177 # in the absence of policy, endpoints in the same EPG
1180 pkt_intra_epg = (Ether(src=self.pg0.remote_mac,
1181 dst=self.pg1.remote_mac) /
1182 IP(src=eps[0].ip4.address,
1183 dst=eps[1].ip4.address) /
1184 UDP(sport=1234, dport=1234) /
1187 self.send_and_expect_bridged(self.pg0,
1188 pkt_intra_epg * NUM_PKTS,
1192 # in the absence of policy, endpoints in the different EPG
1193 # cannot communicate
1195 pkt_inter_epg_220_to_221 = (Ether(src=self.pg0.remote_mac,
1196 dst=self.pg2.remote_mac) /
1197 IP(src=eps[0].ip4.address,
1198 dst=eps[2].ip4.address) /
1199 UDP(sport=1234, dport=1234) /
1201 pkt_inter_epg_221_to_220 = (Ether(src=self.pg2.remote_mac,
1202 dst=self.pg0.remote_mac) /
1203 IP(src=eps[2].ip4.address,
1204 dst=eps[0].ip4.address) /
1205 UDP(sport=1234, dport=1234) /
1207 pkt_inter_epg_220_to_222 = (Ether(src=self.pg0.remote_mac,
1208 dst=str(self.router_mac)) /
1209 IP(src=eps[0].ip4.address,
1210 dst=eps[3].ip4.address) /
1211 UDP(sport=1234, dport=1234) /
1214 self.send_and_assert_no_replies(eps[0].itf,
1215 pkt_inter_epg_220_to_221 * NUM_PKTS)
1216 self.send_and_assert_no_replies(eps[0].itf,
1217 pkt_inter_epg_220_to_222 * NUM_PKTS)
1220 # A uni-directional contract from EPG 220 -> 221
1222 acl = VppGbpAcl(self)
1223 rule = acl.create_rule(permit_deny=1, proto=17)
1224 rule2 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
1225 acl_index = acl.add_vpp_config([rule, rule2])
1226 c1 = VppGbpContract(
1227 self, 400, epgs[0].sclass, epgs[1].sclass, acl_index,
1228 [VppGbpContractRule(
1229 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1230 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1233 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1234 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1236 [ETH_P_IP, ETH_P_IPV6])
1239 self.send_and_expect_bridged(eps[0].itf,
1240 pkt_inter_epg_220_to_221 * NUM_PKTS,
1242 self.send_and_assert_no_replies(eps[0].itf,
1243 pkt_inter_epg_220_to_222 * NUM_PKTS)
1246 # contract for the return direction
1248 c2 = VppGbpContract(
1249 self, 400, epgs[1].sclass, epgs[0].sclass, acl_index,
1250 [VppGbpContractRule(
1251 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1252 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1255 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1256 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1258 [ETH_P_IP, ETH_P_IPV6])
1261 self.send_and_expect_bridged(eps[0].itf,
1262 pkt_inter_epg_220_to_221 * NUM_PKTS,
1264 self.send_and_expect_bridged(eps[2].itf,
1265 pkt_inter_epg_221_to_220 * NUM_PKTS,
1268 ds = c2.get_drop_stats()
1269 self.assertEqual(ds['packets'], 0)
1270 ps = c2.get_permit_stats()
1271 self.assertEqual(ps['packets'], NUM_PKTS)
1274 # the contract does not allow non-IP
1276 pkt_non_ip_inter_epg_220_to_221 = (Ether(src=self.pg0.remote_mac,
1277 dst=self.pg2.remote_mac) /
1279 self.send_and_assert_no_replies(eps[0].itf,
1280 pkt_non_ip_inter_epg_220_to_221 * 17)
1283 # check that inter group is still disabled for the groups
1284 # not in the contract.
1286 self.send_and_assert_no_replies(eps[0].itf,
1287 pkt_inter_epg_220_to_222 * NUM_PKTS)
1290 # A uni-directional contract from EPG 220 -> 222 'L3 routed'
1292 c3 = VppGbpContract(
1293 self, 400, epgs[0].sclass, epgs[2].sclass, acl_index,
1294 [VppGbpContractRule(
1295 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1296 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1299 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1300 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1302 [ETH_P_IP, ETH_P_IPV6])
1305 self.logger.info(self.vapi.cli("sh gbp contract"))
1307 self.send_and_expect_routed(eps[0].itf,
1308 pkt_inter_epg_220_to_222 * NUM_PKTS,
1310 str(self.router_mac))
1313 # remove both contracts, traffic stops in both directions
1315 c2.remove_vpp_config()
1316 c1.remove_vpp_config()
1317 c3.remove_vpp_config()
1318 acl.remove_vpp_config()
1320 self.send_and_assert_no_replies(eps[2].itf,
1321 pkt_inter_epg_221_to_220 * NUM_PKTS)
1322 self.send_and_assert_no_replies(eps[0].itf,
1323 pkt_inter_epg_220_to_221 * NUM_PKTS)
1324 self.send_and_expect_bridged(eps[0].itf,
1325 pkt_intra_epg * NUM_PKTS,
1329 # EPs to the outside world
1332 # in the EP's RD an external subnet via the NAT EPG's recirc
1334 self, rd0, "0.0.0.0", 0,
1335 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1336 sw_if_index=recirc_nat.recirc.sw_if_index,
1337 sclass=epg_nat.sclass)
1339 self, rd0, "11.0.0.0", 8,
1340 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1341 sw_if_index=recirc_nat.recirc.sw_if_index,
1342 sclass=epg_nat.sclass)
1343 se16 = VppGbpSubnet(
1345 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1346 sw_if_index=recirc_nat.recirc.sw_if_index,
1347 sclass=epg_nat.sclass)
1348 # in the NAT RD an external subnet via the NAT EPG's uplink
1350 self, rd20, "0.0.0.0", 0,
1351 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1352 sw_if_index=epg_nat.uplink.sw_if_index,
1353 sclass=epg_nat.sclass)
1354 se36 = VppGbpSubnet(
1355 self, rd20, "::", 0,
1356 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1357 sw_if_index=epg_nat.uplink.sw_if_index,
1358 sclass=epg_nat.sclass)
1360 self, rd20, "11.0.0.0", 8,
1361 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1362 sw_if_index=epg_nat.uplink.sw_if_index,
1363 sclass=epg_nat.sclass)
1364 se1.add_vpp_config()
1365 se2.add_vpp_config()
1366 se16.add_vpp_config()
1367 se3.add_vpp_config()
1368 se36.add_vpp_config()
1369 se4.add_vpp_config()
1371 self.logger.info(self.vapi.cli("sh ip fib 0.0.0.0/0"))
1372 self.logger.info(self.vapi.cli("sh ip fib 11.0.0.1"))
1373 self.logger.info(self.vapi.cli("sh ip6 fib ::/0"))
1374 self.logger.info(self.vapi.cli("sh ip6 fib %s" %
1378 # From an EP to an outside address: IN2OUT
1380 pkt_inter_epg_220_to_global = (Ether(src=self.pg0.remote_mac,
1381 dst=str(self.router_mac)) /
1382 IP(src=eps[0].ip4.address,
1384 UDP(sport=1234, dport=1234) /
1388 self.send_and_assert_no_replies(eps[0].itf,
1389 pkt_inter_epg_220_to_global * NUM_PKTS)
1391 acl2 = VppGbpAcl(self)
1392 rule = acl2.create_rule(permit_deny=1, proto=17, sport_from=1234,
1393 sport_to=1234, dport_from=1234, dport_to=1234)
1394 rule2 = acl2.create_rule(is_ipv6=1, permit_deny=1, proto=17,
1395 sport_from=1234, sport_to=1234,
1396 dport_from=1234, dport_to=1234)
1398 acl_index2 = acl2.add_vpp_config([rule, rule2])
1399 c4 = VppGbpContract(
1400 self, 400, epgs[0].sclass, epgs[3].sclass, acl_index2,
1401 [VppGbpContractRule(
1402 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1403 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1406 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1407 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1409 [ETH_P_IP, ETH_P_IPV6])
1412 self.send_and_expect_natted(eps[0].itf,
1413 pkt_inter_epg_220_to_global * NUM_PKTS,
1415 eps[0].fip4.address)
1417 pkt_inter_epg_220_to_global = (Ether(src=self.pg0.remote_mac,
1418 dst=str(self.router_mac)) /
1419 IPv6(src=eps[0].ip6.address,
1421 UDP(sport=1234, dport=1234) /
1424 self.send_and_expect_natted6(self.pg0,
1425 pkt_inter_epg_220_to_global * NUM_PKTS,
1427 eps[0].fip6.address)
1430 # From a global address to an EP: OUT2IN
1432 pkt_inter_epg_220_from_global = (Ether(src=str(self.router_mac),
1433 dst=self.pg0.remote_mac) /
1434 IP(dst=eps[0].fip4.address,
1436 UDP(sport=1234, dport=1234) /
1439 self.send_and_assert_no_replies(
1440 self.pg7, pkt_inter_epg_220_from_global * NUM_PKTS)
1442 c5 = VppGbpContract(
1443 self, 400, epgs[3].sclass, epgs[0].sclass, acl_index2,
1444 [VppGbpContractRule(
1445 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1446 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1449 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1450 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1452 [ETH_P_IP, ETH_P_IPV6])
1455 self.send_and_expect_unnatted(self.pg7,
1456 pkt_inter_epg_220_from_global * NUM_PKTS,
1460 pkt_inter_epg_220_from_global = (Ether(src=str(self.router_mac),
1461 dst=self.pg0.remote_mac) /
1462 IPv6(dst=eps[0].fip6.address,
1464 UDP(sport=1234, dport=1234) /
1467 self.send_and_expect_unnatted6(
1469 pkt_inter_epg_220_from_global * NUM_PKTS,
1474 # From a local VM to another local VM using resp. public addresses:
1477 pkt_intra_epg_220_global = (Ether(src=self.pg0.remote_mac,
1478 dst=str(self.router_mac)) /
1479 IP(src=eps[0].ip4.address,
1480 dst=eps[1].fip4.address) /
1481 UDP(sport=1234, dport=1234) /
1484 self.send_and_expect_double_natted(eps[0].itf,
1485 pkt_intra_epg_220_global * NUM_PKTS,
1487 eps[0].fip4.address,
1490 pkt_intra_epg_220_global = (Ether(src=self.pg0.remote_mac,
1491 dst=str(self.router_mac)) /
1492 IPv6(src=eps[0].ip6.address,
1493 dst=eps[1].fip6.address) /
1494 UDP(sport=1234, dport=1234) /
1497 self.send_and_expect_double_natted6(
1499 pkt_intra_epg_220_global * NUM_PKTS,
1501 eps[0].fip6.address,
1508 # del static mappings for each EP from the 10/8 to 11/8 network
1509 flags = self.config_flags.NAT_IS_ADDR_ONLY
1510 self.vapi.nat44_add_del_static_mapping(
1512 local_ip_address=ep.ip4.bytes,
1513 external_ip_address=ep.fip4.bytes,
1514 external_sw_if_index=0xFFFFFFFF,
1517 self.vapi.nat66_add_del_static_mapping(
1518 local_ip_address=ep.ip6.bytes,
1519 external_ip_address=ep.fip6.bytes,
1523 # IP config on the BVI interfaces
1524 if epg != epgs[0] and epg != epgs[3]:
1525 flags = self.config_flags.NAT_IS_INSIDE
1526 self.vapi.nat44_interface_add_del_feature(
1527 sw_if_index=epg.bvi.sw_if_index,
1530 self.vapi.nat66_add_del_interface(
1531 is_add=0, flags=flags,
1532 sw_if_index=epg.bvi.sw_if_index)
1534 for recirc in recircs:
1535 self.vapi.nat44_interface_add_del_feature(
1536 sw_if_index=recirc.recirc.sw_if_index,
1538 self.vapi.nat66_add_del_interface(
1540 sw_if_index=recirc.recirc.sw_if_index)
1542 def wait_for_ep_timeout(self, sw_if_index=None, ip=None, mac=None,
1543 tep=None, n_tries=100, s_time=1):
1545 if not find_gbp_endpoint(self, sw_if_index, ip, mac, tep=tep):
1547 n_tries = n_tries - 1
1549 self.assertFalse(find_gbp_endpoint(self, sw_if_index, ip, mac))
1552 def test_gbp_learn_l2(self):
1553 """ GBP L2 Endpoint Learning """
1555 drop_no_contract = self.statistics.get_err_counter(
1556 '/err/gbp-policy-port/drop-no-contract')
1557 allow_intra_class = self.statistics.get_err_counter(
1558 '/err/gbp-policy-port/allow-intra-sclass')
1560 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
1561 learnt = [{'mac': '00:00:11:11:11:01',
1563 'ip6': '2001:10::2'},
1564 {'mac': '00:00:11:11:11:02',
1566 'ip6': '2001:10::3'}]
1571 gt4 = VppIpTable(self, 1)
1572 gt4.add_vpp_config()
1573 gt6 = VppIpTable(self, 1, is_ip6=True)
1574 gt6.add_vpp_config()
1576 rd1 = VppGbpRouteDomain(self, 1, 401, gt4, gt6)
1577 rd1.add_vpp_config()
1580 # Pg2 hosts the vxlan tunnel, hosts on pg2 to act as TEPs
1581 # Pg3 hosts the IP4 UU-flood VXLAN tunnel
1582 # Pg4 hosts the IP6 UU-flood VXLAN tunnel
1584 self.pg2.config_ip4()
1585 self.pg2.resolve_arp()
1586 self.pg2.generate_remote_hosts(4)
1587 self.pg2.configure_ipv4_neighbors()
1588 self.pg3.config_ip4()
1589 self.pg3.resolve_arp()
1590 self.pg4.config_ip4()
1591 self.pg4.resolve_arp()
1594 # Add a mcast destination VXLAN-GBP tunnel for B&M traffic
1596 tun_bm = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
1599 tun_bm.add_vpp_config()
1602 # a GBP bridge domain with a BVI and a UU-flood interface
1604 bd1 = VppBridgeDomain(self, 1)
1605 bd1.add_vpp_config()
1606 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0,
1608 gbd1.add_vpp_config()
1610 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1611 self.logger.info(self.vapi.cli("sh gbp bridge"))
1613 # ... and has a /32 applied
1614 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
1615 ip_addr.add_vpp_config()
1618 # The Endpoint-group in which we are learning endpoints
1620 epg_220 = VppGbpEndpointGroup(self, 220, 112, rd1, gbd1,
1624 VppGbpEndpointRetention(2))
1625 epg_220.add_vpp_config()
1626 epg_330 = VppGbpEndpointGroup(self, 330, 113, rd1, gbd1,
1630 VppGbpEndpointRetention(2))
1631 epg_330.add_vpp_config()
1634 # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
1637 vx_tun_l2_1 = VppGbpVxlanTunnel(
1638 self, 99, bd1.bd_id,
1639 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L2,
1641 vx_tun_l2_1.add_vpp_config()
1644 # A static endpoint that the learnt endpoints are trying to
1647 ep = VppGbpEndpoint(self, self.pg0,
1649 "10.0.0.127", "11.0.0.127",
1650 "2001:10::1", "3001::1")
1653 self.assertTrue(find_route(self, ep.ip4.address, 32, table_id=1))
1655 # a packet with an sclass from an unknown EPG
1656 p = (Ether(src=self.pg2.remote_mac,
1657 dst=self.pg2.local_mac) /
1658 IP(src=self.pg2.remote_hosts[0].ip4,
1659 dst=self.pg2.local_ip4) /
1660 UDP(sport=1234, dport=48879) /
1661 VXLAN(vni=99, gpid=88, flags=0x88) /
1662 Ether(src=learnt[0]["mac"], dst=ep.mac) /
1663 IP(src=learnt[0]["ip"], dst=ep.ip4.address) /
1664 UDP(sport=1234, dport=1234) /
1667 self.send_and_assert_no_replies(self.pg2, p)
1669 self.logger.info(self.vapi.cli("sh error"))
1670 self.assert_error_counter_equal(
1671 '/err/gbp-policy-port/drop-no-contract',
1672 drop_no_contract + 1)
1675 # we should not have learnt a new tunnel endpoint, since
1676 # the EPG was not learnt.
1678 self.assertEqual(INDEX_INVALID,
1679 find_vxlan_gbp_tunnel(self,
1681 self.pg2.remote_hosts[0].ip4,
1684 # ep is not learnt, because the EPG is unknown
1685 self.assertEqual(len(self.vapi.gbp_endpoint_dump()), 1)
1688 # Learn new EPs from IP packets
1690 for ii, l in enumerate(learnt):
1691 # a packet with an sclass from a known EPG
1692 # arriving on an unknown TEP
1693 p = (Ether(src=self.pg2.remote_mac,
1694 dst=self.pg2.local_mac) /
1695 IP(src=self.pg2.remote_hosts[1].ip4,
1696 dst=self.pg2.local_ip4) /
1697 UDP(sport=1234, dport=48879) /
1698 VXLAN(vni=99, gpid=112, flags=0x88) /
1699 Ether(src=l['mac'], dst=ep.mac) /
1700 IP(src=l['ip'], dst=ep.ip4.address) /
1701 UDP(sport=1234, dport=1234) /
1704 rx = self.send_and_expect(self.pg2, [p], self.pg0)
1707 tep1_sw_if_index = find_vxlan_gbp_tunnel(
1710 self.pg2.remote_hosts[1].ip4,
1712 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
1715 # the EP is learnt via the learnt TEP
1716 # both from its MAC and its IP
1718 self.assertTrue(find_gbp_endpoint(self,
1719 vx_tun_l2_1.sw_if_index,
1721 self.assertTrue(find_gbp_endpoint(self,
1722 vx_tun_l2_1.sw_if_index,
1725 self.assert_error_counter_equal(
1726 '/err/gbp-policy-port/allow-intra-sclass',
1727 allow_intra_class + 2)
1729 self.logger.info(self.vapi.cli("show gbp endpoint"))
1730 self.logger.info(self.vapi.cli("show gbp vxlan"))
1731 self.logger.info(self.vapi.cli("show ip mfib"))
1734 # If we sleep for the threshold time, the learnt endpoints should
1738 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1742 # Learn new EPs from GARP packets received on the BD's mcast tunnel
1744 for ii, l in enumerate(learnt):
1745 # add some junk in the reserved field of the vxlan-header
1746 # next to the VNI. we should accept since reserved bits are
1748 p = (Ether(src=self.pg2.remote_mac,
1749 dst=self.pg2.local_mac) /
1750 IP(src=self.pg2.remote_hosts[1].ip4,
1752 UDP(sport=1234, dport=48879) /
1753 VXLAN(vni=88, reserved2=0x80, gpid=112, flags=0x88) /
1754 Ether(src=l['mac'], dst="ff:ff:ff:ff:ff:ff") /
1756 psrc=l['ip'], pdst=l['ip'],
1757 hwsrc=l['mac'], hwdst="ff:ff:ff:ff:ff:ff"))
1759 rx = self.send_and_expect(self.pg4, [p], self.pg0)
1762 tep1_sw_if_index = find_vxlan_gbp_tunnel(
1765 self.pg2.remote_hosts[1].ip4,
1767 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
1770 # the EP is learnt via the learnt TEP
1771 # both from its MAC and its IP
1773 self.assertTrue(find_gbp_endpoint(self,
1774 vx_tun_l2_1.sw_if_index,
1776 self.assertTrue(find_gbp_endpoint(self,
1777 vx_tun_l2_1.sw_if_index,
1781 # wait for the learnt endpoints to age out
1784 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1788 # Learn new EPs from L2 packets
1790 for ii, l in enumerate(learnt):
1791 # a packet with an sclass from a known EPG
1792 # arriving on an unknown TEP
1793 p = (Ether(src=self.pg2.remote_mac,
1794 dst=self.pg2.local_mac) /
1795 IP(src=self.pg2.remote_hosts[1].ip4,
1796 dst=self.pg2.local_ip4) /
1797 UDP(sport=1234, dport=48879) /
1798 VXLAN(vni=99, gpid=112, flags=0x88) /
1799 Ether(src=l['mac'], dst=ep.mac) /
1802 rx = self.send_and_expect(self.pg2, [p], self.pg0)
1805 tep1_sw_if_index = find_vxlan_gbp_tunnel(
1808 self.pg2.remote_hosts[1].ip4,
1810 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
1813 # the EP is learnt via the learnt TEP
1814 # both from its MAC and its IP
1816 self.assertTrue(find_gbp_endpoint(self,
1817 vx_tun_l2_1.sw_if_index,
1820 self.logger.info(self.vapi.cli("show gbp endpoint"))
1821 self.logger.info(self.vapi.cli("show gbp vxlan"))
1822 self.logger.info(self.vapi.cli("show vxlan-gbp tunnel"))
1825 # wait for the learnt endpoints to age out
1828 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1832 # repeat. the do not learn bit is set so the EPs are not learnt
1835 # a packet with an sclass from a known EPG
1836 p = (Ether(src=self.pg2.remote_mac,
1837 dst=self.pg2.local_mac) /
1838 IP(src=self.pg2.remote_hosts[1].ip4,
1839 dst=self.pg2.local_ip4) /
1840 UDP(sport=1234, dport=48879) /
1841 VXLAN(vni=99, gpid=112, flags=0x88, gpflags="D") /
1842 Ether(src=l['mac'], dst=ep.mac) /
1843 IP(src=l['ip'], dst=ep.ip4.address) /
1844 UDP(sport=1234, dport=1234) /
1847 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
1850 self.assertFalse(find_gbp_endpoint(self,
1851 vx_tun_l2_1.sw_if_index,
1858 # a packet with an sclass from a known EPG
1859 # set a reserved bit in addition to the G and I
1860 # reserved bits should not be checked on rx.
1861 p = (Ether(src=self.pg2.remote_mac,
1862 dst=self.pg2.local_mac) /
1863 IP(src=self.pg2.remote_hosts[1].ip4,
1864 dst=self.pg2.local_ip4) /
1865 UDP(sport=1234, dport=48879) /
1866 VXLAN(vni=99, gpid=112, flags=0xc8) /
1867 Ether(src=l['mac'], dst=ep.mac) /
1868 IP(src=l['ip'], dst=ep.ip4.address) /
1869 UDP(sport=1234, dport=1234) /
1872 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
1874 self.assertTrue(find_gbp_endpoint(self,
1875 vx_tun_l2_1.sw_if_index,
1879 # Static EP replies to dynamics
1881 self.logger.info(self.vapi.cli("sh l2fib bd_id 1"))
1883 p = (Ether(src=ep.mac, dst=l['mac']) /
1884 IP(dst=l['ip'], src=ep.ip4.address) /
1885 UDP(sport=1234, dport=1234) /
1888 rxs = self.send_and_expect(self.pg0, p * 17, self.pg2)
1891 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
1892 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
1893 self.assertEqual(rx[UDP].dport, 48879)
1894 # the UDP source port is a random value for hashing
1895 self.assertEqual(rx[VXLAN].gpid, 112)
1896 self.assertEqual(rx[VXLAN].vni, 99)
1897 self.assertTrue(rx[VXLAN].flags.G)
1898 self.assertTrue(rx[VXLAN].flags.Instance)
1899 self.assertTrue(rx[VXLAN].gpflags.A)
1900 self.assertFalse(rx[VXLAN].gpflags.D)
1903 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1907 # repeat in the other EPG
1908 # there's no contract between 220 and 330, but the A-bit is set
1909 # so the packet is cleared for delivery
1912 # a packet with an sclass from a known EPG
1913 p = (Ether(src=self.pg2.remote_mac,
1914 dst=self.pg2.local_mac) /
1915 IP(src=self.pg2.remote_hosts[1].ip4,
1916 dst=self.pg2.local_ip4) /
1917 UDP(sport=1234, dport=48879) /
1918 VXLAN(vni=99, gpid=113, flags=0x88, gpflags='A') /
1919 Ether(src=l['mac'], dst=ep.mac) /
1920 IP(src=l['ip'], dst=ep.ip4.address) /
1921 UDP(sport=1234, dport=1234) /
1924 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
1926 self.assertTrue(find_gbp_endpoint(self,
1927 vx_tun_l2_1.sw_if_index,
1931 # static EP cannot reach the learnt EPs since there is no contract
1932 # only test 1 EP as the others could timeout
1934 p = (Ether(src=ep.mac, dst=l['mac']) /
1935 IP(dst=learnt[0]['ip'], src=ep.ip4.address) /
1936 UDP(sport=1234, dport=1234) /
1939 self.send_and_assert_no_replies(self.pg0, [p])
1942 # refresh the entries after the check for no replies above
1945 # a packet with an sclass from a known EPG
1946 p = (Ether(src=self.pg2.remote_mac,
1947 dst=self.pg2.local_mac) /
1948 IP(src=self.pg2.remote_hosts[1].ip4,
1949 dst=self.pg2.local_ip4) /
1950 UDP(sport=1234, dport=48879) /
1951 VXLAN(vni=99, gpid=113, flags=0x88, gpflags='A') /
1952 Ether(src=l['mac'], dst=ep.mac) /
1953 IP(src=l['ip'], dst=ep.ip4.address) /
1954 UDP(sport=1234, dport=1234) /
1957 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
1959 self.assertTrue(find_gbp_endpoint(self,
1960 vx_tun_l2_1.sw_if_index,
1964 # Add the contract so they can talk
1966 acl = VppGbpAcl(self)
1967 rule = acl.create_rule(permit_deny=1, proto=17)
1968 rule2 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
1969 acl_index = acl.add_vpp_config([rule, rule2])
1970 c1 = VppGbpContract(
1971 self, 401, epg_220.sclass, epg_330.sclass, acl_index,
1972 [VppGbpContractRule(
1973 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1974 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1977 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1978 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1980 [ETH_P_IP, ETH_P_IPV6])
1984 p = (Ether(src=ep.mac, dst=l['mac']) /
1985 IP(dst=l['ip'], src=ep.ip4.address) /
1986 UDP(sport=1234, dport=1234) /
1989 self.send_and_expect(self.pg0, [p], self.pg2)
1992 # send UU packets from the local EP
1994 self.logger.info(self.vapi.cli("sh gbp bridge"))
1995 self.logger.info(self.vapi.cli("sh bridge-domain 1 detail"))
1996 p_uu = (Ether(src=ep.mac, dst="00:11:11:11:11:11") /
1997 IP(dst="10.0.0.133", src=ep.ip4.address) /
1998 UDP(sport=1234, dport=1234) /
2000 rxs = self.send_and_expect(ep.itf, [p_uu], gbd1.uu_fwd)
2002 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2004 p_bm = (Ether(src=ep.mac, dst="ff:ff:ff:ff:ff:ff") /
2005 IP(dst="10.0.0.133", src=ep.ip4.address) /
2006 UDP(sport=1234, dport=1234) /
2008 rxs = self.send_and_expect_only(ep.itf, [p_bm], tun_bm.mcast_itf)
2011 self.assertEqual(rx[IP].src, self.pg4.local_ip4)
2012 self.assertEqual(rx[IP].dst, "239.1.1.1")
2013 self.assertEqual(rx[UDP].dport, 48879)
2014 # the UDP source port is a random value for hashing
2015 self.assertEqual(rx[VXLAN].gpid, 112)
2016 self.assertEqual(rx[VXLAN].vni, 88)
2017 self.assertTrue(rx[VXLAN].flags.G)
2018 self.assertTrue(rx[VXLAN].flags.Instance)
2019 self.assertFalse(rx[VXLAN].gpflags.A)
2020 self.assertFalse(rx[VXLAN].gpflags.D)
2022 acl = VppGbpAcl(self)
2023 rule = acl.create_rule(permit_deny=1, proto=17)
2024 rule2 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
2025 acl_index = acl.add_vpp_config([rule, rule2])
2026 c2 = VppGbpContract(
2027 self, 401, epg_330.sclass, epg_220.sclass, acl_index,
2028 [VppGbpContractRule(
2029 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2030 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2033 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2034 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2036 [ETH_P_IP, ETH_P_IPV6])
2040 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
2043 # Check v6 Endpoints learning
2046 # a packet with an sclass from a known EPG
2047 p = (Ether(src=self.pg2.remote_mac,
2048 dst=self.pg2.local_mac) /
2049 IP(src=self.pg2.remote_hosts[1].ip4,
2050 dst=self.pg2.local_ip4) /
2051 UDP(sport=1234, dport=48879) /
2052 VXLAN(vni=99, gpid=113, flags=0x88) /
2053 Ether(src=l['mac'], dst=ep.mac) /
2054 IPv6(src=l['ip6'], dst=ep.ip6.address) /
2055 UDP(sport=1234, dport=1234) /
2058 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
2059 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
2061 self.assertTrue(find_gbp_endpoint(
2063 vx_tun_l2_1.sw_if_index,
2065 tep=[self.pg2.local_ip4,
2066 self.pg2.remote_hosts[1].ip4]))
2068 self.logger.info(self.vapi.cli("sh int"))
2069 self.logger.info(self.vapi.cli("sh vxlan-gbp tunnel"))
2070 self.logger.info(self.vapi.cli("sh gbp vxlan"))
2071 self.logger.info(self.vapi.cli("sh gbp endpoint"))
2072 self.logger.info(self.vapi.cli("sh gbp interface"))
2075 # EP moves to a different TEP
2078 # a packet with an sclass from a known EPG
2079 p = (Ether(src=self.pg2.remote_mac,
2080 dst=self.pg2.local_mac) /
2081 IP(src=self.pg2.remote_hosts[2].ip4,
2082 dst=self.pg2.local_ip4) /
2083 UDP(sport=1234, dport=48879) /
2084 VXLAN(vni=99, gpid=113, flags=0x88) /
2085 Ether(src=l['mac'], dst=ep.mac) /
2086 IPv6(src=l['ip6'], dst=ep.ip6.address) /
2087 UDP(sport=1234, dport=1234) /
2090 rx = self.send_and_expect(self.pg2, p * 1, self.pg0)
2091 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
2093 self.assertTrue(find_gbp_endpoint(
2095 vx_tun_l2_1.sw_if_index,
2098 tep=[self.pg2.local_ip4,
2099 self.pg2.remote_hosts[2].ip4]))
2102 # v6 remote EP reachability
2105 p = (Ether(src=ep.mac, dst=l['mac']) /
2106 IPv6(dst=l['ip6'], src=ep.ip6.address) /
2107 UDP(sport=1234, dport=1234) /
2110 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
2113 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2114 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[2].ip4)
2115 self.assertEqual(rx[UDP].dport, 48879)
2116 # the UDP source port is a random value for hashing
2117 self.assertEqual(rx[VXLAN].gpid, 112)
2118 self.assertEqual(rx[VXLAN].vni, 99)
2119 self.assertTrue(rx[VXLAN].flags.G)
2120 self.assertTrue(rx[VXLAN].flags.Instance)
2121 self.assertTrue(rx[VXLAN].gpflags.A)
2122 self.assertFalse(rx[VXLAN].gpflags.D)
2123 self.assertEqual(rx[IPv6].dst, l['ip6'])
2129 # a packet with an sclass from a known EPG
2130 p = (Ether(src=self.pg2.remote_mac,
2131 dst=self.pg2.local_mac) /
2132 IP(src=self.pg2.remote_hosts[2].ip4,
2133 dst=self.pg2.local_ip4) /
2134 UDP(sport=1234, dport=48879) /
2135 VXLAN(vni=99, gpid=112, flags=0x88) /
2136 Ether(src=l['mac'], dst=ep.mac) /
2137 IPv6(src=l['ip6'], dst=ep.ip6.address) /
2138 UDP(sport=1234, dport=1234) /
2141 rx = self.send_and_expect(self.pg2, p * 1, self.pg0)
2142 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
2144 self.assertTrue(find_gbp_endpoint(
2146 vx_tun_l2_1.sw_if_index,
2149 tep=[self.pg2.local_ip4,
2150 self.pg2.remote_hosts[2].ip4]))
2153 # check reachability and contract intra-epg
2155 allow_intra_class = self.statistics.get_err_counter(
2156 '/err/gbp-policy-mac/allow-intra-sclass')
2159 p = (Ether(src=ep.mac, dst=l['mac']) /
2160 IPv6(dst=l['ip6'], src=ep.ip6.address) /
2161 UDP(sport=1234, dport=1234) /
2164 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
2167 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2168 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[2].ip4)
2169 self.assertEqual(rx[UDP].dport, 48879)
2170 self.assertEqual(rx[VXLAN].gpid, 112)
2171 self.assertEqual(rx[VXLAN].vni, 99)
2172 self.assertTrue(rx[VXLAN].flags.G)
2173 self.assertTrue(rx[VXLAN].flags.Instance)
2174 self.assertTrue(rx[VXLAN].gpflags.A)
2175 self.assertFalse(rx[VXLAN].gpflags.D)
2176 self.assertEqual(rx[IPv6].dst, l['ip6'])
2178 allow_intra_class += NUM_PKTS
2180 self.assert_error_counter_equal(
2181 '/err/gbp-policy-mac/allow-intra-sclass',
2188 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
2190 self.pg2.unconfig_ip4()
2191 self.pg3.unconfig_ip4()
2192 self.pg4.unconfig_ip4()
2194 def test_gbp_contract(self):
2195 """ GBP Contracts """
2200 gt4 = VppIpTable(self, 0)
2201 gt4.add_vpp_config()
2202 gt6 = VppIpTable(self, 0, is_ip6=True)
2203 gt6.add_vpp_config()
2205 rd0 = VppGbpRouteDomain(self, 0, 400, gt4, gt6, None, None)
2207 rd0.add_vpp_config()
2212 bd1 = VppBridgeDomain(self, 1, arp_term=0)
2213 bd2 = VppBridgeDomain(self, 2, arp_term=0)
2215 bd1.add_vpp_config()
2216 bd2.add_vpp_config()
2218 gbd1 = VppGbpBridgeDomain(self, bd1, rd0, self.loop0)
2219 gbd2 = VppGbpBridgeDomain(self, bd2, rd0, self.loop1)
2221 gbd1.add_vpp_config()
2222 gbd2.add_vpp_config()
2225 # 3 EPGs, 2 of which share a BD.
2227 epgs = [VppGbpEndpointGroup(self, 220, 1220, rd0, gbd1,
2229 "10.0.0.128", "2001:10::128"),
2230 VppGbpEndpointGroup(self, 221, 1221, rd0, gbd1,
2232 "10.0.1.128", "2001:10:1::128"),
2233 VppGbpEndpointGroup(self, 222, 1222, rd0, gbd2,
2235 "10.0.2.128", "2001:10:2::128")]
2237 # 4 end-points, 2 in the same subnet, 3 in the same BD
2239 eps = [VppGbpEndpoint(self, self.pg0,
2241 "10.0.0.1", "11.0.0.1",
2242 "2001:10::1", "3001::1"),
2243 VppGbpEndpoint(self, self.pg1,
2245 "10.0.0.2", "11.0.0.2",
2246 "2001:10::2", "3001::2"),
2247 VppGbpEndpoint(self, self.pg2,
2249 "10.0.1.1", "11.0.0.3",
2250 "2001:10:1::1", "3001::3"),
2251 VppGbpEndpoint(self, self.pg3,
2253 "10.0.2.1", "11.0.0.4",
2254 "2001:10:2::1", "3001::4")]
2257 # Config related to each of the EPGs
2260 # IP config on the BVI interfaces
2262 VppIpInterfaceBind(self, epg.bvi, epg.rd.t4).add_vpp_config()
2263 VppIpInterfaceBind(self, epg.bvi, epg.rd.t6).add_vpp_config()
2264 self.vapi.sw_interface_set_mac_address(
2265 epg.bvi.sw_if_index,
2266 self.router_mac.packed)
2268 if_ip4 = VppIpInterfaceAddress(self, epg.bvi, epg.bvi_ip4, 32)
2269 if_ip6 = VppIpInterfaceAddress(self, epg.bvi, epg.bvi_ip6, 128)
2270 if_ip4.add_vpp_config()
2271 if_ip6.add_vpp_config()
2273 # add the BD ARP termination entry for BVI IP
2274 epg.bd_arp_ip4 = VppBridgeDomainArpEntry(self, epg.bd.bd,
2275 str(self.router_mac),
2276 epg.bvi_ip4.address)
2277 epg.bd_arp_ip4.add_vpp_config()
2280 epg.add_vpp_config()
2288 self.logger.info(self.vapi.cli("show gbp endpoint"))
2289 self.logger.info(self.vapi.cli("show interface"))
2290 self.logger.info(self.vapi.cli("show br"))
2293 # Intra epg allowed without contract
2295 pkt_intra_epg_220_to_220 = (Ether(src=self.pg0.remote_mac,
2296 dst=self.pg1.remote_mac) /
2297 IP(src=eps[0].ip4.address,
2298 dst=eps[1].ip4.address) /
2299 UDP(sport=1234, dport=1234) /
2302 self.send_and_expect_bridged(self.pg0,
2303 pkt_intra_epg_220_to_220 * 65,
2306 pkt_intra_epg_220_to_220 = (Ether(src=self.pg0.remote_mac,
2307 dst=self.pg1.remote_mac) /
2308 IPv6(src=eps[0].ip6.address,
2309 dst=eps[1].ip6.address) /
2310 UDP(sport=1234, dport=1234) /
2313 self.send_and_expect_bridged6(self.pg0,
2314 pkt_intra_epg_220_to_220 * 65,
2318 # Inter epg denied without contract
2320 pkt_inter_epg_220_to_221 = (Ether(src=self.pg0.remote_mac,
2321 dst=self.pg2.remote_mac) /
2322 IP(src=eps[0].ip4.address,
2323 dst=eps[2].ip4.address) /
2324 UDP(sport=1234, dport=1234) /
2327 self.send_and_assert_no_replies(self.pg0, pkt_inter_epg_220_to_221)
2330 # A uni-directional contract from EPG 220 -> 221
2332 acl = VppGbpAcl(self)
2333 rule = acl.create_rule(permit_deny=1, proto=17)
2334 rule2 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
2335 rule3 = acl.create_rule(permit_deny=1, proto=1)
2336 acl_index = acl.add_vpp_config([rule, rule2, rule3])
2337 c1 = VppGbpContract(
2338 self, 400, epgs[0].sclass, epgs[1].sclass, acl_index,
2339 [VppGbpContractRule(
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,
2348 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2349 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2351 [ETH_P_IP, ETH_P_IPV6])
2354 self.send_and_expect_bridged(eps[0].itf,
2355 pkt_inter_epg_220_to_221 * 65,
2358 pkt_inter_epg_220_to_222 = (Ether(src=self.pg0.remote_mac,
2359 dst=str(self.router_mac)) /
2360 IP(src=eps[0].ip4.address,
2361 dst=eps[3].ip4.address) /
2362 UDP(sport=1234, dport=1234) /
2364 self.send_and_assert_no_replies(eps[0].itf,
2365 pkt_inter_epg_220_to_222 * 65)
2368 # ping router IP in different BD
2370 pkt_router_ping_220_to_221 = (Ether(src=self.pg0.remote_mac,
2371 dst=str(self.router_mac)) /
2372 IP(src=eps[0].ip4.address,
2373 dst=epgs[1].bvi_ip4.address) /
2374 ICMP(type='echo-request'))
2376 self.send_and_expect(self.pg0, [pkt_router_ping_220_to_221], self.pg0)
2378 pkt_router_ping_220_to_221 = (Ether(src=self.pg0.remote_mac,
2379 dst=str(self.router_mac)) /
2380 IPv6(src=eps[0].ip6.address,
2381 dst=epgs[1].bvi_ip6.address) /
2382 ICMPv6EchoRequest())
2384 self.send_and_expect(self.pg0, [pkt_router_ping_220_to_221], self.pg0)
2387 # contract for the return direction
2389 c2 = VppGbpContract(
2390 self, 400, epgs[1].sclass, epgs[0].sclass, acl_index,
2391 [VppGbpContractRule(
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,
2396 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2397 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2399 [ETH_P_IP, ETH_P_IPV6])
2402 self.send_and_expect_bridged(eps[0].itf,
2403 pkt_inter_epg_220_to_221 * 65,
2405 pkt_inter_epg_221_to_220 = (Ether(src=self.pg2.remote_mac,
2406 dst=self.pg0.remote_mac) /
2407 IP(src=eps[2].ip4.address,
2408 dst=eps[0].ip4.address) /
2409 UDP(sport=1234, dport=1234) /
2411 self.send_and_expect_bridged(eps[2].itf,
2412 pkt_inter_epg_221_to_220 * 65,
2414 pkt_inter_epg_221_to_220 = (Ether(src=self.pg2.remote_mac,
2415 dst=str(self.router_mac)) /
2416 IP(src=eps[2].ip4.address,
2417 dst=eps[0].ip4.address) /
2418 UDP(sport=1234, dport=1234) /
2420 self.send_and_expect_routed(eps[2].itf,
2421 pkt_inter_epg_221_to_220 * 65,
2423 str(self.router_mac))
2424 pkt_inter_epg_221_to_220 = (Ether(src=self.pg2.remote_mac,
2425 dst=str(self.router_mac)) /
2426 IPv6(src=eps[2].ip6.address,
2427 dst=eps[0].ip6.address) /
2428 UDP(sport=1234, dport=1234) /
2430 self.send_and_expect_routed6(eps[2].itf,
2431 pkt_inter_epg_221_to_220 * 65,
2433 str(self.router_mac))
2436 # contract between 220 and 222 uni-direction
2438 c3 = VppGbpContract(
2439 self, 400, epgs[0].sclass, epgs[2].sclass, acl_index,
2440 [VppGbpContractRule(
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,
2445 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2446 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2448 [ETH_P_IP, ETH_P_IPV6])
2451 self.send_and_expect(eps[0].itf,
2452 pkt_inter_epg_220_to_222 * 65,
2455 c3.remove_vpp_config()
2456 c1.remove_vpp_config()
2457 c2.remove_vpp_config()
2458 acl.remove_vpp_config()
2460 def test_gbp_bd_drop_flags(self):
2461 """ GBP BD drop flags """
2466 gt4 = VppIpTable(self, 1)
2467 gt4.add_vpp_config()
2468 gt6 = VppIpTable(self, 1, is_ip6=True)
2469 gt6.add_vpp_config()
2471 rd1 = VppGbpRouteDomain(self, 1, 401, gt4, gt6)
2472 rd1.add_vpp_config()
2475 # a GBP bridge domain with a BVI only
2477 bd1 = VppBridgeDomain(self, 1)
2478 bd1.add_vpp_config()
2480 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0,
2482 uu_drop=True, bm_drop=True)
2483 gbd1.add_vpp_config()
2485 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2486 self.logger.info(self.vapi.cli("sh gbp bridge"))
2488 # ... and has a /32 applied
2489 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2490 ip_addr.add_vpp_config()
2493 # The Endpoint-group
2495 epg_220 = VppGbpEndpointGroup(self, 220, 112, rd1, gbd1,
2499 VppGbpEndpointRetention(2))
2500 epg_220.add_vpp_config()
2502 ep = VppGbpEndpoint(self, self.pg0,
2504 "10.0.0.127", "11.0.0.127",
2505 "2001:10::1", "3001::1")
2509 # send UU/BM packet from the local EP with UU drop and BM drop enabled
2512 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2513 self.logger.info(self.vapi.cli("sh gbp bridge"))
2514 p_uu = (Ether(src=ep.mac, dst="00:11:11:11:11:11") /
2515 IP(dst="10.0.0.133", src=ep.ip4.address) /
2516 UDP(sport=1234, dport=1234) /
2518 self.send_and_assert_no_replies(ep.itf, [p_uu])
2520 p_bm = (Ether(src=ep.mac, dst="ff:ff:ff:ff:ff:ff") /
2521 IP(dst="10.0.0.133", src=ep.ip4.address) /
2522 UDP(sport=1234, dport=1234) /
2524 self.send_and_assert_no_replies(ep.itf, [p_bm])
2526 self.pg3.unconfig_ip4()
2528 self.logger.info(self.vapi.cli("sh int"))
2530 def test_gbp_bd_arp_flags(self):
2531 """ GBP BD arp flags """
2536 gt4 = VppIpTable(self, 1)
2537 gt4.add_vpp_config()
2538 gt6 = VppIpTable(self, 1, is_ip6=True)
2539 gt6.add_vpp_config()
2541 rd1 = VppGbpRouteDomain(self, 1, 401, gt4, gt6)
2542 rd1.add_vpp_config()
2545 # Pg4 hosts the IP6 UU-flood VXLAN tunnel
2547 self.pg4.config_ip4()
2548 self.pg4.resolve_arp()
2551 # Add a mcast destination VXLAN-GBP tunnel for B&M traffic
2553 tun_uu = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
2556 tun_uu.add_vpp_config()
2559 # a GBP bridge domain with a BVI and a UU-flood interface
2561 bd1 = VppBridgeDomain(self, 1)
2562 bd1.add_vpp_config()
2564 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0,
2567 gbd1.add_vpp_config()
2569 # ... and has a /32 applied
2570 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2571 ip_addr.add_vpp_config()
2574 # The Endpoint-group
2576 epg_220 = VppGbpEndpointGroup(self, 220, 112, rd1, gbd1,
2580 VppGbpEndpointRetention(2))
2581 epg_220.add_vpp_config()
2583 ep = VppGbpEndpoint(self, self.pg0,
2585 "10.0.0.127", "11.0.0.127",
2586 "2001:10::1", "3001::1")
2590 # send ARP packet from the local EP expect it on the uu interface
2592 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2593 self.logger.info(self.vapi.cli("sh gbp bridge"))
2594 p_arp = (Ether(src=ep.mac, dst="ff:ff:ff:ff:ff:ff") /
2596 psrc=ep.ip4.address, pdst="10.0.0.99",
2598 hwdst="ff:ff:ff:ff:ff:ff"))
2599 self.send_and_expect(ep.itf, [p_arp], self.pg4)
2601 self.pg4.unconfig_ip4()
2603 def test_gbp_learn_vlan_l2(self):
2604 """ GBP L2 Endpoint w/ VLANs"""
2606 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
2607 learnt = [{'mac': '00:00:11:11:11:01',
2609 'ip6': '2001:10::2'},
2610 {'mac': '00:00:11:11:11:02',
2612 'ip6': '2001:10::3'}]
2617 gt4 = VppIpTable(self, 1)
2618 gt4.add_vpp_config()
2619 gt6 = VppIpTable(self, 1, is_ip6=True)
2620 gt6.add_vpp_config()
2622 rd1 = VppGbpRouteDomain(self, 1, 401, gt4, gt6)
2623 rd1.add_vpp_config()
2626 # Pg2 hosts the vxlan tunnel, hosts on pg2 to act as TEPs
2628 self.pg2.config_ip4()
2629 self.pg2.resolve_arp()
2630 self.pg2.generate_remote_hosts(4)
2631 self.pg2.configure_ipv4_neighbors()
2632 self.pg3.config_ip4()
2633 self.pg3.resolve_arp()
2636 # The EP will be on a vlan sub-interface
2638 vlan_11 = VppDot1QSubint(self, self.pg0, 11)
2640 self.vapi.l2_interface_vlan_tag_rewrite(
2641 sw_if_index=vlan_11.sw_if_index, vtr_op=L2_VTR_OP.L2_POP_1,
2644 bd_uu_fwd = VppVxlanGbpTunnel(self, self.pg3.local_ip4,
2645 self.pg3.remote_ip4, 116)
2646 bd_uu_fwd.add_vpp_config()
2649 # a GBP bridge domain with a BVI and a UU-flood interface
2650 # The BD is marked as do not learn, so no endpoints are ever
2651 # learnt in this BD.
2653 bd1 = VppBridgeDomain(self, 1)
2654 bd1.add_vpp_config()
2655 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0, bd_uu_fwd,
2657 gbd1.add_vpp_config()
2659 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2660 self.logger.info(self.vapi.cli("sh gbp bridge"))
2662 # ... and has a /32 applied
2663 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2664 ip_addr.add_vpp_config()
2667 # The Endpoint-group in which we are learning endpoints
2669 epg_220 = VppGbpEndpointGroup(self, 220, 441, rd1, gbd1,
2673 VppGbpEndpointRetention(2))
2674 epg_220.add_vpp_config()
2677 # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
2680 vx_tun_l2_1 = VppGbpVxlanTunnel(
2681 self, 99, bd1.bd_id,
2682 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L2,
2684 vx_tun_l2_1.add_vpp_config()
2687 # A static endpoint that the learnt endpoints are trying to
2690 ep = VppGbpEndpoint(self, vlan_11,
2692 "10.0.0.127", "11.0.0.127",
2693 "2001:10::1", "3001::1")
2696 self.assertTrue(find_route(self, ep.ip4.address, 32, table_id=1))
2699 # Send to the static EP
2701 for ii, l in enumerate(learnt):
2702 # a packet with an sclass from a known EPG
2703 # arriving on an unknown TEP
2704 p = (Ether(src=self.pg2.remote_mac,
2705 dst=self.pg2.local_mac) /
2706 IP(src=self.pg2.remote_hosts[1].ip4,
2707 dst=self.pg2.local_ip4) /
2708 UDP(sport=1234, dport=48879) /
2709 VXLAN(vni=99, gpid=441, flags=0x88) /
2710 Ether(src=l['mac'], dst=ep.mac) /
2711 IP(src=l['ip'], dst=ep.ip4.address) /
2712 UDP(sport=1234, dport=1234) /
2715 rxs = self.send_and_expect(self.pg2, [p], self.pg0)
2718 # packet to EP has the EP's vlan tag
2721 self.assertEqual(rx[Dot1Q].vlan, 11)
2724 # the EP is not learnt since the BD setting prevents it
2727 self.assertFalse(find_gbp_endpoint(self,
2728 vx_tun_l2_1.sw_if_index,
2730 self.assertEqual(INDEX_INVALID,
2731 find_vxlan_gbp_tunnel(
2734 self.pg2.remote_hosts[1].ip4,
2737 self.assertEqual(len(self.vapi.gbp_endpoint_dump()), 1)
2741 # we didn't learn the remotes so they are sent to the UU-fwd
2744 p = (Ether(src=ep.mac, dst=l['mac']) /
2746 IP(dst=l['ip'], src=ep.ip4.address) /
2747 UDP(sport=1234, dport=1234) /
2750 rxs = self.send_and_expect(self.pg0, p * 17, self.pg3)
2753 self.assertEqual(rx[IP].src, self.pg3.local_ip4)
2754 self.assertEqual(rx[IP].dst, self.pg3.remote_ip4)
2755 self.assertEqual(rx[UDP].dport, 48879)
2756 # the UDP source port is a random value for hashing
2757 self.assertEqual(rx[VXLAN].gpid, 441)
2758 self.assertEqual(rx[VXLAN].vni, 116)
2759 self.assertTrue(rx[VXLAN].flags.G)
2760 self.assertTrue(rx[VXLAN].flags.Instance)
2761 self.assertFalse(rx[VXLAN].gpflags.A)
2762 self.assertFalse(rx[VXLAN].gpflags.D)
2764 self.pg2.unconfig_ip4()
2765 self.pg3.unconfig_ip4()
2767 def test_gbp_learn_l3(self):
2768 """ GBP L3 Endpoint Learning """
2770 self.vapi.cli("set logging class gbp level debug")
2772 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
2773 routed_dst_mac = "00:0c:0c:0c:0c:0c"
2774 routed_src_mac = "00:22:bd:f8:19:ff"
2776 learnt = [{'mac': '00:00:11:11:11:02',
2778 'ip6': '2001:10::2'},
2779 {'mac': '00:00:11:11:11:03',
2781 'ip6': '2001:10::3'}]
2786 t4 = VppIpTable(self, 1)
2788 t6 = VppIpTable(self, 1, True)
2791 tun_ip4_uu = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
2792 self.pg4.remote_ip4, 114)
2793 tun_ip6_uu = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
2794 self.pg4.remote_ip4, 116)
2795 tun_ip4_uu.add_vpp_config()
2796 tun_ip6_uu.add_vpp_config()
2798 rd1 = VppGbpRouteDomain(self, 2, 401, t4, t6, tun_ip4_uu, tun_ip6_uu)
2799 rd1.add_vpp_config()
2801 self.loop0.set_mac(self.router_mac)
2804 # Bind the BVI to the RD
2806 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
2807 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
2810 # Pg2 hosts the vxlan tunnel
2811 # hosts on pg2 to act as TEPs
2815 self.pg2.config_ip4()
2816 self.pg2.resolve_arp()
2817 self.pg2.generate_remote_hosts(4)
2818 self.pg2.configure_ipv4_neighbors()
2819 self.pg3.config_ip4()
2820 self.pg3.resolve_arp()
2821 self.pg4.config_ip4()
2822 self.pg4.resolve_arp()
2825 # a GBP bridge domain with a BVI and a UU-flood interface
2827 bd1 = VppBridgeDomain(self, 1)
2828 bd1.add_vpp_config()
2829 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0, self.pg3)
2830 gbd1.add_vpp_config()
2832 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2833 self.logger.info(self.vapi.cli("sh gbp bridge"))
2834 self.logger.info(self.vapi.cli("sh gbp route"))
2836 # ... and has a /32 and /128 applied
2837 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2838 ip4_addr.add_vpp_config()
2839 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 128)
2840 ip6_addr.add_vpp_config()
2843 # The Endpoint-group in which we are learning endpoints
2845 epg_220 = VppGbpEndpointGroup(self, 220, 441, rd1, gbd1,
2849 VppGbpEndpointRetention(2))
2850 epg_220.add_vpp_config()
2853 # The VXLAN GBP tunnel is in L3 mode with learning enabled
2855 vx_tun_l3 = VppGbpVxlanTunnel(
2856 self, 101, rd1.rd_id,
2857 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
2859 vx_tun_l3.add_vpp_config()
2862 # A static endpoint that the learnt endpoints are trying to
2865 ep = VppGbpEndpoint(self, self.pg0,
2867 "10.0.0.127", "11.0.0.127",
2868 "2001:10::1", "3001::1")
2872 # learn some remote IPv4 EPs
2874 for ii, l in enumerate(learnt):
2875 # a packet with an sclass from a known EPG
2876 # arriving on an unknown TEP
2877 p = (Ether(src=self.pg2.remote_mac,
2878 dst=self.pg2.local_mac) /
2879 IP(src=self.pg2.remote_hosts[1].ip4,
2880 dst=self.pg2.local_ip4) /
2881 UDP(sport=1234, dport=48879) /
2882 VXLAN(vni=101, gpid=441, flags=0x88) /
2883 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2884 IP(src=l['ip'], dst=ep.ip4.address) /
2885 UDP(sport=1234, dport=1234) /
2888 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2891 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2894 self.pg2.remote_hosts[1].ip4,
2896 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2898 # endpoint learnt via the parent GBP-vxlan interface
2899 self.assertTrue(find_gbp_endpoint(self,
2900 vx_tun_l3._sw_if_index,
2904 # Static IPv4 EP replies to learnt
2907 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2908 IP(dst=l['ip'], src=ep.ip4.address) /
2909 UDP(sport=1234, dport=1234) /
2912 rxs = self.send_and_expect(self.pg0, p * 1, self.pg2)
2915 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2916 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2917 self.assertEqual(rx[UDP].dport, 48879)
2918 # the UDP source port is a random value for hashing
2919 self.assertEqual(rx[VXLAN].gpid, 441)
2920 self.assertEqual(rx[VXLAN].vni, 101)
2921 self.assertTrue(rx[VXLAN].flags.G)
2922 self.assertTrue(rx[VXLAN].flags.Instance)
2923 self.assertTrue(rx[VXLAN].gpflags.A)
2924 self.assertFalse(rx[VXLAN].gpflags.D)
2926 inner = rx[VXLAN].payload
2928 self.assertEqual(inner[Ether].src, routed_src_mac)
2929 self.assertEqual(inner[Ether].dst, routed_dst_mac)
2930 self.assertEqual(inner[IP].src, ep.ip4.address)
2931 self.assertEqual(inner[IP].dst, l['ip'])
2934 self.assertFalse(find_gbp_endpoint(self,
2939 # learn some remote IPv6 EPs
2941 for ii, l in enumerate(learnt):
2942 # a packet with an sclass from a known EPG
2943 # arriving on an unknown TEP
2944 p = (Ether(src=self.pg2.remote_mac,
2945 dst=self.pg2.local_mac) /
2946 IP(src=self.pg2.remote_hosts[1].ip4,
2947 dst=self.pg2.local_ip4) /
2948 UDP(sport=1234, dport=48879) /
2949 VXLAN(vni=101, gpid=441, flags=0x88) /
2950 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2951 IPv6(src=l['ip6'], dst=ep.ip6.address) /
2952 UDP(sport=1234, dport=1234) /
2955 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2958 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2961 self.pg2.remote_hosts[1].ip4,
2963 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2965 self.logger.info(self.vapi.cli("show gbp bridge"))
2966 self.logger.info(self.vapi.cli("show vxlan-gbp tunnel"))
2967 self.logger.info(self.vapi.cli("show gbp vxlan"))
2968 self.logger.info(self.vapi.cli("show int addr"))
2970 # endpoint learnt via the TEP
2971 self.assertTrue(find_gbp_endpoint(self, ip=l['ip6']))
2973 self.logger.info(self.vapi.cli("show gbp endpoint"))
2974 self.logger.info(self.vapi.cli("show ip fib index 1 %s" % l['ip']))
2977 # Static EP replies to learnt
2980 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2981 IPv6(dst=l['ip6'], src=ep.ip6.address) /
2982 UDP(sport=1234, dport=1234) /
2985 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
2988 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2989 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2990 self.assertEqual(rx[UDP].dport, 48879)
2991 # the UDP source port is a random value for hashing
2992 self.assertEqual(rx[VXLAN].gpid, 441)
2993 self.assertEqual(rx[VXLAN].vni, 101)
2994 self.assertTrue(rx[VXLAN].flags.G)
2995 self.assertTrue(rx[VXLAN].flags.Instance)
2996 self.assertTrue(rx[VXLAN].gpflags.A)
2997 self.assertFalse(rx[VXLAN].gpflags.D)
2999 inner = rx[VXLAN].payload
3001 self.assertEqual(inner[Ether].src, routed_src_mac)
3002 self.assertEqual(inner[Ether].dst, routed_dst_mac)
3003 self.assertEqual(inner[IPv6].src, ep.ip6.address)
3004 self.assertEqual(inner[IPv6].dst, l['ip6'])
3006 self.logger.info(self.vapi.cli("sh gbp endpoint"))
3008 self.wait_for_ep_timeout(ip=l['ip'])
3011 # Static sends to unknown EP with no route
3013 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
3014 IP(dst="10.0.0.99", src=ep.ip4.address) /
3015 UDP(sport=1234, dport=1234) /
3018 self.send_and_assert_no_replies(self.pg0, [p])
3021 # Add a route to static EP's v4 and v6 subnet
3023 se_10_24 = VppGbpSubnet(
3024 self, rd1, "10.0.0.0", 24,
3025 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT)
3026 se_10_24.add_vpp_config()
3029 # static pings router
3031 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
3032 IP(dst=epg_220.bvi_ip4.address, src=ep.ip4.address) /
3033 UDP(sport=1234, dport=1234) /
3036 self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg0)
3038 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
3039 IPv6(dst=epg_220.bvi_ip6.address, src=ep.ip6.address) /
3040 UDP(sport=1234, dport=1234) /
3043 self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg0)
3046 # packets to address in the subnet are sent on the uu-fwd
3048 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
3049 IP(dst="10.0.0.99", src=ep.ip4.address) /
3050 UDP(sport=1234, dport=1234) /
3053 rxs = self.send_and_expect(self.pg0, [p], self.pg4)
3055 self.assertEqual(rx[IP].src, self.pg4.local_ip4)
3056 self.assertEqual(rx[IP].dst, self.pg4.remote_ip4)
3057 self.assertEqual(rx[UDP].dport, 48879)
3058 # the UDP source port is a random value for hashing
3059 self.assertEqual(rx[VXLAN].gpid, 441)
3060 self.assertEqual(rx[VXLAN].vni, 114)
3061 self.assertTrue(rx[VXLAN].flags.G)
3062 self.assertTrue(rx[VXLAN].flags.Instance)
3063 # policy is not applied to packets sent to the uu-fwd interfaces
3064 self.assertFalse(rx[VXLAN].gpflags.A)
3065 self.assertFalse(rx[VXLAN].gpflags.D)
3068 # learn some remote IPv4 EPs
3070 for ii, l in enumerate(learnt):
3071 # a packet with an sclass from a known EPG
3072 # arriving on an unknown TEP
3073 p = (Ether(src=self.pg2.remote_mac,
3074 dst=self.pg2.local_mac) /
3075 IP(src=self.pg2.remote_hosts[2].ip4,
3076 dst=self.pg2.local_ip4) /
3077 UDP(sport=1234, dport=48879) /
3078 VXLAN(vni=101, gpid=441, flags=0x88) /
3079 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
3080 IP(src=l['ip'], dst=ep.ip4.address) /
3081 UDP(sport=1234, dport=1234) /
3084 rx = self.send_and_expect(self.pg2, [p], self.pg0)
3087 tep1_sw_if_index = find_vxlan_gbp_tunnel(
3090 self.pg2.remote_hosts[2].ip4,
3092 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
3094 # endpoint learnt via the parent GBP-vxlan interface
3095 self.assertTrue(find_gbp_endpoint(self,
3096 vx_tun_l3._sw_if_index,
3100 # Add a remote endpoint from the API
3102 rep_88 = VppGbpEndpoint(self, vx_tun_l3,
3104 "10.0.0.88", "11.0.0.88",
3105 "2001:10::88", "3001::88",
3106 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
3108 self.pg2.remote_hosts[2].ip4,
3110 rep_88.add_vpp_config()
3113 # Add a remote endpoint from the API that matches an existing one
3114 # this is a lower priority, hence the packet is sent to the DP leanrt
3117 rep_2 = VppGbpEndpoint(self, vx_tun_l3,
3119 learnt[0]['ip'], "11.0.0.101",
3120 learnt[0]['ip6'], "3001::101",
3121 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
3123 self.pg2.remote_hosts[1].ip4,
3125 rep_2.add_vpp_config()
3128 # Add a route to the learned EP's v4 subnet
3129 # packets should be send on the v4/v6 uu=fwd interface resp.
3131 se_10_1_24 = VppGbpSubnet(
3132 self, rd1, "10.0.1.0", 24,
3133 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT)
3134 se_10_1_24.add_vpp_config()
3136 self.logger.info(self.vapi.cli("show gbp endpoint"))
3138 ips = ["10.0.0.88", learnt[0]['ip']]
3140 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
3141 IP(dst=ip, src=ep.ip4.address) /
3142 UDP(sport=1234, dport=1234) /
3145 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
3148 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
3149 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[2].ip4)
3150 self.assertEqual(rx[UDP].dport, 48879)
3151 # the UDP source port is a random value for hashing
3152 self.assertEqual(rx[VXLAN].gpid, 441)
3153 self.assertEqual(rx[VXLAN].vni, 101)
3154 self.assertTrue(rx[VXLAN].flags.G)
3155 self.assertTrue(rx[VXLAN].flags.Instance)
3156 self.assertTrue(rx[VXLAN].gpflags.A)
3157 self.assertFalse(rx[VXLAN].gpflags.D)
3159 inner = rx[VXLAN].payload
3161 self.assertEqual(inner[Ether].src, routed_src_mac)
3162 self.assertEqual(inner[Ether].dst, routed_dst_mac)
3163 self.assertEqual(inner[IP].src, ep.ip4.address)
3164 self.assertEqual(inner[IP].dst, ip)
3167 # remove the API remote EPs, only API sourced is gone, the DP
3168 # learnt one remains
3170 rep_88.remove_vpp_config()
3171 rep_2.remove_vpp_config()
3173 self.assertTrue(find_gbp_endpoint(self, ip=rep_2.ip4.address))
3175 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
3176 IP(src=ep.ip4.address, dst=rep_2.ip4.address) /
3177 UDP(sport=1234, dport=1234) /
3179 rxs = self.send_and_expect(self.pg0, [p], self.pg2)
3181 self.assertFalse(find_gbp_endpoint(self, ip=rep_88.ip4.address))
3183 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
3184 IP(src=ep.ip4.address, dst=rep_88.ip4.address) /
3185 UDP(sport=1234, dport=1234) /
3187 rxs = self.send_and_expect(self.pg0, [p], self.pg4)
3190 # to appease the testcase we cannot have the registered EP still
3191 # present (because it's DP learnt) when the TC ends so wait until
3194 self.wait_for_ep_timeout(ip=rep_88.ip4.address)
3195 self.wait_for_ep_timeout(ip=rep_2.ip4.address)
3198 # Same as above, learn a remote EP via CP and DP
3199 # this time remove the DP one first. expect the CP data to remain
3201 rep_3 = VppGbpEndpoint(self, vx_tun_l3,
3203 "10.0.1.4", "11.0.0.103",
3204 "2001::10:3", "3001::103",
3205 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
3207 self.pg2.remote_hosts[1].ip4,
3209 rep_3.add_vpp_config()
3211 p = (Ether(src=self.pg2.remote_mac,
3212 dst=self.pg2.local_mac) /
3213 IP(src=self.pg2.remote_hosts[2].ip4,
3214 dst=self.pg2.local_ip4) /
3215 UDP(sport=1234, dport=48879) /
3216 VXLAN(vni=101, gpid=441, flags=0x88) /
3217 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
3218 IP(src="10.0.1.4", dst=ep.ip4.address) /
3219 UDP(sport=1234, dport=1234) /
3221 rxs = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
3223 self.assertTrue(find_gbp_endpoint(self,
3224 vx_tun_l3._sw_if_index,
3225 ip=rep_3.ip4.address,
3226 tep=[self.pg2.local_ip4,
3227 self.pg2.remote_hosts[2].ip4]))
3229 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
3230 IP(dst="10.0.1.4", src=ep.ip4.address) /
3231 UDP(sport=1234, dport=1234) /
3233 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
3235 # host 2 is the DP learned TEP
3237 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
3238 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[2].ip4)
3240 self.wait_for_ep_timeout(ip=rep_3.ip4.address,
3241 tep=[self.pg2.local_ip4,
3242 self.pg2.remote_hosts[2].ip4])
3244 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
3246 # host 1 is the CP learned TEP
3248 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
3249 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
3252 # shutdown with learnt endpoint present
3254 p = (Ether(src=self.pg2.remote_mac,
3255 dst=self.pg2.local_mac) /
3256 IP(src=self.pg2.remote_hosts[1].ip4,
3257 dst=self.pg2.local_ip4) /
3258 UDP(sport=1234, dport=48879) /
3259 VXLAN(vni=101, gpid=441, flags=0x88) /
3260 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
3261 IP(src=learnt[1]['ip'], dst=ep.ip4.address) /
3262 UDP(sport=1234, dport=1234) /
3265 rx = self.send_and_expect(self.pg2, [p], self.pg0)
3267 # endpoint learnt via the parent GBP-vxlan interface
3268 self.assertTrue(find_gbp_endpoint(self,
3269 vx_tun_l3._sw_if_index,
3274 # remote endpoint becomes local
3276 self.pg2.unconfig_ip4()
3277 self.pg3.unconfig_ip4()
3278 self.pg4.unconfig_ip4()
3280 def test_gbp_redirect(self):
3281 """ GBP Endpoint Redirect """
3283 self.vapi.cli("set logging class gbp level debug")
3285 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
3286 routed_dst_mac = "00:0c:0c:0c:0c:0c"
3287 routed_src_mac = "00:22:bd:f8:19:ff"
3289 learnt = [{'mac': '00:00:11:11:11:02',
3291 'ip6': '2001:10::2'},
3292 {'mac': '00:00:11:11:11:03',
3294 'ip6': '2001:10::3'}]
3299 t4 = VppIpTable(self, 1)
3301 t6 = VppIpTable(self, 1, True)
3304 rd1 = VppGbpRouteDomain(self, 2, 402, t4, t6)
3305 rd1.add_vpp_config()
3307 self.loop0.set_mac(self.router_mac)
3310 # Bind the BVI to the RD
3312 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
3313 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
3316 # Pg7 hosts a BD's UU-fwd
3318 self.pg7.config_ip4()
3319 self.pg7.resolve_arp()
3322 # a GBP bridge domains for the EPs
3324 bd1 = VppBridgeDomain(self, 1)
3325 bd1.add_vpp_config()
3326 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0)
3327 gbd1.add_vpp_config()
3329 bd2 = VppBridgeDomain(self, 2)
3330 bd2.add_vpp_config()
3331 gbd2 = VppGbpBridgeDomain(self, bd2, rd1, self.loop1)
3332 gbd2.add_vpp_config()
3334 # ... and has a /32 and /128 applied
3335 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
3336 ip4_addr.add_vpp_config()
3337 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 128)
3338 ip6_addr.add_vpp_config()
3339 ip4_addr = VppIpInterfaceAddress(self, gbd2.bvi, "10.0.1.128", 32)
3340 ip4_addr.add_vpp_config()
3341 ip6_addr = VppIpInterfaceAddress(self, gbd2.bvi, "2001:11::128", 128)
3342 ip6_addr.add_vpp_config()
3345 # The Endpoint-groups in which we are learning endpoints
3347 epg_220 = VppGbpEndpointGroup(self, 220, 440, rd1, gbd1,
3351 VppGbpEndpointRetention(2))
3352 epg_220.add_vpp_config()
3353 epg_221 = VppGbpEndpointGroup(self, 221, 441, rd1, gbd2,
3357 VppGbpEndpointRetention(2))
3358 epg_221.add_vpp_config()
3359 epg_222 = VppGbpEndpointGroup(self, 222, 442, rd1, gbd1,
3363 VppGbpEndpointRetention(2))
3364 epg_222.add_vpp_config()
3367 # a GBP bridge domains for the SEPs
3369 bd_uu1 = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
3370 self.pg7.remote_ip4, 116)
3371 bd_uu1.add_vpp_config()
3372 bd_uu2 = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
3373 self.pg7.remote_ip4, 117)
3374 bd_uu2.add_vpp_config()
3376 bd3 = VppBridgeDomain(self, 3)
3377 bd3.add_vpp_config()
3378 gbd3 = VppGbpBridgeDomain(self, bd3, rd1, self.loop2,
3379 bd_uu1, learn=False)
3380 gbd3.add_vpp_config()
3381 bd4 = VppBridgeDomain(self, 4)
3382 bd4.add_vpp_config()
3383 gbd4 = VppGbpBridgeDomain(self, bd4, rd1, self.loop3,
3384 bd_uu2, learn=False)
3385 gbd4.add_vpp_config()
3388 # EPGs in which the service endpoints exist
3390 epg_320 = VppGbpEndpointGroup(self, 320, 550, rd1, gbd3,
3394 VppGbpEndpointRetention(2))
3395 epg_320.add_vpp_config()
3396 epg_321 = VppGbpEndpointGroup(self, 321, 551, rd1, gbd4,
3400 VppGbpEndpointRetention(2))
3401 epg_321.add_vpp_config()
3404 # three local endpoints
3406 ep1 = VppGbpEndpoint(self, self.pg0,
3408 "10.0.0.1", "11.0.0.1",
3409 "2001:10::1", "3001:10::1")
3410 ep1.add_vpp_config()
3411 ep2 = VppGbpEndpoint(self, self.pg1,
3413 "10.0.1.1", "11.0.1.1",
3414 "2001:11::1", "3001:11::1")
3415 ep2.add_vpp_config()
3416 ep3 = VppGbpEndpoint(self, self.pg2,
3418 "10.0.2.2", "11.0.2.2",
3419 "2001:12::1", "3001:12::1")
3420 ep3.add_vpp_config()
3425 sep1 = VppGbpEndpoint(self, self.pg3,
3427 "12.0.0.1", "13.0.0.1",
3428 "4001:10::1", "5001:10::1")
3429 sep1.add_vpp_config()
3430 sep2 = VppGbpEndpoint(self, self.pg4,
3432 "12.0.0.2", "13.0.0.2",
3433 "4001:10::2", "5001:10::2")
3434 sep2.add_vpp_config()
3435 sep3 = VppGbpEndpoint(self, self.pg5,
3437 "12.0.1.1", "13.0.1.1",
3438 "4001:11::1", "5001:11::1")
3439 sep3.add_vpp_config()
3440 # this EP is not installed immediately
3441 sep4 = VppGbpEndpoint(self, self.pg6,
3443 "12.0.1.2", "13.0.1.2",
3444 "4001:11::2", "5001:11::2")
3447 # an L2 switch packet between local EPs in different EPGs
3448 # different dest ports on each so the are LB hashed differently
3450 p4 = [(Ether(src=ep1.mac, dst=ep3.mac) /
3451 IP(src=ep1.ip4.address, dst=ep3.ip4.address) /
3452 UDP(sport=1234, dport=1234) /
3454 (Ether(src=ep3.mac, dst=ep1.mac) /
3455 IP(src=ep3.ip4.address, dst=ep1.ip4.address) /
3456 UDP(sport=1234, dport=1234) /
3458 p6 = [(Ether(src=ep1.mac, dst=ep3.mac) /
3459 IPv6(src=ep1.ip6.address, dst=ep3.ip6.address) /
3460 UDP(sport=1234, dport=1234) /
3462 (Ether(src=ep3.mac, dst=ep1.mac) /
3463 IPv6(src=ep3.ip6.address, dst=ep1.ip6.address) /
3464 UDP(sport=1234, dport=1230) /
3467 # should be dropped since no contract yet
3468 self.send_and_assert_no_replies(self.pg0, [p4[0]])
3469 self.send_and_assert_no_replies(self.pg0, [p6[0]])
3472 # Add a contract with a rule to load-balance redirect via SEP1 and SEP2
3473 # one of the next-hops is via an EP that is not known
3475 acl = VppGbpAcl(self)
3476 rule4 = acl.create_rule(permit_deny=1, proto=17)
3477 rule6 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
3478 acl_index = acl.add_vpp_config([rule4, rule6])
3481 # test the src-ip hash mode
3483 c1 = VppGbpContract(
3484 self, 402, epg_220.sclass, epg_222.sclass, acl_index,
3485 [VppGbpContractRule(
3486 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3487 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3488 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3489 sep1.ip4, sep1.epg.rd),
3490 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3491 sep2.ip4, sep2.epg.rd)]),
3493 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3494 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3495 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3496 sep3.ip6, sep3.epg.rd),
3497 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3498 sep4.ip6, sep4.epg.rd)])],
3499 [ETH_P_IP, ETH_P_IPV6])
3502 c2 = VppGbpContract(
3503 self, 402, epg_222.sclass, epg_220.sclass, acl_index,
3504 [VppGbpContractRule(
3505 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3506 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3507 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3508 sep1.ip4, sep1.epg.rd),
3509 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3510 sep2.ip4, sep2.epg.rd)]),
3512 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3513 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3514 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3515 sep3.ip6, sep3.epg.rd),
3516 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3517 sep4.ip6, sep4.epg.rd)])],
3518 [ETH_P_IP, ETH_P_IPV6])
3522 # send again with the contract preset, now packets arrive
3523 # at SEP1 or SEP2 depending on the hashing
3525 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3528 self.assertEqual(rx[Ether].src, routed_src_mac)
3529 self.assertEqual(rx[Ether].dst, sep1.mac)
3530 self.assertEqual(rx[IP].src, ep1.ip4.address)
3531 self.assertEqual(rx[IP].dst, ep3.ip4.address)
3533 rxs = self.send_and_expect(self.pg2, p4[1] * 17, sep2.itf)
3536 self.assertEqual(rx[Ether].src, routed_src_mac)
3537 self.assertEqual(rx[Ether].dst, sep2.mac)
3538 self.assertEqual(rx[IP].src, ep3.ip4.address)
3539 self.assertEqual(rx[IP].dst, ep1.ip4.address)
3541 rxs = self.send_and_expect(self.pg0, p6[0] * 17, self.pg7)
3544 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3545 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3546 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3547 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
3548 self.assertEqual(rx[VXLAN].vni, 117)
3549 self.assertTrue(rx[VXLAN].flags.G)
3550 self.assertTrue(rx[VXLAN].flags.Instance)
3551 # redirect policy has been applied
3552 self.assertTrue(rx[VXLAN].gpflags.A)
3553 self.assertFalse(rx[VXLAN].gpflags.D)
3555 inner = rx[VXLAN].payload
3557 self.assertEqual(inner[Ether].src, routed_src_mac)
3558 self.assertEqual(inner[Ether].dst, sep4.mac)
3559 self.assertEqual(inner[IPv6].src, ep1.ip6.address)
3560 self.assertEqual(inner[IPv6].dst, ep3.ip6.address)
3562 rxs = self.send_and_expect(self.pg2, p6[1] * 17, sep3.itf)
3565 self.assertEqual(rx[Ether].src, routed_src_mac)
3566 self.assertEqual(rx[Ether].dst, sep3.mac)
3567 self.assertEqual(rx[IPv6].src, ep3.ip6.address)
3568 self.assertEqual(rx[IPv6].dst, ep1.ip6.address)
3571 # programme the unknown EP
3573 sep4.add_vpp_config()
3575 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep4.itf)
3578 self.assertEqual(rx[Ether].src, routed_src_mac)
3579 self.assertEqual(rx[Ether].dst, sep4.mac)
3580 self.assertEqual(rx[IPv6].src, ep1.ip6.address)
3581 self.assertEqual(rx[IPv6].dst, ep3.ip6.address)
3584 # and revert back to unprogrammed
3586 sep4.remove_vpp_config()
3588 rxs = self.send_and_expect(self.pg0, p6[0] * 17, self.pg7)
3591 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3592 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3593 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3594 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
3595 self.assertEqual(rx[VXLAN].vni, 117)
3596 self.assertTrue(rx[VXLAN].flags.G)
3597 self.assertTrue(rx[VXLAN].flags.Instance)
3598 # redirect policy has been applied
3599 self.assertTrue(rx[VXLAN].gpflags.A)
3600 self.assertFalse(rx[VXLAN].gpflags.D)
3602 inner = rx[VXLAN].payload
3604 self.assertEqual(inner[Ether].src, routed_src_mac)
3605 self.assertEqual(inner[Ether].dst, sep4.mac)
3606 self.assertEqual(inner[IPv6].src, ep1.ip6.address)
3607 self.assertEqual(inner[IPv6].dst, ep3.ip6.address)
3609 c1.remove_vpp_config()
3610 c2.remove_vpp_config()
3613 # test the symmetric hash mode
3615 c1 = VppGbpContract(
3616 self, 402, epg_220.sclass, epg_222.sclass, acl_index,
3617 [VppGbpContractRule(
3618 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3619 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3620 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3621 sep1.ip4, sep1.epg.rd),
3622 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3623 sep2.ip4, sep2.epg.rd)]),
3625 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3626 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3627 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3628 sep3.ip6, sep3.epg.rd),
3629 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3630 sep4.ip6, sep4.epg.rd)])],
3631 [ETH_P_IP, ETH_P_IPV6])
3634 c2 = VppGbpContract(
3635 self, 402, epg_222.sclass, epg_220.sclass, acl_index,
3636 [VppGbpContractRule(
3637 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3638 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3639 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3640 sep1.ip4, sep1.epg.rd),
3641 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3642 sep2.ip4, sep2.epg.rd)]),
3644 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3645 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3646 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3647 sep3.ip6, sep3.epg.rd),
3648 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3649 sep4.ip6, sep4.epg.rd)])],
3650 [ETH_P_IP, ETH_P_IPV6])
3654 # send again with the contract preset, now packets arrive
3655 # at SEP1 for both directions
3657 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3660 self.assertEqual(rx[Ether].src, routed_src_mac)
3661 self.assertEqual(rx[Ether].dst, sep1.mac)
3662 self.assertEqual(rx[IP].src, ep1.ip4.address)
3663 self.assertEqual(rx[IP].dst, ep3.ip4.address)
3665 rxs = self.send_and_expect(self.pg2, p4[1] * 17, sep1.itf)
3668 self.assertEqual(rx[Ether].src, routed_src_mac)
3669 self.assertEqual(rx[Ether].dst, sep1.mac)
3670 self.assertEqual(rx[IP].src, ep3.ip4.address)
3671 self.assertEqual(rx[IP].dst, ep1.ip4.address)
3674 # programme the unknown EP for the L3 tests
3676 sep4.add_vpp_config()
3679 # an L3 switch packet between local EPs in different EPGs
3680 # different dest ports on each so the are LB hashed differently
3682 p4 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3683 IP(src=ep1.ip4.address, dst=ep2.ip4.address) /
3684 UDP(sport=1234, dport=1234) /
3686 (Ether(src=ep2.mac, dst=str(self.router_mac)) /
3687 IP(src=ep2.ip4.address, dst=ep1.ip4.address) /
3688 UDP(sport=1234, dport=1234) /
3690 p6 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3691 IPv6(src=ep1.ip6.address, dst=ep2.ip6.address) /
3692 UDP(sport=1234, dport=1234) /
3694 (Ether(src=ep2.mac, dst=str(self.router_mac)) /
3695 IPv6(src=ep2.ip6.address, dst=ep1.ip6.address) /
3696 UDP(sport=1234, dport=1234) /
3699 c3 = VppGbpContract(
3700 self, 402, epg_220.sclass, epg_221.sclass, acl_index,
3701 [VppGbpContractRule(
3702 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3703 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3704 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3705 sep1.ip4, sep1.epg.rd),
3706 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3707 sep2.ip4, sep2.epg.rd)]),
3709 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3710 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3711 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3712 sep3.ip6, sep3.epg.rd),
3713 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3714 sep4.ip6, sep4.epg.rd)])],
3715 [ETH_P_IP, ETH_P_IPV6])
3718 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3721 self.assertEqual(rx[Ether].src, routed_src_mac)
3722 self.assertEqual(rx[Ether].dst, sep1.mac)
3723 self.assertEqual(rx[IP].src, ep1.ip4.address)
3724 self.assertEqual(rx[IP].dst, ep2.ip4.address)
3727 # learn a remote EP in EPG 221
3728 # packets coming from unknown remote EPs will be leant & redirected
3730 vx_tun_l3 = VppGbpVxlanTunnel(
3731 self, 444, rd1.rd_id,
3732 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
3734 vx_tun_l3.add_vpp_config()
3736 c4 = VppGbpContract(
3737 self, 402, epg_221.sclass, epg_220.sclass, acl_index,
3738 [VppGbpContractRule(
3739 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3740 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3741 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3742 sep1.ip4, sep1.epg.rd),
3743 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3744 sep2.ip4, sep2.epg.rd)]),
3746 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3747 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3748 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3749 sep3.ip6, sep3.epg.rd),
3750 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3751 sep4.ip6, sep4.epg.rd)])],
3752 [ETH_P_IP, ETH_P_IPV6])
3755 p = (Ether(src=self.pg7.remote_mac,
3756 dst=self.pg7.local_mac) /
3757 IP(src=self.pg7.remote_ip4,
3758 dst=self.pg7.local_ip4) /
3759 UDP(sport=1234, dport=48879) /
3760 VXLAN(vni=444, gpid=441, flags=0x88) /
3761 Ether(src="00:22:22:22:22:33", dst=str(self.router_mac)) /
3762 IP(src="10.0.0.88", dst=ep1.ip4.address) /
3763 UDP(sport=1234, dport=1234) /
3766 # unknown remote EP to local EP redirected
3767 rxs = self.send_and_expect(self.pg7, [p], sep1.itf)
3770 self.assertEqual(rx[Ether].src, routed_src_mac)
3771 self.assertEqual(rx[Ether].dst, sep1.mac)
3772 self.assertEqual(rx[IP].src, "10.0.0.88")
3773 self.assertEqual(rx[IP].dst, ep1.ip4.address)
3775 # endpoint learnt via the parent GBP-vxlan interface
3776 self.assertTrue(find_gbp_endpoint(self,
3777 vx_tun_l3._sw_if_index,
3780 p = (Ether(src=self.pg7.remote_mac,
3781 dst=self.pg7.local_mac) /
3782 IP(src=self.pg7.remote_ip4,
3783 dst=self.pg7.local_ip4) /
3784 UDP(sport=1234, dport=48879) /
3785 VXLAN(vni=444, gpid=441, flags=0x88) /
3786 Ether(src="00:22:22:22:22:33", dst=str(self.router_mac)) /
3787 IPv6(src="2001:10::88", dst=ep1.ip6.address) /
3788 UDP(sport=1234, dport=1234) /
3791 # unknown remote EP to local EP redirected (ipv6)
3792 rxs = self.send_and_expect(self.pg7, [p], sep3.itf)
3795 self.assertEqual(rx[Ether].src, routed_src_mac)
3796 self.assertEqual(rx[Ether].dst, sep3.mac)
3797 self.assertEqual(rx[IPv6].src, "2001:10::88")
3798 self.assertEqual(rx[IPv6].dst, ep1.ip6.address)
3800 # endpoint learnt via the parent GBP-vxlan interface
3801 self.assertTrue(find_gbp_endpoint(self,
3802 vx_tun_l3._sw_if_index,
3806 # L3 switch from local to remote EP
3808 p4 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3809 IP(src=ep1.ip4.address, dst="10.0.0.88") /
3810 UDP(sport=1234, dport=1234) /
3812 p6 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3813 IPv6(src=ep1.ip6.address, dst="2001:10::88") /
3814 UDP(sport=1234, dport=1234) /
3817 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3820 self.assertEqual(rx[Ether].src, routed_src_mac)
3821 self.assertEqual(rx[Ether].dst, sep1.mac)
3822 self.assertEqual(rx[IP].src, ep1.ip4.address)
3823 self.assertEqual(rx[IP].dst, "10.0.0.88")
3825 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep4.itf)
3828 self.assertEqual(rx[Ether].src, routed_src_mac)
3829 self.assertEqual(rx[Ether].dst, sep4.mac)
3830 self.assertEqual(rx[IPv6].src, ep1.ip6.address)
3831 self.assertEqual(rx[IPv6].dst, "2001:10::88")
3834 # test the dst-ip hash mode
3836 c5 = VppGbpContract(
3837 self, 402, epg_220.sclass, epg_221.sclass, acl_index,
3838 [VppGbpContractRule(
3839 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3840 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
3841 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3842 sep1.ip4, sep1.epg.rd),
3843 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3844 sep2.ip4, sep2.epg.rd)]),
3846 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3847 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
3848 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3849 sep3.ip6, sep3.epg.rd),
3850 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3851 sep4.ip6, sep4.epg.rd)])],
3852 [ETH_P_IP, ETH_P_IPV6])
3855 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3858 self.assertEqual(rx[Ether].src, routed_src_mac)
3859 self.assertEqual(rx[Ether].dst, sep1.mac)
3860 self.assertEqual(rx[IP].src, ep1.ip4.address)
3861 self.assertEqual(rx[IP].dst, "10.0.0.88")
3863 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep3.itf)
3866 self.assertEqual(rx[Ether].src, routed_src_mac)
3867 self.assertEqual(rx[Ether].dst, sep3.mac)
3868 self.assertEqual(rx[IPv6].src, ep1.ip6.address)
3869 self.assertEqual(rx[IPv6].dst, "2001:10::88")
3872 # redirect to programmed remote SEP in EPG 320
3875 # gbp vxlan tunnel for the remote SEP
3876 vx_tun_l3_sep = VppGbpVxlanTunnel(
3877 self, 555, rd1.rd_id,
3878 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
3880 vx_tun_l3_sep.add_vpp_config()
3883 sep5 = VppGbpEndpoint(self, vx_tun_l3_sep,
3885 "12.0.0.10", "13.0.0.10",
3886 "4001:10::10", "5001:10::10",
3887 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
3889 self.pg7.remote_ip4,
3891 sep5.add_vpp_config()
3894 # redirect from local l3out to remote (known, then unknown) SEP
3899 self.loop4.set_mac(self.router_mac)
3900 VppIpInterfaceBind(self, self.loop4, t4).add_vpp_config()
3901 VppIpInterfaceBind(self, self.loop4, t6).add_vpp_config()
3902 ebd = VppBridgeDomain(self, 100)
3903 ebd.add_vpp_config()
3904 gebd = VppGbpBridgeDomain(self, ebd, rd1, self.loop4, None, None)
3905 gebd.add_vpp_config()
3907 eepg = VppGbpEndpointGroup(self, 888, 765, rd1, gebd,
3911 VppGbpEndpointRetention(2))
3912 eepg.add_vpp_config()
3913 # add subnets to BVI
3914 VppIpInterfaceAddress(
3918 24).add_vpp_config()
3919 VppIpInterfaceAddress(
3923 64).add_vpp_config()
3924 # ... which are L3-out subnets
3925 VppGbpSubnet(self, rd1, "10.1.0.0", 24,
3926 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3927 sclass=765).add_vpp_config()
3928 VppGbpSubnet(self, rd1, "2001:10:1::128", 64,
3929 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3930 sclass=765).add_vpp_config()
3931 # external endpoints
3932 VppL2Vtr(self, self.vlan_100, L2_VTR_OP.L2_POP_1).add_vpp_config()
3933 eep1 = VppGbpEndpoint(self, self.vlan_100, eepg, None, "10.1.0.1",
3934 "11.1.0.1", "2001:10:1::1", "3001:10:1::1",
3935 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
3936 eep1.add_vpp_config()
3937 VppL2Vtr(self, self.vlan_101, L2_VTR_OP.L2_POP_1).add_vpp_config()
3938 eep2 = VppGbpEndpoint(self, self.vlan_101, eepg, None, "10.1.0.2",
3939 "11.1.0.2", "2001:10:1::2", "3001:10:1::2",
3940 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
3941 eep2.add_vpp_config()
3943 # external subnets reachable though eep1 and eep2 respectively
3944 VppIpRoute(self, "10.220.0.0", 24,
3945 [VppRoutePath(eep1.ip4.address, eep1.epg.bvi.sw_if_index)],
3946 table_id=t4.table_id).add_vpp_config()
3947 VppGbpSubnet(self, rd1, "10.220.0.0", 24,
3948 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3949 sclass=4220).add_vpp_config()
3950 VppIpRoute(self, "10:220::", 64,
3951 [VppRoutePath(eep1.ip6.address, eep1.epg.bvi.sw_if_index)],
3952 table_id=t6.table_id).add_vpp_config()
3953 VppGbpSubnet(self, rd1, "10:220::", 64,
3954 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3955 sclass=4220).add_vpp_config()
3956 VppIpRoute(self, "10.221.0.0", 24,
3957 [VppRoutePath(eep2.ip4.address, eep2.epg.bvi.sw_if_index)],
3958 table_id=t4.table_id).add_vpp_config()
3959 VppGbpSubnet(self, rd1, "10.221.0.0", 24,
3960 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3961 sclass=4221).add_vpp_config()
3962 VppIpRoute(self, "10:221::", 64,
3963 [VppRoutePath(eep2.ip6.address, eep2.epg.bvi.sw_if_index)],
3964 table_id=t6.table_id).add_vpp_config()
3965 VppGbpSubnet(self, rd1, "10:221::", 64,
3966 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3967 sclass=4221).add_vpp_config()
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 # redirect remote EP to remote SEP
4047 # remote SEP known again
4048 sep5.add_vpp_config()
4050 # contract to redirect to learnt SEP
4052 self, 402, epg_221.sclass, epg_222.sclass, acl_index,
4053 [VppGbpContractRule(
4054 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4055 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
4056 [VppGbpContractNextHop(sep5.vmac, sep5.epg.bd,
4057 sep5.ip4, sep5.epg.rd)]),
4059 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4060 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
4061 [VppGbpContractNextHop(sep5.vmac, sep5.epg.bd,
4062 sep5.ip6, sep5.epg.rd)])],
4063 [ETH_P_IP, ETH_P_IPV6]).add_vpp_config()
4065 # packets from unknown EP 221 to known EP in EPG 222
4066 # should be redirected to known remote SEP
4067 base = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
4068 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
4069 UDP(sport=1234, dport=48879) /
4070 VXLAN(vni=444, gpid=441, flags=0x88) /
4071 Ether(src="00:22:22:22:22:44", dst=str(self.router_mac)))
4073 IP(src="10.0.1.100", dst=ep3.ip4.address) /
4074 UDP(sport=1234, dport=1234) /
4077 IPv6(src="2001:10::100", dst=ep3.ip6.address) /
4078 UDP(sport=1234, dport=1234) /
4081 # unknown remote EP to local EP redirected to known remote SEP
4082 rxs = self.send_and_expect(self.pg7, p, self.pg7)
4084 for rx, tx in zip(rxs, p):
4085 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4086 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4087 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4088 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4089 # this should use the programmed remote leaf TEP
4090 self.assertEqual(rx[VXLAN].vni, 555)
4091 self.assertEqual(rx[VXLAN].gpid, epg_221.sclass)
4092 self.assertTrue(rx[VXLAN].flags.G)
4093 self.assertTrue(rx[VXLAN].flags.Instance)
4094 # redirect policy has been applied
4095 self.assertTrue(rx[VXLAN].gpflags.A)
4096 self.assertFalse(rx[VXLAN].gpflags.D)
4097 rxip = rx[VXLAN][Ether].payload
4098 txip = tx[VXLAN][Ether].payload
4099 self.assertEqual(rxip.src, txip.src)
4100 self.assertEqual(rxip.dst, txip.dst)
4102 # endpoint learnt via the parent GBP-vxlan interface
4103 self.assertTrue(find_gbp_endpoint(self,
4104 vx_tun_l3._sw_if_index,
4106 self.assertTrue(find_gbp_endpoint(self,
4107 vx_tun_l3._sw_if_index,
4110 # remote SEP: it is now an unknown remote SEP and should go
4112 sep5.remove_vpp_config()
4114 # remote EP (coming from spine proxy) to local EP redirected to
4116 rxs = self.send_and_expect(self.pg7, p, self.pg7)
4118 for rx, tx in zip(rxs, p):
4119 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4120 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4121 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4122 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4123 # this should use the spine proxy TEP
4124 self.assertEqual(rx[VXLAN].vni, epg_320.bd.uu_fwd.vni)
4125 self.assertEqual(rx[VXLAN].gpid, epg_221.sclass)
4126 self.assertTrue(rx[VXLAN].flags.G)
4127 self.assertTrue(rx[VXLAN].flags.Instance)
4128 # redirect policy has been applied
4129 self.assertTrue(rx[VXLAN].gpflags.A)
4130 self.assertFalse(rx[VXLAN].gpflags.D)
4131 rxip = rx[VXLAN][Ether].payload
4132 txip = tx[VXLAN][Ether].payload
4133 self.assertEqual(rxip.src, txip.src)
4134 self.assertEqual(rxip.dst, txip.dst)
4139 self.pg7.unconfig_ip4()
4141 def test_gbp_l3_out(self):
4144 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
4145 self.vapi.cli("set logging class gbp level debug")
4147 routed_dst_mac = "00:0c:0c:0c:0c:0c"
4148 routed_src_mac = "00:22:bd:f8:19:ff"
4153 t4 = VppIpTable(self, 1)
4155 t6 = VppIpTable(self, 1, True)
4158 rd1 = VppGbpRouteDomain(self, 2, 55, t4, t6)
4159 rd1.add_vpp_config()
4161 self.loop0.set_mac(self.router_mac)
4164 # Bind the BVI to the RD
4166 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
4167 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
4170 # Pg7 hosts a BD's BUM
4171 # Pg1 some other l3 interface
4173 self.pg7.config_ip4()
4174 self.pg7.resolve_arp()
4177 # a multicast vxlan-gbp tunnel for broadcast in the BD
4179 tun_bm = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
4182 tun_bm.add_vpp_config()
4185 # a GBP external bridge domains for the EPs
4187 bd1 = VppBridgeDomain(self, 1)
4188 bd1.add_vpp_config()
4189 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0, None, tun_bm)
4190 gbd1.add_vpp_config()
4193 # The Endpoint-groups in which the external endpoints exist
4195 epg_220 = VppGbpEndpointGroup(self, 220, 113, rd1, gbd1,
4199 VppGbpEndpointRetention(2))
4200 epg_220.add_vpp_config()
4202 # the BVIs have the subnets applied ...
4203 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 24)
4204 ip4_addr.add_vpp_config()
4205 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 64)
4206 ip6_addr.add_vpp_config()
4208 # ... which are L3-out subnets
4209 l3o_1 = VppGbpSubnet(
4210 self, rd1, "10.0.0.0", 24,
4211 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
4213 l3o_1.add_vpp_config()
4216 # an external interface attached to the outside world and the
4219 VppL2Vtr(self, self.vlan_100, L2_VTR_OP.L2_POP_1).add_vpp_config()
4220 VppL2Vtr(self, self.vlan_101, L2_VTR_OP.L2_POP_1).add_vpp_config()
4221 vlan_144 = VppDot1QSubint(self, self.pg0, 144)
4223 # vlan_102 is not poped
4226 # an unicast vxlan-gbp for inter-RD traffic
4228 vx_tun_l3 = VppGbpVxlanTunnel(
4229 self, 444, rd1.rd_id,
4230 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
4232 vx_tun_l3.add_vpp_config()
4235 # External Endpoints
4237 eep1 = VppGbpEndpoint(self, self.vlan_100,
4239 "10.0.0.1", "11.0.0.1",
4240 "2001:10::1", "3001::1",
4241 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
4242 eep1.add_vpp_config()
4243 eep2 = VppGbpEndpoint(self, self.vlan_101,
4245 "10.0.0.2", "11.0.0.2",
4246 "2001:10::2", "3001::2",
4247 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
4248 eep2.add_vpp_config()
4249 eep3 = VppGbpEndpoint(self, self.vlan_102,
4251 "10.0.0.3", "11.0.0.3",
4252 "2001:10::3", "3001::3",
4253 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
4254 eep3.add_vpp_config()
4257 # A remote external endpoint
4259 rep = VppGbpEndpoint(self, vx_tun_l3,
4261 "10.0.0.101", "11.0.0.101",
4262 "2001:10::101", "3001::101",
4263 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
4265 self.pg7.remote_ip4,
4267 rep.add_vpp_config()
4270 # EP1 impersonating EP3 is dropped
4272 p = (Ether(src=eep1.mac, dst="ff:ff:ff:ff:ff:ff") /
4275 psrc="10.0.0.3", pdst="10.0.0.128",
4276 hwsrc=eep1.mac, hwdst="ff:ff:ff:ff:ff:ff"))
4277 self.send_and_assert_no_replies(self.pg0, p)
4280 # ARP packet from External EPs are accepted and replied to
4282 p_arp = (Ether(src=eep1.mac, dst="ff:ff:ff:ff:ff:ff") /
4285 psrc=eep1.ip4.address, pdst="10.0.0.128",
4286 hwsrc=eep1.mac, hwdst="ff:ff:ff:ff:ff:ff"))
4287 rxs = self.send_and_expect(self.pg0, p_arp * 1, self.pg0)
4290 # ARP packet from host in remote subnet are accepted and replied to
4292 p_arp = (Ether(src=eep3.mac, dst="ff:ff:ff:ff:ff:ff") /
4295 psrc=eep3.ip4.address, pdst="10.0.0.128",
4296 hwsrc=eep3.mac, hwdst="ff:ff:ff:ff:ff:ff"))
4297 rxs = self.send_and_expect(self.pg0, p_arp * 1, self.pg0)
4300 # packets destined to unknown addresses in the BVI's subnet
4303 p4 = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
4305 IP(src="10.0.0.1", dst="10.0.0.88") /
4306 UDP(sport=1234, dport=1234) /
4308 p6 = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
4310 IPv6(src="2001:10::1", dst="2001:10::88") /
4311 UDP(sport=1234, dport=1234) /
4314 rxs = self.send_and_expect(self.pg0, p4 * 1, self.pg7)
4317 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4318 # self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4319 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4320 self.assertEqual(rx[IP].dst, "239.1.1.1")
4321 self.assertEqual(rx[VXLAN].vni, 88)
4322 self.assertTrue(rx[VXLAN].flags.G)
4323 self.assertTrue(rx[VXLAN].flags.Instance)
4324 # policy was applied to the original IP packet
4325 self.assertEqual(rx[VXLAN].gpid, 113)
4326 self.assertTrue(rx[VXLAN].gpflags.A)
4327 self.assertFalse(rx[VXLAN].gpflags.D)
4329 inner = rx[VXLAN].payload
4331 self.assertTrue(inner.haslayer(ARP))
4334 # remote to external
4336 p = (Ether(src=self.pg7.remote_mac,
4337 dst=self.pg7.local_mac) /
4338 IP(src=self.pg7.remote_ip4,
4339 dst=self.pg7.local_ip4) /
4340 UDP(sport=1234, dport=48879) /
4341 VXLAN(vni=444, gpid=113, flags=0x88) /
4342 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
4343 IP(src="10.0.0.101", dst="10.0.0.1") /
4344 UDP(sport=1234, dport=1234) /
4347 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
4350 # local EP pings router
4352 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
4354 IP(src=eep1.ip4.address, dst="10.0.0.128") /
4355 ICMP(type='echo-request'))
4357 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
4360 self.assertEqual(rx[Ether].src, str(self.router_mac))
4361 self.assertEqual(rx[Ether].dst, eep1.mac)
4362 self.assertEqual(rx[Dot1Q].vlan, 100)
4365 # local EP pings other local EP
4367 p = (Ether(src=eep1.mac, dst=eep2.mac) /
4369 IP(src=eep1.ip4.address, dst=eep2.ip4.address) /
4370 ICMP(type='echo-request'))
4372 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
4375 self.assertEqual(rx[Ether].src, eep1.mac)
4376 self.assertEqual(rx[Ether].dst, eep2.mac)
4377 self.assertEqual(rx[Dot1Q].vlan, 101)
4380 # local EP pings router w/o vlan tag poped
4382 p = (Ether(src=eep3.mac, dst=str(self.router_mac)) /
4384 IP(src=eep3.ip4.address, dst="10.0.0.128") /
4385 ICMP(type='echo-request'))
4387 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
4390 self.assertEqual(rx[Ether].src, str(self.router_mac))
4391 self.assertEqual(rx[Ether].dst, self.vlan_102.remote_mac)
4394 # A ip4 subnet reachable through the external EP1
4396 ip_220 = VppIpRoute(self, "10.220.0.0", 24,
4397 [VppRoutePath(eep1.ip4.address,
4398 eep1.epg.bvi.sw_if_index)],
4399 table_id=t4.table_id)
4400 ip_220.add_vpp_config()
4402 l3o_220 = VppGbpSubnet(
4403 self, rd1, "10.220.0.0", 24,
4404 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
4406 l3o_220.add_vpp_config()
4409 # An ip6 subnet reachable through the external EP1
4411 ip6_220 = VppIpRoute(self, "10:220::", 64,
4412 [VppRoutePath(eep1.ip6.address,
4413 eep1.epg.bvi.sw_if_index)],
4414 table_id=t6.table_id)
4415 ip6_220.add_vpp_config()
4417 l3o6_220 = VppGbpSubnet(
4418 self, rd1, "10:220::", 64,
4419 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
4421 l3o6_220.add_vpp_config()
4424 # A subnet reachable through the external EP2
4426 ip_221 = VppIpRoute(self, "10.221.0.0", 24,
4427 [VppRoutePath(eep2.ip4.address,
4428 eep2.epg.bvi.sw_if_index)],
4429 table_id=t4.table_id)
4430 ip_221.add_vpp_config()
4432 l3o_221 = VppGbpSubnet(
4433 self, rd1, "10.221.0.0", 24,
4434 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
4436 l3o_221.add_vpp_config()
4439 # ping between hosts in remote subnets
4440 # dropped without a contract
4442 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
4444 IP(src="10.220.0.1", dst="10.221.0.1") /
4445 ICMP(type='echo-request'))
4447 self.send_and_assert_no_replies(self.pg0, p * 1)
4450 # contract for the external nets to communicate
4452 acl = VppGbpAcl(self)
4453 rule4 = acl.create_rule(permit_deny=1, proto=17)
4454 rule6 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
4455 acl_index = acl.add_vpp_config([rule4, rule6])
4458 # A contract with the wrong scope is not matched
4460 c_44 = VppGbpContract(
4461 self, 44, 4220, 4221, acl_index,
4462 [VppGbpContractRule(
4463 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4466 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4468 [ETH_P_IP, ETH_P_IPV6])
4469 c_44.add_vpp_config()
4470 self.send_and_assert_no_replies(self.pg0, p * 1)
4472 c1 = VppGbpContract(
4473 self, 55, 4220, 4221, acl_index,
4474 [VppGbpContractRule(
4475 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4476 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4479 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4480 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4482 [ETH_P_IP, ETH_P_IPV6])
4486 # Contracts allowing ext-net 200 to talk with external EPs
4488 c2 = VppGbpContract(
4489 self, 55, 4220, 113, acl_index,
4490 [VppGbpContractRule(
4491 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4492 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4495 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4496 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4498 [ETH_P_IP, ETH_P_IPV6])
4500 c3 = VppGbpContract(
4501 self, 55, 113, 4220, acl_index,
4502 [VppGbpContractRule(
4503 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4504 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4507 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4508 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4510 [ETH_P_IP, ETH_P_IPV6])
4514 # ping between hosts in remote subnets
4516 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
4518 IP(src="10.220.0.1", dst="10.221.0.1") /
4519 UDP(sport=1234, dport=1234) /
4522 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
4525 self.assertEqual(rx[Ether].src, str(self.router_mac))
4526 self.assertEqual(rx[Ether].dst, eep2.mac)
4527 self.assertEqual(rx[Dot1Q].vlan, 101)
4529 # we did not learn these external hosts
4530 self.assertFalse(find_gbp_endpoint(self, ip="10.220.0.1"))
4531 self.assertFalse(find_gbp_endpoint(self, ip="10.221.0.1"))
4534 # from remote external EP to local external EP
4536 p = (Ether(src=self.pg7.remote_mac,
4537 dst=self.pg7.local_mac) /
4538 IP(src=self.pg7.remote_ip4,
4539 dst=self.pg7.local_ip4) /
4540 UDP(sport=1234, dport=48879) /
4541 VXLAN(vni=444, gpid=113, flags=0x88) /
4542 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
4543 IP(src="10.0.0.101", dst="10.220.0.1") /
4544 UDP(sport=1234, dport=1234) /
4547 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
4550 # ping from an external host to the remote external EP
4552 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
4554 IP(src="10.220.0.1", dst=rep.ip4.address) /
4555 UDP(sport=1234, dport=1234) /
4558 rxs = self.send_and_expect(self.pg0, p * 1, self.pg7)
4561 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4562 # self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4563 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4564 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4565 self.assertEqual(rx[VXLAN].vni, 444)
4566 self.assertTrue(rx[VXLAN].flags.G)
4567 self.assertTrue(rx[VXLAN].flags.Instance)
4568 # the sclass of the ext-net the packet came from
4569 self.assertEqual(rx[VXLAN].gpid, 4220)
4570 # policy was applied to the original IP packet
4571 self.assertTrue(rx[VXLAN].gpflags.A)
4572 # since it's an external host the reciever should not learn it
4573 self.assertTrue(rx[VXLAN].gpflags.D)
4574 inner = rx[VXLAN].payload
4575 self.assertEqual(inner[IP].src, "10.220.0.1")
4576 self.assertEqual(inner[IP].dst, rep.ip4.address)
4579 # An external subnet reachable via the remote external EP
4583 # first the VXLAN-GBP tunnel over which it is reached
4585 vx_tun_r1 = VppVxlanGbpTunnel(
4586 self, self.pg7.local_ip4,
4587 self.pg7.remote_ip4, 445,
4588 mode=(VppEnum.vl_api_vxlan_gbp_api_tunnel_mode_t.
4589 VXLAN_GBP_API_TUNNEL_MODE_L3))
4590 vx_tun_r1.add_vpp_config()
4591 VppIpInterfaceBind(self, vx_tun_r1, t4).add_vpp_config()
4593 self.logger.info(self.vapi.cli("sh vxlan-gbp tunnel"))
4596 # then the special adj to resolve through on that tunnel
4598 n1 = VppNeighbor(self,
4599 vx_tun_r1.sw_if_index,
4600 "00:0c:0c:0c:0c:0c",
4601 self.pg7.remote_ip4)
4605 # the route via the adj above
4607 ip_222 = VppIpRoute(self, "10.222.0.0", 24,
4608 [VppRoutePath(self.pg7.remote_ip4,
4609 vx_tun_r1.sw_if_index)],
4610 table_id=t4.table_id)
4611 ip_222.add_vpp_config()
4613 l3o_222 = VppGbpSubnet(
4614 self, rd1, "10.222.0.0", 24,
4615 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
4617 l3o_222.add_vpp_config()
4620 # ping between hosts in local and remote external subnets
4621 # dropped without a contract
4623 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
4625 IP(src="10.220.0.1", dst="10.222.0.1") /
4626 UDP(sport=1234, dport=1234) /
4629 rxs = self.send_and_assert_no_replies(self.pg0, p * 1)
4632 # Add contracts ext-nets for 220 -> 222
4634 c4 = VppGbpContract(
4635 self, 55, 4220, 4222, acl_index,
4636 [VppGbpContractRule(
4637 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4638 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4641 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4642 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4644 [ETH_P_IP, ETH_P_IPV6])
4648 # ping from host in local to remote external subnets
4650 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
4652 IP(src="10.220.0.1", dst="10.222.0.1") /
4653 UDP(sport=1234, dport=1234) /
4656 rxs = self.send_and_expect(self.pg0, p * 3, self.pg7)
4659 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4660 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4661 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4662 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4663 self.assertEqual(rx[VXLAN].vni, 445)
4664 self.assertTrue(rx[VXLAN].flags.G)
4665 self.assertTrue(rx[VXLAN].flags.Instance)
4666 # the sclass of the ext-net the packet came from
4667 self.assertEqual(rx[VXLAN].gpid, 4220)
4668 # policy was applied to the original IP packet
4669 self.assertTrue(rx[VXLAN].gpflags.A)
4670 # since it's an external host the reciever should not learn it
4671 self.assertTrue(rx[VXLAN].gpflags.D)
4672 inner = rx[VXLAN].payload
4673 self.assertEqual(inner[Ether].dst, "00:0c:0c:0c:0c:0c")
4674 self.assertEqual(inner[IP].src, "10.220.0.1")
4675 self.assertEqual(inner[IP].dst, "10.222.0.1")
4678 # make the external subnet ECMP
4680 vx_tun_r2 = VppVxlanGbpTunnel(
4681 self, self.pg7.local_ip4,
4682 self.pg7.remote_ip4, 446,
4683 mode=(VppEnum.vl_api_vxlan_gbp_api_tunnel_mode_t.
4684 VXLAN_GBP_API_TUNNEL_MODE_L3))
4685 vx_tun_r2.add_vpp_config()
4686 VppIpInterfaceBind(self, vx_tun_r2, t4).add_vpp_config()
4688 self.logger.info(self.vapi.cli("sh vxlan-gbp tunnel"))
4690 n2 = VppNeighbor(self,
4691 vx_tun_r2.sw_if_index,
4692 "00:0c:0c:0c:0c:0c",
4693 self.pg7.remote_ip4)
4696 ip_222.modify([VppRoutePath(self.pg7.remote_ip4,
4697 vx_tun_r1.sw_if_index),
4698 VppRoutePath(self.pg7.remote_ip4,
4699 vx_tun_r2.sw_if_index)])
4702 # now expect load-balance
4704 p = [(Ether(src=eep1.mac, dst=str(self.router_mac)) /
4706 IP(src="10.220.0.1", dst="10.222.0.1") /
4707 UDP(sport=1234, dport=1234) /
4709 (Ether(src=eep1.mac, dst=str(self.router_mac)) /
4711 IP(src="10.220.0.1", dst="10.222.0.1") /
4712 UDP(sport=1222, dport=1235) /
4715 rxs = self.send_and_expect(self.pg0, p, self.pg7)
4717 self.assertEqual(rxs[0][VXLAN].vni, 445)
4718 self.assertEqual(rxs[1][VXLAN].vni, 446)
4721 # Same LB test for v6
4723 n3 = VppNeighbor(self,
4724 vx_tun_r1.sw_if_index,
4725 "00:0c:0c:0c:0c:0c",
4726 self.pg7.remote_ip6)
4728 n4 = VppNeighbor(self,
4729 vx_tun_r2.sw_if_index,
4730 "00:0c:0c:0c:0c:0c",
4731 self.pg7.remote_ip6)
4734 ip_222_6 = VppIpRoute(self, "10:222::", 64,
4735 [VppRoutePath(self.pg7.remote_ip6,
4736 vx_tun_r1.sw_if_index),
4737 VppRoutePath(self.pg7.remote_ip6,
4738 vx_tun_r2.sw_if_index)],
4739 table_id=t6.table_id)
4740 ip_222_6.add_vpp_config()
4742 l3o_222_6 = VppGbpSubnet(
4743 self, rd1, "10:222::", 64,
4744 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
4746 l3o_222_6.add_vpp_config()
4748 p = [(Ether(src=eep1.mac, dst=str(self.router_mac)) /
4750 IPv6(src="10:220::1", dst="10:222::1") /
4751 UDP(sport=1234, dport=1234) /
4753 (Ether(src=eep1.mac, dst=str(self.router_mac)) /
4755 IPv6(src="10:220::1", dst="10:222::1") /
4756 UDP(sport=7777, dport=8881) /
4759 self.logger.info(self.vapi.cli("sh ip6 fib 10:222::1"))
4760 rxs = self.send_and_expect(self.pg0, p, self.pg7)
4762 self.assertEqual(rxs[0][VXLAN].vni, 445)
4763 self.assertEqual(rxs[1][VXLAN].vni, 446)
4766 # ping from host in remote to local external subnets
4767 # there's no contract for this, but the A bit is set.
4769 p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
4770 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
4771 UDP(sport=1234, dport=48879) /
4772 VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
4773 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
4774 IP(src="10.222.0.1", dst="10.220.0.1") /
4775 UDP(sport=1234, dport=1234) /
4778 rxs = self.send_and_expect(self.pg7, p * 3, self.pg0)
4779 self.assertFalse(find_gbp_endpoint(self, ip="10.222.0.1"))
4782 # ping from host in remote to remote external subnets
4783 # this is dropped by reflection check.
4785 p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
4786 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
4787 UDP(sport=1234, dport=48879) /
4788 VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
4789 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
4790 IP(src="10.222.0.1", dst="10.222.0.2") /
4791 UDP(sport=1234, dport=1234) /
4794 rxs = self.send_and_assert_no_replies(self.pg7, p * 3)
4796 p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
4797 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
4798 UDP(sport=1234, dport=48879) /
4799 VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
4800 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
4801 IPv6(src="10:222::1", dst="10:222::2") /
4802 UDP(sport=1234, dport=1234) /
4805 rxs = self.send_and_assert_no_replies(self.pg7, p * 3)
4810 lep1 = VppGbpEndpoint(self, vlan_144,
4812 "10.0.0.44", "11.0.0.44",
4813 "2001:10::44", "3001::44")
4814 lep1.add_vpp_config()
4817 # local EP to local ip4 external subnet
4819 p = (Ether(src=lep1.mac, dst=str(self.router_mac)) /
4821 IP(src=lep1.ip4.address, dst="10.220.0.1") /
4822 UDP(sport=1234, dport=1234) /
4825 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
4828 self.assertEqual(rx[Ether].src, str(self.router_mac))
4829 self.assertEqual(rx[Ether].dst, eep1.mac)
4830 self.assertEqual(rx[Dot1Q].vlan, 100)
4833 # local EP to local ip6 external subnet
4835 p = (Ether(src=lep1.mac, dst=str(self.router_mac)) /
4837 IPv6(src=lep1.ip6.address, dst="10:220::1") /
4838 UDP(sport=1234, dport=1234) /
4841 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
4844 self.assertEqual(rx[Ether].src, str(self.router_mac))
4845 self.assertEqual(rx[Ether].dst, eep1.mac)
4846 self.assertEqual(rx[Dot1Q].vlan, 100)
4849 # ip4 and ip6 subnets that load-balance
4851 ip_20 = VppIpRoute(self, "10.20.0.0", 24,
4852 [VppRoutePath(eep1.ip4.address,
4853 eep1.epg.bvi.sw_if_index),
4854 VppRoutePath(eep2.ip4.address,
4855 eep2.epg.bvi.sw_if_index)],
4856 table_id=t4.table_id)
4857 ip_20.add_vpp_config()
4859 l3o_20 = VppGbpSubnet(
4860 self, rd1, "10.20.0.0", 24,
4861 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
4863 l3o_20.add_vpp_config()
4865 ip6_20 = VppIpRoute(self, "10:20::", 64,
4866 [VppRoutePath(eep1.ip6.address,
4867 eep1.epg.bvi.sw_if_index),
4868 VppRoutePath(eep2.ip6.address,
4869 eep2.epg.bvi.sw_if_index)],
4870 table_id=t6.table_id)
4871 ip6_20.add_vpp_config()
4873 l3o6_20 = VppGbpSubnet(
4874 self, rd1, "10:20::", 64,
4875 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
4877 l3o6_20.add_vpp_config()
4879 self.logger.info(self.vapi.cli("sh ip fib 10.20.0.1"))
4880 self.logger.info(self.vapi.cli("sh ip6 fib 10:20::1"))
4882 # two ip6 packets whose port are chosen so they load-balance
4883 p = [(Ether(src=lep1.mac, dst=str(self.router_mac)) /
4885 IPv6(src=lep1.ip6.address, dst="10:20::1") /
4886 UDP(sport=1234, dport=1234) /
4888 (Ether(src=lep1.mac, dst=str(self.router_mac)) /
4890 IPv6(src=lep1.ip6.address, dst="10:20::1") /
4891 UDP(sport=124, dport=1230) /
4894 rxs = self.send_and_expect(self.pg0, p, self.pg0, 2)
4896 self.assertEqual(rxs[0][Dot1Q].vlan, 101)
4897 self.assertEqual(rxs[1][Dot1Q].vlan, 100)
4899 # two ip4 packets whose port are chosen so they load-balance
4900 p = [(Ether(src=lep1.mac, dst=str(self.router_mac)) /
4902 IP(src=lep1.ip4.address, dst="10.20.0.1") /
4903 UDP(sport=1235, dport=1235) /
4905 (Ether(src=lep1.mac, dst=str(self.router_mac)) /
4907 IP(src=lep1.ip4.address, dst="10.20.0.1") /
4908 UDP(sport=124, dport=1230) /
4911 rxs = self.send_and_expect(self.pg0, p, self.pg0, 2)
4913 self.assertEqual(rxs[0][Dot1Q].vlan, 101)
4914 self.assertEqual(rxs[1][Dot1Q].vlan, 100)
4919 ip_222.remove_vpp_config()
4920 self.pg7.unconfig_ip4()
4921 self.vlan_101.set_vtr(L2_VTR_OP.L2_DISABLED)
4922 self.vlan_100.set_vtr(L2_VTR_OP.L2_DISABLED)
4924 def test_gbp_anon_l3_out(self):
4925 """ GBP Anonymous L3 Out """
4927 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
4928 self.vapi.cli("set logging class gbp level debug")
4930 routed_dst_mac = "00:0c:0c:0c:0c:0c"
4931 routed_src_mac = "00:22:bd:f8:19:ff"
4936 t4 = VppIpTable(self, 1)
4938 t6 = VppIpTable(self, 1, True)
4941 rd1 = VppGbpRouteDomain(self, 2, 55, t4, t6)
4942 rd1.add_vpp_config()
4944 self.loop0.set_mac(self.router_mac)
4947 # Bind the BVI to the RD
4949 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
4950 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
4953 # Pg7 hosts a BD's BUM
4954 # Pg1 some other l3 interface
4956 self.pg7.config_ip4()
4957 self.pg7.resolve_arp()
4960 # a GBP external bridge domains for the EPs
4962 bd1 = VppBridgeDomain(self, 1)
4963 bd1.add_vpp_config()
4964 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0, None, None)
4965 gbd1.add_vpp_config()
4968 # The Endpoint-groups in which the external endpoints exist
4970 epg_220 = VppGbpEndpointGroup(self, 220, 113, rd1, gbd1,
4974 VppGbpEndpointRetention(2))
4975 epg_220.add_vpp_config()
4977 # the BVIs have the subnet applied ...
4978 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 24)
4979 ip4_addr.add_vpp_config()
4981 # ... which is an Anonymous L3-out subnets
4982 l3o_1 = VppGbpSubnet(
4983 self, rd1, "10.0.0.0", 24,
4984 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_ANON_L3_OUT,
4986 l3o_1.add_vpp_config()
4989 # an external interface attached to the outside world and the
4992 VppL2Vtr(self, self.vlan_100, L2_VTR_OP.L2_POP_1).add_vpp_config()
4993 VppL2Vtr(self, self.vlan_101, L2_VTR_OP.L2_POP_1).add_vpp_config()
4996 # vlan_100 and vlan_101 are anonymous l3-out interfaces
4998 ext_itf = VppGbpExtItf(self, self.vlan_100, bd1, rd1, anon=True)
4999 ext_itf.add_vpp_config()
5000 ext_itf = VppGbpExtItf(self, self.vlan_101, bd1, rd1, anon=True)
5001 ext_itf.add_vpp_config()
5004 # an unicast vxlan-gbp for inter-RD traffic
5006 vx_tun_l3 = VppGbpVxlanTunnel(
5007 self, 444, rd1.rd_id,
5008 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
5010 vx_tun_l3.add_vpp_config()
5013 # A remote external endpoint
5015 rep = VppGbpEndpoint(self, vx_tun_l3,
5017 "10.0.0.201", "11.0.0.201",
5018 "2001:10::201", "3001::101",
5019 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
5021 self.pg7.remote_ip4,
5023 rep.add_vpp_config()
5026 # ARP packet from host in external subnet are accepted, flooded and
5027 # replied to. We expect 2 packets:
5028 # - APR request flooded over the other vlan subif
5029 # - ARP reply from BVI
5031 p_arp = (Ether(src=self.vlan_100.remote_mac,
5032 dst="ff:ff:ff:ff:ff:ff") /
5037 hwsrc=self.vlan_100.remote_mac,
5038 hwdst="ff:ff:ff:ff:ff:ff"))
5039 rxs = self.send_and_expect(self.pg0, p_arp * 1, self.pg0, n_rx=2)
5041 p_arp = (Ether(src=self.vlan_101.remote_mac,
5042 dst="ff:ff:ff:ff:ff:ff") /
5047 hwsrc=self.vlan_101.remote_mac,
5048 hwdst="ff:ff:ff:ff:ff:ff"))
5049 rxs = self.send_and_expect(self.pg0, p_arp * 1, self.pg0, n_rx=2)
5052 # remote to external
5054 p = (Ether(src=self.pg7.remote_mac,
5055 dst=self.pg7.local_mac) /
5056 IP(src=self.pg7.remote_ip4,
5057 dst=self.pg7.local_ip4) /
5058 UDP(sport=1234, dport=48879) /
5059 VXLAN(vni=vx_tun_l3.vni, gpid=epg_220.sclass, flags=0x88) /
5060 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
5061 IP(src=str(rep.ip4), dst="10.0.0.100") /
5062 UDP(sport=1234, dport=1234) /
5064 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
5067 # local EP pings router
5069 p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
5071 IP(src="10.0.0.100", dst="10.0.0.128") /
5072 ICMP(type='echo-request'))
5073 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
5076 self.assertEqual(rx[Ether].src, str(self.router_mac))
5077 self.assertEqual(rx[Ether].dst, self.vlan_100.remote_mac)
5078 self.assertEqual(rx[Dot1Q].vlan, 100)
5081 # local EP pings other local EP
5083 p = (Ether(src=self.vlan_100.remote_mac,
5084 dst=self.vlan_101.remote_mac) /
5086 IP(src="10.0.0.100", dst="10.0.0.101") /
5087 ICMP(type='echo-request'))
5088 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
5091 self.assertEqual(rx[Ether].src, self.vlan_100.remote_mac)
5092 self.assertEqual(rx[Ether].dst, self.vlan_101.remote_mac)
5093 self.assertEqual(rx[Dot1Q].vlan, 101)
5096 # A subnet reachable through an external router on vlan 100
5098 ip_220 = VppIpRoute(self, "10.220.0.0", 24,
5099 [VppRoutePath("10.0.0.100",
5100 epg_220.bvi.sw_if_index)],
5101 table_id=t4.table_id)
5102 ip_220.add_vpp_config()
5104 l3o_220 = VppGbpSubnet(
5105 self, rd1, "10.220.0.0", 24,
5106 # note: this a "regular" L3 out subnet (not connected)
5107 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
5109 l3o_220.add_vpp_config()
5112 # A subnet reachable through an external router on vlan 101
5114 ip_221 = VppIpRoute(self, "10.221.0.0", 24,
5115 [VppRoutePath("10.0.0.101",
5116 epg_220.bvi.sw_if_index)],
5117 table_id=t4.table_id)
5118 ip_221.add_vpp_config()
5120 l3o_221 = VppGbpSubnet(
5121 self, rd1, "10.221.0.0", 24,
5122 # note: this a "regular" L3 out subnet (not connected)
5123 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
5125 l3o_221.add_vpp_config()
5128 # ping between hosts in remote subnets
5129 # dropped without a contract
5131 p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
5133 IP(src="10.220.0.1", dst="10.221.0.1") /
5134 ICMP(type='echo-request'))
5136 rxs = self.send_and_assert_no_replies(self.pg0, p * 1)
5139 # contract for the external nets to communicate
5141 acl = VppGbpAcl(self)
5142 rule4 = acl.create_rule(permit_deny=1, proto=17)
5143 rule6 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
5144 acl_index = acl.add_vpp_config([rule4, rule6])
5146 c1 = VppGbpContract(
5147 self, 55, 4220, 4221, acl_index,
5148 [VppGbpContractRule(
5149 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5150 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5153 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5154 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5156 [ETH_P_IP, ETH_P_IPV6])
5160 # Contracts allowing ext-net 200 to talk with external EPs
5162 c2 = VppGbpContract(
5163 self, 55, 4220, 113, acl_index,
5164 [VppGbpContractRule(
5165 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5166 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5169 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5170 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5172 [ETH_P_IP, ETH_P_IPV6])
5174 c3 = VppGbpContract(
5175 self, 55, 113, 4220, acl_index,
5176 [VppGbpContractRule(
5177 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5178 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5181 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5182 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5184 [ETH_P_IP, ETH_P_IPV6])
5188 # ping between hosts in remote subnets
5190 p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
5192 IP(src="10.220.0.1", dst="10.221.0.1") /
5193 UDP(sport=1234, dport=1234) /
5196 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
5199 self.assertEqual(rx[Ether].src, str(self.router_mac))
5200 self.assertEqual(rx[Ether].dst, self.vlan_101.remote_mac)
5201 self.assertEqual(rx[Dot1Q].vlan, 101)
5203 # we did not learn these external hosts
5204 self.assertFalse(find_gbp_endpoint(self, ip="10.220.0.1"))
5205 self.assertFalse(find_gbp_endpoint(self, ip="10.221.0.1"))
5208 # from remote external EP to local external EP
5210 p = (Ether(src=self.pg7.remote_mac,
5211 dst=self.pg7.local_mac) /
5212 IP(src=self.pg7.remote_ip4,
5213 dst=self.pg7.local_ip4) /
5214 UDP(sport=1234, dport=48879) /
5215 VXLAN(vni=444, gpid=113, flags=0x88) /
5216 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
5217 IP(src=rep.ip4.address, dst="10.220.0.1") /
5218 UDP(sport=1234, dport=1234) /
5221 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
5224 # ping from an external host to the remote external EP
5226 p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
5228 IP(src="10.220.0.1", dst=rep.ip4.address) /
5229 UDP(sport=1234, dport=1234) /
5232 rxs = self.send_and_expect(self.pg0, p * 1, self.pg7)
5235 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
5236 # self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
5237 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
5238 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
5239 self.assertEqual(rx[VXLAN].vni, 444)
5240 self.assertTrue(rx[VXLAN].flags.G)
5241 self.assertTrue(rx[VXLAN].flags.Instance)
5242 # the sclass of the ext-net the packet came from
5243 self.assertEqual(rx[VXLAN].gpid, 4220)
5244 # policy was applied to the original IP packet
5245 self.assertTrue(rx[VXLAN].gpflags.A)
5246 # since it's an external host the reciever should not learn it
5247 self.assertTrue(rx[VXLAN].gpflags.D)
5248 inner = rx[VXLAN].payload
5249 self.assertEqual(inner[IP].src, "10.220.0.1")
5250 self.assertEqual(inner[IP].dst, rep.ip4.address)
5253 # An external subnet reachable via the remote external EP
5257 # first the VXLAN-GBP tunnel over which it is reached
5259 vx_tun_r = VppVxlanGbpTunnel(
5260 self, self.pg7.local_ip4,
5261 self.pg7.remote_ip4, 445,
5262 mode=(VppEnum.vl_api_vxlan_gbp_api_tunnel_mode_t.
5263 VXLAN_GBP_API_TUNNEL_MODE_L3))
5264 vx_tun_r.add_vpp_config()
5265 VppIpInterfaceBind(self, vx_tun_r, t4).add_vpp_config()
5267 self.logger.info(self.vapi.cli("sh vxlan-gbp tunnel"))
5270 # then the special adj to resolve through on that tunnel
5272 n1 = VppNeighbor(self,
5273 vx_tun_r.sw_if_index,
5274 "00:0c:0c:0c:0c:0c",
5275 self.pg7.remote_ip4)
5279 # the route via the adj above
5281 ip_222 = VppIpRoute(self, "10.222.0.0", 24,
5282 [VppRoutePath(self.pg7.remote_ip4,
5283 vx_tun_r.sw_if_index)],
5284 table_id=t4.table_id)
5285 ip_222.add_vpp_config()
5287 l3o_222 = VppGbpSubnet(
5288 self, rd1, "10.222.0.0", 24,
5289 # note: this a "regular" l3out subnet (not connected)
5290 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
5292 l3o_222.add_vpp_config()
5295 # ping between hosts in local and remote external subnets
5296 # dropped without a contract
5298 p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
5300 IP(src="10.220.0.1", dst="10.222.0.1") /
5301 UDP(sport=1234, dport=1234) /
5304 rxs = self.send_and_assert_no_replies(self.pg0, p * 1)
5307 # Add contracts ext-nets for 220 -> 222
5309 c4 = VppGbpContract(
5310 self, 55, 4220, 4222, acl_index,
5311 [VppGbpContractRule(
5312 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5313 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5316 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5317 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5319 [ETH_P_IP, ETH_P_IPV6])
5323 # ping from host in local to remote external subnets
5325 p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
5327 IP(src="10.220.0.1", dst="10.222.0.1") /
5328 UDP(sport=1234, dport=1234) /
5331 rxs = self.send_and_expect(self.pg0, p * 3, self.pg7)
5334 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
5335 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
5336 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
5337 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
5338 self.assertEqual(rx[VXLAN].vni, 445)
5339 self.assertTrue(rx[VXLAN].flags.G)
5340 self.assertTrue(rx[VXLAN].flags.Instance)
5341 # the sclass of the ext-net the packet came from
5342 self.assertEqual(rx[VXLAN].gpid, 4220)
5343 # policy was applied to the original IP packet
5344 self.assertTrue(rx[VXLAN].gpflags.A)
5345 # since it's an external host the reciever should not learn it
5346 self.assertTrue(rx[VXLAN].gpflags.D)
5347 inner = rx[VXLAN].payload
5348 self.assertEqual(inner[Ether].dst, "00:0c:0c:0c:0c:0c")
5349 self.assertEqual(inner[IP].src, "10.220.0.1")
5350 self.assertEqual(inner[IP].dst, "10.222.0.1")
5353 # ping from host in remote to local external subnets
5354 # there's no contract for this, but the A bit is set.
5356 p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
5357 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
5358 UDP(sport=1234, dport=48879) /
5359 VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
5360 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
5361 IP(src="10.222.0.1", dst="10.220.0.1") /
5362 UDP(sport=1234, dport=1234) /
5365 rxs = self.send_and_expect(self.pg7, p * 3, self.pg0)
5366 self.assertFalse(find_gbp_endpoint(self, ip="10.222.0.1"))
5369 # ping from host in remote to remote external subnets
5370 # this is dropped by reflection check.
5372 p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
5373 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
5374 UDP(sport=1234, dport=48879) /
5375 VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
5376 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
5377 IP(src="10.222.0.1", dst="10.222.0.2") /
5378 UDP(sport=1234, dport=1234) /
5381 rxs = self.send_and_assert_no_replies(self.pg7, p * 3)
5386 self.vlan_101.set_vtr(L2_VTR_OP.L2_DISABLED)
5387 self.vlan_100.set_vtr(L2_VTR_OP.L2_DISABLED)
5388 self.pg7.unconfig_ip4()
5391 if __name__ == '__main__':
5392 unittest.main(testRunner=VppTestRunner)