3 from socket import AF_INET, AF_INET6, inet_pton, inet_ntop
5 from ipaddress import ip_address, IPv4Network, IPv6Network
7 from scapy.packet import Raw
8 from scapy.layers.l2 import Ether, ARP, Dot1Q
9 from scapy.layers.inet import IP, UDP, ICMP
10 from scapy.layers.inet6 import IPv6, ICMPv6ND_NS, ICMPv6NDOptSrcLLAddr, \
11 ICMPv6ND_NA, ICMPv6EchoRequest
12 from scapy.utils6 import in6_getnsma, in6_getnsmac
13 from scapy.layers.vxlan import VXLAN
14 from scapy.data import ETH_P_IP, ETH_P_IPV6, ETH_P_ARP
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 DpoProto, get_dpo_proto
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,
39 tep=None, sclass=None):
43 vmac = MACAddress(mac)
45 eps = test.vapi.gbp_endpoint_dump()
51 if src != str(ep.endpoint.tun.src) or \
52 dst != str(ep.endpoint.tun.dst):
55 if ep.endpoint.sw_if_index != sw_if_index:
58 if ep.endpoint.sclass != sclass:
61 for eip in ep.endpoint.ips:
65 if vmac == ep.endpoint.mac:
71 def find_gbp_vxlan(test, vni):
72 ts = test.vapi.gbp_vxlan_tunnel_dump()
74 if t.tunnel.vni == vni:
79 class VppGbpEndpoint(VppObject):
106 return [self.ip4, self.ip6]
110 return [self.fip4, self.fip6]
112 def __init__(self, test, itf, epg, recirc, ip4, fip4, ip6, fip6,
128 self.vmac = MACAddress(self.itf.remote_mac)
130 self.vmac = MACAddress("00:00:00:00:00:00")
133 self.tun_src = tun_src
134 self.tun_dst = tun_dst
136 def add_vpp_config(self):
137 res = self._test.vapi.gbp_endpoint_add(
138 self.itf.sw_if_index,
139 [self.ip4, self.ip6],
145 self.handle = res.handle
146 self._test.registry.register(self, self._test.logger)
148 def remove_vpp_config(self):
149 self._test.vapi.gbp_endpoint_del(self.handle)
152 return "gbp-endpoint:[%d==%d:%s:%d]" % (self.handle,
153 self.itf.sw_if_index,
157 def query_vpp_config(self):
158 return find_gbp_endpoint(self._test,
159 self.itf.sw_if_index,
163 class VppGbpRecirc(VppObject):
165 GBP Recirculation Interface
168 def __init__(self, test, epg, recirc, is_ext=False):
174 def add_vpp_config(self):
175 self._test.vapi.gbp_recirc_add_del(
177 self.recirc.sw_if_index,
180 self._test.registry.register(self, self._test.logger)
182 def remove_vpp_config(self):
183 self._test.vapi.gbp_recirc_add_del(
185 self.recirc.sw_if_index,
190 return "gbp-recirc:[%d]" % (self.recirc.sw_if_index)
192 def query_vpp_config(self):
193 rs = self._test.vapi.gbp_recirc_dump()
195 if r.recirc.sw_if_index == self.recirc.sw_if_index:
200 class VppGbpExtItf(VppObject):
202 GBP ExtItfulation Interface
205 def __init__(self, test, itf, bd, rd, anon=False):
210 self.flags = 1 if anon else 0
212 def add_vpp_config(self):
213 self._test.vapi.gbp_ext_itf_add_del(
214 1, self.itf.sw_if_index, self.bd.bd_id, self.rd.rd_id, self.flags)
215 self._test.registry.register(self, self._test.logger)
217 def remove_vpp_config(self):
218 self._test.vapi.gbp_ext_itf_add_del(
219 0, self.itf.sw_if_index, self.bd.bd_id, self.rd.rd_id, self.flags)
222 return "gbp-ext-itf:[%d]%s" % (self.itf.sw_if_index,
223 " [anon]" if self.flags else "")
225 def query_vpp_config(self):
226 rs = self._test.vapi.gbp_ext_itf_dump()
228 if r.ext_itf.sw_if_index == self.itf.sw_if_index:
233 class VppGbpSubnet(VppObject):
238 def __init__(self, test, rd, address, address_len,
239 type, sw_if_index=None, sclass=None):
241 self.rd_id = rd.rd_id
242 a = ip_address(address)
244 self.prefix = IPv4Network("%s/%d" % (address, address_len),
247 self.prefix = IPv6Network("%s/%d" % (address, address_len),
250 self.sw_if_index = sw_if_index
253 def add_vpp_config(self):
254 self._test.vapi.gbp_subnet_add_del(
259 sw_if_index=self.sw_if_index if self.sw_if_index else 0xffffffff,
260 sclass=self.sclass if self.sclass else 0xffff)
261 self._test.registry.register(self, self._test.logger)
263 def remove_vpp_config(self):
264 self._test.vapi.gbp_subnet_add_del(
271 return "gbp-subnet:[%d-%s]" % (self.rd_id, self.prefix)
273 def query_vpp_config(self):
274 ss = self._test.vapi.gbp_subnet_dump()
276 if s.subnet.rd_id == self.rd_id and \
277 s.subnet.type == self.type and \
278 s.subnet.prefix == self.prefix:
283 class VppGbpEndpointRetention(object):
284 def __init__(self, remote_ep_timeout=0xffffffff):
285 self.remote_ep_timeout = remote_ep_timeout
288 return {'remote_ep_timeout': self.remote_ep_timeout}
291 class VppGbpEndpointGroup(VppObject):
296 def __init__(self, test, vnid, sclass, rd, bd, uplink,
297 bvi, bvi_ip4, bvi_ip6=None,
298 retention=VppGbpEndpointRetention()):
302 self.bvi_ip4 = bvi_ip4
303 self.bvi_ip6 = bvi_ip6
310 self.retention = retention
312 def add_vpp_config(self):
313 self._test.vapi.gbp_endpoint_group_add(
318 self.uplink.sw_if_index if self.uplink else INDEX_INVALID,
319 self.retention.encode())
320 self._test.registry.register(self, self._test.logger)
322 def remove_vpp_config(self):
323 self._test.vapi.gbp_endpoint_group_del(self.sclass)
326 return "gbp-endpoint-group:[%d]" % (self.vnid)
328 def query_vpp_config(self):
329 epgs = self._test.vapi.gbp_endpoint_group_dump()
331 if epg.epg.vnid == self.vnid:
336 class VppGbpBridgeDomain(VppObject):
341 def __init__(self, test, bd, rd, bvi, uu_fwd=None,
342 bm_flood=None, learn=True,
343 uu_drop=False, bm_drop=False,
348 self.bm_flood = bm_flood
352 e = VppEnum.vl_api_gbp_bridge_domain_flags_t
354 self.flags = e.GBP_BD_API_FLAG_NONE
356 self.flags |= e.GBP_BD_API_FLAG_DO_NOT_LEARN
358 self.flags |= e.GBP_BD_API_FLAG_UU_FWD_DROP
360 self.flags |= e.GBP_BD_API_FLAG_MCAST_DROP
362 self.flags |= e.GBP_BD_API_FLAG_UCAST_ARP
364 def add_vpp_config(self):
365 self._test.vapi.gbp_bridge_domain_add(
369 self.bvi.sw_if_index,
370 self.uu_fwd.sw_if_index if self.uu_fwd else INDEX_INVALID,
371 self.bm_flood.sw_if_index if self.bm_flood else INDEX_INVALID)
372 self._test.registry.register(self, self._test.logger)
374 def remove_vpp_config(self):
375 self._test.vapi.gbp_bridge_domain_del(self.bd.bd_id)
378 return "gbp-bridge-domain:[%d]" % (self.bd.bd_id)
380 def query_vpp_config(self):
381 bds = self._test.vapi.gbp_bridge_domain_dump()
383 if bd.bd.bd_id == self.bd.bd_id:
388 class VppGbpRouteDomain(VppObject):
393 def __init__(self, test, rd_id, scope, t4, t6, ip4_uu=None, ip6_uu=None):
402 def add_vpp_config(self):
403 self._test.vapi.gbp_route_domain_add(
408 self.ip4_uu.sw_if_index if self.ip4_uu else INDEX_INVALID,
409 self.ip6_uu.sw_if_index if self.ip6_uu else INDEX_INVALID)
410 self._test.registry.register(self, self._test.logger)
412 def remove_vpp_config(self):
413 self._test.vapi.gbp_route_domain_del(self.rd_id)
416 return "gbp-route-domain:[%d]" % (self.rd_id)
418 def query_vpp_config(self):
419 rds = self._test.vapi.gbp_route_domain_dump()
421 if rd.rd.rd_id == self.rd_id:
426 class VppGbpContractNextHop():
427 def __init__(self, mac, bd, ip, rd):
434 return {'ip': self.ip,
435 'mac': self.mac.packed,
436 'bd_id': self.bd.bd.bd_id,
437 'rd_id': self.rd.rd_id}
440 class VppGbpContractRule():
441 def __init__(self, action, hash_mode, nhs=None):
443 self.hash_mode = hash_mode
444 self.nhs = [] if nhs is None else nhs
449 nhs.append(nh.encode())
452 return {'action': self.action,
454 'hash_mode': self.hash_mode,
455 'n_nhs': len(self.nhs),
459 return '<VppGbpContractRule action=%s, hash_mode=%s>' % (
460 self.action, self.hash_mode)
463 class VppGbpContract(VppObject):
468 def __init__(self, test, scope, sclass, dclass, acl_index,
469 rules, allowed_ethertypes):
471 if not isinstance(rules, list):
472 raise ValueError("'rules' must be a list.")
473 if not isinstance(allowed_ethertypes, list):
474 raise ValueError("'allowed_ethertypes' must be a list.")
476 self.acl_index = acl_index
480 self.allowed_ethertypes = allowed_ethertypes
481 while (len(self.allowed_ethertypes) < 16):
482 self.allowed_ethertypes.append(0)
484 def add_vpp_config(self):
487 rules.append(r.encode())
488 r = self._test.vapi.gbp_contract_add_del(
491 'acl_index': self.acl_index,
493 'sclass': self.sclass,
494 'dclass': self.dclass,
495 'n_rules': len(rules),
497 'n_ether_types': len(self.allowed_ethertypes),
498 'allowed_ethertypes': self.allowed_ethertypes})
499 self.stats_index = r.stats_index
500 self._test.registry.register(self, self._test.logger)
502 def remove_vpp_config(self):
503 self._test.vapi.gbp_contract_add_del(
506 'acl_index': self.acl_index,
508 'sclass': self.sclass,
509 'dclass': self.dclass,
512 'n_ether_types': len(self.allowed_ethertypes),
513 'allowed_ethertypes': self.allowed_ethertypes})
516 return "gbp-contract:[%d:%d:%d:%d]" % (self.scope,
521 def query_vpp_config(self):
522 cs = self._test.vapi.gbp_contract_dump()
524 if c.contract.scope == self.scope \
525 and c.contract.sclass == self.sclass \
526 and c.contract.dclass == self.dclass:
530 def get_drop_stats(self):
531 c = self._test.statistics.get_counter("/net/gbp/contract/drop")
532 return c[0][self.stats_index]
534 def get_permit_stats(self):
535 c = self._test.statistics.get_counter("/net/gbp/contract/permit")
536 return c[0][self.stats_index]
539 class VppGbpVxlanTunnel(VppInterface):
544 def __init__(self, test, vni, bd_rd_id, mode, src):
545 super(VppGbpVxlanTunnel, self).__init__(test)
548 self.bd_rd_id = bd_rd_id
552 def add_vpp_config(self):
553 r = self._test.vapi.gbp_vxlan_tunnel_add(
558 self.set_sw_if_index(r.sw_if_index)
559 self._test.registry.register(self, self._test.logger)
561 def remove_vpp_config(self):
562 self._test.vapi.gbp_vxlan_tunnel_del(self.vni)
565 return "gbp-vxlan:%d" % (self.sw_if_index)
567 def query_vpp_config(self):
568 return find_gbp_vxlan(self._test, self.vni)
571 class VppGbpAcl(VppObject):
576 def __init__(self, test):
578 self.acl_index = 4294967295
580 def create_rule(self, is_ipv6=0, permit_deny=0, proto=-1,
581 s_prefix=0, s_ip=b'\x00\x00\x00\x00', sport_from=0,
582 sport_to=65535, d_prefix=0, d_ip=b'\x00\x00\x00\x00',
583 dport_from=0, dport_to=65535):
584 if proto == -1 or proto == 0:
587 elif proto == 1 or proto == 58:
590 rule = ({'is_permit': permit_deny, 'is_ipv6': is_ipv6, 'proto': proto,
591 'srcport_or_icmptype_first': sport_from,
592 'srcport_or_icmptype_last': sport_to,
593 'src_ip_prefix_len': s_prefix,
595 'dstport_or_icmpcode_first': dport_from,
596 'dstport_or_icmpcode_last': dport_to,
597 'dst_ip_prefix_len': d_prefix,
598 'dst_ip_addr': d_ip})
601 def add_vpp_config(self, rules):
603 reply = self._test.vapi.acl_add_replace(acl_index=self.acl_index,
606 self.acl_index = reply.acl_index
607 return self.acl_index
609 def remove_vpp_config(self):
610 self._test.vapi.acl_del(self.acl_index)
613 return "gbp-acl:[%d]" % (self.acl_index)
615 def query_vpp_config(self):
616 cs = self._test.vapi.acl_dump()
618 if c.acl_index == self.acl_index:
623 class TestGBP(VppTestCase):
624 """ GBP Test Case """
627 def config_flags(self):
628 return VppEnum.vl_api_nat_config_flags_t
632 super(TestGBP, cls).setUpClass()
635 def tearDownClass(cls):
636 super(TestGBP, cls).tearDownClass()
639 super(TestGBP, self).setUp()
641 self.create_pg_interfaces(range(9))
642 self.create_loopback_interfaces(8)
644 self.router_mac = MACAddress("00:11:22:33:44:55")
646 for i in self.pg_interfaces:
648 for i in self.lo_interfaces:
651 self.vlan_100 = VppDot1QSubint(self, self.pg0, 100)
652 self.vlan_100.admin_up()
653 self.vlan_101 = VppDot1QSubint(self, self.pg0, 101)
654 self.vlan_101.admin_up()
655 self.vlan_102 = VppDot1QSubint(self, self.pg0, 102)
656 self.vlan_102.admin_up()
659 for i in self.pg_interfaces:
661 super(TestGBP, self).tearDown()
662 for i in self.lo_interfaces:
663 i.remove_vpp_config()
664 self.lo_interfaces = []
665 self.vlan_102.remove_vpp_config()
666 self.vlan_101.remove_vpp_config()
667 self.vlan_100.remove_vpp_config()
669 def send_and_expect_bridged(self, src, tx, dst):
670 rx = self.send_and_expect(src, tx, dst)
673 self.assertEqual(r[Ether].src, tx[0][Ether].src)
674 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
675 self.assertEqual(r[IP].src, tx[0][IP].src)
676 self.assertEqual(r[IP].dst, tx[0][IP].dst)
679 def send_and_expect_bridged6(self, src, tx, dst):
680 rx = self.send_and_expect(src, tx, dst)
683 self.assertEqual(r[Ether].src, tx[0][Ether].src)
684 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
685 self.assertEqual(r[IPv6].src, tx[0][IPv6].src)
686 self.assertEqual(r[IPv6].dst, tx[0][IPv6].dst)
689 def send_and_expect_routed(self, src, tx, dst, src_mac):
690 rx = self.send_and_expect(src, tx, dst)
693 self.assertEqual(r[Ether].src, src_mac)
694 self.assertEqual(r[Ether].dst, dst.remote_mac)
695 self.assertEqual(r[IP].src, tx[0][IP].src)
696 self.assertEqual(r[IP].dst, tx[0][IP].dst)
699 def send_and_expect_routed6(self, src, tx, dst, src_mac):
700 rx = self.send_and_expect(src, tx, dst)
703 self.assertEqual(r[Ether].src, src_mac)
704 self.assertEqual(r[Ether].dst, dst.remote_mac)
705 self.assertEqual(r[IPv6].src, tx[0][IPv6].src)
706 self.assertEqual(r[IPv6].dst, tx[0][IPv6].dst)
709 def send_and_expect_natted(self, src, tx, dst, src_ip):
710 rx = self.send_and_expect(src, tx, dst)
713 self.assertEqual(r[Ether].src, tx[0][Ether].src)
714 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
715 self.assertEqual(r[IP].src, src_ip)
716 self.assertEqual(r[IP].dst, tx[0][IP].dst)
719 def send_and_expect_natted6(self, src, tx, dst, src_ip):
720 rx = self.send_and_expect(src, tx, dst)
723 self.assertEqual(r[Ether].src, tx[0][Ether].src)
724 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
725 self.assertEqual(r[IPv6].src, src_ip)
726 self.assertEqual(r[IPv6].dst, tx[0][IPv6].dst)
729 def send_and_expect_unnatted(self, src, tx, dst, dst_ip):
730 rx = self.send_and_expect(src, tx, dst)
733 self.assertEqual(r[Ether].src, tx[0][Ether].src)
734 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
735 self.assertEqual(r[IP].dst, dst_ip)
736 self.assertEqual(r[IP].src, tx[0][IP].src)
739 def send_and_expect_unnatted6(self, src, tx, dst, dst_ip):
740 rx = self.send_and_expect(src, tx, dst)
743 self.assertEqual(r[Ether].src, tx[0][Ether].src)
744 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
745 self.assertEqual(r[IPv6].dst, dst_ip)
746 self.assertEqual(r[IPv6].src, tx[0][IPv6].src)
749 def send_and_expect_double_natted(self, src, tx, dst, src_ip, dst_ip):
750 rx = self.send_and_expect(src, tx, dst)
753 self.assertEqual(r[Ether].src, str(self.router_mac))
754 self.assertEqual(r[Ether].dst, dst.remote_mac)
755 self.assertEqual(r[IP].dst, dst_ip)
756 self.assertEqual(r[IP].src, src_ip)
759 def send_and_expect_double_natted6(self, src, tx, dst, src_ip, dst_ip):
760 rx = self.send_and_expect(src, tx, dst)
763 self.assertEqual(r[Ether].src, str(self.router_mac))
764 self.assertEqual(r[Ether].dst, dst.remote_mac)
765 self.assertEqual(r[IPv6].dst, dst_ip)
766 self.assertEqual(r[IPv6].src, src_ip)
769 def send_and_expect_no_arp(self, src, tx, dst):
770 self.pg_send(src, tx)
771 dst.get_capture(0, timeout=1)
772 dst.assert_nothing_captured(remark="")
775 def send_and_expect_arp(self, src, tx, dst):
776 rx = self.send_and_expect(src, tx, dst)
779 self.assertEqual(r[Ether].src, tx[0][Ether].src)
780 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
781 self.assertEqual(r[ARP].psrc, tx[0][ARP].psrc)
782 self.assertEqual(r[ARP].pdst, tx[0][ARP].pdst)
783 self.assertEqual(r[ARP].hwsrc, tx[0][ARP].hwsrc)
784 self.assertEqual(r[ARP].hwdst, tx[0][ARP].hwdst)
788 """ Group Based Policy """
790 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
795 gt4 = VppIpTable(self, 0)
797 gt6 = VppIpTable(self, 0, is_ip6=True)
799 nt4 = VppIpTable(self, 20)
801 nt6 = VppIpTable(self, 20, is_ip6=True)
804 rd0 = VppGbpRouteDomain(self, 0, 400, gt4, gt6, None, None)
805 rd20 = VppGbpRouteDomain(self, 20, 420, nt4, nt6, None, None)
808 rd20.add_vpp_config()
813 bd1 = VppBridgeDomain(self, 1)
814 bd2 = VppBridgeDomain(self, 2)
815 bd20 = VppBridgeDomain(self, 20)
819 bd20.add_vpp_config()
821 gbd1 = VppGbpBridgeDomain(self, bd1, rd0, self.loop0)
822 gbd2 = VppGbpBridgeDomain(self, bd2, rd0, self.loop1)
823 gbd20 = VppGbpBridgeDomain(self, bd20, rd20, self.loop2)
825 gbd1.add_vpp_config()
826 gbd2.add_vpp_config()
827 gbd20.add_vpp_config()
830 # 3 EPGs, 2 of which share a BD.
831 # 2 NAT EPGs, one for floating-IP subnets, the other for internet
833 epgs = [VppGbpEndpointGroup(self, 220, 1220, rd0, gbd1,
834 self.pg4, self.loop0,
835 "10.0.0.128", "2001:10::128"),
836 VppGbpEndpointGroup(self, 221, 1221, rd0, gbd1,
837 self.pg5, self.loop0,
838 "10.0.1.128", "2001:10:1::128"),
839 VppGbpEndpointGroup(self, 222, 1222, rd0, gbd2,
840 self.pg6, self.loop1,
841 "10.0.2.128", "2001:10:2::128"),
842 VppGbpEndpointGroup(self, 333, 1333, rd20, gbd20,
843 self.pg7, self.loop2,
844 "11.0.0.128", "3001::128"),
845 VppGbpEndpointGroup(self, 444, 1444, rd20, gbd20,
846 self.pg8, self.loop2,
847 "11.0.0.129", "3001::129")]
848 recircs = [VppGbpRecirc(self, epgs[0], self.loop3),
849 VppGbpRecirc(self, epgs[1], self.loop4),
850 VppGbpRecirc(self, epgs[2], self.loop5),
851 VppGbpRecirc(self, epgs[3], self.loop6, is_ext=True),
852 VppGbpRecirc(self, epgs[4], self.loop7, is_ext=True)]
855 recirc_nat = recircs[3]
858 # 4 end-points, 2 in the same subnet, 3 in the same BD
860 eps = [VppGbpEndpoint(self, self.pg0,
862 "10.0.0.1", "11.0.0.1",
863 "2001:10::1", "3001::1"),
864 VppGbpEndpoint(self, self.pg1,
866 "10.0.0.2", "11.0.0.2",
867 "2001:10::2", "3001::2"),
868 VppGbpEndpoint(self, self.pg2,
870 "10.0.1.1", "11.0.0.3",
871 "2001:10:1::1", "3001::3"),
872 VppGbpEndpoint(self, self.pg3,
874 "10.0.2.1", "11.0.0.4",
875 "2001:10:2::1", "3001::4")]
878 # Config related to each of the EPGs
881 # IP config on the BVI interfaces
882 if epg != epgs[1] and epg != epgs[4]:
883 VppIpInterfaceBind(self, epg.bvi, epg.rd.t4).add_vpp_config()
884 VppIpInterfaceBind(self, epg.bvi, epg.rd.t6).add_vpp_config()
885 epg.bvi.set_mac(self.router_mac)
887 # The BVIs are NAT inside interfaces
888 flags = self.config_flags.NAT_IS_INSIDE
889 self.vapi.nat44_interface_add_del_feature(
890 sw_if_index=epg.bvi.sw_if_index,
891 flags=flags, is_add=1)
892 self.vapi.nat66_add_del_interface(
893 is_add=1, flags=flags,
894 sw_if_index=epg.bvi.sw_if_index)
896 if_ip4 = VppIpInterfaceAddress(self, epg.bvi, epg.bvi_ip4, 32)
897 if_ip6 = VppIpInterfaceAddress(self, epg.bvi, epg.bvi_ip6, 128)
898 if_ip4.add_vpp_config()
899 if_ip6.add_vpp_config()
901 # EPG uplink interfaces in the RD
902 VppIpInterfaceBind(self, epg.uplink, epg.rd.t4).add_vpp_config()
903 VppIpInterfaceBind(self, epg.uplink, epg.rd.t6).add_vpp_config()
905 # add the BD ARP termination entry for BVI IP
906 epg.bd_arp_ip4 = VppBridgeDomainArpEntry(self, epg.bd.bd,
907 str(self.router_mac),
909 epg.bd_arp_ip6 = VppBridgeDomainArpEntry(self, epg.bd.bd,
910 str(self.router_mac),
912 epg.bd_arp_ip4.add_vpp_config()
913 epg.bd_arp_ip6.add_vpp_config()
918 for recirc in recircs:
919 # EPG's ingress recirculation interface maps to its RD
920 VppIpInterfaceBind(self, recirc.recirc,
921 recirc.epg.rd.t4).add_vpp_config()
922 VppIpInterfaceBind(self, recirc.recirc,
923 recirc.epg.rd.t6).add_vpp_config()
925 self.vapi.nat44_interface_add_del_feature(
926 sw_if_index=recirc.recirc.sw_if_index, is_add=1)
927 self.vapi.nat66_add_del_interface(
929 sw_if_index=recirc.recirc.sw_if_index)
931 recirc.add_vpp_config()
933 for recirc in recircs:
934 self.assertTrue(find_bridge_domain_port(self,
935 recirc.epg.bd.bd.bd_id,
936 recirc.recirc.sw_if_index))
939 self.pg_enable_capture(self.pg_interfaces)
942 # routes to the endpoints. We need these since there are no
943 # adj-fibs due to the fact the the BVI address has /32 and
944 # the subnet is not attached.
946 for (ip, fip) in zip(ep.ips, ep.fips):
947 # Add static mappings for each EP from the 10/8 to 11/8 network
948 if ip_address(ip).version == 4:
949 flags = self.config_flags.NAT_IS_ADDR_ONLY
950 self.vapi.nat44_add_del_static_mapping(
953 external_ip_address=fip,
954 external_sw_if_index=0xFFFFFFFF,
958 self.vapi.nat66_add_del_static_mapping(
960 external_ip_address=fip,
966 self.logger.info(self.vapi.cli("sh gbp endpoint"))
968 # ... results in a Gratuitous ARP/ND on the EPG's uplink
969 rx = ep.epg.uplink.get_capture(len(ep.ips), timeout=0.2)
971 for ii, ip in enumerate(ep.ips):
974 if ip_address(ip).version == 6:
975 self.assertTrue(p.haslayer(ICMPv6ND_NA))
976 self.assertEqual(p[ICMPv6ND_NA].tgt, ip)
978 self.assertTrue(p.haslayer(ARP))
979 self.assertEqual(p[ARP].psrc, ip)
980 self.assertEqual(p[ARP].pdst, ip)
982 # add the BD ARP termination entry for floating IP
984 ba = VppBridgeDomainArpEntry(self, epg_nat.bd.bd, ep.mac,
988 # floating IPs route via EPG recirc
990 self, fip, ip_address(fip).max_prefixlen,
992 ep.recirc.recirc.sw_if_index,
993 type=FibPathType.FIB_PATH_TYPE_DVR,
994 proto=get_dpo_proto(fip))],
998 # L2 FIB entries in the NAT EPG BD to bridge the packets from
999 # the outside direct to the internal EPG
1000 lf = VppL2FibEntry(self, epg_nat.bd.bd, ep.mac,
1001 ep.recirc.recirc, bvi_mac=0)
1005 # ARP packets for unknown IP are sent to the EPG uplink
1007 pkt_arp = (Ether(dst="ff:ff:ff:ff:ff:ff",
1008 src=self.pg0.remote_mac) /
1010 hwdst="ff:ff:ff:ff:ff:ff",
1011 hwsrc=self.pg0.remote_mac,
1015 self.vapi.cli("clear trace")
1016 self.pg0.add_stream(pkt_arp)
1018 self.pg_enable_capture(self.pg_interfaces)
1021 rxd = epgs[0].uplink.get_capture(1)
1024 # ARP/ND packets get a response
1026 pkt_arp = (Ether(dst="ff:ff:ff:ff:ff:ff",
1027 src=self.pg0.remote_mac) /
1029 hwdst="ff:ff:ff:ff:ff:ff",
1030 hwsrc=self.pg0.remote_mac,
1031 pdst=epgs[0].bvi_ip4,
1034 self.send_and_expect(self.pg0, [pkt_arp], self.pg0)
1036 nsma = in6_getnsma(inet_pton(AF_INET6, eps[0].ip6))
1037 d = inet_ntop(AF_INET6, nsma)
1038 pkt_nd = (Ether(dst=in6_getnsmac(nsma),
1039 src=self.pg0.remote_mac) /
1040 IPv6(dst=d, src=eps[0].ip6) /
1041 ICMPv6ND_NS(tgt=epgs[0].bvi_ip6) /
1042 ICMPv6NDOptSrcLLAddr(lladdr=self.pg0.remote_mac))
1043 self.send_and_expect(self.pg0, [pkt_nd], self.pg0)
1046 # broadcast packets are flooded
1048 pkt_bcast = (Ether(dst="ff:ff:ff:ff:ff:ff",
1049 src=self.pg0.remote_mac) /
1050 IP(src=eps[0].ip4, dst="232.1.1.1") /
1051 UDP(sport=1234, dport=1234) /
1054 self.vapi.cli("clear trace")
1055 self.pg0.add_stream(pkt_bcast)
1057 self.pg_enable_capture(self.pg_interfaces)
1060 rxd = eps[1].itf.get_capture(1)
1061 self.assertEqual(rxd[0][Ether].dst, pkt_bcast[Ether].dst)
1062 rxd = epgs[0].uplink.get_capture(1)
1063 self.assertEqual(rxd[0][Ether].dst, pkt_bcast[Ether].dst)
1066 # packets to non-local L3 destinations dropped
1068 pkt_intra_epg_220_ip4 = (Ether(src=self.pg0.remote_mac,
1069 dst=str(self.router_mac)) /
1072 UDP(sport=1234, dport=1234) /
1074 pkt_inter_epg_222_ip4 = (Ether(src=self.pg0.remote_mac,
1075 dst=str(self.router_mac)) /
1078 UDP(sport=1234, dport=1234) /
1081 self.send_and_assert_no_replies(self.pg0,
1082 pkt_intra_epg_220_ip4 * NUM_PKTS)
1084 pkt_inter_epg_222_ip6 = (Ether(src=self.pg0.remote_mac,
1085 dst=str(self.router_mac)) /
1086 IPv6(src=eps[0].ip6,
1087 dst="2001:10::99") /
1088 UDP(sport=1234, dport=1234) /
1090 self.send_and_assert_no_replies(self.pg0,
1091 pkt_inter_epg_222_ip6 * NUM_PKTS)
1094 # Add the subnet routes
1097 self, rd0, "10.0.0.0", 24,
1098 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1100 self, rd0, "10.0.1.0", 24,
1101 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1103 self, rd0, "10.0.2.0", 24,
1104 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1106 self, rd0, "2001:10::1", 64,
1107 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1109 self, rd0, "2001:10:1::1", 64,
1110 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1112 self, rd0, "2001:10:2::1", 64,
1113 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1114 s41.add_vpp_config()
1115 s42.add_vpp_config()
1116 s43.add_vpp_config()
1117 s61.add_vpp_config()
1118 s62.add_vpp_config()
1119 s63.add_vpp_config()
1121 self.send_and_expect_bridged(eps[0].itf,
1122 pkt_intra_epg_220_ip4 * NUM_PKTS,
1124 self.send_and_expect_bridged(eps[0].itf,
1125 pkt_inter_epg_222_ip4 * NUM_PKTS,
1127 self.send_and_expect_bridged6(eps[0].itf,
1128 pkt_inter_epg_222_ip6 * NUM_PKTS,
1131 self.logger.info(self.vapi.cli("sh ip fib 11.0.0.2"))
1132 self.logger.info(self.vapi.cli("sh gbp endpoint-group"))
1133 self.logger.info(self.vapi.cli("sh gbp endpoint"))
1134 self.logger.info(self.vapi.cli("sh gbp recirc"))
1135 self.logger.info(self.vapi.cli("sh int"))
1136 self.logger.info(self.vapi.cli("sh int addr"))
1137 self.logger.info(self.vapi.cli("sh int feat loop6"))
1138 self.logger.info(self.vapi.cli("sh vlib graph ip4-gbp-src-classify"))
1139 self.logger.info(self.vapi.cli("sh int feat loop3"))
1140 self.logger.info(self.vapi.cli("sh int feat pg0"))
1143 # Packet destined to unknown unicast is sent on the epg uplink ...
1145 pkt_intra_epg_220_to_uplink = (Ether(src=self.pg0.remote_mac,
1146 dst="00:00:00:33:44:55") /
1149 UDP(sport=1234, dport=1234) /
1152 self.send_and_expect_bridged(eps[0].itf,
1153 pkt_intra_epg_220_to_uplink * NUM_PKTS,
1155 # ... and nowhere else
1156 self.pg1.get_capture(0, timeout=0.1)
1157 self.pg1.assert_nothing_captured(remark="Flood onto other VMS")
1159 pkt_intra_epg_221_to_uplink = (Ether(src=self.pg2.remote_mac,
1160 dst="00:00:00:33:44:66") /
1163 UDP(sport=1234, dport=1234) /
1166 self.send_and_expect_bridged(eps[2].itf,
1167 pkt_intra_epg_221_to_uplink * NUM_PKTS,
1171 # Packets from the uplink are forwarded in the absence of a contract
1173 pkt_intra_epg_220_from_uplink = (Ether(src="00:00:00:33:44:55",
1174 dst=self.pg0.remote_mac) /
1177 UDP(sport=1234, dport=1234) /
1180 self.send_and_expect_bridged(self.pg4,
1181 pkt_intra_epg_220_from_uplink * NUM_PKTS,
1185 # in the absence of policy, endpoints in the same EPG
1188 pkt_intra_epg = (Ether(src=self.pg0.remote_mac,
1189 dst=self.pg1.remote_mac) /
1192 UDP(sport=1234, dport=1234) /
1195 self.send_and_expect_bridged(self.pg0,
1196 pkt_intra_epg * NUM_PKTS,
1200 # in the absence of policy, endpoints in the different EPG
1201 # cannot communicate
1203 pkt_inter_epg_220_to_221 = (Ether(src=self.pg0.remote_mac,
1204 dst=self.pg2.remote_mac) /
1207 UDP(sport=1234, dport=1234) /
1209 pkt_inter_epg_221_to_220 = (Ether(src=self.pg2.remote_mac,
1210 dst=self.pg0.remote_mac) /
1213 UDP(sport=1234, dport=1234) /
1215 pkt_inter_epg_220_to_222 = (Ether(src=self.pg0.remote_mac,
1216 dst=str(self.router_mac)) /
1219 UDP(sport=1234, dport=1234) /
1222 self.send_and_assert_no_replies(eps[0].itf,
1223 pkt_inter_epg_220_to_221 * NUM_PKTS)
1224 self.send_and_assert_no_replies(eps[0].itf,
1225 pkt_inter_epg_220_to_222 * NUM_PKTS)
1228 # A uni-directional contract from EPG 220 -> 221
1230 acl = VppGbpAcl(self)
1231 rule = acl.create_rule(permit_deny=1, proto=17)
1232 rule2 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
1233 acl_index = acl.add_vpp_config([rule, rule2])
1234 c1 = VppGbpContract(
1235 self, 400, epgs[0].sclass, epgs[1].sclass, acl_index,
1236 [VppGbpContractRule(
1237 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1238 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1241 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1242 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1244 [ETH_P_IP, ETH_P_IPV6])
1247 self.send_and_expect_bridged(eps[0].itf,
1248 pkt_inter_epg_220_to_221 * NUM_PKTS,
1250 self.send_and_assert_no_replies(eps[0].itf,
1251 pkt_inter_epg_220_to_222 * NUM_PKTS)
1254 # contract for the return direction
1256 c2 = VppGbpContract(
1257 self, 400, epgs[1].sclass, epgs[0].sclass, acl_index,
1258 [VppGbpContractRule(
1259 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1260 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1263 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1264 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1266 [ETH_P_IP, ETH_P_IPV6])
1269 self.send_and_expect_bridged(eps[0].itf,
1270 pkt_inter_epg_220_to_221 * NUM_PKTS,
1272 self.send_and_expect_bridged(eps[2].itf,
1273 pkt_inter_epg_221_to_220 * NUM_PKTS,
1276 ds = c2.get_drop_stats()
1277 self.assertEqual(ds['packets'], 0)
1278 ps = c2.get_permit_stats()
1279 self.assertEqual(ps['packets'], NUM_PKTS)
1282 # the contract does not allow non-IP
1284 pkt_non_ip_inter_epg_220_to_221 = (Ether(src=self.pg0.remote_mac,
1285 dst=self.pg2.remote_mac) /
1287 self.send_and_assert_no_replies(eps[0].itf,
1288 pkt_non_ip_inter_epg_220_to_221 * 17)
1291 # check that inter group is still disabled for the groups
1292 # not in the contract.
1294 self.send_and_assert_no_replies(eps[0].itf,
1295 pkt_inter_epg_220_to_222 * NUM_PKTS)
1298 # A uni-directional contract from EPG 220 -> 222 'L3 routed'
1300 c3 = VppGbpContract(
1301 self, 400, epgs[0].sclass, epgs[2].sclass, acl_index,
1302 [VppGbpContractRule(
1303 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1304 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1307 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1308 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1310 [ETH_P_IP, ETH_P_IPV6])
1313 self.logger.info(self.vapi.cli("sh gbp contract"))
1315 self.send_and_expect_routed(eps[0].itf,
1316 pkt_inter_epg_220_to_222 * NUM_PKTS,
1318 str(self.router_mac))
1321 # remove both contracts, traffic stops in both directions
1323 c2.remove_vpp_config()
1324 c1.remove_vpp_config()
1325 c3.remove_vpp_config()
1326 acl.remove_vpp_config()
1328 self.send_and_assert_no_replies(eps[2].itf,
1329 pkt_inter_epg_221_to_220 * NUM_PKTS)
1330 self.send_and_assert_no_replies(eps[0].itf,
1331 pkt_inter_epg_220_to_221 * NUM_PKTS)
1332 self.send_and_expect_bridged(eps[0].itf,
1333 pkt_intra_epg * NUM_PKTS,
1337 # EPs to the outside world
1340 # in the EP's RD an external subnet via the NAT EPG's recirc
1342 self, rd0, "0.0.0.0", 0,
1343 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1344 sw_if_index=recirc_nat.recirc.sw_if_index,
1345 sclass=epg_nat.sclass)
1347 self, rd0, "11.0.0.0", 8,
1348 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1349 sw_if_index=recirc_nat.recirc.sw_if_index,
1350 sclass=epg_nat.sclass)
1351 se16 = VppGbpSubnet(
1353 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1354 sw_if_index=recirc_nat.recirc.sw_if_index,
1355 sclass=epg_nat.sclass)
1356 # in the NAT RD an external subnet via the NAT EPG's uplink
1358 self, rd20, "0.0.0.0", 0,
1359 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1360 sw_if_index=epg_nat.uplink.sw_if_index,
1361 sclass=epg_nat.sclass)
1362 se36 = VppGbpSubnet(
1363 self, rd20, "::", 0,
1364 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1365 sw_if_index=epg_nat.uplink.sw_if_index,
1366 sclass=epg_nat.sclass)
1368 self, rd20, "11.0.0.0", 8,
1369 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1370 sw_if_index=epg_nat.uplink.sw_if_index,
1371 sclass=epg_nat.sclass)
1372 se1.add_vpp_config()
1373 se2.add_vpp_config()
1374 se16.add_vpp_config()
1375 se3.add_vpp_config()
1376 se36.add_vpp_config()
1377 se4.add_vpp_config()
1379 self.logger.info(self.vapi.cli("sh ip fib 0.0.0.0/0"))
1380 self.logger.info(self.vapi.cli("sh ip fib 11.0.0.1"))
1381 self.logger.info(self.vapi.cli("sh ip6 fib ::/0"))
1382 self.logger.info(self.vapi.cli("sh ip6 fib %s" %
1386 # From an EP to an outside address: IN2OUT
1388 pkt_inter_epg_220_to_global = (Ether(src=self.pg0.remote_mac,
1389 dst=str(self.router_mac)) /
1392 UDP(sport=1234, dport=1234) /
1396 self.send_and_assert_no_replies(eps[0].itf,
1397 pkt_inter_epg_220_to_global * NUM_PKTS)
1399 acl2 = VppGbpAcl(self)
1400 rule = acl2.create_rule(permit_deny=1, proto=17, sport_from=1234,
1401 sport_to=1234, dport_from=1234, dport_to=1234)
1402 rule2 = acl2.create_rule(is_ipv6=1, permit_deny=1, proto=17,
1403 sport_from=1234, sport_to=1234,
1404 dport_from=1234, dport_to=1234)
1406 acl_index2 = acl2.add_vpp_config([rule, rule2])
1407 c4 = VppGbpContract(
1408 self, 400, epgs[0].sclass, epgs[3].sclass, acl_index2,
1409 [VppGbpContractRule(
1410 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1411 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1414 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1415 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1417 [ETH_P_IP, ETH_P_IPV6])
1420 self.send_and_expect_natted(eps[0].itf,
1421 pkt_inter_epg_220_to_global * NUM_PKTS,
1425 pkt_inter_epg_220_to_global = (Ether(src=self.pg0.remote_mac,
1426 dst=str(self.router_mac)) /
1427 IPv6(src=eps[0].ip6,
1429 UDP(sport=1234, dport=1234) /
1432 self.send_and_expect_natted6(self.pg0,
1433 pkt_inter_epg_220_to_global * NUM_PKTS,
1438 # From a global address to an EP: OUT2IN
1440 pkt_inter_epg_220_from_global = (Ether(src=str(self.router_mac),
1441 dst=self.pg0.remote_mac) /
1444 UDP(sport=1234, dport=1234) /
1447 self.send_and_assert_no_replies(
1448 self.pg7, pkt_inter_epg_220_from_global * NUM_PKTS)
1450 c5 = VppGbpContract(
1451 self, 400, epgs[3].sclass, epgs[0].sclass, acl_index2,
1452 [VppGbpContractRule(
1453 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1454 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1457 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1458 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1460 [ETH_P_IP, ETH_P_IPV6])
1463 self.send_and_expect_unnatted(self.pg7,
1464 pkt_inter_epg_220_from_global * NUM_PKTS,
1468 pkt_inter_epg_220_from_global = (Ether(src=str(self.router_mac),
1469 dst=self.pg0.remote_mac) /
1470 IPv6(dst=eps[0].fip6,
1472 UDP(sport=1234, dport=1234) /
1475 self.send_and_expect_unnatted6(
1477 pkt_inter_epg_220_from_global * NUM_PKTS,
1482 # From a local VM to another local VM using resp. public addresses:
1485 pkt_intra_epg_220_global = (Ether(src=self.pg0.remote_mac,
1486 dst=str(self.router_mac)) /
1489 UDP(sport=1234, dport=1234) /
1492 self.send_and_expect_double_natted(eps[0].itf,
1493 pkt_intra_epg_220_global * NUM_PKTS,
1498 pkt_intra_epg_220_global = (Ether(src=self.pg0.remote_mac,
1499 dst=str(self.router_mac)) /
1500 IPv6(src=eps[0].ip6,
1502 UDP(sport=1234, dport=1234) /
1505 self.send_and_expect_double_natted6(
1507 pkt_intra_epg_220_global * NUM_PKTS,
1516 # del static mappings for each EP from the 10/8 to 11/8 network
1517 flags = self.config_flags.NAT_IS_ADDR_ONLY
1518 self.vapi.nat44_add_del_static_mapping(
1520 local_ip_address=ep.ip4,
1521 external_ip_address=ep.fip4,
1522 external_sw_if_index=0xFFFFFFFF,
1525 self.vapi.nat66_add_del_static_mapping(
1526 local_ip_address=ep.ip6,
1527 external_ip_address=ep.fip6,
1531 # IP config on the BVI interfaces
1532 if epg != epgs[0] and epg != epgs[3]:
1533 flags = self.config_flags.NAT_IS_INSIDE
1534 self.vapi.nat44_interface_add_del_feature(
1535 sw_if_index=epg.bvi.sw_if_index,
1538 self.vapi.nat66_add_del_interface(
1539 is_add=0, flags=flags,
1540 sw_if_index=epg.bvi.sw_if_index)
1542 for recirc in recircs:
1543 self.vapi.nat44_interface_add_del_feature(
1544 sw_if_index=recirc.recirc.sw_if_index,
1546 self.vapi.nat66_add_del_interface(
1548 sw_if_index=recirc.recirc.sw_if_index)
1550 def wait_for_ep_timeout(self, sw_if_index=None, ip=None, mac=None,
1551 tep=None, n_tries=100, s_time=1):
1553 if not find_gbp_endpoint(self, sw_if_index, ip, mac, tep=tep):
1555 n_tries = n_tries - 1
1557 self.assertFalse(find_gbp_endpoint(self, sw_if_index, ip, mac))
1560 def test_gbp_learn_l2(self):
1561 """ GBP L2 Endpoint Learning """
1563 drop_no_contract = self.statistics.get_err_counter(
1564 '/err/gbp-policy-port/drop-no-contract')
1565 allow_intra_class = self.statistics.get_err_counter(
1566 '/err/gbp-policy-port/allow-intra-sclass')
1568 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
1569 learnt = [{'mac': '00:00:11:11:11:01',
1571 'ip6': '2001:10::2'},
1572 {'mac': '00:00:11:11:11:02',
1574 'ip6': '2001:10::3'}]
1579 gt4 = VppIpTable(self, 1)
1580 gt4.add_vpp_config()
1581 gt6 = VppIpTable(self, 1, is_ip6=True)
1582 gt6.add_vpp_config()
1584 rd1 = VppGbpRouteDomain(self, 1, 401, gt4, gt6)
1585 rd1.add_vpp_config()
1588 # Pg2 hosts the vxlan tunnel, hosts on pg2 to act as TEPs
1589 # Pg3 hosts the IP4 UU-flood VXLAN tunnel
1590 # Pg4 hosts the IP6 UU-flood VXLAN tunnel
1592 self.pg2.config_ip4()
1593 self.pg2.resolve_arp()
1594 self.pg2.generate_remote_hosts(4)
1595 self.pg2.configure_ipv4_neighbors()
1596 self.pg3.config_ip4()
1597 self.pg3.resolve_arp()
1598 self.pg4.config_ip4()
1599 self.pg4.resolve_arp()
1602 # Add a mcast destination VXLAN-GBP tunnel for B&M traffic
1604 tun_bm = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
1607 tun_bm.add_vpp_config()
1610 # a GBP bridge domain with a BVI and a UU-flood interface
1612 bd1 = VppBridgeDomain(self, 1)
1613 bd1.add_vpp_config()
1614 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0,
1616 gbd1.add_vpp_config()
1618 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1619 self.logger.info(self.vapi.cli("sh gbp bridge"))
1621 # ... and has a /32 applied
1622 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
1623 ip_addr.add_vpp_config()
1626 # The Endpoint-group in which we are learning endpoints
1628 epg_220 = VppGbpEndpointGroup(self, 220, 112, rd1, gbd1,
1632 VppGbpEndpointRetention(2))
1633 epg_220.add_vpp_config()
1634 epg_330 = VppGbpEndpointGroup(self, 330, 113, rd1, gbd1,
1638 VppGbpEndpointRetention(2))
1639 epg_330.add_vpp_config()
1642 # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
1645 vx_tun_l2_1 = VppGbpVxlanTunnel(
1646 self, 99, bd1.bd_id,
1647 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L2,
1649 vx_tun_l2_1.add_vpp_config()
1652 # A static endpoint that the learnt endpoints are trying to
1655 ep = VppGbpEndpoint(self, self.pg0,
1657 "10.0.0.127", "11.0.0.127",
1658 "2001:10::1", "3001::1")
1661 self.assertTrue(find_route(self, ep.ip4, 32, table_id=1))
1663 # a packet with an sclass from an unknown EPG
1664 p = (Ether(src=self.pg2.remote_mac,
1665 dst=self.pg2.local_mac) /
1666 IP(src=self.pg2.remote_hosts[0].ip4,
1667 dst=self.pg2.local_ip4) /
1668 UDP(sport=1234, dport=48879) /
1669 VXLAN(vni=99, gpid=88, flags=0x88) /
1670 Ether(src=learnt[0]["mac"], dst=ep.mac) /
1671 IP(src=learnt[0]["ip"], dst=ep.ip4) /
1672 UDP(sport=1234, dport=1234) /
1675 self.send_and_assert_no_replies(self.pg2, p)
1677 self.logger.info(self.vapi.cli("sh error"))
1678 self.assert_error_counter_equal(
1679 '/err/gbp-policy-port/drop-no-contract',
1680 drop_no_contract + 1)
1683 # we should not have learnt a new tunnel endpoint, since
1684 # the EPG was not learnt.
1686 self.assertEqual(INDEX_INVALID,
1687 find_vxlan_gbp_tunnel(self,
1689 self.pg2.remote_hosts[0].ip4,
1692 # ep is not learnt, because the EPG is unknown
1693 self.assertEqual(len(self.vapi.gbp_endpoint_dump()), 1)
1696 # Learn new EPs from IP packets
1698 for ii, l in enumerate(learnt):
1699 # a packet with an sclass from a known EPG
1700 # arriving on an unknown TEP
1701 p = (Ether(src=self.pg2.remote_mac,
1702 dst=self.pg2.local_mac) /
1703 IP(src=self.pg2.remote_hosts[1].ip4,
1704 dst=self.pg2.local_ip4) /
1705 UDP(sport=1234, dport=48879) /
1706 VXLAN(vni=99, gpid=112, flags=0x88) /
1707 Ether(src=l['mac'], dst=ep.mac) /
1708 IP(src=l['ip'], dst=ep.ip4) /
1709 UDP(sport=1234, dport=1234) /
1712 rx = self.send_and_expect(self.pg2, [p], self.pg0)
1715 tep1_sw_if_index = find_vxlan_gbp_tunnel(
1718 self.pg2.remote_hosts[1].ip4,
1720 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
1723 # the EP is learnt via the learnt TEP
1724 # both from its MAC and its IP
1726 self.assertTrue(find_gbp_endpoint(self,
1727 vx_tun_l2_1.sw_if_index,
1729 self.assertTrue(find_gbp_endpoint(self,
1730 vx_tun_l2_1.sw_if_index,
1733 self.assert_error_counter_equal(
1734 '/err/gbp-policy-port/allow-intra-sclass',
1735 allow_intra_class + 2)
1737 self.logger.info(self.vapi.cli("show gbp endpoint"))
1738 self.logger.info(self.vapi.cli("show gbp vxlan"))
1739 self.logger.info(self.vapi.cli("show ip mfib"))
1742 # If we sleep for the threshold time, the learnt endpoints should
1746 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1750 # Learn new EPs from GARP packets received on the BD's mcast tunnel
1752 for ii, l in enumerate(learnt):
1753 # add some junk in the reserved field of the vxlan-header
1754 # next to the VNI. we should accept since reserved bits are
1756 p = (Ether(src=self.pg2.remote_mac,
1757 dst=self.pg2.local_mac) /
1758 IP(src=self.pg2.remote_hosts[1].ip4,
1760 UDP(sport=1234, dport=48879) /
1761 VXLAN(vni=88, reserved2=0x80, gpid=112, flags=0x88) /
1762 Ether(src=l['mac'], dst="ff:ff:ff:ff:ff:ff") /
1764 psrc=l['ip'], pdst=l['ip'],
1765 hwsrc=l['mac'], hwdst="ff:ff:ff:ff:ff:ff"))
1767 rx = self.send_and_expect(self.pg4, [p], self.pg0)
1770 tep1_sw_if_index = find_vxlan_gbp_tunnel(
1773 self.pg2.remote_hosts[1].ip4,
1775 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
1778 # the EP is learnt via the learnt TEP
1779 # both from its MAC and its IP
1781 self.assertTrue(find_gbp_endpoint(self,
1782 vx_tun_l2_1.sw_if_index,
1784 self.assertTrue(find_gbp_endpoint(self,
1785 vx_tun_l2_1.sw_if_index,
1789 # wait for the learnt endpoints to age out
1792 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1796 # Learn new EPs from L2 packets
1798 for ii, l in enumerate(learnt):
1799 # a packet with an sclass from a known EPG
1800 # arriving on an unknown TEP
1801 p = (Ether(src=self.pg2.remote_mac,
1802 dst=self.pg2.local_mac) /
1803 IP(src=self.pg2.remote_hosts[1].ip4,
1804 dst=self.pg2.local_ip4) /
1805 UDP(sport=1234, dport=48879) /
1806 VXLAN(vni=99, gpid=112, flags=0x88) /
1807 Ether(src=l['mac'], dst=ep.mac) /
1810 rx = self.send_and_expect(self.pg2, [p], self.pg0)
1813 tep1_sw_if_index = find_vxlan_gbp_tunnel(
1816 self.pg2.remote_hosts[1].ip4,
1818 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
1821 # the EP is learnt via the learnt TEP
1822 # both from its MAC and its IP
1824 self.assertTrue(find_gbp_endpoint(self,
1825 vx_tun_l2_1.sw_if_index,
1828 self.logger.info(self.vapi.cli("show gbp endpoint"))
1829 self.logger.info(self.vapi.cli("show gbp vxlan"))
1830 self.logger.info(self.vapi.cli("show vxlan-gbp tunnel"))
1833 # wait for the learnt endpoints to age out
1836 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1840 # repeat. the do not learn bit is set so the EPs are not learnt
1843 # a packet with an sclass from a known EPG
1844 p = (Ether(src=self.pg2.remote_mac,
1845 dst=self.pg2.local_mac) /
1846 IP(src=self.pg2.remote_hosts[1].ip4,
1847 dst=self.pg2.local_ip4) /
1848 UDP(sport=1234, dport=48879) /
1849 VXLAN(vni=99, gpid=112, flags=0x88, gpflags="D") /
1850 Ether(src=l['mac'], dst=ep.mac) /
1851 IP(src=l['ip'], dst=ep.ip4) /
1852 UDP(sport=1234, dport=1234) /
1855 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
1858 self.assertFalse(find_gbp_endpoint(self,
1859 vx_tun_l2_1.sw_if_index,
1866 # a packet with an sclass from a known EPG
1867 # set a reserved bit in addition to the G and I
1868 # reserved bits should not be checked on rx.
1869 p = (Ether(src=self.pg2.remote_mac,
1870 dst=self.pg2.local_mac) /
1871 IP(src=self.pg2.remote_hosts[1].ip4,
1872 dst=self.pg2.local_ip4) /
1873 UDP(sport=1234, dport=48879) /
1874 VXLAN(vni=99, gpid=112, flags=0xc8) /
1875 Ether(src=l['mac'], dst=ep.mac) /
1876 IP(src=l['ip'], dst=ep.ip4) /
1877 UDP(sport=1234, dport=1234) /
1880 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
1882 self.assertTrue(find_gbp_endpoint(self,
1883 vx_tun_l2_1.sw_if_index,
1887 # Static EP replies to dynamics
1889 self.logger.info(self.vapi.cli("sh l2fib bd_id 1"))
1891 p = (Ether(src=ep.mac, dst=l['mac']) /
1892 IP(dst=l['ip'], src=ep.ip4) /
1893 UDP(sport=1234, dport=1234) /
1896 rxs = self.send_and_expect(self.pg0, p * 17, self.pg2)
1899 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
1900 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
1901 self.assertEqual(rx[UDP].dport, 48879)
1902 # the UDP source port is a random value for hashing
1903 self.assertEqual(rx[VXLAN].gpid, 112)
1904 self.assertEqual(rx[VXLAN].vni, 99)
1905 self.assertTrue(rx[VXLAN].flags.G)
1906 self.assertTrue(rx[VXLAN].flags.Instance)
1907 self.assertTrue(rx[VXLAN].gpflags.A)
1908 self.assertFalse(rx[VXLAN].gpflags.D)
1911 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1915 # repeat in the other EPG
1916 # there's no contract between 220 and 330, but the A-bit is set
1917 # so the packet is cleared for delivery
1920 # a packet with an sclass from a known EPG
1921 p = (Ether(src=self.pg2.remote_mac,
1922 dst=self.pg2.local_mac) /
1923 IP(src=self.pg2.remote_hosts[1].ip4,
1924 dst=self.pg2.local_ip4) /
1925 UDP(sport=1234, dport=48879) /
1926 VXLAN(vni=99, gpid=113, flags=0x88, gpflags='A') /
1927 Ether(src=l['mac'], dst=ep.mac) /
1928 IP(src=l['ip'], dst=ep.ip4) /
1929 UDP(sport=1234, dport=1234) /
1932 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
1934 self.assertTrue(find_gbp_endpoint(self,
1935 vx_tun_l2_1.sw_if_index,
1939 # static EP cannot reach the learnt EPs since there is no contract
1940 # only test 1 EP as the others could timeout
1942 p = (Ether(src=ep.mac, dst=l['mac']) /
1943 IP(dst=learnt[0]['ip'], src=ep.ip4) /
1944 UDP(sport=1234, dport=1234) /
1947 self.send_and_assert_no_replies(self.pg0, [p])
1950 # refresh the entries after the check for no replies above
1953 # a packet with an sclass from a known EPG
1954 p = (Ether(src=self.pg2.remote_mac,
1955 dst=self.pg2.local_mac) /
1956 IP(src=self.pg2.remote_hosts[1].ip4,
1957 dst=self.pg2.local_ip4) /
1958 UDP(sport=1234, dport=48879) /
1959 VXLAN(vni=99, gpid=113, flags=0x88, gpflags='A') /
1960 Ether(src=l['mac'], dst=ep.mac) /
1961 IP(src=l['ip'], dst=ep.ip4) /
1962 UDP(sport=1234, dport=1234) /
1965 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
1967 self.assertTrue(find_gbp_endpoint(self,
1968 vx_tun_l2_1.sw_if_index,
1972 # Add the contract so they can talk
1974 acl = VppGbpAcl(self)
1975 rule = acl.create_rule(permit_deny=1, proto=17)
1976 rule2 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
1977 acl_index = acl.add_vpp_config([rule, rule2])
1978 c1 = VppGbpContract(
1979 self, 401, epg_220.sclass, epg_330.sclass, acl_index,
1980 [VppGbpContractRule(
1981 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1982 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1985 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1986 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1988 [ETH_P_IP, ETH_P_IPV6])
1992 p = (Ether(src=ep.mac, dst=l['mac']) /
1993 IP(dst=l['ip'], src=ep.ip4) /
1994 UDP(sport=1234, dport=1234) /
1997 self.send_and_expect(self.pg0, [p], self.pg2)
2000 # send UU packets from the local EP
2002 self.logger.info(self.vapi.cli("sh gbp bridge"))
2003 self.logger.info(self.vapi.cli("sh bridge-domain 1 detail"))
2004 p_uu = (Ether(src=ep.mac, dst="00:11:11:11:11:11") /
2005 IP(dst="10.0.0.133", src=ep.ip4) /
2006 UDP(sport=1234, dport=1234) /
2008 rxs = self.send_and_expect(ep.itf, [p_uu], gbd1.uu_fwd)
2010 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2012 p_bm = (Ether(src=ep.mac, dst="ff:ff:ff:ff:ff:ff") /
2013 IP(dst="10.0.0.133", src=ep.ip4) /
2014 UDP(sport=1234, dport=1234) /
2016 rxs = self.send_and_expect_only(ep.itf, [p_bm], tun_bm.mcast_itf)
2019 self.assertEqual(rx[IP].src, self.pg4.local_ip4)
2020 self.assertEqual(rx[IP].dst, "239.1.1.1")
2021 self.assertEqual(rx[UDP].dport, 48879)
2022 # the UDP source port is a random value for hashing
2023 self.assertEqual(rx[VXLAN].gpid, 112)
2024 self.assertEqual(rx[VXLAN].vni, 88)
2025 self.assertTrue(rx[VXLAN].flags.G)
2026 self.assertTrue(rx[VXLAN].flags.Instance)
2027 self.assertFalse(rx[VXLAN].gpflags.A)
2028 self.assertFalse(rx[VXLAN].gpflags.D)
2030 acl = VppGbpAcl(self)
2031 rule = acl.create_rule(permit_deny=1, proto=17)
2032 rule2 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
2033 acl_index = acl.add_vpp_config([rule, rule2])
2034 c2 = VppGbpContract(
2035 self, 401, epg_330.sclass, epg_220.sclass, acl_index,
2036 [VppGbpContractRule(
2037 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2038 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2041 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2042 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2044 [ETH_P_IP, ETH_P_IPV6])
2048 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
2051 # Check v6 Endpoints learning
2054 # a packet with an sclass from a known EPG
2055 p = (Ether(src=self.pg2.remote_mac,
2056 dst=self.pg2.local_mac) /
2057 IP(src=self.pg2.remote_hosts[1].ip4,
2058 dst=self.pg2.local_ip4) /
2059 UDP(sport=1234, dport=48879) /
2060 VXLAN(vni=99, gpid=113, flags=0x88) /
2061 Ether(src=l['mac'], dst=ep.mac) /
2062 IPv6(src=l['ip6'], dst=ep.ip6) /
2063 UDP(sport=1234, dport=1234) /
2066 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
2067 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
2069 self.assertTrue(find_gbp_endpoint(
2071 vx_tun_l2_1.sw_if_index,
2073 tep=[self.pg2.local_ip4,
2074 self.pg2.remote_hosts[1].ip4]))
2076 self.logger.info(self.vapi.cli("sh int"))
2077 self.logger.info(self.vapi.cli("sh vxlan-gbp tunnel"))
2078 self.logger.info(self.vapi.cli("sh gbp vxlan"))
2079 self.logger.info(self.vapi.cli("sh gbp endpoint"))
2080 self.logger.info(self.vapi.cli("sh gbp interface"))
2083 # EP moves to a different TEP
2086 # a packet with an sclass from a known EPG
2087 p = (Ether(src=self.pg2.remote_mac,
2088 dst=self.pg2.local_mac) /
2089 IP(src=self.pg2.remote_hosts[2].ip4,
2090 dst=self.pg2.local_ip4) /
2091 UDP(sport=1234, dport=48879) /
2092 VXLAN(vni=99, gpid=113, flags=0x88) /
2093 Ether(src=l['mac'], dst=ep.mac) /
2094 IPv6(src=l['ip6'], dst=ep.ip6) /
2095 UDP(sport=1234, dport=1234) /
2098 rx = self.send_and_expect(self.pg2, p * 1, self.pg0)
2099 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
2101 self.assertTrue(find_gbp_endpoint(
2103 vx_tun_l2_1.sw_if_index,
2106 tep=[self.pg2.local_ip4,
2107 self.pg2.remote_hosts[2].ip4]))
2110 # v6 remote EP reachability
2113 p = (Ether(src=ep.mac, dst=l['mac']) /
2114 IPv6(dst=l['ip6'], src=ep.ip6) /
2115 UDP(sport=1234, dport=1234) /
2118 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
2121 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2122 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[2].ip4)
2123 self.assertEqual(rx[UDP].dport, 48879)
2124 # the UDP source port is a random value for hashing
2125 self.assertEqual(rx[VXLAN].gpid, 112)
2126 self.assertEqual(rx[VXLAN].vni, 99)
2127 self.assertTrue(rx[VXLAN].flags.G)
2128 self.assertTrue(rx[VXLAN].flags.Instance)
2129 self.assertTrue(rx[VXLAN].gpflags.A)
2130 self.assertFalse(rx[VXLAN].gpflags.D)
2131 self.assertEqual(rx[IPv6].dst, l['ip6'])
2137 # a packet with an sclass from a known EPG
2138 p = (Ether(src=self.pg2.remote_mac,
2139 dst=self.pg2.local_mac) /
2140 IP(src=self.pg2.remote_hosts[2].ip4,
2141 dst=self.pg2.local_ip4) /
2142 UDP(sport=1234, dport=48879) /
2143 VXLAN(vni=99, gpid=112, flags=0x88) /
2144 Ether(src=l['mac'], dst=ep.mac) /
2145 IPv6(src=l['ip6'], dst=ep.ip6) /
2146 UDP(sport=1234, dport=1234) /
2149 rx = self.send_and_expect(self.pg2, p * 1, self.pg0)
2150 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
2152 self.assertTrue(find_gbp_endpoint(
2154 vx_tun_l2_1.sw_if_index,
2157 tep=[self.pg2.local_ip4,
2158 self.pg2.remote_hosts[2].ip4]))
2161 # check reachability and contract intra-epg
2163 allow_intra_class = self.statistics.get_err_counter(
2164 '/err/gbp-policy-mac/allow-intra-sclass')
2167 p = (Ether(src=ep.mac, dst=l['mac']) /
2168 IPv6(dst=l['ip6'], src=ep.ip6) /
2169 UDP(sport=1234, dport=1234) /
2172 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
2175 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2176 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[2].ip4)
2177 self.assertEqual(rx[UDP].dport, 48879)
2178 self.assertEqual(rx[VXLAN].gpid, 112)
2179 self.assertEqual(rx[VXLAN].vni, 99)
2180 self.assertTrue(rx[VXLAN].flags.G)
2181 self.assertTrue(rx[VXLAN].flags.Instance)
2182 self.assertTrue(rx[VXLAN].gpflags.A)
2183 self.assertFalse(rx[VXLAN].gpflags.D)
2184 self.assertEqual(rx[IPv6].dst, l['ip6'])
2186 allow_intra_class += NUM_PKTS
2188 self.assert_error_counter_equal(
2189 '/err/gbp-policy-mac/allow-intra-sclass',
2196 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
2198 self.pg2.unconfig_ip4()
2199 self.pg3.unconfig_ip4()
2200 self.pg4.unconfig_ip4()
2202 def test_gbp_contract(self):
2203 """ GBP Contracts """
2208 gt4 = VppIpTable(self, 0)
2209 gt4.add_vpp_config()
2210 gt6 = VppIpTable(self, 0, is_ip6=True)
2211 gt6.add_vpp_config()
2213 rd0 = VppGbpRouteDomain(self, 0, 400, gt4, gt6, None, None)
2215 rd0.add_vpp_config()
2220 bd1 = VppBridgeDomain(self, 1, arp_term=0)
2221 bd2 = VppBridgeDomain(self, 2, arp_term=0)
2223 bd1.add_vpp_config()
2224 bd2.add_vpp_config()
2226 gbd1 = VppGbpBridgeDomain(self, bd1, rd0, self.loop0)
2227 gbd2 = VppGbpBridgeDomain(self, bd2, rd0, self.loop1)
2229 gbd1.add_vpp_config()
2230 gbd2.add_vpp_config()
2233 # 3 EPGs, 2 of which share a BD.
2235 epgs = [VppGbpEndpointGroup(self, 220, 1220, rd0, gbd1,
2237 "10.0.0.128", "2001:10::128"),
2238 VppGbpEndpointGroup(self, 221, 1221, rd0, gbd1,
2240 "10.0.1.128", "2001:10:1::128"),
2241 VppGbpEndpointGroup(self, 222, 1222, rd0, gbd2,
2243 "10.0.2.128", "2001:10:2::128")]
2245 # 4 end-points, 2 in the same subnet, 3 in the same BD
2247 eps = [VppGbpEndpoint(self, self.pg0,
2249 "10.0.0.1", "11.0.0.1",
2250 "2001:10::1", "3001::1"),
2251 VppGbpEndpoint(self, self.pg1,
2253 "10.0.0.2", "11.0.0.2",
2254 "2001:10::2", "3001::2"),
2255 VppGbpEndpoint(self, self.pg2,
2257 "10.0.1.1", "11.0.0.3",
2258 "2001:10:1::1", "3001::3"),
2259 VppGbpEndpoint(self, self.pg3,
2261 "10.0.2.1", "11.0.0.4",
2262 "2001:10:2::1", "3001::4")]
2265 # Config related to each of the EPGs
2268 # IP config on the BVI interfaces
2270 VppIpInterfaceBind(self, epg.bvi, epg.rd.t4).add_vpp_config()
2271 VppIpInterfaceBind(self, epg.bvi, epg.rd.t6).add_vpp_config()
2272 epg.bvi.set_mac(self.router_mac)
2274 if_ip4 = VppIpInterfaceAddress(self, epg.bvi, epg.bvi_ip4, 32)
2275 if_ip6 = VppIpInterfaceAddress(self, epg.bvi, epg.bvi_ip6, 128)
2276 if_ip4.add_vpp_config()
2277 if_ip6.add_vpp_config()
2279 # add the BD ARP termination entry for BVI IP
2280 epg.bd_arp_ip4 = VppBridgeDomainArpEntry(self, epg.bd.bd,
2281 str(self.router_mac),
2283 epg.bd_arp_ip4.add_vpp_config()
2286 epg.add_vpp_config()
2294 self.logger.info(self.vapi.cli("show gbp endpoint"))
2295 self.logger.info(self.vapi.cli("show interface"))
2296 self.logger.info(self.vapi.cli("show br"))
2299 # Intra epg allowed without contract
2301 pkt_intra_epg_220_to_220 = (Ether(src=self.pg0.remote_mac,
2302 dst=self.pg1.remote_mac) /
2305 UDP(sport=1234, dport=1234) /
2308 self.send_and_expect_bridged(self.pg0,
2309 pkt_intra_epg_220_to_220 * 65,
2312 pkt_intra_epg_220_to_220 = (Ether(src=self.pg0.remote_mac,
2313 dst=self.pg1.remote_mac) /
2314 IPv6(src=eps[0].ip6,
2316 UDP(sport=1234, dport=1234) /
2319 self.send_and_expect_bridged6(self.pg0,
2320 pkt_intra_epg_220_to_220 * 65,
2324 # Inter epg denied without contract
2326 pkt_inter_epg_220_to_221 = (Ether(src=self.pg0.remote_mac,
2327 dst=self.pg2.remote_mac) /
2330 UDP(sport=1234, dport=1234) /
2333 self.send_and_assert_no_replies(self.pg0, pkt_inter_epg_220_to_221)
2336 # A uni-directional contract from EPG 220 -> 221
2338 acl = VppGbpAcl(self)
2339 rule = acl.create_rule(permit_deny=1, proto=17)
2340 rule2 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
2341 rule3 = acl.create_rule(permit_deny=1, proto=1)
2342 acl_index = acl.add_vpp_config([rule, rule2, rule3])
2343 c1 = VppGbpContract(
2344 self, 400, epgs[0].sclass, epgs[1].sclass, acl_index,
2345 [VppGbpContractRule(
2346 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2347 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2350 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2351 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2354 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2355 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2357 [ETH_P_IP, ETH_P_IPV6])
2360 self.send_and_expect_bridged(eps[0].itf,
2361 pkt_inter_epg_220_to_221 * 65,
2364 pkt_inter_epg_220_to_222 = (Ether(src=self.pg0.remote_mac,
2365 dst=str(self.router_mac)) /
2368 UDP(sport=1234, dport=1234) /
2370 self.send_and_assert_no_replies(eps[0].itf,
2371 pkt_inter_epg_220_to_222 * 65)
2374 # ping router IP in different BD
2376 pkt_router_ping_220_to_221 = (Ether(src=self.pg0.remote_mac,
2377 dst=str(self.router_mac)) /
2379 dst=epgs[1].bvi_ip4) /
2380 ICMP(type='echo-request'))
2382 self.send_and_expect(self.pg0, [pkt_router_ping_220_to_221], self.pg0)
2384 pkt_router_ping_220_to_221 = (Ether(src=self.pg0.remote_mac,
2385 dst=str(self.router_mac)) /
2386 IPv6(src=eps[0].ip6,
2387 dst=epgs[1].bvi_ip6) /
2388 ICMPv6EchoRequest())
2390 self.send_and_expect(self.pg0, [pkt_router_ping_220_to_221], self.pg0)
2393 # contract for the return direction
2395 c2 = VppGbpContract(
2396 self, 400, epgs[1].sclass, epgs[0].sclass, acl_index,
2397 [VppGbpContractRule(
2398 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2399 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2402 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2403 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2405 [ETH_P_IP, ETH_P_IPV6])
2408 self.send_and_expect_bridged(eps[0].itf,
2409 pkt_inter_epg_220_to_221 * 65,
2411 pkt_inter_epg_221_to_220 = (Ether(src=self.pg2.remote_mac,
2412 dst=self.pg0.remote_mac) /
2415 UDP(sport=1234, dport=1234) /
2417 self.send_and_expect_bridged(eps[2].itf,
2418 pkt_inter_epg_221_to_220 * 65,
2420 pkt_inter_epg_221_to_220 = (Ether(src=self.pg2.remote_mac,
2421 dst=str(self.router_mac)) /
2424 UDP(sport=1234, dport=1234) /
2426 self.send_and_expect_routed(eps[2].itf,
2427 pkt_inter_epg_221_to_220 * 65,
2429 str(self.router_mac))
2430 pkt_inter_epg_221_to_220 = (Ether(src=self.pg2.remote_mac,
2431 dst=str(self.router_mac)) /
2432 IPv6(src=eps[2].ip6,
2434 UDP(sport=1234, dport=1234) /
2436 self.send_and_expect_routed6(eps[2].itf,
2437 pkt_inter_epg_221_to_220 * 65,
2439 str(self.router_mac))
2442 # contract between 220 and 222 uni-direction
2444 c3 = VppGbpContract(
2445 self, 400, epgs[0].sclass, epgs[2].sclass, acl_index,
2446 [VppGbpContractRule(
2447 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2448 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2451 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2452 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2454 [ETH_P_IP, ETH_P_IPV6])
2457 self.send_and_expect(eps[0].itf,
2458 pkt_inter_epg_220_to_222 * 65,
2461 c3.remove_vpp_config()
2462 c1.remove_vpp_config()
2463 c2.remove_vpp_config()
2464 acl.remove_vpp_config()
2466 def test_gbp_bd_drop_flags(self):
2467 """ GBP BD drop flags """
2472 gt4 = VppIpTable(self, 1)
2473 gt4.add_vpp_config()
2474 gt6 = VppIpTable(self, 1, is_ip6=True)
2475 gt6.add_vpp_config()
2477 rd1 = VppGbpRouteDomain(self, 1, 401, gt4, gt6)
2478 rd1.add_vpp_config()
2481 # a GBP bridge domain with a BVI only
2483 bd1 = VppBridgeDomain(self, 1)
2484 bd1.add_vpp_config()
2486 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0,
2488 uu_drop=True, bm_drop=True)
2489 gbd1.add_vpp_config()
2491 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2492 self.logger.info(self.vapi.cli("sh gbp bridge"))
2494 # ... and has a /32 applied
2495 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2496 ip_addr.add_vpp_config()
2499 # The Endpoint-group
2501 epg_220 = VppGbpEndpointGroup(self, 220, 112, rd1, gbd1,
2505 VppGbpEndpointRetention(2))
2506 epg_220.add_vpp_config()
2508 ep = VppGbpEndpoint(self, self.pg0,
2510 "10.0.0.127", "11.0.0.127",
2511 "2001:10::1", "3001::1")
2515 # send UU/BM packet from the local EP with UU drop and BM drop enabled
2518 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2519 self.logger.info(self.vapi.cli("sh gbp bridge"))
2520 p_uu = (Ether(src=ep.mac, dst="00:11:11:11:11:11") /
2521 IP(dst="10.0.0.133", src=ep.ip4) /
2522 UDP(sport=1234, dport=1234) /
2524 self.send_and_assert_no_replies(ep.itf, [p_uu])
2526 p_bm = (Ether(src=ep.mac, dst="ff:ff:ff:ff:ff:ff") /
2527 IP(dst="10.0.0.133", src=ep.ip4) /
2528 UDP(sport=1234, dport=1234) /
2530 self.send_and_assert_no_replies(ep.itf, [p_bm])
2532 self.pg3.unconfig_ip4()
2534 self.logger.info(self.vapi.cli("sh int"))
2536 def test_gbp_bd_arp_flags(self):
2537 """ GBP BD arp flags """
2542 gt4 = VppIpTable(self, 1)
2543 gt4.add_vpp_config()
2544 gt6 = VppIpTable(self, 1, is_ip6=True)
2545 gt6.add_vpp_config()
2547 rd1 = VppGbpRouteDomain(self, 1, 401, gt4, gt6)
2548 rd1.add_vpp_config()
2551 # Pg4 hosts the IP6 UU-flood VXLAN tunnel
2553 self.pg4.config_ip4()
2554 self.pg4.resolve_arp()
2557 # Add a mcast destination VXLAN-GBP tunnel for B&M traffic
2559 tun_uu = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
2562 tun_uu.add_vpp_config()
2565 # a GBP bridge domain with a BVI and a UU-flood interface
2567 bd1 = VppBridgeDomain(self, 1)
2568 bd1.add_vpp_config()
2570 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0,
2573 gbd1.add_vpp_config()
2575 # ... and has a /32 applied
2576 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2577 ip_addr.add_vpp_config()
2580 # The Endpoint-group
2582 epg_220 = VppGbpEndpointGroup(self, 220, 112, rd1, gbd1,
2586 VppGbpEndpointRetention(2))
2587 epg_220.add_vpp_config()
2589 ep = VppGbpEndpoint(self, self.pg0,
2591 "10.0.0.127", "11.0.0.127",
2592 "2001:10::1", "3001::1")
2596 # send ARP packet from the local EP expect it on the uu interface
2598 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2599 self.logger.info(self.vapi.cli("sh gbp bridge"))
2600 p_arp = (Ether(src=ep.mac, dst="ff:ff:ff:ff:ff:ff") /
2602 psrc=ep.ip4, pdst="10.0.0.99",
2604 hwdst="ff:ff:ff:ff:ff:ff"))
2605 self.send_and_expect(ep.itf, [p_arp], self.pg4)
2607 self.pg4.unconfig_ip4()
2609 def test_gbp_learn_vlan_l2(self):
2610 """ GBP L2 Endpoint w/ VLANs"""
2612 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
2613 learnt = [{'mac': '00:00:11:11:11:01',
2615 'ip6': '2001:10::2'},
2616 {'mac': '00:00:11:11:11:02',
2618 'ip6': '2001:10::3'}]
2623 gt4 = VppIpTable(self, 1)
2624 gt4.add_vpp_config()
2625 gt6 = VppIpTable(self, 1, is_ip6=True)
2626 gt6.add_vpp_config()
2628 rd1 = VppGbpRouteDomain(self, 1, 401, gt4, gt6)
2629 rd1.add_vpp_config()
2632 # Pg2 hosts the vxlan tunnel, hosts on pg2 to act as TEPs
2634 self.pg2.config_ip4()
2635 self.pg2.resolve_arp()
2636 self.pg2.generate_remote_hosts(4)
2637 self.pg2.configure_ipv4_neighbors()
2638 self.pg3.config_ip4()
2639 self.pg3.resolve_arp()
2642 # The EP will be on a vlan sub-interface
2644 vlan_11 = VppDot1QSubint(self, self.pg0, 11)
2646 self.vapi.l2_interface_vlan_tag_rewrite(
2647 sw_if_index=vlan_11.sw_if_index, vtr_op=L2_VTR_OP.L2_POP_1,
2650 bd_uu_fwd = VppVxlanGbpTunnel(self, self.pg3.local_ip4,
2651 self.pg3.remote_ip4, 116)
2652 bd_uu_fwd.add_vpp_config()
2655 # a GBP bridge domain with a BVI and a UU-flood interface
2656 # The BD is marked as do not learn, so no endpoints are ever
2657 # learnt in this BD.
2659 bd1 = VppBridgeDomain(self, 1)
2660 bd1.add_vpp_config()
2661 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0, bd_uu_fwd,
2663 gbd1.add_vpp_config()
2665 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2666 self.logger.info(self.vapi.cli("sh gbp bridge"))
2668 # ... and has a /32 applied
2669 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2670 ip_addr.add_vpp_config()
2673 # The Endpoint-group in which we are learning endpoints
2675 epg_220 = VppGbpEndpointGroup(self, 220, 441, rd1, gbd1,
2679 VppGbpEndpointRetention(2))
2680 epg_220.add_vpp_config()
2683 # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
2686 vx_tun_l2_1 = VppGbpVxlanTunnel(
2687 self, 99, bd1.bd_id,
2688 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L2,
2690 vx_tun_l2_1.add_vpp_config()
2693 # A static endpoint that the learnt endpoints are trying to
2696 ep = VppGbpEndpoint(self, vlan_11,
2698 "10.0.0.127", "11.0.0.127",
2699 "2001:10::1", "3001::1")
2702 self.assertTrue(find_route(self, ep.ip4, 32, table_id=1))
2705 # Send to the static EP
2707 for ii, l in enumerate(learnt):
2708 # a packet with an sclass from a known EPG
2709 # arriving on an unknown TEP
2710 p = (Ether(src=self.pg2.remote_mac,
2711 dst=self.pg2.local_mac) /
2712 IP(src=self.pg2.remote_hosts[1].ip4,
2713 dst=self.pg2.local_ip4) /
2714 UDP(sport=1234, dport=48879) /
2715 VXLAN(vni=99, gpid=441, flags=0x88) /
2716 Ether(src=l['mac'], dst=ep.mac) /
2717 IP(src=l['ip'], dst=ep.ip4) /
2718 UDP(sport=1234, dport=1234) /
2721 rxs = self.send_and_expect(self.pg2, [p], self.pg0)
2724 # packet to EP has the EP's vlan tag
2727 self.assertEqual(rx[Dot1Q].vlan, 11)
2730 # the EP is not learnt since the BD setting prevents it
2733 self.assertFalse(find_gbp_endpoint(self,
2734 vx_tun_l2_1.sw_if_index,
2736 self.assertEqual(INDEX_INVALID,
2737 find_vxlan_gbp_tunnel(
2740 self.pg2.remote_hosts[1].ip4,
2743 self.assertEqual(len(self.vapi.gbp_endpoint_dump()), 1)
2747 # we didn't learn the remotes so they are sent to the UU-fwd
2750 p = (Ether(src=ep.mac, dst=l['mac']) /
2752 IP(dst=l['ip'], src=ep.ip4) /
2753 UDP(sport=1234, dport=1234) /
2756 rxs = self.send_and_expect(self.pg0, p * 17, self.pg3)
2759 self.assertEqual(rx[IP].src, self.pg3.local_ip4)
2760 self.assertEqual(rx[IP].dst, self.pg3.remote_ip4)
2761 self.assertEqual(rx[UDP].dport, 48879)
2762 # the UDP source port is a random value for hashing
2763 self.assertEqual(rx[VXLAN].gpid, 441)
2764 self.assertEqual(rx[VXLAN].vni, 116)
2765 self.assertTrue(rx[VXLAN].flags.G)
2766 self.assertTrue(rx[VXLAN].flags.Instance)
2767 self.assertFalse(rx[VXLAN].gpflags.A)
2768 self.assertFalse(rx[VXLAN].gpflags.D)
2770 self.pg2.unconfig_ip4()
2771 self.pg3.unconfig_ip4()
2773 def test_gbp_learn_l3(self):
2774 """ GBP L3 Endpoint Learning """
2776 self.vapi.cli("set logging class gbp level debug")
2778 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
2779 routed_dst_mac = "00:0c:0c:0c:0c:0c"
2780 routed_src_mac = "00:22:bd:f8:19:ff"
2782 learnt = [{'mac': '00:00:11:11:11:02',
2784 'ip6': '2001:10::2'},
2785 {'mac': '00:00:11:11:11:03',
2787 'ip6': '2001:10::3'}]
2792 t4 = VppIpTable(self, 1)
2794 t6 = VppIpTable(self, 1, True)
2797 tun_ip4_uu = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
2798 self.pg4.remote_ip4, 114)
2799 tun_ip6_uu = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
2800 self.pg4.remote_ip4, 116)
2801 tun_ip4_uu.add_vpp_config()
2802 tun_ip6_uu.add_vpp_config()
2804 rd1 = VppGbpRouteDomain(self, 2, 401, t4, t6, tun_ip4_uu, tun_ip6_uu)
2805 rd1.add_vpp_config()
2807 self.loop0.set_mac(self.router_mac)
2810 # Bind the BVI to the RD
2812 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
2813 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
2816 # Pg2 hosts the vxlan tunnel
2817 # hosts on pg2 to act as TEPs
2821 self.pg2.config_ip4()
2822 self.pg2.resolve_arp()
2823 self.pg2.generate_remote_hosts(4)
2824 self.pg2.configure_ipv4_neighbors()
2825 self.pg3.config_ip4()
2826 self.pg3.resolve_arp()
2827 self.pg4.config_ip4()
2828 self.pg4.resolve_arp()
2831 # a GBP bridge domain with a BVI and a UU-flood interface
2833 bd1 = VppBridgeDomain(self, 1)
2834 bd1.add_vpp_config()
2835 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0, self.pg3)
2836 gbd1.add_vpp_config()
2838 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2839 self.logger.info(self.vapi.cli("sh gbp bridge"))
2840 self.logger.info(self.vapi.cli("sh gbp route"))
2842 # ... and has a /32 and /128 applied
2843 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2844 ip4_addr.add_vpp_config()
2845 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 128)
2846 ip6_addr.add_vpp_config()
2849 # The Endpoint-group in which we are learning endpoints
2851 epg_220 = VppGbpEndpointGroup(self, 220, 441, rd1, gbd1,
2855 VppGbpEndpointRetention(2))
2856 epg_220.add_vpp_config()
2859 # The VXLAN GBP tunnel is in L3 mode with learning enabled
2861 vx_tun_l3 = VppGbpVxlanTunnel(
2862 self, 101, rd1.rd_id,
2863 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
2865 vx_tun_l3.add_vpp_config()
2868 # A static endpoint that the learnt endpoints are trying to
2871 ep = VppGbpEndpoint(self, self.pg0,
2873 "10.0.0.127", "11.0.0.127",
2874 "2001:10::1", "3001::1")
2878 # learn some remote IPv4 EPs
2880 for ii, l in enumerate(learnt):
2881 # a packet with an sclass from a known EPG
2882 # arriving on an unknown TEP
2883 p = (Ether(src=self.pg2.remote_mac,
2884 dst=self.pg2.local_mac) /
2885 IP(src=self.pg2.remote_hosts[1].ip4,
2886 dst=self.pg2.local_ip4) /
2887 UDP(sport=1234, dport=48879) /
2888 VXLAN(vni=101, gpid=441, flags=0x88) /
2889 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2890 IP(src=l['ip'], dst=ep.ip4) /
2891 UDP(sport=1234, dport=1234) /
2894 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2897 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2900 self.pg2.remote_hosts[1].ip4,
2902 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2904 # endpoint learnt via the parent GBP-vxlan interface
2905 self.assertTrue(find_gbp_endpoint(self,
2906 vx_tun_l3._sw_if_index,
2910 # Static IPv4 EP replies to learnt
2913 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2914 IP(dst=l['ip'], src=ep.ip4) /
2915 UDP(sport=1234, dport=1234) /
2918 rxs = self.send_and_expect(self.pg0, p * 1, self.pg2)
2921 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2922 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2923 self.assertEqual(rx[UDP].dport, 48879)
2924 # the UDP source port is a random value for hashing
2925 self.assertEqual(rx[VXLAN].gpid, 441)
2926 self.assertEqual(rx[VXLAN].vni, 101)
2927 self.assertTrue(rx[VXLAN].flags.G)
2928 self.assertTrue(rx[VXLAN].flags.Instance)
2929 self.assertTrue(rx[VXLAN].gpflags.A)
2930 self.assertFalse(rx[VXLAN].gpflags.D)
2932 inner = rx[VXLAN].payload
2934 self.assertEqual(inner[Ether].src, routed_src_mac)
2935 self.assertEqual(inner[Ether].dst, routed_dst_mac)
2936 self.assertEqual(inner[IP].src, ep.ip4)
2937 self.assertEqual(inner[IP].dst, l['ip'])
2940 self.assertFalse(find_gbp_endpoint(self,
2945 # learn some remote IPv6 EPs
2947 for ii, l in enumerate(learnt):
2948 # a packet with an sclass from a known EPG
2949 # arriving on an unknown TEP
2950 p = (Ether(src=self.pg2.remote_mac,
2951 dst=self.pg2.local_mac) /
2952 IP(src=self.pg2.remote_hosts[1].ip4,
2953 dst=self.pg2.local_ip4) /
2954 UDP(sport=1234, dport=48879) /
2955 VXLAN(vni=101, gpid=441, flags=0x88) /
2956 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2957 IPv6(src=l['ip6'], dst=ep.ip6) /
2958 UDP(sport=1234, dport=1234) /
2961 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2964 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2967 self.pg2.remote_hosts[1].ip4,
2969 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2971 self.logger.info(self.vapi.cli("show gbp bridge"))
2972 self.logger.info(self.vapi.cli("show vxlan-gbp tunnel"))
2973 self.logger.info(self.vapi.cli("show gbp vxlan"))
2974 self.logger.info(self.vapi.cli("show int addr"))
2976 # endpoint learnt via the TEP
2977 self.assertTrue(find_gbp_endpoint(self, ip=l['ip6']))
2979 self.logger.info(self.vapi.cli("show gbp endpoint"))
2980 self.logger.info(self.vapi.cli("show ip fib index 1 %s" % l['ip']))
2983 # Static EP replies to learnt
2986 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2987 IPv6(dst=l['ip6'], src=ep.ip6) /
2988 UDP(sport=1234, dport=1234) /
2991 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
2994 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2995 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2996 self.assertEqual(rx[UDP].dport, 48879)
2997 # the UDP source port is a random value for hashing
2998 self.assertEqual(rx[VXLAN].gpid, 441)
2999 self.assertEqual(rx[VXLAN].vni, 101)
3000 self.assertTrue(rx[VXLAN].flags.G)
3001 self.assertTrue(rx[VXLAN].flags.Instance)
3002 self.assertTrue(rx[VXLAN].gpflags.A)
3003 self.assertFalse(rx[VXLAN].gpflags.D)
3005 inner = rx[VXLAN].payload
3007 self.assertEqual(inner[Ether].src, routed_src_mac)
3008 self.assertEqual(inner[Ether].dst, routed_dst_mac)
3009 self.assertEqual(inner[IPv6].src, ep.ip6)
3010 self.assertEqual(inner[IPv6].dst, l['ip6'])
3012 self.logger.info(self.vapi.cli("sh gbp endpoint"))
3014 self.wait_for_ep_timeout(ip=l['ip'])
3017 # Static sends to unknown EP with no route
3019 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
3020 IP(dst="10.0.0.99", src=ep.ip4) /
3021 UDP(sport=1234, dport=1234) /
3024 self.send_and_assert_no_replies(self.pg0, [p])
3027 # Add a route to static EP's v4 and v6 subnet
3029 se_10_24 = VppGbpSubnet(
3030 self, rd1, "10.0.0.0", 24,
3031 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT)
3032 se_10_24.add_vpp_config()
3035 # static pings router
3037 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
3038 IP(dst=epg_220.bvi_ip4, src=ep.ip4) /
3039 UDP(sport=1234, dport=1234) /
3042 self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg0)
3044 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
3045 IPv6(dst=epg_220.bvi_ip6, src=ep.ip6) /
3046 UDP(sport=1234, dport=1234) /
3049 self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg0)
3052 # packets to address in the subnet are sent on the uu-fwd
3054 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
3055 IP(dst="10.0.0.99", src=ep.ip4) /
3056 UDP(sport=1234, dport=1234) /
3059 rxs = self.send_and_expect(self.pg0, [p], self.pg4)
3061 self.assertEqual(rx[IP].src, self.pg4.local_ip4)
3062 self.assertEqual(rx[IP].dst, self.pg4.remote_ip4)
3063 self.assertEqual(rx[UDP].dport, 48879)
3064 # the UDP source port is a random value for hashing
3065 self.assertEqual(rx[VXLAN].gpid, 441)
3066 self.assertEqual(rx[VXLAN].vni, 114)
3067 self.assertTrue(rx[VXLAN].flags.G)
3068 self.assertTrue(rx[VXLAN].flags.Instance)
3069 # policy is not applied to packets sent to the uu-fwd interfaces
3070 self.assertFalse(rx[VXLAN].gpflags.A)
3071 self.assertFalse(rx[VXLAN].gpflags.D)
3074 # learn some remote IPv4 EPs
3076 for ii, l in enumerate(learnt):
3077 # a packet with an sclass from a known EPG
3078 # arriving on an unknown TEP
3079 p = (Ether(src=self.pg2.remote_mac,
3080 dst=self.pg2.local_mac) /
3081 IP(src=self.pg2.remote_hosts[2].ip4,
3082 dst=self.pg2.local_ip4) /
3083 UDP(sport=1234, dport=48879) /
3084 VXLAN(vni=101, gpid=441, flags=0x88) /
3085 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
3086 IP(src=l['ip'], dst=ep.ip4) /
3087 UDP(sport=1234, dport=1234) /
3090 rx = self.send_and_expect(self.pg2, [p], self.pg0)
3093 tep1_sw_if_index = find_vxlan_gbp_tunnel(
3096 self.pg2.remote_hosts[2].ip4,
3098 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
3100 # endpoint learnt via the parent GBP-vxlan interface
3101 self.assertTrue(find_gbp_endpoint(self,
3102 vx_tun_l3._sw_if_index,
3106 # Add a remote endpoint from the API
3108 rep_88 = VppGbpEndpoint(self, vx_tun_l3,
3110 "10.0.0.88", "11.0.0.88",
3111 "2001:10::88", "3001::88",
3112 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
3114 self.pg2.remote_hosts[2].ip4,
3116 rep_88.add_vpp_config()
3119 # Add a remote endpoint from the API that matches an existing one
3120 # this is a lower priority, hence the packet is sent to the DP leanrt
3123 rep_2 = VppGbpEndpoint(self, vx_tun_l3,
3125 learnt[0]['ip'], "11.0.0.101",
3126 learnt[0]['ip6'], "3001::101",
3127 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
3129 self.pg2.remote_hosts[1].ip4,
3131 rep_2.add_vpp_config()
3134 # Add a route to the learned EP's v4 subnet
3135 # packets should be send on the v4/v6 uu=fwd interface resp.
3137 se_10_1_24 = VppGbpSubnet(
3138 self, rd1, "10.0.1.0", 24,
3139 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT)
3140 se_10_1_24.add_vpp_config()
3142 self.logger.info(self.vapi.cli("show gbp endpoint"))
3144 ips = ["10.0.0.88", learnt[0]['ip']]
3146 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
3147 IP(dst=ip, src=ep.ip4) /
3148 UDP(sport=1234, dport=1234) /
3151 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
3154 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
3155 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[2].ip4)
3156 self.assertEqual(rx[UDP].dport, 48879)
3157 # the UDP source port is a random value for hashing
3158 self.assertEqual(rx[VXLAN].gpid, 441)
3159 self.assertEqual(rx[VXLAN].vni, 101)
3160 self.assertTrue(rx[VXLAN].flags.G)
3161 self.assertTrue(rx[VXLAN].flags.Instance)
3162 self.assertTrue(rx[VXLAN].gpflags.A)
3163 self.assertFalse(rx[VXLAN].gpflags.D)
3165 inner = rx[VXLAN].payload
3167 self.assertEqual(inner[Ether].src, routed_src_mac)
3168 self.assertEqual(inner[Ether].dst, routed_dst_mac)
3169 self.assertEqual(inner[IP].src, ep.ip4)
3170 self.assertEqual(inner[IP].dst, ip)
3173 # remove the API remote EPs, only API sourced is gone, the DP
3174 # learnt one remains
3176 rep_88.remove_vpp_config()
3177 rep_2.remove_vpp_config()
3179 self.assertTrue(find_gbp_endpoint(self, ip=rep_2.ip4))
3181 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
3182 IP(src=ep.ip4, dst=rep_2.ip4) /
3183 UDP(sport=1234, dport=1234) /
3185 rxs = self.send_and_expect(self.pg0, [p], self.pg2)
3187 self.assertFalse(find_gbp_endpoint(self, ip=rep_88.ip4))
3189 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
3190 IP(src=ep.ip4, dst=rep_88.ip4) /
3191 UDP(sport=1234, dport=1234) /
3193 rxs = self.send_and_expect(self.pg0, [p], self.pg4)
3196 # to appease the testcase we cannot have the registered EP still
3197 # present (because it's DP learnt) when the TC ends so wait until
3200 self.wait_for_ep_timeout(ip=rep_88.ip4)
3201 self.wait_for_ep_timeout(ip=rep_2.ip4)
3204 # Same as above, learn a remote EP via CP and DP
3205 # this time remove the DP one first. expect the CP data to remain
3207 rep_3 = VppGbpEndpoint(self, vx_tun_l3,
3209 "10.0.1.4", "11.0.0.103",
3210 "2001::10:3", "3001::103",
3211 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
3213 self.pg2.remote_hosts[1].ip4,
3215 rep_3.add_vpp_config()
3217 p = (Ether(src=self.pg2.remote_mac,
3218 dst=self.pg2.local_mac) /
3219 IP(src=self.pg2.remote_hosts[2].ip4,
3220 dst=self.pg2.local_ip4) /
3221 UDP(sport=1234, dport=48879) /
3222 VXLAN(vni=101, gpid=441, flags=0x88) /
3223 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
3224 IP(src="10.0.1.4", dst=ep.ip4) /
3225 UDP(sport=1234, dport=1234) /
3227 rxs = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
3229 self.assertTrue(find_gbp_endpoint(self,
3230 vx_tun_l3._sw_if_index,
3232 tep=[self.pg2.local_ip4,
3233 self.pg2.remote_hosts[2].ip4]))
3235 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
3236 IP(dst="10.0.1.4", src=ep.ip4) /
3237 UDP(sport=1234, dport=1234) /
3239 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
3241 # host 2 is the DP learned TEP
3243 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
3244 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[2].ip4)
3246 self.wait_for_ep_timeout(ip=rep_3.ip4,
3247 tep=[self.pg2.local_ip4,
3248 self.pg2.remote_hosts[2].ip4])
3250 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
3252 # host 1 is the CP learned TEP
3254 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
3255 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
3258 # shutdown with learnt endpoint present
3260 p = (Ether(src=self.pg2.remote_mac,
3261 dst=self.pg2.local_mac) /
3262 IP(src=self.pg2.remote_hosts[1].ip4,
3263 dst=self.pg2.local_ip4) /
3264 UDP(sport=1234, dport=48879) /
3265 VXLAN(vni=101, gpid=441, flags=0x88) /
3266 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
3267 IP(src=learnt[1]['ip'], dst=ep.ip4) /
3268 UDP(sport=1234, dport=1234) /
3271 rx = self.send_and_expect(self.pg2, [p], self.pg0)
3273 # endpoint learnt via the parent GBP-vxlan interface
3274 self.assertTrue(find_gbp_endpoint(self,
3275 vx_tun_l3._sw_if_index,
3280 # remote endpoint becomes local
3282 self.pg2.unconfig_ip4()
3283 self.pg3.unconfig_ip4()
3284 self.pg4.unconfig_ip4()
3286 def test_gbp_redirect(self):
3287 """ GBP Endpoint Redirect """
3289 self.vapi.cli("set logging class gbp level debug")
3291 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
3292 routed_dst_mac = "00:0c:0c:0c:0c:0c"
3293 routed_src_mac = "00:22:bd:f8:19:ff"
3295 learnt = [{'mac': '00:00:11:11:11:02',
3297 'ip6': '2001:10::2'},
3298 {'mac': '00:00:11:11:11:03',
3300 'ip6': '2001:10::3'}]
3305 t4 = VppIpTable(self, 1)
3307 t6 = VppIpTable(self, 1, True)
3310 rd1 = VppGbpRouteDomain(self, 2, 402, t4, t6)
3311 rd1.add_vpp_config()
3313 self.loop0.set_mac(self.router_mac)
3316 # Bind the BVI to the RD
3318 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
3319 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
3322 # Pg7 hosts a BD's UU-fwd
3324 self.pg7.config_ip4()
3325 self.pg7.resolve_arp()
3328 # a GBP bridge domains for the EPs
3330 bd1 = VppBridgeDomain(self, 1)
3331 bd1.add_vpp_config()
3332 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0)
3333 gbd1.add_vpp_config()
3335 bd2 = VppBridgeDomain(self, 2)
3336 bd2.add_vpp_config()
3337 gbd2 = VppGbpBridgeDomain(self, bd2, rd1, self.loop1)
3338 gbd2.add_vpp_config()
3340 # ... and has a /32 and /128 applied
3341 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
3342 ip4_addr.add_vpp_config()
3343 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 128)
3344 ip6_addr.add_vpp_config()
3345 ip4_addr = VppIpInterfaceAddress(self, gbd2.bvi, "10.0.1.128", 32)
3346 ip4_addr.add_vpp_config()
3347 ip6_addr = VppIpInterfaceAddress(self, gbd2.bvi, "2001:11::128", 128)
3348 ip6_addr.add_vpp_config()
3351 # The Endpoint-groups in which we are learning endpoints
3353 epg_220 = VppGbpEndpointGroup(self, 220, 440, rd1, gbd1,
3357 VppGbpEndpointRetention(2))
3358 epg_220.add_vpp_config()
3359 epg_221 = VppGbpEndpointGroup(self, 221, 441, rd1, gbd2,
3363 VppGbpEndpointRetention(2))
3364 epg_221.add_vpp_config()
3365 epg_222 = VppGbpEndpointGroup(self, 222, 442, rd1, gbd1,
3369 VppGbpEndpointRetention(2))
3370 epg_222.add_vpp_config()
3373 # a GBP bridge domains for the SEPs
3375 bd_uu1 = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
3376 self.pg7.remote_ip4, 116)
3377 bd_uu1.add_vpp_config()
3378 bd_uu2 = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
3379 self.pg7.remote_ip4, 117)
3380 bd_uu2.add_vpp_config()
3382 bd3 = VppBridgeDomain(self, 3)
3383 bd3.add_vpp_config()
3384 gbd3 = VppGbpBridgeDomain(self, bd3, rd1, self.loop2,
3385 bd_uu1, learn=False)
3386 gbd3.add_vpp_config()
3387 bd4 = VppBridgeDomain(self, 4)
3388 bd4.add_vpp_config()
3389 gbd4 = VppGbpBridgeDomain(self, bd4, rd1, self.loop3,
3390 bd_uu2, learn=False)
3391 gbd4.add_vpp_config()
3394 # EPGs in which the service endpoints exist
3396 epg_320 = VppGbpEndpointGroup(self, 320, 550, rd1, gbd3,
3400 VppGbpEndpointRetention(2))
3401 epg_320.add_vpp_config()
3402 epg_321 = VppGbpEndpointGroup(self, 321, 551, rd1, gbd4,
3406 VppGbpEndpointRetention(2))
3407 epg_321.add_vpp_config()
3410 # three local endpoints
3412 ep1 = VppGbpEndpoint(self, self.pg0,
3414 "10.0.0.1", "11.0.0.1",
3415 "2001:10::1", "3001:10::1")
3416 ep1.add_vpp_config()
3417 ep2 = VppGbpEndpoint(self, self.pg1,
3419 "10.0.1.1", "11.0.1.1",
3420 "2001:11::1", "3001:11::1")
3421 ep2.add_vpp_config()
3422 ep3 = VppGbpEndpoint(self, self.pg2,
3424 "10.0.2.2", "11.0.2.2",
3425 "2001:12::1", "3001:12::1")
3426 ep3.add_vpp_config()
3431 sep1 = VppGbpEndpoint(self, self.pg3,
3433 "12.0.0.1", "13.0.0.1",
3434 "4001:10::1", "5001:10::1")
3435 sep1.add_vpp_config()
3436 sep2 = VppGbpEndpoint(self, self.pg4,
3438 "12.0.0.2", "13.0.0.2",
3439 "4001:10::2", "5001:10::2")
3440 sep2.add_vpp_config()
3441 sep3 = VppGbpEndpoint(self, self.pg5,
3443 "12.0.1.1", "13.0.1.1",
3444 "4001:11::1", "5001:11::1")
3445 sep3.add_vpp_config()
3446 # this EP is not installed immediately
3447 sep4 = VppGbpEndpoint(self, self.pg6,
3449 "12.0.1.2", "13.0.1.2",
3450 "4001:11::2", "5001:11::2")
3453 # an L2 switch packet between local EPs in different EPGs
3454 # different dest ports on each so the are LB hashed differently
3456 p4 = [(Ether(src=ep1.mac, dst=ep3.mac) /
3457 IP(src=ep1.ip4, dst=ep3.ip4) /
3458 UDP(sport=1234, dport=1234) /
3459 Raw(b'\xa5' * 100)),
3460 (Ether(src=ep3.mac, dst=ep1.mac) /
3461 IP(src=ep3.ip4, dst=ep1.ip4) /
3462 UDP(sport=1234, dport=1234) /
3463 Raw(b'\xa5' * 100))]
3464 p6 = [(Ether(src=ep1.mac, dst=ep3.mac) /
3465 IPv6(src=ep1.ip6, dst=ep3.ip6) /
3466 UDP(sport=1234, dport=1234) /
3467 Raw(b'\xa5' * 100)),
3468 (Ether(src=ep3.mac, dst=ep1.mac) /
3469 IPv6(src=ep3.ip6, dst=ep1.ip6) /
3470 UDP(sport=1234, dport=1230) /
3471 Raw(b'\xa5' * 100))]
3473 # should be dropped since no contract yet
3474 self.send_and_assert_no_replies(self.pg0, [p4[0]])
3475 self.send_and_assert_no_replies(self.pg0, [p6[0]])
3478 # Add a contract with a rule to load-balance redirect via SEP1 and SEP2
3479 # one of the next-hops is via an EP that is not known
3481 acl = VppGbpAcl(self)
3482 rule4 = acl.create_rule(permit_deny=1, proto=17)
3483 rule6 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
3484 acl_index = acl.add_vpp_config([rule4, rule6])
3487 # test the src-ip hash mode
3489 c1 = VppGbpContract(
3490 self, 402, epg_220.sclass, epg_222.sclass, acl_index,
3491 [VppGbpContractRule(
3492 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3493 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3494 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3495 sep1.ip4, sep1.epg.rd),
3496 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3497 sep2.ip4, sep2.epg.rd)]),
3499 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3500 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3501 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3502 sep3.ip6, sep3.epg.rd),
3503 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3504 sep4.ip6, sep4.epg.rd)])],
3505 [ETH_P_IP, ETH_P_IPV6])
3508 c2 = VppGbpContract(
3509 self, 402, epg_222.sclass, epg_220.sclass, acl_index,
3510 [VppGbpContractRule(
3511 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3512 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3513 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3514 sep1.ip4, sep1.epg.rd),
3515 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3516 sep2.ip4, sep2.epg.rd)]),
3518 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3519 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3520 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3521 sep3.ip6, sep3.epg.rd),
3522 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3523 sep4.ip6, sep4.epg.rd)])],
3524 [ETH_P_IP, ETH_P_IPV6])
3528 # send again with the contract preset, now packets arrive
3529 # at SEP1 or SEP2 depending on the hashing
3531 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3534 self.assertEqual(rx[Ether].src, routed_src_mac)
3535 self.assertEqual(rx[Ether].dst, sep1.mac)
3536 self.assertEqual(rx[IP].src, ep1.ip4)
3537 self.assertEqual(rx[IP].dst, ep3.ip4)
3539 rxs = self.send_and_expect(self.pg2, p4[1] * 17, sep2.itf)
3542 self.assertEqual(rx[Ether].src, routed_src_mac)
3543 self.assertEqual(rx[Ether].dst, sep2.mac)
3544 self.assertEqual(rx[IP].src, ep3.ip4)
3545 self.assertEqual(rx[IP].dst, ep1.ip4)
3547 rxs = self.send_and_expect(self.pg0, p6[0] * 17, self.pg7)
3550 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3551 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3552 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3553 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
3554 self.assertEqual(rx[VXLAN].vni, 117)
3555 self.assertTrue(rx[VXLAN].flags.G)
3556 self.assertTrue(rx[VXLAN].flags.Instance)
3557 # redirect policy has been applied
3558 self.assertTrue(rx[VXLAN].gpflags.A)
3559 self.assertFalse(rx[VXLAN].gpflags.D)
3561 inner = rx[VXLAN].payload
3563 self.assertEqual(inner[Ether].src, routed_src_mac)
3564 self.assertEqual(inner[Ether].dst, sep4.mac)
3565 self.assertEqual(inner[IPv6].src, ep1.ip6)
3566 self.assertEqual(inner[IPv6].dst, ep3.ip6)
3568 rxs = self.send_and_expect(self.pg2, p6[1] * 17, sep3.itf)
3571 self.assertEqual(rx[Ether].src, routed_src_mac)
3572 self.assertEqual(rx[Ether].dst, sep3.mac)
3573 self.assertEqual(rx[IPv6].src, ep3.ip6)
3574 self.assertEqual(rx[IPv6].dst, ep1.ip6)
3577 # programme the unknown EP
3579 sep4.add_vpp_config()
3581 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep4.itf)
3584 self.assertEqual(rx[Ether].src, routed_src_mac)
3585 self.assertEqual(rx[Ether].dst, sep4.mac)
3586 self.assertEqual(rx[IPv6].src, ep1.ip6)
3587 self.assertEqual(rx[IPv6].dst, ep3.ip6)
3590 # and revert back to unprogrammed
3592 sep4.remove_vpp_config()
3594 rxs = self.send_and_expect(self.pg0, p6[0] * 17, self.pg7)
3597 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3598 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3599 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3600 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
3601 self.assertEqual(rx[VXLAN].vni, 117)
3602 self.assertTrue(rx[VXLAN].flags.G)
3603 self.assertTrue(rx[VXLAN].flags.Instance)
3604 # redirect policy has been applied
3605 self.assertTrue(rx[VXLAN].gpflags.A)
3606 self.assertFalse(rx[VXLAN].gpflags.D)
3608 inner = rx[VXLAN].payload
3610 self.assertEqual(inner[Ether].src, routed_src_mac)
3611 self.assertEqual(inner[Ether].dst, sep4.mac)
3612 self.assertEqual(inner[IPv6].src, ep1.ip6)
3613 self.assertEqual(inner[IPv6].dst, ep3.ip6)
3615 c1.remove_vpp_config()
3616 c2.remove_vpp_config()
3619 # test the symmetric hash mode
3621 c1 = VppGbpContract(
3622 self, 402, epg_220.sclass, epg_222.sclass, acl_index,
3623 [VppGbpContractRule(
3624 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3625 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3626 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3627 sep1.ip4, sep1.epg.rd),
3628 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3629 sep2.ip4, sep2.epg.rd)]),
3631 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3632 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3633 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3634 sep3.ip6, sep3.epg.rd),
3635 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3636 sep4.ip6, sep4.epg.rd)])],
3637 [ETH_P_IP, ETH_P_IPV6])
3640 c2 = VppGbpContract(
3641 self, 402, epg_222.sclass, epg_220.sclass, acl_index,
3642 [VppGbpContractRule(
3643 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3644 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3645 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3646 sep1.ip4, sep1.epg.rd),
3647 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3648 sep2.ip4, sep2.epg.rd)]),
3650 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3651 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3652 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3653 sep3.ip6, sep3.epg.rd),
3654 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3655 sep4.ip6, sep4.epg.rd)])],
3656 [ETH_P_IP, ETH_P_IPV6])
3660 # send again with the contract preset, now packets arrive
3661 # at SEP1 for both directions
3663 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3666 self.assertEqual(rx[Ether].src, routed_src_mac)
3667 self.assertEqual(rx[Ether].dst, sep1.mac)
3668 self.assertEqual(rx[IP].src, ep1.ip4)
3669 self.assertEqual(rx[IP].dst, ep3.ip4)
3671 rxs = self.send_and_expect(self.pg2, p4[1] * 17, sep1.itf)
3674 self.assertEqual(rx[Ether].src, routed_src_mac)
3675 self.assertEqual(rx[Ether].dst, sep1.mac)
3676 self.assertEqual(rx[IP].src, ep3.ip4)
3677 self.assertEqual(rx[IP].dst, ep1.ip4)
3680 # programme the unknown EP for the L3 tests
3682 sep4.add_vpp_config()
3685 # an L3 switch packet between local EPs in different EPGs
3686 # different dest ports on each so the are LB hashed differently
3688 p4 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3689 IP(src=ep1.ip4, dst=ep2.ip4) /
3690 UDP(sport=1234, dport=1234) /
3691 Raw(b'\xa5' * 100)),
3692 (Ether(src=ep2.mac, dst=str(self.router_mac)) /
3693 IP(src=ep2.ip4, dst=ep1.ip4) /
3694 UDP(sport=1234, dport=1234) /
3695 Raw(b'\xa5' * 100))]
3696 p6 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3697 IPv6(src=ep1.ip6, dst=ep2.ip6) /
3698 UDP(sport=1234, dport=1234) /
3699 Raw(b'\xa5' * 100)),
3700 (Ether(src=ep2.mac, dst=str(self.router_mac)) /
3701 IPv6(src=ep2.ip6, dst=ep1.ip6) /
3702 UDP(sport=1234, dport=1234) /
3703 Raw(b'\xa5' * 100))]
3705 c3 = VppGbpContract(
3706 self, 402, epg_220.sclass, epg_221.sclass, acl_index,
3707 [VppGbpContractRule(
3708 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3709 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3710 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3711 sep1.ip4, sep1.epg.rd),
3712 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3713 sep2.ip4, sep2.epg.rd)]),
3715 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3716 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3717 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3718 sep3.ip6, sep3.epg.rd),
3719 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3720 sep4.ip6, sep4.epg.rd)])],
3721 [ETH_P_IP, ETH_P_IPV6])
3724 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3727 self.assertEqual(rx[Ether].src, routed_src_mac)
3728 self.assertEqual(rx[Ether].dst, sep1.mac)
3729 self.assertEqual(rx[IP].src, ep1.ip4)
3730 self.assertEqual(rx[IP].dst, ep2.ip4)
3733 # learn a remote EP in EPG 221
3734 # packets coming from unknown remote EPs will be leant & redirected
3736 vx_tun_l3 = VppGbpVxlanTunnel(
3737 self, 444, rd1.rd_id,
3738 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
3740 vx_tun_l3.add_vpp_config()
3742 c4 = VppGbpContract(
3743 self, 402, epg_221.sclass, epg_220.sclass, acl_index,
3744 [VppGbpContractRule(
3745 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3746 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3747 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3748 sep1.ip4, sep1.epg.rd),
3749 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3750 sep2.ip4, sep2.epg.rd)]),
3752 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3753 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3754 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3755 sep3.ip6, sep3.epg.rd),
3756 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3757 sep4.ip6, sep4.epg.rd)])],
3758 [ETH_P_IP, ETH_P_IPV6])
3761 p = (Ether(src=self.pg7.remote_mac,
3762 dst=self.pg7.local_mac) /
3763 IP(src=self.pg7.remote_ip4,
3764 dst=self.pg7.local_ip4) /
3765 UDP(sport=1234, dport=48879) /
3766 VXLAN(vni=444, gpid=441, flags=0x88) /
3767 Ether(src="00:22:22:22:22:33", dst=str(self.router_mac)) /
3768 IP(src="10.0.0.88", dst=ep1.ip4) /
3769 UDP(sport=1234, dport=1234) /
3772 # unknown remote EP to local EP redirected
3773 rxs = self.send_and_expect(self.pg7, [p], sep1.itf)
3776 self.assertEqual(rx[Ether].src, routed_src_mac)
3777 self.assertEqual(rx[Ether].dst, sep1.mac)
3778 self.assertEqual(rx[IP].src, "10.0.0.88")
3779 self.assertEqual(rx[IP].dst, ep1.ip4)
3781 # endpoint learnt via the parent GBP-vxlan interface
3782 self.assertTrue(find_gbp_endpoint(self,
3783 vx_tun_l3._sw_if_index,
3786 p = (Ether(src=self.pg7.remote_mac,
3787 dst=self.pg7.local_mac) /
3788 IP(src=self.pg7.remote_ip4,
3789 dst=self.pg7.local_ip4) /
3790 UDP(sport=1234, dport=48879) /
3791 VXLAN(vni=444, gpid=441, flags=0x88) /
3792 Ether(src="00:22:22:22:22:33", dst=str(self.router_mac)) /
3793 IPv6(src="2001:10::88", dst=ep1.ip6) /
3794 UDP(sport=1234, dport=1234) /
3797 # unknown remote EP to local EP redirected (ipv6)
3798 rxs = self.send_and_expect(self.pg7, [p], sep3.itf)
3801 self.assertEqual(rx[Ether].src, routed_src_mac)
3802 self.assertEqual(rx[Ether].dst, sep3.mac)
3803 self.assertEqual(rx[IPv6].src, "2001:10::88")
3804 self.assertEqual(rx[IPv6].dst, ep1.ip6)
3806 # endpoint learnt via the parent GBP-vxlan interface
3807 self.assertTrue(find_gbp_endpoint(self,
3808 vx_tun_l3._sw_if_index,
3812 # L3 switch from local to remote EP
3814 p4 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3815 IP(src=ep1.ip4, dst="10.0.0.88") /
3816 UDP(sport=1234, dport=1234) /
3817 Raw(b'\xa5' * 100))]
3818 p6 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3819 IPv6(src=ep1.ip6, dst="2001:10::88") /
3820 UDP(sport=1234, dport=1234) /
3821 Raw(b'\xa5' * 100))]
3823 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3826 self.assertEqual(rx[Ether].src, routed_src_mac)
3827 self.assertEqual(rx[Ether].dst, sep1.mac)
3828 self.assertEqual(rx[IP].src, ep1.ip4)
3829 self.assertEqual(rx[IP].dst, "10.0.0.88")
3831 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep4.itf)
3834 self.assertEqual(rx[Ether].src, routed_src_mac)
3835 self.assertEqual(rx[Ether].dst, sep4.mac)
3836 self.assertEqual(rx[IPv6].src, ep1.ip6)
3837 self.assertEqual(rx[IPv6].dst, "2001:10::88")
3840 # test the dst-ip hash mode
3842 c5 = VppGbpContract(
3843 self, 402, epg_220.sclass, epg_221.sclass, acl_index,
3844 [VppGbpContractRule(
3845 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3846 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
3847 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3848 sep1.ip4, sep1.epg.rd),
3849 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3850 sep2.ip4, sep2.epg.rd)]),
3852 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3853 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
3854 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3855 sep3.ip6, sep3.epg.rd),
3856 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3857 sep4.ip6, sep4.epg.rd)])],
3858 [ETH_P_IP, ETH_P_IPV6])
3861 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3864 self.assertEqual(rx[Ether].src, routed_src_mac)
3865 self.assertEqual(rx[Ether].dst, sep1.mac)
3866 self.assertEqual(rx[IP].src, ep1.ip4)
3867 self.assertEqual(rx[IP].dst, "10.0.0.88")
3869 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep3.itf)
3872 self.assertEqual(rx[Ether].src, routed_src_mac)
3873 self.assertEqual(rx[Ether].dst, sep3.mac)
3874 self.assertEqual(rx[IPv6].src, ep1.ip6)
3875 self.assertEqual(rx[IPv6].dst, "2001:10::88")
3878 # a programmed remote SEP in EPG 320
3881 # gbp vxlan tunnel for the remote SEP
3882 vx_tun_l3_sep = VppGbpVxlanTunnel(
3883 self, 555, rd1.rd_id,
3884 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
3886 vx_tun_l3_sep.add_vpp_config()
3889 sep5 = VppGbpEndpoint(self, vx_tun_l3_sep,
3891 "12.0.0.10", "13.0.0.10",
3892 "4001:10::10", "5001:10::10",
3893 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
3895 self.pg7.remote_ip4,
3897 sep5.add_vpp_config()
3900 # local l3out redirect tests
3905 self.loop4.set_mac(self.router_mac)
3906 VppIpInterfaceBind(self, self.loop4, t4).add_vpp_config()
3907 VppIpInterfaceBind(self, self.loop4, t6).add_vpp_config()
3908 ebd = VppBridgeDomain(self, 100)
3909 ebd.add_vpp_config()
3910 gebd = VppGbpBridgeDomain(self, ebd, rd1, self.loop4, None, None)
3911 gebd.add_vpp_config()
3913 eepg = VppGbpEndpointGroup(self, 888, 765, rd1, gebd,
3917 VppGbpEndpointRetention(2))
3918 eepg.add_vpp_config()
3919 # add subnets to BVI
3920 VppIpInterfaceAddress(
3924 24).add_vpp_config()
3925 VppIpInterfaceAddress(
3929 64).add_vpp_config()
3930 # ... which are L3-out subnets
3931 VppGbpSubnet(self, rd1, "10.1.0.0", 24,
3932 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3933 sclass=765).add_vpp_config()
3934 VppGbpSubnet(self, rd1, "2001:10:1::128", 64,
3935 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3936 sclass=765).add_vpp_config()
3937 # external endpoints
3938 VppL2Vtr(self, self.vlan_100, L2_VTR_OP.L2_POP_1).add_vpp_config()
3939 eep1 = VppGbpEndpoint(self, self.vlan_100, eepg, None, "10.1.0.1",
3940 "11.1.0.1", "2001:10:1::1", "3001:10:1::1",
3941 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
3942 eep1.add_vpp_config()
3943 VppL2Vtr(self, self.vlan_101, L2_VTR_OP.L2_POP_1).add_vpp_config()
3944 eep2 = VppGbpEndpoint(self, self.vlan_101, eepg, None, "10.1.0.2",
3945 "11.1.0.2", "2001:10:1::2", "3001:10:1::2",
3946 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
3947 eep2.add_vpp_config()
3949 # external subnets reachable though eep1 and eep2 respectively
3950 VppIpRoute(self, "10.220.0.0", 24,
3951 [VppRoutePath(eep1.ip4, eep1.epg.bvi.sw_if_index)],
3952 table_id=t4.table_id).add_vpp_config()
3953 VppGbpSubnet(self, rd1, "10.220.0.0", 24,
3954 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3955 sclass=4220).add_vpp_config()
3956 VppIpRoute(self, "10:220::", 64,
3957 [VppRoutePath(eep1.ip6, eep1.epg.bvi.sw_if_index)],
3958 table_id=t6.table_id).add_vpp_config()
3959 VppGbpSubnet(self, rd1, "10:220::", 64,
3960 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3961 sclass=4220).add_vpp_config()
3962 VppIpRoute(self, "10.221.0.0", 24,
3963 [VppRoutePath(eep2.ip4, eep2.epg.bvi.sw_if_index)],
3964 table_id=t4.table_id).add_vpp_config()
3965 VppGbpSubnet(self, rd1, "10.221.0.0", 24,
3966 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3967 sclass=4221).add_vpp_config()
3968 VppIpRoute(self, "10:221::", 64,
3969 [VppRoutePath(eep2.ip6, eep2.epg.bvi.sw_if_index)],
3970 table_id=t6.table_id).add_vpp_config()
3971 VppGbpSubnet(self, rd1, "10:221::", 64,
3972 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3973 sclass=4221).add_vpp_config()
3976 # l3out redirect to remote (known, then unknown) SEP
3979 # packets from 1 external subnet to the other
3980 p = [(Ether(src=eep1.mac, dst=self.router_mac) /
3982 IP(src="10.220.0.17", dst="10.221.0.65") /
3983 UDP(sport=1234, dport=1234) /
3984 Raw(b'\xa5' * 100)),
3985 (Ether(src=eep1.mac, dst=self.router_mac) /
3987 IPv6(src="10:220::17", dst="10:221::65") /
3988 UDP(sport=1234, dport=1234) /
3989 Raw(b'\xa5' * 100))]
3991 # packets should be dropped in absence of contract
3992 self.send_and_assert_no_replies(self.pg0, p)
3994 # contract redirecting to sep5
3996 self, 402, 4220, 4221, acl_index,
3997 [VppGbpContractRule(
3998 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3999 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
4000 [VppGbpContractNextHop(sep5.vmac, sep5.epg.bd,
4001 sep5.ip4, sep5.epg.rd)]),
4003 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4004 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
4005 [VppGbpContractNextHop(sep5.vmac, sep5.epg.bd,
4006 sep5.ip6, sep5.epg.rd)])],
4007 [ETH_P_IP, ETH_P_IPV6]).add_vpp_config()
4009 rxs = self.send_and_expect(self.pg0, p, self.pg7)
4011 for rx, tx in zip(rxs, p):
4012 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4013 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4014 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4015 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4016 # this should use the programmed remote leaf TEP
4017 self.assertEqual(rx[VXLAN].vni, 555)
4018 self.assertEqual(rx[VXLAN].gpid, 4220)
4019 self.assertTrue(rx[VXLAN].flags.G)
4020 self.assertTrue(rx[VXLAN].flags.Instance)
4021 # redirect policy has been applied
4022 self.assertTrue(rx[VXLAN].gpflags.A)
4023 self.assertTrue(rx[VXLAN].gpflags.D)
4024 rxip = rx[VXLAN][Ether].payload
4025 txip = tx[Dot1Q].payload
4026 self.assertEqual(rxip.src, txip.src)
4027 self.assertEqual(rxip.dst, txip.dst)
4029 # remote SEP: it is now an unknown remote SEP and should go
4031 sep5.remove_vpp_config()
4033 rxs = self.send_and_expect(self.pg0, p, self.pg7)
4035 for rx, tx in zip(rxs, p):
4036 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4037 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4038 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4039 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4040 # this should use the spine proxy TEP
4041 self.assertEqual(rx[VXLAN].vni, epg_320.bd.uu_fwd.vni)
4042 self.assertEqual(rx[VXLAN].gpid, 4220)
4043 self.assertTrue(rx[VXLAN].flags.G)
4044 self.assertTrue(rx[VXLAN].flags.Instance)
4045 # redirect policy has been applied
4046 self.assertTrue(rx[VXLAN].gpflags.A)
4047 self.assertTrue(rx[VXLAN].gpflags.D)
4048 rxip = rx[VXLAN][Ether].payload
4049 txip = tx[Dot1Q].payload
4050 self.assertEqual(rxip.src, txip.src)
4051 self.assertEqual(rxip.dst, txip.dst)
4054 # l3out redirect to local SEP
4057 # change the contract between l3out to redirect to local SEPs
4058 # instead of remote SEP
4060 self, 402, 4220, 4221, acl_index,
4061 [VppGbpContractRule(
4062 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4063 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
4064 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
4065 sep1.ip4, sep1.epg.rd)]),
4067 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4068 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
4069 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
4070 sep1.ip6, sep1.epg.rd)])],
4071 [ETH_P_IP, ETH_P_IPV6]).add_vpp_config()
4073 rxs = self.send_and_expect(self.pg0, p, sep1.itf)
4074 for rx, tx in zip(rxs, p):
4075 self.assertEqual(rx[Ether].src, routed_src_mac)
4076 self.assertEqual(rx[Ether].dst, sep1.mac)
4077 rxip = rx[Ether].payload
4078 txip = tx[Ether].payload
4079 self.assertEqual(rxip.src, txip.src)
4080 self.assertEqual(rxip.dst, txip.dst)
4083 # redirect remote EP to remote (known then unknown) SEP
4086 # remote SEP known again
4087 sep5.add_vpp_config()
4089 # contract to redirect to learnt SEP
4091 self, 402, epg_221.sclass, epg_222.sclass, acl_index,
4092 [VppGbpContractRule(
4093 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4094 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
4095 [VppGbpContractNextHop(sep5.vmac, sep5.epg.bd,
4096 sep5.ip4, sep5.epg.rd)]),
4098 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4099 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
4100 [VppGbpContractNextHop(sep5.vmac, sep5.epg.bd,
4101 sep5.ip6, sep5.epg.rd)])],
4102 [ETH_P_IP, ETH_P_IPV6]).add_vpp_config()
4104 # packets from unknown EP 221 to known EP in EPG 222
4105 # should be redirected to known remote SEP
4106 base = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
4107 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
4108 UDP(sport=1234, dport=48879) /
4109 VXLAN(vni=444, gpid=441, flags=0x88) /
4110 Ether(src="00:22:22:22:22:44", dst=str(self.router_mac)))
4112 IP(src="10.0.1.100", dst=ep3.ip4) /
4113 UDP(sport=1234, dport=1234) /
4114 Raw(b'\xa5' * 100)),
4116 IPv6(src="2001:10::100", dst=ep3.ip6) /
4117 UDP(sport=1234, dport=1234) /
4118 Raw(b'\xa5' * 100))]
4120 # unknown remote EP to local EP redirected to known remote SEP
4121 rxs = self.send_and_expect(self.pg7, p, self.pg7)
4123 for rx, tx in zip(rxs, p):
4124 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4125 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4126 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4127 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4128 # this should use the programmed remote leaf TEP
4129 self.assertEqual(rx[VXLAN].vni, 555)
4130 self.assertEqual(rx[VXLAN].gpid, epg_221.sclass)
4131 self.assertTrue(rx[VXLAN].flags.G)
4132 self.assertTrue(rx[VXLAN].flags.Instance)
4133 # redirect policy has been applied
4134 self.assertTrue(rx[VXLAN].gpflags.A)
4135 self.assertFalse(rx[VXLAN].gpflags.D)
4136 rxip = rx[VXLAN][Ether].payload
4137 txip = tx[VXLAN][Ether].payload
4138 self.assertEqual(rxip.src, txip.src)
4139 self.assertEqual(rxip.dst, txip.dst)
4141 # endpoint learnt via the parent GBP-vxlan interface
4142 self.assertTrue(find_gbp_endpoint(self,
4143 vx_tun_l3._sw_if_index,
4145 self.assertTrue(find_gbp_endpoint(self,
4146 vx_tun_l3._sw_if_index,
4149 # remote SEP: it is now an unknown remote SEP and should go
4151 sep5.remove_vpp_config()
4153 # remote EP (coming from spine proxy) to local EP redirected to
4155 rxs = self.send_and_expect(self.pg7, p, self.pg7)
4157 for rx, tx in zip(rxs, p):
4158 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4159 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4160 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4161 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4162 # this should use the spine proxy TEP
4163 self.assertEqual(rx[VXLAN].vni, epg_320.bd.uu_fwd.vni)
4164 self.assertEqual(rx[VXLAN].gpid, epg_221.sclass)
4165 self.assertTrue(rx[VXLAN].flags.G)
4166 self.assertTrue(rx[VXLAN].flags.Instance)
4167 # redirect policy has been applied
4168 self.assertTrue(rx[VXLAN].gpflags.A)
4169 self.assertFalse(rx[VXLAN].gpflags.D)
4170 rxip = rx[VXLAN][Ether].payload
4171 txip = tx[VXLAN][Ether].payload
4172 self.assertEqual(rxip.src, txip.src)
4173 self.assertEqual(rxip.dst, txip.dst)
4178 self.pg7.unconfig_ip4()
4180 def test_gbp_redirect_extended(self):
4181 """ GBP Endpoint Redirect Extended """
4183 self.vapi.cli("set logging class gbp level debug")
4185 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
4186 routed_dst_mac = "00:0c:0c:0c:0c:0c"
4187 routed_src_mac = "00:22:bd:f8:19:ff"
4189 learnt = [{'mac': '00:00:11:11:11:02',
4191 'ip6': '2001:10::2'},
4192 {'mac': '00:00:11:11:11:03',
4194 'ip6': '2001:10::3'}]
4199 t4 = VppIpTable(self, 1)
4201 t6 = VppIpTable(self, 1, True)
4204 # create IPv4 and IPv6 RD UU VxLAN-GBP TEP and bind them to the right
4206 rd_uu4 = VppVxlanGbpTunnel(
4209 self.pg7.remote_ip4,
4211 mode=(VppEnum.vl_api_vxlan_gbp_api_tunnel_mode_t.
4212 VXLAN_GBP_API_TUNNEL_MODE_L3))
4213 rd_uu4.add_vpp_config()
4214 VppIpInterfaceBind(self, rd_uu4, t4).add_vpp_config()
4216 rd_uu6 = VppVxlanGbpTunnel(
4219 self.pg7.remote_ip4,
4221 mode=(VppEnum.vl_api_vxlan_gbp_api_tunnel_mode_t.
4222 VXLAN_GBP_API_TUNNEL_MODE_L3))
4223 rd_uu6.add_vpp_config()
4224 VppIpInterfaceBind(self, rd_uu6, t4).add_vpp_config()
4226 rd1 = VppGbpRouteDomain(self, 2, 402, t4, t6, rd_uu4, rd_uu6)
4227 rd1.add_vpp_config()
4229 self.loop0.set_mac(self.router_mac)
4230 self.loop1.set_mac(self.router_mac)
4231 self.loop2.set_mac(self.router_mac)
4234 # Bind the BVI to the RD
4236 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
4237 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
4238 VppIpInterfaceBind(self, self.loop1, t4).add_vpp_config()
4239 VppIpInterfaceBind(self, self.loop1, t6).add_vpp_config()
4240 VppIpInterfaceBind(self, self.loop2, t4).add_vpp_config()
4241 VppIpInterfaceBind(self, self.loop2, t6).add_vpp_config()
4244 # Pg7 hosts a BD's UU-fwd
4246 self.pg7.config_ip4()
4247 self.pg7.resolve_arp()
4250 # a GBP bridge domains for the EPs
4252 bd1 = VppBridgeDomain(self, 1)
4253 bd1.add_vpp_config()
4254 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0)
4255 gbd1.add_vpp_config()
4257 bd2 = VppBridgeDomain(self, 2)
4258 bd2.add_vpp_config()
4259 gbd2 = VppGbpBridgeDomain(self, bd2, rd1, self.loop1)
4260 gbd2.add_vpp_config()
4262 # ... and has a /32 and /128 applied
4263 ip4_addr1 = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
4264 ip4_addr1.add_vpp_config()
4265 ip6_addr1 = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 128)
4266 ip6_addr1.add_vpp_config()
4267 ip4_addr2 = VppIpInterfaceAddress(self, gbd2.bvi, "10.0.1.128", 32)
4268 ip4_addr2.add_vpp_config()
4269 ip6_addr2 = VppIpInterfaceAddress(self, gbd2.bvi, "2001:11::128", 128)
4270 ip6_addr2.add_vpp_config()
4273 # The Endpoint-groups
4275 epg_220 = VppGbpEndpointGroup(self, 220, 440, rd1, gbd1,
4279 VppGbpEndpointRetention(2))
4280 epg_220.add_vpp_config()
4281 epg_221 = VppGbpEndpointGroup(self, 221, 441, rd1, gbd2,
4285 VppGbpEndpointRetention(2))
4286 epg_221.add_vpp_config()
4289 # a GBP bridge domains for the SEPs
4291 bd_uu3 = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
4292 self.pg7.remote_ip4, 116)
4293 bd_uu3.add_vpp_config()
4295 bd3 = VppBridgeDomain(self, 3)
4296 bd3.add_vpp_config()
4297 gbd3 = VppGbpBridgeDomain(self, bd3, rd1, self.loop2,
4298 bd_uu3, learn=False)
4299 gbd3.add_vpp_config()
4301 ip4_addr3 = VppIpInterfaceAddress(self, gbd3.bvi, "12.0.0.128", 32)
4302 ip4_addr3.add_vpp_config()
4303 ip6_addr3 = VppIpInterfaceAddress(self, gbd3.bvi, "4001:10::128", 128)
4304 ip6_addr3.add_vpp_config()
4307 # self.logger.info(self.vapi.cli("show gbp bridge"))
4308 # self.logger.info(self.vapi.cli("show vxlan-gbp tunnel"))
4309 # self.logger.info(self.vapi.cli("show gbp vxlan"))
4310 # self.logger.info(self.vapi.cli("show int addr"))
4314 # EPGs in which the service endpoints exist
4316 epg_320 = VppGbpEndpointGroup(self, 320, 550, rd1, gbd3,
4320 VppGbpEndpointRetention(2))
4321 epg_320.add_vpp_config()
4326 ep1 = VppGbpEndpoint(self, self.pg0,
4328 "10.0.0.1", "11.0.0.1",
4329 "2001:10::1", "3001:10::1")
4330 ep1.add_vpp_config()
4331 ep2 = VppGbpEndpoint(self, self.pg1,
4333 "10.0.1.1", "11.0.1.1",
4334 "2001:11::1", "3001:11::1")
4335 ep2.add_vpp_config()
4340 sep1 = VppGbpEndpoint(self, self.pg3,
4342 "12.0.0.1", "13.0.0.1",
4343 "4001:10::1", "5001:10::1")
4344 sep2 = VppGbpEndpoint(self, self.pg4,
4346 "12.0.0.2", "13.0.0.2",
4347 "4001:10::2", "5001:10::2")
4349 # sep1 and sep2 are not added to config yet
4350 # they are unknown for now
4353 # add routes to EPG subnets
4355 VppGbpSubnet(self, rd1, "10.0.0.0", 24,
4356 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT
4358 VppGbpSubnet(self, rd1, "10.0.1.0", 24,
4359 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT
4363 # Local host to known local host in different BD
4364 # with SFC contract (source and destination are in
4365 # one node and service endpoint in another node)
4367 p4 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
4368 IP(src=ep1.ip4, dst=ep2.ip4) /
4369 UDP(sport=1234, dport=1234) /
4370 Raw(b'\xa5' * 100)),
4371 (Ether(src=ep2.mac, dst=str(self.router_mac)) /
4372 IP(src=ep2.ip4, dst=ep1.ip4) /
4373 UDP(sport=1234, dport=1234) /
4374 Raw(b'\xa5' * 100))]
4375 p6 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
4376 IPv6(src=ep1.ip6, dst=ep2.ip6) /
4377 UDP(sport=1234, dport=1234) /
4378 Raw(b'\xa5' * 100)),
4379 (Ether(src=ep2.mac, dst=str(self.router_mac)) /
4380 IPv6(src=ep2.ip6, dst=ep1.ip6) /
4381 UDP(sport=1234, dport=1230) /
4382 Raw(b'\xa5' * 100))]
4384 # should be dropped since no contract yet
4385 self.send_and_assert_no_replies(self.pg0, [p4[0]])
4386 self.send_and_assert_no_replies(self.pg0, [p6[0]])
4389 # Add a contract with a rule to load-balance redirect via SEP1 and SEP2
4390 # one of the next-hops is via an EP that is not known
4392 acl = VppGbpAcl(self)
4393 rule4 = acl.create_rule(permit_deny=1, proto=17)
4394 rule6 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
4395 acl_index = acl.add_vpp_config([rule4, rule6])
4398 # test the src-ip hash mode
4400 c1 = VppGbpContract(
4401 self, 402, epg_220.sclass, epg_221.sclass, acl_index,
4402 [VppGbpContractRule(
4403 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4404 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
4405 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
4406 sep1.ip4, sep1.epg.rd)]),
4408 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4409 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
4410 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
4411 sep1.ip6, sep1.epg.rd)])],
4412 [ETH_P_IP, ETH_P_IPV6])
4415 c2 = VppGbpContract(
4416 self, 402, epg_221.sclass, epg_220.sclass, acl_index,
4417 [VppGbpContractRule(
4418 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4419 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
4420 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
4421 sep1.ip4, sep1.epg.rd)]),
4423 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
4424 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
4425 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
4426 sep1.ip6, sep1.epg.rd)])],
4427 [ETH_P_IP, ETH_P_IPV6])
4430 # ep1 <--> ep2 redirected through sep1
4432 # packet is redirected to sep bd and then go through sep bd UU
4434 rxs = self.send_and_expect(self.pg0, p4[0] * 17, self.pg7)
4437 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4438 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4439 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4440 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4441 self.assertEqual(rx[VXLAN].vni, 116)
4442 self.assertTrue(rx[VXLAN].flags.G)
4443 self.assertTrue(rx[VXLAN].flags.Instance)
4444 # redirect policy has been applied
4445 self.assertTrue(rx[VXLAN].gpflags.A)
4446 self.assertFalse(rx[VXLAN].gpflags.D)
4448 inner = rx[VXLAN].payload
4450 self.assertEqual(inner[Ether].src, routed_src_mac)
4451 self.assertEqual(inner[Ether].dst, sep1.mac)
4452 self.assertEqual(inner[IP].src, ep1.ip4)
4453 self.assertEqual(inner[IP].dst, ep2.ip4)
4455 rxs = self.send_and_expect(self.pg1, p4[1] * 17, self.pg7)
4458 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4459 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4460 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4461 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4462 self.assertEqual(rx[VXLAN].vni, 116)
4463 self.assertTrue(rx[VXLAN].flags.G)
4464 self.assertTrue(rx[VXLAN].flags.Instance)
4465 # redirect policy has been applied
4466 self.assertTrue(rx[VXLAN].gpflags.A)
4467 self.assertFalse(rx[VXLAN].gpflags.D)
4469 inner = rx[VXLAN].payload
4471 self.assertEqual(inner[Ether].src, routed_src_mac)
4472 self.assertEqual(inner[Ether].dst, sep1.mac)
4473 self.assertEqual(inner[IP].src, ep2.ip4)
4474 self.assertEqual(inner[IP].dst, ep1.ip4)
4476 rxs = self.send_and_expect(self.pg0, p6[0] * 17, self.pg7)
4479 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4480 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4481 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4482 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4483 self.assertEqual(rx[VXLAN].vni, 116)
4484 self.assertTrue(rx[VXLAN].flags.G)
4485 self.assertTrue(rx[VXLAN].flags.Instance)
4486 # redirect policy has been applied
4487 inner = rx[VXLAN].payload
4489 self.assertEqual(inner[Ether].src, routed_src_mac)
4490 self.assertEqual(inner[Ether].dst, sep1.mac)
4491 self.assertEqual(inner[IPv6].src, ep1.ip6)
4492 self.assertEqual(inner[IPv6].dst, ep2.ip6)
4494 rxs = self.send_and_expect(self.pg1, p6[1] * 17, self.pg7)
4497 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4498 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4499 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4500 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4501 self.assertEqual(rx[VXLAN].vni, 116)
4502 self.assertTrue(rx[VXLAN].flags.G)
4503 self.assertTrue(rx[VXLAN].flags.Instance)
4504 # redirect policy has been applied
4505 self.assertTrue(rx[VXLAN].gpflags.A)
4506 self.assertFalse(rx[VXLAN].gpflags.D)
4508 inner = rx[VXLAN].payload
4510 self.assertEqual(inner[Ether].src, routed_src_mac)
4511 self.assertEqual(inner[Ether].dst, sep1.mac)
4512 self.assertEqual(inner[IPv6].src, ep2.ip6)
4513 self.assertEqual(inner[IPv6].dst, ep1.ip6)
4515 # configure sep1: it is now local
4516 # packets between ep1 and ep2 are redirected locally
4517 sep1.add_vpp_config()
4519 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
4522 self.assertEqual(rx[Ether].src, routed_src_mac)
4523 self.assertEqual(rx[Ether].dst, sep1.mac)
4524 self.assertEqual(rx[IP].src, ep1.ip4)
4525 self.assertEqual(rx[IP].dst, ep2.ip4)
4527 rxs = self.send_and_expect(self.pg1, p6[1] * 17, sep1.itf)
4530 self.assertEqual(rx[Ether].src, routed_src_mac)
4531 self.assertEqual(rx[Ether].dst, sep1.mac)
4532 self.assertEqual(rx[IPv6].src, ep2.ip6)
4533 self.assertEqual(rx[IPv6].dst, ep1.ip6)
4535 # packet coming from the l2 spine-proxy to sep1
4536 p = (Ether(src=self.pg7.remote_mac,
4537 dst=self.pg7.local_mac) /
4538 IP(src=self.pg7.remote_ip4,
4539 dst=self.pg7.local_ip4) /
4540 UDP(sport=1234, dport=48879) /
4541 VXLAN(vni=116, gpid=440, gpflags=0x08, flags=0x88) /
4542 Ether(src=str(self.router_mac), dst=sep1.mac) /
4543 IP(src=ep1.ip4, dst=ep2.ip4) /
4544 UDP(sport=1234, dport=1234) /
4547 rxs = self.send_and_expect(self.pg7, [p] * 17, sep1.itf)
4550 self.assertEqual(rx[Ether].src, str(self.router_mac))
4551 self.assertEqual(rx[Ether].dst, sep1.mac)
4552 self.assertEqual(rx[IP].src, ep1.ip4)
4553 self.assertEqual(rx[IP].dst, ep2.ip4)
4555 # contract for SEP to communicate with dst EP
4556 c3 = VppGbpContract(
4557 self, 402, epg_320.sclass, epg_221.sclass, acl_index,
4558 [VppGbpContractRule(
4559 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4560 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC),
4562 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4563 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC)],
4564 [ETH_P_IP, ETH_P_IPV6])
4567 # temporarily remove ep2, so that ep2 is remote & unknown
4568 ep2.remove_vpp_config()
4570 # packet going back from sep1 to its original dest (ep2)
4571 # as ep2 is now unknown (see above), it must go through
4572 # the rd UU (packet is routed)
4574 p1 = (Ether(src=sep1.mac, dst=self.router_mac) /
4575 IP(src=ep1.ip4, dst=ep2.ip4) /
4576 UDP(sport=1234, dport=1234) /
4579 rxs = self.send_and_expect(self.pg3, [p1] * 17, self.pg7)
4582 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4583 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4584 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4585 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4586 self.assertEqual(rx[VXLAN].vni, 114)
4587 self.assertTrue(rx[VXLAN].flags.G)
4588 self.assertTrue(rx[VXLAN].flags.Instance)
4589 # redirect policy has been applied
4590 inner = rx[VXLAN].payload
4591 self.assertEqual(inner[Ether].src, routed_src_mac)
4592 self.assertEqual(inner[Ether].dst, routed_dst_mac)
4593 self.assertEqual(inner[IP].src, ep1.ip4)
4594 self.assertEqual(inner[IP].dst, ep2.ip4)
4596 self.logger.info(self.vapi.cli("show bridge 3 detail"))
4597 sep1.remove_vpp_config()
4599 self.logger.info(self.vapi.cli("show bridge 1 detail"))
4600 self.logger.info(self.vapi.cli("show bridge 2 detail"))
4602 # re-add ep2: it is local again :)
4603 ep2.add_vpp_config()
4605 # packet coming back from the remote sep through rd UU
4606 p2 = (Ether(src=self.pg7.remote_mac,
4607 dst=self.pg7.local_mac) /
4608 IP(src=self.pg7.remote_ip4,
4609 dst=self.pg7.local_ip4) /
4610 UDP(sport=1234, dport=48879) /
4611 VXLAN(vni=114, gpid=441, gpflags=0x09, flags=0x88) /
4612 Ether(src=str(self.router_mac), dst=self.router_mac) /
4613 IP(src=ep1.ip4, dst=ep2.ip4) /
4614 UDP(sport=1234, dport=1234) /
4617 rxs = self.send_and_expect(self.pg7, [p2], self.pg1)
4620 self.assertEqual(rx[Ether].src, str(self.router_mac))
4621 self.assertEqual(rx[Ether].dst, self.pg1.remote_mac)
4622 self.assertEqual(rx[IP].src, ep1.ip4)
4623 self.assertEqual(rx[IP].dst, ep2.ip4)
4626 # bd_uu2.add_vpp_config()
4632 c1.remove_vpp_config()
4633 c2.remove_vpp_config()
4634 c3.remove_vpp_config()
4635 self.pg7.unconfig_ip4()
4637 def test_gbp_l3_out(self):
4640 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
4641 self.vapi.cli("set logging class gbp level debug")
4643 routed_dst_mac = "00:0c:0c:0c:0c:0c"
4644 routed_src_mac = "00:22:bd:f8:19:ff"
4649 t4 = VppIpTable(self, 1)
4651 t6 = VppIpTable(self, 1, True)
4654 rd1 = VppGbpRouteDomain(self, 2, 55, t4, t6)
4655 rd1.add_vpp_config()
4657 self.loop0.set_mac(self.router_mac)
4660 # Bind the BVI to the RD
4662 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
4663 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
4666 # Pg7 hosts a BD's BUM
4667 # Pg1 some other l3 interface
4669 self.pg7.config_ip4()
4670 self.pg7.resolve_arp()
4673 # a multicast vxlan-gbp tunnel for broadcast in the BD
4675 tun_bm = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
4678 tun_bm.add_vpp_config()
4681 # a GBP external bridge domains for the EPs
4683 bd1 = VppBridgeDomain(self, 1)
4684 bd1.add_vpp_config()
4685 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0, None, tun_bm)
4686 gbd1.add_vpp_config()
4689 # The Endpoint-groups in which the external endpoints exist
4691 epg_220 = VppGbpEndpointGroup(self, 220, 113, rd1, gbd1,
4695 VppGbpEndpointRetention(2))
4696 epg_220.add_vpp_config()
4698 # the BVIs have the subnets applied ...
4699 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 24)
4700 ip4_addr.add_vpp_config()
4701 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 64)
4702 ip6_addr.add_vpp_config()
4704 # ... which are L3-out subnets
4705 l3o_1 = VppGbpSubnet(
4706 self, rd1, "10.0.0.0", 24,
4707 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
4709 l3o_1.add_vpp_config()
4712 # an external interface attached to the outside world and the
4715 VppL2Vtr(self, self.vlan_100, L2_VTR_OP.L2_POP_1).add_vpp_config()
4716 VppL2Vtr(self, self.vlan_101, L2_VTR_OP.L2_POP_1).add_vpp_config()
4717 vlan_144 = VppDot1QSubint(self, self.pg0, 144)
4719 # vlan_102 is not poped
4722 # an unicast vxlan-gbp for inter-RD traffic
4724 vx_tun_l3 = VppGbpVxlanTunnel(
4725 self, 444, rd1.rd_id,
4726 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
4728 vx_tun_l3.add_vpp_config()
4731 # External Endpoints
4733 eep1 = VppGbpEndpoint(self, self.vlan_100,
4735 "10.0.0.1", "11.0.0.1",
4736 "2001:10::1", "3001::1",
4737 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
4738 eep1.add_vpp_config()
4739 eep2 = VppGbpEndpoint(self, self.vlan_101,
4741 "10.0.0.2", "11.0.0.2",
4742 "2001:10::2", "3001::2",
4743 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
4744 eep2.add_vpp_config()
4745 eep3 = VppGbpEndpoint(self, self.vlan_102,
4747 "10.0.0.3", "11.0.0.3",
4748 "2001:10::3", "3001::3",
4749 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
4750 eep3.add_vpp_config()
4753 # A remote external endpoint
4755 rep = VppGbpEndpoint(self, vx_tun_l3,
4757 "10.0.0.101", "11.0.0.101",
4758 "2001:10::101", "3001::101",
4759 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
4761 self.pg7.remote_ip4,
4763 rep.add_vpp_config()
4766 # EP1 impersonating EP3 is dropped
4768 p = (Ether(src=eep1.mac, dst="ff:ff:ff:ff:ff:ff") /
4771 psrc="10.0.0.3", pdst="10.0.0.128",
4772 hwsrc=eep1.mac, hwdst="ff:ff:ff:ff:ff:ff"))
4773 self.send_and_assert_no_replies(self.pg0, p)
4776 # ARP packet from External EPs are accepted and replied to
4778 p_arp = (Ether(src=eep1.mac, dst="ff:ff:ff:ff:ff:ff") /
4781 psrc=eep1.ip4, pdst="10.0.0.128",
4782 hwsrc=eep1.mac, hwdst="ff:ff:ff:ff:ff:ff"))
4783 rxs = self.send_and_expect(self.pg0, p_arp * 1, self.pg0)
4786 # ARP packet from host in remote subnet are accepted and replied to
4788 p_arp = (Ether(src=eep3.mac, dst="ff:ff:ff:ff:ff:ff") /
4791 psrc=eep3.ip4, pdst="10.0.0.128",
4792 hwsrc=eep3.mac, hwdst="ff:ff:ff:ff:ff:ff"))
4793 rxs = self.send_and_expect(self.pg0, p_arp * 1, self.pg0)
4796 # packets destined to unknown addresses in the BVI's subnet
4799 p4 = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
4801 IP(src="10.0.0.1", dst="10.0.0.88") /
4802 UDP(sport=1234, dport=1234) /
4804 p6 = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
4806 IPv6(src="2001:10::1", dst="2001:10::88") /
4807 UDP(sport=1234, dport=1234) /
4810 rxs = self.send_and_expect(self.pg0, p4 * 1, self.pg7)
4813 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4814 # self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4815 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4816 self.assertEqual(rx[IP].dst, "239.1.1.1")
4817 self.assertEqual(rx[VXLAN].vni, 88)
4818 self.assertTrue(rx[VXLAN].flags.G)
4819 self.assertTrue(rx[VXLAN].flags.Instance)
4820 # policy was applied to the original IP packet
4821 self.assertEqual(rx[VXLAN].gpid, 113)
4822 self.assertTrue(rx[VXLAN].gpflags.A)
4823 self.assertFalse(rx[VXLAN].gpflags.D)
4825 inner = rx[VXLAN].payload
4827 self.assertTrue(inner.haslayer(ARP))
4830 # remote to external
4832 p = (Ether(src=self.pg7.remote_mac,
4833 dst=self.pg7.local_mac) /
4834 IP(src=self.pg7.remote_ip4,
4835 dst=self.pg7.local_ip4) /
4836 UDP(sport=1234, dport=48879) /
4837 VXLAN(vni=444, gpid=113, flags=0x88) /
4838 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
4839 IP(src="10.0.0.101", dst="10.0.0.1") /
4840 UDP(sport=1234, dport=1234) /
4843 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
4846 # local EP pings router
4848 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
4850 IP(src=eep1.ip4, dst="10.0.0.128") /
4851 ICMP(type='echo-request'))
4853 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
4856 self.assertEqual(rx[Ether].src, str(self.router_mac))
4857 self.assertEqual(rx[Ether].dst, eep1.mac)
4858 self.assertEqual(rx[Dot1Q].vlan, 100)
4861 # local EP pings other local EP
4863 p = (Ether(src=eep1.mac, dst=eep2.mac) /
4865 IP(src=eep1.ip4, dst=eep2.ip4) /
4866 ICMP(type='echo-request'))
4868 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
4871 self.assertEqual(rx[Ether].src, eep1.mac)
4872 self.assertEqual(rx[Ether].dst, eep2.mac)
4873 self.assertEqual(rx[Dot1Q].vlan, 101)
4876 # local EP pings router w/o vlan tag poped
4878 p = (Ether(src=eep3.mac, dst=str(self.router_mac)) /
4880 IP(src=eep3.ip4, dst="10.0.0.128") /
4881 ICMP(type='echo-request'))
4883 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
4886 self.assertEqual(rx[Ether].src, str(self.router_mac))
4887 self.assertEqual(rx[Ether].dst, self.vlan_102.remote_mac)
4890 # A ip4 subnet reachable through the external EP1
4892 ip_220 = VppIpRoute(self, "10.220.0.0", 24,
4893 [VppRoutePath(eep1.ip4,
4894 eep1.epg.bvi.sw_if_index)],
4895 table_id=t4.table_id)
4896 ip_220.add_vpp_config()
4898 l3o_220 = VppGbpSubnet(
4899 self, rd1, "10.220.0.0", 24,
4900 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
4902 l3o_220.add_vpp_config()
4905 # An ip6 subnet reachable through the external EP1
4907 ip6_220 = VppIpRoute(self, "10:220::", 64,
4908 [VppRoutePath(eep1.ip6,
4909 eep1.epg.bvi.sw_if_index)],
4910 table_id=t6.table_id)
4911 ip6_220.add_vpp_config()
4913 l3o6_220 = VppGbpSubnet(
4914 self, rd1, "10:220::", 64,
4915 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
4917 l3o6_220.add_vpp_config()
4920 # A subnet reachable through the external EP2
4922 ip_221 = VppIpRoute(self, "10.221.0.0", 24,
4923 [VppRoutePath(eep2.ip4,
4924 eep2.epg.bvi.sw_if_index)],
4925 table_id=t4.table_id)
4926 ip_221.add_vpp_config()
4928 l3o_221 = VppGbpSubnet(
4929 self, rd1, "10.221.0.0", 24,
4930 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
4932 l3o_221.add_vpp_config()
4935 # ping between hosts in remote subnets
4936 # dropped without a contract
4938 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
4940 IP(src="10.220.0.1", dst="10.221.0.1") /
4941 ICMP(type='echo-request'))
4943 self.send_and_assert_no_replies(self.pg0, p * 1)
4946 # contract for the external nets to communicate
4948 acl = VppGbpAcl(self)
4949 rule4 = acl.create_rule(permit_deny=1, proto=17)
4950 rule6 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
4951 acl_index = acl.add_vpp_config([rule4, rule6])
4954 # A contract with the wrong scope is not matched
4956 c_44 = VppGbpContract(
4957 self, 44, 4220, 4221, acl_index,
4958 [VppGbpContractRule(
4959 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4960 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4963 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4964 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4966 [ETH_P_IP, ETH_P_IPV6])
4967 c_44.add_vpp_config()
4968 self.send_and_assert_no_replies(self.pg0, p * 1)
4970 c1 = VppGbpContract(
4971 self, 55, 4220, 4221, acl_index,
4972 [VppGbpContractRule(
4973 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4974 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4977 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4978 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4980 [ETH_P_IP, ETH_P_IPV6])
4984 # Contracts allowing ext-net 200 to talk with external EPs
4986 c2 = VppGbpContract(
4987 self, 55, 4220, 113, acl_index,
4988 [VppGbpContractRule(
4989 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4990 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4993 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
4994 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
4996 [ETH_P_IP, ETH_P_IPV6])
4998 c3 = VppGbpContract(
4999 self, 55, 113, 4220, acl_index,
5000 [VppGbpContractRule(
5001 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5002 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5005 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5006 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5008 [ETH_P_IP, ETH_P_IPV6])
5012 # ping between hosts in remote subnets
5014 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
5016 IP(src="10.220.0.1", dst="10.221.0.1") /
5017 UDP(sport=1234, dport=1234) /
5020 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
5023 self.assertEqual(rx[Ether].src, str(self.router_mac))
5024 self.assertEqual(rx[Ether].dst, eep2.mac)
5025 self.assertEqual(rx[Dot1Q].vlan, 101)
5027 # we did not learn these external hosts
5028 self.assertFalse(find_gbp_endpoint(self, ip="10.220.0.1"))
5029 self.assertFalse(find_gbp_endpoint(self, ip="10.221.0.1"))
5032 # from remote external EP to local external EP
5034 p = (Ether(src=self.pg7.remote_mac,
5035 dst=self.pg7.local_mac) /
5036 IP(src=self.pg7.remote_ip4,
5037 dst=self.pg7.local_ip4) /
5038 UDP(sport=1234, dport=48879) /
5039 VXLAN(vni=444, gpid=113, flags=0x88) /
5040 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
5041 IP(src="10.0.0.101", dst="10.220.0.1") /
5042 UDP(sport=1234, dport=1234) /
5045 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
5048 # ping from an external host to the remote external EP
5050 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
5052 IP(src="10.220.0.1", dst=rep.ip4) /
5053 UDP(sport=1234, dport=1234) /
5056 rxs = self.send_and_expect(self.pg0, p * 1, self.pg7)
5059 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
5060 # self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
5061 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
5062 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
5063 self.assertEqual(rx[VXLAN].vni, 444)
5064 self.assertTrue(rx[VXLAN].flags.G)
5065 self.assertTrue(rx[VXLAN].flags.Instance)
5066 # the sclass of the ext-net the packet came from
5067 self.assertEqual(rx[VXLAN].gpid, 4220)
5068 # policy was applied to the original IP packet
5069 self.assertTrue(rx[VXLAN].gpflags.A)
5070 # since it's an external host the reciever should not learn it
5071 self.assertTrue(rx[VXLAN].gpflags.D)
5072 inner = rx[VXLAN].payload
5073 self.assertEqual(inner[IP].src, "10.220.0.1")
5074 self.assertEqual(inner[IP].dst, rep.ip4)
5077 # An external subnet reachable via the remote external EP
5081 # first the VXLAN-GBP tunnel over which it is reached
5083 vx_tun_r1 = VppVxlanGbpTunnel(
5084 self, self.pg7.local_ip4,
5085 self.pg7.remote_ip4, 445,
5086 mode=(VppEnum.vl_api_vxlan_gbp_api_tunnel_mode_t.
5087 VXLAN_GBP_API_TUNNEL_MODE_L3))
5088 vx_tun_r1.add_vpp_config()
5089 VppIpInterfaceBind(self, vx_tun_r1, t4).add_vpp_config()
5091 self.logger.info(self.vapi.cli("sh vxlan-gbp tunnel"))
5094 # then the special adj to resolve through on that tunnel
5096 n1 = VppNeighbor(self,
5097 vx_tun_r1.sw_if_index,
5098 "00:0c:0c:0c:0c:0c",
5099 self.pg7.remote_ip4)
5103 # the route via the adj above
5105 ip_222 = VppIpRoute(self, "10.222.0.0", 24,
5106 [VppRoutePath(self.pg7.remote_ip4,
5107 vx_tun_r1.sw_if_index)],
5108 table_id=t4.table_id)
5109 ip_222.add_vpp_config()
5111 l3o_222 = VppGbpSubnet(
5112 self, rd1, "10.222.0.0", 24,
5113 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
5115 l3o_222.add_vpp_config()
5118 # ping between hosts in local and remote external subnets
5119 # dropped without a contract
5121 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
5123 IP(src="10.220.0.1", dst="10.222.0.1") /
5124 UDP(sport=1234, dport=1234) /
5127 rxs = self.send_and_assert_no_replies(self.pg0, p * 1)
5130 # Add contracts ext-nets for 220 -> 222
5132 c4 = VppGbpContract(
5133 self, 55, 4220, 4222, acl_index,
5134 [VppGbpContractRule(
5135 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5136 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5139 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5140 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5142 [ETH_P_IP, ETH_P_IPV6])
5146 # ping from host in local to remote external subnets
5148 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
5150 IP(src="10.220.0.1", dst="10.222.0.1") /
5151 UDP(sport=1234, dport=1234) /
5154 rxs = self.send_and_expect(self.pg0, p * 3, self.pg7)
5157 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
5158 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
5159 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
5160 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
5161 self.assertEqual(rx[VXLAN].vni, 445)
5162 self.assertTrue(rx[VXLAN].flags.G)
5163 self.assertTrue(rx[VXLAN].flags.Instance)
5164 # the sclass of the ext-net the packet came from
5165 self.assertEqual(rx[VXLAN].gpid, 4220)
5166 # policy was applied to the original IP packet
5167 self.assertTrue(rx[VXLAN].gpflags.A)
5168 # since it's an external host the reciever should not learn it
5169 self.assertTrue(rx[VXLAN].gpflags.D)
5170 inner = rx[VXLAN].payload
5171 self.assertEqual(inner[Ether].dst, "00:0c:0c:0c:0c:0c")
5172 self.assertEqual(inner[IP].src, "10.220.0.1")
5173 self.assertEqual(inner[IP].dst, "10.222.0.1")
5176 # make the external subnet ECMP
5178 vx_tun_r2 = VppVxlanGbpTunnel(
5179 self, self.pg7.local_ip4,
5180 self.pg7.remote_ip4, 446,
5181 mode=(VppEnum.vl_api_vxlan_gbp_api_tunnel_mode_t.
5182 VXLAN_GBP_API_TUNNEL_MODE_L3))
5183 vx_tun_r2.add_vpp_config()
5184 VppIpInterfaceBind(self, vx_tun_r2, t4).add_vpp_config()
5186 self.logger.info(self.vapi.cli("sh vxlan-gbp tunnel"))
5188 n2 = VppNeighbor(self,
5189 vx_tun_r2.sw_if_index,
5190 "00:0c:0c:0c:0c:0c",
5191 self.pg7.remote_ip4)
5194 ip_222.modify([VppRoutePath(self.pg7.remote_ip4,
5195 vx_tun_r1.sw_if_index),
5196 VppRoutePath(self.pg7.remote_ip4,
5197 vx_tun_r2.sw_if_index)])
5200 # now expect load-balance
5202 p = [(Ether(src=eep1.mac, dst=str(self.router_mac)) /
5204 IP(src="10.220.0.1", dst="10.222.0.1") /
5205 UDP(sport=1234, dport=1234) /
5206 Raw(b'\xa5' * 100)),
5207 (Ether(src=eep1.mac, dst=str(self.router_mac)) /
5209 IP(src="10.220.0.1", dst="10.222.0.1") /
5210 UDP(sport=1222, dport=1235) /
5211 Raw(b'\xa5' * 100))]
5213 rxs = self.send_and_expect(self.pg0, p, self.pg7)
5215 self.assertEqual(rxs[0][VXLAN].vni, 445)
5216 self.assertEqual(rxs[1][VXLAN].vni, 446)
5219 # Same LB test for v6
5221 n3 = VppNeighbor(self,
5222 vx_tun_r1.sw_if_index,
5223 "00:0c:0c:0c:0c:0c",
5224 self.pg7.remote_ip6)
5226 n4 = VppNeighbor(self,
5227 vx_tun_r2.sw_if_index,
5228 "00:0c:0c:0c:0c:0c",
5229 self.pg7.remote_ip6)
5232 ip_222_6 = VppIpRoute(self, "10:222::", 64,
5233 [VppRoutePath(self.pg7.remote_ip6,
5234 vx_tun_r1.sw_if_index),
5235 VppRoutePath(self.pg7.remote_ip6,
5236 vx_tun_r2.sw_if_index)],
5237 table_id=t6.table_id)
5238 ip_222_6.add_vpp_config()
5240 l3o_222_6 = VppGbpSubnet(
5241 self, rd1, "10:222::", 64,
5242 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
5244 l3o_222_6.add_vpp_config()
5246 p = [(Ether(src=eep1.mac, dst=str(self.router_mac)) /
5248 IPv6(src="10:220::1", dst="10:222::1") /
5249 UDP(sport=1234, dport=1234) /
5250 Raw(b'\xa5' * 100)),
5251 (Ether(src=eep1.mac, dst=str(self.router_mac)) /
5253 IPv6(src="10:220::1", dst="10:222::1") /
5254 UDP(sport=7777, dport=8881) /
5255 Raw(b'\xa5' * 100))]
5257 self.logger.info(self.vapi.cli("sh ip6 fib 10:222::1"))
5258 rxs = self.send_and_expect(self.pg0, p, self.pg7)
5260 self.assertEqual(rxs[0][VXLAN].vni, 445)
5261 self.assertEqual(rxs[1][VXLAN].vni, 446)
5264 # ping from host in remote to local external subnets
5265 # there's no contract for this, but the A bit is set.
5267 p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
5268 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
5269 UDP(sport=1234, dport=48879) /
5270 VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
5271 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
5272 IP(src="10.222.0.1", dst="10.220.0.1") /
5273 UDP(sport=1234, dport=1234) /
5276 rxs = self.send_and_expect(self.pg7, p * 3, self.pg0)
5277 self.assertFalse(find_gbp_endpoint(self, ip="10.222.0.1"))
5280 # ping from host in remote to remote external subnets
5281 # this is dropped by reflection check.
5283 p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
5284 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
5285 UDP(sport=1234, dport=48879) /
5286 VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
5287 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
5288 IP(src="10.222.0.1", dst="10.222.0.2") /
5289 UDP(sport=1234, dport=1234) /
5292 rxs = self.send_and_assert_no_replies(self.pg7, p * 3)
5294 p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
5295 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
5296 UDP(sport=1234, dport=48879) /
5297 VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
5298 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
5299 IPv6(src="10:222::1", dst="10:222::2") /
5300 UDP(sport=1234, dport=1234) /
5303 rxs = self.send_and_assert_no_replies(self.pg7, p * 3)
5308 lep1 = VppGbpEndpoint(self, vlan_144,
5310 "10.0.0.44", "11.0.0.44",
5311 "2001:10::44", "3001::44")
5312 lep1.add_vpp_config()
5315 # local EP to local ip4 external subnet
5317 p = (Ether(src=lep1.mac, dst=str(self.router_mac)) /
5319 IP(src=lep1.ip4, dst="10.220.0.1") /
5320 UDP(sport=1234, dport=1234) /
5323 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
5326 self.assertEqual(rx[Ether].src, str(self.router_mac))
5327 self.assertEqual(rx[Ether].dst, eep1.mac)
5328 self.assertEqual(rx[Dot1Q].vlan, 100)
5331 # local EP to local ip6 external subnet
5333 p = (Ether(src=lep1.mac, dst=str(self.router_mac)) /
5335 IPv6(src=lep1.ip6, dst="10:220::1") /
5336 UDP(sport=1234, dport=1234) /
5339 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
5342 self.assertEqual(rx[Ether].src, str(self.router_mac))
5343 self.assertEqual(rx[Ether].dst, eep1.mac)
5344 self.assertEqual(rx[Dot1Q].vlan, 100)
5347 # ip4 and ip6 subnets that load-balance
5349 ip_20 = VppIpRoute(self, "10.20.0.0", 24,
5350 [VppRoutePath(eep1.ip4,
5351 eep1.epg.bvi.sw_if_index),
5352 VppRoutePath(eep2.ip4,
5353 eep2.epg.bvi.sw_if_index)],
5354 table_id=t4.table_id)
5355 ip_20.add_vpp_config()
5357 l3o_20 = VppGbpSubnet(
5358 self, rd1, "10.20.0.0", 24,
5359 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
5361 l3o_20.add_vpp_config()
5363 ip6_20 = VppIpRoute(self, "10:20::", 64,
5364 [VppRoutePath(eep1.ip6,
5365 eep1.epg.bvi.sw_if_index),
5366 VppRoutePath(eep2.ip6,
5367 eep2.epg.bvi.sw_if_index)],
5368 table_id=t6.table_id)
5369 ip6_20.add_vpp_config()
5371 l3o6_20 = VppGbpSubnet(
5372 self, rd1, "10:20::", 64,
5373 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
5375 l3o6_20.add_vpp_config()
5377 self.logger.info(self.vapi.cli("sh ip fib 10.20.0.1"))
5378 self.logger.info(self.vapi.cli("sh ip6 fib 10:20::1"))
5380 # two ip6 packets whose port are chosen so they load-balance
5381 p = [(Ether(src=lep1.mac, dst=str(self.router_mac)) /
5383 IPv6(src=lep1.ip6, dst="10:20::1") /
5384 UDP(sport=1234, dport=1234) /
5385 Raw(b'\xa5' * 100)),
5386 (Ether(src=lep1.mac, dst=str(self.router_mac)) /
5388 IPv6(src=lep1.ip6, dst="10:20::1") /
5389 UDP(sport=124, dport=1230) /
5390 Raw(b'\xa5' * 100))]
5392 rxs = self.send_and_expect(self.pg0, p, self.pg0, 2)
5394 self.assertEqual(rxs[0][Dot1Q].vlan, 101)
5395 self.assertEqual(rxs[1][Dot1Q].vlan, 100)
5397 # two ip4 packets whose port are chosen so they load-balance
5398 p = [(Ether(src=lep1.mac, dst=str(self.router_mac)) /
5400 IP(src=lep1.ip4, dst="10.20.0.1") /
5401 UDP(sport=1235, dport=1235) /
5402 Raw(b'\xa5' * 100)),
5403 (Ether(src=lep1.mac, dst=str(self.router_mac)) /
5405 IP(src=lep1.ip4, dst="10.20.0.1") /
5406 UDP(sport=124, dport=1230) /
5407 Raw(b'\xa5' * 100))]
5409 rxs = self.send_and_expect(self.pg0, p, self.pg0, 2)
5411 self.assertEqual(rxs[0][Dot1Q].vlan, 101)
5412 self.assertEqual(rxs[1][Dot1Q].vlan, 100)
5417 ip_222.remove_vpp_config()
5418 self.pg7.unconfig_ip4()
5419 self.vlan_101.set_vtr(L2_VTR_OP.L2_DISABLED)
5420 self.vlan_100.set_vtr(L2_VTR_OP.L2_DISABLED)
5422 def test_gbp_anon_l3_out(self):
5423 """ GBP Anonymous L3 Out """
5425 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
5426 self.vapi.cli("set logging class gbp level debug")
5428 routed_dst_mac = "00:0c:0c:0c:0c:0c"
5429 routed_src_mac = "00:22:bd:f8:19:ff"
5434 t4 = VppIpTable(self, 1)
5436 t6 = VppIpTable(self, 1, True)
5439 rd1 = VppGbpRouteDomain(self, 2, 55, t4, t6)
5440 rd1.add_vpp_config()
5442 self.loop0.set_mac(self.router_mac)
5445 # Bind the BVI to the RD
5447 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
5448 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
5451 # Pg7 hosts a BD's BUM
5452 # Pg1 some other l3 interface
5454 self.pg7.config_ip4()
5455 self.pg7.resolve_arp()
5458 # a GBP external bridge domains for the EPs
5460 bd1 = VppBridgeDomain(self, 1)
5461 bd1.add_vpp_config()
5462 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0, None, None)
5463 gbd1.add_vpp_config()
5466 # The Endpoint-groups in which the external endpoints exist
5468 epg_220 = VppGbpEndpointGroup(self, 220, 113, rd1, gbd1,
5472 VppGbpEndpointRetention(2))
5473 epg_220.add_vpp_config()
5475 # the BVIs have the subnet applied ...
5476 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 24)
5477 ip4_addr.add_vpp_config()
5479 # ... which is an Anonymous L3-out subnets
5480 l3o_1 = VppGbpSubnet(
5481 self, rd1, "10.0.0.0", 24,
5482 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_ANON_L3_OUT,
5484 l3o_1.add_vpp_config()
5487 # an external interface attached to the outside world and the
5490 VppL2Vtr(self, self.vlan_100, L2_VTR_OP.L2_POP_1).add_vpp_config()
5491 VppL2Vtr(self, self.vlan_101, L2_VTR_OP.L2_POP_1).add_vpp_config()
5494 # vlan_100 and vlan_101 are anonymous l3-out interfaces
5496 ext_itf = VppGbpExtItf(self, self.vlan_100, bd1, rd1, anon=True)
5497 ext_itf.add_vpp_config()
5498 ext_itf = VppGbpExtItf(self, self.vlan_101, bd1, rd1, anon=True)
5499 ext_itf.add_vpp_config()
5502 # an unicast vxlan-gbp for inter-RD traffic
5504 vx_tun_l3 = VppGbpVxlanTunnel(
5505 self, 444, rd1.rd_id,
5506 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
5508 vx_tun_l3.add_vpp_config()
5511 # A remote external endpoint
5513 rep = VppGbpEndpoint(self, vx_tun_l3,
5515 "10.0.0.201", "11.0.0.201",
5516 "2001:10::201", "3001::101",
5517 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
5519 self.pg7.remote_ip4,
5521 rep.add_vpp_config()
5524 # ARP packet from host in external subnet are accepted, flooded and
5525 # replied to. We expect 2 packets:
5526 # - APR request flooded over the other vlan subif
5527 # - ARP reply from BVI
5529 p_arp = (Ether(src=self.vlan_100.remote_mac,
5530 dst="ff:ff:ff:ff:ff:ff") /
5535 hwsrc=self.vlan_100.remote_mac,
5536 hwdst="ff:ff:ff:ff:ff:ff"))
5537 rxs = self.send_and_expect(self.pg0, p_arp * 1, self.pg0, n_rx=2)
5539 p_arp = (Ether(src=self.vlan_101.remote_mac,
5540 dst="ff:ff:ff:ff:ff:ff") /
5545 hwsrc=self.vlan_101.remote_mac,
5546 hwdst="ff:ff:ff:ff:ff:ff"))
5547 rxs = self.send_and_expect(self.pg0, p_arp * 1, self.pg0, n_rx=2)
5550 # remote to external
5552 p = (Ether(src=self.pg7.remote_mac,
5553 dst=self.pg7.local_mac) /
5554 IP(src=self.pg7.remote_ip4,
5555 dst=self.pg7.local_ip4) /
5556 UDP(sport=1234, dport=48879) /
5557 VXLAN(vni=vx_tun_l3.vni, gpid=epg_220.sclass, flags=0x88) /
5558 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
5559 IP(src=str(rep.ip4), dst="10.0.0.100") /
5560 UDP(sport=1234, dport=1234) /
5562 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
5565 # local EP pings router
5567 p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
5569 IP(src="10.0.0.100", dst="10.0.0.128") /
5570 ICMP(type='echo-request'))
5571 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
5574 self.assertEqual(rx[Ether].src, str(self.router_mac))
5575 self.assertEqual(rx[Ether].dst, self.vlan_100.remote_mac)
5576 self.assertEqual(rx[Dot1Q].vlan, 100)
5579 # local EP pings other local EP
5581 p = (Ether(src=self.vlan_100.remote_mac,
5582 dst=self.vlan_101.remote_mac) /
5584 IP(src="10.0.0.100", dst="10.0.0.101") /
5585 ICMP(type='echo-request'))
5586 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
5589 self.assertEqual(rx[Ether].src, self.vlan_100.remote_mac)
5590 self.assertEqual(rx[Ether].dst, self.vlan_101.remote_mac)
5591 self.assertEqual(rx[Dot1Q].vlan, 101)
5594 # A subnet reachable through an external router on vlan 100
5596 ip_220 = VppIpRoute(self, "10.220.0.0", 24,
5597 [VppRoutePath("10.0.0.100",
5598 epg_220.bvi.sw_if_index)],
5599 table_id=t4.table_id)
5600 ip_220.add_vpp_config()
5602 l3o_220 = VppGbpSubnet(
5603 self, rd1, "10.220.0.0", 24,
5604 # note: this a "regular" L3 out subnet (not connected)
5605 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
5607 l3o_220.add_vpp_config()
5610 # A subnet reachable through an external router on vlan 101
5612 ip_221 = VppIpRoute(self, "10.221.0.0", 24,
5613 [VppRoutePath("10.0.0.101",
5614 epg_220.bvi.sw_if_index)],
5615 table_id=t4.table_id)
5616 ip_221.add_vpp_config()
5618 l3o_221 = VppGbpSubnet(
5619 self, rd1, "10.221.0.0", 24,
5620 # note: this a "regular" L3 out subnet (not connected)
5621 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
5623 l3o_221.add_vpp_config()
5626 # ping between hosts in remote subnets
5627 # dropped without a contract
5629 p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
5631 IP(src="10.220.0.1", dst="10.221.0.1") /
5632 ICMP(type='echo-request'))
5634 rxs = self.send_and_assert_no_replies(self.pg0, p * 1)
5637 # contract for the external nets to communicate
5639 acl = VppGbpAcl(self)
5640 rule4 = acl.create_rule(permit_deny=1, proto=17)
5641 rule6 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
5642 acl_index = acl.add_vpp_config([rule4, rule6])
5644 c1 = VppGbpContract(
5645 self, 55, 4220, 4221, acl_index,
5646 [VppGbpContractRule(
5647 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5648 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5651 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5652 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5654 [ETH_P_IP, ETH_P_IPV6])
5658 # Contracts allowing ext-net 200 to talk with external EPs
5660 c2 = VppGbpContract(
5661 self, 55, 4220, 113, acl_index,
5662 [VppGbpContractRule(
5663 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5664 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5667 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5668 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5670 [ETH_P_IP, ETH_P_IPV6])
5672 c3 = VppGbpContract(
5673 self, 55, 113, 4220, acl_index,
5674 [VppGbpContractRule(
5675 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5676 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5679 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5680 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5682 [ETH_P_IP, ETH_P_IPV6])
5686 # ping between hosts in remote subnets
5688 p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
5690 IP(src="10.220.0.1", dst="10.221.0.1") /
5691 UDP(sport=1234, dport=1234) /
5694 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
5697 self.assertEqual(rx[Ether].src, str(self.router_mac))
5698 self.assertEqual(rx[Ether].dst, self.vlan_101.remote_mac)
5699 self.assertEqual(rx[Dot1Q].vlan, 101)
5701 # we did not learn these external hosts
5702 self.assertFalse(find_gbp_endpoint(self, ip="10.220.0.1"))
5703 self.assertFalse(find_gbp_endpoint(self, ip="10.221.0.1"))
5706 # from remote external EP to local external EP
5708 p = (Ether(src=self.pg7.remote_mac,
5709 dst=self.pg7.local_mac) /
5710 IP(src=self.pg7.remote_ip4,
5711 dst=self.pg7.local_ip4) /
5712 UDP(sport=1234, dport=48879) /
5713 VXLAN(vni=444, gpid=113, flags=0x88) /
5714 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
5715 IP(src=rep.ip4, dst="10.220.0.1") /
5716 UDP(sport=1234, dport=1234) /
5719 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
5722 # ping from an external host to the remote external EP
5724 p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
5726 IP(src="10.220.0.1", dst=rep.ip4) /
5727 UDP(sport=1234, dport=1234) /
5730 rxs = self.send_and_expect(self.pg0, p * 1, self.pg7)
5733 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
5734 # self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
5735 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
5736 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
5737 self.assertEqual(rx[VXLAN].vni, 444)
5738 self.assertTrue(rx[VXLAN].flags.G)
5739 self.assertTrue(rx[VXLAN].flags.Instance)
5740 # the sclass of the ext-net the packet came from
5741 self.assertEqual(rx[VXLAN].gpid, 4220)
5742 # policy was applied to the original IP packet
5743 self.assertTrue(rx[VXLAN].gpflags.A)
5744 # since it's an external host the reciever should not learn it
5745 self.assertTrue(rx[VXLAN].gpflags.D)
5746 inner = rx[VXLAN].payload
5747 self.assertEqual(inner[IP].src, "10.220.0.1")
5748 self.assertEqual(inner[IP].dst, rep.ip4)
5751 # An external subnet reachable via the remote external EP
5755 # first the VXLAN-GBP tunnel over which it is reached
5757 vx_tun_r = VppVxlanGbpTunnel(
5758 self, self.pg7.local_ip4,
5759 self.pg7.remote_ip4, 445,
5760 mode=(VppEnum.vl_api_vxlan_gbp_api_tunnel_mode_t.
5761 VXLAN_GBP_API_TUNNEL_MODE_L3))
5762 vx_tun_r.add_vpp_config()
5763 VppIpInterfaceBind(self, vx_tun_r, t4).add_vpp_config()
5765 self.logger.info(self.vapi.cli("sh vxlan-gbp tunnel"))
5768 # then the special adj to resolve through on that tunnel
5770 n1 = VppNeighbor(self,
5771 vx_tun_r.sw_if_index,
5772 "00:0c:0c:0c:0c:0c",
5773 self.pg7.remote_ip4)
5777 # the route via the adj above
5779 ip_222 = VppIpRoute(self, "10.222.0.0", 24,
5780 [VppRoutePath(self.pg7.remote_ip4,
5781 vx_tun_r.sw_if_index)],
5782 table_id=t4.table_id)
5783 ip_222.add_vpp_config()
5785 l3o_222 = VppGbpSubnet(
5786 self, rd1, "10.222.0.0", 24,
5787 # note: this a "regular" l3out subnet (not connected)
5788 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
5790 l3o_222.add_vpp_config()
5793 # ping between hosts in local and remote external subnets
5794 # dropped without a contract
5796 p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
5798 IP(src="10.220.0.1", dst="10.222.0.1") /
5799 UDP(sport=1234, dport=1234) /
5802 rxs = self.send_and_assert_no_replies(self.pg0, p * 1)
5805 # Add contracts ext-nets for 220 -> 222
5807 c4 = VppGbpContract(
5808 self, 55, 4220, 4222, acl_index,
5809 [VppGbpContractRule(
5810 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5811 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5814 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
5815 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
5817 [ETH_P_IP, ETH_P_IPV6])
5821 # ping from host in local to remote external subnets
5823 p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
5825 IP(src="10.220.0.1", dst="10.222.0.1") /
5826 UDP(sport=1234, dport=1234) /
5829 rxs = self.send_and_expect(self.pg0, p * 3, self.pg7)
5832 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
5833 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
5834 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
5835 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
5836 self.assertEqual(rx[VXLAN].vni, 445)
5837 self.assertTrue(rx[VXLAN].flags.G)
5838 self.assertTrue(rx[VXLAN].flags.Instance)
5839 # the sclass of the ext-net the packet came from
5840 self.assertEqual(rx[VXLAN].gpid, 4220)
5841 # policy was applied to the original IP packet
5842 self.assertTrue(rx[VXLAN].gpflags.A)
5843 # since it's an external host the reciever should not learn it
5844 self.assertTrue(rx[VXLAN].gpflags.D)
5845 inner = rx[VXLAN].payload
5846 self.assertEqual(inner[Ether].dst, "00:0c:0c:0c:0c:0c")
5847 self.assertEqual(inner[IP].src, "10.220.0.1")
5848 self.assertEqual(inner[IP].dst, "10.222.0.1")
5851 # ping from host in remote to local external subnets
5852 # there's no contract for this, but the A bit is set.
5854 p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
5855 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
5856 UDP(sport=1234, dport=48879) /
5857 VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
5858 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
5859 IP(src="10.222.0.1", dst="10.220.0.1") /
5860 UDP(sport=1234, dport=1234) /
5863 rxs = self.send_and_expect(self.pg7, p * 3, self.pg0)
5864 self.assertFalse(find_gbp_endpoint(self, ip="10.222.0.1"))
5867 # ping from host in remote to remote external subnets
5868 # this is dropped by reflection check.
5870 p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
5871 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
5872 UDP(sport=1234, dport=48879) /
5873 VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
5874 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
5875 IP(src="10.222.0.1", dst="10.222.0.2") /
5876 UDP(sport=1234, dport=1234) /
5879 rxs = self.send_and_assert_no_replies(self.pg7, p * 3)
5884 self.vlan_101.set_vtr(L2_VTR_OP.L2_DISABLED)
5885 self.vlan_100.set_vtr(L2_VTR_OP.L2_DISABLED)
5886 self.pg7.unconfig_ip4()
5889 if __name__ == '__main__':
5890 unittest.main(testRunner=VppTestRunner)