3 from socket import AF_INET, AF_INET6
6 from scapy.packet import Raw
7 from scapy.layers.l2 import Ether, ARP, Dot1Q
8 from scapy.layers.inet import IP, UDP, ICMP
9 from scapy.layers.inet6 import IPv6, ICMPv6ND_NS, ICMPv6NDOptSrcLLAddr, \
11 from scapy.utils6 import in6_getnsma, in6_getnsmac
12 from scapy.layers.vxlan import VXLAN
13 from scapy.data import ETH_P_IP, ETH_P_IPV6, ETH_P_ARP
14 from scapy.utils import inet_pton, inet_ntop
16 from framework import VppTestCase, VppTestRunner
17 from vpp_object import VppObject
18 from vpp_interface import VppInterface
19 from vpp_ip_route import VppIpRoute, VppRoutePath, VppIpTable, \
20 VppIpInterfaceAddress, VppIpInterfaceBind, find_route, FibPathProto, \
22 from vpp_l2 import VppBridgeDomain, VppBridgeDomainPort, \
23 VppBridgeDomainArpEntry, VppL2FibEntry, find_bridge_domain_port, VppL2Vtr
24 from vpp_sub_interface import L2_VTR_OP, VppDot1QSubint
25 from vpp_ip import VppIpAddress, VppIpPrefix
26 from vpp_papi import VppEnum, MACAddress
27 from vpp_vxlan_gbp_tunnel import find_vxlan_gbp_tunnel, INDEX_INVALID, \
29 from vpp_neighbor import VppNeighbor
34 def find_gbp_endpoint(test, sw_if_index=None, ip=None, mac=None):
36 vip = VppIpAddress(ip)
38 vmac = MACAddress(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.packed == 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):
91 return [self.ip4, self.ip6]
95 return [self.fip4, self.fip6]
97 def __init__(self, test, itf, epg, recirc, ip4, fip4, ip6, fip6,
107 self._ip4 = VppIpAddress(ip4)
108 self._fip4 = VppIpAddress(fip4)
109 self._ip6 = VppIpAddress(ip6)
110 self._fip6 = VppIpAddress(fip6)
113 self.vmac = MACAddress(self.itf.remote_mac)
115 self.vmac = MACAddress("00:00:00:00:00:00")
118 self.tun_src = VppIpAddress(tun_src)
119 self.tun_dst = VppIpAddress(tun_dst)
121 def add_vpp_config(self):
122 res = self._test.vapi.gbp_endpoint_add(
123 self.itf.sw_if_index,
124 [self.ip4.encode(), self.ip6.encode()],
128 self.tun_src.encode(),
129 self.tun_dst.encode())
130 self.handle = res.handle
131 self._test.registry.register(self, self._test.logger)
133 def remove_vpp_config(self):
134 self._test.vapi.gbp_endpoint_del(self.handle)
137 return "gbp-endpoint:[%d==%d:%s:%d]" % (self.handle,
138 self.itf.sw_if_index,
142 def query_vpp_config(self):
143 return find_gbp_endpoint(self._test,
144 self.itf.sw_if_index,
148 class VppGbpRecirc(VppObject):
150 GBP Recirculation Interface
153 def __init__(self, test, epg, recirc, is_ext=False):
159 def add_vpp_config(self):
160 self._test.vapi.gbp_recirc_add_del(
162 self.recirc.sw_if_index,
165 self._test.registry.register(self, self._test.logger)
167 def remove_vpp_config(self):
168 self._test.vapi.gbp_recirc_add_del(
170 self.recirc.sw_if_index,
175 return "gbp-recirc:[%d]" % (self.recirc.sw_if_index)
177 def query_vpp_config(self):
178 rs = self._test.vapi.gbp_recirc_dump()
180 if r.recirc.sw_if_index == self.recirc.sw_if_index:
185 class VppGbpExtItf(VppObject):
187 GBP ExtItfulation Interface
190 def __init__(self, test, itf, bd, rd):
196 def add_vpp_config(self):
197 self._test.vapi.gbp_ext_itf_add_del(
199 self.itf.sw_if_index,
202 self._test.registry.register(self, self._test.logger)
204 def remove_vpp_config(self):
205 self._test.vapi.gbp_ext_itf_add_del(
207 self.itf.sw_if_index,
212 return "gbp-ext-itf:[%d]" % (self.itf.sw_if_index)
214 def query_vpp_config(self):
215 rs = self._test.vapi.gbp_ext_itf_dump()
217 if r.ext_itf.sw_if_index == self.itf.sw_if_index:
222 class VppGbpSubnet(VppObject):
227 def __init__(self, test, rd, address, address_len,
228 type, sw_if_index=None, sclass=None):
230 self.rd_id = rd.rd_id
231 self.prefix = VppIpPrefix(address, address_len)
233 self.sw_if_index = sw_if_index
236 def add_vpp_config(self):
237 self._test.vapi.gbp_subnet_add_del(
240 self.prefix.encode(),
242 sw_if_index=self.sw_if_index if self.sw_if_index else 0xffffffff,
243 sclass=self.sclass if self.sclass else 0xffff)
244 self._test.registry.register(self, self._test.logger)
246 def remove_vpp_config(self):
247 self._test.vapi.gbp_subnet_add_del(
250 self.prefix.encode(),
254 return "gbp-subnet:[%d-%s]" % (self.rd_id, self.prefix)
256 def query_vpp_config(self):
257 ss = self._test.vapi.gbp_subnet_dump()
259 if s.subnet.rd_id == self.rd_id and \
260 s.subnet.type == self.type and \
261 s.subnet.prefix == self.prefix:
266 class VppGbpEndpointRetention(object):
267 def __init__(self, remote_ep_timeout=0xffffffff):
268 self.remote_ep_timeout = remote_ep_timeout
271 return {'remote_ep_timeout': self.remote_ep_timeout}
274 class VppGbpEndpointGroup(VppObject):
279 def __init__(self, test, vnid, sclass, rd, bd, uplink,
280 bvi, bvi_ip4, bvi_ip6=None,
281 retention=VppGbpEndpointRetention()):
285 self.bvi_ip4 = VppIpAddress(bvi_ip4)
286 self.bvi_ip6 = VppIpAddress(bvi_ip6)
293 self.retention = retention
295 def add_vpp_config(self):
296 self._test.vapi.gbp_endpoint_group_add(
301 self.uplink.sw_if_index if self.uplink else INDEX_INVALID,
302 self.retention.encode())
303 self._test.registry.register(self, self._test.logger)
305 def remove_vpp_config(self):
306 self._test.vapi.gbp_endpoint_group_del(self.sclass)
309 return "gbp-endpoint-group:[%d]" % (self.vnid)
311 def query_vpp_config(self):
312 epgs = self._test.vapi.gbp_endpoint_group_dump()
314 if epg.epg.vnid == self.vnid:
319 class VppGbpBridgeDomain(VppObject):
324 def __init__(self, test, bd, rd, bvi, uu_fwd=None,
325 bm_flood=None, learn=True, uu_drop=False, bm_drop=False):
329 self.bm_flood = bm_flood
333 e = VppEnum.vl_api_gbp_bridge_domain_flags_t
335 self.learn = e.GBP_BD_API_FLAG_NONE
337 self.learn = e.GBP_BD_API_FLAG_DO_NOT_LEARN
339 self.learn |= e.GBP_BD_API_FLAG_UU_FWD_DROP
341 self.learn |= e.GBP_BD_API_FLAG_MCAST_DROP
343 def add_vpp_config(self):
344 self._test.vapi.gbp_bridge_domain_add(
348 self.bvi.sw_if_index,
349 self.uu_fwd.sw_if_index if self.uu_fwd else INDEX_INVALID,
350 self.bm_flood.sw_if_index if self.bm_flood else INDEX_INVALID)
351 self._test.registry.register(self, self._test.logger)
353 def remove_vpp_config(self):
354 self._test.vapi.gbp_bridge_domain_del(self.bd.bd_id)
357 return "gbp-bridge-domain:[%d]" % (self.bd.bd_id)
359 def query_vpp_config(self):
360 bds = self._test.vapi.gbp_bridge_domain_dump()
362 if bd.bd.bd_id == self.bd.bd_id:
367 class VppGbpRouteDomain(VppObject):
372 def __init__(self, test, rd_id, scope, t4, t6, ip4_uu=None, ip6_uu=None):
381 def add_vpp_config(self):
382 self._test.vapi.gbp_route_domain_add(
387 self.ip4_uu.sw_if_index if self.ip4_uu else INDEX_INVALID,
388 self.ip6_uu.sw_if_index if self.ip6_uu else INDEX_INVALID)
389 self._test.registry.register(self, self._test.logger)
391 def remove_vpp_config(self):
392 self._test.vapi.gbp_route_domain_del(self.rd_id)
395 return "gbp-route-domain:[%d]" % (self.rd_id)
397 def query_vpp_config(self):
398 rds = self._test.vapi.gbp_route_domain_dump()
400 if rd.rd.rd_id == self.rd_id:
405 class VppGbpContractNextHop():
406 def __init__(self, mac, bd, ip, rd):
413 return {'ip': self.ip.encode(),
414 'mac': self.mac.packed,
415 'bd_id': self.bd.bd.bd_id,
416 'rd_id': self.rd.rd_id}
419 class VppGbpContractRule():
420 def __init__(self, action, hash_mode, nhs=None):
422 self.hash_mode = hash_mode
423 self.nhs = [] if nhs is None else nhs
428 nhs.append(nh.encode())
431 return {'action': self.action,
433 'hash_mode': self.hash_mode,
434 'n_nhs': len(self.nhs),
438 return '<VppGbpContractRule action=%s, hash_mode=%s>' % (
439 self.action, self.hash_mode)
442 class VppGbpContract(VppObject):
447 def __init__(self, test, scope, sclass, dclass, acl_index,
448 rules, allowed_ethertypes):
450 if not isinstance(rules, list):
451 raise ValueError("'rules' must be a list.")
452 if not isinstance(allowed_ethertypes, list):
453 raise ValueError("'allowed_ethertypes' must be a list.")
455 self.acl_index = acl_index
459 self.allowed_ethertypes = allowed_ethertypes
460 while (len(self.allowed_ethertypes) < 16):
461 self.allowed_ethertypes.append(0)
463 def add_vpp_config(self):
466 rules.append(r.encode())
467 r = self._test.vapi.gbp_contract_add_del(
470 'acl_index': self.acl_index,
472 'sclass': self.sclass,
473 'dclass': self.dclass,
474 'n_rules': len(rules),
476 'n_ether_types': len(self.allowed_ethertypes),
477 'allowed_ethertypes': self.allowed_ethertypes})
478 self.stats_index = r.stats_index
479 self._test.registry.register(self, self._test.logger)
481 def remove_vpp_config(self):
482 self._test.vapi.gbp_contract_add_del(
485 'acl_index': self.acl_index,
487 'sclass': self.sclass,
488 'dclass': self.dclass,
491 'n_ether_types': len(self.allowed_ethertypes),
492 'allowed_ethertypes': self.allowed_ethertypes})
495 return "gbp-contract:[%d:%d:%d:%d]" % (self.scope,
500 def query_vpp_config(self):
501 cs = self._test.vapi.gbp_contract_dump()
503 if c.contract.scope == self.scope \
504 and c.contract.sclass == self.sclass \
505 and c.contract.dclass == self.dclass:
509 def get_drop_stats(self):
510 c = self._test.statistics.get_counter("/net/gbp/contract/drop")
511 return c[0][self.stats_index]
513 def get_permit_stats(self):
514 c = self._test.statistics.get_counter("/net/gbp/contract/permit")
515 return c[0][self.stats_index]
518 class VppGbpVxlanTunnel(VppInterface):
523 def __init__(self, test, vni, bd_rd_id, mode, src):
524 super(VppGbpVxlanTunnel, self).__init__(test)
527 self.bd_rd_id = bd_rd_id
531 def add_vpp_config(self):
532 r = self._test.vapi.gbp_vxlan_tunnel_add(
537 self.set_sw_if_index(r.sw_if_index)
538 self._test.registry.register(self, self._test.logger)
540 def remove_vpp_config(self):
541 self._test.vapi.gbp_vxlan_tunnel_del(self.vni)
544 return "gbp-vxlan:%d" % (self.sw_if_index)
546 def query_vpp_config(self):
547 return find_gbp_vxlan(self._test, self.vni)
550 class VppGbpAcl(VppObject):
555 def __init__(self, test):
557 self.acl_index = 4294967295
559 def create_rule(self, is_ipv6=0, permit_deny=0, proto=-1,
560 s_prefix=0, s_ip=b'\x00\x00\x00\x00', sport_from=0,
561 sport_to=65535, d_prefix=0, d_ip=b'\x00\x00\x00\x00',
562 dport_from=0, dport_to=65535):
563 if proto == -1 or proto == 0:
566 elif proto == 1 or proto == 58:
569 rule = ({'is_permit': permit_deny, 'is_ipv6': is_ipv6, 'proto': proto,
570 'srcport_or_icmptype_first': sport_from,
571 'srcport_or_icmptype_last': sport_to,
572 'src_ip_prefix_len': s_prefix,
574 'dstport_or_icmpcode_first': dport_from,
575 'dstport_or_icmpcode_last': dport_to,
576 'dst_ip_prefix_len': d_prefix,
577 'dst_ip_addr': d_ip})
580 def add_vpp_config(self, rules):
582 reply = self._test.vapi.acl_add_replace(acl_index=self.acl_index,
585 self.acl_index = reply.acl_index
586 return self.acl_index
588 def remove_vpp_config(self):
589 self._test.vapi.acl_del(self.acl_index)
592 return "gbp-acl:[%d]" % (self.acl_index)
594 def query_vpp_config(self):
595 cs = self._test.vapi.acl_dump()
597 if c.acl_index == self.acl_index:
602 class TestGBP(VppTestCase):
603 """ GBP Test Case """
606 def config_flags(self):
607 return VppEnum.vl_api_nat_config_flags_t
611 super(TestGBP, cls).setUpClass()
614 def tearDownClass(cls):
615 super(TestGBP, cls).tearDownClass()
618 super(TestGBP, self).setUp()
620 self.create_pg_interfaces(range(9))
621 self.create_loopback_interfaces(8)
623 self.router_mac = MACAddress("00:11:22:33:44:55")
625 for i in self.pg_interfaces:
627 for i in self.lo_interfaces:
631 for i in self.pg_interfaces:
634 super(TestGBP, self).tearDown()
636 def send_and_expect_bridged(self, src, tx, dst):
637 rx = self.send_and_expect(src, tx, dst)
640 self.assertEqual(r[Ether].src, tx[0][Ether].src)
641 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
642 self.assertEqual(r[IP].src, tx[0][IP].src)
643 self.assertEqual(r[IP].dst, tx[0][IP].dst)
646 def send_and_expect_bridged6(self, src, tx, dst):
647 rx = self.send_and_expect(src, tx, dst)
650 self.assertEqual(r[Ether].src, tx[0][Ether].src)
651 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
652 self.assertEqual(r[IPv6].src, tx[0][IPv6].src)
653 self.assertEqual(r[IPv6].dst, tx[0][IPv6].dst)
656 def send_and_expect_routed(self, src, tx, dst, src_mac):
657 rx = self.send_and_expect(src, tx, dst)
660 self.assertEqual(r[Ether].src, src_mac)
661 self.assertEqual(r[Ether].dst, dst.remote_mac)
662 self.assertEqual(r[IP].src, tx[0][IP].src)
663 self.assertEqual(r[IP].dst, tx[0][IP].dst)
666 def send_and_expect_natted(self, src, tx, dst, src_ip):
667 rx = self.send_and_expect(src, tx, dst)
670 self.assertEqual(r[Ether].src, tx[0][Ether].src)
671 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
672 self.assertEqual(r[IP].src, src_ip)
673 self.assertEqual(r[IP].dst, tx[0][IP].dst)
676 def send_and_expect_natted6(self, src, tx, dst, src_ip):
677 rx = self.send_and_expect(src, tx, dst)
680 self.assertEqual(r[Ether].src, tx[0][Ether].src)
681 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
682 self.assertEqual(r[IPv6].src, src_ip)
683 self.assertEqual(r[IPv6].dst, tx[0][IPv6].dst)
686 def send_and_expect_unnatted(self, src, tx, dst, dst_ip):
687 rx = self.send_and_expect(src, tx, dst)
690 self.assertEqual(r[Ether].src, tx[0][Ether].src)
691 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
692 self.assertEqual(r[IP].dst, dst_ip)
693 self.assertEqual(r[IP].src, tx[0][IP].src)
696 def send_and_expect_unnatted6(self, src, tx, dst, dst_ip):
697 rx = self.send_and_expect(src, tx, dst)
700 self.assertEqual(r[Ether].src, tx[0][Ether].src)
701 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
702 self.assertEqual(r[IPv6].dst, dst_ip)
703 self.assertEqual(r[IPv6].src, tx[0][IPv6].src)
706 def send_and_expect_double_natted(self, src, tx, dst, src_ip, dst_ip):
707 rx = self.send_and_expect(src, tx, dst)
710 self.assertEqual(r[Ether].src, str(self.router_mac))
711 self.assertEqual(r[Ether].dst, dst.remote_mac)
712 self.assertEqual(r[IP].dst, dst_ip)
713 self.assertEqual(r[IP].src, src_ip)
716 def send_and_expect_double_natted6(self, src, tx, dst, src_ip, dst_ip):
717 rx = self.send_and_expect(src, tx, dst)
720 self.assertEqual(r[Ether].src, str(self.router_mac))
721 self.assertEqual(r[Ether].dst, dst.remote_mac)
722 self.assertEqual(r[IPv6].dst, dst_ip)
723 self.assertEqual(r[IPv6].src, src_ip)
726 def send_and_expect_no_arp(self, src, tx, dst):
727 self.pg_send(src, tx)
728 dst.get_capture(0, timeout=1)
729 dst.assert_nothing_captured(remark="")
732 def send_and_expect_arp(self, src, tx, dst):
733 rx = self.send_and_expect(src, tx, dst)
736 self.assertEqual(r[Ether].src, tx[0][Ether].src)
737 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
738 self.assertEqual(r[ARP].psrc, tx[0][ARP].psrc)
739 self.assertEqual(r[ARP].pdst, tx[0][ARP].pdst)
740 self.assertEqual(r[ARP].hwsrc, tx[0][ARP].hwsrc)
741 self.assertEqual(r[ARP].hwdst, tx[0][ARP].hwdst)
745 """ Group Based Policy """
747 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
752 gt4 = VppIpTable(self, 0)
754 gt6 = VppIpTable(self, 0, is_ip6=True)
756 nt4 = VppIpTable(self, 20)
758 nt6 = VppIpTable(self, 20, is_ip6=True)
761 rd0 = VppGbpRouteDomain(self, 0, 400, gt4, gt6, None, None)
762 rd20 = VppGbpRouteDomain(self, 20, 420, nt4, nt6, None, None)
765 rd20.add_vpp_config()
770 bd1 = VppBridgeDomain(self, 1)
771 bd2 = VppBridgeDomain(self, 2)
772 bd20 = VppBridgeDomain(self, 20)
776 bd20.add_vpp_config()
778 gbd1 = VppGbpBridgeDomain(self, bd1, rd0, self.loop0)
779 gbd2 = VppGbpBridgeDomain(self, bd2, rd0, self.loop1)
780 gbd20 = VppGbpBridgeDomain(self, bd20, rd20, self.loop2)
782 gbd1.add_vpp_config()
783 gbd2.add_vpp_config()
784 gbd20.add_vpp_config()
787 # 3 EPGs, 2 of which share a BD.
788 # 2 NAT EPGs, one for floating-IP subnets, the other for internet
790 epgs = [VppGbpEndpointGroup(self, 220, 1220, rd0, gbd1,
791 self.pg4, self.loop0,
792 "10.0.0.128", "2001:10::128"),
793 VppGbpEndpointGroup(self, 221, 1221, rd0, gbd1,
794 self.pg5, self.loop0,
795 "10.0.1.128", "2001:10:1::128"),
796 VppGbpEndpointGroup(self, 222, 1222, rd0, gbd2,
797 self.pg6, self.loop1,
798 "10.0.2.128", "2001:10:2::128"),
799 VppGbpEndpointGroup(self, 333, 1333, rd20, gbd20,
800 self.pg7, self.loop2,
801 "11.0.0.128", "3001::128"),
802 VppGbpEndpointGroup(self, 444, 1444, rd20, gbd20,
803 self.pg8, self.loop2,
804 "11.0.0.129", "3001::129")]
805 recircs = [VppGbpRecirc(self, epgs[0], self.loop3),
806 VppGbpRecirc(self, epgs[1], self.loop4),
807 VppGbpRecirc(self, epgs[2], self.loop5),
808 VppGbpRecirc(self, epgs[3], self.loop6, is_ext=True),
809 VppGbpRecirc(self, epgs[4], self.loop7, is_ext=True)]
812 recirc_nat = recircs[3]
815 # 4 end-points, 2 in the same subnet, 3 in the same BD
817 eps = [VppGbpEndpoint(self, self.pg0,
819 "10.0.0.1", "11.0.0.1",
820 "2001:10::1", "3001::1"),
821 VppGbpEndpoint(self, self.pg1,
823 "10.0.0.2", "11.0.0.2",
824 "2001:10::2", "3001::2"),
825 VppGbpEndpoint(self, self.pg2,
827 "10.0.1.1", "11.0.0.3",
828 "2001:10:1::1", "3001::3"),
829 VppGbpEndpoint(self, self.pg3,
831 "10.0.2.1", "11.0.0.4",
832 "2001:10:2::1", "3001::4")]
835 # Config related to each of the EPGs
838 # IP config on the BVI interfaces
839 if epg != epgs[1] and epg != epgs[4]:
840 VppIpInterfaceBind(self, epg.bvi, epg.rd.t4).add_vpp_config()
841 VppIpInterfaceBind(self, epg.bvi, epg.rd.t6).add_vpp_config()
842 self.vapi.sw_interface_set_mac_address(
844 self.router_mac.packed)
846 # The BVIs are NAT inside interfaces
847 flags = self.config_flags.NAT_IS_INSIDE
848 self.vapi.nat44_interface_add_del_feature(
849 sw_if_index=epg.bvi.sw_if_index,
850 flags=flags, is_add=1)
851 self.vapi.nat66_add_del_interface(
852 is_add=1, flags=flags,
853 sw_if_index=epg.bvi.sw_if_index)
855 if_ip4 = VppIpInterfaceAddress(self, epg.bvi, epg.bvi_ip4, 32)
856 if_ip6 = VppIpInterfaceAddress(self, epg.bvi, epg.bvi_ip6, 128)
857 if_ip4.add_vpp_config()
858 if_ip6.add_vpp_config()
860 # EPG uplink interfaces in the RD
861 VppIpInterfaceBind(self, epg.uplink, epg.rd.t4).add_vpp_config()
862 VppIpInterfaceBind(self, epg.uplink, epg.rd.t6).add_vpp_config()
864 # add the BD ARP termination entry for BVI IP
865 epg.bd_arp_ip4 = VppBridgeDomainArpEntry(self, epg.bd.bd,
866 str(self.router_mac),
868 epg.bd_arp_ip6 = VppBridgeDomainArpEntry(self, epg.bd.bd,
869 str(self.router_mac),
871 epg.bd_arp_ip4.add_vpp_config()
872 epg.bd_arp_ip6.add_vpp_config()
877 for recirc in recircs:
878 # EPG's ingress recirculation interface maps to its RD
879 VppIpInterfaceBind(self, recirc.recirc,
880 recirc.epg.rd.t4).add_vpp_config()
881 VppIpInterfaceBind(self, recirc.recirc,
882 recirc.epg.rd.t6).add_vpp_config()
884 self.vapi.nat44_interface_add_del_feature(
885 sw_if_index=recirc.recirc.sw_if_index, is_add=1)
886 self.vapi.nat66_add_del_interface(
888 sw_if_index=recirc.recirc.sw_if_index)
890 recirc.add_vpp_config()
892 for recirc in recircs:
893 self.assertTrue(find_bridge_domain_port(self,
894 recirc.epg.bd.bd.bd_id,
895 recirc.recirc.sw_if_index))
898 self.pg_enable_capture(self.pg_interfaces)
901 # routes to the endpoints. We need these since there are no
902 # adj-fibs due to the fact the the BVI address has /32 and
903 # the subnet is not attached.
905 for (ip, fip) in zip(ep.ips, ep.fips):
906 # Add static mappings for each EP from the 10/8 to 11/8 network
908 flags = self.config_flags.NAT_IS_ADDR_ONLY
909 self.vapi.nat44_add_del_static_mapping(
911 local_ip_address=ip.bytes,
912 external_ip_address=fip.bytes,
913 external_sw_if_index=0xFFFFFFFF,
917 self.vapi.nat66_add_del_static_mapping(
918 local_ip_address=ip.bytes,
919 external_ip_address=fip.bytes,
925 self.logger.info(self.vapi.cli("sh gbp endpoint"))
927 # ... results in a Gratuitous ARP/ND on the EPG's uplink
928 rx = ep.epg.uplink.get_capture(len(ep.ips), timeout=0.2)
930 for ii, ip in enumerate(ep.ips):
934 self.assertTrue(p.haslayer(ICMPv6ND_NA))
935 self.assertEqual(p[ICMPv6ND_NA].tgt, ip.address)
937 self.assertTrue(p.haslayer(ARP))
938 self.assertEqual(p[ARP].psrc, ip.address)
939 self.assertEqual(p[ARP].pdst, ip.address)
941 # add the BD ARP termination entry for floating IP
943 ba = VppBridgeDomainArpEntry(self, epg_nat.bd.bd, ep.mac,
947 # floating IPs route via EPG recirc
949 self, fip.address, fip.length,
950 [VppRoutePath(fip.address,
951 ep.recirc.recirc.sw_if_index,
952 type=FibPathType.FIB_PATH_TYPE_DVR,
953 proto=fip.dpo_proto)],
957 # L2 FIB entries in the NAT EPG BD to bridge the packets from
958 # the outside direct to the internal EPG
959 lf = VppL2FibEntry(self, epg_nat.bd.bd, ep.mac,
960 ep.recirc.recirc, bvi_mac=0)
964 # ARP packets for unknown IP are sent to the EPG uplink
966 pkt_arp = (Ether(dst="ff:ff:ff:ff:ff:ff",
967 src=self.pg0.remote_mac) /
969 hwdst="ff:ff:ff:ff:ff:ff",
970 hwsrc=self.pg0.remote_mac,
974 self.vapi.cli("clear trace")
975 self.pg0.add_stream(pkt_arp)
977 self.pg_enable_capture(self.pg_interfaces)
980 rxd = epgs[0].uplink.get_capture(1)
983 # ARP/ND packets get a response
985 pkt_arp = (Ether(dst="ff:ff:ff:ff:ff:ff",
986 src=self.pg0.remote_mac) /
988 hwdst="ff:ff:ff:ff:ff:ff",
989 hwsrc=self.pg0.remote_mac,
990 pdst=epgs[0].bvi_ip4.address,
991 psrc=eps[0].ip4.address))
993 self.send_and_expect(self.pg0, [pkt_arp], self.pg0)
995 nsma = in6_getnsma(inet_pton(AF_INET6, eps[0].ip6.address))
996 d = inet_ntop(AF_INET6, nsma)
997 pkt_nd = (Ether(dst=in6_getnsmac(nsma),
998 src=self.pg0.remote_mac) /
999 IPv6(dst=d, src=eps[0].ip6.address) /
1000 ICMPv6ND_NS(tgt=epgs[0].bvi_ip6.address) /
1001 ICMPv6NDOptSrcLLAddr(lladdr=self.pg0.remote_mac))
1002 self.send_and_expect(self.pg0, [pkt_nd], self.pg0)
1005 # broadcast packets are flooded
1007 pkt_bcast = (Ether(dst="ff:ff:ff:ff:ff:ff",
1008 src=self.pg0.remote_mac) /
1009 IP(src=eps[0].ip4.address, dst="232.1.1.1") /
1010 UDP(sport=1234, dport=1234) /
1013 self.vapi.cli("clear trace")
1014 self.pg0.add_stream(pkt_bcast)
1016 self.pg_enable_capture(self.pg_interfaces)
1019 rxd = eps[1].itf.get_capture(1)
1020 self.assertEqual(rxd[0][Ether].dst, pkt_bcast[Ether].dst)
1021 rxd = epgs[0].uplink.get_capture(1)
1022 self.assertEqual(rxd[0][Ether].dst, pkt_bcast[Ether].dst)
1025 # packets to non-local L3 destinations dropped
1027 pkt_intra_epg_220_ip4 = (Ether(src=self.pg0.remote_mac,
1028 dst=str(self.router_mac)) /
1029 IP(src=eps[0].ip4.address,
1031 UDP(sport=1234, dport=1234) /
1033 pkt_inter_epg_222_ip4 = (Ether(src=self.pg0.remote_mac,
1034 dst=str(self.router_mac)) /
1035 IP(src=eps[0].ip4.address,
1037 UDP(sport=1234, dport=1234) /
1040 self.send_and_assert_no_replies(self.pg0,
1041 pkt_intra_epg_220_ip4 * NUM_PKTS)
1043 pkt_inter_epg_222_ip6 = (Ether(src=self.pg0.remote_mac,
1044 dst=str(self.router_mac)) /
1045 IPv6(src=eps[0].ip6.address,
1046 dst="2001:10::99") /
1047 UDP(sport=1234, dport=1234) /
1049 self.send_and_assert_no_replies(self.pg0,
1050 pkt_inter_epg_222_ip6 * NUM_PKTS)
1053 # Add the subnet routes
1056 self, rd0, "10.0.0.0", 24,
1057 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1059 self, rd0, "10.0.1.0", 24,
1060 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1062 self, rd0, "10.0.2.0", 24,
1063 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1065 self, rd0, "2001:10::1", 64,
1066 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1068 self, rd0, "2001:10:1::1", 64,
1069 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1071 self, rd0, "2001:10:2::1", 64,
1072 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1073 s41.add_vpp_config()
1074 s42.add_vpp_config()
1075 s43.add_vpp_config()
1076 s61.add_vpp_config()
1077 s62.add_vpp_config()
1078 s63.add_vpp_config()
1080 self.send_and_expect_bridged(eps[0].itf,
1081 pkt_intra_epg_220_ip4 * NUM_PKTS,
1083 self.send_and_expect_bridged(eps[0].itf,
1084 pkt_inter_epg_222_ip4 * NUM_PKTS,
1086 self.send_and_expect_bridged6(eps[0].itf,
1087 pkt_inter_epg_222_ip6 * NUM_PKTS,
1090 self.logger.info(self.vapi.cli("sh ip fib 11.0.0.2"))
1091 self.logger.info(self.vapi.cli("sh gbp endpoint-group"))
1092 self.logger.info(self.vapi.cli("sh gbp endpoint"))
1093 self.logger.info(self.vapi.cli("sh gbp recirc"))
1094 self.logger.info(self.vapi.cli("sh int"))
1095 self.logger.info(self.vapi.cli("sh int addr"))
1096 self.logger.info(self.vapi.cli("sh int feat loop6"))
1097 self.logger.info(self.vapi.cli("sh vlib graph ip4-gbp-src-classify"))
1098 self.logger.info(self.vapi.cli("sh int feat loop3"))
1099 self.logger.info(self.vapi.cli("sh int feat pg0"))
1102 # Packet destined to unknown unicast is sent on the epg uplink ...
1104 pkt_intra_epg_220_to_uplink = (Ether(src=self.pg0.remote_mac,
1105 dst="00:00:00:33:44:55") /
1106 IP(src=eps[0].ip4.address,
1108 UDP(sport=1234, dport=1234) /
1111 self.send_and_expect_bridged(eps[0].itf,
1112 pkt_intra_epg_220_to_uplink * NUM_PKTS,
1114 # ... and nowhere else
1115 self.pg1.get_capture(0, timeout=0.1)
1116 self.pg1.assert_nothing_captured(remark="Flood onto other VMS")
1118 pkt_intra_epg_221_to_uplink = (Ether(src=self.pg2.remote_mac,
1119 dst="00:00:00:33:44:66") /
1120 IP(src=eps[0].ip4.address,
1122 UDP(sport=1234, dport=1234) /
1125 self.send_and_expect_bridged(eps[2].itf,
1126 pkt_intra_epg_221_to_uplink * NUM_PKTS,
1130 # Packets from the uplink are forwarded in the absence of a contract
1132 pkt_intra_epg_220_from_uplink = (Ether(src="00:00:00:33:44:55",
1133 dst=self.pg0.remote_mac) /
1134 IP(src=eps[0].ip4.address,
1136 UDP(sport=1234, dport=1234) /
1139 self.send_and_expect_bridged(self.pg4,
1140 pkt_intra_epg_220_from_uplink * NUM_PKTS,
1144 # in the absence of policy, endpoints in the same EPG
1147 pkt_intra_epg = (Ether(src=self.pg0.remote_mac,
1148 dst=self.pg1.remote_mac) /
1149 IP(src=eps[0].ip4.address,
1150 dst=eps[1].ip4.address) /
1151 UDP(sport=1234, dport=1234) /
1154 self.send_and_expect_bridged(self.pg0,
1155 pkt_intra_epg * NUM_PKTS,
1159 # in the absence of policy, endpoints in the different EPG
1160 # cannot communicate
1162 pkt_inter_epg_220_to_221 = (Ether(src=self.pg0.remote_mac,
1163 dst=self.pg2.remote_mac) /
1164 IP(src=eps[0].ip4.address,
1165 dst=eps[2].ip4.address) /
1166 UDP(sport=1234, dport=1234) /
1168 pkt_inter_epg_221_to_220 = (Ether(src=self.pg2.remote_mac,
1169 dst=self.pg0.remote_mac) /
1170 IP(src=eps[2].ip4.address,
1171 dst=eps[0].ip4.address) /
1172 UDP(sport=1234, dport=1234) /
1174 pkt_inter_epg_220_to_222 = (Ether(src=self.pg0.remote_mac,
1175 dst=str(self.router_mac)) /
1176 IP(src=eps[0].ip4.address,
1177 dst=eps[3].ip4.address) /
1178 UDP(sport=1234, dport=1234) /
1181 self.send_and_assert_no_replies(eps[0].itf,
1182 pkt_inter_epg_220_to_221 * NUM_PKTS)
1183 self.send_and_assert_no_replies(eps[0].itf,
1184 pkt_inter_epg_220_to_222 * NUM_PKTS)
1187 # A uni-directional contract from EPG 220 -> 221
1189 acl = VppGbpAcl(self)
1190 rule = acl.create_rule(permit_deny=1, proto=17)
1191 rule2 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
1192 acl_index = acl.add_vpp_config([rule, rule2])
1193 c1 = VppGbpContract(
1194 self, 400, epgs[0].sclass, epgs[1].sclass, acl_index,
1195 [VppGbpContractRule(
1196 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1197 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1200 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1201 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1203 [ETH_P_IP, ETH_P_IPV6])
1206 self.send_and_expect_bridged(eps[0].itf,
1207 pkt_inter_epg_220_to_221 * NUM_PKTS,
1209 self.send_and_assert_no_replies(eps[0].itf,
1210 pkt_inter_epg_220_to_222 * NUM_PKTS)
1213 # contract for the return direction
1215 c2 = VppGbpContract(
1216 self, 400, epgs[1].sclass, epgs[0].sclass, acl_index,
1217 [VppGbpContractRule(
1218 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1219 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1222 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1223 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1225 [ETH_P_IP, ETH_P_IPV6])
1228 self.send_and_expect_bridged(eps[0].itf,
1229 pkt_inter_epg_220_to_221 * NUM_PKTS,
1231 self.send_and_expect_bridged(eps[2].itf,
1232 pkt_inter_epg_221_to_220 * NUM_PKTS,
1235 ds = c2.get_drop_stats()
1236 self.assertEqual(ds['packets'], 0)
1237 ps = c2.get_permit_stats()
1238 self.assertEqual(ps['packets'], NUM_PKTS)
1241 # the contract does not allow non-IP
1243 pkt_non_ip_inter_epg_220_to_221 = (Ether(src=self.pg0.remote_mac,
1244 dst=self.pg2.remote_mac) /
1246 self.send_and_assert_no_replies(eps[0].itf,
1247 pkt_non_ip_inter_epg_220_to_221 * 17)
1250 # check that inter group is still disabled for the groups
1251 # not in the contract.
1253 self.send_and_assert_no_replies(eps[0].itf,
1254 pkt_inter_epg_220_to_222 * NUM_PKTS)
1257 # A uni-directional contract from EPG 220 -> 222 'L3 routed'
1259 c3 = VppGbpContract(
1260 self, 400, epgs[0].sclass, epgs[2].sclass, acl_index,
1261 [VppGbpContractRule(
1262 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1263 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1266 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1267 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1269 [ETH_P_IP, ETH_P_IPV6])
1272 self.logger.info(self.vapi.cli("sh gbp contract"))
1274 self.send_and_expect_routed(eps[0].itf,
1275 pkt_inter_epg_220_to_222 * NUM_PKTS,
1277 str(self.router_mac))
1280 # remove both contracts, traffic stops in both directions
1282 c2.remove_vpp_config()
1283 c1.remove_vpp_config()
1284 c3.remove_vpp_config()
1285 acl.remove_vpp_config()
1287 self.send_and_assert_no_replies(eps[2].itf,
1288 pkt_inter_epg_221_to_220 * NUM_PKTS)
1289 self.send_and_assert_no_replies(eps[0].itf,
1290 pkt_inter_epg_220_to_221 * NUM_PKTS)
1291 self.send_and_expect_bridged(eps[0].itf,
1292 pkt_intra_epg * NUM_PKTS,
1296 # EPs to the outside world
1299 # in the EP's RD an external subnet via the NAT EPG's recirc
1301 self, rd0, "0.0.0.0", 0,
1302 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1303 sw_if_index=recirc_nat.recirc.sw_if_index,
1304 sclass=epg_nat.sclass)
1306 self, rd0, "11.0.0.0", 8,
1307 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1308 sw_if_index=recirc_nat.recirc.sw_if_index,
1309 sclass=epg_nat.sclass)
1310 se16 = VppGbpSubnet(
1312 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1313 sw_if_index=recirc_nat.recirc.sw_if_index,
1314 sclass=epg_nat.sclass)
1315 # in the NAT RD an external subnet via the NAT EPG's uplink
1317 self, rd20, "0.0.0.0", 0,
1318 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1319 sw_if_index=epg_nat.uplink.sw_if_index,
1320 sclass=epg_nat.sclass)
1321 se36 = VppGbpSubnet(
1322 self, rd20, "::", 0,
1323 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1324 sw_if_index=epg_nat.uplink.sw_if_index,
1325 sclass=epg_nat.sclass)
1327 self, rd20, "11.0.0.0", 8,
1328 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1329 sw_if_index=epg_nat.uplink.sw_if_index,
1330 sclass=epg_nat.sclass)
1331 se1.add_vpp_config()
1332 se2.add_vpp_config()
1333 se16.add_vpp_config()
1334 se3.add_vpp_config()
1335 se36.add_vpp_config()
1336 se4.add_vpp_config()
1338 self.logger.info(self.vapi.cli("sh ip fib 0.0.0.0/0"))
1339 self.logger.info(self.vapi.cli("sh ip fib 11.0.0.1"))
1340 self.logger.info(self.vapi.cli("sh ip6 fib ::/0"))
1341 self.logger.info(self.vapi.cli("sh ip6 fib %s" %
1345 # From an EP to an outside address: IN2OUT
1347 pkt_inter_epg_220_to_global = (Ether(src=self.pg0.remote_mac,
1348 dst=str(self.router_mac)) /
1349 IP(src=eps[0].ip4.address,
1351 UDP(sport=1234, dport=1234) /
1355 self.send_and_assert_no_replies(eps[0].itf,
1356 pkt_inter_epg_220_to_global * NUM_PKTS)
1358 acl2 = VppGbpAcl(self)
1359 rule = acl2.create_rule(permit_deny=1, proto=17, sport_from=1234,
1360 sport_to=1234, dport_from=1234, dport_to=1234)
1361 rule2 = acl2.create_rule(is_ipv6=1, permit_deny=1, proto=17,
1362 sport_from=1234, sport_to=1234,
1363 dport_from=1234, dport_to=1234)
1365 acl_index2 = acl2.add_vpp_config([rule, rule2])
1366 c4 = VppGbpContract(
1367 self, 400, epgs[0].sclass, epgs[3].sclass, acl_index2,
1368 [VppGbpContractRule(
1369 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1370 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1373 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1374 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1376 [ETH_P_IP, ETH_P_IPV6])
1379 self.send_and_expect_natted(eps[0].itf,
1380 pkt_inter_epg_220_to_global * NUM_PKTS,
1382 eps[0].fip4.address)
1384 pkt_inter_epg_220_to_global = (Ether(src=self.pg0.remote_mac,
1385 dst=str(self.router_mac)) /
1386 IPv6(src=eps[0].ip6.address,
1388 UDP(sport=1234, dport=1234) /
1391 self.send_and_expect_natted6(self.pg0,
1392 pkt_inter_epg_220_to_global * NUM_PKTS,
1394 eps[0].fip6.address)
1397 # From a global address to an EP: OUT2IN
1399 pkt_inter_epg_220_from_global = (Ether(src=str(self.router_mac),
1400 dst=self.pg0.remote_mac) /
1401 IP(dst=eps[0].fip4.address,
1403 UDP(sport=1234, dport=1234) /
1406 self.send_and_assert_no_replies(
1407 self.pg7, pkt_inter_epg_220_from_global * NUM_PKTS)
1409 c5 = VppGbpContract(
1410 self, 400, epgs[3].sclass, epgs[0].sclass, acl_index2,
1411 [VppGbpContractRule(
1412 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1413 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1416 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1417 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1419 [ETH_P_IP, ETH_P_IPV6])
1422 self.send_and_expect_unnatted(self.pg7,
1423 pkt_inter_epg_220_from_global * NUM_PKTS,
1427 pkt_inter_epg_220_from_global = (Ether(src=str(self.router_mac),
1428 dst=self.pg0.remote_mac) /
1429 IPv6(dst=eps[0].fip6.address,
1431 UDP(sport=1234, dport=1234) /
1434 self.send_and_expect_unnatted6(
1436 pkt_inter_epg_220_from_global * NUM_PKTS,
1441 # From a local VM to another local VM using resp. public addresses:
1444 pkt_intra_epg_220_global = (Ether(src=self.pg0.remote_mac,
1445 dst=str(self.router_mac)) /
1446 IP(src=eps[0].ip4.address,
1447 dst=eps[1].fip4.address) /
1448 UDP(sport=1234, dport=1234) /
1451 self.send_and_expect_double_natted(eps[0].itf,
1452 pkt_intra_epg_220_global * NUM_PKTS,
1454 eps[0].fip4.address,
1457 pkt_intra_epg_220_global = (Ether(src=self.pg0.remote_mac,
1458 dst=str(self.router_mac)) /
1459 IPv6(src=eps[0].ip6.address,
1460 dst=eps[1].fip6.address) /
1461 UDP(sport=1234, dport=1234) /
1464 self.send_and_expect_double_natted6(
1466 pkt_intra_epg_220_global * NUM_PKTS,
1468 eps[0].fip6.address,
1475 # del static mappings for each EP from the 10/8 to 11/8 network
1476 flags = self.config_flags.NAT_IS_ADDR_ONLY
1477 self.vapi.nat44_add_del_static_mapping(
1479 local_ip_address=ep.ip4.bytes,
1480 external_ip_address=ep.fip4.bytes,
1481 external_sw_if_index=0xFFFFFFFF,
1484 self.vapi.nat66_add_del_static_mapping(
1485 local_ip_address=ep.ip6.bytes,
1486 external_ip_address=ep.fip6.bytes,
1490 # IP config on the BVI interfaces
1491 if epg != epgs[0] and epg != epgs[3]:
1492 flags = self.config_flags.NAT_IS_INSIDE
1493 self.vapi.nat44_interface_add_del_feature(
1494 sw_if_index=epg.bvi.sw_if_index,
1497 self.vapi.nat66_add_del_interface(
1498 is_add=0, flags=flags,
1499 sw_if_index=epg.bvi.sw_if_index)
1501 for recirc in recircs:
1502 self.vapi.nat44_interface_add_del_feature(
1503 sw_if_index=recirc.recirc.sw_if_index,
1505 self.vapi.nat66_add_del_interface(
1507 sw_if_index=recirc.recirc.sw_if_index)
1509 def wait_for_ep_timeout(self, sw_if_index=None, ip=None, mac=None,
1510 n_tries=100, s_time=1):
1512 if not find_gbp_endpoint(self, sw_if_index, ip, mac):
1514 n_tries = n_tries - 1
1516 self.assertFalse(find_gbp_endpoint(self, sw_if_index, ip, mac))
1519 def test_gbp_learn_l2(self):
1520 """ GBP L2 Endpoint Learning """
1522 self.vapi.cli("clear errors")
1524 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
1525 learnt = [{'mac': '00:00:11:11:11:01',
1527 'ip6': '2001:10::2'},
1528 {'mac': '00:00:11:11:11:02',
1530 'ip6': '2001:10::3'}]
1535 gt4 = VppIpTable(self, 1)
1536 gt4.add_vpp_config()
1537 gt6 = VppIpTable(self, 1, is_ip6=True)
1538 gt6.add_vpp_config()
1540 rd1 = VppGbpRouteDomain(self, 1, 401, gt4, gt6)
1541 rd1.add_vpp_config()
1544 # Pg2 hosts the vxlan tunnel, hosts on pg2 to act as TEPs
1545 # Pg3 hosts the IP4 UU-flood VXLAN tunnel
1546 # Pg4 hosts the IP6 UU-flood VXLAN tunnel
1548 self.pg2.config_ip4()
1549 self.pg2.resolve_arp()
1550 self.pg2.generate_remote_hosts(4)
1551 self.pg2.configure_ipv4_neighbors()
1552 self.pg3.config_ip4()
1553 self.pg3.resolve_arp()
1554 self.pg4.config_ip4()
1555 self.pg4.resolve_arp()
1558 # Add a mcast destination VXLAN-GBP tunnel for B&M traffic
1560 tun_bm = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
1563 tun_bm.add_vpp_config()
1566 # a GBP bridge domain with a BVI and a UU-flood interface
1568 bd1 = VppBridgeDomain(self, 1)
1569 bd1.add_vpp_config()
1570 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0,
1572 gbd1.add_vpp_config()
1574 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1575 self.logger.info(self.vapi.cli("sh gbp bridge"))
1577 # ... and has a /32 applied
1578 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
1579 ip_addr.add_vpp_config()
1582 # The Endpoint-group in which we are learning endpoints
1584 epg_220 = VppGbpEndpointGroup(self, 220, 112, rd1, gbd1,
1588 VppGbpEndpointRetention(2))
1589 epg_220.add_vpp_config()
1590 epg_330 = VppGbpEndpointGroup(self, 330, 113, rd1, gbd1,
1594 VppGbpEndpointRetention(2))
1595 epg_330.add_vpp_config()
1598 # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
1601 vx_tun_l2_1 = VppGbpVxlanTunnel(
1602 self, 99, bd1.bd_id,
1603 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L2,
1605 vx_tun_l2_1.add_vpp_config()
1608 # A static endpoint that the learnt endpoints are trying to
1611 ep = VppGbpEndpoint(self, self.pg0,
1613 "10.0.0.127", "11.0.0.127",
1614 "2001:10::1", "3001::1")
1617 self.assertTrue(find_route(self, ep.ip4.address, 32, table_id=1))
1619 # a packet with an sclass from an unknown EPG
1620 p = (Ether(src=self.pg2.remote_mac,
1621 dst=self.pg2.local_mac) /
1622 IP(src=self.pg2.remote_hosts[0].ip4,
1623 dst=self.pg2.local_ip4) /
1624 UDP(sport=1234, dport=48879) /
1625 VXLAN(vni=99, gpid=88, flags=0x88) /
1626 Ether(src=learnt[0]["mac"], dst=ep.mac) /
1627 IP(src=learnt[0]["ip"], dst=ep.ip4.address) /
1628 UDP(sport=1234, dport=1234) /
1631 self.send_and_assert_no_replies(self.pg2, p)
1633 self.logger.info(self.vapi.cli("sh error"))
1634 # self.assert_packet_counter_equal(
1635 # '/err/gbp-policy-port/drop-no-contract', 1)
1638 # we should not have learnt a new tunnel endpoint, since
1639 # the EPG was not learnt.
1641 self.assertEqual(INDEX_INVALID,
1642 find_vxlan_gbp_tunnel(self,
1644 self.pg2.remote_hosts[0].ip4,
1647 # epg is not learnt, because the EPG is unknown
1648 self.assertEqual(len(self.vapi.gbp_endpoint_dump()), 1)
1651 # Learn new EPs from IP packets
1653 for ii, l in enumerate(learnt):
1654 # a packet with an sclass from a known EPG
1655 # arriving on an unknown TEP
1656 p = (Ether(src=self.pg2.remote_mac,
1657 dst=self.pg2.local_mac) /
1658 IP(src=self.pg2.remote_hosts[1].ip4,
1659 dst=self.pg2.local_ip4) /
1660 UDP(sport=1234, dport=48879) /
1661 VXLAN(vni=99, gpid=112, flags=0x88) /
1662 Ether(src=l['mac'], dst=ep.mac) /
1663 IP(src=l['ip'], dst=ep.ip4.address) /
1664 UDP(sport=1234, dport=1234) /
1667 rx = self.send_and_expect(self.pg2, [p], self.pg0)
1670 tep1_sw_if_index = find_vxlan_gbp_tunnel(
1673 self.pg2.remote_hosts[1].ip4,
1675 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
1678 # the EP is learnt via the learnt TEP
1679 # both from its MAC and its IP
1681 self.assertTrue(find_gbp_endpoint(self,
1682 vx_tun_l2_1.sw_if_index,
1684 self.assertTrue(find_gbp_endpoint(self,
1685 vx_tun_l2_1.sw_if_index,
1688 # self.assert_packet_counter_equal(
1689 # '/err/gbp-policy-port/allow-intra-sclass', 2)
1691 self.logger.info(self.vapi.cli("show gbp endpoint"))
1692 self.logger.info(self.vapi.cli("show gbp vxlan"))
1693 self.logger.info(self.vapi.cli("show ip mfib"))
1696 # If we sleep for the threshold time, the learnt endpoints should
1700 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1704 # Learn new EPs from GARP packets received on the BD's mcast tunnel
1706 for ii, l in enumerate(learnt):
1707 # a packet with an sclass from a known EPG
1708 # arriving on an unknown TEP
1709 p = (Ether(src=self.pg2.remote_mac,
1710 dst=self.pg2.local_mac) /
1711 IP(src=self.pg2.remote_hosts[1].ip4,
1713 UDP(sport=1234, dport=48879) /
1714 VXLAN(vni=88, gpid=112, flags=0x88) /
1715 Ether(src=l['mac'], dst="ff:ff:ff:ff:ff:ff") /
1717 psrc=l['ip'], pdst=l['ip'],
1718 hwsrc=l['mac'], hwdst="ff:ff:ff:ff:ff:ff"))
1720 rx = self.send_and_expect(self.pg4, [p], self.pg0)
1723 tep1_sw_if_index = find_vxlan_gbp_tunnel(
1726 self.pg2.remote_hosts[1].ip4,
1728 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
1731 # the EP is learnt via the learnt TEP
1732 # both from its MAC and its IP
1734 self.assertTrue(find_gbp_endpoint(self,
1735 vx_tun_l2_1.sw_if_index,
1737 self.assertTrue(find_gbp_endpoint(self,
1738 vx_tun_l2_1.sw_if_index,
1742 # wait for the learnt endpoints to age out
1745 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1749 # Learn new EPs from L2 packets
1751 for ii, l in enumerate(learnt):
1752 # a packet with an sclass from a known EPG
1753 # arriving on an unknown TEP
1754 p = (Ether(src=self.pg2.remote_mac,
1755 dst=self.pg2.local_mac) /
1756 IP(src=self.pg2.remote_hosts[1].ip4,
1757 dst=self.pg2.local_ip4) /
1758 UDP(sport=1234, dport=48879) /
1759 VXLAN(vni=99, gpid=112, flags=0x88) /
1760 Ether(src=l['mac'], dst=ep.mac) /
1763 rx = self.send_and_expect(self.pg2, [p], self.pg0)
1766 tep1_sw_if_index = find_vxlan_gbp_tunnel(
1769 self.pg2.remote_hosts[1].ip4,
1771 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
1774 # the EP is learnt via the learnt TEP
1775 # both from its MAC and its IP
1777 self.assertTrue(find_gbp_endpoint(self,
1778 vx_tun_l2_1.sw_if_index,
1781 self.logger.info(self.vapi.cli("show gbp endpoint"))
1782 self.logger.info(self.vapi.cli("show gbp vxlan"))
1783 self.logger.info(self.vapi.cli("show vxlan-gbp tunnel"))
1786 # wait for the learnt endpoints to age out
1789 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1793 # repeat. the do not learn bit is set so the EPs are not learnt
1796 # a packet with an sclass from a known EPG
1797 p = (Ether(src=self.pg2.remote_mac,
1798 dst=self.pg2.local_mac) /
1799 IP(src=self.pg2.remote_hosts[1].ip4,
1800 dst=self.pg2.local_ip4) /
1801 UDP(sport=1234, dport=48879) /
1802 VXLAN(vni=99, gpid=112, flags=0x88, gpflags="D") /
1803 Ether(src=l['mac'], dst=ep.mac) /
1804 IP(src=l['ip'], dst=ep.ip4.address) /
1805 UDP(sport=1234, dport=1234) /
1808 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
1811 self.assertFalse(find_gbp_endpoint(self,
1812 vx_tun_l2_1.sw_if_index,
1819 # a packet with an sclass from a known EPG
1820 p = (Ether(src=self.pg2.remote_mac,
1821 dst=self.pg2.local_mac) /
1822 IP(src=self.pg2.remote_hosts[1].ip4,
1823 dst=self.pg2.local_ip4) /
1824 UDP(sport=1234, dport=48879) /
1825 VXLAN(vni=99, gpid=112, flags=0x88) /
1826 Ether(src=l['mac'], dst=ep.mac) /
1827 IP(src=l['ip'], dst=ep.ip4.address) /
1828 UDP(sport=1234, dport=1234) /
1831 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
1833 self.assertTrue(find_gbp_endpoint(self,
1834 vx_tun_l2_1.sw_if_index,
1838 # Static EP replies to dynamics
1840 self.logger.info(self.vapi.cli("sh l2fib bd_id 1"))
1842 p = (Ether(src=ep.mac, dst=l['mac']) /
1843 IP(dst=l['ip'], src=ep.ip4.address) /
1844 UDP(sport=1234, dport=1234) /
1847 rxs = self.send_and_expect(self.pg0, p * 17, self.pg2)
1850 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
1851 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
1852 self.assertEqual(rx[UDP].dport, 48879)
1853 # the UDP source port is a random value for hashing
1854 self.assertEqual(rx[VXLAN].gpid, 112)
1855 self.assertEqual(rx[VXLAN].vni, 99)
1856 self.assertTrue(rx[VXLAN].flags.G)
1857 self.assertTrue(rx[VXLAN].flags.Instance)
1858 self.assertTrue(rx[VXLAN].gpflags.A)
1859 self.assertFalse(rx[VXLAN].gpflags.D)
1862 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1866 # repeat in the other EPG
1867 # there's no contract between 220 and 330, but the A-bit is set
1868 # so the packet is cleared for delivery
1871 # a packet with an sclass from a known EPG
1872 p = (Ether(src=self.pg2.remote_mac,
1873 dst=self.pg2.local_mac) /
1874 IP(src=self.pg2.remote_hosts[1].ip4,
1875 dst=self.pg2.local_ip4) /
1876 UDP(sport=1234, dport=48879) /
1877 VXLAN(vni=99, gpid=113, flags=0x88, gpflags='A') /
1878 Ether(src=l['mac'], dst=ep.mac) /
1879 IP(src=l['ip'], dst=ep.ip4.address) /
1880 UDP(sport=1234, dport=1234) /
1883 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
1885 self.assertTrue(find_gbp_endpoint(self,
1886 vx_tun_l2_1.sw_if_index,
1890 # static EP cannot reach the learnt EPs since there is no contract
1891 # only test 1 EP as the others could timeout
1893 p = (Ether(src=ep.mac, dst=l['mac']) /
1894 IP(dst=learnt[0]['ip'], src=ep.ip4.address) /
1895 UDP(sport=1234, dport=1234) /
1898 self.send_and_assert_no_replies(self.pg0, [p])
1901 # refresh the entries after the check for no replies above
1904 # a packet with an sclass from a known EPG
1905 p = (Ether(src=self.pg2.remote_mac,
1906 dst=self.pg2.local_mac) /
1907 IP(src=self.pg2.remote_hosts[1].ip4,
1908 dst=self.pg2.local_ip4) /
1909 UDP(sport=1234, dport=48879) /
1910 VXLAN(vni=99, gpid=113, flags=0x88, gpflags='A') /
1911 Ether(src=l['mac'], dst=ep.mac) /
1912 IP(src=l['ip'], dst=ep.ip4.address) /
1913 UDP(sport=1234, dport=1234) /
1916 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
1918 self.assertTrue(find_gbp_endpoint(self,
1919 vx_tun_l2_1.sw_if_index,
1923 # Add the contract so they can talk
1925 acl = VppGbpAcl(self)
1926 rule = acl.create_rule(permit_deny=1, proto=17)
1927 rule2 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
1928 acl_index = acl.add_vpp_config([rule, rule2])
1929 c1 = VppGbpContract(
1930 self, 401, epg_220.sclass, epg_330.sclass, acl_index,
1931 [VppGbpContractRule(
1932 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1933 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1936 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1937 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
1939 [ETH_P_IP, ETH_P_IPV6])
1943 p = (Ether(src=ep.mac, dst=l['mac']) /
1944 IP(dst=l['ip'], src=ep.ip4.address) /
1945 UDP(sport=1234, dport=1234) /
1948 self.send_and_expect(self.pg0, [p], self.pg2)
1951 # send UU packets from the local EP
1953 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1954 self.logger.info(self.vapi.cli("sh gbp bridge"))
1955 p_uu = (Ether(src=ep.mac, dst="00:11:11:11:11:11") /
1956 IP(dst="10.0.0.133", src=ep.ip4.address) /
1957 UDP(sport=1234, dport=1234) /
1959 rxs = self.send_and_expect(ep.itf, [p_uu], gbd1.uu_fwd)
1961 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1963 p_bm = (Ether(src=ep.mac, dst="ff:ff:ff:ff:ff:ff") /
1964 IP(dst="10.0.0.133", src=ep.ip4.address) /
1965 UDP(sport=1234, dport=1234) /
1967 rxs = self.send_and_expect_only(ep.itf, [p_bm], tun_bm.mcast_itf)
1970 self.assertEqual(rx[IP].src, self.pg4.local_ip4)
1971 self.assertEqual(rx[IP].dst, "239.1.1.1")
1972 self.assertEqual(rx[UDP].dport, 48879)
1973 # the UDP source port is a random value for hashing
1974 self.assertEqual(rx[VXLAN].gpid, 112)
1975 self.assertEqual(rx[VXLAN].vni, 88)
1976 self.assertTrue(rx[VXLAN].flags.G)
1977 self.assertTrue(rx[VXLAN].flags.Instance)
1978 self.assertFalse(rx[VXLAN].gpflags.A)
1979 self.assertFalse(rx[VXLAN].gpflags.D)
1982 # Check v6 Endpoints
1985 # a packet with an sclass from a known EPG
1986 p = (Ether(src=self.pg2.remote_mac,
1987 dst=self.pg2.local_mac) /
1988 IP(src=self.pg2.remote_hosts[1].ip4,
1989 dst=self.pg2.local_ip4) /
1990 UDP(sport=1234, dport=48879) /
1991 VXLAN(vni=99, gpid=113, flags=0x88, gpflags='A') /
1992 Ether(src=l['mac'], dst=ep.mac) /
1993 IPv6(src=l['ip6'], dst=ep.ip6.address) /
1994 UDP(sport=1234, dport=1234) /
1997 rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
1999 self.assertTrue(find_gbp_endpoint(self,
2000 vx_tun_l2_1.sw_if_index,
2004 # L3 Endpoint Learning
2005 # - configured on the bridge's BVI
2012 self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
2014 self.pg2.unconfig_ip4()
2015 self.pg3.unconfig_ip4()
2016 self.pg4.unconfig_ip4()
2018 self.logger.info(self.vapi.cli("sh int"))
2019 self.logger.info(self.vapi.cli("sh gbp vxlan"))
2021 def test_gbp_contract(self):
2022 """ GBP CONTRACTS """
2027 gt4 = VppIpTable(self, 0)
2028 gt4.add_vpp_config()
2029 gt6 = VppIpTable(self, 0, is_ip6=True)
2030 gt6.add_vpp_config()
2032 rd0 = VppGbpRouteDomain(self, 0, 400, gt4, gt6, None, None)
2034 rd0.add_vpp_config()
2039 bd1 = VppBridgeDomain(self, 1, arp_term=0)
2040 bd2 = VppBridgeDomain(self, 2, arp_term=0)
2042 bd1.add_vpp_config()
2043 bd2.add_vpp_config()
2045 gbd1 = VppGbpBridgeDomain(self, bd1, rd0, self.loop0)
2046 gbd2 = VppGbpBridgeDomain(self, bd2, rd0, self.loop1)
2048 gbd1.add_vpp_config()
2049 gbd2.add_vpp_config()
2052 # 3 EPGs, 2 of which share a BD.
2054 epgs = [VppGbpEndpointGroup(self, 220, 1220, rd0, gbd1,
2056 "10.0.0.128", "2001:10::128"),
2057 VppGbpEndpointGroup(self, 221, 1221, rd0, gbd1,
2059 "10.0.1.128", "2001:10:1::128"),
2060 VppGbpEndpointGroup(self, 222, 1222, rd0, gbd2,
2062 "10.0.2.128", "2001:10:2::128")]
2064 # 4 end-points, 2 in the same subnet, 3 in the same BD
2066 eps = [VppGbpEndpoint(self, self.pg0,
2068 "10.0.0.1", "11.0.0.1",
2069 "2001:10::1", "3001::1"),
2070 VppGbpEndpoint(self, self.pg1,
2072 "10.0.0.2", "11.0.0.2",
2073 "2001:10::2", "3001::2"),
2074 VppGbpEndpoint(self, self.pg2,
2076 "10.0.1.1", "11.0.0.3",
2077 "2001:10:1::1", "3001::3"),
2078 VppGbpEndpoint(self, self.pg3,
2080 "10.0.2.1", "11.0.0.4",
2081 "2001:10:2::1", "3001::4")]
2084 # Config related to each of the EPGs
2087 # IP config on the BVI interfaces
2089 VppIpInterfaceBind(self, epg.bvi, epg.rd.t4).add_vpp_config()
2090 VppIpInterfaceBind(self, epg.bvi, epg.rd.t6).add_vpp_config()
2091 self.vapi.sw_interface_set_mac_address(
2092 epg.bvi.sw_if_index,
2093 self.router_mac.packed)
2095 if_ip4 = VppIpInterfaceAddress(self, epg.bvi, epg.bvi_ip4, 32)
2096 if_ip6 = VppIpInterfaceAddress(self, epg.bvi, epg.bvi_ip6, 128)
2097 if_ip4.add_vpp_config()
2098 if_ip6.add_vpp_config()
2100 # add the BD ARP termination entry for BVI IP
2101 epg.bd_arp_ip4 = VppBridgeDomainArpEntry(self, epg.bd.bd,
2102 str(self.router_mac),
2103 epg.bvi_ip4.address)
2104 epg.bd_arp_ip4.add_vpp_config()
2107 epg.add_vpp_config()
2115 self.logger.info(self.vapi.cli("show gbp endpoint"))
2116 self.logger.info(self.vapi.cli("show interface"))
2117 self.logger.info(self.vapi.cli("show br"))
2120 # Intra epg allowed without contract
2122 pkt_intra_epg_220_to_220 = (Ether(src=self.pg0.remote_mac,
2123 dst=self.pg1.remote_mac) /
2124 IP(src=eps[0].ip4.address,
2125 dst=eps[1].ip4.address) /
2126 UDP(sport=1234, dport=1234) /
2129 self.send_and_expect_bridged(self.pg0,
2130 pkt_intra_epg_220_to_220 * 65,
2134 # Inter epg denied without contract
2136 pkt_inter_epg_220_to_221 = (Ether(src=self.pg0.remote_mac,
2137 dst=self.pg2.remote_mac) /
2138 IP(src=eps[0].ip4.address,
2139 dst=eps[2].ip4.address) /
2140 UDP(sport=1234, dport=1234) /
2143 self.send_and_assert_no_replies(self.pg0, pkt_inter_epg_220_to_221)
2146 # A uni-directional contract from EPG 220 -> 221
2148 acl = VppGbpAcl(self)
2149 rule = acl.create_rule(permit_deny=1, proto=17)
2150 rule2 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
2151 acl_index = acl.add_vpp_config([rule, rule2])
2152 c1 = VppGbpContract(
2153 self, 400, epgs[0].sclass, epgs[1].sclass, acl_index,
2154 [VppGbpContractRule(
2155 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2156 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2159 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2160 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2162 [ETH_P_IP, ETH_P_IPV6])
2165 self.send_and_expect_bridged(eps[0].itf,
2166 pkt_inter_epg_220_to_221 * 65,
2169 pkt_inter_epg_220_to_222 = (Ether(src=self.pg0.remote_mac,
2170 dst=str(self.router_mac)) /
2171 IP(src=eps[0].ip4.address,
2172 dst=eps[3].ip4.address) /
2173 UDP(sport=1234, dport=1234) /
2175 self.send_and_assert_no_replies(eps[0].itf,
2176 pkt_inter_epg_220_to_222 * 65)
2179 # contract for the return direction
2181 c2 = VppGbpContract(
2182 self, 400, epgs[1].sclass, epgs[0].sclass, acl_index,
2183 [VppGbpContractRule(
2184 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2185 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2188 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2189 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2191 [ETH_P_IP, ETH_P_IPV6])
2194 self.send_and_expect_bridged(eps[0].itf,
2195 pkt_inter_epg_220_to_221 * 65,
2197 pkt_inter_epg_221_to_220 = (Ether(src=self.pg2.remote_mac,
2198 dst=self.pg0.remote_mac) /
2199 IP(src=eps[2].ip4.address,
2200 dst=eps[0].ip4.address) /
2201 UDP(sport=1234, dport=1234) /
2203 self.send_and_expect_bridged(eps[2].itf,
2204 pkt_inter_epg_221_to_220 * 65,
2208 # contract between 220 and 222 uni-direction
2210 c3 = VppGbpContract(
2211 self, 400, epgs[0].sclass, epgs[2].sclass, acl_index,
2212 [VppGbpContractRule(
2213 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2214 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2217 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2218 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
2220 [ETH_P_IP, ETH_P_IPV6])
2223 self.send_and_expect(eps[0].itf,
2224 pkt_inter_epg_220_to_222 * 65,
2227 c3.remove_vpp_config()
2228 c1.remove_vpp_config()
2229 c2.remove_vpp_config()
2230 acl.remove_vpp_config()
2232 def test_gbp_bd_flags(self):
2233 """ GBP BD FLAGS """
2238 gt4 = VppIpTable(self, 1)
2239 gt4.add_vpp_config()
2240 gt6 = VppIpTable(self, 1, is_ip6=True)
2241 gt6.add_vpp_config()
2243 rd1 = VppGbpRouteDomain(self, 1, 401, gt4, gt6)
2244 rd1.add_vpp_config()
2247 # Pg3 hosts the IP4 UU-flood VXLAN tunnel
2248 # Pg4 hosts the IP6 UU-flood VXLAN tunnel
2250 self.pg3.config_ip4()
2251 self.pg3.resolve_arp()
2252 self.pg4.config_ip4()
2253 self.pg4.resolve_arp()
2256 # Add a mcast destination VXLAN-GBP tunnel for B&M traffic
2258 tun_bm = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
2261 tun_bm.add_vpp_config()
2264 # a GBP bridge domain with a BVI and a UU-flood interface
2266 bd1 = VppBridgeDomain(self, 1)
2267 bd1.add_vpp_config()
2269 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0, self.pg3,
2270 tun_bm, uu_drop=True, bm_drop=True)
2271 gbd1.add_vpp_config()
2273 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2274 self.logger.info(self.vapi.cli("sh gbp bridge"))
2276 # ... and has a /32 applied
2277 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2278 ip_addr.add_vpp_config()
2281 # The Endpoint-group
2283 epg_220 = VppGbpEndpointGroup(self, 220, 112, rd1, gbd1,
2287 VppGbpEndpointRetention(2))
2288 epg_220.add_vpp_config()
2290 ep = VppGbpEndpoint(self, self.pg0,
2292 "10.0.0.127", "11.0.0.127",
2293 "2001:10::1", "3001::1")
2296 # send UU/BM packet from the local EP with UU drop and BM drop enabled
2299 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2300 self.logger.info(self.vapi.cli("sh gbp bridge"))
2301 p_uu = (Ether(src=ep.mac, dst="00:11:11:11:11:11") /
2302 IP(dst="10.0.0.133", src=ep.ip4.address) /
2303 UDP(sport=1234, dport=1234) /
2305 self.send_and_assert_no_replies(ep.itf, [p_uu])
2307 p_bm = (Ether(src=ep.mac, dst="ff:ff:ff:ff:ff:ff") /
2308 IP(dst="10.0.0.133", src=ep.ip4.address) /
2309 UDP(sport=1234, dport=1234) /
2311 self.send_and_assert_no_replies(ep.itf, [p_bm])
2313 self.pg3.unconfig_ip4()
2314 self.pg4.unconfig_ip4()
2316 self.logger.info(self.vapi.cli("sh int"))
2318 def test_gbp_learn_vlan_l2(self):
2319 """ GBP L2 Endpoint w/ VLANs"""
2321 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
2322 learnt = [{'mac': '00:00:11:11:11:01',
2324 'ip6': '2001:10::2'},
2325 {'mac': '00:00:11:11:11:02',
2327 'ip6': '2001:10::3'}]
2332 gt4 = VppIpTable(self, 1)
2333 gt4.add_vpp_config()
2334 gt6 = VppIpTable(self, 1, is_ip6=True)
2335 gt6.add_vpp_config()
2337 rd1 = VppGbpRouteDomain(self, 1, 401, gt4, gt6)
2338 rd1.add_vpp_config()
2341 # Pg2 hosts the vxlan tunnel, hosts on pg2 to act as TEPs
2343 self.pg2.config_ip4()
2344 self.pg2.resolve_arp()
2345 self.pg2.generate_remote_hosts(4)
2346 self.pg2.configure_ipv4_neighbors()
2347 self.pg3.config_ip4()
2348 self.pg3.resolve_arp()
2351 # The EP will be on a vlan sub-interface
2353 vlan_11 = VppDot1QSubint(self, self.pg0, 11)
2355 self.vapi.l2_interface_vlan_tag_rewrite(
2356 sw_if_index=vlan_11.sw_if_index, vtr_op=L2_VTR_OP.L2_POP_1,
2359 bd_uu_fwd = VppVxlanGbpTunnel(self, self.pg3.local_ip4,
2360 self.pg3.remote_ip4, 116)
2361 bd_uu_fwd.add_vpp_config()
2364 # a GBP bridge domain with a BVI and a UU-flood interface
2365 # The BD is marked as do not learn, so no endpoints are ever
2366 # learnt in this BD.
2368 bd1 = VppBridgeDomain(self, 1)
2369 bd1.add_vpp_config()
2370 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0, bd_uu_fwd,
2372 gbd1.add_vpp_config()
2374 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2375 self.logger.info(self.vapi.cli("sh gbp bridge"))
2377 # ... and has a /32 applied
2378 ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2379 ip_addr.add_vpp_config()
2382 # The Endpoint-group in which we are learning endpoints
2384 epg_220 = VppGbpEndpointGroup(self, 220, 441, rd1, gbd1,
2388 VppGbpEndpointRetention(2))
2389 epg_220.add_vpp_config()
2392 # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
2395 vx_tun_l2_1 = VppGbpVxlanTunnel(
2396 self, 99, bd1.bd_id,
2397 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L2,
2399 vx_tun_l2_1.add_vpp_config()
2402 # A static endpoint that the learnt endpoints are trying to
2405 ep = VppGbpEndpoint(self, vlan_11,
2407 "10.0.0.127", "11.0.0.127",
2408 "2001:10::1", "3001::1")
2411 self.assertTrue(find_route(self, ep.ip4.address, 32, table_id=1))
2414 # Send to the static EP
2416 for ii, l in enumerate(learnt):
2417 # a packet with an sclass from a known EPG
2418 # arriving on an unknown TEP
2419 p = (Ether(src=self.pg2.remote_mac,
2420 dst=self.pg2.local_mac) /
2421 IP(src=self.pg2.remote_hosts[1].ip4,
2422 dst=self.pg2.local_ip4) /
2423 UDP(sport=1234, dport=48879) /
2424 VXLAN(vni=99, gpid=441, flags=0x88) /
2425 Ether(src=l['mac'], dst=ep.mac) /
2426 IP(src=l['ip'], dst=ep.ip4.address) /
2427 UDP(sport=1234, dport=1234) /
2430 rxs = self.send_and_expect(self.pg2, [p], self.pg0)
2433 # packet to EP has the EP's vlan tag
2436 self.assertEqual(rx[Dot1Q].vlan, 11)
2439 # the EP is not learnt since the BD setting prevents it
2442 self.assertFalse(find_gbp_endpoint(self,
2443 vx_tun_l2_1.sw_if_index,
2445 self.assertEqual(INDEX_INVALID,
2446 find_vxlan_gbp_tunnel(
2449 self.pg2.remote_hosts[1].ip4,
2452 self.assertEqual(len(self.vapi.gbp_endpoint_dump()), 1)
2456 # we didn't learn the remotes so they are sent to the UU-fwd
2459 p = (Ether(src=ep.mac, dst=l['mac']) /
2461 IP(dst=l['ip'], src=ep.ip4.address) /
2462 UDP(sport=1234, dport=1234) /
2465 rxs = self.send_and_expect(self.pg0, p * 17, self.pg3)
2468 self.assertEqual(rx[IP].src, self.pg3.local_ip4)
2469 self.assertEqual(rx[IP].dst, self.pg3.remote_ip4)
2470 self.assertEqual(rx[UDP].dport, 48879)
2471 # the UDP source port is a random value for hashing
2472 self.assertEqual(rx[VXLAN].gpid, 441)
2473 self.assertEqual(rx[VXLAN].vni, 116)
2474 self.assertTrue(rx[VXLAN].flags.G)
2475 self.assertTrue(rx[VXLAN].flags.Instance)
2476 self.assertFalse(rx[VXLAN].gpflags.A)
2477 self.assertFalse(rx[VXLAN].gpflags.D)
2479 self.pg2.unconfig_ip4()
2480 self.pg3.unconfig_ip4()
2482 def test_gbp_learn_l3(self):
2483 """ GBP L3 Endpoint Learning """
2485 self.vapi.cli("set logging class gbp level debug")
2487 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
2488 routed_dst_mac = "00:0c:0c:0c:0c:0c"
2489 routed_src_mac = "00:22:bd:f8:19:ff"
2491 learnt = [{'mac': '00:00:11:11:11:02',
2493 'ip6': '2001:10::2'},
2494 {'mac': '00:00:11:11:11:03',
2496 'ip6': '2001:10::3'}]
2501 t4 = VppIpTable(self, 1)
2503 t6 = VppIpTable(self, 1, True)
2506 tun_ip4_uu = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
2507 self.pg4.remote_ip4, 114)
2508 tun_ip6_uu = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
2509 self.pg4.remote_ip4, 116)
2510 tun_ip4_uu.add_vpp_config()
2511 tun_ip6_uu.add_vpp_config()
2513 rd1 = VppGbpRouteDomain(self, 2, 401, t4, t6, tun_ip4_uu, tun_ip6_uu)
2514 rd1.add_vpp_config()
2516 self.loop0.set_mac(self.router_mac)
2519 # Bind the BVI to the RD
2521 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
2522 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
2525 # Pg2 hosts the vxlan tunnel
2526 # hosts on pg2 to act as TEPs
2530 self.pg2.config_ip4()
2531 self.pg2.resolve_arp()
2532 self.pg2.generate_remote_hosts(4)
2533 self.pg2.configure_ipv4_neighbors()
2534 self.pg3.config_ip4()
2535 self.pg3.resolve_arp()
2536 self.pg4.config_ip4()
2537 self.pg4.resolve_arp()
2540 # a GBP bridge domain with a BVI and a UU-flood interface
2542 bd1 = VppBridgeDomain(self, 1)
2543 bd1.add_vpp_config()
2544 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0, self.pg3)
2545 gbd1.add_vpp_config()
2547 self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2548 self.logger.info(self.vapi.cli("sh gbp bridge"))
2549 self.logger.info(self.vapi.cli("sh gbp route"))
2551 # ... and has a /32 and /128 applied
2552 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2553 ip4_addr.add_vpp_config()
2554 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 128)
2555 ip6_addr.add_vpp_config()
2558 # The Endpoint-group in which we are learning endpoints
2560 epg_220 = VppGbpEndpointGroup(self, 220, 441, rd1, gbd1,
2564 VppGbpEndpointRetention(2))
2565 epg_220.add_vpp_config()
2568 # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
2571 vx_tun_l3 = VppGbpVxlanTunnel(
2572 self, 101, rd1.rd_id,
2573 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
2575 vx_tun_l3.add_vpp_config()
2578 # A static endpoint that the learnt endpoints are trying to
2581 ep = VppGbpEndpoint(self, self.pg0,
2583 "10.0.0.127", "11.0.0.127",
2584 "2001:10::1", "3001::1")
2588 # learn some remote IPv4 EPs
2590 for ii, l in enumerate(learnt):
2591 # a packet with an sclass from a known EPG
2592 # arriving on an unknown TEP
2593 p = (Ether(src=self.pg2.remote_mac,
2594 dst=self.pg2.local_mac) /
2595 IP(src=self.pg2.remote_hosts[1].ip4,
2596 dst=self.pg2.local_ip4) /
2597 UDP(sport=1234, dport=48879) /
2598 VXLAN(vni=101, gpid=441, flags=0x88) /
2599 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2600 IP(src=l['ip'], dst=ep.ip4.address) /
2601 UDP(sport=1234, dport=1234) /
2604 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2607 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2610 self.pg2.remote_hosts[1].ip4,
2612 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2614 # endpoint learnt via the parent GBP-vxlan interface
2615 self.assertTrue(find_gbp_endpoint(self,
2616 vx_tun_l3._sw_if_index,
2620 # Static IPv4 EP replies to learnt
2623 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2624 IP(dst=l['ip'], src=ep.ip4.address) /
2625 UDP(sport=1234, dport=1234) /
2628 rxs = self.send_and_expect(self.pg0, p * 1, self.pg2)
2631 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2632 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2633 self.assertEqual(rx[UDP].dport, 48879)
2634 # the UDP source port is a random value for hashing
2635 self.assertEqual(rx[VXLAN].gpid, 441)
2636 self.assertEqual(rx[VXLAN].vni, 101)
2637 self.assertTrue(rx[VXLAN].flags.G)
2638 self.assertTrue(rx[VXLAN].flags.Instance)
2639 self.assertTrue(rx[VXLAN].gpflags.A)
2640 self.assertFalse(rx[VXLAN].gpflags.D)
2642 inner = rx[VXLAN].payload
2644 self.assertEqual(inner[Ether].src, routed_src_mac)
2645 self.assertEqual(inner[Ether].dst, routed_dst_mac)
2646 self.assertEqual(inner[IP].src, ep.ip4.address)
2647 self.assertEqual(inner[IP].dst, l['ip'])
2650 self.assertFalse(find_gbp_endpoint(self,
2655 # learn some remote IPv6 EPs
2657 for ii, l in enumerate(learnt):
2658 # a packet with an sclass from a known EPG
2659 # arriving on an unknown TEP
2660 p = (Ether(src=self.pg2.remote_mac,
2661 dst=self.pg2.local_mac) /
2662 IP(src=self.pg2.remote_hosts[1].ip4,
2663 dst=self.pg2.local_ip4) /
2664 UDP(sport=1234, dport=48879) /
2665 VXLAN(vni=101, gpid=441, flags=0x88) /
2666 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2667 IPv6(src=l['ip6'], dst=ep.ip6.address) /
2668 UDP(sport=1234, dport=1234) /
2671 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2674 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2677 self.pg2.remote_hosts[1].ip4,
2679 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2681 self.logger.info(self.vapi.cli("show gbp bridge"))
2682 self.logger.info(self.vapi.cli("show vxlan-gbp tunnel"))
2683 self.logger.info(self.vapi.cli("show gbp vxlan"))
2684 self.logger.info(self.vapi.cli("show int addr"))
2686 # endpoint learnt via the TEP
2687 self.assertTrue(find_gbp_endpoint(self, ip=l['ip6']))
2689 self.logger.info(self.vapi.cli("show gbp endpoint"))
2690 self.logger.info(self.vapi.cli("show ip fib index 1 %s" % l['ip']))
2693 # Static EP replies to learnt
2696 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2697 IPv6(dst=l['ip6'], src=ep.ip6.address) /
2698 UDP(sport=1234, dport=1234) /
2701 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
2704 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2705 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2706 self.assertEqual(rx[UDP].dport, 48879)
2707 # the UDP source port is a random value for hashing
2708 self.assertEqual(rx[VXLAN].gpid, 441)
2709 self.assertEqual(rx[VXLAN].vni, 101)
2710 self.assertTrue(rx[VXLAN].flags.G)
2711 self.assertTrue(rx[VXLAN].flags.Instance)
2712 self.assertTrue(rx[VXLAN].gpflags.A)
2713 self.assertFalse(rx[VXLAN].gpflags.D)
2715 inner = rx[VXLAN].payload
2717 self.assertEqual(inner[Ether].src, routed_src_mac)
2718 self.assertEqual(inner[Ether].dst, routed_dst_mac)
2719 self.assertEqual(inner[IPv6].src, ep.ip6.address)
2720 self.assertEqual(inner[IPv6].dst, l['ip6'])
2722 self.logger.info(self.vapi.cli("sh gbp endpoint"))
2724 self.wait_for_ep_timeout(ip=l['ip'])
2727 # Static sends to unknown EP with no route
2729 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2730 IP(dst="10.0.0.99", src=ep.ip4.address) /
2731 UDP(sport=1234, dport=1234) /
2734 self.send_and_assert_no_replies(self.pg0, [p])
2737 # Add a route to static EP's v4 and v6 subnet
2738 # packets should be sent on the v4/v6 uu=fwd interface resp.
2740 se_10_24 = VppGbpSubnet(
2741 self, rd1, "10.0.0.0", 24,
2742 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT)
2743 se_10_24.add_vpp_config()
2745 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2746 IP(dst="10.0.0.99", src=ep.ip4.address) /
2747 UDP(sport=1234, dport=1234) /
2750 rxs = self.send_and_expect(self.pg0, [p], self.pg4)
2752 self.assertEqual(rx[IP].src, self.pg4.local_ip4)
2753 self.assertEqual(rx[IP].dst, self.pg4.remote_ip4)
2754 self.assertEqual(rx[UDP].dport, 48879)
2755 # the UDP source port is a random value for hashing
2756 self.assertEqual(rx[VXLAN].gpid, 441)
2757 self.assertEqual(rx[VXLAN].vni, 114)
2758 self.assertTrue(rx[VXLAN].flags.G)
2759 self.assertTrue(rx[VXLAN].flags.Instance)
2760 # policy is not applied to packets sent to the uu-fwd interfaces
2761 self.assertFalse(rx[VXLAN].gpflags.A)
2762 self.assertFalse(rx[VXLAN].gpflags.D)
2765 # learn some remote IPv4 EPs
2767 for ii, l in enumerate(learnt):
2768 # a packet with an sclass from a known EPG
2769 # arriving on an unknown TEP
2770 p = (Ether(src=self.pg2.remote_mac,
2771 dst=self.pg2.local_mac) /
2772 IP(src=self.pg2.remote_hosts[2].ip4,
2773 dst=self.pg2.local_ip4) /
2774 UDP(sport=1234, dport=48879) /
2775 VXLAN(vni=101, gpid=441, flags=0x88) /
2776 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2777 IP(src=l['ip'], dst=ep.ip4.address) /
2778 UDP(sport=1234, dport=1234) /
2781 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2784 tep1_sw_if_index = find_vxlan_gbp_tunnel(
2787 self.pg2.remote_hosts[2].ip4,
2789 self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2791 # endpoint learnt via the parent GBP-vxlan interface
2792 self.assertTrue(find_gbp_endpoint(self,
2793 vx_tun_l3._sw_if_index,
2797 # Add a remote endpoint from the API
2799 rep_88 = VppGbpEndpoint(self, vx_tun_l3,
2801 "10.0.0.88", "11.0.0.88",
2802 "2001:10::88", "3001::88",
2803 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
2805 self.pg2.remote_hosts[1].ip4,
2807 rep_88.add_vpp_config()
2810 # Add a remote endpoint from the API that matches an existing one
2812 rep_2 = VppGbpEndpoint(self, vx_tun_l3,
2814 learnt[0]['ip'], "11.0.0.101",
2815 learnt[0]['ip6'], "3001::101",
2816 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
2818 self.pg2.remote_hosts[1].ip4,
2820 rep_2.add_vpp_config()
2823 # Add a route to the learned EP's v4 subnet
2824 # packets should be send on the v4/v6 uu=fwd interface resp.
2826 se_10_1_24 = VppGbpSubnet(
2827 self, rd1, "10.0.1.0", 24,
2828 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT)
2829 se_10_1_24.add_vpp_config()
2831 self.logger.info(self.vapi.cli("show gbp endpoint"))
2833 ips = ["10.0.0.88", learnt[0]['ip']]
2835 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2836 IP(dst=ip, src=ep.ip4.address) /
2837 UDP(sport=1234, dport=1234) /
2840 rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
2843 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2844 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2845 self.assertEqual(rx[UDP].dport, 48879)
2846 # the UDP source port is a random value for hashing
2847 self.assertEqual(rx[VXLAN].gpid, 441)
2848 self.assertEqual(rx[VXLAN].vni, 101)
2849 self.assertTrue(rx[VXLAN].flags.G)
2850 self.assertTrue(rx[VXLAN].flags.Instance)
2851 self.assertTrue(rx[VXLAN].gpflags.A)
2852 self.assertFalse(rx[VXLAN].gpflags.D)
2854 inner = rx[VXLAN].payload
2856 self.assertEqual(inner[Ether].src, routed_src_mac)
2857 self.assertEqual(inner[Ether].dst, routed_dst_mac)
2858 self.assertEqual(inner[IP].src, ep.ip4.address)
2859 self.assertEqual(inner[IP].dst, ip)
2862 # remove the API remote EPs, only API sourced is gone, the DP
2863 # learnt one remains
2865 rep_88.remove_vpp_config()
2866 rep_2.remove_vpp_config()
2868 self.assertTrue(find_gbp_endpoint(self, ip=rep_2.ip4.address))
2870 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2871 IP(src=ep.ip4.address, dst=rep_2.ip4.address) /
2872 UDP(sport=1234, dport=1234) /
2874 rxs = self.send_and_expect(self.pg0, [p], self.pg2)
2876 self.assertFalse(find_gbp_endpoint(self, ip=rep_88.ip4.address))
2878 p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2879 IP(src=ep.ip4.address, dst=rep_88.ip4.address) /
2880 UDP(sport=1234, dport=1234) /
2882 rxs = self.send_and_expect(self.pg0, [p], self.pg4)
2885 # to appease the testcase we cannot have the registered EP still
2886 # present (because it's DP learnt) when the TC ends so wait until
2889 self.wait_for_ep_timeout(ip=rep_88.ip4.address)
2890 self.wait_for_ep_timeout(ip=rep_2.ip4.address)
2893 # shutdown with learnt endpoint present
2895 p = (Ether(src=self.pg2.remote_mac,
2896 dst=self.pg2.local_mac) /
2897 IP(src=self.pg2.remote_hosts[1].ip4,
2898 dst=self.pg2.local_ip4) /
2899 UDP(sport=1234, dport=48879) /
2900 VXLAN(vni=101, gpid=441, flags=0x88) /
2901 Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2902 IP(src=learnt[1]['ip'], dst=ep.ip4.address) /
2903 UDP(sport=1234, dport=1234) /
2906 rx = self.send_and_expect(self.pg2, [p], self.pg0)
2908 # endpoint learnt via the parent GBP-vxlan interface
2909 self.assertTrue(find_gbp_endpoint(self,
2910 vx_tun_l3._sw_if_index,
2915 # remote endpoint becomes local
2917 self.pg2.unconfig_ip4()
2918 self.pg3.unconfig_ip4()
2919 self.pg4.unconfig_ip4()
2921 def test_gbp_redirect(self):
2922 """ GBP Endpoint Redirect """
2924 self.vapi.cli("set logging class gbp level debug")
2926 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
2927 routed_dst_mac = "00:0c:0c:0c:0c:0c"
2928 routed_src_mac = "00:22:bd:f8:19:ff"
2930 learnt = [{'mac': '00:00:11:11:11:02',
2932 'ip6': '2001:10::2'},
2933 {'mac': '00:00:11:11:11:03',
2935 'ip6': '2001:10::3'}]
2940 t4 = VppIpTable(self, 1)
2942 t6 = VppIpTable(self, 1, True)
2945 rd1 = VppGbpRouteDomain(self, 2, 402, t4, t6)
2946 rd1.add_vpp_config()
2948 self.loop0.set_mac(self.router_mac)
2951 # Bind the BVI to the RD
2953 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
2954 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
2957 # Pg7 hosts a BD's UU-fwd
2959 self.pg7.config_ip4()
2960 self.pg7.resolve_arp()
2963 # a GBP bridge domains for the EPs
2965 bd1 = VppBridgeDomain(self, 1)
2966 bd1.add_vpp_config()
2967 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0)
2968 gbd1.add_vpp_config()
2970 bd2 = VppBridgeDomain(self, 2)
2971 bd2.add_vpp_config()
2972 gbd2 = VppGbpBridgeDomain(self, bd2, rd1, self.loop1)
2973 gbd2.add_vpp_config()
2975 # ... and has a /32 and /128 applied
2976 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2977 ip4_addr.add_vpp_config()
2978 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 128)
2979 ip6_addr.add_vpp_config()
2980 ip4_addr = VppIpInterfaceAddress(self, gbd2.bvi, "10.0.1.128", 32)
2981 ip4_addr.add_vpp_config()
2982 ip6_addr = VppIpInterfaceAddress(self, gbd2.bvi, "2001:11::128", 128)
2983 ip6_addr.add_vpp_config()
2986 # The Endpoint-groups in which we are learning endpoints
2988 epg_220 = VppGbpEndpointGroup(self, 220, 440, rd1, gbd1,
2992 VppGbpEndpointRetention(2))
2993 epg_220.add_vpp_config()
2994 epg_221 = VppGbpEndpointGroup(self, 221, 441, rd1, gbd2,
2998 VppGbpEndpointRetention(2))
2999 epg_221.add_vpp_config()
3000 epg_222 = VppGbpEndpointGroup(self, 222, 442, rd1, gbd1,
3004 VppGbpEndpointRetention(2))
3005 epg_222.add_vpp_config()
3008 # a GBP bridge domains for the SEPs
3010 bd_uu1 = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
3011 self.pg7.remote_ip4, 116)
3012 bd_uu1.add_vpp_config()
3013 bd_uu2 = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
3014 self.pg7.remote_ip4, 117)
3015 bd_uu2.add_vpp_config()
3017 bd3 = VppBridgeDomain(self, 3)
3018 bd3.add_vpp_config()
3019 gbd3 = VppGbpBridgeDomain(self, bd3, rd1, self.loop2,
3020 bd_uu1, learn=False)
3021 gbd3.add_vpp_config()
3022 bd4 = VppBridgeDomain(self, 4)
3023 bd4.add_vpp_config()
3024 gbd4 = VppGbpBridgeDomain(self, bd4, rd1, self.loop3,
3025 bd_uu2, learn=False)
3026 gbd4.add_vpp_config()
3029 # EPGs in which the service endpoints exist
3031 epg_320 = VppGbpEndpointGroup(self, 320, 550, rd1, gbd3,
3035 VppGbpEndpointRetention(2))
3036 epg_320.add_vpp_config()
3037 epg_321 = VppGbpEndpointGroup(self, 321, 551, rd1, gbd4,
3041 VppGbpEndpointRetention(2))
3042 epg_321.add_vpp_config()
3045 # three local endpoints
3047 ep1 = VppGbpEndpoint(self, self.pg0,
3049 "10.0.0.1", "11.0.0.1",
3050 "2001:10::1", "3001:10::1")
3051 ep1.add_vpp_config()
3052 ep2 = VppGbpEndpoint(self, self.pg1,
3054 "10.0.1.1", "11.0.1.1",
3055 "2001:11::1", "3001:11::1")
3056 ep2.add_vpp_config()
3057 ep3 = VppGbpEndpoint(self, self.pg2,
3059 "10.0.2.2", "11.0.2.2",
3060 "2001:12::1", "3001:12::1")
3061 ep3.add_vpp_config()
3066 sep1 = VppGbpEndpoint(self, self.pg3,
3068 "12.0.0.1", "13.0.0.1",
3069 "4001:10::1", "5001:10::1")
3070 sep1.add_vpp_config()
3071 sep2 = VppGbpEndpoint(self, self.pg4,
3073 "12.0.0.2", "13.0.0.2",
3074 "4001:10::2", "5001:10::2")
3075 sep2.add_vpp_config()
3076 sep3 = VppGbpEndpoint(self, self.pg5,
3078 "12.0.1.1", "13.0.1.1",
3079 "4001:11::1", "5001:11::1")
3080 sep3.add_vpp_config()
3081 # this EP is not installed immediately
3082 sep4 = VppGbpEndpoint(self, self.pg6,
3084 "12.0.1.2", "13.0.1.2",
3085 "4001:11::2", "5001:11::2")
3088 # an L2 switch packet between local EPs in different EPGs
3089 # different dest ports on each so the are LB hashed differently
3091 p4 = [(Ether(src=ep1.mac, dst=ep3.mac) /
3092 IP(src=ep1.ip4.address, dst=ep3.ip4.address) /
3093 UDP(sport=1234, dport=1234) /
3095 (Ether(src=ep3.mac, dst=ep1.mac) /
3096 IP(src=ep3.ip4.address, dst=ep1.ip4.address) /
3097 UDP(sport=1234, dport=1234) /
3099 p6 = [(Ether(src=ep1.mac, dst=ep3.mac) /
3100 IPv6(src=ep1.ip6.address, dst=ep3.ip6.address) /
3101 UDP(sport=1234, dport=1234) /
3103 (Ether(src=ep3.mac, dst=ep1.mac) /
3104 IPv6(src=ep3.ip6.address, dst=ep1.ip6.address) /
3105 UDP(sport=1234, dport=1230) /
3108 # should be dropped since no contract yet
3109 self.send_and_assert_no_replies(self.pg0, [p4[0]])
3110 self.send_and_assert_no_replies(self.pg0, [p6[0]])
3113 # Add a contract with a rule to load-balance redirect via SEP1 and SEP2
3114 # one of the next-hops is via an EP that is not known
3116 acl = VppGbpAcl(self)
3117 rule4 = acl.create_rule(permit_deny=1, proto=17)
3118 rule6 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
3119 acl_index = acl.add_vpp_config([rule4, rule6])
3122 # test the src-ip hash mode
3124 c1 = VppGbpContract(
3125 self, 402, epg_220.sclass, epg_222.sclass, acl_index,
3126 [VppGbpContractRule(
3127 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3128 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3129 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3130 sep1.ip4, sep1.epg.rd),
3131 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3132 sep2.ip4, sep2.epg.rd)]),
3134 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3135 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3136 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3137 sep3.ip6, sep3.epg.rd),
3138 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3139 sep4.ip6, sep4.epg.rd)])],
3140 [ETH_P_IP, ETH_P_IPV6])
3143 c2 = VppGbpContract(
3144 self, 402, epg_222.sclass, epg_220.sclass, acl_index,
3145 [VppGbpContractRule(
3146 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3147 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3148 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3149 sep1.ip4, sep1.epg.rd),
3150 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3151 sep2.ip4, sep2.epg.rd)]),
3153 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3154 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3155 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3156 sep3.ip6, sep3.epg.rd),
3157 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3158 sep4.ip6, sep4.epg.rd)])],
3159 [ETH_P_IP, ETH_P_IPV6])
3163 # send again with the contract preset, now packets arrive
3164 # at SEP1 or SEP2 depending on the hashing
3166 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3169 self.assertEqual(rx[Ether].src, routed_src_mac)
3170 self.assertEqual(rx[Ether].dst, sep1.mac)
3171 self.assertEqual(rx[IP].src, ep1.ip4.address)
3172 self.assertEqual(rx[IP].dst, ep3.ip4.address)
3174 rxs = self.send_and_expect(self.pg2, p4[1] * 17, sep2.itf)
3177 self.assertEqual(rx[Ether].src, routed_src_mac)
3178 self.assertEqual(rx[Ether].dst, sep2.mac)
3179 self.assertEqual(rx[IP].src, ep3.ip4.address)
3180 self.assertEqual(rx[IP].dst, ep1.ip4.address)
3182 rxs = self.send_and_expect(self.pg0, p6[0] * 17, self.pg7)
3185 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3186 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3187 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3188 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
3189 self.assertEqual(rx[VXLAN].vni, 117)
3190 self.assertTrue(rx[VXLAN].flags.G)
3191 self.assertTrue(rx[VXLAN].flags.Instance)
3192 # redirect policy has been applied
3193 self.assertTrue(rx[VXLAN].gpflags.A)
3194 self.assertFalse(rx[VXLAN].gpflags.D)
3196 inner = rx[VXLAN].payload
3198 self.assertEqual(inner[Ether].src, routed_src_mac)
3199 self.assertEqual(inner[Ether].dst, sep4.mac)
3200 self.assertEqual(inner[IPv6].src, ep1.ip6.address)
3201 self.assertEqual(inner[IPv6].dst, ep3.ip6.address)
3203 rxs = self.send_and_expect(self.pg2, p6[1] * 17, sep3.itf)
3206 self.assertEqual(rx[Ether].src, routed_src_mac)
3207 self.assertEqual(rx[Ether].dst, sep3.mac)
3208 self.assertEqual(rx[IPv6].src, ep3.ip6.address)
3209 self.assertEqual(rx[IPv6].dst, ep1.ip6.address)
3212 # programme the unknown EP
3214 sep4.add_vpp_config()
3216 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep4.itf)
3219 self.assertEqual(rx[Ether].src, routed_src_mac)
3220 self.assertEqual(rx[Ether].dst, sep4.mac)
3221 self.assertEqual(rx[IPv6].src, ep1.ip6.address)
3222 self.assertEqual(rx[IPv6].dst, ep3.ip6.address)
3225 # and revert back to unprogrammed
3227 sep4.remove_vpp_config()
3229 rxs = self.send_and_expect(self.pg0, p6[0] * 17, self.pg7)
3232 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3233 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3234 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3235 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
3236 self.assertEqual(rx[VXLAN].vni, 117)
3237 self.assertTrue(rx[VXLAN].flags.G)
3238 self.assertTrue(rx[VXLAN].flags.Instance)
3239 # redirect policy has been applied
3240 self.assertTrue(rx[VXLAN].gpflags.A)
3241 self.assertFalse(rx[VXLAN].gpflags.D)
3243 inner = rx[VXLAN].payload
3245 self.assertEqual(inner[Ether].src, routed_src_mac)
3246 self.assertEqual(inner[Ether].dst, sep4.mac)
3247 self.assertEqual(inner[IPv6].src, ep1.ip6.address)
3248 self.assertEqual(inner[IPv6].dst, ep3.ip6.address)
3250 c1.remove_vpp_config()
3251 c2.remove_vpp_config()
3254 # test the symmetric hash mode
3256 c1 = VppGbpContract(
3257 self, 402, epg_220.sclass, epg_222.sclass, acl_index,
3258 [VppGbpContractRule(
3259 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3260 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3261 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3262 sep1.ip4, sep1.epg.rd),
3263 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3264 sep2.ip4, sep2.epg.rd)]),
3266 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3267 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3268 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3269 sep3.ip6, sep3.epg.rd),
3270 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3271 sep4.ip6, sep4.epg.rd)])],
3272 [ETH_P_IP, ETH_P_IPV6])
3275 c2 = VppGbpContract(
3276 self, 402, epg_222.sclass, epg_220.sclass, acl_index,
3277 [VppGbpContractRule(
3278 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3279 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3280 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3281 sep1.ip4, sep1.epg.rd),
3282 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3283 sep2.ip4, sep2.epg.rd)]),
3285 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3286 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3287 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3288 sep3.ip6, sep3.epg.rd),
3289 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3290 sep4.ip6, sep4.epg.rd)])],
3291 [ETH_P_IP, ETH_P_IPV6])
3295 # send again with the contract preset, now packets arrive
3296 # at SEP1 for both directions
3298 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3301 self.assertEqual(rx[Ether].src, routed_src_mac)
3302 self.assertEqual(rx[Ether].dst, sep1.mac)
3303 self.assertEqual(rx[IP].src, ep1.ip4.address)
3304 self.assertEqual(rx[IP].dst, ep3.ip4.address)
3306 rxs = self.send_and_expect(self.pg2, p4[1] * 17, sep1.itf)
3309 self.assertEqual(rx[Ether].src, routed_src_mac)
3310 self.assertEqual(rx[Ether].dst, sep1.mac)
3311 self.assertEqual(rx[IP].src, ep3.ip4.address)
3312 self.assertEqual(rx[IP].dst, ep1.ip4.address)
3315 # programme the unknown EP for the L3 tests
3317 sep4.add_vpp_config()
3320 # an L3 switch packet between local EPs in different EPGs
3321 # different dest ports on each so the are LB hashed differently
3323 p4 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3324 IP(src=ep1.ip4.address, dst=ep2.ip4.address) /
3325 UDP(sport=1234, dport=1234) /
3327 (Ether(src=ep2.mac, dst=str(self.router_mac)) /
3328 IP(src=ep2.ip4.address, dst=ep1.ip4.address) /
3329 UDP(sport=1234, dport=1234) /
3331 p6 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3332 IPv6(src=ep1.ip6.address, dst=ep2.ip6.address) /
3333 UDP(sport=1234, dport=1234) /
3335 (Ether(src=ep2.mac, dst=str(self.router_mac)) /
3336 IPv6(src=ep2.ip6.address, dst=ep1.ip6.address) /
3337 UDP(sport=1234, dport=1234) /
3340 c3 = VppGbpContract(
3341 self, 402, epg_220.sclass, epg_221.sclass, acl_index,
3342 [VppGbpContractRule(
3343 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3344 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3345 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3346 sep1.ip4, sep1.epg.rd),
3347 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3348 sep2.ip4, sep2.epg.rd)]),
3350 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3351 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3352 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3353 sep3.ip6, sep3.epg.rd),
3354 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3355 sep4.ip6, sep4.epg.rd)])],
3356 [ETH_P_IP, ETH_P_IPV6])
3359 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3362 self.assertEqual(rx[Ether].src, routed_src_mac)
3363 self.assertEqual(rx[Ether].dst, sep1.mac)
3364 self.assertEqual(rx[IP].src, ep1.ip4.address)
3365 self.assertEqual(rx[IP].dst, ep2.ip4.address)
3368 # learn a remote EP in EPG 221
3370 vx_tun_l3 = VppGbpVxlanTunnel(
3371 self, 444, rd1.rd_id,
3372 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
3374 vx_tun_l3.add_vpp_config()
3376 c4 = VppGbpContract(
3377 self, 402, epg_221.sclass, epg_220.sclass, acl_index,
3378 [VppGbpContractRule(
3379 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3380 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3383 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3384 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3386 [ETH_P_IP, ETH_P_IPV6])
3389 p = (Ether(src=self.pg7.remote_mac,
3390 dst=self.pg7.local_mac) /
3391 IP(src=self.pg7.remote_ip4,
3392 dst=self.pg7.local_ip4) /
3393 UDP(sport=1234, dport=48879) /
3394 VXLAN(vni=444, gpid=441, flags=0x88) /
3395 Ether(src="00:22:22:22:22:33", dst=str(self.router_mac)) /
3396 IP(src="10.0.0.88", dst=ep1.ip4.address) /
3397 UDP(sport=1234, dport=1234) /
3400 rx = self.send_and_expect(self.pg7, [p], self.pg0)
3402 # endpoint learnt via the parent GBP-vxlan interface
3403 self.assertTrue(find_gbp_endpoint(self,
3404 vx_tun_l3._sw_if_index,
3407 p = (Ether(src=self.pg7.remote_mac,
3408 dst=self.pg7.local_mac) /
3409 IP(src=self.pg7.remote_ip4,
3410 dst=self.pg7.local_ip4) /
3411 UDP(sport=1234, dport=48879) /
3412 VXLAN(vni=444, gpid=441, flags=0x88) /
3413 Ether(src="00:22:22:22:22:33", dst=str(self.router_mac)) /
3414 IPv6(src="2001:10::88", dst=ep1.ip6.address) /
3415 UDP(sport=1234, dport=1234) /
3418 rx = self.send_and_expect(self.pg7, [p], self.pg0)
3420 # endpoint learnt via the parent GBP-vxlan interface
3421 self.assertTrue(find_gbp_endpoint(self,
3422 vx_tun_l3._sw_if_index,
3426 # L3 switch from local to remote EP
3428 p4 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3429 IP(src=ep1.ip4.address, dst="10.0.0.88") /
3430 UDP(sport=1234, dport=1234) /
3432 p6 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3433 IPv6(src=ep1.ip6.address, dst="2001:10::88") /
3434 UDP(sport=1234, dport=1234) /
3437 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3440 self.assertEqual(rx[Ether].src, routed_src_mac)
3441 self.assertEqual(rx[Ether].dst, sep1.mac)
3442 self.assertEqual(rx[IP].src, ep1.ip4.address)
3443 self.assertEqual(rx[IP].dst, "10.0.0.88")
3445 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep4.itf)
3448 self.assertEqual(rx[Ether].src, routed_src_mac)
3449 self.assertEqual(rx[Ether].dst, sep4.mac)
3450 self.assertEqual(rx[IPv6].src, ep1.ip6.address)
3451 self.assertEqual(rx[IPv6].dst, "2001:10::88")
3454 # test the dst-ip hash mode
3456 c5 = VppGbpContract(
3457 self, 402, epg_220.sclass, epg_221.sclass, acl_index,
3458 [VppGbpContractRule(
3459 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3460 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
3461 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3462 sep1.ip4, sep1.epg.rd),
3463 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3464 sep2.ip4, sep2.epg.rd)]),
3466 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3467 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
3468 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3469 sep3.ip6, sep3.epg.rd),
3470 VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3471 sep4.ip6, sep4.epg.rd)])],
3472 [ETH_P_IP, ETH_P_IPV6])
3475 rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3478 self.assertEqual(rx[Ether].src, routed_src_mac)
3479 self.assertEqual(rx[Ether].dst, sep1.mac)
3480 self.assertEqual(rx[IP].src, ep1.ip4.address)
3481 self.assertEqual(rx[IP].dst, "10.0.0.88")
3483 rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep3.itf)
3486 self.assertEqual(rx[Ether].src, routed_src_mac)
3487 self.assertEqual(rx[Ether].dst, sep3.mac)
3488 self.assertEqual(rx[IPv6].src, ep1.ip6.address)
3489 self.assertEqual(rx[IPv6].dst, "2001:10::88")
3494 self.pg7.unconfig_ip4()
3496 def test_gbp_l3_out(self):
3499 ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
3500 self.vapi.cli("set logging class gbp level debug")
3502 routed_dst_mac = "00:0c:0c:0c:0c:0c"
3503 routed_src_mac = "00:22:bd:f8:19:ff"
3508 t4 = VppIpTable(self, 1)
3510 t6 = VppIpTable(self, 1, True)
3513 rd1 = VppGbpRouteDomain(self, 2, 55, t4, t6)
3514 rd1.add_vpp_config()
3516 self.loop0.set_mac(self.router_mac)
3519 # Bind the BVI to the RD
3521 VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
3522 VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
3525 # Pg7 hosts a BD's BUM
3526 # Pg1 some other l3 interface
3528 self.pg7.config_ip4()
3529 self.pg7.resolve_arp()
3532 # a multicast vxlan-gbp tunnel for broadcast in the BD
3534 tun_bm = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
3537 tun_bm.add_vpp_config()
3540 # a GBP external bridge domains for the EPs
3542 bd1 = VppBridgeDomain(self, 1)
3543 bd1.add_vpp_config()
3544 gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0, None, tun_bm)
3545 gbd1.add_vpp_config()
3548 # The Endpoint-groups in which the external endpoints exist
3550 epg_220 = VppGbpEndpointGroup(self, 220, 113, rd1, gbd1,
3554 VppGbpEndpointRetention(2))
3555 epg_220.add_vpp_config()
3557 # the BVIs have the subnets applied ...
3558 ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 24)
3559 ip4_addr.add_vpp_config()
3560 ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 64)
3561 ip6_addr.add_vpp_config()
3563 # ... which are L3-out subnets
3564 l3o_1 = VppGbpSubnet(
3565 self, rd1, "10.0.0.0", 24,
3566 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3568 l3o_1.add_vpp_config()
3571 # an external interface attached to the outside world and the
3574 vlan_100 = VppDot1QSubint(self, self.pg0, 100)
3576 VppL2Vtr(self, vlan_100, L2_VTR_OP.L2_POP_1).add_vpp_config()
3577 vlan_101 = VppDot1QSubint(self, self.pg0, 101)
3579 VppL2Vtr(self, vlan_101, L2_VTR_OP.L2_POP_1).add_vpp_config()
3580 # vlan_102 is not poped
3581 vlan_102 = VppDot1QSubint(self, self.pg0, 102)
3584 ext_itf = VppGbpExtItf(self, self.loop0, bd1, rd1)
3585 ext_itf.add_vpp_config()
3588 # an unicast vxlan-gbp for inter-RD traffic
3590 vx_tun_l3 = VppGbpVxlanTunnel(
3591 self, 444, rd1.rd_id,
3592 VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
3594 vx_tun_l3.add_vpp_config()
3597 # External Endpoints
3599 eep1 = VppGbpEndpoint(self, vlan_100,
3601 "10.0.0.1", "11.0.0.1",
3602 "2001:10::1", "3001::1",
3603 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
3604 eep1.add_vpp_config()
3605 eep2 = VppGbpEndpoint(self, vlan_101,
3607 "10.0.0.2", "11.0.0.2",
3608 "2001:10::2", "3001::2",
3609 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
3610 eep2.add_vpp_config()
3611 eep3 = VppGbpEndpoint(self, vlan_102,
3613 "10.0.0.3", "11.0.0.3",
3614 "2001:10::3", "3001::3",
3615 ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
3616 eep3.add_vpp_config()
3619 # A remote external endpoint
3621 rep = VppGbpEndpoint(self, vx_tun_l3,
3623 "10.0.0.101", "11.0.0.101",
3624 "2001:10::101", "3001::101",
3625 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
3627 self.pg7.remote_ip4,
3629 rep.add_vpp_config()
3632 # EP1 impersonating EP3 is dropped
3634 p = (Ether(src=eep1.mac, dst="ff:ff:ff:ff:ff:ff") /
3637 psrc="10.0.0.3", pdst="10.0.0.128",
3638 hwsrc=eep1.mac, hwdst="ff:ff:ff:ff:ff:ff"))
3639 self.send_and_assert_no_replies(self.pg0, p)
3642 # ARP packet from External EPs are accepted and replied to
3644 p_arp = (Ether(src=eep1.mac, dst="ff:ff:ff:ff:ff:ff") /
3647 psrc=eep1.ip4.address, pdst="10.0.0.128",
3648 hwsrc=eep1.mac, hwdst="ff:ff:ff:ff:ff:ff"))
3649 rxs = self.send_and_expect(self.pg0, p_arp * 1, self.pg0)
3652 # ARP packet from host in remote subnet are accepted and replied to
3654 p_arp = (Ether(src=eep3.mac, dst="ff:ff:ff:ff:ff:ff") /
3657 psrc=eep3.ip4.address, pdst="10.0.0.128",
3658 hwsrc=eep3.mac, hwdst="ff:ff:ff:ff:ff:ff"))
3659 rxs = self.send_and_expect(self.pg0, p_arp * 1, self.pg0)
3662 # packets destined to unknown addresses in the BVI's subnet
3665 p4 = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3667 IP(src="10.0.0.1", dst="10.0.0.88") /
3668 UDP(sport=1234, dport=1234) /
3670 p6 = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3672 IPv6(src="2001:10::1", dst="2001:10::88") /
3673 UDP(sport=1234, dport=1234) /
3676 rxs = self.send_and_expect(self.pg0, p4 * 1, self.pg7)
3679 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3680 # self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3681 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3682 self.assertEqual(rx[IP].dst, "239.1.1.1")
3683 self.assertEqual(rx[VXLAN].vni, 88)
3684 self.assertTrue(rx[VXLAN].flags.G)
3685 self.assertTrue(rx[VXLAN].flags.Instance)
3686 # policy was applied to the original IP packet
3687 self.assertEqual(rx[VXLAN].gpid, 113)
3688 self.assertTrue(rx[VXLAN].gpflags.A)
3689 self.assertFalse(rx[VXLAN].gpflags.D)
3691 inner = rx[VXLAN].payload
3693 self.assertTrue(inner.haslayer(ARP))
3696 # remote to external
3698 p = (Ether(src=self.pg7.remote_mac,
3699 dst=self.pg7.local_mac) /
3700 IP(src=self.pg7.remote_ip4,
3701 dst=self.pg7.local_ip4) /
3702 UDP(sport=1234, dport=48879) /
3703 VXLAN(vni=444, gpid=113, flags=0x88) /
3704 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
3705 IP(src="10.0.0.101", dst="10.0.0.1") /
3706 UDP(sport=1234, dport=1234) /
3709 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
3712 # local EP pings router
3714 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3716 IP(src=eep1.ip4.address, dst="10.0.0.128") /
3717 ICMP(type='echo-request'))
3719 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
3722 self.assertEqual(rx[Ether].src, str(self.router_mac))
3723 self.assertEqual(rx[Ether].dst, eep1.mac)
3724 self.assertEqual(rx[Dot1Q].vlan, 100)
3727 # local EP pings other local EP
3729 p = (Ether(src=eep1.mac, dst=eep2.mac) /
3731 IP(src=eep1.ip4.address, dst=eep2.ip4.address) /
3732 ICMP(type='echo-request'))
3734 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
3737 self.assertEqual(rx[Ether].src, eep1.mac)
3738 self.assertEqual(rx[Ether].dst, eep2.mac)
3739 self.assertEqual(rx[Dot1Q].vlan, 101)
3742 # local EP pings router w/o vlan tag poped
3744 p = (Ether(src=eep3.mac, dst=str(self.router_mac)) /
3746 IP(src=eep3.ip4.address, dst="10.0.0.128") /
3747 ICMP(type='echo-request'))
3749 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
3752 self.assertEqual(rx[Ether].src, str(self.router_mac))
3753 self.assertEqual(rx[Ether].dst, vlan_102.remote_mac)
3756 # A subnet reachable through the external EP1
3758 ip_220 = VppIpRoute(self, "10.220.0.0", 24,
3759 [VppRoutePath(eep1.ip4.address,
3760 eep1.epg.bvi.sw_if_index)],
3761 table_id=t4.table_id)
3762 ip_220.add_vpp_config()
3764 l3o_220 = VppGbpSubnet(
3765 self, rd1, "10.220.0.0", 24,
3766 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3768 l3o_220.add_vpp_config()
3771 # A subnet reachable through the external EP2
3773 ip_221 = VppIpRoute(self, "10.221.0.0", 24,
3774 [VppRoutePath(eep2.ip4.address,
3775 eep2.epg.bvi.sw_if_index)],
3776 table_id=t4.table_id)
3777 ip_221.add_vpp_config()
3779 l3o_221 = VppGbpSubnet(
3780 self, rd1, "10.221.0.0", 24,
3781 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3783 l3o_221.add_vpp_config()
3786 # ping between hosts in remote subnets
3787 # dropped without a contract
3789 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3791 IP(src="10.220.0.1", dst="10.221.0.1") /
3792 ICMP(type='echo-request'))
3794 self.send_and_assert_no_replies(self.pg0, p * 1)
3797 # contract for the external nets to communicate
3799 acl = VppGbpAcl(self)
3800 rule4 = acl.create_rule(permit_deny=1, proto=17)
3801 rule6 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
3802 acl_index = acl.add_vpp_config([rule4, rule6])
3805 # A contract with the wrong scope is not matched
3807 c_44 = VppGbpContract(
3808 self, 44, 4220, 4221, acl_index,
3809 [VppGbpContractRule(
3810 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3813 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3815 [ETH_P_IP, ETH_P_IPV6])
3816 c_44.add_vpp_config()
3817 self.send_and_assert_no_replies(self.pg0, p * 1)
3819 c1 = VppGbpContract(
3820 self, 55, 4220, 4221, acl_index,
3821 [VppGbpContractRule(
3822 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3823 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3826 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3827 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3829 [ETH_P_IP, ETH_P_IPV6])
3833 # Contracts allowing ext-net 200 to talk with external EPs
3835 c2 = VppGbpContract(
3836 self, 55, 4220, 113, acl_index,
3837 [VppGbpContractRule(
3838 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3839 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3842 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3843 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3845 [ETH_P_IP, ETH_P_IPV6])
3847 c3 = VppGbpContract(
3848 self, 55, 113, 4220, acl_index,
3849 [VppGbpContractRule(
3850 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3851 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3854 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3855 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3857 [ETH_P_IP, ETH_P_IPV6])
3861 # ping between hosts in remote subnets
3863 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3865 IP(src="10.220.0.1", dst="10.221.0.1") /
3866 UDP(sport=1234, dport=1234) /
3869 rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
3872 self.assertEqual(rx[Ether].src, str(self.router_mac))
3873 self.assertEqual(rx[Ether].dst, eep2.mac)
3874 self.assertEqual(rx[Dot1Q].vlan, 101)
3876 # we did not learn these external hosts
3877 self.assertFalse(find_gbp_endpoint(self, ip="10.220.0.1"))
3878 self.assertFalse(find_gbp_endpoint(self, ip="10.221.0.1"))
3881 # from remote external EP to local external EP
3883 p = (Ether(src=self.pg7.remote_mac,
3884 dst=self.pg7.local_mac) /
3885 IP(src=self.pg7.remote_ip4,
3886 dst=self.pg7.local_ip4) /
3887 UDP(sport=1234, dport=48879) /
3888 VXLAN(vni=444, gpid=113, flags=0x88) /
3889 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
3890 IP(src="10.0.0.101", dst="10.220.0.1") /
3891 UDP(sport=1234, dport=1234) /
3894 rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
3897 # ping from an external host to the remote external EP
3899 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3901 IP(src="10.220.0.1", dst=rep.ip4.address) /
3902 UDP(sport=1234, dport=1234) /
3905 rxs = self.send_and_expect(self.pg0, p * 1, self.pg7)
3908 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3909 # self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3910 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3911 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
3912 self.assertEqual(rx[VXLAN].vni, 444)
3913 self.assertTrue(rx[VXLAN].flags.G)
3914 self.assertTrue(rx[VXLAN].flags.Instance)
3915 # the sclass of the ext-net the packet came from
3916 self.assertEqual(rx[VXLAN].gpid, 4220)
3917 # policy was applied to the original IP packet
3918 self.assertTrue(rx[VXLAN].gpflags.A)
3919 # since it's an external host the reciever should not learn it
3920 self.assertTrue(rx[VXLAN].gpflags.D)
3921 inner = rx[VXLAN].payload
3922 self.assertEqual(inner[IP].src, "10.220.0.1")
3923 self.assertEqual(inner[IP].dst, rep.ip4.address)
3926 # An external subnet reachable via the remote external EP
3930 # first the VXLAN-GBP tunnel over which it is reached
3932 vx_tun_r = VppVxlanGbpTunnel(
3933 self, self.pg7.local_ip4,
3934 self.pg7.remote_ip4, 445,
3935 mode=(VppEnum.vl_api_vxlan_gbp_api_tunnel_mode_t.
3936 VXLAN_GBP_API_TUNNEL_MODE_L3))
3937 vx_tun_r.add_vpp_config()
3938 VppIpInterfaceBind(self, vx_tun_r, t4).add_vpp_config()
3940 self.logger.info(self.vapi.cli("sh vxlan-gbp tunnel"))
3943 # then the special adj to resolve through on that tunnel
3945 n1 = VppNeighbor(self,
3946 vx_tun_r.sw_if_index,
3947 "00:0c:0c:0c:0c:0c",
3948 self.pg7.remote_ip4)
3952 # the route via the adj above
3954 ip_222 = VppIpRoute(self, "10.222.0.0", 24,
3955 [VppRoutePath(self.pg7.remote_ip4,
3956 vx_tun_r.sw_if_index)],
3957 table_id=t4.table_id)
3958 ip_222.add_vpp_config()
3960 l3o_222 = VppGbpSubnet(
3961 self, rd1, "10.222.0.0", 24,
3962 VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3964 l3o_222.add_vpp_config()
3967 # ping between hosts in local and remote external subnets
3968 # dropped without a contract
3970 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3972 IP(src="10.220.0.1", dst="10.222.0.1") /
3973 UDP(sport=1234, dport=1234) /
3976 rxs = self.send_and_assert_no_replies(self.pg0, p * 1)
3979 # Add contracts ext-nets for 220 -> 222
3981 c4 = VppGbpContract(
3982 self, 55, 4220, 4222, acl_index,
3983 [VppGbpContractRule(
3984 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3985 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3988 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3989 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3991 [ETH_P_IP, ETH_P_IPV6])
3995 # ping from host in local to remote external subnets
3997 p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3999 IP(src="10.220.0.1", dst="10.222.0.1") /
4000 UDP(sport=1234, dport=1234) /
4003 rxs = self.send_and_expect(self.pg0, p * 3, self.pg7)
4006 self.assertEqual(rx[Ether].src, self.pg7.local_mac)
4007 self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
4008 self.assertEqual(rx[IP].src, self.pg7.local_ip4)
4009 self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
4010 self.assertEqual(rx[VXLAN].vni, 445)
4011 self.assertTrue(rx[VXLAN].flags.G)
4012 self.assertTrue(rx[VXLAN].flags.Instance)
4013 # the sclass of the ext-net the packet came from
4014 self.assertEqual(rx[VXLAN].gpid, 4220)
4015 # policy was applied to the original IP packet
4016 self.assertTrue(rx[VXLAN].gpflags.A)
4017 # since it's an external host the reciever should not learn it
4018 self.assertTrue(rx[VXLAN].gpflags.D)
4019 inner = rx[VXLAN].payload
4020 self.assertEqual(inner[Ether].dst, "00:0c:0c:0c:0c:0c")
4021 self.assertEqual(inner[IP].src, "10.220.0.1")
4022 self.assertEqual(inner[IP].dst, "10.222.0.1")
4025 # ping from host in remote to local external subnets
4026 # there's no contract for this, but the A bit is set.
4028 p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
4029 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
4030 UDP(sport=1234, dport=48879) /
4031 VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
4032 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
4033 IP(src="10.222.0.1", dst="10.220.0.1") /
4034 UDP(sport=1234, dport=1234) /
4037 rxs = self.send_and_expect(self.pg7, p * 3, self.pg0)
4038 self.assertFalse(find_gbp_endpoint(self, ip="10.222.0.1"))
4041 # ping from host in remote to remote external subnets
4042 # this is dropped by reflection check.
4044 p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
4045 IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
4046 UDP(sport=1234, dport=48879) /
4047 VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
4048 Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
4049 IP(src="10.222.0.1", dst="10.222.0.2") /
4050 UDP(sport=1234, dport=1234) /
4053 rxs = self.send_and_assert_no_replies(self.pg7, p * 3)
4058 self.pg7.unconfig_ip4()
4059 vlan_100.set_vtr(L2_VTR_OP.L2_DISABLED)
4062 if __name__ == '__main__':
4063 unittest.main(testRunner=VppTestRunner)