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