blob: f172dabe98b6151d89c3b35bb5414a9a97af03b5 [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
2612 # state anyway. RST followed by a data packet should keep it
2613 # established.
2614 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
2627 # State is established, session should be still open after 6 seconds
2628 self.virtual_sleep(6)
2629
Filip Varga18f1e412020-12-03 15:27:40 +01002630 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
2631 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Klement Sekera56c492a2022-01-10 21:57:27 +00002632 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
2633 flags="R"))
2634 self.send_and_expect(self.pg0, p, self.pg1)
2635
2636 # State is transitory, session should be closed after 6 seconds
2637 self.virtual_sleep(6)
2638
2639 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
2640 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2641 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
2642 flags="P"))
2643 self.send_and_assert_no_replies(self.pg0, p, self.pg1)
Filip Varga18f1e412020-12-03 15:27:40 +01002644
2645 def test_dynamic_out_of_ports(self):
2646 """ NAT44ED dynamic translation test: out of ports """
2647
2648 self.nat_add_inside_interface(self.pg0)
2649 self.nat_add_outside_interface(self.pg1)
2650
2651 # in2out and no NAT addresses added
Filip Varga18f1e412020-12-03 15:27:40 +01002652 pkts = self.create_stream_in(self.pg0, self.pg1)
Filip Varga18f1e412020-12-03 15:27:40 +01002653
Klement Sekeraad3187f2022-02-18 10:34:35 +00002654 self.send_and_assert_no_replies(
2655 self.pg0, pkts, msg="i2o pkts",
2656 stats_diff=self.no_diff | {
2657 "err": {
2658 '/err/nat44-ed-in2out-slowpath/out of ports': len(pkts),
2659 },
2660 self.pg0.sw_if_index: {
2661 '/nat44-ed/in2out/slowpath/drops': len(pkts),
2662 },
2663 }
2664 )
Filip Varga18f1e412020-12-03 15:27:40 +01002665
2666 # in2out after NAT addresses added
2667 self.nat_add_address(self.nat_addr)
2668
Klement Sekeraad3187f2022-02-18 10:34:35 +00002669 tcpn, udpn, icmpn = (sum(x) for x in
2670 zip(*((TCP in p, UDP in p, ICMP in p)
2671 for p in pkts)))
Filip Varga18f1e412020-12-03 15:27:40 +01002672
Klement Sekeraad3187f2022-02-18 10:34:35 +00002673 self.send_and_expect(
2674 self.pg0, pkts, self.pg1, msg="i2o pkts",
2675 stats_diff=self.no_diff | {
2676 "err": {
2677 '/err/nat44-ed-in2out-slowpath/out of ports': 0,
2678 },
2679 self.pg0.sw_if_index: {
2680 '/nat44-ed/in2out/slowpath/drops': 0,
2681 '/nat44-ed/in2out/slowpath/tcp': tcpn,
2682 '/nat44-ed/in2out/slowpath/udp': udpn,
2683 '/nat44-ed/in2out/slowpath/icmp': icmpn,
2684 },
2685 }
2686 )
Filip Varga18f1e412020-12-03 15:27:40 +01002687
2688 def test_unknown_proto(self):
2689 """ NAT44ED translate packet with unknown protocol """
2690
2691 self.nat_add_address(self.nat_addr)
2692 self.nat_add_inside_interface(self.pg0)
2693 self.nat_add_outside_interface(self.pg1)
2694
2695 # in2out
2696 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2697 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2698 TCP(sport=self.tcp_port_in, dport=20))
2699 self.pg0.add_stream(p)
2700 self.pg_enable_capture(self.pg_interfaces)
2701 self.pg_start()
2702 p = self.pg1.get_capture(1)
2703
2704 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2705 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2706 GRE() /
2707 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
2708 TCP(sport=1234, dport=1234))
2709 self.pg0.add_stream(p)
2710 self.pg_enable_capture(self.pg_interfaces)
2711 self.pg_start()
2712 p = self.pg1.get_capture(1)
2713 packet = p[0]
2714 try:
2715 self.assertEqual(packet[IP].src, self.nat_addr)
2716 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
2717 self.assertEqual(packet.haslayer(GRE), 1)
2718 self.assert_packet_checksums_valid(packet)
2719 except:
2720 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2721 raise
2722
2723 # out2in
2724 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
2725 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
2726 GRE() /
2727 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
2728 TCP(sport=1234, dport=1234))
2729 self.pg1.add_stream(p)
2730 self.pg_enable_capture(self.pg_interfaces)
2731 self.pg_start()
2732 p = self.pg0.get_capture(1)
2733 packet = p[0]
2734 try:
2735 self.assertEqual(packet[IP].src, self.pg1.remote_ip4)
2736 self.assertEqual(packet[IP].dst, self.pg0.remote_ip4)
2737 self.assertEqual(packet.haslayer(GRE), 1)
2738 self.assert_packet_checksums_valid(packet)
2739 except:
2740 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2741 raise
2742
2743 def test_hairpinning_unknown_proto(self):
2744 """ NAT44ED translate packet with unknown protocol - hairpinning """
2745 host = self.pg0.remote_hosts[0]
2746 server = self.pg0.remote_hosts[1]
2747 host_in_port = 1234
2748 server_out_port = 8765
2749 server_nat_ip = "10.0.0.11"
2750
2751 self.nat_add_address(self.nat_addr)
2752 self.nat_add_inside_interface(self.pg0)
2753 self.nat_add_outside_interface(self.pg1)
2754
2755 # add static mapping for server
2756 self.nat_add_static_mapping(server.ip4, server_nat_ip)
2757
2758 # host to server
2759 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
2760 IP(src=host.ip4, dst=server_nat_ip) /
2761 TCP(sport=host_in_port, dport=server_out_port))
2762 self.pg0.add_stream(p)
2763 self.pg_enable_capture(self.pg_interfaces)
2764 self.pg_start()
2765 self.pg0.get_capture(1)
2766
2767 p = (Ether(dst=self.pg0.local_mac, src=host.mac) /
2768 IP(src=host.ip4, dst=server_nat_ip) /
2769 GRE() /
2770 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
2771 TCP(sport=1234, dport=1234))
2772 self.pg0.add_stream(p)
2773 self.pg_enable_capture(self.pg_interfaces)
2774 self.pg_start()
2775 p = self.pg0.get_capture(1)
2776 packet = p[0]
2777 try:
2778 self.assertEqual(packet[IP].src, self.nat_addr)
2779 self.assertEqual(packet[IP].dst, server.ip4)
2780 self.assertEqual(packet.haslayer(GRE), 1)
2781 self.assert_packet_checksums_valid(packet)
2782 except:
2783 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2784 raise
2785
2786 # server to host
2787 p = (Ether(dst=self.pg0.local_mac, src=server.mac) /
2788 IP(src=server.ip4, dst=self.nat_addr) /
2789 GRE() /
2790 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
2791 TCP(sport=1234, dport=1234))
2792 self.pg0.add_stream(p)
2793 self.pg_enable_capture(self.pg_interfaces)
2794 self.pg_start()
2795 p = self.pg0.get_capture(1)
2796 packet = p[0]
2797 try:
2798 self.assertEqual(packet[IP].src, server_nat_ip)
2799 self.assertEqual(packet[IP].dst, host.ip4)
2800 self.assertEqual(packet.haslayer(GRE), 1)
2801 self.assert_packet_checksums_valid(packet)
2802 except:
2803 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2804 raise
2805
2806 def test_output_feature_and_service(self):
2807 """ NAT44ED interface output feature and services """
2808 external_addr = '1.2.3.4'
2809 external_port = 80
2810 local_port = 8080
2811
2812 self.vapi.nat44_forwarding_enable_disable(enable=1)
2813 self.nat_add_address(self.nat_addr)
2814 flags = self.config_flags.NAT_IS_ADDR_ONLY
2815 self.vapi.nat44_add_del_identity_mapping(
2816 ip_address=self.pg1.remote_ip4, sw_if_index=0xFFFFFFFF,
2817 flags=flags, is_add=1)
2818 flags = self.config_flags.NAT_IS_OUT2IN_ONLY
2819 self.nat_add_static_mapping(self.pg0.remote_ip4, external_addr,
2820 local_port, external_port,
2821 proto=IP_PROTOS.tcp, flags=flags)
2822
2823 self.nat_add_inside_interface(self.pg0)
2824 self.nat_add_outside_interface(self.pg0)
Filip Varga9c25eb12021-10-21 13:00:27 +02002825 self.vapi.nat44_ed_add_del_output_interface(
Filip Varga18f1e412020-12-03 15:27:40 +01002826 sw_if_index=self.pg1.sw_if_index, is_add=1)
2827
2828 # from client to service
2829 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
2830 IP(src=self.pg1.remote_ip4, dst=external_addr) /
2831 TCP(sport=12345, dport=external_port))
2832 self.pg1.add_stream(p)
2833 self.pg_enable_capture(self.pg_interfaces)
2834 self.pg_start()
2835 capture = self.pg0.get_capture(1)
2836 p = capture[0]
2837 try:
2838 ip = p[IP]
2839 tcp = p[TCP]
2840 self.assertEqual(ip.dst, self.pg0.remote_ip4)
2841 self.assertEqual(tcp.dport, local_port)
2842 self.assert_packet_checksums_valid(p)
2843 except:
2844 self.logger.error(ppp("Unexpected or invalid packet:", p))
2845 raise
2846
2847 # from service back to client
2848 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
2849 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2850 TCP(sport=local_port, dport=12345))
2851 self.pg0.add_stream(p)
2852 self.pg_enable_capture(self.pg_interfaces)
2853 self.pg_start()
2854 capture = self.pg1.get_capture(1)
2855 p = capture[0]
2856 try:
2857 ip = p[IP]
2858 tcp = p[TCP]
2859 self.assertEqual(ip.src, external_addr)
2860 self.assertEqual(tcp.sport, external_port)
2861 self.assert_packet_checksums_valid(p)
2862 except:
2863 self.logger.error(ppp("Unexpected or invalid packet:", p))
2864 raise
2865
2866 # from local network host to external network
2867 pkts = self.create_stream_in(self.pg0, self.pg1)
2868 self.pg0.add_stream(pkts)
2869 self.pg_enable_capture(self.pg_interfaces)
2870 self.pg_start()
2871 capture = self.pg1.get_capture(len(pkts))
2872 self.verify_capture_out(capture, ignore_port=True)
2873 pkts = self.create_stream_in(self.pg0, self.pg1)
2874 self.pg0.add_stream(pkts)
2875 self.pg_enable_capture(self.pg_interfaces)
2876 self.pg_start()
2877 capture = self.pg1.get_capture(len(pkts))
2878 self.verify_capture_out(capture, ignore_port=True)
2879
2880 # from external network back to local network host
2881 pkts = self.create_stream_out(self.pg1)
2882 self.pg1.add_stream(pkts)
2883 self.pg_enable_capture(self.pg_interfaces)
2884 self.pg_start()
2885 capture = self.pg0.get_capture(len(pkts))
2886 self.verify_capture_in(capture, self.pg0)
2887
2888 def test_output_feature_and_service3(self):
2889 """ NAT44ED interface output feature and DST NAT """
2890 external_addr = '1.2.3.4'
2891 external_port = 80
2892 local_port = 8080
2893
2894 self.vapi.nat44_forwarding_enable_disable(enable=1)
2895 self.nat_add_address(self.nat_addr)
2896 flags = self.config_flags.NAT_IS_OUT2IN_ONLY
2897 self.nat_add_static_mapping(self.pg1.remote_ip4, external_addr,
2898 local_port, external_port,
2899 proto=IP_PROTOS.tcp, flags=flags)
2900
2901 self.nat_add_inside_interface(self.pg0)
2902 self.nat_add_outside_interface(self.pg0)
Filip Varga9c25eb12021-10-21 13:00:27 +02002903 self.vapi.nat44_ed_add_del_output_interface(
Filip Varga18f1e412020-12-03 15:27:40 +01002904 sw_if_index=self.pg1.sw_if_index, is_add=1)
2905
2906 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
2907 IP(src=self.pg0.remote_ip4, dst=external_addr) /
2908 TCP(sport=12345, dport=external_port))
2909 self.pg0.add_stream(p)
2910 self.pg_enable_capture(self.pg_interfaces)
2911 self.pg_start()
2912 capture = self.pg1.get_capture(1)
2913 p = capture[0]
2914 try:
2915 ip = p[IP]
2916 tcp = p[TCP]
2917 self.assertEqual(ip.src, self.pg0.remote_ip4)
2918 self.assertEqual(tcp.sport, 12345)
2919 self.assertEqual(ip.dst, self.pg1.remote_ip4)
2920 self.assertEqual(tcp.dport, local_port)
2921 self.assert_packet_checksums_valid(p)
2922 except:
2923 self.logger.error(ppp("Unexpected or invalid packet:", p))
2924 raise
2925
2926 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
2927 IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
2928 TCP(sport=local_port, dport=12345))
2929 self.pg1.add_stream(p)
2930 self.pg_enable_capture(self.pg_interfaces)
2931 self.pg_start()
2932 capture = self.pg0.get_capture(1)
2933 p = capture[0]
2934 try:
2935 ip = p[IP]
2936 tcp = p[TCP]
2937 self.assertEqual(ip.src, external_addr)
2938 self.assertEqual(tcp.sport, external_port)
2939 self.assertEqual(ip.dst, self.pg0.remote_ip4)
2940 self.assertEqual(tcp.dport, 12345)
2941 self.assert_packet_checksums_valid(p)
2942 except:
2943 self.logger.error(ppp("Unexpected or invalid packet:", p))
2944 raise
2945
2946 def test_self_twice_nat_lb_negative(self):
2947 """ NAT44ED Self Twice NAT local service load balancing (negative test)
2948 """
2949 self.twice_nat_common(lb=True, self_twice_nat=True, same_pg=True,
2950 client_id=2)
2951
2952 def test_self_twice_nat_negative(self):
2953 """ NAT44ED Self Twice NAT (negative test) """
2954 self.twice_nat_common(self_twice_nat=True)
2955
2956 def test_static_lb_multi_clients(self):
2957 """ NAT44ED local service load balancing - multiple clients"""
2958
2959 external_addr = self.nat_addr
2960 external_port = 80
2961 local_port = 8080
2962 server1 = self.pg0.remote_hosts[0]
2963 server2 = self.pg0.remote_hosts[1]
2964 server3 = self.pg0.remote_hosts[2]
2965
2966 locals = [{'addr': server1.ip4,
2967 'port': local_port,
2968 'probability': 90,
2969 'vrf_id': 0},
2970 {'addr': server2.ip4,
2971 'port': local_port,
2972 'probability': 10,
2973 'vrf_id': 0}]
2974
2975 flags = self.config_flags.NAT_IS_INSIDE
2976 self.vapi.nat44_interface_add_del_feature(
2977 sw_if_index=self.pg0.sw_if_index,
2978 flags=flags, is_add=1)
2979 self.vapi.nat44_interface_add_del_feature(
2980 sw_if_index=self.pg1.sw_if_index,
2981 is_add=1)
2982
2983 self.nat_add_address(self.nat_addr)
2984 self.vapi.nat44_add_del_lb_static_mapping(is_add=1,
2985 external_addr=external_addr,
2986 external_port=external_port,
2987 protocol=IP_PROTOS.tcp,
2988 local_num=len(locals),
2989 locals=locals)
2990
2991 server1_n = 0
2992 server2_n = 0
2993 clients = ip4_range(self.pg1.remote_ip4, 10, 50)
2994 pkts = []
2995 for client in clients:
2996 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
2997 IP(src=client, dst=self.nat_addr) /
2998 TCP(sport=12345, dport=external_port))
2999 pkts.append(p)
3000 self.pg1.add_stream(pkts)
3001 self.pg_enable_capture(self.pg_interfaces)
3002 self.pg_start()
3003 capture = self.pg0.get_capture(len(pkts))
3004 for p in capture:
3005 if p[IP].dst == server1.ip4:
3006 server1_n += 1
3007 else:
3008 server2_n += 1
Klement Sekera1fbf0342021-03-31 13:38:09 +02003009 self.assertGreaterEqual(server1_n, server2_n)
Filip Varga18f1e412020-12-03 15:27:40 +01003010
3011 local = {
3012 'addr': server3.ip4,
3013 'port': local_port,
3014 'probability': 20,
3015 'vrf_id': 0
3016 }
3017
3018 # add new back-end
3019 self.vapi.nat44_lb_static_mapping_add_del_local(
3020 is_add=1,
3021 external_addr=external_addr,
3022 external_port=external_port,
3023 local=local,
3024 protocol=IP_PROTOS.tcp)
3025 server1_n = 0
3026 server2_n = 0
3027 server3_n = 0
3028 clients = ip4_range(self.pg1.remote_ip4, 60, 110)
3029 pkts = []
3030 for client in clients:
3031 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3032 IP(src=client, dst=self.nat_addr) /
3033 TCP(sport=12346, dport=external_port))
3034 pkts.append(p)
3035 self.assertGreater(len(pkts), 0)
3036 self.pg1.add_stream(pkts)
3037 self.pg_enable_capture(self.pg_interfaces)
3038 self.pg_start()
3039 capture = self.pg0.get_capture(len(pkts))
3040 for p in capture:
3041 if p[IP].dst == server1.ip4:
3042 server1_n += 1
3043 elif p[IP].dst == server2.ip4:
3044 server2_n += 1
3045 else:
3046 server3_n += 1
3047 self.assertGreater(server1_n, 0)
3048 self.assertGreater(server2_n, 0)
3049 self.assertGreater(server3_n, 0)
3050
3051 local = {
3052 'addr': server2.ip4,
3053 'port': local_port,
3054 'probability': 10,
3055 'vrf_id': 0
3056 }
3057
3058 # remove one back-end
3059 self.vapi.nat44_lb_static_mapping_add_del_local(
3060 is_add=0,
3061 external_addr=external_addr,
3062 external_port=external_port,
3063 local=local,
3064 protocol=IP_PROTOS.tcp)
3065 server1_n = 0
3066 server2_n = 0
3067 server3_n = 0
3068 self.pg1.add_stream(pkts)
3069 self.pg_enable_capture(self.pg_interfaces)
3070 self.pg_start()
3071 capture = self.pg0.get_capture(len(pkts))
3072 for p in capture:
3073 if p[IP].dst == server1.ip4:
3074 server1_n += 1
3075 elif p[IP].dst == server2.ip4:
3076 server2_n += 1
3077 else:
3078 server3_n += 1
3079 self.assertGreater(server1_n, 0)
3080 self.assertEqual(server2_n, 0)
3081 self.assertGreater(server3_n, 0)
3082
Klement Sekera56c492a2022-01-10 21:57:27 +00003083 # put zzz in front of syslog test name so that it runs as a last test
3084 # setting syslog sender cannot be undone and if it is set, it messes
3085 # with self.send_and_assert_no_replies functionality
3086 def test_zzz_syslog_sess(self):
Filip Varga18f1e412020-12-03 15:27:40 +01003087 """ NAT44ED Test syslog session creation and deletion """
3088 self.vapi.syslog_set_filter(
3089 self.syslog_severity.SYSLOG_API_SEVERITY_INFO)
3090 self.vapi.syslog_set_sender(self.pg3.local_ip4, self.pg3.remote_ip4)
3091
3092 self.nat_add_address(self.nat_addr)
3093 self.nat_add_inside_interface(self.pg0)
3094 self.nat_add_outside_interface(self.pg1)
3095
3096 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3097 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3098 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port))
3099 self.pg0.add_stream(p)
3100 self.pg_enable_capture(self.pg_interfaces)
3101 self.pg_start()
3102 capture = self.pg1.get_capture(1)
3103 self.tcp_port_out = capture[0][TCP].sport
3104 capture = self.pg3.get_capture(1)
Klement Sekera56c492a2022-01-10 21:57:27 +00003105 self.verify_syslog_sess(capture[0][Raw].load, 'SADD')
Filip Varga18f1e412020-12-03 15:27:40 +01003106
3107 self.pg_enable_capture(self.pg_interfaces)
3108 self.pg_start()
3109 self.nat_add_address(self.nat_addr, is_add=0)
3110 capture = self.pg3.get_capture(1)
Klement Sekera56c492a2022-01-10 21:57:27 +00003111 self.verify_syslog_sess(capture[0][Raw].load, 'SDEL')
3112
3113 # put zzz in front of syslog test name so that it runs as a last test
3114 # setting syslog sender cannot be undone and if it is set, it messes
3115 # with self.send_and_assert_no_replies functionality
3116 def test_zzz_syslog_sess_reopen(self):
3117 """ Syslog events for session reopen """
3118 self.vapi.syslog_set_filter(
3119 self.syslog_severity.SYSLOG_API_SEVERITY_INFO)
3120 self.vapi.syslog_set_sender(self.pg3.local_ip4, self.pg3.remote_ip4)
3121
3122 self.nat_add_address(self.nat_addr)
3123 self.nat_add_inside_interface(self.pg0)
3124 self.nat_add_outside_interface(self.pg1)
3125
3126 # SYN in2out
3127 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3128 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3129 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port))
3130 capture = self.send_and_expect(self.pg0, p, self.pg1)[0]
3131 self.tcp_port_out = capture[0][TCP].sport
3132 capture = self.pg3.get_capture(1)
3133 self.verify_syslog_sess(capture[0][Raw].load, 'SADD')
3134
3135 # SYN out2in
3136 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
3137 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3138 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out))
3139 self.send_and_expect(self.pg1, p, self.pg0)
3140
3141 # FIN in2out
3142 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3143 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3144 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
3145 flags="F"))
3146 self.send_and_expect(self.pg0, p, self.pg1)
3147
3148 # FIN out2in
3149 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
3150 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3151 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
3152 flags="F"))
3153 self.send_and_expect(self.pg1, p, self.pg0)
3154
3155 # SYN in2out
3156 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3157 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3158 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port))
3159 self.send_and_expect(self.pg0, p, self.pg1)
3160
3161 # SYN out2in
3162 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
3163 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3164 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out))
3165 self.send_and_expect(self.pg1, p, self.pg0)
3166
3167 # 2 records should be produced - first one del & add
3168 capture = self.pg3.get_capture(2)
3169 self.verify_syslog_sess(capture[0][Raw].load, 'SDEL')
3170 self.verify_syslog_sess(capture[1][Raw].load, 'SADD')
Filip Varga18f1e412020-12-03 15:27:40 +01003171
3172 def test_twice_nat_interface_addr(self):
3173 """ NAT44ED Acquire twice NAT addresses from interface """
3174 flags = self.config_flags.NAT_IS_TWICE_NAT
3175 self.vapi.nat44_add_del_interface_addr(
3176 sw_if_index=self.pg11.sw_if_index,
3177 flags=flags, is_add=1)
3178
3179 # no address in NAT pool
3180 adresses = self.vapi.nat44_address_dump()
3181 self.assertEqual(0, len(adresses))
3182
3183 # configure interface address and check NAT address pool
3184 self.pg11.config_ip4()
3185 adresses = self.vapi.nat44_address_dump()
3186 self.assertEqual(1, len(adresses))
3187 self.assertEqual(str(adresses[0].ip_address),
3188 self.pg11.local_ip4)
3189 self.assertEqual(adresses[0].flags, flags)
3190
3191 # remove interface address and check NAT address pool
3192 self.pg11.unconfig_ip4()
3193 adresses = self.vapi.nat44_address_dump()
3194 self.assertEqual(0, len(adresses))
3195
3196 def test_output_feature_stateful_acl(self):
3197 """ NAT44ED output feature works with stateful ACL """
3198
3199 self.nat_add_address(self.nat_addr)
Filip Varga9c25eb12021-10-21 13:00:27 +02003200 self.vapi.nat44_ed_add_del_output_interface(
Filip Varga63e15812021-06-29 14:28:21 +02003201 sw_if_index=self.pg1.sw_if_index, is_add=1)
Filip Varga18f1e412020-12-03 15:27:40 +01003202
3203 # First ensure that the NAT is working sans ACL
3204
3205 # send packets out2in, no sessions yet so packets should drop
3206 pkts_out2in = self.create_stream_out(self.pg1)
3207 self.send_and_assert_no_replies(self.pg1, pkts_out2in)
3208
3209 # send packets into inside intf, ensure received via outside intf
3210 pkts_in2out = self.create_stream_in(self.pg0, self.pg1)
3211 capture = self.send_and_expect(self.pg0, pkts_in2out, self.pg1,
3212 len(pkts_in2out))
3213 self.verify_capture_out(capture, ignore_port=True)
3214
3215 # send out2in again, with sessions created it should work now
3216 pkts_out2in = self.create_stream_out(self.pg1)
3217 capture = self.send_and_expect(self.pg1, pkts_out2in, self.pg0,
3218 len(pkts_out2in))
3219 self.verify_capture_in(capture, self.pg0)
3220
3221 # Create an ACL blocking everything
3222 out2in_deny_rule = AclRule(is_permit=0)
3223 out2in_acl = VppAcl(self, rules=[out2in_deny_rule])
3224 out2in_acl.add_vpp_config()
3225
3226 # create an ACL to permit/reflect everything
3227 in2out_reflect_rule = AclRule(is_permit=2)
3228 in2out_acl = VppAcl(self, rules=[in2out_reflect_rule])
3229 in2out_acl.add_vpp_config()
3230
3231 # apply as input acl on interface and confirm it blocks everything
3232 acl_if = VppAclInterface(self, sw_if_index=self.pg1.sw_if_index,
3233 n_input=1, acls=[out2in_acl])
3234 acl_if.add_vpp_config()
3235 self.send_and_assert_no_replies(self.pg1, pkts_out2in)
3236
3237 # apply output acl
3238 acl_if.acls = [out2in_acl, in2out_acl]
3239 acl_if.add_vpp_config()
3240 # send in2out to generate ACL state (NAT state was created earlier)
3241 capture = self.send_and_expect(self.pg0, pkts_in2out, self.pg1,
3242 len(pkts_in2out))
3243 self.verify_capture_out(capture, ignore_port=True)
3244
3245 # send out2in again. ACL state exists so it should work now.
3246 # TCP packets with the syn flag set also need the ack flag
3247 for p in pkts_out2in:
3248 if p.haslayer(TCP) and p[TCP].flags & 0x02:
3249 p[TCP].flags |= 0x10
3250 capture = self.send_and_expect(self.pg1, pkts_out2in, self.pg0,
3251 len(pkts_out2in))
3252 self.verify_capture_in(capture, self.pg0)
3253 self.logger.info(self.vapi.cli("show trace"))
3254
3255 def test_tcp_close(self):
3256 """ NAT44ED Close TCP session from inside network - output feature """
Filip Vargab6810822022-02-15 11:56:07 -08003257 config = self.vapi.nat44_show_running_config()
3258 old_timeouts = config.timeouts
Filip Varga18f1e412020-12-03 15:27:40 +01003259 new_transitory = 2
3260 self.vapi.nat_set_timeouts(
3261 udp=old_timeouts.udp,
3262 tcp_established=old_timeouts.tcp_established,
3263 icmp=old_timeouts.icmp,
3264 tcp_transitory=new_transitory)
3265
3266 self.vapi.nat44_forwarding_enable_disable(enable=1)
3267 self.nat_add_address(self.pg1.local_ip4)
3268 twice_nat_addr = '10.0.1.3'
3269 service_ip = '192.168.16.150'
3270 self.nat_add_address(twice_nat_addr, twice_nat=1)
3271
3272 flags = self.config_flags.NAT_IS_INSIDE
3273 self.vapi.nat44_interface_add_del_feature(
3274 sw_if_index=self.pg0.sw_if_index,
3275 is_add=1)
3276 self.vapi.nat44_interface_add_del_feature(
3277 sw_if_index=self.pg0.sw_if_index,
3278 flags=flags, is_add=1)
Filip Varga9c25eb12021-10-21 13:00:27 +02003279 self.vapi.nat44_ed_add_del_output_interface(
Filip Varga18f1e412020-12-03 15:27:40 +01003280 is_add=1,
3281 sw_if_index=self.pg1.sw_if_index)
3282
3283 flags = (self.config_flags.NAT_IS_OUT2IN_ONLY |
3284 self.config_flags.NAT_IS_TWICE_NAT)
3285 self.nat_add_static_mapping(self.pg0.remote_ip4,
3286 service_ip, 80, 80,
3287 proto=IP_PROTOS.tcp,
3288 flags=flags)
3289 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3290 start_sessnum = len(sessions)
3291
3292 # SYN packet out->in
3293 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3294 IP(src=self.pg1.remote_ip4, dst=service_ip) /
3295 TCP(sport=33898, dport=80, flags="S"))
Klement Sekera56c492a2022-01-10 21:57:27 +00003296 capture = self.send_and_expect(self.pg1, p, self.pg0, n_rx=1)
Filip Varga18f1e412020-12-03 15:27:40 +01003297 p = capture[0]
3298 tcp_port = p[TCP].sport
3299
3300 # SYN + ACK packet in->out
3301 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3302 IP(src=self.pg0.remote_ip4, dst=twice_nat_addr) /
3303 TCP(sport=80, dport=tcp_port, flags="SA"))
Klement Sekera56c492a2022-01-10 21:57:27 +00003304 self.send_and_expect(self.pg0, p, self.pg1, n_rx=1)
Filip Varga18f1e412020-12-03 15:27:40 +01003305
3306 # ACK packet out->in
3307 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3308 IP(src=self.pg1.remote_ip4, dst=service_ip) /
3309 TCP(sport=33898, dport=80, flags="A"))
Klement Sekera56c492a2022-01-10 21:57:27 +00003310 self.send_and_expect(self.pg1, p, self.pg0, n_rx=1)
Filip Varga18f1e412020-12-03 15:27:40 +01003311
3312 # FIN packet in -> out
3313 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3314 IP(src=self.pg0.remote_ip4, dst=twice_nat_addr) /
3315 TCP(sport=80, dport=tcp_port, flags="FA", seq=100, ack=300))
Klement Sekera56c492a2022-01-10 21:57:27 +00003316 self.send_and_expect(self.pg0, p, self.pg1, n_rx=1)
Filip Varga18f1e412020-12-03 15:27:40 +01003317
3318 # FIN+ACK packet out -> in
3319 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3320 IP(src=self.pg1.remote_ip4, dst=service_ip) /
3321 TCP(sport=33898, dport=80, flags="FA", seq=300, ack=101))
Klement Sekera56c492a2022-01-10 21:57:27 +00003322 self.send_and_expect(self.pg1, p, self.pg0, n_rx=1)
Filip Varga18f1e412020-12-03 15:27:40 +01003323
3324 # ACK packet in -> out
3325 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3326 IP(src=self.pg0.remote_ip4, dst=twice_nat_addr) /
3327 TCP(sport=80, dport=tcp_port, flags="A", seq=101, ack=301))
Klement Sekera56c492a2022-01-10 21:57:27 +00003328 self.send_and_expect(self.pg0, p, self.pg1, n_rx=1)
Filip Varga18f1e412020-12-03 15:27:40 +01003329
Klement Sekera56c492a2022-01-10 21:57:27 +00003330 # session now in transitory timeout, but traffic still flows
3331 # try FIN packet out->in
Filip Varga18f1e412020-12-03 15:27:40 +01003332 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3333 IP(src=self.pg1.remote_ip4, dst=service_ip) /
Klement Sekera56c492a2022-01-10 21:57:27 +00003334 TCP(sport=33898, dport=80, flags="F"))
Filip Varga18f1e412020-12-03 15:27:40 +01003335 self.pg1.add_stream(p)
3336 self.pg_enable_capture(self.pg_interfaces)
3337 self.pg_start()
3338
Benoît Ganne56eccdb2021-08-20 09:18:31 +02003339 self.virtual_sleep(new_transitory, "wait for transitory timeout")
Klement Sekera56c492a2022-01-10 21:57:27 +00003340 self.pg0.get_capture(1)
Filip Varga18f1e412020-12-03 15:27:40 +01003341
3342 # session should still exist
3343 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3344 self.assertEqual(len(sessions) - start_sessnum, 1)
3345
3346 # send FIN+ACK packet out -> in - will cause session to be wiped
3347 # but won't create a new session
3348 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3349 IP(src=self.pg1.remote_ip4, dst=service_ip) /
3350 TCP(sport=33898, dport=80, flags="FA", seq=300, ack=101))
Klement Sekera56c492a2022-01-10 21:57:27 +00003351 self.send_and_assert_no_replies(self.pg1, p)
Filip Varga18f1e412020-12-03 15:27:40 +01003352 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3353 self.assertEqual(len(sessions) - start_sessnum, 0)
Filip Varga18f1e412020-12-03 15:27:40 +01003354
3355 def test_tcp_session_close_in(self):
3356 """ NAT44ED Close TCP session from inside network """
3357
3358 in_port = self.tcp_port_in
3359 out_port = 10505
3360 ext_port = self.tcp_external_port
3361
3362 self.nat_add_address(self.nat_addr)
3363 self.nat_add_inside_interface(self.pg0)
3364 self.nat_add_outside_interface(self.pg1)
3365 self.nat_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
3366 in_port, out_port, proto=IP_PROTOS.tcp,
3367 flags=self.config_flags.NAT_IS_TWICE_NAT)
3368
3369 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3370 session_n = len(sessions)
3371
3372 self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
3373 tcp_transitory=2, icmp=5)
3374
3375 self.init_tcp_session(self.pg0, self.pg1, in_port, ext_port)
3376
3377 # FIN packet in -> out
3378 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3379 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3380 TCP(sport=in_port, dport=ext_port,
3381 flags="FA", seq=100, ack=300))
Klement Sekera56c492a2022-01-10 21:57:27 +00003382 self.send_and_expect(self.pg0, p, self.pg1)
Filip Varga18f1e412020-12-03 15:27:40 +01003383 pkts = []
3384
3385 # ACK packet out -> in
3386 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3387 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3388 TCP(sport=ext_port, dport=out_port,
3389 flags="A", seq=300, ack=101))
3390 pkts.append(p)
3391
3392 # FIN packet out -> in
3393 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3394 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3395 TCP(sport=ext_port, dport=out_port,
3396 flags="FA", seq=300, ack=101))
3397 pkts.append(p)
3398
Klement Sekera56c492a2022-01-10 21:57:27 +00003399 self.send_and_expect(self.pg1, pkts, self.pg0)
Filip Varga18f1e412020-12-03 15:27:40 +01003400
3401 # ACK packet in -> out
3402 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3403 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3404 TCP(sport=in_port, dport=ext_port,
3405 flags="A", seq=101, ack=301))
Klement Sekera56c492a2022-01-10 21:57:27 +00003406 self.send_and_expect(self.pg0, p, self.pg1)
Filip Varga18f1e412020-12-03 15:27:40 +01003407
3408 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3409 self.assertEqual(len(sessions) - session_n, 1)
3410
Klement Sekera56c492a2022-01-10 21:57:27 +00003411 # retransmit FIN packet out -> in
Filip Varga18f1e412020-12-03 15:27:40 +01003412 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3413 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3414 TCP(sport=ext_port, dport=out_port,
3415 flags="FA", seq=300, ack=101))
3416
Klement Sekera56c492a2022-01-10 21:57:27 +00003417 self.send_and_expect(self.pg1, p, self.pg0)
Filip Varga18f1e412020-12-03 15:27:40 +01003418
Klement Sekera56c492a2022-01-10 21:57:27 +00003419 # retransmit ACK packet in -> out
Filip Varga18f1e412020-12-03 15:27:40 +01003420 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3421 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3422 TCP(sport=in_port, dport=ext_port,
3423 flags="A", seq=101, ack=301))
Klement Sekera56c492a2022-01-10 21:57:27 +00003424 self.send_and_expect(self.pg0, p, self.pg1)
Filip Varga18f1e412020-12-03 15:27:40 +01003425
Benoît Ganne56eccdb2021-08-20 09:18:31 +02003426 self.virtual_sleep(3)
Klement Sekera56c492a2022-01-10 21:57:27 +00003427 # retransmit ACK packet in -> out - this will cause session to be wiped
Filip Varga18f1e412020-12-03 15:27:40 +01003428 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3429 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3430 TCP(sport=in_port, dport=ext_port,
3431 flags="A", seq=101, ack=301))
Klement Sekera56c492a2022-01-10 21:57:27 +00003432 self.send_and_assert_no_replies(self.pg0, p)
Filip Varga18f1e412020-12-03 15:27:40 +01003433 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3434 self.assertEqual(len(sessions) - session_n, 0)
3435
3436 def test_tcp_session_close_out(self):
3437 """ NAT44ED Close TCP session from outside network """
3438
3439 in_port = self.tcp_port_in
3440 out_port = 10505
3441 ext_port = self.tcp_external_port
3442
3443 self.nat_add_address(self.nat_addr)
3444 self.nat_add_inside_interface(self.pg0)
3445 self.nat_add_outside_interface(self.pg1)
3446 self.nat_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
3447 in_port, out_port, proto=IP_PROTOS.tcp,
3448 flags=self.config_flags.NAT_IS_TWICE_NAT)
3449
3450 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3451 session_n = len(sessions)
3452
3453 self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
3454 tcp_transitory=2, icmp=5)
3455
3456 _ = self.init_tcp_session(self.pg0, self.pg1, in_port, ext_port)
3457
3458 # FIN packet out -> in
3459 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3460 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3461 TCP(sport=ext_port, dport=out_port,
3462 flags="FA", seq=100, ack=300))
3463 self.pg1.add_stream(p)
3464 self.pg_enable_capture(self.pg_interfaces)
3465 self.pg_start()
3466 self.pg0.get_capture(1)
3467
3468 # FIN+ACK packet in -> out
3469 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3470 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3471 TCP(sport=in_port, dport=ext_port,
3472 flags="FA", seq=300, ack=101))
3473
3474 self.pg0.add_stream(p)
3475 self.pg_enable_capture(self.pg_interfaces)
3476 self.pg_start()
3477 self.pg1.get_capture(1)
3478
3479 # ACK packet out -> in
3480 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3481 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3482 TCP(sport=ext_port, dport=out_port,
3483 flags="A", seq=101, ack=301))
3484 self.pg1.add_stream(p)
3485 self.pg_enable_capture(self.pg_interfaces)
3486 self.pg_start()
3487 self.pg0.get_capture(1)
3488
3489 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3490 self.assertEqual(len(sessions) - session_n, 1)
3491
Klement Sekera56c492a2022-01-10 21:57:27 +00003492 # retransmit FIN packet out -> in
Filip Varga18f1e412020-12-03 15:27:40 +01003493 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3494 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3495 TCP(sport=ext_port, dport=out_port,
3496 flags="FA", seq=300, ack=101))
Klement Sekera56c492a2022-01-10 21:57:27 +00003497 self.send_and_expect(self.pg1, p, self.pg0)
Filip Varga18f1e412020-12-03 15:27:40 +01003498
Klement Sekera56c492a2022-01-10 21:57:27 +00003499 # retransmit ACK packet in -> out
Filip Varga18f1e412020-12-03 15:27:40 +01003500 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3501 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3502 TCP(sport=in_port, dport=ext_port,
3503 flags="A", seq=101, ack=301))
Klement Sekera56c492a2022-01-10 21:57:27 +00003504 self.send_and_expect(self.pg0, p, self.pg1)
Filip Varga18f1e412020-12-03 15:27:40 +01003505
Benoît Ganne56eccdb2021-08-20 09:18:31 +02003506 self.virtual_sleep(3)
Klement Sekera56c492a2022-01-10 21:57:27 +00003507 # retransmit ACK packet in -> out - this will cause session to be wiped
Filip Varga18f1e412020-12-03 15:27:40 +01003508 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3509 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3510 TCP(sport=in_port, dport=ext_port,
3511 flags="A", seq=101, ack=301))
Klement Sekera56c492a2022-01-10 21:57:27 +00003512 self.send_and_assert_no_replies(self.pg0, p)
Filip Varga18f1e412020-12-03 15:27:40 +01003513 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3514 self.assertEqual(len(sessions) - session_n, 0)
3515
3516 def test_tcp_session_close_simultaneous(self):
Klement Sekera56c492a2022-01-10 21:57:27 +00003517 """ Simultaneous TCP close from both sides """
Filip Varga18f1e412020-12-03 15:27:40 +01003518
3519 in_port = self.tcp_port_in
3520 ext_port = 10505
3521
3522 self.nat_add_address(self.nat_addr)
3523 self.nat_add_inside_interface(self.pg0)
3524 self.nat_add_outside_interface(self.pg1)
3525 self.nat_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
3526 in_port, ext_port, proto=IP_PROTOS.tcp,
3527 flags=self.config_flags.NAT_IS_TWICE_NAT)
3528
3529 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3530 session_n = len(sessions)
3531
3532 self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
3533 tcp_transitory=2, icmp=5)
3534
3535 out_port = self.init_tcp_session(self.pg0, self.pg1, in_port, ext_port)
3536
3537 # FIN packet in -> out
3538 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3539 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3540 TCP(sport=in_port, dport=ext_port,
3541 flags="FA", seq=100, ack=300))
Klement Sekera56c492a2022-01-10 21:57:27 +00003542 self.send_and_expect(self.pg0, p, self.pg1)
Filip Varga18f1e412020-12-03 15:27:40 +01003543
3544 # FIN packet out -> in
3545 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3546 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3547 TCP(sport=ext_port, dport=out_port,
3548 flags="FA", seq=300, ack=100))
Klement Sekera56c492a2022-01-10 21:57:27 +00003549 self.send_and_expect(self.pg1, p, self.pg0)
Filip Varga18f1e412020-12-03 15:27:40 +01003550
3551 # ACK packet in -> out
3552 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3553 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3554 TCP(sport=in_port, dport=ext_port,
3555 flags="A", seq=101, ack=301))
Klement Sekera56c492a2022-01-10 21:57:27 +00003556 self.send_and_expect(self.pg0, p, self.pg1)
Filip Varga18f1e412020-12-03 15:27:40 +01003557
3558 # ACK packet out -> in
3559 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3560 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3561 TCP(sport=ext_port, dport=out_port,
3562 flags="A", seq=301, ack=101))
Klement Sekera56c492a2022-01-10 21:57:27 +00003563 self.send_and_expect(self.pg1, p, self.pg0)
Filip Varga18f1e412020-12-03 15:27:40 +01003564
3565 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3566 self.assertEqual(len(sessions) - session_n, 1)
3567
Klement Sekera56c492a2022-01-10 21:57:27 +00003568 # retransmit FIN packet out -> in
Filip Varga18f1e412020-12-03 15:27:40 +01003569 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3570 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3571 TCP(sport=ext_port, dport=out_port,
3572 flags="FA", seq=300, ack=101))
Klement Sekera56c492a2022-01-10 21:57:27 +00003573 self.send_and_expect(self.pg1, p, self.pg0)
Filip Varga18f1e412020-12-03 15:27:40 +01003574
Klement Sekera56c492a2022-01-10 21:57:27 +00003575 # retransmit ACK packet in -> out
Filip Varga18f1e412020-12-03 15:27:40 +01003576 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3577 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3578 TCP(sport=in_port, dport=ext_port,
3579 flags="A", seq=101, ack=301))
Klement Sekera56c492a2022-01-10 21:57:27 +00003580 self.send_and_expect(self.pg0, p, self.pg1)
Filip Varga18f1e412020-12-03 15:27:40 +01003581
Benoît Ganne56eccdb2021-08-20 09:18:31 +02003582 self.virtual_sleep(3)
Klement Sekera56c492a2022-01-10 21:57:27 +00003583 # retransmit ACK packet in -> out - this will cause session to be wiped
Filip Varga18f1e412020-12-03 15:27:40 +01003584 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3585 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3586 TCP(sport=in_port, dport=ext_port,
3587 flags="A", seq=101, ack=301))
Klement Sekera56c492a2022-01-10 21:57:27 +00003588 self.pg_send(self.pg0, p)
3589 self.send_and_assert_no_replies(self.pg0, p)
Filip Varga18f1e412020-12-03 15:27:40 +01003590 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3591 self.assertEqual(len(sessions) - session_n, 0)
3592
Klement Sekera56c492a2022-01-10 21:57:27 +00003593 def test_tcp_session_half_reopen_inside(self):
3594 """ TCP session in FIN/FIN state not reopened by in2out SYN only """
3595 in_port = self.tcp_port_in
3596 ext_port = 10505
3597
3598 self.nat_add_address(self.nat_addr)
3599 self.nat_add_inside_interface(self.pg0)
3600 self.nat_add_outside_interface(self.pg1)
3601 self.nat_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
3602 in_port, ext_port, proto=IP_PROTOS.tcp,
3603 flags=self.config_flags.NAT_IS_TWICE_NAT)
3604
3605 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3606 session_n = len(sessions)
3607
3608 self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
3609 tcp_transitory=2, icmp=5)
3610
3611 out_port = self.init_tcp_session(self.pg0, self.pg1, in_port, ext_port)
3612
3613 # FIN packet in -> out
3614 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3615 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3616 TCP(sport=in_port, dport=ext_port,
3617 flags="FA", seq=100, ack=300))
3618 self.send_and_expect(self.pg0, p, self.pg1)
3619
3620 # FIN packet out -> in
3621 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3622 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3623 TCP(sport=ext_port, dport=out_port,
3624 flags="FA", seq=300, ack=100))
3625 self.send_and_expect(self.pg1, p, self.pg0)
3626
3627 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3628 self.assertEqual(len(sessions) - session_n, 1)
3629
3630 # send SYN packet in -> out
3631 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3632 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3633 TCP(sport=in_port, dport=ext_port,
3634 flags="S", seq=101, ack=301))
3635 self.send_and_expect(self.pg0, p, self.pg1)
3636
3637 self.virtual_sleep(3)
3638 # send ACK packet in -> out - session should be wiped
3639 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3640 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3641 TCP(sport=in_port, dport=ext_port,
3642 flags="A", seq=101, ack=301))
3643 self.send_and_assert_no_replies(self.pg0, p, self.pg1)
3644 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3645 self.assertEqual(len(sessions) - session_n, 0)
3646
3647 def test_tcp_session_half_reopen_outside(self):
3648 """ TCP session in FIN/FIN state not reopened by out2in SYN only """
3649 in_port = self.tcp_port_in
3650 ext_port = 10505
3651
3652 self.nat_add_address(self.nat_addr)
3653 self.nat_add_inside_interface(self.pg0)
3654 self.nat_add_outside_interface(self.pg1)
3655 self.nat_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
3656 in_port, ext_port, proto=IP_PROTOS.tcp,
3657 flags=self.config_flags.NAT_IS_TWICE_NAT)
3658
3659 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3660 session_n = len(sessions)
3661
3662 self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
3663 tcp_transitory=2, icmp=5)
3664
3665 out_port = self.init_tcp_session(self.pg0, self.pg1, in_port, ext_port)
3666
3667 # FIN packet in -> out
3668 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3669 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3670 TCP(sport=in_port, dport=ext_port,
3671 flags="FA", seq=100, ack=300))
3672 self.send_and_expect(self.pg0, p, self.pg1)
3673
3674 # FIN packet out -> in
3675 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3676 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3677 TCP(sport=ext_port, dport=out_port,
3678 flags="FA", seq=300, ack=100))
3679 self.send_and_expect(self.pg1, p, self.pg0)
3680
3681 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3682 self.assertEqual(len(sessions) - session_n, 1)
3683
3684 # send SYN packet out -> in
3685 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3686 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3687 TCP(sport=ext_port, dport=out_port,
3688 flags="S", seq=300, ack=101))
3689 self.send_and_expect(self.pg1, p, self.pg0)
3690
3691 self.virtual_sleep(3)
3692 # send ACK packet in -> out - session should be wiped
3693 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3694 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3695 TCP(sport=in_port, dport=ext_port,
3696 flags="A", seq=101, ack=301))
3697 self.send_and_assert_no_replies(self.pg0, p, self.pg1)
3698 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3699 self.assertEqual(len(sessions) - session_n, 0)
3700
3701 def test_tcp_session_reopen(self):
3702 """ TCP session in FIN/FIN state reopened by SYN from both sides """
3703 in_port = self.tcp_port_in
3704 ext_port = 10505
3705
3706 self.nat_add_address(self.nat_addr)
3707 self.nat_add_inside_interface(self.pg0)
3708 self.nat_add_outside_interface(self.pg1)
3709 self.nat_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
3710 in_port, ext_port, proto=IP_PROTOS.tcp,
3711 flags=self.config_flags.NAT_IS_TWICE_NAT)
3712
3713 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3714 session_n = len(sessions)
3715
3716 self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
3717 tcp_transitory=2, icmp=5)
3718
3719 out_port = self.init_tcp_session(self.pg0, self.pg1, in_port, ext_port)
3720
3721 # FIN packet in -> out
3722 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3723 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3724 TCP(sport=in_port, dport=ext_port,
3725 flags="FA", seq=100, ack=300))
3726 self.send_and_expect(self.pg0, p, self.pg1)
3727
3728 # FIN packet out -> in
3729 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3730 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3731 TCP(sport=ext_port, dport=out_port,
3732 flags="FA", seq=300, ack=100))
3733 self.send_and_expect(self.pg1, p, self.pg0)
3734
3735 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3736 self.assertEqual(len(sessions) - session_n, 1)
3737
3738 # send SYN packet out -> in
3739 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3740 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3741 TCP(sport=ext_port, dport=out_port,
3742 flags="S", seq=300, ack=101))
3743 self.send_and_expect(self.pg1, p, self.pg0)
3744
3745 # send SYN packet in -> out
3746 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3747 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3748 TCP(sport=in_port, dport=ext_port,
3749 flags="S", seq=101, ack=301))
3750 self.send_and_expect(self.pg0, p, self.pg1)
3751
3752 self.virtual_sleep(3)
3753 # send ACK packet in -> out - should be forwarded and session alive
3754 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3755 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3756 TCP(sport=in_port, dport=ext_port,
3757 flags="A", seq=101, ack=301))
3758 self.send_and_expect(self.pg0, p, self.pg1)
3759 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3760 self.assertEqual(len(sessions) - session_n, 1)
3761
Filip Vargabdd61492021-04-13 17:47:13 +02003762 def test_dynamic_vrf(self):
3763 """ NAT44ED dynamic translation test: different VRF"""
3764
3765 vrf_id_in = 33
3766 vrf_id_out = 34
3767
3768 self.nat_add_address(self.nat_addr, vrf_id=vrf_id_in)
3769
3770 try:
3771 self.configure_ip4_interface(self.pg7, table_id=vrf_id_in)
3772 self.configure_ip4_interface(self.pg8, table_id=vrf_id_out)
3773
3774 self.nat_add_inside_interface(self.pg7)
3775 self.nat_add_outside_interface(self.pg8)
3776
3777 # just basic stuff nothing special
3778 pkts = self.create_stream_in(self.pg7, self.pg8)
3779 self.pg7.add_stream(pkts)
3780 self.pg_enable_capture(self.pg_interfaces)
3781 self.pg_start()
3782 capture = self.pg8.get_capture(len(pkts))
3783 self.verify_capture_out(capture, ignore_port=True)
3784
3785 pkts = self.create_stream_out(self.pg8)
3786 self.pg8.add_stream(pkts)
3787 self.pg_enable_capture(self.pg_interfaces)
3788 self.pg_start()
3789 capture = self.pg7.get_capture(len(pkts))
3790 self.verify_capture_in(capture, self.pg7)
3791
3792 finally:
3793 self.pg7.unconfig()
3794 self.pg8.unconfig()
3795
3796 self.vapi.ip_table_add_del(is_add=0,
3797 table={'table_id': vrf_id_in})
3798 self.vapi.ip_table_add_del(is_add=0,
3799 table={'table_id': vrf_id_out})
3800
Filip Varga18f1e412020-12-03 15:27:40 +01003801 def test_dynamic_output_feature_vrf(self):
3802 """ NAT44ED dynamic translation test: output-feature, VRF"""
3803
3804 # other then default (0)
3805 new_vrf_id = 22
3806
3807 self.nat_add_address(self.nat_addr)
Filip Vargab6810822022-02-15 11:56:07 -08003808 self.vapi.nat44_ed_add_del_output_interface(
3809 sw_if_index=self.pg8.sw_if_index,
3810 is_add=1)
Filip Varga18f1e412020-12-03 15:27:40 +01003811 try:
3812 self.configure_ip4_interface(self.pg7, table_id=new_vrf_id)
3813 self.configure_ip4_interface(self.pg8, table_id=new_vrf_id)
3814
3815 # in2out
Klement Sekera3887be72021-03-30 20:29:05 +02003816 tcpn = self.statistics['/nat44-ed/in2out/slowpath/tcp']
3817 udpn = self.statistics['/nat44-ed/in2out/slowpath/udp']
3818 icmpn = self.statistics['/nat44-ed/in2out/slowpath/icmp']
3819 drops = self.statistics['/nat44-ed/in2out/slowpath/drops']
Filip Varga18f1e412020-12-03 15:27:40 +01003820
3821 pkts = self.create_stream_in(self.pg7, self.pg8)
3822 self.pg7.add_stream(pkts)
3823 self.pg_enable_capture(self.pg_interfaces)
3824 self.pg_start()
3825 capture = self.pg8.get_capture(len(pkts))
3826 self.verify_capture_out(capture, ignore_port=True)
3827
Alexander Chernavin4de12b92021-07-06 06:08:26 -04003828 if_idx = self.pg8.sw_if_index
Klement Sekera3887be72021-03-30 20:29:05 +02003829 cnt = self.statistics['/nat44-ed/in2out/slowpath/tcp']
3830 self.assertEqual(cnt[:, if_idx].sum() - tcpn[:, if_idx].sum(), 2)
3831 cnt = self.statistics['/nat44-ed/in2out/slowpath/udp']
3832 self.assertEqual(cnt[:, if_idx].sum() - udpn[:, if_idx].sum(), 1)
3833 cnt = self.statistics['/nat44-ed/in2out/slowpath/icmp']
3834 self.assertEqual(cnt[:, if_idx].sum() - icmpn[:, if_idx].sum(), 1)
3835 cnt = self.statistics['/nat44-ed/in2out/slowpath/drops']
3836 self.assertEqual(cnt[:, if_idx].sum() - drops[:, if_idx].sum(), 0)
Filip Varga18f1e412020-12-03 15:27:40 +01003837
3838 # out2in
Klement Sekera3887be72021-03-30 20:29:05 +02003839 tcpn = self.statistics['/nat44-ed/out2in/fastpath/tcp']
3840 udpn = self.statistics['/nat44-ed/out2in/fastpath/udp']
3841 icmpn = self.statistics['/nat44-ed/out2in/fastpath/icmp']
3842 drops = self.statistics['/nat44-ed/out2in/fastpath/drops']
Filip Varga18f1e412020-12-03 15:27:40 +01003843
3844 pkts = self.create_stream_out(self.pg8)
3845 self.pg8.add_stream(pkts)
3846 self.pg_enable_capture(self.pg_interfaces)
3847 self.pg_start()
3848 capture = self.pg7.get_capture(len(pkts))
3849 self.verify_capture_in(capture, self.pg7)
3850
3851 if_idx = self.pg8.sw_if_index
Klement Sekera3887be72021-03-30 20:29:05 +02003852 cnt = self.statistics['/nat44-ed/out2in/fastpath/tcp']
3853 self.assertEqual(cnt[:, if_idx].sum() - tcpn[:, if_idx].sum(), 2)
3854 cnt = self.statistics['/nat44-ed/out2in/fastpath/udp']
3855 self.assertEqual(cnt[:, if_idx].sum() - udpn[:, if_idx].sum(), 1)
3856 cnt = self.statistics['/nat44-ed/out2in/fastpath/icmp']
3857 self.assertEqual(cnt[:, if_idx].sum() - icmpn[:, if_idx].sum(), 1)
3858 cnt = self.statistics['/nat44-ed/out2in/fastpath/drops']
3859 self.assertEqual(cnt[:, if_idx].sum() - drops[:, if_idx].sum(), 0)
Filip Varga18f1e412020-12-03 15:27:40 +01003860
Klement Sekera3887be72021-03-30 20:29:05 +02003861 sessions = self.statistics['/nat44-ed/total-sessions']
3862 self.assertEqual(sessions[:, 0].sum(), 3)
Filip Varga18f1e412020-12-03 15:27:40 +01003863
3864 finally:
Filip Vargabdd61492021-04-13 17:47:13 +02003865 self.pg7.unconfig()
3866 self.pg8.unconfig()
Filip Varga18f1e412020-12-03 15:27:40 +01003867
3868 self.vapi.ip_table_add_del(is_add=0,
3869 table={'table_id': new_vrf_id})
3870
3871 def test_next_src_nat(self):
3872 """ NAT44ED On way back forward packet to nat44-in2out node. """
3873
3874 twice_nat_addr = '10.0.1.3'
3875 external_port = 80
3876 local_port = 8080
3877 post_twice_nat_port = 0
3878
3879 self.vapi.nat44_forwarding_enable_disable(enable=1)
3880 self.nat_add_address(twice_nat_addr, twice_nat=1)
3881 flags = (self.config_flags.NAT_IS_OUT2IN_ONLY |
3882 self.config_flags.NAT_IS_SELF_TWICE_NAT)
3883 self.nat_add_static_mapping(self.pg6.remote_ip4, self.pg1.remote_ip4,
3884 local_port, external_port,
3885 proto=IP_PROTOS.tcp, vrf_id=1,
3886 flags=flags)
3887 self.vapi.nat44_interface_add_del_feature(
3888 sw_if_index=self.pg6.sw_if_index,
3889 is_add=1)
3890
3891 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
3892 IP(src=self.pg6.remote_ip4, dst=self.pg1.remote_ip4) /
3893 TCP(sport=12345, dport=external_port))
3894 self.pg6.add_stream(p)
3895 self.pg_enable_capture(self.pg_interfaces)
3896 self.pg_start()
3897 capture = self.pg6.get_capture(1)
3898 p = capture[0]
3899 try:
3900 ip = p[IP]
3901 tcp = p[TCP]
3902 self.assertEqual(ip.src, twice_nat_addr)
3903 self.assertNotEqual(tcp.sport, 12345)
3904 post_twice_nat_port = tcp.sport
3905 self.assertEqual(ip.dst, self.pg6.remote_ip4)
3906 self.assertEqual(tcp.dport, local_port)
3907 self.assert_packet_checksums_valid(p)
3908 except:
3909 self.logger.error(ppp("Unexpected or invalid packet:", p))
3910 raise
3911
3912 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
3913 IP(src=self.pg6.remote_ip4, dst=twice_nat_addr) /
3914 TCP(sport=local_port, dport=post_twice_nat_port))
3915 self.pg6.add_stream(p)
3916 self.pg_enable_capture(self.pg_interfaces)
3917 self.pg_start()
3918 capture = self.pg6.get_capture(1)
3919 p = capture[0]
3920 try:
3921 ip = p[IP]
3922 tcp = p[TCP]
3923 self.assertEqual(ip.src, self.pg1.remote_ip4)
3924 self.assertEqual(tcp.sport, external_port)
3925 self.assertEqual(ip.dst, self.pg6.remote_ip4)
3926 self.assertEqual(tcp.dport, 12345)
3927 self.assert_packet_checksums_valid(p)
3928 except:
3929 self.logger.error(ppp("Unexpected or invalid packet:", p))
3930 raise
3931
3932 def test_one_armed_nat44_static(self):
3933 """ NAT44ED One armed NAT and 1:1 NAPT asymmetrical rule """
3934
3935 remote_host = self.pg4.remote_hosts[0]
3936 local_host = self.pg4.remote_hosts[1]
3937 external_port = 80
3938 local_port = 8080
3939 eh_port_in = 0
3940
3941 self.vapi.nat44_forwarding_enable_disable(enable=1)
3942 self.nat_add_address(self.nat_addr, twice_nat=1)
3943 flags = (self.config_flags.NAT_IS_OUT2IN_ONLY |
3944 self.config_flags.NAT_IS_TWICE_NAT)
3945 self.nat_add_static_mapping(local_host.ip4, self.nat_addr,
3946 local_port, external_port,
3947 proto=IP_PROTOS.tcp, flags=flags)
3948 flags = self.config_flags.NAT_IS_INSIDE
3949 self.vapi.nat44_interface_add_del_feature(
3950 sw_if_index=self.pg4.sw_if_index,
3951 is_add=1)
3952 self.vapi.nat44_interface_add_del_feature(
3953 sw_if_index=self.pg4.sw_if_index,
3954 flags=flags, is_add=1)
3955
3956 # from client to service
3957 p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
3958 IP(src=remote_host.ip4, dst=self.nat_addr) /
3959 TCP(sport=12345, dport=external_port))
3960 self.pg4.add_stream(p)
3961 self.pg_enable_capture(self.pg_interfaces)
3962 self.pg_start()
3963 capture = self.pg4.get_capture(1)
3964 p = capture[0]
3965 try:
3966 ip = p[IP]
3967 tcp = p[TCP]
3968 self.assertEqual(ip.dst, local_host.ip4)
3969 self.assertEqual(ip.src, self.nat_addr)
3970 self.assertEqual(tcp.dport, local_port)
3971 self.assertNotEqual(tcp.sport, 12345)
3972 eh_port_in = tcp.sport
3973 self.assert_packet_checksums_valid(p)
3974 except:
3975 self.logger.error(ppp("Unexpected or invalid packet:", p))
3976 raise
3977
3978 # from service back to client
3979 p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
3980 IP(src=local_host.ip4, dst=self.nat_addr) /
3981 TCP(sport=local_port, dport=eh_port_in))
3982 self.pg4.add_stream(p)
3983 self.pg_enable_capture(self.pg_interfaces)
3984 self.pg_start()
3985 capture = self.pg4.get_capture(1)
3986 p = capture[0]
3987 try:
3988 ip = p[IP]
3989 tcp = p[TCP]
3990 self.assertEqual(ip.src, self.nat_addr)
3991 self.assertEqual(ip.dst, remote_host.ip4)
3992 self.assertEqual(tcp.sport, external_port)
3993 self.assertEqual(tcp.dport, 12345)
3994 self.assert_packet_checksums_valid(p)
3995 except:
3996 self.logger.error(ppp("Unexpected or invalid packet:", p))
3997 raise
3998
Matthew Smithad510752021-08-10 12:22:14 -05003999 def test_icmp_error_fwd_outbound(self):
4000 """ NAT44ED ICMP error outbound with forwarding enabled """
4001
4002 # Ensure that an outbound ICMP error message is properly associated
4003 # with the inbound forward bypass session it is related to.
4004 payload = "H" * 10
4005
4006 self.nat_add_address(self.nat_addr)
4007 self.nat_add_inside_interface(self.pg0)
4008 self.nat_add_outside_interface(self.pg1)
4009
4010 # enable forwarding and initiate connection out2in
4011 self.vapi.nat44_forwarding_enable_disable(enable=1)
4012 p1 = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4013 IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
4014 UDP(sport=21, dport=20) / payload)
4015
4016 self.pg1.add_stream(p1)
4017 self.pg_enable_capture(self.pg_interfaces)
4018 self.pg_start()
4019 capture = self.pg0.get_capture(1)[0]
4020
4021 self.logger.info(self.vapi.cli("show nat44 sessions"))
4022
4023 # reply with ICMP error message in2out
4024 # We cannot reliably retrieve forward bypass sessions via the API.
4025 # session dumps for a user will only look on the worker that the
4026 # user is supposed to be mapped to in2out. The forward bypass session
4027 # is not necessarily created on that worker.
4028 p2 = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4029 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4030 ICMP(type='dest-unreach', code='port-unreachable') /
4031 capture[IP:])
4032
4033 self.pg0.add_stream(p2)
4034 self.pg_enable_capture(self.pg_interfaces)
4035 self.pg_start()
4036 capture = self.pg1.get_capture(1)[0]
4037
4038 self.logger.info(self.vapi.cli("show nat44 sessions"))
4039
4040 self.logger.info(ppp("p1 packet:", p1))
4041 self.logger.info(ppp("p2 packet:", p2))
4042 self.logger.info(ppp("capture packet:", capture))
4043
Klement Sekera56c492a2022-01-10 21:57:27 +00004044 def test_tcp_session_open_retransmit1(self):
4045 """ NAT44ED Open TCP session with SYN,ACK retransmit 1
4046
4047 The client does not receive the [SYN,ACK] or the
4048 ACK from the client is lost. Therefore, the [SYN, ACK]
4049 is retransmitted by the server.
4050 """
4051
4052 in_port = self.tcp_port_in
4053 ext_port = self.tcp_external_port
4054 payload = "H" * 10
4055
4056 self.nat_add_address(self.nat_addr)
4057 self.nat_add_inside_interface(self.pg0)
4058 self.nat_add_outside_interface(self.pg1)
4059
4060 self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
4061 tcp_transitory=5, icmp=60)
4062 # SYN packet in->out
4063 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4064 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4065 TCP(sport=in_port, dport=ext_port, flags="S"))
4066 p = self.send_and_expect(self.pg0, p, self.pg1)[0]
4067 out_port = p[TCP].sport
4068
4069 # SYN + ACK packet out->in
4070 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4071 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4072 TCP(sport=ext_port, dport=out_port, flags="SA"))
4073 self.send_and_expect(self.pg1, p, self.pg0)
4074
4075 # ACK in->out does not arrive
4076
4077 # resent SYN + ACK packet out->in
4078 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4079 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4080 TCP(sport=ext_port, dport=out_port, flags="SA"))
4081 self.send_and_expect(self.pg1, p, self.pg0)
4082
4083 # ACK packet in->out
4084 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4085 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4086 TCP(sport=in_port, dport=ext_port, flags="A"))
4087 self.send_and_expect(self.pg0, p, self.pg1)
4088
4089 # Verify that the data can be transmitted after the transitory time
4090 self.virtual_sleep(6)
4091
4092 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4093 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4094 TCP(sport=in_port, dport=ext_port, flags="PA") /
4095 Raw(payload))
4096 self.send_and_expect(self.pg0, p, self.pg1)
4097
4098 def test_tcp_session_open_retransmit2(self):
4099 """ NAT44ED Open TCP session with SYN,ACK retransmit 2
4100
4101 The ACK is lost to the server after the TCP session is opened.
4102 Data is sent by the client, then the [SYN,ACK] is
4103 retransmitted by the server.
4104 """
4105
4106 in_port = self.tcp_port_in
4107 ext_port = self.tcp_external_port
4108 payload = "H" * 10
4109
4110 self.nat_add_address(self.nat_addr)
4111 self.nat_add_inside_interface(self.pg0)
4112 self.nat_add_outside_interface(self.pg1)
4113
4114 self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
4115 tcp_transitory=5, icmp=60)
4116 # SYN packet in->out
4117 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4118 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4119 TCP(sport=in_port, dport=ext_port, flags="S"))
4120 p = self.send_and_expect(self.pg0, p, self.pg1)[0]
4121 out_port = p[TCP].sport
4122
4123 # SYN + ACK packet out->in
4124 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4125 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4126 TCP(sport=ext_port, dport=out_port, flags="SA"))
4127 self.send_and_expect(self.pg1, p, self.pg0)
4128
4129 # ACK packet in->out -- not received by the server
4130 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4131 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4132 TCP(sport=in_port, dport=ext_port, flags="A"))
4133 self.send_and_expect(self.pg0, p, self.pg1)
4134
4135 # PUSH + ACK packet in->out
4136 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4137 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4138 TCP(sport=in_port, dport=ext_port, flags="PA") /
4139 Raw(payload))
4140 self.send_and_expect(self.pg0, p, self.pg1)
4141
4142 # resent SYN + ACK packet out->in
4143 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4144 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4145 TCP(sport=ext_port, dport=out_port, flags="SA"))
4146 self.send_and_expect(self.pg1, p, self.pg0)
4147
4148 # resent ACK packet in->out
4149 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4150 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4151 TCP(sport=in_port, dport=ext_port, flags="A"))
4152 self.send_and_expect(self.pg0, p, self.pg1)
4153
4154 # resent PUSH + ACK packet in->out
4155 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4156 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4157 TCP(sport=in_port, dport=ext_port, flags="PA") /
4158 Raw(payload))
4159 self.send_and_expect(self.pg0, p, self.pg1)
4160
4161 # ACK packet out->in
4162 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4163 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4164 TCP(sport=ext_port, dport=out_port, flags="A"))
4165 self.send_and_expect(self.pg1, p, self.pg0)
4166
4167 # Verify that the data can be transmitted after the transitory time
4168 self.virtual_sleep(6)
4169
4170 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4171 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4172 TCP(sport=in_port, dport=ext_port, flags="PA") /
4173 Raw(payload))
4174 self.send_and_expect(self.pg0, p, self.pg1)
4175
Filip Varga18f1e412020-12-03 15:27:40 +01004176
4177if __name__ == '__main__':
4178 unittest.main(testRunner=VppTestRunner)