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