blob: 21eebb22de483f96639950ebf029d2ff3b967dc7 [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
7import scapy.compat
8from framework import VppTestCase, VppTestRunner
9from scapy.data import IP_PROTOS
10from scapy.layers.inet import IP, TCP, UDP, ICMP, GRE
11from scapy.layers.inet import IPerror, TCPerror
12from scapy.layers.l2 import Ether
13from scapy.packet import Raw
14from syslog_rfc5424_parser import SyslogMessage, ParseError
15from syslog_rfc5424_parser.constants import SyslogSeverity
Klement Sekerac2feb652022-03-08 20:13:57 +010016from util import ppp, pr, ip4_range
Filip Varga18f1e412020-12-03 15:27:40 +010017from vpp_acl import AclRule, VppAcl, VppAclInterface
18from vpp_ip_route import VppIpRoute, VppRoutePath
19from vpp_papi import VppEnum
Klement Sekeraad3187f2022-02-18 10:34:35 +000020from util import StatsDiff
Filip Varga18f1e412020-12-03 15:27:40 +010021
22
Klement Sekeraff334db2021-05-26 13:02:35 +020023class TestNAT44ED(VppTestCase):
24 """ NAT44ED Test Case """
Filip Varga18f1e412020-12-03 15:27:40 +010025
Filip Vargab19d3e32021-11-22 10:57:32 +010026 nat_addr = '10.0.10.3'
Filip Varga18f1e412020-12-03 15:27:40 +010027
28 tcp_port_in = 6303
29 tcp_port_out = 6303
30
31 udp_port_in = 6304
32 udp_port_out = 6304
33
34 icmp_id_in = 6305
35 icmp_id_out = 6305
36
37 tcp_external_port = 80
38
39 max_sessions = 100
40
41 def setUp(self):
Klement Sekeraff334db2021-05-26 13:02:35 +020042 super().setUp()
Filip Varga18f1e412020-12-03 15:27:40 +010043 self.plugin_enable()
44
45 def tearDown(self):
Klement Sekeraff334db2021-05-26 13:02:35 +020046 super().tearDown()
Filip Varga18f1e412020-12-03 15:27:40 +010047 if not self.vpp_dead:
48 self.plugin_disable()
49
50 def plugin_enable(self):
Filip Vargae7a80a92021-02-26 09:31:21 +010051 self.vapi.nat44_ed_plugin_enable_disable(
Ole Troan23a15b32021-10-12 12:45:08 +020052 sessions=self.max_sessions, enable=1)
Filip Varga18f1e412020-12-03 15:27:40 +010053
54 def plugin_disable(self):
Filip Vargae7a80a92021-02-26 09:31:21 +010055 self.vapi.nat44_ed_plugin_enable_disable(enable=0)
Filip Varga18f1e412020-12-03 15:27:40 +010056
57 @property
58 def config_flags(self):
59 return VppEnum.vl_api_nat_config_flags_t
60
61 @property
62 def nat44_config_flags(self):
63 return VppEnum.vl_api_nat44_config_flags_t
64
65 @property
66 def syslog_severity(self):
67 return VppEnum.vl_api_syslog_severity_t
68
69 @property
70 def server_addr(self):
71 return self.pg1.remote_hosts[0].ip4
72
73 @staticmethod
74 def random_port():
75 return randint(1025, 65535)
76
77 @staticmethod
78 def proto2layer(proto):
79 if proto == IP_PROTOS.tcp:
80 return TCP
81 elif proto == IP_PROTOS.udp:
82 return UDP
83 elif proto == IP_PROTOS.icmp:
84 return ICMP
85 else:
86 raise Exception("Unsupported protocol")
87
88 @classmethod
89 def create_and_add_ip4_table(cls, i, table_id=0):
90 cls.vapi.ip_table_add_del(is_add=1, table={'table_id': table_id})
91 i.set_table_ip4(table_id)
92
93 @classmethod
94 def configure_ip4_interface(cls, i, hosts=0, table_id=None):
95 if table_id:
96 cls.create_and_add_ip4_table(i, table_id)
97
98 i.admin_up()
Filip Varga18f1e412020-12-03 15:27:40 +010099 i.config_ip4()
100 i.resolve_arp()
101
102 if hosts:
103 i.generate_remote_hosts(hosts)
104 i.configure_ipv4_neighbors()
105
106 @classmethod
107 def nat_add_interface_address(cls, i):
108 cls.vapi.nat44_add_del_interface_addr(
109 sw_if_index=i.sw_if_index, is_add=1)
110
111 def nat_add_inside_interface(self, i):
112 self.vapi.nat44_interface_add_del_feature(
113 flags=self.config_flags.NAT_IS_INSIDE,
114 sw_if_index=i.sw_if_index, is_add=1)
115
116 def nat_add_outside_interface(self, i):
117 self.vapi.nat44_interface_add_del_feature(
118 flags=self.config_flags.NAT_IS_OUTSIDE,
119 sw_if_index=i.sw_if_index, is_add=1)
120
121 def nat_add_address(self, address, twice_nat=0,
122 vrf_id=0xFFFFFFFF, is_add=1):
123 flags = self.config_flags.NAT_IS_TWICE_NAT if twice_nat else 0
124 self.vapi.nat44_add_del_address_range(first_ip_address=address,
125 last_ip_address=address,
126 vrf_id=vrf_id,
127 is_add=is_add,
128 flags=flags)
129
130 def nat_add_static_mapping(self, local_ip, external_ip='0.0.0.0',
131 local_port=0, external_port=0, vrf_id=0,
132 is_add=1, external_sw_if_index=0xFFFFFFFF,
133 proto=0, tag="", flags=0):
134
135 if not (local_port and external_port):
136 flags |= self.config_flags.NAT_IS_ADDR_ONLY
137
138 self.vapi.nat44_add_del_static_mapping(
139 is_add=is_add,
140 local_ip_address=local_ip,
141 external_ip_address=external_ip,
142 external_sw_if_index=external_sw_if_index,
143 local_port=local_port,
144 external_port=external_port,
145 vrf_id=vrf_id, protocol=proto,
146 flags=flags,
147 tag=tag)
148
149 @classmethod
150 def setUpClass(cls):
Klement Sekeraff334db2021-05-26 13:02:35 +0200151 super().setUpClass()
Filip Varga18f1e412020-12-03 15:27:40 +0100152
153 cls.create_pg_interfaces(range(12))
154 cls.interfaces = list(cls.pg_interfaces[:4])
155
156 cls.create_and_add_ip4_table(cls.pg2, 10)
157
158 for i in cls.interfaces:
159 cls.configure_ip4_interface(i, hosts=3)
160
161 # test specific (test-multiple-vrf)
162 cls.vapi.ip_table_add_del(is_add=1, table={'table_id': 1})
163
164 # test specific (test-one-armed-nat44-static)
165 cls.pg4.generate_remote_hosts(2)
166 cls.pg4.config_ip4()
167 cls.vapi.sw_interface_add_del_address(
168 sw_if_index=cls.pg4.sw_if_index,
169 prefix="10.0.0.1/24")
170 cls.pg4.admin_up()
171 cls.pg4.resolve_arp()
172 cls.pg4._remote_hosts[1]._ip4 = cls.pg4._remote_hosts[0]._ip4
173 cls.pg4.resolve_arp()
174
175 # test specific interface (pg5)
176 cls.pg5._local_ip4 = "10.1.1.1"
177 cls.pg5._remote_hosts[0]._ip4 = "10.1.1.2"
178 cls.pg5.set_table_ip4(1)
179 cls.pg5.config_ip4()
180 cls.pg5.admin_up()
181 cls.pg5.resolve_arp()
182
183 # test specific interface (pg6)
184 cls.pg6._local_ip4 = "10.1.2.1"
185 cls.pg6._remote_hosts[0]._ip4 = "10.1.2.2"
186 cls.pg6.set_table_ip4(1)
187 cls.pg6.config_ip4()
188 cls.pg6.admin_up()
189 cls.pg6.resolve_arp()
190
191 rl = list()
192
193 rl.append(VppIpRoute(cls, "0.0.0.0", 0,
194 [VppRoutePath("0.0.0.0", 0xffffffff,
195 nh_table_id=0)],
196 register=False, table_id=1))
197 rl.append(VppIpRoute(cls, "0.0.0.0", 0,
198 [VppRoutePath(cls.pg1.local_ip4,
199 cls.pg1.sw_if_index)],
200 register=False))
201 rl.append(VppIpRoute(cls, cls.pg5.remote_ip4, 32,
202 [VppRoutePath("0.0.0.0",
203 cls.pg5.sw_if_index)],
204 register=False, table_id=1))
205 rl.append(VppIpRoute(cls, cls.pg6.remote_ip4, 32,
206 [VppRoutePath("0.0.0.0",
207 cls.pg6.sw_if_index)],
208 register=False, table_id=1))
209 rl.append(VppIpRoute(cls, cls.pg6.remote_ip4, 16,
210 [VppRoutePath("0.0.0.0", 0xffffffff,
211 nh_table_id=1)],
212 register=False, table_id=0))
213
214 for r in rl:
215 r.add_vpp_config()
216
Klement Sekeraad3187f2022-02-18 10:34:35 +0000217 cls.no_diff = StatsDiff({
218 pg.sw_if_index: {
219 '/nat44-ed/in2out/fastpath/tcp': 0,
220 '/nat44-ed/in2out/fastpath/udp': 0,
221 '/nat44-ed/in2out/fastpath/icmp': 0,
222 '/nat44-ed/in2out/fastpath/drops': 0,
223 '/nat44-ed/in2out/slowpath/tcp': 0,
224 '/nat44-ed/in2out/slowpath/udp': 0,
225 '/nat44-ed/in2out/slowpath/icmp': 0,
226 '/nat44-ed/in2out/slowpath/drops': 0,
227 '/nat44-ed/in2out/fastpath/tcp': 0,
228 '/nat44-ed/in2out/fastpath/udp': 0,
229 '/nat44-ed/in2out/fastpath/icmp': 0,
230 '/nat44-ed/in2out/fastpath/drops': 0,
231 '/nat44-ed/in2out/slowpath/tcp': 0,
232 '/nat44-ed/in2out/slowpath/udp': 0,
233 '/nat44-ed/in2out/slowpath/icmp': 0,
234 '/nat44-ed/in2out/slowpath/drops': 0,
235 }
236 for pg in cls.pg_interfaces
237 })
238
Filip Varga18f1e412020-12-03 15:27:40 +0100239 def get_err_counter(self, path):
240 return self.statistics.get_err_counter(path)
241
Filip Varga18f1e412020-12-03 15:27:40 +0100242 def reass_hairpinning(self, server_addr, server_in_port, server_out_port,
243 host_in_port, proto=IP_PROTOS.tcp,
244 ignore_port=False):
245 layer = self.proto2layer(proto)
246
247 if proto == IP_PROTOS.tcp:
248 data = b"A" * 4 + b"B" * 16 + b"C" * 3
249 else:
250 data = b"A" * 16 + b"B" * 16 + b"C" * 3
251
252 # send packet from host to server
253 pkts = self.create_stream_frag(self.pg0,
254 self.nat_addr,
255 host_in_port,
256 server_out_port,
257 data,
258 proto)
259 self.pg0.add_stream(pkts)
260 self.pg_enable_capture(self.pg_interfaces)
261 self.pg_start()
262 frags = self.pg0.get_capture(len(pkts))
263 p = self.reass_frags_and_verify(frags,
264 self.nat_addr,
265 server_addr)
266 if proto != IP_PROTOS.icmp:
267 if not ignore_port:
268 self.assertNotEqual(p[layer].sport, host_in_port)
269 self.assertEqual(p[layer].dport, server_in_port)
270 else:
271 if not ignore_port:
272 self.assertNotEqual(p[layer].id, host_in_port)
273 self.assertEqual(data, p[Raw].load)
274
275 def frag_out_of_order(self, proto=IP_PROTOS.tcp, dont_translate=False,
276 ignore_port=False):
277 layer = self.proto2layer(proto)
278
279 if proto == IP_PROTOS.tcp:
280 data = b"A" * 4 + b"B" * 16 + b"C" * 3
281 else:
282 data = b"A" * 16 + b"B" * 16 + b"C" * 3
283 self.port_in = self.random_port()
284
285 for i in range(2):
286 # in2out
287 pkts = self.create_stream_frag(self.pg0, self.pg1.remote_ip4,
288 self.port_in, 20, data, proto)
289 pkts.reverse()
290 self.pg0.add_stream(pkts)
291 self.pg_enable_capture(self.pg_interfaces)
292 self.pg_start()
293 frags = self.pg1.get_capture(len(pkts))
294 if not dont_translate:
295 p = self.reass_frags_and_verify(frags,
296 self.nat_addr,
297 self.pg1.remote_ip4)
298 else:
299 p = self.reass_frags_and_verify(frags,
300 self.pg0.remote_ip4,
301 self.pg1.remote_ip4)
302 if proto != IP_PROTOS.icmp:
303 if not dont_translate:
304 self.assertEqual(p[layer].dport, 20)
305 if not ignore_port:
306 self.assertNotEqual(p[layer].sport, self.port_in)
307 else:
308 self.assertEqual(p[layer].sport, self.port_in)
309 else:
310 if not ignore_port:
311 if not dont_translate:
312 self.assertNotEqual(p[layer].id, self.port_in)
313 else:
314 self.assertEqual(p[layer].id, self.port_in)
315 self.assertEqual(data, p[Raw].load)
316
317 # out2in
318 if not dont_translate:
319 dst_addr = self.nat_addr
320 else:
321 dst_addr = self.pg0.remote_ip4
322 if proto != IP_PROTOS.icmp:
323 sport = 20
324 dport = p[layer].sport
325 else:
326 sport = p[layer].id
327 dport = 0
328 pkts = self.create_stream_frag(self.pg1, dst_addr, sport, dport,
329 data, proto, echo_reply=True)
330 pkts.reverse()
331 self.pg1.add_stream(pkts)
332 self.pg_enable_capture(self.pg_interfaces)
Klement Sekerae79bbe92021-03-04 18:41:02 +0100333 self.logger.info(self.vapi.cli("show trace"))
Filip Varga18f1e412020-12-03 15:27:40 +0100334 self.pg_start()
335 frags = self.pg0.get_capture(len(pkts))
336 p = self.reass_frags_and_verify(frags,
337 self.pg1.remote_ip4,
338 self.pg0.remote_ip4)
339 if proto != IP_PROTOS.icmp:
340 self.assertEqual(p[layer].sport, 20)
341 self.assertEqual(p[layer].dport, self.port_in)
342 else:
343 self.assertEqual(p[layer].id, self.port_in)
344 self.assertEqual(data, p[Raw].load)
345
346 def reass_frags_and_verify(self, frags, src, dst):
347 buffer = BytesIO()
348 for p in frags:
349 self.assertEqual(p[IP].src, src)
350 self.assertEqual(p[IP].dst, dst)
351 self.assert_ip_checksum_valid(p)
352 buffer.seek(p[IP].frag * 8)
353 buffer.write(bytes(p[IP].payload))
354 ip = IP(src=frags[0][IP].src, dst=frags[0][IP].dst,
355 proto=frags[0][IP].proto)
356 if ip.proto == IP_PROTOS.tcp:
357 p = (ip / TCP(buffer.getvalue()))
358 self.logger.debug(ppp("Reassembled:", p))
359 self.assert_tcp_checksum_valid(p)
360 elif ip.proto == IP_PROTOS.udp:
361 p = (ip / UDP(buffer.getvalue()[:8]) /
362 Raw(buffer.getvalue()[8:]))
363 elif ip.proto == IP_PROTOS.icmp:
364 p = (ip / ICMP(buffer.getvalue()))
365 return p
366
367 def frag_in_order(self, proto=IP_PROTOS.tcp, dont_translate=False,
368 ignore_port=False):
369 layer = self.proto2layer(proto)
370
371 if proto == IP_PROTOS.tcp:
372 data = b"A" * 4 + b"B" * 16 + b"C" * 3
373 else:
374 data = b"A" * 16 + b"B" * 16 + b"C" * 3
375 self.port_in = self.random_port()
376
377 # in2out
378 pkts = self.create_stream_frag(self.pg0, self.pg1.remote_ip4,
379 self.port_in, 20, data, proto)
380 self.pg0.add_stream(pkts)
381 self.pg_enable_capture(self.pg_interfaces)
382 self.pg_start()
383 frags = self.pg1.get_capture(len(pkts))
384 if not dont_translate:
385 p = self.reass_frags_and_verify(frags,
386 self.nat_addr,
387 self.pg1.remote_ip4)
388 else:
389 p = self.reass_frags_and_verify(frags,
390 self.pg0.remote_ip4,
391 self.pg1.remote_ip4)
392 if proto != IP_PROTOS.icmp:
393 if not dont_translate:
394 self.assertEqual(p[layer].dport, 20)
395 if not ignore_port:
396 self.assertNotEqual(p[layer].sport, self.port_in)
397 else:
398 self.assertEqual(p[layer].sport, self.port_in)
399 else:
400 if not ignore_port:
401 if not dont_translate:
402 self.assertNotEqual(p[layer].id, self.port_in)
403 else:
404 self.assertEqual(p[layer].id, self.port_in)
405 self.assertEqual(data, p[Raw].load)
406
407 # out2in
408 if not dont_translate:
409 dst_addr = self.nat_addr
410 else:
411 dst_addr = self.pg0.remote_ip4
412 if proto != IP_PROTOS.icmp:
413 sport = 20
414 dport = p[layer].sport
415 else:
416 sport = p[layer].id
417 dport = 0
418 pkts = self.create_stream_frag(self.pg1, dst_addr, sport, dport, data,
419 proto, echo_reply=True)
420 self.pg1.add_stream(pkts)
421 self.pg_enable_capture(self.pg_interfaces)
422 self.pg_start()
423 frags = self.pg0.get_capture(len(pkts))
424 p = self.reass_frags_and_verify(frags,
425 self.pg1.remote_ip4,
426 self.pg0.remote_ip4)
427 if proto != IP_PROTOS.icmp:
428 self.assertEqual(p[layer].sport, 20)
429 self.assertEqual(p[layer].dport, self.port_in)
430 else:
431 self.assertEqual(p[layer].id, self.port_in)
432 self.assertEqual(data, p[Raw].load)
433
434 def verify_capture_out(self, capture, nat_ip=None, same_port=False,
435 dst_ip=None, ignore_port=False):
436 if nat_ip is None:
437 nat_ip = self.nat_addr
438 for packet in capture:
439 try:
440 self.assert_packet_checksums_valid(packet)
441 self.assertEqual(packet[IP].src, nat_ip)
442 if dst_ip is not None:
443 self.assertEqual(packet[IP].dst, dst_ip)
444 if packet.haslayer(TCP):
445 if not ignore_port:
446 if same_port:
447 self.assertEqual(
448 packet[TCP].sport, self.tcp_port_in)
449 else:
450 self.assertNotEqual(
451 packet[TCP].sport, self.tcp_port_in)
452 self.tcp_port_out = packet[TCP].sport
453 self.assert_packet_checksums_valid(packet)
454 elif packet.haslayer(UDP):
455 if not ignore_port:
456 if same_port:
457 self.assertEqual(
458 packet[UDP].sport, self.udp_port_in)
459 else:
460 self.assertNotEqual(
461 packet[UDP].sport, self.udp_port_in)
462 self.udp_port_out = packet[UDP].sport
463 else:
464 if not ignore_port:
465 if same_port:
466 self.assertEqual(
467 packet[ICMP].id, self.icmp_id_in)
468 else:
469 self.assertNotEqual(
470 packet[ICMP].id, self.icmp_id_in)
471 self.icmp_id_out = packet[ICMP].id
472 self.assert_packet_checksums_valid(packet)
473 except:
474 self.logger.error(ppp("Unexpected or invalid packet "
475 "(outside network):", packet))
476 raise
477
478 def verify_capture_in(self, capture, in_if):
479 for packet in capture:
480 try:
481 self.assert_packet_checksums_valid(packet)
482 self.assertEqual(packet[IP].dst, in_if.remote_ip4)
483 if packet.haslayer(TCP):
484 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
485 elif packet.haslayer(UDP):
486 self.assertEqual(packet[UDP].dport, self.udp_port_in)
487 else:
488 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
489 except:
490 self.logger.error(ppp("Unexpected or invalid packet "
491 "(inside network):", packet))
492 raise
493
494 def create_stream_in(self, in_if, out_if, dst_ip=None, ttl=64):
495 if dst_ip is None:
496 dst_ip = out_if.remote_ip4
497
498 pkts = []
499 # TCP
500 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
501 IP(src=in_if.remote_ip4, dst=dst_ip, ttl=ttl) /
502 TCP(sport=self.tcp_port_in, dport=20))
503 pkts.extend([p, p])
504
505 # UDP
506 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
507 IP(src=in_if.remote_ip4, dst=dst_ip, ttl=ttl) /
508 UDP(sport=self.udp_port_in, dport=20))
509 pkts.append(p)
510
511 # ICMP
512 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
513 IP(src=in_if.remote_ip4, dst=dst_ip, ttl=ttl) /
514 ICMP(id=self.icmp_id_in, type='echo-request'))
515 pkts.append(p)
516
517 return pkts
518
519 def create_stream_out(self, out_if, dst_ip=None, ttl=64,
520 use_inside_ports=False):
521 if dst_ip is None:
522 dst_ip = self.nat_addr
523 if not use_inside_ports:
524 tcp_port = self.tcp_port_out
525 udp_port = self.udp_port_out
526 icmp_id = self.icmp_id_out
527 else:
528 tcp_port = self.tcp_port_in
529 udp_port = self.udp_port_in
530 icmp_id = self.icmp_id_in
531 pkts = []
532 # TCP
533 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
534 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
535 TCP(dport=tcp_port, sport=20))
536 pkts.extend([p, p])
537
538 # UDP
539 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
540 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
541 UDP(dport=udp_port, sport=20))
542 pkts.append(p)
543
544 # ICMP
545 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
546 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
547 ICMP(id=icmp_id, type='echo-reply'))
548 pkts.append(p)
549
550 return pkts
551
552 def create_tcp_stream(self, in_if, out_if, count):
553 pkts = []
554 port = 6303
555
556 for i in range(count):
557 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
558 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=64) /
559 TCP(sport=port + i, dport=20))
560 pkts.append(p)
561
562 return pkts
563
564 def create_stream_frag(self, src_if, dst, sport, dport, data,
565 proto=IP_PROTOS.tcp, echo_reply=False):
566 if proto == IP_PROTOS.tcp:
567 p = (IP(src=src_if.remote_ip4, dst=dst) /
568 TCP(sport=sport, dport=dport) /
569 Raw(data))
570 p = p.__class__(scapy.compat.raw(p))
571 chksum = p[TCP].chksum
572 proto_header = TCP(sport=sport, dport=dport, chksum=chksum)
573 elif proto == IP_PROTOS.udp:
574 proto_header = UDP(sport=sport, dport=dport)
575 elif proto == IP_PROTOS.icmp:
576 if not echo_reply:
577 proto_header = ICMP(id=sport, type='echo-request')
578 else:
579 proto_header = ICMP(id=sport, type='echo-reply')
580 else:
581 raise Exception("Unsupported protocol")
582 id = self.random_port()
583 pkts = []
584 if proto == IP_PROTOS.tcp:
585 raw = Raw(data[0:4])
586 else:
587 raw = Raw(data[0:16])
588 p = (Ether(src=src_if.remote_mac, dst=src_if.local_mac) /
589 IP(src=src_if.remote_ip4, dst=dst, flags="MF", frag=0, id=id) /
590 proto_header /
591 raw)
592 pkts.append(p)
593 if proto == IP_PROTOS.tcp:
594 raw = Raw(data[4:20])
595 else:
596 raw = Raw(data[16:32])
597 p = (Ether(src=src_if.remote_mac, dst=src_if.local_mac) /
598 IP(src=src_if.remote_ip4, dst=dst, flags="MF", frag=3, id=id,
599 proto=proto) /
600 raw)
601 pkts.append(p)
602 if proto == IP_PROTOS.tcp:
603 raw = Raw(data[20:])
604 else:
605 raw = Raw(data[32:])
606 p = (Ether(src=src_if.remote_mac, dst=src_if.local_mac) /
607 IP(src=src_if.remote_ip4, dst=dst, frag=5, proto=proto,
608 id=id) /
609 raw)
610 pkts.append(p)
611 return pkts
612
613 def frag_in_order_in_plus_out(self, in_addr, out_addr, in_port, out_port,
614 proto=IP_PROTOS.tcp):
615
616 layer = self.proto2layer(proto)
617
618 if proto == IP_PROTOS.tcp:
619 data = b"A" * 4 + b"B" * 16 + b"C" * 3
620 else:
621 data = b"A" * 16 + b"B" * 16 + b"C" * 3
622 port_in = self.random_port()
623
624 for i in range(2):
625 # out2in
626 pkts = self.create_stream_frag(self.pg0, out_addr,
627 port_in, out_port,
628 data, proto)
629 self.pg0.add_stream(pkts)
630 self.pg_enable_capture(self.pg_interfaces)
631 self.pg_start()
632 frags = self.pg1.get_capture(len(pkts))
633 p = self.reass_frags_and_verify(frags,
634 self.pg0.remote_ip4,
635 in_addr)
636 if proto != IP_PROTOS.icmp:
637 self.assertEqual(p[layer].sport, port_in)
638 self.assertEqual(p[layer].dport, in_port)
639 else:
640 self.assertEqual(p[layer].id, port_in)
641 self.assertEqual(data, p[Raw].load)
642
643 # in2out
644 if proto != IP_PROTOS.icmp:
645 pkts = self.create_stream_frag(self.pg1, self.pg0.remote_ip4,
646 in_port,
647 p[layer].sport, data, proto)
648 else:
649 pkts = self.create_stream_frag(self.pg1, self.pg0.remote_ip4,
650 p[layer].id, 0, data, proto,
651 echo_reply=True)
652 self.pg1.add_stream(pkts)
653 self.pg_enable_capture(self.pg_interfaces)
654 self.pg_start()
655 frags = self.pg0.get_capture(len(pkts))
656 p = self.reass_frags_and_verify(frags,
657 out_addr,
658 self.pg0.remote_ip4)
659 if proto != IP_PROTOS.icmp:
660 self.assertEqual(p[layer].sport, out_port)
661 self.assertEqual(p[layer].dport, port_in)
662 else:
663 self.assertEqual(p[layer].id, port_in)
664 self.assertEqual(data, p[Raw].load)
665
666 def frag_out_of_order_in_plus_out(self, in_addr, out_addr, in_port,
667 out_port, proto=IP_PROTOS.tcp):
668
669 layer = self.proto2layer(proto)
670
671 if proto == IP_PROTOS.tcp:
672 data = b"A" * 4 + b"B" * 16 + b"C" * 3
673 else:
674 data = b"A" * 16 + b"B" * 16 + b"C" * 3
675 port_in = self.random_port()
676
677 for i in range(2):
678 # out2in
679 pkts = self.create_stream_frag(self.pg0, out_addr,
680 port_in, out_port,
681 data, proto)
682 pkts.reverse()
683 self.pg0.add_stream(pkts)
684 self.pg_enable_capture(self.pg_interfaces)
685 self.pg_start()
686 frags = self.pg1.get_capture(len(pkts))
687 p = self.reass_frags_and_verify(frags,
688 self.pg0.remote_ip4,
689 in_addr)
690 if proto != IP_PROTOS.icmp:
691 self.assertEqual(p[layer].dport, in_port)
692 self.assertEqual(p[layer].sport, port_in)
693 self.assertEqual(p[layer].dport, in_port)
694 else:
695 self.assertEqual(p[layer].id, port_in)
696 self.assertEqual(data, p[Raw].load)
697
698 # in2out
699 if proto != IP_PROTOS.icmp:
700 pkts = self.create_stream_frag(self.pg1, self.pg0.remote_ip4,
701 in_port,
702 p[layer].sport, data, proto)
703 else:
704 pkts = self.create_stream_frag(self.pg1, self.pg0.remote_ip4,
705 p[layer].id, 0, data, proto,
706 echo_reply=True)
707 pkts.reverse()
708 self.pg1.add_stream(pkts)
709 self.pg_enable_capture(self.pg_interfaces)
710 self.pg_start()
711 frags = self.pg0.get_capture(len(pkts))
712 p = self.reass_frags_and_verify(frags,
713 out_addr,
714 self.pg0.remote_ip4)
715 if proto != IP_PROTOS.icmp:
716 self.assertEqual(p[layer].sport, out_port)
717 self.assertEqual(p[layer].dport, port_in)
718 else:
719 self.assertEqual(p[layer].id, port_in)
720 self.assertEqual(data, p[Raw].load)
721
722 def init_tcp_session(self, in_if, out_if, in_port, ext_port):
723 # SYN packet in->out
724 p = (Ether(src=in_if.remote_mac, dst=in_if.local_mac) /
725 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4) /
726 TCP(sport=in_port, dport=ext_port, flags="S"))
727 in_if.add_stream(p)
728 self.pg_enable_capture(self.pg_interfaces)
729 self.pg_start()
730 capture = out_if.get_capture(1)
731 p = capture[0]
732 out_port = p[TCP].sport
733
734 # SYN + ACK packet out->in
735 p = (Ether(src=out_if.remote_mac, dst=out_if.local_mac) /
736 IP(src=out_if.remote_ip4, dst=self.nat_addr) /
737 TCP(sport=ext_port, dport=out_port, flags="SA"))
738 out_if.add_stream(p)
739 self.pg_enable_capture(self.pg_interfaces)
740 self.pg_start()
741 in_if.get_capture(1)
742
743 # ACK packet in->out
744 p = (Ether(src=in_if.remote_mac, dst=in_if.local_mac) /
745 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4) /
746 TCP(sport=in_port, dport=ext_port, flags="A"))
747 in_if.add_stream(p)
748 self.pg_enable_capture(self.pg_interfaces)
749 self.pg_start()
750 out_if.get_capture(1)
751
752 return out_port
753
754 def twice_nat_common(self, self_twice_nat=False, same_pg=False, lb=False,
755 client_id=None):
756 twice_nat_addr = '10.0.1.3'
757
758 port_in = 8080
759 if lb:
760 if not same_pg:
761 port_in1 = port_in
762 port_in2 = port_in
763 else:
764 port_in1 = port_in + 1
765 port_in2 = port_in + 2
766
767 port_out = 80
768 eh_port_out = 4567
769
770 server1 = self.pg0.remote_hosts[0]
771 server2 = self.pg0.remote_hosts[1]
772 if lb and same_pg:
773 server2 = server1
774 if not lb:
775 server = server1
776
777 pg0 = self.pg0
778 if same_pg:
779 pg1 = self.pg0
780 else:
781 pg1 = self.pg1
782
783 eh_translate = ((not self_twice_nat) or (not lb and same_pg) or
784 client_id == 1)
785
786 self.nat_add_address(self.nat_addr)
787 self.nat_add_address(twice_nat_addr, twice_nat=1)
788
789 flags = 0
790 if self_twice_nat:
791 flags |= self.config_flags.NAT_IS_SELF_TWICE_NAT
792 else:
793 flags |= self.config_flags.NAT_IS_TWICE_NAT
794
795 if not lb:
796 self.nat_add_static_mapping(pg0.remote_ip4, self.nat_addr,
797 port_in, port_out,
798 proto=IP_PROTOS.tcp,
799 flags=flags)
800 else:
801 locals = [{'addr': server1.ip4,
802 'port': port_in1,
803 'probability': 50,
804 'vrf_id': 0},
805 {'addr': server2.ip4,
806 'port': port_in2,
807 'probability': 50,
808 'vrf_id': 0}]
809 out_addr = self.nat_addr
810
811 self.vapi.nat44_add_del_lb_static_mapping(is_add=1, flags=flags,
812 external_addr=out_addr,
813 external_port=port_out,
814 protocol=IP_PROTOS.tcp,
815 local_num=len(locals),
816 locals=locals)
817 self.nat_add_inside_interface(pg0)
818 self.nat_add_outside_interface(pg1)
819
820 if same_pg:
821 if not lb:
822 client = server
823 else:
824 assert client_id is not None
825 if client_id == 1:
826 client = self.pg0.remote_hosts[0]
827 elif client_id == 2:
828 client = self.pg0.remote_hosts[1]
829 else:
830 client = pg1.remote_hosts[0]
831 p = (Ether(src=pg1.remote_mac, dst=pg1.local_mac) /
832 IP(src=client.ip4, dst=self.nat_addr) /
833 TCP(sport=eh_port_out, dport=port_out))
834 pg1.add_stream(p)
835 self.pg_enable_capture(self.pg_interfaces)
836 self.pg_start()
837 capture = pg0.get_capture(1)
838 p = capture[0]
839 try:
840 ip = p[IP]
841 tcp = p[TCP]
842 if lb:
843 if ip.dst == server1.ip4:
844 server = server1
845 port_in = port_in1
846 else:
847 server = server2
848 port_in = port_in2
849 self.assertEqual(ip.dst, server.ip4)
850 if lb and same_pg:
851 self.assertIn(tcp.dport, [port_in1, port_in2])
852 else:
853 self.assertEqual(tcp.dport, port_in)
854 if eh_translate:
855 self.assertEqual(ip.src, twice_nat_addr)
856 self.assertNotEqual(tcp.sport, eh_port_out)
857 else:
858 self.assertEqual(ip.src, client.ip4)
859 self.assertEqual(tcp.sport, eh_port_out)
860 eh_addr_in = ip.src
861 eh_port_in = tcp.sport
862 saved_port_in = tcp.dport
863 self.assert_packet_checksums_valid(p)
864 except:
865 self.logger.error(ppp("Unexpected or invalid packet:", p))
866 raise
867
868 p = (Ether(src=server.mac, dst=pg0.local_mac) /
869 IP(src=server.ip4, dst=eh_addr_in) /
870 TCP(sport=saved_port_in, dport=eh_port_in))
871 pg0.add_stream(p)
872 self.pg_enable_capture(self.pg_interfaces)
873 self.pg_start()
874 capture = pg1.get_capture(1)
875 p = capture[0]
876 try:
877 ip = p[IP]
878 tcp = p[TCP]
879 self.assertEqual(ip.dst, client.ip4)
880 self.assertEqual(ip.src, self.nat_addr)
881 self.assertEqual(tcp.dport, eh_port_out)
882 self.assertEqual(tcp.sport, port_out)
883 self.assert_packet_checksums_valid(p)
884 except:
885 self.logger.error(ppp("Unexpected or invalid packet:", p))
886 raise
887
888 if eh_translate:
889 sessions = self.vapi.nat44_user_session_dump(server.ip4, 0)
890 self.assertEqual(len(sessions), 1)
891 self.assertTrue(sessions[0].flags &
892 self.config_flags.NAT_IS_EXT_HOST_VALID)
893 self.assertTrue(sessions[0].flags &
894 self.config_flags.NAT_IS_TWICE_NAT)
Filip Varga0eaf4e62021-02-17 14:34:54 +0100895 self.logger.info(self.vapi.cli("show nat44 sessions"))
Filip Varga18f1e412020-12-03 15:27:40 +0100896 self.vapi.nat44_del_session(
897 address=sessions[0].inside_ip_address,
898 port=sessions[0].inside_port,
899 protocol=sessions[0].protocol,
900 flags=(self.config_flags.NAT_IS_INSIDE |
901 self.config_flags.NAT_IS_EXT_HOST_VALID),
902 ext_host_address=sessions[0].ext_host_nat_address,
903 ext_host_port=sessions[0].ext_host_nat_port)
904 sessions = self.vapi.nat44_user_session_dump(server.ip4, 0)
905 self.assertEqual(len(sessions), 0)
906
Klement Sekera56c492a2022-01-10 21:57:27 +0000907 def verify_syslog_sess(self, data, msgid, is_ip6=False):
Filip Varga18f1e412020-12-03 15:27:40 +0100908 message = data.decode('utf-8')
909 try:
910 message = SyslogMessage.parse(message)
911 except ParseError as e:
912 self.logger.error(e)
913 raise
914 else:
915 self.assertEqual(message.severity, SyslogSeverity.info)
916 self.assertEqual(message.appname, 'NAT')
Klement Sekera56c492a2022-01-10 21:57:27 +0000917 self.assertEqual(message.msgid, msgid)
Filip Varga18f1e412020-12-03 15:27:40 +0100918 sd_params = message.sd.get('nsess')
919 self.assertTrue(sd_params is not None)
920 if is_ip6:
921 self.assertEqual(sd_params.get('IATYP'), 'IPv6')
922 self.assertEqual(sd_params.get('ISADDR'), self.pg0.remote_ip6)
923 else:
924 self.assertEqual(sd_params.get('IATYP'), 'IPv4')
925 self.assertEqual(sd_params.get('ISADDR'), self.pg0.remote_ip4)
926 self.assertTrue(sd_params.get('SSUBIX') is not None)
927 self.assertEqual(sd_params.get('ISPORT'), "%d" % self.tcp_port_in)
928 self.assertEqual(sd_params.get('XATYP'), 'IPv4')
929 self.assertEqual(sd_params.get('XSADDR'), self.nat_addr)
930 self.assertEqual(sd_params.get('XSPORT'), "%d" % self.tcp_port_out)
931 self.assertEqual(sd_params.get('PROTO'), "%d" % IP_PROTOS.tcp)
932 self.assertEqual(sd_params.get('SVLAN'), '0')
933 self.assertEqual(sd_params.get('XDADDR'), self.pg1.remote_ip4)
934 self.assertEqual(sd_params.get('XDPORT'),
935 "%d" % self.tcp_external_port)
936
Filip Vargaa0648b62021-06-21 12:59:41 +0200937 def test_icmp_error(self):
938 """ NAT44ED test ICMP error message with inner header"""
939
940 payload = "H" * 10
941
942 self.nat_add_address(self.nat_addr)
943 self.nat_add_inside_interface(self.pg0)
944 self.nat_add_outside_interface(self.pg1)
945
946 # in2out (initiate connection)
Klement Sekerac2feb652022-03-08 20:13:57 +0100947 p1 = [Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
Filip Vargaa0648b62021-06-21 12:59:41 +0200948 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Klement Sekerac2feb652022-03-08 20:13:57 +0100949 UDP(sport=21, dport=20) / payload,
950 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
951 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
952 TCP(sport=21, dport=20, flags="S") / payload,
953 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
954 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
955 ICMP(type='echo-request', id=7777) / payload,
956 ]
Filip Vargaa0648b62021-06-21 12:59:41 +0200957
Klement Sekerac2feb652022-03-08 20:13:57 +0100958 capture = self.send_and_expect(self.pg0, p1, self.pg1)
Filip Vargaa0648b62021-06-21 12:59:41 +0200959
960 # out2in (send error message)
Klement Sekerac2feb652022-03-08 20:13:57 +0100961 p2 = [Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
Filip Vargaa0648b62021-06-21 12:59:41 +0200962 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
963 ICMP(type='dest-unreach', code='port-unreachable') /
Klement Sekerac2feb652022-03-08 20:13:57 +0100964 c[IP:]
965 for c in capture]
Filip Vargaa0648b62021-06-21 12:59:41 +0200966
Klement Sekerac2feb652022-03-08 20:13:57 +0100967 capture = self.send_and_expect(self.pg1, p2, self.pg0)
Filip Vargaa0648b62021-06-21 12:59:41 +0200968
Klement Sekerac2feb652022-03-08 20:13:57 +0100969 for c in capture:
970 try:
971 assert c[IP].dst == self.pg0.remote_ip4
972 assert c[IPerror].src == self.pg0.remote_ip4
973 except AssertionError as a:
974 raise AssertionError(
975 f"Packet {pr(c)} not translated properly") from a
Filip Vargaa0648b62021-06-21 12:59:41 +0200976
Klement Sekera254c8032021-07-27 13:33:51 +0200977 def test_icmp_echo_reply_trailer(self):
978 """ ICMP echo reply with ethernet trailer"""
979
980 self.nat_add_address(self.nat_addr)
981 self.nat_add_inside_interface(self.pg0)
982 self.nat_add_outside_interface(self.pg1)
983
984 # in2out
985 p1 = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
986 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
987 ICMP(type=8, id=0xabcd, seq=0))
988
989 self.pg0.add_stream(p1)
990 self.pg_enable_capture(self.pg_interfaces)
991 self.pg_start()
992 c = self.pg1.get_capture(1)[0]
993
994 self.logger.debug(self.vapi.cli("show trace"))
995
996 # out2in
997 p2 = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
998 IP(src=self.pg1.remote_ip4, dst=self.nat_addr, id=0xee59) /
999 ICMP(type=0, id=c[ICMP].id, seq=0))
1000
1001 # force checksum calculation
1002 p2 = p2.__class__(bytes(p2))
1003
1004 self.logger.debug(ppp("Packet before modification:", p2))
1005
1006 # hex representation of vss monitoring ethernet trailer
1007 # this seems to be just added to end of packet without modifying
1008 # IP or ICMP lengths / checksums
1009 p2 = p2 / Raw("\x00\x00\x52\x54\x00\x46\xab\x04\x84\x18")
1010 # change it so that IP/ICMP is unaffected
1011 p2[IP].len = 28
1012
1013 self.logger.debug(ppp("Packet with added trailer:", p2))
1014
1015 self.pg1.add_stream(p2)
1016 self.pg_enable_capture(self.pg_interfaces)
1017 self.pg_start()
1018
1019 self.pg0.get_capture(1)
1020
Filip Varga18f1e412020-12-03 15:27:40 +01001021 def test_users_dump(self):
1022 """ NAT44ED API test - nat44_user_dump """
1023
1024 self.nat_add_address(self.nat_addr)
1025 self.nat_add_inside_interface(self.pg0)
1026 self.nat_add_outside_interface(self.pg1)
1027
1028 self.vapi.nat44_forwarding_enable_disable(enable=1)
1029
1030 local_ip = self.pg0.remote_ip4
1031 external_ip = self.nat_addr
1032 self.nat_add_static_mapping(local_ip, external_ip)
1033
1034 users = self.vapi.nat44_user_dump()
1035 self.assertEqual(len(users), 0)
1036
1037 # in2out - static mapping match
1038
1039 pkts = self.create_stream_out(self.pg1)
1040 self.pg1.add_stream(pkts)
1041 self.pg_enable_capture(self.pg_interfaces)
1042 self.pg_start()
1043 capture = self.pg0.get_capture(len(pkts))
1044 self.verify_capture_in(capture, self.pg0)
1045
1046 pkts = self.create_stream_in(self.pg0, self.pg1)
1047 self.pg0.add_stream(pkts)
1048 self.pg_enable_capture(self.pg_interfaces)
1049 self.pg_start()
1050 capture = self.pg1.get_capture(len(pkts))
1051 self.verify_capture_out(capture, same_port=True)
1052
1053 users = self.vapi.nat44_user_dump()
1054 self.assertEqual(len(users), 1)
1055 static_user = users[0]
1056 self.assertEqual(static_user.nstaticsessions, 3)
1057 self.assertEqual(static_user.nsessions, 0)
1058
1059 # in2out - no static mapping match (forwarding test)
1060
1061 host0 = self.pg0.remote_hosts[0]
1062 self.pg0.remote_hosts[0] = self.pg0.remote_hosts[1]
1063 try:
1064 pkts = self.create_stream_out(self.pg1,
1065 dst_ip=self.pg0.remote_ip4,
1066 use_inside_ports=True)
1067 self.pg1.add_stream(pkts)
1068 self.pg_enable_capture(self.pg_interfaces)
1069 self.pg_start()
1070 capture = self.pg0.get_capture(len(pkts))
1071 self.verify_capture_in(capture, self.pg0)
1072
1073 pkts = self.create_stream_in(self.pg0, self.pg1)
1074 self.pg0.add_stream(pkts)
1075 self.pg_enable_capture(self.pg_interfaces)
1076 self.pg_start()
1077 capture = self.pg1.get_capture(len(pkts))
1078 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
1079 same_port=True)
1080 finally:
1081 self.pg0.remote_hosts[0] = host0
1082
1083 users = self.vapi.nat44_user_dump()
1084 self.assertEqual(len(users), 2)
1085 if str(users[0].ip_address) == self.pg0.remote_hosts[0].ip4:
1086 non_static_user = users[1]
1087 static_user = users[0]
1088 else:
1089 non_static_user = users[0]
1090 static_user = users[1]
1091 self.assertEqual(static_user.nstaticsessions, 3)
1092 self.assertEqual(static_user.nsessions, 0)
1093 self.assertEqual(non_static_user.nstaticsessions, 0)
1094 self.assertEqual(non_static_user.nsessions, 3)
1095
1096 users = self.vapi.nat44_user_dump()
1097 self.assertEqual(len(users), 2)
1098 if str(users[0].ip_address) == self.pg0.remote_hosts[0].ip4:
1099 non_static_user = users[1]
1100 static_user = users[0]
1101 else:
1102 non_static_user = users[0]
1103 static_user = users[1]
1104 self.assertEqual(static_user.nstaticsessions, 3)
1105 self.assertEqual(static_user.nsessions, 0)
1106 self.assertEqual(non_static_user.nstaticsessions, 0)
1107 self.assertEqual(non_static_user.nsessions, 3)
1108
1109 def test_frag_out_of_order_do_not_translate(self):
1110 """ NAT44ED don't translate fragments arriving out of order """
1111 self.nat_add_inside_interface(self.pg0)
1112 self.nat_add_outside_interface(self.pg1)
1113 self.vapi.nat44_forwarding_enable_disable(enable=True)
1114 self.frag_out_of_order(proto=IP_PROTOS.tcp, dont_translate=True)
1115
1116 def test_forwarding(self):
1117 """ NAT44ED forwarding test """
1118
1119 self.nat_add_inside_interface(self.pg0)
1120 self.nat_add_outside_interface(self.pg1)
1121 self.vapi.nat44_forwarding_enable_disable(enable=1)
1122
1123 real_ip = self.pg0.remote_ip4
1124 alias_ip = self.nat_addr
1125 flags = self.config_flags.NAT_IS_ADDR_ONLY
1126 self.vapi.nat44_add_del_static_mapping(is_add=1,
1127 local_ip_address=real_ip,
1128 external_ip_address=alias_ip,
1129 external_sw_if_index=0xFFFFFFFF,
1130 flags=flags)
1131
1132 try:
1133 # in2out - static mapping match
1134
1135 pkts = self.create_stream_out(self.pg1)
1136 self.pg1.add_stream(pkts)
1137 self.pg_enable_capture(self.pg_interfaces)
1138 self.pg_start()
1139 capture = self.pg0.get_capture(len(pkts))
1140 self.verify_capture_in(capture, self.pg0)
1141
1142 pkts = self.create_stream_in(self.pg0, self.pg1)
1143 self.pg0.add_stream(pkts)
1144 self.pg_enable_capture(self.pg_interfaces)
1145 self.pg_start()
1146 capture = self.pg1.get_capture(len(pkts))
1147 self.verify_capture_out(capture, same_port=True)
1148
1149 # in2out - no static mapping match
1150
1151 host0 = self.pg0.remote_hosts[0]
1152 self.pg0.remote_hosts[0] = self.pg0.remote_hosts[1]
1153 try:
1154 pkts = self.create_stream_out(self.pg1,
1155 dst_ip=self.pg0.remote_ip4,
1156 use_inside_ports=True)
1157 self.pg1.add_stream(pkts)
1158 self.pg_enable_capture(self.pg_interfaces)
1159 self.pg_start()
1160 capture = self.pg0.get_capture(len(pkts))
1161 self.verify_capture_in(capture, self.pg0)
1162
1163 pkts = self.create_stream_in(self.pg0, self.pg1)
1164 self.pg0.add_stream(pkts)
1165 self.pg_enable_capture(self.pg_interfaces)
1166 self.pg_start()
1167 capture = self.pg1.get_capture(len(pkts))
1168 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
1169 same_port=True)
1170 finally:
1171 self.pg0.remote_hosts[0] = host0
1172
1173 user = self.pg0.remote_hosts[1]
1174 sessions = self.vapi.nat44_user_session_dump(user.ip4, 0)
1175 self.assertEqual(len(sessions), 3)
1176 self.assertTrue(sessions[0].flags &
1177 self.config_flags.NAT_IS_EXT_HOST_VALID)
1178 self.vapi.nat44_del_session(
1179 address=sessions[0].inside_ip_address,
1180 port=sessions[0].inside_port,
1181 protocol=sessions[0].protocol,
1182 flags=(self.config_flags.NAT_IS_INSIDE |
1183 self.config_flags.NAT_IS_EXT_HOST_VALID),
1184 ext_host_address=sessions[0].ext_host_address,
1185 ext_host_port=sessions[0].ext_host_port)
1186 sessions = self.vapi.nat44_user_session_dump(user.ip4, 0)
1187 self.assertEqual(len(sessions), 2)
1188
1189 finally:
1190 self.vapi.nat44_forwarding_enable_disable(enable=0)
1191 flags = self.config_flags.NAT_IS_ADDR_ONLY
1192 self.vapi.nat44_add_del_static_mapping(
1193 is_add=0,
1194 local_ip_address=real_ip,
1195 external_ip_address=alias_ip,
1196 external_sw_if_index=0xFFFFFFFF,
1197 flags=flags)
1198
1199 def test_output_feature_and_service2(self):
1200 """ NAT44ED interface output feature and service host direct access """
1201 self.vapi.nat44_forwarding_enable_disable(enable=1)
1202 self.nat_add_address(self.nat_addr)
1203
Filip Vargab6810822022-02-15 11:56:07 -08001204 self.vapi.nat44_ed_add_del_output_interface(
1205 sw_if_index=self.pg1.sw_if_index,
1206 is_add=1)
Filip Varga18f1e412020-12-03 15:27:40 +01001207
1208 # session initiated from service host - translate
1209 pkts = self.create_stream_in(self.pg0, self.pg1)
1210 self.pg0.add_stream(pkts)
1211 self.pg_enable_capture(self.pg_interfaces)
1212 self.pg_start()
1213 capture = self.pg1.get_capture(len(pkts))
1214 self.verify_capture_out(capture, ignore_port=True)
1215
1216 pkts = self.create_stream_out(self.pg1)
1217 self.pg1.add_stream(pkts)
1218 self.pg_enable_capture(self.pg_interfaces)
1219 self.pg_start()
1220 capture = self.pg0.get_capture(len(pkts))
1221 self.verify_capture_in(capture, self.pg0)
1222
1223 # session initiated from remote host - do not translate
1224 tcp_port_in = self.tcp_port_in
1225 udp_port_in = self.udp_port_in
1226 icmp_id_in = self.icmp_id_in
1227
1228 self.tcp_port_in = 60303
1229 self.udp_port_in = 60304
1230 self.icmp_id_in = 60305
1231
1232 try:
1233 pkts = self.create_stream_out(self.pg1,
1234 self.pg0.remote_ip4,
1235 use_inside_ports=True)
1236 self.pg1.add_stream(pkts)
1237 self.pg_enable_capture(self.pg_interfaces)
1238 self.pg_start()
1239 capture = self.pg0.get_capture(len(pkts))
1240 self.verify_capture_in(capture, self.pg0)
1241
1242 pkts = self.create_stream_in(self.pg0, self.pg1)
1243 self.pg0.add_stream(pkts)
1244 self.pg_enable_capture(self.pg_interfaces)
1245 self.pg_start()
1246 capture = self.pg1.get_capture(len(pkts))
1247 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
1248 same_port=True)
1249 finally:
1250 self.tcp_port_in = tcp_port_in
1251 self.udp_port_in = udp_port_in
1252 self.icmp_id_in = icmp_id_in
1253
1254 def test_twice_nat(self):
1255 """ NAT44ED Twice NAT """
1256 self.twice_nat_common()
1257
1258 def test_self_twice_nat_positive(self):
1259 """ NAT44ED Self Twice NAT (positive test) """
1260 self.twice_nat_common(self_twice_nat=True, same_pg=True)
1261
1262 def test_self_twice_nat_lb_positive(self):
1263 """ NAT44ED Self Twice NAT local service load balancing (positive test)
1264 """
1265 self.twice_nat_common(lb=True, self_twice_nat=True, same_pg=True,
1266 client_id=1)
1267
1268 def test_twice_nat_lb(self):
1269 """ NAT44ED Twice NAT local service load balancing """
1270 self.twice_nat_common(lb=True)
1271
1272 def test_output_feature(self):
1273 """ NAT44ED interface output feature (in2out postrouting) """
1274 self.vapi.nat44_forwarding_enable_disable(enable=1)
1275 self.nat_add_address(self.nat_addr)
1276
1277 self.nat_add_outside_interface(self.pg0)
Filip Vargab6810822022-02-15 11:56:07 -08001278 self.vapi.nat44_ed_add_del_output_interface(
1279 sw_if_index=self.pg1.sw_if_index,
1280 is_add=1)
Filip Varga18f1e412020-12-03 15:27:40 +01001281
1282 # in2out
1283 pkts = self.create_stream_in(self.pg0, self.pg1)
1284 self.pg0.add_stream(pkts)
1285 self.pg_enable_capture(self.pg_interfaces)
1286 self.pg_start()
1287 capture = self.pg1.get_capture(len(pkts))
1288 self.verify_capture_out(capture, ignore_port=True)
Klement Sekera05b5a5b2021-06-28 13:40:40 +02001289 self.logger.debug(self.vapi.cli("show trace"))
Filip Varga18f1e412020-12-03 15:27:40 +01001290
1291 # out2in
1292 pkts = self.create_stream_out(self.pg1)
1293 self.pg1.add_stream(pkts)
1294 self.pg_enable_capture(self.pg_interfaces)
1295 self.pg_start()
1296 capture = self.pg0.get_capture(len(pkts))
1297 self.verify_capture_in(capture, self.pg0)
Klement Sekera05b5a5b2021-06-28 13:40:40 +02001298 self.logger.debug(self.vapi.cli("show trace"))
Filip Varga18f1e412020-12-03 15:27:40 +01001299
Klement Sekera79699b02021-06-21 16:04:40 +02001300 # in2out
1301 pkts = self.create_stream_in(self.pg0, self.pg1, ttl=2)
1302 self.pg0.add_stream(pkts)
1303 self.pg_enable_capture(self.pg_interfaces)
1304 self.pg_start()
1305 capture = self.pg1.get_capture(len(pkts))
1306 self.verify_capture_out(capture, ignore_port=True)
Klement Sekera05b5a5b2021-06-28 13:40:40 +02001307 self.logger.debug(self.vapi.cli("show trace"))
Klement Sekera79699b02021-06-21 16:04:40 +02001308
1309 # out2in
1310 pkts = self.create_stream_out(self.pg1, ttl=2)
1311 self.pg1.add_stream(pkts)
1312 self.pg_enable_capture(self.pg_interfaces)
1313 self.pg_start()
1314 capture = self.pg0.get_capture(len(pkts))
1315 self.verify_capture_in(capture, self.pg0)
Klement Sekera05b5a5b2021-06-28 13:40:40 +02001316 self.logger.debug(self.vapi.cli("show trace"))
Klement Sekera79699b02021-06-21 16:04:40 +02001317
1318 # in2out
1319 pkts = self.create_stream_in(self.pg0, self.pg1, ttl=1)
Neale Ranns5c6dd172022-02-17 09:08:47 +00001320 capture = self.send_and_expect_some(self.pg0, pkts, self.pg0)
Klement Sekera79699b02021-06-21 16:04:40 +02001321 for p in capture:
1322 self.assertIn(ICMP, p)
1323 self.assertEqual(p[ICMP].type, 11) # 11 == time-exceeded
1324
Filip Varga18f1e412020-12-03 15:27:40 +01001325 def test_static_with_port_out2(self):
1326 """ NAT44ED 1:1 NAPT asymmetrical rule """
1327
1328 external_port = 80
1329 local_port = 8080
1330
1331 self.vapi.nat44_forwarding_enable_disable(enable=1)
1332 flags = self.config_flags.NAT_IS_OUT2IN_ONLY
1333 self.nat_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1334 local_port, external_port,
1335 proto=IP_PROTOS.tcp, flags=flags)
1336
1337 self.nat_add_inside_interface(self.pg0)
1338 self.nat_add_outside_interface(self.pg1)
1339
1340 # from client to service
1341 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
1342 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
1343 TCP(sport=12345, dport=external_port))
1344 self.pg1.add_stream(p)
1345 self.pg_enable_capture(self.pg_interfaces)
1346 self.pg_start()
1347 capture = self.pg0.get_capture(1)
1348 p = capture[0]
1349 try:
1350 ip = p[IP]
1351 tcp = p[TCP]
1352 self.assertEqual(ip.dst, self.pg0.remote_ip4)
1353 self.assertEqual(tcp.dport, local_port)
1354 self.assert_packet_checksums_valid(p)
1355 except:
1356 self.logger.error(ppp("Unexpected or invalid packet:", p))
1357 raise
1358
1359 # ICMP error
1360 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1361 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
1362 ICMP(type=11) / capture[0][IP])
1363 self.pg0.add_stream(p)
1364 self.pg_enable_capture(self.pg_interfaces)
1365 self.pg_start()
1366 capture = self.pg1.get_capture(1)
1367 p = capture[0]
1368 try:
1369 self.assertEqual(p[IP].src, self.nat_addr)
1370 inner = p[IPerror]
1371 self.assertEqual(inner.dst, self.nat_addr)
1372 self.assertEqual(inner[TCPerror].dport, external_port)
1373 except:
1374 self.logger.error(ppp("Unexpected or invalid packet:", p))
1375 raise
1376
1377 # from service back to client
1378 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
1379 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
1380 TCP(sport=local_port, dport=12345))
1381 self.pg0.add_stream(p)
1382 self.pg_enable_capture(self.pg_interfaces)
1383 self.pg_start()
1384 capture = self.pg1.get_capture(1)
1385 p = capture[0]
1386 try:
1387 ip = p[IP]
1388 tcp = p[TCP]
1389 self.assertEqual(ip.src, self.nat_addr)
1390 self.assertEqual(tcp.sport, external_port)
1391 self.assert_packet_checksums_valid(p)
1392 except:
1393 self.logger.error(ppp("Unexpected or invalid packet:", p))
1394 raise
1395
1396 # ICMP error
1397 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1398 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
1399 ICMP(type=11) / capture[0][IP])
1400 self.pg1.add_stream(p)
1401 self.pg_enable_capture(self.pg_interfaces)
1402 self.pg_start()
1403 capture = self.pg0.get_capture(1)
1404 p = capture[0]
1405 try:
1406 self.assertEqual(p[IP].dst, self.pg0.remote_ip4)
1407 inner = p[IPerror]
1408 self.assertEqual(inner.src, self.pg0.remote_ip4)
1409 self.assertEqual(inner[TCPerror].sport, local_port)
1410 except:
1411 self.logger.error(ppp("Unexpected or invalid packet:", p))
1412 raise
1413
1414 # from client to server (no translation)
1415 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
1416 IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
1417 TCP(sport=12346, dport=local_port))
1418 self.pg1.add_stream(p)
1419 self.pg_enable_capture(self.pg_interfaces)
1420 self.pg_start()
1421 capture = self.pg0.get_capture(1)
1422 p = capture[0]
1423 try:
1424 ip = p[IP]
1425 tcp = p[TCP]
1426 self.assertEqual(ip.dst, self.pg0.remote_ip4)
1427 self.assertEqual(tcp.dport, local_port)
1428 self.assert_packet_checksums_valid(p)
1429 except:
1430 self.logger.error(ppp("Unexpected or invalid packet:", p))
1431 raise
1432
1433 # from service back to client (no translation)
1434 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
1435 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
1436 TCP(sport=local_port, dport=12346))
1437 self.pg0.add_stream(p)
1438 self.pg_enable_capture(self.pg_interfaces)
1439 self.pg_start()
1440 capture = self.pg1.get_capture(1)
1441 p = capture[0]
1442 try:
1443 ip = p[IP]
1444 tcp = p[TCP]
1445 self.assertEqual(ip.src, self.pg0.remote_ip4)
1446 self.assertEqual(tcp.sport, local_port)
1447 self.assert_packet_checksums_valid(p)
1448 except:
1449 self.logger.error(ppp("Unexpected or invalid packet:", p))
1450 raise
1451
1452 def test_static_lb(self):
1453 """ NAT44ED local service load balancing """
1454 external_addr_n = self.nat_addr
1455 external_port = 80
1456 local_port = 8080
1457 server1 = self.pg0.remote_hosts[0]
1458 server2 = self.pg0.remote_hosts[1]
1459
1460 locals = [{'addr': server1.ip4,
1461 'port': local_port,
1462 'probability': 70,
1463 'vrf_id': 0},
1464 {'addr': server2.ip4,
1465 'port': local_port,
1466 'probability': 30,
1467 'vrf_id': 0}]
1468
1469 self.nat_add_address(self.nat_addr)
1470 self.vapi.nat44_add_del_lb_static_mapping(
1471 is_add=1,
1472 external_addr=external_addr_n,
1473 external_port=external_port,
1474 protocol=IP_PROTOS.tcp,
1475 local_num=len(locals),
1476 locals=locals)
1477 flags = self.config_flags.NAT_IS_INSIDE
1478 self.vapi.nat44_interface_add_del_feature(
1479 sw_if_index=self.pg0.sw_if_index,
1480 flags=flags, is_add=1)
1481 self.vapi.nat44_interface_add_del_feature(
1482 sw_if_index=self.pg1.sw_if_index,
1483 is_add=1)
1484
1485 # from client to service
1486 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
1487 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
1488 TCP(sport=12345, dport=external_port))
1489 self.pg1.add_stream(p)
1490 self.pg_enable_capture(self.pg_interfaces)
1491 self.pg_start()
1492 capture = self.pg0.get_capture(1)
1493 p = capture[0]
1494 server = None
1495 try:
1496 ip = p[IP]
1497 tcp = p[TCP]
1498 self.assertIn(ip.dst, [server1.ip4, server2.ip4])
1499 if ip.dst == server1.ip4:
1500 server = server1
1501 else:
1502 server = server2
1503 self.assertEqual(tcp.dport, local_port)
1504 self.assert_packet_checksums_valid(p)
1505 except:
1506 self.logger.error(ppp("Unexpected or invalid packet:", p))
1507 raise
1508
1509 # from service back to client
1510 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
1511 IP(src=server.ip4, dst=self.pg1.remote_ip4) /
1512 TCP(sport=local_port, dport=12345))
1513 self.pg0.add_stream(p)
1514 self.pg_enable_capture(self.pg_interfaces)
1515 self.pg_start()
1516 capture = self.pg1.get_capture(1)
1517 p = capture[0]
1518 try:
1519 ip = p[IP]
1520 tcp = p[TCP]
1521 self.assertEqual(ip.src, self.nat_addr)
1522 self.assertEqual(tcp.sport, external_port)
1523 self.assert_packet_checksums_valid(p)
1524 except:
1525 self.logger.error(ppp("Unexpected or invalid packet:", p))
1526 raise
1527
1528 sessions = self.vapi.nat44_user_session_dump(server.ip4, 0)
1529 self.assertEqual(len(sessions), 1)
1530 self.assertTrue(sessions[0].flags &
1531 self.config_flags.NAT_IS_EXT_HOST_VALID)
1532 self.vapi.nat44_del_session(
1533 address=sessions[0].inside_ip_address,
1534 port=sessions[0].inside_port,
1535 protocol=sessions[0].protocol,
1536 flags=(self.config_flags.NAT_IS_INSIDE |
1537 self.config_flags.NAT_IS_EXT_HOST_VALID),
1538 ext_host_address=sessions[0].ext_host_address,
1539 ext_host_port=sessions[0].ext_host_port)
1540 sessions = self.vapi.nat44_user_session_dump(server.ip4, 0)
1541 self.assertEqual(len(sessions), 0)
1542
1543 def test_static_lb_2(self):
1544 """ NAT44ED local service load balancing (asymmetrical rule) """
1545 external_addr = self.nat_addr
1546 external_port = 80
1547 local_port = 8080
1548 server1 = self.pg0.remote_hosts[0]
1549 server2 = self.pg0.remote_hosts[1]
1550
1551 locals = [{'addr': server1.ip4,
1552 'port': local_port,
1553 'probability': 70,
1554 'vrf_id': 0},
1555 {'addr': server2.ip4,
1556 'port': local_port,
1557 'probability': 30,
1558 'vrf_id': 0}]
1559
1560 self.vapi.nat44_forwarding_enable_disable(enable=1)
1561 flags = self.config_flags.NAT_IS_OUT2IN_ONLY
1562 self.vapi.nat44_add_del_lb_static_mapping(is_add=1, flags=flags,
1563 external_addr=external_addr,
1564 external_port=external_port,
1565 protocol=IP_PROTOS.tcp,
1566 local_num=len(locals),
1567 locals=locals)
1568 flags = self.config_flags.NAT_IS_INSIDE
1569 self.vapi.nat44_interface_add_del_feature(
1570 sw_if_index=self.pg0.sw_if_index,
1571 flags=flags, is_add=1)
1572 self.vapi.nat44_interface_add_del_feature(
1573 sw_if_index=self.pg1.sw_if_index,
1574 is_add=1)
1575
1576 # from client to service
1577 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
1578 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
1579 TCP(sport=12345, dport=external_port))
1580 self.pg1.add_stream(p)
1581 self.pg_enable_capture(self.pg_interfaces)
1582 self.pg_start()
1583 capture = self.pg0.get_capture(1)
1584 p = capture[0]
1585 server = None
1586 try:
1587 ip = p[IP]
1588 tcp = p[TCP]
1589 self.assertIn(ip.dst, [server1.ip4, server2.ip4])
1590 if ip.dst == server1.ip4:
1591 server = server1
1592 else:
1593 server = server2
1594 self.assertEqual(tcp.dport, local_port)
1595 self.assert_packet_checksums_valid(p)
1596 except:
1597 self.logger.error(ppp("Unexpected or invalid packet:", p))
1598 raise
1599
1600 # from service back to client
1601 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
1602 IP(src=server.ip4, dst=self.pg1.remote_ip4) /
1603 TCP(sport=local_port, dport=12345))
1604 self.pg0.add_stream(p)
1605 self.pg_enable_capture(self.pg_interfaces)
1606 self.pg_start()
1607 capture = self.pg1.get_capture(1)
1608 p = capture[0]
1609 try:
1610 ip = p[IP]
1611 tcp = p[TCP]
1612 self.assertEqual(ip.src, self.nat_addr)
1613 self.assertEqual(tcp.sport, external_port)
1614 self.assert_packet_checksums_valid(p)
1615 except:
1616 self.logger.error(ppp("Unexpected or invalid packet:", p))
1617 raise
1618
1619 # from client to server (no translation)
1620 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
1621 IP(src=self.pg1.remote_ip4, dst=server1.ip4) /
1622 TCP(sport=12346, dport=local_port))
1623 self.pg1.add_stream(p)
1624 self.pg_enable_capture(self.pg_interfaces)
1625 self.pg_start()
1626 capture = self.pg0.get_capture(1)
1627 p = capture[0]
1628 server = None
1629 try:
1630 ip = p[IP]
1631 tcp = p[TCP]
1632 self.assertEqual(ip.dst, server1.ip4)
1633 self.assertEqual(tcp.dport, local_port)
1634 self.assert_packet_checksums_valid(p)
1635 except:
1636 self.logger.error(ppp("Unexpected or invalid packet:", p))
1637 raise
1638
1639 # from service back to client (no translation)
1640 p = (Ether(src=server1.mac, dst=self.pg0.local_mac) /
1641 IP(src=server1.ip4, dst=self.pg1.remote_ip4) /
1642 TCP(sport=local_port, dport=12346))
1643 self.pg0.add_stream(p)
1644 self.pg_enable_capture(self.pg_interfaces)
1645 self.pg_start()
1646 capture = self.pg1.get_capture(1)
1647 p = capture[0]
1648 try:
1649 ip = p[IP]
1650 tcp = p[TCP]
1651 self.assertEqual(ip.src, server1.ip4)
1652 self.assertEqual(tcp.sport, local_port)
1653 self.assert_packet_checksums_valid(p)
1654 except:
1655 self.logger.error(ppp("Unexpected or invalid packet:", p))
1656 raise
1657
1658 def test_lb_affinity(self):
1659 """ NAT44ED local service load balancing affinity """
1660 external_addr = self.nat_addr
1661 external_port = 80
1662 local_port = 8080
1663 server1 = self.pg0.remote_hosts[0]
1664 server2 = self.pg0.remote_hosts[1]
1665
1666 locals = [{'addr': server1.ip4,
1667 'port': local_port,
1668 'probability': 50,
1669 'vrf_id': 0},
1670 {'addr': server2.ip4,
1671 'port': local_port,
1672 'probability': 50,
1673 'vrf_id': 0}]
1674
1675 self.nat_add_address(self.nat_addr)
1676 self.vapi.nat44_add_del_lb_static_mapping(is_add=1,
1677 external_addr=external_addr,
1678 external_port=external_port,
1679 protocol=IP_PROTOS.tcp,
1680 affinity=10800,
1681 local_num=len(locals),
1682 locals=locals)
1683 flags = self.config_flags.NAT_IS_INSIDE
1684 self.vapi.nat44_interface_add_del_feature(
1685 sw_if_index=self.pg0.sw_if_index,
1686 flags=flags, is_add=1)
1687 self.vapi.nat44_interface_add_del_feature(
1688 sw_if_index=self.pg1.sw_if_index,
1689 is_add=1)
1690
1691 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1692 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
1693 TCP(sport=1025, dport=external_port))
1694 self.pg1.add_stream(p)
1695 self.pg_enable_capture(self.pg_interfaces)
1696 self.pg_start()
1697 capture = self.pg0.get_capture(1)
1698 backend = capture[0][IP].dst
1699
1700 sessions = self.vapi.nat44_user_session_dump(backend, 0)
1701 self.assertEqual(len(sessions), 1)
1702 self.assertTrue(sessions[0].flags &
1703 self.config_flags.NAT_IS_EXT_HOST_VALID)
1704 self.vapi.nat44_del_session(
1705 address=sessions[0].inside_ip_address,
1706 port=sessions[0].inside_port,
1707 protocol=sessions[0].protocol,
1708 flags=(self.config_flags.NAT_IS_INSIDE |
1709 self.config_flags.NAT_IS_EXT_HOST_VALID),
1710 ext_host_address=sessions[0].ext_host_address,
1711 ext_host_port=sessions[0].ext_host_port)
1712
1713 pkts = []
1714 for port in range(1030, 1100):
1715 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1716 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
1717 TCP(sport=port, dport=external_port))
1718 pkts.append(p)
1719 self.pg1.add_stream(pkts)
1720 self.pg_enable_capture(self.pg_interfaces)
1721 self.pg_start()
1722 capture = self.pg0.get_capture(len(pkts))
1723 for p in capture:
1724 self.assertEqual(p[IP].dst, backend)
1725
Klement Sekeraa920af72021-05-17 13:17:56 +02001726 def test_multiple_vrf_1(self):
1727 """ Multiple VRF - both client & service in VRF1 """
Filip Varga18f1e412020-12-03 15:27:40 +01001728
1729 external_addr = '1.2.3.4'
1730 external_port = 80
1731 local_port = 8080
1732 port = 0
1733
Filip Varga18f1e412020-12-03 15:27:40 +01001734 flags = self.config_flags.NAT_IS_INSIDE
1735 self.vapi.nat44_interface_add_del_feature(
Filip Varga18f1e412020-12-03 15:27:40 +01001736 sw_if_index=self.pg5.sw_if_index,
1737 is_add=1)
1738 self.vapi.nat44_interface_add_del_feature(
1739 sw_if_index=self.pg5.sw_if_index,
1740 is_add=1, flags=flags)
1741 self.vapi.nat44_interface_add_del_feature(
1742 sw_if_index=self.pg6.sw_if_index,
1743 is_add=1)
1744 flags = self.config_flags.NAT_IS_OUT2IN_ONLY
1745 self.nat_add_static_mapping(self.pg5.remote_ip4, external_addr,
1746 local_port, external_port, vrf_id=1,
1747 proto=IP_PROTOS.tcp, flags=flags)
Filip Varga18f1e412020-12-03 15:27:40 +01001748
Filip Varga18f1e412020-12-03 15:27:40 +01001749 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
1750 IP(src=self.pg6.remote_ip4, dst=external_addr) /
1751 TCP(sport=12345, dport=external_port))
1752 self.pg6.add_stream(p)
1753 self.pg_enable_capture(self.pg_interfaces)
1754 self.pg_start()
1755 capture = self.pg5.get_capture(1)
1756 p = capture[0]
1757 try:
1758 ip = p[IP]
1759 tcp = p[TCP]
1760 self.assertEqual(ip.dst, self.pg5.remote_ip4)
1761 self.assertEqual(tcp.dport, local_port)
1762 self.assert_packet_checksums_valid(p)
1763 except:
1764 self.logger.error(ppp("Unexpected or invalid packet:", p))
1765 raise
1766
Filip Varga18f1e412020-12-03 15:27:40 +01001767 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
1768 IP(src=self.pg5.remote_ip4, dst=self.pg6.remote_ip4) /
1769 TCP(sport=local_port, dport=12345))
1770 self.pg5.add_stream(p)
1771 self.pg_enable_capture(self.pg_interfaces)
1772 self.pg_start()
1773 capture = self.pg6.get_capture(1)
1774 p = capture[0]
1775 try:
1776 ip = p[IP]
1777 tcp = p[TCP]
1778 self.assertEqual(ip.src, external_addr)
1779 self.assertEqual(tcp.sport, external_port)
1780 self.assert_packet_checksums_valid(p)
1781 except:
1782 self.logger.error(ppp("Unexpected or invalid packet:", p))
1783 raise
1784
Klement Sekeraa920af72021-05-17 13:17:56 +02001785 def test_multiple_vrf_2(self):
1786 """ Multiple VRF - dynamic NAT from VRF1 to VRF0 (output-feature) """
1787
1788 external_addr = '1.2.3.4'
1789 external_port = 80
1790 local_port = 8080
1791 port = 0
1792
1793 self.nat_add_address(self.nat_addr)
1794 flags = self.config_flags.NAT_IS_INSIDE
Filip Vargab6810822022-02-15 11:56:07 -08001795 self.vapi.nat44_ed_add_del_output_interface(
Klement Sekeraa920af72021-05-17 13:17:56 +02001796 sw_if_index=self.pg1.sw_if_index,
1797 is_add=1)
1798 self.vapi.nat44_interface_add_del_feature(
1799 sw_if_index=self.pg5.sw_if_index,
1800 is_add=1)
1801 self.vapi.nat44_interface_add_del_feature(
1802 sw_if_index=self.pg5.sw_if_index,
1803 is_add=1, flags=flags)
1804 flags = self.config_flags.NAT_IS_OUT2IN_ONLY
1805 self.nat_add_static_mapping(self.pg5.remote_ip4, external_addr,
1806 local_port, external_port, vrf_id=1,
1807 proto=IP_PROTOS.tcp, flags=flags)
1808
Filip Varga18f1e412020-12-03 15:27:40 +01001809 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
1810 IP(src=self.pg5.remote_ip4, dst=self.pg1.remote_ip4) /
1811 TCP(sport=2345, dport=22))
1812 self.pg5.add_stream(p)
1813 self.pg_enable_capture(self.pg_interfaces)
1814 self.pg_start()
1815 capture = self.pg1.get_capture(1)
1816 p = capture[0]
1817 try:
1818 ip = p[IP]
1819 tcp = p[TCP]
1820 self.assertEqual(ip.src, self.nat_addr)
1821 self.assert_packet_checksums_valid(p)
1822 port = tcp.sport
1823 except:
1824 self.logger.error(ppp("Unexpected or invalid packet:", p))
1825 raise
1826
1827 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
1828 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
1829 TCP(sport=22, dport=port))
1830 self.pg1.add_stream(p)
1831 self.pg_enable_capture(self.pg_interfaces)
1832 self.pg_start()
1833 capture = self.pg5.get_capture(1)
1834 p = capture[0]
1835 try:
1836 ip = p[IP]
1837 tcp = p[TCP]
1838 self.assertEqual(ip.dst, self.pg5.remote_ip4)
1839 self.assertEqual(tcp.dport, 2345)
1840 self.assert_packet_checksums_valid(p)
1841 except:
1842 self.logger.error(ppp("Unexpected or invalid packet:", p))
1843 raise
1844
Klement Sekeraa920af72021-05-17 13:17:56 +02001845 def test_multiple_vrf_3(self):
1846 """ Multiple VRF - client in VRF1, service in VRF0 """
1847
1848 external_addr = '1.2.3.4'
1849 external_port = 80
1850 local_port = 8080
1851 port = 0
1852
1853 flags = self.config_flags.NAT_IS_INSIDE
1854 self.vapi.nat44_interface_add_del_feature(
1855 sw_if_index=self.pg0.sw_if_index,
1856 is_add=1)
1857 self.vapi.nat44_interface_add_del_feature(
1858 sw_if_index=self.pg0.sw_if_index,
1859 is_add=1, flags=flags)
1860 self.vapi.nat44_interface_add_del_feature(
1861 sw_if_index=self.pg6.sw_if_index,
1862 is_add=1)
1863 flags = self.config_flags.NAT_IS_OUT2IN_ONLY
1864 self.nat_add_static_mapping(
1865 self.pg0.remote_ip4,
1866 external_sw_if_index=self.pg0.sw_if_index,
1867 local_port=local_port,
1868 vrf_id=0,
1869 external_port=external_port,
1870 proto=IP_PROTOS.tcp,
1871 flags=flags
1872 )
1873
Filip Varga18f1e412020-12-03 15:27:40 +01001874 # from client VRF1 to service VRF0
1875 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
1876 IP(src=self.pg6.remote_ip4, dst=self.pg0.local_ip4) /
1877 TCP(sport=12346, dport=external_port))
1878 self.pg6.add_stream(p)
1879 self.pg_enable_capture(self.pg_interfaces)
1880 self.pg_start()
1881 capture = self.pg0.get_capture(1)
1882 p = capture[0]
1883 try:
1884 ip = p[IP]
1885 tcp = p[TCP]
1886 self.assertEqual(ip.dst, self.pg0.remote_ip4)
1887 self.assertEqual(tcp.dport, local_port)
1888 self.assert_packet_checksums_valid(p)
1889 except:
1890 self.logger.error(ppp("Unexpected or invalid packet:", p))
1891 raise
1892
1893 # from service VRF0 back to client VRF1
1894 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
1895 IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
1896 TCP(sport=local_port, dport=12346))
1897 self.pg0.add_stream(p)
1898 self.pg_enable_capture(self.pg_interfaces)
1899 self.pg_start()
1900 capture = self.pg6.get_capture(1)
1901 p = capture[0]
1902 try:
1903 ip = p[IP]
1904 tcp = p[TCP]
1905 self.assertEqual(ip.src, self.pg0.local_ip4)
1906 self.assertEqual(tcp.sport, external_port)
1907 self.assert_packet_checksums_valid(p)
1908 except:
1909 self.logger.error(ppp("Unexpected or invalid packet:", p))
1910 raise
1911
Klement Sekeraa920af72021-05-17 13:17:56 +02001912 def test_multiple_vrf_4(self):
1913 """ Multiple VRF - client in VRF0, service in VRF1 """
1914
1915 external_addr = '1.2.3.4'
1916 external_port = 80
1917 local_port = 8080
1918 port = 0
1919
1920 flags = self.config_flags.NAT_IS_INSIDE
1921 self.vapi.nat44_interface_add_del_feature(
1922 sw_if_index=self.pg0.sw_if_index,
1923 is_add=1)
1924 self.vapi.nat44_interface_add_del_feature(
1925 sw_if_index=self.pg0.sw_if_index,
1926 is_add=1, flags=flags)
1927 self.vapi.nat44_interface_add_del_feature(
1928 sw_if_index=self.pg5.sw_if_index,
1929 is_add=1)
1930 self.vapi.nat44_interface_add_del_feature(
1931 sw_if_index=self.pg5.sw_if_index,
1932 is_add=1, flags=flags)
1933 flags = self.config_flags.NAT_IS_OUT2IN_ONLY
1934 self.nat_add_static_mapping(self.pg5.remote_ip4, external_addr,
1935 local_port, external_port, vrf_id=1,
1936 proto=IP_PROTOS.tcp, flags=flags)
1937
Filip Varga18f1e412020-12-03 15:27:40 +01001938 # from client VRF0 to service VRF1
1939 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
1940 IP(src=self.pg0.remote_ip4, dst=external_addr) /
1941 TCP(sport=12347, dport=external_port))
1942 self.pg0.add_stream(p)
1943 self.pg_enable_capture(self.pg_interfaces)
1944 self.pg_start()
1945 capture = self.pg5.get_capture(1)
1946 p = capture[0]
1947 try:
1948 ip = p[IP]
1949 tcp = p[TCP]
1950 self.assertEqual(ip.dst, self.pg5.remote_ip4)
1951 self.assertEqual(tcp.dport, local_port)
1952 self.assert_packet_checksums_valid(p)
1953 except:
1954 self.logger.error(ppp("Unexpected or invalid packet:", p))
1955 raise
1956
1957 # from service VRF1 back to client VRF0
1958 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
1959 IP(src=self.pg5.remote_ip4, dst=self.pg0.remote_ip4) /
1960 TCP(sport=local_port, dport=12347))
1961 self.pg5.add_stream(p)
1962 self.pg_enable_capture(self.pg_interfaces)
1963 self.pg_start()
1964 capture = self.pg0.get_capture(1)
1965 p = capture[0]
1966 try:
1967 ip = p[IP]
1968 tcp = p[TCP]
1969 self.assertEqual(ip.src, external_addr)
1970 self.assertEqual(tcp.sport, external_port)
1971 self.assert_packet_checksums_valid(p)
1972 except:
1973 self.logger.error(ppp("Unexpected or invalid packet:", p))
1974 raise
1975
Klement Sekeraa920af72021-05-17 13:17:56 +02001976 def test_multiple_vrf_5(self):
1977 """ Multiple VRF - forwarding - no translation """
1978
1979 external_addr = '1.2.3.4'
1980 external_port = 80
1981 local_port = 8080
1982 port = 0
1983
1984 self.vapi.nat44_forwarding_enable_disable(enable=1)
1985 flags = self.config_flags.NAT_IS_INSIDE
1986 self.vapi.nat44_interface_add_del_feature(
1987 sw_if_index=self.pg0.sw_if_index,
1988 is_add=1)
1989 self.vapi.nat44_interface_add_del_feature(
1990 sw_if_index=self.pg0.sw_if_index,
1991 is_add=1, flags=flags)
1992 self.vapi.nat44_interface_add_del_feature(
1993 sw_if_index=self.pg5.sw_if_index,
1994 is_add=1)
1995 self.vapi.nat44_interface_add_del_feature(
1996 sw_if_index=self.pg5.sw_if_index,
1997 is_add=1, flags=flags)
1998 self.vapi.nat44_interface_add_del_feature(
1999 sw_if_index=self.pg6.sw_if_index,
2000 is_add=1)
2001 flags = self.config_flags.NAT_IS_OUT2IN_ONLY
2002 self.nat_add_static_mapping(self.pg5.remote_ip4, external_addr,
2003 local_port, external_port, vrf_id=1,
2004 proto=IP_PROTOS.tcp, flags=flags)
2005 self.nat_add_static_mapping(
2006 self.pg0.remote_ip4,
2007 external_sw_if_index=self.pg0.sw_if_index,
2008 local_port=local_port,
2009 vrf_id=0,
2010 external_port=external_port,
2011 proto=IP_PROTOS.tcp,
2012 flags=flags
2013 )
2014
Filip Varga18f1e412020-12-03 15:27:40 +01002015 # from client to server (both VRF1, no translation)
2016 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
2017 IP(src=self.pg6.remote_ip4, dst=self.pg5.remote_ip4) /
2018 TCP(sport=12348, dport=local_port))
2019 self.pg6.add_stream(p)
2020 self.pg_enable_capture(self.pg_interfaces)
2021 self.pg_start()
2022 capture = self.pg5.get_capture(1)
2023 p = capture[0]
2024 try:
2025 ip = p[IP]
2026 tcp = p[TCP]
2027 self.assertEqual(ip.dst, self.pg5.remote_ip4)
2028 self.assertEqual(tcp.dport, local_port)
2029 self.assert_packet_checksums_valid(p)
2030 except:
2031 self.logger.error(ppp("Unexpected or invalid packet:", p))
2032 raise
2033
2034 # from server back to client (both VRF1, no translation)
2035 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
2036 IP(src=self.pg5.remote_ip4, dst=self.pg6.remote_ip4) /
2037 TCP(sport=local_port, dport=12348))
2038 self.pg5.add_stream(p)
2039 self.pg_enable_capture(self.pg_interfaces)
2040 self.pg_start()
2041 capture = self.pg6.get_capture(1)
2042 p = capture[0]
2043 try:
2044 ip = p[IP]
2045 tcp = p[TCP]
2046 self.assertEqual(ip.src, self.pg5.remote_ip4)
2047 self.assertEqual(tcp.sport, local_port)
2048 self.assert_packet_checksums_valid(p)
2049 except:
2050 self.logger.error(ppp("Unexpected or invalid packet:", p))
2051 raise
2052
2053 # from client VRF1 to server VRF0 (no translation)
2054 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
2055 IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
2056 TCP(sport=local_port, dport=12349))
2057 self.pg0.add_stream(p)
2058 self.pg_enable_capture(self.pg_interfaces)
2059 self.pg_start()
2060 capture = self.pg6.get_capture(1)
2061 p = capture[0]
2062 try:
2063 ip = p[IP]
2064 tcp = p[TCP]
2065 self.assertEqual(ip.src, self.pg0.remote_ip4)
2066 self.assertEqual(tcp.sport, local_port)
2067 self.assert_packet_checksums_valid(p)
2068 except:
2069 self.logger.error(ppp("Unexpected or invalid packet:", p))
2070 raise
2071
2072 # from server VRF0 back to client VRF1 (no translation)
2073 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
2074 IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
2075 TCP(sport=local_port, dport=12349))
2076 self.pg0.add_stream(p)
2077 self.pg_enable_capture(self.pg_interfaces)
2078 self.pg_start()
2079 capture = self.pg6.get_capture(1)
2080 p = capture[0]
2081 try:
2082 ip = p[IP]
2083 tcp = p[TCP]
2084 self.assertEqual(ip.src, self.pg0.remote_ip4)
2085 self.assertEqual(tcp.sport, local_port)
2086 self.assert_packet_checksums_valid(p)
2087 except:
2088 self.logger.error(ppp("Unexpected or invalid packet:", p))
2089 raise
2090
2091 # from client VRF0 to server VRF1 (no translation)
2092 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
2093 IP(src=self.pg0.remote_ip4, dst=self.pg5.remote_ip4) /
2094 TCP(sport=12344, dport=local_port))
2095 self.pg0.add_stream(p)
2096 self.pg_enable_capture(self.pg_interfaces)
2097 self.pg_start()
2098 capture = self.pg5.get_capture(1)
2099 p = capture[0]
2100 try:
2101 ip = p[IP]
2102 tcp = p[TCP]
2103 self.assertEqual(ip.dst, self.pg5.remote_ip4)
2104 self.assertEqual(tcp.dport, local_port)
2105 self.assert_packet_checksums_valid(p)
2106 except:
2107 self.logger.error(ppp("Unexpected or invalid packet:", p))
2108 raise
2109
2110 # from server VRF1 back to client VRF0 (no translation)
2111 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
2112 IP(src=self.pg5.remote_ip4, dst=self.pg0.remote_ip4) /
2113 TCP(sport=local_port, dport=12344))
2114 self.pg5.add_stream(p)
2115 self.pg_enable_capture(self.pg_interfaces)
2116 self.pg_start()
2117 capture = self.pg0.get_capture(1)
2118 p = capture[0]
2119 try:
2120 ip = p[IP]
2121 tcp = p[TCP]
2122 self.assertEqual(ip.src, self.pg5.remote_ip4)
2123 self.assertEqual(tcp.sport, local_port)
2124 self.assert_packet_checksums_valid(p)
2125 except:
2126 self.logger.error(ppp("Unexpected or invalid packet:", p))
2127 raise
2128
Klement Sekeradc243ee2021-02-25 16:47:23 +01002129 def test_outside_address_distribution(self):
2130 """ Outside address distribution based on source address """
2131
2132 x = 100
2133 nat_addresses = []
2134
2135 for i in range(1, x):
2136 a = "10.0.0.%d" % i
2137 nat_addresses.append(a)
2138
2139 self.nat_add_inside_interface(self.pg0)
2140 self.nat_add_outside_interface(self.pg1)
2141
2142 self.vapi.nat44_add_del_address_range(
2143 first_ip_address=nat_addresses[0],
2144 last_ip_address=nat_addresses[-1],
2145 vrf_id=0xFFFFFFFF, is_add=1, flags=0)
2146
2147 self.pg0.generate_remote_hosts(x)
2148
2149 pkts = []
2150 for i in range(x):
Klement Sekerad2b69972021-03-09 17:53:47 +01002151 info = self.create_packet_info(self.pg0, self.pg1)
2152 payload = self.info_to_payload(info)
Klement Sekeradc243ee2021-02-25 16:47:23 +01002153 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2154 IP(src=self.pg0.remote_hosts[i].ip4,
2155 dst=self.pg1.remote_ip4) /
Klement Sekerad2b69972021-03-09 17:53:47 +01002156 UDP(sport=7000+i, dport=8000+i) /
2157 Raw(payload))
2158 info.data = p
Klement Sekeradc243ee2021-02-25 16:47:23 +01002159 pkts.append(p)
2160
2161 self.pg0.add_stream(pkts)
2162 self.pg_enable_capture(self.pg_interfaces)
2163 self.pg_start()
2164 recvd = self.pg1.get_capture(len(pkts))
Klement Sekerad2b69972021-03-09 17:53:47 +01002165 for p_recvd in recvd:
2166 payload_info = self.payload_to_info(p_recvd[Raw])
2167 packet_index = payload_info.index
2168 info = self._packet_infos[packet_index]
2169 self.assertTrue(info is not None)
2170 self.assertEqual(packet_index, info.index)
2171 p_sent = info.data
Klement Sekeradc243ee2021-02-25 16:47:23 +01002172 packed = socket.inet_aton(p_sent[IP].src)
2173 numeric = struct.unpack("!L", packed)[0]
2174 numeric = socket.htonl(numeric)
2175 a = nat_addresses[(numeric-1) % len(nat_addresses)]
Klement Sekerad2b69972021-03-09 17:53:47 +01002176 self.assertEqual(
2177 a, p_recvd[IP].src,
2178 "Invalid packet (src IP %s translated to %s, but expected %s)"
2179 % (p_sent[IP].src, p_recvd[IP].src, a))
Klement Sekeradc243ee2021-02-25 16:47:23 +01002180
Filip Varga18f1e412020-12-03 15:27:40 +01002181
2182class TestNAT44EDMW(TestNAT44ED):
2183 """ NAT44ED MW Test Case """
Klement Sekera1fbf0342021-03-31 13:38:09 +02002184 vpp_worker_count = 4
2185 max_sessions = 5000
Filip Varga18f1e412020-12-03 15:27:40 +01002186
Filip Varga18f1e412020-12-03 15:27:40 +01002187 def test_dynamic(self):
2188 """ NAT44ED dynamic translation test """
Klement Sekera1fbf0342021-03-31 13:38:09 +02002189 pkt_count = 1500
2190 tcp_port_offset = 20
2191 udp_port_offset = 20
2192 icmp_id_offset = 20
Filip Varga18f1e412020-12-03 15:27:40 +01002193
2194 self.nat_add_address(self.nat_addr)
2195 self.nat_add_inside_interface(self.pg0)
2196 self.nat_add_outside_interface(self.pg1)
2197
2198 # in2out
Klement Sekera3887be72021-03-30 20:29:05 +02002199 tc1 = self.statistics['/nat44-ed/in2out/slowpath/tcp']
2200 uc1 = self.statistics['/nat44-ed/in2out/slowpath/udp']
2201 ic1 = self.statistics['/nat44-ed/in2out/slowpath/icmp']
2202 dc1 = self.statistics['/nat44-ed/in2out/slowpath/drops']
Filip Varga18f1e412020-12-03 15:27:40 +01002203
Klement Sekera1fbf0342021-03-31 13:38:09 +02002204 i2o_pkts = [[] for x in range(0, self.vpp_worker_count)]
2205
2206 for i in range(pkt_count):
2207 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2208 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2209 TCP(sport=tcp_port_offset + i, dport=20))
2210 i2o_pkts[p[TCP].sport % self.vpp_worker_count].append(p)
2211
2212 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2213 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2214 UDP(sport=udp_port_offset + i, dport=20))
2215 i2o_pkts[p[UDP].sport % self.vpp_worker_count].append(p)
2216
2217 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2218 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2219 ICMP(id=icmp_id_offset + i, type='echo-request'))
2220 i2o_pkts[p[ICMP].id % self.vpp_worker_count].append(p)
2221
2222 for i in range(0, self.vpp_worker_count):
2223 if len(i2o_pkts[i]) > 0:
2224 self.pg0.add_stream(i2o_pkts[i], worker=i)
2225
Filip Varga18f1e412020-12-03 15:27:40 +01002226 self.pg_enable_capture(self.pg_interfaces)
2227 self.pg_start()
Klement Sekeraff334db2021-05-26 13:02:35 +02002228 capture = self.pg1.get_capture(pkt_count * 3, timeout=5)
Filip Varga18f1e412020-12-03 15:27:40 +01002229
2230 if_idx = self.pg0.sw_if_index
Klement Sekera3887be72021-03-30 20:29:05 +02002231 tc2 = self.statistics['/nat44-ed/in2out/slowpath/tcp']
2232 uc2 = self.statistics['/nat44-ed/in2out/slowpath/udp']
2233 ic2 = self.statistics['/nat44-ed/in2out/slowpath/icmp']
2234 dc2 = self.statistics['/nat44-ed/in2out/slowpath/drops']
Filip Varga18f1e412020-12-03 15:27:40 +01002235
Klement Sekera1fbf0342021-03-31 13:38:09 +02002236 self.assertEqual(
2237 tc2[:, if_idx].sum() - tc1[:, if_idx].sum(), pkt_count)
2238 self.assertEqual(
2239 uc2[:, if_idx].sum() - uc1[:, if_idx].sum(), pkt_count)
2240 self.assertEqual(
2241 ic2[:, if_idx].sum() - ic1[:, if_idx].sum(), pkt_count)
Klement Sekera3887be72021-03-30 20:29:05 +02002242 self.assertEqual(dc2[:, if_idx].sum() - dc1[:, if_idx].sum(), 0)
Filip Varga18f1e412020-12-03 15:27:40 +01002243
Klement Sekera1fbf0342021-03-31 13:38:09 +02002244 self.logger.info(self.vapi.cli("show trace"))
2245
Filip Varga18f1e412020-12-03 15:27:40 +01002246 # out2in
Klement Sekera3887be72021-03-30 20:29:05 +02002247 tc1 = self.statistics['/nat44-ed/out2in/fastpath/tcp']
2248 uc1 = self.statistics['/nat44-ed/out2in/fastpath/udp']
2249 ic1 = self.statistics['/nat44-ed/out2in/fastpath/icmp']
2250 dc1 = self.statistics['/nat44-ed/out2in/fastpath/drops']
Filip Varga18f1e412020-12-03 15:27:40 +01002251
Klement Sekera1fbf0342021-03-31 13:38:09 +02002252 recvd_tcp_ports = set()
2253 recvd_udp_ports = set()
2254 recvd_icmp_ids = set()
2255
2256 for p in capture:
2257 if TCP in p:
2258 recvd_tcp_ports.add(p[TCP].sport)
2259 if UDP in p:
2260 recvd_udp_ports.add(p[UDP].sport)
2261 if ICMP in p:
2262 recvd_icmp_ids.add(p[ICMP].id)
2263
2264 recvd_tcp_ports = list(recvd_tcp_ports)
2265 recvd_udp_ports = list(recvd_udp_ports)
2266 recvd_icmp_ids = list(recvd_icmp_ids)
2267
2268 o2i_pkts = [[] for x in range(0, self.vpp_worker_count)]
2269 for i in range(pkt_count):
2270 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
2271 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
2272 TCP(dport=choice(recvd_tcp_ports), sport=20))
2273 o2i_pkts[p[TCP].dport % self.vpp_worker_count].append(p)
2274
2275 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
2276 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
2277 UDP(dport=choice(recvd_udp_ports), sport=20))
2278 o2i_pkts[p[UDP].dport % self.vpp_worker_count].append(p)
2279
2280 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
2281 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
2282 ICMP(id=choice(recvd_icmp_ids), type='echo-reply'))
2283 o2i_pkts[p[ICMP].id % self.vpp_worker_count].append(p)
2284
2285 for i in range(0, self.vpp_worker_count):
2286 if len(o2i_pkts[i]) > 0:
2287 self.pg1.add_stream(o2i_pkts[i], worker=i)
2288
Filip Varga18f1e412020-12-03 15:27:40 +01002289 self.pg_enable_capture(self.pg_interfaces)
2290 self.pg_start()
Klement Sekera1fbf0342021-03-31 13:38:09 +02002291 capture = self.pg0.get_capture(pkt_count * 3)
2292 for packet in capture:
2293 try:
2294 self.assert_packet_checksums_valid(packet)
2295 self.assertEqual(packet[IP].dst, self.pg0.remote_ip4)
2296 if packet.haslayer(TCP):
2297 self.assert_in_range(
2298 packet[TCP].dport, tcp_port_offset,
2299 tcp_port_offset + pkt_count, "dst TCP port")
2300 elif packet.haslayer(UDP):
2301 self.assert_in_range(
2302 packet[UDP].dport, udp_port_offset,
2303 udp_port_offset + pkt_count, "dst UDP port")
2304 else:
2305 self.assert_in_range(
2306 packet[ICMP].id, icmp_id_offset,
2307 icmp_id_offset + pkt_count, "ICMP id")
2308 except:
2309 self.logger.error(ppp("Unexpected or invalid packet "
2310 "(inside network):", packet))
2311 raise
Filip Varga18f1e412020-12-03 15:27:40 +01002312
2313 if_idx = self.pg1.sw_if_index
Klement Sekera3887be72021-03-30 20:29:05 +02002314 tc2 = self.statistics['/nat44-ed/out2in/fastpath/tcp']
2315 uc2 = self.statistics['/nat44-ed/out2in/fastpath/udp']
2316 ic2 = self.statistics['/nat44-ed/out2in/fastpath/icmp']
2317 dc2 = self.statistics['/nat44-ed/out2in/fastpath/drops']
Filip Varga18f1e412020-12-03 15:27:40 +01002318
Klement Sekera1fbf0342021-03-31 13:38:09 +02002319 self.assertEqual(
2320 tc2[:, if_idx].sum() - tc1[:, if_idx].sum(), pkt_count)
2321 self.assertEqual(
2322 uc2[:, if_idx].sum() - uc1[:, if_idx].sum(), pkt_count)
2323 self.assertEqual(
2324 ic2[:, if_idx].sum() - ic1[:, if_idx].sum(), pkt_count)
Klement Sekera3887be72021-03-30 20:29:05 +02002325 self.assertEqual(dc2[:, if_idx].sum() - dc1[:, if_idx].sum(), 0)
Filip Varga18f1e412020-12-03 15:27:40 +01002326
Klement Sekera3887be72021-03-30 20:29:05 +02002327 sc = self.statistics['/nat44-ed/total-sessions']
Klement Sekera1fbf0342021-03-31 13:38:09 +02002328 self.assertEqual(sc[:, 0].sum(), len(recvd_tcp_ports) +
2329 len(recvd_udp_ports) + len(recvd_icmp_ids))
Filip Varga18f1e412020-12-03 15:27:40 +01002330
2331 def test_frag_in_order(self):
2332 """ NAT44ED translate fragments arriving in order """
2333
2334 self.nat_add_address(self.nat_addr)
2335 self.nat_add_inside_interface(self.pg0)
2336 self.nat_add_outside_interface(self.pg1)
2337
2338 self.frag_in_order(proto=IP_PROTOS.tcp, ignore_port=True)
2339 self.frag_in_order(proto=IP_PROTOS.udp, ignore_port=True)
2340 self.frag_in_order(proto=IP_PROTOS.icmp, ignore_port=True)
2341
2342 def test_frag_in_order_do_not_translate(self):
2343 """ NAT44ED don't translate fragments arriving in order """
2344
2345 self.nat_add_address(self.nat_addr)
2346 self.nat_add_inside_interface(self.pg0)
2347 self.nat_add_outside_interface(self.pg1)
2348 self.vapi.nat44_forwarding_enable_disable(enable=True)
2349
2350 self.frag_in_order(proto=IP_PROTOS.tcp, dont_translate=True)
2351
2352 def test_frag_out_of_order(self):
2353 """ NAT44ED translate fragments arriving out of order """
2354
2355 self.nat_add_address(self.nat_addr)
2356 self.nat_add_inside_interface(self.pg0)
2357 self.nat_add_outside_interface(self.pg1)
2358
2359 self.frag_out_of_order(proto=IP_PROTOS.tcp, ignore_port=True)
2360 self.frag_out_of_order(proto=IP_PROTOS.udp, ignore_port=True)
2361 self.frag_out_of_order(proto=IP_PROTOS.icmp, ignore_port=True)
2362
2363 def test_frag_in_order_in_plus_out(self):
2364 """ NAT44ED in+out interface fragments in order """
2365
2366 in_port = self.random_port()
2367 out_port = self.random_port()
2368
2369 self.nat_add_address(self.nat_addr)
2370 self.nat_add_inside_interface(self.pg0)
2371 self.nat_add_outside_interface(self.pg0)
2372 self.nat_add_inside_interface(self.pg1)
2373 self.nat_add_outside_interface(self.pg1)
2374
2375 # add static mappings for server
2376 self.nat_add_static_mapping(self.server_addr,
2377 self.nat_addr,
2378 in_port,
2379 out_port,
2380 proto=IP_PROTOS.tcp)
2381 self.nat_add_static_mapping(self.server_addr,
2382 self.nat_addr,
2383 in_port,
2384 out_port,
2385 proto=IP_PROTOS.udp)
2386 self.nat_add_static_mapping(self.server_addr,
2387 self.nat_addr,
2388 proto=IP_PROTOS.icmp)
2389
2390 # run tests for each protocol
2391 self.frag_in_order_in_plus_out(self.server_addr,
2392 self.nat_addr,
2393 in_port,
2394 out_port,
2395 IP_PROTOS.tcp)
2396 self.frag_in_order_in_plus_out(self.server_addr,
2397 self.nat_addr,
2398 in_port,
2399 out_port,
2400 IP_PROTOS.udp)
2401 self.frag_in_order_in_plus_out(self.server_addr,
2402 self.nat_addr,
2403 in_port,
2404 out_port,
2405 IP_PROTOS.icmp)
2406
2407 def test_frag_out_of_order_in_plus_out(self):
2408 """ NAT44ED in+out interface fragments out of order """
2409
2410 in_port = self.random_port()
2411 out_port = self.random_port()
2412
2413 self.nat_add_address(self.nat_addr)
2414 self.nat_add_inside_interface(self.pg0)
2415 self.nat_add_outside_interface(self.pg0)
2416 self.nat_add_inside_interface(self.pg1)
2417 self.nat_add_outside_interface(self.pg1)
2418
2419 # add static mappings for server
2420 self.nat_add_static_mapping(self.server_addr,
2421 self.nat_addr,
2422 in_port,
2423 out_port,
2424 proto=IP_PROTOS.tcp)
2425 self.nat_add_static_mapping(self.server_addr,
2426 self.nat_addr,
2427 in_port,
2428 out_port,
2429 proto=IP_PROTOS.udp)
2430 self.nat_add_static_mapping(self.server_addr,
2431 self.nat_addr,
2432 proto=IP_PROTOS.icmp)
2433
2434 # run tests for each protocol
2435 self.frag_out_of_order_in_plus_out(self.server_addr,
2436 self.nat_addr,
2437 in_port,
2438 out_port,
2439 IP_PROTOS.tcp)
2440 self.frag_out_of_order_in_plus_out(self.server_addr,
2441 self.nat_addr,
2442 in_port,
2443 out_port,
2444 IP_PROTOS.udp)
2445 self.frag_out_of_order_in_plus_out(self.server_addr,
2446 self.nat_addr,
2447 in_port,
2448 out_port,
2449 IP_PROTOS.icmp)
2450
2451 def test_reass_hairpinning(self):
2452 """ NAT44ED fragments hairpinning """
2453
2454 server_addr = self.pg0.remote_hosts[1].ip4
2455
2456 host_in_port = self.random_port()
2457 server_in_port = self.random_port()
2458 server_out_port = self.random_port()
2459
2460 self.nat_add_address(self.nat_addr)
2461 self.nat_add_inside_interface(self.pg0)
2462 self.nat_add_outside_interface(self.pg1)
2463
2464 # add static mapping for server
2465 self.nat_add_static_mapping(server_addr, self.nat_addr,
2466 server_in_port, server_out_port,
2467 proto=IP_PROTOS.tcp)
2468 self.nat_add_static_mapping(server_addr, self.nat_addr,
2469 server_in_port, server_out_port,
2470 proto=IP_PROTOS.udp)
2471 self.nat_add_static_mapping(server_addr, self.nat_addr)
2472
2473 self.reass_hairpinning(server_addr, server_in_port, server_out_port,
2474 host_in_port, proto=IP_PROTOS.tcp,
2475 ignore_port=True)
2476 self.reass_hairpinning(server_addr, server_in_port, server_out_port,
2477 host_in_port, proto=IP_PROTOS.udp,
2478 ignore_port=True)
2479 self.reass_hairpinning(server_addr, server_in_port, server_out_port,
2480 host_in_port, proto=IP_PROTOS.icmp,
2481 ignore_port=True)
2482
2483 def test_session_limit_per_vrf(self):
2484 """ NAT44ED per vrf session limit """
2485
2486 inside = self.pg0
2487 inside_vrf10 = self.pg2
2488 outside = self.pg1
2489
2490 limit = 5
2491
2492 # 2 interfaces pg0, pg1 (vrf10, limit 1 tcp session)
2493 # non existing vrf_id makes process core dump
2494 self.vapi.nat44_set_session_limit(session_limit=limit, vrf_id=10)
2495
2496 self.nat_add_inside_interface(inside)
2497 self.nat_add_inside_interface(inside_vrf10)
2498 self.nat_add_outside_interface(outside)
2499
2500 # vrf independent
2501 self.nat_add_interface_address(outside)
2502
2503 # BUG: causing core dump - when bad vrf_id is specified
2504 # self.nat_add_address(outside.local_ip4, vrf_id=20)
2505
2506 stream = self.create_tcp_stream(inside_vrf10, outside, limit * 2)
2507 inside_vrf10.add_stream(stream)
2508
2509 self.pg_enable_capture(self.pg_interfaces)
2510 self.pg_start()
2511
2512 capture = outside.get_capture(limit)
2513
2514 stream = self.create_tcp_stream(inside, outside, limit * 2)
2515 inside.add_stream(stream)
2516
2517 self.pg_enable_capture(self.pg_interfaces)
2518 self.pg_start()
2519
2520 capture = outside.get_capture(len(stream))
2521
Filip Varga18f1e412020-12-03 15:27:40 +01002522 def test_show_max_translations(self):
2523 """ NAT44ED API test - max translations per thread """
Filip Vargab6810822022-02-15 11:56:07 -08002524 config = self.vapi.nat44_show_running_config()
Filip Varga18f1e412020-12-03 15:27:40 +01002525 self.assertEqual(self.max_sessions,
Filip Vargab6810822022-02-15 11:56:07 -08002526 config.sessions)
Filip Varga18f1e412020-12-03 15:27:40 +01002527
2528 def test_lru_cleanup(self):
2529 """ NAT44ED LRU cleanup algorithm """
2530
2531 self.nat_add_address(self.nat_addr)
2532 self.nat_add_inside_interface(self.pg0)
2533 self.nat_add_outside_interface(self.pg1)
2534
2535 self.vapi.nat_set_timeouts(
2536 udp=1, tcp_established=7440, tcp_transitory=30, icmp=1)
2537
2538 tcp_port_out = self.init_tcp_session(self.pg0, self.pg1, 2000, 80)
2539 pkts = []
2540 for i in range(0, self.max_sessions - 1):
2541 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2542 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4, ttl=64) /
2543 UDP(sport=7000+i, dport=80))
2544 pkts.append(p)
2545
2546 self.pg0.add_stream(pkts)
2547 self.pg_enable_capture(self.pg_interfaces)
2548 self.pg_start()
2549 self.pg1.get_capture(len(pkts))
Benoît Ganne56eccdb2021-08-20 09:18:31 +02002550 self.virtual_sleep(1.5, "wait for timeouts")
Filip Varga18f1e412020-12-03 15:27:40 +01002551
2552 pkts = []
2553 for i in range(0, self.max_sessions - 1):
2554 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2555 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4, ttl=64) /
2556 ICMP(id=8000+i, type='echo-request'))
2557 pkts.append(p)
2558
2559 self.pg0.add_stream(pkts)
2560 self.pg_enable_capture(self.pg_interfaces)
2561 self.pg_start()
2562 self.pg1.get_capture(len(pkts))
2563
2564 def test_session_rst_timeout(self):
2565 """ NAT44ED session RST timeouts """
2566
2567 self.nat_add_address(self.nat_addr)
2568 self.nat_add_inside_interface(self.pg0)
2569 self.nat_add_outside_interface(self.pg1)
2570
2571 self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
2572 tcp_transitory=5, icmp=60)
2573
2574 self.init_tcp_session(self.pg0, self.pg1, self.tcp_port_in,
2575 self.tcp_external_port)
2576 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
2577 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2578 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
2579 flags="R"))
Klement Sekera56c492a2022-01-10 21:57:27 +00002580 self.send_and_expect(self.pg0, p, self.pg1)
Filip Varga18f1e412020-12-03 15:27:40 +01002581
Benoît Ganne56eccdb2021-08-20 09:18:31 +02002582 self.virtual_sleep(6)
Filip Varga18f1e412020-12-03 15:27:40 +01002583
Klement Sekera56c492a2022-01-10 21:57:27 +00002584 # The session is already closed
2585 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
2586 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2587 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
2588 flags="P"))
2589 self.send_and_assert_no_replies(self.pg0, p, self.pg1)
2590
2591 # The session can be re-opened
2592 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
2593 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2594 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
2595 flags="S"))
2596 self.send_and_expect(self.pg0, p, self.pg1)
2597
2598 def test_session_rst_established_timeout(self):
2599 """ NAT44ED session RST timeouts """
2600
2601 self.nat_add_address(self.nat_addr)
2602 self.nat_add_inside_interface(self.pg0)
2603 self.nat_add_outside_interface(self.pg1)
2604
2605 self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
2606 tcp_transitory=5, icmp=60)
2607
2608 self.init_tcp_session(self.pg0, self.pg1, self.tcp_port_in,
2609 self.tcp_external_port)
2610
2611 # Wait at least the transitory time, the session is in established
Ole Troan52974472022-03-17 11:58:38 +01002612 # state anyway. RST followed by a data packet should move it to
2613 # transitory state.
Klement Sekera56c492a2022-01-10 21:57:27 +00002614 self.virtual_sleep(6)
2615 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
2616 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2617 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
2618 flags="R"))
2619 self.send_and_expect(self.pg0, p, self.pg1)
2620
2621 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
2622 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2623 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
2624 flags="P"))
2625 self.send_and_expect(self.pg0, p, self.pg1)
2626
Klement Sekera56c492a2022-01-10 21:57:27 +00002627 # State is transitory, session should be closed after 6 seconds
2628 self.virtual_sleep(6)
2629
2630 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
2631 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2632 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
2633 flags="P"))
2634 self.send_and_assert_no_replies(self.pg0, p, self.pg1)
Filip Varga18f1e412020-12-03 15:27:40 +01002635
2636 def test_dynamic_out_of_ports(self):
2637 """ NAT44ED dynamic translation test: out of ports """
2638
2639 self.nat_add_inside_interface(self.pg0)
2640 self.nat_add_outside_interface(self.pg1)
2641
2642 # in2out and no NAT addresses added
Filip Varga18f1e412020-12-03 15:27:40 +01002643 pkts = self.create_stream_in(self.pg0, self.pg1)
Filip Varga18f1e412020-12-03 15:27:40 +01002644
Klement Sekeraad3187f2022-02-18 10:34:35 +00002645 self.send_and_assert_no_replies(
2646 self.pg0, pkts, msg="i2o pkts",
2647 stats_diff=self.no_diff | {
2648 "err": {
2649 '/err/nat44-ed-in2out-slowpath/out of ports': len(pkts),
2650 },
2651 self.pg0.sw_if_index: {
2652 '/nat44-ed/in2out/slowpath/drops': len(pkts),
2653 },
2654 }
2655 )
Filip Varga18f1e412020-12-03 15:27:40 +01002656
2657 # in2out after NAT addresses added
2658 self.nat_add_address(self.nat_addr)
2659
Klement Sekeraad3187f2022-02-18 10:34:35 +00002660 tcpn, udpn, icmpn = (sum(x) for x in
2661 zip(*((TCP in p, UDP in p, ICMP in p)
2662 for p in pkts)))
Filip Varga18f1e412020-12-03 15:27:40 +01002663
Klement Sekeraad3187f2022-02-18 10:34:35 +00002664 self.send_and_expect(
2665 self.pg0, pkts, self.pg1, msg="i2o pkts",
2666 stats_diff=self.no_diff | {
2667 "err": {
2668 '/err/nat44-ed-in2out-slowpath/out of ports': 0,
2669 },
2670 self.pg0.sw_if_index: {
2671 '/nat44-ed/in2out/slowpath/drops': 0,
2672 '/nat44-ed/in2out/slowpath/tcp': tcpn,
2673 '/nat44-ed/in2out/slowpath/udp': udpn,
2674 '/nat44-ed/in2out/slowpath/icmp': icmpn,
2675 },
2676 }
2677 )
Filip Varga18f1e412020-12-03 15:27:40 +01002678
2679 def test_unknown_proto(self):
2680 """ NAT44ED translate packet with unknown protocol """
2681
2682 self.nat_add_address(self.nat_addr)
2683 self.nat_add_inside_interface(self.pg0)
2684 self.nat_add_outside_interface(self.pg1)
2685
2686 # in2out
2687 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2688 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2689 TCP(sport=self.tcp_port_in, dport=20))
2690 self.pg0.add_stream(p)
2691 self.pg_enable_capture(self.pg_interfaces)
2692 self.pg_start()
2693 p = self.pg1.get_capture(1)
2694
2695 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2696 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2697 GRE() /
2698 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
2699 TCP(sport=1234, dport=1234))
2700 self.pg0.add_stream(p)
2701 self.pg_enable_capture(self.pg_interfaces)
2702 self.pg_start()
2703 p = self.pg1.get_capture(1)
2704 packet = p[0]
2705 try:
2706 self.assertEqual(packet[IP].src, self.nat_addr)
2707 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
2708 self.assertEqual(packet.haslayer(GRE), 1)
2709 self.assert_packet_checksums_valid(packet)
2710 except:
2711 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2712 raise
2713
2714 # out2in
2715 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
2716 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
2717 GRE() /
2718 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
2719 TCP(sport=1234, dport=1234))
2720 self.pg1.add_stream(p)
2721 self.pg_enable_capture(self.pg_interfaces)
2722 self.pg_start()
2723 p = self.pg0.get_capture(1)
2724 packet = p[0]
2725 try:
2726 self.assertEqual(packet[IP].src, self.pg1.remote_ip4)
2727 self.assertEqual(packet[IP].dst, self.pg0.remote_ip4)
2728 self.assertEqual(packet.haslayer(GRE), 1)
2729 self.assert_packet_checksums_valid(packet)
2730 except:
2731 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2732 raise
2733
2734 def test_hairpinning_unknown_proto(self):
2735 """ NAT44ED translate packet with unknown protocol - hairpinning """
2736 host = self.pg0.remote_hosts[0]
2737 server = self.pg0.remote_hosts[1]
2738 host_in_port = 1234
2739 server_out_port = 8765
2740 server_nat_ip = "10.0.0.11"
2741
2742 self.nat_add_address(self.nat_addr)
2743 self.nat_add_inside_interface(self.pg0)
2744 self.nat_add_outside_interface(self.pg1)
2745
2746 # add static mapping for server
2747 self.nat_add_static_mapping(server.ip4, server_nat_ip)
2748
2749 # host to server
2750 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
2751 IP(src=host.ip4, dst=server_nat_ip) /
2752 TCP(sport=host_in_port, dport=server_out_port))
2753 self.pg0.add_stream(p)
2754 self.pg_enable_capture(self.pg_interfaces)
2755 self.pg_start()
2756 self.pg0.get_capture(1)
2757
2758 p = (Ether(dst=self.pg0.local_mac, src=host.mac) /
2759 IP(src=host.ip4, dst=server_nat_ip) /
2760 GRE() /
2761 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
2762 TCP(sport=1234, dport=1234))
2763 self.pg0.add_stream(p)
2764 self.pg_enable_capture(self.pg_interfaces)
2765 self.pg_start()
2766 p = self.pg0.get_capture(1)
2767 packet = p[0]
2768 try:
2769 self.assertEqual(packet[IP].src, self.nat_addr)
2770 self.assertEqual(packet[IP].dst, server.ip4)
2771 self.assertEqual(packet.haslayer(GRE), 1)
2772 self.assert_packet_checksums_valid(packet)
2773 except:
2774 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2775 raise
2776
2777 # server to host
2778 p = (Ether(dst=self.pg0.local_mac, src=server.mac) /
2779 IP(src=server.ip4, dst=self.nat_addr) /
2780 GRE() /
2781 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
2782 TCP(sport=1234, dport=1234))
2783 self.pg0.add_stream(p)
2784 self.pg_enable_capture(self.pg_interfaces)
2785 self.pg_start()
2786 p = self.pg0.get_capture(1)
2787 packet = p[0]
2788 try:
2789 self.assertEqual(packet[IP].src, server_nat_ip)
2790 self.assertEqual(packet[IP].dst, host.ip4)
2791 self.assertEqual(packet.haslayer(GRE), 1)
2792 self.assert_packet_checksums_valid(packet)
2793 except:
2794 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2795 raise
2796
2797 def test_output_feature_and_service(self):
2798 """ NAT44ED interface output feature and services """
2799 external_addr = '1.2.3.4'
2800 external_port = 80
2801 local_port = 8080
2802
2803 self.vapi.nat44_forwarding_enable_disable(enable=1)
2804 self.nat_add_address(self.nat_addr)
2805 flags = self.config_flags.NAT_IS_ADDR_ONLY
2806 self.vapi.nat44_add_del_identity_mapping(
2807 ip_address=self.pg1.remote_ip4, sw_if_index=0xFFFFFFFF,
2808 flags=flags, is_add=1)
2809 flags = self.config_flags.NAT_IS_OUT2IN_ONLY
2810 self.nat_add_static_mapping(self.pg0.remote_ip4, external_addr,
2811 local_port, external_port,
2812 proto=IP_PROTOS.tcp, flags=flags)
2813
2814 self.nat_add_inside_interface(self.pg0)
2815 self.nat_add_outside_interface(self.pg0)
Filip Varga9c25eb12021-10-21 13:00:27 +02002816 self.vapi.nat44_ed_add_del_output_interface(
Filip Varga18f1e412020-12-03 15:27:40 +01002817 sw_if_index=self.pg1.sw_if_index, is_add=1)
2818
2819 # from client to service
2820 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
2821 IP(src=self.pg1.remote_ip4, dst=external_addr) /
2822 TCP(sport=12345, dport=external_port))
2823 self.pg1.add_stream(p)
2824 self.pg_enable_capture(self.pg_interfaces)
2825 self.pg_start()
2826 capture = self.pg0.get_capture(1)
2827 p = capture[0]
2828 try:
2829 ip = p[IP]
2830 tcp = p[TCP]
2831 self.assertEqual(ip.dst, self.pg0.remote_ip4)
2832 self.assertEqual(tcp.dport, local_port)
2833 self.assert_packet_checksums_valid(p)
2834 except:
2835 self.logger.error(ppp("Unexpected or invalid packet:", p))
2836 raise
2837
2838 # from service back to client
2839 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
2840 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2841 TCP(sport=local_port, dport=12345))
2842 self.pg0.add_stream(p)
2843 self.pg_enable_capture(self.pg_interfaces)
2844 self.pg_start()
2845 capture = self.pg1.get_capture(1)
2846 p = capture[0]
2847 try:
2848 ip = p[IP]
2849 tcp = p[TCP]
2850 self.assertEqual(ip.src, external_addr)
2851 self.assertEqual(tcp.sport, external_port)
2852 self.assert_packet_checksums_valid(p)
2853 except:
2854 self.logger.error(ppp("Unexpected or invalid packet:", p))
2855 raise
2856
2857 # from local network host to external network
2858 pkts = self.create_stream_in(self.pg0, self.pg1)
2859 self.pg0.add_stream(pkts)
2860 self.pg_enable_capture(self.pg_interfaces)
2861 self.pg_start()
2862 capture = self.pg1.get_capture(len(pkts))
2863 self.verify_capture_out(capture, ignore_port=True)
2864 pkts = self.create_stream_in(self.pg0, self.pg1)
2865 self.pg0.add_stream(pkts)
2866 self.pg_enable_capture(self.pg_interfaces)
2867 self.pg_start()
2868 capture = self.pg1.get_capture(len(pkts))
2869 self.verify_capture_out(capture, ignore_port=True)
2870
2871 # from external network back to local network host
2872 pkts = self.create_stream_out(self.pg1)
2873 self.pg1.add_stream(pkts)
2874 self.pg_enable_capture(self.pg_interfaces)
2875 self.pg_start()
2876 capture = self.pg0.get_capture(len(pkts))
2877 self.verify_capture_in(capture, self.pg0)
2878
2879 def test_output_feature_and_service3(self):
2880 """ NAT44ED interface output feature and DST NAT """
2881 external_addr = '1.2.3.4'
2882 external_port = 80
2883 local_port = 8080
2884
2885 self.vapi.nat44_forwarding_enable_disable(enable=1)
2886 self.nat_add_address(self.nat_addr)
2887 flags = self.config_flags.NAT_IS_OUT2IN_ONLY
2888 self.nat_add_static_mapping(self.pg1.remote_ip4, external_addr,
2889 local_port, external_port,
2890 proto=IP_PROTOS.tcp, flags=flags)
2891
2892 self.nat_add_inside_interface(self.pg0)
2893 self.nat_add_outside_interface(self.pg0)
Filip Varga9c25eb12021-10-21 13:00:27 +02002894 self.vapi.nat44_ed_add_del_output_interface(
Filip Varga18f1e412020-12-03 15:27:40 +01002895 sw_if_index=self.pg1.sw_if_index, is_add=1)
2896
2897 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
2898 IP(src=self.pg0.remote_ip4, dst=external_addr) /
2899 TCP(sport=12345, dport=external_port))
2900 self.pg0.add_stream(p)
2901 self.pg_enable_capture(self.pg_interfaces)
2902 self.pg_start()
2903 capture = self.pg1.get_capture(1)
2904 p = capture[0]
2905 try:
2906 ip = p[IP]
2907 tcp = p[TCP]
2908 self.assertEqual(ip.src, self.pg0.remote_ip4)
2909 self.assertEqual(tcp.sport, 12345)
2910 self.assertEqual(ip.dst, self.pg1.remote_ip4)
2911 self.assertEqual(tcp.dport, local_port)
2912 self.assert_packet_checksums_valid(p)
2913 except:
2914 self.logger.error(ppp("Unexpected or invalid packet:", p))
2915 raise
2916
2917 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
2918 IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
2919 TCP(sport=local_port, dport=12345))
2920 self.pg1.add_stream(p)
2921 self.pg_enable_capture(self.pg_interfaces)
2922 self.pg_start()
2923 capture = self.pg0.get_capture(1)
2924 p = capture[0]
2925 try:
2926 ip = p[IP]
2927 tcp = p[TCP]
2928 self.assertEqual(ip.src, external_addr)
2929 self.assertEqual(tcp.sport, external_port)
2930 self.assertEqual(ip.dst, self.pg0.remote_ip4)
2931 self.assertEqual(tcp.dport, 12345)
2932 self.assert_packet_checksums_valid(p)
2933 except:
2934 self.logger.error(ppp("Unexpected or invalid packet:", p))
2935 raise
2936
2937 def test_self_twice_nat_lb_negative(self):
2938 """ NAT44ED Self Twice NAT local service load balancing (negative test)
2939 """
2940 self.twice_nat_common(lb=True, self_twice_nat=True, same_pg=True,
2941 client_id=2)
2942
2943 def test_self_twice_nat_negative(self):
2944 """ NAT44ED Self Twice NAT (negative test) """
2945 self.twice_nat_common(self_twice_nat=True)
2946
2947 def test_static_lb_multi_clients(self):
2948 """ NAT44ED local service load balancing - multiple clients"""
2949
2950 external_addr = self.nat_addr
2951 external_port = 80
2952 local_port = 8080
2953 server1 = self.pg0.remote_hosts[0]
2954 server2 = self.pg0.remote_hosts[1]
2955 server3 = self.pg0.remote_hosts[2]
2956
2957 locals = [{'addr': server1.ip4,
2958 'port': local_port,
2959 'probability': 90,
2960 'vrf_id': 0},
2961 {'addr': server2.ip4,
2962 'port': local_port,
2963 'probability': 10,
2964 'vrf_id': 0}]
2965
2966 flags = self.config_flags.NAT_IS_INSIDE
2967 self.vapi.nat44_interface_add_del_feature(
2968 sw_if_index=self.pg0.sw_if_index,
2969 flags=flags, is_add=1)
2970 self.vapi.nat44_interface_add_del_feature(
2971 sw_if_index=self.pg1.sw_if_index,
2972 is_add=1)
2973
2974 self.nat_add_address(self.nat_addr)
2975 self.vapi.nat44_add_del_lb_static_mapping(is_add=1,
2976 external_addr=external_addr,
2977 external_port=external_port,
2978 protocol=IP_PROTOS.tcp,
2979 local_num=len(locals),
2980 locals=locals)
2981
2982 server1_n = 0
2983 server2_n = 0
2984 clients = ip4_range(self.pg1.remote_ip4, 10, 50)
2985 pkts = []
2986 for client in clients:
2987 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
2988 IP(src=client, dst=self.nat_addr) /
2989 TCP(sport=12345, dport=external_port))
2990 pkts.append(p)
2991 self.pg1.add_stream(pkts)
2992 self.pg_enable_capture(self.pg_interfaces)
2993 self.pg_start()
2994 capture = self.pg0.get_capture(len(pkts))
2995 for p in capture:
2996 if p[IP].dst == server1.ip4:
2997 server1_n += 1
2998 else:
2999 server2_n += 1
Klement Sekera1fbf0342021-03-31 13:38:09 +02003000 self.assertGreaterEqual(server1_n, server2_n)
Filip Varga18f1e412020-12-03 15:27:40 +01003001
3002 local = {
3003 'addr': server3.ip4,
3004 'port': local_port,
3005 'probability': 20,
3006 'vrf_id': 0
3007 }
3008
3009 # add new back-end
3010 self.vapi.nat44_lb_static_mapping_add_del_local(
3011 is_add=1,
3012 external_addr=external_addr,
3013 external_port=external_port,
3014 local=local,
3015 protocol=IP_PROTOS.tcp)
3016 server1_n = 0
3017 server2_n = 0
3018 server3_n = 0
3019 clients = ip4_range(self.pg1.remote_ip4, 60, 110)
3020 pkts = []
3021 for client in clients:
3022 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3023 IP(src=client, dst=self.nat_addr) /
3024 TCP(sport=12346, dport=external_port))
3025 pkts.append(p)
3026 self.assertGreater(len(pkts), 0)
3027 self.pg1.add_stream(pkts)
3028 self.pg_enable_capture(self.pg_interfaces)
3029 self.pg_start()
3030 capture = self.pg0.get_capture(len(pkts))
3031 for p in capture:
3032 if p[IP].dst == server1.ip4:
3033 server1_n += 1
3034 elif p[IP].dst == server2.ip4:
3035 server2_n += 1
3036 else:
3037 server3_n += 1
3038 self.assertGreater(server1_n, 0)
3039 self.assertGreater(server2_n, 0)
3040 self.assertGreater(server3_n, 0)
3041
3042 local = {
3043 'addr': server2.ip4,
3044 'port': local_port,
3045 'probability': 10,
3046 'vrf_id': 0
3047 }
3048
3049 # remove one back-end
3050 self.vapi.nat44_lb_static_mapping_add_del_local(
3051 is_add=0,
3052 external_addr=external_addr,
3053 external_port=external_port,
3054 local=local,
3055 protocol=IP_PROTOS.tcp)
3056 server1_n = 0
3057 server2_n = 0
3058 server3_n = 0
3059 self.pg1.add_stream(pkts)
3060 self.pg_enable_capture(self.pg_interfaces)
3061 self.pg_start()
3062 capture = self.pg0.get_capture(len(pkts))
3063 for p in capture:
3064 if p[IP].dst == server1.ip4:
3065 server1_n += 1
3066 elif p[IP].dst == server2.ip4:
3067 server2_n += 1
3068 else:
3069 server3_n += 1
3070 self.assertGreater(server1_n, 0)
3071 self.assertEqual(server2_n, 0)
3072 self.assertGreater(server3_n, 0)
3073
Klement Sekera56c492a2022-01-10 21:57:27 +00003074 # put zzz in front of syslog test name so that it runs as a last test
3075 # setting syslog sender cannot be undone and if it is set, it messes
3076 # with self.send_and_assert_no_replies functionality
3077 def test_zzz_syslog_sess(self):
Filip Varga18f1e412020-12-03 15:27:40 +01003078 """ NAT44ED Test syslog session creation and deletion """
3079 self.vapi.syslog_set_filter(
3080 self.syslog_severity.SYSLOG_API_SEVERITY_INFO)
3081 self.vapi.syslog_set_sender(self.pg3.local_ip4, self.pg3.remote_ip4)
3082
3083 self.nat_add_address(self.nat_addr)
3084 self.nat_add_inside_interface(self.pg0)
3085 self.nat_add_outside_interface(self.pg1)
3086
3087 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3088 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3089 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port))
3090 self.pg0.add_stream(p)
3091 self.pg_enable_capture(self.pg_interfaces)
3092 self.pg_start()
3093 capture = self.pg1.get_capture(1)
3094 self.tcp_port_out = capture[0][TCP].sport
3095 capture = self.pg3.get_capture(1)
Klement Sekera56c492a2022-01-10 21:57:27 +00003096 self.verify_syslog_sess(capture[0][Raw].load, 'SADD')
Filip Varga18f1e412020-12-03 15:27:40 +01003097
3098 self.pg_enable_capture(self.pg_interfaces)
3099 self.pg_start()
3100 self.nat_add_address(self.nat_addr, is_add=0)
3101 capture = self.pg3.get_capture(1)
Klement Sekera56c492a2022-01-10 21:57:27 +00003102 self.verify_syslog_sess(capture[0][Raw].load, 'SDEL')
3103
3104 # put zzz in front of syslog test name so that it runs as a last test
3105 # setting syslog sender cannot be undone and if it is set, it messes
3106 # with self.send_and_assert_no_replies functionality
3107 def test_zzz_syslog_sess_reopen(self):
3108 """ Syslog events for session reopen """
3109 self.vapi.syslog_set_filter(
3110 self.syslog_severity.SYSLOG_API_SEVERITY_INFO)
3111 self.vapi.syslog_set_sender(self.pg3.local_ip4, self.pg3.remote_ip4)
3112
3113 self.nat_add_address(self.nat_addr)
3114 self.nat_add_inside_interface(self.pg0)
3115 self.nat_add_outside_interface(self.pg1)
3116
3117 # SYN in2out
3118 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3119 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3120 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port))
3121 capture = self.send_and_expect(self.pg0, p, self.pg1)[0]
3122 self.tcp_port_out = capture[0][TCP].sport
3123 capture = self.pg3.get_capture(1)
3124 self.verify_syslog_sess(capture[0][Raw].load, 'SADD')
3125
3126 # SYN out2in
3127 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
3128 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Ole Troan52974472022-03-17 11:58:38 +01003129 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
3130 flags='SA'))
Klement Sekera56c492a2022-01-10 21:57:27 +00003131 self.send_and_expect(self.pg1, p, self.pg0)
3132
Ole Troan52974472022-03-17 11:58:38 +01003133 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3134 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3135 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
3136 flags="A"))
3137 self.send_and_expect(self.pg0, p, self.pg1)
3138
Klement Sekera56c492a2022-01-10 21:57:27 +00003139 # FIN in2out
3140 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3141 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3142 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
3143 flags="F"))
3144 self.send_and_expect(self.pg0, p, self.pg1)
3145
3146 # FIN out2in
3147 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
3148 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3149 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
3150 flags="F"))
3151 self.send_and_expect(self.pg1, p, self.pg0)
3152
Ole Troan52974472022-03-17 11:58:38 +01003153 self.init_tcp_session(self.pg0, self.pg1, self.tcp_port_in,
3154 self.tcp_external_port)
Klement Sekera56c492a2022-01-10 21:57:27 +00003155
3156 # 2 records should be produced - first one del & add
3157 capture = self.pg3.get_capture(2)
3158 self.verify_syslog_sess(capture[0][Raw].load, 'SDEL')
3159 self.verify_syslog_sess(capture[1][Raw].load, 'SADD')
Filip Varga18f1e412020-12-03 15:27:40 +01003160
3161 def test_twice_nat_interface_addr(self):
3162 """ NAT44ED Acquire twice NAT addresses from interface """
3163 flags = self.config_flags.NAT_IS_TWICE_NAT
3164 self.vapi.nat44_add_del_interface_addr(
3165 sw_if_index=self.pg11.sw_if_index,
3166 flags=flags, is_add=1)
3167
3168 # no address in NAT pool
3169 adresses = self.vapi.nat44_address_dump()
3170 self.assertEqual(0, len(adresses))
3171
3172 # configure interface address and check NAT address pool
3173 self.pg11.config_ip4()
3174 adresses = self.vapi.nat44_address_dump()
3175 self.assertEqual(1, len(adresses))
3176 self.assertEqual(str(adresses[0].ip_address),
3177 self.pg11.local_ip4)
3178 self.assertEqual(adresses[0].flags, flags)
3179
3180 # remove interface address and check NAT address pool
3181 self.pg11.unconfig_ip4()
3182 adresses = self.vapi.nat44_address_dump()
3183 self.assertEqual(0, len(adresses))
3184
3185 def test_output_feature_stateful_acl(self):
3186 """ NAT44ED output feature works with stateful ACL """
3187
3188 self.nat_add_address(self.nat_addr)
Filip Varga9c25eb12021-10-21 13:00:27 +02003189 self.vapi.nat44_ed_add_del_output_interface(
Filip Varga63e15812021-06-29 14:28:21 +02003190 sw_if_index=self.pg1.sw_if_index, is_add=1)
Filip Varga18f1e412020-12-03 15:27:40 +01003191
3192 # First ensure that the NAT is working sans ACL
3193
3194 # send packets out2in, no sessions yet so packets should drop
3195 pkts_out2in = self.create_stream_out(self.pg1)
3196 self.send_and_assert_no_replies(self.pg1, pkts_out2in)
3197
3198 # send packets into inside intf, ensure received via outside intf
3199 pkts_in2out = self.create_stream_in(self.pg0, self.pg1)
3200 capture = self.send_and_expect(self.pg0, pkts_in2out, self.pg1,
3201 len(pkts_in2out))
3202 self.verify_capture_out(capture, ignore_port=True)
3203
3204 # send out2in again, with sessions created it should work now
3205 pkts_out2in = self.create_stream_out(self.pg1)
3206 capture = self.send_and_expect(self.pg1, pkts_out2in, self.pg0,
3207 len(pkts_out2in))
3208 self.verify_capture_in(capture, self.pg0)
3209
3210 # Create an ACL blocking everything
3211 out2in_deny_rule = AclRule(is_permit=0)
3212 out2in_acl = VppAcl(self, rules=[out2in_deny_rule])
3213 out2in_acl.add_vpp_config()
3214
3215 # create an ACL to permit/reflect everything
3216 in2out_reflect_rule = AclRule(is_permit=2)
3217 in2out_acl = VppAcl(self, rules=[in2out_reflect_rule])
3218 in2out_acl.add_vpp_config()
3219
3220 # apply as input acl on interface and confirm it blocks everything
3221 acl_if = VppAclInterface(self, sw_if_index=self.pg1.sw_if_index,
3222 n_input=1, acls=[out2in_acl])
3223 acl_if.add_vpp_config()
3224 self.send_and_assert_no_replies(self.pg1, pkts_out2in)
3225
3226 # apply output acl
3227 acl_if.acls = [out2in_acl, in2out_acl]
3228 acl_if.add_vpp_config()
3229 # send in2out to generate ACL state (NAT state was created earlier)
3230 capture = self.send_and_expect(self.pg0, pkts_in2out, self.pg1,
3231 len(pkts_in2out))
3232 self.verify_capture_out(capture, ignore_port=True)
3233
3234 # send out2in again. ACL state exists so it should work now.
3235 # TCP packets with the syn flag set also need the ack flag
3236 for p in pkts_out2in:
3237 if p.haslayer(TCP) and p[TCP].flags & 0x02:
3238 p[TCP].flags |= 0x10
3239 capture = self.send_and_expect(self.pg1, pkts_out2in, self.pg0,
3240 len(pkts_out2in))
3241 self.verify_capture_in(capture, self.pg0)
3242 self.logger.info(self.vapi.cli("show trace"))
3243
3244 def test_tcp_close(self):
3245 """ NAT44ED Close TCP session from inside network - output feature """
Filip Vargab6810822022-02-15 11:56:07 -08003246 config = self.vapi.nat44_show_running_config()
3247 old_timeouts = config.timeouts
Filip Varga18f1e412020-12-03 15:27:40 +01003248 new_transitory = 2
3249 self.vapi.nat_set_timeouts(
3250 udp=old_timeouts.udp,
3251 tcp_established=old_timeouts.tcp_established,
3252 icmp=old_timeouts.icmp,
3253 tcp_transitory=new_transitory)
3254
3255 self.vapi.nat44_forwarding_enable_disable(enable=1)
3256 self.nat_add_address(self.pg1.local_ip4)
3257 twice_nat_addr = '10.0.1.3'
3258 service_ip = '192.168.16.150'
3259 self.nat_add_address(twice_nat_addr, twice_nat=1)
3260
3261 flags = self.config_flags.NAT_IS_INSIDE
3262 self.vapi.nat44_interface_add_del_feature(
3263 sw_if_index=self.pg0.sw_if_index,
3264 is_add=1)
3265 self.vapi.nat44_interface_add_del_feature(
3266 sw_if_index=self.pg0.sw_if_index,
3267 flags=flags, is_add=1)
Filip Varga9c25eb12021-10-21 13:00:27 +02003268 self.vapi.nat44_ed_add_del_output_interface(
Filip Varga18f1e412020-12-03 15:27:40 +01003269 is_add=1,
3270 sw_if_index=self.pg1.sw_if_index)
3271
3272 flags = (self.config_flags.NAT_IS_OUT2IN_ONLY |
3273 self.config_flags.NAT_IS_TWICE_NAT)
3274 self.nat_add_static_mapping(self.pg0.remote_ip4,
3275 service_ip, 80, 80,
3276 proto=IP_PROTOS.tcp,
3277 flags=flags)
3278 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3279 start_sessnum = len(sessions)
3280
3281 # SYN packet out->in
3282 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3283 IP(src=self.pg1.remote_ip4, dst=service_ip) /
3284 TCP(sport=33898, dport=80, flags="S"))
Klement Sekera56c492a2022-01-10 21:57:27 +00003285 capture = self.send_and_expect(self.pg1, p, self.pg0, n_rx=1)
Filip Varga18f1e412020-12-03 15:27:40 +01003286 p = capture[0]
3287 tcp_port = p[TCP].sport
3288
3289 # SYN + ACK packet in->out
3290 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3291 IP(src=self.pg0.remote_ip4, dst=twice_nat_addr) /
3292 TCP(sport=80, dport=tcp_port, flags="SA"))
Klement Sekera56c492a2022-01-10 21:57:27 +00003293 self.send_and_expect(self.pg0, p, self.pg1, n_rx=1)
Filip Varga18f1e412020-12-03 15:27:40 +01003294
3295 # ACK packet out->in
3296 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3297 IP(src=self.pg1.remote_ip4, dst=service_ip) /
3298 TCP(sport=33898, dport=80, flags="A"))
Klement Sekera56c492a2022-01-10 21:57:27 +00003299 self.send_and_expect(self.pg1, p, self.pg0, n_rx=1)
Filip Varga18f1e412020-12-03 15:27:40 +01003300
3301 # FIN packet in -> out
3302 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3303 IP(src=self.pg0.remote_ip4, dst=twice_nat_addr) /
3304 TCP(sport=80, dport=tcp_port, flags="FA", seq=100, ack=300))
Klement Sekera56c492a2022-01-10 21:57:27 +00003305 self.send_and_expect(self.pg0, p, self.pg1, n_rx=1)
Filip Varga18f1e412020-12-03 15:27:40 +01003306
3307 # FIN+ACK packet out -> in
3308 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3309 IP(src=self.pg1.remote_ip4, dst=service_ip) /
3310 TCP(sport=33898, dport=80, flags="FA", seq=300, ack=101))
Klement Sekera56c492a2022-01-10 21:57:27 +00003311 self.send_and_expect(self.pg1, p, self.pg0, n_rx=1)
Filip Varga18f1e412020-12-03 15:27:40 +01003312
3313 # ACK packet in -> out
3314 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3315 IP(src=self.pg0.remote_ip4, dst=twice_nat_addr) /
3316 TCP(sport=80, dport=tcp_port, flags="A", seq=101, ack=301))
Klement Sekera56c492a2022-01-10 21:57:27 +00003317 self.send_and_expect(self.pg0, p, self.pg1, n_rx=1)
Filip Varga18f1e412020-12-03 15:27:40 +01003318
Klement Sekera56c492a2022-01-10 21:57:27 +00003319 # session now in transitory timeout, but traffic still flows
3320 # try FIN packet out->in
Filip Varga18f1e412020-12-03 15:27:40 +01003321 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3322 IP(src=self.pg1.remote_ip4, dst=service_ip) /
Klement Sekera56c492a2022-01-10 21:57:27 +00003323 TCP(sport=33898, dport=80, flags="F"))
Filip Varga18f1e412020-12-03 15:27:40 +01003324 self.pg1.add_stream(p)
3325 self.pg_enable_capture(self.pg_interfaces)
3326 self.pg_start()
3327
Benoît Ganne56eccdb2021-08-20 09:18:31 +02003328 self.virtual_sleep(new_transitory, "wait for transitory timeout")
Klement Sekera56c492a2022-01-10 21:57:27 +00003329 self.pg0.get_capture(1)
Filip Varga18f1e412020-12-03 15:27:40 +01003330
3331 # session should still exist
3332 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3333 self.assertEqual(len(sessions) - start_sessnum, 1)
3334
3335 # send FIN+ACK packet out -> in - will cause session to be wiped
3336 # but won't create a new session
3337 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3338 IP(src=self.pg1.remote_ip4, dst=service_ip) /
3339 TCP(sport=33898, dport=80, flags="FA", seq=300, ack=101))
Klement Sekera56c492a2022-01-10 21:57:27 +00003340 self.send_and_assert_no_replies(self.pg1, p)
Filip Varga18f1e412020-12-03 15:27:40 +01003341 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3342 self.assertEqual(len(sessions) - start_sessnum, 0)
Filip Varga18f1e412020-12-03 15:27:40 +01003343
3344 def test_tcp_session_close_in(self):
3345 """ NAT44ED Close TCP session from inside network """
3346
3347 in_port = self.tcp_port_in
3348 out_port = 10505
3349 ext_port = self.tcp_external_port
3350
3351 self.nat_add_address(self.nat_addr)
3352 self.nat_add_inside_interface(self.pg0)
3353 self.nat_add_outside_interface(self.pg1)
3354 self.nat_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
3355 in_port, out_port, proto=IP_PROTOS.tcp,
3356 flags=self.config_flags.NAT_IS_TWICE_NAT)
3357
3358 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3359 session_n = len(sessions)
3360
3361 self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
3362 tcp_transitory=2, icmp=5)
3363
3364 self.init_tcp_session(self.pg0, self.pg1, in_port, ext_port)
3365
3366 # FIN packet in -> out
3367 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3368 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3369 TCP(sport=in_port, dport=ext_port,
3370 flags="FA", seq=100, ack=300))
Klement Sekera56c492a2022-01-10 21:57:27 +00003371 self.send_and_expect(self.pg0, p, self.pg1)
Filip Varga18f1e412020-12-03 15:27:40 +01003372 pkts = []
3373
3374 # ACK packet out -> in
3375 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3376 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3377 TCP(sport=ext_port, dport=out_port,
3378 flags="A", seq=300, ack=101))
3379 pkts.append(p)
3380
3381 # FIN packet out -> in
3382 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3383 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3384 TCP(sport=ext_port, dport=out_port,
3385 flags="FA", seq=300, ack=101))
3386 pkts.append(p)
3387
Klement Sekera56c492a2022-01-10 21:57:27 +00003388 self.send_and_expect(self.pg1, pkts, self.pg0)
Filip Varga18f1e412020-12-03 15:27:40 +01003389
3390 # ACK packet in -> out
3391 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3392 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3393 TCP(sport=in_port, dport=ext_port,
3394 flags="A", seq=101, ack=301))
Klement Sekera56c492a2022-01-10 21:57:27 +00003395 self.send_and_expect(self.pg0, p, self.pg1)
Filip Varga18f1e412020-12-03 15:27:40 +01003396
3397 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3398 self.assertEqual(len(sessions) - session_n, 1)
3399
Klement Sekera56c492a2022-01-10 21:57:27 +00003400 # retransmit FIN packet out -> in
Filip Varga18f1e412020-12-03 15:27:40 +01003401 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3402 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3403 TCP(sport=ext_port, dport=out_port,
3404 flags="FA", seq=300, ack=101))
3405
Klement Sekera56c492a2022-01-10 21:57:27 +00003406 self.send_and_expect(self.pg1, p, self.pg0)
Filip Varga18f1e412020-12-03 15:27:40 +01003407
Klement Sekera56c492a2022-01-10 21:57:27 +00003408 # retransmit ACK packet in -> out
Filip Varga18f1e412020-12-03 15:27:40 +01003409 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3410 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3411 TCP(sport=in_port, dport=ext_port,
3412 flags="A", seq=101, ack=301))
Klement Sekera56c492a2022-01-10 21:57:27 +00003413 self.send_and_expect(self.pg0, p, self.pg1)
Filip Varga18f1e412020-12-03 15:27:40 +01003414
Benoît Ganne56eccdb2021-08-20 09:18:31 +02003415 self.virtual_sleep(3)
Klement Sekera56c492a2022-01-10 21:57:27 +00003416 # retransmit ACK packet in -> out - this will cause session to be wiped
Filip Varga18f1e412020-12-03 15:27:40 +01003417 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3418 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3419 TCP(sport=in_port, dport=ext_port,
3420 flags="A", seq=101, ack=301))
Klement Sekera56c492a2022-01-10 21:57:27 +00003421 self.send_and_assert_no_replies(self.pg0, p)
Filip Varga18f1e412020-12-03 15:27:40 +01003422 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3423 self.assertEqual(len(sessions) - session_n, 0)
3424
3425 def test_tcp_session_close_out(self):
3426 """ NAT44ED Close TCP session from outside network """
3427
3428 in_port = self.tcp_port_in
3429 out_port = 10505
3430 ext_port = self.tcp_external_port
3431
3432 self.nat_add_address(self.nat_addr)
3433 self.nat_add_inside_interface(self.pg0)
3434 self.nat_add_outside_interface(self.pg1)
3435 self.nat_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
3436 in_port, out_port, proto=IP_PROTOS.tcp,
3437 flags=self.config_flags.NAT_IS_TWICE_NAT)
3438
3439 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3440 session_n = len(sessions)
3441
3442 self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
3443 tcp_transitory=2, icmp=5)
3444
3445 _ = self.init_tcp_session(self.pg0, self.pg1, in_port, ext_port)
3446
3447 # FIN packet out -> in
3448 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3449 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3450 TCP(sport=ext_port, dport=out_port,
3451 flags="FA", seq=100, ack=300))
3452 self.pg1.add_stream(p)
3453 self.pg_enable_capture(self.pg_interfaces)
3454 self.pg_start()
3455 self.pg0.get_capture(1)
3456
3457 # FIN+ACK packet in -> out
3458 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3459 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3460 TCP(sport=in_port, dport=ext_port,
3461 flags="FA", seq=300, ack=101))
3462
3463 self.pg0.add_stream(p)
3464 self.pg_enable_capture(self.pg_interfaces)
3465 self.pg_start()
3466 self.pg1.get_capture(1)
3467
3468 # ACK packet out -> in
3469 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3470 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3471 TCP(sport=ext_port, dport=out_port,
3472 flags="A", seq=101, ack=301))
3473 self.pg1.add_stream(p)
3474 self.pg_enable_capture(self.pg_interfaces)
3475 self.pg_start()
3476 self.pg0.get_capture(1)
3477
3478 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3479 self.assertEqual(len(sessions) - session_n, 1)
3480
Klement Sekera56c492a2022-01-10 21:57:27 +00003481 # retransmit FIN packet out -> in
Filip Varga18f1e412020-12-03 15:27:40 +01003482 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3483 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3484 TCP(sport=ext_port, dport=out_port,
3485 flags="FA", seq=300, ack=101))
Klement Sekera56c492a2022-01-10 21:57:27 +00003486 self.send_and_expect(self.pg1, p, self.pg0)
Filip Varga18f1e412020-12-03 15:27:40 +01003487
Klement Sekera56c492a2022-01-10 21:57:27 +00003488 # retransmit ACK packet in -> out
Filip Varga18f1e412020-12-03 15:27:40 +01003489 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3490 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3491 TCP(sport=in_port, dport=ext_port,
3492 flags="A", seq=101, ack=301))
Klement Sekera56c492a2022-01-10 21:57:27 +00003493 self.send_and_expect(self.pg0, p, self.pg1)
Filip Varga18f1e412020-12-03 15:27:40 +01003494
Benoît Ganne56eccdb2021-08-20 09:18:31 +02003495 self.virtual_sleep(3)
Klement Sekera56c492a2022-01-10 21:57:27 +00003496 # retransmit ACK packet in -> out - this will cause session to be wiped
Filip Varga18f1e412020-12-03 15:27:40 +01003497 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3498 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3499 TCP(sport=in_port, dport=ext_port,
3500 flags="A", seq=101, ack=301))
Klement Sekera56c492a2022-01-10 21:57:27 +00003501 self.send_and_assert_no_replies(self.pg0, p)
Filip Varga18f1e412020-12-03 15:27:40 +01003502 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3503 self.assertEqual(len(sessions) - session_n, 0)
3504
3505 def test_tcp_session_close_simultaneous(self):
Klement Sekera56c492a2022-01-10 21:57:27 +00003506 """ Simultaneous TCP close from both sides """
Filip Varga18f1e412020-12-03 15:27:40 +01003507
3508 in_port = self.tcp_port_in
3509 ext_port = 10505
3510
3511 self.nat_add_address(self.nat_addr)
3512 self.nat_add_inside_interface(self.pg0)
3513 self.nat_add_outside_interface(self.pg1)
3514 self.nat_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
3515 in_port, ext_port, proto=IP_PROTOS.tcp,
3516 flags=self.config_flags.NAT_IS_TWICE_NAT)
3517
3518 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3519 session_n = len(sessions)
3520
3521 self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
3522 tcp_transitory=2, icmp=5)
3523
3524 out_port = self.init_tcp_session(self.pg0, self.pg1, in_port, ext_port)
3525
3526 # FIN packet in -> out
3527 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3528 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3529 TCP(sport=in_port, dport=ext_port,
3530 flags="FA", seq=100, ack=300))
Klement Sekera56c492a2022-01-10 21:57:27 +00003531 self.send_and_expect(self.pg0, p, self.pg1)
Filip Varga18f1e412020-12-03 15:27:40 +01003532
3533 # FIN packet out -> in
3534 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3535 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3536 TCP(sport=ext_port, dport=out_port,
3537 flags="FA", seq=300, ack=100))
Klement Sekera56c492a2022-01-10 21:57:27 +00003538 self.send_and_expect(self.pg1, p, self.pg0)
Filip Varga18f1e412020-12-03 15:27:40 +01003539
3540 # ACK packet in -> out
3541 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3542 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3543 TCP(sport=in_port, dport=ext_port,
3544 flags="A", seq=101, ack=301))
Klement Sekera56c492a2022-01-10 21:57:27 +00003545 self.send_and_expect(self.pg0, p, self.pg1)
Filip Varga18f1e412020-12-03 15:27:40 +01003546
3547 # ACK packet out -> in
3548 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3549 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3550 TCP(sport=ext_port, dport=out_port,
3551 flags="A", seq=301, ack=101))
Klement Sekera56c492a2022-01-10 21:57:27 +00003552 self.send_and_expect(self.pg1, p, self.pg0)
Filip Varga18f1e412020-12-03 15:27:40 +01003553
3554 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3555 self.assertEqual(len(sessions) - session_n, 1)
3556
Klement Sekera56c492a2022-01-10 21:57:27 +00003557 # retransmit FIN packet out -> in
Filip Varga18f1e412020-12-03 15:27:40 +01003558 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3559 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3560 TCP(sport=ext_port, dport=out_port,
3561 flags="FA", seq=300, ack=101))
Klement Sekera56c492a2022-01-10 21:57:27 +00003562 self.send_and_expect(self.pg1, p, self.pg0)
Filip Varga18f1e412020-12-03 15:27:40 +01003563
Klement Sekera56c492a2022-01-10 21:57:27 +00003564 # retransmit ACK packet in -> out
Filip Varga18f1e412020-12-03 15:27:40 +01003565 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3566 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3567 TCP(sport=in_port, dport=ext_port,
3568 flags="A", seq=101, ack=301))
Klement Sekera56c492a2022-01-10 21:57:27 +00003569 self.send_and_expect(self.pg0, p, self.pg1)
Filip Varga18f1e412020-12-03 15:27:40 +01003570
Benoît Ganne56eccdb2021-08-20 09:18:31 +02003571 self.virtual_sleep(3)
Klement Sekera56c492a2022-01-10 21:57:27 +00003572 # retransmit ACK packet in -> out - this will cause session to be wiped
Filip Varga18f1e412020-12-03 15:27:40 +01003573 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3574 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3575 TCP(sport=in_port, dport=ext_port,
3576 flags="A", seq=101, ack=301))
Klement Sekera56c492a2022-01-10 21:57:27 +00003577 self.pg_send(self.pg0, p)
3578 self.send_and_assert_no_replies(self.pg0, p)
Filip Varga18f1e412020-12-03 15:27:40 +01003579 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3580 self.assertEqual(len(sessions) - session_n, 0)
3581
Klement Sekera56c492a2022-01-10 21:57:27 +00003582 def test_tcp_session_half_reopen_inside(self):
3583 """ TCP session in FIN/FIN state not reopened by in2out SYN only """
3584 in_port = self.tcp_port_in
3585 ext_port = 10505
3586
3587 self.nat_add_address(self.nat_addr)
3588 self.nat_add_inside_interface(self.pg0)
3589 self.nat_add_outside_interface(self.pg1)
3590 self.nat_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
3591 in_port, ext_port, proto=IP_PROTOS.tcp,
3592 flags=self.config_flags.NAT_IS_TWICE_NAT)
3593
3594 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3595 session_n = len(sessions)
3596
3597 self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
3598 tcp_transitory=2, icmp=5)
3599
3600 out_port = self.init_tcp_session(self.pg0, self.pg1, in_port, ext_port)
3601
3602 # FIN packet in -> out
3603 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3604 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3605 TCP(sport=in_port, dport=ext_port,
3606 flags="FA", seq=100, ack=300))
3607 self.send_and_expect(self.pg0, p, self.pg1)
3608
3609 # FIN packet out -> in
3610 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3611 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3612 TCP(sport=ext_port, dport=out_port,
3613 flags="FA", seq=300, ack=100))
3614 self.send_and_expect(self.pg1, p, self.pg0)
3615
3616 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3617 self.assertEqual(len(sessions) - session_n, 1)
3618
3619 # send SYN packet in -> out
3620 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3621 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3622 TCP(sport=in_port, dport=ext_port,
3623 flags="S", seq=101, ack=301))
3624 self.send_and_expect(self.pg0, p, self.pg1)
3625
3626 self.virtual_sleep(3)
3627 # send ACK packet in -> out - session should be wiped
3628 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3629 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3630 TCP(sport=in_port, dport=ext_port,
3631 flags="A", seq=101, ack=301))
3632 self.send_and_assert_no_replies(self.pg0, p, self.pg1)
3633 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3634 self.assertEqual(len(sessions) - session_n, 0)
3635
3636 def test_tcp_session_half_reopen_outside(self):
3637 """ TCP session in FIN/FIN state not reopened by out2in SYN only """
3638 in_port = self.tcp_port_in
3639 ext_port = 10505
3640
3641 self.nat_add_address(self.nat_addr)
3642 self.nat_add_inside_interface(self.pg0)
3643 self.nat_add_outside_interface(self.pg1)
3644 self.nat_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
3645 in_port, ext_port, proto=IP_PROTOS.tcp,
3646 flags=self.config_flags.NAT_IS_TWICE_NAT)
3647
3648 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3649 session_n = len(sessions)
3650
3651 self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
3652 tcp_transitory=2, icmp=5)
3653
3654 out_port = self.init_tcp_session(self.pg0, self.pg1, in_port, ext_port)
3655
3656 # FIN packet in -> out
3657 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3658 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3659 TCP(sport=in_port, dport=ext_port,
3660 flags="FA", seq=100, ack=300))
3661 self.send_and_expect(self.pg0, p, self.pg1)
3662
3663 # FIN packet out -> in
3664 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3665 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3666 TCP(sport=ext_port, dport=out_port,
3667 flags="FA", seq=300, ack=100))
3668 self.send_and_expect(self.pg1, p, self.pg0)
3669
3670 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3671 self.assertEqual(len(sessions) - session_n, 1)
3672
3673 # send SYN packet out -> in
3674 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3675 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3676 TCP(sport=ext_port, dport=out_port,
3677 flags="S", seq=300, ack=101))
3678 self.send_and_expect(self.pg1, p, self.pg0)
3679
3680 self.virtual_sleep(3)
3681 # send ACK packet in -> out - session should be wiped
3682 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3683 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3684 TCP(sport=in_port, dport=ext_port,
3685 flags="A", seq=101, ack=301))
3686 self.send_and_assert_no_replies(self.pg0, p, self.pg1)
3687 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3688 self.assertEqual(len(sessions) - session_n, 0)
3689
3690 def test_tcp_session_reopen(self):
3691 """ TCP session in FIN/FIN state reopened by SYN from both sides """
3692 in_port = self.tcp_port_in
3693 ext_port = 10505
3694
3695 self.nat_add_address(self.nat_addr)
3696 self.nat_add_inside_interface(self.pg0)
3697 self.nat_add_outside_interface(self.pg1)
3698 self.nat_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
3699 in_port, ext_port, proto=IP_PROTOS.tcp,
3700 flags=self.config_flags.NAT_IS_TWICE_NAT)
3701
3702 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3703 session_n = len(sessions)
3704
3705 self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
3706 tcp_transitory=2, icmp=5)
3707
3708 out_port = self.init_tcp_session(self.pg0, self.pg1, in_port, ext_port)
3709
3710 # FIN packet in -> out
3711 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3712 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3713 TCP(sport=in_port, dport=ext_port,
3714 flags="FA", seq=100, ack=300))
3715 self.send_and_expect(self.pg0, p, self.pg1)
3716
3717 # FIN packet out -> in
3718 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3719 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3720 TCP(sport=ext_port, dport=out_port,
3721 flags="FA", seq=300, ack=100))
3722 self.send_and_expect(self.pg1, p, self.pg0)
3723
3724 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3725 self.assertEqual(len(sessions) - session_n, 1)
3726
3727 # send SYN packet out -> in
3728 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3729 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3730 TCP(sport=ext_port, dport=out_port,
3731 flags="S", seq=300, ack=101))
3732 self.send_and_expect(self.pg1, p, self.pg0)
3733
3734 # send SYN packet in -> out
3735 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3736 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3737 TCP(sport=in_port, dport=ext_port,
Ole Troan52974472022-03-17 11:58:38 +01003738 flags="SA", seq=101, ack=301))
Klement Sekera56c492a2022-01-10 21:57:27 +00003739 self.send_and_expect(self.pg0, p, self.pg1)
3740
Ole Troan52974472022-03-17 11:58:38 +01003741 # send ACK packet out -> in
3742 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3743 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3744 TCP(sport=ext_port, dport=out_port,
3745 flags="A", seq=300, ack=101))
3746 self.send_and_expect(self.pg1, p, self.pg0)
3747
Klement Sekera56c492a2022-01-10 21:57:27 +00003748 self.virtual_sleep(3)
3749 # send ACK packet in -> out - should be forwarded and session alive
3750 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3751 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3752 TCP(sport=in_port, dport=ext_port,
3753 flags="A", seq=101, ack=301))
3754 self.send_and_expect(self.pg0, p, self.pg1)
3755 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3756 self.assertEqual(len(sessions) - session_n, 1)
3757
Filip Vargabdd61492021-04-13 17:47:13 +02003758 def test_dynamic_vrf(self):
3759 """ NAT44ED dynamic translation test: different VRF"""
3760
3761 vrf_id_in = 33
3762 vrf_id_out = 34
3763
3764 self.nat_add_address(self.nat_addr, vrf_id=vrf_id_in)
3765
3766 try:
3767 self.configure_ip4_interface(self.pg7, table_id=vrf_id_in)
3768 self.configure_ip4_interface(self.pg8, table_id=vrf_id_out)
3769
3770 self.nat_add_inside_interface(self.pg7)
3771 self.nat_add_outside_interface(self.pg8)
3772
3773 # just basic stuff nothing special
3774 pkts = self.create_stream_in(self.pg7, self.pg8)
3775 self.pg7.add_stream(pkts)
3776 self.pg_enable_capture(self.pg_interfaces)
3777 self.pg_start()
3778 capture = self.pg8.get_capture(len(pkts))
3779 self.verify_capture_out(capture, ignore_port=True)
3780
3781 pkts = self.create_stream_out(self.pg8)
3782 self.pg8.add_stream(pkts)
3783 self.pg_enable_capture(self.pg_interfaces)
3784 self.pg_start()
3785 capture = self.pg7.get_capture(len(pkts))
3786 self.verify_capture_in(capture, self.pg7)
3787
3788 finally:
3789 self.pg7.unconfig()
3790 self.pg8.unconfig()
3791
3792 self.vapi.ip_table_add_del(is_add=0,
3793 table={'table_id': vrf_id_in})
3794 self.vapi.ip_table_add_del(is_add=0,
3795 table={'table_id': vrf_id_out})
3796
Filip Varga18f1e412020-12-03 15:27:40 +01003797 def test_dynamic_output_feature_vrf(self):
3798 """ NAT44ED dynamic translation test: output-feature, VRF"""
3799
3800 # other then default (0)
3801 new_vrf_id = 22
3802
3803 self.nat_add_address(self.nat_addr)
Filip Vargab6810822022-02-15 11:56:07 -08003804 self.vapi.nat44_ed_add_del_output_interface(
3805 sw_if_index=self.pg8.sw_if_index,
3806 is_add=1)
Filip Varga18f1e412020-12-03 15:27:40 +01003807 try:
3808 self.configure_ip4_interface(self.pg7, table_id=new_vrf_id)
3809 self.configure_ip4_interface(self.pg8, table_id=new_vrf_id)
3810
3811 # in2out
Klement Sekera3887be72021-03-30 20:29:05 +02003812 tcpn = self.statistics['/nat44-ed/in2out/slowpath/tcp']
3813 udpn = self.statistics['/nat44-ed/in2out/slowpath/udp']
3814 icmpn = self.statistics['/nat44-ed/in2out/slowpath/icmp']
3815 drops = self.statistics['/nat44-ed/in2out/slowpath/drops']
Filip Varga18f1e412020-12-03 15:27:40 +01003816
3817 pkts = self.create_stream_in(self.pg7, self.pg8)
3818 self.pg7.add_stream(pkts)
3819 self.pg_enable_capture(self.pg_interfaces)
3820 self.pg_start()
3821 capture = self.pg8.get_capture(len(pkts))
3822 self.verify_capture_out(capture, ignore_port=True)
3823
Alexander Chernavin4de12b92021-07-06 06:08:26 -04003824 if_idx = self.pg8.sw_if_index
Klement Sekera3887be72021-03-30 20:29:05 +02003825 cnt = self.statistics['/nat44-ed/in2out/slowpath/tcp']
3826 self.assertEqual(cnt[:, if_idx].sum() - tcpn[:, if_idx].sum(), 2)
3827 cnt = self.statistics['/nat44-ed/in2out/slowpath/udp']
3828 self.assertEqual(cnt[:, if_idx].sum() - udpn[:, if_idx].sum(), 1)
3829 cnt = self.statistics['/nat44-ed/in2out/slowpath/icmp']
3830 self.assertEqual(cnt[:, if_idx].sum() - icmpn[:, if_idx].sum(), 1)
3831 cnt = self.statistics['/nat44-ed/in2out/slowpath/drops']
3832 self.assertEqual(cnt[:, if_idx].sum() - drops[:, if_idx].sum(), 0)
Filip Varga18f1e412020-12-03 15:27:40 +01003833
3834 # out2in
Klement Sekera3887be72021-03-30 20:29:05 +02003835 tcpn = self.statistics['/nat44-ed/out2in/fastpath/tcp']
3836 udpn = self.statistics['/nat44-ed/out2in/fastpath/udp']
3837 icmpn = self.statistics['/nat44-ed/out2in/fastpath/icmp']
3838 drops = self.statistics['/nat44-ed/out2in/fastpath/drops']
Filip Varga18f1e412020-12-03 15:27:40 +01003839
3840 pkts = self.create_stream_out(self.pg8)
3841 self.pg8.add_stream(pkts)
3842 self.pg_enable_capture(self.pg_interfaces)
3843 self.pg_start()
3844 capture = self.pg7.get_capture(len(pkts))
3845 self.verify_capture_in(capture, self.pg7)
3846
3847 if_idx = self.pg8.sw_if_index
Klement Sekera3887be72021-03-30 20:29:05 +02003848 cnt = self.statistics['/nat44-ed/out2in/fastpath/tcp']
3849 self.assertEqual(cnt[:, if_idx].sum() - tcpn[:, if_idx].sum(), 2)
3850 cnt = self.statistics['/nat44-ed/out2in/fastpath/udp']
3851 self.assertEqual(cnt[:, if_idx].sum() - udpn[:, if_idx].sum(), 1)
3852 cnt = self.statistics['/nat44-ed/out2in/fastpath/icmp']
3853 self.assertEqual(cnt[:, if_idx].sum() - icmpn[:, if_idx].sum(), 1)
3854 cnt = self.statistics['/nat44-ed/out2in/fastpath/drops']
3855 self.assertEqual(cnt[:, if_idx].sum() - drops[:, if_idx].sum(), 0)
Filip Varga18f1e412020-12-03 15:27:40 +01003856
Klement Sekera3887be72021-03-30 20:29:05 +02003857 sessions = self.statistics['/nat44-ed/total-sessions']
3858 self.assertEqual(sessions[:, 0].sum(), 3)
Filip Varga18f1e412020-12-03 15:27:40 +01003859
3860 finally:
Filip Vargabdd61492021-04-13 17:47:13 +02003861 self.pg7.unconfig()
3862 self.pg8.unconfig()
Filip Varga18f1e412020-12-03 15:27:40 +01003863
3864 self.vapi.ip_table_add_del(is_add=0,
3865 table={'table_id': new_vrf_id})
3866
3867 def test_next_src_nat(self):
3868 """ NAT44ED On way back forward packet to nat44-in2out node. """
3869
3870 twice_nat_addr = '10.0.1.3'
3871 external_port = 80
3872 local_port = 8080
3873 post_twice_nat_port = 0
3874
3875 self.vapi.nat44_forwarding_enable_disable(enable=1)
3876 self.nat_add_address(twice_nat_addr, twice_nat=1)
3877 flags = (self.config_flags.NAT_IS_OUT2IN_ONLY |
3878 self.config_flags.NAT_IS_SELF_TWICE_NAT)
3879 self.nat_add_static_mapping(self.pg6.remote_ip4, self.pg1.remote_ip4,
3880 local_port, external_port,
3881 proto=IP_PROTOS.tcp, vrf_id=1,
3882 flags=flags)
3883 self.vapi.nat44_interface_add_del_feature(
3884 sw_if_index=self.pg6.sw_if_index,
3885 is_add=1)
3886
3887 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
3888 IP(src=self.pg6.remote_ip4, dst=self.pg1.remote_ip4) /
3889 TCP(sport=12345, dport=external_port))
3890 self.pg6.add_stream(p)
3891 self.pg_enable_capture(self.pg_interfaces)
3892 self.pg_start()
3893 capture = self.pg6.get_capture(1)
3894 p = capture[0]
3895 try:
3896 ip = p[IP]
3897 tcp = p[TCP]
3898 self.assertEqual(ip.src, twice_nat_addr)
3899 self.assertNotEqual(tcp.sport, 12345)
3900 post_twice_nat_port = tcp.sport
3901 self.assertEqual(ip.dst, self.pg6.remote_ip4)
3902 self.assertEqual(tcp.dport, local_port)
3903 self.assert_packet_checksums_valid(p)
3904 except:
3905 self.logger.error(ppp("Unexpected or invalid packet:", p))
3906 raise
3907
3908 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
3909 IP(src=self.pg6.remote_ip4, dst=twice_nat_addr) /
3910 TCP(sport=local_port, dport=post_twice_nat_port))
3911 self.pg6.add_stream(p)
3912 self.pg_enable_capture(self.pg_interfaces)
3913 self.pg_start()
3914 capture = self.pg6.get_capture(1)
3915 p = capture[0]
3916 try:
3917 ip = p[IP]
3918 tcp = p[TCP]
3919 self.assertEqual(ip.src, self.pg1.remote_ip4)
3920 self.assertEqual(tcp.sport, external_port)
3921 self.assertEqual(ip.dst, self.pg6.remote_ip4)
3922 self.assertEqual(tcp.dport, 12345)
3923 self.assert_packet_checksums_valid(p)
3924 except:
3925 self.logger.error(ppp("Unexpected or invalid packet:", p))
3926 raise
3927
3928 def test_one_armed_nat44_static(self):
3929 """ NAT44ED One armed NAT and 1:1 NAPT asymmetrical rule """
3930
3931 remote_host = self.pg4.remote_hosts[0]
3932 local_host = self.pg4.remote_hosts[1]
3933 external_port = 80
3934 local_port = 8080
3935 eh_port_in = 0
3936
3937 self.vapi.nat44_forwarding_enable_disable(enable=1)
3938 self.nat_add_address(self.nat_addr, twice_nat=1)
3939 flags = (self.config_flags.NAT_IS_OUT2IN_ONLY |
3940 self.config_flags.NAT_IS_TWICE_NAT)
3941 self.nat_add_static_mapping(local_host.ip4, self.nat_addr,
3942 local_port, external_port,
3943 proto=IP_PROTOS.tcp, flags=flags)
3944 flags = self.config_flags.NAT_IS_INSIDE
3945 self.vapi.nat44_interface_add_del_feature(
3946 sw_if_index=self.pg4.sw_if_index,
3947 is_add=1)
3948 self.vapi.nat44_interface_add_del_feature(
3949 sw_if_index=self.pg4.sw_if_index,
3950 flags=flags, is_add=1)
3951
3952 # from client to service
3953 p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
3954 IP(src=remote_host.ip4, dst=self.nat_addr) /
3955 TCP(sport=12345, dport=external_port))
3956 self.pg4.add_stream(p)
3957 self.pg_enable_capture(self.pg_interfaces)
3958 self.pg_start()
3959 capture = self.pg4.get_capture(1)
3960 p = capture[0]
3961 try:
3962 ip = p[IP]
3963 tcp = p[TCP]
3964 self.assertEqual(ip.dst, local_host.ip4)
3965 self.assertEqual(ip.src, self.nat_addr)
3966 self.assertEqual(tcp.dport, local_port)
3967 self.assertNotEqual(tcp.sport, 12345)
3968 eh_port_in = tcp.sport
3969 self.assert_packet_checksums_valid(p)
3970 except:
3971 self.logger.error(ppp("Unexpected or invalid packet:", p))
3972 raise
3973
3974 # from service back to client
3975 p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
3976 IP(src=local_host.ip4, dst=self.nat_addr) /
3977 TCP(sport=local_port, dport=eh_port_in))
3978 self.pg4.add_stream(p)
3979 self.pg_enable_capture(self.pg_interfaces)
3980 self.pg_start()
3981 capture = self.pg4.get_capture(1)
3982 p = capture[0]
3983 try:
3984 ip = p[IP]
3985 tcp = p[TCP]
3986 self.assertEqual(ip.src, self.nat_addr)
3987 self.assertEqual(ip.dst, remote_host.ip4)
3988 self.assertEqual(tcp.sport, external_port)
3989 self.assertEqual(tcp.dport, 12345)
3990 self.assert_packet_checksums_valid(p)
3991 except:
3992 self.logger.error(ppp("Unexpected or invalid packet:", p))
3993 raise
3994
Matthew Smithad510752021-08-10 12:22:14 -05003995 def test_icmp_error_fwd_outbound(self):
3996 """ NAT44ED ICMP error outbound with forwarding enabled """
3997
3998 # Ensure that an outbound ICMP error message is properly associated
3999 # with the inbound forward bypass session it is related to.
4000 payload = "H" * 10
4001
4002 self.nat_add_address(self.nat_addr)
4003 self.nat_add_inside_interface(self.pg0)
4004 self.nat_add_outside_interface(self.pg1)
4005
4006 # enable forwarding and initiate connection out2in
4007 self.vapi.nat44_forwarding_enable_disable(enable=1)
4008 p1 = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4009 IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
4010 UDP(sport=21, dport=20) / payload)
4011
4012 self.pg1.add_stream(p1)
4013 self.pg_enable_capture(self.pg_interfaces)
4014 self.pg_start()
4015 capture = self.pg0.get_capture(1)[0]
4016
4017 self.logger.info(self.vapi.cli("show nat44 sessions"))
4018
4019 # reply with ICMP error message in2out
4020 # We cannot reliably retrieve forward bypass sessions via the API.
4021 # session dumps for a user will only look on the worker that the
4022 # user is supposed to be mapped to in2out. The forward bypass session
4023 # is not necessarily created on that worker.
4024 p2 = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4025 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4026 ICMP(type='dest-unreach', code='port-unreachable') /
4027 capture[IP:])
4028
4029 self.pg0.add_stream(p2)
4030 self.pg_enable_capture(self.pg_interfaces)
4031 self.pg_start()
4032 capture = self.pg1.get_capture(1)[0]
4033
4034 self.logger.info(self.vapi.cli("show nat44 sessions"))
4035
4036 self.logger.info(ppp("p1 packet:", p1))
4037 self.logger.info(ppp("p2 packet:", p2))
4038 self.logger.info(ppp("capture packet:", capture))
4039
Klement Sekera56c492a2022-01-10 21:57:27 +00004040 def test_tcp_session_open_retransmit1(self):
4041 """ NAT44ED Open TCP session with SYN,ACK retransmit 1
4042
4043 The client does not receive the [SYN,ACK] or the
4044 ACK from the client is lost. Therefore, the [SYN, ACK]
4045 is retransmitted by the server.
4046 """
4047
4048 in_port = self.tcp_port_in
4049 ext_port = self.tcp_external_port
4050 payload = "H" * 10
4051
4052 self.nat_add_address(self.nat_addr)
4053 self.nat_add_inside_interface(self.pg0)
4054 self.nat_add_outside_interface(self.pg1)
4055
4056 self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
4057 tcp_transitory=5, icmp=60)
4058 # SYN packet in->out
4059 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4060 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4061 TCP(sport=in_port, dport=ext_port, flags="S"))
4062 p = self.send_and_expect(self.pg0, p, self.pg1)[0]
4063 out_port = p[TCP].sport
4064
4065 # SYN + ACK packet out->in
4066 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4067 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4068 TCP(sport=ext_port, dport=out_port, flags="SA"))
4069 self.send_and_expect(self.pg1, p, self.pg0)
4070
4071 # ACK in->out does not arrive
4072
4073 # resent SYN + ACK packet out->in
4074 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4075 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4076 TCP(sport=ext_port, dport=out_port, flags="SA"))
4077 self.send_and_expect(self.pg1, p, self.pg0)
4078
4079 # ACK packet in->out
4080 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4081 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4082 TCP(sport=in_port, dport=ext_port, flags="A"))
4083 self.send_and_expect(self.pg0, p, self.pg1)
4084
4085 # Verify that the data can be transmitted after the transitory time
4086 self.virtual_sleep(6)
4087
4088 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4089 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4090 TCP(sport=in_port, dport=ext_port, flags="PA") /
4091 Raw(payload))
4092 self.send_and_expect(self.pg0, p, self.pg1)
4093
4094 def test_tcp_session_open_retransmit2(self):
4095 """ NAT44ED Open TCP session with SYN,ACK retransmit 2
4096
4097 The ACK is lost to the server after the TCP session is opened.
4098 Data is sent by the client, then the [SYN,ACK] is
4099 retransmitted by the server.
4100 """
4101
4102 in_port = self.tcp_port_in
4103 ext_port = self.tcp_external_port
4104 payload = "H" * 10
4105
4106 self.nat_add_address(self.nat_addr)
4107 self.nat_add_inside_interface(self.pg0)
4108 self.nat_add_outside_interface(self.pg1)
4109
4110 self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
4111 tcp_transitory=5, icmp=60)
4112 # SYN packet in->out
4113 p = (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="S"))
4116 p = self.send_and_expect(self.pg0, p, self.pg1)[0]
4117 out_port = p[TCP].sport
4118
4119 # SYN + ACK packet out->in
4120 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4121 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4122 TCP(sport=ext_port, dport=out_port, flags="SA"))
4123 self.send_and_expect(self.pg1, p, self.pg0)
4124
4125 # ACK packet in->out -- not received by the server
4126 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4127 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4128 TCP(sport=in_port, dport=ext_port, flags="A"))
4129 self.send_and_expect(self.pg0, p, self.pg1)
4130
4131 # PUSH + ACK packet in->out
4132 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4133 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4134 TCP(sport=in_port, dport=ext_port, flags="PA") /
4135 Raw(payload))
4136 self.send_and_expect(self.pg0, p, self.pg1)
4137
4138 # resent SYN + ACK packet out->in
4139 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4140 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4141 TCP(sport=ext_port, dport=out_port, flags="SA"))
4142 self.send_and_expect(self.pg1, p, self.pg0)
4143
4144 # resent ACK packet in->out
4145 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4146 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4147 TCP(sport=in_port, dport=ext_port, flags="A"))
4148 self.send_and_expect(self.pg0, p, self.pg1)
4149
4150 # resent PUSH + ACK packet in->out
4151 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4152 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4153 TCP(sport=in_port, dport=ext_port, flags="PA") /
4154 Raw(payload))
4155 self.send_and_expect(self.pg0, p, self.pg1)
4156
4157 # ACK packet out->in
4158 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4159 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4160 TCP(sport=ext_port, dport=out_port, flags="A"))
4161 self.send_and_expect(self.pg1, p, self.pg0)
4162
4163 # Verify that the data can be transmitted after the transitory time
4164 self.virtual_sleep(6)
4165
4166 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4167 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4168 TCP(sport=in_port, dport=ext_port, flags="PA") /
4169 Raw(payload))
4170 self.send_and_expect(self.pg0, p, self.pg1)
4171
Filip Varga18f1e412020-12-03 15:27:40 +01004172
4173if __name__ == '__main__':
4174 unittest.main(testRunner=VppTestRunner)