nat: pick outside addr based on local addr
[vpp.git] / src / plugins / nat / test / test_nat44_ed.py
1 #!/usr/bin/env python3
2
3 import unittest
4 from io import BytesIO
5 from random import randint
6
7 import scapy.compat
8 from framework import tag_fixme_vpp_workers
9 from framework import VppTestCase, VppTestRunner
10 from scapy.data import IP_PROTOS
11 from scapy.layers.inet import IP, TCP, UDP, ICMP, GRE
12 from scapy.layers.inet import IPerror, TCPerror
13 from scapy.layers.l2 import Ether
14 from scapy.packet import Raw
15 from syslog_rfc5424_parser import SyslogMessage, ParseError
16 from syslog_rfc5424_parser.constants import SyslogSeverity
17 from util import ppp, ip4_range
18 from vpp_acl import AclRule, VppAcl, VppAclInterface
19 from vpp_ip_route import VppIpRoute, VppRoutePath
20 from vpp_papi import VppEnum
21
22
23 class NAT44EDTestCase(VppTestCase):
24
25     nat_addr = '10.0.0.3'
26
27     tcp_port_in = 6303
28     tcp_port_out = 6303
29
30     udp_port_in = 6304
31     udp_port_out = 6304
32
33     icmp_id_in = 6305
34     icmp_id_out = 6305
35
36     tcp_external_port = 80
37
38     max_sessions = 100
39
40     def setUp(self):
41         super(NAT44EDTestCase, self).setUp()
42         self.plugin_enable()
43
44     def tearDown(self):
45         super(NAT44EDTestCase, self).tearDown()
46         if not self.vpp_dead:
47             self.plugin_disable()
48
49     def plugin_enable(self):
50         self.vapi.nat44_ed_plugin_enable_disable(
51             sessions=self.max_sessions, enable=1)
52
53     def plugin_disable(self):
54         self.vapi.nat44_ed_plugin_enable_disable(enable=0)
55
56     @property
57     def config_flags(self):
58         return VppEnum.vl_api_nat_config_flags_t
59
60     @property
61     def nat44_config_flags(self):
62         return VppEnum.vl_api_nat44_config_flags_t
63
64     @property
65     def syslog_severity(self):
66         return VppEnum.vl_api_syslog_severity_t
67
68     @property
69     def server_addr(self):
70         return self.pg1.remote_hosts[0].ip4
71
72     @staticmethod
73     def random_port():
74         return randint(1025, 65535)
75
76     @staticmethod
77     def proto2layer(proto):
78         if proto == IP_PROTOS.tcp:
79             return TCP
80         elif proto == IP_PROTOS.udp:
81             return UDP
82         elif proto == IP_PROTOS.icmp:
83             return ICMP
84         else:
85             raise Exception("Unsupported protocol")
86
87     @classmethod
88     def create_and_add_ip4_table(cls, i, table_id=0):
89         cls.vapi.ip_table_add_del(is_add=1, table={'table_id': table_id})
90         i.set_table_ip4(table_id)
91
92     @classmethod
93     def configure_ip4_interface(cls, i, hosts=0, table_id=None):
94         if table_id:
95             cls.create_and_add_ip4_table(i, table_id)
96
97         i.admin_up()
98         i.unconfig_ip4()
99         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):
151         super(NAT44EDTestCase, cls).setUpClass()
152
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
217     def get_err_counter(self, path):
218         return self.statistics.get_err_counter(path)
219
220     def get_stats_counter(self, path, worker=0):
221         return self.statistics.get_counter(path)[worker]
222
223     def reass_hairpinning(self, server_addr, server_in_port, server_out_port,
224                           host_in_port, proto=IP_PROTOS.tcp,
225                           ignore_port=False):
226         layer = self.proto2layer(proto)
227
228         if proto == IP_PROTOS.tcp:
229             data = b"A" * 4 + b"B" * 16 + b"C" * 3
230         else:
231             data = b"A" * 16 + b"B" * 16 + b"C" * 3
232
233         # send packet from host to server
234         pkts = self.create_stream_frag(self.pg0,
235                                        self.nat_addr,
236                                        host_in_port,
237                                        server_out_port,
238                                        data,
239                                        proto)
240         self.pg0.add_stream(pkts)
241         self.pg_enable_capture(self.pg_interfaces)
242         self.pg_start()
243         frags = self.pg0.get_capture(len(pkts))
244         p = self.reass_frags_and_verify(frags,
245                                         self.nat_addr,
246                                         server_addr)
247         if proto != IP_PROTOS.icmp:
248             if not ignore_port:
249                 self.assertNotEqual(p[layer].sport, host_in_port)
250             self.assertEqual(p[layer].dport, server_in_port)
251         else:
252             if not ignore_port:
253                 self.assertNotEqual(p[layer].id, host_in_port)
254         self.assertEqual(data, p[Raw].load)
255
256     def frag_out_of_order(self, proto=IP_PROTOS.tcp, dont_translate=False,
257                           ignore_port=False):
258         layer = self.proto2layer(proto)
259
260         if proto == IP_PROTOS.tcp:
261             data = b"A" * 4 + b"B" * 16 + b"C" * 3
262         else:
263             data = b"A" * 16 + b"B" * 16 + b"C" * 3
264         self.port_in = self.random_port()
265
266         for i in range(2):
267             # in2out
268             pkts = self.create_stream_frag(self.pg0, self.pg1.remote_ip4,
269                                            self.port_in, 20, data, proto)
270             pkts.reverse()
271             self.pg0.add_stream(pkts)
272             self.pg_enable_capture(self.pg_interfaces)
273             self.pg_start()
274             frags = self.pg1.get_capture(len(pkts))
275             if not dont_translate:
276                 p = self.reass_frags_and_verify(frags,
277                                                 self.nat_addr,
278                                                 self.pg1.remote_ip4)
279             else:
280                 p = self.reass_frags_and_verify(frags,
281                                                 self.pg0.remote_ip4,
282                                                 self.pg1.remote_ip4)
283             if proto != IP_PROTOS.icmp:
284                 if not dont_translate:
285                     self.assertEqual(p[layer].dport, 20)
286                     if not ignore_port:
287                         self.assertNotEqual(p[layer].sport, self.port_in)
288                 else:
289                     self.assertEqual(p[layer].sport, self.port_in)
290             else:
291                 if not ignore_port:
292                     if not dont_translate:
293                         self.assertNotEqual(p[layer].id, self.port_in)
294                     else:
295                         self.assertEqual(p[layer].id, self.port_in)
296             self.assertEqual(data, p[Raw].load)
297
298             # out2in
299             if not dont_translate:
300                 dst_addr = self.nat_addr
301             else:
302                 dst_addr = self.pg0.remote_ip4
303             if proto != IP_PROTOS.icmp:
304                 sport = 20
305                 dport = p[layer].sport
306             else:
307                 sport = p[layer].id
308                 dport = 0
309             pkts = self.create_stream_frag(self.pg1, dst_addr, sport, dport,
310                                            data, proto, echo_reply=True)
311             pkts.reverse()
312             self.pg1.add_stream(pkts)
313             self.pg_enable_capture(self.pg_interfaces)
314             self.pg_start()
315             frags = self.pg0.get_capture(len(pkts))
316             p = self.reass_frags_and_verify(frags,
317                                             self.pg1.remote_ip4,
318                                             self.pg0.remote_ip4)
319             if proto != IP_PROTOS.icmp:
320                 self.assertEqual(p[layer].sport, 20)
321                 self.assertEqual(p[layer].dport, self.port_in)
322             else:
323                 self.assertEqual(p[layer].id, self.port_in)
324             self.assertEqual(data, p[Raw].load)
325
326     def reass_frags_and_verify(self, frags, src, dst):
327         buffer = BytesIO()
328         for p in frags:
329             self.assertEqual(p[IP].src, src)
330             self.assertEqual(p[IP].dst, dst)
331             self.assert_ip_checksum_valid(p)
332             buffer.seek(p[IP].frag * 8)
333             buffer.write(bytes(p[IP].payload))
334         ip = IP(src=frags[0][IP].src, dst=frags[0][IP].dst,
335                 proto=frags[0][IP].proto)
336         if ip.proto == IP_PROTOS.tcp:
337             p = (ip / TCP(buffer.getvalue()))
338             self.logger.debug(ppp("Reassembled:", p))
339             self.assert_tcp_checksum_valid(p)
340         elif ip.proto == IP_PROTOS.udp:
341             p = (ip / UDP(buffer.getvalue()[:8]) /
342                  Raw(buffer.getvalue()[8:]))
343         elif ip.proto == IP_PROTOS.icmp:
344             p = (ip / ICMP(buffer.getvalue()))
345         return p
346
347     def frag_in_order(self, proto=IP_PROTOS.tcp, dont_translate=False,
348                       ignore_port=False):
349         layer = self.proto2layer(proto)
350
351         if proto == IP_PROTOS.tcp:
352             data = b"A" * 4 + b"B" * 16 + b"C" * 3
353         else:
354             data = b"A" * 16 + b"B" * 16 + b"C" * 3
355         self.port_in = self.random_port()
356
357         # in2out
358         pkts = self.create_stream_frag(self.pg0, self.pg1.remote_ip4,
359                                        self.port_in, 20, data, proto)
360         self.pg0.add_stream(pkts)
361         self.pg_enable_capture(self.pg_interfaces)
362         self.pg_start()
363         frags = self.pg1.get_capture(len(pkts))
364         if not dont_translate:
365             p = self.reass_frags_and_verify(frags,
366                                             self.nat_addr,
367                                             self.pg1.remote_ip4)
368         else:
369             p = self.reass_frags_and_verify(frags,
370                                             self.pg0.remote_ip4,
371                                             self.pg1.remote_ip4)
372         if proto != IP_PROTOS.icmp:
373             if not dont_translate:
374                 self.assertEqual(p[layer].dport, 20)
375                 if not ignore_port:
376                     self.assertNotEqual(p[layer].sport, self.port_in)
377             else:
378                 self.assertEqual(p[layer].sport, self.port_in)
379         else:
380             if not ignore_port:
381                 if not dont_translate:
382                     self.assertNotEqual(p[layer].id, self.port_in)
383                 else:
384                     self.assertEqual(p[layer].id, self.port_in)
385         self.assertEqual(data, p[Raw].load)
386
387         # out2in
388         if not dont_translate:
389             dst_addr = self.nat_addr
390         else:
391             dst_addr = self.pg0.remote_ip4
392         if proto != IP_PROTOS.icmp:
393             sport = 20
394             dport = p[layer].sport
395         else:
396             sport = p[layer].id
397             dport = 0
398         pkts = self.create_stream_frag(self.pg1, dst_addr, sport, dport, data,
399                                        proto, echo_reply=True)
400         self.pg1.add_stream(pkts)
401         self.pg_enable_capture(self.pg_interfaces)
402         self.pg_start()
403         frags = self.pg0.get_capture(len(pkts))
404         p = self.reass_frags_and_verify(frags,
405                                         self.pg1.remote_ip4,
406                                         self.pg0.remote_ip4)
407         if proto != IP_PROTOS.icmp:
408             self.assertEqual(p[layer].sport, 20)
409             self.assertEqual(p[layer].dport, self.port_in)
410         else:
411             self.assertEqual(p[layer].id, self.port_in)
412         self.assertEqual(data, p[Raw].load)
413
414     def verify_capture_out(self, capture, nat_ip=None, same_port=False,
415                            dst_ip=None, ignore_port=False):
416         if nat_ip is None:
417             nat_ip = self.nat_addr
418         for packet in capture:
419             try:
420                 self.assert_packet_checksums_valid(packet)
421                 self.assertEqual(packet[IP].src, nat_ip)
422                 if dst_ip is not None:
423                     self.assertEqual(packet[IP].dst, dst_ip)
424                 if packet.haslayer(TCP):
425                     if not ignore_port:
426                         if same_port:
427                             self.assertEqual(
428                                 packet[TCP].sport, self.tcp_port_in)
429                         else:
430                             self.assertNotEqual(
431                                 packet[TCP].sport, self.tcp_port_in)
432                     self.tcp_port_out = packet[TCP].sport
433                     self.assert_packet_checksums_valid(packet)
434                 elif packet.haslayer(UDP):
435                     if not ignore_port:
436                         if same_port:
437                             self.assertEqual(
438                                 packet[UDP].sport, self.udp_port_in)
439                         else:
440                             self.assertNotEqual(
441                                 packet[UDP].sport, self.udp_port_in)
442                     self.udp_port_out = packet[UDP].sport
443                 else:
444                     if not ignore_port:
445                         if same_port:
446                             self.assertEqual(
447                                 packet[ICMP].id, self.icmp_id_in)
448                         else:
449                             self.assertNotEqual(
450                                 packet[ICMP].id, self.icmp_id_in)
451                     self.icmp_id_out = packet[ICMP].id
452                     self.assert_packet_checksums_valid(packet)
453             except:
454                 self.logger.error(ppp("Unexpected or invalid packet "
455                                       "(outside network):", packet))
456                 raise
457
458     def verify_capture_in(self, capture, in_if):
459         for packet in capture:
460             try:
461                 self.assert_packet_checksums_valid(packet)
462                 self.assertEqual(packet[IP].dst, in_if.remote_ip4)
463                 if packet.haslayer(TCP):
464                     self.assertEqual(packet[TCP].dport, self.tcp_port_in)
465                 elif packet.haslayer(UDP):
466                     self.assertEqual(packet[UDP].dport, self.udp_port_in)
467                 else:
468                     self.assertEqual(packet[ICMP].id, self.icmp_id_in)
469             except:
470                 self.logger.error(ppp("Unexpected or invalid packet "
471                                       "(inside network):", packet))
472                 raise
473
474     def create_stream_in(self, in_if, out_if, dst_ip=None, ttl=64):
475         if dst_ip is None:
476             dst_ip = out_if.remote_ip4
477
478         pkts = []
479         # TCP
480         p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
481              IP(src=in_if.remote_ip4, dst=dst_ip, ttl=ttl) /
482              TCP(sport=self.tcp_port_in, dport=20))
483         pkts.extend([p, p])
484
485         # UDP
486         p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
487              IP(src=in_if.remote_ip4, dst=dst_ip, ttl=ttl) /
488              UDP(sport=self.udp_port_in, dport=20))
489         pkts.append(p)
490
491         # ICMP
492         p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
493              IP(src=in_if.remote_ip4, dst=dst_ip, ttl=ttl) /
494              ICMP(id=self.icmp_id_in, type='echo-request'))
495         pkts.append(p)
496
497         return pkts
498
499     def create_stream_out(self, out_if, dst_ip=None, ttl=64,
500                           use_inside_ports=False):
501         if dst_ip is None:
502             dst_ip = self.nat_addr
503         if not use_inside_ports:
504             tcp_port = self.tcp_port_out
505             udp_port = self.udp_port_out
506             icmp_id = self.icmp_id_out
507         else:
508             tcp_port = self.tcp_port_in
509             udp_port = self.udp_port_in
510             icmp_id = self.icmp_id_in
511         pkts = []
512         # TCP
513         p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
514              IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
515              TCP(dport=tcp_port, sport=20))
516         pkts.extend([p, p])
517
518         # UDP
519         p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
520              IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
521              UDP(dport=udp_port, sport=20))
522         pkts.append(p)
523
524         # ICMP
525         p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
526              IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
527              ICMP(id=icmp_id, type='echo-reply'))
528         pkts.append(p)
529
530         return pkts
531
532     def create_tcp_stream(self, in_if, out_if, count):
533         pkts = []
534         port = 6303
535
536         for i in range(count):
537             p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
538                  IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=64) /
539                  TCP(sport=port + i, dport=20))
540             pkts.append(p)
541
542         return pkts
543
544     def create_stream_frag(self, src_if, dst, sport, dport, data,
545                            proto=IP_PROTOS.tcp, echo_reply=False):
546         if proto == IP_PROTOS.tcp:
547             p = (IP(src=src_if.remote_ip4, dst=dst) /
548                  TCP(sport=sport, dport=dport) /
549                  Raw(data))
550             p = p.__class__(scapy.compat.raw(p))
551             chksum = p[TCP].chksum
552             proto_header = TCP(sport=sport, dport=dport, chksum=chksum)
553         elif proto == IP_PROTOS.udp:
554             proto_header = UDP(sport=sport, dport=dport)
555         elif proto == IP_PROTOS.icmp:
556             if not echo_reply:
557                 proto_header = ICMP(id=sport, type='echo-request')
558             else:
559                 proto_header = ICMP(id=sport, type='echo-reply')
560         else:
561             raise Exception("Unsupported protocol")
562         id = self.random_port()
563         pkts = []
564         if proto == IP_PROTOS.tcp:
565             raw = Raw(data[0:4])
566         else:
567             raw = Raw(data[0:16])
568         p = (Ether(src=src_if.remote_mac, dst=src_if.local_mac) /
569              IP(src=src_if.remote_ip4, dst=dst, flags="MF", frag=0, id=id) /
570              proto_header /
571              raw)
572         pkts.append(p)
573         if proto == IP_PROTOS.tcp:
574             raw = Raw(data[4:20])
575         else:
576             raw = Raw(data[16:32])
577         p = (Ether(src=src_if.remote_mac, dst=src_if.local_mac) /
578              IP(src=src_if.remote_ip4, dst=dst, flags="MF", frag=3, id=id,
579                 proto=proto) /
580              raw)
581         pkts.append(p)
582         if proto == IP_PROTOS.tcp:
583             raw = Raw(data[20:])
584         else:
585             raw = Raw(data[32:])
586         p = (Ether(src=src_if.remote_mac, dst=src_if.local_mac) /
587              IP(src=src_if.remote_ip4, dst=dst, frag=5, proto=proto,
588                 id=id) /
589              raw)
590         pkts.append(p)
591         return pkts
592
593     def frag_in_order_in_plus_out(self, in_addr, out_addr, in_port, out_port,
594                                   proto=IP_PROTOS.tcp):
595
596         layer = self.proto2layer(proto)
597
598         if proto == IP_PROTOS.tcp:
599             data = b"A" * 4 + b"B" * 16 + b"C" * 3
600         else:
601             data = b"A" * 16 + b"B" * 16 + b"C" * 3
602         port_in = self.random_port()
603
604         for i in range(2):
605             # out2in
606             pkts = self.create_stream_frag(self.pg0, out_addr,
607                                            port_in, out_port,
608                                            data, proto)
609             self.pg0.add_stream(pkts)
610             self.pg_enable_capture(self.pg_interfaces)
611             self.pg_start()
612             frags = self.pg1.get_capture(len(pkts))
613             p = self.reass_frags_and_verify(frags,
614                                             self.pg0.remote_ip4,
615                                             in_addr)
616             if proto != IP_PROTOS.icmp:
617                 self.assertEqual(p[layer].sport, port_in)
618                 self.assertEqual(p[layer].dport, in_port)
619             else:
620                 self.assertEqual(p[layer].id, port_in)
621             self.assertEqual(data, p[Raw].load)
622
623             # in2out
624             if proto != IP_PROTOS.icmp:
625                 pkts = self.create_stream_frag(self.pg1, self.pg0.remote_ip4,
626                                                in_port,
627                                                p[layer].sport, data, proto)
628             else:
629                 pkts = self.create_stream_frag(self.pg1, self.pg0.remote_ip4,
630                                                p[layer].id, 0, data, proto,
631                                                echo_reply=True)
632             self.pg1.add_stream(pkts)
633             self.pg_enable_capture(self.pg_interfaces)
634             self.pg_start()
635             frags = self.pg0.get_capture(len(pkts))
636             p = self.reass_frags_and_verify(frags,
637                                             out_addr,
638                                             self.pg0.remote_ip4)
639             if proto != IP_PROTOS.icmp:
640                 self.assertEqual(p[layer].sport, out_port)
641                 self.assertEqual(p[layer].dport, port_in)
642             else:
643                 self.assertEqual(p[layer].id, port_in)
644             self.assertEqual(data, p[Raw].load)
645
646     def frag_out_of_order_in_plus_out(self, in_addr, out_addr, in_port,
647                                       out_port, proto=IP_PROTOS.tcp):
648
649         layer = self.proto2layer(proto)
650
651         if proto == IP_PROTOS.tcp:
652             data = b"A" * 4 + b"B" * 16 + b"C" * 3
653         else:
654             data = b"A" * 16 + b"B" * 16 + b"C" * 3
655         port_in = self.random_port()
656
657         for i in range(2):
658             # out2in
659             pkts = self.create_stream_frag(self.pg0, out_addr,
660                                            port_in, out_port,
661                                            data, proto)
662             pkts.reverse()
663             self.pg0.add_stream(pkts)
664             self.pg_enable_capture(self.pg_interfaces)
665             self.pg_start()
666             frags = self.pg1.get_capture(len(pkts))
667             p = self.reass_frags_and_verify(frags,
668                                             self.pg0.remote_ip4,
669                                             in_addr)
670             if proto != IP_PROTOS.icmp:
671                 self.assertEqual(p[layer].dport, in_port)
672                 self.assertEqual(p[layer].sport, port_in)
673                 self.assertEqual(p[layer].dport, in_port)
674             else:
675                 self.assertEqual(p[layer].id, port_in)
676             self.assertEqual(data, p[Raw].load)
677
678             # in2out
679             if proto != IP_PROTOS.icmp:
680                 pkts = self.create_stream_frag(self.pg1, self.pg0.remote_ip4,
681                                                in_port,
682                                                p[layer].sport, data, proto)
683             else:
684                 pkts = self.create_stream_frag(self.pg1, self.pg0.remote_ip4,
685                                                p[layer].id, 0, data, proto,
686                                                echo_reply=True)
687             pkts.reverse()
688             self.pg1.add_stream(pkts)
689             self.pg_enable_capture(self.pg_interfaces)
690             self.pg_start()
691             frags = self.pg0.get_capture(len(pkts))
692             p = self.reass_frags_and_verify(frags,
693                                             out_addr,
694                                             self.pg0.remote_ip4)
695             if proto != IP_PROTOS.icmp:
696                 self.assertEqual(p[layer].sport, out_port)
697                 self.assertEqual(p[layer].dport, port_in)
698             else:
699                 self.assertEqual(p[layer].id, port_in)
700             self.assertEqual(data, p[Raw].load)
701
702     def init_tcp_session(self, in_if, out_if, in_port, ext_port):
703         # SYN packet in->out
704         p = (Ether(src=in_if.remote_mac, dst=in_if.local_mac) /
705              IP(src=in_if.remote_ip4, dst=out_if.remote_ip4) /
706              TCP(sport=in_port, dport=ext_port, flags="S"))
707         in_if.add_stream(p)
708         self.pg_enable_capture(self.pg_interfaces)
709         self.pg_start()
710         capture = out_if.get_capture(1)
711         p = capture[0]
712         out_port = p[TCP].sport
713
714         # SYN + ACK packet out->in
715         p = (Ether(src=out_if.remote_mac, dst=out_if.local_mac) /
716              IP(src=out_if.remote_ip4, dst=self.nat_addr) /
717              TCP(sport=ext_port, dport=out_port, flags="SA"))
718         out_if.add_stream(p)
719         self.pg_enable_capture(self.pg_interfaces)
720         self.pg_start()
721         in_if.get_capture(1)
722
723         # ACK 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="A"))
727         in_if.add_stream(p)
728         self.pg_enable_capture(self.pg_interfaces)
729         self.pg_start()
730         out_if.get_capture(1)
731
732         return out_port
733
734     def twice_nat_common(self, self_twice_nat=False, same_pg=False, lb=False,
735                          client_id=None):
736         twice_nat_addr = '10.0.1.3'
737
738         port_in = 8080
739         if lb:
740             if not same_pg:
741                 port_in1 = port_in
742                 port_in2 = port_in
743             else:
744                 port_in1 = port_in + 1
745                 port_in2 = port_in + 2
746
747         port_out = 80
748         eh_port_out = 4567
749
750         server1 = self.pg0.remote_hosts[0]
751         server2 = self.pg0.remote_hosts[1]
752         if lb and same_pg:
753             server2 = server1
754         if not lb:
755             server = server1
756
757         pg0 = self.pg0
758         if same_pg:
759             pg1 = self.pg0
760         else:
761             pg1 = self.pg1
762
763         eh_translate = ((not self_twice_nat) or (not lb and same_pg) or
764                         client_id == 1)
765
766         self.nat_add_address(self.nat_addr)
767         self.nat_add_address(twice_nat_addr, twice_nat=1)
768
769         flags = 0
770         if self_twice_nat:
771             flags |= self.config_flags.NAT_IS_SELF_TWICE_NAT
772         else:
773             flags |= self.config_flags.NAT_IS_TWICE_NAT
774
775         if not lb:
776             self.nat_add_static_mapping(pg0.remote_ip4, self.nat_addr,
777                                         port_in, port_out,
778                                         proto=IP_PROTOS.tcp,
779                                         flags=flags)
780         else:
781             locals = [{'addr': server1.ip4,
782                        'port': port_in1,
783                        'probability': 50,
784                        'vrf_id': 0},
785                       {'addr': server2.ip4,
786                        'port': port_in2,
787                        'probability': 50,
788                        'vrf_id': 0}]
789             out_addr = self.nat_addr
790
791             self.vapi.nat44_add_del_lb_static_mapping(is_add=1, flags=flags,
792                                                       external_addr=out_addr,
793                                                       external_port=port_out,
794                                                       protocol=IP_PROTOS.tcp,
795                                                       local_num=len(locals),
796                                                       locals=locals)
797         self.nat_add_inside_interface(pg0)
798         self.nat_add_outside_interface(pg1)
799
800         if same_pg:
801             if not lb:
802                 client = server
803             else:
804                 assert client_id is not None
805                 if client_id == 1:
806                     client = self.pg0.remote_hosts[0]
807                 elif client_id == 2:
808                     client = self.pg0.remote_hosts[1]
809         else:
810             client = pg1.remote_hosts[0]
811         p = (Ether(src=pg1.remote_mac, dst=pg1.local_mac) /
812              IP(src=client.ip4, dst=self.nat_addr) /
813              TCP(sport=eh_port_out, dport=port_out))
814         pg1.add_stream(p)
815         self.pg_enable_capture(self.pg_interfaces)
816         self.pg_start()
817         capture = pg0.get_capture(1)
818         p = capture[0]
819         try:
820             ip = p[IP]
821             tcp = p[TCP]
822             if lb:
823                 if ip.dst == server1.ip4:
824                     server = server1
825                     port_in = port_in1
826                 else:
827                     server = server2
828                     port_in = port_in2
829             self.assertEqual(ip.dst, server.ip4)
830             if lb and same_pg:
831                 self.assertIn(tcp.dport, [port_in1, port_in2])
832             else:
833                 self.assertEqual(tcp.dport, port_in)
834             if eh_translate:
835                 self.assertEqual(ip.src, twice_nat_addr)
836                 self.assertNotEqual(tcp.sport, eh_port_out)
837             else:
838                 self.assertEqual(ip.src, client.ip4)
839                 self.assertEqual(tcp.sport, eh_port_out)
840             eh_addr_in = ip.src
841             eh_port_in = tcp.sport
842             saved_port_in = tcp.dport
843             self.assert_packet_checksums_valid(p)
844         except:
845             self.logger.error(ppp("Unexpected or invalid packet:", p))
846             raise
847
848         p = (Ether(src=server.mac, dst=pg0.local_mac) /
849              IP(src=server.ip4, dst=eh_addr_in) /
850              TCP(sport=saved_port_in, dport=eh_port_in))
851         pg0.add_stream(p)
852         self.pg_enable_capture(self.pg_interfaces)
853         self.pg_start()
854         capture = pg1.get_capture(1)
855         p = capture[0]
856         try:
857             ip = p[IP]
858             tcp = p[TCP]
859             self.assertEqual(ip.dst, client.ip4)
860             self.assertEqual(ip.src, self.nat_addr)
861             self.assertEqual(tcp.dport, eh_port_out)
862             self.assertEqual(tcp.sport, port_out)
863             self.assert_packet_checksums_valid(p)
864         except:
865             self.logger.error(ppp("Unexpected or invalid packet:", p))
866             raise
867
868         if eh_translate:
869             sessions = self.vapi.nat44_user_session_dump(server.ip4, 0)
870             self.assertEqual(len(sessions), 1)
871             self.assertTrue(sessions[0].flags &
872                             self.config_flags.NAT_IS_EXT_HOST_VALID)
873             self.assertTrue(sessions[0].flags &
874                             self.config_flags.NAT_IS_TWICE_NAT)
875             self.logger.info(self.vapi.cli("show nat44 sessions"))
876             self.vapi.nat44_del_session(
877                 address=sessions[0].inside_ip_address,
878                 port=sessions[0].inside_port,
879                 protocol=sessions[0].protocol,
880                 flags=(self.config_flags.NAT_IS_INSIDE |
881                        self.config_flags.NAT_IS_EXT_HOST_VALID),
882                 ext_host_address=sessions[0].ext_host_nat_address,
883                 ext_host_port=sessions[0].ext_host_nat_port)
884             sessions = self.vapi.nat44_user_session_dump(server.ip4, 0)
885             self.assertEqual(len(sessions), 0)
886
887     def verify_syslog_sess(self, data, is_add=True, is_ip6=False):
888         message = data.decode('utf-8')
889         try:
890             message = SyslogMessage.parse(message)
891         except ParseError as e:
892             self.logger.error(e)
893             raise
894         else:
895             self.assertEqual(message.severity, SyslogSeverity.info)
896             self.assertEqual(message.appname, 'NAT')
897             self.assertEqual(message.msgid, 'SADD' if is_add else 'SDEL')
898             sd_params = message.sd.get('nsess')
899             self.assertTrue(sd_params is not None)
900             if is_ip6:
901                 self.assertEqual(sd_params.get('IATYP'), 'IPv6')
902                 self.assertEqual(sd_params.get('ISADDR'), self.pg0.remote_ip6)
903             else:
904                 self.assertEqual(sd_params.get('IATYP'), 'IPv4')
905                 self.assertEqual(sd_params.get('ISADDR'), self.pg0.remote_ip4)
906                 self.assertTrue(sd_params.get('SSUBIX') is not None)
907             self.assertEqual(sd_params.get('ISPORT'), "%d" % self.tcp_port_in)
908             self.assertEqual(sd_params.get('XATYP'), 'IPv4')
909             self.assertEqual(sd_params.get('XSADDR'), self.nat_addr)
910             self.assertEqual(sd_params.get('XSPORT'), "%d" % self.tcp_port_out)
911             self.assertEqual(sd_params.get('PROTO'), "%d" % IP_PROTOS.tcp)
912             self.assertEqual(sd_params.get('SVLAN'), '0')
913             self.assertEqual(sd_params.get('XDADDR'), self.pg1.remote_ip4)
914             self.assertEqual(sd_params.get('XDPORT'),
915                              "%d" % self.tcp_external_port)
916
917
918 @tag_fixme_vpp_workers
919 class TestNAT44ED(NAT44EDTestCase):
920     """ NAT44ED Test Case """
921
922     def test_users_dump(self):
923         """ NAT44ED API test - nat44_user_dump """
924
925         self.nat_add_address(self.nat_addr)
926         self.nat_add_inside_interface(self.pg0)
927         self.nat_add_outside_interface(self.pg1)
928
929         self.vapi.nat44_forwarding_enable_disable(enable=1)
930
931         local_ip = self.pg0.remote_ip4
932         external_ip = self.nat_addr
933         self.nat_add_static_mapping(local_ip, external_ip)
934
935         users = self.vapi.nat44_user_dump()
936         self.assertEqual(len(users), 0)
937
938         # in2out - static mapping match
939
940         pkts = self.create_stream_out(self.pg1)
941         self.pg1.add_stream(pkts)
942         self.pg_enable_capture(self.pg_interfaces)
943         self.pg_start()
944         capture = self.pg0.get_capture(len(pkts))
945         self.verify_capture_in(capture, self.pg0)
946
947         pkts = self.create_stream_in(self.pg0, self.pg1)
948         self.pg0.add_stream(pkts)
949         self.pg_enable_capture(self.pg_interfaces)
950         self.pg_start()
951         capture = self.pg1.get_capture(len(pkts))
952         self.verify_capture_out(capture, same_port=True)
953
954         users = self.vapi.nat44_user_dump()
955         self.assertEqual(len(users), 1)
956         static_user = users[0]
957         self.assertEqual(static_user.nstaticsessions, 3)
958         self.assertEqual(static_user.nsessions, 0)
959
960         # in2out - no static mapping match (forwarding test)
961
962         host0 = self.pg0.remote_hosts[0]
963         self.pg0.remote_hosts[0] = self.pg0.remote_hosts[1]
964         try:
965             pkts = self.create_stream_out(self.pg1,
966                                           dst_ip=self.pg0.remote_ip4,
967                                           use_inside_ports=True)
968             self.pg1.add_stream(pkts)
969             self.pg_enable_capture(self.pg_interfaces)
970             self.pg_start()
971             capture = self.pg0.get_capture(len(pkts))
972             self.verify_capture_in(capture, self.pg0)
973
974             pkts = self.create_stream_in(self.pg0, self.pg1)
975             self.pg0.add_stream(pkts)
976             self.pg_enable_capture(self.pg_interfaces)
977             self.pg_start()
978             capture = self.pg1.get_capture(len(pkts))
979             self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
980                                     same_port=True)
981         finally:
982             self.pg0.remote_hosts[0] = host0
983
984         users = self.vapi.nat44_user_dump()
985         self.assertEqual(len(users), 2)
986         if str(users[0].ip_address) == self.pg0.remote_hosts[0].ip4:
987             non_static_user = users[1]
988             static_user = users[0]
989         else:
990             non_static_user = users[0]
991             static_user = users[1]
992         self.assertEqual(static_user.nstaticsessions, 3)
993         self.assertEqual(static_user.nsessions, 0)
994         self.assertEqual(non_static_user.nstaticsessions, 0)
995         self.assertEqual(non_static_user.nsessions, 3)
996
997         users = self.vapi.nat44_user_dump()
998         self.assertEqual(len(users), 2)
999         if str(users[0].ip_address) == self.pg0.remote_hosts[0].ip4:
1000             non_static_user = users[1]
1001             static_user = users[0]
1002         else:
1003             non_static_user = users[0]
1004             static_user = users[1]
1005         self.assertEqual(static_user.nstaticsessions, 3)
1006         self.assertEqual(static_user.nsessions, 0)
1007         self.assertEqual(non_static_user.nstaticsessions, 0)
1008         self.assertEqual(non_static_user.nsessions, 3)
1009
1010     def test_frag_out_of_order_do_not_translate(self):
1011         """ NAT44ED don't translate fragments arriving out of order """
1012         self.nat_add_inside_interface(self.pg0)
1013         self.nat_add_outside_interface(self.pg1)
1014         self.vapi.nat44_forwarding_enable_disable(enable=True)
1015         self.frag_out_of_order(proto=IP_PROTOS.tcp, dont_translate=True)
1016
1017     def test_forwarding(self):
1018         """ NAT44ED forwarding test """
1019
1020         self.nat_add_inside_interface(self.pg0)
1021         self.nat_add_outside_interface(self.pg1)
1022         self.vapi.nat44_forwarding_enable_disable(enable=1)
1023
1024         real_ip = self.pg0.remote_ip4
1025         alias_ip = self.nat_addr
1026         flags = self.config_flags.NAT_IS_ADDR_ONLY
1027         self.vapi.nat44_add_del_static_mapping(is_add=1,
1028                                                local_ip_address=real_ip,
1029                                                external_ip_address=alias_ip,
1030                                                external_sw_if_index=0xFFFFFFFF,
1031                                                flags=flags)
1032
1033         try:
1034             # in2out - static mapping match
1035
1036             pkts = self.create_stream_out(self.pg1)
1037             self.pg1.add_stream(pkts)
1038             self.pg_enable_capture(self.pg_interfaces)
1039             self.pg_start()
1040             capture = self.pg0.get_capture(len(pkts))
1041             self.verify_capture_in(capture, self.pg0)
1042
1043             pkts = self.create_stream_in(self.pg0, self.pg1)
1044             self.pg0.add_stream(pkts)
1045             self.pg_enable_capture(self.pg_interfaces)
1046             self.pg_start()
1047             capture = self.pg1.get_capture(len(pkts))
1048             self.verify_capture_out(capture, same_port=True)
1049
1050             # in2out - no static mapping match
1051
1052             host0 = self.pg0.remote_hosts[0]
1053             self.pg0.remote_hosts[0] = self.pg0.remote_hosts[1]
1054             try:
1055                 pkts = self.create_stream_out(self.pg1,
1056                                               dst_ip=self.pg0.remote_ip4,
1057                                               use_inside_ports=True)
1058                 self.pg1.add_stream(pkts)
1059                 self.pg_enable_capture(self.pg_interfaces)
1060                 self.pg_start()
1061                 capture = self.pg0.get_capture(len(pkts))
1062                 self.verify_capture_in(capture, self.pg0)
1063
1064                 pkts = self.create_stream_in(self.pg0, self.pg1)
1065                 self.pg0.add_stream(pkts)
1066                 self.pg_enable_capture(self.pg_interfaces)
1067                 self.pg_start()
1068                 capture = self.pg1.get_capture(len(pkts))
1069                 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
1070                                         same_port=True)
1071             finally:
1072                 self.pg0.remote_hosts[0] = host0
1073
1074             user = self.pg0.remote_hosts[1]
1075             sessions = self.vapi.nat44_user_session_dump(user.ip4, 0)
1076             self.assertEqual(len(sessions), 3)
1077             self.assertTrue(sessions[0].flags &
1078                             self.config_flags.NAT_IS_EXT_HOST_VALID)
1079             self.vapi.nat44_del_session(
1080                 address=sessions[0].inside_ip_address,
1081                 port=sessions[0].inside_port,
1082                 protocol=sessions[0].protocol,
1083                 flags=(self.config_flags.NAT_IS_INSIDE |
1084                        self.config_flags.NAT_IS_EXT_HOST_VALID),
1085                 ext_host_address=sessions[0].ext_host_address,
1086                 ext_host_port=sessions[0].ext_host_port)
1087             sessions = self.vapi.nat44_user_session_dump(user.ip4, 0)
1088             self.assertEqual(len(sessions), 2)
1089
1090         finally:
1091             self.vapi.nat44_forwarding_enable_disable(enable=0)
1092             flags = self.config_flags.NAT_IS_ADDR_ONLY
1093             self.vapi.nat44_add_del_static_mapping(
1094                 is_add=0,
1095                 local_ip_address=real_ip,
1096                 external_ip_address=alias_ip,
1097                 external_sw_if_index=0xFFFFFFFF,
1098                 flags=flags)
1099
1100     def test_output_feature_and_service2(self):
1101         """ NAT44ED interface output feature and service host direct access """
1102         self.vapi.nat44_forwarding_enable_disable(enable=1)
1103         self.nat_add_address(self.nat_addr)
1104
1105         self.vapi.nat44_interface_add_del_output_feature(
1106             sw_if_index=self.pg1.sw_if_index, is_add=1,)
1107
1108         # session initiated from service host - translate
1109         pkts = self.create_stream_in(self.pg0, self.pg1)
1110         self.pg0.add_stream(pkts)
1111         self.pg_enable_capture(self.pg_interfaces)
1112         self.pg_start()
1113         capture = self.pg1.get_capture(len(pkts))
1114         self.verify_capture_out(capture, ignore_port=True)
1115
1116         pkts = self.create_stream_out(self.pg1)
1117         self.pg1.add_stream(pkts)
1118         self.pg_enable_capture(self.pg_interfaces)
1119         self.pg_start()
1120         capture = self.pg0.get_capture(len(pkts))
1121         self.verify_capture_in(capture, self.pg0)
1122
1123         # session initiated from remote host - do not translate
1124         tcp_port_in = self.tcp_port_in
1125         udp_port_in = self.udp_port_in
1126         icmp_id_in = self.icmp_id_in
1127
1128         self.tcp_port_in = 60303
1129         self.udp_port_in = 60304
1130         self.icmp_id_in = 60305
1131
1132         try:
1133             pkts = self.create_stream_out(self.pg1,
1134                                           self.pg0.remote_ip4,
1135                                           use_inside_ports=True)
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, nat_ip=self.pg0.remote_ip4,
1148                                     same_port=True)
1149         finally:
1150             self.tcp_port_in = tcp_port_in
1151             self.udp_port_in = udp_port_in
1152             self.icmp_id_in = icmp_id_in
1153
1154     def test_twice_nat(self):
1155         """ NAT44ED Twice NAT """
1156         self.twice_nat_common()
1157
1158     def test_self_twice_nat_positive(self):
1159         """ NAT44ED Self Twice NAT (positive test) """
1160         self.twice_nat_common(self_twice_nat=True, same_pg=True)
1161
1162     def test_self_twice_nat_lb_positive(self):
1163         """ NAT44ED Self Twice NAT local service load balancing (positive test)
1164         """
1165         self.twice_nat_common(lb=True, self_twice_nat=True, same_pg=True,
1166                               client_id=1)
1167
1168     def test_twice_nat_lb(self):
1169         """ NAT44ED Twice NAT local service load balancing """
1170         self.twice_nat_common(lb=True)
1171
1172     def test_output_feature(self):
1173         """ NAT44ED interface output feature (in2out postrouting) """
1174         self.vapi.nat44_forwarding_enable_disable(enable=1)
1175         self.nat_add_address(self.nat_addr)
1176
1177         self.nat_add_outside_interface(self.pg0)
1178         self.vapi.nat44_interface_add_del_output_feature(
1179             sw_if_index=self.pg1.sw_if_index, is_add=1)
1180
1181         # in2out
1182         pkts = self.create_stream_in(self.pg0, self.pg1)
1183         self.pg0.add_stream(pkts)
1184         self.pg_enable_capture(self.pg_interfaces)
1185         self.pg_start()
1186         capture = self.pg1.get_capture(len(pkts))
1187         self.verify_capture_out(capture, ignore_port=True)
1188
1189         # out2in
1190         pkts = self.create_stream_out(self.pg1)
1191         self.pg1.add_stream(pkts)
1192         self.pg_enable_capture(self.pg_interfaces)
1193         self.pg_start()
1194         capture = self.pg0.get_capture(len(pkts))
1195         self.verify_capture_in(capture, self.pg0)
1196
1197     def test_static_with_port_out2(self):
1198         """ NAT44ED 1:1 NAPT asymmetrical rule """
1199
1200         external_port = 80
1201         local_port = 8080
1202
1203         self.vapi.nat44_forwarding_enable_disable(enable=1)
1204         flags = self.config_flags.NAT_IS_OUT2IN_ONLY
1205         self.nat_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1206                                     local_port, external_port,
1207                                     proto=IP_PROTOS.tcp, flags=flags)
1208
1209         self.nat_add_inside_interface(self.pg0)
1210         self.nat_add_outside_interface(self.pg1)
1211
1212         # from client to service
1213         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
1214              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
1215              TCP(sport=12345, dport=external_port))
1216         self.pg1.add_stream(p)
1217         self.pg_enable_capture(self.pg_interfaces)
1218         self.pg_start()
1219         capture = self.pg0.get_capture(1)
1220         p = capture[0]
1221         try:
1222             ip = p[IP]
1223             tcp = p[TCP]
1224             self.assertEqual(ip.dst, self.pg0.remote_ip4)
1225             self.assertEqual(tcp.dport, local_port)
1226             self.assert_packet_checksums_valid(p)
1227         except:
1228             self.logger.error(ppp("Unexpected or invalid packet:", p))
1229             raise
1230
1231         # ICMP error
1232         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1233              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
1234              ICMP(type=11) / capture[0][IP])
1235         self.pg0.add_stream(p)
1236         self.pg_enable_capture(self.pg_interfaces)
1237         self.pg_start()
1238         capture = self.pg1.get_capture(1)
1239         p = capture[0]
1240         try:
1241             self.assertEqual(p[IP].src, self.nat_addr)
1242             inner = p[IPerror]
1243             self.assertEqual(inner.dst, self.nat_addr)
1244             self.assertEqual(inner[TCPerror].dport, external_port)
1245         except:
1246             self.logger.error(ppp("Unexpected or invalid packet:", p))
1247             raise
1248
1249         # from service back to client
1250         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
1251              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
1252              TCP(sport=local_port, dport=12345))
1253         self.pg0.add_stream(p)
1254         self.pg_enable_capture(self.pg_interfaces)
1255         self.pg_start()
1256         capture = self.pg1.get_capture(1)
1257         p = capture[0]
1258         try:
1259             ip = p[IP]
1260             tcp = p[TCP]
1261             self.assertEqual(ip.src, self.nat_addr)
1262             self.assertEqual(tcp.sport, external_port)
1263             self.assert_packet_checksums_valid(p)
1264         except:
1265             self.logger.error(ppp("Unexpected or invalid packet:", p))
1266             raise
1267
1268         # ICMP error
1269         p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1270              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
1271              ICMP(type=11) / capture[0][IP])
1272         self.pg1.add_stream(p)
1273         self.pg_enable_capture(self.pg_interfaces)
1274         self.pg_start()
1275         capture = self.pg0.get_capture(1)
1276         p = capture[0]
1277         try:
1278             self.assertEqual(p[IP].dst, self.pg0.remote_ip4)
1279             inner = p[IPerror]
1280             self.assertEqual(inner.src, self.pg0.remote_ip4)
1281             self.assertEqual(inner[TCPerror].sport, local_port)
1282         except:
1283             self.logger.error(ppp("Unexpected or invalid packet:", p))
1284             raise
1285
1286         # from client to server (no translation)
1287         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
1288              IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
1289              TCP(sport=12346, dport=local_port))
1290         self.pg1.add_stream(p)
1291         self.pg_enable_capture(self.pg_interfaces)
1292         self.pg_start()
1293         capture = self.pg0.get_capture(1)
1294         p = capture[0]
1295         try:
1296             ip = p[IP]
1297             tcp = p[TCP]
1298             self.assertEqual(ip.dst, self.pg0.remote_ip4)
1299             self.assertEqual(tcp.dport, local_port)
1300             self.assert_packet_checksums_valid(p)
1301         except:
1302             self.logger.error(ppp("Unexpected or invalid packet:", p))
1303             raise
1304
1305         # from service back to client (no translation)
1306         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
1307              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
1308              TCP(sport=local_port, dport=12346))
1309         self.pg0.add_stream(p)
1310         self.pg_enable_capture(self.pg_interfaces)
1311         self.pg_start()
1312         capture = self.pg1.get_capture(1)
1313         p = capture[0]
1314         try:
1315             ip = p[IP]
1316             tcp = p[TCP]
1317             self.assertEqual(ip.src, self.pg0.remote_ip4)
1318             self.assertEqual(tcp.sport, local_port)
1319             self.assert_packet_checksums_valid(p)
1320         except:
1321             self.logger.error(ppp("Unexpected or invalid packet:", p))
1322             raise
1323
1324     def test_static_lb(self):
1325         """ NAT44ED local service load balancing """
1326         external_addr_n = self.nat_addr
1327         external_port = 80
1328         local_port = 8080
1329         server1 = self.pg0.remote_hosts[0]
1330         server2 = self.pg0.remote_hosts[1]
1331
1332         locals = [{'addr': server1.ip4,
1333                    'port': local_port,
1334                    'probability': 70,
1335                    'vrf_id': 0},
1336                   {'addr': server2.ip4,
1337                    'port': local_port,
1338                    'probability': 30,
1339                    'vrf_id': 0}]
1340
1341         self.nat_add_address(self.nat_addr)
1342         self.vapi.nat44_add_del_lb_static_mapping(
1343             is_add=1,
1344             external_addr=external_addr_n,
1345             external_port=external_port,
1346             protocol=IP_PROTOS.tcp,
1347             local_num=len(locals),
1348             locals=locals)
1349         flags = self.config_flags.NAT_IS_INSIDE
1350         self.vapi.nat44_interface_add_del_feature(
1351             sw_if_index=self.pg0.sw_if_index,
1352             flags=flags, is_add=1)
1353         self.vapi.nat44_interface_add_del_feature(
1354             sw_if_index=self.pg1.sw_if_index,
1355             is_add=1)
1356
1357         # from client to service
1358         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
1359              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
1360              TCP(sport=12345, dport=external_port))
1361         self.pg1.add_stream(p)
1362         self.pg_enable_capture(self.pg_interfaces)
1363         self.pg_start()
1364         capture = self.pg0.get_capture(1)
1365         p = capture[0]
1366         server = None
1367         try:
1368             ip = p[IP]
1369             tcp = p[TCP]
1370             self.assertIn(ip.dst, [server1.ip4, server2.ip4])
1371             if ip.dst == server1.ip4:
1372                 server = server1
1373             else:
1374                 server = server2
1375             self.assertEqual(tcp.dport, local_port)
1376             self.assert_packet_checksums_valid(p)
1377         except:
1378             self.logger.error(ppp("Unexpected or invalid packet:", p))
1379             raise
1380
1381         # from service back to client
1382         p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
1383              IP(src=server.ip4, dst=self.pg1.remote_ip4) /
1384              TCP(sport=local_port, dport=12345))
1385         self.pg0.add_stream(p)
1386         self.pg_enable_capture(self.pg_interfaces)
1387         self.pg_start()
1388         capture = self.pg1.get_capture(1)
1389         p = capture[0]
1390         try:
1391             ip = p[IP]
1392             tcp = p[TCP]
1393             self.assertEqual(ip.src, self.nat_addr)
1394             self.assertEqual(tcp.sport, external_port)
1395             self.assert_packet_checksums_valid(p)
1396         except:
1397             self.logger.error(ppp("Unexpected or invalid packet:", p))
1398             raise
1399
1400         sessions = self.vapi.nat44_user_session_dump(server.ip4, 0)
1401         self.assertEqual(len(sessions), 1)
1402         self.assertTrue(sessions[0].flags &
1403                         self.config_flags.NAT_IS_EXT_HOST_VALID)
1404         self.vapi.nat44_del_session(
1405             address=sessions[0].inside_ip_address,
1406             port=sessions[0].inside_port,
1407             protocol=sessions[0].protocol,
1408             flags=(self.config_flags.NAT_IS_INSIDE |
1409                    self.config_flags.NAT_IS_EXT_HOST_VALID),
1410             ext_host_address=sessions[0].ext_host_address,
1411             ext_host_port=sessions[0].ext_host_port)
1412         sessions = self.vapi.nat44_user_session_dump(server.ip4, 0)
1413         self.assertEqual(len(sessions), 0)
1414
1415     def test_static_lb_2(self):
1416         """ NAT44ED local service load balancing (asymmetrical rule) """
1417         external_addr = self.nat_addr
1418         external_port = 80
1419         local_port = 8080
1420         server1 = self.pg0.remote_hosts[0]
1421         server2 = self.pg0.remote_hosts[1]
1422
1423         locals = [{'addr': server1.ip4,
1424                    'port': local_port,
1425                    'probability': 70,
1426                    'vrf_id': 0},
1427                   {'addr': server2.ip4,
1428                    'port': local_port,
1429                    'probability': 30,
1430                    'vrf_id': 0}]
1431
1432         self.vapi.nat44_forwarding_enable_disable(enable=1)
1433         flags = self.config_flags.NAT_IS_OUT2IN_ONLY
1434         self.vapi.nat44_add_del_lb_static_mapping(is_add=1, flags=flags,
1435                                                   external_addr=external_addr,
1436                                                   external_port=external_port,
1437                                                   protocol=IP_PROTOS.tcp,
1438                                                   local_num=len(locals),
1439                                                   locals=locals)
1440         flags = self.config_flags.NAT_IS_INSIDE
1441         self.vapi.nat44_interface_add_del_feature(
1442             sw_if_index=self.pg0.sw_if_index,
1443             flags=flags, is_add=1)
1444         self.vapi.nat44_interface_add_del_feature(
1445             sw_if_index=self.pg1.sw_if_index,
1446             is_add=1)
1447
1448         # from client to service
1449         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
1450              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
1451              TCP(sport=12345, dport=external_port))
1452         self.pg1.add_stream(p)
1453         self.pg_enable_capture(self.pg_interfaces)
1454         self.pg_start()
1455         capture = self.pg0.get_capture(1)
1456         p = capture[0]
1457         server = None
1458         try:
1459             ip = p[IP]
1460             tcp = p[TCP]
1461             self.assertIn(ip.dst, [server1.ip4, server2.ip4])
1462             if ip.dst == server1.ip4:
1463                 server = server1
1464             else:
1465                 server = server2
1466             self.assertEqual(tcp.dport, local_port)
1467             self.assert_packet_checksums_valid(p)
1468         except:
1469             self.logger.error(ppp("Unexpected or invalid packet:", p))
1470             raise
1471
1472         # from service back to client
1473         p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
1474              IP(src=server.ip4, dst=self.pg1.remote_ip4) /
1475              TCP(sport=local_port, dport=12345))
1476         self.pg0.add_stream(p)
1477         self.pg_enable_capture(self.pg_interfaces)
1478         self.pg_start()
1479         capture = self.pg1.get_capture(1)
1480         p = capture[0]
1481         try:
1482             ip = p[IP]
1483             tcp = p[TCP]
1484             self.assertEqual(ip.src, self.nat_addr)
1485             self.assertEqual(tcp.sport, external_port)
1486             self.assert_packet_checksums_valid(p)
1487         except:
1488             self.logger.error(ppp("Unexpected or invalid packet:", p))
1489             raise
1490
1491         # from client to server (no translation)
1492         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
1493              IP(src=self.pg1.remote_ip4, dst=server1.ip4) /
1494              TCP(sport=12346, dport=local_port))
1495         self.pg1.add_stream(p)
1496         self.pg_enable_capture(self.pg_interfaces)
1497         self.pg_start()
1498         capture = self.pg0.get_capture(1)
1499         p = capture[0]
1500         server = None
1501         try:
1502             ip = p[IP]
1503             tcp = p[TCP]
1504             self.assertEqual(ip.dst, server1.ip4)
1505             self.assertEqual(tcp.dport, local_port)
1506             self.assert_packet_checksums_valid(p)
1507         except:
1508             self.logger.error(ppp("Unexpected or invalid packet:", p))
1509             raise
1510
1511         # from service back to client (no translation)
1512         p = (Ether(src=server1.mac, dst=self.pg0.local_mac) /
1513              IP(src=server1.ip4, dst=self.pg1.remote_ip4) /
1514              TCP(sport=local_port, dport=12346))
1515         self.pg0.add_stream(p)
1516         self.pg_enable_capture(self.pg_interfaces)
1517         self.pg_start()
1518         capture = self.pg1.get_capture(1)
1519         p = capture[0]
1520         try:
1521             ip = p[IP]
1522             tcp = p[TCP]
1523             self.assertEqual(ip.src, server1.ip4)
1524             self.assertEqual(tcp.sport, local_port)
1525             self.assert_packet_checksums_valid(p)
1526         except:
1527             self.logger.error(ppp("Unexpected or invalid packet:", p))
1528             raise
1529
1530     def test_lb_affinity(self):
1531         """ NAT44ED local service load balancing affinity """
1532         external_addr = self.nat_addr
1533         external_port = 80
1534         local_port = 8080
1535         server1 = self.pg0.remote_hosts[0]
1536         server2 = self.pg0.remote_hosts[1]
1537
1538         locals = [{'addr': server1.ip4,
1539                    'port': local_port,
1540                    'probability': 50,
1541                    'vrf_id': 0},
1542                   {'addr': server2.ip4,
1543                    'port': local_port,
1544                    'probability': 50,
1545                    'vrf_id': 0}]
1546
1547         self.nat_add_address(self.nat_addr)
1548         self.vapi.nat44_add_del_lb_static_mapping(is_add=1,
1549                                                   external_addr=external_addr,
1550                                                   external_port=external_port,
1551                                                   protocol=IP_PROTOS.tcp,
1552                                                   affinity=10800,
1553                                                   local_num=len(locals),
1554                                                   locals=locals)
1555         flags = self.config_flags.NAT_IS_INSIDE
1556         self.vapi.nat44_interface_add_del_feature(
1557             sw_if_index=self.pg0.sw_if_index,
1558             flags=flags, is_add=1)
1559         self.vapi.nat44_interface_add_del_feature(
1560             sw_if_index=self.pg1.sw_if_index,
1561             is_add=1)
1562
1563         p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1564              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
1565              TCP(sport=1025, dport=external_port))
1566         self.pg1.add_stream(p)
1567         self.pg_enable_capture(self.pg_interfaces)
1568         self.pg_start()
1569         capture = self.pg0.get_capture(1)
1570         backend = capture[0][IP].dst
1571
1572         sessions = self.vapi.nat44_user_session_dump(backend, 0)
1573         self.assertEqual(len(sessions), 1)
1574         self.assertTrue(sessions[0].flags &
1575                         self.config_flags.NAT_IS_EXT_HOST_VALID)
1576         self.vapi.nat44_del_session(
1577             address=sessions[0].inside_ip_address,
1578             port=sessions[0].inside_port,
1579             protocol=sessions[0].protocol,
1580             flags=(self.config_flags.NAT_IS_INSIDE |
1581                    self.config_flags.NAT_IS_EXT_HOST_VALID),
1582             ext_host_address=sessions[0].ext_host_address,
1583             ext_host_port=sessions[0].ext_host_port)
1584
1585         pkts = []
1586         for port in range(1030, 1100):
1587             p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1588                  IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
1589                  TCP(sport=port, dport=external_port))
1590             pkts.append(p)
1591         self.pg1.add_stream(pkts)
1592         self.pg_enable_capture(self.pg_interfaces)
1593         self.pg_start()
1594         capture = self.pg0.get_capture(len(pkts))
1595         for p in capture:
1596             self.assertEqual(p[IP].dst, backend)
1597
1598     def test_multiple_vrf(self):
1599         """ NAT44ED Multiple VRF setup """
1600
1601         external_addr = '1.2.3.4'
1602         external_port = 80
1603         local_port = 8080
1604         port = 0
1605
1606         self.vapi.nat44_forwarding_enable_disable(enable=1)
1607         self.nat_add_address(self.nat_addr)
1608         flags = self.config_flags.NAT_IS_INSIDE
1609         self.vapi.nat44_interface_add_del_feature(
1610             sw_if_index=self.pg0.sw_if_index,
1611             is_add=1)
1612         self.vapi.nat44_interface_add_del_feature(
1613             sw_if_index=self.pg0.sw_if_index,
1614             is_add=1, flags=flags)
1615         self.vapi.nat44_interface_add_del_output_feature(
1616             sw_if_index=self.pg1.sw_if_index,
1617             is_add=1)
1618         self.vapi.nat44_interface_add_del_feature(
1619             sw_if_index=self.pg5.sw_if_index,
1620             is_add=1)
1621         self.vapi.nat44_interface_add_del_feature(
1622             sw_if_index=self.pg5.sw_if_index,
1623             is_add=1, flags=flags)
1624         self.vapi.nat44_interface_add_del_feature(
1625             sw_if_index=self.pg6.sw_if_index,
1626             is_add=1)
1627         flags = self.config_flags.NAT_IS_OUT2IN_ONLY
1628         self.nat_add_static_mapping(self.pg5.remote_ip4, external_addr,
1629                                     local_port, external_port, vrf_id=1,
1630                                     proto=IP_PROTOS.tcp, flags=flags)
1631         self.nat_add_static_mapping(
1632             self.pg0.remote_ip4,
1633             external_sw_if_index=self.pg0.sw_if_index,
1634             local_port=local_port,
1635             vrf_id=0,
1636             external_port=external_port,
1637             proto=IP_PROTOS.tcp,
1638             flags=flags
1639         )
1640
1641         # from client to service (both VRF1)
1642         p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
1643              IP(src=self.pg6.remote_ip4, dst=external_addr) /
1644              TCP(sport=12345, dport=external_port))
1645         self.pg6.add_stream(p)
1646         self.pg_enable_capture(self.pg_interfaces)
1647         self.pg_start()
1648         capture = self.pg5.get_capture(1)
1649         p = capture[0]
1650         try:
1651             ip = p[IP]
1652             tcp = p[TCP]
1653             self.assertEqual(ip.dst, self.pg5.remote_ip4)
1654             self.assertEqual(tcp.dport, local_port)
1655             self.assert_packet_checksums_valid(p)
1656         except:
1657             self.logger.error(ppp("Unexpected or invalid packet:", p))
1658             raise
1659
1660         # from service back to client (both VRF1)
1661         p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
1662              IP(src=self.pg5.remote_ip4, dst=self.pg6.remote_ip4) /
1663              TCP(sport=local_port, dport=12345))
1664         self.pg5.add_stream(p)
1665         self.pg_enable_capture(self.pg_interfaces)
1666         self.pg_start()
1667         capture = self.pg6.get_capture(1)
1668         p = capture[0]
1669         try:
1670             ip = p[IP]
1671             tcp = p[TCP]
1672             self.assertEqual(ip.src, external_addr)
1673             self.assertEqual(tcp.sport, external_port)
1674             self.assert_packet_checksums_valid(p)
1675         except:
1676             self.logger.error(ppp("Unexpected or invalid packet:", p))
1677             raise
1678
1679         # dynamic NAT from VRF1 to VRF0 (output-feature)
1680         p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
1681              IP(src=self.pg5.remote_ip4, dst=self.pg1.remote_ip4) /
1682              TCP(sport=2345, dport=22))
1683         self.pg5.add_stream(p)
1684         self.pg_enable_capture(self.pg_interfaces)
1685         self.pg_start()
1686         capture = self.pg1.get_capture(1)
1687         p = capture[0]
1688         try:
1689             ip = p[IP]
1690             tcp = p[TCP]
1691             self.assertEqual(ip.src, self.nat_addr)
1692             self.assert_packet_checksums_valid(p)
1693             port = tcp.sport
1694         except:
1695             self.logger.error(ppp("Unexpected or invalid packet:", p))
1696             raise
1697
1698         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
1699              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
1700              TCP(sport=22, dport=port))
1701         self.pg1.add_stream(p)
1702         self.pg_enable_capture(self.pg_interfaces)
1703         self.pg_start()
1704         capture = self.pg5.get_capture(1)
1705         p = capture[0]
1706         try:
1707             ip = p[IP]
1708             tcp = p[TCP]
1709             self.assertEqual(ip.dst, self.pg5.remote_ip4)
1710             self.assertEqual(tcp.dport, 2345)
1711             self.assert_packet_checksums_valid(p)
1712         except:
1713             self.logger.error(ppp("Unexpected or invalid packet:", p))
1714             raise
1715
1716         # from client VRF1 to service VRF0
1717         p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
1718              IP(src=self.pg6.remote_ip4, dst=self.pg0.local_ip4) /
1719              TCP(sport=12346, dport=external_port))
1720         self.pg6.add_stream(p)
1721         self.pg_enable_capture(self.pg_interfaces)
1722         self.pg_start()
1723         capture = self.pg0.get_capture(1)
1724         p = capture[0]
1725         try:
1726             ip = p[IP]
1727             tcp = p[TCP]
1728             self.assertEqual(ip.dst, self.pg0.remote_ip4)
1729             self.assertEqual(tcp.dport, local_port)
1730             self.assert_packet_checksums_valid(p)
1731         except:
1732             self.logger.error(ppp("Unexpected or invalid packet:", p))
1733             raise
1734
1735         # from service VRF0 back to client VRF1
1736         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
1737              IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
1738              TCP(sport=local_port, dport=12346))
1739         self.pg0.add_stream(p)
1740         self.pg_enable_capture(self.pg_interfaces)
1741         self.pg_start()
1742         capture = self.pg6.get_capture(1)
1743         p = capture[0]
1744         try:
1745             ip = p[IP]
1746             tcp = p[TCP]
1747             self.assertEqual(ip.src, self.pg0.local_ip4)
1748             self.assertEqual(tcp.sport, external_port)
1749             self.assert_packet_checksums_valid(p)
1750         except:
1751             self.logger.error(ppp("Unexpected or invalid packet:", p))
1752             raise
1753
1754         # from client VRF0 to service VRF1
1755         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
1756              IP(src=self.pg0.remote_ip4, dst=external_addr) /
1757              TCP(sport=12347, dport=external_port))
1758         self.pg0.add_stream(p)
1759         self.pg_enable_capture(self.pg_interfaces)
1760         self.pg_start()
1761         capture = self.pg5.get_capture(1)
1762         p = capture[0]
1763         try:
1764             ip = p[IP]
1765             tcp = p[TCP]
1766             self.assertEqual(ip.dst, self.pg5.remote_ip4)
1767             self.assertEqual(tcp.dport, local_port)
1768             self.assert_packet_checksums_valid(p)
1769         except:
1770             self.logger.error(ppp("Unexpected or invalid packet:", p))
1771             raise
1772
1773         # from service VRF1 back to client VRF0
1774         p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
1775              IP(src=self.pg5.remote_ip4, dst=self.pg0.remote_ip4) /
1776              TCP(sport=local_port, dport=12347))
1777         self.pg5.add_stream(p)
1778         self.pg_enable_capture(self.pg_interfaces)
1779         self.pg_start()
1780         capture = self.pg0.get_capture(1)
1781         p = capture[0]
1782         try:
1783             ip = p[IP]
1784             tcp = p[TCP]
1785             self.assertEqual(ip.src, external_addr)
1786             self.assertEqual(tcp.sport, external_port)
1787             self.assert_packet_checksums_valid(p)
1788         except:
1789             self.logger.error(ppp("Unexpected or invalid packet:", p))
1790             raise
1791
1792         # from client to server (both VRF1, no translation)
1793         p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
1794              IP(src=self.pg6.remote_ip4, dst=self.pg5.remote_ip4) /
1795              TCP(sport=12348, dport=local_port))
1796         self.pg6.add_stream(p)
1797         self.pg_enable_capture(self.pg_interfaces)
1798         self.pg_start()
1799         capture = self.pg5.get_capture(1)
1800         p = capture[0]
1801         try:
1802             ip = p[IP]
1803             tcp = p[TCP]
1804             self.assertEqual(ip.dst, self.pg5.remote_ip4)
1805             self.assertEqual(tcp.dport, local_port)
1806             self.assert_packet_checksums_valid(p)
1807         except:
1808             self.logger.error(ppp("Unexpected or invalid packet:", p))
1809             raise
1810
1811         # from server back to client (both VRF1, no translation)
1812         p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
1813              IP(src=self.pg5.remote_ip4, dst=self.pg6.remote_ip4) /
1814              TCP(sport=local_port, dport=12348))
1815         self.pg5.add_stream(p)
1816         self.pg_enable_capture(self.pg_interfaces)
1817         self.pg_start()
1818         capture = self.pg6.get_capture(1)
1819         p = capture[0]
1820         try:
1821             ip = p[IP]
1822             tcp = p[TCP]
1823             self.assertEqual(ip.src, self.pg5.remote_ip4)
1824             self.assertEqual(tcp.sport, local_port)
1825             self.assert_packet_checksums_valid(p)
1826         except:
1827             self.logger.error(ppp("Unexpected or invalid packet:", p))
1828             raise
1829
1830         # from client VRF1 to server VRF0 (no translation)
1831         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
1832              IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
1833              TCP(sport=local_port, dport=12349))
1834         self.pg0.add_stream(p)
1835         self.pg_enable_capture(self.pg_interfaces)
1836         self.pg_start()
1837         capture = self.pg6.get_capture(1)
1838         p = capture[0]
1839         try:
1840             ip = p[IP]
1841             tcp = p[TCP]
1842             self.assertEqual(ip.src, self.pg0.remote_ip4)
1843             self.assertEqual(tcp.sport, local_port)
1844             self.assert_packet_checksums_valid(p)
1845         except:
1846             self.logger.error(ppp("Unexpected or invalid packet:", p))
1847             raise
1848
1849         # from server VRF0 back to client VRF1 (no translation)
1850         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
1851              IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
1852              TCP(sport=local_port, dport=12349))
1853         self.pg0.add_stream(p)
1854         self.pg_enable_capture(self.pg_interfaces)
1855         self.pg_start()
1856         capture = self.pg6.get_capture(1)
1857         p = capture[0]
1858         try:
1859             ip = p[IP]
1860             tcp = p[TCP]
1861             self.assertEqual(ip.src, self.pg0.remote_ip4)
1862             self.assertEqual(tcp.sport, local_port)
1863             self.assert_packet_checksums_valid(p)
1864         except:
1865             self.logger.error(ppp("Unexpected or invalid packet:", p))
1866             raise
1867
1868         # from client VRF0 to server VRF1 (no translation)
1869         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
1870              IP(src=self.pg0.remote_ip4, dst=self.pg5.remote_ip4) /
1871              TCP(sport=12344, dport=local_port))
1872         self.pg0.add_stream(p)
1873         self.pg_enable_capture(self.pg_interfaces)
1874         self.pg_start()
1875         capture = self.pg5.get_capture(1)
1876         p = capture[0]
1877         try:
1878             ip = p[IP]
1879             tcp = p[TCP]
1880             self.assertEqual(ip.dst, self.pg5.remote_ip4)
1881             self.assertEqual(tcp.dport, local_port)
1882             self.assert_packet_checksums_valid(p)
1883         except:
1884             self.logger.error(ppp("Unexpected or invalid packet:", p))
1885             raise
1886
1887         # from server VRF1 back to client VRF0 (no translation)
1888         p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
1889              IP(src=self.pg5.remote_ip4, dst=self.pg0.remote_ip4) /
1890              TCP(sport=local_port, dport=12344))
1891         self.pg5.add_stream(p)
1892         self.pg_enable_capture(self.pg_interfaces)
1893         self.pg_start()
1894         capture = self.pg0.get_capture(1)
1895         p = capture[0]
1896         try:
1897             ip = p[IP]
1898             tcp = p[TCP]
1899             self.assertEqual(ip.src, self.pg5.remote_ip4)
1900             self.assertEqual(tcp.sport, local_port)
1901             self.assert_packet_checksums_valid(p)
1902         except:
1903             self.logger.error(ppp("Unexpected or invalid packet:", p))
1904             raise
1905
1906     def test_outside_address_distribution(self):
1907         """ Outside address distribution based on source address """
1908
1909         x = 100
1910         nat_addresses = []
1911
1912         for i in range(1, x):
1913             a = "10.0.0.%d" % i
1914             nat_addresses.append(a)
1915
1916         self.nat_add_inside_interface(self.pg0)
1917         self.nat_add_outside_interface(self.pg1)
1918
1919         self.vapi.nat44_add_del_address_range(
1920             first_ip_address=nat_addresses[0],
1921             last_ip_address=nat_addresses[-1],
1922             vrf_id=0xFFFFFFFF, is_add=1, flags=0)
1923
1924         self.pg0.generate_remote_hosts(x)
1925
1926         pkts = []
1927         for i in range(x):
1928             p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1929                  IP(src=self.pg0.remote_hosts[i].ip4,
1930                      dst=self.pg1.remote_ip4) /
1931                  UDP(sport=7000+i, dport=80+i))
1932             pkts.append(p)
1933
1934         self.pg0.add_stream(pkts)
1935         self.pg_enable_capture(self.pg_interfaces)
1936         self.pg_start()
1937         recvd = self.pg1.get_capture(len(pkts))
1938         for (p_sent, p_recvd) in zip(pkts, recvd):
1939             packed = socket.inet_aton(p_sent[IP].src)
1940             numeric = struct.unpack("!L", packed)[0]
1941             numeric = socket.htonl(numeric)
1942             a = nat_addresses[(numeric-1) % len(nat_addresses)]
1943             self.assertEqual(a, p_recvd[IP].src, "Packet not translated")
1944
1945
1946 class TestNAT44EDMW(TestNAT44ED):
1947     """ NAT44ED MW Test Case """
1948     worker_config = "workers 1"
1949
1950     def get_stats_counter(self, path, worker=1):
1951         return super(TestNAT44EDMW, self).get_stats_counter(path, worker)
1952
1953     @unittest.skip('MW fix required')
1954     def test_users_dump(self):
1955         """ NAT44ED API test - nat44_user_dump """
1956
1957     @unittest.skip('MW fix required')
1958     def test_frag_out_of_order_do_not_translate(self):
1959         """ NAT44ED don't translate fragments arriving out of order """
1960
1961     @unittest.skip('MW fix required')
1962     def test_forwarding(self):
1963         """ NAT44ED forwarding test """
1964
1965     @unittest.skip('MW fix required')
1966     def test_twice_nat(self):
1967         """ NAT44ED Twice NAT """
1968
1969     @unittest.skip('MW fix required')
1970     def test_twice_nat_lb(self):
1971         """ NAT44ED Twice NAT local service load balancing """
1972
1973     @unittest.skip('MW fix required')
1974     def test_output_feature(self):
1975         """ NAT44ED interface output feature (in2out postrouting) """
1976
1977     @unittest.skip('MW fix required')
1978     def test_static_with_port_out2(self):
1979         """ NAT44ED 1:1 NAPT asymmetrical rule """
1980
1981     @unittest.skip('MW fix required')
1982     def test_output_feature_and_service2(self):
1983         """ NAT44ED interface output feature and service host direct access """
1984
1985     @unittest.skip('MW fix required')
1986     def test_static_lb(self):
1987         """ NAT44ED local service load balancing """
1988
1989     @unittest.skip('MW fix required')
1990     def test_static_lb_2(self):
1991         """ NAT44ED local service load balancing (asymmetrical rule) """
1992
1993     @unittest.skip('MW fix required')
1994     def test_lb_affinity(self):
1995         """ NAT44ED local service load balancing affinity """
1996
1997     @unittest.skip('MW fix required')
1998     def test_multiple_vrf(self):
1999         """ NAT44ED Multiple VRF setup """
2000
2001     @unittest.skip('MW fix required')
2002     def test_self_twice_nat_positive(self):
2003         """ NAT44ED Self Twice NAT (positive test) """
2004
2005     @unittest.skip('MW fix required')
2006     def test_self_twice_nat_lb_positive(self):
2007         """ NAT44ED Self Twice NAT local service load balancing (positive test)
2008         """
2009
2010     def test_dynamic(self):
2011         """ NAT44ED dynamic translation test """
2012
2013         self.nat_add_address(self.nat_addr)
2014         self.nat_add_inside_interface(self.pg0)
2015         self.nat_add_outside_interface(self.pg1)
2016
2017         # in2out
2018         tc1 = self.get_stats_counter('/nat44-ed/in2out/slowpath/tcp')
2019         uc1 = self.get_stats_counter('/nat44-ed/in2out/slowpath/udp')
2020         ic1 = self.get_stats_counter('/nat44-ed/in2out/slowpath/icmp')
2021         dc1 = self.get_stats_counter('/nat44-ed/in2out/slowpath/drops')
2022
2023         pkts = self.create_stream_in(self.pg0, self.pg1)
2024         # TODO: specify worker=idx, also stats have to
2025         #       know from which worker to take capture
2026         self.pg0.add_stream(pkts)
2027         self.pg_enable_capture(self.pg_interfaces)
2028         self.pg_start()
2029         capture = self.pg1.get_capture(len(pkts))
2030         self.verify_capture_out(capture, ignore_port=True)
2031
2032         if_idx = self.pg0.sw_if_index
2033         tc2 = self.get_stats_counter('/nat44-ed/in2out/slowpath/tcp')
2034         uc2 = self.get_stats_counter('/nat44-ed/in2out/slowpath/udp')
2035         ic2 = self.get_stats_counter('/nat44-ed/in2out/slowpath/icmp')
2036         dc2 = self.get_stats_counter('/nat44-ed/in2out/slowpath/drops')
2037
2038         self.assertEqual(tc2[if_idx] - tc1[if_idx], 2)
2039         self.assertEqual(uc2[if_idx] - uc1[if_idx], 1)
2040         self.assertEqual(ic2[if_idx] - ic1[if_idx], 1)
2041         self.assertEqual(dc2[if_idx] - dc1[if_idx], 0)
2042
2043         # out2in
2044         tc1 = self.get_stats_counter('/nat44-ed/out2in/fastpath/tcp')
2045         uc1 = self.get_stats_counter('/nat44-ed/out2in/fastpath/udp')
2046         ic1 = self.get_stats_counter('/nat44-ed/out2in/fastpath/icmp')
2047         dc1 = self.get_stats_counter('/nat44-ed/out2in/fastpath/drops')
2048
2049         pkts = self.create_stream_out(self.pg1)
2050         self.pg1.add_stream(pkts)
2051         self.pg_enable_capture(self.pg_interfaces)
2052         self.pg_start()
2053         capture = self.pg0.get_capture(len(pkts))
2054         self.verify_capture_in(capture, self.pg0)
2055
2056         if_idx = self.pg1.sw_if_index
2057         tc2 = self.get_stats_counter('/nat44-ed/out2in/fastpath/tcp')
2058         uc2 = self.get_stats_counter('/nat44-ed/out2in/fastpath/udp')
2059         ic2 = self.get_stats_counter('/nat44-ed/out2in/fastpath/icmp')
2060         dc2 = self.get_stats_counter('/nat44-ed/out2in/fastpath/drops')
2061
2062         self.assertEqual(tc2[if_idx] - tc1[if_idx], 2)
2063         self.assertEqual(uc2[if_idx] - uc1[if_idx], 1)
2064         self.assertEqual(ic2[if_idx] - ic1[if_idx], 1)
2065         self.assertEqual(dc2[if_idx] - dc1[if_idx], 0)
2066
2067         sc = self.get_stats_counter('/nat44-ed/total-sessions')
2068         self.assertEqual(sc[0], 3)
2069
2070     def test_frag_in_order(self):
2071         """ NAT44ED translate fragments arriving in order """
2072
2073         self.nat_add_address(self.nat_addr)
2074         self.nat_add_inside_interface(self.pg0)
2075         self.nat_add_outside_interface(self.pg1)
2076
2077         self.frag_in_order(proto=IP_PROTOS.tcp, ignore_port=True)
2078         self.frag_in_order(proto=IP_PROTOS.udp, ignore_port=True)
2079         self.frag_in_order(proto=IP_PROTOS.icmp, ignore_port=True)
2080
2081     def test_frag_in_order_do_not_translate(self):
2082         """ NAT44ED don't translate fragments arriving in order """
2083
2084         self.nat_add_address(self.nat_addr)
2085         self.nat_add_inside_interface(self.pg0)
2086         self.nat_add_outside_interface(self.pg1)
2087         self.vapi.nat44_forwarding_enable_disable(enable=True)
2088
2089         self.frag_in_order(proto=IP_PROTOS.tcp, dont_translate=True)
2090
2091     def test_frag_out_of_order(self):
2092         """ NAT44ED translate fragments arriving out of order """
2093
2094         self.nat_add_address(self.nat_addr)
2095         self.nat_add_inside_interface(self.pg0)
2096         self.nat_add_outside_interface(self.pg1)
2097
2098         self.frag_out_of_order(proto=IP_PROTOS.tcp, ignore_port=True)
2099         self.frag_out_of_order(proto=IP_PROTOS.udp, ignore_port=True)
2100         self.frag_out_of_order(proto=IP_PROTOS.icmp, ignore_port=True)
2101
2102     def test_frag_in_order_in_plus_out(self):
2103         """ NAT44ED in+out interface fragments in order """
2104
2105         in_port = self.random_port()
2106         out_port = self.random_port()
2107
2108         self.nat_add_address(self.nat_addr)
2109         self.nat_add_inside_interface(self.pg0)
2110         self.nat_add_outside_interface(self.pg0)
2111         self.nat_add_inside_interface(self.pg1)
2112         self.nat_add_outside_interface(self.pg1)
2113
2114         # add static mappings for server
2115         self.nat_add_static_mapping(self.server_addr,
2116                                     self.nat_addr,
2117                                     in_port,
2118                                     out_port,
2119                                     proto=IP_PROTOS.tcp)
2120         self.nat_add_static_mapping(self.server_addr,
2121                                     self.nat_addr,
2122                                     in_port,
2123                                     out_port,
2124                                     proto=IP_PROTOS.udp)
2125         self.nat_add_static_mapping(self.server_addr,
2126                                     self.nat_addr,
2127                                     proto=IP_PROTOS.icmp)
2128
2129         # run tests for each protocol
2130         self.frag_in_order_in_plus_out(self.server_addr,
2131                                        self.nat_addr,
2132                                        in_port,
2133                                        out_port,
2134                                        IP_PROTOS.tcp)
2135         self.frag_in_order_in_plus_out(self.server_addr,
2136                                        self.nat_addr,
2137                                        in_port,
2138                                        out_port,
2139                                        IP_PROTOS.udp)
2140         self.frag_in_order_in_plus_out(self.server_addr,
2141                                        self.nat_addr,
2142                                        in_port,
2143                                        out_port,
2144                                        IP_PROTOS.icmp)
2145
2146     def test_frag_out_of_order_in_plus_out(self):
2147         """ NAT44ED in+out interface fragments out of order """
2148
2149         in_port = self.random_port()
2150         out_port = self.random_port()
2151
2152         self.nat_add_address(self.nat_addr)
2153         self.nat_add_inside_interface(self.pg0)
2154         self.nat_add_outside_interface(self.pg0)
2155         self.nat_add_inside_interface(self.pg1)
2156         self.nat_add_outside_interface(self.pg1)
2157
2158         # add static mappings for server
2159         self.nat_add_static_mapping(self.server_addr,
2160                                     self.nat_addr,
2161                                     in_port,
2162                                     out_port,
2163                                     proto=IP_PROTOS.tcp)
2164         self.nat_add_static_mapping(self.server_addr,
2165                                     self.nat_addr,
2166                                     in_port,
2167                                     out_port,
2168                                     proto=IP_PROTOS.udp)
2169         self.nat_add_static_mapping(self.server_addr,
2170                                     self.nat_addr,
2171                                     proto=IP_PROTOS.icmp)
2172
2173         # run tests for each protocol
2174         self.frag_out_of_order_in_plus_out(self.server_addr,
2175                                            self.nat_addr,
2176                                            in_port,
2177                                            out_port,
2178                                            IP_PROTOS.tcp)
2179         self.frag_out_of_order_in_plus_out(self.server_addr,
2180                                            self.nat_addr,
2181                                            in_port,
2182                                            out_port,
2183                                            IP_PROTOS.udp)
2184         self.frag_out_of_order_in_plus_out(self.server_addr,
2185                                            self.nat_addr,
2186                                            in_port,
2187                                            out_port,
2188                                            IP_PROTOS.icmp)
2189
2190     def test_reass_hairpinning(self):
2191         """ NAT44ED fragments hairpinning """
2192
2193         server_addr = self.pg0.remote_hosts[1].ip4
2194
2195         host_in_port = self.random_port()
2196         server_in_port = self.random_port()
2197         server_out_port = self.random_port()
2198
2199         self.nat_add_address(self.nat_addr)
2200         self.nat_add_inside_interface(self.pg0)
2201         self.nat_add_outside_interface(self.pg1)
2202
2203         # add static mapping for server
2204         self.nat_add_static_mapping(server_addr, self.nat_addr,
2205                                     server_in_port, server_out_port,
2206                                     proto=IP_PROTOS.tcp)
2207         self.nat_add_static_mapping(server_addr, self.nat_addr,
2208                                     server_in_port, server_out_port,
2209                                     proto=IP_PROTOS.udp)
2210         self.nat_add_static_mapping(server_addr, self.nat_addr)
2211
2212         self.reass_hairpinning(server_addr, server_in_port, server_out_port,
2213                                host_in_port, proto=IP_PROTOS.tcp,
2214                                ignore_port=True)
2215         self.reass_hairpinning(server_addr, server_in_port, server_out_port,
2216                                host_in_port, proto=IP_PROTOS.udp,
2217                                ignore_port=True)
2218         self.reass_hairpinning(server_addr, server_in_port, server_out_port,
2219                                host_in_port, proto=IP_PROTOS.icmp,
2220                                ignore_port=True)
2221
2222     def test_session_limit_per_vrf(self):
2223         """ NAT44ED per vrf session limit """
2224
2225         inside = self.pg0
2226         inside_vrf10 = self.pg2
2227         outside = self.pg1
2228
2229         limit = 5
2230
2231         # 2 interfaces pg0, pg1 (vrf10, limit 1 tcp session)
2232         # non existing vrf_id makes process core dump
2233         self.vapi.nat44_set_session_limit(session_limit=limit, vrf_id=10)
2234
2235         self.nat_add_inside_interface(inside)
2236         self.nat_add_inside_interface(inside_vrf10)
2237         self.nat_add_outside_interface(outside)
2238
2239         # vrf independent
2240         self.nat_add_interface_address(outside)
2241
2242         # BUG: causing core dump - when bad vrf_id is specified
2243         # self.nat_add_address(outside.local_ip4, vrf_id=20)
2244
2245         stream = self.create_tcp_stream(inside_vrf10, outside, limit * 2)
2246         inside_vrf10.add_stream(stream)
2247
2248         self.pg_enable_capture(self.pg_interfaces)
2249         self.pg_start()
2250
2251         capture = outside.get_capture(limit)
2252
2253         stream = self.create_tcp_stream(inside, outside, limit * 2)
2254         inside.add_stream(stream)
2255
2256         self.pg_enable_capture(self.pg_interfaces)
2257         self.pg_start()
2258
2259         capture = outside.get_capture(len(stream))
2260
2261     def test_show_max_translations(self):
2262         """ NAT44ED API test - max translations per thread """
2263         nat_config = self.vapi.nat_show_config_2()
2264         self.assertEqual(self.max_sessions,
2265                          nat_config.max_translations_per_thread)
2266
2267     def test_lru_cleanup(self):
2268         """ NAT44ED LRU cleanup algorithm """
2269
2270         self.nat_add_address(self.nat_addr)
2271         self.nat_add_inside_interface(self.pg0)
2272         self.nat_add_outside_interface(self.pg1)
2273
2274         self.vapi.nat_set_timeouts(
2275             udp=1, tcp_established=7440, tcp_transitory=30, icmp=1)
2276
2277         tcp_port_out = self.init_tcp_session(self.pg0, self.pg1, 2000, 80)
2278         pkts = []
2279         for i in range(0, self.max_sessions - 1):
2280             p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2281                  IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4, ttl=64) /
2282                  UDP(sport=7000+i, dport=80))
2283             pkts.append(p)
2284
2285         self.pg0.add_stream(pkts)
2286         self.pg_enable_capture(self.pg_interfaces)
2287         self.pg_start()
2288         self.pg1.get_capture(len(pkts))
2289         self.sleep(1.5, "wait for timeouts")
2290
2291         pkts = []
2292         for i in range(0, self.max_sessions - 1):
2293             p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2294                  IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4, ttl=64) /
2295                  ICMP(id=8000+i, type='echo-request'))
2296             pkts.append(p)
2297
2298         self.pg0.add_stream(pkts)
2299         self.pg_enable_capture(self.pg_interfaces)
2300         self.pg_start()
2301         self.pg1.get_capture(len(pkts))
2302
2303     def test_session_rst_timeout(self):
2304         """ NAT44ED session RST timeouts """
2305
2306         self.nat_add_address(self.nat_addr)
2307         self.nat_add_inside_interface(self.pg0)
2308         self.nat_add_outside_interface(self.pg1)
2309
2310         self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
2311                                    tcp_transitory=5, icmp=60)
2312
2313         self.init_tcp_session(self.pg0, self.pg1, self.tcp_port_in,
2314                               self.tcp_external_port)
2315         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
2316              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2317              TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
2318                  flags="R"))
2319         self.pg0.add_stream(p)
2320         self.pg_enable_capture(self.pg_interfaces)
2321         self.pg_start()
2322         self.pg1.get_capture(1)
2323
2324         self.sleep(6)
2325
2326         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
2327              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2328              TCP(sport=self.tcp_port_in + 1, dport=self.tcp_external_port + 1,
2329                  flags="S"))
2330         self.pg0.add_stream(p)
2331         self.pg_enable_capture(self.pg_interfaces)
2332         self.pg_start()
2333         self.pg1.get_capture(1)
2334
2335     def test_dynamic_out_of_ports(self):
2336         """ NAT44ED dynamic translation test: out of ports """
2337
2338         self.nat_add_inside_interface(self.pg0)
2339         self.nat_add_outside_interface(self.pg1)
2340
2341         # in2out and no NAT addresses added
2342         err_old = self.statistics.get_err_counter(
2343             '/err/nat44-ed-in2out-slowpath/out of ports')
2344
2345         pkts = self.create_stream_in(self.pg0, self.pg1)
2346         self.pg0.add_stream(pkts)
2347         self.pg_enable_capture(self.pg_interfaces)
2348         self.pg_start()
2349         self.pg1.get_capture(0, timeout=1)
2350
2351         err_new = self.statistics.get_err_counter(
2352             '/err/nat44-ed-in2out-slowpath/out of ports')
2353
2354         self.assertEqual(err_new - err_old, len(pkts))
2355
2356         # in2out after NAT addresses added
2357         self.nat_add_address(self.nat_addr)
2358
2359         err_old = self.statistics.get_err_counter(
2360             '/err/nat44-ed-in2out-slowpath/out of ports')
2361
2362         pkts = self.create_stream_in(self.pg0, self.pg1)
2363         self.pg0.add_stream(pkts)
2364         self.pg_enable_capture(self.pg_interfaces)
2365         self.pg_start()
2366         capture = self.pg1.get_capture(len(pkts))
2367         self.verify_capture_out(capture, ignore_port=True)
2368
2369         err_new = self.statistics.get_err_counter(
2370             '/err/nat44-ed-in2out-slowpath/out of ports')
2371
2372         self.assertEqual(err_new, err_old)
2373
2374     def test_unknown_proto(self):
2375         """ NAT44ED translate packet with unknown protocol """
2376
2377         self.nat_add_address(self.nat_addr)
2378         self.nat_add_inside_interface(self.pg0)
2379         self.nat_add_outside_interface(self.pg1)
2380
2381         # in2out
2382         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2383              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2384              TCP(sport=self.tcp_port_in, dport=20))
2385         self.pg0.add_stream(p)
2386         self.pg_enable_capture(self.pg_interfaces)
2387         self.pg_start()
2388         p = self.pg1.get_capture(1)
2389
2390         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2391              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2392              GRE() /
2393              IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
2394              TCP(sport=1234, dport=1234))
2395         self.pg0.add_stream(p)
2396         self.pg_enable_capture(self.pg_interfaces)
2397         self.pg_start()
2398         p = self.pg1.get_capture(1)
2399         packet = p[0]
2400         try:
2401             self.assertEqual(packet[IP].src, self.nat_addr)
2402             self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
2403             self.assertEqual(packet.haslayer(GRE), 1)
2404             self.assert_packet_checksums_valid(packet)
2405         except:
2406             self.logger.error(ppp("Unexpected or invalid packet:", packet))
2407             raise
2408
2409         # out2in
2410         p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
2411              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
2412              GRE() /
2413              IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
2414              TCP(sport=1234, dport=1234))
2415         self.pg1.add_stream(p)
2416         self.pg_enable_capture(self.pg_interfaces)
2417         self.pg_start()
2418         p = self.pg0.get_capture(1)
2419         packet = p[0]
2420         try:
2421             self.assertEqual(packet[IP].src, self.pg1.remote_ip4)
2422             self.assertEqual(packet[IP].dst, self.pg0.remote_ip4)
2423             self.assertEqual(packet.haslayer(GRE), 1)
2424             self.assert_packet_checksums_valid(packet)
2425         except:
2426             self.logger.error(ppp("Unexpected or invalid packet:", packet))
2427             raise
2428
2429     def test_hairpinning_unknown_proto(self):
2430         """ NAT44ED translate packet with unknown protocol - hairpinning """
2431         host = self.pg0.remote_hosts[0]
2432         server = self.pg0.remote_hosts[1]
2433         host_in_port = 1234
2434         server_out_port = 8765
2435         server_nat_ip = "10.0.0.11"
2436
2437         self.nat_add_address(self.nat_addr)
2438         self.nat_add_inside_interface(self.pg0)
2439         self.nat_add_outside_interface(self.pg1)
2440
2441         # add static mapping for server
2442         self.nat_add_static_mapping(server.ip4, server_nat_ip)
2443
2444         # host to server
2445         p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
2446              IP(src=host.ip4, dst=server_nat_ip) /
2447              TCP(sport=host_in_port, dport=server_out_port))
2448         self.pg0.add_stream(p)
2449         self.pg_enable_capture(self.pg_interfaces)
2450         self.pg_start()
2451         self.pg0.get_capture(1)
2452
2453         p = (Ether(dst=self.pg0.local_mac, src=host.mac) /
2454              IP(src=host.ip4, dst=server_nat_ip) /
2455              GRE() /
2456              IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
2457              TCP(sport=1234, dport=1234))
2458         self.pg0.add_stream(p)
2459         self.pg_enable_capture(self.pg_interfaces)
2460         self.pg_start()
2461         p = self.pg0.get_capture(1)
2462         packet = p[0]
2463         try:
2464             self.assertEqual(packet[IP].src, self.nat_addr)
2465             self.assertEqual(packet[IP].dst, server.ip4)
2466             self.assertEqual(packet.haslayer(GRE), 1)
2467             self.assert_packet_checksums_valid(packet)
2468         except:
2469             self.logger.error(ppp("Unexpected or invalid packet:", packet))
2470             raise
2471
2472         # server to host
2473         p = (Ether(dst=self.pg0.local_mac, src=server.mac) /
2474              IP(src=server.ip4, dst=self.nat_addr) /
2475              GRE() /
2476              IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
2477              TCP(sport=1234, dport=1234))
2478         self.pg0.add_stream(p)
2479         self.pg_enable_capture(self.pg_interfaces)
2480         self.pg_start()
2481         p = self.pg0.get_capture(1)
2482         packet = p[0]
2483         try:
2484             self.assertEqual(packet[IP].src, server_nat_ip)
2485             self.assertEqual(packet[IP].dst, host.ip4)
2486             self.assertEqual(packet.haslayer(GRE), 1)
2487             self.assert_packet_checksums_valid(packet)
2488         except:
2489             self.logger.error(ppp("Unexpected or invalid packet:", packet))
2490             raise
2491
2492     def test_output_feature_and_service(self):
2493         """ NAT44ED interface output feature and services """
2494         external_addr = '1.2.3.4'
2495         external_port = 80
2496         local_port = 8080
2497
2498         self.vapi.nat44_forwarding_enable_disable(enable=1)
2499         self.nat_add_address(self.nat_addr)
2500         flags = self.config_flags.NAT_IS_ADDR_ONLY
2501         self.vapi.nat44_add_del_identity_mapping(
2502             ip_address=self.pg1.remote_ip4, sw_if_index=0xFFFFFFFF,
2503             flags=flags, is_add=1)
2504         flags = self.config_flags.NAT_IS_OUT2IN_ONLY
2505         self.nat_add_static_mapping(self.pg0.remote_ip4, external_addr,
2506                                     local_port, external_port,
2507                                     proto=IP_PROTOS.tcp, flags=flags)
2508
2509         self.nat_add_inside_interface(self.pg0)
2510         self.nat_add_outside_interface(self.pg0)
2511         self.vapi.nat44_interface_add_del_output_feature(
2512             sw_if_index=self.pg1.sw_if_index, is_add=1)
2513
2514         # from client to service
2515         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
2516              IP(src=self.pg1.remote_ip4, dst=external_addr) /
2517              TCP(sport=12345, dport=external_port))
2518         self.pg1.add_stream(p)
2519         self.pg_enable_capture(self.pg_interfaces)
2520         self.pg_start()
2521         capture = self.pg0.get_capture(1)
2522         p = capture[0]
2523         try:
2524             ip = p[IP]
2525             tcp = p[TCP]
2526             self.assertEqual(ip.dst, self.pg0.remote_ip4)
2527             self.assertEqual(tcp.dport, local_port)
2528             self.assert_packet_checksums_valid(p)
2529         except:
2530             self.logger.error(ppp("Unexpected or invalid packet:", p))
2531             raise
2532
2533         # from service back to client
2534         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
2535              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2536              TCP(sport=local_port, dport=12345))
2537         self.pg0.add_stream(p)
2538         self.pg_enable_capture(self.pg_interfaces)
2539         self.pg_start()
2540         capture = self.pg1.get_capture(1)
2541         p = capture[0]
2542         try:
2543             ip = p[IP]
2544             tcp = p[TCP]
2545             self.assertEqual(ip.src, external_addr)
2546             self.assertEqual(tcp.sport, external_port)
2547             self.assert_packet_checksums_valid(p)
2548         except:
2549             self.logger.error(ppp("Unexpected or invalid packet:", p))
2550             raise
2551
2552         # from local network host to external network
2553         pkts = self.create_stream_in(self.pg0, self.pg1)
2554         self.pg0.add_stream(pkts)
2555         self.pg_enable_capture(self.pg_interfaces)
2556         self.pg_start()
2557         capture = self.pg1.get_capture(len(pkts))
2558         self.verify_capture_out(capture, ignore_port=True)
2559         pkts = self.create_stream_in(self.pg0, self.pg1)
2560         self.pg0.add_stream(pkts)
2561         self.pg_enable_capture(self.pg_interfaces)
2562         self.pg_start()
2563         capture = self.pg1.get_capture(len(pkts))
2564         self.verify_capture_out(capture, ignore_port=True)
2565
2566         # from external network back to local network host
2567         pkts = self.create_stream_out(self.pg1)
2568         self.pg1.add_stream(pkts)
2569         self.pg_enable_capture(self.pg_interfaces)
2570         self.pg_start()
2571         capture = self.pg0.get_capture(len(pkts))
2572         self.verify_capture_in(capture, self.pg0)
2573
2574     def test_output_feature_and_service3(self):
2575         """ NAT44ED interface output feature and DST NAT """
2576         external_addr = '1.2.3.4'
2577         external_port = 80
2578         local_port = 8080
2579
2580         self.vapi.nat44_forwarding_enable_disable(enable=1)
2581         self.nat_add_address(self.nat_addr)
2582         flags = self.config_flags.NAT_IS_OUT2IN_ONLY
2583         self.nat_add_static_mapping(self.pg1.remote_ip4, external_addr,
2584                                     local_port, external_port,
2585                                     proto=IP_PROTOS.tcp, flags=flags)
2586
2587         self.nat_add_inside_interface(self.pg0)
2588         self.nat_add_outside_interface(self.pg0)
2589         self.vapi.nat44_interface_add_del_output_feature(
2590             sw_if_index=self.pg1.sw_if_index, is_add=1)
2591
2592         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
2593              IP(src=self.pg0.remote_ip4, dst=external_addr) /
2594              TCP(sport=12345, dport=external_port))
2595         self.pg0.add_stream(p)
2596         self.pg_enable_capture(self.pg_interfaces)
2597         self.pg_start()
2598         capture = self.pg1.get_capture(1)
2599         p = capture[0]
2600         try:
2601             ip = p[IP]
2602             tcp = p[TCP]
2603             self.assertEqual(ip.src, self.pg0.remote_ip4)
2604             self.assertEqual(tcp.sport, 12345)
2605             self.assertEqual(ip.dst, self.pg1.remote_ip4)
2606             self.assertEqual(tcp.dport, local_port)
2607             self.assert_packet_checksums_valid(p)
2608         except:
2609             self.logger.error(ppp("Unexpected or invalid packet:", p))
2610             raise
2611
2612         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
2613              IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
2614              TCP(sport=local_port, dport=12345))
2615         self.pg1.add_stream(p)
2616         self.pg_enable_capture(self.pg_interfaces)
2617         self.pg_start()
2618         capture = self.pg0.get_capture(1)
2619         p = capture[0]
2620         try:
2621             ip = p[IP]
2622             tcp = p[TCP]
2623             self.assertEqual(ip.src, external_addr)
2624             self.assertEqual(tcp.sport, external_port)
2625             self.assertEqual(ip.dst, self.pg0.remote_ip4)
2626             self.assertEqual(tcp.dport, 12345)
2627             self.assert_packet_checksums_valid(p)
2628         except:
2629             self.logger.error(ppp("Unexpected or invalid packet:", p))
2630             raise
2631
2632     def test_self_twice_nat_lb_negative(self):
2633         """ NAT44ED Self Twice NAT local service load balancing (negative test)
2634         """
2635         self.twice_nat_common(lb=True, self_twice_nat=True, same_pg=True,
2636                               client_id=2)
2637
2638     def test_self_twice_nat_negative(self):
2639         """ NAT44ED Self Twice NAT (negative test) """
2640         self.twice_nat_common(self_twice_nat=True)
2641
2642     def test_static_lb_multi_clients(self):
2643         """ NAT44ED local service load balancing - multiple clients"""
2644
2645         external_addr = self.nat_addr
2646         external_port = 80
2647         local_port = 8080
2648         server1 = self.pg0.remote_hosts[0]
2649         server2 = self.pg0.remote_hosts[1]
2650         server3 = self.pg0.remote_hosts[2]
2651
2652         locals = [{'addr': server1.ip4,
2653                    'port': local_port,
2654                    'probability': 90,
2655                    'vrf_id': 0},
2656                   {'addr': server2.ip4,
2657                    'port': local_port,
2658                    'probability': 10,
2659                    'vrf_id': 0}]
2660
2661         flags = self.config_flags.NAT_IS_INSIDE
2662         self.vapi.nat44_interface_add_del_feature(
2663             sw_if_index=self.pg0.sw_if_index,
2664             flags=flags, is_add=1)
2665         self.vapi.nat44_interface_add_del_feature(
2666             sw_if_index=self.pg1.sw_if_index,
2667             is_add=1)
2668
2669         self.nat_add_address(self.nat_addr)
2670         self.vapi.nat44_add_del_lb_static_mapping(is_add=1,
2671                                                   external_addr=external_addr,
2672                                                   external_port=external_port,
2673                                                   protocol=IP_PROTOS.tcp,
2674                                                   local_num=len(locals),
2675                                                   locals=locals)
2676
2677         server1_n = 0
2678         server2_n = 0
2679         clients = ip4_range(self.pg1.remote_ip4, 10, 50)
2680         pkts = []
2681         for client in clients:
2682             p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
2683                  IP(src=client, dst=self.nat_addr) /
2684                  TCP(sport=12345, dport=external_port))
2685             pkts.append(p)
2686         self.pg1.add_stream(pkts)
2687         self.pg_enable_capture(self.pg_interfaces)
2688         self.pg_start()
2689         capture = self.pg0.get_capture(len(pkts))
2690         for p in capture:
2691             if p[IP].dst == server1.ip4:
2692                 server1_n += 1
2693             else:
2694                 server2_n += 1
2695         self.assertGreater(server1_n, server2_n)
2696
2697         local = {
2698             'addr': server3.ip4,
2699             'port': local_port,
2700             'probability': 20,
2701             'vrf_id': 0
2702         }
2703
2704         # add new back-end
2705         self.vapi.nat44_lb_static_mapping_add_del_local(
2706             is_add=1,
2707             external_addr=external_addr,
2708             external_port=external_port,
2709             local=local,
2710             protocol=IP_PROTOS.tcp)
2711         server1_n = 0
2712         server2_n = 0
2713         server3_n = 0
2714         clients = ip4_range(self.pg1.remote_ip4, 60, 110)
2715         pkts = []
2716         for client in clients:
2717             p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
2718                  IP(src=client, dst=self.nat_addr) /
2719                  TCP(sport=12346, dport=external_port))
2720             pkts.append(p)
2721         self.assertGreater(len(pkts), 0)
2722         self.pg1.add_stream(pkts)
2723         self.pg_enable_capture(self.pg_interfaces)
2724         self.pg_start()
2725         capture = self.pg0.get_capture(len(pkts))
2726         for p in capture:
2727             if p[IP].dst == server1.ip4:
2728                 server1_n += 1
2729             elif p[IP].dst == server2.ip4:
2730                 server2_n += 1
2731             else:
2732                 server3_n += 1
2733         self.assertGreater(server1_n, 0)
2734         self.assertGreater(server2_n, 0)
2735         self.assertGreater(server3_n, 0)
2736
2737         local = {
2738             'addr': server2.ip4,
2739             'port': local_port,
2740             'probability': 10,
2741             'vrf_id': 0
2742         }
2743
2744         # remove one back-end
2745         self.vapi.nat44_lb_static_mapping_add_del_local(
2746             is_add=0,
2747             external_addr=external_addr,
2748             external_port=external_port,
2749             local=local,
2750             protocol=IP_PROTOS.tcp)
2751         server1_n = 0
2752         server2_n = 0
2753         server3_n = 0
2754         self.pg1.add_stream(pkts)
2755         self.pg_enable_capture(self.pg_interfaces)
2756         self.pg_start()
2757         capture = self.pg0.get_capture(len(pkts))
2758         for p in capture:
2759             if p[IP].dst == server1.ip4:
2760                 server1_n += 1
2761             elif p[IP].dst == server2.ip4:
2762                 server2_n += 1
2763             else:
2764                 server3_n += 1
2765         self.assertGreater(server1_n, 0)
2766         self.assertEqual(server2_n, 0)
2767         self.assertGreater(server3_n, 0)
2768
2769     def test_syslog_sess(self):
2770         """ NAT44ED Test syslog session creation and deletion """
2771         self.vapi.syslog_set_filter(
2772             self.syslog_severity.SYSLOG_API_SEVERITY_INFO)
2773         self.vapi.syslog_set_sender(self.pg3.local_ip4, self.pg3.remote_ip4)
2774
2775         self.nat_add_address(self.nat_addr)
2776         self.nat_add_inside_interface(self.pg0)
2777         self.nat_add_outside_interface(self.pg1)
2778
2779         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2780              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2781              TCP(sport=self.tcp_port_in, dport=self.tcp_external_port))
2782         self.pg0.add_stream(p)
2783         self.pg_enable_capture(self.pg_interfaces)
2784         self.pg_start()
2785         capture = self.pg1.get_capture(1)
2786         self.tcp_port_out = capture[0][TCP].sport
2787         capture = self.pg3.get_capture(1)
2788         self.verify_syslog_sess(capture[0][Raw].load)
2789
2790         self.pg_enable_capture(self.pg_interfaces)
2791         self.pg_start()
2792         self.nat_add_address(self.nat_addr, is_add=0)
2793         capture = self.pg3.get_capture(1)
2794         self.verify_syslog_sess(capture[0][Raw].load, False)
2795
2796     def test_twice_nat_interface_addr(self):
2797         """ NAT44ED Acquire twice NAT addresses from interface """
2798         flags = self.config_flags.NAT_IS_TWICE_NAT
2799         self.vapi.nat44_add_del_interface_addr(
2800             sw_if_index=self.pg11.sw_if_index,
2801             flags=flags, is_add=1)
2802
2803         # no address in NAT pool
2804         adresses = self.vapi.nat44_address_dump()
2805         self.assertEqual(0, len(adresses))
2806
2807         # configure interface address and check NAT address pool
2808         self.pg11.config_ip4()
2809         adresses = self.vapi.nat44_address_dump()
2810         self.assertEqual(1, len(adresses))
2811         self.assertEqual(str(adresses[0].ip_address),
2812                          self.pg11.local_ip4)
2813         self.assertEqual(adresses[0].flags, flags)
2814
2815         # remove interface address and check NAT address pool
2816         self.pg11.unconfig_ip4()
2817         adresses = self.vapi.nat44_address_dump()
2818         self.assertEqual(0, len(adresses))
2819
2820     def test_output_feature_stateful_acl(self):
2821         """ NAT44ED output feature works with stateful ACL """
2822
2823         self.nat_add_address(self.nat_addr)
2824         self.vapi.nat44_interface_add_del_output_feature(
2825             sw_if_index=self.pg0.sw_if_index,
2826             flags=self.config_flags.NAT_IS_INSIDE, is_add=1)
2827         self.vapi.nat44_interface_add_del_output_feature(
2828             sw_if_index=self.pg1.sw_if_index,
2829             flags=self.config_flags.NAT_IS_OUTSIDE, is_add=1)
2830
2831         # First ensure that the NAT is working sans ACL
2832
2833         # send packets out2in, no sessions yet so packets should drop
2834         pkts_out2in = self.create_stream_out(self.pg1)
2835         self.send_and_assert_no_replies(self.pg1, pkts_out2in)
2836
2837         # send packets into inside intf, ensure received via outside intf
2838         pkts_in2out = self.create_stream_in(self.pg0, self.pg1)
2839         capture = self.send_and_expect(self.pg0, pkts_in2out, self.pg1,
2840                                        len(pkts_in2out))
2841         self.verify_capture_out(capture, ignore_port=True)
2842
2843         # send out2in again, with sessions created it should work now
2844         pkts_out2in = self.create_stream_out(self.pg1)
2845         capture = self.send_and_expect(self.pg1, pkts_out2in, self.pg0,
2846                                        len(pkts_out2in))
2847         self.verify_capture_in(capture, self.pg0)
2848
2849         # Create an ACL blocking everything
2850         out2in_deny_rule = AclRule(is_permit=0)
2851         out2in_acl = VppAcl(self, rules=[out2in_deny_rule])
2852         out2in_acl.add_vpp_config()
2853
2854         # create an ACL to permit/reflect everything
2855         in2out_reflect_rule = AclRule(is_permit=2)
2856         in2out_acl = VppAcl(self, rules=[in2out_reflect_rule])
2857         in2out_acl.add_vpp_config()
2858
2859         # apply as input acl on interface and confirm it blocks everything
2860         acl_if = VppAclInterface(self, sw_if_index=self.pg1.sw_if_index,
2861                                  n_input=1, acls=[out2in_acl])
2862         acl_if.add_vpp_config()
2863         self.send_and_assert_no_replies(self.pg1, pkts_out2in)
2864
2865         # apply output acl
2866         acl_if.acls = [out2in_acl, in2out_acl]
2867         acl_if.add_vpp_config()
2868         # send in2out to generate ACL state (NAT state was created earlier)
2869         capture = self.send_and_expect(self.pg0, pkts_in2out, self.pg1,
2870                                        len(pkts_in2out))
2871         self.verify_capture_out(capture, ignore_port=True)
2872
2873         # send out2in again. ACL state exists so it should work now.
2874         # TCP packets with the syn flag set also need the ack flag
2875         for p in pkts_out2in:
2876             if p.haslayer(TCP) and p[TCP].flags & 0x02:
2877                 p[TCP].flags |= 0x10
2878         capture = self.send_and_expect(self.pg1, pkts_out2in, self.pg0,
2879                                        len(pkts_out2in))
2880         self.verify_capture_in(capture, self.pg0)
2881         self.logger.info(self.vapi.cli("show trace"))
2882
2883     def test_tcp_close(self):
2884         """ NAT44ED Close TCP session from inside network - output feature """
2885         old_timeouts = self.vapi.nat_get_timeouts()
2886         new_transitory = 2
2887         self.vapi.nat_set_timeouts(
2888             udp=old_timeouts.udp,
2889             tcp_established=old_timeouts.tcp_established,
2890             icmp=old_timeouts.icmp,
2891             tcp_transitory=new_transitory)
2892
2893         self.vapi.nat44_forwarding_enable_disable(enable=1)
2894         self.nat_add_address(self.pg1.local_ip4)
2895         twice_nat_addr = '10.0.1.3'
2896         service_ip = '192.168.16.150'
2897         self.nat_add_address(twice_nat_addr, twice_nat=1)
2898
2899         flags = self.config_flags.NAT_IS_INSIDE
2900         self.vapi.nat44_interface_add_del_feature(
2901             sw_if_index=self.pg0.sw_if_index,
2902             is_add=1)
2903         self.vapi.nat44_interface_add_del_feature(
2904             sw_if_index=self.pg0.sw_if_index,
2905             flags=flags, is_add=1)
2906         self.vapi.nat44_interface_add_del_output_feature(
2907             is_add=1,
2908             sw_if_index=self.pg1.sw_if_index)
2909
2910         flags = (self.config_flags.NAT_IS_OUT2IN_ONLY |
2911                  self.config_flags.NAT_IS_TWICE_NAT)
2912         self.nat_add_static_mapping(self.pg0.remote_ip4,
2913                                     service_ip, 80, 80,
2914                                     proto=IP_PROTOS.tcp,
2915                                     flags=flags)
2916         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
2917         start_sessnum = len(sessions)
2918
2919         # SYN packet out->in
2920         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
2921              IP(src=self.pg1.remote_ip4, dst=service_ip) /
2922              TCP(sport=33898, dport=80, flags="S"))
2923         self.pg1.add_stream(p)
2924         self.pg_enable_capture(self.pg_interfaces)
2925         self.pg_start()
2926         capture = self.pg0.get_capture(1)
2927         p = capture[0]
2928         tcp_port = p[TCP].sport
2929
2930         # SYN + ACK packet in->out
2931         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
2932              IP(src=self.pg0.remote_ip4, dst=twice_nat_addr) /
2933              TCP(sport=80, dport=tcp_port, flags="SA"))
2934         self.pg0.add_stream(p)
2935         self.pg_enable_capture(self.pg_interfaces)
2936         self.pg_start()
2937         self.pg1.get_capture(1)
2938
2939         # ACK packet out->in
2940         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
2941              IP(src=self.pg1.remote_ip4, dst=service_ip) /
2942              TCP(sport=33898, dport=80, flags="A"))
2943         self.pg1.add_stream(p)
2944         self.pg_enable_capture(self.pg_interfaces)
2945         self.pg_start()
2946         self.pg0.get_capture(1)
2947
2948         # FIN packet in -> out
2949         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
2950              IP(src=self.pg0.remote_ip4, dst=twice_nat_addr) /
2951              TCP(sport=80, dport=tcp_port, flags="FA", seq=100, ack=300))
2952         self.pg0.add_stream(p)
2953         self.pg_enable_capture(self.pg_interfaces)
2954         self.pg_start()
2955         self.pg1.get_capture(1)
2956
2957         # FIN+ACK packet out -> in
2958         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
2959              IP(src=self.pg1.remote_ip4, dst=service_ip) /
2960              TCP(sport=33898, dport=80, flags="FA", seq=300, ack=101))
2961         self.pg1.add_stream(p)
2962         self.pg_enable_capture(self.pg_interfaces)
2963         self.pg_start()
2964         self.pg0.get_capture(1)
2965
2966         # ACK packet in -> out
2967         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
2968              IP(src=self.pg0.remote_ip4, dst=twice_nat_addr) /
2969              TCP(sport=80, dport=tcp_port, flags="A", seq=101, ack=301))
2970         self.pg0.add_stream(p)
2971         self.pg_enable_capture(self.pg_interfaces)
2972         self.pg_start()
2973         self.pg1.get_capture(1)
2974
2975         # session now in transitory timeout
2976         # try SYN packet out->in - should be dropped
2977         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
2978              IP(src=self.pg1.remote_ip4, dst=service_ip) /
2979              TCP(sport=33898, dport=80, flags="S"))
2980         self.pg1.add_stream(p)
2981         self.pg_enable_capture(self.pg_interfaces)
2982         self.pg_start()
2983
2984         self.sleep(new_transitory, "wait for transitory timeout")
2985         self.pg0.assert_nothing_captured(0)
2986
2987         # session should still exist
2988         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
2989         self.assertEqual(len(sessions) - start_sessnum, 1)
2990
2991         # send FIN+ACK packet out -> in - will cause session to be wiped
2992         # but won't create a new session
2993         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
2994              IP(src=self.pg1.remote_ip4, dst=service_ip) /
2995              TCP(sport=33898, dport=80, flags="FA", seq=300, ack=101))
2996         self.pg1.add_stream(p)
2997         self.pg_enable_capture(self.pg_interfaces)
2998         self.pg_start()
2999
3000         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3001         self.assertEqual(len(sessions) - start_sessnum, 0)
3002         self.pg0.assert_nothing_captured(0)
3003
3004     def test_tcp_session_close_in(self):
3005         """ NAT44ED Close TCP session from inside network """
3006
3007         in_port = self.tcp_port_in
3008         out_port = 10505
3009         ext_port = self.tcp_external_port
3010
3011         self.nat_add_address(self.nat_addr)
3012         self.nat_add_inside_interface(self.pg0)
3013         self.nat_add_outside_interface(self.pg1)
3014         self.nat_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
3015                                     in_port, out_port, proto=IP_PROTOS.tcp,
3016                                     flags=self.config_flags.NAT_IS_TWICE_NAT)
3017
3018         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3019         session_n = len(sessions)
3020
3021         self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
3022                                    tcp_transitory=2, icmp=5)
3023
3024         self.init_tcp_session(self.pg0, self.pg1, in_port, ext_port)
3025
3026         # FIN packet in -> out
3027         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3028              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3029              TCP(sport=in_port, dport=ext_port,
3030                  flags="FA", seq=100, ack=300))
3031         self.pg0.add_stream(p)
3032         self.pg_enable_capture(self.pg_interfaces)
3033         self.pg_start()
3034         self.pg1.get_capture(1)
3035
3036         pkts = []
3037
3038         # ACK packet out -> in
3039         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3040              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3041              TCP(sport=ext_port, dport=out_port,
3042                  flags="A", seq=300, ack=101))
3043         pkts.append(p)
3044
3045         # FIN packet out -> in
3046         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3047              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3048              TCP(sport=ext_port, dport=out_port,
3049                  flags="FA", seq=300, ack=101))
3050         pkts.append(p)
3051
3052         self.pg1.add_stream(pkts)
3053         self.pg_enable_capture(self.pg_interfaces)
3054         self.pg_start()
3055         self.pg0.get_capture(2)
3056
3057         # ACK packet in -> out
3058         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3059              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3060              TCP(sport=in_port, dport=ext_port,
3061                  flags="A", seq=101, ack=301))
3062         self.pg0.add_stream(p)
3063         self.pg_enable_capture(self.pg_interfaces)
3064         self.pg_start()
3065         self.pg1.get_capture(1)
3066
3067         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3068         self.assertEqual(len(sessions) - session_n, 1)
3069
3070         out2in_drops = self.get_err_counter(
3071             '/err/nat44-ed-out2in/drops due to TCP in transitory timeout')
3072         in2out_drops = self.get_err_counter(
3073             '/err/nat44-ed-in2out/drops due to TCP in transitory timeout')
3074
3075         # extra FIN packet out -> in - this should be dropped
3076         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3077              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3078              TCP(sport=ext_port, dport=out_port,
3079                  flags="FA", seq=300, ack=101))
3080
3081         self.pg1.add_stream(p)
3082         self.pg_enable_capture(self.pg_interfaces)
3083         self.pg_start()
3084         self.pg0.assert_nothing_captured()
3085
3086         # extra ACK packet in -> out - this should be dropped
3087         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3088              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3089              TCP(sport=in_port, dport=ext_port,
3090                  flags="A", seq=101, ack=301))
3091         self.pg0.add_stream(p)
3092         self.pg_enable_capture(self.pg_interfaces)
3093         self.pg_start()
3094         self.pg1.assert_nothing_captured()
3095
3096         stats = self.get_err_counter(
3097             '/err/nat44-ed-out2in/drops due to TCP in transitory timeout')
3098         self.assertEqual(stats - out2in_drops, 1)
3099         stats = self.get_err_counter(
3100             '/err/nat44-ed-in2out/drops due to TCP in transitory timeout')
3101         self.assertEqual(stats - in2out_drops, 1)
3102
3103         self.sleep(3)
3104         # extra ACK packet in -> out - this will cause session to be wiped
3105         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3106              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3107              TCP(sport=in_port, dport=ext_port,
3108                  flags="A", seq=101, ack=301))
3109         self.pg0.add_stream(p)
3110         self.pg_enable_capture(self.pg_interfaces)
3111         self.pg_start()
3112         self.pg1.assert_nothing_captured()
3113         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3114         self.assertEqual(len(sessions) - session_n, 0)
3115
3116     def test_tcp_session_close_out(self):
3117         """ NAT44ED Close TCP session from outside network """
3118
3119         in_port = self.tcp_port_in
3120         out_port = 10505
3121         ext_port = self.tcp_external_port
3122
3123         self.nat_add_address(self.nat_addr)
3124         self.nat_add_inside_interface(self.pg0)
3125         self.nat_add_outside_interface(self.pg1)
3126         self.nat_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
3127                                     in_port, out_port, proto=IP_PROTOS.tcp,
3128                                     flags=self.config_flags.NAT_IS_TWICE_NAT)
3129
3130         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3131         session_n = len(sessions)
3132
3133         self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
3134                                    tcp_transitory=2, icmp=5)
3135
3136         _ = self.init_tcp_session(self.pg0, self.pg1, in_port, ext_port)
3137
3138         # FIN packet out -> in
3139         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3140              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3141              TCP(sport=ext_port, dport=out_port,
3142                  flags="FA", seq=100, ack=300))
3143         self.pg1.add_stream(p)
3144         self.pg_enable_capture(self.pg_interfaces)
3145         self.pg_start()
3146         self.pg0.get_capture(1)
3147
3148         # FIN+ACK packet in -> out
3149         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3150              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3151              TCP(sport=in_port, dport=ext_port,
3152                  flags="FA", seq=300, ack=101))
3153
3154         self.pg0.add_stream(p)
3155         self.pg_enable_capture(self.pg_interfaces)
3156         self.pg_start()
3157         self.pg1.get_capture(1)
3158
3159         # ACK packet out -> in
3160         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3161              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3162              TCP(sport=ext_port, dport=out_port,
3163                  flags="A", seq=101, ack=301))
3164         self.pg1.add_stream(p)
3165         self.pg_enable_capture(self.pg_interfaces)
3166         self.pg_start()
3167         self.pg0.get_capture(1)
3168
3169         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3170         self.assertEqual(len(sessions) - session_n, 1)
3171
3172         out2in_drops = self.get_err_counter(
3173             '/err/nat44-ed-out2in/drops due to TCP in transitory timeout')
3174         in2out_drops = self.get_err_counter(
3175             '/err/nat44-ed-in2out/drops due to TCP in transitory timeout')
3176
3177         # extra FIN packet out -> in - this should be dropped
3178         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3179              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3180              TCP(sport=ext_port, dport=out_port,
3181                  flags="FA", seq=300, ack=101))
3182
3183         self.pg1.add_stream(p)
3184         self.pg_enable_capture(self.pg_interfaces)
3185         self.pg_start()
3186         self.pg0.assert_nothing_captured()
3187
3188         # extra ACK packet in -> out - this should be dropped
3189         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3190              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3191              TCP(sport=in_port, dport=ext_port,
3192                  flags="A", seq=101, ack=301))
3193         self.pg0.add_stream(p)
3194         self.pg_enable_capture(self.pg_interfaces)
3195         self.pg_start()
3196         self.pg1.assert_nothing_captured()
3197
3198         stats = self.get_err_counter(
3199             '/err/nat44-ed-out2in/drops due to TCP in transitory timeout')
3200         self.assertEqual(stats - out2in_drops, 1)
3201         stats = self.get_err_counter(
3202             '/err/nat44-ed-in2out/drops due to TCP in transitory timeout')
3203         self.assertEqual(stats - in2out_drops, 1)
3204
3205         self.sleep(3)
3206         # extra ACK packet in -> out - this will cause session to be wiped
3207         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3208              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3209              TCP(sport=in_port, dport=ext_port,
3210                  flags="A", seq=101, ack=301))
3211         self.pg0.add_stream(p)
3212         self.pg_enable_capture(self.pg_interfaces)
3213         self.pg_start()
3214         self.pg1.assert_nothing_captured()
3215         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3216         self.assertEqual(len(sessions) - session_n, 0)
3217
3218     def test_tcp_session_close_simultaneous(self):
3219         """ NAT44ED Close TCP session from inside network """
3220
3221         in_port = self.tcp_port_in
3222         ext_port = 10505
3223
3224         self.nat_add_address(self.nat_addr)
3225         self.nat_add_inside_interface(self.pg0)
3226         self.nat_add_outside_interface(self.pg1)
3227         self.nat_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
3228                                     in_port, ext_port, proto=IP_PROTOS.tcp,
3229                                     flags=self.config_flags.NAT_IS_TWICE_NAT)
3230
3231         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3232         session_n = len(sessions)
3233
3234         self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
3235                                    tcp_transitory=2, icmp=5)
3236
3237         out_port = self.init_tcp_session(self.pg0, self.pg1, in_port, ext_port)
3238
3239         # FIN packet in -> out
3240         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3241              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3242              TCP(sport=in_port, dport=ext_port,
3243                  flags="FA", seq=100, ack=300))
3244         self.pg0.add_stream(p)
3245         self.pg_enable_capture(self.pg_interfaces)
3246         self.pg_start()
3247         self.pg1.get_capture(1)
3248
3249         # FIN packet out -> in
3250         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3251              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3252              TCP(sport=ext_port, dport=out_port,
3253                  flags="FA", seq=300, ack=100))
3254         self.pg1.add_stream(p)
3255         self.pg_enable_capture(self.pg_interfaces)
3256         self.pg_start()
3257         self.pg0.get_capture(1)
3258
3259         # ACK packet in -> out
3260         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3261              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3262              TCP(sport=in_port, dport=ext_port,
3263                  flags="A", seq=101, ack=301))
3264         self.pg0.add_stream(p)
3265         self.pg_enable_capture(self.pg_interfaces)
3266         self.pg_start()
3267         self.pg1.get_capture(1)
3268
3269         # ACK packet out -> in
3270         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3271              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3272              TCP(sport=ext_port, dport=out_port,
3273                  flags="A", seq=301, ack=101))
3274         self.pg1.add_stream(p)
3275         self.pg_enable_capture(self.pg_interfaces)
3276         self.pg_start()
3277         self.pg0.get_capture(1)
3278
3279         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3280         self.assertEqual(len(sessions) - session_n, 1)
3281
3282         out2in_drops = self.get_err_counter(
3283             '/err/nat44-ed-out2in/drops due to TCP in transitory timeout')
3284         in2out_drops = self.get_err_counter(
3285             '/err/nat44-ed-in2out/drops due to TCP in transitory timeout')
3286
3287         # extra FIN packet out -> in - this should be dropped
3288         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3289              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3290              TCP(sport=ext_port, dport=out_port,
3291                  flags="FA", seq=300, ack=101))
3292
3293         self.pg1.add_stream(p)
3294         self.pg_enable_capture(self.pg_interfaces)
3295         self.pg_start()
3296         self.pg0.assert_nothing_captured()
3297
3298         # extra ACK packet in -> out - this should be dropped
3299         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3300              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3301              TCP(sport=in_port, dport=ext_port,
3302                  flags="A", seq=101, ack=301))
3303         self.pg0.add_stream(p)
3304         self.pg_enable_capture(self.pg_interfaces)
3305         self.pg_start()
3306         self.pg1.assert_nothing_captured()
3307
3308         stats = self.get_err_counter(
3309             '/err/nat44-ed-out2in/drops due to TCP in transitory timeout')
3310         self.assertEqual(stats - out2in_drops, 1)
3311         stats = self.get_err_counter(
3312             '/err/nat44-ed-in2out/drops due to TCP in transitory timeout')
3313         self.assertEqual(stats - in2out_drops, 1)
3314
3315         self.sleep(3)
3316         # extra ACK packet in -> out - this will cause session to be wiped
3317         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3318              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3319              TCP(sport=in_port, dport=ext_port,
3320                  flags="A", seq=101, ack=301))
3321         self.pg0.add_stream(p)
3322         self.pg_enable_capture(self.pg_interfaces)
3323         self.pg_start()
3324         self.pg1.assert_nothing_captured()
3325         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3326         self.assertEqual(len(sessions) - session_n, 0)
3327
3328     def test_dynamic_output_feature_vrf(self):
3329         """ NAT44ED dynamic translation test: output-feature, VRF"""
3330
3331         # other then default (0)
3332         new_vrf_id = 22
3333
3334         self.nat_add_address(self.nat_addr)
3335         flags = self.config_flags.NAT_IS_INSIDE
3336         self.vapi.nat44_interface_add_del_output_feature(
3337             sw_if_index=self.pg7.sw_if_index,
3338             flags=flags, is_add=1)
3339         self.vapi.nat44_interface_add_del_output_feature(
3340             sw_if_index=self.pg8.sw_if_index,
3341             is_add=1)
3342
3343         try:
3344             self.configure_ip4_interface(self.pg7, table_id=new_vrf_id)
3345             self.configure_ip4_interface(self.pg8, table_id=new_vrf_id)
3346
3347             # in2out
3348             tcpn = self.get_stats_counter(
3349                 '/nat44-ed/in2out/slowpath/tcp')
3350             udpn = self.get_stats_counter(
3351                 '/nat44-ed/in2out/slowpath/udp')
3352             icmpn = self.get_stats_counter(
3353                 '/nat44-ed/in2out/slowpath/icmp')
3354             drops = self.get_stats_counter(
3355                 '/nat44-ed/in2out/slowpath/drops')
3356
3357             pkts = self.create_stream_in(self.pg7, self.pg8)
3358             self.pg7.add_stream(pkts)
3359             self.pg_enable_capture(self.pg_interfaces)
3360             self.pg_start()
3361             capture = self.pg8.get_capture(len(pkts))
3362             self.verify_capture_out(capture, ignore_port=True)
3363
3364             if_idx = self.pg7.sw_if_index
3365             cnt = self.get_stats_counter(
3366                 '/nat44-ed/in2out/slowpath/tcp')
3367             self.assertEqual(cnt[if_idx] - tcpn[if_idx], 2)
3368             cnt = self.get_stats_counter(
3369                 '/nat44-ed/in2out/slowpath/udp')
3370             self.assertEqual(cnt[if_idx] - udpn[if_idx], 1)
3371             cnt = self.get_stats_counter(
3372                 '/nat44-ed/in2out/slowpath/icmp')
3373             self.assertEqual(cnt[if_idx] - icmpn[if_idx], 1)
3374             cnt = self.get_stats_counter(
3375                 '/nat44-ed/in2out/slowpath/drops')
3376             self.assertEqual(cnt[if_idx] - drops[if_idx], 0)
3377
3378             # out2in
3379             tcpn = self.get_stats_counter(
3380                 '/nat44-ed/out2in/fastpath/tcp')
3381             udpn = self.get_stats_counter(
3382                 '/nat44-ed/out2in/fastpath/udp')
3383             icmpn = self.get_stats_counter(
3384                 '/nat44-ed/out2in/fastpath/icmp')
3385             drops = self.get_stats_counter(
3386                 '/nat44-ed/out2in/fastpath/drops')
3387
3388             pkts = self.create_stream_out(self.pg8)
3389             self.pg8.add_stream(pkts)
3390             self.pg_enable_capture(self.pg_interfaces)
3391             self.pg_start()
3392             capture = self.pg7.get_capture(len(pkts))
3393             self.verify_capture_in(capture, self.pg7)
3394
3395             if_idx = self.pg8.sw_if_index
3396             cnt = self.get_stats_counter(
3397                 '/nat44-ed/out2in/fastpath/tcp')
3398             self.assertEqual(cnt[if_idx] - tcpn[if_idx], 2)
3399             cnt = self.get_stats_counter(
3400                 '/nat44-ed/out2in/fastpath/udp')
3401             self.assertEqual(cnt[if_idx] - udpn[if_idx], 1)
3402             cnt = self.get_stats_counter(
3403                 '/nat44-ed/out2in/fastpath/icmp')
3404             self.assertEqual(cnt[if_idx] - icmpn[if_idx], 1)
3405             cnt = self.get_stats_counter(
3406                 '/nat44-ed/out2in/fastpath/drops')
3407             self.assertEqual(cnt[if_idx] - drops[if_idx], 0)
3408
3409             sessions = self.get_stats_counter('/nat44-ed/total-sessions')
3410             self.assertEqual(sessions[0], 3)
3411
3412         finally:
3413             self.configure_ip4_interface(self.pg7, table_id=0)
3414             self.configure_ip4_interface(self.pg8, table_id=0)
3415
3416             self.vapi.ip_table_add_del(is_add=0,
3417                                        table={'table_id': new_vrf_id})
3418
3419     def test_next_src_nat(self):
3420         """ NAT44ED On way back forward packet to nat44-in2out node. """
3421
3422         twice_nat_addr = '10.0.1.3'
3423         external_port = 80
3424         local_port = 8080
3425         post_twice_nat_port = 0
3426
3427         self.vapi.nat44_forwarding_enable_disable(enable=1)
3428         self.nat_add_address(twice_nat_addr, twice_nat=1)
3429         flags = (self.config_flags.NAT_IS_OUT2IN_ONLY |
3430                  self.config_flags.NAT_IS_SELF_TWICE_NAT)
3431         self.nat_add_static_mapping(self.pg6.remote_ip4, self.pg1.remote_ip4,
3432                                     local_port, external_port,
3433                                     proto=IP_PROTOS.tcp, vrf_id=1,
3434                                     flags=flags)
3435         self.vapi.nat44_interface_add_del_feature(
3436             sw_if_index=self.pg6.sw_if_index,
3437             is_add=1)
3438
3439         p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
3440              IP(src=self.pg6.remote_ip4, dst=self.pg1.remote_ip4) /
3441              TCP(sport=12345, dport=external_port))
3442         self.pg6.add_stream(p)
3443         self.pg_enable_capture(self.pg_interfaces)
3444         self.pg_start()
3445         capture = self.pg6.get_capture(1)
3446         p = capture[0]
3447         try:
3448             ip = p[IP]
3449             tcp = p[TCP]
3450             self.assertEqual(ip.src, twice_nat_addr)
3451             self.assertNotEqual(tcp.sport, 12345)
3452             post_twice_nat_port = tcp.sport
3453             self.assertEqual(ip.dst, self.pg6.remote_ip4)
3454             self.assertEqual(tcp.dport, local_port)
3455             self.assert_packet_checksums_valid(p)
3456         except:
3457             self.logger.error(ppp("Unexpected or invalid packet:", p))
3458             raise
3459
3460         p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
3461              IP(src=self.pg6.remote_ip4, dst=twice_nat_addr) /
3462              TCP(sport=local_port, dport=post_twice_nat_port))
3463         self.pg6.add_stream(p)
3464         self.pg_enable_capture(self.pg_interfaces)
3465         self.pg_start()
3466         capture = self.pg6.get_capture(1)
3467         p = capture[0]
3468         try:
3469             ip = p[IP]
3470             tcp = p[TCP]
3471             self.assertEqual(ip.src, self.pg1.remote_ip4)
3472             self.assertEqual(tcp.sport, external_port)
3473             self.assertEqual(ip.dst, self.pg6.remote_ip4)
3474             self.assertEqual(tcp.dport, 12345)
3475             self.assert_packet_checksums_valid(p)
3476         except:
3477             self.logger.error(ppp("Unexpected or invalid packet:", p))
3478             raise
3479
3480     def test_one_armed_nat44_static(self):
3481         """ NAT44ED One armed NAT and 1:1 NAPT asymmetrical rule """
3482
3483         remote_host = self.pg4.remote_hosts[0]
3484         local_host = self.pg4.remote_hosts[1]
3485         external_port = 80
3486         local_port = 8080
3487         eh_port_in = 0
3488
3489         self.vapi.nat44_forwarding_enable_disable(enable=1)
3490         self.nat_add_address(self.nat_addr, twice_nat=1)
3491         flags = (self.config_flags.NAT_IS_OUT2IN_ONLY |
3492                  self.config_flags.NAT_IS_TWICE_NAT)
3493         self.nat_add_static_mapping(local_host.ip4, self.nat_addr,
3494                                     local_port, external_port,
3495                                     proto=IP_PROTOS.tcp, flags=flags)
3496         flags = self.config_flags.NAT_IS_INSIDE
3497         self.vapi.nat44_interface_add_del_feature(
3498             sw_if_index=self.pg4.sw_if_index,
3499             is_add=1)
3500         self.vapi.nat44_interface_add_del_feature(
3501             sw_if_index=self.pg4.sw_if_index,
3502             flags=flags, is_add=1)
3503
3504         # from client to service
3505         p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
3506              IP(src=remote_host.ip4, dst=self.nat_addr) /
3507              TCP(sport=12345, dport=external_port))
3508         self.pg4.add_stream(p)
3509         self.pg_enable_capture(self.pg_interfaces)
3510         self.pg_start()
3511         capture = self.pg4.get_capture(1)
3512         p = capture[0]
3513         try:
3514             ip = p[IP]
3515             tcp = p[TCP]
3516             self.assertEqual(ip.dst, local_host.ip4)
3517             self.assertEqual(ip.src, self.nat_addr)
3518             self.assertEqual(tcp.dport, local_port)
3519             self.assertNotEqual(tcp.sport, 12345)
3520             eh_port_in = tcp.sport
3521             self.assert_packet_checksums_valid(p)
3522         except:
3523             self.logger.error(ppp("Unexpected or invalid packet:", p))
3524             raise
3525
3526         # from service back to client
3527         p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
3528              IP(src=local_host.ip4, dst=self.nat_addr) /
3529              TCP(sport=local_port, dport=eh_port_in))
3530         self.pg4.add_stream(p)
3531         self.pg_enable_capture(self.pg_interfaces)
3532         self.pg_start()
3533         capture = self.pg4.get_capture(1)
3534         p = capture[0]
3535         try:
3536             ip = p[IP]
3537             tcp = p[TCP]
3538             self.assertEqual(ip.src, self.nat_addr)
3539             self.assertEqual(ip.dst, remote_host.ip4)
3540             self.assertEqual(tcp.sport, external_port)
3541             self.assertEqual(tcp.dport, 12345)
3542             self.assert_packet_checksums_valid(p)
3543         except:
3544             self.logger.error(ppp("Unexpected or invalid packet:", p))
3545             raise
3546
3547
3548 if __name__ == '__main__':
3549     unittest.main(testRunner=VppTestRunner)