3 from socket import AF_INET, AF_INET6
6 from scapy.packet import Raw
7 from scapy.layers.l2 import Ether, ARP, Dot1Q
8 from scapy.layers.inet import IP, UDP, ICMP
9 from scapy.layers.inet6 import IPv6, ICMPv6ND_NS, ICMPv6NDOptSrcLLAddr, \
11 from scapy.utils6 import in6_getnsma, in6_getnsmac
12 from scapy.layers.vxlan import VXLAN
13 from scapy.data import ETH_P_IP, ETH_P_IPV6, ETH_P_ARP
14 from scapy.utils import inet_pton, inet_ntop
16 from framework import VppTestCase, VppTestRunner
17 from vpp_object import VppObject
18 from vpp_interface import VppInterface
19 from vpp_ip_route import VppIpRoute, VppRoutePath, VppIpTable, \
20 VppIpInterfaceAddress, VppIpInterfaceBind, find_route, FibPathProto, \
22 from vpp_l2 import VppBridgeDomain, VppBridgeDomainPort, \
23 VppBridgeDomainArpEntry, VppL2FibEntry, find_bridge_domain_port, VppL2Vtr
24 from vpp_sub_interface import L2_VTR_OP, VppDot1QSubint
25 from vpp_ip import VppIpAddress, VppIpPrefix
26 from vpp_papi import VppEnum, MACAddress
27 from vpp_vxlan_gbp_tunnel import find_vxlan_gbp_tunnel, INDEX_INVALID, \
29 from vpp_neighbor import VppNeighbor
34 def find_gbp_endpoint(test, sw_if_index=None, ip=None, mac=None):
36 vip = VppIpAddress(ip)
38 vmac = MACAddress(mac)
40 eps = test.vapi.gbp_endpoint_dump()
44 if ep.endpoint.sw_if_index != sw_if_index:
47 for eip in ep.endpoint.ips:
51 if vmac.packed == ep.endpoint.mac:
56 def find_gbp_vxlan(test, vni):
57 ts = test.vapi.gbp_vxlan_tunnel_dump()
59 if t.tunnel.vni == vni:
64 class VppGbpEndpoint(VppObject):
91 return [self.ip4, self.ip6]
95 return [self.fip4, self.fip6]
97 def __init__(self, test, itf, epg, recirc, ip4, fip4, ip6, fip6,
107 self._ip4 = VppIpAddress(ip4)
108 self._fip4 = VppIpAddress(fip4)
109 self._ip6 = VppIpAddress(ip6)
110 self._fip6 = VppIpAddress(fip6)
113 self.vmac = MACAddress(self.itf.remote_mac)
115 self.vmac = MACAddress("00:00:00:00:00:00")
118 self.tun_src = VppIpAddress(tun_src)
119 self.tun_dst = VppIpAddress(tun_dst)
121 def add_vpp_config(self):
122 res = self._test.vapi.gbp_endpoint_add(
123 self.itf.sw_if_index,
124 [self.ip4.encode(), self.ip6.encode()],
128 self.tun_src.encode(),
129 self.tun_dst.encode())
130 self.handle = res.handle
131 self._test.registry.register(self, self._test.logger)
133 def remove_vpp_config(self):
134 self._test.vapi.gbp_endpoint_del(self.handle)
137 return "gbp-endpoint:[%d==%d:%s:%d]" % (self.handle,
138 self.itf.sw_if_index,
142 def query_vpp_config(self):
143 return find_gbp_endpoint(self._test,
144 self.itf.sw_if_index,
148 class VppGbpRecirc(VppObject):
150 GBP Recirculation Interface
153 def __init__(self, test, epg, recirc, is_ext=False):
159 def add_vpp_config(self):
160 self._test.vapi.gbp_recirc_add_del(
162 self.recirc.sw_if_index,
165 self._test.registry.register(self, self._test.logger)
167 def remove_vpp_config(self):
168 self._test.vapi.gbp_recirc_add_del(
170 self.recirc.sw_if_index,
175 return "gbp-recirc:[%d]" % (self.recirc.sw_if_index)
177 def query_vpp_config(self):
178 rs = self._test.vapi.gbp_recirc_dump()
180 if r.recirc.sw_if_index == self.recirc.sw_if_index:
185 class VppGbpExtItf(VppObject):
187 GBP ExtItfulation Interface
190 def __init__(self, test, itf, bd, rd):
196 def add_vpp_config(self):
197 self._test.vapi.gbp_ext_itf_add_del(
199 self.itf.sw_if_index,
202 self._test.registry.register(self, self._test.logger)
204 def remove_vpp_config(self):
205 self._test.vapi.gbp_ext_itf_add_del(
207 self.itf.sw_if_index,
212 return "gbp-ext-itf:[%d]" % (self.itf.sw_if_index)
214 def query_vpp_config(self):
215 rs = self._test.vapi.gbp_ext_itf_dump()
217 if r.ext_itf.sw_if_index == self.itf.sw_if_index:
222 class VppGbpSubnet(VppObject):
227 def __init__(self, test, rd, address, address_len,
228 type, sw_if_index=None, sclass=None):
230 self.rd_id = rd.rd_id
231 self.prefix = VppIpPrefix(address, address_len)
233 self.sw_if_index = sw_if_index
236 def add_vpp_config(self):
237 self._test.vapi.gbp_subnet_add_del(
240 self.prefix.encode(),
242 sw_if_index=self.sw_if_index if self.sw_if_index else 0xffffffff,
243 sclass=self.sclass if self.sclass else 0xffff)
244 self._test.registry.register(self, self._test.logger)
246 def remove_vpp_config(self):
247 self._test.vapi.gbp_subnet_add_del(
250 self.prefix.encode(),
254 return "gbp-subnet:[%d-%s]" % (self.rd_id, self.prefix)
256 def query_vpp_config(self):
257 ss = self._test.vapi.gbp_subnet_dump()
259 if s.subnet.rd_id == self.rd_id and \
260 s.subnet.type == self.type and \
261 s.subnet.prefix == self.prefix:
266 class VppGbpEndpointRetention(object):
267 def __init__(self, remote_ep_timeout=0xffffffff):
268 self.remote_ep_timeout = remote_ep_timeout
271 return {'remote_ep_timeout': self.remote_ep_timeout}
274 class VppGbpEndpointGroup(VppObject):
279 def __init__(self, test, vnid, sclass, rd, bd, uplink,
280 bvi, bvi_ip4, bvi_ip6=None,
281 retention=VppGbpEndpointRetention()):
285 self.bvi_ip4 = VppIpAddress(bvi_ip4)
286 self.bvi_ip6 = VppIpAddress(bvi_ip6)
293 self.retention = retention
295 def add_vpp_config(self):
296 self._test.vapi.gbp_endpoint_group_add(
301 self.uplink.sw_if_index if self.uplink else INDEX_INVALID,
302 self.retention.encode())
303 self._test.registry.register(self, self._test.logger)
305 def remove_vpp_config(self):
306 self._test.vapi.gbp_endpoint_group_del(self.sclass)
309 return "gbp-endpoint-group:[%d]" % (self.vnid)
311 def query_vpp_config(self):
312 epgs = self._test.vapi.gbp_endpoint_group_dump()
314 if epg.epg.vnid == self.vnid:
319 class VppGbpBridgeDomain(VppObject):
324 def __init__(self, test, bd, bvi, uu_fwd=None,
325 bm_flood=None, learn=True, uu_drop=False, bm_drop=False):
329 self.bm_flood = bm_flood
332 e = VppEnum.vl_api_gbp_bridge_domain_flags_t
334 self.learn = e.GBP_BD_API_FLAG_NONE
336 self.learn = e.GBP_BD_API_FLAG_DO_NOT_LEARN
338 self.learn |= e.GBP_BD_API_FLAG_UU_FWD_DROP
340 self.learn |= e.GBP_BD_API_FLAG_MCAST_DROP
342 def add_vpp_config(self):
343 self._test.vapi.gbp_bridge_domain_add(
346 self.bvi.sw_if_index,
347 self.uu_fwd.sw_if_index if self.uu_fwd else INDEX_INVALID,
348 self.bm_flood.sw_if_index if self.bm_flood else INDEX_INVALID)
349 self._test.registry.register(self, self._test.logger)
351 def remove_vpp_config(self):
352 self._test.vapi.gbp_bridge_domain_del(self.bd.bd_id)
355 return "gbp-bridge-domain:[%d]" % (self.bd.bd_id)
357 def query_vpp_config(self):
358 bds = self._test.vapi.gbp_bridge_domain_dump()
360 if bd.bd.bd_id == self.bd.bd_id:
365 class VppGbpRouteDomain(VppObject):
370 def __init__(self, test, rd_id, t4, t6, ip4_uu=None, ip6_uu=None):
378 def add_vpp_config(self):
379 self._test.vapi.gbp_route_domain_add(
383 self.ip4_uu.sw_if_index if self.ip4_uu else INDEX_INVALID,
384 self.ip6_uu.sw_if_index if self.ip6_uu else INDEX_INVALID)
385 self._test.registry.register(self, self._test.logger)
387 def remove_vpp_config(self):
388 self._test.vapi.gbp_route_domain_del(self.rd_id)
391 return "gbp-route-domain:[%d]" % (self.rd_id)
393 def query_vpp_config(self):
394 rds = self._test.vapi.gbp_route_domain_dump()
396 if rd.rd.rd_id == self.rd_id:
401 class VppGbpContractNextHop():
402 def __init__(self, mac, bd, ip, rd):
409 return {'ip': self.ip.encode(),
410 'mac': self.mac.packed,
411 'bd_id': self.bd.bd.bd_id,
412 'rd_id': self.rd.rd_id}
415 class VppGbpContractRule():
416 def __init__(self, action, hash_mode, nhs=None):
418 self.hash_mode = hash_mode
419 self.nhs = [] if nhs is None else nhs
424 nhs.append(nh.encode())
427 return {'action': self.action,
429 'hash_mode': self.hash_mode,
430 'n_nhs': len(self.nhs),
434 return '<VppGbpContractRule action=%s, hash_mode=%s>' % (
435 self.action, self.hash_mode)
438 class VppGbpContract(VppObject):
443 def __init__(self, test, sclass, dclass, acl_index,
444 rules, allowed_ethertypes):
446 if not isinstance(rules, list):
447 raise ValueError("'rules' must be a list.")
448 if not isinstance(allowed_ethertypes, list):
449 raise ValueError("'allowed_ethertypes' must be a list.")
450 self.acl_index = acl_index
454 self.allowed_ethertypes = allowed_ethertypes
455 while (len(self.allowed_ethertypes) < 16):
456 self.allowed_ethertypes.append(0)
458 def add_vpp_config(self):
461 rules.append(r.encode())
462 r = self._test.vapi.gbp_contract_add_del(
465 'acl_index': self.acl_index,
466 'sclass': self.sclass,
467 'dclass': self.dclass,
468 'n_rules': len(rules),
470 'n_ether_types': len(self.allowed_ethertypes),
471 'allowed_ethertypes': self.allowed_ethertypes})
472 self.stats_index = r.stats_index
473 self._test.registry.register(self, self._test.logger)
475 def remove_vpp_config(self):
476 self._test.vapi.gbp_contract_add_del(
479 'acl_index': self.acl_index,
480 'sclass': self.sclass,
481 'dclass': self.dclass,
484 'n_ether_types': len(self.allowed_ethertypes),
485 'allowed_ethertypes': self.allowed_ethertypes}
489 return "gbp-contract:[%d:%s:%d]" % (self.sclass,
493 def query_vpp_config(self):
494 cs = self._test.vapi.gbp_contract_dump()
496 if c.contract.sclass == self.sclass \
497 and c.contract.dclass == self.dclass:
501 def get_drop_stats(self):
502 c = self._test.statistics.get_counter("/net/gbp/contract/drop")
503 return c[0][self.stats_index]
505 def get_permit_stats(self):
506 c = self._test.statistics.get_counter("/net/gbp/contract/permit")
507 return c[0][self.stats_index]
510 class VppGbpVxlanTunnel(VppInterface):
515 def __init__(self, test, vni, bd_rd_id, mode, src):
516 super(VppGbpVxlanTunnel, self).__init__(test)
519 self.bd_rd_id = bd_rd_id
523 def add_vpp_config(self):
524 r = self._test.vapi.gbp_vxlan_tunnel_add(
529 self.set_sw_if_index(r.sw_if_index)
530 self._test.registry.register(self, self._test.logger)
532 def remove_vpp_config(self):
533 self._test.vapi.gbp_vxlan_tunnel_del(self.vni)
536 return "gbp-vxlan:%d" % (self.sw_if_index)
538 def query_vpp_config(self):
539 return find_gbp_vxlan(self._test, self.vni)
542 class VppGbpAcl(VppObject):
547 def __init__(self, test):
549 self.acl_index = 4294967295
551 def create_rule(self, is_ipv6=0, permit_deny=0, proto=-1,
552 s_prefix=0, s_ip=b'\x00\x00\x00\x00', sport_from=0,
553 sport_to=65535, d_prefix=0, d_ip=b'\x00\x00\x00\x00',
554 dport_from=0, dport_to=65535):
555 if proto == -1 or proto == 0:
558 elif proto == 1 or proto == 58:
561 rule = ({'is_permit': permit_deny, 'is_ipv6': is_ipv6, 'proto': proto,
562 'srcport_or_icmptype_first': sport_from,
563 'srcport_or_icmptype_last': sport_to,
564 'src_ip_prefix_len': s_prefix,
566 'dstport_or_icmpcode_first': dport_from,
567 'dstport_or_icmpcode_last': dport_to,
568 'dst_ip_prefix_len': d_prefix,
569 'dst_ip_addr': d_ip})
572 def add_vpp_config(self, rules):
574 reply = self._test.vapi.acl_add_replace(acl_index=self.acl_index,
577 self.acl_index = reply.acl_index
578 return self.acl_index
580 def remove_vpp_config(self):
581 self._test.vapi.acl_del(self.acl_index)
584 return "gbp-acl:[%d]" % (self.acl_index)
586 def query_vpp_config(self):
587 cs = self._test.vapi.acl_dump()
589 if c.acl_index == self.acl_index:
594 class TestGBP(VppTestCase):
595 """ GBP Test Case """
598 def config_flags(self):
599 return VppEnum.vl_api_nat_config_flags_t
603 super(TestGBP, cls).setUpClass()
606 def tearDownClass(cls):
607 super(TestGBP, cls).tearDownClass()
610 super(TestGBP, self).setUp()
612 self.create_pg_interfaces(range(9))
613 self.create_loopback_interfaces(8)
615 self.router_mac = MACAddress("00:11:22:33:44:55")
617 for i in self.pg_interfaces:
619 for i in self.lo_interfaces:
623 for i in self.pg_interfaces:
626 super(TestGBP, self).tearDown()
628 def send_and_expect_bridged(self, src, tx, dst):
629 rx = self.send_and_expect(src, tx, dst)
632 self.assertEqual(r[Ether].src, tx[0][Ether].src)
633 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
634 self.assertEqual(r[IP].src, tx[0][IP].src)
635 self.assertEqual(r[IP].dst, tx[0][IP].dst)
638 def send_and_expect_bridged6(self, src, tx, dst):
639 rx = self.send_and_expect(src, tx, dst)
642 self.assertEqual(r[Ether].src, tx[0][Ether].src)
643 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
644 self.assertEqual(r[IPv6].src, tx[0][IPv6].src)
645 self.assertEqual(r[IPv6].dst, tx[0][IPv6].dst)
648 def send_and_expect_routed(self, src, tx, dst, src_mac):
649 rx = self.send_and_expect(src, tx, dst)
652 self.assertEqual(r[Ether].src, src_mac)
653 self.assertEqual(r[Ether].dst, dst.remote_mac)
654 self.assertEqual(r[IP].src, tx[0][IP].src)
655 self.assertEqual(r[IP].dst, tx[0][IP].dst)
658 def send_and_expect_natted(self, src, tx, dst, src_ip):
659 rx = self.send_and_expect(src, tx, dst)
662 self.assertEqual(r[Ether].src, tx[0][Ether].src)
663 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
664 self.assertEqual(r[IP].src, src_ip)
665 self.assertEqual(r[IP].dst, tx[0][IP].dst)
668 def send_and_expect_natted6(self, src, tx, dst, src_ip):
669 rx = self.send_and_expect(src, tx, dst)
672 self.assertEqual(r[Ether].src, tx[0][Ether].src)
673 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
674 self.assertEqual(r[IPv6].src, src_ip)
675 self.assertEqual(r[IPv6].dst, tx[0][IPv6].dst)
678 def send_and_expect_unnatted(self, src, tx, dst, dst_ip):
679 rx = self.send_and_expect(src, tx, dst)
682 self.assertEqual(r[Ether].src, tx[0][Ether].src)
683 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
684 self.assertEqual(r[IP].dst, dst_ip)
685 self.assertEqual(r[IP].src, tx[0][IP].src)
688 def send_and_expect_unnatted6(self, src, tx, dst, dst_ip):
689 rx = self.send_and_expect(src, tx, dst)
692 self.assertEqual(r[Ether].src, tx[0][Ether].src)
693 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
694 self.assertEqual(r[IPv6].dst, dst_ip)
695 self.assertEqual(r[IPv6].src, tx[0][IPv6].src)
698 def send_and_expect_double_natted(self, src, tx, dst, src_ip, dst_ip):
699 rx = self.send_and_expect(src, tx, dst)
702 self.assertEqual(r[Ether].src, str(self.router_mac))
703 self.assertEqual(r[Ether].dst, dst.remote_mac)
704 self.assertEqual(r[IP].dst, dst_ip)
705 self.assertEqual(r[IP].src, src_ip)
708 def send_and_expect_double_natted6(self, src, tx, dst, src_ip, dst_ip):
709 rx = self.send_and_expect(src, tx, dst)
712 self.assertEqual(r[Ether].src, str(self.router_mac))
713 self.assertEqual(r[Ether].dst, dst.remote_mac)
714 self.assertEqual(r[IPv6].dst, dst_ip)
715 self.assertEqual(r[IPv6].src, src_ip)
718 def send_and_expect_no_arp(self, src, tx, dst):
719 self.pg_send(src, tx)
720 dst.get_capture(0, timeout=1)
721 dst.assert_nothing_captured(remark="")
724 def send_and_expect_arp(self, src, tx, dst):
725 rx = self.send_and_expect(src, tx, dst)
728 self.assertEqual(r[Ether].src, tx[0][Ether].src)
729 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
730 self.assertEqual(r[ARP].psrc, tx[0][ARP].psrc)
731 self.assertEqual(r[ARP].pdst, tx[0][ARP].pdst)
732 self.assertEqual(r[ARP].hwsrc, tx[0][ARP].hwsrc)
733 self.assertEqual(r[ARP].hwdst, tx[0][ARP].hwdst)
737 """ Group Based Policy """
739 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
744 bd1 = VppBridgeDomain(self, 1)
745 bd2 = VppBridgeDomain(self, 2)
746 bd20 = VppBridgeDomain(self, 20)
750 bd20.add_vpp_config()
752 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0)
753 gbd2 = VppGbpBridgeDomain(self, bd2, self.loop1)
754 gbd20 = VppGbpBridgeDomain(self, bd20, self.loop2)
756 gbd1.add_vpp_config()
757 gbd2.add_vpp_config()
758 gbd20.add_vpp_config()
763 gt4 = VppIpTable(self, 0)
765 gt6 = VppIpTable(self, 0, is_ip6=True)
767 nt4 = VppIpTable(self, 20)
769 nt6 = VppIpTable(self, 20, is_ip6=True)
772 rd0 = VppGbpRouteDomain(self, 0, gt4, gt6, None, None)
773 rd20 = VppGbpRouteDomain(self, 20, nt4, nt6, None, None)
776 rd20.add_vpp_config()
779 # 3 EPGs, 2 of which share a BD.
780 # 2 NAT EPGs, one for floating-IP subnets, the other for internet
782 epgs = [VppGbpEndpointGroup(self, 220, 1220, rd0, gbd1,
783 self.pg4, self.loop0,
784 "10.0.0.128", "2001:10::128"),
785 VppGbpEndpointGroup(self, 221, 1221, rd0, gbd1,
786 self.pg5, self.loop0,
787 "10.0.1.128", "2001:10:1::128"),
788 VppGbpEndpointGroup(self, 222, 1222, rd0, gbd2,
789 self.pg6, self.loop1,
790 "10.0.2.128", "2001:10:2::128"),
791 VppGbpEndpointGroup(self, 333, 1333, rd20, gbd20,
792 self.pg7, self.loop2,
793 "11.0.0.128", "3001::128"),
794 VppGbpEndpointGroup(self, 444, 1444, rd20, gbd20,
795 self.pg8, self.loop2,
796 "11.0.0.129", "3001::129")]
797 recircs = [VppGbpRecirc(self, epgs[0], self.loop3),
798 VppGbpRecirc(self, epgs[1], self.loop4),
799 VppGbpRecirc(self, epgs[2], self.loop5),
800 VppGbpRecirc(self, epgs[3], self.loop6, is_ext=True),
801 VppGbpRecirc(self, epgs[4], self.loop7, is_ext=True)]
804 recirc_nat = recircs[3]
807 # 4 end-points, 2 in the same subnet, 3 in the same BD
809 eps = [VppGbpEndpoint(self, self.pg0,
811 "10.0.0.1", "11.0.0.1",
812 "2001:10::1", "3001::1"),
813 VppGbpEndpoint(self, self.pg1,
815 "10.0.0.2", "11.0.0.2",
816 "2001:10::2", "3001::2"),
817 VppGbpEndpoint(self, self.pg2,
819 "10.0.1.1", "11.0.0.3",
820 "2001:10:1::1", "3001::3"),
821 VppGbpEndpoint(self, self.pg3,
823 "10.0.2.1", "11.0.0.4",
824 "2001:10:2::1", "3001::4")]
827 # Config related to each of the EPGs
830 # IP config on the BVI interfaces
831 if epg != epgs[1] and epg != epgs[4]:
832 VppIpInterfaceBind(self, epg.bvi, epg.rd.t4).add_vpp_config()
833 VppIpInterfaceBind(self, epg.bvi, epg.rd.t6).add_vpp_config()
834 self.vapi.sw_interface_set_mac_address(
836 self.router_mac.packed)
838 # The BVIs are NAT inside interfaces
839 flags = self.config_flags.NAT_IS_INSIDE
840 self.vapi.nat44_interface_add_del_feature(
841 sw_if_index=epg.bvi.sw_if_index,
842 flags=flags, is_add=1)
843 self.vapi.nat66_add_del_interface(
844 is_add=1, flags=flags,
845 sw_if_index=epg.bvi.sw_if_index)
847 if_ip4 = VppIpInterfaceAddress(self, epg.bvi, epg.bvi_ip4, 32)
848 if_ip6 = VppIpInterfaceAddress(self, epg.bvi, epg.bvi_ip6, 128)
849 if_ip4.add_vpp_config()
850 if_ip6.add_vpp_config()
852 # EPG uplink interfaces in the RD
853 VppIpInterfaceBind(self, epg.uplink, epg.rd.t4).add_vpp_config()
854 VppIpInterfaceBind(self, epg.uplink, epg.rd.t6).add_vpp_config()
856 # add the BD ARP termination entry for BVI IP
857 epg.bd_arp_ip4 = VppBridgeDomainArpEntry(self, epg.bd.bd,
858 str(self.router_mac),
860 epg.bd_arp_ip6 = VppBridgeDomainArpEntry(self, epg.bd.bd,
861 str(self.router_mac),
863 epg.bd_arp_ip4.add_vpp_config()
864 epg.bd_arp_ip6.add_vpp_config()
869 for recirc in recircs:
870 # EPG's ingress recirculation interface maps to its RD
871 VppIpInterfaceBind(self, recirc.recirc,
872 recirc.epg.rd.t4).add_vpp_config()
873 VppIpInterfaceBind(self, recirc.recirc,
874 recirc.epg.rd.t6).add_vpp_config()
876 self.vapi.nat44_interface_add_del_feature(
877 sw_if_index=recirc.recirc.sw_if_index, is_add=1)
878 self.vapi.nat66_add_del_interface(
880 sw_if_index=recirc.recirc.sw_if_index)
882 recirc.add_vpp_config()
884 for recirc in recircs:
885 self.assertTrue(find_bridge_domain_port(self,
886 recirc.epg.bd.bd.bd_id,
887 recirc.recirc.sw_if_index))
890 self.pg_enable_capture(self.pg_interfaces)
893 # routes to the endpoints. We need these since there are no
894 # adj-fibs due to the fact the the BVI address has /32 and
895 # the subnet is not attached.
897 for (ip, fip) in zip(ep.ips, ep.fips):
898 # Add static mappings for each EP from the 10/8 to 11/8 network
900 flags = self.config_flags.NAT_IS_ADDR_ONLY
901 self.vapi.nat44_add_del_static_mapping(
903 local_ip_address=ip.bytes,
904 external_ip_address=fip.bytes,
905 external_sw_if_index=0xFFFFFFFF,
909 self.vapi.nat66_add_del_static_mapping(
910 local_ip_address=ip.bytes,
911 external_ip_address=fip.bytes,
917 self.logger.info(self.vapi.cli("sh gbp endpoint"))
919 # ... results in a Gratuitous ARP/ND on the EPG's uplink
920 rx = ep.epg.uplink.get_capture(len(ep.ips), timeout=0.2)
922 for ii, ip in enumerate(ep.ips):
926 self.assertTrue(p.haslayer(ICMPv6ND_NA))
927 self.assertEqual(p[ICMPv6ND_NA].tgt, ip.address)
929 self.assertTrue(p.haslayer(ARP))
930 self.assertEqual(p[ARP].psrc, ip.address)
931 self.assertEqual(p[ARP].pdst, ip.address)
933 # add the BD ARP termination entry for floating IP
935 ba = VppBridgeDomainArpEntry(self, epg_nat.bd.bd, ep.mac,
939 # floating IPs route via EPG recirc
941 self, fip.address, fip.length,
942 [VppRoutePath(fip.address,
943 ep.recirc.recirc.sw_if_index,
944 type=FibPathType.FIB_PATH_TYPE_DVR,
945 proto=fip.dpo_proto)],
949 # L2 FIB entries in the NAT EPG BD to bridge the packets from
950 # the outside direct to the internal EPG
951 lf = VppL2FibEntry(self, epg_nat.bd.bd, ep.mac,
952 ep.recirc.recirc, bvi_mac=0)
956 # ARP packets for unknown IP are sent to the EPG uplink
958 pkt_arp = (Ether(dst="ff:ff:ff:ff:ff:ff",
959 src=self.pg0.remote_mac) /
961 hwdst="ff:ff:ff:ff:ff:ff",
962 hwsrc=self.pg0.remote_mac,
966 self.vapi.cli("clear trace")
967 self.pg0.add_stream(pkt_arp)
969 self.pg_enable_capture(self.pg_interfaces)
972 rxd = epgs[0].uplink.get_capture(1)
975 # ARP/ND packets get a response
977 pkt_arp = (Ether(dst="ff:ff:ff:ff:ff:ff",
978 src=self.pg0.remote_mac) /
980 hwdst="ff:ff:ff:ff:ff:ff",
981 hwsrc=self.pg0.remote_mac,
982 pdst=epgs[0].bvi_ip4.address,
983 psrc=eps[0].ip4.address))
985 self.send_and_expect(self.pg0, [pkt_arp], self.pg0)
987 nsma = in6_getnsma(inet_pton(AF_INET6, eps[0].ip6.address))
988 d = inet_ntop(AF_INET6, nsma)
989 pkt_nd = (Ether(dst=in6_getnsmac(nsma),
990 src=self.pg0.remote_mac) /
991 IPv6(dst=d, src=eps[0].ip6.address) /
992 ICMPv6ND_NS(tgt=epgs[0].bvi_ip6.address) /
993 ICMPv6NDOptSrcLLAddr(lladdr=self.pg0.remote_mac))
994 self.send_and_expect(self.pg0, [pkt_nd], self.pg0)
997 # broadcast packets are flooded
999 pkt_bcast = (Ether(dst="ff:ff:ff:ff:ff:ff",
1000 src=self.pg0.remote_mac) /
1001 IP(src=eps[0].ip4.address, dst="232.1.1.1") /
1002 UDP(sport=1234, dport=1234) /
1005 self.vapi.cli("clear trace")
1006 self.pg0.add_stream(pkt_bcast)
1008 self.pg_enable_capture(self.pg_interfaces)
1011 rxd = eps[1].itf.get_capture(1)
1012 self.assertEqual(rxd[0][Ether].dst, pkt_bcast[Ether].dst)
1013 rxd = epgs[0].uplink.get_capture(1)
1014 self.assertEqual(rxd[0][Ether].dst, pkt_bcast[Ether].dst)
1017 # packets to non-local L3 destinations dropped
1019 pkt_intra_epg_220_ip4 = (Ether(src=self.pg0.remote_mac,
1020 dst=str(self.router_mac)) /
1021 IP(src=eps[0].ip4.address,
1023 UDP(sport=1234, dport=1234) /
1025 pkt_inter_epg_222_ip4 = (Ether(src=self.pg0.remote_mac,
1026 dst=str(self.router_mac)) /
1027 IP(src=eps[0].ip4.address,
1029 UDP(sport=1234, dport=1234) /
1032 self.send_and_assert_no_replies(self.pg0,
1033 pkt_intra_epg_220_ip4 * NUM_PKTS)
1035 pkt_inter_epg_222_ip6 = (Ether(src=self.pg0.remote_mac,
1036 dst=str(self.router_mac)) /
1037 IPv6(src=eps[0].ip6.address,
1038 dst="2001:10::99") /
1039 UDP(sport=1234, dport=1234) /
1041 self.send_and_assert_no_replies(self.pg0,
1042 pkt_inter_epg_222_ip6 * NUM_PKTS)
1045 # Add the subnet routes
1048 self, rd0, "10.0.0.0", 24,
1049 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1051 self, rd0, "10.0.1.0", 24,
1052 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1054 self, rd0, "10.0.2.0", 24,
1055 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1057 self, rd0, "2001:10::1", 64,
1058 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1060 self, rd0, "2001:10:1::1", 64,
1061 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1063 self, rd0, "2001:10:2::1", 64,
1064 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1065 s41.add_vpp_config()
1066 s42.add_vpp_config()
1067 s43.add_vpp_config()
1068 s61.add_vpp_config()
1069 s62.add_vpp_config()
1070 s63.add_vpp_config()
1072 self.send_and_expect_bridged(eps[0].itf,
1073 pkt_intra_epg_220_ip4 * NUM_PKTS,
1075 self.send_and_expect_bridged(eps[0].itf,
1076 pkt_inter_epg_222_ip4 * NUM_PKTS,
1078 self.send_and_expect_bridged6(eps[0].itf,
1079 pkt_inter_epg_222_ip6 * NUM_PKTS,
1082 self.logger.info(self.vapi.cli("sh ip fib 11.0.0.2"))
1083 self.logger.info(self.vapi.cli("sh gbp endpoint-group"))
1084 self.logger.info(self.vapi.cli("sh gbp endpoint"))
1085 self.logger.info(self.vapi.cli("sh gbp recirc"))
1086 self.logger.info(self.vapi.cli("sh int"))
1087 self.logger.info(self.vapi.cli("sh int addr"))
1088 self.logger.info(self.vapi.cli("sh int feat loop6"))
1089 self.logger.info(self.vapi.cli("sh vlib graph ip4-gbp-src-classify"))
1090 self.logger.info(self.vapi.cli("sh int feat loop3"))
1091 self.logger.info(self.vapi.cli("sh int feat pg0"))
1094 # Packet destined to unknown unicast is sent on the epg uplink ...
1096 pkt_intra_epg_220_to_uplink = (Ether(src=self.pg0.remote_mac,
1097 dst="00:00:00:33:44:55") /
1098 IP(src=eps[0].ip4.address,
1100 UDP(sport=1234, dport=1234) /
1103 self.send_and_expect_bridged(eps[0].itf,
1104 pkt_intra_epg_220_to_uplink * NUM_PKTS,
1106 # ... and nowhere else
1107 self.pg1.get_capture(0, timeout=0.1)
1108 self.pg1.assert_nothing_captured(remark="Flood onto other VMS")
1110 pkt_intra_epg_221_to_uplink = (Ether(src=self.pg2.remote_mac,
1111 dst="00:00:00:33:44:66") /
1112 IP(src=eps[0].ip4.address,
1114 UDP(sport=1234, dport=1234) /
1117 self.send_and_expect_bridged(eps[2].itf,
1118 pkt_intra_epg_221_to_uplink * NUM_PKTS,
1122 # Packets from the uplink are forwarded in the absence of a contract
1124 pkt_intra_epg_220_from_uplink = (Ether(src="00:00:00:33:44:55",
1125 dst=self.pg0.remote_mac) /
1126 IP(src=eps[0].ip4.address,
1128 UDP(sport=1234, dport=1234) /
1131 self.send_and_expect_bridged(self.pg4,
1132 pkt_intra_epg_220_from_uplink * NUM_PKTS,
1136 # in the absence of policy, endpoints in the same EPG
1139 pkt_intra_epg = (Ether(src=self.pg0.remote_mac,
1140 dst=self.pg1.remote_mac) /
1141 IP(src=eps[0].ip4.address,
1142 dst=eps[1].ip4.address) /
1143 UDP(sport=1234, dport=1234) /
1146 self.send_and_expect_bridged(self.pg0,
1147 pkt_intra_epg * NUM_PKTS,
1151 # in the absence of policy, endpoints in the different EPG
1152 # cannot communicate
1154 pkt_inter_epg_220_to_221 = (Ether(src=self.pg0.remote_mac,
1155 dst=self.pg2.remote_mac) /
1156 IP(src=eps[0].ip4.address,
1157 dst=eps[2].ip4.address) /
1158 UDP(sport=1234, dport=1234) /
1160 pkt_inter_epg_221_to_220 = (Ether(src=self.pg2.remote_mac,
1161 dst=self.pg0.remote_mac) /
1162 IP(src=eps[2].ip4.address,
1163 dst=eps[0].ip4.address) /
1164 UDP(sport=1234, dport=1234) /
1166 pkt_inter_epg_220_to_222 = (Ether(src=self.pg0.remote_mac,
1167 dst=str(self.router_mac)) /
1168 IP(src=eps[0].ip4.address,
1169 dst=eps[3].ip4.address) /
1170 UDP(sport=1234, dport=1234) /
1173 self.send_and_assert_no_replies(eps[0].itf,
1174 pkt_inter_epg_220_to_221 * NUM_PKTS)
1175 self.send_and_assert_no_replies(eps[0].itf,
1176 pkt_inter_epg_220_to_222 * NUM_PKTS)
1179 # A uni-directional contract from EPG 220 -> 221
1181 acl = VppGbpAcl(self)
1182 rule = acl.create_rule(permit_deny=1, proto=17)
1183 rule2 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
1184 acl_index = acl.add_vpp_config([rule, rule2])
1185 c1 = VppGbpContract(
1186 self, epgs[0].sclass, epgs[1].sclass, acl_index,
1187 [VppGbpContractRule(
1188 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1189 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1192 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1193 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1195 [ETH_P_IP, ETH_P_IPV6])
1198 self.send_and_expect_bridged(eps[0].itf,
1199 pkt_inter_epg_220_to_221 * NUM_PKTS,
1201 self.send_and_assert_no_replies(eps[0].itf,
1202 pkt_inter_epg_220_to_222 * NUM_PKTS)
1205 # contract for the return direction
1207 c2 = VppGbpContract(
1208 self, epgs[1].sclass, epgs[0].sclass, acl_index,
1209 [VppGbpContractRule(
1210 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1211 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1214 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1215 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1217 [ETH_P_IP, ETH_P_IPV6])
1220 self.send_and_expect_bridged(eps[0].itf,
1221 pkt_inter_epg_220_to_221 * NUM_PKTS,
1223 self.send_and_expect_bridged(eps[2].itf,
1224 pkt_inter_epg_221_to_220 * NUM_PKTS,
1227 ds = c2.get_drop_stats()
1228 self.assertEqual(ds['packets'], 0)
1229 ps = c2.get_permit_stats()
1230 self.assertEqual(ps['packets'], NUM_PKTS)
1233 # the contract does not allow non-IP
1235 pkt_non_ip_inter_epg_220_to_221 = (Ether(src=self.pg0.remote_mac,
1236 dst=self.pg2.remote_mac) /
1238 self.send_and_assert_no_replies(eps[0].itf,
1239 pkt_non_ip_inter_epg_220_to_221 * 17)
1242 # check that inter group is still disabled for the groups
1243 # not in the contract.
1245 self.send_and_assert_no_replies(eps[0].itf,
1246 pkt_inter_epg_220_to_222 * NUM_PKTS)
1249 # A uni-directional contract from EPG 220 -> 222 'L3 routed'
1251 c3 = VppGbpContract(
1252 self, epgs[0].sclass, epgs[2].sclass, acl_index,
1253 [VppGbpContractRule(
1254 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1255 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1258 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1259 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1261 [ETH_P_IP, ETH_P_IPV6])
1264 self.logger.info(self.vapi.cli("sh gbp contract"))
1266 self.send_and_expect_routed(eps[0].itf,
1267 pkt_inter_epg_220_to_222 * NUM_PKTS,
1269 str(self.router_mac))
1272 # remove both contracts, traffic stops in both directions
1274 c2.remove_vpp_config()
1275 c1.remove_vpp_config()
1276 c3.remove_vpp_config()
1277 acl.remove_vpp_config()
1279 self.send_and_assert_no_replies(eps[2].itf,
1280 pkt_inter_epg_221_to_220 * NUM_PKTS)
1281 self.send_and_assert_no_replies(eps[0].itf,
1282 pkt_inter_epg_220_to_221 * NUM_PKTS)
1283 self.send_and_expect_bridged(eps[0].itf,
1284 pkt_intra_epg * NUM_PKTS,
1288 # EPs to the outside world
1291 # in the EP's RD an external subnet via the NAT EPG's recirc
1293 self, rd0, "0.0.0.0", 0,
1294 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1295 sw_if_index=recirc_nat.recirc.sw_if_index,
1296 sclass=epg_nat.sclass)
1298 self, rd0, "11.0.0.0", 8,
1299 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1300 sw_if_index=recirc_nat.recirc.sw_if_index,
1301 sclass=epg_nat.sclass)
1302 se16 = VppGbpSubnet(
1304 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1305 sw_if_index=recirc_nat.recirc.sw_if_index,
1306 sclass=epg_nat.sclass)
1307 # in the NAT RD an external subnet via the NAT EPG's uplink
1309 self, rd20, "0.0.0.0", 0,
1310 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1311 sw_if_index=epg_nat.uplink.sw_if_index,
1312 sclass=epg_nat.sclass)
1313 se36 = VppGbpSubnet(
1314 self, rd20, "::", 0,
1315 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1316 sw_if_index=epg_nat.uplink.sw_if_index,
1317 sclass=epg_nat.sclass)
1319 self, rd20, "11.0.0.0", 8,
1320 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1321 sw_if_index=epg_nat.uplink.sw_if_index,
1322 sclass=epg_nat.sclass)
1323 se1.add_vpp_config()
1324 se2.add_vpp_config()
1325 se16.add_vpp_config()
1326 se3.add_vpp_config()
1327 se36.add_vpp_config()
1328 se4.add_vpp_config()
1330 self.logger.info(self.vapi.cli("sh ip fib 0.0.0.0/0"))
1331 self.logger.info(self.vapi.cli("sh ip fib 11.0.0.1"))
1332 self.logger.info(self.vapi.cli("sh ip6 fib ::/0"))
1333 self.logger.info(self.vapi.cli("sh ip6 fib %s" %
1337 # From an EP to an outside address: IN2OUT
1339 pkt_inter_epg_220_to_global = (Ether(src=self.pg0.remote_mac,
1340 dst=str(self.router_mac)) /
1341 IP(src=eps[0].ip4.address,
1343 UDP(sport=1234, dport=1234) /
1347 self.send_and_assert_no_replies(eps[0].itf,
1348 pkt_inter_epg_220_to_global * NUM_PKTS)
1350 acl2 = VppGbpAcl(self)
1351 rule = acl2.create_rule(permit_deny=1, proto=17, sport_from=1234,
1352 sport_to=1234, dport_from=1234, dport_to=1234)
1353 rule2 = acl2.create_rule(is_ipv6=1, permit_deny=1, proto=17,
1354 sport_from=1234, sport_to=1234,
1355 dport_from=1234, dport_to=1234)
1357 acl_index2 = acl2.add_vpp_config([rule, rule2])
1358 c4 = VppGbpContract(
1359 self, epgs[0].sclass, epgs[3].sclass, acl_index2,
1360 [VppGbpContractRule(
1361 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1362 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1365 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1366 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1368 [ETH_P_IP, ETH_P_IPV6])
1371 self.send_and_expect_natted(eps[0].itf,
1372 pkt_inter_epg_220_to_global * NUM_PKTS,
1374 eps[0].fip4.address)
1376 pkt_inter_epg_220_to_global = (Ether(src=self.pg0.remote_mac,
1377 dst=str(self.router_mac)) /
1378 IPv6(src=eps[0].ip6.address,
1380 UDP(sport=1234, dport=1234) /
1383 self.send_and_expect_natted6(self.pg0,
1384 pkt_inter_epg_220_to_global * NUM_PKTS,
1386 eps[0].fip6.address)
1389 # From a global address to an EP: OUT2IN
1391 pkt_inter_epg_220_from_global = (Ether(src=str(self.router_mac),
1392 dst=self.pg0.remote_mac) /
1393 IP(dst=eps[0].fip4.address,
1395 UDP(sport=1234, dport=1234) /
1398 self.send_and_assert_no_replies(
1399 self.pg7, pkt_inter_epg_220_from_global * NUM_PKTS)
1401 c5 = VppGbpContract(
1402 self, epgs[3].sclass, epgs[0].sclass, acl_index2,
1403 [VppGbpContractRule(
1404 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1405 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1408 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1409 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1411 [ETH_P_IP, ETH_P_IPV6])
1414 self.send_and_expect_unnatted(self.pg7,
1415 pkt_inter_epg_220_from_global * NUM_PKTS,
1419 pkt_inter_epg_220_from_global = (Ether(src=str(self.router_mac),
1420 dst=self.pg0.remote_mac) /
1421 IPv6(dst=eps[0].fip6.address,
1423 UDP(sport=1234, dport=1234) /
1426 self.send_and_expect_unnatted6(
1428 pkt_inter_epg_220_from_global * NUM_PKTS,
1433 # From a local VM to another local VM using resp. public addresses:
1436 pkt_intra_epg_220_global = (Ether(src=self.pg0.remote_mac,
1437 dst=str(self.router_mac)) /
1438 IP(src=eps[0].ip4.address,
1439 dst=eps[1].fip4.address) /
1440 UDP(sport=1234, dport=1234) /
1443 self.send_and_expect_double_natted(eps[0].itf,
1444 pkt_intra_epg_220_global * NUM_PKTS,
1446 eps[0].fip4.address,
1449 pkt_intra_epg_220_global = (Ether(src=self.pg0.remote_mac,
1450 dst=str(self.router_mac)) /
1451 IPv6(src=eps[0].ip6.address,
1452 dst=eps[1].fip6.address) /
1453 UDP(sport=1234, dport=1234) /
1456 self.send_and_expect_double_natted6(
1458 pkt_intra_epg_220_global * NUM_PKTS,
1460 eps[0].fip6.address,
1467 # del static mappings for each EP from the 10/8 to 11/8 network
1468 flags = self.config_flags.NAT_IS_ADDR_ONLY
1469 self.vapi.nat44_add_del_static_mapping(
1471 local_ip_address=ep.ip4.bytes,
1472 external_ip_address=ep.fip4.bytes,
1473 external_sw_if_index=0xFFFFFFFF,
1476 self.vapi.nat66_add_del_static_mapping(
1477 local_ip_address=ep.ip6.bytes,
1478 external_ip_address=ep.fip6.bytes,
1482 # IP config on the BVI interfaces
1483 if epg != epgs[0] and epg != epgs[3]:
1484 flags = self.config_flags.NAT_IS_INSIDE
1485 self.vapi.nat44_interface_add_del_feature(
1486 sw_if_index=epg.bvi.sw_if_index,
1489 self.vapi.nat66_add_del_interface(
1490 is_add=0, flags=flags,
1491 sw_if_index=epg.bvi.sw_if_index)
1493 for recirc in recircs:
1494 self.vapi.nat44_interface_add_del_feature(
1495 sw_if_index=recirc.recirc.sw_if_index,
1497 self.vapi.nat66_add_del_interface(
1499 sw_if_index=recirc.recirc.sw_if_index)
1501 def wait_for_ep_timeout(self, sw_if_index=None, ip=None, mac=None,
1502 n_tries=100, s_time=1):
1504 if not find_gbp_endpoint(self, sw_if_index, ip, mac):
1506 n_tries = n_tries - 1
1508 self.assertFalse(find_gbp_endpoint(self, sw_if_index, ip, mac))
1511 def test_gbp_learn_l2(self):
1512 """ GBP L2 Endpoint Learning """
1514 self.vapi.cli("clear errors")
1516 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
1517 learnt = [{'mac': '00:00:11:11:11:01',
1519 'ip6': '2001:10::2'},
1520 {'mac': '00:00:11:11:11:02',
1522 'ip6': '2001:10::3'}]
1527 gt4 = VppIpTable(self, 1)
1528 gt4.add_vpp_config()
1529 gt6 = VppIpTable(self, 1, is_ip6=True)
1530 gt6.add_vpp_config()
1532 rd1 = VppGbpRouteDomain(self, 1, gt4, gt6)
1533 rd1.add_vpp_config()
1536 # Pg2 hosts the vxlan tunnel, hosts on pg2 to act as TEPs
1537 # Pg3 hosts the IP4 UU-flood VXLAN tunnel
1538 # Pg4 hosts the IP6 UU-flood VXLAN tunnel
1540 self.pg2.config_ip4()
1541 self.pg2.resolve_arp()
1542 self.pg2.generate_remote_hosts(4)
1543 self.pg2.configure_ipv4_neighbors()
1544 self.pg3.config_ip4()
1545 self.pg3.resolve_arp()
1546 self.pg4.config_ip4()
1547 self.pg4.resolve_arp()
1550 # Add a mcast destination VXLAN-GBP tunnel for B&M traffic
1552 tun_bm = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
1555 tun_bm.add_vpp_config()
1558 # a GBP bridge domain with a BVI and a UU-flood interface
1560 bd1 = VppBridgeDomain(self, 1)
1561 bd1.add_vpp_config()
1562 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0, self.pg3, tun_bm)
1563 gbd1.add_vpp_config()
1565 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1566 self.logger.info(self.vapi.cli("sh gbp bridge"))
1568 # ... and has a /32 applied
1569 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
1570 ip_addr.add_vpp_config()
1573 # The Endpoint-group in which we are learning endpoints
1575 epg_220 = VppGbpEndpointGroup(self, 220, 112, rd1, gbd1,
1579 VppGbpEndpointRetention(2))
1580 epg_220.add_vpp_config()
1581 epg_330 = VppGbpEndpointGroup(self, 330, 113, rd1, gbd1,
1585 VppGbpEndpointRetention(2))
1586 epg_330.add_vpp_config()
1589 # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
1592 vx_tun_l2_1 = VppGbpVxlanTunnel(
1593 self, 99, bd1.bd_id,
1594 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L2,
1596 vx_tun_l2_1.add_vpp_config()
1599 # A static endpoint that the learnt endpoints are trying to
1602 ep = VppGbpEndpoint(self, self.pg0,
1604 "10.0.0.127", "11.0.0.127",
1605 "2001:10::1", "3001::1")
1608 self.assertTrue(find_route(self, ep.ip4.address, 32, table_id=1))
1610 # a packet with an sclass from an unknown EPG
1611 p = (Ether(src=self.pg2.remote_mac,
1612 dst=self.pg2.local_mac) /
1613 IP(src=self.pg2.remote_hosts[0].ip4,
1614 dst=self.pg2.local_ip4) /
1615 UDP(sport=1234, dport=48879) /
1616 VXLAN(vni=99, gpid=88, flags=0x88) /
1617 Ether(src=learnt[0]["mac"], dst=ep.mac) /
1618 IP(src=learnt[0]["ip"], dst=ep.ip4.address) /
1619 UDP(sport=1234, dport=1234) /
1622 self.send_and_assert_no_replies(self.pg2, p)
1624 self.logger.info(self.vapi.cli("sh error"))
1625 # self.assert_packet_counter_equal(
1626 # '/err/gbp-policy-port/drop-no-contract', 1)
1629 # we should not have learnt a new tunnel endpoint, since
1630 # the EPG was not learnt.
1632 self.assertEqual(INDEX_INVALID,
1633 find_vxlan_gbp_tunnel(self,
1635 self.pg2.remote_hosts[0].ip4,
1638 # epg is not learnt, because the EPG is unknown
1639 self.assertEqual(len(self.vapi.gbp_endpoint_dump()), 1)
1642 # Learn new EPs from IP packets
1644 for ii, l in enumerate(learnt):
1645 # a packet with an sclass from a known EPG
1646 # arriving on an unknown TEP
1647 p = (Ether(src=self.pg2.remote_mac,
1648 dst=self.pg2.local_mac) /
1649 IP(src=self.pg2.remote_hosts[1].ip4,
1650 dst=self.pg2.local_ip4) /
1651 UDP(sport=1234, dport=48879) /
1652 VXLAN(vni=99, gpid=112, flags=0x88) /
1653 Ether(src=l['mac'], dst=ep.mac) /
1654 IP(src=l['ip'], dst=ep.ip4.address) /
1655 UDP(sport=1234, dport=1234) /
1658 rx = self.send_and_expect(self.pg2, [p], self.pg0)
1661 tep1_sw_if_index = find_vxlan_gbp_tunnel(
1664 self.pg2.remote_hosts[1].ip4,
1666 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
1669 # the EP is learnt via the learnt TEP
1670 # both from its MAC and its IP
1672 self.assertTrue(find_gbp_endpoint(self,
1673 vx_tun_l2_1.sw_if_index,
1675 self.assertTrue(find_gbp_endpoint(self,
1676 vx_tun_l2_1.sw_if_index,
1679 # self.assert_packet_counter_equal(
1680 # '/err/gbp-policy-port/allow-intra-sclass', 2)
1682 self.logger.info(self.vapi.cli("show gbp endpoint"))
1683 self.logger.info(self.vapi.cli("show gbp vxlan"))
1684 self.logger.info(self.vapi.cli("show ip mfib"))
1687 # If we sleep for the threshold time, the learnt endpoints should
1691 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1695 # Learn new EPs from GARP packets received on the BD's mcast tunnel
1697 for ii, l in enumerate(learnt):
1698 # a packet with an sclass from a known EPG
1699 # arriving on an unknown TEP
1700 p = (Ether(src=self.pg2.remote_mac,
1701 dst=self.pg2.local_mac) /
1702 IP(src=self.pg2.remote_hosts[1].ip4,
1704 UDP(sport=1234, dport=48879) /
1705 VXLAN(vni=88, gpid=112, flags=0x88) /
1706 Ether(src=l['mac'], dst="ff:ff:ff:ff:ff:ff") /
1708 psrc=l['ip'], pdst=l['ip'],
1709 hwsrc=l['mac'], hwdst="ff:ff:ff:ff:ff:ff"))
1711 rx = self.send_and_expect(self.pg4, [p], self.pg0)
1714 tep1_sw_if_index = find_vxlan_gbp_tunnel(
1717 self.pg2.remote_hosts[1].ip4,
1719 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
1722 # the EP is learnt via the learnt TEP
1723 # both from its MAC and its IP
1725 self.assertTrue(find_gbp_endpoint(self,
1726 vx_tun_l2_1.sw_if_index,
1728 self.assertTrue(find_gbp_endpoint(self,
1729 vx_tun_l2_1.sw_if_index,
1733 # wait for the learnt endpoints to age out
1736 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1740 # Learn new EPs from L2 packets
1742 for ii, l in enumerate(learnt):
1743 # a packet with an sclass from a known EPG
1744 # arriving on an unknown TEP
1745 p = (Ether(src=self.pg2.remote_mac,
1746 dst=self.pg2.local_mac) /
1747 IP(src=self.pg2.remote_hosts[1].ip4,
1748 dst=self.pg2.local_ip4) /
1749 UDP(sport=1234, dport=48879) /
1750 VXLAN(vni=99, gpid=112, flags=0x88) /
1751 Ether(src=l['mac'], dst=ep.mac) /
1754 rx = self.send_and_expect(self.pg2, [p], self.pg0)
1757 tep1_sw_if_index = find_vxlan_gbp_tunnel(
1760 self.pg2.remote_hosts[1].ip4,
1762 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
1765 # the EP is learnt via the learnt TEP
1766 # both from its MAC and its IP
1768 self.assertTrue(find_gbp_endpoint(self,
1769 vx_tun_l2_1.sw_if_index,
1772 self.logger.info(self.vapi.cli("show gbp endpoint"))
1773 self.logger.info(self.vapi.cli("show gbp vxlan"))
1774 self.logger.info(self.vapi.cli("show vxlan-gbp tunnel"))
1777 # wait for the learnt endpoints to age out
1780 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1784 # repeat. the do not learn bit is set so the EPs are not learnt
1787 # a packet with an sclass from a known EPG
1788 p = (Ether(src=self.pg2.remote_mac,
1789 dst=self.pg2.local_mac) /
1790 IP(src=self.pg2.remote_hosts[1].ip4,
1791 dst=self.pg2.local_ip4) /
1792 UDP(sport=1234, dport=48879) /
1793 VXLAN(vni=99, gpid=112, flags=0x88, gpflags="D") /
1794 Ether(src=l['mac'], dst=ep.mac) /
1795 IP(src=l['ip'], dst=ep.ip4.address) /
1796 UDP(sport=1234, dport=1234) /
1799 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
1802 self.assertFalse(find_gbp_endpoint(self,
1803 vx_tun_l2_1.sw_if_index,
1810 # a packet with an sclass from a known EPG
1811 p = (Ether(src=self.pg2.remote_mac,
1812 dst=self.pg2.local_mac) /
1813 IP(src=self.pg2.remote_hosts[1].ip4,
1814 dst=self.pg2.local_ip4) /
1815 UDP(sport=1234, dport=48879) /
1816 VXLAN(vni=99, gpid=112, flags=0x88) /
1817 Ether(src=l['mac'], dst=ep.mac) /
1818 IP(src=l['ip'], dst=ep.ip4.address) /
1819 UDP(sport=1234, dport=1234) /
1822 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
1824 self.assertTrue(find_gbp_endpoint(self,
1825 vx_tun_l2_1.sw_if_index,
1829 # Static EP replies to dynamics
1831 self.logger.info(self.vapi.cli("sh l2fib bd_id 1"))
1833 p = (Ether(src=ep.mac, dst=l['mac']) /
1834 IP(dst=l['ip'], src=ep.ip4.address) /
1835 UDP(sport=1234, dport=1234) /
1838 rxs = self.send_and_expect(self.pg0, p * 17, self.pg2)
1841 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
1842 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
1843 self.assertEqual(rx[UDP].dport, 48879)
1844 # the UDP source port is a random value for hashing
1845 self.assertEqual(rx[VXLAN].gpid, 112)
1846 self.assertEqual(rx[VXLAN].vni, 99)
1847 self.assertTrue(rx[VXLAN].flags.G)
1848 self.assertTrue(rx[VXLAN].flags.Instance)
1849 self.assertTrue(rx[VXLAN].gpflags.A)
1850 self.assertFalse(rx[VXLAN].gpflags.D)
1853 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1857 # repeat in the other EPG
1858 # there's no contract between 220 and 330, but the A-bit is set
1859 # so the packet is cleared for delivery
1862 # a packet with an sclass from a known EPG
1863 p = (Ether(src=self.pg2.remote_mac,
1864 dst=self.pg2.local_mac) /
1865 IP(src=self.pg2.remote_hosts[1].ip4,
1866 dst=self.pg2.local_ip4) /
1867 UDP(sport=1234, dport=48879) /
1868 VXLAN(vni=99, gpid=113, flags=0x88, gpflags='A') /
1869 Ether(src=l['mac'], dst=ep.mac) /
1870 IP(src=l['ip'], dst=ep.ip4.address) /
1871 UDP(sport=1234, dport=1234) /
1874 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
1876 self.assertTrue(find_gbp_endpoint(self,
1877 vx_tun_l2_1.sw_if_index,
1881 # static EP cannot reach the learnt EPs since there is no contract
1882 # only test 1 EP as the others could timeout
1884 p = (Ether(src=ep.mac, dst=l['mac']) /
1885 IP(dst=learnt[0]['ip'], src=ep.ip4.address) /
1886 UDP(sport=1234, dport=1234) /
1889 self.send_and_assert_no_replies(self.pg0, [p])
1892 # refresh the entries after the check for no replies above
1895 # a packet with an sclass from a known EPG
1896 p = (Ether(src=self.pg2.remote_mac,
1897 dst=self.pg2.local_mac) /
1898 IP(src=self.pg2.remote_hosts[1].ip4,
1899 dst=self.pg2.local_ip4) /
1900 UDP(sport=1234, dport=48879) /
1901 VXLAN(vni=99, gpid=113, flags=0x88, gpflags='A') /
1902 Ether(src=l['mac'], dst=ep.mac) /
1903 IP(src=l['ip'], dst=ep.ip4.address) /
1904 UDP(sport=1234, dport=1234) /
1907 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
1909 self.assertTrue(find_gbp_endpoint(self,
1910 vx_tun_l2_1.sw_if_index,
1914 # Add the contract so they can talk
1916 acl = VppGbpAcl(self)
1917 rule = acl.create_rule(permit_deny=1, proto=17)
1918 rule2 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
1919 acl_index = acl.add_vpp_config([rule, rule2])
1920 c1 = VppGbpContract(
1921 self, epg_220.sclass, epg_330.sclass, acl_index,
1922 [VppGbpContractRule(
1923 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1924 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1927 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1928 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1930 [ETH_P_IP, ETH_P_IPV6])
1934 p = (Ether(src=ep.mac, dst=l['mac']) /
1935 IP(dst=l['ip'], src=ep.ip4.address) /
1936 UDP(sport=1234, dport=1234) /
1939 self.send_and_expect(self.pg0, [p], self.pg2)
1942 # send UU packets from the local EP
1944 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1945 self.logger.info(self.vapi.cli("sh gbp bridge"))
1946 p_uu = (Ether(src=ep.mac, dst="00:11:11:11:11:11") /
1947 IP(dst="10.0.0.133", src=ep.ip4.address) /
1948 UDP(sport=1234, dport=1234) /
1950 rxs = self.send_and_expect(ep.itf, [p_uu], gbd1.uu_fwd)
1952 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1954 p_bm = (Ether(src=ep.mac, dst="ff:ff:ff:ff:ff:ff") /
1955 IP(dst="10.0.0.133", src=ep.ip4.address) /
1956 UDP(sport=1234, dport=1234) /
1958 rxs = self.send_and_expect_only(ep.itf, [p_bm], tun_bm.mcast_itf)
1961 self.assertEqual(rx[IP].src, self.pg4.local_ip4)
1962 self.assertEqual(rx[IP].dst, "239.1.1.1")
1963 self.assertEqual(rx[UDP].dport, 48879)
1964 # the UDP source port is a random value for hashing
1965 self.assertEqual(rx[VXLAN].gpid, 112)
1966 self.assertEqual(rx[VXLAN].vni, 88)
1967 self.assertTrue(rx[VXLAN].flags.G)
1968 self.assertTrue(rx[VXLAN].flags.Instance)
1969 self.assertFalse(rx[VXLAN].gpflags.A)
1970 self.assertFalse(rx[VXLAN].gpflags.D)
1973 # Check v6 Endpoints
1976 # a packet with an sclass from a known EPG
1977 p = (Ether(src=self.pg2.remote_mac,
1978 dst=self.pg2.local_mac) /
1979 IP(src=self.pg2.remote_hosts[1].ip4,
1980 dst=self.pg2.local_ip4) /
1981 UDP(sport=1234, dport=48879) /
1982 VXLAN(vni=99, gpid=113, flags=0x88, gpflags='A') /
1983 Ether(src=l['mac'], dst=ep.mac) /
1984 IPv6(src=l['ip6'], dst=ep.ip6.address) /
1985 UDP(sport=1234, dport=1234) /
1988 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
1990 self.assertTrue(find_gbp_endpoint(self,
1991 vx_tun_l2_1.sw_if_index,
1995 # L3 Endpoint Learning
1996 # - configured on the bridge's BVI
2003 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
2005 self.pg2.unconfig_ip4()
2006 self.pg3.unconfig_ip4()
2007 self.pg4.unconfig_ip4()
2009 self.logger.info(self.vapi.cli("sh int"))
2010 self.logger.info(self.vapi.cli("sh gbp vxlan"))
2012 def test_gbp_contract(self):
2013 """ GBP CONTRACTS """
2018 bd1 = VppBridgeDomain(self, 1, arp_term=0)
2019 bd2 = VppBridgeDomain(self, 2, arp_term=0)
2021 bd1.add_vpp_config()
2022 bd2.add_vpp_config()
2024 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0)
2025 gbd2 = VppGbpBridgeDomain(self, bd2, self.loop1)
2027 gbd1.add_vpp_config()
2028 gbd2.add_vpp_config()
2033 gt4 = VppIpTable(self, 0)
2034 gt4.add_vpp_config()
2035 gt6 = VppIpTable(self, 0, is_ip6=True)
2036 gt6.add_vpp_config()
2038 rd0 = VppGbpRouteDomain(self, 0, gt4, gt6, None, None)
2040 rd0.add_vpp_config()
2043 # 3 EPGs, 2 of which share a BD.
2045 epgs = [VppGbpEndpointGroup(self, 220, 1220, rd0, gbd1,
2047 "10.0.0.128", "2001:10::128"),
2048 VppGbpEndpointGroup(self, 221, 1221, rd0, gbd1,
2050 "10.0.1.128", "2001:10:1::128"),
2051 VppGbpEndpointGroup(self, 222, 1222, rd0, gbd2,
2053 "10.0.2.128", "2001:10:2::128")]
2055 # 4 end-points, 2 in the same subnet, 3 in the same BD
2057 eps = [VppGbpEndpoint(self, self.pg0,
2059 "10.0.0.1", "11.0.0.1",
2060 "2001:10::1", "3001::1"),
2061 VppGbpEndpoint(self, self.pg1,
2063 "10.0.0.2", "11.0.0.2",
2064 "2001:10::2", "3001::2"),
2065 VppGbpEndpoint(self, self.pg2,
2067 "10.0.1.1", "11.0.0.3",
2068 "2001:10:1::1", "3001::3"),
2069 VppGbpEndpoint(self, self.pg3,
2071 "10.0.2.1", "11.0.0.4",
2072 "2001:10:2::1", "3001::4")]
2075 # Config related to each of the EPGs
2078 # IP config on the BVI interfaces
2080 VppIpInterfaceBind(self, epg.bvi, epg.rd.t4).add_vpp_config()
2081 VppIpInterfaceBind(self, epg.bvi, epg.rd.t6).add_vpp_config()
2082 self.vapi.sw_interface_set_mac_address(
2083 epg.bvi.sw_if_index,
2084 self.router_mac.packed)
2086 if_ip4 = VppIpInterfaceAddress(self, epg.bvi, epg.bvi_ip4, 32)
2087 if_ip6 = VppIpInterfaceAddress(self, epg.bvi, epg.bvi_ip6, 128)
2088 if_ip4.add_vpp_config()
2089 if_ip6.add_vpp_config()
2091 # add the BD ARP termination entry for BVI IP
2092 epg.bd_arp_ip4 = VppBridgeDomainArpEntry(self, epg.bd.bd,
2093 str(self.router_mac),
2094 epg.bvi_ip4.address)
2095 epg.bd_arp_ip4.add_vpp_config()
2098 epg.add_vpp_config()
2106 self.logger.info(self.vapi.cli("show gbp endpoint"))
2107 self.logger.info(self.vapi.cli("show interface"))
2108 self.logger.info(self.vapi.cli("show br"))
2111 # Intra epg allowed without contract
2113 pkt_intra_epg_220_to_220 = (Ether(src=self.pg0.remote_mac,
2114 dst=self.pg1.remote_mac) /
2115 IP(src=eps[0].ip4.address,
2116 dst=eps[1].ip4.address) /
2117 UDP(sport=1234, dport=1234) /
2120 self.send_and_expect_bridged(self.pg0,
2121 pkt_intra_epg_220_to_220 * 65,
2125 # Inter epg denied without contract
2127 pkt_inter_epg_220_to_221 = (Ether(src=self.pg0.remote_mac,
2128 dst=self.pg2.remote_mac) /
2129 IP(src=eps[0].ip4.address,
2130 dst=eps[2].ip4.address) /
2131 UDP(sport=1234, dport=1234) /
2134 self.send_and_assert_no_replies(self.pg0, pkt_inter_epg_220_to_221)
2137 # A uni-directional contract from EPG 220 -> 221
2139 acl = VppGbpAcl(self)
2140 rule = acl.create_rule(permit_deny=1, proto=17)
2141 rule2 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
2142 acl_index = acl.add_vpp_config([rule, rule2])
2143 c1 = VppGbpContract(
2144 self, epgs[0].sclass, epgs[1].sclass, acl_index,
2145 [VppGbpContractRule(
2146 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2147 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2150 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2151 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2153 [ETH_P_IP, ETH_P_IPV6])
2156 self.send_and_expect_bridged(eps[0].itf,
2157 pkt_inter_epg_220_to_221 * 65,
2160 pkt_inter_epg_220_to_222 = (Ether(src=self.pg0.remote_mac,
2161 dst=str(self.router_mac)) /
2162 IP(src=eps[0].ip4.address,
2163 dst=eps[3].ip4.address) /
2164 UDP(sport=1234, dport=1234) /
2166 self.send_and_assert_no_replies(eps[0].itf,
2167 pkt_inter_epg_220_to_222 * 65)
2170 # contract for the return direction
2172 c2 = VppGbpContract(
2173 self, epgs[1].sclass, epgs[0].sclass, acl_index,
2174 [VppGbpContractRule(
2175 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2176 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2179 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2180 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2182 [ETH_P_IP, ETH_P_IPV6])
2185 self.send_and_expect_bridged(eps[0].itf,
2186 pkt_inter_epg_220_to_221 * 65,
2188 pkt_inter_epg_221_to_220 = (Ether(src=self.pg2.remote_mac,
2189 dst=self.pg0.remote_mac) /
2190 IP(src=eps[2].ip4.address,
2191 dst=eps[0].ip4.address) /
2192 UDP(sport=1234, dport=1234) /
2194 self.send_and_expect_bridged(eps[2].itf,
2195 pkt_inter_epg_221_to_220 * 65,
2199 # contract between 220 and 222 uni-direction
2201 c3 = VppGbpContract(
2202 self, epgs[0].sclass, epgs[2].sclass, acl_index,
2203 [VppGbpContractRule(
2204 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2205 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2208 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2209 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2211 [ETH_P_IP, ETH_P_IPV6])
2214 self.send_and_expect(eps[0].itf,
2215 pkt_inter_epg_220_to_222 * 65,
2218 c3.remove_vpp_config()
2219 c1.remove_vpp_config()
2220 c2.remove_vpp_config()
2221 acl.remove_vpp_config()
2223 def test_gbp_bd_flags(self):
2224 """ GBP BD FLAGS """
2229 gt4 = VppIpTable(self, 1)
2230 gt4.add_vpp_config()
2231 gt6 = VppIpTable(self, 1, is_ip6=True)
2232 gt6.add_vpp_config()
2234 rd1 = VppGbpRouteDomain(self, 1, gt4, gt6)
2235 rd1.add_vpp_config()
2238 # Pg3 hosts the IP4 UU-flood VXLAN tunnel
2239 # Pg4 hosts the IP6 UU-flood VXLAN tunnel
2241 self.pg3.config_ip4()
2242 self.pg3.resolve_arp()
2243 self.pg4.config_ip4()
2244 self.pg4.resolve_arp()
2247 # Add a mcast destination VXLAN-GBP tunnel for B&M traffic
2249 tun_bm = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
2252 tun_bm.add_vpp_config()
2255 # a GBP bridge domain with a BVI and a UU-flood interface
2257 bd1 = VppBridgeDomain(self, 1)
2258 bd1.add_vpp_config()
2260 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0, self.pg3, tun_bm,
2261 uu_drop=True, bm_drop=True)
2262 gbd1.add_vpp_config()
2264 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2265 self.logger.info(self.vapi.cli("sh gbp bridge"))
2267 # ... and has a /32 applied
2268 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2269 ip_addr.add_vpp_config()
2272 # The Endpoint-group
2274 epg_220 = VppGbpEndpointGroup(self, 220, 112, rd1, gbd1,
2278 VppGbpEndpointRetention(2))
2279 epg_220.add_vpp_config()
2281 ep = VppGbpEndpoint(self, self.pg0,
2283 "10.0.0.127", "11.0.0.127",
2284 "2001:10::1", "3001::1")
2287 # send UU/BM packet from the local EP with UU drop and BM drop enabled
2290 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2291 self.logger.info(self.vapi.cli("sh gbp bridge"))
2292 p_uu = (Ether(src=ep.mac, dst="00:11:11:11:11:11") /
2293 IP(dst="10.0.0.133", src=ep.ip4.address) /
2294 UDP(sport=1234, dport=1234) /
2296 self.send_and_assert_no_replies(ep.itf, [p_uu])
2298 p_bm = (Ether(src=ep.mac, dst="ff:ff:ff:ff:ff:ff") /
2299 IP(dst="10.0.0.133", src=ep.ip4.address) /
2300 UDP(sport=1234, dport=1234) /
2302 self.send_and_assert_no_replies(ep.itf, [p_bm])
2304 self.pg3.unconfig_ip4()
2305 self.pg4.unconfig_ip4()
2307 self.logger.info(self.vapi.cli("sh int"))
2309 def test_gbp_learn_vlan_l2(self):
2310 """ GBP L2 Endpoint w/ VLANs"""
2312 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
2313 learnt = [{'mac': '00:00:11:11:11:01',
2315 'ip6': '2001:10::2'},
2316 {'mac': '00:00:11:11:11:02',
2318 'ip6': '2001:10::3'}]
2323 gt4 = VppIpTable(self, 1)
2324 gt4.add_vpp_config()
2325 gt6 = VppIpTable(self, 1, is_ip6=True)
2326 gt6.add_vpp_config()
2328 rd1 = VppGbpRouteDomain(self, 1, gt4, gt6)
2329 rd1.add_vpp_config()
2332 # Pg2 hosts the vxlan tunnel, hosts on pg2 to act as TEPs
2334 self.pg2.config_ip4()
2335 self.pg2.resolve_arp()
2336 self.pg2.generate_remote_hosts(4)
2337 self.pg2.configure_ipv4_neighbors()
2338 self.pg3.config_ip4()
2339 self.pg3.resolve_arp()
2342 # The EP will be on a vlan sub-interface
2344 vlan_11 = VppDot1QSubint(self, self.pg0, 11)
2346 self.vapi.l2_interface_vlan_tag_rewrite(
2347 sw_if_index=vlan_11.sw_if_index, vtr_op=L2_VTR_OP.L2_POP_1,
2350 bd_uu_fwd = VppVxlanGbpTunnel(self, self.pg3.local_ip4,
2351 self.pg3.remote_ip4, 116)
2352 bd_uu_fwd.add_vpp_config()
2355 # a GBP bridge domain with a BVI and a UU-flood interface
2356 # The BD is marked as do not learn, so no endpoints are ever
2357 # learnt in this BD.
2359 bd1 = VppBridgeDomain(self, 1)
2360 bd1.add_vpp_config()
2361 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0, bd_uu_fwd,
2363 gbd1.add_vpp_config()
2365 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2366 self.logger.info(self.vapi.cli("sh gbp bridge"))
2368 # ... and has a /32 applied
2369 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2370 ip_addr.add_vpp_config()
2373 # The Endpoint-group in which we are learning endpoints
2375 epg_220 = VppGbpEndpointGroup(self, 220, 441, rd1, gbd1,
2379 VppGbpEndpointRetention(2))
2380 epg_220.add_vpp_config()
2383 # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
2386 vx_tun_l2_1 = VppGbpVxlanTunnel(
2387 self, 99, bd1.bd_id,
2388 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L2,
2390 vx_tun_l2_1.add_vpp_config()
2393 # A static endpoint that the learnt endpoints are trying to
2396 ep = VppGbpEndpoint(self, vlan_11,
2398 "10.0.0.127", "11.0.0.127",
2399 "2001:10::1", "3001::1")
2402 self.assertTrue(find_route(self, ep.ip4.address, 32, table_id=1))
2405 # Send to the static EP
2407 for ii, l in enumerate(learnt):
2408 # a packet with an sclass from a known EPG
2409 # arriving on an unknown TEP
2410 p = (Ether(src=self.pg2.remote_mac,
2411 dst=self.pg2.local_mac) /
2412 IP(src=self.pg2.remote_hosts[1].ip4,
2413 dst=self.pg2.local_ip4) /
2414 UDP(sport=1234, dport=48879) /
2415 VXLAN(vni=99, gpid=441, flags=0x88) /
2416 Ether(src=l['mac'], dst=ep.mac) /
2417 IP(src=l['ip'], dst=ep.ip4.address) /
2418 UDP(sport=1234, dport=1234) /
2421 rxs = self.send_and_expect(self.pg2, [p], self.pg0)
2424 # packet to EP has the EP's vlan tag
2427 self.assertEqual(rx[Dot1Q].vlan, 11)
2430 # the EP is not learnt since the BD setting prevents it
2433 self.assertFalse(find_gbp_endpoint(self,
2434 vx_tun_l2_1.sw_if_index,
2436 self.assertEqual(INDEX_INVALID,
2437 find_vxlan_gbp_tunnel(
2440 self.pg2.remote_hosts[1].ip4,
2443 self.assertEqual(len(self.vapi.gbp_endpoint_dump()), 1)
2447 # we didn't learn the remotes so they are sent to the UU-fwd
2450 p = (Ether(src=ep.mac, dst=l['mac']) /
2452 IP(dst=l['ip'], src=ep.ip4.address) /
2453 UDP(sport=1234, dport=1234) /
2456 rxs = self.send_and_expect(self.pg0, p * 17, self.pg3)
2459 self.assertEqual(rx[IP].src, self.pg3.local_ip4)
2460 self.assertEqual(rx[IP].dst, self.pg3.remote_ip4)
2461 self.assertEqual(rx[UDP].dport, 48879)
2462 # the UDP source port is a random value for hashing
2463 self.assertEqual(rx[VXLAN].gpid, 441)
2464 self.assertEqual(rx[VXLAN].vni, 116)
2465 self.assertTrue(rx[VXLAN].flags.G)
2466 self.assertTrue(rx[VXLAN].flags.Instance)
2467 self.assertFalse(rx[VXLAN].gpflags.A)
2468 self.assertFalse(rx[VXLAN].gpflags.D)
2470 self.pg2.unconfig_ip4()
2471 self.pg3.unconfig_ip4()
2473 def test_gbp_learn_l3(self):
2474 """ GBP L3 Endpoint Learning """
2476 self.vapi.cli("set logging class gbp level debug")
2478 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
2479 routed_dst_mac = "00:0c:0c:0c:0c:0c"
2480 routed_src_mac = "00:22:bd:f8:19:ff"
2482 learnt = [{'mac': '00:00:11:11:11:02',
2484 'ip6': '2001:10::2'},
2485 {'mac': '00:00:11:11:11:03',
2487 'ip6': '2001:10::3'}]
2492 t4 = VppIpTable(self, 1)
2494 t6 = VppIpTable(self, 1, True)
2497 tun_ip4_uu = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
2498 self.pg4.remote_ip4, 114)
2499 tun_ip6_uu = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
2500 self.pg4.remote_ip4, 116)
2501 tun_ip4_uu.add_vpp_config()
2502 tun_ip6_uu.add_vpp_config()
2504 rd1 = VppGbpRouteDomain(self, 2, t4, t6, tun_ip4_uu, tun_ip6_uu)
2505 rd1.add_vpp_config()
2507 self.loop0.set_mac(self.router_mac)
2510 # Bind the BVI to the RD
2512 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
2513 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
2516 # Pg2 hosts the vxlan tunnel
2517 # hosts on pg2 to act as TEPs
2521 self.pg2.config_ip4()
2522 self.pg2.resolve_arp()
2523 self.pg2.generate_remote_hosts(4)
2524 self.pg2.configure_ipv4_neighbors()
2525 self.pg3.config_ip4()
2526 self.pg3.resolve_arp()
2527 self.pg4.config_ip4()
2528 self.pg4.resolve_arp()
2531 # a GBP bridge domain with a BVI and a UU-flood interface
2533 bd1 = VppBridgeDomain(self, 1)
2534 bd1.add_vpp_config()
2535 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0, self.pg3)
2536 gbd1.add_vpp_config()
2538 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2539 self.logger.info(self.vapi.cli("sh gbp bridge"))
2540 self.logger.info(self.vapi.cli("sh gbp route"))
2542 # ... and has a /32 and /128 applied
2543 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2544 ip4_addr.add_vpp_config()
2545 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 128)
2546 ip6_addr.add_vpp_config()
2549 # The Endpoint-group in which we are learning endpoints
2551 epg_220 = VppGbpEndpointGroup(self, 220, 441, rd1, gbd1,
2555 VppGbpEndpointRetention(2))
2556 epg_220.add_vpp_config()
2559 # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
2562 vx_tun_l3 = VppGbpVxlanTunnel(
2563 self, 101, rd1.rd_id,
2564 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
2566 vx_tun_l3.add_vpp_config()
2569 # A static endpoint that the learnt endpoints are trying to
2572 ep = VppGbpEndpoint(self, self.pg0,
2574 "10.0.0.127", "11.0.0.127",
2575 "2001:10::1", "3001::1")
2579 # learn some remote IPv4 EPs
2581 for ii, l in enumerate(learnt):
2582 # a packet with an sclass from a known EPG
2583 # arriving on an unknown TEP
2584 p = (Ether(src=self.pg2.remote_mac,
2585 dst=self.pg2.local_mac) /
2586 IP(src=self.pg2.remote_hosts[1].ip4,
2587 dst=self.pg2.local_ip4) /
2588 UDP(sport=1234, dport=48879) /
2589 VXLAN(vni=101, gpid=441, flags=0x88) /
2590 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2591 IP(src=l['ip'], dst=ep.ip4.address) /
2592 UDP(sport=1234, dport=1234) /
2595 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2598 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2601 self.pg2.remote_hosts[1].ip4,
2603 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2605 # endpoint learnt via the parent GBP-vxlan interface
2606 self.assertTrue(find_gbp_endpoint(self,
2607 vx_tun_l3._sw_if_index,
2611 # Static IPv4 EP replies to learnt
2614 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2615 IP(dst=l['ip'], src=ep.ip4.address) /
2616 UDP(sport=1234, dport=1234) /
2619 rxs = self.send_and_expect(self.pg0, p * 1, self.pg2)
2622 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2623 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2624 self.assertEqual(rx[UDP].dport, 48879)
2625 # the UDP source port is a random value for hashing
2626 self.assertEqual(rx[VXLAN].gpid, 441)
2627 self.assertEqual(rx[VXLAN].vni, 101)
2628 self.assertTrue(rx[VXLAN].flags.G)
2629 self.assertTrue(rx[VXLAN].flags.Instance)
2630 self.assertTrue(rx[VXLAN].gpflags.A)
2631 self.assertFalse(rx[VXLAN].gpflags.D)
2633 inner = rx[VXLAN].payload
2635 self.assertEqual(inner[Ether].src, routed_src_mac)
2636 self.assertEqual(inner[Ether].dst, routed_dst_mac)
2637 self.assertEqual(inner[IP].src, ep.ip4.address)
2638 self.assertEqual(inner[IP].dst, l['ip'])
2641 self.assertFalse(find_gbp_endpoint(self,
2646 # learn some remote IPv6 EPs
2648 for ii, l in enumerate(learnt):
2649 # a packet with an sclass from a known EPG
2650 # arriving on an unknown TEP
2651 p = (Ether(src=self.pg2.remote_mac,
2652 dst=self.pg2.local_mac) /
2653 IP(src=self.pg2.remote_hosts[1].ip4,
2654 dst=self.pg2.local_ip4) /
2655 UDP(sport=1234, dport=48879) /
2656 VXLAN(vni=101, gpid=441, flags=0x88) /
2657 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2658 IPv6(src=l['ip6'], dst=ep.ip6.address) /
2659 UDP(sport=1234, dport=1234) /
2662 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2665 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2668 self.pg2.remote_hosts[1].ip4,
2670 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2672 self.logger.info(self.vapi.cli("show gbp bridge"))
2673 self.logger.info(self.vapi.cli("show vxlan-gbp tunnel"))
2674 self.logger.info(self.vapi.cli("show gbp vxlan"))
2675 self.logger.info(self.vapi.cli("show int addr"))
2677 # endpoint learnt via the TEP
2678 self.assertTrue(find_gbp_endpoint(self, ip=l['ip6']))
2680 self.logger.info(self.vapi.cli("show gbp endpoint"))
2681 self.logger.info(self.vapi.cli("show ip fib index 1 %s" % l['ip']))
2684 # Static EP replies to learnt
2687 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2688 IPv6(dst=l['ip6'], src=ep.ip6.address) /
2689 UDP(sport=1234, dport=1234) /
2692 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
2695 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2696 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2697 self.assertEqual(rx[UDP].dport, 48879)
2698 # the UDP source port is a random value for hashing
2699 self.assertEqual(rx[VXLAN].gpid, 441)
2700 self.assertEqual(rx[VXLAN].vni, 101)
2701 self.assertTrue(rx[VXLAN].flags.G)
2702 self.assertTrue(rx[VXLAN].flags.Instance)
2703 self.assertTrue(rx[VXLAN].gpflags.A)
2704 self.assertFalse(rx[VXLAN].gpflags.D)
2706 inner = rx[VXLAN].payload
2708 self.assertEqual(inner[Ether].src, routed_src_mac)
2709 self.assertEqual(inner[Ether].dst, routed_dst_mac)
2710 self.assertEqual(inner[IPv6].src, ep.ip6.address)
2711 self.assertEqual(inner[IPv6].dst, l['ip6'])
2713 self.logger.info(self.vapi.cli("sh gbp endpoint"))
2715 self.wait_for_ep_timeout(ip=l['ip'])
2718 # Static sends to unknown EP with no route
2720 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2721 IP(dst="10.0.0.99", src=ep.ip4.address) /
2722 UDP(sport=1234, dport=1234) /
2725 self.send_and_assert_no_replies(self.pg0, [p])
2728 # Add a route to static EP's v4 and v6 subnet
2729 # packets should be sent on the v4/v6 uu=fwd interface resp.
2731 se_10_24 = VppGbpSubnet(
2732 self, rd1, "10.0.0.0", 24,
2733 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT)
2734 se_10_24.add_vpp_config()
2736 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2737 IP(dst="10.0.0.99", src=ep.ip4.address) /
2738 UDP(sport=1234, dport=1234) /
2741 rxs = self.send_and_expect(self.pg0, [p], self.pg4)
2743 self.assertEqual(rx[IP].src, self.pg4.local_ip4)
2744 self.assertEqual(rx[IP].dst, self.pg4.remote_ip4)
2745 self.assertEqual(rx[UDP].dport, 48879)
2746 # the UDP source port is a random value for hashing
2747 self.assertEqual(rx[VXLAN].gpid, 441)
2748 self.assertEqual(rx[VXLAN].vni, 114)
2749 self.assertTrue(rx[VXLAN].flags.G)
2750 self.assertTrue(rx[VXLAN].flags.Instance)
2751 # policy is not applied to packets sent to the uu-fwd interfaces
2752 self.assertFalse(rx[VXLAN].gpflags.A)
2753 self.assertFalse(rx[VXLAN].gpflags.D)
2756 # learn some remote IPv4 EPs
2758 for ii, l in enumerate(learnt):
2759 # a packet with an sclass from a known EPG
2760 # arriving on an unknown TEP
2761 p = (Ether(src=self.pg2.remote_mac,
2762 dst=self.pg2.local_mac) /
2763 IP(src=self.pg2.remote_hosts[2].ip4,
2764 dst=self.pg2.local_ip4) /
2765 UDP(sport=1234, dport=48879) /
2766 VXLAN(vni=101, gpid=441, flags=0x88) /
2767 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2768 IP(src=l['ip'], dst=ep.ip4.address) /
2769 UDP(sport=1234, dport=1234) /
2772 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2775 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2778 self.pg2.remote_hosts[2].ip4,
2780 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2782 # endpoint learnt via the parent GBP-vxlan interface
2783 self.assertTrue(find_gbp_endpoint(self,
2784 vx_tun_l3._sw_if_index,
2788 # Add a remote endpoint from the API
2790 rep_88 = VppGbpEndpoint(self, vx_tun_l3,
2792 "10.0.0.88", "11.0.0.88",
2793 "2001:10::88", "3001::88",
2794 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
2796 self.pg2.remote_hosts[1].ip4,
2798 rep_88.add_vpp_config()
2801 # Add a remote endpoint from the API that matches an existing one
2803 rep_2 = VppGbpEndpoint(self, vx_tun_l3,
2805 learnt[0]['ip'], "11.0.0.101",
2806 learnt[0]['ip6'], "3001::101",
2807 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
2809 self.pg2.remote_hosts[1].ip4,
2811 rep_2.add_vpp_config()
2814 # Add a route to the learned EP's v4 subnet
2815 # packets should be send on the v4/v6 uu=fwd interface resp.
2817 se_10_1_24 = VppGbpSubnet(
2818 self, rd1, "10.0.1.0", 24,
2819 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT)
2820 se_10_1_24.add_vpp_config()
2822 self.logger.info(self.vapi.cli("show gbp endpoint"))
2824 ips = ["10.0.0.88", learnt[0]['ip']]
2826 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2827 IP(dst=ip, src=ep.ip4.address) /
2828 UDP(sport=1234, dport=1234) /
2831 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
2834 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2835 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2836 self.assertEqual(rx[UDP].dport, 48879)
2837 # the UDP source port is a random value for hashing
2838 self.assertEqual(rx[VXLAN].gpid, 441)
2839 self.assertEqual(rx[VXLAN].vni, 101)
2840 self.assertTrue(rx[VXLAN].flags.G)
2841 self.assertTrue(rx[VXLAN].flags.Instance)
2842 self.assertTrue(rx[VXLAN].gpflags.A)
2843 self.assertFalse(rx[VXLAN].gpflags.D)
2845 inner = rx[VXLAN].payload
2847 self.assertEqual(inner[Ether].src, routed_src_mac)
2848 self.assertEqual(inner[Ether].dst, routed_dst_mac)
2849 self.assertEqual(inner[IP].src, ep.ip4.address)
2850 self.assertEqual(inner[IP].dst, ip)
2853 # remove the API remote EPs, only API sourced is gone, the DP
2854 # learnt one remains
2856 rep_88.remove_vpp_config()
2857 rep_2.remove_vpp_config()
2859 self.assertTrue(find_gbp_endpoint(self, ip=rep_2.ip4.address))
2861 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2862 IP(src=ep.ip4.address, dst=rep_2.ip4.address) /
2863 UDP(sport=1234, dport=1234) /
2865 rxs = self.send_and_expect(self.pg0, [p], self.pg2)
2867 self.assertFalse(find_gbp_endpoint(self, ip=rep_88.ip4.address))
2869 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2870 IP(src=ep.ip4.address, dst=rep_88.ip4.address) /
2871 UDP(sport=1234, dport=1234) /
2873 rxs = self.send_and_expect(self.pg0, [p], self.pg4)
2876 # to appease the testcase we cannot have the registered EP still
2877 # present (because it's DP learnt) when the TC ends so wait until
2880 self.wait_for_ep_timeout(ip=rep_88.ip4.address)
2881 self.wait_for_ep_timeout(ip=rep_2.ip4.address)
2884 # shutdown with learnt endpoint present
2886 p = (Ether(src=self.pg2.remote_mac,
2887 dst=self.pg2.local_mac) /
2888 IP(src=self.pg2.remote_hosts[1].ip4,
2889 dst=self.pg2.local_ip4) /
2890 UDP(sport=1234, dport=48879) /
2891 VXLAN(vni=101, gpid=441, flags=0x88) /
2892 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2893 IP(src=learnt[1]['ip'], dst=ep.ip4.address) /
2894 UDP(sport=1234, dport=1234) /
2897 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2899 # endpoint learnt via the parent GBP-vxlan interface
2900 self.assertTrue(find_gbp_endpoint(self,
2901 vx_tun_l3._sw_if_index,
2906 # remote endpoint becomes local
2908 self.pg2.unconfig_ip4()
2909 self.pg3.unconfig_ip4()
2910 self.pg4.unconfig_ip4()
2912 def test_gbp_redirect(self):
2913 """ GBP Endpoint Redirect """
2915 self.vapi.cli("set logging class gbp level debug")
2917 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
2918 routed_dst_mac = "00:0c:0c:0c:0c:0c"
2919 routed_src_mac = "00:22:bd:f8:19:ff"
2921 learnt = [{'mac': '00:00:11:11:11:02',
2923 'ip6': '2001:10::2'},
2924 {'mac': '00:00:11:11:11:03',
2926 'ip6': '2001:10::3'}]
2931 t4 = VppIpTable(self, 1)
2933 t6 = VppIpTable(self, 1, True)
2936 rd1 = VppGbpRouteDomain(self, 2, t4, t6)
2937 rd1.add_vpp_config()
2939 self.loop0.set_mac(self.router_mac)
2942 # Bind the BVI to the RD
2944 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
2945 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
2948 # Pg7 hosts a BD's UU-fwd
2950 self.pg7.config_ip4()
2951 self.pg7.resolve_arp()
2954 # a GBP bridge domains for the EPs
2956 bd1 = VppBridgeDomain(self, 1)
2957 bd1.add_vpp_config()
2958 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0)
2959 gbd1.add_vpp_config()
2961 bd2 = VppBridgeDomain(self, 2)
2962 bd2.add_vpp_config()
2963 gbd2 = VppGbpBridgeDomain(self, bd2, self.loop1)
2964 gbd2.add_vpp_config()
2966 # ... and has a /32 and /128 applied
2967 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2968 ip4_addr.add_vpp_config()
2969 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 128)
2970 ip6_addr.add_vpp_config()
2971 ip4_addr = VppIpInterfaceAddress(self, gbd2.bvi, "10.0.1.128", 32)
2972 ip4_addr.add_vpp_config()
2973 ip6_addr = VppIpInterfaceAddress(self, gbd2.bvi, "2001:11::128", 128)
2974 ip6_addr.add_vpp_config()
2977 # The Endpoint-groups in which we are learning endpoints
2979 epg_220 = VppGbpEndpointGroup(self, 220, 440, rd1, gbd1,
2983 VppGbpEndpointRetention(2))
2984 epg_220.add_vpp_config()
2985 epg_221 = VppGbpEndpointGroup(self, 221, 441, rd1, gbd2,
2989 VppGbpEndpointRetention(2))
2990 epg_221.add_vpp_config()
2991 epg_222 = VppGbpEndpointGroup(self, 222, 442, rd1, gbd1,
2995 VppGbpEndpointRetention(2))
2996 epg_222.add_vpp_config()
2999 # a GBP bridge domains for the SEPs
3001 bd_uu1 = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
3002 self.pg7.remote_ip4, 116)
3003 bd_uu1.add_vpp_config()
3004 bd_uu2 = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
3005 self.pg7.remote_ip4, 117)
3006 bd_uu2.add_vpp_config()
3008 bd3 = VppBridgeDomain(self, 3)
3009 bd3.add_vpp_config()
3010 gbd3 = VppGbpBridgeDomain(self, bd3, self.loop2, bd_uu1, learn=False)
3011 gbd3.add_vpp_config()
3012 bd4 = VppBridgeDomain(self, 4)
3013 bd4.add_vpp_config()
3014 gbd4 = VppGbpBridgeDomain(self, bd4, self.loop3, bd_uu2, learn=False)
3015 gbd4.add_vpp_config()
3018 # EPGs in which the service endpoints exist
3020 epg_320 = VppGbpEndpointGroup(self, 320, 550, rd1, gbd3,
3024 VppGbpEndpointRetention(2))
3025 epg_320.add_vpp_config()
3026 epg_321 = VppGbpEndpointGroup(self, 321, 551, rd1, gbd4,
3030 VppGbpEndpointRetention(2))
3031 epg_321.add_vpp_config()
3034 # three local endpoints
3036 ep1 = VppGbpEndpoint(self, self.pg0,
3038 "10.0.0.1", "11.0.0.1",
3039 "2001:10::1", "3001:10::1")
3040 ep1.add_vpp_config()
3041 ep2 = VppGbpEndpoint(self, self.pg1,
3043 "10.0.1.1", "11.0.1.1",
3044 "2001:11::1", "3001:11::1")
3045 ep2.add_vpp_config()
3046 ep3 = VppGbpEndpoint(self, self.pg2,
3048 "10.0.2.2", "11.0.2.2",
3049 "2001:12::1", "3001:12::1")
3050 ep3.add_vpp_config()
3055 sep1 = VppGbpEndpoint(self, self.pg3,
3057 "12.0.0.1", "13.0.0.1",
3058 "4001:10::1", "5001:10::1")
3059 sep1.add_vpp_config()
3060 sep2 = VppGbpEndpoint(self, self.pg4,
3062 "12.0.0.2", "13.0.0.2",
3063 "4001:10::2", "5001:10::2")
3064 sep2.add_vpp_config()
3065 sep3 = VppGbpEndpoint(self, self.pg5,
3067 "12.0.1.1", "13.0.1.1",
3068 "4001:11::1", "5001:11::1")
3069 sep3.add_vpp_config()
3070 # this EP is not installed immediately
3071 sep4 = VppGbpEndpoint(self, self.pg6,
3073 "12.0.1.2", "13.0.1.2",
3074 "4001:11::2", "5001:11::2")
3077 # an L2 switch packet between local EPs in different EPGs
3078 # different dest ports on each so the are LB hashed differently
3080 p4 = [(Ether(src=ep1.mac, dst=ep3.mac) /
3081 IP(src=ep1.ip4.address, dst=ep3.ip4.address) /
3082 UDP(sport=1234, dport=1234) /
3084 (Ether(src=ep3.mac, dst=ep1.mac) /
3085 IP(src=ep3.ip4.address, dst=ep1.ip4.address) /
3086 UDP(sport=1234, dport=1234) /
3088 p6 = [(Ether(src=ep1.mac, dst=ep3.mac) /
3089 IPv6(src=ep1.ip6.address, dst=ep3.ip6.address) /
3090 UDP(sport=1234, dport=1234) /
3092 (Ether(src=ep3.mac, dst=ep1.mac) /
3093 IPv6(src=ep3.ip6.address, dst=ep1.ip6.address) /
3094 UDP(sport=1234, dport=1230) /
3097 # should be dropped since no contract yet
3098 self.send_and_assert_no_replies(self.pg0, [p4[0]])
3099 self.send_and_assert_no_replies(self.pg0, [p6[0]])
3102 # Add a contract with a rule to load-balance redirect via SEP1 and SEP2
3103 # one of the next-hops is via an EP that is not known
3105 acl = VppGbpAcl(self)
3106 rule4 = acl.create_rule(permit_deny=1, proto=17)
3107 rule6 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
3108 acl_index = acl.add_vpp_config([rule4, rule6])
3111 # test the src-ip hash mode
3113 c1 = VppGbpContract(
3114 self, epg_220.sclass, epg_222.sclass, acl_index,
3115 [VppGbpContractRule(
3116 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3117 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3118 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3119 sep1.ip4, sep1.epg.rd),
3120 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3121 sep2.ip4, sep2.epg.rd)]),
3123 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3124 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3125 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3126 sep3.ip6, sep3.epg.rd),
3127 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3128 sep4.ip6, sep4.epg.rd)])],
3129 [ETH_P_IP, ETH_P_IPV6])
3132 c2 = VppGbpContract(
3133 self, epg_222.sclass, epg_220.sclass, acl_index,
3134 [VppGbpContractRule(
3135 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3136 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3137 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3138 sep1.ip4, sep1.epg.rd),
3139 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3140 sep2.ip4, sep2.epg.rd)]),
3142 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3143 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3144 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3145 sep3.ip6, sep3.epg.rd),
3146 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3147 sep4.ip6, sep4.epg.rd)])],
3148 [ETH_P_IP, ETH_P_IPV6])
3152 # send again with the contract preset, now packets arrive
3153 # at SEP1 or SEP2 depending on the hashing
3155 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3158 self.assertEqual(rx[Ether].src, routed_src_mac)
3159 self.assertEqual(rx[Ether].dst, sep1.mac)
3160 self.assertEqual(rx[IP].src, ep1.ip4.address)
3161 self.assertEqual(rx[IP].dst, ep3.ip4.address)
3163 rxs = self.send_and_expect(self.pg2, p4[1] * 17, sep2.itf)
3166 self.assertEqual(rx[Ether].src, routed_src_mac)
3167 self.assertEqual(rx[Ether].dst, sep2.mac)
3168 self.assertEqual(rx[IP].src, ep3.ip4.address)
3169 self.assertEqual(rx[IP].dst, ep1.ip4.address)
3171 rxs = self.send_and_expect(self.pg0, p6[0] * 17, self.pg7)
3174 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3175 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3176 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3177 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
3178 self.assertEqual(rx[VXLAN].vni, 117)
3179 self.assertTrue(rx[VXLAN].flags.G)
3180 self.assertTrue(rx[VXLAN].flags.Instance)
3181 # redirect policy has been applied
3182 self.assertTrue(rx[VXLAN].gpflags.A)
3183 self.assertFalse(rx[VXLAN].gpflags.D)
3185 inner = rx[VXLAN].payload
3187 self.assertEqual(inner[Ether].src, routed_src_mac)
3188 self.assertEqual(inner[Ether].dst, sep4.mac)
3189 self.assertEqual(inner[IPv6].src, ep1.ip6.address)
3190 self.assertEqual(inner[IPv6].dst, ep3.ip6.address)
3192 rxs = self.send_and_expect(self.pg2, p6[1] * 17, sep3.itf)
3195 self.assertEqual(rx[Ether].src, routed_src_mac)
3196 self.assertEqual(rx[Ether].dst, sep3.mac)
3197 self.assertEqual(rx[IPv6].src, ep3.ip6.address)
3198 self.assertEqual(rx[IPv6].dst, ep1.ip6.address)
3201 # programme the unknown EP
3203 sep4.add_vpp_config()
3205 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep4.itf)
3208 self.assertEqual(rx[Ether].src, routed_src_mac)
3209 self.assertEqual(rx[Ether].dst, sep4.mac)
3210 self.assertEqual(rx[IPv6].src, ep1.ip6.address)
3211 self.assertEqual(rx[IPv6].dst, ep3.ip6.address)
3214 # and revert back to unprogrammed
3216 sep4.remove_vpp_config()
3218 rxs = self.send_and_expect(self.pg0, p6[0] * 17, self.pg7)
3221 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3222 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3223 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3224 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
3225 self.assertEqual(rx[VXLAN].vni, 117)
3226 self.assertTrue(rx[VXLAN].flags.G)
3227 self.assertTrue(rx[VXLAN].flags.Instance)
3228 # redirect policy has been applied
3229 self.assertTrue(rx[VXLAN].gpflags.A)
3230 self.assertFalse(rx[VXLAN].gpflags.D)
3232 inner = rx[VXLAN].payload
3234 self.assertEqual(inner[Ether].src, routed_src_mac)
3235 self.assertEqual(inner[Ether].dst, sep4.mac)
3236 self.assertEqual(inner[IPv6].src, ep1.ip6.address)
3237 self.assertEqual(inner[IPv6].dst, ep3.ip6.address)
3239 c1.remove_vpp_config()
3240 c2.remove_vpp_config()
3243 # test the symmetric hash mode
3245 c1 = VppGbpContract(
3246 self, epg_220.sclass, epg_222.sclass, acl_index,
3247 [VppGbpContractRule(
3248 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3249 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3250 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3251 sep1.ip4, sep1.epg.rd),
3252 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3253 sep2.ip4, sep2.epg.rd)]),
3255 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3256 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3257 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3258 sep3.ip6, sep3.epg.rd),
3259 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3260 sep4.ip6, sep4.epg.rd)])],
3261 [ETH_P_IP, ETH_P_IPV6])
3264 c2 = VppGbpContract(
3265 self, epg_222.sclass, epg_220.sclass, acl_index,
3266 [VppGbpContractRule(
3267 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3268 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3269 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3270 sep1.ip4, sep1.epg.rd),
3271 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3272 sep2.ip4, sep2.epg.rd)]),
3274 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3275 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3276 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3277 sep3.ip6, sep3.epg.rd),
3278 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3279 sep4.ip6, sep4.epg.rd)])],
3280 [ETH_P_IP, ETH_P_IPV6])
3284 # send again with the contract preset, now packets arrive
3285 # at SEP1 for both directions
3287 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3290 self.assertEqual(rx[Ether].src, routed_src_mac)
3291 self.assertEqual(rx[Ether].dst, sep1.mac)
3292 self.assertEqual(rx[IP].src, ep1.ip4.address)
3293 self.assertEqual(rx[IP].dst, ep3.ip4.address)
3295 rxs = self.send_and_expect(self.pg2, p4[1] * 17, sep1.itf)
3298 self.assertEqual(rx[Ether].src, routed_src_mac)
3299 self.assertEqual(rx[Ether].dst, sep1.mac)
3300 self.assertEqual(rx[IP].src, ep3.ip4.address)
3301 self.assertEqual(rx[IP].dst, ep1.ip4.address)
3304 # programme the unknown EP for the L3 tests
3306 sep4.add_vpp_config()
3309 # an L3 switch packet between local EPs in different EPGs
3310 # different dest ports on each so the are LB hashed differently
3312 p4 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3313 IP(src=ep1.ip4.address, dst=ep2.ip4.address) /
3314 UDP(sport=1234, dport=1234) /
3316 (Ether(src=ep2.mac, dst=str(self.router_mac)) /
3317 IP(src=ep2.ip4.address, dst=ep1.ip4.address) /
3318 UDP(sport=1234, dport=1234) /
3320 p6 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3321 IPv6(src=ep1.ip6.address, dst=ep2.ip6.address) /
3322 UDP(sport=1234, dport=1234) /
3324 (Ether(src=ep2.mac, dst=str(self.router_mac)) /
3325 IPv6(src=ep2.ip6.address, dst=ep1.ip6.address) /
3326 UDP(sport=1234, dport=1234) /
3329 c3 = VppGbpContract(
3330 self, epg_220.sclass, epg_221.sclass, acl_index,
3331 [VppGbpContractRule(
3332 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3333 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3334 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3335 sep1.ip4, sep1.epg.rd),
3336 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3337 sep2.ip4, sep2.epg.rd)]),
3339 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3340 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3341 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3342 sep3.ip6, sep3.epg.rd),
3343 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3344 sep4.ip6, sep4.epg.rd)])],
3345 [ETH_P_IP, ETH_P_IPV6])
3348 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3351 self.assertEqual(rx[Ether].src, routed_src_mac)
3352 self.assertEqual(rx[Ether].dst, sep1.mac)
3353 self.assertEqual(rx[IP].src, ep1.ip4.address)
3354 self.assertEqual(rx[IP].dst, ep2.ip4.address)
3357 # learn a remote EP in EPG 221
3359 vx_tun_l3 = VppGbpVxlanTunnel(
3360 self, 444, rd1.rd_id,
3361 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
3363 vx_tun_l3.add_vpp_config()
3365 c4 = VppGbpContract(
3366 self, epg_221.sclass, epg_220.sclass, acl_index,
3367 [VppGbpContractRule(
3368 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3369 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3372 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3373 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3375 [ETH_P_IP, ETH_P_IPV6])
3378 p = (Ether(src=self.pg7.remote_mac,
3379 dst=self.pg7.local_mac) /
3380 IP(src=self.pg7.remote_ip4,
3381 dst=self.pg7.local_ip4) /
3382 UDP(sport=1234, dport=48879) /
3383 VXLAN(vni=444, gpid=441, flags=0x88) /
3384 Ether(src="00:22:22:22:22:33", dst=str(self.router_mac)) /
3385 IP(src="10.0.0.88", dst=ep1.ip4.address) /
3386 UDP(sport=1234, dport=1234) /
3389 rx = self.send_and_expect(self.pg7, [p], self.pg0)
3391 # endpoint learnt via the parent GBP-vxlan interface
3392 self.assertTrue(find_gbp_endpoint(self,
3393 vx_tun_l3._sw_if_index,
3396 p = (Ether(src=self.pg7.remote_mac,
3397 dst=self.pg7.local_mac) /
3398 IP(src=self.pg7.remote_ip4,
3399 dst=self.pg7.local_ip4) /
3400 UDP(sport=1234, dport=48879) /
3401 VXLAN(vni=444, gpid=441, flags=0x88) /
3402 Ether(src="00:22:22:22:22:33", dst=str(self.router_mac)) /
3403 IPv6(src="2001:10::88", dst=ep1.ip6.address) /
3404 UDP(sport=1234, dport=1234) /
3407 rx = self.send_and_expect(self.pg7, [p], self.pg0)
3409 # endpoint learnt via the parent GBP-vxlan interface
3410 self.assertTrue(find_gbp_endpoint(self,
3411 vx_tun_l3._sw_if_index,
3415 # L3 switch from local to remote EP
3417 p4 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3418 IP(src=ep1.ip4.address, dst="10.0.0.88") /
3419 UDP(sport=1234, dport=1234) /
3421 p6 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3422 IPv6(src=ep1.ip6.address, dst="2001:10::88") /
3423 UDP(sport=1234, dport=1234) /
3426 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3429 self.assertEqual(rx[Ether].src, routed_src_mac)
3430 self.assertEqual(rx[Ether].dst, sep1.mac)
3431 self.assertEqual(rx[IP].src, ep1.ip4.address)
3432 self.assertEqual(rx[IP].dst, "10.0.0.88")
3434 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep4.itf)
3437 self.assertEqual(rx[Ether].src, routed_src_mac)
3438 self.assertEqual(rx[Ether].dst, sep4.mac)
3439 self.assertEqual(rx[IPv6].src, ep1.ip6.address)
3440 self.assertEqual(rx[IPv6].dst, "2001:10::88")
3443 # test the dst-ip hash mode
3445 c5 = VppGbpContract(
3446 self, epg_220.sclass, epg_221.sclass, acl_index,
3447 [VppGbpContractRule(
3448 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3449 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
3450 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3451 sep1.ip4, sep1.epg.rd),
3452 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3453 sep2.ip4, sep2.epg.rd)]),
3455 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3456 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
3457 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3458 sep3.ip6, sep3.epg.rd),
3459 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3460 sep4.ip6, sep4.epg.rd)])],
3461 [ETH_P_IP, ETH_P_IPV6])
3464 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3467 self.assertEqual(rx[Ether].src, routed_src_mac)
3468 self.assertEqual(rx[Ether].dst, sep1.mac)
3469 self.assertEqual(rx[IP].src, ep1.ip4.address)
3470 self.assertEqual(rx[IP].dst, "10.0.0.88")
3472 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep3.itf)
3475 self.assertEqual(rx[Ether].src, routed_src_mac)
3476 self.assertEqual(rx[Ether].dst, sep3.mac)
3477 self.assertEqual(rx[IPv6].src, ep1.ip6.address)
3478 self.assertEqual(rx[IPv6].dst, "2001:10::88")
3483 self.pg7.unconfig_ip4()
3485 def test_gbp_l3_out(self):
3488 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
3489 self.vapi.cli("set logging class gbp level debug")
3491 routed_dst_mac = "00:0c:0c:0c:0c:0c"
3492 routed_src_mac = "00:22:bd:f8:19:ff"
3497 t4 = VppIpTable(self, 1)
3499 t6 = VppIpTable(self, 1, True)
3502 rd1 = VppGbpRouteDomain(self, 2, t4, t6)
3503 rd1.add_vpp_config()
3505 self.loop0.set_mac(self.router_mac)
3508 # Bind the BVI to the RD
3510 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
3511 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
3514 # Pg7 hosts a BD's BUM
3515 # Pg1 some other l3 interface
3517 self.pg7.config_ip4()
3518 self.pg7.resolve_arp()
3521 # a multicast vxlan-gbp tunnel for broadcast in the BD
3523 tun_bm = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
3526 tun_bm.add_vpp_config()
3529 # a GBP external bridge domains for the EPs
3531 bd1 = VppBridgeDomain(self, 1)
3532 bd1.add_vpp_config()
3533 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0, None, tun_bm)
3534 gbd1.add_vpp_config()
3537 # The Endpoint-groups in which the external endpoints exist
3539 epg_220 = VppGbpEndpointGroup(self, 220, 113, rd1, gbd1,
3543 VppGbpEndpointRetention(2))
3544 epg_220.add_vpp_config()
3546 # the BVIs have the subnets applied ...
3547 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 24)
3548 ip4_addr.add_vpp_config()
3549 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 64)
3550 ip6_addr.add_vpp_config()
3552 # ... which are L3-out subnets
3553 l3o_1 = VppGbpSubnet(
3554 self, rd1, "10.0.0.0", 24,
3555 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3557 l3o_1.add_vpp_config()
3560 # an external interface attached to the outside world and the
3563 vlan_100 = VppDot1QSubint(self, self.pg0, 100)
3565 VppL2Vtr(self, vlan_100, L2_VTR_OP.L2_POP_1).add_vpp_config()
3566 vlan_101 = VppDot1QSubint(self, self.pg0, 101)
3568 VppL2Vtr(self, vlan_101, L2_VTR_OP.L2_POP_1).add_vpp_config()
3569 # vlan_102 is not poped
3570 vlan_102 = VppDot1QSubint(self, self.pg0, 102)
3573 ext_itf = VppGbpExtItf(self, self.loop0, bd1, rd1)
3574 ext_itf.add_vpp_config()
3577 # an unicast vxlan-gbp for inter-RD traffic
3579 vx_tun_l3 = VppGbpVxlanTunnel(
3580 self, 444, rd1.rd_id,
3581 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
3583 vx_tun_l3.add_vpp_config()
3586 # External Endpoints
3588 eep1 = VppGbpEndpoint(self, vlan_100,
3590 "10.0.0.1", "11.0.0.1",
3591 "2001:10::1", "3001::1",
3592 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
3593 eep1.add_vpp_config()
3594 eep2 = VppGbpEndpoint(self, vlan_101,
3596 "10.0.0.2", "11.0.0.2",
3597 "2001:10::2", "3001::2",
3598 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
3599 eep2.add_vpp_config()
3600 eep3 = VppGbpEndpoint(self, vlan_102,
3602 "10.0.0.3", "11.0.0.3",
3603 "2001:10::3", "3001::3",
3604 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
3605 eep3.add_vpp_config()
3608 # A remote external endpoint
3610 rep = VppGbpEndpoint(self, vx_tun_l3,
3612 "10.0.0.101", "11.0.0.101",
3613 "2001:10::101", "3001::101",
3614 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
3616 self.pg7.remote_ip4,
3618 rep.add_vpp_config()
3621 # ARP packet from External EPs are accepted and replied to
3623 p_arp = (Ether(src=eep1.mac, dst="ff:ff:ff:ff:ff:ff") /
3626 psrc=eep1.ip4.address, pdst="10.0.0.128",
3627 hwsrc=eep1.mac, hwdst="ff:ff:ff:ff:ff:ff"))
3628 rxs = self.send_and_expect(self.pg0, p_arp * 1, self.pg0)
3631 # ARP packet from host in remote subnet are accepted and replied to
3633 p_arp = (Ether(src=vlan_102.remote_mac, dst="ff:ff:ff:ff:ff:ff") /
3636 psrc="10.0.0.17", pdst="10.0.0.128",
3637 hwsrc=vlan_102.remote_mac, hwdst="ff:ff:ff:ff:ff:ff"))
3638 rxs = self.send_and_expect(self.pg0, p_arp * 1, self.pg0)
3641 # packets destined to unknown addresses in the BVI's subnet
3644 p4 = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3646 IP(src="10.0.0.1", dst="10.0.0.88") /
3647 UDP(sport=1234, dport=1234) /
3649 p6 = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3651 IPv6(src="2001:10::1", dst="2001:10::88") /
3652 UDP(sport=1234, dport=1234) /
3655 rxs = self.send_and_expect(self.pg0, p4 * 1, self.pg7)
3658 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3659 # self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3660 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3661 self.assertEqual(rx[IP].dst, "239.1.1.1")
3662 self.assertEqual(rx[VXLAN].vni, 88)
3663 self.assertTrue(rx[VXLAN].flags.G)
3664 self.assertTrue(rx[VXLAN].flags.Instance)
3665 # policy was applied to the original IP packet
3666 self.assertEqual(rx[VXLAN].gpid, 113)
3667 self.assertTrue(rx[VXLAN].gpflags.A)
3668 self.assertFalse(rx[VXLAN].gpflags.D)
3670 inner = rx[VXLAN].payload
3672 self.assertTrue(inner.haslayer(ARP))
3675 # remote to external
3677 p = (Ether(src=self.pg7.remote_mac,
3678 dst=self.pg7.local_mac) /
3679 IP(src=self.pg7.remote_ip4,
3680 dst=self.pg7.local_ip4) /
3681 UDP(sport=1234, dport=48879) /
3682 VXLAN(vni=444, gpid=113, flags=0x88) /
3683 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
3684 IP(src="10.0.0.101", dst="10.0.0.1") /
3685 UDP(sport=1234, dport=1234) /
3688 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
3691 # local EP pings router
3693 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3695 IP(src=eep1.ip4.address, dst="10.0.0.128") /
3696 ICMP(type='echo-request'))
3698 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
3701 self.assertEqual(rx[Ether].src, str(self.router_mac))
3702 self.assertEqual(rx[Ether].dst, eep1.mac)
3703 self.assertEqual(rx[Dot1Q].vlan, 100)
3706 # local EP pings other local EP
3708 p = (Ether(src=eep1.mac, dst=eep2.mac) /
3710 IP(src=eep1.ip4.address, dst=eep2.ip4.address) /
3711 ICMP(type='echo-request'))
3713 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
3716 self.assertEqual(rx[Ether].src, eep1.mac)
3717 self.assertEqual(rx[Ether].dst, eep2.mac)
3718 self.assertEqual(rx[Dot1Q].vlan, 101)
3721 # local EP pings router w/o vlan tag poped
3723 p = (Ether(src=eep3.mac, dst=str(self.router_mac)) /
3725 IP(src=eep3.ip4.address, dst="10.0.0.128") /
3726 ICMP(type='echo-request'))
3728 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
3731 self.assertEqual(rx[Ether].src, str(self.router_mac))
3732 self.assertEqual(rx[Ether].dst, vlan_102.remote_mac)
3735 # A subnet reachable through the external EP1
3737 ip_220 = VppIpRoute(self, "10.220.0.0", 24,
3738 [VppRoutePath(eep1.ip4.address,
3739 eep1.epg.bvi.sw_if_index)],
3740 table_id=t4.table_id)
3741 ip_220.add_vpp_config()
3743 l3o_220 = VppGbpSubnet(
3744 self, rd1, "10.220.0.0", 24,
3745 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3747 l3o_220.add_vpp_config()
3750 # A subnet reachable through the external EP2
3752 ip_221 = VppIpRoute(self, "10.221.0.0", 24,
3753 [VppRoutePath(eep2.ip4.address,
3754 eep2.epg.bvi.sw_if_index)],
3755 table_id=t4.table_id)
3756 ip_221.add_vpp_config()
3758 l3o_221 = VppGbpSubnet(
3759 self, rd1, "10.221.0.0", 24,
3760 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3762 l3o_221.add_vpp_config()
3765 # ping between hosts in remote subnets
3766 # dropped without a contract
3768 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3770 IP(src="10.220.0.1", dst="10.221.0.1") /
3771 ICMP(type='echo-request'))
3773 rxs = self.send_and_assert_no_replies(self.pg0, p * 1)
3776 # contract for the external nets to communicate
3778 acl = VppGbpAcl(self)
3779 rule4 = acl.create_rule(permit_deny=1, proto=17)
3780 rule6 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
3781 acl_index = acl.add_vpp_config([rule4, rule6])
3783 c1 = VppGbpContract(
3784 self, 4220, 4221, acl_index,
3785 [VppGbpContractRule(
3786 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3787 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3790 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3791 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3793 [ETH_P_IP, ETH_P_IPV6])
3797 # Contracts allowing ext-net 200 to talk with external EPs
3799 c2 = VppGbpContract(
3800 self, 4220, 113, acl_index,
3801 [VppGbpContractRule(
3802 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3803 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3806 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3807 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3809 [ETH_P_IP, ETH_P_IPV6])
3811 c3 = VppGbpContract(
3812 self, 113, 4220, acl_index,
3813 [VppGbpContractRule(
3814 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3815 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3818 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3819 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3821 [ETH_P_IP, ETH_P_IPV6])
3825 # ping between hosts in remote subnets
3827 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3829 IP(src="10.220.0.1", dst="10.221.0.1") /
3830 UDP(sport=1234, dport=1234) /
3833 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
3836 self.assertEqual(rx[Ether].src, str(self.router_mac))
3837 self.assertEqual(rx[Ether].dst, eep2.mac)
3838 self.assertEqual(rx[Dot1Q].vlan, 101)
3840 # we did not learn these external hosts
3841 self.assertFalse(find_gbp_endpoint(self, ip="10.220.0.1"))
3842 self.assertFalse(find_gbp_endpoint(self, ip="10.221.0.1"))
3845 # from remote external EP to local external EP
3847 p = (Ether(src=self.pg7.remote_mac,
3848 dst=self.pg7.local_mac) /
3849 IP(src=self.pg7.remote_ip4,
3850 dst=self.pg7.local_ip4) /
3851 UDP(sport=1234, dport=48879) /
3852 VXLAN(vni=444, gpid=113, flags=0x88) /
3853 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
3854 IP(src="10.0.0.101", dst="10.220.0.1") /
3855 UDP(sport=1234, dport=1234) /
3858 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
3861 # ping from an external host to the remote external EP
3863 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3865 IP(src="10.220.0.1", dst=rep.ip4.address) /
3866 UDP(sport=1234, dport=1234) /
3869 rxs = self.send_and_expect(self.pg0, p * 1, self.pg7)
3872 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3873 # self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3874 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3875 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
3876 self.assertEqual(rx[VXLAN].vni, 444)
3877 self.assertTrue(rx[VXLAN].flags.G)
3878 self.assertTrue(rx[VXLAN].flags.Instance)
3879 # the sclass of the ext-net the packet came from
3880 self.assertEqual(rx[VXLAN].gpid, 4220)
3881 # policy was applied to the original IP packet
3882 self.assertTrue(rx[VXLAN].gpflags.A)
3883 # since it's an external host the reciever should not learn it
3884 self.assertTrue(rx[VXLAN].gpflags.D)
3885 inner = rx[VXLAN].payload
3886 self.assertEqual(inner[IP].src, "10.220.0.1")
3887 self.assertEqual(inner[IP].dst, rep.ip4.address)
3890 # An external subnet reachable via the remote external EP
3894 # first the VXLAN-GBP tunnel over which it is reached
3896 vx_tun_r = VppVxlanGbpTunnel(
3897 self, self.pg7.local_ip4,
3898 self.pg7.remote_ip4, 445,
3899 mode=(VppEnum.vl_api_vxlan_gbp_api_tunnel_mode_t.
3900 VXLAN_GBP_API_TUNNEL_MODE_L3))
3901 vx_tun_r.add_vpp_config()
3902 VppIpInterfaceBind(self, vx_tun_r, t4).add_vpp_config()
3904 self.logger.info(self.vapi.cli("sh vxlan-gbp tunnel"))
3907 # then the special adj to resolve through on that tunnel
3909 n1 = VppNeighbor(self,
3910 vx_tun_r.sw_if_index,
3911 "00:0c:0c:0c:0c:0c",
3912 self.pg7.remote_ip4)
3916 # the route via the adj above
3918 ip_222 = VppIpRoute(self, "10.222.0.0", 24,
3919 [VppRoutePath(self.pg7.remote_ip4,
3920 vx_tun_r.sw_if_index)],
3921 table_id=t4.table_id)
3922 ip_222.add_vpp_config()
3924 l3o_222 = VppGbpSubnet(
3925 self, rd1, "10.222.0.0", 24,
3926 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3928 l3o_222.add_vpp_config()
3931 # ping between hosts in local and remote external subnets
3932 # dropped without a contract
3934 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3936 IP(src="10.220.0.1", dst="10.222.0.1") /
3937 UDP(sport=1234, dport=1234) /
3940 rxs = self.send_and_assert_no_replies(self.pg0, p * 1)
3943 # Add contracts ext-nets for 220 -> 222
3945 c4 = VppGbpContract(
3946 self, 4220, 4222, acl_index,
3947 [VppGbpContractRule(
3948 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3949 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3952 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3953 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3955 [ETH_P_IP, ETH_P_IPV6])
3959 # ping from host in local to remote external subnets
3961 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3963 IP(src="10.220.0.1", dst="10.222.0.1") /
3964 UDP(sport=1234, dport=1234) /
3967 rxs = self.send_and_expect(self.pg0, p * 3, self.pg7)
3970 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3971 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3972 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3973 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
3974 self.assertEqual(rx[VXLAN].vni, 445)
3975 self.assertTrue(rx[VXLAN].flags.G)
3976 self.assertTrue(rx[VXLAN].flags.Instance)
3977 # the sclass of the ext-net the packet came from
3978 self.assertEqual(rx[VXLAN].gpid, 4220)
3979 # policy was applied to the original IP packet
3980 self.assertTrue(rx[VXLAN].gpflags.A)
3981 # since it's an external host the reciever should not learn it
3982 self.assertTrue(rx[VXLAN].gpflags.D)
3983 inner = rx[VXLAN].payload
3984 self.assertEqual(inner[Ether].dst, "00:0c:0c:0c:0c:0c")
3985 self.assertEqual(inner[IP].src, "10.220.0.1")
3986 self.assertEqual(inner[IP].dst, "10.222.0.1")
3989 # ping from host in remote to local external subnets
3990 # there's no contract for this, but the A bit is set.
3992 p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
3993 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
3994 UDP(sport=1234, dport=48879) /
3995 VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
3996 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
3997 IP(src="10.222.0.1", dst="10.220.0.1") /
3998 UDP(sport=1234, dport=1234) /
4001 rxs = self.send_and_expect(self.pg7, p * 3, self.pg0)
4002 self.assertFalse(find_gbp_endpoint(self, ip="10.222.0.1"))
4005 # ping from host in remote to remote external subnets
4006 # this is dropped by reflection check.
4008 p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
4009 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
4010 UDP(sport=1234, dport=48879) /
4011 VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
4012 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
4013 IP(src="10.222.0.1", dst="10.222.0.2") /
4014 UDP(sport=1234, dport=1234) /
4017 rxs = self.send_and_assert_no_replies(self.pg7, p * 3)
4022 self.pg7.unconfig_ip4()
4023 vlan_100.set_vtr(L2_VTR_OP.L2_DISABLED)
4026 if __name__ == '__main__':
4027 unittest.main(testRunner=VppTestRunner)