5 from framework import VppTestCase, VppTestRunner
6 from vpp_object import VppObject
7 from vpp_neighbor import VppNeighbor
8 from vpp_ip_route import VppIpRoute, VppRoutePath, VppIpTable
13 from scapy.packet import Raw
14 from scapy.layers.l2 import Ether, ARP
15 from scapy.layers.inet import IP, UDP
16 from scapy.layers.inet6 import IPv6, ICMPv6ND_NS, ICMPv6NDOptSrcLLAddr, \
18 from scapy.utils6 import in6_getnsma, in6_getnsmac
20 from socket import AF_INET, AF_INET6
21 from scapy.utils import inet_pton, inet_ntop
22 from util import mactobinary
25 def find_gbp_endpoint(test, sw_if_index, ip=None, mac=None):
26 vip = VppIpAddress(ip)
28 eps = test.vapi.gbp_endpoint_dump()
30 if ep.endpoint.sw_if_index != sw_if_index:
32 for eip in ep.endpoint.ips:
38 class VppGbpEndpoint(VppObject):
45 return mactobinary(self.itf.remote_mac)
49 return self.itf.remote_mac
69 return [self.ip4, self.ip6]
73 return [self.fip4, self.fip6]
75 def __init__(self, test, itf, epg, recirc, ip4, fip4, ip6, fip6):
81 self._ip4 = VppIpAddress(ip4)
82 self._fip4 = VppIpAddress(fip4)
83 self._ip6 = VppIpAddress(ip6)
84 self._fip6 = VppIpAddress(fip6)
86 self.vmac = VppMacAddress(self.itf.remote_mac)
88 def add_vpp_config(self):
89 res = self._test.vapi.gbp_endpoint_add(
91 [self.ip4.encode(), self.ip6.encode()],
94 self.handle = res.handle
95 self._test.registry.register(self, self._test.logger)
97 def remove_vpp_config(self):
98 self._test.vapi.gbp_endpoint_del(self.handle)
101 return self.object_id()
104 return "gbp-endpoint;[%d:%s:%d]" % (self.itf.sw_if_index,
108 def query_vpp_config(self):
109 return find_gbp_endpoint(self._test,
110 self.itf.sw_if_index,
114 class VppGbpRecirc(VppObject):
116 GBP Recirculation Interface
119 def __init__(self, test, epg, recirc, is_ext=False):
125 def add_vpp_config(self):
126 self._test.vapi.gbp_recirc_add_del(
128 self.recirc.sw_if_index,
131 self._test.registry.register(self, self._test.logger)
133 def remove_vpp_config(self):
134 self._test.vapi.gbp_recirc_add_del(
136 self.recirc.sw_if_index,
141 return self.object_id()
144 return "gbp-recirc;[%d]" % (self.recirc.sw_if_index)
146 def query_vpp_config(self):
147 rs = self._test.vapi.gbp_recirc_dump()
149 if r.recirc.sw_if_index == self.recirc.sw_if_index:
154 class VppGbpSubnet(VppObject):
159 def __init__(self, test, table_id, address, address_len,
161 sw_if_index=None, epg=None):
163 self.table_id = table_id
164 self.prefix = VppIpPrefix(address, address_len)
165 self.is_internal = is_internal
166 self.sw_if_index = sw_if_index
169 def add_vpp_config(self):
170 self._test.vapi.gbp_subnet_add_del(
174 self.prefix.encode(),
175 sw_if_index=self.sw_if_index if self.sw_if_index else 0xffffffff,
176 epg_id=self.epg if self.epg else 0xffff)
177 self._test.registry.register(self, self._test.logger)
179 def remove_vpp_config(self):
180 self._test.vapi.gbp_subnet_add_del(
184 self.prefix.encode())
187 return self.object_id()
190 return "gbp-subnet;[%d-%s]" % (self.table_id,
193 def query_vpp_config(self):
194 ss = self._test.vapi.gbp_subnet_dump()
196 if s.subnet.table_id == self.table_id and \
197 s.subnet.prefix == self.prefix:
202 class VppGbpEndpointGroup(VppObject):
207 def __init__(self, test, epg, rd, bd, uplink,
208 bvi, bvi_ip4, bvi_ip6=None):
212 self.bvi_ip4 = bvi_ip4
213 self.bvi_ip4_n = inet_pton(AF_INET, bvi_ip4)
214 self.bvi_ip6 = bvi_ip6
215 self.bvi_ip6_n = inet_pton(AF_INET6, bvi_ip6)
220 def add_vpp_config(self):
221 self._test.vapi.gbp_endpoint_group_add_del(
227 self.uplink.sw_if_index)
228 self._test.registry.register(self, self._test.logger)
230 def remove_vpp_config(self):
231 self._test.vapi.gbp_endpoint_group_add_del(
237 self.uplink.sw_if_index)
240 return self.object_id()
243 return "gbp-endpoint-group;[%d]" % (self.epg)
245 def query_vpp_config(self):
246 epgs = self._test.vapi.gbp_endpoint_group_dump()
248 if epg.epg.epg_id == self.epg:
253 class VppGbpContract(VppObject):
258 def __init__(self, test, src_epg, dst_epg, acl_index):
260 self.acl_index = acl_index
261 self.src_epg = src_epg
262 self.dst_epg = dst_epg
264 def add_vpp_config(self):
265 self._test.vapi.gbp_contract_add_del(
270 self._test.registry.register(self, self._test.logger)
272 def remove_vpp_config(self):
273 self._test.vapi.gbp_contract_add_del(
280 return self.object_id()
283 return "gbp-contract;[%d:%s:%d]" % (self.src_epg,
287 def query_vpp_config(self):
288 cs = self._test.vapi.gbp_contract_dump()
290 if c.contract.src_epg == self.src_epg \
291 and c.contract.dst_epg == self.dst_epg:
296 class VppGbpAcl(VppObject):
301 def __init__(self, test):
303 self.acl_index = 4294967295
305 def create_rule(self, is_ipv6=0, permit_deny=0, proto=-1,
306 s_prefix=0, s_ip='\x00\x00\x00\x00', sport_from=0,
307 sport_to=65535, d_prefix=0, d_ip='\x00\x00\x00\x00',
308 dport_from=0, dport_to=65535):
309 if proto == -1 or proto == 0:
312 elif proto == 1 or proto == 58:
315 rule = ({'is_permit': permit_deny, 'is_ipv6': is_ipv6, 'proto': proto,
316 'srcport_or_icmptype_first': sport_from,
317 'srcport_or_icmptype_last': sport_to,
318 'src_ip_prefix_len': s_prefix,
320 'dstport_or_icmpcode_first': dport_from,
321 'dstport_or_icmpcode_last': dport_to,
322 'dst_ip_prefix_len': d_prefix,
323 'dst_ip_addr': d_ip})
326 def add_vpp_config(self, rules):
328 reply = self._test.vapi.acl_add_replace(self.acl_index,
331 self.acl_index = reply.acl_index
332 return self.acl_index
334 def remove_vpp_config(self):
335 self._test.vapi.acl_del(self.acl_index)
338 return self.object_id()
341 return "gbp-acl;[%d]" % (self.acl_index)
343 def query_vpp_config(self):
344 cs = self._test.vapi.acl_dump()
346 if c.acl_index == self.acl_index:
351 class TestGBP(VppTestCase):
352 """ GBP Test Case """
355 super(TestGBP, self).setUp()
357 self.create_pg_interfaces(range(9))
358 self.create_loopback_interfaces(9)
360 self.router_mac = "00:11:22:33:44:55"
362 for i in self.pg_interfaces:
364 for i in self.lo_interfaces:
366 self.vapi.sw_interface_set_mac_address(
368 mactobinary(self.router_mac))
371 for i in self.pg_interfaces:
374 super(TestGBP, self).tearDown()
376 def send_and_expect_bridged(self, src, tx, dst):
377 rx = self.send_and_expect(src, tx, dst)
380 self.assertEqual(r[Ether].src, tx[0][Ether].src)
381 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
382 self.assertEqual(r[IP].src, tx[0][IP].src)
383 self.assertEqual(r[IP].dst, tx[0][IP].dst)
386 def send_and_expect_bridged6(self, src, tx, dst):
387 rx = self.send_and_expect(src, tx, dst)
390 self.assertEqual(r[Ether].src, tx[0][Ether].src)
391 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
392 self.assertEqual(r[IPv6].src, tx[0][IPv6].src)
393 self.assertEqual(r[IPv6].dst, tx[0][IPv6].dst)
396 def send_and_expect_routed(self, src, tx, dst, src_mac):
397 rx = self.send_and_expect(src, tx, dst)
400 self.assertEqual(r[Ether].src, src_mac)
401 self.assertEqual(r[Ether].dst, dst.remote_mac)
402 self.assertEqual(r[IP].src, tx[0][IP].src)
403 self.assertEqual(r[IP].dst, tx[0][IP].dst)
406 def send_and_expect_natted(self, src, tx, dst, src_ip):
407 rx = self.send_and_expect(src, tx, dst)
410 self.assertEqual(r[Ether].src, tx[0][Ether].src)
411 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
412 self.assertEqual(r[IP].src, src_ip)
413 self.assertEqual(r[IP].dst, tx[0][IP].dst)
416 def send_and_expect_natted6(self, src, tx, dst, src_ip):
417 rx = self.send_and_expect(src, tx, dst)
420 self.assertEqual(r[Ether].src, tx[0][Ether].src)
421 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
422 self.assertEqual(r[IPv6].src, src_ip)
423 self.assertEqual(r[IPv6].dst, tx[0][IPv6].dst)
426 def send_and_expect_unnatted(self, src, tx, dst, dst_ip):
427 rx = self.send_and_expect(src, tx, dst)
430 self.assertEqual(r[Ether].src, tx[0][Ether].src)
431 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
432 self.assertEqual(r[IP].dst, dst_ip)
433 self.assertEqual(r[IP].src, tx[0][IP].src)
436 def send_and_expect_unnatted6(self, src, tx, dst, dst_ip):
437 rx = self.send_and_expect(src, tx, dst)
440 self.assertEqual(r[Ether].src, tx[0][Ether].src)
441 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
442 self.assertEqual(r[IPv6].dst, dst_ip)
443 self.assertEqual(r[IPv6].src, tx[0][IPv6].src)
446 def send_and_expect_double_natted(self, src, tx, dst, src_ip, dst_ip):
447 rx = self.send_and_expect(src, tx, dst)
450 self.assertEqual(r[Ether].src, self.router_mac)
451 self.assertEqual(r[Ether].dst, dst.remote_mac)
452 self.assertEqual(r[IP].dst, dst_ip)
453 self.assertEqual(r[IP].src, src_ip)
456 def send_and_expect_double_natted6(self, src, tx, dst, src_ip, dst_ip):
457 rx = self.send_and_expect(src, tx, dst)
460 self.assertEqual(r[Ether].src, self.router_mac)
461 self.assertEqual(r[Ether].dst, dst.remote_mac)
462 self.assertEqual(r[IPv6].dst, dst_ip)
463 self.assertEqual(r[IPv6].src, src_ip)
467 """ Group Based Policy """
469 nat_table = VppIpTable(self, 20)
470 nat_table.add_vpp_config()
471 nat_table = VppIpTable(self, 20, is_ip6=True)
472 nat_table.add_vpp_config()
477 self.vapi.bridge_domain_add_del(1, flood=1, uu_flood=1, forward=1,
478 learn=0, arp_term=1, is_add=1)
479 self.vapi.bridge_domain_add_del(2, flood=1, uu_flood=1, forward=1,
480 learn=0, arp_term=1, is_add=1)
481 self.vapi.bridge_domain_add_del(20, flood=1, uu_flood=1, forward=1,
482 learn=0, arp_term=1, is_add=1)
485 # 3 EPGs, 2 of which share a BD.
486 # 2 NAT EPGs, one for floating-IP subnets, the other for internet
488 epgs = [VppGbpEndpointGroup(self, 220, 0, 1, self.pg4,
492 VppGbpEndpointGroup(self, 221, 0, 1, self.pg5,
496 VppGbpEndpointGroup(self, 222, 0, 2, self.pg6,
500 VppGbpEndpointGroup(self, 333, 20, 20, self.pg7,
504 VppGbpEndpointGroup(self, 444, 20, 20, self.pg8,
508 recircs = [VppGbpRecirc(self, epgs[0],
510 VppGbpRecirc(self, epgs[1],
512 VppGbpRecirc(self, epgs[2],
514 VppGbpRecirc(self, epgs[3],
515 self.loop6, is_ext=True),
516 VppGbpRecirc(self, epgs[4],
517 self.loop8, is_ext=True)]
520 recirc_nat = recircs[3]
523 # 4 end-points, 2 in the same subnet, 3 in the same BD
525 eps = [VppGbpEndpoint(self, self.pg0,
527 "10.0.0.1", "11.0.0.1",
528 "2001:10::1", "3001::1"),
529 VppGbpEndpoint(self, self.pg1,
531 "10.0.0.2", "11.0.0.2",
532 "2001:10::2", "3001::2"),
533 VppGbpEndpoint(self, self.pg2,
535 "10.0.1.1", "11.0.0.3",
536 "2001:10:1::1", "3001::3"),
537 VppGbpEndpoint(self, self.pg3,
539 "10.0.2.1", "11.0.0.4",
540 "2001:10:2::1", "3001::4")]
543 # Config related to each of the EPGs
546 # IP config on the BVI interfaces
547 if epg != epgs[1] and epg != epgs[4]:
548 epg.bvi.set_table_ip4(epg.rd)
549 epg.bvi.set_table_ip6(epg.rd)
551 # The BVIs are NAT inside interfaces
552 self.vapi.nat44_interface_add_del_feature(epg.bvi.sw_if_index,
555 self.vapi.nat66_add_del_interface(epg.bvi.sw_if_index,
559 self.vapi.sw_interface_add_del_address(epg.bvi.sw_if_index,
562 self.vapi.sw_interface_add_del_address(epg.bvi.sw_if_index,
567 # EPG uplink interfaces in the BD
568 epg.uplink.set_table_ip4(epg.rd)
569 epg.uplink.set_table_ip6(epg.rd)
570 self.vapi.sw_interface_set_l2_bridge(epg.uplink.sw_if_index,
573 # add the BD ARP termination entry for BVI IP
574 self.vapi.bd_ip_mac_add_del(bd_id=epg.bd,
575 mac=mactobinary(self.router_mac),
579 self.vapi.bd_ip_mac_add_del(bd_id=epg.bd,
580 mac=mactobinary(self.router_mac),
585 # epg[1] shares the same BVI to epg[0]
586 if epg != epgs[1] and epg != epgs[4]:
588 self.vapi.sw_interface_set_l2_bridge(epg.bvi.sw_if_index,
592 self.vapi.l2fib_add_del(self.router_mac,
600 for recirc in recircs:
601 # EPG's ingress recirculation interface maps to its RD
602 recirc.recirc.set_table_ip4(recirc.epg.rd)
603 recirc.recirc.set_table_ip6(recirc.epg.rd)
605 # in the bridge to allow DVR. L2 emulation to punt to L3
606 self.vapi.sw_interface_set_l2_bridge(recirc.recirc.sw_if_index,
608 self.vapi.sw_interface_set_l2_emulation(
609 recirc.recirc.sw_if_index)
611 self.vapi.nat44_interface_add_del_feature(
612 recirc.recirc.sw_if_index,
615 self.vapi.nat66_add_del_interface(
616 recirc.recirc.sw_if_index,
620 recirc.add_vpp_config()
625 self.pg_enable_capture(self.pg_interfaces)
628 # routes to the endpoints. We need these since there are no
629 # adj-fibs due to the fact the the BVI address has /32 and
630 # the subnet is not attached.
632 for (ip, fip) in zip(ep.ips, ep.fips):
633 r = VppIpRoute(self, ip.address, ip.length,
634 [VppRoutePath(ip.address,
635 ep.epg.bvi.sw_if_index,
636 proto=ip.dpo_proto)],
642 # ARP entries for the endpoints
644 a = VppNeighbor(self,
645 ep.epg.bvi.sw_if_index,
652 # add the BD ARP termination entry
653 self.vapi.bd_ip_mac_add_del(bd_id=ep.epg.bd,
659 # Add static mappings for each EP from the 10/8 to 11/8 network
661 self.vapi.nat44_add_del_static_mapping(ip.bytes,
666 self.vapi.nat66_add_del_static_mapping(ip.bytes,
670 # add each EP itf to the its BD
671 self.vapi.sw_interface_set_l2_bridge(ep.itf.sw_if_index,
675 self.vapi.l2fib_add_del(ep.mac,
683 self.logger.info(self.vapi.cli("sh gbp endpoint"))
685 # ... results in a Gratuitous ARP/ND on the EPG's uplink
686 rx = ep.epg.uplink.get_capture(len(ep.ips), timeout=0.2)
688 for ii, ip in enumerate(ep.ips):
692 self.assertTrue(p.haslayer(ICMPv6ND_NA))
693 self.assertEqual(p[ICMPv6ND_NA].tgt, ip.address)
695 self.assertTrue(p.haslayer(ARP))
696 self.assertEqual(p[ARP].psrc, ip.address)
697 self.assertEqual(p[ARP].pdst, ip.address)
699 # add the BD ARP termination entry for floating IP
701 self.vapi.bd_ip_mac_add_del(bd_id=epg_nat.bd,
707 # floating IPs route via EPG recirc
708 r = VppIpRoute(self, fip.address, fip.length,
709 [VppRoutePath(fip.address,
710 ep.recirc.recirc.sw_if_index,
712 proto=fip.dpo_proto)],
718 # L2 FIB entries in the NAT EPG BD to bridge the packets from
719 # the outside direct to the internal EPG
720 self.vapi.l2fib_add_del(ep.mac,
722 ep.recirc.recirc.sw_if_index,
726 # ARP packets for unknown IP are flooded
728 pkt_arp = (Ether(dst="ff:ff:ff:ff:ff:ff",
729 src=self.pg0.remote_mac) /
731 hwdst="ff:ff:ff:ff:ff:ff",
732 hwsrc=self.pg0.remote_mac,
733 pdst=epgs[0].bvi_ip4,
736 self.send_and_expect(self.pg0, [pkt_arp], self.pg0)
739 # ARP/ND packets get a response
741 pkt_arp = (Ether(dst="ff:ff:ff:ff:ff:ff",
742 src=self.pg0.remote_mac) /
744 hwdst="ff:ff:ff:ff:ff:ff",
745 hwsrc=self.pg0.remote_mac,
746 pdst=epgs[0].bvi_ip4,
747 psrc=eps[0].ip4.address))
749 self.send_and_expect(self.pg0, [pkt_arp], self.pg0)
751 nsma = in6_getnsma(inet_pton(AF_INET6, eps[0].ip6.address))
752 d = inet_ntop(AF_INET6, nsma)
753 pkt_nd = (Ether(dst=in6_getnsmac(nsma)) /
754 IPv6(dst=d, src=eps[0].ip6.address) /
755 ICMPv6ND_NS(tgt=epgs[0].bvi_ip6) /
756 ICMPv6NDOptSrcLLAddr(lladdr=self.pg0.remote_mac))
757 self.send_and_expect(self.pg0, [pkt_nd], self.pg0)
760 # broadcast packets are flooded
762 pkt_bcast = (Ether(dst="ff:ff:ff:ff:ff:ff",
763 src=self.pg0.remote_mac) /
764 IP(src=eps[0].ip4.address, dst="232.1.1.1") /
765 UDP(sport=1234, dport=1234) /
768 self.vapi.cli("clear trace")
769 self.pg0.add_stream(pkt_bcast)
771 self.pg_enable_capture(self.pg_interfaces)
774 rxd = eps[1].itf.get_capture(1)
775 self.assertEqual(rxd[0][Ether].dst, pkt_bcast[Ether].dst)
776 rxd = epgs[0].uplink.get_capture(1)
777 self.assertEqual(rxd[0][Ether].dst, pkt_bcast[Ether].dst)
780 # packets to non-local L3 destinations dropped
782 pkt_intra_epg_220_ip4 = (Ether(src=self.pg0.remote_mac,
783 dst=self.router_mac) /
784 IP(src=eps[0].ip4.address,
786 UDP(sport=1234, dport=1234) /
788 pkt_inter_epg_222_ip4 = (Ether(src=self.pg0.remote_mac,
789 dst=self.router_mac) /
790 IP(src=eps[0].ip4.address,
792 UDP(sport=1234, dport=1234) /
795 self.send_and_assert_no_replies(self.pg0, pkt_intra_epg_220_ip4 * 65)
797 pkt_inter_epg_222_ip6 = (Ether(src=self.pg0.remote_mac,
798 dst=self.router_mac) /
799 IPv6(src=eps[0].ip6.address,
801 UDP(sport=1234, dport=1234) /
803 self.send_and_assert_no_replies(self.pg0, pkt_inter_epg_222_ip6 * 65)
806 # Add the subnet routes
808 s41 = VppGbpSubnet(self, 0, "10.0.0.0", 24)
809 s42 = VppGbpSubnet(self, 0, "10.0.1.0", 24)
810 s43 = VppGbpSubnet(self, 0, "10.0.2.0", 24)
814 s61 = VppGbpSubnet(self, 0, "2001:10::1", 64)
815 s62 = VppGbpSubnet(self, 0, "2001:10:1::1", 64)
816 s63 = VppGbpSubnet(self, 0, "2001:10:2::1", 64)
821 self.send_and_expect_bridged(self.pg0,
822 pkt_intra_epg_220_ip4 * 65,
824 self.send_and_expect_bridged(self.pg3,
825 pkt_inter_epg_222_ip4 * 65,
827 self.send_and_expect_bridged6(self.pg3,
828 pkt_inter_epg_222_ip6 * 65,
831 self.logger.info(self.vapi.cli("sh ip fib 11.0.0.2"))
832 self.logger.info(self.vapi.cli("sh gbp endpoint-group"))
833 self.logger.info(self.vapi.cli("sh gbp endpoint"))
834 self.logger.info(self.vapi.cli("sh gbp recirc"))
835 self.logger.info(self.vapi.cli("sh int"))
836 self.logger.info(self.vapi.cli("sh int addr"))
837 self.logger.info(self.vapi.cli("sh int feat loop6"))
838 self.logger.info(self.vapi.cli("sh vlib graph ip4-gbp-src-classify"))
839 self.logger.info(self.vapi.cli("sh int feat loop3"))
842 # Packet destined to unknown unicast is sent on the epg uplink ...
844 pkt_intra_epg_220_to_uplink = (Ether(src=self.pg0.remote_mac,
845 dst="00:00:00:33:44:55") /
846 IP(src=eps[0].ip4.address,
848 UDP(sport=1234, dport=1234) /
851 self.send_and_expect_bridged(self.pg0,
852 pkt_intra_epg_220_to_uplink * 65,
854 # ... and nowhere else
855 self.pg1.get_capture(0, timeout=0.1)
856 self.pg1.assert_nothing_captured(remark="Flood onto other VMS")
858 pkt_intra_epg_221_to_uplink = (Ether(src=self.pg2.remote_mac,
859 dst="00:00:00:33:44:66") /
860 IP(src=eps[0].ip4.address,
862 UDP(sport=1234, dport=1234) /
865 self.send_and_expect_bridged(self.pg2,
866 pkt_intra_epg_221_to_uplink * 65,
870 # Packets from the uplink are forwarded in the absence of a contract
872 pkt_intra_epg_220_from_uplink = (Ether(src="00:00:00:33:44:55",
873 dst=self.pg0.remote_mac) /
874 IP(src=eps[0].ip4.address,
876 UDP(sport=1234, dport=1234) /
879 self.send_and_expect_bridged(self.pg4,
880 pkt_intra_epg_220_from_uplink * 65,
884 # in the absence of policy, endpoints in the same EPG
887 pkt_intra_epg = (Ether(src=self.pg0.remote_mac,
888 dst=self.pg1.remote_mac) /
889 IP(src=eps[0].ip4.address,
890 dst=eps[1].ip4.address) /
891 UDP(sport=1234, dport=1234) /
894 self.send_and_expect_bridged(self.pg0, pkt_intra_epg * 65, self.pg1)
897 # in the abscense of policy, endpoints in the different EPG
900 pkt_inter_epg_220_to_221 = (Ether(src=self.pg0.remote_mac,
901 dst=self.pg2.remote_mac) /
902 IP(src=eps[0].ip4.address,
903 dst=eps[2].ip4.address) /
904 UDP(sport=1234, dport=1234) /
906 pkt_inter_epg_221_to_220 = (Ether(src=self.pg2.remote_mac,
907 dst=self.pg0.remote_mac) /
908 IP(src=eps[2].ip4.address,
909 dst=eps[0].ip4.address) /
910 UDP(sport=1234, dport=1234) /
912 pkt_inter_epg_220_to_222 = (Ether(src=self.pg0.remote_mac,
913 dst=self.router_mac) /
914 IP(src=eps[0].ip4.address,
915 dst=eps[3].ip4.address) /
916 UDP(sport=1234, dport=1234) /
919 self.send_and_assert_no_replies(self.pg0,
920 pkt_inter_epg_220_to_221 * 65)
921 self.send_and_assert_no_replies(self.pg0,
922 pkt_inter_epg_220_to_222 * 65)
925 # A uni-directional contract from EPG 220 -> 221
927 acl = VppGbpAcl(self)
928 rule = acl.create_rule(permit_deny=1, proto=17)
929 rule2 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
930 acl_index = acl.add_vpp_config([rule, rule2])
931 c1 = VppGbpContract(self, 220, 221, acl_index)
934 self.send_and_expect_bridged(self.pg0,
935 pkt_inter_epg_220_to_221 * 65,
937 self.send_and_assert_no_replies(self.pg0,
938 pkt_inter_epg_220_to_222 * 65)
941 # contract for the return direction
943 c2 = VppGbpContract(self, 221, 220, acl_index)
946 self.send_and_expect_bridged(self.pg0,
947 pkt_inter_epg_220_to_221 * 65,
949 self.send_and_expect_bridged(self.pg2,
950 pkt_inter_epg_221_to_220 * 65,
954 # check that inter group is still disabled for the groups
955 # not in the contract.
957 self.send_and_assert_no_replies(self.pg0,
958 pkt_inter_epg_220_to_222 * 65)
961 # A uni-directional contract from EPG 220 -> 222 'L3 routed'
963 c3 = VppGbpContract(self, 220, 222, acl_index)
966 self.logger.info(self.vapi.cli("sh gbp contract"))
968 self.send_and_expect_routed(self.pg0,
969 pkt_inter_epg_220_to_222 * 65,
974 # remove both contracts, traffic stops in both directions
976 c2.remove_vpp_config()
977 c1.remove_vpp_config()
978 c3.remove_vpp_config()
979 acl.remove_vpp_config()
981 self.send_and_assert_no_replies(self.pg2,
982 pkt_inter_epg_221_to_220 * 65)
983 self.send_and_assert_no_replies(self.pg0,
984 pkt_inter_epg_220_to_221 * 65)
985 self.send_and_expect_bridged(self.pg0, pkt_intra_epg * 65, self.pg1)
988 # EPs to the outside world
991 # in the EP's RD an external subnet via the NAT EPG's recirc
992 se1 = VppGbpSubnet(self, 0, "0.0.0.0", 0,
994 sw_if_index=recirc_nat.recirc.sw_if_index,
997 se2 = VppGbpSubnet(self, 0, "11.0.0.0", 8,
999 sw_if_index=recirc_nat.recirc.sw_if_index,
1001 se2.add_vpp_config()
1002 se16 = VppGbpSubnet(self, 0, "::", 0,
1004 sw_if_index=recirc_nat.recirc.sw_if_index,
1006 se16.add_vpp_config()
1007 # in the NAT RD an external subnet via the NAT EPG's uplink
1008 se3 = VppGbpSubnet(self, 20, "0.0.0.0", 0,
1010 sw_if_index=epg_nat.uplink.sw_if_index,
1012 se36 = VppGbpSubnet(self, 20, "::", 0,
1014 sw_if_index=epg_nat.uplink.sw_if_index,
1016 se4 = VppGbpSubnet(self, 20, "11.0.0.0", 8,
1018 sw_if_index=epg_nat.uplink.sw_if_index,
1020 se3.add_vpp_config()
1021 se36.add_vpp_config()
1022 se4.add_vpp_config()
1024 self.logger.info(self.vapi.cli("sh ip fib 0.0.0.0/0"))
1025 self.logger.info(self.vapi.cli("sh ip fib 11.0.0.1"))
1026 self.logger.info(self.vapi.cli("sh ip6 fib ::/0"))
1027 self.logger.info(self.vapi.cli("sh ip6 fib %s" %
1031 # From an EP to an outside addess: IN2OUT
1033 pkt_inter_epg_220_to_global = (Ether(src=self.pg0.remote_mac,
1034 dst=self.router_mac) /
1035 IP(src=eps[0].ip4.address,
1037 UDP(sport=1234, dport=1234) /
1041 self.send_and_assert_no_replies(self.pg0,
1042 pkt_inter_epg_220_to_global * 65)
1044 acl2 = VppGbpAcl(self)
1045 rule = acl2.create_rule(permit_deny=1, proto=17, sport_from=1234,
1046 sport_to=1234, dport_from=1234, dport_to=1234)
1047 rule2 = acl2.create_rule(is_ipv6=1, permit_deny=1, proto=17,
1048 sport_from=1234, sport_to=1234,
1049 dport_from=1234, dport_to=1234)
1051 acl_index2 = acl2.add_vpp_config([rule, rule2])
1052 c4 = VppGbpContract(self, 220, 333, acl_index2)
1055 self.send_and_expect_natted(self.pg0,
1056 pkt_inter_epg_220_to_global * 65,
1058 eps[0].fip4.address)
1060 pkt_inter_epg_220_to_global = (Ether(src=self.pg0.remote_mac,
1061 dst=self.router_mac) /
1062 IPv6(src=eps[0].ip6.address,
1064 UDP(sport=1234, dport=1234) /
1067 self.send_and_expect_natted6(self.pg0,
1068 pkt_inter_epg_220_to_global * 65,
1070 eps[0].fip6.address)
1073 # From a global address to an EP: OUT2IN
1075 pkt_inter_epg_220_from_global = (Ether(src=self.router_mac,
1076 dst=self.pg0.remote_mac) /
1077 IP(dst=eps[0].fip4.address,
1079 UDP(sport=1234, dport=1234) /
1082 self.send_and_assert_no_replies(self.pg7,
1083 pkt_inter_epg_220_from_global * 65)
1085 c5 = VppGbpContract(self, 333, 220, acl_index2)
1088 self.send_and_expect_unnatted(self.pg7,
1089 pkt_inter_epg_220_from_global * 65,
1093 pkt_inter_epg_220_from_global = (Ether(src=self.router_mac,
1094 dst=self.pg0.remote_mac) /
1095 IPv6(dst=eps[0].fip6.address,
1097 UDP(sport=1234, dport=1234) /
1100 self.send_and_expect_unnatted6(self.pg7,
1101 pkt_inter_epg_220_from_global * 65,
1106 # From a local VM to another local VM using resp. public addresses:
1109 pkt_intra_epg_220_global = (Ether(src=self.pg0.remote_mac,
1110 dst=self.router_mac) /
1111 IP(src=eps[0].ip4.address,
1112 dst=eps[1].fip4.address) /
1113 UDP(sport=1234, dport=1234) /
1116 self.send_and_expect_double_natted(eps[0].itf,
1117 pkt_intra_epg_220_global * 65,
1119 eps[0].fip4.address,
1122 pkt_intra_epg_220_global = (Ether(src=self.pg0.remote_mac,
1123 dst=self.router_mac) /
1124 IPv6(src=eps[0].ip6.address,
1125 dst=eps[1].fip6.address) /
1126 UDP(sport=1234, dport=1234) /
1129 self.send_and_expect_double_natted6(eps[0].itf,
1130 pkt_intra_epg_220_global * 65,
1132 eps[0].fip6.address,
1139 # del static mappings for each EP from the 10/8 to 11/8 network
1140 self.vapi.nat44_add_del_static_mapping(ep.ip4.bytes,
1145 self.vapi.nat66_add_del_static_mapping(ep.ip6.bytes,
1151 # IP config on the BVI interfaces
1152 self.vapi.sw_interface_add_del_address(epg.bvi.sw_if_index,
1156 self.vapi.sw_interface_add_del_address(epg.bvi.sw_if_index,
1161 self.logger.info(self.vapi.cli("sh int addr"))
1163 epg.uplink.set_table_ip4(0)
1164 epg.uplink.set_table_ip6(0)
1166 if epg != epgs[0] and epg != epgs[3]:
1167 epg.bvi.set_table_ip4(0)
1168 epg.bvi.set_table_ip6(0)
1170 self.vapi.nat44_interface_add_del_feature(epg.bvi.sw_if_index,
1173 self.vapi.nat66_add_del_interface(epg.bvi.sw_if_index,
1177 for recirc in recircs:
1178 recirc.recirc.set_table_ip4(0)
1179 recirc.recirc.set_table_ip6(0)
1181 self.vapi.nat44_interface_add_del_feature(
1182 recirc.recirc.sw_if_index,
1185 self.vapi.nat66_add_del_interface(
1186 recirc.recirc.sw_if_index,
1191 if __name__ == '__main__':
1192 unittest.main(testRunner=VppTestRunner)