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 # a packet with an sclass from a known EPG
1723 # arriving on an unknown TEP
1724 p = (Ether(src=self.pg2.remote_mac,
1725 dst=self.pg2.local_mac) /
1726 IP(src=self.pg2.remote_hosts[1].ip4,
1728 UDP(sport=1234, dport=48879) /
1729 VXLAN(vni=88, gpid=112, flags=0x88) /
1730 Ether(src=l['mac'], dst="ff:ff:ff:ff:ff:ff") /
1732 psrc=l['ip'], pdst=l['ip'],
1733 hwsrc=l['mac'], hwdst="ff:ff:ff:ff:ff:ff"))
1735 rx = self.send_and_expect(self.pg4, [p], self.pg0)
1738 tep1_sw_if_index = find_vxlan_gbp_tunnel(
1741 self.pg2.remote_hosts[1].ip4,
1743 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
1746 # the EP is learnt via the learnt TEP
1747 # both from its MAC and its IP
1749 self.assertTrue(find_gbp_endpoint(self,
1750 vx_tun_l2_1.sw_if_index,
1752 self.assertTrue(find_gbp_endpoint(self,
1753 vx_tun_l2_1.sw_if_index,
1757 # wait for the learnt endpoints to age out
1760 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1764 # Learn new EPs from L2 packets
1766 for ii, l in enumerate(learnt):
1767 # a packet with an sclass from a known EPG
1768 # arriving on an unknown TEP
1769 p = (Ether(src=self.pg2.remote_mac,
1770 dst=self.pg2.local_mac) /
1771 IP(src=self.pg2.remote_hosts[1].ip4,
1772 dst=self.pg2.local_ip4) /
1773 UDP(sport=1234, dport=48879) /
1774 VXLAN(vni=99, gpid=112, flags=0x88) /
1775 Ether(src=l['mac'], dst=ep.mac) /
1778 rx = self.send_and_expect(self.pg2, [p], self.pg0)
1781 tep1_sw_if_index = find_vxlan_gbp_tunnel(
1784 self.pg2.remote_hosts[1].ip4,
1786 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
1789 # the EP is learnt via the learnt TEP
1790 # both from its MAC and its IP
1792 self.assertTrue(find_gbp_endpoint(self,
1793 vx_tun_l2_1.sw_if_index,
1796 self.logger.info(self.vapi.cli("show gbp endpoint"))
1797 self.logger.info(self.vapi.cli("show gbp vxlan"))
1798 self.logger.info(self.vapi.cli("show vxlan-gbp tunnel"))
1801 # wait for the learnt endpoints to age out
1804 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1808 # repeat. the do not learn bit is set so the EPs are not learnt
1811 # a packet with an sclass from a known EPG
1812 p = (Ether(src=self.pg2.remote_mac,
1813 dst=self.pg2.local_mac) /
1814 IP(src=self.pg2.remote_hosts[1].ip4,
1815 dst=self.pg2.local_ip4) /
1816 UDP(sport=1234, dport=48879) /
1817 VXLAN(vni=99, gpid=112, flags=0x88, gpflags="D") /
1818 Ether(src=l['mac'], dst=ep.mac) /
1819 IP(src=l['ip'], dst=ep.ip4.address) /
1820 UDP(sport=1234, dport=1234) /
1823 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
1826 self.assertFalse(find_gbp_endpoint(self,
1827 vx_tun_l2_1.sw_if_index,
1834 # a packet with an sclass from a known EPG
1835 p = (Ether(src=self.pg2.remote_mac,
1836 dst=self.pg2.local_mac) /
1837 IP(src=self.pg2.remote_hosts[1].ip4,
1838 dst=self.pg2.local_ip4) /
1839 UDP(sport=1234, dport=48879) /
1840 VXLAN(vni=99, gpid=112, flags=0x88) /
1841 Ether(src=l['mac'], dst=ep.mac) /
1842 IP(src=l['ip'], dst=ep.ip4.address) /
1843 UDP(sport=1234, dport=1234) /
1846 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
1848 self.assertTrue(find_gbp_endpoint(self,
1849 vx_tun_l2_1.sw_if_index,
1853 # Static EP replies to dynamics
1855 self.logger.info(self.vapi.cli("sh l2fib bd_id 1"))
1857 p = (Ether(src=ep.mac, dst=l['mac']) /
1858 IP(dst=l['ip'], src=ep.ip4.address) /
1859 UDP(sport=1234, dport=1234) /
1862 rxs = self.send_and_expect(self.pg0, p * 17, self.pg2)
1865 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
1866 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
1867 self.assertEqual(rx[UDP].dport, 48879)
1868 # the UDP source port is a random value for hashing
1869 self.assertEqual(rx[VXLAN].gpid, 112)
1870 self.assertEqual(rx[VXLAN].vni, 99)
1871 self.assertTrue(rx[VXLAN].flags.G)
1872 self.assertTrue(rx[VXLAN].flags.Instance)
1873 self.assertTrue(rx[VXLAN].gpflags.A)
1874 self.assertFalse(rx[VXLAN].gpflags.D)
1877 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1881 # repeat in the other EPG
1882 # there's no contract between 220 and 330, but the A-bit is set
1883 # so the packet is cleared for delivery
1886 # a packet with an sclass from a known EPG
1887 p = (Ether(src=self.pg2.remote_mac,
1888 dst=self.pg2.local_mac) /
1889 IP(src=self.pg2.remote_hosts[1].ip4,
1890 dst=self.pg2.local_ip4) /
1891 UDP(sport=1234, dport=48879) /
1892 VXLAN(vni=99, gpid=113, flags=0x88, gpflags='A') /
1893 Ether(src=l['mac'], dst=ep.mac) /
1894 IP(src=l['ip'], dst=ep.ip4.address) /
1895 UDP(sport=1234, dport=1234) /
1898 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
1900 self.assertTrue(find_gbp_endpoint(self,
1901 vx_tun_l2_1.sw_if_index,
1905 # static EP cannot reach the learnt EPs since there is no contract
1906 # only test 1 EP as the others could timeout
1908 p = (Ether(src=ep.mac, dst=l['mac']) /
1909 IP(dst=learnt[0]['ip'], src=ep.ip4.address) /
1910 UDP(sport=1234, dport=1234) /
1913 self.send_and_assert_no_replies(self.pg0, [p])
1916 # refresh the entries after the check for no replies above
1919 # a packet with an sclass from a known EPG
1920 p = (Ether(src=self.pg2.remote_mac,
1921 dst=self.pg2.local_mac) /
1922 IP(src=self.pg2.remote_hosts[1].ip4,
1923 dst=self.pg2.local_ip4) /
1924 UDP(sport=1234, dport=48879) /
1925 VXLAN(vni=99, gpid=113, flags=0x88, gpflags='A') /
1926 Ether(src=l['mac'], dst=ep.mac) /
1927 IP(src=l['ip'], dst=ep.ip4.address) /
1928 UDP(sport=1234, dport=1234) /
1931 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
1933 self.assertTrue(find_gbp_endpoint(self,
1934 vx_tun_l2_1.sw_if_index,
1938 # Add the contract so they can talk
1940 acl = VppGbpAcl(self)
1941 rule = acl.create_rule(permit_deny=1, proto=17)
1942 rule2 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
1943 acl_index = acl.add_vpp_config([rule, rule2])
1944 c1 = VppGbpContract(
1945 self, 401, epg_220.sclass, epg_330.sclass, acl_index,
1946 [VppGbpContractRule(
1947 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1948 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1951 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1952 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1954 [ETH_P_IP, ETH_P_IPV6])
1958 p = (Ether(src=ep.mac, dst=l['mac']) /
1959 IP(dst=l['ip'], src=ep.ip4.address) /
1960 UDP(sport=1234, dport=1234) /
1963 self.send_and_expect(self.pg0, [p], self.pg2)
1966 # send UU packets from the local EP
1968 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1969 self.logger.info(self.vapi.cli("sh gbp bridge"))
1970 p_uu = (Ether(src=ep.mac, dst="00:11:11:11:11:11") /
1971 IP(dst="10.0.0.133", src=ep.ip4.address) /
1972 UDP(sport=1234, dport=1234) /
1974 rxs = self.send_and_expect(ep.itf, [p_uu], gbd1.uu_fwd)
1976 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1978 p_bm = (Ether(src=ep.mac, dst="ff:ff:ff:ff:ff:ff") /
1979 IP(dst="10.0.0.133", src=ep.ip4.address) /
1980 UDP(sport=1234, dport=1234) /
1982 rxs = self.send_and_expect_only(ep.itf, [p_bm], tun_bm.mcast_itf)
1985 self.assertEqual(rx[IP].src, self.pg4.local_ip4)
1986 self.assertEqual(rx[IP].dst, "239.1.1.1")
1987 self.assertEqual(rx[UDP].dport, 48879)
1988 # the UDP source port is a random value for hashing
1989 self.assertEqual(rx[VXLAN].gpid, 112)
1990 self.assertEqual(rx[VXLAN].vni, 88)
1991 self.assertTrue(rx[VXLAN].flags.G)
1992 self.assertTrue(rx[VXLAN].flags.Instance)
1993 self.assertFalse(rx[VXLAN].gpflags.A)
1994 self.assertFalse(rx[VXLAN].gpflags.D)
1997 # Check v6 Endpoints
2000 # a packet with an sclass from a known EPG
2001 p = (Ether(src=self.pg2.remote_mac,
2002 dst=self.pg2.local_mac) /
2003 IP(src=self.pg2.remote_hosts[1].ip4,
2004 dst=self.pg2.local_ip4) /
2005 UDP(sport=1234, dport=48879) /
2006 VXLAN(vni=99, gpid=113, flags=0x88, gpflags='A') /
2007 Ether(src=l['mac'], dst=ep.mac) /
2008 IPv6(src=l['ip6'], dst=ep.ip6.address) /
2009 UDP(sport=1234, dport=1234) /
2012 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
2014 self.assertTrue(find_gbp_endpoint(self,
2015 vx_tun_l2_1.sw_if_index,
2019 # L3 Endpoint Learning
2020 # - configured on the bridge's BVI
2027 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
2029 self.pg2.unconfig_ip4()
2030 self.pg3.unconfig_ip4()
2031 self.pg4.unconfig_ip4()
2033 self.logger.info(self.vapi.cli("sh int"))
2034 self.logger.info(self.vapi.cli("sh gbp vxlan"))
2036 def test_gbp_contract(self):
2037 """ GBP CONTRACTS """
2042 gt4 = VppIpTable(self, 0)
2043 gt4.add_vpp_config()
2044 gt6 = VppIpTable(self, 0, is_ip6=True)
2045 gt6.add_vpp_config()
2047 rd0 = VppGbpRouteDomain(self, 0, 400, gt4, gt6, None, None)
2049 rd0.add_vpp_config()
2054 bd1 = VppBridgeDomain(self, 1, arp_term=0)
2055 bd2 = VppBridgeDomain(self, 2, arp_term=0)
2057 bd1.add_vpp_config()
2058 bd2.add_vpp_config()
2060 gbd1 = VppGbpBridgeDomain(self, bd1, rd0, self.loop0)
2061 gbd2 = VppGbpBridgeDomain(self, bd2, rd0, self.loop1)
2063 gbd1.add_vpp_config()
2064 gbd2.add_vpp_config()
2067 # 3 EPGs, 2 of which share a BD.
2069 epgs = [VppGbpEndpointGroup(self, 220, 1220, rd0, gbd1,
2071 "10.0.0.128", "2001:10::128"),
2072 VppGbpEndpointGroup(self, 221, 1221, rd0, gbd1,
2074 "10.0.1.128", "2001:10:1::128"),
2075 VppGbpEndpointGroup(self, 222, 1222, rd0, gbd2,
2077 "10.0.2.128", "2001:10:2::128")]
2079 # 4 end-points, 2 in the same subnet, 3 in the same BD
2081 eps = [VppGbpEndpoint(self, self.pg0,
2083 "10.0.0.1", "11.0.0.1",
2084 "2001:10::1", "3001::1"),
2085 VppGbpEndpoint(self, self.pg1,
2087 "10.0.0.2", "11.0.0.2",
2088 "2001:10::2", "3001::2"),
2089 VppGbpEndpoint(self, self.pg2,
2091 "10.0.1.1", "11.0.0.3",
2092 "2001:10:1::1", "3001::3"),
2093 VppGbpEndpoint(self, self.pg3,
2095 "10.0.2.1", "11.0.0.4",
2096 "2001:10:2::1", "3001::4")]
2099 # Config related to each of the EPGs
2102 # IP config on the BVI interfaces
2104 VppIpInterfaceBind(self, epg.bvi, epg.rd.t4).add_vpp_config()
2105 VppIpInterfaceBind(self, epg.bvi, epg.rd.t6).add_vpp_config()
2106 self.vapi.sw_interface_set_mac_address(
2107 epg.bvi.sw_if_index,
2108 self.router_mac.packed)
2110 if_ip4 = VppIpInterfaceAddress(self, epg.bvi, epg.bvi_ip4, 32)
2111 if_ip6 = VppIpInterfaceAddress(self, epg.bvi, epg.bvi_ip6, 128)
2112 if_ip4.add_vpp_config()
2113 if_ip6.add_vpp_config()
2115 # add the BD ARP termination entry for BVI IP
2116 epg.bd_arp_ip4 = VppBridgeDomainArpEntry(self, epg.bd.bd,
2117 str(self.router_mac),
2118 epg.bvi_ip4.address)
2119 epg.bd_arp_ip4.add_vpp_config()
2122 epg.add_vpp_config()
2130 self.logger.info(self.vapi.cli("show gbp endpoint"))
2131 self.logger.info(self.vapi.cli("show interface"))
2132 self.logger.info(self.vapi.cli("show br"))
2135 # Intra epg allowed without contract
2137 pkt_intra_epg_220_to_220 = (Ether(src=self.pg0.remote_mac,
2138 dst=self.pg1.remote_mac) /
2139 IP(src=eps[0].ip4.address,
2140 dst=eps[1].ip4.address) /
2141 UDP(sport=1234, dport=1234) /
2144 self.send_and_expect_bridged(self.pg0,
2145 pkt_intra_epg_220_to_220 * 65,
2149 # Inter epg denied without contract
2151 pkt_inter_epg_220_to_221 = (Ether(src=self.pg0.remote_mac,
2152 dst=self.pg2.remote_mac) /
2153 IP(src=eps[0].ip4.address,
2154 dst=eps[2].ip4.address) /
2155 UDP(sport=1234, dport=1234) /
2158 self.send_and_assert_no_replies(self.pg0, pkt_inter_epg_220_to_221)
2161 # A uni-directional contract from EPG 220 -> 221
2163 acl = VppGbpAcl(self)
2164 rule = acl.create_rule(permit_deny=1, proto=17)
2165 rule2 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
2166 acl_index = acl.add_vpp_config([rule, rule2])
2167 c1 = VppGbpContract(
2168 self, 400, epgs[0].sclass, epgs[1].sclass, acl_index,
2169 [VppGbpContractRule(
2170 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2171 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2174 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2175 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2177 [ETH_P_IP, ETH_P_IPV6])
2180 self.send_and_expect_bridged(eps[0].itf,
2181 pkt_inter_epg_220_to_221 * 65,
2184 pkt_inter_epg_220_to_222 = (Ether(src=self.pg0.remote_mac,
2185 dst=str(self.router_mac)) /
2186 IP(src=eps[0].ip4.address,
2187 dst=eps[3].ip4.address) /
2188 UDP(sport=1234, dport=1234) /
2190 self.send_and_assert_no_replies(eps[0].itf,
2191 pkt_inter_epg_220_to_222 * 65)
2194 # contract for the return direction
2196 c2 = VppGbpContract(
2197 self, 400, epgs[1].sclass, epgs[0].sclass, acl_index,
2198 [VppGbpContractRule(
2199 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2200 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2203 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2204 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2206 [ETH_P_IP, ETH_P_IPV6])
2209 self.send_and_expect_bridged(eps[0].itf,
2210 pkt_inter_epg_220_to_221 * 65,
2212 pkt_inter_epg_221_to_220 = (Ether(src=self.pg2.remote_mac,
2213 dst=self.pg0.remote_mac) /
2214 IP(src=eps[2].ip4.address,
2215 dst=eps[0].ip4.address) /
2216 UDP(sport=1234, dport=1234) /
2218 self.send_and_expect_bridged(eps[2].itf,
2219 pkt_inter_epg_221_to_220 * 65,
2223 # contract between 220 and 222 uni-direction
2225 c3 = VppGbpContract(
2226 self, 400, epgs[0].sclass, epgs[2].sclass, acl_index,
2227 [VppGbpContractRule(
2228 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2229 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2232 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2233 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2235 [ETH_P_IP, ETH_P_IPV6])
2238 self.send_and_expect(eps[0].itf,
2239 pkt_inter_epg_220_to_222 * 65,
2242 c3.remove_vpp_config()
2243 c1.remove_vpp_config()
2244 c2.remove_vpp_config()
2245 acl.remove_vpp_config()
2247 def test_gbp_bd_flags(self):
2248 """ GBP BD FLAGS """
2253 gt4 = VppIpTable(self, 1)
2254 gt4.add_vpp_config()
2255 gt6 = VppIpTable(self, 1, is_ip6=True)
2256 gt6.add_vpp_config()
2258 rd1 = VppGbpRouteDomain(self, 1, 401, gt4, gt6)
2259 rd1.add_vpp_config()
2262 # Pg3 hosts the IP4 UU-flood VXLAN tunnel
2263 # Pg4 hosts the IP6 UU-flood VXLAN tunnel
2265 self.pg3.config_ip4()
2266 self.pg3.resolve_arp()
2267 self.pg4.config_ip4()
2268 self.pg4.resolve_arp()
2271 # Add a mcast destination VXLAN-GBP tunnel for B&M traffic
2273 tun_bm = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
2276 tun_bm.add_vpp_config()
2279 # a GBP bridge domain with a BVI and a UU-flood interface
2281 bd1 = VppBridgeDomain(self, 1)
2282 bd1.add_vpp_config()
2284 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0, self.pg3,
2285 tun_bm, uu_drop=True, bm_drop=True)
2286 gbd1.add_vpp_config()
2288 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2289 self.logger.info(self.vapi.cli("sh gbp bridge"))
2291 # ... and has a /32 applied
2292 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2293 ip_addr.add_vpp_config()
2296 # The Endpoint-group
2298 epg_220 = VppGbpEndpointGroup(self, 220, 112, rd1, gbd1,
2302 VppGbpEndpointRetention(2))
2303 epg_220.add_vpp_config()
2305 ep = VppGbpEndpoint(self, self.pg0,
2307 "10.0.0.127", "11.0.0.127",
2308 "2001:10::1", "3001::1")
2311 # send UU/BM packet from the local EP with UU drop and BM drop enabled
2314 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2315 self.logger.info(self.vapi.cli("sh gbp bridge"))
2316 p_uu = (Ether(src=ep.mac, dst="00:11:11:11:11:11") /
2317 IP(dst="10.0.0.133", src=ep.ip4.address) /
2318 UDP(sport=1234, dport=1234) /
2320 self.send_and_assert_no_replies(ep.itf, [p_uu])
2322 p_bm = (Ether(src=ep.mac, dst="ff:ff:ff:ff:ff:ff") /
2323 IP(dst="10.0.0.133", src=ep.ip4.address) /
2324 UDP(sport=1234, dport=1234) /
2326 self.send_and_assert_no_replies(ep.itf, [p_bm])
2328 self.pg3.unconfig_ip4()
2329 self.pg4.unconfig_ip4()
2331 self.logger.info(self.vapi.cli("sh int"))
2333 def test_gbp_learn_vlan_l2(self):
2334 """ GBP L2 Endpoint w/ VLANs"""
2336 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
2337 learnt = [{'mac': '00:00:11:11:11:01',
2339 'ip6': '2001:10::2'},
2340 {'mac': '00:00:11:11:11:02',
2342 'ip6': '2001:10::3'}]
2347 gt4 = VppIpTable(self, 1)
2348 gt4.add_vpp_config()
2349 gt6 = VppIpTable(self, 1, is_ip6=True)
2350 gt6.add_vpp_config()
2352 rd1 = VppGbpRouteDomain(self, 1, 401, gt4, gt6)
2353 rd1.add_vpp_config()
2356 # Pg2 hosts the vxlan tunnel, hosts on pg2 to act as TEPs
2358 self.pg2.config_ip4()
2359 self.pg2.resolve_arp()
2360 self.pg2.generate_remote_hosts(4)
2361 self.pg2.configure_ipv4_neighbors()
2362 self.pg3.config_ip4()
2363 self.pg3.resolve_arp()
2366 # The EP will be on a vlan sub-interface
2368 vlan_11 = VppDot1QSubint(self, self.pg0, 11)
2370 self.vapi.l2_interface_vlan_tag_rewrite(
2371 sw_if_index=vlan_11.sw_if_index, vtr_op=L2_VTR_OP.L2_POP_1,
2374 bd_uu_fwd = VppVxlanGbpTunnel(self, self.pg3.local_ip4,
2375 self.pg3.remote_ip4, 116)
2376 bd_uu_fwd.add_vpp_config()
2379 # a GBP bridge domain with a BVI and a UU-flood interface
2380 # The BD is marked as do not learn, so no endpoints are ever
2381 # learnt in this BD.
2383 bd1 = VppBridgeDomain(self, 1)
2384 bd1.add_vpp_config()
2385 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0, bd_uu_fwd,
2387 gbd1.add_vpp_config()
2389 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2390 self.logger.info(self.vapi.cli("sh gbp bridge"))
2392 # ... and has a /32 applied
2393 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2394 ip_addr.add_vpp_config()
2397 # The Endpoint-group in which we are learning endpoints
2399 epg_220 = VppGbpEndpointGroup(self, 220, 441, rd1, gbd1,
2403 VppGbpEndpointRetention(2))
2404 epg_220.add_vpp_config()
2407 # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
2410 vx_tun_l2_1 = VppGbpVxlanTunnel(
2411 self, 99, bd1.bd_id,
2412 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L2,
2414 vx_tun_l2_1.add_vpp_config()
2417 # A static endpoint that the learnt endpoints are trying to
2420 ep = VppGbpEndpoint(self, vlan_11,
2422 "10.0.0.127", "11.0.0.127",
2423 "2001:10::1", "3001::1")
2426 self.assertTrue(find_route(self, ep.ip4.address, 32, table_id=1))
2429 # Send to the static EP
2431 for ii, l in enumerate(learnt):
2432 # a packet with an sclass from a known EPG
2433 # arriving on an unknown TEP
2434 p = (Ether(src=self.pg2.remote_mac,
2435 dst=self.pg2.local_mac) /
2436 IP(src=self.pg2.remote_hosts[1].ip4,
2437 dst=self.pg2.local_ip4) /
2438 UDP(sport=1234, dport=48879) /
2439 VXLAN(vni=99, gpid=441, flags=0x88) /
2440 Ether(src=l['mac'], dst=ep.mac) /
2441 IP(src=l['ip'], dst=ep.ip4.address) /
2442 UDP(sport=1234, dport=1234) /
2445 rxs = self.send_and_expect(self.pg2, [p], self.pg0)
2448 # packet to EP has the EP's vlan tag
2451 self.assertEqual(rx[Dot1Q].vlan, 11)
2454 # the EP is not learnt since the BD setting prevents it
2457 self.assertFalse(find_gbp_endpoint(self,
2458 vx_tun_l2_1.sw_if_index,
2460 self.assertEqual(INDEX_INVALID,
2461 find_vxlan_gbp_tunnel(
2464 self.pg2.remote_hosts[1].ip4,
2467 self.assertEqual(len(self.vapi.gbp_endpoint_dump()), 1)
2471 # we didn't learn the remotes so they are sent to the UU-fwd
2474 p = (Ether(src=ep.mac, dst=l['mac']) /
2476 IP(dst=l['ip'], src=ep.ip4.address) /
2477 UDP(sport=1234, dport=1234) /
2480 rxs = self.send_and_expect(self.pg0, p * 17, self.pg3)
2483 self.assertEqual(rx[IP].src, self.pg3.local_ip4)
2484 self.assertEqual(rx[IP].dst, self.pg3.remote_ip4)
2485 self.assertEqual(rx[UDP].dport, 48879)
2486 # the UDP source port is a random value for hashing
2487 self.assertEqual(rx[VXLAN].gpid, 441)
2488 self.assertEqual(rx[VXLAN].vni, 116)
2489 self.assertTrue(rx[VXLAN].flags.G)
2490 self.assertTrue(rx[VXLAN].flags.Instance)
2491 self.assertFalse(rx[VXLAN].gpflags.A)
2492 self.assertFalse(rx[VXLAN].gpflags.D)
2494 self.pg2.unconfig_ip4()
2495 self.pg3.unconfig_ip4()
2497 def test_gbp_learn_l3(self):
2498 """ GBP L3 Endpoint Learning """
2500 self.vapi.cli("set logging class gbp level debug")
2502 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
2503 routed_dst_mac = "00:0c:0c:0c:0c:0c"
2504 routed_src_mac = "00:22:bd:f8:19:ff"
2506 learnt = [{'mac': '00:00:11:11:11:02',
2508 'ip6': '2001:10::2'},
2509 {'mac': '00:00:11:11:11:03',
2511 'ip6': '2001:10::3'}]
2516 t4 = VppIpTable(self, 1)
2518 t6 = VppIpTable(self, 1, True)
2521 tun_ip4_uu = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
2522 self.pg4.remote_ip4, 114)
2523 tun_ip6_uu = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
2524 self.pg4.remote_ip4, 116)
2525 tun_ip4_uu.add_vpp_config()
2526 tun_ip6_uu.add_vpp_config()
2528 rd1 = VppGbpRouteDomain(self, 2, 401, t4, t6, tun_ip4_uu, tun_ip6_uu)
2529 rd1.add_vpp_config()
2531 self.loop0.set_mac(self.router_mac)
2534 # Bind the BVI to the RD
2536 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
2537 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
2540 # Pg2 hosts the vxlan tunnel
2541 # hosts on pg2 to act as TEPs
2545 self.pg2.config_ip4()
2546 self.pg2.resolve_arp()
2547 self.pg2.generate_remote_hosts(4)
2548 self.pg2.configure_ipv4_neighbors()
2549 self.pg3.config_ip4()
2550 self.pg3.resolve_arp()
2551 self.pg4.config_ip4()
2552 self.pg4.resolve_arp()
2555 # a GBP bridge domain with a BVI and a UU-flood interface
2557 bd1 = VppBridgeDomain(self, 1)
2558 bd1.add_vpp_config()
2559 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0, self.pg3)
2560 gbd1.add_vpp_config()
2562 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2563 self.logger.info(self.vapi.cli("sh gbp bridge"))
2564 self.logger.info(self.vapi.cli("sh gbp route"))
2566 # ... and has a /32 and /128 applied
2567 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2568 ip4_addr.add_vpp_config()
2569 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 128)
2570 ip6_addr.add_vpp_config()
2573 # The Endpoint-group in which we are learning endpoints
2575 epg_220 = VppGbpEndpointGroup(self, 220, 441, rd1, gbd1,
2579 VppGbpEndpointRetention(2))
2580 epg_220.add_vpp_config()
2583 # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
2586 vx_tun_l3 = VppGbpVxlanTunnel(
2587 self, 101, rd1.rd_id,
2588 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
2590 vx_tun_l3.add_vpp_config()
2593 # A static endpoint that the learnt endpoints are trying to
2596 ep = VppGbpEndpoint(self, self.pg0,
2598 "10.0.0.127", "11.0.0.127",
2599 "2001:10::1", "3001::1")
2603 # learn some remote IPv4 EPs
2605 for ii, l in enumerate(learnt):
2606 # a packet with an sclass from a known EPG
2607 # arriving on an unknown TEP
2608 p = (Ether(src=self.pg2.remote_mac,
2609 dst=self.pg2.local_mac) /
2610 IP(src=self.pg2.remote_hosts[1].ip4,
2611 dst=self.pg2.local_ip4) /
2612 UDP(sport=1234, dport=48879) /
2613 VXLAN(vni=101, gpid=441, flags=0x88) /
2614 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2615 IP(src=l['ip'], dst=ep.ip4.address) /
2616 UDP(sport=1234, dport=1234) /
2619 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2622 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2625 self.pg2.remote_hosts[1].ip4,
2627 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2629 # endpoint learnt via the parent GBP-vxlan interface
2630 self.assertTrue(find_gbp_endpoint(self,
2631 vx_tun_l3._sw_if_index,
2635 # Static IPv4 EP replies to learnt
2638 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2639 IP(dst=l['ip'], src=ep.ip4.address) /
2640 UDP(sport=1234, dport=1234) /
2643 rxs = self.send_and_expect(self.pg0, p * 1, self.pg2)
2646 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2647 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2648 self.assertEqual(rx[UDP].dport, 48879)
2649 # the UDP source port is a random value for hashing
2650 self.assertEqual(rx[VXLAN].gpid, 441)
2651 self.assertEqual(rx[VXLAN].vni, 101)
2652 self.assertTrue(rx[VXLAN].flags.G)
2653 self.assertTrue(rx[VXLAN].flags.Instance)
2654 self.assertTrue(rx[VXLAN].gpflags.A)
2655 self.assertFalse(rx[VXLAN].gpflags.D)
2657 inner = rx[VXLAN].payload
2659 self.assertEqual(inner[Ether].src, routed_src_mac)
2660 self.assertEqual(inner[Ether].dst, routed_dst_mac)
2661 self.assertEqual(inner[IP].src, ep.ip4.address)
2662 self.assertEqual(inner[IP].dst, l['ip'])
2665 self.assertFalse(find_gbp_endpoint(self,
2670 # learn some remote IPv6 EPs
2672 for ii, l in enumerate(learnt):
2673 # a packet with an sclass from a known EPG
2674 # arriving on an unknown TEP
2675 p = (Ether(src=self.pg2.remote_mac,
2676 dst=self.pg2.local_mac) /
2677 IP(src=self.pg2.remote_hosts[1].ip4,
2678 dst=self.pg2.local_ip4) /
2679 UDP(sport=1234, dport=48879) /
2680 VXLAN(vni=101, gpid=441, flags=0x88) /
2681 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2682 IPv6(src=l['ip6'], dst=ep.ip6.address) /
2683 UDP(sport=1234, dport=1234) /
2686 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2689 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2692 self.pg2.remote_hosts[1].ip4,
2694 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2696 self.logger.info(self.vapi.cli("show gbp bridge"))
2697 self.logger.info(self.vapi.cli("show vxlan-gbp tunnel"))
2698 self.logger.info(self.vapi.cli("show gbp vxlan"))
2699 self.logger.info(self.vapi.cli("show int addr"))
2701 # endpoint learnt via the TEP
2702 self.assertTrue(find_gbp_endpoint(self, ip=l['ip6']))
2704 self.logger.info(self.vapi.cli("show gbp endpoint"))
2705 self.logger.info(self.vapi.cli("show ip fib index 1 %s" % l['ip']))
2708 # Static EP replies to learnt
2711 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2712 IPv6(dst=l['ip6'], src=ep.ip6.address) /
2713 UDP(sport=1234, dport=1234) /
2716 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
2719 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2720 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2721 self.assertEqual(rx[UDP].dport, 48879)
2722 # the UDP source port is a random value for hashing
2723 self.assertEqual(rx[VXLAN].gpid, 441)
2724 self.assertEqual(rx[VXLAN].vni, 101)
2725 self.assertTrue(rx[VXLAN].flags.G)
2726 self.assertTrue(rx[VXLAN].flags.Instance)
2727 self.assertTrue(rx[VXLAN].gpflags.A)
2728 self.assertFalse(rx[VXLAN].gpflags.D)
2730 inner = rx[VXLAN].payload
2732 self.assertEqual(inner[Ether].src, routed_src_mac)
2733 self.assertEqual(inner[Ether].dst, routed_dst_mac)
2734 self.assertEqual(inner[IPv6].src, ep.ip6.address)
2735 self.assertEqual(inner[IPv6].dst, l['ip6'])
2737 self.logger.info(self.vapi.cli("sh gbp endpoint"))
2739 self.wait_for_ep_timeout(ip=l['ip'])
2742 # Static sends to unknown EP with no route
2744 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2745 IP(dst="10.0.0.99", src=ep.ip4.address) /
2746 UDP(sport=1234, dport=1234) /
2749 self.send_and_assert_no_replies(self.pg0, [p])
2752 # Add a route to static EP's v4 and v6 subnet
2753 # packets should be sent on the v4/v6 uu=fwd interface resp.
2755 se_10_24 = VppGbpSubnet(
2756 self, rd1, "10.0.0.0", 24,
2757 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT)
2758 se_10_24.add_vpp_config()
2760 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2761 IP(dst="10.0.0.99", src=ep.ip4.address) /
2762 UDP(sport=1234, dport=1234) /
2765 rxs = self.send_and_expect(self.pg0, [p], self.pg4)
2767 self.assertEqual(rx[IP].src, self.pg4.local_ip4)
2768 self.assertEqual(rx[IP].dst, self.pg4.remote_ip4)
2769 self.assertEqual(rx[UDP].dport, 48879)
2770 # the UDP source port is a random value for hashing
2771 self.assertEqual(rx[VXLAN].gpid, 441)
2772 self.assertEqual(rx[VXLAN].vni, 114)
2773 self.assertTrue(rx[VXLAN].flags.G)
2774 self.assertTrue(rx[VXLAN].flags.Instance)
2775 # policy is not applied to packets sent to the uu-fwd interfaces
2776 self.assertFalse(rx[VXLAN].gpflags.A)
2777 self.assertFalse(rx[VXLAN].gpflags.D)
2780 # learn some remote IPv4 EPs
2782 for ii, l in enumerate(learnt):
2783 # a packet with an sclass from a known EPG
2784 # arriving on an unknown TEP
2785 p = (Ether(src=self.pg2.remote_mac,
2786 dst=self.pg2.local_mac) /
2787 IP(src=self.pg2.remote_hosts[2].ip4,
2788 dst=self.pg2.local_ip4) /
2789 UDP(sport=1234, dport=48879) /
2790 VXLAN(vni=101, gpid=441, flags=0x88) /
2791 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2792 IP(src=l['ip'], dst=ep.ip4.address) /
2793 UDP(sport=1234, dport=1234) /
2796 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2799 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2802 self.pg2.remote_hosts[2].ip4,
2804 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2806 # endpoint learnt via the parent GBP-vxlan interface
2807 self.assertTrue(find_gbp_endpoint(self,
2808 vx_tun_l3._sw_if_index,
2812 # Add a remote endpoint from the API
2814 rep_88 = VppGbpEndpoint(self, vx_tun_l3,
2816 "10.0.0.88", "11.0.0.88",
2817 "2001:10::88", "3001::88",
2818 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
2820 self.pg2.remote_hosts[2].ip4,
2822 rep_88.add_vpp_config()
2825 # Add a remote endpoint from the API that matches an existing one
2826 # this is a lower priority, hence the packet is sent to the DP leanrt
2829 rep_2 = VppGbpEndpoint(self, vx_tun_l3,
2831 learnt[0]['ip'], "11.0.0.101",
2832 learnt[0]['ip6'], "3001::101",
2833 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
2835 self.pg2.remote_hosts[1].ip4,
2837 rep_2.add_vpp_config()
2840 # Add a route to the learned EP's v4 subnet
2841 # packets should be send on the v4/v6 uu=fwd interface resp.
2843 se_10_1_24 = VppGbpSubnet(
2844 self, rd1, "10.0.1.0", 24,
2845 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT)
2846 se_10_1_24.add_vpp_config()
2848 self.logger.info(self.vapi.cli("show gbp endpoint"))
2850 ips = ["10.0.0.88", learnt[0]['ip']]
2852 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2853 IP(dst=ip, src=ep.ip4.address) /
2854 UDP(sport=1234, dport=1234) /
2857 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
2860 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2861 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[2].ip4)
2862 self.assertEqual(rx[UDP].dport, 48879)
2863 # the UDP source port is a random value for hashing
2864 self.assertEqual(rx[VXLAN].gpid, 441)
2865 self.assertEqual(rx[VXLAN].vni, 101)
2866 self.assertTrue(rx[VXLAN].flags.G)
2867 self.assertTrue(rx[VXLAN].flags.Instance)
2868 self.assertTrue(rx[VXLAN].gpflags.A)
2869 self.assertFalse(rx[VXLAN].gpflags.D)
2871 inner = rx[VXLAN].payload
2873 self.assertEqual(inner[Ether].src, routed_src_mac)
2874 self.assertEqual(inner[Ether].dst, routed_dst_mac)
2875 self.assertEqual(inner[IP].src, ep.ip4.address)
2876 self.assertEqual(inner[IP].dst, ip)
2879 # remove the API remote EPs, only API sourced is gone, the DP
2880 # learnt one remains
2882 rep_88.remove_vpp_config()
2883 rep_2.remove_vpp_config()
2885 self.assertTrue(find_gbp_endpoint(self, ip=rep_2.ip4.address))
2887 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2888 IP(src=ep.ip4.address, dst=rep_2.ip4.address) /
2889 UDP(sport=1234, dport=1234) /
2891 rxs = self.send_and_expect(self.pg0, [p], self.pg2)
2893 self.assertFalse(find_gbp_endpoint(self, ip=rep_88.ip4.address))
2895 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2896 IP(src=ep.ip4.address, dst=rep_88.ip4.address) /
2897 UDP(sport=1234, dport=1234) /
2899 rxs = self.send_and_expect(self.pg0, [p], self.pg4)
2902 # to appease the testcase we cannot have the registered EP still
2903 # present (because it's DP learnt) when the TC ends so wait until
2906 self.wait_for_ep_timeout(ip=rep_88.ip4.address)
2907 self.wait_for_ep_timeout(ip=rep_2.ip4.address)
2910 # Same as above, learn a remote EP via CP and DP
2911 # this time remove the DP one first. expect the CP data to remain
2913 rep_3 = VppGbpEndpoint(self, vx_tun_l3,
2915 "10.0.1.4", "11.0.0.103",
2916 "2001::10:3", "3001::103",
2917 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
2919 self.pg2.remote_hosts[1].ip4,
2921 rep_3.add_vpp_config()
2923 p = (Ether(src=self.pg2.remote_mac,
2924 dst=self.pg2.local_mac) /
2925 IP(src=self.pg2.remote_hosts[2].ip4,
2926 dst=self.pg2.local_ip4) /
2927 UDP(sport=1234, dport=48879) /
2928 VXLAN(vni=101, gpid=441, flags=0x88) /
2929 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2930 IP(src="10.0.1.4", dst=ep.ip4.address) /
2931 UDP(sport=1234, dport=1234) /
2933 rxs = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
2935 self.assertTrue(find_gbp_endpoint(self,
2936 vx_tun_l3._sw_if_index,
2937 ip=rep_3.ip4.address,
2938 tep=[self.pg2.local_ip4,
2939 self.pg2.remote_hosts[2].ip4]))
2941 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2942 IP(dst="10.0.1.4", src=ep.ip4.address) /
2943 UDP(sport=1234, dport=1234) /
2945 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
2947 # host 2 is the DP learned TEP
2949 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2950 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[2].ip4)
2952 self.wait_for_ep_timeout(ip=rep_3.ip4.address,
2953 tep=[self.pg2.local_ip4,
2954 self.pg2.remote_hosts[2].ip4])
2956 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
2958 # host 1 is the CP learned TEP
2960 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2961 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2964 # shutdown with learnt endpoint present
2966 p = (Ether(src=self.pg2.remote_mac,
2967 dst=self.pg2.local_mac) /
2968 IP(src=self.pg2.remote_hosts[1].ip4,
2969 dst=self.pg2.local_ip4) /
2970 UDP(sport=1234, dport=48879) /
2971 VXLAN(vni=101, gpid=441, flags=0x88) /
2972 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2973 IP(src=learnt[1]['ip'], dst=ep.ip4.address) /
2974 UDP(sport=1234, dport=1234) /
2977 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2979 # endpoint learnt via the parent GBP-vxlan interface
2980 self.assertTrue(find_gbp_endpoint(self,
2981 vx_tun_l3._sw_if_index,
2986 # remote endpoint becomes local
2988 self.pg2.unconfig_ip4()
2989 self.pg3.unconfig_ip4()
2990 self.pg4.unconfig_ip4()
2992 def test_gbp_redirect(self):
2993 """ GBP Endpoint Redirect """
2995 self.vapi.cli("set logging class gbp level debug")
2997 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
2998 routed_dst_mac = "00:0c:0c:0c:0c:0c"
2999 routed_src_mac = "00:22:bd:f8:19:ff"
3001 learnt = [{'mac': '00:00:11:11:11:02',
3003 'ip6': '2001:10::2'},
3004 {'mac': '00:00:11:11:11:03',
3006 'ip6': '2001:10::3'}]
3011 t4 = VppIpTable(self, 1)
3013 t6 = VppIpTable(self, 1, True)
3016 rd1 = VppGbpRouteDomain(self, 2, 402, t4, t6)
3017 rd1.add_vpp_config()
3019 self.loop0.set_mac(self.router_mac)
3022 # Bind the BVI to the RD
3024 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
3025 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
3028 # Pg7 hosts a BD's UU-fwd
3030 self.pg7.config_ip4()
3031 self.pg7.resolve_arp()
3034 # a GBP bridge domains for the EPs
3036 bd1 = VppBridgeDomain(self, 1)
3037 bd1.add_vpp_config()
3038 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0)
3039 gbd1.add_vpp_config()
3041 bd2 = VppBridgeDomain(self, 2)
3042 bd2.add_vpp_config()
3043 gbd2 = VppGbpBridgeDomain(self, bd2, rd1, self.loop1)
3044 gbd2.add_vpp_config()
3046 # ... and has a /32 and /128 applied
3047 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
3048 ip4_addr.add_vpp_config()
3049 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 128)
3050 ip6_addr.add_vpp_config()
3051 ip4_addr = VppIpInterfaceAddress(self, gbd2.bvi, "10.0.1.128", 32)
3052 ip4_addr.add_vpp_config()
3053 ip6_addr = VppIpInterfaceAddress(self, gbd2.bvi, "2001:11::128", 128)
3054 ip6_addr.add_vpp_config()
3057 # The Endpoint-groups in which we are learning endpoints
3059 epg_220 = VppGbpEndpointGroup(self, 220, 440, rd1, gbd1,
3063 VppGbpEndpointRetention(2))
3064 epg_220.add_vpp_config()
3065 epg_221 = VppGbpEndpointGroup(self, 221, 441, rd1, gbd2,
3069 VppGbpEndpointRetention(2))
3070 epg_221.add_vpp_config()
3071 epg_222 = VppGbpEndpointGroup(self, 222, 442, rd1, gbd1,
3075 VppGbpEndpointRetention(2))
3076 epg_222.add_vpp_config()
3079 # a GBP bridge domains for the SEPs
3081 bd_uu1 = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
3082 self.pg7.remote_ip4, 116)
3083 bd_uu1.add_vpp_config()
3084 bd_uu2 = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
3085 self.pg7.remote_ip4, 117)
3086 bd_uu2.add_vpp_config()
3088 bd3 = VppBridgeDomain(self, 3)
3089 bd3.add_vpp_config()
3090 gbd3 = VppGbpBridgeDomain(self, bd3, rd1, self.loop2,
3091 bd_uu1, learn=False)
3092 gbd3.add_vpp_config()
3093 bd4 = VppBridgeDomain(self, 4)
3094 bd4.add_vpp_config()
3095 gbd4 = VppGbpBridgeDomain(self, bd4, rd1, self.loop3,
3096 bd_uu2, learn=False)
3097 gbd4.add_vpp_config()
3100 # EPGs in which the service endpoints exist
3102 epg_320 = VppGbpEndpointGroup(self, 320, 550, rd1, gbd3,
3106 VppGbpEndpointRetention(2))
3107 epg_320.add_vpp_config()
3108 epg_321 = VppGbpEndpointGroup(self, 321, 551, rd1, gbd4,
3112 VppGbpEndpointRetention(2))
3113 epg_321.add_vpp_config()
3116 # three local endpoints
3118 ep1 = VppGbpEndpoint(self, self.pg0,
3120 "10.0.0.1", "11.0.0.1",
3121 "2001:10::1", "3001:10::1")
3122 ep1.add_vpp_config()
3123 ep2 = VppGbpEndpoint(self, self.pg1,
3125 "10.0.1.1", "11.0.1.1",
3126 "2001:11::1", "3001:11::1")
3127 ep2.add_vpp_config()
3128 ep3 = VppGbpEndpoint(self, self.pg2,
3130 "10.0.2.2", "11.0.2.2",
3131 "2001:12::1", "3001:12::1")
3132 ep3.add_vpp_config()
3137 sep1 = VppGbpEndpoint(self, self.pg3,
3139 "12.0.0.1", "13.0.0.1",
3140 "4001:10::1", "5001:10::1")
3141 sep1.add_vpp_config()
3142 sep2 = VppGbpEndpoint(self, self.pg4,
3144 "12.0.0.2", "13.0.0.2",
3145 "4001:10::2", "5001:10::2")
3146 sep2.add_vpp_config()
3147 sep3 = VppGbpEndpoint(self, self.pg5,
3149 "12.0.1.1", "13.0.1.1",
3150 "4001:11::1", "5001:11::1")
3151 sep3.add_vpp_config()
3152 # this EP is not installed immediately
3153 sep4 = VppGbpEndpoint(self, self.pg6,
3155 "12.0.1.2", "13.0.1.2",
3156 "4001:11::2", "5001:11::2")
3159 # an L2 switch packet between local EPs in different EPGs
3160 # different dest ports on each so the are LB hashed differently
3162 p4 = [(Ether(src=ep1.mac, dst=ep3.mac) /
3163 IP(src=ep1.ip4.address, dst=ep3.ip4.address) /
3164 UDP(sport=1234, dport=1234) /
3166 (Ether(src=ep3.mac, dst=ep1.mac) /
3167 IP(src=ep3.ip4.address, dst=ep1.ip4.address) /
3168 UDP(sport=1234, dport=1234) /
3170 p6 = [(Ether(src=ep1.mac, dst=ep3.mac) /
3171 IPv6(src=ep1.ip6.address, dst=ep3.ip6.address) /
3172 UDP(sport=1234, dport=1234) /
3174 (Ether(src=ep3.mac, dst=ep1.mac) /
3175 IPv6(src=ep3.ip6.address, dst=ep1.ip6.address) /
3176 UDP(sport=1234, dport=1230) /
3179 # should be dropped since no contract yet
3180 self.send_and_assert_no_replies(self.pg0, [p4[0]])
3181 self.send_and_assert_no_replies(self.pg0, [p6[0]])
3184 # Add a contract with a rule to load-balance redirect via SEP1 and SEP2
3185 # one of the next-hops is via an EP that is not known
3187 acl = VppGbpAcl(self)
3188 rule4 = acl.create_rule(permit_deny=1, proto=17)
3189 rule6 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
3190 acl_index = acl.add_vpp_config([rule4, rule6])
3193 # test the src-ip hash mode
3195 c1 = VppGbpContract(
3196 self, 402, epg_220.sclass, epg_222.sclass, acl_index,
3197 [VppGbpContractRule(
3198 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3199 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3200 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3201 sep1.ip4, sep1.epg.rd),
3202 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3203 sep2.ip4, sep2.epg.rd)]),
3205 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3206 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3207 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3208 sep3.ip6, sep3.epg.rd),
3209 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3210 sep4.ip6, sep4.epg.rd)])],
3211 [ETH_P_IP, ETH_P_IPV6])
3214 c2 = VppGbpContract(
3215 self, 402, epg_222.sclass, epg_220.sclass, acl_index,
3216 [VppGbpContractRule(
3217 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3218 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3219 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3220 sep1.ip4, sep1.epg.rd),
3221 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3222 sep2.ip4, sep2.epg.rd)]),
3224 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3225 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3226 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3227 sep3.ip6, sep3.epg.rd),
3228 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3229 sep4.ip6, sep4.epg.rd)])],
3230 [ETH_P_IP, ETH_P_IPV6])
3234 # send again with the contract preset, now packets arrive
3235 # at SEP1 or SEP2 depending on the hashing
3237 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3240 self.assertEqual(rx[Ether].src, routed_src_mac)
3241 self.assertEqual(rx[Ether].dst, sep1.mac)
3242 self.assertEqual(rx[IP].src, ep1.ip4.address)
3243 self.assertEqual(rx[IP].dst, ep3.ip4.address)
3245 rxs = self.send_and_expect(self.pg2, p4[1] * 17, sep2.itf)
3248 self.assertEqual(rx[Ether].src, routed_src_mac)
3249 self.assertEqual(rx[Ether].dst, sep2.mac)
3250 self.assertEqual(rx[IP].src, ep3.ip4.address)
3251 self.assertEqual(rx[IP].dst, ep1.ip4.address)
3253 rxs = self.send_and_expect(self.pg0, p6[0] * 17, self.pg7)
3256 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3257 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3258 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3259 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
3260 self.assertEqual(rx[VXLAN].vni, 117)
3261 self.assertTrue(rx[VXLAN].flags.G)
3262 self.assertTrue(rx[VXLAN].flags.Instance)
3263 # redirect policy has been applied
3264 self.assertTrue(rx[VXLAN].gpflags.A)
3265 self.assertFalse(rx[VXLAN].gpflags.D)
3267 inner = rx[VXLAN].payload
3269 self.assertEqual(inner[Ether].src, routed_src_mac)
3270 self.assertEqual(inner[Ether].dst, sep4.mac)
3271 self.assertEqual(inner[IPv6].src, ep1.ip6.address)
3272 self.assertEqual(inner[IPv6].dst, ep3.ip6.address)
3274 rxs = self.send_and_expect(self.pg2, p6[1] * 17, sep3.itf)
3277 self.assertEqual(rx[Ether].src, routed_src_mac)
3278 self.assertEqual(rx[Ether].dst, sep3.mac)
3279 self.assertEqual(rx[IPv6].src, ep3.ip6.address)
3280 self.assertEqual(rx[IPv6].dst, ep1.ip6.address)
3283 # programme the unknown EP
3285 sep4.add_vpp_config()
3287 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep4.itf)
3290 self.assertEqual(rx[Ether].src, routed_src_mac)
3291 self.assertEqual(rx[Ether].dst, sep4.mac)
3292 self.assertEqual(rx[IPv6].src, ep1.ip6.address)
3293 self.assertEqual(rx[IPv6].dst, ep3.ip6.address)
3296 # and revert back to unprogrammed
3298 sep4.remove_vpp_config()
3300 rxs = self.send_and_expect(self.pg0, p6[0] * 17, self.pg7)
3303 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3304 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3305 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3306 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
3307 self.assertEqual(rx[VXLAN].vni, 117)
3308 self.assertTrue(rx[VXLAN].flags.G)
3309 self.assertTrue(rx[VXLAN].flags.Instance)
3310 # redirect policy has been applied
3311 self.assertTrue(rx[VXLAN].gpflags.A)
3312 self.assertFalse(rx[VXLAN].gpflags.D)
3314 inner = rx[VXLAN].payload
3316 self.assertEqual(inner[Ether].src, routed_src_mac)
3317 self.assertEqual(inner[Ether].dst, sep4.mac)
3318 self.assertEqual(inner[IPv6].src, ep1.ip6.address)
3319 self.assertEqual(inner[IPv6].dst, ep3.ip6.address)
3321 c1.remove_vpp_config()
3322 c2.remove_vpp_config()
3325 # test the symmetric hash mode
3327 c1 = VppGbpContract(
3328 self, 402, epg_220.sclass, epg_222.sclass, acl_index,
3329 [VppGbpContractRule(
3330 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3331 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3332 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3333 sep1.ip4, sep1.epg.rd),
3334 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3335 sep2.ip4, sep2.epg.rd)]),
3337 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3338 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3339 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3340 sep3.ip6, sep3.epg.rd),
3341 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3342 sep4.ip6, sep4.epg.rd)])],
3343 [ETH_P_IP, ETH_P_IPV6])
3346 c2 = VppGbpContract(
3347 self, 402, epg_222.sclass, epg_220.sclass, acl_index,
3348 [VppGbpContractRule(
3349 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3350 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3351 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3352 sep1.ip4, sep1.epg.rd),
3353 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3354 sep2.ip4, sep2.epg.rd)]),
3356 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3357 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3358 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3359 sep3.ip6, sep3.epg.rd),
3360 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3361 sep4.ip6, sep4.epg.rd)])],
3362 [ETH_P_IP, ETH_P_IPV6])
3366 # send again with the contract preset, now packets arrive
3367 # at SEP1 for both directions
3369 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3372 self.assertEqual(rx[Ether].src, routed_src_mac)
3373 self.assertEqual(rx[Ether].dst, sep1.mac)
3374 self.assertEqual(rx[IP].src, ep1.ip4.address)
3375 self.assertEqual(rx[IP].dst, ep3.ip4.address)
3377 rxs = self.send_and_expect(self.pg2, p4[1] * 17, sep1.itf)
3380 self.assertEqual(rx[Ether].src, routed_src_mac)
3381 self.assertEqual(rx[Ether].dst, sep1.mac)
3382 self.assertEqual(rx[IP].src, ep3.ip4.address)
3383 self.assertEqual(rx[IP].dst, ep1.ip4.address)
3386 # programme the unknown EP for the L3 tests
3388 sep4.add_vpp_config()
3391 # an L3 switch packet between local EPs in different EPGs
3392 # different dest ports on each so the are LB hashed differently
3394 p4 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3395 IP(src=ep1.ip4.address, dst=ep2.ip4.address) /
3396 UDP(sport=1234, dport=1234) /
3398 (Ether(src=ep2.mac, dst=str(self.router_mac)) /
3399 IP(src=ep2.ip4.address, dst=ep1.ip4.address) /
3400 UDP(sport=1234, dport=1234) /
3402 p6 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3403 IPv6(src=ep1.ip6.address, dst=ep2.ip6.address) /
3404 UDP(sport=1234, dport=1234) /
3406 (Ether(src=ep2.mac, dst=str(self.router_mac)) /
3407 IPv6(src=ep2.ip6.address, dst=ep1.ip6.address) /
3408 UDP(sport=1234, dport=1234) /
3411 c3 = VppGbpContract(
3412 self, 402, epg_220.sclass, epg_221.sclass, acl_index,
3413 [VppGbpContractRule(
3414 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3415 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3416 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3417 sep1.ip4, sep1.epg.rd),
3418 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3419 sep2.ip4, sep2.epg.rd)]),
3421 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3422 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3423 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3424 sep3.ip6, sep3.epg.rd),
3425 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3426 sep4.ip6, sep4.epg.rd)])],
3427 [ETH_P_IP, ETH_P_IPV6])
3430 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3433 self.assertEqual(rx[Ether].src, routed_src_mac)
3434 self.assertEqual(rx[Ether].dst, sep1.mac)
3435 self.assertEqual(rx[IP].src, ep1.ip4.address)
3436 self.assertEqual(rx[IP].dst, ep2.ip4.address)
3439 # learn a remote EP in EPG 221
3441 vx_tun_l3 = VppGbpVxlanTunnel(
3442 self, 444, rd1.rd_id,
3443 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
3445 vx_tun_l3.add_vpp_config()
3447 c4 = VppGbpContract(
3448 self, 402, epg_221.sclass, epg_220.sclass, acl_index,
3449 [VppGbpContractRule(
3450 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3451 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3454 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3455 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3457 [ETH_P_IP, ETH_P_IPV6])
3460 p = (Ether(src=self.pg7.remote_mac,
3461 dst=self.pg7.local_mac) /
3462 IP(src=self.pg7.remote_ip4,
3463 dst=self.pg7.local_ip4) /
3464 UDP(sport=1234, dport=48879) /
3465 VXLAN(vni=444, gpid=441, flags=0x88) /
3466 Ether(src="00:22:22:22:22:33", dst=str(self.router_mac)) /
3467 IP(src="10.0.0.88", dst=ep1.ip4.address) /
3468 UDP(sport=1234, dport=1234) /
3471 rx = self.send_and_expect(self.pg7, [p], self.pg0)
3473 # endpoint learnt via the parent GBP-vxlan interface
3474 self.assertTrue(find_gbp_endpoint(self,
3475 vx_tun_l3._sw_if_index,
3478 p = (Ether(src=self.pg7.remote_mac,
3479 dst=self.pg7.local_mac) /
3480 IP(src=self.pg7.remote_ip4,
3481 dst=self.pg7.local_ip4) /
3482 UDP(sport=1234, dport=48879) /
3483 VXLAN(vni=444, gpid=441, flags=0x88) /
3484 Ether(src="00:22:22:22:22:33", dst=str(self.router_mac)) /
3485 IPv6(src="2001:10::88", dst=ep1.ip6.address) /
3486 UDP(sport=1234, dport=1234) /
3489 rx = self.send_and_expect(self.pg7, [p], self.pg0)
3491 # endpoint learnt via the parent GBP-vxlan interface
3492 self.assertTrue(find_gbp_endpoint(self,
3493 vx_tun_l3._sw_if_index,
3497 # L3 switch from local to remote EP
3499 p4 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3500 IP(src=ep1.ip4.address, dst="10.0.0.88") /
3501 UDP(sport=1234, dport=1234) /
3503 p6 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3504 IPv6(src=ep1.ip6.address, dst="2001:10::88") /
3505 UDP(sport=1234, dport=1234) /
3508 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3511 self.assertEqual(rx[Ether].src, routed_src_mac)
3512 self.assertEqual(rx[Ether].dst, sep1.mac)
3513 self.assertEqual(rx[IP].src, ep1.ip4.address)
3514 self.assertEqual(rx[IP].dst, "10.0.0.88")
3516 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep4.itf)
3519 self.assertEqual(rx[Ether].src, routed_src_mac)
3520 self.assertEqual(rx[Ether].dst, sep4.mac)
3521 self.assertEqual(rx[IPv6].src, ep1.ip6.address)
3522 self.assertEqual(rx[IPv6].dst, "2001:10::88")
3525 # test the dst-ip hash mode
3527 c5 = VppGbpContract(
3528 self, 402, epg_220.sclass, epg_221.sclass, acl_index,
3529 [VppGbpContractRule(
3530 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3531 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
3532 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3533 sep1.ip4, sep1.epg.rd),
3534 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3535 sep2.ip4, sep2.epg.rd)]),
3537 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3538 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
3539 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3540 sep3.ip6, sep3.epg.rd),
3541 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3542 sep4.ip6, sep4.epg.rd)])],
3543 [ETH_P_IP, ETH_P_IPV6])
3546 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3549 self.assertEqual(rx[Ether].src, routed_src_mac)
3550 self.assertEqual(rx[Ether].dst, sep1.mac)
3551 self.assertEqual(rx[IP].src, ep1.ip4.address)
3552 self.assertEqual(rx[IP].dst, "10.0.0.88")
3554 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep3.itf)
3557 self.assertEqual(rx[Ether].src, routed_src_mac)
3558 self.assertEqual(rx[Ether].dst, sep3.mac)
3559 self.assertEqual(rx[IPv6].src, ep1.ip6.address)
3560 self.assertEqual(rx[IPv6].dst, "2001:10::88")
3565 self.pg7.unconfig_ip4()
3567 def test_gbp_l3_out(self):
3570 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
3571 self.vapi.cli("set logging class gbp level debug")
3573 routed_dst_mac = "00:0c:0c:0c:0c:0c"
3574 routed_src_mac = "00:22:bd:f8:19:ff"
3579 t4 = VppIpTable(self, 1)
3581 t6 = VppIpTable(self, 1, True)
3584 rd1 = VppGbpRouteDomain(self, 2, 55, t4, t6)
3585 rd1.add_vpp_config()
3587 self.loop0.set_mac(self.router_mac)
3590 # Bind the BVI to the RD
3592 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
3593 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
3596 # Pg7 hosts a BD's BUM
3597 # Pg1 some other l3 interface
3599 self.pg7.config_ip4()
3600 self.pg7.resolve_arp()
3603 # a multicast vxlan-gbp tunnel for broadcast in the BD
3605 tun_bm = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
3608 tun_bm.add_vpp_config()
3611 # a GBP external bridge domains for the EPs
3613 bd1 = VppBridgeDomain(self, 1)
3614 bd1.add_vpp_config()
3615 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0, None, tun_bm)
3616 gbd1.add_vpp_config()
3619 # The Endpoint-groups in which the external endpoints exist
3621 epg_220 = VppGbpEndpointGroup(self, 220, 113, rd1, gbd1,
3625 VppGbpEndpointRetention(2))
3626 epg_220.add_vpp_config()
3628 # the BVIs have the subnets applied ...
3629 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 24)
3630 ip4_addr.add_vpp_config()
3631 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 64)
3632 ip6_addr.add_vpp_config()
3634 # ... which are L3-out subnets
3635 l3o_1 = VppGbpSubnet(
3636 self, rd1, "10.0.0.0", 24,
3637 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3639 l3o_1.add_vpp_config()
3642 # an external interface attached to the outside world and the
3645 VppL2Vtr(self, self.vlan_100, L2_VTR_OP.L2_POP_1).add_vpp_config()
3646 VppL2Vtr(self, self.vlan_101, L2_VTR_OP.L2_POP_1).add_vpp_config()
3647 # vlan_102 is not poped
3649 ext_itf = VppGbpExtItf(self, self.loop0, bd1, rd1)
3650 ext_itf.add_vpp_config()
3653 # an unicast vxlan-gbp for inter-RD traffic
3655 vx_tun_l3 = VppGbpVxlanTunnel(
3656 self, 444, rd1.rd_id,
3657 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
3659 vx_tun_l3.add_vpp_config()
3662 # External Endpoints
3664 eep1 = VppGbpEndpoint(self, self.vlan_100,
3666 "10.0.0.1", "11.0.0.1",
3667 "2001:10::1", "3001::1",
3668 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
3669 eep1.add_vpp_config()
3670 eep2 = VppGbpEndpoint(self, self.vlan_101,
3672 "10.0.0.2", "11.0.0.2",
3673 "2001:10::2", "3001::2",
3674 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
3675 eep2.add_vpp_config()
3676 eep3 = VppGbpEndpoint(self, self.vlan_102,
3678 "10.0.0.3", "11.0.0.3",
3679 "2001:10::3", "3001::3",
3680 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
3681 eep3.add_vpp_config()
3684 # A remote external endpoint
3686 rep = VppGbpEndpoint(self, vx_tun_l3,
3688 "10.0.0.101", "11.0.0.101",
3689 "2001:10::101", "3001::101",
3690 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
3692 self.pg7.remote_ip4,
3694 rep.add_vpp_config()
3697 # EP1 impersonating EP3 is dropped
3699 p = (Ether(src=eep1.mac, dst="ff:ff:ff:ff:ff:ff") /
3702 psrc="10.0.0.3", pdst="10.0.0.128",
3703 hwsrc=eep1.mac, hwdst="ff:ff:ff:ff:ff:ff"))
3704 self.send_and_assert_no_replies(self.pg0, p)
3707 # ARP packet from External EPs are accepted and replied to
3709 p_arp = (Ether(src=eep1.mac, dst="ff:ff:ff:ff:ff:ff") /
3712 psrc=eep1.ip4.address, pdst="10.0.0.128",
3713 hwsrc=eep1.mac, hwdst="ff:ff:ff:ff:ff:ff"))
3714 rxs = self.send_and_expect(self.pg0, p_arp * 1, self.pg0)
3717 # ARP packet from host in remote subnet are accepted and replied to
3719 p_arp = (Ether(src=eep3.mac, dst="ff:ff:ff:ff:ff:ff") /
3722 psrc=eep3.ip4.address, pdst="10.0.0.128",
3723 hwsrc=eep3.mac, hwdst="ff:ff:ff:ff:ff:ff"))
3724 rxs = self.send_and_expect(self.pg0, p_arp * 1, self.pg0)
3727 # packets destined to unknown addresses in the BVI's subnet
3730 p4 = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3732 IP(src="10.0.0.1", dst="10.0.0.88") /
3733 UDP(sport=1234, dport=1234) /
3735 p6 = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3737 IPv6(src="2001:10::1", dst="2001:10::88") /
3738 UDP(sport=1234, dport=1234) /
3741 rxs = self.send_and_expect(self.pg0, p4 * 1, self.pg7)
3744 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3745 # self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3746 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3747 self.assertEqual(rx[IP].dst, "239.1.1.1")
3748 self.assertEqual(rx[VXLAN].vni, 88)
3749 self.assertTrue(rx[VXLAN].flags.G)
3750 self.assertTrue(rx[VXLAN].flags.Instance)
3751 # policy was applied to the original IP packet
3752 self.assertEqual(rx[VXLAN].gpid, 113)
3753 self.assertTrue(rx[VXLAN].gpflags.A)
3754 self.assertFalse(rx[VXLAN].gpflags.D)
3756 inner = rx[VXLAN].payload
3758 self.assertTrue(inner.haslayer(ARP))
3761 # remote to external
3763 p = (Ether(src=self.pg7.remote_mac,
3764 dst=self.pg7.local_mac) /
3765 IP(src=self.pg7.remote_ip4,
3766 dst=self.pg7.local_ip4) /
3767 UDP(sport=1234, dport=48879) /
3768 VXLAN(vni=444, gpid=113, flags=0x88) /
3769 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
3770 IP(src="10.0.0.101", dst="10.0.0.1") /
3771 UDP(sport=1234, dport=1234) /
3774 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
3777 # local EP pings router
3779 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3781 IP(src=eep1.ip4.address, dst="10.0.0.128") /
3782 ICMP(type='echo-request'))
3784 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
3787 self.assertEqual(rx[Ether].src, str(self.router_mac))
3788 self.assertEqual(rx[Ether].dst, eep1.mac)
3789 self.assertEqual(rx[Dot1Q].vlan, 100)
3792 # local EP pings other local EP
3794 p = (Ether(src=eep1.mac, dst=eep2.mac) /
3796 IP(src=eep1.ip4.address, dst=eep2.ip4.address) /
3797 ICMP(type='echo-request'))
3799 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
3802 self.assertEqual(rx[Ether].src, eep1.mac)
3803 self.assertEqual(rx[Ether].dst, eep2.mac)
3804 self.assertEqual(rx[Dot1Q].vlan, 101)
3807 # local EP pings router w/o vlan tag poped
3809 p = (Ether(src=eep3.mac, dst=str(self.router_mac)) /
3811 IP(src=eep3.ip4.address, dst="10.0.0.128") /
3812 ICMP(type='echo-request'))
3814 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
3817 self.assertEqual(rx[Ether].src, str(self.router_mac))
3818 self.assertEqual(rx[Ether].dst, self.vlan_102.remote_mac)
3821 # A subnet reachable through the external EP1
3823 ip_220 = VppIpRoute(self, "10.220.0.0", 24,
3824 [VppRoutePath(eep1.ip4.address,
3825 eep1.epg.bvi.sw_if_index)],
3826 table_id=t4.table_id)
3827 ip_220.add_vpp_config()
3829 l3o_220 = VppGbpSubnet(
3830 self, rd1, "10.220.0.0", 24,
3831 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3833 l3o_220.add_vpp_config()
3836 # A subnet reachable through the external EP2
3838 ip_221 = VppIpRoute(self, "10.221.0.0", 24,
3839 [VppRoutePath(eep2.ip4.address,
3840 eep2.epg.bvi.sw_if_index)],
3841 table_id=t4.table_id)
3842 ip_221.add_vpp_config()
3844 l3o_221 = VppGbpSubnet(
3845 self, rd1, "10.221.0.0", 24,
3846 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3848 l3o_221.add_vpp_config()
3851 # ping between hosts in remote subnets
3852 # dropped without a contract
3854 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3856 IP(src="10.220.0.1", dst="10.221.0.1") /
3857 ICMP(type='echo-request'))
3859 self.send_and_assert_no_replies(self.pg0, p * 1)
3862 # contract for the external nets to communicate
3864 acl = VppGbpAcl(self)
3865 rule4 = acl.create_rule(permit_deny=1, proto=17)
3866 rule6 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
3867 acl_index = acl.add_vpp_config([rule4, rule6])
3870 # A contract with the wrong scope is not matched
3872 c_44 = VppGbpContract(
3873 self, 44, 4220, 4221, acl_index,
3874 [VppGbpContractRule(
3875 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3878 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3880 [ETH_P_IP, ETH_P_IPV6])
3881 c_44.add_vpp_config()
3882 self.send_and_assert_no_replies(self.pg0, p * 1)
3884 c1 = VppGbpContract(
3885 self, 55, 4220, 4221, acl_index,
3886 [VppGbpContractRule(
3887 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3888 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3891 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3892 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3894 [ETH_P_IP, ETH_P_IPV6])
3898 # Contracts allowing ext-net 200 to talk with external EPs
3900 c2 = VppGbpContract(
3901 self, 55, 4220, 113, acl_index,
3902 [VppGbpContractRule(
3903 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3904 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3907 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3908 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3910 [ETH_P_IP, ETH_P_IPV6])
3912 c3 = VppGbpContract(
3913 self, 55, 113, 4220, acl_index,
3914 [VppGbpContractRule(
3915 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3916 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3919 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3920 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3922 [ETH_P_IP, ETH_P_IPV6])
3926 # ping between hosts in remote subnets
3928 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3930 IP(src="10.220.0.1", dst="10.221.0.1") /
3931 UDP(sport=1234, dport=1234) /
3934 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
3937 self.assertEqual(rx[Ether].src, str(self.router_mac))
3938 self.assertEqual(rx[Ether].dst, eep2.mac)
3939 self.assertEqual(rx[Dot1Q].vlan, 101)
3941 # we did not learn these external hosts
3942 self.assertFalse(find_gbp_endpoint(self, ip="10.220.0.1"))
3943 self.assertFalse(find_gbp_endpoint(self, ip="10.221.0.1"))
3946 # from remote external EP to local external EP
3948 p = (Ether(src=self.pg7.remote_mac,
3949 dst=self.pg7.local_mac) /
3950 IP(src=self.pg7.remote_ip4,
3951 dst=self.pg7.local_ip4) /
3952 UDP(sport=1234, dport=48879) /
3953 VXLAN(vni=444, gpid=113, flags=0x88) /
3954 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
3955 IP(src="10.0.0.101", dst="10.220.0.1") /
3956 UDP(sport=1234, dport=1234) /
3959 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
3962 # ping from an external host to the remote external EP
3964 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3966 IP(src="10.220.0.1", dst=rep.ip4.address) /
3967 UDP(sport=1234, dport=1234) /
3970 rxs = self.send_and_expect(self.pg0, p * 1, self.pg7)
3973 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3974 # self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3975 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3976 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
3977 self.assertEqual(rx[VXLAN].vni, 444)
3978 self.assertTrue(rx[VXLAN].flags.G)
3979 self.assertTrue(rx[VXLAN].flags.Instance)
3980 # the sclass of the ext-net the packet came from
3981 self.assertEqual(rx[VXLAN].gpid, 4220)
3982 # policy was applied to the original IP packet
3983 self.assertTrue(rx[VXLAN].gpflags.A)
3984 # since it's an external host the reciever should not learn it
3985 self.assertTrue(rx[VXLAN].gpflags.D)
3986 inner = rx[VXLAN].payload
3987 self.assertEqual(inner[IP].src, "10.220.0.1")
3988 self.assertEqual(inner[IP].dst, rep.ip4.address)
3991 # An external subnet reachable via the remote external EP
3995 # first the VXLAN-GBP tunnel over which it is reached
3997 vx_tun_r = VppVxlanGbpTunnel(
3998 self, self.pg7.local_ip4,
3999 self.pg7.remote_ip4, 445,
4000 mode=(VppEnum.vl_api_vxlan_gbp_api_tunnel_mode_t.
4001 VXLAN_GBP_API_TUNNEL_MODE_L3))
4002 vx_tun_r.add_vpp_config()
4003 VppIpInterfaceBind(self, vx_tun_r, t4).add_vpp_config()
4005 self.logger.info(self.vapi.cli("sh vxlan-gbp tunnel"))
4008 # then the special adj to resolve through on that tunnel
4010 n1 = VppNeighbor(self,
4011 vx_tun_r.sw_if_index,
4012 "00:0c:0c:0c:0c:0c",
4013 self.pg7.remote_ip4)
4017 # the route via the adj above
4019 ip_222 = VppIpRoute(self, "10.222.0.0", 24,
4020 [VppRoutePath(self.pg7.remote_ip4,
4021 vx_tun_r.sw_if_index)],
4022 table_id=t4.table_id)
4023 ip_222.add_vpp_config()
4025 l3o_222 = VppGbpSubnet(
4026 self, rd1, "10.222.0.0", 24,
4027 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
4029 l3o_222.add_vpp_config()
4032 # ping between hosts in local and remote external subnets
4033 # dropped without a contract
4035 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
4037 IP(src="10.220.0.1", dst="10.222.0.1") /
4038 UDP(sport=1234, dport=1234) /
4041 rxs = self.send_and_assert_no_replies(self.pg0, p * 1)
4044 # Add contracts ext-nets for 220 -> 222
4046 c4 = VppGbpContract(
4047 self, 55, 4220, 4222, acl_index,
4048 [VppGbpContractRule(
4049 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4050 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4053 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4054 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4056 [ETH_P_IP, ETH_P_IPV6])
4060 # ping from host in local to remote external subnets
4062 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
4064 IP(src="10.220.0.1", dst="10.222.0.1") /
4065 UDP(sport=1234, dport=1234) /
4068 rxs = self.send_and_expect(self.pg0, p * 3, self.pg7)
4071 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4072 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4073 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4074 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4075 self.assertEqual(rx[VXLAN].vni, 445)
4076 self.assertTrue(rx[VXLAN].flags.G)
4077 self.assertTrue(rx[VXLAN].flags.Instance)
4078 # the sclass of the ext-net the packet came from
4079 self.assertEqual(rx[VXLAN].gpid, 4220)
4080 # policy was applied to the original IP packet
4081 self.assertTrue(rx[VXLAN].gpflags.A)
4082 # since it's an external host the reciever should not learn it
4083 self.assertTrue(rx[VXLAN].gpflags.D)
4084 inner = rx[VXLAN].payload
4085 self.assertEqual(inner[Ether].dst, "00:0c:0c:0c:0c:0c")
4086 self.assertEqual(inner[IP].src, "10.220.0.1")
4087 self.assertEqual(inner[IP].dst, "10.222.0.1")
4090 # ping from host in remote to local external subnets
4091 # there's no contract for this, but the A bit is set.
4093 p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
4094 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
4095 UDP(sport=1234, dport=48879) /
4096 VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
4097 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
4098 IP(src="10.222.0.1", dst="10.220.0.1") /
4099 UDP(sport=1234, dport=1234) /
4102 rxs = self.send_and_expect(self.pg7, p * 3, self.pg0)
4103 self.assertFalse(find_gbp_endpoint(self, ip="10.222.0.1"))
4106 # ping from host in remote to remote external subnets
4107 # this is dropped by reflection check.
4109 p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
4110 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
4111 UDP(sport=1234, dport=48879) /
4112 VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
4113 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
4114 IP(src="10.222.0.1", dst="10.222.0.2") /
4115 UDP(sport=1234, dport=1234) /
4118 rxs = self.send_and_assert_no_replies(self.pg7, p * 3)
4123 self.pg7.unconfig_ip4()
4124 self.vlan_101.set_vtr(L2_VTR_OP.L2_DISABLED)
4125 self.vlan_100.set_vtr(L2_VTR_OP.L2_DISABLED)
4127 def test_gbp_anon_l3_out(self):
4128 """ GBP Anonymous L3 Out """
4130 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
4131 self.vapi.cli("set logging class gbp level debug")
4133 routed_dst_mac = "00:0c:0c:0c:0c:0c"
4134 routed_src_mac = "00:22:bd:f8:19:ff"
4139 t4 = VppIpTable(self, 1)
4141 t6 = VppIpTable(self, 1, True)
4144 rd1 = VppGbpRouteDomain(self, 2, 55, t4, t6)
4145 rd1.add_vpp_config()
4147 self.loop0.set_mac(self.router_mac)
4150 # Bind the BVI to the RD
4152 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
4153 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
4156 # Pg7 hosts a BD's BUM
4157 # Pg1 some other l3 interface
4159 self.pg7.config_ip4()
4160 self.pg7.resolve_arp()
4163 # a GBP external bridge domains for the EPs
4165 bd1 = VppBridgeDomain(self, 1)
4166 bd1.add_vpp_config()
4167 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0, None, None)
4168 gbd1.add_vpp_config()
4171 # The Endpoint-groups in which the external endpoints exist
4173 epg_220 = VppGbpEndpointGroup(self, 220, 113, rd1, gbd1,
4177 VppGbpEndpointRetention(2))
4178 epg_220.add_vpp_config()
4180 # the BVIs have the subnet applied ...
4181 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 24)
4182 ip4_addr.add_vpp_config()
4184 # ... which is an Anonymous L3-out subnets
4185 l3o_1 = VppGbpSubnet(
4186 self, rd1, "10.0.0.0", 24,
4187 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_ANON_L3_OUT,
4189 l3o_1.add_vpp_config()
4192 # an external interface attached to the outside world and the
4195 VppL2Vtr(self, self.vlan_100, L2_VTR_OP.L2_POP_1).add_vpp_config()
4196 VppL2Vtr(self, self.vlan_101, L2_VTR_OP.L2_POP_1).add_vpp_config()
4198 ext_itf = VppGbpExtItf(self, self.loop0, bd1, rd1)
4199 ext_itf.add_vpp_config()
4202 # vlan_100 and vlan_101 are anonymous l3-out interfaces
4204 ext_itf = VppGbpExtItf(self, self.vlan_100, bd1, rd1, anon=True)
4205 ext_itf.add_vpp_config()
4206 ext_itf = VppGbpExtItf(self, self.vlan_101, bd1, rd1, anon=True)
4207 ext_itf.add_vpp_config()
4210 # an unicast vxlan-gbp for inter-RD traffic
4212 vx_tun_l3 = VppGbpVxlanTunnel(
4213 self, 444, rd1.rd_id,
4214 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
4216 vx_tun_l3.add_vpp_config()
4219 # A remote external endpoint
4221 rep = VppGbpEndpoint(self, vx_tun_l3,
4223 "10.0.0.201", "11.0.0.201",
4224 "2001:10::201", "3001::101",
4225 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
4227 self.pg7.remote_ip4,
4229 rep.add_vpp_config()
4232 # ARP packet from host in external subnet are accepted, flooded and
4233 # replied to. We expect 2 packets:
4234 # - APR request flooded over the other vlan subif
4235 # - ARP reply from BVI
4237 p_arp = (Ether(src=self.vlan_100.remote_mac,
4238 dst="ff:ff:ff:ff:ff:ff") /
4243 hwsrc=self.vlan_100.remote_mac,
4244 hwdst="ff:ff:ff:ff:ff:ff"))
4245 rxs = self.send_and_expect(self.pg0, p_arp * 1, self.pg0, n_rx=2)
4247 p_arp = (Ether(src=self.vlan_101.remote_mac,
4248 dst="ff:ff:ff:ff:ff:ff") /
4253 hwsrc=self.vlan_101.remote_mac,
4254 hwdst="ff:ff:ff:ff:ff:ff"))
4255 rxs = self.send_and_expect(self.pg0, p_arp * 1, self.pg0, n_rx=2)
4258 # remote to external
4260 p = (Ether(src=self.pg7.remote_mac,
4261 dst=self.pg7.local_mac) /
4262 IP(src=self.pg7.remote_ip4,
4263 dst=self.pg7.local_ip4) /
4264 UDP(sport=1234, dport=48879) /
4265 VXLAN(vni=vx_tun_l3.vni, gpid=epg_220.sclass, flags=0x88) /
4266 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
4267 IP(src=str(rep.ip4), dst="10.0.0.100") /
4268 UDP(sport=1234, dport=1234) /
4270 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
4273 # local EP pings router
4275 p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
4277 IP(src="10.0.0.100", dst="10.0.0.128") /
4278 ICMP(type='echo-request'))
4279 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
4282 self.assertEqual(rx[Ether].src, str(self.router_mac))
4283 self.assertEqual(rx[Ether].dst, self.vlan_100.remote_mac)
4284 self.assertEqual(rx[Dot1Q].vlan, 100)
4287 # local EP pings other local EP
4289 p = (Ether(src=self.vlan_100.remote_mac,
4290 dst=self.vlan_101.remote_mac) /
4292 IP(src="10.0.0.100", dst="10.0.0.101") /
4293 ICMP(type='echo-request'))
4294 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
4297 self.assertEqual(rx[Ether].src, self.vlan_100.remote_mac)
4298 self.assertEqual(rx[Ether].dst, self.vlan_101.remote_mac)
4299 self.assertEqual(rx[Dot1Q].vlan, 101)
4302 # A subnet reachable through an external router on vlan 100
4304 ip_220 = VppIpRoute(self, "10.220.0.0", 24,
4305 [VppRoutePath("10.0.0.100",
4306 epg_220.bvi.sw_if_index)],
4307 table_id=t4.table_id)
4308 ip_220.add_vpp_config()
4310 l3o_220 = VppGbpSubnet(
4311 self, rd1, "10.220.0.0", 24,
4312 # note: this a "regular" L3 out subnet (not connected)
4313 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
4315 l3o_220.add_vpp_config()
4318 # A subnet reachable through an external router on vlan 101
4320 ip_221 = VppIpRoute(self, "10.221.0.0", 24,
4321 [VppRoutePath("10.0.0.101",
4322 epg_220.bvi.sw_if_index)],
4323 table_id=t4.table_id)
4324 ip_221.add_vpp_config()
4326 l3o_221 = VppGbpSubnet(
4327 self, rd1, "10.221.0.0", 24,
4328 # note: this a "regular" L3 out subnet (not connected)
4329 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
4331 l3o_221.add_vpp_config()
4334 # ping between hosts in remote subnets
4335 # dropped without a contract
4337 p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
4339 IP(src="10.220.0.1", dst="10.221.0.1") /
4340 ICMP(type='echo-request'))
4342 rxs = self.send_and_assert_no_replies(self.pg0, p * 1)
4345 # contract for the external nets to communicate
4347 acl = VppGbpAcl(self)
4348 rule4 = acl.create_rule(permit_deny=1, proto=17)
4349 rule6 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
4350 acl_index = acl.add_vpp_config([rule4, rule6])
4352 c1 = VppGbpContract(
4353 self, 55, 4220, 4221, acl_index,
4354 [VppGbpContractRule(
4355 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4356 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4359 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4360 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4362 [ETH_P_IP, ETH_P_IPV6])
4366 # Contracts allowing ext-net 200 to talk with external EPs
4368 c2 = VppGbpContract(
4369 self, 55, 4220, 113, acl_index,
4370 [VppGbpContractRule(
4371 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4372 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4375 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4376 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4378 [ETH_P_IP, ETH_P_IPV6])
4380 c3 = VppGbpContract(
4381 self, 55, 113, 4220, acl_index,
4382 [VppGbpContractRule(
4383 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4384 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4387 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4388 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4390 [ETH_P_IP, ETH_P_IPV6])
4394 # ping between hosts in remote subnets
4396 p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
4398 IP(src="10.220.0.1", dst="10.221.0.1") /
4399 UDP(sport=1234, dport=1234) /
4402 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
4405 self.assertEqual(rx[Ether].src, str(self.router_mac))
4406 self.assertEqual(rx[Ether].dst, self.vlan_101.remote_mac)
4407 self.assertEqual(rx[Dot1Q].vlan, 101)
4409 # we did not learn these external hosts
4410 self.assertFalse(find_gbp_endpoint(self, ip="10.220.0.1"))
4411 self.assertFalse(find_gbp_endpoint(self, ip="10.221.0.1"))
4414 # from remote external EP to local external EP
4416 p = (Ether(src=self.pg7.remote_mac,
4417 dst=self.pg7.local_mac) /
4418 IP(src=self.pg7.remote_ip4,
4419 dst=self.pg7.local_ip4) /
4420 UDP(sport=1234, dport=48879) /
4421 VXLAN(vni=444, gpid=113, flags=0x88) /
4422 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
4423 IP(src=rep.ip4.address, dst="10.220.0.1") /
4424 UDP(sport=1234, dport=1234) /
4427 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
4430 # ping from an external host to the remote external EP
4432 p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
4434 IP(src="10.220.0.1", dst=rep.ip4.address) /
4435 UDP(sport=1234, dport=1234) /
4438 rxs = self.send_and_expect(self.pg0, p * 1, self.pg7)
4441 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4442 # self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4443 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4444 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4445 self.assertEqual(rx[VXLAN].vni, 444)
4446 self.assertTrue(rx[VXLAN].flags.G)
4447 self.assertTrue(rx[VXLAN].flags.Instance)
4448 # the sclass of the ext-net the packet came from
4449 self.assertEqual(rx[VXLAN].gpid, 4220)
4450 # policy was applied to the original IP packet
4451 self.assertTrue(rx[VXLAN].gpflags.A)
4452 # since it's an external host the reciever should not learn it
4453 self.assertTrue(rx[VXLAN].gpflags.D)
4454 inner = rx[VXLAN].payload
4455 self.assertEqual(inner[IP].src, "10.220.0.1")
4456 self.assertEqual(inner[IP].dst, rep.ip4.address)
4459 # An external subnet reachable via the remote external EP
4463 # first the VXLAN-GBP tunnel over which it is reached
4465 vx_tun_r = VppVxlanGbpTunnel(
4466 self, self.pg7.local_ip4,
4467 self.pg7.remote_ip4, 445,
4468 mode=(VppEnum.vl_api_vxlan_gbp_api_tunnel_mode_t.
4469 VXLAN_GBP_API_TUNNEL_MODE_L3))
4470 vx_tun_r.add_vpp_config()
4471 VppIpInterfaceBind(self, vx_tun_r, t4).add_vpp_config()
4473 self.logger.info(self.vapi.cli("sh vxlan-gbp tunnel"))
4476 # then the special adj to resolve through on that tunnel
4478 n1 = VppNeighbor(self,
4479 vx_tun_r.sw_if_index,
4480 "00:0c:0c:0c:0c:0c",
4481 self.pg7.remote_ip4)
4485 # the route via the adj above
4487 ip_222 = VppIpRoute(self, "10.222.0.0", 24,
4488 [VppRoutePath(self.pg7.remote_ip4,
4489 vx_tun_r.sw_if_index)],
4490 table_id=t4.table_id)
4491 ip_222.add_vpp_config()
4493 l3o_222 = VppGbpSubnet(
4494 self, rd1, "10.222.0.0", 24,
4495 # note: this a "regular" l3out subnet (not connected)
4496 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
4498 l3o_222.add_vpp_config()
4501 # ping between hosts in local and remote external subnets
4502 # dropped without a contract
4504 p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
4506 IP(src="10.220.0.1", dst="10.222.0.1") /
4507 UDP(sport=1234, dport=1234) /
4510 rxs = self.send_and_assert_no_replies(self.pg0, p * 1)
4513 # Add contracts ext-nets for 220 -> 222
4515 c4 = VppGbpContract(
4516 self, 55, 4220, 4222, acl_index,
4517 [VppGbpContractRule(
4518 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4519 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4522 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4523 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4525 [ETH_P_IP, ETH_P_IPV6])
4529 # ping from host in local to remote external subnets
4531 p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
4533 IP(src="10.220.0.1", dst="10.222.0.1") /
4534 UDP(sport=1234, dport=1234) /
4537 rxs = self.send_and_expect(self.pg0, p * 3, self.pg7)
4540 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4541 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4542 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4543 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4544 self.assertEqual(rx[VXLAN].vni, 445)
4545 self.assertTrue(rx[VXLAN].flags.G)
4546 self.assertTrue(rx[VXLAN].flags.Instance)
4547 # the sclass of the ext-net the packet came from
4548 self.assertEqual(rx[VXLAN].gpid, 4220)
4549 # policy was applied to the original IP packet
4550 self.assertTrue(rx[VXLAN].gpflags.A)
4551 # since it's an external host the reciever should not learn it
4552 self.assertTrue(rx[VXLAN].gpflags.D)
4553 inner = rx[VXLAN].payload
4554 self.assertEqual(inner[Ether].dst, "00:0c:0c:0c:0c:0c")
4555 self.assertEqual(inner[IP].src, "10.220.0.1")
4556 self.assertEqual(inner[IP].dst, "10.222.0.1")
4559 # ping from host in remote to local external subnets
4560 # there's no contract for this, but the A bit is set.
4562 p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
4563 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
4564 UDP(sport=1234, dport=48879) /
4565 VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
4566 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
4567 IP(src="10.222.0.1", dst="10.220.0.1") /
4568 UDP(sport=1234, dport=1234) /
4571 rxs = self.send_and_expect(self.pg7, p * 3, self.pg0)
4572 self.assertFalse(find_gbp_endpoint(self, ip="10.222.0.1"))
4575 # ping from host in remote to remote external subnets
4576 # this is dropped by reflection check.
4578 p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
4579 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
4580 UDP(sport=1234, dport=48879) /
4581 VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
4582 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
4583 IP(src="10.222.0.1", dst="10.222.0.2") /
4584 UDP(sport=1234, dport=1234) /
4587 rxs = self.send_and_assert_no_replies(self.pg7, p * 3)
4592 self.vlan_101.set_vtr(L2_VTR_OP.L2_DISABLED)
4593 self.vlan_100.set_vtr(L2_VTR_OP.L2_DISABLED)
4594 self.pg7.unconfig_ip4()
4597 if __name__ == '__main__':
4598 unittest.main(testRunner=VppTestRunner)