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 bridge 1 detail"))
1991 self.logger.info(self.vapi.cli("sh gbp bridge"))
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)
2019 # Check v6 Endpoints learning
2022 # a packet with an sclass from a known EPG
2023 p = (Ether(src=self.pg2.remote_mac,
2024 dst=self.pg2.local_mac) /
2025 IP(src=self.pg2.remote_hosts[1].ip4,
2026 dst=self.pg2.local_ip4) /
2027 UDP(sport=1234, dport=48879) /
2028 VXLAN(vni=99, gpid=113, flags=0x88, gpflags='A') /
2029 Ether(src=l['mac'], dst=ep.mac) /
2030 IPv6(src=l['ip6'], dst=ep.ip6.address) /
2031 UDP(sport=1234, dport=1234) /
2034 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
2036 self.assertTrue(find_gbp_endpoint(self,
2037 vx_tun_l2_1.sw_if_index,
2041 # v6 remote EP reachability
2044 p = (Ether(src=ep.mac, dst=l['mac']) /
2045 IPv6(dst=l['ip6'], src=ep.ip6.address) /
2046 UDP(sport=1234, dport=1234) /
2049 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
2052 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2053 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2054 self.assertEqual(rx[UDP].dport, 48879)
2055 # the UDP source port is a random value for hashing
2056 self.assertEqual(rx[VXLAN].gpid, 112)
2057 self.assertEqual(rx[VXLAN].vni, 99)
2058 self.assertTrue(rx[VXLAN].flags.G)
2059 self.assertTrue(rx[VXLAN].flags.Instance)
2060 self.assertTrue(rx[VXLAN].gpflags.A)
2061 self.assertFalse(rx[VXLAN].gpflags.D)
2062 self.assertEqual(rx[IPv6].dst, l['ip6'])
2068 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
2070 self.pg2.unconfig_ip4()
2071 self.pg3.unconfig_ip4()
2072 self.pg4.unconfig_ip4()
2074 self.logger.info(self.vapi.cli("sh int"))
2075 self.logger.info(self.vapi.cli("sh gbp vxlan"))
2077 def test_gbp_contract(self):
2078 """ GBP Contracts """
2083 gt4 = VppIpTable(self, 0)
2084 gt4.add_vpp_config()
2085 gt6 = VppIpTable(self, 0, is_ip6=True)
2086 gt6.add_vpp_config()
2088 rd0 = VppGbpRouteDomain(self, 0, 400, gt4, gt6, None, None)
2090 rd0.add_vpp_config()
2095 bd1 = VppBridgeDomain(self, 1, arp_term=0)
2096 bd2 = VppBridgeDomain(self, 2, arp_term=0)
2098 bd1.add_vpp_config()
2099 bd2.add_vpp_config()
2101 gbd1 = VppGbpBridgeDomain(self, bd1, rd0, self.loop0)
2102 gbd2 = VppGbpBridgeDomain(self, bd2, rd0, self.loop1)
2104 gbd1.add_vpp_config()
2105 gbd2.add_vpp_config()
2108 # 3 EPGs, 2 of which share a BD.
2110 epgs = [VppGbpEndpointGroup(self, 220, 1220, rd0, gbd1,
2112 "10.0.0.128", "2001:10::128"),
2113 VppGbpEndpointGroup(self, 221, 1221, rd0, gbd1,
2115 "10.0.1.128", "2001:10:1::128"),
2116 VppGbpEndpointGroup(self, 222, 1222, rd0, gbd2,
2118 "10.0.2.128", "2001:10:2::128")]
2120 # 4 end-points, 2 in the same subnet, 3 in the same BD
2122 eps = [VppGbpEndpoint(self, self.pg0,
2124 "10.0.0.1", "11.0.0.1",
2125 "2001:10::1", "3001::1"),
2126 VppGbpEndpoint(self, self.pg1,
2128 "10.0.0.2", "11.0.0.2",
2129 "2001:10::2", "3001::2"),
2130 VppGbpEndpoint(self, self.pg2,
2132 "10.0.1.1", "11.0.0.3",
2133 "2001:10:1::1", "3001::3"),
2134 VppGbpEndpoint(self, self.pg3,
2136 "10.0.2.1", "11.0.0.4",
2137 "2001:10:2::1", "3001::4")]
2140 # Config related to each of the EPGs
2143 # IP config on the BVI interfaces
2145 VppIpInterfaceBind(self, epg.bvi, epg.rd.t4).add_vpp_config()
2146 VppIpInterfaceBind(self, epg.bvi, epg.rd.t6).add_vpp_config()
2147 self.vapi.sw_interface_set_mac_address(
2148 epg.bvi.sw_if_index,
2149 self.router_mac.packed)
2151 if_ip4 = VppIpInterfaceAddress(self, epg.bvi, epg.bvi_ip4, 32)
2152 if_ip6 = VppIpInterfaceAddress(self, epg.bvi, epg.bvi_ip6, 128)
2153 if_ip4.add_vpp_config()
2154 if_ip6.add_vpp_config()
2156 # add the BD ARP termination entry for BVI IP
2157 epg.bd_arp_ip4 = VppBridgeDomainArpEntry(self, epg.bd.bd,
2158 str(self.router_mac),
2159 epg.bvi_ip4.address)
2160 epg.bd_arp_ip4.add_vpp_config()
2163 epg.add_vpp_config()
2171 self.logger.info(self.vapi.cli("show gbp endpoint"))
2172 self.logger.info(self.vapi.cli("show interface"))
2173 self.logger.info(self.vapi.cli("show br"))
2176 # Intra epg allowed without contract
2178 pkt_intra_epg_220_to_220 = (Ether(src=self.pg0.remote_mac,
2179 dst=self.pg1.remote_mac) /
2180 IP(src=eps[0].ip4.address,
2181 dst=eps[1].ip4.address) /
2182 UDP(sport=1234, dport=1234) /
2185 self.send_and_expect_bridged(self.pg0,
2186 pkt_intra_epg_220_to_220 * 65,
2189 pkt_intra_epg_220_to_220 = (Ether(src=self.pg0.remote_mac,
2190 dst=self.pg1.remote_mac) /
2191 IPv6(src=eps[0].ip6.address,
2192 dst=eps[1].ip6.address) /
2193 UDP(sport=1234, dport=1234) /
2196 self.send_and_expect_bridged6(self.pg0,
2197 pkt_intra_epg_220_to_220 * 65,
2201 # Inter epg denied without contract
2203 pkt_inter_epg_220_to_221 = (Ether(src=self.pg0.remote_mac,
2204 dst=self.pg2.remote_mac) /
2205 IP(src=eps[0].ip4.address,
2206 dst=eps[2].ip4.address) /
2207 UDP(sport=1234, dport=1234) /
2210 self.send_and_assert_no_replies(self.pg0, pkt_inter_epg_220_to_221)
2213 # A uni-directional contract from EPG 220 -> 221
2215 acl = VppGbpAcl(self)
2216 rule = acl.create_rule(permit_deny=1, proto=17)
2217 rule2 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
2218 rule3 = acl.create_rule(permit_deny=1, proto=1)
2219 acl_index = acl.add_vpp_config([rule, rule2, rule3])
2220 c1 = VppGbpContract(
2221 self, 400, epgs[0].sclass, epgs[1].sclass, acl_index,
2222 [VppGbpContractRule(
2223 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2224 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2227 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2228 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2231 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2232 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2234 [ETH_P_IP, ETH_P_IPV6])
2237 self.send_and_expect_bridged(eps[0].itf,
2238 pkt_inter_epg_220_to_221 * 65,
2241 pkt_inter_epg_220_to_222 = (Ether(src=self.pg0.remote_mac,
2242 dst=str(self.router_mac)) /
2243 IP(src=eps[0].ip4.address,
2244 dst=eps[3].ip4.address) /
2245 UDP(sport=1234, dport=1234) /
2247 self.send_and_assert_no_replies(eps[0].itf,
2248 pkt_inter_epg_220_to_222 * 65)
2251 # ping router IP in different BD
2253 pkt_router_ping_220_to_221 = (Ether(src=self.pg0.remote_mac,
2254 dst=str(self.router_mac)) /
2255 IP(src=eps[0].ip4.address,
2256 dst=epgs[1].bvi_ip4.address) /
2257 ICMP(type='echo-request'))
2259 self.send_and_expect(self.pg0, [pkt_router_ping_220_to_221], self.pg0)
2261 pkt_router_ping_220_to_221 = (Ether(src=self.pg0.remote_mac,
2262 dst=str(self.router_mac)) /
2263 IPv6(src=eps[0].ip6.address,
2264 dst=epgs[1].bvi_ip6.address) /
2265 ICMPv6EchoRequest())
2267 self.send_and_expect(self.pg0, [pkt_router_ping_220_to_221], self.pg0)
2270 # contract for the return direction
2272 c2 = VppGbpContract(
2273 self, 400, epgs[1].sclass, epgs[0].sclass, acl_index,
2274 [VppGbpContractRule(
2275 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2276 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2279 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2280 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2282 [ETH_P_IP, ETH_P_IPV6])
2285 self.send_and_expect_bridged(eps[0].itf,
2286 pkt_inter_epg_220_to_221 * 65,
2288 pkt_inter_epg_221_to_220 = (Ether(src=self.pg2.remote_mac,
2289 dst=self.pg0.remote_mac) /
2290 IP(src=eps[2].ip4.address,
2291 dst=eps[0].ip4.address) /
2292 UDP(sport=1234, dport=1234) /
2294 self.send_and_expect_bridged(eps[2].itf,
2295 pkt_inter_epg_221_to_220 * 65,
2297 pkt_inter_epg_221_to_220 = (Ether(src=self.pg2.remote_mac,
2298 dst=str(self.router_mac)) /
2299 IP(src=eps[2].ip4.address,
2300 dst=eps[0].ip4.address) /
2301 UDP(sport=1234, dport=1234) /
2303 self.send_and_expect_routed(eps[2].itf,
2304 pkt_inter_epg_221_to_220 * 65,
2306 str(self.router_mac))
2307 pkt_inter_epg_221_to_220 = (Ether(src=self.pg2.remote_mac,
2308 dst=str(self.router_mac)) /
2309 IPv6(src=eps[2].ip6.address,
2310 dst=eps[0].ip6.address) /
2311 UDP(sport=1234, dport=1234) /
2313 self.send_and_expect_routed6(eps[2].itf,
2314 pkt_inter_epg_221_to_220 * 65,
2316 str(self.router_mac))
2319 # contract between 220 and 222 uni-direction
2321 c3 = VppGbpContract(
2322 self, 400, epgs[0].sclass, epgs[2].sclass, acl_index,
2323 [VppGbpContractRule(
2324 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2325 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
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,
2331 [ETH_P_IP, ETH_P_IPV6])
2334 self.send_and_expect(eps[0].itf,
2335 pkt_inter_epg_220_to_222 * 65,
2338 c3.remove_vpp_config()
2339 c1.remove_vpp_config()
2340 c2.remove_vpp_config()
2341 acl.remove_vpp_config()
2343 def test_gbp_bd_drop_flags(self):
2344 """ GBP BD drop flags """
2349 gt4 = VppIpTable(self, 1)
2350 gt4.add_vpp_config()
2351 gt6 = VppIpTable(self, 1, is_ip6=True)
2352 gt6.add_vpp_config()
2354 rd1 = VppGbpRouteDomain(self, 1, 401, gt4, gt6)
2355 rd1.add_vpp_config()
2358 # a GBP bridge domain with a BVI only
2360 bd1 = VppBridgeDomain(self, 1)
2361 bd1.add_vpp_config()
2363 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0,
2365 uu_drop=True, bm_drop=True)
2366 gbd1.add_vpp_config()
2368 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2369 self.logger.info(self.vapi.cli("sh gbp bridge"))
2371 # ... and has a /32 applied
2372 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2373 ip_addr.add_vpp_config()
2376 # The Endpoint-group
2378 epg_220 = VppGbpEndpointGroup(self, 220, 112, rd1, gbd1,
2382 VppGbpEndpointRetention(2))
2383 epg_220.add_vpp_config()
2385 ep = VppGbpEndpoint(self, self.pg0,
2387 "10.0.0.127", "11.0.0.127",
2388 "2001:10::1", "3001::1")
2392 # send UU/BM packet from the local EP with UU drop and BM drop enabled
2395 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2396 self.logger.info(self.vapi.cli("sh gbp bridge"))
2397 p_uu = (Ether(src=ep.mac, dst="00:11:11:11:11:11") /
2398 IP(dst="10.0.0.133", src=ep.ip4.address) /
2399 UDP(sport=1234, dport=1234) /
2401 self.send_and_assert_no_replies(ep.itf, [p_uu])
2403 p_bm = (Ether(src=ep.mac, dst="ff:ff:ff:ff:ff:ff") /
2404 IP(dst="10.0.0.133", src=ep.ip4.address) /
2405 UDP(sport=1234, dport=1234) /
2407 self.send_and_assert_no_replies(ep.itf, [p_bm])
2409 self.pg3.unconfig_ip4()
2411 self.logger.info(self.vapi.cli("sh int"))
2413 def test_gbp_bd_arp_flags(self):
2414 """ GBP BD arp flags """
2419 gt4 = VppIpTable(self, 1)
2420 gt4.add_vpp_config()
2421 gt6 = VppIpTable(self, 1, is_ip6=True)
2422 gt6.add_vpp_config()
2424 rd1 = VppGbpRouteDomain(self, 1, 401, gt4, gt6)
2425 rd1.add_vpp_config()
2428 # Pg4 hosts the IP6 UU-flood VXLAN tunnel
2430 self.pg4.config_ip4()
2431 self.pg4.resolve_arp()
2434 # Add a mcast destination VXLAN-GBP tunnel for B&M traffic
2436 tun_uu = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
2439 tun_uu.add_vpp_config()
2442 # a GBP bridge domain with a BVI and a UU-flood interface
2444 bd1 = VppBridgeDomain(self, 1)
2445 bd1.add_vpp_config()
2447 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0,
2450 gbd1.add_vpp_config()
2452 # ... and has a /32 applied
2453 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2454 ip_addr.add_vpp_config()
2457 # The Endpoint-group
2459 epg_220 = VppGbpEndpointGroup(self, 220, 112, rd1, gbd1,
2463 VppGbpEndpointRetention(2))
2464 epg_220.add_vpp_config()
2466 ep = VppGbpEndpoint(self, self.pg0,
2468 "10.0.0.127", "11.0.0.127",
2469 "2001:10::1", "3001::1")
2473 # send ARP packet from the local EP expect it on the uu interface
2475 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2476 self.logger.info(self.vapi.cli("sh gbp bridge"))
2477 p_arp = (Ether(src=ep.mac, dst="ff:ff:ff:ff:ff:ff") /
2479 psrc=ep.ip4.address, pdst="10.0.0.99",
2481 hwdst="ff:ff:ff:ff:ff:ff"))
2482 self.send_and_expect(ep.itf, [p_arp], self.pg4)
2484 self.pg4.unconfig_ip4()
2486 def test_gbp_learn_vlan_l2(self):
2487 """ GBP L2 Endpoint w/ VLANs"""
2489 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
2490 learnt = [{'mac': '00:00:11:11:11:01',
2492 'ip6': '2001:10::2'},
2493 {'mac': '00:00:11:11:11:02',
2495 'ip6': '2001:10::3'}]
2500 gt4 = VppIpTable(self, 1)
2501 gt4.add_vpp_config()
2502 gt6 = VppIpTable(self, 1, is_ip6=True)
2503 gt6.add_vpp_config()
2505 rd1 = VppGbpRouteDomain(self, 1, 401, gt4, gt6)
2506 rd1.add_vpp_config()
2509 # Pg2 hosts the vxlan tunnel, hosts on pg2 to act as TEPs
2511 self.pg2.config_ip4()
2512 self.pg2.resolve_arp()
2513 self.pg2.generate_remote_hosts(4)
2514 self.pg2.configure_ipv4_neighbors()
2515 self.pg3.config_ip4()
2516 self.pg3.resolve_arp()
2519 # The EP will be on a vlan sub-interface
2521 vlan_11 = VppDot1QSubint(self, self.pg0, 11)
2523 self.vapi.l2_interface_vlan_tag_rewrite(
2524 sw_if_index=vlan_11.sw_if_index, vtr_op=L2_VTR_OP.L2_POP_1,
2527 bd_uu_fwd = VppVxlanGbpTunnel(self, self.pg3.local_ip4,
2528 self.pg3.remote_ip4, 116)
2529 bd_uu_fwd.add_vpp_config()
2532 # a GBP bridge domain with a BVI and a UU-flood interface
2533 # The BD is marked as do not learn, so no endpoints are ever
2534 # learnt in this BD.
2536 bd1 = VppBridgeDomain(self, 1)
2537 bd1.add_vpp_config()
2538 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0, bd_uu_fwd,
2540 gbd1.add_vpp_config()
2542 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2543 self.logger.info(self.vapi.cli("sh gbp bridge"))
2545 # ... and has a /32 applied
2546 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2547 ip_addr.add_vpp_config()
2550 # The Endpoint-group in which we are learning endpoints
2552 epg_220 = VppGbpEndpointGroup(self, 220, 441, rd1, gbd1,
2556 VppGbpEndpointRetention(2))
2557 epg_220.add_vpp_config()
2560 # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
2563 vx_tun_l2_1 = VppGbpVxlanTunnel(
2564 self, 99, bd1.bd_id,
2565 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L2,
2567 vx_tun_l2_1.add_vpp_config()
2570 # A static endpoint that the learnt endpoints are trying to
2573 ep = VppGbpEndpoint(self, vlan_11,
2575 "10.0.0.127", "11.0.0.127",
2576 "2001:10::1", "3001::1")
2579 self.assertTrue(find_route(self, ep.ip4.address, 32, table_id=1))
2582 # Send to the static EP
2584 for ii, l in enumerate(learnt):
2585 # a packet with an sclass from a known EPG
2586 # arriving on an unknown TEP
2587 p = (Ether(src=self.pg2.remote_mac,
2588 dst=self.pg2.local_mac) /
2589 IP(src=self.pg2.remote_hosts[1].ip4,
2590 dst=self.pg2.local_ip4) /
2591 UDP(sport=1234, dport=48879) /
2592 VXLAN(vni=99, gpid=441, flags=0x88) /
2593 Ether(src=l['mac'], dst=ep.mac) /
2594 IP(src=l['ip'], dst=ep.ip4.address) /
2595 UDP(sport=1234, dport=1234) /
2598 rxs = self.send_and_expect(self.pg2, [p], self.pg0)
2601 # packet to EP has the EP's vlan tag
2604 self.assertEqual(rx[Dot1Q].vlan, 11)
2607 # the EP is not learnt since the BD setting prevents it
2610 self.assertFalse(find_gbp_endpoint(self,
2611 vx_tun_l2_1.sw_if_index,
2613 self.assertEqual(INDEX_INVALID,
2614 find_vxlan_gbp_tunnel(
2617 self.pg2.remote_hosts[1].ip4,
2620 self.assertEqual(len(self.vapi.gbp_endpoint_dump()), 1)
2624 # we didn't learn the remotes so they are sent to the UU-fwd
2627 p = (Ether(src=ep.mac, dst=l['mac']) /
2629 IP(dst=l['ip'], src=ep.ip4.address) /
2630 UDP(sport=1234, dport=1234) /
2633 rxs = self.send_and_expect(self.pg0, p * 17, self.pg3)
2636 self.assertEqual(rx[IP].src, self.pg3.local_ip4)
2637 self.assertEqual(rx[IP].dst, self.pg3.remote_ip4)
2638 self.assertEqual(rx[UDP].dport, 48879)
2639 # the UDP source port is a random value for hashing
2640 self.assertEqual(rx[VXLAN].gpid, 441)
2641 self.assertEqual(rx[VXLAN].vni, 116)
2642 self.assertTrue(rx[VXLAN].flags.G)
2643 self.assertTrue(rx[VXLAN].flags.Instance)
2644 self.assertFalse(rx[VXLAN].gpflags.A)
2645 self.assertFalse(rx[VXLAN].gpflags.D)
2647 self.pg2.unconfig_ip4()
2648 self.pg3.unconfig_ip4()
2650 def test_gbp_learn_l3(self):
2651 """ GBP L3 Endpoint Learning """
2653 self.vapi.cli("set logging class gbp level debug")
2655 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
2656 routed_dst_mac = "00:0c:0c:0c:0c:0c"
2657 routed_src_mac = "00:22:bd:f8:19:ff"
2659 learnt = [{'mac': '00:00:11:11:11:02',
2661 'ip6': '2001:10::2'},
2662 {'mac': '00:00:11:11:11:03',
2664 'ip6': '2001:10::3'}]
2669 t4 = VppIpTable(self, 1)
2671 t6 = VppIpTable(self, 1, True)
2674 tun_ip4_uu = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
2675 self.pg4.remote_ip4, 114)
2676 tun_ip6_uu = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
2677 self.pg4.remote_ip4, 116)
2678 tun_ip4_uu.add_vpp_config()
2679 tun_ip6_uu.add_vpp_config()
2681 rd1 = VppGbpRouteDomain(self, 2, 401, t4, t6, tun_ip4_uu, tun_ip6_uu)
2682 rd1.add_vpp_config()
2684 self.loop0.set_mac(self.router_mac)
2687 # Bind the BVI to the RD
2689 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
2690 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
2693 # Pg2 hosts the vxlan tunnel
2694 # hosts on pg2 to act as TEPs
2698 self.pg2.config_ip4()
2699 self.pg2.resolve_arp()
2700 self.pg2.generate_remote_hosts(4)
2701 self.pg2.configure_ipv4_neighbors()
2702 self.pg3.config_ip4()
2703 self.pg3.resolve_arp()
2704 self.pg4.config_ip4()
2705 self.pg4.resolve_arp()
2708 # a GBP bridge domain with a BVI and a UU-flood interface
2710 bd1 = VppBridgeDomain(self, 1)
2711 bd1.add_vpp_config()
2712 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0, self.pg3)
2713 gbd1.add_vpp_config()
2715 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2716 self.logger.info(self.vapi.cli("sh gbp bridge"))
2717 self.logger.info(self.vapi.cli("sh gbp route"))
2719 # ... and has a /32 and /128 applied
2720 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2721 ip4_addr.add_vpp_config()
2722 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 128)
2723 ip6_addr.add_vpp_config()
2726 # The Endpoint-group in which we are learning endpoints
2728 epg_220 = VppGbpEndpointGroup(self, 220, 441, rd1, gbd1,
2732 VppGbpEndpointRetention(2))
2733 epg_220.add_vpp_config()
2736 # The VXLAN GBP tunnel is in L3 mode with learning enabled
2738 vx_tun_l3 = VppGbpVxlanTunnel(
2739 self, 101, rd1.rd_id,
2740 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
2742 vx_tun_l3.add_vpp_config()
2745 # A static endpoint that the learnt endpoints are trying to
2748 ep = VppGbpEndpoint(self, self.pg0,
2750 "10.0.0.127", "11.0.0.127",
2751 "2001:10::1", "3001::1")
2755 # learn some remote IPv4 EPs
2757 for ii, l in enumerate(learnt):
2758 # a packet with an sclass from a known EPG
2759 # arriving on an unknown TEP
2760 p = (Ether(src=self.pg2.remote_mac,
2761 dst=self.pg2.local_mac) /
2762 IP(src=self.pg2.remote_hosts[1].ip4,
2763 dst=self.pg2.local_ip4) /
2764 UDP(sport=1234, dport=48879) /
2765 VXLAN(vni=101, gpid=441, flags=0x88) /
2766 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2767 IP(src=l['ip'], dst=ep.ip4.address) /
2768 UDP(sport=1234, dport=1234) /
2771 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2774 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2777 self.pg2.remote_hosts[1].ip4,
2779 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2781 # endpoint learnt via the parent GBP-vxlan interface
2782 self.assertTrue(find_gbp_endpoint(self,
2783 vx_tun_l3._sw_if_index,
2787 # Static IPv4 EP replies to learnt
2790 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2791 IP(dst=l['ip'], src=ep.ip4.address) /
2792 UDP(sport=1234, dport=1234) /
2795 rxs = self.send_and_expect(self.pg0, p * 1, self.pg2)
2798 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2799 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2800 self.assertEqual(rx[UDP].dport, 48879)
2801 # the UDP source port is a random value for hashing
2802 self.assertEqual(rx[VXLAN].gpid, 441)
2803 self.assertEqual(rx[VXLAN].vni, 101)
2804 self.assertTrue(rx[VXLAN].flags.G)
2805 self.assertTrue(rx[VXLAN].flags.Instance)
2806 self.assertTrue(rx[VXLAN].gpflags.A)
2807 self.assertFalse(rx[VXLAN].gpflags.D)
2809 inner = rx[VXLAN].payload
2811 self.assertEqual(inner[Ether].src, routed_src_mac)
2812 self.assertEqual(inner[Ether].dst, routed_dst_mac)
2813 self.assertEqual(inner[IP].src, ep.ip4.address)
2814 self.assertEqual(inner[IP].dst, l['ip'])
2817 self.assertFalse(find_gbp_endpoint(self,
2822 # learn some remote IPv6 EPs
2824 for ii, l in enumerate(learnt):
2825 # a packet with an sclass from a known EPG
2826 # arriving on an unknown TEP
2827 p = (Ether(src=self.pg2.remote_mac,
2828 dst=self.pg2.local_mac) /
2829 IP(src=self.pg2.remote_hosts[1].ip4,
2830 dst=self.pg2.local_ip4) /
2831 UDP(sport=1234, dport=48879) /
2832 VXLAN(vni=101, gpid=441, flags=0x88) /
2833 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2834 IPv6(src=l['ip6'], dst=ep.ip6.address) /
2835 UDP(sport=1234, dport=1234) /
2838 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2841 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2844 self.pg2.remote_hosts[1].ip4,
2846 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2848 self.logger.info(self.vapi.cli("show gbp bridge"))
2849 self.logger.info(self.vapi.cli("show vxlan-gbp tunnel"))
2850 self.logger.info(self.vapi.cli("show gbp vxlan"))
2851 self.logger.info(self.vapi.cli("show int addr"))
2853 # endpoint learnt via the TEP
2854 self.assertTrue(find_gbp_endpoint(self, ip=l['ip6']))
2856 self.logger.info(self.vapi.cli("show gbp endpoint"))
2857 self.logger.info(self.vapi.cli("show ip fib index 1 %s" % l['ip']))
2860 # Static EP replies to learnt
2863 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2864 IPv6(dst=l['ip6'], src=ep.ip6.address) /
2865 UDP(sport=1234, dport=1234) /
2868 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
2871 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2872 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2873 self.assertEqual(rx[UDP].dport, 48879)
2874 # the UDP source port is a random value for hashing
2875 self.assertEqual(rx[VXLAN].gpid, 441)
2876 self.assertEqual(rx[VXLAN].vni, 101)
2877 self.assertTrue(rx[VXLAN].flags.G)
2878 self.assertTrue(rx[VXLAN].flags.Instance)
2879 self.assertTrue(rx[VXLAN].gpflags.A)
2880 self.assertFalse(rx[VXLAN].gpflags.D)
2882 inner = rx[VXLAN].payload
2884 self.assertEqual(inner[Ether].src, routed_src_mac)
2885 self.assertEqual(inner[Ether].dst, routed_dst_mac)
2886 self.assertEqual(inner[IPv6].src, ep.ip6.address)
2887 self.assertEqual(inner[IPv6].dst, l['ip6'])
2889 self.logger.info(self.vapi.cli("sh gbp endpoint"))
2891 self.wait_for_ep_timeout(ip=l['ip'])
2894 # Static sends to unknown EP with no route
2896 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2897 IP(dst="10.0.0.99", src=ep.ip4.address) /
2898 UDP(sport=1234, dport=1234) /
2901 self.send_and_assert_no_replies(self.pg0, [p])
2904 # Add a route to static EP's v4 and v6 subnet
2906 se_10_24 = VppGbpSubnet(
2907 self, rd1, "10.0.0.0", 24,
2908 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT)
2909 se_10_24.add_vpp_config()
2912 # static pings router
2914 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2915 IP(dst=epg_220.bvi_ip4.address, src=ep.ip4.address) /
2916 UDP(sport=1234, dport=1234) /
2919 self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg0)
2921 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2922 IPv6(dst=epg_220.bvi_ip6.address, src=ep.ip6.address) /
2923 UDP(sport=1234, dport=1234) /
2926 self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg0)
2929 # packets to address in the subnet are sent on the uu-fwd
2931 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2932 IP(dst="10.0.0.99", src=ep.ip4.address) /
2933 UDP(sport=1234, dport=1234) /
2936 rxs = self.send_and_expect(self.pg0, [p], self.pg4)
2938 self.assertEqual(rx[IP].src, self.pg4.local_ip4)
2939 self.assertEqual(rx[IP].dst, self.pg4.remote_ip4)
2940 self.assertEqual(rx[UDP].dport, 48879)
2941 # the UDP source port is a random value for hashing
2942 self.assertEqual(rx[VXLAN].gpid, 441)
2943 self.assertEqual(rx[VXLAN].vni, 114)
2944 self.assertTrue(rx[VXLAN].flags.G)
2945 self.assertTrue(rx[VXLAN].flags.Instance)
2946 # policy is not applied to packets sent to the uu-fwd interfaces
2947 self.assertFalse(rx[VXLAN].gpflags.A)
2948 self.assertFalse(rx[VXLAN].gpflags.D)
2951 # learn some remote IPv4 EPs
2953 for ii, l in enumerate(learnt):
2954 # a packet with an sclass from a known EPG
2955 # arriving on an unknown TEP
2956 p = (Ether(src=self.pg2.remote_mac,
2957 dst=self.pg2.local_mac) /
2958 IP(src=self.pg2.remote_hosts[2].ip4,
2959 dst=self.pg2.local_ip4) /
2960 UDP(sport=1234, dport=48879) /
2961 VXLAN(vni=101, gpid=441, flags=0x88) /
2962 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2963 IP(src=l['ip'], dst=ep.ip4.address) /
2964 UDP(sport=1234, dport=1234) /
2967 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2970 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2973 self.pg2.remote_hosts[2].ip4,
2975 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2977 # endpoint learnt via the parent GBP-vxlan interface
2978 self.assertTrue(find_gbp_endpoint(self,
2979 vx_tun_l3._sw_if_index,
2983 # Add a remote endpoint from the API
2985 rep_88 = VppGbpEndpoint(self, vx_tun_l3,
2987 "10.0.0.88", "11.0.0.88",
2988 "2001:10::88", "3001::88",
2989 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
2991 self.pg2.remote_hosts[2].ip4,
2993 rep_88.add_vpp_config()
2996 # Add a remote endpoint from the API that matches an existing one
2997 # this is a lower priority, hence the packet is sent to the DP leanrt
3000 rep_2 = VppGbpEndpoint(self, vx_tun_l3,
3002 learnt[0]['ip'], "11.0.0.101",
3003 learnt[0]['ip6'], "3001::101",
3004 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
3006 self.pg2.remote_hosts[1].ip4,
3008 rep_2.add_vpp_config()
3011 # Add a route to the learned EP's v4 subnet
3012 # packets should be send on the v4/v6 uu=fwd interface resp.
3014 se_10_1_24 = VppGbpSubnet(
3015 self, rd1, "10.0.1.0", 24,
3016 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT)
3017 se_10_1_24.add_vpp_config()
3019 self.logger.info(self.vapi.cli("show gbp endpoint"))
3021 ips = ["10.0.0.88", learnt[0]['ip']]
3023 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
3024 IP(dst=ip, src=ep.ip4.address) /
3025 UDP(sport=1234, dport=1234) /
3028 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
3031 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
3032 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[2].ip4)
3033 self.assertEqual(rx[UDP].dport, 48879)
3034 # the UDP source port is a random value for hashing
3035 self.assertEqual(rx[VXLAN].gpid, 441)
3036 self.assertEqual(rx[VXLAN].vni, 101)
3037 self.assertTrue(rx[VXLAN].flags.G)
3038 self.assertTrue(rx[VXLAN].flags.Instance)
3039 self.assertTrue(rx[VXLAN].gpflags.A)
3040 self.assertFalse(rx[VXLAN].gpflags.D)
3042 inner = rx[VXLAN].payload
3044 self.assertEqual(inner[Ether].src, routed_src_mac)
3045 self.assertEqual(inner[Ether].dst, routed_dst_mac)
3046 self.assertEqual(inner[IP].src, ep.ip4.address)
3047 self.assertEqual(inner[IP].dst, ip)
3050 # remove the API remote EPs, only API sourced is gone, the DP
3051 # learnt one remains
3053 rep_88.remove_vpp_config()
3054 rep_2.remove_vpp_config()
3056 self.assertTrue(find_gbp_endpoint(self, ip=rep_2.ip4.address))
3058 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
3059 IP(src=ep.ip4.address, dst=rep_2.ip4.address) /
3060 UDP(sport=1234, dport=1234) /
3062 rxs = self.send_and_expect(self.pg0, [p], self.pg2)
3064 self.assertFalse(find_gbp_endpoint(self, ip=rep_88.ip4.address))
3066 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
3067 IP(src=ep.ip4.address, dst=rep_88.ip4.address) /
3068 UDP(sport=1234, dport=1234) /
3070 rxs = self.send_and_expect(self.pg0, [p], self.pg4)
3073 # to appease the testcase we cannot have the registered EP still
3074 # present (because it's DP learnt) when the TC ends so wait until
3077 self.wait_for_ep_timeout(ip=rep_88.ip4.address)
3078 self.wait_for_ep_timeout(ip=rep_2.ip4.address)
3081 # Same as above, learn a remote EP via CP and DP
3082 # this time remove the DP one first. expect the CP data to remain
3084 rep_3 = VppGbpEndpoint(self, vx_tun_l3,
3086 "10.0.1.4", "11.0.0.103",
3087 "2001::10:3", "3001::103",
3088 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
3090 self.pg2.remote_hosts[1].ip4,
3092 rep_3.add_vpp_config()
3094 p = (Ether(src=self.pg2.remote_mac,
3095 dst=self.pg2.local_mac) /
3096 IP(src=self.pg2.remote_hosts[2].ip4,
3097 dst=self.pg2.local_ip4) /
3098 UDP(sport=1234, dport=48879) /
3099 VXLAN(vni=101, gpid=441, flags=0x88) /
3100 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
3101 IP(src="10.0.1.4", dst=ep.ip4.address) /
3102 UDP(sport=1234, dport=1234) /
3104 rxs = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
3106 self.assertTrue(find_gbp_endpoint(self,
3107 vx_tun_l3._sw_if_index,
3108 ip=rep_3.ip4.address,
3109 tep=[self.pg2.local_ip4,
3110 self.pg2.remote_hosts[2].ip4]))
3112 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
3113 IP(dst="10.0.1.4", src=ep.ip4.address) /
3114 UDP(sport=1234, dport=1234) /
3116 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
3118 # host 2 is the DP learned TEP
3120 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
3121 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[2].ip4)
3123 self.wait_for_ep_timeout(ip=rep_3.ip4.address,
3124 tep=[self.pg2.local_ip4,
3125 self.pg2.remote_hosts[2].ip4])
3127 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
3129 # host 1 is the CP learned TEP
3131 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
3132 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
3135 # shutdown with learnt endpoint present
3137 p = (Ether(src=self.pg2.remote_mac,
3138 dst=self.pg2.local_mac) /
3139 IP(src=self.pg2.remote_hosts[1].ip4,
3140 dst=self.pg2.local_ip4) /
3141 UDP(sport=1234, dport=48879) /
3142 VXLAN(vni=101, gpid=441, flags=0x88) /
3143 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
3144 IP(src=learnt[1]['ip'], dst=ep.ip4.address) /
3145 UDP(sport=1234, dport=1234) /
3148 rx = self.send_and_expect(self.pg2, [p], self.pg0)
3150 # endpoint learnt via the parent GBP-vxlan interface
3151 self.assertTrue(find_gbp_endpoint(self,
3152 vx_tun_l3._sw_if_index,
3157 # remote endpoint becomes local
3159 self.pg2.unconfig_ip4()
3160 self.pg3.unconfig_ip4()
3161 self.pg4.unconfig_ip4()
3163 def test_gbp_redirect(self):
3164 """ GBP Endpoint Redirect """
3166 self.vapi.cli("set logging class gbp level debug")
3168 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
3169 routed_dst_mac = "00:0c:0c:0c:0c:0c"
3170 routed_src_mac = "00:22:bd:f8:19:ff"
3172 learnt = [{'mac': '00:00:11:11:11:02',
3174 'ip6': '2001:10::2'},
3175 {'mac': '00:00:11:11:11:03',
3177 'ip6': '2001:10::3'}]
3182 t4 = VppIpTable(self, 1)
3184 t6 = VppIpTable(self, 1, True)
3187 rd1 = VppGbpRouteDomain(self, 2, 402, t4, t6)
3188 rd1.add_vpp_config()
3190 self.loop0.set_mac(self.router_mac)
3193 # Bind the BVI to the RD
3195 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
3196 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
3199 # Pg7 hosts a BD's UU-fwd
3201 self.pg7.config_ip4()
3202 self.pg7.resolve_arp()
3205 # a GBP bridge domains for the EPs
3207 bd1 = VppBridgeDomain(self, 1)
3208 bd1.add_vpp_config()
3209 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0)
3210 gbd1.add_vpp_config()
3212 bd2 = VppBridgeDomain(self, 2)
3213 bd2.add_vpp_config()
3214 gbd2 = VppGbpBridgeDomain(self, bd2, rd1, self.loop1)
3215 gbd2.add_vpp_config()
3217 # ... and has a /32 and /128 applied
3218 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
3219 ip4_addr.add_vpp_config()
3220 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 128)
3221 ip6_addr.add_vpp_config()
3222 ip4_addr = VppIpInterfaceAddress(self, gbd2.bvi, "10.0.1.128", 32)
3223 ip4_addr.add_vpp_config()
3224 ip6_addr = VppIpInterfaceAddress(self, gbd2.bvi, "2001:11::128", 128)
3225 ip6_addr.add_vpp_config()
3228 # The Endpoint-groups in which we are learning endpoints
3230 epg_220 = VppGbpEndpointGroup(self, 220, 440, rd1, gbd1,
3234 VppGbpEndpointRetention(2))
3235 epg_220.add_vpp_config()
3236 epg_221 = VppGbpEndpointGroup(self, 221, 441, rd1, gbd2,
3240 VppGbpEndpointRetention(2))
3241 epg_221.add_vpp_config()
3242 epg_222 = VppGbpEndpointGroup(self, 222, 442, rd1, gbd1,
3246 VppGbpEndpointRetention(2))
3247 epg_222.add_vpp_config()
3250 # a GBP bridge domains for the SEPs
3252 bd_uu1 = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
3253 self.pg7.remote_ip4, 116)
3254 bd_uu1.add_vpp_config()
3255 bd_uu2 = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
3256 self.pg7.remote_ip4, 117)
3257 bd_uu2.add_vpp_config()
3259 bd3 = VppBridgeDomain(self, 3)
3260 bd3.add_vpp_config()
3261 gbd3 = VppGbpBridgeDomain(self, bd3, rd1, self.loop2,
3262 bd_uu1, learn=False)
3263 gbd3.add_vpp_config()
3264 bd4 = VppBridgeDomain(self, 4)
3265 bd4.add_vpp_config()
3266 gbd4 = VppGbpBridgeDomain(self, bd4, rd1, self.loop3,
3267 bd_uu2, learn=False)
3268 gbd4.add_vpp_config()
3271 # EPGs in which the service endpoints exist
3273 epg_320 = VppGbpEndpointGroup(self, 320, 550, rd1, gbd3,
3277 VppGbpEndpointRetention(2))
3278 epg_320.add_vpp_config()
3279 epg_321 = VppGbpEndpointGroup(self, 321, 551, rd1, gbd4,
3283 VppGbpEndpointRetention(2))
3284 epg_321.add_vpp_config()
3287 # three local endpoints
3289 ep1 = VppGbpEndpoint(self, self.pg0,
3291 "10.0.0.1", "11.0.0.1",
3292 "2001:10::1", "3001:10::1")
3293 ep1.add_vpp_config()
3294 ep2 = VppGbpEndpoint(self, self.pg1,
3296 "10.0.1.1", "11.0.1.1",
3297 "2001:11::1", "3001:11::1")
3298 ep2.add_vpp_config()
3299 ep3 = VppGbpEndpoint(self, self.pg2,
3301 "10.0.2.2", "11.0.2.2",
3302 "2001:12::1", "3001:12::1")
3303 ep3.add_vpp_config()
3308 sep1 = VppGbpEndpoint(self, self.pg3,
3310 "12.0.0.1", "13.0.0.1",
3311 "4001:10::1", "5001:10::1")
3312 sep1.add_vpp_config()
3313 sep2 = VppGbpEndpoint(self, self.pg4,
3315 "12.0.0.2", "13.0.0.2",
3316 "4001:10::2", "5001:10::2")
3317 sep2.add_vpp_config()
3318 sep3 = VppGbpEndpoint(self, self.pg5,
3320 "12.0.1.1", "13.0.1.1",
3321 "4001:11::1", "5001:11::1")
3322 sep3.add_vpp_config()
3323 # this EP is not installed immediately
3324 sep4 = VppGbpEndpoint(self, self.pg6,
3326 "12.0.1.2", "13.0.1.2",
3327 "4001:11::2", "5001:11::2")
3330 # an L2 switch packet between local EPs in different EPGs
3331 # different dest ports on each so the are LB hashed differently
3333 p4 = [(Ether(src=ep1.mac, dst=ep3.mac) /
3334 IP(src=ep1.ip4.address, dst=ep3.ip4.address) /
3335 UDP(sport=1234, dport=1234) /
3337 (Ether(src=ep3.mac, dst=ep1.mac) /
3338 IP(src=ep3.ip4.address, dst=ep1.ip4.address) /
3339 UDP(sport=1234, dport=1234) /
3341 p6 = [(Ether(src=ep1.mac, dst=ep3.mac) /
3342 IPv6(src=ep1.ip6.address, dst=ep3.ip6.address) /
3343 UDP(sport=1234, dport=1234) /
3345 (Ether(src=ep3.mac, dst=ep1.mac) /
3346 IPv6(src=ep3.ip6.address, dst=ep1.ip6.address) /
3347 UDP(sport=1234, dport=1230) /
3350 # should be dropped since no contract yet
3351 self.send_and_assert_no_replies(self.pg0, [p4[0]])
3352 self.send_and_assert_no_replies(self.pg0, [p6[0]])
3355 # Add a contract with a rule to load-balance redirect via SEP1 and SEP2
3356 # one of the next-hops is via an EP that is not known
3358 acl = VppGbpAcl(self)
3359 rule4 = acl.create_rule(permit_deny=1, proto=17)
3360 rule6 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
3361 acl_index = acl.add_vpp_config([rule4, rule6])
3364 # test the src-ip hash mode
3366 c1 = VppGbpContract(
3367 self, 402, epg_220.sclass, epg_222.sclass, acl_index,
3368 [VppGbpContractRule(
3369 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3370 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3371 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3372 sep1.ip4, sep1.epg.rd),
3373 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3374 sep2.ip4, sep2.epg.rd)]),
3376 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3377 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3378 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3379 sep3.ip6, sep3.epg.rd),
3380 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3381 sep4.ip6, sep4.epg.rd)])],
3382 [ETH_P_IP, ETH_P_IPV6])
3385 c2 = VppGbpContract(
3386 self, 402, epg_222.sclass, epg_220.sclass, acl_index,
3387 [VppGbpContractRule(
3388 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3389 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3390 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3391 sep1.ip4, sep1.epg.rd),
3392 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3393 sep2.ip4, sep2.epg.rd)]),
3395 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3396 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3397 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3398 sep3.ip6, sep3.epg.rd),
3399 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3400 sep4.ip6, sep4.epg.rd)])],
3401 [ETH_P_IP, ETH_P_IPV6])
3405 # send again with the contract preset, now packets arrive
3406 # at SEP1 or SEP2 depending on the hashing
3408 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3411 self.assertEqual(rx[Ether].src, routed_src_mac)
3412 self.assertEqual(rx[Ether].dst, sep1.mac)
3413 self.assertEqual(rx[IP].src, ep1.ip4.address)
3414 self.assertEqual(rx[IP].dst, ep3.ip4.address)
3416 rxs = self.send_and_expect(self.pg2, p4[1] * 17, sep2.itf)
3419 self.assertEqual(rx[Ether].src, routed_src_mac)
3420 self.assertEqual(rx[Ether].dst, sep2.mac)
3421 self.assertEqual(rx[IP].src, ep3.ip4.address)
3422 self.assertEqual(rx[IP].dst, ep1.ip4.address)
3424 rxs = self.send_and_expect(self.pg0, p6[0] * 17, self.pg7)
3427 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3428 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3429 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3430 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
3431 self.assertEqual(rx[VXLAN].vni, 117)
3432 self.assertTrue(rx[VXLAN].flags.G)
3433 self.assertTrue(rx[VXLAN].flags.Instance)
3434 # redirect policy has been applied
3435 self.assertTrue(rx[VXLAN].gpflags.A)
3436 self.assertFalse(rx[VXLAN].gpflags.D)
3438 inner = rx[VXLAN].payload
3440 self.assertEqual(inner[Ether].src, routed_src_mac)
3441 self.assertEqual(inner[Ether].dst, sep4.mac)
3442 self.assertEqual(inner[IPv6].src, ep1.ip6.address)
3443 self.assertEqual(inner[IPv6].dst, ep3.ip6.address)
3445 rxs = self.send_and_expect(self.pg2, p6[1] * 17, sep3.itf)
3448 self.assertEqual(rx[Ether].src, routed_src_mac)
3449 self.assertEqual(rx[Ether].dst, sep3.mac)
3450 self.assertEqual(rx[IPv6].src, ep3.ip6.address)
3451 self.assertEqual(rx[IPv6].dst, ep1.ip6.address)
3454 # programme the unknown EP
3456 sep4.add_vpp_config()
3458 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep4.itf)
3461 self.assertEqual(rx[Ether].src, routed_src_mac)
3462 self.assertEqual(rx[Ether].dst, sep4.mac)
3463 self.assertEqual(rx[IPv6].src, ep1.ip6.address)
3464 self.assertEqual(rx[IPv6].dst, ep3.ip6.address)
3467 # and revert back to unprogrammed
3469 sep4.remove_vpp_config()
3471 rxs = self.send_and_expect(self.pg0, p6[0] * 17, self.pg7)
3474 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3475 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3476 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3477 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
3478 self.assertEqual(rx[VXLAN].vni, 117)
3479 self.assertTrue(rx[VXLAN].flags.G)
3480 self.assertTrue(rx[VXLAN].flags.Instance)
3481 # redirect policy has been applied
3482 self.assertTrue(rx[VXLAN].gpflags.A)
3483 self.assertFalse(rx[VXLAN].gpflags.D)
3485 inner = rx[VXLAN].payload
3487 self.assertEqual(inner[Ether].src, routed_src_mac)
3488 self.assertEqual(inner[Ether].dst, sep4.mac)
3489 self.assertEqual(inner[IPv6].src, ep1.ip6.address)
3490 self.assertEqual(inner[IPv6].dst, ep3.ip6.address)
3492 c1.remove_vpp_config()
3493 c2.remove_vpp_config()
3496 # test the symmetric hash mode
3498 c1 = VppGbpContract(
3499 self, 402, epg_220.sclass, epg_222.sclass, acl_index,
3500 [VppGbpContractRule(
3501 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3502 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3503 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3504 sep1.ip4, sep1.epg.rd),
3505 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3506 sep2.ip4, sep2.epg.rd)]),
3508 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3509 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3510 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3511 sep3.ip6, sep3.epg.rd),
3512 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3513 sep4.ip6, sep4.epg.rd)])],
3514 [ETH_P_IP, ETH_P_IPV6])
3517 c2 = VppGbpContract(
3518 self, 402, epg_222.sclass, epg_220.sclass, acl_index,
3519 [VppGbpContractRule(
3520 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3521 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3522 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3523 sep1.ip4, sep1.epg.rd),
3524 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3525 sep2.ip4, sep2.epg.rd)]),
3527 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3528 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3529 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3530 sep3.ip6, sep3.epg.rd),
3531 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3532 sep4.ip6, sep4.epg.rd)])],
3533 [ETH_P_IP, ETH_P_IPV6])
3537 # send again with the contract preset, now packets arrive
3538 # at SEP1 for both directions
3540 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3543 self.assertEqual(rx[Ether].src, routed_src_mac)
3544 self.assertEqual(rx[Ether].dst, sep1.mac)
3545 self.assertEqual(rx[IP].src, ep1.ip4.address)
3546 self.assertEqual(rx[IP].dst, ep3.ip4.address)
3548 rxs = self.send_and_expect(self.pg2, p4[1] * 17, sep1.itf)
3551 self.assertEqual(rx[Ether].src, routed_src_mac)
3552 self.assertEqual(rx[Ether].dst, sep1.mac)
3553 self.assertEqual(rx[IP].src, ep3.ip4.address)
3554 self.assertEqual(rx[IP].dst, ep1.ip4.address)
3557 # programme the unknown EP for the L3 tests
3559 sep4.add_vpp_config()
3562 # an L3 switch packet between local EPs in different EPGs
3563 # different dest ports on each so the are LB hashed differently
3565 p4 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3566 IP(src=ep1.ip4.address, dst=ep2.ip4.address) /
3567 UDP(sport=1234, dport=1234) /
3569 (Ether(src=ep2.mac, dst=str(self.router_mac)) /
3570 IP(src=ep2.ip4.address, dst=ep1.ip4.address) /
3571 UDP(sport=1234, dport=1234) /
3573 p6 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3574 IPv6(src=ep1.ip6.address, dst=ep2.ip6.address) /
3575 UDP(sport=1234, dport=1234) /
3577 (Ether(src=ep2.mac, dst=str(self.router_mac)) /
3578 IPv6(src=ep2.ip6.address, dst=ep1.ip6.address) /
3579 UDP(sport=1234, dport=1234) /
3582 c3 = VppGbpContract(
3583 self, 402, epg_220.sclass, epg_221.sclass, acl_index,
3584 [VppGbpContractRule(
3585 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3586 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3587 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3588 sep1.ip4, sep1.epg.rd),
3589 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3590 sep2.ip4, sep2.epg.rd)]),
3592 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3593 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3594 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3595 sep3.ip6, sep3.epg.rd),
3596 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3597 sep4.ip6, sep4.epg.rd)])],
3598 [ETH_P_IP, ETH_P_IPV6])
3601 rxs = self.send_and_expect(self.pg0, p4[0] * 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, ep1.ip4.address)
3607 self.assertEqual(rx[IP].dst, ep2.ip4.address)
3610 # learn a remote EP in EPG 221
3612 vx_tun_l3 = VppGbpVxlanTunnel(
3613 self, 444, rd1.rd_id,
3614 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
3616 vx_tun_l3.add_vpp_config()
3618 c4 = VppGbpContract(
3619 self, 402, epg_221.sclass, epg_220.sclass, acl_index,
3620 [VppGbpContractRule(
3621 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3622 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3625 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3626 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3628 [ETH_P_IP, ETH_P_IPV6])
3631 p = (Ether(src=self.pg7.remote_mac,
3632 dst=self.pg7.local_mac) /
3633 IP(src=self.pg7.remote_ip4,
3634 dst=self.pg7.local_ip4) /
3635 UDP(sport=1234, dport=48879) /
3636 VXLAN(vni=444, gpid=441, flags=0x88) /
3637 Ether(src="00:22:22:22:22:33", dst=str(self.router_mac)) /
3638 IP(src="10.0.0.88", dst=ep1.ip4.address) /
3639 UDP(sport=1234, dport=1234) /
3642 rx = self.send_and_expect(self.pg7, [p], self.pg0)
3644 # endpoint learnt via the parent GBP-vxlan interface
3645 self.assertTrue(find_gbp_endpoint(self,
3646 vx_tun_l3._sw_if_index,
3649 p = (Ether(src=self.pg7.remote_mac,
3650 dst=self.pg7.local_mac) /
3651 IP(src=self.pg7.remote_ip4,
3652 dst=self.pg7.local_ip4) /
3653 UDP(sport=1234, dport=48879) /
3654 VXLAN(vni=444, gpid=441, flags=0x88) /
3655 Ether(src="00:22:22:22:22:33", dst=str(self.router_mac)) /
3656 IPv6(src="2001:10::88", dst=ep1.ip6.address) /
3657 UDP(sport=1234, dport=1234) /
3660 rx = self.send_and_expect(self.pg7, [p], self.pg0)
3662 # endpoint learnt via the parent GBP-vxlan interface
3663 self.assertTrue(find_gbp_endpoint(self,
3664 vx_tun_l3._sw_if_index,
3668 # L3 switch from local to remote EP
3670 p4 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3671 IP(src=ep1.ip4.address, dst="10.0.0.88") /
3672 UDP(sport=1234, dport=1234) /
3674 p6 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3675 IPv6(src=ep1.ip6.address, dst="2001:10::88") /
3676 UDP(sport=1234, dport=1234) /
3679 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3682 self.assertEqual(rx[Ether].src, routed_src_mac)
3683 self.assertEqual(rx[Ether].dst, sep1.mac)
3684 self.assertEqual(rx[IP].src, ep1.ip4.address)
3685 self.assertEqual(rx[IP].dst, "10.0.0.88")
3687 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep4.itf)
3690 self.assertEqual(rx[Ether].src, routed_src_mac)
3691 self.assertEqual(rx[Ether].dst, sep4.mac)
3692 self.assertEqual(rx[IPv6].src, ep1.ip6.address)
3693 self.assertEqual(rx[IPv6].dst, "2001:10::88")
3696 # test the dst-ip hash mode
3698 c5 = VppGbpContract(
3699 self, 402, epg_220.sclass, epg_221.sclass, acl_index,
3700 [VppGbpContractRule(
3701 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3702 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
3703 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3704 sep1.ip4, sep1.epg.rd),
3705 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3706 sep2.ip4, sep2.epg.rd)]),
3708 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3709 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
3710 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3711 sep3.ip6, sep3.epg.rd),
3712 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3713 sep4.ip6, sep4.epg.rd)])],
3714 [ETH_P_IP, ETH_P_IPV6])
3717 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3720 self.assertEqual(rx[Ether].src, routed_src_mac)
3721 self.assertEqual(rx[Ether].dst, sep1.mac)
3722 self.assertEqual(rx[IP].src, ep1.ip4.address)
3723 self.assertEqual(rx[IP].dst, "10.0.0.88")
3725 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep3.itf)
3728 self.assertEqual(rx[Ether].src, routed_src_mac)
3729 self.assertEqual(rx[Ether].dst, sep3.mac)
3730 self.assertEqual(rx[IPv6].src, ep1.ip6.address)
3731 self.assertEqual(rx[IPv6].dst, "2001:10::88")
3736 self.pg7.unconfig_ip4()
3738 def test_gbp_l3_out(self):
3741 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
3742 self.vapi.cli("set logging class gbp level debug")
3744 routed_dst_mac = "00:0c:0c:0c:0c:0c"
3745 routed_src_mac = "00:22:bd:f8:19:ff"
3750 t4 = VppIpTable(self, 1)
3752 t6 = VppIpTable(self, 1, True)
3755 rd1 = VppGbpRouteDomain(self, 2, 55, t4, t6)
3756 rd1.add_vpp_config()
3758 self.loop0.set_mac(self.router_mac)
3761 # Bind the BVI to the RD
3763 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
3764 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
3767 # Pg7 hosts a BD's BUM
3768 # Pg1 some other l3 interface
3770 self.pg7.config_ip4()
3771 self.pg7.resolve_arp()
3774 # a multicast vxlan-gbp tunnel for broadcast in the BD
3776 tun_bm = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
3779 tun_bm.add_vpp_config()
3782 # a GBP external bridge domains for the EPs
3784 bd1 = VppBridgeDomain(self, 1)
3785 bd1.add_vpp_config()
3786 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0, None, tun_bm)
3787 gbd1.add_vpp_config()
3790 # The Endpoint-groups in which the external endpoints exist
3792 epg_220 = VppGbpEndpointGroup(self, 220, 113, rd1, gbd1,
3796 VppGbpEndpointRetention(2))
3797 epg_220.add_vpp_config()
3799 # the BVIs have the subnets applied ...
3800 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 24)
3801 ip4_addr.add_vpp_config()
3802 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 64)
3803 ip6_addr.add_vpp_config()
3805 # ... which are L3-out subnets
3806 l3o_1 = VppGbpSubnet(
3807 self, rd1, "10.0.0.0", 24,
3808 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3810 l3o_1.add_vpp_config()
3813 # an external interface attached to the outside world and the
3816 VppL2Vtr(self, self.vlan_100, L2_VTR_OP.L2_POP_1).add_vpp_config()
3817 VppL2Vtr(self, self.vlan_101, L2_VTR_OP.L2_POP_1).add_vpp_config()
3818 vlan_144 = VppDot1QSubint(self, self.pg0, 144)
3820 # vlan_102 is not poped
3822 ext_itf = VppGbpExtItf(self, self.loop0, bd1, rd1)
3823 ext_itf.add_vpp_config()
3826 # an unicast vxlan-gbp for inter-RD traffic
3828 vx_tun_l3 = VppGbpVxlanTunnel(
3829 self, 444, rd1.rd_id,
3830 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
3832 vx_tun_l3.add_vpp_config()
3835 # External Endpoints
3837 eep1 = VppGbpEndpoint(self, self.vlan_100,
3839 "10.0.0.1", "11.0.0.1",
3840 "2001:10::1", "3001::1",
3841 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
3842 eep1.add_vpp_config()
3843 eep2 = VppGbpEndpoint(self, self.vlan_101,
3845 "10.0.0.2", "11.0.0.2",
3846 "2001:10::2", "3001::2",
3847 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
3848 eep2.add_vpp_config()
3849 eep3 = VppGbpEndpoint(self, self.vlan_102,
3851 "10.0.0.3", "11.0.0.3",
3852 "2001:10::3", "3001::3",
3853 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
3854 eep3.add_vpp_config()
3857 # A remote external endpoint
3859 rep = VppGbpEndpoint(self, vx_tun_l3,
3861 "10.0.0.101", "11.0.0.101",
3862 "2001:10::101", "3001::101",
3863 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
3865 self.pg7.remote_ip4,
3867 rep.add_vpp_config()
3870 # EP1 impersonating EP3 is dropped
3872 p = (Ether(src=eep1.mac, dst="ff:ff:ff:ff:ff:ff") /
3875 psrc="10.0.0.3", pdst="10.0.0.128",
3876 hwsrc=eep1.mac, hwdst="ff:ff:ff:ff:ff:ff"))
3877 self.send_and_assert_no_replies(self.pg0, p)
3880 # ARP packet from External EPs are accepted and replied to
3882 p_arp = (Ether(src=eep1.mac, dst="ff:ff:ff:ff:ff:ff") /
3885 psrc=eep1.ip4.address, pdst="10.0.0.128",
3886 hwsrc=eep1.mac, hwdst="ff:ff:ff:ff:ff:ff"))
3887 rxs = self.send_and_expect(self.pg0, p_arp * 1, self.pg0)
3890 # ARP packet from host in remote subnet are accepted and replied to
3892 p_arp = (Ether(src=eep3.mac, dst="ff:ff:ff:ff:ff:ff") /
3895 psrc=eep3.ip4.address, pdst="10.0.0.128",
3896 hwsrc=eep3.mac, hwdst="ff:ff:ff:ff:ff:ff"))
3897 rxs = self.send_and_expect(self.pg0, p_arp * 1, self.pg0)
3900 # packets destined to unknown addresses in the BVI's subnet
3903 p4 = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3905 IP(src="10.0.0.1", dst="10.0.0.88") /
3906 UDP(sport=1234, dport=1234) /
3908 p6 = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3910 IPv6(src="2001:10::1", dst="2001:10::88") /
3911 UDP(sport=1234, dport=1234) /
3914 rxs = self.send_and_expect(self.pg0, p4 * 1, self.pg7)
3917 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3918 # self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3919 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3920 self.assertEqual(rx[IP].dst, "239.1.1.1")
3921 self.assertEqual(rx[VXLAN].vni, 88)
3922 self.assertTrue(rx[VXLAN].flags.G)
3923 self.assertTrue(rx[VXLAN].flags.Instance)
3924 # policy was applied to the original IP packet
3925 self.assertEqual(rx[VXLAN].gpid, 113)
3926 self.assertTrue(rx[VXLAN].gpflags.A)
3927 self.assertFalse(rx[VXLAN].gpflags.D)
3929 inner = rx[VXLAN].payload
3931 self.assertTrue(inner.haslayer(ARP))
3934 # remote to external
3936 p = (Ether(src=self.pg7.remote_mac,
3937 dst=self.pg7.local_mac) /
3938 IP(src=self.pg7.remote_ip4,
3939 dst=self.pg7.local_ip4) /
3940 UDP(sport=1234, dport=48879) /
3941 VXLAN(vni=444, gpid=113, flags=0x88) /
3942 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
3943 IP(src="10.0.0.101", dst="10.0.0.1") /
3944 UDP(sport=1234, dport=1234) /
3947 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
3950 # local EP pings router
3952 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3954 IP(src=eep1.ip4.address, dst="10.0.0.128") /
3955 ICMP(type='echo-request'))
3957 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
3960 self.assertEqual(rx[Ether].src, str(self.router_mac))
3961 self.assertEqual(rx[Ether].dst, eep1.mac)
3962 self.assertEqual(rx[Dot1Q].vlan, 100)
3965 # local EP pings other local EP
3967 p = (Ether(src=eep1.mac, dst=eep2.mac) /
3969 IP(src=eep1.ip4.address, dst=eep2.ip4.address) /
3970 ICMP(type='echo-request'))
3972 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
3975 self.assertEqual(rx[Ether].src, eep1.mac)
3976 self.assertEqual(rx[Ether].dst, eep2.mac)
3977 self.assertEqual(rx[Dot1Q].vlan, 101)
3980 # local EP pings router w/o vlan tag poped
3982 p = (Ether(src=eep3.mac, dst=str(self.router_mac)) /
3984 IP(src=eep3.ip4.address, dst="10.0.0.128") /
3985 ICMP(type='echo-request'))
3987 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
3990 self.assertEqual(rx[Ether].src, str(self.router_mac))
3991 self.assertEqual(rx[Ether].dst, self.vlan_102.remote_mac)
3994 # A ip4 subnet reachable through the external EP1
3996 ip_220 = VppIpRoute(self, "10.220.0.0", 24,
3997 [VppRoutePath(eep1.ip4.address,
3998 eep1.epg.bvi.sw_if_index)],
3999 table_id=t4.table_id)
4000 ip_220.add_vpp_config()
4002 l3o_220 = VppGbpSubnet(
4003 self, rd1, "10.220.0.0", 24,
4004 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
4006 l3o_220.add_vpp_config()
4009 # An ip6 subnet reachable through the external EP1
4011 ip6_220 = VppIpRoute(self, "10:220::", 64,
4012 [VppRoutePath(eep1.ip6.address,
4013 eep1.epg.bvi.sw_if_index)],
4014 table_id=t6.table_id)
4015 ip6_220.add_vpp_config()
4017 l3o6_220 = VppGbpSubnet(
4018 self, rd1, "10:220::", 64,
4019 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
4021 l3o6_220.add_vpp_config()
4024 # A subnet reachable through the external EP2
4026 ip_221 = VppIpRoute(self, "10.221.0.0", 24,
4027 [VppRoutePath(eep2.ip4.address,
4028 eep2.epg.bvi.sw_if_index)],
4029 table_id=t4.table_id)
4030 ip_221.add_vpp_config()
4032 l3o_221 = VppGbpSubnet(
4033 self, rd1, "10.221.0.0", 24,
4034 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
4036 l3o_221.add_vpp_config()
4039 # ping between hosts in remote subnets
4040 # dropped without a contract
4042 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
4044 IP(src="10.220.0.1", dst="10.221.0.1") /
4045 ICMP(type='echo-request'))
4047 self.send_and_assert_no_replies(self.pg0, p * 1)
4050 # contract for the external nets to communicate
4052 acl = VppGbpAcl(self)
4053 rule4 = acl.create_rule(permit_deny=1, proto=17)
4054 rule6 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
4055 acl_index = acl.add_vpp_config([rule4, rule6])
4058 # A contract with the wrong scope is not matched
4060 c_44 = VppGbpContract(
4061 self, 44, 4220, 4221, acl_index,
4062 [VppGbpContractRule(
4063 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4066 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4068 [ETH_P_IP, ETH_P_IPV6])
4069 c_44.add_vpp_config()
4070 self.send_and_assert_no_replies(self.pg0, p * 1)
4072 c1 = VppGbpContract(
4073 self, 55, 4220, 4221, acl_index,
4074 [VppGbpContractRule(
4075 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4076 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4079 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4080 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4082 [ETH_P_IP, ETH_P_IPV6])
4086 # Contracts allowing ext-net 200 to talk with external EPs
4088 c2 = VppGbpContract(
4089 self, 55, 4220, 113, acl_index,
4090 [VppGbpContractRule(
4091 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4092 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4095 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4096 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4098 [ETH_P_IP, ETH_P_IPV6])
4100 c3 = VppGbpContract(
4101 self, 55, 113, 4220, acl_index,
4102 [VppGbpContractRule(
4103 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4104 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4107 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4108 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4110 [ETH_P_IP, ETH_P_IPV6])
4114 # ping between hosts in remote subnets
4116 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
4118 IP(src="10.220.0.1", dst="10.221.0.1") /
4119 UDP(sport=1234, dport=1234) /
4122 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
4125 self.assertEqual(rx[Ether].src, str(self.router_mac))
4126 self.assertEqual(rx[Ether].dst, eep2.mac)
4127 self.assertEqual(rx[Dot1Q].vlan, 101)
4129 # we did not learn these external hosts
4130 self.assertFalse(find_gbp_endpoint(self, ip="10.220.0.1"))
4131 self.assertFalse(find_gbp_endpoint(self, ip="10.221.0.1"))
4134 # from remote external EP to local external EP
4136 p = (Ether(src=self.pg7.remote_mac,
4137 dst=self.pg7.local_mac) /
4138 IP(src=self.pg7.remote_ip4,
4139 dst=self.pg7.local_ip4) /
4140 UDP(sport=1234, dport=48879) /
4141 VXLAN(vni=444, gpid=113, flags=0x88) /
4142 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
4143 IP(src="10.0.0.101", dst="10.220.0.1") /
4144 UDP(sport=1234, dport=1234) /
4147 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
4150 # ping from an external host to the remote external EP
4152 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
4154 IP(src="10.220.0.1", dst=rep.ip4.address) /
4155 UDP(sport=1234, dport=1234) /
4158 rxs = self.send_and_expect(self.pg0, p * 1, self.pg7)
4161 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4162 # self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4163 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4164 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4165 self.assertEqual(rx[VXLAN].vni, 444)
4166 self.assertTrue(rx[VXLAN].flags.G)
4167 self.assertTrue(rx[VXLAN].flags.Instance)
4168 # the sclass of the ext-net the packet came from
4169 self.assertEqual(rx[VXLAN].gpid, 4220)
4170 # policy was applied to the original IP packet
4171 self.assertTrue(rx[VXLAN].gpflags.A)
4172 # since it's an external host the reciever should not learn it
4173 self.assertTrue(rx[VXLAN].gpflags.D)
4174 inner = rx[VXLAN].payload
4175 self.assertEqual(inner[IP].src, "10.220.0.1")
4176 self.assertEqual(inner[IP].dst, rep.ip4.address)
4179 # An external subnet reachable via the remote external EP
4183 # first the VXLAN-GBP tunnel over which it is reached
4185 vx_tun_r1 = VppVxlanGbpTunnel(
4186 self, self.pg7.local_ip4,
4187 self.pg7.remote_ip4, 445,
4188 mode=(VppEnum.vl_api_vxlan_gbp_api_tunnel_mode_t.
4189 VXLAN_GBP_API_TUNNEL_MODE_L3))
4190 vx_tun_r1.add_vpp_config()
4191 VppIpInterfaceBind(self, vx_tun_r1, t4).add_vpp_config()
4193 self.logger.info(self.vapi.cli("sh vxlan-gbp tunnel"))
4196 # then the special adj to resolve through on that tunnel
4198 n1 = VppNeighbor(self,
4199 vx_tun_r1.sw_if_index,
4200 "00:0c:0c:0c:0c:0c",
4201 self.pg7.remote_ip4)
4205 # the route via the adj above
4207 ip_222 = VppIpRoute(self, "10.222.0.0", 24,
4208 [VppRoutePath(self.pg7.remote_ip4,
4209 vx_tun_r1.sw_if_index)],
4210 table_id=t4.table_id)
4211 ip_222.add_vpp_config()
4213 l3o_222 = VppGbpSubnet(
4214 self, rd1, "10.222.0.0", 24,
4215 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
4217 l3o_222.add_vpp_config()
4220 # ping between hosts in local and remote external subnets
4221 # dropped without a contract
4223 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
4225 IP(src="10.220.0.1", dst="10.222.0.1") /
4226 UDP(sport=1234, dport=1234) /
4229 rxs = self.send_and_assert_no_replies(self.pg0, p * 1)
4232 # Add contracts ext-nets for 220 -> 222
4234 c4 = VppGbpContract(
4235 self, 55, 4220, 4222, acl_index,
4236 [VppGbpContractRule(
4237 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4238 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4241 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4242 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4244 [ETH_P_IP, ETH_P_IPV6])
4248 # ping from host in local to remote external subnets
4250 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
4252 IP(src="10.220.0.1", dst="10.222.0.1") /
4253 UDP(sport=1234, dport=1234) /
4256 rxs = self.send_and_expect(self.pg0, p * 3, self.pg7)
4259 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4260 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4261 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4262 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4263 self.assertEqual(rx[VXLAN].vni, 445)
4264 self.assertTrue(rx[VXLAN].flags.G)
4265 self.assertTrue(rx[VXLAN].flags.Instance)
4266 # the sclass of the ext-net the packet came from
4267 self.assertEqual(rx[VXLAN].gpid, 4220)
4268 # policy was applied to the original IP packet
4269 self.assertTrue(rx[VXLAN].gpflags.A)
4270 # since it's an external host the reciever should not learn it
4271 self.assertTrue(rx[VXLAN].gpflags.D)
4272 inner = rx[VXLAN].payload
4273 self.assertEqual(inner[Ether].dst, "00:0c:0c:0c:0c:0c")
4274 self.assertEqual(inner[IP].src, "10.220.0.1")
4275 self.assertEqual(inner[IP].dst, "10.222.0.1")
4278 # make the external subnet ECMP
4280 vx_tun_r2 = VppVxlanGbpTunnel(
4281 self, self.pg7.local_ip4,
4282 self.pg7.remote_ip4, 446,
4283 mode=(VppEnum.vl_api_vxlan_gbp_api_tunnel_mode_t.
4284 VXLAN_GBP_API_TUNNEL_MODE_L3))
4285 vx_tun_r2.add_vpp_config()
4286 VppIpInterfaceBind(self, vx_tun_r2, t4).add_vpp_config()
4288 self.logger.info(self.vapi.cli("sh vxlan-gbp tunnel"))
4290 n2 = VppNeighbor(self,
4291 vx_tun_r2.sw_if_index,
4292 "00:0c:0c:0c:0c:0c",
4293 self.pg7.remote_ip4)
4296 ip_222.modify([VppRoutePath(self.pg7.remote_ip4,
4297 vx_tun_r1.sw_if_index),
4298 VppRoutePath(self.pg7.remote_ip4,
4299 vx_tun_r2.sw_if_index)])
4302 # now expect load-balance
4304 p = [(Ether(src=eep1.mac, dst=str(self.router_mac)) /
4306 IP(src="10.220.0.1", dst="10.222.0.1") /
4307 UDP(sport=1234, dport=1234) /
4309 (Ether(src=eep1.mac, dst=str(self.router_mac)) /
4311 IP(src="10.220.0.1", dst="10.222.0.1") /
4312 UDP(sport=1222, dport=1235) /
4315 rxs = self.send_and_expect(self.pg0, p, self.pg7)
4317 self.assertEqual(rxs[0][VXLAN].vni, 445)
4318 self.assertEqual(rxs[1][VXLAN].vni, 446)
4321 # Same LB test for v6
4323 n3 = VppNeighbor(self,
4324 vx_tun_r1.sw_if_index,
4325 "00:0c:0c:0c:0c:0c",
4326 self.pg7.remote_ip6)
4328 n4 = VppNeighbor(self,
4329 vx_tun_r2.sw_if_index,
4330 "00:0c:0c:0c:0c:0c",
4331 self.pg7.remote_ip6)
4334 ip_222_6 = VppIpRoute(self, "10:222::", 64,
4335 [VppRoutePath(self.pg7.remote_ip6,
4336 vx_tun_r1.sw_if_index),
4337 VppRoutePath(self.pg7.remote_ip6,
4338 vx_tun_r2.sw_if_index)],
4339 table_id=t6.table_id)
4340 ip_222_6.add_vpp_config()
4342 l3o_222_6 = VppGbpSubnet(
4343 self, rd1, "10:222::", 64,
4344 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
4346 l3o_222_6.add_vpp_config()
4348 p = [(Ether(src=eep1.mac, dst=str(self.router_mac)) /
4350 IPv6(src="10:220::1", dst="10:222::1") /
4351 UDP(sport=1234, dport=1234) /
4353 (Ether(src=eep1.mac, dst=str(self.router_mac)) /
4355 IPv6(src="10:220::1", dst="10:222::1") /
4356 UDP(sport=7777, dport=8881) /
4359 self.logger.info(self.vapi.cli("sh ip6 fib 10:222::1"))
4360 rxs = self.send_and_expect(self.pg0, p, self.pg7)
4362 self.assertEqual(rxs[0][VXLAN].vni, 445)
4363 self.assertEqual(rxs[1][VXLAN].vni, 446)
4366 # ping from host in remote to local external subnets
4367 # there's no contract for this, but the A bit is set.
4369 p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
4370 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
4371 UDP(sport=1234, dport=48879) /
4372 VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
4373 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
4374 IP(src="10.222.0.1", dst="10.220.0.1") /
4375 UDP(sport=1234, dport=1234) /
4378 rxs = self.send_and_expect(self.pg7, p * 3, self.pg0)
4379 self.assertFalse(find_gbp_endpoint(self, ip="10.222.0.1"))
4382 # ping from host in remote to remote external subnets
4383 # this is dropped by reflection check.
4385 p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
4386 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
4387 UDP(sport=1234, dport=48879) /
4388 VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
4389 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
4390 IP(src="10.222.0.1", dst="10.222.0.2") /
4391 UDP(sport=1234, dport=1234) /
4394 rxs = self.send_and_assert_no_replies(self.pg7, p * 3)
4396 p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
4397 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
4398 UDP(sport=1234, dport=48879) /
4399 VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
4400 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
4401 IPv6(src="10:222::1", dst="10:222::2") /
4402 UDP(sport=1234, dport=1234) /
4405 rxs = self.send_and_assert_no_replies(self.pg7, p * 3)
4410 lep1 = VppGbpEndpoint(self, vlan_144,
4412 "10.0.0.44", "11.0.0.44",
4413 "2001:10::44", "3001::44")
4414 lep1.add_vpp_config()
4417 # local EP to local ip4 external subnet
4419 p = (Ether(src=lep1.mac, dst=str(self.router_mac)) /
4421 IP(src=lep1.ip4.address, dst="10.220.0.1") /
4422 UDP(sport=1234, dport=1234) /
4425 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
4428 self.assertEqual(rx[Ether].src, str(self.router_mac))
4429 self.assertEqual(rx[Ether].dst, eep1.mac)
4430 self.assertEqual(rx[Dot1Q].vlan, 100)
4433 # local EP to local ip6 external subnet
4435 p = (Ether(src=lep1.mac, dst=str(self.router_mac)) /
4437 IPv6(src=lep1.ip6.address, dst="10:220::1") /
4438 UDP(sport=1234, dport=1234) /
4441 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
4444 self.assertEqual(rx[Ether].src, str(self.router_mac))
4445 self.assertEqual(rx[Ether].dst, eep1.mac)
4446 self.assertEqual(rx[Dot1Q].vlan, 100)
4449 # ip4 and ip6 subnets that load-balance
4451 ip_20 = VppIpRoute(self, "10.20.0.0", 24,
4452 [VppRoutePath(eep1.ip4.address,
4453 eep1.epg.bvi.sw_if_index),
4454 VppRoutePath(eep2.ip4.address,
4455 eep2.epg.bvi.sw_if_index)],
4456 table_id=t4.table_id)
4457 ip_20.add_vpp_config()
4459 l3o_20 = VppGbpSubnet(
4460 self, rd1, "10.20.0.0", 24,
4461 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
4463 l3o_20.add_vpp_config()
4465 ip6_20 = VppIpRoute(self, "10:20::", 64,
4466 [VppRoutePath(eep1.ip6.address,
4467 eep1.epg.bvi.sw_if_index),
4468 VppRoutePath(eep2.ip6.address,
4469 eep2.epg.bvi.sw_if_index)],
4470 table_id=t6.table_id)
4471 ip6_20.add_vpp_config()
4473 l3o6_20 = VppGbpSubnet(
4474 self, rd1, "10:20::", 64,
4475 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
4477 l3o6_20.add_vpp_config()
4479 self.logger.info(self.vapi.cli("sh ip fib 10.20.0.1"))
4480 self.logger.info(self.vapi.cli("sh ip6 fib 10:20::1"))
4482 # two ip6 packets whose port are chosen so they load-balance
4483 p = [(Ether(src=lep1.mac, dst=str(self.router_mac)) /
4485 IPv6(src=lep1.ip6.address, dst="10:20::1") /
4486 UDP(sport=1234, dport=1234) /
4488 (Ether(src=lep1.mac, dst=str(self.router_mac)) /
4490 IPv6(src=lep1.ip6.address, dst="10:20::1") /
4491 UDP(sport=124, dport=1230) /
4494 rxs = self.send_and_expect(self.pg0, p, self.pg0, 2)
4496 self.assertEqual(rxs[0][Dot1Q].vlan, 101)
4497 self.assertEqual(rxs[1][Dot1Q].vlan, 100)
4499 # two ip4 packets whose port are chosen so they load-balance
4500 p = [(Ether(src=lep1.mac, dst=str(self.router_mac)) /
4502 IP(src=lep1.ip4.address, dst="10.20.0.1") /
4503 UDP(sport=1235, dport=1235) /
4505 (Ether(src=lep1.mac, dst=str(self.router_mac)) /
4507 IP(src=lep1.ip4.address, dst="10.20.0.1") /
4508 UDP(sport=124, dport=1230) /
4511 rxs = self.send_and_expect(self.pg0, p, self.pg0, 2)
4513 self.assertEqual(rxs[0][Dot1Q].vlan, 101)
4514 self.assertEqual(rxs[1][Dot1Q].vlan, 100)
4519 ip_222.remove_vpp_config()
4520 self.pg7.unconfig_ip4()
4521 self.vlan_101.set_vtr(L2_VTR_OP.L2_DISABLED)
4522 self.vlan_100.set_vtr(L2_VTR_OP.L2_DISABLED)
4524 def test_gbp_anon_l3_out(self):
4525 """ GBP Anonymous L3 Out """
4527 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
4528 self.vapi.cli("set logging class gbp level debug")
4530 routed_dst_mac = "00:0c:0c:0c:0c:0c"
4531 routed_src_mac = "00:22:bd:f8:19:ff"
4536 t4 = VppIpTable(self, 1)
4538 t6 = VppIpTable(self, 1, True)
4541 rd1 = VppGbpRouteDomain(self, 2, 55, t4, t6)
4542 rd1.add_vpp_config()
4544 self.loop0.set_mac(self.router_mac)
4547 # Bind the BVI to the RD
4549 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
4550 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
4553 # Pg7 hosts a BD's BUM
4554 # Pg1 some other l3 interface
4556 self.pg7.config_ip4()
4557 self.pg7.resolve_arp()
4560 # a GBP external bridge domains for the EPs
4562 bd1 = VppBridgeDomain(self, 1)
4563 bd1.add_vpp_config()
4564 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0, None, None)
4565 gbd1.add_vpp_config()
4568 # The Endpoint-groups in which the external endpoints exist
4570 epg_220 = VppGbpEndpointGroup(self, 220, 113, rd1, gbd1,
4574 VppGbpEndpointRetention(2))
4575 epg_220.add_vpp_config()
4577 # the BVIs have the subnet applied ...
4578 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 24)
4579 ip4_addr.add_vpp_config()
4581 # ... which is an Anonymous L3-out subnets
4582 l3o_1 = VppGbpSubnet(
4583 self, rd1, "10.0.0.0", 24,
4584 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_ANON_L3_OUT,
4586 l3o_1.add_vpp_config()
4589 # an external interface attached to the outside world and the
4592 VppL2Vtr(self, self.vlan_100, L2_VTR_OP.L2_POP_1).add_vpp_config()
4593 VppL2Vtr(self, self.vlan_101, L2_VTR_OP.L2_POP_1).add_vpp_config()
4595 ext_itf = VppGbpExtItf(self, self.loop0, bd1, rd1)
4596 ext_itf.add_vpp_config()
4599 # vlan_100 and vlan_101 are anonymous l3-out interfaces
4601 ext_itf = VppGbpExtItf(self, self.vlan_100, bd1, rd1, anon=True)
4602 ext_itf.add_vpp_config()
4603 ext_itf = VppGbpExtItf(self, self.vlan_101, bd1, rd1, anon=True)
4604 ext_itf.add_vpp_config()
4607 # an unicast vxlan-gbp for inter-RD traffic
4609 vx_tun_l3 = VppGbpVxlanTunnel(
4610 self, 444, rd1.rd_id,
4611 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
4613 vx_tun_l3.add_vpp_config()
4616 # A remote external endpoint
4618 rep = VppGbpEndpoint(self, vx_tun_l3,
4620 "10.0.0.201", "11.0.0.201",
4621 "2001:10::201", "3001::101",
4622 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
4624 self.pg7.remote_ip4,
4626 rep.add_vpp_config()
4629 # ARP packet from host in external subnet are accepted, flooded and
4630 # replied to. We expect 2 packets:
4631 # - APR request flooded over the other vlan subif
4632 # - ARP reply from BVI
4634 p_arp = (Ether(src=self.vlan_100.remote_mac,
4635 dst="ff:ff:ff:ff:ff:ff") /
4640 hwsrc=self.vlan_100.remote_mac,
4641 hwdst="ff:ff:ff:ff:ff:ff"))
4642 rxs = self.send_and_expect(self.pg0, p_arp * 1, self.pg0, n_rx=2)
4644 p_arp = (Ether(src=self.vlan_101.remote_mac,
4645 dst="ff:ff:ff:ff:ff:ff") /
4650 hwsrc=self.vlan_101.remote_mac,
4651 hwdst="ff:ff:ff:ff:ff:ff"))
4652 rxs = self.send_and_expect(self.pg0, p_arp * 1, self.pg0, n_rx=2)
4655 # remote to external
4657 p = (Ether(src=self.pg7.remote_mac,
4658 dst=self.pg7.local_mac) /
4659 IP(src=self.pg7.remote_ip4,
4660 dst=self.pg7.local_ip4) /
4661 UDP(sport=1234, dport=48879) /
4662 VXLAN(vni=vx_tun_l3.vni, gpid=epg_220.sclass, flags=0x88) /
4663 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
4664 IP(src=str(rep.ip4), dst="10.0.0.100") /
4665 UDP(sport=1234, dport=1234) /
4667 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
4670 # local EP pings router
4672 p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
4674 IP(src="10.0.0.100", dst="10.0.0.128") /
4675 ICMP(type='echo-request'))
4676 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
4679 self.assertEqual(rx[Ether].src, str(self.router_mac))
4680 self.assertEqual(rx[Ether].dst, self.vlan_100.remote_mac)
4681 self.assertEqual(rx[Dot1Q].vlan, 100)
4684 # local EP pings other local EP
4686 p = (Ether(src=self.vlan_100.remote_mac,
4687 dst=self.vlan_101.remote_mac) /
4689 IP(src="10.0.0.100", dst="10.0.0.101") /
4690 ICMP(type='echo-request'))
4691 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
4694 self.assertEqual(rx[Ether].src, self.vlan_100.remote_mac)
4695 self.assertEqual(rx[Ether].dst, self.vlan_101.remote_mac)
4696 self.assertEqual(rx[Dot1Q].vlan, 101)
4699 # A subnet reachable through an external router on vlan 100
4701 ip_220 = VppIpRoute(self, "10.220.0.0", 24,
4702 [VppRoutePath("10.0.0.100",
4703 epg_220.bvi.sw_if_index)],
4704 table_id=t4.table_id)
4705 ip_220.add_vpp_config()
4707 l3o_220 = VppGbpSubnet(
4708 self, rd1, "10.220.0.0", 24,
4709 # note: this a "regular" L3 out subnet (not connected)
4710 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
4712 l3o_220.add_vpp_config()
4715 # A subnet reachable through an external router on vlan 101
4717 ip_221 = VppIpRoute(self, "10.221.0.0", 24,
4718 [VppRoutePath("10.0.0.101",
4719 epg_220.bvi.sw_if_index)],
4720 table_id=t4.table_id)
4721 ip_221.add_vpp_config()
4723 l3o_221 = VppGbpSubnet(
4724 self, rd1, "10.221.0.0", 24,
4725 # note: this a "regular" L3 out subnet (not connected)
4726 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
4728 l3o_221.add_vpp_config()
4731 # ping between hosts in remote subnets
4732 # dropped without a contract
4734 p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
4736 IP(src="10.220.0.1", dst="10.221.0.1") /
4737 ICMP(type='echo-request'))
4739 rxs = self.send_and_assert_no_replies(self.pg0, p * 1)
4742 # contract for the external nets to communicate
4744 acl = VppGbpAcl(self)
4745 rule4 = acl.create_rule(permit_deny=1, proto=17)
4746 rule6 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
4747 acl_index = acl.add_vpp_config([rule4, rule6])
4749 c1 = VppGbpContract(
4750 self, 55, 4220, 4221, acl_index,
4751 [VppGbpContractRule(
4752 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4753 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4756 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4757 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4759 [ETH_P_IP, ETH_P_IPV6])
4763 # Contracts allowing ext-net 200 to talk with external EPs
4765 c2 = VppGbpContract(
4766 self, 55, 4220, 113, acl_index,
4767 [VppGbpContractRule(
4768 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4769 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4772 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4773 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4775 [ETH_P_IP, ETH_P_IPV6])
4777 c3 = VppGbpContract(
4778 self, 55, 113, 4220, acl_index,
4779 [VppGbpContractRule(
4780 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4781 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4784 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4785 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4787 [ETH_P_IP, ETH_P_IPV6])
4791 # ping between hosts in remote subnets
4793 p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
4795 IP(src="10.220.0.1", dst="10.221.0.1") /
4796 UDP(sport=1234, dport=1234) /
4799 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
4802 self.assertEqual(rx[Ether].src, str(self.router_mac))
4803 self.assertEqual(rx[Ether].dst, self.vlan_101.remote_mac)
4804 self.assertEqual(rx[Dot1Q].vlan, 101)
4806 # we did not learn these external hosts
4807 self.assertFalse(find_gbp_endpoint(self, ip="10.220.0.1"))
4808 self.assertFalse(find_gbp_endpoint(self, ip="10.221.0.1"))
4811 # from remote external EP to local external EP
4813 p = (Ether(src=self.pg7.remote_mac,
4814 dst=self.pg7.local_mac) /
4815 IP(src=self.pg7.remote_ip4,
4816 dst=self.pg7.local_ip4) /
4817 UDP(sport=1234, dport=48879) /
4818 VXLAN(vni=444, gpid=113, flags=0x88) /
4819 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
4820 IP(src=rep.ip4.address, dst="10.220.0.1") /
4821 UDP(sport=1234, dport=1234) /
4824 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
4827 # ping from an external host to the remote external EP
4829 p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
4831 IP(src="10.220.0.1", dst=rep.ip4.address) /
4832 UDP(sport=1234, dport=1234) /
4835 rxs = self.send_and_expect(self.pg0, p * 1, self.pg7)
4838 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4839 # self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4840 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4841 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4842 self.assertEqual(rx[VXLAN].vni, 444)
4843 self.assertTrue(rx[VXLAN].flags.G)
4844 self.assertTrue(rx[VXLAN].flags.Instance)
4845 # the sclass of the ext-net the packet came from
4846 self.assertEqual(rx[VXLAN].gpid, 4220)
4847 # policy was applied to the original IP packet
4848 self.assertTrue(rx[VXLAN].gpflags.A)
4849 # since it's an external host the reciever should not learn it
4850 self.assertTrue(rx[VXLAN].gpflags.D)
4851 inner = rx[VXLAN].payload
4852 self.assertEqual(inner[IP].src, "10.220.0.1")
4853 self.assertEqual(inner[IP].dst, rep.ip4.address)
4856 # An external subnet reachable via the remote external EP
4860 # first the VXLAN-GBP tunnel over which it is reached
4862 vx_tun_r = VppVxlanGbpTunnel(
4863 self, self.pg7.local_ip4,
4864 self.pg7.remote_ip4, 445,
4865 mode=(VppEnum.vl_api_vxlan_gbp_api_tunnel_mode_t.
4866 VXLAN_GBP_API_TUNNEL_MODE_L3))
4867 vx_tun_r.add_vpp_config()
4868 VppIpInterfaceBind(self, vx_tun_r, t4).add_vpp_config()
4870 self.logger.info(self.vapi.cli("sh vxlan-gbp tunnel"))
4873 # then the special adj to resolve through on that tunnel
4875 n1 = VppNeighbor(self,
4876 vx_tun_r.sw_if_index,
4877 "00:0c:0c:0c:0c:0c",
4878 self.pg7.remote_ip4)
4882 # the route via the adj above
4884 ip_222 = VppIpRoute(self, "10.222.0.0", 24,
4885 [VppRoutePath(self.pg7.remote_ip4,
4886 vx_tun_r.sw_if_index)],
4887 table_id=t4.table_id)
4888 ip_222.add_vpp_config()
4890 l3o_222 = VppGbpSubnet(
4891 self, rd1, "10.222.0.0", 24,
4892 # note: this a "regular" l3out subnet (not connected)
4893 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
4895 l3o_222.add_vpp_config()
4898 # ping between hosts in local and remote external subnets
4899 # dropped without a contract
4901 p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
4903 IP(src="10.220.0.1", dst="10.222.0.1") /
4904 UDP(sport=1234, dport=1234) /
4907 rxs = self.send_and_assert_no_replies(self.pg0, p * 1)
4910 # Add contracts ext-nets for 220 -> 222
4912 c4 = VppGbpContract(
4913 self, 55, 4220, 4222, acl_index,
4914 [VppGbpContractRule(
4915 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4916 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4919 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4920 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4922 [ETH_P_IP, ETH_P_IPV6])
4926 # ping from host in local to remote external subnets
4928 p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
4930 IP(src="10.220.0.1", dst="10.222.0.1") /
4931 UDP(sport=1234, dport=1234) /
4934 rxs = self.send_and_expect(self.pg0, p * 3, self.pg7)
4937 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4938 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4939 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4940 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4941 self.assertEqual(rx[VXLAN].vni, 445)
4942 self.assertTrue(rx[VXLAN].flags.G)
4943 self.assertTrue(rx[VXLAN].flags.Instance)
4944 # the sclass of the ext-net the packet came from
4945 self.assertEqual(rx[VXLAN].gpid, 4220)
4946 # policy was applied to the original IP packet
4947 self.assertTrue(rx[VXLAN].gpflags.A)
4948 # since it's an external host the reciever should not learn it
4949 self.assertTrue(rx[VXLAN].gpflags.D)
4950 inner = rx[VXLAN].payload
4951 self.assertEqual(inner[Ether].dst, "00:0c:0c:0c:0c:0c")
4952 self.assertEqual(inner[IP].src, "10.220.0.1")
4953 self.assertEqual(inner[IP].dst, "10.222.0.1")
4956 # ping from host in remote to local external subnets
4957 # there's no contract for this, but the A bit is set.
4959 p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
4960 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
4961 UDP(sport=1234, dport=48879) /
4962 VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
4963 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
4964 IP(src="10.222.0.1", dst="10.220.0.1") /
4965 UDP(sport=1234, dport=1234) /
4968 rxs = self.send_and_expect(self.pg7, p * 3, self.pg0)
4969 self.assertFalse(find_gbp_endpoint(self, ip="10.222.0.1"))
4972 # ping from host in remote to remote external subnets
4973 # this is dropped by reflection check.
4975 p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
4976 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
4977 UDP(sport=1234, dport=48879) /
4978 VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
4979 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
4980 IP(src="10.222.0.1", dst="10.222.0.2") /
4981 UDP(sport=1234, dport=1234) /
4984 rxs = self.send_and_assert_no_replies(self.pg7, p * 3)
4989 self.vlan_101.set_vtr(L2_VTR_OP.L2_DISABLED)
4990 self.vlan_100.set_vtr(L2_VTR_OP.L2_DISABLED)
4991 self.pg7.unconfig_ip4()
4994 if __name__ == '__main__':
4995 unittest.main(testRunner=VppTestRunner)