5 from framework import VppTestCase, VppTestRunner
6 from vpp_object import VppObject
7 from vpp_neighbor import VppNeighbor
8 from vpp_ip_route import VppIpRoute, VppRoutePath, VppIpTable, \
9 VppIpInterfaceAddress, VppIpInterfaceBind, find_route
10 from vpp_l2 import VppBridgeDomain, VppBridgeDomainPort, \
11 VppBridgeDomainArpEntry, VppL2FibEntry, find_bridge_domain_port
12 from vpp_vxlan_gbp_tunnel import *
13 from vpp_sub_interface import VppDot1QSubint
17 from vpp_papi_provider import L2_PORT_TYPE
18 from vpp_papi import VppEnum
20 from scapy.packet import Raw
21 from scapy.layers.l2 import Ether, ARP, Dot1Q
22 from scapy.layers.inet import IP, UDP
23 from scapy.layers.inet6 import IPv6, ICMPv6ND_NS, ICMPv6NDOptSrcLLAddr, \
25 from scapy.utils6 import in6_getnsma, in6_getnsmac
26 from scapy.layers.vxlan import VXLAN
28 from socket import AF_INET, AF_INET6
29 from scapy.utils import inet_pton, inet_ntop
30 from util import mactobinary
31 from vpp_papi_provider import L2_VTR_OP
34 def find_gbp_endpoint(test, sw_if_index=None, ip=None, mac=None):
36 vip = VppIpAddress(ip)
38 vmac = VppMacAddress(mac)
40 eps = test.vapi.gbp_endpoint_dump()
44 if ep.endpoint.sw_if_index != sw_if_index:
47 for eip in ep.endpoint.ips:
51 if vmac == ep.endpoint.mac:
56 def find_gbp_vxlan(test, vni):
57 ts = test.vapi.gbp_vxlan_tunnel_dump()
59 if t.tunnel.vni == vni:
64 class VppGbpEndpoint(VppObject):
71 return self.vmac.bytes
75 return self.vmac.address
79 return self.itf.remote_mac
99 return [self.ip4, self.ip6]
103 return [self.fip4, self.fip6]
105 def __init__(self, test, itf, epg, recirc, ip4, fip4, ip6, fip6,
115 self._ip4 = VppIpAddress(ip4)
116 self._fip4 = VppIpAddress(fip4)
117 self._ip6 = VppIpAddress(ip6)
118 self._fip6 = VppIpAddress(fip6)
121 self.vmac = VppMacAddress(self.itf.remote_mac)
123 self.vmac = VppMacAddress("00:00:00:00:00:00")
126 self.tun_src = VppIpAddress(tun_src)
127 self.tun_dst = VppIpAddress(tun_dst)
129 def add_vpp_config(self):
130 res = self._test.vapi.gbp_endpoint_add(
131 self.itf.sw_if_index,
132 [self.ip4.encode(), self.ip6.encode()],
136 self.tun_src.encode(),
137 self.tun_dst.encode())
138 self.handle = res.handle
139 self._test.registry.register(self, self._test.logger)
141 def remove_vpp_config(self):
142 self._test.vapi.gbp_endpoint_del(self.handle)
145 return self.object_id()
148 return "gbp-endpoint:[%d==%d:%s:%d]" % (self.handle,
149 self.itf.sw_if_index,
153 def query_vpp_config(self):
154 return find_gbp_endpoint(self._test,
155 self.itf.sw_if_index,
159 class VppGbpRecirc(VppObject):
161 GBP Recirculation Interface
164 def __init__(self, test, epg, recirc, is_ext=False):
170 def add_vpp_config(self):
171 self._test.vapi.gbp_recirc_add_del(
173 self.recirc.sw_if_index,
176 self._test.registry.register(self, self._test.logger)
178 def remove_vpp_config(self):
179 self._test.vapi.gbp_recirc_add_del(
181 self.recirc.sw_if_index,
186 return self.object_id()
189 return "gbp-recirc:[%d]" % (self.recirc.sw_if_index)
191 def query_vpp_config(self):
192 rs = self._test.vapi.gbp_recirc_dump()
194 if r.recirc.sw_if_index == self.recirc.sw_if_index:
199 class VppGbpSubnet(VppObject):
203 def __init__(self, test, rd, address, address_len,
204 type, sw_if_index=None, epg=None):
206 self.rd_id = rd.rd_id
207 self.prefix = VppIpPrefix(address, address_len)
209 self.sw_if_index = sw_if_index
212 def add_vpp_config(self):
213 self._test.vapi.gbp_subnet_add_del(
216 self.prefix.encode(),
218 sw_if_index=self.sw_if_index if self.sw_if_index else 0xffffffff,
219 epg_id=self.epg if self.epg else 0xffff)
220 self._test.registry.register(self, self._test.logger)
222 def remove_vpp_config(self):
223 self._test.vapi.gbp_subnet_add_del(
226 self.prefix.encode(),
230 return self.object_id()
233 return "gbp-subnet:[%d-%s]" % (self.rd_id, self.prefix)
235 def query_vpp_config(self):
236 ss = self._test.vapi.gbp_subnet_dump()
238 if s.subnet.rd_id == self.rd_id and \
239 s.subnet.type == self.type and \
240 s.subnet.prefix == self.prefix:
245 class VppGbpEndpointGroup(VppObject):
250 def __init__(self, test, epg, rd, bd, uplink,
251 bvi, bvi_ip4, bvi_ip6=None):
255 self.bvi_ip4 = VppIpAddress(bvi_ip4)
256 self.bvi_ip6 = VppIpAddress(bvi_ip6)
261 def add_vpp_config(self):
262 self._test.vapi.gbp_endpoint_group_add(
266 self.uplink.sw_if_index if self.uplink else INDEX_INVALID)
267 self._test.registry.register(self, self._test.logger)
269 def remove_vpp_config(self):
270 self._test.vapi.gbp_endpoint_group_del(
274 return self.object_id()
277 return "gbp-endpoint-group:[%d]" % (self.epg)
279 def query_vpp_config(self):
280 epgs = self._test.vapi.gbp_endpoint_group_dump()
282 if epg.epg.epg_id == self.epg:
287 class VppGbpBridgeDomain(VppObject):
292 def __init__(self, test, bd, bvi, uu_flood=None, learn=True):
295 self.uu_flood = uu_flood
298 e = VppEnum.vl_api_gbp_bridge_domain_flags_t
300 self.learn = e.GBP_BD_API_FLAG_NONE
302 self.learn = e.GBP_BD_API_FLAG_DO_NOT_LEARN
304 def add_vpp_config(self):
305 self._test.vapi.gbp_bridge_domain_add(
308 self.bvi.sw_if_index,
309 self.uu_flood.sw_if_index if self.uu_flood else INDEX_INVALID)
310 self._test.registry.register(self, self._test.logger)
312 def remove_vpp_config(self):
313 self._test.vapi.gbp_bridge_domain_del(self.bd.bd_id)
316 return self.object_id()
319 return "gbp-bridge-domain:[%d]" % (self.bd.bd_id)
321 def query_vpp_config(self):
322 bds = self._test.vapi.gbp_bridge_domain_dump()
324 if bd.bd.bd_id == self.bd.bd_id:
329 class VppGbpRouteDomain(VppObject):
334 def __init__(self, test, rd_id, t4, t6, ip4_uu=None, ip6_uu=None):
342 def add_vpp_config(self):
343 self._test.vapi.gbp_route_domain_add(
347 self.ip4_uu.sw_if_index if self.ip4_uu else INDEX_INVALID,
348 self.ip6_uu.sw_if_index if self.ip6_uu else INDEX_INVALID)
349 self._test.registry.register(self, self._test.logger)
351 def remove_vpp_config(self):
352 self._test.vapi.gbp_route_domain_del(self.rd_id)
355 return self.object_id()
358 return "gbp-route-domain:[%d]" % (self.rd_id)
360 def query_vpp_config(self):
361 rds = self._test.vapi.gbp_route_domain_dump()
363 if rd.rd.rd_id == self.rd_id:
368 class VppGbpContractNextHop():
369 def __init__(self, mac, bd, ip, rd):
376 return {'ip': self.ip.encode(),
377 'mac': self.mac.encode(),
378 'bd_id': self.bd.bd.bd_id,
379 'rd_id': self.rd.rd_id}
382 class VppGbpContractRule():
383 def __init__(self, action, hash_mode, nhs=[]):
385 self.hash_mode = hash_mode
391 nhs.append(nh.encode())
394 return {'action': self.action,
396 'hash_mode': self.hash_mode,
397 'n_nhs': len(self.nhs),
401 class VppGbpContract(VppObject):
406 def __init__(self, test, src_epg, dst_epg, acl_index, rules=[]):
408 self.acl_index = acl_index
409 self.src_epg = src_epg
410 self.dst_epg = dst_epg
413 def add_vpp_config(self):
416 rules.append(r.encode())
417 self._test.vapi.gbp_contract_add_del(
423 self._test.registry.register(self, self._test.logger)
425 def remove_vpp_config(self):
426 self._test.vapi.gbp_contract_add_del(
434 return self.object_id()
437 return "gbp-contract:[%d:%s:%d]" % (self.src_epg,
441 def query_vpp_config(self):
442 cs = self._test.vapi.gbp_contract_dump()
444 if c.contract.src_epg == self.src_epg \
445 and c.contract.dst_epg == self.dst_epg:
450 class VppGbpVxlanTunnel(VppInterface):
455 def __init__(self, test, vni, bd_rd_id, mode):
456 super(VppGbpVxlanTunnel, self).__init__(test)
459 self.bd_rd_id = bd_rd_id
462 def add_vpp_config(self):
463 r = self._test.vapi.gbp_vxlan_tunnel_add(
467 self.set_sw_if_index(r.sw_if_index)
468 self._test.registry.register(self, self._test.logger)
470 def remove_vpp_config(self):
471 self._test.vapi.gbp_vxlan_tunnel_del(self.vni)
474 return self.object_id()
477 return "gbp-vxlan:%d" % (self.vni)
479 def query_vpp_config(self):
480 return find_gbp_vxlan(self._test, self.vni)
483 class VppGbpAcl(VppObject):
488 def __init__(self, test):
490 self.acl_index = 4294967295
492 def create_rule(self, is_ipv6=0, permit_deny=0, proto=-1,
493 s_prefix=0, s_ip='\x00\x00\x00\x00', sport_from=0,
494 sport_to=65535, d_prefix=0, d_ip='\x00\x00\x00\x00',
495 dport_from=0, dport_to=65535):
496 if proto == -1 or proto == 0:
499 elif proto == 1 or proto == 58:
502 rule = ({'is_permit': permit_deny, 'is_ipv6': is_ipv6, 'proto': proto,
503 'srcport_or_icmptype_first': sport_from,
504 'srcport_or_icmptype_last': sport_to,
505 'src_ip_prefix_len': s_prefix,
507 'dstport_or_icmpcode_first': dport_from,
508 'dstport_or_icmpcode_last': dport_to,
509 'dst_ip_prefix_len': d_prefix,
510 'dst_ip_addr': d_ip})
513 def add_vpp_config(self, rules):
515 reply = self._test.vapi.acl_add_replace(self.acl_index,
518 self.acl_index = reply.acl_index
519 return self.acl_index
521 def remove_vpp_config(self):
522 self._test.vapi.acl_del(self.acl_index)
525 return self.object_id()
528 return "gbp-acl:[%d]" % (self.acl_index)
530 def query_vpp_config(self):
531 cs = self._test.vapi.acl_dump()
533 if c.acl_index == self.acl_index:
538 class TestGBP(VppTestCase):
539 """ GBP Test Case """
542 super(TestGBP, self).setUp()
544 self.create_pg_interfaces(range(9))
545 self.create_loopback_interfaces(8)
547 self.router_mac = VppMacAddress("00:11:22:33:44:55")
549 for i in self.pg_interfaces:
551 for i in self.lo_interfaces:
555 for i in self.pg_interfaces:
558 super(TestGBP, self).tearDown()
560 def send_and_expect_bridged(self, src, tx, dst):
561 rx = self.send_and_expect(src, tx, dst)
564 self.assertEqual(r[Ether].src, tx[0][Ether].src)
565 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
566 self.assertEqual(r[IP].src, tx[0][IP].src)
567 self.assertEqual(r[IP].dst, tx[0][IP].dst)
570 def send_and_expect_bridged6(self, src, tx, dst):
571 rx = self.send_and_expect(src, tx, dst)
574 self.assertEqual(r[Ether].src, tx[0][Ether].src)
575 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
576 self.assertEqual(r[IPv6].src, tx[0][IPv6].src)
577 self.assertEqual(r[IPv6].dst, tx[0][IPv6].dst)
580 def send_and_expect_routed(self, src, tx, dst, src_mac):
581 rx = self.send_and_expect(src, tx, dst)
584 self.assertEqual(r[Ether].src, src_mac)
585 self.assertEqual(r[Ether].dst, dst.remote_mac)
586 self.assertEqual(r[IP].src, tx[0][IP].src)
587 self.assertEqual(r[IP].dst, tx[0][IP].dst)
590 def send_and_expect_natted(self, src, tx, dst, src_ip):
591 rx = self.send_and_expect(src, tx, dst)
594 self.assertEqual(r[Ether].src, tx[0][Ether].src)
595 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
596 self.assertEqual(r[IP].src, src_ip)
597 self.assertEqual(r[IP].dst, tx[0][IP].dst)
600 def send_and_expect_natted6(self, src, tx, dst, src_ip):
601 rx = self.send_and_expect(src, tx, dst)
604 self.assertEqual(r[Ether].src, tx[0][Ether].src)
605 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
606 self.assertEqual(r[IPv6].src, src_ip)
607 self.assertEqual(r[IPv6].dst, tx[0][IPv6].dst)
610 def send_and_expect_unnatted(self, src, tx, dst, dst_ip):
611 rx = self.send_and_expect(src, tx, dst)
614 self.assertEqual(r[Ether].src, tx[0][Ether].src)
615 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
616 self.assertEqual(r[IP].dst, dst_ip)
617 self.assertEqual(r[IP].src, tx[0][IP].src)
620 def send_and_expect_unnatted6(self, src, tx, dst, dst_ip):
621 rx = self.send_and_expect(src, tx, dst)
624 self.assertEqual(r[Ether].src, tx[0][Ether].src)
625 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
626 self.assertEqual(r[IPv6].dst, dst_ip)
627 self.assertEqual(r[IPv6].src, tx[0][IPv6].src)
630 def send_and_expect_double_natted(self, src, tx, dst, src_ip, dst_ip):
631 rx = self.send_and_expect(src, tx, dst)
634 self.assertEqual(r[Ether].src, self.router_mac.address)
635 self.assertEqual(r[Ether].dst, dst.remote_mac)
636 self.assertEqual(r[IP].dst, dst_ip)
637 self.assertEqual(r[IP].src, src_ip)
640 def send_and_expect_double_natted6(self, src, tx, dst, src_ip, dst_ip):
641 rx = self.send_and_expect(src, tx, dst)
644 self.assertEqual(r[Ether].src, self.router_mac.address)
645 self.assertEqual(r[Ether].dst, dst.remote_mac)
646 self.assertEqual(r[IPv6].dst, dst_ip)
647 self.assertEqual(r[IPv6].src, src_ip)
651 """ Group Based Policy """
656 bd1 = VppBridgeDomain(self, 1)
657 bd2 = VppBridgeDomain(self, 2)
658 bd20 = VppBridgeDomain(self, 20)
662 bd20.add_vpp_config()
664 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0)
665 gbd2 = VppGbpBridgeDomain(self, bd2, self.loop1)
666 gbd20 = VppGbpBridgeDomain(self, bd20, self.loop2)
668 gbd1.add_vpp_config()
669 gbd2.add_vpp_config()
670 gbd20.add_vpp_config()
675 gt4 = VppIpTable(self, 0)
677 gt6 = VppIpTable(self, 0, is_ip6=True)
679 nt4 = VppIpTable(self, 20)
681 nt6 = VppIpTable(self, 20, is_ip6=True)
684 rd0 = VppGbpRouteDomain(self, 0, gt4, gt6, None, None)
685 rd20 = VppGbpRouteDomain(self, 20, nt4, nt6, None, None)
688 rd20.add_vpp_config()
691 # 3 EPGs, 2 of which share a BD.
692 # 2 NAT EPGs, one for floating-IP subnets, the other for internet
694 epgs = [VppGbpEndpointGroup(self, 220, rd0, gbd1, self.pg4,
698 VppGbpEndpointGroup(self, 221, rd0, gbd1, self.pg5,
702 VppGbpEndpointGroup(self, 222, rd0, gbd2, self.pg6,
706 VppGbpEndpointGroup(self, 333, rd20, gbd20, self.pg7,
710 VppGbpEndpointGroup(self, 444, rd20, gbd20, self.pg8,
714 recircs = [VppGbpRecirc(self, epgs[0],
716 VppGbpRecirc(self, epgs[1],
718 VppGbpRecirc(self, epgs[2],
720 VppGbpRecirc(self, epgs[3],
721 self.loop6, is_ext=True),
722 VppGbpRecirc(self, epgs[4],
723 self.loop7, is_ext=True)]
726 recirc_nat = recircs[3]
729 # 4 end-points, 2 in the same subnet, 3 in the same BD
731 eps = [VppGbpEndpoint(self, self.pg0,
733 "10.0.0.1", "11.0.0.1",
734 "2001:10::1", "3001::1"),
735 VppGbpEndpoint(self, self.pg1,
737 "10.0.0.2", "11.0.0.2",
738 "2001:10::2", "3001::2"),
739 VppGbpEndpoint(self, self.pg2,
741 "10.0.1.1", "11.0.0.3",
742 "2001:10:1::1", "3001::3"),
743 VppGbpEndpoint(self, self.pg3,
745 "10.0.2.1", "11.0.0.4",
746 "2001:10:2::1", "3001::4")]
749 # Config related to each of the EPGs
752 # IP config on the BVI interfaces
753 if epg != epgs[1] and epg != epgs[4]:
754 VppIpInterfaceBind(self, epg.bvi, epg.rd.t4).add_vpp_config()
755 VppIpInterfaceBind(self, epg.bvi, epg.rd.t6).add_vpp_config()
756 self.vapi.sw_interface_set_mac_address(
758 self.router_mac.bytes)
760 # The BVIs are NAT inside interfaces
761 self.vapi.nat44_interface_add_del_feature(epg.bvi.sw_if_index,
764 self.vapi.nat66_add_del_interface(epg.bvi.sw_if_index,
768 if_ip4 = VppIpInterfaceAddress(self, epg.bvi, epg.bvi_ip4, 32)
769 if_ip6 = VppIpInterfaceAddress(self, epg.bvi, epg.bvi_ip6, 128)
770 if_ip4.add_vpp_config()
771 if_ip6.add_vpp_config()
773 # EPG uplink interfaces in the RD
774 VppIpInterfaceBind(self, epg.uplink, epg.rd.t4).add_vpp_config()
775 VppIpInterfaceBind(self, epg.uplink, epg.rd.t6).add_vpp_config()
777 # add the BD ARP termination entry for BVI IP
778 epg.bd_arp_ip4 = VppBridgeDomainArpEntry(self, epg.bd.bd,
779 self.router_mac.address,
781 epg.bd_arp_ip6 = VppBridgeDomainArpEntry(self, epg.bd.bd,
782 self.router_mac.address,
784 epg.bd_arp_ip4.add_vpp_config()
785 epg.bd_arp_ip6.add_vpp_config()
790 for recirc in recircs:
791 # EPG's ingress recirculation interface maps to its RD
792 VppIpInterfaceBind(self, recirc.recirc,
793 recirc.epg.rd.t4).add_vpp_config()
794 VppIpInterfaceBind(self, recirc.recirc,
795 recirc.epg.rd.t6).add_vpp_config()
797 self.vapi.sw_interface_set_l2_emulation(
798 recirc.recirc.sw_if_index)
799 self.vapi.nat44_interface_add_del_feature(
800 recirc.recirc.sw_if_index,
803 self.vapi.nat66_add_del_interface(
804 recirc.recirc.sw_if_index,
808 recirc.add_vpp_config()
810 for recirc in recircs:
811 self.assertTrue(find_bridge_domain_port(self,
812 recirc.epg.bd.bd.bd_id,
813 recirc.recirc.sw_if_index))
816 self.pg_enable_capture(self.pg_interfaces)
819 # routes to the endpoints. We need these since there are no
820 # adj-fibs due to the fact the the BVI address has /32 and
821 # the subnet is not attached.
823 for (ip, fip) in zip(ep.ips, ep.fips):
824 # Add static mappings for each EP from the 10/8 to 11/8 network
826 self.vapi.nat44_add_del_static_mapping(ip.bytes,
831 self.vapi.nat66_add_del_static_mapping(ip.bytes,
838 self.logger.info(self.vapi.cli("sh gbp endpoint"))
840 # ... results in a Gratuitous ARP/ND on the EPG's uplink
841 rx = ep.epg.uplink.get_capture(len(ep.ips), timeout=0.2)
843 for ii, ip in enumerate(ep.ips):
847 self.assertTrue(p.haslayer(ICMPv6ND_NA))
848 self.assertEqual(p[ICMPv6ND_NA].tgt, ip.address)
850 self.assertTrue(p.haslayer(ARP))
851 self.assertEqual(p[ARP].psrc, ip.address)
852 self.assertEqual(p[ARP].pdst, ip.address)
854 # add the BD ARP termination entry for floating IP
856 ba = VppBridgeDomainArpEntry(self, epg_nat.bd.bd, ep.mac, fip)
859 # floating IPs route via EPG recirc
860 r = VppIpRoute(self, fip.address, fip.length,
861 [VppRoutePath(fip.address,
862 ep.recirc.recirc.sw_if_index,
864 proto=fip.dpo_proto)],
869 # L2 FIB entries in the NAT EPG BD to bridge the packets from
870 # the outside direct to the internal EPG
871 lf = VppL2FibEntry(self, epg_nat.bd.bd, ep.mac,
872 ep.recirc.recirc, bvi_mac=0)
876 # ARP packets for unknown IP are sent to the EPG uplink
878 pkt_arp = (Ether(dst="ff:ff:ff:ff:ff:ff",
879 src=self.pg0.remote_mac) /
881 hwdst="ff:ff:ff:ff:ff:ff",
882 hwsrc=self.pg0.remote_mac,
886 self.vapi.cli("clear trace")
887 self.pg0.add_stream(pkt_arp)
889 self.pg_enable_capture(self.pg_interfaces)
892 rxd = epgs[0].uplink.get_capture(1)
895 # ARP/ND packets get a response
897 pkt_arp = (Ether(dst="ff:ff:ff:ff:ff:ff",
898 src=self.pg0.remote_mac) /
900 hwdst="ff:ff:ff:ff:ff:ff",
901 hwsrc=self.pg0.remote_mac,
902 pdst=epgs[0].bvi_ip4.address,
903 psrc=eps[0].ip4.address))
905 self.send_and_expect(self.pg0, [pkt_arp], self.pg0)
907 nsma = in6_getnsma(inet_pton(AF_INET6, eps[0].ip6.address))
908 d = inet_ntop(AF_INET6, nsma)
909 pkt_nd = (Ether(dst=in6_getnsmac(nsma),
910 src=self.pg0.remote_mac) /
911 IPv6(dst=d, src=eps[0].ip6.address) /
912 ICMPv6ND_NS(tgt=epgs[0].bvi_ip6.address) /
913 ICMPv6NDOptSrcLLAddr(lladdr=self.pg0.remote_mac))
914 self.send_and_expect(self.pg0, [pkt_nd], self.pg0)
917 # broadcast packets are flooded
919 pkt_bcast = (Ether(dst="ff:ff:ff:ff:ff:ff",
920 src=self.pg0.remote_mac) /
921 IP(src=eps[0].ip4.address, dst="232.1.1.1") /
922 UDP(sport=1234, dport=1234) /
925 self.vapi.cli("clear trace")
926 self.pg0.add_stream(pkt_bcast)
928 self.pg_enable_capture(self.pg_interfaces)
931 rxd = eps[1].itf.get_capture(1)
932 self.assertEqual(rxd[0][Ether].dst, pkt_bcast[Ether].dst)
933 rxd = epgs[0].uplink.get_capture(1)
934 self.assertEqual(rxd[0][Ether].dst, pkt_bcast[Ether].dst)
937 # packets to non-local L3 destinations dropped
939 pkt_intra_epg_220_ip4 = (Ether(src=self.pg0.remote_mac,
940 dst=self.router_mac.address) /
941 IP(src=eps[0].ip4.address,
943 UDP(sport=1234, dport=1234) /
945 pkt_inter_epg_222_ip4 = (Ether(src=self.pg0.remote_mac,
946 dst=self.router_mac.address) /
947 IP(src=eps[0].ip4.address,
949 UDP(sport=1234, dport=1234) /
952 self.send_and_assert_no_replies(self.pg0, pkt_intra_epg_220_ip4 * 65)
954 pkt_inter_epg_222_ip6 = (Ether(src=self.pg0.remote_mac,
955 dst=self.router_mac.address) /
956 IPv6(src=eps[0].ip6.address,
958 UDP(sport=1234, dport=1234) /
960 self.send_and_assert_no_replies(self.pg0, pkt_inter_epg_222_ip6 * 65)
963 # Add the subnet routes
966 self, rd0, "10.0.0.0", 24,
967 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
969 self, rd0, "10.0.1.0", 24,
970 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
972 self, rd0, "10.0.2.0", 24,
973 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
975 self, rd0, "2001:10::1", 64,
976 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
978 self, rd0, "2001:10:1::1", 64,
979 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
981 self, rd0, "2001:10:2::1", 64,
982 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
990 self.send_and_expect_bridged(eps[0].itf,
991 pkt_intra_epg_220_ip4 * 65,
993 self.send_and_expect_bridged(eps[0].itf,
994 pkt_inter_epg_222_ip4 * 65,
996 self.send_and_expect_bridged6(eps[0].itf,
997 pkt_inter_epg_222_ip6 * 65,
1000 self.logger.info(self.vapi.cli("sh ip fib 11.0.0.2"))
1001 self.logger.info(self.vapi.cli("sh gbp endpoint-group"))
1002 self.logger.info(self.vapi.cli("sh gbp endpoint"))
1003 self.logger.info(self.vapi.cli("sh gbp recirc"))
1004 self.logger.info(self.vapi.cli("sh int"))
1005 self.logger.info(self.vapi.cli("sh int addr"))
1006 self.logger.info(self.vapi.cli("sh int feat loop6"))
1007 self.logger.info(self.vapi.cli("sh vlib graph ip4-gbp-src-classify"))
1008 self.logger.info(self.vapi.cli("sh int feat loop3"))
1009 self.logger.info(self.vapi.cli("sh int feat pg0"))
1012 # Packet destined to unknown unicast is sent on the epg uplink ...
1014 pkt_intra_epg_220_to_uplink = (Ether(src=self.pg0.remote_mac,
1015 dst="00:00:00:33:44:55") /
1016 IP(src=eps[0].ip4.address,
1018 UDP(sport=1234, dport=1234) /
1021 self.send_and_expect_bridged(eps[0].itf,
1022 pkt_intra_epg_220_to_uplink * 65,
1024 # ... and nowhere else
1025 self.pg1.get_capture(0, timeout=0.1)
1026 self.pg1.assert_nothing_captured(remark="Flood onto other VMS")
1028 pkt_intra_epg_221_to_uplink = (Ether(src=self.pg2.remote_mac,
1029 dst="00:00:00:33:44:66") /
1030 IP(src=eps[0].ip4.address,
1032 UDP(sport=1234, dport=1234) /
1035 self.send_and_expect_bridged(eps[2].itf,
1036 pkt_intra_epg_221_to_uplink * 65,
1040 # Packets from the uplink are forwarded in the absence of a contract
1042 pkt_intra_epg_220_from_uplink = (Ether(src="00:00:00:33:44:55",
1043 dst=self.pg0.remote_mac) /
1044 IP(src=eps[0].ip4.address,
1046 UDP(sport=1234, dport=1234) /
1049 self.send_and_expect_bridged(self.pg4,
1050 pkt_intra_epg_220_from_uplink * 65,
1054 # in the absence of policy, endpoints in the same EPG
1057 pkt_intra_epg = (Ether(src=self.pg0.remote_mac,
1058 dst=self.pg1.remote_mac) /
1059 IP(src=eps[0].ip4.address,
1060 dst=eps[1].ip4.address) /
1061 UDP(sport=1234, dport=1234) /
1064 self.send_and_expect_bridged(self.pg0, pkt_intra_epg * 65, self.pg1)
1067 # in the abscense of policy, endpoints in the different EPG
1068 # cannot communicate
1070 pkt_inter_epg_220_to_221 = (Ether(src=self.pg0.remote_mac,
1071 dst=self.pg2.remote_mac) /
1072 IP(src=eps[0].ip4.address,
1073 dst=eps[2].ip4.address) /
1074 UDP(sport=1234, dport=1234) /
1076 pkt_inter_epg_221_to_220 = (Ether(src=self.pg2.remote_mac,
1077 dst=self.pg0.remote_mac) /
1078 IP(src=eps[2].ip4.address,
1079 dst=eps[0].ip4.address) /
1080 UDP(sport=1234, dport=1234) /
1082 pkt_inter_epg_220_to_222 = (Ether(src=self.pg0.remote_mac,
1083 dst=self.router_mac.address) /
1084 IP(src=eps[0].ip4.address,
1085 dst=eps[3].ip4.address) /
1086 UDP(sport=1234, dport=1234) /
1089 self.send_and_assert_no_replies(eps[0].itf,
1090 pkt_inter_epg_220_to_221 * 65)
1091 self.send_and_assert_no_replies(eps[0].itf,
1092 pkt_inter_epg_220_to_222 * 65)
1095 # A uni-directional contract from EPG 220 -> 221
1097 acl = VppGbpAcl(self)
1098 rule = acl.create_rule(permit_deny=1, proto=17)
1099 rule2 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
1100 acl_index = acl.add_vpp_config([rule, rule2])
1101 c1 = VppGbpContract(
1102 self, 220, 221, acl_index,
1103 [VppGbpContractRule(
1104 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1107 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1111 self.send_and_expect_bridged(eps[0].itf,
1112 pkt_inter_epg_220_to_221 * 65,
1114 self.send_and_assert_no_replies(eps[0].itf,
1115 pkt_inter_epg_220_to_222 * 65)
1118 # contract for the return direction
1120 c2 = VppGbpContract(
1121 self, 221, 220, acl_index,
1122 [VppGbpContractRule(
1123 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1126 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1131 self.send_and_expect_bridged(eps[0].itf,
1132 pkt_inter_epg_220_to_221 * 65,
1134 self.send_and_expect_bridged(eps[2].itf,
1135 pkt_inter_epg_221_to_220 * 65,
1139 # check that inter group is still disabled for the groups
1140 # not in the contract.
1142 self.send_and_assert_no_replies(eps[0].itf,
1143 pkt_inter_epg_220_to_222 * 65)
1146 # A uni-directional contract from EPG 220 -> 222 'L3 routed'
1148 c3 = VppGbpContract(
1149 self, 220, 222, acl_index,
1150 [VppGbpContractRule(
1151 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1154 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1159 self.logger.info(self.vapi.cli("sh gbp contract"))
1161 self.send_and_expect_routed(eps[0].itf,
1162 pkt_inter_epg_220_to_222 * 65,
1164 self.router_mac.address)
1167 # remove both contracts, traffic stops in both directions
1169 c2.remove_vpp_config()
1170 c1.remove_vpp_config()
1171 c3.remove_vpp_config()
1172 acl.remove_vpp_config()
1174 self.send_and_assert_no_replies(eps[2].itf,
1175 pkt_inter_epg_221_to_220 * 65)
1176 self.send_and_assert_no_replies(eps[0].itf,
1177 pkt_inter_epg_220_to_221 * 65)
1178 self.send_and_expect_bridged(eps[0].itf,
1183 # EPs to the outside world
1186 # in the EP's RD an external subnet via the NAT EPG's recirc
1188 self, rd0, "0.0.0.0", 0,
1189 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1190 sw_if_index=recirc_nat.recirc.sw_if_index,
1193 self, rd0, "11.0.0.0", 8,
1194 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1195 sw_if_index=recirc_nat.recirc.sw_if_index,
1197 se16 = VppGbpSubnet(
1199 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1200 sw_if_index=recirc_nat.recirc.sw_if_index,
1202 # in the NAT RD an external subnet via the NAT EPG's uplink
1204 self, rd20, "0.0.0.0", 0,
1205 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1206 sw_if_index=epg_nat.uplink.sw_if_index,
1208 se36 = VppGbpSubnet(
1209 self, rd20, "::", 0,
1210 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1211 sw_if_index=epg_nat.uplink.sw_if_index,
1214 self, rd20, "11.0.0.0", 8,
1215 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1216 sw_if_index=epg_nat.uplink.sw_if_index,
1218 se1.add_vpp_config()
1219 se2.add_vpp_config()
1220 se16.add_vpp_config()
1221 se3.add_vpp_config()
1222 se36.add_vpp_config()
1223 se4.add_vpp_config()
1225 self.logger.info(self.vapi.cli("sh ip fib 0.0.0.0/0"))
1226 self.logger.info(self.vapi.cli("sh ip fib 11.0.0.1"))
1227 self.logger.info(self.vapi.cli("sh ip6 fib ::/0"))
1228 self.logger.info(self.vapi.cli("sh ip6 fib %s" %
1232 # From an EP to an outside addess: IN2OUT
1234 pkt_inter_epg_220_to_global = (Ether(src=self.pg0.remote_mac,
1235 dst=self.router_mac.address) /
1236 IP(src=eps[0].ip4.address,
1238 UDP(sport=1234, dport=1234) /
1242 self.send_and_assert_no_replies(eps[0].itf,
1243 pkt_inter_epg_220_to_global * 65)
1245 acl2 = VppGbpAcl(self)
1246 rule = acl2.create_rule(permit_deny=1, proto=17, sport_from=1234,
1247 sport_to=1234, dport_from=1234, dport_to=1234)
1248 rule2 = acl2.create_rule(is_ipv6=1, permit_deny=1, proto=17,
1249 sport_from=1234, sport_to=1234,
1250 dport_from=1234, dport_to=1234)
1252 acl_index2 = acl2.add_vpp_config([rule, rule2])
1253 c4 = VppGbpContract(
1254 self, 220, 333, acl_index2,
1255 [VppGbpContractRule(
1256 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1259 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1264 self.send_and_expect_natted(eps[0].itf,
1265 pkt_inter_epg_220_to_global * 65,
1267 eps[0].fip4.address)
1269 pkt_inter_epg_220_to_global = (Ether(src=self.pg0.remote_mac,
1270 dst=self.router_mac.address) /
1271 IPv6(src=eps[0].ip6.address,
1273 UDP(sport=1234, dport=1234) /
1276 self.send_and_expect_natted6(self.pg0,
1277 pkt_inter_epg_220_to_global * 65,
1279 eps[0].fip6.address)
1282 # From a global address to an EP: OUT2IN
1284 pkt_inter_epg_220_from_global = (Ether(src=self.router_mac.address,
1285 dst=self.pg0.remote_mac) /
1286 IP(dst=eps[0].fip4.address,
1288 UDP(sport=1234, dport=1234) /
1291 self.send_and_assert_no_replies(self.pg7,
1292 pkt_inter_epg_220_from_global * 65)
1294 c5 = VppGbpContract(
1295 self, 333, 220, acl_index2,
1296 [VppGbpContractRule(
1297 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1300 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1305 self.send_and_expect_unnatted(self.pg7,
1306 pkt_inter_epg_220_from_global * 65,
1310 pkt_inter_epg_220_from_global = (Ether(src=self.router_mac.address,
1311 dst=self.pg0.remote_mac) /
1312 IPv6(dst=eps[0].fip6.address,
1314 UDP(sport=1234, dport=1234) /
1317 self.send_and_expect_unnatted6(self.pg7,
1318 pkt_inter_epg_220_from_global * 65,
1323 # From a local VM to another local VM using resp. public addresses:
1326 pkt_intra_epg_220_global = (Ether(src=self.pg0.remote_mac,
1327 dst=self.router_mac.address) /
1328 IP(src=eps[0].ip4.address,
1329 dst=eps[1].fip4.address) /
1330 UDP(sport=1234, dport=1234) /
1333 self.send_and_expect_double_natted(eps[0].itf,
1334 pkt_intra_epg_220_global * 65,
1336 eps[0].fip4.address,
1339 pkt_intra_epg_220_global = (Ether(src=self.pg0.remote_mac,
1340 dst=self.router_mac.address) /
1341 IPv6(src=eps[0].ip6.address,
1342 dst=eps[1].fip6.address) /
1343 UDP(sport=1234, dport=1234) /
1346 self.send_and_expect_double_natted6(eps[0].itf,
1347 pkt_intra_epg_220_global * 65,
1349 eps[0].fip6.address,
1356 # del static mappings for each EP from the 10/8 to 11/8 network
1357 self.vapi.nat44_add_del_static_mapping(ep.ip4.bytes,
1362 self.vapi.nat66_add_del_static_mapping(ep.ip6.bytes,
1368 # IP config on the BVI interfaces
1369 if epg != epgs[0] and epg != epgs[3]:
1370 self.vapi.nat44_interface_add_del_feature(epg.bvi.sw_if_index,
1373 self.vapi.nat66_add_del_interface(epg.bvi.sw_if_index,
1377 for recirc in recircs:
1378 self.vapi.sw_interface_set_l2_emulation(
1379 recirc.recirc.sw_if_index, enable=0)
1380 self.vapi.nat44_interface_add_del_feature(
1381 recirc.recirc.sw_if_index,
1384 self.vapi.nat66_add_del_interface(
1385 recirc.recirc.sw_if_index,
1389 def test_gbp_learn_l2(self):
1390 """ GBP L2 Endpoint Learning """
1392 learnt = [{'mac': '00:00:11:11:11:01',
1394 'ip6': '2001:10::2'},
1395 {'mac': '00:00:11:11:11:02',
1397 'ip6': '2001:10::3'}]
1400 # lower the inactive threshold so these tests pass in a
1401 # reasonable amount of time
1403 self.vapi.gbp_endpoint_learn_set_inactive_threshold(1)
1408 gt4 = VppIpTable(self, 1)
1409 gt4.add_vpp_config()
1410 gt6 = VppIpTable(self, 1, is_ip6=True)
1411 gt6.add_vpp_config()
1413 rd1 = VppGbpRouteDomain(self, 1, gt4, gt6)
1414 rd1.add_vpp_config()
1417 # Pg2 hosts the vxlan tunnel, hosts on pg2 to act as TEPs
1418 # Pg3 hosts the IP4 UU-flood VXLAN tunnel
1419 # Pg4 hosts the IP6 UU-flood VXLAN tunnel
1421 self.pg2.config_ip4()
1422 self.pg2.resolve_arp()
1423 self.pg2.generate_remote_hosts(4)
1424 self.pg2.configure_ipv4_neighbors()
1425 self.pg3.config_ip4()
1426 self.pg3.resolve_arp()
1427 self.pg4.config_ip4()
1428 self.pg4.resolve_arp()
1431 # a GBP bridge domain with a BVI and a UU-flood interface
1433 bd1 = VppBridgeDomain(self, 1)
1434 bd1.add_vpp_config()
1435 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0, self.pg3)
1436 gbd1.add_vpp_config()
1438 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1439 self.logger.info(self.vapi.cli("sh gbp bridge"))
1441 # ... and has a /32 applied
1442 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
1443 ip_addr.add_vpp_config()
1446 # The Endpoint-group in which we are learning endpoints
1448 epg_220 = VppGbpEndpointGroup(self, 220, rd1, gbd1,
1452 epg_220.add_vpp_config()
1453 epg_330 = VppGbpEndpointGroup(self, 330, rd1, gbd1,
1457 epg_330.add_vpp_config()
1460 # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
1463 vx_tun_l2_1 = VppGbpVxlanTunnel(
1464 self, 99, bd1.bd_id,
1465 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L2)
1466 vx_tun_l2_1.add_vpp_config()
1469 # A static endpoint that the learnt endpoints are trying to
1472 ep = VppGbpEndpoint(self, self.pg0,
1474 "10.0.0.127", "11.0.0.127",
1475 "2001:10::1", "3001::1")
1478 self.assertTrue(find_route(self, ep.ip4.address, 32, table_id=1))
1480 # a packet with an sclass from an unknwon EPG
1481 p = (Ether(src=self.pg2.remote_mac,
1482 dst=self.pg2.local_mac) /
1483 IP(src=self.pg2.remote_hosts[0].ip4,
1484 dst=self.pg2.local_ip4) /
1485 UDP(sport=1234, dport=48879) /
1486 VXLAN(vni=99, gpid=88, flags=0x88) /
1487 Ether(src=learnt[0]["mac"], dst=ep.mac) /
1488 IP(src=learnt[0]["ip"], dst=ep.ip4.address) /
1489 UDP(sport=1234, dport=1234) /
1492 self.send_and_assert_no_replies(self.pg2, p)
1495 # we should not have learnt a new tunnel endpoint, since
1496 # the EPG was not learnt.
1498 self.assertEqual(INDEX_INVALID,
1499 find_vxlan_gbp_tunnel(self,
1501 self.pg2.remote_hosts[0].ip4,
1504 # epg is not learnt, becasue the EPG is unknwon
1505 self.assertEqual(len(self.vapi.gbp_endpoint_dump()), 1)
1507 for ii, l in enumerate(learnt):
1508 # a packet with an sclass from a knwon EPG
1509 # arriving on an unknown TEP
1510 p = (Ether(src=self.pg2.remote_mac,
1511 dst=self.pg2.local_mac) /
1512 IP(src=self.pg2.remote_hosts[1].ip4,
1513 dst=self.pg2.local_ip4) /
1514 UDP(sport=1234, dport=48879) /
1515 VXLAN(vni=99, gpid=220, flags=0x88) /
1516 Ether(src=l['mac'], dst=ep.mac) /
1517 IP(src=l['ip'], dst=ep.ip4.address) /
1518 UDP(sport=1234, dport=1234) /
1521 rx = self.send_and_expect(self.pg2, [p], self.pg0)
1524 tep1_sw_if_index = find_vxlan_gbp_tunnel(
1527 self.pg2.remote_hosts[1].ip4,
1529 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
1532 # the EP is learnt via the learnt TEP
1533 # both from its MAC and its IP
1535 self.assertTrue(find_gbp_endpoint(self,
1536 vx_tun_l2_1.sw_if_index,
1538 self.assertTrue(find_gbp_endpoint(self,
1539 vx_tun_l2_1.sw_if_index,
1542 self.logger.info(self.vapi.cli("show gbp endpoint"))
1543 self.logger.info(self.vapi.cli("show gbp vxlan"))
1544 self.logger.info(self.vapi.cli("show vxlan-gbp tunnel"))
1547 # If we sleep for the threshold time, the learnt endpoints should
1552 self.assertFalse(find_gbp_endpoint(self,
1556 self.logger.info(self.vapi.cli("show gbp endpoint"))
1557 self.logger.info(self.vapi.cli("show gbp vxlan"))
1558 self.logger.info(self.vapi.cli("show vxlan-gbp tunnel"))
1561 # repeat. the do not learn bit is set so the EPs are not learnt
1564 # a packet with an sclass from a knwon EPG
1565 p = (Ether(src=self.pg2.remote_mac,
1566 dst=self.pg2.local_mac) /
1567 IP(src=self.pg2.remote_hosts[1].ip4,
1568 dst=self.pg2.local_ip4) /
1569 UDP(sport=1234, dport=48879) /
1570 VXLAN(vni=99, gpid=220, flags=0x88, gpflags="D") /
1571 Ether(src=l['mac'], dst=ep.mac) /
1572 IP(src=l['ip'], dst=ep.ip4.address) /
1573 UDP(sport=1234, dport=1234) /
1576 rx = self.send_and_expect(self.pg2, p*65, self.pg0)
1579 self.assertFalse(find_gbp_endpoint(self,
1580 vx_tun_l2_1.sw_if_index,
1587 # a packet with an sclass from a knwon EPG
1588 p = (Ether(src=self.pg2.remote_mac,
1589 dst=self.pg2.local_mac) /
1590 IP(src=self.pg2.remote_hosts[1].ip4,
1591 dst=self.pg2.local_ip4) /
1592 UDP(sport=1234, dport=48879) /
1593 VXLAN(vni=99, gpid=220, flags=0x88) /
1594 Ether(src=l['mac'], dst=ep.mac) /
1595 IP(src=l['ip'], dst=ep.ip4.address) /
1596 UDP(sport=1234, dport=1234) /
1599 rx = self.send_and_expect(self.pg2, p*65, self.pg0)
1601 self.assertTrue(find_gbp_endpoint(self,
1602 vx_tun_l2_1.sw_if_index,
1606 # Static EP replies to dynamics
1608 self.logger.info(self.vapi.cli("sh l2fib bd_id 1"))
1610 p = (Ether(src=ep.mac, dst=l['mac']) /
1611 IP(dst=l['ip'], src=ep.ip4.address) /
1612 UDP(sport=1234, dport=1234) /
1615 rxs = self.send_and_expect(self.pg0, p * 17, self.pg2)
1618 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
1619 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
1620 self.assertEqual(rx[UDP].dport, 48879)
1621 # the UDP source port is a random value for hashing
1622 self.assertEqual(rx[VXLAN].gpid, 220)
1623 self.assertEqual(rx[VXLAN].vni, 99)
1624 self.assertTrue(rx[VXLAN].flags.G)
1625 self.assertTrue(rx[VXLAN].flags.Instance)
1626 self.assertTrue(rx[VXLAN].gpflags.A)
1627 self.assertFalse(rx[VXLAN].gpflags.D)
1631 self.assertFalse(find_gbp_endpoint(self,
1632 vx_tun_l2_1.sw_if_index,
1636 # repeat in the other EPG
1637 # there's no contract between 220 and 330, but the A-bit is set
1638 # so the packet is cleared for delivery
1641 # a packet with an sclass from a knwon EPG
1642 p = (Ether(src=self.pg2.remote_mac,
1643 dst=self.pg2.local_mac) /
1644 IP(src=self.pg2.remote_hosts[1].ip4,
1645 dst=self.pg2.local_ip4) /
1646 UDP(sport=1234, dport=48879) /
1647 VXLAN(vni=99, gpid=330, flags=0x88, gpflags='A') /
1648 Ether(src=l['mac'], dst=ep.mac) /
1649 IP(src=l['ip'], dst=ep.ip4.address) /
1650 UDP(sport=1234, dport=1234) /
1653 rx = self.send_and_expect(self.pg2, p*65, self.pg0)
1655 self.assertTrue(find_gbp_endpoint(self,
1656 vx_tun_l2_1.sw_if_index,
1660 # static EP cannot reach the learnt EPs since there is no contract
1661 # only test 1 EP as the others could timeout
1663 p = (Ether(src=ep.mac, dst=l['mac']) /
1664 IP(dst=learnt[0]['ip'], src=ep.ip4.address) /
1665 UDP(sport=1234, dport=1234) /
1668 self.send_and_assert_no_replies(self.pg0, [p])
1671 # refresh the entries after the check for no replies above
1674 # a packet with an sclass from a knwon EPG
1675 p = (Ether(src=self.pg2.remote_mac,
1676 dst=self.pg2.local_mac) /
1677 IP(src=self.pg2.remote_hosts[1].ip4,
1678 dst=self.pg2.local_ip4) /
1679 UDP(sport=1234, dport=48879) /
1680 VXLAN(vni=99, gpid=330, flags=0x88, gpflags='A') /
1681 Ether(src=l['mac'], dst=ep.mac) /
1682 IP(src=l['ip'], dst=ep.ip4.address) /
1683 UDP(sport=1234, dport=1234) /
1686 rx = self.send_and_expect(self.pg2, p*65, self.pg0)
1688 self.assertTrue(find_gbp_endpoint(self,
1689 vx_tun_l2_1.sw_if_index,
1693 # Add the contract so they can talk
1695 acl = VppGbpAcl(self)
1696 rule = acl.create_rule(permit_deny=1, proto=17)
1697 rule2 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
1698 acl_index = acl.add_vpp_config([rule, rule2])
1699 c1 = VppGbpContract(
1700 self, 220, 330, acl_index,
1701 [VppGbpContractRule(
1702 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1705 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1711 p = (Ether(src=ep.mac, dst=l['mac']) /
1712 IP(dst=l['ip'], src=ep.ip4.address) /
1713 UDP(sport=1234, dport=1234) /
1716 self.send_and_expect(self.pg0, [p], self.pg2)
1719 # send UU packets from the local EP
1721 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1722 self.logger.info(self.vapi.cli("sh gbp bridge"))
1723 p_uu = (Ether(src=ep.mac, dst="00:11:11:11:11:11") /
1724 IP(dst="10.0.0.133", src=ep.ip4.address) /
1725 UDP(sport=1234, dport=1234) /
1727 rxs = self.send_and_expect(ep.itf, [p_uu], gbd1.uu_flood)
1730 # Add a mcast destination VXLAN-GBP tunnel for B&M traffic
1732 tun_bm = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
1735 tun_bm.add_vpp_config()
1736 bp_bm = VppBridgeDomainPort(self, bd1, tun_bm,
1737 port_type=L2_PORT_TYPE.NORMAL)
1738 bp_bm.add_vpp_config()
1740 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1742 p_bm = (Ether(src=ep.mac, dst="ff:ff:ff:ff:ff:ff") /
1743 IP(dst="10.0.0.133", src=ep.ip4.address) /
1744 UDP(sport=1234, dport=1234) /
1746 rxs = self.send_and_expect_only(ep.itf, [p_bm], tun_bm.mcast_itf)
1749 # Check v6 Endpoints
1752 # a packet with an sclass from a knwon EPG
1753 p = (Ether(src=self.pg2.remote_mac,
1754 dst=self.pg2.local_mac) /
1755 IP(src=self.pg2.remote_hosts[1].ip4,
1756 dst=self.pg2.local_ip4) /
1757 UDP(sport=1234, dport=48879) /
1758 VXLAN(vni=99, gpid=330, flags=0x88, gpflags='A') /
1759 Ether(src=l['mac'], dst=ep.mac) /
1760 IPv6(src=l['ip6'], dst=ep.ip6.address) /
1761 UDP(sport=1234, dport=1234) /
1764 rx = self.send_and_expect(self.pg2, p*65, self.pg0)
1766 self.assertTrue(find_gbp_endpoint(self,
1767 vx_tun_l2_1.sw_if_index,
1771 # L3 Endpoint Learning
1772 # - configured on the bridge's BVI
1780 self.assertFalse(find_gbp_endpoint(self,
1781 vx_tun_l2_1.sw_if_index,
1784 self.pg2.unconfig_ip4()
1785 self.pg3.unconfig_ip4()
1786 self.pg4.unconfig_ip4()
1788 self.logger.info(self.vapi.cli("sh int"))
1789 self.logger.info(self.vapi.cli("sh gbp vxlan"))
1791 def test_gbp_learn_vlan_l2(self):
1792 """ GBP L2 Endpoint w/ VLANs"""
1794 learnt = [{'mac': '00:00:11:11:11:01',
1796 'ip6': '2001:10::2'},
1797 {'mac': '00:00:11:11:11:02',
1799 'ip6': '2001:10::3'}]
1802 # lower the inactive threshold so these tests pass in a
1803 # reasonable amount of time
1805 self.vapi.gbp_endpoint_learn_set_inactive_threshold(1)
1810 gt4 = VppIpTable(self, 1)
1811 gt4.add_vpp_config()
1812 gt6 = VppIpTable(self, 1, is_ip6=True)
1813 gt6.add_vpp_config()
1815 rd1 = VppGbpRouteDomain(self, 1, gt4, gt6)
1816 rd1.add_vpp_config()
1819 # Pg2 hosts the vxlan tunnel, hosts on pg2 to act as TEPs
1821 self.pg2.config_ip4()
1822 self.pg2.resolve_arp()
1823 self.pg2.generate_remote_hosts(4)
1824 self.pg2.configure_ipv4_neighbors()
1825 self.pg3.config_ip4()
1826 self.pg3.resolve_arp()
1829 # The EP will be on a vlan sub-interface
1831 vlan_11 = VppDot1QSubint(self, self.pg0, 11)
1833 self.vapi.sw_interface_set_l2_tag_rewrite(vlan_11.sw_if_index,
1837 bd_uu_fwd = VppVxlanGbpTunnel(self, self.pg3.local_ip4,
1838 self.pg3.remote_ip4, 116)
1839 bd_uu_fwd.add_vpp_config()
1842 # a GBP bridge domain with a BVI and a UU-flood interface
1843 # The BD is marked as do not learn, so no endpoints are ever
1844 # learnt in this BD.
1846 bd1 = VppBridgeDomain(self, 1)
1847 bd1.add_vpp_config()
1848 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0, bd_uu_fwd,
1850 gbd1.add_vpp_config()
1852 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1853 self.logger.info(self.vapi.cli("sh gbp bridge"))
1855 # ... and has a /32 applied
1856 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
1857 ip_addr.add_vpp_config()
1860 # The Endpoint-group in which we are learning endpoints
1862 epg_220 = VppGbpEndpointGroup(self, 220, rd1, gbd1,
1866 epg_220.add_vpp_config()
1869 # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
1872 vx_tun_l2_1 = VppGbpVxlanTunnel(
1873 self, 99, bd1.bd_id,
1874 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L2)
1875 vx_tun_l2_1.add_vpp_config()
1878 # A static endpoint that the learnt endpoints are trying to
1881 ep = VppGbpEndpoint(self, vlan_11,
1883 "10.0.0.127", "11.0.0.127",
1884 "2001:10::1", "3001::1")
1887 self.assertTrue(find_route(self, ep.ip4.address, 32, table_id=1))
1890 # Send to the static EP
1892 for ii, l in enumerate(learnt):
1893 # a packet with an sclass from a knwon EPG
1894 # arriving on an unknown TEP
1895 p = (Ether(src=self.pg2.remote_mac,
1896 dst=self.pg2.local_mac) /
1897 IP(src=self.pg2.remote_hosts[1].ip4,
1898 dst=self.pg2.local_ip4) /
1899 UDP(sport=1234, dport=48879) /
1900 VXLAN(vni=99, gpid=220, flags=0x88) /
1901 Ether(src=l['mac'], dst=ep.mac) /
1902 IP(src=l['ip'], dst=ep.ip4.address) /
1903 UDP(sport=1234, dport=1234) /
1906 rxs = self.send_and_expect(self.pg2, [p], self.pg0)
1909 # packet to EP has the EP's vlan tag
1912 self.assertEqual(rx[Dot1Q].vlan, 11)
1915 # the EP is not learnt since the BD setting prevents it
1918 self.assertFalse(find_gbp_endpoint(self,
1919 vx_tun_l2_1.sw_if_index,
1921 self.assertEqual(INDEX_INVALID,
1922 find_vxlan_gbp_tunnel(
1925 self.pg2.remote_hosts[1].ip4,
1928 self.assertEqual(len(self.vapi.gbp_endpoint_dump()), 1)
1932 # we didn't learn the remotes so they are sent to the UU-fwd
1935 p = (Ether(src=ep.mac, dst=l['mac']) /
1937 IP(dst=l['ip'], src=ep.ip4.address) /
1938 UDP(sport=1234, dport=1234) /
1941 rxs = self.send_and_expect(self.pg0, p * 17, self.pg3)
1944 self.assertEqual(rx[IP].src, self.pg3.local_ip4)
1945 self.assertEqual(rx[IP].dst, self.pg3.remote_ip4)
1946 self.assertEqual(rx[UDP].dport, 48879)
1947 # the UDP source port is a random value for hashing
1948 self.assertEqual(rx[VXLAN].gpid, 220)
1949 self.assertEqual(rx[VXLAN].vni, 116)
1950 self.assertTrue(rx[VXLAN].flags.G)
1951 self.assertTrue(rx[VXLAN].flags.Instance)
1952 self.assertFalse(rx[VXLAN].gpflags.A)
1953 self.assertFalse(rx[VXLAN].gpflags.D)
1955 self.pg2.unconfig_ip4()
1956 self.pg3.unconfig_ip4()
1958 def test_gbp_learn_l3(self):
1959 """ GBP L3 Endpoint Learning """
1961 self.vapi.cli("set logging class gbp debug")
1963 routed_dst_mac = "00:0c:0c:0c:0c:0c"
1964 routed_src_mac = "00:22:bd:f8:19:ff"
1966 learnt = [{'mac': '00:00:11:11:11:02',
1968 'ip6': '2001:10::2'},
1969 {'mac': '00:00:11:11:11:03',
1971 'ip6': '2001:10::3'}]
1974 # lower the inactive threshold so these tests pass in a
1975 # reasonable amount of time
1977 self.vapi.gbp_endpoint_learn_set_inactive_threshold(1)
1982 t4 = VppIpTable(self, 1)
1984 t6 = VppIpTable(self, 1, True)
1987 tun_ip4_uu = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
1988 self.pg4.remote_ip4, 114)
1989 tun_ip6_uu = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
1990 self.pg4.remote_ip4, 116)
1991 tun_ip4_uu.add_vpp_config()
1992 tun_ip6_uu.add_vpp_config()
1994 rd1 = VppGbpRouteDomain(self, 2, t4, t6, tun_ip4_uu, tun_ip6_uu)
1995 rd1.add_vpp_config()
1997 self.loop0.set_mac(self.router_mac.address)
2000 # Bind the BVI to the RD
2002 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
2003 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
2006 # Pg2 hosts the vxlan tunnel
2007 # hosts on pg2 to act as TEPs
2011 self.pg2.config_ip4()
2012 self.pg2.resolve_arp()
2013 self.pg2.generate_remote_hosts(4)
2014 self.pg2.configure_ipv4_neighbors()
2015 self.pg3.config_ip4()
2016 self.pg3.resolve_arp()
2017 self.pg4.config_ip4()
2018 self.pg4.resolve_arp()
2021 # a GBP bridge domain with a BVI and a UU-flood interface
2023 bd1 = VppBridgeDomain(self, 1)
2024 bd1.add_vpp_config()
2025 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0, self.pg3)
2026 gbd1.add_vpp_config()
2028 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2029 self.logger.info(self.vapi.cli("sh gbp bridge"))
2030 self.logger.info(self.vapi.cli("sh gbp route"))
2032 # ... and has a /32 and /128 applied
2033 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2034 ip4_addr.add_vpp_config()
2035 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 128)
2036 ip6_addr.add_vpp_config()
2039 # The Endpoint-group in which we are learning endpoints
2041 epg_220 = VppGbpEndpointGroup(self, 220, rd1, gbd1,
2045 epg_220.add_vpp_config()
2048 # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
2051 vx_tun_l3 = VppGbpVxlanTunnel(
2052 self, 101, rd1.rd_id,
2053 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3)
2054 vx_tun_l3.add_vpp_config()
2057 # A static endpoint that the learnt endpoints are trying to
2060 ep = VppGbpEndpoint(self, self.pg0,
2062 "10.0.0.127", "11.0.0.127",
2063 "2001:10::1", "3001::1")
2067 # learn some remote IPv4 EPs
2069 for ii, l in enumerate(learnt):
2070 # a packet with an sclass from a knwon EPG
2071 # arriving on an unknown TEP
2072 p = (Ether(src=self.pg2.remote_mac,
2073 dst=self.pg2.local_mac) /
2074 IP(src=self.pg2.remote_hosts[1].ip4,
2075 dst=self.pg2.local_ip4) /
2076 UDP(sport=1234, dport=48879) /
2077 VXLAN(vni=101, gpid=220, flags=0x88) /
2078 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2079 IP(src=l['ip'], dst=ep.ip4.address) /
2080 UDP(sport=1234, dport=1234) /
2083 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2086 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2089 self.pg2.remote_hosts[1].ip4,
2091 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2093 # endpoint learnt via the parent GBP-vxlan interface
2094 self.assertTrue(find_gbp_endpoint(self,
2095 vx_tun_l3._sw_if_index,
2099 # Static IPv4 EP replies to learnt
2102 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2103 IP(dst=l['ip'], src=ep.ip4.address) /
2104 UDP(sport=1234, dport=1234) /
2107 rxs = self.send_and_expect(self.pg0, p*1, self.pg2)
2110 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2111 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2112 self.assertEqual(rx[UDP].dport, 48879)
2113 # the UDP source port is a random value for hashing
2114 self.assertEqual(rx[VXLAN].gpid, 220)
2115 self.assertEqual(rx[VXLAN].vni, 101)
2116 self.assertTrue(rx[VXLAN].flags.G)
2117 self.assertTrue(rx[VXLAN].flags.Instance)
2118 self.assertTrue(rx[VXLAN].gpflags.A)
2119 self.assertFalse(rx[VXLAN].gpflags.D)
2121 inner = rx[VXLAN].payload
2123 self.assertEqual(inner[Ether].src, routed_src_mac)
2124 self.assertEqual(inner[Ether].dst, routed_dst_mac)
2125 self.assertEqual(inner[IP].src, ep.ip4.address)
2126 self.assertEqual(inner[IP].dst, l['ip'])
2130 self.assertFalse(find_gbp_endpoint(self,
2135 # learn some remote IPv6 EPs
2137 for ii, l in enumerate(learnt):
2138 # a packet with an sclass from a knwon EPG
2139 # arriving on an unknown TEP
2140 p = (Ether(src=self.pg2.remote_mac,
2141 dst=self.pg2.local_mac) /
2142 IP(src=self.pg2.remote_hosts[1].ip4,
2143 dst=self.pg2.local_ip4) /
2144 UDP(sport=1234, dport=48879) /
2145 VXLAN(vni=101, gpid=220, flags=0x88) /
2146 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2147 IPv6(src=l['ip6'], dst=ep.ip6.address) /
2148 UDP(sport=1234, dport=1234) /
2151 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2154 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2157 self.pg2.remote_hosts[1].ip4,
2159 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2161 self.logger.info(self.vapi.cli("show gbp bridge"))
2162 self.logger.info(self.vapi.cli("show vxlan-gbp tunnel"))
2163 self.logger.info(self.vapi.cli("show gbp vxlan"))
2164 self.logger.info(self.vapi.cli("show int addr"))
2166 # endpoint learnt via the TEP
2167 self.assertTrue(find_gbp_endpoint(self, ip=l['ip6']))
2169 self.logger.info(self.vapi.cli("show gbp endpoint"))
2170 self.logger.info(self.vapi.cli("show ip fib index 1 %s" % l['ip']))
2173 # Static EP replies to learnt
2176 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2177 IPv6(dst=l['ip6'], src=ep.ip6.address) /
2178 UDP(sport=1234, dport=1234) /
2181 rxs = self.send_and_expect(self.pg0, p*65, self.pg2)
2184 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2185 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2186 self.assertEqual(rx[UDP].dport, 48879)
2187 # the UDP source port is a random value for hashing
2188 self.assertEqual(rx[VXLAN].gpid, 220)
2189 self.assertEqual(rx[VXLAN].vni, 101)
2190 self.assertTrue(rx[VXLAN].flags.G)
2191 self.assertTrue(rx[VXLAN].flags.Instance)
2192 self.assertTrue(rx[VXLAN].gpflags.A)
2193 self.assertFalse(rx[VXLAN].gpflags.D)
2195 inner = rx[VXLAN].payload
2197 self.assertEqual(inner[Ether].src, routed_src_mac)
2198 self.assertEqual(inner[Ether].dst, routed_dst_mac)
2199 self.assertEqual(inner[IPv6].src, ep.ip6.address)
2200 self.assertEqual(inner[IPv6].dst, l['ip6'])
2202 self.logger.info(self.vapi.cli("sh gbp endpoint"))
2205 self.assertFalse(find_gbp_endpoint(self,
2210 # Static sends to unknown EP with no route
2212 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2213 IP(dst="10.0.0.99", src=ep.ip4.address) /
2214 UDP(sport=1234, dport=1234) /
2217 self.send_and_assert_no_replies(self.pg0, [p])
2220 # Add a route to static EP's v4 and v6 subnet
2221 # packets should be send on the v4/v6 uu=fwd interface resp.
2223 se_10_24 = VppGbpSubnet(
2224 self, rd1, "10.0.0.0", 24,
2225 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT)
2226 se_10_24.add_vpp_config()
2228 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2229 IP(dst="10.0.0.99", src=ep.ip4.address) /
2230 UDP(sport=1234, dport=1234) /
2233 rxs = self.send_and_expect(self.pg0, [p], self.pg4)
2235 self.assertEqual(rx[IP].src, self.pg4.local_ip4)
2236 self.assertEqual(rx[IP].dst, self.pg4.remote_ip4)
2237 self.assertEqual(rx[UDP].dport, 48879)
2238 # the UDP source port is a random value for hashing
2239 self.assertEqual(rx[VXLAN].gpid, 220)
2240 self.assertEqual(rx[VXLAN].vni, 114)
2241 self.assertTrue(rx[VXLAN].flags.G)
2242 self.assertTrue(rx[VXLAN].flags.Instance)
2243 # policy is not applied to packets sent to the uu-fwd interfaces
2244 self.assertFalse(rx[VXLAN].gpflags.A)
2245 self.assertFalse(rx[VXLAN].gpflags.D)
2248 # learn some remote IPv4 EPs
2250 for ii, l in enumerate(learnt):
2251 # a packet with an sclass from a knwon EPG
2252 # arriving on an unknown TEP
2253 p = (Ether(src=self.pg2.remote_mac,
2254 dst=self.pg2.local_mac) /
2255 IP(src=self.pg2.remote_hosts[1].ip4,
2256 dst=self.pg2.local_ip4) /
2257 UDP(sport=1234, dport=48879) /
2258 VXLAN(vni=101, gpid=220, flags=0x88) /
2259 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2260 IP(src=l['ip'], dst=ep.ip4.address) /
2261 UDP(sport=1234, dport=1234) /
2264 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2267 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2270 self.pg2.remote_hosts[1].ip4,
2272 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2274 # endpoint learnt via the parent GBP-vxlan interface
2275 self.assertTrue(find_gbp_endpoint(self,
2276 vx_tun_l3._sw_if_index,
2280 # Add a remote endpoint from the API
2282 rep_88 = VppGbpEndpoint(self, vx_tun_l3,
2284 "10.0.0.88", "11.0.0.88",
2285 "2001:10::88", "3001::88",
2286 VppEnum.vl_api_gbp_endpoint_flags_t.REMOTE,
2288 self.pg2.remote_hosts[1].ip4,
2290 rep_88.add_vpp_config()
2293 # Add a remote endpoint from the API that matches an existing one
2295 rep_2 = VppGbpEndpoint(self, vx_tun_l3,
2297 learnt[0]['ip'], "11.0.0.101",
2298 learnt[0]['ip6'], "3001::101",
2299 VppEnum.vl_api_gbp_endpoint_flags_t.REMOTE,
2301 self.pg2.remote_hosts[1].ip4,
2303 rep_2.add_vpp_config()
2306 # Add a route to the leanred EP's v4 subnet
2307 # packets should be send on the v4/v6 uu=fwd interface resp.
2309 se_10_1_24 = VppGbpSubnet(
2310 self, rd1, "10.0.1.0", 24,
2311 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT)
2312 se_10_1_24.add_vpp_config()
2314 self.logger.info(self.vapi.cli("show gbp endpoint"))
2316 ips = ["10.0.0.88", learnt[0]['ip']]
2318 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2319 IP(dst=ip, src=ep.ip4.address) /
2320 UDP(sport=1234, dport=1234) /
2323 rxs = self.send_and_expect(self.pg0, p*65, self.pg2)
2326 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2327 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2328 self.assertEqual(rx[UDP].dport, 48879)
2329 # the UDP source port is a random value for hashing
2330 self.assertEqual(rx[VXLAN].gpid, 220)
2331 self.assertEqual(rx[VXLAN].vni, 101)
2332 self.assertTrue(rx[VXLAN].flags.G)
2333 self.assertTrue(rx[VXLAN].flags.Instance)
2334 self.assertTrue(rx[VXLAN].gpflags.A)
2335 self.assertFalse(rx[VXLAN].gpflags.D)
2337 inner = rx[VXLAN].payload
2339 self.assertEqual(inner[Ether].src, routed_src_mac)
2340 self.assertEqual(inner[Ether].dst, routed_dst_mac)
2341 self.assertEqual(inner[IP].src, ep.ip4.address)
2342 self.assertEqual(inner[IP].dst, ip)
2345 # remove the API remote EPs, only API sourced is gone, the DP
2346 # learnt one remains
2348 rep_88.remove_vpp_config()
2349 rep_2.remove_vpp_config()
2351 self.logger.info(self.vapi.cli("show gbp endpoint"))
2353 self.assertFalse(find_gbp_endpoint(self, ip=rep_88.ip4.address))
2355 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2356 IP(src=ep.ip4.address, dst=rep_88.ip4.address) /
2357 UDP(sport=1234, dport=1234) /
2359 rxs = self.send_and_expect(self.pg0, [p], self.pg4)
2361 self.assertTrue(find_gbp_endpoint(self, ip=rep_2.ip4.address))
2363 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2364 IP(src=ep.ip4.address, dst=rep_2.ip4.address) /
2365 UDP(sport=1234, dport=1234) /
2367 rxs = self.send_and_expect(self.pg0, [p], self.pg2)
2370 # to appease the testcase we cannot have the registered EP stll
2371 # present (because it's DP learnt) when the TC ends so wait until
2377 # shutdown with learnt endpoint present
2379 p = (Ether(src=self.pg2.remote_mac,
2380 dst=self.pg2.local_mac) /
2381 IP(src=self.pg2.remote_hosts[1].ip4,
2382 dst=self.pg2.local_ip4) /
2383 UDP(sport=1234, dport=48879) /
2384 VXLAN(vni=101, gpid=220, flags=0x88) /
2385 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2386 IP(src=learnt[1]['ip'], dst=ep.ip4.address) /
2387 UDP(sport=1234, dport=1234) /
2390 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2392 # endpoint learnt via the parent GBP-vxlan interface
2393 self.assertTrue(find_gbp_endpoint(self,
2394 vx_tun_l3._sw_if_index,
2399 # remote endpoint becomes local
2401 self.pg2.unconfig_ip4()
2402 self.pg3.unconfig_ip4()
2403 self.pg4.unconfig_ip4()
2405 def test_gbp_redirect(self):
2406 """ GBP Endpoint Redirect """
2408 self.vapi.cli("set logging class gbp debug")
2410 routed_dst_mac = "00:0c:0c:0c:0c:0c"
2411 routed_src_mac = "00:22:bd:f8:19:ff"
2413 learnt = [{'mac': '00:00:11:11:11:02',
2415 'ip6': '2001:10::2'},
2416 {'mac': '00:00:11:11:11:03',
2418 'ip6': '2001:10::3'}]
2421 # lower the inactive threshold so these tests pass in a
2422 # reasonable amount of time
2424 self.vapi.gbp_endpoint_learn_set_inactive_threshold(1)
2429 t4 = VppIpTable(self, 1)
2431 t6 = VppIpTable(self, 1, True)
2434 rd1 = VppGbpRouteDomain(self, 2, t4, t6)
2435 rd1.add_vpp_config()
2437 self.loop0.set_mac(self.router_mac.address)
2440 # Bind the BVI to the RD
2442 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
2443 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
2446 # Pg7 hosts a BD's UU-fwd
2448 self.pg7.config_ip4()
2449 self.pg7.resolve_arp()
2452 # a GBP bridge domains for the EPs
2454 bd1 = VppBridgeDomain(self, 1)
2455 bd1.add_vpp_config()
2456 gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0)
2457 gbd1.add_vpp_config()
2459 bd2 = VppBridgeDomain(self, 2)
2460 bd2.add_vpp_config()
2461 gbd2 = VppGbpBridgeDomain(self, bd2, self.loop1)
2462 gbd2.add_vpp_config()
2464 # ... and has a /32 and /128 applied
2465 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2466 ip4_addr.add_vpp_config()
2467 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 128)
2468 ip6_addr.add_vpp_config()
2469 ip4_addr = VppIpInterfaceAddress(self, gbd2.bvi, "10.0.1.128", 32)
2470 ip4_addr.add_vpp_config()
2471 ip6_addr = VppIpInterfaceAddress(self, gbd2.bvi, "2001:11::128", 128)
2472 ip6_addr.add_vpp_config()
2475 # The Endpoint-groups in which we are learning endpoints
2477 epg_220 = VppGbpEndpointGroup(self, 220, rd1, gbd1,
2481 epg_220.add_vpp_config()
2482 epg_221 = VppGbpEndpointGroup(self, 221, rd1, gbd2,
2486 epg_221.add_vpp_config()
2487 epg_222 = VppGbpEndpointGroup(self, 222, rd1, gbd1,
2491 epg_222.add_vpp_config()
2494 # a GBP bridge domains for the SEPs
2496 bd_uu1 = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
2497 self.pg7.remote_ip4, 116)
2498 bd_uu1.add_vpp_config()
2499 bd_uu2 = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
2500 self.pg7.remote_ip4, 117)
2501 bd_uu2.add_vpp_config()
2503 bd3 = VppBridgeDomain(self, 3)
2504 bd3.add_vpp_config()
2505 gbd3 = VppGbpBridgeDomain(self, bd3, self.loop2, bd_uu1, learn=False)
2506 gbd3.add_vpp_config()
2507 bd4 = VppBridgeDomain(self, 4)
2508 bd4.add_vpp_config()
2509 gbd4 = VppGbpBridgeDomain(self, bd4, self.loop3, bd_uu2, learn=False)
2510 gbd4.add_vpp_config()
2513 # EPGs in which the service endpoints exist
2515 epg_320 = VppGbpEndpointGroup(self, 320, rd1, gbd3,
2519 epg_320.add_vpp_config()
2520 epg_321 = VppGbpEndpointGroup(self, 321, rd1, gbd4,
2524 epg_321.add_vpp_config()
2527 # three local endpoints
2529 ep1 = VppGbpEndpoint(self, self.pg0,
2531 "10.0.0.1", "11.0.0.1",
2532 "2001:10::1", "3001:10::1")
2533 ep1.add_vpp_config()
2534 ep2 = VppGbpEndpoint(self, self.pg1,
2536 "10.0.1.1", "11.0.1.1",
2537 "2001:11::1", "3001:11::1")
2538 ep2.add_vpp_config()
2539 ep3 = VppGbpEndpoint(self, self.pg2,
2541 "10.0.2.2", "11.0.2.2",
2542 "2001:12::1", "3001:12::1")
2543 ep3.add_vpp_config()
2548 sep1 = VppGbpEndpoint(self, self.pg3,
2550 "12.0.0.1", "13.0.0.1",
2551 "4001:10::1", "5001:10::1")
2552 sep1.add_vpp_config()
2553 sep2 = VppGbpEndpoint(self, self.pg4,
2555 "12.0.0.2", "13.0.0.2",
2556 "4001:10::2", "5001:10::2")
2557 sep2.add_vpp_config()
2558 sep3 = VppGbpEndpoint(self, self.pg5,
2560 "12.0.1.1", "13.0.1.1",
2561 "4001:11::1", "5001:11::1")
2562 sep3.add_vpp_config()
2563 # this EP is not installed immediately
2564 sep4 = VppGbpEndpoint(self, self.pg6,
2566 "12.0.1.2", "13.0.1.2",
2567 "4001:11::2", "5001:11::2")
2570 # an L2 switch packet between local EPs in different EPGs
2571 # different dest ports on each so the are LB hashed differently
2573 p4 = [(Ether(src=ep1.mac, dst=ep3.mac) /
2574 IP(src=ep1.ip4.address, dst=ep3.ip4.address) /
2575 UDP(sport=1234, dport=1234) /
2577 (Ether(src=ep3.mac, dst=ep1.mac) /
2578 IP(src=ep3.ip4.address, dst=ep1.ip4.address) /
2579 UDP(sport=1234, dport=1234) /
2581 p6 = [(Ether(src=ep1.mac, dst=ep3.mac) /
2582 IPv6(src=ep1.ip6.address, dst=ep3.ip6.address) /
2583 UDP(sport=1234, dport=1234) /
2585 (Ether(src=ep3.mac, dst=ep1.mac) /
2586 IPv6(src=ep3.ip6.address, dst=ep1.ip6.address) /
2587 UDP(sport=1234, dport=1230) /
2590 # should be dropped since no contract yet
2591 self.send_and_assert_no_replies(self.pg0, [p4[0]])
2592 self.send_and_assert_no_replies(self.pg0, [p6[0]])
2595 # Add a contract with a rule to load-balance redirect via SEP1 and SEP2
2596 # one of the next-hops is via an EP that is not known
2598 acl = VppGbpAcl(self)
2599 rule4 = acl.create_rule(permit_deny=1, proto=17)
2600 rule6 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
2601 acl_index = acl.add_vpp_config([rule4, rule6])
2604 # test the src-ip hash mode
2606 c1 = VppGbpContract(
2607 self, 220, 222, acl_index,
2608 [VppGbpContractRule(
2609 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2610 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2611 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
2612 sep1.ip4, sep1.epg.rd),
2613 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
2614 sep2.ip4, sep2.epg.rd)]),
2616 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2617 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2618 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
2619 sep3.ip6, sep3.epg.rd),
2620 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
2621 sep4.ip6, sep4.epg.rd)])])
2624 c2 = VppGbpContract(
2625 self, 222, 220, acl_index,
2626 [VppGbpContractRule(
2627 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2628 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2629 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
2630 sep1.ip4, sep1.epg.rd),
2631 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
2632 sep2.ip4, sep2.epg.rd)]),
2634 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2635 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2636 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
2637 sep3.ip6, sep3.epg.rd),
2638 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
2639 sep4.ip6, sep4.epg.rd)])])
2643 # send again with the contract preset, now packets arrive
2644 # at SEP1 or SEP2 depending on the hashing
2646 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
2649 self.assertEqual(rx[Ether].src, routed_src_mac)
2650 self.assertEqual(rx[Ether].dst, sep1.mac)
2651 self.assertEqual(rx[IP].src, ep1.ip4.address)
2652 self.assertEqual(rx[IP].dst, ep3.ip4.address)
2654 rxs = self.send_and_expect(self.pg2, p4[1] * 17, sep2.itf)
2657 self.assertEqual(rx[Ether].src, routed_src_mac)
2658 self.assertEqual(rx[Ether].dst, sep2.mac)
2659 self.assertEqual(rx[IP].src, ep3.ip4.address)
2660 self.assertEqual(rx[IP].dst, ep1.ip4.address)
2662 rxs = self.send_and_expect(self.pg0, p6[0] * 17, self.pg7)
2665 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
2666 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
2667 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
2668 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
2669 self.assertEqual(rx[VXLAN].vni, 117)
2670 self.assertTrue(rx[VXLAN].flags.G)
2671 self.assertTrue(rx[VXLAN].flags.Instance)
2672 # redirect policy has been applied
2673 self.assertTrue(rx[VXLAN].gpflags.A)
2674 self.assertFalse(rx[VXLAN].gpflags.D)
2676 inner = rx[VXLAN].payload
2678 self.assertEqual(inner[Ether].src, routed_src_mac)
2679 self.assertEqual(inner[Ether].dst, sep4.mac)
2680 self.assertEqual(inner[IPv6].src, ep1.ip6.address)
2681 self.assertEqual(inner[IPv6].dst, ep3.ip6.address)
2683 rxs = self.send_and_expect(self.pg2, p6[1] * 17, sep3.itf)
2686 self.assertEqual(rx[Ether].src, routed_src_mac)
2687 self.assertEqual(rx[Ether].dst, sep3.mac)
2688 self.assertEqual(rx[IPv6].src, ep3.ip6.address)
2689 self.assertEqual(rx[IPv6].dst, ep1.ip6.address)
2692 # programme the unknown EP
2694 sep4.add_vpp_config()
2696 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep4.itf)
2699 self.assertEqual(rx[Ether].src, routed_src_mac)
2700 self.assertEqual(rx[Ether].dst, sep4.mac)
2701 self.assertEqual(rx[IPv6].src, ep1.ip6.address)
2702 self.assertEqual(rx[IPv6].dst, ep3.ip6.address)
2705 # and revert back to unprogrammed
2707 sep4.remove_vpp_config()
2709 rxs = self.send_and_expect(self.pg0, p6[0] * 17, self.pg7)
2712 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
2713 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
2714 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
2715 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
2716 self.assertEqual(rx[VXLAN].vni, 117)
2717 self.assertTrue(rx[VXLAN].flags.G)
2718 self.assertTrue(rx[VXLAN].flags.Instance)
2719 # redirect policy has been applied
2720 self.assertTrue(rx[VXLAN].gpflags.A)
2721 self.assertFalse(rx[VXLAN].gpflags.D)
2723 inner = rx[VXLAN].payload
2725 self.assertEqual(inner[Ether].src, routed_src_mac)
2726 self.assertEqual(inner[Ether].dst, sep4.mac)
2727 self.assertEqual(inner[IPv6].src, ep1.ip6.address)
2728 self.assertEqual(inner[IPv6].dst, ep3.ip6.address)
2730 c1.remove_vpp_config()
2731 c2.remove_vpp_config()
2734 # test the symmetric hash mode
2736 c1 = VppGbpContract(
2737 self, 220, 222, acl_index,
2738 [VppGbpContractRule(
2739 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2740 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
2741 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
2742 sep1.ip4, sep1.epg.rd),
2743 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
2744 sep2.ip4, sep2.epg.rd)]),
2746 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2747 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
2748 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
2749 sep3.ip6, sep3.epg.rd),
2750 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
2751 sep4.ip6, sep4.epg.rd)])])
2754 c2 = VppGbpContract(
2755 self, 222, 220, acl_index,
2756 [VppGbpContractRule(
2757 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2758 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
2759 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
2760 sep1.ip4, sep1.epg.rd),
2761 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
2762 sep2.ip4, sep2.epg.rd)]),
2764 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2765 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
2766 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
2767 sep3.ip6, sep3.epg.rd),
2768 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
2769 sep4.ip6, sep4.epg.rd)])])
2773 # send again with the contract preset, now packets arrive
2774 # at SEP1 for both directions
2776 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
2779 self.assertEqual(rx[Ether].src, routed_src_mac)
2780 self.assertEqual(rx[Ether].dst, sep1.mac)
2781 self.assertEqual(rx[IP].src, ep1.ip4.address)
2782 self.assertEqual(rx[IP].dst, ep3.ip4.address)
2784 rxs = self.send_and_expect(self.pg2, p4[1] * 17, sep1.itf)
2787 self.assertEqual(rx[Ether].src, routed_src_mac)
2788 self.assertEqual(rx[Ether].dst, sep1.mac)
2789 self.assertEqual(rx[IP].src, ep3.ip4.address)
2790 self.assertEqual(rx[IP].dst, ep1.ip4.address)
2793 # programme the unknown EP for the L3 tests
2795 sep4.add_vpp_config()
2798 # an L3 switch packet between local EPs in different EPGs
2799 # different dest ports on each so the are LB hashed differently
2801 p4 = [(Ether(src=ep1.mac, dst=self.router_mac.address) /
2802 IP(src=ep1.ip4.address, dst=ep2.ip4.address) /
2803 UDP(sport=1234, dport=1234) /
2805 (Ether(src=ep2.mac, dst=self.router_mac.address) /
2806 IP(src=ep2.ip4.address, dst=ep1.ip4.address) /
2807 UDP(sport=1234, dport=1234) /
2809 p6 = [(Ether(src=ep1.mac, dst=self.router_mac.address) /
2810 IPv6(src=ep1.ip6.address, dst=ep2.ip6.address) /
2811 UDP(sport=1234, dport=1234) /
2813 (Ether(src=ep2.mac, dst=self.router_mac.address) /
2814 IPv6(src=ep2.ip6.address, dst=ep1.ip6.address) /
2815 UDP(sport=1234, dport=1234) /
2818 c3 = VppGbpContract(
2819 self, 220, 221, acl_index,
2820 [VppGbpContractRule(
2821 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2822 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
2823 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
2824 sep1.ip4, sep1.epg.rd),
2825 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
2826 sep2.ip4, sep2.epg.rd)]),
2828 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2829 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
2830 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
2831 sep3.ip6, sep3.epg.rd),
2832 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
2833 sep4.ip6, sep4.epg.rd)])])
2836 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
2839 self.assertEqual(rx[Ether].src, routed_src_mac)
2840 self.assertEqual(rx[Ether].dst, sep1.mac)
2841 self.assertEqual(rx[IP].src, ep1.ip4.address)
2842 self.assertEqual(rx[IP].dst, ep2.ip4.address)
2845 # learn a remote EP in EPG 221
2847 vx_tun_l3 = VppGbpVxlanTunnel(
2848 self, 444, rd1.rd_id,
2849 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3)
2850 vx_tun_l3.add_vpp_config()
2852 c4 = VppGbpContract(
2853 self, 221, 220, acl_index,
2854 [VppGbpContractRule(
2855 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2858 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2862 p = (Ether(src=self.pg7.remote_mac,
2863 dst=self.pg7.local_mac) /
2864 IP(src=self.pg7.remote_ip4,
2865 dst=self.pg7.local_ip4) /
2866 UDP(sport=1234, dport=48879) /
2867 VXLAN(vni=444, gpid=221, flags=0x88) /
2868 Ether(src="00:22:22:22:22:33", dst=self.router_mac.address) /
2869 IP(src="10.0.0.88", dst=ep1.ip4.address) /
2870 UDP(sport=1234, dport=1234) /
2873 rx = self.send_and_expect(self.pg7, [p], self.pg0)
2875 # endpoint learnt via the parent GBP-vxlan interface
2876 self.assertTrue(find_gbp_endpoint(self,
2877 vx_tun_l3._sw_if_index,
2880 p = (Ether(src=self.pg7.remote_mac,
2881 dst=self.pg7.local_mac) /
2882 IP(src=self.pg7.remote_ip4,
2883 dst=self.pg7.local_ip4) /
2884 UDP(sport=1234, dport=48879) /
2885 VXLAN(vni=444, gpid=221, flags=0x88) /
2886 Ether(src="00:22:22:22:22:33", dst=self.router_mac.address) /
2887 IPv6(src="2001:10::88", dst=ep1.ip6.address) /
2888 UDP(sport=1234, dport=1234) /
2891 rx = self.send_and_expect(self.pg7, [p], self.pg0)
2893 # endpoint learnt via the parent GBP-vxlan interface
2894 self.assertTrue(find_gbp_endpoint(self,
2895 vx_tun_l3._sw_if_index,
2899 # L3 switch from local to remote EP
2901 p4 = [(Ether(src=ep1.mac, dst=self.router_mac.address) /
2902 IP(src=ep1.ip4.address, dst="10.0.0.88") /
2903 UDP(sport=1234, dport=1234) /
2905 p6 = [(Ether(src=ep1.mac, dst=self.router_mac.address) /
2906 IPv6(src=ep1.ip6.address, dst="2001:10::88") /
2907 UDP(sport=1234, dport=1234) /
2910 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
2913 self.assertEqual(rx[Ether].src, routed_src_mac)
2914 self.assertEqual(rx[Ether].dst, sep1.mac)
2915 self.assertEqual(rx[IP].src, ep1.ip4.address)
2916 self.assertEqual(rx[IP].dst, "10.0.0.88")
2918 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep4.itf)
2921 self.assertEqual(rx[Ether].src, routed_src_mac)
2922 self.assertEqual(rx[Ether].dst, sep4.mac)
2923 self.assertEqual(rx[IPv6].src, ep1.ip6.address)
2924 self.assertEqual(rx[IPv6].dst, "2001:10::88")
2927 # test the dst-ip hash mode
2929 c5 = VppGbpContract(
2930 self, 220, 221, acl_index,
2931 [VppGbpContractRule(
2932 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2933 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
2934 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
2935 sep1.ip4, sep1.epg.rd),
2936 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
2937 sep2.ip4, sep2.epg.rd)]),
2939 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
2940 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
2941 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
2942 sep3.ip6, sep3.epg.rd),
2943 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
2944 sep4.ip6, sep4.epg.rd)])])
2947 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
2950 self.assertEqual(rx[Ether].src, routed_src_mac)
2951 self.assertEqual(rx[Ether].dst, sep1.mac)
2952 self.assertEqual(rx[IP].src, ep1.ip4.address)
2953 self.assertEqual(rx[IP].dst, "10.0.0.88")
2955 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep3.itf)
2958 self.assertEqual(rx[Ether].src, routed_src_mac)
2959 self.assertEqual(rx[Ether].dst, sep3.mac)
2960 self.assertEqual(rx[IPv6].src, ep1.ip6.address)
2961 self.assertEqual(rx[IPv6].dst, "2001:10::88")
2964 if __name__ == '__main__':
2965 unittest.main(testRunner=VppTestRunner)