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
38 def find_gbp_endpoint(test, sw_if_index=None, ip=None, mac=None, tep=None):
40 vip = VppIpAddress(ip)
42 vmac = MACAddress(mac)
44 eps = test.vapi.gbp_endpoint_dump()
48 src = VppIpAddress(tep[0])
49 dst = VppIpAddress(tep[1])
50 if src != ep.endpoint.tun.src or dst != ep.endpoint.tun.dst:
53 if ep.endpoint.sw_if_index != sw_if_index:
56 for eip in ep.endpoint.ips:
60 if vmac.packed == ep.endpoint.mac:
66 def find_gbp_vxlan(test, vni):
67 ts = test.vapi.gbp_vxlan_tunnel_dump()
69 if t.tunnel.vni == vni:
74 class VppGbpEndpoint(VppObject):
101 return [self.ip4, self.ip6]
105 return [self.fip4, self.fip6]
107 def __init__(self, test, itf, epg, recirc, ip4, fip4, ip6, fip6,
117 self._ip4 = VppIpAddress(ip4)
118 self._fip4 = VppIpAddress(fip4)
119 self._ip6 = VppIpAddress(ip6)
120 self._fip6 = VppIpAddress(fip6)
123 self.vmac = MACAddress(self.itf.remote_mac)
125 self.vmac = MACAddress("00:00:00:00:00:00")
128 self.tun_src = VppIpAddress(tun_src)
129 self.tun_dst = VppIpAddress(tun_dst)
131 def add_vpp_config(self):
132 res = self._test.vapi.gbp_endpoint_add(
133 self.itf.sw_if_index,
134 [self.ip4.encode(), self.ip6.encode()],
138 self.tun_src.encode(),
139 self.tun_dst.encode())
140 self.handle = res.handle
141 self._test.registry.register(self, self._test.logger)
143 def remove_vpp_config(self):
144 self._test.vapi.gbp_endpoint_del(self.handle)
147 return "gbp-endpoint:[%d==%d:%s:%d]" % (self.handle,
148 self.itf.sw_if_index,
152 def query_vpp_config(self):
153 return find_gbp_endpoint(self._test,
154 self.itf.sw_if_index,
158 class VppGbpRecirc(VppObject):
160 GBP Recirculation Interface
163 def __init__(self, test, epg, recirc, is_ext=False):
169 def add_vpp_config(self):
170 self._test.vapi.gbp_recirc_add_del(
172 self.recirc.sw_if_index,
175 self._test.registry.register(self, self._test.logger)
177 def remove_vpp_config(self):
178 self._test.vapi.gbp_recirc_add_del(
180 self.recirc.sw_if_index,
185 return "gbp-recirc:[%d]" % (self.recirc.sw_if_index)
187 def query_vpp_config(self):
188 rs = self._test.vapi.gbp_recirc_dump()
190 if r.recirc.sw_if_index == self.recirc.sw_if_index:
195 class VppGbpExtItf(VppObject):
197 GBP ExtItfulation Interface
200 def __init__(self, test, itf, bd, rd, anon=False):
205 self.flags = 1 if anon else 0
207 def add_vpp_config(self):
208 self._test.vapi.gbp_ext_itf_add_del(
209 1, self.itf.sw_if_index, self.bd.bd_id, self.rd.rd_id, self.flags)
210 self._test.registry.register(self, self._test.logger)
212 def remove_vpp_config(self):
213 self._test.vapi.gbp_ext_itf_add_del(
214 0, self.itf.sw_if_index, self.bd.bd_id, self.rd.rd_id, self.flags)
217 return "gbp-ext-itf:[%d]%s" % (self.itf.sw_if_index,
218 " [anon]" if self.flags else "")
220 def query_vpp_config(self):
221 rs = self._test.vapi.gbp_ext_itf_dump()
223 if r.ext_itf.sw_if_index == self.itf.sw_if_index:
228 class VppGbpSubnet(VppObject):
233 def __init__(self, test, rd, address, address_len,
234 type, sw_if_index=None, sclass=None):
236 self.rd_id = rd.rd_id
237 self.prefix = VppIpPrefix(address, address_len)
239 self.sw_if_index = sw_if_index
242 def add_vpp_config(self):
243 self._test.vapi.gbp_subnet_add_del(
246 self.prefix.encode(),
248 sw_if_index=self.sw_if_index if self.sw_if_index else 0xffffffff,
249 sclass=self.sclass if self.sclass else 0xffff)
250 self._test.registry.register(self, self._test.logger)
252 def remove_vpp_config(self):
253 self._test.vapi.gbp_subnet_add_del(
256 self.prefix.encode(),
260 return "gbp-subnet:[%d-%s]" % (self.rd_id, self.prefix)
262 def query_vpp_config(self):
263 ss = self._test.vapi.gbp_subnet_dump()
265 if s.subnet.rd_id == self.rd_id and \
266 s.subnet.type == self.type and \
267 s.subnet.prefix == self.prefix:
272 class VppGbpEndpointRetention(object):
273 def __init__(self, remote_ep_timeout=0xffffffff):
274 self.remote_ep_timeout = remote_ep_timeout
277 return {'remote_ep_timeout': self.remote_ep_timeout}
280 class VppGbpEndpointGroup(VppObject):
285 def __init__(self, test, vnid, sclass, rd, bd, uplink,
286 bvi, bvi_ip4, bvi_ip6=None,
287 retention=VppGbpEndpointRetention()):
291 self.bvi_ip4 = VppIpAddress(bvi_ip4)
292 self.bvi_ip6 = VppIpAddress(bvi_ip6)
299 self.retention = retention
301 def add_vpp_config(self):
302 self._test.vapi.gbp_endpoint_group_add(
307 self.uplink.sw_if_index if self.uplink else INDEX_INVALID,
308 self.retention.encode())
309 self._test.registry.register(self, self._test.logger)
311 def remove_vpp_config(self):
312 self._test.vapi.gbp_endpoint_group_del(self.sclass)
315 return "gbp-endpoint-group:[%d]" % (self.vnid)
317 def query_vpp_config(self):
318 epgs = self._test.vapi.gbp_endpoint_group_dump()
320 if epg.epg.vnid == self.vnid:
325 class VppGbpBridgeDomain(VppObject):
330 def __init__(self, test, bd, rd, bvi, uu_fwd=None,
331 bm_flood=None, learn=True, uu_drop=False, bm_drop=False):
335 self.bm_flood = bm_flood
339 e = VppEnum.vl_api_gbp_bridge_domain_flags_t
341 self.learn = e.GBP_BD_API_FLAG_NONE
343 self.learn = e.GBP_BD_API_FLAG_DO_NOT_LEARN
345 self.learn |= e.GBP_BD_API_FLAG_UU_FWD_DROP
347 self.learn |= e.GBP_BD_API_FLAG_MCAST_DROP
349 def add_vpp_config(self):
350 self._test.vapi.gbp_bridge_domain_add(
354 self.bvi.sw_if_index,
355 self.uu_fwd.sw_if_index if self.uu_fwd else INDEX_INVALID,
356 self.bm_flood.sw_if_index if self.bm_flood else INDEX_INVALID)
357 self._test.registry.register(self, self._test.logger)
359 def remove_vpp_config(self):
360 self._test.vapi.gbp_bridge_domain_del(self.bd.bd_id)
363 return "gbp-bridge-domain:[%d]" % (self.bd.bd_id)
365 def query_vpp_config(self):
366 bds = self._test.vapi.gbp_bridge_domain_dump()
368 if bd.bd.bd_id == self.bd.bd_id:
373 class VppGbpRouteDomain(VppObject):
378 def __init__(self, test, rd_id, scope, t4, t6, ip4_uu=None, ip6_uu=None):
387 def add_vpp_config(self):
388 self._test.vapi.gbp_route_domain_add(
393 self.ip4_uu.sw_if_index if self.ip4_uu else INDEX_INVALID,
394 self.ip6_uu.sw_if_index if self.ip6_uu else INDEX_INVALID)
395 self._test.registry.register(self, self._test.logger)
397 def remove_vpp_config(self):
398 self._test.vapi.gbp_route_domain_del(self.rd_id)
401 return "gbp-route-domain:[%d]" % (self.rd_id)
403 def query_vpp_config(self):
404 rds = self._test.vapi.gbp_route_domain_dump()
406 if rd.rd.rd_id == self.rd_id:
411 class VppGbpContractNextHop():
412 def __init__(self, mac, bd, ip, rd):
419 return {'ip': self.ip.encode(),
420 'mac': self.mac.packed,
421 'bd_id': self.bd.bd.bd_id,
422 'rd_id': self.rd.rd_id}
425 class VppGbpContractRule():
426 def __init__(self, action, hash_mode, nhs=None):
428 self.hash_mode = hash_mode
429 self.nhs = [] if nhs is None else nhs
434 nhs.append(nh.encode())
437 return {'action': self.action,
439 'hash_mode': self.hash_mode,
440 'n_nhs': len(self.nhs),
444 return '<VppGbpContractRule action=%s, hash_mode=%s>' % (
445 self.action, self.hash_mode)
448 class VppGbpContract(VppObject):
453 def __init__(self, test, scope, sclass, dclass, acl_index,
454 rules, allowed_ethertypes):
456 if not isinstance(rules, list):
457 raise ValueError("'rules' must be a list.")
458 if not isinstance(allowed_ethertypes, list):
459 raise ValueError("'allowed_ethertypes' must be a list.")
461 self.acl_index = acl_index
465 self.allowed_ethertypes = allowed_ethertypes
466 while (len(self.allowed_ethertypes) < 16):
467 self.allowed_ethertypes.append(0)
469 def add_vpp_config(self):
472 rules.append(r.encode())
473 r = self._test.vapi.gbp_contract_add_del(
476 'acl_index': self.acl_index,
478 'sclass': self.sclass,
479 'dclass': self.dclass,
480 'n_rules': len(rules),
482 'n_ether_types': len(self.allowed_ethertypes),
483 'allowed_ethertypes': self.allowed_ethertypes})
484 self.stats_index = r.stats_index
485 self._test.registry.register(self, self._test.logger)
487 def remove_vpp_config(self):
488 self._test.vapi.gbp_contract_add_del(
491 'acl_index': self.acl_index,
493 'sclass': self.sclass,
494 'dclass': self.dclass,
497 'n_ether_types': len(self.allowed_ethertypes),
498 'allowed_ethertypes': self.allowed_ethertypes})
501 return "gbp-contract:[%d:%d:%d:%d]" % (self.scope,
506 def query_vpp_config(self):
507 cs = self._test.vapi.gbp_contract_dump()
509 if c.contract.scope == self.scope \
510 and c.contract.sclass == self.sclass \
511 and c.contract.dclass == self.dclass:
515 def get_drop_stats(self):
516 c = self._test.statistics.get_counter("/net/gbp/contract/drop")
517 return c[0][self.stats_index]
519 def get_permit_stats(self):
520 c = self._test.statistics.get_counter("/net/gbp/contract/permit")
521 return c[0][self.stats_index]
524 class VppGbpVxlanTunnel(VppInterface):
529 def __init__(self, test, vni, bd_rd_id, mode, src):
530 super(VppGbpVxlanTunnel, self).__init__(test)
533 self.bd_rd_id = bd_rd_id
537 def add_vpp_config(self):
538 r = self._test.vapi.gbp_vxlan_tunnel_add(
543 self.set_sw_if_index(r.sw_if_index)
544 self._test.registry.register(self, self._test.logger)
546 def remove_vpp_config(self):
547 self._test.vapi.gbp_vxlan_tunnel_del(self.vni)
550 return "gbp-vxlan:%d" % (self.sw_if_index)
552 def query_vpp_config(self):
553 return find_gbp_vxlan(self._test, self.vni)
556 class VppGbpAcl(VppObject):
561 def __init__(self, test):
563 self.acl_index = 4294967295
565 def create_rule(self, is_ipv6=0, permit_deny=0, proto=-1,
566 s_prefix=0, s_ip=b'\x00\x00\x00\x00', sport_from=0,
567 sport_to=65535, d_prefix=0, d_ip=b'\x00\x00\x00\x00',
568 dport_from=0, dport_to=65535):
569 if proto == -1 or proto == 0:
572 elif proto == 1 or proto == 58:
575 rule = ({'is_permit': permit_deny, 'is_ipv6': is_ipv6, 'proto': proto,
576 'srcport_or_icmptype_first': sport_from,
577 'srcport_or_icmptype_last': sport_to,
578 'src_ip_prefix_len': s_prefix,
580 'dstport_or_icmpcode_first': dport_from,
581 'dstport_or_icmpcode_last': dport_to,
582 'dst_ip_prefix_len': d_prefix,
583 'dst_ip_addr': d_ip})
586 def add_vpp_config(self, rules):
588 reply = self._test.vapi.acl_add_replace(acl_index=self.acl_index,
591 self.acl_index = reply.acl_index
592 return self.acl_index
594 def remove_vpp_config(self):
595 self._test.vapi.acl_del(self.acl_index)
598 return "gbp-acl:[%d]" % (self.acl_index)
600 def query_vpp_config(self):
601 cs = self._test.vapi.acl_dump()
603 if c.acl_index == self.acl_index:
608 class TestGBP(VppTestCase):
609 """ GBP Test Case """
612 def config_flags(self):
613 return VppEnum.vl_api_nat_config_flags_t
617 super(TestGBP, cls).setUpClass()
620 def tearDownClass(cls):
621 super(TestGBP, cls).tearDownClass()
624 super(TestGBP, self).setUp()
626 self.create_pg_interfaces(range(9))
627 self.create_loopback_interfaces(8)
629 self.router_mac = MACAddress("00:11:22:33:44:55")
631 for i in self.pg_interfaces:
633 for i in self.lo_interfaces:
636 self.vlan_100 = VppDot1QSubint(self, self.pg0, 100)
637 self.vlan_100.admin_up()
638 self.vlan_101 = VppDot1QSubint(self, self.pg0, 101)
639 self.vlan_101.admin_up()
640 self.vlan_102 = VppDot1QSubint(self, self.pg0, 102)
641 self.vlan_102.admin_up()
644 for i in self.pg_interfaces:
646 super(TestGBP, self).tearDown()
647 self.vlan_102.remove_vpp_config()
648 self.vlan_101.remove_vpp_config()
649 self.vlan_100.remove_vpp_config()
651 def send_and_expect_bridged(self, src, tx, dst):
652 rx = self.send_and_expect(src, tx, dst)
655 self.assertEqual(r[Ether].src, tx[0][Ether].src)
656 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
657 self.assertEqual(r[IP].src, tx[0][IP].src)
658 self.assertEqual(r[IP].dst, tx[0][IP].dst)
661 def send_and_expect_bridged6(self, src, tx, dst):
662 rx = self.send_and_expect(src, tx, dst)
665 self.assertEqual(r[Ether].src, tx[0][Ether].src)
666 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
667 self.assertEqual(r[IPv6].src, tx[0][IPv6].src)
668 self.assertEqual(r[IPv6].dst, tx[0][IPv6].dst)
671 def send_and_expect_routed(self, src, tx, dst, src_mac):
672 rx = self.send_and_expect(src, tx, dst)
675 self.assertEqual(r[Ether].src, src_mac)
676 self.assertEqual(r[Ether].dst, dst.remote_mac)
677 self.assertEqual(r[IP].src, tx[0][IP].src)
678 self.assertEqual(r[IP].dst, tx[0][IP].dst)
681 def send_and_expect_natted(self, src, tx, dst, src_ip):
682 rx = self.send_and_expect(src, tx, dst)
685 self.assertEqual(r[Ether].src, tx[0][Ether].src)
686 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
687 self.assertEqual(r[IP].src, src_ip)
688 self.assertEqual(r[IP].dst, tx[0][IP].dst)
691 def send_and_expect_natted6(self, src, tx, dst, src_ip):
692 rx = self.send_and_expect(src, tx, dst)
695 self.assertEqual(r[Ether].src, tx[0][Ether].src)
696 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
697 self.assertEqual(r[IPv6].src, src_ip)
698 self.assertEqual(r[IPv6].dst, tx[0][IPv6].dst)
701 def send_and_expect_unnatted(self, src, tx, dst, dst_ip):
702 rx = self.send_and_expect(src, tx, dst)
705 self.assertEqual(r[Ether].src, tx[0][Ether].src)
706 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
707 self.assertEqual(r[IP].dst, dst_ip)
708 self.assertEqual(r[IP].src, tx[0][IP].src)
711 def send_and_expect_unnatted6(self, src, tx, dst, dst_ip):
712 rx = self.send_and_expect(src, tx, dst)
715 self.assertEqual(r[Ether].src, tx[0][Ether].src)
716 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
717 self.assertEqual(r[IPv6].dst, dst_ip)
718 self.assertEqual(r[IPv6].src, tx[0][IPv6].src)
721 def send_and_expect_double_natted(self, src, tx, dst, src_ip, dst_ip):
722 rx = self.send_and_expect(src, tx, dst)
725 self.assertEqual(r[Ether].src, str(self.router_mac))
726 self.assertEqual(r[Ether].dst, dst.remote_mac)
727 self.assertEqual(r[IP].dst, dst_ip)
728 self.assertEqual(r[IP].src, src_ip)
731 def send_and_expect_double_natted6(self, src, tx, dst, src_ip, dst_ip):
732 rx = self.send_and_expect(src, tx, dst)
735 self.assertEqual(r[Ether].src, str(self.router_mac))
736 self.assertEqual(r[Ether].dst, dst.remote_mac)
737 self.assertEqual(r[IPv6].dst, dst_ip)
738 self.assertEqual(r[IPv6].src, src_ip)
741 def send_and_expect_no_arp(self, src, tx, dst):
742 self.pg_send(src, tx)
743 dst.get_capture(0, timeout=1)
744 dst.assert_nothing_captured(remark="")
747 def send_and_expect_arp(self, src, tx, dst):
748 rx = self.send_and_expect(src, tx, dst)
751 self.assertEqual(r[Ether].src, tx[0][Ether].src)
752 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
753 self.assertEqual(r[ARP].psrc, tx[0][ARP].psrc)
754 self.assertEqual(r[ARP].pdst, tx[0][ARP].pdst)
755 self.assertEqual(r[ARP].hwsrc, tx[0][ARP].hwsrc)
756 self.assertEqual(r[ARP].hwdst, tx[0][ARP].hwdst)
760 """ Group Based Policy """
762 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
767 gt4 = VppIpTable(self, 0)
769 gt6 = VppIpTable(self, 0, is_ip6=True)
771 nt4 = VppIpTable(self, 20)
773 nt6 = VppIpTable(self, 20, is_ip6=True)
776 rd0 = VppGbpRouteDomain(self, 0, 400, gt4, gt6, None, None)
777 rd20 = VppGbpRouteDomain(self, 20, 420, nt4, nt6, None, None)
780 rd20.add_vpp_config()
785 bd1 = VppBridgeDomain(self, 1)
786 bd2 = VppBridgeDomain(self, 2)
787 bd20 = VppBridgeDomain(self, 20)
791 bd20.add_vpp_config()
793 gbd1 = VppGbpBridgeDomain(self, bd1, rd0, self.loop0)
794 gbd2 = VppGbpBridgeDomain(self, bd2, rd0, self.loop1)
795 gbd20 = VppGbpBridgeDomain(self, bd20, rd20, self.loop2)
797 gbd1.add_vpp_config()
798 gbd2.add_vpp_config()
799 gbd20.add_vpp_config()
802 # 3 EPGs, 2 of which share a BD.
803 # 2 NAT EPGs, one for floating-IP subnets, the other for internet
805 epgs = [VppGbpEndpointGroup(self, 220, 1220, rd0, gbd1,
806 self.pg4, self.loop0,
807 "10.0.0.128", "2001:10::128"),
808 VppGbpEndpointGroup(self, 221, 1221, rd0, gbd1,
809 self.pg5, self.loop0,
810 "10.0.1.128", "2001:10:1::128"),
811 VppGbpEndpointGroup(self, 222, 1222, rd0, gbd2,
812 self.pg6, self.loop1,
813 "10.0.2.128", "2001:10:2::128"),
814 VppGbpEndpointGroup(self, 333, 1333, rd20, gbd20,
815 self.pg7, self.loop2,
816 "11.0.0.128", "3001::128"),
817 VppGbpEndpointGroup(self, 444, 1444, rd20, gbd20,
818 self.pg8, self.loop2,
819 "11.0.0.129", "3001::129")]
820 recircs = [VppGbpRecirc(self, epgs[0], self.loop3),
821 VppGbpRecirc(self, epgs[1], self.loop4),
822 VppGbpRecirc(self, epgs[2], self.loop5),
823 VppGbpRecirc(self, epgs[3], self.loop6, is_ext=True),
824 VppGbpRecirc(self, epgs[4], self.loop7, is_ext=True)]
827 recirc_nat = recircs[3]
830 # 4 end-points, 2 in the same subnet, 3 in the same BD
832 eps = [VppGbpEndpoint(self, self.pg0,
834 "10.0.0.1", "11.0.0.1",
835 "2001:10::1", "3001::1"),
836 VppGbpEndpoint(self, self.pg1,
838 "10.0.0.2", "11.0.0.2",
839 "2001:10::2", "3001::2"),
840 VppGbpEndpoint(self, self.pg2,
842 "10.0.1.1", "11.0.0.3",
843 "2001:10:1::1", "3001::3"),
844 VppGbpEndpoint(self, self.pg3,
846 "10.0.2.1", "11.0.0.4",
847 "2001:10:2::1", "3001::4")]
850 # Config related to each of the EPGs
853 # IP config on the BVI interfaces
854 if epg != epgs[1] and epg != epgs[4]:
855 VppIpInterfaceBind(self, epg.bvi, epg.rd.t4).add_vpp_config()
856 VppIpInterfaceBind(self, epg.bvi, epg.rd.t6).add_vpp_config()
857 self.vapi.sw_interface_set_mac_address(
859 self.router_mac.packed)
861 # The BVIs are NAT inside interfaces
862 flags = self.config_flags.NAT_IS_INSIDE
863 self.vapi.nat44_interface_add_del_feature(
864 sw_if_index=epg.bvi.sw_if_index,
865 flags=flags, is_add=1)
866 self.vapi.nat66_add_del_interface(
867 is_add=1, flags=flags,
868 sw_if_index=epg.bvi.sw_if_index)
870 if_ip4 = VppIpInterfaceAddress(self, epg.bvi, epg.bvi_ip4, 32)
871 if_ip6 = VppIpInterfaceAddress(self, epg.bvi, epg.bvi_ip6, 128)
872 if_ip4.add_vpp_config()
873 if_ip6.add_vpp_config()
875 # EPG uplink interfaces in the RD
876 VppIpInterfaceBind(self, epg.uplink, epg.rd.t4).add_vpp_config()
877 VppIpInterfaceBind(self, epg.uplink, epg.rd.t6).add_vpp_config()
879 # add the BD ARP termination entry for BVI IP
880 epg.bd_arp_ip4 = VppBridgeDomainArpEntry(self, epg.bd.bd,
881 str(self.router_mac),
883 epg.bd_arp_ip6 = VppBridgeDomainArpEntry(self, epg.bd.bd,
884 str(self.router_mac),
886 epg.bd_arp_ip4.add_vpp_config()
887 epg.bd_arp_ip6.add_vpp_config()
892 for recirc in recircs:
893 # EPG's ingress recirculation interface maps to its RD
894 VppIpInterfaceBind(self, recirc.recirc,
895 recirc.epg.rd.t4).add_vpp_config()
896 VppIpInterfaceBind(self, recirc.recirc,
897 recirc.epg.rd.t6).add_vpp_config()
899 self.vapi.nat44_interface_add_del_feature(
900 sw_if_index=recirc.recirc.sw_if_index, is_add=1)
901 self.vapi.nat66_add_del_interface(
903 sw_if_index=recirc.recirc.sw_if_index)
905 recirc.add_vpp_config()
907 for recirc in recircs:
908 self.assertTrue(find_bridge_domain_port(self,
909 recirc.epg.bd.bd.bd_id,
910 recirc.recirc.sw_if_index))
913 self.pg_enable_capture(self.pg_interfaces)
916 # routes to the endpoints. We need these since there are no
917 # adj-fibs due to the fact the the BVI address has /32 and
918 # the subnet is not attached.
920 for (ip, fip) in zip(ep.ips, ep.fips):
921 # Add static mappings for each EP from the 10/8 to 11/8 network
923 flags = self.config_flags.NAT_IS_ADDR_ONLY
924 self.vapi.nat44_add_del_static_mapping(
926 local_ip_address=ip.bytes,
927 external_ip_address=fip.bytes,
928 external_sw_if_index=0xFFFFFFFF,
932 self.vapi.nat66_add_del_static_mapping(
933 local_ip_address=ip.bytes,
934 external_ip_address=fip.bytes,
940 self.logger.info(self.vapi.cli("sh gbp endpoint"))
942 # ... results in a Gratuitous ARP/ND on the EPG's uplink
943 rx = ep.epg.uplink.get_capture(len(ep.ips), timeout=0.2)
945 for ii, ip in enumerate(ep.ips):
949 self.assertTrue(p.haslayer(ICMPv6ND_NA))
950 self.assertEqual(p[ICMPv6ND_NA].tgt, ip.address)
952 self.assertTrue(p.haslayer(ARP))
953 self.assertEqual(p[ARP].psrc, ip.address)
954 self.assertEqual(p[ARP].pdst, ip.address)
956 # add the BD ARP termination entry for floating IP
958 ba = VppBridgeDomainArpEntry(self, epg_nat.bd.bd, ep.mac,
962 # floating IPs route via EPG recirc
964 self, fip.address, fip.length,
965 [VppRoutePath(fip.address,
966 ep.recirc.recirc.sw_if_index,
967 type=FibPathType.FIB_PATH_TYPE_DVR,
968 proto=fip.dpo_proto)],
972 # L2 FIB entries in the NAT EPG BD to bridge the packets from
973 # the outside direct to the internal EPG
974 lf = VppL2FibEntry(self, epg_nat.bd.bd, ep.mac,
975 ep.recirc.recirc, bvi_mac=0)
979 # ARP packets for unknown IP are sent to the EPG uplink
981 pkt_arp = (Ether(dst="ff:ff:ff:ff:ff:ff",
982 src=self.pg0.remote_mac) /
984 hwdst="ff:ff:ff:ff:ff:ff",
985 hwsrc=self.pg0.remote_mac,
989 self.vapi.cli("clear trace")
990 self.pg0.add_stream(pkt_arp)
992 self.pg_enable_capture(self.pg_interfaces)
995 rxd = epgs[0].uplink.get_capture(1)
998 # ARP/ND packets get a response
1000 pkt_arp = (Ether(dst="ff:ff:ff:ff:ff:ff",
1001 src=self.pg0.remote_mac) /
1003 hwdst="ff:ff:ff:ff:ff:ff",
1004 hwsrc=self.pg0.remote_mac,
1005 pdst=epgs[0].bvi_ip4.address,
1006 psrc=eps[0].ip4.address))
1008 self.send_and_expect(self.pg0, [pkt_arp], self.pg0)
1010 nsma = in6_getnsma(inet_pton(AF_INET6, eps[0].ip6.address))
1011 d = inet_ntop(AF_INET6, nsma)
1012 pkt_nd = (Ether(dst=in6_getnsmac(nsma),
1013 src=self.pg0.remote_mac) /
1014 IPv6(dst=d, src=eps[0].ip6.address) /
1015 ICMPv6ND_NS(tgt=epgs[0].bvi_ip6.address) /
1016 ICMPv6NDOptSrcLLAddr(lladdr=self.pg0.remote_mac))
1017 self.send_and_expect(self.pg0, [pkt_nd], self.pg0)
1020 # broadcast packets are flooded
1022 pkt_bcast = (Ether(dst="ff:ff:ff:ff:ff:ff",
1023 src=self.pg0.remote_mac) /
1024 IP(src=eps[0].ip4.address, dst="232.1.1.1") /
1025 UDP(sport=1234, dport=1234) /
1028 self.vapi.cli("clear trace")
1029 self.pg0.add_stream(pkt_bcast)
1031 self.pg_enable_capture(self.pg_interfaces)
1034 rxd = eps[1].itf.get_capture(1)
1035 self.assertEqual(rxd[0][Ether].dst, pkt_bcast[Ether].dst)
1036 rxd = epgs[0].uplink.get_capture(1)
1037 self.assertEqual(rxd[0][Ether].dst, pkt_bcast[Ether].dst)
1040 # packets to non-local L3 destinations dropped
1042 pkt_intra_epg_220_ip4 = (Ether(src=self.pg0.remote_mac,
1043 dst=str(self.router_mac)) /
1044 IP(src=eps[0].ip4.address,
1046 UDP(sport=1234, dport=1234) /
1048 pkt_inter_epg_222_ip4 = (Ether(src=self.pg0.remote_mac,
1049 dst=str(self.router_mac)) /
1050 IP(src=eps[0].ip4.address,
1052 UDP(sport=1234, dport=1234) /
1055 self.send_and_assert_no_replies(self.pg0,
1056 pkt_intra_epg_220_ip4 * NUM_PKTS)
1058 pkt_inter_epg_222_ip6 = (Ether(src=self.pg0.remote_mac,
1059 dst=str(self.router_mac)) /
1060 IPv6(src=eps[0].ip6.address,
1061 dst="2001:10::99") /
1062 UDP(sport=1234, dport=1234) /
1064 self.send_and_assert_no_replies(self.pg0,
1065 pkt_inter_epg_222_ip6 * NUM_PKTS)
1068 # Add the subnet routes
1071 self, rd0, "10.0.0.0", 24,
1072 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1074 self, rd0, "10.0.1.0", 24,
1075 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1077 self, rd0, "10.0.2.0", 24,
1078 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1080 self, rd0, "2001:10::1", 64,
1081 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1083 self, rd0, "2001:10:1::1", 64,
1084 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1086 self, rd0, "2001:10:2::1", 64,
1087 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1088 s41.add_vpp_config()
1089 s42.add_vpp_config()
1090 s43.add_vpp_config()
1091 s61.add_vpp_config()
1092 s62.add_vpp_config()
1093 s63.add_vpp_config()
1095 self.send_and_expect_bridged(eps[0].itf,
1096 pkt_intra_epg_220_ip4 * NUM_PKTS,
1098 self.send_and_expect_bridged(eps[0].itf,
1099 pkt_inter_epg_222_ip4 * NUM_PKTS,
1101 self.send_and_expect_bridged6(eps[0].itf,
1102 pkt_inter_epg_222_ip6 * NUM_PKTS,
1105 self.logger.info(self.vapi.cli("sh ip fib 11.0.0.2"))
1106 self.logger.info(self.vapi.cli("sh gbp endpoint-group"))
1107 self.logger.info(self.vapi.cli("sh gbp endpoint"))
1108 self.logger.info(self.vapi.cli("sh gbp recirc"))
1109 self.logger.info(self.vapi.cli("sh int"))
1110 self.logger.info(self.vapi.cli("sh int addr"))
1111 self.logger.info(self.vapi.cli("sh int feat loop6"))
1112 self.logger.info(self.vapi.cli("sh vlib graph ip4-gbp-src-classify"))
1113 self.logger.info(self.vapi.cli("sh int feat loop3"))
1114 self.logger.info(self.vapi.cli("sh int feat pg0"))
1117 # Packet destined to unknown unicast is sent on the epg uplink ...
1119 pkt_intra_epg_220_to_uplink = (Ether(src=self.pg0.remote_mac,
1120 dst="00:00:00:33:44:55") /
1121 IP(src=eps[0].ip4.address,
1123 UDP(sport=1234, dport=1234) /
1126 self.send_and_expect_bridged(eps[0].itf,
1127 pkt_intra_epg_220_to_uplink * NUM_PKTS,
1129 # ... and nowhere else
1130 self.pg1.get_capture(0, timeout=0.1)
1131 self.pg1.assert_nothing_captured(remark="Flood onto other VMS")
1133 pkt_intra_epg_221_to_uplink = (Ether(src=self.pg2.remote_mac,
1134 dst="00:00:00:33:44:66") /
1135 IP(src=eps[0].ip4.address,
1137 UDP(sport=1234, dport=1234) /
1140 self.send_and_expect_bridged(eps[2].itf,
1141 pkt_intra_epg_221_to_uplink * NUM_PKTS,
1145 # Packets from the uplink are forwarded in the absence of a contract
1147 pkt_intra_epg_220_from_uplink = (Ether(src="00:00:00:33:44:55",
1148 dst=self.pg0.remote_mac) /
1149 IP(src=eps[0].ip4.address,
1151 UDP(sport=1234, dport=1234) /
1154 self.send_and_expect_bridged(self.pg4,
1155 pkt_intra_epg_220_from_uplink * NUM_PKTS,
1159 # in the absence of policy, endpoints in the same EPG
1162 pkt_intra_epg = (Ether(src=self.pg0.remote_mac,
1163 dst=self.pg1.remote_mac) /
1164 IP(src=eps[0].ip4.address,
1165 dst=eps[1].ip4.address) /
1166 UDP(sport=1234, dport=1234) /
1169 self.send_and_expect_bridged(self.pg0,
1170 pkt_intra_epg * NUM_PKTS,
1174 # in the absence of policy, endpoints in the different EPG
1175 # cannot communicate
1177 pkt_inter_epg_220_to_221 = (Ether(src=self.pg0.remote_mac,
1178 dst=self.pg2.remote_mac) /
1179 IP(src=eps[0].ip4.address,
1180 dst=eps[2].ip4.address) /
1181 UDP(sport=1234, dport=1234) /
1183 pkt_inter_epg_221_to_220 = (Ether(src=self.pg2.remote_mac,
1184 dst=self.pg0.remote_mac) /
1185 IP(src=eps[2].ip4.address,
1186 dst=eps[0].ip4.address) /
1187 UDP(sport=1234, dport=1234) /
1189 pkt_inter_epg_220_to_222 = (Ether(src=self.pg0.remote_mac,
1190 dst=str(self.router_mac)) /
1191 IP(src=eps[0].ip4.address,
1192 dst=eps[3].ip4.address) /
1193 UDP(sport=1234, dport=1234) /
1196 self.send_and_assert_no_replies(eps[0].itf,
1197 pkt_inter_epg_220_to_221 * NUM_PKTS)
1198 self.send_and_assert_no_replies(eps[0].itf,
1199 pkt_inter_epg_220_to_222 * NUM_PKTS)
1202 # A uni-directional contract from EPG 220 -> 221
1204 acl = VppGbpAcl(self)
1205 rule = acl.create_rule(permit_deny=1, proto=17)
1206 rule2 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
1207 acl_index = acl.add_vpp_config([rule, rule2])
1208 c1 = VppGbpContract(
1209 self, 400, epgs[0].sclass, epgs[1].sclass, acl_index,
1210 [VppGbpContractRule(
1211 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1212 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1215 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1216 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1218 [ETH_P_IP, ETH_P_IPV6])
1221 self.send_and_expect_bridged(eps[0].itf,
1222 pkt_inter_epg_220_to_221 * NUM_PKTS,
1224 self.send_and_assert_no_replies(eps[0].itf,
1225 pkt_inter_epg_220_to_222 * NUM_PKTS)
1228 # contract for the return direction
1230 c2 = VppGbpContract(
1231 self, 400, epgs[1].sclass, epgs[0].sclass, acl_index,
1232 [VppGbpContractRule(
1233 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1234 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1237 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1238 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1240 [ETH_P_IP, ETH_P_IPV6])
1243 self.send_and_expect_bridged(eps[0].itf,
1244 pkt_inter_epg_220_to_221 * NUM_PKTS,
1246 self.send_and_expect_bridged(eps[2].itf,
1247 pkt_inter_epg_221_to_220 * NUM_PKTS,
1250 ds = c2.get_drop_stats()
1251 self.assertEqual(ds['packets'], 0)
1252 ps = c2.get_permit_stats()
1253 self.assertEqual(ps['packets'], NUM_PKTS)
1256 # the contract does not allow non-IP
1258 pkt_non_ip_inter_epg_220_to_221 = (Ether(src=self.pg0.remote_mac,
1259 dst=self.pg2.remote_mac) /
1261 self.send_and_assert_no_replies(eps[0].itf,
1262 pkt_non_ip_inter_epg_220_to_221 * 17)
1265 # check that inter group is still disabled for the groups
1266 # not in the contract.
1268 self.send_and_assert_no_replies(eps[0].itf,
1269 pkt_inter_epg_220_to_222 * NUM_PKTS)
1272 # A uni-directional contract from EPG 220 -> 222 'L3 routed'
1274 c3 = VppGbpContract(
1275 self, 400, epgs[0].sclass, epgs[2].sclass, acl_index,
1276 [VppGbpContractRule(
1277 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1278 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1281 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1282 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1284 [ETH_P_IP, ETH_P_IPV6])
1287 self.logger.info(self.vapi.cli("sh gbp contract"))
1289 self.send_and_expect_routed(eps[0].itf,
1290 pkt_inter_epg_220_to_222 * NUM_PKTS,
1292 str(self.router_mac))
1295 # remove both contracts, traffic stops in both directions
1297 c2.remove_vpp_config()
1298 c1.remove_vpp_config()
1299 c3.remove_vpp_config()
1300 acl.remove_vpp_config()
1302 self.send_and_assert_no_replies(eps[2].itf,
1303 pkt_inter_epg_221_to_220 * NUM_PKTS)
1304 self.send_and_assert_no_replies(eps[0].itf,
1305 pkt_inter_epg_220_to_221 * NUM_PKTS)
1306 self.send_and_expect_bridged(eps[0].itf,
1307 pkt_intra_epg * NUM_PKTS,
1311 # EPs to the outside world
1314 # in the EP's RD an external subnet via the NAT EPG's recirc
1316 self, rd0, "0.0.0.0", 0,
1317 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1318 sw_if_index=recirc_nat.recirc.sw_if_index,
1319 sclass=epg_nat.sclass)
1321 self, rd0, "11.0.0.0", 8,
1322 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1323 sw_if_index=recirc_nat.recirc.sw_if_index,
1324 sclass=epg_nat.sclass)
1325 se16 = VppGbpSubnet(
1327 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1328 sw_if_index=recirc_nat.recirc.sw_if_index,
1329 sclass=epg_nat.sclass)
1330 # in the NAT RD an external subnet via the NAT EPG's uplink
1332 self, rd20, "0.0.0.0", 0,
1333 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1334 sw_if_index=epg_nat.uplink.sw_if_index,
1335 sclass=epg_nat.sclass)
1336 se36 = VppGbpSubnet(
1337 self, rd20, "::", 0,
1338 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1339 sw_if_index=epg_nat.uplink.sw_if_index,
1340 sclass=epg_nat.sclass)
1342 self, rd20, "11.0.0.0", 8,
1343 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1344 sw_if_index=epg_nat.uplink.sw_if_index,
1345 sclass=epg_nat.sclass)
1346 se1.add_vpp_config()
1347 se2.add_vpp_config()
1348 se16.add_vpp_config()
1349 se3.add_vpp_config()
1350 se36.add_vpp_config()
1351 se4.add_vpp_config()
1353 self.logger.info(self.vapi.cli("sh ip fib 0.0.0.0/0"))
1354 self.logger.info(self.vapi.cli("sh ip fib 11.0.0.1"))
1355 self.logger.info(self.vapi.cli("sh ip6 fib ::/0"))
1356 self.logger.info(self.vapi.cli("sh ip6 fib %s" %
1360 # From an EP to an outside address: IN2OUT
1362 pkt_inter_epg_220_to_global = (Ether(src=self.pg0.remote_mac,
1363 dst=str(self.router_mac)) /
1364 IP(src=eps[0].ip4.address,
1366 UDP(sport=1234, dport=1234) /
1370 self.send_and_assert_no_replies(eps[0].itf,
1371 pkt_inter_epg_220_to_global * NUM_PKTS)
1373 acl2 = VppGbpAcl(self)
1374 rule = acl2.create_rule(permit_deny=1, proto=17, sport_from=1234,
1375 sport_to=1234, dport_from=1234, dport_to=1234)
1376 rule2 = acl2.create_rule(is_ipv6=1, permit_deny=1, proto=17,
1377 sport_from=1234, sport_to=1234,
1378 dport_from=1234, dport_to=1234)
1380 acl_index2 = acl2.add_vpp_config([rule, rule2])
1381 c4 = VppGbpContract(
1382 self, 400, epgs[0].sclass, epgs[3].sclass, acl_index2,
1383 [VppGbpContractRule(
1384 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1385 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1388 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1389 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1391 [ETH_P_IP, ETH_P_IPV6])
1394 self.send_and_expect_natted(eps[0].itf,
1395 pkt_inter_epg_220_to_global * NUM_PKTS,
1397 eps[0].fip4.address)
1399 pkt_inter_epg_220_to_global = (Ether(src=self.pg0.remote_mac,
1400 dst=str(self.router_mac)) /
1401 IPv6(src=eps[0].ip6.address,
1403 UDP(sport=1234, dport=1234) /
1406 self.send_and_expect_natted6(self.pg0,
1407 pkt_inter_epg_220_to_global * NUM_PKTS,
1409 eps[0].fip6.address)
1412 # From a global address to an EP: OUT2IN
1414 pkt_inter_epg_220_from_global = (Ether(src=str(self.router_mac),
1415 dst=self.pg0.remote_mac) /
1416 IP(dst=eps[0].fip4.address,
1418 UDP(sport=1234, dport=1234) /
1421 self.send_and_assert_no_replies(
1422 self.pg7, pkt_inter_epg_220_from_global * NUM_PKTS)
1424 c5 = VppGbpContract(
1425 self, 400, epgs[3].sclass, epgs[0].sclass, acl_index2,
1426 [VppGbpContractRule(
1427 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1428 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1431 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1432 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1434 [ETH_P_IP, ETH_P_IPV6])
1437 self.send_and_expect_unnatted(self.pg7,
1438 pkt_inter_epg_220_from_global * NUM_PKTS,
1442 pkt_inter_epg_220_from_global = (Ether(src=str(self.router_mac),
1443 dst=self.pg0.remote_mac) /
1444 IPv6(dst=eps[0].fip6.address,
1446 UDP(sport=1234, dport=1234) /
1449 self.send_and_expect_unnatted6(
1451 pkt_inter_epg_220_from_global * NUM_PKTS,
1456 # From a local VM to another local VM using resp. public addresses:
1459 pkt_intra_epg_220_global = (Ether(src=self.pg0.remote_mac,
1460 dst=str(self.router_mac)) /
1461 IP(src=eps[0].ip4.address,
1462 dst=eps[1].fip4.address) /
1463 UDP(sport=1234, dport=1234) /
1466 self.send_and_expect_double_natted(eps[0].itf,
1467 pkt_intra_epg_220_global * NUM_PKTS,
1469 eps[0].fip4.address,
1472 pkt_intra_epg_220_global = (Ether(src=self.pg0.remote_mac,
1473 dst=str(self.router_mac)) /
1474 IPv6(src=eps[0].ip6.address,
1475 dst=eps[1].fip6.address) /
1476 UDP(sport=1234, dport=1234) /
1479 self.send_and_expect_double_natted6(
1481 pkt_intra_epg_220_global * NUM_PKTS,
1483 eps[0].fip6.address,
1490 # del static mappings for each EP from the 10/8 to 11/8 network
1491 flags = self.config_flags.NAT_IS_ADDR_ONLY
1492 self.vapi.nat44_add_del_static_mapping(
1494 local_ip_address=ep.ip4.bytes,
1495 external_ip_address=ep.fip4.bytes,
1496 external_sw_if_index=0xFFFFFFFF,
1499 self.vapi.nat66_add_del_static_mapping(
1500 local_ip_address=ep.ip6.bytes,
1501 external_ip_address=ep.fip6.bytes,
1505 # IP config on the BVI interfaces
1506 if epg != epgs[0] and epg != epgs[3]:
1507 flags = self.config_flags.NAT_IS_INSIDE
1508 self.vapi.nat44_interface_add_del_feature(
1509 sw_if_index=epg.bvi.sw_if_index,
1512 self.vapi.nat66_add_del_interface(
1513 is_add=0, flags=flags,
1514 sw_if_index=epg.bvi.sw_if_index)
1516 for recirc in recircs:
1517 self.vapi.nat44_interface_add_del_feature(
1518 sw_if_index=recirc.recirc.sw_if_index,
1520 self.vapi.nat66_add_del_interface(
1522 sw_if_index=recirc.recirc.sw_if_index)
1524 def wait_for_ep_timeout(self, sw_if_index=None, ip=None, mac=None,
1525 tep=None, n_tries=100, s_time=1):
1527 if not find_gbp_endpoint(self, sw_if_index, ip, mac, tep=tep):
1529 n_tries = n_tries - 1
1531 self.assertFalse(find_gbp_endpoint(self, sw_if_index, ip, mac))
1534 def test_gbp_learn_l2(self):
1535 """ GBP L2 Endpoint Learning """
1537 self.vapi.cli("clear errors")
1539 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
1540 learnt = [{'mac': '00:00:11:11:11:01',
1542 'ip6': '2001:10::2'},
1543 {'mac': '00:00:11:11:11:02',
1545 'ip6': '2001:10::3'}]
1550 gt4 = VppIpTable(self, 1)
1551 gt4.add_vpp_config()
1552 gt6 = VppIpTable(self, 1, is_ip6=True)
1553 gt6.add_vpp_config()
1555 rd1 = VppGbpRouteDomain(self, 1, 401, gt4, gt6)
1556 rd1.add_vpp_config()
1559 # Pg2 hosts the vxlan tunnel, hosts on pg2 to act as TEPs
1560 # Pg3 hosts the IP4 UU-flood VXLAN tunnel
1561 # Pg4 hosts the IP6 UU-flood VXLAN tunnel
1563 self.pg2.config_ip4()
1564 self.pg2.resolve_arp()
1565 self.pg2.generate_remote_hosts(4)
1566 self.pg2.configure_ipv4_neighbors()
1567 self.pg3.config_ip4()
1568 self.pg3.resolve_arp()
1569 self.pg4.config_ip4()
1570 self.pg4.resolve_arp()
1573 # Add a mcast destination VXLAN-GBP tunnel for B&M traffic
1575 tun_bm = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
1578 tun_bm.add_vpp_config()
1581 # a GBP bridge domain with a BVI and a UU-flood interface
1583 bd1 = VppBridgeDomain(self, 1)
1584 bd1.add_vpp_config()
1585 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0,
1587 gbd1.add_vpp_config()
1589 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1590 self.logger.info(self.vapi.cli("sh gbp bridge"))
1592 # ... and has a /32 applied
1593 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
1594 ip_addr.add_vpp_config()
1597 # The Endpoint-group in which we are learning endpoints
1599 epg_220 = VppGbpEndpointGroup(self, 220, 112, rd1, gbd1,
1603 VppGbpEndpointRetention(2))
1604 epg_220.add_vpp_config()
1605 epg_330 = VppGbpEndpointGroup(self, 330, 113, rd1, gbd1,
1609 VppGbpEndpointRetention(2))
1610 epg_330.add_vpp_config()
1613 # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
1616 vx_tun_l2_1 = VppGbpVxlanTunnel(
1617 self, 99, bd1.bd_id,
1618 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L2,
1620 vx_tun_l2_1.add_vpp_config()
1623 # A static endpoint that the learnt endpoints are trying to
1626 ep = VppGbpEndpoint(self, self.pg0,
1628 "10.0.0.127", "11.0.0.127",
1629 "2001:10::1", "3001::1")
1632 self.assertTrue(find_route(self, ep.ip4.address, 32, table_id=1))
1634 # a packet with an sclass from an unknown EPG
1635 p = (Ether(src=self.pg2.remote_mac,
1636 dst=self.pg2.local_mac) /
1637 IP(src=self.pg2.remote_hosts[0].ip4,
1638 dst=self.pg2.local_ip4) /
1639 UDP(sport=1234, dport=48879) /
1640 VXLAN(vni=99, gpid=88, flags=0x88) /
1641 Ether(src=learnt[0]["mac"], dst=ep.mac) /
1642 IP(src=learnt[0]["ip"], dst=ep.ip4.address) /
1643 UDP(sport=1234, dport=1234) /
1646 self.send_and_assert_no_replies(self.pg2, p)
1648 self.logger.info(self.vapi.cli("sh error"))
1649 # self.assert_packet_counter_equal(
1650 # '/err/gbp-policy-port/drop-no-contract', 1)
1653 # we should not have learnt a new tunnel endpoint, since
1654 # the EPG was not learnt.
1656 self.assertEqual(INDEX_INVALID,
1657 find_vxlan_gbp_tunnel(self,
1659 self.pg2.remote_hosts[0].ip4,
1662 # epg is not learnt, because the EPG is unknown
1663 self.assertEqual(len(self.vapi.gbp_endpoint_dump()), 1)
1666 # Learn new EPs from IP packets
1668 for ii, l in enumerate(learnt):
1669 # a packet with an sclass from a known EPG
1670 # arriving on an unknown TEP
1671 p = (Ether(src=self.pg2.remote_mac,
1672 dst=self.pg2.local_mac) /
1673 IP(src=self.pg2.remote_hosts[1].ip4,
1674 dst=self.pg2.local_ip4) /
1675 UDP(sport=1234, dport=48879) /
1676 VXLAN(vni=99, gpid=112, flags=0x88) /
1677 Ether(src=l['mac'], dst=ep.mac) /
1678 IP(src=l['ip'], dst=ep.ip4.address) /
1679 UDP(sport=1234, dport=1234) /
1682 rx = self.send_and_expect(self.pg2, [p], self.pg0)
1685 tep1_sw_if_index = find_vxlan_gbp_tunnel(
1688 self.pg2.remote_hosts[1].ip4,
1690 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
1693 # the EP is learnt via the learnt TEP
1694 # both from its MAC and its IP
1696 self.assertTrue(find_gbp_endpoint(self,
1697 vx_tun_l2_1.sw_if_index,
1699 self.assertTrue(find_gbp_endpoint(self,
1700 vx_tun_l2_1.sw_if_index,
1703 # self.assert_packet_counter_equal(
1704 # '/err/gbp-policy-port/allow-intra-sclass', 2)
1706 self.logger.info(self.vapi.cli("show gbp endpoint"))
1707 self.logger.info(self.vapi.cli("show gbp vxlan"))
1708 self.logger.info(self.vapi.cli("show ip mfib"))
1711 # If we sleep for the threshold time, the learnt endpoints should
1715 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1719 # Learn new EPs from GARP packets received on the BD's mcast tunnel
1721 for ii, l in enumerate(learnt):
1722 # add some junk in the reserved field of the vxlan-header
1723 # next to the VNI. we should accept since reserved bits are
1725 p = (Ether(src=self.pg2.remote_mac,
1726 dst=self.pg2.local_mac) /
1727 IP(src=self.pg2.remote_hosts[1].ip4,
1729 UDP(sport=1234, dport=48879) /
1730 VXLAN(vni=88, reserved2=0x80, gpid=112, flags=0x88) /
1731 Ether(src=l['mac'], dst="ff:ff:ff:ff:ff:ff") /
1733 psrc=l['ip'], pdst=l['ip'],
1734 hwsrc=l['mac'], hwdst="ff:ff:ff:ff:ff:ff"))
1736 rx = self.send_and_expect(self.pg4, [p], self.pg0)
1739 tep1_sw_if_index = find_vxlan_gbp_tunnel(
1742 self.pg2.remote_hosts[1].ip4,
1744 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
1747 # the EP is learnt via the learnt TEP
1748 # both from its MAC and its IP
1750 self.assertTrue(find_gbp_endpoint(self,
1751 vx_tun_l2_1.sw_if_index,
1753 self.assertTrue(find_gbp_endpoint(self,
1754 vx_tun_l2_1.sw_if_index,
1758 # wait for the learnt endpoints to age out
1761 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1765 # Learn new EPs from L2 packets
1767 for ii, l in enumerate(learnt):
1768 # a packet with an sclass from a known EPG
1769 # arriving on an unknown TEP
1770 p = (Ether(src=self.pg2.remote_mac,
1771 dst=self.pg2.local_mac) /
1772 IP(src=self.pg2.remote_hosts[1].ip4,
1773 dst=self.pg2.local_ip4) /
1774 UDP(sport=1234, dport=48879) /
1775 VXLAN(vni=99, gpid=112, flags=0x88) /
1776 Ether(src=l['mac'], dst=ep.mac) /
1779 rx = self.send_and_expect(self.pg2, [p], self.pg0)
1782 tep1_sw_if_index = find_vxlan_gbp_tunnel(
1785 self.pg2.remote_hosts[1].ip4,
1787 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
1790 # the EP is learnt via the learnt TEP
1791 # both from its MAC and its IP
1793 self.assertTrue(find_gbp_endpoint(self,
1794 vx_tun_l2_1.sw_if_index,
1797 self.logger.info(self.vapi.cli("show gbp endpoint"))
1798 self.logger.info(self.vapi.cli("show gbp vxlan"))
1799 self.logger.info(self.vapi.cli("show vxlan-gbp tunnel"))
1802 # wait for the learnt endpoints to age out
1805 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1809 # repeat. the do not learn bit is set so the EPs are not learnt
1812 # a packet with an sclass from a known EPG
1813 p = (Ether(src=self.pg2.remote_mac,
1814 dst=self.pg2.local_mac) /
1815 IP(src=self.pg2.remote_hosts[1].ip4,
1816 dst=self.pg2.local_ip4) /
1817 UDP(sport=1234, dport=48879) /
1818 VXLAN(vni=99, gpid=112, flags=0x88, gpflags="D") /
1819 Ether(src=l['mac'], dst=ep.mac) /
1820 IP(src=l['ip'], dst=ep.ip4.address) /
1821 UDP(sport=1234, dport=1234) /
1824 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
1827 self.assertFalse(find_gbp_endpoint(self,
1828 vx_tun_l2_1.sw_if_index,
1835 # a packet with an sclass from a known EPG
1836 # set a reserved bit in addition to the G and I
1837 # reserved bits should not be checked on rx.
1838 p = (Ether(src=self.pg2.remote_mac,
1839 dst=self.pg2.local_mac) /
1840 IP(src=self.pg2.remote_hosts[1].ip4,
1841 dst=self.pg2.local_ip4) /
1842 UDP(sport=1234, dport=48879) /
1843 VXLAN(vni=99, gpid=112, flags=0xc8) /
1844 Ether(src=l['mac'], dst=ep.mac) /
1845 IP(src=l['ip'], dst=ep.ip4.address) /
1846 UDP(sport=1234, dport=1234) /
1849 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
1851 self.assertTrue(find_gbp_endpoint(self,
1852 vx_tun_l2_1.sw_if_index,
1856 # Static EP replies to dynamics
1858 self.logger.info(self.vapi.cli("sh l2fib bd_id 1"))
1860 p = (Ether(src=ep.mac, dst=l['mac']) /
1861 IP(dst=l['ip'], src=ep.ip4.address) /
1862 UDP(sport=1234, dport=1234) /
1865 rxs = self.send_and_expect(self.pg0, p * 17, self.pg2)
1868 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
1869 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
1870 self.assertEqual(rx[UDP].dport, 48879)
1871 # the UDP source port is a random value for hashing
1872 self.assertEqual(rx[VXLAN].gpid, 112)
1873 self.assertEqual(rx[VXLAN].vni, 99)
1874 self.assertTrue(rx[VXLAN].flags.G)
1875 self.assertTrue(rx[VXLAN].flags.Instance)
1876 self.assertTrue(rx[VXLAN].gpflags.A)
1877 self.assertFalse(rx[VXLAN].gpflags.D)
1880 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1884 # repeat in the other EPG
1885 # there's no contract between 220 and 330, but the A-bit is set
1886 # so the packet is cleared for delivery
1889 # a packet with an sclass from a known EPG
1890 p = (Ether(src=self.pg2.remote_mac,
1891 dst=self.pg2.local_mac) /
1892 IP(src=self.pg2.remote_hosts[1].ip4,
1893 dst=self.pg2.local_ip4) /
1894 UDP(sport=1234, dport=48879) /
1895 VXLAN(vni=99, gpid=113, flags=0x88, gpflags='A') /
1896 Ether(src=l['mac'], dst=ep.mac) /
1897 IP(src=l['ip'], dst=ep.ip4.address) /
1898 UDP(sport=1234, dport=1234) /
1901 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
1903 self.assertTrue(find_gbp_endpoint(self,
1904 vx_tun_l2_1.sw_if_index,
1908 # static EP cannot reach the learnt EPs since there is no contract
1909 # only test 1 EP as the others could timeout
1911 p = (Ether(src=ep.mac, dst=l['mac']) /
1912 IP(dst=learnt[0]['ip'], src=ep.ip4.address) /
1913 UDP(sport=1234, dport=1234) /
1916 self.send_and_assert_no_replies(self.pg0, [p])
1919 # refresh the entries after the check for no replies above
1922 # a packet with an sclass from a known EPG
1923 p = (Ether(src=self.pg2.remote_mac,
1924 dst=self.pg2.local_mac) /
1925 IP(src=self.pg2.remote_hosts[1].ip4,
1926 dst=self.pg2.local_ip4) /
1927 UDP(sport=1234, dport=48879) /
1928 VXLAN(vni=99, gpid=113, flags=0x88, gpflags='A') /
1929 Ether(src=l['mac'], dst=ep.mac) /
1930 IP(src=l['ip'], dst=ep.ip4.address) /
1931 UDP(sport=1234, dport=1234) /
1934 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
1936 self.assertTrue(find_gbp_endpoint(self,
1937 vx_tun_l2_1.sw_if_index,
1941 # Add the contract so they can talk
1943 acl = VppGbpAcl(self)
1944 rule = acl.create_rule(permit_deny=1, proto=17)
1945 rule2 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
1946 acl_index = acl.add_vpp_config([rule, rule2])
1947 c1 = VppGbpContract(
1948 self, 401, epg_220.sclass, epg_330.sclass, acl_index,
1949 [VppGbpContractRule(
1950 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1951 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1954 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1955 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1957 [ETH_P_IP, ETH_P_IPV6])
1961 p = (Ether(src=ep.mac, dst=l['mac']) /
1962 IP(dst=l['ip'], src=ep.ip4.address) /
1963 UDP(sport=1234, dport=1234) /
1966 self.send_and_expect(self.pg0, [p], self.pg2)
1969 # send UU packets from the local EP
1971 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1972 self.logger.info(self.vapi.cli("sh gbp bridge"))
1973 p_uu = (Ether(src=ep.mac, dst="00:11:11:11:11:11") /
1974 IP(dst="10.0.0.133", src=ep.ip4.address) /
1975 UDP(sport=1234, dport=1234) /
1977 rxs = self.send_and_expect(ep.itf, [p_uu], gbd1.uu_fwd)
1979 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1981 p_bm = (Ether(src=ep.mac, dst="ff:ff:ff:ff:ff:ff") /
1982 IP(dst="10.0.0.133", src=ep.ip4.address) /
1983 UDP(sport=1234, dport=1234) /
1985 rxs = self.send_and_expect_only(ep.itf, [p_bm], tun_bm.mcast_itf)
1988 self.assertEqual(rx[IP].src, self.pg4.local_ip4)
1989 self.assertEqual(rx[IP].dst, "239.1.1.1")
1990 self.assertEqual(rx[UDP].dport, 48879)
1991 # the UDP source port is a random value for hashing
1992 self.assertEqual(rx[VXLAN].gpid, 112)
1993 self.assertEqual(rx[VXLAN].vni, 88)
1994 self.assertTrue(rx[VXLAN].flags.G)
1995 self.assertTrue(rx[VXLAN].flags.Instance)
1996 self.assertFalse(rx[VXLAN].gpflags.A)
1997 self.assertFalse(rx[VXLAN].gpflags.D)
2000 # Check v6 Endpoints
2003 # a packet with an sclass from a known EPG
2004 p = (Ether(src=self.pg2.remote_mac,
2005 dst=self.pg2.local_mac) /
2006 IP(src=self.pg2.remote_hosts[1].ip4,
2007 dst=self.pg2.local_ip4) /
2008 UDP(sport=1234, dport=48879) /
2009 VXLAN(vni=99, gpid=113, flags=0x88, gpflags='A') /
2010 Ether(src=l['mac'], dst=ep.mac) /
2011 IPv6(src=l['ip6'], dst=ep.ip6.address) /
2012 UDP(sport=1234, dport=1234) /
2015 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
2017 self.assertTrue(find_gbp_endpoint(self,
2018 vx_tun_l2_1.sw_if_index,
2022 # L3 Endpoint Learning
2023 # - configured on the bridge's BVI
2030 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
2032 self.pg2.unconfig_ip4()
2033 self.pg3.unconfig_ip4()
2034 self.pg4.unconfig_ip4()
2036 self.logger.info(self.vapi.cli("sh int"))
2037 self.logger.info(self.vapi.cli("sh gbp vxlan"))
2039 def test_gbp_contract(self):
2040 """ GBP CONTRACTS """
2045 gt4 = VppIpTable(self, 0)
2046 gt4.add_vpp_config()
2047 gt6 = VppIpTable(self, 0, is_ip6=True)
2048 gt6.add_vpp_config()
2050 rd0 = VppGbpRouteDomain(self, 0, 400, gt4, gt6, None, None)
2052 rd0.add_vpp_config()
2057 bd1 = VppBridgeDomain(self, 1, arp_term=0)
2058 bd2 = VppBridgeDomain(self, 2, arp_term=0)
2060 bd1.add_vpp_config()
2061 bd2.add_vpp_config()
2063 gbd1 = VppGbpBridgeDomain(self, bd1, rd0, self.loop0)
2064 gbd2 = VppGbpBridgeDomain(self, bd2, rd0, self.loop1)
2066 gbd1.add_vpp_config()
2067 gbd2.add_vpp_config()
2070 # 3 EPGs, 2 of which share a BD.
2072 epgs = [VppGbpEndpointGroup(self, 220, 1220, rd0, gbd1,
2074 "10.0.0.128", "2001:10::128"),
2075 VppGbpEndpointGroup(self, 221, 1221, rd0, gbd1,
2077 "10.0.1.128", "2001:10:1::128"),
2078 VppGbpEndpointGroup(self, 222, 1222, rd0, gbd2,
2080 "10.0.2.128", "2001:10:2::128")]
2082 # 4 end-points, 2 in the same subnet, 3 in the same BD
2084 eps = [VppGbpEndpoint(self, self.pg0,
2086 "10.0.0.1", "11.0.0.1",
2087 "2001:10::1", "3001::1"),
2088 VppGbpEndpoint(self, self.pg1,
2090 "10.0.0.2", "11.0.0.2",
2091 "2001:10::2", "3001::2"),
2092 VppGbpEndpoint(self, self.pg2,
2094 "10.0.1.1", "11.0.0.3",
2095 "2001:10:1::1", "3001::3"),
2096 VppGbpEndpoint(self, self.pg3,
2098 "10.0.2.1", "11.0.0.4",
2099 "2001:10:2::1", "3001::4")]
2102 # Config related to each of the EPGs
2105 # IP config on the BVI interfaces
2107 VppIpInterfaceBind(self, epg.bvi, epg.rd.t4).add_vpp_config()
2108 VppIpInterfaceBind(self, epg.bvi, epg.rd.t6).add_vpp_config()
2109 self.vapi.sw_interface_set_mac_address(
2110 epg.bvi.sw_if_index,
2111 self.router_mac.packed)
2113 if_ip4 = VppIpInterfaceAddress(self, epg.bvi, epg.bvi_ip4, 32)
2114 if_ip6 = VppIpInterfaceAddress(self, epg.bvi, epg.bvi_ip6, 128)
2115 if_ip4.add_vpp_config()
2116 if_ip6.add_vpp_config()
2118 # add the BD ARP termination entry for BVI IP
2119 epg.bd_arp_ip4 = VppBridgeDomainArpEntry(self, epg.bd.bd,
2120 str(self.router_mac),
2121 epg.bvi_ip4.address)
2122 epg.bd_arp_ip4.add_vpp_config()
2125 epg.add_vpp_config()
2133 self.logger.info(self.vapi.cli("show gbp endpoint"))
2134 self.logger.info(self.vapi.cli("show interface"))
2135 self.logger.info(self.vapi.cli("show br"))
2138 # Intra epg allowed without contract
2140 pkt_intra_epg_220_to_220 = (Ether(src=self.pg0.remote_mac,
2141 dst=self.pg1.remote_mac) /
2142 IP(src=eps[0].ip4.address,
2143 dst=eps[1].ip4.address) /
2144 UDP(sport=1234, dport=1234) /
2147 self.send_and_expect_bridged(self.pg0,
2148 pkt_intra_epg_220_to_220 * 65,
2152 # Inter epg denied without contract
2154 pkt_inter_epg_220_to_221 = (Ether(src=self.pg0.remote_mac,
2155 dst=self.pg2.remote_mac) /
2156 IP(src=eps[0].ip4.address,
2157 dst=eps[2].ip4.address) /
2158 UDP(sport=1234, dport=1234) /
2161 self.send_and_assert_no_replies(self.pg0, pkt_inter_epg_220_to_221)
2164 # A uni-directional contract from EPG 220 -> 221
2166 acl = VppGbpAcl(self)
2167 rule = acl.create_rule(permit_deny=1, proto=17)
2168 rule2 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
2169 acl_index = acl.add_vpp_config([rule, rule2])
2170 c1 = VppGbpContract(
2171 self, 400, epgs[0].sclass, epgs[1].sclass, acl_index,
2172 [VppGbpContractRule(
2173 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2174 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2177 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2178 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2180 [ETH_P_IP, ETH_P_IPV6])
2183 self.send_and_expect_bridged(eps[0].itf,
2184 pkt_inter_epg_220_to_221 * 65,
2187 pkt_inter_epg_220_to_222 = (Ether(src=self.pg0.remote_mac,
2188 dst=str(self.router_mac)) /
2189 IP(src=eps[0].ip4.address,
2190 dst=eps[3].ip4.address) /
2191 UDP(sport=1234, dport=1234) /
2193 self.send_and_assert_no_replies(eps[0].itf,
2194 pkt_inter_epg_220_to_222 * 65)
2197 # contract for the return direction
2199 c2 = VppGbpContract(
2200 self, 400, epgs[1].sclass, epgs[0].sclass, acl_index,
2201 [VppGbpContractRule(
2202 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2203 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2206 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2207 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2209 [ETH_P_IP, ETH_P_IPV6])
2212 self.send_and_expect_bridged(eps[0].itf,
2213 pkt_inter_epg_220_to_221 * 65,
2215 pkt_inter_epg_221_to_220 = (Ether(src=self.pg2.remote_mac,
2216 dst=self.pg0.remote_mac) /
2217 IP(src=eps[2].ip4.address,
2218 dst=eps[0].ip4.address) /
2219 UDP(sport=1234, dport=1234) /
2221 self.send_and_expect_bridged(eps[2].itf,
2222 pkt_inter_epg_221_to_220 * 65,
2226 # contract between 220 and 222 uni-direction
2228 c3 = VppGbpContract(
2229 self, 400, epgs[0].sclass, epgs[2].sclass, acl_index,
2230 [VppGbpContractRule(
2231 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2232 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2235 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2236 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2238 [ETH_P_IP, ETH_P_IPV6])
2241 self.send_and_expect(eps[0].itf,
2242 pkt_inter_epg_220_to_222 * 65,
2245 c3.remove_vpp_config()
2246 c1.remove_vpp_config()
2247 c2.remove_vpp_config()
2248 acl.remove_vpp_config()
2250 def test_gbp_bd_flags(self):
2251 """ GBP BD FLAGS """
2256 gt4 = VppIpTable(self, 1)
2257 gt4.add_vpp_config()
2258 gt6 = VppIpTable(self, 1, is_ip6=True)
2259 gt6.add_vpp_config()
2261 rd1 = VppGbpRouteDomain(self, 1, 401, gt4, gt6)
2262 rd1.add_vpp_config()
2265 # Pg3 hosts the IP4 UU-flood VXLAN tunnel
2266 # Pg4 hosts the IP6 UU-flood VXLAN tunnel
2268 self.pg3.config_ip4()
2269 self.pg3.resolve_arp()
2270 self.pg4.config_ip4()
2271 self.pg4.resolve_arp()
2274 # Add a mcast destination VXLAN-GBP tunnel for B&M traffic
2276 tun_bm = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
2279 tun_bm.add_vpp_config()
2282 # a GBP bridge domain with a BVI and a UU-flood interface
2284 bd1 = VppBridgeDomain(self, 1)
2285 bd1.add_vpp_config()
2287 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0, self.pg3,
2288 tun_bm, uu_drop=True, bm_drop=True)
2289 gbd1.add_vpp_config()
2291 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2292 self.logger.info(self.vapi.cli("sh gbp bridge"))
2294 # ... and has a /32 applied
2295 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2296 ip_addr.add_vpp_config()
2299 # The Endpoint-group
2301 epg_220 = VppGbpEndpointGroup(self, 220, 112, rd1, gbd1,
2305 VppGbpEndpointRetention(2))
2306 epg_220.add_vpp_config()
2308 ep = VppGbpEndpoint(self, self.pg0,
2310 "10.0.0.127", "11.0.0.127",
2311 "2001:10::1", "3001::1")
2314 # send UU/BM packet from the local EP with UU drop and BM drop enabled
2317 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2318 self.logger.info(self.vapi.cli("sh gbp bridge"))
2319 p_uu = (Ether(src=ep.mac, dst="00:11:11:11:11:11") /
2320 IP(dst="10.0.0.133", src=ep.ip4.address) /
2321 UDP(sport=1234, dport=1234) /
2323 self.send_and_assert_no_replies(ep.itf, [p_uu])
2325 p_bm = (Ether(src=ep.mac, dst="ff:ff:ff:ff:ff:ff") /
2326 IP(dst="10.0.0.133", src=ep.ip4.address) /
2327 UDP(sport=1234, dport=1234) /
2329 self.send_and_assert_no_replies(ep.itf, [p_bm])
2331 self.pg3.unconfig_ip4()
2332 self.pg4.unconfig_ip4()
2334 self.logger.info(self.vapi.cli("sh int"))
2336 def test_gbp_learn_vlan_l2(self):
2337 """ GBP L2 Endpoint w/ VLANs"""
2339 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
2340 learnt = [{'mac': '00:00:11:11:11:01',
2342 'ip6': '2001:10::2'},
2343 {'mac': '00:00:11:11:11:02',
2345 'ip6': '2001:10::3'}]
2350 gt4 = VppIpTable(self, 1)
2351 gt4.add_vpp_config()
2352 gt6 = VppIpTable(self, 1, is_ip6=True)
2353 gt6.add_vpp_config()
2355 rd1 = VppGbpRouteDomain(self, 1, 401, gt4, gt6)
2356 rd1.add_vpp_config()
2359 # Pg2 hosts the vxlan tunnel, hosts on pg2 to act as TEPs
2361 self.pg2.config_ip4()
2362 self.pg2.resolve_arp()
2363 self.pg2.generate_remote_hosts(4)
2364 self.pg2.configure_ipv4_neighbors()
2365 self.pg3.config_ip4()
2366 self.pg3.resolve_arp()
2369 # The EP will be on a vlan sub-interface
2371 vlan_11 = VppDot1QSubint(self, self.pg0, 11)
2373 self.vapi.l2_interface_vlan_tag_rewrite(
2374 sw_if_index=vlan_11.sw_if_index, vtr_op=L2_VTR_OP.L2_POP_1,
2377 bd_uu_fwd = VppVxlanGbpTunnel(self, self.pg3.local_ip4,
2378 self.pg3.remote_ip4, 116)
2379 bd_uu_fwd.add_vpp_config()
2382 # a GBP bridge domain with a BVI and a UU-flood interface
2383 # The BD is marked as do not learn, so no endpoints are ever
2384 # learnt in this BD.
2386 bd1 = VppBridgeDomain(self, 1)
2387 bd1.add_vpp_config()
2388 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0, bd_uu_fwd,
2390 gbd1.add_vpp_config()
2392 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2393 self.logger.info(self.vapi.cli("sh gbp bridge"))
2395 # ... and has a /32 applied
2396 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2397 ip_addr.add_vpp_config()
2400 # The Endpoint-group in which we are learning endpoints
2402 epg_220 = VppGbpEndpointGroup(self, 220, 441, rd1, gbd1,
2406 VppGbpEndpointRetention(2))
2407 epg_220.add_vpp_config()
2410 # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
2413 vx_tun_l2_1 = VppGbpVxlanTunnel(
2414 self, 99, bd1.bd_id,
2415 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L2,
2417 vx_tun_l2_1.add_vpp_config()
2420 # A static endpoint that the learnt endpoints are trying to
2423 ep = VppGbpEndpoint(self, vlan_11,
2425 "10.0.0.127", "11.0.0.127",
2426 "2001:10::1", "3001::1")
2429 self.assertTrue(find_route(self, ep.ip4.address, 32, table_id=1))
2432 # Send to the static EP
2434 for ii, l in enumerate(learnt):
2435 # a packet with an sclass from a known EPG
2436 # arriving on an unknown TEP
2437 p = (Ether(src=self.pg2.remote_mac,
2438 dst=self.pg2.local_mac) /
2439 IP(src=self.pg2.remote_hosts[1].ip4,
2440 dst=self.pg2.local_ip4) /
2441 UDP(sport=1234, dport=48879) /
2442 VXLAN(vni=99, gpid=441, flags=0x88) /
2443 Ether(src=l['mac'], dst=ep.mac) /
2444 IP(src=l['ip'], dst=ep.ip4.address) /
2445 UDP(sport=1234, dport=1234) /
2448 rxs = self.send_and_expect(self.pg2, [p], self.pg0)
2451 # packet to EP has the EP's vlan tag
2454 self.assertEqual(rx[Dot1Q].vlan, 11)
2457 # the EP is not learnt since the BD setting prevents it
2460 self.assertFalse(find_gbp_endpoint(self,
2461 vx_tun_l2_1.sw_if_index,
2463 self.assertEqual(INDEX_INVALID,
2464 find_vxlan_gbp_tunnel(
2467 self.pg2.remote_hosts[1].ip4,
2470 self.assertEqual(len(self.vapi.gbp_endpoint_dump()), 1)
2474 # we didn't learn the remotes so they are sent to the UU-fwd
2477 p = (Ether(src=ep.mac, dst=l['mac']) /
2479 IP(dst=l['ip'], src=ep.ip4.address) /
2480 UDP(sport=1234, dport=1234) /
2483 rxs = self.send_and_expect(self.pg0, p * 17, self.pg3)
2486 self.assertEqual(rx[IP].src, self.pg3.local_ip4)
2487 self.assertEqual(rx[IP].dst, self.pg3.remote_ip4)
2488 self.assertEqual(rx[UDP].dport, 48879)
2489 # the UDP source port is a random value for hashing
2490 self.assertEqual(rx[VXLAN].gpid, 441)
2491 self.assertEqual(rx[VXLAN].vni, 116)
2492 self.assertTrue(rx[VXLAN].flags.G)
2493 self.assertTrue(rx[VXLAN].flags.Instance)
2494 self.assertFalse(rx[VXLAN].gpflags.A)
2495 self.assertFalse(rx[VXLAN].gpflags.D)
2497 self.pg2.unconfig_ip4()
2498 self.pg3.unconfig_ip4()
2500 def test_gbp_learn_l3(self):
2501 """ GBP L3 Endpoint Learning """
2503 self.vapi.cli("set logging class gbp level debug")
2505 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
2506 routed_dst_mac = "00:0c:0c:0c:0c:0c"
2507 routed_src_mac = "00:22:bd:f8:19:ff"
2509 learnt = [{'mac': '00:00:11:11:11:02',
2511 'ip6': '2001:10::2'},
2512 {'mac': '00:00:11:11:11:03',
2514 'ip6': '2001:10::3'}]
2519 t4 = VppIpTable(self, 1)
2521 t6 = VppIpTable(self, 1, True)
2524 tun_ip4_uu = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
2525 self.pg4.remote_ip4, 114)
2526 tun_ip6_uu = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
2527 self.pg4.remote_ip4, 116)
2528 tun_ip4_uu.add_vpp_config()
2529 tun_ip6_uu.add_vpp_config()
2531 rd1 = VppGbpRouteDomain(self, 2, 401, t4, t6, tun_ip4_uu, tun_ip6_uu)
2532 rd1.add_vpp_config()
2534 self.loop0.set_mac(self.router_mac)
2537 # Bind the BVI to the RD
2539 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
2540 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
2543 # Pg2 hosts the vxlan tunnel
2544 # hosts on pg2 to act as TEPs
2548 self.pg2.config_ip4()
2549 self.pg2.resolve_arp()
2550 self.pg2.generate_remote_hosts(4)
2551 self.pg2.configure_ipv4_neighbors()
2552 self.pg3.config_ip4()
2553 self.pg3.resolve_arp()
2554 self.pg4.config_ip4()
2555 self.pg4.resolve_arp()
2558 # a GBP bridge domain with a BVI and a UU-flood interface
2560 bd1 = VppBridgeDomain(self, 1)
2561 bd1.add_vpp_config()
2562 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0, self.pg3)
2563 gbd1.add_vpp_config()
2565 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2566 self.logger.info(self.vapi.cli("sh gbp bridge"))
2567 self.logger.info(self.vapi.cli("sh gbp route"))
2569 # ... and has a /32 and /128 applied
2570 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2571 ip4_addr.add_vpp_config()
2572 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 128)
2573 ip6_addr.add_vpp_config()
2576 # The Endpoint-group in which we are learning endpoints
2578 epg_220 = VppGbpEndpointGroup(self, 220, 441, rd1, gbd1,
2582 VppGbpEndpointRetention(2))
2583 epg_220.add_vpp_config()
2586 # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
2589 vx_tun_l3 = VppGbpVxlanTunnel(
2590 self, 101, rd1.rd_id,
2591 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
2593 vx_tun_l3.add_vpp_config()
2596 # A static endpoint that the learnt endpoints are trying to
2599 ep = VppGbpEndpoint(self, self.pg0,
2601 "10.0.0.127", "11.0.0.127",
2602 "2001:10::1", "3001::1")
2606 # learn some remote IPv4 EPs
2608 for ii, l in enumerate(learnt):
2609 # a packet with an sclass from a known EPG
2610 # arriving on an unknown TEP
2611 p = (Ether(src=self.pg2.remote_mac,
2612 dst=self.pg2.local_mac) /
2613 IP(src=self.pg2.remote_hosts[1].ip4,
2614 dst=self.pg2.local_ip4) /
2615 UDP(sport=1234, dport=48879) /
2616 VXLAN(vni=101, gpid=441, flags=0x88) /
2617 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2618 IP(src=l['ip'], dst=ep.ip4.address) /
2619 UDP(sport=1234, dport=1234) /
2622 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2625 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2628 self.pg2.remote_hosts[1].ip4,
2630 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2632 # endpoint learnt via the parent GBP-vxlan interface
2633 self.assertTrue(find_gbp_endpoint(self,
2634 vx_tun_l3._sw_if_index,
2638 # Static IPv4 EP replies to learnt
2641 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2642 IP(dst=l['ip'], src=ep.ip4.address) /
2643 UDP(sport=1234, dport=1234) /
2646 rxs = self.send_and_expect(self.pg0, p * 1, self.pg2)
2649 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2650 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2651 self.assertEqual(rx[UDP].dport, 48879)
2652 # the UDP source port is a random value for hashing
2653 self.assertEqual(rx[VXLAN].gpid, 441)
2654 self.assertEqual(rx[VXLAN].vni, 101)
2655 self.assertTrue(rx[VXLAN].flags.G)
2656 self.assertTrue(rx[VXLAN].flags.Instance)
2657 self.assertTrue(rx[VXLAN].gpflags.A)
2658 self.assertFalse(rx[VXLAN].gpflags.D)
2660 inner = rx[VXLAN].payload
2662 self.assertEqual(inner[Ether].src, routed_src_mac)
2663 self.assertEqual(inner[Ether].dst, routed_dst_mac)
2664 self.assertEqual(inner[IP].src, ep.ip4.address)
2665 self.assertEqual(inner[IP].dst, l['ip'])
2668 self.assertFalse(find_gbp_endpoint(self,
2673 # learn some remote IPv6 EPs
2675 for ii, l in enumerate(learnt):
2676 # a packet with an sclass from a known EPG
2677 # arriving on an unknown TEP
2678 p = (Ether(src=self.pg2.remote_mac,
2679 dst=self.pg2.local_mac) /
2680 IP(src=self.pg2.remote_hosts[1].ip4,
2681 dst=self.pg2.local_ip4) /
2682 UDP(sport=1234, dport=48879) /
2683 VXLAN(vni=101, gpid=441, flags=0x88) /
2684 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2685 IPv6(src=l['ip6'], dst=ep.ip6.address) /
2686 UDP(sport=1234, dport=1234) /
2689 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2692 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2695 self.pg2.remote_hosts[1].ip4,
2697 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2699 self.logger.info(self.vapi.cli("show gbp bridge"))
2700 self.logger.info(self.vapi.cli("show vxlan-gbp tunnel"))
2701 self.logger.info(self.vapi.cli("show gbp vxlan"))
2702 self.logger.info(self.vapi.cli("show int addr"))
2704 # endpoint learnt via the TEP
2705 self.assertTrue(find_gbp_endpoint(self, ip=l['ip6']))
2707 self.logger.info(self.vapi.cli("show gbp endpoint"))
2708 self.logger.info(self.vapi.cli("show ip fib index 1 %s" % l['ip']))
2711 # Static EP replies to learnt
2714 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2715 IPv6(dst=l['ip6'], src=ep.ip6.address) /
2716 UDP(sport=1234, dport=1234) /
2719 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
2722 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2723 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2724 self.assertEqual(rx[UDP].dport, 48879)
2725 # the UDP source port is a random value for hashing
2726 self.assertEqual(rx[VXLAN].gpid, 441)
2727 self.assertEqual(rx[VXLAN].vni, 101)
2728 self.assertTrue(rx[VXLAN].flags.G)
2729 self.assertTrue(rx[VXLAN].flags.Instance)
2730 self.assertTrue(rx[VXLAN].gpflags.A)
2731 self.assertFalse(rx[VXLAN].gpflags.D)
2733 inner = rx[VXLAN].payload
2735 self.assertEqual(inner[Ether].src, routed_src_mac)
2736 self.assertEqual(inner[Ether].dst, routed_dst_mac)
2737 self.assertEqual(inner[IPv6].src, ep.ip6.address)
2738 self.assertEqual(inner[IPv6].dst, l['ip6'])
2740 self.logger.info(self.vapi.cli("sh gbp endpoint"))
2742 self.wait_for_ep_timeout(ip=l['ip'])
2745 # Static sends to unknown EP with no route
2747 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2748 IP(dst="10.0.0.99", src=ep.ip4.address) /
2749 UDP(sport=1234, dport=1234) /
2752 self.send_and_assert_no_replies(self.pg0, [p])
2755 # Add a route to static EP's v4 and v6 subnet
2756 # packets should be sent on the v4/v6 uu=fwd interface resp.
2758 se_10_24 = VppGbpSubnet(
2759 self, rd1, "10.0.0.0", 24,
2760 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT)
2761 se_10_24.add_vpp_config()
2763 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2764 IP(dst="10.0.0.99", src=ep.ip4.address) /
2765 UDP(sport=1234, dport=1234) /
2768 rxs = self.send_and_expect(self.pg0, [p], self.pg4)
2770 self.assertEqual(rx[IP].src, self.pg4.local_ip4)
2771 self.assertEqual(rx[IP].dst, self.pg4.remote_ip4)
2772 self.assertEqual(rx[UDP].dport, 48879)
2773 # the UDP source port is a random value for hashing
2774 self.assertEqual(rx[VXLAN].gpid, 441)
2775 self.assertEqual(rx[VXLAN].vni, 114)
2776 self.assertTrue(rx[VXLAN].flags.G)
2777 self.assertTrue(rx[VXLAN].flags.Instance)
2778 # policy is not applied to packets sent to the uu-fwd interfaces
2779 self.assertFalse(rx[VXLAN].gpflags.A)
2780 self.assertFalse(rx[VXLAN].gpflags.D)
2783 # learn some remote IPv4 EPs
2785 for ii, l in enumerate(learnt):
2786 # a packet with an sclass from a known EPG
2787 # arriving on an unknown TEP
2788 p = (Ether(src=self.pg2.remote_mac,
2789 dst=self.pg2.local_mac) /
2790 IP(src=self.pg2.remote_hosts[2].ip4,
2791 dst=self.pg2.local_ip4) /
2792 UDP(sport=1234, dport=48879) /
2793 VXLAN(vni=101, gpid=441, flags=0x88) /
2794 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2795 IP(src=l['ip'], dst=ep.ip4.address) /
2796 UDP(sport=1234, dport=1234) /
2799 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2802 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2805 self.pg2.remote_hosts[2].ip4,
2807 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2809 # endpoint learnt via the parent GBP-vxlan interface
2810 self.assertTrue(find_gbp_endpoint(self,
2811 vx_tun_l3._sw_if_index,
2815 # Add a remote endpoint from the API
2817 rep_88 = VppGbpEndpoint(self, vx_tun_l3,
2819 "10.0.0.88", "11.0.0.88",
2820 "2001:10::88", "3001::88",
2821 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
2823 self.pg2.remote_hosts[2].ip4,
2825 rep_88.add_vpp_config()
2828 # Add a remote endpoint from the API that matches an existing one
2829 # this is a lower priority, hence the packet is sent to the DP leanrt
2832 rep_2 = VppGbpEndpoint(self, vx_tun_l3,
2834 learnt[0]['ip'], "11.0.0.101",
2835 learnt[0]['ip6'], "3001::101",
2836 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
2838 self.pg2.remote_hosts[1].ip4,
2840 rep_2.add_vpp_config()
2843 # Add a route to the learned EP's v4 subnet
2844 # packets should be send on the v4/v6 uu=fwd interface resp.
2846 se_10_1_24 = VppGbpSubnet(
2847 self, rd1, "10.0.1.0", 24,
2848 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT)
2849 se_10_1_24.add_vpp_config()
2851 self.logger.info(self.vapi.cli("show gbp endpoint"))
2853 ips = ["10.0.0.88", learnt[0]['ip']]
2855 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2856 IP(dst=ip, src=ep.ip4.address) /
2857 UDP(sport=1234, dport=1234) /
2860 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
2863 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2864 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[2].ip4)
2865 self.assertEqual(rx[UDP].dport, 48879)
2866 # the UDP source port is a random value for hashing
2867 self.assertEqual(rx[VXLAN].gpid, 441)
2868 self.assertEqual(rx[VXLAN].vni, 101)
2869 self.assertTrue(rx[VXLAN].flags.G)
2870 self.assertTrue(rx[VXLAN].flags.Instance)
2871 self.assertTrue(rx[VXLAN].gpflags.A)
2872 self.assertFalse(rx[VXLAN].gpflags.D)
2874 inner = rx[VXLAN].payload
2876 self.assertEqual(inner[Ether].src, routed_src_mac)
2877 self.assertEqual(inner[Ether].dst, routed_dst_mac)
2878 self.assertEqual(inner[IP].src, ep.ip4.address)
2879 self.assertEqual(inner[IP].dst, ip)
2882 # remove the API remote EPs, only API sourced is gone, the DP
2883 # learnt one remains
2885 rep_88.remove_vpp_config()
2886 rep_2.remove_vpp_config()
2888 self.assertTrue(find_gbp_endpoint(self, ip=rep_2.ip4.address))
2890 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2891 IP(src=ep.ip4.address, dst=rep_2.ip4.address) /
2892 UDP(sport=1234, dport=1234) /
2894 rxs = self.send_and_expect(self.pg0, [p], self.pg2)
2896 self.assertFalse(find_gbp_endpoint(self, ip=rep_88.ip4.address))
2898 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2899 IP(src=ep.ip4.address, dst=rep_88.ip4.address) /
2900 UDP(sport=1234, dport=1234) /
2902 rxs = self.send_and_expect(self.pg0, [p], self.pg4)
2905 # to appease the testcase we cannot have the registered EP still
2906 # present (because it's DP learnt) when the TC ends so wait until
2909 self.wait_for_ep_timeout(ip=rep_88.ip4.address)
2910 self.wait_for_ep_timeout(ip=rep_2.ip4.address)
2913 # Same as above, learn a remote EP via CP and DP
2914 # this time remove the DP one first. expect the CP data to remain
2916 rep_3 = VppGbpEndpoint(self, vx_tun_l3,
2918 "10.0.1.4", "11.0.0.103",
2919 "2001::10:3", "3001::103",
2920 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
2922 self.pg2.remote_hosts[1].ip4,
2924 rep_3.add_vpp_config()
2926 p = (Ether(src=self.pg2.remote_mac,
2927 dst=self.pg2.local_mac) /
2928 IP(src=self.pg2.remote_hosts[2].ip4,
2929 dst=self.pg2.local_ip4) /
2930 UDP(sport=1234, dport=48879) /
2931 VXLAN(vni=101, gpid=441, flags=0x88) /
2932 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2933 IP(src="10.0.1.4", dst=ep.ip4.address) /
2934 UDP(sport=1234, dport=1234) /
2936 rxs = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
2938 self.assertTrue(find_gbp_endpoint(self,
2939 vx_tun_l3._sw_if_index,
2940 ip=rep_3.ip4.address,
2941 tep=[self.pg2.local_ip4,
2942 self.pg2.remote_hosts[2].ip4]))
2944 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2945 IP(dst="10.0.1.4", src=ep.ip4.address) /
2946 UDP(sport=1234, dport=1234) /
2948 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
2950 # host 2 is the DP learned TEP
2952 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2953 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[2].ip4)
2955 self.wait_for_ep_timeout(ip=rep_3.ip4.address,
2956 tep=[self.pg2.local_ip4,
2957 self.pg2.remote_hosts[2].ip4])
2959 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
2961 # host 1 is the CP learned TEP
2963 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2964 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2967 # shutdown with learnt endpoint present
2969 p = (Ether(src=self.pg2.remote_mac,
2970 dst=self.pg2.local_mac) /
2971 IP(src=self.pg2.remote_hosts[1].ip4,
2972 dst=self.pg2.local_ip4) /
2973 UDP(sport=1234, dport=48879) /
2974 VXLAN(vni=101, gpid=441, flags=0x88) /
2975 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2976 IP(src=learnt[1]['ip'], dst=ep.ip4.address) /
2977 UDP(sport=1234, dport=1234) /
2980 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2982 # endpoint learnt via the parent GBP-vxlan interface
2983 self.assertTrue(find_gbp_endpoint(self,
2984 vx_tun_l3._sw_if_index,
2989 # remote endpoint becomes local
2991 self.pg2.unconfig_ip4()
2992 self.pg3.unconfig_ip4()
2993 self.pg4.unconfig_ip4()
2995 def test_gbp_redirect(self):
2996 """ GBP Endpoint Redirect """
2998 self.vapi.cli("set logging class gbp level debug")
3000 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
3001 routed_dst_mac = "00:0c:0c:0c:0c:0c"
3002 routed_src_mac = "00:22:bd:f8:19:ff"
3004 learnt = [{'mac': '00:00:11:11:11:02',
3006 'ip6': '2001:10::2'},
3007 {'mac': '00:00:11:11:11:03',
3009 'ip6': '2001:10::3'}]
3014 t4 = VppIpTable(self, 1)
3016 t6 = VppIpTable(self, 1, True)
3019 rd1 = VppGbpRouteDomain(self, 2, 402, t4, t6)
3020 rd1.add_vpp_config()
3022 self.loop0.set_mac(self.router_mac)
3025 # Bind the BVI to the RD
3027 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
3028 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
3031 # Pg7 hosts a BD's UU-fwd
3033 self.pg7.config_ip4()
3034 self.pg7.resolve_arp()
3037 # a GBP bridge domains for the EPs
3039 bd1 = VppBridgeDomain(self, 1)
3040 bd1.add_vpp_config()
3041 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0)
3042 gbd1.add_vpp_config()
3044 bd2 = VppBridgeDomain(self, 2)
3045 bd2.add_vpp_config()
3046 gbd2 = VppGbpBridgeDomain(self, bd2, rd1, self.loop1)
3047 gbd2.add_vpp_config()
3049 # ... and has a /32 and /128 applied
3050 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
3051 ip4_addr.add_vpp_config()
3052 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 128)
3053 ip6_addr.add_vpp_config()
3054 ip4_addr = VppIpInterfaceAddress(self, gbd2.bvi, "10.0.1.128", 32)
3055 ip4_addr.add_vpp_config()
3056 ip6_addr = VppIpInterfaceAddress(self, gbd2.bvi, "2001:11::128", 128)
3057 ip6_addr.add_vpp_config()
3060 # The Endpoint-groups in which we are learning endpoints
3062 epg_220 = VppGbpEndpointGroup(self, 220, 440, rd1, gbd1,
3066 VppGbpEndpointRetention(2))
3067 epg_220.add_vpp_config()
3068 epg_221 = VppGbpEndpointGroup(self, 221, 441, rd1, gbd2,
3072 VppGbpEndpointRetention(2))
3073 epg_221.add_vpp_config()
3074 epg_222 = VppGbpEndpointGroup(self, 222, 442, rd1, gbd1,
3078 VppGbpEndpointRetention(2))
3079 epg_222.add_vpp_config()
3082 # a GBP bridge domains for the SEPs
3084 bd_uu1 = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
3085 self.pg7.remote_ip4, 116)
3086 bd_uu1.add_vpp_config()
3087 bd_uu2 = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
3088 self.pg7.remote_ip4, 117)
3089 bd_uu2.add_vpp_config()
3091 bd3 = VppBridgeDomain(self, 3)
3092 bd3.add_vpp_config()
3093 gbd3 = VppGbpBridgeDomain(self, bd3, rd1, self.loop2,
3094 bd_uu1, learn=False)
3095 gbd3.add_vpp_config()
3096 bd4 = VppBridgeDomain(self, 4)
3097 bd4.add_vpp_config()
3098 gbd4 = VppGbpBridgeDomain(self, bd4, rd1, self.loop3,
3099 bd_uu2, learn=False)
3100 gbd4.add_vpp_config()
3103 # EPGs in which the service endpoints exist
3105 epg_320 = VppGbpEndpointGroup(self, 320, 550, rd1, gbd3,
3109 VppGbpEndpointRetention(2))
3110 epg_320.add_vpp_config()
3111 epg_321 = VppGbpEndpointGroup(self, 321, 551, rd1, gbd4,
3115 VppGbpEndpointRetention(2))
3116 epg_321.add_vpp_config()
3119 # three local endpoints
3121 ep1 = VppGbpEndpoint(self, self.pg0,
3123 "10.0.0.1", "11.0.0.1",
3124 "2001:10::1", "3001:10::1")
3125 ep1.add_vpp_config()
3126 ep2 = VppGbpEndpoint(self, self.pg1,
3128 "10.0.1.1", "11.0.1.1",
3129 "2001:11::1", "3001:11::1")
3130 ep2.add_vpp_config()
3131 ep3 = VppGbpEndpoint(self, self.pg2,
3133 "10.0.2.2", "11.0.2.2",
3134 "2001:12::1", "3001:12::1")
3135 ep3.add_vpp_config()
3140 sep1 = VppGbpEndpoint(self, self.pg3,
3142 "12.0.0.1", "13.0.0.1",
3143 "4001:10::1", "5001:10::1")
3144 sep1.add_vpp_config()
3145 sep2 = VppGbpEndpoint(self, self.pg4,
3147 "12.0.0.2", "13.0.0.2",
3148 "4001:10::2", "5001:10::2")
3149 sep2.add_vpp_config()
3150 sep3 = VppGbpEndpoint(self, self.pg5,
3152 "12.0.1.1", "13.0.1.1",
3153 "4001:11::1", "5001:11::1")
3154 sep3.add_vpp_config()
3155 # this EP is not installed immediately
3156 sep4 = VppGbpEndpoint(self, self.pg6,
3158 "12.0.1.2", "13.0.1.2",
3159 "4001:11::2", "5001:11::2")
3162 # an L2 switch packet between local EPs in different EPGs
3163 # different dest ports on each so the are LB hashed differently
3165 p4 = [(Ether(src=ep1.mac, dst=ep3.mac) /
3166 IP(src=ep1.ip4.address, dst=ep3.ip4.address) /
3167 UDP(sport=1234, dport=1234) /
3169 (Ether(src=ep3.mac, dst=ep1.mac) /
3170 IP(src=ep3.ip4.address, dst=ep1.ip4.address) /
3171 UDP(sport=1234, dport=1234) /
3173 p6 = [(Ether(src=ep1.mac, dst=ep3.mac) /
3174 IPv6(src=ep1.ip6.address, dst=ep3.ip6.address) /
3175 UDP(sport=1234, dport=1234) /
3177 (Ether(src=ep3.mac, dst=ep1.mac) /
3178 IPv6(src=ep3.ip6.address, dst=ep1.ip6.address) /
3179 UDP(sport=1234, dport=1230) /
3182 # should be dropped since no contract yet
3183 self.send_and_assert_no_replies(self.pg0, [p4[0]])
3184 self.send_and_assert_no_replies(self.pg0, [p6[0]])
3187 # Add a contract with a rule to load-balance redirect via SEP1 and SEP2
3188 # one of the next-hops is via an EP that is not known
3190 acl = VppGbpAcl(self)
3191 rule4 = acl.create_rule(permit_deny=1, proto=17)
3192 rule6 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
3193 acl_index = acl.add_vpp_config([rule4, rule6])
3196 # test the src-ip hash mode
3198 c1 = VppGbpContract(
3199 self, 402, epg_220.sclass, epg_222.sclass, acl_index,
3200 [VppGbpContractRule(
3201 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3202 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3203 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3204 sep1.ip4, sep1.epg.rd),
3205 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3206 sep2.ip4, sep2.epg.rd)]),
3208 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3209 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3210 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3211 sep3.ip6, sep3.epg.rd),
3212 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3213 sep4.ip6, sep4.epg.rd)])],
3214 [ETH_P_IP, ETH_P_IPV6])
3217 c2 = VppGbpContract(
3218 self, 402, epg_222.sclass, epg_220.sclass, acl_index,
3219 [VppGbpContractRule(
3220 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3221 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3222 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3223 sep1.ip4, sep1.epg.rd),
3224 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3225 sep2.ip4, sep2.epg.rd)]),
3227 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3228 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3229 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3230 sep3.ip6, sep3.epg.rd),
3231 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3232 sep4.ip6, sep4.epg.rd)])],
3233 [ETH_P_IP, ETH_P_IPV6])
3237 # send again with the contract preset, now packets arrive
3238 # at SEP1 or SEP2 depending on the hashing
3240 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3243 self.assertEqual(rx[Ether].src, routed_src_mac)
3244 self.assertEqual(rx[Ether].dst, sep1.mac)
3245 self.assertEqual(rx[IP].src, ep1.ip4.address)
3246 self.assertEqual(rx[IP].dst, ep3.ip4.address)
3248 rxs = self.send_and_expect(self.pg2, p4[1] * 17, sep2.itf)
3251 self.assertEqual(rx[Ether].src, routed_src_mac)
3252 self.assertEqual(rx[Ether].dst, sep2.mac)
3253 self.assertEqual(rx[IP].src, ep3.ip4.address)
3254 self.assertEqual(rx[IP].dst, ep1.ip4.address)
3256 rxs = self.send_and_expect(self.pg0, p6[0] * 17, self.pg7)
3259 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3260 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3261 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3262 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
3263 self.assertEqual(rx[VXLAN].vni, 117)
3264 self.assertTrue(rx[VXLAN].flags.G)
3265 self.assertTrue(rx[VXLAN].flags.Instance)
3266 # redirect policy has been applied
3267 self.assertTrue(rx[VXLAN].gpflags.A)
3268 self.assertFalse(rx[VXLAN].gpflags.D)
3270 inner = rx[VXLAN].payload
3272 self.assertEqual(inner[Ether].src, routed_src_mac)
3273 self.assertEqual(inner[Ether].dst, sep4.mac)
3274 self.assertEqual(inner[IPv6].src, ep1.ip6.address)
3275 self.assertEqual(inner[IPv6].dst, ep3.ip6.address)
3277 rxs = self.send_and_expect(self.pg2, p6[1] * 17, sep3.itf)
3280 self.assertEqual(rx[Ether].src, routed_src_mac)
3281 self.assertEqual(rx[Ether].dst, sep3.mac)
3282 self.assertEqual(rx[IPv6].src, ep3.ip6.address)
3283 self.assertEqual(rx[IPv6].dst, ep1.ip6.address)
3286 # programme the unknown EP
3288 sep4.add_vpp_config()
3290 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep4.itf)
3293 self.assertEqual(rx[Ether].src, routed_src_mac)
3294 self.assertEqual(rx[Ether].dst, sep4.mac)
3295 self.assertEqual(rx[IPv6].src, ep1.ip6.address)
3296 self.assertEqual(rx[IPv6].dst, ep3.ip6.address)
3299 # and revert back to unprogrammed
3301 sep4.remove_vpp_config()
3303 rxs = self.send_and_expect(self.pg0, p6[0] * 17, self.pg7)
3306 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3307 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3308 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3309 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
3310 self.assertEqual(rx[VXLAN].vni, 117)
3311 self.assertTrue(rx[VXLAN].flags.G)
3312 self.assertTrue(rx[VXLAN].flags.Instance)
3313 # redirect policy has been applied
3314 self.assertTrue(rx[VXLAN].gpflags.A)
3315 self.assertFalse(rx[VXLAN].gpflags.D)
3317 inner = rx[VXLAN].payload
3319 self.assertEqual(inner[Ether].src, routed_src_mac)
3320 self.assertEqual(inner[Ether].dst, sep4.mac)
3321 self.assertEqual(inner[IPv6].src, ep1.ip6.address)
3322 self.assertEqual(inner[IPv6].dst, ep3.ip6.address)
3324 c1.remove_vpp_config()
3325 c2.remove_vpp_config()
3328 # test the symmetric hash mode
3330 c1 = VppGbpContract(
3331 self, 402, epg_220.sclass, epg_222.sclass, acl_index,
3332 [VppGbpContractRule(
3333 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3334 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3335 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3336 sep1.ip4, sep1.epg.rd),
3337 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3338 sep2.ip4, sep2.epg.rd)]),
3340 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3341 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3342 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3343 sep3.ip6, sep3.epg.rd),
3344 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3345 sep4.ip6, sep4.epg.rd)])],
3346 [ETH_P_IP, ETH_P_IPV6])
3349 c2 = VppGbpContract(
3350 self, 402, epg_222.sclass, epg_220.sclass, acl_index,
3351 [VppGbpContractRule(
3352 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3353 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3354 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3355 sep1.ip4, sep1.epg.rd),
3356 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3357 sep2.ip4, sep2.epg.rd)]),
3359 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3360 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3361 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3362 sep3.ip6, sep3.epg.rd),
3363 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3364 sep4.ip6, sep4.epg.rd)])],
3365 [ETH_P_IP, ETH_P_IPV6])
3369 # send again with the contract preset, now packets arrive
3370 # at SEP1 for both directions
3372 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3375 self.assertEqual(rx[Ether].src, routed_src_mac)
3376 self.assertEqual(rx[Ether].dst, sep1.mac)
3377 self.assertEqual(rx[IP].src, ep1.ip4.address)
3378 self.assertEqual(rx[IP].dst, ep3.ip4.address)
3380 rxs = self.send_and_expect(self.pg2, p4[1] * 17, sep1.itf)
3383 self.assertEqual(rx[Ether].src, routed_src_mac)
3384 self.assertEqual(rx[Ether].dst, sep1.mac)
3385 self.assertEqual(rx[IP].src, ep3.ip4.address)
3386 self.assertEqual(rx[IP].dst, ep1.ip4.address)
3389 # programme the unknown EP for the L3 tests
3391 sep4.add_vpp_config()
3394 # an L3 switch packet between local EPs in different EPGs
3395 # different dest ports on each so the are LB hashed differently
3397 p4 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3398 IP(src=ep1.ip4.address, dst=ep2.ip4.address) /
3399 UDP(sport=1234, dport=1234) /
3401 (Ether(src=ep2.mac, dst=str(self.router_mac)) /
3402 IP(src=ep2.ip4.address, dst=ep1.ip4.address) /
3403 UDP(sport=1234, dport=1234) /
3405 p6 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3406 IPv6(src=ep1.ip6.address, dst=ep2.ip6.address) /
3407 UDP(sport=1234, dport=1234) /
3409 (Ether(src=ep2.mac, dst=str(self.router_mac)) /
3410 IPv6(src=ep2.ip6.address, dst=ep1.ip6.address) /
3411 UDP(sport=1234, dport=1234) /
3414 c3 = VppGbpContract(
3415 self, 402, epg_220.sclass, epg_221.sclass, acl_index,
3416 [VppGbpContractRule(
3417 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3418 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3419 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3420 sep1.ip4, sep1.epg.rd),
3421 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3422 sep2.ip4, sep2.epg.rd)]),
3424 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3425 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3426 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3427 sep3.ip6, sep3.epg.rd),
3428 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3429 sep4.ip6, sep4.epg.rd)])],
3430 [ETH_P_IP, ETH_P_IPV6])
3433 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3436 self.assertEqual(rx[Ether].src, routed_src_mac)
3437 self.assertEqual(rx[Ether].dst, sep1.mac)
3438 self.assertEqual(rx[IP].src, ep1.ip4.address)
3439 self.assertEqual(rx[IP].dst, ep2.ip4.address)
3442 # learn a remote EP in EPG 221
3444 vx_tun_l3 = VppGbpVxlanTunnel(
3445 self, 444, rd1.rd_id,
3446 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
3448 vx_tun_l3.add_vpp_config()
3450 c4 = VppGbpContract(
3451 self, 402, epg_221.sclass, epg_220.sclass, acl_index,
3452 [VppGbpContractRule(
3453 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3454 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3457 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3458 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3460 [ETH_P_IP, ETH_P_IPV6])
3463 p = (Ether(src=self.pg7.remote_mac,
3464 dst=self.pg7.local_mac) /
3465 IP(src=self.pg7.remote_ip4,
3466 dst=self.pg7.local_ip4) /
3467 UDP(sport=1234, dport=48879) /
3468 VXLAN(vni=444, gpid=441, flags=0x88) /
3469 Ether(src="00:22:22:22:22:33", dst=str(self.router_mac)) /
3470 IP(src="10.0.0.88", dst=ep1.ip4.address) /
3471 UDP(sport=1234, dport=1234) /
3474 rx = self.send_and_expect(self.pg7, [p], self.pg0)
3476 # endpoint learnt via the parent GBP-vxlan interface
3477 self.assertTrue(find_gbp_endpoint(self,
3478 vx_tun_l3._sw_if_index,
3481 p = (Ether(src=self.pg7.remote_mac,
3482 dst=self.pg7.local_mac) /
3483 IP(src=self.pg7.remote_ip4,
3484 dst=self.pg7.local_ip4) /
3485 UDP(sport=1234, dport=48879) /
3486 VXLAN(vni=444, gpid=441, flags=0x88) /
3487 Ether(src="00:22:22:22:22:33", dst=str(self.router_mac)) /
3488 IPv6(src="2001:10::88", dst=ep1.ip6.address) /
3489 UDP(sport=1234, dport=1234) /
3492 rx = self.send_and_expect(self.pg7, [p], self.pg0)
3494 # endpoint learnt via the parent GBP-vxlan interface
3495 self.assertTrue(find_gbp_endpoint(self,
3496 vx_tun_l3._sw_if_index,
3500 # L3 switch from local to remote EP
3502 p4 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3503 IP(src=ep1.ip4.address, dst="10.0.0.88") /
3504 UDP(sport=1234, dport=1234) /
3506 p6 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3507 IPv6(src=ep1.ip6.address, dst="2001:10::88") /
3508 UDP(sport=1234, dport=1234) /
3511 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3514 self.assertEqual(rx[Ether].src, routed_src_mac)
3515 self.assertEqual(rx[Ether].dst, sep1.mac)
3516 self.assertEqual(rx[IP].src, ep1.ip4.address)
3517 self.assertEqual(rx[IP].dst, "10.0.0.88")
3519 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep4.itf)
3522 self.assertEqual(rx[Ether].src, routed_src_mac)
3523 self.assertEqual(rx[Ether].dst, sep4.mac)
3524 self.assertEqual(rx[IPv6].src, ep1.ip6.address)
3525 self.assertEqual(rx[IPv6].dst, "2001:10::88")
3528 # test the dst-ip hash mode
3530 c5 = VppGbpContract(
3531 self, 402, epg_220.sclass, epg_221.sclass, acl_index,
3532 [VppGbpContractRule(
3533 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3534 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
3535 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3536 sep1.ip4, sep1.epg.rd),
3537 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3538 sep2.ip4, sep2.epg.rd)]),
3540 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3541 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
3542 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3543 sep3.ip6, sep3.epg.rd),
3544 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3545 sep4.ip6, sep4.epg.rd)])],
3546 [ETH_P_IP, ETH_P_IPV6])
3549 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3552 self.assertEqual(rx[Ether].src, routed_src_mac)
3553 self.assertEqual(rx[Ether].dst, sep1.mac)
3554 self.assertEqual(rx[IP].src, ep1.ip4.address)
3555 self.assertEqual(rx[IP].dst, "10.0.0.88")
3557 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep3.itf)
3560 self.assertEqual(rx[Ether].src, routed_src_mac)
3561 self.assertEqual(rx[Ether].dst, sep3.mac)
3562 self.assertEqual(rx[IPv6].src, ep1.ip6.address)
3563 self.assertEqual(rx[IPv6].dst, "2001:10::88")
3568 self.pg7.unconfig_ip4()
3570 def test_gbp_l3_out(self):
3573 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
3574 self.vapi.cli("set logging class gbp level debug")
3576 routed_dst_mac = "00:0c:0c:0c:0c:0c"
3577 routed_src_mac = "00:22:bd:f8:19:ff"
3582 t4 = VppIpTable(self, 1)
3584 t6 = VppIpTable(self, 1, True)
3587 rd1 = VppGbpRouteDomain(self, 2, 55, t4, t6)
3588 rd1.add_vpp_config()
3590 self.loop0.set_mac(self.router_mac)
3593 # Bind the BVI to the RD
3595 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
3596 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
3599 # Pg7 hosts a BD's BUM
3600 # Pg1 some other l3 interface
3602 self.pg7.config_ip4()
3603 self.pg7.resolve_arp()
3606 # a multicast vxlan-gbp tunnel for broadcast in the BD
3608 tun_bm = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
3611 tun_bm.add_vpp_config()
3614 # a GBP external bridge domains for the EPs
3616 bd1 = VppBridgeDomain(self, 1)
3617 bd1.add_vpp_config()
3618 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0, None, tun_bm)
3619 gbd1.add_vpp_config()
3622 # The Endpoint-groups in which the external endpoints exist
3624 epg_220 = VppGbpEndpointGroup(self, 220, 113, rd1, gbd1,
3628 VppGbpEndpointRetention(2))
3629 epg_220.add_vpp_config()
3631 # the BVIs have the subnets applied ...
3632 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 24)
3633 ip4_addr.add_vpp_config()
3634 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 64)
3635 ip6_addr.add_vpp_config()
3637 # ... which are L3-out subnets
3638 l3o_1 = VppGbpSubnet(
3639 self, rd1, "10.0.0.0", 24,
3640 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3642 l3o_1.add_vpp_config()
3645 # an external interface attached to the outside world and the
3648 VppL2Vtr(self, self.vlan_100, L2_VTR_OP.L2_POP_1).add_vpp_config()
3649 VppL2Vtr(self, self.vlan_101, L2_VTR_OP.L2_POP_1).add_vpp_config()
3650 # vlan_102 is not poped
3652 ext_itf = VppGbpExtItf(self, self.loop0, bd1, rd1)
3653 ext_itf.add_vpp_config()
3656 # an unicast vxlan-gbp for inter-RD traffic
3658 vx_tun_l3 = VppGbpVxlanTunnel(
3659 self, 444, rd1.rd_id,
3660 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
3662 vx_tun_l3.add_vpp_config()
3665 # External Endpoints
3667 eep1 = VppGbpEndpoint(self, self.vlan_100,
3669 "10.0.0.1", "11.0.0.1",
3670 "2001:10::1", "3001::1",
3671 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
3672 eep1.add_vpp_config()
3673 eep2 = VppGbpEndpoint(self, self.vlan_101,
3675 "10.0.0.2", "11.0.0.2",
3676 "2001:10::2", "3001::2",
3677 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
3678 eep2.add_vpp_config()
3679 eep3 = VppGbpEndpoint(self, self.vlan_102,
3681 "10.0.0.3", "11.0.0.3",
3682 "2001:10::3", "3001::3",
3683 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
3684 eep3.add_vpp_config()
3687 # A remote external endpoint
3689 rep = VppGbpEndpoint(self, vx_tun_l3,
3691 "10.0.0.101", "11.0.0.101",
3692 "2001:10::101", "3001::101",
3693 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
3695 self.pg7.remote_ip4,
3697 rep.add_vpp_config()
3700 # EP1 impersonating EP3 is dropped
3702 p = (Ether(src=eep1.mac, dst="ff:ff:ff:ff:ff:ff") /
3705 psrc="10.0.0.3", pdst="10.0.0.128",
3706 hwsrc=eep1.mac, hwdst="ff:ff:ff:ff:ff:ff"))
3707 self.send_and_assert_no_replies(self.pg0, p)
3710 # ARP packet from External EPs are accepted and replied to
3712 p_arp = (Ether(src=eep1.mac, dst="ff:ff:ff:ff:ff:ff") /
3715 psrc=eep1.ip4.address, pdst="10.0.0.128",
3716 hwsrc=eep1.mac, hwdst="ff:ff:ff:ff:ff:ff"))
3717 rxs = self.send_and_expect(self.pg0, p_arp * 1, self.pg0)
3720 # ARP packet from host in remote subnet are accepted and replied to
3722 p_arp = (Ether(src=eep3.mac, dst="ff:ff:ff:ff:ff:ff") /
3725 psrc=eep3.ip4.address, pdst="10.0.0.128",
3726 hwsrc=eep3.mac, hwdst="ff:ff:ff:ff:ff:ff"))
3727 rxs = self.send_and_expect(self.pg0, p_arp * 1, self.pg0)
3730 # packets destined to unknown addresses in the BVI's subnet
3733 p4 = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3735 IP(src="10.0.0.1", dst="10.0.0.88") /
3736 UDP(sport=1234, dport=1234) /
3738 p6 = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3740 IPv6(src="2001:10::1", dst="2001:10::88") /
3741 UDP(sport=1234, dport=1234) /
3744 rxs = self.send_and_expect(self.pg0, p4 * 1, self.pg7)
3747 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3748 # self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3749 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3750 self.assertEqual(rx[IP].dst, "239.1.1.1")
3751 self.assertEqual(rx[VXLAN].vni, 88)
3752 self.assertTrue(rx[VXLAN].flags.G)
3753 self.assertTrue(rx[VXLAN].flags.Instance)
3754 # policy was applied to the original IP packet
3755 self.assertEqual(rx[VXLAN].gpid, 113)
3756 self.assertTrue(rx[VXLAN].gpflags.A)
3757 self.assertFalse(rx[VXLAN].gpflags.D)
3759 inner = rx[VXLAN].payload
3761 self.assertTrue(inner.haslayer(ARP))
3764 # remote to external
3766 p = (Ether(src=self.pg7.remote_mac,
3767 dst=self.pg7.local_mac) /
3768 IP(src=self.pg7.remote_ip4,
3769 dst=self.pg7.local_ip4) /
3770 UDP(sport=1234, dport=48879) /
3771 VXLAN(vni=444, gpid=113, flags=0x88) /
3772 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
3773 IP(src="10.0.0.101", dst="10.0.0.1") /
3774 UDP(sport=1234, dport=1234) /
3777 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
3780 # local EP pings router
3782 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3784 IP(src=eep1.ip4.address, dst="10.0.0.128") /
3785 ICMP(type='echo-request'))
3787 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
3790 self.assertEqual(rx[Ether].src, str(self.router_mac))
3791 self.assertEqual(rx[Ether].dst, eep1.mac)
3792 self.assertEqual(rx[Dot1Q].vlan, 100)
3795 # local EP pings other local EP
3797 p = (Ether(src=eep1.mac, dst=eep2.mac) /
3799 IP(src=eep1.ip4.address, dst=eep2.ip4.address) /
3800 ICMP(type='echo-request'))
3802 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
3805 self.assertEqual(rx[Ether].src, eep1.mac)
3806 self.assertEqual(rx[Ether].dst, eep2.mac)
3807 self.assertEqual(rx[Dot1Q].vlan, 101)
3810 # local EP pings router w/o vlan tag poped
3812 p = (Ether(src=eep3.mac, dst=str(self.router_mac)) /
3814 IP(src=eep3.ip4.address, dst="10.0.0.128") /
3815 ICMP(type='echo-request'))
3817 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
3820 self.assertEqual(rx[Ether].src, str(self.router_mac))
3821 self.assertEqual(rx[Ether].dst, self.vlan_102.remote_mac)
3824 # A subnet reachable through the external EP1
3826 ip_220 = VppIpRoute(self, "10.220.0.0", 24,
3827 [VppRoutePath(eep1.ip4.address,
3828 eep1.epg.bvi.sw_if_index)],
3829 table_id=t4.table_id)
3830 ip_220.add_vpp_config()
3832 l3o_220 = VppGbpSubnet(
3833 self, rd1, "10.220.0.0", 24,
3834 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3836 l3o_220.add_vpp_config()
3839 # A subnet reachable through the external EP2
3841 ip_221 = VppIpRoute(self, "10.221.0.0", 24,
3842 [VppRoutePath(eep2.ip4.address,
3843 eep2.epg.bvi.sw_if_index)],
3844 table_id=t4.table_id)
3845 ip_221.add_vpp_config()
3847 l3o_221 = VppGbpSubnet(
3848 self, rd1, "10.221.0.0", 24,
3849 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3851 l3o_221.add_vpp_config()
3854 # ping between hosts in remote subnets
3855 # dropped without a contract
3857 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3859 IP(src="10.220.0.1", dst="10.221.0.1") /
3860 ICMP(type='echo-request'))
3862 self.send_and_assert_no_replies(self.pg0, p * 1)
3865 # contract for the external nets to communicate
3867 acl = VppGbpAcl(self)
3868 rule4 = acl.create_rule(permit_deny=1, proto=17)
3869 rule6 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
3870 acl_index = acl.add_vpp_config([rule4, rule6])
3873 # A contract with the wrong scope is not matched
3875 c_44 = VppGbpContract(
3876 self, 44, 4220, 4221, acl_index,
3877 [VppGbpContractRule(
3878 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3881 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3883 [ETH_P_IP, ETH_P_IPV6])
3884 c_44.add_vpp_config()
3885 self.send_and_assert_no_replies(self.pg0, p * 1)
3887 c1 = VppGbpContract(
3888 self, 55, 4220, 4221, acl_index,
3889 [VppGbpContractRule(
3890 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3891 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3894 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3895 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3897 [ETH_P_IP, ETH_P_IPV6])
3901 # Contracts allowing ext-net 200 to talk with external EPs
3903 c2 = VppGbpContract(
3904 self, 55, 4220, 113, acl_index,
3905 [VppGbpContractRule(
3906 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3907 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3910 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3911 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3913 [ETH_P_IP, ETH_P_IPV6])
3915 c3 = VppGbpContract(
3916 self, 55, 113, 4220, acl_index,
3917 [VppGbpContractRule(
3918 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3919 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3922 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3923 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3925 [ETH_P_IP, ETH_P_IPV6])
3929 # ping between hosts in remote subnets
3931 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3933 IP(src="10.220.0.1", dst="10.221.0.1") /
3934 UDP(sport=1234, dport=1234) /
3937 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
3940 self.assertEqual(rx[Ether].src, str(self.router_mac))
3941 self.assertEqual(rx[Ether].dst, eep2.mac)
3942 self.assertEqual(rx[Dot1Q].vlan, 101)
3944 # we did not learn these external hosts
3945 self.assertFalse(find_gbp_endpoint(self, ip="10.220.0.1"))
3946 self.assertFalse(find_gbp_endpoint(self, ip="10.221.0.1"))
3949 # from remote external EP to local external EP
3951 p = (Ether(src=self.pg7.remote_mac,
3952 dst=self.pg7.local_mac) /
3953 IP(src=self.pg7.remote_ip4,
3954 dst=self.pg7.local_ip4) /
3955 UDP(sport=1234, dport=48879) /
3956 VXLAN(vni=444, gpid=113, flags=0x88) /
3957 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
3958 IP(src="10.0.0.101", dst="10.220.0.1") /
3959 UDP(sport=1234, dport=1234) /
3962 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
3965 # ping from an external host to the remote external EP
3967 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3969 IP(src="10.220.0.1", dst=rep.ip4.address) /
3970 UDP(sport=1234, dport=1234) /
3973 rxs = self.send_and_expect(self.pg0, p * 1, self.pg7)
3976 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3977 # self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3978 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3979 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
3980 self.assertEqual(rx[VXLAN].vni, 444)
3981 self.assertTrue(rx[VXLAN].flags.G)
3982 self.assertTrue(rx[VXLAN].flags.Instance)
3983 # the sclass of the ext-net the packet came from
3984 self.assertEqual(rx[VXLAN].gpid, 4220)
3985 # policy was applied to the original IP packet
3986 self.assertTrue(rx[VXLAN].gpflags.A)
3987 # since it's an external host the reciever should not learn it
3988 self.assertTrue(rx[VXLAN].gpflags.D)
3989 inner = rx[VXLAN].payload
3990 self.assertEqual(inner[IP].src, "10.220.0.1")
3991 self.assertEqual(inner[IP].dst, rep.ip4.address)
3994 # An external subnet reachable via the remote external EP
3998 # first the VXLAN-GBP tunnel over which it is reached
4000 vx_tun_r = VppVxlanGbpTunnel(
4001 self, self.pg7.local_ip4,
4002 self.pg7.remote_ip4, 445,
4003 mode=(VppEnum.vl_api_vxlan_gbp_api_tunnel_mode_t.
4004 VXLAN_GBP_API_TUNNEL_MODE_L3))
4005 vx_tun_r.add_vpp_config()
4006 VppIpInterfaceBind(self, vx_tun_r, t4).add_vpp_config()
4008 self.logger.info(self.vapi.cli("sh vxlan-gbp tunnel"))
4011 # then the special adj to resolve through on that tunnel
4013 n1 = VppNeighbor(self,
4014 vx_tun_r.sw_if_index,
4015 "00:0c:0c:0c:0c:0c",
4016 self.pg7.remote_ip4)
4020 # the route via the adj above
4022 ip_222 = VppIpRoute(self, "10.222.0.0", 24,
4023 [VppRoutePath(self.pg7.remote_ip4,
4024 vx_tun_r.sw_if_index)],
4025 table_id=t4.table_id)
4026 ip_222.add_vpp_config()
4028 l3o_222 = VppGbpSubnet(
4029 self, rd1, "10.222.0.0", 24,
4030 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
4032 l3o_222.add_vpp_config()
4035 # ping between hosts in local and remote external subnets
4036 # dropped without a contract
4038 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
4040 IP(src="10.220.0.1", dst="10.222.0.1") /
4041 UDP(sport=1234, dport=1234) /
4044 rxs = self.send_and_assert_no_replies(self.pg0, p * 1)
4047 # Add contracts ext-nets for 220 -> 222
4049 c4 = VppGbpContract(
4050 self, 55, 4220, 4222, acl_index,
4051 [VppGbpContractRule(
4052 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4053 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4056 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4057 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4059 [ETH_P_IP, ETH_P_IPV6])
4063 # ping from host in local to remote external subnets
4065 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
4067 IP(src="10.220.0.1", dst="10.222.0.1") /
4068 UDP(sport=1234, dport=1234) /
4071 rxs = self.send_and_expect(self.pg0, p * 3, self.pg7)
4074 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4075 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4076 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4077 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4078 self.assertEqual(rx[VXLAN].vni, 445)
4079 self.assertTrue(rx[VXLAN].flags.G)
4080 self.assertTrue(rx[VXLAN].flags.Instance)
4081 # the sclass of the ext-net the packet came from
4082 self.assertEqual(rx[VXLAN].gpid, 4220)
4083 # policy was applied to the original IP packet
4084 self.assertTrue(rx[VXLAN].gpflags.A)
4085 # since it's an external host the reciever should not learn it
4086 self.assertTrue(rx[VXLAN].gpflags.D)
4087 inner = rx[VXLAN].payload
4088 self.assertEqual(inner[Ether].dst, "00:0c:0c:0c:0c:0c")
4089 self.assertEqual(inner[IP].src, "10.220.0.1")
4090 self.assertEqual(inner[IP].dst, "10.222.0.1")
4093 # ping from host in remote to local external subnets
4094 # there's no contract for this, but the A bit is set.
4096 p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
4097 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
4098 UDP(sport=1234, dport=48879) /
4099 VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
4100 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
4101 IP(src="10.222.0.1", dst="10.220.0.1") /
4102 UDP(sport=1234, dport=1234) /
4105 rxs = self.send_and_expect(self.pg7, p * 3, self.pg0)
4106 self.assertFalse(find_gbp_endpoint(self, ip="10.222.0.1"))
4109 # ping from host in remote to remote external subnets
4110 # this is dropped by reflection check.
4112 p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
4113 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
4114 UDP(sport=1234, dport=48879) /
4115 VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
4116 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
4117 IP(src="10.222.0.1", dst="10.222.0.2") /
4118 UDP(sport=1234, dport=1234) /
4121 rxs = self.send_and_assert_no_replies(self.pg7, p * 3)
4126 self.pg7.unconfig_ip4()
4127 self.vlan_101.set_vtr(L2_VTR_OP.L2_DISABLED)
4128 self.vlan_100.set_vtr(L2_VTR_OP.L2_DISABLED)
4130 def test_gbp_anon_l3_out(self):
4131 """ GBP Anonymous L3 Out """
4133 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
4134 self.vapi.cli("set logging class gbp level debug")
4136 routed_dst_mac = "00:0c:0c:0c:0c:0c"
4137 routed_src_mac = "00:22:bd:f8:19:ff"
4142 t4 = VppIpTable(self, 1)
4144 t6 = VppIpTable(self, 1, True)
4147 rd1 = VppGbpRouteDomain(self, 2, 55, t4, t6)
4148 rd1.add_vpp_config()
4150 self.loop0.set_mac(self.router_mac)
4153 # Bind the BVI to the RD
4155 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
4156 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
4159 # Pg7 hosts a BD's BUM
4160 # Pg1 some other l3 interface
4162 self.pg7.config_ip4()
4163 self.pg7.resolve_arp()
4166 # a GBP external bridge domains for the EPs
4168 bd1 = VppBridgeDomain(self, 1)
4169 bd1.add_vpp_config()
4170 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0, None, None)
4171 gbd1.add_vpp_config()
4174 # The Endpoint-groups in which the external endpoints exist
4176 epg_220 = VppGbpEndpointGroup(self, 220, 113, rd1, gbd1,
4180 VppGbpEndpointRetention(2))
4181 epg_220.add_vpp_config()
4183 # the BVIs have the subnet applied ...
4184 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 24)
4185 ip4_addr.add_vpp_config()
4187 # ... which is an Anonymous L3-out subnets
4188 l3o_1 = VppGbpSubnet(
4189 self, rd1, "10.0.0.0", 24,
4190 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_ANON_L3_OUT,
4192 l3o_1.add_vpp_config()
4195 # an external interface attached to the outside world and the
4198 VppL2Vtr(self, self.vlan_100, L2_VTR_OP.L2_POP_1).add_vpp_config()
4199 VppL2Vtr(self, self.vlan_101, L2_VTR_OP.L2_POP_1).add_vpp_config()
4201 ext_itf = VppGbpExtItf(self, self.loop0, bd1, rd1)
4202 ext_itf.add_vpp_config()
4205 # vlan_100 and vlan_101 are anonymous l3-out interfaces
4207 ext_itf = VppGbpExtItf(self, self.vlan_100, bd1, rd1, anon=True)
4208 ext_itf.add_vpp_config()
4209 ext_itf = VppGbpExtItf(self, self.vlan_101, bd1, rd1, anon=True)
4210 ext_itf.add_vpp_config()
4213 # an unicast vxlan-gbp for inter-RD traffic
4215 vx_tun_l3 = VppGbpVxlanTunnel(
4216 self, 444, rd1.rd_id,
4217 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
4219 vx_tun_l3.add_vpp_config()
4222 # A remote external endpoint
4224 rep = VppGbpEndpoint(self, vx_tun_l3,
4226 "10.0.0.201", "11.0.0.201",
4227 "2001:10::201", "3001::101",
4228 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
4230 self.pg7.remote_ip4,
4232 rep.add_vpp_config()
4235 # ARP packet from host in external subnet are accepted, flooded and
4236 # replied to. We expect 2 packets:
4237 # - APR request flooded over the other vlan subif
4238 # - ARP reply from BVI
4240 p_arp = (Ether(src=self.vlan_100.remote_mac,
4241 dst="ff:ff:ff:ff:ff:ff") /
4246 hwsrc=self.vlan_100.remote_mac,
4247 hwdst="ff:ff:ff:ff:ff:ff"))
4248 rxs = self.send_and_expect(self.pg0, p_arp * 1, self.pg0, n_rx=2)
4250 p_arp = (Ether(src=self.vlan_101.remote_mac,
4251 dst="ff:ff:ff:ff:ff:ff") /
4256 hwsrc=self.vlan_101.remote_mac,
4257 hwdst="ff:ff:ff:ff:ff:ff"))
4258 rxs = self.send_and_expect(self.pg0, p_arp * 1, self.pg0, n_rx=2)
4261 # remote to external
4263 p = (Ether(src=self.pg7.remote_mac,
4264 dst=self.pg7.local_mac) /
4265 IP(src=self.pg7.remote_ip4,
4266 dst=self.pg7.local_ip4) /
4267 UDP(sport=1234, dport=48879) /
4268 VXLAN(vni=vx_tun_l3.vni, gpid=epg_220.sclass, flags=0x88) /
4269 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
4270 IP(src=str(rep.ip4), dst="10.0.0.100") /
4271 UDP(sport=1234, dport=1234) /
4273 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
4276 # local EP pings router
4278 p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
4280 IP(src="10.0.0.100", dst="10.0.0.128") /
4281 ICMP(type='echo-request'))
4282 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
4285 self.assertEqual(rx[Ether].src, str(self.router_mac))
4286 self.assertEqual(rx[Ether].dst, self.vlan_100.remote_mac)
4287 self.assertEqual(rx[Dot1Q].vlan, 100)
4290 # local EP pings other local EP
4292 p = (Ether(src=self.vlan_100.remote_mac,
4293 dst=self.vlan_101.remote_mac) /
4295 IP(src="10.0.0.100", dst="10.0.0.101") /
4296 ICMP(type='echo-request'))
4297 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
4300 self.assertEqual(rx[Ether].src, self.vlan_100.remote_mac)
4301 self.assertEqual(rx[Ether].dst, self.vlan_101.remote_mac)
4302 self.assertEqual(rx[Dot1Q].vlan, 101)
4305 # A subnet reachable through an external router on vlan 100
4307 ip_220 = VppIpRoute(self, "10.220.0.0", 24,
4308 [VppRoutePath("10.0.0.100",
4309 epg_220.bvi.sw_if_index)],
4310 table_id=t4.table_id)
4311 ip_220.add_vpp_config()
4313 l3o_220 = VppGbpSubnet(
4314 self, rd1, "10.220.0.0", 24,
4315 # note: this a "regular" L3 out subnet (not connected)
4316 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
4318 l3o_220.add_vpp_config()
4321 # A subnet reachable through an external router on vlan 101
4323 ip_221 = VppIpRoute(self, "10.221.0.0", 24,
4324 [VppRoutePath("10.0.0.101",
4325 epg_220.bvi.sw_if_index)],
4326 table_id=t4.table_id)
4327 ip_221.add_vpp_config()
4329 l3o_221 = VppGbpSubnet(
4330 self, rd1, "10.221.0.0", 24,
4331 # note: this a "regular" L3 out subnet (not connected)
4332 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
4334 l3o_221.add_vpp_config()
4337 # ping between hosts in remote subnets
4338 # dropped without a contract
4340 p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
4342 IP(src="10.220.0.1", dst="10.221.0.1") /
4343 ICMP(type='echo-request'))
4345 rxs = self.send_and_assert_no_replies(self.pg0, p * 1)
4348 # contract for the external nets to communicate
4350 acl = VppGbpAcl(self)
4351 rule4 = acl.create_rule(permit_deny=1, proto=17)
4352 rule6 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
4353 acl_index = acl.add_vpp_config([rule4, rule6])
4355 c1 = VppGbpContract(
4356 self, 55, 4220, 4221, acl_index,
4357 [VppGbpContractRule(
4358 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4359 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4362 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4363 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4365 [ETH_P_IP, ETH_P_IPV6])
4369 # Contracts allowing ext-net 200 to talk with external EPs
4371 c2 = VppGbpContract(
4372 self, 55, 4220, 113, acl_index,
4373 [VppGbpContractRule(
4374 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4375 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4378 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4379 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4381 [ETH_P_IP, ETH_P_IPV6])
4383 c3 = VppGbpContract(
4384 self, 55, 113, 4220, acl_index,
4385 [VppGbpContractRule(
4386 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4387 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4390 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4391 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4393 [ETH_P_IP, ETH_P_IPV6])
4397 # ping between hosts in remote subnets
4399 p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
4401 IP(src="10.220.0.1", dst="10.221.0.1") /
4402 UDP(sport=1234, dport=1234) /
4405 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
4408 self.assertEqual(rx[Ether].src, str(self.router_mac))
4409 self.assertEqual(rx[Ether].dst, self.vlan_101.remote_mac)
4410 self.assertEqual(rx[Dot1Q].vlan, 101)
4412 # we did not learn these external hosts
4413 self.assertFalse(find_gbp_endpoint(self, ip="10.220.0.1"))
4414 self.assertFalse(find_gbp_endpoint(self, ip="10.221.0.1"))
4417 # from remote external EP to local external EP
4419 p = (Ether(src=self.pg7.remote_mac,
4420 dst=self.pg7.local_mac) /
4421 IP(src=self.pg7.remote_ip4,
4422 dst=self.pg7.local_ip4) /
4423 UDP(sport=1234, dport=48879) /
4424 VXLAN(vni=444, gpid=113, flags=0x88) /
4425 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
4426 IP(src=rep.ip4.address, dst="10.220.0.1") /
4427 UDP(sport=1234, dport=1234) /
4430 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
4433 # ping from an external host to the remote external EP
4435 p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
4437 IP(src="10.220.0.1", dst=rep.ip4.address) /
4438 UDP(sport=1234, dport=1234) /
4441 rxs = self.send_and_expect(self.pg0, p * 1, self.pg7)
4444 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4445 # self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4446 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4447 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4448 self.assertEqual(rx[VXLAN].vni, 444)
4449 self.assertTrue(rx[VXLAN].flags.G)
4450 self.assertTrue(rx[VXLAN].flags.Instance)
4451 # the sclass of the ext-net the packet came from
4452 self.assertEqual(rx[VXLAN].gpid, 4220)
4453 # policy was applied to the original IP packet
4454 self.assertTrue(rx[VXLAN].gpflags.A)
4455 # since it's an external host the reciever should not learn it
4456 self.assertTrue(rx[VXLAN].gpflags.D)
4457 inner = rx[VXLAN].payload
4458 self.assertEqual(inner[IP].src, "10.220.0.1")
4459 self.assertEqual(inner[IP].dst, rep.ip4.address)
4462 # An external subnet reachable via the remote external EP
4466 # first the VXLAN-GBP tunnel over which it is reached
4468 vx_tun_r = VppVxlanGbpTunnel(
4469 self, self.pg7.local_ip4,
4470 self.pg7.remote_ip4, 445,
4471 mode=(VppEnum.vl_api_vxlan_gbp_api_tunnel_mode_t.
4472 VXLAN_GBP_API_TUNNEL_MODE_L3))
4473 vx_tun_r.add_vpp_config()
4474 VppIpInterfaceBind(self, vx_tun_r, t4).add_vpp_config()
4476 self.logger.info(self.vapi.cli("sh vxlan-gbp tunnel"))
4479 # then the special adj to resolve through on that tunnel
4481 n1 = VppNeighbor(self,
4482 vx_tun_r.sw_if_index,
4483 "00:0c:0c:0c:0c:0c",
4484 self.pg7.remote_ip4)
4488 # the route via the adj above
4490 ip_222 = VppIpRoute(self, "10.222.0.0", 24,
4491 [VppRoutePath(self.pg7.remote_ip4,
4492 vx_tun_r.sw_if_index)],
4493 table_id=t4.table_id)
4494 ip_222.add_vpp_config()
4496 l3o_222 = VppGbpSubnet(
4497 self, rd1, "10.222.0.0", 24,
4498 # note: this a "regular" l3out subnet (not connected)
4499 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
4501 l3o_222.add_vpp_config()
4504 # ping between hosts in local and remote external subnets
4505 # dropped without a contract
4507 p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
4509 IP(src="10.220.0.1", dst="10.222.0.1") /
4510 UDP(sport=1234, dport=1234) /
4513 rxs = self.send_and_assert_no_replies(self.pg0, p * 1)
4516 # Add contracts ext-nets for 220 -> 222
4518 c4 = VppGbpContract(
4519 self, 55, 4220, 4222, acl_index,
4520 [VppGbpContractRule(
4521 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4522 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4525 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4526 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4528 [ETH_P_IP, ETH_P_IPV6])
4532 # ping from host in local to remote external subnets
4534 p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
4536 IP(src="10.220.0.1", dst="10.222.0.1") /
4537 UDP(sport=1234, dport=1234) /
4540 rxs = self.send_and_expect(self.pg0, p * 3, self.pg7)
4543 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4544 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4545 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4546 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4547 self.assertEqual(rx[VXLAN].vni, 445)
4548 self.assertTrue(rx[VXLAN].flags.G)
4549 self.assertTrue(rx[VXLAN].flags.Instance)
4550 # the sclass of the ext-net the packet came from
4551 self.assertEqual(rx[VXLAN].gpid, 4220)
4552 # policy was applied to the original IP packet
4553 self.assertTrue(rx[VXLAN].gpflags.A)
4554 # since it's an external host the reciever should not learn it
4555 self.assertTrue(rx[VXLAN].gpflags.D)
4556 inner = rx[VXLAN].payload
4557 self.assertEqual(inner[Ether].dst, "00:0c:0c:0c:0c:0c")
4558 self.assertEqual(inner[IP].src, "10.220.0.1")
4559 self.assertEqual(inner[IP].dst, "10.222.0.1")
4562 # ping from host in remote to local external subnets
4563 # there's no contract for this, but the A bit is set.
4565 p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
4566 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
4567 UDP(sport=1234, dport=48879) /
4568 VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
4569 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
4570 IP(src="10.222.0.1", dst="10.220.0.1") /
4571 UDP(sport=1234, dport=1234) /
4574 rxs = self.send_and_expect(self.pg7, p * 3, self.pg0)
4575 self.assertFalse(find_gbp_endpoint(self, ip="10.222.0.1"))
4578 # ping from host in remote to remote external subnets
4579 # this is dropped by reflection check.
4581 p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
4582 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
4583 UDP(sport=1234, dport=48879) /
4584 VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
4585 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
4586 IP(src="10.222.0.1", dst="10.222.0.2") /
4587 UDP(sport=1234, dport=1234) /
4590 rxs = self.send_and_assert_no_replies(self.pg7, p * 3)
4595 self.vlan_101.set_vtr(L2_VTR_OP.L2_DISABLED)
4596 self.vlan_100.set_vtr(L2_VTR_OP.L2_DISABLED)
4597 self.pg7.unconfig_ip4()
4600 if __name__ == '__main__':
4601 unittest.main(testRunner=VppTestRunner)