3 from socket import AF_INET, AF_INET6
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
15 from scapy.utils import inet_pton, inet_ntop
17 from framework import VppTestCase, VppTestRunner
18 from vpp_object import VppObject
19 from vpp_interface import VppInterface
20 from vpp_ip_route import VppIpRoute, VppRoutePath, VppIpTable, \
21 VppIpInterfaceAddress, VppIpInterfaceBind, find_route, FibPathProto, \
23 from vpp_l2 import VppBridgeDomain, VppBridgeDomainPort, \
24 VppBridgeDomainArpEntry, VppL2FibEntry, find_bridge_domain_port, VppL2Vtr
25 from vpp_sub_interface import L2_VTR_OP, VppDot1QSubint
26 from vpp_ip import DpoProto, get_dpo_proto
27 from vpp_papi import VppEnum, MACAddress
28 from vpp_vxlan_gbp_tunnel import find_vxlan_gbp_tunnel, INDEX_INVALID, \
30 from vpp_neighbor import VppNeighbor
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 VppGbpAcl(VppObject):
577 def __init__(self, test):
579 self.acl_index = 4294967295
581 def create_rule(self, is_ipv6=0, permit_deny=0, proto=-1,
582 s_prefix=0, s_ip=b'\x00\x00\x00\x00', sport_from=0,
583 sport_to=65535, d_prefix=0, d_ip=b'\x00\x00\x00\x00',
584 dport_from=0, dport_to=65535):
585 if proto == -1 or proto == 0:
588 elif proto == 1 or proto == 58:
591 rule = ({'is_permit': permit_deny, 'is_ipv6': is_ipv6, 'proto': proto,
592 'srcport_or_icmptype_first': sport_from,
593 'srcport_or_icmptype_last': sport_to,
594 'src_ip_prefix_len': s_prefix,
596 'dstport_or_icmpcode_first': dport_from,
597 'dstport_or_icmpcode_last': dport_to,
598 'dst_ip_prefix_len': d_prefix,
599 'dst_ip_addr': d_ip})
602 def add_vpp_config(self, rules):
604 reply = self._test.vapi.acl_add_replace(acl_index=self.acl_index,
607 self.acl_index = reply.acl_index
608 return self.acl_index
610 def remove_vpp_config(self):
611 self._test.vapi.acl_del(self.acl_index)
614 return "gbp-acl:[%d]" % (self.acl_index)
616 def query_vpp_config(self):
617 cs = self._test.vapi.acl_dump()
619 if c.acl_index == self.acl_index:
624 class TestGBP(VppTestCase):
625 """ GBP Test Case """
628 def config_flags(self):
629 return VppEnum.vl_api_nat_config_flags_t
633 super(TestGBP, cls).setUpClass()
636 def tearDownClass(cls):
637 super(TestGBP, cls).tearDownClass()
640 super(TestGBP, self).setUp()
642 self.create_pg_interfaces(range(9))
643 self.create_loopback_interfaces(8)
645 self.router_mac = MACAddress("00:11:22:33:44:55")
647 for i in self.pg_interfaces:
649 for i in self.lo_interfaces:
652 self.vlan_100 = VppDot1QSubint(self, self.pg0, 100)
653 self.vlan_100.admin_up()
654 self.vlan_101 = VppDot1QSubint(self, self.pg0, 101)
655 self.vlan_101.admin_up()
656 self.vlan_102 = VppDot1QSubint(self, self.pg0, 102)
657 self.vlan_102.admin_up()
660 for i in self.pg_interfaces:
662 super(TestGBP, self).tearDown()
663 for i in self.lo_interfaces:
664 i.remove_vpp_config()
665 self.lo_interfaces = []
666 self.vlan_102.remove_vpp_config()
667 self.vlan_101.remove_vpp_config()
668 self.vlan_100.remove_vpp_config()
670 def send_and_expect_bridged(self, src, tx, dst):
671 rx = self.send_and_expect(src, tx, dst)
674 self.assertEqual(r[Ether].src, tx[0][Ether].src)
675 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
676 self.assertEqual(r[IP].src, tx[0][IP].src)
677 self.assertEqual(r[IP].dst, tx[0][IP].dst)
680 def send_and_expect_bridged6(self, src, tx, dst):
681 rx = self.send_and_expect(src, tx, dst)
684 self.assertEqual(r[Ether].src, tx[0][Ether].src)
685 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
686 self.assertEqual(r[IPv6].src, tx[0][IPv6].src)
687 self.assertEqual(r[IPv6].dst, tx[0][IPv6].dst)
690 def send_and_expect_routed(self, src, tx, dst, src_mac):
691 rx = self.send_and_expect(src, tx, dst)
694 self.assertEqual(r[Ether].src, src_mac)
695 self.assertEqual(r[Ether].dst, dst.remote_mac)
696 self.assertEqual(r[IP].src, tx[0][IP].src)
697 self.assertEqual(r[IP].dst, tx[0][IP].dst)
700 def send_and_expect_routed6(self, src, tx, dst, src_mac):
701 rx = self.send_and_expect(src, tx, dst)
704 self.assertEqual(r[Ether].src, src_mac)
705 self.assertEqual(r[Ether].dst, dst.remote_mac)
706 self.assertEqual(r[IPv6].src, tx[0][IPv6].src)
707 self.assertEqual(r[IPv6].dst, tx[0][IPv6].dst)
710 def send_and_expect_natted(self, src, tx, dst, src_ip):
711 rx = self.send_and_expect(src, tx, dst)
714 self.assertEqual(r[Ether].src, tx[0][Ether].src)
715 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
716 self.assertEqual(r[IP].src, src_ip)
717 self.assertEqual(r[IP].dst, tx[0][IP].dst)
720 def send_and_expect_natted6(self, src, tx, dst, src_ip):
721 rx = self.send_and_expect(src, tx, dst)
724 self.assertEqual(r[Ether].src, tx[0][Ether].src)
725 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
726 self.assertEqual(r[IPv6].src, src_ip)
727 self.assertEqual(r[IPv6].dst, tx[0][IPv6].dst)
730 def send_and_expect_unnatted(self, src, tx, dst, dst_ip):
731 rx = self.send_and_expect(src, tx, dst)
734 self.assertEqual(r[Ether].src, tx[0][Ether].src)
735 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
736 self.assertEqual(r[IP].dst, dst_ip)
737 self.assertEqual(r[IP].src, tx[0][IP].src)
740 def send_and_expect_unnatted6(self, src, tx, dst, dst_ip):
741 rx = self.send_and_expect(src, tx, dst)
744 self.assertEqual(r[Ether].src, tx[0][Ether].src)
745 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
746 self.assertEqual(r[IPv6].dst, dst_ip)
747 self.assertEqual(r[IPv6].src, tx[0][IPv6].src)
750 def send_and_expect_double_natted(self, src, tx, dst, src_ip, dst_ip):
751 rx = self.send_and_expect(src, tx, dst)
754 self.assertEqual(r[Ether].src, str(self.router_mac))
755 self.assertEqual(r[Ether].dst, dst.remote_mac)
756 self.assertEqual(r[IP].dst, dst_ip)
757 self.assertEqual(r[IP].src, src_ip)
760 def send_and_expect_double_natted6(self, src, tx, dst, src_ip, dst_ip):
761 rx = self.send_and_expect(src, tx, dst)
764 self.assertEqual(r[Ether].src, str(self.router_mac))
765 self.assertEqual(r[Ether].dst, dst.remote_mac)
766 self.assertEqual(r[IPv6].dst, dst_ip)
767 self.assertEqual(r[IPv6].src, src_ip)
770 def send_and_expect_no_arp(self, src, tx, dst):
771 self.pg_send(src, tx)
772 dst.get_capture(0, timeout=1)
773 dst.assert_nothing_captured(remark="")
776 def send_and_expect_arp(self, src, tx, dst):
777 rx = self.send_and_expect(src, tx, dst)
780 self.assertEqual(r[Ether].src, tx[0][Ether].src)
781 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
782 self.assertEqual(r[ARP].psrc, tx[0][ARP].psrc)
783 self.assertEqual(r[ARP].pdst, tx[0][ARP].pdst)
784 self.assertEqual(r[ARP].hwsrc, tx[0][ARP].hwsrc)
785 self.assertEqual(r[ARP].hwdst, tx[0][ARP].hwdst)
789 """ Group Based Policy """
791 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
796 gt4 = VppIpTable(self, 0)
798 gt6 = VppIpTable(self, 0, is_ip6=True)
800 nt4 = VppIpTable(self, 20)
802 nt6 = VppIpTable(self, 20, is_ip6=True)
805 rd0 = VppGbpRouteDomain(self, 0, 400, gt4, gt6, None, None)
806 rd20 = VppGbpRouteDomain(self, 20, 420, nt4, nt6, None, None)
809 rd20.add_vpp_config()
814 bd1 = VppBridgeDomain(self, 1)
815 bd2 = VppBridgeDomain(self, 2)
816 bd20 = VppBridgeDomain(self, 20)
820 bd20.add_vpp_config()
822 gbd1 = VppGbpBridgeDomain(self, bd1, rd0, self.loop0)
823 gbd2 = VppGbpBridgeDomain(self, bd2, rd0, self.loop1)
824 gbd20 = VppGbpBridgeDomain(self, bd20, rd20, self.loop2)
826 gbd1.add_vpp_config()
827 gbd2.add_vpp_config()
828 gbd20.add_vpp_config()
831 # 3 EPGs, 2 of which share a BD.
832 # 2 NAT EPGs, one for floating-IP subnets, the other for internet
834 epgs = [VppGbpEndpointGroup(self, 220, 1220, rd0, gbd1,
835 self.pg4, self.loop0,
836 "10.0.0.128", "2001:10::128"),
837 VppGbpEndpointGroup(self, 221, 1221, rd0, gbd1,
838 self.pg5, self.loop0,
839 "10.0.1.128", "2001:10:1::128"),
840 VppGbpEndpointGroup(self, 222, 1222, rd0, gbd2,
841 self.pg6, self.loop1,
842 "10.0.2.128", "2001:10:2::128"),
843 VppGbpEndpointGroup(self, 333, 1333, rd20, gbd20,
844 self.pg7, self.loop2,
845 "11.0.0.128", "3001::128"),
846 VppGbpEndpointGroup(self, 444, 1444, rd20, gbd20,
847 self.pg8, self.loop2,
848 "11.0.0.129", "3001::129")]
849 recircs = [VppGbpRecirc(self, epgs[0], self.loop3),
850 VppGbpRecirc(self, epgs[1], self.loop4),
851 VppGbpRecirc(self, epgs[2], self.loop5),
852 VppGbpRecirc(self, epgs[3], self.loop6, is_ext=True),
853 VppGbpRecirc(self, epgs[4], self.loop7, is_ext=True)]
856 recirc_nat = recircs[3]
859 # 4 end-points, 2 in the same subnet, 3 in the same BD
861 eps = [VppGbpEndpoint(self, self.pg0,
863 "10.0.0.1", "11.0.0.1",
864 "2001:10::1", "3001::1"),
865 VppGbpEndpoint(self, self.pg1,
867 "10.0.0.2", "11.0.0.2",
868 "2001:10::2", "3001::2"),
869 VppGbpEndpoint(self, self.pg2,
871 "10.0.1.1", "11.0.0.3",
872 "2001:10:1::1", "3001::3"),
873 VppGbpEndpoint(self, self.pg3,
875 "10.0.2.1", "11.0.0.4",
876 "2001:10:2::1", "3001::4")]
879 # Config related to each of the EPGs
882 # IP config on the BVI interfaces
883 if epg != epgs[1] and epg != epgs[4]:
884 VppIpInterfaceBind(self, epg.bvi, epg.rd.t4).add_vpp_config()
885 VppIpInterfaceBind(self, epg.bvi, epg.rd.t6).add_vpp_config()
886 epg.bvi.set_mac(self.router_mac)
888 # The BVIs are NAT inside interfaces
889 flags = self.config_flags.NAT_IS_INSIDE
890 self.vapi.nat44_interface_add_del_feature(
891 sw_if_index=epg.bvi.sw_if_index,
892 flags=flags, is_add=1)
893 self.vapi.nat66_add_del_interface(
894 is_add=1, flags=flags,
895 sw_if_index=epg.bvi.sw_if_index)
897 if_ip4 = VppIpInterfaceAddress(self, epg.bvi, epg.bvi_ip4, 32)
898 if_ip6 = VppIpInterfaceAddress(self, epg.bvi, epg.bvi_ip6, 128)
899 if_ip4.add_vpp_config()
900 if_ip6.add_vpp_config()
902 # EPG uplink interfaces in the RD
903 VppIpInterfaceBind(self, epg.uplink, epg.rd.t4).add_vpp_config()
904 VppIpInterfaceBind(self, epg.uplink, epg.rd.t6).add_vpp_config()
906 # add the BD ARP termination entry for BVI IP
907 epg.bd_arp_ip4 = VppBridgeDomainArpEntry(self, epg.bd.bd,
908 str(self.router_mac),
910 epg.bd_arp_ip6 = VppBridgeDomainArpEntry(self, epg.bd.bd,
911 str(self.router_mac),
913 epg.bd_arp_ip4.add_vpp_config()
914 epg.bd_arp_ip6.add_vpp_config()
919 for recirc in recircs:
920 # EPG's ingress recirculation interface maps to its RD
921 VppIpInterfaceBind(self, recirc.recirc,
922 recirc.epg.rd.t4).add_vpp_config()
923 VppIpInterfaceBind(self, recirc.recirc,
924 recirc.epg.rd.t6).add_vpp_config()
926 self.vapi.nat44_interface_add_del_feature(
927 sw_if_index=recirc.recirc.sw_if_index, is_add=1)
928 self.vapi.nat66_add_del_interface(
930 sw_if_index=recirc.recirc.sw_if_index)
932 recirc.add_vpp_config()
934 for recirc in recircs:
935 self.assertTrue(find_bridge_domain_port(self,
936 recirc.epg.bd.bd.bd_id,
937 recirc.recirc.sw_if_index))
940 self.pg_enable_capture(self.pg_interfaces)
943 # routes to the endpoints. We need these since there are no
944 # adj-fibs due to the fact the the BVI address has /32 and
945 # the subnet is not attached.
947 for (ip, fip) in zip(ep.ips, ep.fips):
948 # Add static mappings for each EP from the 10/8 to 11/8 network
949 if ip_address(ip).version == 4:
950 flags = self.config_flags.NAT_IS_ADDR_ONLY
951 self.vapi.nat44_add_del_static_mapping(
954 external_ip_address=fip,
955 external_sw_if_index=0xFFFFFFFF,
959 self.vapi.nat66_add_del_static_mapping(
961 external_ip_address=fip,
967 self.logger.info(self.vapi.cli("sh gbp endpoint"))
969 # ... results in a Gratuitous ARP/ND on the EPG's uplink
970 rx = ep.epg.uplink.get_capture(len(ep.ips), timeout=0.2)
972 for ii, ip in enumerate(ep.ips):
975 if ip_address(ip).version == 6:
976 self.assertTrue(p.haslayer(ICMPv6ND_NA))
977 self.assertEqual(p[ICMPv6ND_NA].tgt, ip)
979 self.assertTrue(p.haslayer(ARP))
980 self.assertEqual(p[ARP].psrc, ip)
981 self.assertEqual(p[ARP].pdst, ip)
983 # add the BD ARP termination entry for floating IP
985 ba = VppBridgeDomainArpEntry(self, epg_nat.bd.bd, ep.mac,
989 # floating IPs route via EPG recirc
991 self, fip, ip_address(fip).max_prefixlen,
993 ep.recirc.recirc.sw_if_index,
994 type=FibPathType.FIB_PATH_TYPE_DVR,
995 proto=get_dpo_proto(fip))],
999 # L2 FIB entries in the NAT EPG BD to bridge the packets from
1000 # the outside direct to the internal EPG
1001 lf = VppL2FibEntry(self, epg_nat.bd.bd, ep.mac,
1002 ep.recirc.recirc, bvi_mac=0)
1006 # ARP packets for unknown IP are sent to the EPG uplink
1008 pkt_arp = (Ether(dst="ff:ff:ff:ff:ff:ff",
1009 src=self.pg0.remote_mac) /
1011 hwdst="ff:ff:ff:ff:ff:ff",
1012 hwsrc=self.pg0.remote_mac,
1016 self.vapi.cli("clear trace")
1017 self.pg0.add_stream(pkt_arp)
1019 self.pg_enable_capture(self.pg_interfaces)
1022 rxd = epgs[0].uplink.get_capture(1)
1025 # ARP/ND packets get a response
1027 pkt_arp = (Ether(dst="ff:ff:ff:ff:ff:ff",
1028 src=self.pg0.remote_mac) /
1030 hwdst="ff:ff:ff:ff:ff:ff",
1031 hwsrc=self.pg0.remote_mac,
1032 pdst=epgs[0].bvi_ip4,
1035 self.send_and_expect(self.pg0, [pkt_arp], self.pg0)
1037 nsma = in6_getnsma(inet_pton(AF_INET6, eps[0].ip6))
1038 d = inet_ntop(AF_INET6, nsma)
1039 pkt_nd = (Ether(dst=in6_getnsmac(nsma),
1040 src=self.pg0.remote_mac) /
1041 IPv6(dst=d, src=eps[0].ip6) /
1042 ICMPv6ND_NS(tgt=epgs[0].bvi_ip6) /
1043 ICMPv6NDOptSrcLLAddr(lladdr=self.pg0.remote_mac))
1044 self.send_and_expect(self.pg0, [pkt_nd], self.pg0)
1047 # broadcast packets are flooded
1049 pkt_bcast = (Ether(dst="ff:ff:ff:ff:ff:ff",
1050 src=self.pg0.remote_mac) /
1051 IP(src=eps[0].ip4, dst="232.1.1.1") /
1052 UDP(sport=1234, dport=1234) /
1055 self.vapi.cli("clear trace")
1056 self.pg0.add_stream(pkt_bcast)
1058 self.pg_enable_capture(self.pg_interfaces)
1061 rxd = eps[1].itf.get_capture(1)
1062 self.assertEqual(rxd[0][Ether].dst, pkt_bcast[Ether].dst)
1063 rxd = epgs[0].uplink.get_capture(1)
1064 self.assertEqual(rxd[0][Ether].dst, pkt_bcast[Ether].dst)
1067 # packets to non-local L3 destinations dropped
1069 pkt_intra_epg_220_ip4 = (Ether(src=self.pg0.remote_mac,
1070 dst=str(self.router_mac)) /
1073 UDP(sport=1234, dport=1234) /
1075 pkt_inter_epg_222_ip4 = (Ether(src=self.pg0.remote_mac,
1076 dst=str(self.router_mac)) /
1079 UDP(sport=1234, dport=1234) /
1082 self.send_and_assert_no_replies(self.pg0,
1083 pkt_intra_epg_220_ip4 * NUM_PKTS)
1085 pkt_inter_epg_222_ip6 = (Ether(src=self.pg0.remote_mac,
1086 dst=str(self.router_mac)) /
1087 IPv6(src=eps[0].ip6,
1088 dst="2001:10::99") /
1089 UDP(sport=1234, dport=1234) /
1091 self.send_and_assert_no_replies(self.pg0,
1092 pkt_inter_epg_222_ip6 * NUM_PKTS)
1095 # Add the subnet routes
1098 self, rd0, "10.0.0.0", 24,
1099 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1101 self, rd0, "10.0.1.0", 24,
1102 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1104 self, rd0, "10.0.2.0", 24,
1105 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1107 self, rd0, "2001:10::1", 64,
1108 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1110 self, rd0, "2001:10:1::1", 64,
1111 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1113 self, rd0, "2001:10:2::1", 64,
1114 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1115 s41.add_vpp_config()
1116 s42.add_vpp_config()
1117 s43.add_vpp_config()
1118 s61.add_vpp_config()
1119 s62.add_vpp_config()
1120 s63.add_vpp_config()
1122 self.send_and_expect_bridged(eps[0].itf,
1123 pkt_intra_epg_220_ip4 * NUM_PKTS,
1125 self.send_and_expect_bridged(eps[0].itf,
1126 pkt_inter_epg_222_ip4 * NUM_PKTS,
1128 self.send_and_expect_bridged6(eps[0].itf,
1129 pkt_inter_epg_222_ip6 * NUM_PKTS,
1132 self.logger.info(self.vapi.cli("sh ip fib 11.0.0.2"))
1133 self.logger.info(self.vapi.cli("sh gbp endpoint-group"))
1134 self.logger.info(self.vapi.cli("sh gbp endpoint"))
1135 self.logger.info(self.vapi.cli("sh gbp recirc"))
1136 self.logger.info(self.vapi.cli("sh int"))
1137 self.logger.info(self.vapi.cli("sh int addr"))
1138 self.logger.info(self.vapi.cli("sh int feat loop6"))
1139 self.logger.info(self.vapi.cli("sh vlib graph ip4-gbp-src-classify"))
1140 self.logger.info(self.vapi.cli("sh int feat loop3"))
1141 self.logger.info(self.vapi.cli("sh int feat pg0"))
1144 # Packet destined to unknown unicast is sent on the epg uplink ...
1146 pkt_intra_epg_220_to_uplink = (Ether(src=self.pg0.remote_mac,
1147 dst="00:00:00:33:44:55") /
1150 UDP(sport=1234, dport=1234) /
1153 self.send_and_expect_bridged(eps[0].itf,
1154 pkt_intra_epg_220_to_uplink * NUM_PKTS,
1156 # ... and nowhere else
1157 self.pg1.get_capture(0, timeout=0.1)
1158 self.pg1.assert_nothing_captured(remark="Flood onto other VMS")
1160 pkt_intra_epg_221_to_uplink = (Ether(src=self.pg2.remote_mac,
1161 dst="00:00:00:33:44:66") /
1164 UDP(sport=1234, dport=1234) /
1167 self.send_and_expect_bridged(eps[2].itf,
1168 pkt_intra_epg_221_to_uplink * NUM_PKTS,
1172 # Packets from the uplink are forwarded in the absence of a contract
1174 pkt_intra_epg_220_from_uplink = (Ether(src="00:00:00:33:44:55",
1175 dst=self.pg0.remote_mac) /
1178 UDP(sport=1234, dport=1234) /
1181 self.send_and_expect_bridged(self.pg4,
1182 pkt_intra_epg_220_from_uplink * NUM_PKTS,
1186 # in the absence of policy, endpoints in the same EPG
1189 pkt_intra_epg = (Ether(src=self.pg0.remote_mac,
1190 dst=self.pg1.remote_mac) /
1193 UDP(sport=1234, dport=1234) /
1196 self.send_and_expect_bridged(self.pg0,
1197 pkt_intra_epg * NUM_PKTS,
1201 # in the absence of policy, endpoints in the different EPG
1202 # cannot communicate
1204 pkt_inter_epg_220_to_221 = (Ether(src=self.pg0.remote_mac,
1205 dst=self.pg2.remote_mac) /
1208 UDP(sport=1234, dport=1234) /
1210 pkt_inter_epg_221_to_220 = (Ether(src=self.pg2.remote_mac,
1211 dst=self.pg0.remote_mac) /
1214 UDP(sport=1234, dport=1234) /
1216 pkt_inter_epg_220_to_222 = (Ether(src=self.pg0.remote_mac,
1217 dst=str(self.router_mac)) /
1220 UDP(sport=1234, dport=1234) /
1223 self.send_and_assert_no_replies(eps[0].itf,
1224 pkt_inter_epg_220_to_221 * NUM_PKTS)
1225 self.send_and_assert_no_replies(eps[0].itf,
1226 pkt_inter_epg_220_to_222 * NUM_PKTS)
1229 # A uni-directional contract from EPG 220 -> 221
1231 acl = VppGbpAcl(self)
1232 rule = acl.create_rule(permit_deny=1, proto=17)
1233 rule2 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
1234 acl_index = acl.add_vpp_config([rule, rule2])
1235 c1 = VppGbpContract(
1236 self, 400, epgs[0].sclass, epgs[1].sclass, acl_index,
1237 [VppGbpContractRule(
1238 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1239 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1242 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1243 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1245 [ETH_P_IP, ETH_P_IPV6])
1248 self.send_and_expect_bridged(eps[0].itf,
1249 pkt_inter_epg_220_to_221 * NUM_PKTS,
1251 self.send_and_assert_no_replies(eps[0].itf,
1252 pkt_inter_epg_220_to_222 * NUM_PKTS)
1255 # contract for the return direction
1257 c2 = VppGbpContract(
1258 self, 400, epgs[1].sclass, epgs[0].sclass, acl_index,
1259 [VppGbpContractRule(
1260 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1261 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1264 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1265 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1267 [ETH_P_IP, ETH_P_IPV6])
1270 self.send_and_expect_bridged(eps[0].itf,
1271 pkt_inter_epg_220_to_221 * NUM_PKTS,
1273 self.send_and_expect_bridged(eps[2].itf,
1274 pkt_inter_epg_221_to_220 * NUM_PKTS,
1277 ds = c2.get_drop_stats()
1278 self.assertEqual(ds['packets'], 0)
1279 ps = c2.get_permit_stats()
1280 self.assertEqual(ps['packets'], NUM_PKTS)
1283 # the contract does not allow non-IP
1285 pkt_non_ip_inter_epg_220_to_221 = (Ether(src=self.pg0.remote_mac,
1286 dst=self.pg2.remote_mac) /
1288 self.send_and_assert_no_replies(eps[0].itf,
1289 pkt_non_ip_inter_epg_220_to_221 * 17)
1292 # check that inter group is still disabled for the groups
1293 # not in the contract.
1295 self.send_and_assert_no_replies(eps[0].itf,
1296 pkt_inter_epg_220_to_222 * NUM_PKTS)
1299 # A uni-directional contract from EPG 220 -> 222 'L3 routed'
1301 c3 = VppGbpContract(
1302 self, 400, epgs[0].sclass, epgs[2].sclass, acl_index,
1303 [VppGbpContractRule(
1304 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1305 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1308 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1309 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1311 [ETH_P_IP, ETH_P_IPV6])
1314 self.logger.info(self.vapi.cli("sh gbp contract"))
1316 self.send_and_expect_routed(eps[0].itf,
1317 pkt_inter_epg_220_to_222 * NUM_PKTS,
1319 str(self.router_mac))
1322 # remove both contracts, traffic stops in both directions
1324 c2.remove_vpp_config()
1325 c1.remove_vpp_config()
1326 c3.remove_vpp_config()
1327 acl.remove_vpp_config()
1329 self.send_and_assert_no_replies(eps[2].itf,
1330 pkt_inter_epg_221_to_220 * NUM_PKTS)
1331 self.send_and_assert_no_replies(eps[0].itf,
1332 pkt_inter_epg_220_to_221 * NUM_PKTS)
1333 self.send_and_expect_bridged(eps[0].itf,
1334 pkt_intra_epg * NUM_PKTS,
1338 # EPs to the outside world
1341 # in the EP's RD an external subnet via the NAT EPG's recirc
1343 self, rd0, "0.0.0.0", 0,
1344 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1345 sw_if_index=recirc_nat.recirc.sw_if_index,
1346 sclass=epg_nat.sclass)
1348 self, rd0, "11.0.0.0", 8,
1349 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1350 sw_if_index=recirc_nat.recirc.sw_if_index,
1351 sclass=epg_nat.sclass)
1352 se16 = VppGbpSubnet(
1354 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1355 sw_if_index=recirc_nat.recirc.sw_if_index,
1356 sclass=epg_nat.sclass)
1357 # in the NAT RD an external subnet via the NAT EPG's uplink
1359 self, rd20, "0.0.0.0", 0,
1360 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1361 sw_if_index=epg_nat.uplink.sw_if_index,
1362 sclass=epg_nat.sclass)
1363 se36 = VppGbpSubnet(
1364 self, rd20, "::", 0,
1365 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1366 sw_if_index=epg_nat.uplink.sw_if_index,
1367 sclass=epg_nat.sclass)
1369 self, rd20, "11.0.0.0", 8,
1370 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1371 sw_if_index=epg_nat.uplink.sw_if_index,
1372 sclass=epg_nat.sclass)
1373 se1.add_vpp_config()
1374 se2.add_vpp_config()
1375 se16.add_vpp_config()
1376 se3.add_vpp_config()
1377 se36.add_vpp_config()
1378 se4.add_vpp_config()
1380 self.logger.info(self.vapi.cli("sh ip fib 0.0.0.0/0"))
1381 self.logger.info(self.vapi.cli("sh ip fib 11.0.0.1"))
1382 self.logger.info(self.vapi.cli("sh ip6 fib ::/0"))
1383 self.logger.info(self.vapi.cli("sh ip6 fib %s" %
1387 # From an EP to an outside address: IN2OUT
1389 pkt_inter_epg_220_to_global = (Ether(src=self.pg0.remote_mac,
1390 dst=str(self.router_mac)) /
1393 UDP(sport=1234, dport=1234) /
1397 self.send_and_assert_no_replies(eps[0].itf,
1398 pkt_inter_epg_220_to_global * NUM_PKTS)
1400 acl2 = VppGbpAcl(self)
1401 rule = acl2.create_rule(permit_deny=1, proto=17, sport_from=1234,
1402 sport_to=1234, dport_from=1234, dport_to=1234)
1403 rule2 = acl2.create_rule(is_ipv6=1, permit_deny=1, proto=17,
1404 sport_from=1234, sport_to=1234,
1405 dport_from=1234, dport_to=1234)
1407 acl_index2 = acl2.add_vpp_config([rule, rule2])
1408 c4 = VppGbpContract(
1409 self, 400, epgs[0].sclass, epgs[3].sclass, acl_index2,
1410 [VppGbpContractRule(
1411 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1412 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1415 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1416 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1418 [ETH_P_IP, ETH_P_IPV6])
1421 self.send_and_expect_natted(eps[0].itf,
1422 pkt_inter_epg_220_to_global * NUM_PKTS,
1426 pkt_inter_epg_220_to_global = (Ether(src=self.pg0.remote_mac,
1427 dst=str(self.router_mac)) /
1428 IPv6(src=eps[0].ip6,
1430 UDP(sport=1234, dport=1234) /
1433 self.send_and_expect_natted6(self.pg0,
1434 pkt_inter_epg_220_to_global * NUM_PKTS,
1439 # From a global address to an EP: OUT2IN
1441 pkt_inter_epg_220_from_global = (Ether(src=str(self.router_mac),
1442 dst=self.pg0.remote_mac) /
1445 UDP(sport=1234, dport=1234) /
1448 self.send_and_assert_no_replies(
1449 self.pg7, pkt_inter_epg_220_from_global * NUM_PKTS)
1451 c5 = VppGbpContract(
1452 self, 400, epgs[3].sclass, epgs[0].sclass, acl_index2,
1453 [VppGbpContractRule(
1454 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1455 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1458 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1459 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1461 [ETH_P_IP, ETH_P_IPV6])
1464 self.send_and_expect_unnatted(self.pg7,
1465 pkt_inter_epg_220_from_global * NUM_PKTS,
1469 pkt_inter_epg_220_from_global = (Ether(src=str(self.router_mac),
1470 dst=self.pg0.remote_mac) /
1471 IPv6(dst=eps[0].fip6,
1473 UDP(sport=1234, dport=1234) /
1476 self.send_and_expect_unnatted6(
1478 pkt_inter_epg_220_from_global * NUM_PKTS,
1483 # From a local VM to another local VM using resp. public addresses:
1486 pkt_intra_epg_220_global = (Ether(src=self.pg0.remote_mac,
1487 dst=str(self.router_mac)) /
1490 UDP(sport=1234, dport=1234) /
1493 self.send_and_expect_double_natted(eps[0].itf,
1494 pkt_intra_epg_220_global * NUM_PKTS,
1499 pkt_intra_epg_220_global = (Ether(src=self.pg0.remote_mac,
1500 dst=str(self.router_mac)) /
1501 IPv6(src=eps[0].ip6,
1503 UDP(sport=1234, dport=1234) /
1506 self.send_and_expect_double_natted6(
1508 pkt_intra_epg_220_global * NUM_PKTS,
1517 # del static mappings for each EP from the 10/8 to 11/8 network
1518 flags = self.config_flags.NAT_IS_ADDR_ONLY
1519 self.vapi.nat44_add_del_static_mapping(
1521 local_ip_address=ep.ip4,
1522 external_ip_address=ep.fip4,
1523 external_sw_if_index=0xFFFFFFFF,
1526 self.vapi.nat66_add_del_static_mapping(
1527 local_ip_address=ep.ip6,
1528 external_ip_address=ep.fip6,
1532 # IP config on the BVI interfaces
1533 if epg != epgs[0] and epg != epgs[3]:
1534 flags = self.config_flags.NAT_IS_INSIDE
1535 self.vapi.nat44_interface_add_del_feature(
1536 sw_if_index=epg.bvi.sw_if_index,
1539 self.vapi.nat66_add_del_interface(
1540 is_add=0, flags=flags,
1541 sw_if_index=epg.bvi.sw_if_index)
1543 for recirc in recircs:
1544 self.vapi.nat44_interface_add_del_feature(
1545 sw_if_index=recirc.recirc.sw_if_index,
1547 self.vapi.nat66_add_del_interface(
1549 sw_if_index=recirc.recirc.sw_if_index)
1551 def wait_for_ep_timeout(self, sw_if_index=None, ip=None, mac=None,
1552 tep=None, n_tries=100, s_time=1):
1554 if not find_gbp_endpoint(self, sw_if_index, ip, mac, tep=tep):
1556 n_tries = n_tries - 1
1558 self.assertFalse(find_gbp_endpoint(self, sw_if_index, ip, mac))
1561 def test_gbp_learn_l2(self):
1562 """ GBP L2 Endpoint Learning """
1564 drop_no_contract = self.statistics.get_err_counter(
1565 '/err/gbp-policy-port/drop-no-contract')
1566 allow_intra_class = self.statistics.get_err_counter(
1567 '/err/gbp-policy-port/allow-intra-sclass')
1569 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
1570 learnt = [{'mac': '00:00:11:11:11:01',
1572 'ip6': '2001:10::2'},
1573 {'mac': '00:00:11:11:11:02',
1575 'ip6': '2001:10::3'}]
1580 gt4 = VppIpTable(self, 1)
1581 gt4.add_vpp_config()
1582 gt6 = VppIpTable(self, 1, is_ip6=True)
1583 gt6.add_vpp_config()
1585 rd1 = VppGbpRouteDomain(self, 1, 401, gt4, gt6)
1586 rd1.add_vpp_config()
1589 # Pg2 hosts the vxlan tunnel, hosts on pg2 to act as TEPs
1590 # Pg3 hosts the IP4 UU-flood VXLAN tunnel
1591 # Pg4 hosts the IP6 UU-flood VXLAN tunnel
1593 self.pg2.config_ip4()
1594 self.pg2.resolve_arp()
1595 self.pg2.generate_remote_hosts(4)
1596 self.pg2.configure_ipv4_neighbors()
1597 self.pg3.config_ip4()
1598 self.pg3.resolve_arp()
1599 self.pg4.config_ip4()
1600 self.pg4.resolve_arp()
1603 # Add a mcast destination VXLAN-GBP tunnel for B&M traffic
1605 tun_bm = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
1608 tun_bm.add_vpp_config()
1611 # a GBP bridge domain with a BVI and a UU-flood interface
1613 bd1 = VppBridgeDomain(self, 1)
1614 bd1.add_vpp_config()
1615 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0,
1617 gbd1.add_vpp_config()
1619 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1620 self.logger.info(self.vapi.cli("sh gbp bridge"))
1622 # ... and has a /32 applied
1623 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
1624 ip_addr.add_vpp_config()
1627 # The Endpoint-group in which we are learning endpoints
1629 epg_220 = VppGbpEndpointGroup(self, 220, 112, rd1, gbd1,
1633 VppGbpEndpointRetention(2))
1634 epg_220.add_vpp_config()
1635 epg_330 = VppGbpEndpointGroup(self, 330, 113, rd1, gbd1,
1639 VppGbpEndpointRetention(2))
1640 epg_330.add_vpp_config()
1643 # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
1646 vx_tun_l2_1 = VppGbpVxlanTunnel(
1647 self, 99, bd1.bd_id,
1648 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L2,
1650 vx_tun_l2_1.add_vpp_config()
1653 # A static endpoint that the learnt endpoints are trying to
1656 ep = VppGbpEndpoint(self, self.pg0,
1658 "10.0.0.127", "11.0.0.127",
1659 "2001:10::1", "3001::1")
1662 self.assertTrue(find_route(self, ep.ip4, 32, table_id=1))
1664 # a packet with an sclass from an unknown EPG
1665 p = (Ether(src=self.pg2.remote_mac,
1666 dst=self.pg2.local_mac) /
1667 IP(src=self.pg2.remote_hosts[0].ip4,
1668 dst=self.pg2.local_ip4) /
1669 UDP(sport=1234, dport=48879) /
1670 VXLAN(vni=99, gpid=88, flags=0x88) /
1671 Ether(src=learnt[0]["mac"], dst=ep.mac) /
1672 IP(src=learnt[0]["ip"], dst=ep.ip4) /
1673 UDP(sport=1234, dport=1234) /
1676 self.send_and_assert_no_replies(self.pg2, p)
1678 self.logger.info(self.vapi.cli("sh error"))
1679 self.assert_error_counter_equal(
1680 '/err/gbp-policy-port/drop-no-contract',
1681 drop_no_contract + 1)
1684 # we should not have learnt a new tunnel endpoint, since
1685 # the EPG was not learnt.
1687 self.assertEqual(INDEX_INVALID,
1688 find_vxlan_gbp_tunnel(self,
1690 self.pg2.remote_hosts[0].ip4,
1693 # ep is not learnt, because the EPG is unknown
1694 self.assertEqual(len(self.vapi.gbp_endpoint_dump()), 1)
1697 # Learn new EPs from IP packets
1699 for ii, l in enumerate(learnt):
1700 # a packet with an sclass from a known EPG
1701 # arriving on an unknown TEP
1702 p = (Ether(src=self.pg2.remote_mac,
1703 dst=self.pg2.local_mac) /
1704 IP(src=self.pg2.remote_hosts[1].ip4,
1705 dst=self.pg2.local_ip4) /
1706 UDP(sport=1234, dport=48879) /
1707 VXLAN(vni=99, gpid=112, flags=0x88) /
1708 Ether(src=l['mac'], dst=ep.mac) /
1709 IP(src=l['ip'], dst=ep.ip4) /
1710 UDP(sport=1234, dport=1234) /
1713 rx = self.send_and_expect(self.pg2, [p], self.pg0)
1716 tep1_sw_if_index = find_vxlan_gbp_tunnel(
1719 self.pg2.remote_hosts[1].ip4,
1721 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
1724 # the EP is learnt via the learnt TEP
1725 # both from its MAC and its IP
1727 self.assertTrue(find_gbp_endpoint(self,
1728 vx_tun_l2_1.sw_if_index,
1730 self.assertTrue(find_gbp_endpoint(self,
1731 vx_tun_l2_1.sw_if_index,
1734 self.assert_error_counter_equal(
1735 '/err/gbp-policy-port/allow-intra-sclass',
1736 allow_intra_class + 2)
1738 self.logger.info(self.vapi.cli("show gbp endpoint"))
1739 self.logger.info(self.vapi.cli("show gbp vxlan"))
1740 self.logger.info(self.vapi.cli("show ip mfib"))
1743 # If we sleep for the threshold time, the learnt endpoints should
1747 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1751 # Learn new EPs from GARP packets received on the BD's mcast tunnel
1753 for ii, l in enumerate(learnt):
1754 # add some junk in the reserved field of the vxlan-header
1755 # next to the VNI. we should accept since reserved bits are
1757 p = (Ether(src=self.pg2.remote_mac,
1758 dst=self.pg2.local_mac) /
1759 IP(src=self.pg2.remote_hosts[1].ip4,
1761 UDP(sport=1234, dport=48879) /
1762 VXLAN(vni=88, reserved2=0x80, gpid=112, flags=0x88) /
1763 Ether(src=l['mac'], dst="ff:ff:ff:ff:ff:ff") /
1765 psrc=l['ip'], pdst=l['ip'],
1766 hwsrc=l['mac'], hwdst="ff:ff:ff:ff:ff:ff"))
1768 rx = self.send_and_expect(self.pg4, [p], self.pg0)
1771 tep1_sw_if_index = find_vxlan_gbp_tunnel(
1774 self.pg2.remote_hosts[1].ip4,
1776 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
1779 # the EP is learnt via the learnt TEP
1780 # both from its MAC and its IP
1782 self.assertTrue(find_gbp_endpoint(self,
1783 vx_tun_l2_1.sw_if_index,
1785 self.assertTrue(find_gbp_endpoint(self,
1786 vx_tun_l2_1.sw_if_index,
1790 # wait for the learnt endpoints to age out
1793 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1797 # Learn new EPs from L2 packets
1799 for ii, l in enumerate(learnt):
1800 # a packet with an sclass from a known EPG
1801 # arriving on an unknown TEP
1802 p = (Ether(src=self.pg2.remote_mac,
1803 dst=self.pg2.local_mac) /
1804 IP(src=self.pg2.remote_hosts[1].ip4,
1805 dst=self.pg2.local_ip4) /
1806 UDP(sport=1234, dport=48879) /
1807 VXLAN(vni=99, gpid=112, flags=0x88) /
1808 Ether(src=l['mac'], dst=ep.mac) /
1811 rx = self.send_and_expect(self.pg2, [p], self.pg0)
1814 tep1_sw_if_index = find_vxlan_gbp_tunnel(
1817 self.pg2.remote_hosts[1].ip4,
1819 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
1822 # the EP is learnt via the learnt TEP
1823 # both from its MAC and its IP
1825 self.assertTrue(find_gbp_endpoint(self,
1826 vx_tun_l2_1.sw_if_index,
1829 self.logger.info(self.vapi.cli("show gbp endpoint"))
1830 self.logger.info(self.vapi.cli("show gbp vxlan"))
1831 self.logger.info(self.vapi.cli("show vxlan-gbp tunnel"))
1834 # wait for the learnt endpoints to age out
1837 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1841 # repeat. the do not learn bit is set so the EPs are not learnt
1844 # a packet with an sclass from a known EPG
1845 p = (Ether(src=self.pg2.remote_mac,
1846 dst=self.pg2.local_mac) /
1847 IP(src=self.pg2.remote_hosts[1].ip4,
1848 dst=self.pg2.local_ip4) /
1849 UDP(sport=1234, dport=48879) /
1850 VXLAN(vni=99, gpid=112, flags=0x88, gpflags="D") /
1851 Ether(src=l['mac'], dst=ep.mac) /
1852 IP(src=l['ip'], dst=ep.ip4) /
1853 UDP(sport=1234, dport=1234) /
1856 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
1859 self.assertFalse(find_gbp_endpoint(self,
1860 vx_tun_l2_1.sw_if_index,
1867 # a packet with an sclass from a known EPG
1868 # set a reserved bit in addition to the G and I
1869 # reserved bits should not be checked on rx.
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=112, flags=0xc8) /
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 replies to dynamics
1890 self.logger.info(self.vapi.cli("sh l2fib bd_id 1"))
1892 p = (Ether(src=ep.mac, dst=l['mac']) /
1893 IP(dst=l['ip'], src=ep.ip4) /
1894 UDP(sport=1234, dport=1234) /
1897 rxs = self.send_and_expect(self.pg0, p * 17, self.pg2)
1900 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
1901 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
1902 self.assertEqual(rx[UDP].dport, 48879)
1903 # the UDP source port is a random value for hashing
1904 self.assertEqual(rx[VXLAN].gpid, 112)
1905 self.assertEqual(rx[VXLAN].vni, 99)
1906 self.assertTrue(rx[VXLAN].flags.G)
1907 self.assertTrue(rx[VXLAN].flags.Instance)
1908 self.assertTrue(rx[VXLAN].gpflags.A)
1909 self.assertFalse(rx[VXLAN].gpflags.D)
1912 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1916 # repeat in the other EPG
1917 # there's no contract between 220 and 330, but the A-bit is set
1918 # so the packet is cleared for delivery
1921 # a packet with an sclass from a known EPG
1922 p = (Ether(src=self.pg2.remote_mac,
1923 dst=self.pg2.local_mac) /
1924 IP(src=self.pg2.remote_hosts[1].ip4,
1925 dst=self.pg2.local_ip4) /
1926 UDP(sport=1234, dport=48879) /
1927 VXLAN(vni=99, gpid=113, flags=0x88, gpflags='A') /
1928 Ether(src=l['mac'], dst=ep.mac) /
1929 IP(src=l['ip'], dst=ep.ip4) /
1930 UDP(sport=1234, dport=1234) /
1933 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
1935 self.assertTrue(find_gbp_endpoint(self,
1936 vx_tun_l2_1.sw_if_index,
1940 # static EP cannot reach the learnt EPs since there is no contract
1941 # only test 1 EP as the others could timeout
1943 p = (Ether(src=ep.mac, dst=l['mac']) /
1944 IP(dst=learnt[0]['ip'], src=ep.ip4) /
1945 UDP(sport=1234, dport=1234) /
1948 self.send_and_assert_no_replies(self.pg0, [p])
1951 # refresh the entries after the check for no replies above
1954 # a packet with an sclass from a known EPG
1955 p = (Ether(src=self.pg2.remote_mac,
1956 dst=self.pg2.local_mac) /
1957 IP(src=self.pg2.remote_hosts[1].ip4,
1958 dst=self.pg2.local_ip4) /
1959 UDP(sport=1234, dport=48879) /
1960 VXLAN(vni=99, gpid=113, flags=0x88, gpflags='A') /
1961 Ether(src=l['mac'], dst=ep.mac) /
1962 IP(src=l['ip'], dst=ep.ip4) /
1963 UDP(sport=1234, dport=1234) /
1966 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
1968 self.assertTrue(find_gbp_endpoint(self,
1969 vx_tun_l2_1.sw_if_index,
1973 # Add the contract so they can talk
1975 acl = VppGbpAcl(self)
1976 rule = acl.create_rule(permit_deny=1, proto=17)
1977 rule2 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
1978 acl_index = acl.add_vpp_config([rule, rule2])
1979 c1 = VppGbpContract(
1980 self, 401, epg_220.sclass, epg_330.sclass, acl_index,
1981 [VppGbpContractRule(
1982 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1983 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1986 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1987 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1989 [ETH_P_IP, ETH_P_IPV6])
1993 p = (Ether(src=ep.mac, dst=l['mac']) /
1994 IP(dst=l['ip'], src=ep.ip4) /
1995 UDP(sport=1234, dport=1234) /
1998 self.send_and_expect(self.pg0, [p], self.pg2)
2001 # send UU packets from the local EP
2003 self.logger.info(self.vapi.cli("sh gbp bridge"))
2004 self.logger.info(self.vapi.cli("sh bridge-domain 1 detail"))
2005 p_uu = (Ether(src=ep.mac, dst="00:11:11:11:11:11") /
2006 IP(dst="10.0.0.133", src=ep.ip4) /
2007 UDP(sport=1234, dport=1234) /
2009 rxs = self.send_and_expect(ep.itf, [p_uu], gbd1.uu_fwd)
2011 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2013 p_bm = (Ether(src=ep.mac, dst="ff:ff:ff:ff:ff:ff") /
2014 IP(dst="10.0.0.133", src=ep.ip4) /
2015 UDP(sport=1234, dport=1234) /
2017 rxs = self.send_and_expect_only(ep.itf, [p_bm], tun_bm.mcast_itf)
2020 self.assertEqual(rx[IP].src, self.pg4.local_ip4)
2021 self.assertEqual(rx[IP].dst, "239.1.1.1")
2022 self.assertEqual(rx[UDP].dport, 48879)
2023 # the UDP source port is a random value for hashing
2024 self.assertEqual(rx[VXLAN].gpid, 112)
2025 self.assertEqual(rx[VXLAN].vni, 88)
2026 self.assertTrue(rx[VXLAN].flags.G)
2027 self.assertTrue(rx[VXLAN].flags.Instance)
2028 self.assertFalse(rx[VXLAN].gpflags.A)
2029 self.assertFalse(rx[VXLAN].gpflags.D)
2031 acl = VppGbpAcl(self)
2032 rule = acl.create_rule(permit_deny=1, proto=17)
2033 rule2 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
2034 acl_index = acl.add_vpp_config([rule, rule2])
2035 c2 = VppGbpContract(
2036 self, 401, epg_330.sclass, epg_220.sclass, acl_index,
2037 [VppGbpContractRule(
2038 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2039 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2042 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2043 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2045 [ETH_P_IP, ETH_P_IPV6])
2049 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
2052 # Check v6 Endpoints learning
2055 # a packet with an sclass from a known EPG
2056 p = (Ether(src=self.pg2.remote_mac,
2057 dst=self.pg2.local_mac) /
2058 IP(src=self.pg2.remote_hosts[1].ip4,
2059 dst=self.pg2.local_ip4) /
2060 UDP(sport=1234, dport=48879) /
2061 VXLAN(vni=99, gpid=113, flags=0x88) /
2062 Ether(src=l['mac'], dst=ep.mac) /
2063 IPv6(src=l['ip6'], dst=ep.ip6) /
2064 UDP(sport=1234, dport=1234) /
2067 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
2068 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
2070 self.assertTrue(find_gbp_endpoint(
2072 vx_tun_l2_1.sw_if_index,
2074 tep=[self.pg2.local_ip4,
2075 self.pg2.remote_hosts[1].ip4]))
2077 self.logger.info(self.vapi.cli("sh int"))
2078 self.logger.info(self.vapi.cli("sh vxlan-gbp tunnel"))
2079 self.logger.info(self.vapi.cli("sh gbp vxlan"))
2080 self.logger.info(self.vapi.cli("sh gbp endpoint"))
2081 self.logger.info(self.vapi.cli("sh gbp interface"))
2084 # EP moves to a different TEP
2087 # a packet with an sclass from a known EPG
2088 p = (Ether(src=self.pg2.remote_mac,
2089 dst=self.pg2.local_mac) /
2090 IP(src=self.pg2.remote_hosts[2].ip4,
2091 dst=self.pg2.local_ip4) /
2092 UDP(sport=1234, dport=48879) /
2093 VXLAN(vni=99, gpid=113, flags=0x88) /
2094 Ether(src=l['mac'], dst=ep.mac) /
2095 IPv6(src=l['ip6'], dst=ep.ip6) /
2096 UDP(sport=1234, dport=1234) /
2099 rx = self.send_and_expect(self.pg2, p * 1, self.pg0)
2100 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
2102 self.assertTrue(find_gbp_endpoint(
2104 vx_tun_l2_1.sw_if_index,
2107 tep=[self.pg2.local_ip4,
2108 self.pg2.remote_hosts[2].ip4]))
2111 # v6 remote EP reachability
2114 p = (Ether(src=ep.mac, dst=l['mac']) /
2115 IPv6(dst=l['ip6'], src=ep.ip6) /
2116 UDP(sport=1234, dport=1234) /
2119 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
2122 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2123 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[2].ip4)
2124 self.assertEqual(rx[UDP].dport, 48879)
2125 # the UDP source port is a random value for hashing
2126 self.assertEqual(rx[VXLAN].gpid, 112)
2127 self.assertEqual(rx[VXLAN].vni, 99)
2128 self.assertTrue(rx[VXLAN].flags.G)
2129 self.assertTrue(rx[VXLAN].flags.Instance)
2130 self.assertTrue(rx[VXLAN].gpflags.A)
2131 self.assertFalse(rx[VXLAN].gpflags.D)
2132 self.assertEqual(rx[IPv6].dst, l['ip6'])
2138 # a packet with an sclass from a known EPG
2139 p = (Ether(src=self.pg2.remote_mac,
2140 dst=self.pg2.local_mac) /
2141 IP(src=self.pg2.remote_hosts[2].ip4,
2142 dst=self.pg2.local_ip4) /
2143 UDP(sport=1234, dport=48879) /
2144 VXLAN(vni=99, gpid=112, flags=0x88) /
2145 Ether(src=l['mac'], dst=ep.mac) /
2146 IPv6(src=l['ip6'], dst=ep.ip6) /
2147 UDP(sport=1234, dport=1234) /
2150 rx = self.send_and_expect(self.pg2, p * 1, self.pg0)
2151 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
2153 self.assertTrue(find_gbp_endpoint(
2155 vx_tun_l2_1.sw_if_index,
2158 tep=[self.pg2.local_ip4,
2159 self.pg2.remote_hosts[2].ip4]))
2162 # check reachability and contract intra-epg
2164 allow_intra_class = self.statistics.get_err_counter(
2165 '/err/gbp-policy-mac/allow-intra-sclass')
2168 p = (Ether(src=ep.mac, dst=l['mac']) /
2169 IPv6(dst=l['ip6'], src=ep.ip6) /
2170 UDP(sport=1234, dport=1234) /
2173 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
2176 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2177 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[2].ip4)
2178 self.assertEqual(rx[UDP].dport, 48879)
2179 self.assertEqual(rx[VXLAN].gpid, 112)
2180 self.assertEqual(rx[VXLAN].vni, 99)
2181 self.assertTrue(rx[VXLAN].flags.G)
2182 self.assertTrue(rx[VXLAN].flags.Instance)
2183 self.assertTrue(rx[VXLAN].gpflags.A)
2184 self.assertFalse(rx[VXLAN].gpflags.D)
2185 self.assertEqual(rx[IPv6].dst, l['ip6'])
2187 allow_intra_class += NUM_PKTS
2189 self.assert_error_counter_equal(
2190 '/err/gbp-policy-mac/allow-intra-sclass',
2197 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
2199 self.pg2.unconfig_ip4()
2200 self.pg3.unconfig_ip4()
2201 self.pg4.unconfig_ip4()
2203 def test_gbp_contract(self):
2204 """ GBP Contracts """
2209 gt4 = VppIpTable(self, 0)
2210 gt4.add_vpp_config()
2211 gt6 = VppIpTable(self, 0, is_ip6=True)
2212 gt6.add_vpp_config()
2214 rd0 = VppGbpRouteDomain(self, 0, 400, gt4, gt6, None, None)
2216 rd0.add_vpp_config()
2221 bd1 = VppBridgeDomain(self, 1, arp_term=0)
2222 bd2 = VppBridgeDomain(self, 2, arp_term=0)
2224 bd1.add_vpp_config()
2225 bd2.add_vpp_config()
2227 gbd1 = VppGbpBridgeDomain(self, bd1, rd0, self.loop0)
2228 gbd2 = VppGbpBridgeDomain(self, bd2, rd0, self.loop1)
2230 gbd1.add_vpp_config()
2231 gbd2.add_vpp_config()
2234 # 3 EPGs, 2 of which share a BD.
2236 epgs = [VppGbpEndpointGroup(self, 220, 1220, rd0, gbd1,
2238 "10.0.0.128", "2001:10::128"),
2239 VppGbpEndpointGroup(self, 221, 1221, rd0, gbd1,
2241 "10.0.1.128", "2001:10:1::128"),
2242 VppGbpEndpointGroup(self, 222, 1222, rd0, gbd2,
2244 "10.0.2.128", "2001:10:2::128")]
2246 # 4 end-points, 2 in the same subnet, 3 in the same BD
2248 eps = [VppGbpEndpoint(self, self.pg0,
2250 "10.0.0.1", "11.0.0.1",
2251 "2001:10::1", "3001::1"),
2252 VppGbpEndpoint(self, self.pg1,
2254 "10.0.0.2", "11.0.0.2",
2255 "2001:10::2", "3001::2"),
2256 VppGbpEndpoint(self, self.pg2,
2258 "10.0.1.1", "11.0.0.3",
2259 "2001:10:1::1", "3001::3"),
2260 VppGbpEndpoint(self, self.pg3,
2262 "10.0.2.1", "11.0.0.4",
2263 "2001:10:2::1", "3001::4")]
2266 # Config related to each of the EPGs
2269 # IP config on the BVI interfaces
2271 VppIpInterfaceBind(self, epg.bvi, epg.rd.t4).add_vpp_config()
2272 VppIpInterfaceBind(self, epg.bvi, epg.rd.t6).add_vpp_config()
2273 epg.bvi.set_mac(self.router_mac)
2275 if_ip4 = VppIpInterfaceAddress(self, epg.bvi, epg.bvi_ip4, 32)
2276 if_ip6 = VppIpInterfaceAddress(self, epg.bvi, epg.bvi_ip6, 128)
2277 if_ip4.add_vpp_config()
2278 if_ip6.add_vpp_config()
2280 # add the BD ARP termination entry for BVI IP
2281 epg.bd_arp_ip4 = VppBridgeDomainArpEntry(self, epg.bd.bd,
2282 str(self.router_mac),
2284 epg.bd_arp_ip4.add_vpp_config()
2287 epg.add_vpp_config()
2295 self.logger.info(self.vapi.cli("show gbp endpoint"))
2296 self.logger.info(self.vapi.cli("show interface"))
2297 self.logger.info(self.vapi.cli("show br"))
2300 # Intra epg allowed without contract
2302 pkt_intra_epg_220_to_220 = (Ether(src=self.pg0.remote_mac,
2303 dst=self.pg1.remote_mac) /
2306 UDP(sport=1234, dport=1234) /
2309 self.send_and_expect_bridged(self.pg0,
2310 pkt_intra_epg_220_to_220 * 65,
2313 pkt_intra_epg_220_to_220 = (Ether(src=self.pg0.remote_mac,
2314 dst=self.pg1.remote_mac) /
2315 IPv6(src=eps[0].ip6,
2317 UDP(sport=1234, dport=1234) /
2320 self.send_and_expect_bridged6(self.pg0,
2321 pkt_intra_epg_220_to_220 * 65,
2325 # Inter epg denied without contract
2327 pkt_inter_epg_220_to_221 = (Ether(src=self.pg0.remote_mac,
2328 dst=self.pg2.remote_mac) /
2331 UDP(sport=1234, dport=1234) /
2334 self.send_and_assert_no_replies(self.pg0, pkt_inter_epg_220_to_221)
2337 # A uni-directional contract from EPG 220 -> 221
2339 acl = VppGbpAcl(self)
2340 rule = acl.create_rule(permit_deny=1, proto=17)
2341 rule2 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
2342 rule3 = acl.create_rule(permit_deny=1, proto=1)
2343 acl_index = acl.add_vpp_config([rule, rule2, rule3])
2344 c1 = VppGbpContract(
2345 self, 400, epgs[0].sclass, epgs[1].sclass, acl_index,
2346 [VppGbpContractRule(
2347 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2348 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2351 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2352 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2355 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2356 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2358 [ETH_P_IP, ETH_P_IPV6])
2361 self.send_and_expect_bridged(eps[0].itf,
2362 pkt_inter_epg_220_to_221 * 65,
2365 pkt_inter_epg_220_to_222 = (Ether(src=self.pg0.remote_mac,
2366 dst=str(self.router_mac)) /
2369 UDP(sport=1234, dport=1234) /
2371 self.send_and_assert_no_replies(eps[0].itf,
2372 pkt_inter_epg_220_to_222 * 65)
2375 # ping router IP in different BD
2377 pkt_router_ping_220_to_221 = (Ether(src=self.pg0.remote_mac,
2378 dst=str(self.router_mac)) /
2380 dst=epgs[1].bvi_ip4) /
2381 ICMP(type='echo-request'))
2383 self.send_and_expect(self.pg0, [pkt_router_ping_220_to_221], self.pg0)
2385 pkt_router_ping_220_to_221 = (Ether(src=self.pg0.remote_mac,
2386 dst=str(self.router_mac)) /
2387 IPv6(src=eps[0].ip6,
2388 dst=epgs[1].bvi_ip6) /
2389 ICMPv6EchoRequest())
2391 self.send_and_expect(self.pg0, [pkt_router_ping_220_to_221], self.pg0)
2394 # contract for the return direction
2396 c2 = VppGbpContract(
2397 self, 400, epgs[1].sclass, epgs[0].sclass, acl_index,
2398 [VppGbpContractRule(
2399 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2400 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2403 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2404 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2406 [ETH_P_IP, ETH_P_IPV6])
2409 self.send_and_expect_bridged(eps[0].itf,
2410 pkt_inter_epg_220_to_221 * 65,
2412 pkt_inter_epg_221_to_220 = (Ether(src=self.pg2.remote_mac,
2413 dst=self.pg0.remote_mac) /
2416 UDP(sport=1234, dport=1234) /
2418 self.send_and_expect_bridged(eps[2].itf,
2419 pkt_inter_epg_221_to_220 * 65,
2421 pkt_inter_epg_221_to_220 = (Ether(src=self.pg2.remote_mac,
2422 dst=str(self.router_mac)) /
2425 UDP(sport=1234, dport=1234) /
2427 self.send_and_expect_routed(eps[2].itf,
2428 pkt_inter_epg_221_to_220 * 65,
2430 str(self.router_mac))
2431 pkt_inter_epg_221_to_220 = (Ether(src=self.pg2.remote_mac,
2432 dst=str(self.router_mac)) /
2433 IPv6(src=eps[2].ip6,
2435 UDP(sport=1234, dport=1234) /
2437 self.send_and_expect_routed6(eps[2].itf,
2438 pkt_inter_epg_221_to_220 * 65,
2440 str(self.router_mac))
2443 # contract between 220 and 222 uni-direction
2445 c3 = VppGbpContract(
2446 self, 400, epgs[0].sclass, epgs[2].sclass, acl_index,
2447 [VppGbpContractRule(
2448 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2449 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2452 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2453 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2455 [ETH_P_IP, ETH_P_IPV6])
2458 self.send_and_expect(eps[0].itf,
2459 pkt_inter_epg_220_to_222 * 65,
2462 c3.remove_vpp_config()
2463 c1.remove_vpp_config()
2464 c2.remove_vpp_config()
2465 acl.remove_vpp_config()
2467 def test_gbp_bd_drop_flags(self):
2468 """ GBP BD drop flags """
2473 gt4 = VppIpTable(self, 1)
2474 gt4.add_vpp_config()
2475 gt6 = VppIpTable(self, 1, is_ip6=True)
2476 gt6.add_vpp_config()
2478 rd1 = VppGbpRouteDomain(self, 1, 401, gt4, gt6)
2479 rd1.add_vpp_config()
2482 # a GBP bridge domain with a BVI only
2484 bd1 = VppBridgeDomain(self, 1)
2485 bd1.add_vpp_config()
2487 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0,
2489 uu_drop=True, bm_drop=True)
2490 gbd1.add_vpp_config()
2492 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2493 self.logger.info(self.vapi.cli("sh gbp bridge"))
2495 # ... and has a /32 applied
2496 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2497 ip_addr.add_vpp_config()
2500 # The Endpoint-group
2502 epg_220 = VppGbpEndpointGroup(self, 220, 112, rd1, gbd1,
2506 VppGbpEndpointRetention(2))
2507 epg_220.add_vpp_config()
2509 ep = VppGbpEndpoint(self, self.pg0,
2511 "10.0.0.127", "11.0.0.127",
2512 "2001:10::1", "3001::1")
2516 # send UU/BM packet from the local EP with UU drop and BM drop enabled
2519 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2520 self.logger.info(self.vapi.cli("sh gbp bridge"))
2521 p_uu = (Ether(src=ep.mac, dst="00:11:11:11:11:11") /
2522 IP(dst="10.0.0.133", src=ep.ip4) /
2523 UDP(sport=1234, dport=1234) /
2525 self.send_and_assert_no_replies(ep.itf, [p_uu])
2527 p_bm = (Ether(src=ep.mac, dst="ff:ff:ff:ff:ff:ff") /
2528 IP(dst="10.0.0.133", src=ep.ip4) /
2529 UDP(sport=1234, dport=1234) /
2531 self.send_and_assert_no_replies(ep.itf, [p_bm])
2533 self.pg3.unconfig_ip4()
2535 self.logger.info(self.vapi.cli("sh int"))
2537 def test_gbp_bd_arp_flags(self):
2538 """ GBP BD arp flags """
2543 gt4 = VppIpTable(self, 1)
2544 gt4.add_vpp_config()
2545 gt6 = VppIpTable(self, 1, is_ip6=True)
2546 gt6.add_vpp_config()
2548 rd1 = VppGbpRouteDomain(self, 1, 401, gt4, gt6)
2549 rd1.add_vpp_config()
2552 # Pg4 hosts the IP6 UU-flood VXLAN tunnel
2554 self.pg4.config_ip4()
2555 self.pg4.resolve_arp()
2558 # Add a mcast destination VXLAN-GBP tunnel for B&M traffic
2560 tun_uu = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
2563 tun_uu.add_vpp_config()
2566 # a GBP bridge domain with a BVI and a UU-flood interface
2568 bd1 = VppBridgeDomain(self, 1)
2569 bd1.add_vpp_config()
2571 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0,
2574 gbd1.add_vpp_config()
2576 # ... and has a /32 applied
2577 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2578 ip_addr.add_vpp_config()
2581 # The Endpoint-group
2583 epg_220 = VppGbpEndpointGroup(self, 220, 112, rd1, gbd1,
2587 VppGbpEndpointRetention(2))
2588 epg_220.add_vpp_config()
2590 ep = VppGbpEndpoint(self, self.pg0,
2592 "10.0.0.127", "11.0.0.127",
2593 "2001:10::1", "3001::1")
2597 # send ARP packet from the local EP expect it on the uu interface
2599 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2600 self.logger.info(self.vapi.cli("sh gbp bridge"))
2601 p_arp = (Ether(src=ep.mac, dst="ff:ff:ff:ff:ff:ff") /
2603 psrc=ep.ip4, pdst="10.0.0.99",
2605 hwdst="ff:ff:ff:ff:ff:ff"))
2606 self.send_and_expect(ep.itf, [p_arp], self.pg4)
2608 self.pg4.unconfig_ip4()
2610 def test_gbp_learn_vlan_l2(self):
2611 """ GBP L2 Endpoint w/ VLANs"""
2613 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
2614 learnt = [{'mac': '00:00:11:11:11:01',
2616 'ip6': '2001:10::2'},
2617 {'mac': '00:00:11:11:11:02',
2619 'ip6': '2001:10::3'}]
2624 gt4 = VppIpTable(self, 1)
2625 gt4.add_vpp_config()
2626 gt6 = VppIpTable(self, 1, is_ip6=True)
2627 gt6.add_vpp_config()
2629 rd1 = VppGbpRouteDomain(self, 1, 401, gt4, gt6)
2630 rd1.add_vpp_config()
2633 # Pg2 hosts the vxlan tunnel, hosts on pg2 to act as TEPs
2635 self.pg2.config_ip4()
2636 self.pg2.resolve_arp()
2637 self.pg2.generate_remote_hosts(4)
2638 self.pg2.configure_ipv4_neighbors()
2639 self.pg3.config_ip4()
2640 self.pg3.resolve_arp()
2643 # The EP will be on a vlan sub-interface
2645 vlan_11 = VppDot1QSubint(self, self.pg0, 11)
2647 self.vapi.l2_interface_vlan_tag_rewrite(
2648 sw_if_index=vlan_11.sw_if_index, vtr_op=L2_VTR_OP.L2_POP_1,
2651 bd_uu_fwd = VppVxlanGbpTunnel(self, self.pg3.local_ip4,
2652 self.pg3.remote_ip4, 116)
2653 bd_uu_fwd.add_vpp_config()
2656 # a GBP bridge domain with a BVI and a UU-flood interface
2657 # The BD is marked as do not learn, so no endpoints are ever
2658 # learnt in this BD.
2660 bd1 = VppBridgeDomain(self, 1)
2661 bd1.add_vpp_config()
2662 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0, bd_uu_fwd,
2664 gbd1.add_vpp_config()
2666 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2667 self.logger.info(self.vapi.cli("sh gbp bridge"))
2669 # ... and has a /32 applied
2670 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2671 ip_addr.add_vpp_config()
2674 # The Endpoint-group in which we are learning endpoints
2676 epg_220 = VppGbpEndpointGroup(self, 220, 441, rd1, gbd1,
2680 VppGbpEndpointRetention(2))
2681 epg_220.add_vpp_config()
2684 # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
2687 vx_tun_l2_1 = VppGbpVxlanTunnel(
2688 self, 99, bd1.bd_id,
2689 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L2,
2691 vx_tun_l2_1.add_vpp_config()
2694 # A static endpoint that the learnt endpoints are trying to
2697 ep = VppGbpEndpoint(self, vlan_11,
2699 "10.0.0.127", "11.0.0.127",
2700 "2001:10::1", "3001::1")
2703 self.assertTrue(find_route(self, ep.ip4, 32, table_id=1))
2706 # Send to the static EP
2708 for ii, l in enumerate(learnt):
2709 # a packet with an sclass from a known EPG
2710 # arriving on an unknown TEP
2711 p = (Ether(src=self.pg2.remote_mac,
2712 dst=self.pg2.local_mac) /
2713 IP(src=self.pg2.remote_hosts[1].ip4,
2714 dst=self.pg2.local_ip4) /
2715 UDP(sport=1234, dport=48879) /
2716 VXLAN(vni=99, gpid=441, flags=0x88) /
2717 Ether(src=l['mac'], dst=ep.mac) /
2718 IP(src=l['ip'], dst=ep.ip4) /
2719 UDP(sport=1234, dport=1234) /
2722 rxs = self.send_and_expect(self.pg2, [p], self.pg0)
2725 # packet to EP has the EP's vlan tag
2728 self.assertEqual(rx[Dot1Q].vlan, 11)
2731 # the EP is not learnt since the BD setting prevents it
2734 self.assertFalse(find_gbp_endpoint(self,
2735 vx_tun_l2_1.sw_if_index,
2737 self.assertEqual(INDEX_INVALID,
2738 find_vxlan_gbp_tunnel(
2741 self.pg2.remote_hosts[1].ip4,
2744 self.assertEqual(len(self.vapi.gbp_endpoint_dump()), 1)
2748 # we didn't learn the remotes so they are sent to the UU-fwd
2751 p = (Ether(src=ep.mac, dst=l['mac']) /
2753 IP(dst=l['ip'], src=ep.ip4) /
2754 UDP(sport=1234, dport=1234) /
2757 rxs = self.send_and_expect(self.pg0, p * 17, self.pg3)
2760 self.assertEqual(rx[IP].src, self.pg3.local_ip4)
2761 self.assertEqual(rx[IP].dst, self.pg3.remote_ip4)
2762 self.assertEqual(rx[UDP].dport, 48879)
2763 # the UDP source port is a random value for hashing
2764 self.assertEqual(rx[VXLAN].gpid, 441)
2765 self.assertEqual(rx[VXLAN].vni, 116)
2766 self.assertTrue(rx[VXLAN].flags.G)
2767 self.assertTrue(rx[VXLAN].flags.Instance)
2768 self.assertFalse(rx[VXLAN].gpflags.A)
2769 self.assertFalse(rx[VXLAN].gpflags.D)
2771 self.pg2.unconfig_ip4()
2772 self.pg3.unconfig_ip4()
2774 def test_gbp_learn_l3(self):
2775 """ GBP L3 Endpoint Learning """
2777 self.vapi.cli("set logging class gbp level debug")
2779 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
2780 routed_dst_mac = "00:0c:0c:0c:0c:0c"
2781 routed_src_mac = "00:22:bd:f8:19:ff"
2783 learnt = [{'mac': '00:00:11:11:11:02',
2785 'ip6': '2001:10::2'},
2786 {'mac': '00:00:11:11:11:03',
2788 'ip6': '2001:10::3'}]
2793 t4 = VppIpTable(self, 1)
2795 t6 = VppIpTable(self, 1, True)
2798 tun_ip4_uu = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
2799 self.pg4.remote_ip4, 114)
2800 tun_ip6_uu = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
2801 self.pg4.remote_ip4, 116)
2802 tun_ip4_uu.add_vpp_config()
2803 tun_ip6_uu.add_vpp_config()
2805 rd1 = VppGbpRouteDomain(self, 2, 401, t4, t6, tun_ip4_uu, tun_ip6_uu)
2806 rd1.add_vpp_config()
2808 self.loop0.set_mac(self.router_mac)
2811 # Bind the BVI to the RD
2813 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
2814 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
2817 # Pg2 hosts the vxlan tunnel
2818 # hosts on pg2 to act as TEPs
2822 self.pg2.config_ip4()
2823 self.pg2.resolve_arp()
2824 self.pg2.generate_remote_hosts(4)
2825 self.pg2.configure_ipv4_neighbors()
2826 self.pg3.config_ip4()
2827 self.pg3.resolve_arp()
2828 self.pg4.config_ip4()
2829 self.pg4.resolve_arp()
2832 # a GBP bridge domain with a BVI and a UU-flood interface
2834 bd1 = VppBridgeDomain(self, 1)
2835 bd1.add_vpp_config()
2836 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0, self.pg3)
2837 gbd1.add_vpp_config()
2839 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2840 self.logger.info(self.vapi.cli("sh gbp bridge"))
2841 self.logger.info(self.vapi.cli("sh gbp route"))
2843 # ... and has a /32 and /128 applied
2844 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2845 ip4_addr.add_vpp_config()
2846 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 128)
2847 ip6_addr.add_vpp_config()
2850 # The Endpoint-group in which we are learning endpoints
2852 epg_220 = VppGbpEndpointGroup(self, 220, 441, rd1, gbd1,
2856 VppGbpEndpointRetention(2))
2857 epg_220.add_vpp_config()
2860 # The VXLAN GBP tunnel is in L3 mode with learning enabled
2862 vx_tun_l3 = VppGbpVxlanTunnel(
2863 self, 101, rd1.rd_id,
2864 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
2866 vx_tun_l3.add_vpp_config()
2869 # A static endpoint that the learnt endpoints are trying to
2872 ep = VppGbpEndpoint(self, self.pg0,
2874 "10.0.0.127", "11.0.0.127",
2875 "2001:10::1", "3001::1")
2879 # learn some remote IPv4 EPs
2881 for ii, l in enumerate(learnt):
2882 # a packet with an sclass from a known EPG
2883 # arriving on an unknown TEP
2884 p = (Ether(src=self.pg2.remote_mac,
2885 dst=self.pg2.local_mac) /
2886 IP(src=self.pg2.remote_hosts[1].ip4,
2887 dst=self.pg2.local_ip4) /
2888 UDP(sport=1234, dport=48879) /
2889 VXLAN(vni=101, gpid=441, flags=0x88) /
2890 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2891 IP(src=l['ip'], dst=ep.ip4) /
2892 UDP(sport=1234, dport=1234) /
2895 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2898 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2901 self.pg2.remote_hosts[1].ip4,
2903 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2905 # endpoint learnt via the parent GBP-vxlan interface
2906 self.assertTrue(find_gbp_endpoint(self,
2907 vx_tun_l3._sw_if_index,
2911 # Static IPv4 EP replies to learnt
2914 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2915 IP(dst=l['ip'], src=ep.ip4) /
2916 UDP(sport=1234, dport=1234) /
2919 rxs = self.send_and_expect(self.pg0, p * 1, self.pg2)
2922 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2923 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2924 self.assertEqual(rx[UDP].dport, 48879)
2925 # the UDP source port is a random value for hashing
2926 self.assertEqual(rx[VXLAN].gpid, 441)
2927 self.assertEqual(rx[VXLAN].vni, 101)
2928 self.assertTrue(rx[VXLAN].flags.G)
2929 self.assertTrue(rx[VXLAN].flags.Instance)
2930 self.assertTrue(rx[VXLAN].gpflags.A)
2931 self.assertFalse(rx[VXLAN].gpflags.D)
2933 inner = rx[VXLAN].payload
2935 self.assertEqual(inner[Ether].src, routed_src_mac)
2936 self.assertEqual(inner[Ether].dst, routed_dst_mac)
2937 self.assertEqual(inner[IP].src, ep.ip4)
2938 self.assertEqual(inner[IP].dst, l['ip'])
2941 self.assertFalse(find_gbp_endpoint(self,
2946 # learn some remote IPv6 EPs
2948 for ii, l in enumerate(learnt):
2949 # a packet with an sclass from a known EPG
2950 # arriving on an unknown TEP
2951 p = (Ether(src=self.pg2.remote_mac,
2952 dst=self.pg2.local_mac) /
2953 IP(src=self.pg2.remote_hosts[1].ip4,
2954 dst=self.pg2.local_ip4) /
2955 UDP(sport=1234, dport=48879) /
2956 VXLAN(vni=101, gpid=441, flags=0x88) /
2957 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2958 IPv6(src=l['ip6'], dst=ep.ip6) /
2959 UDP(sport=1234, dport=1234) /
2962 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2965 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2968 self.pg2.remote_hosts[1].ip4,
2970 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2972 self.logger.info(self.vapi.cli("show gbp bridge"))
2973 self.logger.info(self.vapi.cli("show vxlan-gbp tunnel"))
2974 self.logger.info(self.vapi.cli("show gbp vxlan"))
2975 self.logger.info(self.vapi.cli("show int addr"))
2977 # endpoint learnt via the TEP
2978 self.assertTrue(find_gbp_endpoint(self, ip=l['ip6']))
2980 self.logger.info(self.vapi.cli("show gbp endpoint"))
2981 self.logger.info(self.vapi.cli("show ip fib index 1 %s" % l['ip']))
2984 # Static EP replies to learnt
2987 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2988 IPv6(dst=l['ip6'], src=ep.ip6) /
2989 UDP(sport=1234, dport=1234) /
2992 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
2995 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2996 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2997 self.assertEqual(rx[UDP].dport, 48879)
2998 # the UDP source port is a random value for hashing
2999 self.assertEqual(rx[VXLAN].gpid, 441)
3000 self.assertEqual(rx[VXLAN].vni, 101)
3001 self.assertTrue(rx[VXLAN].flags.G)
3002 self.assertTrue(rx[VXLAN].flags.Instance)
3003 self.assertTrue(rx[VXLAN].gpflags.A)
3004 self.assertFalse(rx[VXLAN].gpflags.D)
3006 inner = rx[VXLAN].payload
3008 self.assertEqual(inner[Ether].src, routed_src_mac)
3009 self.assertEqual(inner[Ether].dst, routed_dst_mac)
3010 self.assertEqual(inner[IPv6].src, ep.ip6)
3011 self.assertEqual(inner[IPv6].dst, l['ip6'])
3013 self.logger.info(self.vapi.cli("sh gbp endpoint"))
3015 self.wait_for_ep_timeout(ip=l['ip'])
3018 # Static sends to unknown EP with no route
3020 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
3021 IP(dst="10.0.0.99", src=ep.ip4) /
3022 UDP(sport=1234, dport=1234) /
3025 self.send_and_assert_no_replies(self.pg0, [p])
3028 # Add a route to static EP's v4 and v6 subnet
3030 se_10_24 = VppGbpSubnet(
3031 self, rd1, "10.0.0.0", 24,
3032 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT)
3033 se_10_24.add_vpp_config()
3036 # static pings router
3038 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
3039 IP(dst=epg_220.bvi_ip4, src=ep.ip4) /
3040 UDP(sport=1234, dport=1234) /
3043 self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg0)
3045 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
3046 IPv6(dst=epg_220.bvi_ip6, src=ep.ip6) /
3047 UDP(sport=1234, dport=1234) /
3050 self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg0)
3053 # packets to address in the subnet are sent on the uu-fwd
3055 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
3056 IP(dst="10.0.0.99", src=ep.ip4) /
3057 UDP(sport=1234, dport=1234) /
3060 rxs = self.send_and_expect(self.pg0, [p], self.pg4)
3062 self.assertEqual(rx[IP].src, self.pg4.local_ip4)
3063 self.assertEqual(rx[IP].dst, self.pg4.remote_ip4)
3064 self.assertEqual(rx[UDP].dport, 48879)
3065 # the UDP source port is a random value for hashing
3066 self.assertEqual(rx[VXLAN].gpid, 441)
3067 self.assertEqual(rx[VXLAN].vni, 114)
3068 self.assertTrue(rx[VXLAN].flags.G)
3069 self.assertTrue(rx[VXLAN].flags.Instance)
3070 # policy is not applied to packets sent to the uu-fwd interfaces
3071 self.assertFalse(rx[VXLAN].gpflags.A)
3072 self.assertFalse(rx[VXLAN].gpflags.D)
3075 # learn some remote IPv4 EPs
3077 for ii, l in enumerate(learnt):
3078 # a packet with an sclass from a known EPG
3079 # arriving on an unknown TEP
3080 p = (Ether(src=self.pg2.remote_mac,
3081 dst=self.pg2.local_mac) /
3082 IP(src=self.pg2.remote_hosts[2].ip4,
3083 dst=self.pg2.local_ip4) /
3084 UDP(sport=1234, dport=48879) /
3085 VXLAN(vni=101, gpid=441, flags=0x88) /
3086 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
3087 IP(src=l['ip'], dst=ep.ip4) /
3088 UDP(sport=1234, dport=1234) /
3091 rx = self.send_and_expect(self.pg2, [p], self.pg0)
3094 tep1_sw_if_index = find_vxlan_gbp_tunnel(
3097 self.pg2.remote_hosts[2].ip4,
3099 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
3101 # endpoint learnt via the parent GBP-vxlan interface
3102 self.assertTrue(find_gbp_endpoint(self,
3103 vx_tun_l3._sw_if_index,
3107 # Add a remote endpoint from the API
3109 rep_88 = VppGbpEndpoint(self, vx_tun_l3,
3111 "10.0.0.88", "11.0.0.88",
3112 "2001:10::88", "3001::88",
3113 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
3115 self.pg2.remote_hosts[2].ip4,
3117 rep_88.add_vpp_config()
3120 # Add a remote endpoint from the API that matches an existing one
3121 # this is a lower priority, hence the packet is sent to the DP leanrt
3124 rep_2 = VppGbpEndpoint(self, vx_tun_l3,
3126 learnt[0]['ip'], "11.0.0.101",
3127 learnt[0]['ip6'], "3001::101",
3128 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
3130 self.pg2.remote_hosts[1].ip4,
3132 rep_2.add_vpp_config()
3135 # Add a route to the learned EP's v4 subnet
3136 # packets should be send on the v4/v6 uu=fwd interface resp.
3138 se_10_1_24 = VppGbpSubnet(
3139 self, rd1, "10.0.1.0", 24,
3140 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT)
3141 se_10_1_24.add_vpp_config()
3143 self.logger.info(self.vapi.cli("show gbp endpoint"))
3145 ips = ["10.0.0.88", learnt[0]['ip']]
3147 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
3148 IP(dst=ip, src=ep.ip4) /
3149 UDP(sport=1234, dport=1234) /
3152 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
3155 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
3156 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[2].ip4)
3157 self.assertEqual(rx[UDP].dport, 48879)
3158 # the UDP source port is a random value for hashing
3159 self.assertEqual(rx[VXLAN].gpid, 441)
3160 self.assertEqual(rx[VXLAN].vni, 101)
3161 self.assertTrue(rx[VXLAN].flags.G)
3162 self.assertTrue(rx[VXLAN].flags.Instance)
3163 self.assertTrue(rx[VXLAN].gpflags.A)
3164 self.assertFalse(rx[VXLAN].gpflags.D)
3166 inner = rx[VXLAN].payload
3168 self.assertEqual(inner[Ether].src, routed_src_mac)
3169 self.assertEqual(inner[Ether].dst, routed_dst_mac)
3170 self.assertEqual(inner[IP].src, ep.ip4)
3171 self.assertEqual(inner[IP].dst, ip)
3174 # remove the API remote EPs, only API sourced is gone, the DP
3175 # learnt one remains
3177 rep_88.remove_vpp_config()
3178 rep_2.remove_vpp_config()
3180 self.assertTrue(find_gbp_endpoint(self, ip=rep_2.ip4))
3182 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
3183 IP(src=ep.ip4, dst=rep_2.ip4) /
3184 UDP(sport=1234, dport=1234) /
3186 rxs = self.send_and_expect(self.pg0, [p], self.pg2)
3188 self.assertFalse(find_gbp_endpoint(self, ip=rep_88.ip4))
3190 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
3191 IP(src=ep.ip4, dst=rep_88.ip4) /
3192 UDP(sport=1234, dport=1234) /
3194 rxs = self.send_and_expect(self.pg0, [p], self.pg4)
3197 # to appease the testcase we cannot have the registered EP still
3198 # present (because it's DP learnt) when the TC ends so wait until
3201 self.wait_for_ep_timeout(ip=rep_88.ip4)
3202 self.wait_for_ep_timeout(ip=rep_2.ip4)
3205 # Same as above, learn a remote EP via CP and DP
3206 # this time remove the DP one first. expect the CP data to remain
3208 rep_3 = VppGbpEndpoint(self, vx_tun_l3,
3210 "10.0.1.4", "11.0.0.103",
3211 "2001::10:3", "3001::103",
3212 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
3214 self.pg2.remote_hosts[1].ip4,
3216 rep_3.add_vpp_config()
3218 p = (Ether(src=self.pg2.remote_mac,
3219 dst=self.pg2.local_mac) /
3220 IP(src=self.pg2.remote_hosts[2].ip4,
3221 dst=self.pg2.local_ip4) /
3222 UDP(sport=1234, dport=48879) /
3223 VXLAN(vni=101, gpid=441, flags=0x88) /
3224 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
3225 IP(src="10.0.1.4", dst=ep.ip4) /
3226 UDP(sport=1234, dport=1234) /
3228 rxs = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
3230 self.assertTrue(find_gbp_endpoint(self,
3231 vx_tun_l3._sw_if_index,
3233 tep=[self.pg2.local_ip4,
3234 self.pg2.remote_hosts[2].ip4]))
3236 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
3237 IP(dst="10.0.1.4", src=ep.ip4) /
3238 UDP(sport=1234, dport=1234) /
3240 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
3242 # host 2 is the DP learned TEP
3244 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
3245 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[2].ip4)
3247 self.wait_for_ep_timeout(ip=rep_3.ip4,
3248 tep=[self.pg2.local_ip4,
3249 self.pg2.remote_hosts[2].ip4])
3251 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
3253 # host 1 is the CP learned TEP
3255 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
3256 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
3259 # shutdown with learnt endpoint present
3261 p = (Ether(src=self.pg2.remote_mac,
3262 dst=self.pg2.local_mac) /
3263 IP(src=self.pg2.remote_hosts[1].ip4,
3264 dst=self.pg2.local_ip4) /
3265 UDP(sport=1234, dport=48879) /
3266 VXLAN(vni=101, gpid=441, flags=0x88) /
3267 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
3268 IP(src=learnt[1]['ip'], dst=ep.ip4) /
3269 UDP(sport=1234, dport=1234) /
3272 rx = self.send_and_expect(self.pg2, [p], self.pg0)
3274 # endpoint learnt via the parent GBP-vxlan interface
3275 self.assertTrue(find_gbp_endpoint(self,
3276 vx_tun_l3._sw_if_index,
3281 # remote endpoint becomes local
3283 self.pg2.unconfig_ip4()
3284 self.pg3.unconfig_ip4()
3285 self.pg4.unconfig_ip4()
3287 def test_gbp_redirect(self):
3288 """ GBP Endpoint Redirect """
3290 self.vapi.cli("set logging class gbp level debug")
3292 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
3293 routed_dst_mac = "00:0c:0c:0c:0c:0c"
3294 routed_src_mac = "00:22:bd:f8:19:ff"
3296 learnt = [{'mac': '00:00:11:11:11:02',
3298 'ip6': '2001:10::2'},
3299 {'mac': '00:00:11:11:11:03',
3301 'ip6': '2001:10::3'}]
3306 t4 = VppIpTable(self, 1)
3308 t6 = VppIpTable(self, 1, True)
3311 rd1 = VppGbpRouteDomain(self, 2, 402, t4, t6)
3312 rd1.add_vpp_config()
3314 self.loop0.set_mac(self.router_mac)
3317 # Bind the BVI to the RD
3319 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
3320 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
3323 # Pg7 hosts a BD's UU-fwd
3325 self.pg7.config_ip4()
3326 self.pg7.resolve_arp()
3329 # a GBP bridge domains for the EPs
3331 bd1 = VppBridgeDomain(self, 1)
3332 bd1.add_vpp_config()
3333 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0)
3334 gbd1.add_vpp_config()
3336 bd2 = VppBridgeDomain(self, 2)
3337 bd2.add_vpp_config()
3338 gbd2 = VppGbpBridgeDomain(self, bd2, rd1, self.loop1)
3339 gbd2.add_vpp_config()
3341 # ... and has a /32 and /128 applied
3342 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
3343 ip4_addr.add_vpp_config()
3344 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 128)
3345 ip6_addr.add_vpp_config()
3346 ip4_addr = VppIpInterfaceAddress(self, gbd2.bvi, "10.0.1.128", 32)
3347 ip4_addr.add_vpp_config()
3348 ip6_addr = VppIpInterfaceAddress(self, gbd2.bvi, "2001:11::128", 128)
3349 ip6_addr.add_vpp_config()
3352 # The Endpoint-groups in which we are learning endpoints
3354 epg_220 = VppGbpEndpointGroup(self, 220, 440, rd1, gbd1,
3358 VppGbpEndpointRetention(2))
3359 epg_220.add_vpp_config()
3360 epg_221 = VppGbpEndpointGroup(self, 221, 441, rd1, gbd2,
3364 VppGbpEndpointRetention(2))
3365 epg_221.add_vpp_config()
3366 epg_222 = VppGbpEndpointGroup(self, 222, 442, rd1, gbd1,
3370 VppGbpEndpointRetention(2))
3371 epg_222.add_vpp_config()
3374 # a GBP bridge domains for the SEPs
3376 bd_uu1 = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
3377 self.pg7.remote_ip4, 116)
3378 bd_uu1.add_vpp_config()
3379 bd_uu2 = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
3380 self.pg7.remote_ip4, 117)
3381 bd_uu2.add_vpp_config()
3383 bd3 = VppBridgeDomain(self, 3)
3384 bd3.add_vpp_config()
3385 gbd3 = VppGbpBridgeDomain(self, bd3, rd1, self.loop2,
3386 bd_uu1, learn=False)
3387 gbd3.add_vpp_config()
3388 bd4 = VppBridgeDomain(self, 4)
3389 bd4.add_vpp_config()
3390 gbd4 = VppGbpBridgeDomain(self, bd4, rd1, self.loop3,
3391 bd_uu2, learn=False)
3392 gbd4.add_vpp_config()
3395 # EPGs in which the service endpoints exist
3397 epg_320 = VppGbpEndpointGroup(self, 320, 550, rd1, gbd3,
3401 VppGbpEndpointRetention(2))
3402 epg_320.add_vpp_config()
3403 epg_321 = VppGbpEndpointGroup(self, 321, 551, rd1, gbd4,
3407 VppGbpEndpointRetention(2))
3408 epg_321.add_vpp_config()
3411 # three local endpoints
3413 ep1 = VppGbpEndpoint(self, self.pg0,
3415 "10.0.0.1", "11.0.0.1",
3416 "2001:10::1", "3001:10::1")
3417 ep1.add_vpp_config()
3418 ep2 = VppGbpEndpoint(self, self.pg1,
3420 "10.0.1.1", "11.0.1.1",
3421 "2001:11::1", "3001:11::1")
3422 ep2.add_vpp_config()
3423 ep3 = VppGbpEndpoint(self, self.pg2,
3425 "10.0.2.2", "11.0.2.2",
3426 "2001:12::1", "3001:12::1")
3427 ep3.add_vpp_config()
3432 sep1 = VppGbpEndpoint(self, self.pg3,
3434 "12.0.0.1", "13.0.0.1",
3435 "4001:10::1", "5001:10::1")
3436 sep1.add_vpp_config()
3437 sep2 = VppGbpEndpoint(self, self.pg4,
3439 "12.0.0.2", "13.0.0.2",
3440 "4001:10::2", "5001:10::2")
3441 sep2.add_vpp_config()
3442 sep3 = VppGbpEndpoint(self, self.pg5,
3444 "12.0.1.1", "13.0.1.1",
3445 "4001:11::1", "5001:11::1")
3446 sep3.add_vpp_config()
3447 # this EP is not installed immediately
3448 sep4 = VppGbpEndpoint(self, self.pg6,
3450 "12.0.1.2", "13.0.1.2",
3451 "4001:11::2", "5001:11::2")
3454 # an L2 switch packet between local EPs in different EPGs
3455 # different dest ports on each so the are LB hashed differently
3457 p4 = [(Ether(src=ep1.mac, dst=ep3.mac) /
3458 IP(src=ep1.ip4, dst=ep3.ip4) /
3459 UDP(sport=1234, dport=1234) /
3460 Raw(b'\xa5' * 100)),
3461 (Ether(src=ep3.mac, dst=ep1.mac) /
3462 IP(src=ep3.ip4, dst=ep1.ip4) /
3463 UDP(sport=1234, dport=1234) /
3464 Raw(b'\xa5' * 100))]
3465 p6 = [(Ether(src=ep1.mac, dst=ep3.mac) /
3466 IPv6(src=ep1.ip6, dst=ep3.ip6) /
3467 UDP(sport=1234, dport=1234) /
3468 Raw(b'\xa5' * 100)),
3469 (Ether(src=ep3.mac, dst=ep1.mac) /
3470 IPv6(src=ep3.ip6, dst=ep1.ip6) /
3471 UDP(sport=1234, dport=1230) /
3472 Raw(b'\xa5' * 100))]
3474 # should be dropped since no contract yet
3475 self.send_and_assert_no_replies(self.pg0, [p4[0]])
3476 self.send_and_assert_no_replies(self.pg0, [p6[0]])
3479 # Add a contract with a rule to load-balance redirect via SEP1 and SEP2
3480 # one of the next-hops is via an EP that is not known
3482 acl = VppGbpAcl(self)
3483 rule4 = acl.create_rule(permit_deny=1, proto=17)
3484 rule6 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
3485 acl_index = acl.add_vpp_config([rule4, rule6])
3488 # test the src-ip hash mode
3490 c1 = VppGbpContract(
3491 self, 402, epg_220.sclass, epg_222.sclass, acl_index,
3492 [VppGbpContractRule(
3493 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3494 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3495 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3496 sep1.ip4, sep1.epg.rd),
3497 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3498 sep2.ip4, sep2.epg.rd)]),
3500 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3501 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3502 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3503 sep3.ip6, sep3.epg.rd),
3504 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3505 sep4.ip6, sep4.epg.rd)])],
3506 [ETH_P_IP, ETH_P_IPV6])
3509 c2 = VppGbpContract(
3510 self, 402, epg_222.sclass, epg_220.sclass, acl_index,
3511 [VppGbpContractRule(
3512 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3513 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3514 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3515 sep1.ip4, sep1.epg.rd),
3516 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3517 sep2.ip4, sep2.epg.rd)]),
3519 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3520 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3521 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3522 sep3.ip6, sep3.epg.rd),
3523 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3524 sep4.ip6, sep4.epg.rd)])],
3525 [ETH_P_IP, ETH_P_IPV6])
3529 # send again with the contract preset, now packets arrive
3530 # at SEP1 or SEP2 depending on the hashing
3532 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3535 self.assertEqual(rx[Ether].src, routed_src_mac)
3536 self.assertEqual(rx[Ether].dst, sep1.mac)
3537 self.assertEqual(rx[IP].src, ep1.ip4)
3538 self.assertEqual(rx[IP].dst, ep3.ip4)
3540 rxs = self.send_and_expect(self.pg2, p4[1] * 17, sep2.itf)
3543 self.assertEqual(rx[Ether].src, routed_src_mac)
3544 self.assertEqual(rx[Ether].dst, sep2.mac)
3545 self.assertEqual(rx[IP].src, ep3.ip4)
3546 self.assertEqual(rx[IP].dst, ep1.ip4)
3548 rxs = self.send_and_expect(self.pg0, p6[0] * 17, self.pg7)
3551 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3552 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3553 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3554 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
3555 self.assertEqual(rx[VXLAN].vni, 117)
3556 self.assertTrue(rx[VXLAN].flags.G)
3557 self.assertTrue(rx[VXLAN].flags.Instance)
3558 # redirect policy has been applied
3559 self.assertTrue(rx[VXLAN].gpflags.A)
3560 self.assertFalse(rx[VXLAN].gpflags.D)
3562 inner = rx[VXLAN].payload
3564 self.assertEqual(inner[Ether].src, routed_src_mac)
3565 self.assertEqual(inner[Ether].dst, sep4.mac)
3566 self.assertEqual(inner[IPv6].src, ep1.ip6)
3567 self.assertEqual(inner[IPv6].dst, ep3.ip6)
3569 rxs = self.send_and_expect(self.pg2, p6[1] * 17, sep3.itf)
3572 self.assertEqual(rx[Ether].src, routed_src_mac)
3573 self.assertEqual(rx[Ether].dst, sep3.mac)
3574 self.assertEqual(rx[IPv6].src, ep3.ip6)
3575 self.assertEqual(rx[IPv6].dst, ep1.ip6)
3578 # programme the unknown EP
3580 sep4.add_vpp_config()
3582 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep4.itf)
3585 self.assertEqual(rx[Ether].src, routed_src_mac)
3586 self.assertEqual(rx[Ether].dst, sep4.mac)
3587 self.assertEqual(rx[IPv6].src, ep1.ip6)
3588 self.assertEqual(rx[IPv6].dst, ep3.ip6)
3591 # and revert back to unprogrammed
3593 sep4.remove_vpp_config()
3595 rxs = self.send_and_expect(self.pg0, p6[0] * 17, self.pg7)
3598 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3599 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3600 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3601 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
3602 self.assertEqual(rx[VXLAN].vni, 117)
3603 self.assertTrue(rx[VXLAN].flags.G)
3604 self.assertTrue(rx[VXLAN].flags.Instance)
3605 # redirect policy has been applied
3606 self.assertTrue(rx[VXLAN].gpflags.A)
3607 self.assertFalse(rx[VXLAN].gpflags.D)
3609 inner = rx[VXLAN].payload
3611 self.assertEqual(inner[Ether].src, routed_src_mac)
3612 self.assertEqual(inner[Ether].dst, sep4.mac)
3613 self.assertEqual(inner[IPv6].src, ep1.ip6)
3614 self.assertEqual(inner[IPv6].dst, ep3.ip6)
3616 c1.remove_vpp_config()
3617 c2.remove_vpp_config()
3620 # test the symmetric hash mode
3622 c1 = VppGbpContract(
3623 self, 402, epg_220.sclass, epg_222.sclass, acl_index,
3624 [VppGbpContractRule(
3625 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3626 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3627 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3628 sep1.ip4, sep1.epg.rd),
3629 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3630 sep2.ip4, sep2.epg.rd)]),
3632 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3633 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3634 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3635 sep3.ip6, sep3.epg.rd),
3636 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3637 sep4.ip6, sep4.epg.rd)])],
3638 [ETH_P_IP, ETH_P_IPV6])
3641 c2 = VppGbpContract(
3642 self, 402, epg_222.sclass, epg_220.sclass, acl_index,
3643 [VppGbpContractRule(
3644 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3645 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3646 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3647 sep1.ip4, sep1.epg.rd),
3648 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3649 sep2.ip4, sep2.epg.rd)]),
3651 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3652 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3653 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3654 sep3.ip6, sep3.epg.rd),
3655 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3656 sep4.ip6, sep4.epg.rd)])],
3657 [ETH_P_IP, ETH_P_IPV6])
3661 # send again with the contract preset, now packets arrive
3662 # at SEP1 for both directions
3664 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3667 self.assertEqual(rx[Ether].src, routed_src_mac)
3668 self.assertEqual(rx[Ether].dst, sep1.mac)
3669 self.assertEqual(rx[IP].src, ep1.ip4)
3670 self.assertEqual(rx[IP].dst, ep3.ip4)
3672 rxs = self.send_and_expect(self.pg2, p4[1] * 17, sep1.itf)
3675 self.assertEqual(rx[Ether].src, routed_src_mac)
3676 self.assertEqual(rx[Ether].dst, sep1.mac)
3677 self.assertEqual(rx[IP].src, ep3.ip4)
3678 self.assertEqual(rx[IP].dst, ep1.ip4)
3681 # programme the unknown EP for the L3 tests
3683 sep4.add_vpp_config()
3686 # an L3 switch packet between local EPs in different EPGs
3687 # different dest ports on each so the are LB hashed differently
3689 p4 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3690 IP(src=ep1.ip4, dst=ep2.ip4) /
3691 UDP(sport=1234, dport=1234) /
3692 Raw(b'\xa5' * 100)),
3693 (Ether(src=ep2.mac, dst=str(self.router_mac)) /
3694 IP(src=ep2.ip4, dst=ep1.ip4) /
3695 UDP(sport=1234, dport=1234) /
3696 Raw(b'\xa5' * 100))]
3697 p6 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3698 IPv6(src=ep1.ip6, dst=ep2.ip6) /
3699 UDP(sport=1234, dport=1234) /
3700 Raw(b'\xa5' * 100)),
3701 (Ether(src=ep2.mac, dst=str(self.router_mac)) /
3702 IPv6(src=ep2.ip6, dst=ep1.ip6) /
3703 UDP(sport=1234, dport=1234) /
3704 Raw(b'\xa5' * 100))]
3706 c3 = VppGbpContract(
3707 self, 402, epg_220.sclass, epg_221.sclass, acl_index,
3708 [VppGbpContractRule(
3709 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3710 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3711 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3712 sep1.ip4, sep1.epg.rd),
3713 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3714 sep2.ip4, sep2.epg.rd)]),
3716 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3717 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3718 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3719 sep3.ip6, sep3.epg.rd),
3720 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3721 sep4.ip6, sep4.epg.rd)])],
3722 [ETH_P_IP, ETH_P_IPV6])
3725 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3728 self.assertEqual(rx[Ether].src, routed_src_mac)
3729 self.assertEqual(rx[Ether].dst, sep1.mac)
3730 self.assertEqual(rx[IP].src, ep1.ip4)
3731 self.assertEqual(rx[IP].dst, ep2.ip4)
3734 # learn a remote EP in EPG 221
3735 # packets coming from unknown remote EPs will be leant & redirected
3737 vx_tun_l3 = VppGbpVxlanTunnel(
3738 self, 444, rd1.rd_id,
3739 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
3741 vx_tun_l3.add_vpp_config()
3743 c4 = VppGbpContract(
3744 self, 402, epg_221.sclass, epg_220.sclass, acl_index,
3745 [VppGbpContractRule(
3746 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3747 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3748 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3749 sep1.ip4, sep1.epg.rd),
3750 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3751 sep2.ip4, sep2.epg.rd)]),
3753 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3754 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3755 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3756 sep3.ip6, sep3.epg.rd),
3757 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3758 sep4.ip6, sep4.epg.rd)])],
3759 [ETH_P_IP, ETH_P_IPV6])
3762 p = (Ether(src=self.pg7.remote_mac,
3763 dst=self.pg7.local_mac) /
3764 IP(src=self.pg7.remote_ip4,
3765 dst=self.pg7.local_ip4) /
3766 UDP(sport=1234, dport=48879) /
3767 VXLAN(vni=444, gpid=441, flags=0x88) /
3768 Ether(src="00:22:22:22:22:33", dst=str(self.router_mac)) /
3769 IP(src="10.0.0.88", dst=ep1.ip4) /
3770 UDP(sport=1234, dport=1234) /
3773 # unknown remote EP to local EP redirected
3774 rxs = self.send_and_expect(self.pg7, [p], sep1.itf)
3777 self.assertEqual(rx[Ether].src, routed_src_mac)
3778 self.assertEqual(rx[Ether].dst, sep1.mac)
3779 self.assertEqual(rx[IP].src, "10.0.0.88")
3780 self.assertEqual(rx[IP].dst, ep1.ip4)
3782 # endpoint learnt via the parent GBP-vxlan interface
3783 self.assertTrue(find_gbp_endpoint(self,
3784 vx_tun_l3._sw_if_index,
3787 p = (Ether(src=self.pg7.remote_mac,
3788 dst=self.pg7.local_mac) /
3789 IP(src=self.pg7.remote_ip4,
3790 dst=self.pg7.local_ip4) /
3791 UDP(sport=1234, dport=48879) /
3792 VXLAN(vni=444, gpid=441, flags=0x88) /
3793 Ether(src="00:22:22:22:22:33", dst=str(self.router_mac)) /
3794 IPv6(src="2001:10::88", dst=ep1.ip6) /
3795 UDP(sport=1234, dport=1234) /
3798 # unknown remote EP to local EP redirected (ipv6)
3799 rxs = self.send_and_expect(self.pg7, [p], sep3.itf)
3802 self.assertEqual(rx[Ether].src, routed_src_mac)
3803 self.assertEqual(rx[Ether].dst, sep3.mac)
3804 self.assertEqual(rx[IPv6].src, "2001:10::88")
3805 self.assertEqual(rx[IPv6].dst, ep1.ip6)
3807 # endpoint learnt via the parent GBP-vxlan interface
3808 self.assertTrue(find_gbp_endpoint(self,
3809 vx_tun_l3._sw_if_index,
3813 # L3 switch from local to remote EP
3815 p4 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3816 IP(src=ep1.ip4, dst="10.0.0.88") /
3817 UDP(sport=1234, dport=1234) /
3818 Raw(b'\xa5' * 100))]
3819 p6 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3820 IPv6(src=ep1.ip6, dst="2001:10::88") /
3821 UDP(sport=1234, dport=1234) /
3822 Raw(b'\xa5' * 100))]
3824 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3827 self.assertEqual(rx[Ether].src, routed_src_mac)
3828 self.assertEqual(rx[Ether].dst, sep1.mac)
3829 self.assertEqual(rx[IP].src, ep1.ip4)
3830 self.assertEqual(rx[IP].dst, "10.0.0.88")
3832 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep4.itf)
3835 self.assertEqual(rx[Ether].src, routed_src_mac)
3836 self.assertEqual(rx[Ether].dst, sep4.mac)
3837 self.assertEqual(rx[IPv6].src, ep1.ip6)
3838 self.assertEqual(rx[IPv6].dst, "2001:10::88")
3841 # test the dst-ip hash mode
3843 c5 = VppGbpContract(
3844 self, 402, epg_220.sclass, epg_221.sclass, acl_index,
3845 [VppGbpContractRule(
3846 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3847 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
3848 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3849 sep1.ip4, sep1.epg.rd),
3850 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3851 sep2.ip4, sep2.epg.rd)]),
3853 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3854 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
3855 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3856 sep3.ip6, sep3.epg.rd),
3857 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3858 sep4.ip6, sep4.epg.rd)])],
3859 [ETH_P_IP, ETH_P_IPV6])
3862 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3865 self.assertEqual(rx[Ether].src, routed_src_mac)
3866 self.assertEqual(rx[Ether].dst, sep1.mac)
3867 self.assertEqual(rx[IP].src, ep1.ip4)
3868 self.assertEqual(rx[IP].dst, "10.0.0.88")
3870 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep3.itf)
3873 self.assertEqual(rx[Ether].src, routed_src_mac)
3874 self.assertEqual(rx[Ether].dst, sep3.mac)
3875 self.assertEqual(rx[IPv6].src, ep1.ip6)
3876 self.assertEqual(rx[IPv6].dst, "2001:10::88")
3879 # a programmed remote SEP in EPG 320
3882 # gbp vxlan tunnel for the remote SEP
3883 vx_tun_l3_sep = VppGbpVxlanTunnel(
3884 self, 555, rd1.rd_id,
3885 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
3887 vx_tun_l3_sep.add_vpp_config()
3890 sep5 = VppGbpEndpoint(self, vx_tun_l3_sep,
3892 "12.0.0.10", "13.0.0.10",
3893 "4001:10::10", "5001:10::10",
3894 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
3896 self.pg7.remote_ip4,
3898 sep5.add_vpp_config()
3901 # local l3out redirect tests
3906 self.loop4.set_mac(self.router_mac)
3907 VppIpInterfaceBind(self, self.loop4, t4).add_vpp_config()
3908 VppIpInterfaceBind(self, self.loop4, t6).add_vpp_config()
3909 ebd = VppBridgeDomain(self, 100)
3910 ebd.add_vpp_config()
3911 gebd = VppGbpBridgeDomain(self, ebd, rd1, self.loop4, None, None)
3912 gebd.add_vpp_config()
3914 eepg = VppGbpEndpointGroup(self, 888, 765, rd1, gebd,
3918 VppGbpEndpointRetention(2))
3919 eepg.add_vpp_config()
3920 # add subnets to BVI
3921 VppIpInterfaceAddress(
3925 24).add_vpp_config()
3926 VppIpInterfaceAddress(
3930 64).add_vpp_config()
3931 # ... which are L3-out subnets
3932 VppGbpSubnet(self, rd1, "10.1.0.0", 24,
3933 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3934 sclass=765).add_vpp_config()
3935 VppGbpSubnet(self, rd1, "2001:10:1::128", 64,
3936 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3937 sclass=765).add_vpp_config()
3938 # external endpoints
3939 VppL2Vtr(self, self.vlan_100, L2_VTR_OP.L2_POP_1).add_vpp_config()
3940 eep1 = VppGbpEndpoint(self, self.vlan_100, eepg, None, "10.1.0.1",
3941 "11.1.0.1", "2001:10:1::1", "3001:10:1::1",
3942 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
3943 eep1.add_vpp_config()
3944 VppL2Vtr(self, self.vlan_101, L2_VTR_OP.L2_POP_1).add_vpp_config()
3945 eep2 = VppGbpEndpoint(self, self.vlan_101, eepg, None, "10.1.0.2",
3946 "11.1.0.2", "2001:10:1::2", "3001:10:1::2",
3947 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
3948 eep2.add_vpp_config()
3950 # external subnets reachable though eep1 and eep2 respectively
3951 VppIpRoute(self, "10.220.0.0", 24,
3952 [VppRoutePath(eep1.ip4, eep1.epg.bvi.sw_if_index)],
3953 table_id=t4.table_id).add_vpp_config()
3954 VppGbpSubnet(self, rd1, "10.220.0.0", 24,
3955 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3956 sclass=4220).add_vpp_config()
3957 VppIpRoute(self, "10:220::", 64,
3958 [VppRoutePath(eep1.ip6, eep1.epg.bvi.sw_if_index)],
3959 table_id=t6.table_id).add_vpp_config()
3960 VppGbpSubnet(self, rd1, "10:220::", 64,
3961 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3962 sclass=4220).add_vpp_config()
3963 VppIpRoute(self, "10.221.0.0", 24,
3964 [VppRoutePath(eep2.ip4, eep2.epg.bvi.sw_if_index)],
3965 table_id=t4.table_id).add_vpp_config()
3966 VppGbpSubnet(self, rd1, "10.221.0.0", 24,
3967 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3968 sclass=4221).add_vpp_config()
3969 VppIpRoute(self, "10:221::", 64,
3970 [VppRoutePath(eep2.ip6, eep2.epg.bvi.sw_if_index)],
3971 table_id=t6.table_id).add_vpp_config()
3972 VppGbpSubnet(self, rd1, "10:221::", 64,
3973 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3974 sclass=4221).add_vpp_config()
3977 # l3out redirect to remote (known, then unknown) SEP
3980 # packets from 1 external subnet to the other
3981 p = [(Ether(src=eep1.mac, dst=self.router_mac) /
3983 IP(src="10.220.0.17", dst="10.221.0.65") /
3984 UDP(sport=1234, dport=1234) /
3985 Raw(b'\xa5' * 100)),
3986 (Ether(src=eep1.mac, dst=self.router_mac) /
3988 IPv6(src="10:220::17", dst="10:221::65") /
3989 UDP(sport=1234, dport=1234) /
3990 Raw(b'\xa5' * 100))]
3992 # packets should be dropped in absence of contract
3993 self.send_and_assert_no_replies(self.pg0, p)
3995 # contract redirecting to sep5
3997 self, 402, 4220, 4221, acl_index,
3998 [VppGbpContractRule(
3999 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4000 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
4001 [VppGbpContractNextHop(sep5.vmac, sep5.epg.bd,
4002 sep5.ip4, sep5.epg.rd)]),
4004 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4005 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
4006 [VppGbpContractNextHop(sep5.vmac, sep5.epg.bd,
4007 sep5.ip6, sep5.epg.rd)])],
4008 [ETH_P_IP, ETH_P_IPV6]).add_vpp_config()
4010 rxs = self.send_and_expect(self.pg0, p, self.pg7)
4012 for rx, tx in zip(rxs, p):
4013 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4014 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4015 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4016 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4017 # this should use the programmed remote leaf TEP
4018 self.assertEqual(rx[VXLAN].vni, 555)
4019 self.assertEqual(rx[VXLAN].gpid, 4220)
4020 self.assertTrue(rx[VXLAN].flags.G)
4021 self.assertTrue(rx[VXLAN].flags.Instance)
4022 # redirect policy has been applied
4023 self.assertTrue(rx[VXLAN].gpflags.A)
4024 self.assertTrue(rx[VXLAN].gpflags.D)
4025 rxip = rx[VXLAN][Ether].payload
4026 txip = tx[Dot1Q].payload
4027 self.assertEqual(rxip.src, txip.src)
4028 self.assertEqual(rxip.dst, txip.dst)
4030 # remote SEP: it is now an unknown remote SEP and should go
4032 sep5.remove_vpp_config()
4034 rxs = self.send_and_expect(self.pg0, p, self.pg7)
4036 for rx, tx in zip(rxs, p):
4037 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4038 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4039 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4040 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4041 # this should use the spine proxy TEP
4042 self.assertEqual(rx[VXLAN].vni, epg_320.bd.uu_fwd.vni)
4043 self.assertEqual(rx[VXLAN].gpid, 4220)
4044 self.assertTrue(rx[VXLAN].flags.G)
4045 self.assertTrue(rx[VXLAN].flags.Instance)
4046 # redirect policy has been applied
4047 self.assertTrue(rx[VXLAN].gpflags.A)
4048 self.assertTrue(rx[VXLAN].gpflags.D)
4049 rxip = rx[VXLAN][Ether].payload
4050 txip = tx[Dot1Q].payload
4051 self.assertEqual(rxip.src, txip.src)
4052 self.assertEqual(rxip.dst, txip.dst)
4055 # l3out redirect to local SEP
4058 # change the contract between l3out to redirect to local SEPs
4059 # instead of remote SEP
4061 self, 402, 4220, 4221, acl_index,
4062 [VppGbpContractRule(
4063 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4064 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
4065 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
4066 sep1.ip4, sep1.epg.rd)]),
4068 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4069 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
4070 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
4071 sep1.ip6, sep1.epg.rd)])],
4072 [ETH_P_IP, ETH_P_IPV6]).add_vpp_config()
4074 rxs = self.send_and_expect(self.pg0, p, sep1.itf)
4075 for rx, tx in zip(rxs, p):
4076 self.assertEqual(rx[Ether].src, routed_src_mac)
4077 self.assertEqual(rx[Ether].dst, sep1.mac)
4078 rxip = rx[Ether].payload
4079 txip = tx[Ether].payload
4080 self.assertEqual(rxip.src, txip.src)
4081 self.assertEqual(rxip.dst, txip.dst)
4084 # redirect remote EP to remote (known then unknown) SEP
4087 # remote SEP known again
4088 sep5.add_vpp_config()
4090 # contract to redirect to learnt SEP
4092 self, 402, epg_221.sclass, epg_222.sclass, acl_index,
4093 [VppGbpContractRule(
4094 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4095 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
4096 [VppGbpContractNextHop(sep5.vmac, sep5.epg.bd,
4097 sep5.ip4, sep5.epg.rd)]),
4099 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4100 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
4101 [VppGbpContractNextHop(sep5.vmac, sep5.epg.bd,
4102 sep5.ip6, sep5.epg.rd)])],
4103 [ETH_P_IP, ETH_P_IPV6]).add_vpp_config()
4105 # packets from unknown EP 221 to known EP in EPG 222
4106 # should be redirected to known remote SEP
4107 base = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
4108 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
4109 UDP(sport=1234, dport=48879) /
4110 VXLAN(vni=444, gpid=441, flags=0x88) /
4111 Ether(src="00:22:22:22:22:44", dst=str(self.router_mac)))
4113 IP(src="10.0.1.100", dst=ep3.ip4) /
4114 UDP(sport=1234, dport=1234) /
4115 Raw(b'\xa5' * 100)),
4117 IPv6(src="2001:10::100", dst=ep3.ip6) /
4118 UDP(sport=1234, dport=1234) /
4119 Raw(b'\xa5' * 100))]
4121 # unknown remote EP to local EP redirected to known remote SEP
4122 rxs = self.send_and_expect(self.pg7, p, self.pg7)
4124 for rx, tx in zip(rxs, p):
4125 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4126 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4127 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4128 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4129 # this should use the programmed remote leaf TEP
4130 self.assertEqual(rx[VXLAN].vni, 555)
4131 self.assertEqual(rx[VXLAN].gpid, epg_221.sclass)
4132 self.assertTrue(rx[VXLAN].flags.G)
4133 self.assertTrue(rx[VXLAN].flags.Instance)
4134 # redirect policy has been applied
4135 self.assertTrue(rx[VXLAN].gpflags.A)
4136 self.assertFalse(rx[VXLAN].gpflags.D)
4137 rxip = rx[VXLAN][Ether].payload
4138 txip = tx[VXLAN][Ether].payload
4139 self.assertEqual(rxip.src, txip.src)
4140 self.assertEqual(rxip.dst, txip.dst)
4142 # endpoint learnt via the parent GBP-vxlan interface
4143 self.assertTrue(find_gbp_endpoint(self,
4144 vx_tun_l3._sw_if_index,
4146 self.assertTrue(find_gbp_endpoint(self,
4147 vx_tun_l3._sw_if_index,
4150 # remote SEP: it is now an unknown remote SEP and should go
4152 sep5.remove_vpp_config()
4154 # remote EP (coming from spine proxy) to local EP redirected to
4156 rxs = self.send_and_expect(self.pg7, p, self.pg7)
4158 for rx, tx in zip(rxs, p):
4159 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4160 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4161 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4162 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4163 # this should use the spine proxy TEP
4164 self.assertEqual(rx[VXLAN].vni, epg_320.bd.uu_fwd.vni)
4165 self.assertEqual(rx[VXLAN].gpid, epg_221.sclass)
4166 self.assertTrue(rx[VXLAN].flags.G)
4167 self.assertTrue(rx[VXLAN].flags.Instance)
4168 # redirect policy has been applied
4169 self.assertTrue(rx[VXLAN].gpflags.A)
4170 self.assertFalse(rx[VXLAN].gpflags.D)
4171 rxip = rx[VXLAN][Ether].payload
4172 txip = tx[VXLAN][Ether].payload
4173 self.assertEqual(rxip.src, txip.src)
4174 self.assertEqual(rxip.dst, txip.dst)
4179 self.pg7.unconfig_ip4()
4181 def test_gbp_redirect_extended(self):
4182 """ GBP Endpoint Redirect Extended """
4184 self.vapi.cli("set logging class gbp level debug")
4186 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
4187 routed_dst_mac = "00:0c:0c:0c:0c:0c"
4188 routed_src_mac = "00:22:bd:f8:19:ff"
4190 learnt = [{'mac': '00:00:11:11:11:02',
4192 'ip6': '2001:10::2'},
4193 {'mac': '00:00:11:11:11:03',
4195 'ip6': '2001:10::3'}]
4200 t4 = VppIpTable(self, 1)
4202 t6 = VppIpTable(self, 1, True)
4205 # create IPv4 and IPv6 RD UU VxLAN-GBP TEP and bind them to the right
4207 rd_uu4 = VppVxlanGbpTunnel(
4210 self.pg7.remote_ip4,
4212 mode=(VppEnum.vl_api_vxlan_gbp_api_tunnel_mode_t.
4213 VXLAN_GBP_API_TUNNEL_MODE_L3))
4214 rd_uu4.add_vpp_config()
4215 VppIpInterfaceBind(self, rd_uu4, t4).add_vpp_config()
4217 rd_uu6 = VppVxlanGbpTunnel(
4220 self.pg7.remote_ip4,
4222 mode=(VppEnum.vl_api_vxlan_gbp_api_tunnel_mode_t.
4223 VXLAN_GBP_API_TUNNEL_MODE_L3))
4224 rd_uu6.add_vpp_config()
4225 VppIpInterfaceBind(self, rd_uu6, t4).add_vpp_config()
4227 rd1 = VppGbpRouteDomain(self, 2, 402, t4, t6, rd_uu4, rd_uu6)
4228 rd1.add_vpp_config()
4230 self.loop0.set_mac(self.router_mac)
4231 self.loop1.set_mac(self.router_mac)
4232 self.loop2.set_mac(self.router_mac)
4235 # Bind the BVI to the RD
4237 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
4238 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
4239 VppIpInterfaceBind(self, self.loop1, t4).add_vpp_config()
4240 VppIpInterfaceBind(self, self.loop1, t6).add_vpp_config()
4241 VppIpInterfaceBind(self, self.loop2, t4).add_vpp_config()
4242 VppIpInterfaceBind(self, self.loop2, t6).add_vpp_config()
4245 # Pg7 hosts a BD's UU-fwd
4247 self.pg7.config_ip4()
4248 self.pg7.resolve_arp()
4251 # a GBP bridge domains for the EPs
4253 bd1 = VppBridgeDomain(self, 1)
4254 bd1.add_vpp_config()
4255 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0)
4256 gbd1.add_vpp_config()
4258 bd2 = VppBridgeDomain(self, 2)
4259 bd2.add_vpp_config()
4260 gbd2 = VppGbpBridgeDomain(self, bd2, rd1, self.loop1)
4261 gbd2.add_vpp_config()
4263 # ... and has a /32 and /128 applied
4264 ip4_addr1 = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
4265 ip4_addr1.add_vpp_config()
4266 ip6_addr1 = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 128)
4267 ip6_addr1.add_vpp_config()
4268 ip4_addr2 = VppIpInterfaceAddress(self, gbd2.bvi, "10.0.1.128", 32)
4269 ip4_addr2.add_vpp_config()
4270 ip6_addr2 = VppIpInterfaceAddress(self, gbd2.bvi, "2001:11::128", 128)
4271 ip6_addr2.add_vpp_config()
4274 # The Endpoint-groups
4276 epg_220 = VppGbpEndpointGroup(self, 220, 440, rd1, gbd1,
4280 VppGbpEndpointRetention(2))
4281 epg_220.add_vpp_config()
4282 epg_221 = VppGbpEndpointGroup(self, 221, 441, rd1, gbd2,
4286 VppGbpEndpointRetention(2))
4287 epg_221.add_vpp_config()
4290 # a GBP bridge domains for the SEPs
4292 bd_uu3 = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
4293 self.pg7.remote_ip4, 116)
4294 bd_uu3.add_vpp_config()
4296 bd3 = VppBridgeDomain(self, 3)
4297 bd3.add_vpp_config()
4298 gbd3 = VppGbpBridgeDomain(self, bd3, rd1, self.loop2,
4299 bd_uu3, learn=False)
4300 gbd3.add_vpp_config()
4302 ip4_addr3 = VppIpInterfaceAddress(self, gbd3.bvi, "12.0.0.128", 32)
4303 ip4_addr3.add_vpp_config()
4304 ip6_addr3 = VppIpInterfaceAddress(self, gbd3.bvi, "4001:10::128", 128)
4305 ip6_addr3.add_vpp_config()
4308 # self.logger.info(self.vapi.cli("show gbp bridge"))
4309 # self.logger.info(self.vapi.cli("show vxlan-gbp tunnel"))
4310 # self.logger.info(self.vapi.cli("show gbp vxlan"))
4311 # self.logger.info(self.vapi.cli("show int addr"))
4315 # EPGs in which the service endpoints exist
4317 epg_320 = VppGbpEndpointGroup(self, 320, 550, rd1, gbd3,
4321 VppGbpEndpointRetention(2))
4322 epg_320.add_vpp_config()
4327 ep1 = VppGbpEndpoint(self, self.pg0,
4329 "10.0.0.1", "11.0.0.1",
4330 "2001:10::1", "3001:10::1")
4331 ep1.add_vpp_config()
4332 ep2 = VppGbpEndpoint(self, self.pg1,
4334 "10.0.1.1", "11.0.1.1",
4335 "2001:11::1", "3001:11::1")
4336 ep2.add_vpp_config()
4341 sep1 = VppGbpEndpoint(self, self.pg3,
4343 "12.0.0.1", "13.0.0.1",
4344 "4001:10::1", "5001:10::1")
4345 sep2 = VppGbpEndpoint(self, self.pg4,
4347 "12.0.0.2", "13.0.0.2",
4348 "4001:10::2", "5001:10::2")
4350 # sep1 and sep2 are not added to config yet
4351 # they are unknown for now
4354 # add routes to EPG subnets
4356 VppGbpSubnet(self, rd1, "10.0.0.0", 24,
4357 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT
4359 VppGbpSubnet(self, rd1, "10.0.1.0", 24,
4360 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT
4364 # Local host to known local host in different BD
4365 # with SFC contract (source and destination are in
4366 # one node and service endpoint in another node)
4368 p4 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
4369 IP(src=ep1.ip4, dst=ep2.ip4) /
4370 UDP(sport=1234, dport=1234) /
4371 Raw(b'\xa5' * 100)),
4372 (Ether(src=ep2.mac, dst=str(self.router_mac)) /
4373 IP(src=ep2.ip4, dst=ep1.ip4) /
4374 UDP(sport=1234, dport=1234) /
4375 Raw(b'\xa5' * 100))]
4376 p6 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
4377 IPv6(src=ep1.ip6, dst=ep2.ip6) /
4378 UDP(sport=1234, dport=1234) /
4379 Raw(b'\xa5' * 100)),
4380 (Ether(src=ep2.mac, dst=str(self.router_mac)) /
4381 IPv6(src=ep2.ip6, dst=ep1.ip6) /
4382 UDP(sport=1234, dport=1230) /
4383 Raw(b'\xa5' * 100))]
4385 # should be dropped since no contract yet
4386 self.send_and_assert_no_replies(self.pg0, [p4[0]])
4387 self.send_and_assert_no_replies(self.pg0, [p6[0]])
4390 # Add a contract with a rule to load-balance redirect via SEP1 and SEP2
4391 # one of the next-hops is via an EP that is not known
4393 acl = VppGbpAcl(self)
4394 rule4 = acl.create_rule(permit_deny=1, proto=17)
4395 rule6 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
4396 acl_index = acl.add_vpp_config([rule4, rule6])
4399 # test the src-ip hash mode
4401 c1 = VppGbpContract(
4402 self, 402, epg_220.sclass, epg_221.sclass, acl_index,
4403 [VppGbpContractRule(
4404 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4405 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
4406 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
4407 sep1.ip4, sep1.epg.rd)]),
4409 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4410 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
4411 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
4412 sep1.ip6, sep1.epg.rd)])],
4413 [ETH_P_IP, ETH_P_IPV6])
4416 c2 = VppGbpContract(
4417 self, 402, epg_221.sclass, epg_220.sclass, acl_index,
4418 [VppGbpContractRule(
4419 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4420 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
4421 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
4422 sep1.ip4, sep1.epg.rd)]),
4424 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4425 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
4426 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
4427 sep1.ip6, sep1.epg.rd)])],
4428 [ETH_P_IP, ETH_P_IPV6])
4431 # ep1 <--> ep2 redirected through sep1
4433 # packet is redirected to sep bd and then go through sep bd UU
4435 rxs = self.send_and_expect(self.pg0, p4[0] * 17, self.pg7)
4438 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4439 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4440 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4441 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4442 self.assertEqual(rx[VXLAN].vni, 116)
4443 self.assertTrue(rx[VXLAN].flags.G)
4444 self.assertTrue(rx[VXLAN].flags.Instance)
4445 # redirect policy has been applied
4446 self.assertTrue(rx[VXLAN].gpflags.A)
4447 self.assertFalse(rx[VXLAN].gpflags.D)
4449 inner = rx[VXLAN].payload
4451 self.assertEqual(inner[Ether].src, routed_src_mac)
4452 self.assertEqual(inner[Ether].dst, sep1.mac)
4453 self.assertEqual(inner[IP].src, ep1.ip4)
4454 self.assertEqual(inner[IP].dst, ep2.ip4)
4456 rxs = self.send_and_expect(self.pg1, p4[1] * 17, self.pg7)
4459 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4460 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4461 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4462 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4463 self.assertEqual(rx[VXLAN].vni, 116)
4464 self.assertTrue(rx[VXLAN].flags.G)
4465 self.assertTrue(rx[VXLAN].flags.Instance)
4466 # redirect policy has been applied
4467 self.assertTrue(rx[VXLAN].gpflags.A)
4468 self.assertFalse(rx[VXLAN].gpflags.D)
4470 inner = rx[VXLAN].payload
4472 self.assertEqual(inner[Ether].src, routed_src_mac)
4473 self.assertEqual(inner[Ether].dst, sep1.mac)
4474 self.assertEqual(inner[IP].src, ep2.ip4)
4475 self.assertEqual(inner[IP].dst, ep1.ip4)
4477 rxs = self.send_and_expect(self.pg0, p6[0] * 17, self.pg7)
4480 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4481 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4482 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4483 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4484 self.assertEqual(rx[VXLAN].vni, 116)
4485 self.assertTrue(rx[VXLAN].flags.G)
4486 self.assertTrue(rx[VXLAN].flags.Instance)
4487 # redirect policy has been applied
4488 inner = rx[VXLAN].payload
4490 self.assertEqual(inner[Ether].src, routed_src_mac)
4491 self.assertEqual(inner[Ether].dst, sep1.mac)
4492 self.assertEqual(inner[IPv6].src, ep1.ip6)
4493 self.assertEqual(inner[IPv6].dst, ep2.ip6)
4495 rxs = self.send_and_expect(self.pg1, p6[1] * 17, self.pg7)
4498 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4499 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4500 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4501 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4502 self.assertEqual(rx[VXLAN].vni, 116)
4503 self.assertTrue(rx[VXLAN].flags.G)
4504 self.assertTrue(rx[VXLAN].flags.Instance)
4505 # redirect policy has been applied
4506 self.assertTrue(rx[VXLAN].gpflags.A)
4507 self.assertFalse(rx[VXLAN].gpflags.D)
4509 inner = rx[VXLAN].payload
4511 self.assertEqual(inner[Ether].src, routed_src_mac)
4512 self.assertEqual(inner[Ether].dst, sep1.mac)
4513 self.assertEqual(inner[IPv6].src, ep2.ip6)
4514 self.assertEqual(inner[IPv6].dst, ep1.ip6)
4516 # configure sep1: it is now local
4517 # packets between ep1 and ep2 are redirected locally
4518 sep1.add_vpp_config()
4520 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
4523 self.assertEqual(rx[Ether].src, routed_src_mac)
4524 self.assertEqual(rx[Ether].dst, sep1.mac)
4525 self.assertEqual(rx[IP].src, ep1.ip4)
4526 self.assertEqual(rx[IP].dst, ep2.ip4)
4528 rxs = self.send_and_expect(self.pg1, p6[1] * 17, sep1.itf)
4531 self.assertEqual(rx[Ether].src, routed_src_mac)
4532 self.assertEqual(rx[Ether].dst, sep1.mac)
4533 self.assertEqual(rx[IPv6].src, ep2.ip6)
4534 self.assertEqual(rx[IPv6].dst, ep1.ip6)
4536 # packet coming from the l2 spine-proxy to sep1
4537 p = (Ether(src=self.pg7.remote_mac,
4538 dst=self.pg7.local_mac) /
4539 IP(src=self.pg7.remote_ip4,
4540 dst=self.pg7.local_ip4) /
4541 UDP(sport=1234, dport=48879) /
4542 VXLAN(vni=116, gpid=440, gpflags=0x08, flags=0x88) /
4543 Ether(src=str(self.router_mac), dst=sep1.mac) /
4544 IP(src=ep1.ip4, dst=ep2.ip4) /
4545 UDP(sport=1234, dport=1234) /
4548 rxs = self.send_and_expect(self.pg7, [p] * 17, sep1.itf)
4551 self.assertEqual(rx[Ether].src, str(self.router_mac))
4552 self.assertEqual(rx[Ether].dst, sep1.mac)
4553 self.assertEqual(rx[IP].src, ep1.ip4)
4554 self.assertEqual(rx[IP].dst, ep2.ip4)
4556 # contract for SEP to communicate with dst EP
4557 c3 = VppGbpContract(
4558 self, 402, epg_320.sclass, epg_221.sclass, acl_index,
4559 [VppGbpContractRule(
4560 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4561 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC),
4563 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4564 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC)],
4565 [ETH_P_IP, ETH_P_IPV6])
4568 # temporarily remove ep2, so that ep2 is remote & unknown
4569 ep2.remove_vpp_config()
4571 # packet going back from sep1 to its original dest (ep2)
4572 # as ep2 is now unknown (see above), it must go through
4573 # the rd UU (packet is routed)
4575 p1 = (Ether(src=sep1.mac, dst=self.router_mac) /
4576 IP(src=ep1.ip4, dst=ep2.ip4) /
4577 UDP(sport=1234, dport=1234) /
4580 rxs = self.send_and_expect(self.pg3, [p1] * 17, self.pg7)
4583 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4584 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4585 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4586 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4587 self.assertEqual(rx[VXLAN].vni, 114)
4588 self.assertTrue(rx[VXLAN].flags.G)
4589 self.assertTrue(rx[VXLAN].flags.Instance)
4590 # redirect policy has been applied
4591 inner = rx[VXLAN].payload
4592 self.assertEqual(inner[Ether].src, routed_src_mac)
4593 self.assertEqual(inner[Ether].dst, routed_dst_mac)
4594 self.assertEqual(inner[IP].src, ep1.ip4)
4595 self.assertEqual(inner[IP].dst, ep2.ip4)
4597 self.logger.info(self.vapi.cli("show bridge 3 detail"))
4598 sep1.remove_vpp_config()
4600 self.logger.info(self.vapi.cli("show bridge 1 detail"))
4601 self.logger.info(self.vapi.cli("show bridge 2 detail"))
4603 # re-add ep2: it is local again :)
4604 ep2.add_vpp_config()
4606 # packet coming back from the remote sep through rd UU
4607 p2 = (Ether(src=self.pg7.remote_mac,
4608 dst=self.pg7.local_mac) /
4609 IP(src=self.pg7.remote_ip4,
4610 dst=self.pg7.local_ip4) /
4611 UDP(sport=1234, dport=48879) /
4612 VXLAN(vni=114, gpid=441, gpflags=0x09, flags=0x88) /
4613 Ether(src=str(self.router_mac), dst=self.router_mac) /
4614 IP(src=ep1.ip4, dst=ep2.ip4) /
4615 UDP(sport=1234, dport=1234) /
4618 rxs = self.send_and_expect(self.pg7, [p2], self.pg1)
4621 self.assertEqual(rx[Ether].src, str(self.router_mac))
4622 self.assertEqual(rx[Ether].dst, self.pg1.remote_mac)
4623 self.assertEqual(rx[IP].src, ep1.ip4)
4624 self.assertEqual(rx[IP].dst, ep2.ip4)
4627 # bd_uu2.add_vpp_config()
4633 c1.remove_vpp_config()
4634 c2.remove_vpp_config()
4635 c3.remove_vpp_config()
4636 self.pg7.unconfig_ip4()
4638 def test_gbp_l3_out(self):
4641 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
4642 self.vapi.cli("set logging class gbp level debug")
4644 routed_dst_mac = "00:0c:0c:0c:0c:0c"
4645 routed_src_mac = "00:22:bd:f8:19:ff"
4650 t4 = VppIpTable(self, 1)
4652 t6 = VppIpTable(self, 1, True)
4655 rd1 = VppGbpRouteDomain(self, 2, 55, t4, t6)
4656 rd1.add_vpp_config()
4658 self.loop0.set_mac(self.router_mac)
4661 # Bind the BVI to the RD
4663 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
4664 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
4667 # Pg7 hosts a BD's BUM
4668 # Pg1 some other l3 interface
4670 self.pg7.config_ip4()
4671 self.pg7.resolve_arp()
4674 # a multicast vxlan-gbp tunnel for broadcast in the BD
4676 tun_bm = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
4679 tun_bm.add_vpp_config()
4682 # a GBP external bridge domains for the EPs
4684 bd1 = VppBridgeDomain(self, 1)
4685 bd1.add_vpp_config()
4686 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0, None, tun_bm)
4687 gbd1.add_vpp_config()
4690 # The Endpoint-groups in which the external endpoints exist
4692 epg_220 = VppGbpEndpointGroup(self, 220, 113, rd1, gbd1,
4696 VppGbpEndpointRetention(2))
4697 epg_220.add_vpp_config()
4699 # the BVIs have the subnets applied ...
4700 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 24)
4701 ip4_addr.add_vpp_config()
4702 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 64)
4703 ip6_addr.add_vpp_config()
4705 # ... which are L3-out subnets
4706 l3o_1 = VppGbpSubnet(
4707 self, rd1, "10.0.0.0", 24,
4708 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
4710 l3o_1.add_vpp_config()
4713 # an external interface attached to the outside world and the
4716 VppL2Vtr(self, self.vlan_100, L2_VTR_OP.L2_POP_1).add_vpp_config()
4717 VppL2Vtr(self, self.vlan_101, L2_VTR_OP.L2_POP_1).add_vpp_config()
4718 vlan_144 = VppDot1QSubint(self, self.pg0, 144)
4720 # vlan_102 is not poped
4723 # an unicast vxlan-gbp for inter-RD traffic
4725 vx_tun_l3 = VppGbpVxlanTunnel(
4726 self, 444, rd1.rd_id,
4727 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
4729 vx_tun_l3.add_vpp_config()
4732 # External Endpoints
4734 eep1 = VppGbpEndpoint(self, self.vlan_100,
4736 "10.0.0.1", "11.0.0.1",
4737 "2001:10::1", "3001::1",
4738 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
4739 eep1.add_vpp_config()
4740 eep2 = VppGbpEndpoint(self, self.vlan_101,
4742 "10.0.0.2", "11.0.0.2",
4743 "2001:10::2", "3001::2",
4744 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
4745 eep2.add_vpp_config()
4746 eep3 = VppGbpEndpoint(self, self.vlan_102,
4748 "10.0.0.3", "11.0.0.3",
4749 "2001:10::3", "3001::3",
4750 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
4751 eep3.add_vpp_config()
4754 # A remote external endpoint
4756 rep = VppGbpEndpoint(self, vx_tun_l3,
4758 "10.0.0.101", "11.0.0.101",
4759 "2001:10::101", "3001::101",
4760 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
4762 self.pg7.remote_ip4,
4764 rep.add_vpp_config()
4767 # EP1 impersonating EP3 is dropped
4769 p = (Ether(src=eep1.mac, dst="ff:ff:ff:ff:ff:ff") /
4772 psrc="10.0.0.3", pdst="10.0.0.128",
4773 hwsrc=eep1.mac, hwdst="ff:ff:ff:ff:ff:ff"))
4774 self.send_and_assert_no_replies(self.pg0, p)
4777 # ARP packet from External EPs are accepted and replied to
4779 p_arp = (Ether(src=eep1.mac, dst="ff:ff:ff:ff:ff:ff") /
4782 psrc=eep1.ip4, pdst="10.0.0.128",
4783 hwsrc=eep1.mac, hwdst="ff:ff:ff:ff:ff:ff"))
4784 rxs = self.send_and_expect(self.pg0, p_arp * 1, self.pg0)
4787 # ARP packet from host in remote subnet are accepted and replied to
4789 p_arp = (Ether(src=eep3.mac, dst="ff:ff:ff:ff:ff:ff") /
4792 psrc=eep3.ip4, pdst="10.0.0.128",
4793 hwsrc=eep3.mac, hwdst="ff:ff:ff:ff:ff:ff"))
4794 rxs = self.send_and_expect(self.pg0, p_arp * 1, self.pg0)
4797 # packets destined to unknown addresses in the BVI's subnet
4800 p4 = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
4802 IP(src="10.0.0.1", dst="10.0.0.88") /
4803 UDP(sport=1234, dport=1234) /
4805 p6 = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
4807 IPv6(src="2001:10::1", dst="2001:10::88") /
4808 UDP(sport=1234, dport=1234) /
4811 rxs = self.send_and_expect(self.pg0, p4 * 1, self.pg7)
4814 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4815 # self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4816 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4817 self.assertEqual(rx[IP].dst, "239.1.1.1")
4818 self.assertEqual(rx[VXLAN].vni, 88)
4819 self.assertTrue(rx[VXLAN].flags.G)
4820 self.assertTrue(rx[VXLAN].flags.Instance)
4821 # policy was applied to the original IP packet
4822 self.assertEqual(rx[VXLAN].gpid, 113)
4823 self.assertTrue(rx[VXLAN].gpflags.A)
4824 self.assertFalse(rx[VXLAN].gpflags.D)
4826 inner = rx[VXLAN].payload
4828 self.assertTrue(inner.haslayer(ARP))
4831 # remote to external
4833 p = (Ether(src=self.pg7.remote_mac,
4834 dst=self.pg7.local_mac) /
4835 IP(src=self.pg7.remote_ip4,
4836 dst=self.pg7.local_ip4) /
4837 UDP(sport=1234, dport=48879) /
4838 VXLAN(vni=444, gpid=113, flags=0x88) /
4839 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
4840 IP(src="10.0.0.101", dst="10.0.0.1") /
4841 UDP(sport=1234, dport=1234) /
4844 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
4847 # local EP pings router
4849 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
4851 IP(src=eep1.ip4, dst="10.0.0.128") /
4852 ICMP(type='echo-request'))
4854 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
4857 self.assertEqual(rx[Ether].src, str(self.router_mac))
4858 self.assertEqual(rx[Ether].dst, eep1.mac)
4859 self.assertEqual(rx[Dot1Q].vlan, 100)
4862 # local EP pings other local EP
4864 p = (Ether(src=eep1.mac, dst=eep2.mac) /
4866 IP(src=eep1.ip4, dst=eep2.ip4) /
4867 ICMP(type='echo-request'))
4869 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
4872 self.assertEqual(rx[Ether].src, eep1.mac)
4873 self.assertEqual(rx[Ether].dst, eep2.mac)
4874 self.assertEqual(rx[Dot1Q].vlan, 101)
4877 # local EP pings router w/o vlan tag poped
4879 p = (Ether(src=eep3.mac, dst=str(self.router_mac)) /
4881 IP(src=eep3.ip4, dst="10.0.0.128") /
4882 ICMP(type='echo-request'))
4884 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
4887 self.assertEqual(rx[Ether].src, str(self.router_mac))
4888 self.assertEqual(rx[Ether].dst, self.vlan_102.remote_mac)
4891 # A ip4 subnet reachable through the external EP1
4893 ip_220 = VppIpRoute(self, "10.220.0.0", 24,
4894 [VppRoutePath(eep1.ip4,
4895 eep1.epg.bvi.sw_if_index)],
4896 table_id=t4.table_id)
4897 ip_220.add_vpp_config()
4899 l3o_220 = VppGbpSubnet(
4900 self, rd1, "10.220.0.0", 24,
4901 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
4903 l3o_220.add_vpp_config()
4906 # An ip6 subnet reachable through the external EP1
4908 ip6_220 = VppIpRoute(self, "10:220::", 64,
4909 [VppRoutePath(eep1.ip6,
4910 eep1.epg.bvi.sw_if_index)],
4911 table_id=t6.table_id)
4912 ip6_220.add_vpp_config()
4914 l3o6_220 = VppGbpSubnet(
4915 self, rd1, "10:220::", 64,
4916 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
4918 l3o6_220.add_vpp_config()
4921 # A subnet reachable through the external EP2
4923 ip_221 = VppIpRoute(self, "10.221.0.0", 24,
4924 [VppRoutePath(eep2.ip4,
4925 eep2.epg.bvi.sw_if_index)],
4926 table_id=t4.table_id)
4927 ip_221.add_vpp_config()
4929 l3o_221 = VppGbpSubnet(
4930 self, rd1, "10.221.0.0", 24,
4931 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
4933 l3o_221.add_vpp_config()
4936 # ping between hosts in remote subnets
4937 # dropped without a contract
4939 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
4941 IP(src="10.220.0.1", dst="10.221.0.1") /
4942 ICMP(type='echo-request'))
4944 self.send_and_assert_no_replies(self.pg0, p * 1)
4947 # contract for the external nets to communicate
4949 acl = VppGbpAcl(self)
4950 rule4 = acl.create_rule(permit_deny=1, proto=17)
4951 rule6 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
4952 acl_index = acl.add_vpp_config([rule4, rule6])
4955 # A contract with the wrong scope is not matched
4957 c_44 = VppGbpContract(
4958 self, 44, 4220, 4221, acl_index,
4959 [VppGbpContractRule(
4960 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4961 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4964 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4965 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4967 [ETH_P_IP, ETH_P_IPV6])
4968 c_44.add_vpp_config()
4969 self.send_and_assert_no_replies(self.pg0, p * 1)
4971 c1 = VppGbpContract(
4972 self, 55, 4220, 4221, acl_index,
4973 [VppGbpContractRule(
4974 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4975 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4978 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4979 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4981 [ETH_P_IP, ETH_P_IPV6])
4985 # Contracts allowing ext-net 200 to talk with external EPs
4987 c2 = VppGbpContract(
4988 self, 55, 4220, 113, acl_index,
4989 [VppGbpContractRule(
4990 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4991 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4994 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4995 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4997 [ETH_P_IP, ETH_P_IPV6])
4999 c3 = VppGbpContract(
5000 self, 55, 113, 4220, acl_index,
5001 [VppGbpContractRule(
5002 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5003 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5006 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5007 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5009 [ETH_P_IP, ETH_P_IPV6])
5013 # ping between hosts in remote subnets
5015 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
5017 IP(src="10.220.0.1", dst="10.221.0.1") /
5018 UDP(sport=1234, dport=1234) /
5021 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
5024 self.assertEqual(rx[Ether].src, str(self.router_mac))
5025 self.assertEqual(rx[Ether].dst, eep2.mac)
5026 self.assertEqual(rx[Dot1Q].vlan, 101)
5028 # we did not learn these external hosts
5029 self.assertFalse(find_gbp_endpoint(self, ip="10.220.0.1"))
5030 self.assertFalse(find_gbp_endpoint(self, ip="10.221.0.1"))
5033 # from remote external EP to local external EP
5035 p = (Ether(src=self.pg7.remote_mac,
5036 dst=self.pg7.local_mac) /
5037 IP(src=self.pg7.remote_ip4,
5038 dst=self.pg7.local_ip4) /
5039 UDP(sport=1234, dport=48879) /
5040 VXLAN(vni=444, gpid=113, flags=0x88) /
5041 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
5042 IP(src="10.0.0.101", dst="10.220.0.1") /
5043 UDP(sport=1234, dport=1234) /
5046 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
5049 # ping from an external host to the remote external EP
5051 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
5053 IP(src="10.220.0.1", dst=rep.ip4) /
5054 UDP(sport=1234, dport=1234) /
5057 rxs = self.send_and_expect(self.pg0, p * 1, self.pg7)
5060 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
5061 # self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
5062 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
5063 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
5064 self.assertEqual(rx[VXLAN].vni, 444)
5065 self.assertTrue(rx[VXLAN].flags.G)
5066 self.assertTrue(rx[VXLAN].flags.Instance)
5067 # the sclass of the ext-net the packet came from
5068 self.assertEqual(rx[VXLAN].gpid, 4220)
5069 # policy was applied to the original IP packet
5070 self.assertTrue(rx[VXLAN].gpflags.A)
5071 # since it's an external host the reciever should not learn it
5072 self.assertTrue(rx[VXLAN].gpflags.D)
5073 inner = rx[VXLAN].payload
5074 self.assertEqual(inner[IP].src, "10.220.0.1")
5075 self.assertEqual(inner[IP].dst, rep.ip4)
5078 # An external subnet reachable via the remote external EP
5082 # first the VXLAN-GBP tunnel over which it is reached
5084 vx_tun_r1 = VppVxlanGbpTunnel(
5085 self, self.pg7.local_ip4,
5086 self.pg7.remote_ip4, 445,
5087 mode=(VppEnum.vl_api_vxlan_gbp_api_tunnel_mode_t.
5088 VXLAN_GBP_API_TUNNEL_MODE_L3))
5089 vx_tun_r1.add_vpp_config()
5090 VppIpInterfaceBind(self, vx_tun_r1, t4).add_vpp_config()
5092 self.logger.info(self.vapi.cli("sh vxlan-gbp tunnel"))
5095 # then the special adj to resolve through on that tunnel
5097 n1 = VppNeighbor(self,
5098 vx_tun_r1.sw_if_index,
5099 "00:0c:0c:0c:0c:0c",
5100 self.pg7.remote_ip4)
5104 # the route via the adj above
5106 ip_222 = VppIpRoute(self, "10.222.0.0", 24,
5107 [VppRoutePath(self.pg7.remote_ip4,
5108 vx_tun_r1.sw_if_index)],
5109 table_id=t4.table_id)
5110 ip_222.add_vpp_config()
5112 l3o_222 = VppGbpSubnet(
5113 self, rd1, "10.222.0.0", 24,
5114 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
5116 l3o_222.add_vpp_config()
5119 # ping between hosts in local and remote external subnets
5120 # dropped without a contract
5122 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
5124 IP(src="10.220.0.1", dst="10.222.0.1") /
5125 UDP(sport=1234, dport=1234) /
5128 rxs = self.send_and_assert_no_replies(self.pg0, p * 1)
5131 # Add contracts ext-nets for 220 -> 222
5133 c4 = VppGbpContract(
5134 self, 55, 4220, 4222, acl_index,
5135 [VppGbpContractRule(
5136 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5137 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5140 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5141 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5143 [ETH_P_IP, ETH_P_IPV6])
5147 # ping from host in local to remote external subnets
5149 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
5151 IP(src="10.220.0.1", dst="10.222.0.1") /
5152 UDP(sport=1234, dport=1234) /
5155 rxs = self.send_and_expect(self.pg0, p * 3, self.pg7)
5158 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
5159 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
5160 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
5161 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
5162 self.assertEqual(rx[VXLAN].vni, 445)
5163 self.assertTrue(rx[VXLAN].flags.G)
5164 self.assertTrue(rx[VXLAN].flags.Instance)
5165 # the sclass of the ext-net the packet came from
5166 self.assertEqual(rx[VXLAN].gpid, 4220)
5167 # policy was applied to the original IP packet
5168 self.assertTrue(rx[VXLAN].gpflags.A)
5169 # since it's an external host the reciever should not learn it
5170 self.assertTrue(rx[VXLAN].gpflags.D)
5171 inner = rx[VXLAN].payload
5172 self.assertEqual(inner[Ether].dst, "00:0c:0c:0c:0c:0c")
5173 self.assertEqual(inner[IP].src, "10.220.0.1")
5174 self.assertEqual(inner[IP].dst, "10.222.0.1")
5177 # make the external subnet ECMP
5179 vx_tun_r2 = VppVxlanGbpTunnel(
5180 self, self.pg7.local_ip4,
5181 self.pg7.remote_ip4, 446,
5182 mode=(VppEnum.vl_api_vxlan_gbp_api_tunnel_mode_t.
5183 VXLAN_GBP_API_TUNNEL_MODE_L3))
5184 vx_tun_r2.add_vpp_config()
5185 VppIpInterfaceBind(self, vx_tun_r2, t4).add_vpp_config()
5187 self.logger.info(self.vapi.cli("sh vxlan-gbp tunnel"))
5189 n2 = VppNeighbor(self,
5190 vx_tun_r2.sw_if_index,
5191 "00:0c:0c:0c:0c:0c",
5192 self.pg7.remote_ip4)
5195 ip_222.modify([VppRoutePath(self.pg7.remote_ip4,
5196 vx_tun_r1.sw_if_index),
5197 VppRoutePath(self.pg7.remote_ip4,
5198 vx_tun_r2.sw_if_index)])
5201 # now expect load-balance
5203 p = [(Ether(src=eep1.mac, dst=str(self.router_mac)) /
5205 IP(src="10.220.0.1", dst="10.222.0.1") /
5206 UDP(sport=1234, dport=1234) /
5207 Raw(b'\xa5' * 100)),
5208 (Ether(src=eep1.mac, dst=str(self.router_mac)) /
5210 IP(src="10.220.0.1", dst="10.222.0.1") /
5211 UDP(sport=1222, dport=1235) /
5212 Raw(b'\xa5' * 100))]
5214 rxs = self.send_and_expect(self.pg0, p, self.pg7)
5216 self.assertEqual(rxs[0][VXLAN].vni, 445)
5217 self.assertEqual(rxs[1][VXLAN].vni, 446)
5220 # Same LB test for v6
5222 n3 = VppNeighbor(self,
5223 vx_tun_r1.sw_if_index,
5224 "00:0c:0c:0c:0c:0c",
5225 self.pg7.remote_ip6)
5227 n4 = VppNeighbor(self,
5228 vx_tun_r2.sw_if_index,
5229 "00:0c:0c:0c:0c:0c",
5230 self.pg7.remote_ip6)
5233 ip_222_6 = VppIpRoute(self, "10:222::", 64,
5234 [VppRoutePath(self.pg7.remote_ip6,
5235 vx_tun_r1.sw_if_index),
5236 VppRoutePath(self.pg7.remote_ip6,
5237 vx_tun_r2.sw_if_index)],
5238 table_id=t6.table_id)
5239 ip_222_6.add_vpp_config()
5241 l3o_222_6 = VppGbpSubnet(
5242 self, rd1, "10:222::", 64,
5243 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
5245 l3o_222_6.add_vpp_config()
5247 p = [(Ether(src=eep1.mac, dst=str(self.router_mac)) /
5249 IPv6(src="10:220::1", dst="10:222::1") /
5250 UDP(sport=1234, dport=1234) /
5251 Raw(b'\xa5' * 100)),
5252 (Ether(src=eep1.mac, dst=str(self.router_mac)) /
5254 IPv6(src="10:220::1", dst="10:222::1") /
5255 UDP(sport=7777, dport=8881) /
5256 Raw(b'\xa5' * 100))]
5258 self.logger.info(self.vapi.cli("sh ip6 fib 10:222::1"))
5259 rxs = self.send_and_expect(self.pg0, p, self.pg7)
5261 self.assertEqual(rxs[0][VXLAN].vni, 445)
5262 self.assertEqual(rxs[1][VXLAN].vni, 446)
5265 # ping from host in remote to local external subnets
5266 # there's no contract for this, but the A bit is set.
5268 p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
5269 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
5270 UDP(sport=1234, dport=48879) /
5271 VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
5272 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
5273 IP(src="10.222.0.1", dst="10.220.0.1") /
5274 UDP(sport=1234, dport=1234) /
5277 rxs = self.send_and_expect(self.pg7, p * 3, self.pg0)
5278 self.assertFalse(find_gbp_endpoint(self, ip="10.222.0.1"))
5281 # ping from host in remote to remote external subnets
5282 # this is dropped by reflection check.
5284 p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
5285 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
5286 UDP(sport=1234, dport=48879) /
5287 VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
5288 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
5289 IP(src="10.222.0.1", dst="10.222.0.2") /
5290 UDP(sport=1234, dport=1234) /
5293 rxs = self.send_and_assert_no_replies(self.pg7, p * 3)
5295 p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
5296 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
5297 UDP(sport=1234, dport=48879) /
5298 VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
5299 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
5300 IPv6(src="10:222::1", dst="10:222::2") /
5301 UDP(sport=1234, dport=1234) /
5304 rxs = self.send_and_assert_no_replies(self.pg7, p * 3)
5309 lep1 = VppGbpEndpoint(self, vlan_144,
5311 "10.0.0.44", "11.0.0.44",
5312 "2001:10::44", "3001::44")
5313 lep1.add_vpp_config()
5316 # local EP to local ip4 external subnet
5318 p = (Ether(src=lep1.mac, dst=str(self.router_mac)) /
5320 IP(src=lep1.ip4, dst="10.220.0.1") /
5321 UDP(sport=1234, dport=1234) /
5324 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
5327 self.assertEqual(rx[Ether].src, str(self.router_mac))
5328 self.assertEqual(rx[Ether].dst, eep1.mac)
5329 self.assertEqual(rx[Dot1Q].vlan, 100)
5332 # local EP to local ip6 external subnet
5334 p = (Ether(src=lep1.mac, dst=str(self.router_mac)) /
5336 IPv6(src=lep1.ip6, dst="10:220::1") /
5337 UDP(sport=1234, dport=1234) /
5340 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
5343 self.assertEqual(rx[Ether].src, str(self.router_mac))
5344 self.assertEqual(rx[Ether].dst, eep1.mac)
5345 self.assertEqual(rx[Dot1Q].vlan, 100)
5348 # ip4 and ip6 subnets that load-balance
5350 ip_20 = VppIpRoute(self, "10.20.0.0", 24,
5351 [VppRoutePath(eep1.ip4,
5352 eep1.epg.bvi.sw_if_index),
5353 VppRoutePath(eep2.ip4,
5354 eep2.epg.bvi.sw_if_index)],
5355 table_id=t4.table_id)
5356 ip_20.add_vpp_config()
5358 l3o_20 = VppGbpSubnet(
5359 self, rd1, "10.20.0.0", 24,
5360 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
5362 l3o_20.add_vpp_config()
5364 ip6_20 = VppIpRoute(self, "10:20::", 64,
5365 [VppRoutePath(eep1.ip6,
5366 eep1.epg.bvi.sw_if_index),
5367 VppRoutePath(eep2.ip6,
5368 eep2.epg.bvi.sw_if_index)],
5369 table_id=t6.table_id)
5370 ip6_20.add_vpp_config()
5372 l3o6_20 = VppGbpSubnet(
5373 self, rd1, "10:20::", 64,
5374 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
5376 l3o6_20.add_vpp_config()
5378 self.logger.info(self.vapi.cli("sh ip fib 10.20.0.1"))
5379 self.logger.info(self.vapi.cli("sh ip6 fib 10:20::1"))
5381 # two ip6 packets whose port are chosen so they load-balance
5382 p = [(Ether(src=lep1.mac, dst=str(self.router_mac)) /
5384 IPv6(src=lep1.ip6, dst="10:20::1") /
5385 UDP(sport=1234, dport=1234) /
5386 Raw(b'\xa5' * 100)),
5387 (Ether(src=lep1.mac, dst=str(self.router_mac)) /
5389 IPv6(src=lep1.ip6, dst="10:20::1") /
5390 UDP(sport=124, dport=1230) /
5391 Raw(b'\xa5' * 100))]
5393 rxs = self.send_and_expect(self.pg0, p, self.pg0, 2)
5395 self.assertEqual(rxs[0][Dot1Q].vlan, 101)
5396 self.assertEqual(rxs[1][Dot1Q].vlan, 100)
5398 # two ip4 packets whose port are chosen so they load-balance
5399 p = [(Ether(src=lep1.mac, dst=str(self.router_mac)) /
5401 IP(src=lep1.ip4, dst="10.20.0.1") /
5402 UDP(sport=1235, dport=1235) /
5403 Raw(b'\xa5' * 100)),
5404 (Ether(src=lep1.mac, dst=str(self.router_mac)) /
5406 IP(src=lep1.ip4, dst="10.20.0.1") /
5407 UDP(sport=124, dport=1230) /
5408 Raw(b'\xa5' * 100))]
5410 rxs = self.send_and_expect(self.pg0, p, self.pg0, 2)
5412 self.assertEqual(rxs[0][Dot1Q].vlan, 101)
5413 self.assertEqual(rxs[1][Dot1Q].vlan, 100)
5418 ip_222.remove_vpp_config()
5419 self.pg7.unconfig_ip4()
5420 self.vlan_101.set_vtr(L2_VTR_OP.L2_DISABLED)
5421 self.vlan_100.set_vtr(L2_VTR_OP.L2_DISABLED)
5423 def test_gbp_anon_l3_out(self):
5424 """ GBP Anonymous L3 Out """
5426 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
5427 self.vapi.cli("set logging class gbp level debug")
5429 routed_dst_mac = "00:0c:0c:0c:0c:0c"
5430 routed_src_mac = "00:22:bd:f8:19:ff"
5435 t4 = VppIpTable(self, 1)
5437 t6 = VppIpTable(self, 1, True)
5440 rd1 = VppGbpRouteDomain(self, 2, 55, t4, t6)
5441 rd1.add_vpp_config()
5443 self.loop0.set_mac(self.router_mac)
5446 # Bind the BVI to the RD
5448 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
5449 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
5452 # Pg7 hosts a BD's BUM
5453 # Pg1 some other l3 interface
5455 self.pg7.config_ip4()
5456 self.pg7.resolve_arp()
5459 # a GBP external bridge domains for the EPs
5461 bd1 = VppBridgeDomain(self, 1)
5462 bd1.add_vpp_config()
5463 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0, None, None)
5464 gbd1.add_vpp_config()
5467 # The Endpoint-groups in which the external endpoints exist
5469 epg_220 = VppGbpEndpointGroup(self, 220, 113, rd1, gbd1,
5473 VppGbpEndpointRetention(2))
5474 epg_220.add_vpp_config()
5476 # the BVIs have the subnet applied ...
5477 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 24)
5478 ip4_addr.add_vpp_config()
5480 # ... which is an Anonymous L3-out subnets
5481 l3o_1 = VppGbpSubnet(
5482 self, rd1, "10.0.0.0", 24,
5483 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_ANON_L3_OUT,
5485 l3o_1.add_vpp_config()
5488 # an external interface attached to the outside world and the
5491 VppL2Vtr(self, self.vlan_100, L2_VTR_OP.L2_POP_1).add_vpp_config()
5492 VppL2Vtr(self, self.vlan_101, L2_VTR_OP.L2_POP_1).add_vpp_config()
5495 # vlan_100 and vlan_101 are anonymous l3-out interfaces
5497 ext_itf = VppGbpExtItf(self, self.vlan_100, bd1, rd1, anon=True)
5498 ext_itf.add_vpp_config()
5499 ext_itf = VppGbpExtItf(self, self.vlan_101, bd1, rd1, anon=True)
5500 ext_itf.add_vpp_config()
5503 # an unicast vxlan-gbp for inter-RD traffic
5505 vx_tun_l3 = VppGbpVxlanTunnel(
5506 self, 444, rd1.rd_id,
5507 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
5509 vx_tun_l3.add_vpp_config()
5512 # A remote external endpoint
5514 rep = VppGbpEndpoint(self, vx_tun_l3,
5516 "10.0.0.201", "11.0.0.201",
5517 "2001:10::201", "3001::101",
5518 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
5520 self.pg7.remote_ip4,
5522 rep.add_vpp_config()
5525 # ARP packet from host in external subnet are accepted, flooded and
5526 # replied to. We expect 2 packets:
5527 # - APR request flooded over the other vlan subif
5528 # - ARP reply from BVI
5530 p_arp = (Ether(src=self.vlan_100.remote_mac,
5531 dst="ff:ff:ff:ff:ff:ff") /
5536 hwsrc=self.vlan_100.remote_mac,
5537 hwdst="ff:ff:ff:ff:ff:ff"))
5538 rxs = self.send_and_expect(self.pg0, p_arp * 1, self.pg0, n_rx=2)
5540 p_arp = (Ether(src=self.vlan_101.remote_mac,
5541 dst="ff:ff:ff:ff:ff:ff") /
5546 hwsrc=self.vlan_101.remote_mac,
5547 hwdst="ff:ff:ff:ff:ff:ff"))
5548 rxs = self.send_and_expect(self.pg0, p_arp * 1, self.pg0, n_rx=2)
5551 # remote to external
5553 p = (Ether(src=self.pg7.remote_mac,
5554 dst=self.pg7.local_mac) /
5555 IP(src=self.pg7.remote_ip4,
5556 dst=self.pg7.local_ip4) /
5557 UDP(sport=1234, dport=48879) /
5558 VXLAN(vni=vx_tun_l3.vni, gpid=epg_220.sclass, flags=0x88) /
5559 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
5560 IP(src=str(rep.ip4), dst="10.0.0.100") /
5561 UDP(sport=1234, dport=1234) /
5563 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
5566 # local EP pings router
5568 p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
5570 IP(src="10.0.0.100", dst="10.0.0.128") /
5571 ICMP(type='echo-request'))
5572 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
5575 self.assertEqual(rx[Ether].src, str(self.router_mac))
5576 self.assertEqual(rx[Ether].dst, self.vlan_100.remote_mac)
5577 self.assertEqual(rx[Dot1Q].vlan, 100)
5580 # local EP pings other local EP
5582 p = (Ether(src=self.vlan_100.remote_mac,
5583 dst=self.vlan_101.remote_mac) /
5585 IP(src="10.0.0.100", dst="10.0.0.101") /
5586 ICMP(type='echo-request'))
5587 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
5590 self.assertEqual(rx[Ether].src, self.vlan_100.remote_mac)
5591 self.assertEqual(rx[Ether].dst, self.vlan_101.remote_mac)
5592 self.assertEqual(rx[Dot1Q].vlan, 101)
5595 # A subnet reachable through an external router on vlan 100
5597 ip_220 = VppIpRoute(self, "10.220.0.0", 24,
5598 [VppRoutePath("10.0.0.100",
5599 epg_220.bvi.sw_if_index)],
5600 table_id=t4.table_id)
5601 ip_220.add_vpp_config()
5603 l3o_220 = VppGbpSubnet(
5604 self, rd1, "10.220.0.0", 24,
5605 # note: this a "regular" L3 out subnet (not connected)
5606 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
5608 l3o_220.add_vpp_config()
5611 # A subnet reachable through an external router on vlan 101
5613 ip_221 = VppIpRoute(self, "10.221.0.0", 24,
5614 [VppRoutePath("10.0.0.101",
5615 epg_220.bvi.sw_if_index)],
5616 table_id=t4.table_id)
5617 ip_221.add_vpp_config()
5619 l3o_221 = VppGbpSubnet(
5620 self, rd1, "10.221.0.0", 24,
5621 # note: this a "regular" L3 out subnet (not connected)
5622 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
5624 l3o_221.add_vpp_config()
5627 # ping between hosts in remote subnets
5628 # dropped without a contract
5630 p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
5632 IP(src="10.220.0.1", dst="10.221.0.1") /
5633 ICMP(type='echo-request'))
5635 rxs = self.send_and_assert_no_replies(self.pg0, p * 1)
5638 # contract for the external nets to communicate
5640 acl = VppGbpAcl(self)
5641 rule4 = acl.create_rule(permit_deny=1, proto=17)
5642 rule6 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
5643 acl_index = acl.add_vpp_config([rule4, rule6])
5645 c1 = VppGbpContract(
5646 self, 55, 4220, 4221, acl_index,
5647 [VppGbpContractRule(
5648 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5649 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5652 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5653 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5655 [ETH_P_IP, ETH_P_IPV6])
5659 # Contracts allowing ext-net 200 to talk with external EPs
5661 c2 = VppGbpContract(
5662 self, 55, 4220, 113, acl_index,
5663 [VppGbpContractRule(
5664 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5665 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5668 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5669 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5671 [ETH_P_IP, ETH_P_IPV6])
5673 c3 = VppGbpContract(
5674 self, 55, 113, 4220, acl_index,
5675 [VppGbpContractRule(
5676 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5677 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5680 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5681 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5683 [ETH_P_IP, ETH_P_IPV6])
5687 # ping between hosts in remote subnets
5689 p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
5691 IP(src="10.220.0.1", dst="10.221.0.1") /
5692 UDP(sport=1234, dport=1234) /
5695 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
5698 self.assertEqual(rx[Ether].src, str(self.router_mac))
5699 self.assertEqual(rx[Ether].dst, self.vlan_101.remote_mac)
5700 self.assertEqual(rx[Dot1Q].vlan, 101)
5702 # we did not learn these external hosts
5703 self.assertFalse(find_gbp_endpoint(self, ip="10.220.0.1"))
5704 self.assertFalse(find_gbp_endpoint(self, ip="10.221.0.1"))
5707 # from remote external EP to local external EP
5709 p = (Ether(src=self.pg7.remote_mac,
5710 dst=self.pg7.local_mac) /
5711 IP(src=self.pg7.remote_ip4,
5712 dst=self.pg7.local_ip4) /
5713 UDP(sport=1234, dport=48879) /
5714 VXLAN(vni=444, gpid=113, flags=0x88) /
5715 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
5716 IP(src=rep.ip4, dst="10.220.0.1") /
5717 UDP(sport=1234, dport=1234) /
5720 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
5723 # ping from an external host to the remote external EP
5725 p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
5727 IP(src="10.220.0.1", dst=rep.ip4) /
5728 UDP(sport=1234, dport=1234) /
5731 rxs = self.send_and_expect(self.pg0, p * 1, self.pg7)
5734 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
5735 # self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
5736 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
5737 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
5738 self.assertEqual(rx[VXLAN].vni, 444)
5739 self.assertTrue(rx[VXLAN].flags.G)
5740 self.assertTrue(rx[VXLAN].flags.Instance)
5741 # the sclass of the ext-net the packet came from
5742 self.assertEqual(rx[VXLAN].gpid, 4220)
5743 # policy was applied to the original IP packet
5744 self.assertTrue(rx[VXLAN].gpflags.A)
5745 # since it's an external host the reciever should not learn it
5746 self.assertTrue(rx[VXLAN].gpflags.D)
5747 inner = rx[VXLAN].payload
5748 self.assertEqual(inner[IP].src, "10.220.0.1")
5749 self.assertEqual(inner[IP].dst, rep.ip4)
5752 # An external subnet reachable via the remote external EP
5756 # first the VXLAN-GBP tunnel over which it is reached
5758 vx_tun_r = VppVxlanGbpTunnel(
5759 self, self.pg7.local_ip4,
5760 self.pg7.remote_ip4, 445,
5761 mode=(VppEnum.vl_api_vxlan_gbp_api_tunnel_mode_t.
5762 VXLAN_GBP_API_TUNNEL_MODE_L3))
5763 vx_tun_r.add_vpp_config()
5764 VppIpInterfaceBind(self, vx_tun_r, t4).add_vpp_config()
5766 self.logger.info(self.vapi.cli("sh vxlan-gbp tunnel"))
5769 # then the special adj to resolve through on that tunnel
5771 n1 = VppNeighbor(self,
5772 vx_tun_r.sw_if_index,
5773 "00:0c:0c:0c:0c:0c",
5774 self.pg7.remote_ip4)
5778 # the route via the adj above
5780 ip_222 = VppIpRoute(self, "10.222.0.0", 24,
5781 [VppRoutePath(self.pg7.remote_ip4,
5782 vx_tun_r.sw_if_index)],
5783 table_id=t4.table_id)
5784 ip_222.add_vpp_config()
5786 l3o_222 = VppGbpSubnet(
5787 self, rd1, "10.222.0.0", 24,
5788 # note: this a "regular" l3out subnet (not connected)
5789 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
5791 l3o_222.add_vpp_config()
5794 # ping between hosts in local and remote external subnets
5795 # dropped without a contract
5797 p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
5799 IP(src="10.220.0.1", dst="10.222.0.1") /
5800 UDP(sport=1234, dport=1234) /
5803 rxs = self.send_and_assert_no_replies(self.pg0, p * 1)
5806 # Add contracts ext-nets for 220 -> 222
5808 c4 = VppGbpContract(
5809 self, 55, 4220, 4222, acl_index,
5810 [VppGbpContractRule(
5811 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5812 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5815 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5816 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5818 [ETH_P_IP, ETH_P_IPV6])
5822 # ping from host in local to remote external subnets
5824 p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
5826 IP(src="10.220.0.1", dst="10.222.0.1") /
5827 UDP(sport=1234, dport=1234) /
5830 rxs = self.send_and_expect(self.pg0, p * 3, self.pg7)
5833 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
5834 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
5835 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
5836 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
5837 self.assertEqual(rx[VXLAN].vni, 445)
5838 self.assertTrue(rx[VXLAN].flags.G)
5839 self.assertTrue(rx[VXLAN].flags.Instance)
5840 # the sclass of the ext-net the packet came from
5841 self.assertEqual(rx[VXLAN].gpid, 4220)
5842 # policy was applied to the original IP packet
5843 self.assertTrue(rx[VXLAN].gpflags.A)
5844 # since it's an external host the reciever should not learn it
5845 self.assertTrue(rx[VXLAN].gpflags.D)
5846 inner = rx[VXLAN].payload
5847 self.assertEqual(inner[Ether].dst, "00:0c:0c:0c:0c:0c")
5848 self.assertEqual(inner[IP].src, "10.220.0.1")
5849 self.assertEqual(inner[IP].dst, "10.222.0.1")
5852 # ping from host in remote to local external subnets
5853 # there's no contract for this, but the A bit is set.
5855 p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
5856 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
5857 UDP(sport=1234, dport=48879) /
5858 VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
5859 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
5860 IP(src="10.222.0.1", dst="10.220.0.1") /
5861 UDP(sport=1234, dport=1234) /
5864 rxs = self.send_and_expect(self.pg7, p * 3, self.pg0)
5865 self.assertFalse(find_gbp_endpoint(self, ip="10.222.0.1"))
5868 # ping from host in remote to remote external subnets
5869 # this is dropped by reflection check.
5871 p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
5872 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
5873 UDP(sport=1234, dport=48879) /
5874 VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
5875 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
5876 IP(src="10.222.0.1", dst="10.222.0.2") /
5877 UDP(sport=1234, dport=1234) /
5880 rxs = self.send_and_assert_no_replies(self.pg7, p * 3)
5885 self.vlan_101.set_vtr(L2_VTR_OP.L2_DISABLED)
5886 self.vlan_100.set_vtr(L2_VTR_OP.L2_DISABLED)
5887 self.pg7.unconfig_ip4()
5890 if __name__ == '__main__':
5891 unittest.main(testRunner=VppTestRunner)