blob: d3d6d07457bf998684383140f31a8f720f1dc23c [file] [log] [blame]
Filip Varga18f1e412020-12-03 15:27:40 +01001#!/usr/bin/env python3
2
3import unittest
4from io import BytesIO
Klement Sekeraad3187f2022-02-18 10:34:35 +00005from random import randint, choice
Filip Varga18f1e412020-12-03 15:27:40 +01006
Dmitry Valter6b97c432022-12-09 19:34:22 +00007import re
Filip Varga18f1e412020-12-03 15:27:40 +01008import scapy.compat
Dave Wallace8800f732023-08-31 00:47:44 -04009from framework import VppTestCase, VppLoInterface
10from asfframework import VppTestRunner, tag_fixme_ubuntu2204, is_distro_ubuntu2204
Filip Varga18f1e412020-12-03 15:27:40 +010011from scapy.data import IP_PROTOS
12from scapy.layers.inet import IP, TCP, UDP, ICMP, GRE
13from scapy.layers.inet import IPerror, TCPerror
14from scapy.layers.l2 import Ether
15from scapy.packet import Raw
Vladislav Grishenko579a6fb2023-03-16 19:31:00 +050016from statistics import variance
Filip Varga18f1e412020-12-03 15:27:40 +010017from syslog_rfc5424_parser import SyslogMessage, ParseError
18from syslog_rfc5424_parser.constants import SyslogSeverity
Klement Sekerac2feb652022-03-08 20:13:57 +010019from util import ppp, pr, ip4_range
Filip Varga18f1e412020-12-03 15:27:40 +010020from vpp_acl import AclRule, VppAcl, VppAclInterface
21from vpp_ip_route import VppIpRoute, VppRoutePath
22from vpp_papi import VppEnum
Klement Sekeraad3187f2022-02-18 10:34:35 +000023from util import StatsDiff
Filip Varga18f1e412020-12-03 15:27:40 +010024
25
Klement Sekeraff334db2021-05-26 13:02:35 +020026class TestNAT44ED(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020027 """NAT44ED Test Case"""
Filip Varga18f1e412020-12-03 15:27:40 +010028
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020029 nat_addr = "10.0.10.3"
Filip Varga18f1e412020-12-03 15:27:40 +010030
31 tcp_port_in = 6303
32 tcp_port_out = 6303
33
34 udp_port_in = 6304
35 udp_port_out = 6304
36
37 icmp_id_in = 6305
38 icmp_id_out = 6305
39
40 tcp_external_port = 80
41
42 max_sessions = 100
43
44 def setUp(self):
Klement Sekeraff334db2021-05-26 13:02:35 +020045 super().setUp()
Filip Varga18f1e412020-12-03 15:27:40 +010046 self.plugin_enable()
47
48 def tearDown(self):
Klement Sekeraff334db2021-05-26 13:02:35 +020049 super().tearDown()
Filip Varga18f1e412020-12-03 15:27:40 +010050 if not self.vpp_dead:
51 self.plugin_disable()
52
Dmitry Valter6b97c432022-12-09 19:34:22 +000053 def plugin_enable(self, max_sessions=None):
54 max_sessions = max_sessions or self.max_sessions
55 self.vapi.nat44_ed_plugin_enable_disable(sessions=max_sessions, enable=1)
Filip Varga18f1e412020-12-03 15:27:40 +010056
57 def plugin_disable(self):
Filip Vargae7a80a92021-02-26 09:31:21 +010058 self.vapi.nat44_ed_plugin_enable_disable(enable=0)
Filip Varga18f1e412020-12-03 15:27:40 +010059
60 @property
61 def config_flags(self):
62 return VppEnum.vl_api_nat_config_flags_t
63
64 @property
65 def nat44_config_flags(self):
66 return VppEnum.vl_api_nat44_config_flags_t
67
68 @property
69 def syslog_severity(self):
70 return VppEnum.vl_api_syslog_severity_t
71
72 @property
73 def server_addr(self):
74 return self.pg1.remote_hosts[0].ip4
75
76 @staticmethod
77 def random_port():
Vladislav Grishenko5f694d12022-08-19 20:42:22 +050078 return randint(1024, 65535)
Filip Varga18f1e412020-12-03 15:27:40 +010079
80 @staticmethod
81 def proto2layer(proto):
82 if proto == IP_PROTOS.tcp:
83 return TCP
84 elif proto == IP_PROTOS.udp:
85 return UDP
86 elif proto == IP_PROTOS.icmp:
87 return ICMP
88 else:
89 raise Exception("Unsupported protocol")
90
91 @classmethod
92 def create_and_add_ip4_table(cls, i, table_id=0):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020093 cls.vapi.ip_table_add_del(is_add=1, table={"table_id": table_id})
Filip Varga18f1e412020-12-03 15:27:40 +010094 i.set_table_ip4(table_id)
95
96 @classmethod
97 def configure_ip4_interface(cls, i, hosts=0, table_id=None):
98 if table_id:
99 cls.create_and_add_ip4_table(i, table_id)
100
101 i.admin_up()
Filip Varga18f1e412020-12-03 15:27:40 +0100102 i.config_ip4()
103 i.resolve_arp()
104
105 if hosts:
106 i.generate_remote_hosts(hosts)
107 i.configure_ipv4_neighbors()
108
109 @classmethod
110 def nat_add_interface_address(cls, i):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200111 cls.vapi.nat44_add_del_interface_addr(sw_if_index=i.sw_if_index, is_add=1)
Filip Varga18f1e412020-12-03 15:27:40 +0100112
113 def nat_add_inside_interface(self, i):
114 self.vapi.nat44_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200115 flags=self.config_flags.NAT_IS_INSIDE, sw_if_index=i.sw_if_index, is_add=1
116 )
Filip Varga18f1e412020-12-03 15:27:40 +0100117
118 def nat_add_outside_interface(self, i):
119 self.vapi.nat44_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200120 flags=self.config_flags.NAT_IS_OUTSIDE, sw_if_index=i.sw_if_index, is_add=1
121 )
Filip Varga18f1e412020-12-03 15:27:40 +0100122
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200123 def nat_add_address(self, address, twice_nat=0, vrf_id=0xFFFFFFFF, is_add=1):
Filip Varga18f1e412020-12-03 15:27:40 +0100124 flags = self.config_flags.NAT_IS_TWICE_NAT if twice_nat else 0
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200125 self.vapi.nat44_add_del_address_range(
126 first_ip_address=address,
127 last_ip_address=address,
128 vrf_id=vrf_id,
129 is_add=is_add,
130 flags=flags,
131 )
Filip Varga18f1e412020-12-03 15:27:40 +0100132
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200133 def nat_add_static_mapping(
134 self,
135 local_ip,
136 external_ip="0.0.0.0",
137 local_port=0,
138 external_port=0,
139 vrf_id=0,
140 is_add=1,
141 external_sw_if_index=0xFFFFFFFF,
142 proto=0,
143 tag="",
144 flags=0,
145 ):
Filip Varga18f1e412020-12-03 15:27:40 +0100146 if not (local_port and external_port):
147 flags |= self.config_flags.NAT_IS_ADDR_ONLY
148
149 self.vapi.nat44_add_del_static_mapping(
150 is_add=is_add,
151 local_ip_address=local_ip,
152 external_ip_address=external_ip,
153 external_sw_if_index=external_sw_if_index,
154 local_port=local_port,
155 external_port=external_port,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200156 vrf_id=vrf_id,
157 protocol=proto,
Filip Varga18f1e412020-12-03 15:27:40 +0100158 flags=flags,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200159 tag=tag,
160 )
Filip Varga18f1e412020-12-03 15:27:40 +0100161
162 @classmethod
163 def setUpClass(cls):
Klement Sekeraff334db2021-05-26 13:02:35 +0200164 super().setUpClass()
Filip Varga18f1e412020-12-03 15:27:40 +0100165
166 cls.create_pg_interfaces(range(12))
167 cls.interfaces = list(cls.pg_interfaces[:4])
168
169 cls.create_and_add_ip4_table(cls.pg2, 10)
170
171 for i in cls.interfaces:
172 cls.configure_ip4_interface(i, hosts=3)
173
174 # test specific (test-multiple-vrf)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200175 cls.vapi.ip_table_add_del(is_add=1, table={"table_id": 1})
Filip Varga18f1e412020-12-03 15:27:40 +0100176
177 # test specific (test-one-armed-nat44-static)
178 cls.pg4.generate_remote_hosts(2)
179 cls.pg4.config_ip4()
180 cls.vapi.sw_interface_add_del_address(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200181 sw_if_index=cls.pg4.sw_if_index, prefix="10.0.0.1/24"
182 )
Filip Varga18f1e412020-12-03 15:27:40 +0100183 cls.pg4.admin_up()
184 cls.pg4.resolve_arp()
185 cls.pg4._remote_hosts[1]._ip4 = cls.pg4._remote_hosts[0]._ip4
186 cls.pg4.resolve_arp()
187
188 # test specific interface (pg5)
189 cls.pg5._local_ip4 = "10.1.1.1"
190 cls.pg5._remote_hosts[0]._ip4 = "10.1.1.2"
191 cls.pg5.set_table_ip4(1)
192 cls.pg5.config_ip4()
193 cls.pg5.admin_up()
194 cls.pg5.resolve_arp()
195
196 # test specific interface (pg6)
197 cls.pg6._local_ip4 = "10.1.2.1"
198 cls.pg6._remote_hosts[0]._ip4 = "10.1.2.2"
199 cls.pg6.set_table_ip4(1)
200 cls.pg6.config_ip4()
201 cls.pg6.admin_up()
202 cls.pg6.resolve_arp()
203
204 rl = list()
205
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200206 rl.append(
207 VppIpRoute(
208 cls,
209 "0.0.0.0",
210 0,
211 [VppRoutePath("0.0.0.0", 0xFFFFFFFF, nh_table_id=0)],
212 register=False,
213 table_id=1,
214 )
215 )
216 rl.append(
217 VppIpRoute(
218 cls,
219 "0.0.0.0",
220 0,
221 [VppRoutePath(cls.pg1.local_ip4, cls.pg1.sw_if_index)],
222 register=False,
223 )
224 )
225 rl.append(
226 VppIpRoute(
227 cls,
228 cls.pg5.remote_ip4,
229 32,
230 [VppRoutePath("0.0.0.0", cls.pg5.sw_if_index)],
231 register=False,
232 table_id=1,
233 )
234 )
235 rl.append(
236 VppIpRoute(
237 cls,
238 cls.pg6.remote_ip4,
239 32,
240 [VppRoutePath("0.0.0.0", cls.pg6.sw_if_index)],
241 register=False,
242 table_id=1,
243 )
244 )
245 rl.append(
246 VppIpRoute(
247 cls,
248 cls.pg6.remote_ip4,
249 16,
250 [VppRoutePath("0.0.0.0", 0xFFFFFFFF, nh_table_id=1)],
251 register=False,
252 table_id=0,
253 )
254 )
Filip Varga18f1e412020-12-03 15:27:40 +0100255
256 for r in rl:
257 r.add_vpp_config()
258
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200259 cls.no_diff = StatsDiff(
260 {
261 pg.sw_if_index: {
262 "/nat44-ed/in2out/fastpath/tcp": 0,
263 "/nat44-ed/in2out/fastpath/udp": 0,
264 "/nat44-ed/in2out/fastpath/icmp": 0,
265 "/nat44-ed/in2out/fastpath/drops": 0,
266 "/nat44-ed/in2out/slowpath/tcp": 0,
267 "/nat44-ed/in2out/slowpath/udp": 0,
268 "/nat44-ed/in2out/slowpath/icmp": 0,
269 "/nat44-ed/in2out/slowpath/drops": 0,
270 "/nat44-ed/in2out/fastpath/tcp": 0,
271 "/nat44-ed/in2out/fastpath/udp": 0,
272 "/nat44-ed/in2out/fastpath/icmp": 0,
273 "/nat44-ed/in2out/fastpath/drops": 0,
274 "/nat44-ed/in2out/slowpath/tcp": 0,
275 "/nat44-ed/in2out/slowpath/udp": 0,
276 "/nat44-ed/in2out/slowpath/icmp": 0,
277 "/nat44-ed/in2out/slowpath/drops": 0,
278 }
279 for pg in cls.pg_interfaces
Klement Sekeraad3187f2022-02-18 10:34:35 +0000280 }
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200281 )
Klement Sekeraad3187f2022-02-18 10:34:35 +0000282
Filip Varga18f1e412020-12-03 15:27:40 +0100283 def get_err_counter(self, path):
284 return self.statistics.get_err_counter(path)
285
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200286 def reass_hairpinning(
287 self,
288 server_addr,
289 server_in_port,
290 server_out_port,
291 host_in_port,
292 proto=IP_PROTOS.tcp,
293 ignore_port=False,
294 ):
Filip Varga18f1e412020-12-03 15:27:40 +0100295 layer = self.proto2layer(proto)
296
297 if proto == IP_PROTOS.tcp:
298 data = b"A" * 4 + b"B" * 16 + b"C" * 3
299 else:
300 data = b"A" * 16 + b"B" * 16 + b"C" * 3
301
302 # send packet from host to server
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200303 pkts = self.create_stream_frag(
304 self.pg0, self.nat_addr, host_in_port, server_out_port, data, proto
305 )
Filip Varga18f1e412020-12-03 15:27:40 +0100306 self.pg0.add_stream(pkts)
307 self.pg_enable_capture(self.pg_interfaces)
308 self.pg_start()
309 frags = self.pg0.get_capture(len(pkts))
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200310 p = self.reass_frags_and_verify(frags, self.nat_addr, server_addr)
Filip Varga18f1e412020-12-03 15:27:40 +0100311 if proto != IP_PROTOS.icmp:
312 if not ignore_port:
313 self.assertNotEqual(p[layer].sport, host_in_port)
314 self.assertEqual(p[layer].dport, server_in_port)
315 else:
316 if not ignore_port:
317 self.assertNotEqual(p[layer].id, host_in_port)
318 self.assertEqual(data, p[Raw].load)
319
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200320 def frag_out_of_order(
321 self, proto=IP_PROTOS.tcp, dont_translate=False, ignore_port=False
322 ):
Filip Varga18f1e412020-12-03 15:27:40 +0100323 layer = self.proto2layer(proto)
324
325 if proto == IP_PROTOS.tcp:
326 data = b"A" * 4 + b"B" * 16 + b"C" * 3
327 else:
328 data = b"A" * 16 + b"B" * 16 + b"C" * 3
329 self.port_in = self.random_port()
330
331 for i in range(2):
332 # in2out
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200333 pkts = self.create_stream_frag(
334 self.pg0, self.pg1.remote_ip4, self.port_in, 20, data, proto
335 )
Filip Varga18f1e412020-12-03 15:27:40 +0100336 pkts.reverse()
337 self.pg0.add_stream(pkts)
338 self.pg_enable_capture(self.pg_interfaces)
339 self.pg_start()
340 frags = self.pg1.get_capture(len(pkts))
341 if not dont_translate:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200342 p = self.reass_frags_and_verify(
343 frags, self.nat_addr, self.pg1.remote_ip4
344 )
Filip Varga18f1e412020-12-03 15:27:40 +0100345 else:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200346 p = self.reass_frags_and_verify(
347 frags, self.pg0.remote_ip4, self.pg1.remote_ip4
348 )
Filip Varga18f1e412020-12-03 15:27:40 +0100349 if proto != IP_PROTOS.icmp:
350 if not dont_translate:
351 self.assertEqual(p[layer].dport, 20)
352 if not ignore_port:
353 self.assertNotEqual(p[layer].sport, self.port_in)
354 else:
355 self.assertEqual(p[layer].sport, self.port_in)
356 else:
357 if not ignore_port:
358 if not dont_translate:
359 self.assertNotEqual(p[layer].id, self.port_in)
360 else:
361 self.assertEqual(p[layer].id, self.port_in)
362 self.assertEqual(data, p[Raw].load)
363
364 # out2in
365 if not dont_translate:
366 dst_addr = self.nat_addr
367 else:
368 dst_addr = self.pg0.remote_ip4
369 if proto != IP_PROTOS.icmp:
370 sport = 20
371 dport = p[layer].sport
372 else:
373 sport = p[layer].id
374 dport = 0
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200375 pkts = self.create_stream_frag(
376 self.pg1, dst_addr, sport, dport, data, proto, echo_reply=True
377 )
Filip Varga18f1e412020-12-03 15:27:40 +0100378 pkts.reverse()
379 self.pg1.add_stream(pkts)
380 self.pg_enable_capture(self.pg_interfaces)
Klement Sekerae79bbe92021-03-04 18:41:02 +0100381 self.logger.info(self.vapi.cli("show trace"))
Filip Varga18f1e412020-12-03 15:27:40 +0100382 self.pg_start()
383 frags = self.pg0.get_capture(len(pkts))
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200384 p = self.reass_frags_and_verify(
385 frags, self.pg1.remote_ip4, self.pg0.remote_ip4
386 )
Filip Varga18f1e412020-12-03 15:27:40 +0100387 if proto != IP_PROTOS.icmp:
388 self.assertEqual(p[layer].sport, 20)
389 self.assertEqual(p[layer].dport, self.port_in)
390 else:
391 self.assertEqual(p[layer].id, self.port_in)
392 self.assertEqual(data, p[Raw].load)
393
394 def reass_frags_and_verify(self, frags, src, dst):
395 buffer = BytesIO()
396 for p in frags:
397 self.assertEqual(p[IP].src, src)
398 self.assertEqual(p[IP].dst, dst)
399 self.assert_ip_checksum_valid(p)
400 buffer.seek(p[IP].frag * 8)
401 buffer.write(bytes(p[IP].payload))
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200402 ip = IP(src=frags[0][IP].src, dst=frags[0][IP].dst, proto=frags[0][IP].proto)
Filip Varga18f1e412020-12-03 15:27:40 +0100403 if ip.proto == IP_PROTOS.tcp:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200404 p = ip / TCP(buffer.getvalue())
Filip Varga18f1e412020-12-03 15:27:40 +0100405 self.logger.debug(ppp("Reassembled:", p))
406 self.assert_tcp_checksum_valid(p)
407 elif ip.proto == IP_PROTOS.udp:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200408 p = ip / UDP(buffer.getvalue()[:8]) / Raw(buffer.getvalue()[8:])
Filip Varga18f1e412020-12-03 15:27:40 +0100409 elif ip.proto == IP_PROTOS.icmp:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200410 p = ip / ICMP(buffer.getvalue())
Filip Varga18f1e412020-12-03 15:27:40 +0100411 return p
412
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200413 def frag_in_order(
414 self, proto=IP_PROTOS.tcp, dont_translate=False, ignore_port=False
415 ):
Filip Varga18f1e412020-12-03 15:27:40 +0100416 layer = self.proto2layer(proto)
417
418 if proto == IP_PROTOS.tcp:
419 data = b"A" * 4 + b"B" * 16 + b"C" * 3
420 else:
421 data = b"A" * 16 + b"B" * 16 + b"C" * 3
422 self.port_in = self.random_port()
423
424 # in2out
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200425 pkts = self.create_stream_frag(
426 self.pg0, self.pg1.remote_ip4, self.port_in, 20, data, proto
427 )
Filip Varga18f1e412020-12-03 15:27:40 +0100428 self.pg0.add_stream(pkts)
429 self.pg_enable_capture(self.pg_interfaces)
430 self.pg_start()
431 frags = self.pg1.get_capture(len(pkts))
432 if not dont_translate:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200433 p = self.reass_frags_and_verify(frags, self.nat_addr, self.pg1.remote_ip4)
Filip Varga18f1e412020-12-03 15:27:40 +0100434 else:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200435 p = self.reass_frags_and_verify(
436 frags, self.pg0.remote_ip4, self.pg1.remote_ip4
437 )
Filip Varga18f1e412020-12-03 15:27:40 +0100438 if proto != IP_PROTOS.icmp:
439 if not dont_translate:
440 self.assertEqual(p[layer].dport, 20)
441 if not ignore_port:
442 self.assertNotEqual(p[layer].sport, self.port_in)
443 else:
444 self.assertEqual(p[layer].sport, self.port_in)
445 else:
446 if not ignore_port:
447 if not dont_translate:
448 self.assertNotEqual(p[layer].id, self.port_in)
449 else:
450 self.assertEqual(p[layer].id, self.port_in)
451 self.assertEqual(data, p[Raw].load)
452
453 # out2in
454 if not dont_translate:
455 dst_addr = self.nat_addr
456 else:
457 dst_addr = self.pg0.remote_ip4
458 if proto != IP_PROTOS.icmp:
459 sport = 20
460 dport = p[layer].sport
461 else:
462 sport = p[layer].id
463 dport = 0
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200464 pkts = self.create_stream_frag(
465 self.pg1, dst_addr, sport, dport, data, proto, echo_reply=True
466 )
Filip Varga18f1e412020-12-03 15:27:40 +0100467 self.pg1.add_stream(pkts)
468 self.pg_enable_capture(self.pg_interfaces)
469 self.pg_start()
470 frags = self.pg0.get_capture(len(pkts))
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200471 p = self.reass_frags_and_verify(frags, self.pg1.remote_ip4, self.pg0.remote_ip4)
Filip Varga18f1e412020-12-03 15:27:40 +0100472 if proto != IP_PROTOS.icmp:
473 self.assertEqual(p[layer].sport, 20)
474 self.assertEqual(p[layer].dport, self.port_in)
475 else:
476 self.assertEqual(p[layer].id, self.port_in)
477 self.assertEqual(data, p[Raw].load)
478
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200479 def verify_capture_out(
480 self, capture, nat_ip=None, same_port=False, dst_ip=None, ignore_port=False
481 ):
Filip Varga18f1e412020-12-03 15:27:40 +0100482 if nat_ip is None:
483 nat_ip = self.nat_addr
484 for packet in capture:
485 try:
486 self.assert_packet_checksums_valid(packet)
487 self.assertEqual(packet[IP].src, nat_ip)
488 if dst_ip is not None:
489 self.assertEqual(packet[IP].dst, dst_ip)
490 if packet.haslayer(TCP):
491 if not ignore_port:
492 if same_port:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200493 self.assertEqual(packet[TCP].sport, self.tcp_port_in)
Filip Varga18f1e412020-12-03 15:27:40 +0100494 else:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200495 self.assertNotEqual(packet[TCP].sport, self.tcp_port_in)
Filip Varga18f1e412020-12-03 15:27:40 +0100496 self.tcp_port_out = packet[TCP].sport
497 self.assert_packet_checksums_valid(packet)
498 elif packet.haslayer(UDP):
499 if not ignore_port:
500 if same_port:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200501 self.assertEqual(packet[UDP].sport, self.udp_port_in)
Filip Varga18f1e412020-12-03 15:27:40 +0100502 else:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200503 self.assertNotEqual(packet[UDP].sport, self.udp_port_in)
Filip Varga18f1e412020-12-03 15:27:40 +0100504 self.udp_port_out = packet[UDP].sport
505 else:
506 if not ignore_port:
507 if same_port:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200508 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
Filip Varga18f1e412020-12-03 15:27:40 +0100509 else:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200510 self.assertNotEqual(packet[ICMP].id, self.icmp_id_in)
Filip Varga18f1e412020-12-03 15:27:40 +0100511 self.icmp_id_out = packet[ICMP].id
512 self.assert_packet_checksums_valid(packet)
513 except:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200514 self.logger.error(
515 ppp("Unexpected or invalid packet (outside network):", packet)
516 )
Filip Varga18f1e412020-12-03 15:27:40 +0100517 raise
518
519 def verify_capture_in(self, capture, in_if):
520 for packet in capture:
521 try:
522 self.assert_packet_checksums_valid(packet)
523 self.assertEqual(packet[IP].dst, in_if.remote_ip4)
524 if packet.haslayer(TCP):
525 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
526 elif packet.haslayer(UDP):
527 self.assertEqual(packet[UDP].dport, self.udp_port_in)
528 else:
529 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
530 except:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200531 self.logger.error(
532 ppp("Unexpected or invalid packet (inside network):", packet)
533 )
Filip Varga18f1e412020-12-03 15:27:40 +0100534 raise
535
536 def create_stream_in(self, in_if, out_if, dst_ip=None, ttl=64):
537 if dst_ip is None:
538 dst_ip = out_if.remote_ip4
539
540 pkts = []
541 # TCP
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200542 p = (
543 Ether(dst=in_if.local_mac, src=in_if.remote_mac)
544 / IP(src=in_if.remote_ip4, dst=dst_ip, ttl=ttl)
545 / TCP(sport=self.tcp_port_in, dport=20)
546 )
Filip Varga18f1e412020-12-03 15:27:40 +0100547 pkts.extend([p, p])
548
549 # UDP
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200550 p = (
551 Ether(dst=in_if.local_mac, src=in_if.remote_mac)
552 / IP(src=in_if.remote_ip4, dst=dst_ip, ttl=ttl)
553 / UDP(sport=self.udp_port_in, dport=20)
554 )
Filip Varga18f1e412020-12-03 15:27:40 +0100555 pkts.append(p)
556
557 # ICMP
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200558 p = (
559 Ether(dst=in_if.local_mac, src=in_if.remote_mac)
560 / IP(src=in_if.remote_ip4, dst=dst_ip, ttl=ttl)
561 / ICMP(id=self.icmp_id_in, type="echo-request")
562 )
Filip Varga18f1e412020-12-03 15:27:40 +0100563 pkts.append(p)
564
565 return pkts
566
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200567 def create_stream_out(self, out_if, dst_ip=None, ttl=64, use_inside_ports=False):
Filip Varga18f1e412020-12-03 15:27:40 +0100568 if dst_ip is None:
569 dst_ip = self.nat_addr
570 if not use_inside_ports:
571 tcp_port = self.tcp_port_out
572 udp_port = self.udp_port_out
573 icmp_id = self.icmp_id_out
574 else:
575 tcp_port = self.tcp_port_in
576 udp_port = self.udp_port_in
577 icmp_id = self.icmp_id_in
578 pkts = []
579 # TCP
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200580 p = (
581 Ether(dst=out_if.local_mac, src=out_if.remote_mac)
582 / IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl)
583 / TCP(dport=tcp_port, sport=20)
584 )
Filip Varga18f1e412020-12-03 15:27:40 +0100585 pkts.extend([p, p])
586
587 # UDP
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200588 p = (
589 Ether(dst=out_if.local_mac, src=out_if.remote_mac)
590 / IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl)
591 / UDP(dport=udp_port, sport=20)
592 )
Filip Varga18f1e412020-12-03 15:27:40 +0100593 pkts.append(p)
594
595 # ICMP
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200596 p = (
597 Ether(dst=out_if.local_mac, src=out_if.remote_mac)
598 / IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl)
599 / ICMP(id=icmp_id, type="echo-reply")
600 )
Filip Varga18f1e412020-12-03 15:27:40 +0100601 pkts.append(p)
602
603 return pkts
604
605 def create_tcp_stream(self, in_if, out_if, count):
606 pkts = []
607 port = 6303
608
609 for i in range(count):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200610 p = (
611 Ether(dst=in_if.local_mac, src=in_if.remote_mac)
612 / IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=64)
613 / TCP(sport=port + i, dport=20)
614 )
Filip Varga18f1e412020-12-03 15:27:40 +0100615 pkts.append(p)
616
617 return pkts
618
Dmitry Valter6b97c432022-12-09 19:34:22 +0000619 def create_udp_stream(self, in_if, out_if, count, base_port=6303):
620 return [
621 (
622 Ether(dst=in_if.local_mac, src=in_if.remote_mac)
623 / IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=64)
624 / UDP(sport=base_port + i, dport=20)
625 )
626 for i in range(count)
627 ]
628
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200629 def create_stream_frag(
630 self, src_if, dst, sport, dport, data, proto=IP_PROTOS.tcp, echo_reply=False
631 ):
Filip Varga18f1e412020-12-03 15:27:40 +0100632 if proto == IP_PROTOS.tcp:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200633 p = (
634 IP(src=src_if.remote_ip4, dst=dst)
635 / TCP(sport=sport, dport=dport)
636 / Raw(data)
637 )
Filip Varga18f1e412020-12-03 15:27:40 +0100638 p = p.__class__(scapy.compat.raw(p))
639 chksum = p[TCP].chksum
640 proto_header = TCP(sport=sport, dport=dport, chksum=chksum)
641 elif proto == IP_PROTOS.udp:
642 proto_header = UDP(sport=sport, dport=dport)
643 elif proto == IP_PROTOS.icmp:
644 if not echo_reply:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200645 proto_header = ICMP(id=sport, type="echo-request")
Filip Varga18f1e412020-12-03 15:27:40 +0100646 else:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200647 proto_header = ICMP(id=sport, type="echo-reply")
Filip Varga18f1e412020-12-03 15:27:40 +0100648 else:
649 raise Exception("Unsupported protocol")
650 id = self.random_port()
651 pkts = []
652 if proto == IP_PROTOS.tcp:
653 raw = Raw(data[0:4])
654 else:
655 raw = Raw(data[0:16])
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200656 p = (
657 Ether(src=src_if.remote_mac, dst=src_if.local_mac)
658 / IP(src=src_if.remote_ip4, dst=dst, flags="MF", frag=0, id=id)
659 / proto_header
660 / raw
661 )
Filip Varga18f1e412020-12-03 15:27:40 +0100662 pkts.append(p)
663 if proto == IP_PROTOS.tcp:
664 raw = Raw(data[4:20])
665 else:
666 raw = Raw(data[16:32])
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200667 p = (
668 Ether(src=src_if.remote_mac, dst=src_if.local_mac)
669 / IP(src=src_if.remote_ip4, dst=dst, flags="MF", frag=3, id=id, proto=proto)
670 / raw
671 )
Filip Varga18f1e412020-12-03 15:27:40 +0100672 pkts.append(p)
673 if proto == IP_PROTOS.tcp:
674 raw = Raw(data[20:])
675 else:
676 raw = Raw(data[32:])
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200677 p = (
678 Ether(src=src_if.remote_mac, dst=src_if.local_mac)
679 / IP(src=src_if.remote_ip4, dst=dst, frag=5, proto=proto, id=id)
680 / raw
681 )
Filip Varga18f1e412020-12-03 15:27:40 +0100682 pkts.append(p)
683 return pkts
684
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200685 def frag_in_order_in_plus_out(
686 self, in_addr, out_addr, in_port, out_port, proto=IP_PROTOS.tcp
687 ):
Filip Varga18f1e412020-12-03 15:27:40 +0100688 layer = self.proto2layer(proto)
689
690 if proto == IP_PROTOS.tcp:
691 data = b"A" * 4 + b"B" * 16 + b"C" * 3
692 else:
693 data = b"A" * 16 + b"B" * 16 + b"C" * 3
694 port_in = self.random_port()
695
696 for i in range(2):
697 # out2in
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200698 pkts = self.create_stream_frag(
699 self.pg0, out_addr, port_in, out_port, data, proto
700 )
Filip Varga18f1e412020-12-03 15:27:40 +0100701 self.pg0.add_stream(pkts)
702 self.pg_enable_capture(self.pg_interfaces)
703 self.pg_start()
704 frags = self.pg1.get_capture(len(pkts))
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200705 p = self.reass_frags_and_verify(frags, self.pg0.remote_ip4, in_addr)
Filip Varga18f1e412020-12-03 15:27:40 +0100706 if proto != IP_PROTOS.icmp:
707 self.assertEqual(p[layer].sport, port_in)
708 self.assertEqual(p[layer].dport, in_port)
709 else:
710 self.assertEqual(p[layer].id, port_in)
711 self.assertEqual(data, p[Raw].load)
712
713 # in2out
714 if proto != IP_PROTOS.icmp:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200715 pkts = self.create_stream_frag(
716 self.pg1, self.pg0.remote_ip4, in_port, p[layer].sport, data, proto
717 )
Filip Varga18f1e412020-12-03 15:27:40 +0100718 else:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200719 pkts = self.create_stream_frag(
720 self.pg1,
721 self.pg0.remote_ip4,
722 p[layer].id,
723 0,
724 data,
725 proto,
726 echo_reply=True,
727 )
Filip Varga18f1e412020-12-03 15:27:40 +0100728 self.pg1.add_stream(pkts)
729 self.pg_enable_capture(self.pg_interfaces)
730 self.pg_start()
731 frags = self.pg0.get_capture(len(pkts))
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200732 p = self.reass_frags_and_verify(frags, out_addr, self.pg0.remote_ip4)
Filip Varga18f1e412020-12-03 15:27:40 +0100733 if proto != IP_PROTOS.icmp:
734 self.assertEqual(p[layer].sport, out_port)
735 self.assertEqual(p[layer].dport, port_in)
736 else:
737 self.assertEqual(p[layer].id, port_in)
738 self.assertEqual(data, p[Raw].load)
739
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200740 def frag_out_of_order_in_plus_out(
741 self, in_addr, out_addr, in_port, out_port, proto=IP_PROTOS.tcp
742 ):
Filip Varga18f1e412020-12-03 15:27:40 +0100743 layer = self.proto2layer(proto)
744
745 if proto == IP_PROTOS.tcp:
746 data = b"A" * 4 + b"B" * 16 + b"C" * 3
747 else:
748 data = b"A" * 16 + b"B" * 16 + b"C" * 3
749 port_in = self.random_port()
750
751 for i in range(2):
752 # out2in
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200753 pkts = self.create_stream_frag(
754 self.pg0, out_addr, port_in, out_port, data, proto
755 )
Filip Varga18f1e412020-12-03 15:27:40 +0100756 pkts.reverse()
757 self.pg0.add_stream(pkts)
758 self.pg_enable_capture(self.pg_interfaces)
759 self.pg_start()
760 frags = self.pg1.get_capture(len(pkts))
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200761 p = self.reass_frags_and_verify(frags, self.pg0.remote_ip4, in_addr)
Filip Varga18f1e412020-12-03 15:27:40 +0100762 if proto != IP_PROTOS.icmp:
763 self.assertEqual(p[layer].dport, in_port)
764 self.assertEqual(p[layer].sport, port_in)
765 self.assertEqual(p[layer].dport, in_port)
766 else:
767 self.assertEqual(p[layer].id, port_in)
768 self.assertEqual(data, p[Raw].load)
769
770 # in2out
771 if proto != IP_PROTOS.icmp:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200772 pkts = self.create_stream_frag(
773 self.pg1, self.pg0.remote_ip4, in_port, p[layer].sport, data, proto
774 )
Filip Varga18f1e412020-12-03 15:27:40 +0100775 else:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200776 pkts = self.create_stream_frag(
777 self.pg1,
778 self.pg0.remote_ip4,
779 p[layer].id,
780 0,
781 data,
782 proto,
783 echo_reply=True,
784 )
Filip Varga18f1e412020-12-03 15:27:40 +0100785 pkts.reverse()
786 self.pg1.add_stream(pkts)
787 self.pg_enable_capture(self.pg_interfaces)
788 self.pg_start()
789 frags = self.pg0.get_capture(len(pkts))
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200790 p = self.reass_frags_and_verify(frags, out_addr, self.pg0.remote_ip4)
Filip Varga18f1e412020-12-03 15:27:40 +0100791 if proto != IP_PROTOS.icmp:
792 self.assertEqual(p[layer].sport, out_port)
793 self.assertEqual(p[layer].dport, port_in)
794 else:
795 self.assertEqual(p[layer].id, port_in)
796 self.assertEqual(data, p[Raw].load)
797
798 def init_tcp_session(self, in_if, out_if, in_port, ext_port):
799 # SYN packet in->out
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200800 p = (
801 Ether(src=in_if.remote_mac, dst=in_if.local_mac)
802 / IP(src=in_if.remote_ip4, dst=out_if.remote_ip4)
803 / TCP(sport=in_port, dport=ext_port, flags="S")
804 )
Filip Varga18f1e412020-12-03 15:27:40 +0100805 in_if.add_stream(p)
806 self.pg_enable_capture(self.pg_interfaces)
807 self.pg_start()
808 capture = out_if.get_capture(1)
809 p = capture[0]
810 out_port = p[TCP].sport
811
812 # SYN + ACK packet out->in
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200813 p = (
814 Ether(src=out_if.remote_mac, dst=out_if.local_mac)
815 / IP(src=out_if.remote_ip4, dst=self.nat_addr)
816 / TCP(sport=ext_port, dport=out_port, flags="SA")
817 )
Filip Varga18f1e412020-12-03 15:27:40 +0100818 out_if.add_stream(p)
819 self.pg_enable_capture(self.pg_interfaces)
820 self.pg_start()
821 in_if.get_capture(1)
822
823 # ACK packet in->out
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200824 p = (
825 Ether(src=in_if.remote_mac, dst=in_if.local_mac)
826 / IP(src=in_if.remote_ip4, dst=out_if.remote_ip4)
827 / TCP(sport=in_port, dport=ext_port, flags="A")
828 )
Filip Varga18f1e412020-12-03 15:27:40 +0100829 in_if.add_stream(p)
830 self.pg_enable_capture(self.pg_interfaces)
831 self.pg_start()
832 out_if.get_capture(1)
833
834 return out_port
835
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200836 def twice_nat_common(
837 self, self_twice_nat=False, same_pg=False, lb=False, client_id=None
838 ):
839 twice_nat_addr = "10.0.1.3"
Filip Varga18f1e412020-12-03 15:27:40 +0100840
841 port_in = 8080
842 if lb:
843 if not same_pg:
844 port_in1 = port_in
845 port_in2 = port_in
846 else:
847 port_in1 = port_in + 1
848 port_in2 = port_in + 2
849
850 port_out = 80
851 eh_port_out = 4567
852
853 server1 = self.pg0.remote_hosts[0]
854 server2 = self.pg0.remote_hosts[1]
855 if lb and same_pg:
856 server2 = server1
857 if not lb:
858 server = server1
859
860 pg0 = self.pg0
861 if same_pg:
862 pg1 = self.pg0
863 else:
864 pg1 = self.pg1
865
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200866 eh_translate = (not self_twice_nat) or (not lb and same_pg) or client_id == 1
Filip Varga18f1e412020-12-03 15:27:40 +0100867
868 self.nat_add_address(self.nat_addr)
869 self.nat_add_address(twice_nat_addr, twice_nat=1)
870
871 flags = 0
872 if self_twice_nat:
873 flags |= self.config_flags.NAT_IS_SELF_TWICE_NAT
874 else:
875 flags |= self.config_flags.NAT_IS_TWICE_NAT
876
877 if not lb:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200878 self.nat_add_static_mapping(
879 pg0.remote_ip4,
880 self.nat_addr,
881 port_in,
882 port_out,
883 proto=IP_PROTOS.tcp,
884 flags=flags,
885 )
Filip Varga18f1e412020-12-03 15:27:40 +0100886 else:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200887 locals = [
888 {"addr": server1.ip4, "port": port_in1, "probability": 50, "vrf_id": 0},
889 {"addr": server2.ip4, "port": port_in2, "probability": 50, "vrf_id": 0},
890 ]
Filip Varga18f1e412020-12-03 15:27:40 +0100891 out_addr = self.nat_addr
892
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200893 self.vapi.nat44_add_del_lb_static_mapping(
894 is_add=1,
895 flags=flags,
896 external_addr=out_addr,
897 external_port=port_out,
898 protocol=IP_PROTOS.tcp,
899 local_num=len(locals),
900 locals=locals,
901 )
Filip Varga18f1e412020-12-03 15:27:40 +0100902 self.nat_add_inside_interface(pg0)
903 self.nat_add_outside_interface(pg1)
904
905 if same_pg:
906 if not lb:
907 client = server
908 else:
909 assert client_id is not None
910 if client_id == 1:
911 client = self.pg0.remote_hosts[0]
912 elif client_id == 2:
913 client = self.pg0.remote_hosts[1]
914 else:
915 client = pg1.remote_hosts[0]
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200916 p = (
917 Ether(src=pg1.remote_mac, dst=pg1.local_mac)
918 / IP(src=client.ip4, dst=self.nat_addr)
919 / TCP(sport=eh_port_out, dport=port_out)
920 )
Filip Varga18f1e412020-12-03 15:27:40 +0100921 pg1.add_stream(p)
922 self.pg_enable_capture(self.pg_interfaces)
923 self.pg_start()
924 capture = pg0.get_capture(1)
925 p = capture[0]
926 try:
927 ip = p[IP]
928 tcp = p[TCP]
929 if lb:
930 if ip.dst == server1.ip4:
931 server = server1
932 port_in = port_in1
933 else:
934 server = server2
935 port_in = port_in2
936 self.assertEqual(ip.dst, server.ip4)
937 if lb and same_pg:
938 self.assertIn(tcp.dport, [port_in1, port_in2])
939 else:
940 self.assertEqual(tcp.dport, port_in)
941 if eh_translate:
942 self.assertEqual(ip.src, twice_nat_addr)
943 self.assertNotEqual(tcp.sport, eh_port_out)
944 else:
945 self.assertEqual(ip.src, client.ip4)
946 self.assertEqual(tcp.sport, eh_port_out)
947 eh_addr_in = ip.src
948 eh_port_in = tcp.sport
949 saved_port_in = tcp.dport
950 self.assert_packet_checksums_valid(p)
951 except:
952 self.logger.error(ppp("Unexpected or invalid packet:", p))
953 raise
954
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200955 p = (
956 Ether(src=server.mac, dst=pg0.local_mac)
957 / IP(src=server.ip4, dst=eh_addr_in)
958 / TCP(sport=saved_port_in, dport=eh_port_in)
959 )
Filip Varga18f1e412020-12-03 15:27:40 +0100960 pg0.add_stream(p)
961 self.pg_enable_capture(self.pg_interfaces)
962 self.pg_start()
963 capture = pg1.get_capture(1)
964 p = capture[0]
965 try:
966 ip = p[IP]
967 tcp = p[TCP]
968 self.assertEqual(ip.dst, client.ip4)
969 self.assertEqual(ip.src, self.nat_addr)
970 self.assertEqual(tcp.dport, eh_port_out)
971 self.assertEqual(tcp.sport, port_out)
972 self.assert_packet_checksums_valid(p)
973 except:
974 self.logger.error(ppp("Unexpected or invalid packet:", p))
975 raise
976
977 if eh_translate:
978 sessions = self.vapi.nat44_user_session_dump(server.ip4, 0)
979 self.assertEqual(len(sessions), 1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200980 self.assertTrue(sessions[0].flags & self.config_flags.NAT_IS_EXT_HOST_VALID)
981 self.assertTrue(sessions[0].flags & self.config_flags.NAT_IS_TWICE_NAT)
Filip Varga0eaf4e62021-02-17 14:34:54 +0100982 self.logger.info(self.vapi.cli("show nat44 sessions"))
Filip Varga18f1e412020-12-03 15:27:40 +0100983 self.vapi.nat44_del_session(
984 address=sessions[0].inside_ip_address,
985 port=sessions[0].inside_port,
986 protocol=sessions[0].protocol,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200987 flags=(
988 self.config_flags.NAT_IS_INSIDE
989 | self.config_flags.NAT_IS_EXT_HOST_VALID
990 ),
Filip Varga18f1e412020-12-03 15:27:40 +0100991 ext_host_address=sessions[0].ext_host_nat_address,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200992 ext_host_port=sessions[0].ext_host_nat_port,
993 )
Filip Varga18f1e412020-12-03 15:27:40 +0100994 sessions = self.vapi.nat44_user_session_dump(server.ip4, 0)
995 self.assertEqual(len(sessions), 0)
996
Klement Sekera56c492a2022-01-10 21:57:27 +0000997 def verify_syslog_sess(self, data, msgid, is_ip6=False):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200998 message = data.decode("utf-8")
Filip Varga18f1e412020-12-03 15:27:40 +0100999 try:
1000 message = SyslogMessage.parse(message)
1001 except ParseError as e:
1002 self.logger.error(e)
1003 raise
1004 else:
1005 self.assertEqual(message.severity, SyslogSeverity.info)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001006 self.assertEqual(message.appname, "NAT")
Klement Sekera56c492a2022-01-10 21:57:27 +00001007 self.assertEqual(message.msgid, msgid)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001008 sd_params = message.sd.get("nsess")
Filip Varga18f1e412020-12-03 15:27:40 +01001009 self.assertTrue(sd_params is not None)
1010 if is_ip6:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001011 self.assertEqual(sd_params.get("IATYP"), "IPv6")
1012 self.assertEqual(sd_params.get("ISADDR"), self.pg0.remote_ip6)
Filip Varga18f1e412020-12-03 15:27:40 +01001013 else:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001014 self.assertEqual(sd_params.get("IATYP"), "IPv4")
1015 self.assertEqual(sd_params.get("ISADDR"), self.pg0.remote_ip4)
1016 self.assertTrue(sd_params.get("SSUBIX") is not None)
1017 self.assertEqual(sd_params.get("ISPORT"), "%d" % self.tcp_port_in)
1018 self.assertEqual(sd_params.get("XATYP"), "IPv4")
1019 self.assertEqual(sd_params.get("XSADDR"), self.nat_addr)
1020 self.assertEqual(sd_params.get("XSPORT"), "%d" % self.tcp_port_out)
1021 self.assertEqual(sd_params.get("PROTO"), "%d" % IP_PROTOS.tcp)
1022 self.assertEqual(sd_params.get("SVLAN"), "0")
1023 self.assertEqual(sd_params.get("XDADDR"), self.pg1.remote_ip4)
1024 self.assertEqual(sd_params.get("XDPORT"), "%d" % self.tcp_external_port)
Filip Varga18f1e412020-12-03 15:27:40 +01001025
Filip Vargaa0648b62021-06-21 12:59:41 +02001026 def test_icmp_error(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001027 """NAT44ED test ICMP error message with inner header"""
Filip Vargaa0648b62021-06-21 12:59:41 +02001028
1029 payload = "H" * 10
1030
1031 self.nat_add_address(self.nat_addr)
1032 self.nat_add_inside_interface(self.pg0)
1033 self.nat_add_outside_interface(self.pg1)
1034
1035 # in2out (initiate connection)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001036 p1 = [
1037 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
1038 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
1039 / UDP(sport=21, dport=20)
1040 / payload,
1041 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
1042 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
1043 / TCP(sport=21, dport=20, flags="S")
1044 / payload,
1045 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
1046 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
1047 / ICMP(type="echo-request", id=7777)
1048 / payload,
1049 ]
Filip Vargaa0648b62021-06-21 12:59:41 +02001050
Klement Sekerac2feb652022-03-08 20:13:57 +01001051 capture = self.send_and_expect(self.pg0, p1, self.pg1)
Filip Vargaa0648b62021-06-21 12:59:41 +02001052
1053 # out2in (send error message)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001054 p2 = [
1055 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
1056 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
1057 / ICMP(type="dest-unreach", code="port-unreachable")
1058 / c[IP:]
1059 for c in capture
1060 ]
Filip Vargaa0648b62021-06-21 12:59:41 +02001061
Klement Sekerac2feb652022-03-08 20:13:57 +01001062 capture = self.send_and_expect(self.pg1, p2, self.pg0)
Filip Vargaa0648b62021-06-21 12:59:41 +02001063
Klement Sekerac2feb652022-03-08 20:13:57 +01001064 for c in capture:
1065 try:
1066 assert c[IP].dst == self.pg0.remote_ip4
1067 assert c[IPerror].src == self.pg0.remote_ip4
1068 except AssertionError as a:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001069 raise AssertionError(f"Packet {pr(c)} not translated properly") from a
Filip Vargaa0648b62021-06-21 12:59:41 +02001070
Klement Sekera254c8032021-07-27 13:33:51 +02001071 def test_icmp_echo_reply_trailer(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001072 """ICMP echo reply with ethernet trailer"""
Klement Sekera254c8032021-07-27 13:33:51 +02001073
1074 self.nat_add_address(self.nat_addr)
1075 self.nat_add_inside_interface(self.pg0)
1076 self.nat_add_outside_interface(self.pg1)
1077
1078 # in2out
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001079 p1 = (
1080 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
1081 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
1082 / ICMP(type=8, id=0xABCD, seq=0)
1083 )
Klement Sekera254c8032021-07-27 13:33:51 +02001084
1085 self.pg0.add_stream(p1)
1086 self.pg_enable_capture(self.pg_interfaces)
1087 self.pg_start()
1088 c = self.pg1.get_capture(1)[0]
1089
1090 self.logger.debug(self.vapi.cli("show trace"))
1091
1092 # out2in
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001093 p2 = (
1094 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
1095 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr, id=0xEE59)
1096 / ICMP(type=0, id=c[ICMP].id, seq=0)
1097 )
Klement Sekera254c8032021-07-27 13:33:51 +02001098
1099 # force checksum calculation
1100 p2 = p2.__class__(bytes(p2))
1101
1102 self.logger.debug(ppp("Packet before modification:", p2))
1103
1104 # hex representation of vss monitoring ethernet trailer
1105 # this seems to be just added to end of packet without modifying
1106 # IP or ICMP lengths / checksums
1107 p2 = p2 / Raw("\x00\x00\x52\x54\x00\x46\xab\x04\x84\x18")
1108 # change it so that IP/ICMP is unaffected
1109 p2[IP].len = 28
1110
1111 self.logger.debug(ppp("Packet with added trailer:", p2))
1112
1113 self.pg1.add_stream(p2)
1114 self.pg_enable_capture(self.pg_interfaces)
1115 self.pg_start()
1116
1117 self.pg0.get_capture(1)
1118
Filip Varga18f1e412020-12-03 15:27:40 +01001119 def test_users_dump(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001120 """NAT44ED API test - nat44_user_dump"""
Filip Varga18f1e412020-12-03 15:27:40 +01001121
1122 self.nat_add_address(self.nat_addr)
1123 self.nat_add_inside_interface(self.pg0)
1124 self.nat_add_outside_interface(self.pg1)
1125
1126 self.vapi.nat44_forwarding_enable_disable(enable=1)
1127
1128 local_ip = self.pg0.remote_ip4
1129 external_ip = self.nat_addr
1130 self.nat_add_static_mapping(local_ip, external_ip)
1131
1132 users = self.vapi.nat44_user_dump()
1133 self.assertEqual(len(users), 0)
1134
1135 # in2out - static mapping match
1136
1137 pkts = self.create_stream_out(self.pg1)
1138 self.pg1.add_stream(pkts)
1139 self.pg_enable_capture(self.pg_interfaces)
1140 self.pg_start()
1141 capture = self.pg0.get_capture(len(pkts))
1142 self.verify_capture_in(capture, self.pg0)
1143
1144 pkts = self.create_stream_in(self.pg0, self.pg1)
1145 self.pg0.add_stream(pkts)
1146 self.pg_enable_capture(self.pg_interfaces)
1147 self.pg_start()
1148 capture = self.pg1.get_capture(len(pkts))
1149 self.verify_capture_out(capture, same_port=True)
1150
1151 users = self.vapi.nat44_user_dump()
1152 self.assertEqual(len(users), 1)
1153 static_user = users[0]
1154 self.assertEqual(static_user.nstaticsessions, 3)
1155 self.assertEqual(static_user.nsessions, 0)
1156
1157 # in2out - no static mapping match (forwarding test)
1158
1159 host0 = self.pg0.remote_hosts[0]
1160 self.pg0.remote_hosts[0] = self.pg0.remote_hosts[1]
1161 try:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001162 pkts = self.create_stream_out(
1163 self.pg1, dst_ip=self.pg0.remote_ip4, use_inside_ports=True
1164 )
Filip Varga18f1e412020-12-03 15:27:40 +01001165 self.pg1.add_stream(pkts)
1166 self.pg_enable_capture(self.pg_interfaces)
1167 self.pg_start()
1168 capture = self.pg0.get_capture(len(pkts))
1169 self.verify_capture_in(capture, self.pg0)
1170
1171 pkts = self.create_stream_in(self.pg0, self.pg1)
1172 self.pg0.add_stream(pkts)
1173 self.pg_enable_capture(self.pg_interfaces)
1174 self.pg_start()
1175 capture = self.pg1.get_capture(len(pkts))
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001176 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4, same_port=True)
Filip Varga18f1e412020-12-03 15:27:40 +01001177 finally:
1178 self.pg0.remote_hosts[0] = host0
1179
1180 users = self.vapi.nat44_user_dump()
1181 self.assertEqual(len(users), 2)
1182 if str(users[0].ip_address) == self.pg0.remote_hosts[0].ip4:
1183 non_static_user = users[1]
1184 static_user = users[0]
1185 else:
1186 non_static_user = users[0]
1187 static_user = users[1]
1188 self.assertEqual(static_user.nstaticsessions, 3)
1189 self.assertEqual(static_user.nsessions, 0)
1190 self.assertEqual(non_static_user.nstaticsessions, 0)
1191 self.assertEqual(non_static_user.nsessions, 3)
1192
1193 users = self.vapi.nat44_user_dump()
1194 self.assertEqual(len(users), 2)
1195 if str(users[0].ip_address) == self.pg0.remote_hosts[0].ip4:
1196 non_static_user = users[1]
1197 static_user = users[0]
1198 else:
1199 non_static_user = users[0]
1200 static_user = users[1]
1201 self.assertEqual(static_user.nstaticsessions, 3)
1202 self.assertEqual(static_user.nsessions, 0)
1203 self.assertEqual(non_static_user.nstaticsessions, 0)
1204 self.assertEqual(non_static_user.nsessions, 3)
1205
1206 def test_frag_out_of_order_do_not_translate(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001207 """NAT44ED don't translate fragments arriving out of order"""
Filip Varga18f1e412020-12-03 15:27:40 +01001208 self.nat_add_inside_interface(self.pg0)
1209 self.nat_add_outside_interface(self.pg1)
1210 self.vapi.nat44_forwarding_enable_disable(enable=True)
1211 self.frag_out_of_order(proto=IP_PROTOS.tcp, dont_translate=True)
1212
1213 def test_forwarding(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001214 """NAT44ED forwarding test"""
Filip Varga18f1e412020-12-03 15:27:40 +01001215
1216 self.nat_add_inside_interface(self.pg0)
1217 self.nat_add_outside_interface(self.pg1)
1218 self.vapi.nat44_forwarding_enable_disable(enable=1)
1219
1220 real_ip = self.pg0.remote_ip4
1221 alias_ip = self.nat_addr
1222 flags = self.config_flags.NAT_IS_ADDR_ONLY
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001223 self.vapi.nat44_add_del_static_mapping(
1224 is_add=1,
1225 local_ip_address=real_ip,
1226 external_ip_address=alias_ip,
1227 external_sw_if_index=0xFFFFFFFF,
1228 flags=flags,
1229 )
Filip Varga18f1e412020-12-03 15:27:40 +01001230
1231 try:
1232 # in2out - static mapping match
1233
1234 pkts = self.create_stream_out(self.pg1)
1235 self.pg1.add_stream(pkts)
1236 self.pg_enable_capture(self.pg_interfaces)
1237 self.pg_start()
1238 capture = self.pg0.get_capture(len(pkts))
1239 self.verify_capture_in(capture, self.pg0)
1240
1241 pkts = self.create_stream_in(self.pg0, self.pg1)
1242 self.pg0.add_stream(pkts)
1243 self.pg_enable_capture(self.pg_interfaces)
1244 self.pg_start()
1245 capture = self.pg1.get_capture(len(pkts))
1246 self.verify_capture_out(capture, same_port=True)
1247
1248 # in2out - no static mapping match
1249
1250 host0 = self.pg0.remote_hosts[0]
1251 self.pg0.remote_hosts[0] = self.pg0.remote_hosts[1]
1252 try:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001253 pkts = self.create_stream_out(
1254 self.pg1, dst_ip=self.pg0.remote_ip4, use_inside_ports=True
1255 )
Filip Varga18f1e412020-12-03 15:27:40 +01001256 self.pg1.add_stream(pkts)
1257 self.pg_enable_capture(self.pg_interfaces)
1258 self.pg_start()
1259 capture = self.pg0.get_capture(len(pkts))
1260 self.verify_capture_in(capture, self.pg0)
1261
1262 pkts = self.create_stream_in(self.pg0, self.pg1)
1263 self.pg0.add_stream(pkts)
1264 self.pg_enable_capture(self.pg_interfaces)
1265 self.pg_start()
1266 capture = self.pg1.get_capture(len(pkts))
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001267 self.verify_capture_out(
1268 capture, nat_ip=self.pg0.remote_ip4, same_port=True
1269 )
Filip Varga18f1e412020-12-03 15:27:40 +01001270 finally:
1271 self.pg0.remote_hosts[0] = host0
1272
1273 user = self.pg0.remote_hosts[1]
1274 sessions = self.vapi.nat44_user_session_dump(user.ip4, 0)
1275 self.assertEqual(len(sessions), 3)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001276 self.assertTrue(sessions[0].flags & self.config_flags.NAT_IS_EXT_HOST_VALID)
Filip Varga18f1e412020-12-03 15:27:40 +01001277 self.vapi.nat44_del_session(
1278 address=sessions[0].inside_ip_address,
1279 port=sessions[0].inside_port,
1280 protocol=sessions[0].protocol,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001281 flags=(
1282 self.config_flags.NAT_IS_INSIDE
1283 | self.config_flags.NAT_IS_EXT_HOST_VALID
1284 ),
Filip Varga18f1e412020-12-03 15:27:40 +01001285 ext_host_address=sessions[0].ext_host_address,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001286 ext_host_port=sessions[0].ext_host_port,
1287 )
Filip Varga18f1e412020-12-03 15:27:40 +01001288 sessions = self.vapi.nat44_user_session_dump(user.ip4, 0)
1289 self.assertEqual(len(sessions), 2)
1290
1291 finally:
1292 self.vapi.nat44_forwarding_enable_disable(enable=0)
1293 flags = self.config_flags.NAT_IS_ADDR_ONLY
1294 self.vapi.nat44_add_del_static_mapping(
1295 is_add=0,
1296 local_ip_address=real_ip,
1297 external_ip_address=alias_ip,
1298 external_sw_if_index=0xFFFFFFFF,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001299 flags=flags,
1300 )
Filip Varga18f1e412020-12-03 15:27:40 +01001301
1302 def test_output_feature_and_service2(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001303 """NAT44ED interface output feature and service host direct access"""
Filip Varga18f1e412020-12-03 15:27:40 +01001304 self.vapi.nat44_forwarding_enable_disable(enable=1)
1305 self.nat_add_address(self.nat_addr)
1306
Filip Vargab6810822022-02-15 11:56:07 -08001307 self.vapi.nat44_ed_add_del_output_interface(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001308 sw_if_index=self.pg1.sw_if_index, is_add=1
1309 )
Filip Varga18f1e412020-12-03 15:27:40 +01001310
1311 # session initiated from service host - translate
1312 pkts = self.create_stream_in(self.pg0, self.pg1)
1313 self.pg0.add_stream(pkts)
1314 self.pg_enable_capture(self.pg_interfaces)
1315 self.pg_start()
1316 capture = self.pg1.get_capture(len(pkts))
1317 self.verify_capture_out(capture, ignore_port=True)
1318
1319 pkts = self.create_stream_out(self.pg1)
1320 self.pg1.add_stream(pkts)
1321 self.pg_enable_capture(self.pg_interfaces)
1322 self.pg_start()
1323 capture = self.pg0.get_capture(len(pkts))
1324 self.verify_capture_in(capture, self.pg0)
1325
1326 # session initiated from remote host - do not translate
1327 tcp_port_in = self.tcp_port_in
1328 udp_port_in = self.udp_port_in
1329 icmp_id_in = self.icmp_id_in
1330
1331 self.tcp_port_in = 60303
1332 self.udp_port_in = 60304
1333 self.icmp_id_in = 60305
1334
1335 try:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001336 pkts = self.create_stream_out(
1337 self.pg1, self.pg0.remote_ip4, use_inside_ports=True
1338 )
Filip Varga18f1e412020-12-03 15:27:40 +01001339 self.pg1.add_stream(pkts)
1340 self.pg_enable_capture(self.pg_interfaces)
1341 self.pg_start()
1342 capture = self.pg0.get_capture(len(pkts))
1343 self.verify_capture_in(capture, self.pg0)
1344
1345 pkts = self.create_stream_in(self.pg0, self.pg1)
1346 self.pg0.add_stream(pkts)
1347 self.pg_enable_capture(self.pg_interfaces)
1348 self.pg_start()
1349 capture = self.pg1.get_capture(len(pkts))
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001350 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4, same_port=True)
Filip Varga18f1e412020-12-03 15:27:40 +01001351 finally:
1352 self.tcp_port_in = tcp_port_in
1353 self.udp_port_in = udp_port_in
1354 self.icmp_id_in = icmp_id_in
1355
1356 def test_twice_nat(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001357 """NAT44ED Twice NAT"""
Filip Varga18f1e412020-12-03 15:27:40 +01001358 self.twice_nat_common()
1359
1360 def test_self_twice_nat_positive(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001361 """NAT44ED Self Twice NAT (positive test)"""
Filip Varga18f1e412020-12-03 15:27:40 +01001362 self.twice_nat_common(self_twice_nat=True, same_pg=True)
1363
1364 def test_self_twice_nat_lb_positive(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001365 """NAT44ED Self Twice NAT local service load balancing (positive test)"""
1366 self.twice_nat_common(lb=True, self_twice_nat=True, same_pg=True, client_id=1)
Filip Varga18f1e412020-12-03 15:27:40 +01001367
1368 def test_twice_nat_lb(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001369 """NAT44ED Twice NAT local service load balancing"""
Filip Varga18f1e412020-12-03 15:27:40 +01001370 self.twice_nat_common(lb=True)
1371
1372 def test_output_feature(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001373 """NAT44ED interface output feature (in2out postrouting)"""
Filip Varga18f1e412020-12-03 15:27:40 +01001374 self.vapi.nat44_forwarding_enable_disable(enable=1)
1375 self.nat_add_address(self.nat_addr)
1376
1377 self.nat_add_outside_interface(self.pg0)
Filip Vargab6810822022-02-15 11:56:07 -08001378 self.vapi.nat44_ed_add_del_output_interface(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001379 sw_if_index=self.pg1.sw_if_index, is_add=1
1380 )
Filip Varga18f1e412020-12-03 15:27:40 +01001381
1382 # in2out
1383 pkts = self.create_stream_in(self.pg0, self.pg1)
1384 self.pg0.add_stream(pkts)
1385 self.pg_enable_capture(self.pg_interfaces)
1386 self.pg_start()
1387 capture = self.pg1.get_capture(len(pkts))
1388 self.verify_capture_out(capture, ignore_port=True)
Klement Sekera05b5a5b2021-06-28 13:40:40 +02001389 self.logger.debug(self.vapi.cli("show trace"))
Filip Varga18f1e412020-12-03 15:27:40 +01001390
1391 # out2in
1392 pkts = self.create_stream_out(self.pg1)
1393 self.pg1.add_stream(pkts)
1394 self.pg_enable_capture(self.pg_interfaces)
1395 self.pg_start()
1396 capture = self.pg0.get_capture(len(pkts))
1397 self.verify_capture_in(capture, self.pg0)
Klement Sekera05b5a5b2021-06-28 13:40:40 +02001398 self.logger.debug(self.vapi.cli("show trace"))
Filip Varga18f1e412020-12-03 15:27:40 +01001399
Klement Sekera79699b02021-06-21 16:04:40 +02001400 # in2out
1401 pkts = self.create_stream_in(self.pg0, self.pg1, ttl=2)
1402 self.pg0.add_stream(pkts)
1403 self.pg_enable_capture(self.pg_interfaces)
1404 self.pg_start()
1405 capture = self.pg1.get_capture(len(pkts))
1406 self.verify_capture_out(capture, ignore_port=True)
Klement Sekera05b5a5b2021-06-28 13:40:40 +02001407 self.logger.debug(self.vapi.cli("show trace"))
Klement Sekera79699b02021-06-21 16:04:40 +02001408
1409 # out2in
1410 pkts = self.create_stream_out(self.pg1, ttl=2)
1411 self.pg1.add_stream(pkts)
1412 self.pg_enable_capture(self.pg_interfaces)
1413 self.pg_start()
1414 capture = self.pg0.get_capture(len(pkts))
1415 self.verify_capture_in(capture, self.pg0)
Klement Sekera05b5a5b2021-06-28 13:40:40 +02001416 self.logger.debug(self.vapi.cli("show trace"))
Klement Sekera79699b02021-06-21 16:04:40 +02001417
1418 # in2out
1419 pkts = self.create_stream_in(self.pg0, self.pg1, ttl=1)
Neale Ranns5c6dd172022-02-17 09:08:47 +00001420 capture = self.send_and_expect_some(self.pg0, pkts, self.pg0)
Klement Sekera79699b02021-06-21 16:04:40 +02001421 for p in capture:
1422 self.assertIn(ICMP, p)
1423 self.assertEqual(p[ICMP].type, 11) # 11 == time-exceeded
1424
Filip Varga18f1e412020-12-03 15:27:40 +01001425 def test_static_with_port_out2(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001426 """NAT44ED 1:1 NAPT asymmetrical rule"""
Filip Varga18f1e412020-12-03 15:27:40 +01001427
1428 external_port = 80
1429 local_port = 8080
1430
1431 self.vapi.nat44_forwarding_enable_disable(enable=1)
1432 flags = self.config_flags.NAT_IS_OUT2IN_ONLY
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001433 self.nat_add_static_mapping(
1434 self.pg0.remote_ip4,
1435 self.nat_addr,
1436 local_port,
1437 external_port,
1438 proto=IP_PROTOS.tcp,
1439 flags=flags,
1440 )
Filip Varga18f1e412020-12-03 15:27:40 +01001441
1442 self.nat_add_inside_interface(self.pg0)
1443 self.nat_add_outside_interface(self.pg1)
1444
1445 # from client to service
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001446 p = (
1447 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
1448 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
1449 / TCP(sport=12345, dport=external_port)
1450 )
Filip Varga18f1e412020-12-03 15:27:40 +01001451 self.pg1.add_stream(p)
1452 self.pg_enable_capture(self.pg_interfaces)
1453 self.pg_start()
1454 capture = self.pg0.get_capture(1)
1455 p = capture[0]
1456 try:
1457 ip = p[IP]
1458 tcp = p[TCP]
1459 self.assertEqual(ip.dst, self.pg0.remote_ip4)
1460 self.assertEqual(tcp.dport, local_port)
1461 self.assert_packet_checksums_valid(p)
1462 except:
1463 self.logger.error(ppp("Unexpected or invalid packet:", p))
1464 raise
1465
1466 # ICMP error
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001467 p = (
1468 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
1469 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
1470 / ICMP(type=11)
1471 / capture[0][IP]
1472 )
Filip Varga18f1e412020-12-03 15:27:40 +01001473 self.pg0.add_stream(p)
1474 self.pg_enable_capture(self.pg_interfaces)
1475 self.pg_start()
1476 capture = self.pg1.get_capture(1)
1477 p = capture[0]
1478 try:
1479 self.assertEqual(p[IP].src, self.nat_addr)
1480 inner = p[IPerror]
1481 self.assertEqual(inner.dst, self.nat_addr)
1482 self.assertEqual(inner[TCPerror].dport, external_port)
1483 except:
1484 self.logger.error(ppp("Unexpected or invalid packet:", p))
1485 raise
1486
1487 # from service back to client
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001488 p = (
1489 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
1490 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
1491 / TCP(sport=local_port, dport=12345)
1492 )
Filip Varga18f1e412020-12-03 15:27:40 +01001493 self.pg0.add_stream(p)
1494 self.pg_enable_capture(self.pg_interfaces)
1495 self.pg_start()
1496 capture = self.pg1.get_capture(1)
1497 p = capture[0]
1498 try:
1499 ip = p[IP]
1500 tcp = p[TCP]
1501 self.assertEqual(ip.src, self.nat_addr)
1502 self.assertEqual(tcp.sport, external_port)
1503 self.assert_packet_checksums_valid(p)
1504 except:
1505 self.logger.error(ppp("Unexpected or invalid packet:", p))
1506 raise
1507
1508 # ICMP error
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001509 p = (
1510 Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac)
1511 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
1512 / ICMP(type=11)
1513 / capture[0][IP]
1514 )
Filip Varga18f1e412020-12-03 15:27:40 +01001515 self.pg1.add_stream(p)
1516 self.pg_enable_capture(self.pg_interfaces)
1517 self.pg_start()
1518 capture = self.pg0.get_capture(1)
1519 p = capture[0]
1520 try:
1521 self.assertEqual(p[IP].dst, self.pg0.remote_ip4)
1522 inner = p[IPerror]
1523 self.assertEqual(inner.src, self.pg0.remote_ip4)
1524 self.assertEqual(inner[TCPerror].sport, local_port)
1525 except:
1526 self.logger.error(ppp("Unexpected or invalid packet:", p))
1527 raise
1528
1529 # from client to server (no translation)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001530 p = (
1531 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
1532 / IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4)
1533 / TCP(sport=12346, dport=local_port)
1534 )
Filip Varga18f1e412020-12-03 15:27:40 +01001535 self.pg1.add_stream(p)
1536 self.pg_enable_capture(self.pg_interfaces)
1537 self.pg_start()
1538 capture = self.pg0.get_capture(1)
1539 p = capture[0]
1540 try:
1541 ip = p[IP]
1542 tcp = p[TCP]
1543 self.assertEqual(ip.dst, self.pg0.remote_ip4)
1544 self.assertEqual(tcp.dport, local_port)
1545 self.assert_packet_checksums_valid(p)
1546 except:
1547 self.logger.error(ppp("Unexpected or invalid packet:", p))
1548 raise
1549
1550 # from service back to client (no translation)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001551 p = (
1552 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
1553 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
1554 / TCP(sport=local_port, dport=12346)
1555 )
Filip Varga18f1e412020-12-03 15:27:40 +01001556 self.pg0.add_stream(p)
1557 self.pg_enable_capture(self.pg_interfaces)
1558 self.pg_start()
1559 capture = self.pg1.get_capture(1)
1560 p = capture[0]
1561 try:
1562 ip = p[IP]
1563 tcp = p[TCP]
1564 self.assertEqual(ip.src, self.pg0.remote_ip4)
1565 self.assertEqual(tcp.sport, local_port)
1566 self.assert_packet_checksums_valid(p)
1567 except:
1568 self.logger.error(ppp("Unexpected or invalid packet:", p))
1569 raise
1570
1571 def test_static_lb(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001572 """NAT44ED local service load balancing"""
Filip Varga18f1e412020-12-03 15:27:40 +01001573 external_addr_n = self.nat_addr
1574 external_port = 80
1575 local_port = 8080
1576 server1 = self.pg0.remote_hosts[0]
1577 server2 = self.pg0.remote_hosts[1]
1578
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001579 locals = [
1580 {"addr": server1.ip4, "port": local_port, "probability": 70, "vrf_id": 0},
1581 {"addr": server2.ip4, "port": local_port, "probability": 30, "vrf_id": 0},
1582 ]
Filip Varga18f1e412020-12-03 15:27:40 +01001583
1584 self.nat_add_address(self.nat_addr)
1585 self.vapi.nat44_add_del_lb_static_mapping(
1586 is_add=1,
1587 external_addr=external_addr_n,
1588 external_port=external_port,
1589 protocol=IP_PROTOS.tcp,
1590 local_num=len(locals),
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001591 locals=locals,
1592 )
Filip Varga18f1e412020-12-03 15:27:40 +01001593 flags = self.config_flags.NAT_IS_INSIDE
1594 self.vapi.nat44_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001595 sw_if_index=self.pg0.sw_if_index, flags=flags, is_add=1
1596 )
Filip Varga18f1e412020-12-03 15:27:40 +01001597 self.vapi.nat44_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001598 sw_if_index=self.pg1.sw_if_index, is_add=1
1599 )
Filip Varga18f1e412020-12-03 15:27:40 +01001600
1601 # from client to service
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001602 p = (
1603 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
1604 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
1605 / TCP(sport=12345, dport=external_port)
1606 )
Filip Varga18f1e412020-12-03 15:27:40 +01001607 self.pg1.add_stream(p)
1608 self.pg_enable_capture(self.pg_interfaces)
1609 self.pg_start()
1610 capture = self.pg0.get_capture(1)
1611 p = capture[0]
1612 server = None
1613 try:
1614 ip = p[IP]
1615 tcp = p[TCP]
1616 self.assertIn(ip.dst, [server1.ip4, server2.ip4])
1617 if ip.dst == server1.ip4:
1618 server = server1
1619 else:
1620 server = server2
1621 self.assertEqual(tcp.dport, local_port)
1622 self.assert_packet_checksums_valid(p)
1623 except:
1624 self.logger.error(ppp("Unexpected or invalid packet:", p))
1625 raise
1626
1627 # from service back to client
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001628 p = (
1629 Ether(src=server.mac, dst=self.pg0.local_mac)
1630 / IP(src=server.ip4, dst=self.pg1.remote_ip4)
1631 / TCP(sport=local_port, dport=12345)
1632 )
Filip Varga18f1e412020-12-03 15:27:40 +01001633 self.pg0.add_stream(p)
1634 self.pg_enable_capture(self.pg_interfaces)
1635 self.pg_start()
1636 capture = self.pg1.get_capture(1)
1637 p = capture[0]
1638 try:
1639 ip = p[IP]
1640 tcp = p[TCP]
1641 self.assertEqual(ip.src, self.nat_addr)
1642 self.assertEqual(tcp.sport, external_port)
1643 self.assert_packet_checksums_valid(p)
1644 except:
1645 self.logger.error(ppp("Unexpected or invalid packet:", p))
1646 raise
1647
1648 sessions = self.vapi.nat44_user_session_dump(server.ip4, 0)
1649 self.assertEqual(len(sessions), 1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001650 self.assertTrue(sessions[0].flags & self.config_flags.NAT_IS_EXT_HOST_VALID)
Filip Varga18f1e412020-12-03 15:27:40 +01001651 self.vapi.nat44_del_session(
1652 address=sessions[0].inside_ip_address,
1653 port=sessions[0].inside_port,
1654 protocol=sessions[0].protocol,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001655 flags=(
1656 self.config_flags.NAT_IS_INSIDE
1657 | self.config_flags.NAT_IS_EXT_HOST_VALID
1658 ),
Filip Varga18f1e412020-12-03 15:27:40 +01001659 ext_host_address=sessions[0].ext_host_address,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001660 ext_host_port=sessions[0].ext_host_port,
1661 )
Filip Varga18f1e412020-12-03 15:27:40 +01001662 sessions = self.vapi.nat44_user_session_dump(server.ip4, 0)
1663 self.assertEqual(len(sessions), 0)
1664
1665 def test_static_lb_2(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001666 """NAT44ED local service load balancing (asymmetrical rule)"""
Filip Varga18f1e412020-12-03 15:27:40 +01001667 external_addr = self.nat_addr
1668 external_port = 80
1669 local_port = 8080
1670 server1 = self.pg0.remote_hosts[0]
1671 server2 = self.pg0.remote_hosts[1]
1672
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001673 locals = [
1674 {"addr": server1.ip4, "port": local_port, "probability": 70, "vrf_id": 0},
1675 {"addr": server2.ip4, "port": local_port, "probability": 30, "vrf_id": 0},
1676 ]
Filip Varga18f1e412020-12-03 15:27:40 +01001677
1678 self.vapi.nat44_forwarding_enable_disable(enable=1)
1679 flags = self.config_flags.NAT_IS_OUT2IN_ONLY
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001680 self.vapi.nat44_add_del_lb_static_mapping(
1681 is_add=1,
1682 flags=flags,
1683 external_addr=external_addr,
1684 external_port=external_port,
1685 protocol=IP_PROTOS.tcp,
1686 local_num=len(locals),
1687 locals=locals,
1688 )
Filip Varga18f1e412020-12-03 15:27:40 +01001689 flags = self.config_flags.NAT_IS_INSIDE
1690 self.vapi.nat44_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001691 sw_if_index=self.pg0.sw_if_index, flags=flags, is_add=1
1692 )
Filip Varga18f1e412020-12-03 15:27:40 +01001693 self.vapi.nat44_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001694 sw_if_index=self.pg1.sw_if_index, is_add=1
1695 )
Filip Varga18f1e412020-12-03 15:27:40 +01001696
1697 # from client to service
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001698 p = (
1699 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
1700 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
1701 / TCP(sport=12345, dport=external_port)
1702 )
Filip Varga18f1e412020-12-03 15:27:40 +01001703 self.pg1.add_stream(p)
1704 self.pg_enable_capture(self.pg_interfaces)
1705 self.pg_start()
1706 capture = self.pg0.get_capture(1)
1707 p = capture[0]
1708 server = None
1709 try:
1710 ip = p[IP]
1711 tcp = p[TCP]
1712 self.assertIn(ip.dst, [server1.ip4, server2.ip4])
1713 if ip.dst == server1.ip4:
1714 server = server1
1715 else:
1716 server = server2
1717 self.assertEqual(tcp.dport, local_port)
1718 self.assert_packet_checksums_valid(p)
1719 except:
1720 self.logger.error(ppp("Unexpected or invalid packet:", p))
1721 raise
1722
1723 # from service back to client
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001724 p = (
1725 Ether(src=server.mac, dst=self.pg0.local_mac)
1726 / IP(src=server.ip4, dst=self.pg1.remote_ip4)
1727 / TCP(sport=local_port, dport=12345)
1728 )
Filip Varga18f1e412020-12-03 15:27:40 +01001729 self.pg0.add_stream(p)
1730 self.pg_enable_capture(self.pg_interfaces)
1731 self.pg_start()
1732 capture = self.pg1.get_capture(1)
1733 p = capture[0]
1734 try:
1735 ip = p[IP]
1736 tcp = p[TCP]
1737 self.assertEqual(ip.src, self.nat_addr)
1738 self.assertEqual(tcp.sport, external_port)
1739 self.assert_packet_checksums_valid(p)
1740 except:
1741 self.logger.error(ppp("Unexpected or invalid packet:", p))
1742 raise
1743
1744 # from client to server (no translation)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001745 p = (
1746 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
1747 / IP(src=self.pg1.remote_ip4, dst=server1.ip4)
1748 / TCP(sport=12346, dport=local_port)
1749 )
Filip Varga18f1e412020-12-03 15:27:40 +01001750 self.pg1.add_stream(p)
1751 self.pg_enable_capture(self.pg_interfaces)
1752 self.pg_start()
1753 capture = self.pg0.get_capture(1)
1754 p = capture[0]
1755 server = None
1756 try:
1757 ip = p[IP]
1758 tcp = p[TCP]
1759 self.assertEqual(ip.dst, server1.ip4)
1760 self.assertEqual(tcp.dport, local_port)
1761 self.assert_packet_checksums_valid(p)
1762 except:
1763 self.logger.error(ppp("Unexpected or invalid packet:", p))
1764 raise
1765
1766 # from service back to client (no translation)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001767 p = (
1768 Ether(src=server1.mac, dst=self.pg0.local_mac)
1769 / IP(src=server1.ip4, dst=self.pg1.remote_ip4)
1770 / TCP(sport=local_port, dport=12346)
1771 )
Filip Varga18f1e412020-12-03 15:27:40 +01001772 self.pg0.add_stream(p)
1773 self.pg_enable_capture(self.pg_interfaces)
1774 self.pg_start()
1775 capture = self.pg1.get_capture(1)
1776 p = capture[0]
1777 try:
1778 ip = p[IP]
1779 tcp = p[TCP]
1780 self.assertEqual(ip.src, server1.ip4)
1781 self.assertEqual(tcp.sport, local_port)
1782 self.assert_packet_checksums_valid(p)
1783 except:
1784 self.logger.error(ppp("Unexpected or invalid packet:", p))
1785 raise
1786
1787 def test_lb_affinity(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001788 """NAT44ED local service load balancing affinity"""
Filip Varga18f1e412020-12-03 15:27:40 +01001789 external_addr = self.nat_addr
1790 external_port = 80
1791 local_port = 8080
1792 server1 = self.pg0.remote_hosts[0]
1793 server2 = self.pg0.remote_hosts[1]
1794
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001795 locals = [
1796 {"addr": server1.ip4, "port": local_port, "probability": 50, "vrf_id": 0},
1797 {"addr": server2.ip4, "port": local_port, "probability": 50, "vrf_id": 0},
1798 ]
Filip Varga18f1e412020-12-03 15:27:40 +01001799
1800 self.nat_add_address(self.nat_addr)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001801 self.vapi.nat44_add_del_lb_static_mapping(
1802 is_add=1,
1803 external_addr=external_addr,
1804 external_port=external_port,
1805 protocol=IP_PROTOS.tcp,
1806 affinity=10800,
1807 local_num=len(locals),
1808 locals=locals,
1809 )
Filip Varga18f1e412020-12-03 15:27:40 +01001810 flags = self.config_flags.NAT_IS_INSIDE
1811 self.vapi.nat44_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001812 sw_if_index=self.pg0.sw_if_index, flags=flags, is_add=1
1813 )
Filip Varga18f1e412020-12-03 15:27:40 +01001814 self.vapi.nat44_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001815 sw_if_index=self.pg1.sw_if_index, is_add=1
1816 )
Filip Varga18f1e412020-12-03 15:27:40 +01001817
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001818 p = (
1819 Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac)
1820 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
1821 / TCP(sport=1025, dport=external_port)
1822 )
Filip Varga18f1e412020-12-03 15:27:40 +01001823 self.pg1.add_stream(p)
1824 self.pg_enable_capture(self.pg_interfaces)
1825 self.pg_start()
1826 capture = self.pg0.get_capture(1)
1827 backend = capture[0][IP].dst
1828
1829 sessions = self.vapi.nat44_user_session_dump(backend, 0)
1830 self.assertEqual(len(sessions), 1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001831 self.assertTrue(sessions[0].flags & self.config_flags.NAT_IS_EXT_HOST_VALID)
Filip Varga18f1e412020-12-03 15:27:40 +01001832 self.vapi.nat44_del_session(
1833 address=sessions[0].inside_ip_address,
1834 port=sessions[0].inside_port,
1835 protocol=sessions[0].protocol,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001836 flags=(
1837 self.config_flags.NAT_IS_INSIDE
1838 | self.config_flags.NAT_IS_EXT_HOST_VALID
1839 ),
Filip Varga18f1e412020-12-03 15:27:40 +01001840 ext_host_address=sessions[0].ext_host_address,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001841 ext_host_port=sessions[0].ext_host_port,
1842 )
Filip Varga18f1e412020-12-03 15:27:40 +01001843
1844 pkts = []
1845 for port in range(1030, 1100):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001846 p = (
1847 Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac)
1848 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
1849 / TCP(sport=port, dport=external_port)
1850 )
Filip Varga18f1e412020-12-03 15:27:40 +01001851 pkts.append(p)
1852 self.pg1.add_stream(pkts)
1853 self.pg_enable_capture(self.pg_interfaces)
1854 self.pg_start()
1855 capture = self.pg0.get_capture(len(pkts))
1856 for p in capture:
1857 self.assertEqual(p[IP].dst, backend)
1858
Klement Sekeraa920af72021-05-17 13:17:56 +02001859 def test_multiple_vrf_1(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001860 """Multiple VRF - both client & service in VRF1"""
Filip Varga18f1e412020-12-03 15:27:40 +01001861
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001862 external_addr = "1.2.3.4"
Filip Varga18f1e412020-12-03 15:27:40 +01001863 external_port = 80
1864 local_port = 8080
1865 port = 0
1866
Filip Varga18f1e412020-12-03 15:27:40 +01001867 flags = self.config_flags.NAT_IS_INSIDE
1868 self.vapi.nat44_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001869 sw_if_index=self.pg5.sw_if_index, is_add=1
1870 )
Filip Varga18f1e412020-12-03 15:27:40 +01001871 self.vapi.nat44_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001872 sw_if_index=self.pg5.sw_if_index, is_add=1, flags=flags
1873 )
Filip Varga18f1e412020-12-03 15:27:40 +01001874 self.vapi.nat44_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001875 sw_if_index=self.pg6.sw_if_index, is_add=1
1876 )
Filip Varga18f1e412020-12-03 15:27:40 +01001877 flags = self.config_flags.NAT_IS_OUT2IN_ONLY
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001878 self.nat_add_static_mapping(
1879 self.pg5.remote_ip4,
1880 external_addr,
1881 local_port,
1882 external_port,
1883 vrf_id=1,
1884 proto=IP_PROTOS.tcp,
1885 flags=flags,
1886 )
Filip Varga18f1e412020-12-03 15:27:40 +01001887
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001888 p = (
1889 Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac)
1890 / IP(src=self.pg6.remote_ip4, dst=external_addr)
1891 / TCP(sport=12345, dport=external_port)
1892 )
Filip Varga18f1e412020-12-03 15:27:40 +01001893 self.pg6.add_stream(p)
1894 self.pg_enable_capture(self.pg_interfaces)
1895 self.pg_start()
1896 capture = self.pg5.get_capture(1)
1897 p = capture[0]
1898 try:
1899 ip = p[IP]
1900 tcp = p[TCP]
1901 self.assertEqual(ip.dst, self.pg5.remote_ip4)
1902 self.assertEqual(tcp.dport, local_port)
1903 self.assert_packet_checksums_valid(p)
1904 except:
1905 self.logger.error(ppp("Unexpected or invalid packet:", p))
1906 raise
1907
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001908 p = (
1909 Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac)
1910 / IP(src=self.pg5.remote_ip4, dst=self.pg6.remote_ip4)
1911 / TCP(sport=local_port, dport=12345)
1912 )
Filip Varga18f1e412020-12-03 15:27:40 +01001913 self.pg5.add_stream(p)
1914 self.pg_enable_capture(self.pg_interfaces)
1915 self.pg_start()
1916 capture = self.pg6.get_capture(1)
1917 p = capture[0]
1918 try:
1919 ip = p[IP]
1920 tcp = p[TCP]
1921 self.assertEqual(ip.src, external_addr)
1922 self.assertEqual(tcp.sport, external_port)
1923 self.assert_packet_checksums_valid(p)
1924 except:
1925 self.logger.error(ppp("Unexpected or invalid packet:", p))
1926 raise
1927
Klement Sekeraa920af72021-05-17 13:17:56 +02001928 def test_multiple_vrf_2(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001929 """Multiple VRF - dynamic NAT from VRF1 to VRF0 (output-feature)"""
Klement Sekeraa920af72021-05-17 13:17:56 +02001930
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001931 external_addr = "1.2.3.4"
Klement Sekeraa920af72021-05-17 13:17:56 +02001932 external_port = 80
1933 local_port = 8080
1934 port = 0
1935
1936 self.nat_add_address(self.nat_addr)
1937 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargab6810822022-02-15 11:56:07 -08001938 self.vapi.nat44_ed_add_del_output_interface(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001939 sw_if_index=self.pg1.sw_if_index, is_add=1
1940 )
Klement Sekeraa920af72021-05-17 13:17:56 +02001941 self.vapi.nat44_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001942 sw_if_index=self.pg5.sw_if_index, is_add=1
1943 )
Klement Sekeraa920af72021-05-17 13:17:56 +02001944 self.vapi.nat44_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001945 sw_if_index=self.pg5.sw_if_index, is_add=1, flags=flags
1946 )
Klement Sekeraa920af72021-05-17 13:17:56 +02001947 flags = self.config_flags.NAT_IS_OUT2IN_ONLY
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001948 self.nat_add_static_mapping(
1949 self.pg5.remote_ip4,
1950 external_addr,
1951 local_port,
1952 external_port,
1953 vrf_id=1,
1954 proto=IP_PROTOS.tcp,
1955 flags=flags,
1956 )
Klement Sekeraa920af72021-05-17 13:17:56 +02001957
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001958 p = (
1959 Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac)
1960 / IP(src=self.pg5.remote_ip4, dst=self.pg1.remote_ip4)
1961 / TCP(sport=2345, dport=22)
1962 )
Filip Varga18f1e412020-12-03 15:27:40 +01001963 self.pg5.add_stream(p)
1964 self.pg_enable_capture(self.pg_interfaces)
1965 self.pg_start()
1966 capture = self.pg1.get_capture(1)
1967 p = capture[0]
1968 try:
1969 ip = p[IP]
1970 tcp = p[TCP]
1971 self.assertEqual(ip.src, self.nat_addr)
1972 self.assert_packet_checksums_valid(p)
1973 port = tcp.sport
1974 except:
1975 self.logger.error(ppp("Unexpected or invalid packet:", p))
1976 raise
1977
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001978 p = (
1979 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
1980 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
1981 / TCP(sport=22, dport=port)
1982 )
Filip Varga18f1e412020-12-03 15:27:40 +01001983 self.pg1.add_stream(p)
1984 self.pg_enable_capture(self.pg_interfaces)
1985 self.pg_start()
1986 capture = self.pg5.get_capture(1)
1987 p = capture[0]
1988 try:
1989 ip = p[IP]
1990 tcp = p[TCP]
1991 self.assertEqual(ip.dst, self.pg5.remote_ip4)
1992 self.assertEqual(tcp.dport, 2345)
1993 self.assert_packet_checksums_valid(p)
1994 except:
1995 self.logger.error(ppp("Unexpected or invalid packet:", p))
1996 raise
1997
Klement Sekeraa920af72021-05-17 13:17:56 +02001998 def test_multiple_vrf_3(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001999 """Multiple VRF - client in VRF1, service in VRF0"""
Klement Sekeraa920af72021-05-17 13:17:56 +02002000
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002001 external_addr = "1.2.3.4"
Klement Sekeraa920af72021-05-17 13:17:56 +02002002 external_port = 80
2003 local_port = 8080
2004 port = 0
2005
2006 flags = self.config_flags.NAT_IS_INSIDE
2007 self.vapi.nat44_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002008 sw_if_index=self.pg0.sw_if_index, is_add=1
2009 )
Klement Sekeraa920af72021-05-17 13:17:56 +02002010 self.vapi.nat44_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002011 sw_if_index=self.pg0.sw_if_index, is_add=1, flags=flags
2012 )
Klement Sekeraa920af72021-05-17 13:17:56 +02002013 self.vapi.nat44_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002014 sw_if_index=self.pg6.sw_if_index, is_add=1
2015 )
Klement Sekeraa920af72021-05-17 13:17:56 +02002016 flags = self.config_flags.NAT_IS_OUT2IN_ONLY
2017 self.nat_add_static_mapping(
2018 self.pg0.remote_ip4,
2019 external_sw_if_index=self.pg0.sw_if_index,
2020 local_port=local_port,
2021 vrf_id=0,
2022 external_port=external_port,
2023 proto=IP_PROTOS.tcp,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002024 flags=flags,
Klement Sekeraa920af72021-05-17 13:17:56 +02002025 )
2026
Filip Varga18f1e412020-12-03 15:27:40 +01002027 # from client VRF1 to service VRF0
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002028 p = (
2029 Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac)
2030 / IP(src=self.pg6.remote_ip4, dst=self.pg0.local_ip4)
2031 / TCP(sport=12346, dport=external_port)
2032 )
Filip Varga18f1e412020-12-03 15:27:40 +01002033 self.pg6.add_stream(p)
2034 self.pg_enable_capture(self.pg_interfaces)
2035 self.pg_start()
2036 capture = self.pg0.get_capture(1)
2037 p = capture[0]
2038 try:
2039 ip = p[IP]
2040 tcp = p[TCP]
2041 self.assertEqual(ip.dst, self.pg0.remote_ip4)
2042 self.assertEqual(tcp.dport, local_port)
2043 self.assert_packet_checksums_valid(p)
2044 except:
2045 self.logger.error(ppp("Unexpected or invalid packet:", p))
2046 raise
2047
2048 # from service VRF0 back to client VRF1
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002049 p = (
2050 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
2051 / IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4)
2052 / TCP(sport=local_port, dport=12346)
2053 )
Filip Varga18f1e412020-12-03 15:27:40 +01002054 self.pg0.add_stream(p)
2055 self.pg_enable_capture(self.pg_interfaces)
2056 self.pg_start()
2057 capture = self.pg6.get_capture(1)
2058 p = capture[0]
2059 try:
2060 ip = p[IP]
2061 tcp = p[TCP]
2062 self.assertEqual(ip.src, self.pg0.local_ip4)
2063 self.assertEqual(tcp.sport, external_port)
2064 self.assert_packet_checksums_valid(p)
2065 except:
2066 self.logger.error(ppp("Unexpected or invalid packet:", p))
2067 raise
2068
Klement Sekeraa920af72021-05-17 13:17:56 +02002069 def test_multiple_vrf_4(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002070 """Multiple VRF - client in VRF0, service in VRF1"""
Klement Sekeraa920af72021-05-17 13:17:56 +02002071
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002072 external_addr = "1.2.3.4"
Klement Sekeraa920af72021-05-17 13:17:56 +02002073 external_port = 80
2074 local_port = 8080
2075 port = 0
2076
2077 flags = self.config_flags.NAT_IS_INSIDE
2078 self.vapi.nat44_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002079 sw_if_index=self.pg0.sw_if_index, is_add=1
2080 )
Klement Sekeraa920af72021-05-17 13:17:56 +02002081 self.vapi.nat44_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002082 sw_if_index=self.pg0.sw_if_index, is_add=1, flags=flags
2083 )
Klement Sekeraa920af72021-05-17 13:17:56 +02002084 self.vapi.nat44_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002085 sw_if_index=self.pg5.sw_if_index, is_add=1
2086 )
Klement Sekeraa920af72021-05-17 13:17:56 +02002087 self.vapi.nat44_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002088 sw_if_index=self.pg5.sw_if_index, is_add=1, flags=flags
2089 )
Klement Sekeraa920af72021-05-17 13:17:56 +02002090 flags = self.config_flags.NAT_IS_OUT2IN_ONLY
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002091 self.nat_add_static_mapping(
2092 self.pg5.remote_ip4,
2093 external_addr,
2094 local_port,
2095 external_port,
2096 vrf_id=1,
2097 proto=IP_PROTOS.tcp,
2098 flags=flags,
2099 )
Klement Sekeraa920af72021-05-17 13:17:56 +02002100
Filip Varga18f1e412020-12-03 15:27:40 +01002101 # from client VRF0 to service VRF1
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002102 p = (
2103 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
2104 / IP(src=self.pg0.remote_ip4, dst=external_addr)
2105 / TCP(sport=12347, dport=external_port)
2106 )
Filip Varga18f1e412020-12-03 15:27:40 +01002107 self.pg0.add_stream(p)
2108 self.pg_enable_capture(self.pg_interfaces)
2109 self.pg_start()
2110 capture = self.pg5.get_capture(1)
2111 p = capture[0]
2112 try:
2113 ip = p[IP]
2114 tcp = p[TCP]
2115 self.assertEqual(ip.dst, self.pg5.remote_ip4)
2116 self.assertEqual(tcp.dport, local_port)
2117 self.assert_packet_checksums_valid(p)
2118 except:
2119 self.logger.error(ppp("Unexpected or invalid packet:", p))
2120 raise
2121
2122 # from service VRF1 back to client VRF0
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002123 p = (
2124 Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac)
2125 / IP(src=self.pg5.remote_ip4, dst=self.pg0.remote_ip4)
2126 / TCP(sport=local_port, dport=12347)
2127 )
Filip Varga18f1e412020-12-03 15:27:40 +01002128 self.pg5.add_stream(p)
2129 self.pg_enable_capture(self.pg_interfaces)
2130 self.pg_start()
2131 capture = self.pg0.get_capture(1)
2132 p = capture[0]
2133 try:
2134 ip = p[IP]
2135 tcp = p[TCP]
2136 self.assertEqual(ip.src, external_addr)
2137 self.assertEqual(tcp.sport, external_port)
2138 self.assert_packet_checksums_valid(p)
2139 except:
2140 self.logger.error(ppp("Unexpected or invalid packet:", p))
2141 raise
2142
Klement Sekeraa920af72021-05-17 13:17:56 +02002143 def test_multiple_vrf_5(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002144 """Multiple VRF - forwarding - no translation"""
Klement Sekeraa920af72021-05-17 13:17:56 +02002145
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002146 external_addr = "1.2.3.4"
Klement Sekeraa920af72021-05-17 13:17:56 +02002147 external_port = 80
2148 local_port = 8080
2149 port = 0
2150
2151 self.vapi.nat44_forwarding_enable_disable(enable=1)
2152 flags = self.config_flags.NAT_IS_INSIDE
2153 self.vapi.nat44_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002154 sw_if_index=self.pg0.sw_if_index, is_add=1
2155 )
Klement Sekeraa920af72021-05-17 13:17:56 +02002156 self.vapi.nat44_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002157 sw_if_index=self.pg0.sw_if_index, is_add=1, flags=flags
2158 )
Klement Sekeraa920af72021-05-17 13:17:56 +02002159 self.vapi.nat44_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002160 sw_if_index=self.pg5.sw_if_index, is_add=1
2161 )
Klement Sekeraa920af72021-05-17 13:17:56 +02002162 self.vapi.nat44_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002163 sw_if_index=self.pg5.sw_if_index, is_add=1, flags=flags
2164 )
Klement Sekeraa920af72021-05-17 13:17:56 +02002165 self.vapi.nat44_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002166 sw_if_index=self.pg6.sw_if_index, is_add=1
2167 )
Klement Sekeraa920af72021-05-17 13:17:56 +02002168 flags = self.config_flags.NAT_IS_OUT2IN_ONLY
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002169 self.nat_add_static_mapping(
2170 self.pg5.remote_ip4,
2171 external_addr,
2172 local_port,
2173 external_port,
2174 vrf_id=1,
2175 proto=IP_PROTOS.tcp,
2176 flags=flags,
2177 )
Klement Sekeraa920af72021-05-17 13:17:56 +02002178 self.nat_add_static_mapping(
2179 self.pg0.remote_ip4,
2180 external_sw_if_index=self.pg0.sw_if_index,
2181 local_port=local_port,
2182 vrf_id=0,
2183 external_port=external_port,
2184 proto=IP_PROTOS.tcp,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002185 flags=flags,
Klement Sekeraa920af72021-05-17 13:17:56 +02002186 )
2187
Filip Varga18f1e412020-12-03 15:27:40 +01002188 # from client to server (both VRF1, no translation)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002189 p = (
2190 Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac)
2191 / IP(src=self.pg6.remote_ip4, dst=self.pg5.remote_ip4)
2192 / TCP(sport=12348, dport=local_port)
2193 )
Filip Varga18f1e412020-12-03 15:27:40 +01002194 self.pg6.add_stream(p)
2195 self.pg_enable_capture(self.pg_interfaces)
2196 self.pg_start()
2197 capture = self.pg5.get_capture(1)
2198 p = capture[0]
2199 try:
2200 ip = p[IP]
2201 tcp = p[TCP]
2202 self.assertEqual(ip.dst, self.pg5.remote_ip4)
2203 self.assertEqual(tcp.dport, local_port)
2204 self.assert_packet_checksums_valid(p)
2205 except:
2206 self.logger.error(ppp("Unexpected or invalid packet:", p))
2207 raise
2208
2209 # from server back to client (both VRF1, no translation)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002210 p = (
2211 Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac)
2212 / IP(src=self.pg5.remote_ip4, dst=self.pg6.remote_ip4)
2213 / TCP(sport=local_port, dport=12348)
2214 )
Filip Varga18f1e412020-12-03 15:27:40 +01002215 self.pg5.add_stream(p)
2216 self.pg_enable_capture(self.pg_interfaces)
2217 self.pg_start()
2218 capture = self.pg6.get_capture(1)
2219 p = capture[0]
2220 try:
2221 ip = p[IP]
2222 tcp = p[TCP]
2223 self.assertEqual(ip.src, self.pg5.remote_ip4)
2224 self.assertEqual(tcp.sport, local_port)
2225 self.assert_packet_checksums_valid(p)
2226 except:
2227 self.logger.error(ppp("Unexpected or invalid packet:", p))
2228 raise
2229
2230 # from client VRF1 to server VRF0 (no translation)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002231 p = (
2232 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
2233 / IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4)
2234 / TCP(sport=local_port, dport=12349)
2235 )
Filip Varga18f1e412020-12-03 15:27:40 +01002236 self.pg0.add_stream(p)
2237 self.pg_enable_capture(self.pg_interfaces)
2238 self.pg_start()
2239 capture = self.pg6.get_capture(1)
2240 p = capture[0]
2241 try:
2242 ip = p[IP]
2243 tcp = p[TCP]
2244 self.assertEqual(ip.src, self.pg0.remote_ip4)
2245 self.assertEqual(tcp.sport, local_port)
2246 self.assert_packet_checksums_valid(p)
2247 except:
2248 self.logger.error(ppp("Unexpected or invalid packet:", p))
2249 raise
2250
2251 # from server VRF0 back to client VRF1 (no translation)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002252 p = (
2253 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
2254 / IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4)
2255 / TCP(sport=local_port, dport=12349)
2256 )
Filip Varga18f1e412020-12-03 15:27:40 +01002257 self.pg0.add_stream(p)
2258 self.pg_enable_capture(self.pg_interfaces)
2259 self.pg_start()
2260 capture = self.pg6.get_capture(1)
2261 p = capture[0]
2262 try:
2263 ip = p[IP]
2264 tcp = p[TCP]
2265 self.assertEqual(ip.src, self.pg0.remote_ip4)
2266 self.assertEqual(tcp.sport, local_port)
2267 self.assert_packet_checksums_valid(p)
2268 except:
2269 self.logger.error(ppp("Unexpected or invalid packet:", p))
2270 raise
2271
2272 # from client VRF0 to server VRF1 (no translation)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002273 p = (
2274 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
2275 / IP(src=self.pg0.remote_ip4, dst=self.pg5.remote_ip4)
2276 / TCP(sport=12344, dport=local_port)
2277 )
Filip Varga18f1e412020-12-03 15:27:40 +01002278 self.pg0.add_stream(p)
2279 self.pg_enable_capture(self.pg_interfaces)
2280 self.pg_start()
2281 capture = self.pg5.get_capture(1)
2282 p = capture[0]
2283 try:
2284 ip = p[IP]
2285 tcp = p[TCP]
2286 self.assertEqual(ip.dst, self.pg5.remote_ip4)
2287 self.assertEqual(tcp.dport, local_port)
2288 self.assert_packet_checksums_valid(p)
2289 except:
2290 self.logger.error(ppp("Unexpected or invalid packet:", p))
2291 raise
2292
2293 # from server VRF1 back to client VRF0 (no translation)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002294 p = (
2295 Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac)
2296 / IP(src=self.pg5.remote_ip4, dst=self.pg0.remote_ip4)
2297 / TCP(sport=local_port, dport=12344)
2298 )
Filip Varga18f1e412020-12-03 15:27:40 +01002299 self.pg5.add_stream(p)
2300 self.pg_enable_capture(self.pg_interfaces)
2301 self.pg_start()
2302 capture = self.pg0.get_capture(1)
2303 p = capture[0]
2304 try:
2305 ip = p[IP]
2306 tcp = p[TCP]
2307 self.assertEqual(ip.src, self.pg5.remote_ip4)
2308 self.assertEqual(tcp.sport, local_port)
2309 self.assert_packet_checksums_valid(p)
2310 except:
2311 self.logger.error(ppp("Unexpected or invalid packet:", p))
2312 raise
2313
Klement Sekeradc243ee2021-02-25 16:47:23 +01002314 def test_outside_address_distribution(self):
Vladislav Grishenko579a6fb2023-03-16 19:31:00 +05002315 """NAT44ED outside address distribution based on source address"""
Klement Sekeradc243ee2021-02-25 16:47:23 +01002316
Vladislav Grishenko579a6fb2023-03-16 19:31:00 +05002317 addresses = 65
Klement Sekeradc243ee2021-02-25 16:47:23 +01002318 x = 100
Klement Sekeradc243ee2021-02-25 16:47:23 +01002319
Vladislav Grishenko579a6fb2023-03-16 19:31:00 +05002320 nat_addresses = []
2321 nat_distribution = {}
2322 for i in range(1, addresses):
Klement Sekeradc243ee2021-02-25 16:47:23 +01002323 a = "10.0.0.%d" % i
2324 nat_addresses.append(a)
Vladislav Grishenko579a6fb2023-03-16 19:31:00 +05002325 nat_distribution[a] = set()
Klement Sekeradc243ee2021-02-25 16:47:23 +01002326
2327 self.nat_add_inside_interface(self.pg0)
2328 self.nat_add_outside_interface(self.pg1)
2329
2330 self.vapi.nat44_add_del_address_range(
2331 first_ip_address=nat_addresses[0],
2332 last_ip_address=nat_addresses[-1],
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002333 vrf_id=0xFFFFFFFF,
2334 is_add=1,
2335 flags=0,
2336 )
Klement Sekeradc243ee2021-02-25 16:47:23 +01002337
2338 self.pg0.generate_remote_hosts(x)
2339
2340 pkts = []
2341 for i in range(x):
Klement Sekerad2b69972021-03-09 17:53:47 +01002342 info = self.create_packet_info(self.pg0, self.pg1)
2343 payload = self.info_to_payload(info)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002344 p = (
2345 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
2346 / IP(src=self.pg0.remote_hosts[i].ip4, dst=self.pg1.remote_ip4)
2347 / UDP(sport=7000 + i, dport=8000 + i)
2348 / Raw(payload)
2349 )
Klement Sekerad2b69972021-03-09 17:53:47 +01002350 info.data = p
Klement Sekeradc243ee2021-02-25 16:47:23 +01002351 pkts.append(p)
2352
2353 self.pg0.add_stream(pkts)
2354 self.pg_enable_capture(self.pg_interfaces)
2355 self.pg_start()
2356 recvd = self.pg1.get_capture(len(pkts))
Klement Sekerad2b69972021-03-09 17:53:47 +01002357 for p_recvd in recvd:
2358 payload_info = self.payload_to_info(p_recvd[Raw])
2359 packet_index = payload_info.index
2360 info = self._packet_infos[packet_index]
2361 self.assertTrue(info is not None)
2362 self.assertEqual(packet_index, info.index)
2363 p_sent = info.data
Vladislav Grishenko579a6fb2023-03-16 19:31:00 +05002364 self.assertIn(p_recvd[IP].src, nat_distribution)
2365 nat_distribution[p_recvd[IP].src].add(p_sent[IP].src)
2366
2367 var = variance(map(len, nat_distribution.values()), x / addresses)
2368 self.assertLess(var, 0.33, msg="Bad outside address distribution")
Klement Sekeradc243ee2021-02-25 16:47:23 +01002369
Vladislav Grishenko5f694d12022-08-19 20:42:22 +05002370 def test_dynamic_edge_ports(self):
2371 """NAT44ED dynamic translation test: edge ports"""
2372
2373 worker_count = self.vpp_worker_count or 1
2374 port_offset = 1024
2375 port_per_thread = (65536 - port_offset) // worker_count
2376 port_count = port_per_thread * worker_count
2377
2378 # worker thread edge ports
2379 thread_edge_ports = {0, port_offset - 1, 65535}
2380 for i in range(0, worker_count):
2381 port_thread_offset = (port_per_thread * i) + port_offset
2382 for port_range_offset in [0, port_per_thread - 1]:
2383 port = port_thread_offset + port_range_offset
2384 thread_edge_ports.add(port)
2385 thread_drop_ports = set(
2386 filter(
2387 lambda x: x not in range(port_offset, port_offset + port_count),
2388 thread_edge_ports,
2389 )
2390 )
2391
2392 in_if = self.pg7
2393 out_if = self.pg8
2394
2395 self.nat_add_address(self.nat_addr)
2396
2397 try:
2398 self.configure_ip4_interface(in_if, hosts=worker_count)
2399 self.configure_ip4_interface(out_if)
2400
2401 self.nat_add_inside_interface(in_if)
2402 self.nat_add_outside_interface(out_if)
2403
2404 # in2out
2405 tc1 = self.statistics["/nat44-ed/in2out/slowpath/tcp"]
2406 uc1 = self.statistics["/nat44-ed/in2out/slowpath/udp"]
2407 ic1 = self.statistics["/nat44-ed/in2out/slowpath/icmp"]
2408 dc1 = self.statistics["/nat44-ed/in2out/slowpath/drops"]
2409
2410 pkt_count = worker_count * len(thread_edge_ports)
2411
2412 i2o_pkts = [[] for x in range(0, worker_count)]
2413 for i in range(0, worker_count):
2414 remote_host = in_if.remote_hosts[i]
2415 for port in thread_edge_ports:
2416 p = (
2417 Ether(dst=in_if.local_mac, src=in_if.remote_mac)
2418 / IP(src=remote_host.ip4, dst=out_if.remote_ip4)
2419 / TCP(sport=port, dport=port)
2420 )
2421 i2o_pkts[i].append(p)
2422
2423 p = (
2424 Ether(dst=in_if.local_mac, src=in_if.remote_mac)
2425 / IP(src=remote_host.ip4, dst=out_if.remote_ip4)
2426 / UDP(sport=port, dport=port)
2427 )
2428 i2o_pkts[i].append(p)
2429
2430 p = (
2431 Ether(dst=in_if.local_mac, src=in_if.remote_mac)
2432 / IP(src=remote_host.ip4, dst=out_if.remote_ip4)
2433 / ICMP(id=port, seq=port, type="echo-request")
2434 )
2435 i2o_pkts[i].append(p)
2436
2437 for i in range(0, worker_count):
2438 if len(i2o_pkts[i]) > 0:
2439 in_if.add_stream(i2o_pkts[i], worker=i)
2440
2441 self.pg_enable_capture(self.pg_interfaces)
2442 self.pg_start()
2443 capture = out_if.get_capture(pkt_count * 3)
2444 for packet in capture:
2445 self.assert_packet_checksums_valid(packet)
2446 if packet.haslayer(TCP):
2447 self.assert_in_range(
2448 packet[TCP].sport,
2449 port_offset,
2450 port_offset + port_count,
2451 "src TCP port",
2452 )
2453 elif packet.haslayer(UDP):
2454 self.assert_in_range(
2455 packet[UDP].sport,
2456 port_offset,
2457 port_offset + port_count,
2458 "src UDP port",
2459 )
2460 elif packet.haslayer(ICMP):
2461 self.assert_in_range(
2462 packet[ICMP].id,
2463 port_offset,
2464 port_offset + port_count,
2465 "ICMP id",
2466 )
2467 else:
2468 self.fail(
2469 ppp("Unexpected or invalid packet (outside network):", packet)
2470 )
2471
2472 if_idx = in_if.sw_if_index
2473 tc2 = self.statistics["/nat44-ed/in2out/slowpath/tcp"]
2474 uc2 = self.statistics["/nat44-ed/in2out/slowpath/udp"]
2475 ic2 = self.statistics["/nat44-ed/in2out/slowpath/icmp"]
2476 dc2 = self.statistics["/nat44-ed/in2out/slowpath/drops"]
2477
2478 self.assertEqual(tc2[:, if_idx].sum() - tc1[:, if_idx].sum(), pkt_count)
2479 self.assertEqual(uc2[:, if_idx].sum() - uc1[:, if_idx].sum(), pkt_count)
2480 self.assertEqual(ic2[:, if_idx].sum() - ic1[:, if_idx].sum(), pkt_count)
2481 self.assertEqual(dc2[:, if_idx].sum() - dc1[:, if_idx].sum(), 0)
2482
2483 # out2in
2484 tc1 = self.statistics["/nat44-ed/out2in/fastpath/tcp"]
2485 uc1 = self.statistics["/nat44-ed/out2in/fastpath/udp"]
2486 ic1 = self.statistics["/nat44-ed/out2in/fastpath/icmp"]
2487 dc1 = self.statistics["/nat44-ed/out2in/fastpath/drops"]
2488 dc3 = self.statistics["/nat44-ed/out2in/slowpath/drops"]
2489
2490 # replies to unchanged thread ports should pass on each worker,
2491 # excluding packets outside dynamic port range
2492 drop_count = worker_count * len(thread_drop_ports)
2493 pass_count = worker_count * len(thread_edge_ports) - drop_count
2494
2495 o2i_pkts = [[] for x in range(0, worker_count)]
2496 for i in range(0, worker_count):
2497 for port in thread_edge_ports:
2498 p = (
2499 Ether(dst=out_if.local_mac, src=out_if.remote_mac)
2500 / IP(src=out_if.remote_ip4, dst=self.nat_addr)
2501 / TCP(sport=port, dport=port)
2502 )
2503 o2i_pkts[i].append(p)
2504
2505 p = (
2506 Ether(dst=out_if.local_mac, src=out_if.remote_mac)
2507 / IP(src=out_if.remote_ip4, dst=self.nat_addr)
2508 / UDP(sport=port, dport=port)
2509 )
2510 o2i_pkts[i].append(p)
2511
2512 p = (
2513 Ether(dst=out_if.local_mac, src=out_if.remote_mac)
2514 / IP(src=out_if.remote_ip4, dst=self.nat_addr)
2515 / ICMP(id=port, seq=port, type="echo-reply")
2516 )
2517 o2i_pkts[i].append(p)
2518
2519 for i in range(0, worker_count):
2520 if len(o2i_pkts[i]) > 0:
2521 out_if.add_stream(o2i_pkts[i], worker=i)
2522
2523 self.pg_enable_capture(self.pg_interfaces)
2524 self.pg_start()
2525 capture = in_if.get_capture(pass_count * 3)
2526 for packet in capture:
2527 self.assert_packet_checksums_valid(packet)
2528 if packet.haslayer(TCP):
2529 self.assertIn(packet[TCP].dport, thread_edge_ports, "dst TCP port")
2530 self.assertEqual(packet[TCP].dport, packet[TCP].sport, "TCP ports")
2531 elif packet.haslayer(UDP):
2532 self.assertIn(packet[UDP].dport, thread_edge_ports, "dst UDP port")
2533 self.assertEqual(packet[UDP].dport, packet[UDP].sport, "UDP ports")
2534 elif packet.haslayer(ICMP):
2535 self.assertIn(packet[ICMP].id, thread_edge_ports, "ICMP id")
2536 self.assertEqual(packet[ICMP].id, packet[ICMP].seq, "ICMP id & seq")
2537 else:
2538 self.fail(
2539 ppp("Unexpected or invalid packet (inside network):", packet)
2540 )
2541
2542 if_idx = out_if.sw_if_index
2543 tc2 = self.statistics["/nat44-ed/out2in/fastpath/tcp"]
2544 uc2 = self.statistics["/nat44-ed/out2in/fastpath/udp"]
2545 ic2 = self.statistics["/nat44-ed/out2in/fastpath/icmp"]
2546 dc2 = self.statistics["/nat44-ed/out2in/fastpath/drops"]
2547 dc4 = self.statistics["/nat44-ed/out2in/slowpath/drops"]
2548
2549 self.assertEqual(tc2[:, if_idx].sum() - tc1[:, if_idx].sum(), pass_count)
2550 self.assertEqual(uc2[:, if_idx].sum() - uc1[:, if_idx].sum(), pass_count)
2551 self.assertEqual(ic2[:, if_idx].sum() - ic1[:, if_idx].sum(), pass_count)
2552 self.assertEqual(dc2[:, if_idx].sum() - dc1[:, if_idx].sum(), 0)
2553 self.assertEqual(
2554 dc4[:, if_idx].sum() - dc3[:, if_idx].sum(), drop_count * 3
2555 )
2556
2557 finally:
2558 in_if.unconfig()
2559 out_if.unconfig()
2560
Vladislav Grishenko3abb32c2022-12-04 15:02:03 +05002561 def test_delete_interface(self):
2562 """NAT44ED delete nat interface"""
2563
2564 self.nat_add_address(self.nat_addr)
2565
2566 interfaces = self.create_loopback_interfaces(4)
2567 self.nat_add_outside_interface(interfaces[0])
2568 self.nat_add_inside_interface(interfaces[1])
2569 self.nat_add_outside_interface(interfaces[2])
2570 self.nat_add_inside_interface(interfaces[2])
2571 self.vapi.nat44_ed_add_del_output_interface(
2572 sw_if_index=interfaces[3].sw_if_index, is_add=1
2573 )
2574
2575 nat_sw_if_indices = [
2576 i.sw_if_index
2577 for i in self.vapi.nat44_interface_dump()
2578 + list(self.vapi.vpp.details_iter(self.vapi.nat44_ed_output_interface_get))
2579 ]
2580 self.assertEqual(len(nat_sw_if_indices), len(interfaces))
2581
2582 loopbacks = []
2583 for i in interfaces:
2584 # delete nat-enabled interface
2585 self.assertIn(i.sw_if_index, nat_sw_if_indices)
2586 i.remove_vpp_config()
2587
2588 # create interface with the same index
2589 lo = VppLoInterface(self)
2590 loopbacks.append(lo)
2591 self.assertEqual(lo.sw_if_index, i.sw_if_index)
2592
2593 # check interface is not nat-enabled
2594 nat_sw_if_indices = [
2595 i.sw_if_index
2596 for i in self.vapi.nat44_interface_dump()
2597 + list(
2598 self.vapi.vpp.details_iter(self.vapi.nat44_ed_output_interface_get)
2599 )
2600 ]
2601 self.assertNotIn(lo.sw_if_index, nat_sw_if_indices)
2602
2603 for i in loopbacks:
2604 i.remove_vpp_config()
2605
Filip Varga18f1e412020-12-03 15:27:40 +01002606
Dave Wallace670724c2022-09-20 21:52:18 -04002607@tag_fixme_ubuntu2204
Filip Varga18f1e412020-12-03 15:27:40 +01002608class TestNAT44EDMW(TestNAT44ED):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002609 """NAT44ED MW Test Case"""
2610
Klement Sekera1fbf0342021-03-31 13:38:09 +02002611 vpp_worker_count = 4
2612 max_sessions = 5000
Filip Varga18f1e412020-12-03 15:27:40 +01002613
Filip Varga18f1e412020-12-03 15:27:40 +01002614 def test_dynamic(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002615 """NAT44ED dynamic translation test"""
Klement Sekera1fbf0342021-03-31 13:38:09 +02002616 pkt_count = 1500
2617 tcp_port_offset = 20
2618 udp_port_offset = 20
2619 icmp_id_offset = 20
Filip Varga18f1e412020-12-03 15:27:40 +01002620
2621 self.nat_add_address(self.nat_addr)
2622 self.nat_add_inside_interface(self.pg0)
2623 self.nat_add_outside_interface(self.pg1)
2624
2625 # in2out
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002626 tc1 = self.statistics["/nat44-ed/in2out/slowpath/tcp"]
2627 uc1 = self.statistics["/nat44-ed/in2out/slowpath/udp"]
2628 ic1 = self.statistics["/nat44-ed/in2out/slowpath/icmp"]
2629 dc1 = self.statistics["/nat44-ed/in2out/slowpath/drops"]
Filip Varga18f1e412020-12-03 15:27:40 +01002630
Klement Sekera1fbf0342021-03-31 13:38:09 +02002631 i2o_pkts = [[] for x in range(0, self.vpp_worker_count)]
2632
2633 for i in range(pkt_count):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002634 p = (
2635 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
2636 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
2637 / TCP(sport=tcp_port_offset + i, dport=20)
2638 )
Klement Sekera1fbf0342021-03-31 13:38:09 +02002639 i2o_pkts[p[TCP].sport % self.vpp_worker_count].append(p)
2640
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002641 p = (
2642 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
2643 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
2644 / UDP(sport=udp_port_offset + i, dport=20)
2645 )
Klement Sekera1fbf0342021-03-31 13:38:09 +02002646 i2o_pkts[p[UDP].sport % self.vpp_worker_count].append(p)
2647
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002648 p = (
2649 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
2650 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
2651 / ICMP(id=icmp_id_offset + i, type="echo-request")
2652 )
Klement Sekera1fbf0342021-03-31 13:38:09 +02002653 i2o_pkts[p[ICMP].id % self.vpp_worker_count].append(p)
2654
2655 for i in range(0, self.vpp_worker_count):
2656 if len(i2o_pkts[i]) > 0:
2657 self.pg0.add_stream(i2o_pkts[i], worker=i)
2658
Filip Varga18f1e412020-12-03 15:27:40 +01002659 self.pg_enable_capture(self.pg_interfaces)
2660 self.pg_start()
Klement Sekeraff334db2021-05-26 13:02:35 +02002661 capture = self.pg1.get_capture(pkt_count * 3, timeout=5)
Filip Varga18f1e412020-12-03 15:27:40 +01002662
2663 if_idx = self.pg0.sw_if_index
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002664 tc2 = self.statistics["/nat44-ed/in2out/slowpath/tcp"]
2665 uc2 = self.statistics["/nat44-ed/in2out/slowpath/udp"]
2666 ic2 = self.statistics["/nat44-ed/in2out/slowpath/icmp"]
2667 dc2 = self.statistics["/nat44-ed/in2out/slowpath/drops"]
Filip Varga18f1e412020-12-03 15:27:40 +01002668
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002669 self.assertEqual(tc2[:, if_idx].sum() - tc1[:, if_idx].sum(), pkt_count)
2670 self.assertEqual(uc2[:, if_idx].sum() - uc1[:, if_idx].sum(), pkt_count)
2671 self.assertEqual(ic2[:, if_idx].sum() - ic1[:, if_idx].sum(), pkt_count)
Klement Sekera3887be72021-03-30 20:29:05 +02002672 self.assertEqual(dc2[:, if_idx].sum() - dc1[:, if_idx].sum(), 0)
Filip Varga18f1e412020-12-03 15:27:40 +01002673
Klement Sekera1fbf0342021-03-31 13:38:09 +02002674 self.logger.info(self.vapi.cli("show trace"))
2675
Filip Varga18f1e412020-12-03 15:27:40 +01002676 # out2in
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002677 tc1 = self.statistics["/nat44-ed/out2in/fastpath/tcp"]
2678 uc1 = self.statistics["/nat44-ed/out2in/fastpath/udp"]
2679 ic1 = self.statistics["/nat44-ed/out2in/fastpath/icmp"]
2680 dc1 = self.statistics["/nat44-ed/out2in/fastpath/drops"]
Filip Varga18f1e412020-12-03 15:27:40 +01002681
Klement Sekera1fbf0342021-03-31 13:38:09 +02002682 recvd_tcp_ports = set()
2683 recvd_udp_ports = set()
2684 recvd_icmp_ids = set()
2685
2686 for p in capture:
2687 if TCP in p:
2688 recvd_tcp_ports.add(p[TCP].sport)
2689 if UDP in p:
2690 recvd_udp_ports.add(p[UDP].sport)
2691 if ICMP in p:
2692 recvd_icmp_ids.add(p[ICMP].id)
2693
2694 recvd_tcp_ports = list(recvd_tcp_ports)
2695 recvd_udp_ports = list(recvd_udp_ports)
2696 recvd_icmp_ids = list(recvd_icmp_ids)
2697
2698 o2i_pkts = [[] for x in range(0, self.vpp_worker_count)]
2699 for i in range(pkt_count):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002700 p = (
2701 Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac)
2702 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
2703 / TCP(dport=choice(recvd_tcp_ports), sport=20)
2704 )
Klement Sekera1fbf0342021-03-31 13:38:09 +02002705 o2i_pkts[p[TCP].dport % self.vpp_worker_count].append(p)
2706
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002707 p = (
2708 Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac)
2709 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
2710 / UDP(dport=choice(recvd_udp_ports), sport=20)
2711 )
Klement Sekera1fbf0342021-03-31 13:38:09 +02002712 o2i_pkts[p[UDP].dport % self.vpp_worker_count].append(p)
2713
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002714 p = (
2715 Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac)
2716 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
2717 / ICMP(id=choice(recvd_icmp_ids), type="echo-reply")
2718 )
Klement Sekera1fbf0342021-03-31 13:38:09 +02002719 o2i_pkts[p[ICMP].id % self.vpp_worker_count].append(p)
2720
2721 for i in range(0, self.vpp_worker_count):
2722 if len(o2i_pkts[i]) > 0:
2723 self.pg1.add_stream(o2i_pkts[i], worker=i)
2724
Filip Varga18f1e412020-12-03 15:27:40 +01002725 self.pg_enable_capture(self.pg_interfaces)
2726 self.pg_start()
Klement Sekera1fbf0342021-03-31 13:38:09 +02002727 capture = self.pg0.get_capture(pkt_count * 3)
2728 for packet in capture:
2729 try:
2730 self.assert_packet_checksums_valid(packet)
2731 self.assertEqual(packet[IP].dst, self.pg0.remote_ip4)
2732 if packet.haslayer(TCP):
2733 self.assert_in_range(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002734 packet[TCP].dport,
2735 tcp_port_offset,
2736 tcp_port_offset + pkt_count,
2737 "dst TCP port",
2738 )
Klement Sekera1fbf0342021-03-31 13:38:09 +02002739 elif packet.haslayer(UDP):
2740 self.assert_in_range(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002741 packet[UDP].dport,
2742 udp_port_offset,
2743 udp_port_offset + pkt_count,
2744 "dst UDP port",
2745 )
Klement Sekera1fbf0342021-03-31 13:38:09 +02002746 else:
2747 self.assert_in_range(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002748 packet[ICMP].id,
2749 icmp_id_offset,
2750 icmp_id_offset + pkt_count,
2751 "ICMP id",
2752 )
Klement Sekera1fbf0342021-03-31 13:38:09 +02002753 except:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002754 self.logger.error(
2755 ppp("Unexpected or invalid packet (inside network):", packet)
2756 )
Klement Sekera1fbf0342021-03-31 13:38:09 +02002757 raise
Filip Varga18f1e412020-12-03 15:27:40 +01002758
2759 if_idx = self.pg1.sw_if_index
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002760 tc2 = self.statistics["/nat44-ed/out2in/fastpath/tcp"]
2761 uc2 = self.statistics["/nat44-ed/out2in/fastpath/udp"]
2762 ic2 = self.statistics["/nat44-ed/out2in/fastpath/icmp"]
2763 dc2 = self.statistics["/nat44-ed/out2in/fastpath/drops"]
Filip Varga18f1e412020-12-03 15:27:40 +01002764
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002765 self.assertEqual(tc2[:, if_idx].sum() - tc1[:, if_idx].sum(), pkt_count)
2766 self.assertEqual(uc2[:, if_idx].sum() - uc1[:, if_idx].sum(), pkt_count)
2767 self.assertEqual(ic2[:, if_idx].sum() - ic1[:, if_idx].sum(), pkt_count)
Klement Sekera3887be72021-03-30 20:29:05 +02002768 self.assertEqual(dc2[:, if_idx].sum() - dc1[:, if_idx].sum(), 0)
Filip Varga18f1e412020-12-03 15:27:40 +01002769
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002770 sc = self.statistics["/nat44-ed/total-sessions"]
2771 self.assertEqual(
2772 sc[:, 0].sum(),
2773 len(recvd_tcp_ports) + len(recvd_udp_ports) + len(recvd_icmp_ids),
2774 )
Filip Varga18f1e412020-12-03 15:27:40 +01002775
2776 def test_frag_in_order(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002777 """NAT44ED translate fragments arriving in order"""
Filip Varga18f1e412020-12-03 15:27:40 +01002778
2779 self.nat_add_address(self.nat_addr)
2780 self.nat_add_inside_interface(self.pg0)
2781 self.nat_add_outside_interface(self.pg1)
2782
2783 self.frag_in_order(proto=IP_PROTOS.tcp, ignore_port=True)
2784 self.frag_in_order(proto=IP_PROTOS.udp, ignore_port=True)
2785 self.frag_in_order(proto=IP_PROTOS.icmp, ignore_port=True)
2786
2787 def test_frag_in_order_do_not_translate(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002788 """NAT44ED don't translate fragments arriving in order"""
Filip Varga18f1e412020-12-03 15:27:40 +01002789
2790 self.nat_add_address(self.nat_addr)
2791 self.nat_add_inside_interface(self.pg0)
2792 self.nat_add_outside_interface(self.pg1)
2793 self.vapi.nat44_forwarding_enable_disable(enable=True)
2794
2795 self.frag_in_order(proto=IP_PROTOS.tcp, dont_translate=True)
2796
2797 def test_frag_out_of_order(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002798 """NAT44ED translate fragments arriving out of order"""
Filip Varga18f1e412020-12-03 15:27:40 +01002799
2800 self.nat_add_address(self.nat_addr)
2801 self.nat_add_inside_interface(self.pg0)
2802 self.nat_add_outside_interface(self.pg1)
2803
2804 self.frag_out_of_order(proto=IP_PROTOS.tcp, ignore_port=True)
2805 self.frag_out_of_order(proto=IP_PROTOS.udp, ignore_port=True)
2806 self.frag_out_of_order(proto=IP_PROTOS.icmp, ignore_port=True)
2807
2808 def test_frag_in_order_in_plus_out(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002809 """NAT44ED in+out interface fragments in order"""
Filip Varga18f1e412020-12-03 15:27:40 +01002810
2811 in_port = self.random_port()
2812 out_port = self.random_port()
2813
2814 self.nat_add_address(self.nat_addr)
2815 self.nat_add_inside_interface(self.pg0)
2816 self.nat_add_outside_interface(self.pg0)
2817 self.nat_add_inside_interface(self.pg1)
2818 self.nat_add_outside_interface(self.pg1)
2819
2820 # add static mappings for server
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002821 self.nat_add_static_mapping(
2822 self.server_addr, self.nat_addr, in_port, out_port, proto=IP_PROTOS.tcp
2823 )
2824 self.nat_add_static_mapping(
2825 self.server_addr, self.nat_addr, in_port, out_port, proto=IP_PROTOS.udp
2826 )
2827 self.nat_add_static_mapping(
2828 self.server_addr, self.nat_addr, proto=IP_PROTOS.icmp
2829 )
Filip Varga18f1e412020-12-03 15:27:40 +01002830
2831 # run tests for each protocol
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002832 self.frag_in_order_in_plus_out(
2833 self.server_addr, self.nat_addr, in_port, out_port, IP_PROTOS.tcp
2834 )
2835 self.frag_in_order_in_plus_out(
2836 self.server_addr, self.nat_addr, in_port, out_port, IP_PROTOS.udp
2837 )
2838 self.frag_in_order_in_plus_out(
2839 self.server_addr, self.nat_addr, in_port, out_port, IP_PROTOS.icmp
2840 )
Filip Varga18f1e412020-12-03 15:27:40 +01002841
2842 def test_frag_out_of_order_in_plus_out(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002843 """NAT44ED in+out interface fragments out of order"""
Filip Varga18f1e412020-12-03 15:27:40 +01002844
2845 in_port = self.random_port()
2846 out_port = self.random_port()
2847
2848 self.nat_add_address(self.nat_addr)
2849 self.nat_add_inside_interface(self.pg0)
2850 self.nat_add_outside_interface(self.pg0)
2851 self.nat_add_inside_interface(self.pg1)
2852 self.nat_add_outside_interface(self.pg1)
2853
2854 # add static mappings for server
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002855 self.nat_add_static_mapping(
2856 self.server_addr, self.nat_addr, in_port, out_port, proto=IP_PROTOS.tcp
2857 )
2858 self.nat_add_static_mapping(
2859 self.server_addr, self.nat_addr, in_port, out_port, proto=IP_PROTOS.udp
2860 )
2861 self.nat_add_static_mapping(
2862 self.server_addr, self.nat_addr, proto=IP_PROTOS.icmp
2863 )
Filip Varga18f1e412020-12-03 15:27:40 +01002864
2865 # run tests for each protocol
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002866 self.frag_out_of_order_in_plus_out(
2867 self.server_addr, self.nat_addr, in_port, out_port, IP_PROTOS.tcp
2868 )
2869 self.frag_out_of_order_in_plus_out(
2870 self.server_addr, self.nat_addr, in_port, out_port, IP_PROTOS.udp
2871 )
2872 self.frag_out_of_order_in_plus_out(
2873 self.server_addr, self.nat_addr, in_port, out_port, IP_PROTOS.icmp
2874 )
Filip Varga18f1e412020-12-03 15:27:40 +01002875
2876 def test_reass_hairpinning(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002877 """NAT44ED fragments hairpinning"""
Filip Varga18f1e412020-12-03 15:27:40 +01002878
2879 server_addr = self.pg0.remote_hosts[1].ip4
2880
2881 host_in_port = self.random_port()
2882 server_in_port = self.random_port()
2883 server_out_port = self.random_port()
2884
2885 self.nat_add_address(self.nat_addr)
2886 self.nat_add_inside_interface(self.pg0)
2887 self.nat_add_outside_interface(self.pg1)
2888
2889 # add static mapping for server
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002890 self.nat_add_static_mapping(
2891 server_addr,
2892 self.nat_addr,
2893 server_in_port,
2894 server_out_port,
2895 proto=IP_PROTOS.tcp,
2896 )
2897 self.nat_add_static_mapping(
2898 server_addr,
2899 self.nat_addr,
2900 server_in_port,
2901 server_out_port,
2902 proto=IP_PROTOS.udp,
2903 )
Filip Varga18f1e412020-12-03 15:27:40 +01002904 self.nat_add_static_mapping(server_addr, self.nat_addr)
2905
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002906 self.reass_hairpinning(
2907 server_addr,
2908 server_in_port,
2909 server_out_port,
2910 host_in_port,
2911 proto=IP_PROTOS.tcp,
2912 ignore_port=True,
2913 )
2914 self.reass_hairpinning(
2915 server_addr,
2916 server_in_port,
2917 server_out_port,
2918 host_in_port,
2919 proto=IP_PROTOS.udp,
2920 ignore_port=True,
2921 )
2922 self.reass_hairpinning(
2923 server_addr,
2924 server_in_port,
2925 server_out_port,
2926 host_in_port,
2927 proto=IP_PROTOS.icmp,
2928 ignore_port=True,
2929 )
Filip Varga18f1e412020-12-03 15:27:40 +01002930
2931 def test_session_limit_per_vrf(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002932 """NAT44ED per vrf session limit"""
Filip Varga18f1e412020-12-03 15:27:40 +01002933
2934 inside = self.pg0
2935 inside_vrf10 = self.pg2
2936 outside = self.pg1
2937
2938 limit = 5
2939
Vladislav Grishenko5b3e04c2022-09-05 10:32:46 +05002940 # 2 interfaces pg0, pg1 (vrf10, limit 5 tcp sessions)
Filip Varga18f1e412020-12-03 15:27:40 +01002941 self.vapi.nat44_set_session_limit(session_limit=limit, vrf_id=10)
2942
Vladislav Grishenko5b3e04c2022-09-05 10:32:46 +05002943 # expect error when bad is specified
2944 with self.vapi.assert_negative_api_retval():
2945 self.vapi.nat44_set_session_limit(session_limit=limit, vrf_id=20)
2946
Filip Varga18f1e412020-12-03 15:27:40 +01002947 self.nat_add_inside_interface(inside)
2948 self.nat_add_inside_interface(inside_vrf10)
2949 self.nat_add_outside_interface(outside)
2950
2951 # vrf independent
2952 self.nat_add_interface_address(outside)
2953
2954 # BUG: causing core dump - when bad vrf_id is specified
2955 # self.nat_add_address(outside.local_ip4, vrf_id=20)
2956
2957 stream = self.create_tcp_stream(inside_vrf10, outside, limit * 2)
2958 inside_vrf10.add_stream(stream)
2959
2960 self.pg_enable_capture(self.pg_interfaces)
2961 self.pg_start()
2962
2963 capture = outside.get_capture(limit)
2964
2965 stream = self.create_tcp_stream(inside, outside, limit * 2)
2966 inside.add_stream(stream)
2967
2968 self.pg_enable_capture(self.pg_interfaces)
2969 self.pg_start()
2970
2971 capture = outside.get_capture(len(stream))
2972
Filip Varga18f1e412020-12-03 15:27:40 +01002973 def test_show_max_translations(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002974 """NAT44ED API test - max translations per thread"""
Filip Vargab6810822022-02-15 11:56:07 -08002975 config = self.vapi.nat44_show_running_config()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002976 self.assertEqual(self.max_sessions, config.sessions)
Filip Varga18f1e412020-12-03 15:27:40 +01002977
2978 def test_lru_cleanup(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002979 """NAT44ED LRU cleanup algorithm"""
Filip Varga18f1e412020-12-03 15:27:40 +01002980
2981 self.nat_add_address(self.nat_addr)
2982 self.nat_add_inside_interface(self.pg0)
2983 self.nat_add_outside_interface(self.pg1)
2984
2985 self.vapi.nat_set_timeouts(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002986 udp=1, tcp_established=7440, tcp_transitory=30, icmp=1
2987 )
Filip Varga18f1e412020-12-03 15:27:40 +01002988
2989 tcp_port_out = self.init_tcp_session(self.pg0, self.pg1, 2000, 80)
2990 pkts = []
2991 for i in range(0, self.max_sessions - 1):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002992 p = (
2993 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
2994 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4, ttl=64)
2995 / UDP(sport=7000 + i, dport=80)
2996 )
Filip Varga18f1e412020-12-03 15:27:40 +01002997 pkts.append(p)
2998
2999 self.pg0.add_stream(pkts)
3000 self.pg_enable_capture(self.pg_interfaces)
3001 self.pg_start()
3002 self.pg1.get_capture(len(pkts))
Benoît Ganne56eccdb2021-08-20 09:18:31 +02003003 self.virtual_sleep(1.5, "wait for timeouts")
Filip Varga18f1e412020-12-03 15:27:40 +01003004
3005 pkts = []
3006 for i in range(0, self.max_sessions - 1):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003007 p = (
3008 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
3009 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4, ttl=64)
3010 / ICMP(id=8000 + i, type="echo-request")
3011 )
Filip Varga18f1e412020-12-03 15:27:40 +01003012 pkts.append(p)
3013
3014 self.pg0.add_stream(pkts)
3015 self.pg_enable_capture(self.pg_interfaces)
3016 self.pg_start()
3017 self.pg1.get_capture(len(pkts))
3018
3019 def test_session_rst_timeout(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003020 """NAT44ED session RST timeouts"""
Filip Varga18f1e412020-12-03 15:27:40 +01003021
3022 self.nat_add_address(self.nat_addr)
3023 self.nat_add_inside_interface(self.pg0)
3024 self.nat_add_outside_interface(self.pg1)
3025
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003026 self.vapi.nat_set_timeouts(
3027 udp=300, tcp_established=7440, tcp_transitory=5, icmp=60
3028 )
Filip Varga18f1e412020-12-03 15:27:40 +01003029
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003030 self.init_tcp_session(
3031 self.pg0, self.pg1, self.tcp_port_in, self.tcp_external_port
3032 )
3033 p = (
3034 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
3035 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
3036 / TCP(sport=self.tcp_port_in, dport=self.tcp_external_port, flags="R")
3037 )
Klement Sekera56c492a2022-01-10 21:57:27 +00003038 self.send_and_expect(self.pg0, p, self.pg1)
Filip Varga18f1e412020-12-03 15:27:40 +01003039
Benoît Ganne56eccdb2021-08-20 09:18:31 +02003040 self.virtual_sleep(6)
Filip Varga18f1e412020-12-03 15:27:40 +01003041
Klement Sekera56c492a2022-01-10 21:57:27 +00003042 # The session is already closed
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003043 p = (
3044 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
3045 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
3046 / TCP(sport=self.tcp_port_in, dport=self.tcp_external_port, flags="P")
3047 )
Klement Sekera56c492a2022-01-10 21:57:27 +00003048 self.send_and_assert_no_replies(self.pg0, p, self.pg1)
3049
3050 # The session can be re-opened
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003051 p = (
3052 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
3053 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
3054 / TCP(sport=self.tcp_port_in, dport=self.tcp_external_port, flags="S")
3055 )
Klement Sekera56c492a2022-01-10 21:57:27 +00003056 self.send_and_expect(self.pg0, p, self.pg1)
3057
3058 def test_session_rst_established_timeout(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003059 """NAT44ED session RST timeouts"""
Klement Sekera56c492a2022-01-10 21:57:27 +00003060
3061 self.nat_add_address(self.nat_addr)
3062 self.nat_add_inside_interface(self.pg0)
3063 self.nat_add_outside_interface(self.pg1)
3064
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003065 self.vapi.nat_set_timeouts(
3066 udp=300, tcp_established=7440, tcp_transitory=5, icmp=60
3067 )
Klement Sekera56c492a2022-01-10 21:57:27 +00003068
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003069 self.init_tcp_session(
3070 self.pg0, self.pg1, self.tcp_port_in, self.tcp_external_port
3071 )
Klement Sekera56c492a2022-01-10 21:57:27 +00003072
3073 # Wait at least the transitory time, the session is in established
Ole Troan52974472022-03-17 11:58:38 +01003074 # state anyway. RST followed by a data packet should move it to
3075 # transitory state.
Klement Sekera56c492a2022-01-10 21:57:27 +00003076 self.virtual_sleep(6)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003077 p = (
3078 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
3079 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
3080 / TCP(sport=self.tcp_port_in, dport=self.tcp_external_port, flags="R")
3081 )
Klement Sekera56c492a2022-01-10 21:57:27 +00003082 self.send_and_expect(self.pg0, p, self.pg1)
3083
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003084 p = (
3085 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
3086 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
3087 / TCP(sport=self.tcp_port_in, dport=self.tcp_external_port, flags="P")
3088 )
Klement Sekera56c492a2022-01-10 21:57:27 +00003089 self.send_and_expect(self.pg0, p, self.pg1)
3090
Klement Sekera56c492a2022-01-10 21:57:27 +00003091 # State is transitory, session should be closed after 6 seconds
3092 self.virtual_sleep(6)
3093
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003094 p = (
3095 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
3096 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
3097 / TCP(sport=self.tcp_port_in, dport=self.tcp_external_port, flags="P")
3098 )
Klement Sekera56c492a2022-01-10 21:57:27 +00003099 self.send_and_assert_no_replies(self.pg0, p, self.pg1)
Filip Varga18f1e412020-12-03 15:27:40 +01003100
3101 def test_dynamic_out_of_ports(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003102 """NAT44ED dynamic translation test: out of ports"""
Filip Varga18f1e412020-12-03 15:27:40 +01003103
3104 self.nat_add_inside_interface(self.pg0)
3105 self.nat_add_outside_interface(self.pg1)
3106
3107 # in2out and no NAT addresses added
Filip Varga18f1e412020-12-03 15:27:40 +01003108 pkts = self.create_stream_in(self.pg0, self.pg1)
Filip Varga18f1e412020-12-03 15:27:40 +01003109
Klement Sekeraad3187f2022-02-18 10:34:35 +00003110 self.send_and_assert_no_replies(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003111 self.pg0,
3112 pkts,
3113 msg="i2o pkts",
3114 stats_diff=self.no_diff
3115 | {
Klement Sekeraad3187f2022-02-18 10:34:35 +00003116 "err": {
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003117 "/err/nat44-ed-in2out-slowpath/out of ports": len(pkts),
Klement Sekeraad3187f2022-02-18 10:34:35 +00003118 },
3119 self.pg0.sw_if_index: {
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003120 "/nat44-ed/in2out/slowpath/drops": len(pkts),
Klement Sekeraad3187f2022-02-18 10:34:35 +00003121 },
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003122 },
Klement Sekeraad3187f2022-02-18 10:34:35 +00003123 )
Filip Varga18f1e412020-12-03 15:27:40 +01003124
3125 # in2out after NAT addresses added
3126 self.nat_add_address(self.nat_addr)
3127
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003128 tcpn, udpn, icmpn = (
3129 sum(x) for x in zip(*((TCP in p, UDP in p, ICMP in p) for p in pkts))
3130 )
Filip Varga18f1e412020-12-03 15:27:40 +01003131
Klement Sekeraad3187f2022-02-18 10:34:35 +00003132 self.send_and_expect(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003133 self.pg0,
3134 pkts,
3135 self.pg1,
3136 msg="i2o pkts",
3137 stats_diff=self.no_diff
3138 | {
Klement Sekeraad3187f2022-02-18 10:34:35 +00003139 "err": {
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003140 "/err/nat44-ed-in2out-slowpath/out of ports": 0,
Klement Sekeraad3187f2022-02-18 10:34:35 +00003141 },
3142 self.pg0.sw_if_index: {
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003143 "/nat44-ed/in2out/slowpath/drops": 0,
3144 "/nat44-ed/in2out/slowpath/tcp": tcpn,
3145 "/nat44-ed/in2out/slowpath/udp": udpn,
3146 "/nat44-ed/in2out/slowpath/icmp": icmpn,
Klement Sekeraad3187f2022-02-18 10:34:35 +00003147 },
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003148 },
Klement Sekeraad3187f2022-02-18 10:34:35 +00003149 )
Filip Varga18f1e412020-12-03 15:27:40 +01003150
3151 def test_unknown_proto(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003152 """NAT44ED translate packet with unknown protocol"""
Filip Varga18f1e412020-12-03 15:27:40 +01003153
3154 self.nat_add_address(self.nat_addr)
3155 self.nat_add_inside_interface(self.pg0)
3156 self.nat_add_outside_interface(self.pg1)
3157
3158 # in2out
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003159 p = (
3160 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
3161 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
3162 / TCP(sport=self.tcp_port_in, dport=20)
3163 )
Filip Varga18f1e412020-12-03 15:27:40 +01003164 self.pg0.add_stream(p)
3165 self.pg_enable_capture(self.pg_interfaces)
3166 self.pg_start()
3167 p = self.pg1.get_capture(1)
3168
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003169 p = (
3170 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
3171 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
3172 / GRE()
3173 / IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4)
3174 / TCP(sport=1234, dport=1234)
3175 )
Filip Varga18f1e412020-12-03 15:27:40 +01003176 self.pg0.add_stream(p)
3177 self.pg_enable_capture(self.pg_interfaces)
3178 self.pg_start()
3179 p = self.pg1.get_capture(1)
3180 packet = p[0]
3181 try:
3182 self.assertEqual(packet[IP].src, self.nat_addr)
3183 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
3184 self.assertEqual(packet.haslayer(GRE), 1)
3185 self.assert_packet_checksums_valid(packet)
3186 except:
3187 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3188 raise
3189
3190 # out2in
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003191 p = (
3192 Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac)
3193 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
3194 / GRE()
3195 / IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4)
3196 / TCP(sport=1234, dport=1234)
3197 )
Filip Varga18f1e412020-12-03 15:27:40 +01003198 self.pg1.add_stream(p)
3199 self.pg_enable_capture(self.pg_interfaces)
3200 self.pg_start()
3201 p = self.pg0.get_capture(1)
3202 packet = p[0]
3203 try:
3204 self.assertEqual(packet[IP].src, self.pg1.remote_ip4)
3205 self.assertEqual(packet[IP].dst, self.pg0.remote_ip4)
3206 self.assertEqual(packet.haslayer(GRE), 1)
3207 self.assert_packet_checksums_valid(packet)
3208 except:
3209 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3210 raise
3211
3212 def test_hairpinning_unknown_proto(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003213 """NAT44ED translate packet with unknown protocol - hairpinning"""
Filip Varga18f1e412020-12-03 15:27:40 +01003214 host = self.pg0.remote_hosts[0]
3215 server = self.pg0.remote_hosts[1]
3216 host_in_port = 1234
3217 server_out_port = 8765
3218 server_nat_ip = "10.0.0.11"
3219
3220 self.nat_add_address(self.nat_addr)
3221 self.nat_add_inside_interface(self.pg0)
3222 self.nat_add_outside_interface(self.pg1)
3223
3224 # add static mapping for server
3225 self.nat_add_static_mapping(server.ip4, server_nat_ip)
3226
3227 # host to server
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003228 p = (
3229 Ether(src=host.mac, dst=self.pg0.local_mac)
3230 / IP(src=host.ip4, dst=server_nat_ip)
3231 / TCP(sport=host_in_port, dport=server_out_port)
3232 )
Filip Varga18f1e412020-12-03 15:27:40 +01003233 self.pg0.add_stream(p)
3234 self.pg_enable_capture(self.pg_interfaces)
3235 self.pg_start()
3236 self.pg0.get_capture(1)
3237
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003238 p = (
3239 Ether(dst=self.pg0.local_mac, src=host.mac)
3240 / IP(src=host.ip4, dst=server_nat_ip)
3241 / GRE()
3242 / IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4)
3243 / TCP(sport=1234, dport=1234)
3244 )
Filip Varga18f1e412020-12-03 15:27:40 +01003245 self.pg0.add_stream(p)
3246 self.pg_enable_capture(self.pg_interfaces)
3247 self.pg_start()
3248 p = self.pg0.get_capture(1)
3249 packet = p[0]
3250 try:
3251 self.assertEqual(packet[IP].src, self.nat_addr)
3252 self.assertEqual(packet[IP].dst, server.ip4)
3253 self.assertEqual(packet.haslayer(GRE), 1)
3254 self.assert_packet_checksums_valid(packet)
3255 except:
3256 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3257 raise
3258
3259 # server to host
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003260 p = (
3261 Ether(dst=self.pg0.local_mac, src=server.mac)
3262 / IP(src=server.ip4, dst=self.nat_addr)
3263 / GRE()
3264 / IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4)
3265 / TCP(sport=1234, dport=1234)
3266 )
Filip Varga18f1e412020-12-03 15:27:40 +01003267 self.pg0.add_stream(p)
3268 self.pg_enable_capture(self.pg_interfaces)
3269 self.pg_start()
3270 p = self.pg0.get_capture(1)
3271 packet = p[0]
3272 try:
3273 self.assertEqual(packet[IP].src, server_nat_ip)
3274 self.assertEqual(packet[IP].dst, host.ip4)
3275 self.assertEqual(packet.haslayer(GRE), 1)
3276 self.assert_packet_checksums_valid(packet)
3277 except:
3278 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3279 raise
3280
3281 def test_output_feature_and_service(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003282 """NAT44ED interface output feature and services"""
3283 external_addr = "1.2.3.4"
Filip Varga18f1e412020-12-03 15:27:40 +01003284 external_port = 80
3285 local_port = 8080
3286
3287 self.vapi.nat44_forwarding_enable_disable(enable=1)
3288 self.nat_add_address(self.nat_addr)
3289 flags = self.config_flags.NAT_IS_ADDR_ONLY
3290 self.vapi.nat44_add_del_identity_mapping(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003291 ip_address=self.pg1.remote_ip4,
3292 sw_if_index=0xFFFFFFFF,
3293 flags=flags,
3294 is_add=1,
3295 )
Filip Varga18f1e412020-12-03 15:27:40 +01003296 flags = self.config_flags.NAT_IS_OUT2IN_ONLY
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003297 self.nat_add_static_mapping(
3298 self.pg0.remote_ip4,
3299 external_addr,
3300 local_port,
3301 external_port,
3302 proto=IP_PROTOS.tcp,
3303 flags=flags,
3304 )
Filip Varga18f1e412020-12-03 15:27:40 +01003305
3306 self.nat_add_inside_interface(self.pg0)
3307 self.nat_add_outside_interface(self.pg0)
Filip Varga9c25eb12021-10-21 13:00:27 +02003308 self.vapi.nat44_ed_add_del_output_interface(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003309 sw_if_index=self.pg1.sw_if_index, is_add=1
3310 )
Filip Varga18f1e412020-12-03 15:27:40 +01003311
3312 # from client to service
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003313 p = (
3314 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
3315 / IP(src=self.pg1.remote_ip4, dst=external_addr)
3316 / TCP(sport=12345, dport=external_port)
3317 )
Filip Varga18f1e412020-12-03 15:27:40 +01003318 self.pg1.add_stream(p)
3319 self.pg_enable_capture(self.pg_interfaces)
3320 self.pg_start()
3321 capture = self.pg0.get_capture(1)
3322 p = capture[0]
3323 try:
3324 ip = p[IP]
3325 tcp = p[TCP]
3326 self.assertEqual(ip.dst, self.pg0.remote_ip4)
3327 self.assertEqual(tcp.dport, local_port)
3328 self.assert_packet_checksums_valid(p)
3329 except:
3330 self.logger.error(ppp("Unexpected or invalid packet:", p))
3331 raise
3332
3333 # from service back to client
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003334 p = (
3335 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
3336 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
3337 / TCP(sport=local_port, dport=12345)
3338 )
Filip Varga18f1e412020-12-03 15:27:40 +01003339 self.pg0.add_stream(p)
3340 self.pg_enable_capture(self.pg_interfaces)
3341 self.pg_start()
3342 capture = self.pg1.get_capture(1)
3343 p = capture[0]
3344 try:
3345 ip = p[IP]
3346 tcp = p[TCP]
3347 self.assertEqual(ip.src, external_addr)
3348 self.assertEqual(tcp.sport, external_port)
3349 self.assert_packet_checksums_valid(p)
3350 except:
3351 self.logger.error(ppp("Unexpected or invalid packet:", p))
3352 raise
3353
3354 # from local network host to external network
3355 pkts = self.create_stream_in(self.pg0, self.pg1)
3356 self.pg0.add_stream(pkts)
3357 self.pg_enable_capture(self.pg_interfaces)
3358 self.pg_start()
3359 capture = self.pg1.get_capture(len(pkts))
3360 self.verify_capture_out(capture, ignore_port=True)
3361 pkts = self.create_stream_in(self.pg0, self.pg1)
3362 self.pg0.add_stream(pkts)
3363 self.pg_enable_capture(self.pg_interfaces)
3364 self.pg_start()
3365 capture = self.pg1.get_capture(len(pkts))
3366 self.verify_capture_out(capture, ignore_port=True)
3367
3368 # from external network back to local network host
3369 pkts = self.create_stream_out(self.pg1)
3370 self.pg1.add_stream(pkts)
3371 self.pg_enable_capture(self.pg_interfaces)
3372 self.pg_start()
3373 capture = self.pg0.get_capture(len(pkts))
3374 self.verify_capture_in(capture, self.pg0)
3375
3376 def test_output_feature_and_service3(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003377 """NAT44ED interface output feature and DST NAT"""
3378 external_addr = "1.2.3.4"
Filip Varga18f1e412020-12-03 15:27:40 +01003379 external_port = 80
3380 local_port = 8080
3381
3382 self.vapi.nat44_forwarding_enable_disable(enable=1)
3383 self.nat_add_address(self.nat_addr)
3384 flags = self.config_flags.NAT_IS_OUT2IN_ONLY
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003385 self.nat_add_static_mapping(
3386 self.pg1.remote_ip4,
3387 external_addr,
3388 local_port,
3389 external_port,
3390 proto=IP_PROTOS.tcp,
3391 flags=flags,
3392 )
Filip Varga18f1e412020-12-03 15:27:40 +01003393
3394 self.nat_add_inside_interface(self.pg0)
3395 self.nat_add_outside_interface(self.pg0)
Filip Varga9c25eb12021-10-21 13:00:27 +02003396 self.vapi.nat44_ed_add_del_output_interface(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003397 sw_if_index=self.pg1.sw_if_index, is_add=1
3398 )
Filip Varga18f1e412020-12-03 15:27:40 +01003399
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003400 p = (
3401 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
3402 / IP(src=self.pg0.remote_ip4, dst=external_addr)
3403 / TCP(sport=12345, dport=external_port)
3404 )
Filip Varga18f1e412020-12-03 15:27:40 +01003405 self.pg0.add_stream(p)
3406 self.pg_enable_capture(self.pg_interfaces)
3407 self.pg_start()
3408 capture = self.pg1.get_capture(1)
3409 p = capture[0]
3410 try:
3411 ip = p[IP]
3412 tcp = p[TCP]
3413 self.assertEqual(ip.src, self.pg0.remote_ip4)
3414 self.assertEqual(tcp.sport, 12345)
3415 self.assertEqual(ip.dst, self.pg1.remote_ip4)
3416 self.assertEqual(tcp.dport, local_port)
3417 self.assert_packet_checksums_valid(p)
3418 except:
3419 self.logger.error(ppp("Unexpected or invalid packet:", p))
3420 raise
3421
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003422 p = (
3423 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
3424 / IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4)
3425 / TCP(sport=local_port, dport=12345)
3426 )
Filip Varga18f1e412020-12-03 15:27:40 +01003427 self.pg1.add_stream(p)
3428 self.pg_enable_capture(self.pg_interfaces)
3429 self.pg_start()
3430 capture = self.pg0.get_capture(1)
3431 p = capture[0]
3432 try:
3433 ip = p[IP]
3434 tcp = p[TCP]
3435 self.assertEqual(ip.src, external_addr)
3436 self.assertEqual(tcp.sport, external_port)
3437 self.assertEqual(ip.dst, self.pg0.remote_ip4)
3438 self.assertEqual(tcp.dport, 12345)
3439 self.assert_packet_checksums_valid(p)
3440 except:
3441 self.logger.error(ppp("Unexpected or invalid packet:", p))
3442 raise
3443
3444 def test_self_twice_nat_lb_negative(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003445 """NAT44ED Self Twice NAT local service load balancing (negative test)"""
3446 self.twice_nat_common(lb=True, self_twice_nat=True, same_pg=True, client_id=2)
Filip Varga18f1e412020-12-03 15:27:40 +01003447
3448 def test_self_twice_nat_negative(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003449 """NAT44ED Self Twice NAT (negative test)"""
Filip Varga18f1e412020-12-03 15:27:40 +01003450 self.twice_nat_common(self_twice_nat=True)
3451
3452 def test_static_lb_multi_clients(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003453 """NAT44ED local service load balancing - multiple clients"""
Filip Varga18f1e412020-12-03 15:27:40 +01003454
3455 external_addr = self.nat_addr
3456 external_port = 80
3457 local_port = 8080
3458 server1 = self.pg0.remote_hosts[0]
3459 server2 = self.pg0.remote_hosts[1]
3460 server3 = self.pg0.remote_hosts[2]
3461
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003462 locals = [
3463 {"addr": server1.ip4, "port": local_port, "probability": 90, "vrf_id": 0},
3464 {"addr": server2.ip4, "port": local_port, "probability": 10, "vrf_id": 0},
3465 ]
Filip Varga18f1e412020-12-03 15:27:40 +01003466
3467 flags = self.config_flags.NAT_IS_INSIDE
3468 self.vapi.nat44_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003469 sw_if_index=self.pg0.sw_if_index, flags=flags, is_add=1
3470 )
Filip Varga18f1e412020-12-03 15:27:40 +01003471 self.vapi.nat44_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003472 sw_if_index=self.pg1.sw_if_index, is_add=1
3473 )
Filip Varga18f1e412020-12-03 15:27:40 +01003474
3475 self.nat_add_address(self.nat_addr)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003476 self.vapi.nat44_add_del_lb_static_mapping(
3477 is_add=1,
3478 external_addr=external_addr,
3479 external_port=external_port,
3480 protocol=IP_PROTOS.tcp,
3481 local_num=len(locals),
3482 locals=locals,
3483 )
Filip Varga18f1e412020-12-03 15:27:40 +01003484
3485 server1_n = 0
3486 server2_n = 0
3487 clients = ip4_range(self.pg1.remote_ip4, 10, 50)
3488 pkts = []
3489 for client in clients:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003490 p = (
3491 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
3492 / IP(src=client, dst=self.nat_addr)
3493 / TCP(sport=12345, dport=external_port)
3494 )
Filip Varga18f1e412020-12-03 15:27:40 +01003495 pkts.append(p)
3496 self.pg1.add_stream(pkts)
3497 self.pg_enable_capture(self.pg_interfaces)
3498 self.pg_start()
3499 capture = self.pg0.get_capture(len(pkts))
3500 for p in capture:
3501 if p[IP].dst == server1.ip4:
3502 server1_n += 1
3503 else:
3504 server2_n += 1
Klement Sekera1fbf0342021-03-31 13:38:09 +02003505 self.assertGreaterEqual(server1_n, server2_n)
Filip Varga18f1e412020-12-03 15:27:40 +01003506
3507 local = {
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003508 "addr": server3.ip4,
3509 "port": local_port,
3510 "probability": 20,
3511 "vrf_id": 0,
Filip Varga18f1e412020-12-03 15:27:40 +01003512 }
3513
3514 # add new back-end
3515 self.vapi.nat44_lb_static_mapping_add_del_local(
3516 is_add=1,
3517 external_addr=external_addr,
3518 external_port=external_port,
3519 local=local,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003520 protocol=IP_PROTOS.tcp,
3521 )
Filip Varga18f1e412020-12-03 15:27:40 +01003522 server1_n = 0
3523 server2_n = 0
3524 server3_n = 0
3525 clients = ip4_range(self.pg1.remote_ip4, 60, 110)
3526 pkts = []
3527 for client in clients:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003528 p = (
3529 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
3530 / IP(src=client, dst=self.nat_addr)
3531 / TCP(sport=12346, dport=external_port)
3532 )
Filip Varga18f1e412020-12-03 15:27:40 +01003533 pkts.append(p)
3534 self.assertGreater(len(pkts), 0)
3535 self.pg1.add_stream(pkts)
3536 self.pg_enable_capture(self.pg_interfaces)
3537 self.pg_start()
3538 capture = self.pg0.get_capture(len(pkts))
3539 for p in capture:
3540 if p[IP].dst == server1.ip4:
3541 server1_n += 1
3542 elif p[IP].dst == server2.ip4:
3543 server2_n += 1
3544 else:
3545 server3_n += 1
3546 self.assertGreater(server1_n, 0)
3547 self.assertGreater(server2_n, 0)
3548 self.assertGreater(server3_n, 0)
3549
3550 local = {
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003551 "addr": server2.ip4,
3552 "port": local_port,
3553 "probability": 10,
3554 "vrf_id": 0,
Filip Varga18f1e412020-12-03 15:27:40 +01003555 }
3556
3557 # remove one back-end
3558 self.vapi.nat44_lb_static_mapping_add_del_local(
3559 is_add=0,
3560 external_addr=external_addr,
3561 external_port=external_port,
3562 local=local,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003563 protocol=IP_PROTOS.tcp,
3564 )
Filip Varga18f1e412020-12-03 15:27:40 +01003565 server1_n = 0
3566 server2_n = 0
3567 server3_n = 0
3568 self.pg1.add_stream(pkts)
3569 self.pg_enable_capture(self.pg_interfaces)
3570 self.pg_start()
3571 capture = self.pg0.get_capture(len(pkts))
3572 for p in capture:
3573 if p[IP].dst == server1.ip4:
3574 server1_n += 1
3575 elif p[IP].dst == server2.ip4:
3576 server2_n += 1
3577 else:
3578 server3_n += 1
3579 self.assertGreater(server1_n, 0)
3580 self.assertEqual(server2_n, 0)
3581 self.assertGreater(server3_n, 0)
3582
Klement Sekera56c492a2022-01-10 21:57:27 +00003583 # put zzz in front of syslog test name so that it runs as a last test
3584 # setting syslog sender cannot be undone and if it is set, it messes
3585 # with self.send_and_assert_no_replies functionality
3586 def test_zzz_syslog_sess(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003587 """NAT44ED Test syslog session creation and deletion"""
3588 self.vapi.syslog_set_filter(self.syslog_severity.SYSLOG_API_SEVERITY_INFO)
Filip Varga18f1e412020-12-03 15:27:40 +01003589 self.vapi.syslog_set_sender(self.pg3.local_ip4, self.pg3.remote_ip4)
3590
3591 self.nat_add_address(self.nat_addr)
3592 self.nat_add_inside_interface(self.pg0)
3593 self.nat_add_outside_interface(self.pg1)
3594
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003595 p = (
3596 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
3597 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
3598 / TCP(sport=self.tcp_port_in, dport=self.tcp_external_port)
3599 )
Filip Varga18f1e412020-12-03 15:27:40 +01003600 self.pg0.add_stream(p)
3601 self.pg_enable_capture(self.pg_interfaces)
3602 self.pg_start()
3603 capture = self.pg1.get_capture(1)
3604 self.tcp_port_out = capture[0][TCP].sport
3605 capture = self.pg3.get_capture(1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003606 self.verify_syslog_sess(capture[0][Raw].load, "SADD")
Filip Varga18f1e412020-12-03 15:27:40 +01003607
3608 self.pg_enable_capture(self.pg_interfaces)
3609 self.pg_start()
3610 self.nat_add_address(self.nat_addr, is_add=0)
3611 capture = self.pg3.get_capture(1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003612 self.verify_syslog_sess(capture[0][Raw].load, "SDEL")
Klement Sekera56c492a2022-01-10 21:57:27 +00003613
3614 # put zzz in front of syslog test name so that it runs as a last test
3615 # setting syslog sender cannot be undone and if it is set, it messes
3616 # with self.send_and_assert_no_replies functionality
3617 def test_zzz_syslog_sess_reopen(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003618 """Syslog events for session reopen"""
3619 self.vapi.syslog_set_filter(self.syslog_severity.SYSLOG_API_SEVERITY_INFO)
Klement Sekera56c492a2022-01-10 21:57:27 +00003620 self.vapi.syslog_set_sender(self.pg3.local_ip4, self.pg3.remote_ip4)
3621
3622 self.nat_add_address(self.nat_addr)
3623 self.nat_add_inside_interface(self.pg0)
3624 self.nat_add_outside_interface(self.pg1)
3625
3626 # SYN in2out
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003627 p = (
3628 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
3629 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
3630 / TCP(sport=self.tcp_port_in, dport=self.tcp_external_port)
3631 )
Klement Sekera56c492a2022-01-10 21:57:27 +00003632 capture = self.send_and_expect(self.pg0, p, self.pg1)[0]
3633 self.tcp_port_out = capture[0][TCP].sport
3634 capture = self.pg3.get_capture(1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003635 self.verify_syslog_sess(capture[0][Raw].load, "SADD")
Klement Sekera56c492a2022-01-10 21:57:27 +00003636
3637 # SYN out2in
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003638 p = (
3639 Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac)
3640 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
3641 / TCP(sport=self.tcp_external_port, dport=self.tcp_port_out, flags="SA")
3642 )
Klement Sekera56c492a2022-01-10 21:57:27 +00003643 self.send_and_expect(self.pg1, p, self.pg0)
3644
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003645 p = (
3646 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
3647 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
3648 / TCP(sport=self.tcp_port_in, dport=self.tcp_external_port, flags="A")
3649 )
Ole Troan52974472022-03-17 11:58:38 +01003650 self.send_and_expect(self.pg0, p, self.pg1)
3651
Klement Sekera56c492a2022-01-10 21:57:27 +00003652 # FIN in2out
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003653 p = (
3654 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
3655 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
3656 / TCP(sport=self.tcp_port_in, dport=self.tcp_external_port, flags="F")
3657 )
Klement Sekera56c492a2022-01-10 21:57:27 +00003658 self.send_and_expect(self.pg0, p, self.pg1)
3659
3660 # FIN out2in
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003661 p = (
3662 Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac)
3663 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
3664 / TCP(sport=self.tcp_external_port, dport=self.tcp_port_out, flags="F")
3665 )
Klement Sekera56c492a2022-01-10 21:57:27 +00003666 self.send_and_expect(self.pg1, p, self.pg0)
3667
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003668 self.init_tcp_session(
3669 self.pg0, self.pg1, self.tcp_port_in, self.tcp_external_port
3670 )
Klement Sekera56c492a2022-01-10 21:57:27 +00003671
3672 # 2 records should be produced - first one del & add
3673 capture = self.pg3.get_capture(2)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003674 self.verify_syslog_sess(capture[0][Raw].load, "SDEL")
3675 self.verify_syslog_sess(capture[1][Raw].load, "SADD")
Filip Varga18f1e412020-12-03 15:27:40 +01003676
3677 def test_twice_nat_interface_addr(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003678 """NAT44ED Acquire twice NAT addresses from interface"""
Filip Varga18f1e412020-12-03 15:27:40 +01003679 flags = self.config_flags.NAT_IS_TWICE_NAT
3680 self.vapi.nat44_add_del_interface_addr(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003681 sw_if_index=self.pg11.sw_if_index, flags=flags, is_add=1
3682 )
Filip Varga18f1e412020-12-03 15:27:40 +01003683
3684 # no address in NAT pool
3685 adresses = self.vapi.nat44_address_dump()
3686 self.assertEqual(0, len(adresses))
3687
3688 # configure interface address and check NAT address pool
3689 self.pg11.config_ip4()
3690 adresses = self.vapi.nat44_address_dump()
3691 self.assertEqual(1, len(adresses))
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003692 self.assertEqual(str(adresses[0].ip_address), self.pg11.local_ip4)
Filip Varga18f1e412020-12-03 15:27:40 +01003693 self.assertEqual(adresses[0].flags, flags)
3694
3695 # remove interface address and check NAT address pool
3696 self.pg11.unconfig_ip4()
3697 adresses = self.vapi.nat44_address_dump()
3698 self.assertEqual(0, len(adresses))
3699
3700 def test_output_feature_stateful_acl(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003701 """NAT44ED output feature works with stateful ACL"""
Filip Varga18f1e412020-12-03 15:27:40 +01003702
3703 self.nat_add_address(self.nat_addr)
Filip Varga9c25eb12021-10-21 13:00:27 +02003704 self.vapi.nat44_ed_add_del_output_interface(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003705 sw_if_index=self.pg1.sw_if_index, is_add=1
3706 )
Filip Varga18f1e412020-12-03 15:27:40 +01003707
3708 # First ensure that the NAT is working sans ACL
3709
3710 # send packets out2in, no sessions yet so packets should drop
3711 pkts_out2in = self.create_stream_out(self.pg1)
3712 self.send_and_assert_no_replies(self.pg1, pkts_out2in)
3713
3714 # send packets into inside intf, ensure received via outside intf
3715 pkts_in2out = self.create_stream_in(self.pg0, self.pg1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003716 capture = self.send_and_expect(
3717 self.pg0, pkts_in2out, self.pg1, len(pkts_in2out)
3718 )
Filip Varga18f1e412020-12-03 15:27:40 +01003719 self.verify_capture_out(capture, ignore_port=True)
3720
3721 # send out2in again, with sessions created it should work now
3722 pkts_out2in = self.create_stream_out(self.pg1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003723 capture = self.send_and_expect(
3724 self.pg1, pkts_out2in, self.pg0, len(pkts_out2in)
3725 )
Filip Varga18f1e412020-12-03 15:27:40 +01003726 self.verify_capture_in(capture, self.pg0)
3727
3728 # Create an ACL blocking everything
3729 out2in_deny_rule = AclRule(is_permit=0)
3730 out2in_acl = VppAcl(self, rules=[out2in_deny_rule])
3731 out2in_acl.add_vpp_config()
3732
3733 # create an ACL to permit/reflect everything
3734 in2out_reflect_rule = AclRule(is_permit=2)
3735 in2out_acl = VppAcl(self, rules=[in2out_reflect_rule])
3736 in2out_acl.add_vpp_config()
3737
3738 # apply as input acl on interface and confirm it blocks everything
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003739 acl_if = VppAclInterface(
3740 self, sw_if_index=self.pg1.sw_if_index, n_input=1, acls=[out2in_acl]
3741 )
Filip Varga18f1e412020-12-03 15:27:40 +01003742 acl_if.add_vpp_config()
3743 self.send_and_assert_no_replies(self.pg1, pkts_out2in)
3744
3745 # apply output acl
3746 acl_if.acls = [out2in_acl, in2out_acl]
3747 acl_if.add_vpp_config()
3748 # send in2out to generate ACL state (NAT state was created earlier)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003749 capture = self.send_and_expect(
3750 self.pg0, pkts_in2out, self.pg1, len(pkts_in2out)
3751 )
Filip Varga18f1e412020-12-03 15:27:40 +01003752 self.verify_capture_out(capture, ignore_port=True)
3753
3754 # send out2in again. ACL state exists so it should work now.
3755 # TCP packets with the syn flag set also need the ack flag
3756 for p in pkts_out2in:
3757 if p.haslayer(TCP) and p[TCP].flags & 0x02:
3758 p[TCP].flags |= 0x10
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003759 capture = self.send_and_expect(
3760 self.pg1, pkts_out2in, self.pg0, len(pkts_out2in)
3761 )
Filip Varga18f1e412020-12-03 15:27:40 +01003762 self.verify_capture_in(capture, self.pg0)
3763 self.logger.info(self.vapi.cli("show trace"))
3764
3765 def test_tcp_close(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003766 """NAT44ED Close TCP session from inside network - output feature"""
Filip Vargab6810822022-02-15 11:56:07 -08003767 config = self.vapi.nat44_show_running_config()
3768 old_timeouts = config.timeouts
Filip Varga18f1e412020-12-03 15:27:40 +01003769 new_transitory = 2
3770 self.vapi.nat_set_timeouts(
3771 udp=old_timeouts.udp,
3772 tcp_established=old_timeouts.tcp_established,
3773 icmp=old_timeouts.icmp,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003774 tcp_transitory=new_transitory,
3775 )
Filip Varga18f1e412020-12-03 15:27:40 +01003776
3777 self.vapi.nat44_forwarding_enable_disable(enable=1)
3778 self.nat_add_address(self.pg1.local_ip4)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003779 twice_nat_addr = "10.0.1.3"
3780 service_ip = "192.168.16.150"
Filip Varga18f1e412020-12-03 15:27:40 +01003781 self.nat_add_address(twice_nat_addr, twice_nat=1)
3782
3783 flags = self.config_flags.NAT_IS_INSIDE
3784 self.vapi.nat44_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003785 sw_if_index=self.pg0.sw_if_index, is_add=1
3786 )
Filip Varga18f1e412020-12-03 15:27:40 +01003787 self.vapi.nat44_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003788 sw_if_index=self.pg0.sw_if_index, flags=flags, is_add=1
3789 )
Filip Varga9c25eb12021-10-21 13:00:27 +02003790 self.vapi.nat44_ed_add_del_output_interface(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003791 is_add=1, sw_if_index=self.pg1.sw_if_index
3792 )
Filip Varga18f1e412020-12-03 15:27:40 +01003793
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003794 flags = (
3795 self.config_flags.NAT_IS_OUT2IN_ONLY | self.config_flags.NAT_IS_TWICE_NAT
3796 )
3797 self.nat_add_static_mapping(
3798 self.pg0.remote_ip4, service_ip, 80, 80, proto=IP_PROTOS.tcp, flags=flags
3799 )
Filip Varga18f1e412020-12-03 15:27:40 +01003800 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3801 start_sessnum = len(sessions)
3802
3803 # SYN packet out->in
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003804 p = (
3805 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
3806 / IP(src=self.pg1.remote_ip4, dst=service_ip)
3807 / TCP(sport=33898, dport=80, flags="S")
3808 )
Klement Sekera56c492a2022-01-10 21:57:27 +00003809 capture = self.send_and_expect(self.pg1, p, self.pg0, n_rx=1)
Filip Varga18f1e412020-12-03 15:27:40 +01003810 p = capture[0]
3811 tcp_port = p[TCP].sport
3812
3813 # SYN + ACK packet in->out
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003814 p = (
3815 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
3816 / IP(src=self.pg0.remote_ip4, dst=twice_nat_addr)
3817 / TCP(sport=80, dport=tcp_port, flags="SA")
3818 )
Klement Sekera56c492a2022-01-10 21:57:27 +00003819 self.send_and_expect(self.pg0, p, self.pg1, n_rx=1)
Filip Varga18f1e412020-12-03 15:27:40 +01003820
3821 # ACK packet out->in
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003822 p = (
3823 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
3824 / IP(src=self.pg1.remote_ip4, dst=service_ip)
3825 / TCP(sport=33898, dport=80, flags="A")
3826 )
Klement Sekera56c492a2022-01-10 21:57:27 +00003827 self.send_and_expect(self.pg1, p, self.pg0, n_rx=1)
Filip Varga18f1e412020-12-03 15:27:40 +01003828
3829 # FIN packet in -> out
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003830 p = (
3831 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
3832 / IP(src=self.pg0.remote_ip4, dst=twice_nat_addr)
3833 / TCP(sport=80, dport=tcp_port, flags="FA", seq=100, ack=300)
3834 )
Klement Sekera56c492a2022-01-10 21:57:27 +00003835 self.send_and_expect(self.pg0, p, self.pg1, n_rx=1)
Filip Varga18f1e412020-12-03 15:27:40 +01003836
3837 # FIN+ACK packet out -> in
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003838 p = (
3839 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
3840 / IP(src=self.pg1.remote_ip4, dst=service_ip)
3841 / TCP(sport=33898, dport=80, flags="FA", seq=300, ack=101)
3842 )
Klement Sekera56c492a2022-01-10 21:57:27 +00003843 self.send_and_expect(self.pg1, p, self.pg0, n_rx=1)
Filip Varga18f1e412020-12-03 15:27:40 +01003844
3845 # ACK packet in -> out
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003846 p = (
3847 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
3848 / IP(src=self.pg0.remote_ip4, dst=twice_nat_addr)
3849 / TCP(sport=80, dport=tcp_port, flags="A", seq=101, ack=301)
3850 )
Klement Sekera56c492a2022-01-10 21:57:27 +00003851 self.send_and_expect(self.pg0, p, self.pg1, n_rx=1)
Filip Varga18f1e412020-12-03 15:27:40 +01003852
Klement Sekera56c492a2022-01-10 21:57:27 +00003853 # session now in transitory timeout, but traffic still flows
3854 # try FIN packet out->in
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003855 p = (
3856 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
3857 / IP(src=self.pg1.remote_ip4, dst=service_ip)
3858 / TCP(sport=33898, dport=80, flags="F")
3859 )
Filip Varga18f1e412020-12-03 15:27:40 +01003860 self.pg1.add_stream(p)
3861 self.pg_enable_capture(self.pg_interfaces)
3862 self.pg_start()
3863
Benoît Ganne56eccdb2021-08-20 09:18:31 +02003864 self.virtual_sleep(new_transitory, "wait for transitory timeout")
Klement Sekera56c492a2022-01-10 21:57:27 +00003865 self.pg0.get_capture(1)
Filip Varga18f1e412020-12-03 15:27:40 +01003866
3867 # session should still exist
3868 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3869 self.assertEqual(len(sessions) - start_sessnum, 1)
3870
3871 # send FIN+ACK packet out -> in - will cause session to be wiped
3872 # but won't create a new session
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003873 p = (
3874 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
3875 / IP(src=self.pg1.remote_ip4, dst=service_ip)
3876 / TCP(sport=33898, dport=80, flags="FA", seq=300, ack=101)
3877 )
Klement Sekera56c492a2022-01-10 21:57:27 +00003878 self.send_and_assert_no_replies(self.pg1, p)
Filip Varga18f1e412020-12-03 15:27:40 +01003879 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3880 self.assertEqual(len(sessions) - start_sessnum, 0)
Filip Varga18f1e412020-12-03 15:27:40 +01003881
3882 def test_tcp_session_close_in(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003883 """NAT44ED Close TCP session from inside network"""
Filip Varga18f1e412020-12-03 15:27:40 +01003884
3885 in_port = self.tcp_port_in
3886 out_port = 10505
3887 ext_port = self.tcp_external_port
3888
3889 self.nat_add_address(self.nat_addr)
3890 self.nat_add_inside_interface(self.pg0)
3891 self.nat_add_outside_interface(self.pg1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003892 self.nat_add_static_mapping(
3893 self.pg0.remote_ip4,
3894 self.nat_addr,
3895 in_port,
3896 out_port,
3897 proto=IP_PROTOS.tcp,
3898 flags=self.config_flags.NAT_IS_TWICE_NAT,
3899 )
Filip Varga18f1e412020-12-03 15:27:40 +01003900
3901 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3902 session_n = len(sessions)
3903
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003904 self.vapi.nat_set_timeouts(
3905 udp=300, tcp_established=7440, tcp_transitory=2, icmp=5
3906 )
Filip Varga18f1e412020-12-03 15:27:40 +01003907
3908 self.init_tcp_session(self.pg0, self.pg1, in_port, ext_port)
3909
3910 # FIN packet in -> out
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003911 p = (
3912 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
3913 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
3914 / TCP(sport=in_port, dport=ext_port, flags="FA", seq=100, ack=300)
3915 )
Klement Sekera56c492a2022-01-10 21:57:27 +00003916 self.send_and_expect(self.pg0, p, self.pg1)
Filip Varga18f1e412020-12-03 15:27:40 +01003917 pkts = []
3918
3919 # ACK packet out -> in
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003920 p = (
3921 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
3922 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
3923 / TCP(sport=ext_port, dport=out_port, flags="A", seq=300, ack=101)
3924 )
Filip Varga18f1e412020-12-03 15:27:40 +01003925 pkts.append(p)
3926
3927 # FIN packet out -> in
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003928 p = (
3929 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
3930 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
3931 / TCP(sport=ext_port, dport=out_port, flags="FA", seq=300, ack=101)
3932 )
Filip Varga18f1e412020-12-03 15:27:40 +01003933 pkts.append(p)
3934
Klement Sekera56c492a2022-01-10 21:57:27 +00003935 self.send_and_expect(self.pg1, pkts, self.pg0)
Filip Varga18f1e412020-12-03 15:27:40 +01003936
3937 # ACK packet in -> out
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003938 p = (
3939 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
3940 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
3941 / TCP(sport=in_port, dport=ext_port, flags="A", seq=101, ack=301)
3942 )
Klement Sekera56c492a2022-01-10 21:57:27 +00003943 self.send_and_expect(self.pg0, p, self.pg1)
Filip Varga18f1e412020-12-03 15:27:40 +01003944
3945 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3946 self.assertEqual(len(sessions) - session_n, 1)
3947
Klement Sekera56c492a2022-01-10 21:57:27 +00003948 # retransmit FIN packet out -> in
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003949 p = (
3950 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
3951 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
3952 / TCP(sport=ext_port, dport=out_port, flags="FA", seq=300, ack=101)
3953 )
Filip Varga18f1e412020-12-03 15:27:40 +01003954
Klement Sekera56c492a2022-01-10 21:57:27 +00003955 self.send_and_expect(self.pg1, p, self.pg0)
Filip Varga18f1e412020-12-03 15:27:40 +01003956
Klement Sekera56c492a2022-01-10 21:57:27 +00003957 # retransmit ACK packet in -> out
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003958 p = (
3959 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
3960 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
3961 / TCP(sport=in_port, dport=ext_port, flags="A", seq=101, ack=301)
3962 )
Klement Sekera56c492a2022-01-10 21:57:27 +00003963 self.send_and_expect(self.pg0, p, self.pg1)
Filip Varga18f1e412020-12-03 15:27:40 +01003964
Benoît Ganne56eccdb2021-08-20 09:18:31 +02003965 self.virtual_sleep(3)
Klement Sekera56c492a2022-01-10 21:57:27 +00003966 # retransmit ACK packet in -> out - this will cause session to be wiped
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003967 p = (
3968 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
3969 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
3970 / TCP(sport=in_port, dport=ext_port, flags="A", seq=101, ack=301)
3971 )
Klement Sekera56c492a2022-01-10 21:57:27 +00003972 self.send_and_assert_no_replies(self.pg0, p)
Filip Varga18f1e412020-12-03 15:27:40 +01003973 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3974 self.assertEqual(len(sessions) - session_n, 0)
3975
3976 def test_tcp_session_close_out(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003977 """NAT44ED Close TCP session from outside network"""
Filip Varga18f1e412020-12-03 15:27:40 +01003978
3979 in_port = self.tcp_port_in
3980 out_port = 10505
3981 ext_port = self.tcp_external_port
3982
3983 self.nat_add_address(self.nat_addr)
3984 self.nat_add_inside_interface(self.pg0)
3985 self.nat_add_outside_interface(self.pg1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003986 self.nat_add_static_mapping(
3987 self.pg0.remote_ip4,
3988 self.nat_addr,
3989 in_port,
3990 out_port,
3991 proto=IP_PROTOS.tcp,
3992 flags=self.config_flags.NAT_IS_TWICE_NAT,
3993 )
Filip Varga18f1e412020-12-03 15:27:40 +01003994
3995 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3996 session_n = len(sessions)
3997
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003998 self.vapi.nat_set_timeouts(
3999 udp=300, tcp_established=7440, tcp_transitory=2, icmp=5
4000 )
Filip Varga18f1e412020-12-03 15:27:40 +01004001
4002 _ = self.init_tcp_session(self.pg0, self.pg1, in_port, ext_port)
4003
4004 # FIN packet out -> in
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004005 p = (
4006 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
4007 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
4008 / TCP(sport=ext_port, dport=out_port, flags="FA", seq=100, ack=300)
4009 )
Filip Varga18f1e412020-12-03 15:27:40 +01004010 self.pg1.add_stream(p)
4011 self.pg_enable_capture(self.pg_interfaces)
4012 self.pg_start()
4013 self.pg0.get_capture(1)
4014
4015 # FIN+ACK packet in -> out
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004016 p = (
4017 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
4018 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
4019 / TCP(sport=in_port, dport=ext_port, flags="FA", seq=300, ack=101)
4020 )
Filip Varga18f1e412020-12-03 15:27:40 +01004021
4022 self.pg0.add_stream(p)
4023 self.pg_enable_capture(self.pg_interfaces)
4024 self.pg_start()
4025 self.pg1.get_capture(1)
4026
4027 # ACK packet out -> in
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004028 p = (
4029 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
4030 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
4031 / TCP(sport=ext_port, dport=out_port, flags="A", seq=101, ack=301)
4032 )
Filip Varga18f1e412020-12-03 15:27:40 +01004033 self.pg1.add_stream(p)
4034 self.pg_enable_capture(self.pg_interfaces)
4035 self.pg_start()
4036 self.pg0.get_capture(1)
4037
4038 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
4039 self.assertEqual(len(sessions) - session_n, 1)
4040
Klement Sekera56c492a2022-01-10 21:57:27 +00004041 # retransmit FIN packet out -> in
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004042 p = (
4043 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
4044 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
4045 / TCP(sport=ext_port, dport=out_port, flags="FA", seq=300, ack=101)
4046 )
Klement Sekera56c492a2022-01-10 21:57:27 +00004047 self.send_and_expect(self.pg1, p, self.pg0)
Filip Varga18f1e412020-12-03 15:27:40 +01004048
Klement Sekera56c492a2022-01-10 21:57:27 +00004049 # retransmit ACK packet in -> out
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004050 p = (
4051 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
4052 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
4053 / TCP(sport=in_port, dport=ext_port, flags="A", seq=101, ack=301)
4054 )
Klement Sekera56c492a2022-01-10 21:57:27 +00004055 self.send_and_expect(self.pg0, p, self.pg1)
Filip Varga18f1e412020-12-03 15:27:40 +01004056
Benoît Ganne56eccdb2021-08-20 09:18:31 +02004057 self.virtual_sleep(3)
Klement Sekera56c492a2022-01-10 21:57:27 +00004058 # retransmit ACK packet in -> out - this will cause session to be wiped
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004059 p = (
4060 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
4061 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
4062 / TCP(sport=in_port, dport=ext_port, flags="A", seq=101, ack=301)
4063 )
Klement Sekera56c492a2022-01-10 21:57:27 +00004064 self.send_and_assert_no_replies(self.pg0, p)
Filip Varga18f1e412020-12-03 15:27:40 +01004065 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
4066 self.assertEqual(len(sessions) - session_n, 0)
4067
4068 def test_tcp_session_close_simultaneous(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004069 """Simultaneous TCP close from both sides"""
Filip Varga18f1e412020-12-03 15:27:40 +01004070
4071 in_port = self.tcp_port_in
4072 ext_port = 10505
4073
4074 self.nat_add_address(self.nat_addr)
4075 self.nat_add_inside_interface(self.pg0)
4076 self.nat_add_outside_interface(self.pg1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004077 self.nat_add_static_mapping(
4078 self.pg0.remote_ip4,
4079 self.nat_addr,
4080 in_port,
4081 ext_port,
4082 proto=IP_PROTOS.tcp,
4083 flags=self.config_flags.NAT_IS_TWICE_NAT,
4084 )
Filip Varga18f1e412020-12-03 15:27:40 +01004085
4086 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
4087 session_n = len(sessions)
4088
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004089 self.vapi.nat_set_timeouts(
4090 udp=300, tcp_established=7440, tcp_transitory=2, icmp=5
4091 )
Filip Varga18f1e412020-12-03 15:27:40 +01004092
4093 out_port = self.init_tcp_session(self.pg0, self.pg1, in_port, ext_port)
4094
4095 # FIN packet in -> out
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004096 p = (
4097 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
4098 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
4099 / TCP(sport=in_port, dport=ext_port, flags="FA", seq=100, ack=300)
4100 )
Klement Sekera56c492a2022-01-10 21:57:27 +00004101 self.send_and_expect(self.pg0, p, self.pg1)
Filip Varga18f1e412020-12-03 15:27:40 +01004102
4103 # FIN packet out -> in
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004104 p = (
4105 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
4106 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
4107 / TCP(sport=ext_port, dport=out_port, flags="FA", seq=300, ack=100)
4108 )
Klement Sekera56c492a2022-01-10 21:57:27 +00004109 self.send_and_expect(self.pg1, p, self.pg0)
Filip Varga18f1e412020-12-03 15:27:40 +01004110
4111 # ACK packet in -> out
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004112 p = (
4113 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
4114 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
4115 / TCP(sport=in_port, dport=ext_port, flags="A", seq=101, ack=301)
4116 )
Klement Sekera56c492a2022-01-10 21:57:27 +00004117 self.send_and_expect(self.pg0, p, self.pg1)
Filip Varga18f1e412020-12-03 15:27:40 +01004118
4119 # ACK packet out -> in
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004120 p = (
4121 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
4122 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
4123 / TCP(sport=ext_port, dport=out_port, flags="A", seq=301, ack=101)
4124 )
Klement Sekera56c492a2022-01-10 21:57:27 +00004125 self.send_and_expect(self.pg1, p, self.pg0)
Filip Varga18f1e412020-12-03 15:27:40 +01004126
4127 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
4128 self.assertEqual(len(sessions) - session_n, 1)
4129
Klement Sekera56c492a2022-01-10 21:57:27 +00004130 # retransmit FIN packet out -> in
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004131 p = (
4132 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
4133 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
4134 / TCP(sport=ext_port, dport=out_port, flags="FA", seq=300, ack=101)
4135 )
Klement Sekera56c492a2022-01-10 21:57:27 +00004136 self.send_and_expect(self.pg1, p, self.pg0)
Filip Varga18f1e412020-12-03 15:27:40 +01004137
Klement Sekera56c492a2022-01-10 21:57:27 +00004138 # retransmit ACK packet in -> out
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004139 p = (
4140 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
4141 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
4142 / TCP(sport=in_port, dport=ext_port, flags="A", seq=101, ack=301)
4143 )
Klement Sekera56c492a2022-01-10 21:57:27 +00004144 self.send_and_expect(self.pg0, p, self.pg1)
Filip Varga18f1e412020-12-03 15:27:40 +01004145
Benoît Ganne56eccdb2021-08-20 09:18:31 +02004146 self.virtual_sleep(3)
Klement Sekera56c492a2022-01-10 21:57:27 +00004147 # retransmit ACK packet in -> out - this will cause session to be wiped
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004148 p = (
4149 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
4150 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
4151 / TCP(sport=in_port, dport=ext_port, flags="A", seq=101, ack=301)
4152 )
Klement Sekera56c492a2022-01-10 21:57:27 +00004153 self.pg_send(self.pg0, p)
4154 self.send_and_assert_no_replies(self.pg0, p)
Filip Varga18f1e412020-12-03 15:27:40 +01004155 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
4156 self.assertEqual(len(sessions) - session_n, 0)
4157
Klement Sekera56c492a2022-01-10 21:57:27 +00004158 def test_tcp_session_half_reopen_inside(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004159 """TCP session in FIN/FIN state not reopened by in2out SYN only"""
Klement Sekera56c492a2022-01-10 21:57:27 +00004160 in_port = self.tcp_port_in
4161 ext_port = 10505
4162
4163 self.nat_add_address(self.nat_addr)
4164 self.nat_add_inside_interface(self.pg0)
4165 self.nat_add_outside_interface(self.pg1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004166 self.nat_add_static_mapping(
4167 self.pg0.remote_ip4,
4168 self.nat_addr,
4169 in_port,
4170 ext_port,
4171 proto=IP_PROTOS.tcp,
4172 flags=self.config_flags.NAT_IS_TWICE_NAT,
4173 )
Klement Sekera56c492a2022-01-10 21:57:27 +00004174
4175 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
4176 session_n = len(sessions)
4177
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004178 self.vapi.nat_set_timeouts(
4179 udp=300, tcp_established=7440, tcp_transitory=2, icmp=5
4180 )
Klement Sekera56c492a2022-01-10 21:57:27 +00004181
4182 out_port = self.init_tcp_session(self.pg0, self.pg1, in_port, ext_port)
4183
4184 # FIN packet in -> out
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004185 p = (
4186 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
4187 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
4188 / TCP(sport=in_port, dport=ext_port, flags="FA", seq=100, ack=300)
4189 )
Klement Sekera56c492a2022-01-10 21:57:27 +00004190 self.send_and_expect(self.pg0, p, self.pg1)
4191
4192 # FIN packet out -> in
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004193 p = (
4194 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
4195 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
4196 / TCP(sport=ext_port, dport=out_port, flags="FA", seq=300, ack=100)
4197 )
Klement Sekera56c492a2022-01-10 21:57:27 +00004198 self.send_and_expect(self.pg1, p, self.pg0)
4199
4200 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
4201 self.assertEqual(len(sessions) - session_n, 1)
4202
4203 # send SYN packet in -> out
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004204 p = (
4205 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
4206 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
4207 / TCP(sport=in_port, dport=ext_port, flags="S", seq=101, ack=301)
4208 )
Klement Sekera56c492a2022-01-10 21:57:27 +00004209 self.send_and_expect(self.pg0, p, self.pg1)
4210
4211 self.virtual_sleep(3)
4212 # send ACK packet in -> out - session should be wiped
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004213 p = (
4214 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
4215 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
4216 / TCP(sport=in_port, dport=ext_port, flags="A", seq=101, ack=301)
4217 )
Klement Sekera56c492a2022-01-10 21:57:27 +00004218 self.send_and_assert_no_replies(self.pg0, p, self.pg1)
4219 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
4220 self.assertEqual(len(sessions) - session_n, 0)
4221
4222 def test_tcp_session_half_reopen_outside(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004223 """TCP session in FIN/FIN state not reopened by out2in SYN only"""
Klement Sekera56c492a2022-01-10 21:57:27 +00004224 in_port = self.tcp_port_in
4225 ext_port = 10505
4226
4227 self.nat_add_address(self.nat_addr)
4228 self.nat_add_inside_interface(self.pg0)
4229 self.nat_add_outside_interface(self.pg1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004230 self.nat_add_static_mapping(
4231 self.pg0.remote_ip4,
4232 self.nat_addr,
4233 in_port,
4234 ext_port,
4235 proto=IP_PROTOS.tcp,
4236 flags=self.config_flags.NAT_IS_TWICE_NAT,
4237 )
Klement Sekera56c492a2022-01-10 21:57:27 +00004238
4239 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
4240 session_n = len(sessions)
4241
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004242 self.vapi.nat_set_timeouts(
4243 udp=300, tcp_established=7440, tcp_transitory=2, icmp=5
4244 )
Klement Sekera56c492a2022-01-10 21:57:27 +00004245
4246 out_port = self.init_tcp_session(self.pg0, self.pg1, in_port, ext_port)
4247
4248 # FIN packet in -> out
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004249 p = (
4250 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
4251 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
4252 / TCP(sport=in_port, dport=ext_port, flags="FA", seq=100, ack=300)
4253 )
Klement Sekera56c492a2022-01-10 21:57:27 +00004254 self.send_and_expect(self.pg0, p, self.pg1)
4255
4256 # FIN packet out -> in
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004257 p = (
4258 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
4259 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
4260 / TCP(sport=ext_port, dport=out_port, flags="FA", seq=300, ack=100)
4261 )
Klement Sekera56c492a2022-01-10 21:57:27 +00004262 self.send_and_expect(self.pg1, p, self.pg0)
4263
4264 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
4265 self.assertEqual(len(sessions) - session_n, 1)
4266
4267 # send SYN packet out -> in
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004268 p = (
4269 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
4270 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
4271 / TCP(sport=ext_port, dport=out_port, flags="S", seq=300, ack=101)
4272 )
Klement Sekera56c492a2022-01-10 21:57:27 +00004273 self.send_and_expect(self.pg1, p, self.pg0)
4274
4275 self.virtual_sleep(3)
4276 # send ACK packet in -> out - session should be wiped
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004277 p = (
4278 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
4279 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
4280 / TCP(sport=in_port, dport=ext_port, flags="A", seq=101, ack=301)
4281 )
Klement Sekera56c492a2022-01-10 21:57:27 +00004282 self.send_and_assert_no_replies(self.pg0, p, self.pg1)
4283 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
4284 self.assertEqual(len(sessions) - session_n, 0)
4285
4286 def test_tcp_session_reopen(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004287 """TCP session in FIN/FIN state reopened by SYN from both sides"""
Klement Sekera56c492a2022-01-10 21:57:27 +00004288 in_port = self.tcp_port_in
4289 ext_port = 10505
4290
4291 self.nat_add_address(self.nat_addr)
4292 self.nat_add_inside_interface(self.pg0)
4293 self.nat_add_outside_interface(self.pg1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004294 self.nat_add_static_mapping(
4295 self.pg0.remote_ip4,
4296 self.nat_addr,
4297 in_port,
4298 ext_port,
4299 proto=IP_PROTOS.tcp,
4300 flags=self.config_flags.NAT_IS_TWICE_NAT,
4301 )
Klement Sekera56c492a2022-01-10 21:57:27 +00004302
4303 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
4304 session_n = len(sessions)
4305
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004306 self.vapi.nat_set_timeouts(
4307 udp=300, tcp_established=7440, tcp_transitory=2, icmp=5
4308 )
Klement Sekera56c492a2022-01-10 21:57:27 +00004309
4310 out_port = self.init_tcp_session(self.pg0, self.pg1, in_port, ext_port)
4311
4312 # FIN packet in -> out
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004313 p = (
4314 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
4315 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
4316 / TCP(sport=in_port, dport=ext_port, flags="FA", seq=100, ack=300)
4317 )
Klement Sekera56c492a2022-01-10 21:57:27 +00004318 self.send_and_expect(self.pg0, p, self.pg1)
4319
4320 # FIN packet out -> in
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004321 p = (
4322 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
4323 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
4324 / TCP(sport=ext_port, dport=out_port, flags="FA", seq=300, ack=100)
4325 )
Klement Sekera56c492a2022-01-10 21:57:27 +00004326 self.send_and_expect(self.pg1, p, self.pg0)
4327
4328 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
4329 self.assertEqual(len(sessions) - session_n, 1)
4330
4331 # send SYN packet out -> in
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004332 p = (
4333 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
4334 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
4335 / TCP(sport=ext_port, dport=out_port, flags="S", seq=300, ack=101)
4336 )
Klement Sekera56c492a2022-01-10 21:57:27 +00004337 self.send_and_expect(self.pg1, p, self.pg0)
4338
4339 # send SYN packet in -> out
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004340 p = (
4341 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
4342 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
4343 / TCP(sport=in_port, dport=ext_port, flags="SA", seq=101, ack=301)
4344 )
Klement Sekera56c492a2022-01-10 21:57:27 +00004345 self.send_and_expect(self.pg0, p, self.pg1)
4346
Ole Troan52974472022-03-17 11:58:38 +01004347 # send ACK packet out -> in
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004348 p = (
4349 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
4350 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
4351 / TCP(sport=ext_port, dport=out_port, flags="A", seq=300, ack=101)
4352 )
Ole Troan52974472022-03-17 11:58:38 +01004353 self.send_and_expect(self.pg1, p, self.pg0)
4354
Klement Sekera56c492a2022-01-10 21:57:27 +00004355 self.virtual_sleep(3)
4356 # send ACK packet in -> out - should be forwarded and session alive
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004357 p = (
4358 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
4359 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
4360 / TCP(sport=in_port, dport=ext_port, flags="A", seq=101, ack=301)
4361 )
Klement Sekera56c492a2022-01-10 21:57:27 +00004362 self.send_and_expect(self.pg0, p, self.pg1)
4363 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
4364 self.assertEqual(len(sessions) - session_n, 1)
4365
Filip Vargabdd61492021-04-13 17:47:13 +02004366 def test_dynamic_vrf(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004367 """NAT44ED dynamic translation test: different VRF"""
Filip Vargabdd61492021-04-13 17:47:13 +02004368
4369 vrf_id_in = 33
4370 vrf_id_out = 34
4371
4372 self.nat_add_address(self.nat_addr, vrf_id=vrf_id_in)
4373
4374 try:
4375 self.configure_ip4_interface(self.pg7, table_id=vrf_id_in)
4376 self.configure_ip4_interface(self.pg8, table_id=vrf_id_out)
4377
4378 self.nat_add_inside_interface(self.pg7)
4379 self.nat_add_outside_interface(self.pg8)
4380
4381 # just basic stuff nothing special
4382 pkts = self.create_stream_in(self.pg7, self.pg8)
4383 self.pg7.add_stream(pkts)
4384 self.pg_enable_capture(self.pg_interfaces)
4385 self.pg_start()
4386 capture = self.pg8.get_capture(len(pkts))
4387 self.verify_capture_out(capture, ignore_port=True)
4388
4389 pkts = self.create_stream_out(self.pg8)
4390 self.pg8.add_stream(pkts)
4391 self.pg_enable_capture(self.pg_interfaces)
4392 self.pg_start()
4393 capture = self.pg7.get_capture(len(pkts))
4394 self.verify_capture_in(capture, self.pg7)
4395
4396 finally:
4397 self.pg7.unconfig()
4398 self.pg8.unconfig()
4399
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004400 self.vapi.ip_table_add_del(is_add=0, table={"table_id": vrf_id_in})
4401 self.vapi.ip_table_add_del(is_add=0, table={"table_id": vrf_id_out})
Filip Vargabdd61492021-04-13 17:47:13 +02004402
Filip Varga18f1e412020-12-03 15:27:40 +01004403 def test_dynamic_output_feature_vrf(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004404 """NAT44ED dynamic translation test: output-feature, VRF"""
Filip Varga18f1e412020-12-03 15:27:40 +01004405
4406 # other then default (0)
4407 new_vrf_id = 22
4408
4409 self.nat_add_address(self.nat_addr)
Filip Vargab6810822022-02-15 11:56:07 -08004410 self.vapi.nat44_ed_add_del_output_interface(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004411 sw_if_index=self.pg8.sw_if_index, is_add=1
4412 )
Filip Varga18f1e412020-12-03 15:27:40 +01004413 try:
4414 self.configure_ip4_interface(self.pg7, table_id=new_vrf_id)
4415 self.configure_ip4_interface(self.pg8, table_id=new_vrf_id)
4416
4417 # in2out
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004418 tcpn = self.statistics["/nat44-ed/in2out/slowpath/tcp"]
4419 udpn = self.statistics["/nat44-ed/in2out/slowpath/udp"]
4420 icmpn = self.statistics["/nat44-ed/in2out/slowpath/icmp"]
4421 drops = self.statistics["/nat44-ed/in2out/slowpath/drops"]
Filip Varga18f1e412020-12-03 15:27:40 +01004422
4423 pkts = self.create_stream_in(self.pg7, self.pg8)
4424 self.pg7.add_stream(pkts)
4425 self.pg_enable_capture(self.pg_interfaces)
4426 self.pg_start()
4427 capture = self.pg8.get_capture(len(pkts))
4428 self.verify_capture_out(capture, ignore_port=True)
4429
Alexander Chernavin4de12b92021-07-06 06:08:26 -04004430 if_idx = self.pg8.sw_if_index
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004431 cnt = self.statistics["/nat44-ed/in2out/slowpath/tcp"]
Klement Sekera3887be72021-03-30 20:29:05 +02004432 self.assertEqual(cnt[:, if_idx].sum() - tcpn[:, if_idx].sum(), 2)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004433 cnt = self.statistics["/nat44-ed/in2out/slowpath/udp"]
Klement Sekera3887be72021-03-30 20:29:05 +02004434 self.assertEqual(cnt[:, if_idx].sum() - udpn[:, if_idx].sum(), 1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004435 cnt = self.statistics["/nat44-ed/in2out/slowpath/icmp"]
Klement Sekera3887be72021-03-30 20:29:05 +02004436 self.assertEqual(cnt[:, if_idx].sum() - icmpn[:, if_idx].sum(), 1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004437 cnt = self.statistics["/nat44-ed/in2out/slowpath/drops"]
Klement Sekera3887be72021-03-30 20:29:05 +02004438 self.assertEqual(cnt[:, if_idx].sum() - drops[:, if_idx].sum(), 0)
Filip Varga18f1e412020-12-03 15:27:40 +01004439
4440 # out2in
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004441 tcpn = self.statistics["/nat44-ed/out2in/fastpath/tcp"]
4442 udpn = self.statistics["/nat44-ed/out2in/fastpath/udp"]
4443 icmpn = self.statistics["/nat44-ed/out2in/fastpath/icmp"]
4444 drops = self.statistics["/nat44-ed/out2in/fastpath/drops"]
Filip Varga18f1e412020-12-03 15:27:40 +01004445
4446 pkts = self.create_stream_out(self.pg8)
4447 self.pg8.add_stream(pkts)
4448 self.pg_enable_capture(self.pg_interfaces)
4449 self.pg_start()
4450 capture = self.pg7.get_capture(len(pkts))
4451 self.verify_capture_in(capture, self.pg7)
4452
4453 if_idx = self.pg8.sw_if_index
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004454 cnt = self.statistics["/nat44-ed/out2in/fastpath/tcp"]
Klement Sekera3887be72021-03-30 20:29:05 +02004455 self.assertEqual(cnt[:, if_idx].sum() - tcpn[:, if_idx].sum(), 2)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004456 cnt = self.statistics["/nat44-ed/out2in/fastpath/udp"]
Klement Sekera3887be72021-03-30 20:29:05 +02004457 self.assertEqual(cnt[:, if_idx].sum() - udpn[:, if_idx].sum(), 1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004458 cnt = self.statistics["/nat44-ed/out2in/fastpath/icmp"]
Klement Sekera3887be72021-03-30 20:29:05 +02004459 self.assertEqual(cnt[:, if_idx].sum() - icmpn[:, if_idx].sum(), 1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004460 cnt = self.statistics["/nat44-ed/out2in/fastpath/drops"]
Klement Sekera3887be72021-03-30 20:29:05 +02004461 self.assertEqual(cnt[:, if_idx].sum() - drops[:, if_idx].sum(), 0)
Filip Varga18f1e412020-12-03 15:27:40 +01004462
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004463 sessions = self.statistics["/nat44-ed/total-sessions"]
Klement Sekera3887be72021-03-30 20:29:05 +02004464 self.assertEqual(sessions[:, 0].sum(), 3)
Filip Varga18f1e412020-12-03 15:27:40 +01004465
4466 finally:
Filip Vargabdd61492021-04-13 17:47:13 +02004467 self.pg7.unconfig()
4468 self.pg8.unconfig()
Filip Varga18f1e412020-12-03 15:27:40 +01004469
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004470 self.vapi.ip_table_add_del(is_add=0, table={"table_id": new_vrf_id})
Filip Varga18f1e412020-12-03 15:27:40 +01004471
4472 def test_next_src_nat(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004473 """NAT44ED On way back forward packet to nat44-in2out node."""
Filip Varga18f1e412020-12-03 15:27:40 +01004474
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004475 twice_nat_addr = "10.0.1.3"
Filip Varga18f1e412020-12-03 15:27:40 +01004476 external_port = 80
4477 local_port = 8080
4478 post_twice_nat_port = 0
4479
4480 self.vapi.nat44_forwarding_enable_disable(enable=1)
4481 self.nat_add_address(twice_nat_addr, twice_nat=1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004482 flags = (
4483 self.config_flags.NAT_IS_OUT2IN_ONLY
4484 | self.config_flags.NAT_IS_SELF_TWICE_NAT
4485 )
4486 self.nat_add_static_mapping(
4487 self.pg6.remote_ip4,
4488 self.pg1.remote_ip4,
4489 local_port,
4490 external_port,
4491 proto=IP_PROTOS.tcp,
4492 vrf_id=1,
4493 flags=flags,
4494 )
Filip Varga18f1e412020-12-03 15:27:40 +01004495 self.vapi.nat44_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004496 sw_if_index=self.pg6.sw_if_index, is_add=1
4497 )
Filip Varga18f1e412020-12-03 15:27:40 +01004498
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004499 p = (
4500 Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac)
4501 / IP(src=self.pg6.remote_ip4, dst=self.pg1.remote_ip4)
4502 / TCP(sport=12345, dport=external_port)
4503 )
Filip Varga18f1e412020-12-03 15:27:40 +01004504 self.pg6.add_stream(p)
4505 self.pg_enable_capture(self.pg_interfaces)
4506 self.pg_start()
4507 capture = self.pg6.get_capture(1)
4508 p = capture[0]
4509 try:
4510 ip = p[IP]
4511 tcp = p[TCP]
4512 self.assertEqual(ip.src, twice_nat_addr)
4513 self.assertNotEqual(tcp.sport, 12345)
4514 post_twice_nat_port = tcp.sport
4515 self.assertEqual(ip.dst, self.pg6.remote_ip4)
4516 self.assertEqual(tcp.dport, local_port)
4517 self.assert_packet_checksums_valid(p)
4518 except:
4519 self.logger.error(ppp("Unexpected or invalid packet:", p))
4520 raise
4521
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004522 p = (
4523 Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac)
4524 / IP(src=self.pg6.remote_ip4, dst=twice_nat_addr)
4525 / TCP(sport=local_port, dport=post_twice_nat_port)
4526 )
Filip Varga18f1e412020-12-03 15:27:40 +01004527 self.pg6.add_stream(p)
4528 self.pg_enable_capture(self.pg_interfaces)
4529 self.pg_start()
4530 capture = self.pg6.get_capture(1)
4531 p = capture[0]
4532 try:
4533 ip = p[IP]
4534 tcp = p[TCP]
4535 self.assertEqual(ip.src, self.pg1.remote_ip4)
4536 self.assertEqual(tcp.sport, external_port)
4537 self.assertEqual(ip.dst, self.pg6.remote_ip4)
4538 self.assertEqual(tcp.dport, 12345)
4539 self.assert_packet_checksums_valid(p)
4540 except:
4541 self.logger.error(ppp("Unexpected or invalid packet:", p))
4542 raise
4543
4544 def test_one_armed_nat44_static(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004545 """NAT44ED One armed NAT and 1:1 NAPT asymmetrical rule"""
Filip Varga18f1e412020-12-03 15:27:40 +01004546
4547 remote_host = self.pg4.remote_hosts[0]
4548 local_host = self.pg4.remote_hosts[1]
4549 external_port = 80
4550 local_port = 8080
4551 eh_port_in = 0
4552
4553 self.vapi.nat44_forwarding_enable_disable(enable=1)
4554 self.nat_add_address(self.nat_addr, twice_nat=1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004555 flags = (
4556 self.config_flags.NAT_IS_OUT2IN_ONLY | self.config_flags.NAT_IS_TWICE_NAT
4557 )
4558 self.nat_add_static_mapping(
4559 local_host.ip4,
4560 self.nat_addr,
4561 local_port,
4562 external_port,
4563 proto=IP_PROTOS.tcp,
4564 flags=flags,
4565 )
Filip Varga18f1e412020-12-03 15:27:40 +01004566 flags = self.config_flags.NAT_IS_INSIDE
4567 self.vapi.nat44_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004568 sw_if_index=self.pg4.sw_if_index, is_add=1
4569 )
Filip Varga18f1e412020-12-03 15:27:40 +01004570 self.vapi.nat44_interface_add_del_feature(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004571 sw_if_index=self.pg4.sw_if_index, flags=flags, is_add=1
4572 )
Filip Varga18f1e412020-12-03 15:27:40 +01004573
4574 # from client to service
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004575 p = (
4576 Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac)
4577 / IP(src=remote_host.ip4, dst=self.nat_addr)
4578 / TCP(sport=12345, dport=external_port)
4579 )
Filip Varga18f1e412020-12-03 15:27:40 +01004580 self.pg4.add_stream(p)
4581 self.pg_enable_capture(self.pg_interfaces)
4582 self.pg_start()
4583 capture = self.pg4.get_capture(1)
4584 p = capture[0]
4585 try:
4586 ip = p[IP]
4587 tcp = p[TCP]
4588 self.assertEqual(ip.dst, local_host.ip4)
4589 self.assertEqual(ip.src, self.nat_addr)
4590 self.assertEqual(tcp.dport, local_port)
4591 self.assertNotEqual(tcp.sport, 12345)
4592 eh_port_in = tcp.sport
4593 self.assert_packet_checksums_valid(p)
4594 except:
4595 self.logger.error(ppp("Unexpected or invalid packet:", p))
4596 raise
4597
4598 # from service back to client
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004599 p = (
4600 Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac)
4601 / IP(src=local_host.ip4, dst=self.nat_addr)
4602 / TCP(sport=local_port, dport=eh_port_in)
4603 )
Filip Varga18f1e412020-12-03 15:27:40 +01004604 self.pg4.add_stream(p)
4605 self.pg_enable_capture(self.pg_interfaces)
4606 self.pg_start()
4607 capture = self.pg4.get_capture(1)
4608 p = capture[0]
4609 try:
4610 ip = p[IP]
4611 tcp = p[TCP]
4612 self.assertEqual(ip.src, self.nat_addr)
4613 self.assertEqual(ip.dst, remote_host.ip4)
4614 self.assertEqual(tcp.sport, external_port)
4615 self.assertEqual(tcp.dport, 12345)
4616 self.assert_packet_checksums_valid(p)
4617 except:
4618 self.logger.error(ppp("Unexpected or invalid packet:", p))
4619 raise
4620
Matthew Smithad510752021-08-10 12:22:14 -05004621 def test_icmp_error_fwd_outbound(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004622 """NAT44ED ICMP error outbound with forwarding enabled"""
Matthew Smithad510752021-08-10 12:22:14 -05004623
4624 # Ensure that an outbound ICMP error message is properly associated
4625 # with the inbound forward bypass session it is related to.
4626 payload = "H" * 10
4627
4628 self.nat_add_address(self.nat_addr)
4629 self.nat_add_inside_interface(self.pg0)
4630 self.nat_add_outside_interface(self.pg1)
4631
4632 # enable forwarding and initiate connection out2in
4633 self.vapi.nat44_forwarding_enable_disable(enable=1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004634 p1 = (
4635 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
4636 / IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4)
4637 / UDP(sport=21, dport=20)
4638 / payload
4639 )
Matthew Smithad510752021-08-10 12:22:14 -05004640
4641 self.pg1.add_stream(p1)
4642 self.pg_enable_capture(self.pg_interfaces)
4643 self.pg_start()
4644 capture = self.pg0.get_capture(1)[0]
4645
4646 self.logger.info(self.vapi.cli("show nat44 sessions"))
4647
4648 # reply with ICMP error message in2out
4649 # We cannot reliably retrieve forward bypass sessions via the API.
4650 # session dumps for a user will only look on the worker that the
4651 # user is supposed to be mapped to in2out. The forward bypass session
4652 # is not necessarily created on that worker.
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004653 p2 = (
4654 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
4655 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
4656 / ICMP(type="dest-unreach", code="port-unreachable")
4657 / capture[IP:]
4658 )
Matthew Smithad510752021-08-10 12:22:14 -05004659
4660 self.pg0.add_stream(p2)
4661 self.pg_enable_capture(self.pg_interfaces)
4662 self.pg_start()
4663 capture = self.pg1.get_capture(1)[0]
4664
4665 self.logger.info(self.vapi.cli("show nat44 sessions"))
4666
4667 self.logger.info(ppp("p1 packet:", p1))
4668 self.logger.info(ppp("p2 packet:", p2))
4669 self.logger.info(ppp("capture packet:", capture))
4670
Klement Sekera56c492a2022-01-10 21:57:27 +00004671 def test_tcp_session_open_retransmit1(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004672 """NAT44ED Open TCP session with SYN,ACK retransmit 1
Klement Sekera56c492a2022-01-10 21:57:27 +00004673
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004674 The client does not receive the [SYN,ACK] or the
4675 ACK from the client is lost. Therefore, the [SYN, ACK]
4676 is retransmitted by the server.
Klement Sekera56c492a2022-01-10 21:57:27 +00004677 """
4678
4679 in_port = self.tcp_port_in
4680 ext_port = self.tcp_external_port
4681 payload = "H" * 10
4682
4683 self.nat_add_address(self.nat_addr)
4684 self.nat_add_inside_interface(self.pg0)
4685 self.nat_add_outside_interface(self.pg1)
4686
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004687 self.vapi.nat_set_timeouts(
4688 udp=300, tcp_established=7440, tcp_transitory=5, icmp=60
4689 )
Klement Sekera56c492a2022-01-10 21:57:27 +00004690 # SYN packet in->out
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004691 p = (
4692 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
4693 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
4694 / TCP(sport=in_port, dport=ext_port, flags="S")
4695 )
Klement Sekera56c492a2022-01-10 21:57:27 +00004696 p = self.send_and_expect(self.pg0, p, self.pg1)[0]
4697 out_port = p[TCP].sport
4698
4699 # SYN + ACK packet out->in
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004700 p = (
4701 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
4702 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
4703 / TCP(sport=ext_port, dport=out_port, flags="SA")
4704 )
Klement Sekera56c492a2022-01-10 21:57:27 +00004705 self.send_and_expect(self.pg1, p, self.pg0)
4706
4707 # ACK in->out does not arrive
4708
4709 # resent SYN + ACK packet out->in
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004710 p = (
4711 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
4712 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
4713 / TCP(sport=ext_port, dport=out_port, flags="SA")
4714 )
Klement Sekera56c492a2022-01-10 21:57:27 +00004715 self.send_and_expect(self.pg1, p, self.pg0)
4716
4717 # ACK packet in->out
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004718 p = (
4719 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
4720 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
4721 / TCP(sport=in_port, dport=ext_port, flags="A")
4722 )
Klement Sekera56c492a2022-01-10 21:57:27 +00004723 self.send_and_expect(self.pg0, p, self.pg1)
4724
4725 # Verify that the data can be transmitted after the transitory time
4726 self.virtual_sleep(6)
4727
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004728 p = (
4729 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
4730 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
4731 / TCP(sport=in_port, dport=ext_port, flags="PA")
4732 / Raw(payload)
4733 )
Klement Sekera56c492a2022-01-10 21:57:27 +00004734 self.send_and_expect(self.pg0, p, self.pg1)
4735
4736 def test_tcp_session_open_retransmit2(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004737 """NAT44ED Open TCP session with SYN,ACK retransmit 2
Klement Sekera56c492a2022-01-10 21:57:27 +00004738
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004739 The ACK is lost to the server after the TCP session is opened.
4740 Data is sent by the client, then the [SYN,ACK] is
4741 retransmitted by the server.
Klement Sekera56c492a2022-01-10 21:57:27 +00004742 """
4743
4744 in_port = self.tcp_port_in
4745 ext_port = self.tcp_external_port
4746 payload = "H" * 10
4747
4748 self.nat_add_address(self.nat_addr)
4749 self.nat_add_inside_interface(self.pg0)
4750 self.nat_add_outside_interface(self.pg1)
4751
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004752 self.vapi.nat_set_timeouts(
4753 udp=300, tcp_established=7440, tcp_transitory=5, icmp=60
4754 )
Klement Sekera56c492a2022-01-10 21:57:27 +00004755 # SYN packet in->out
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004756 p = (
4757 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
4758 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
4759 / TCP(sport=in_port, dport=ext_port, flags="S")
4760 )
Klement Sekera56c492a2022-01-10 21:57:27 +00004761 p = self.send_and_expect(self.pg0, p, self.pg1)[0]
4762 out_port = p[TCP].sport
4763
4764 # SYN + ACK packet out->in
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004765 p = (
4766 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
4767 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
4768 / TCP(sport=ext_port, dport=out_port, flags="SA")
4769 )
Klement Sekera56c492a2022-01-10 21:57:27 +00004770 self.send_and_expect(self.pg1, p, self.pg0)
4771
4772 # ACK packet in->out -- not received by the server
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004773 p = (
4774 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
4775 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
4776 / TCP(sport=in_port, dport=ext_port, flags="A")
4777 )
Klement Sekera56c492a2022-01-10 21:57:27 +00004778 self.send_and_expect(self.pg0, p, self.pg1)
4779
4780 # PUSH + ACK packet in->out
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004781 p = (
4782 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
4783 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
4784 / TCP(sport=in_port, dport=ext_port, flags="PA")
4785 / Raw(payload)
4786 )
Klement Sekera56c492a2022-01-10 21:57:27 +00004787 self.send_and_expect(self.pg0, p, self.pg1)
4788
4789 # resent SYN + ACK packet out->in
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004790 p = (
4791 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
4792 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
4793 / TCP(sport=ext_port, dport=out_port, flags="SA")
4794 )
Klement Sekera56c492a2022-01-10 21:57:27 +00004795 self.send_and_expect(self.pg1, p, self.pg0)
4796
4797 # resent ACK packet in->out
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004798 p = (
4799 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
4800 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
4801 / TCP(sport=in_port, dport=ext_port, flags="A")
4802 )
Klement Sekera56c492a2022-01-10 21:57:27 +00004803 self.send_and_expect(self.pg0, p, self.pg1)
4804
4805 # resent PUSH + ACK packet in->out
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004806 p = (
4807 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
4808 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
4809 / TCP(sport=in_port, dport=ext_port, flags="PA")
4810 / Raw(payload)
4811 )
Klement Sekera56c492a2022-01-10 21:57:27 +00004812 self.send_and_expect(self.pg0, p, self.pg1)
4813
4814 # ACK packet out->in
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004815 p = (
4816 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
4817 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
4818 / TCP(sport=ext_port, dport=out_port, flags="A")
4819 )
Klement Sekera56c492a2022-01-10 21:57:27 +00004820 self.send_and_expect(self.pg1, p, self.pg0)
4821
4822 # Verify that the data can be transmitted after the transitory time
4823 self.virtual_sleep(6)
4824
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004825 p = (
4826 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
4827 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
4828 / TCP(sport=in_port, dport=ext_port, flags="PA")
4829 / Raw(payload)
4830 )
Klement Sekera56c492a2022-01-10 21:57:27 +00004831 self.send_and_expect(self.pg0, p, self.pg1)
4832
Dmitry Valter6b97c432022-12-09 19:34:22 +00004833 def test_dynamic_ports_exhausted(self):
4834 """NAT44ED dynamic translation test: address ports exhaused"""
4835
4836 sessions_per_batch = 128
4837 n_available_ports = 65536 - 1024
4838 n_sessions = n_available_ports + 2 * sessions_per_batch
4839
4840 # set high enough session limit for ports to be exhausted
4841 self.plugin_disable()
4842 self.plugin_enable(max_sessions=n_sessions)
4843
4844 self.nat_add_inside_interface(self.pg0)
4845 self.nat_add_outside_interface(self.pg1)
4846
4847 # set timeouts to high for sessions to reallistically expire
4848 config = self.vapi.nat44_show_running_config()
4849 old_timeouts = config.timeouts
4850 self.vapi.nat_set_timeouts(
4851 udp=21600,
4852 tcp_established=old_timeouts.tcp_established,
4853 tcp_transitory=old_timeouts.tcp_transitory,
4854 icmp=old_timeouts.icmp,
4855 )
4856
4857 # in2out after NAT addresses added
4858 self.nat_add_address(self.nat_addr)
4859
4860 for i in range(n_sessions // sessions_per_batch):
4861 pkts = self.create_udp_stream(
4862 self.pg0,
4863 self.pg1,
4864 sessions_per_batch,
4865 base_port=i * sessions_per_batch + 100,
4866 )
4867
4868 self.pg0.add_stream(pkts)
4869 self.pg_start()
4870
4871 err = self.statistics.get_err_counter(
4872 "/err/nat44-ed-in2out-slowpath/out of ports"
4873 )
4874 if err > sessions_per_batch:
4875 break
4876
4877 # Check for ports to be used no more than once
4878 ports = set()
4879 sessions = self.vapi.cli("show nat44 sessions")
4880 rx = re.compile(
4881 f" *o2i flow: match: saddr {self.pg1.remote_ip4} sport [0-9]+ daddr {self.nat_addr} dport ([0-9]+) proto UDP.*"
4882 )
4883 for line in sessions.splitlines():
4884 m = rx.match(line)
4885 if m:
4886 port = int(m.groups()[0])
4887 self.assertNotIn(port, ports)
4888 ports.add(port)
4889
4890 self.assertGreaterEqual(err, sessions_per_batch)
4891
Filip Varga18f1e412020-12-03 15:27:40 +01004892
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004893if __name__ == "__main__":
Filip Varga18f1e412020-12-03 15:27:40 +01004894 unittest.main(testRunner=VppTestRunner)