tests: re-enable the rest of NAT44ED tests for multiworker
[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 class TestNAT44ED(NAT44EDTestCase):
920     """ NAT44ED Test Case """
921
922     def test_users_dump(self):
923         """ NAT44ED API test - nat44_user_dump """
924
925         self.nat_add_address(self.nat_addr)
926         self.nat_add_inside_interface(self.pg0)
927         self.nat_add_outside_interface(self.pg1)
928
929         self.vapi.nat44_forwarding_enable_disable(enable=1)
930
931         local_ip = self.pg0.remote_ip4
932         external_ip = self.nat_addr
933         self.nat_add_static_mapping(local_ip, external_ip)
934
935         users = self.vapi.nat44_user_dump()
936         self.assertEqual(len(users), 0)
937
938         # in2out - static mapping match
939
940         pkts = self.create_stream_out(self.pg1)
941         self.pg1.add_stream(pkts)
942         self.pg_enable_capture(self.pg_interfaces)
943         self.pg_start()
944         capture = self.pg0.get_capture(len(pkts))
945         self.verify_capture_in(capture, self.pg0)
946
947         pkts = self.create_stream_in(self.pg0, self.pg1)
948         self.pg0.add_stream(pkts)
949         self.pg_enable_capture(self.pg_interfaces)
950         self.pg_start()
951         capture = self.pg1.get_capture(len(pkts))
952         self.verify_capture_out(capture, same_port=True)
953
954         users = self.vapi.nat44_user_dump()
955         self.assertEqual(len(users), 1)
956         static_user = users[0]
957         self.assertEqual(static_user.nstaticsessions, 3)
958         self.assertEqual(static_user.nsessions, 0)
959
960         # in2out - no static mapping match (forwarding test)
961
962         host0 = self.pg0.remote_hosts[0]
963         self.pg0.remote_hosts[0] = self.pg0.remote_hosts[1]
964         try:
965             pkts = self.create_stream_out(self.pg1,
966                                           dst_ip=self.pg0.remote_ip4,
967                                           use_inside_ports=True)
968             self.pg1.add_stream(pkts)
969             self.pg_enable_capture(self.pg_interfaces)
970             self.pg_start()
971             capture = self.pg0.get_capture(len(pkts))
972             self.verify_capture_in(capture, self.pg0)
973
974             pkts = self.create_stream_in(self.pg0, self.pg1)
975             self.pg0.add_stream(pkts)
976             self.pg_enable_capture(self.pg_interfaces)
977             self.pg_start()
978             capture = self.pg1.get_capture(len(pkts))
979             self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
980                                     same_port=True)
981         finally:
982             self.pg0.remote_hosts[0] = host0
983
984         users = self.vapi.nat44_user_dump()
985         self.assertEqual(len(users), 2)
986         if str(users[0].ip_address) == self.pg0.remote_hosts[0].ip4:
987             non_static_user = users[1]
988             static_user = users[0]
989         else:
990             non_static_user = users[0]
991             static_user = users[1]
992         self.assertEqual(static_user.nstaticsessions, 3)
993         self.assertEqual(static_user.nsessions, 0)
994         self.assertEqual(non_static_user.nstaticsessions, 0)
995         self.assertEqual(non_static_user.nsessions, 3)
996
997         users = self.vapi.nat44_user_dump()
998         self.assertEqual(len(users), 2)
999         if str(users[0].ip_address) == self.pg0.remote_hosts[0].ip4:
1000             non_static_user = users[1]
1001             static_user = users[0]
1002         else:
1003             non_static_user = users[0]
1004             static_user = users[1]
1005         self.assertEqual(static_user.nstaticsessions, 3)
1006         self.assertEqual(static_user.nsessions, 0)
1007         self.assertEqual(non_static_user.nstaticsessions, 0)
1008         self.assertEqual(non_static_user.nsessions, 3)
1009
1010     def test_frag_out_of_order_do_not_translate(self):
1011         """ NAT44ED don't translate fragments arriving out of order """
1012         self.nat_add_inside_interface(self.pg0)
1013         self.nat_add_outside_interface(self.pg1)
1014         self.vapi.nat44_forwarding_enable_disable(enable=True)
1015         self.frag_out_of_order(proto=IP_PROTOS.tcp, dont_translate=True)
1016
1017     def test_forwarding(self):
1018         """ NAT44ED forwarding test """
1019
1020         self.nat_add_inside_interface(self.pg0)
1021         self.nat_add_outside_interface(self.pg1)
1022         self.vapi.nat44_forwarding_enable_disable(enable=1)
1023
1024         real_ip = self.pg0.remote_ip4
1025         alias_ip = self.nat_addr
1026         flags = self.config_flags.NAT_IS_ADDR_ONLY
1027         self.vapi.nat44_add_del_static_mapping(is_add=1,
1028                                                local_ip_address=real_ip,
1029                                                external_ip_address=alias_ip,
1030                                                external_sw_if_index=0xFFFFFFFF,
1031                                                flags=flags)
1032
1033         try:
1034             # in2out - static mapping match
1035
1036             pkts = self.create_stream_out(self.pg1)
1037             self.pg1.add_stream(pkts)
1038             self.pg_enable_capture(self.pg_interfaces)
1039             self.pg_start()
1040             capture = self.pg0.get_capture(len(pkts))
1041             self.verify_capture_in(capture, self.pg0)
1042
1043             pkts = self.create_stream_in(self.pg0, self.pg1)
1044             self.pg0.add_stream(pkts)
1045             self.pg_enable_capture(self.pg_interfaces)
1046             self.pg_start()
1047             capture = self.pg1.get_capture(len(pkts))
1048             self.verify_capture_out(capture, same_port=True)
1049
1050             # in2out - no static mapping match
1051
1052             host0 = self.pg0.remote_hosts[0]
1053             self.pg0.remote_hosts[0] = self.pg0.remote_hosts[1]
1054             try:
1055                 pkts = self.create_stream_out(self.pg1,
1056                                               dst_ip=self.pg0.remote_ip4,
1057                                               use_inside_ports=True)
1058                 self.pg1.add_stream(pkts)
1059                 self.pg_enable_capture(self.pg_interfaces)
1060                 self.pg_start()
1061                 capture = self.pg0.get_capture(len(pkts))
1062                 self.verify_capture_in(capture, self.pg0)
1063
1064                 pkts = self.create_stream_in(self.pg0, self.pg1)
1065                 self.pg0.add_stream(pkts)
1066                 self.pg_enable_capture(self.pg_interfaces)
1067                 self.pg_start()
1068                 capture = self.pg1.get_capture(len(pkts))
1069                 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
1070                                         same_port=True)
1071             finally:
1072                 self.pg0.remote_hosts[0] = host0
1073
1074             user = self.pg0.remote_hosts[1]
1075             sessions = self.vapi.nat44_user_session_dump(user.ip4, 0)
1076             self.assertEqual(len(sessions), 3)
1077             self.assertTrue(sessions[0].flags &
1078                             self.config_flags.NAT_IS_EXT_HOST_VALID)
1079             self.vapi.nat44_del_session(
1080                 address=sessions[0].inside_ip_address,
1081                 port=sessions[0].inside_port,
1082                 protocol=sessions[0].protocol,
1083                 flags=(self.config_flags.NAT_IS_INSIDE |
1084                        self.config_flags.NAT_IS_EXT_HOST_VALID),
1085                 ext_host_address=sessions[0].ext_host_address,
1086                 ext_host_port=sessions[0].ext_host_port)
1087             sessions = self.vapi.nat44_user_session_dump(user.ip4, 0)
1088             self.assertEqual(len(sessions), 2)
1089
1090         finally:
1091             self.vapi.nat44_forwarding_enable_disable(enable=0)
1092             flags = self.config_flags.NAT_IS_ADDR_ONLY
1093             self.vapi.nat44_add_del_static_mapping(
1094                 is_add=0,
1095                 local_ip_address=real_ip,
1096                 external_ip_address=alias_ip,
1097                 external_sw_if_index=0xFFFFFFFF,
1098                 flags=flags)
1099
1100     def test_output_feature_and_service2(self):
1101         """ NAT44ED interface output feature and service host direct access """
1102         self.vapi.nat44_forwarding_enable_disable(enable=1)
1103         self.nat_add_address(self.nat_addr)
1104
1105         self.vapi.nat44_interface_add_del_output_feature(
1106             sw_if_index=self.pg1.sw_if_index, is_add=1,)
1107
1108         # session initiated from service host - translate
1109         pkts = self.create_stream_in(self.pg0, self.pg1)
1110         self.pg0.add_stream(pkts)
1111         self.pg_enable_capture(self.pg_interfaces)
1112         self.pg_start()
1113         capture = self.pg1.get_capture(len(pkts))
1114         self.verify_capture_out(capture, ignore_port=True)
1115
1116         pkts = self.create_stream_out(self.pg1)
1117         self.pg1.add_stream(pkts)
1118         self.pg_enable_capture(self.pg_interfaces)
1119         self.pg_start()
1120         capture = self.pg0.get_capture(len(pkts))
1121         self.verify_capture_in(capture, self.pg0)
1122
1123         # session initiated from remote host - do not translate
1124         tcp_port_in = self.tcp_port_in
1125         udp_port_in = self.udp_port_in
1126         icmp_id_in = self.icmp_id_in
1127
1128         self.tcp_port_in = 60303
1129         self.udp_port_in = 60304
1130         self.icmp_id_in = 60305
1131
1132         try:
1133             pkts = self.create_stream_out(self.pg1,
1134                                           self.pg0.remote_ip4,
1135                                           use_inside_ports=True)
1136             self.pg1.add_stream(pkts)
1137             self.pg_enable_capture(self.pg_interfaces)
1138             self.pg_start()
1139             capture = self.pg0.get_capture(len(pkts))
1140             self.verify_capture_in(capture, self.pg0)
1141
1142             pkts = self.create_stream_in(self.pg0, self.pg1)
1143             self.pg0.add_stream(pkts)
1144             self.pg_enable_capture(self.pg_interfaces)
1145             self.pg_start()
1146             capture = self.pg1.get_capture(len(pkts))
1147             self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
1148                                     same_port=True)
1149         finally:
1150             self.tcp_port_in = tcp_port_in
1151             self.udp_port_in = udp_port_in
1152             self.icmp_id_in = icmp_id_in
1153
1154     def test_twice_nat(self):
1155         """ NAT44ED Twice NAT """
1156         self.twice_nat_common()
1157
1158     def test_self_twice_nat_positive(self):
1159         """ NAT44ED Self Twice NAT (positive test) """
1160         self.twice_nat_common(self_twice_nat=True, same_pg=True)
1161
1162     def test_self_twice_nat_lb_positive(self):
1163         """ NAT44ED Self Twice NAT local service load balancing (positive test)
1164         """
1165         self.twice_nat_common(lb=True, self_twice_nat=True, same_pg=True,
1166                               client_id=1)
1167
1168     def test_twice_nat_lb(self):
1169         """ NAT44ED Twice NAT local service load balancing """
1170         self.twice_nat_common(lb=True)
1171
1172     def test_output_feature(self):
1173         """ NAT44ED interface output feature (in2out postrouting) """
1174         self.vapi.nat44_forwarding_enable_disable(enable=1)
1175         self.nat_add_address(self.nat_addr)
1176
1177         self.nat_add_outside_interface(self.pg0)
1178         self.vapi.nat44_interface_add_del_output_feature(
1179             sw_if_index=self.pg1.sw_if_index, is_add=1)
1180
1181         # in2out
1182         pkts = self.create_stream_in(self.pg0, self.pg1)
1183         self.pg0.add_stream(pkts)
1184         self.pg_enable_capture(self.pg_interfaces)
1185         self.pg_start()
1186         capture = self.pg1.get_capture(len(pkts))
1187         self.verify_capture_out(capture, ignore_port=True)
1188
1189         # out2in
1190         pkts = self.create_stream_out(self.pg1)
1191         self.pg1.add_stream(pkts)
1192         self.pg_enable_capture(self.pg_interfaces)
1193         self.pg_start()
1194         capture = self.pg0.get_capture(len(pkts))
1195         self.verify_capture_in(capture, self.pg0)
1196
1197     def test_static_with_port_out2(self):
1198         """ NAT44ED 1:1 NAPT asymmetrical rule """
1199
1200         external_port = 80
1201         local_port = 8080
1202
1203         self.vapi.nat44_forwarding_enable_disable(enable=1)
1204         flags = self.config_flags.NAT_IS_OUT2IN_ONLY
1205         self.nat_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1206                                     local_port, external_port,
1207                                     proto=IP_PROTOS.tcp, flags=flags)
1208
1209         self.nat_add_inside_interface(self.pg0)
1210         self.nat_add_outside_interface(self.pg1)
1211
1212         # from client to service
1213         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
1214              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
1215              TCP(sport=12345, dport=external_port))
1216         self.pg1.add_stream(p)
1217         self.pg_enable_capture(self.pg_interfaces)
1218         self.pg_start()
1219         capture = self.pg0.get_capture(1)
1220         p = capture[0]
1221         try:
1222             ip = p[IP]
1223             tcp = p[TCP]
1224             self.assertEqual(ip.dst, self.pg0.remote_ip4)
1225             self.assertEqual(tcp.dport, local_port)
1226             self.assert_packet_checksums_valid(p)
1227         except:
1228             self.logger.error(ppp("Unexpected or invalid packet:", p))
1229             raise
1230
1231         # ICMP error
1232         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1233              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
1234              ICMP(type=11) / capture[0][IP])
1235         self.pg0.add_stream(p)
1236         self.pg_enable_capture(self.pg_interfaces)
1237         self.pg_start()
1238         capture = self.pg1.get_capture(1)
1239         p = capture[0]
1240         try:
1241             self.assertEqual(p[IP].src, self.nat_addr)
1242             inner = p[IPerror]
1243             self.assertEqual(inner.dst, self.nat_addr)
1244             self.assertEqual(inner[TCPerror].dport, external_port)
1245         except:
1246             self.logger.error(ppp("Unexpected or invalid packet:", p))
1247             raise
1248
1249         # from service back to client
1250         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
1251              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
1252              TCP(sport=local_port, dport=12345))
1253         self.pg0.add_stream(p)
1254         self.pg_enable_capture(self.pg_interfaces)
1255         self.pg_start()
1256         capture = self.pg1.get_capture(1)
1257         p = capture[0]
1258         try:
1259             ip = p[IP]
1260             tcp = p[TCP]
1261             self.assertEqual(ip.src, self.nat_addr)
1262             self.assertEqual(tcp.sport, external_port)
1263             self.assert_packet_checksums_valid(p)
1264         except:
1265             self.logger.error(ppp("Unexpected or invalid packet:", p))
1266             raise
1267
1268         # ICMP error
1269         p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1270              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
1271              ICMP(type=11) / capture[0][IP])
1272         self.pg1.add_stream(p)
1273         self.pg_enable_capture(self.pg_interfaces)
1274         self.pg_start()
1275         capture = self.pg0.get_capture(1)
1276         p = capture[0]
1277         try:
1278             self.assertEqual(p[IP].dst, self.pg0.remote_ip4)
1279             inner = p[IPerror]
1280             self.assertEqual(inner.src, self.pg0.remote_ip4)
1281             self.assertEqual(inner[TCPerror].sport, local_port)
1282         except:
1283             self.logger.error(ppp("Unexpected or invalid packet:", p))
1284             raise
1285
1286         # from client to server (no translation)
1287         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
1288              IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
1289              TCP(sport=12346, dport=local_port))
1290         self.pg1.add_stream(p)
1291         self.pg_enable_capture(self.pg_interfaces)
1292         self.pg_start()
1293         capture = self.pg0.get_capture(1)
1294         p = capture[0]
1295         try:
1296             ip = p[IP]
1297             tcp = p[TCP]
1298             self.assertEqual(ip.dst, self.pg0.remote_ip4)
1299             self.assertEqual(tcp.dport, local_port)
1300             self.assert_packet_checksums_valid(p)
1301         except:
1302             self.logger.error(ppp("Unexpected or invalid packet:", p))
1303             raise
1304
1305         # from service back to client (no translation)
1306         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
1307              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
1308              TCP(sport=local_port, dport=12346))
1309         self.pg0.add_stream(p)
1310         self.pg_enable_capture(self.pg_interfaces)
1311         self.pg_start()
1312         capture = self.pg1.get_capture(1)
1313         p = capture[0]
1314         try:
1315             ip = p[IP]
1316             tcp = p[TCP]
1317             self.assertEqual(ip.src, self.pg0.remote_ip4)
1318             self.assertEqual(tcp.sport, local_port)
1319             self.assert_packet_checksums_valid(p)
1320         except:
1321             self.logger.error(ppp("Unexpected or invalid packet:", p))
1322             raise
1323
1324     def test_static_lb(self):
1325         """ NAT44ED local service load balancing """
1326         external_addr_n = self.nat_addr
1327         external_port = 80
1328         local_port = 8080
1329         server1 = self.pg0.remote_hosts[0]
1330         server2 = self.pg0.remote_hosts[1]
1331
1332         locals = [{'addr': server1.ip4,
1333                    'port': local_port,
1334                    'probability': 70,
1335                    'vrf_id': 0},
1336                   {'addr': server2.ip4,
1337                    'port': local_port,
1338                    'probability': 30,
1339                    'vrf_id': 0}]
1340
1341         self.nat_add_address(self.nat_addr)
1342         self.vapi.nat44_add_del_lb_static_mapping(
1343             is_add=1,
1344             external_addr=external_addr_n,
1345             external_port=external_port,
1346             protocol=IP_PROTOS.tcp,
1347             local_num=len(locals),
1348             locals=locals)
1349         flags = self.config_flags.NAT_IS_INSIDE
1350         self.vapi.nat44_interface_add_del_feature(
1351             sw_if_index=self.pg0.sw_if_index,
1352             flags=flags, is_add=1)
1353         self.vapi.nat44_interface_add_del_feature(
1354             sw_if_index=self.pg1.sw_if_index,
1355             is_add=1)
1356
1357         # from client to service
1358         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
1359              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
1360              TCP(sport=12345, dport=external_port))
1361         self.pg1.add_stream(p)
1362         self.pg_enable_capture(self.pg_interfaces)
1363         self.pg_start()
1364         capture = self.pg0.get_capture(1)
1365         p = capture[0]
1366         server = None
1367         try:
1368             ip = p[IP]
1369             tcp = p[TCP]
1370             self.assertIn(ip.dst, [server1.ip4, server2.ip4])
1371             if ip.dst == server1.ip4:
1372                 server = server1
1373             else:
1374                 server = server2
1375             self.assertEqual(tcp.dport, local_port)
1376             self.assert_packet_checksums_valid(p)
1377         except:
1378             self.logger.error(ppp("Unexpected or invalid packet:", p))
1379             raise
1380
1381         # from service back to client
1382         p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
1383              IP(src=server.ip4, dst=self.pg1.remote_ip4) /
1384              TCP(sport=local_port, dport=12345))
1385         self.pg0.add_stream(p)
1386         self.pg_enable_capture(self.pg_interfaces)
1387         self.pg_start()
1388         capture = self.pg1.get_capture(1)
1389         p = capture[0]
1390         try:
1391             ip = p[IP]
1392             tcp = p[TCP]
1393             self.assertEqual(ip.src, self.nat_addr)
1394             self.assertEqual(tcp.sport, external_port)
1395             self.assert_packet_checksums_valid(p)
1396         except:
1397             self.logger.error(ppp("Unexpected or invalid packet:", p))
1398             raise
1399
1400         sessions = self.vapi.nat44_user_session_dump(server.ip4, 0)
1401         self.assertEqual(len(sessions), 1)
1402         self.assertTrue(sessions[0].flags &
1403                         self.config_flags.NAT_IS_EXT_HOST_VALID)
1404         self.vapi.nat44_del_session(
1405             address=sessions[0].inside_ip_address,
1406             port=sessions[0].inside_port,
1407             protocol=sessions[0].protocol,
1408             flags=(self.config_flags.NAT_IS_INSIDE |
1409                    self.config_flags.NAT_IS_EXT_HOST_VALID),
1410             ext_host_address=sessions[0].ext_host_address,
1411             ext_host_port=sessions[0].ext_host_port)
1412         sessions = self.vapi.nat44_user_session_dump(server.ip4, 0)
1413         self.assertEqual(len(sessions), 0)
1414
1415     def test_static_lb_2(self):
1416         """ NAT44ED local service load balancing (asymmetrical rule) """
1417         external_addr = self.nat_addr
1418         external_port = 80
1419         local_port = 8080
1420         server1 = self.pg0.remote_hosts[0]
1421         server2 = self.pg0.remote_hosts[1]
1422
1423         locals = [{'addr': server1.ip4,
1424                    'port': local_port,
1425                    'probability': 70,
1426                    'vrf_id': 0},
1427                   {'addr': server2.ip4,
1428                    'port': local_port,
1429                    'probability': 30,
1430                    'vrf_id': 0}]
1431
1432         self.vapi.nat44_forwarding_enable_disable(enable=1)
1433         flags = self.config_flags.NAT_IS_OUT2IN_ONLY
1434         self.vapi.nat44_add_del_lb_static_mapping(is_add=1, flags=flags,
1435                                                   external_addr=external_addr,
1436                                                   external_port=external_port,
1437                                                   protocol=IP_PROTOS.tcp,
1438                                                   local_num=len(locals),
1439                                                   locals=locals)
1440         flags = self.config_flags.NAT_IS_INSIDE
1441         self.vapi.nat44_interface_add_del_feature(
1442             sw_if_index=self.pg0.sw_if_index,
1443             flags=flags, is_add=1)
1444         self.vapi.nat44_interface_add_del_feature(
1445             sw_if_index=self.pg1.sw_if_index,
1446             is_add=1)
1447
1448         # from client to service
1449         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
1450              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
1451              TCP(sport=12345, dport=external_port))
1452         self.pg1.add_stream(p)
1453         self.pg_enable_capture(self.pg_interfaces)
1454         self.pg_start()
1455         capture = self.pg0.get_capture(1)
1456         p = capture[0]
1457         server = None
1458         try:
1459             ip = p[IP]
1460             tcp = p[TCP]
1461             self.assertIn(ip.dst, [server1.ip4, server2.ip4])
1462             if ip.dst == server1.ip4:
1463                 server = server1
1464             else:
1465                 server = server2
1466             self.assertEqual(tcp.dport, local_port)
1467             self.assert_packet_checksums_valid(p)
1468         except:
1469             self.logger.error(ppp("Unexpected or invalid packet:", p))
1470             raise
1471
1472         # from service back to client
1473         p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
1474              IP(src=server.ip4, dst=self.pg1.remote_ip4) /
1475              TCP(sport=local_port, dport=12345))
1476         self.pg0.add_stream(p)
1477         self.pg_enable_capture(self.pg_interfaces)
1478         self.pg_start()
1479         capture = self.pg1.get_capture(1)
1480         p = capture[0]
1481         try:
1482             ip = p[IP]
1483             tcp = p[TCP]
1484             self.assertEqual(ip.src, self.nat_addr)
1485             self.assertEqual(tcp.sport, external_port)
1486             self.assert_packet_checksums_valid(p)
1487         except:
1488             self.logger.error(ppp("Unexpected or invalid packet:", p))
1489             raise
1490
1491         # from client to server (no translation)
1492         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
1493              IP(src=self.pg1.remote_ip4, dst=server1.ip4) /
1494              TCP(sport=12346, dport=local_port))
1495         self.pg1.add_stream(p)
1496         self.pg_enable_capture(self.pg_interfaces)
1497         self.pg_start()
1498         capture = self.pg0.get_capture(1)
1499         p = capture[0]
1500         server = None
1501         try:
1502             ip = p[IP]
1503             tcp = p[TCP]
1504             self.assertEqual(ip.dst, server1.ip4)
1505             self.assertEqual(tcp.dport, local_port)
1506             self.assert_packet_checksums_valid(p)
1507         except:
1508             self.logger.error(ppp("Unexpected or invalid packet:", p))
1509             raise
1510
1511         # from service back to client (no translation)
1512         p = (Ether(src=server1.mac, dst=self.pg0.local_mac) /
1513              IP(src=server1.ip4, dst=self.pg1.remote_ip4) /
1514              TCP(sport=local_port, dport=12346))
1515         self.pg0.add_stream(p)
1516         self.pg_enable_capture(self.pg_interfaces)
1517         self.pg_start()
1518         capture = self.pg1.get_capture(1)
1519         p = capture[0]
1520         try:
1521             ip = p[IP]
1522             tcp = p[TCP]
1523             self.assertEqual(ip.src, server1.ip4)
1524             self.assertEqual(tcp.sport, local_port)
1525             self.assert_packet_checksums_valid(p)
1526         except:
1527             self.logger.error(ppp("Unexpected or invalid packet:", p))
1528             raise
1529
1530     def test_lb_affinity(self):
1531         """ NAT44ED local service load balancing affinity """
1532         external_addr = self.nat_addr
1533         external_port = 80
1534         local_port = 8080
1535         server1 = self.pg0.remote_hosts[0]
1536         server2 = self.pg0.remote_hosts[1]
1537
1538         locals = [{'addr': server1.ip4,
1539                    'port': local_port,
1540                    'probability': 50,
1541                    'vrf_id': 0},
1542                   {'addr': server2.ip4,
1543                    'port': local_port,
1544                    'probability': 50,
1545                    'vrf_id': 0}]
1546
1547         self.nat_add_address(self.nat_addr)
1548         self.vapi.nat44_add_del_lb_static_mapping(is_add=1,
1549                                                   external_addr=external_addr,
1550                                                   external_port=external_port,
1551                                                   protocol=IP_PROTOS.tcp,
1552                                                   affinity=10800,
1553                                                   local_num=len(locals),
1554                                                   locals=locals)
1555         flags = self.config_flags.NAT_IS_INSIDE
1556         self.vapi.nat44_interface_add_del_feature(
1557             sw_if_index=self.pg0.sw_if_index,
1558             flags=flags, is_add=1)
1559         self.vapi.nat44_interface_add_del_feature(
1560             sw_if_index=self.pg1.sw_if_index,
1561             is_add=1)
1562
1563         p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1564              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
1565              TCP(sport=1025, dport=external_port))
1566         self.pg1.add_stream(p)
1567         self.pg_enable_capture(self.pg_interfaces)
1568         self.pg_start()
1569         capture = self.pg0.get_capture(1)
1570         backend = capture[0][IP].dst
1571
1572         sessions = self.vapi.nat44_user_session_dump(backend, 0)
1573         self.assertEqual(len(sessions), 1)
1574         self.assertTrue(sessions[0].flags &
1575                         self.config_flags.NAT_IS_EXT_HOST_VALID)
1576         self.vapi.nat44_del_session(
1577             address=sessions[0].inside_ip_address,
1578             port=sessions[0].inside_port,
1579             protocol=sessions[0].protocol,
1580             flags=(self.config_flags.NAT_IS_INSIDE |
1581                    self.config_flags.NAT_IS_EXT_HOST_VALID),
1582             ext_host_address=sessions[0].ext_host_address,
1583             ext_host_port=sessions[0].ext_host_port)
1584
1585         pkts = []
1586         for port in range(1030, 1100):
1587             p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1588                  IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
1589                  TCP(sport=port, dport=external_port))
1590             pkts.append(p)
1591         self.pg1.add_stream(pkts)
1592         self.pg_enable_capture(self.pg_interfaces)
1593         self.pg_start()
1594         capture = self.pg0.get_capture(len(pkts))
1595         for p in capture:
1596             self.assertEqual(p[IP].dst, backend)
1597
1598     def test_multiple_vrf(self):
1599         """ NAT44ED Multiple VRF setup """
1600
1601         external_addr = '1.2.3.4'
1602         external_port = 80
1603         local_port = 8080
1604         port = 0
1605
1606         self.vapi.nat44_forwarding_enable_disable(enable=1)
1607         self.nat_add_address(self.nat_addr)
1608         flags = self.config_flags.NAT_IS_INSIDE
1609         self.vapi.nat44_interface_add_del_feature(
1610             sw_if_index=self.pg0.sw_if_index,
1611             is_add=1)
1612         self.vapi.nat44_interface_add_del_feature(
1613             sw_if_index=self.pg0.sw_if_index,
1614             is_add=1, flags=flags)
1615         self.vapi.nat44_interface_add_del_output_feature(
1616             sw_if_index=self.pg1.sw_if_index,
1617             is_add=1)
1618         self.vapi.nat44_interface_add_del_feature(
1619             sw_if_index=self.pg5.sw_if_index,
1620             is_add=1)
1621         self.vapi.nat44_interface_add_del_feature(
1622             sw_if_index=self.pg5.sw_if_index,
1623             is_add=1, flags=flags)
1624         self.vapi.nat44_interface_add_del_feature(
1625             sw_if_index=self.pg6.sw_if_index,
1626             is_add=1)
1627         flags = self.config_flags.NAT_IS_OUT2IN_ONLY
1628         self.nat_add_static_mapping(self.pg5.remote_ip4, external_addr,
1629                                     local_port, external_port, vrf_id=1,
1630                                     proto=IP_PROTOS.tcp, flags=flags)
1631         self.nat_add_static_mapping(
1632             self.pg0.remote_ip4,
1633             external_sw_if_index=self.pg0.sw_if_index,
1634             local_port=local_port,
1635             vrf_id=0,
1636             external_port=external_port,
1637             proto=IP_PROTOS.tcp,
1638             flags=flags
1639         )
1640
1641         # from client to service (both VRF1)
1642         p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
1643              IP(src=self.pg6.remote_ip4, dst=external_addr) /
1644              TCP(sport=12345, dport=external_port))
1645         self.pg6.add_stream(p)
1646         self.pg_enable_capture(self.pg_interfaces)
1647         self.pg_start()
1648         capture = self.pg5.get_capture(1)
1649         p = capture[0]
1650         try:
1651             ip = p[IP]
1652             tcp = p[TCP]
1653             self.assertEqual(ip.dst, self.pg5.remote_ip4)
1654             self.assertEqual(tcp.dport, local_port)
1655             self.assert_packet_checksums_valid(p)
1656         except:
1657             self.logger.error(ppp("Unexpected or invalid packet:", p))
1658             raise
1659
1660         # from service back to client (both VRF1)
1661         p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
1662              IP(src=self.pg5.remote_ip4, dst=self.pg6.remote_ip4) /
1663              TCP(sport=local_port, dport=12345))
1664         self.pg5.add_stream(p)
1665         self.pg_enable_capture(self.pg_interfaces)
1666         self.pg_start()
1667         capture = self.pg6.get_capture(1)
1668         p = capture[0]
1669         try:
1670             ip = p[IP]
1671             tcp = p[TCP]
1672             self.assertEqual(ip.src, external_addr)
1673             self.assertEqual(tcp.sport, external_port)
1674             self.assert_packet_checksums_valid(p)
1675         except:
1676             self.logger.error(ppp("Unexpected or invalid packet:", p))
1677             raise
1678
1679         # dynamic NAT from VRF1 to VRF0 (output-feature)
1680         p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
1681              IP(src=self.pg5.remote_ip4, dst=self.pg1.remote_ip4) /
1682              TCP(sport=2345, dport=22))
1683         self.pg5.add_stream(p)
1684         self.pg_enable_capture(self.pg_interfaces)
1685         self.pg_start()
1686         capture = self.pg1.get_capture(1)
1687         p = capture[0]
1688         try:
1689             ip = p[IP]
1690             tcp = p[TCP]
1691             self.assertEqual(ip.src, self.nat_addr)
1692             self.assert_packet_checksums_valid(p)
1693             port = tcp.sport
1694         except:
1695             self.logger.error(ppp("Unexpected or invalid packet:", p))
1696             raise
1697
1698         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
1699              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
1700              TCP(sport=22, dport=port))
1701         self.pg1.add_stream(p)
1702         self.pg_enable_capture(self.pg_interfaces)
1703         self.pg_start()
1704         capture = self.pg5.get_capture(1)
1705         p = capture[0]
1706         try:
1707             ip = p[IP]
1708             tcp = p[TCP]
1709             self.assertEqual(ip.dst, self.pg5.remote_ip4)
1710             self.assertEqual(tcp.dport, 2345)
1711             self.assert_packet_checksums_valid(p)
1712         except:
1713             self.logger.error(ppp("Unexpected or invalid packet:", p))
1714             raise
1715
1716         # from client VRF1 to service VRF0
1717         p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
1718              IP(src=self.pg6.remote_ip4, dst=self.pg0.local_ip4) /
1719              TCP(sport=12346, dport=external_port))
1720         self.pg6.add_stream(p)
1721         self.pg_enable_capture(self.pg_interfaces)
1722         self.pg_start()
1723         capture = self.pg0.get_capture(1)
1724         p = capture[0]
1725         try:
1726             ip = p[IP]
1727             tcp = p[TCP]
1728             self.assertEqual(ip.dst, self.pg0.remote_ip4)
1729             self.assertEqual(tcp.dport, local_port)
1730             self.assert_packet_checksums_valid(p)
1731         except:
1732             self.logger.error(ppp("Unexpected or invalid packet:", p))
1733             raise
1734
1735         # from service VRF0 back to client VRF1
1736         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
1737              IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
1738              TCP(sport=local_port, dport=12346))
1739         self.pg0.add_stream(p)
1740         self.pg_enable_capture(self.pg_interfaces)
1741         self.pg_start()
1742         capture = self.pg6.get_capture(1)
1743         p = capture[0]
1744         try:
1745             ip = p[IP]
1746             tcp = p[TCP]
1747             self.assertEqual(ip.src, self.pg0.local_ip4)
1748             self.assertEqual(tcp.sport, external_port)
1749             self.assert_packet_checksums_valid(p)
1750         except:
1751             self.logger.error(ppp("Unexpected or invalid packet:", p))
1752             raise
1753
1754         # from client VRF0 to service VRF1
1755         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
1756              IP(src=self.pg0.remote_ip4, dst=external_addr) /
1757              TCP(sport=12347, dport=external_port))
1758         self.pg0.add_stream(p)
1759         self.pg_enable_capture(self.pg_interfaces)
1760         self.pg_start()
1761         capture = self.pg5.get_capture(1)
1762         p = capture[0]
1763         try:
1764             ip = p[IP]
1765             tcp = p[TCP]
1766             self.assertEqual(ip.dst, self.pg5.remote_ip4)
1767             self.assertEqual(tcp.dport, local_port)
1768             self.assert_packet_checksums_valid(p)
1769         except:
1770             self.logger.error(ppp("Unexpected or invalid packet:", p))
1771             raise
1772
1773         # from service VRF1 back to client VRF0
1774         p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
1775              IP(src=self.pg5.remote_ip4, dst=self.pg0.remote_ip4) /
1776              TCP(sport=local_port, dport=12347))
1777         self.pg5.add_stream(p)
1778         self.pg_enable_capture(self.pg_interfaces)
1779         self.pg_start()
1780         capture = self.pg0.get_capture(1)
1781         p = capture[0]
1782         try:
1783             ip = p[IP]
1784             tcp = p[TCP]
1785             self.assertEqual(ip.src, external_addr)
1786             self.assertEqual(tcp.sport, external_port)
1787             self.assert_packet_checksums_valid(p)
1788         except:
1789             self.logger.error(ppp("Unexpected or invalid packet:", p))
1790             raise
1791
1792         # from client to server (both VRF1, no translation)
1793         p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
1794              IP(src=self.pg6.remote_ip4, dst=self.pg5.remote_ip4) /
1795              TCP(sport=12348, dport=local_port))
1796         self.pg6.add_stream(p)
1797         self.pg_enable_capture(self.pg_interfaces)
1798         self.pg_start()
1799         capture = self.pg5.get_capture(1)
1800         p = capture[0]
1801         try:
1802             ip = p[IP]
1803             tcp = p[TCP]
1804             self.assertEqual(ip.dst, self.pg5.remote_ip4)
1805             self.assertEqual(tcp.dport, local_port)
1806             self.assert_packet_checksums_valid(p)
1807         except:
1808             self.logger.error(ppp("Unexpected or invalid packet:", p))
1809             raise
1810
1811         # from server back to client (both VRF1, no translation)
1812         p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
1813              IP(src=self.pg5.remote_ip4, dst=self.pg6.remote_ip4) /
1814              TCP(sport=local_port, dport=12348))
1815         self.pg5.add_stream(p)
1816         self.pg_enable_capture(self.pg_interfaces)
1817         self.pg_start()
1818         capture = self.pg6.get_capture(1)
1819         p = capture[0]
1820         try:
1821             ip = p[IP]
1822             tcp = p[TCP]
1823             self.assertEqual(ip.src, self.pg5.remote_ip4)
1824             self.assertEqual(tcp.sport, local_port)
1825             self.assert_packet_checksums_valid(p)
1826         except:
1827             self.logger.error(ppp("Unexpected or invalid packet:", p))
1828             raise
1829
1830         # from client VRF1 to server VRF0 (no translation)
1831         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
1832              IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
1833              TCP(sport=local_port, dport=12349))
1834         self.pg0.add_stream(p)
1835         self.pg_enable_capture(self.pg_interfaces)
1836         self.pg_start()
1837         capture = self.pg6.get_capture(1)
1838         p = capture[0]
1839         try:
1840             ip = p[IP]
1841             tcp = p[TCP]
1842             self.assertEqual(ip.src, self.pg0.remote_ip4)
1843             self.assertEqual(tcp.sport, local_port)
1844             self.assert_packet_checksums_valid(p)
1845         except:
1846             self.logger.error(ppp("Unexpected or invalid packet:", p))
1847             raise
1848
1849         # from server VRF0 back to client VRF1 (no translation)
1850         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
1851              IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
1852              TCP(sport=local_port, dport=12349))
1853         self.pg0.add_stream(p)
1854         self.pg_enable_capture(self.pg_interfaces)
1855         self.pg_start()
1856         capture = self.pg6.get_capture(1)
1857         p = capture[0]
1858         try:
1859             ip = p[IP]
1860             tcp = p[TCP]
1861             self.assertEqual(ip.src, self.pg0.remote_ip4)
1862             self.assertEqual(tcp.sport, local_port)
1863             self.assert_packet_checksums_valid(p)
1864         except:
1865             self.logger.error(ppp("Unexpected or invalid packet:", p))
1866             raise
1867
1868         # from client VRF0 to server VRF1 (no translation)
1869         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
1870              IP(src=self.pg0.remote_ip4, dst=self.pg5.remote_ip4) /
1871              TCP(sport=12344, dport=local_port))
1872         self.pg0.add_stream(p)
1873         self.pg_enable_capture(self.pg_interfaces)
1874         self.pg_start()
1875         capture = self.pg5.get_capture(1)
1876         p = capture[0]
1877         try:
1878             ip = p[IP]
1879             tcp = p[TCP]
1880             self.assertEqual(ip.dst, self.pg5.remote_ip4)
1881             self.assertEqual(tcp.dport, local_port)
1882             self.assert_packet_checksums_valid(p)
1883         except:
1884             self.logger.error(ppp("Unexpected or invalid packet:", p))
1885             raise
1886
1887         # from server VRF1 back to client VRF0 (no translation)
1888         p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
1889              IP(src=self.pg5.remote_ip4, dst=self.pg0.remote_ip4) /
1890              TCP(sport=local_port, dport=12344))
1891         self.pg5.add_stream(p)
1892         self.pg_enable_capture(self.pg_interfaces)
1893         self.pg_start()
1894         capture = self.pg0.get_capture(1)
1895         p = capture[0]
1896         try:
1897             ip = p[IP]
1898             tcp = p[TCP]
1899             self.assertEqual(ip.src, self.pg5.remote_ip4)
1900             self.assertEqual(tcp.sport, local_port)
1901             self.assert_packet_checksums_valid(p)
1902         except:
1903             self.logger.error(ppp("Unexpected or invalid packet:", p))
1904             raise
1905
1906     def test_outside_address_distribution(self):
1907         """ Outside address distribution based on source address """
1908
1909         x = 100
1910         nat_addresses = []
1911
1912         for i in range(1, x):
1913             a = "10.0.0.%d" % i
1914             nat_addresses.append(a)
1915
1916         self.nat_add_inside_interface(self.pg0)
1917         self.nat_add_outside_interface(self.pg1)
1918
1919         self.vapi.nat44_add_del_address_range(
1920             first_ip_address=nat_addresses[0],
1921             last_ip_address=nat_addresses[-1],
1922             vrf_id=0xFFFFFFFF, is_add=1, flags=0)
1923
1924         self.pg0.generate_remote_hosts(x)
1925
1926         pkts = []
1927         for i in range(x):
1928             info = self.create_packet_info(self.pg0, self.pg1)
1929             payload = self.info_to_payload(info)
1930             p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1931                  IP(src=self.pg0.remote_hosts[i].ip4,
1932                      dst=self.pg1.remote_ip4) /
1933                  UDP(sport=7000+i, dport=8000+i) /
1934                  Raw(payload))
1935             info.data = p
1936             pkts.append(p)
1937
1938         self.pg0.add_stream(pkts)
1939         self.pg_enable_capture(self.pg_interfaces)
1940         self.pg_start()
1941         recvd = self.pg1.get_capture(len(pkts))
1942         for p_recvd in recvd:
1943             payload_info = self.payload_to_info(p_recvd[Raw])
1944             packet_index = payload_info.index
1945             info = self._packet_infos[packet_index]
1946             self.assertTrue(info is not None)
1947             self.assertEqual(packet_index, info.index)
1948             p_sent = info.data
1949             packed = socket.inet_aton(p_sent[IP].src)
1950             numeric = struct.unpack("!L", packed)[0]
1951             numeric = socket.htonl(numeric)
1952             a = nat_addresses[(numeric-1) % len(nat_addresses)]
1953             self.assertEqual(
1954                 a, p_recvd[IP].src,
1955                 "Invalid packet (src IP %s translated to %s, but expected %s)"
1956                 % (p_sent[IP].src, p_recvd[IP].src, a))
1957
1958
1959 class TestNAT44EDMW(TestNAT44ED):
1960     """ NAT44ED MW Test Case """
1961     worker_config = "workers 1"
1962
1963     def get_stats_counter(self, path, worker=1):
1964         return super(TestNAT44EDMW, self).get_stats_counter(path, worker)
1965
1966     @unittest.skip('MW fix required')
1967     def test_users_dump(self):
1968         """ NAT44ED API test - nat44_user_dump """
1969
1970     @unittest.skip('MW fix required')
1971     def test_frag_out_of_order_do_not_translate(self):
1972         """ NAT44ED don't translate fragments arriving out of order """
1973
1974     @unittest.skip('MW fix required')
1975     def test_forwarding(self):
1976         """ NAT44ED forwarding test """
1977
1978     @unittest.skip('MW fix required')
1979     def test_twice_nat(self):
1980         """ NAT44ED Twice NAT """
1981
1982     @unittest.skip('MW fix required')
1983     def test_twice_nat_lb(self):
1984         """ NAT44ED Twice NAT local service load balancing """
1985
1986     @unittest.skip('MW fix required')
1987     def test_output_feature(self):
1988         """ NAT44ED interface output feature (in2out postrouting) """
1989
1990     @unittest.skip('MW fix required')
1991     def test_static_with_port_out2(self):
1992         """ NAT44ED 1:1 NAPT asymmetrical rule """
1993
1994     @unittest.skip('MW fix required')
1995     def test_output_feature_and_service2(self):
1996         """ NAT44ED interface output feature and service host direct access """
1997
1998     @unittest.skip('MW fix required')
1999     def test_static_lb(self):
2000         """ NAT44ED local service load balancing """
2001
2002     @unittest.skip('MW fix required')
2003     def test_static_lb_2(self):
2004         """ NAT44ED local service load balancing (asymmetrical rule) """
2005
2006     @unittest.skip('MW fix required')
2007     def test_lb_affinity(self):
2008         """ NAT44ED local service load balancing affinity """
2009
2010     @unittest.skip('MW fix required')
2011     def test_multiple_vrf(self):
2012         """ NAT44ED Multiple VRF setup """
2013
2014     @unittest.skip('MW fix required')
2015     def test_self_twice_nat_positive(self):
2016         """ NAT44ED Self Twice NAT (positive test) """
2017
2018     @unittest.skip('MW fix required')
2019     def test_self_twice_nat_lb_positive(self):
2020         """ NAT44ED Self Twice NAT local service load balancing (positive test)
2021         """
2022
2023     def test_dynamic(self):
2024         """ NAT44ED dynamic translation test """
2025
2026         self.nat_add_address(self.nat_addr)
2027         self.nat_add_inside_interface(self.pg0)
2028         self.nat_add_outside_interface(self.pg1)
2029
2030         # in2out
2031         tc1 = self.get_stats_counter('/nat44-ed/in2out/slowpath/tcp')
2032         uc1 = self.get_stats_counter('/nat44-ed/in2out/slowpath/udp')
2033         ic1 = self.get_stats_counter('/nat44-ed/in2out/slowpath/icmp')
2034         dc1 = self.get_stats_counter('/nat44-ed/in2out/slowpath/drops')
2035
2036         pkts = self.create_stream_in(self.pg0, self.pg1)
2037         # TODO: specify worker=idx, also stats have to
2038         #       know from which worker to take capture
2039         self.pg0.add_stream(pkts)
2040         self.pg_enable_capture(self.pg_interfaces)
2041         self.pg_start()
2042         capture = self.pg1.get_capture(len(pkts))
2043         self.verify_capture_out(capture, ignore_port=True)
2044
2045         if_idx = self.pg0.sw_if_index
2046         tc2 = self.get_stats_counter('/nat44-ed/in2out/slowpath/tcp')
2047         uc2 = self.get_stats_counter('/nat44-ed/in2out/slowpath/udp')
2048         ic2 = self.get_stats_counter('/nat44-ed/in2out/slowpath/icmp')
2049         dc2 = self.get_stats_counter('/nat44-ed/in2out/slowpath/drops')
2050
2051         self.assertEqual(tc2[if_idx] - tc1[if_idx], 2)
2052         self.assertEqual(uc2[if_idx] - uc1[if_idx], 1)
2053         self.assertEqual(ic2[if_idx] - ic1[if_idx], 1)
2054         self.assertEqual(dc2[if_idx] - dc1[if_idx], 0)
2055
2056         # out2in
2057         tc1 = self.get_stats_counter('/nat44-ed/out2in/fastpath/tcp')
2058         uc1 = self.get_stats_counter('/nat44-ed/out2in/fastpath/udp')
2059         ic1 = self.get_stats_counter('/nat44-ed/out2in/fastpath/icmp')
2060         dc1 = self.get_stats_counter('/nat44-ed/out2in/fastpath/drops')
2061
2062         pkts = self.create_stream_out(self.pg1)
2063         self.pg1.add_stream(pkts)
2064         self.pg_enable_capture(self.pg_interfaces)
2065         self.pg_start()
2066         capture = self.pg0.get_capture(len(pkts))
2067         self.verify_capture_in(capture, self.pg0)
2068
2069         if_idx = self.pg1.sw_if_index
2070         tc2 = self.get_stats_counter('/nat44-ed/out2in/fastpath/tcp')
2071         uc2 = self.get_stats_counter('/nat44-ed/out2in/fastpath/udp')
2072         ic2 = self.get_stats_counter('/nat44-ed/out2in/fastpath/icmp')
2073         dc2 = self.get_stats_counter('/nat44-ed/out2in/fastpath/drops')
2074
2075         self.assertEqual(tc2[if_idx] - tc1[if_idx], 2)
2076         self.assertEqual(uc2[if_idx] - uc1[if_idx], 1)
2077         self.assertEqual(ic2[if_idx] - ic1[if_idx], 1)
2078         self.assertEqual(dc2[if_idx] - dc1[if_idx], 0)
2079
2080         sc = self.get_stats_counter('/nat44-ed/total-sessions')
2081         self.assertEqual(sc[0], 3)
2082
2083     def test_frag_in_order(self):
2084         """ NAT44ED translate fragments arriving in order """
2085
2086         self.nat_add_address(self.nat_addr)
2087         self.nat_add_inside_interface(self.pg0)
2088         self.nat_add_outside_interface(self.pg1)
2089
2090         self.frag_in_order(proto=IP_PROTOS.tcp, ignore_port=True)
2091         self.frag_in_order(proto=IP_PROTOS.udp, ignore_port=True)
2092         self.frag_in_order(proto=IP_PROTOS.icmp, ignore_port=True)
2093
2094     def test_frag_in_order_do_not_translate(self):
2095         """ NAT44ED don't translate fragments arriving in order """
2096
2097         self.nat_add_address(self.nat_addr)
2098         self.nat_add_inside_interface(self.pg0)
2099         self.nat_add_outside_interface(self.pg1)
2100         self.vapi.nat44_forwarding_enable_disable(enable=True)
2101
2102         self.frag_in_order(proto=IP_PROTOS.tcp, dont_translate=True)
2103
2104     def test_frag_out_of_order(self):
2105         """ NAT44ED translate fragments arriving out of order """
2106
2107         self.nat_add_address(self.nat_addr)
2108         self.nat_add_inside_interface(self.pg0)
2109         self.nat_add_outside_interface(self.pg1)
2110
2111         self.frag_out_of_order(proto=IP_PROTOS.tcp, ignore_port=True)
2112         self.frag_out_of_order(proto=IP_PROTOS.udp, ignore_port=True)
2113         self.frag_out_of_order(proto=IP_PROTOS.icmp, ignore_port=True)
2114
2115     def test_frag_in_order_in_plus_out(self):
2116         """ NAT44ED in+out interface fragments in order """
2117
2118         in_port = self.random_port()
2119         out_port = self.random_port()
2120
2121         self.nat_add_address(self.nat_addr)
2122         self.nat_add_inside_interface(self.pg0)
2123         self.nat_add_outside_interface(self.pg0)
2124         self.nat_add_inside_interface(self.pg1)
2125         self.nat_add_outside_interface(self.pg1)
2126
2127         # add static mappings for server
2128         self.nat_add_static_mapping(self.server_addr,
2129                                     self.nat_addr,
2130                                     in_port,
2131                                     out_port,
2132                                     proto=IP_PROTOS.tcp)
2133         self.nat_add_static_mapping(self.server_addr,
2134                                     self.nat_addr,
2135                                     in_port,
2136                                     out_port,
2137                                     proto=IP_PROTOS.udp)
2138         self.nat_add_static_mapping(self.server_addr,
2139                                     self.nat_addr,
2140                                     proto=IP_PROTOS.icmp)
2141
2142         # run tests for each protocol
2143         self.frag_in_order_in_plus_out(self.server_addr,
2144                                        self.nat_addr,
2145                                        in_port,
2146                                        out_port,
2147                                        IP_PROTOS.tcp)
2148         self.frag_in_order_in_plus_out(self.server_addr,
2149                                        self.nat_addr,
2150                                        in_port,
2151                                        out_port,
2152                                        IP_PROTOS.udp)
2153         self.frag_in_order_in_plus_out(self.server_addr,
2154                                        self.nat_addr,
2155                                        in_port,
2156                                        out_port,
2157                                        IP_PROTOS.icmp)
2158
2159     def test_frag_out_of_order_in_plus_out(self):
2160         """ NAT44ED in+out interface fragments out of order """
2161
2162         in_port = self.random_port()
2163         out_port = self.random_port()
2164
2165         self.nat_add_address(self.nat_addr)
2166         self.nat_add_inside_interface(self.pg0)
2167         self.nat_add_outside_interface(self.pg0)
2168         self.nat_add_inside_interface(self.pg1)
2169         self.nat_add_outside_interface(self.pg1)
2170
2171         # add static mappings for server
2172         self.nat_add_static_mapping(self.server_addr,
2173                                     self.nat_addr,
2174                                     in_port,
2175                                     out_port,
2176                                     proto=IP_PROTOS.tcp)
2177         self.nat_add_static_mapping(self.server_addr,
2178                                     self.nat_addr,
2179                                     in_port,
2180                                     out_port,
2181                                     proto=IP_PROTOS.udp)
2182         self.nat_add_static_mapping(self.server_addr,
2183                                     self.nat_addr,
2184                                     proto=IP_PROTOS.icmp)
2185
2186         # run tests for each protocol
2187         self.frag_out_of_order_in_plus_out(self.server_addr,
2188                                            self.nat_addr,
2189                                            in_port,
2190                                            out_port,
2191                                            IP_PROTOS.tcp)
2192         self.frag_out_of_order_in_plus_out(self.server_addr,
2193                                            self.nat_addr,
2194                                            in_port,
2195                                            out_port,
2196                                            IP_PROTOS.udp)
2197         self.frag_out_of_order_in_plus_out(self.server_addr,
2198                                            self.nat_addr,
2199                                            in_port,
2200                                            out_port,
2201                                            IP_PROTOS.icmp)
2202
2203     def test_reass_hairpinning(self):
2204         """ NAT44ED fragments hairpinning """
2205
2206         server_addr = self.pg0.remote_hosts[1].ip4
2207
2208         host_in_port = self.random_port()
2209         server_in_port = self.random_port()
2210         server_out_port = self.random_port()
2211
2212         self.nat_add_address(self.nat_addr)
2213         self.nat_add_inside_interface(self.pg0)
2214         self.nat_add_outside_interface(self.pg1)
2215
2216         # add static mapping for server
2217         self.nat_add_static_mapping(server_addr, self.nat_addr,
2218                                     server_in_port, server_out_port,
2219                                     proto=IP_PROTOS.tcp)
2220         self.nat_add_static_mapping(server_addr, self.nat_addr,
2221                                     server_in_port, server_out_port,
2222                                     proto=IP_PROTOS.udp)
2223         self.nat_add_static_mapping(server_addr, self.nat_addr)
2224
2225         self.reass_hairpinning(server_addr, server_in_port, server_out_port,
2226                                host_in_port, proto=IP_PROTOS.tcp,
2227                                ignore_port=True)
2228         self.reass_hairpinning(server_addr, server_in_port, server_out_port,
2229                                host_in_port, proto=IP_PROTOS.udp,
2230                                ignore_port=True)
2231         self.reass_hairpinning(server_addr, server_in_port, server_out_port,
2232                                host_in_port, proto=IP_PROTOS.icmp,
2233                                ignore_port=True)
2234
2235     def test_session_limit_per_vrf(self):
2236         """ NAT44ED per vrf session limit """
2237
2238         inside = self.pg0
2239         inside_vrf10 = self.pg2
2240         outside = self.pg1
2241
2242         limit = 5
2243
2244         # 2 interfaces pg0, pg1 (vrf10, limit 1 tcp session)
2245         # non existing vrf_id makes process core dump
2246         self.vapi.nat44_set_session_limit(session_limit=limit, vrf_id=10)
2247
2248         self.nat_add_inside_interface(inside)
2249         self.nat_add_inside_interface(inside_vrf10)
2250         self.nat_add_outside_interface(outside)
2251
2252         # vrf independent
2253         self.nat_add_interface_address(outside)
2254
2255         # BUG: causing core dump - when bad vrf_id is specified
2256         # self.nat_add_address(outside.local_ip4, vrf_id=20)
2257
2258         stream = self.create_tcp_stream(inside_vrf10, outside, limit * 2)
2259         inside_vrf10.add_stream(stream)
2260
2261         self.pg_enable_capture(self.pg_interfaces)
2262         self.pg_start()
2263
2264         capture = outside.get_capture(limit)
2265
2266         stream = self.create_tcp_stream(inside, outside, limit * 2)
2267         inside.add_stream(stream)
2268
2269         self.pg_enable_capture(self.pg_interfaces)
2270         self.pg_start()
2271
2272         capture = outside.get_capture(len(stream))
2273
2274     def test_show_max_translations(self):
2275         """ NAT44ED API test - max translations per thread """
2276         nat_config = self.vapi.nat_show_config_2()
2277         self.assertEqual(self.max_sessions,
2278                          nat_config.max_translations_per_thread)
2279
2280     def test_lru_cleanup(self):
2281         """ NAT44ED LRU cleanup algorithm """
2282
2283         self.nat_add_address(self.nat_addr)
2284         self.nat_add_inside_interface(self.pg0)
2285         self.nat_add_outside_interface(self.pg1)
2286
2287         self.vapi.nat_set_timeouts(
2288             udp=1, tcp_established=7440, tcp_transitory=30, icmp=1)
2289
2290         tcp_port_out = self.init_tcp_session(self.pg0, self.pg1, 2000, 80)
2291         pkts = []
2292         for i in range(0, self.max_sessions - 1):
2293             p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2294                  IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4, ttl=64) /
2295                  UDP(sport=7000+i, dport=80))
2296             pkts.append(p)
2297
2298         self.pg0.add_stream(pkts)
2299         self.pg_enable_capture(self.pg_interfaces)
2300         self.pg_start()
2301         self.pg1.get_capture(len(pkts))
2302         self.sleep(1.5, "wait for timeouts")
2303
2304         pkts = []
2305         for i in range(0, self.max_sessions - 1):
2306             p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2307                  IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4, ttl=64) /
2308                  ICMP(id=8000+i, type='echo-request'))
2309             pkts.append(p)
2310
2311         self.pg0.add_stream(pkts)
2312         self.pg_enable_capture(self.pg_interfaces)
2313         self.pg_start()
2314         self.pg1.get_capture(len(pkts))
2315
2316     def test_session_rst_timeout(self):
2317         """ NAT44ED session RST timeouts """
2318
2319         self.nat_add_address(self.nat_addr)
2320         self.nat_add_inside_interface(self.pg0)
2321         self.nat_add_outside_interface(self.pg1)
2322
2323         self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
2324                                    tcp_transitory=5, icmp=60)
2325
2326         self.init_tcp_session(self.pg0, self.pg1, self.tcp_port_in,
2327                               self.tcp_external_port)
2328         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
2329              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2330              TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
2331                  flags="R"))
2332         self.pg0.add_stream(p)
2333         self.pg_enable_capture(self.pg_interfaces)
2334         self.pg_start()
2335         self.pg1.get_capture(1)
2336
2337         self.sleep(6)
2338
2339         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
2340              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2341              TCP(sport=self.tcp_port_in + 1, dport=self.tcp_external_port + 1,
2342                  flags="S"))
2343         self.pg0.add_stream(p)
2344         self.pg_enable_capture(self.pg_interfaces)
2345         self.pg_start()
2346         self.pg1.get_capture(1)
2347
2348     def test_dynamic_out_of_ports(self):
2349         """ NAT44ED dynamic translation test: out of ports """
2350
2351         self.nat_add_inside_interface(self.pg0)
2352         self.nat_add_outside_interface(self.pg1)
2353
2354         # in2out and no NAT addresses added
2355         err_old = self.statistics.get_err_counter(
2356             '/err/nat44-ed-in2out-slowpath/out of ports')
2357
2358         pkts = self.create_stream_in(self.pg0, self.pg1)
2359         self.pg0.add_stream(pkts)
2360         self.pg_enable_capture(self.pg_interfaces)
2361         self.pg_start()
2362         self.pg1.get_capture(0, timeout=1)
2363
2364         err_new = self.statistics.get_err_counter(
2365             '/err/nat44-ed-in2out-slowpath/out of ports')
2366
2367         self.assertEqual(err_new - err_old, len(pkts))
2368
2369         # in2out after NAT addresses added
2370         self.nat_add_address(self.nat_addr)
2371
2372         err_old = self.statistics.get_err_counter(
2373             '/err/nat44-ed-in2out-slowpath/out of ports')
2374
2375         pkts = self.create_stream_in(self.pg0, self.pg1)
2376         self.pg0.add_stream(pkts)
2377         self.pg_enable_capture(self.pg_interfaces)
2378         self.pg_start()
2379         capture = self.pg1.get_capture(len(pkts))
2380         self.verify_capture_out(capture, ignore_port=True)
2381
2382         err_new = self.statistics.get_err_counter(
2383             '/err/nat44-ed-in2out-slowpath/out of ports')
2384
2385         self.assertEqual(err_new, err_old)
2386
2387     def test_unknown_proto(self):
2388         """ NAT44ED translate packet with unknown protocol """
2389
2390         self.nat_add_address(self.nat_addr)
2391         self.nat_add_inside_interface(self.pg0)
2392         self.nat_add_outside_interface(self.pg1)
2393
2394         # in2out
2395         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2396              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2397              TCP(sport=self.tcp_port_in, dport=20))
2398         self.pg0.add_stream(p)
2399         self.pg_enable_capture(self.pg_interfaces)
2400         self.pg_start()
2401         p = self.pg1.get_capture(1)
2402
2403         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2404              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2405              GRE() /
2406              IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
2407              TCP(sport=1234, dport=1234))
2408         self.pg0.add_stream(p)
2409         self.pg_enable_capture(self.pg_interfaces)
2410         self.pg_start()
2411         p = self.pg1.get_capture(1)
2412         packet = p[0]
2413         try:
2414             self.assertEqual(packet[IP].src, self.nat_addr)
2415             self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
2416             self.assertEqual(packet.haslayer(GRE), 1)
2417             self.assert_packet_checksums_valid(packet)
2418         except:
2419             self.logger.error(ppp("Unexpected or invalid packet:", packet))
2420             raise
2421
2422         # out2in
2423         p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
2424              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
2425              GRE() /
2426              IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
2427              TCP(sport=1234, dport=1234))
2428         self.pg1.add_stream(p)
2429         self.pg_enable_capture(self.pg_interfaces)
2430         self.pg_start()
2431         p = self.pg0.get_capture(1)
2432         packet = p[0]
2433         try:
2434             self.assertEqual(packet[IP].src, self.pg1.remote_ip4)
2435             self.assertEqual(packet[IP].dst, self.pg0.remote_ip4)
2436             self.assertEqual(packet.haslayer(GRE), 1)
2437             self.assert_packet_checksums_valid(packet)
2438         except:
2439             self.logger.error(ppp("Unexpected or invalid packet:", packet))
2440             raise
2441
2442     def test_hairpinning_unknown_proto(self):
2443         """ NAT44ED translate packet with unknown protocol - hairpinning """
2444         host = self.pg0.remote_hosts[0]
2445         server = self.pg0.remote_hosts[1]
2446         host_in_port = 1234
2447         server_out_port = 8765
2448         server_nat_ip = "10.0.0.11"
2449
2450         self.nat_add_address(self.nat_addr)
2451         self.nat_add_inside_interface(self.pg0)
2452         self.nat_add_outside_interface(self.pg1)
2453
2454         # add static mapping for server
2455         self.nat_add_static_mapping(server.ip4, server_nat_ip)
2456
2457         # host to server
2458         p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
2459              IP(src=host.ip4, dst=server_nat_ip) /
2460              TCP(sport=host_in_port, dport=server_out_port))
2461         self.pg0.add_stream(p)
2462         self.pg_enable_capture(self.pg_interfaces)
2463         self.pg_start()
2464         self.pg0.get_capture(1)
2465
2466         p = (Ether(dst=self.pg0.local_mac, src=host.mac) /
2467              IP(src=host.ip4, dst=server_nat_ip) /
2468              GRE() /
2469              IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
2470              TCP(sport=1234, dport=1234))
2471         self.pg0.add_stream(p)
2472         self.pg_enable_capture(self.pg_interfaces)
2473         self.pg_start()
2474         p = self.pg0.get_capture(1)
2475         packet = p[0]
2476         try:
2477             self.assertEqual(packet[IP].src, self.nat_addr)
2478             self.assertEqual(packet[IP].dst, server.ip4)
2479             self.assertEqual(packet.haslayer(GRE), 1)
2480             self.assert_packet_checksums_valid(packet)
2481         except:
2482             self.logger.error(ppp("Unexpected or invalid packet:", packet))
2483             raise
2484
2485         # server to host
2486         p = (Ether(dst=self.pg0.local_mac, src=server.mac) /
2487              IP(src=server.ip4, dst=self.nat_addr) /
2488              GRE() /
2489              IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
2490              TCP(sport=1234, dport=1234))
2491         self.pg0.add_stream(p)
2492         self.pg_enable_capture(self.pg_interfaces)
2493         self.pg_start()
2494         p = self.pg0.get_capture(1)
2495         packet = p[0]
2496         try:
2497             self.assertEqual(packet[IP].src, server_nat_ip)
2498             self.assertEqual(packet[IP].dst, host.ip4)
2499             self.assertEqual(packet.haslayer(GRE), 1)
2500             self.assert_packet_checksums_valid(packet)
2501         except:
2502             self.logger.error(ppp("Unexpected or invalid packet:", packet))
2503             raise
2504
2505     def test_output_feature_and_service(self):
2506         """ NAT44ED interface output feature and services """
2507         external_addr = '1.2.3.4'
2508         external_port = 80
2509         local_port = 8080
2510
2511         self.vapi.nat44_forwarding_enable_disable(enable=1)
2512         self.nat_add_address(self.nat_addr)
2513         flags = self.config_flags.NAT_IS_ADDR_ONLY
2514         self.vapi.nat44_add_del_identity_mapping(
2515             ip_address=self.pg1.remote_ip4, sw_if_index=0xFFFFFFFF,
2516             flags=flags, is_add=1)
2517         flags = self.config_flags.NAT_IS_OUT2IN_ONLY
2518         self.nat_add_static_mapping(self.pg0.remote_ip4, external_addr,
2519                                     local_port, external_port,
2520                                     proto=IP_PROTOS.tcp, flags=flags)
2521
2522         self.nat_add_inside_interface(self.pg0)
2523         self.nat_add_outside_interface(self.pg0)
2524         self.vapi.nat44_interface_add_del_output_feature(
2525             sw_if_index=self.pg1.sw_if_index, is_add=1)
2526
2527         # from client to service
2528         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
2529              IP(src=self.pg1.remote_ip4, dst=external_addr) /
2530              TCP(sport=12345, dport=external_port))
2531         self.pg1.add_stream(p)
2532         self.pg_enable_capture(self.pg_interfaces)
2533         self.pg_start()
2534         capture = self.pg0.get_capture(1)
2535         p = capture[0]
2536         try:
2537             ip = p[IP]
2538             tcp = p[TCP]
2539             self.assertEqual(ip.dst, self.pg0.remote_ip4)
2540             self.assertEqual(tcp.dport, local_port)
2541             self.assert_packet_checksums_valid(p)
2542         except:
2543             self.logger.error(ppp("Unexpected or invalid packet:", p))
2544             raise
2545
2546         # from service back to client
2547         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
2548              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2549              TCP(sport=local_port, dport=12345))
2550         self.pg0.add_stream(p)
2551         self.pg_enable_capture(self.pg_interfaces)
2552         self.pg_start()
2553         capture = self.pg1.get_capture(1)
2554         p = capture[0]
2555         try:
2556             ip = p[IP]
2557             tcp = p[TCP]
2558             self.assertEqual(ip.src, external_addr)
2559             self.assertEqual(tcp.sport, external_port)
2560             self.assert_packet_checksums_valid(p)
2561         except:
2562             self.logger.error(ppp("Unexpected or invalid packet:", p))
2563             raise
2564
2565         # from local network host to external network
2566         pkts = self.create_stream_in(self.pg0, self.pg1)
2567         self.pg0.add_stream(pkts)
2568         self.pg_enable_capture(self.pg_interfaces)
2569         self.pg_start()
2570         capture = self.pg1.get_capture(len(pkts))
2571         self.verify_capture_out(capture, ignore_port=True)
2572         pkts = self.create_stream_in(self.pg0, self.pg1)
2573         self.pg0.add_stream(pkts)
2574         self.pg_enable_capture(self.pg_interfaces)
2575         self.pg_start()
2576         capture = self.pg1.get_capture(len(pkts))
2577         self.verify_capture_out(capture, ignore_port=True)
2578
2579         # from external network back to local network host
2580         pkts = self.create_stream_out(self.pg1)
2581         self.pg1.add_stream(pkts)
2582         self.pg_enable_capture(self.pg_interfaces)
2583         self.pg_start()
2584         capture = self.pg0.get_capture(len(pkts))
2585         self.verify_capture_in(capture, self.pg0)
2586
2587     def test_output_feature_and_service3(self):
2588         """ NAT44ED interface output feature and DST NAT """
2589         external_addr = '1.2.3.4'
2590         external_port = 80
2591         local_port = 8080
2592
2593         self.vapi.nat44_forwarding_enable_disable(enable=1)
2594         self.nat_add_address(self.nat_addr)
2595         flags = self.config_flags.NAT_IS_OUT2IN_ONLY
2596         self.nat_add_static_mapping(self.pg1.remote_ip4, external_addr,
2597                                     local_port, external_port,
2598                                     proto=IP_PROTOS.tcp, flags=flags)
2599
2600         self.nat_add_inside_interface(self.pg0)
2601         self.nat_add_outside_interface(self.pg0)
2602         self.vapi.nat44_interface_add_del_output_feature(
2603             sw_if_index=self.pg1.sw_if_index, is_add=1)
2604
2605         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
2606              IP(src=self.pg0.remote_ip4, dst=external_addr) /
2607              TCP(sport=12345, dport=external_port))
2608         self.pg0.add_stream(p)
2609         self.pg_enable_capture(self.pg_interfaces)
2610         self.pg_start()
2611         capture = self.pg1.get_capture(1)
2612         p = capture[0]
2613         try:
2614             ip = p[IP]
2615             tcp = p[TCP]
2616             self.assertEqual(ip.src, self.pg0.remote_ip4)
2617             self.assertEqual(tcp.sport, 12345)
2618             self.assertEqual(ip.dst, self.pg1.remote_ip4)
2619             self.assertEqual(tcp.dport, local_port)
2620             self.assert_packet_checksums_valid(p)
2621         except:
2622             self.logger.error(ppp("Unexpected or invalid packet:", p))
2623             raise
2624
2625         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
2626              IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
2627              TCP(sport=local_port, dport=12345))
2628         self.pg1.add_stream(p)
2629         self.pg_enable_capture(self.pg_interfaces)
2630         self.pg_start()
2631         capture = self.pg0.get_capture(1)
2632         p = capture[0]
2633         try:
2634             ip = p[IP]
2635             tcp = p[TCP]
2636             self.assertEqual(ip.src, external_addr)
2637             self.assertEqual(tcp.sport, external_port)
2638             self.assertEqual(ip.dst, self.pg0.remote_ip4)
2639             self.assertEqual(tcp.dport, 12345)
2640             self.assert_packet_checksums_valid(p)
2641         except:
2642             self.logger.error(ppp("Unexpected or invalid packet:", p))
2643             raise
2644
2645     def test_self_twice_nat_lb_negative(self):
2646         """ NAT44ED Self Twice NAT local service load balancing (negative test)
2647         """
2648         self.twice_nat_common(lb=True, self_twice_nat=True, same_pg=True,
2649                               client_id=2)
2650
2651     def test_self_twice_nat_negative(self):
2652         """ NAT44ED Self Twice NAT (negative test) """
2653         self.twice_nat_common(self_twice_nat=True)
2654
2655     def test_static_lb_multi_clients(self):
2656         """ NAT44ED local service load balancing - multiple clients"""
2657
2658         external_addr = self.nat_addr
2659         external_port = 80
2660         local_port = 8080
2661         server1 = self.pg0.remote_hosts[0]
2662         server2 = self.pg0.remote_hosts[1]
2663         server3 = self.pg0.remote_hosts[2]
2664
2665         locals = [{'addr': server1.ip4,
2666                    'port': local_port,
2667                    'probability': 90,
2668                    'vrf_id': 0},
2669                   {'addr': server2.ip4,
2670                    'port': local_port,
2671                    'probability': 10,
2672                    'vrf_id': 0}]
2673
2674         flags = self.config_flags.NAT_IS_INSIDE
2675         self.vapi.nat44_interface_add_del_feature(
2676             sw_if_index=self.pg0.sw_if_index,
2677             flags=flags, is_add=1)
2678         self.vapi.nat44_interface_add_del_feature(
2679             sw_if_index=self.pg1.sw_if_index,
2680             is_add=1)
2681
2682         self.nat_add_address(self.nat_addr)
2683         self.vapi.nat44_add_del_lb_static_mapping(is_add=1,
2684                                                   external_addr=external_addr,
2685                                                   external_port=external_port,
2686                                                   protocol=IP_PROTOS.tcp,
2687                                                   local_num=len(locals),
2688                                                   locals=locals)
2689
2690         server1_n = 0
2691         server2_n = 0
2692         clients = ip4_range(self.pg1.remote_ip4, 10, 50)
2693         pkts = []
2694         for client in clients:
2695             p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
2696                  IP(src=client, dst=self.nat_addr) /
2697                  TCP(sport=12345, dport=external_port))
2698             pkts.append(p)
2699         self.pg1.add_stream(pkts)
2700         self.pg_enable_capture(self.pg_interfaces)
2701         self.pg_start()
2702         capture = self.pg0.get_capture(len(pkts))
2703         for p in capture:
2704             if p[IP].dst == server1.ip4:
2705                 server1_n += 1
2706             else:
2707                 server2_n += 1
2708         self.assertGreater(server1_n, server2_n)
2709
2710         local = {
2711             'addr': server3.ip4,
2712             'port': local_port,
2713             'probability': 20,
2714             'vrf_id': 0
2715         }
2716
2717         # add new back-end
2718         self.vapi.nat44_lb_static_mapping_add_del_local(
2719             is_add=1,
2720             external_addr=external_addr,
2721             external_port=external_port,
2722             local=local,
2723             protocol=IP_PROTOS.tcp)
2724         server1_n = 0
2725         server2_n = 0
2726         server3_n = 0
2727         clients = ip4_range(self.pg1.remote_ip4, 60, 110)
2728         pkts = []
2729         for client in clients:
2730             p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
2731                  IP(src=client, dst=self.nat_addr) /
2732                  TCP(sport=12346, dport=external_port))
2733             pkts.append(p)
2734         self.assertGreater(len(pkts), 0)
2735         self.pg1.add_stream(pkts)
2736         self.pg_enable_capture(self.pg_interfaces)
2737         self.pg_start()
2738         capture = self.pg0.get_capture(len(pkts))
2739         for p in capture:
2740             if p[IP].dst == server1.ip4:
2741                 server1_n += 1
2742             elif p[IP].dst == server2.ip4:
2743                 server2_n += 1
2744             else:
2745                 server3_n += 1
2746         self.assertGreater(server1_n, 0)
2747         self.assertGreater(server2_n, 0)
2748         self.assertGreater(server3_n, 0)
2749
2750         local = {
2751             'addr': server2.ip4,
2752             'port': local_port,
2753             'probability': 10,
2754             'vrf_id': 0
2755         }
2756
2757         # remove one back-end
2758         self.vapi.nat44_lb_static_mapping_add_del_local(
2759             is_add=0,
2760             external_addr=external_addr,
2761             external_port=external_port,
2762             local=local,
2763             protocol=IP_PROTOS.tcp)
2764         server1_n = 0
2765         server2_n = 0
2766         server3_n = 0
2767         self.pg1.add_stream(pkts)
2768         self.pg_enable_capture(self.pg_interfaces)
2769         self.pg_start()
2770         capture = self.pg0.get_capture(len(pkts))
2771         for p in capture:
2772             if p[IP].dst == server1.ip4:
2773                 server1_n += 1
2774             elif p[IP].dst == server2.ip4:
2775                 server2_n += 1
2776             else:
2777                 server3_n += 1
2778         self.assertGreater(server1_n, 0)
2779         self.assertEqual(server2_n, 0)
2780         self.assertGreater(server3_n, 0)
2781
2782     def test_syslog_sess(self):
2783         """ NAT44ED Test syslog session creation and deletion """
2784         self.vapi.syslog_set_filter(
2785             self.syslog_severity.SYSLOG_API_SEVERITY_INFO)
2786         self.vapi.syslog_set_sender(self.pg3.local_ip4, self.pg3.remote_ip4)
2787
2788         self.nat_add_address(self.nat_addr)
2789         self.nat_add_inside_interface(self.pg0)
2790         self.nat_add_outside_interface(self.pg1)
2791
2792         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2793              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2794              TCP(sport=self.tcp_port_in, dport=self.tcp_external_port))
2795         self.pg0.add_stream(p)
2796         self.pg_enable_capture(self.pg_interfaces)
2797         self.pg_start()
2798         capture = self.pg1.get_capture(1)
2799         self.tcp_port_out = capture[0][TCP].sport
2800         capture = self.pg3.get_capture(1)
2801         self.verify_syslog_sess(capture[0][Raw].load)
2802
2803         self.pg_enable_capture(self.pg_interfaces)
2804         self.pg_start()
2805         self.nat_add_address(self.nat_addr, is_add=0)
2806         capture = self.pg3.get_capture(1)
2807         self.verify_syslog_sess(capture[0][Raw].load, False)
2808
2809     def test_twice_nat_interface_addr(self):
2810         """ NAT44ED Acquire twice NAT addresses from interface """
2811         flags = self.config_flags.NAT_IS_TWICE_NAT
2812         self.vapi.nat44_add_del_interface_addr(
2813             sw_if_index=self.pg11.sw_if_index,
2814             flags=flags, is_add=1)
2815
2816         # no address in NAT pool
2817         adresses = self.vapi.nat44_address_dump()
2818         self.assertEqual(0, len(adresses))
2819
2820         # configure interface address and check NAT address pool
2821         self.pg11.config_ip4()
2822         adresses = self.vapi.nat44_address_dump()
2823         self.assertEqual(1, len(adresses))
2824         self.assertEqual(str(adresses[0].ip_address),
2825                          self.pg11.local_ip4)
2826         self.assertEqual(adresses[0].flags, flags)
2827
2828         # remove interface address and check NAT address pool
2829         self.pg11.unconfig_ip4()
2830         adresses = self.vapi.nat44_address_dump()
2831         self.assertEqual(0, len(adresses))
2832
2833     def test_output_feature_stateful_acl(self):
2834         """ NAT44ED output feature works with stateful ACL """
2835
2836         self.nat_add_address(self.nat_addr)
2837         self.vapi.nat44_interface_add_del_output_feature(
2838             sw_if_index=self.pg0.sw_if_index,
2839             flags=self.config_flags.NAT_IS_INSIDE, is_add=1)
2840         self.vapi.nat44_interface_add_del_output_feature(
2841             sw_if_index=self.pg1.sw_if_index,
2842             flags=self.config_flags.NAT_IS_OUTSIDE, is_add=1)
2843
2844         # First ensure that the NAT is working sans ACL
2845
2846         # send packets out2in, no sessions yet so packets should drop
2847         pkts_out2in = self.create_stream_out(self.pg1)
2848         self.send_and_assert_no_replies(self.pg1, pkts_out2in)
2849
2850         # send packets into inside intf, ensure received via outside intf
2851         pkts_in2out = self.create_stream_in(self.pg0, self.pg1)
2852         capture = self.send_and_expect(self.pg0, pkts_in2out, self.pg1,
2853                                        len(pkts_in2out))
2854         self.verify_capture_out(capture, ignore_port=True)
2855
2856         # send out2in again, with sessions created it should work now
2857         pkts_out2in = self.create_stream_out(self.pg1)
2858         capture = self.send_and_expect(self.pg1, pkts_out2in, self.pg0,
2859                                        len(pkts_out2in))
2860         self.verify_capture_in(capture, self.pg0)
2861
2862         # Create an ACL blocking everything
2863         out2in_deny_rule = AclRule(is_permit=0)
2864         out2in_acl = VppAcl(self, rules=[out2in_deny_rule])
2865         out2in_acl.add_vpp_config()
2866
2867         # create an ACL to permit/reflect everything
2868         in2out_reflect_rule = AclRule(is_permit=2)
2869         in2out_acl = VppAcl(self, rules=[in2out_reflect_rule])
2870         in2out_acl.add_vpp_config()
2871
2872         # apply as input acl on interface and confirm it blocks everything
2873         acl_if = VppAclInterface(self, sw_if_index=self.pg1.sw_if_index,
2874                                  n_input=1, acls=[out2in_acl])
2875         acl_if.add_vpp_config()
2876         self.send_and_assert_no_replies(self.pg1, pkts_out2in)
2877
2878         # apply output acl
2879         acl_if.acls = [out2in_acl, in2out_acl]
2880         acl_if.add_vpp_config()
2881         # send in2out to generate ACL state (NAT state was created earlier)
2882         capture = self.send_and_expect(self.pg0, pkts_in2out, self.pg1,
2883                                        len(pkts_in2out))
2884         self.verify_capture_out(capture, ignore_port=True)
2885
2886         # send out2in again. ACL state exists so it should work now.
2887         # TCP packets with the syn flag set also need the ack flag
2888         for p in pkts_out2in:
2889             if p.haslayer(TCP) and p[TCP].flags & 0x02:
2890                 p[TCP].flags |= 0x10
2891         capture = self.send_and_expect(self.pg1, pkts_out2in, self.pg0,
2892                                        len(pkts_out2in))
2893         self.verify_capture_in(capture, self.pg0)
2894         self.logger.info(self.vapi.cli("show trace"))
2895
2896     def test_tcp_close(self):
2897         """ NAT44ED Close TCP session from inside network - output feature """
2898         old_timeouts = self.vapi.nat_get_timeouts()
2899         new_transitory = 2
2900         self.vapi.nat_set_timeouts(
2901             udp=old_timeouts.udp,
2902             tcp_established=old_timeouts.tcp_established,
2903             icmp=old_timeouts.icmp,
2904             tcp_transitory=new_transitory)
2905
2906         self.vapi.nat44_forwarding_enable_disable(enable=1)
2907         self.nat_add_address(self.pg1.local_ip4)
2908         twice_nat_addr = '10.0.1.3'
2909         service_ip = '192.168.16.150'
2910         self.nat_add_address(twice_nat_addr, twice_nat=1)
2911
2912         flags = self.config_flags.NAT_IS_INSIDE
2913         self.vapi.nat44_interface_add_del_feature(
2914             sw_if_index=self.pg0.sw_if_index,
2915             is_add=1)
2916         self.vapi.nat44_interface_add_del_feature(
2917             sw_if_index=self.pg0.sw_if_index,
2918             flags=flags, is_add=1)
2919         self.vapi.nat44_interface_add_del_output_feature(
2920             is_add=1,
2921             sw_if_index=self.pg1.sw_if_index)
2922
2923         flags = (self.config_flags.NAT_IS_OUT2IN_ONLY |
2924                  self.config_flags.NAT_IS_TWICE_NAT)
2925         self.nat_add_static_mapping(self.pg0.remote_ip4,
2926                                     service_ip, 80, 80,
2927                                     proto=IP_PROTOS.tcp,
2928                                     flags=flags)
2929         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
2930         start_sessnum = len(sessions)
2931
2932         # SYN packet out->in
2933         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
2934              IP(src=self.pg1.remote_ip4, dst=service_ip) /
2935              TCP(sport=33898, dport=80, flags="S"))
2936         self.pg1.add_stream(p)
2937         self.pg_enable_capture(self.pg_interfaces)
2938         self.pg_start()
2939         capture = self.pg0.get_capture(1)
2940         p = capture[0]
2941         tcp_port = p[TCP].sport
2942
2943         # SYN + ACK packet in->out
2944         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
2945              IP(src=self.pg0.remote_ip4, dst=twice_nat_addr) /
2946              TCP(sport=80, dport=tcp_port, flags="SA"))
2947         self.pg0.add_stream(p)
2948         self.pg_enable_capture(self.pg_interfaces)
2949         self.pg_start()
2950         self.pg1.get_capture(1)
2951
2952         # ACK packet out->in
2953         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
2954              IP(src=self.pg1.remote_ip4, dst=service_ip) /
2955              TCP(sport=33898, dport=80, flags="A"))
2956         self.pg1.add_stream(p)
2957         self.pg_enable_capture(self.pg_interfaces)
2958         self.pg_start()
2959         self.pg0.get_capture(1)
2960
2961         # FIN packet in -> out
2962         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
2963              IP(src=self.pg0.remote_ip4, dst=twice_nat_addr) /
2964              TCP(sport=80, dport=tcp_port, flags="FA", seq=100, ack=300))
2965         self.pg0.add_stream(p)
2966         self.pg_enable_capture(self.pg_interfaces)
2967         self.pg_start()
2968         self.pg1.get_capture(1)
2969
2970         # FIN+ACK packet out -> in
2971         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
2972              IP(src=self.pg1.remote_ip4, dst=service_ip) /
2973              TCP(sport=33898, dport=80, flags="FA", seq=300, ack=101))
2974         self.pg1.add_stream(p)
2975         self.pg_enable_capture(self.pg_interfaces)
2976         self.pg_start()
2977         self.pg0.get_capture(1)
2978
2979         # ACK packet in -> out
2980         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
2981              IP(src=self.pg0.remote_ip4, dst=twice_nat_addr) /
2982              TCP(sport=80, dport=tcp_port, flags="A", seq=101, ack=301))
2983         self.pg0.add_stream(p)
2984         self.pg_enable_capture(self.pg_interfaces)
2985         self.pg_start()
2986         self.pg1.get_capture(1)
2987
2988         # session now in transitory timeout
2989         # try SYN packet out->in - should be dropped
2990         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
2991              IP(src=self.pg1.remote_ip4, dst=service_ip) /
2992              TCP(sport=33898, dport=80, flags="S"))
2993         self.pg1.add_stream(p)
2994         self.pg_enable_capture(self.pg_interfaces)
2995         self.pg_start()
2996
2997         self.sleep(new_transitory, "wait for transitory timeout")
2998         self.pg0.assert_nothing_captured(0)
2999
3000         # session should still exist
3001         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3002         self.assertEqual(len(sessions) - start_sessnum, 1)
3003
3004         # send FIN+ACK packet out -> in - will cause session to be wiped
3005         # but won't create a new session
3006         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3007              IP(src=self.pg1.remote_ip4, dst=service_ip) /
3008              TCP(sport=33898, dport=80, flags="FA", seq=300, ack=101))
3009         self.pg1.add_stream(p)
3010         self.pg_enable_capture(self.pg_interfaces)
3011         self.pg_start()
3012
3013         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3014         self.assertEqual(len(sessions) - start_sessnum, 0)
3015         self.pg0.assert_nothing_captured(0)
3016
3017     def test_tcp_session_close_in(self):
3018         """ NAT44ED Close TCP session from inside network """
3019
3020         in_port = self.tcp_port_in
3021         out_port = 10505
3022         ext_port = self.tcp_external_port
3023
3024         self.nat_add_address(self.nat_addr)
3025         self.nat_add_inside_interface(self.pg0)
3026         self.nat_add_outside_interface(self.pg1)
3027         self.nat_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
3028                                     in_port, out_port, proto=IP_PROTOS.tcp,
3029                                     flags=self.config_flags.NAT_IS_TWICE_NAT)
3030
3031         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3032         session_n = len(sessions)
3033
3034         self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
3035                                    tcp_transitory=2, icmp=5)
3036
3037         self.init_tcp_session(self.pg0, self.pg1, in_port, ext_port)
3038
3039         # FIN packet in -> out
3040         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3041              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3042              TCP(sport=in_port, dport=ext_port,
3043                  flags="FA", seq=100, ack=300))
3044         self.pg0.add_stream(p)
3045         self.pg_enable_capture(self.pg_interfaces)
3046         self.pg_start()
3047         self.pg1.get_capture(1)
3048
3049         pkts = []
3050
3051         # ACK packet out -> in
3052         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3053              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3054              TCP(sport=ext_port, dport=out_port,
3055                  flags="A", seq=300, ack=101))
3056         pkts.append(p)
3057
3058         # FIN packet out -> in
3059         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3060              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3061              TCP(sport=ext_port, dport=out_port,
3062                  flags="FA", seq=300, ack=101))
3063         pkts.append(p)
3064
3065         self.pg1.add_stream(pkts)
3066         self.pg_enable_capture(self.pg_interfaces)
3067         self.pg_start()
3068         self.pg0.get_capture(2)
3069
3070         # ACK packet in -> out
3071         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3072              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3073              TCP(sport=in_port, dport=ext_port,
3074                  flags="A", seq=101, ack=301))
3075         self.pg0.add_stream(p)
3076         self.pg_enable_capture(self.pg_interfaces)
3077         self.pg_start()
3078         self.pg1.get_capture(1)
3079
3080         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3081         self.assertEqual(len(sessions) - session_n, 1)
3082
3083         out2in_drops = self.get_err_counter(
3084             '/err/nat44-ed-out2in/drops due to TCP in transitory timeout')
3085         in2out_drops = self.get_err_counter(
3086             '/err/nat44-ed-in2out/drops due to TCP in transitory timeout')
3087
3088         # extra FIN packet out -> in - this should be dropped
3089         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3090              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3091              TCP(sport=ext_port, dport=out_port,
3092                  flags="FA", seq=300, ack=101))
3093
3094         self.pg1.add_stream(p)
3095         self.pg_enable_capture(self.pg_interfaces)
3096         self.pg_start()
3097         self.pg0.assert_nothing_captured()
3098
3099         # extra ACK packet in -> out - this should be dropped
3100         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3101              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3102              TCP(sport=in_port, dport=ext_port,
3103                  flags="A", seq=101, ack=301))
3104         self.pg0.add_stream(p)
3105         self.pg_enable_capture(self.pg_interfaces)
3106         self.pg_start()
3107         self.pg1.assert_nothing_captured()
3108
3109         stats = self.get_err_counter(
3110             '/err/nat44-ed-out2in/drops due to TCP in transitory timeout')
3111         self.assertEqual(stats - out2in_drops, 1)
3112         stats = self.get_err_counter(
3113             '/err/nat44-ed-in2out/drops due to TCP in transitory timeout')
3114         self.assertEqual(stats - in2out_drops, 1)
3115
3116         self.sleep(3)
3117         # extra ACK packet in -> out - this will cause session to be wiped
3118         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3119              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3120              TCP(sport=in_port, dport=ext_port,
3121                  flags="A", seq=101, ack=301))
3122         self.pg0.add_stream(p)
3123         self.pg_enable_capture(self.pg_interfaces)
3124         self.pg_start()
3125         self.pg1.assert_nothing_captured()
3126         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3127         self.assertEqual(len(sessions) - session_n, 0)
3128
3129     def test_tcp_session_close_out(self):
3130         """ NAT44ED Close TCP session from outside network """
3131
3132         in_port = self.tcp_port_in
3133         out_port = 10505
3134         ext_port = self.tcp_external_port
3135
3136         self.nat_add_address(self.nat_addr)
3137         self.nat_add_inside_interface(self.pg0)
3138         self.nat_add_outside_interface(self.pg1)
3139         self.nat_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
3140                                     in_port, out_port, proto=IP_PROTOS.tcp,
3141                                     flags=self.config_flags.NAT_IS_TWICE_NAT)
3142
3143         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3144         session_n = len(sessions)
3145
3146         self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
3147                                    tcp_transitory=2, icmp=5)
3148
3149         _ = self.init_tcp_session(self.pg0, self.pg1, in_port, ext_port)
3150
3151         # FIN packet out -> in
3152         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3153              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3154              TCP(sport=ext_port, dport=out_port,
3155                  flags="FA", seq=100, ack=300))
3156         self.pg1.add_stream(p)
3157         self.pg_enable_capture(self.pg_interfaces)
3158         self.pg_start()
3159         self.pg0.get_capture(1)
3160
3161         # FIN+ACK packet in -> out
3162         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3163              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3164              TCP(sport=in_port, dport=ext_port,
3165                  flags="FA", seq=300, ack=101))
3166
3167         self.pg0.add_stream(p)
3168         self.pg_enable_capture(self.pg_interfaces)
3169         self.pg_start()
3170         self.pg1.get_capture(1)
3171
3172         # ACK packet out -> in
3173         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3174              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3175              TCP(sport=ext_port, dport=out_port,
3176                  flags="A", seq=101, ack=301))
3177         self.pg1.add_stream(p)
3178         self.pg_enable_capture(self.pg_interfaces)
3179         self.pg_start()
3180         self.pg0.get_capture(1)
3181
3182         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3183         self.assertEqual(len(sessions) - session_n, 1)
3184
3185         out2in_drops = self.get_err_counter(
3186             '/err/nat44-ed-out2in/drops due to TCP in transitory timeout')
3187         in2out_drops = self.get_err_counter(
3188             '/err/nat44-ed-in2out/drops due to TCP in transitory timeout')
3189
3190         # extra FIN packet out -> in - this should be dropped
3191         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3192              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3193              TCP(sport=ext_port, dport=out_port,
3194                  flags="FA", seq=300, ack=101))
3195
3196         self.pg1.add_stream(p)
3197         self.pg_enable_capture(self.pg_interfaces)
3198         self.pg_start()
3199         self.pg0.assert_nothing_captured()
3200
3201         # extra ACK packet in -> out - this should be dropped
3202         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3203              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3204              TCP(sport=in_port, dport=ext_port,
3205                  flags="A", seq=101, ack=301))
3206         self.pg0.add_stream(p)
3207         self.pg_enable_capture(self.pg_interfaces)
3208         self.pg_start()
3209         self.pg1.assert_nothing_captured()
3210
3211         stats = self.get_err_counter(
3212             '/err/nat44-ed-out2in/drops due to TCP in transitory timeout')
3213         self.assertEqual(stats - out2in_drops, 1)
3214         stats = self.get_err_counter(
3215             '/err/nat44-ed-in2out/drops due to TCP in transitory timeout')
3216         self.assertEqual(stats - in2out_drops, 1)
3217
3218         self.sleep(3)
3219         # extra ACK packet in -> out - this will cause session to be wiped
3220         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3221              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3222              TCP(sport=in_port, dport=ext_port,
3223                  flags="A", seq=101, ack=301))
3224         self.pg0.add_stream(p)
3225         self.pg_enable_capture(self.pg_interfaces)
3226         self.pg_start()
3227         self.pg1.assert_nothing_captured()
3228         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3229         self.assertEqual(len(sessions) - session_n, 0)
3230
3231     def test_tcp_session_close_simultaneous(self):
3232         """ NAT44ED Close TCP session from inside network """
3233
3234         in_port = self.tcp_port_in
3235         ext_port = 10505
3236
3237         self.nat_add_address(self.nat_addr)
3238         self.nat_add_inside_interface(self.pg0)
3239         self.nat_add_outside_interface(self.pg1)
3240         self.nat_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
3241                                     in_port, ext_port, proto=IP_PROTOS.tcp,
3242                                     flags=self.config_flags.NAT_IS_TWICE_NAT)
3243
3244         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3245         session_n = len(sessions)
3246
3247         self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
3248                                    tcp_transitory=2, icmp=5)
3249
3250         out_port = self.init_tcp_session(self.pg0, self.pg1, in_port, ext_port)
3251
3252         # FIN packet in -> out
3253         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3254              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3255              TCP(sport=in_port, dport=ext_port,
3256                  flags="FA", seq=100, ack=300))
3257         self.pg0.add_stream(p)
3258         self.pg_enable_capture(self.pg_interfaces)
3259         self.pg_start()
3260         self.pg1.get_capture(1)
3261
3262         # FIN packet out -> in
3263         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3264              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3265              TCP(sport=ext_port, dport=out_port,
3266                  flags="FA", seq=300, ack=100))
3267         self.pg1.add_stream(p)
3268         self.pg_enable_capture(self.pg_interfaces)
3269         self.pg_start()
3270         self.pg0.get_capture(1)
3271
3272         # ACK packet in -> out
3273         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3274              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3275              TCP(sport=in_port, dport=ext_port,
3276                  flags="A", seq=101, ack=301))
3277         self.pg0.add_stream(p)
3278         self.pg_enable_capture(self.pg_interfaces)
3279         self.pg_start()
3280         self.pg1.get_capture(1)
3281
3282         # ACK packet out -> in
3283         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3284              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3285              TCP(sport=ext_port, dport=out_port,
3286                  flags="A", seq=301, ack=101))
3287         self.pg1.add_stream(p)
3288         self.pg_enable_capture(self.pg_interfaces)
3289         self.pg_start()
3290         self.pg0.get_capture(1)
3291
3292         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3293         self.assertEqual(len(sessions) - session_n, 1)
3294
3295         out2in_drops = self.get_err_counter(
3296             '/err/nat44-ed-out2in/drops due to TCP in transitory timeout')
3297         in2out_drops = self.get_err_counter(
3298             '/err/nat44-ed-in2out/drops due to TCP in transitory timeout')
3299
3300         # extra FIN packet out -> in - this should be dropped
3301         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3302              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3303              TCP(sport=ext_port, dport=out_port,
3304                  flags="FA", seq=300, ack=101))
3305
3306         self.pg1.add_stream(p)
3307         self.pg_enable_capture(self.pg_interfaces)
3308         self.pg_start()
3309         self.pg0.assert_nothing_captured()
3310
3311         # extra ACK packet in -> out - this should be dropped
3312         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3313              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3314              TCP(sport=in_port, dport=ext_port,
3315                  flags="A", seq=101, ack=301))
3316         self.pg0.add_stream(p)
3317         self.pg_enable_capture(self.pg_interfaces)
3318         self.pg_start()
3319         self.pg1.assert_nothing_captured()
3320
3321         stats = self.get_err_counter(
3322             '/err/nat44-ed-out2in/drops due to TCP in transitory timeout')
3323         self.assertEqual(stats - out2in_drops, 1)
3324         stats = self.get_err_counter(
3325             '/err/nat44-ed-in2out/drops due to TCP in transitory timeout')
3326         self.assertEqual(stats - in2out_drops, 1)
3327
3328         self.sleep(3)
3329         # extra ACK packet in -> out - this will cause session to be wiped
3330         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3331              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3332              TCP(sport=in_port, dport=ext_port,
3333                  flags="A", seq=101, ack=301))
3334         self.pg0.add_stream(p)
3335         self.pg_enable_capture(self.pg_interfaces)
3336         self.pg_start()
3337         self.pg1.assert_nothing_captured()
3338         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3339         self.assertEqual(len(sessions) - session_n, 0)
3340
3341     def test_dynamic_output_feature_vrf(self):
3342         """ NAT44ED dynamic translation test: output-feature, VRF"""
3343
3344         # other then default (0)
3345         new_vrf_id = 22
3346
3347         self.nat_add_address(self.nat_addr)
3348         flags = self.config_flags.NAT_IS_INSIDE
3349         self.vapi.nat44_interface_add_del_output_feature(
3350             sw_if_index=self.pg7.sw_if_index,
3351             flags=flags, is_add=1)
3352         self.vapi.nat44_interface_add_del_output_feature(
3353             sw_if_index=self.pg8.sw_if_index,
3354             is_add=1)
3355
3356         try:
3357             self.configure_ip4_interface(self.pg7, table_id=new_vrf_id)
3358             self.configure_ip4_interface(self.pg8, table_id=new_vrf_id)
3359
3360             # in2out
3361             tcpn = self.get_stats_counter(
3362                 '/nat44-ed/in2out/slowpath/tcp')
3363             udpn = self.get_stats_counter(
3364                 '/nat44-ed/in2out/slowpath/udp')
3365             icmpn = self.get_stats_counter(
3366                 '/nat44-ed/in2out/slowpath/icmp')
3367             drops = self.get_stats_counter(
3368                 '/nat44-ed/in2out/slowpath/drops')
3369
3370             pkts = self.create_stream_in(self.pg7, self.pg8)
3371             self.pg7.add_stream(pkts)
3372             self.pg_enable_capture(self.pg_interfaces)
3373             self.pg_start()
3374             capture = self.pg8.get_capture(len(pkts))
3375             self.verify_capture_out(capture, ignore_port=True)
3376
3377             if_idx = self.pg7.sw_if_index
3378             cnt = self.get_stats_counter(
3379                 '/nat44-ed/in2out/slowpath/tcp')
3380             self.assertEqual(cnt[if_idx] - tcpn[if_idx], 2)
3381             cnt = self.get_stats_counter(
3382                 '/nat44-ed/in2out/slowpath/udp')
3383             self.assertEqual(cnt[if_idx] - udpn[if_idx], 1)
3384             cnt = self.get_stats_counter(
3385                 '/nat44-ed/in2out/slowpath/icmp')
3386             self.assertEqual(cnt[if_idx] - icmpn[if_idx], 1)
3387             cnt = self.get_stats_counter(
3388                 '/nat44-ed/in2out/slowpath/drops')
3389             self.assertEqual(cnt[if_idx] - drops[if_idx], 0)
3390
3391             # out2in
3392             tcpn = self.get_stats_counter(
3393                 '/nat44-ed/out2in/fastpath/tcp')
3394             udpn = self.get_stats_counter(
3395                 '/nat44-ed/out2in/fastpath/udp')
3396             icmpn = self.get_stats_counter(
3397                 '/nat44-ed/out2in/fastpath/icmp')
3398             drops = self.get_stats_counter(
3399                 '/nat44-ed/out2in/fastpath/drops')
3400
3401             pkts = self.create_stream_out(self.pg8)
3402             self.pg8.add_stream(pkts)
3403             self.pg_enable_capture(self.pg_interfaces)
3404             self.pg_start()
3405             capture = self.pg7.get_capture(len(pkts))
3406             self.verify_capture_in(capture, self.pg7)
3407
3408             if_idx = self.pg8.sw_if_index
3409             cnt = self.get_stats_counter(
3410                 '/nat44-ed/out2in/fastpath/tcp')
3411             self.assertEqual(cnt[if_idx] - tcpn[if_idx], 2)
3412             cnt = self.get_stats_counter(
3413                 '/nat44-ed/out2in/fastpath/udp')
3414             self.assertEqual(cnt[if_idx] - udpn[if_idx], 1)
3415             cnt = self.get_stats_counter(
3416                 '/nat44-ed/out2in/fastpath/icmp')
3417             self.assertEqual(cnt[if_idx] - icmpn[if_idx], 1)
3418             cnt = self.get_stats_counter(
3419                 '/nat44-ed/out2in/fastpath/drops')
3420             self.assertEqual(cnt[if_idx] - drops[if_idx], 0)
3421
3422             sessions = self.get_stats_counter('/nat44-ed/total-sessions')
3423             self.assertEqual(sessions[0], 3)
3424
3425         finally:
3426             self.configure_ip4_interface(self.pg7, table_id=0)
3427             self.configure_ip4_interface(self.pg8, table_id=0)
3428
3429             self.vapi.ip_table_add_del(is_add=0,
3430                                        table={'table_id': new_vrf_id})
3431
3432     def test_next_src_nat(self):
3433         """ NAT44ED On way back forward packet to nat44-in2out node. """
3434
3435         twice_nat_addr = '10.0.1.3'
3436         external_port = 80
3437         local_port = 8080
3438         post_twice_nat_port = 0
3439
3440         self.vapi.nat44_forwarding_enable_disable(enable=1)
3441         self.nat_add_address(twice_nat_addr, twice_nat=1)
3442         flags = (self.config_flags.NAT_IS_OUT2IN_ONLY |
3443                  self.config_flags.NAT_IS_SELF_TWICE_NAT)
3444         self.nat_add_static_mapping(self.pg6.remote_ip4, self.pg1.remote_ip4,
3445                                     local_port, external_port,
3446                                     proto=IP_PROTOS.tcp, vrf_id=1,
3447                                     flags=flags)
3448         self.vapi.nat44_interface_add_del_feature(
3449             sw_if_index=self.pg6.sw_if_index,
3450             is_add=1)
3451
3452         p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
3453              IP(src=self.pg6.remote_ip4, dst=self.pg1.remote_ip4) /
3454              TCP(sport=12345, dport=external_port))
3455         self.pg6.add_stream(p)
3456         self.pg_enable_capture(self.pg_interfaces)
3457         self.pg_start()
3458         capture = self.pg6.get_capture(1)
3459         p = capture[0]
3460         try:
3461             ip = p[IP]
3462             tcp = p[TCP]
3463             self.assertEqual(ip.src, twice_nat_addr)
3464             self.assertNotEqual(tcp.sport, 12345)
3465             post_twice_nat_port = tcp.sport
3466             self.assertEqual(ip.dst, self.pg6.remote_ip4)
3467             self.assertEqual(tcp.dport, local_port)
3468             self.assert_packet_checksums_valid(p)
3469         except:
3470             self.logger.error(ppp("Unexpected or invalid packet:", p))
3471             raise
3472
3473         p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
3474              IP(src=self.pg6.remote_ip4, dst=twice_nat_addr) /
3475              TCP(sport=local_port, dport=post_twice_nat_port))
3476         self.pg6.add_stream(p)
3477         self.pg_enable_capture(self.pg_interfaces)
3478         self.pg_start()
3479         capture = self.pg6.get_capture(1)
3480         p = capture[0]
3481         try:
3482             ip = p[IP]
3483             tcp = p[TCP]
3484             self.assertEqual(ip.src, self.pg1.remote_ip4)
3485             self.assertEqual(tcp.sport, external_port)
3486             self.assertEqual(ip.dst, self.pg6.remote_ip4)
3487             self.assertEqual(tcp.dport, 12345)
3488             self.assert_packet_checksums_valid(p)
3489         except:
3490             self.logger.error(ppp("Unexpected or invalid packet:", p))
3491             raise
3492
3493     def test_one_armed_nat44_static(self):
3494         """ NAT44ED One armed NAT and 1:1 NAPT asymmetrical rule """
3495
3496         remote_host = self.pg4.remote_hosts[0]
3497         local_host = self.pg4.remote_hosts[1]
3498         external_port = 80
3499         local_port = 8080
3500         eh_port_in = 0
3501
3502         self.vapi.nat44_forwarding_enable_disable(enable=1)
3503         self.nat_add_address(self.nat_addr, twice_nat=1)
3504         flags = (self.config_flags.NAT_IS_OUT2IN_ONLY |
3505                  self.config_flags.NAT_IS_TWICE_NAT)
3506         self.nat_add_static_mapping(local_host.ip4, self.nat_addr,
3507                                     local_port, external_port,
3508                                     proto=IP_PROTOS.tcp, flags=flags)
3509         flags = self.config_flags.NAT_IS_INSIDE
3510         self.vapi.nat44_interface_add_del_feature(
3511             sw_if_index=self.pg4.sw_if_index,
3512             is_add=1)
3513         self.vapi.nat44_interface_add_del_feature(
3514             sw_if_index=self.pg4.sw_if_index,
3515             flags=flags, is_add=1)
3516
3517         # from client to service
3518         p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
3519              IP(src=remote_host.ip4, dst=self.nat_addr) /
3520              TCP(sport=12345, dport=external_port))
3521         self.pg4.add_stream(p)
3522         self.pg_enable_capture(self.pg_interfaces)
3523         self.pg_start()
3524         capture = self.pg4.get_capture(1)
3525         p = capture[0]
3526         try:
3527             ip = p[IP]
3528             tcp = p[TCP]
3529             self.assertEqual(ip.dst, local_host.ip4)
3530             self.assertEqual(ip.src, self.nat_addr)
3531             self.assertEqual(tcp.dport, local_port)
3532             self.assertNotEqual(tcp.sport, 12345)
3533             eh_port_in = tcp.sport
3534             self.assert_packet_checksums_valid(p)
3535         except:
3536             self.logger.error(ppp("Unexpected or invalid packet:", p))
3537             raise
3538
3539         # from service back to client
3540         p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
3541              IP(src=local_host.ip4, dst=self.nat_addr) /
3542              TCP(sport=local_port, dport=eh_port_in))
3543         self.pg4.add_stream(p)
3544         self.pg_enable_capture(self.pg_interfaces)
3545         self.pg_start()
3546         capture = self.pg4.get_capture(1)
3547         p = capture[0]
3548         try:
3549             ip = p[IP]
3550             tcp = p[TCP]
3551             self.assertEqual(ip.src, self.nat_addr)
3552             self.assertEqual(ip.dst, remote_host.ip4)
3553             self.assertEqual(tcp.sport, external_port)
3554             self.assertEqual(tcp.dport, 12345)
3555             self.assert_packet_checksums_valid(p)
3556         except:
3557             self.logger.error(ppp("Unexpected or invalid packet:", p))
3558             raise
3559
3560
3561 if __name__ == '__main__':
3562     unittest.main(testRunner=VppTestRunner)