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