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, DpoProto
10 from scapy.packet import Raw
11 from scapy.layers.l2 import Ether, ARP
12 from scapy.layers.inet import IP, UDP
13 from scapy.layers.inet6 import IPv6, ICMPv6ND_NS, ICMPv6NDOptSrcLLAddr, \
15 from scapy.utils6 import in6_getnsma, in6_getnsmac
17 from socket import AF_INET, AF_INET6
18 from scapy.utils import inet_pton, inet_ntop
19 from util import mactobinary
22 class VppGbpEndpoint(VppObject):
29 return mactobinary(self.itf.remote_mac)
33 return self.itf.remote_mac
35 def __init__(self, test, itf, epg, recirc, ip, fip, is_ip6=False):
41 self.floating_ip = fip
44 self.proto = DpoProto.DPO_PROTO_IP6
49 self.proto = DpoProto.DPO_PROTO_IP4
53 self.ip_n = inet_pton(self.af, ip)
54 self.floating_ip_n = inet_pton(self.af, fip)
56 def add_vpp_config(self):
57 self._test.vapi.gbp_endpoint_add_del(
63 self._test.registry.register(self, self._test.logger)
65 def remove_vpp_config(self):
66 self._test.vapi.gbp_endpoint_add_del(
74 return self.object_id()
77 return "gbp-endpoint;[%d:%s:%d]" % (self.itf.sw_if_index,
81 def query_vpp_config(self):
82 eps = self._test.vapi.gbp_endpoint_dump()
85 if ep.endpoint.address == self.ip_n \
86 and ep.endpoint.sw_if_index == self.itf.sw_if_index:
89 if ep.endpoint.address[:4] == self.ip_n \
90 and ep.endpoint.sw_if_index == self.itf.sw_if_index:
95 class VppGbpRecirc(VppObject):
97 GBP Recirculation Interface
100 def __init__(self, test, epg, recirc, is_ext=False):
106 def add_vpp_config(self):
107 self._test.vapi.gbp_recirc_add_del(
109 self.recirc.sw_if_index,
112 self._test.registry.register(self, self._test.logger)
114 def remove_vpp_config(self):
115 self._test.vapi.gbp_recirc_add_del(
117 self.recirc.sw_if_index,
122 return self.object_id()
125 return "gbp-recirc;[%d]" % (self.recirc.sw_if_index)
127 def query_vpp_config(self):
128 rs = self._test.vapi.gbp_recirc_dump()
130 if r.recirc.sw_if_index == self.recirc.sw_if_index:
135 class VppGbpSubnet(VppObject):
140 def __init__(self, test, table_id, address, address_len,
141 is_internal=True, is_ip6=False,
142 sw_if_index=None, epg=None):
144 self.table_id = table_id
145 self.address = address
146 self.address_len = address_len
149 self.address_n = inet_pton(AF_INET6, address)
151 self.address_n = inet_pton(AF_INET, address)
152 self.is_internal = is_internal
153 self.sw_if_index = sw_if_index
156 def add_vpp_config(self):
157 self._test.vapi.gbp_subnet_add_del(
163 sw_if_index=self.sw_if_index if self.sw_if_index else 0xffffffff,
164 epg_id=self.epg if self.epg else 0xffffffff,
166 self._test.registry.register(self, self._test.logger)
168 def remove_vpp_config(self):
169 self._test.vapi.gbp_subnet_add_del(
178 return self.object_id()
181 return "gbp-subnet;[%d:%s/%d]" % (self.table_id,
185 def query_vpp_config(self):
186 ss = self._test.vapi.gbp_subnet_dump()
188 if s.subnet.table_id == self.table_id and \
189 s.subnet.address_length == self.address_len and \
190 s.subnet.is_ip6 == self.is_ip6:
192 if s.subnet.address == self.address_n:
195 if s.subnet.address[:4] == self.address_n:
200 class VppGbpEndpointGroup(VppObject):
205 def __init__(self, test, epg, rd, bd, uplink,
206 bvi, bvi_ip4, bvi_ip6=None):
210 self.bvi_ip4 = bvi_ip4
211 self.bvi_ip4_n = inet_pton(AF_INET, bvi_ip4)
212 self.bvi_ip6 = bvi_ip6
213 self.bvi_ip6_n = inet_pton(AF_INET6, bvi_ip6)
218 def add_vpp_config(self):
219 self._test.vapi.gbp_endpoint_group_add_del(
225 self.uplink.sw_if_index)
226 self._test.registry.register(self, self._test.logger)
228 def remove_vpp_config(self):
229 self._test.vapi.gbp_endpoint_group_add_del(
235 self.uplink.sw_if_index)
238 return self.object_id()
241 return "gbp-endpoint-group;[%d]" % (self.epg)
243 def query_vpp_config(self):
244 epgs = self._test.vapi.gbp_endpoint_group_dump()
246 if epg.epg.epg_id == self.epg:
251 class VppGbpContract(VppObject):
256 def __init__(self, test, src_epg, dst_epg, acl_index):
258 self.acl_index = acl_index
259 self.src_epg = src_epg
260 self.dst_epg = dst_epg
262 def add_vpp_config(self):
263 self._test.vapi.gbp_contract_add_del(
268 self._test.registry.register(self, self._test.logger)
270 def remove_vpp_config(self):
271 self._test.vapi.gbp_contract_add_del(
278 return self.object_id()
281 return "gbp-contract;[%d:%s:%d]" % (self.src_epg,
285 def query_vpp_config(self):
286 cs = self._test.vapi.gbp_contract_dump()
288 if c.contract.src_epg == self.src_epg \
289 and c.contract.dst_epg == self.dst_epg:
294 class VppGbpAcl(VppObject):
299 def __init__(self, test):
301 self.acl_index = 4294967295
303 def create_rule(self, is_ipv6=0, permit_deny=0, proto=-1,
304 s_prefix=0, s_ip='\x00\x00\x00\x00', sport_from=0,
305 sport_to=65535, d_prefix=0, d_ip='\x00\x00\x00\x00',
306 dport_from=0, dport_to=65535):
307 if proto == -1 or proto == 0:
310 elif proto == 1 or proto == 58:
313 rule = ({'is_permit': permit_deny, 'is_ipv6': is_ipv6, 'proto': proto,
314 'srcport_or_icmptype_first': sport_from,
315 'srcport_or_icmptype_last': sport_to,
316 'src_ip_prefix_len': s_prefix,
318 'dstport_or_icmpcode_first': dport_from,
319 'dstport_or_icmpcode_last': dport_to,
320 'dst_ip_prefix_len': d_prefix,
321 'dst_ip_addr': d_ip})
324 def add_vpp_config(self, rules):
326 reply = self._test.vapi.acl_add_replace(self.acl_index,
329 self.acl_index = reply.acl_index
330 return self.acl_index
332 def remove_vpp_config(self):
333 self._test.vapi.acl_del(self.acl_index)
336 return self.object_id()
339 return "gbp-acl;[%d]" % (self.acl_index)
341 def query_vpp_config(self):
342 cs = self._test.vapi.acl_dump()
344 if c.acl_index == self.acl_index:
349 class TestGBP(VppTestCase):
350 """ GBP Test Case """
353 super(TestGBP, self).setUp()
355 self.create_pg_interfaces(range(9))
356 self.create_loopback_interfaces(9)
358 self.router_mac = "00:11:22:33:44:55"
360 for i in self.pg_interfaces:
362 for i in self.lo_interfaces:
364 self.vapi.sw_interface_set_mac_address(
366 mactobinary(self.router_mac))
369 for i in self.pg_interfaces:
372 super(TestGBP, self).tearDown()
374 def send_and_expect_bridged(self, src, tx, dst):
375 rx = self.send_and_expect(src, tx, dst)
378 self.assertEqual(r[Ether].src, tx[0][Ether].src)
379 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
380 self.assertEqual(r[IP].src, tx[0][IP].src)
381 self.assertEqual(r[IP].dst, tx[0][IP].dst)
384 def send_and_expect_bridged6(self, src, tx, dst):
385 rx = self.send_and_expect(src, tx, dst)
388 self.assertEqual(r[Ether].src, tx[0][Ether].src)
389 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
390 self.assertEqual(r[IPv6].src, tx[0][IPv6].src)
391 self.assertEqual(r[IPv6].dst, tx[0][IPv6].dst)
394 def send_and_expect_routed(self, src, tx, dst, src_mac):
395 rx = self.send_and_expect(src, tx, dst)
398 self.assertEqual(r[Ether].src, src_mac)
399 self.assertEqual(r[Ether].dst, dst.remote_mac)
400 self.assertEqual(r[IP].src, tx[0][IP].src)
401 self.assertEqual(r[IP].dst, tx[0][IP].dst)
404 def send_and_expect_natted(self, src, tx, dst, src_ip):
405 rx = self.send_and_expect(src, tx, dst)
408 self.assertEqual(r[Ether].src, tx[0][Ether].src)
409 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
410 self.assertEqual(r[IP].src, src_ip)
411 self.assertEqual(r[IP].dst, tx[0][IP].dst)
414 def send_and_expect_natted6(self, src, tx, dst, src_ip):
415 rx = self.send_and_expect(src, tx, dst)
418 self.assertEqual(r[Ether].src, tx[0][Ether].src)
419 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
420 self.assertEqual(r[IPv6].src, src_ip)
421 self.assertEqual(r[IPv6].dst, tx[0][IPv6].dst)
424 def send_and_expect_unnatted(self, src, tx, dst, dst_ip):
425 rx = self.send_and_expect(src, tx, dst)
428 self.assertEqual(r[Ether].src, tx[0][Ether].src)
429 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
430 self.assertEqual(r[IP].dst, dst_ip)
431 self.assertEqual(r[IP].src, tx[0][IP].src)
434 def send_and_expect_unnatted6(self, src, tx, dst, dst_ip):
435 rx = self.send_and_expect(src, tx, dst)
438 self.assertEqual(r[Ether].src, tx[0][Ether].src)
439 self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
440 self.assertEqual(r[IPv6].dst, dst_ip)
441 self.assertEqual(r[IPv6].src, tx[0][IPv6].src)
444 def send_and_expect_double_natted(self, src, tx, dst, src_ip, dst_ip):
445 rx = self.send_and_expect(src, tx, dst)
448 self.assertEqual(r[Ether].src, self.router_mac)
449 self.assertEqual(r[Ether].dst, dst.remote_mac)
450 self.assertEqual(r[IP].dst, dst_ip)
451 self.assertEqual(r[IP].src, src_ip)
454 def send_and_expect_double_natted6(self, src, tx, dst, src_ip, dst_ip):
455 rx = self.send_and_expect(src, tx, dst)
458 self.assertEqual(r[Ether].src, self.router_mac)
459 self.assertEqual(r[Ether].dst, dst.remote_mac)
460 self.assertEqual(r[IPv6].dst, dst_ip)
461 self.assertEqual(r[IPv6].src, src_ip)
465 """ Group Based Policy """
467 nat_table = VppIpTable(self, 20)
468 nat_table.add_vpp_config()
469 nat_table = VppIpTable(self, 20, is_ip6=True)
470 nat_table.add_vpp_config()
475 self.vapi.bridge_domain_add_del(1, flood=1, uu_flood=1, forward=1,
476 learn=0, arp_term=1, is_add=1)
477 self.vapi.bridge_domain_add_del(2, flood=1, uu_flood=1, forward=1,
478 learn=0, arp_term=1, is_add=1)
479 self.vapi.bridge_domain_add_del(20, flood=1, uu_flood=1, forward=1,
480 learn=0, arp_term=1, is_add=1)
483 # 3 EPGs, 2 of which share a BD.
487 epgs.append(VppGbpEndpointGroup(self, 220, 0, 1, self.pg4,
491 recircs.append(VppGbpRecirc(self, epgs[0],
493 epgs.append(VppGbpEndpointGroup(self, 221, 0, 1, self.pg5,
497 recircs.append(VppGbpRecirc(self, epgs[1],
499 epgs.append(VppGbpEndpointGroup(self, 222, 0, 2, self.pg6,
503 recircs.append(VppGbpRecirc(self, epgs[2],
507 # 2 NAT EPGs, one for floating-IP subnets, the other for internet
509 epgs.append(VppGbpEndpointGroup(self, 333, 20, 20, self.pg7,
513 recircs.append(VppGbpRecirc(self, epgs[3],
514 self.loop6, is_ext=True))
515 epgs.append(VppGbpEndpointGroup(self, 444, 20, 20, self.pg8,
519 recircs.append(VppGbpRecirc(self, epgs[4],
520 self.loop8, is_ext=True))
523 recirc_nat = recircs[3]
526 # 4 end-points, 2 in the same subnet, 3 in the same BD
529 eps.append(VppGbpEndpoint(self, self.pg0,
533 eps.append(VppGbpEndpoint(self, self.pg1,
537 eps.append(VppGbpEndpoint(self, self.pg2,
541 eps.append(VppGbpEndpoint(self, self.pg3,
545 eps.append(VppGbpEndpoint(self, self.pg0,
550 eps.append(VppGbpEndpoint(self, self.pg1,
555 eps.append(VppGbpEndpoint(self, self.pg2,
560 eps.append(VppGbpEndpoint(self, self.pg3,
567 # Config related to each of the EPGs
570 # IP config on the BVI interfaces
571 if epg != epgs[1] and epg != epgs[4]:
572 epg.bvi.set_table_ip4(epg.rd)
573 epg.bvi.set_table_ip6(epg.rd)
575 # The BVIs are NAT inside interfaces
576 self.vapi.nat44_interface_add_del_feature(epg.bvi.sw_if_index,
579 self.vapi.nat66_add_del_interface(epg.bvi.sw_if_index,
583 self.vapi.sw_interface_add_del_address(epg.bvi.sw_if_index,
586 self.vapi.sw_interface_add_del_address(epg.bvi.sw_if_index,
591 # EPG uplink interfaces in the BD
592 epg.uplink.set_table_ip4(epg.rd)
593 epg.uplink.set_table_ip6(epg.rd)
594 self.vapi.sw_interface_set_l2_bridge(epg.uplink.sw_if_index,
597 # add the BD ARP termination entry for BVI IP
598 self.vapi.bd_ip_mac_add_del(bd_id=epg.bd,
599 mac=mactobinary(self.router_mac),
603 self.vapi.bd_ip_mac_add_del(bd_id=epg.bd,
604 mac=mactobinary(self.router_mac),
609 # epg[1] shares the same BVI to epg[0]
610 if epg != epgs[1] and epg != epgs[4]:
612 self.vapi.sw_interface_set_l2_bridge(epg.bvi.sw_if_index,
616 self.vapi.l2fib_add_del(self.router_mac,
624 for recirc in recircs:
625 # EPG's ingress recirculation interface maps to its RD
626 recirc.recirc.set_table_ip4(recirc.epg.rd)
627 recirc.recirc.set_table_ip6(recirc.epg.rd)
629 # in the bridge to allow DVR. L2 emulation to punt to L3
630 self.vapi.sw_interface_set_l2_bridge(recirc.recirc.sw_if_index,
632 self.vapi.sw_interface_set_l2_emulation(
633 recirc.recirc.sw_if_index)
635 self.vapi.nat44_interface_add_del_feature(
636 recirc.recirc.sw_if_index,
639 self.vapi.nat66_add_del_interface(
640 recirc.recirc.sw_if_index,
644 recirc.add_vpp_config()
649 self.pg_enable_capture(self.pg_interfaces)
652 # routes to the endpoints. We need these since there are no
653 # adj-fibs due to the fact the the BVI address has /32 and
654 # the subnet is not attached.
656 r = VppIpRoute(self, ep.ip, ep.ip_len,
658 ep.epg.bvi.sw_if_index,
665 # ARP entries for the endpoints
667 a = VppNeighbor(self,
668 ep.epg.bvi.sw_if_index,
674 # add each EP itf to the its BD
675 self.vapi.sw_interface_set_l2_bridge(ep.itf.sw_if_index,
678 # add the BD ARP termination entry
679 self.vapi.bd_ip_mac_add_del(bd_id=ep.epg.bd,
686 self.vapi.l2fib_add_del(ep.mac,
691 # Add static mappings for each EP from the 10/8 to 11/8 network
693 self.vapi.nat44_add_del_static_mapping(ep.ip_n,
698 self.vapi.nat66_add_del_static_mapping(ep.ip_n,
705 # ... results in a Gratuitous ARP/ND on the EPG's uplink
706 rx = ep.epg.uplink.get_capture(1, timeout=0.2)
709 self.assertTrue(rx[0].haslayer(ICMPv6ND_NA))
710 self.assertEqual(rx[0][ICMPv6ND_NA].tgt, ep.ip)
712 self.assertTrue(rx[0].haslayer(ARP))
713 self.assertEqual(rx[0][ARP].psrc, ep.ip)
714 self.assertEqual(rx[0][ARP].pdst, ep.ip)
716 # add the BD ARP termination entry for floating IP
717 self.vapi.bd_ip_mac_add_del(bd_id=epg_nat.bd,
723 # floating IPs route via EPG recirc
724 r = VppIpRoute(self, ep.floating_ip, ep.ip_len,
725 [VppRoutePath(ep.floating_ip,
726 ep.recirc.recirc.sw_if_index,
734 # L2 FIB entries in the NAT EPG BD to bridge the packets from
735 # the outside direct to the internal EPG
736 self.vapi.l2fib_add_del(ep.mac,
738 ep.recirc.recirc.sw_if_index,
742 # ARP packets for unknown IP are flooded
744 pkt_arp = (Ether(dst="ff:ff:ff:ff:ff:ff",
745 src=self.pg0.remote_mac) /
747 hwdst="ff:ff:ff:ff:ff:ff",
748 hwsrc=self.pg0.remote_mac,
749 pdst=epgs[0].bvi_ip4,
752 self.send_and_expect(self.pg0, [pkt_arp], self.pg0)
755 # ARP/ND packets get a response
757 pkt_arp = (Ether(dst="ff:ff:ff:ff:ff:ff",
758 src=self.pg0.remote_mac) /
760 hwdst="ff:ff:ff:ff:ff:ff",
761 hwsrc=self.pg0.remote_mac,
762 pdst=epgs[0].bvi_ip4,
765 self.send_and_expect(self.pg0, [pkt_arp], self.pg0)
767 nsma = in6_getnsma(inet_pton(AF_INET6, eps[4].ip))
768 d = inet_ntop(AF_INET6, nsma)
769 pkt_nd = (Ether(dst=in6_getnsmac(nsma)) /
770 IPv6(dst=d, src=eps[4].ip) /
771 ICMPv6ND_NS(tgt=epgs[0].bvi_ip6) /
772 ICMPv6NDOptSrcLLAddr(lladdr=self.pg0.remote_mac))
773 self.send_and_expect(self.pg0, [pkt_nd], self.pg0)
776 # broadcast packets are flooded
778 pkt_bcast = (Ether(dst="ff:ff:ff:ff:ff:ff",
779 src=self.pg0.remote_mac) /
780 IP(src=eps[0].ip, dst="232.1.1.1") /
781 UDP(sport=1234, dport=1234) /
784 self.vapi.cli("clear trace")
785 self.pg0.add_stream(pkt_bcast)
787 self.pg_enable_capture(self.pg_interfaces)
790 rxd = eps[1].itf.get_capture(1)
791 self.assertEqual(rxd[0][Ether].dst, pkt_bcast[Ether].dst)
792 rxd = epgs[0].uplink.get_capture(1)
793 self.assertEqual(rxd[0][Ether].dst, pkt_bcast[Ether].dst)
796 # packets to non-local L3 destinations dropped
798 pkt_intra_epg_220_ip4 = (Ether(src=self.pg0.remote_mac,
799 dst=self.router_mac) /
800 IP(src=eps[0].ip, dst="10.0.0.99") /
801 UDP(sport=1234, dport=1234) /
803 pkt_inter_epg_222_ip4 = (Ether(src=self.pg0.remote_mac,
804 dst=self.router_mac) /
805 IP(src=eps[0].ip, dst="10.0.1.99") /
806 UDP(sport=1234, dport=1234) /
809 self.send_and_assert_no_replies(self.pg0, pkt_intra_epg_220_ip4 * 65)
811 pkt_inter_epg_222_ip6 = (Ether(src=self.pg0.remote_mac,
812 dst=self.router_mac) /
813 IPv6(src=eps[4].ip, dst="2001:10::99") /
814 UDP(sport=1234, dport=1234) /
816 self.send_and_assert_no_replies(self.pg0, pkt_inter_epg_222_ip6 * 65)
819 # Add the subnet routes
821 s41 = VppGbpSubnet(self, 0, "10.0.0.0", 24)
822 s42 = VppGbpSubnet(self, 0, "10.0.1.0", 24)
823 s43 = VppGbpSubnet(self, 0, "10.0.2.0", 24)
827 s61 = VppGbpSubnet(self, 0, "2001:10::1", 64, is_ip6=True)
828 s62 = VppGbpSubnet(self, 0, "2001:10:1::1", 64, is_ip6=True)
829 s63 = VppGbpSubnet(self, 0, "2001:10:2::1", 64, is_ip6=True)
834 self.send_and_expect_bridged(self.pg0,
835 pkt_intra_epg_220_ip4 * 65,
837 self.send_and_expect_bridged(self.pg3,
838 pkt_inter_epg_222_ip4 * 65,
840 self.send_and_expect_bridged6(self.pg3,
841 pkt_inter_epg_222_ip6 * 65,
844 self.logger.info(self.vapi.cli("sh ip fib 11.0.0.2"))
845 self.logger.info(self.vapi.cli("sh gbp endpoint-group"))
846 self.logger.info(self.vapi.cli("sh gbp endpoint"))
847 self.logger.info(self.vapi.cli("sh gbp recirc"))
848 self.logger.info(self.vapi.cli("sh int"))
849 self.logger.info(self.vapi.cli("sh int addr"))
850 self.logger.info(self.vapi.cli("sh int feat loop6"))
851 self.logger.info(self.vapi.cli("sh vlib graph ip4-gbp-src-classify"))
852 self.logger.info(self.vapi.cli("sh int feat loop3"))
855 # Packet destined to unknown unicast is sent on the epg uplink ...
857 pkt_intra_epg_220_to_uplink = (Ether(src=self.pg0.remote_mac,
858 dst="00:00:00:33:44:55") /
859 IP(src=eps[0].ip, dst="10.0.0.99") /
860 UDP(sport=1234, dport=1234) /
863 self.send_and_expect_bridged(self.pg0,
864 pkt_intra_epg_220_to_uplink * 65,
866 # ... and nowhere else
867 self.pg1.get_capture(0, timeout=0.1)
868 self.pg1.assert_nothing_captured(remark="Flood onto other VMS")
870 pkt_intra_epg_221_to_uplink = (Ether(src=self.pg2.remote_mac,
871 dst="00:00:00:33:44:66") /
872 IP(src=eps[0].ip, dst="10.0.0.99") /
873 UDP(sport=1234, dport=1234) /
876 self.send_and_expect_bridged(self.pg2,
877 pkt_intra_epg_221_to_uplink * 65,
881 # Packets from the uplink are forwarded in the absence of a contract
883 pkt_intra_epg_220_from_uplink = (Ether(src="00:00:00:33:44:55",
884 dst=self.pg0.remote_mac) /
885 IP(src=eps[0].ip, dst="10.0.0.99") /
886 UDP(sport=1234, dport=1234) /
889 self.send_and_expect_bridged(self.pg4,
890 pkt_intra_epg_220_from_uplink * 65,
894 # in the absence of policy, endpoints in the same EPG
897 pkt_intra_epg = (Ether(src=self.pg0.remote_mac,
898 dst=self.pg1.remote_mac) /
899 IP(src=eps[0].ip, dst=eps[1].ip) /
900 UDP(sport=1234, dport=1234) /
903 self.send_and_expect_bridged(self.pg0, pkt_intra_epg * 65, self.pg1)
906 # in the abscense of policy, endpoints in the different EPG
909 pkt_inter_epg_220_to_221 = (Ether(src=self.pg0.remote_mac,
910 dst=self.pg2.remote_mac) /
911 IP(src=eps[0].ip, dst=eps[2].ip) /
912 UDP(sport=1234, dport=1234) /
914 pkt_inter_epg_221_to_220 = (Ether(src=self.pg2.remote_mac,
915 dst=self.pg0.remote_mac) /
916 IP(src=eps[2].ip, dst=eps[0].ip) /
917 UDP(sport=1234, dport=1234) /
919 pkt_inter_epg_220_to_222 = (Ether(src=self.pg0.remote_mac,
920 dst=self.router_mac) /
921 IP(src=eps[0].ip, dst=eps[3].ip) /
922 UDP(sport=1234, dport=1234) /
925 self.send_and_assert_no_replies(self.pg0,
926 pkt_inter_epg_220_to_221 * 65)
927 self.send_and_assert_no_replies(self.pg0,
928 pkt_inter_epg_220_to_222 * 65)
931 # A uni-directional contract from EPG 220 -> 221
933 acl = VppGbpAcl(self)
934 rule = acl.create_rule(permit_deny=1, proto=17)
935 rule2 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
936 acl_index = acl.add_vpp_config([rule, rule2])
937 c1 = VppGbpContract(self, 220, 221, acl_index)
940 self.send_and_expect_bridged(self.pg0,
941 pkt_inter_epg_220_to_221 * 65,
943 self.send_and_assert_no_replies(self.pg0,
944 pkt_inter_epg_220_to_222 * 65)
947 # contract for the return direction
949 c2 = VppGbpContract(self, 221, 220, acl_index)
952 self.send_and_expect_bridged(self.pg0,
953 pkt_inter_epg_220_to_221 * 65,
955 self.send_and_expect_bridged(self.pg2,
956 pkt_inter_epg_221_to_220 * 65,
960 # check that inter group is still disabled for the groups
961 # not in the contract.
963 self.send_and_assert_no_replies(self.pg0,
964 pkt_inter_epg_220_to_222 * 65)
967 # A uni-directional contract from EPG 220 -> 222 'L3 routed'
969 c3 = VppGbpContract(self, 220, 222, acl_index)
972 self.logger.info(self.vapi.cli("sh gbp contract"))
974 self.send_and_expect_routed(self.pg0,
975 pkt_inter_epg_220_to_222 * 65,
980 # remove both contracts, traffic stops in both directions
982 c2.remove_vpp_config()
983 c1.remove_vpp_config()
984 c3.remove_vpp_config()
985 acl.remove_vpp_config()
987 self.send_and_assert_no_replies(self.pg2,
988 pkt_inter_epg_221_to_220 * 65)
989 self.send_and_assert_no_replies(self.pg0,
990 pkt_inter_epg_220_to_221 * 65)
991 self.send_and_expect_bridged(self.pg0, pkt_intra_epg * 65, self.pg1)
994 # EPs to the outside world
997 # in the EP's RD an external subnet via the NAT EPG's recirc
998 se1 = VppGbpSubnet(self, 0, "0.0.0.0", 0,
1000 sw_if_index=recirc_nat.recirc.sw_if_index,
1002 se1.add_vpp_config()
1003 se2 = VppGbpSubnet(self, 0, "11.0.0.0", 8,
1005 sw_if_index=recirc_nat.recirc.sw_if_index,
1007 se2.add_vpp_config()
1008 se16 = VppGbpSubnet(self, 0, "::", 0,
1010 sw_if_index=recirc_nat.recirc.sw_if_index,
1013 se16.add_vpp_config()
1014 # in the NAT RD an external subnet via the NAT EPG's uplink
1015 se3 = VppGbpSubnet(self, 20, "0.0.0.0", 0,
1017 sw_if_index=epg_nat.uplink.sw_if_index,
1019 se36 = VppGbpSubnet(self, 20, "::", 0,
1021 sw_if_index=epg_nat.uplink.sw_if_index,
1024 se4 = VppGbpSubnet(self, 20, "11.0.0.0", 8,
1026 sw_if_index=epg_nat.uplink.sw_if_index,
1028 se3.add_vpp_config()
1029 se36.add_vpp_config()
1030 se4.add_vpp_config()
1032 self.logger.info(self.vapi.cli("sh ip fib 0.0.0.0/0"))
1033 self.logger.info(self.vapi.cli("sh ip fib 11.0.0.1"))
1034 self.logger.info(self.vapi.cli("sh ip6 fib ::/0"))
1035 self.logger.info(self.vapi.cli("sh ip6 fib %s" %
1036 eps[4].floating_ip))
1039 # From an EP to an outside addess: IN2OUT
1041 pkt_inter_epg_220_to_global = (Ether(src=self.pg0.remote_mac,
1042 dst=self.router_mac) /
1043 IP(src=eps[0].ip, dst="1.1.1.1") /
1044 UDP(sport=1234, dport=1234) /
1048 self.send_and_assert_no_replies(self.pg0,
1049 pkt_inter_epg_220_to_global * 65)
1051 acl2 = VppGbpAcl(self)
1052 rule = acl2.create_rule(permit_deny=1, proto=17, sport_from=1234,
1053 sport_to=1234, dport_from=1234, dport_to=1234)
1054 rule2 = acl2.create_rule(is_ipv6=1, permit_deny=1, proto=17,
1055 sport_from=1234, sport_to=1234,
1056 dport_from=1234, dport_to=1234)
1058 acl_index2 = acl2.add_vpp_config([rule, rule2])
1059 c4 = VppGbpContract(self, 220, 333, acl_index2)
1062 self.send_and_expect_natted(self.pg0,
1063 pkt_inter_epg_220_to_global * 65,
1067 pkt_inter_epg_220_to_global = (Ether(src=self.pg0.remote_mac,
1068 dst=self.router_mac) /
1069 IPv6(src=eps[4].ip, dst="6001::1") /
1070 UDP(sport=1234, dport=1234) /
1073 self.send_and_expect_natted6(self.pg0,
1074 pkt_inter_epg_220_to_global * 65,
1079 # From a global address to an EP: OUT2IN
1081 pkt_inter_epg_220_from_global = (Ether(src=self.router_mac,
1082 dst=self.pg0.remote_mac) /
1083 IP(dst=eps[0].floating_ip,
1085 UDP(sport=1234, dport=1234) /
1088 self.send_and_assert_no_replies(self.pg7,
1089 pkt_inter_epg_220_from_global * 65)
1091 c5 = VppGbpContract(self, 333, 220, acl_index2)
1094 self.send_and_expect_unnatted(self.pg7,
1095 pkt_inter_epg_220_from_global * 65,
1099 pkt_inter_epg_220_from_global = (Ether(src=self.router_mac,
1100 dst=self.pg0.remote_mac) /
1101 IPv6(dst=eps[4].floating_ip,
1103 UDP(sport=1234, dport=1234) /
1106 self.send_and_expect_unnatted6(self.pg7,
1107 pkt_inter_epg_220_from_global * 65,
1112 # From a local VM to another local VM using resp. public addresses:
1115 pkt_intra_epg_220_global = (Ether(src=self.pg0.remote_mac,
1116 dst=self.router_mac) /
1118 dst=eps[1].floating_ip) /
1119 UDP(sport=1234, dport=1234) /
1122 self.send_and_expect_double_natted(eps[0].itf,
1123 pkt_intra_epg_220_global * 65,
1128 pkt_intra_epg_220_global = (Ether(src=self.pg4.remote_mac,
1129 dst=self.router_mac) /
1131 dst=eps[5].floating_ip) /
1132 UDP(sport=1234, dport=1234) /
1135 self.send_and_expect_double_natted6(eps[4].itf,
1136 pkt_intra_epg_220_global * 65,
1145 # del static mappings for each EP from the 10/8 to 11/8 network
1146 if ep.af == AF_INET:
1147 self.vapi.nat44_add_del_static_mapping(ep.ip_n,
1153 self.vapi.nat66_add_del_static_mapping(ep.ip_n,
1159 # IP config on the BVI interfaces
1160 self.vapi.sw_interface_add_del_address(epg.bvi.sw_if_index,
1164 self.vapi.sw_interface_add_del_address(epg.bvi.sw_if_index,
1169 self.logger.info(self.vapi.cli("sh int addr"))
1171 epg.uplink.set_table_ip4(0)
1172 epg.uplink.set_table_ip6(0)
1174 if epg != epgs[0] and epg != epgs[3]:
1175 epg.bvi.set_table_ip4(0)
1176 epg.bvi.set_table_ip6(0)
1178 self.vapi.nat44_interface_add_del_feature(epg.bvi.sw_if_index,
1181 self.vapi.nat66_add_del_interface(epg.bvi.sw_if_index,
1185 for recirc in recircs:
1186 recirc.recirc.set_table_ip4(0)
1187 recirc.recirc.set_table_ip6(0)
1189 self.vapi.nat44_interface_add_del_feature(
1190 recirc.recirc.sw_if_index,
1193 self.vapi.nat66_add_del_interface(
1194 recirc.recirc.sw_if_index,
1199 if __name__ == '__main__':
1200 unittest.main(testRunner=VppTestRunner)