NAT44: nat44_del_session and nat44_user_session_details API update (VPP-1271)
[vpp.git] / test / test_nat.py
1 #!/usr/bin/env python
2
3 import socket
4 import unittest
5 import struct
6 import StringIO
7 import random
8
9 from framework import VppTestCase, VppTestRunner, running_extended_tests
10 from scapy.layers.inet import IP, TCP, UDP, ICMP
11 from scapy.layers.inet import IPerror, TCPerror, UDPerror, ICMPerror
12 from scapy.layers.inet6 import IPv6, ICMPv6EchoRequest, ICMPv6EchoReply
13 from scapy.layers.inet6 import ICMPv6DestUnreach, IPerror6, IPv6ExtHdrFragment
14 from scapy.layers.l2 import Ether, ARP, GRE
15 from scapy.data import IP_PROTOS
16 from scapy.packet import bind_layers, Raw
17 from scapy.all import fragment6
18 from util import ppp
19 from ipfix import IPFIX, Set, Template, Data, IPFIXDecoder
20 from time import sleep
21 from util import ip4_range
22 from util import mactobinary
23
24
25 class MethodHolder(VppTestCase):
26     """ NAT create capture and verify method holder """
27
28     def create_stream_in(self, in_if, out_if, dst_ip=None, ttl=64):
29         """
30         Create packet stream for inside network
31
32         :param in_if: Inside interface
33         :param out_if: Outside interface
34         :param dst_ip: Destination address
35         :param ttl: TTL of generated packets
36         """
37         if dst_ip is None:
38             dst_ip = out_if.remote_ip4
39
40         pkts = []
41         # TCP
42         p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
43              IP(src=in_if.remote_ip4, dst=dst_ip, ttl=ttl) /
44              TCP(sport=self.tcp_port_in, dport=20))
45         pkts.append(p)
46
47         # UDP
48         p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
49              IP(src=in_if.remote_ip4, dst=dst_ip, ttl=ttl) /
50              UDP(sport=self.udp_port_in, dport=20))
51         pkts.append(p)
52
53         # ICMP
54         p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
55              IP(src=in_if.remote_ip4, dst=dst_ip, ttl=ttl) /
56              ICMP(id=self.icmp_id_in, type='echo-request'))
57         pkts.append(p)
58
59         return pkts
60
61     def compose_ip6(self, ip4, pref, plen):
62         """
63         Compose IPv4-embedded IPv6 addresses
64
65         :param ip4: IPv4 address
66         :param pref: IPv6 prefix
67         :param plen: IPv6 prefix length
68         :returns: IPv4-embedded IPv6 addresses
69         """
70         pref_n = list(socket.inet_pton(socket.AF_INET6, pref))
71         ip4_n = list(socket.inet_pton(socket.AF_INET, ip4))
72         if plen == 32:
73             pref_n[4] = ip4_n[0]
74             pref_n[5] = ip4_n[1]
75             pref_n[6] = ip4_n[2]
76             pref_n[7] = ip4_n[3]
77         elif plen == 40:
78             pref_n[5] = ip4_n[0]
79             pref_n[6] = ip4_n[1]
80             pref_n[7] = ip4_n[2]
81             pref_n[9] = ip4_n[3]
82         elif plen == 48:
83             pref_n[6] = ip4_n[0]
84             pref_n[7] = ip4_n[1]
85             pref_n[9] = ip4_n[2]
86             pref_n[10] = ip4_n[3]
87         elif plen == 56:
88             pref_n[7] = ip4_n[0]
89             pref_n[9] = ip4_n[1]
90             pref_n[10] = ip4_n[2]
91             pref_n[11] = ip4_n[3]
92         elif plen == 64:
93             pref_n[9] = ip4_n[0]
94             pref_n[10] = ip4_n[1]
95             pref_n[11] = ip4_n[2]
96             pref_n[12] = ip4_n[3]
97         elif plen == 96:
98             pref_n[12] = ip4_n[0]
99             pref_n[13] = ip4_n[1]
100             pref_n[14] = ip4_n[2]
101             pref_n[15] = ip4_n[3]
102         return socket.inet_ntop(socket.AF_INET6, ''.join(pref_n))
103
104     def extract_ip4(self, ip6, plen):
105         """
106         Extract IPv4 address embedded in IPv6 addresses
107
108         :param ip6: IPv6 address
109         :param plen: IPv6 prefix length
110         :returns: extracted IPv4 address
111         """
112         ip6_n = list(socket.inet_pton(socket.AF_INET6, ip6))
113         ip4_n = [None] * 4
114         if plen == 32:
115             ip4_n[0] = ip6_n[4]
116             ip4_n[1] = ip6_n[5]
117             ip4_n[2] = ip6_n[6]
118             ip4_n[3] = ip6_n[7]
119         elif plen == 40:
120             ip4_n[0] = ip6_n[5]
121             ip4_n[1] = ip6_n[6]
122             ip4_n[2] = ip6_n[7]
123             ip4_n[3] = ip6_n[9]
124         elif plen == 48:
125             ip4_n[0] = ip6_n[6]
126             ip4_n[1] = ip6_n[7]
127             ip4_n[2] = ip6_n[9]
128             ip4_n[3] = ip6_n[10]
129         elif plen == 56:
130             ip4_n[0] = ip6_n[7]
131             ip4_n[1] = ip6_n[9]
132             ip4_n[2] = ip6_n[10]
133             ip4_n[3] = ip6_n[11]
134         elif plen == 64:
135             ip4_n[0] = ip6_n[9]
136             ip4_n[1] = ip6_n[10]
137             ip4_n[2] = ip6_n[11]
138             ip4_n[3] = ip6_n[12]
139         elif plen == 96:
140             ip4_n[0] = ip6_n[12]
141             ip4_n[1] = ip6_n[13]
142             ip4_n[2] = ip6_n[14]
143             ip4_n[3] = ip6_n[15]
144         return socket.inet_ntop(socket.AF_INET, ''.join(ip4_n))
145
146     def create_stream_in_ip6(self, in_if, out_if, hlim=64, pref=None, plen=0):
147         """
148         Create IPv6 packet stream for inside network
149
150         :param in_if: Inside interface
151         :param out_if: Outside interface
152         :param ttl: Hop Limit of generated packets
153         :param pref: NAT64 prefix
154         :param plen: NAT64 prefix length
155         """
156         pkts = []
157         if pref is None:
158             dst = ''.join(['64:ff9b::', out_if.remote_ip4])
159         else:
160             dst = self.compose_ip6(out_if.remote_ip4, pref, plen)
161
162         # TCP
163         p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
164              IPv6(src=in_if.remote_ip6, dst=dst, hlim=hlim) /
165              TCP(sport=self.tcp_port_in, dport=20))
166         pkts.append(p)
167
168         # UDP
169         p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
170              IPv6(src=in_if.remote_ip6, dst=dst, hlim=hlim) /
171              UDP(sport=self.udp_port_in, dport=20))
172         pkts.append(p)
173
174         # ICMP
175         p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
176              IPv6(src=in_if.remote_ip6, dst=dst, hlim=hlim) /
177              ICMPv6EchoRequest(id=self.icmp_id_in))
178         pkts.append(p)
179
180         return pkts
181
182     def create_stream_out(self, out_if, dst_ip=None, ttl=64,
183                           use_inside_ports=False):
184         """
185         Create packet stream for outside network
186
187         :param out_if: Outside interface
188         :param dst_ip: Destination IP address (Default use global NAT address)
189         :param ttl: TTL of generated packets
190         :param use_inside_ports: Use inside NAT ports as destination ports
191                instead of outside ports
192         """
193         if dst_ip is None:
194             dst_ip = self.nat_addr
195         if not use_inside_ports:
196             tcp_port = self.tcp_port_out
197             udp_port = self.udp_port_out
198             icmp_id = self.icmp_id_out
199         else:
200             tcp_port = self.tcp_port_in
201             udp_port = self.udp_port_in
202             icmp_id = self.icmp_id_in
203         pkts = []
204         # TCP
205         p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
206              IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
207              TCP(dport=tcp_port, sport=20))
208         pkts.append(p)
209
210         # UDP
211         p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
212              IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
213              UDP(dport=udp_port, sport=20))
214         pkts.append(p)
215
216         # ICMP
217         p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
218              IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
219              ICMP(id=icmp_id, type='echo-reply'))
220         pkts.append(p)
221
222         return pkts
223
224     def create_stream_out_ip6(self, out_if, src_ip, dst_ip, hl=64):
225         """
226         Create packet stream for outside network
227
228         :param out_if: Outside interface
229         :param dst_ip: Destination IP address (Default use global NAT address)
230         :param hl: HL of generated packets
231         """
232         pkts = []
233         # TCP
234         p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
235              IPv6(src=src_ip, dst=dst_ip, hlim=hl) /
236              TCP(dport=self.tcp_port_out, sport=20))
237         pkts.append(p)
238
239         # UDP
240         p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
241              IPv6(src=src_ip, dst=dst_ip, hlim=hl) /
242              UDP(dport=self.udp_port_out, sport=20))
243         pkts.append(p)
244
245         # ICMP
246         p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
247              IPv6(src=src_ip, dst=dst_ip, hlim=hl) /
248              ICMPv6EchoReply(id=self.icmp_id_out))
249         pkts.append(p)
250
251         return pkts
252
253     def verify_capture_out(self, capture, nat_ip=None, same_port=False,
254                            packet_num=3, dst_ip=None, is_ip6=False):
255         """
256         Verify captured packets on outside network
257
258         :param capture: Captured packets
259         :param nat_ip: Translated IP address (Default use global NAT address)
260         :param same_port: Sorce port number is not translated (Default False)
261         :param packet_num: Expected number of packets (Default 3)
262         :param dst_ip: Destination IP address (Default do not verify)
263         :param is_ip6: If L3 protocol is IPv6 (Default False)
264         """
265         if is_ip6:
266             IP46 = IPv6
267             ICMP46 = ICMPv6EchoRequest
268         else:
269             IP46 = IP
270             ICMP46 = ICMP
271         if nat_ip is None:
272             nat_ip = self.nat_addr
273         self.assertEqual(packet_num, len(capture))
274         for packet in capture:
275             try:
276                 if not is_ip6:
277                     self.assert_packet_checksums_valid(packet)
278                 self.assertEqual(packet[IP46].src, nat_ip)
279                 if dst_ip is not None:
280                     self.assertEqual(packet[IP46].dst, dst_ip)
281                 if packet.haslayer(TCP):
282                     if same_port:
283                         self.assertEqual(packet[TCP].sport, self.tcp_port_in)
284                     else:
285                         self.assertNotEqual(
286                             packet[TCP].sport, self.tcp_port_in)
287                     self.tcp_port_out = packet[TCP].sport
288                     self.assert_packet_checksums_valid(packet)
289                 elif packet.haslayer(UDP):
290                     if same_port:
291                         self.assertEqual(packet[UDP].sport, self.udp_port_in)
292                     else:
293                         self.assertNotEqual(
294                             packet[UDP].sport, self.udp_port_in)
295                     self.udp_port_out = packet[UDP].sport
296                 else:
297                     if same_port:
298                         self.assertEqual(packet[ICMP46].id, self.icmp_id_in)
299                     else:
300                         self.assertNotEqual(packet[ICMP46].id, self.icmp_id_in)
301                     self.icmp_id_out = packet[ICMP46].id
302                     self.assert_packet_checksums_valid(packet)
303             except:
304                 self.logger.error(ppp("Unexpected or invalid packet "
305                                       "(outside network):", packet))
306                 raise
307
308     def verify_capture_out_ip6(self, capture, nat_ip, same_port=False,
309                                packet_num=3, dst_ip=None):
310         """
311         Verify captured packets on outside network
312
313         :param capture: Captured packets
314         :param nat_ip: Translated IP address
315         :param same_port: Sorce port number is not translated (Default False)
316         :param packet_num: Expected number of packets (Default 3)
317         :param dst_ip: Destination IP address (Default do not verify)
318         """
319         return self.verify_capture_out(capture, nat_ip, same_port, packet_num,
320                                        dst_ip, True)
321
322     def verify_capture_in(self, capture, in_if, packet_num=3):
323         """
324         Verify captured packets on inside network
325
326         :param capture: Captured packets
327         :param in_if: Inside interface
328         :param packet_num: Expected number of packets (Default 3)
329         """
330         self.assertEqual(packet_num, len(capture))
331         for packet in capture:
332             try:
333                 self.assert_packet_checksums_valid(packet)
334                 self.assertEqual(packet[IP].dst, in_if.remote_ip4)
335                 if packet.haslayer(TCP):
336                     self.assertEqual(packet[TCP].dport, self.tcp_port_in)
337                 elif packet.haslayer(UDP):
338                     self.assertEqual(packet[UDP].dport, self.udp_port_in)
339                 else:
340                     self.assertEqual(packet[ICMP].id, self.icmp_id_in)
341             except:
342                 self.logger.error(ppp("Unexpected or invalid packet "
343                                       "(inside network):", packet))
344                 raise
345
346     def verify_capture_in_ip6(self, capture, src_ip, dst_ip, packet_num=3):
347         """
348         Verify captured IPv6 packets on inside network
349
350         :param capture: Captured packets
351         :param src_ip: Source IP
352         :param dst_ip: Destination IP address
353         :param packet_num: Expected number of packets (Default 3)
354         """
355         self.assertEqual(packet_num, len(capture))
356         for packet in capture:
357             try:
358                 self.assertEqual(packet[IPv6].src, src_ip)
359                 self.assertEqual(packet[IPv6].dst, dst_ip)
360                 self.assert_packet_checksums_valid(packet)
361                 if packet.haslayer(TCP):
362                     self.assertEqual(packet[TCP].dport, self.tcp_port_in)
363                 elif packet.haslayer(UDP):
364                     self.assertEqual(packet[UDP].dport, self.udp_port_in)
365                 else:
366                     self.assertEqual(packet[ICMPv6EchoReply].id,
367                                      self.icmp_id_in)
368             except:
369                 self.logger.error(ppp("Unexpected or invalid packet "
370                                       "(inside network):", packet))
371                 raise
372
373     def verify_capture_no_translation(self, capture, ingress_if, egress_if):
374         """
375         Verify captured packet that don't have to be translated
376
377         :param capture: Captured packets
378         :param ingress_if: Ingress interface
379         :param egress_if: Egress interface
380         """
381         for packet in capture:
382             try:
383                 self.assertEqual(packet[IP].src, ingress_if.remote_ip4)
384                 self.assertEqual(packet[IP].dst, egress_if.remote_ip4)
385                 if packet.haslayer(TCP):
386                     self.assertEqual(packet[TCP].sport, self.tcp_port_in)
387                 elif packet.haslayer(UDP):
388                     self.assertEqual(packet[UDP].sport, self.udp_port_in)
389                 else:
390                     self.assertEqual(packet[ICMP].id, self.icmp_id_in)
391             except:
392                 self.logger.error(ppp("Unexpected or invalid packet "
393                                       "(inside network):", packet))
394                 raise
395
396     def verify_capture_out_with_icmp_errors(self, capture, src_ip=None,
397                                             packet_num=3, icmp_type=11):
398         """
399         Verify captured packets with ICMP errors on outside network
400
401         :param capture: Captured packets
402         :param src_ip: Translated IP address or IP address of VPP
403                        (Default use global NAT address)
404         :param packet_num: Expected number of packets (Default 3)
405         :param icmp_type: Type of error ICMP packet
406                           we are expecting (Default 11)
407         """
408         if src_ip is None:
409             src_ip = self.nat_addr
410         self.assertEqual(packet_num, len(capture))
411         for packet in capture:
412             try:
413                 self.assertEqual(packet[IP].src, src_ip)
414                 self.assertTrue(packet.haslayer(ICMP))
415                 icmp = packet[ICMP]
416                 self.assertEqual(icmp.type, icmp_type)
417                 self.assertTrue(icmp.haslayer(IPerror))
418                 inner_ip = icmp[IPerror]
419                 if inner_ip.haslayer(TCPerror):
420                     self.assertEqual(inner_ip[TCPerror].dport,
421                                      self.tcp_port_out)
422                 elif inner_ip.haslayer(UDPerror):
423                     self.assertEqual(inner_ip[UDPerror].dport,
424                                      self.udp_port_out)
425                 else:
426                     self.assertEqual(inner_ip[ICMPerror].id, self.icmp_id_out)
427             except:
428                 self.logger.error(ppp("Unexpected or invalid packet "
429                                       "(outside network):", packet))
430                 raise
431
432     def verify_capture_in_with_icmp_errors(self, capture, in_if, packet_num=3,
433                                            icmp_type=11):
434         """
435         Verify captured packets with ICMP errors on inside network
436
437         :param capture: Captured packets
438         :param in_if: Inside interface
439         :param packet_num: Expected number of packets (Default 3)
440         :param icmp_type: Type of error ICMP packet
441                           we are expecting (Default 11)
442         """
443         self.assertEqual(packet_num, len(capture))
444         for packet in capture:
445             try:
446                 self.assertEqual(packet[IP].dst, in_if.remote_ip4)
447                 self.assertTrue(packet.haslayer(ICMP))
448                 icmp = packet[ICMP]
449                 self.assertEqual(icmp.type, icmp_type)
450                 self.assertTrue(icmp.haslayer(IPerror))
451                 inner_ip = icmp[IPerror]
452                 if inner_ip.haslayer(TCPerror):
453                     self.assertEqual(inner_ip[TCPerror].sport,
454                                      self.tcp_port_in)
455                 elif inner_ip.haslayer(UDPerror):
456                     self.assertEqual(inner_ip[UDPerror].sport,
457                                      self.udp_port_in)
458                 else:
459                     self.assertEqual(inner_ip[ICMPerror].id, self.icmp_id_in)
460             except:
461                 self.logger.error(ppp("Unexpected or invalid packet "
462                                       "(inside network):", packet))
463                 raise
464
465     def create_stream_frag(self, src_if, dst, sport, dport, data):
466         """
467         Create fragmented packet stream
468
469         :param src_if: Source interface
470         :param dst: Destination IPv4 address
471         :param sport: Source TCP port
472         :param dport: Destination TCP port
473         :param data: Payload data
474         :returns: Fragmets
475         """
476         id = random.randint(0, 65535)
477         p = (IP(src=src_if.remote_ip4, dst=dst) /
478              TCP(sport=sport, dport=dport) /
479              Raw(data))
480         p = p.__class__(str(p))
481         chksum = p['TCP'].chksum
482         pkts = []
483         p = (Ether(src=src_if.remote_mac, dst=src_if.local_mac) /
484              IP(src=src_if.remote_ip4, dst=dst, flags="MF", frag=0, id=id) /
485              TCP(sport=sport, dport=dport, chksum=chksum) /
486              Raw(data[0:4]))
487         pkts.append(p)
488         p = (Ether(src=src_if.remote_mac, dst=src_if.local_mac) /
489              IP(src=src_if.remote_ip4, dst=dst, flags="MF", frag=3, id=id,
490                 proto=IP_PROTOS.tcp) /
491              Raw(data[4:20]))
492         pkts.append(p)
493         p = (Ether(src=src_if.remote_mac, dst=src_if.local_mac) /
494              IP(src=src_if.remote_ip4, dst=dst, frag=5, proto=IP_PROTOS.tcp,
495                 id=id) /
496              Raw(data[20:]))
497         pkts.append(p)
498         return pkts
499
500     def create_stream_frag_ip6(self, src_if, dst, sport, dport, data,
501                                pref=None, plen=0, frag_size=128):
502         """
503         Create fragmented packet stream
504
505         :param src_if: Source interface
506         :param dst: Destination IPv4 address
507         :param sport: Source TCP port
508         :param dport: Destination TCP port
509         :param data: Payload data
510         :param pref: NAT64 prefix
511         :param plen: NAT64 prefix length
512         :param fragsize: size of fragments
513         :returns: Fragmets
514         """
515         if pref is None:
516             dst_ip6 = ''.join(['64:ff9b::', dst])
517         else:
518             dst_ip6 = self.compose_ip6(dst, pref, plen)
519
520         p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
521              IPv6(src=src_if.remote_ip6, dst=dst_ip6) /
522              IPv6ExtHdrFragment(id=random.randint(0, 65535)) /
523              TCP(sport=sport, dport=dport) /
524              Raw(data))
525
526         return fragment6(p, frag_size)
527
528     def reass_frags_and_verify(self, frags, src, dst):
529         """
530         Reassemble and verify fragmented packet
531
532         :param frags: Captured fragments
533         :param src: Source IPv4 address to verify
534         :param dst: Destination IPv4 address to verify
535
536         :returns: Reassembled IPv4 packet
537         """
538         buffer = StringIO.StringIO()
539         for p in frags:
540             self.assertEqual(p[IP].src, src)
541             self.assertEqual(p[IP].dst, dst)
542             self.assert_ip_checksum_valid(p)
543             buffer.seek(p[IP].frag * 8)
544             buffer.write(p[IP].payload)
545         ip = frags[0].getlayer(IP)
546         ip = IP(src=frags[0][IP].src, dst=frags[0][IP].dst,
547                 proto=frags[0][IP].proto)
548         if ip.proto == IP_PROTOS.tcp:
549             p = (ip / TCP(buffer.getvalue()))
550             self.assert_tcp_checksum_valid(p)
551         elif ip.proto == IP_PROTOS.udp:
552             p = (ip / UDP(buffer.getvalue()))
553         return p
554
555     def reass_frags_and_verify_ip6(self, frags, src, dst):
556         """
557         Reassemble and verify fragmented packet
558
559         :param frags: Captured fragments
560         :param src: Source IPv6 address to verify
561         :param dst: Destination IPv6 address to verify
562
563         :returns: Reassembled IPv6 packet
564         """
565         buffer = StringIO.StringIO()
566         for p in frags:
567             self.assertEqual(p[IPv6].src, src)
568             self.assertEqual(p[IPv6].dst, dst)
569             buffer.seek(p[IPv6ExtHdrFragment].offset * 8)
570             buffer.write(p[IPv6ExtHdrFragment].payload)
571         ip = IPv6(src=frags[0][IPv6].src, dst=frags[0][IPv6].dst,
572                   nh=frags[0][IPv6ExtHdrFragment].nh)
573         if ip.nh == IP_PROTOS.tcp:
574             p = (ip / TCP(buffer.getvalue()))
575         elif ip.nh == IP_PROTOS.udp:
576             p = (ip / UDP(buffer.getvalue()))
577         self.assert_packet_checksums_valid(p)
578         return p
579
580     def initiate_tcp_session(self, in_if, out_if):
581         """
582         Initiates TCP session
583
584         :param in_if: Inside interface
585         :param out_if: Outside interface
586         """
587         try:
588             # SYN packet in->out
589             p = (Ether(src=in_if.remote_mac, dst=in_if.local_mac) /
590                  IP(src=in_if.remote_ip4, dst=out_if.remote_ip4) /
591                  TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
592                      flags="S"))
593             in_if.add_stream(p)
594             self.pg_enable_capture(self.pg_interfaces)
595             self.pg_start()
596             capture = out_if.get_capture(1)
597             p = capture[0]
598             self.tcp_port_out = p[TCP].sport
599
600             # SYN + ACK packet out->in
601             p = (Ether(src=out_if.remote_mac, dst=out_if.local_mac) /
602                  IP(src=out_if.remote_ip4, dst=self.nat_addr) /
603                  TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
604                      flags="SA"))
605             out_if.add_stream(p)
606             self.pg_enable_capture(self.pg_interfaces)
607             self.pg_start()
608             in_if.get_capture(1)
609
610             # ACK packet in->out
611             p = (Ether(src=in_if.remote_mac, dst=in_if.local_mac) /
612                  IP(src=in_if.remote_ip4, dst=out_if.remote_ip4) /
613                  TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
614                      flags="A"))
615             in_if.add_stream(p)
616             self.pg_enable_capture(self.pg_interfaces)
617             self.pg_start()
618             out_if.get_capture(1)
619
620         except:
621             self.logger.error("TCP 3 way handshake failed")
622             raise
623
624     def verify_ipfix_nat44_ses(self, data):
625         """
626         Verify IPFIX NAT44 session create/delete event
627
628         :param data: Decoded IPFIX data records
629         """
630         nat44_ses_create_num = 0
631         nat44_ses_delete_num = 0
632         self.assertEqual(6, len(data))
633         for record in data:
634             # natEvent
635             self.assertIn(ord(record[230]), [4, 5])
636             if ord(record[230]) == 4:
637                 nat44_ses_create_num += 1
638             else:
639                 nat44_ses_delete_num += 1
640             # sourceIPv4Address
641             self.assertEqual(self.pg0.remote_ip4n, record[8])
642             # postNATSourceIPv4Address
643             self.assertEqual(socket.inet_pton(socket.AF_INET, self.nat_addr),
644                              record[225])
645             # ingressVRFID
646             self.assertEqual(struct.pack("!I", 0), record[234])
647             # protocolIdentifier/sourceTransportPort/postNAPTSourceTransportPort
648             if IP_PROTOS.icmp == ord(record[4]):
649                 self.assertEqual(struct.pack("!H", self.icmp_id_in), record[7])
650                 self.assertEqual(struct.pack("!H", self.icmp_id_out),
651                                  record[227])
652             elif IP_PROTOS.tcp == ord(record[4]):
653                 self.assertEqual(struct.pack("!H", self.tcp_port_in),
654                                  record[7])
655                 self.assertEqual(struct.pack("!H", self.tcp_port_out),
656                                  record[227])
657             elif IP_PROTOS.udp == ord(record[4]):
658                 self.assertEqual(struct.pack("!H", self.udp_port_in),
659                                  record[7])
660                 self.assertEqual(struct.pack("!H", self.udp_port_out),
661                                  record[227])
662             else:
663                 self.fail("Invalid protocol")
664         self.assertEqual(3, nat44_ses_create_num)
665         self.assertEqual(3, nat44_ses_delete_num)
666
667     def verify_ipfix_addr_exhausted(self, data):
668         """
669         Verify IPFIX NAT addresses event
670
671         :param data: Decoded IPFIX data records
672         """
673         self.assertEqual(1, len(data))
674         record = data[0]
675         # natEvent
676         self.assertEqual(ord(record[230]), 3)
677         # natPoolID
678         self.assertEqual(struct.pack("!I", 0), record[283])
679
680     def verify_ipfix_max_sessions(self, data, limit):
681         """
682         Verify IPFIX maximum session entries exceeded event
683
684         :param data: Decoded IPFIX data records
685         :param limit: Number of maximum session entries that can be created.
686         """
687         self.assertEqual(1, len(data))
688         record = data[0]
689         # natEvent
690         self.assertEqual(ord(record[230]), 13)
691         # natQuotaExceededEvent
692         self.assertEqual(struct.pack("I", 1), record[466])
693         # maxSessionEntries
694         self.assertEqual(struct.pack("I", limit), record[471])
695
696     def verify_ipfix_max_bibs(self, data, limit):
697         """
698         Verify IPFIX maximum BIB entries exceeded event
699
700         :param data: Decoded IPFIX data records
701         :param limit: Number of maximum BIB entries that can be created.
702         """
703         self.assertEqual(1, len(data))
704         record = data[0]
705         # natEvent
706         self.assertEqual(ord(record[230]), 13)
707         # natQuotaExceededEvent
708         self.assertEqual(struct.pack("I", 2), record[466])
709         # maxBIBEntries
710         self.assertEqual(struct.pack("I", limit), record[472])
711
712     def verify_ipfix_max_fragments_ip6(self, data, limit, src_addr):
713         """
714         Verify IPFIX maximum IPv6 fragments pending reassembly exceeded event
715
716         :param data: Decoded IPFIX data records
717         :param limit: Number of maximum fragments pending reassembly
718         :param src_addr: IPv6 source address
719         """
720         self.assertEqual(1, len(data))
721         record = data[0]
722         # natEvent
723         self.assertEqual(ord(record[230]), 13)
724         # natQuotaExceededEvent
725         self.assertEqual(struct.pack("I", 5), record[466])
726         # maxFragmentsPendingReassembly
727         self.assertEqual(struct.pack("I", limit), record[475])
728         # sourceIPv6Address
729         self.assertEqual(src_addr, record[27])
730
731     def verify_ipfix_max_fragments_ip4(self, data, limit, src_addr):
732         """
733         Verify IPFIX maximum IPv4 fragments pending reassembly exceeded event
734
735         :param data: Decoded IPFIX data records
736         :param limit: Number of maximum fragments pending reassembly
737         :param src_addr: IPv4 source address
738         """
739         self.assertEqual(1, len(data))
740         record = data[0]
741         # natEvent
742         self.assertEqual(ord(record[230]), 13)
743         # natQuotaExceededEvent
744         self.assertEqual(struct.pack("I", 5), record[466])
745         # maxFragmentsPendingReassembly
746         self.assertEqual(struct.pack("I", limit), record[475])
747         # sourceIPv4Address
748         self.assertEqual(src_addr, record[8])
749
750     def verify_ipfix_bib(self, data, is_create, src_addr):
751         """
752         Verify IPFIX NAT64 BIB create and delete events
753
754         :param data: Decoded IPFIX data records
755         :param is_create: Create event if nonzero value otherwise delete event
756         :param src_addr: IPv6 source address
757         """
758         self.assertEqual(1, len(data))
759         record = data[0]
760         # natEvent
761         if is_create:
762             self.assertEqual(ord(record[230]), 10)
763         else:
764             self.assertEqual(ord(record[230]), 11)
765         # sourceIPv6Address
766         self.assertEqual(src_addr, record[27])
767         # postNATSourceIPv4Address
768         self.assertEqual(self.nat_addr_n, record[225])
769         # protocolIdentifier
770         self.assertEqual(IP_PROTOS.tcp, ord(record[4]))
771         # ingressVRFID
772         self.assertEqual(struct.pack("!I", 0), record[234])
773         # sourceTransportPort
774         self.assertEqual(struct.pack("!H", self.tcp_port_in), record[7])
775         # postNAPTSourceTransportPort
776         self.assertEqual(struct.pack("!H", self.tcp_port_out), record[227])
777
778     def verify_ipfix_nat64_ses(self, data, is_create, src_addr, dst_addr,
779                                dst_port):
780         """
781         Verify IPFIX NAT64 session create and delete events
782
783         :param data: Decoded IPFIX data records
784         :param is_create: Create event if nonzero value otherwise delete event
785         :param src_addr: IPv6 source address
786         :param dst_addr: IPv4 destination address
787         :param dst_port: destination TCP port
788         """
789         self.assertEqual(1, len(data))
790         record = data[0]
791         # natEvent
792         if is_create:
793             self.assertEqual(ord(record[230]), 6)
794         else:
795             self.assertEqual(ord(record[230]), 7)
796         # sourceIPv6Address
797         self.assertEqual(src_addr, record[27])
798         # destinationIPv6Address
799         self.assertEqual(socket.inet_pton(socket.AF_INET6,
800                                           self.compose_ip6(dst_addr,
801                                                            '64:ff9b::',
802                                                            96)),
803                          record[28])
804         # postNATSourceIPv4Address
805         self.assertEqual(self.nat_addr_n, record[225])
806         # postNATDestinationIPv4Address
807         self.assertEqual(socket.inet_pton(socket.AF_INET, dst_addr),
808                          record[226])
809         # protocolIdentifier
810         self.assertEqual(IP_PROTOS.tcp, ord(record[4]))
811         # ingressVRFID
812         self.assertEqual(struct.pack("!I", 0), record[234])
813         # sourceTransportPort
814         self.assertEqual(struct.pack("!H", self.tcp_port_in), record[7])
815         # postNAPTSourceTransportPort
816         self.assertEqual(struct.pack("!H", self.tcp_port_out), record[227])
817         # destinationTransportPort
818         self.assertEqual(struct.pack("!H", dst_port), record[11])
819         # postNAPTDestinationTransportPort
820         self.assertEqual(struct.pack("!H", dst_port), record[228])
821
822
823 class TestNAT44(MethodHolder):
824     """ NAT44 Test Cases """
825
826     @classmethod
827     def setUpClass(cls):
828         super(TestNAT44, cls).setUpClass()
829
830         try:
831             cls.tcp_port_in = 6303
832             cls.tcp_port_out = 6303
833             cls.udp_port_in = 6304
834             cls.udp_port_out = 6304
835             cls.icmp_id_in = 6305
836             cls.icmp_id_out = 6305
837             cls.nat_addr = '10.0.0.3'
838             cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
839             cls.ipfix_src_port = 4739
840             cls.ipfix_domain_id = 1
841             cls.tcp_external_port = 80
842
843             cls.create_pg_interfaces(range(10))
844             cls.interfaces = list(cls.pg_interfaces[0:4])
845
846             for i in cls.interfaces:
847                 i.admin_up()
848                 i.config_ip4()
849                 i.resolve_arp()
850
851             cls.pg0.generate_remote_hosts(3)
852             cls.pg0.configure_ipv4_neighbors()
853
854             cls.pg1.generate_remote_hosts(1)
855             cls.pg1.configure_ipv4_neighbors()
856
857             cls.overlapping_interfaces = list(list(cls.pg_interfaces[4:7]))
858             cls.vapi.ip_table_add_del(10, is_add=1)
859             cls.vapi.ip_table_add_del(20, is_add=1)
860
861             cls.pg4._local_ip4 = "172.16.255.1"
862             cls.pg4._local_ip4n = socket.inet_pton(socket.AF_INET, i.local_ip4)
863             cls.pg4._remote_hosts[0]._ip4 = "172.16.255.2"
864             cls.pg4.set_table_ip4(10)
865             cls.pg5._local_ip4 = "172.17.255.3"
866             cls.pg5._local_ip4n = socket.inet_pton(socket.AF_INET, i.local_ip4)
867             cls.pg5._remote_hosts[0]._ip4 = "172.17.255.4"
868             cls.pg5.set_table_ip4(10)
869             cls.pg6._local_ip4 = "172.16.255.1"
870             cls.pg6._local_ip4n = socket.inet_pton(socket.AF_INET, i.local_ip4)
871             cls.pg6._remote_hosts[0]._ip4 = "172.16.255.2"
872             cls.pg6.set_table_ip4(20)
873             for i in cls.overlapping_interfaces:
874                 i.config_ip4()
875                 i.admin_up()
876                 i.resolve_arp()
877
878             cls.pg7.admin_up()
879             cls.pg8.admin_up()
880
881             cls.pg9.generate_remote_hosts(2)
882             cls.pg9.config_ip4()
883             ip_addr_n = socket.inet_pton(socket.AF_INET, "10.0.0.1")
884             cls.vapi.sw_interface_add_del_address(cls.pg9.sw_if_index,
885                                                   ip_addr_n,
886                                                   24)
887             cls.pg9.admin_up()
888             cls.pg9.resolve_arp()
889             cls.pg9._remote_hosts[1]._ip4 = cls.pg9._remote_hosts[0]._ip4
890             cls.pg4._remote_ip4 = cls.pg9._remote_hosts[0]._ip4 = "10.0.0.2"
891             cls.pg9.resolve_arp()
892
893         except Exception:
894             super(TestNAT44, cls).tearDownClass()
895             raise
896
897     def clear_nat44(self):
898         """
899         Clear NAT44 configuration.
900         """
901         # I found no elegant way to do this
902         self.vapi.ip_add_del_route(dst_address=self.pg7.remote_ip4n,
903                                    dst_address_length=32,
904                                    next_hop_address=self.pg7.remote_ip4n,
905                                    next_hop_sw_if_index=self.pg7.sw_if_index,
906                                    is_add=0)
907         self.vapi.ip_add_del_route(dst_address=self.pg8.remote_ip4n,
908                                    dst_address_length=32,
909                                    next_hop_address=self.pg8.remote_ip4n,
910                                    next_hop_sw_if_index=self.pg8.sw_if_index,
911                                    is_add=0)
912
913         for intf in [self.pg7, self.pg8]:
914             neighbors = self.vapi.ip_neighbor_dump(intf.sw_if_index)
915             for n in neighbors:
916                 self.vapi.ip_neighbor_add_del(intf.sw_if_index,
917                                               n.mac_address,
918                                               n.ip_address,
919                                               is_add=0)
920
921         if self.pg7.has_ip4_config:
922             self.pg7.unconfig_ip4()
923
924         self.vapi.nat44_forwarding_enable_disable(0)
925
926         interfaces = self.vapi.nat44_interface_addr_dump()
927         for intf in interfaces:
928             self.vapi.nat44_add_interface_addr(intf.sw_if_index,
929                                                twice_nat=intf.twice_nat,
930                                                is_add=0)
931
932         self.vapi.nat_ipfix(enable=0, src_port=self.ipfix_src_port,
933                             domain_id=self.ipfix_domain_id)
934         self.ipfix_src_port = 4739
935         self.ipfix_domain_id = 1
936
937         interfaces = self.vapi.nat44_interface_dump()
938         for intf in interfaces:
939             if intf.is_inside > 1:
940                 self.vapi.nat44_interface_add_del_feature(intf.sw_if_index,
941                                                           0,
942                                                           is_add=0)
943             self.vapi.nat44_interface_add_del_feature(intf.sw_if_index,
944                                                       intf.is_inside,
945                                                       is_add=0)
946
947         interfaces = self.vapi.nat44_interface_output_feature_dump()
948         for intf in interfaces:
949             self.vapi.nat44_interface_add_del_output_feature(intf.sw_if_index,
950                                                              intf.is_inside,
951                                                              is_add=0)
952
953         static_mappings = self.vapi.nat44_static_mapping_dump()
954         for sm in static_mappings:
955             self.vapi.nat44_add_del_static_mapping(
956                 sm.local_ip_address,
957                 sm.external_ip_address,
958                 local_port=sm.local_port,
959                 external_port=sm.external_port,
960                 addr_only=sm.addr_only,
961                 vrf_id=sm.vrf_id,
962                 protocol=sm.protocol,
963                 twice_nat=sm.twice_nat,
964                 self_twice_nat=sm.self_twice_nat,
965                 out2in_only=sm.out2in_only,
966                 tag=sm.tag,
967                 external_sw_if_index=sm.external_sw_if_index,
968                 is_add=0)
969
970         lb_static_mappings = self.vapi.nat44_lb_static_mapping_dump()
971         for lb_sm in lb_static_mappings:
972             self.vapi.nat44_add_del_lb_static_mapping(
973                 lb_sm.external_addr,
974                 lb_sm.external_port,
975                 lb_sm.protocol,
976                 vrf_id=lb_sm.vrf_id,
977                 twice_nat=lb_sm.twice_nat,
978                 self_twice_nat=lb_sm.self_twice_nat,
979                 out2in_only=lb_sm.out2in_only,
980                 tag=lb_sm.tag,
981                 is_add=0,
982                 local_num=0,
983                 locals=[])
984
985         identity_mappings = self.vapi.nat44_identity_mapping_dump()
986         for id_m in identity_mappings:
987             self.vapi.nat44_add_del_identity_mapping(
988                 addr_only=id_m.addr_only,
989                 ip=id_m.ip_address,
990                 port=id_m.port,
991                 sw_if_index=id_m.sw_if_index,
992                 vrf_id=id_m.vrf_id,
993                 protocol=id_m.protocol,
994                 is_add=0)
995
996         adresses = self.vapi.nat44_address_dump()
997         for addr in adresses:
998             self.vapi.nat44_add_del_address_range(addr.ip_address,
999                                                   addr.ip_address,
1000                                                   twice_nat=addr.twice_nat,
1001                                                   is_add=0)
1002
1003         self.vapi.nat_set_reass()
1004         self.vapi.nat_set_reass(is_ip6=1)
1005
1006     def nat44_add_static_mapping(self, local_ip, external_ip='0.0.0.0',
1007                                  local_port=0, external_port=0, vrf_id=0,
1008                                  is_add=1, external_sw_if_index=0xFFFFFFFF,
1009                                  proto=0, twice_nat=0, self_twice_nat=0,
1010                                  out2in_only=0, tag=""):
1011         """
1012         Add/delete NAT44 static mapping
1013
1014         :param local_ip: Local IP address
1015         :param external_ip: External IP address
1016         :param local_port: Local port number (Optional)
1017         :param external_port: External port number (Optional)
1018         :param vrf_id: VRF ID (Default 0)
1019         :param is_add: 1 if add, 0 if delete (Default add)
1020         :param external_sw_if_index: External interface instead of IP address
1021         :param proto: IP protocol (Mandatory if port specified)
1022         :param twice_nat: 1 if translate external host address and port
1023         :param self_twice_nat: 1 if translate external host address and port
1024                                whenever external host address equals
1025                                local address of internal host
1026         :param out2in_only: if 1 rule is matching only out2in direction
1027         :param tag: Opaque string tag
1028         """
1029         addr_only = 1
1030         if local_port and external_port:
1031             addr_only = 0
1032         l_ip = socket.inet_pton(socket.AF_INET, local_ip)
1033         e_ip = socket.inet_pton(socket.AF_INET, external_ip)
1034         self.vapi.nat44_add_del_static_mapping(
1035             l_ip,
1036             e_ip,
1037             external_sw_if_index,
1038             local_port,
1039             external_port,
1040             addr_only,
1041             vrf_id,
1042             proto,
1043             twice_nat,
1044             self_twice_nat,
1045             out2in_only,
1046             tag,
1047             is_add)
1048
1049     def nat44_add_address(self, ip, is_add=1, vrf_id=0xFFFFFFFF, twice_nat=0):
1050         """
1051         Add/delete NAT44 address
1052
1053         :param ip: IP address
1054         :param is_add: 1 if add, 0 if delete (Default add)
1055         :param twice_nat: twice NAT address for extenal hosts
1056         """
1057         nat_addr = socket.inet_pton(socket.AF_INET, ip)
1058         self.vapi.nat44_add_del_address_range(nat_addr, nat_addr, is_add,
1059                                               vrf_id=vrf_id,
1060                                               twice_nat=twice_nat)
1061
1062     def test_dynamic(self):
1063         """ NAT44 dynamic translation test """
1064
1065         self.nat44_add_address(self.nat_addr)
1066         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1067         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1068                                                   is_inside=0)
1069
1070         # in2out
1071         pkts = self.create_stream_in(self.pg0, self.pg1)
1072         self.pg0.add_stream(pkts)
1073         self.pg_enable_capture(self.pg_interfaces)
1074         self.pg_start()
1075         capture = self.pg1.get_capture(len(pkts))
1076         self.verify_capture_out(capture)
1077
1078         # out2in
1079         pkts = self.create_stream_out(self.pg1)
1080         self.pg1.add_stream(pkts)
1081         self.pg_enable_capture(self.pg_interfaces)
1082         self.pg_start()
1083         capture = self.pg0.get_capture(len(pkts))
1084         self.verify_capture_in(capture, self.pg0)
1085
1086     def test_dynamic_icmp_errors_in2out_ttl_1(self):
1087         """ NAT44 handling of client packets with TTL=1 """
1088
1089         self.nat44_add_address(self.nat_addr)
1090         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1091         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1092                                                   is_inside=0)
1093
1094         # Client side - generate traffic
1095         pkts = self.create_stream_in(self.pg0, self.pg1, ttl=1)
1096         self.pg0.add_stream(pkts)
1097         self.pg_enable_capture(self.pg_interfaces)
1098         self.pg_start()
1099
1100         # Client side - verify ICMP type 11 packets
1101         capture = self.pg0.get_capture(len(pkts))
1102         self.verify_capture_in_with_icmp_errors(capture, self.pg0)
1103
1104     def test_dynamic_icmp_errors_out2in_ttl_1(self):
1105         """ NAT44 handling of server packets with TTL=1 """
1106
1107         self.nat44_add_address(self.nat_addr)
1108         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1109         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1110                                                   is_inside=0)
1111
1112         # Client side - create sessions
1113         pkts = self.create_stream_in(self.pg0, self.pg1)
1114         self.pg0.add_stream(pkts)
1115         self.pg_enable_capture(self.pg_interfaces)
1116         self.pg_start()
1117
1118         # Server side - generate traffic
1119         capture = self.pg1.get_capture(len(pkts))
1120         self.verify_capture_out(capture)
1121         pkts = self.create_stream_out(self.pg1, ttl=1)
1122         self.pg1.add_stream(pkts)
1123         self.pg_enable_capture(self.pg_interfaces)
1124         self.pg_start()
1125
1126         # Server side - verify ICMP type 11 packets
1127         capture = self.pg1.get_capture(len(pkts))
1128         self.verify_capture_out_with_icmp_errors(capture,
1129                                                  src_ip=self.pg1.local_ip4)
1130
1131     def test_dynamic_icmp_errors_in2out_ttl_2(self):
1132         """ NAT44 handling of error responses to client packets with TTL=2 """
1133
1134         self.nat44_add_address(self.nat_addr)
1135         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1136         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1137                                                   is_inside=0)
1138
1139         # Client side - generate traffic
1140         pkts = self.create_stream_in(self.pg0, self.pg1, ttl=2)
1141         self.pg0.add_stream(pkts)
1142         self.pg_enable_capture(self.pg_interfaces)
1143         self.pg_start()
1144
1145         # Server side - simulate ICMP type 11 response
1146         capture = self.pg1.get_capture(len(pkts))
1147         pkts = [Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1148                 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
1149                 ICMP(type=11) / packet[IP] for packet in capture]
1150         self.pg1.add_stream(pkts)
1151         self.pg_enable_capture(self.pg_interfaces)
1152         self.pg_start()
1153
1154         # Client side - verify ICMP type 11 packets
1155         capture = self.pg0.get_capture(len(pkts))
1156         self.verify_capture_in_with_icmp_errors(capture, self.pg0)
1157
1158     def test_dynamic_icmp_errors_out2in_ttl_2(self):
1159         """ NAT44 handling of error responses to server packets with TTL=2 """
1160
1161         self.nat44_add_address(self.nat_addr)
1162         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1163         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1164                                                   is_inside=0)
1165
1166         # Client side - create sessions
1167         pkts = self.create_stream_in(self.pg0, self.pg1)
1168         self.pg0.add_stream(pkts)
1169         self.pg_enable_capture(self.pg_interfaces)
1170         self.pg_start()
1171
1172         # Server side - generate traffic
1173         capture = self.pg1.get_capture(len(pkts))
1174         self.verify_capture_out(capture)
1175         pkts = self.create_stream_out(self.pg1, ttl=2)
1176         self.pg1.add_stream(pkts)
1177         self.pg_enable_capture(self.pg_interfaces)
1178         self.pg_start()
1179
1180         # Client side - simulate ICMP type 11 response
1181         capture = self.pg0.get_capture(len(pkts))
1182         pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1183                 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
1184                 ICMP(type=11) / packet[IP] for packet in capture]
1185         self.pg0.add_stream(pkts)
1186         self.pg_enable_capture(self.pg_interfaces)
1187         self.pg_start()
1188
1189         # Server side - verify ICMP type 11 packets
1190         capture = self.pg1.get_capture(len(pkts))
1191         self.verify_capture_out_with_icmp_errors(capture)
1192
1193     def test_ping_out_interface_from_outside(self):
1194         """ Ping NAT44 out interface from outside network """
1195
1196         self.nat44_add_address(self.nat_addr)
1197         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1198         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1199                                                   is_inside=0)
1200
1201         p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1202              IP(src=self.pg1.remote_ip4, dst=self.pg1.local_ip4) /
1203              ICMP(id=self.icmp_id_out, type='echo-request'))
1204         pkts = [p]
1205         self.pg1.add_stream(pkts)
1206         self.pg_enable_capture(self.pg_interfaces)
1207         self.pg_start()
1208         capture = self.pg1.get_capture(len(pkts))
1209         self.assertEqual(1, len(capture))
1210         packet = capture[0]
1211         try:
1212             self.assertEqual(packet[IP].src, self.pg1.local_ip4)
1213             self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
1214             self.assertEqual(packet[ICMP].id, self.icmp_id_in)
1215             self.assertEqual(packet[ICMP].type, 0)  # echo reply
1216         except:
1217             self.logger.error(ppp("Unexpected or invalid packet "
1218                                   "(outside network):", packet))
1219             raise
1220
1221     def test_ping_internal_host_from_outside(self):
1222         """ Ping internal host from outside network """
1223
1224         self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr)
1225         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1226         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1227                                                   is_inside=0)
1228
1229         # out2in
1230         pkt = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1231                IP(src=self.pg1.remote_ip4, dst=self.nat_addr, ttl=64) /
1232                ICMP(id=self.icmp_id_out, type='echo-request'))
1233         self.pg1.add_stream(pkt)
1234         self.pg_enable_capture(self.pg_interfaces)
1235         self.pg_start()
1236         capture = self.pg0.get_capture(1)
1237         self.verify_capture_in(capture, self.pg0, packet_num=1)
1238         self.assert_equal(capture[0][IP].proto, IP_PROTOS.icmp)
1239
1240         # in2out
1241         pkt = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1242                IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4, ttl=64) /
1243                ICMP(id=self.icmp_id_in, type='echo-reply'))
1244         self.pg0.add_stream(pkt)
1245         self.pg_enable_capture(self.pg_interfaces)
1246         self.pg_start()
1247         capture = self.pg1.get_capture(1)
1248         self.verify_capture_out(capture, same_port=True, packet_num=1)
1249         self.assert_equal(capture[0][IP].proto, IP_PROTOS.icmp)
1250
1251     def test_forwarding(self):
1252         """ NAT44 forwarding test """
1253
1254         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1255         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1256                                                   is_inside=0)
1257         self.vapi.nat44_forwarding_enable_disable(1)
1258
1259         real_ip = self.pg0.remote_ip4n
1260         alias_ip = self.nat_addr_n
1261         self.vapi.nat44_add_del_static_mapping(local_ip=real_ip,
1262                                                external_ip=alias_ip)
1263
1264         try:
1265             # in2out - static mapping match
1266
1267             pkts = self.create_stream_out(self.pg1)
1268             self.pg1.add_stream(pkts)
1269             self.pg_enable_capture(self.pg_interfaces)
1270             self.pg_start()
1271             capture = self.pg0.get_capture(len(pkts))
1272             self.verify_capture_in(capture, self.pg0)
1273
1274             pkts = self.create_stream_in(self.pg0, self.pg1)
1275             self.pg0.add_stream(pkts)
1276             self.pg_enable_capture(self.pg_interfaces)
1277             self.pg_start()
1278             capture = self.pg1.get_capture(len(pkts))
1279             self.verify_capture_out(capture, same_port=True)
1280
1281             # in2out - no static mapping match
1282
1283             host0 = self.pg0.remote_hosts[0]
1284             self.pg0.remote_hosts[0] = self.pg0.remote_hosts[1]
1285             try:
1286                 pkts = self.create_stream_out(self.pg1,
1287                                               dst_ip=self.pg0.remote_ip4,
1288                                               use_inside_ports=True)
1289                 self.pg1.add_stream(pkts)
1290                 self.pg_enable_capture(self.pg_interfaces)
1291                 self.pg_start()
1292                 capture = self.pg0.get_capture(len(pkts))
1293                 self.verify_capture_in(capture, self.pg0)
1294
1295                 pkts = self.create_stream_in(self.pg0, self.pg1)
1296                 self.pg0.add_stream(pkts)
1297                 self.pg_enable_capture(self.pg_interfaces)
1298                 self.pg_start()
1299                 capture = self.pg1.get_capture(len(pkts))
1300                 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
1301                                         same_port=True)
1302             finally:
1303                 self.pg0.remote_hosts[0] = host0
1304
1305             user = self.pg0.remote_hosts[1]
1306             sessions = self.vapi.nat44_user_session_dump(user.ip4n, 0)
1307             self.assertEqual(len(sessions), 3)
1308             self.assertTrue(sessions[0].ext_host_valid)
1309             self.vapi.nat44_del_session(
1310                 sessions[0].inside_ip_address,
1311                 sessions[0].inside_port,
1312                 sessions[0].protocol,
1313                 ext_host_address=sessions[0].ext_host_address,
1314                 ext_host_port=sessions[0].ext_host_port)
1315             sessions = self.vapi.nat44_user_session_dump(user.ip4n, 0)
1316             self.assertEqual(len(sessions), 2)
1317
1318         finally:
1319             self.vapi.nat44_forwarding_enable_disable(0)
1320             self.vapi.nat44_add_del_static_mapping(local_ip=real_ip,
1321                                                    external_ip=alias_ip,
1322                                                    is_add=0)
1323
1324     def test_static_in(self):
1325         """ 1:1 NAT initialized from inside network """
1326
1327         nat_ip = "10.0.0.10"
1328         self.tcp_port_out = 6303
1329         self.udp_port_out = 6304
1330         self.icmp_id_out = 6305
1331
1332         self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
1333         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1334         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1335                                                   is_inside=0)
1336         sm = self.vapi.nat44_static_mapping_dump()
1337         self.assertEqual(len(sm), 1)
1338         self.assertEqual((sm[0].tag).split('\0', 1)[0], '')
1339         self.assertEqual(sm[0].protocol, 0)
1340         self.assertEqual(sm[0].local_port, 0)
1341         self.assertEqual(sm[0].external_port, 0)
1342
1343         # in2out
1344         pkts = self.create_stream_in(self.pg0, self.pg1)
1345         self.pg0.add_stream(pkts)
1346         self.pg_enable_capture(self.pg_interfaces)
1347         self.pg_start()
1348         capture = self.pg1.get_capture(len(pkts))
1349         self.verify_capture_out(capture, nat_ip, True)
1350
1351         # out2in
1352         pkts = self.create_stream_out(self.pg1, nat_ip)
1353         self.pg1.add_stream(pkts)
1354         self.pg_enable_capture(self.pg_interfaces)
1355         self.pg_start()
1356         capture = self.pg0.get_capture(len(pkts))
1357         self.verify_capture_in(capture, self.pg0)
1358
1359     def test_static_out(self):
1360         """ 1:1 NAT initialized from outside network """
1361
1362         nat_ip = "10.0.0.20"
1363         self.tcp_port_out = 6303
1364         self.udp_port_out = 6304
1365         self.icmp_id_out = 6305
1366         tag = "testTAG"
1367
1368         self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip, tag=tag)
1369         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1370         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1371                                                   is_inside=0)
1372         sm = self.vapi.nat44_static_mapping_dump()
1373         self.assertEqual(len(sm), 1)
1374         self.assertEqual((sm[0].tag).split('\0', 1)[0], tag)
1375
1376         # out2in
1377         pkts = self.create_stream_out(self.pg1, nat_ip)
1378         self.pg1.add_stream(pkts)
1379         self.pg_enable_capture(self.pg_interfaces)
1380         self.pg_start()
1381         capture = self.pg0.get_capture(len(pkts))
1382         self.verify_capture_in(capture, self.pg0)
1383
1384         # in2out
1385         pkts = self.create_stream_in(self.pg0, self.pg1)
1386         self.pg0.add_stream(pkts)
1387         self.pg_enable_capture(self.pg_interfaces)
1388         self.pg_start()
1389         capture = self.pg1.get_capture(len(pkts))
1390         self.verify_capture_out(capture, nat_ip, True)
1391
1392     def test_static_with_port_in(self):
1393         """ 1:1 NAPT initialized from inside network """
1394
1395         self.tcp_port_out = 3606
1396         self.udp_port_out = 3607
1397         self.icmp_id_out = 3608
1398
1399         self.nat44_add_address(self.nat_addr)
1400         self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1401                                       self.tcp_port_in, self.tcp_port_out,
1402                                       proto=IP_PROTOS.tcp)
1403         self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1404                                       self.udp_port_in, self.udp_port_out,
1405                                       proto=IP_PROTOS.udp)
1406         self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1407                                       self.icmp_id_in, self.icmp_id_out,
1408                                       proto=IP_PROTOS.icmp)
1409         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1410         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1411                                                   is_inside=0)
1412
1413         # in2out
1414         pkts = self.create_stream_in(self.pg0, self.pg1)
1415         self.pg0.add_stream(pkts)
1416         self.pg_enable_capture(self.pg_interfaces)
1417         self.pg_start()
1418         capture = self.pg1.get_capture(len(pkts))
1419         self.verify_capture_out(capture)
1420
1421         # out2in
1422         pkts = self.create_stream_out(self.pg1)
1423         self.pg1.add_stream(pkts)
1424         self.pg_enable_capture(self.pg_interfaces)
1425         self.pg_start()
1426         capture = self.pg0.get_capture(len(pkts))
1427         self.verify_capture_in(capture, self.pg0)
1428
1429     def test_static_with_port_out(self):
1430         """ 1:1 NAPT initialized from outside network """
1431
1432         self.tcp_port_out = 30606
1433         self.udp_port_out = 30607
1434         self.icmp_id_out = 30608
1435
1436         self.nat44_add_address(self.nat_addr)
1437         self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1438                                       self.tcp_port_in, self.tcp_port_out,
1439                                       proto=IP_PROTOS.tcp)
1440         self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1441                                       self.udp_port_in, self.udp_port_out,
1442                                       proto=IP_PROTOS.udp)
1443         self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1444                                       self.icmp_id_in, self.icmp_id_out,
1445                                       proto=IP_PROTOS.icmp)
1446         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1447         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1448                                                   is_inside=0)
1449
1450         # out2in
1451         pkts = self.create_stream_out(self.pg1)
1452         self.pg1.add_stream(pkts)
1453         self.pg_enable_capture(self.pg_interfaces)
1454         self.pg_start()
1455         capture = self.pg0.get_capture(len(pkts))
1456         self.verify_capture_in(capture, self.pg0)
1457
1458         # in2out
1459         pkts = self.create_stream_in(self.pg0, self.pg1)
1460         self.pg0.add_stream(pkts)
1461         self.pg_enable_capture(self.pg_interfaces)
1462         self.pg_start()
1463         capture = self.pg1.get_capture(len(pkts))
1464         self.verify_capture_out(capture)
1465
1466     def test_static_with_port_out2(self):
1467         """ 1:1 NAPT symmetrical rule """
1468
1469         external_port = 80
1470         local_port = 8080
1471
1472         self.vapi.nat44_forwarding_enable_disable(1)
1473         self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1474                                       local_port, external_port,
1475                                       proto=IP_PROTOS.tcp, out2in_only=1)
1476         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1477         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1478                                                   is_inside=0)
1479
1480         # from client to service
1481         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
1482              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
1483              TCP(sport=12345, dport=external_port))
1484         self.pg1.add_stream(p)
1485         self.pg_enable_capture(self.pg_interfaces)
1486         self.pg_start()
1487         capture = self.pg0.get_capture(1)
1488         p = capture[0]
1489         try:
1490             ip = p[IP]
1491             tcp = p[TCP]
1492             self.assertEqual(ip.dst, self.pg0.remote_ip4)
1493             self.assertEqual(tcp.dport, local_port)
1494             self.assert_packet_checksums_valid(p)
1495         except:
1496             self.logger.error(ppp("Unexpected or invalid packet:", p))
1497             raise
1498
1499         # ICMP error
1500         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1501              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
1502              ICMP(type=11) / capture[0][IP])
1503         self.pg0.add_stream(p)
1504         self.pg_enable_capture(self.pg_interfaces)
1505         self.pg_start()
1506         capture = self.pg1.get_capture(1)
1507         p = capture[0]
1508         try:
1509             self.assertEqual(p[IP].src, self.nat_addr)
1510             inner = p[IPerror]
1511             self.assertEqual(inner.dst, self.nat_addr)
1512             self.assertEqual(inner[TCPerror].dport, external_port)
1513         except:
1514             self.logger.error(ppp("Unexpected or invalid packet:", p))
1515             raise
1516
1517         # from service back to client
1518         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
1519              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
1520              TCP(sport=local_port, dport=12345))
1521         self.pg0.add_stream(p)
1522         self.pg_enable_capture(self.pg_interfaces)
1523         self.pg_start()
1524         capture = self.pg1.get_capture(1)
1525         p = capture[0]
1526         try:
1527             ip = p[IP]
1528             tcp = p[TCP]
1529             self.assertEqual(ip.src, self.nat_addr)
1530             self.assertEqual(tcp.sport, external_port)
1531             self.assert_packet_checksums_valid(p)
1532         except:
1533             self.logger.error(ppp("Unexpected or invalid packet:", p))
1534             raise
1535
1536         # ICMP error
1537         p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1538              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
1539              ICMP(type=11) / capture[0][IP])
1540         self.pg1.add_stream(p)
1541         self.pg_enable_capture(self.pg_interfaces)
1542         self.pg_start()
1543         capture = self.pg0.get_capture(1)
1544         p = capture[0]
1545         try:
1546             self.assertEqual(p[IP].dst, self.pg0.remote_ip4)
1547             inner = p[IPerror]
1548             self.assertEqual(inner.src, self.pg0.remote_ip4)
1549             self.assertEqual(inner[TCPerror].sport, local_port)
1550         except:
1551             self.logger.error(ppp("Unexpected or invalid packet:", p))
1552             raise
1553
1554         # from client to server (no translation)
1555         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
1556              IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
1557              TCP(sport=12346, dport=local_port))
1558         self.pg1.add_stream(p)
1559         self.pg_enable_capture(self.pg_interfaces)
1560         self.pg_start()
1561         capture = self.pg0.get_capture(1)
1562         p = capture[0]
1563         try:
1564             ip = p[IP]
1565             tcp = p[TCP]
1566             self.assertEqual(ip.dst, self.pg0.remote_ip4)
1567             self.assertEqual(tcp.dport, local_port)
1568             self.assert_packet_checksums_valid(p)
1569         except:
1570             self.logger.error(ppp("Unexpected or invalid packet:", p))
1571             raise
1572
1573         # from service back to client (no translation)
1574         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
1575              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
1576              TCP(sport=local_port, dport=12346))
1577         self.pg0.add_stream(p)
1578         self.pg_enable_capture(self.pg_interfaces)
1579         self.pg_start()
1580         capture = self.pg1.get_capture(1)
1581         p = capture[0]
1582         try:
1583             ip = p[IP]
1584             tcp = p[TCP]
1585             self.assertEqual(ip.src, self.pg0.remote_ip4)
1586             self.assertEqual(tcp.sport, local_port)
1587             self.assert_packet_checksums_valid(p)
1588         except:
1589             self.logger.error(ppp("Unexpected or invalid packet:", p))
1590             raise
1591
1592     def test_static_vrf_aware(self):
1593         """ 1:1 NAT VRF awareness """
1594
1595         nat_ip1 = "10.0.0.30"
1596         nat_ip2 = "10.0.0.40"
1597         self.tcp_port_out = 6303
1598         self.udp_port_out = 6304
1599         self.icmp_id_out = 6305
1600
1601         self.nat44_add_static_mapping(self.pg4.remote_ip4, nat_ip1,
1602                                       vrf_id=10)
1603         self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip2,
1604                                       vrf_id=10)
1605         self.vapi.nat44_interface_add_del_feature(self.pg3.sw_if_index,
1606                                                   is_inside=0)
1607         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1608         self.vapi.nat44_interface_add_del_feature(self.pg4.sw_if_index)
1609
1610         # inside interface VRF match NAT44 static mapping VRF
1611         pkts = self.create_stream_in(self.pg4, self.pg3)
1612         self.pg4.add_stream(pkts)
1613         self.pg_enable_capture(self.pg_interfaces)
1614         self.pg_start()
1615         capture = self.pg3.get_capture(len(pkts))
1616         self.verify_capture_out(capture, nat_ip1, True)
1617
1618         # inside interface VRF don't match NAT44 static mapping VRF (packets
1619         # are dropped)
1620         pkts = self.create_stream_in(self.pg0, self.pg3)
1621         self.pg0.add_stream(pkts)
1622         self.pg_enable_capture(self.pg_interfaces)
1623         self.pg_start()
1624         self.pg3.assert_nothing_captured()
1625
1626     def test_dynamic_to_static(self):
1627         """ Switch from dynamic translation to 1:1NAT """
1628         nat_ip = "10.0.0.10"
1629         self.tcp_port_out = 6303
1630         self.udp_port_out = 6304
1631         self.icmp_id_out = 6305
1632
1633         self.nat44_add_address(self.nat_addr)
1634         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1635         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1636                                                   is_inside=0)
1637
1638         # dynamic
1639         pkts = self.create_stream_in(self.pg0, self.pg1)
1640         self.pg0.add_stream(pkts)
1641         self.pg_enable_capture(self.pg_interfaces)
1642         self.pg_start()
1643         capture = self.pg1.get_capture(len(pkts))
1644         self.verify_capture_out(capture)
1645
1646         # 1:1NAT
1647         self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
1648         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
1649         self.assertEqual(len(sessions), 0)
1650         pkts = self.create_stream_in(self.pg0, self.pg1)
1651         self.pg0.add_stream(pkts)
1652         self.pg_enable_capture(self.pg_interfaces)
1653         self.pg_start()
1654         capture = self.pg1.get_capture(len(pkts))
1655         self.verify_capture_out(capture, nat_ip, True)
1656
1657     def test_identity_nat(self):
1658         """ Identity NAT """
1659
1660         self.vapi.nat44_add_del_identity_mapping(ip=self.pg0.remote_ip4n)
1661         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1662         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1663                                                   is_inside=0)
1664
1665         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
1666              IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
1667              TCP(sport=12345, dport=56789))
1668         self.pg1.add_stream(p)
1669         self.pg_enable_capture(self.pg_interfaces)
1670         self.pg_start()
1671         capture = self.pg0.get_capture(1)
1672         p = capture[0]
1673         try:
1674             ip = p[IP]
1675             tcp = p[TCP]
1676             self.assertEqual(ip.dst, self.pg0.remote_ip4)
1677             self.assertEqual(ip.src, self.pg1.remote_ip4)
1678             self.assertEqual(tcp.dport, 56789)
1679             self.assertEqual(tcp.sport, 12345)
1680             self.assert_packet_checksums_valid(p)
1681         except:
1682             self.logger.error(ppp("Unexpected or invalid packet:", p))
1683             raise
1684
1685     def test_static_lb(self):
1686         """ NAT44 local service load balancing """
1687         external_addr_n = socket.inet_pton(socket.AF_INET, self.nat_addr)
1688         external_port = 80
1689         local_port = 8080
1690         server1 = self.pg0.remote_hosts[0]
1691         server2 = self.pg0.remote_hosts[1]
1692
1693         locals = [{'addr': server1.ip4n,
1694                    'port': local_port,
1695                    'probability': 70},
1696                   {'addr': server2.ip4n,
1697                    'port': local_port,
1698                    'probability': 30}]
1699
1700         self.nat44_add_address(self.nat_addr)
1701         self.vapi.nat44_add_del_lb_static_mapping(external_addr_n,
1702                                                   external_port,
1703                                                   IP_PROTOS.tcp,
1704                                                   local_num=len(locals),
1705                                                   locals=locals)
1706         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1707         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1708                                                   is_inside=0)
1709
1710         # from client to service
1711         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
1712              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
1713              TCP(sport=12345, dport=external_port))
1714         self.pg1.add_stream(p)
1715         self.pg_enable_capture(self.pg_interfaces)
1716         self.pg_start()
1717         capture = self.pg0.get_capture(1)
1718         p = capture[0]
1719         server = None
1720         try:
1721             ip = p[IP]
1722             tcp = p[TCP]
1723             self.assertIn(ip.dst, [server1.ip4, server2.ip4])
1724             if ip.dst == server1.ip4:
1725                 server = server1
1726             else:
1727                 server = server2
1728             self.assertEqual(tcp.dport, local_port)
1729             self.assert_packet_checksums_valid(p)
1730         except:
1731             self.logger.error(ppp("Unexpected or invalid packet:", p))
1732             raise
1733
1734         # from service back to client
1735         p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
1736              IP(src=server.ip4, dst=self.pg1.remote_ip4) /
1737              TCP(sport=local_port, dport=12345))
1738         self.pg0.add_stream(p)
1739         self.pg_enable_capture(self.pg_interfaces)
1740         self.pg_start()
1741         capture = self.pg1.get_capture(1)
1742         p = capture[0]
1743         try:
1744             ip = p[IP]
1745             tcp = p[TCP]
1746             self.assertEqual(ip.src, self.nat_addr)
1747             self.assertEqual(tcp.sport, external_port)
1748             self.assert_packet_checksums_valid(p)
1749         except:
1750             self.logger.error(ppp("Unexpected or invalid packet:", p))
1751             raise
1752
1753         sessions = self.vapi.nat44_user_session_dump(server.ip4n, 0)
1754         self.assertEqual(len(sessions), 1)
1755         self.assertTrue(sessions[0].ext_host_valid)
1756         self.vapi.nat44_del_session(
1757             sessions[0].inside_ip_address,
1758             sessions[0].inside_port,
1759             sessions[0].protocol,
1760             ext_host_address=sessions[0].ext_host_address,
1761             ext_host_port=sessions[0].ext_host_port)
1762         sessions = self.vapi.nat44_user_session_dump(server.ip4n, 0)
1763         self.assertEqual(len(sessions), 0)
1764
1765     @unittest.skipUnless(running_extended_tests(), "part of extended tests")
1766     def test_static_lb_multi_clients(self):
1767         """ NAT44 local service load balancing - multiple clients"""
1768
1769         external_addr_n = socket.inet_pton(socket.AF_INET, self.nat_addr)
1770         external_port = 80
1771         local_port = 8080
1772         server1 = self.pg0.remote_hosts[0]
1773         server2 = self.pg0.remote_hosts[1]
1774
1775         locals = [{'addr': server1.ip4n,
1776                    'port': local_port,
1777                    'probability': 90},
1778                   {'addr': server2.ip4n,
1779                    'port': local_port,
1780                    'probability': 10}]
1781
1782         self.nat44_add_address(self.nat_addr)
1783         self.vapi.nat44_add_del_lb_static_mapping(external_addr_n,
1784                                                   external_port,
1785                                                   IP_PROTOS.tcp,
1786                                                   local_num=len(locals),
1787                                                   locals=locals)
1788         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1789         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1790                                                   is_inside=0)
1791
1792         server1_n = 0
1793         server2_n = 0
1794         clients = ip4_range(self.pg1.remote_ip4, 10, 50)
1795         pkts = []
1796         for client in clients:
1797             p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
1798                  IP(src=client, dst=self.nat_addr) /
1799                  TCP(sport=12345, dport=external_port))
1800             pkts.append(p)
1801         self.pg1.add_stream(pkts)
1802         self.pg_enable_capture(self.pg_interfaces)
1803         self.pg_start()
1804         capture = self.pg0.get_capture(len(pkts))
1805         for p in capture:
1806             if p[IP].dst == server1.ip4:
1807                 server1_n += 1
1808             else:
1809                 server2_n += 1
1810         self.assertTrue(server1_n > server2_n)
1811
1812     def test_static_lb_2(self):
1813         """ NAT44 local service load balancing (asymmetrical rule) """
1814         external_addr_n = socket.inet_pton(socket.AF_INET, self.nat_addr)
1815         external_port = 80
1816         local_port = 8080
1817         server1 = self.pg0.remote_hosts[0]
1818         server2 = self.pg0.remote_hosts[1]
1819
1820         locals = [{'addr': server1.ip4n,
1821                    'port': local_port,
1822                    'probability': 70},
1823                   {'addr': server2.ip4n,
1824                    'port': local_port,
1825                    'probability': 30}]
1826
1827         self.vapi.nat44_forwarding_enable_disable(1)
1828         self.vapi.nat44_add_del_lb_static_mapping(external_addr_n,
1829                                                   external_port,
1830                                                   IP_PROTOS.tcp,
1831                                                   out2in_only=1,
1832                                                   local_num=len(locals),
1833                                                   locals=locals)
1834         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1835         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1836                                                   is_inside=0)
1837
1838         # from client to service
1839         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
1840              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
1841              TCP(sport=12345, dport=external_port))
1842         self.pg1.add_stream(p)
1843         self.pg_enable_capture(self.pg_interfaces)
1844         self.pg_start()
1845         capture = self.pg0.get_capture(1)
1846         p = capture[0]
1847         server = None
1848         try:
1849             ip = p[IP]
1850             tcp = p[TCP]
1851             self.assertIn(ip.dst, [server1.ip4, server2.ip4])
1852             if ip.dst == server1.ip4:
1853                 server = server1
1854             else:
1855                 server = server2
1856             self.assertEqual(tcp.dport, local_port)
1857             self.assert_packet_checksums_valid(p)
1858         except:
1859             self.logger.error(ppp("Unexpected or invalid packet:", p))
1860             raise
1861
1862         # from service back to client
1863         p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
1864              IP(src=server.ip4, dst=self.pg1.remote_ip4) /
1865              TCP(sport=local_port, dport=12345))
1866         self.pg0.add_stream(p)
1867         self.pg_enable_capture(self.pg_interfaces)
1868         self.pg_start()
1869         capture = self.pg1.get_capture(1)
1870         p = capture[0]
1871         try:
1872             ip = p[IP]
1873             tcp = p[TCP]
1874             self.assertEqual(ip.src, self.nat_addr)
1875             self.assertEqual(tcp.sport, external_port)
1876             self.assert_packet_checksums_valid(p)
1877         except:
1878             self.logger.error(ppp("Unexpected or invalid packet:", p))
1879             raise
1880
1881         # from client to server (no translation)
1882         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
1883              IP(src=self.pg1.remote_ip4, dst=server1.ip4) /
1884              TCP(sport=12346, dport=local_port))
1885         self.pg1.add_stream(p)
1886         self.pg_enable_capture(self.pg_interfaces)
1887         self.pg_start()
1888         capture = self.pg0.get_capture(1)
1889         p = capture[0]
1890         server = None
1891         try:
1892             ip = p[IP]
1893             tcp = p[TCP]
1894             self.assertEqual(ip.dst, server1.ip4)
1895             self.assertEqual(tcp.dport, local_port)
1896             self.assert_packet_checksums_valid(p)
1897         except:
1898             self.logger.error(ppp("Unexpected or invalid packet:", p))
1899             raise
1900
1901         # from service back to client (no translation)
1902         p = (Ether(src=server1.mac, dst=self.pg0.local_mac) /
1903              IP(src=server1.ip4, dst=self.pg1.remote_ip4) /
1904              TCP(sport=local_port, dport=12346))
1905         self.pg0.add_stream(p)
1906         self.pg_enable_capture(self.pg_interfaces)
1907         self.pg_start()
1908         capture = self.pg1.get_capture(1)
1909         p = capture[0]
1910         try:
1911             ip = p[IP]
1912             tcp = p[TCP]
1913             self.assertEqual(ip.src, server1.ip4)
1914             self.assertEqual(tcp.sport, local_port)
1915             self.assert_packet_checksums_valid(p)
1916         except:
1917             self.logger.error(ppp("Unexpected or invalid packet:", p))
1918             raise
1919
1920     def test_multiple_inside_interfaces(self):
1921         """ NAT44 multiple non-overlapping address space inside interfaces """
1922
1923         self.nat44_add_address(self.nat_addr)
1924         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1925         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
1926         self.vapi.nat44_interface_add_del_feature(self.pg3.sw_if_index,
1927                                                   is_inside=0)
1928
1929         # between two NAT44 inside interfaces (no translation)
1930         pkts = self.create_stream_in(self.pg0, self.pg1)
1931         self.pg0.add_stream(pkts)
1932         self.pg_enable_capture(self.pg_interfaces)
1933         self.pg_start()
1934         capture = self.pg1.get_capture(len(pkts))
1935         self.verify_capture_no_translation(capture, self.pg0, self.pg1)
1936
1937         # from NAT44 inside to interface without NAT44 feature (no translation)
1938         pkts = self.create_stream_in(self.pg0, self.pg2)
1939         self.pg0.add_stream(pkts)
1940         self.pg_enable_capture(self.pg_interfaces)
1941         self.pg_start()
1942         capture = self.pg2.get_capture(len(pkts))
1943         self.verify_capture_no_translation(capture, self.pg0, self.pg2)
1944
1945         # in2out 1st interface
1946         pkts = self.create_stream_in(self.pg0, self.pg3)
1947         self.pg0.add_stream(pkts)
1948         self.pg_enable_capture(self.pg_interfaces)
1949         self.pg_start()
1950         capture = self.pg3.get_capture(len(pkts))
1951         self.verify_capture_out(capture)
1952
1953         # out2in 1st interface
1954         pkts = self.create_stream_out(self.pg3)
1955         self.pg3.add_stream(pkts)
1956         self.pg_enable_capture(self.pg_interfaces)
1957         self.pg_start()
1958         capture = self.pg0.get_capture(len(pkts))
1959         self.verify_capture_in(capture, self.pg0)
1960
1961         # in2out 2nd interface
1962         pkts = self.create_stream_in(self.pg1, self.pg3)
1963         self.pg1.add_stream(pkts)
1964         self.pg_enable_capture(self.pg_interfaces)
1965         self.pg_start()
1966         capture = self.pg3.get_capture(len(pkts))
1967         self.verify_capture_out(capture)
1968
1969         # out2in 2nd interface
1970         pkts = self.create_stream_out(self.pg3)
1971         self.pg3.add_stream(pkts)
1972         self.pg_enable_capture(self.pg_interfaces)
1973         self.pg_start()
1974         capture = self.pg1.get_capture(len(pkts))
1975         self.verify_capture_in(capture, self.pg1)
1976
1977     def test_inside_overlapping_interfaces(self):
1978         """ NAT44 multiple inside interfaces with overlapping address space """
1979
1980         static_nat_ip = "10.0.0.10"
1981         self.nat44_add_address(self.nat_addr)
1982         self.vapi.nat44_interface_add_del_feature(self.pg3.sw_if_index,
1983                                                   is_inside=0)
1984         self.vapi.nat44_interface_add_del_feature(self.pg4.sw_if_index)
1985         self.vapi.nat44_interface_add_del_feature(self.pg5.sw_if_index)
1986         self.vapi.nat44_interface_add_del_feature(self.pg6.sw_if_index)
1987         self.nat44_add_static_mapping(self.pg6.remote_ip4, static_nat_ip,
1988                                       vrf_id=20)
1989
1990         # between NAT44 inside interfaces with same VRF (no translation)
1991         pkts = self.create_stream_in(self.pg4, self.pg5)
1992         self.pg4.add_stream(pkts)
1993         self.pg_enable_capture(self.pg_interfaces)
1994         self.pg_start()
1995         capture = self.pg5.get_capture(len(pkts))
1996         self.verify_capture_no_translation(capture, self.pg4, self.pg5)
1997
1998         # between NAT44 inside interfaces with different VRF (hairpinning)
1999         p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
2000              IP(src=self.pg4.remote_ip4, dst=static_nat_ip) /
2001              TCP(sport=1234, dport=5678))
2002         self.pg4.add_stream(p)
2003         self.pg_enable_capture(self.pg_interfaces)
2004         self.pg_start()
2005         capture = self.pg6.get_capture(1)
2006         p = capture[0]
2007         try:
2008             ip = p[IP]
2009             tcp = p[TCP]
2010             self.assertEqual(ip.src, self.nat_addr)
2011             self.assertEqual(ip.dst, self.pg6.remote_ip4)
2012             self.assertNotEqual(tcp.sport, 1234)
2013             self.assertEqual(tcp.dport, 5678)
2014         except:
2015             self.logger.error(ppp("Unexpected or invalid packet:", p))
2016             raise
2017
2018         # in2out 1st interface
2019         pkts = self.create_stream_in(self.pg4, self.pg3)
2020         self.pg4.add_stream(pkts)
2021         self.pg_enable_capture(self.pg_interfaces)
2022         self.pg_start()
2023         capture = self.pg3.get_capture(len(pkts))
2024         self.verify_capture_out(capture)
2025
2026         # out2in 1st interface
2027         pkts = self.create_stream_out(self.pg3)
2028         self.pg3.add_stream(pkts)
2029         self.pg_enable_capture(self.pg_interfaces)
2030         self.pg_start()
2031         capture = self.pg4.get_capture(len(pkts))
2032         self.verify_capture_in(capture, self.pg4)
2033
2034         # in2out 2nd interface
2035         pkts = self.create_stream_in(self.pg5, self.pg3)
2036         self.pg5.add_stream(pkts)
2037         self.pg_enable_capture(self.pg_interfaces)
2038         self.pg_start()
2039         capture = self.pg3.get_capture(len(pkts))
2040         self.verify_capture_out(capture)
2041
2042         # out2in 2nd interface
2043         pkts = self.create_stream_out(self.pg3)
2044         self.pg3.add_stream(pkts)
2045         self.pg_enable_capture(self.pg_interfaces)
2046         self.pg_start()
2047         capture = self.pg5.get_capture(len(pkts))
2048         self.verify_capture_in(capture, self.pg5)
2049
2050         # pg5 session dump
2051         addresses = self.vapi.nat44_address_dump()
2052         self.assertEqual(len(addresses), 1)
2053         sessions = self.vapi.nat44_user_session_dump(self.pg5.remote_ip4n, 10)
2054         self.assertEqual(len(sessions), 3)
2055         for session in sessions:
2056             self.assertFalse(session.is_static)
2057             self.assertEqual(session.inside_ip_address[0:4],
2058                              self.pg5.remote_ip4n)
2059             self.assertEqual(session.outside_ip_address,
2060                              addresses[0].ip_address)
2061         self.assertEqual(sessions[0].protocol, IP_PROTOS.tcp)
2062         self.assertEqual(sessions[1].protocol, IP_PROTOS.udp)
2063         self.assertEqual(sessions[2].protocol, IP_PROTOS.icmp)
2064         self.assertEqual(sessions[0].inside_port, self.tcp_port_in)
2065         self.assertEqual(sessions[1].inside_port, self.udp_port_in)
2066         self.assertEqual(sessions[2].inside_port, self.icmp_id_in)
2067         self.assertEqual(sessions[0].outside_port, self.tcp_port_out)
2068         self.assertEqual(sessions[1].outside_port, self.udp_port_out)
2069         self.assertEqual(sessions[2].outside_port, self.icmp_id_out)
2070
2071         # in2out 3rd interface
2072         pkts = self.create_stream_in(self.pg6, self.pg3)
2073         self.pg6.add_stream(pkts)
2074         self.pg_enable_capture(self.pg_interfaces)
2075         self.pg_start()
2076         capture = self.pg3.get_capture(len(pkts))
2077         self.verify_capture_out(capture, static_nat_ip, True)
2078
2079         # out2in 3rd interface
2080         pkts = self.create_stream_out(self.pg3, static_nat_ip)
2081         self.pg3.add_stream(pkts)
2082         self.pg_enable_capture(self.pg_interfaces)
2083         self.pg_start()
2084         capture = self.pg6.get_capture(len(pkts))
2085         self.verify_capture_in(capture, self.pg6)
2086
2087         # general user and session dump verifications
2088         users = self.vapi.nat44_user_dump()
2089         self.assertTrue(len(users) >= 3)
2090         addresses = self.vapi.nat44_address_dump()
2091         self.assertEqual(len(addresses), 1)
2092         for user in users:
2093             sessions = self.vapi.nat44_user_session_dump(user.ip_address,
2094                                                          user.vrf_id)
2095             for session in sessions:
2096                 self.assertEqual(user.ip_address, session.inside_ip_address)
2097                 self.assertTrue(session.total_bytes > session.total_pkts > 0)
2098                 self.assertTrue(session.protocol in
2099                                 [IP_PROTOS.tcp, IP_PROTOS.udp,
2100                                  IP_PROTOS.icmp])
2101                 self.assertFalse(session.ext_host_valid)
2102
2103         # pg4 session dump
2104         sessions = self.vapi.nat44_user_session_dump(self.pg4.remote_ip4n, 10)
2105         self.assertTrue(len(sessions) >= 4)
2106         for session in sessions:
2107             self.assertFalse(session.is_static)
2108             self.assertEqual(session.inside_ip_address[0:4],
2109                              self.pg4.remote_ip4n)
2110             self.assertEqual(session.outside_ip_address,
2111                              addresses[0].ip_address)
2112
2113         # pg6 session dump
2114         sessions = self.vapi.nat44_user_session_dump(self.pg6.remote_ip4n, 20)
2115         self.assertTrue(len(sessions) >= 3)
2116         for session in sessions:
2117             self.assertTrue(session.is_static)
2118             self.assertEqual(session.inside_ip_address[0:4],
2119                              self.pg6.remote_ip4n)
2120             self.assertEqual(map(ord, session.outside_ip_address[0:4]),
2121                              map(int, static_nat_ip.split('.')))
2122             self.assertTrue(session.inside_port in
2123                             [self.tcp_port_in, self.udp_port_in,
2124                              self.icmp_id_in])
2125
2126     def test_hairpinning(self):
2127         """ NAT44 hairpinning - 1:1 NAPT """
2128
2129         host = self.pg0.remote_hosts[0]
2130         server = self.pg0.remote_hosts[1]
2131         host_in_port = 1234
2132         host_out_port = 0
2133         server_in_port = 5678
2134         server_out_port = 8765
2135
2136         self.nat44_add_address(self.nat_addr)
2137         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2138         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2139                                                   is_inside=0)
2140         # add static mapping for server
2141         self.nat44_add_static_mapping(server.ip4, self.nat_addr,
2142                                       server_in_port, server_out_port,
2143                                       proto=IP_PROTOS.tcp)
2144
2145         # send packet from host to server
2146         p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
2147              IP(src=host.ip4, dst=self.nat_addr) /
2148              TCP(sport=host_in_port, dport=server_out_port))
2149         self.pg0.add_stream(p)
2150         self.pg_enable_capture(self.pg_interfaces)
2151         self.pg_start()
2152         capture = self.pg0.get_capture(1)
2153         p = capture[0]
2154         try:
2155             ip = p[IP]
2156             tcp = p[TCP]
2157             self.assertEqual(ip.src, self.nat_addr)
2158             self.assertEqual(ip.dst, server.ip4)
2159             self.assertNotEqual(tcp.sport, host_in_port)
2160             self.assertEqual(tcp.dport, server_in_port)
2161             self.assert_packet_checksums_valid(p)
2162             host_out_port = tcp.sport
2163         except:
2164             self.logger.error(ppp("Unexpected or invalid packet:", p))
2165             raise
2166
2167         # send reply from server to host
2168         p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
2169              IP(src=server.ip4, dst=self.nat_addr) /
2170              TCP(sport=server_in_port, dport=host_out_port))
2171         self.pg0.add_stream(p)
2172         self.pg_enable_capture(self.pg_interfaces)
2173         self.pg_start()
2174         capture = self.pg0.get_capture(1)
2175         p = capture[0]
2176         try:
2177             ip = p[IP]
2178             tcp = p[TCP]
2179             self.assertEqual(ip.src, self.nat_addr)
2180             self.assertEqual(ip.dst, host.ip4)
2181             self.assertEqual(tcp.sport, server_out_port)
2182             self.assertEqual(tcp.dport, host_in_port)
2183             self.assert_packet_checksums_valid(p)
2184         except:
2185             self.logger.error(ppp("Unexpected or invalid packet:", p))
2186             raise
2187
2188     def test_hairpinning2(self):
2189         """ NAT44 hairpinning - 1:1 NAT"""
2190
2191         server1_nat_ip = "10.0.0.10"
2192         server2_nat_ip = "10.0.0.11"
2193         host = self.pg0.remote_hosts[0]
2194         server1 = self.pg0.remote_hosts[1]
2195         server2 = self.pg0.remote_hosts[2]
2196         server_tcp_port = 22
2197         server_udp_port = 20
2198
2199         self.nat44_add_address(self.nat_addr)
2200         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2201         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2202                                                   is_inside=0)
2203
2204         # add static mapping for servers
2205         self.nat44_add_static_mapping(server1.ip4, server1_nat_ip)
2206         self.nat44_add_static_mapping(server2.ip4, server2_nat_ip)
2207
2208         # host to server1
2209         pkts = []
2210         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2211              IP(src=host.ip4, dst=server1_nat_ip) /
2212              TCP(sport=self.tcp_port_in, dport=server_tcp_port))
2213         pkts.append(p)
2214         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2215              IP(src=host.ip4, dst=server1_nat_ip) /
2216              UDP(sport=self.udp_port_in, dport=server_udp_port))
2217         pkts.append(p)
2218         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2219              IP(src=host.ip4, dst=server1_nat_ip) /
2220              ICMP(id=self.icmp_id_in, type='echo-request'))
2221         pkts.append(p)
2222         self.pg0.add_stream(pkts)
2223         self.pg_enable_capture(self.pg_interfaces)
2224         self.pg_start()
2225         capture = self.pg0.get_capture(len(pkts))
2226         for packet in capture:
2227             try:
2228                 self.assertEqual(packet[IP].src, self.nat_addr)
2229                 self.assertEqual(packet[IP].dst, server1.ip4)
2230                 if packet.haslayer(TCP):
2231                     self.assertNotEqual(packet[TCP].sport, self.tcp_port_in)
2232                     self.assertEqual(packet[TCP].dport, server_tcp_port)
2233                     self.tcp_port_out = packet[TCP].sport
2234                     self.assert_packet_checksums_valid(packet)
2235                 elif packet.haslayer(UDP):
2236                     self.assertNotEqual(packet[UDP].sport, self.udp_port_in)
2237                     self.assertEqual(packet[UDP].dport, server_udp_port)
2238                     self.udp_port_out = packet[UDP].sport
2239                 else:
2240                     self.assertNotEqual(packet[ICMP].id, self.icmp_id_in)
2241                     self.icmp_id_out = packet[ICMP].id
2242             except:
2243                 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2244                 raise
2245
2246         # server1 to host
2247         pkts = []
2248         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2249              IP(src=server1.ip4, dst=self.nat_addr) /
2250              TCP(sport=server_tcp_port, dport=self.tcp_port_out))
2251         pkts.append(p)
2252         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2253              IP(src=server1.ip4, dst=self.nat_addr) /
2254              UDP(sport=server_udp_port, dport=self.udp_port_out))
2255         pkts.append(p)
2256         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2257              IP(src=server1.ip4, dst=self.nat_addr) /
2258              ICMP(id=self.icmp_id_out, type='echo-reply'))
2259         pkts.append(p)
2260         self.pg0.add_stream(pkts)
2261         self.pg_enable_capture(self.pg_interfaces)
2262         self.pg_start()
2263         capture = self.pg0.get_capture(len(pkts))
2264         for packet in capture:
2265             try:
2266                 self.assertEqual(packet[IP].src, server1_nat_ip)
2267                 self.assertEqual(packet[IP].dst, host.ip4)
2268                 if packet.haslayer(TCP):
2269                     self.assertEqual(packet[TCP].dport, self.tcp_port_in)
2270                     self.assertEqual(packet[TCP].sport, server_tcp_port)
2271                     self.assert_packet_checksums_valid(packet)
2272                 elif packet.haslayer(UDP):
2273                     self.assertEqual(packet[UDP].dport, self.udp_port_in)
2274                     self.assertEqual(packet[UDP].sport, server_udp_port)
2275                 else:
2276                     self.assertEqual(packet[ICMP].id, self.icmp_id_in)
2277             except:
2278                 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2279                 raise
2280
2281         # server2 to server1
2282         pkts = []
2283         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2284              IP(src=server2.ip4, dst=server1_nat_ip) /
2285              TCP(sport=self.tcp_port_in, dport=server_tcp_port))
2286         pkts.append(p)
2287         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2288              IP(src=server2.ip4, dst=server1_nat_ip) /
2289              UDP(sport=self.udp_port_in, dport=server_udp_port))
2290         pkts.append(p)
2291         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2292              IP(src=server2.ip4, dst=server1_nat_ip) /
2293              ICMP(id=self.icmp_id_in, type='echo-request'))
2294         pkts.append(p)
2295         self.pg0.add_stream(pkts)
2296         self.pg_enable_capture(self.pg_interfaces)
2297         self.pg_start()
2298         capture = self.pg0.get_capture(len(pkts))
2299         for packet in capture:
2300             try:
2301                 self.assertEqual(packet[IP].src, server2_nat_ip)
2302                 self.assertEqual(packet[IP].dst, server1.ip4)
2303                 if packet.haslayer(TCP):
2304                     self.assertEqual(packet[TCP].sport, self.tcp_port_in)
2305                     self.assertEqual(packet[TCP].dport, server_tcp_port)
2306                     self.tcp_port_out = packet[TCP].sport
2307                     self.assert_packet_checksums_valid(packet)
2308                 elif packet.haslayer(UDP):
2309                     self.assertEqual(packet[UDP].sport, self.udp_port_in)
2310                     self.assertEqual(packet[UDP].dport, server_udp_port)
2311                     self.udp_port_out = packet[UDP].sport
2312                 else:
2313                     self.assertEqual(packet[ICMP].id, self.icmp_id_in)
2314                     self.icmp_id_out = packet[ICMP].id
2315             except:
2316                 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2317                 raise
2318
2319         # server1 to server2
2320         pkts = []
2321         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2322              IP(src=server1.ip4, dst=server2_nat_ip) /
2323              TCP(sport=server_tcp_port, dport=self.tcp_port_out))
2324         pkts.append(p)
2325         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2326              IP(src=server1.ip4, dst=server2_nat_ip) /
2327              UDP(sport=server_udp_port, dport=self.udp_port_out))
2328         pkts.append(p)
2329         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2330              IP(src=server1.ip4, dst=server2_nat_ip) /
2331              ICMP(id=self.icmp_id_out, type='echo-reply'))
2332         pkts.append(p)
2333         self.pg0.add_stream(pkts)
2334         self.pg_enable_capture(self.pg_interfaces)
2335         self.pg_start()
2336         capture = self.pg0.get_capture(len(pkts))
2337         for packet in capture:
2338             try:
2339                 self.assertEqual(packet[IP].src, server1_nat_ip)
2340                 self.assertEqual(packet[IP].dst, server2.ip4)
2341                 if packet.haslayer(TCP):
2342                     self.assertEqual(packet[TCP].dport, self.tcp_port_in)
2343                     self.assertEqual(packet[TCP].sport, server_tcp_port)
2344                     self.assert_packet_checksums_valid(packet)
2345                 elif packet.haslayer(UDP):
2346                     self.assertEqual(packet[UDP].dport, self.udp_port_in)
2347                     self.assertEqual(packet[UDP].sport, server_udp_port)
2348                 else:
2349                     self.assertEqual(packet[ICMP].id, self.icmp_id_in)
2350             except:
2351                 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2352                 raise
2353
2354     def test_max_translations_per_user(self):
2355         """ MAX translations per user - recycle the least recently used """
2356
2357         self.nat44_add_address(self.nat_addr)
2358         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2359         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2360                                                   is_inside=0)
2361
2362         # get maximum number of translations per user
2363         nat44_config = self.vapi.nat_show_config()
2364
2365         # send more than maximum number of translations per user packets
2366         pkts_num = nat44_config.max_translations_per_user + 5
2367         pkts = []
2368         for port in range(0, pkts_num):
2369             p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2370                  IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2371                  TCP(sport=1025 + port))
2372             pkts.append(p)
2373         self.pg0.add_stream(pkts)
2374         self.pg_enable_capture(self.pg_interfaces)
2375         self.pg_start()
2376
2377         # verify number of translated packet
2378         self.pg1.get_capture(pkts_num)
2379
2380         users = self.vapi.nat44_user_dump()
2381         for user in users:
2382             if user.ip_address == self.pg0.remote_ip4n:
2383                 self.assertEqual(user.nsessions,
2384                                  nat44_config.max_translations_per_user)
2385                 self.assertEqual(user.nstaticsessions, 0)
2386
2387         tcp_port = 22
2388         self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
2389                                       tcp_port, tcp_port,
2390                                       proto=IP_PROTOS.tcp)
2391         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2392              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2393              TCP(sport=tcp_port))
2394         self.pg0.add_stream(p)
2395         self.pg_enable_capture(self.pg_interfaces)
2396         self.pg_start()
2397         self.pg1.get_capture(1)
2398         users = self.vapi.nat44_user_dump()
2399         for user in users:
2400             if user.ip_address == self.pg0.remote_ip4n:
2401                 self.assertEqual(user.nsessions,
2402                                  nat44_config.max_translations_per_user - 1)
2403                 self.assertEqual(user.nstaticsessions, 1)
2404
2405     def test_interface_addr(self):
2406         """ Acquire NAT44 addresses from interface """
2407         self.vapi.nat44_add_interface_addr(self.pg7.sw_if_index)
2408
2409         # no address in NAT pool
2410         adresses = self.vapi.nat44_address_dump()
2411         self.assertEqual(0, len(adresses))
2412
2413         # configure interface address and check NAT address pool
2414         self.pg7.config_ip4()
2415         adresses = self.vapi.nat44_address_dump()
2416         self.assertEqual(1, len(adresses))
2417         self.assertEqual(adresses[0].ip_address[0:4], self.pg7.local_ip4n)
2418
2419         # remove interface address and check NAT address pool
2420         self.pg7.unconfig_ip4()
2421         adresses = self.vapi.nat44_address_dump()
2422         self.assertEqual(0, len(adresses))
2423
2424     def test_interface_addr_static_mapping(self):
2425         """ Static mapping with addresses from interface """
2426         tag = "testTAG"
2427
2428         self.vapi.nat44_add_interface_addr(self.pg7.sw_if_index)
2429         self.nat44_add_static_mapping(
2430             '1.2.3.4',
2431             external_sw_if_index=self.pg7.sw_if_index,
2432             tag=tag)
2433
2434         # static mappings with external interface
2435         static_mappings = self.vapi.nat44_static_mapping_dump()
2436         self.assertEqual(1, len(static_mappings))
2437         self.assertEqual(self.pg7.sw_if_index,
2438                          static_mappings[0].external_sw_if_index)
2439         self.assertEqual((static_mappings[0].tag).split('\0', 1)[0], tag)
2440
2441         # configure interface address and check static mappings
2442         self.pg7.config_ip4()
2443         static_mappings = self.vapi.nat44_static_mapping_dump()
2444         self.assertEqual(2, len(static_mappings))
2445         resolved = False
2446         for sm in static_mappings:
2447             if sm.external_sw_if_index == 0xFFFFFFFF:
2448                 self.assertEqual(sm.external_ip_address[0:4],
2449                                  self.pg7.local_ip4n)
2450                 self.assertEqual((sm.tag).split('\0', 1)[0], tag)
2451                 resolved = True
2452         self.assertTrue(resolved)
2453
2454         # remove interface address and check static mappings
2455         self.pg7.unconfig_ip4()
2456         static_mappings = self.vapi.nat44_static_mapping_dump()
2457         self.assertEqual(1, len(static_mappings))
2458         self.assertEqual(self.pg7.sw_if_index,
2459                          static_mappings[0].external_sw_if_index)
2460         self.assertEqual((static_mappings[0].tag).split('\0', 1)[0], tag)
2461
2462         # configure interface address again and check static mappings
2463         self.pg7.config_ip4()
2464         static_mappings = self.vapi.nat44_static_mapping_dump()
2465         self.assertEqual(2, len(static_mappings))
2466         resolved = False
2467         for sm in static_mappings:
2468             if sm.external_sw_if_index == 0xFFFFFFFF:
2469                 self.assertEqual(sm.external_ip_address[0:4],
2470                                  self.pg7.local_ip4n)
2471                 self.assertEqual((sm.tag).split('\0', 1)[0], tag)
2472                 resolved = True
2473         self.assertTrue(resolved)
2474
2475         # remove static mapping
2476         self.nat44_add_static_mapping(
2477             '1.2.3.4',
2478             external_sw_if_index=self.pg7.sw_if_index,
2479             tag=tag,
2480             is_add=0)
2481         static_mappings = self.vapi.nat44_static_mapping_dump()
2482         self.assertEqual(0, len(static_mappings))
2483
2484     def test_interface_addr_identity_nat(self):
2485         """ Identity NAT with addresses from interface """
2486
2487         port = 53053
2488         self.vapi.nat44_add_interface_addr(self.pg7.sw_if_index)
2489         self.vapi.nat44_add_del_identity_mapping(
2490             sw_if_index=self.pg7.sw_if_index,
2491             port=port,
2492             protocol=IP_PROTOS.tcp,
2493             addr_only=0)
2494
2495         # identity mappings with external interface
2496         identity_mappings = self.vapi.nat44_identity_mapping_dump()
2497         self.assertEqual(1, len(identity_mappings))
2498         self.assertEqual(self.pg7.sw_if_index,
2499                          identity_mappings[0].sw_if_index)
2500
2501         # configure interface address and check identity mappings
2502         self.pg7.config_ip4()
2503         identity_mappings = self.vapi.nat44_identity_mapping_dump()
2504         resolved = False
2505         self.assertEqual(2, len(identity_mappings))
2506         for sm in identity_mappings:
2507             if sm.sw_if_index == 0xFFFFFFFF:
2508                 self.assertEqual(identity_mappings[0].ip_address,
2509                                  self.pg7.local_ip4n)
2510                 self.assertEqual(port, identity_mappings[0].port)
2511                 self.assertEqual(IP_PROTOS.tcp, identity_mappings[0].protocol)
2512                 resolved = True
2513         self.assertTrue(resolved)
2514
2515         # remove interface address and check identity mappings
2516         self.pg7.unconfig_ip4()
2517         identity_mappings = self.vapi.nat44_identity_mapping_dump()
2518         self.assertEqual(1, len(identity_mappings))
2519         self.assertEqual(self.pg7.sw_if_index,
2520                          identity_mappings[0].sw_if_index)
2521
2522     def test_ipfix_nat44_sess(self):
2523         """ IPFIX logging NAT44 session created/delted """
2524         self.ipfix_domain_id = 10
2525         self.ipfix_src_port = 20202
2526         colector_port = 30303
2527         bind_layers(UDP, IPFIX, dport=30303)
2528         self.nat44_add_address(self.nat_addr)
2529         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2530         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2531                                                   is_inside=0)
2532         self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
2533                                      src_address=self.pg3.local_ip4n,
2534                                      path_mtu=512,
2535                                      template_interval=10,
2536                                      collector_port=colector_port)
2537         self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
2538                             src_port=self.ipfix_src_port)
2539
2540         pkts = self.create_stream_in(self.pg0, self.pg1)
2541         self.pg0.add_stream(pkts)
2542         self.pg_enable_capture(self.pg_interfaces)
2543         self.pg_start()
2544         capture = self.pg1.get_capture(len(pkts))
2545         self.verify_capture_out(capture)
2546         self.nat44_add_address(self.nat_addr, is_add=0)
2547         self.vapi.cli("ipfix flush")  # FIXME this should be an API call
2548         capture = self.pg3.get_capture(9)
2549         ipfix = IPFIXDecoder()
2550         # first load template
2551         for p in capture:
2552             self.assertTrue(p.haslayer(IPFIX))
2553             self.assertEqual(p[IP].src, self.pg3.local_ip4)
2554             self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2555             self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2556             self.assertEqual(p[UDP].dport, colector_port)
2557             self.assertEqual(p[IPFIX].observationDomainID,
2558                              self.ipfix_domain_id)
2559             if p.haslayer(Template):
2560                 ipfix.add_template(p.getlayer(Template))
2561         # verify events in data set
2562         for p in capture:
2563             if p.haslayer(Data):
2564                 data = ipfix.decode_data_set(p.getlayer(Set))
2565                 self.verify_ipfix_nat44_ses(data)
2566
2567     def test_ipfix_addr_exhausted(self):
2568         """ IPFIX logging NAT addresses exhausted """
2569         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2570         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2571                                                   is_inside=0)
2572         self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
2573                                      src_address=self.pg3.local_ip4n,
2574                                      path_mtu=512,
2575                                      template_interval=10)
2576         self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
2577                             src_port=self.ipfix_src_port)
2578
2579         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
2580              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2581              TCP(sport=3025))
2582         self.pg0.add_stream(p)
2583         self.pg_enable_capture(self.pg_interfaces)
2584         self.pg_start()
2585         capture = self.pg1.get_capture(0)
2586         self.vapi.cli("ipfix flush")  # FIXME this should be an API call
2587         capture = self.pg3.get_capture(9)
2588         ipfix = IPFIXDecoder()
2589         # first load template
2590         for p in capture:
2591             self.assertTrue(p.haslayer(IPFIX))
2592             self.assertEqual(p[IP].src, self.pg3.local_ip4)
2593             self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2594             self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2595             self.assertEqual(p[UDP].dport, 4739)
2596             self.assertEqual(p[IPFIX].observationDomainID,
2597                              self.ipfix_domain_id)
2598             if p.haslayer(Template):
2599                 ipfix.add_template(p.getlayer(Template))
2600         # verify events in data set
2601         for p in capture:
2602             if p.haslayer(Data):
2603                 data = ipfix.decode_data_set(p.getlayer(Set))
2604                 self.verify_ipfix_addr_exhausted(data)
2605
2606     @unittest.skipUnless(running_extended_tests(), "part of extended tests")
2607     def test_ipfix_max_sessions(self):
2608         """ IPFIX logging maximum session entries exceeded """
2609         self.nat44_add_address(self.nat_addr)
2610         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2611         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2612                                                   is_inside=0)
2613
2614         nat44_config = self.vapi.nat_show_config()
2615         max_sessions = 10 * nat44_config.translation_buckets
2616
2617         pkts = []
2618         for i in range(0, max_sessions):
2619             src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
2620             p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2621                  IP(src=src, dst=self.pg1.remote_ip4) /
2622                  TCP(sport=1025))
2623             pkts.append(p)
2624         self.pg0.add_stream(pkts)
2625         self.pg_enable_capture(self.pg_interfaces)
2626         self.pg_start()
2627
2628         self.pg1.get_capture(max_sessions)
2629         self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
2630                                      src_address=self.pg3.local_ip4n,
2631                                      path_mtu=512,
2632                                      template_interval=10)
2633         self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
2634                             src_port=self.ipfix_src_port)
2635
2636         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2637              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2638              TCP(sport=1025))
2639         self.pg0.add_stream(p)
2640         self.pg_enable_capture(self.pg_interfaces)
2641         self.pg_start()
2642         self.pg1.get_capture(0)
2643         self.vapi.cli("ipfix flush")  # FIXME this should be an API call
2644         capture = self.pg3.get_capture(9)
2645         ipfix = IPFIXDecoder()
2646         # first load template
2647         for p in capture:
2648             self.assertTrue(p.haslayer(IPFIX))
2649             self.assertEqual(p[IP].src, self.pg3.local_ip4)
2650             self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2651             self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2652             self.assertEqual(p[UDP].dport, 4739)
2653             self.assertEqual(p[IPFIX].observationDomainID,
2654                              self.ipfix_domain_id)
2655             if p.haslayer(Template):
2656                 ipfix.add_template(p.getlayer(Template))
2657         # verify events in data set
2658         for p in capture:
2659             if p.haslayer(Data):
2660                 data = ipfix.decode_data_set(p.getlayer(Set))
2661                 self.verify_ipfix_max_sessions(data, max_sessions)
2662
2663     def test_pool_addr_fib(self):
2664         """ NAT44 add pool addresses to FIB """
2665         static_addr = '10.0.0.10'
2666         self.nat44_add_address(self.nat_addr)
2667         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2668         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2669                                                   is_inside=0)
2670         self.nat44_add_static_mapping(self.pg0.remote_ip4, static_addr)
2671
2672         # NAT44 address
2673         p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2674              ARP(op=ARP.who_has, pdst=self.nat_addr,
2675                  psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2676         self.pg1.add_stream(p)
2677         self.pg_enable_capture(self.pg_interfaces)
2678         self.pg_start()
2679         capture = self.pg1.get_capture(1)
2680         self.assertTrue(capture[0].haslayer(ARP))
2681         self.assertTrue(capture[0][ARP].op, ARP.is_at)
2682
2683         # 1:1 NAT address
2684         p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2685              ARP(op=ARP.who_has, pdst=static_addr,
2686                  psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2687         self.pg1.add_stream(p)
2688         self.pg_enable_capture(self.pg_interfaces)
2689         self.pg_start()
2690         capture = self.pg1.get_capture(1)
2691         self.assertTrue(capture[0].haslayer(ARP))
2692         self.assertTrue(capture[0][ARP].op, ARP.is_at)
2693
2694         # send ARP to non-NAT44 interface
2695         p = (Ether(src=self.pg2.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2696              ARP(op=ARP.who_has, pdst=self.nat_addr,
2697                  psrc=self.pg2.remote_ip4, hwsrc=self.pg2.remote_mac))
2698         self.pg2.add_stream(p)
2699         self.pg_enable_capture(self.pg_interfaces)
2700         self.pg_start()
2701         capture = self.pg1.get_capture(0)
2702
2703         # remove addresses and verify
2704         self.nat44_add_address(self.nat_addr, is_add=0)
2705         self.nat44_add_static_mapping(self.pg0.remote_ip4, static_addr,
2706                                       is_add=0)
2707
2708         p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2709              ARP(op=ARP.who_has, pdst=self.nat_addr,
2710                  psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2711         self.pg1.add_stream(p)
2712         self.pg_enable_capture(self.pg_interfaces)
2713         self.pg_start()
2714         capture = self.pg1.get_capture(0)
2715
2716         p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2717              ARP(op=ARP.who_has, pdst=static_addr,
2718                  psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2719         self.pg1.add_stream(p)
2720         self.pg_enable_capture(self.pg_interfaces)
2721         self.pg_start()
2722         capture = self.pg1.get_capture(0)
2723
2724     def test_vrf_mode(self):
2725         """ NAT44 tenant VRF aware address pool mode """
2726
2727         vrf_id1 = 1
2728         vrf_id2 = 2
2729         nat_ip1 = "10.0.0.10"
2730         nat_ip2 = "10.0.0.11"
2731
2732         self.pg0.unconfig_ip4()
2733         self.pg1.unconfig_ip4()
2734         self.vapi.ip_table_add_del(vrf_id1, is_add=1)
2735         self.vapi.ip_table_add_del(vrf_id2, is_add=1)
2736         self.pg0.set_table_ip4(vrf_id1)
2737         self.pg1.set_table_ip4(vrf_id2)
2738         self.pg0.config_ip4()
2739         self.pg1.config_ip4()
2740
2741         self.nat44_add_address(nat_ip1, vrf_id=vrf_id1)
2742         self.nat44_add_address(nat_ip2, vrf_id=vrf_id2)
2743         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2744         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
2745         self.vapi.nat44_interface_add_del_feature(self.pg2.sw_if_index,
2746                                                   is_inside=0)
2747
2748         # first VRF
2749         pkts = self.create_stream_in(self.pg0, self.pg2)
2750         self.pg0.add_stream(pkts)
2751         self.pg_enable_capture(self.pg_interfaces)
2752         self.pg_start()
2753         capture = self.pg2.get_capture(len(pkts))
2754         self.verify_capture_out(capture, nat_ip1)
2755
2756         # second VRF
2757         pkts = self.create_stream_in(self.pg1, self.pg2)
2758         self.pg1.add_stream(pkts)
2759         self.pg_enable_capture(self.pg_interfaces)
2760         self.pg_start()
2761         capture = self.pg2.get_capture(len(pkts))
2762         self.verify_capture_out(capture, nat_ip2)
2763
2764         self.pg0.unconfig_ip4()
2765         self.pg1.unconfig_ip4()
2766         self.pg0.set_table_ip4(0)
2767         self.pg1.set_table_ip4(0)
2768         self.vapi.ip_table_add_del(vrf_id1, is_add=0)
2769         self.vapi.ip_table_add_del(vrf_id2, is_add=0)
2770
2771     def test_vrf_feature_independent(self):
2772         """ NAT44 tenant VRF independent address pool mode """
2773
2774         nat_ip1 = "10.0.0.10"
2775         nat_ip2 = "10.0.0.11"
2776
2777         self.nat44_add_address(nat_ip1)
2778         self.nat44_add_address(nat_ip2, vrf_id=99)
2779         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2780         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
2781         self.vapi.nat44_interface_add_del_feature(self.pg2.sw_if_index,
2782                                                   is_inside=0)
2783
2784         # first VRF
2785         pkts = self.create_stream_in(self.pg0, self.pg2)
2786         self.pg0.add_stream(pkts)
2787         self.pg_enable_capture(self.pg_interfaces)
2788         self.pg_start()
2789         capture = self.pg2.get_capture(len(pkts))
2790         self.verify_capture_out(capture, nat_ip1)
2791
2792         # second VRF
2793         pkts = self.create_stream_in(self.pg1, self.pg2)
2794         self.pg1.add_stream(pkts)
2795         self.pg_enable_capture(self.pg_interfaces)
2796         self.pg_start()
2797         capture = self.pg2.get_capture(len(pkts))
2798         self.verify_capture_out(capture, nat_ip1)
2799
2800     def test_dynamic_ipless_interfaces(self):
2801         """ NAT44 interfaces without configured IP address """
2802
2803         self.vapi.ip_neighbor_add_del(self.pg7.sw_if_index,
2804                                       mactobinary(self.pg7.remote_mac),
2805                                       self.pg7.remote_ip4n,
2806                                       is_static=1)
2807         self.vapi.ip_neighbor_add_del(self.pg8.sw_if_index,
2808                                       mactobinary(self.pg8.remote_mac),
2809                                       self.pg8.remote_ip4n,
2810                                       is_static=1)
2811
2812         self.vapi.ip_add_del_route(dst_address=self.pg7.remote_ip4n,
2813                                    dst_address_length=32,
2814                                    next_hop_address=self.pg7.remote_ip4n,
2815                                    next_hop_sw_if_index=self.pg7.sw_if_index)
2816         self.vapi.ip_add_del_route(dst_address=self.pg8.remote_ip4n,
2817                                    dst_address_length=32,
2818                                    next_hop_address=self.pg8.remote_ip4n,
2819                                    next_hop_sw_if_index=self.pg8.sw_if_index)
2820
2821         self.nat44_add_address(self.nat_addr)
2822         self.vapi.nat44_interface_add_del_feature(self.pg7.sw_if_index)
2823         self.vapi.nat44_interface_add_del_feature(self.pg8.sw_if_index,
2824                                                   is_inside=0)
2825
2826         # in2out
2827         pkts = self.create_stream_in(self.pg7, self.pg8)
2828         self.pg7.add_stream(pkts)
2829         self.pg_enable_capture(self.pg_interfaces)
2830         self.pg_start()
2831         capture = self.pg8.get_capture(len(pkts))
2832         self.verify_capture_out(capture)
2833
2834         # out2in
2835         pkts = self.create_stream_out(self.pg8, self.nat_addr)
2836         self.pg8.add_stream(pkts)
2837         self.pg_enable_capture(self.pg_interfaces)
2838         self.pg_start()
2839         capture = self.pg7.get_capture(len(pkts))
2840         self.verify_capture_in(capture, self.pg7)
2841
2842     def test_static_ipless_interfaces(self):
2843         """ NAT44 interfaces without configured IP address - 1:1 NAT """
2844
2845         self.vapi.ip_neighbor_add_del(self.pg7.sw_if_index,
2846                                       mactobinary(self.pg7.remote_mac),
2847                                       self.pg7.remote_ip4n,
2848                                       is_static=1)
2849         self.vapi.ip_neighbor_add_del(self.pg8.sw_if_index,
2850                                       mactobinary(self.pg8.remote_mac),
2851                                       self.pg8.remote_ip4n,
2852                                       is_static=1)
2853
2854         self.vapi.ip_add_del_route(dst_address=self.pg7.remote_ip4n,
2855                                    dst_address_length=32,
2856                                    next_hop_address=self.pg7.remote_ip4n,
2857                                    next_hop_sw_if_index=self.pg7.sw_if_index)
2858         self.vapi.ip_add_del_route(dst_address=self.pg8.remote_ip4n,
2859                                    dst_address_length=32,
2860                                    next_hop_address=self.pg8.remote_ip4n,
2861                                    next_hop_sw_if_index=self.pg8.sw_if_index)
2862
2863         self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr)
2864         self.vapi.nat44_interface_add_del_feature(self.pg7.sw_if_index)
2865         self.vapi.nat44_interface_add_del_feature(self.pg8.sw_if_index,
2866                                                   is_inside=0)
2867
2868         # out2in
2869         pkts = self.create_stream_out(self.pg8)
2870         self.pg8.add_stream(pkts)
2871         self.pg_enable_capture(self.pg_interfaces)
2872         self.pg_start()
2873         capture = self.pg7.get_capture(len(pkts))
2874         self.verify_capture_in(capture, self.pg7)
2875
2876         # in2out
2877         pkts = self.create_stream_in(self.pg7, self.pg8)
2878         self.pg7.add_stream(pkts)
2879         self.pg_enable_capture(self.pg_interfaces)
2880         self.pg_start()
2881         capture = self.pg8.get_capture(len(pkts))
2882         self.verify_capture_out(capture, self.nat_addr, True)
2883
2884     def test_static_with_port_ipless_interfaces(self):
2885         """ NAT44 interfaces without configured IP address - 1:1 NAPT """
2886
2887         self.tcp_port_out = 30606
2888         self.udp_port_out = 30607
2889         self.icmp_id_out = 30608
2890
2891         self.vapi.ip_neighbor_add_del(self.pg7.sw_if_index,
2892                                       mactobinary(self.pg7.remote_mac),
2893                                       self.pg7.remote_ip4n,
2894                                       is_static=1)
2895         self.vapi.ip_neighbor_add_del(self.pg8.sw_if_index,
2896                                       mactobinary(self.pg8.remote_mac),
2897                                       self.pg8.remote_ip4n,
2898                                       is_static=1)
2899
2900         self.vapi.ip_add_del_route(dst_address=self.pg7.remote_ip4n,
2901                                    dst_address_length=32,
2902                                    next_hop_address=self.pg7.remote_ip4n,
2903                                    next_hop_sw_if_index=self.pg7.sw_if_index)
2904         self.vapi.ip_add_del_route(dst_address=self.pg8.remote_ip4n,
2905                                    dst_address_length=32,
2906                                    next_hop_address=self.pg8.remote_ip4n,
2907                                    next_hop_sw_if_index=self.pg8.sw_if_index)
2908
2909         self.nat44_add_address(self.nat_addr)
2910         self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
2911                                       self.tcp_port_in, self.tcp_port_out,
2912                                       proto=IP_PROTOS.tcp)
2913         self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
2914                                       self.udp_port_in, self.udp_port_out,
2915                                       proto=IP_PROTOS.udp)
2916         self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
2917                                       self.icmp_id_in, self.icmp_id_out,
2918                                       proto=IP_PROTOS.icmp)
2919         self.vapi.nat44_interface_add_del_feature(self.pg7.sw_if_index)
2920         self.vapi.nat44_interface_add_del_feature(self.pg8.sw_if_index,
2921                                                   is_inside=0)
2922
2923         # out2in
2924         pkts = self.create_stream_out(self.pg8)
2925         self.pg8.add_stream(pkts)
2926         self.pg_enable_capture(self.pg_interfaces)
2927         self.pg_start()
2928         capture = self.pg7.get_capture(len(pkts))
2929         self.verify_capture_in(capture, self.pg7)
2930
2931         # in2out
2932         pkts = self.create_stream_in(self.pg7, self.pg8)
2933         self.pg7.add_stream(pkts)
2934         self.pg_enable_capture(self.pg_interfaces)
2935         self.pg_start()
2936         capture = self.pg8.get_capture(len(pkts))
2937         self.verify_capture_out(capture)
2938
2939     def test_static_unknown_proto(self):
2940         """ 1:1 NAT translate packet with unknown protocol """
2941         nat_ip = "10.0.0.10"
2942         self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
2943         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2944         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2945                                                   is_inside=0)
2946
2947         # in2out
2948         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2949              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2950              GRE() /
2951              IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4) /
2952              TCP(sport=1234, dport=1234))
2953         self.pg0.add_stream(p)
2954         self.pg_enable_capture(self.pg_interfaces)
2955         self.pg_start()
2956         p = self.pg1.get_capture(1)
2957         packet = p[0]
2958         try:
2959             self.assertEqual(packet[IP].src, nat_ip)
2960             self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
2961             self.assertTrue(packet.haslayer(GRE))
2962             self.assert_packet_checksums_valid(packet)
2963         except:
2964             self.logger.error(ppp("Unexpected or invalid packet:", packet))
2965             raise
2966
2967         # out2in
2968         p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
2969              IP(src=self.pg1.remote_ip4, dst=nat_ip) /
2970              GRE() /
2971              IP(src=self.pg3.remote_ip4, dst=self.pg2.remote_ip4) /
2972              TCP(sport=1234, dport=1234))
2973         self.pg1.add_stream(p)
2974         self.pg_enable_capture(self.pg_interfaces)
2975         self.pg_start()
2976         p = self.pg0.get_capture(1)
2977         packet = p[0]
2978         try:
2979             self.assertEqual(packet[IP].src, self.pg1.remote_ip4)
2980             self.assertEqual(packet[IP].dst, self.pg0.remote_ip4)
2981             self.assertTrue(packet.haslayer(GRE))
2982             self.assert_packet_checksums_valid(packet)
2983         except:
2984             self.logger.error(ppp("Unexpected or invalid packet:", packet))
2985             raise
2986
2987     def test_hairpinning_static_unknown_proto(self):
2988         """ 1:1 NAT translate packet with unknown protocol - hairpinning """
2989
2990         host = self.pg0.remote_hosts[0]
2991         server = self.pg0.remote_hosts[1]
2992
2993         host_nat_ip = "10.0.0.10"
2994         server_nat_ip = "10.0.0.11"
2995
2996         self.nat44_add_static_mapping(host.ip4, host_nat_ip)
2997         self.nat44_add_static_mapping(server.ip4, server_nat_ip)
2998         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2999         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3000                                                   is_inside=0)
3001
3002         # host to server
3003         p = (Ether(dst=self.pg0.local_mac, src=host.mac) /
3004              IP(src=host.ip4, dst=server_nat_ip) /
3005              GRE() /
3006              IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4) /
3007              TCP(sport=1234, dport=1234))
3008         self.pg0.add_stream(p)
3009         self.pg_enable_capture(self.pg_interfaces)
3010         self.pg_start()
3011         p = self.pg0.get_capture(1)
3012         packet = p[0]
3013         try:
3014             self.assertEqual(packet[IP].src, host_nat_ip)
3015             self.assertEqual(packet[IP].dst, server.ip4)
3016             self.assertTrue(packet.haslayer(GRE))
3017             self.assert_packet_checksums_valid(packet)
3018         except:
3019             self.logger.error(ppp("Unexpected or invalid packet:", packet))
3020             raise
3021
3022         # server to host
3023         p = (Ether(dst=self.pg0.local_mac, src=server.mac) /
3024              IP(src=server.ip4, dst=host_nat_ip) /
3025              GRE() /
3026              IP(src=self.pg3.remote_ip4, dst=self.pg2.remote_ip4) /
3027              TCP(sport=1234, dport=1234))
3028         self.pg0.add_stream(p)
3029         self.pg_enable_capture(self.pg_interfaces)
3030         self.pg_start()
3031         p = self.pg0.get_capture(1)
3032         packet = p[0]
3033         try:
3034             self.assertEqual(packet[IP].src, server_nat_ip)
3035             self.assertEqual(packet[IP].dst, host.ip4)
3036             self.assertTrue(packet.haslayer(GRE))
3037             self.assert_packet_checksums_valid(packet)
3038         except:
3039             self.logger.error(ppp("Unexpected or invalid packet:", packet))
3040             raise
3041
3042     def test_unknown_proto(self):
3043         """ NAT44 translate packet with unknown protocol """
3044         self.nat44_add_address(self.nat_addr)
3045         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3046         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3047                                                   is_inside=0)
3048
3049         # in2out
3050         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3051              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3052              TCP(sport=self.tcp_port_in, dport=20))
3053         self.pg0.add_stream(p)
3054         self.pg_enable_capture(self.pg_interfaces)
3055         self.pg_start()
3056         p = self.pg1.get_capture(1)
3057
3058         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3059              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3060              GRE() /
3061              IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4) /
3062              TCP(sport=1234, dport=1234))
3063         self.pg0.add_stream(p)
3064         self.pg_enable_capture(self.pg_interfaces)
3065         self.pg_start()
3066         p = self.pg1.get_capture(1)
3067         packet = p[0]
3068         try:
3069             self.assertEqual(packet[IP].src, self.nat_addr)
3070             self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
3071             self.assertTrue(packet.haslayer(GRE))
3072             self.assert_packet_checksums_valid(packet)
3073         except:
3074             self.logger.error(ppp("Unexpected or invalid packet:", packet))
3075             raise
3076
3077         # out2in
3078         p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
3079              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3080              GRE() /
3081              IP(src=self.pg3.remote_ip4, dst=self.pg2.remote_ip4) /
3082              TCP(sport=1234, dport=1234))
3083         self.pg1.add_stream(p)
3084         self.pg_enable_capture(self.pg_interfaces)
3085         self.pg_start()
3086         p = self.pg0.get_capture(1)
3087         packet = p[0]
3088         try:
3089             self.assertEqual(packet[IP].src, self.pg1.remote_ip4)
3090             self.assertEqual(packet[IP].dst, self.pg0.remote_ip4)
3091             self.assertTrue(packet.haslayer(GRE))
3092             self.assert_packet_checksums_valid(packet)
3093         except:
3094             self.logger.error(ppp("Unexpected or invalid packet:", packet))
3095             raise
3096
3097     def test_hairpinning_unknown_proto(self):
3098         """ NAT44 translate packet with unknown protocol - hairpinning """
3099         host = self.pg0.remote_hosts[0]
3100         server = self.pg0.remote_hosts[1]
3101         host_in_port = 1234
3102         server_out_port = 8765
3103         server_nat_ip = "10.0.0.11"
3104
3105         self.nat44_add_address(self.nat_addr)
3106         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3107         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3108                                                   is_inside=0)
3109
3110         # add static mapping for server
3111         self.nat44_add_static_mapping(server.ip4, server_nat_ip)
3112
3113         # host to server
3114         p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
3115              IP(src=host.ip4, dst=server_nat_ip) /
3116              TCP(sport=host_in_port, dport=server_out_port))
3117         self.pg0.add_stream(p)
3118         self.pg_enable_capture(self.pg_interfaces)
3119         self.pg_start()
3120         capture = self.pg0.get_capture(1)
3121
3122         p = (Ether(dst=self.pg0.local_mac, src=host.mac) /
3123              IP(src=host.ip4, dst=server_nat_ip) /
3124              GRE() /
3125              IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4) /
3126              TCP(sport=1234, dport=1234))
3127         self.pg0.add_stream(p)
3128         self.pg_enable_capture(self.pg_interfaces)
3129         self.pg_start()
3130         p = self.pg0.get_capture(1)
3131         packet = p[0]
3132         try:
3133             self.assertEqual(packet[IP].src, self.nat_addr)
3134             self.assertEqual(packet[IP].dst, server.ip4)
3135             self.assertTrue(packet.haslayer(GRE))
3136             self.assert_packet_checksums_valid(packet)
3137         except:
3138             self.logger.error(ppp("Unexpected or invalid packet:", packet))
3139             raise
3140
3141         # server to host
3142         p = (Ether(dst=self.pg0.local_mac, src=server.mac) /
3143              IP(src=server.ip4, dst=self.nat_addr) /
3144              GRE() /
3145              IP(src=self.pg3.remote_ip4, dst=self.pg2.remote_ip4) /
3146              TCP(sport=1234, dport=1234))
3147         self.pg0.add_stream(p)
3148         self.pg_enable_capture(self.pg_interfaces)
3149         self.pg_start()
3150         p = self.pg0.get_capture(1)
3151         packet = p[0]
3152         try:
3153             self.assertEqual(packet[IP].src, server_nat_ip)
3154             self.assertEqual(packet[IP].dst, host.ip4)
3155             self.assertTrue(packet.haslayer(GRE))
3156             self.assert_packet_checksums_valid(packet)
3157         except:
3158             self.logger.error(ppp("Unexpected or invalid packet:", packet))
3159             raise
3160
3161     def test_output_feature(self):
3162         """ NAT44 interface output feature (in2out postrouting) """
3163         self.nat44_add_address(self.nat_addr)
3164         self.vapi.nat44_interface_add_del_output_feature(self.pg0.sw_if_index)
3165         self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index)
3166         self.vapi.nat44_interface_add_del_output_feature(self.pg3.sw_if_index,
3167                                                          is_inside=0)
3168
3169         # in2out
3170         pkts = self.create_stream_in(self.pg0, self.pg3)
3171         self.pg0.add_stream(pkts)
3172         self.pg_enable_capture(self.pg_interfaces)
3173         self.pg_start()
3174         capture = self.pg3.get_capture(len(pkts))
3175         self.verify_capture_out(capture)
3176
3177         # out2in
3178         pkts = self.create_stream_out(self.pg3)
3179         self.pg3.add_stream(pkts)
3180         self.pg_enable_capture(self.pg_interfaces)
3181         self.pg_start()
3182         capture = self.pg0.get_capture(len(pkts))
3183         self.verify_capture_in(capture, self.pg0)
3184
3185         # from non-NAT interface to NAT inside interface
3186         pkts = self.create_stream_in(self.pg2, self.pg0)
3187         self.pg2.add_stream(pkts)
3188         self.pg_enable_capture(self.pg_interfaces)
3189         self.pg_start()
3190         capture = self.pg0.get_capture(len(pkts))
3191         self.verify_capture_no_translation(capture, self.pg2, self.pg0)
3192
3193     def test_output_feature_vrf_aware(self):
3194         """ NAT44 interface output feature VRF aware (in2out postrouting) """
3195         nat_ip_vrf10 = "10.0.0.10"
3196         nat_ip_vrf20 = "10.0.0.20"
3197
3198         self.vapi.ip_add_del_route(dst_address=self.pg3.remote_ip4n,
3199                                    dst_address_length=32,
3200                                    next_hop_address=self.pg3.remote_ip4n,
3201                                    next_hop_sw_if_index=self.pg3.sw_if_index,
3202                                    table_id=10)
3203         self.vapi.ip_add_del_route(dst_address=self.pg3.remote_ip4n,
3204                                    dst_address_length=32,
3205                                    next_hop_address=self.pg3.remote_ip4n,
3206                                    next_hop_sw_if_index=self.pg3.sw_if_index,
3207                                    table_id=20)
3208
3209         self.nat44_add_address(nat_ip_vrf10, vrf_id=10)
3210         self.nat44_add_address(nat_ip_vrf20, vrf_id=20)
3211         self.vapi.nat44_interface_add_del_output_feature(self.pg4.sw_if_index)
3212         self.vapi.nat44_interface_add_del_output_feature(self.pg6.sw_if_index)
3213         self.vapi.nat44_interface_add_del_output_feature(self.pg3.sw_if_index,
3214                                                          is_inside=0)
3215
3216         # in2out VRF 10
3217         pkts = self.create_stream_in(self.pg4, self.pg3)
3218         self.pg4.add_stream(pkts)
3219         self.pg_enable_capture(self.pg_interfaces)
3220         self.pg_start()
3221         capture = self.pg3.get_capture(len(pkts))
3222         self.verify_capture_out(capture, nat_ip=nat_ip_vrf10)
3223
3224         # out2in VRF 10
3225         pkts = self.create_stream_out(self.pg3, dst_ip=nat_ip_vrf10)
3226         self.pg3.add_stream(pkts)
3227         self.pg_enable_capture(self.pg_interfaces)
3228         self.pg_start()
3229         capture = self.pg4.get_capture(len(pkts))
3230         self.verify_capture_in(capture, self.pg4)
3231
3232         # in2out VRF 20
3233         pkts = self.create_stream_in(self.pg6, self.pg3)
3234         self.pg6.add_stream(pkts)
3235         self.pg_enable_capture(self.pg_interfaces)
3236         self.pg_start()
3237         capture = self.pg3.get_capture(len(pkts))
3238         self.verify_capture_out(capture, nat_ip=nat_ip_vrf20)
3239
3240         # out2in VRF 20
3241         pkts = self.create_stream_out(self.pg3, dst_ip=nat_ip_vrf20)
3242         self.pg3.add_stream(pkts)
3243         self.pg_enable_capture(self.pg_interfaces)
3244         self.pg_start()
3245         capture = self.pg6.get_capture(len(pkts))
3246         self.verify_capture_in(capture, self.pg6)
3247
3248     def test_output_feature_hairpinning(self):
3249         """ NAT44 interface output feature hairpinning (in2out postrouting) """
3250         host = self.pg0.remote_hosts[0]
3251         server = self.pg0.remote_hosts[1]
3252         host_in_port = 1234
3253         host_out_port = 0
3254         server_in_port = 5678
3255         server_out_port = 8765
3256
3257         self.nat44_add_address(self.nat_addr)
3258         self.vapi.nat44_interface_add_del_output_feature(self.pg0.sw_if_index)
3259         self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
3260                                                          is_inside=0)
3261
3262         # add static mapping for server
3263         self.nat44_add_static_mapping(server.ip4, self.nat_addr,
3264                                       server_in_port, server_out_port,
3265                                       proto=IP_PROTOS.tcp)
3266
3267         # send packet from host to server
3268         p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
3269              IP(src=host.ip4, dst=self.nat_addr) /
3270              TCP(sport=host_in_port, dport=server_out_port))
3271         self.pg0.add_stream(p)
3272         self.pg_enable_capture(self.pg_interfaces)
3273         self.pg_start()
3274         capture = self.pg0.get_capture(1)
3275         p = capture[0]
3276         try:
3277             ip = p[IP]
3278             tcp = p[TCP]
3279             self.assertEqual(ip.src, self.nat_addr)
3280             self.assertEqual(ip.dst, server.ip4)
3281             self.assertNotEqual(tcp.sport, host_in_port)
3282             self.assertEqual(tcp.dport, server_in_port)
3283             self.assert_packet_checksums_valid(p)
3284             host_out_port = tcp.sport
3285         except:
3286             self.logger.error(ppp("Unexpected or invalid packet:", p))
3287             raise
3288
3289         # send reply from server to host
3290         p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
3291              IP(src=server.ip4, dst=self.nat_addr) /
3292              TCP(sport=server_in_port, dport=host_out_port))
3293         self.pg0.add_stream(p)
3294         self.pg_enable_capture(self.pg_interfaces)
3295         self.pg_start()
3296         capture = self.pg0.get_capture(1)
3297         p = capture[0]
3298         try:
3299             ip = p[IP]
3300             tcp = p[TCP]
3301             self.assertEqual(ip.src, self.nat_addr)
3302             self.assertEqual(ip.dst, host.ip4)
3303             self.assertEqual(tcp.sport, server_out_port)
3304             self.assertEqual(tcp.dport, host_in_port)
3305             self.assert_packet_checksums_valid(p)
3306         except:
3307             self.logger.error(ppp("Unexpected or invalid packet:", p))
3308             raise
3309
3310     def test_output_feature_and_service(self):
3311         """ NAT44 interface output feature and services """
3312         external_addr = '1.2.3.4'
3313         external_port = 80
3314         local_port = 8080
3315
3316         self.vapi.nat44_forwarding_enable_disable(1)
3317         self.nat44_add_address(self.nat_addr)
3318         self.vapi.nat44_add_del_identity_mapping(ip=self.pg1.remote_ip4n)
3319         self.nat44_add_static_mapping(self.pg0.remote_ip4, external_addr,
3320                                       local_port, external_port,
3321                                       proto=IP_PROTOS.tcp, out2in_only=1)
3322         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3323         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
3324                                                   is_inside=0)
3325         self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
3326                                                          is_inside=0)
3327
3328         # from client to service
3329         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3330              IP(src=self.pg1.remote_ip4, dst=external_addr) /
3331              TCP(sport=12345, dport=external_port))
3332         self.pg1.add_stream(p)
3333         self.pg_enable_capture(self.pg_interfaces)
3334         self.pg_start()
3335         capture = self.pg0.get_capture(1)
3336         p = capture[0]
3337         try:
3338             ip = p[IP]
3339             tcp = p[TCP]
3340             self.assertEqual(ip.dst, self.pg0.remote_ip4)
3341             self.assertEqual(tcp.dport, local_port)
3342             self.assert_packet_checksums_valid(p)
3343         except:
3344             self.logger.error(ppp("Unexpected or invalid packet:", p))
3345             raise
3346
3347         # from service back to client
3348         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3349              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3350              TCP(sport=local_port, dport=12345))
3351         self.pg0.add_stream(p)
3352         self.pg_enable_capture(self.pg_interfaces)
3353         self.pg_start()
3354         capture = self.pg1.get_capture(1)
3355         p = capture[0]
3356         try:
3357             ip = p[IP]
3358             tcp = p[TCP]
3359             self.assertEqual(ip.src, external_addr)
3360             self.assertEqual(tcp.sport, external_port)
3361             self.assert_packet_checksums_valid(p)
3362         except:
3363             self.logger.error(ppp("Unexpected or invalid packet:", p))
3364             raise
3365
3366         # from local network host to external network
3367         pkts = self.create_stream_in(self.pg0, self.pg1)
3368         self.pg0.add_stream(pkts)
3369         self.pg_enable_capture(self.pg_interfaces)
3370         self.pg_start()
3371         capture = self.pg1.get_capture(len(pkts))
3372         self.verify_capture_out(capture)
3373         pkts = self.create_stream_in(self.pg0, self.pg1)
3374         self.pg0.add_stream(pkts)
3375         self.pg_enable_capture(self.pg_interfaces)
3376         self.pg_start()
3377         capture = self.pg1.get_capture(len(pkts))
3378         self.verify_capture_out(capture)
3379
3380         # from external network back to local network host
3381         pkts = self.create_stream_out(self.pg1)
3382         self.pg1.add_stream(pkts)
3383         self.pg_enable_capture(self.pg_interfaces)
3384         self.pg_start()
3385         capture = self.pg0.get_capture(len(pkts))
3386         self.verify_capture_in(capture, self.pg0)
3387
3388     def test_output_feature_and_service2(self):
3389         """ NAT44 interface output feature and service host direct access """
3390         self.vapi.nat44_forwarding_enable_disable(1)
3391         self.nat44_add_address(self.nat_addr)
3392         self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
3393                                                          is_inside=0)
3394
3395         # session initiaded from service host - translate
3396         pkts = self.create_stream_in(self.pg0, self.pg1)
3397         self.pg0.add_stream(pkts)
3398         self.pg_enable_capture(self.pg_interfaces)
3399         self.pg_start()
3400         capture = self.pg1.get_capture(len(pkts))
3401         self.verify_capture_out(capture)
3402
3403         pkts = self.create_stream_out(self.pg1)
3404         self.pg1.add_stream(pkts)
3405         self.pg_enable_capture(self.pg_interfaces)
3406         self.pg_start()
3407         capture = self.pg0.get_capture(len(pkts))
3408         self.verify_capture_in(capture, self.pg0)
3409
3410         # session initiaded from remote host - do not translate
3411         pkts = self.create_stream_out(self.pg1,
3412                                       self.pg0.remote_ip4,
3413                                       use_inside_ports=True)
3414         self.pg1.add_stream(pkts)
3415         self.pg_enable_capture(self.pg_interfaces)
3416         self.pg_start()
3417         capture = self.pg0.get_capture(len(pkts))
3418         self.verify_capture_in(capture, self.pg0)
3419
3420         pkts = self.create_stream_in(self.pg0, self.pg1)
3421         self.pg0.add_stream(pkts)
3422         self.pg_enable_capture(self.pg_interfaces)
3423         self.pg_start()
3424         capture = self.pg1.get_capture(len(pkts))
3425         self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
3426                                 same_port=True)
3427
3428     def test_output_feature_and_service3(self):
3429         """ NAT44 interface output feature and DST NAT """
3430         external_addr = '1.2.3.4'
3431         external_port = 80
3432         local_port = 8080
3433
3434         self.vapi.nat44_forwarding_enable_disable(1)
3435         self.nat44_add_address(self.nat_addr)
3436         self.nat44_add_static_mapping(self.pg1.remote_ip4, external_addr,
3437                                       local_port, external_port,
3438                                       proto=IP_PROTOS.tcp, out2in_only=1)
3439         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3440         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
3441                                                   is_inside=0)
3442         self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
3443                                                          is_inside=0)
3444
3445         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3446              IP(src=self.pg0.remote_ip4, dst=external_addr) /
3447              TCP(sport=12345, dport=external_port))
3448         self.pg0.add_stream(p)
3449         self.pg_enable_capture(self.pg_interfaces)
3450         self.pg_start()
3451         capture = self.pg1.get_capture(1)
3452         p = capture[0]
3453         try:
3454             ip = p[IP]
3455             tcp = p[TCP]
3456             self.assertEqual(ip.src, self.pg0.remote_ip4)
3457             self.assertEqual(tcp.sport, 12345)
3458             self.assertEqual(ip.dst, self.pg1.remote_ip4)
3459             self.assertEqual(tcp.dport, local_port)
3460             self.assert_packet_checksums_valid(p)
3461         except:
3462             self.logger.error(ppp("Unexpected or invalid packet:", p))
3463             raise
3464
3465         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3466              IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
3467              TCP(sport=local_port, dport=12345))
3468         self.pg1.add_stream(p)
3469         self.pg_enable_capture(self.pg_interfaces)
3470         self.pg_start()
3471         capture = self.pg0.get_capture(1)
3472         p = capture[0]
3473         try:
3474             ip = p[IP]
3475             tcp = p[TCP]
3476             self.assertEqual(ip.src, external_addr)
3477             self.assertEqual(tcp.sport, external_port)
3478             self.assertEqual(ip.dst, self.pg0.remote_ip4)
3479             self.assertEqual(tcp.dport, 12345)
3480             self.assert_packet_checksums_valid(p)
3481         except:
3482             self.logger.error(ppp("Unexpected or invalid packet:", p))
3483             raise
3484
3485     def test_one_armed_nat44(self):
3486         """ One armed NAT44 """
3487         remote_host = self.pg9.remote_hosts[0]
3488         local_host = self.pg9.remote_hosts[1]
3489         external_port = 0
3490
3491         self.nat44_add_address(self.nat_addr)
3492         self.vapi.nat44_interface_add_del_feature(self.pg9.sw_if_index)
3493         self.vapi.nat44_interface_add_del_feature(self.pg9.sw_if_index,
3494                                                   is_inside=0)
3495
3496         # in2out
3497         p = (Ether(src=self.pg9.remote_mac, dst=self.pg9.local_mac) /
3498              IP(src=local_host.ip4, dst=remote_host.ip4) /
3499              TCP(sport=12345, dport=80))
3500         self.pg9.add_stream(p)
3501         self.pg_enable_capture(self.pg_interfaces)
3502         self.pg_start()
3503         capture = self.pg9.get_capture(1)
3504         p = capture[0]
3505         try:
3506             ip = p[IP]
3507             tcp = p[TCP]
3508             self.assertEqual(ip.src, self.nat_addr)
3509             self.assertEqual(ip.dst, remote_host.ip4)
3510             self.assertNotEqual(tcp.sport, 12345)
3511             external_port = tcp.sport
3512             self.assertEqual(tcp.dport, 80)
3513             self.assert_packet_checksums_valid(p)
3514         except:
3515             self.logger.error(ppp("Unexpected or invalid packet:", p))
3516             raise
3517
3518         # out2in
3519         p = (Ether(src=self.pg9.remote_mac, dst=self.pg9.local_mac) /
3520              IP(src=remote_host.ip4, dst=self.nat_addr) /
3521              TCP(sport=80, dport=external_port))
3522         self.pg9.add_stream(p)
3523         self.pg_enable_capture(self.pg_interfaces)
3524         self.pg_start()
3525         capture = self.pg9.get_capture(1)
3526         p = capture[0]
3527         try:
3528             ip = p[IP]
3529             tcp = p[TCP]
3530             self.assertEqual(ip.src, remote_host.ip4)
3531             self.assertEqual(ip.dst, local_host.ip4)
3532             self.assertEqual(tcp.sport, 80)
3533             self.assertEqual(tcp.dport, 12345)
3534             self.assert_packet_checksums_valid(p)
3535         except:
3536             self.logger.error(ppp("Unexpected or invalid packet:", p))
3537             raise
3538
3539     def test_one_armed_nat44_static(self):
3540         """ One armed NAT44 and 1:1 NAPT symmetrical rule """
3541         remote_host = self.pg9.remote_hosts[0]
3542         local_host = self.pg9.remote_hosts[1]
3543         external_port = 80
3544         local_port = 8080
3545         eh_port_in = 0
3546
3547         self.vapi.nat44_forwarding_enable_disable(1)
3548         self.nat44_add_address(self.nat_addr, twice_nat=1)
3549         self.nat44_add_static_mapping(local_host.ip4, self.nat_addr,
3550                                       local_port, external_port,
3551                                       proto=IP_PROTOS.tcp, out2in_only=1,
3552                                       twice_nat=1)
3553         self.vapi.nat44_interface_add_del_feature(self.pg9.sw_if_index)
3554         self.vapi.nat44_interface_add_del_feature(self.pg9.sw_if_index,
3555                                                   is_inside=0)
3556
3557         # from client to service
3558         p = (Ether(src=self.pg9.remote_mac, dst=self.pg9.local_mac) /
3559              IP(src=remote_host.ip4, dst=self.nat_addr) /
3560              TCP(sport=12345, dport=external_port))
3561         self.pg9.add_stream(p)
3562         self.pg_enable_capture(self.pg_interfaces)
3563         self.pg_start()
3564         capture = self.pg9.get_capture(1)
3565         p = capture[0]
3566         try:
3567             ip = p[IP]
3568             tcp = p[TCP]
3569             self.assertEqual(ip.dst, local_host.ip4)
3570             self.assertEqual(ip.src, self.nat_addr)
3571             self.assertEqual(tcp.dport, local_port)
3572             self.assertNotEqual(tcp.sport, 12345)
3573             eh_port_in = tcp.sport
3574             self.assert_packet_checksums_valid(p)
3575         except:
3576             self.logger.error(ppp("Unexpected or invalid packet:", p))
3577             raise
3578
3579         # from service back to client
3580         p = (Ether(src=self.pg9.remote_mac, dst=self.pg9.local_mac) /
3581              IP(src=local_host.ip4, dst=self.nat_addr) /
3582              TCP(sport=local_port, dport=eh_port_in))
3583         self.pg9.add_stream(p)
3584         self.pg_enable_capture(self.pg_interfaces)
3585         self.pg_start()
3586         capture = self.pg9.get_capture(1)
3587         p = capture[0]
3588         try:
3589             ip = p[IP]
3590             tcp = p[TCP]
3591             self.assertEqual(ip.src, self.nat_addr)
3592             self.assertEqual(ip.dst, remote_host.ip4)
3593             self.assertEqual(tcp.sport, external_port)
3594             self.assertEqual(tcp.dport, 12345)
3595             self.assert_packet_checksums_valid(p)
3596         except:
3597             self.logger.error(ppp("Unexpected or invalid packet:", p))
3598             raise
3599
3600     def test_del_session(self):
3601         """ Delete NAT44 session """
3602         self.nat44_add_address(self.nat_addr)
3603         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3604         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3605                                                   is_inside=0)
3606
3607         pkts = self.create_stream_in(self.pg0, self.pg1)
3608         self.pg0.add_stream(pkts)
3609         self.pg_enable_capture(self.pg_interfaces)
3610         self.pg_start()
3611         capture = self.pg1.get_capture(len(pkts))
3612
3613         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
3614         nsessions = len(sessions)
3615
3616         self.vapi.nat44_del_session(sessions[0].inside_ip_address,
3617                                     sessions[0].inside_port,
3618                                     sessions[0].protocol)
3619         self.vapi.nat44_del_session(sessions[1].outside_ip_address,
3620                                     sessions[1].outside_port,
3621                                     sessions[1].protocol,
3622                                     is_in=0)
3623
3624         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
3625         self.assertEqual(nsessions - len(sessions), 2)
3626
3627     def test_set_get_reass(self):
3628         """ NAT44 set/get virtual fragmentation reassembly """
3629         reas_cfg1 = self.vapi.nat_get_reass()
3630
3631         self.vapi.nat_set_reass(timeout=reas_cfg1.ip4_timeout + 5,
3632                                 max_reass=reas_cfg1.ip4_max_reass * 2,
3633                                 max_frag=reas_cfg1.ip4_max_frag * 2)
3634
3635         reas_cfg2 = self.vapi.nat_get_reass()
3636
3637         self.assertEqual(reas_cfg1.ip4_timeout + 5, reas_cfg2.ip4_timeout)
3638         self.assertEqual(reas_cfg1.ip4_max_reass * 2, reas_cfg2.ip4_max_reass)
3639         self.assertEqual(reas_cfg1.ip4_max_frag * 2, reas_cfg2.ip4_max_frag)
3640
3641         self.vapi.nat_set_reass(drop_frag=1)
3642         self.assertTrue(self.vapi.nat_get_reass().ip4_drop_frag)
3643
3644     def test_frag_in_order(self):
3645         """ NAT44 translate fragments arriving in order """
3646         self.nat44_add_address(self.nat_addr)
3647         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3648         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3649                                                   is_inside=0)
3650
3651         data = "A" * 4 + "B" * 16 + "C" * 3
3652         self.tcp_port_in = random.randint(1025, 65535)
3653
3654         reass = self.vapi.nat_reass_dump()
3655         reass_n_start = len(reass)
3656
3657         # in2out
3658         pkts = self.create_stream_frag(self.pg0,
3659                                        self.pg1.remote_ip4,
3660                                        self.tcp_port_in,
3661                                        20,
3662                                        data)
3663         self.pg0.add_stream(pkts)
3664         self.pg_enable_capture(self.pg_interfaces)
3665         self.pg_start()
3666         frags = self.pg1.get_capture(len(pkts))
3667         p = self.reass_frags_and_verify(frags,
3668                                         self.nat_addr,
3669                                         self.pg1.remote_ip4)
3670         self.assertEqual(p[TCP].dport, 20)
3671         self.assertNotEqual(p[TCP].sport, self.tcp_port_in)
3672         self.tcp_port_out = p[TCP].sport
3673         self.assertEqual(data, p[Raw].load)
3674
3675         # out2in
3676         pkts = self.create_stream_frag(self.pg1,
3677                                        self.nat_addr,
3678                                        20,
3679                                        self.tcp_port_out,
3680                                        data)
3681         self.pg1.add_stream(pkts)
3682         self.pg_enable_capture(self.pg_interfaces)
3683         self.pg_start()
3684         frags = self.pg0.get_capture(len(pkts))
3685         p = self.reass_frags_and_verify(frags,
3686                                         self.pg1.remote_ip4,
3687                                         self.pg0.remote_ip4)
3688         self.assertEqual(p[TCP].sport, 20)
3689         self.assertEqual(p[TCP].dport, self.tcp_port_in)
3690         self.assertEqual(data, p[Raw].load)
3691
3692         reass = self.vapi.nat_reass_dump()
3693         reass_n_end = len(reass)
3694
3695         self.assertEqual(reass_n_end - reass_n_start, 2)
3696
3697     def test_reass_hairpinning(self):
3698         """ NAT44 fragments hairpinning """
3699         server = self.pg0.remote_hosts[1]
3700         host_in_port = random.randint(1025, 65535)
3701         server_in_port = random.randint(1025, 65535)
3702         server_out_port = random.randint(1025, 65535)
3703         data = "A" * 4 + "B" * 16 + "C" * 3
3704
3705         self.nat44_add_address(self.nat_addr)
3706         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3707         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3708                                                   is_inside=0)
3709         # add static mapping for server
3710         self.nat44_add_static_mapping(server.ip4, self.nat_addr,
3711                                       server_in_port, server_out_port,
3712                                       proto=IP_PROTOS.tcp)
3713
3714         # send packet from host to server
3715         pkts = self.create_stream_frag(self.pg0,
3716                                        self.nat_addr,
3717                                        host_in_port,
3718                                        server_out_port,
3719                                        data)
3720         self.pg0.add_stream(pkts)
3721         self.pg_enable_capture(self.pg_interfaces)
3722         self.pg_start()
3723         frags = self.pg0.get_capture(len(pkts))
3724         p = self.reass_frags_and_verify(frags,
3725                                         self.nat_addr,
3726                                         server.ip4)
3727         self.assertNotEqual(p[TCP].sport, host_in_port)
3728         self.assertEqual(p[TCP].dport, server_in_port)
3729         self.assertEqual(data, p[Raw].load)
3730
3731     def test_frag_out_of_order(self):
3732         """ NAT44 translate fragments arriving out of order """
3733         self.nat44_add_address(self.nat_addr)
3734         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3735         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3736                                                   is_inside=0)
3737
3738         data = "A" * 4 + "B" * 16 + "C" * 3
3739         random.randint(1025, 65535)
3740
3741         # in2out
3742         pkts = self.create_stream_frag(self.pg0,
3743                                        self.pg1.remote_ip4,
3744                                        self.tcp_port_in,
3745                                        20,
3746                                        data)
3747         pkts.reverse()
3748         self.pg0.add_stream(pkts)
3749         self.pg_enable_capture(self.pg_interfaces)
3750         self.pg_start()
3751         frags = self.pg1.get_capture(len(pkts))
3752         p = self.reass_frags_and_verify(frags,
3753                                         self.nat_addr,
3754                                         self.pg1.remote_ip4)
3755         self.assertEqual(p[TCP].dport, 20)
3756         self.assertNotEqual(p[TCP].sport, self.tcp_port_in)
3757         self.tcp_port_out = p[TCP].sport
3758         self.assertEqual(data, p[Raw].load)
3759
3760         # out2in
3761         pkts = self.create_stream_frag(self.pg1,
3762                                        self.nat_addr,
3763                                        20,
3764                                        self.tcp_port_out,
3765                                        data)
3766         pkts.reverse()
3767         self.pg1.add_stream(pkts)
3768         self.pg_enable_capture(self.pg_interfaces)
3769         self.pg_start()
3770         frags = self.pg0.get_capture(len(pkts))
3771         p = self.reass_frags_and_verify(frags,
3772                                         self.pg1.remote_ip4,
3773                                         self.pg0.remote_ip4)
3774         self.assertEqual(p[TCP].sport, 20)
3775         self.assertEqual(p[TCP].dport, self.tcp_port_in)
3776         self.assertEqual(data, p[Raw].load)
3777
3778     def test_port_restricted(self):
3779         """ Port restricted NAT44 (MAP-E CE) """
3780         self.nat44_add_address(self.nat_addr)
3781         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3782         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3783                                                   is_inside=0)
3784         self.vapi.cli("nat addr-port-assignment-alg map-e psid 10 "
3785                       "psid-offset 6 psid-len 6")
3786
3787         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3788              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3789              TCP(sport=4567, dport=22))
3790         self.pg0.add_stream(p)
3791         self.pg_enable_capture(self.pg_interfaces)
3792         self.pg_start()
3793         capture = self.pg1.get_capture(1)
3794         p = capture[0]
3795         try:
3796             ip = p[IP]
3797             tcp = p[TCP]
3798             self.assertEqual(ip.dst, self.pg1.remote_ip4)
3799             self.assertEqual(ip.src, self.nat_addr)
3800             self.assertEqual(tcp.dport, 22)
3801             self.assertNotEqual(tcp.sport, 4567)
3802             self.assertEqual((tcp.sport >> 6) & 63, 10)
3803             self.assert_packet_checksums_valid(p)
3804         except:
3805             self.logger.error(ppp("Unexpected or invalid packet:", p))
3806             raise
3807
3808     def twice_nat_common(self, self_twice_nat=False, same_pg=False, lb=False,
3809                          client_id=None):
3810         twice_nat_addr = '10.0.1.3'
3811
3812         port_in = 8080
3813         if lb:
3814             if not same_pg:
3815                 port_in1 = port_in
3816                 port_in2 = port_in
3817             else:
3818                 port_in1 = port_in+1
3819                 port_in2 = port_in+2
3820
3821         port_out = 80
3822         eh_port_out = 4567
3823
3824         server1 = self.pg0.remote_hosts[0]
3825         server2 = self.pg0.remote_hosts[1]
3826         if lb and same_pg:
3827             server2 = server1
3828         if not lb:
3829             server = server1
3830
3831         pg0 = self.pg0
3832         if same_pg:
3833             pg1 = self.pg0
3834         else:
3835             pg1 = self.pg1
3836
3837         eh_translate = ((not self_twice_nat) or (not lb and same_pg) or
3838                         client_id == 1)
3839
3840         self.nat44_add_address(self.nat_addr)
3841         self.nat44_add_address(twice_nat_addr, twice_nat=1)
3842         if not lb:
3843             self.nat44_add_static_mapping(pg0.remote_ip4, self.nat_addr,
3844                                           port_in, port_out,
3845                                           proto=IP_PROTOS.tcp,
3846                                           twice_nat=int(not self_twice_nat),
3847                                           self_twice_nat=int(self_twice_nat))
3848         else:
3849             locals = [{'addr': server1.ip4n,
3850                        'port': port_in1,
3851                        'probability': 50},
3852                       {'addr': server2.ip4n,
3853                        'port': port_in2,
3854                        'probability': 50}]
3855             out_addr_n = socket.inet_pton(socket.AF_INET, self.nat_addr)
3856             self.vapi.nat44_add_del_lb_static_mapping(out_addr_n,
3857                                                       port_out,
3858                                                       IP_PROTOS.tcp,
3859                                                       twice_nat=int(
3860                                                           not self_twice_nat),
3861                                                       self_twice_nat=int(
3862                                                           self_twice_nat),
3863                                                       local_num=len(locals),
3864                                                       locals=locals)
3865         self.vapi.nat44_interface_add_del_feature(pg0.sw_if_index)
3866         self.vapi.nat44_interface_add_del_feature(pg1.sw_if_index,
3867                                                   is_inside=0)
3868
3869         if same_pg:
3870             if not lb:
3871                 client = server
3872             else:
3873                 assert client_id is not None
3874                 if client_id == 1:
3875                     client = self.pg0.remote_hosts[0]
3876                 elif client_id == 2:
3877                     client = self.pg0.remote_hosts[1]
3878         else:
3879             client = pg1.remote_hosts[0]
3880         p = (Ether(src=pg1.remote_mac, dst=pg1.local_mac) /
3881              IP(src=client.ip4, dst=self.nat_addr) /
3882              TCP(sport=eh_port_out, dport=port_out))
3883         pg1.add_stream(p)
3884         self.pg_enable_capture(self.pg_interfaces)
3885         self.pg_start()
3886         capture = pg0.get_capture(1)
3887         p = capture[0]
3888         try:
3889             ip = p[IP]
3890             tcp = p[TCP]
3891             if lb:
3892                 if ip.dst == server1.ip4:
3893                     server = server1
3894                     port_in = port_in1
3895                 else:
3896                     server = server2
3897                     port_in = port_in2
3898             self.assertEqual(ip.dst, server.ip4)
3899             if lb and same_pg:
3900                 self.assertIn(tcp.dport, [port_in1, port_in2])
3901             else:
3902                 self.assertEqual(tcp.dport, port_in)
3903             if eh_translate:
3904                 self.assertEqual(ip.src, twice_nat_addr)
3905                 self.assertNotEqual(tcp.sport, eh_port_out)
3906             else:
3907                 self.assertEqual(ip.src, client.ip4)
3908                 self.assertEqual(tcp.sport, eh_port_out)
3909             eh_addr_in = ip.src
3910             eh_port_in = tcp.sport
3911             saved_port_in = tcp.dport
3912             self.assert_packet_checksums_valid(p)
3913         except:
3914             self.logger.error(ppp("Unexpected or invalid packet:", p))
3915             raise
3916
3917         p = (Ether(src=server.mac, dst=pg0.local_mac) /
3918              IP(src=server.ip4, dst=eh_addr_in) /
3919              TCP(sport=saved_port_in, dport=eh_port_in))
3920         pg0.add_stream(p)
3921         self.pg_enable_capture(self.pg_interfaces)
3922         self.pg_start()
3923         capture = pg1.get_capture(1)
3924         p = capture[0]
3925         try:
3926             ip = p[IP]
3927             tcp = p[TCP]
3928             self.assertEqual(ip.dst, client.ip4)
3929             self.assertEqual(ip.src, self.nat_addr)
3930             self.assertEqual(tcp.dport, eh_port_out)
3931             self.assertEqual(tcp.sport, port_out)
3932             self.assert_packet_checksums_valid(p)
3933         except:
3934             self.logger.error(ppp("Unexpected or invalid packet:", p))
3935             raise
3936
3937         if eh_translate:
3938             sessions = self.vapi.nat44_user_session_dump(server.ip4n, 0)
3939             self.assertEqual(len(sessions), 1)
3940             self.assertTrue(sessions[0].ext_host_valid)
3941             self.assertTrue(sessions[0].is_twicenat)
3942             self.vapi.nat44_del_session(
3943                 sessions[0].inside_ip_address,
3944                 sessions[0].inside_port,
3945                 sessions[0].protocol,
3946                 ext_host_address=sessions[0].ext_host_nat_address,
3947                 ext_host_port=sessions[0].ext_host_nat_port)
3948             sessions = self.vapi.nat44_user_session_dump(server.ip4n, 0)
3949             self.assertEqual(len(sessions), 0)
3950
3951     def test_twice_nat(self):
3952         """ Twice NAT44 """
3953         self.twice_nat_common()
3954
3955     def test_self_twice_nat_positive(self):
3956         """ Self Twice NAT44 (positive test) """
3957         self.twice_nat_common(self_twice_nat=True, same_pg=True)
3958
3959     def test_self_twice_nat_negative(self):
3960         """ Self Twice NAT44 (negative test) """
3961         self.twice_nat_common(self_twice_nat=True)
3962
3963     def test_twice_nat_lb(self):
3964         """ Twice NAT44 local service load balancing """
3965         self.twice_nat_common(lb=True)
3966
3967     def test_self_twice_nat_lb_positive(self):
3968         """ Self Twice NAT44 local service load balancing (positive test) """
3969         self.twice_nat_common(lb=True, self_twice_nat=True, same_pg=True,
3970                               client_id=1)
3971
3972     def test_self_twice_nat_lb_negative(self):
3973         """ Self Twice NAT44 local service load balancing (negative test) """
3974         self.twice_nat_common(lb=True, self_twice_nat=True, same_pg=True,
3975                               client_id=2)
3976
3977     def test_twice_nat_interface_addr(self):
3978         """ Acquire twice NAT44 addresses from interface """
3979         self.vapi.nat44_add_interface_addr(self.pg7.sw_if_index, twice_nat=1)
3980
3981         # no address in NAT pool
3982         adresses = self.vapi.nat44_address_dump()
3983         self.assertEqual(0, len(adresses))
3984
3985         # configure interface address and check NAT address pool
3986         self.pg7.config_ip4()
3987         adresses = self.vapi.nat44_address_dump()
3988         self.assertEqual(1, len(adresses))
3989         self.assertEqual(adresses[0].ip_address[0:4], self.pg7.local_ip4n)
3990         self.assertEqual(adresses[0].twice_nat, 1)
3991
3992         # remove interface address and check NAT address pool
3993         self.pg7.unconfig_ip4()
3994         adresses = self.vapi.nat44_address_dump()
3995         self.assertEqual(0, len(adresses))
3996
3997     def test_ipfix_max_frags(self):
3998         """ IPFIX logging maximum fragments pending reassembly exceeded """
3999         self.nat44_add_address(self.nat_addr)
4000         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4001         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4002                                                   is_inside=0)
4003         self.vapi.nat_set_reass(max_frag=0)
4004         self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
4005                                      src_address=self.pg3.local_ip4n,
4006                                      path_mtu=512,
4007                                      template_interval=10)
4008         self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
4009                             src_port=self.ipfix_src_port)
4010
4011         data = "A" * 4 + "B" * 16 + "C" * 3
4012         self.tcp_port_in = random.randint(1025, 65535)
4013         pkts = self.create_stream_frag(self.pg0,
4014                                        self.pg1.remote_ip4,
4015                                        self.tcp_port_in,
4016                                        20,
4017                                        data)
4018         self.pg0.add_stream(pkts[-1])
4019         self.pg_enable_capture(self.pg_interfaces)
4020         self.pg_start()
4021         frags = self.pg1.get_capture(0)
4022         self.vapi.cli("ipfix flush")  # FIXME this should be an API call
4023         capture = self.pg3.get_capture(9)
4024         ipfix = IPFIXDecoder()
4025         # first load template
4026         for p in capture:
4027             self.assertTrue(p.haslayer(IPFIX))
4028             self.assertEqual(p[IP].src, self.pg3.local_ip4)
4029             self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
4030             self.assertEqual(p[UDP].sport, self.ipfix_src_port)
4031             self.assertEqual(p[UDP].dport, 4739)
4032             self.assertEqual(p[IPFIX].observationDomainID,
4033                              self.ipfix_domain_id)
4034             if p.haslayer(Template):
4035                 ipfix.add_template(p.getlayer(Template))
4036         # verify events in data set
4037         for p in capture:
4038             if p.haslayer(Data):
4039                 data = ipfix.decode_data_set(p.getlayer(Set))
4040                 self.verify_ipfix_max_fragments_ip4(data, 0,
4041                                                     self.pg0.remote_ip4n)
4042
4043     def test_tcp_session_close_in(self):
4044         """ Close TCP session from inside network """
4045         self.nat44_add_address(self.nat_addr)
4046         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4047         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4048                                                   is_inside=0)
4049
4050         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
4051         start_sessnum = len(sessions)
4052
4053         self.initiate_tcp_session(self.pg0, self.pg1)
4054
4055         # close the session from inside
4056         try:
4057             # FIN packet in -> out
4058             p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4059                  IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4060                  TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
4061                      flags="FA", seq=100, ack=300))
4062             self.pg0.add_stream(p)
4063             self.pg_enable_capture(self.pg_interfaces)
4064             self.pg_start()
4065             self.pg1.get_capture(1)
4066
4067             pkts = []
4068
4069             # ACK packet out -> in
4070             p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4071                  IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4072                  TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
4073                      flags="A", seq=300, ack=101))
4074             pkts.append(p)
4075
4076             # FIN packet out -> in
4077             p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4078                  IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4079                  TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
4080                      flags="FA", seq=300, ack=101))
4081             pkts.append(p)
4082
4083             self.pg1.add_stream(pkts)
4084             self.pg_enable_capture(self.pg_interfaces)
4085             self.pg_start()
4086             self.pg0.get_capture(2)
4087
4088             # ACK packet in -> out
4089             p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4090                  IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4091                  TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
4092                      flags="A", seq=101, ack=301))
4093             self.pg0.add_stream(p)
4094             self.pg_enable_capture(self.pg_interfaces)
4095             self.pg_start()
4096             self.pg1.get_capture(1)
4097
4098             self.initiate_tcp_session(self.pg0, self.pg1)
4099             sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n,
4100                                                          0)
4101             self.assertEqual(len(sessions) - start_sessnum, 1)
4102         except:
4103             self.logger.error("TCP session termination failed")
4104             raise
4105
4106     def test_tcp_session_close_out(self):
4107         """ Close TCP session from outside network """
4108         self.nat44_add_address(self.nat_addr)
4109         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4110         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4111                                                   is_inside=0)
4112
4113         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
4114         start_sessnum = len(sessions)
4115
4116         self.initiate_tcp_session(self.pg0, self.pg1)
4117
4118         # close the session from outside
4119         try:
4120             # FIN packet out -> in
4121             p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4122                  IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4123                  TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
4124                      flags="FA", seq=100, ack=300))
4125             self.pg1.add_stream(p)
4126             self.pg_enable_capture(self.pg_interfaces)
4127             self.pg_start()
4128             self.pg0.get_capture(1)
4129
4130             # FIN+ACK packet in -> out
4131             p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4132                  IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4133                  TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
4134                      flags="FA", seq=300, ack=101))
4135
4136             self.pg0.add_stream(p)
4137             self.pg_enable_capture(self.pg_interfaces)
4138             self.pg_start()
4139             self.pg1.get_capture(1)
4140
4141             # ACK packet out -> in
4142             p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4143                  IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4144                  TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
4145                      flags="A", seq=101, ack=301))
4146             self.pg1.add_stream(p)
4147             self.pg_enable_capture(self.pg_interfaces)
4148             self.pg_start()
4149             self.pg0.get_capture(1)
4150
4151             self.initiate_tcp_session(self.pg0, self.pg1)
4152             sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n,
4153                                                          0)
4154             self.assertEqual(len(sessions) - start_sessnum, 1)
4155         except:
4156             self.logger.error("TCP session termination failed")
4157             raise
4158
4159     def test_tcp_session_close_simultaneous(self):
4160         """ Close TCP session from inside network """
4161         self.nat44_add_address(self.nat_addr)
4162         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4163         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4164                                                   is_inside=0)
4165
4166         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
4167         start_sessnum = len(sessions)
4168
4169         self.initiate_tcp_session(self.pg0, self.pg1)
4170
4171         # close the session from inside
4172         try:
4173             # FIN packet in -> out
4174             p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4175                  IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4176                  TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
4177                      flags="FA", seq=100, ack=300))
4178             self.pg0.add_stream(p)
4179             self.pg_enable_capture(self.pg_interfaces)
4180             self.pg_start()
4181             self.pg1.get_capture(1)
4182
4183             # FIN packet out -> in
4184             p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4185                  IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4186                  TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
4187                      flags="FA", seq=300, ack=100))
4188             self.pg1.add_stream(p)
4189             self.pg_enable_capture(self.pg_interfaces)
4190             self.pg_start()
4191             self.pg0.get_capture(1)
4192
4193             # ACK packet in -> out
4194             p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4195                  IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4196                  TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
4197                      flags="A", seq=101, ack=301))
4198             self.pg0.add_stream(p)
4199             self.pg_enable_capture(self.pg_interfaces)
4200             self.pg_start()
4201             self.pg1.get_capture(1)
4202
4203             # ACK packet out -> in
4204             p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4205                  IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4206                  TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
4207                      flags="A", seq=301, ack=101))
4208             self.pg1.add_stream(p)
4209             self.pg_enable_capture(self.pg_interfaces)
4210             self.pg_start()
4211             self.pg0.get_capture(1)
4212
4213             self.initiate_tcp_session(self.pg0, self.pg1)
4214             sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n,
4215                                                          0)
4216             self.assertEqual(len(sessions) - start_sessnum, 1)
4217         except:
4218             self.logger.error("TCP session termination failed")
4219             raise
4220
4221     def tearDown(self):
4222         super(TestNAT44, self).tearDown()
4223         if not self.vpp_dead:
4224             self.logger.info(self.vapi.cli("show nat44 addresses"))
4225             self.logger.info(self.vapi.cli("show nat44 interfaces"))
4226             self.logger.info(self.vapi.cli("show nat44 static mappings"))
4227             self.logger.info(self.vapi.cli("show nat44 interface address"))
4228             self.logger.info(self.vapi.cli("show nat44 sessions detail"))
4229             self.logger.info(self.vapi.cli("show nat virtual-reassembly"))
4230             self.vapi.cli("nat addr-port-assignment-alg default")
4231             self.clear_nat44()
4232
4233
4234 class TestNAT44Out2InDPO(MethodHolder):
4235     """ NAT44 Test Cases using out2in DPO """
4236
4237     @classmethod
4238     def setUpConstants(cls):
4239         super(TestNAT44Out2InDPO, cls).setUpConstants()
4240         cls.vpp_cmdline.extend(["nat", "{", "out2in dpo", "}"])
4241
4242     @classmethod
4243     def setUpClass(cls):
4244         super(TestNAT44Out2InDPO, cls).setUpClass()
4245
4246         try:
4247             cls.tcp_port_in = 6303
4248             cls.tcp_port_out = 6303
4249             cls.udp_port_in = 6304
4250             cls.udp_port_out = 6304
4251             cls.icmp_id_in = 6305
4252             cls.icmp_id_out = 6305
4253             cls.nat_addr = '10.0.0.3'
4254             cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
4255             cls.dst_ip4 = '192.168.70.1'
4256
4257             cls.create_pg_interfaces(range(2))
4258
4259             cls.pg0.admin_up()
4260             cls.pg0.config_ip4()
4261             cls.pg0.resolve_arp()
4262
4263             cls.pg1.admin_up()
4264             cls.pg1.config_ip6()
4265             cls.pg1.resolve_ndp()
4266
4267             cls.vapi.ip_add_del_route(is_ipv6=True, dst_address='\x00'*16,
4268                                       dst_address_length=0,
4269                                       next_hop_address=cls.pg1.remote_ip6n,
4270                                       next_hop_sw_if_index=cls.pg1.sw_if_index)
4271
4272         except Exception:
4273             super(TestNAT44Out2InDPO, cls).tearDownClass()
4274             raise
4275
4276     def configure_xlat(self):
4277         self.dst_ip6_pfx = '1:2:3::'
4278         self.dst_ip6_pfx_n = socket.inet_pton(socket.AF_INET6,
4279                                               self.dst_ip6_pfx)
4280         self.dst_ip6_pfx_len = 96
4281         self.src_ip6_pfx = '4:5:6::'
4282         self.src_ip6_pfx_n = socket.inet_pton(socket.AF_INET6,
4283                                               self.src_ip6_pfx)
4284         self.src_ip6_pfx_len = 96
4285         self.vapi.map_add_domain(self.dst_ip6_pfx_n, self.dst_ip6_pfx_len,
4286                                  self.src_ip6_pfx_n, self.src_ip6_pfx_len,
4287                                  '\x00\x00\x00\x00', 0, is_translation=1,
4288                                  is_rfc6052=1)
4289
4290     def test_464xlat_ce(self):
4291         """ Test 464XLAT CE with NAT44 """
4292
4293         self.configure_xlat()
4294
4295         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4296         self.vapi.nat44_add_del_address_range(self.nat_addr_n, self.nat_addr_n)
4297
4298         out_src_ip6 = self.compose_ip6(self.dst_ip4, self.dst_ip6_pfx,
4299                                        self.dst_ip6_pfx_len)
4300         out_dst_ip6 = self.compose_ip6(self.nat_addr, self.src_ip6_pfx,
4301                                        self.src_ip6_pfx_len)
4302
4303         try:
4304             pkts = self.create_stream_in(self.pg0, self.pg1, self.dst_ip4)
4305             self.pg0.add_stream(pkts)
4306             self.pg_enable_capture(self.pg_interfaces)
4307             self.pg_start()
4308             capture = self.pg1.get_capture(len(pkts))
4309             self.verify_capture_out_ip6(capture, nat_ip=out_dst_ip6,
4310                                         dst_ip=out_src_ip6)
4311
4312             pkts = self.create_stream_out_ip6(self.pg1, out_src_ip6,
4313                                               out_dst_ip6)
4314             self.pg1.add_stream(pkts)
4315             self.pg_enable_capture(self.pg_interfaces)
4316             self.pg_start()
4317             capture = self.pg0.get_capture(len(pkts))
4318             self.verify_capture_in(capture, self.pg0)
4319         finally:
4320             self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
4321                                                       is_add=0)
4322             self.vapi.nat44_add_del_address_range(self.nat_addr_n,
4323                                                   self.nat_addr_n, is_add=0)
4324
4325     def test_464xlat_ce_no_nat(self):
4326         """ Test 464XLAT CE without NAT44 """
4327
4328         self.configure_xlat()
4329
4330         out_src_ip6 = self.compose_ip6(self.dst_ip4, self.dst_ip6_pfx,
4331                                        self.dst_ip6_pfx_len)
4332         out_dst_ip6 = self.compose_ip6(self.pg0.remote_ip4, self.src_ip6_pfx,
4333                                        self.src_ip6_pfx_len)
4334
4335         pkts = self.create_stream_in(self.pg0, self.pg1, self.dst_ip4)
4336         self.pg0.add_stream(pkts)
4337         self.pg_enable_capture(self.pg_interfaces)
4338         self.pg_start()
4339         capture = self.pg1.get_capture(len(pkts))
4340         self.verify_capture_out_ip6(capture, dst_ip=out_src_ip6,
4341                                     nat_ip=out_dst_ip6, same_port=True)
4342
4343         pkts = self.create_stream_out_ip6(self.pg1, out_src_ip6, out_dst_ip6)
4344         self.pg1.add_stream(pkts)
4345         self.pg_enable_capture(self.pg_interfaces)
4346         self.pg_start()
4347         capture = self.pg0.get_capture(len(pkts))
4348         self.verify_capture_in(capture, self.pg0)
4349
4350
4351 class TestDeterministicNAT(MethodHolder):
4352     """ Deterministic NAT Test Cases """
4353
4354     @classmethod
4355     def setUpConstants(cls):
4356         super(TestDeterministicNAT, cls).setUpConstants()
4357         cls.vpp_cmdline.extend(["nat", "{", "deterministic", "}"])
4358
4359     @classmethod
4360     def setUpClass(cls):
4361         super(TestDeterministicNAT, cls).setUpClass()
4362
4363         try:
4364             cls.tcp_port_in = 6303
4365             cls.tcp_external_port = 6303
4366             cls.udp_port_in = 6304
4367             cls.udp_external_port = 6304
4368             cls.icmp_id_in = 6305
4369             cls.nat_addr = '10.0.0.3'
4370
4371             cls.create_pg_interfaces(range(3))
4372             cls.interfaces = list(cls.pg_interfaces)
4373
4374             for i in cls.interfaces:
4375                 i.admin_up()
4376                 i.config_ip4()
4377                 i.resolve_arp()
4378
4379             cls.pg0.generate_remote_hosts(2)
4380             cls.pg0.configure_ipv4_neighbors()
4381
4382         except Exception:
4383             super(TestDeterministicNAT, cls).tearDownClass()
4384             raise
4385
4386     def create_stream_in(self, in_if, out_if, ttl=64):
4387         """
4388         Create packet stream for inside network
4389
4390         :param in_if: Inside interface
4391         :param out_if: Outside interface
4392         :param ttl: TTL of generated packets
4393         """
4394         pkts = []
4395         # TCP
4396         p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
4397              IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
4398              TCP(sport=self.tcp_port_in, dport=self.tcp_external_port))
4399         pkts.append(p)
4400
4401         # UDP
4402         p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
4403              IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
4404              UDP(sport=self.udp_port_in, dport=self.udp_external_port))
4405         pkts.append(p)
4406
4407         # ICMP
4408         p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
4409              IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
4410              ICMP(id=self.icmp_id_in, type='echo-request'))
4411         pkts.append(p)
4412
4413         return pkts
4414
4415     def create_stream_out(self, out_if, dst_ip=None, ttl=64):
4416         """
4417         Create packet stream for outside network
4418
4419         :param out_if: Outside interface
4420         :param dst_ip: Destination IP address (Default use global NAT address)
4421         :param ttl: TTL of generated packets
4422         """
4423         if dst_ip is None:
4424             dst_ip = self.nat_addr
4425         pkts = []
4426         # TCP
4427         p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
4428              IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
4429              TCP(dport=self.tcp_port_out, sport=self.tcp_external_port))
4430         pkts.append(p)
4431
4432         # UDP
4433         p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
4434              IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
4435              UDP(dport=self.udp_port_out, sport=self.udp_external_port))
4436         pkts.append(p)
4437
4438         # ICMP
4439         p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
4440              IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
4441              ICMP(id=self.icmp_external_id, type='echo-reply'))
4442         pkts.append(p)
4443
4444         return pkts
4445
4446     def verify_capture_out(self, capture, nat_ip=None, packet_num=3):
4447         """
4448         Verify captured packets on outside network
4449
4450         :param capture: Captured packets
4451         :param nat_ip: Translated IP address (Default use global NAT address)
4452         :param same_port: Sorce port number is not translated (Default False)
4453         :param packet_num: Expected number of packets (Default 3)
4454         """
4455         if nat_ip is None:
4456             nat_ip = self.nat_addr
4457         self.assertEqual(packet_num, len(capture))
4458         for packet in capture:
4459             try:
4460                 self.assertEqual(packet[IP].src, nat_ip)
4461                 if packet.haslayer(TCP):
4462                     self.tcp_port_out = packet[TCP].sport
4463                 elif packet.haslayer(UDP):
4464                     self.udp_port_out = packet[UDP].sport
4465                 else:
4466                     self.icmp_external_id = packet[ICMP].id
4467             except:
4468                 self.logger.error(ppp("Unexpected or invalid packet "
4469                                       "(outside network):", packet))
4470                 raise
4471
4472     def verify_ipfix_max_entries_per_user(self, data):
4473         """
4474         Verify IPFIX maximum entries per user exceeded event
4475
4476         :param data: Decoded IPFIX data records
4477         """
4478         self.assertEqual(1, len(data))
4479         record = data[0]
4480         # natEvent
4481         self.assertEqual(ord(record[230]), 13)
4482         # natQuotaExceededEvent
4483         self.assertEqual('\x03\x00\x00\x00', record[466])
4484         # maxEntriesPerUser
4485         self.assertEqual('\xe8\x03\x00\x00', record[473])
4486         # sourceIPv4Address
4487         self.assertEqual(self.pg0.remote_ip4n, record[8])
4488
4489     def test_deterministic_mode(self):
4490         """ NAT plugin run deterministic mode """
4491         in_addr = '172.16.255.0'
4492         out_addr = '172.17.255.50'
4493         in_addr_t = '172.16.255.20'
4494         in_addr_n = socket.inet_aton(in_addr)
4495         out_addr_n = socket.inet_aton(out_addr)
4496         in_addr_t_n = socket.inet_aton(in_addr_t)
4497         in_plen = 24
4498         out_plen = 32
4499
4500         nat_config = self.vapi.nat_show_config()
4501         self.assertEqual(1, nat_config.deterministic)
4502
4503         self.vapi.nat_det_add_del_map(in_addr_n, in_plen, out_addr_n, out_plen)
4504
4505         rep1 = self.vapi.nat_det_forward(in_addr_t_n)
4506         self.assertEqual(rep1.out_addr[:4], out_addr_n)
4507         rep2 = self.vapi.nat_det_reverse(out_addr_n, rep1.out_port_hi)
4508         self.assertEqual(rep2.in_addr[:4], in_addr_t_n)
4509
4510         deterministic_mappings = self.vapi.nat_det_map_dump()
4511         self.assertEqual(len(deterministic_mappings), 1)
4512         dsm = deterministic_mappings[0]
4513         self.assertEqual(in_addr_n, dsm.in_addr[:4])
4514         self.assertEqual(in_plen, dsm.in_plen)
4515         self.assertEqual(out_addr_n, dsm.out_addr[:4])
4516         self.assertEqual(out_plen, dsm.out_plen)
4517
4518         self.clear_nat_det()
4519         deterministic_mappings = self.vapi.nat_det_map_dump()
4520         self.assertEqual(len(deterministic_mappings), 0)
4521
4522     def test_set_timeouts(self):
4523         """ Set deterministic NAT timeouts """
4524         timeouts_before = self.vapi.nat_det_get_timeouts()
4525
4526         self.vapi.nat_det_set_timeouts(timeouts_before.udp + 10,
4527                                        timeouts_before.tcp_established + 10,
4528                                        timeouts_before.tcp_transitory + 10,
4529                                        timeouts_before.icmp + 10)
4530
4531         timeouts_after = self.vapi.nat_det_get_timeouts()
4532
4533         self.assertNotEqual(timeouts_before.udp, timeouts_after.udp)
4534         self.assertNotEqual(timeouts_before.icmp, timeouts_after.icmp)
4535         self.assertNotEqual(timeouts_before.tcp_established,
4536                             timeouts_after.tcp_established)
4537         self.assertNotEqual(timeouts_before.tcp_transitory,
4538                             timeouts_after.tcp_transitory)
4539
4540     def test_det_in(self):
4541         """ Deterministic NAT translation test (TCP, UDP, ICMP) """
4542
4543         nat_ip = "10.0.0.10"
4544
4545         self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
4546                                       32,
4547                                       socket.inet_aton(nat_ip),
4548                                       32)
4549         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4550         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4551                                                   is_inside=0)
4552
4553         # in2out
4554         pkts = self.create_stream_in(self.pg0, self.pg1)
4555         self.pg0.add_stream(pkts)
4556         self.pg_enable_capture(self.pg_interfaces)
4557         self.pg_start()
4558         capture = self.pg1.get_capture(len(pkts))
4559         self.verify_capture_out(capture, nat_ip)
4560
4561         # out2in
4562         pkts = self.create_stream_out(self.pg1, nat_ip)
4563         self.pg1.add_stream(pkts)
4564         self.pg_enable_capture(self.pg_interfaces)
4565         self.pg_start()
4566         capture = self.pg0.get_capture(len(pkts))
4567         self.verify_capture_in(capture, self.pg0)
4568
4569         # session dump test
4570         sessions = self.vapi.nat_det_session_dump(self.pg0.remote_ip4n)
4571         self.assertEqual(len(sessions), 3)
4572
4573         # TCP session
4574         s = sessions[0]
4575         self.assertEqual(s.ext_addr[:4], self.pg1.remote_ip4n)
4576         self.assertEqual(s.in_port, self.tcp_port_in)
4577         self.assertEqual(s.out_port, self.tcp_port_out)
4578         self.assertEqual(s.ext_port, self.tcp_external_port)
4579
4580         # UDP session
4581         s = sessions[1]
4582         self.assertEqual(s.ext_addr[:4], self.pg1.remote_ip4n)
4583         self.assertEqual(s.in_port, self.udp_port_in)
4584         self.assertEqual(s.out_port, self.udp_port_out)
4585         self.assertEqual(s.ext_port, self.udp_external_port)
4586
4587         # ICMP session
4588         s = sessions[2]
4589         self.assertEqual(s.ext_addr[:4], self.pg1.remote_ip4n)
4590         self.assertEqual(s.in_port, self.icmp_id_in)
4591         self.assertEqual(s.out_port, self.icmp_external_id)
4592
4593     def test_multiple_users(self):
4594         """ Deterministic NAT multiple users """
4595
4596         nat_ip = "10.0.0.10"
4597         port_in = 80
4598         external_port = 6303
4599
4600         host0 = self.pg0.remote_hosts[0]
4601         host1 = self.pg0.remote_hosts[1]
4602
4603         self.vapi.nat_det_add_del_map(host0.ip4n,
4604                                       24,
4605                                       socket.inet_aton(nat_ip),
4606                                       32)
4607         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4608         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4609                                                   is_inside=0)
4610
4611         # host0 to out
4612         p = (Ether(src=host0.mac, dst=self.pg0.local_mac) /
4613              IP(src=host0.ip4, dst=self.pg1.remote_ip4) /
4614              TCP(sport=port_in, dport=external_port))
4615         self.pg0.add_stream(p)
4616         self.pg_enable_capture(self.pg_interfaces)
4617         self.pg_start()
4618         capture = self.pg1.get_capture(1)
4619         p = capture[0]
4620         try:
4621             ip = p[IP]
4622             tcp = p[TCP]
4623             self.assertEqual(ip.src, nat_ip)
4624             self.assertEqual(ip.dst, self.pg1.remote_ip4)
4625             self.assertEqual(tcp.dport, external_port)
4626             port_out0 = tcp.sport
4627         except:
4628             self.logger.error(ppp("Unexpected or invalid packet:", p))
4629             raise
4630
4631         # host1 to out
4632         p = (Ether(src=host1.mac, dst=self.pg0.local_mac) /
4633              IP(src=host1.ip4, dst=self.pg1.remote_ip4) /
4634              TCP(sport=port_in, dport=external_port))
4635         self.pg0.add_stream(p)
4636         self.pg_enable_capture(self.pg_interfaces)
4637         self.pg_start()
4638         capture = self.pg1.get_capture(1)
4639         p = capture[0]
4640         try:
4641             ip = p[IP]
4642             tcp = p[TCP]
4643             self.assertEqual(ip.src, nat_ip)
4644             self.assertEqual(ip.dst, self.pg1.remote_ip4)
4645             self.assertEqual(tcp.dport, external_port)
4646             port_out1 = tcp.sport
4647         except:
4648             self.logger.error(ppp("Unexpected or invalid packet:", p))
4649             raise
4650
4651         dms = self.vapi.nat_det_map_dump()
4652         self.assertEqual(1, len(dms))
4653         self.assertEqual(2, dms[0].ses_num)
4654
4655         # out to host0
4656         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4657              IP(src=self.pg1.remote_ip4, dst=nat_ip) /
4658              TCP(sport=external_port, dport=port_out0))
4659         self.pg1.add_stream(p)
4660         self.pg_enable_capture(self.pg_interfaces)
4661         self.pg_start()
4662         capture = self.pg0.get_capture(1)
4663         p = capture[0]
4664         try:
4665             ip = p[IP]
4666             tcp = p[TCP]
4667             self.assertEqual(ip.src, self.pg1.remote_ip4)
4668             self.assertEqual(ip.dst, host0.ip4)
4669             self.assertEqual(tcp.dport, port_in)
4670             self.assertEqual(tcp.sport, external_port)
4671         except:
4672             self.logger.error(ppp("Unexpected or invalid packet:", p))
4673             raise
4674
4675         # out to host1
4676         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4677              IP(src=self.pg1.remote_ip4, dst=nat_ip) /
4678              TCP(sport=external_port, dport=port_out1))
4679         self.pg1.add_stream(p)
4680         self.pg_enable_capture(self.pg_interfaces)
4681         self.pg_start()
4682         capture = self.pg0.get_capture(1)
4683         p = capture[0]
4684         try:
4685             ip = p[IP]
4686             tcp = p[TCP]
4687             self.assertEqual(ip.src, self.pg1.remote_ip4)
4688             self.assertEqual(ip.dst, host1.ip4)
4689             self.assertEqual(tcp.dport, port_in)
4690             self.assertEqual(tcp.sport, external_port)
4691         except:
4692             self.logger.error(ppp("Unexpected or invalid packet", p))
4693             raise
4694
4695         # session close api test
4696         self.vapi.nat_det_close_session_out(socket.inet_aton(nat_ip),
4697                                             port_out1,
4698                                             self.pg1.remote_ip4n,
4699                                             external_port)
4700         dms = self.vapi.nat_det_map_dump()
4701         self.assertEqual(dms[0].ses_num, 1)
4702
4703         self.vapi.nat_det_close_session_in(host0.ip4n,
4704                                            port_in,
4705                                            self.pg1.remote_ip4n,
4706                                            external_port)
4707         dms = self.vapi.nat_det_map_dump()
4708         self.assertEqual(dms[0].ses_num, 0)
4709
4710     def test_tcp_session_close_detection_in(self):
4711         """ Deterministic NAT TCP session close from inside network """
4712         self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
4713                                       32,
4714                                       socket.inet_aton(self.nat_addr),
4715                                       32)
4716         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4717         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4718                                                   is_inside=0)
4719
4720         self.initiate_tcp_session(self.pg0, self.pg1)
4721
4722         # close the session from inside
4723         try:
4724             # FIN packet in -> out
4725             p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4726                  IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4727                  TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
4728                      flags="F"))
4729             self.pg0.add_stream(p)
4730             self.pg_enable_capture(self.pg_interfaces)
4731             self.pg_start()
4732             self.pg1.get_capture(1)
4733
4734             pkts = []
4735
4736             # ACK packet out -> in
4737             p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4738                  IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4739                  TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
4740                      flags="A"))
4741             pkts.append(p)
4742
4743             # FIN packet out -> in
4744             p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4745                  IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4746                  TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
4747                      flags="F"))
4748             pkts.append(p)
4749
4750             self.pg1.add_stream(pkts)
4751             self.pg_enable_capture(self.pg_interfaces)
4752             self.pg_start()
4753             self.pg0.get_capture(2)
4754
4755             # ACK packet in -> out
4756             p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4757                  IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4758                  TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
4759                      flags="A"))
4760             self.pg0.add_stream(p)
4761             self.pg_enable_capture(self.pg_interfaces)
4762             self.pg_start()
4763             self.pg1.get_capture(1)
4764
4765             # Check if deterministic NAT44 closed the session
4766             dms = self.vapi.nat_det_map_dump()
4767             self.assertEqual(0, dms[0].ses_num)
4768         except:
4769             self.logger.error("TCP session termination failed")
4770             raise
4771
4772     def test_tcp_session_close_detection_out(self):
4773         """ Deterministic NAT TCP session close from outside network """
4774         self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
4775                                       32,
4776                                       socket.inet_aton(self.nat_addr),
4777                                       32)
4778         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4779         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4780                                                   is_inside=0)
4781
4782         self.initiate_tcp_session(self.pg0, self.pg1)
4783
4784         # close the session from outside
4785         try:
4786             # FIN packet out -> in
4787             p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4788                  IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4789                  TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
4790                      flags="F"))
4791             self.pg1.add_stream(p)
4792             self.pg_enable_capture(self.pg_interfaces)
4793             self.pg_start()
4794             self.pg0.get_capture(1)
4795
4796             pkts = []
4797
4798             # ACK packet in -> out
4799             p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4800                  IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4801                  TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
4802                      flags="A"))
4803             pkts.append(p)
4804
4805             # ACK packet in -> out
4806             p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4807                  IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4808                  TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
4809                      flags="F"))
4810             pkts.append(p)
4811
4812             self.pg0.add_stream(pkts)
4813             self.pg_enable_capture(self.pg_interfaces)
4814             self.pg_start()
4815             self.pg1.get_capture(2)
4816
4817             # ACK packet out -> in
4818             p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4819                  IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4820                  TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
4821                      flags="A"))
4822             self.pg1.add_stream(p)
4823             self.pg_enable_capture(self.pg_interfaces)
4824             self.pg_start()
4825             self.pg0.get_capture(1)
4826
4827             # Check if deterministic NAT44 closed the session
4828             dms = self.vapi.nat_det_map_dump()
4829             self.assertEqual(0, dms[0].ses_num)
4830         except:
4831             self.logger.error("TCP session termination failed")
4832             raise
4833
4834     @unittest.skipUnless(running_extended_tests(), "part of extended tests")
4835     def test_session_timeout(self):
4836         """ Deterministic NAT session timeouts """
4837         self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
4838                                       32,
4839                                       socket.inet_aton(self.nat_addr),
4840                                       32)
4841         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4842         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4843                                                   is_inside=0)
4844
4845         self.initiate_tcp_session(self.pg0, self.pg1)
4846         self.vapi.nat_det_set_timeouts(5, 5, 5, 5)
4847         pkts = self.create_stream_in(self.pg0, self.pg1)
4848         self.pg0.add_stream(pkts)
4849         self.pg_enable_capture(self.pg_interfaces)
4850         self.pg_start()
4851         capture = self.pg1.get_capture(len(pkts))
4852         sleep(15)
4853
4854         dms = self.vapi.nat_det_map_dump()
4855         self.assertEqual(0, dms[0].ses_num)
4856
4857     @unittest.skipUnless(running_extended_tests(), "part of extended tests")
4858     def test_session_limit_per_user(self):
4859         """ Deterministic NAT maximum sessions per user limit """
4860         self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
4861                                       32,
4862                                       socket.inet_aton(self.nat_addr),
4863                                       32)
4864         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4865         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4866                                                   is_inside=0)
4867         self.vapi.set_ipfix_exporter(collector_address=self.pg2.remote_ip4n,
4868                                      src_address=self.pg2.local_ip4n,
4869                                      path_mtu=512,
4870                                      template_interval=10)
4871         self.vapi.nat_ipfix()
4872
4873         pkts = []
4874         for port in range(1025, 2025):
4875             p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4876                  IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4877                  UDP(sport=port, dport=port))
4878             pkts.append(p)
4879
4880         self.pg0.add_stream(pkts)
4881         self.pg_enable_capture(self.pg_interfaces)
4882         self.pg_start()
4883         capture = self.pg1.get_capture(len(pkts))
4884
4885         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4886              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4887              UDP(sport=3001, dport=3002))
4888         self.pg0.add_stream(p)
4889         self.pg_enable_capture(self.pg_interfaces)
4890         self.pg_start()
4891         capture = self.pg1.assert_nothing_captured()
4892
4893         # verify ICMP error packet
4894         capture = self.pg0.get_capture(1)
4895         p = capture[0]
4896         self.assertTrue(p.haslayer(ICMP))
4897         icmp = p[ICMP]
4898         self.assertEqual(icmp.type, 3)
4899         self.assertEqual(icmp.code, 1)
4900         self.assertTrue(icmp.haslayer(IPerror))
4901         inner_ip = icmp[IPerror]
4902         self.assertEqual(inner_ip[UDPerror].sport, 3001)
4903         self.assertEqual(inner_ip[UDPerror].dport, 3002)
4904
4905         dms = self.vapi.nat_det_map_dump()
4906
4907         self.assertEqual(1000, dms[0].ses_num)
4908
4909         # verify IPFIX logging
4910         self.vapi.cli("ipfix flush")  # FIXME this should be an API call
4911         sleep(1)
4912         capture = self.pg2.get_capture(2)
4913         ipfix = IPFIXDecoder()
4914         # first load template
4915         for p in capture:
4916             self.assertTrue(p.haslayer(IPFIX))
4917             if p.haslayer(Template):
4918                 ipfix.add_template(p.getlayer(Template))
4919         # verify events in data set
4920         for p in capture:
4921             if p.haslayer(Data):
4922                 data = ipfix.decode_data_set(p.getlayer(Set))
4923                 self.verify_ipfix_max_entries_per_user(data)
4924
4925     def clear_nat_det(self):
4926         """
4927         Clear deterministic NAT configuration.
4928         """
4929         self.vapi.nat_ipfix(enable=0)
4930         self.vapi.nat_det_set_timeouts()
4931         deterministic_mappings = self.vapi.nat_det_map_dump()
4932         for dsm in deterministic_mappings:
4933             self.vapi.nat_det_add_del_map(dsm.in_addr,
4934                                           dsm.in_plen,
4935                                           dsm.out_addr,
4936                                           dsm.out_plen,
4937                                           is_add=0)
4938
4939         interfaces = self.vapi.nat44_interface_dump()
4940         for intf in interfaces:
4941             self.vapi.nat44_interface_add_del_feature(intf.sw_if_index,
4942                                                       intf.is_inside,
4943                                                       is_add=0)
4944
4945     def tearDown(self):
4946         super(TestDeterministicNAT, self).tearDown()
4947         if not self.vpp_dead:
4948             self.logger.info(self.vapi.cli("show nat44 interfaces"))
4949             self.logger.info(
4950                 self.vapi.cli("show nat44 deterministic mappings"))
4951             self.logger.info(
4952                 self.vapi.cli("show nat44 deterministic timeouts"))
4953             self.logger.info(
4954                 self.vapi.cli("show nat44 deterministic sessions"))
4955             self.clear_nat_det()
4956
4957
4958 class TestNAT64(MethodHolder):
4959     """ NAT64 Test Cases """
4960
4961     @classmethod
4962     def setUpConstants(cls):
4963         super(TestNAT64, cls).setUpConstants()
4964         cls.vpp_cmdline.extend(["nat", "{", "nat64 bib hash buckets 128",
4965                                 "nat64 st hash buckets 256", "}"])
4966
4967     @classmethod
4968     def setUpClass(cls):
4969         super(TestNAT64, cls).setUpClass()
4970
4971         try:
4972             cls.tcp_port_in = 6303
4973             cls.tcp_port_out = 6303
4974             cls.udp_port_in = 6304
4975             cls.udp_port_out = 6304
4976             cls.icmp_id_in = 6305
4977             cls.icmp_id_out = 6305
4978             cls.nat_addr = '10.0.0.3'
4979             cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
4980             cls.vrf1_id = 10
4981             cls.vrf1_nat_addr = '10.0.10.3'
4982             cls.vrf1_nat_addr_n = socket.inet_pton(socket.AF_INET,
4983                                                    cls.vrf1_nat_addr)
4984             cls.ipfix_src_port = 4739
4985             cls.ipfix_domain_id = 1
4986
4987             cls.create_pg_interfaces(range(5))
4988             cls.ip6_interfaces = list(cls.pg_interfaces[0:1])
4989             cls.ip6_interfaces.append(cls.pg_interfaces[2])
4990             cls.ip4_interfaces = list(cls.pg_interfaces[1:2])
4991
4992             cls.vapi.ip_table_add_del(cls.vrf1_id, is_add=1, is_ipv6=1)
4993
4994             cls.pg_interfaces[2].set_table_ip6(cls.vrf1_id)
4995
4996             cls.pg0.generate_remote_hosts(2)
4997
4998             for i in cls.ip6_interfaces:
4999                 i.admin_up()
5000                 i.config_ip6()
5001                 i.configure_ipv6_neighbors()
5002
5003             for i in cls.ip4_interfaces:
5004                 i.admin_up()
5005                 i.config_ip4()
5006                 i.resolve_arp()
5007
5008             cls.pg3.admin_up()
5009             cls.pg3.config_ip4()
5010             cls.pg3.resolve_arp()
5011             cls.pg3.config_ip6()
5012             cls.pg3.configure_ipv6_neighbors()
5013
5014         except Exception:
5015             super(TestNAT64, cls).tearDownClass()
5016             raise
5017
5018     def test_pool(self):
5019         """ Add/delete address to NAT64 pool """
5020         nat_addr = socket.inet_pton(socket.AF_INET, '1.2.3.4')
5021
5022         self.vapi.nat64_add_del_pool_addr_range(nat_addr, nat_addr)
5023
5024         addresses = self.vapi.nat64_pool_addr_dump()
5025         self.assertEqual(len(addresses), 1)
5026         self.assertEqual(addresses[0].address, nat_addr)
5027
5028         self.vapi.nat64_add_del_pool_addr_range(nat_addr, nat_addr, is_add=0)
5029
5030         addresses = self.vapi.nat64_pool_addr_dump()
5031         self.assertEqual(len(addresses), 0)
5032
5033     def test_interface(self):
5034         """ Enable/disable NAT64 feature on the interface """
5035         self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
5036         self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
5037
5038         interfaces = self.vapi.nat64_interface_dump()
5039         self.assertEqual(len(interfaces), 2)
5040         pg0_found = False
5041         pg1_found = False
5042         for intf in interfaces:
5043             if intf.sw_if_index == self.pg0.sw_if_index:
5044                 self.assertEqual(intf.is_inside, 1)
5045                 pg0_found = True
5046             elif intf.sw_if_index == self.pg1.sw_if_index:
5047                 self.assertEqual(intf.is_inside, 0)
5048                 pg1_found = True
5049         self.assertTrue(pg0_found)
5050         self.assertTrue(pg1_found)
5051
5052         features = self.vapi.cli("show interface features pg0")
5053         self.assertNotEqual(features.find('nat64-in2out'), -1)
5054         features = self.vapi.cli("show interface features pg1")
5055         self.assertNotEqual(features.find('nat64-out2in'), -1)
5056
5057         self.vapi.nat64_add_del_interface(self.pg0.sw_if_index, is_add=0)
5058         self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_add=0)
5059
5060         interfaces = self.vapi.nat64_interface_dump()
5061         self.assertEqual(len(interfaces), 0)
5062
5063     def test_static_bib(self):
5064         """ Add/delete static BIB entry """
5065         in_addr = socket.inet_pton(socket.AF_INET6,
5066                                    '2001:db8:85a3::8a2e:370:7334')
5067         out_addr = socket.inet_pton(socket.AF_INET, '10.1.1.3')
5068         in_port = 1234
5069         out_port = 5678
5070         proto = IP_PROTOS.tcp
5071
5072         self.vapi.nat64_add_del_static_bib(in_addr,
5073                                            out_addr,
5074                                            in_port,
5075                                            out_port,
5076                                            proto)
5077         bib = self.vapi.nat64_bib_dump(IP_PROTOS.tcp)
5078         static_bib_num = 0
5079         for bibe in bib:
5080             if bibe.is_static:
5081                 static_bib_num += 1
5082                 self.assertEqual(bibe.i_addr, in_addr)
5083                 self.assertEqual(bibe.o_addr, out_addr)
5084                 self.assertEqual(bibe.i_port, in_port)
5085                 self.assertEqual(bibe.o_port, out_port)
5086         self.assertEqual(static_bib_num, 1)
5087
5088         self.vapi.nat64_add_del_static_bib(in_addr,
5089                                            out_addr,
5090                                            in_port,
5091                                            out_port,
5092                                            proto,
5093                                            is_add=0)
5094         bib = self.vapi.nat64_bib_dump(IP_PROTOS.tcp)
5095         static_bib_num = 0
5096         for bibe in bib:
5097             if bibe.is_static:
5098                 static_bib_num += 1
5099         self.assertEqual(static_bib_num, 0)
5100
5101     def test_set_timeouts(self):
5102         """ Set NAT64 timeouts """
5103         # verify default values
5104         timeouts = self.vapi.nat64_get_timeouts()
5105         self.assertEqual(timeouts.udp, 300)
5106         self.assertEqual(timeouts.icmp, 60)
5107         self.assertEqual(timeouts.tcp_trans, 240)
5108         self.assertEqual(timeouts.tcp_est, 7440)
5109         self.assertEqual(timeouts.tcp_incoming_syn, 6)
5110
5111         # set and verify custom values
5112         self.vapi.nat64_set_timeouts(udp=200, icmp=30, tcp_trans=250,
5113                                      tcp_est=7450, tcp_incoming_syn=10)
5114         timeouts = self.vapi.nat64_get_timeouts()
5115         self.assertEqual(timeouts.udp, 200)
5116         self.assertEqual(timeouts.icmp, 30)
5117         self.assertEqual(timeouts.tcp_trans, 250)
5118         self.assertEqual(timeouts.tcp_est, 7450)
5119         self.assertEqual(timeouts.tcp_incoming_syn, 10)
5120
5121     def test_dynamic(self):
5122         """ NAT64 dynamic translation test """
5123         self.tcp_port_in = 6303
5124         self.udp_port_in = 6304
5125         self.icmp_id_in = 6305
5126
5127         ses_num_start = self.nat64_get_ses_num()
5128
5129         self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
5130                                                 self.nat_addr_n)
5131         self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
5132         self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
5133
5134         # in2out
5135         pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
5136         self.pg0.add_stream(pkts)
5137         self.pg_enable_capture(self.pg_interfaces)
5138         self.pg_start()
5139         capture = self.pg1.get_capture(len(pkts))
5140         self.verify_capture_out(capture, nat_ip=self.nat_addr,
5141                                 dst_ip=self.pg1.remote_ip4)
5142
5143         # out2in
5144         pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
5145         self.pg1.add_stream(pkts)
5146         self.pg_enable_capture(self.pg_interfaces)
5147         self.pg_start()
5148         capture = self.pg0.get_capture(len(pkts))
5149         ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
5150         self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
5151
5152         # in2out
5153         pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
5154         self.pg0.add_stream(pkts)
5155         self.pg_enable_capture(self.pg_interfaces)
5156         self.pg_start()
5157         capture = self.pg1.get_capture(len(pkts))
5158         self.verify_capture_out(capture, nat_ip=self.nat_addr,
5159                                 dst_ip=self.pg1.remote_ip4)
5160
5161         # out2in
5162         pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
5163         self.pg1.add_stream(pkts)
5164         self.pg_enable_capture(self.pg_interfaces)
5165         self.pg_start()
5166         capture = self.pg0.get_capture(len(pkts))
5167         self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
5168
5169         ses_num_end = self.nat64_get_ses_num()
5170
5171         self.assertEqual(ses_num_end - ses_num_start, 3)
5172
5173         # tenant with specific VRF
5174         self.vapi.nat64_add_del_pool_addr_range(self.vrf1_nat_addr_n,
5175                                                 self.vrf1_nat_addr_n,
5176                                                 vrf_id=self.vrf1_id)
5177         self.vapi.nat64_add_del_interface(self.pg2.sw_if_index)
5178
5179         pkts = self.create_stream_in_ip6(self.pg2, self.pg1)
5180         self.pg2.add_stream(pkts)
5181         self.pg_enable_capture(self.pg_interfaces)
5182         self.pg_start()
5183         capture = self.pg1.get_capture(len(pkts))
5184         self.verify_capture_out(capture, nat_ip=self.vrf1_nat_addr,
5185                                 dst_ip=self.pg1.remote_ip4)
5186
5187         pkts = self.create_stream_out(self.pg1, dst_ip=self.vrf1_nat_addr)
5188         self.pg1.add_stream(pkts)
5189         self.pg_enable_capture(self.pg_interfaces)
5190         self.pg_start()
5191         capture = self.pg2.get_capture(len(pkts))
5192         self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg2.remote_ip6)
5193
5194     def test_static(self):
5195         """ NAT64 static translation test """
5196         self.tcp_port_in = 60303
5197         self.udp_port_in = 60304
5198         self.icmp_id_in = 60305
5199         self.tcp_port_out = 60303
5200         self.udp_port_out = 60304
5201         self.icmp_id_out = 60305
5202
5203         ses_num_start = self.nat64_get_ses_num()
5204
5205         self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
5206                                                 self.nat_addr_n)
5207         self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
5208         self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
5209
5210         self.vapi.nat64_add_del_static_bib(self.pg0.remote_ip6n,
5211                                            self.nat_addr_n,
5212                                            self.tcp_port_in,
5213                                            self.tcp_port_out,
5214                                            IP_PROTOS.tcp)
5215         self.vapi.nat64_add_del_static_bib(self.pg0.remote_ip6n,
5216                                            self.nat_addr_n,
5217                                            self.udp_port_in,
5218                                            self.udp_port_out,
5219                                            IP_PROTOS.udp)
5220         self.vapi.nat64_add_del_static_bib(self.pg0.remote_ip6n,
5221                                            self.nat_addr_n,
5222                                            self.icmp_id_in,
5223                                            self.icmp_id_out,
5224                                            IP_PROTOS.icmp)
5225
5226         # in2out
5227         pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
5228         self.pg0.add_stream(pkts)
5229         self.pg_enable_capture(self.pg_interfaces)
5230         self.pg_start()
5231         capture = self.pg1.get_capture(len(pkts))
5232         self.verify_capture_out(capture, nat_ip=self.nat_addr,
5233                                 dst_ip=self.pg1.remote_ip4, same_port=True)
5234
5235         # out2in
5236         pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
5237         self.pg1.add_stream(pkts)
5238         self.pg_enable_capture(self.pg_interfaces)
5239         self.pg_start()
5240         capture = self.pg0.get_capture(len(pkts))
5241         ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
5242         self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
5243
5244         ses_num_end = self.nat64_get_ses_num()
5245
5246         self.assertEqual(ses_num_end - ses_num_start, 3)
5247
5248     @unittest.skipUnless(running_extended_tests(), "part of extended tests")
5249     def test_session_timeout(self):
5250         """ NAT64 session timeout """
5251         self.icmp_id_in = 1234
5252         self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
5253                                                 self.nat_addr_n)
5254         self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
5255         self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
5256         self.vapi.nat64_set_timeouts(icmp=5)
5257
5258         pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
5259         self.pg0.add_stream(pkts)
5260         self.pg_enable_capture(self.pg_interfaces)
5261         self.pg_start()
5262         capture = self.pg1.get_capture(len(pkts))
5263
5264         ses_num_before_timeout = self.nat64_get_ses_num()
5265
5266         sleep(15)
5267
5268         # ICMP session after timeout
5269         ses_num_after_timeout = self.nat64_get_ses_num()
5270         self.assertNotEqual(ses_num_before_timeout, ses_num_after_timeout)
5271
5272     def test_icmp_error(self):
5273         """ NAT64 ICMP Error message translation """
5274         self.tcp_port_in = 6303
5275         self.udp_port_in = 6304
5276         self.icmp_id_in = 6305
5277
5278         self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
5279                                                 self.nat_addr_n)
5280         self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
5281         self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
5282
5283         # send some packets to create sessions
5284         pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
5285         self.pg0.add_stream(pkts)
5286         self.pg_enable_capture(self.pg_interfaces)
5287         self.pg_start()
5288         capture_ip4 = self.pg1.get_capture(len(pkts))
5289         self.verify_capture_out(capture_ip4,
5290                                 nat_ip=self.nat_addr,
5291                                 dst_ip=self.pg1.remote_ip4)
5292
5293         pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
5294         self.pg1.add_stream(pkts)
5295         self.pg_enable_capture(self.pg_interfaces)
5296         self.pg_start()
5297         capture_ip6 = self.pg0.get_capture(len(pkts))
5298         ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
5299         self.verify_capture_in_ip6(capture_ip6, ip[IPv6].src,
5300                                    self.pg0.remote_ip6)
5301
5302         # in2out
5303         pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5304                 IPv6(src=self.pg0.remote_ip6, dst=ip[IPv6].src) /
5305                 ICMPv6DestUnreach(code=1) /
5306                 packet[IPv6] for packet in capture_ip6]
5307         self.pg0.add_stream(pkts)
5308         self.pg_enable_capture(self.pg_interfaces)
5309         self.pg_start()
5310         capture = self.pg1.get_capture(len(pkts))
5311         for packet in capture:
5312             try:
5313                 self.assertEqual(packet[IP].src, self.nat_addr)
5314                 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
5315                 self.assertEqual(packet[ICMP].type, 3)
5316                 self.assertEqual(packet[ICMP].code, 13)
5317                 inner = packet[IPerror]
5318                 self.assertEqual(inner.src, self.pg1.remote_ip4)
5319                 self.assertEqual(inner.dst, self.nat_addr)
5320                 self.assert_packet_checksums_valid(packet)
5321                 if inner.haslayer(TCPerror):
5322                     self.assertEqual(inner[TCPerror].dport, self.tcp_port_out)
5323                 elif inner.haslayer(UDPerror):
5324                     self.assertEqual(inner[UDPerror].dport, self.udp_port_out)
5325                 else:
5326                     self.assertEqual(inner[ICMPerror].id, self.icmp_id_out)
5327             except:
5328                 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5329                 raise
5330
5331         # out2in
5332         pkts = [Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
5333                 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5334                 ICMP(type=3, code=13) /
5335                 packet[IP] for packet in capture_ip4]
5336         self.pg1.add_stream(pkts)
5337         self.pg_enable_capture(self.pg_interfaces)
5338         self.pg_start()
5339         capture = self.pg0.get_capture(len(pkts))
5340         for packet in capture:
5341             try:
5342                 self.assertEqual(packet[IPv6].src, ip.src)
5343                 self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
5344                 icmp = packet[ICMPv6DestUnreach]
5345                 self.assertEqual(icmp.code, 1)
5346                 inner = icmp[IPerror6]
5347                 self.assertEqual(inner.src, self.pg0.remote_ip6)
5348                 self.assertEqual(inner.dst, ip.src)
5349                 self.assert_icmpv6_checksum_valid(packet)
5350                 if inner.haslayer(TCPerror):
5351                     self.assertEqual(inner[TCPerror].sport, self.tcp_port_in)
5352                 elif inner.haslayer(UDPerror):
5353                     self.assertEqual(inner[UDPerror].sport, self.udp_port_in)
5354                 else:
5355                     self.assertEqual(inner[ICMPv6EchoRequest].id,
5356                                      self.icmp_id_in)
5357             except:
5358                 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5359                 raise
5360
5361     def test_hairpinning(self):
5362         """ NAT64 hairpinning """
5363
5364         client = self.pg0.remote_hosts[0]
5365         server = self.pg0.remote_hosts[1]
5366         server_tcp_in_port = 22
5367         server_tcp_out_port = 4022
5368         server_udp_in_port = 23
5369         server_udp_out_port = 4023
5370         client_tcp_in_port = 1234
5371         client_udp_in_port = 1235
5372         client_tcp_out_port = 0
5373         client_udp_out_port = 0
5374         ip = IPv6(src=''.join(['64:ff9b::', self.nat_addr]))
5375         nat_addr_ip6 = ip.src
5376
5377         self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
5378                                                 self.nat_addr_n)
5379         self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
5380         self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
5381
5382         self.vapi.nat64_add_del_static_bib(server.ip6n,
5383                                            self.nat_addr_n,
5384                                            server_tcp_in_port,
5385                                            server_tcp_out_port,
5386                                            IP_PROTOS.tcp)
5387         self.vapi.nat64_add_del_static_bib(server.ip6n,
5388                                            self.nat_addr_n,
5389                                            server_udp_in_port,
5390                                            server_udp_out_port,
5391                                            IP_PROTOS.udp)
5392
5393         # client to server
5394         pkts = []
5395         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5396              IPv6(src=client.ip6, dst=nat_addr_ip6) /
5397              TCP(sport=client_tcp_in_port, dport=server_tcp_out_port))
5398         pkts.append(p)
5399         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5400              IPv6(src=client.ip6, dst=nat_addr_ip6) /
5401              UDP(sport=client_udp_in_port, dport=server_udp_out_port))
5402         pkts.append(p)
5403         self.pg0.add_stream(pkts)
5404         self.pg_enable_capture(self.pg_interfaces)
5405         self.pg_start()
5406         capture = self.pg0.get_capture(len(pkts))
5407         for packet in capture:
5408             try:
5409                 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
5410                 self.assertEqual(packet[IPv6].dst, server.ip6)
5411                 self.assert_packet_checksums_valid(packet)
5412                 if packet.haslayer(TCP):
5413                     self.assertNotEqual(packet[TCP].sport, client_tcp_in_port)
5414                     self.assertEqual(packet[TCP].dport, server_tcp_in_port)
5415                     client_tcp_out_port = packet[TCP].sport
5416                 else:
5417                     self.assertNotEqual(packet[UDP].sport, client_udp_in_port)
5418                     self.assertEqual(packet[UDP].dport, server_udp_in_port)
5419                     client_udp_out_port = packet[UDP].sport
5420             except:
5421                 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5422                 raise
5423
5424         # server to client
5425         pkts = []
5426         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5427              IPv6(src=server.ip6, dst=nat_addr_ip6) /
5428              TCP(sport=server_tcp_in_port, dport=client_tcp_out_port))
5429         pkts.append(p)
5430         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5431              IPv6(src=server.ip6, dst=nat_addr_ip6) /
5432              UDP(sport=server_udp_in_port, dport=client_udp_out_port))
5433         pkts.append(p)
5434         self.pg0.add_stream(pkts)
5435         self.pg_enable_capture(self.pg_interfaces)
5436         self.pg_start()
5437         capture = self.pg0.get_capture(len(pkts))
5438         for packet in capture:
5439             try:
5440                 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
5441                 self.assertEqual(packet[IPv6].dst, client.ip6)
5442                 self.assert_packet_checksums_valid(packet)
5443                 if packet.haslayer(TCP):
5444                     self.assertEqual(packet[TCP].sport, server_tcp_out_port)
5445                     self.assertEqual(packet[TCP].dport, client_tcp_in_port)
5446                 else:
5447                     self.assertEqual(packet[UDP].sport, server_udp_out_port)
5448                     self.assertEqual(packet[UDP].dport, client_udp_in_port)
5449             except:
5450                 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5451                 raise
5452
5453         # ICMP error
5454         pkts = []
5455         pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5456                 IPv6(src=client.ip6, dst=nat_addr_ip6) /
5457                 ICMPv6DestUnreach(code=1) /
5458                 packet[IPv6] for packet in capture]
5459         self.pg0.add_stream(pkts)
5460         self.pg_enable_capture(self.pg_interfaces)
5461         self.pg_start()
5462         capture = self.pg0.get_capture(len(pkts))
5463         for packet in capture:
5464             try:
5465                 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
5466                 self.assertEqual(packet[IPv6].dst, server.ip6)
5467                 icmp = packet[ICMPv6DestUnreach]
5468                 self.assertEqual(icmp.code, 1)
5469                 inner = icmp[IPerror6]
5470                 self.assertEqual(inner.src, server.ip6)
5471                 self.assertEqual(inner.dst, nat_addr_ip6)
5472                 self.assert_packet_checksums_valid(packet)
5473                 if inner.haslayer(TCPerror):
5474                     self.assertEqual(inner[TCPerror].sport, server_tcp_in_port)
5475                     self.assertEqual(inner[TCPerror].dport,
5476                                      client_tcp_out_port)
5477                 else:
5478                     self.assertEqual(inner[UDPerror].sport, server_udp_in_port)
5479                     self.assertEqual(inner[UDPerror].dport,
5480                                      client_udp_out_port)
5481             except:
5482                 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5483                 raise
5484
5485     def test_prefix(self):
5486         """ NAT64 Network-Specific Prefix """
5487
5488         self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
5489                                                 self.nat_addr_n)
5490         self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
5491         self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
5492         self.vapi.nat64_add_del_pool_addr_range(self.vrf1_nat_addr_n,
5493                                                 self.vrf1_nat_addr_n,
5494                                                 vrf_id=self.vrf1_id)
5495         self.vapi.nat64_add_del_interface(self.pg2.sw_if_index)
5496
5497         # Add global prefix
5498         global_pref64 = "2001:db8::"
5499         global_pref64_n = socket.inet_pton(socket.AF_INET6, global_pref64)
5500         global_pref64_len = 32
5501         self.vapi.nat64_add_del_prefix(global_pref64_n, global_pref64_len)
5502
5503         prefix = self.vapi.nat64_prefix_dump()
5504         self.assertEqual(len(prefix), 1)
5505         self.assertEqual(prefix[0].prefix, global_pref64_n)
5506         self.assertEqual(prefix[0].prefix_len, global_pref64_len)
5507         self.assertEqual(prefix[0].vrf_id, 0)
5508
5509         # Add tenant specific prefix
5510         vrf1_pref64 = "2001:db8:122:300::"
5511         vrf1_pref64_n = socket.inet_pton(socket.AF_INET6, vrf1_pref64)
5512         vrf1_pref64_len = 56
5513         self.vapi.nat64_add_del_prefix(vrf1_pref64_n,
5514                                        vrf1_pref64_len,
5515                                        vrf_id=self.vrf1_id)
5516         prefix = self.vapi.nat64_prefix_dump()
5517         self.assertEqual(len(prefix), 2)
5518
5519         # Global prefix
5520         pkts = self.create_stream_in_ip6(self.pg0,
5521                                          self.pg1,
5522                                          pref=global_pref64,
5523                                          plen=global_pref64_len)
5524         self.pg0.add_stream(pkts)
5525         self.pg_enable_capture(self.pg_interfaces)
5526         self.pg_start()
5527         capture = self.pg1.get_capture(len(pkts))
5528         self.verify_capture_out(capture, nat_ip=self.nat_addr,
5529                                 dst_ip=self.pg1.remote_ip4)
5530
5531         pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
5532         self.pg1.add_stream(pkts)
5533         self.pg_enable_capture(self.pg_interfaces)
5534         self.pg_start()
5535         capture = self.pg0.get_capture(len(pkts))
5536         dst_ip = self.compose_ip6(self.pg1.remote_ip4,
5537                                   global_pref64,
5538                                   global_pref64_len)
5539         self.verify_capture_in_ip6(capture, dst_ip, self.pg0.remote_ip6)
5540
5541         # Tenant specific prefix
5542         pkts = self.create_stream_in_ip6(self.pg2,
5543                                          self.pg1,
5544                                          pref=vrf1_pref64,
5545                                          plen=vrf1_pref64_len)
5546         self.pg2.add_stream(pkts)
5547         self.pg_enable_capture(self.pg_interfaces)
5548         self.pg_start()
5549         capture = self.pg1.get_capture(len(pkts))
5550         self.verify_capture_out(capture, nat_ip=self.vrf1_nat_addr,
5551                                 dst_ip=self.pg1.remote_ip4)
5552
5553         pkts = self.create_stream_out(self.pg1, dst_ip=self.vrf1_nat_addr)
5554         self.pg1.add_stream(pkts)
5555         self.pg_enable_capture(self.pg_interfaces)
5556         self.pg_start()
5557         capture = self.pg2.get_capture(len(pkts))
5558         dst_ip = self.compose_ip6(self.pg1.remote_ip4,
5559                                   vrf1_pref64,
5560                                   vrf1_pref64_len)
5561         self.verify_capture_in_ip6(capture, dst_ip, self.pg2.remote_ip6)
5562
5563     def test_unknown_proto(self):
5564         """ NAT64 translate packet with unknown protocol """
5565
5566         self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
5567                                                 self.nat_addr_n)
5568         self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
5569         self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
5570         remote_ip6 = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
5571
5572         # in2out
5573         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5574              IPv6(src=self.pg0.remote_ip6, dst=remote_ip6) /
5575              TCP(sport=self.tcp_port_in, dport=20))
5576         self.pg0.add_stream(p)
5577         self.pg_enable_capture(self.pg_interfaces)
5578         self.pg_start()
5579         p = self.pg1.get_capture(1)
5580
5581         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5582              IPv6(src=self.pg0.remote_ip6, dst=remote_ip6, nh=47) /
5583              GRE() /
5584              IP(src=self.pg2.local_ip4, dst=self.pg2.remote_ip4) /
5585              TCP(sport=1234, dport=1234))
5586         self.pg0.add_stream(p)
5587         self.pg_enable_capture(self.pg_interfaces)
5588         self.pg_start()
5589         p = self.pg1.get_capture(1)
5590         packet = p[0]
5591         try:
5592             self.assertEqual(packet[IP].src, self.nat_addr)
5593             self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
5594             self.assertTrue(packet.haslayer(GRE))
5595             self.assert_packet_checksums_valid(packet)
5596         except:
5597             self.logger.error(ppp("Unexpected or invalid packet:", packet))
5598             raise
5599
5600         # out2in
5601         p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
5602              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5603              GRE() /
5604              IP(src=self.pg2.remote_ip4, dst=self.pg2.local_ip4) /
5605              TCP(sport=1234, dport=1234))
5606         self.pg1.add_stream(p)
5607         self.pg_enable_capture(self.pg_interfaces)
5608         self.pg_start()
5609         p = self.pg0.get_capture(1)
5610         packet = p[0]
5611         try:
5612             self.assertEqual(packet[IPv6].src, remote_ip6)
5613             self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
5614             self.assertEqual(packet[IPv6].nh, 47)
5615         except:
5616             self.logger.error(ppp("Unexpected or invalid packet:", packet))
5617             raise
5618
5619     def test_hairpinning_unknown_proto(self):
5620         """ NAT64 translate packet with unknown protocol - hairpinning """
5621
5622         client = self.pg0.remote_hosts[0]
5623         server = self.pg0.remote_hosts[1]
5624         server_tcp_in_port = 22
5625         server_tcp_out_port = 4022
5626         client_tcp_in_port = 1234
5627         client_tcp_out_port = 1235
5628         server_nat_ip = "10.0.0.100"
5629         client_nat_ip = "10.0.0.110"
5630         server_nat_ip_n = socket.inet_pton(socket.AF_INET, server_nat_ip)
5631         client_nat_ip_n = socket.inet_pton(socket.AF_INET, client_nat_ip)
5632         server_nat_ip6 = self.compose_ip6(server_nat_ip, '64:ff9b::', 96)
5633         client_nat_ip6 = self.compose_ip6(client_nat_ip, '64:ff9b::', 96)
5634
5635         self.vapi.nat64_add_del_pool_addr_range(server_nat_ip_n,
5636                                                 client_nat_ip_n)
5637         self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
5638         self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
5639
5640         self.vapi.nat64_add_del_static_bib(server.ip6n,
5641                                            server_nat_ip_n,
5642                                            server_tcp_in_port,
5643                                            server_tcp_out_port,
5644                                            IP_PROTOS.tcp)
5645
5646         self.vapi.nat64_add_del_static_bib(server.ip6n,
5647                                            server_nat_ip_n,
5648                                            0,
5649                                            0,
5650                                            IP_PROTOS.gre)
5651
5652         self.vapi.nat64_add_del_static_bib(client.ip6n,
5653                                            client_nat_ip_n,
5654                                            client_tcp_in_port,
5655                                            client_tcp_out_port,
5656                                            IP_PROTOS.tcp)
5657
5658         # client to server
5659         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5660              IPv6(src=client.ip6, dst=server_nat_ip6) /
5661              TCP(sport=client_tcp_in_port, dport=server_tcp_out_port))
5662         self.pg0.add_stream(p)
5663         self.pg_enable_capture(self.pg_interfaces)
5664         self.pg_start()
5665         p = self.pg0.get_capture(1)
5666
5667         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5668              IPv6(src=client.ip6, dst=server_nat_ip6, nh=IP_PROTOS.gre) /
5669              GRE() /
5670              IP(src=self.pg2.local_ip4, dst=self.pg2.remote_ip4) /
5671              TCP(sport=1234, dport=1234))
5672         self.pg0.add_stream(p)
5673         self.pg_enable_capture(self.pg_interfaces)
5674         self.pg_start()
5675         p = self.pg0.get_capture(1)
5676         packet = p[0]
5677         try:
5678             self.assertEqual(packet[IPv6].src, client_nat_ip6)
5679             self.assertEqual(packet[IPv6].dst, server.ip6)
5680             self.assertEqual(packet[IPv6].nh, IP_PROTOS.gre)
5681         except:
5682             self.logger.error(ppp("Unexpected or invalid packet:", packet))
5683             raise
5684
5685         # server to client
5686         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5687              IPv6(src=server.ip6, dst=client_nat_ip6, nh=IP_PROTOS.gre) /
5688              GRE() /
5689              IP(src=self.pg2.remote_ip4, dst=self.pg2.local_ip4) /
5690              TCP(sport=1234, dport=1234))
5691         self.pg0.add_stream(p)
5692         self.pg_enable_capture(self.pg_interfaces)
5693         self.pg_start()
5694         p = self.pg0.get_capture(1)
5695         packet = p[0]
5696         try:
5697             self.assertEqual(packet[IPv6].src, server_nat_ip6)
5698             self.assertEqual(packet[IPv6].dst, client.ip6)
5699             self.assertEqual(packet[IPv6].nh, IP_PROTOS.gre)
5700         except:
5701             self.logger.error(ppp("Unexpected or invalid packet:", packet))
5702             raise
5703
5704     def test_one_armed_nat64(self):
5705         """ One armed NAT64 """
5706         external_port = 0
5707         remote_host_ip6 = self.compose_ip6(self.pg3.remote_ip4,
5708                                            '64:ff9b::',
5709                                            96)
5710
5711         self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
5712                                                 self.nat_addr_n)
5713         self.vapi.nat64_add_del_interface(self.pg3.sw_if_index)
5714         self.vapi.nat64_add_del_interface(self.pg3.sw_if_index, is_inside=0)
5715
5716         # in2out
5717         p = (Ether(src=self.pg3.remote_mac, dst=self.pg3.local_mac) /
5718              IPv6(src=self.pg3.remote_ip6, dst=remote_host_ip6) /
5719              TCP(sport=12345, dport=80))
5720         self.pg3.add_stream(p)
5721         self.pg_enable_capture(self.pg_interfaces)
5722         self.pg_start()
5723         capture = self.pg3.get_capture(1)
5724         p = capture[0]
5725         try:
5726             ip = p[IP]
5727             tcp = p[TCP]
5728             self.assertEqual(ip.src, self.nat_addr)
5729             self.assertEqual(ip.dst, self.pg3.remote_ip4)
5730             self.assertNotEqual(tcp.sport, 12345)
5731             external_port = tcp.sport
5732             self.assertEqual(tcp.dport, 80)
5733             self.assert_packet_checksums_valid(p)
5734         except:
5735             self.logger.error(ppp("Unexpected or invalid packet:", p))
5736             raise
5737
5738         # out2in
5739         p = (Ether(src=self.pg3.remote_mac, dst=self.pg3.local_mac) /
5740              IP(src=self.pg3.remote_ip4, dst=self.nat_addr) /
5741              TCP(sport=80, dport=external_port))
5742         self.pg3.add_stream(p)
5743         self.pg_enable_capture(self.pg_interfaces)
5744         self.pg_start()
5745         capture = self.pg3.get_capture(1)
5746         p = capture[0]
5747         try:
5748             ip = p[IPv6]
5749             tcp = p[TCP]
5750             self.assertEqual(ip.src, remote_host_ip6)
5751             self.assertEqual(ip.dst, self.pg3.remote_ip6)
5752             self.assertEqual(tcp.sport, 80)
5753             self.assertEqual(tcp.dport, 12345)
5754             self.assert_packet_checksums_valid(p)
5755         except:
5756             self.logger.error(ppp("Unexpected or invalid packet:", p))
5757             raise
5758
5759     def test_frag_in_order(self):
5760         """ NAT64 translate fragments arriving in order """
5761         self.tcp_port_in = random.randint(1025, 65535)
5762
5763         self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
5764                                                 self.nat_addr_n)
5765         self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
5766         self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
5767
5768         reass = self.vapi.nat_reass_dump()
5769         reass_n_start = len(reass)
5770
5771         # in2out
5772         data = 'a' * 200
5773         pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
5774                                            self.tcp_port_in, 20, data)
5775         self.pg0.add_stream(pkts)
5776         self.pg_enable_capture(self.pg_interfaces)
5777         self.pg_start()
5778         frags = self.pg1.get_capture(len(pkts))
5779         p = self.reass_frags_and_verify(frags,
5780                                         self.nat_addr,
5781                                         self.pg1.remote_ip4)
5782         self.assertEqual(p[TCP].dport, 20)
5783         self.assertNotEqual(p[TCP].sport, self.tcp_port_in)
5784         self.tcp_port_out = p[TCP].sport
5785         self.assertEqual(data, p[Raw].load)
5786
5787         # out2in
5788         data = "A" * 4 + "b" * 16 + "C" * 3
5789         pkts = self.create_stream_frag(self.pg1,
5790                                        self.nat_addr,
5791                                        20,
5792                                        self.tcp_port_out,
5793                                        data)
5794         self.pg1.add_stream(pkts)
5795         self.pg_enable_capture(self.pg_interfaces)
5796         self.pg_start()
5797         frags = self.pg0.get_capture(len(pkts))
5798         src = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
5799         p = self.reass_frags_and_verify_ip6(frags, src, self.pg0.remote_ip6)
5800         self.assertEqual(p[TCP].sport, 20)
5801         self.assertEqual(p[TCP].dport, self.tcp_port_in)
5802         self.assertEqual(data, p[Raw].load)
5803
5804         reass = self.vapi.nat_reass_dump()
5805         reass_n_end = len(reass)
5806
5807         self.assertEqual(reass_n_end - reass_n_start, 2)
5808
5809     def test_reass_hairpinning(self):
5810         """ NAT64 fragments hairpinning """
5811         data = 'a' * 200
5812         server = self.pg0.remote_hosts[1]
5813         server_in_port = random.randint(1025, 65535)
5814         server_out_port = random.randint(1025, 65535)
5815         client_in_port = random.randint(1025, 65535)
5816         ip = IPv6(src=''.join(['64:ff9b::', self.nat_addr]))
5817         nat_addr_ip6 = ip.src
5818
5819         self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
5820                                                 self.nat_addr_n)
5821         self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
5822         self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
5823
5824         # add static BIB entry for server
5825         self.vapi.nat64_add_del_static_bib(server.ip6n,
5826                                            self.nat_addr_n,
5827                                            server_in_port,
5828                                            server_out_port,
5829                                            IP_PROTOS.tcp)
5830
5831         # send packet from host to server
5832         pkts = self.create_stream_frag_ip6(self.pg0,
5833                                            self.nat_addr,
5834                                            client_in_port,
5835                                            server_out_port,
5836                                            data)
5837         self.pg0.add_stream(pkts)
5838         self.pg_enable_capture(self.pg_interfaces)
5839         self.pg_start()
5840         frags = self.pg0.get_capture(len(pkts))
5841         p = self.reass_frags_and_verify_ip6(frags, nat_addr_ip6, server.ip6)
5842         self.assertNotEqual(p[TCP].sport, client_in_port)
5843         self.assertEqual(p[TCP].dport, server_in_port)
5844         self.assertEqual(data, p[Raw].load)
5845
5846     def test_frag_out_of_order(self):
5847         """ NAT64 translate fragments arriving out of order """
5848         self.tcp_port_in = random.randint(1025, 65535)
5849
5850         self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
5851                                                 self.nat_addr_n)
5852         self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
5853         self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
5854
5855         # in2out
5856         data = 'a' * 200
5857         pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
5858                                            self.tcp_port_in, 20, data)
5859         pkts.reverse()
5860         self.pg0.add_stream(pkts)
5861         self.pg_enable_capture(self.pg_interfaces)
5862         self.pg_start()
5863         frags = self.pg1.get_capture(len(pkts))
5864         p = self.reass_frags_and_verify(frags,
5865                                         self.nat_addr,
5866                                         self.pg1.remote_ip4)
5867         self.assertEqual(p[TCP].dport, 20)
5868         self.assertNotEqual(p[TCP].sport, self.tcp_port_in)
5869         self.tcp_port_out = p[TCP].sport
5870         self.assertEqual(data, p[Raw].load)
5871
5872         # out2in
5873         data = "A" * 4 + "B" * 16 + "C" * 3
5874         pkts = self.create_stream_frag(self.pg1,
5875                                        self.nat_addr,
5876                                        20,
5877                                        self.tcp_port_out,
5878                                        data)
5879         pkts.reverse()
5880         self.pg1.add_stream(pkts)
5881         self.pg_enable_capture(self.pg_interfaces)
5882         self.pg_start()
5883         frags = self.pg0.get_capture(len(pkts))
5884         src = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
5885         p = self.reass_frags_and_verify_ip6(frags, src, self.pg0.remote_ip6)
5886         self.assertEqual(p[TCP].sport, 20)
5887         self.assertEqual(p[TCP].dport, self.tcp_port_in)
5888         self.assertEqual(data, p[Raw].load)
5889
5890     def test_interface_addr(self):
5891         """ Acquire NAT64 pool addresses from interface """
5892         self.vapi.nat64_add_interface_addr(self.pg4.sw_if_index)
5893
5894         # no address in NAT64 pool
5895         adresses = self.vapi.nat44_address_dump()
5896         self.assertEqual(0, len(adresses))
5897
5898         # configure interface address and check NAT64 address pool
5899         self.pg4.config_ip4()
5900         addresses = self.vapi.nat64_pool_addr_dump()
5901         self.assertEqual(len(addresses), 1)
5902         self.assertEqual(addresses[0].address, self.pg4.local_ip4n)
5903
5904         # remove interface address and check NAT64 address pool
5905         self.pg4.unconfig_ip4()
5906         addresses = self.vapi.nat64_pool_addr_dump()
5907         self.assertEqual(0, len(adresses))
5908
5909     @unittest.skipUnless(running_extended_tests(), "part of extended tests")
5910     def test_ipfix_max_bibs_sessions(self):
5911         """ IPFIX logging maximum session and BIB entries exceeded """
5912         max_bibs = 1280
5913         max_sessions = 2560
5914         remote_host_ip6 = self.compose_ip6(self.pg1.remote_ip4,
5915                                            '64:ff9b::',
5916                                            96)
5917
5918         self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
5919                                                 self.nat_addr_n)
5920         self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
5921         self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
5922
5923         pkts = []
5924         src = ""
5925         for i in range(0, max_bibs):
5926             src = "fd01:aa::%x" % (i)
5927             p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5928                  IPv6(src=src, dst=remote_host_ip6) /
5929                  TCP(sport=12345, dport=80))
5930             pkts.append(p)
5931             p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5932                  IPv6(src=src, dst=remote_host_ip6) /
5933                  TCP(sport=12345, dport=22))
5934             pkts.append(p)
5935         self.pg0.add_stream(pkts)
5936         self.pg_enable_capture(self.pg_interfaces)
5937         self.pg_start()
5938         self.pg1.get_capture(max_sessions)
5939
5940         self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
5941                                      src_address=self.pg3.local_ip4n,
5942                                      path_mtu=512,
5943                                      template_interval=10)
5944         self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
5945                             src_port=self.ipfix_src_port)
5946
5947         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5948              IPv6(src=src, dst=remote_host_ip6) /
5949              TCP(sport=12345, dport=25))
5950         self.pg0.add_stream(p)
5951         self.pg_enable_capture(self.pg_interfaces)
5952         self.pg_start()
5953         self.pg1.get_capture(0)
5954         self.vapi.cli("ipfix flush")  # FIXME this should be an API call
5955         capture = self.pg3.get_capture(9)
5956         ipfix = IPFIXDecoder()
5957         # first load template
5958         for p in capture:
5959             self.assertTrue(p.haslayer(IPFIX))
5960             self.assertEqual(p[IP].src, self.pg3.local_ip4)
5961             self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
5962             self.assertEqual(p[UDP].sport, self.ipfix_src_port)
5963             self.assertEqual(p[UDP].dport, 4739)
5964             self.assertEqual(p[IPFIX].observationDomainID,
5965                              self.ipfix_domain_id)
5966             if p.haslayer(Template):
5967                 ipfix.add_template(p.getlayer(Template))
5968         # verify events in data set
5969         for p in capture:
5970             if p.haslayer(Data):
5971                 data = ipfix.decode_data_set(p.getlayer(Set))
5972                 self.verify_ipfix_max_sessions(data, max_sessions)
5973
5974         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5975              IPv6(src=self.pg0.remote_ip6, dst=remote_host_ip6) /
5976              TCP(sport=12345, dport=80))
5977         self.pg0.add_stream(p)
5978         self.pg_enable_capture(self.pg_interfaces)
5979         self.pg_start()
5980         self.pg1.get_capture(0)
5981         self.vapi.cli("ipfix flush")  # FIXME this should be an API call
5982         capture = self.pg3.get_capture(1)
5983         # verify events in data set
5984         for p in capture:
5985             self.assertTrue(p.haslayer(IPFIX))
5986             self.assertEqual(p[IP].src, self.pg3.local_ip4)
5987             self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
5988             self.assertEqual(p[UDP].sport, self.ipfix_src_port)
5989             self.assertEqual(p[UDP].dport, 4739)
5990             self.assertEqual(p[IPFIX].observationDomainID,
5991                              self.ipfix_domain_id)
5992             if p.haslayer(Data):
5993                 data = ipfix.decode_data_set(p.getlayer(Set))
5994                 self.verify_ipfix_max_bibs(data, max_bibs)
5995
5996     def test_ipfix_max_frags(self):
5997         """ IPFIX logging maximum fragments pending reassembly exceeded """
5998         self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
5999                                                 self.nat_addr_n)
6000         self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6001         self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6002         self.vapi.nat_set_reass(max_frag=0, is_ip6=1)
6003         self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
6004                                      src_address=self.pg3.local_ip4n,
6005                                      path_mtu=512,
6006                                      template_interval=10)
6007         self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
6008                             src_port=self.ipfix_src_port)
6009
6010         data = 'a' * 200
6011         pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
6012                                            self.tcp_port_in, 20, data)
6013         self.pg0.add_stream(pkts[-1])
6014         self.pg_enable_capture(self.pg_interfaces)
6015         self.pg_start()
6016         self.pg1.get_capture(0)
6017         self.vapi.cli("ipfix flush")  # FIXME this should be an API call
6018         capture = self.pg3.get_capture(9)
6019         ipfix = IPFIXDecoder()
6020         # first load template
6021         for p in capture:
6022             self.assertTrue(p.haslayer(IPFIX))
6023             self.assertEqual(p[IP].src, self.pg3.local_ip4)
6024             self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
6025             self.assertEqual(p[UDP].sport, self.ipfix_src_port)
6026             self.assertEqual(p[UDP].dport, 4739)
6027             self.assertEqual(p[IPFIX].observationDomainID,
6028                              self.ipfix_domain_id)
6029             if p.haslayer(Template):
6030                 ipfix.add_template(p.getlayer(Template))
6031         # verify events in data set
6032         for p in capture:
6033             if p.haslayer(Data):
6034                 data = ipfix.decode_data_set(p.getlayer(Set))
6035                 self.verify_ipfix_max_fragments_ip6(data, 0,
6036                                                     self.pg0.remote_ip6n)
6037
6038     def test_ipfix_bib_ses(self):
6039         """ IPFIX logging NAT64 BIB/session create and delete events """
6040         self.tcp_port_in = random.randint(1025, 65535)
6041         remote_host_ip6 = self.compose_ip6(self.pg1.remote_ip4,
6042                                            '64:ff9b::',
6043                                            96)
6044
6045         self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6046                                                 self.nat_addr_n)
6047         self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6048         self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6049         self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
6050                                      src_address=self.pg3.local_ip4n,
6051                                      path_mtu=512,
6052                                      template_interval=10)
6053         self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
6054                             src_port=self.ipfix_src_port)
6055
6056         # Create
6057         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6058              IPv6(src=self.pg0.remote_ip6, dst=remote_host_ip6) /
6059              TCP(sport=self.tcp_port_in, dport=25))
6060         self.pg0.add_stream(p)
6061         self.pg_enable_capture(self.pg_interfaces)
6062         self.pg_start()
6063         p = self.pg1.get_capture(1)
6064         self.tcp_port_out = p[0][TCP].sport
6065         self.vapi.cli("ipfix flush")  # FIXME this should be an API call
6066         capture = self.pg3.get_capture(10)
6067         ipfix = IPFIXDecoder()
6068         # first load template
6069         for p in capture:
6070             self.assertTrue(p.haslayer(IPFIX))
6071             self.assertEqual(p[IP].src, self.pg3.local_ip4)
6072             self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
6073             self.assertEqual(p[UDP].sport, self.ipfix_src_port)
6074             self.assertEqual(p[UDP].dport, 4739)
6075             self.assertEqual(p[IPFIX].observationDomainID,
6076                              self.ipfix_domain_id)
6077             if p.haslayer(Template):
6078                 ipfix.add_template(p.getlayer(Template))
6079         # verify events in data set
6080         for p in capture:
6081             if p.haslayer(Data):
6082                 data = ipfix.decode_data_set(p.getlayer(Set))
6083                 if ord(data[0][230]) == 10:
6084                     self.verify_ipfix_bib(data, 1, self.pg0.remote_ip6n)
6085                 elif ord(data[0][230]) == 6:
6086                     self.verify_ipfix_nat64_ses(data,
6087                                                 1,
6088                                                 self.pg0.remote_ip6n,
6089                                                 self.pg1.remote_ip4,
6090                                                 25)
6091                 else:
6092                     self.logger.error(ppp("Unexpected or invalid packet: ", p))
6093
6094         # Delete
6095         self.pg_enable_capture(self.pg_interfaces)
6096         self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6097                                                 self.nat_addr_n,
6098                                                 is_add=0)
6099         self.vapi.cli("ipfix flush")  # FIXME this should be an API call
6100         capture = self.pg3.get_capture(2)
6101         # verify events in data set
6102         for p in capture:
6103             self.assertTrue(p.haslayer(IPFIX))
6104             self.assertEqual(p[IP].src, self.pg3.local_ip4)
6105             self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
6106             self.assertEqual(p[UDP].sport, self.ipfix_src_port)
6107             self.assertEqual(p[UDP].dport, 4739)
6108             self.assertEqual(p[IPFIX].observationDomainID,
6109                              self.ipfix_domain_id)
6110             if p.haslayer(Data):
6111                 data = ipfix.decode_data_set(p.getlayer(Set))
6112                 if ord(data[0][230]) == 11:
6113                     self.verify_ipfix_bib(data, 0, self.pg0.remote_ip6n)
6114                 elif ord(data[0][230]) == 7:
6115                     self.verify_ipfix_nat64_ses(data,
6116                                                 0,
6117                                                 self.pg0.remote_ip6n,
6118                                                 self.pg1.remote_ip4,
6119                                                 25)
6120                 else:
6121                     self.logger.error(ppp("Unexpected or invalid packet: ", p))
6122
6123     def nat64_get_ses_num(self):
6124         """
6125         Return number of active NAT64 sessions.
6126         """
6127         st = self.vapi.nat64_st_dump()
6128         return len(st)
6129
6130     def clear_nat64(self):
6131         """
6132         Clear NAT64 configuration.
6133         """
6134         self.vapi.nat_ipfix(enable=0, src_port=self.ipfix_src_port,
6135                             domain_id=self.ipfix_domain_id)
6136         self.ipfix_src_port = 4739
6137         self.ipfix_domain_id = 1
6138
6139         self.vapi.nat64_set_timeouts()
6140
6141         interfaces = self.vapi.nat64_interface_dump()
6142         for intf in interfaces:
6143             if intf.is_inside > 1:
6144                 self.vapi.nat64_add_del_interface(intf.sw_if_index,
6145                                                   0,
6146                                                   is_add=0)
6147             self.vapi.nat64_add_del_interface(intf.sw_if_index,
6148                                               intf.is_inside,
6149                                               is_add=0)
6150
6151         bib = self.vapi.nat64_bib_dump(255)
6152         for bibe in bib:
6153             if bibe.is_static:
6154                 self.vapi.nat64_add_del_static_bib(bibe.i_addr,
6155                                                    bibe.o_addr,
6156                                                    bibe.i_port,
6157                                                    bibe.o_port,
6158                                                    bibe.proto,
6159                                                    bibe.vrf_id,
6160                                                    is_add=0)
6161
6162         adresses = self.vapi.nat64_pool_addr_dump()
6163         for addr in adresses:
6164             self.vapi.nat64_add_del_pool_addr_range(addr.address,
6165                                                     addr.address,
6166                                                     vrf_id=addr.vrf_id,
6167                                                     is_add=0)
6168
6169         prefixes = self.vapi.nat64_prefix_dump()
6170         for prefix in prefixes:
6171             self.vapi.nat64_add_del_prefix(prefix.prefix,
6172                                            prefix.prefix_len,
6173                                            vrf_id=prefix.vrf_id,
6174                                            is_add=0)
6175
6176     def tearDown(self):
6177         super(TestNAT64, self).tearDown()
6178         if not self.vpp_dead:
6179             self.logger.info(self.vapi.cli("show nat64 pool"))
6180             self.logger.info(self.vapi.cli("show nat64 interfaces"))
6181             self.logger.info(self.vapi.cli("show nat64 prefix"))
6182             self.logger.info(self.vapi.cli("show nat64 bib all"))
6183             self.logger.info(self.vapi.cli("show nat64 session table all"))
6184             self.logger.info(self.vapi.cli("show nat virtual-reassembly"))
6185             self.clear_nat64()
6186
6187
6188 class TestDSlite(MethodHolder):
6189     """ DS-Lite Test Cases """
6190
6191     @classmethod
6192     def setUpClass(cls):
6193         super(TestDSlite, cls).setUpClass()
6194
6195         try:
6196             cls.nat_addr = '10.0.0.3'
6197             cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
6198
6199             cls.create_pg_interfaces(range(2))
6200             cls.pg0.admin_up()
6201             cls.pg0.config_ip4()
6202             cls.pg0.resolve_arp()
6203             cls.pg1.admin_up()
6204             cls.pg1.config_ip6()
6205             cls.pg1.generate_remote_hosts(2)
6206             cls.pg1.configure_ipv6_neighbors()
6207
6208         except Exception:
6209             super(TestDSlite, cls).tearDownClass()
6210             raise
6211
6212     def test_dslite(self):
6213         """ Test DS-Lite """
6214         self.vapi.dslite_add_del_pool_addr_range(self.nat_addr_n,
6215                                                  self.nat_addr_n)
6216         aftr_ip4 = '192.0.0.1'
6217         aftr_ip4_n = socket.inet_pton(socket.AF_INET, aftr_ip4)
6218         aftr_ip6 = '2001:db8:85a3::8a2e:370:1'
6219         aftr_ip6_n = socket.inet_pton(socket.AF_INET6, aftr_ip6)
6220         self.vapi.dslite_set_aftr_addr(aftr_ip6_n, aftr_ip4_n)
6221
6222         # UDP
6223         p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
6224              IPv6(dst=aftr_ip6, src=self.pg1.remote_hosts[0].ip6) /
6225              IP(dst=self.pg0.remote_ip4, src='192.168.1.1') /
6226              UDP(sport=20000, dport=10000))
6227         self.pg1.add_stream(p)
6228         self.pg_enable_capture(self.pg_interfaces)
6229         self.pg_start()
6230         capture = self.pg0.get_capture(1)
6231         capture = capture[0]
6232         self.assertFalse(capture.haslayer(IPv6))
6233         self.assertEqual(capture[IP].src, self.nat_addr)
6234         self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
6235         self.assertNotEqual(capture[UDP].sport, 20000)
6236         self.assertEqual(capture[UDP].dport, 10000)
6237         self.assert_packet_checksums_valid(capture)
6238         out_port = capture[UDP].sport
6239
6240         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6241              IP(dst=self.nat_addr, src=self.pg0.remote_ip4) /
6242              UDP(sport=10000, dport=out_port))
6243         self.pg0.add_stream(p)
6244         self.pg_enable_capture(self.pg_interfaces)
6245         self.pg_start()
6246         capture = self.pg1.get_capture(1)
6247         capture = capture[0]
6248         self.assertEqual(capture[IPv6].src, aftr_ip6)
6249         self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[0].ip6)
6250         self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
6251         self.assertEqual(capture[IP].dst, '192.168.1.1')
6252         self.assertEqual(capture[UDP].sport, 10000)
6253         self.assertEqual(capture[UDP].dport, 20000)
6254         self.assert_packet_checksums_valid(capture)
6255
6256         # TCP
6257         p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
6258              IPv6(dst=aftr_ip6, src=self.pg1.remote_hosts[1].ip6) /
6259              IP(dst=self.pg0.remote_ip4, src='192.168.1.1') /
6260              TCP(sport=20001, dport=10001))
6261         self.pg1.add_stream(p)
6262         self.pg_enable_capture(self.pg_interfaces)
6263         self.pg_start()
6264         capture = self.pg0.get_capture(1)
6265         capture = capture[0]
6266         self.assertFalse(capture.haslayer(IPv6))
6267         self.assertEqual(capture[IP].src, self.nat_addr)
6268         self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
6269         self.assertNotEqual(capture[TCP].sport, 20001)
6270         self.assertEqual(capture[TCP].dport, 10001)
6271         self.assert_packet_checksums_valid(capture)
6272         out_port = capture[TCP].sport
6273
6274         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6275              IP(dst=self.nat_addr, src=self.pg0.remote_ip4) /
6276              TCP(sport=10001, dport=out_port))
6277         self.pg0.add_stream(p)
6278         self.pg_enable_capture(self.pg_interfaces)
6279         self.pg_start()
6280         capture = self.pg1.get_capture(1)
6281         capture = capture[0]
6282         self.assertEqual(capture[IPv6].src, aftr_ip6)
6283         self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[1].ip6)
6284         self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
6285         self.assertEqual(capture[IP].dst, '192.168.1.1')
6286         self.assertEqual(capture[TCP].sport, 10001)
6287         self.assertEqual(capture[TCP].dport, 20001)
6288         self.assert_packet_checksums_valid(capture)
6289
6290         # ICMP
6291         p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
6292              IPv6(dst=aftr_ip6, src=self.pg1.remote_hosts[1].ip6) /
6293              IP(dst=self.pg0.remote_ip4, src='192.168.1.1') /
6294              ICMP(id=4000, type='echo-request'))
6295         self.pg1.add_stream(p)
6296         self.pg_enable_capture(self.pg_interfaces)
6297         self.pg_start()
6298         capture = self.pg0.get_capture(1)
6299         capture = capture[0]
6300         self.assertFalse(capture.haslayer(IPv6))
6301         self.assertEqual(capture[IP].src, self.nat_addr)
6302         self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
6303         self.assertNotEqual(capture[ICMP].id, 4000)
6304         self.assert_packet_checksums_valid(capture)
6305         out_id = capture[ICMP].id
6306
6307         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6308              IP(dst=self.nat_addr, src=self.pg0.remote_ip4) /
6309              ICMP(id=out_id, type='echo-reply'))
6310         self.pg0.add_stream(p)
6311         self.pg_enable_capture(self.pg_interfaces)
6312         self.pg_start()
6313         capture = self.pg1.get_capture(1)
6314         capture = capture[0]
6315         self.assertEqual(capture[IPv6].src, aftr_ip6)
6316         self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[1].ip6)
6317         self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
6318         self.assertEqual(capture[IP].dst, '192.168.1.1')
6319         self.assertEqual(capture[ICMP].id, 4000)
6320         self.assert_packet_checksums_valid(capture)
6321
6322         # ping DS-Lite AFTR tunnel endpoint address
6323         p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
6324              IPv6(src=self.pg1.remote_hosts[1].ip6, dst=aftr_ip6) /
6325              ICMPv6EchoRequest())
6326         self.pg1.add_stream(p)
6327         self.pg_enable_capture(self.pg_interfaces)
6328         self.pg_start()
6329         capture = self.pg1.get_capture(1)
6330         self.assertEqual(1, len(capture))
6331         capture = capture[0]
6332         self.assertEqual(capture[IPv6].src, aftr_ip6)
6333         self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[1].ip6)
6334         self.assertTrue(capture.haslayer(ICMPv6EchoReply))
6335
6336     def tearDown(self):
6337         super(TestDSlite, self).tearDown()
6338         if not self.vpp_dead:
6339             self.logger.info(self.vapi.cli("show dslite pool"))
6340             self.logger.info(
6341                 self.vapi.cli("show dslite aftr-tunnel-endpoint-address"))
6342             self.logger.info(self.vapi.cli("show dslite sessions"))
6343
6344
6345 class TestDSliteCE(MethodHolder):
6346     """ DS-Lite CE Test Cases """
6347
6348     @classmethod
6349     def setUpConstants(cls):
6350         super(TestDSliteCE, cls).setUpConstants()
6351         cls.vpp_cmdline.extend(["nat", "{", "dslite ce", "}"])
6352
6353     @classmethod
6354     def setUpClass(cls):
6355         super(TestDSliteCE, cls).setUpClass()
6356
6357         try:
6358             cls.create_pg_interfaces(range(2))
6359             cls.pg0.admin_up()
6360             cls.pg0.config_ip4()
6361             cls.pg0.resolve_arp()
6362             cls.pg1.admin_up()
6363             cls.pg1.config_ip6()
6364             cls.pg1.generate_remote_hosts(1)
6365             cls.pg1.configure_ipv6_neighbors()
6366
6367         except Exception:
6368             super(TestDSliteCE, cls).tearDownClass()
6369             raise
6370
6371     def test_dslite_ce(self):
6372         """ Test DS-Lite CE """
6373
6374         b4_ip4 = '192.0.0.2'
6375         b4_ip4_n = socket.inet_pton(socket.AF_INET, b4_ip4)
6376         b4_ip6 = '2001:db8:62aa::375e:f4c1:1'
6377         b4_ip6_n = socket.inet_pton(socket.AF_INET6, b4_ip6)
6378         self.vapi.dslite_set_b4_addr(b4_ip6_n, b4_ip4_n)
6379
6380         aftr_ip4 = '192.0.0.1'
6381         aftr_ip4_n = socket.inet_pton(socket.AF_INET, aftr_ip4)
6382         aftr_ip6 = '2001:db8:85a3::8a2e:370:1'
6383         aftr_ip6_n = socket.inet_pton(socket.AF_INET6, aftr_ip6)
6384         self.vapi.dslite_set_aftr_addr(aftr_ip6_n, aftr_ip4_n)
6385
6386         self.vapi.ip_add_del_route(dst_address=aftr_ip6_n,
6387                                    dst_address_length=128,
6388                                    next_hop_address=self.pg1.remote_ip6n,
6389                                    next_hop_sw_if_index=self.pg1.sw_if_index,
6390                                    is_ipv6=1)
6391
6392         # UDP encapsulation
6393         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6394              IP(dst=self.pg1.remote_ip4, src=self.pg0.remote_ip4) /
6395              UDP(sport=10000, dport=20000))
6396         self.pg0.add_stream(p)
6397         self.pg_enable_capture(self.pg_interfaces)
6398         self.pg_start()
6399         capture = self.pg1.get_capture(1)
6400         capture = capture[0]
6401         self.assertEqual(capture[IPv6].src, b4_ip6)
6402         self.assertEqual(capture[IPv6].dst, aftr_ip6)
6403         self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
6404         self.assertEqual(capture[IP].dst, self.pg1.remote_ip4)
6405         self.assertEqual(capture[UDP].sport, 10000)
6406         self.assertEqual(capture[UDP].dport, 20000)
6407         self.assert_packet_checksums_valid(capture)
6408
6409         # UDP decapsulation
6410         p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
6411              IPv6(dst=b4_ip6, src=aftr_ip6) /
6412              IP(dst=self.pg0.remote_ip4, src=self.pg1.remote_ip4) /
6413              UDP(sport=20000, dport=10000))
6414         self.pg1.add_stream(p)
6415         self.pg_enable_capture(self.pg_interfaces)
6416         self.pg_start()
6417         capture = self.pg0.get_capture(1)
6418         capture = capture[0]
6419         self.assertFalse(capture.haslayer(IPv6))
6420         self.assertEqual(capture[IP].src, self.pg1.remote_ip4)
6421         self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
6422         self.assertEqual(capture[UDP].sport, 20000)
6423         self.assertEqual(capture[UDP].dport, 10000)
6424         self.assert_packet_checksums_valid(capture)
6425
6426         # ping DS-Lite B4 tunnel endpoint address
6427         p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
6428              IPv6(src=self.pg1.remote_hosts[0].ip6, dst=b4_ip6) /
6429              ICMPv6EchoRequest())
6430         self.pg1.add_stream(p)
6431         self.pg_enable_capture(self.pg_interfaces)
6432         self.pg_start()
6433         capture = self.pg1.get_capture(1)
6434         self.assertEqual(1, len(capture))
6435         capture = capture[0]
6436         self.assertEqual(capture[IPv6].src, b4_ip6)
6437         self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[0].ip6)
6438         self.assertTrue(capture.haslayer(ICMPv6EchoReply))
6439
6440     def tearDown(self):
6441         super(TestDSliteCE, self).tearDown()
6442         if not self.vpp_dead:
6443             self.logger.info(
6444                 self.vapi.cli("show dslite aftr-tunnel-endpoint-address"))
6445             self.logger.info(
6446                 self.vapi.cli("show dslite b4-tunnel-endpoint-address"))
6447
6448
6449 class TestNAT66(MethodHolder):
6450     """ NAT66 Test Cases """
6451
6452     @classmethod
6453     def setUpClass(cls):
6454         super(TestNAT66, cls).setUpClass()
6455
6456         try:
6457             cls.nat_addr = 'fd01:ff::2'
6458             cls.nat_addr_n = socket.inet_pton(socket.AF_INET6, cls.nat_addr)
6459
6460             cls.create_pg_interfaces(range(2))
6461             cls.interfaces = list(cls.pg_interfaces)
6462
6463             for i in cls.interfaces:
6464                 i.admin_up()
6465                 i.config_ip6()
6466                 i.configure_ipv6_neighbors()
6467
6468         except Exception:
6469             super(TestNAT66, cls).tearDownClass()
6470             raise
6471
6472     def test_static(self):
6473         """ 1:1 NAT66 test """
6474         self.vapi.nat66_add_del_interface(self.pg0.sw_if_index)
6475         self.vapi.nat66_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6476         self.vapi.nat66_add_del_static_mapping(self.pg0.remote_ip6n,
6477                                                self.nat_addr_n)
6478
6479         # in2out
6480         pkts = []
6481         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6482              IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
6483              TCP())
6484         pkts.append(p)
6485         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6486              IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
6487              UDP())
6488         pkts.append(p)
6489         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6490              IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
6491              ICMPv6EchoRequest())
6492         pkts.append(p)
6493         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6494              IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
6495              GRE() / IP() / TCP())
6496         pkts.append(p)
6497         self.pg0.add_stream(pkts)
6498         self.pg_enable_capture(self.pg_interfaces)
6499         self.pg_start()
6500         capture = self.pg1.get_capture(len(pkts))
6501         for packet in capture:
6502             try:
6503                 self.assertEqual(packet[IPv6].src, self.nat_addr)
6504                 self.assertEqual(packet[IPv6].dst, self.pg1.remote_ip6)
6505                 self.assert_packet_checksums_valid(packet)
6506             except:
6507                 self.logger.error(ppp("Unexpected or invalid packet:", packet))
6508                 raise
6509
6510         # out2in
6511         pkts = []
6512         p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
6513              IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
6514              TCP())
6515         pkts.append(p)
6516         p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
6517              IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
6518              UDP())
6519         pkts.append(p)
6520         p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
6521              IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
6522              ICMPv6EchoReply())
6523         pkts.append(p)
6524         p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
6525              IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
6526              GRE() / IP() / TCP())
6527         pkts.append(p)
6528         self.pg1.add_stream(pkts)
6529         self.pg_enable_capture(self.pg_interfaces)
6530         self.pg_start()
6531         capture = self.pg0.get_capture(len(pkts))
6532         for packet in capture:
6533             try:
6534                 self.assertEqual(packet[IPv6].src, self.pg1.remote_ip6)
6535                 self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
6536                 self.assert_packet_checksums_valid(packet)
6537             except:
6538                 self.logger.error(ppp("Unexpected or invalid packet:", packet))
6539                 raise
6540
6541         sm = self.vapi.nat66_static_mapping_dump()
6542         self.assertEqual(len(sm), 1)
6543         self.assertEqual(sm[0].total_pkts, 8)
6544
6545     def test_check_no_translate(self):
6546         """ NAT66 translate only when egress interface is outside interface """
6547         self.vapi.nat66_add_del_interface(self.pg0.sw_if_index)
6548         self.vapi.nat66_add_del_interface(self.pg1.sw_if_index)
6549         self.vapi.nat66_add_del_static_mapping(self.pg0.remote_ip6n,
6550                                                self.nat_addr_n)
6551
6552         # in2out
6553         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6554              IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
6555              UDP())
6556         self.pg0.add_stream([p])
6557         self.pg_enable_capture(self.pg_interfaces)
6558         self.pg_start()
6559         capture = self.pg1.get_capture(1)
6560         packet = capture[0]
6561         try:
6562             self.assertEqual(packet[IPv6].src, self.pg0.remote_ip6)
6563             self.assertEqual(packet[IPv6].dst, self.pg1.remote_ip6)
6564         except:
6565             self.logger.error(ppp("Unexpected or invalid packet:", packet))
6566             raise
6567
6568     def clear_nat66(self):
6569         """
6570         Clear NAT66 configuration.
6571         """
6572         interfaces = self.vapi.nat66_interface_dump()
6573         for intf in interfaces:
6574             self.vapi.nat66_add_del_interface(intf.sw_if_index,
6575                                               intf.is_inside,
6576                                               is_add=0)
6577
6578         static_mappings = self.vapi.nat66_static_mapping_dump()
6579         for sm in static_mappings:
6580             self.vapi.nat66_add_del_static_mapping(sm.local_ip_address,
6581                                                    sm.external_ip_address,
6582                                                    sm.vrf_id,
6583                                                    is_add=0)
6584
6585     def tearDown(self):
6586         super(TestNAT66, self).tearDown()
6587         if not self.vpp_dead:
6588             self.logger.info(self.vapi.cli("show nat66 interfaces"))
6589             self.logger.info(self.vapi.cli("show nat66 static mappings"))
6590             self.clear_nat66()
6591
6592
6593 if __name__ == '__main__':
6594     unittest.main(testRunner=VppTestRunner)