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