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