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, \
10 ICMPv6ND_NA, ICMPv6EchoRequest
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, DpoProto
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,
332 uu_drop=False, bm_drop=False,
337 self.bm_flood = bm_flood
341 e = VppEnum.vl_api_gbp_bridge_domain_flags_t
343 self.flags = e.GBP_BD_API_FLAG_NONE
345 self.flags |= e.GBP_BD_API_FLAG_DO_NOT_LEARN
347 self.flags |= e.GBP_BD_API_FLAG_UU_FWD_DROP
349 self.flags |= e.GBP_BD_API_FLAG_MCAST_DROP
351 self.flags |= e.GBP_BD_API_FLAG_UCAST_ARP
353 def add_vpp_config(self):
354 self._test.vapi.gbp_bridge_domain_add(
358 self.bvi.sw_if_index,
359 self.uu_fwd.sw_if_index if self.uu_fwd else INDEX_INVALID,
360 self.bm_flood.sw_if_index if self.bm_flood else INDEX_INVALID)
361 self._test.registry.register(self, self._test.logger)
363 def remove_vpp_config(self):
364 self._test.vapi.gbp_bridge_domain_del(self.bd.bd_id)
367 return "gbp-bridge-domain:[%d]" % (self.bd.bd_id)
369 def query_vpp_config(self):
370 bds = self._test.vapi.gbp_bridge_domain_dump()
372 if bd.bd.bd_id == self.bd.bd_id:
377 class VppGbpRouteDomain(VppObject):
382 def __init__(self, test, rd_id, scope, t4, t6, ip4_uu=None, ip6_uu=None):
391 def add_vpp_config(self):
392 self._test.vapi.gbp_route_domain_add(
397 self.ip4_uu.sw_if_index if self.ip4_uu else INDEX_INVALID,
398 self.ip6_uu.sw_if_index if self.ip6_uu else INDEX_INVALID)
399 self._test.registry.register(self, self._test.logger)
401 def remove_vpp_config(self):
402 self._test.vapi.gbp_route_domain_del(self.rd_id)
405 return "gbp-route-domain:[%d]" % (self.rd_id)
407 def query_vpp_config(self):
408 rds = self._test.vapi.gbp_route_domain_dump()
410 if rd.rd.rd_id == self.rd_id:
415 class VppGbpContractNextHop():
416 def __init__(self, mac, bd, ip, rd):
423 return {'ip': self.ip.encode(),
424 'mac': self.mac.packed,
425 'bd_id': self.bd.bd.bd_id,
426 'rd_id': self.rd.rd_id}
429 class VppGbpContractRule():
430 def __init__(self, action, hash_mode, nhs=None):
432 self.hash_mode = hash_mode
433 self.nhs = [] if nhs is None else nhs
438 nhs.append(nh.encode())
441 return {'action': self.action,
443 'hash_mode': self.hash_mode,
444 'n_nhs': len(self.nhs),
448 return '<VppGbpContractRule action=%s, hash_mode=%s>' % (
449 self.action, self.hash_mode)
452 class VppGbpContract(VppObject):
457 def __init__(self, test, scope, sclass, dclass, acl_index,
458 rules, allowed_ethertypes):
460 if not isinstance(rules, list):
461 raise ValueError("'rules' must be a list.")
462 if not isinstance(allowed_ethertypes, list):
463 raise ValueError("'allowed_ethertypes' must be a list.")
465 self.acl_index = acl_index
469 self.allowed_ethertypes = allowed_ethertypes
470 while (len(self.allowed_ethertypes) < 16):
471 self.allowed_ethertypes.append(0)
473 def add_vpp_config(self):
476 rules.append(r.encode())
477 r = self._test.vapi.gbp_contract_add_del(
480 'acl_index': self.acl_index,
482 'sclass': self.sclass,
483 'dclass': self.dclass,
484 'n_rules': len(rules),
486 'n_ether_types': len(self.allowed_ethertypes),
487 'allowed_ethertypes': self.allowed_ethertypes})
488 self.stats_index = r.stats_index
489 self._test.registry.register(self, self._test.logger)
491 def remove_vpp_config(self):
492 self._test.vapi.gbp_contract_add_del(
495 'acl_index': self.acl_index,
497 'sclass': self.sclass,
498 'dclass': self.dclass,
501 'n_ether_types': len(self.allowed_ethertypes),
502 'allowed_ethertypes': self.allowed_ethertypes})
505 return "gbp-contract:[%d:%d:%d:%d]" % (self.scope,
510 def query_vpp_config(self):
511 cs = self._test.vapi.gbp_contract_dump()
513 if c.contract.scope == self.scope \
514 and c.contract.sclass == self.sclass \
515 and c.contract.dclass == self.dclass:
519 def get_drop_stats(self):
520 c = self._test.statistics.get_counter("/net/gbp/contract/drop")
521 return c[0][self.stats_index]
523 def get_permit_stats(self):
524 c = self._test.statistics.get_counter("/net/gbp/contract/permit")
525 return c[0][self.stats_index]
528 class VppGbpVxlanTunnel(VppInterface):
533 def __init__(self, test, vni, bd_rd_id, mode, src):
534 super(VppGbpVxlanTunnel, self).__init__(test)
537 self.bd_rd_id = bd_rd_id
541 def add_vpp_config(self):
542 r = self._test.vapi.gbp_vxlan_tunnel_add(
547 self.set_sw_if_index(r.sw_if_index)
548 self._test.registry.register(self, self._test.logger)
550 def remove_vpp_config(self):
551 self._test.vapi.gbp_vxlan_tunnel_del(self.vni)
554 return "gbp-vxlan:%d" % (self.sw_if_index)
556 def query_vpp_config(self):
557 return find_gbp_vxlan(self._test, self.vni)
560 class VppGbpAcl(VppObject):
565 def __init__(self, test):
567 self.acl_index = 4294967295
569 def create_rule(self, is_ipv6=0, permit_deny=0, proto=-1,
570 s_prefix=0, s_ip=b'\x00\x00\x00\x00', sport_from=0,
571 sport_to=65535, d_prefix=0, d_ip=b'\x00\x00\x00\x00',
572 dport_from=0, dport_to=65535):
573 if proto == -1 or proto == 0:
576 elif proto == 1 or proto == 58:
579 rule = ({'is_permit': permit_deny, 'is_ipv6': is_ipv6, 'proto': proto,
580 'srcport_or_icmptype_first': sport_from,
581 'srcport_or_icmptype_last': sport_to,
582 'src_ip_prefix_len': s_prefix,
584 'dstport_or_icmpcode_first': dport_from,
585 'dstport_or_icmpcode_last': dport_to,
586 'dst_ip_prefix_len': d_prefix,
587 'dst_ip_addr': d_ip})
590 def add_vpp_config(self, rules):
592 reply = self._test.vapi.acl_add_replace(acl_index=self.acl_index,
595 self.acl_index = reply.acl_index
596 return self.acl_index
598 def remove_vpp_config(self):
599 self._test.vapi.acl_del(self.acl_index)
602 return "gbp-acl:[%d]" % (self.acl_index)
604 def query_vpp_config(self):
605 cs = self._test.vapi.acl_dump()
607 if c.acl_index == self.acl_index:
612 class TestGBP(VppTestCase):
613 """ GBP Test Case """
616 def config_flags(self):
617 return VppEnum.vl_api_nat_config_flags_t
621 super(TestGBP, cls).setUpClass()
624 def tearDownClass(cls):
625 super(TestGBP, cls).tearDownClass()
628 super(TestGBP, self).setUp()
630 self.create_pg_interfaces(range(9))
631 self.create_loopback_interfaces(8)
633 self.router_mac = MACAddress("00:11:22:33:44:55")
635 for i in self.pg_interfaces:
637 for i in self.lo_interfaces:
640 self.vlan_100 = VppDot1QSubint(self, self.pg0, 100)
641 self.vlan_100.admin_up()
642 self.vlan_101 = VppDot1QSubint(self, self.pg0, 101)
643 self.vlan_101.admin_up()
644 self.vlan_102 = VppDot1QSubint(self, self.pg0, 102)
645 self.vlan_102.admin_up()
648 for i in self.pg_interfaces:
650 super(TestGBP, self).tearDown()
651 self.vlan_102.remove_vpp_config()
652 self.vlan_101.remove_vpp_config()
653 self.vlan_100.remove_vpp_config()
655 def send_and_expect_bridged(self, src, tx, dst):
656 rx = self.send_and_expect(src, tx, dst)
659 self.assertEqual(r[Ether].src, tx[0][Ether].src)
660 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
661 self.assertEqual(r[IP].src, tx[0][IP].src)
662 self.assertEqual(r[IP].dst, tx[0][IP].dst)
665 def send_and_expect_bridged6(self, src, tx, dst):
666 rx = self.send_and_expect(src, tx, dst)
669 self.assertEqual(r[Ether].src, tx[0][Ether].src)
670 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
671 self.assertEqual(r[IPv6].src, tx[0][IPv6].src)
672 self.assertEqual(r[IPv6].dst, tx[0][IPv6].dst)
675 def send_and_expect_routed(self, src, tx, dst, src_mac):
676 rx = self.send_and_expect(src, tx, dst)
679 self.assertEqual(r[Ether].src, src_mac)
680 self.assertEqual(r[Ether].dst, dst.remote_mac)
681 self.assertEqual(r[IP].src, tx[0][IP].src)
682 self.assertEqual(r[IP].dst, tx[0][IP].dst)
685 def send_and_expect_routed6(self, src, tx, dst, src_mac):
686 rx = self.send_and_expect(src, tx, dst)
689 self.assertEqual(r[Ether].src, src_mac)
690 self.assertEqual(r[Ether].dst, dst.remote_mac)
691 self.assertEqual(r[IPv6].src, tx[0][IPv6].src)
692 self.assertEqual(r[IPv6].dst, tx[0][IPv6].dst)
695 def send_and_expect_natted(self, src, tx, dst, src_ip):
696 rx = self.send_and_expect(src, tx, dst)
699 self.assertEqual(r[Ether].src, tx[0][Ether].src)
700 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
701 self.assertEqual(r[IP].src, src_ip)
702 self.assertEqual(r[IP].dst, tx[0][IP].dst)
705 def send_and_expect_natted6(self, src, tx, dst, src_ip):
706 rx = self.send_and_expect(src, tx, dst)
709 self.assertEqual(r[Ether].src, tx[0][Ether].src)
710 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
711 self.assertEqual(r[IPv6].src, src_ip)
712 self.assertEqual(r[IPv6].dst, tx[0][IPv6].dst)
715 def send_and_expect_unnatted(self, src, tx, dst, dst_ip):
716 rx = self.send_and_expect(src, tx, dst)
719 self.assertEqual(r[Ether].src, tx[0][Ether].src)
720 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
721 self.assertEqual(r[IP].dst, dst_ip)
722 self.assertEqual(r[IP].src, tx[0][IP].src)
725 def send_and_expect_unnatted6(self, src, tx, dst, dst_ip):
726 rx = self.send_and_expect(src, tx, dst)
729 self.assertEqual(r[Ether].src, tx[0][Ether].src)
730 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
731 self.assertEqual(r[IPv6].dst, dst_ip)
732 self.assertEqual(r[IPv6].src, tx[0][IPv6].src)
735 def send_and_expect_double_natted(self, src, tx, dst, src_ip, dst_ip):
736 rx = self.send_and_expect(src, tx, dst)
739 self.assertEqual(r[Ether].src, str(self.router_mac))
740 self.assertEqual(r[Ether].dst, dst.remote_mac)
741 self.assertEqual(r[IP].dst, dst_ip)
742 self.assertEqual(r[IP].src, src_ip)
745 def send_and_expect_double_natted6(self, src, tx, dst, src_ip, dst_ip):
746 rx = self.send_and_expect(src, tx, dst)
749 self.assertEqual(r[Ether].src, str(self.router_mac))
750 self.assertEqual(r[Ether].dst, dst.remote_mac)
751 self.assertEqual(r[IPv6].dst, dst_ip)
752 self.assertEqual(r[IPv6].src, src_ip)
755 def send_and_expect_no_arp(self, src, tx, dst):
756 self.pg_send(src, tx)
757 dst.get_capture(0, timeout=1)
758 dst.assert_nothing_captured(remark="")
761 def send_and_expect_arp(self, src, tx, dst):
762 rx = self.send_and_expect(src, tx, dst)
765 self.assertEqual(r[Ether].src, tx[0][Ether].src)
766 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
767 self.assertEqual(r[ARP].psrc, tx[0][ARP].psrc)
768 self.assertEqual(r[ARP].pdst, tx[0][ARP].pdst)
769 self.assertEqual(r[ARP].hwsrc, tx[0][ARP].hwsrc)
770 self.assertEqual(r[ARP].hwdst, tx[0][ARP].hwdst)
774 """ Group Based Policy """
776 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
781 gt4 = VppIpTable(self, 0)
783 gt6 = VppIpTable(self, 0, is_ip6=True)
785 nt4 = VppIpTable(self, 20)
787 nt6 = VppIpTable(self, 20, is_ip6=True)
790 rd0 = VppGbpRouteDomain(self, 0, 400, gt4, gt6, None, None)
791 rd20 = VppGbpRouteDomain(self, 20, 420, nt4, nt6, None, None)
794 rd20.add_vpp_config()
799 bd1 = VppBridgeDomain(self, 1)
800 bd2 = VppBridgeDomain(self, 2)
801 bd20 = VppBridgeDomain(self, 20)
805 bd20.add_vpp_config()
807 gbd1 = VppGbpBridgeDomain(self, bd1, rd0, self.loop0)
808 gbd2 = VppGbpBridgeDomain(self, bd2, rd0, self.loop1)
809 gbd20 = VppGbpBridgeDomain(self, bd20, rd20, self.loop2)
811 gbd1.add_vpp_config()
812 gbd2.add_vpp_config()
813 gbd20.add_vpp_config()
816 # 3 EPGs, 2 of which share a BD.
817 # 2 NAT EPGs, one for floating-IP subnets, the other for internet
819 epgs = [VppGbpEndpointGroup(self, 220, 1220, rd0, gbd1,
820 self.pg4, self.loop0,
821 "10.0.0.128", "2001:10::128"),
822 VppGbpEndpointGroup(self, 221, 1221, rd0, gbd1,
823 self.pg5, self.loop0,
824 "10.0.1.128", "2001:10:1::128"),
825 VppGbpEndpointGroup(self, 222, 1222, rd0, gbd2,
826 self.pg6, self.loop1,
827 "10.0.2.128", "2001:10:2::128"),
828 VppGbpEndpointGroup(self, 333, 1333, rd20, gbd20,
829 self.pg7, self.loop2,
830 "11.0.0.128", "3001::128"),
831 VppGbpEndpointGroup(self, 444, 1444, rd20, gbd20,
832 self.pg8, self.loop2,
833 "11.0.0.129", "3001::129")]
834 recircs = [VppGbpRecirc(self, epgs[0], self.loop3),
835 VppGbpRecirc(self, epgs[1], self.loop4),
836 VppGbpRecirc(self, epgs[2], self.loop5),
837 VppGbpRecirc(self, epgs[3], self.loop6, is_ext=True),
838 VppGbpRecirc(self, epgs[4], self.loop7, is_ext=True)]
841 recirc_nat = recircs[3]
844 # 4 end-points, 2 in the same subnet, 3 in the same BD
846 eps = [VppGbpEndpoint(self, self.pg0,
848 "10.0.0.1", "11.0.0.1",
849 "2001:10::1", "3001::1"),
850 VppGbpEndpoint(self, self.pg1,
852 "10.0.0.2", "11.0.0.2",
853 "2001:10::2", "3001::2"),
854 VppGbpEndpoint(self, self.pg2,
856 "10.0.1.1", "11.0.0.3",
857 "2001:10:1::1", "3001::3"),
858 VppGbpEndpoint(self, self.pg3,
860 "10.0.2.1", "11.0.0.4",
861 "2001:10:2::1", "3001::4")]
864 # Config related to each of the EPGs
867 # IP config on the BVI interfaces
868 if epg != epgs[1] and epg != epgs[4]:
869 VppIpInterfaceBind(self, epg.bvi, epg.rd.t4).add_vpp_config()
870 VppIpInterfaceBind(self, epg.bvi, epg.rd.t6).add_vpp_config()
871 self.vapi.sw_interface_set_mac_address(
873 self.router_mac.packed)
875 # The BVIs are NAT inside interfaces
876 flags = self.config_flags.NAT_IS_INSIDE
877 self.vapi.nat44_interface_add_del_feature(
878 sw_if_index=epg.bvi.sw_if_index,
879 flags=flags, is_add=1)
880 self.vapi.nat66_add_del_interface(
881 is_add=1, flags=flags,
882 sw_if_index=epg.bvi.sw_if_index)
884 if_ip4 = VppIpInterfaceAddress(self, epg.bvi, epg.bvi_ip4, 32)
885 if_ip6 = VppIpInterfaceAddress(self, epg.bvi, epg.bvi_ip6, 128)
886 if_ip4.add_vpp_config()
887 if_ip6.add_vpp_config()
889 # EPG uplink interfaces in the RD
890 VppIpInterfaceBind(self, epg.uplink, epg.rd.t4).add_vpp_config()
891 VppIpInterfaceBind(self, epg.uplink, epg.rd.t6).add_vpp_config()
893 # add the BD ARP termination entry for BVI IP
894 epg.bd_arp_ip4 = VppBridgeDomainArpEntry(self, epg.bd.bd,
895 str(self.router_mac),
897 epg.bd_arp_ip6 = VppBridgeDomainArpEntry(self, epg.bd.bd,
898 str(self.router_mac),
900 epg.bd_arp_ip4.add_vpp_config()
901 epg.bd_arp_ip6.add_vpp_config()
906 for recirc in recircs:
907 # EPG's ingress recirculation interface maps to its RD
908 VppIpInterfaceBind(self, recirc.recirc,
909 recirc.epg.rd.t4).add_vpp_config()
910 VppIpInterfaceBind(self, recirc.recirc,
911 recirc.epg.rd.t6).add_vpp_config()
913 self.vapi.nat44_interface_add_del_feature(
914 sw_if_index=recirc.recirc.sw_if_index, is_add=1)
915 self.vapi.nat66_add_del_interface(
917 sw_if_index=recirc.recirc.sw_if_index)
919 recirc.add_vpp_config()
921 for recirc in recircs:
922 self.assertTrue(find_bridge_domain_port(self,
923 recirc.epg.bd.bd.bd_id,
924 recirc.recirc.sw_if_index))
927 self.pg_enable_capture(self.pg_interfaces)
930 # routes to the endpoints. We need these since there are no
931 # adj-fibs due to the fact the the BVI address has /32 and
932 # the subnet is not attached.
934 for (ip, fip) in zip(ep.ips, ep.fips):
935 # Add static mappings for each EP from the 10/8 to 11/8 network
937 flags = self.config_flags.NAT_IS_ADDR_ONLY
938 self.vapi.nat44_add_del_static_mapping(
940 local_ip_address=ip.bytes,
941 external_ip_address=fip.bytes,
942 external_sw_if_index=0xFFFFFFFF,
946 self.vapi.nat66_add_del_static_mapping(
947 local_ip_address=ip.bytes,
948 external_ip_address=fip.bytes,
954 self.logger.info(self.vapi.cli("sh gbp endpoint"))
956 # ... results in a Gratuitous ARP/ND on the EPG's uplink
957 rx = ep.epg.uplink.get_capture(len(ep.ips), timeout=0.2)
959 for ii, ip in enumerate(ep.ips):
963 self.assertTrue(p.haslayer(ICMPv6ND_NA))
964 self.assertEqual(p[ICMPv6ND_NA].tgt, ip.address)
966 self.assertTrue(p.haslayer(ARP))
967 self.assertEqual(p[ARP].psrc, ip.address)
968 self.assertEqual(p[ARP].pdst, ip.address)
970 # add the BD ARP termination entry for floating IP
972 ba = VppBridgeDomainArpEntry(self, epg_nat.bd.bd, ep.mac,
976 # floating IPs route via EPG recirc
978 self, fip.address, fip.length,
979 [VppRoutePath(fip.address,
980 ep.recirc.recirc.sw_if_index,
981 type=FibPathType.FIB_PATH_TYPE_DVR,
982 proto=fip.dpo_proto)],
986 # L2 FIB entries in the NAT EPG BD to bridge the packets from
987 # the outside direct to the internal EPG
988 lf = VppL2FibEntry(self, epg_nat.bd.bd, ep.mac,
989 ep.recirc.recirc, bvi_mac=0)
993 # ARP packets for unknown IP are sent to the EPG uplink
995 pkt_arp = (Ether(dst="ff:ff:ff:ff:ff:ff",
996 src=self.pg0.remote_mac) /
998 hwdst="ff:ff:ff:ff:ff:ff",
999 hwsrc=self.pg0.remote_mac,
1003 self.vapi.cli("clear trace")
1004 self.pg0.add_stream(pkt_arp)
1006 self.pg_enable_capture(self.pg_interfaces)
1009 rxd = epgs[0].uplink.get_capture(1)
1012 # ARP/ND packets get a response
1014 pkt_arp = (Ether(dst="ff:ff:ff:ff:ff:ff",
1015 src=self.pg0.remote_mac) /
1017 hwdst="ff:ff:ff:ff:ff:ff",
1018 hwsrc=self.pg0.remote_mac,
1019 pdst=epgs[0].bvi_ip4.address,
1020 psrc=eps[0].ip4.address))
1022 self.send_and_expect(self.pg0, [pkt_arp], self.pg0)
1024 nsma = in6_getnsma(inet_pton(AF_INET6, eps[0].ip6.address))
1025 d = inet_ntop(AF_INET6, nsma)
1026 pkt_nd = (Ether(dst=in6_getnsmac(nsma),
1027 src=self.pg0.remote_mac) /
1028 IPv6(dst=d, src=eps[0].ip6.address) /
1029 ICMPv6ND_NS(tgt=epgs[0].bvi_ip6.address) /
1030 ICMPv6NDOptSrcLLAddr(lladdr=self.pg0.remote_mac))
1031 self.send_and_expect(self.pg0, [pkt_nd], self.pg0)
1034 # broadcast packets are flooded
1036 pkt_bcast = (Ether(dst="ff:ff:ff:ff:ff:ff",
1037 src=self.pg0.remote_mac) /
1038 IP(src=eps[0].ip4.address, dst="232.1.1.1") /
1039 UDP(sport=1234, dport=1234) /
1042 self.vapi.cli("clear trace")
1043 self.pg0.add_stream(pkt_bcast)
1045 self.pg_enable_capture(self.pg_interfaces)
1048 rxd = eps[1].itf.get_capture(1)
1049 self.assertEqual(rxd[0][Ether].dst, pkt_bcast[Ether].dst)
1050 rxd = epgs[0].uplink.get_capture(1)
1051 self.assertEqual(rxd[0][Ether].dst, pkt_bcast[Ether].dst)
1054 # packets to non-local L3 destinations dropped
1056 pkt_intra_epg_220_ip4 = (Ether(src=self.pg0.remote_mac,
1057 dst=str(self.router_mac)) /
1058 IP(src=eps[0].ip4.address,
1060 UDP(sport=1234, dport=1234) /
1062 pkt_inter_epg_222_ip4 = (Ether(src=self.pg0.remote_mac,
1063 dst=str(self.router_mac)) /
1064 IP(src=eps[0].ip4.address,
1066 UDP(sport=1234, dport=1234) /
1069 self.send_and_assert_no_replies(self.pg0,
1070 pkt_intra_epg_220_ip4 * NUM_PKTS)
1072 pkt_inter_epg_222_ip6 = (Ether(src=self.pg0.remote_mac,
1073 dst=str(self.router_mac)) /
1074 IPv6(src=eps[0].ip6.address,
1075 dst="2001:10::99") /
1076 UDP(sport=1234, dport=1234) /
1078 self.send_and_assert_no_replies(self.pg0,
1079 pkt_inter_epg_222_ip6 * NUM_PKTS)
1082 # Add the subnet routes
1085 self, rd0, "10.0.0.0", 24,
1086 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1088 self, rd0, "10.0.1.0", 24,
1089 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1091 self, rd0, "10.0.2.0", 24,
1092 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1094 self, rd0, "2001:10::1", 64,
1095 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1097 self, rd0, "2001:10:1::1", 64,
1098 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1100 self, rd0, "2001:10:2::1", 64,
1101 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1102 s41.add_vpp_config()
1103 s42.add_vpp_config()
1104 s43.add_vpp_config()
1105 s61.add_vpp_config()
1106 s62.add_vpp_config()
1107 s63.add_vpp_config()
1109 self.send_and_expect_bridged(eps[0].itf,
1110 pkt_intra_epg_220_ip4 * NUM_PKTS,
1112 self.send_and_expect_bridged(eps[0].itf,
1113 pkt_inter_epg_222_ip4 * NUM_PKTS,
1115 self.send_and_expect_bridged6(eps[0].itf,
1116 pkt_inter_epg_222_ip6 * NUM_PKTS,
1119 self.logger.info(self.vapi.cli("sh ip fib 11.0.0.2"))
1120 self.logger.info(self.vapi.cli("sh gbp endpoint-group"))
1121 self.logger.info(self.vapi.cli("sh gbp endpoint"))
1122 self.logger.info(self.vapi.cli("sh gbp recirc"))
1123 self.logger.info(self.vapi.cli("sh int"))
1124 self.logger.info(self.vapi.cli("sh int addr"))
1125 self.logger.info(self.vapi.cli("sh int feat loop6"))
1126 self.logger.info(self.vapi.cli("sh vlib graph ip4-gbp-src-classify"))
1127 self.logger.info(self.vapi.cli("sh int feat loop3"))
1128 self.logger.info(self.vapi.cli("sh int feat pg0"))
1131 # Packet destined to unknown unicast is sent on the epg uplink ...
1133 pkt_intra_epg_220_to_uplink = (Ether(src=self.pg0.remote_mac,
1134 dst="00:00:00:33:44:55") /
1135 IP(src=eps[0].ip4.address,
1137 UDP(sport=1234, dport=1234) /
1140 self.send_and_expect_bridged(eps[0].itf,
1141 pkt_intra_epg_220_to_uplink * NUM_PKTS,
1143 # ... and nowhere else
1144 self.pg1.get_capture(0, timeout=0.1)
1145 self.pg1.assert_nothing_captured(remark="Flood onto other VMS")
1147 pkt_intra_epg_221_to_uplink = (Ether(src=self.pg2.remote_mac,
1148 dst="00:00:00:33:44:66") /
1149 IP(src=eps[0].ip4.address,
1151 UDP(sport=1234, dport=1234) /
1154 self.send_and_expect_bridged(eps[2].itf,
1155 pkt_intra_epg_221_to_uplink * NUM_PKTS,
1159 # Packets from the uplink are forwarded in the absence of a contract
1161 pkt_intra_epg_220_from_uplink = (Ether(src="00:00:00:33:44:55",
1162 dst=self.pg0.remote_mac) /
1163 IP(src=eps[0].ip4.address,
1165 UDP(sport=1234, dport=1234) /
1168 self.send_and_expect_bridged(self.pg4,
1169 pkt_intra_epg_220_from_uplink * NUM_PKTS,
1173 # in the absence of policy, endpoints in the same EPG
1176 pkt_intra_epg = (Ether(src=self.pg0.remote_mac,
1177 dst=self.pg1.remote_mac) /
1178 IP(src=eps[0].ip4.address,
1179 dst=eps[1].ip4.address) /
1180 UDP(sport=1234, dport=1234) /
1183 self.send_and_expect_bridged(self.pg0,
1184 pkt_intra_epg * NUM_PKTS,
1188 # in the absence of policy, endpoints in the different EPG
1189 # cannot communicate
1191 pkt_inter_epg_220_to_221 = (Ether(src=self.pg0.remote_mac,
1192 dst=self.pg2.remote_mac) /
1193 IP(src=eps[0].ip4.address,
1194 dst=eps[2].ip4.address) /
1195 UDP(sport=1234, dport=1234) /
1197 pkt_inter_epg_221_to_220 = (Ether(src=self.pg2.remote_mac,
1198 dst=self.pg0.remote_mac) /
1199 IP(src=eps[2].ip4.address,
1200 dst=eps[0].ip4.address) /
1201 UDP(sport=1234, dport=1234) /
1203 pkt_inter_epg_220_to_222 = (Ether(src=self.pg0.remote_mac,
1204 dst=str(self.router_mac)) /
1205 IP(src=eps[0].ip4.address,
1206 dst=eps[3].ip4.address) /
1207 UDP(sport=1234, dport=1234) /
1210 self.send_and_assert_no_replies(eps[0].itf,
1211 pkt_inter_epg_220_to_221 * NUM_PKTS)
1212 self.send_and_assert_no_replies(eps[0].itf,
1213 pkt_inter_epg_220_to_222 * NUM_PKTS)
1216 # A uni-directional contract from EPG 220 -> 221
1218 acl = VppGbpAcl(self)
1219 rule = acl.create_rule(permit_deny=1, proto=17)
1220 rule2 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
1221 acl_index = acl.add_vpp_config([rule, rule2])
1222 c1 = VppGbpContract(
1223 self, 400, epgs[0].sclass, epgs[1].sclass, acl_index,
1224 [VppGbpContractRule(
1225 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1226 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1229 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1230 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1232 [ETH_P_IP, ETH_P_IPV6])
1235 self.send_and_expect_bridged(eps[0].itf,
1236 pkt_inter_epg_220_to_221 * NUM_PKTS,
1238 self.send_and_assert_no_replies(eps[0].itf,
1239 pkt_inter_epg_220_to_222 * NUM_PKTS)
1242 # contract for the return direction
1244 c2 = VppGbpContract(
1245 self, 400, epgs[1].sclass, epgs[0].sclass, acl_index,
1246 [VppGbpContractRule(
1247 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1248 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1251 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1252 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1254 [ETH_P_IP, ETH_P_IPV6])
1257 self.send_and_expect_bridged(eps[0].itf,
1258 pkt_inter_epg_220_to_221 * NUM_PKTS,
1260 self.send_and_expect_bridged(eps[2].itf,
1261 pkt_inter_epg_221_to_220 * NUM_PKTS,
1264 ds = c2.get_drop_stats()
1265 self.assertEqual(ds['packets'], 0)
1266 ps = c2.get_permit_stats()
1267 self.assertEqual(ps['packets'], NUM_PKTS)
1270 # the contract does not allow non-IP
1272 pkt_non_ip_inter_epg_220_to_221 = (Ether(src=self.pg0.remote_mac,
1273 dst=self.pg2.remote_mac) /
1275 self.send_and_assert_no_replies(eps[0].itf,
1276 pkt_non_ip_inter_epg_220_to_221 * 17)
1279 # check that inter group is still disabled for the groups
1280 # not in the contract.
1282 self.send_and_assert_no_replies(eps[0].itf,
1283 pkt_inter_epg_220_to_222 * NUM_PKTS)
1286 # A uni-directional contract from EPG 220 -> 222 'L3 routed'
1288 c3 = VppGbpContract(
1289 self, 400, epgs[0].sclass, epgs[2].sclass, acl_index,
1290 [VppGbpContractRule(
1291 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1292 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1295 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1296 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1298 [ETH_P_IP, ETH_P_IPV6])
1301 self.logger.info(self.vapi.cli("sh gbp contract"))
1303 self.send_and_expect_routed(eps[0].itf,
1304 pkt_inter_epg_220_to_222 * NUM_PKTS,
1306 str(self.router_mac))
1309 # remove both contracts, traffic stops in both directions
1311 c2.remove_vpp_config()
1312 c1.remove_vpp_config()
1313 c3.remove_vpp_config()
1314 acl.remove_vpp_config()
1316 self.send_and_assert_no_replies(eps[2].itf,
1317 pkt_inter_epg_221_to_220 * NUM_PKTS)
1318 self.send_and_assert_no_replies(eps[0].itf,
1319 pkt_inter_epg_220_to_221 * NUM_PKTS)
1320 self.send_and_expect_bridged(eps[0].itf,
1321 pkt_intra_epg * NUM_PKTS,
1325 # EPs to the outside world
1328 # in the EP's RD an external subnet via the NAT EPG's recirc
1330 self, rd0, "0.0.0.0", 0,
1331 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1332 sw_if_index=recirc_nat.recirc.sw_if_index,
1333 sclass=epg_nat.sclass)
1335 self, rd0, "11.0.0.0", 8,
1336 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1337 sw_if_index=recirc_nat.recirc.sw_if_index,
1338 sclass=epg_nat.sclass)
1339 se16 = VppGbpSubnet(
1341 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1342 sw_if_index=recirc_nat.recirc.sw_if_index,
1343 sclass=epg_nat.sclass)
1344 # in the NAT RD an external subnet via the NAT EPG's uplink
1346 self, rd20, "0.0.0.0", 0,
1347 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1348 sw_if_index=epg_nat.uplink.sw_if_index,
1349 sclass=epg_nat.sclass)
1350 se36 = VppGbpSubnet(
1351 self, rd20, "::", 0,
1352 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1353 sw_if_index=epg_nat.uplink.sw_if_index,
1354 sclass=epg_nat.sclass)
1356 self, rd20, "11.0.0.0", 8,
1357 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1358 sw_if_index=epg_nat.uplink.sw_if_index,
1359 sclass=epg_nat.sclass)
1360 se1.add_vpp_config()
1361 se2.add_vpp_config()
1362 se16.add_vpp_config()
1363 se3.add_vpp_config()
1364 se36.add_vpp_config()
1365 se4.add_vpp_config()
1367 self.logger.info(self.vapi.cli("sh ip fib 0.0.0.0/0"))
1368 self.logger.info(self.vapi.cli("sh ip fib 11.0.0.1"))
1369 self.logger.info(self.vapi.cli("sh ip6 fib ::/0"))
1370 self.logger.info(self.vapi.cli("sh ip6 fib %s" %
1374 # From an EP to an outside address: IN2OUT
1376 pkt_inter_epg_220_to_global = (Ether(src=self.pg0.remote_mac,
1377 dst=str(self.router_mac)) /
1378 IP(src=eps[0].ip4.address,
1380 UDP(sport=1234, dport=1234) /
1384 self.send_and_assert_no_replies(eps[0].itf,
1385 pkt_inter_epg_220_to_global * NUM_PKTS)
1387 acl2 = VppGbpAcl(self)
1388 rule = acl2.create_rule(permit_deny=1, proto=17, sport_from=1234,
1389 sport_to=1234, dport_from=1234, dport_to=1234)
1390 rule2 = acl2.create_rule(is_ipv6=1, permit_deny=1, proto=17,
1391 sport_from=1234, sport_to=1234,
1392 dport_from=1234, dport_to=1234)
1394 acl_index2 = acl2.add_vpp_config([rule, rule2])
1395 c4 = VppGbpContract(
1396 self, 400, epgs[0].sclass, epgs[3].sclass, acl_index2,
1397 [VppGbpContractRule(
1398 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1399 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1402 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1403 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1405 [ETH_P_IP, ETH_P_IPV6])
1408 self.send_and_expect_natted(eps[0].itf,
1409 pkt_inter_epg_220_to_global * NUM_PKTS,
1411 eps[0].fip4.address)
1413 pkt_inter_epg_220_to_global = (Ether(src=self.pg0.remote_mac,
1414 dst=str(self.router_mac)) /
1415 IPv6(src=eps[0].ip6.address,
1417 UDP(sport=1234, dport=1234) /
1420 self.send_and_expect_natted6(self.pg0,
1421 pkt_inter_epg_220_to_global * NUM_PKTS,
1423 eps[0].fip6.address)
1426 # From a global address to an EP: OUT2IN
1428 pkt_inter_epg_220_from_global = (Ether(src=str(self.router_mac),
1429 dst=self.pg0.remote_mac) /
1430 IP(dst=eps[0].fip4.address,
1432 UDP(sport=1234, dport=1234) /
1435 self.send_and_assert_no_replies(
1436 self.pg7, pkt_inter_epg_220_from_global * NUM_PKTS)
1438 c5 = VppGbpContract(
1439 self, 400, epgs[3].sclass, epgs[0].sclass, acl_index2,
1440 [VppGbpContractRule(
1441 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1442 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1445 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1446 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1448 [ETH_P_IP, ETH_P_IPV6])
1451 self.send_and_expect_unnatted(self.pg7,
1452 pkt_inter_epg_220_from_global * NUM_PKTS,
1456 pkt_inter_epg_220_from_global = (Ether(src=str(self.router_mac),
1457 dst=self.pg0.remote_mac) /
1458 IPv6(dst=eps[0].fip6.address,
1460 UDP(sport=1234, dport=1234) /
1463 self.send_and_expect_unnatted6(
1465 pkt_inter_epg_220_from_global * NUM_PKTS,
1470 # From a local VM to another local VM using resp. public addresses:
1473 pkt_intra_epg_220_global = (Ether(src=self.pg0.remote_mac,
1474 dst=str(self.router_mac)) /
1475 IP(src=eps[0].ip4.address,
1476 dst=eps[1].fip4.address) /
1477 UDP(sport=1234, dport=1234) /
1480 self.send_and_expect_double_natted(eps[0].itf,
1481 pkt_intra_epg_220_global * NUM_PKTS,
1483 eps[0].fip4.address,
1486 pkt_intra_epg_220_global = (Ether(src=self.pg0.remote_mac,
1487 dst=str(self.router_mac)) /
1488 IPv6(src=eps[0].ip6.address,
1489 dst=eps[1].fip6.address) /
1490 UDP(sport=1234, dport=1234) /
1493 self.send_and_expect_double_natted6(
1495 pkt_intra_epg_220_global * NUM_PKTS,
1497 eps[0].fip6.address,
1504 # del static mappings for each EP from the 10/8 to 11/8 network
1505 flags = self.config_flags.NAT_IS_ADDR_ONLY
1506 self.vapi.nat44_add_del_static_mapping(
1508 local_ip_address=ep.ip4.bytes,
1509 external_ip_address=ep.fip4.bytes,
1510 external_sw_if_index=0xFFFFFFFF,
1513 self.vapi.nat66_add_del_static_mapping(
1514 local_ip_address=ep.ip6.bytes,
1515 external_ip_address=ep.fip6.bytes,
1519 # IP config on the BVI interfaces
1520 if epg != epgs[0] and epg != epgs[3]:
1521 flags = self.config_flags.NAT_IS_INSIDE
1522 self.vapi.nat44_interface_add_del_feature(
1523 sw_if_index=epg.bvi.sw_if_index,
1526 self.vapi.nat66_add_del_interface(
1527 is_add=0, flags=flags,
1528 sw_if_index=epg.bvi.sw_if_index)
1530 for recirc in recircs:
1531 self.vapi.nat44_interface_add_del_feature(
1532 sw_if_index=recirc.recirc.sw_if_index,
1534 self.vapi.nat66_add_del_interface(
1536 sw_if_index=recirc.recirc.sw_if_index)
1538 def wait_for_ep_timeout(self, sw_if_index=None, ip=None, mac=None,
1539 tep=None, n_tries=100, s_time=1):
1541 if not find_gbp_endpoint(self, sw_if_index, ip, mac, tep=tep):
1543 n_tries = n_tries - 1
1545 self.assertFalse(find_gbp_endpoint(self, sw_if_index, ip, mac))
1548 def test_gbp_learn_l2(self):
1549 """ GBP L2 Endpoint Learning """
1551 drop_no_contract = self.statistics.get_err_counter(
1552 '/err/gbp-policy-port/drop-no-contract')
1553 allow_intra_class = self.statistics.get_err_counter(
1554 '/err/gbp-policy-port/allow-intra-sclass')
1556 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
1557 learnt = [{'mac': '00:00:11:11:11:01',
1559 'ip6': '2001:10::2'},
1560 {'mac': '00:00:11:11:11:02',
1562 'ip6': '2001:10::3'}]
1567 gt4 = VppIpTable(self, 1)
1568 gt4.add_vpp_config()
1569 gt6 = VppIpTable(self, 1, is_ip6=True)
1570 gt6.add_vpp_config()
1572 rd1 = VppGbpRouteDomain(self, 1, 401, gt4, gt6)
1573 rd1.add_vpp_config()
1576 # Pg2 hosts the vxlan tunnel, hosts on pg2 to act as TEPs
1577 # Pg3 hosts the IP4 UU-flood VXLAN tunnel
1578 # Pg4 hosts the IP6 UU-flood VXLAN tunnel
1580 self.pg2.config_ip4()
1581 self.pg2.resolve_arp()
1582 self.pg2.generate_remote_hosts(4)
1583 self.pg2.configure_ipv4_neighbors()
1584 self.pg3.config_ip4()
1585 self.pg3.resolve_arp()
1586 self.pg4.config_ip4()
1587 self.pg4.resolve_arp()
1590 # Add a mcast destination VXLAN-GBP tunnel for B&M traffic
1592 tun_bm = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
1595 tun_bm.add_vpp_config()
1598 # a GBP bridge domain with a BVI and a UU-flood interface
1600 bd1 = VppBridgeDomain(self, 1)
1601 bd1.add_vpp_config()
1602 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0,
1604 gbd1.add_vpp_config()
1606 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1607 self.logger.info(self.vapi.cli("sh gbp bridge"))
1609 # ... and has a /32 applied
1610 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
1611 ip_addr.add_vpp_config()
1614 # The Endpoint-group in which we are learning endpoints
1616 epg_220 = VppGbpEndpointGroup(self, 220, 112, rd1, gbd1,
1620 VppGbpEndpointRetention(2))
1621 epg_220.add_vpp_config()
1622 epg_330 = VppGbpEndpointGroup(self, 330, 113, rd1, gbd1,
1626 VppGbpEndpointRetention(2))
1627 epg_330.add_vpp_config()
1630 # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
1633 vx_tun_l2_1 = VppGbpVxlanTunnel(
1634 self, 99, bd1.bd_id,
1635 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L2,
1637 vx_tun_l2_1.add_vpp_config()
1640 # A static endpoint that the learnt endpoints are trying to
1643 ep = VppGbpEndpoint(self, self.pg0,
1645 "10.0.0.127", "11.0.0.127",
1646 "2001:10::1", "3001::1")
1649 self.assertTrue(find_route(self, ep.ip4.address, 32, table_id=1))
1651 # a packet with an sclass from an unknown EPG
1652 p = (Ether(src=self.pg2.remote_mac,
1653 dst=self.pg2.local_mac) /
1654 IP(src=self.pg2.remote_hosts[0].ip4,
1655 dst=self.pg2.local_ip4) /
1656 UDP(sport=1234, dport=48879) /
1657 VXLAN(vni=99, gpid=88, flags=0x88) /
1658 Ether(src=learnt[0]["mac"], dst=ep.mac) /
1659 IP(src=learnt[0]["ip"], dst=ep.ip4.address) /
1660 UDP(sport=1234, dport=1234) /
1663 self.send_and_assert_no_replies(self.pg2, p)
1665 self.logger.info(self.vapi.cli("sh error"))
1666 self.assert_error_counter_equal(
1667 '/err/gbp-policy-port/drop-no-contract',
1668 drop_no_contract + 1)
1671 # we should not have learnt a new tunnel endpoint, since
1672 # the EPG was not learnt.
1674 self.assertEqual(INDEX_INVALID,
1675 find_vxlan_gbp_tunnel(self,
1677 self.pg2.remote_hosts[0].ip4,
1680 # ep is not learnt, because the EPG is unknown
1681 self.assertEqual(len(self.vapi.gbp_endpoint_dump()), 1)
1684 # Learn new EPs from IP packets
1686 for ii, l in enumerate(learnt):
1687 # a packet with an sclass from a known EPG
1688 # arriving on an unknown TEP
1689 p = (Ether(src=self.pg2.remote_mac,
1690 dst=self.pg2.local_mac) /
1691 IP(src=self.pg2.remote_hosts[1].ip4,
1692 dst=self.pg2.local_ip4) /
1693 UDP(sport=1234, dport=48879) /
1694 VXLAN(vni=99, gpid=112, flags=0x88) /
1695 Ether(src=l['mac'], dst=ep.mac) /
1696 IP(src=l['ip'], dst=ep.ip4.address) /
1697 UDP(sport=1234, dport=1234) /
1700 rx = self.send_and_expect(self.pg2, [p], self.pg0)
1703 tep1_sw_if_index = find_vxlan_gbp_tunnel(
1706 self.pg2.remote_hosts[1].ip4,
1708 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
1711 # the EP is learnt via the learnt TEP
1712 # both from its MAC and its IP
1714 self.assertTrue(find_gbp_endpoint(self,
1715 vx_tun_l2_1.sw_if_index,
1717 self.assertTrue(find_gbp_endpoint(self,
1718 vx_tun_l2_1.sw_if_index,
1721 self.assert_error_counter_equal(
1722 '/err/gbp-policy-port/allow-intra-sclass',
1723 allow_intra_class + 2)
1725 self.logger.info(self.vapi.cli("show gbp endpoint"))
1726 self.logger.info(self.vapi.cli("show gbp vxlan"))
1727 self.logger.info(self.vapi.cli("show ip mfib"))
1730 # If we sleep for the threshold time, the learnt endpoints should
1734 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1738 # Learn new EPs from GARP packets received on the BD's mcast tunnel
1740 for ii, l in enumerate(learnt):
1741 # add some junk in the reserved field of the vxlan-header
1742 # next to the VNI. we should accept since reserved bits are
1744 p = (Ether(src=self.pg2.remote_mac,
1745 dst=self.pg2.local_mac) /
1746 IP(src=self.pg2.remote_hosts[1].ip4,
1748 UDP(sport=1234, dport=48879) /
1749 VXLAN(vni=88, reserved2=0x80, gpid=112, flags=0x88) /
1750 Ether(src=l['mac'], dst="ff:ff:ff:ff:ff:ff") /
1752 psrc=l['ip'], pdst=l['ip'],
1753 hwsrc=l['mac'], hwdst="ff:ff:ff:ff:ff:ff"))
1755 rx = self.send_and_expect(self.pg4, [p], self.pg0)
1758 tep1_sw_if_index = find_vxlan_gbp_tunnel(
1761 self.pg2.remote_hosts[1].ip4,
1763 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
1766 # the EP is learnt via the learnt TEP
1767 # both from its MAC and its IP
1769 self.assertTrue(find_gbp_endpoint(self,
1770 vx_tun_l2_1.sw_if_index,
1772 self.assertTrue(find_gbp_endpoint(self,
1773 vx_tun_l2_1.sw_if_index,
1777 # wait for the learnt endpoints to age out
1780 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1784 # Learn new EPs from L2 packets
1786 for ii, l in enumerate(learnt):
1787 # a packet with an sclass from a known EPG
1788 # arriving on an unknown TEP
1789 p = (Ether(src=self.pg2.remote_mac,
1790 dst=self.pg2.local_mac) /
1791 IP(src=self.pg2.remote_hosts[1].ip4,
1792 dst=self.pg2.local_ip4) /
1793 UDP(sport=1234, dport=48879) /
1794 VXLAN(vni=99, gpid=112, flags=0x88) /
1795 Ether(src=l['mac'], dst=ep.mac) /
1798 rx = self.send_and_expect(self.pg2, [p], self.pg0)
1801 tep1_sw_if_index = find_vxlan_gbp_tunnel(
1804 self.pg2.remote_hosts[1].ip4,
1806 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
1809 # the EP is learnt via the learnt TEP
1810 # both from its MAC and its IP
1812 self.assertTrue(find_gbp_endpoint(self,
1813 vx_tun_l2_1.sw_if_index,
1816 self.logger.info(self.vapi.cli("show gbp endpoint"))
1817 self.logger.info(self.vapi.cli("show gbp vxlan"))
1818 self.logger.info(self.vapi.cli("show vxlan-gbp tunnel"))
1821 # wait for the learnt endpoints to age out
1824 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1828 # repeat. the do not learn bit is set so the EPs are not learnt
1831 # a packet with an sclass from a known EPG
1832 p = (Ether(src=self.pg2.remote_mac,
1833 dst=self.pg2.local_mac) /
1834 IP(src=self.pg2.remote_hosts[1].ip4,
1835 dst=self.pg2.local_ip4) /
1836 UDP(sport=1234, dport=48879) /
1837 VXLAN(vni=99, gpid=112, flags=0x88, gpflags="D") /
1838 Ether(src=l['mac'], dst=ep.mac) /
1839 IP(src=l['ip'], dst=ep.ip4.address) /
1840 UDP(sport=1234, dport=1234) /
1843 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
1846 self.assertFalse(find_gbp_endpoint(self,
1847 vx_tun_l2_1.sw_if_index,
1854 # a packet with an sclass from a known EPG
1855 # set a reserved bit in addition to the G and I
1856 # reserved bits should not be checked on rx.
1857 p = (Ether(src=self.pg2.remote_mac,
1858 dst=self.pg2.local_mac) /
1859 IP(src=self.pg2.remote_hosts[1].ip4,
1860 dst=self.pg2.local_ip4) /
1861 UDP(sport=1234, dport=48879) /
1862 VXLAN(vni=99, gpid=112, flags=0xc8) /
1863 Ether(src=l['mac'], dst=ep.mac) /
1864 IP(src=l['ip'], dst=ep.ip4.address) /
1865 UDP(sport=1234, dport=1234) /
1868 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
1870 self.assertTrue(find_gbp_endpoint(self,
1871 vx_tun_l2_1.sw_if_index,
1875 # Static EP replies to dynamics
1877 self.logger.info(self.vapi.cli("sh l2fib bd_id 1"))
1879 p = (Ether(src=ep.mac, dst=l['mac']) /
1880 IP(dst=l['ip'], src=ep.ip4.address) /
1881 UDP(sport=1234, dport=1234) /
1884 rxs = self.send_and_expect(self.pg0, p * 17, self.pg2)
1887 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
1888 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
1889 self.assertEqual(rx[UDP].dport, 48879)
1890 # the UDP source port is a random value for hashing
1891 self.assertEqual(rx[VXLAN].gpid, 112)
1892 self.assertEqual(rx[VXLAN].vni, 99)
1893 self.assertTrue(rx[VXLAN].flags.G)
1894 self.assertTrue(rx[VXLAN].flags.Instance)
1895 self.assertTrue(rx[VXLAN].gpflags.A)
1896 self.assertFalse(rx[VXLAN].gpflags.D)
1899 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1903 # repeat in the other EPG
1904 # there's no contract between 220 and 330, but the A-bit is set
1905 # so the packet is cleared for delivery
1908 # a packet with an sclass from a known EPG
1909 p = (Ether(src=self.pg2.remote_mac,
1910 dst=self.pg2.local_mac) /
1911 IP(src=self.pg2.remote_hosts[1].ip4,
1912 dst=self.pg2.local_ip4) /
1913 UDP(sport=1234, dport=48879) /
1914 VXLAN(vni=99, gpid=113, flags=0x88, gpflags='A') /
1915 Ether(src=l['mac'], dst=ep.mac) /
1916 IP(src=l['ip'], dst=ep.ip4.address) /
1917 UDP(sport=1234, dport=1234) /
1920 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
1922 self.assertTrue(find_gbp_endpoint(self,
1923 vx_tun_l2_1.sw_if_index,
1927 # static EP cannot reach the learnt EPs since there is no contract
1928 # only test 1 EP as the others could timeout
1930 p = (Ether(src=ep.mac, dst=l['mac']) /
1931 IP(dst=learnt[0]['ip'], src=ep.ip4.address) /
1932 UDP(sport=1234, dport=1234) /
1935 self.send_and_assert_no_replies(self.pg0, [p])
1938 # refresh the entries after the check for no replies above
1941 # a packet with an sclass from a known EPG
1942 p = (Ether(src=self.pg2.remote_mac,
1943 dst=self.pg2.local_mac) /
1944 IP(src=self.pg2.remote_hosts[1].ip4,
1945 dst=self.pg2.local_ip4) /
1946 UDP(sport=1234, dport=48879) /
1947 VXLAN(vni=99, gpid=113, flags=0x88, gpflags='A') /
1948 Ether(src=l['mac'], dst=ep.mac) /
1949 IP(src=l['ip'], dst=ep.ip4.address) /
1950 UDP(sport=1234, dport=1234) /
1953 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
1955 self.assertTrue(find_gbp_endpoint(self,
1956 vx_tun_l2_1.sw_if_index,
1960 # Add the contract so they can talk
1962 acl = VppGbpAcl(self)
1963 rule = acl.create_rule(permit_deny=1, proto=17)
1964 rule2 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
1965 acl_index = acl.add_vpp_config([rule, rule2])
1966 c1 = VppGbpContract(
1967 self, 401, epg_220.sclass, epg_330.sclass, acl_index,
1968 [VppGbpContractRule(
1969 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1970 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1973 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1974 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1976 [ETH_P_IP, ETH_P_IPV6])
1980 p = (Ether(src=ep.mac, dst=l['mac']) /
1981 IP(dst=l['ip'], src=ep.ip4.address) /
1982 UDP(sport=1234, dport=1234) /
1985 self.send_and_expect(self.pg0, [p], self.pg2)
1988 # send UU packets from the local EP
1990 self.logger.info(self.vapi.cli("sh gbp bridge"))
1991 self.logger.info(self.vapi.cli("sh bridge-domain 1 detail"))
1992 p_uu = (Ether(src=ep.mac, dst="00:11:11:11:11:11") /
1993 IP(dst="10.0.0.133", src=ep.ip4.address) /
1994 UDP(sport=1234, dport=1234) /
1996 rxs = self.send_and_expect(ep.itf, [p_uu], gbd1.uu_fwd)
1998 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2000 p_bm = (Ether(src=ep.mac, dst="ff:ff:ff:ff:ff:ff") /
2001 IP(dst="10.0.0.133", src=ep.ip4.address) /
2002 UDP(sport=1234, dport=1234) /
2004 rxs = self.send_and_expect_only(ep.itf, [p_bm], tun_bm.mcast_itf)
2007 self.assertEqual(rx[IP].src, self.pg4.local_ip4)
2008 self.assertEqual(rx[IP].dst, "239.1.1.1")
2009 self.assertEqual(rx[UDP].dport, 48879)
2010 # the UDP source port is a random value for hashing
2011 self.assertEqual(rx[VXLAN].gpid, 112)
2012 self.assertEqual(rx[VXLAN].vni, 88)
2013 self.assertTrue(rx[VXLAN].flags.G)
2014 self.assertTrue(rx[VXLAN].flags.Instance)
2015 self.assertFalse(rx[VXLAN].gpflags.A)
2016 self.assertFalse(rx[VXLAN].gpflags.D)
2018 acl = VppGbpAcl(self)
2019 rule = acl.create_rule(permit_deny=1, proto=17)
2020 rule2 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
2021 acl_index = acl.add_vpp_config([rule, rule2])
2022 c2 = VppGbpContract(
2023 self, 401, epg_330.sclass, epg_220.sclass, acl_index,
2024 [VppGbpContractRule(
2025 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2026 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2029 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2030 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2032 [ETH_P_IP, ETH_P_IPV6])
2036 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
2039 # Check v6 Endpoints learning
2042 # a packet with an sclass from a known EPG
2043 p = (Ether(src=self.pg2.remote_mac,
2044 dst=self.pg2.local_mac) /
2045 IP(src=self.pg2.remote_hosts[1].ip4,
2046 dst=self.pg2.local_ip4) /
2047 UDP(sport=1234, dport=48879) /
2048 VXLAN(vni=99, gpid=113, flags=0x88) /
2049 Ether(src=l['mac'], dst=ep.mac) /
2050 IPv6(src=l['ip6'], dst=ep.ip6.address) /
2051 UDP(sport=1234, dport=1234) /
2054 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
2055 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
2057 self.assertTrue(find_gbp_endpoint(
2059 vx_tun_l2_1.sw_if_index,
2061 tep=[self.pg2.local_ip4,
2062 self.pg2.remote_hosts[1].ip4]))
2064 self.logger.info(self.vapi.cli("sh int"))
2065 self.logger.info(self.vapi.cli("sh vxlan-gbp tunnel"))
2066 self.logger.info(self.vapi.cli("sh gbp vxlan"))
2067 self.logger.info(self.vapi.cli("sh gbp endpoint"))
2068 self.logger.info(self.vapi.cli("sh gbp interface"))
2071 # EP moves to a different TEP
2074 # a packet with an sclass from a known EPG
2075 p = (Ether(src=self.pg2.remote_mac,
2076 dst=self.pg2.local_mac) /
2077 IP(src=self.pg2.remote_hosts[2].ip4,
2078 dst=self.pg2.local_ip4) /
2079 UDP(sport=1234, dport=48879) /
2080 VXLAN(vni=99, gpid=113, flags=0x88) /
2081 Ether(src=l['mac'], dst=ep.mac) /
2082 IPv6(src=l['ip6'], dst=ep.ip6.address) /
2083 UDP(sport=1234, dport=1234) /
2086 rx = self.send_and_expect(self.pg2, p * 1, self.pg0)
2087 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
2089 self.assertTrue(find_gbp_endpoint(
2091 vx_tun_l2_1.sw_if_index,
2093 tep=[self.pg2.local_ip4,
2094 self.pg2.remote_hosts[2].ip4]))
2097 # v6 remote EP reachability
2100 p = (Ether(src=ep.mac, dst=l['mac']) /
2101 IPv6(dst=l['ip6'], src=ep.ip6.address) /
2102 UDP(sport=1234, dport=1234) /
2105 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
2108 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2109 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[2].ip4)
2110 self.assertEqual(rx[UDP].dport, 48879)
2111 # the UDP source port is a random value for hashing
2112 self.assertEqual(rx[VXLAN].gpid, 112)
2113 self.assertEqual(rx[VXLAN].vni, 99)
2114 self.assertTrue(rx[VXLAN].flags.G)
2115 self.assertTrue(rx[VXLAN].flags.Instance)
2116 self.assertTrue(rx[VXLAN].gpflags.A)
2117 self.assertFalse(rx[VXLAN].gpflags.D)
2118 self.assertEqual(rx[IPv6].dst, l['ip6'])
2124 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
2126 self.pg2.unconfig_ip4()
2127 self.pg3.unconfig_ip4()
2128 self.pg4.unconfig_ip4()
2130 def test_gbp_contract(self):
2131 """ GBP Contracts """
2136 gt4 = VppIpTable(self, 0)
2137 gt4.add_vpp_config()
2138 gt6 = VppIpTable(self, 0, is_ip6=True)
2139 gt6.add_vpp_config()
2141 rd0 = VppGbpRouteDomain(self, 0, 400, gt4, gt6, None, None)
2143 rd0.add_vpp_config()
2148 bd1 = VppBridgeDomain(self, 1, arp_term=0)
2149 bd2 = VppBridgeDomain(self, 2, arp_term=0)
2151 bd1.add_vpp_config()
2152 bd2.add_vpp_config()
2154 gbd1 = VppGbpBridgeDomain(self, bd1, rd0, self.loop0)
2155 gbd2 = VppGbpBridgeDomain(self, bd2, rd0, self.loop1)
2157 gbd1.add_vpp_config()
2158 gbd2.add_vpp_config()
2161 # 3 EPGs, 2 of which share a BD.
2163 epgs = [VppGbpEndpointGroup(self, 220, 1220, rd0, gbd1,
2165 "10.0.0.128", "2001:10::128"),
2166 VppGbpEndpointGroup(self, 221, 1221, rd0, gbd1,
2168 "10.0.1.128", "2001:10:1::128"),
2169 VppGbpEndpointGroup(self, 222, 1222, rd0, gbd2,
2171 "10.0.2.128", "2001:10:2::128")]
2173 # 4 end-points, 2 in the same subnet, 3 in the same BD
2175 eps = [VppGbpEndpoint(self, self.pg0,
2177 "10.0.0.1", "11.0.0.1",
2178 "2001:10::1", "3001::1"),
2179 VppGbpEndpoint(self, self.pg1,
2181 "10.0.0.2", "11.0.0.2",
2182 "2001:10::2", "3001::2"),
2183 VppGbpEndpoint(self, self.pg2,
2185 "10.0.1.1", "11.0.0.3",
2186 "2001:10:1::1", "3001::3"),
2187 VppGbpEndpoint(self, self.pg3,
2189 "10.0.2.1", "11.0.0.4",
2190 "2001:10:2::1", "3001::4")]
2193 # Config related to each of the EPGs
2196 # IP config on the BVI interfaces
2198 VppIpInterfaceBind(self, epg.bvi, epg.rd.t4).add_vpp_config()
2199 VppIpInterfaceBind(self, epg.bvi, epg.rd.t6).add_vpp_config()
2200 self.vapi.sw_interface_set_mac_address(
2201 epg.bvi.sw_if_index,
2202 self.router_mac.packed)
2204 if_ip4 = VppIpInterfaceAddress(self, epg.bvi, epg.bvi_ip4, 32)
2205 if_ip6 = VppIpInterfaceAddress(self, epg.bvi, epg.bvi_ip6, 128)
2206 if_ip4.add_vpp_config()
2207 if_ip6.add_vpp_config()
2209 # add the BD ARP termination entry for BVI IP
2210 epg.bd_arp_ip4 = VppBridgeDomainArpEntry(self, epg.bd.bd,
2211 str(self.router_mac),
2212 epg.bvi_ip4.address)
2213 epg.bd_arp_ip4.add_vpp_config()
2216 epg.add_vpp_config()
2224 self.logger.info(self.vapi.cli("show gbp endpoint"))
2225 self.logger.info(self.vapi.cli("show interface"))
2226 self.logger.info(self.vapi.cli("show br"))
2229 # Intra epg allowed without contract
2231 pkt_intra_epg_220_to_220 = (Ether(src=self.pg0.remote_mac,
2232 dst=self.pg1.remote_mac) /
2233 IP(src=eps[0].ip4.address,
2234 dst=eps[1].ip4.address) /
2235 UDP(sport=1234, dport=1234) /
2238 self.send_and_expect_bridged(self.pg0,
2239 pkt_intra_epg_220_to_220 * 65,
2242 pkt_intra_epg_220_to_220 = (Ether(src=self.pg0.remote_mac,
2243 dst=self.pg1.remote_mac) /
2244 IPv6(src=eps[0].ip6.address,
2245 dst=eps[1].ip6.address) /
2246 UDP(sport=1234, dport=1234) /
2249 self.send_and_expect_bridged6(self.pg0,
2250 pkt_intra_epg_220_to_220 * 65,
2254 # Inter epg denied without contract
2256 pkt_inter_epg_220_to_221 = (Ether(src=self.pg0.remote_mac,
2257 dst=self.pg2.remote_mac) /
2258 IP(src=eps[0].ip4.address,
2259 dst=eps[2].ip4.address) /
2260 UDP(sport=1234, dport=1234) /
2263 self.send_and_assert_no_replies(self.pg0, pkt_inter_epg_220_to_221)
2266 # A uni-directional contract from EPG 220 -> 221
2268 acl = VppGbpAcl(self)
2269 rule = acl.create_rule(permit_deny=1, proto=17)
2270 rule2 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
2271 rule3 = acl.create_rule(permit_deny=1, proto=1)
2272 acl_index = acl.add_vpp_config([rule, rule2, rule3])
2273 c1 = VppGbpContract(
2274 self, 400, epgs[0].sclass, epgs[1].sclass, acl_index,
2275 [VppGbpContractRule(
2276 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2277 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2280 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2281 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2284 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2285 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2287 [ETH_P_IP, ETH_P_IPV6])
2290 self.send_and_expect_bridged(eps[0].itf,
2291 pkt_inter_epg_220_to_221 * 65,
2294 pkt_inter_epg_220_to_222 = (Ether(src=self.pg0.remote_mac,
2295 dst=str(self.router_mac)) /
2296 IP(src=eps[0].ip4.address,
2297 dst=eps[3].ip4.address) /
2298 UDP(sport=1234, dport=1234) /
2300 self.send_and_assert_no_replies(eps[0].itf,
2301 pkt_inter_epg_220_to_222 * 65)
2304 # ping router IP in different BD
2306 pkt_router_ping_220_to_221 = (Ether(src=self.pg0.remote_mac,
2307 dst=str(self.router_mac)) /
2308 IP(src=eps[0].ip4.address,
2309 dst=epgs[1].bvi_ip4.address) /
2310 ICMP(type='echo-request'))
2312 self.send_and_expect(self.pg0, [pkt_router_ping_220_to_221], self.pg0)
2314 pkt_router_ping_220_to_221 = (Ether(src=self.pg0.remote_mac,
2315 dst=str(self.router_mac)) /
2316 IPv6(src=eps[0].ip6.address,
2317 dst=epgs[1].bvi_ip6.address) /
2318 ICMPv6EchoRequest())
2320 self.send_and_expect(self.pg0, [pkt_router_ping_220_to_221], self.pg0)
2323 # contract for the return direction
2325 c2 = VppGbpContract(
2326 self, 400, epgs[1].sclass, epgs[0].sclass, acl_index,
2327 [VppGbpContractRule(
2328 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2329 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2332 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2333 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2335 [ETH_P_IP, ETH_P_IPV6])
2338 self.send_and_expect_bridged(eps[0].itf,
2339 pkt_inter_epg_220_to_221 * 65,
2341 pkt_inter_epg_221_to_220 = (Ether(src=self.pg2.remote_mac,
2342 dst=self.pg0.remote_mac) /
2343 IP(src=eps[2].ip4.address,
2344 dst=eps[0].ip4.address) /
2345 UDP(sport=1234, dport=1234) /
2347 self.send_and_expect_bridged(eps[2].itf,
2348 pkt_inter_epg_221_to_220 * 65,
2350 pkt_inter_epg_221_to_220 = (Ether(src=self.pg2.remote_mac,
2351 dst=str(self.router_mac)) /
2352 IP(src=eps[2].ip4.address,
2353 dst=eps[0].ip4.address) /
2354 UDP(sport=1234, dport=1234) /
2356 self.send_and_expect_routed(eps[2].itf,
2357 pkt_inter_epg_221_to_220 * 65,
2359 str(self.router_mac))
2360 pkt_inter_epg_221_to_220 = (Ether(src=self.pg2.remote_mac,
2361 dst=str(self.router_mac)) /
2362 IPv6(src=eps[2].ip6.address,
2363 dst=eps[0].ip6.address) /
2364 UDP(sport=1234, dport=1234) /
2366 self.send_and_expect_routed6(eps[2].itf,
2367 pkt_inter_epg_221_to_220 * 65,
2369 str(self.router_mac))
2372 # contract between 220 and 222 uni-direction
2374 c3 = VppGbpContract(
2375 self, 400, epgs[0].sclass, epgs[2].sclass, acl_index,
2376 [VppGbpContractRule(
2377 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2378 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2381 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2382 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2384 [ETH_P_IP, ETH_P_IPV6])
2387 self.send_and_expect(eps[0].itf,
2388 pkt_inter_epg_220_to_222 * 65,
2391 c3.remove_vpp_config()
2392 c1.remove_vpp_config()
2393 c2.remove_vpp_config()
2394 acl.remove_vpp_config()
2396 def test_gbp_bd_drop_flags(self):
2397 """ GBP BD drop flags """
2402 gt4 = VppIpTable(self, 1)
2403 gt4.add_vpp_config()
2404 gt6 = VppIpTable(self, 1, is_ip6=True)
2405 gt6.add_vpp_config()
2407 rd1 = VppGbpRouteDomain(self, 1, 401, gt4, gt6)
2408 rd1.add_vpp_config()
2411 # a GBP bridge domain with a BVI only
2413 bd1 = VppBridgeDomain(self, 1)
2414 bd1.add_vpp_config()
2416 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0,
2418 uu_drop=True, bm_drop=True)
2419 gbd1.add_vpp_config()
2421 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2422 self.logger.info(self.vapi.cli("sh gbp bridge"))
2424 # ... and has a /32 applied
2425 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2426 ip_addr.add_vpp_config()
2429 # The Endpoint-group
2431 epg_220 = VppGbpEndpointGroup(self, 220, 112, rd1, gbd1,
2435 VppGbpEndpointRetention(2))
2436 epg_220.add_vpp_config()
2438 ep = VppGbpEndpoint(self, self.pg0,
2440 "10.0.0.127", "11.0.0.127",
2441 "2001:10::1", "3001::1")
2445 # send UU/BM packet from the local EP with UU drop and BM drop enabled
2448 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2449 self.logger.info(self.vapi.cli("sh gbp bridge"))
2450 p_uu = (Ether(src=ep.mac, dst="00:11:11:11:11:11") /
2451 IP(dst="10.0.0.133", src=ep.ip4.address) /
2452 UDP(sport=1234, dport=1234) /
2454 self.send_and_assert_no_replies(ep.itf, [p_uu])
2456 p_bm = (Ether(src=ep.mac, dst="ff:ff:ff:ff:ff:ff") /
2457 IP(dst="10.0.0.133", src=ep.ip4.address) /
2458 UDP(sport=1234, dport=1234) /
2460 self.send_and_assert_no_replies(ep.itf, [p_bm])
2462 self.pg3.unconfig_ip4()
2464 self.logger.info(self.vapi.cli("sh int"))
2466 def test_gbp_bd_arp_flags(self):
2467 """ GBP BD arp flags """
2472 gt4 = VppIpTable(self, 1)
2473 gt4.add_vpp_config()
2474 gt6 = VppIpTable(self, 1, is_ip6=True)
2475 gt6.add_vpp_config()
2477 rd1 = VppGbpRouteDomain(self, 1, 401, gt4, gt6)
2478 rd1.add_vpp_config()
2481 # Pg4 hosts the IP6 UU-flood VXLAN tunnel
2483 self.pg4.config_ip4()
2484 self.pg4.resolve_arp()
2487 # Add a mcast destination VXLAN-GBP tunnel for B&M traffic
2489 tun_uu = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
2492 tun_uu.add_vpp_config()
2495 # a GBP bridge domain with a BVI and a UU-flood interface
2497 bd1 = VppBridgeDomain(self, 1)
2498 bd1.add_vpp_config()
2500 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0,
2503 gbd1.add_vpp_config()
2505 # ... and has a /32 applied
2506 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2507 ip_addr.add_vpp_config()
2510 # The Endpoint-group
2512 epg_220 = VppGbpEndpointGroup(self, 220, 112, rd1, gbd1,
2516 VppGbpEndpointRetention(2))
2517 epg_220.add_vpp_config()
2519 ep = VppGbpEndpoint(self, self.pg0,
2521 "10.0.0.127", "11.0.0.127",
2522 "2001:10::1", "3001::1")
2526 # send ARP packet from the local EP expect it on the uu interface
2528 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2529 self.logger.info(self.vapi.cli("sh gbp bridge"))
2530 p_arp = (Ether(src=ep.mac, dst="ff:ff:ff:ff:ff:ff") /
2532 psrc=ep.ip4.address, pdst="10.0.0.99",
2534 hwdst="ff:ff:ff:ff:ff:ff"))
2535 self.send_and_expect(ep.itf, [p_arp], self.pg4)
2537 self.pg4.unconfig_ip4()
2539 def test_gbp_learn_vlan_l2(self):
2540 """ GBP L2 Endpoint w/ VLANs"""
2542 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
2543 learnt = [{'mac': '00:00:11:11:11:01',
2545 'ip6': '2001:10::2'},
2546 {'mac': '00:00:11:11:11:02',
2548 'ip6': '2001:10::3'}]
2553 gt4 = VppIpTable(self, 1)
2554 gt4.add_vpp_config()
2555 gt6 = VppIpTable(self, 1, is_ip6=True)
2556 gt6.add_vpp_config()
2558 rd1 = VppGbpRouteDomain(self, 1, 401, gt4, gt6)
2559 rd1.add_vpp_config()
2562 # Pg2 hosts the vxlan tunnel, hosts on pg2 to act as TEPs
2564 self.pg2.config_ip4()
2565 self.pg2.resolve_arp()
2566 self.pg2.generate_remote_hosts(4)
2567 self.pg2.configure_ipv4_neighbors()
2568 self.pg3.config_ip4()
2569 self.pg3.resolve_arp()
2572 # The EP will be on a vlan sub-interface
2574 vlan_11 = VppDot1QSubint(self, self.pg0, 11)
2576 self.vapi.l2_interface_vlan_tag_rewrite(
2577 sw_if_index=vlan_11.sw_if_index, vtr_op=L2_VTR_OP.L2_POP_1,
2580 bd_uu_fwd = VppVxlanGbpTunnel(self, self.pg3.local_ip4,
2581 self.pg3.remote_ip4, 116)
2582 bd_uu_fwd.add_vpp_config()
2585 # a GBP bridge domain with a BVI and a UU-flood interface
2586 # The BD is marked as do not learn, so no endpoints are ever
2587 # learnt in this BD.
2589 bd1 = VppBridgeDomain(self, 1)
2590 bd1.add_vpp_config()
2591 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0, bd_uu_fwd,
2593 gbd1.add_vpp_config()
2595 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2596 self.logger.info(self.vapi.cli("sh gbp bridge"))
2598 # ... and has a /32 applied
2599 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2600 ip_addr.add_vpp_config()
2603 # The Endpoint-group in which we are learning endpoints
2605 epg_220 = VppGbpEndpointGroup(self, 220, 441, rd1, gbd1,
2609 VppGbpEndpointRetention(2))
2610 epg_220.add_vpp_config()
2613 # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
2616 vx_tun_l2_1 = VppGbpVxlanTunnel(
2617 self, 99, bd1.bd_id,
2618 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L2,
2620 vx_tun_l2_1.add_vpp_config()
2623 # A static endpoint that the learnt endpoints are trying to
2626 ep = VppGbpEndpoint(self, vlan_11,
2628 "10.0.0.127", "11.0.0.127",
2629 "2001:10::1", "3001::1")
2632 self.assertTrue(find_route(self, ep.ip4.address, 32, table_id=1))
2635 # Send to the static EP
2637 for ii, l in enumerate(learnt):
2638 # a packet with an sclass from a known EPG
2639 # arriving on an unknown TEP
2640 p = (Ether(src=self.pg2.remote_mac,
2641 dst=self.pg2.local_mac) /
2642 IP(src=self.pg2.remote_hosts[1].ip4,
2643 dst=self.pg2.local_ip4) /
2644 UDP(sport=1234, dport=48879) /
2645 VXLAN(vni=99, gpid=441, flags=0x88) /
2646 Ether(src=l['mac'], dst=ep.mac) /
2647 IP(src=l['ip'], dst=ep.ip4.address) /
2648 UDP(sport=1234, dport=1234) /
2651 rxs = self.send_and_expect(self.pg2, [p], self.pg0)
2654 # packet to EP has the EP's vlan tag
2657 self.assertEqual(rx[Dot1Q].vlan, 11)
2660 # the EP is not learnt since the BD setting prevents it
2663 self.assertFalse(find_gbp_endpoint(self,
2664 vx_tun_l2_1.sw_if_index,
2666 self.assertEqual(INDEX_INVALID,
2667 find_vxlan_gbp_tunnel(
2670 self.pg2.remote_hosts[1].ip4,
2673 self.assertEqual(len(self.vapi.gbp_endpoint_dump()), 1)
2677 # we didn't learn the remotes so they are sent to the UU-fwd
2680 p = (Ether(src=ep.mac, dst=l['mac']) /
2682 IP(dst=l['ip'], src=ep.ip4.address) /
2683 UDP(sport=1234, dport=1234) /
2686 rxs = self.send_and_expect(self.pg0, p * 17, self.pg3)
2689 self.assertEqual(rx[IP].src, self.pg3.local_ip4)
2690 self.assertEqual(rx[IP].dst, self.pg3.remote_ip4)
2691 self.assertEqual(rx[UDP].dport, 48879)
2692 # the UDP source port is a random value for hashing
2693 self.assertEqual(rx[VXLAN].gpid, 441)
2694 self.assertEqual(rx[VXLAN].vni, 116)
2695 self.assertTrue(rx[VXLAN].flags.G)
2696 self.assertTrue(rx[VXLAN].flags.Instance)
2697 self.assertFalse(rx[VXLAN].gpflags.A)
2698 self.assertFalse(rx[VXLAN].gpflags.D)
2700 self.pg2.unconfig_ip4()
2701 self.pg3.unconfig_ip4()
2703 def test_gbp_learn_l3(self):
2704 """ GBP L3 Endpoint Learning """
2706 self.vapi.cli("set logging class gbp level debug")
2708 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
2709 routed_dst_mac = "00:0c:0c:0c:0c:0c"
2710 routed_src_mac = "00:22:bd:f8:19:ff"
2712 learnt = [{'mac': '00:00:11:11:11:02',
2714 'ip6': '2001:10::2'},
2715 {'mac': '00:00:11:11:11:03',
2717 'ip6': '2001:10::3'}]
2722 t4 = VppIpTable(self, 1)
2724 t6 = VppIpTable(self, 1, True)
2727 tun_ip4_uu = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
2728 self.pg4.remote_ip4, 114)
2729 tun_ip6_uu = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
2730 self.pg4.remote_ip4, 116)
2731 tun_ip4_uu.add_vpp_config()
2732 tun_ip6_uu.add_vpp_config()
2734 rd1 = VppGbpRouteDomain(self, 2, 401, t4, t6, tun_ip4_uu, tun_ip6_uu)
2735 rd1.add_vpp_config()
2737 self.loop0.set_mac(self.router_mac)
2740 # Bind the BVI to the RD
2742 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
2743 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
2746 # Pg2 hosts the vxlan tunnel
2747 # hosts on pg2 to act as TEPs
2751 self.pg2.config_ip4()
2752 self.pg2.resolve_arp()
2753 self.pg2.generate_remote_hosts(4)
2754 self.pg2.configure_ipv4_neighbors()
2755 self.pg3.config_ip4()
2756 self.pg3.resolve_arp()
2757 self.pg4.config_ip4()
2758 self.pg4.resolve_arp()
2761 # a GBP bridge domain with a BVI and a UU-flood interface
2763 bd1 = VppBridgeDomain(self, 1)
2764 bd1.add_vpp_config()
2765 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0, self.pg3)
2766 gbd1.add_vpp_config()
2768 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2769 self.logger.info(self.vapi.cli("sh gbp bridge"))
2770 self.logger.info(self.vapi.cli("sh gbp route"))
2772 # ... and has a /32 and /128 applied
2773 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2774 ip4_addr.add_vpp_config()
2775 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 128)
2776 ip6_addr.add_vpp_config()
2779 # The Endpoint-group in which we are learning endpoints
2781 epg_220 = VppGbpEndpointGroup(self, 220, 441, rd1, gbd1,
2785 VppGbpEndpointRetention(2))
2786 epg_220.add_vpp_config()
2789 # The VXLAN GBP tunnel is in L3 mode with learning enabled
2791 vx_tun_l3 = VppGbpVxlanTunnel(
2792 self, 101, rd1.rd_id,
2793 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
2795 vx_tun_l3.add_vpp_config()
2798 # A static endpoint that the learnt endpoints are trying to
2801 ep = VppGbpEndpoint(self, self.pg0,
2803 "10.0.0.127", "11.0.0.127",
2804 "2001:10::1", "3001::1")
2808 # learn some remote IPv4 EPs
2810 for ii, l in enumerate(learnt):
2811 # a packet with an sclass from a known EPG
2812 # arriving on an unknown TEP
2813 p = (Ether(src=self.pg2.remote_mac,
2814 dst=self.pg2.local_mac) /
2815 IP(src=self.pg2.remote_hosts[1].ip4,
2816 dst=self.pg2.local_ip4) /
2817 UDP(sport=1234, dport=48879) /
2818 VXLAN(vni=101, gpid=441, flags=0x88) /
2819 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2820 IP(src=l['ip'], dst=ep.ip4.address) /
2821 UDP(sport=1234, dport=1234) /
2824 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2827 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2830 self.pg2.remote_hosts[1].ip4,
2832 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2834 # endpoint learnt via the parent GBP-vxlan interface
2835 self.assertTrue(find_gbp_endpoint(self,
2836 vx_tun_l3._sw_if_index,
2840 # Static IPv4 EP replies to learnt
2843 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2844 IP(dst=l['ip'], src=ep.ip4.address) /
2845 UDP(sport=1234, dport=1234) /
2848 rxs = self.send_and_expect(self.pg0, p * 1, self.pg2)
2851 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2852 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2853 self.assertEqual(rx[UDP].dport, 48879)
2854 # the UDP source port is a random value for hashing
2855 self.assertEqual(rx[VXLAN].gpid, 441)
2856 self.assertEqual(rx[VXLAN].vni, 101)
2857 self.assertTrue(rx[VXLAN].flags.G)
2858 self.assertTrue(rx[VXLAN].flags.Instance)
2859 self.assertTrue(rx[VXLAN].gpflags.A)
2860 self.assertFalse(rx[VXLAN].gpflags.D)
2862 inner = rx[VXLAN].payload
2864 self.assertEqual(inner[Ether].src, routed_src_mac)
2865 self.assertEqual(inner[Ether].dst, routed_dst_mac)
2866 self.assertEqual(inner[IP].src, ep.ip4.address)
2867 self.assertEqual(inner[IP].dst, l['ip'])
2870 self.assertFalse(find_gbp_endpoint(self,
2875 # learn some remote IPv6 EPs
2877 for ii, l in enumerate(learnt):
2878 # a packet with an sclass from a known EPG
2879 # arriving on an unknown TEP
2880 p = (Ether(src=self.pg2.remote_mac,
2881 dst=self.pg2.local_mac) /
2882 IP(src=self.pg2.remote_hosts[1].ip4,
2883 dst=self.pg2.local_ip4) /
2884 UDP(sport=1234, dport=48879) /
2885 VXLAN(vni=101, gpid=441, flags=0x88) /
2886 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2887 IPv6(src=l['ip6'], dst=ep.ip6.address) /
2888 UDP(sport=1234, dport=1234) /
2891 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2894 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2897 self.pg2.remote_hosts[1].ip4,
2899 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2901 self.logger.info(self.vapi.cli("show gbp bridge"))
2902 self.logger.info(self.vapi.cli("show vxlan-gbp tunnel"))
2903 self.logger.info(self.vapi.cli("show gbp vxlan"))
2904 self.logger.info(self.vapi.cli("show int addr"))
2906 # endpoint learnt via the TEP
2907 self.assertTrue(find_gbp_endpoint(self, ip=l['ip6']))
2909 self.logger.info(self.vapi.cli("show gbp endpoint"))
2910 self.logger.info(self.vapi.cli("show ip fib index 1 %s" % l['ip']))
2913 # Static EP replies to learnt
2916 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2917 IPv6(dst=l['ip6'], src=ep.ip6.address) /
2918 UDP(sport=1234, dport=1234) /
2921 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
2924 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2925 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2926 self.assertEqual(rx[UDP].dport, 48879)
2927 # the UDP source port is a random value for hashing
2928 self.assertEqual(rx[VXLAN].gpid, 441)
2929 self.assertEqual(rx[VXLAN].vni, 101)
2930 self.assertTrue(rx[VXLAN].flags.G)
2931 self.assertTrue(rx[VXLAN].flags.Instance)
2932 self.assertTrue(rx[VXLAN].gpflags.A)
2933 self.assertFalse(rx[VXLAN].gpflags.D)
2935 inner = rx[VXLAN].payload
2937 self.assertEqual(inner[Ether].src, routed_src_mac)
2938 self.assertEqual(inner[Ether].dst, routed_dst_mac)
2939 self.assertEqual(inner[IPv6].src, ep.ip6.address)
2940 self.assertEqual(inner[IPv6].dst, l['ip6'])
2942 self.logger.info(self.vapi.cli("sh gbp endpoint"))
2944 self.wait_for_ep_timeout(ip=l['ip'])
2947 # Static sends to unknown EP with no route
2949 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2950 IP(dst="10.0.0.99", src=ep.ip4.address) /
2951 UDP(sport=1234, dport=1234) /
2954 self.send_and_assert_no_replies(self.pg0, [p])
2957 # Add a route to static EP's v4 and v6 subnet
2959 se_10_24 = VppGbpSubnet(
2960 self, rd1, "10.0.0.0", 24,
2961 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT)
2962 se_10_24.add_vpp_config()
2965 # static pings router
2967 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2968 IP(dst=epg_220.bvi_ip4.address, src=ep.ip4.address) /
2969 UDP(sport=1234, dport=1234) /
2972 self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg0)
2974 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2975 IPv6(dst=epg_220.bvi_ip6.address, src=ep.ip6.address) /
2976 UDP(sport=1234, dport=1234) /
2979 self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg0)
2982 # packets to address in the subnet are sent on the uu-fwd
2984 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2985 IP(dst="10.0.0.99", src=ep.ip4.address) /
2986 UDP(sport=1234, dport=1234) /
2989 rxs = self.send_and_expect(self.pg0, [p], self.pg4)
2991 self.assertEqual(rx[IP].src, self.pg4.local_ip4)
2992 self.assertEqual(rx[IP].dst, self.pg4.remote_ip4)
2993 self.assertEqual(rx[UDP].dport, 48879)
2994 # the UDP source port is a random value for hashing
2995 self.assertEqual(rx[VXLAN].gpid, 441)
2996 self.assertEqual(rx[VXLAN].vni, 114)
2997 self.assertTrue(rx[VXLAN].flags.G)
2998 self.assertTrue(rx[VXLAN].flags.Instance)
2999 # policy is not applied to packets sent to the uu-fwd interfaces
3000 self.assertFalse(rx[VXLAN].gpflags.A)
3001 self.assertFalse(rx[VXLAN].gpflags.D)
3004 # learn some remote IPv4 EPs
3006 for ii, l in enumerate(learnt):
3007 # a packet with an sclass from a known EPG
3008 # arriving on an unknown TEP
3009 p = (Ether(src=self.pg2.remote_mac,
3010 dst=self.pg2.local_mac) /
3011 IP(src=self.pg2.remote_hosts[2].ip4,
3012 dst=self.pg2.local_ip4) /
3013 UDP(sport=1234, dport=48879) /
3014 VXLAN(vni=101, gpid=441, flags=0x88) /
3015 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
3016 IP(src=l['ip'], dst=ep.ip4.address) /
3017 UDP(sport=1234, dport=1234) /
3020 rx = self.send_and_expect(self.pg2, [p], self.pg0)
3023 tep1_sw_if_index = find_vxlan_gbp_tunnel(
3026 self.pg2.remote_hosts[2].ip4,
3028 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
3030 # endpoint learnt via the parent GBP-vxlan interface
3031 self.assertTrue(find_gbp_endpoint(self,
3032 vx_tun_l3._sw_if_index,
3036 # Add a remote endpoint from the API
3038 rep_88 = VppGbpEndpoint(self, vx_tun_l3,
3040 "10.0.0.88", "11.0.0.88",
3041 "2001:10::88", "3001::88",
3042 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
3044 self.pg2.remote_hosts[2].ip4,
3046 rep_88.add_vpp_config()
3049 # Add a remote endpoint from the API that matches an existing one
3050 # this is a lower priority, hence the packet is sent to the DP leanrt
3053 rep_2 = VppGbpEndpoint(self, vx_tun_l3,
3055 learnt[0]['ip'], "11.0.0.101",
3056 learnt[0]['ip6'], "3001::101",
3057 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
3059 self.pg2.remote_hosts[1].ip4,
3061 rep_2.add_vpp_config()
3064 # Add a route to the learned EP's v4 subnet
3065 # packets should be send on the v4/v6 uu=fwd interface resp.
3067 se_10_1_24 = VppGbpSubnet(
3068 self, rd1, "10.0.1.0", 24,
3069 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT)
3070 se_10_1_24.add_vpp_config()
3072 self.logger.info(self.vapi.cli("show gbp endpoint"))
3074 ips = ["10.0.0.88", learnt[0]['ip']]
3076 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
3077 IP(dst=ip, src=ep.ip4.address) /
3078 UDP(sport=1234, dport=1234) /
3081 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
3084 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
3085 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[2].ip4)
3086 self.assertEqual(rx[UDP].dport, 48879)
3087 # the UDP source port is a random value for hashing
3088 self.assertEqual(rx[VXLAN].gpid, 441)
3089 self.assertEqual(rx[VXLAN].vni, 101)
3090 self.assertTrue(rx[VXLAN].flags.G)
3091 self.assertTrue(rx[VXLAN].flags.Instance)
3092 self.assertTrue(rx[VXLAN].gpflags.A)
3093 self.assertFalse(rx[VXLAN].gpflags.D)
3095 inner = rx[VXLAN].payload
3097 self.assertEqual(inner[Ether].src, routed_src_mac)
3098 self.assertEqual(inner[Ether].dst, routed_dst_mac)
3099 self.assertEqual(inner[IP].src, ep.ip4.address)
3100 self.assertEqual(inner[IP].dst, ip)
3103 # remove the API remote EPs, only API sourced is gone, the DP
3104 # learnt one remains
3106 rep_88.remove_vpp_config()
3107 rep_2.remove_vpp_config()
3109 self.assertTrue(find_gbp_endpoint(self, ip=rep_2.ip4.address))
3111 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
3112 IP(src=ep.ip4.address, dst=rep_2.ip4.address) /
3113 UDP(sport=1234, dport=1234) /
3115 rxs = self.send_and_expect(self.pg0, [p], self.pg2)
3117 self.assertFalse(find_gbp_endpoint(self, ip=rep_88.ip4.address))
3119 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
3120 IP(src=ep.ip4.address, dst=rep_88.ip4.address) /
3121 UDP(sport=1234, dport=1234) /
3123 rxs = self.send_and_expect(self.pg0, [p], self.pg4)
3126 # to appease the testcase we cannot have the registered EP still
3127 # present (because it's DP learnt) when the TC ends so wait until
3130 self.wait_for_ep_timeout(ip=rep_88.ip4.address)
3131 self.wait_for_ep_timeout(ip=rep_2.ip4.address)
3134 # Same as above, learn a remote EP via CP and DP
3135 # this time remove the DP one first. expect the CP data to remain
3137 rep_3 = VppGbpEndpoint(self, vx_tun_l3,
3139 "10.0.1.4", "11.0.0.103",
3140 "2001::10:3", "3001::103",
3141 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
3143 self.pg2.remote_hosts[1].ip4,
3145 rep_3.add_vpp_config()
3147 p = (Ether(src=self.pg2.remote_mac,
3148 dst=self.pg2.local_mac) /
3149 IP(src=self.pg2.remote_hosts[2].ip4,
3150 dst=self.pg2.local_ip4) /
3151 UDP(sport=1234, dport=48879) /
3152 VXLAN(vni=101, gpid=441, flags=0x88) /
3153 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
3154 IP(src="10.0.1.4", dst=ep.ip4.address) /
3155 UDP(sport=1234, dport=1234) /
3157 rxs = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
3159 self.assertTrue(find_gbp_endpoint(self,
3160 vx_tun_l3._sw_if_index,
3161 ip=rep_3.ip4.address,
3162 tep=[self.pg2.local_ip4,
3163 self.pg2.remote_hosts[2].ip4]))
3165 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
3166 IP(dst="10.0.1.4", src=ep.ip4.address) /
3167 UDP(sport=1234, dport=1234) /
3169 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
3171 # host 2 is the DP learned TEP
3173 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
3174 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[2].ip4)
3176 self.wait_for_ep_timeout(ip=rep_3.ip4.address,
3177 tep=[self.pg2.local_ip4,
3178 self.pg2.remote_hosts[2].ip4])
3180 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
3182 # host 1 is the CP learned TEP
3184 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
3185 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
3188 # shutdown with learnt endpoint present
3190 p = (Ether(src=self.pg2.remote_mac,
3191 dst=self.pg2.local_mac) /
3192 IP(src=self.pg2.remote_hosts[1].ip4,
3193 dst=self.pg2.local_ip4) /
3194 UDP(sport=1234, dport=48879) /
3195 VXLAN(vni=101, gpid=441, flags=0x88) /
3196 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
3197 IP(src=learnt[1]['ip'], dst=ep.ip4.address) /
3198 UDP(sport=1234, dport=1234) /
3201 rx = self.send_and_expect(self.pg2, [p], self.pg0)
3203 # endpoint learnt via the parent GBP-vxlan interface
3204 self.assertTrue(find_gbp_endpoint(self,
3205 vx_tun_l3._sw_if_index,
3210 # remote endpoint becomes local
3212 self.pg2.unconfig_ip4()
3213 self.pg3.unconfig_ip4()
3214 self.pg4.unconfig_ip4()
3216 def test_gbp_redirect(self):
3217 """ GBP Endpoint Redirect """
3219 self.vapi.cli("set logging class gbp level debug")
3221 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
3222 routed_dst_mac = "00:0c:0c:0c:0c:0c"
3223 routed_src_mac = "00:22:bd:f8:19:ff"
3225 learnt = [{'mac': '00:00:11:11:11:02',
3227 'ip6': '2001:10::2'},
3228 {'mac': '00:00:11:11:11:03',
3230 'ip6': '2001:10::3'}]
3235 t4 = VppIpTable(self, 1)
3237 t6 = VppIpTable(self, 1, True)
3240 rd1 = VppGbpRouteDomain(self, 2, 402, t4, t6)
3241 rd1.add_vpp_config()
3243 self.loop0.set_mac(self.router_mac)
3246 # Bind the BVI to the RD
3248 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
3249 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
3252 # Pg7 hosts a BD's UU-fwd
3254 self.pg7.config_ip4()
3255 self.pg7.resolve_arp()
3258 # a GBP bridge domains for the EPs
3260 bd1 = VppBridgeDomain(self, 1)
3261 bd1.add_vpp_config()
3262 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0)
3263 gbd1.add_vpp_config()
3265 bd2 = VppBridgeDomain(self, 2)
3266 bd2.add_vpp_config()
3267 gbd2 = VppGbpBridgeDomain(self, bd2, rd1, self.loop1)
3268 gbd2.add_vpp_config()
3270 # ... and has a /32 and /128 applied
3271 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
3272 ip4_addr.add_vpp_config()
3273 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 128)
3274 ip6_addr.add_vpp_config()
3275 ip4_addr = VppIpInterfaceAddress(self, gbd2.bvi, "10.0.1.128", 32)
3276 ip4_addr.add_vpp_config()
3277 ip6_addr = VppIpInterfaceAddress(self, gbd2.bvi, "2001:11::128", 128)
3278 ip6_addr.add_vpp_config()
3281 # The Endpoint-groups in which we are learning endpoints
3283 epg_220 = VppGbpEndpointGroup(self, 220, 440, rd1, gbd1,
3287 VppGbpEndpointRetention(2))
3288 epg_220.add_vpp_config()
3289 epg_221 = VppGbpEndpointGroup(self, 221, 441, rd1, gbd2,
3293 VppGbpEndpointRetention(2))
3294 epg_221.add_vpp_config()
3295 epg_222 = VppGbpEndpointGroup(self, 222, 442, rd1, gbd1,
3299 VppGbpEndpointRetention(2))
3300 epg_222.add_vpp_config()
3303 # a GBP bridge domains for the SEPs
3305 bd_uu1 = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
3306 self.pg7.remote_ip4, 116)
3307 bd_uu1.add_vpp_config()
3308 bd_uu2 = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
3309 self.pg7.remote_ip4, 117)
3310 bd_uu2.add_vpp_config()
3312 bd3 = VppBridgeDomain(self, 3)
3313 bd3.add_vpp_config()
3314 gbd3 = VppGbpBridgeDomain(self, bd3, rd1, self.loop2,
3315 bd_uu1, learn=False)
3316 gbd3.add_vpp_config()
3317 bd4 = VppBridgeDomain(self, 4)
3318 bd4.add_vpp_config()
3319 gbd4 = VppGbpBridgeDomain(self, bd4, rd1, self.loop3,
3320 bd_uu2, learn=False)
3321 gbd4.add_vpp_config()
3324 # EPGs in which the service endpoints exist
3326 epg_320 = VppGbpEndpointGroup(self, 320, 550, rd1, gbd3,
3330 VppGbpEndpointRetention(2))
3331 epg_320.add_vpp_config()
3332 epg_321 = VppGbpEndpointGroup(self, 321, 551, rd1, gbd4,
3336 VppGbpEndpointRetention(2))
3337 epg_321.add_vpp_config()
3340 # three local endpoints
3342 ep1 = VppGbpEndpoint(self, self.pg0,
3344 "10.0.0.1", "11.0.0.1",
3345 "2001:10::1", "3001:10::1")
3346 ep1.add_vpp_config()
3347 ep2 = VppGbpEndpoint(self, self.pg1,
3349 "10.0.1.1", "11.0.1.1",
3350 "2001:11::1", "3001:11::1")
3351 ep2.add_vpp_config()
3352 ep3 = VppGbpEndpoint(self, self.pg2,
3354 "10.0.2.2", "11.0.2.2",
3355 "2001:12::1", "3001:12::1")
3356 ep3.add_vpp_config()
3361 sep1 = VppGbpEndpoint(self, self.pg3,
3363 "12.0.0.1", "13.0.0.1",
3364 "4001:10::1", "5001:10::1")
3365 sep1.add_vpp_config()
3366 sep2 = VppGbpEndpoint(self, self.pg4,
3368 "12.0.0.2", "13.0.0.2",
3369 "4001:10::2", "5001:10::2")
3370 sep2.add_vpp_config()
3371 sep3 = VppGbpEndpoint(self, self.pg5,
3373 "12.0.1.1", "13.0.1.1",
3374 "4001:11::1", "5001:11::1")
3375 sep3.add_vpp_config()
3376 # this EP is not installed immediately
3377 sep4 = VppGbpEndpoint(self, self.pg6,
3379 "12.0.1.2", "13.0.1.2",
3380 "4001:11::2", "5001:11::2")
3383 # an L2 switch packet between local EPs in different EPGs
3384 # different dest ports on each so the are LB hashed differently
3386 p4 = [(Ether(src=ep1.mac, dst=ep3.mac) /
3387 IP(src=ep1.ip4.address, dst=ep3.ip4.address) /
3388 UDP(sport=1234, dport=1234) /
3390 (Ether(src=ep3.mac, dst=ep1.mac) /
3391 IP(src=ep3.ip4.address, dst=ep1.ip4.address) /
3392 UDP(sport=1234, dport=1234) /
3394 p6 = [(Ether(src=ep1.mac, dst=ep3.mac) /
3395 IPv6(src=ep1.ip6.address, dst=ep3.ip6.address) /
3396 UDP(sport=1234, dport=1234) /
3398 (Ether(src=ep3.mac, dst=ep1.mac) /
3399 IPv6(src=ep3.ip6.address, dst=ep1.ip6.address) /
3400 UDP(sport=1234, dport=1230) /
3403 # should be dropped since no contract yet
3404 self.send_and_assert_no_replies(self.pg0, [p4[0]])
3405 self.send_and_assert_no_replies(self.pg0, [p6[0]])
3408 # Add a contract with a rule to load-balance redirect via SEP1 and SEP2
3409 # one of the next-hops is via an EP that is not known
3411 acl = VppGbpAcl(self)
3412 rule4 = acl.create_rule(permit_deny=1, proto=17)
3413 rule6 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
3414 acl_index = acl.add_vpp_config([rule4, rule6])
3417 # test the src-ip hash mode
3419 c1 = VppGbpContract(
3420 self, 402, epg_220.sclass, epg_222.sclass, acl_index,
3421 [VppGbpContractRule(
3422 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3423 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3424 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3425 sep1.ip4, sep1.epg.rd),
3426 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3427 sep2.ip4, sep2.epg.rd)]),
3429 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3430 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3431 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3432 sep3.ip6, sep3.epg.rd),
3433 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3434 sep4.ip6, sep4.epg.rd)])],
3435 [ETH_P_IP, ETH_P_IPV6])
3438 c2 = VppGbpContract(
3439 self, 402, epg_222.sclass, epg_220.sclass, acl_index,
3440 [VppGbpContractRule(
3441 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3442 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3443 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3444 sep1.ip4, sep1.epg.rd),
3445 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3446 sep2.ip4, sep2.epg.rd)]),
3448 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3449 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3450 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3451 sep3.ip6, sep3.epg.rd),
3452 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3453 sep4.ip6, sep4.epg.rd)])],
3454 [ETH_P_IP, ETH_P_IPV6])
3458 # send again with the contract preset, now packets arrive
3459 # at SEP1 or SEP2 depending on the hashing
3461 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3464 self.assertEqual(rx[Ether].src, routed_src_mac)
3465 self.assertEqual(rx[Ether].dst, sep1.mac)
3466 self.assertEqual(rx[IP].src, ep1.ip4.address)
3467 self.assertEqual(rx[IP].dst, ep3.ip4.address)
3469 rxs = self.send_and_expect(self.pg2, p4[1] * 17, sep2.itf)
3472 self.assertEqual(rx[Ether].src, routed_src_mac)
3473 self.assertEqual(rx[Ether].dst, sep2.mac)
3474 self.assertEqual(rx[IP].src, ep3.ip4.address)
3475 self.assertEqual(rx[IP].dst, ep1.ip4.address)
3477 rxs = self.send_and_expect(self.pg0, p6[0] * 17, self.pg7)
3480 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3481 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3482 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3483 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
3484 self.assertEqual(rx[VXLAN].vni, 117)
3485 self.assertTrue(rx[VXLAN].flags.G)
3486 self.assertTrue(rx[VXLAN].flags.Instance)
3487 # redirect policy has been applied
3488 self.assertTrue(rx[VXLAN].gpflags.A)
3489 self.assertFalse(rx[VXLAN].gpflags.D)
3491 inner = rx[VXLAN].payload
3493 self.assertEqual(inner[Ether].src, routed_src_mac)
3494 self.assertEqual(inner[Ether].dst, sep4.mac)
3495 self.assertEqual(inner[IPv6].src, ep1.ip6.address)
3496 self.assertEqual(inner[IPv6].dst, ep3.ip6.address)
3498 rxs = self.send_and_expect(self.pg2, p6[1] * 17, sep3.itf)
3501 self.assertEqual(rx[Ether].src, routed_src_mac)
3502 self.assertEqual(rx[Ether].dst, sep3.mac)
3503 self.assertEqual(rx[IPv6].src, ep3.ip6.address)
3504 self.assertEqual(rx[IPv6].dst, ep1.ip6.address)
3507 # programme the unknown EP
3509 sep4.add_vpp_config()
3511 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep4.itf)
3514 self.assertEqual(rx[Ether].src, routed_src_mac)
3515 self.assertEqual(rx[Ether].dst, sep4.mac)
3516 self.assertEqual(rx[IPv6].src, ep1.ip6.address)
3517 self.assertEqual(rx[IPv6].dst, ep3.ip6.address)
3520 # and revert back to unprogrammed
3522 sep4.remove_vpp_config()
3524 rxs = self.send_and_expect(self.pg0, p6[0] * 17, self.pg7)
3527 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3528 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3529 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3530 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
3531 self.assertEqual(rx[VXLAN].vni, 117)
3532 self.assertTrue(rx[VXLAN].flags.G)
3533 self.assertTrue(rx[VXLAN].flags.Instance)
3534 # redirect policy has been applied
3535 self.assertTrue(rx[VXLAN].gpflags.A)
3536 self.assertFalse(rx[VXLAN].gpflags.D)
3538 inner = rx[VXLAN].payload
3540 self.assertEqual(inner[Ether].src, routed_src_mac)
3541 self.assertEqual(inner[Ether].dst, sep4.mac)
3542 self.assertEqual(inner[IPv6].src, ep1.ip6.address)
3543 self.assertEqual(inner[IPv6].dst, ep3.ip6.address)
3545 c1.remove_vpp_config()
3546 c2.remove_vpp_config()
3549 # test the symmetric hash mode
3551 c1 = VppGbpContract(
3552 self, 402, epg_220.sclass, epg_222.sclass, acl_index,
3553 [VppGbpContractRule(
3554 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3555 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3556 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3557 sep1.ip4, sep1.epg.rd),
3558 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3559 sep2.ip4, sep2.epg.rd)]),
3561 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3562 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3563 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3564 sep3.ip6, sep3.epg.rd),
3565 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3566 sep4.ip6, sep4.epg.rd)])],
3567 [ETH_P_IP, ETH_P_IPV6])
3570 c2 = VppGbpContract(
3571 self, 402, epg_222.sclass, epg_220.sclass, acl_index,
3572 [VppGbpContractRule(
3573 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3574 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3575 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3576 sep1.ip4, sep1.epg.rd),
3577 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3578 sep2.ip4, sep2.epg.rd)]),
3580 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3581 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3582 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3583 sep3.ip6, sep3.epg.rd),
3584 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3585 sep4.ip6, sep4.epg.rd)])],
3586 [ETH_P_IP, ETH_P_IPV6])
3590 # send again with the contract preset, now packets arrive
3591 # at SEP1 for both directions
3593 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3596 self.assertEqual(rx[Ether].src, routed_src_mac)
3597 self.assertEqual(rx[Ether].dst, sep1.mac)
3598 self.assertEqual(rx[IP].src, ep1.ip4.address)
3599 self.assertEqual(rx[IP].dst, ep3.ip4.address)
3601 rxs = self.send_and_expect(self.pg2, p4[1] * 17, sep1.itf)
3604 self.assertEqual(rx[Ether].src, routed_src_mac)
3605 self.assertEqual(rx[Ether].dst, sep1.mac)
3606 self.assertEqual(rx[IP].src, ep3.ip4.address)
3607 self.assertEqual(rx[IP].dst, ep1.ip4.address)
3610 # programme the unknown EP for the L3 tests
3612 sep4.add_vpp_config()
3615 # an L3 switch packet between local EPs in different EPGs
3616 # different dest ports on each so the are LB hashed differently
3618 p4 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3619 IP(src=ep1.ip4.address, dst=ep2.ip4.address) /
3620 UDP(sport=1234, dport=1234) /
3622 (Ether(src=ep2.mac, dst=str(self.router_mac)) /
3623 IP(src=ep2.ip4.address, dst=ep1.ip4.address) /
3624 UDP(sport=1234, dport=1234) /
3626 p6 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3627 IPv6(src=ep1.ip6.address, dst=ep2.ip6.address) /
3628 UDP(sport=1234, dport=1234) /
3630 (Ether(src=ep2.mac, dst=str(self.router_mac)) /
3631 IPv6(src=ep2.ip6.address, dst=ep1.ip6.address) /
3632 UDP(sport=1234, dport=1234) /
3635 c3 = VppGbpContract(
3636 self, 402, epg_220.sclass, epg_221.sclass, acl_index,
3637 [VppGbpContractRule(
3638 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3639 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3640 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3641 sep1.ip4, sep1.epg.rd),
3642 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3643 sep2.ip4, sep2.epg.rd)]),
3645 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3646 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3647 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3648 sep3.ip6, sep3.epg.rd),
3649 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3650 sep4.ip6, sep4.epg.rd)])],
3651 [ETH_P_IP, ETH_P_IPV6])
3654 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3657 self.assertEqual(rx[Ether].src, routed_src_mac)
3658 self.assertEqual(rx[Ether].dst, sep1.mac)
3659 self.assertEqual(rx[IP].src, ep1.ip4.address)
3660 self.assertEqual(rx[IP].dst, ep2.ip4.address)
3663 # learn a remote EP in EPG 221
3665 vx_tun_l3 = VppGbpVxlanTunnel(
3666 self, 444, rd1.rd_id,
3667 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
3669 vx_tun_l3.add_vpp_config()
3671 c4 = VppGbpContract(
3672 self, 402, epg_221.sclass, epg_220.sclass, acl_index,
3673 [VppGbpContractRule(
3674 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3675 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3678 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3679 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3681 [ETH_P_IP, ETH_P_IPV6])
3684 p = (Ether(src=self.pg7.remote_mac,
3685 dst=self.pg7.local_mac) /
3686 IP(src=self.pg7.remote_ip4,
3687 dst=self.pg7.local_ip4) /
3688 UDP(sport=1234, dport=48879) /
3689 VXLAN(vni=444, gpid=441, flags=0x88) /
3690 Ether(src="00:22:22:22:22:33", dst=str(self.router_mac)) /
3691 IP(src="10.0.0.88", dst=ep1.ip4.address) /
3692 UDP(sport=1234, dport=1234) /
3695 rx = self.send_and_expect(self.pg7, [p], self.pg0)
3697 # endpoint learnt via the parent GBP-vxlan interface
3698 self.assertTrue(find_gbp_endpoint(self,
3699 vx_tun_l3._sw_if_index,
3702 p = (Ether(src=self.pg7.remote_mac,
3703 dst=self.pg7.local_mac) /
3704 IP(src=self.pg7.remote_ip4,
3705 dst=self.pg7.local_ip4) /
3706 UDP(sport=1234, dport=48879) /
3707 VXLAN(vni=444, gpid=441, flags=0x88) /
3708 Ether(src="00:22:22:22:22:33", dst=str(self.router_mac)) /
3709 IPv6(src="2001:10::88", dst=ep1.ip6.address) /
3710 UDP(sport=1234, dport=1234) /
3713 rx = self.send_and_expect(self.pg7, [p], self.pg0)
3715 # endpoint learnt via the parent GBP-vxlan interface
3716 self.assertTrue(find_gbp_endpoint(self,
3717 vx_tun_l3._sw_if_index,
3721 # L3 switch from local to remote EP
3723 p4 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3724 IP(src=ep1.ip4.address, dst="10.0.0.88") /
3725 UDP(sport=1234, dport=1234) /
3727 p6 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3728 IPv6(src=ep1.ip6.address, dst="2001:10::88") /
3729 UDP(sport=1234, dport=1234) /
3732 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3735 self.assertEqual(rx[Ether].src, routed_src_mac)
3736 self.assertEqual(rx[Ether].dst, sep1.mac)
3737 self.assertEqual(rx[IP].src, ep1.ip4.address)
3738 self.assertEqual(rx[IP].dst, "10.0.0.88")
3740 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep4.itf)
3743 self.assertEqual(rx[Ether].src, routed_src_mac)
3744 self.assertEqual(rx[Ether].dst, sep4.mac)
3745 self.assertEqual(rx[IPv6].src, ep1.ip6.address)
3746 self.assertEqual(rx[IPv6].dst, "2001:10::88")
3749 # test the dst-ip hash mode
3751 c5 = VppGbpContract(
3752 self, 402, epg_220.sclass, epg_221.sclass, acl_index,
3753 [VppGbpContractRule(
3754 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3755 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
3756 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3757 sep1.ip4, sep1.epg.rd),
3758 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3759 sep2.ip4, sep2.epg.rd)]),
3761 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3762 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
3763 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3764 sep3.ip6, sep3.epg.rd),
3765 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3766 sep4.ip6, sep4.epg.rd)])],
3767 [ETH_P_IP, ETH_P_IPV6])
3770 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3773 self.assertEqual(rx[Ether].src, routed_src_mac)
3774 self.assertEqual(rx[Ether].dst, sep1.mac)
3775 self.assertEqual(rx[IP].src, ep1.ip4.address)
3776 self.assertEqual(rx[IP].dst, "10.0.0.88")
3778 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep3.itf)
3781 self.assertEqual(rx[Ether].src, routed_src_mac)
3782 self.assertEqual(rx[Ether].dst, sep3.mac)
3783 self.assertEqual(rx[IPv6].src, ep1.ip6.address)
3784 self.assertEqual(rx[IPv6].dst, "2001:10::88")
3789 self.pg7.unconfig_ip4()
3791 def test_gbp_l3_out(self):
3794 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
3795 self.vapi.cli("set logging class gbp level debug")
3797 routed_dst_mac = "00:0c:0c:0c:0c:0c"
3798 routed_src_mac = "00:22:bd:f8:19:ff"
3803 t4 = VppIpTable(self, 1)
3805 t6 = VppIpTable(self, 1, True)
3808 rd1 = VppGbpRouteDomain(self, 2, 55, t4, t6)
3809 rd1.add_vpp_config()
3811 self.loop0.set_mac(self.router_mac)
3814 # Bind the BVI to the RD
3816 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
3817 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
3820 # Pg7 hosts a BD's BUM
3821 # Pg1 some other l3 interface
3823 self.pg7.config_ip4()
3824 self.pg7.resolve_arp()
3827 # a multicast vxlan-gbp tunnel for broadcast in the BD
3829 tun_bm = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
3832 tun_bm.add_vpp_config()
3835 # a GBP external bridge domains for the EPs
3837 bd1 = VppBridgeDomain(self, 1)
3838 bd1.add_vpp_config()
3839 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0, None, tun_bm)
3840 gbd1.add_vpp_config()
3843 # The Endpoint-groups in which the external endpoints exist
3845 epg_220 = VppGbpEndpointGroup(self, 220, 113, rd1, gbd1,
3849 VppGbpEndpointRetention(2))
3850 epg_220.add_vpp_config()
3852 # the BVIs have the subnets applied ...
3853 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 24)
3854 ip4_addr.add_vpp_config()
3855 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 64)
3856 ip6_addr.add_vpp_config()
3858 # ... which are L3-out subnets
3859 l3o_1 = VppGbpSubnet(
3860 self, rd1, "10.0.0.0", 24,
3861 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3863 l3o_1.add_vpp_config()
3866 # an external interface attached to the outside world and the
3869 VppL2Vtr(self, self.vlan_100, L2_VTR_OP.L2_POP_1).add_vpp_config()
3870 VppL2Vtr(self, self.vlan_101, L2_VTR_OP.L2_POP_1).add_vpp_config()
3871 vlan_144 = VppDot1QSubint(self, self.pg0, 144)
3873 # vlan_102 is not poped
3876 # an unicast vxlan-gbp for inter-RD traffic
3878 vx_tun_l3 = VppGbpVxlanTunnel(
3879 self, 444, rd1.rd_id,
3880 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
3882 vx_tun_l3.add_vpp_config()
3885 # External Endpoints
3887 eep1 = VppGbpEndpoint(self, self.vlan_100,
3889 "10.0.0.1", "11.0.0.1",
3890 "2001:10::1", "3001::1",
3891 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
3892 eep1.add_vpp_config()
3893 eep2 = VppGbpEndpoint(self, self.vlan_101,
3895 "10.0.0.2", "11.0.0.2",
3896 "2001:10::2", "3001::2",
3897 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
3898 eep2.add_vpp_config()
3899 eep3 = VppGbpEndpoint(self, self.vlan_102,
3901 "10.0.0.3", "11.0.0.3",
3902 "2001:10::3", "3001::3",
3903 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
3904 eep3.add_vpp_config()
3907 # A remote external endpoint
3909 rep = VppGbpEndpoint(self, vx_tun_l3,
3911 "10.0.0.101", "11.0.0.101",
3912 "2001:10::101", "3001::101",
3913 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
3915 self.pg7.remote_ip4,
3917 rep.add_vpp_config()
3920 # EP1 impersonating EP3 is dropped
3922 p = (Ether(src=eep1.mac, dst="ff:ff:ff:ff:ff:ff") /
3925 psrc="10.0.0.3", pdst="10.0.0.128",
3926 hwsrc=eep1.mac, hwdst="ff:ff:ff:ff:ff:ff"))
3927 self.send_and_assert_no_replies(self.pg0, p)
3930 # ARP packet from External EPs are accepted and replied to
3932 p_arp = (Ether(src=eep1.mac, dst="ff:ff:ff:ff:ff:ff") /
3935 psrc=eep1.ip4.address, pdst="10.0.0.128",
3936 hwsrc=eep1.mac, hwdst="ff:ff:ff:ff:ff:ff"))
3937 rxs = self.send_and_expect(self.pg0, p_arp * 1, self.pg0)
3940 # ARP packet from host in remote subnet are accepted and replied to
3942 p_arp = (Ether(src=eep3.mac, dst="ff:ff:ff:ff:ff:ff") /
3945 psrc=eep3.ip4.address, pdst="10.0.0.128",
3946 hwsrc=eep3.mac, hwdst="ff:ff:ff:ff:ff:ff"))
3947 rxs = self.send_and_expect(self.pg0, p_arp * 1, self.pg0)
3950 # packets destined to unknown addresses in the BVI's subnet
3953 p4 = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3955 IP(src="10.0.0.1", dst="10.0.0.88") /
3956 UDP(sport=1234, dport=1234) /
3958 p6 = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3960 IPv6(src="2001:10::1", dst="2001:10::88") /
3961 UDP(sport=1234, dport=1234) /
3964 rxs = self.send_and_expect(self.pg0, p4 * 1, self.pg7)
3967 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3968 # self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3969 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3970 self.assertEqual(rx[IP].dst, "239.1.1.1")
3971 self.assertEqual(rx[VXLAN].vni, 88)
3972 self.assertTrue(rx[VXLAN].flags.G)
3973 self.assertTrue(rx[VXLAN].flags.Instance)
3974 # policy was applied to the original IP packet
3975 self.assertEqual(rx[VXLAN].gpid, 113)
3976 self.assertTrue(rx[VXLAN].gpflags.A)
3977 self.assertFalse(rx[VXLAN].gpflags.D)
3979 inner = rx[VXLAN].payload
3981 self.assertTrue(inner.haslayer(ARP))
3984 # remote to external
3986 p = (Ether(src=self.pg7.remote_mac,
3987 dst=self.pg7.local_mac) /
3988 IP(src=self.pg7.remote_ip4,
3989 dst=self.pg7.local_ip4) /
3990 UDP(sport=1234, dport=48879) /
3991 VXLAN(vni=444, gpid=113, flags=0x88) /
3992 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
3993 IP(src="10.0.0.101", dst="10.0.0.1") /
3994 UDP(sport=1234, dport=1234) /
3997 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
4000 # local EP pings router
4002 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
4004 IP(src=eep1.ip4.address, dst="10.0.0.128") /
4005 ICMP(type='echo-request'))
4007 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
4010 self.assertEqual(rx[Ether].src, str(self.router_mac))
4011 self.assertEqual(rx[Ether].dst, eep1.mac)
4012 self.assertEqual(rx[Dot1Q].vlan, 100)
4015 # local EP pings other local EP
4017 p = (Ether(src=eep1.mac, dst=eep2.mac) /
4019 IP(src=eep1.ip4.address, dst=eep2.ip4.address) /
4020 ICMP(type='echo-request'))
4022 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
4025 self.assertEqual(rx[Ether].src, eep1.mac)
4026 self.assertEqual(rx[Ether].dst, eep2.mac)
4027 self.assertEqual(rx[Dot1Q].vlan, 101)
4030 # local EP pings router w/o vlan tag poped
4032 p = (Ether(src=eep3.mac, dst=str(self.router_mac)) /
4034 IP(src=eep3.ip4.address, dst="10.0.0.128") /
4035 ICMP(type='echo-request'))
4037 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
4040 self.assertEqual(rx[Ether].src, str(self.router_mac))
4041 self.assertEqual(rx[Ether].dst, self.vlan_102.remote_mac)
4044 # A ip4 subnet reachable through the external EP1
4046 ip_220 = VppIpRoute(self, "10.220.0.0", 24,
4047 [VppRoutePath(eep1.ip4.address,
4048 eep1.epg.bvi.sw_if_index)],
4049 table_id=t4.table_id)
4050 ip_220.add_vpp_config()
4052 l3o_220 = VppGbpSubnet(
4053 self, rd1, "10.220.0.0", 24,
4054 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
4056 l3o_220.add_vpp_config()
4059 # An ip6 subnet reachable through the external EP1
4061 ip6_220 = VppIpRoute(self, "10:220::", 64,
4062 [VppRoutePath(eep1.ip6.address,
4063 eep1.epg.bvi.sw_if_index)],
4064 table_id=t6.table_id)
4065 ip6_220.add_vpp_config()
4067 l3o6_220 = VppGbpSubnet(
4068 self, rd1, "10:220::", 64,
4069 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
4071 l3o6_220.add_vpp_config()
4074 # A subnet reachable through the external EP2
4076 ip_221 = VppIpRoute(self, "10.221.0.0", 24,
4077 [VppRoutePath(eep2.ip4.address,
4078 eep2.epg.bvi.sw_if_index)],
4079 table_id=t4.table_id)
4080 ip_221.add_vpp_config()
4082 l3o_221 = VppGbpSubnet(
4083 self, rd1, "10.221.0.0", 24,
4084 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
4086 l3o_221.add_vpp_config()
4089 # ping between hosts in remote subnets
4090 # dropped without a contract
4092 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
4094 IP(src="10.220.0.1", dst="10.221.0.1") /
4095 ICMP(type='echo-request'))
4097 self.send_and_assert_no_replies(self.pg0, p * 1)
4100 # contract for the external nets to communicate
4102 acl = VppGbpAcl(self)
4103 rule4 = acl.create_rule(permit_deny=1, proto=17)
4104 rule6 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
4105 acl_index = acl.add_vpp_config([rule4, rule6])
4108 # A contract with the wrong scope is not matched
4110 c_44 = VppGbpContract(
4111 self, 44, 4220, 4221, acl_index,
4112 [VppGbpContractRule(
4113 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4116 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4118 [ETH_P_IP, ETH_P_IPV6])
4119 c_44.add_vpp_config()
4120 self.send_and_assert_no_replies(self.pg0, p * 1)
4122 c1 = VppGbpContract(
4123 self, 55, 4220, 4221, acl_index,
4124 [VppGbpContractRule(
4125 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4126 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4129 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4130 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4132 [ETH_P_IP, ETH_P_IPV6])
4136 # Contracts allowing ext-net 200 to talk with external EPs
4138 c2 = VppGbpContract(
4139 self, 55, 4220, 113, acl_index,
4140 [VppGbpContractRule(
4141 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4142 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4145 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4146 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4148 [ETH_P_IP, ETH_P_IPV6])
4150 c3 = VppGbpContract(
4151 self, 55, 113, 4220, acl_index,
4152 [VppGbpContractRule(
4153 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4154 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4157 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4158 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4160 [ETH_P_IP, ETH_P_IPV6])
4164 # ping between hosts in remote subnets
4166 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
4168 IP(src="10.220.0.1", dst="10.221.0.1") /
4169 UDP(sport=1234, dport=1234) /
4172 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
4175 self.assertEqual(rx[Ether].src, str(self.router_mac))
4176 self.assertEqual(rx[Ether].dst, eep2.mac)
4177 self.assertEqual(rx[Dot1Q].vlan, 101)
4179 # we did not learn these external hosts
4180 self.assertFalse(find_gbp_endpoint(self, ip="10.220.0.1"))
4181 self.assertFalse(find_gbp_endpoint(self, ip="10.221.0.1"))
4184 # from remote external EP to local external EP
4186 p = (Ether(src=self.pg7.remote_mac,
4187 dst=self.pg7.local_mac) /
4188 IP(src=self.pg7.remote_ip4,
4189 dst=self.pg7.local_ip4) /
4190 UDP(sport=1234, dport=48879) /
4191 VXLAN(vni=444, gpid=113, flags=0x88) /
4192 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
4193 IP(src="10.0.0.101", dst="10.220.0.1") /
4194 UDP(sport=1234, dport=1234) /
4197 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
4200 # ping from an external host to the remote external EP
4202 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
4204 IP(src="10.220.0.1", dst=rep.ip4.address) /
4205 UDP(sport=1234, dport=1234) /
4208 rxs = self.send_and_expect(self.pg0, p * 1, self.pg7)
4211 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4212 # self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4213 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4214 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4215 self.assertEqual(rx[VXLAN].vni, 444)
4216 self.assertTrue(rx[VXLAN].flags.G)
4217 self.assertTrue(rx[VXLAN].flags.Instance)
4218 # the sclass of the ext-net the packet came from
4219 self.assertEqual(rx[VXLAN].gpid, 4220)
4220 # policy was applied to the original IP packet
4221 self.assertTrue(rx[VXLAN].gpflags.A)
4222 # since it's an external host the reciever should not learn it
4223 self.assertTrue(rx[VXLAN].gpflags.D)
4224 inner = rx[VXLAN].payload
4225 self.assertEqual(inner[IP].src, "10.220.0.1")
4226 self.assertEqual(inner[IP].dst, rep.ip4.address)
4229 # An external subnet reachable via the remote external EP
4233 # first the VXLAN-GBP tunnel over which it is reached
4235 vx_tun_r1 = VppVxlanGbpTunnel(
4236 self, self.pg7.local_ip4,
4237 self.pg7.remote_ip4, 445,
4238 mode=(VppEnum.vl_api_vxlan_gbp_api_tunnel_mode_t.
4239 VXLAN_GBP_API_TUNNEL_MODE_L3))
4240 vx_tun_r1.add_vpp_config()
4241 VppIpInterfaceBind(self, vx_tun_r1, t4).add_vpp_config()
4243 self.logger.info(self.vapi.cli("sh vxlan-gbp tunnel"))
4246 # then the special adj to resolve through on that tunnel
4248 n1 = VppNeighbor(self,
4249 vx_tun_r1.sw_if_index,
4250 "00:0c:0c:0c:0c:0c",
4251 self.pg7.remote_ip4)
4255 # the route via the adj above
4257 ip_222 = VppIpRoute(self, "10.222.0.0", 24,
4258 [VppRoutePath(self.pg7.remote_ip4,
4259 vx_tun_r1.sw_if_index)],
4260 table_id=t4.table_id)
4261 ip_222.add_vpp_config()
4263 l3o_222 = VppGbpSubnet(
4264 self, rd1, "10.222.0.0", 24,
4265 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
4267 l3o_222.add_vpp_config()
4270 # ping between hosts in local and remote external subnets
4271 # dropped without a contract
4273 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
4275 IP(src="10.220.0.1", dst="10.222.0.1") /
4276 UDP(sport=1234, dport=1234) /
4279 rxs = self.send_and_assert_no_replies(self.pg0, p * 1)
4282 # Add contracts ext-nets for 220 -> 222
4284 c4 = VppGbpContract(
4285 self, 55, 4220, 4222, acl_index,
4286 [VppGbpContractRule(
4287 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4288 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4291 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4292 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4294 [ETH_P_IP, ETH_P_IPV6])
4298 # ping from host in local to remote external subnets
4300 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
4302 IP(src="10.220.0.1", dst="10.222.0.1") /
4303 UDP(sport=1234, dport=1234) /
4306 rxs = self.send_and_expect(self.pg0, p * 3, self.pg7)
4309 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4310 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4311 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4312 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4313 self.assertEqual(rx[VXLAN].vni, 445)
4314 self.assertTrue(rx[VXLAN].flags.G)
4315 self.assertTrue(rx[VXLAN].flags.Instance)
4316 # the sclass of the ext-net the packet came from
4317 self.assertEqual(rx[VXLAN].gpid, 4220)
4318 # policy was applied to the original IP packet
4319 self.assertTrue(rx[VXLAN].gpflags.A)
4320 # since it's an external host the reciever should not learn it
4321 self.assertTrue(rx[VXLAN].gpflags.D)
4322 inner = rx[VXLAN].payload
4323 self.assertEqual(inner[Ether].dst, "00:0c:0c:0c:0c:0c")
4324 self.assertEqual(inner[IP].src, "10.220.0.1")
4325 self.assertEqual(inner[IP].dst, "10.222.0.1")
4328 # make the external subnet ECMP
4330 vx_tun_r2 = VppVxlanGbpTunnel(
4331 self, self.pg7.local_ip4,
4332 self.pg7.remote_ip4, 446,
4333 mode=(VppEnum.vl_api_vxlan_gbp_api_tunnel_mode_t.
4334 VXLAN_GBP_API_TUNNEL_MODE_L3))
4335 vx_tun_r2.add_vpp_config()
4336 VppIpInterfaceBind(self, vx_tun_r2, t4).add_vpp_config()
4338 self.logger.info(self.vapi.cli("sh vxlan-gbp tunnel"))
4340 n2 = VppNeighbor(self,
4341 vx_tun_r2.sw_if_index,
4342 "00:0c:0c:0c:0c:0c",
4343 self.pg7.remote_ip4)
4346 ip_222.modify([VppRoutePath(self.pg7.remote_ip4,
4347 vx_tun_r1.sw_if_index),
4348 VppRoutePath(self.pg7.remote_ip4,
4349 vx_tun_r2.sw_if_index)])
4352 # now expect load-balance
4354 p = [(Ether(src=eep1.mac, dst=str(self.router_mac)) /
4356 IP(src="10.220.0.1", dst="10.222.0.1") /
4357 UDP(sport=1234, dport=1234) /
4359 (Ether(src=eep1.mac, dst=str(self.router_mac)) /
4361 IP(src="10.220.0.1", dst="10.222.0.1") /
4362 UDP(sport=1222, dport=1235) /
4365 rxs = self.send_and_expect(self.pg0, p, self.pg7)
4367 self.assertEqual(rxs[0][VXLAN].vni, 445)
4368 self.assertEqual(rxs[1][VXLAN].vni, 446)
4371 # Same LB test for v6
4373 n3 = VppNeighbor(self,
4374 vx_tun_r1.sw_if_index,
4375 "00:0c:0c:0c:0c:0c",
4376 self.pg7.remote_ip6)
4378 n4 = VppNeighbor(self,
4379 vx_tun_r2.sw_if_index,
4380 "00:0c:0c:0c:0c:0c",
4381 self.pg7.remote_ip6)
4384 ip_222_6 = VppIpRoute(self, "10:222::", 64,
4385 [VppRoutePath(self.pg7.remote_ip6,
4386 vx_tun_r1.sw_if_index),
4387 VppRoutePath(self.pg7.remote_ip6,
4388 vx_tun_r2.sw_if_index)],
4389 table_id=t6.table_id)
4390 ip_222_6.add_vpp_config()
4392 l3o_222_6 = VppGbpSubnet(
4393 self, rd1, "10:222::", 64,
4394 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
4396 l3o_222_6.add_vpp_config()
4398 p = [(Ether(src=eep1.mac, dst=str(self.router_mac)) /
4400 IPv6(src="10:220::1", dst="10:222::1") /
4401 UDP(sport=1234, dport=1234) /
4403 (Ether(src=eep1.mac, dst=str(self.router_mac)) /
4405 IPv6(src="10:220::1", dst="10:222::1") /
4406 UDP(sport=7777, dport=8881) /
4409 self.logger.info(self.vapi.cli("sh ip6 fib 10:222::1"))
4410 rxs = self.send_and_expect(self.pg0, p, self.pg7)
4412 self.assertEqual(rxs[0][VXLAN].vni, 445)
4413 self.assertEqual(rxs[1][VXLAN].vni, 446)
4416 # ping from host in remote to local external subnets
4417 # there's no contract for this, but the A bit is set.
4419 p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
4420 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
4421 UDP(sport=1234, dport=48879) /
4422 VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
4423 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
4424 IP(src="10.222.0.1", dst="10.220.0.1") /
4425 UDP(sport=1234, dport=1234) /
4428 rxs = self.send_and_expect(self.pg7, p * 3, self.pg0)
4429 self.assertFalse(find_gbp_endpoint(self, ip="10.222.0.1"))
4432 # ping from host in remote to remote external subnets
4433 # this is dropped by reflection check.
4435 p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
4436 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
4437 UDP(sport=1234, dport=48879) /
4438 VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
4439 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
4440 IP(src="10.222.0.1", dst="10.222.0.2") /
4441 UDP(sport=1234, dport=1234) /
4444 rxs = self.send_and_assert_no_replies(self.pg7, p * 3)
4446 p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
4447 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
4448 UDP(sport=1234, dport=48879) /
4449 VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
4450 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
4451 IPv6(src="10:222::1", dst="10:222::2") /
4452 UDP(sport=1234, dport=1234) /
4455 rxs = self.send_and_assert_no_replies(self.pg7, p * 3)
4460 lep1 = VppGbpEndpoint(self, vlan_144,
4462 "10.0.0.44", "11.0.0.44",
4463 "2001:10::44", "3001::44")
4464 lep1.add_vpp_config()
4467 # local EP to local ip4 external subnet
4469 p = (Ether(src=lep1.mac, dst=str(self.router_mac)) /
4471 IP(src=lep1.ip4.address, dst="10.220.0.1") /
4472 UDP(sport=1234, dport=1234) /
4475 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
4478 self.assertEqual(rx[Ether].src, str(self.router_mac))
4479 self.assertEqual(rx[Ether].dst, eep1.mac)
4480 self.assertEqual(rx[Dot1Q].vlan, 100)
4483 # local EP to local ip6 external subnet
4485 p = (Ether(src=lep1.mac, dst=str(self.router_mac)) /
4487 IPv6(src=lep1.ip6.address, dst="10:220::1") /
4488 UDP(sport=1234, dport=1234) /
4491 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
4494 self.assertEqual(rx[Ether].src, str(self.router_mac))
4495 self.assertEqual(rx[Ether].dst, eep1.mac)
4496 self.assertEqual(rx[Dot1Q].vlan, 100)
4499 # ip4 and ip6 subnets that load-balance
4501 ip_20 = VppIpRoute(self, "10.20.0.0", 24,
4502 [VppRoutePath(eep1.ip4.address,
4503 eep1.epg.bvi.sw_if_index),
4504 VppRoutePath(eep2.ip4.address,
4505 eep2.epg.bvi.sw_if_index)],
4506 table_id=t4.table_id)
4507 ip_20.add_vpp_config()
4509 l3o_20 = VppGbpSubnet(
4510 self, rd1, "10.20.0.0", 24,
4511 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
4513 l3o_20.add_vpp_config()
4515 ip6_20 = VppIpRoute(self, "10:20::", 64,
4516 [VppRoutePath(eep1.ip6.address,
4517 eep1.epg.bvi.sw_if_index),
4518 VppRoutePath(eep2.ip6.address,
4519 eep2.epg.bvi.sw_if_index)],
4520 table_id=t6.table_id)
4521 ip6_20.add_vpp_config()
4523 l3o6_20 = VppGbpSubnet(
4524 self, rd1, "10:20::", 64,
4525 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
4527 l3o6_20.add_vpp_config()
4529 self.logger.info(self.vapi.cli("sh ip fib 10.20.0.1"))
4530 self.logger.info(self.vapi.cli("sh ip6 fib 10:20::1"))
4532 # two ip6 packets whose port are chosen so they load-balance
4533 p = [(Ether(src=lep1.mac, dst=str(self.router_mac)) /
4535 IPv6(src=lep1.ip6.address, dst="10:20::1") /
4536 UDP(sport=1234, dport=1234) /
4538 (Ether(src=lep1.mac, dst=str(self.router_mac)) /
4540 IPv6(src=lep1.ip6.address, dst="10:20::1") /
4541 UDP(sport=124, dport=1230) /
4544 rxs = self.send_and_expect(self.pg0, p, self.pg0, 2)
4546 self.assertEqual(rxs[0][Dot1Q].vlan, 101)
4547 self.assertEqual(rxs[1][Dot1Q].vlan, 100)
4549 # two ip4 packets whose port are chosen so they load-balance
4550 p = [(Ether(src=lep1.mac, dst=str(self.router_mac)) /
4552 IP(src=lep1.ip4.address, dst="10.20.0.1") /
4553 UDP(sport=1235, dport=1235) /
4555 (Ether(src=lep1.mac, dst=str(self.router_mac)) /
4557 IP(src=lep1.ip4.address, dst="10.20.0.1") /
4558 UDP(sport=124, dport=1230) /
4561 rxs = self.send_and_expect(self.pg0, p, self.pg0, 2)
4563 self.assertEqual(rxs[0][Dot1Q].vlan, 101)
4564 self.assertEqual(rxs[1][Dot1Q].vlan, 100)
4569 ip_222.remove_vpp_config()
4570 self.pg7.unconfig_ip4()
4571 self.vlan_101.set_vtr(L2_VTR_OP.L2_DISABLED)
4572 self.vlan_100.set_vtr(L2_VTR_OP.L2_DISABLED)
4574 def test_gbp_anon_l3_out(self):
4575 """ GBP Anonymous L3 Out """
4577 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
4578 self.vapi.cli("set logging class gbp level debug")
4580 routed_dst_mac = "00:0c:0c:0c:0c:0c"
4581 routed_src_mac = "00:22:bd:f8:19:ff"
4586 t4 = VppIpTable(self, 1)
4588 t6 = VppIpTable(self, 1, True)
4591 rd1 = VppGbpRouteDomain(self, 2, 55, t4, t6)
4592 rd1.add_vpp_config()
4594 self.loop0.set_mac(self.router_mac)
4597 # Bind the BVI to the RD
4599 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
4600 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
4603 # Pg7 hosts a BD's BUM
4604 # Pg1 some other l3 interface
4606 self.pg7.config_ip4()
4607 self.pg7.resolve_arp()
4610 # a GBP external bridge domains for the EPs
4612 bd1 = VppBridgeDomain(self, 1)
4613 bd1.add_vpp_config()
4614 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0, None, None)
4615 gbd1.add_vpp_config()
4618 # The Endpoint-groups in which the external endpoints exist
4620 epg_220 = VppGbpEndpointGroup(self, 220, 113, rd1, gbd1,
4624 VppGbpEndpointRetention(2))
4625 epg_220.add_vpp_config()
4627 # the BVIs have the subnet applied ...
4628 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 24)
4629 ip4_addr.add_vpp_config()
4631 # ... which is an Anonymous L3-out subnets
4632 l3o_1 = VppGbpSubnet(
4633 self, rd1, "10.0.0.0", 24,
4634 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_ANON_L3_OUT,
4636 l3o_1.add_vpp_config()
4639 # an external interface attached to the outside world and the
4642 VppL2Vtr(self, self.vlan_100, L2_VTR_OP.L2_POP_1).add_vpp_config()
4643 VppL2Vtr(self, self.vlan_101, L2_VTR_OP.L2_POP_1).add_vpp_config()
4646 # vlan_100 and vlan_101 are anonymous l3-out interfaces
4648 ext_itf = VppGbpExtItf(self, self.vlan_100, bd1, rd1, anon=True)
4649 ext_itf.add_vpp_config()
4650 ext_itf = VppGbpExtItf(self, self.vlan_101, bd1, rd1, anon=True)
4651 ext_itf.add_vpp_config()
4654 # an unicast vxlan-gbp for inter-RD traffic
4656 vx_tun_l3 = VppGbpVxlanTunnel(
4657 self, 444, rd1.rd_id,
4658 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
4660 vx_tun_l3.add_vpp_config()
4663 # A remote external endpoint
4665 rep = VppGbpEndpoint(self, vx_tun_l3,
4667 "10.0.0.201", "11.0.0.201",
4668 "2001:10::201", "3001::101",
4669 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
4671 self.pg7.remote_ip4,
4673 rep.add_vpp_config()
4676 # ARP packet from host in external subnet are accepted, flooded and
4677 # replied to. We expect 2 packets:
4678 # - APR request flooded over the other vlan subif
4679 # - ARP reply from BVI
4681 p_arp = (Ether(src=self.vlan_100.remote_mac,
4682 dst="ff:ff:ff:ff:ff:ff") /
4687 hwsrc=self.vlan_100.remote_mac,
4688 hwdst="ff:ff:ff:ff:ff:ff"))
4689 rxs = self.send_and_expect(self.pg0, p_arp * 1, self.pg0, n_rx=2)
4691 p_arp = (Ether(src=self.vlan_101.remote_mac,
4692 dst="ff:ff:ff:ff:ff:ff") /
4697 hwsrc=self.vlan_101.remote_mac,
4698 hwdst="ff:ff:ff:ff:ff:ff"))
4699 rxs = self.send_and_expect(self.pg0, p_arp * 1, self.pg0, n_rx=2)
4702 # remote to external
4704 p = (Ether(src=self.pg7.remote_mac,
4705 dst=self.pg7.local_mac) /
4706 IP(src=self.pg7.remote_ip4,
4707 dst=self.pg7.local_ip4) /
4708 UDP(sport=1234, dport=48879) /
4709 VXLAN(vni=vx_tun_l3.vni, gpid=epg_220.sclass, flags=0x88) /
4710 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
4711 IP(src=str(rep.ip4), dst="10.0.0.100") /
4712 UDP(sport=1234, dport=1234) /
4714 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
4717 # local EP pings router
4719 p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
4721 IP(src="10.0.0.100", dst="10.0.0.128") /
4722 ICMP(type='echo-request'))
4723 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
4726 self.assertEqual(rx[Ether].src, str(self.router_mac))
4727 self.assertEqual(rx[Ether].dst, self.vlan_100.remote_mac)
4728 self.assertEqual(rx[Dot1Q].vlan, 100)
4731 # local EP pings other local EP
4733 p = (Ether(src=self.vlan_100.remote_mac,
4734 dst=self.vlan_101.remote_mac) /
4736 IP(src="10.0.0.100", dst="10.0.0.101") /
4737 ICMP(type='echo-request'))
4738 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
4741 self.assertEqual(rx[Ether].src, self.vlan_100.remote_mac)
4742 self.assertEqual(rx[Ether].dst, self.vlan_101.remote_mac)
4743 self.assertEqual(rx[Dot1Q].vlan, 101)
4746 # A subnet reachable through an external router on vlan 100
4748 ip_220 = VppIpRoute(self, "10.220.0.0", 24,
4749 [VppRoutePath("10.0.0.100",
4750 epg_220.bvi.sw_if_index)],
4751 table_id=t4.table_id)
4752 ip_220.add_vpp_config()
4754 l3o_220 = VppGbpSubnet(
4755 self, rd1, "10.220.0.0", 24,
4756 # note: this a "regular" L3 out subnet (not connected)
4757 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
4759 l3o_220.add_vpp_config()
4762 # A subnet reachable through an external router on vlan 101
4764 ip_221 = VppIpRoute(self, "10.221.0.0", 24,
4765 [VppRoutePath("10.0.0.101",
4766 epg_220.bvi.sw_if_index)],
4767 table_id=t4.table_id)
4768 ip_221.add_vpp_config()
4770 l3o_221 = VppGbpSubnet(
4771 self, rd1, "10.221.0.0", 24,
4772 # note: this a "regular" L3 out subnet (not connected)
4773 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
4775 l3o_221.add_vpp_config()
4778 # ping between hosts in remote subnets
4779 # dropped without a contract
4781 p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
4783 IP(src="10.220.0.1", dst="10.221.0.1") /
4784 ICMP(type='echo-request'))
4786 rxs = self.send_and_assert_no_replies(self.pg0, p * 1)
4789 # contract for the external nets to communicate
4791 acl = VppGbpAcl(self)
4792 rule4 = acl.create_rule(permit_deny=1, proto=17)
4793 rule6 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
4794 acl_index = acl.add_vpp_config([rule4, rule6])
4796 c1 = VppGbpContract(
4797 self, 55, 4220, 4221, acl_index,
4798 [VppGbpContractRule(
4799 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4800 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4803 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4804 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4806 [ETH_P_IP, ETH_P_IPV6])
4810 # Contracts allowing ext-net 200 to talk with external EPs
4812 c2 = VppGbpContract(
4813 self, 55, 4220, 113, acl_index,
4814 [VppGbpContractRule(
4815 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4816 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4819 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4820 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4822 [ETH_P_IP, ETH_P_IPV6])
4824 c3 = VppGbpContract(
4825 self, 55, 113, 4220, acl_index,
4826 [VppGbpContractRule(
4827 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4828 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4831 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4832 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4834 [ETH_P_IP, ETH_P_IPV6])
4838 # ping between hosts in remote subnets
4840 p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
4842 IP(src="10.220.0.1", dst="10.221.0.1") /
4843 UDP(sport=1234, dport=1234) /
4846 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
4849 self.assertEqual(rx[Ether].src, str(self.router_mac))
4850 self.assertEqual(rx[Ether].dst, self.vlan_101.remote_mac)
4851 self.assertEqual(rx[Dot1Q].vlan, 101)
4853 # we did not learn these external hosts
4854 self.assertFalse(find_gbp_endpoint(self, ip="10.220.0.1"))
4855 self.assertFalse(find_gbp_endpoint(self, ip="10.221.0.1"))
4858 # from remote external EP to local external EP
4860 p = (Ether(src=self.pg7.remote_mac,
4861 dst=self.pg7.local_mac) /
4862 IP(src=self.pg7.remote_ip4,
4863 dst=self.pg7.local_ip4) /
4864 UDP(sport=1234, dport=48879) /
4865 VXLAN(vni=444, gpid=113, flags=0x88) /
4866 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
4867 IP(src=rep.ip4.address, dst="10.220.0.1") /
4868 UDP(sport=1234, dport=1234) /
4871 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
4874 # ping from an external host to the remote external EP
4876 p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
4878 IP(src="10.220.0.1", dst=rep.ip4.address) /
4879 UDP(sport=1234, dport=1234) /
4882 rxs = self.send_and_expect(self.pg0, p * 1, self.pg7)
4885 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4886 # self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4887 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4888 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4889 self.assertEqual(rx[VXLAN].vni, 444)
4890 self.assertTrue(rx[VXLAN].flags.G)
4891 self.assertTrue(rx[VXLAN].flags.Instance)
4892 # the sclass of the ext-net the packet came from
4893 self.assertEqual(rx[VXLAN].gpid, 4220)
4894 # policy was applied to the original IP packet
4895 self.assertTrue(rx[VXLAN].gpflags.A)
4896 # since it's an external host the reciever should not learn it
4897 self.assertTrue(rx[VXLAN].gpflags.D)
4898 inner = rx[VXLAN].payload
4899 self.assertEqual(inner[IP].src, "10.220.0.1")
4900 self.assertEqual(inner[IP].dst, rep.ip4.address)
4903 # An external subnet reachable via the remote external EP
4907 # first the VXLAN-GBP tunnel over which it is reached
4909 vx_tun_r = VppVxlanGbpTunnel(
4910 self, self.pg7.local_ip4,
4911 self.pg7.remote_ip4, 445,
4912 mode=(VppEnum.vl_api_vxlan_gbp_api_tunnel_mode_t.
4913 VXLAN_GBP_API_TUNNEL_MODE_L3))
4914 vx_tun_r.add_vpp_config()
4915 VppIpInterfaceBind(self, vx_tun_r, t4).add_vpp_config()
4917 self.logger.info(self.vapi.cli("sh vxlan-gbp tunnel"))
4920 # then the special adj to resolve through on that tunnel
4922 n1 = VppNeighbor(self,
4923 vx_tun_r.sw_if_index,
4924 "00:0c:0c:0c:0c:0c",
4925 self.pg7.remote_ip4)
4929 # the route via the adj above
4931 ip_222 = VppIpRoute(self, "10.222.0.0", 24,
4932 [VppRoutePath(self.pg7.remote_ip4,
4933 vx_tun_r.sw_if_index)],
4934 table_id=t4.table_id)
4935 ip_222.add_vpp_config()
4937 l3o_222 = VppGbpSubnet(
4938 self, rd1, "10.222.0.0", 24,
4939 # note: this a "regular" l3out subnet (not connected)
4940 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
4942 l3o_222.add_vpp_config()
4945 # ping between hosts in local and remote external subnets
4946 # dropped without a contract
4948 p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
4950 IP(src="10.220.0.1", dst="10.222.0.1") /
4951 UDP(sport=1234, dport=1234) /
4954 rxs = self.send_and_assert_no_replies(self.pg0, p * 1)
4957 # Add contracts ext-nets for 220 -> 222
4959 c4 = VppGbpContract(
4960 self, 55, 4220, 4222, acl_index,
4961 [VppGbpContractRule(
4962 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4963 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4966 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4967 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4969 [ETH_P_IP, ETH_P_IPV6])
4973 # ping from host in local to remote external subnets
4975 p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
4977 IP(src="10.220.0.1", dst="10.222.0.1") /
4978 UDP(sport=1234, dport=1234) /
4981 rxs = self.send_and_expect(self.pg0, p * 3, self.pg7)
4984 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4985 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4986 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4987 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4988 self.assertEqual(rx[VXLAN].vni, 445)
4989 self.assertTrue(rx[VXLAN].flags.G)
4990 self.assertTrue(rx[VXLAN].flags.Instance)
4991 # the sclass of the ext-net the packet came from
4992 self.assertEqual(rx[VXLAN].gpid, 4220)
4993 # policy was applied to the original IP packet
4994 self.assertTrue(rx[VXLAN].gpflags.A)
4995 # since it's an external host the reciever should not learn it
4996 self.assertTrue(rx[VXLAN].gpflags.D)
4997 inner = rx[VXLAN].payload
4998 self.assertEqual(inner[Ether].dst, "00:0c:0c:0c:0c:0c")
4999 self.assertEqual(inner[IP].src, "10.220.0.1")
5000 self.assertEqual(inner[IP].dst, "10.222.0.1")
5003 # ping from host in remote to local external subnets
5004 # there's no contract for this, but the A bit is set.
5006 p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
5007 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
5008 UDP(sport=1234, dport=48879) /
5009 VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
5010 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
5011 IP(src="10.222.0.1", dst="10.220.0.1") /
5012 UDP(sport=1234, dport=1234) /
5015 rxs = self.send_and_expect(self.pg7, p * 3, self.pg0)
5016 self.assertFalse(find_gbp_endpoint(self, ip="10.222.0.1"))
5019 # ping from host in remote to remote external subnets
5020 # this is dropped by reflection check.
5022 p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
5023 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
5024 UDP(sport=1234, dport=48879) /
5025 VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
5026 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
5027 IP(src="10.222.0.1", dst="10.222.0.2") /
5028 UDP(sport=1234, dport=1234) /
5031 rxs = self.send_and_assert_no_replies(self.pg7, p * 3)
5036 self.vlan_101.set_vtr(L2_VTR_OP.L2_DISABLED)
5037 self.vlan_100.set_vtr(L2_VTR_OP.L2_DISABLED)
5038 self.pg7.unconfig_ip4()
5041 if __name__ == '__main__':
5042 unittest.main(testRunner=VppTestRunner)