nat: Final NAT44 EI/ED split patch
[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_plugin_enable_disable(
51             sessions=self.max_sessions, enable=1)
52
53     def plugin_disable(self):
54         self.vapi.nat44_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
1907 class TestNAT44EDMW(TestNAT44ED):
1908     """ NAT44ED MW Test Case """
1909     worker_config = "workers 1"
1910
1911     def get_stats_counter(self, path, worker=1):
1912         return super(TestNAT44EDMW, self).get_stats_counter(path, worker)
1913
1914     @unittest.skip('MW fix required')
1915     def test_users_dump(self):
1916         """ NAT44ED API test - nat44_user_dump """
1917
1918     @unittest.skip('MW fix required')
1919     def test_frag_out_of_order_do_not_translate(self):
1920         """ NAT44ED don't translate fragments arriving out of order """
1921
1922     @unittest.skip('MW fix required')
1923     def test_forwarding(self):
1924         """ NAT44ED forwarding test """
1925
1926     @unittest.skip('MW fix required')
1927     def test_twice_nat(self):
1928         """ NAT44ED Twice NAT """
1929
1930     @unittest.skip('MW fix required')
1931     def test_twice_nat_lb(self):
1932         """ NAT44ED Twice NAT local service load balancing """
1933
1934     @unittest.skip('MW fix required')
1935     def test_output_feature(self):
1936         """ NAT44ED interface output feature (in2out postrouting) """
1937
1938     @unittest.skip('MW fix required')
1939     def test_static_with_port_out2(self):
1940         """ NAT44ED 1:1 NAPT asymmetrical rule """
1941
1942     @unittest.skip('MW fix required')
1943     def test_output_feature_and_service2(self):
1944         """ NAT44ED interface output feature and service host direct access """
1945
1946     @unittest.skip('MW fix required')
1947     def test_static_lb(self):
1948         """ NAT44ED local service load balancing """
1949
1950     @unittest.skip('MW fix required')
1951     def test_static_lb_2(self):
1952         """ NAT44ED local service load balancing (asymmetrical rule) """
1953
1954     @unittest.skip('MW fix required')
1955     def test_lb_affinity(self):
1956         """ NAT44ED local service load balancing affinity """
1957
1958     @unittest.skip('MW fix required')
1959     def test_multiple_vrf(self):
1960         """ NAT44ED Multiple VRF setup """
1961
1962     @unittest.skip('MW fix required')
1963     def test_self_twice_nat_positive(self):
1964         """ NAT44ED Self Twice NAT (positive test) """
1965
1966     @unittest.skip('MW fix required')
1967     def test_self_twice_nat_lb_positive(self):
1968         """ NAT44ED Self Twice NAT local service load balancing (positive test)
1969         """
1970
1971     def test_dynamic(self):
1972         """ NAT44ED dynamic translation test """
1973
1974         self.nat_add_address(self.nat_addr)
1975         self.nat_add_inside_interface(self.pg0)
1976         self.nat_add_outside_interface(self.pg1)
1977
1978         # in2out
1979         tc1 = self.get_stats_counter('/nat44-ed/in2out/slowpath/tcp')
1980         uc1 = self.get_stats_counter('/nat44-ed/in2out/slowpath/udp')
1981         ic1 = self.get_stats_counter('/nat44-ed/in2out/slowpath/icmp')
1982         dc1 = self.get_stats_counter('/nat44-ed/in2out/slowpath/drops')
1983
1984         pkts = self.create_stream_in(self.pg0, self.pg1)
1985         # TODO: specify worker=idx, also stats have to
1986         #       know from which worker to take capture
1987         self.pg0.add_stream(pkts)
1988         self.pg_enable_capture(self.pg_interfaces)
1989         self.pg_start()
1990         capture = self.pg1.get_capture(len(pkts))
1991         self.verify_capture_out(capture, ignore_port=True)
1992
1993         if_idx = self.pg0.sw_if_index
1994         tc2 = self.get_stats_counter('/nat44-ed/in2out/slowpath/tcp')
1995         uc2 = self.get_stats_counter('/nat44-ed/in2out/slowpath/udp')
1996         ic2 = self.get_stats_counter('/nat44-ed/in2out/slowpath/icmp')
1997         dc2 = self.get_stats_counter('/nat44-ed/in2out/slowpath/drops')
1998
1999         self.assertEqual(tc2[if_idx] - tc1[if_idx], 2)
2000         self.assertEqual(uc2[if_idx] - uc1[if_idx], 1)
2001         self.assertEqual(ic2[if_idx] - ic1[if_idx], 1)
2002         self.assertEqual(dc2[if_idx] - dc1[if_idx], 0)
2003
2004         # out2in
2005         tc1 = self.get_stats_counter('/nat44-ed/out2in/fastpath/tcp')
2006         uc1 = self.get_stats_counter('/nat44-ed/out2in/fastpath/udp')
2007         ic1 = self.get_stats_counter('/nat44-ed/out2in/fastpath/icmp')
2008         dc1 = self.get_stats_counter('/nat44-ed/out2in/fastpath/drops')
2009
2010         pkts = self.create_stream_out(self.pg1)
2011         self.pg1.add_stream(pkts)
2012         self.pg_enable_capture(self.pg_interfaces)
2013         self.pg_start()
2014         capture = self.pg0.get_capture(len(pkts))
2015         self.verify_capture_in(capture, self.pg0)
2016
2017         if_idx = self.pg1.sw_if_index
2018         tc2 = self.get_stats_counter('/nat44-ed/out2in/fastpath/tcp')
2019         uc2 = self.get_stats_counter('/nat44-ed/out2in/fastpath/udp')
2020         ic2 = self.get_stats_counter('/nat44-ed/out2in/fastpath/icmp')
2021         dc2 = self.get_stats_counter('/nat44-ed/out2in/fastpath/drops')
2022
2023         self.assertEqual(tc2[if_idx] - tc1[if_idx], 2)
2024         self.assertEqual(uc2[if_idx] - uc1[if_idx], 1)
2025         self.assertEqual(ic2[if_idx] - ic1[if_idx], 1)
2026         self.assertEqual(dc2[if_idx] - dc1[if_idx], 0)
2027
2028         sc = self.get_stats_counter('/nat44-ed/total-sessions')
2029         self.assertEqual(sc[0], 3)
2030
2031     def test_frag_in_order(self):
2032         """ NAT44ED translate fragments arriving in order """
2033
2034         self.nat_add_address(self.nat_addr)
2035         self.nat_add_inside_interface(self.pg0)
2036         self.nat_add_outside_interface(self.pg1)
2037
2038         self.frag_in_order(proto=IP_PROTOS.tcp, ignore_port=True)
2039         self.frag_in_order(proto=IP_PROTOS.udp, ignore_port=True)
2040         self.frag_in_order(proto=IP_PROTOS.icmp, ignore_port=True)
2041
2042     def test_frag_in_order_do_not_translate(self):
2043         """ NAT44ED don't translate fragments arriving in order """
2044
2045         self.nat_add_address(self.nat_addr)
2046         self.nat_add_inside_interface(self.pg0)
2047         self.nat_add_outside_interface(self.pg1)
2048         self.vapi.nat44_forwarding_enable_disable(enable=True)
2049
2050         self.frag_in_order(proto=IP_PROTOS.tcp, dont_translate=True)
2051
2052     def test_frag_out_of_order(self):
2053         """ NAT44ED translate fragments arriving out of order """
2054
2055         self.nat_add_address(self.nat_addr)
2056         self.nat_add_inside_interface(self.pg0)
2057         self.nat_add_outside_interface(self.pg1)
2058
2059         self.frag_out_of_order(proto=IP_PROTOS.tcp, ignore_port=True)
2060         self.frag_out_of_order(proto=IP_PROTOS.udp, ignore_port=True)
2061         self.frag_out_of_order(proto=IP_PROTOS.icmp, ignore_port=True)
2062
2063     def test_frag_in_order_in_plus_out(self):
2064         """ NAT44ED in+out interface fragments in order """
2065
2066         in_port = self.random_port()
2067         out_port = self.random_port()
2068
2069         self.nat_add_address(self.nat_addr)
2070         self.nat_add_inside_interface(self.pg0)
2071         self.nat_add_outside_interface(self.pg0)
2072         self.nat_add_inside_interface(self.pg1)
2073         self.nat_add_outside_interface(self.pg1)
2074
2075         # add static mappings for server
2076         self.nat_add_static_mapping(self.server_addr,
2077                                     self.nat_addr,
2078                                     in_port,
2079                                     out_port,
2080                                     proto=IP_PROTOS.tcp)
2081         self.nat_add_static_mapping(self.server_addr,
2082                                     self.nat_addr,
2083                                     in_port,
2084                                     out_port,
2085                                     proto=IP_PROTOS.udp)
2086         self.nat_add_static_mapping(self.server_addr,
2087                                     self.nat_addr,
2088                                     proto=IP_PROTOS.icmp)
2089
2090         # run tests for each protocol
2091         self.frag_in_order_in_plus_out(self.server_addr,
2092                                        self.nat_addr,
2093                                        in_port,
2094                                        out_port,
2095                                        IP_PROTOS.tcp)
2096         self.frag_in_order_in_plus_out(self.server_addr,
2097                                        self.nat_addr,
2098                                        in_port,
2099                                        out_port,
2100                                        IP_PROTOS.udp)
2101         self.frag_in_order_in_plus_out(self.server_addr,
2102                                        self.nat_addr,
2103                                        in_port,
2104                                        out_port,
2105                                        IP_PROTOS.icmp)
2106
2107     def test_frag_out_of_order_in_plus_out(self):
2108         """ NAT44ED in+out interface fragments out of order """
2109
2110         in_port = self.random_port()
2111         out_port = self.random_port()
2112
2113         self.nat_add_address(self.nat_addr)
2114         self.nat_add_inside_interface(self.pg0)
2115         self.nat_add_outside_interface(self.pg0)
2116         self.nat_add_inside_interface(self.pg1)
2117         self.nat_add_outside_interface(self.pg1)
2118
2119         # add static mappings for server
2120         self.nat_add_static_mapping(self.server_addr,
2121                                     self.nat_addr,
2122                                     in_port,
2123                                     out_port,
2124                                     proto=IP_PROTOS.tcp)
2125         self.nat_add_static_mapping(self.server_addr,
2126                                     self.nat_addr,
2127                                     in_port,
2128                                     out_port,
2129                                     proto=IP_PROTOS.udp)
2130         self.nat_add_static_mapping(self.server_addr,
2131                                     self.nat_addr,
2132                                     proto=IP_PROTOS.icmp)
2133
2134         # run tests for each protocol
2135         self.frag_out_of_order_in_plus_out(self.server_addr,
2136                                            self.nat_addr,
2137                                            in_port,
2138                                            out_port,
2139                                            IP_PROTOS.tcp)
2140         self.frag_out_of_order_in_plus_out(self.server_addr,
2141                                            self.nat_addr,
2142                                            in_port,
2143                                            out_port,
2144                                            IP_PROTOS.udp)
2145         self.frag_out_of_order_in_plus_out(self.server_addr,
2146                                            self.nat_addr,
2147                                            in_port,
2148                                            out_port,
2149                                            IP_PROTOS.icmp)
2150
2151     def test_reass_hairpinning(self):
2152         """ NAT44ED fragments hairpinning """
2153
2154         server_addr = self.pg0.remote_hosts[1].ip4
2155
2156         host_in_port = self.random_port()
2157         server_in_port = self.random_port()
2158         server_out_port = self.random_port()
2159
2160         self.nat_add_address(self.nat_addr)
2161         self.nat_add_inside_interface(self.pg0)
2162         self.nat_add_outside_interface(self.pg1)
2163
2164         # add static mapping for server
2165         self.nat_add_static_mapping(server_addr, self.nat_addr,
2166                                     server_in_port, server_out_port,
2167                                     proto=IP_PROTOS.tcp)
2168         self.nat_add_static_mapping(server_addr, self.nat_addr,
2169                                     server_in_port, server_out_port,
2170                                     proto=IP_PROTOS.udp)
2171         self.nat_add_static_mapping(server_addr, self.nat_addr)
2172
2173         self.reass_hairpinning(server_addr, server_in_port, server_out_port,
2174                                host_in_port, proto=IP_PROTOS.tcp,
2175                                ignore_port=True)
2176         self.reass_hairpinning(server_addr, server_in_port, server_out_port,
2177                                host_in_port, proto=IP_PROTOS.udp,
2178                                ignore_port=True)
2179         self.reass_hairpinning(server_addr, server_in_port, server_out_port,
2180                                host_in_port, proto=IP_PROTOS.icmp,
2181                                ignore_port=True)
2182
2183     def test_session_limit_per_vrf(self):
2184         """ NAT44ED per vrf session limit """
2185
2186         inside = self.pg0
2187         inside_vrf10 = self.pg2
2188         outside = self.pg1
2189
2190         limit = 5
2191
2192         # 2 interfaces pg0, pg1 (vrf10, limit 1 tcp session)
2193         # non existing vrf_id makes process core dump
2194         self.vapi.nat44_set_session_limit(session_limit=limit, vrf_id=10)
2195
2196         self.nat_add_inside_interface(inside)
2197         self.nat_add_inside_interface(inside_vrf10)
2198         self.nat_add_outside_interface(outside)
2199
2200         # vrf independent
2201         self.nat_add_interface_address(outside)
2202
2203         # BUG: causing core dump - when bad vrf_id is specified
2204         # self.nat_add_address(outside.local_ip4, vrf_id=20)
2205
2206         stream = self.create_tcp_stream(inside_vrf10, outside, limit * 2)
2207         inside_vrf10.add_stream(stream)
2208
2209         self.pg_enable_capture(self.pg_interfaces)
2210         self.pg_start()
2211
2212         capture = outside.get_capture(limit)
2213
2214         stream = self.create_tcp_stream(inside, outside, limit * 2)
2215         inside.add_stream(stream)
2216
2217         self.pg_enable_capture(self.pg_interfaces)
2218         self.pg_start()
2219
2220         capture = outside.get_capture(len(stream))
2221
2222     def test_show_max_translations(self):
2223         """ NAT44ED API test - max translations per thread """
2224         nat_config = self.vapi.nat_show_config_2()
2225         self.assertEqual(self.max_sessions,
2226                          nat_config.max_translations_per_thread)
2227
2228     def test_lru_cleanup(self):
2229         """ NAT44ED LRU cleanup algorithm """
2230
2231         self.nat_add_address(self.nat_addr)
2232         self.nat_add_inside_interface(self.pg0)
2233         self.nat_add_outside_interface(self.pg1)
2234
2235         self.vapi.nat_set_timeouts(
2236             udp=1, tcp_established=7440, tcp_transitory=30, icmp=1)
2237
2238         tcp_port_out = self.init_tcp_session(self.pg0, self.pg1, 2000, 80)
2239         pkts = []
2240         for i in range(0, self.max_sessions - 1):
2241             p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2242                  IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4, ttl=64) /
2243                  UDP(sport=7000+i, dport=80))
2244             pkts.append(p)
2245
2246         self.pg0.add_stream(pkts)
2247         self.pg_enable_capture(self.pg_interfaces)
2248         self.pg_start()
2249         self.pg1.get_capture(len(pkts))
2250         self.sleep(1.5, "wait for timeouts")
2251
2252         pkts = []
2253         for i in range(0, self.max_sessions - 1):
2254             p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2255                  IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4, ttl=64) /
2256                  ICMP(id=8000+i, type='echo-request'))
2257             pkts.append(p)
2258
2259         self.pg0.add_stream(pkts)
2260         self.pg_enable_capture(self.pg_interfaces)
2261         self.pg_start()
2262         self.pg1.get_capture(len(pkts))
2263
2264     def test_session_rst_timeout(self):
2265         """ NAT44ED session RST timeouts """
2266
2267         self.nat_add_address(self.nat_addr)
2268         self.nat_add_inside_interface(self.pg0)
2269         self.nat_add_outside_interface(self.pg1)
2270
2271         self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
2272                                    tcp_transitory=5, icmp=60)
2273
2274         self.init_tcp_session(self.pg0, self.pg1, self.tcp_port_in,
2275                               self.tcp_external_port)
2276         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
2277              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2278              TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
2279                  flags="R"))
2280         self.pg0.add_stream(p)
2281         self.pg_enable_capture(self.pg_interfaces)
2282         self.pg_start()
2283         self.pg1.get_capture(1)
2284
2285         self.sleep(6)
2286
2287         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
2288              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2289              TCP(sport=self.tcp_port_in + 1, dport=self.tcp_external_port + 1,
2290                  flags="S"))
2291         self.pg0.add_stream(p)
2292         self.pg_enable_capture(self.pg_interfaces)
2293         self.pg_start()
2294         self.pg1.get_capture(1)
2295
2296     def test_dynamic_out_of_ports(self):
2297         """ NAT44ED dynamic translation test: out of ports """
2298
2299         self.nat_add_inside_interface(self.pg0)
2300         self.nat_add_outside_interface(self.pg1)
2301
2302         # in2out and no NAT addresses added
2303         err_old = self.statistics.get_err_counter(
2304             '/err/nat44-ed-in2out-slowpath/out of ports')
2305
2306         pkts = self.create_stream_in(self.pg0, self.pg1)
2307         self.pg0.add_stream(pkts)
2308         self.pg_enable_capture(self.pg_interfaces)
2309         self.pg_start()
2310         self.pg1.get_capture(0, timeout=1)
2311
2312         err_new = self.statistics.get_err_counter(
2313             '/err/nat44-ed-in2out-slowpath/out of ports')
2314
2315         self.assertEqual(err_new - err_old, len(pkts))
2316
2317         # in2out after NAT addresses added
2318         self.nat_add_address(self.nat_addr)
2319
2320         err_old = self.statistics.get_err_counter(
2321             '/err/nat44-ed-in2out-slowpath/out of ports')
2322
2323         pkts = self.create_stream_in(self.pg0, self.pg1)
2324         self.pg0.add_stream(pkts)
2325         self.pg_enable_capture(self.pg_interfaces)
2326         self.pg_start()
2327         capture = self.pg1.get_capture(len(pkts))
2328         self.verify_capture_out(capture, ignore_port=True)
2329
2330         err_new = self.statistics.get_err_counter(
2331             '/err/nat44-ed-in2out-slowpath/out of ports')
2332
2333         self.assertEqual(err_new, err_old)
2334
2335     def test_unknown_proto(self):
2336         """ NAT44ED translate packet with unknown protocol """
2337
2338         self.nat_add_address(self.nat_addr)
2339         self.nat_add_inside_interface(self.pg0)
2340         self.nat_add_outside_interface(self.pg1)
2341
2342         # in2out
2343         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2344              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2345              TCP(sport=self.tcp_port_in, dport=20))
2346         self.pg0.add_stream(p)
2347         self.pg_enable_capture(self.pg_interfaces)
2348         self.pg_start()
2349         p = self.pg1.get_capture(1)
2350
2351         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2352              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2353              GRE() /
2354              IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
2355              TCP(sport=1234, dport=1234))
2356         self.pg0.add_stream(p)
2357         self.pg_enable_capture(self.pg_interfaces)
2358         self.pg_start()
2359         p = self.pg1.get_capture(1)
2360         packet = p[0]
2361         try:
2362             self.assertEqual(packet[IP].src, self.nat_addr)
2363             self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
2364             self.assertEqual(packet.haslayer(GRE), 1)
2365             self.assert_packet_checksums_valid(packet)
2366         except:
2367             self.logger.error(ppp("Unexpected or invalid packet:", packet))
2368             raise
2369
2370         # out2in
2371         p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
2372              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
2373              GRE() /
2374              IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
2375              TCP(sport=1234, dport=1234))
2376         self.pg1.add_stream(p)
2377         self.pg_enable_capture(self.pg_interfaces)
2378         self.pg_start()
2379         p = self.pg0.get_capture(1)
2380         packet = p[0]
2381         try:
2382             self.assertEqual(packet[IP].src, self.pg1.remote_ip4)
2383             self.assertEqual(packet[IP].dst, self.pg0.remote_ip4)
2384             self.assertEqual(packet.haslayer(GRE), 1)
2385             self.assert_packet_checksums_valid(packet)
2386         except:
2387             self.logger.error(ppp("Unexpected or invalid packet:", packet))
2388             raise
2389
2390     def test_hairpinning_unknown_proto(self):
2391         """ NAT44ED translate packet with unknown protocol - hairpinning """
2392         host = self.pg0.remote_hosts[0]
2393         server = self.pg0.remote_hosts[1]
2394         host_in_port = 1234
2395         server_out_port = 8765
2396         server_nat_ip = "10.0.0.11"
2397
2398         self.nat_add_address(self.nat_addr)
2399         self.nat_add_inside_interface(self.pg0)
2400         self.nat_add_outside_interface(self.pg1)
2401
2402         # add static mapping for server
2403         self.nat_add_static_mapping(server.ip4, server_nat_ip)
2404
2405         # host to server
2406         p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
2407              IP(src=host.ip4, dst=server_nat_ip) /
2408              TCP(sport=host_in_port, dport=server_out_port))
2409         self.pg0.add_stream(p)
2410         self.pg_enable_capture(self.pg_interfaces)
2411         self.pg_start()
2412         self.pg0.get_capture(1)
2413
2414         p = (Ether(dst=self.pg0.local_mac, src=host.mac) /
2415              IP(src=host.ip4, dst=server_nat_ip) /
2416              GRE() /
2417              IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
2418              TCP(sport=1234, dport=1234))
2419         self.pg0.add_stream(p)
2420         self.pg_enable_capture(self.pg_interfaces)
2421         self.pg_start()
2422         p = self.pg0.get_capture(1)
2423         packet = p[0]
2424         try:
2425             self.assertEqual(packet[IP].src, self.nat_addr)
2426             self.assertEqual(packet[IP].dst, server.ip4)
2427             self.assertEqual(packet.haslayer(GRE), 1)
2428             self.assert_packet_checksums_valid(packet)
2429         except:
2430             self.logger.error(ppp("Unexpected or invalid packet:", packet))
2431             raise
2432
2433         # server to host
2434         p = (Ether(dst=self.pg0.local_mac, src=server.mac) /
2435              IP(src=server.ip4, dst=self.nat_addr) /
2436              GRE() /
2437              IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
2438              TCP(sport=1234, dport=1234))
2439         self.pg0.add_stream(p)
2440         self.pg_enable_capture(self.pg_interfaces)
2441         self.pg_start()
2442         p = self.pg0.get_capture(1)
2443         packet = p[0]
2444         try:
2445             self.assertEqual(packet[IP].src, server_nat_ip)
2446             self.assertEqual(packet[IP].dst, host.ip4)
2447             self.assertEqual(packet.haslayer(GRE), 1)
2448             self.assert_packet_checksums_valid(packet)
2449         except:
2450             self.logger.error(ppp("Unexpected or invalid packet:", packet))
2451             raise
2452
2453     def test_output_feature_and_service(self):
2454         """ NAT44ED interface output feature and services """
2455         external_addr = '1.2.3.4'
2456         external_port = 80
2457         local_port = 8080
2458
2459         self.vapi.nat44_forwarding_enable_disable(enable=1)
2460         self.nat_add_address(self.nat_addr)
2461         flags = self.config_flags.NAT_IS_ADDR_ONLY
2462         self.vapi.nat44_add_del_identity_mapping(
2463             ip_address=self.pg1.remote_ip4, sw_if_index=0xFFFFFFFF,
2464             flags=flags, is_add=1)
2465         flags = self.config_flags.NAT_IS_OUT2IN_ONLY
2466         self.nat_add_static_mapping(self.pg0.remote_ip4, external_addr,
2467                                     local_port, external_port,
2468                                     proto=IP_PROTOS.tcp, flags=flags)
2469
2470         self.nat_add_inside_interface(self.pg0)
2471         self.nat_add_outside_interface(self.pg0)
2472         self.vapi.nat44_interface_add_del_output_feature(
2473             sw_if_index=self.pg1.sw_if_index, is_add=1)
2474
2475         # from client to service
2476         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
2477              IP(src=self.pg1.remote_ip4, dst=external_addr) /
2478              TCP(sport=12345, dport=external_port))
2479         self.pg1.add_stream(p)
2480         self.pg_enable_capture(self.pg_interfaces)
2481         self.pg_start()
2482         capture = self.pg0.get_capture(1)
2483         p = capture[0]
2484         try:
2485             ip = p[IP]
2486             tcp = p[TCP]
2487             self.assertEqual(ip.dst, self.pg0.remote_ip4)
2488             self.assertEqual(tcp.dport, local_port)
2489             self.assert_packet_checksums_valid(p)
2490         except:
2491             self.logger.error(ppp("Unexpected or invalid packet:", p))
2492             raise
2493
2494         # from service back to client
2495         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
2496              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2497              TCP(sport=local_port, dport=12345))
2498         self.pg0.add_stream(p)
2499         self.pg_enable_capture(self.pg_interfaces)
2500         self.pg_start()
2501         capture = self.pg1.get_capture(1)
2502         p = capture[0]
2503         try:
2504             ip = p[IP]
2505             tcp = p[TCP]
2506             self.assertEqual(ip.src, external_addr)
2507             self.assertEqual(tcp.sport, external_port)
2508             self.assert_packet_checksums_valid(p)
2509         except:
2510             self.logger.error(ppp("Unexpected or invalid packet:", p))
2511             raise
2512
2513         # from local network host to external network
2514         pkts = self.create_stream_in(self.pg0, self.pg1)
2515         self.pg0.add_stream(pkts)
2516         self.pg_enable_capture(self.pg_interfaces)
2517         self.pg_start()
2518         capture = self.pg1.get_capture(len(pkts))
2519         self.verify_capture_out(capture, ignore_port=True)
2520         pkts = self.create_stream_in(self.pg0, self.pg1)
2521         self.pg0.add_stream(pkts)
2522         self.pg_enable_capture(self.pg_interfaces)
2523         self.pg_start()
2524         capture = self.pg1.get_capture(len(pkts))
2525         self.verify_capture_out(capture, ignore_port=True)
2526
2527         # from external network back to local network host
2528         pkts = self.create_stream_out(self.pg1)
2529         self.pg1.add_stream(pkts)
2530         self.pg_enable_capture(self.pg_interfaces)
2531         self.pg_start()
2532         capture = self.pg0.get_capture(len(pkts))
2533         self.verify_capture_in(capture, self.pg0)
2534
2535     def test_output_feature_and_service3(self):
2536         """ NAT44ED interface output feature and DST NAT """
2537         external_addr = '1.2.3.4'
2538         external_port = 80
2539         local_port = 8080
2540
2541         self.vapi.nat44_forwarding_enable_disable(enable=1)
2542         self.nat_add_address(self.nat_addr)
2543         flags = self.config_flags.NAT_IS_OUT2IN_ONLY
2544         self.nat_add_static_mapping(self.pg1.remote_ip4, external_addr,
2545                                     local_port, external_port,
2546                                     proto=IP_PROTOS.tcp, flags=flags)
2547
2548         self.nat_add_inside_interface(self.pg0)
2549         self.nat_add_outside_interface(self.pg0)
2550         self.vapi.nat44_interface_add_del_output_feature(
2551             sw_if_index=self.pg1.sw_if_index, is_add=1)
2552
2553         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
2554              IP(src=self.pg0.remote_ip4, dst=external_addr) /
2555              TCP(sport=12345, dport=external_port))
2556         self.pg0.add_stream(p)
2557         self.pg_enable_capture(self.pg_interfaces)
2558         self.pg_start()
2559         capture = self.pg1.get_capture(1)
2560         p = capture[0]
2561         try:
2562             ip = p[IP]
2563             tcp = p[TCP]
2564             self.assertEqual(ip.src, self.pg0.remote_ip4)
2565             self.assertEqual(tcp.sport, 12345)
2566             self.assertEqual(ip.dst, self.pg1.remote_ip4)
2567             self.assertEqual(tcp.dport, local_port)
2568             self.assert_packet_checksums_valid(p)
2569         except:
2570             self.logger.error(ppp("Unexpected or invalid packet:", p))
2571             raise
2572
2573         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
2574              IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
2575              TCP(sport=local_port, dport=12345))
2576         self.pg1.add_stream(p)
2577         self.pg_enable_capture(self.pg_interfaces)
2578         self.pg_start()
2579         capture = self.pg0.get_capture(1)
2580         p = capture[0]
2581         try:
2582             ip = p[IP]
2583             tcp = p[TCP]
2584             self.assertEqual(ip.src, external_addr)
2585             self.assertEqual(tcp.sport, external_port)
2586             self.assertEqual(ip.dst, self.pg0.remote_ip4)
2587             self.assertEqual(tcp.dport, 12345)
2588             self.assert_packet_checksums_valid(p)
2589         except:
2590             self.logger.error(ppp("Unexpected or invalid packet:", p))
2591             raise
2592
2593     def test_self_twice_nat_lb_negative(self):
2594         """ NAT44ED Self Twice NAT local service load balancing (negative test)
2595         """
2596         self.twice_nat_common(lb=True, self_twice_nat=True, same_pg=True,
2597                               client_id=2)
2598
2599     def test_self_twice_nat_negative(self):
2600         """ NAT44ED Self Twice NAT (negative test) """
2601         self.twice_nat_common(self_twice_nat=True)
2602
2603     def test_static_lb_multi_clients(self):
2604         """ NAT44ED local service load balancing - multiple clients"""
2605
2606         external_addr = self.nat_addr
2607         external_port = 80
2608         local_port = 8080
2609         server1 = self.pg0.remote_hosts[0]
2610         server2 = self.pg0.remote_hosts[1]
2611         server3 = self.pg0.remote_hosts[2]
2612
2613         locals = [{'addr': server1.ip4,
2614                    'port': local_port,
2615                    'probability': 90,
2616                    'vrf_id': 0},
2617                   {'addr': server2.ip4,
2618                    'port': local_port,
2619                    'probability': 10,
2620                    'vrf_id': 0}]
2621
2622         flags = self.config_flags.NAT_IS_INSIDE
2623         self.vapi.nat44_interface_add_del_feature(
2624             sw_if_index=self.pg0.sw_if_index,
2625             flags=flags, is_add=1)
2626         self.vapi.nat44_interface_add_del_feature(
2627             sw_if_index=self.pg1.sw_if_index,
2628             is_add=1)
2629
2630         self.nat_add_address(self.nat_addr)
2631         self.vapi.nat44_add_del_lb_static_mapping(is_add=1,
2632                                                   external_addr=external_addr,
2633                                                   external_port=external_port,
2634                                                   protocol=IP_PROTOS.tcp,
2635                                                   local_num=len(locals),
2636                                                   locals=locals)
2637
2638         server1_n = 0
2639         server2_n = 0
2640         clients = ip4_range(self.pg1.remote_ip4, 10, 50)
2641         pkts = []
2642         for client in clients:
2643             p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
2644                  IP(src=client, dst=self.nat_addr) /
2645                  TCP(sport=12345, dport=external_port))
2646             pkts.append(p)
2647         self.pg1.add_stream(pkts)
2648         self.pg_enable_capture(self.pg_interfaces)
2649         self.pg_start()
2650         capture = self.pg0.get_capture(len(pkts))
2651         for p in capture:
2652             if p[IP].dst == server1.ip4:
2653                 server1_n += 1
2654             else:
2655                 server2_n += 1
2656         self.assertGreater(server1_n, server2_n)
2657
2658         local = {
2659             'addr': server3.ip4,
2660             'port': local_port,
2661             'probability': 20,
2662             'vrf_id': 0
2663         }
2664
2665         # add new back-end
2666         self.vapi.nat44_lb_static_mapping_add_del_local(
2667             is_add=1,
2668             external_addr=external_addr,
2669             external_port=external_port,
2670             local=local,
2671             protocol=IP_PROTOS.tcp)
2672         server1_n = 0
2673         server2_n = 0
2674         server3_n = 0
2675         clients = ip4_range(self.pg1.remote_ip4, 60, 110)
2676         pkts = []
2677         for client in clients:
2678             p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
2679                  IP(src=client, dst=self.nat_addr) /
2680                  TCP(sport=12346, dport=external_port))
2681             pkts.append(p)
2682         self.assertGreater(len(pkts), 0)
2683         self.pg1.add_stream(pkts)
2684         self.pg_enable_capture(self.pg_interfaces)
2685         self.pg_start()
2686         capture = self.pg0.get_capture(len(pkts))
2687         for p in capture:
2688             if p[IP].dst == server1.ip4:
2689                 server1_n += 1
2690             elif p[IP].dst == server2.ip4:
2691                 server2_n += 1
2692             else:
2693                 server3_n += 1
2694         self.assertGreater(server1_n, 0)
2695         self.assertGreater(server2_n, 0)
2696         self.assertGreater(server3_n, 0)
2697
2698         local = {
2699             'addr': server2.ip4,
2700             'port': local_port,
2701             'probability': 10,
2702             'vrf_id': 0
2703         }
2704
2705         # remove one back-end
2706         self.vapi.nat44_lb_static_mapping_add_del_local(
2707             is_add=0,
2708             external_addr=external_addr,
2709             external_port=external_port,
2710             local=local,
2711             protocol=IP_PROTOS.tcp)
2712         server1_n = 0
2713         server2_n = 0
2714         server3_n = 0
2715         self.pg1.add_stream(pkts)
2716         self.pg_enable_capture(self.pg_interfaces)
2717         self.pg_start()
2718         capture = self.pg0.get_capture(len(pkts))
2719         for p in capture:
2720             if p[IP].dst == server1.ip4:
2721                 server1_n += 1
2722             elif p[IP].dst == server2.ip4:
2723                 server2_n += 1
2724             else:
2725                 server3_n += 1
2726         self.assertGreater(server1_n, 0)
2727         self.assertEqual(server2_n, 0)
2728         self.assertGreater(server3_n, 0)
2729
2730     def test_syslog_sess(self):
2731         """ NAT44ED Test syslog session creation and deletion """
2732         self.vapi.syslog_set_filter(
2733             self.syslog_severity.SYSLOG_API_SEVERITY_INFO)
2734         self.vapi.syslog_set_sender(self.pg3.local_ip4, self.pg3.remote_ip4)
2735
2736         self.nat_add_address(self.nat_addr)
2737         self.nat_add_inside_interface(self.pg0)
2738         self.nat_add_outside_interface(self.pg1)
2739
2740         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2741              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2742              TCP(sport=self.tcp_port_in, dport=self.tcp_external_port))
2743         self.pg0.add_stream(p)
2744         self.pg_enable_capture(self.pg_interfaces)
2745         self.pg_start()
2746         capture = self.pg1.get_capture(1)
2747         self.tcp_port_out = capture[0][TCP].sport
2748         capture = self.pg3.get_capture(1)
2749         self.verify_syslog_sess(capture[0][Raw].load)
2750
2751         self.pg_enable_capture(self.pg_interfaces)
2752         self.pg_start()
2753         self.nat_add_address(self.nat_addr, is_add=0)
2754         capture = self.pg3.get_capture(1)
2755         self.verify_syslog_sess(capture[0][Raw].load, False)
2756
2757     def test_twice_nat_interface_addr(self):
2758         """ NAT44ED Acquire twice NAT addresses from interface """
2759         flags = self.config_flags.NAT_IS_TWICE_NAT
2760         self.vapi.nat44_add_del_interface_addr(
2761             sw_if_index=self.pg11.sw_if_index,
2762             flags=flags, is_add=1)
2763
2764         # no address in NAT pool
2765         adresses = self.vapi.nat44_address_dump()
2766         self.assertEqual(0, len(adresses))
2767
2768         # configure interface address and check NAT address pool
2769         self.pg11.config_ip4()
2770         adresses = self.vapi.nat44_address_dump()
2771         self.assertEqual(1, len(adresses))
2772         self.assertEqual(str(adresses[0].ip_address),
2773                          self.pg11.local_ip4)
2774         self.assertEqual(adresses[0].flags, flags)
2775
2776         # remove interface address and check NAT address pool
2777         self.pg11.unconfig_ip4()
2778         adresses = self.vapi.nat44_address_dump()
2779         self.assertEqual(0, len(adresses))
2780
2781     def test_output_feature_stateful_acl(self):
2782         """ NAT44ED output feature works with stateful ACL """
2783
2784         self.nat_add_address(self.nat_addr)
2785         self.vapi.nat44_interface_add_del_output_feature(
2786             sw_if_index=self.pg0.sw_if_index,
2787             flags=self.config_flags.NAT_IS_INSIDE, is_add=1)
2788         self.vapi.nat44_interface_add_del_output_feature(
2789             sw_if_index=self.pg1.sw_if_index,
2790             flags=self.config_flags.NAT_IS_OUTSIDE, is_add=1)
2791
2792         # First ensure that the NAT is working sans ACL
2793
2794         # send packets out2in, no sessions yet so packets should drop
2795         pkts_out2in = self.create_stream_out(self.pg1)
2796         self.send_and_assert_no_replies(self.pg1, pkts_out2in)
2797
2798         # send packets into inside intf, ensure received via outside intf
2799         pkts_in2out = self.create_stream_in(self.pg0, self.pg1)
2800         capture = self.send_and_expect(self.pg0, pkts_in2out, self.pg1,
2801                                        len(pkts_in2out))
2802         self.verify_capture_out(capture, ignore_port=True)
2803
2804         # send out2in again, with sessions created it should work now
2805         pkts_out2in = self.create_stream_out(self.pg1)
2806         capture = self.send_and_expect(self.pg1, pkts_out2in, self.pg0,
2807                                        len(pkts_out2in))
2808         self.verify_capture_in(capture, self.pg0)
2809
2810         # Create an ACL blocking everything
2811         out2in_deny_rule = AclRule(is_permit=0)
2812         out2in_acl = VppAcl(self, rules=[out2in_deny_rule])
2813         out2in_acl.add_vpp_config()
2814
2815         # create an ACL to permit/reflect everything
2816         in2out_reflect_rule = AclRule(is_permit=2)
2817         in2out_acl = VppAcl(self, rules=[in2out_reflect_rule])
2818         in2out_acl.add_vpp_config()
2819
2820         # apply as input acl on interface and confirm it blocks everything
2821         acl_if = VppAclInterface(self, sw_if_index=self.pg1.sw_if_index,
2822                                  n_input=1, acls=[out2in_acl])
2823         acl_if.add_vpp_config()
2824         self.send_and_assert_no_replies(self.pg1, pkts_out2in)
2825
2826         # apply output acl
2827         acl_if.acls = [out2in_acl, in2out_acl]
2828         acl_if.add_vpp_config()
2829         # send in2out to generate ACL state (NAT state was created earlier)
2830         capture = self.send_and_expect(self.pg0, pkts_in2out, self.pg1,
2831                                        len(pkts_in2out))
2832         self.verify_capture_out(capture, ignore_port=True)
2833
2834         # send out2in again. ACL state exists so it should work now.
2835         # TCP packets with the syn flag set also need the ack flag
2836         for p in pkts_out2in:
2837             if p.haslayer(TCP) and p[TCP].flags & 0x02:
2838                 p[TCP].flags |= 0x10
2839         capture = self.send_and_expect(self.pg1, pkts_out2in, self.pg0,
2840                                        len(pkts_out2in))
2841         self.verify_capture_in(capture, self.pg0)
2842         self.logger.info(self.vapi.cli("show trace"))
2843
2844     def test_tcp_close(self):
2845         """ NAT44ED Close TCP session from inside network - output feature """
2846         old_timeouts = self.vapi.nat_get_timeouts()
2847         new_transitory = 2
2848         self.vapi.nat_set_timeouts(
2849             udp=old_timeouts.udp,
2850             tcp_established=old_timeouts.tcp_established,
2851             icmp=old_timeouts.icmp,
2852             tcp_transitory=new_transitory)
2853
2854         self.vapi.nat44_forwarding_enable_disable(enable=1)
2855         self.nat_add_address(self.pg1.local_ip4)
2856         twice_nat_addr = '10.0.1.3'
2857         service_ip = '192.168.16.150'
2858         self.nat_add_address(twice_nat_addr, twice_nat=1)
2859
2860         flags = self.config_flags.NAT_IS_INSIDE
2861         self.vapi.nat44_interface_add_del_feature(
2862             sw_if_index=self.pg0.sw_if_index,
2863             is_add=1)
2864         self.vapi.nat44_interface_add_del_feature(
2865             sw_if_index=self.pg0.sw_if_index,
2866             flags=flags, is_add=1)
2867         self.vapi.nat44_interface_add_del_output_feature(
2868             is_add=1,
2869             sw_if_index=self.pg1.sw_if_index)
2870
2871         flags = (self.config_flags.NAT_IS_OUT2IN_ONLY |
2872                  self.config_flags.NAT_IS_TWICE_NAT)
2873         self.nat_add_static_mapping(self.pg0.remote_ip4,
2874                                     service_ip, 80, 80,
2875                                     proto=IP_PROTOS.tcp,
2876                                     flags=flags)
2877         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
2878         start_sessnum = len(sessions)
2879
2880         # SYN packet out->in
2881         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
2882              IP(src=self.pg1.remote_ip4, dst=service_ip) /
2883              TCP(sport=33898, dport=80, flags="S"))
2884         self.pg1.add_stream(p)
2885         self.pg_enable_capture(self.pg_interfaces)
2886         self.pg_start()
2887         capture = self.pg0.get_capture(1)
2888         p = capture[0]
2889         tcp_port = p[TCP].sport
2890
2891         # SYN + ACK packet in->out
2892         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
2893              IP(src=self.pg0.remote_ip4, dst=twice_nat_addr) /
2894              TCP(sport=80, dport=tcp_port, flags="SA"))
2895         self.pg0.add_stream(p)
2896         self.pg_enable_capture(self.pg_interfaces)
2897         self.pg_start()
2898         self.pg1.get_capture(1)
2899
2900         # ACK packet out->in
2901         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
2902              IP(src=self.pg1.remote_ip4, dst=service_ip) /
2903              TCP(sport=33898, dport=80, flags="A"))
2904         self.pg1.add_stream(p)
2905         self.pg_enable_capture(self.pg_interfaces)
2906         self.pg_start()
2907         self.pg0.get_capture(1)
2908
2909         # FIN packet in -> out
2910         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
2911              IP(src=self.pg0.remote_ip4, dst=twice_nat_addr) /
2912              TCP(sport=80, dport=tcp_port, flags="FA", seq=100, ack=300))
2913         self.pg0.add_stream(p)
2914         self.pg_enable_capture(self.pg_interfaces)
2915         self.pg_start()
2916         self.pg1.get_capture(1)
2917
2918         # FIN+ACK packet out -> in
2919         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
2920              IP(src=self.pg1.remote_ip4, dst=service_ip) /
2921              TCP(sport=33898, dport=80, flags="FA", seq=300, ack=101))
2922         self.pg1.add_stream(p)
2923         self.pg_enable_capture(self.pg_interfaces)
2924         self.pg_start()
2925         self.pg0.get_capture(1)
2926
2927         # ACK packet in -> out
2928         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
2929              IP(src=self.pg0.remote_ip4, dst=twice_nat_addr) /
2930              TCP(sport=80, dport=tcp_port, flags="A", seq=101, ack=301))
2931         self.pg0.add_stream(p)
2932         self.pg_enable_capture(self.pg_interfaces)
2933         self.pg_start()
2934         self.pg1.get_capture(1)
2935
2936         # session now in transitory timeout
2937         # try SYN packet out->in - should be dropped
2938         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
2939              IP(src=self.pg1.remote_ip4, dst=service_ip) /
2940              TCP(sport=33898, dport=80, flags="S"))
2941         self.pg1.add_stream(p)
2942         self.pg_enable_capture(self.pg_interfaces)
2943         self.pg_start()
2944
2945         self.sleep(new_transitory, "wait for transitory timeout")
2946         self.pg0.assert_nothing_captured(0)
2947
2948         # session should still exist
2949         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
2950         self.assertEqual(len(sessions) - start_sessnum, 1)
2951
2952         # send FIN+ACK packet out -> in - will cause session to be wiped
2953         # but won't create a new session
2954         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
2955              IP(src=self.pg1.remote_ip4, dst=service_ip) /
2956              TCP(sport=33898, dport=80, flags="FA", seq=300, ack=101))
2957         self.pg1.add_stream(p)
2958         self.pg_enable_capture(self.pg_interfaces)
2959         self.pg_start()
2960
2961         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
2962         self.assertEqual(len(sessions) - start_sessnum, 0)
2963         self.pg0.assert_nothing_captured(0)
2964
2965     def test_tcp_session_close_in(self):
2966         """ NAT44ED Close TCP session from inside network """
2967
2968         in_port = self.tcp_port_in
2969         out_port = 10505
2970         ext_port = self.tcp_external_port
2971
2972         self.nat_add_address(self.nat_addr)
2973         self.nat_add_inside_interface(self.pg0)
2974         self.nat_add_outside_interface(self.pg1)
2975         self.nat_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
2976                                     in_port, out_port, proto=IP_PROTOS.tcp,
2977                                     flags=self.config_flags.NAT_IS_TWICE_NAT)
2978
2979         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
2980         session_n = len(sessions)
2981
2982         self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
2983                                    tcp_transitory=2, icmp=5)
2984
2985         self.init_tcp_session(self.pg0, self.pg1, in_port, ext_port)
2986
2987         # FIN packet in -> out
2988         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
2989              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2990              TCP(sport=in_port, dport=ext_port,
2991                  flags="FA", seq=100, ack=300))
2992         self.pg0.add_stream(p)
2993         self.pg_enable_capture(self.pg_interfaces)
2994         self.pg_start()
2995         self.pg1.get_capture(1)
2996
2997         pkts = []
2998
2999         # ACK packet out -> in
3000         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3001              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3002              TCP(sport=ext_port, dport=out_port,
3003                  flags="A", seq=300, ack=101))
3004         pkts.append(p)
3005
3006         # FIN packet out -> in
3007         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3008              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3009              TCP(sport=ext_port, dport=out_port,
3010                  flags="FA", seq=300, ack=101))
3011         pkts.append(p)
3012
3013         self.pg1.add_stream(pkts)
3014         self.pg_enable_capture(self.pg_interfaces)
3015         self.pg_start()
3016         self.pg0.get_capture(2)
3017
3018         # ACK packet in -> out
3019         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3020              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3021              TCP(sport=in_port, dport=ext_port,
3022                  flags="A", seq=101, ack=301))
3023         self.pg0.add_stream(p)
3024         self.pg_enable_capture(self.pg_interfaces)
3025         self.pg_start()
3026         self.pg1.get_capture(1)
3027
3028         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3029         self.assertEqual(len(sessions) - session_n, 1)
3030
3031         out2in_drops = self.get_err_counter(
3032             '/err/nat44-ed-out2in/drops due to TCP in transitory timeout')
3033         in2out_drops = self.get_err_counter(
3034             '/err/nat44-ed-in2out/drops due to TCP in transitory timeout')
3035
3036         # extra FIN packet out -> in - this should be dropped
3037         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3038              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3039              TCP(sport=ext_port, dport=out_port,
3040                  flags="FA", seq=300, ack=101))
3041
3042         self.pg1.add_stream(p)
3043         self.pg_enable_capture(self.pg_interfaces)
3044         self.pg_start()
3045         self.pg0.assert_nothing_captured()
3046
3047         # extra ACK packet in -> out - this should be dropped
3048         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3049              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3050              TCP(sport=in_port, dport=ext_port,
3051                  flags="A", seq=101, ack=301))
3052         self.pg0.add_stream(p)
3053         self.pg_enable_capture(self.pg_interfaces)
3054         self.pg_start()
3055         self.pg1.assert_nothing_captured()
3056
3057         stats = self.get_err_counter(
3058             '/err/nat44-ed-out2in/drops due to TCP in transitory timeout')
3059         self.assertEqual(stats - out2in_drops, 1)
3060         stats = self.get_err_counter(
3061             '/err/nat44-ed-in2out/drops due to TCP in transitory timeout')
3062         self.assertEqual(stats - in2out_drops, 1)
3063
3064         self.sleep(3)
3065         # extra ACK packet in -> out - this will cause session to be wiped
3066         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3067              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3068              TCP(sport=in_port, dport=ext_port,
3069                  flags="A", seq=101, ack=301))
3070         self.pg0.add_stream(p)
3071         self.pg_enable_capture(self.pg_interfaces)
3072         self.pg_start()
3073         self.pg1.assert_nothing_captured()
3074         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3075         self.assertEqual(len(sessions) - session_n, 0)
3076
3077     def test_tcp_session_close_out(self):
3078         """ NAT44ED Close TCP session from outside network """
3079
3080         in_port = self.tcp_port_in
3081         out_port = 10505
3082         ext_port = self.tcp_external_port
3083
3084         self.nat_add_address(self.nat_addr)
3085         self.nat_add_inside_interface(self.pg0)
3086         self.nat_add_outside_interface(self.pg1)
3087         self.nat_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
3088                                     in_port, out_port, proto=IP_PROTOS.tcp,
3089                                     flags=self.config_flags.NAT_IS_TWICE_NAT)
3090
3091         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3092         session_n = len(sessions)
3093
3094         self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
3095                                    tcp_transitory=2, icmp=5)
3096
3097         _ = self.init_tcp_session(self.pg0, self.pg1, in_port, ext_port)
3098
3099         # FIN packet out -> in
3100         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3101              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3102              TCP(sport=ext_port, dport=out_port,
3103                  flags="FA", seq=100, ack=300))
3104         self.pg1.add_stream(p)
3105         self.pg_enable_capture(self.pg_interfaces)
3106         self.pg_start()
3107         self.pg0.get_capture(1)
3108
3109         # FIN+ACK packet in -> out
3110         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3111              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3112              TCP(sport=in_port, dport=ext_port,
3113                  flags="FA", seq=300, ack=101))
3114
3115         self.pg0.add_stream(p)
3116         self.pg_enable_capture(self.pg_interfaces)
3117         self.pg_start()
3118         self.pg1.get_capture(1)
3119
3120         # ACK packet out -> in
3121         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3122              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3123              TCP(sport=ext_port, dport=out_port,
3124                  flags="A", seq=101, ack=301))
3125         self.pg1.add_stream(p)
3126         self.pg_enable_capture(self.pg_interfaces)
3127         self.pg_start()
3128         self.pg0.get_capture(1)
3129
3130         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3131         self.assertEqual(len(sessions) - session_n, 1)
3132
3133         out2in_drops = self.get_err_counter(
3134             '/err/nat44-ed-out2in/drops due to TCP in transitory timeout')
3135         in2out_drops = self.get_err_counter(
3136             '/err/nat44-ed-in2out/drops due to TCP in transitory timeout')
3137
3138         # extra FIN packet out -> in - this should be dropped
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=300, ack=101))
3143
3144         self.pg1.add_stream(p)
3145         self.pg_enable_capture(self.pg_interfaces)
3146         self.pg_start()
3147         self.pg0.assert_nothing_captured()
3148
3149         # extra ACK packet in -> out - this should be dropped
3150         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3151              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3152              TCP(sport=in_port, dport=ext_port,
3153                  flags="A", seq=101, ack=301))
3154         self.pg0.add_stream(p)
3155         self.pg_enable_capture(self.pg_interfaces)
3156         self.pg_start()
3157         self.pg1.assert_nothing_captured()
3158
3159         stats = self.get_err_counter(
3160             '/err/nat44-ed-out2in/drops due to TCP in transitory timeout')
3161         self.assertEqual(stats - out2in_drops, 1)
3162         stats = self.get_err_counter(
3163             '/err/nat44-ed-in2out/drops due to TCP in transitory timeout')
3164         self.assertEqual(stats - in2out_drops, 1)
3165
3166         self.sleep(3)
3167         # extra ACK packet in -> out - this will cause session to be wiped
3168         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3169              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3170              TCP(sport=in_port, dport=ext_port,
3171                  flags="A", seq=101, ack=301))
3172         self.pg0.add_stream(p)
3173         self.pg_enable_capture(self.pg_interfaces)
3174         self.pg_start()
3175         self.pg1.assert_nothing_captured()
3176         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3177         self.assertEqual(len(sessions) - session_n, 0)
3178
3179     def test_tcp_session_close_simultaneous(self):
3180         """ NAT44ED Close TCP session from inside network """
3181
3182         in_port = self.tcp_port_in
3183         ext_port = 10505
3184
3185         self.nat_add_address(self.nat_addr)
3186         self.nat_add_inside_interface(self.pg0)
3187         self.nat_add_outside_interface(self.pg1)
3188         self.nat_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
3189                                     in_port, ext_port, proto=IP_PROTOS.tcp,
3190                                     flags=self.config_flags.NAT_IS_TWICE_NAT)
3191
3192         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3193         session_n = len(sessions)
3194
3195         self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
3196                                    tcp_transitory=2, icmp=5)
3197
3198         out_port = self.init_tcp_session(self.pg0, self.pg1, in_port, ext_port)
3199
3200         # FIN packet in -> out
3201         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3202              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3203              TCP(sport=in_port, dport=ext_port,
3204                  flags="FA", seq=100, ack=300))
3205         self.pg0.add_stream(p)
3206         self.pg_enable_capture(self.pg_interfaces)
3207         self.pg_start()
3208         self.pg1.get_capture(1)
3209
3210         # FIN packet out -> in
3211         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3212              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3213              TCP(sport=ext_port, dport=out_port,
3214                  flags="FA", seq=300, ack=100))
3215         self.pg1.add_stream(p)
3216         self.pg_enable_capture(self.pg_interfaces)
3217         self.pg_start()
3218         self.pg0.get_capture(1)
3219
3220         # ACK packet in -> out
3221         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3222              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3223              TCP(sport=in_port, dport=ext_port,
3224                  flags="A", seq=101, ack=301))
3225         self.pg0.add_stream(p)
3226         self.pg_enable_capture(self.pg_interfaces)
3227         self.pg_start()
3228         self.pg1.get_capture(1)
3229
3230         # ACK packet out -> in
3231         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3232              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3233              TCP(sport=ext_port, dport=out_port,
3234                  flags="A", seq=301, ack=101))
3235         self.pg1.add_stream(p)
3236         self.pg_enable_capture(self.pg_interfaces)
3237         self.pg_start()
3238         self.pg0.get_capture(1)
3239
3240         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3241         self.assertEqual(len(sessions) - session_n, 1)
3242
3243         out2in_drops = self.get_err_counter(
3244             '/err/nat44-ed-out2in/drops due to TCP in transitory timeout')
3245         in2out_drops = self.get_err_counter(
3246             '/err/nat44-ed-in2out/drops due to TCP in transitory timeout')
3247
3248         # extra FIN packet out -> in - this should be dropped
3249         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3250              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3251              TCP(sport=ext_port, dport=out_port,
3252                  flags="FA", seq=300, ack=101))
3253
3254         self.pg1.add_stream(p)
3255         self.pg_enable_capture(self.pg_interfaces)
3256         self.pg_start()
3257         self.pg0.assert_nothing_captured()
3258
3259         # extra ACK packet in -> out - this should be dropped
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.assert_nothing_captured()
3268
3269         stats = self.get_err_counter(
3270             '/err/nat44-ed-out2in/drops due to TCP in transitory timeout')
3271         self.assertEqual(stats - out2in_drops, 1)
3272         stats = self.get_err_counter(
3273             '/err/nat44-ed-in2out/drops due to TCP in transitory timeout')
3274         self.assertEqual(stats - in2out_drops, 1)
3275
3276         self.sleep(3)
3277         # extra ACK packet in -> out - this will cause session to be wiped
3278         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3279              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3280              TCP(sport=in_port, dport=ext_port,
3281                  flags="A", seq=101, ack=301))
3282         self.pg0.add_stream(p)
3283         self.pg_enable_capture(self.pg_interfaces)
3284         self.pg_start()
3285         self.pg1.assert_nothing_captured()
3286         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3287         self.assertEqual(len(sessions) - session_n, 0)
3288
3289     def test_dynamic_output_feature_vrf(self):
3290         """ NAT44ED dynamic translation test: output-feature, VRF"""
3291
3292         # other then default (0)
3293         new_vrf_id = 22
3294
3295         self.nat_add_address(self.nat_addr)
3296         flags = self.config_flags.NAT_IS_INSIDE
3297         self.vapi.nat44_interface_add_del_output_feature(
3298             sw_if_index=self.pg7.sw_if_index,
3299             flags=flags, is_add=1)
3300         self.vapi.nat44_interface_add_del_output_feature(
3301             sw_if_index=self.pg8.sw_if_index,
3302             is_add=1)
3303
3304         try:
3305             self.configure_ip4_interface(self.pg7, table_id=new_vrf_id)
3306             self.configure_ip4_interface(self.pg8, table_id=new_vrf_id)
3307
3308             # in2out
3309             tcpn = self.get_stats_counter(
3310                 '/nat44-ed/in2out/slowpath/tcp')
3311             udpn = self.get_stats_counter(
3312                 '/nat44-ed/in2out/slowpath/udp')
3313             icmpn = self.get_stats_counter(
3314                 '/nat44-ed/in2out/slowpath/icmp')
3315             drops = self.get_stats_counter(
3316                 '/nat44-ed/in2out/slowpath/drops')
3317
3318             pkts = self.create_stream_in(self.pg7, self.pg8)
3319             self.pg7.add_stream(pkts)
3320             self.pg_enable_capture(self.pg_interfaces)
3321             self.pg_start()
3322             capture = self.pg8.get_capture(len(pkts))
3323             self.verify_capture_out(capture, ignore_port=True)
3324
3325             if_idx = self.pg7.sw_if_index
3326             cnt = self.get_stats_counter(
3327                 '/nat44-ed/in2out/slowpath/tcp')
3328             self.assertEqual(cnt[if_idx] - tcpn[if_idx], 2)
3329             cnt = self.get_stats_counter(
3330                 '/nat44-ed/in2out/slowpath/udp')
3331             self.assertEqual(cnt[if_idx] - udpn[if_idx], 1)
3332             cnt = self.get_stats_counter(
3333                 '/nat44-ed/in2out/slowpath/icmp')
3334             self.assertEqual(cnt[if_idx] - icmpn[if_idx], 1)
3335             cnt = self.get_stats_counter(
3336                 '/nat44-ed/in2out/slowpath/drops')
3337             self.assertEqual(cnt[if_idx] - drops[if_idx], 0)
3338
3339             # out2in
3340             tcpn = self.get_stats_counter(
3341                 '/nat44-ed/out2in/fastpath/tcp')
3342             udpn = self.get_stats_counter(
3343                 '/nat44-ed/out2in/fastpath/udp')
3344             icmpn = self.get_stats_counter(
3345                 '/nat44-ed/out2in/fastpath/icmp')
3346             drops = self.get_stats_counter(
3347                 '/nat44-ed/out2in/fastpath/drops')
3348
3349             pkts = self.create_stream_out(self.pg8)
3350             self.pg8.add_stream(pkts)
3351             self.pg_enable_capture(self.pg_interfaces)
3352             self.pg_start()
3353             capture = self.pg7.get_capture(len(pkts))
3354             self.verify_capture_in(capture, self.pg7)
3355
3356             if_idx = self.pg8.sw_if_index
3357             cnt = self.get_stats_counter(
3358                 '/nat44-ed/out2in/fastpath/tcp')
3359             self.assertEqual(cnt[if_idx] - tcpn[if_idx], 2)
3360             cnt = self.get_stats_counter(
3361                 '/nat44-ed/out2in/fastpath/udp')
3362             self.assertEqual(cnt[if_idx] - udpn[if_idx], 1)
3363             cnt = self.get_stats_counter(
3364                 '/nat44-ed/out2in/fastpath/icmp')
3365             self.assertEqual(cnt[if_idx] - icmpn[if_idx], 1)
3366             cnt = self.get_stats_counter(
3367                 '/nat44-ed/out2in/fastpath/drops')
3368             self.assertEqual(cnt[if_idx] - drops[if_idx], 0)
3369
3370             sessions = self.get_stats_counter('/nat44-ed/total-sessions')
3371             self.assertEqual(sessions[0], 3)
3372
3373         finally:
3374             self.configure_ip4_interface(self.pg7, table_id=0)
3375             self.configure_ip4_interface(self.pg8, table_id=0)
3376
3377             self.vapi.ip_table_add_del(is_add=0,
3378                                        table={'table_id': new_vrf_id})
3379
3380     def test_next_src_nat(self):
3381         """ NAT44ED On way back forward packet to nat44-in2out node. """
3382
3383         twice_nat_addr = '10.0.1.3'
3384         external_port = 80
3385         local_port = 8080
3386         post_twice_nat_port = 0
3387
3388         self.vapi.nat44_forwarding_enable_disable(enable=1)
3389         self.nat_add_address(twice_nat_addr, twice_nat=1)
3390         flags = (self.config_flags.NAT_IS_OUT2IN_ONLY |
3391                  self.config_flags.NAT_IS_SELF_TWICE_NAT)
3392         self.nat_add_static_mapping(self.pg6.remote_ip4, self.pg1.remote_ip4,
3393                                     local_port, external_port,
3394                                     proto=IP_PROTOS.tcp, vrf_id=1,
3395                                     flags=flags)
3396         self.vapi.nat44_interface_add_del_feature(
3397             sw_if_index=self.pg6.sw_if_index,
3398             is_add=1)
3399
3400         p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
3401              IP(src=self.pg6.remote_ip4, dst=self.pg1.remote_ip4) /
3402              TCP(sport=12345, dport=external_port))
3403         self.pg6.add_stream(p)
3404         self.pg_enable_capture(self.pg_interfaces)
3405         self.pg_start()
3406         capture = self.pg6.get_capture(1)
3407         p = capture[0]
3408         try:
3409             ip = p[IP]
3410             tcp = p[TCP]
3411             self.assertEqual(ip.src, twice_nat_addr)
3412             self.assertNotEqual(tcp.sport, 12345)
3413             post_twice_nat_port = tcp.sport
3414             self.assertEqual(ip.dst, self.pg6.remote_ip4)
3415             self.assertEqual(tcp.dport, local_port)
3416             self.assert_packet_checksums_valid(p)
3417         except:
3418             self.logger.error(ppp("Unexpected or invalid packet:", p))
3419             raise
3420
3421         p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
3422              IP(src=self.pg6.remote_ip4, dst=twice_nat_addr) /
3423              TCP(sport=local_port, dport=post_twice_nat_port))
3424         self.pg6.add_stream(p)
3425         self.pg_enable_capture(self.pg_interfaces)
3426         self.pg_start()
3427         capture = self.pg6.get_capture(1)
3428         p = capture[0]
3429         try:
3430             ip = p[IP]
3431             tcp = p[TCP]
3432             self.assertEqual(ip.src, self.pg1.remote_ip4)
3433             self.assertEqual(tcp.sport, external_port)
3434             self.assertEqual(ip.dst, self.pg6.remote_ip4)
3435             self.assertEqual(tcp.dport, 12345)
3436             self.assert_packet_checksums_valid(p)
3437         except:
3438             self.logger.error(ppp("Unexpected or invalid packet:", p))
3439             raise
3440
3441     def test_one_armed_nat44_static(self):
3442         """ NAT44ED One armed NAT and 1:1 NAPT asymmetrical rule """
3443
3444         remote_host = self.pg4.remote_hosts[0]
3445         local_host = self.pg4.remote_hosts[1]
3446         external_port = 80
3447         local_port = 8080
3448         eh_port_in = 0
3449
3450         self.vapi.nat44_forwarding_enable_disable(enable=1)
3451         self.nat_add_address(self.nat_addr, twice_nat=1)
3452         flags = (self.config_flags.NAT_IS_OUT2IN_ONLY |
3453                  self.config_flags.NAT_IS_TWICE_NAT)
3454         self.nat_add_static_mapping(local_host.ip4, self.nat_addr,
3455                                     local_port, external_port,
3456                                     proto=IP_PROTOS.tcp, flags=flags)
3457         flags = self.config_flags.NAT_IS_INSIDE
3458         self.vapi.nat44_interface_add_del_feature(
3459             sw_if_index=self.pg4.sw_if_index,
3460             is_add=1)
3461         self.vapi.nat44_interface_add_del_feature(
3462             sw_if_index=self.pg4.sw_if_index,
3463             flags=flags, is_add=1)
3464
3465         # from client to service
3466         p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
3467              IP(src=remote_host.ip4, dst=self.nat_addr) /
3468              TCP(sport=12345, dport=external_port))
3469         self.pg4.add_stream(p)
3470         self.pg_enable_capture(self.pg_interfaces)
3471         self.pg_start()
3472         capture = self.pg4.get_capture(1)
3473         p = capture[0]
3474         try:
3475             ip = p[IP]
3476             tcp = p[TCP]
3477             self.assertEqual(ip.dst, local_host.ip4)
3478             self.assertEqual(ip.src, self.nat_addr)
3479             self.assertEqual(tcp.dport, local_port)
3480             self.assertNotEqual(tcp.sport, 12345)
3481             eh_port_in = tcp.sport
3482             self.assert_packet_checksums_valid(p)
3483         except:
3484             self.logger.error(ppp("Unexpected or invalid packet:", p))
3485             raise
3486
3487         # from service back to client
3488         p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
3489              IP(src=local_host.ip4, dst=self.nat_addr) /
3490              TCP(sport=local_port, dport=eh_port_in))
3491         self.pg4.add_stream(p)
3492         self.pg_enable_capture(self.pg_interfaces)
3493         self.pg_start()
3494         capture = self.pg4.get_capture(1)
3495         p = capture[0]
3496         try:
3497             ip = p[IP]
3498             tcp = p[TCP]
3499             self.assertEqual(ip.src, self.nat_addr)
3500             self.assertEqual(ip.dst, remote_host.ip4)
3501             self.assertEqual(tcp.sport, external_port)
3502             self.assertEqual(tcp.dport, 12345)
3503             self.assert_packet_checksums_valid(p)
3504         except:
3505             self.logger.error(ppp("Unexpected or invalid packet:", p))
3506             raise
3507
3508
3509 if __name__ == '__main__':
3510     unittest.main(testRunner=VppTestRunner)