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
3729 vx_tun_l3 = VppGbpVxlanTunnel(
3730 self, 444, rd1.rd_id,
3731 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
3733 vx_tun_l3.add_vpp_config()
3735 c4 = VppGbpContract(
3736 self, 402, epg_221.sclass, epg_220.sclass, acl_index,
3737 [VppGbpContractRule(
3738 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3739 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3742 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3743 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3745 [ETH_P_IP, ETH_P_IPV6])
3748 p = (Ether(src=self.pg7.remote_mac,
3749 dst=self.pg7.local_mac) /
3750 IP(src=self.pg7.remote_ip4,
3751 dst=self.pg7.local_ip4) /
3752 UDP(sport=1234, dport=48879) /
3753 VXLAN(vni=444, gpid=441, flags=0x88) /
3754 Ether(src="00:22:22:22:22:33", dst=str(self.router_mac)) /
3755 IP(src="10.0.0.88", dst=ep1.ip4.address) /
3756 UDP(sport=1234, dport=1234) /
3759 rx = self.send_and_expect(self.pg7, [p], self.pg0)
3761 # endpoint learnt via the parent GBP-vxlan interface
3762 self.assertTrue(find_gbp_endpoint(self,
3763 vx_tun_l3._sw_if_index,
3766 p = (Ether(src=self.pg7.remote_mac,
3767 dst=self.pg7.local_mac) /
3768 IP(src=self.pg7.remote_ip4,
3769 dst=self.pg7.local_ip4) /
3770 UDP(sport=1234, dport=48879) /
3771 VXLAN(vni=444, gpid=441, flags=0x88) /
3772 Ether(src="00:22:22:22:22:33", dst=str(self.router_mac)) /
3773 IPv6(src="2001:10::88", dst=ep1.ip6.address) /
3774 UDP(sport=1234, dport=1234) /
3777 rx = self.send_and_expect(self.pg7, [p], self.pg0)
3779 # endpoint learnt via the parent GBP-vxlan interface
3780 self.assertTrue(find_gbp_endpoint(self,
3781 vx_tun_l3._sw_if_index,
3785 # L3 switch from local to remote EP
3787 p4 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3788 IP(src=ep1.ip4.address, dst="10.0.0.88") /
3789 UDP(sport=1234, dport=1234) /
3791 p6 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3792 IPv6(src=ep1.ip6.address, dst="2001:10::88") /
3793 UDP(sport=1234, dport=1234) /
3796 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3799 self.assertEqual(rx[Ether].src, routed_src_mac)
3800 self.assertEqual(rx[Ether].dst, sep1.mac)
3801 self.assertEqual(rx[IP].src, ep1.ip4.address)
3802 self.assertEqual(rx[IP].dst, "10.0.0.88")
3804 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep4.itf)
3807 self.assertEqual(rx[Ether].src, routed_src_mac)
3808 self.assertEqual(rx[Ether].dst, sep4.mac)
3809 self.assertEqual(rx[IPv6].src, ep1.ip6.address)
3810 self.assertEqual(rx[IPv6].dst, "2001:10::88")
3813 # test the dst-ip hash mode
3815 c5 = VppGbpContract(
3816 self, 402, epg_220.sclass, epg_221.sclass, acl_index,
3817 [VppGbpContractRule(
3818 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3819 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
3820 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3821 sep1.ip4, sep1.epg.rd),
3822 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3823 sep2.ip4, sep2.epg.rd)]),
3825 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3826 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
3827 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3828 sep3.ip6, sep3.epg.rd),
3829 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3830 sep4.ip6, sep4.epg.rd)])],
3831 [ETH_P_IP, ETH_P_IPV6])
3834 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3837 self.assertEqual(rx[Ether].src, routed_src_mac)
3838 self.assertEqual(rx[Ether].dst, sep1.mac)
3839 self.assertEqual(rx[IP].src, ep1.ip4.address)
3840 self.assertEqual(rx[IP].dst, "10.0.0.88")
3842 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep3.itf)
3845 self.assertEqual(rx[Ether].src, routed_src_mac)
3846 self.assertEqual(rx[Ether].dst, sep3.mac)
3847 self.assertEqual(rx[IPv6].src, ep1.ip6.address)
3848 self.assertEqual(rx[IPv6].dst, "2001:10::88")
3853 self.pg7.unconfig_ip4()
3855 def test_gbp_l3_out(self):
3858 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
3859 self.vapi.cli("set logging class gbp level debug")
3861 routed_dst_mac = "00:0c:0c:0c:0c:0c"
3862 routed_src_mac = "00:22:bd:f8:19:ff"
3867 t4 = VppIpTable(self, 1)
3869 t6 = VppIpTable(self, 1, True)
3872 rd1 = VppGbpRouteDomain(self, 2, 55, t4, t6)
3873 rd1.add_vpp_config()
3875 self.loop0.set_mac(self.router_mac)
3878 # Bind the BVI to the RD
3880 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
3881 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
3884 # Pg7 hosts a BD's BUM
3885 # Pg1 some other l3 interface
3887 self.pg7.config_ip4()
3888 self.pg7.resolve_arp()
3891 # a multicast vxlan-gbp tunnel for broadcast in the BD
3893 tun_bm = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
3896 tun_bm.add_vpp_config()
3899 # a GBP external bridge domains for the EPs
3901 bd1 = VppBridgeDomain(self, 1)
3902 bd1.add_vpp_config()
3903 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0, None, tun_bm)
3904 gbd1.add_vpp_config()
3907 # The Endpoint-groups in which the external endpoints exist
3909 epg_220 = VppGbpEndpointGroup(self, 220, 113, rd1, gbd1,
3913 VppGbpEndpointRetention(2))
3914 epg_220.add_vpp_config()
3916 # the BVIs have the subnets applied ...
3917 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 24)
3918 ip4_addr.add_vpp_config()
3919 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 64)
3920 ip6_addr.add_vpp_config()
3922 # ... which are L3-out subnets
3923 l3o_1 = VppGbpSubnet(
3924 self, rd1, "10.0.0.0", 24,
3925 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3927 l3o_1.add_vpp_config()
3930 # an external interface attached to the outside world and the
3933 VppL2Vtr(self, self.vlan_100, L2_VTR_OP.L2_POP_1).add_vpp_config()
3934 VppL2Vtr(self, self.vlan_101, L2_VTR_OP.L2_POP_1).add_vpp_config()
3935 vlan_144 = VppDot1QSubint(self, self.pg0, 144)
3937 # vlan_102 is not poped
3940 # an unicast vxlan-gbp for inter-RD traffic
3942 vx_tun_l3 = VppGbpVxlanTunnel(
3943 self, 444, rd1.rd_id,
3944 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
3946 vx_tun_l3.add_vpp_config()
3949 # External Endpoints
3951 eep1 = VppGbpEndpoint(self, self.vlan_100,
3953 "10.0.0.1", "11.0.0.1",
3954 "2001:10::1", "3001::1",
3955 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
3956 eep1.add_vpp_config()
3957 eep2 = VppGbpEndpoint(self, self.vlan_101,
3959 "10.0.0.2", "11.0.0.2",
3960 "2001:10::2", "3001::2",
3961 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
3962 eep2.add_vpp_config()
3963 eep3 = VppGbpEndpoint(self, self.vlan_102,
3965 "10.0.0.3", "11.0.0.3",
3966 "2001:10::3", "3001::3",
3967 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
3968 eep3.add_vpp_config()
3971 # A remote external endpoint
3973 rep = VppGbpEndpoint(self, vx_tun_l3,
3975 "10.0.0.101", "11.0.0.101",
3976 "2001:10::101", "3001::101",
3977 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
3979 self.pg7.remote_ip4,
3981 rep.add_vpp_config()
3984 # EP1 impersonating EP3 is dropped
3986 p = (Ether(src=eep1.mac, dst="ff:ff:ff:ff:ff:ff") /
3989 psrc="10.0.0.3", pdst="10.0.0.128",
3990 hwsrc=eep1.mac, hwdst="ff:ff:ff:ff:ff:ff"))
3991 self.send_and_assert_no_replies(self.pg0, p)
3994 # ARP packet from External EPs are accepted and replied to
3996 p_arp = (Ether(src=eep1.mac, dst="ff:ff:ff:ff:ff:ff") /
3999 psrc=eep1.ip4.address, pdst="10.0.0.128",
4000 hwsrc=eep1.mac, hwdst="ff:ff:ff:ff:ff:ff"))
4001 rxs = self.send_and_expect(self.pg0, p_arp * 1, self.pg0)
4004 # ARP packet from host in remote subnet are accepted and replied to
4006 p_arp = (Ether(src=eep3.mac, dst="ff:ff:ff:ff:ff:ff") /
4009 psrc=eep3.ip4.address, pdst="10.0.0.128",
4010 hwsrc=eep3.mac, hwdst="ff:ff:ff:ff:ff:ff"))
4011 rxs = self.send_and_expect(self.pg0, p_arp * 1, self.pg0)
4014 # packets destined to unknown addresses in the BVI's subnet
4017 p4 = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
4019 IP(src="10.0.0.1", dst="10.0.0.88") /
4020 UDP(sport=1234, dport=1234) /
4022 p6 = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
4024 IPv6(src="2001:10::1", dst="2001:10::88") /
4025 UDP(sport=1234, dport=1234) /
4028 rxs = self.send_and_expect(self.pg0, p4 * 1, self.pg7)
4031 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4032 # self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4033 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4034 self.assertEqual(rx[IP].dst, "239.1.1.1")
4035 self.assertEqual(rx[VXLAN].vni, 88)
4036 self.assertTrue(rx[VXLAN].flags.G)
4037 self.assertTrue(rx[VXLAN].flags.Instance)
4038 # policy was applied to the original IP packet
4039 self.assertEqual(rx[VXLAN].gpid, 113)
4040 self.assertTrue(rx[VXLAN].gpflags.A)
4041 self.assertFalse(rx[VXLAN].gpflags.D)
4043 inner = rx[VXLAN].payload
4045 self.assertTrue(inner.haslayer(ARP))
4048 # remote to external
4050 p = (Ether(src=self.pg7.remote_mac,
4051 dst=self.pg7.local_mac) /
4052 IP(src=self.pg7.remote_ip4,
4053 dst=self.pg7.local_ip4) /
4054 UDP(sport=1234, dport=48879) /
4055 VXLAN(vni=444, gpid=113, flags=0x88) /
4056 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
4057 IP(src="10.0.0.101", dst="10.0.0.1") /
4058 UDP(sport=1234, dport=1234) /
4061 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
4064 # local EP pings router
4066 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
4068 IP(src=eep1.ip4.address, dst="10.0.0.128") /
4069 ICMP(type='echo-request'))
4071 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
4074 self.assertEqual(rx[Ether].src, str(self.router_mac))
4075 self.assertEqual(rx[Ether].dst, eep1.mac)
4076 self.assertEqual(rx[Dot1Q].vlan, 100)
4079 # local EP pings other local EP
4081 p = (Ether(src=eep1.mac, dst=eep2.mac) /
4083 IP(src=eep1.ip4.address, dst=eep2.ip4.address) /
4084 ICMP(type='echo-request'))
4086 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
4089 self.assertEqual(rx[Ether].src, eep1.mac)
4090 self.assertEqual(rx[Ether].dst, eep2.mac)
4091 self.assertEqual(rx[Dot1Q].vlan, 101)
4094 # local EP pings router w/o vlan tag poped
4096 p = (Ether(src=eep3.mac, dst=str(self.router_mac)) /
4098 IP(src=eep3.ip4.address, dst="10.0.0.128") /
4099 ICMP(type='echo-request'))
4101 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
4104 self.assertEqual(rx[Ether].src, str(self.router_mac))
4105 self.assertEqual(rx[Ether].dst, self.vlan_102.remote_mac)
4108 # A ip4 subnet reachable through the external EP1
4110 ip_220 = VppIpRoute(self, "10.220.0.0", 24,
4111 [VppRoutePath(eep1.ip4.address,
4112 eep1.epg.bvi.sw_if_index)],
4113 table_id=t4.table_id)
4114 ip_220.add_vpp_config()
4116 l3o_220 = VppGbpSubnet(
4117 self, rd1, "10.220.0.0", 24,
4118 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
4120 l3o_220.add_vpp_config()
4123 # An ip6 subnet reachable through the external EP1
4125 ip6_220 = VppIpRoute(self, "10:220::", 64,
4126 [VppRoutePath(eep1.ip6.address,
4127 eep1.epg.bvi.sw_if_index)],
4128 table_id=t6.table_id)
4129 ip6_220.add_vpp_config()
4131 l3o6_220 = VppGbpSubnet(
4132 self, rd1, "10:220::", 64,
4133 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
4135 l3o6_220.add_vpp_config()
4138 # A subnet reachable through the external EP2
4140 ip_221 = VppIpRoute(self, "10.221.0.0", 24,
4141 [VppRoutePath(eep2.ip4.address,
4142 eep2.epg.bvi.sw_if_index)],
4143 table_id=t4.table_id)
4144 ip_221.add_vpp_config()
4146 l3o_221 = VppGbpSubnet(
4147 self, rd1, "10.221.0.0", 24,
4148 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
4150 l3o_221.add_vpp_config()
4153 # ping between hosts in remote subnets
4154 # dropped without a contract
4156 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
4158 IP(src="10.220.0.1", dst="10.221.0.1") /
4159 ICMP(type='echo-request'))
4161 self.send_and_assert_no_replies(self.pg0, p * 1)
4164 # contract for the external nets to communicate
4166 acl = VppGbpAcl(self)
4167 rule4 = acl.create_rule(permit_deny=1, proto=17)
4168 rule6 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
4169 acl_index = acl.add_vpp_config([rule4, rule6])
4172 # A contract with the wrong scope is not matched
4174 c_44 = VppGbpContract(
4175 self, 44, 4220, 4221, acl_index,
4176 [VppGbpContractRule(
4177 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4180 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4182 [ETH_P_IP, ETH_P_IPV6])
4183 c_44.add_vpp_config()
4184 self.send_and_assert_no_replies(self.pg0, p * 1)
4186 c1 = VppGbpContract(
4187 self, 55, 4220, 4221, acl_index,
4188 [VppGbpContractRule(
4189 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4190 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4193 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4194 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4196 [ETH_P_IP, ETH_P_IPV6])
4200 # Contracts allowing ext-net 200 to talk with external EPs
4202 c2 = VppGbpContract(
4203 self, 55, 4220, 113, acl_index,
4204 [VppGbpContractRule(
4205 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4206 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4209 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4210 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4212 [ETH_P_IP, ETH_P_IPV6])
4214 c3 = VppGbpContract(
4215 self, 55, 113, 4220, acl_index,
4216 [VppGbpContractRule(
4217 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4218 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4221 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4222 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4224 [ETH_P_IP, ETH_P_IPV6])
4228 # ping between hosts in remote subnets
4230 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
4232 IP(src="10.220.0.1", dst="10.221.0.1") /
4233 UDP(sport=1234, dport=1234) /
4236 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
4239 self.assertEqual(rx[Ether].src, str(self.router_mac))
4240 self.assertEqual(rx[Ether].dst, eep2.mac)
4241 self.assertEqual(rx[Dot1Q].vlan, 101)
4243 # we did not learn these external hosts
4244 self.assertFalse(find_gbp_endpoint(self, ip="10.220.0.1"))
4245 self.assertFalse(find_gbp_endpoint(self, ip="10.221.0.1"))
4248 # from remote external EP to local external EP
4250 p = (Ether(src=self.pg7.remote_mac,
4251 dst=self.pg7.local_mac) /
4252 IP(src=self.pg7.remote_ip4,
4253 dst=self.pg7.local_ip4) /
4254 UDP(sport=1234, dport=48879) /
4255 VXLAN(vni=444, gpid=113, flags=0x88) /
4256 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
4257 IP(src="10.0.0.101", dst="10.220.0.1") /
4258 UDP(sport=1234, dport=1234) /
4261 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
4264 # ping from an external host to the remote external EP
4266 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
4268 IP(src="10.220.0.1", dst=rep.ip4.address) /
4269 UDP(sport=1234, dport=1234) /
4272 rxs = self.send_and_expect(self.pg0, p * 1, self.pg7)
4275 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4276 # self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4277 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4278 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4279 self.assertEqual(rx[VXLAN].vni, 444)
4280 self.assertTrue(rx[VXLAN].flags.G)
4281 self.assertTrue(rx[VXLAN].flags.Instance)
4282 # the sclass of the ext-net the packet came from
4283 self.assertEqual(rx[VXLAN].gpid, 4220)
4284 # policy was applied to the original IP packet
4285 self.assertTrue(rx[VXLAN].gpflags.A)
4286 # since it's an external host the reciever should not learn it
4287 self.assertTrue(rx[VXLAN].gpflags.D)
4288 inner = rx[VXLAN].payload
4289 self.assertEqual(inner[IP].src, "10.220.0.1")
4290 self.assertEqual(inner[IP].dst, rep.ip4.address)
4293 # An external subnet reachable via the remote external EP
4297 # first the VXLAN-GBP tunnel over which it is reached
4299 vx_tun_r1 = VppVxlanGbpTunnel(
4300 self, self.pg7.local_ip4,
4301 self.pg7.remote_ip4, 445,
4302 mode=(VppEnum.vl_api_vxlan_gbp_api_tunnel_mode_t.
4303 VXLAN_GBP_API_TUNNEL_MODE_L3))
4304 vx_tun_r1.add_vpp_config()
4305 VppIpInterfaceBind(self, vx_tun_r1, t4).add_vpp_config()
4307 self.logger.info(self.vapi.cli("sh vxlan-gbp tunnel"))
4310 # then the special adj to resolve through on that tunnel
4312 n1 = VppNeighbor(self,
4313 vx_tun_r1.sw_if_index,
4314 "00:0c:0c:0c:0c:0c",
4315 self.pg7.remote_ip4)
4319 # the route via the adj above
4321 ip_222 = VppIpRoute(self, "10.222.0.0", 24,
4322 [VppRoutePath(self.pg7.remote_ip4,
4323 vx_tun_r1.sw_if_index)],
4324 table_id=t4.table_id)
4325 ip_222.add_vpp_config()
4327 l3o_222 = VppGbpSubnet(
4328 self, rd1, "10.222.0.0", 24,
4329 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
4331 l3o_222.add_vpp_config()
4334 # ping between hosts in local and remote external subnets
4335 # dropped without a contract
4337 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
4339 IP(src="10.220.0.1", dst="10.222.0.1") /
4340 UDP(sport=1234, dport=1234) /
4343 rxs = self.send_and_assert_no_replies(self.pg0, p * 1)
4346 # Add contracts ext-nets for 220 -> 222
4348 c4 = VppGbpContract(
4349 self, 55, 4220, 4222, acl_index,
4350 [VppGbpContractRule(
4351 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4352 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4355 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4356 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4358 [ETH_P_IP, ETH_P_IPV6])
4362 # ping from host in local to remote external subnets
4364 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
4366 IP(src="10.220.0.1", dst="10.222.0.1") /
4367 UDP(sport=1234, dport=1234) /
4370 rxs = self.send_and_expect(self.pg0, p * 3, self.pg7)
4373 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4374 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4375 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4376 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4377 self.assertEqual(rx[VXLAN].vni, 445)
4378 self.assertTrue(rx[VXLAN].flags.G)
4379 self.assertTrue(rx[VXLAN].flags.Instance)
4380 # the sclass of the ext-net the packet came from
4381 self.assertEqual(rx[VXLAN].gpid, 4220)
4382 # policy was applied to the original IP packet
4383 self.assertTrue(rx[VXLAN].gpflags.A)
4384 # since it's an external host the reciever should not learn it
4385 self.assertTrue(rx[VXLAN].gpflags.D)
4386 inner = rx[VXLAN].payload
4387 self.assertEqual(inner[Ether].dst, "00:0c:0c:0c:0c:0c")
4388 self.assertEqual(inner[IP].src, "10.220.0.1")
4389 self.assertEqual(inner[IP].dst, "10.222.0.1")
4392 # make the external subnet ECMP
4394 vx_tun_r2 = VppVxlanGbpTunnel(
4395 self, self.pg7.local_ip4,
4396 self.pg7.remote_ip4, 446,
4397 mode=(VppEnum.vl_api_vxlan_gbp_api_tunnel_mode_t.
4398 VXLAN_GBP_API_TUNNEL_MODE_L3))
4399 vx_tun_r2.add_vpp_config()
4400 VppIpInterfaceBind(self, vx_tun_r2, t4).add_vpp_config()
4402 self.logger.info(self.vapi.cli("sh vxlan-gbp tunnel"))
4404 n2 = VppNeighbor(self,
4405 vx_tun_r2.sw_if_index,
4406 "00:0c:0c:0c:0c:0c",
4407 self.pg7.remote_ip4)
4410 ip_222.modify([VppRoutePath(self.pg7.remote_ip4,
4411 vx_tun_r1.sw_if_index),
4412 VppRoutePath(self.pg7.remote_ip4,
4413 vx_tun_r2.sw_if_index)])
4416 # now expect load-balance
4418 p = [(Ether(src=eep1.mac, dst=str(self.router_mac)) /
4420 IP(src="10.220.0.1", dst="10.222.0.1") /
4421 UDP(sport=1234, dport=1234) /
4423 (Ether(src=eep1.mac, dst=str(self.router_mac)) /
4425 IP(src="10.220.0.1", dst="10.222.0.1") /
4426 UDP(sport=1222, dport=1235) /
4429 rxs = self.send_and_expect(self.pg0, p, self.pg7)
4431 self.assertEqual(rxs[0][VXLAN].vni, 445)
4432 self.assertEqual(rxs[1][VXLAN].vni, 446)
4435 # Same LB test for v6
4437 n3 = VppNeighbor(self,
4438 vx_tun_r1.sw_if_index,
4439 "00:0c:0c:0c:0c:0c",
4440 self.pg7.remote_ip6)
4442 n4 = VppNeighbor(self,
4443 vx_tun_r2.sw_if_index,
4444 "00:0c:0c:0c:0c:0c",
4445 self.pg7.remote_ip6)
4448 ip_222_6 = VppIpRoute(self, "10:222::", 64,
4449 [VppRoutePath(self.pg7.remote_ip6,
4450 vx_tun_r1.sw_if_index),
4451 VppRoutePath(self.pg7.remote_ip6,
4452 vx_tun_r2.sw_if_index)],
4453 table_id=t6.table_id)
4454 ip_222_6.add_vpp_config()
4456 l3o_222_6 = VppGbpSubnet(
4457 self, rd1, "10:222::", 64,
4458 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
4460 l3o_222_6.add_vpp_config()
4462 p = [(Ether(src=eep1.mac, dst=str(self.router_mac)) /
4464 IPv6(src="10:220::1", dst="10:222::1") /
4465 UDP(sport=1234, dport=1234) /
4467 (Ether(src=eep1.mac, dst=str(self.router_mac)) /
4469 IPv6(src="10:220::1", dst="10:222::1") /
4470 UDP(sport=7777, dport=8881) /
4473 self.logger.info(self.vapi.cli("sh ip6 fib 10:222::1"))
4474 rxs = self.send_and_expect(self.pg0, p, self.pg7)
4476 self.assertEqual(rxs[0][VXLAN].vni, 445)
4477 self.assertEqual(rxs[1][VXLAN].vni, 446)
4480 # ping from host in remote to local external subnets
4481 # there's no contract for this, but the A bit is set.
4483 p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
4484 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
4485 UDP(sport=1234, dport=48879) /
4486 VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
4487 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
4488 IP(src="10.222.0.1", dst="10.220.0.1") /
4489 UDP(sport=1234, dport=1234) /
4492 rxs = self.send_and_expect(self.pg7, p * 3, self.pg0)
4493 self.assertFalse(find_gbp_endpoint(self, ip="10.222.0.1"))
4496 # ping from host in remote to remote external subnets
4497 # this is dropped by reflection check.
4499 p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
4500 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
4501 UDP(sport=1234, dport=48879) /
4502 VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
4503 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
4504 IP(src="10.222.0.1", dst="10.222.0.2") /
4505 UDP(sport=1234, dport=1234) /
4508 rxs = self.send_and_assert_no_replies(self.pg7, p * 3)
4510 p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
4511 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
4512 UDP(sport=1234, dport=48879) /
4513 VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
4514 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
4515 IPv6(src="10:222::1", dst="10:222::2") /
4516 UDP(sport=1234, dport=1234) /
4519 rxs = self.send_and_assert_no_replies(self.pg7, p * 3)
4524 lep1 = VppGbpEndpoint(self, vlan_144,
4526 "10.0.0.44", "11.0.0.44",
4527 "2001:10::44", "3001::44")
4528 lep1.add_vpp_config()
4531 # local EP to local ip4 external subnet
4533 p = (Ether(src=lep1.mac, dst=str(self.router_mac)) /
4535 IP(src=lep1.ip4.address, dst="10.220.0.1") /
4536 UDP(sport=1234, dport=1234) /
4539 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
4542 self.assertEqual(rx[Ether].src, str(self.router_mac))
4543 self.assertEqual(rx[Ether].dst, eep1.mac)
4544 self.assertEqual(rx[Dot1Q].vlan, 100)
4547 # local EP to local ip6 external subnet
4549 p = (Ether(src=lep1.mac, dst=str(self.router_mac)) /
4551 IPv6(src=lep1.ip6.address, dst="10:220::1") /
4552 UDP(sport=1234, dport=1234) /
4555 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
4558 self.assertEqual(rx[Ether].src, str(self.router_mac))
4559 self.assertEqual(rx[Ether].dst, eep1.mac)
4560 self.assertEqual(rx[Dot1Q].vlan, 100)
4563 # ip4 and ip6 subnets that load-balance
4565 ip_20 = VppIpRoute(self, "10.20.0.0", 24,
4566 [VppRoutePath(eep1.ip4.address,
4567 eep1.epg.bvi.sw_if_index),
4568 VppRoutePath(eep2.ip4.address,
4569 eep2.epg.bvi.sw_if_index)],
4570 table_id=t4.table_id)
4571 ip_20.add_vpp_config()
4573 l3o_20 = VppGbpSubnet(
4574 self, rd1, "10.20.0.0", 24,
4575 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
4577 l3o_20.add_vpp_config()
4579 ip6_20 = VppIpRoute(self, "10:20::", 64,
4580 [VppRoutePath(eep1.ip6.address,
4581 eep1.epg.bvi.sw_if_index),
4582 VppRoutePath(eep2.ip6.address,
4583 eep2.epg.bvi.sw_if_index)],
4584 table_id=t6.table_id)
4585 ip6_20.add_vpp_config()
4587 l3o6_20 = VppGbpSubnet(
4588 self, rd1, "10:20::", 64,
4589 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
4591 l3o6_20.add_vpp_config()
4593 self.logger.info(self.vapi.cli("sh ip fib 10.20.0.1"))
4594 self.logger.info(self.vapi.cli("sh ip6 fib 10:20::1"))
4596 # two ip6 packets whose port are chosen so they load-balance
4597 p = [(Ether(src=lep1.mac, dst=str(self.router_mac)) /
4599 IPv6(src=lep1.ip6.address, dst="10:20::1") /
4600 UDP(sport=1234, dport=1234) /
4602 (Ether(src=lep1.mac, dst=str(self.router_mac)) /
4604 IPv6(src=lep1.ip6.address, dst="10:20::1") /
4605 UDP(sport=124, dport=1230) /
4608 rxs = self.send_and_expect(self.pg0, p, self.pg0, 2)
4610 self.assertEqual(rxs[0][Dot1Q].vlan, 101)
4611 self.assertEqual(rxs[1][Dot1Q].vlan, 100)
4613 # two ip4 packets whose port are chosen so they load-balance
4614 p = [(Ether(src=lep1.mac, dst=str(self.router_mac)) /
4616 IP(src=lep1.ip4.address, dst="10.20.0.1") /
4617 UDP(sport=1235, dport=1235) /
4619 (Ether(src=lep1.mac, dst=str(self.router_mac)) /
4621 IP(src=lep1.ip4.address, dst="10.20.0.1") /
4622 UDP(sport=124, dport=1230) /
4625 rxs = self.send_and_expect(self.pg0, p, self.pg0, 2)
4627 self.assertEqual(rxs[0][Dot1Q].vlan, 101)
4628 self.assertEqual(rxs[1][Dot1Q].vlan, 100)
4633 ip_222.remove_vpp_config()
4634 self.pg7.unconfig_ip4()
4635 self.vlan_101.set_vtr(L2_VTR_OP.L2_DISABLED)
4636 self.vlan_100.set_vtr(L2_VTR_OP.L2_DISABLED)
4638 def test_gbp_anon_l3_out(self):
4639 """ GBP Anonymous L3 Out """
4641 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
4642 self.vapi.cli("set logging class gbp level debug")
4644 routed_dst_mac = "00:0c:0c:0c:0c:0c"
4645 routed_src_mac = "00:22:bd:f8:19:ff"
4650 t4 = VppIpTable(self, 1)
4652 t6 = VppIpTable(self, 1, True)
4655 rd1 = VppGbpRouteDomain(self, 2, 55, t4, t6)
4656 rd1.add_vpp_config()
4658 self.loop0.set_mac(self.router_mac)
4661 # Bind the BVI to the RD
4663 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
4664 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
4667 # Pg7 hosts a BD's BUM
4668 # Pg1 some other l3 interface
4670 self.pg7.config_ip4()
4671 self.pg7.resolve_arp()
4674 # a GBP external bridge domains for the EPs
4676 bd1 = VppBridgeDomain(self, 1)
4677 bd1.add_vpp_config()
4678 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0, None, None)
4679 gbd1.add_vpp_config()
4682 # The Endpoint-groups in which the external endpoints exist
4684 epg_220 = VppGbpEndpointGroup(self, 220, 113, rd1, gbd1,
4688 VppGbpEndpointRetention(2))
4689 epg_220.add_vpp_config()
4691 # the BVIs have the subnet applied ...
4692 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 24)
4693 ip4_addr.add_vpp_config()
4695 # ... which is an Anonymous L3-out subnets
4696 l3o_1 = VppGbpSubnet(
4697 self, rd1, "10.0.0.0", 24,
4698 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_ANON_L3_OUT,
4700 l3o_1.add_vpp_config()
4703 # an external interface attached to the outside world and the
4706 VppL2Vtr(self, self.vlan_100, L2_VTR_OP.L2_POP_1).add_vpp_config()
4707 VppL2Vtr(self, self.vlan_101, L2_VTR_OP.L2_POP_1).add_vpp_config()
4710 # vlan_100 and vlan_101 are anonymous l3-out interfaces
4712 ext_itf = VppGbpExtItf(self, self.vlan_100, bd1, rd1, anon=True)
4713 ext_itf.add_vpp_config()
4714 ext_itf = VppGbpExtItf(self, self.vlan_101, bd1, rd1, anon=True)
4715 ext_itf.add_vpp_config()
4718 # an unicast vxlan-gbp for inter-RD traffic
4720 vx_tun_l3 = VppGbpVxlanTunnel(
4721 self, 444, rd1.rd_id,
4722 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
4724 vx_tun_l3.add_vpp_config()
4727 # A remote external endpoint
4729 rep = VppGbpEndpoint(self, vx_tun_l3,
4731 "10.0.0.201", "11.0.0.201",
4732 "2001:10::201", "3001::101",
4733 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
4735 self.pg7.remote_ip4,
4737 rep.add_vpp_config()
4740 # ARP packet from host in external subnet are accepted, flooded and
4741 # replied to. We expect 2 packets:
4742 # - APR request flooded over the other vlan subif
4743 # - ARP reply from BVI
4745 p_arp = (Ether(src=self.vlan_100.remote_mac,
4746 dst="ff:ff:ff:ff:ff:ff") /
4751 hwsrc=self.vlan_100.remote_mac,
4752 hwdst="ff:ff:ff:ff:ff:ff"))
4753 rxs = self.send_and_expect(self.pg0, p_arp * 1, self.pg0, n_rx=2)
4755 p_arp = (Ether(src=self.vlan_101.remote_mac,
4756 dst="ff:ff:ff:ff:ff:ff") /
4761 hwsrc=self.vlan_101.remote_mac,
4762 hwdst="ff:ff:ff:ff:ff:ff"))
4763 rxs = self.send_and_expect(self.pg0, p_arp * 1, self.pg0, n_rx=2)
4766 # remote to external
4768 p = (Ether(src=self.pg7.remote_mac,
4769 dst=self.pg7.local_mac) /
4770 IP(src=self.pg7.remote_ip4,
4771 dst=self.pg7.local_ip4) /
4772 UDP(sport=1234, dport=48879) /
4773 VXLAN(vni=vx_tun_l3.vni, gpid=epg_220.sclass, flags=0x88) /
4774 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
4775 IP(src=str(rep.ip4), dst="10.0.0.100") /
4776 UDP(sport=1234, dport=1234) /
4778 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
4781 # local EP pings router
4783 p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
4785 IP(src="10.0.0.100", dst="10.0.0.128") /
4786 ICMP(type='echo-request'))
4787 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
4790 self.assertEqual(rx[Ether].src, str(self.router_mac))
4791 self.assertEqual(rx[Ether].dst, self.vlan_100.remote_mac)
4792 self.assertEqual(rx[Dot1Q].vlan, 100)
4795 # local EP pings other local EP
4797 p = (Ether(src=self.vlan_100.remote_mac,
4798 dst=self.vlan_101.remote_mac) /
4800 IP(src="10.0.0.100", dst="10.0.0.101") /
4801 ICMP(type='echo-request'))
4802 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
4805 self.assertEqual(rx[Ether].src, self.vlan_100.remote_mac)
4806 self.assertEqual(rx[Ether].dst, self.vlan_101.remote_mac)
4807 self.assertEqual(rx[Dot1Q].vlan, 101)
4810 # A subnet reachable through an external router on vlan 100
4812 ip_220 = VppIpRoute(self, "10.220.0.0", 24,
4813 [VppRoutePath("10.0.0.100",
4814 epg_220.bvi.sw_if_index)],
4815 table_id=t4.table_id)
4816 ip_220.add_vpp_config()
4818 l3o_220 = VppGbpSubnet(
4819 self, rd1, "10.220.0.0", 24,
4820 # note: this a "regular" L3 out subnet (not connected)
4821 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
4823 l3o_220.add_vpp_config()
4826 # A subnet reachable through an external router on vlan 101
4828 ip_221 = VppIpRoute(self, "10.221.0.0", 24,
4829 [VppRoutePath("10.0.0.101",
4830 epg_220.bvi.sw_if_index)],
4831 table_id=t4.table_id)
4832 ip_221.add_vpp_config()
4834 l3o_221 = VppGbpSubnet(
4835 self, rd1, "10.221.0.0", 24,
4836 # note: this a "regular" L3 out subnet (not connected)
4837 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
4839 l3o_221.add_vpp_config()
4842 # ping between hosts in remote subnets
4843 # dropped without a contract
4845 p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
4847 IP(src="10.220.0.1", dst="10.221.0.1") /
4848 ICMP(type='echo-request'))
4850 rxs = self.send_and_assert_no_replies(self.pg0, p * 1)
4853 # contract for the external nets to communicate
4855 acl = VppGbpAcl(self)
4856 rule4 = acl.create_rule(permit_deny=1, proto=17)
4857 rule6 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
4858 acl_index = acl.add_vpp_config([rule4, rule6])
4860 c1 = VppGbpContract(
4861 self, 55, 4220, 4221, acl_index,
4862 [VppGbpContractRule(
4863 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4864 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4867 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4868 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4870 [ETH_P_IP, ETH_P_IPV6])
4874 # Contracts allowing ext-net 200 to talk with external EPs
4876 c2 = VppGbpContract(
4877 self, 55, 4220, 113, acl_index,
4878 [VppGbpContractRule(
4879 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4880 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4883 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4884 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4886 [ETH_P_IP, ETH_P_IPV6])
4888 c3 = VppGbpContract(
4889 self, 55, 113, 4220, acl_index,
4890 [VppGbpContractRule(
4891 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4892 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4895 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4896 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4898 [ETH_P_IP, ETH_P_IPV6])
4902 # ping between hosts in remote subnets
4904 p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
4906 IP(src="10.220.0.1", dst="10.221.0.1") /
4907 UDP(sport=1234, dport=1234) /
4910 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
4913 self.assertEqual(rx[Ether].src, str(self.router_mac))
4914 self.assertEqual(rx[Ether].dst, self.vlan_101.remote_mac)
4915 self.assertEqual(rx[Dot1Q].vlan, 101)
4917 # we did not learn these external hosts
4918 self.assertFalse(find_gbp_endpoint(self, ip="10.220.0.1"))
4919 self.assertFalse(find_gbp_endpoint(self, ip="10.221.0.1"))
4922 # from remote external EP to local external EP
4924 p = (Ether(src=self.pg7.remote_mac,
4925 dst=self.pg7.local_mac) /
4926 IP(src=self.pg7.remote_ip4,
4927 dst=self.pg7.local_ip4) /
4928 UDP(sport=1234, dport=48879) /
4929 VXLAN(vni=444, gpid=113, flags=0x88) /
4930 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
4931 IP(src=rep.ip4.address, dst="10.220.0.1") /
4932 UDP(sport=1234, dport=1234) /
4935 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
4938 # ping from an external host to the remote external EP
4940 p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
4942 IP(src="10.220.0.1", dst=rep.ip4.address) /
4943 UDP(sport=1234, dport=1234) /
4946 rxs = self.send_and_expect(self.pg0, p * 1, self.pg7)
4949 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4950 # self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4951 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4952 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4953 self.assertEqual(rx[VXLAN].vni, 444)
4954 self.assertTrue(rx[VXLAN].flags.G)
4955 self.assertTrue(rx[VXLAN].flags.Instance)
4956 # the sclass of the ext-net the packet came from
4957 self.assertEqual(rx[VXLAN].gpid, 4220)
4958 # policy was applied to the original IP packet
4959 self.assertTrue(rx[VXLAN].gpflags.A)
4960 # since it's an external host the reciever should not learn it
4961 self.assertTrue(rx[VXLAN].gpflags.D)
4962 inner = rx[VXLAN].payload
4963 self.assertEqual(inner[IP].src, "10.220.0.1")
4964 self.assertEqual(inner[IP].dst, rep.ip4.address)
4967 # An external subnet reachable via the remote external EP
4971 # first the VXLAN-GBP tunnel over which it is reached
4973 vx_tun_r = VppVxlanGbpTunnel(
4974 self, self.pg7.local_ip4,
4975 self.pg7.remote_ip4, 445,
4976 mode=(VppEnum.vl_api_vxlan_gbp_api_tunnel_mode_t.
4977 VXLAN_GBP_API_TUNNEL_MODE_L3))
4978 vx_tun_r.add_vpp_config()
4979 VppIpInterfaceBind(self, vx_tun_r, t4).add_vpp_config()
4981 self.logger.info(self.vapi.cli("sh vxlan-gbp tunnel"))
4984 # then the special adj to resolve through on that tunnel
4986 n1 = VppNeighbor(self,
4987 vx_tun_r.sw_if_index,
4988 "00:0c:0c:0c:0c:0c",
4989 self.pg7.remote_ip4)
4993 # the route via the adj above
4995 ip_222 = VppIpRoute(self, "10.222.0.0", 24,
4996 [VppRoutePath(self.pg7.remote_ip4,
4997 vx_tun_r.sw_if_index)],
4998 table_id=t4.table_id)
4999 ip_222.add_vpp_config()
5001 l3o_222 = VppGbpSubnet(
5002 self, rd1, "10.222.0.0", 24,
5003 # note: this a "regular" l3out subnet (not connected)
5004 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
5006 l3o_222.add_vpp_config()
5009 # ping between hosts in local and remote external subnets
5010 # dropped without a contract
5012 p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
5014 IP(src="10.220.0.1", dst="10.222.0.1") /
5015 UDP(sport=1234, dport=1234) /
5018 rxs = self.send_and_assert_no_replies(self.pg0, p * 1)
5021 # Add contracts ext-nets for 220 -> 222
5023 c4 = VppGbpContract(
5024 self, 55, 4220, 4222, acl_index,
5025 [VppGbpContractRule(
5026 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5027 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5030 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5031 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5033 [ETH_P_IP, ETH_P_IPV6])
5037 # ping from host in local to remote external subnets
5039 p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
5041 IP(src="10.220.0.1", dst="10.222.0.1") /
5042 UDP(sport=1234, dport=1234) /
5045 rxs = self.send_and_expect(self.pg0, p * 3, self.pg7)
5048 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
5049 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
5050 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
5051 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
5052 self.assertEqual(rx[VXLAN].vni, 445)
5053 self.assertTrue(rx[VXLAN].flags.G)
5054 self.assertTrue(rx[VXLAN].flags.Instance)
5055 # the sclass of the ext-net the packet came from
5056 self.assertEqual(rx[VXLAN].gpid, 4220)
5057 # policy was applied to the original IP packet
5058 self.assertTrue(rx[VXLAN].gpflags.A)
5059 # since it's an external host the reciever should not learn it
5060 self.assertTrue(rx[VXLAN].gpflags.D)
5061 inner = rx[VXLAN].payload
5062 self.assertEqual(inner[Ether].dst, "00:0c:0c:0c:0c:0c")
5063 self.assertEqual(inner[IP].src, "10.220.0.1")
5064 self.assertEqual(inner[IP].dst, "10.222.0.1")
5067 # ping from host in remote to local external subnets
5068 # there's no contract for this, but the A bit is set.
5070 p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
5071 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
5072 UDP(sport=1234, dport=48879) /
5073 VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
5074 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
5075 IP(src="10.222.0.1", dst="10.220.0.1") /
5076 UDP(sport=1234, dport=1234) /
5079 rxs = self.send_and_expect(self.pg7, p * 3, self.pg0)
5080 self.assertFalse(find_gbp_endpoint(self, ip="10.222.0.1"))
5083 # ping from host in remote to remote external subnets
5084 # this is dropped by reflection check.
5086 p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
5087 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
5088 UDP(sport=1234, dport=48879) /
5089 VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
5090 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
5091 IP(src="10.222.0.1", dst="10.222.0.2") /
5092 UDP(sport=1234, dport=1234) /
5095 rxs = self.send_and_assert_no_replies(self.pg7, p * 3)
5100 self.vlan_101.set_vtr(L2_VTR_OP.L2_DISABLED)
5101 self.vlan_100.set_vtr(L2_VTR_OP.L2_DISABLED)
5102 self.pg7.unconfig_ip4()
5105 if __name__ == '__main__':
5106 unittest.main(testRunner=VppTestRunner)