blob: 44df7222f9d1b542657d364642252a7ed4915678 [file] [log] [blame]
Ole Troan96068d62020-07-01 13:16:16 +02001#!/usr/bin/env python3
2
Ole Troan96068d62020-07-01 13:16:16 +02003import unittest
Ole Troan96068d62020-07-01 13:16:16 +02004
Dave Wallace8800f732023-08-31 00:47:44 -04005from framework import VppTestCase
6from asfframework import VppTestRunner
7from scapy.layers.inet import IP, TCP, UDP
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02008from scapy.layers.inet6 import (
9 IPv6,
10 ICMPv6EchoRequest,
11 ICMPv6EchoReply,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020012)
Dave Wallace8800f732023-08-31 00:47:44 -040013from scapy.layers.l2 import Ether, GRE
14from util import ppp
Ole Troan96068d62020-07-01 13:16:16 +020015from vpp_papi import VppEnum
16
17
Filip Vargaed2ee5e2021-03-23 12:57:58 +010018class TestNAT66(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020019 """NAT66 Test Cases"""
Ole Troan96068d62020-07-01 13:16:16 +020020
21 @classmethod
22 def setUpClass(cls):
23 super(TestNAT66, cls).setUpClass()
24
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020025 cls.nat_addr = "fd01:ff::2"
Ole Troan96068d62020-07-01 13:16:16 +020026 cls.create_pg_interfaces(range(2))
27 cls.interfaces = list(cls.pg_interfaces)
28
29 for i in cls.interfaces:
30 i.admin_up()
31 i.config_ip6()
32 i.configure_ipv6_neighbors()
33
Filip Vargaed2ee5e2021-03-23 12:57:58 +010034 @property
35 def config_flags(self):
36 return VppEnum.vl_api_nat_config_flags_t
37
38 def plugin_enable(self):
39 self.vapi.nat66_plugin_enable_disable(enable=1)
40
41 def plugin_disable(self):
42 self.vapi.nat66_plugin_enable_disable(enable=0)
43
44 def setUp(self):
45 super(TestNAT66, self).setUp()
46 self.plugin_enable()
47
48 def tearDown(self):
49 super(TestNAT66, self).tearDown()
50 if not self.vpp_dead:
51 self.plugin_disable()
Ole Troan96068d62020-07-01 13:16:16 +020052
53 def test_static(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020054 """1:1 NAT66 test"""
Ole Troan96068d62020-07-01 13:16:16 +020055 flags = self.config_flags.NAT_IS_INSIDE
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020056 self.vapi.nat66_add_del_interface(
57 is_add=1, flags=flags, sw_if_index=self.pg0.sw_if_index
58 )
59 self.vapi.nat66_add_del_interface(is_add=1, sw_if_index=self.pg1.sw_if_index)
Ole Troan96068d62020-07-01 13:16:16 +020060 self.vapi.nat66_add_del_static_mapping(
61 local_ip_address=self.pg0.remote_ip6,
62 external_ip_address=self.nat_addr,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020063 is_add=1,
64 )
Ole Troan96068d62020-07-01 13:16:16 +020065
66 # in2out
67 pkts = []
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020068 p = (
69 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
70 / IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6)
71 / TCP()
72 )
Ole Troan96068d62020-07-01 13:16:16 +020073 pkts.append(p)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020074 p = (
75 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
76 / IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6)
77 / UDP()
78 )
Ole Troan96068d62020-07-01 13:16:16 +020079 pkts.append(p)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020080 p = (
81 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
82 / IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6)
83 / ICMPv6EchoRequest()
84 )
Ole Troan96068d62020-07-01 13:16:16 +020085 pkts.append(p)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020086 p = (
87 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
88 / IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6)
89 / GRE()
90 / IP()
91 / TCP()
92 )
Ole Troan96068d62020-07-01 13:16:16 +020093 pkts.append(p)
94 self.pg0.add_stream(pkts)
95 self.pg_enable_capture(self.pg_interfaces)
96 self.pg_start()
97 capture = self.pg1.get_capture(len(pkts))
98
99 for packet in capture:
100 try:
101 self.assertEqual(packet[IPv6].src, self.nat_addr)
102 self.assertEqual(packet[IPv6].dst, self.pg1.remote_ip6)
103 self.assert_packet_checksums_valid(packet)
104 except:
105 self.logger.error(ppp("Unexpected or invalid packet:", packet))
106 raise
107
108 # out2in
109 pkts = []
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200110 p = (
111 Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac)
112 / IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr)
113 / TCP()
114 )
Ole Troan96068d62020-07-01 13:16:16 +0200115 pkts.append(p)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200116 p = (
117 Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac)
118 / IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr)
119 / UDP()
120 )
Ole Troan96068d62020-07-01 13:16:16 +0200121 pkts.append(p)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200122 p = (
123 Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac)
124 / IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr)
125 / ICMPv6EchoReply()
126 )
Ole Troan96068d62020-07-01 13:16:16 +0200127 pkts.append(p)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200128 p = (
129 Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac)
130 / IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr)
131 / GRE()
132 / IP()
133 / TCP()
134 )
Ole Troan96068d62020-07-01 13:16:16 +0200135 pkts.append(p)
136 self.pg1.add_stream(pkts)
137 self.pg_enable_capture(self.pg_interfaces)
138 self.pg_start()
139 capture = self.pg0.get_capture(len(pkts))
140 for packet in capture:
141 try:
142 self.assertEqual(packet[IPv6].src, self.pg1.remote_ip6)
143 self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
144 self.assert_packet_checksums_valid(packet)
145 except:
146 self.logger.error(ppp("Unexpected or invalid packet:", packet))
147 raise
148
149 sm = self.vapi.nat66_static_mapping_dump()
150 self.assertEqual(len(sm), 1)
151 self.assertEqual(sm[0].total_pkts, 8)
152
153 def test_check_no_translate(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200154 """NAT66 translate only when egress interface is outside interface"""
Ole Troan96068d62020-07-01 13:16:16 +0200155 flags = self.config_flags.NAT_IS_INSIDE
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200156 self.vapi.nat66_add_del_interface(
157 is_add=1, flags=flags, sw_if_index=self.pg0.sw_if_index
158 )
159 self.vapi.nat66_add_del_interface(
160 is_add=1, flags=flags, sw_if_index=self.pg1.sw_if_index
161 )
Ole Troan96068d62020-07-01 13:16:16 +0200162 self.vapi.nat66_add_del_static_mapping(
163 local_ip_address=self.pg0.remote_ip6,
164 external_ip_address=self.nat_addr,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200165 is_add=1,
166 )
Ole Troan96068d62020-07-01 13:16:16 +0200167
168 # in2out
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200169 p = (
170 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
171 / IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6)
172 / UDP()
173 )
Ole Troan96068d62020-07-01 13:16:16 +0200174 self.pg0.add_stream([p])
175 self.pg_enable_capture(self.pg_interfaces)
176 self.pg_start()
177 capture = self.pg1.get_capture(1)
178 packet = capture[0]
179 try:
180 self.assertEqual(packet[IPv6].src, self.pg0.remote_ip6)
181 self.assertEqual(packet[IPv6].dst, self.pg1.remote_ip6)
182 except:
183 self.logger.error(ppp("Unexpected or invalid packet:", packet))
184 raise
185
Ole Troan96068d62020-07-01 13:16:16 +0200186
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200187if __name__ == "__main__":
Ole Troan96068d62020-07-01 13:16:16 +0200188 unittest.main(testRunner=VppTestRunner)