3 from socket import AF_INET, AF_INET6, inet_pton, inet_ntop
5 from ipaddress import ip_address, IPv4Network, IPv6Network
7 from scapy.packet import Raw
8 from scapy.layers.l2 import Ether, ARP, Dot1Q
9 from scapy.layers.inet import IP, UDP, ICMP
10 from scapy.layers.inet6 import IPv6, ICMPv6ND_NS, ICMPv6NDOptSrcLLAddr, \
11 ICMPv6ND_NA, ICMPv6EchoRequest
12 from scapy.utils6 import in6_getnsma, in6_getnsmac
13 from scapy.layers.vxlan import VXLAN
14 from scapy.data import ETH_P_IP, ETH_P_IPV6, ETH_P_ARP
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 DpoProto, get_dpo_proto
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
30 from vpp_acl import AclRule, VppAcl
39 def find_gbp_endpoint(test, sw_if_index=None, ip=None, mac=None,
40 tep=None, sclass=None):
44 vmac = MACAddress(mac)
46 eps = test.vapi.gbp_endpoint_dump()
52 if src != str(ep.endpoint.tun.src) or \
53 dst != str(ep.endpoint.tun.dst):
56 if ep.endpoint.sw_if_index != sw_if_index:
59 if ep.endpoint.sclass != sclass:
62 for eip in ep.endpoint.ips:
66 if vmac == ep.endpoint.mac:
72 def find_gbp_vxlan(test, vni):
73 ts = test.vapi.gbp_vxlan_tunnel_dump()
75 if t.tunnel.vni == vni:
80 class VppGbpEndpoint(VppObject):
107 return [self.ip4, self.ip6]
111 return [self.fip4, self.fip6]
113 def __init__(self, test, itf, epg, recirc, ip4, fip4, ip6, fip6,
129 self.vmac = MACAddress(self.itf.remote_mac)
131 self.vmac = MACAddress("00:00:00:00:00:00")
134 self.tun_src = tun_src
135 self.tun_dst = tun_dst
137 def add_vpp_config(self):
138 res = self._test.vapi.gbp_endpoint_add(
139 self.itf.sw_if_index,
140 [self.ip4, self.ip6],
146 self.handle = res.handle
147 self._test.registry.register(self, self._test.logger)
149 def remove_vpp_config(self):
150 self._test.vapi.gbp_endpoint_del(self.handle)
153 return "gbp-endpoint:[%d==%d:%s:%d]" % (self.handle,
154 self.itf.sw_if_index,
158 def query_vpp_config(self):
159 return find_gbp_endpoint(self._test,
160 self.itf.sw_if_index,
164 class VppGbpRecirc(VppObject):
166 GBP Recirculation Interface
169 def __init__(self, test, epg, recirc, is_ext=False):
175 def add_vpp_config(self):
176 self._test.vapi.gbp_recirc_add_del(
178 self.recirc.sw_if_index,
181 self._test.registry.register(self, self._test.logger)
183 def remove_vpp_config(self):
184 self._test.vapi.gbp_recirc_add_del(
186 self.recirc.sw_if_index,
191 return "gbp-recirc:[%d]" % (self.recirc.sw_if_index)
193 def query_vpp_config(self):
194 rs = self._test.vapi.gbp_recirc_dump()
196 if r.recirc.sw_if_index == self.recirc.sw_if_index:
201 class VppGbpExtItf(VppObject):
203 GBP ExtItfulation Interface
206 def __init__(self, test, itf, bd, rd, anon=False):
211 self.flags = 1 if anon else 0
213 def add_vpp_config(self):
214 self._test.vapi.gbp_ext_itf_add_del(
215 1, self.itf.sw_if_index, self.bd.bd_id, self.rd.rd_id, self.flags)
216 self._test.registry.register(self, self._test.logger)
218 def remove_vpp_config(self):
219 self._test.vapi.gbp_ext_itf_add_del(
220 0, self.itf.sw_if_index, self.bd.bd_id, self.rd.rd_id, self.flags)
223 return "gbp-ext-itf:[%d]%s" % (self.itf.sw_if_index,
224 " [anon]" if self.flags else "")
226 def query_vpp_config(self):
227 rs = self._test.vapi.gbp_ext_itf_dump()
229 if r.ext_itf.sw_if_index == self.itf.sw_if_index:
234 class VppGbpSubnet(VppObject):
239 def __init__(self, test, rd, address, address_len,
240 type, sw_if_index=None, sclass=None):
242 self.rd_id = rd.rd_id
243 a = ip_address(address)
245 self.prefix = IPv4Network("%s/%d" % (address, address_len),
248 self.prefix = IPv6Network("%s/%d" % (address, address_len),
251 self.sw_if_index = sw_if_index
254 def add_vpp_config(self):
255 self._test.vapi.gbp_subnet_add_del(
260 sw_if_index=self.sw_if_index if self.sw_if_index else 0xffffffff,
261 sclass=self.sclass if self.sclass else 0xffff)
262 self._test.registry.register(self, self._test.logger)
264 def remove_vpp_config(self):
265 self._test.vapi.gbp_subnet_add_del(
272 return "gbp-subnet:[%d-%s]" % (self.rd_id, self.prefix)
274 def query_vpp_config(self):
275 ss = self._test.vapi.gbp_subnet_dump()
277 if s.subnet.rd_id == self.rd_id and \
278 s.subnet.type == self.type and \
279 s.subnet.prefix == self.prefix:
284 class VppGbpEndpointRetention(object):
285 def __init__(self, remote_ep_timeout=0xffffffff):
286 self.remote_ep_timeout = remote_ep_timeout
289 return {'remote_ep_timeout': self.remote_ep_timeout}
292 class VppGbpEndpointGroup(VppObject):
297 def __init__(self, test, vnid, sclass, rd, bd, uplink,
298 bvi, bvi_ip4, bvi_ip6=None,
299 retention=VppGbpEndpointRetention()):
303 self.bvi_ip4 = bvi_ip4
304 self.bvi_ip6 = bvi_ip6
311 self.retention = retention
313 def add_vpp_config(self):
314 self._test.vapi.gbp_endpoint_group_add(
319 self.uplink.sw_if_index if self.uplink else INDEX_INVALID,
320 self.retention.encode())
321 self._test.registry.register(self, self._test.logger)
323 def remove_vpp_config(self):
324 self._test.vapi.gbp_endpoint_group_del(self.sclass)
327 return "gbp-endpoint-group:[%d]" % (self.vnid)
329 def query_vpp_config(self):
330 epgs = self._test.vapi.gbp_endpoint_group_dump()
332 if epg.epg.vnid == self.vnid:
337 class VppGbpBridgeDomain(VppObject):
342 def __init__(self, test, bd, rd, bvi, uu_fwd=None,
343 bm_flood=None, learn=True,
344 uu_drop=False, bm_drop=False,
349 self.bm_flood = bm_flood
353 e = VppEnum.vl_api_gbp_bridge_domain_flags_t
355 self.flags = e.GBP_BD_API_FLAG_NONE
357 self.flags |= e.GBP_BD_API_FLAG_DO_NOT_LEARN
359 self.flags |= e.GBP_BD_API_FLAG_UU_FWD_DROP
361 self.flags |= e.GBP_BD_API_FLAG_MCAST_DROP
363 self.flags |= e.GBP_BD_API_FLAG_UCAST_ARP
365 def add_vpp_config(self):
366 self._test.vapi.gbp_bridge_domain_add(
370 self.bvi.sw_if_index,
371 self.uu_fwd.sw_if_index if self.uu_fwd else INDEX_INVALID,
372 self.bm_flood.sw_if_index if self.bm_flood else INDEX_INVALID)
373 self._test.registry.register(self, self._test.logger)
375 def remove_vpp_config(self):
376 self._test.vapi.gbp_bridge_domain_del(self.bd.bd_id)
379 return "gbp-bridge-domain:[%d]" % (self.bd.bd_id)
381 def query_vpp_config(self):
382 bds = self._test.vapi.gbp_bridge_domain_dump()
384 if bd.bd.bd_id == self.bd.bd_id:
389 class VppGbpRouteDomain(VppObject):
394 def __init__(self, test, rd_id, scope, t4, t6, ip4_uu=None, ip6_uu=None):
403 def add_vpp_config(self):
404 self._test.vapi.gbp_route_domain_add(
409 self.ip4_uu.sw_if_index if self.ip4_uu else INDEX_INVALID,
410 self.ip6_uu.sw_if_index if self.ip6_uu else INDEX_INVALID)
411 self._test.registry.register(self, self._test.logger)
413 def remove_vpp_config(self):
414 self._test.vapi.gbp_route_domain_del(self.rd_id)
417 return "gbp-route-domain:[%d]" % (self.rd_id)
419 def query_vpp_config(self):
420 rds = self._test.vapi.gbp_route_domain_dump()
422 if rd.rd.rd_id == self.rd_id:
427 class VppGbpContractNextHop():
428 def __init__(self, mac, bd, ip, rd):
435 return {'ip': self.ip,
436 'mac': self.mac.packed,
437 'bd_id': self.bd.bd.bd_id,
438 'rd_id': self.rd.rd_id}
441 class VppGbpContractRule():
442 def __init__(self, action, hash_mode, nhs=None):
444 self.hash_mode = hash_mode
445 self.nhs = [] if nhs is None else nhs
450 nhs.append(nh.encode())
453 return {'action': self.action,
455 'hash_mode': self.hash_mode,
456 'n_nhs': len(self.nhs),
460 return '<VppGbpContractRule action=%s, hash_mode=%s>' % (
461 self.action, self.hash_mode)
464 class VppGbpContract(VppObject):
469 def __init__(self, test, scope, sclass, dclass, acl_index,
470 rules, allowed_ethertypes):
472 if not isinstance(rules, list):
473 raise ValueError("'rules' must be a list.")
474 if not isinstance(allowed_ethertypes, list):
475 raise ValueError("'allowed_ethertypes' must be a list.")
477 self.acl_index = acl_index
481 self.allowed_ethertypes = allowed_ethertypes
482 while (len(self.allowed_ethertypes) < 16):
483 self.allowed_ethertypes.append(0)
485 def add_vpp_config(self):
488 rules.append(r.encode())
489 r = self._test.vapi.gbp_contract_add_del(
492 'acl_index': self.acl_index,
494 'sclass': self.sclass,
495 'dclass': self.dclass,
496 'n_rules': len(rules),
498 'n_ether_types': len(self.allowed_ethertypes),
499 'allowed_ethertypes': self.allowed_ethertypes})
500 self.stats_index = r.stats_index
501 self._test.registry.register(self, self._test.logger)
503 def remove_vpp_config(self):
504 self._test.vapi.gbp_contract_add_del(
507 'acl_index': self.acl_index,
509 'sclass': self.sclass,
510 'dclass': self.dclass,
513 'n_ether_types': len(self.allowed_ethertypes),
514 'allowed_ethertypes': self.allowed_ethertypes})
517 return "gbp-contract:[%d:%d:%d:%d]" % (self.scope,
522 def query_vpp_config(self):
523 cs = self._test.vapi.gbp_contract_dump()
525 if c.contract.scope == self.scope \
526 and c.contract.sclass == self.sclass \
527 and c.contract.dclass == self.dclass:
531 def get_drop_stats(self):
532 c = self._test.statistics.get_counter("/net/gbp/contract/drop")
533 return c[0][self.stats_index]
535 def get_permit_stats(self):
536 c = self._test.statistics.get_counter("/net/gbp/contract/permit")
537 return c[0][self.stats_index]
540 class VppGbpVxlanTunnel(VppInterface):
545 def __init__(self, test, vni, bd_rd_id, mode, src):
546 super(VppGbpVxlanTunnel, self).__init__(test)
549 self.bd_rd_id = bd_rd_id
553 def add_vpp_config(self):
554 r = self._test.vapi.gbp_vxlan_tunnel_add(
559 self.set_sw_if_index(r.sw_if_index)
560 self._test.registry.register(self, self._test.logger)
562 def remove_vpp_config(self):
563 self._test.vapi.gbp_vxlan_tunnel_del(self.vni)
566 return "gbp-vxlan:%d" % (self.sw_if_index)
568 def query_vpp_config(self):
569 return find_gbp_vxlan(self._test, self.vni)
572 class TestGBP(VppTestCase):
573 """ GBP Test Case """
576 def config_flags(self):
577 return VppEnum.vl_api_nat_config_flags_t
581 super(TestGBP, cls).setUpClass()
584 def tearDownClass(cls):
585 super(TestGBP, cls).tearDownClass()
588 super(TestGBP, self).setUp()
590 self.create_pg_interfaces(range(9))
591 self.create_loopback_interfaces(8)
593 self.router_mac = MACAddress("00:11:22:33:44:55")
595 for i in self.pg_interfaces:
597 for i in self.lo_interfaces:
600 self.vlan_100 = VppDot1QSubint(self, self.pg0, 100)
601 self.vlan_100.admin_up()
602 self.vlan_101 = VppDot1QSubint(self, self.pg0, 101)
603 self.vlan_101.admin_up()
604 self.vlan_102 = VppDot1QSubint(self, self.pg0, 102)
605 self.vlan_102.admin_up()
608 for i in self.pg_interfaces:
610 super(TestGBP, self).tearDown()
611 for i in self.lo_interfaces:
612 i.remove_vpp_config()
613 self.lo_interfaces = []
614 self.vlan_102.remove_vpp_config()
615 self.vlan_101.remove_vpp_config()
616 self.vlan_100.remove_vpp_config()
618 def send_and_expect_bridged(self, src, tx, dst):
619 rx = self.send_and_expect(src, tx, dst)
622 self.assertEqual(r[Ether].src, tx[0][Ether].src)
623 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
624 self.assertEqual(r[IP].src, tx[0][IP].src)
625 self.assertEqual(r[IP].dst, tx[0][IP].dst)
628 def send_and_expect_bridged6(self, src, tx, dst):
629 rx = self.send_and_expect(src, tx, dst)
632 self.assertEqual(r[Ether].src, tx[0][Ether].src)
633 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
634 self.assertEqual(r[IPv6].src, tx[0][IPv6].src)
635 self.assertEqual(r[IPv6].dst, tx[0][IPv6].dst)
638 def send_and_expect_routed(self, src, tx, dst, src_mac):
639 rx = self.send_and_expect(src, tx, dst)
642 self.assertEqual(r[Ether].src, src_mac)
643 self.assertEqual(r[Ether].dst, dst.remote_mac)
644 self.assertEqual(r[IP].src, tx[0][IP].src)
645 self.assertEqual(r[IP].dst, tx[0][IP].dst)
648 def send_and_expect_routed6(self, src, tx, dst, src_mac):
649 rx = self.send_and_expect(src, tx, dst)
652 self.assertEqual(r[Ether].src, src_mac)
653 self.assertEqual(r[Ether].dst, dst.remote_mac)
654 self.assertEqual(r[IPv6].src, tx[0][IPv6].src)
655 self.assertEqual(r[IPv6].dst, tx[0][IPv6].dst)
658 def send_and_expect_natted(self, src, tx, dst, src_ip):
659 rx = self.send_and_expect(src, tx, dst)
662 self.assertEqual(r[Ether].src, tx[0][Ether].src)
663 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
664 self.assertEqual(r[IP].src, src_ip)
665 self.assertEqual(r[IP].dst, tx[0][IP].dst)
668 def send_and_expect_natted6(self, src, tx, dst, src_ip):
669 rx = self.send_and_expect(src, tx, dst)
672 self.assertEqual(r[Ether].src, tx[0][Ether].src)
673 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
674 self.assertEqual(r[IPv6].src, src_ip)
675 self.assertEqual(r[IPv6].dst, tx[0][IPv6].dst)
678 def send_and_expect_unnatted(self, src, tx, dst, dst_ip):
679 rx = self.send_and_expect(src, tx, dst)
682 self.assertEqual(r[Ether].src, tx[0][Ether].src)
683 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
684 self.assertEqual(r[IP].dst, dst_ip)
685 self.assertEqual(r[IP].src, tx[0][IP].src)
688 def send_and_expect_unnatted6(self, src, tx, dst, dst_ip):
689 rx = self.send_and_expect(src, tx, dst)
692 self.assertEqual(r[Ether].src, tx[0][Ether].src)
693 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
694 self.assertEqual(r[IPv6].dst, dst_ip)
695 self.assertEqual(r[IPv6].src, tx[0][IPv6].src)
698 def send_and_expect_double_natted(self, src, tx, dst, src_ip, dst_ip):
699 rx = self.send_and_expect(src, tx, dst)
702 self.assertEqual(r[Ether].src, str(self.router_mac))
703 self.assertEqual(r[Ether].dst, dst.remote_mac)
704 self.assertEqual(r[IP].dst, dst_ip)
705 self.assertEqual(r[IP].src, src_ip)
708 def send_and_expect_double_natted6(self, src, tx, dst, src_ip, dst_ip):
709 rx = self.send_and_expect(src, tx, dst)
712 self.assertEqual(r[Ether].src, str(self.router_mac))
713 self.assertEqual(r[Ether].dst, dst.remote_mac)
714 self.assertEqual(r[IPv6].dst, dst_ip)
715 self.assertEqual(r[IPv6].src, src_ip)
718 def send_and_expect_no_arp(self, src, tx, dst):
719 self.pg_send(src, tx)
720 dst.get_capture(0, timeout=1)
721 dst.assert_nothing_captured(remark="")
724 def send_and_expect_arp(self, src, tx, dst):
725 rx = self.send_and_expect(src, tx, dst)
728 self.assertEqual(r[Ether].src, tx[0][Ether].src)
729 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
730 self.assertEqual(r[ARP].psrc, tx[0][ARP].psrc)
731 self.assertEqual(r[ARP].pdst, tx[0][ARP].pdst)
732 self.assertEqual(r[ARP].hwsrc, tx[0][ARP].hwsrc)
733 self.assertEqual(r[ARP].hwdst, tx[0][ARP].hwdst)
737 """ Group Based Policy """
739 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
744 gt4 = VppIpTable(self, 0)
746 gt6 = VppIpTable(self, 0, is_ip6=True)
748 nt4 = VppIpTable(self, 20)
750 nt6 = VppIpTable(self, 20, is_ip6=True)
753 rd0 = VppGbpRouteDomain(self, 0, 400, gt4, gt6, None, None)
754 rd20 = VppGbpRouteDomain(self, 20, 420, nt4, nt6, None, None)
757 rd20.add_vpp_config()
762 bd1 = VppBridgeDomain(self, 1)
763 bd2 = VppBridgeDomain(self, 2)
764 bd20 = VppBridgeDomain(self, 20)
768 bd20.add_vpp_config()
770 gbd1 = VppGbpBridgeDomain(self, bd1, rd0, self.loop0)
771 gbd2 = VppGbpBridgeDomain(self, bd2, rd0, self.loop1)
772 gbd20 = VppGbpBridgeDomain(self, bd20, rd20, self.loop2)
774 gbd1.add_vpp_config()
775 gbd2.add_vpp_config()
776 gbd20.add_vpp_config()
779 # 3 EPGs, 2 of which share a BD.
780 # 2 NAT EPGs, one for floating-IP subnets, the other for internet
782 epgs = [VppGbpEndpointGroup(self, 220, 1220, rd0, gbd1,
783 self.pg4, self.loop0,
784 "10.0.0.128", "2001:10::128"),
785 VppGbpEndpointGroup(self, 221, 1221, rd0, gbd1,
786 self.pg5, self.loop0,
787 "10.0.1.128", "2001:10:1::128"),
788 VppGbpEndpointGroup(self, 222, 1222, rd0, gbd2,
789 self.pg6, self.loop1,
790 "10.0.2.128", "2001:10:2::128"),
791 VppGbpEndpointGroup(self, 333, 1333, rd20, gbd20,
792 self.pg7, self.loop2,
793 "11.0.0.128", "3001::128"),
794 VppGbpEndpointGroup(self, 444, 1444, rd20, gbd20,
795 self.pg8, self.loop2,
796 "11.0.0.129", "3001::129")]
797 recircs = [VppGbpRecirc(self, epgs[0], self.loop3),
798 VppGbpRecirc(self, epgs[1], self.loop4),
799 VppGbpRecirc(self, epgs[2], self.loop5),
800 VppGbpRecirc(self, epgs[3], self.loop6, is_ext=True),
801 VppGbpRecirc(self, epgs[4], self.loop7, is_ext=True)]
804 recirc_nat = recircs[3]
807 # 4 end-points, 2 in the same subnet, 3 in the same BD
809 eps = [VppGbpEndpoint(self, self.pg0,
811 "10.0.0.1", "11.0.0.1",
812 "2001:10::1", "3001::1"),
813 VppGbpEndpoint(self, self.pg1,
815 "10.0.0.2", "11.0.0.2",
816 "2001:10::2", "3001::2"),
817 VppGbpEndpoint(self, self.pg2,
819 "10.0.1.1", "11.0.0.3",
820 "2001:10:1::1", "3001::3"),
821 VppGbpEndpoint(self, self.pg3,
823 "10.0.2.1", "11.0.0.4",
824 "2001:10:2::1", "3001::4")]
827 # Config related to each of the EPGs
830 # IP config on the BVI interfaces
831 if epg != epgs[1] and epg != epgs[4]:
832 VppIpInterfaceBind(self, epg.bvi, epg.rd.t4).add_vpp_config()
833 VppIpInterfaceBind(self, epg.bvi, epg.rd.t6).add_vpp_config()
834 epg.bvi.set_mac(self.router_mac)
836 # The BVIs are NAT inside interfaces
837 flags = self.config_flags.NAT_IS_INSIDE
838 self.vapi.nat44_interface_add_del_feature(
839 sw_if_index=epg.bvi.sw_if_index,
840 flags=flags, is_add=1)
841 self.vapi.nat66_add_del_interface(
842 is_add=1, flags=flags,
843 sw_if_index=epg.bvi.sw_if_index)
845 if_ip4 = VppIpInterfaceAddress(self, epg.bvi, epg.bvi_ip4, 32)
846 if_ip6 = VppIpInterfaceAddress(self, epg.bvi, epg.bvi_ip6, 128)
847 if_ip4.add_vpp_config()
848 if_ip6.add_vpp_config()
850 # EPG uplink interfaces in the RD
851 VppIpInterfaceBind(self, epg.uplink, epg.rd.t4).add_vpp_config()
852 VppIpInterfaceBind(self, epg.uplink, epg.rd.t6).add_vpp_config()
854 # add the BD ARP termination entry for BVI IP
855 epg.bd_arp_ip4 = VppBridgeDomainArpEntry(self, epg.bd.bd,
856 str(self.router_mac),
858 epg.bd_arp_ip6 = VppBridgeDomainArpEntry(self, epg.bd.bd,
859 str(self.router_mac),
861 epg.bd_arp_ip4.add_vpp_config()
862 epg.bd_arp_ip6.add_vpp_config()
867 for recirc in recircs:
868 # EPG's ingress recirculation interface maps to its RD
869 VppIpInterfaceBind(self, recirc.recirc,
870 recirc.epg.rd.t4).add_vpp_config()
871 VppIpInterfaceBind(self, recirc.recirc,
872 recirc.epg.rd.t6).add_vpp_config()
874 self.vapi.nat44_interface_add_del_feature(
875 sw_if_index=recirc.recirc.sw_if_index, is_add=1)
876 self.vapi.nat66_add_del_interface(
878 sw_if_index=recirc.recirc.sw_if_index)
880 recirc.add_vpp_config()
882 for recirc in recircs:
883 self.assertTrue(find_bridge_domain_port(self,
884 recirc.epg.bd.bd.bd_id,
885 recirc.recirc.sw_if_index))
888 self.pg_enable_capture(self.pg_interfaces)
891 # routes to the endpoints. We need these since there are no
892 # adj-fibs due to the fact the the BVI address has /32 and
893 # the subnet is not attached.
895 for (ip, fip) in zip(ep.ips, ep.fips):
896 # Add static mappings for each EP from the 10/8 to 11/8 network
897 if ip_address(ip).version == 4:
898 flags = self.config_flags.NAT_IS_ADDR_ONLY
899 self.vapi.nat44_add_del_static_mapping(
902 external_ip_address=fip,
903 external_sw_if_index=0xFFFFFFFF,
907 self.vapi.nat66_add_del_static_mapping(
909 external_ip_address=fip,
915 self.logger.info(self.vapi.cli("sh gbp endpoint"))
917 # ... results in a Gratuitous ARP/ND on the EPG's uplink
918 rx = ep.epg.uplink.get_capture(len(ep.ips), timeout=0.2)
920 for ii, ip in enumerate(ep.ips):
923 if ip_address(ip).version == 6:
924 self.assertTrue(p.haslayer(ICMPv6ND_NA))
925 self.assertEqual(p[ICMPv6ND_NA].tgt, ip)
927 self.assertTrue(p.haslayer(ARP))
928 self.assertEqual(p[ARP].psrc, ip)
929 self.assertEqual(p[ARP].pdst, ip)
931 # add the BD ARP termination entry for floating IP
933 ba = VppBridgeDomainArpEntry(self, epg_nat.bd.bd, ep.mac,
937 # floating IPs route via EPG recirc
939 self, fip, ip_address(fip).max_prefixlen,
941 ep.recirc.recirc.sw_if_index,
942 type=FibPathType.FIB_PATH_TYPE_DVR,
943 proto=get_dpo_proto(fip))],
947 # L2 FIB entries in the NAT EPG BD to bridge the packets from
948 # the outside direct to the internal EPG
949 lf = VppL2FibEntry(self, epg_nat.bd.bd, ep.mac,
950 ep.recirc.recirc, bvi_mac=0)
954 # ARP packets for unknown IP are sent to the EPG uplink
956 pkt_arp = (Ether(dst="ff:ff:ff:ff:ff:ff",
957 src=self.pg0.remote_mac) /
959 hwdst="ff:ff:ff:ff:ff:ff",
960 hwsrc=self.pg0.remote_mac,
964 self.vapi.cli("clear trace")
965 self.pg0.add_stream(pkt_arp)
967 self.pg_enable_capture(self.pg_interfaces)
970 rxd = epgs[0].uplink.get_capture(1)
973 # ARP/ND packets get a response
975 pkt_arp = (Ether(dst="ff:ff:ff:ff:ff:ff",
976 src=self.pg0.remote_mac) /
978 hwdst="ff:ff:ff:ff:ff:ff",
979 hwsrc=self.pg0.remote_mac,
980 pdst=epgs[0].bvi_ip4,
983 self.send_and_expect(self.pg0, [pkt_arp], self.pg0)
985 nsma = in6_getnsma(inet_pton(AF_INET6, eps[0].ip6))
986 d = inet_ntop(AF_INET6, nsma)
987 pkt_nd = (Ether(dst=in6_getnsmac(nsma),
988 src=self.pg0.remote_mac) /
989 IPv6(dst=d, src=eps[0].ip6) /
990 ICMPv6ND_NS(tgt=epgs[0].bvi_ip6) /
991 ICMPv6NDOptSrcLLAddr(lladdr=self.pg0.remote_mac))
992 self.send_and_expect(self.pg0, [pkt_nd], self.pg0)
995 # broadcast packets are flooded
997 pkt_bcast = (Ether(dst="ff:ff:ff:ff:ff:ff",
998 src=self.pg0.remote_mac) /
999 IP(src=eps[0].ip4, dst="232.1.1.1") /
1000 UDP(sport=1234, dport=1234) /
1003 self.vapi.cli("clear trace")
1004 self.pg0.add_stream(pkt_bcast)
1006 self.pg_enable_capture(self.pg_interfaces)
1009 rxd = eps[1].itf.get_capture(1)
1010 self.assertEqual(rxd[0][Ether].dst, pkt_bcast[Ether].dst)
1011 rxd = epgs[0].uplink.get_capture(1)
1012 self.assertEqual(rxd[0][Ether].dst, pkt_bcast[Ether].dst)
1015 # packets to non-local L3 destinations dropped
1017 pkt_intra_epg_220_ip4 = (Ether(src=self.pg0.remote_mac,
1018 dst=str(self.router_mac)) /
1021 UDP(sport=1234, dport=1234) /
1023 pkt_inter_epg_222_ip4 = (Ether(src=self.pg0.remote_mac,
1024 dst=str(self.router_mac)) /
1027 UDP(sport=1234, dport=1234) /
1030 self.send_and_assert_no_replies(self.pg0,
1031 pkt_intra_epg_220_ip4 * NUM_PKTS)
1033 pkt_inter_epg_222_ip6 = (Ether(src=self.pg0.remote_mac,
1034 dst=str(self.router_mac)) /
1035 IPv6(src=eps[0].ip6,
1036 dst="2001:10::99") /
1037 UDP(sport=1234, dport=1234) /
1039 self.send_and_assert_no_replies(self.pg0,
1040 pkt_inter_epg_222_ip6 * NUM_PKTS)
1043 # Add the subnet routes
1046 self, rd0, "10.0.0.0", 24,
1047 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1049 self, rd0, "10.0.1.0", 24,
1050 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1052 self, rd0, "10.0.2.0", 24,
1053 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1055 self, rd0, "2001:10::1", 64,
1056 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1058 self, rd0, "2001:10:1::1", 64,
1059 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1061 self, rd0, "2001:10:2::1", 64,
1062 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1063 s41.add_vpp_config()
1064 s42.add_vpp_config()
1065 s43.add_vpp_config()
1066 s61.add_vpp_config()
1067 s62.add_vpp_config()
1068 s63.add_vpp_config()
1070 self.send_and_expect_bridged(eps[0].itf,
1071 pkt_intra_epg_220_ip4 * NUM_PKTS,
1073 self.send_and_expect_bridged(eps[0].itf,
1074 pkt_inter_epg_222_ip4 * NUM_PKTS,
1076 self.send_and_expect_bridged6(eps[0].itf,
1077 pkt_inter_epg_222_ip6 * NUM_PKTS,
1080 self.logger.info(self.vapi.cli("sh ip fib 11.0.0.2"))
1081 self.logger.info(self.vapi.cli("sh gbp endpoint-group"))
1082 self.logger.info(self.vapi.cli("sh gbp endpoint"))
1083 self.logger.info(self.vapi.cli("sh gbp recirc"))
1084 self.logger.info(self.vapi.cli("sh int"))
1085 self.logger.info(self.vapi.cli("sh int addr"))
1086 self.logger.info(self.vapi.cli("sh int feat loop6"))
1087 self.logger.info(self.vapi.cli("sh vlib graph ip4-gbp-src-classify"))
1088 self.logger.info(self.vapi.cli("sh int feat loop3"))
1089 self.logger.info(self.vapi.cli("sh int feat pg0"))
1092 # Packet destined to unknown unicast is sent on the epg uplink ...
1094 pkt_intra_epg_220_to_uplink = (Ether(src=self.pg0.remote_mac,
1095 dst="00:00:00:33:44:55") /
1098 UDP(sport=1234, dport=1234) /
1101 self.send_and_expect_bridged(eps[0].itf,
1102 pkt_intra_epg_220_to_uplink * NUM_PKTS,
1104 # ... and nowhere else
1105 self.pg1.get_capture(0, timeout=0.1)
1106 self.pg1.assert_nothing_captured(remark="Flood onto other VMS")
1108 pkt_intra_epg_221_to_uplink = (Ether(src=self.pg2.remote_mac,
1109 dst="00:00:00:33:44:66") /
1112 UDP(sport=1234, dport=1234) /
1115 self.send_and_expect_bridged(eps[2].itf,
1116 pkt_intra_epg_221_to_uplink * NUM_PKTS,
1120 # Packets from the uplink are forwarded in the absence of a contract
1122 pkt_intra_epg_220_from_uplink = (Ether(src="00:00:00:33:44:55",
1123 dst=self.pg0.remote_mac) /
1126 UDP(sport=1234, dport=1234) /
1129 self.send_and_expect_bridged(self.pg4,
1130 pkt_intra_epg_220_from_uplink * NUM_PKTS,
1134 # in the absence of policy, endpoints in the same EPG
1137 pkt_intra_epg = (Ether(src=self.pg0.remote_mac,
1138 dst=self.pg1.remote_mac) /
1141 UDP(sport=1234, dport=1234) /
1144 self.send_and_expect_bridged(self.pg0,
1145 pkt_intra_epg * NUM_PKTS,
1149 # in the absence of policy, endpoints in the different EPG
1150 # cannot communicate
1152 pkt_inter_epg_220_to_221 = (Ether(src=self.pg0.remote_mac,
1153 dst=self.pg2.remote_mac) /
1156 UDP(sport=1234, dport=1234) /
1158 pkt_inter_epg_221_to_220 = (Ether(src=self.pg2.remote_mac,
1159 dst=self.pg0.remote_mac) /
1162 UDP(sport=1234, dport=1234) /
1164 pkt_inter_epg_220_to_222 = (Ether(src=self.pg0.remote_mac,
1165 dst=str(self.router_mac)) /
1168 UDP(sport=1234, dport=1234) /
1171 self.send_and_assert_no_replies(eps[0].itf,
1172 pkt_inter_epg_220_to_221 * NUM_PKTS)
1173 self.send_and_assert_no_replies(eps[0].itf,
1174 pkt_inter_epg_220_to_222 * NUM_PKTS)
1177 # A uni-directional contract from EPG 220 -> 221
1179 rule = AclRule(is_permit=1, proto=17)
1180 rule2 = AclRule(src_prefix=IPv6Network((0, 0)),
1181 dst_prefix=IPv6Network((0, 0)), is_permit=1, proto=17)
1182 acl = VppAcl(self, rules=[rule, rule2])
1183 acl.add_vpp_config()
1185 c1 = VppGbpContract(
1186 self, 400, epgs[0].sclass, epgs[1].sclass, acl.acl_index,
1187 [VppGbpContractRule(
1188 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1189 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1192 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1193 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1195 [ETH_P_IP, ETH_P_IPV6])
1198 self.send_and_expect_bridged(eps[0].itf,
1199 pkt_inter_epg_220_to_221 * NUM_PKTS,
1201 self.send_and_assert_no_replies(eps[0].itf,
1202 pkt_inter_epg_220_to_222 * NUM_PKTS)
1205 # contract for the return direction
1207 c2 = VppGbpContract(
1208 self, 400, epgs[1].sclass, epgs[0].sclass, acl.acl_index,
1209 [VppGbpContractRule(
1210 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1211 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1214 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1215 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1217 [ETH_P_IP, ETH_P_IPV6])
1220 self.send_and_expect_bridged(eps[0].itf,
1221 pkt_inter_epg_220_to_221 * NUM_PKTS,
1223 self.send_and_expect_bridged(eps[2].itf,
1224 pkt_inter_epg_221_to_220 * NUM_PKTS,
1227 ds = c2.get_drop_stats()
1228 self.assertEqual(ds['packets'], 0)
1229 ps = c2.get_permit_stats()
1230 self.assertEqual(ps['packets'], NUM_PKTS)
1233 # the contract does not allow non-IP
1235 pkt_non_ip_inter_epg_220_to_221 = (Ether(src=self.pg0.remote_mac,
1236 dst=self.pg2.remote_mac) /
1238 self.send_and_assert_no_replies(eps[0].itf,
1239 pkt_non_ip_inter_epg_220_to_221 * 17)
1242 # check that inter group is still disabled for the groups
1243 # not in the contract.
1245 self.send_and_assert_no_replies(eps[0].itf,
1246 pkt_inter_epg_220_to_222 * NUM_PKTS)
1249 # A uni-directional contract from EPG 220 -> 222 'L3 routed'
1251 c3 = VppGbpContract(
1252 self, 400, epgs[0].sclass, epgs[2].sclass, acl.acl_index,
1253 [VppGbpContractRule(
1254 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1255 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1258 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1259 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1261 [ETH_P_IP, ETH_P_IPV6])
1264 self.logger.info(self.vapi.cli("sh gbp contract"))
1266 self.send_and_expect_routed(eps[0].itf,
1267 pkt_inter_epg_220_to_222 * NUM_PKTS,
1269 str(self.router_mac))
1272 # remove both contracts, traffic stops in both directions
1274 c2.remove_vpp_config()
1275 c1.remove_vpp_config()
1276 c3.remove_vpp_config()
1277 acl.remove_vpp_config()
1279 self.send_and_assert_no_replies(eps[2].itf,
1280 pkt_inter_epg_221_to_220 * NUM_PKTS)
1281 self.send_and_assert_no_replies(eps[0].itf,
1282 pkt_inter_epg_220_to_221 * NUM_PKTS)
1283 self.send_and_expect_bridged(eps[0].itf,
1284 pkt_intra_epg * NUM_PKTS,
1288 # EPs to the outside world
1291 # in the EP's RD an external subnet via the NAT EPG's recirc
1293 self, rd0, "0.0.0.0", 0,
1294 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1295 sw_if_index=recirc_nat.recirc.sw_if_index,
1296 sclass=epg_nat.sclass)
1298 self, rd0, "11.0.0.0", 8,
1299 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1300 sw_if_index=recirc_nat.recirc.sw_if_index,
1301 sclass=epg_nat.sclass)
1302 se16 = VppGbpSubnet(
1304 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1305 sw_if_index=recirc_nat.recirc.sw_if_index,
1306 sclass=epg_nat.sclass)
1307 # in the NAT RD an external subnet via the NAT EPG's uplink
1309 self, rd20, "0.0.0.0", 0,
1310 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1311 sw_if_index=epg_nat.uplink.sw_if_index,
1312 sclass=epg_nat.sclass)
1313 se36 = VppGbpSubnet(
1314 self, rd20, "::", 0,
1315 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1316 sw_if_index=epg_nat.uplink.sw_if_index,
1317 sclass=epg_nat.sclass)
1319 self, rd20, "11.0.0.0", 8,
1320 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1321 sw_if_index=epg_nat.uplink.sw_if_index,
1322 sclass=epg_nat.sclass)
1323 se1.add_vpp_config()
1324 se2.add_vpp_config()
1325 se16.add_vpp_config()
1326 se3.add_vpp_config()
1327 se36.add_vpp_config()
1328 se4.add_vpp_config()
1330 self.logger.info(self.vapi.cli("sh ip fib 0.0.0.0/0"))
1331 self.logger.info(self.vapi.cli("sh ip fib 11.0.0.1"))
1332 self.logger.info(self.vapi.cli("sh ip6 fib ::/0"))
1333 self.logger.info(self.vapi.cli("sh ip6 fib %s" %
1337 # From an EP to an outside address: IN2OUT
1339 pkt_inter_epg_220_to_global = (Ether(src=self.pg0.remote_mac,
1340 dst=str(self.router_mac)) /
1343 UDP(sport=1234, dport=1234) /
1347 self.send_and_assert_no_replies(eps[0].itf,
1348 pkt_inter_epg_220_to_global * NUM_PKTS)
1349 rule = AclRule(is_permit=1, proto=17, ports=1234)
1350 rule2 = AclRule(is_permit=1, proto=17, ports=1234,
1351 src_prefix=IPv6Network((0, 0)),
1352 dst_prefix=IPv6Network((0, 0)))
1353 acl2 = VppAcl(self, rules=[rule, rule2])
1354 acl2.add_vpp_config()
1356 c4 = VppGbpContract(
1357 self, 400, epgs[0].sclass, epgs[3].sclass, acl2.acl_index,
1358 [VppGbpContractRule(
1359 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1360 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1363 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1364 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1366 [ETH_P_IP, ETH_P_IPV6])
1369 self.send_and_expect_natted(eps[0].itf,
1370 pkt_inter_epg_220_to_global * NUM_PKTS,
1374 pkt_inter_epg_220_to_global = (Ether(src=self.pg0.remote_mac,
1375 dst=str(self.router_mac)) /
1376 IPv6(src=eps[0].ip6,
1378 UDP(sport=1234, dport=1234) /
1381 self.send_and_expect_natted6(self.pg0,
1382 pkt_inter_epg_220_to_global * NUM_PKTS,
1387 # From a global address to an EP: OUT2IN
1389 pkt_inter_epg_220_from_global = (Ether(src=str(self.router_mac),
1390 dst=self.pg0.remote_mac) /
1393 UDP(sport=1234, dport=1234) /
1396 self.send_and_assert_no_replies(
1397 self.pg7, pkt_inter_epg_220_from_global * NUM_PKTS)
1399 c5 = VppGbpContract(
1400 self, 400, epgs[3].sclass, epgs[0].sclass, acl2.acl_index,
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_unnatted(self.pg7,
1413 pkt_inter_epg_220_from_global * NUM_PKTS,
1417 pkt_inter_epg_220_from_global = (Ether(src=str(self.router_mac),
1418 dst=self.pg0.remote_mac) /
1419 IPv6(dst=eps[0].fip6,
1421 UDP(sport=1234, dport=1234) /
1424 self.send_and_expect_unnatted6(
1426 pkt_inter_epg_220_from_global * NUM_PKTS,
1431 # From a local VM to another local VM using resp. public addresses:
1434 pkt_intra_epg_220_global = (Ether(src=self.pg0.remote_mac,
1435 dst=str(self.router_mac)) /
1438 UDP(sport=1234, dport=1234) /
1441 self.send_and_expect_double_natted(eps[0].itf,
1442 pkt_intra_epg_220_global * NUM_PKTS,
1447 pkt_intra_epg_220_global = (Ether(src=self.pg0.remote_mac,
1448 dst=str(self.router_mac)) /
1449 IPv6(src=eps[0].ip6,
1451 UDP(sport=1234, dport=1234) /
1454 self.send_and_expect_double_natted6(
1456 pkt_intra_epg_220_global * NUM_PKTS,
1465 # del static mappings for each EP from the 10/8 to 11/8 network
1466 flags = self.config_flags.NAT_IS_ADDR_ONLY
1467 self.vapi.nat44_add_del_static_mapping(
1469 local_ip_address=ep.ip4,
1470 external_ip_address=ep.fip4,
1471 external_sw_if_index=0xFFFFFFFF,
1474 self.vapi.nat66_add_del_static_mapping(
1475 local_ip_address=ep.ip6,
1476 external_ip_address=ep.fip6,
1480 # IP config on the BVI interfaces
1481 if epg != epgs[0] and epg != epgs[3]:
1482 flags = self.config_flags.NAT_IS_INSIDE
1483 self.vapi.nat44_interface_add_del_feature(
1484 sw_if_index=epg.bvi.sw_if_index,
1487 self.vapi.nat66_add_del_interface(
1488 is_add=0, flags=flags,
1489 sw_if_index=epg.bvi.sw_if_index)
1491 for recirc in recircs:
1492 self.vapi.nat44_interface_add_del_feature(
1493 sw_if_index=recirc.recirc.sw_if_index,
1495 self.vapi.nat66_add_del_interface(
1497 sw_if_index=recirc.recirc.sw_if_index)
1499 def wait_for_ep_timeout(self, sw_if_index=None, ip=None, mac=None,
1500 tep=None, n_tries=100, s_time=1):
1502 if not find_gbp_endpoint(self, sw_if_index, ip, mac, tep=tep):
1504 n_tries = n_tries - 1
1506 self.assertFalse(find_gbp_endpoint(self, sw_if_index, ip, mac))
1509 def test_gbp_learn_l2(self):
1510 """ GBP L2 Endpoint Learning """
1512 drop_no_contract = self.statistics.get_err_counter(
1513 '/err/gbp-policy-port/drop-no-contract')
1514 allow_intra_class = self.statistics.get_err_counter(
1515 '/err/gbp-policy-port/allow-intra-sclass')
1517 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
1518 learnt = [{'mac': '00:00:11:11:11:01',
1520 'ip6': '2001:10::2'},
1521 {'mac': '00:00:11:11:11:02',
1523 'ip6': '2001:10::3'}]
1528 gt4 = VppIpTable(self, 1)
1529 gt4.add_vpp_config()
1530 gt6 = VppIpTable(self, 1, is_ip6=True)
1531 gt6.add_vpp_config()
1533 rd1 = VppGbpRouteDomain(self, 1, 401, gt4, gt6)
1534 rd1.add_vpp_config()
1537 # Pg2 hosts the vxlan tunnel, hosts on pg2 to act as TEPs
1538 # Pg3 hosts the IP4 UU-flood VXLAN tunnel
1539 # Pg4 hosts the IP6 UU-flood VXLAN tunnel
1541 self.pg2.config_ip4()
1542 self.pg2.resolve_arp()
1543 self.pg2.generate_remote_hosts(4)
1544 self.pg2.configure_ipv4_neighbors()
1545 self.pg3.config_ip4()
1546 self.pg3.resolve_arp()
1547 self.pg4.config_ip4()
1548 self.pg4.resolve_arp()
1551 # Add a mcast destination VXLAN-GBP tunnel for B&M traffic
1553 tun_bm = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
1556 tun_bm.add_vpp_config()
1559 # a GBP bridge domain with a BVI and a UU-flood interface
1561 bd1 = VppBridgeDomain(self, 1)
1562 bd1.add_vpp_config()
1563 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0,
1565 gbd1.add_vpp_config()
1567 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1568 self.logger.info(self.vapi.cli("sh gbp bridge"))
1570 # ... and has a /32 applied
1571 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
1572 ip_addr.add_vpp_config()
1575 # The Endpoint-group in which we are learning endpoints
1577 epg_220 = VppGbpEndpointGroup(self, 220, 112, rd1, gbd1,
1581 VppGbpEndpointRetention(4))
1582 epg_220.add_vpp_config()
1583 epg_330 = VppGbpEndpointGroup(self, 330, 113, rd1, gbd1,
1587 VppGbpEndpointRetention(4))
1588 epg_330.add_vpp_config()
1591 # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
1594 vx_tun_l2_1 = VppGbpVxlanTunnel(
1595 self, 99, bd1.bd_id,
1596 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L2,
1598 vx_tun_l2_1.add_vpp_config()
1601 # A static endpoint that the learnt endpoints are trying to
1604 ep = VppGbpEndpoint(self, self.pg0,
1606 "10.0.0.127", "11.0.0.127",
1607 "2001:10::1", "3001::1")
1610 self.assertTrue(find_route(self, ep.ip4, 32, table_id=1))
1612 # a packet with an sclass from an unknown EPG
1613 p = (Ether(src=self.pg2.remote_mac,
1614 dst=self.pg2.local_mac) /
1615 IP(src=self.pg2.remote_hosts[0].ip4,
1616 dst=self.pg2.local_ip4) /
1617 UDP(sport=1234, dport=48879) /
1618 VXLAN(vni=99, gpid=88, flags=0x88) /
1619 Ether(src=learnt[0]["mac"], dst=ep.mac) /
1620 IP(src=learnt[0]["ip"], dst=ep.ip4) /
1621 UDP(sport=1234, dport=1234) /
1624 self.send_and_assert_no_replies(self.pg2, p)
1626 self.logger.info(self.vapi.cli("sh error"))
1627 self.assert_error_counter_equal(
1628 '/err/gbp-policy-port/drop-no-contract',
1629 drop_no_contract + 1)
1632 # we should not have learnt a new tunnel endpoint, since
1633 # the EPG was not learnt.
1635 self.assertEqual(INDEX_INVALID,
1636 find_vxlan_gbp_tunnel(self,
1638 self.pg2.remote_hosts[0].ip4,
1641 # ep is not learnt, because the EPG is unknown
1642 self.assertEqual(len(self.vapi.gbp_endpoint_dump()), 1)
1645 # Learn new EPs from IP packets
1647 for ii, l in enumerate(learnt):
1648 # a packet with an sclass from a known EPG
1649 # arriving on an unknown TEP
1650 p = (Ether(src=self.pg2.remote_mac,
1651 dst=self.pg2.local_mac) /
1652 IP(src=self.pg2.remote_hosts[1].ip4,
1653 dst=self.pg2.local_ip4) /
1654 UDP(sport=1234, dport=48879) /
1655 VXLAN(vni=99, gpid=112, flags=0x88) /
1656 Ether(src=l['mac'], dst=ep.mac) /
1657 IP(src=l['ip'], dst=ep.ip4) /
1658 UDP(sport=1234, dport=1234) /
1661 rx = self.send_and_expect(self.pg2, [p], self.pg0)
1664 tep1_sw_if_index = find_vxlan_gbp_tunnel(
1667 self.pg2.remote_hosts[1].ip4,
1669 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
1672 # the EP is learnt via the learnt TEP
1673 # both from its MAC and its IP
1675 self.assertTrue(find_gbp_endpoint(self,
1676 vx_tun_l2_1.sw_if_index,
1678 self.assertTrue(find_gbp_endpoint(self,
1679 vx_tun_l2_1.sw_if_index,
1682 self.assert_error_counter_equal(
1683 '/err/gbp-policy-port/allow-intra-sclass',
1684 allow_intra_class + 2)
1686 self.logger.info(self.vapi.cli("show gbp endpoint"))
1687 self.logger.info(self.vapi.cli("show gbp vxlan"))
1688 self.logger.info(self.vapi.cli("show ip mfib"))
1691 # If we sleep for the threshold time, the learnt endpoints should
1695 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1699 # Learn new EPs from GARP packets received on the BD's mcast tunnel
1701 for ii, l in enumerate(learnt):
1702 # add some junk in the reserved field of the vxlan-header
1703 # next to the VNI. we should accept since reserved bits are
1705 p = (Ether(src=self.pg2.remote_mac,
1706 dst=self.pg2.local_mac) /
1707 IP(src=self.pg2.remote_hosts[1].ip4,
1709 UDP(sport=1234, dport=48879) /
1710 VXLAN(vni=88, reserved2=0x80, gpid=112, flags=0x88) /
1711 Ether(src=l['mac'], dst="ff:ff:ff:ff:ff:ff") /
1713 psrc=l['ip'], pdst=l['ip'],
1714 hwsrc=l['mac'], hwdst="ff:ff:ff:ff:ff:ff"))
1716 rx = self.send_and_expect(self.pg4, [p], self.pg0)
1719 tep1_sw_if_index = find_vxlan_gbp_tunnel(
1722 self.pg2.remote_hosts[1].ip4,
1724 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
1727 # the EP is learnt via the learnt TEP
1728 # both from its MAC and its IP
1730 self.assertTrue(find_gbp_endpoint(self,
1731 vx_tun_l2_1.sw_if_index,
1733 self.assertTrue(find_gbp_endpoint(self,
1734 vx_tun_l2_1.sw_if_index,
1738 # wait for the learnt endpoints to age out
1741 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1745 # Learn new EPs from L2 packets
1747 for ii, l in enumerate(learnt):
1748 # a packet with an sclass from a known EPG
1749 # arriving on an unknown TEP
1750 p = (Ether(src=self.pg2.remote_mac,
1751 dst=self.pg2.local_mac) /
1752 IP(src=self.pg2.remote_hosts[1].ip4,
1753 dst=self.pg2.local_ip4) /
1754 UDP(sport=1234, dport=48879) /
1755 VXLAN(vni=99, gpid=112, flags=0x88) /
1756 Ether(src=l['mac'], dst=ep.mac) /
1759 rx = self.send_and_expect(self.pg2, [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,
1777 self.logger.info(self.vapi.cli("show gbp endpoint"))
1778 self.logger.info(self.vapi.cli("show gbp vxlan"))
1779 self.logger.info(self.vapi.cli("show vxlan-gbp tunnel"))
1782 # wait for the learnt endpoints to age out
1785 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1789 # repeat. the do not learn bit is set so the EPs are not learnt
1792 # a packet with an sclass from a known EPG
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, gpflags="D") /
1799 Ether(src=l['mac'], dst=ep.mac) /
1800 IP(src=l['ip'], dst=ep.ip4) /
1801 UDP(sport=1234, dport=1234) /
1804 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
1807 self.assertFalse(find_gbp_endpoint(self,
1808 vx_tun_l2_1.sw_if_index,
1815 # a packet with an sclass from a known EPG
1816 # set a reserved bit in addition to the G and I
1817 # reserved bits should not be checked on rx.
1818 p = (Ether(src=self.pg2.remote_mac,
1819 dst=self.pg2.local_mac) /
1820 IP(src=self.pg2.remote_hosts[1].ip4,
1821 dst=self.pg2.local_ip4) /
1822 UDP(sport=1234, dport=48879) /
1823 VXLAN(vni=99, gpid=112, flags=0xc8) /
1824 Ether(src=l['mac'], dst=ep.mac) /
1825 IP(src=l['ip'], dst=ep.ip4) /
1826 UDP(sport=1234, dport=1234) /
1829 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
1831 self.assertTrue(find_gbp_endpoint(self,
1832 vx_tun_l2_1.sw_if_index,
1836 # Static EP replies to dynamics
1838 self.logger.info(self.vapi.cli("sh l2fib bd_id 1"))
1840 p = (Ether(src=ep.mac, dst=l['mac']) /
1841 IP(dst=l['ip'], src=ep.ip4) /
1842 UDP(sport=1234, dport=1234) /
1845 rxs = self.send_and_expect(self.pg0, p * 17, self.pg2)
1848 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
1849 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
1850 self.assertEqual(rx[UDP].dport, 48879)
1851 # the UDP source port is a random value for hashing
1852 self.assertEqual(rx[VXLAN].gpid, 112)
1853 self.assertEqual(rx[VXLAN].vni, 99)
1854 self.assertTrue(rx[VXLAN].flags.G)
1855 self.assertTrue(rx[VXLAN].flags.Instance)
1856 self.assertTrue(rx[VXLAN].gpflags.A)
1857 self.assertFalse(rx[VXLAN].gpflags.D)
1860 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1864 # repeat in the other EPG
1865 # there's no contract between 220 and 330, but the A-bit is set
1866 # so the packet is cleared for delivery
1869 # a packet with an sclass from a known EPG
1870 p = (Ether(src=self.pg2.remote_mac,
1871 dst=self.pg2.local_mac) /
1872 IP(src=self.pg2.remote_hosts[1].ip4,
1873 dst=self.pg2.local_ip4) /
1874 UDP(sport=1234, dport=48879) /
1875 VXLAN(vni=99, gpid=113, flags=0x88, gpflags='A') /
1876 Ether(src=l['mac'], dst=ep.mac) /
1877 IP(src=l['ip'], dst=ep.ip4) /
1878 UDP(sport=1234, dport=1234) /
1881 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
1883 self.assertTrue(find_gbp_endpoint(self,
1884 vx_tun_l2_1.sw_if_index,
1888 # static EP cannot reach the learnt EPs since there is no contract
1889 # only test 1 EP as the others could timeout
1891 p = (Ether(src=ep.mac, dst=l['mac']) /
1892 IP(dst=learnt[0]['ip'], src=ep.ip4) /
1893 UDP(sport=1234, dport=1234) /
1896 self.send_and_assert_no_replies(self.pg0, [p])
1899 # refresh the entries after the check for no replies above
1902 # a packet with an sclass from a known EPG
1903 p = (Ether(src=self.pg2.remote_mac,
1904 dst=self.pg2.local_mac) /
1905 IP(src=self.pg2.remote_hosts[1].ip4,
1906 dst=self.pg2.local_ip4) /
1907 UDP(sport=1234, dport=48879) /
1908 VXLAN(vni=99, gpid=113, flags=0x88, gpflags='A') /
1909 Ether(src=l['mac'], dst=ep.mac) /
1910 IP(src=l['ip'], dst=ep.ip4) /
1911 UDP(sport=1234, dport=1234) /
1914 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
1916 self.assertTrue(find_gbp_endpoint(self,
1917 vx_tun_l2_1.sw_if_index,
1921 # Add the contract so they can talk
1923 rule = AclRule(is_permit=1, proto=17)
1924 rule2 = AclRule(src_prefix=IPv6Network((0, 0)),
1925 dst_prefix=IPv6Network((0, 0)), is_permit=1, proto=17)
1926 acl = VppAcl(self, rules=[rule, rule2])
1927 acl.add_vpp_config()
1929 c1 = VppGbpContract(
1930 self, 401, epg_220.sclass, epg_330.sclass, acl.acl_index,
1931 [VppGbpContractRule(
1932 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1933 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1936 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1937 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1939 [ETH_P_IP, ETH_P_IPV6])
1943 p = (Ether(src=ep.mac, dst=l['mac']) /
1944 IP(dst=l['ip'], src=ep.ip4) /
1945 UDP(sport=1234, dport=1234) /
1948 self.send_and_expect(self.pg0, [p], self.pg2)
1951 # send UU packets from the local EP
1953 self.logger.info(self.vapi.cli("sh gbp bridge"))
1954 self.logger.info(self.vapi.cli("sh bridge-domain 1 detail"))
1955 p_uu = (Ether(src=ep.mac, dst="00:11:11:11:11:11") /
1956 IP(dst="10.0.0.133", src=ep.ip4) /
1957 UDP(sport=1234, dport=1234) /
1959 rxs = self.send_and_expect(ep.itf, [p_uu], gbd1.uu_fwd)
1961 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1963 p_bm = (Ether(src=ep.mac, dst="ff:ff:ff:ff:ff:ff") /
1964 IP(dst="10.0.0.133", src=ep.ip4) /
1965 UDP(sport=1234, dport=1234) /
1967 rxs = self.send_and_expect_only(ep.itf, [p_bm], tun_bm.mcast_itf)
1970 self.assertEqual(rx[IP].src, self.pg4.local_ip4)
1971 self.assertEqual(rx[IP].dst, "239.1.1.1")
1972 self.assertEqual(rx[UDP].dport, 48879)
1973 # the UDP source port is a random value for hashing
1974 self.assertEqual(rx[VXLAN].gpid, 112)
1975 self.assertEqual(rx[VXLAN].vni, 88)
1976 self.assertTrue(rx[VXLAN].flags.G)
1977 self.assertTrue(rx[VXLAN].flags.Instance)
1978 self.assertFalse(rx[VXLAN].gpflags.A)
1979 self.assertFalse(rx[VXLAN].gpflags.D)
1981 rule = AclRule(is_permit=1, proto=17)
1982 rule2 = AclRule(src_prefix=IPv6Network((0, 0)),
1983 dst_prefix=IPv6Network((0, 0)), is_permit=1, proto=17)
1984 acl = VppAcl(self, rules=[rule, rule2])
1985 acl.add_vpp_config()
1987 c2 = VppGbpContract(
1988 self, 401, epg_330.sclass, epg_220.sclass, acl.acl_index,
1989 [VppGbpContractRule(
1990 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1991 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1994 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1995 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1997 [ETH_P_IP, ETH_P_IPV6])
2001 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
2004 # Check v6 Endpoints learning
2007 # a packet with an sclass from a known EPG
2008 p = (Ether(src=self.pg2.remote_mac,
2009 dst=self.pg2.local_mac) /
2010 IP(src=self.pg2.remote_hosts[1].ip4,
2011 dst=self.pg2.local_ip4) /
2012 UDP(sport=1234, dport=48879) /
2013 VXLAN(vni=99, gpid=113, flags=0x88) /
2014 Ether(src=l['mac'], dst=ep.mac) /
2015 IPv6(src=l['ip6'], dst=ep.ip6) /
2016 UDP(sport=1234, dport=1234) /
2019 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
2020 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
2022 self.assertTrue(find_gbp_endpoint(
2024 vx_tun_l2_1.sw_if_index,
2026 tep=[self.pg2.local_ip4,
2027 self.pg2.remote_hosts[1].ip4]))
2029 self.logger.info(self.vapi.cli("sh int"))
2030 self.logger.info(self.vapi.cli("sh vxlan-gbp tunnel"))
2031 self.logger.info(self.vapi.cli("sh gbp vxlan"))
2032 self.logger.info(self.vapi.cli("sh gbp endpoint"))
2033 self.logger.info(self.vapi.cli("sh gbp interface"))
2036 # EP moves to a different TEP
2039 # a packet with an sclass from a known EPG
2040 p = (Ether(src=self.pg2.remote_mac,
2041 dst=self.pg2.local_mac) /
2042 IP(src=self.pg2.remote_hosts[2].ip4,
2043 dst=self.pg2.local_ip4) /
2044 UDP(sport=1234, dport=48879) /
2045 VXLAN(vni=99, gpid=113, flags=0x88) /
2046 Ether(src=l['mac'], dst=ep.mac) /
2047 IPv6(src=l['ip6'], dst=ep.ip6) /
2048 UDP(sport=1234, dport=1234) /
2051 rx = self.send_and_expect(self.pg2, p * 1, self.pg0)
2052 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
2054 self.assertTrue(find_gbp_endpoint(
2056 vx_tun_l2_1.sw_if_index,
2059 tep=[self.pg2.local_ip4,
2060 self.pg2.remote_hosts[2].ip4]))
2063 # v6 remote EP reachability
2066 p = (Ether(src=ep.mac, dst=l['mac']) /
2067 IPv6(dst=l['ip6'], src=ep.ip6) /
2068 UDP(sport=1234, dport=1234) /
2071 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
2074 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2075 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[2].ip4)
2076 self.assertEqual(rx[UDP].dport, 48879)
2077 # the UDP source port is a random value for hashing
2078 self.assertEqual(rx[VXLAN].gpid, 112)
2079 self.assertEqual(rx[VXLAN].vni, 99)
2080 self.assertTrue(rx[VXLAN].flags.G)
2081 self.assertTrue(rx[VXLAN].flags.Instance)
2082 self.assertTrue(rx[VXLAN].gpflags.A)
2083 self.assertFalse(rx[VXLAN].gpflags.D)
2084 self.assertEqual(rx[IPv6].dst, l['ip6'])
2090 # a packet with an sclass from a known EPG
2091 p = (Ether(src=self.pg2.remote_mac,
2092 dst=self.pg2.local_mac) /
2093 IP(src=self.pg2.remote_hosts[2].ip4,
2094 dst=self.pg2.local_ip4) /
2095 UDP(sport=1234, dport=48879) /
2096 VXLAN(vni=99, gpid=112, flags=0x88) /
2097 Ether(src=l['mac'], dst=ep.mac) /
2098 IPv6(src=l['ip6'], dst=ep.ip6) /
2099 UDP(sport=1234, dport=1234) /
2102 rx = self.send_and_expect(self.pg2, p * 1, self.pg0)
2103 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
2105 self.assertTrue(find_gbp_endpoint(
2107 vx_tun_l2_1.sw_if_index,
2110 tep=[self.pg2.local_ip4,
2111 self.pg2.remote_hosts[2].ip4]))
2114 # check reachability and contract intra-epg
2116 allow_intra_class = self.statistics.get_err_counter(
2117 '/err/gbp-policy-mac/allow-intra-sclass')
2120 p = (Ether(src=ep.mac, dst=l['mac']) /
2121 IPv6(dst=l['ip6'], src=ep.ip6) /
2122 UDP(sport=1234, dport=1234) /
2125 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
2128 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2129 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[2].ip4)
2130 self.assertEqual(rx[UDP].dport, 48879)
2131 self.assertEqual(rx[VXLAN].gpid, 112)
2132 self.assertEqual(rx[VXLAN].vni, 99)
2133 self.assertTrue(rx[VXLAN].flags.G)
2134 self.assertTrue(rx[VXLAN].flags.Instance)
2135 self.assertTrue(rx[VXLAN].gpflags.A)
2136 self.assertFalse(rx[VXLAN].gpflags.D)
2137 self.assertEqual(rx[IPv6].dst, l['ip6'])
2139 allow_intra_class += NUM_PKTS
2141 self.assert_error_counter_equal(
2142 '/err/gbp-policy-mac/allow-intra-sclass',
2149 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
2151 self.pg2.unconfig_ip4()
2152 self.pg3.unconfig_ip4()
2153 self.pg4.unconfig_ip4()
2155 def test_gbp_contract(self):
2156 """ GBP Contracts """
2161 gt4 = VppIpTable(self, 0)
2162 gt4.add_vpp_config()
2163 gt6 = VppIpTable(self, 0, is_ip6=True)
2164 gt6.add_vpp_config()
2166 rd0 = VppGbpRouteDomain(self, 0, 400, gt4, gt6, None, None)
2168 rd0.add_vpp_config()
2173 bd1 = VppBridgeDomain(self, 1, arp_term=0)
2174 bd2 = VppBridgeDomain(self, 2, arp_term=0)
2176 bd1.add_vpp_config()
2177 bd2.add_vpp_config()
2179 gbd1 = VppGbpBridgeDomain(self, bd1, rd0, self.loop0)
2180 gbd2 = VppGbpBridgeDomain(self, bd2, rd0, self.loop1)
2182 gbd1.add_vpp_config()
2183 gbd2.add_vpp_config()
2186 # 3 EPGs, 2 of which share a BD.
2188 epgs = [VppGbpEndpointGroup(self, 220, 1220, rd0, gbd1,
2190 "10.0.0.128", "2001:10::128"),
2191 VppGbpEndpointGroup(self, 221, 1221, rd0, gbd1,
2193 "10.0.1.128", "2001:10:1::128"),
2194 VppGbpEndpointGroup(self, 222, 1222, rd0, gbd2,
2196 "10.0.2.128", "2001:10:2::128")]
2198 # 4 end-points, 2 in the same subnet, 3 in the same BD
2200 eps = [VppGbpEndpoint(self, self.pg0,
2202 "10.0.0.1", "11.0.0.1",
2203 "2001:10::1", "3001::1"),
2204 VppGbpEndpoint(self, self.pg1,
2206 "10.0.0.2", "11.0.0.2",
2207 "2001:10::2", "3001::2"),
2208 VppGbpEndpoint(self, self.pg2,
2210 "10.0.1.1", "11.0.0.3",
2211 "2001:10:1::1", "3001::3"),
2212 VppGbpEndpoint(self, self.pg3,
2214 "10.0.2.1", "11.0.0.4",
2215 "2001:10:2::1", "3001::4")]
2218 # Config related to each of the EPGs
2221 # IP config on the BVI interfaces
2223 VppIpInterfaceBind(self, epg.bvi, epg.rd.t4).add_vpp_config()
2224 VppIpInterfaceBind(self, epg.bvi, epg.rd.t6).add_vpp_config()
2225 epg.bvi.set_mac(self.router_mac)
2227 if_ip4 = VppIpInterfaceAddress(self, epg.bvi, epg.bvi_ip4, 32)
2228 if_ip6 = VppIpInterfaceAddress(self, epg.bvi, epg.bvi_ip6, 128)
2229 if_ip4.add_vpp_config()
2230 if_ip6.add_vpp_config()
2232 # add the BD ARP termination entry for BVI IP
2233 epg.bd_arp_ip4 = VppBridgeDomainArpEntry(self, epg.bd.bd,
2234 str(self.router_mac),
2236 epg.bd_arp_ip4.add_vpp_config()
2239 epg.add_vpp_config()
2247 self.logger.info(self.vapi.cli("show gbp endpoint"))
2248 self.logger.info(self.vapi.cli("show interface"))
2249 self.logger.info(self.vapi.cli("show br"))
2252 # Intra epg allowed without contract
2254 pkt_intra_epg_220_to_220 = (Ether(src=self.pg0.remote_mac,
2255 dst=self.pg1.remote_mac) /
2258 UDP(sport=1234, dport=1234) /
2261 self.send_and_expect_bridged(self.pg0,
2262 pkt_intra_epg_220_to_220 * 65,
2265 pkt_intra_epg_220_to_220 = (Ether(src=self.pg0.remote_mac,
2266 dst=self.pg1.remote_mac) /
2267 IPv6(src=eps[0].ip6,
2269 UDP(sport=1234, dport=1234) /
2272 self.send_and_expect_bridged6(self.pg0,
2273 pkt_intra_epg_220_to_220 * 65,
2277 # Inter epg denied without contract
2279 pkt_inter_epg_220_to_221 = (Ether(src=self.pg0.remote_mac,
2280 dst=self.pg2.remote_mac) /
2283 UDP(sport=1234, dport=1234) /
2286 self.send_and_assert_no_replies(self.pg0, pkt_inter_epg_220_to_221)
2289 # A uni-directional contract from EPG 220 -> 221
2291 rule = AclRule(is_permit=1, proto=17)
2292 rule2 = AclRule(src_prefix=IPv6Network((0, 0)),
2293 dst_prefix=IPv6Network((0, 0)), is_permit=1, proto=17)
2294 rule3 = AclRule(is_permit=1, proto=1)
2295 acl = VppAcl(self, rules=[rule, rule2, rule3])
2296 acl.add_vpp_config()
2298 c1 = VppGbpContract(
2299 self, 400, epgs[0].sclass, epgs[1].sclass, acl.acl_index,
2300 [VppGbpContractRule(
2301 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2302 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2305 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2306 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2309 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2310 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2312 [ETH_P_IP, ETH_P_IPV6])
2315 self.send_and_expect_bridged(eps[0].itf,
2316 pkt_inter_epg_220_to_221 * 65,
2319 pkt_inter_epg_220_to_222 = (Ether(src=self.pg0.remote_mac,
2320 dst=str(self.router_mac)) /
2323 UDP(sport=1234, dport=1234) /
2325 self.send_and_assert_no_replies(eps[0].itf,
2326 pkt_inter_epg_220_to_222 * 65)
2329 # ping router IP in different BD
2331 pkt_router_ping_220_to_221 = (Ether(src=self.pg0.remote_mac,
2332 dst=str(self.router_mac)) /
2334 dst=epgs[1].bvi_ip4) /
2335 ICMP(type='echo-request'))
2337 self.send_and_expect(self.pg0, [pkt_router_ping_220_to_221], self.pg0)
2339 pkt_router_ping_220_to_221 = (Ether(src=self.pg0.remote_mac,
2340 dst=str(self.router_mac)) /
2341 IPv6(src=eps[0].ip6,
2342 dst=epgs[1].bvi_ip6) /
2343 ICMPv6EchoRequest())
2345 self.send_and_expect(self.pg0, [pkt_router_ping_220_to_221], self.pg0)
2348 # contract for the return direction
2350 c2 = VppGbpContract(
2351 self, 400, epgs[1].sclass, epgs[0].sclass, acl.acl_index,
2352 [VppGbpContractRule(
2353 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2354 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2357 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2358 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2360 [ETH_P_IP, ETH_P_IPV6])
2363 self.send_and_expect_bridged(eps[0].itf,
2364 pkt_inter_epg_220_to_221 * 65,
2366 pkt_inter_epg_221_to_220 = (Ether(src=self.pg2.remote_mac,
2367 dst=self.pg0.remote_mac) /
2370 UDP(sport=1234, dport=1234) /
2372 self.send_and_expect_bridged(eps[2].itf,
2373 pkt_inter_epg_221_to_220 * 65,
2375 pkt_inter_epg_221_to_220 = (Ether(src=self.pg2.remote_mac,
2376 dst=str(self.router_mac)) /
2379 UDP(sport=1234, dport=1234) /
2381 self.send_and_expect_routed(eps[2].itf,
2382 pkt_inter_epg_221_to_220 * 65,
2384 str(self.router_mac))
2385 pkt_inter_epg_221_to_220 = (Ether(src=self.pg2.remote_mac,
2386 dst=str(self.router_mac)) /
2387 IPv6(src=eps[2].ip6,
2389 UDP(sport=1234, dport=1234) /
2391 self.send_and_expect_routed6(eps[2].itf,
2392 pkt_inter_epg_221_to_220 * 65,
2394 str(self.router_mac))
2397 # contract between 220 and 222 uni-direction
2399 c3 = VppGbpContract(
2400 self, 400, epgs[0].sclass, epgs[2].sclass, acl.acl_index,
2401 [VppGbpContractRule(
2402 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2403 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2406 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2407 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2409 [ETH_P_IP, ETH_P_IPV6])
2412 self.send_and_expect(eps[0].itf,
2413 pkt_inter_epg_220_to_222 * 65,
2416 c3.remove_vpp_config()
2417 c1.remove_vpp_config()
2418 c2.remove_vpp_config()
2419 acl.remove_vpp_config()
2421 def test_gbp_bd_drop_flags(self):
2422 """ GBP BD drop flags """
2427 gt4 = VppIpTable(self, 1)
2428 gt4.add_vpp_config()
2429 gt6 = VppIpTable(self, 1, is_ip6=True)
2430 gt6.add_vpp_config()
2432 rd1 = VppGbpRouteDomain(self, 1, 401, gt4, gt6)
2433 rd1.add_vpp_config()
2436 # a GBP bridge domain with a BVI only
2438 bd1 = VppBridgeDomain(self, 1)
2439 bd1.add_vpp_config()
2441 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0,
2443 uu_drop=True, bm_drop=True)
2444 gbd1.add_vpp_config()
2446 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2447 self.logger.info(self.vapi.cli("sh gbp bridge"))
2449 # ... and has a /32 applied
2450 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2451 ip_addr.add_vpp_config()
2454 # The Endpoint-group
2456 epg_220 = VppGbpEndpointGroup(self, 220, 112, rd1, gbd1,
2460 VppGbpEndpointRetention(3))
2461 epg_220.add_vpp_config()
2463 ep = VppGbpEndpoint(self, self.pg0,
2465 "10.0.0.127", "11.0.0.127",
2466 "2001:10::1", "3001::1")
2470 # send UU/BM packet from the local EP with UU drop and BM drop enabled
2473 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2474 self.logger.info(self.vapi.cli("sh gbp bridge"))
2475 p_uu = (Ether(src=ep.mac, dst="00:11:11:11:11:11") /
2476 IP(dst="10.0.0.133", src=ep.ip4) /
2477 UDP(sport=1234, dport=1234) /
2479 self.send_and_assert_no_replies(ep.itf, [p_uu])
2481 p_bm = (Ether(src=ep.mac, dst="ff:ff:ff:ff:ff:ff") /
2482 IP(dst="10.0.0.133", src=ep.ip4) /
2483 UDP(sport=1234, dport=1234) /
2485 self.send_and_assert_no_replies(ep.itf, [p_bm])
2487 self.pg3.unconfig_ip4()
2489 self.logger.info(self.vapi.cli("sh int"))
2491 def test_gbp_bd_arp_flags(self):
2492 """ GBP BD arp flags """
2497 gt4 = VppIpTable(self, 1)
2498 gt4.add_vpp_config()
2499 gt6 = VppIpTable(self, 1, is_ip6=True)
2500 gt6.add_vpp_config()
2502 rd1 = VppGbpRouteDomain(self, 1, 401, gt4, gt6)
2503 rd1.add_vpp_config()
2506 # Pg4 hosts the IP6 UU-flood VXLAN tunnel
2508 self.pg4.config_ip4()
2509 self.pg4.resolve_arp()
2512 # Add a mcast destination VXLAN-GBP tunnel for B&M traffic
2514 tun_uu = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
2517 tun_uu.add_vpp_config()
2520 # a GBP bridge domain with a BVI and a UU-flood interface
2522 bd1 = VppBridgeDomain(self, 1)
2523 bd1.add_vpp_config()
2525 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0,
2528 gbd1.add_vpp_config()
2530 # ... and has a /32 applied
2531 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2532 ip_addr.add_vpp_config()
2535 # The Endpoint-group
2537 epg_220 = VppGbpEndpointGroup(self, 220, 112, rd1, gbd1,
2541 VppGbpEndpointRetention(2))
2542 epg_220.add_vpp_config()
2544 ep = VppGbpEndpoint(self, self.pg0,
2546 "10.0.0.127", "11.0.0.127",
2547 "2001:10::1", "3001::1")
2551 # send ARP packet from the local EP expect it on the uu interface
2553 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2554 self.logger.info(self.vapi.cli("sh gbp bridge"))
2555 p_arp = (Ether(src=ep.mac, dst="ff:ff:ff:ff:ff:ff") /
2557 psrc=ep.ip4, pdst="10.0.0.99",
2559 hwdst="ff:ff:ff:ff:ff:ff"))
2560 self.send_and_expect(ep.itf, [p_arp], self.pg4)
2562 self.pg4.unconfig_ip4()
2564 def test_gbp_learn_vlan_l2(self):
2565 """ GBP L2 Endpoint w/ VLANs"""
2567 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
2568 learnt = [{'mac': '00:00:11:11:11:01',
2570 'ip6': '2001:10::2'},
2571 {'mac': '00:00:11:11:11:02',
2573 'ip6': '2001:10::3'}]
2578 gt4 = VppIpTable(self, 1)
2579 gt4.add_vpp_config()
2580 gt6 = VppIpTable(self, 1, is_ip6=True)
2581 gt6.add_vpp_config()
2583 rd1 = VppGbpRouteDomain(self, 1, 401, gt4, gt6)
2584 rd1.add_vpp_config()
2587 # Pg2 hosts the vxlan tunnel, hosts on pg2 to act as TEPs
2589 self.pg2.config_ip4()
2590 self.pg2.resolve_arp()
2591 self.pg2.generate_remote_hosts(4)
2592 self.pg2.configure_ipv4_neighbors()
2593 self.pg3.config_ip4()
2594 self.pg3.resolve_arp()
2597 # The EP will be on a vlan sub-interface
2599 vlan_11 = VppDot1QSubint(self, self.pg0, 11)
2601 self.vapi.l2_interface_vlan_tag_rewrite(
2602 sw_if_index=vlan_11.sw_if_index, vtr_op=L2_VTR_OP.L2_POP_1,
2605 bd_uu_fwd = VppVxlanGbpTunnel(self, self.pg3.local_ip4,
2606 self.pg3.remote_ip4, 116)
2607 bd_uu_fwd.add_vpp_config()
2610 # a GBP bridge domain with a BVI and a UU-flood interface
2611 # The BD is marked as do not learn, so no endpoints are ever
2612 # learnt in this BD.
2614 bd1 = VppBridgeDomain(self, 1)
2615 bd1.add_vpp_config()
2616 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0, bd_uu_fwd,
2618 gbd1.add_vpp_config()
2620 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2621 self.logger.info(self.vapi.cli("sh gbp bridge"))
2623 # ... and has a /32 applied
2624 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2625 ip_addr.add_vpp_config()
2628 # The Endpoint-group in which we are learning endpoints
2630 epg_220 = VppGbpEndpointGroup(self, 220, 441, rd1, gbd1,
2634 VppGbpEndpointRetention(4))
2635 epg_220.add_vpp_config()
2638 # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
2641 vx_tun_l2_1 = VppGbpVxlanTunnel(
2642 self, 99, bd1.bd_id,
2643 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L2,
2645 vx_tun_l2_1.add_vpp_config()
2648 # A static endpoint that the learnt endpoints are trying to
2651 ep = VppGbpEndpoint(self, vlan_11,
2653 "10.0.0.127", "11.0.0.127",
2654 "2001:10::1", "3001::1")
2657 self.assertTrue(find_route(self, ep.ip4, 32, table_id=1))
2660 # Send to the static EP
2662 for ii, l in enumerate(learnt):
2663 # a packet with an sclass from a known EPG
2664 # arriving on an unknown TEP
2665 p = (Ether(src=self.pg2.remote_mac,
2666 dst=self.pg2.local_mac) /
2667 IP(src=self.pg2.remote_hosts[1].ip4,
2668 dst=self.pg2.local_ip4) /
2669 UDP(sport=1234, dport=48879) /
2670 VXLAN(vni=99, gpid=441, flags=0x88) /
2671 Ether(src=l['mac'], dst=ep.mac) /
2672 IP(src=l['ip'], dst=ep.ip4) /
2673 UDP(sport=1234, dport=1234) /
2676 rxs = self.send_and_expect(self.pg2, [p], self.pg0)
2679 # packet to EP has the EP's vlan tag
2682 self.assertEqual(rx[Dot1Q].vlan, 11)
2685 # the EP is not learnt since the BD setting prevents it
2688 self.assertFalse(find_gbp_endpoint(self,
2689 vx_tun_l2_1.sw_if_index,
2691 self.assertEqual(INDEX_INVALID,
2692 find_vxlan_gbp_tunnel(
2695 self.pg2.remote_hosts[1].ip4,
2698 self.assertEqual(len(self.vapi.gbp_endpoint_dump()), 1)
2702 # we didn't learn the remotes so they are sent to the UU-fwd
2705 p = (Ether(src=ep.mac, dst=l['mac']) /
2707 IP(dst=l['ip'], src=ep.ip4) /
2708 UDP(sport=1234, dport=1234) /
2711 rxs = self.send_and_expect(self.pg0, p * 17, self.pg3)
2714 self.assertEqual(rx[IP].src, self.pg3.local_ip4)
2715 self.assertEqual(rx[IP].dst, self.pg3.remote_ip4)
2716 self.assertEqual(rx[UDP].dport, 48879)
2717 # the UDP source port is a random value for hashing
2718 self.assertEqual(rx[VXLAN].gpid, 441)
2719 self.assertEqual(rx[VXLAN].vni, 116)
2720 self.assertTrue(rx[VXLAN].flags.G)
2721 self.assertTrue(rx[VXLAN].flags.Instance)
2722 self.assertFalse(rx[VXLAN].gpflags.A)
2723 self.assertFalse(rx[VXLAN].gpflags.D)
2725 self.pg2.unconfig_ip4()
2726 self.pg3.unconfig_ip4()
2728 def test_gbp_learn_l3(self):
2729 """ GBP L3 Endpoint Learning """
2731 self.vapi.cli("set logging class gbp level debug")
2733 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
2734 routed_dst_mac = "00:0c:0c:0c:0c:0c"
2735 routed_src_mac = "00:22:bd:f8:19:ff"
2737 learnt = [{'mac': '00:00:11:11:11:02',
2739 'ip6': '2001:10::2'},
2740 {'mac': '00:00:11:11:11:03',
2742 'ip6': '2001:10::3'}]
2747 t4 = VppIpTable(self, 1)
2749 t6 = VppIpTable(self, 1, True)
2752 tun_ip4_uu = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
2753 self.pg4.remote_ip4, 114)
2754 tun_ip6_uu = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
2755 self.pg4.remote_ip4, 116)
2756 tun_ip4_uu.add_vpp_config()
2757 tun_ip6_uu.add_vpp_config()
2759 rd1 = VppGbpRouteDomain(self, 2, 401, t4, t6, tun_ip4_uu, tun_ip6_uu)
2760 rd1.add_vpp_config()
2762 self.loop0.set_mac(self.router_mac)
2765 # Bind the BVI to the RD
2767 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
2768 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
2771 # Pg2 hosts the vxlan tunnel
2772 # hosts on pg2 to act as TEPs
2776 self.pg2.config_ip4()
2777 self.pg2.resolve_arp()
2778 self.pg2.generate_remote_hosts(4)
2779 self.pg2.configure_ipv4_neighbors()
2780 self.pg3.config_ip4()
2781 self.pg3.resolve_arp()
2782 self.pg4.config_ip4()
2783 self.pg4.resolve_arp()
2786 # a GBP bridge domain with a BVI and a UU-flood interface
2788 bd1 = VppBridgeDomain(self, 1)
2789 bd1.add_vpp_config()
2790 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0, self.pg3)
2791 gbd1.add_vpp_config()
2793 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2794 self.logger.info(self.vapi.cli("sh gbp bridge"))
2795 self.logger.info(self.vapi.cli("sh gbp route"))
2797 # ... and has a /32 and /128 applied
2798 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2799 ip4_addr.add_vpp_config()
2800 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 128)
2801 ip6_addr.add_vpp_config()
2804 # The Endpoint-group in which we are learning endpoints
2806 epg_220 = VppGbpEndpointGroup(self, 220, 441, rd1, gbd1,
2810 VppGbpEndpointRetention(4))
2811 epg_220.add_vpp_config()
2814 # The VXLAN GBP tunnel is in L3 mode with learning enabled
2816 vx_tun_l3 = VppGbpVxlanTunnel(
2817 self, 101, rd1.rd_id,
2818 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
2820 vx_tun_l3.add_vpp_config()
2823 # A static endpoint that the learnt endpoints are trying to
2826 ep = VppGbpEndpoint(self, self.pg0,
2828 "10.0.0.127", "11.0.0.127",
2829 "2001:10::1", "3001::1")
2833 # learn some remote IPv4 EPs
2835 for ii, l in enumerate(learnt):
2836 # a packet with an sclass from a known EPG
2837 # arriving on an unknown TEP
2838 p = (Ether(src=self.pg2.remote_mac,
2839 dst=self.pg2.local_mac) /
2840 IP(src=self.pg2.remote_hosts[1].ip4,
2841 dst=self.pg2.local_ip4) /
2842 UDP(sport=1234, dport=48879) /
2843 VXLAN(vni=101, gpid=441, flags=0x88) /
2844 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2845 IP(src=l['ip'], dst=ep.ip4) /
2846 UDP(sport=1234, dport=1234) /
2849 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2852 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2855 self.pg2.remote_hosts[1].ip4,
2857 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2859 # endpoint learnt via the parent GBP-vxlan interface
2860 self.assertTrue(find_gbp_endpoint(self,
2861 vx_tun_l3._sw_if_index,
2865 # Static IPv4 EP replies to learnt
2868 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2869 IP(dst=l['ip'], src=ep.ip4) /
2870 UDP(sport=1234, dport=1234) /
2873 rxs = self.send_and_expect(self.pg0, p * 1, self.pg2)
2876 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2877 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2878 self.assertEqual(rx[UDP].dport, 48879)
2879 # the UDP source port is a random value for hashing
2880 self.assertEqual(rx[VXLAN].gpid, 441)
2881 self.assertEqual(rx[VXLAN].vni, 101)
2882 self.assertTrue(rx[VXLAN].flags.G)
2883 self.assertTrue(rx[VXLAN].flags.Instance)
2884 self.assertTrue(rx[VXLAN].gpflags.A)
2885 self.assertFalse(rx[VXLAN].gpflags.D)
2887 inner = rx[VXLAN].payload
2889 self.assertEqual(inner[Ether].src, routed_src_mac)
2890 self.assertEqual(inner[Ether].dst, routed_dst_mac)
2891 self.assertEqual(inner[IP].src, ep.ip4)
2892 self.assertEqual(inner[IP].dst, l['ip'])
2895 self.assertFalse(find_gbp_endpoint(self,
2900 # learn some remote IPv6 EPs
2902 for ii, l in enumerate(learnt):
2903 # a packet with an sclass from a known EPG
2904 # arriving on an unknown TEP
2905 p = (Ether(src=self.pg2.remote_mac,
2906 dst=self.pg2.local_mac) /
2907 IP(src=self.pg2.remote_hosts[1].ip4,
2908 dst=self.pg2.local_ip4) /
2909 UDP(sport=1234, dport=48879) /
2910 VXLAN(vni=101, gpid=441, flags=0x88) /
2911 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2912 IPv6(src=l['ip6'], dst=ep.ip6) /
2913 UDP(sport=1234, dport=1234) /
2916 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2919 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2922 self.pg2.remote_hosts[1].ip4,
2924 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2926 self.logger.info(self.vapi.cli("show gbp bridge"))
2927 self.logger.info(self.vapi.cli("show vxlan-gbp tunnel"))
2928 self.logger.info(self.vapi.cli("show gbp vxlan"))
2929 self.logger.info(self.vapi.cli("show int addr"))
2931 # endpoint learnt via the TEP
2932 self.assertTrue(find_gbp_endpoint(self, ip=l['ip6']))
2934 self.logger.info(self.vapi.cli("show gbp endpoint"))
2935 self.logger.info(self.vapi.cli("show ip fib index 1 %s" % l['ip']))
2938 # Static EP replies to learnt
2941 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2942 IPv6(dst=l['ip6'], src=ep.ip6) /
2943 UDP(sport=1234, dport=1234) /
2946 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
2949 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2950 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2951 self.assertEqual(rx[UDP].dport, 48879)
2952 # the UDP source port is a random value for hashing
2953 self.assertEqual(rx[VXLAN].gpid, 441)
2954 self.assertEqual(rx[VXLAN].vni, 101)
2955 self.assertTrue(rx[VXLAN].flags.G)
2956 self.assertTrue(rx[VXLAN].flags.Instance)
2957 self.assertTrue(rx[VXLAN].gpflags.A)
2958 self.assertFalse(rx[VXLAN].gpflags.D)
2960 inner = rx[VXLAN].payload
2962 self.assertEqual(inner[Ether].src, routed_src_mac)
2963 self.assertEqual(inner[Ether].dst, routed_dst_mac)
2964 self.assertEqual(inner[IPv6].src, ep.ip6)
2965 self.assertEqual(inner[IPv6].dst, l['ip6'])
2967 self.logger.info(self.vapi.cli("sh gbp endpoint"))
2969 self.wait_for_ep_timeout(ip=l['ip'])
2972 # Static sends to unknown EP with no route
2974 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2975 IP(dst="10.0.0.99", src=ep.ip4) /
2976 UDP(sport=1234, dport=1234) /
2979 self.send_and_assert_no_replies(self.pg0, [p])
2982 # Add a route to static EP's v4 and v6 subnet
2984 se_10_24 = VppGbpSubnet(
2985 self, rd1, "10.0.0.0", 24,
2986 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT)
2987 se_10_24.add_vpp_config()
2990 # static pings router
2992 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2993 IP(dst=epg_220.bvi_ip4, src=ep.ip4) /
2994 UDP(sport=1234, dport=1234) /
2997 self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg0)
2999 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
3000 IPv6(dst=epg_220.bvi_ip6, src=ep.ip6) /
3001 UDP(sport=1234, dport=1234) /
3004 self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg0)
3007 # packets to address in the subnet are sent on the uu-fwd
3009 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
3010 IP(dst="10.0.0.99", src=ep.ip4) /
3011 UDP(sport=1234, dport=1234) /
3014 rxs = self.send_and_expect(self.pg0, [p], self.pg4)
3016 self.assertEqual(rx[IP].src, self.pg4.local_ip4)
3017 self.assertEqual(rx[IP].dst, self.pg4.remote_ip4)
3018 self.assertEqual(rx[UDP].dport, 48879)
3019 # the UDP source port is a random value for hashing
3020 self.assertEqual(rx[VXLAN].gpid, 441)
3021 self.assertEqual(rx[VXLAN].vni, 114)
3022 self.assertTrue(rx[VXLAN].flags.G)
3023 self.assertTrue(rx[VXLAN].flags.Instance)
3024 # policy is not applied to packets sent to the uu-fwd interfaces
3025 self.assertFalse(rx[VXLAN].gpflags.A)
3026 self.assertFalse(rx[VXLAN].gpflags.D)
3029 # learn some remote IPv4 EPs
3031 for ii, l in enumerate(learnt):
3032 # a packet with an sclass from a known EPG
3033 # arriving on an unknown TEP
3034 p = (Ether(src=self.pg2.remote_mac,
3035 dst=self.pg2.local_mac) /
3036 IP(src=self.pg2.remote_hosts[2].ip4,
3037 dst=self.pg2.local_ip4) /
3038 UDP(sport=1234, dport=48879) /
3039 VXLAN(vni=101, gpid=441, flags=0x88) /
3040 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
3041 IP(src=l['ip'], dst=ep.ip4) /
3042 UDP(sport=1234, dport=1234) /
3045 rx = self.send_and_expect(self.pg2, [p], self.pg0)
3048 tep1_sw_if_index = find_vxlan_gbp_tunnel(
3051 self.pg2.remote_hosts[2].ip4,
3053 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
3055 # endpoint learnt via the parent GBP-vxlan interface
3056 self.assertTrue(find_gbp_endpoint(self,
3057 vx_tun_l3._sw_if_index,
3061 # Add a remote endpoint from the API
3063 rep_88 = VppGbpEndpoint(self, vx_tun_l3,
3065 "10.0.0.88", "11.0.0.88",
3066 "2001:10::88", "3001::88",
3067 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
3069 self.pg2.remote_hosts[2].ip4,
3071 rep_88.add_vpp_config()
3074 # Add a remote endpoint from the API that matches an existing one
3075 # this is a lower priority, hence the packet is sent to the DP leanrt
3078 rep_2 = VppGbpEndpoint(self, vx_tun_l3,
3080 learnt[0]['ip'], "11.0.0.101",
3081 learnt[0]['ip6'], "3001::101",
3082 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
3084 self.pg2.remote_hosts[1].ip4,
3086 rep_2.add_vpp_config()
3089 # Add a route to the learned EP's v4 subnet
3090 # packets should be send on the v4/v6 uu=fwd interface resp.
3092 se_10_1_24 = VppGbpSubnet(
3093 self, rd1, "10.0.1.0", 24,
3094 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT)
3095 se_10_1_24.add_vpp_config()
3097 self.logger.info(self.vapi.cli("show gbp endpoint"))
3099 ips = ["10.0.0.88", learnt[0]['ip']]
3101 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
3102 IP(dst=ip, src=ep.ip4) /
3103 UDP(sport=1234, dport=1234) /
3106 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
3109 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
3110 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[2].ip4)
3111 self.assertEqual(rx[UDP].dport, 48879)
3112 # the UDP source port is a random value for hashing
3113 self.assertEqual(rx[VXLAN].gpid, 441)
3114 self.assertEqual(rx[VXLAN].vni, 101)
3115 self.assertTrue(rx[VXLAN].flags.G)
3116 self.assertTrue(rx[VXLAN].flags.Instance)
3117 self.assertTrue(rx[VXLAN].gpflags.A)
3118 self.assertFalse(rx[VXLAN].gpflags.D)
3120 inner = rx[VXLAN].payload
3122 self.assertEqual(inner[Ether].src, routed_src_mac)
3123 self.assertEqual(inner[Ether].dst, routed_dst_mac)
3124 self.assertEqual(inner[IP].src, ep.ip4)
3125 self.assertEqual(inner[IP].dst, ip)
3128 # remove the API remote EPs, only API sourced is gone, the DP
3129 # learnt one remains
3131 rep_88.remove_vpp_config()
3132 rep_2.remove_vpp_config()
3134 self.assertTrue(find_gbp_endpoint(self, ip=rep_2.ip4))
3136 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
3137 IP(src=ep.ip4, dst=rep_2.ip4) /
3138 UDP(sport=1234, dport=1234) /
3140 rxs = self.send_and_expect(self.pg0, [p], self.pg2)
3142 self.assertFalse(find_gbp_endpoint(self, ip=rep_88.ip4))
3144 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
3145 IP(src=ep.ip4, dst=rep_88.ip4) /
3146 UDP(sport=1234, dport=1234) /
3148 rxs = self.send_and_expect(self.pg0, [p], self.pg4)
3151 # to appease the testcase we cannot have the registered EP still
3152 # present (because it's DP learnt) when the TC ends so wait until
3155 self.wait_for_ep_timeout(ip=rep_88.ip4)
3156 self.wait_for_ep_timeout(ip=rep_2.ip4)
3159 # Same as above, learn a remote EP via CP and DP
3160 # this time remove the DP one first. expect the CP data to remain
3162 rep_3 = VppGbpEndpoint(self, vx_tun_l3,
3164 "10.0.1.4", "11.0.0.103",
3165 "2001::10:3", "3001::103",
3166 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
3168 self.pg2.remote_hosts[1].ip4,
3170 rep_3.add_vpp_config()
3172 p = (Ether(src=self.pg2.remote_mac,
3173 dst=self.pg2.local_mac) /
3174 IP(src=self.pg2.remote_hosts[2].ip4,
3175 dst=self.pg2.local_ip4) /
3176 UDP(sport=1234, dport=48879) /
3177 VXLAN(vni=101, gpid=441, flags=0x88) /
3178 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
3179 IP(src="10.0.1.4", dst=ep.ip4) /
3180 UDP(sport=1234, dport=1234) /
3182 rxs = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
3184 self.assertTrue(find_gbp_endpoint(self,
3185 vx_tun_l3._sw_if_index,
3187 tep=[self.pg2.local_ip4,
3188 self.pg2.remote_hosts[2].ip4]))
3190 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
3191 IP(dst="10.0.1.4", src=ep.ip4) /
3192 UDP(sport=1234, dport=1234) /
3194 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
3196 # host 2 is the DP learned TEP
3198 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
3199 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[2].ip4)
3201 self.wait_for_ep_timeout(ip=rep_3.ip4,
3202 tep=[self.pg2.local_ip4,
3203 self.pg2.remote_hosts[2].ip4])
3205 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
3207 # host 1 is the CP learned TEP
3209 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
3210 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
3213 # shutdown with learnt endpoint present
3215 p = (Ether(src=self.pg2.remote_mac,
3216 dst=self.pg2.local_mac) /
3217 IP(src=self.pg2.remote_hosts[1].ip4,
3218 dst=self.pg2.local_ip4) /
3219 UDP(sport=1234, dport=48879) /
3220 VXLAN(vni=101, gpid=441, flags=0x88) /
3221 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
3222 IP(src=learnt[1]['ip'], dst=ep.ip4) /
3223 UDP(sport=1234, dport=1234) /
3226 rx = self.send_and_expect(self.pg2, [p], self.pg0)
3228 # endpoint learnt via the parent GBP-vxlan interface
3229 self.assertTrue(find_gbp_endpoint(self,
3230 vx_tun_l3._sw_if_index,
3235 # remote endpoint becomes local
3237 self.pg2.unconfig_ip4()
3238 self.pg3.unconfig_ip4()
3239 self.pg4.unconfig_ip4()
3241 def test_gbp_redirect(self):
3242 """ GBP Endpoint Redirect """
3244 self.vapi.cli("set logging class gbp level debug")
3246 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
3247 routed_dst_mac = "00:0c:0c:0c:0c:0c"
3248 routed_src_mac = "00:22:bd:f8:19:ff"
3250 learnt = [{'mac': '00:00:11:11:11:02',
3252 'ip6': '2001:10::2'},
3253 {'mac': '00:00:11:11:11:03',
3255 'ip6': '2001:10::3'}]
3260 t4 = VppIpTable(self, 1)
3262 t6 = VppIpTable(self, 1, True)
3265 rd1 = VppGbpRouteDomain(self, 2, 402, t4, t6)
3266 rd1.add_vpp_config()
3268 self.loop0.set_mac(self.router_mac)
3271 # Bind the BVI to the RD
3273 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
3274 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
3277 # Pg7 hosts a BD's UU-fwd
3279 self.pg7.config_ip4()
3280 self.pg7.resolve_arp()
3283 # a GBP bridge domains for the EPs
3285 bd1 = VppBridgeDomain(self, 1)
3286 bd1.add_vpp_config()
3287 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0)
3288 gbd1.add_vpp_config()
3290 bd2 = VppBridgeDomain(self, 2)
3291 bd2.add_vpp_config()
3292 gbd2 = VppGbpBridgeDomain(self, bd2, rd1, self.loop1)
3293 gbd2.add_vpp_config()
3295 # ... and has a /32 and /128 applied
3296 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
3297 ip4_addr.add_vpp_config()
3298 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 128)
3299 ip6_addr.add_vpp_config()
3300 ip4_addr = VppIpInterfaceAddress(self, gbd2.bvi, "10.0.1.128", 32)
3301 ip4_addr.add_vpp_config()
3302 ip6_addr = VppIpInterfaceAddress(self, gbd2.bvi, "2001:11::128", 128)
3303 ip6_addr.add_vpp_config()
3306 # The Endpoint-groups in which we are learning endpoints
3308 epg_220 = VppGbpEndpointGroup(self, 220, 440, rd1, gbd1,
3312 VppGbpEndpointRetention(60))
3313 epg_220.add_vpp_config()
3314 epg_221 = VppGbpEndpointGroup(self, 221, 441, rd1, gbd2,
3318 VppGbpEndpointRetention(60))
3319 epg_221.add_vpp_config()
3320 epg_222 = VppGbpEndpointGroup(self, 222, 442, rd1, gbd1,
3324 VppGbpEndpointRetention(60))
3325 epg_222.add_vpp_config()
3328 # a GBP bridge domains for the SEPs
3330 bd_uu1 = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
3331 self.pg7.remote_ip4, 116)
3332 bd_uu1.add_vpp_config()
3333 bd_uu2 = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
3334 self.pg7.remote_ip4, 117)
3335 bd_uu2.add_vpp_config()
3337 bd3 = VppBridgeDomain(self, 3)
3338 bd3.add_vpp_config()
3339 gbd3 = VppGbpBridgeDomain(self, bd3, rd1, self.loop2,
3340 bd_uu1, learn=False)
3341 gbd3.add_vpp_config()
3342 bd4 = VppBridgeDomain(self, 4)
3343 bd4.add_vpp_config()
3344 gbd4 = VppGbpBridgeDomain(self, bd4, rd1, self.loop3,
3345 bd_uu2, learn=False)
3346 gbd4.add_vpp_config()
3349 # EPGs in which the service endpoints exist
3351 epg_320 = VppGbpEndpointGroup(self, 320, 550, rd1, gbd3,
3355 VppGbpEndpointRetention(60))
3356 epg_320.add_vpp_config()
3357 epg_321 = VppGbpEndpointGroup(self, 321, 551, rd1, gbd4,
3361 VppGbpEndpointRetention(60))
3362 epg_321.add_vpp_config()
3365 # three local endpoints
3367 ep1 = VppGbpEndpoint(self, self.pg0,
3369 "10.0.0.1", "11.0.0.1",
3370 "2001:10::1", "3001:10::1")
3371 ep1.add_vpp_config()
3372 ep2 = VppGbpEndpoint(self, self.pg1,
3374 "10.0.1.1", "11.0.1.1",
3375 "2001:11::1", "3001:11::1")
3376 ep2.add_vpp_config()
3377 ep3 = VppGbpEndpoint(self, self.pg2,
3379 "10.0.2.2", "11.0.2.2",
3380 "2001:12::1", "3001:12::1")
3381 ep3.add_vpp_config()
3386 sep1 = VppGbpEndpoint(self, self.pg3,
3388 "12.0.0.1", "13.0.0.1",
3389 "4001:10::1", "5001:10::1")
3390 sep1.add_vpp_config()
3391 sep2 = VppGbpEndpoint(self, self.pg4,
3393 "12.0.0.2", "13.0.0.2",
3394 "4001:10::2", "5001:10::2")
3395 sep2.add_vpp_config()
3396 sep3 = VppGbpEndpoint(self, self.pg5,
3398 "12.0.1.1", "13.0.1.1",
3399 "4001:11::1", "5001:11::1")
3400 sep3.add_vpp_config()
3401 # this EP is not installed immediately
3402 sep4 = VppGbpEndpoint(self, self.pg6,
3404 "12.0.1.2", "13.0.1.2",
3405 "4001:11::2", "5001:11::2")
3408 # an L2 switch packet between local EPs in different EPGs
3409 # different dest ports on each so the are LB hashed differently
3411 p4 = [(Ether(src=ep1.mac, dst=ep3.mac) /
3412 IP(src=ep1.ip4, dst=ep3.ip4) /
3413 UDP(sport=1234, dport=1234) /
3414 Raw(b'\xa5' * 100)),
3415 (Ether(src=ep3.mac, dst=ep1.mac) /
3416 IP(src=ep3.ip4, dst=ep1.ip4) /
3417 UDP(sport=1234, dport=1234) /
3418 Raw(b'\xa5' * 100))]
3419 p6 = [(Ether(src=ep1.mac, dst=ep3.mac) /
3420 IPv6(src=ep1.ip6, dst=ep3.ip6) /
3421 UDP(sport=1234, dport=1234) /
3422 Raw(b'\xa5' * 100)),
3423 (Ether(src=ep3.mac, dst=ep1.mac) /
3424 IPv6(src=ep3.ip6, dst=ep1.ip6) /
3425 UDP(sport=1234, dport=1230) /
3426 Raw(b'\xa5' * 100))]
3428 # should be dropped since no contract yet
3429 self.send_and_assert_no_replies(self.pg0, [p4[0]])
3430 self.send_and_assert_no_replies(self.pg0, [p6[0]])
3433 # Add a contract with a rule to load-balance redirect via SEP1 and SEP2
3434 # one of the next-hops is via an EP that is not known
3436 rule4 = AclRule(is_permit=1, proto=17)
3437 rule6 = AclRule(src_prefix=IPv6Network((0, 0)),
3438 dst_prefix=IPv6Network((0, 0)), is_permit=1, proto=17)
3439 acl = VppAcl(self, rules=[rule4, rule6])
3440 acl.add_vpp_config()
3443 # test the src-ip hash mode
3445 c1 = VppGbpContract(
3446 self, 402, epg_220.sclass, epg_222.sclass, acl.acl_index,
3447 [VppGbpContractRule(
3448 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3449 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3450 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3451 sep1.ip4, sep1.epg.rd),
3452 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3453 sep2.ip4, sep2.epg.rd)]),
3455 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3456 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3457 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3458 sep3.ip6, sep3.epg.rd),
3459 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3460 sep4.ip6, sep4.epg.rd)])],
3461 [ETH_P_IP, ETH_P_IPV6])
3464 c2 = VppGbpContract(
3465 self, 402, epg_222.sclass, epg_220.sclass, acl.acl_index,
3466 [VppGbpContractRule(
3467 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3468 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3469 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3470 sep1.ip4, sep1.epg.rd),
3471 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3472 sep2.ip4, sep2.epg.rd)]),
3474 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3475 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3476 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3477 sep3.ip6, sep3.epg.rd),
3478 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3479 sep4.ip6, sep4.epg.rd)])],
3480 [ETH_P_IP, ETH_P_IPV6])
3484 # send again with the contract preset, now packets arrive
3485 # at SEP1 or SEP2 depending on the hashing
3487 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3490 self.assertEqual(rx[Ether].src, routed_src_mac)
3491 self.assertEqual(rx[Ether].dst, sep1.mac)
3492 self.assertEqual(rx[IP].src, ep1.ip4)
3493 self.assertEqual(rx[IP].dst, ep3.ip4)
3495 rxs = self.send_and_expect(self.pg2, p4[1] * 17, sep2.itf)
3498 self.assertEqual(rx[Ether].src, routed_src_mac)
3499 self.assertEqual(rx[Ether].dst, sep2.mac)
3500 self.assertEqual(rx[IP].src, ep3.ip4)
3501 self.assertEqual(rx[IP].dst, ep1.ip4)
3503 rxs = self.send_and_expect(self.pg0, p6[0] * 17, self.pg7)
3506 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3507 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3508 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3509 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
3510 self.assertEqual(rx[VXLAN].vni, 117)
3511 self.assertTrue(rx[VXLAN].flags.G)
3512 self.assertTrue(rx[VXLAN].flags.Instance)
3513 # redirect policy has been applied
3514 self.assertTrue(rx[VXLAN].gpflags.A)
3515 self.assertFalse(rx[VXLAN].gpflags.D)
3517 inner = rx[VXLAN].payload
3519 self.assertEqual(inner[Ether].src, routed_src_mac)
3520 self.assertEqual(inner[Ether].dst, sep4.mac)
3521 self.assertEqual(inner[IPv6].src, ep1.ip6)
3522 self.assertEqual(inner[IPv6].dst, ep3.ip6)
3524 rxs = self.send_and_expect(self.pg2, p6[1] * 17, sep3.itf)
3527 self.assertEqual(rx[Ether].src, routed_src_mac)
3528 self.assertEqual(rx[Ether].dst, sep3.mac)
3529 self.assertEqual(rx[IPv6].src, ep3.ip6)
3530 self.assertEqual(rx[IPv6].dst, ep1.ip6)
3533 # programme the unknown EP
3535 sep4.add_vpp_config()
3537 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep4.itf)
3540 self.assertEqual(rx[Ether].src, routed_src_mac)
3541 self.assertEqual(rx[Ether].dst, sep4.mac)
3542 self.assertEqual(rx[IPv6].src, ep1.ip6)
3543 self.assertEqual(rx[IPv6].dst, ep3.ip6)
3546 # and revert back to unprogrammed
3548 sep4.remove_vpp_config()
3550 rxs = self.send_and_expect(self.pg0, p6[0] * 17, self.pg7)
3553 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3554 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3555 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3556 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
3557 self.assertEqual(rx[VXLAN].vni, 117)
3558 self.assertTrue(rx[VXLAN].flags.G)
3559 self.assertTrue(rx[VXLAN].flags.Instance)
3560 # redirect policy has been applied
3561 self.assertTrue(rx[VXLAN].gpflags.A)
3562 self.assertFalse(rx[VXLAN].gpflags.D)
3564 inner = rx[VXLAN].payload
3566 self.assertEqual(inner[Ether].src, routed_src_mac)
3567 self.assertEqual(inner[Ether].dst, sep4.mac)
3568 self.assertEqual(inner[IPv6].src, ep1.ip6)
3569 self.assertEqual(inner[IPv6].dst, ep3.ip6)
3571 c1.remove_vpp_config()
3572 c2.remove_vpp_config()
3575 # test the symmetric hash mode
3577 c1 = VppGbpContract(
3578 self, 402, epg_220.sclass, epg_222.sclass, acl.acl_index,
3579 [VppGbpContractRule(
3580 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3581 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3582 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3583 sep1.ip4, sep1.epg.rd),
3584 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3585 sep2.ip4, sep2.epg.rd)]),
3587 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3588 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3589 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3590 sep3.ip6, sep3.epg.rd),
3591 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3592 sep4.ip6, sep4.epg.rd)])],
3593 [ETH_P_IP, ETH_P_IPV6])
3596 c2 = VppGbpContract(
3597 self, 402, epg_222.sclass, epg_220.sclass, acl.acl_index,
3598 [VppGbpContractRule(
3599 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3600 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3601 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3602 sep1.ip4, sep1.epg.rd),
3603 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3604 sep2.ip4, sep2.epg.rd)]),
3606 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3607 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3608 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3609 sep3.ip6, sep3.epg.rd),
3610 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3611 sep4.ip6, sep4.epg.rd)])],
3612 [ETH_P_IP, ETH_P_IPV6])
3616 # send again with the contract preset, now packets arrive
3617 # at SEP1 for both directions
3619 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3622 self.assertEqual(rx[Ether].src, routed_src_mac)
3623 self.assertEqual(rx[Ether].dst, sep1.mac)
3624 self.assertEqual(rx[IP].src, ep1.ip4)
3625 self.assertEqual(rx[IP].dst, ep3.ip4)
3627 rxs = self.send_and_expect(self.pg2, p4[1] * 17, sep1.itf)
3630 self.assertEqual(rx[Ether].src, routed_src_mac)
3631 self.assertEqual(rx[Ether].dst, sep1.mac)
3632 self.assertEqual(rx[IP].src, ep3.ip4)
3633 self.assertEqual(rx[IP].dst, ep1.ip4)
3636 # programme the unknown EP for the L3 tests
3638 sep4.add_vpp_config()
3641 # an L3 switch packet between local EPs in different EPGs
3642 # different dest ports on each so the are LB hashed differently
3644 p4 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3645 IP(src=ep1.ip4, dst=ep2.ip4) /
3646 UDP(sport=1234, dport=1234) /
3647 Raw(b'\xa5' * 100)),
3648 (Ether(src=ep2.mac, dst=str(self.router_mac)) /
3649 IP(src=ep2.ip4, dst=ep1.ip4) /
3650 UDP(sport=1234, dport=1234) /
3651 Raw(b'\xa5' * 100))]
3652 p6 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3653 IPv6(src=ep1.ip6, dst=ep2.ip6) /
3654 UDP(sport=1234, dport=1234) /
3655 Raw(b'\xa5' * 100)),
3656 (Ether(src=ep2.mac, dst=str(self.router_mac)) /
3657 IPv6(src=ep2.ip6, dst=ep1.ip6) /
3658 UDP(sport=1234, dport=1234) /
3659 Raw(b'\xa5' * 100))]
3661 c3 = VppGbpContract(
3662 self, 402, epg_220.sclass, epg_221.sclass, acl.acl_index,
3663 [VppGbpContractRule(
3664 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3665 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3666 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3667 sep1.ip4, sep1.epg.rd),
3668 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3669 sep2.ip4, sep2.epg.rd)]),
3671 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3672 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3673 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3674 sep3.ip6, sep3.epg.rd),
3675 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3676 sep4.ip6, sep4.epg.rd)])],
3677 [ETH_P_IP, ETH_P_IPV6])
3680 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3683 self.assertEqual(rx[Ether].src, routed_src_mac)
3684 self.assertEqual(rx[Ether].dst, sep1.mac)
3685 self.assertEqual(rx[IP].src, ep1.ip4)
3686 self.assertEqual(rx[IP].dst, ep2.ip4)
3689 # learn a remote EP in EPG 221
3690 # packets coming from unknown remote EPs will be leant & redirected
3692 vx_tun_l3 = VppGbpVxlanTunnel(
3693 self, 444, rd1.rd_id,
3694 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
3696 vx_tun_l3.add_vpp_config()
3698 c4 = VppGbpContract(
3699 self, 402, epg_221.sclass, epg_220.sclass, acl.acl_index,
3700 [VppGbpContractRule(
3701 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3702 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3703 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3704 sep1.ip4, sep1.epg.rd),
3705 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3706 sep2.ip4, sep2.epg.rd)]),
3708 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3709 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3710 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3711 sep3.ip6, sep3.epg.rd),
3712 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3713 sep4.ip6, sep4.epg.rd)])],
3714 [ETH_P_IP, ETH_P_IPV6])
3717 p = (Ether(src=self.pg7.remote_mac,
3718 dst=self.pg7.local_mac) /
3719 IP(src=self.pg7.remote_ip4,
3720 dst=self.pg7.local_ip4) /
3721 UDP(sport=1234, dport=48879) /
3722 VXLAN(vni=444, gpid=441, flags=0x88) /
3723 Ether(src="00:22:22:22:22:33", dst=str(self.router_mac)) /
3724 IP(src="10.0.0.88", dst=ep1.ip4) /
3725 UDP(sport=1234, dport=1234) /
3728 # unknown remote EP to local EP redirected
3729 rxs = self.send_and_expect(self.pg7, [p], sep1.itf)
3732 self.assertEqual(rx[Ether].src, routed_src_mac)
3733 self.assertEqual(rx[Ether].dst, sep1.mac)
3734 self.assertEqual(rx[IP].src, "10.0.0.88")
3735 self.assertEqual(rx[IP].dst, ep1.ip4)
3737 # endpoint learnt via the parent GBP-vxlan interface
3738 self.assertTrue(find_gbp_endpoint(self,
3739 vx_tun_l3._sw_if_index,
3742 p = (Ether(src=self.pg7.remote_mac,
3743 dst=self.pg7.local_mac) /
3744 IP(src=self.pg7.remote_ip4,
3745 dst=self.pg7.local_ip4) /
3746 UDP(sport=1234, dport=48879) /
3747 VXLAN(vni=444, gpid=441, flags=0x88) /
3748 Ether(src="00:22:22:22:22:33", dst=str(self.router_mac)) /
3749 IPv6(src="2001:10::88", dst=ep1.ip6) /
3750 UDP(sport=1234, dport=1234) /
3753 # unknown remote EP to local EP redirected (ipv6)
3754 rxs = self.send_and_expect(self.pg7, [p], sep3.itf)
3757 self.assertEqual(rx[Ether].src, routed_src_mac)
3758 self.assertEqual(rx[Ether].dst, sep3.mac)
3759 self.assertEqual(rx[IPv6].src, "2001:10::88")
3760 self.assertEqual(rx[IPv6].dst, ep1.ip6)
3762 # endpoint learnt via the parent GBP-vxlan interface
3763 self.assertTrue(find_gbp_endpoint(self,
3764 vx_tun_l3._sw_if_index,
3768 # L3 switch from local to remote EP
3770 p4 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3771 IP(src=ep1.ip4, dst="10.0.0.88") /
3772 UDP(sport=1234, dport=1234) /
3773 Raw(b'\xa5' * 100))]
3774 p6 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3775 IPv6(src=ep1.ip6, dst="2001:10::88") /
3776 UDP(sport=1234, dport=1234) /
3777 Raw(b'\xa5' * 100))]
3779 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3782 self.assertEqual(rx[Ether].src, routed_src_mac)
3783 self.assertEqual(rx[Ether].dst, sep1.mac)
3784 self.assertEqual(rx[IP].src, ep1.ip4)
3785 self.assertEqual(rx[IP].dst, "10.0.0.88")
3787 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep4.itf)
3790 self.assertEqual(rx[Ether].src, routed_src_mac)
3791 self.assertEqual(rx[Ether].dst, sep4.mac)
3792 self.assertEqual(rx[IPv6].src, ep1.ip6)
3793 self.assertEqual(rx[IPv6].dst, "2001:10::88")
3796 # test the dst-ip hash mode
3798 c5 = VppGbpContract(
3799 self, 402, epg_220.sclass, epg_221.sclass, acl.acl_index,
3800 [VppGbpContractRule(
3801 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3802 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
3803 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3804 sep1.ip4, sep1.epg.rd),
3805 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3806 sep2.ip4, sep2.epg.rd)]),
3808 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3809 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
3810 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3811 sep3.ip6, sep3.epg.rd),
3812 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3813 sep4.ip6, sep4.epg.rd)])],
3814 [ETH_P_IP, ETH_P_IPV6])
3817 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3820 self.assertEqual(rx[Ether].src, routed_src_mac)
3821 self.assertEqual(rx[Ether].dst, sep1.mac)
3822 self.assertEqual(rx[IP].src, ep1.ip4)
3823 self.assertEqual(rx[IP].dst, "10.0.0.88")
3825 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep3.itf)
3828 self.assertEqual(rx[Ether].src, routed_src_mac)
3829 self.assertEqual(rx[Ether].dst, sep3.mac)
3830 self.assertEqual(rx[IPv6].src, ep1.ip6)
3831 self.assertEqual(rx[IPv6].dst, "2001:10::88")
3834 # a programmed remote SEP in EPG 320
3837 # gbp vxlan tunnel for the remote SEP
3838 vx_tun_l3_sep = VppGbpVxlanTunnel(
3839 self, 555, rd1.rd_id,
3840 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
3842 vx_tun_l3_sep.add_vpp_config()
3845 sep5 = VppGbpEndpoint(self, vx_tun_l3_sep,
3847 "12.0.0.10", "13.0.0.10",
3848 "4001:10::10", "5001:10::10",
3849 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
3851 self.pg7.remote_ip4,
3853 sep5.add_vpp_config()
3856 # local l3out redirect tests
3861 self.loop4.set_mac(self.router_mac)
3862 VppIpInterfaceBind(self, self.loop4, t4).add_vpp_config()
3863 VppIpInterfaceBind(self, self.loop4, t6).add_vpp_config()
3864 ebd = VppBridgeDomain(self, 100)
3865 ebd.add_vpp_config()
3866 gebd = VppGbpBridgeDomain(self, ebd, rd1, self.loop4, None, None)
3867 gebd.add_vpp_config()
3869 eepg = VppGbpEndpointGroup(self, 888, 765, rd1, gebd,
3873 VppGbpEndpointRetention(60))
3874 eepg.add_vpp_config()
3875 # add subnets to BVI
3876 VppIpInterfaceAddress(
3880 24).add_vpp_config()
3881 VppIpInterfaceAddress(
3885 64).add_vpp_config()
3886 # ... which are L3-out subnets
3887 VppGbpSubnet(self, rd1, "10.1.0.0", 24,
3888 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3889 sclass=765).add_vpp_config()
3890 VppGbpSubnet(self, rd1, "2001:10:1::128", 64,
3891 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3892 sclass=765).add_vpp_config()
3893 # external endpoints
3894 VppL2Vtr(self, self.vlan_100, L2_VTR_OP.L2_POP_1).add_vpp_config()
3895 eep1 = VppGbpEndpoint(self, self.vlan_100, eepg, None, "10.1.0.1",
3896 "11.1.0.1", "2001:10:1::1", "3001:10:1::1",
3897 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
3898 eep1.add_vpp_config()
3899 VppL2Vtr(self, self.vlan_101, L2_VTR_OP.L2_POP_1).add_vpp_config()
3900 eep2 = VppGbpEndpoint(self, self.vlan_101, eepg, None, "10.1.0.2",
3901 "11.1.0.2", "2001:10:1::2", "3001:10:1::2",
3902 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
3903 eep2.add_vpp_config()
3905 # external subnets reachable though eep1 and eep2 respectively
3906 VppIpRoute(self, "10.220.0.0", 24,
3907 [VppRoutePath(eep1.ip4, eep1.epg.bvi.sw_if_index)],
3908 table_id=t4.table_id).add_vpp_config()
3909 VppGbpSubnet(self, rd1, "10.220.0.0", 24,
3910 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3911 sclass=4220).add_vpp_config()
3912 VppIpRoute(self, "10:220::", 64,
3913 [VppRoutePath(eep1.ip6, eep1.epg.bvi.sw_if_index)],
3914 table_id=t6.table_id).add_vpp_config()
3915 VppGbpSubnet(self, rd1, "10:220::", 64,
3916 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3917 sclass=4220).add_vpp_config()
3918 VppIpRoute(self, "10.221.0.0", 24,
3919 [VppRoutePath(eep2.ip4, eep2.epg.bvi.sw_if_index)],
3920 table_id=t4.table_id).add_vpp_config()
3921 VppGbpSubnet(self, rd1, "10.221.0.0", 24,
3922 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3923 sclass=4221).add_vpp_config()
3924 VppIpRoute(self, "10:221::", 64,
3925 [VppRoutePath(eep2.ip6, eep2.epg.bvi.sw_if_index)],
3926 table_id=t6.table_id).add_vpp_config()
3927 VppGbpSubnet(self, rd1, "10:221::", 64,
3928 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3929 sclass=4221).add_vpp_config()
3932 # l3out redirect to remote (known, then unknown) SEP
3935 # packets from 1 external subnet to the other
3936 p = [(Ether(src=eep1.mac, dst=self.router_mac) /
3938 IP(src="10.220.0.17", dst="10.221.0.65") /
3939 UDP(sport=1234, dport=1234) /
3940 Raw(b'\xa5' * 100)),
3941 (Ether(src=eep1.mac, dst=self.router_mac) /
3943 IPv6(src="10:220::17", dst="10:221::65") /
3944 UDP(sport=1234, dport=1234) /
3945 Raw(b'\xa5' * 100))]
3947 # packets should be dropped in absence of contract
3948 self.send_and_assert_no_replies(self.pg0, p)
3950 # contract redirecting to sep5
3952 self, 402, 4220, 4221, acl.acl_index,
3953 [VppGbpContractRule(
3954 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3955 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
3956 [VppGbpContractNextHop(sep5.vmac, sep5.epg.bd,
3957 sep5.ip4, sep5.epg.rd)]),
3959 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3960 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
3961 [VppGbpContractNextHop(sep5.vmac, sep5.epg.bd,
3962 sep5.ip6, sep5.epg.rd)])],
3963 [ETH_P_IP, ETH_P_IPV6]).add_vpp_config()
3965 rxs = self.send_and_expect(self.pg0, p, self.pg7)
3967 for rx, tx in zip(rxs, p):
3968 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3969 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3970 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3971 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
3972 # this should use the programmed remote leaf TEP
3973 self.assertEqual(rx[VXLAN].vni, 555)
3974 self.assertEqual(rx[VXLAN].gpid, 4220)
3975 self.assertTrue(rx[VXLAN].flags.G)
3976 self.assertTrue(rx[VXLAN].flags.Instance)
3977 # redirect policy has been applied
3978 self.assertTrue(rx[VXLAN].gpflags.A)
3979 self.assertTrue(rx[VXLAN].gpflags.D)
3980 rxip = rx[VXLAN][Ether].payload
3981 txip = tx[Dot1Q].payload
3982 self.assertEqual(rxip.src, txip.src)
3983 self.assertEqual(rxip.dst, txip.dst)
3985 # remote SEP: it is now an unknown remote SEP and should go
3987 sep5.remove_vpp_config()
3989 rxs = self.send_and_expect(self.pg0, p, self.pg7)
3991 for rx, tx in zip(rxs, p):
3992 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3993 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3994 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3995 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
3996 # this should use the spine proxy TEP
3997 self.assertEqual(rx[VXLAN].vni, epg_320.bd.uu_fwd.vni)
3998 self.assertEqual(rx[VXLAN].gpid, 4220)
3999 self.assertTrue(rx[VXLAN].flags.G)
4000 self.assertTrue(rx[VXLAN].flags.Instance)
4001 # redirect policy has been applied
4002 self.assertTrue(rx[VXLAN].gpflags.A)
4003 self.assertTrue(rx[VXLAN].gpflags.D)
4004 rxip = rx[VXLAN][Ether].payload
4005 txip = tx[Dot1Q].payload
4006 self.assertEqual(rxip.src, txip.src)
4007 self.assertEqual(rxip.dst, txip.dst)
4010 # l3out redirect to local SEP
4013 # change the contract between l3out to redirect to local SEPs
4014 # instead of remote SEP
4016 self, 402, 4220, 4221, acl.acl_index,
4017 [VppGbpContractRule(
4018 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4019 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
4020 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
4021 sep1.ip4, sep1.epg.rd)]),
4023 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4024 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
4025 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
4026 sep1.ip6, sep1.epg.rd)])],
4027 [ETH_P_IP, ETH_P_IPV6]).add_vpp_config()
4029 rxs = self.send_and_expect(self.pg0, p, sep1.itf)
4030 for rx, tx in zip(rxs, p):
4031 self.assertEqual(rx[Ether].src, routed_src_mac)
4032 self.assertEqual(rx[Ether].dst, sep1.mac)
4033 rxip = rx[Ether].payload
4034 txip = tx[Ether].payload
4035 self.assertEqual(rxip.src, txip.src)
4036 self.assertEqual(rxip.dst, txip.dst)
4039 # redirect remote EP to remote (known then unknown) SEP
4042 # remote SEP known again
4043 sep5.add_vpp_config()
4045 # contract to redirect to learnt SEP
4047 self, 402, epg_221.sclass, epg_222.sclass, acl.acl_index,
4048 [VppGbpContractRule(
4049 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4050 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
4051 [VppGbpContractNextHop(sep5.vmac, sep5.epg.bd,
4052 sep5.ip4, sep5.epg.rd)]),
4054 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4055 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
4056 [VppGbpContractNextHop(sep5.vmac, sep5.epg.bd,
4057 sep5.ip6, sep5.epg.rd)])],
4058 [ETH_P_IP, ETH_P_IPV6]).add_vpp_config()
4060 # packets from unknown EP 221 to known EP in EPG 222
4061 # should be redirected to known remote SEP
4062 base = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
4063 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
4064 UDP(sport=1234, dport=48879) /
4065 VXLAN(vni=444, gpid=441, flags=0x88) /
4066 Ether(src="00:22:22:22:22:44", dst=str(self.router_mac)))
4068 IP(src="10.0.1.100", dst=ep3.ip4) /
4069 UDP(sport=1234, dport=1234) /
4070 Raw(b'\xa5' * 100)),
4072 IPv6(src="2001:10::100", dst=ep3.ip6) /
4073 UDP(sport=1234, dport=1234) /
4074 Raw(b'\xa5' * 100))]
4076 # unknown remote EP to local EP redirected to known remote SEP
4077 rxs = self.send_and_expect(self.pg7, p, self.pg7)
4079 for rx, tx in zip(rxs, p):
4080 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4081 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4082 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4083 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4084 # this should use the programmed remote leaf TEP
4085 self.assertEqual(rx[VXLAN].vni, 555)
4086 self.assertEqual(rx[VXLAN].gpid, epg_221.sclass)
4087 self.assertTrue(rx[VXLAN].flags.G)
4088 self.assertTrue(rx[VXLAN].flags.Instance)
4089 # redirect policy has been applied
4090 self.assertTrue(rx[VXLAN].gpflags.A)
4091 self.assertFalse(rx[VXLAN].gpflags.D)
4092 rxip = rx[VXLAN][Ether].payload
4093 txip = tx[VXLAN][Ether].payload
4094 self.assertEqual(rxip.src, txip.src)
4095 self.assertEqual(rxip.dst, txip.dst)
4097 # endpoint learnt via the parent GBP-vxlan interface
4098 self.assertTrue(find_gbp_endpoint(self,
4099 vx_tun_l3._sw_if_index,
4101 self.assertTrue(find_gbp_endpoint(self,
4102 vx_tun_l3._sw_if_index,
4105 # remote SEP: it is now an unknown remote SEP and should go
4107 sep5.remove_vpp_config()
4109 # remote EP (coming from spine proxy) to local EP redirected to
4111 rxs = self.send_and_expect(self.pg7, p, self.pg7)
4113 for rx, tx in zip(rxs, p):
4114 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4115 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4116 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4117 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4118 # this should use the spine proxy TEP
4119 self.assertEqual(rx[VXLAN].vni, epg_320.bd.uu_fwd.vni)
4120 self.assertEqual(rx[VXLAN].gpid, epg_221.sclass)
4121 self.assertTrue(rx[VXLAN].flags.G)
4122 self.assertTrue(rx[VXLAN].flags.Instance)
4123 # redirect policy has been applied
4124 self.assertTrue(rx[VXLAN].gpflags.A)
4125 self.assertFalse(rx[VXLAN].gpflags.D)
4126 rxip = rx[VXLAN][Ether].payload
4127 txip = tx[VXLAN][Ether].payload
4128 self.assertEqual(rxip.src, txip.src)
4129 self.assertEqual(rxip.dst, txip.dst)
4134 self.pg7.unconfig_ip4()
4136 def test_gbp_redirect_extended(self):
4137 """ GBP Endpoint Redirect Extended """
4139 self.vapi.cli("set logging class gbp level debug")
4141 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
4142 routed_dst_mac = "00:0c:0c:0c:0c:0c"
4143 routed_src_mac = "00:22:bd:f8:19:ff"
4145 learnt = [{'mac': '00:00:11:11:11:02',
4147 'ip6': '2001:10::2'},
4148 {'mac': '00:00:11:11:11:03',
4150 'ip6': '2001:10::3'}]
4155 t4 = VppIpTable(self, 1)
4157 t6 = VppIpTable(self, 1, True)
4160 # create IPv4 and IPv6 RD UU VxLAN-GBP TEP and bind them to the right
4162 rd_uu4 = VppVxlanGbpTunnel(
4165 self.pg7.remote_ip4,
4167 mode=(VppEnum.vl_api_vxlan_gbp_api_tunnel_mode_t.
4168 VXLAN_GBP_API_TUNNEL_MODE_L3))
4169 rd_uu4.add_vpp_config()
4170 VppIpInterfaceBind(self, rd_uu4, t4).add_vpp_config()
4172 rd_uu6 = VppVxlanGbpTunnel(
4175 self.pg7.remote_ip4,
4177 mode=(VppEnum.vl_api_vxlan_gbp_api_tunnel_mode_t.
4178 VXLAN_GBP_API_TUNNEL_MODE_L3))
4179 rd_uu6.add_vpp_config()
4180 VppIpInterfaceBind(self, rd_uu6, t4).add_vpp_config()
4182 rd1 = VppGbpRouteDomain(self, 2, 402, t4, t6, rd_uu4, rd_uu6)
4183 rd1.add_vpp_config()
4185 self.loop0.set_mac(self.router_mac)
4186 self.loop1.set_mac(self.router_mac)
4187 self.loop2.set_mac(self.router_mac)
4190 # Bind the BVI to the RD
4192 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
4193 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
4194 VppIpInterfaceBind(self, self.loop1, t4).add_vpp_config()
4195 VppIpInterfaceBind(self, self.loop1, t6).add_vpp_config()
4196 VppIpInterfaceBind(self, self.loop2, t4).add_vpp_config()
4197 VppIpInterfaceBind(self, self.loop2, t6).add_vpp_config()
4200 # Pg7 hosts a BD's UU-fwd
4202 self.pg7.config_ip4()
4203 self.pg7.resolve_arp()
4206 # a GBP bridge domains for the EPs
4208 bd1 = VppBridgeDomain(self, 1)
4209 bd1.add_vpp_config()
4210 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0)
4211 gbd1.add_vpp_config()
4213 bd2 = VppBridgeDomain(self, 2)
4214 bd2.add_vpp_config()
4215 gbd2 = VppGbpBridgeDomain(self, bd2, rd1, self.loop1)
4216 gbd2.add_vpp_config()
4218 # ... and has a /32 and /128 applied
4219 ip4_addr1 = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
4220 ip4_addr1.add_vpp_config()
4221 ip6_addr1 = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 128)
4222 ip6_addr1.add_vpp_config()
4223 ip4_addr2 = VppIpInterfaceAddress(self, gbd2.bvi, "10.0.1.128", 32)
4224 ip4_addr2.add_vpp_config()
4225 ip6_addr2 = VppIpInterfaceAddress(self, gbd2.bvi, "2001:11::128", 128)
4226 ip6_addr2.add_vpp_config()
4229 # The Endpoint-groups
4231 epg_220 = VppGbpEndpointGroup(self, 220, 440, rd1, gbd1,
4235 VppGbpEndpointRetention(60))
4236 epg_220.add_vpp_config()
4237 epg_221 = VppGbpEndpointGroup(self, 221, 441, rd1, gbd2,
4241 VppGbpEndpointRetention(60))
4242 epg_221.add_vpp_config()
4245 # a GBP bridge domains for the SEPs
4247 bd_uu3 = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
4248 self.pg7.remote_ip4, 116)
4249 bd_uu3.add_vpp_config()
4251 bd3 = VppBridgeDomain(self, 3)
4252 bd3.add_vpp_config()
4253 gbd3 = VppGbpBridgeDomain(self, bd3, rd1, self.loop2,
4254 bd_uu3, learn=False)
4255 gbd3.add_vpp_config()
4257 ip4_addr3 = VppIpInterfaceAddress(self, gbd3.bvi, "12.0.0.128", 32)
4258 ip4_addr3.add_vpp_config()
4259 ip6_addr3 = VppIpInterfaceAddress(self, gbd3.bvi, "4001:10::128", 128)
4260 ip6_addr3.add_vpp_config()
4263 # self.logger.info(self.vapi.cli("show gbp bridge"))
4264 # self.logger.info(self.vapi.cli("show vxlan-gbp tunnel"))
4265 # self.logger.info(self.vapi.cli("show gbp vxlan"))
4266 # self.logger.info(self.vapi.cli("show int addr"))
4270 # EPGs in which the service endpoints exist
4272 epg_320 = VppGbpEndpointGroup(self, 320, 550, rd1, gbd3,
4276 VppGbpEndpointRetention(60))
4277 epg_320.add_vpp_config()
4282 ep1 = VppGbpEndpoint(self, self.pg0,
4284 "10.0.0.1", "11.0.0.1",
4285 "2001:10::1", "3001:10::1")
4286 ep1.add_vpp_config()
4287 ep2 = VppGbpEndpoint(self, self.pg1,
4289 "10.0.1.1", "11.0.1.1",
4290 "2001:11::1", "3001:11::1")
4291 ep2.add_vpp_config()
4296 sep1 = VppGbpEndpoint(self, self.pg3,
4298 "12.0.0.1", "13.0.0.1",
4299 "4001:10::1", "5001:10::1")
4300 sep2 = VppGbpEndpoint(self, self.pg4,
4302 "12.0.0.2", "13.0.0.2",
4303 "4001:10::2", "5001:10::2")
4305 # sep1 and sep2 are not added to config yet
4306 # they are unknown for now
4309 # add routes to EPG subnets
4311 VppGbpSubnet(self, rd1, "10.0.0.0", 24,
4312 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT
4314 VppGbpSubnet(self, rd1, "10.0.1.0", 24,
4315 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT
4319 # Local host to known local host in different BD
4320 # with SFC contract (source and destination are in
4321 # one node and service endpoint in another node)
4323 p4 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
4324 IP(src=ep1.ip4, dst=ep2.ip4) /
4325 UDP(sport=1234, dport=1234) /
4326 Raw(b'\xa5' * 100)),
4327 (Ether(src=ep2.mac, dst=str(self.router_mac)) /
4328 IP(src=ep2.ip4, dst=ep1.ip4) /
4329 UDP(sport=1234, dport=1234) /
4330 Raw(b'\xa5' * 100))]
4331 p6 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
4332 IPv6(src=ep1.ip6, dst=ep2.ip6) /
4333 UDP(sport=1234, dport=1234) /
4334 Raw(b'\xa5' * 100)),
4335 (Ether(src=ep2.mac, dst=str(self.router_mac)) /
4336 IPv6(src=ep2.ip6, dst=ep1.ip6) /
4337 UDP(sport=1234, dport=1230) /
4338 Raw(b'\xa5' * 100))]
4340 # should be dropped since no contract yet
4341 self.send_and_assert_no_replies(self.pg0, [p4[0]])
4342 self.send_and_assert_no_replies(self.pg0, [p6[0]])
4345 # Add a contract with a rule to load-balance redirect via SEP1 and SEP2
4346 # one of the next-hops is via an EP that is not known
4348 rule4 = AclRule(is_permit=1, proto=17)
4349 rule6 = AclRule(src_prefix=IPv6Network((0, 0)),
4350 dst_prefix=IPv6Network((0, 0)), is_permit=1, proto=17)
4351 acl = VppAcl(self, rules=[rule4, rule6])
4352 acl.add_vpp_config()
4355 # test the src-ip hash mode
4357 c1 = VppGbpContract(
4358 self, 402, epg_220.sclass, epg_221.sclass, acl.acl_index,
4359 [VppGbpContractRule(
4360 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4361 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
4362 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
4363 sep1.ip4, sep1.epg.rd)]),
4365 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4366 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
4367 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
4368 sep1.ip6, sep1.epg.rd)])],
4369 [ETH_P_IP, ETH_P_IPV6])
4372 c2 = VppGbpContract(
4373 self, 402, epg_221.sclass, epg_220.sclass, acl.acl_index,
4374 [VppGbpContractRule(
4375 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4376 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
4377 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
4378 sep1.ip4, sep1.epg.rd)]),
4380 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4381 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
4382 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
4383 sep1.ip6, sep1.epg.rd)])],
4384 [ETH_P_IP, ETH_P_IPV6])
4387 # ep1 <--> ep2 redirected through sep1
4389 # packet is redirected to sep bd and then go through sep bd UU
4391 rxs = self.send_and_expect(self.pg0, p4[0] * 17, self.pg7)
4394 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4395 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4396 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4397 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4398 self.assertEqual(rx[VXLAN].vni, 116)
4399 self.assertTrue(rx[VXLAN].flags.G)
4400 self.assertTrue(rx[VXLAN].flags.Instance)
4401 # redirect policy has been applied
4402 self.assertTrue(rx[VXLAN].gpflags.A)
4403 self.assertFalse(rx[VXLAN].gpflags.D)
4405 inner = rx[VXLAN].payload
4407 self.assertEqual(inner[Ether].src, routed_src_mac)
4408 self.assertEqual(inner[Ether].dst, sep1.mac)
4409 self.assertEqual(inner[IP].src, ep1.ip4)
4410 self.assertEqual(inner[IP].dst, ep2.ip4)
4412 rxs = self.send_and_expect(self.pg1, p4[1] * 17, self.pg7)
4415 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4416 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4417 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4418 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4419 self.assertEqual(rx[VXLAN].vni, 116)
4420 self.assertTrue(rx[VXLAN].flags.G)
4421 self.assertTrue(rx[VXLAN].flags.Instance)
4422 # redirect policy has been applied
4423 self.assertTrue(rx[VXLAN].gpflags.A)
4424 self.assertFalse(rx[VXLAN].gpflags.D)
4426 inner = rx[VXLAN].payload
4428 self.assertEqual(inner[Ether].src, routed_src_mac)
4429 self.assertEqual(inner[Ether].dst, sep1.mac)
4430 self.assertEqual(inner[IP].src, ep2.ip4)
4431 self.assertEqual(inner[IP].dst, ep1.ip4)
4433 rxs = self.send_and_expect(self.pg0, p6[0] * 17, self.pg7)
4436 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4437 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4438 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4439 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4440 self.assertEqual(rx[VXLAN].vni, 116)
4441 self.assertTrue(rx[VXLAN].flags.G)
4442 self.assertTrue(rx[VXLAN].flags.Instance)
4443 # redirect policy has been applied
4444 inner = rx[VXLAN].payload
4446 self.assertEqual(inner[Ether].src, routed_src_mac)
4447 self.assertEqual(inner[Ether].dst, sep1.mac)
4448 self.assertEqual(inner[IPv6].src, ep1.ip6)
4449 self.assertEqual(inner[IPv6].dst, ep2.ip6)
4451 rxs = self.send_and_expect(self.pg1, p6[1] * 17, self.pg7)
4454 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4455 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4456 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4457 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4458 self.assertEqual(rx[VXLAN].vni, 116)
4459 self.assertTrue(rx[VXLAN].flags.G)
4460 self.assertTrue(rx[VXLAN].flags.Instance)
4461 # redirect policy has been applied
4462 self.assertTrue(rx[VXLAN].gpflags.A)
4463 self.assertFalse(rx[VXLAN].gpflags.D)
4465 inner = rx[VXLAN].payload
4467 self.assertEqual(inner[Ether].src, routed_src_mac)
4468 self.assertEqual(inner[Ether].dst, sep1.mac)
4469 self.assertEqual(inner[IPv6].src, ep2.ip6)
4470 self.assertEqual(inner[IPv6].dst, ep1.ip6)
4472 # configure sep1: it is now local
4473 # packets between ep1 and ep2 are redirected locally
4474 sep1.add_vpp_config()
4476 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
4479 self.assertEqual(rx[Ether].src, routed_src_mac)
4480 self.assertEqual(rx[Ether].dst, sep1.mac)
4481 self.assertEqual(rx[IP].src, ep1.ip4)
4482 self.assertEqual(rx[IP].dst, ep2.ip4)
4484 rxs = self.send_and_expect(self.pg1, p6[1] * 17, sep1.itf)
4487 self.assertEqual(rx[Ether].src, routed_src_mac)
4488 self.assertEqual(rx[Ether].dst, sep1.mac)
4489 self.assertEqual(rx[IPv6].src, ep2.ip6)
4490 self.assertEqual(rx[IPv6].dst, ep1.ip6)
4492 # packet coming from the l2 spine-proxy to sep1
4493 p = (Ether(src=self.pg7.remote_mac,
4494 dst=self.pg7.local_mac) /
4495 IP(src=self.pg7.remote_ip4,
4496 dst=self.pg7.local_ip4) /
4497 UDP(sport=1234, dport=48879) /
4498 VXLAN(vni=116, gpid=440, gpflags=0x08, flags=0x88) /
4499 Ether(src=str(self.router_mac), dst=sep1.mac) /
4500 IP(src=ep1.ip4, dst=ep2.ip4) /
4501 UDP(sport=1234, dport=1234) /
4504 rxs = self.send_and_expect(self.pg7, [p] * 17, sep1.itf)
4507 self.assertEqual(rx[Ether].src, str(self.router_mac))
4508 self.assertEqual(rx[Ether].dst, sep1.mac)
4509 self.assertEqual(rx[IP].src, ep1.ip4)
4510 self.assertEqual(rx[IP].dst, ep2.ip4)
4512 # contract for SEP to communicate with dst EP
4513 c3 = VppGbpContract(
4514 self, 402, epg_320.sclass, epg_221.sclass, acl.acl_index,
4515 [VppGbpContractRule(
4516 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4517 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC),
4519 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4520 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC)],
4521 [ETH_P_IP, ETH_P_IPV6])
4524 # temporarily remove ep2, so that ep2 is remote & unknown
4525 ep2.remove_vpp_config()
4527 # packet going back from sep1 to its original dest (ep2)
4528 # as ep2 is now unknown (see above), it must go through
4529 # the rd UU (packet is routed)
4531 p1 = (Ether(src=sep1.mac, dst=self.router_mac) /
4532 IP(src=ep1.ip4, dst=ep2.ip4) /
4533 UDP(sport=1234, dport=1234) /
4536 rxs = self.send_and_expect(self.pg3, [p1] * 17, self.pg7)
4539 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4540 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4541 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4542 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4543 self.assertEqual(rx[VXLAN].vni, 114)
4544 self.assertTrue(rx[VXLAN].flags.G)
4545 self.assertTrue(rx[VXLAN].flags.Instance)
4546 # redirect policy has been applied
4547 inner = rx[VXLAN].payload
4548 self.assertEqual(inner[Ether].src, routed_src_mac)
4549 self.assertEqual(inner[Ether].dst, routed_dst_mac)
4550 self.assertEqual(inner[IP].src, ep1.ip4)
4551 self.assertEqual(inner[IP].dst, ep2.ip4)
4553 self.logger.info(self.vapi.cli("show bridge 3 detail"))
4554 sep1.remove_vpp_config()
4556 self.logger.info(self.vapi.cli("show bridge 1 detail"))
4557 self.logger.info(self.vapi.cli("show bridge 2 detail"))
4559 # re-add ep2: it is local again :)
4560 ep2.add_vpp_config()
4562 # packet coming back from the remote sep through rd UU
4563 p2 = (Ether(src=self.pg7.remote_mac,
4564 dst=self.pg7.local_mac) /
4565 IP(src=self.pg7.remote_ip4,
4566 dst=self.pg7.local_ip4) /
4567 UDP(sport=1234, dport=48879) /
4568 VXLAN(vni=114, gpid=441, gpflags=0x09, flags=0x88) /
4569 Ether(src=str(self.router_mac), dst=self.router_mac) /
4570 IP(src=ep1.ip4, dst=ep2.ip4) /
4571 UDP(sport=1234, dport=1234) /
4574 rxs = self.send_and_expect(self.pg7, [p2], self.pg1)
4577 self.assertEqual(rx[Ether].src, str(self.router_mac))
4578 self.assertEqual(rx[Ether].dst, self.pg1.remote_mac)
4579 self.assertEqual(rx[IP].src, ep1.ip4)
4580 self.assertEqual(rx[IP].dst, ep2.ip4)
4583 # bd_uu2.add_vpp_config()
4589 c1.remove_vpp_config()
4590 c2.remove_vpp_config()
4591 c3.remove_vpp_config()
4592 self.pg7.unconfig_ip4()
4594 def test_gbp_l3_out(self):
4597 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
4598 self.vapi.cli("set logging class gbp level debug")
4600 routed_dst_mac = "00:0c:0c:0c:0c:0c"
4601 routed_src_mac = "00:22:bd:f8:19:ff"
4606 t4 = VppIpTable(self, 1)
4608 t6 = VppIpTable(self, 1, True)
4611 rd1 = VppGbpRouteDomain(self, 2, 55, t4, t6)
4612 rd1.add_vpp_config()
4614 self.loop0.set_mac(self.router_mac)
4617 # Bind the BVI to the RD
4619 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
4620 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
4623 # Pg7 hosts a BD's BUM
4624 # Pg1 some other l3 interface
4626 self.pg7.config_ip4()
4627 self.pg7.resolve_arp()
4630 # a multicast vxlan-gbp tunnel for broadcast in the BD
4632 tun_bm = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
4635 tun_bm.add_vpp_config()
4638 # a GBP external bridge domains for the EPs
4640 bd1 = VppBridgeDomain(self, 1)
4641 bd1.add_vpp_config()
4642 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0, None, tun_bm)
4643 gbd1.add_vpp_config()
4646 # The Endpoint-groups in which the external endpoints exist
4648 epg_220 = VppGbpEndpointGroup(self, 220, 113, rd1, gbd1,
4652 VppGbpEndpointRetention(4))
4653 epg_220.add_vpp_config()
4655 # the BVIs have the subnets applied ...
4656 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 24)
4657 ip4_addr.add_vpp_config()
4658 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 64)
4659 ip6_addr.add_vpp_config()
4661 # ... which are L3-out subnets
4662 l3o_1 = VppGbpSubnet(
4663 self, rd1, "10.0.0.0", 24,
4664 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
4666 l3o_1.add_vpp_config()
4669 # an external interface attached to the outside world and the
4672 VppL2Vtr(self, self.vlan_100, L2_VTR_OP.L2_POP_1).add_vpp_config()
4673 VppL2Vtr(self, self.vlan_101, L2_VTR_OP.L2_POP_1).add_vpp_config()
4674 vlan_144 = VppDot1QSubint(self, self.pg0, 144)
4676 # vlan_102 is not poped
4679 # an unicast vxlan-gbp for inter-RD traffic
4681 vx_tun_l3 = VppGbpVxlanTunnel(
4682 self, 444, rd1.rd_id,
4683 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
4685 vx_tun_l3.add_vpp_config()
4688 # External Endpoints
4690 eep1 = VppGbpEndpoint(self, self.vlan_100,
4692 "10.0.0.1", "11.0.0.1",
4693 "2001:10::1", "3001::1",
4694 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
4695 eep1.add_vpp_config()
4696 eep2 = VppGbpEndpoint(self, self.vlan_101,
4698 "10.0.0.2", "11.0.0.2",
4699 "2001:10::2", "3001::2",
4700 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
4701 eep2.add_vpp_config()
4702 eep3 = VppGbpEndpoint(self, self.vlan_102,
4704 "10.0.0.3", "11.0.0.3",
4705 "2001:10::3", "3001::3",
4706 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
4707 eep3.add_vpp_config()
4710 # A remote external endpoint
4712 rep = VppGbpEndpoint(self, vx_tun_l3,
4714 "10.0.0.101", "11.0.0.101",
4715 "2001:10::101", "3001::101",
4716 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
4718 self.pg7.remote_ip4,
4720 rep.add_vpp_config()
4723 # EP1 impersonating EP3 is dropped
4725 p = (Ether(src=eep1.mac, dst="ff:ff:ff:ff:ff:ff") /
4728 psrc="10.0.0.3", pdst="10.0.0.128",
4729 hwsrc=eep1.mac, hwdst="ff:ff:ff:ff:ff:ff"))
4730 self.send_and_assert_no_replies(self.pg0, p)
4733 # ARP packet from External EPs are accepted and replied to
4735 p_arp = (Ether(src=eep1.mac, dst="ff:ff:ff:ff:ff:ff") /
4738 psrc=eep1.ip4, pdst="10.0.0.128",
4739 hwsrc=eep1.mac, hwdst="ff:ff:ff:ff:ff:ff"))
4740 rxs = self.send_and_expect(self.pg0, p_arp * 1, self.pg0)
4743 # ARP packet from host in remote subnet are accepted and replied to
4745 p_arp = (Ether(src=eep3.mac, dst="ff:ff:ff:ff:ff:ff") /
4748 psrc=eep3.ip4, pdst="10.0.0.128",
4749 hwsrc=eep3.mac, hwdst="ff:ff:ff:ff:ff:ff"))
4750 rxs = self.send_and_expect(self.pg0, p_arp * 1, self.pg0)
4753 # packets destined to unknown addresses in the BVI's subnet
4756 p4 = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
4758 IP(src="10.0.0.1", dst="10.0.0.88") /
4759 UDP(sport=1234, dport=1234) /
4761 p6 = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
4763 IPv6(src="2001:10::1", dst="2001:10::88") /
4764 UDP(sport=1234, dport=1234) /
4767 rxs = self.send_and_expect(self.pg0, p4 * 1, self.pg7)
4770 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4771 # self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4772 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4773 self.assertEqual(rx[IP].dst, "239.1.1.1")
4774 self.assertEqual(rx[VXLAN].vni, 88)
4775 self.assertTrue(rx[VXLAN].flags.G)
4776 self.assertTrue(rx[VXLAN].flags.Instance)
4777 # policy was applied to the original IP packet
4778 self.assertEqual(rx[VXLAN].gpid, 113)
4779 self.assertTrue(rx[VXLAN].gpflags.A)
4780 self.assertFalse(rx[VXLAN].gpflags.D)
4782 inner = rx[VXLAN].payload
4784 self.assertTrue(inner.haslayer(ARP))
4787 # remote to external
4789 p = (Ether(src=self.pg7.remote_mac,
4790 dst=self.pg7.local_mac) /
4791 IP(src=self.pg7.remote_ip4,
4792 dst=self.pg7.local_ip4) /
4793 UDP(sport=1234, dport=48879) /
4794 VXLAN(vni=444, gpid=113, flags=0x88) /
4795 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
4796 IP(src="10.0.0.101", dst="10.0.0.1") /
4797 UDP(sport=1234, dport=1234) /
4800 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
4803 # local EP pings router
4805 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
4807 IP(src=eep1.ip4, dst="10.0.0.128") /
4808 ICMP(type='echo-request'))
4810 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
4813 self.assertEqual(rx[Ether].src, str(self.router_mac))
4814 self.assertEqual(rx[Ether].dst, eep1.mac)
4815 self.assertEqual(rx[Dot1Q].vlan, 100)
4818 # local EP pings other local EP
4820 p = (Ether(src=eep1.mac, dst=eep2.mac) /
4822 IP(src=eep1.ip4, dst=eep2.ip4) /
4823 ICMP(type='echo-request'))
4825 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
4828 self.assertEqual(rx[Ether].src, eep1.mac)
4829 self.assertEqual(rx[Ether].dst, eep2.mac)
4830 self.assertEqual(rx[Dot1Q].vlan, 101)
4833 # local EP pings router w/o vlan tag poped
4835 p = (Ether(src=eep3.mac, dst=str(self.router_mac)) /
4837 IP(src=eep3.ip4, dst="10.0.0.128") /
4838 ICMP(type='echo-request'))
4840 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
4843 self.assertEqual(rx[Ether].src, str(self.router_mac))
4844 self.assertEqual(rx[Ether].dst, self.vlan_102.remote_mac)
4847 # A ip4 subnet reachable through the external EP1
4849 ip_220 = VppIpRoute(self, "10.220.0.0", 24,
4850 [VppRoutePath(eep1.ip4,
4851 eep1.epg.bvi.sw_if_index)],
4852 table_id=t4.table_id)
4853 ip_220.add_vpp_config()
4855 l3o_220 = VppGbpSubnet(
4856 self, rd1, "10.220.0.0", 24,
4857 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
4859 l3o_220.add_vpp_config()
4862 # An ip6 subnet reachable through the external EP1
4864 ip6_220 = VppIpRoute(self, "10:220::", 64,
4865 [VppRoutePath(eep1.ip6,
4866 eep1.epg.bvi.sw_if_index)],
4867 table_id=t6.table_id)
4868 ip6_220.add_vpp_config()
4870 l3o6_220 = VppGbpSubnet(
4871 self, rd1, "10:220::", 64,
4872 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
4874 l3o6_220.add_vpp_config()
4877 # A subnet reachable through the external EP2
4879 ip_221 = VppIpRoute(self, "10.221.0.0", 24,
4880 [VppRoutePath(eep2.ip4,
4881 eep2.epg.bvi.sw_if_index)],
4882 table_id=t4.table_id)
4883 ip_221.add_vpp_config()
4885 l3o_221 = VppGbpSubnet(
4886 self, rd1, "10.221.0.0", 24,
4887 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
4889 l3o_221.add_vpp_config()
4892 # ping between hosts in remote subnets
4893 # dropped without a contract
4895 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
4897 IP(src="10.220.0.1", dst="10.221.0.1") /
4898 ICMP(type='echo-request'))
4900 self.send_and_assert_no_replies(self.pg0, p * 1)
4903 # contract for the external nets to communicate
4905 rule4 = AclRule(is_permit=1, proto=17)
4906 rule6 = AclRule(src_prefix=IPv6Network((0, 0)),
4907 dst_prefix=IPv6Network((0, 0)), is_permit=1, proto=17)
4908 acl = VppAcl(self, rules=[rule4, rule6])
4909 acl.add_vpp_config()
4912 # A contract with the wrong scope is not matched
4914 c_44 = VppGbpContract(
4915 self, 44, 4220, 4221, acl.acl_index,
4916 [VppGbpContractRule(
4917 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4918 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4921 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4922 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4924 [ETH_P_IP, ETH_P_IPV6])
4925 c_44.add_vpp_config()
4926 self.send_and_assert_no_replies(self.pg0, p * 1)
4928 c1 = VppGbpContract(
4929 self, 55, 4220, 4221, acl.acl_index,
4930 [VppGbpContractRule(
4931 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4932 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4935 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4936 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4938 [ETH_P_IP, ETH_P_IPV6])
4942 # Contracts allowing ext-net 200 to talk with external EPs
4944 c2 = VppGbpContract(
4945 self, 55, 4220, 113, acl.acl_index,
4946 [VppGbpContractRule(
4947 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4948 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4951 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4952 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4954 [ETH_P_IP, ETH_P_IPV6])
4956 c3 = VppGbpContract(
4957 self, 55, 113, 4220, acl.acl_index,
4958 [VppGbpContractRule(
4959 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4960 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4963 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4964 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4966 [ETH_P_IP, ETH_P_IPV6])
4970 # ping between hosts in remote subnets
4972 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
4974 IP(src="10.220.0.1", dst="10.221.0.1") /
4975 UDP(sport=1234, dport=1234) /
4978 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
4981 self.assertEqual(rx[Ether].src, str(self.router_mac))
4982 self.assertEqual(rx[Ether].dst, eep2.mac)
4983 self.assertEqual(rx[Dot1Q].vlan, 101)
4985 # we did not learn these external hosts
4986 self.assertFalse(find_gbp_endpoint(self, ip="10.220.0.1"))
4987 self.assertFalse(find_gbp_endpoint(self, ip="10.221.0.1"))
4990 # from remote external EP to local external EP
4992 p = (Ether(src=self.pg7.remote_mac,
4993 dst=self.pg7.local_mac) /
4994 IP(src=self.pg7.remote_ip4,
4995 dst=self.pg7.local_ip4) /
4996 UDP(sport=1234, dport=48879) /
4997 VXLAN(vni=444, gpid=113, flags=0x88) /
4998 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
4999 IP(src="10.0.0.101", dst="10.220.0.1") /
5000 UDP(sport=1234, dport=1234) /
5003 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
5006 # ping from an external host to the remote external EP
5008 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
5010 IP(src="10.220.0.1", dst=rep.ip4) /
5011 UDP(sport=1234, dport=1234) /
5014 rxs = self.send_and_expect(self.pg0, p * 1, self.pg7)
5017 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
5018 # self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
5019 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
5020 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
5021 self.assertEqual(rx[VXLAN].vni, 444)
5022 self.assertTrue(rx[VXLAN].flags.G)
5023 self.assertTrue(rx[VXLAN].flags.Instance)
5024 # the sclass of the ext-net the packet came from
5025 self.assertEqual(rx[VXLAN].gpid, 4220)
5026 # policy was applied to the original IP packet
5027 self.assertTrue(rx[VXLAN].gpflags.A)
5028 # since it's an external host the reciever should not learn it
5029 self.assertTrue(rx[VXLAN].gpflags.D)
5030 inner = rx[VXLAN].payload
5031 self.assertEqual(inner[IP].src, "10.220.0.1")
5032 self.assertEqual(inner[IP].dst, rep.ip4)
5035 # An external subnet reachable via the remote external EP
5039 # first the VXLAN-GBP tunnel over which it is reached
5041 vx_tun_r1 = VppVxlanGbpTunnel(
5042 self, self.pg7.local_ip4,
5043 self.pg7.remote_ip4, 445,
5044 mode=(VppEnum.vl_api_vxlan_gbp_api_tunnel_mode_t.
5045 VXLAN_GBP_API_TUNNEL_MODE_L3))
5046 vx_tun_r1.add_vpp_config()
5047 VppIpInterfaceBind(self, vx_tun_r1, t4).add_vpp_config()
5049 self.logger.info(self.vapi.cli("sh vxlan-gbp tunnel"))
5052 # then the special adj to resolve through on that tunnel
5054 n1 = VppNeighbor(self,
5055 vx_tun_r1.sw_if_index,
5056 "00:0c:0c:0c:0c:0c",
5057 self.pg7.remote_ip4)
5061 # the route via the adj above
5063 ip_222 = VppIpRoute(self, "10.222.0.0", 24,
5064 [VppRoutePath(self.pg7.remote_ip4,
5065 vx_tun_r1.sw_if_index)],
5066 table_id=t4.table_id)
5067 ip_222.add_vpp_config()
5069 l3o_222 = VppGbpSubnet(
5070 self, rd1, "10.222.0.0", 24,
5071 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
5073 l3o_222.add_vpp_config()
5076 # ping between hosts in local and remote external subnets
5077 # dropped without a contract
5079 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
5081 IP(src="10.220.0.1", dst="10.222.0.1") /
5082 UDP(sport=1234, dport=1234) /
5085 rxs = self.send_and_assert_no_replies(self.pg0, p * 1)
5088 # Add contracts ext-nets for 220 -> 222
5090 c4 = VppGbpContract(
5091 self, 55, 4220, 4222, acl.acl_index,
5092 [VppGbpContractRule(
5093 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5094 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5097 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5098 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5100 [ETH_P_IP, ETH_P_IPV6])
5104 # ping from host in local to remote external subnets
5106 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
5108 IP(src="10.220.0.1", dst="10.222.0.1") /
5109 UDP(sport=1234, dport=1234) /
5112 rxs = self.send_and_expect(self.pg0, p * 3, self.pg7)
5115 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
5116 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
5117 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
5118 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
5119 self.assertEqual(rx[VXLAN].vni, 445)
5120 self.assertTrue(rx[VXLAN].flags.G)
5121 self.assertTrue(rx[VXLAN].flags.Instance)
5122 # the sclass of the ext-net the packet came from
5123 self.assertEqual(rx[VXLAN].gpid, 4220)
5124 # policy was applied to the original IP packet
5125 self.assertTrue(rx[VXLAN].gpflags.A)
5126 # since it's an external host the reciever should not learn it
5127 self.assertTrue(rx[VXLAN].gpflags.D)
5128 inner = rx[VXLAN].payload
5129 self.assertEqual(inner[Ether].dst, "00:0c:0c:0c:0c:0c")
5130 self.assertEqual(inner[IP].src, "10.220.0.1")
5131 self.assertEqual(inner[IP].dst, "10.222.0.1")
5134 # make the external subnet ECMP
5136 vx_tun_r2 = VppVxlanGbpTunnel(
5137 self, self.pg7.local_ip4,
5138 self.pg7.remote_ip4, 446,
5139 mode=(VppEnum.vl_api_vxlan_gbp_api_tunnel_mode_t.
5140 VXLAN_GBP_API_TUNNEL_MODE_L3))
5141 vx_tun_r2.add_vpp_config()
5142 VppIpInterfaceBind(self, vx_tun_r2, t4).add_vpp_config()
5144 self.logger.info(self.vapi.cli("sh vxlan-gbp tunnel"))
5146 n2 = VppNeighbor(self,
5147 vx_tun_r2.sw_if_index,
5148 "00:0c:0c:0c:0c:0c",
5149 self.pg7.remote_ip4)
5152 ip_222.modify([VppRoutePath(self.pg7.remote_ip4,
5153 vx_tun_r1.sw_if_index),
5154 VppRoutePath(self.pg7.remote_ip4,
5155 vx_tun_r2.sw_if_index)])
5158 # now expect load-balance
5160 p = [(Ether(src=eep1.mac, dst=str(self.router_mac)) /
5162 IP(src="10.220.0.1", dst="10.222.0.1") /
5163 UDP(sport=1234, dport=1234) /
5164 Raw(b'\xa5' * 100)),
5165 (Ether(src=eep1.mac, dst=str(self.router_mac)) /
5167 IP(src="10.220.0.1", dst="10.222.0.1") /
5168 UDP(sport=1222, dport=1235) /
5169 Raw(b'\xa5' * 100))]
5171 rxs = self.send_and_expect(self.pg0, p, self.pg7)
5173 self.assertEqual(rxs[0][VXLAN].vni, 445)
5174 self.assertEqual(rxs[1][VXLAN].vni, 446)
5177 # Same LB test for v6
5179 n3 = VppNeighbor(self,
5180 vx_tun_r1.sw_if_index,
5181 "00:0c:0c:0c:0c:0c",
5182 self.pg7.remote_ip6)
5184 n4 = VppNeighbor(self,
5185 vx_tun_r2.sw_if_index,
5186 "00:0c:0c:0c:0c:0c",
5187 self.pg7.remote_ip6)
5190 ip_222_6 = VppIpRoute(self, "10:222::", 64,
5191 [VppRoutePath(self.pg7.remote_ip6,
5192 vx_tun_r1.sw_if_index),
5193 VppRoutePath(self.pg7.remote_ip6,
5194 vx_tun_r2.sw_if_index)],
5195 table_id=t6.table_id)
5196 ip_222_6.add_vpp_config()
5198 l3o_222_6 = VppGbpSubnet(
5199 self, rd1, "10:222::", 64,
5200 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
5202 l3o_222_6.add_vpp_config()
5204 p = [(Ether(src=eep1.mac, dst=str(self.router_mac)) /
5206 IPv6(src="10:220::1", dst="10:222::1") /
5207 UDP(sport=1234, dport=1234) /
5208 Raw(b'\xa5' * 100)),
5209 (Ether(src=eep1.mac, dst=str(self.router_mac)) /
5211 IPv6(src="10:220::1", dst="10:222::1") /
5212 UDP(sport=7777, dport=8881) /
5213 Raw(b'\xa5' * 100))]
5215 self.logger.info(self.vapi.cli("sh ip6 fib 10:222::1"))
5216 rxs = self.send_and_expect(self.pg0, p, self.pg7)
5218 self.assertEqual(rxs[0][VXLAN].vni, 445)
5219 self.assertEqual(rxs[1][VXLAN].vni, 446)
5222 # ping from host in remote to local external subnets
5223 # there's no contract for this, but the A bit is set.
5225 p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
5226 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
5227 UDP(sport=1234, dport=48879) /
5228 VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
5229 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
5230 IP(src="10.222.0.1", dst="10.220.0.1") /
5231 UDP(sport=1234, dport=1234) /
5234 rxs = self.send_and_expect(self.pg7, p * 3, self.pg0)
5235 self.assertFalse(find_gbp_endpoint(self, ip="10.222.0.1"))
5238 # ping from host in remote to remote external subnets
5239 # this is dropped by reflection check.
5241 p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
5242 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
5243 UDP(sport=1234, dport=48879) /
5244 VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
5245 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
5246 IP(src="10.222.0.1", dst="10.222.0.2") /
5247 UDP(sport=1234, dport=1234) /
5250 rxs = self.send_and_assert_no_replies(self.pg7, p * 3)
5252 p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
5253 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
5254 UDP(sport=1234, dport=48879) /
5255 VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
5256 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
5257 IPv6(src="10:222::1", dst="10:222::2") /
5258 UDP(sport=1234, dport=1234) /
5261 rxs = self.send_and_assert_no_replies(self.pg7, p * 3)
5266 lep1 = VppGbpEndpoint(self, vlan_144,
5268 "10.0.0.44", "11.0.0.44",
5269 "2001:10::44", "3001::44")
5270 lep1.add_vpp_config()
5273 # local EP to local ip4 external subnet
5275 p = (Ether(src=lep1.mac, dst=str(self.router_mac)) /
5277 IP(src=lep1.ip4, dst="10.220.0.1") /
5278 UDP(sport=1234, dport=1234) /
5281 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
5284 self.assertEqual(rx[Ether].src, str(self.router_mac))
5285 self.assertEqual(rx[Ether].dst, eep1.mac)
5286 self.assertEqual(rx[Dot1Q].vlan, 100)
5289 # local EP to local ip6 external subnet
5291 p = (Ether(src=lep1.mac, dst=str(self.router_mac)) /
5293 IPv6(src=lep1.ip6, dst="10:220::1") /
5294 UDP(sport=1234, dport=1234) /
5297 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
5300 self.assertEqual(rx[Ether].src, str(self.router_mac))
5301 self.assertEqual(rx[Ether].dst, eep1.mac)
5302 self.assertEqual(rx[Dot1Q].vlan, 100)
5305 # ip4 and ip6 subnets that load-balance
5307 ip_20 = VppIpRoute(self, "10.20.0.0", 24,
5308 [VppRoutePath(eep1.ip4,
5309 eep1.epg.bvi.sw_if_index),
5310 VppRoutePath(eep2.ip4,
5311 eep2.epg.bvi.sw_if_index)],
5312 table_id=t4.table_id)
5313 ip_20.add_vpp_config()
5315 l3o_20 = VppGbpSubnet(
5316 self, rd1, "10.20.0.0", 24,
5317 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
5319 l3o_20.add_vpp_config()
5321 ip6_20 = VppIpRoute(self, "10:20::", 64,
5322 [VppRoutePath(eep1.ip6,
5323 eep1.epg.bvi.sw_if_index),
5324 VppRoutePath(eep2.ip6,
5325 eep2.epg.bvi.sw_if_index)],
5326 table_id=t6.table_id)
5327 ip6_20.add_vpp_config()
5329 l3o6_20 = VppGbpSubnet(
5330 self, rd1, "10:20::", 64,
5331 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
5333 l3o6_20.add_vpp_config()
5335 self.logger.info(self.vapi.cli("sh ip fib 10.20.0.1"))
5336 self.logger.info(self.vapi.cli("sh ip6 fib 10:20::1"))
5338 # two ip6 packets whose port are chosen so they load-balance
5339 p = [(Ether(src=lep1.mac, dst=str(self.router_mac)) /
5341 IPv6(src=lep1.ip6, dst="10:20::1") /
5342 UDP(sport=1234, dport=1234) /
5343 Raw(b'\xa5' * 100)),
5344 (Ether(src=lep1.mac, dst=str(self.router_mac)) /
5346 IPv6(src=lep1.ip6, dst="10:20::1") /
5347 UDP(sport=124, dport=1230) /
5348 Raw(b'\xa5' * 100))]
5350 rxs = self.send_and_expect(self.pg0, p, self.pg0, 2)
5352 self.assertEqual(rxs[0][Dot1Q].vlan, 101)
5353 self.assertEqual(rxs[1][Dot1Q].vlan, 100)
5355 # two ip4 packets whose port are chosen so they load-balance
5356 p = [(Ether(src=lep1.mac, dst=str(self.router_mac)) /
5358 IP(src=lep1.ip4, dst="10.20.0.1") /
5359 UDP(sport=1235, dport=1235) /
5360 Raw(b'\xa5' * 100)),
5361 (Ether(src=lep1.mac, dst=str(self.router_mac)) /
5363 IP(src=lep1.ip4, dst="10.20.0.1") /
5364 UDP(sport=124, dport=1230) /
5365 Raw(b'\xa5' * 100))]
5367 rxs = self.send_and_expect(self.pg0, p, self.pg0, 2)
5369 self.assertEqual(rxs[0][Dot1Q].vlan, 101)
5370 self.assertEqual(rxs[1][Dot1Q].vlan, 100)
5375 ip_222.remove_vpp_config()
5376 self.pg7.unconfig_ip4()
5377 self.vlan_101.set_vtr(L2_VTR_OP.L2_DISABLED)
5378 self.vlan_100.set_vtr(L2_VTR_OP.L2_DISABLED)
5380 def test_gbp_anon_l3_out(self):
5381 """ GBP Anonymous L3 Out """
5383 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
5384 self.vapi.cli("set logging class gbp level debug")
5386 routed_dst_mac = "00:0c:0c:0c:0c:0c"
5387 routed_src_mac = "00:22:bd:f8:19:ff"
5392 t4 = VppIpTable(self, 1)
5394 t6 = VppIpTable(self, 1, True)
5397 rd1 = VppGbpRouteDomain(self, 2, 55, t4, t6)
5398 rd1.add_vpp_config()
5400 self.loop0.set_mac(self.router_mac)
5403 # Bind the BVI to the RD
5405 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
5406 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
5409 # Pg7 hosts a BD's BUM
5410 # Pg1 some other l3 interface
5412 self.pg7.config_ip4()
5413 self.pg7.resolve_arp()
5416 # a GBP external bridge domains for the EPs
5418 bd1 = VppBridgeDomain(self, 1)
5419 bd1.add_vpp_config()
5420 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0, None, None)
5421 gbd1.add_vpp_config()
5424 # The Endpoint-groups in which the external endpoints exist
5426 epg_220 = VppGbpEndpointGroup(self, 220, 113, rd1, gbd1,
5430 VppGbpEndpointRetention(4))
5431 epg_220.add_vpp_config()
5433 # the BVIs have the subnet applied ...
5434 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 24)
5435 ip4_addr.add_vpp_config()
5437 # ... which is an Anonymous L3-out subnets
5438 l3o_1 = VppGbpSubnet(
5439 self, rd1, "10.0.0.0", 24,
5440 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_ANON_L3_OUT,
5442 l3o_1.add_vpp_config()
5445 # an external interface attached to the outside world and the
5448 VppL2Vtr(self, self.vlan_100, L2_VTR_OP.L2_POP_1).add_vpp_config()
5449 VppL2Vtr(self, self.vlan_101, L2_VTR_OP.L2_POP_1).add_vpp_config()
5452 # vlan_100 and vlan_101 are anonymous l3-out interfaces
5454 ext_itf = VppGbpExtItf(self, self.vlan_100, bd1, rd1, anon=True)
5455 ext_itf.add_vpp_config()
5456 ext_itf = VppGbpExtItf(self, self.vlan_101, bd1, rd1, anon=True)
5457 ext_itf.add_vpp_config()
5460 # an unicast vxlan-gbp for inter-RD traffic
5462 vx_tun_l3 = VppGbpVxlanTunnel(
5463 self, 444, rd1.rd_id,
5464 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
5466 vx_tun_l3.add_vpp_config()
5469 # A remote external endpoint
5471 rep = VppGbpEndpoint(self, vx_tun_l3,
5473 "10.0.0.201", "11.0.0.201",
5474 "2001:10::201", "3001::101",
5475 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
5477 self.pg7.remote_ip4,
5479 rep.add_vpp_config()
5482 # ARP packet from host in external subnet are accepted, flooded and
5483 # replied to. We expect 2 packets:
5484 # - APR request flooded over the other vlan subif
5485 # - ARP reply from BVI
5487 p_arp = (Ether(src=self.vlan_100.remote_mac,
5488 dst="ff:ff:ff:ff:ff:ff") /
5493 hwsrc=self.vlan_100.remote_mac,
5494 hwdst="ff:ff:ff:ff:ff:ff"))
5495 rxs = self.send_and_expect(self.pg0, p_arp * 1, self.pg0, n_rx=2)
5497 p_arp = (Ether(src=self.vlan_101.remote_mac,
5498 dst="ff:ff:ff:ff:ff:ff") /
5503 hwsrc=self.vlan_101.remote_mac,
5504 hwdst="ff:ff:ff:ff:ff:ff"))
5505 rxs = self.send_and_expect(self.pg0, p_arp * 1, self.pg0, n_rx=2)
5508 # remote to external
5510 p = (Ether(src=self.pg7.remote_mac,
5511 dst=self.pg7.local_mac) /
5512 IP(src=self.pg7.remote_ip4,
5513 dst=self.pg7.local_ip4) /
5514 UDP(sport=1234, dport=48879) /
5515 VXLAN(vni=vx_tun_l3.vni, gpid=epg_220.sclass, flags=0x88) /
5516 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
5517 IP(src=str(rep.ip4), dst="10.0.0.100") /
5518 UDP(sport=1234, dport=1234) /
5520 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
5523 # local EP pings router
5525 p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
5527 IP(src="10.0.0.100", dst="10.0.0.128") /
5528 ICMP(type='echo-request'))
5529 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
5532 self.assertEqual(rx[Ether].src, str(self.router_mac))
5533 self.assertEqual(rx[Ether].dst, self.vlan_100.remote_mac)
5534 self.assertEqual(rx[Dot1Q].vlan, 100)
5537 # local EP pings other local EP
5539 p = (Ether(src=self.vlan_100.remote_mac,
5540 dst=self.vlan_101.remote_mac) /
5542 IP(src="10.0.0.100", dst="10.0.0.101") /
5543 ICMP(type='echo-request'))
5544 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
5547 self.assertEqual(rx[Ether].src, self.vlan_100.remote_mac)
5548 self.assertEqual(rx[Ether].dst, self.vlan_101.remote_mac)
5549 self.assertEqual(rx[Dot1Q].vlan, 101)
5552 # A subnet reachable through an external router on vlan 100
5554 ip_220 = VppIpRoute(self, "10.220.0.0", 24,
5555 [VppRoutePath("10.0.0.100",
5556 epg_220.bvi.sw_if_index)],
5557 table_id=t4.table_id)
5558 ip_220.add_vpp_config()
5560 l3o_220 = VppGbpSubnet(
5561 self, rd1, "10.220.0.0", 24,
5562 # note: this a "regular" L3 out subnet (not connected)
5563 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
5565 l3o_220.add_vpp_config()
5568 # A subnet reachable through an external router on vlan 101
5570 ip_221 = VppIpRoute(self, "10.221.0.0", 24,
5571 [VppRoutePath("10.0.0.101",
5572 epg_220.bvi.sw_if_index)],
5573 table_id=t4.table_id)
5574 ip_221.add_vpp_config()
5576 l3o_221 = VppGbpSubnet(
5577 self, rd1, "10.221.0.0", 24,
5578 # note: this a "regular" L3 out subnet (not connected)
5579 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
5581 l3o_221.add_vpp_config()
5584 # ping between hosts in remote subnets
5585 # dropped without a contract
5587 p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
5589 IP(src="10.220.0.1", dst="10.221.0.1") /
5590 ICMP(type='echo-request'))
5592 rxs = self.send_and_assert_no_replies(self.pg0, p * 1)
5595 # contract for the external nets to communicate
5597 rule4 = AclRule(is_permit=1, proto=17)
5598 rule6 = AclRule(src_prefix=IPv6Network((0, 0)),
5599 dst_prefix=IPv6Network((0, 0)), is_permit=1, proto=17)
5600 acl = VppAcl(self, rules=[rule4, rule6])
5601 acl.add_vpp_config()
5603 c1 = VppGbpContract(
5604 self, 55, 4220, 4221, acl.acl_index,
5605 [VppGbpContractRule(
5606 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5607 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5610 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5611 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5613 [ETH_P_IP, ETH_P_IPV6])
5617 # Contracts allowing ext-net 200 to talk with external EPs
5619 c2 = VppGbpContract(
5620 self, 55, 4220, 113, acl.acl_index,
5621 [VppGbpContractRule(
5622 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5623 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5626 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5627 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5629 [ETH_P_IP, ETH_P_IPV6])
5631 c3 = VppGbpContract(
5632 self, 55, 113, 4220, acl.acl_index,
5633 [VppGbpContractRule(
5634 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5635 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5638 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5639 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5641 [ETH_P_IP, ETH_P_IPV6])
5645 # ping between hosts in remote subnets
5647 p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
5649 IP(src="10.220.0.1", dst="10.221.0.1") /
5650 UDP(sport=1234, dport=1234) /
5653 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
5656 self.assertEqual(rx[Ether].src, str(self.router_mac))
5657 self.assertEqual(rx[Ether].dst, self.vlan_101.remote_mac)
5658 self.assertEqual(rx[Dot1Q].vlan, 101)
5660 # we did not learn these external hosts
5661 self.assertFalse(find_gbp_endpoint(self, ip="10.220.0.1"))
5662 self.assertFalse(find_gbp_endpoint(self, ip="10.221.0.1"))
5665 # from remote external EP to local external EP
5667 p = (Ether(src=self.pg7.remote_mac,
5668 dst=self.pg7.local_mac) /
5669 IP(src=self.pg7.remote_ip4,
5670 dst=self.pg7.local_ip4) /
5671 UDP(sport=1234, dport=48879) /
5672 VXLAN(vni=444, gpid=113, flags=0x88) /
5673 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
5674 IP(src=rep.ip4, dst="10.220.0.1") /
5675 UDP(sport=1234, dport=1234) /
5678 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
5681 # ping from an external host to the remote external EP
5683 p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
5685 IP(src="10.220.0.1", dst=rep.ip4) /
5686 UDP(sport=1234, dport=1234) /
5689 rxs = self.send_and_expect(self.pg0, p * 1, self.pg7)
5692 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
5693 # self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
5694 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
5695 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
5696 self.assertEqual(rx[VXLAN].vni, 444)
5697 self.assertTrue(rx[VXLAN].flags.G)
5698 self.assertTrue(rx[VXLAN].flags.Instance)
5699 # the sclass of the ext-net the packet came from
5700 self.assertEqual(rx[VXLAN].gpid, 4220)
5701 # policy was applied to the original IP packet
5702 self.assertTrue(rx[VXLAN].gpflags.A)
5703 # since it's an external host the reciever should not learn it
5704 self.assertTrue(rx[VXLAN].gpflags.D)
5705 inner = rx[VXLAN].payload
5706 self.assertEqual(inner[IP].src, "10.220.0.1")
5707 self.assertEqual(inner[IP].dst, rep.ip4)
5710 # An external subnet reachable via the remote external EP
5714 # first the VXLAN-GBP tunnel over which it is reached
5716 vx_tun_r = VppVxlanGbpTunnel(
5717 self, self.pg7.local_ip4,
5718 self.pg7.remote_ip4, 445,
5719 mode=(VppEnum.vl_api_vxlan_gbp_api_tunnel_mode_t.
5720 VXLAN_GBP_API_TUNNEL_MODE_L3))
5721 vx_tun_r.add_vpp_config()
5722 VppIpInterfaceBind(self, vx_tun_r, t4).add_vpp_config()
5724 self.logger.info(self.vapi.cli("sh vxlan-gbp tunnel"))
5727 # then the special adj to resolve through on that tunnel
5729 n1 = VppNeighbor(self,
5730 vx_tun_r.sw_if_index,
5731 "00:0c:0c:0c:0c:0c",
5732 self.pg7.remote_ip4)
5736 # the route via the adj above
5738 ip_222 = VppIpRoute(self, "10.222.0.0", 24,
5739 [VppRoutePath(self.pg7.remote_ip4,
5740 vx_tun_r.sw_if_index)],
5741 table_id=t4.table_id)
5742 ip_222.add_vpp_config()
5744 l3o_222 = VppGbpSubnet(
5745 self, rd1, "10.222.0.0", 24,
5746 # note: this a "regular" l3out subnet (not connected)
5747 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
5749 l3o_222.add_vpp_config()
5752 # ping between hosts in local and remote external subnets
5753 # dropped without a contract
5755 p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
5757 IP(src="10.220.0.1", dst="10.222.0.1") /
5758 UDP(sport=1234, dport=1234) /
5761 rxs = self.send_and_assert_no_replies(self.pg0, p * 1)
5764 # Add contracts ext-nets for 220 -> 222
5766 c4 = VppGbpContract(
5767 self, 55, 4220, 4222, acl.acl_index,
5768 [VppGbpContractRule(
5769 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5770 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5773 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5774 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5776 [ETH_P_IP, ETH_P_IPV6])
5780 # ping from host in local to remote external subnets
5782 p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
5784 IP(src="10.220.0.1", dst="10.222.0.1") /
5785 UDP(sport=1234, dport=1234) /
5788 rxs = self.send_and_expect(self.pg0, p * 3, self.pg7)
5791 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
5792 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
5793 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
5794 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
5795 self.assertEqual(rx[VXLAN].vni, 445)
5796 self.assertTrue(rx[VXLAN].flags.G)
5797 self.assertTrue(rx[VXLAN].flags.Instance)
5798 # the sclass of the ext-net the packet came from
5799 self.assertEqual(rx[VXLAN].gpid, 4220)
5800 # policy was applied to the original IP packet
5801 self.assertTrue(rx[VXLAN].gpflags.A)
5802 # since it's an external host the reciever should not learn it
5803 self.assertTrue(rx[VXLAN].gpflags.D)
5804 inner = rx[VXLAN].payload
5805 self.assertEqual(inner[Ether].dst, "00:0c:0c:0c:0c:0c")
5806 self.assertEqual(inner[IP].src, "10.220.0.1")
5807 self.assertEqual(inner[IP].dst, "10.222.0.1")
5810 # ping from host in remote to local external subnets
5811 # there's no contract for this, but the A bit is set.
5813 p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
5814 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
5815 UDP(sport=1234, dport=48879) /
5816 VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
5817 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
5818 IP(src="10.222.0.1", dst="10.220.0.1") /
5819 UDP(sport=1234, dport=1234) /
5822 rxs = self.send_and_expect(self.pg7, p * 3, self.pg0)
5823 self.assertFalse(find_gbp_endpoint(self, ip="10.222.0.1"))
5826 # ping from host in remote to remote external subnets
5827 # this is dropped by reflection check.
5829 p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
5830 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
5831 UDP(sport=1234, dport=48879) /
5832 VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
5833 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
5834 IP(src="10.222.0.1", dst="10.222.0.2") /
5835 UDP(sport=1234, dport=1234) /
5838 rxs = self.send_and_assert_no_replies(self.pg7, p * 3)
5843 self.vlan_101.set_vtr(L2_VTR_OP.L2_DISABLED)
5844 self.vlan_100.set_vtr(L2_VTR_OP.L2_DISABLED)
5845 self.pg7.unconfig_ip4()
5848 if __name__ == '__main__':
5849 unittest.main(testRunner=VppTestRunner)