blob: ad2b9649b7de53c5c8d063d6584f935644575154 [file] [log] [blame]
Matus Fabiande886752016-12-07 03:38:19 -08001#!/usr/bin/env python
2
3import socket
4import unittest
Matus Fabianeea28d72017-01-13 04:15:54 -08005import struct
Matus Fabianefcd1e92017-08-15 06:59:19 -07006import StringIO
7import random
Matus Fabiande886752016-12-07 03:38:19 -08008
Martin Gálik977c1cb2017-03-30 23:21:51 -07009from framework import VppTestCase, VppTestRunner, running_extended_tests
Matus Fabiande886752016-12-07 03:38:19 -080010from scapy.layers.inet import IP, TCP, UDP, ICMP
Juraj Slobodab33f4132017-02-08 23:54:21 -080011from scapy.layers.inet import IPerror, TCPerror, UDPerror, ICMPerror
Matus Fabian06596c52017-06-06 04:53:28 -070012from scapy.layers.inet6 import IPv6, ICMPv6EchoRequest, ICMPv6EchoReply
Matus Fabianefcd1e92017-08-15 06:59:19 -070013from scapy.layers.inet6 import ICMPv6DestUnreach, IPerror6, IPv6ExtHdrFragment
Matus Fabian328dbc82017-06-19 04:28:04 -070014from scapy.layers.l2 import Ether, ARP, GRE
Matus Fabianeea28d72017-01-13 04:15:54 -080015from scapy.data import IP_PROTOS
Matus Fabianefcd1e92017-08-15 06:59:19 -070016from scapy.packet import bind_layers, Raw
17from scapy.all import fragment6
Klement Sekera9225dee2016-12-12 08:36:58 +010018from util import ppp
Matus Fabianeea28d72017-01-13 04:15:54 -080019from ipfix import IPFIX, Set, Template, Data, IPFIXDecoder
Martin Gálik977c1cb2017-03-30 23:21:51 -070020from time import sleep
Matus Fabian704018c2017-09-04 02:17:18 -070021from util import ip4_range
Ole Troan895b6e82017-10-20 13:28:20 +020022from util import mactobinary
Matus Fabiande886752016-12-07 03:38:19 -080023
24
Martin Gálikd7f75cd2017-03-27 06:02:47 -070025class MethodHolder(VppTestCase):
Matus Fabian2ba92e32017-08-21 07:05:03 -070026 """ NAT create capture and verify method holder """
Matus Fabiande886752016-12-07 03:38:19 -080027
Juraj Slobodacba69362017-12-19 02:09:32 +010028 def create_stream_in(self, in_if, out_if, dst_ip=None, ttl=64):
Matus Fabiande886752016-12-07 03:38:19 -080029 """
30 Create packet stream for inside network
31
32 :param in_if: Inside interface
33 :param out_if: Outside interface
Juraj Slobodacba69362017-12-19 02:09:32 +010034 :param dst_ip: Destination address
Juraj Slobodab33f4132017-02-08 23:54:21 -080035 :param ttl: TTL of generated packets
Matus Fabiande886752016-12-07 03:38:19 -080036 """
Juraj Slobodacba69362017-12-19 02:09:32 +010037 if dst_ip is None:
38 dst_ip = out_if.remote_ip4
39
Matus Fabiande886752016-12-07 03:38:19 -080040 pkts = []
41 # TCP
42 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
Juraj Slobodacba69362017-12-19 02:09:32 +010043 IP(src=in_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Matus Fabian06596c52017-06-06 04:53:28 -070044 TCP(sport=self.tcp_port_in, dport=20))
Matus Fabiande886752016-12-07 03:38:19 -080045 pkts.append(p)
46
47 # UDP
48 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
Juraj Slobodacba69362017-12-19 02:09:32 +010049 IP(src=in_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Matus Fabian06596c52017-06-06 04:53:28 -070050 UDP(sport=self.udp_port_in, dport=20))
Matus Fabiande886752016-12-07 03:38:19 -080051 pkts.append(p)
52
53 # ICMP
54 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
Juraj Slobodacba69362017-12-19 02:09:32 +010055 IP(src=in_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Matus Fabiande886752016-12-07 03:38:19 -080056 ICMP(id=self.icmp_id_in, type='echo-request'))
57 pkts.append(p)
58
59 return pkts
60
Matus Fabian428dc912017-06-21 06:15:18 -070061 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
Juraj Slobodacba69362017-12-19 02:09:32 +0100104 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
Matus Fabian428dc912017-06-21 06:15:18 -0700146 def create_stream_in_ip6(self, in_if, out_if, hlim=64, pref=None, plen=0):
Matus Fabian06596c52017-06-06 04:53:28 -0700147 """
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
Matus Fabian428dc912017-06-21 06:15:18 -0700153 :param pref: NAT64 prefix
154 :param plen: NAT64 prefix length
Matus Fabian06596c52017-06-06 04:53:28 -0700155 """
156 pkts = []
Matus Fabian428dc912017-06-21 06:15:18 -0700157 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
Matus Fabian06596c52017-06-06 04:53:28 -0700162 # 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
Juraj Sloboda7b929792017-11-23 13:20:48 +0100182 def create_stream_out(self, out_if, dst_ip=None, ttl=64,
183 use_inside_ports=False):
Matus Fabiande886752016-12-07 03:38:19 -0800184 """
185 Create packet stream for outside network
186
187 :param out_if: Outside interface
Matus Fabian2ba92e32017-08-21 07:05:03 -0700188 :param dst_ip: Destination IP address (Default use global NAT address)
Juraj Slobodab33f4132017-02-08 23:54:21 -0800189 :param ttl: TTL of generated packets
Juraj Sloboda7b929792017-11-23 13:20:48 +0100190 :param use_inside_ports: Use inside NAT ports as destination ports
191 instead of outside ports
Matus Fabiande886752016-12-07 03:38:19 -0800192 """
193 if dst_ip is None:
Matus Fabian2ba92e32017-08-21 07:05:03 -0700194 dst_ip = self.nat_addr
Juraj Sloboda7b929792017-11-23 13:20:48 +0100195 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
Matus Fabiande886752016-12-07 03:38:19 -0800203 pkts = []
204 # TCP
205 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
Juraj Slobodab33f4132017-02-08 23:54:21 -0800206 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Juraj Sloboda7b929792017-11-23 13:20:48 +0100207 TCP(dport=tcp_port, sport=20))
Matus Fabiande886752016-12-07 03:38:19 -0800208 pkts.append(p)
209
210 # UDP
211 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
Juraj Slobodab33f4132017-02-08 23:54:21 -0800212 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Juraj Sloboda7b929792017-11-23 13:20:48 +0100213 UDP(dport=udp_port, sport=20))
Matus Fabiande886752016-12-07 03:38:19 -0800214 pkts.append(p)
215
216 # ICMP
217 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
Juraj Slobodab33f4132017-02-08 23:54:21 -0800218 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Juraj Sloboda7b929792017-11-23 13:20:48 +0100219 ICMP(id=icmp_id, type='echo-reply'))
Matus Fabiande886752016-12-07 03:38:19 -0800220 pkts.append(p)
221
222 return pkts
223
Juraj Slobodacba69362017-12-19 02:09:32 +0100224 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
Matus Fabiande886752016-12-07 03:38:19 -0800253 def verify_capture_out(self, capture, nat_ip=None, same_port=False,
Juraj Slobodacba69362017-12-19 02:09:32 +0100254 packet_num=3, dst_ip=None, is_ip6=False):
Matus Fabiande886752016-12-07 03:38:19 -0800255 """
256 Verify captured packets on outside network
257
258 :param capture: Captured packets
Matus Fabian2ba92e32017-08-21 07:05:03 -0700259 :param nat_ip: Translated IP address (Default use global NAT address)
Matus Fabiande886752016-12-07 03:38:19 -0800260 :param same_port: Sorce port number is not translated (Default False)
261 :param packet_num: Expected number of packets (Default 3)
Matus Fabian06596c52017-06-06 04:53:28 -0700262 :param dst_ip: Destination IP address (Default do not verify)
Juraj Slobodacba69362017-12-19 02:09:32 +0100263 :param is_ip6: If L3 protocol is IPv6 (Default False)
Matus Fabiande886752016-12-07 03:38:19 -0800264 """
Juraj Slobodacba69362017-12-19 02:09:32 +0100265 if is_ip6:
266 IP46 = IPv6
267 ICMP46 = ICMPv6EchoRequest
268 else:
269 IP46 = IP
270 ICMP46 = ICMP
Matus Fabiande886752016-12-07 03:38:19 -0800271 if nat_ip is None:
Matus Fabian2ba92e32017-08-21 07:05:03 -0700272 nat_ip = self.nat_addr
Matus Fabiande886752016-12-07 03:38:19 -0800273 self.assertEqual(packet_num, len(capture))
274 for packet in capture:
275 try:
Juraj Slobodacba69362017-12-19 02:09:32 +0100276 if not is_ip6:
Klement Sekerad81ae412018-05-16 10:52:54 +0200277 self.assert_packet_checksums_valid(packet)
Juraj Slobodacba69362017-12-19 02:09:32 +0100278 self.assertEqual(packet[IP46].src, nat_ip)
Matus Fabian06596c52017-06-06 04:53:28 -0700279 if dst_ip is not None:
Juraj Slobodacba69362017-12-19 02:09:32 +0100280 self.assertEqual(packet[IP46].dst, dst_ip)
Matus Fabiande886752016-12-07 03:38:19 -0800281 if packet.haslayer(TCP):
282 if same_port:
283 self.assertEqual(packet[TCP].sport, self.tcp_port_in)
284 else:
Klement Sekerada505f62017-01-04 12:58:53 +0100285 self.assertNotEqual(
286 packet[TCP].sport, self.tcp_port_in)
Matus Fabiande886752016-12-07 03:38:19 -0800287 self.tcp_port_out = packet[TCP].sport
Klement Sekerad81ae412018-05-16 10:52:54 +0200288 self.assert_packet_checksums_valid(packet)
Matus Fabiande886752016-12-07 03:38:19 -0800289 elif packet.haslayer(UDP):
290 if same_port:
291 self.assertEqual(packet[UDP].sport, self.udp_port_in)
292 else:
Klement Sekerada505f62017-01-04 12:58:53 +0100293 self.assertNotEqual(
294 packet[UDP].sport, self.udp_port_in)
Matus Fabiande886752016-12-07 03:38:19 -0800295 self.udp_port_out = packet[UDP].sport
296 else:
297 if same_port:
Juraj Slobodacba69362017-12-19 02:09:32 +0100298 self.assertEqual(packet[ICMP46].id, self.icmp_id_in)
Matus Fabiande886752016-12-07 03:38:19 -0800299 else:
Juraj Slobodacba69362017-12-19 02:09:32 +0100300 self.assertNotEqual(packet[ICMP46].id, self.icmp_id_in)
301 self.icmp_id_out = packet[ICMP46].id
Klement Sekerad81ae412018-05-16 10:52:54 +0200302 self.assert_packet_checksums_valid(packet)
Matus Fabiande886752016-12-07 03:38:19 -0800303 except:
Klement Sekera9225dee2016-12-12 08:36:58 +0100304 self.logger.error(ppp("Unexpected or invalid packet "
305 "(outside network):", packet))
Matus Fabiande886752016-12-07 03:38:19 -0800306 raise
307
Juraj Slobodacba69362017-12-19 02:09:32 +0100308 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
Matus Fabiande886752016-12-07 03:38:19 -0800322 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:
Klement Sekerad81ae412018-05-16 10:52:54 +0200333 self.assert_packet_checksums_valid(packet)
Matus Fabiande886752016-12-07 03:38:19 -0800334 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:
Klement Sekera9225dee2016-12-12 08:36:58 +0100342 self.logger.error(ppp("Unexpected or invalid packet "
343 "(inside network):", packet))
Matus Fabiande886752016-12-07 03:38:19 -0800344 raise
345
Matus Fabian06596c52017-06-06 04:53:28 -0700346 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)
Klement Sekerad81ae412018-05-16 10:52:54 +0200360 self.assert_packet_checksums_valid(packet)
Matus Fabian06596c52017-06-06 04:53:28 -0700361 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
Matus Fabian675a69c2017-01-18 01:46:01 -0800373 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
Juraj Slobodab33f4132017-02-08 23:54:21 -0800396 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
Matus Fabian2ba92e32017-08-21 07:05:03 -0700403 (Default use global NAT address)
Juraj Slobodab33f4132017-02-08 23:54:21 -0800404 :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:
Matus Fabian2ba92e32017-08-21 07:05:03 -0700409 src_ip = self.nat_addr
Juraj Slobodab33f4132017-02-08 23:54:21 -0800410 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
Matus Fabianefcd1e92017-08-15 06:59:19 -0700465 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)
Klement Sekerad81ae412018-05-16 10:52:54 +0200542 self.assert_ip_checksum_valid(p)
Matus Fabianefcd1e92017-08-15 06:59:19 -0700543 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()))
Klement Sekerad81ae412018-05-16 10:52:54 +0200550 self.assert_tcp_checksum_valid(p)
Matus Fabianefcd1e92017-08-15 06:59:19 -0700551 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()))
Matus Fabianefcd1e92017-08-15 06:59:19 -0700575 elif ip.nh == IP_PROTOS.udp:
576 p = (ip / UDP(buffer.getvalue()))
Klement Sekerad81ae412018-05-16 10:52:54 +0200577 self.assert_packet_checksums_valid(p)
Matus Fabianefcd1e92017-08-15 06:59:19 -0700578 return p
579
Matus Fabianebdf1902018-05-04 03:57:42 -0700580 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
Matus Fabianeea28d72017-01-13 04:15:54 -0800624 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
Matus Fabian2ba92e32017-08-21 07:05:03 -0700643 self.assertEqual(socket.inet_pton(socket.AF_INET, self.nat_addr),
Matus Fabianeea28d72017-01-13 04:15:54 -0800644 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
Matus Fabiana431ad12018-01-04 04:03:14 -0800680 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
Martin Gálikd7f75cd2017-03-27 06:02:47 -0700822
Matus Fabian2ba92e32017-08-21 07:05:03 -0700823class TestNAT44(MethodHolder):
824 """ NAT44 Test Cases """
Martin Gálikd7f75cd2017-03-27 06:02:47 -0700825
826 @classmethod
827 def setUpClass(cls):
Matus Fabian2ba92e32017-08-21 07:05:03 -0700828 super(TestNAT44, cls).setUpClass()
Matus Fabian229c1aa2018-05-28 04:09:52 -0700829 cls.vapi.cli("set log class nat level debug")
Martin Gálikd7f75cd2017-03-27 06:02:47 -0700830
831 try:
832 cls.tcp_port_in = 6303
833 cls.tcp_port_out = 6303
834 cls.udp_port_in = 6304
835 cls.udp_port_out = 6304
836 cls.icmp_id_in = 6305
837 cls.icmp_id_out = 6305
Matus Fabian2ba92e32017-08-21 07:05:03 -0700838 cls.nat_addr = '10.0.0.3'
Juraj Sloboda7b929792017-11-23 13:20:48 +0100839 cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
Matus Fabian6631e9c2017-05-24 01:52:20 -0700840 cls.ipfix_src_port = 4739
841 cls.ipfix_domain_id = 1
Matus Fabianebdf1902018-05-04 03:57:42 -0700842 cls.tcp_external_port = 80
Martin Gálikd7f75cd2017-03-27 06:02:47 -0700843
Matus Fabian36ea2d62017-10-24 04:13:49 -0700844 cls.create_pg_interfaces(range(10))
Martin Gálikd7f75cd2017-03-27 06:02:47 -0700845 cls.interfaces = list(cls.pg_interfaces[0:4])
846
847 for i in cls.interfaces:
848 i.admin_up()
849 i.config_ip4()
850 i.resolve_arp()
851
Matus Fabian6fa74c62017-06-05 05:55:48 -0700852 cls.pg0.generate_remote_hosts(3)
Martin Gálikd7f75cd2017-03-27 06:02:47 -0700853 cls.pg0.configure_ipv4_neighbors()
854
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +0200855 cls.pg1.generate_remote_hosts(1)
856 cls.pg1.configure_ipv4_neighbors()
857
Martin Gálikd7f75cd2017-03-27 06:02:47 -0700858 cls.overlapping_interfaces = list(list(cls.pg_interfaces[4:7]))
Neale Ranns15002542017-09-10 04:39:11 -0700859 cls.vapi.ip_table_add_del(10, is_add=1)
860 cls.vapi.ip_table_add_del(20, is_add=1)
Martin Gálikd7f75cd2017-03-27 06:02:47 -0700861
862 cls.pg4._local_ip4 = "172.16.255.1"
863 cls.pg4._local_ip4n = socket.inet_pton(socket.AF_INET, i.local_ip4)
864 cls.pg4._remote_hosts[0]._ip4 = "172.16.255.2"
865 cls.pg4.set_table_ip4(10)
Matus Fabian69126282017-08-14 23:39:58 -0700866 cls.pg5._local_ip4 = "172.17.255.3"
Martin Gálikd7f75cd2017-03-27 06:02:47 -0700867 cls.pg5._local_ip4n = socket.inet_pton(socket.AF_INET, i.local_ip4)
Matus Fabian69126282017-08-14 23:39:58 -0700868 cls.pg5._remote_hosts[0]._ip4 = "172.17.255.4"
Martin Gálikd7f75cd2017-03-27 06:02:47 -0700869 cls.pg5.set_table_ip4(10)
870 cls.pg6._local_ip4 = "172.16.255.1"
871 cls.pg6._local_ip4n = socket.inet_pton(socket.AF_INET, i.local_ip4)
872 cls.pg6._remote_hosts[0]._ip4 = "172.16.255.2"
873 cls.pg6.set_table_ip4(20)
874 for i in cls.overlapping_interfaces:
875 i.config_ip4()
876 i.admin_up()
877 i.resolve_arp()
878
879 cls.pg7.admin_up()
Martin Gálik406eb1d2017-05-04 04:35:04 -0700880 cls.pg8.admin_up()
Martin Gálikd7f75cd2017-03-27 06:02:47 -0700881
Matus Fabian36ea2d62017-10-24 04:13:49 -0700882 cls.pg9.generate_remote_hosts(2)
883 cls.pg9.config_ip4()
884 ip_addr_n = socket.inet_pton(socket.AF_INET, "10.0.0.1")
885 cls.vapi.sw_interface_add_del_address(cls.pg9.sw_if_index,
886 ip_addr_n,
887 24)
888 cls.pg9.admin_up()
889 cls.pg9.resolve_arp()
890 cls.pg9._remote_hosts[1]._ip4 = cls.pg9._remote_hosts[0]._ip4
891 cls.pg4._remote_ip4 = cls.pg9._remote_hosts[0]._ip4 = "10.0.0.2"
892 cls.pg9.resolve_arp()
893
Martin Gálikd7f75cd2017-03-27 06:02:47 -0700894 except Exception:
Matus Fabian2ba92e32017-08-21 07:05:03 -0700895 super(TestNAT44, cls).tearDownClass()
Martin Gálikd7f75cd2017-03-27 06:02:47 -0700896 raise
897
Matus Fabian2ba92e32017-08-21 07:05:03 -0700898 def clear_nat44(self):
Matus Fabiande886752016-12-07 03:38:19 -0800899 """
Matus Fabian2ba92e32017-08-21 07:05:03 -0700900 Clear NAT44 configuration.
Matus Fabiande886752016-12-07 03:38:19 -0800901 """
Martin Gálik406eb1d2017-05-04 04:35:04 -0700902 # I found no elegant way to do this
903 self.vapi.ip_add_del_route(dst_address=self.pg7.remote_ip4n,
904 dst_address_length=32,
905 next_hop_address=self.pg7.remote_ip4n,
906 next_hop_sw_if_index=self.pg7.sw_if_index,
907 is_add=0)
908 self.vapi.ip_add_del_route(dst_address=self.pg8.remote_ip4n,
909 dst_address_length=32,
910 next_hop_address=self.pg8.remote_ip4n,
911 next_hop_sw_if_index=self.pg8.sw_if_index,
912 is_add=0)
913
914 for intf in [self.pg7, self.pg8]:
915 neighbors = self.vapi.ip_neighbor_dump(intf.sw_if_index)
916 for n in neighbors:
917 self.vapi.ip_neighbor_add_del(intf.sw_if_index,
918 n.mac_address,
919 n.ip_address,
920 is_add=0)
921
Matus Fabian36532bd2017-01-23 23:42:28 -0800922 if self.pg7.has_ip4_config:
923 self.pg7.unconfig_ip4()
924
Matus Fabian240b5ef2018-01-11 04:09:17 -0800925 self.vapi.nat44_forwarding_enable_disable(0)
926
Matus Fabian2ba92e32017-08-21 07:05:03 -0700927 interfaces = self.vapi.nat44_interface_addr_dump()
Matus Fabian8bf68e82017-01-12 04:24:35 -0800928 for intf in interfaces:
Matus Fabianb932d262017-12-18 05:38:24 -0800929 self.vapi.nat44_add_interface_addr(intf.sw_if_index,
930 twice_nat=intf.twice_nat,
931 is_add=0)
Matus Fabian8bf68e82017-01-12 04:24:35 -0800932
Matus Fabian2ba92e32017-08-21 07:05:03 -0700933 self.vapi.nat_ipfix(enable=0, src_port=self.ipfix_src_port,
934 domain_id=self.ipfix_domain_id)
Matus Fabian6631e9c2017-05-24 01:52:20 -0700935 self.ipfix_src_port = 4739
936 self.ipfix_domain_id = 1
Matus Fabianeea28d72017-01-13 04:15:54 -0800937
Matus Fabian2ba92e32017-08-21 07:05:03 -0700938 interfaces = self.vapi.nat44_interface_dump()
Matus Fabiande886752016-12-07 03:38:19 -0800939 for intf in interfaces:
Matus Fabian36ea2d62017-10-24 04:13:49 -0700940 if intf.is_inside > 1:
941 self.vapi.nat44_interface_add_del_feature(intf.sw_if_index,
942 0,
943 is_add=0)
Matus Fabian2ba92e32017-08-21 07:05:03 -0700944 self.vapi.nat44_interface_add_del_feature(intf.sw_if_index,
945 intf.is_inside,
946 is_add=0)
Matus Fabiande886752016-12-07 03:38:19 -0800947
Matus Fabian2ba92e32017-08-21 07:05:03 -0700948 interfaces = self.vapi.nat44_interface_output_feature_dump()
Matus Fabian93d84c92017-07-19 08:06:01 -0700949 for intf in interfaces:
Matus Fabian2ba92e32017-08-21 07:05:03 -0700950 self.vapi.nat44_interface_add_del_output_feature(intf.sw_if_index,
951 intf.is_inside,
952 is_add=0)
Matus Fabian93d84c92017-07-19 08:06:01 -0700953
Matus Fabian2ba92e32017-08-21 07:05:03 -0700954 static_mappings = self.vapi.nat44_static_mapping_dump()
Matus Fabiande886752016-12-07 03:38:19 -0800955 for sm in static_mappings:
Matus Fabian2ba92e32017-08-21 07:05:03 -0700956 self.vapi.nat44_add_del_static_mapping(
957 sm.local_ip_address,
958 sm.external_ip_address,
959 local_port=sm.local_port,
960 external_port=sm.external_port,
961 addr_only=sm.addr_only,
962 vrf_id=sm.vrf_id,
963 protocol=sm.protocol,
Matus Fabianb932d262017-12-18 05:38:24 -0800964 twice_nat=sm.twice_nat,
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +0200965 self_twice_nat=sm.self_twice_nat,
Matus Fabiane82488f2018-01-18 03:38:45 -0800966 out2in_only=sm.out2in_only,
Matus Fabian5f224992018-01-25 21:59:16 -0800967 tag=sm.tag,
Matus Fabianea2600a2018-03-28 04:06:26 -0700968 external_sw_if_index=sm.external_sw_if_index,
Matus Fabian2ba92e32017-08-21 07:05:03 -0700969 is_add=0)
Matus Fabiande886752016-12-07 03:38:19 -0800970
Matus Fabian704018c2017-09-04 02:17:18 -0700971 lb_static_mappings = self.vapi.nat44_lb_static_mapping_dump()
972 for lb_sm in lb_static_mappings:
973 self.vapi.nat44_add_del_lb_static_mapping(
974 lb_sm.external_addr,
975 lb_sm.external_port,
976 lb_sm.protocol,
Matus Fabianb932d262017-12-18 05:38:24 -0800977 vrf_id=lb_sm.vrf_id,
978 twice_nat=lb_sm.twice_nat,
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +0200979 self_twice_nat=lb_sm.self_twice_nat,
Matus Fabian240b5ef2018-01-11 04:09:17 -0800980 out2in_only=lb_sm.out2in_only,
Matus Fabian5f224992018-01-25 21:59:16 -0800981 tag=lb_sm.tag,
Ole Troan895b6e82017-10-20 13:28:20 +0200982 is_add=0,
983 local_num=0,
984 locals=[])
Matus Fabian704018c2017-09-04 02:17:18 -0700985
Matus Fabianab7a8052017-11-28 04:29:41 -0800986 identity_mappings = self.vapi.nat44_identity_mapping_dump()
987 for id_m in identity_mappings:
988 self.vapi.nat44_add_del_identity_mapping(
989 addr_only=id_m.addr_only,
990 ip=id_m.ip_address,
991 port=id_m.port,
992 sw_if_index=id_m.sw_if_index,
993 vrf_id=id_m.vrf_id,
994 protocol=id_m.protocol,
995 is_add=0)
996
Matus Fabian2ba92e32017-08-21 07:05:03 -0700997 adresses = self.vapi.nat44_address_dump()
Matus Fabiande886752016-12-07 03:38:19 -0800998 for addr in adresses:
Matus Fabian2ba92e32017-08-21 07:05:03 -0700999 self.vapi.nat44_add_del_address_range(addr.ip_address,
1000 addr.ip_address,
Matus Fabianb932d262017-12-18 05:38:24 -08001001 twice_nat=addr.twice_nat,
Matus Fabian2ba92e32017-08-21 07:05:03 -07001002 is_add=0)
Matus Fabiande886752016-12-07 03:38:19 -08001003
Matus Fabianefcd1e92017-08-15 06:59:19 -07001004 self.vapi.nat_set_reass()
1005 self.vapi.nat_set_reass(is_ip6=1)
1006
Matus Fabian2ba92e32017-08-21 07:05:03 -07001007 def nat44_add_static_mapping(self, local_ip, external_ip='0.0.0.0',
1008 local_port=0, external_port=0, vrf_id=0,
1009 is_add=1, external_sw_if_index=0xFFFFFFFF,
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02001010 proto=0, twice_nat=0, self_twice_nat=0,
1011 out2in_only=0, tag=""):
Matus Fabiande886752016-12-07 03:38:19 -08001012 """
Matus Fabian2ba92e32017-08-21 07:05:03 -07001013 Add/delete NAT44 static mapping
Matus Fabiande886752016-12-07 03:38:19 -08001014
1015 :param local_ip: Local IP address
1016 :param external_ip: External IP address
1017 :param local_port: Local port number (Optional)
1018 :param external_port: External port number (Optional)
1019 :param vrf_id: VRF ID (Default 0)
1020 :param is_add: 1 if add, 0 if delete (Default add)
Matus Fabian36532bd2017-01-23 23:42:28 -08001021 :param external_sw_if_index: External interface instead of IP address
Matus Fabian09d96f42017-02-02 01:43:00 -08001022 :param proto: IP protocol (Mandatory if port specified)
Matus Fabianb932d262017-12-18 05:38:24 -08001023 :param twice_nat: 1 if translate external host address and port
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02001024 :param self_twice_nat: 1 if translate external host address and port
1025 whenever external host address equals
1026 local address of internal host
Matus Fabiane82488f2018-01-18 03:38:45 -08001027 :param out2in_only: if 1 rule is matching only out2in direction
Matus Fabian5f224992018-01-25 21:59:16 -08001028 :param tag: Opaque string tag
Matus Fabiande886752016-12-07 03:38:19 -08001029 """
1030 addr_only = 1
1031 if local_port and external_port:
1032 addr_only = 0
1033 l_ip = socket.inet_pton(socket.AF_INET, local_ip)
1034 e_ip = socket.inet_pton(socket.AF_INET, external_ip)
Matus Fabian2ba92e32017-08-21 07:05:03 -07001035 self.vapi.nat44_add_del_static_mapping(
Klement Sekerada505f62017-01-04 12:58:53 +01001036 l_ip,
1037 e_ip,
Matus Fabian36532bd2017-01-23 23:42:28 -08001038 external_sw_if_index,
Klement Sekerada505f62017-01-04 12:58:53 +01001039 local_port,
1040 external_port,
1041 addr_only,
1042 vrf_id,
Matus Fabian09d96f42017-02-02 01:43:00 -08001043 proto,
Matus Fabianb932d262017-12-18 05:38:24 -08001044 twice_nat,
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02001045 self_twice_nat,
Matus Fabiane82488f2018-01-18 03:38:45 -08001046 out2in_only,
Matus Fabian5f224992018-01-25 21:59:16 -08001047 tag,
Klement Sekerada505f62017-01-04 12:58:53 +01001048 is_add)
Matus Fabiande886752016-12-07 03:38:19 -08001049
Matus Fabianb932d262017-12-18 05:38:24 -08001050 def nat44_add_address(self, ip, is_add=1, vrf_id=0xFFFFFFFF, twice_nat=0):
Matus Fabiande886752016-12-07 03:38:19 -08001051 """
Matus Fabian2ba92e32017-08-21 07:05:03 -07001052 Add/delete NAT44 address
Matus Fabiande886752016-12-07 03:38:19 -08001053
1054 :param ip: IP address
1055 :param is_add: 1 if add, 0 if delete (Default add)
Matus Fabianb932d262017-12-18 05:38:24 -08001056 :param twice_nat: twice NAT address for extenal hosts
Matus Fabiande886752016-12-07 03:38:19 -08001057 """
Matus Fabian2ba92e32017-08-21 07:05:03 -07001058 nat_addr = socket.inet_pton(socket.AF_INET, ip)
1059 self.vapi.nat44_add_del_address_range(nat_addr, nat_addr, is_add,
Matus Fabianb932d262017-12-18 05:38:24 -08001060 vrf_id=vrf_id,
1061 twice_nat=twice_nat)
Matus Fabiande886752016-12-07 03:38:19 -08001062
1063 def test_dynamic(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001064 """ NAT44 dynamic translation test """
Matus Fabiande886752016-12-07 03:38:19 -08001065
Matus Fabian2ba92e32017-08-21 07:05:03 -07001066 self.nat44_add_address(self.nat_addr)
1067 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1068 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1069 is_inside=0)
Matus Fabiande886752016-12-07 03:38:19 -08001070
1071 # in2out
1072 pkts = self.create_stream_in(self.pg0, self.pg1)
1073 self.pg0.add_stream(pkts)
1074 self.pg_enable_capture(self.pg_interfaces)
1075 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001076 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001077 self.verify_capture_out(capture)
1078
1079 # out2in
1080 pkts = self.create_stream_out(self.pg1)
1081 self.pg1.add_stream(pkts)
1082 self.pg_enable_capture(self.pg_interfaces)
1083 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001084 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001085 self.verify_capture_in(capture, self.pg0)
1086
Juraj Slobodab33f4132017-02-08 23:54:21 -08001087 def test_dynamic_icmp_errors_in2out_ttl_1(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001088 """ NAT44 handling of client packets with TTL=1 """
Juraj Slobodab33f4132017-02-08 23:54:21 -08001089
Matus Fabian2ba92e32017-08-21 07:05:03 -07001090 self.nat44_add_address(self.nat_addr)
1091 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1092 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1093 is_inside=0)
Juraj Slobodab33f4132017-02-08 23:54:21 -08001094
1095 # Client side - generate traffic
1096 pkts = self.create_stream_in(self.pg0, self.pg1, ttl=1)
1097 self.pg0.add_stream(pkts)
1098 self.pg_enable_capture(self.pg_interfaces)
1099 self.pg_start()
1100
1101 # Client side - verify ICMP type 11 packets
1102 capture = self.pg0.get_capture(len(pkts))
1103 self.verify_capture_in_with_icmp_errors(capture, self.pg0)
1104
1105 def test_dynamic_icmp_errors_out2in_ttl_1(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001106 """ NAT44 handling of server packets with TTL=1 """
Juraj Slobodab33f4132017-02-08 23:54:21 -08001107
Matus Fabian2ba92e32017-08-21 07:05:03 -07001108 self.nat44_add_address(self.nat_addr)
1109 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1110 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1111 is_inside=0)
Juraj Slobodab33f4132017-02-08 23:54:21 -08001112
1113 # Client side - create sessions
1114 pkts = self.create_stream_in(self.pg0, self.pg1)
1115 self.pg0.add_stream(pkts)
1116 self.pg_enable_capture(self.pg_interfaces)
1117 self.pg_start()
1118
1119 # Server side - generate traffic
1120 capture = self.pg1.get_capture(len(pkts))
1121 self.verify_capture_out(capture)
1122 pkts = self.create_stream_out(self.pg1, ttl=1)
1123 self.pg1.add_stream(pkts)
1124 self.pg_enable_capture(self.pg_interfaces)
1125 self.pg_start()
1126
1127 # Server side - verify ICMP type 11 packets
1128 capture = self.pg1.get_capture(len(pkts))
1129 self.verify_capture_out_with_icmp_errors(capture,
1130 src_ip=self.pg1.local_ip4)
1131
1132 def test_dynamic_icmp_errors_in2out_ttl_2(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001133 """ NAT44 handling of error responses to client packets with TTL=2 """
Juraj Slobodab33f4132017-02-08 23:54:21 -08001134
Matus Fabian2ba92e32017-08-21 07:05:03 -07001135 self.nat44_add_address(self.nat_addr)
1136 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1137 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1138 is_inside=0)
Juraj Slobodab33f4132017-02-08 23:54:21 -08001139
1140 # Client side - generate traffic
1141 pkts = self.create_stream_in(self.pg0, self.pg1, ttl=2)
1142 self.pg0.add_stream(pkts)
1143 self.pg_enable_capture(self.pg_interfaces)
1144 self.pg_start()
1145
1146 # Server side - simulate ICMP type 11 response
1147 capture = self.pg1.get_capture(len(pkts))
1148 pkts = [Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07001149 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Juraj Slobodab33f4132017-02-08 23:54:21 -08001150 ICMP(type=11) / packet[IP] for packet in capture]
1151 self.pg1.add_stream(pkts)
1152 self.pg_enable_capture(self.pg_interfaces)
1153 self.pg_start()
1154
1155 # Client side - verify ICMP type 11 packets
1156 capture = self.pg0.get_capture(len(pkts))
1157 self.verify_capture_in_with_icmp_errors(capture, self.pg0)
1158
1159 def test_dynamic_icmp_errors_out2in_ttl_2(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001160 """ NAT44 handling of error responses to server packets with TTL=2 """
Juraj Slobodab33f4132017-02-08 23:54:21 -08001161
Matus Fabian2ba92e32017-08-21 07:05:03 -07001162 self.nat44_add_address(self.nat_addr)
1163 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1164 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1165 is_inside=0)
Juraj Slobodab33f4132017-02-08 23:54:21 -08001166
1167 # Client side - create sessions
1168 pkts = self.create_stream_in(self.pg0, self.pg1)
1169 self.pg0.add_stream(pkts)
1170 self.pg_enable_capture(self.pg_interfaces)
1171 self.pg_start()
1172
1173 # Server side - generate traffic
1174 capture = self.pg1.get_capture(len(pkts))
1175 self.verify_capture_out(capture)
1176 pkts = self.create_stream_out(self.pg1, ttl=2)
1177 self.pg1.add_stream(pkts)
1178 self.pg_enable_capture(self.pg_interfaces)
1179 self.pg_start()
1180
1181 # Client side - simulate ICMP type 11 response
1182 capture = self.pg0.get_capture(len(pkts))
1183 pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1184 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
1185 ICMP(type=11) / packet[IP] for packet in capture]
1186 self.pg0.add_stream(pkts)
1187 self.pg_enable_capture(self.pg_interfaces)
1188 self.pg_start()
1189
1190 # Server side - verify ICMP type 11 packets
1191 capture = self.pg1.get_capture(len(pkts))
1192 self.verify_capture_out_with_icmp_errors(capture)
1193
Juraj Sloboda665e4822017-02-16 17:17:19 -08001194 def test_ping_out_interface_from_outside(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001195 """ Ping NAT44 out interface from outside network """
Juraj Sloboda665e4822017-02-16 17:17:19 -08001196
Matus Fabian2ba92e32017-08-21 07:05:03 -07001197 self.nat44_add_address(self.nat_addr)
1198 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1199 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1200 is_inside=0)
Juraj Sloboda665e4822017-02-16 17:17:19 -08001201
1202 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1203 IP(src=self.pg1.remote_ip4, dst=self.pg1.local_ip4) /
1204 ICMP(id=self.icmp_id_out, type='echo-request'))
1205 pkts = [p]
1206 self.pg1.add_stream(pkts)
1207 self.pg_enable_capture(self.pg_interfaces)
1208 self.pg_start()
1209 capture = self.pg1.get_capture(len(pkts))
1210 self.assertEqual(1, len(capture))
1211 packet = capture[0]
1212 try:
1213 self.assertEqual(packet[IP].src, self.pg1.local_ip4)
1214 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
1215 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
1216 self.assertEqual(packet[ICMP].type, 0) # echo reply
1217 except:
1218 self.logger.error(ppp("Unexpected or invalid packet "
1219 "(outside network):", packet))
1220 raise
1221
Juraj Slobodad3677682017-04-14 03:24:45 +02001222 def test_ping_internal_host_from_outside(self):
1223 """ Ping internal host from outside network """
1224
Matus Fabian2ba92e32017-08-21 07:05:03 -07001225 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr)
1226 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1227 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1228 is_inside=0)
Juraj Slobodad3677682017-04-14 03:24:45 +02001229
1230 # out2in
1231 pkt = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07001232 IP(src=self.pg1.remote_ip4, dst=self.nat_addr, ttl=64) /
Juraj Slobodad3677682017-04-14 03:24:45 +02001233 ICMP(id=self.icmp_id_out, type='echo-request'))
1234 self.pg1.add_stream(pkt)
1235 self.pg_enable_capture(self.pg_interfaces)
1236 self.pg_start()
1237 capture = self.pg0.get_capture(1)
1238 self.verify_capture_in(capture, self.pg0, packet_num=1)
1239 self.assert_equal(capture[0][IP].proto, IP_PROTOS.icmp)
1240
1241 # in2out
1242 pkt = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1243 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4, ttl=64) /
1244 ICMP(id=self.icmp_id_in, type='echo-reply'))
1245 self.pg0.add_stream(pkt)
1246 self.pg_enable_capture(self.pg_interfaces)
1247 self.pg_start()
1248 capture = self.pg1.get_capture(1)
1249 self.verify_capture_out(capture, same_port=True, packet_num=1)
1250 self.assert_equal(capture[0][IP].proto, IP_PROTOS.icmp)
1251
Juraj Sloboda7b929792017-11-23 13:20:48 +01001252 def test_forwarding(self):
1253 """ NAT44 forwarding test """
1254
1255 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1256 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1257 is_inside=0)
1258 self.vapi.nat44_forwarding_enable_disable(1)
1259
1260 real_ip = self.pg0.remote_ip4n
1261 alias_ip = self.nat_addr_n
1262 self.vapi.nat44_add_del_static_mapping(local_ip=real_ip,
1263 external_ip=alias_ip)
1264
1265 try:
1266 # in2out - static mapping match
1267
1268 pkts = self.create_stream_out(self.pg1)
1269 self.pg1.add_stream(pkts)
1270 self.pg_enable_capture(self.pg_interfaces)
1271 self.pg_start()
1272 capture = self.pg0.get_capture(len(pkts))
1273 self.verify_capture_in(capture, self.pg0)
1274
1275 pkts = self.create_stream_in(self.pg0, self.pg1)
1276 self.pg0.add_stream(pkts)
1277 self.pg_enable_capture(self.pg_interfaces)
1278 self.pg_start()
1279 capture = self.pg1.get_capture(len(pkts))
1280 self.verify_capture_out(capture, same_port=True)
1281
1282 # in2out - no static mapping match
1283
1284 host0 = self.pg0.remote_hosts[0]
1285 self.pg0.remote_hosts[0] = self.pg0.remote_hosts[1]
1286 try:
1287 pkts = self.create_stream_out(self.pg1,
1288 dst_ip=self.pg0.remote_ip4,
1289 use_inside_ports=True)
1290 self.pg1.add_stream(pkts)
1291 self.pg_enable_capture(self.pg_interfaces)
1292 self.pg_start()
1293 capture = self.pg0.get_capture(len(pkts))
1294 self.verify_capture_in(capture, self.pg0)
1295
1296 pkts = self.create_stream_in(self.pg0, self.pg1)
1297 self.pg0.add_stream(pkts)
1298 self.pg_enable_capture(self.pg_interfaces)
1299 self.pg_start()
1300 capture = self.pg1.get_capture(len(pkts))
1301 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
1302 same_port=True)
1303 finally:
1304 self.pg0.remote_hosts[0] = host0
1305
Matus Fabian70a26ac2018-05-14 06:20:28 -07001306 user = self.pg0.remote_hosts[1]
1307 sessions = self.vapi.nat44_user_session_dump(user.ip4n, 0)
1308 self.assertEqual(len(sessions), 3)
1309 self.assertTrue(sessions[0].ext_host_valid)
1310 self.vapi.nat44_del_session(
1311 sessions[0].inside_ip_address,
1312 sessions[0].inside_port,
1313 sessions[0].protocol,
1314 ext_host_address=sessions[0].ext_host_address,
1315 ext_host_port=sessions[0].ext_host_port)
1316 sessions = self.vapi.nat44_user_session_dump(user.ip4n, 0)
1317 self.assertEqual(len(sessions), 2)
1318
Juraj Sloboda7b929792017-11-23 13:20:48 +01001319 finally:
1320 self.vapi.nat44_forwarding_enable_disable(0)
1321 self.vapi.nat44_add_del_static_mapping(local_ip=real_ip,
1322 external_ip=alias_ip,
1323 is_add=0)
1324
Matus Fabiande886752016-12-07 03:38:19 -08001325 def test_static_in(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001326 """ 1:1 NAT initialized from inside network """
Matus Fabiande886752016-12-07 03:38:19 -08001327
1328 nat_ip = "10.0.0.10"
1329 self.tcp_port_out = 6303
1330 self.udp_port_out = 6304
1331 self.icmp_id_out = 6305
1332
Matus Fabian2ba92e32017-08-21 07:05:03 -07001333 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
1334 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1335 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1336 is_inside=0)
Matus Fabian5f224992018-01-25 21:59:16 -08001337 sm = self.vapi.nat44_static_mapping_dump()
1338 self.assertEqual(len(sm), 1)
1339 self.assertEqual((sm[0].tag).split('\0', 1)[0], '')
Matus Fabian9dba7812018-01-31 01:13:23 -08001340 self.assertEqual(sm[0].protocol, 0)
1341 self.assertEqual(sm[0].local_port, 0)
1342 self.assertEqual(sm[0].external_port, 0)
Matus Fabiande886752016-12-07 03:38:19 -08001343
1344 # in2out
1345 pkts = self.create_stream_in(self.pg0, self.pg1)
1346 self.pg0.add_stream(pkts)
1347 self.pg_enable_capture(self.pg_interfaces)
1348 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001349 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001350 self.verify_capture_out(capture, nat_ip, True)
1351
1352 # out2in
1353 pkts = self.create_stream_out(self.pg1, nat_ip)
1354 self.pg1.add_stream(pkts)
1355 self.pg_enable_capture(self.pg_interfaces)
1356 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001357 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001358 self.verify_capture_in(capture, self.pg0)
1359
1360 def test_static_out(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001361 """ 1:1 NAT initialized from outside network """
Matus Fabiande886752016-12-07 03:38:19 -08001362
1363 nat_ip = "10.0.0.20"
1364 self.tcp_port_out = 6303
1365 self.udp_port_out = 6304
1366 self.icmp_id_out = 6305
Matus Fabian5f224992018-01-25 21:59:16 -08001367 tag = "testTAG"
Matus Fabiande886752016-12-07 03:38:19 -08001368
Matus Fabian5f224992018-01-25 21:59:16 -08001369 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip, tag=tag)
Matus Fabian2ba92e32017-08-21 07:05:03 -07001370 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1371 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1372 is_inside=0)
Matus Fabian5f224992018-01-25 21:59:16 -08001373 sm = self.vapi.nat44_static_mapping_dump()
1374 self.assertEqual(len(sm), 1)
1375 self.assertEqual((sm[0].tag).split('\0', 1)[0], tag)
Matus Fabiande886752016-12-07 03:38:19 -08001376
1377 # out2in
1378 pkts = self.create_stream_out(self.pg1, nat_ip)
1379 self.pg1.add_stream(pkts)
1380 self.pg_enable_capture(self.pg_interfaces)
1381 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001382 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001383 self.verify_capture_in(capture, self.pg0)
1384
1385 # in2out
1386 pkts = self.create_stream_in(self.pg0, self.pg1)
1387 self.pg0.add_stream(pkts)
1388 self.pg_enable_capture(self.pg_interfaces)
1389 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001390 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001391 self.verify_capture_out(capture, nat_ip, True)
1392
1393 def test_static_with_port_in(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001394 """ 1:1 NAPT initialized from inside network """
Matus Fabiande886752016-12-07 03:38:19 -08001395
1396 self.tcp_port_out = 3606
1397 self.udp_port_out = 3607
1398 self.icmp_id_out = 3608
1399
Matus Fabian2ba92e32017-08-21 07:05:03 -07001400 self.nat44_add_address(self.nat_addr)
1401 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1402 self.tcp_port_in, self.tcp_port_out,
1403 proto=IP_PROTOS.tcp)
1404 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1405 self.udp_port_in, self.udp_port_out,
1406 proto=IP_PROTOS.udp)
1407 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1408 self.icmp_id_in, self.icmp_id_out,
1409 proto=IP_PROTOS.icmp)
1410 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1411 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1412 is_inside=0)
Matus Fabiande886752016-12-07 03:38:19 -08001413
1414 # in2out
1415 pkts = self.create_stream_in(self.pg0, self.pg1)
1416 self.pg0.add_stream(pkts)
1417 self.pg_enable_capture(self.pg_interfaces)
1418 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001419 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001420 self.verify_capture_out(capture)
1421
1422 # out2in
1423 pkts = self.create_stream_out(self.pg1)
1424 self.pg1.add_stream(pkts)
1425 self.pg_enable_capture(self.pg_interfaces)
1426 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001427 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001428 self.verify_capture_in(capture, self.pg0)
1429
1430 def test_static_with_port_out(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001431 """ 1:1 NAPT initialized from outside network """
Matus Fabiande886752016-12-07 03:38:19 -08001432
1433 self.tcp_port_out = 30606
1434 self.udp_port_out = 30607
1435 self.icmp_id_out = 30608
1436
Matus Fabian2ba92e32017-08-21 07:05:03 -07001437 self.nat44_add_address(self.nat_addr)
1438 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1439 self.tcp_port_in, self.tcp_port_out,
1440 proto=IP_PROTOS.tcp)
1441 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1442 self.udp_port_in, self.udp_port_out,
1443 proto=IP_PROTOS.udp)
1444 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1445 self.icmp_id_in, self.icmp_id_out,
1446 proto=IP_PROTOS.icmp)
1447 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1448 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1449 is_inside=0)
Matus Fabiande886752016-12-07 03:38:19 -08001450
1451 # out2in
1452 pkts = self.create_stream_out(self.pg1)
1453 self.pg1.add_stream(pkts)
1454 self.pg_enable_capture(self.pg_interfaces)
1455 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001456 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001457 self.verify_capture_in(capture, self.pg0)
1458
1459 # in2out
1460 pkts = self.create_stream_in(self.pg0, self.pg1)
1461 self.pg0.add_stream(pkts)
1462 self.pg_enable_capture(self.pg_interfaces)
1463 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001464 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001465 self.verify_capture_out(capture)
1466
Matus Fabiane82488f2018-01-18 03:38:45 -08001467 def test_static_with_port_out2(self):
1468 """ 1:1 NAPT symmetrical rule """
1469
1470 external_port = 80
1471 local_port = 8080
1472
1473 self.vapi.nat44_forwarding_enable_disable(1)
1474 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1475 local_port, external_port,
1476 proto=IP_PROTOS.tcp, out2in_only=1)
1477 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1478 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1479 is_inside=0)
1480
1481 # from client to service
1482 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
1483 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
1484 TCP(sport=12345, dport=external_port))
1485 self.pg1.add_stream(p)
1486 self.pg_enable_capture(self.pg_interfaces)
1487 self.pg_start()
1488 capture = self.pg0.get_capture(1)
1489 p = capture[0]
Matus Fabiane82488f2018-01-18 03:38:45 -08001490 try:
1491 ip = p[IP]
1492 tcp = p[TCP]
1493 self.assertEqual(ip.dst, self.pg0.remote_ip4)
1494 self.assertEqual(tcp.dport, local_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02001495 self.assert_packet_checksums_valid(p)
Matus Fabiane82488f2018-01-18 03:38:45 -08001496 except:
1497 self.logger.error(ppp("Unexpected or invalid packet:", p))
1498 raise
1499
Matus Fabian87233b52018-01-26 03:17:01 -08001500 # ICMP error
1501 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1502 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
1503 ICMP(type=11) / capture[0][IP])
1504 self.pg0.add_stream(p)
1505 self.pg_enable_capture(self.pg_interfaces)
1506 self.pg_start()
1507 capture = self.pg1.get_capture(1)
1508 p = capture[0]
1509 try:
1510 self.assertEqual(p[IP].src, self.nat_addr)
1511 inner = p[IPerror]
1512 self.assertEqual(inner.dst, self.nat_addr)
1513 self.assertEqual(inner[TCPerror].dport, external_port)
1514 except:
1515 self.logger.error(ppp("Unexpected or invalid packet:", p))
1516 raise
1517
Matus Fabiane82488f2018-01-18 03:38:45 -08001518 # from service back to client
1519 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
1520 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
1521 TCP(sport=local_port, dport=12345))
1522 self.pg0.add_stream(p)
1523 self.pg_enable_capture(self.pg_interfaces)
1524 self.pg_start()
1525 capture = self.pg1.get_capture(1)
1526 p = capture[0]
1527 try:
1528 ip = p[IP]
1529 tcp = p[TCP]
1530 self.assertEqual(ip.src, self.nat_addr)
1531 self.assertEqual(tcp.sport, external_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02001532 self.assert_packet_checksums_valid(p)
Matus Fabiane82488f2018-01-18 03:38:45 -08001533 except:
1534 self.logger.error(ppp("Unexpected or invalid packet:", p))
1535 raise
1536
Matus Fabian87233b52018-01-26 03:17:01 -08001537 # ICMP error
1538 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1539 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
1540 ICMP(type=11) / capture[0][IP])
1541 self.pg1.add_stream(p)
1542 self.pg_enable_capture(self.pg_interfaces)
1543 self.pg_start()
1544 capture = self.pg0.get_capture(1)
1545 p = capture[0]
1546 try:
1547 self.assertEqual(p[IP].dst, self.pg0.remote_ip4)
1548 inner = p[IPerror]
1549 self.assertEqual(inner.src, self.pg0.remote_ip4)
1550 self.assertEqual(inner[TCPerror].sport, local_port)
1551 except:
1552 self.logger.error(ppp("Unexpected or invalid packet:", p))
1553 raise
1554
Matus Fabiane82488f2018-01-18 03:38:45 -08001555 # from client to server (no translation)
1556 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
1557 IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
1558 TCP(sport=12346, dport=local_port))
1559 self.pg1.add_stream(p)
1560 self.pg_enable_capture(self.pg_interfaces)
1561 self.pg_start()
1562 capture = self.pg0.get_capture(1)
1563 p = capture[0]
Matus Fabiane82488f2018-01-18 03:38:45 -08001564 try:
1565 ip = p[IP]
1566 tcp = p[TCP]
1567 self.assertEqual(ip.dst, self.pg0.remote_ip4)
1568 self.assertEqual(tcp.dport, local_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02001569 self.assert_packet_checksums_valid(p)
Matus Fabiane82488f2018-01-18 03:38:45 -08001570 except:
1571 self.logger.error(ppp("Unexpected or invalid packet:", p))
1572 raise
1573
1574 # from service back to client (no translation)
1575 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
1576 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
1577 TCP(sport=local_port, dport=12346))
1578 self.pg0.add_stream(p)
1579 self.pg_enable_capture(self.pg_interfaces)
1580 self.pg_start()
1581 capture = self.pg1.get_capture(1)
1582 p = capture[0]
1583 try:
1584 ip = p[IP]
1585 tcp = p[TCP]
1586 self.assertEqual(ip.src, self.pg0.remote_ip4)
1587 self.assertEqual(tcp.sport, local_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02001588 self.assert_packet_checksums_valid(p)
Matus Fabiane82488f2018-01-18 03:38:45 -08001589 except:
1590 self.logger.error(ppp("Unexpected or invalid packet:", p))
1591 raise
1592
Matus Fabiande886752016-12-07 03:38:19 -08001593 def test_static_vrf_aware(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001594 """ 1:1 NAT VRF awareness """
Matus Fabiande886752016-12-07 03:38:19 -08001595
1596 nat_ip1 = "10.0.0.30"
1597 nat_ip2 = "10.0.0.40"
1598 self.tcp_port_out = 6303
1599 self.udp_port_out = 6304
1600 self.icmp_id_out = 6305
1601
Matus Fabian2ba92e32017-08-21 07:05:03 -07001602 self.nat44_add_static_mapping(self.pg4.remote_ip4, nat_ip1,
1603 vrf_id=10)
1604 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip2,
1605 vrf_id=10)
1606 self.vapi.nat44_interface_add_del_feature(self.pg3.sw_if_index,
1607 is_inside=0)
1608 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1609 self.vapi.nat44_interface_add_del_feature(self.pg4.sw_if_index)
Matus Fabiande886752016-12-07 03:38:19 -08001610
Matus Fabian2ba92e32017-08-21 07:05:03 -07001611 # inside interface VRF match NAT44 static mapping VRF
Matus Fabiande886752016-12-07 03:38:19 -08001612 pkts = self.create_stream_in(self.pg4, self.pg3)
1613 self.pg4.add_stream(pkts)
1614 self.pg_enable_capture(self.pg_interfaces)
1615 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001616 capture = self.pg3.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001617 self.verify_capture_out(capture, nat_ip1, True)
1618
Matus Fabian2ba92e32017-08-21 07:05:03 -07001619 # inside interface VRF don't match NAT44 static mapping VRF (packets
Matus Fabiande886752016-12-07 03:38:19 -08001620 # are dropped)
1621 pkts = self.create_stream_in(self.pg0, self.pg3)
1622 self.pg0.add_stream(pkts)
1623 self.pg_enable_capture(self.pg_interfaces)
1624 self.pg_start()
Klement Sekera9225dee2016-12-12 08:36:58 +01001625 self.pg3.assert_nothing_captured()
Matus Fabiande886752016-12-07 03:38:19 -08001626
Matus Fabianb793d092018-01-31 05:50:21 -08001627 def test_dynamic_to_static(self):
1628 """ Switch from dynamic translation to 1:1NAT """
1629 nat_ip = "10.0.0.10"
1630 self.tcp_port_out = 6303
1631 self.udp_port_out = 6304
1632 self.icmp_id_out = 6305
1633
1634 self.nat44_add_address(self.nat_addr)
1635 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1636 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1637 is_inside=0)
1638
1639 # dynamic
1640 pkts = self.create_stream_in(self.pg0, self.pg1)
1641 self.pg0.add_stream(pkts)
1642 self.pg_enable_capture(self.pg_interfaces)
1643 self.pg_start()
1644 capture = self.pg1.get_capture(len(pkts))
1645 self.verify_capture_out(capture)
1646
1647 # 1:1NAT
1648 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
1649 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
1650 self.assertEqual(len(sessions), 0)
1651 pkts = self.create_stream_in(self.pg0, self.pg1)
1652 self.pg0.add_stream(pkts)
1653 self.pg_enable_capture(self.pg_interfaces)
1654 self.pg_start()
1655 capture = self.pg1.get_capture(len(pkts))
1656 self.verify_capture_out(capture, nat_ip, True)
1657
Matus Fabianab7a8052017-11-28 04:29:41 -08001658 def test_identity_nat(self):
1659 """ Identity NAT """
1660
1661 self.vapi.nat44_add_del_identity_mapping(ip=self.pg0.remote_ip4n)
1662 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1663 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1664 is_inside=0)
1665
1666 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
1667 IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
1668 TCP(sport=12345, dport=56789))
1669 self.pg1.add_stream(p)
1670 self.pg_enable_capture(self.pg_interfaces)
1671 self.pg_start()
1672 capture = self.pg0.get_capture(1)
1673 p = capture[0]
1674 try:
1675 ip = p[IP]
1676 tcp = p[TCP]
1677 self.assertEqual(ip.dst, self.pg0.remote_ip4)
1678 self.assertEqual(ip.src, self.pg1.remote_ip4)
1679 self.assertEqual(tcp.dport, 56789)
1680 self.assertEqual(tcp.sport, 12345)
Klement Sekerad81ae412018-05-16 10:52:54 +02001681 self.assert_packet_checksums_valid(p)
Matus Fabianab7a8052017-11-28 04:29:41 -08001682 except:
1683 self.logger.error(ppp("Unexpected or invalid packet:", p))
1684 raise
1685
Matus Fabian704018c2017-09-04 02:17:18 -07001686 def test_static_lb(self):
1687 """ NAT44 local service load balancing """
1688 external_addr_n = socket.inet_pton(socket.AF_INET, self.nat_addr)
1689 external_port = 80
1690 local_port = 8080
1691 server1 = self.pg0.remote_hosts[0]
1692 server2 = self.pg0.remote_hosts[1]
1693
1694 locals = [{'addr': server1.ip4n,
1695 'port': local_port,
1696 'probability': 70},
1697 {'addr': server2.ip4n,
1698 'port': local_port,
1699 'probability': 30}]
1700
1701 self.nat44_add_address(self.nat_addr)
1702 self.vapi.nat44_add_del_lb_static_mapping(external_addr_n,
1703 external_port,
1704 IP_PROTOS.tcp,
1705 local_num=len(locals),
1706 locals=locals)
1707 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1708 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1709 is_inside=0)
1710
1711 # from client to service
1712 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
1713 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
1714 TCP(sport=12345, dport=external_port))
1715 self.pg1.add_stream(p)
1716 self.pg_enable_capture(self.pg_interfaces)
1717 self.pg_start()
1718 capture = self.pg0.get_capture(1)
1719 p = capture[0]
1720 server = None
1721 try:
1722 ip = p[IP]
1723 tcp = p[TCP]
1724 self.assertIn(ip.dst, [server1.ip4, server2.ip4])
1725 if ip.dst == server1.ip4:
1726 server = server1
1727 else:
1728 server = server2
1729 self.assertEqual(tcp.dport, local_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02001730 self.assert_packet_checksums_valid(p)
Matus Fabian704018c2017-09-04 02:17:18 -07001731 except:
1732 self.logger.error(ppp("Unexpected or invalid packet:", p))
1733 raise
1734
1735 # from service back to client
1736 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
1737 IP(src=server.ip4, dst=self.pg1.remote_ip4) /
1738 TCP(sport=local_port, dport=12345))
1739 self.pg0.add_stream(p)
1740 self.pg_enable_capture(self.pg_interfaces)
1741 self.pg_start()
1742 capture = self.pg1.get_capture(1)
1743 p = capture[0]
1744 try:
1745 ip = p[IP]
1746 tcp = p[TCP]
1747 self.assertEqual(ip.src, self.nat_addr)
1748 self.assertEqual(tcp.sport, external_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02001749 self.assert_packet_checksums_valid(p)
Matus Fabian704018c2017-09-04 02:17:18 -07001750 except:
1751 self.logger.error(ppp("Unexpected or invalid packet:", p))
1752 raise
1753
Matus Fabian70a26ac2018-05-14 06:20:28 -07001754 sessions = self.vapi.nat44_user_session_dump(server.ip4n, 0)
1755 self.assertEqual(len(sessions), 1)
1756 self.assertTrue(sessions[0].ext_host_valid)
1757 self.vapi.nat44_del_session(
1758 sessions[0].inside_ip_address,
1759 sessions[0].inside_port,
1760 sessions[0].protocol,
1761 ext_host_address=sessions[0].ext_host_address,
1762 ext_host_port=sessions[0].ext_host_port)
1763 sessions = self.vapi.nat44_user_session_dump(server.ip4n, 0)
1764 self.assertEqual(len(sessions), 0)
1765
Matus Fabian2aad8762018-03-07 04:57:22 -08001766 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
1767 def test_static_lb_multi_clients(self):
1768 """ NAT44 local service load balancing - multiple clients"""
1769
1770 external_addr_n = socket.inet_pton(socket.AF_INET, self.nat_addr)
1771 external_port = 80
1772 local_port = 8080
1773 server1 = self.pg0.remote_hosts[0]
1774 server2 = self.pg0.remote_hosts[1]
1775
1776 locals = [{'addr': server1.ip4n,
1777 'port': local_port,
1778 'probability': 90},
1779 {'addr': server2.ip4n,
1780 'port': local_port,
1781 'probability': 10}]
1782
1783 self.nat44_add_address(self.nat_addr)
1784 self.vapi.nat44_add_del_lb_static_mapping(external_addr_n,
1785 external_port,
1786 IP_PROTOS.tcp,
1787 local_num=len(locals),
1788 locals=locals)
1789 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1790 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1791 is_inside=0)
1792
Matus Fabian704018c2017-09-04 02:17:18 -07001793 server1_n = 0
1794 server2_n = 0
Matus Fabian2aad8762018-03-07 04:57:22 -08001795 clients = ip4_range(self.pg1.remote_ip4, 10, 50)
Matus Fabian704018c2017-09-04 02:17:18 -07001796 pkts = []
1797 for client in clients:
1798 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
1799 IP(src=client, dst=self.nat_addr) /
1800 TCP(sport=12345, dport=external_port))
1801 pkts.append(p)
1802 self.pg1.add_stream(pkts)
1803 self.pg_enable_capture(self.pg_interfaces)
1804 self.pg_start()
1805 capture = self.pg0.get_capture(len(pkts))
1806 for p in capture:
1807 if p[IP].dst == server1.ip4:
1808 server1_n += 1
1809 else:
1810 server2_n += 1
1811 self.assertTrue(server1_n > server2_n)
1812
Matus Fabian240b5ef2018-01-11 04:09:17 -08001813 def test_static_lb_2(self):
1814 """ NAT44 local service load balancing (asymmetrical rule) """
1815 external_addr_n = socket.inet_pton(socket.AF_INET, self.nat_addr)
1816 external_port = 80
1817 local_port = 8080
1818 server1 = self.pg0.remote_hosts[0]
1819 server2 = self.pg0.remote_hosts[1]
1820
1821 locals = [{'addr': server1.ip4n,
1822 'port': local_port,
1823 'probability': 70},
1824 {'addr': server2.ip4n,
1825 'port': local_port,
1826 'probability': 30}]
1827
1828 self.vapi.nat44_forwarding_enable_disable(1)
1829 self.vapi.nat44_add_del_lb_static_mapping(external_addr_n,
1830 external_port,
1831 IP_PROTOS.tcp,
1832 out2in_only=1,
1833 local_num=len(locals),
1834 locals=locals)
1835 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1836 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1837 is_inside=0)
1838
1839 # from client to service
1840 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
1841 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
1842 TCP(sport=12345, dport=external_port))
1843 self.pg1.add_stream(p)
1844 self.pg_enable_capture(self.pg_interfaces)
1845 self.pg_start()
1846 capture = self.pg0.get_capture(1)
1847 p = capture[0]
1848 server = None
1849 try:
1850 ip = p[IP]
1851 tcp = p[TCP]
1852 self.assertIn(ip.dst, [server1.ip4, server2.ip4])
1853 if ip.dst == server1.ip4:
1854 server = server1
1855 else:
1856 server = server2
1857 self.assertEqual(tcp.dport, local_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02001858 self.assert_packet_checksums_valid(p)
Matus Fabian240b5ef2018-01-11 04:09:17 -08001859 except:
1860 self.logger.error(ppp("Unexpected or invalid packet:", p))
1861 raise
1862
1863 # from service back to client
1864 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
1865 IP(src=server.ip4, dst=self.pg1.remote_ip4) /
1866 TCP(sport=local_port, dport=12345))
1867 self.pg0.add_stream(p)
1868 self.pg_enable_capture(self.pg_interfaces)
1869 self.pg_start()
1870 capture = self.pg1.get_capture(1)
1871 p = capture[0]
1872 try:
1873 ip = p[IP]
1874 tcp = p[TCP]
1875 self.assertEqual(ip.src, self.nat_addr)
1876 self.assertEqual(tcp.sport, external_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02001877 self.assert_packet_checksums_valid(p)
Matus Fabian240b5ef2018-01-11 04:09:17 -08001878 except:
1879 self.logger.error(ppp("Unexpected or invalid packet:", p))
1880 raise
1881
1882 # from client to server (no translation)
1883 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
1884 IP(src=self.pg1.remote_ip4, dst=server1.ip4) /
1885 TCP(sport=12346, dport=local_port))
1886 self.pg1.add_stream(p)
1887 self.pg_enable_capture(self.pg_interfaces)
1888 self.pg_start()
1889 capture = self.pg0.get_capture(1)
1890 p = capture[0]
1891 server = None
1892 try:
1893 ip = p[IP]
1894 tcp = p[TCP]
1895 self.assertEqual(ip.dst, server1.ip4)
1896 self.assertEqual(tcp.dport, local_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02001897 self.assert_packet_checksums_valid(p)
Matus Fabian240b5ef2018-01-11 04:09:17 -08001898 except:
1899 self.logger.error(ppp("Unexpected or invalid packet:", p))
1900 raise
1901
1902 # from service back to client (no translation)
1903 p = (Ether(src=server1.mac, dst=self.pg0.local_mac) /
1904 IP(src=server1.ip4, dst=self.pg1.remote_ip4) /
1905 TCP(sport=local_port, dport=12346))
1906 self.pg0.add_stream(p)
1907 self.pg_enable_capture(self.pg_interfaces)
1908 self.pg_start()
1909 capture = self.pg1.get_capture(1)
1910 p = capture[0]
1911 try:
1912 ip = p[IP]
1913 tcp = p[TCP]
1914 self.assertEqual(ip.src, server1.ip4)
1915 self.assertEqual(tcp.sport, local_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02001916 self.assert_packet_checksums_valid(p)
Matus Fabian240b5ef2018-01-11 04:09:17 -08001917 except:
1918 self.logger.error(ppp("Unexpected or invalid packet:", p))
1919 raise
1920
Matus Fabiande886752016-12-07 03:38:19 -08001921 def test_multiple_inside_interfaces(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001922 """ NAT44 multiple non-overlapping address space inside interfaces """
Matus Fabiande886752016-12-07 03:38:19 -08001923
Matus Fabian2ba92e32017-08-21 07:05:03 -07001924 self.nat44_add_address(self.nat_addr)
1925 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1926 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
1927 self.vapi.nat44_interface_add_del_feature(self.pg3.sw_if_index,
1928 is_inside=0)
Matus Fabiande886752016-12-07 03:38:19 -08001929
Matus Fabian2ba92e32017-08-21 07:05:03 -07001930 # between two NAT44 inside interfaces (no translation)
Matus Fabian675a69c2017-01-18 01:46:01 -08001931 pkts = self.create_stream_in(self.pg0, self.pg1)
1932 self.pg0.add_stream(pkts)
1933 self.pg_enable_capture(self.pg_interfaces)
1934 self.pg_start()
1935 capture = self.pg1.get_capture(len(pkts))
1936 self.verify_capture_no_translation(capture, self.pg0, self.pg1)
1937
Matus Fabian2ba92e32017-08-21 07:05:03 -07001938 # from NAT44 inside to interface without NAT44 feature (no translation)
Matus Fabian675a69c2017-01-18 01:46:01 -08001939 pkts = self.create_stream_in(self.pg0, self.pg2)
1940 self.pg0.add_stream(pkts)
1941 self.pg_enable_capture(self.pg_interfaces)
1942 self.pg_start()
1943 capture = self.pg2.get_capture(len(pkts))
1944 self.verify_capture_no_translation(capture, self.pg0, self.pg2)
1945
Matus Fabiande886752016-12-07 03:38:19 -08001946 # in2out 1st interface
1947 pkts = self.create_stream_in(self.pg0, self.pg3)
1948 self.pg0.add_stream(pkts)
1949 self.pg_enable_capture(self.pg_interfaces)
1950 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001951 capture = self.pg3.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001952 self.verify_capture_out(capture)
1953
1954 # out2in 1st interface
1955 pkts = self.create_stream_out(self.pg3)
1956 self.pg3.add_stream(pkts)
1957 self.pg_enable_capture(self.pg_interfaces)
1958 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001959 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001960 self.verify_capture_in(capture, self.pg0)
1961
1962 # in2out 2nd interface
1963 pkts = self.create_stream_in(self.pg1, self.pg3)
1964 self.pg1.add_stream(pkts)
1965 self.pg_enable_capture(self.pg_interfaces)
1966 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001967 capture = self.pg3.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001968 self.verify_capture_out(capture)
1969
1970 # out2in 2nd interface
1971 pkts = self.create_stream_out(self.pg3)
1972 self.pg3.add_stream(pkts)
1973 self.pg_enable_capture(self.pg_interfaces)
1974 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001975 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001976 self.verify_capture_in(capture, self.pg1)
1977
Matus Fabiande886752016-12-07 03:38:19 -08001978 def test_inside_overlapping_interfaces(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001979 """ NAT44 multiple inside interfaces with overlapping address space """
Matus Fabiande886752016-12-07 03:38:19 -08001980
Matus Fabian675a69c2017-01-18 01:46:01 -08001981 static_nat_ip = "10.0.0.10"
Matus Fabian2ba92e32017-08-21 07:05:03 -07001982 self.nat44_add_address(self.nat_addr)
1983 self.vapi.nat44_interface_add_del_feature(self.pg3.sw_if_index,
1984 is_inside=0)
1985 self.vapi.nat44_interface_add_del_feature(self.pg4.sw_if_index)
1986 self.vapi.nat44_interface_add_del_feature(self.pg5.sw_if_index)
1987 self.vapi.nat44_interface_add_del_feature(self.pg6.sw_if_index)
1988 self.nat44_add_static_mapping(self.pg6.remote_ip4, static_nat_ip,
1989 vrf_id=20)
Matus Fabian675a69c2017-01-18 01:46:01 -08001990
Matus Fabian2ba92e32017-08-21 07:05:03 -07001991 # between NAT44 inside interfaces with same VRF (no translation)
Matus Fabian675a69c2017-01-18 01:46:01 -08001992 pkts = self.create_stream_in(self.pg4, self.pg5)
1993 self.pg4.add_stream(pkts)
1994 self.pg_enable_capture(self.pg_interfaces)
1995 self.pg_start()
1996 capture = self.pg5.get_capture(len(pkts))
1997 self.verify_capture_no_translation(capture, self.pg4, self.pg5)
1998
Matus Fabian2ba92e32017-08-21 07:05:03 -07001999 # between NAT44 inside interfaces with different VRF (hairpinning)
Matus Fabian675a69c2017-01-18 01:46:01 -08002000 p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
2001 IP(src=self.pg4.remote_ip4, dst=static_nat_ip) /
2002 TCP(sport=1234, dport=5678))
2003 self.pg4.add_stream(p)
2004 self.pg_enable_capture(self.pg_interfaces)
2005 self.pg_start()
2006 capture = self.pg6.get_capture(1)
2007 p = capture[0]
2008 try:
2009 ip = p[IP]
2010 tcp = p[TCP]
Matus Fabian2ba92e32017-08-21 07:05:03 -07002011 self.assertEqual(ip.src, self.nat_addr)
Matus Fabian675a69c2017-01-18 01:46:01 -08002012 self.assertEqual(ip.dst, self.pg6.remote_ip4)
2013 self.assertNotEqual(tcp.sport, 1234)
2014 self.assertEqual(tcp.dport, 5678)
2015 except:
2016 self.logger.error(ppp("Unexpected or invalid packet:", p))
2017 raise
Matus Fabiande886752016-12-07 03:38:19 -08002018
2019 # in2out 1st interface
2020 pkts = self.create_stream_in(self.pg4, self.pg3)
2021 self.pg4.add_stream(pkts)
2022 self.pg_enable_capture(self.pg_interfaces)
2023 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002024 capture = self.pg3.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002025 self.verify_capture_out(capture)
2026
2027 # out2in 1st interface
2028 pkts = self.create_stream_out(self.pg3)
2029 self.pg3.add_stream(pkts)
2030 self.pg_enable_capture(self.pg_interfaces)
2031 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002032 capture = self.pg4.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002033 self.verify_capture_in(capture, self.pg4)
2034
2035 # in2out 2nd interface
2036 pkts = self.create_stream_in(self.pg5, self.pg3)
2037 self.pg5.add_stream(pkts)
2038 self.pg_enable_capture(self.pg_interfaces)
2039 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002040 capture = self.pg3.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002041 self.verify_capture_out(capture)
2042
2043 # out2in 2nd interface
2044 pkts = self.create_stream_out(self.pg3)
2045 self.pg3.add_stream(pkts)
2046 self.pg_enable_capture(self.pg_interfaces)
2047 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002048 capture = self.pg5.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002049 self.verify_capture_in(capture, self.pg5)
2050
magalik23caa882017-02-08 23:25:45 -08002051 # pg5 session dump
Matus Fabian2ba92e32017-08-21 07:05:03 -07002052 addresses = self.vapi.nat44_address_dump()
magalik23caa882017-02-08 23:25:45 -08002053 self.assertEqual(len(addresses), 1)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002054 sessions = self.vapi.nat44_user_session_dump(self.pg5.remote_ip4n, 10)
magalik23caa882017-02-08 23:25:45 -08002055 self.assertEqual(len(sessions), 3)
2056 for session in sessions:
2057 self.assertFalse(session.is_static)
2058 self.assertEqual(session.inside_ip_address[0:4],
2059 self.pg5.remote_ip4n)
2060 self.assertEqual(session.outside_ip_address,
2061 addresses[0].ip_address)
2062 self.assertEqual(sessions[0].protocol, IP_PROTOS.tcp)
2063 self.assertEqual(sessions[1].protocol, IP_PROTOS.udp)
2064 self.assertEqual(sessions[2].protocol, IP_PROTOS.icmp)
2065 self.assertEqual(sessions[0].inside_port, self.tcp_port_in)
2066 self.assertEqual(sessions[1].inside_port, self.udp_port_in)
2067 self.assertEqual(sessions[2].inside_port, self.icmp_id_in)
2068 self.assertEqual(sessions[0].outside_port, self.tcp_port_out)
2069 self.assertEqual(sessions[1].outside_port, self.udp_port_out)
2070 self.assertEqual(sessions[2].outside_port, self.icmp_id_out)
2071
Matus Fabiande886752016-12-07 03:38:19 -08002072 # in2out 3rd interface
2073 pkts = self.create_stream_in(self.pg6, self.pg3)
2074 self.pg6.add_stream(pkts)
2075 self.pg_enable_capture(self.pg_interfaces)
2076 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002077 capture = self.pg3.get_capture(len(pkts))
Matus Fabian675a69c2017-01-18 01:46:01 -08002078 self.verify_capture_out(capture, static_nat_ip, True)
Matus Fabiande886752016-12-07 03:38:19 -08002079
2080 # out2in 3rd interface
Matus Fabian675a69c2017-01-18 01:46:01 -08002081 pkts = self.create_stream_out(self.pg3, static_nat_ip)
Matus Fabiande886752016-12-07 03:38:19 -08002082 self.pg3.add_stream(pkts)
2083 self.pg_enable_capture(self.pg_interfaces)
2084 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002085 capture = self.pg6.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002086 self.verify_capture_in(capture, self.pg6)
2087
magalik23caa882017-02-08 23:25:45 -08002088 # general user and session dump verifications
Matus Fabian2ba92e32017-08-21 07:05:03 -07002089 users = self.vapi.nat44_user_dump()
magalik23caa882017-02-08 23:25:45 -08002090 self.assertTrue(len(users) >= 3)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002091 addresses = self.vapi.nat44_address_dump()
magalik23caa882017-02-08 23:25:45 -08002092 self.assertEqual(len(addresses), 1)
2093 for user in users:
Matus Fabian2ba92e32017-08-21 07:05:03 -07002094 sessions = self.vapi.nat44_user_session_dump(user.ip_address,
2095 user.vrf_id)
magalik23caa882017-02-08 23:25:45 -08002096 for session in sessions:
2097 self.assertEqual(user.ip_address, session.inside_ip_address)
2098 self.assertTrue(session.total_bytes > session.total_pkts > 0)
2099 self.assertTrue(session.protocol in
2100 [IP_PROTOS.tcp, IP_PROTOS.udp,
2101 IP_PROTOS.icmp])
Matus Fabian70a26ac2018-05-14 06:20:28 -07002102 self.assertFalse(session.ext_host_valid)
magalik23caa882017-02-08 23:25:45 -08002103
2104 # pg4 session dump
Matus Fabian2ba92e32017-08-21 07:05:03 -07002105 sessions = self.vapi.nat44_user_session_dump(self.pg4.remote_ip4n, 10)
magalik23caa882017-02-08 23:25:45 -08002106 self.assertTrue(len(sessions) >= 4)
2107 for session in sessions:
2108 self.assertFalse(session.is_static)
2109 self.assertEqual(session.inside_ip_address[0:4],
2110 self.pg4.remote_ip4n)
2111 self.assertEqual(session.outside_ip_address,
2112 addresses[0].ip_address)
2113
2114 # pg6 session dump
Matus Fabian2ba92e32017-08-21 07:05:03 -07002115 sessions = self.vapi.nat44_user_session_dump(self.pg6.remote_ip4n, 20)
magalik23caa882017-02-08 23:25:45 -08002116 self.assertTrue(len(sessions) >= 3)
2117 for session in sessions:
2118 self.assertTrue(session.is_static)
2119 self.assertEqual(session.inside_ip_address[0:4],
2120 self.pg6.remote_ip4n)
2121 self.assertEqual(map(ord, session.outside_ip_address[0:4]),
2122 map(int, static_nat_ip.split('.')))
2123 self.assertTrue(session.inside_port in
2124 [self.tcp_port_in, self.udp_port_in,
2125 self.icmp_id_in])
2126
Matus Fabianf78a70d2016-12-12 04:30:39 -08002127 def test_hairpinning(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002128 """ NAT44 hairpinning - 1:1 NAPT """
Matus Fabianf78a70d2016-12-12 04:30:39 -08002129
2130 host = self.pg0.remote_hosts[0]
2131 server = self.pg0.remote_hosts[1]
2132 host_in_port = 1234
2133 host_out_port = 0
2134 server_in_port = 5678
2135 server_out_port = 8765
2136
Matus Fabian2ba92e32017-08-21 07:05:03 -07002137 self.nat44_add_address(self.nat_addr)
2138 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2139 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2140 is_inside=0)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002141 # add static mapping for server
Matus Fabian2ba92e32017-08-21 07:05:03 -07002142 self.nat44_add_static_mapping(server.ip4, self.nat_addr,
2143 server_in_port, server_out_port,
2144 proto=IP_PROTOS.tcp)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002145
2146 # send packet from host to server
2147 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002148 IP(src=host.ip4, dst=self.nat_addr) /
Matus Fabianf78a70d2016-12-12 04:30:39 -08002149 TCP(sport=host_in_port, dport=server_out_port))
2150 self.pg0.add_stream(p)
2151 self.pg_enable_capture(self.pg_interfaces)
2152 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002153 capture = self.pg0.get_capture(1)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002154 p = capture[0]
2155 try:
2156 ip = p[IP]
2157 tcp = p[TCP]
Matus Fabian2ba92e32017-08-21 07:05:03 -07002158 self.assertEqual(ip.src, self.nat_addr)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002159 self.assertEqual(ip.dst, server.ip4)
2160 self.assertNotEqual(tcp.sport, host_in_port)
2161 self.assertEqual(tcp.dport, server_in_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02002162 self.assert_packet_checksums_valid(p)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002163 host_out_port = tcp.sport
2164 except:
Klement Sekera9225dee2016-12-12 08:36:58 +01002165 self.logger.error(ppp("Unexpected or invalid packet:", p))
Matus Fabianf78a70d2016-12-12 04:30:39 -08002166 raise
2167
2168 # send reply from server to host
2169 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002170 IP(src=server.ip4, dst=self.nat_addr) /
Matus Fabianf78a70d2016-12-12 04:30:39 -08002171 TCP(sport=server_in_port, dport=host_out_port))
2172 self.pg0.add_stream(p)
2173 self.pg_enable_capture(self.pg_interfaces)
2174 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002175 capture = self.pg0.get_capture(1)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002176 p = capture[0]
2177 try:
2178 ip = p[IP]
2179 tcp = p[TCP]
Matus Fabian2ba92e32017-08-21 07:05:03 -07002180 self.assertEqual(ip.src, self.nat_addr)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002181 self.assertEqual(ip.dst, host.ip4)
2182 self.assertEqual(tcp.sport, server_out_port)
2183 self.assertEqual(tcp.dport, host_in_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02002184 self.assert_packet_checksums_valid(p)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002185 except:
Matus Fabiane82488f2018-01-18 03:38:45 -08002186 self.logger.error(ppp("Unexpected or invalid packet:", p))
Matus Fabianf78a70d2016-12-12 04:30:39 -08002187 raise
2188
Matus Fabian6fa74c62017-06-05 05:55:48 -07002189 def test_hairpinning2(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002190 """ NAT44 hairpinning - 1:1 NAT"""
Matus Fabian6fa74c62017-06-05 05:55:48 -07002191
2192 server1_nat_ip = "10.0.0.10"
2193 server2_nat_ip = "10.0.0.11"
2194 host = self.pg0.remote_hosts[0]
2195 server1 = self.pg0.remote_hosts[1]
2196 server2 = self.pg0.remote_hosts[2]
2197 server_tcp_port = 22
2198 server_udp_port = 20
2199
Matus Fabian2ba92e32017-08-21 07:05:03 -07002200 self.nat44_add_address(self.nat_addr)
2201 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2202 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2203 is_inside=0)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002204
2205 # add static mapping for servers
Matus Fabian2ba92e32017-08-21 07:05:03 -07002206 self.nat44_add_static_mapping(server1.ip4, server1_nat_ip)
2207 self.nat44_add_static_mapping(server2.ip4, server2_nat_ip)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002208
2209 # host to server1
2210 pkts = []
2211 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2212 IP(src=host.ip4, dst=server1_nat_ip) /
2213 TCP(sport=self.tcp_port_in, dport=server_tcp_port))
2214 pkts.append(p)
2215 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2216 IP(src=host.ip4, dst=server1_nat_ip) /
2217 UDP(sport=self.udp_port_in, dport=server_udp_port))
2218 pkts.append(p)
2219 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2220 IP(src=host.ip4, dst=server1_nat_ip) /
2221 ICMP(id=self.icmp_id_in, type='echo-request'))
2222 pkts.append(p)
2223 self.pg0.add_stream(pkts)
2224 self.pg_enable_capture(self.pg_interfaces)
2225 self.pg_start()
2226 capture = self.pg0.get_capture(len(pkts))
2227 for packet in capture:
2228 try:
Matus Fabian2ba92e32017-08-21 07:05:03 -07002229 self.assertEqual(packet[IP].src, self.nat_addr)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002230 self.assertEqual(packet[IP].dst, server1.ip4)
2231 if packet.haslayer(TCP):
2232 self.assertNotEqual(packet[TCP].sport, self.tcp_port_in)
2233 self.assertEqual(packet[TCP].dport, server_tcp_port)
2234 self.tcp_port_out = packet[TCP].sport
Klement Sekerad81ae412018-05-16 10:52:54 +02002235 self.assert_packet_checksums_valid(packet)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002236 elif packet.haslayer(UDP):
2237 self.assertNotEqual(packet[UDP].sport, self.udp_port_in)
2238 self.assertEqual(packet[UDP].dport, server_udp_port)
2239 self.udp_port_out = packet[UDP].sport
2240 else:
2241 self.assertNotEqual(packet[ICMP].id, self.icmp_id_in)
2242 self.icmp_id_out = packet[ICMP].id
2243 except:
2244 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2245 raise
2246
2247 # server1 to host
2248 pkts = []
2249 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002250 IP(src=server1.ip4, dst=self.nat_addr) /
Matus Fabian6fa74c62017-06-05 05:55:48 -07002251 TCP(sport=server_tcp_port, dport=self.tcp_port_out))
2252 pkts.append(p)
2253 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002254 IP(src=server1.ip4, dst=self.nat_addr) /
Matus Fabian6fa74c62017-06-05 05:55:48 -07002255 UDP(sport=server_udp_port, dport=self.udp_port_out))
2256 pkts.append(p)
2257 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002258 IP(src=server1.ip4, dst=self.nat_addr) /
Matus Fabian6fa74c62017-06-05 05:55:48 -07002259 ICMP(id=self.icmp_id_out, type='echo-reply'))
2260 pkts.append(p)
2261 self.pg0.add_stream(pkts)
2262 self.pg_enable_capture(self.pg_interfaces)
2263 self.pg_start()
2264 capture = self.pg0.get_capture(len(pkts))
2265 for packet in capture:
2266 try:
2267 self.assertEqual(packet[IP].src, server1_nat_ip)
2268 self.assertEqual(packet[IP].dst, host.ip4)
2269 if packet.haslayer(TCP):
2270 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
2271 self.assertEqual(packet[TCP].sport, server_tcp_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02002272 self.assert_packet_checksums_valid(packet)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002273 elif packet.haslayer(UDP):
2274 self.assertEqual(packet[UDP].dport, self.udp_port_in)
2275 self.assertEqual(packet[UDP].sport, server_udp_port)
2276 else:
2277 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
2278 except:
2279 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2280 raise
2281
2282 # server2 to server1
2283 pkts = []
2284 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2285 IP(src=server2.ip4, dst=server1_nat_ip) /
2286 TCP(sport=self.tcp_port_in, dport=server_tcp_port))
2287 pkts.append(p)
2288 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2289 IP(src=server2.ip4, dst=server1_nat_ip) /
2290 UDP(sport=self.udp_port_in, dport=server_udp_port))
2291 pkts.append(p)
2292 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2293 IP(src=server2.ip4, dst=server1_nat_ip) /
2294 ICMP(id=self.icmp_id_in, type='echo-request'))
2295 pkts.append(p)
2296 self.pg0.add_stream(pkts)
2297 self.pg_enable_capture(self.pg_interfaces)
2298 self.pg_start()
2299 capture = self.pg0.get_capture(len(pkts))
2300 for packet in capture:
2301 try:
2302 self.assertEqual(packet[IP].src, server2_nat_ip)
2303 self.assertEqual(packet[IP].dst, server1.ip4)
2304 if packet.haslayer(TCP):
2305 self.assertEqual(packet[TCP].sport, self.tcp_port_in)
2306 self.assertEqual(packet[TCP].dport, server_tcp_port)
2307 self.tcp_port_out = packet[TCP].sport
Klement Sekerad81ae412018-05-16 10:52:54 +02002308 self.assert_packet_checksums_valid(packet)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002309 elif packet.haslayer(UDP):
2310 self.assertEqual(packet[UDP].sport, self.udp_port_in)
2311 self.assertEqual(packet[UDP].dport, server_udp_port)
2312 self.udp_port_out = packet[UDP].sport
2313 else:
2314 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
2315 self.icmp_id_out = packet[ICMP].id
2316 except:
2317 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2318 raise
2319
2320 # server1 to server2
2321 pkts = []
2322 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2323 IP(src=server1.ip4, dst=server2_nat_ip) /
2324 TCP(sport=server_tcp_port, dport=self.tcp_port_out))
2325 pkts.append(p)
2326 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2327 IP(src=server1.ip4, dst=server2_nat_ip) /
2328 UDP(sport=server_udp_port, dport=self.udp_port_out))
2329 pkts.append(p)
2330 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2331 IP(src=server1.ip4, dst=server2_nat_ip) /
2332 ICMP(id=self.icmp_id_out, type='echo-reply'))
2333 pkts.append(p)
2334 self.pg0.add_stream(pkts)
2335 self.pg_enable_capture(self.pg_interfaces)
2336 self.pg_start()
2337 capture = self.pg0.get_capture(len(pkts))
2338 for packet in capture:
2339 try:
2340 self.assertEqual(packet[IP].src, server1_nat_ip)
2341 self.assertEqual(packet[IP].dst, server2.ip4)
2342 if packet.haslayer(TCP):
2343 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
2344 self.assertEqual(packet[TCP].sport, server_tcp_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02002345 self.assert_packet_checksums_valid(packet)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002346 elif packet.haslayer(UDP):
2347 self.assertEqual(packet[UDP].dport, self.udp_port_in)
2348 self.assertEqual(packet[UDP].sport, server_udp_port)
2349 else:
2350 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
2351 except:
2352 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2353 raise
2354
Matus Fabian9902fcd2016-12-21 23:58:46 -08002355 def test_max_translations_per_user(self):
2356 """ MAX translations per user - recycle the least recently used """
2357
Matus Fabian2ba92e32017-08-21 07:05:03 -07002358 self.nat44_add_address(self.nat_addr)
2359 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2360 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2361 is_inside=0)
Matus Fabian9902fcd2016-12-21 23:58:46 -08002362
2363 # get maximum number of translations per user
Matus Fabian2ba92e32017-08-21 07:05:03 -07002364 nat44_config = self.vapi.nat_show_config()
Matus Fabian9902fcd2016-12-21 23:58:46 -08002365
2366 # send more than maximum number of translations per user packets
Matus Fabian2ba92e32017-08-21 07:05:03 -07002367 pkts_num = nat44_config.max_translations_per_user + 5
Matus Fabian9902fcd2016-12-21 23:58:46 -08002368 pkts = []
2369 for port in range(0, pkts_num):
2370 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2371 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2372 TCP(sport=1025 + port))
2373 pkts.append(p)
2374 self.pg0.add_stream(pkts)
2375 self.pg_enable_capture(self.pg_interfaces)
2376 self.pg_start()
2377
2378 # verify number of translated packet
Klement Sekeradab231a2016-12-21 08:50:14 +01002379 self.pg1.get_capture(pkts_num)
Matus Fabian9902fcd2016-12-21 23:58:46 -08002380
Matus Fabian132dc492018-05-09 04:51:03 -07002381 users = self.vapi.nat44_user_dump()
2382 for user in users:
2383 if user.ip_address == self.pg0.remote_ip4n:
2384 self.assertEqual(user.nsessions,
2385 nat44_config.max_translations_per_user)
2386 self.assertEqual(user.nstaticsessions, 0)
2387
2388 tcp_port = 22
2389 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
2390 tcp_port, tcp_port,
2391 proto=IP_PROTOS.tcp)
2392 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2393 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2394 TCP(sport=tcp_port))
2395 self.pg0.add_stream(p)
2396 self.pg_enable_capture(self.pg_interfaces)
2397 self.pg_start()
2398 self.pg1.get_capture(1)
2399 users = self.vapi.nat44_user_dump()
2400 for user in users:
2401 if user.ip_address == self.pg0.remote_ip4n:
2402 self.assertEqual(user.nsessions,
2403 nat44_config.max_translations_per_user - 1)
2404 self.assertEqual(user.nstaticsessions, 1)
2405
Matus Fabian8bf68e82017-01-12 04:24:35 -08002406 def test_interface_addr(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002407 """ Acquire NAT44 addresses from interface """
2408 self.vapi.nat44_add_interface_addr(self.pg7.sw_if_index)
Matus Fabian8bf68e82017-01-12 04:24:35 -08002409
2410 # no address in NAT pool
Matus Fabian2ba92e32017-08-21 07:05:03 -07002411 adresses = self.vapi.nat44_address_dump()
Matus Fabian8bf68e82017-01-12 04:24:35 -08002412 self.assertEqual(0, len(adresses))
2413
2414 # configure interface address and check NAT address pool
2415 self.pg7.config_ip4()
Matus Fabian2ba92e32017-08-21 07:05:03 -07002416 adresses = self.vapi.nat44_address_dump()
Matus Fabian8bf68e82017-01-12 04:24:35 -08002417 self.assertEqual(1, len(adresses))
Matus Fabian36532bd2017-01-23 23:42:28 -08002418 self.assertEqual(adresses[0].ip_address[0:4], self.pg7.local_ip4n)
Matus Fabian8bf68e82017-01-12 04:24:35 -08002419
2420 # remove interface address and check NAT address pool
2421 self.pg7.unconfig_ip4()
Matus Fabian2ba92e32017-08-21 07:05:03 -07002422 adresses = self.vapi.nat44_address_dump()
Matus Fabian8bf68e82017-01-12 04:24:35 -08002423 self.assertEqual(0, len(adresses))
2424
Matus Fabian36532bd2017-01-23 23:42:28 -08002425 def test_interface_addr_static_mapping(self):
2426 """ Static mapping with addresses from interface """
Matus Fabian5f224992018-01-25 21:59:16 -08002427 tag = "testTAG"
2428
Matus Fabian2ba92e32017-08-21 07:05:03 -07002429 self.vapi.nat44_add_interface_addr(self.pg7.sw_if_index)
2430 self.nat44_add_static_mapping(
2431 '1.2.3.4',
Matus Fabian5f224992018-01-25 21:59:16 -08002432 external_sw_if_index=self.pg7.sw_if_index,
2433 tag=tag)
Matus Fabian36532bd2017-01-23 23:42:28 -08002434
Matus Fabiane22e5462017-02-14 23:33:43 -08002435 # static mappings with external interface
Matus Fabian2ba92e32017-08-21 07:05:03 -07002436 static_mappings = self.vapi.nat44_static_mapping_dump()
Matus Fabiane22e5462017-02-14 23:33:43 -08002437 self.assertEqual(1, len(static_mappings))
2438 self.assertEqual(self.pg7.sw_if_index,
2439 static_mappings[0].external_sw_if_index)
Matus Fabian5f224992018-01-25 21:59:16 -08002440 self.assertEqual((static_mappings[0].tag).split('\0', 1)[0], tag)
Matus Fabian36532bd2017-01-23 23:42:28 -08002441
2442 # configure interface address and check static mappings
2443 self.pg7.config_ip4()
Matus Fabian2ba92e32017-08-21 07:05:03 -07002444 static_mappings = self.vapi.nat44_static_mapping_dump()
Matus Fabianea2600a2018-03-28 04:06:26 -07002445 self.assertEqual(2, len(static_mappings))
2446 resolved = False
2447 for sm in static_mappings:
2448 if sm.external_sw_if_index == 0xFFFFFFFF:
2449 self.assertEqual(sm.external_ip_address[0:4],
2450 self.pg7.local_ip4n)
2451 self.assertEqual((sm.tag).split('\0', 1)[0], tag)
2452 resolved = True
2453 self.assertTrue(resolved)
Matus Fabian36532bd2017-01-23 23:42:28 -08002454
2455 # remove interface address and check static mappings
2456 self.pg7.unconfig_ip4()
Matus Fabian2ba92e32017-08-21 07:05:03 -07002457 static_mappings = self.vapi.nat44_static_mapping_dump()
Matus Fabianea2600a2018-03-28 04:06:26 -07002458 self.assertEqual(1, len(static_mappings))
2459 self.assertEqual(self.pg7.sw_if_index,
2460 static_mappings[0].external_sw_if_index)
2461 self.assertEqual((static_mappings[0].tag).split('\0', 1)[0], tag)
2462
2463 # configure interface address again and check static mappings
2464 self.pg7.config_ip4()
2465 static_mappings = self.vapi.nat44_static_mapping_dump()
2466 self.assertEqual(2, len(static_mappings))
2467 resolved = False
2468 for sm in static_mappings:
2469 if sm.external_sw_if_index == 0xFFFFFFFF:
2470 self.assertEqual(sm.external_ip_address[0:4],
2471 self.pg7.local_ip4n)
2472 self.assertEqual((sm.tag).split('\0', 1)[0], tag)
2473 resolved = True
2474 self.assertTrue(resolved)
2475
2476 # remove static mapping
2477 self.nat44_add_static_mapping(
2478 '1.2.3.4',
2479 external_sw_if_index=self.pg7.sw_if_index,
2480 tag=tag,
2481 is_add=0)
2482 static_mappings = self.vapi.nat44_static_mapping_dump()
Matus Fabian36532bd2017-01-23 23:42:28 -08002483 self.assertEqual(0, len(static_mappings))
2484
Matus Fabianab7a8052017-11-28 04:29:41 -08002485 def test_interface_addr_identity_nat(self):
2486 """ Identity NAT with addresses from interface """
2487
2488 port = 53053
2489 self.vapi.nat44_add_interface_addr(self.pg7.sw_if_index)
2490 self.vapi.nat44_add_del_identity_mapping(
2491 sw_if_index=self.pg7.sw_if_index,
2492 port=port,
2493 protocol=IP_PROTOS.tcp,
2494 addr_only=0)
2495
2496 # identity mappings with external interface
2497 identity_mappings = self.vapi.nat44_identity_mapping_dump()
2498 self.assertEqual(1, len(identity_mappings))
2499 self.assertEqual(self.pg7.sw_if_index,
2500 identity_mappings[0].sw_if_index)
2501
2502 # configure interface address and check identity mappings
2503 self.pg7.config_ip4()
2504 identity_mappings = self.vapi.nat44_identity_mapping_dump()
Matus Fabianea2600a2018-03-28 04:06:26 -07002505 resolved = False
2506 self.assertEqual(2, len(identity_mappings))
2507 for sm in identity_mappings:
2508 if sm.sw_if_index == 0xFFFFFFFF:
2509 self.assertEqual(identity_mappings[0].ip_address,
2510 self.pg7.local_ip4n)
2511 self.assertEqual(port, identity_mappings[0].port)
2512 self.assertEqual(IP_PROTOS.tcp, identity_mappings[0].protocol)
2513 resolved = True
2514 self.assertTrue(resolved)
Matus Fabianab7a8052017-11-28 04:29:41 -08002515
2516 # remove interface address and check identity mappings
2517 self.pg7.unconfig_ip4()
2518 identity_mappings = self.vapi.nat44_identity_mapping_dump()
Matus Fabianea2600a2018-03-28 04:06:26 -07002519 self.assertEqual(1, len(identity_mappings))
2520 self.assertEqual(self.pg7.sw_if_index,
2521 identity_mappings[0].sw_if_index)
Matus Fabianab7a8052017-11-28 04:29:41 -08002522
Matus Fabianeea28d72017-01-13 04:15:54 -08002523 def test_ipfix_nat44_sess(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002524 """ IPFIX logging NAT44 session created/delted """
Matus Fabian6631e9c2017-05-24 01:52:20 -07002525 self.ipfix_domain_id = 10
2526 self.ipfix_src_port = 20202
2527 colector_port = 30303
2528 bind_layers(UDP, IPFIX, dport=30303)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002529 self.nat44_add_address(self.nat_addr)
2530 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2531 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2532 is_inside=0)
Matus Fabianeea28d72017-01-13 04:15:54 -08002533 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
2534 src_address=self.pg3.local_ip4n,
2535 path_mtu=512,
Matus Fabian6631e9c2017-05-24 01:52:20 -07002536 template_interval=10,
2537 collector_port=colector_port)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002538 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
2539 src_port=self.ipfix_src_port)
Matus Fabianeea28d72017-01-13 04:15:54 -08002540
2541 pkts = self.create_stream_in(self.pg0, self.pg1)
2542 self.pg0.add_stream(pkts)
2543 self.pg_enable_capture(self.pg_interfaces)
2544 self.pg_start()
2545 capture = self.pg1.get_capture(len(pkts))
2546 self.verify_capture_out(capture)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002547 self.nat44_add_address(self.nat_addr, is_add=0)
Matus Fabianeea28d72017-01-13 04:15:54 -08002548 self.vapi.cli("ipfix flush") # FIXME this should be an API call
Matus Fabiana431ad12018-01-04 04:03:14 -08002549 capture = self.pg3.get_capture(9)
Matus Fabianeea28d72017-01-13 04:15:54 -08002550 ipfix = IPFIXDecoder()
2551 # first load template
2552 for p in capture:
2553 self.assertTrue(p.haslayer(IPFIX))
Matus Fabian6631e9c2017-05-24 01:52:20 -07002554 self.assertEqual(p[IP].src, self.pg3.local_ip4)
2555 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2556 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2557 self.assertEqual(p[UDP].dport, colector_port)
2558 self.assertEqual(p[IPFIX].observationDomainID,
2559 self.ipfix_domain_id)
Matus Fabianeea28d72017-01-13 04:15:54 -08002560 if p.haslayer(Template):
2561 ipfix.add_template(p.getlayer(Template))
2562 # verify events in data set
2563 for p in capture:
2564 if p.haslayer(Data):
2565 data = ipfix.decode_data_set(p.getlayer(Set))
2566 self.verify_ipfix_nat44_ses(data)
2567
2568 def test_ipfix_addr_exhausted(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002569 """ IPFIX logging NAT addresses exhausted """
2570 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2571 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2572 is_inside=0)
Matus Fabianeea28d72017-01-13 04:15:54 -08002573 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
2574 src_address=self.pg3.local_ip4n,
2575 path_mtu=512,
2576 template_interval=10)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002577 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
2578 src_port=self.ipfix_src_port)
Matus Fabianeea28d72017-01-13 04:15:54 -08002579
2580 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
2581 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2582 TCP(sport=3025))
2583 self.pg0.add_stream(p)
2584 self.pg_enable_capture(self.pg_interfaces)
2585 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07002586 self.pg1.assert_nothing_captured()
2587 sleep(1)
Matus Fabianeea28d72017-01-13 04:15:54 -08002588 self.vapi.cli("ipfix flush") # FIXME this should be an API call
Matus Fabiana431ad12018-01-04 04:03:14 -08002589 capture = self.pg3.get_capture(9)
Matus Fabianeea28d72017-01-13 04:15:54 -08002590 ipfix = IPFIXDecoder()
2591 # first load template
2592 for p in capture:
2593 self.assertTrue(p.haslayer(IPFIX))
Matus Fabian6631e9c2017-05-24 01:52:20 -07002594 self.assertEqual(p[IP].src, self.pg3.local_ip4)
2595 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2596 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2597 self.assertEqual(p[UDP].dport, 4739)
2598 self.assertEqual(p[IPFIX].observationDomainID,
2599 self.ipfix_domain_id)
Matus Fabianeea28d72017-01-13 04:15:54 -08002600 if p.haslayer(Template):
2601 ipfix.add_template(p.getlayer(Template))
2602 # verify events in data set
2603 for p in capture:
2604 if p.haslayer(Data):
2605 data = ipfix.decode_data_set(p.getlayer(Set))
2606 self.verify_ipfix_addr_exhausted(data)
2607
Matus Fabiana431ad12018-01-04 04:03:14 -08002608 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
2609 def test_ipfix_max_sessions(self):
2610 """ IPFIX logging maximum session entries exceeded """
2611 self.nat44_add_address(self.nat_addr)
2612 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2613 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2614 is_inside=0)
2615
2616 nat44_config = self.vapi.nat_show_config()
2617 max_sessions = 10 * nat44_config.translation_buckets
2618
2619 pkts = []
2620 for i in range(0, max_sessions):
2621 src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
2622 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2623 IP(src=src, dst=self.pg1.remote_ip4) /
2624 TCP(sport=1025))
2625 pkts.append(p)
2626 self.pg0.add_stream(pkts)
2627 self.pg_enable_capture(self.pg_interfaces)
2628 self.pg_start()
2629
2630 self.pg1.get_capture(max_sessions)
2631 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
2632 src_address=self.pg3.local_ip4n,
2633 path_mtu=512,
2634 template_interval=10)
2635 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
2636 src_port=self.ipfix_src_port)
2637
2638 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2639 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2640 TCP(sport=1025))
2641 self.pg0.add_stream(p)
2642 self.pg_enable_capture(self.pg_interfaces)
2643 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07002644 self.pg1.assert_nothing_captured()
2645 sleep(1)
Matus Fabiana431ad12018-01-04 04:03:14 -08002646 self.vapi.cli("ipfix flush") # FIXME this should be an API call
2647 capture = self.pg3.get_capture(9)
2648 ipfix = IPFIXDecoder()
2649 # first load template
2650 for p in capture:
2651 self.assertTrue(p.haslayer(IPFIX))
2652 self.assertEqual(p[IP].src, self.pg3.local_ip4)
2653 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2654 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2655 self.assertEqual(p[UDP].dport, 4739)
2656 self.assertEqual(p[IPFIX].observationDomainID,
2657 self.ipfix_domain_id)
2658 if p.haslayer(Template):
2659 ipfix.add_template(p.getlayer(Template))
2660 # verify events in data set
2661 for p in capture:
2662 if p.haslayer(Data):
2663 data = ipfix.decode_data_set(p.getlayer(Set))
2664 self.verify_ipfix_max_sessions(data, max_sessions)
2665
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002666 def test_pool_addr_fib(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002667 """ NAT44 add pool addresses to FIB """
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002668 static_addr = '10.0.0.10'
Matus Fabian2ba92e32017-08-21 07:05:03 -07002669 self.nat44_add_address(self.nat_addr)
2670 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2671 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2672 is_inside=0)
2673 self.nat44_add_static_mapping(self.pg0.remote_ip4, static_addr)
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002674
Matus Fabian2ba92e32017-08-21 07:05:03 -07002675 # NAT44 address
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002676 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002677 ARP(op=ARP.who_has, pdst=self.nat_addr,
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002678 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2679 self.pg1.add_stream(p)
2680 self.pg_enable_capture(self.pg_interfaces)
2681 self.pg_start()
2682 capture = self.pg1.get_capture(1)
2683 self.assertTrue(capture[0].haslayer(ARP))
2684 self.assertTrue(capture[0][ARP].op, ARP.is_at)
2685
2686 # 1:1 NAT address
2687 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2688 ARP(op=ARP.who_has, pdst=static_addr,
2689 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2690 self.pg1.add_stream(p)
2691 self.pg_enable_capture(self.pg_interfaces)
2692 self.pg_start()
2693 capture = self.pg1.get_capture(1)
2694 self.assertTrue(capture[0].haslayer(ARP))
2695 self.assertTrue(capture[0][ARP].op, ARP.is_at)
2696
Matus Fabian2ba92e32017-08-21 07:05:03 -07002697 # send ARP to non-NAT44 interface
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002698 p = (Ether(src=self.pg2.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002699 ARP(op=ARP.who_has, pdst=self.nat_addr,
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002700 psrc=self.pg2.remote_ip4, hwsrc=self.pg2.remote_mac))
2701 self.pg2.add_stream(p)
2702 self.pg_enable_capture(self.pg_interfaces)
2703 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07002704 self.pg1.assert_nothing_captured()
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002705
2706 # remove addresses and verify
Matus Fabian2ba92e32017-08-21 07:05:03 -07002707 self.nat44_add_address(self.nat_addr, is_add=0)
2708 self.nat44_add_static_mapping(self.pg0.remote_ip4, static_addr,
2709 is_add=0)
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002710
2711 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002712 ARP(op=ARP.who_has, pdst=self.nat_addr,
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002713 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2714 self.pg1.add_stream(p)
2715 self.pg_enable_capture(self.pg_interfaces)
2716 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07002717 self.pg1.assert_nothing_captured()
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002718
2719 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2720 ARP(op=ARP.who_has, pdst=static_addr,
2721 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2722 self.pg1.add_stream(p)
2723 self.pg_enable_capture(self.pg_interfaces)
2724 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07002725 self.pg1.assert_nothing_captured()
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002726
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002727 def test_vrf_mode(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002728 """ NAT44 tenant VRF aware address pool mode """
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002729
2730 vrf_id1 = 1
2731 vrf_id2 = 2
2732 nat_ip1 = "10.0.0.10"
2733 nat_ip2 = "10.0.0.11"
2734
2735 self.pg0.unconfig_ip4()
2736 self.pg1.unconfig_ip4()
Neale Ranns15002542017-09-10 04:39:11 -07002737 self.vapi.ip_table_add_del(vrf_id1, is_add=1)
2738 self.vapi.ip_table_add_del(vrf_id2, is_add=1)
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002739 self.pg0.set_table_ip4(vrf_id1)
2740 self.pg1.set_table_ip4(vrf_id2)
2741 self.pg0.config_ip4()
2742 self.pg1.config_ip4()
2743
Matus Fabian2ba92e32017-08-21 07:05:03 -07002744 self.nat44_add_address(nat_ip1, vrf_id=vrf_id1)
2745 self.nat44_add_address(nat_ip2, vrf_id=vrf_id2)
2746 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2747 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
2748 self.vapi.nat44_interface_add_del_feature(self.pg2.sw_if_index,
2749 is_inside=0)
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002750
2751 # first VRF
2752 pkts = self.create_stream_in(self.pg0, self.pg2)
2753 self.pg0.add_stream(pkts)
2754 self.pg_enable_capture(self.pg_interfaces)
2755 self.pg_start()
2756 capture = self.pg2.get_capture(len(pkts))
2757 self.verify_capture_out(capture, nat_ip1)
2758
2759 # second VRF
2760 pkts = self.create_stream_in(self.pg1, self.pg2)
2761 self.pg1.add_stream(pkts)
2762 self.pg_enable_capture(self.pg_interfaces)
2763 self.pg_start()
2764 capture = self.pg2.get_capture(len(pkts))
2765 self.verify_capture_out(capture, nat_ip2)
2766
Neale Ranns15002542017-09-10 04:39:11 -07002767 self.pg0.unconfig_ip4()
2768 self.pg1.unconfig_ip4()
2769 self.pg0.set_table_ip4(0)
2770 self.pg1.set_table_ip4(0)
2771 self.vapi.ip_table_add_del(vrf_id1, is_add=0)
2772 self.vapi.ip_table_add_del(vrf_id2, is_add=0)
2773
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002774 def test_vrf_feature_independent(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002775 """ NAT44 tenant VRF independent address pool mode """
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002776
2777 nat_ip1 = "10.0.0.10"
2778 nat_ip2 = "10.0.0.11"
2779
Matus Fabian2ba92e32017-08-21 07:05:03 -07002780 self.nat44_add_address(nat_ip1)
Matus Fabian51e759f2017-12-07 23:22:51 -08002781 self.nat44_add_address(nat_ip2, vrf_id=99)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002782 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2783 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
2784 self.vapi.nat44_interface_add_del_feature(self.pg2.sw_if_index,
2785 is_inside=0)
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002786
2787 # first VRF
2788 pkts = self.create_stream_in(self.pg0, self.pg2)
2789 self.pg0.add_stream(pkts)
2790 self.pg_enable_capture(self.pg_interfaces)
2791 self.pg_start()
2792 capture = self.pg2.get_capture(len(pkts))
2793 self.verify_capture_out(capture, nat_ip1)
2794
2795 # second VRF
2796 pkts = self.create_stream_in(self.pg1, self.pg2)
2797 self.pg1.add_stream(pkts)
2798 self.pg_enable_capture(self.pg_interfaces)
2799 self.pg_start()
2800 capture = self.pg2.get_capture(len(pkts))
2801 self.verify_capture_out(capture, nat_ip1)
2802
Martin Gálik406eb1d2017-05-04 04:35:04 -07002803 def test_dynamic_ipless_interfaces(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002804 """ NAT44 interfaces without configured IP address """
Martin Gálik406eb1d2017-05-04 04:35:04 -07002805
2806 self.vapi.ip_neighbor_add_del(self.pg7.sw_if_index,
Ole Troan895b6e82017-10-20 13:28:20 +02002807 mactobinary(self.pg7.remote_mac),
Martin Gálik406eb1d2017-05-04 04:35:04 -07002808 self.pg7.remote_ip4n,
2809 is_static=1)
2810 self.vapi.ip_neighbor_add_del(self.pg8.sw_if_index,
Ole Troan895b6e82017-10-20 13:28:20 +02002811 mactobinary(self.pg8.remote_mac),
Martin Gálik406eb1d2017-05-04 04:35:04 -07002812 self.pg8.remote_ip4n,
2813 is_static=1)
2814
2815 self.vapi.ip_add_del_route(dst_address=self.pg7.remote_ip4n,
2816 dst_address_length=32,
2817 next_hop_address=self.pg7.remote_ip4n,
2818 next_hop_sw_if_index=self.pg7.sw_if_index)
2819 self.vapi.ip_add_del_route(dst_address=self.pg8.remote_ip4n,
2820 dst_address_length=32,
2821 next_hop_address=self.pg8.remote_ip4n,
2822 next_hop_sw_if_index=self.pg8.sw_if_index)
2823
Matus Fabian2ba92e32017-08-21 07:05:03 -07002824 self.nat44_add_address(self.nat_addr)
2825 self.vapi.nat44_interface_add_del_feature(self.pg7.sw_if_index)
2826 self.vapi.nat44_interface_add_del_feature(self.pg8.sw_if_index,
2827 is_inside=0)
Martin Gálik406eb1d2017-05-04 04:35:04 -07002828
2829 # in2out
2830 pkts = self.create_stream_in(self.pg7, self.pg8)
2831 self.pg7.add_stream(pkts)
2832 self.pg_enable_capture(self.pg_interfaces)
2833 self.pg_start()
2834 capture = self.pg8.get_capture(len(pkts))
2835 self.verify_capture_out(capture)
2836
2837 # out2in
Matus Fabian2ba92e32017-08-21 07:05:03 -07002838 pkts = self.create_stream_out(self.pg8, self.nat_addr)
Martin Gálik406eb1d2017-05-04 04:35:04 -07002839 self.pg8.add_stream(pkts)
2840 self.pg_enable_capture(self.pg_interfaces)
2841 self.pg_start()
2842 capture = self.pg7.get_capture(len(pkts))
2843 self.verify_capture_in(capture, self.pg7)
2844
2845 def test_static_ipless_interfaces(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002846 """ NAT44 interfaces without configured IP address - 1:1 NAT """
Martin Gálik406eb1d2017-05-04 04:35:04 -07002847
2848 self.vapi.ip_neighbor_add_del(self.pg7.sw_if_index,
Ole Troan895b6e82017-10-20 13:28:20 +02002849 mactobinary(self.pg7.remote_mac),
Martin Gálik406eb1d2017-05-04 04:35:04 -07002850 self.pg7.remote_ip4n,
2851 is_static=1)
2852 self.vapi.ip_neighbor_add_del(self.pg8.sw_if_index,
Ole Troan895b6e82017-10-20 13:28:20 +02002853 mactobinary(self.pg8.remote_mac),
Martin Gálik406eb1d2017-05-04 04:35:04 -07002854 self.pg8.remote_ip4n,
2855 is_static=1)
2856
2857 self.vapi.ip_add_del_route(dst_address=self.pg7.remote_ip4n,
2858 dst_address_length=32,
2859 next_hop_address=self.pg7.remote_ip4n,
2860 next_hop_sw_if_index=self.pg7.sw_if_index)
2861 self.vapi.ip_add_del_route(dst_address=self.pg8.remote_ip4n,
2862 dst_address_length=32,
2863 next_hop_address=self.pg8.remote_ip4n,
2864 next_hop_sw_if_index=self.pg8.sw_if_index)
2865
Matus Fabian2ba92e32017-08-21 07:05:03 -07002866 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr)
2867 self.vapi.nat44_interface_add_del_feature(self.pg7.sw_if_index)
2868 self.vapi.nat44_interface_add_del_feature(self.pg8.sw_if_index,
2869 is_inside=0)
Martin Gálik406eb1d2017-05-04 04:35:04 -07002870
2871 # out2in
2872 pkts = self.create_stream_out(self.pg8)
2873 self.pg8.add_stream(pkts)
2874 self.pg_enable_capture(self.pg_interfaces)
2875 self.pg_start()
2876 capture = self.pg7.get_capture(len(pkts))
2877 self.verify_capture_in(capture, self.pg7)
2878
2879 # in2out
2880 pkts = self.create_stream_in(self.pg7, self.pg8)
2881 self.pg7.add_stream(pkts)
2882 self.pg_enable_capture(self.pg_interfaces)
2883 self.pg_start()
2884 capture = self.pg8.get_capture(len(pkts))
Matus Fabian2ba92e32017-08-21 07:05:03 -07002885 self.verify_capture_out(capture, self.nat_addr, True)
Martin Gálik406eb1d2017-05-04 04:35:04 -07002886
2887 def test_static_with_port_ipless_interfaces(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002888 """ NAT44 interfaces without configured IP address - 1:1 NAPT """
Martin Gálik406eb1d2017-05-04 04:35:04 -07002889
2890 self.tcp_port_out = 30606
2891 self.udp_port_out = 30607
2892 self.icmp_id_out = 30608
2893
2894 self.vapi.ip_neighbor_add_del(self.pg7.sw_if_index,
Ole Troan895b6e82017-10-20 13:28:20 +02002895 mactobinary(self.pg7.remote_mac),
Martin Gálik406eb1d2017-05-04 04:35:04 -07002896 self.pg7.remote_ip4n,
2897 is_static=1)
2898 self.vapi.ip_neighbor_add_del(self.pg8.sw_if_index,
Ole Troan895b6e82017-10-20 13:28:20 +02002899 mactobinary(self.pg8.remote_mac),
Martin Gálik406eb1d2017-05-04 04:35:04 -07002900 self.pg8.remote_ip4n,
2901 is_static=1)
2902
2903 self.vapi.ip_add_del_route(dst_address=self.pg7.remote_ip4n,
2904 dst_address_length=32,
2905 next_hop_address=self.pg7.remote_ip4n,
2906 next_hop_sw_if_index=self.pg7.sw_if_index)
2907 self.vapi.ip_add_del_route(dst_address=self.pg8.remote_ip4n,
2908 dst_address_length=32,
2909 next_hop_address=self.pg8.remote_ip4n,
2910 next_hop_sw_if_index=self.pg8.sw_if_index)
2911
Matus Fabian2ba92e32017-08-21 07:05:03 -07002912 self.nat44_add_address(self.nat_addr)
2913 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
2914 self.tcp_port_in, self.tcp_port_out,
2915 proto=IP_PROTOS.tcp)
2916 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
2917 self.udp_port_in, self.udp_port_out,
2918 proto=IP_PROTOS.udp)
2919 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
2920 self.icmp_id_in, self.icmp_id_out,
2921 proto=IP_PROTOS.icmp)
2922 self.vapi.nat44_interface_add_del_feature(self.pg7.sw_if_index)
2923 self.vapi.nat44_interface_add_del_feature(self.pg8.sw_if_index,
2924 is_inside=0)
Martin Gálik406eb1d2017-05-04 04:35:04 -07002925
2926 # out2in
2927 pkts = self.create_stream_out(self.pg8)
2928 self.pg8.add_stream(pkts)
2929 self.pg_enable_capture(self.pg_interfaces)
2930 self.pg_start()
2931 capture = self.pg7.get_capture(len(pkts))
2932 self.verify_capture_in(capture, self.pg7)
2933
2934 # in2out
2935 pkts = self.create_stream_in(self.pg7, self.pg8)
2936 self.pg7.add_stream(pkts)
2937 self.pg_enable_capture(self.pg_interfaces)
2938 self.pg_start()
2939 capture = self.pg8.get_capture(len(pkts))
2940 self.verify_capture_out(capture)
2941
Matus Fabian328dbc82017-06-19 04:28:04 -07002942 def test_static_unknown_proto(self):
2943 """ 1:1 NAT translate packet with unknown protocol """
2944 nat_ip = "10.0.0.10"
Matus Fabian2ba92e32017-08-21 07:05:03 -07002945 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
2946 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2947 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2948 is_inside=0)
Matus Fabian328dbc82017-06-19 04:28:04 -07002949
2950 # in2out
2951 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2952 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2953 GRE() /
Matus Fabian1e8db5f2017-06-20 01:45:49 -07002954 IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4) /
Matus Fabian328dbc82017-06-19 04:28:04 -07002955 TCP(sport=1234, dport=1234))
2956 self.pg0.add_stream(p)
2957 self.pg_enable_capture(self.pg_interfaces)
2958 self.pg_start()
2959 p = self.pg1.get_capture(1)
2960 packet = p[0]
2961 try:
2962 self.assertEqual(packet[IP].src, nat_ip)
2963 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
2964 self.assertTrue(packet.haslayer(GRE))
Klement Sekerad81ae412018-05-16 10:52:54 +02002965 self.assert_packet_checksums_valid(packet)
Matus Fabian328dbc82017-06-19 04:28:04 -07002966 except:
2967 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2968 raise
2969
2970 # out2in
2971 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
2972 IP(src=self.pg1.remote_ip4, dst=nat_ip) /
2973 GRE() /
Matus Fabian1e8db5f2017-06-20 01:45:49 -07002974 IP(src=self.pg3.remote_ip4, dst=self.pg2.remote_ip4) /
Matus Fabian328dbc82017-06-19 04:28:04 -07002975 TCP(sport=1234, dport=1234))
2976 self.pg1.add_stream(p)
2977 self.pg_enable_capture(self.pg_interfaces)
2978 self.pg_start()
2979 p = self.pg0.get_capture(1)
2980 packet = p[0]
2981 try:
2982 self.assertEqual(packet[IP].src, self.pg1.remote_ip4)
2983 self.assertEqual(packet[IP].dst, self.pg0.remote_ip4)
2984 self.assertTrue(packet.haslayer(GRE))
Klement Sekerad81ae412018-05-16 10:52:54 +02002985 self.assert_packet_checksums_valid(packet)
Matus Fabian328dbc82017-06-19 04:28:04 -07002986 except:
2987 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2988 raise
2989
Matus Fabian7968e6c2017-07-06 05:37:49 -07002990 def test_hairpinning_static_unknown_proto(self):
Matus Fabian1e8db5f2017-06-20 01:45:49 -07002991 """ 1:1 NAT translate packet with unknown protocol - hairpinning """
2992
2993 host = self.pg0.remote_hosts[0]
2994 server = self.pg0.remote_hosts[1]
2995
2996 host_nat_ip = "10.0.0.10"
2997 server_nat_ip = "10.0.0.11"
2998
Matus Fabian2ba92e32017-08-21 07:05:03 -07002999 self.nat44_add_static_mapping(host.ip4, host_nat_ip)
3000 self.nat44_add_static_mapping(server.ip4, server_nat_ip)
3001 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3002 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3003 is_inside=0)
Matus Fabian1e8db5f2017-06-20 01:45:49 -07003004
3005 # host to server
3006 p = (Ether(dst=self.pg0.local_mac, src=host.mac) /
3007 IP(src=host.ip4, dst=server_nat_ip) /
3008 GRE() /
3009 IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4) /
3010 TCP(sport=1234, dport=1234))
3011 self.pg0.add_stream(p)
3012 self.pg_enable_capture(self.pg_interfaces)
3013 self.pg_start()
3014 p = self.pg0.get_capture(1)
3015 packet = p[0]
3016 try:
3017 self.assertEqual(packet[IP].src, host_nat_ip)
3018 self.assertEqual(packet[IP].dst, server.ip4)
3019 self.assertTrue(packet.haslayer(GRE))
Klement Sekerad81ae412018-05-16 10:52:54 +02003020 self.assert_packet_checksums_valid(packet)
Matus Fabian1e8db5f2017-06-20 01:45:49 -07003021 except:
3022 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3023 raise
3024
3025 # server to host
3026 p = (Ether(dst=self.pg0.local_mac, src=server.mac) /
3027 IP(src=server.ip4, dst=host_nat_ip) /
3028 GRE() /
3029 IP(src=self.pg3.remote_ip4, dst=self.pg2.remote_ip4) /
3030 TCP(sport=1234, dport=1234))
3031 self.pg0.add_stream(p)
3032 self.pg_enable_capture(self.pg_interfaces)
3033 self.pg_start()
3034 p = self.pg0.get_capture(1)
3035 packet = p[0]
3036 try:
3037 self.assertEqual(packet[IP].src, server_nat_ip)
3038 self.assertEqual(packet[IP].dst, host.ip4)
3039 self.assertTrue(packet.haslayer(GRE))
Klement Sekerad81ae412018-05-16 10:52:54 +02003040 self.assert_packet_checksums_valid(packet)
Matus Fabian1e8db5f2017-06-20 01:45:49 -07003041 except:
3042 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3043 raise
3044
Matus Fabian7968e6c2017-07-06 05:37:49 -07003045 def test_unknown_proto(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07003046 """ NAT44 translate packet with unknown protocol """
3047 self.nat44_add_address(self.nat_addr)
3048 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3049 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3050 is_inside=0)
Matus Fabian7968e6c2017-07-06 05:37:49 -07003051
3052 # in2out
3053 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3054 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3055 TCP(sport=self.tcp_port_in, dport=20))
3056 self.pg0.add_stream(p)
3057 self.pg_enable_capture(self.pg_interfaces)
3058 self.pg_start()
3059 p = self.pg1.get_capture(1)
3060
3061 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3062 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3063 GRE() /
3064 IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4) /
3065 TCP(sport=1234, dport=1234))
3066 self.pg0.add_stream(p)
3067 self.pg_enable_capture(self.pg_interfaces)
3068 self.pg_start()
3069 p = self.pg1.get_capture(1)
3070 packet = p[0]
3071 try:
Matus Fabian2ba92e32017-08-21 07:05:03 -07003072 self.assertEqual(packet[IP].src, self.nat_addr)
Matus Fabian7968e6c2017-07-06 05:37:49 -07003073 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
3074 self.assertTrue(packet.haslayer(GRE))
Klement Sekerad81ae412018-05-16 10:52:54 +02003075 self.assert_packet_checksums_valid(packet)
Matus Fabian7968e6c2017-07-06 05:37:49 -07003076 except:
3077 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3078 raise
3079
3080 # out2in
3081 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07003082 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Matus Fabian7968e6c2017-07-06 05:37:49 -07003083 GRE() /
3084 IP(src=self.pg3.remote_ip4, dst=self.pg2.remote_ip4) /
3085 TCP(sport=1234, dport=1234))
3086 self.pg1.add_stream(p)
3087 self.pg_enable_capture(self.pg_interfaces)
3088 self.pg_start()
3089 p = self.pg0.get_capture(1)
3090 packet = p[0]
3091 try:
3092 self.assertEqual(packet[IP].src, self.pg1.remote_ip4)
3093 self.assertEqual(packet[IP].dst, self.pg0.remote_ip4)
3094 self.assertTrue(packet.haslayer(GRE))
Klement Sekerad81ae412018-05-16 10:52:54 +02003095 self.assert_packet_checksums_valid(packet)
Matus Fabian7968e6c2017-07-06 05:37:49 -07003096 except:
3097 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3098 raise
3099
3100 def test_hairpinning_unknown_proto(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07003101 """ NAT44 translate packet with unknown protocol - hairpinning """
Matus Fabian7968e6c2017-07-06 05:37:49 -07003102 host = self.pg0.remote_hosts[0]
3103 server = self.pg0.remote_hosts[1]
3104 host_in_port = 1234
Matus Fabian7968e6c2017-07-06 05:37:49 -07003105 server_out_port = 8765
3106 server_nat_ip = "10.0.0.11"
3107
Matus Fabian2ba92e32017-08-21 07:05:03 -07003108 self.nat44_add_address(self.nat_addr)
3109 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3110 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3111 is_inside=0)
Matus Fabian7968e6c2017-07-06 05:37:49 -07003112
3113 # add static mapping for server
Matus Fabian2ba92e32017-08-21 07:05:03 -07003114 self.nat44_add_static_mapping(server.ip4, server_nat_ip)
Matus Fabian7968e6c2017-07-06 05:37:49 -07003115
3116 # host to server
3117 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
3118 IP(src=host.ip4, dst=server_nat_ip) /
3119 TCP(sport=host_in_port, dport=server_out_port))
3120 self.pg0.add_stream(p)
3121 self.pg_enable_capture(self.pg_interfaces)
3122 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07003123 self.pg0.get_capture(1)
Matus Fabian7968e6c2017-07-06 05:37:49 -07003124
3125 p = (Ether(dst=self.pg0.local_mac, src=host.mac) /
3126 IP(src=host.ip4, dst=server_nat_ip) /
3127 GRE() /
3128 IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4) /
3129 TCP(sport=1234, dport=1234))
3130 self.pg0.add_stream(p)
3131 self.pg_enable_capture(self.pg_interfaces)
3132 self.pg_start()
3133 p = self.pg0.get_capture(1)
3134 packet = p[0]
3135 try:
Matus Fabian2ba92e32017-08-21 07:05:03 -07003136 self.assertEqual(packet[IP].src, self.nat_addr)
Matus Fabian7968e6c2017-07-06 05:37:49 -07003137 self.assertEqual(packet[IP].dst, server.ip4)
3138 self.assertTrue(packet.haslayer(GRE))
Klement Sekerad81ae412018-05-16 10:52:54 +02003139 self.assert_packet_checksums_valid(packet)
Matus Fabian7968e6c2017-07-06 05:37:49 -07003140 except:
3141 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3142 raise
3143
3144 # server to host
3145 p = (Ether(dst=self.pg0.local_mac, src=server.mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07003146 IP(src=server.ip4, dst=self.nat_addr) /
Matus Fabian7968e6c2017-07-06 05:37:49 -07003147 GRE() /
3148 IP(src=self.pg3.remote_ip4, dst=self.pg2.remote_ip4) /
3149 TCP(sport=1234, dport=1234))
3150 self.pg0.add_stream(p)
3151 self.pg_enable_capture(self.pg_interfaces)
3152 self.pg_start()
3153 p = self.pg0.get_capture(1)
3154 packet = p[0]
3155 try:
3156 self.assertEqual(packet[IP].src, server_nat_ip)
3157 self.assertEqual(packet[IP].dst, host.ip4)
3158 self.assertTrue(packet.haslayer(GRE))
Klement Sekerad81ae412018-05-16 10:52:54 +02003159 self.assert_packet_checksums_valid(packet)
Matus Fabian7968e6c2017-07-06 05:37:49 -07003160 except:
3161 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3162 raise
3163
Matus Fabian93d84c92017-07-19 08:06:01 -07003164 def test_output_feature(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07003165 """ NAT44 interface output feature (in2out postrouting) """
3166 self.nat44_add_address(self.nat_addr)
3167 self.vapi.nat44_interface_add_del_output_feature(self.pg0.sw_if_index)
Matus Fabianb2d2fc72017-09-10 22:17:47 -07003168 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index)
3169 self.vapi.nat44_interface_add_del_output_feature(self.pg3.sw_if_index,
Matus Fabian2ba92e32017-08-21 07:05:03 -07003170 is_inside=0)
Matus Fabian93d84c92017-07-19 08:06:01 -07003171
3172 # in2out
Matus Fabianb2d2fc72017-09-10 22:17:47 -07003173 pkts = self.create_stream_in(self.pg0, self.pg3)
Matus Fabian93d84c92017-07-19 08:06:01 -07003174 self.pg0.add_stream(pkts)
3175 self.pg_enable_capture(self.pg_interfaces)
3176 self.pg_start()
Matus Fabianb2d2fc72017-09-10 22:17:47 -07003177 capture = self.pg3.get_capture(len(pkts))
Matus Fabian93d84c92017-07-19 08:06:01 -07003178 self.verify_capture_out(capture)
3179
3180 # out2in
Matus Fabianb2d2fc72017-09-10 22:17:47 -07003181 pkts = self.create_stream_out(self.pg3)
3182 self.pg3.add_stream(pkts)
Matus Fabian93d84c92017-07-19 08:06:01 -07003183 self.pg_enable_capture(self.pg_interfaces)
3184 self.pg_start()
3185 capture = self.pg0.get_capture(len(pkts))
3186 self.verify_capture_in(capture, self.pg0)
3187
Matus Fabianb2d2fc72017-09-10 22:17:47 -07003188 # from non-NAT interface to NAT inside interface
3189 pkts = self.create_stream_in(self.pg2, self.pg0)
3190 self.pg2.add_stream(pkts)
3191 self.pg_enable_capture(self.pg_interfaces)
3192 self.pg_start()
3193 capture = self.pg0.get_capture(len(pkts))
3194 self.verify_capture_no_translation(capture, self.pg2, self.pg0)
3195
Matus Fabian93d84c92017-07-19 08:06:01 -07003196 def test_output_feature_vrf_aware(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07003197 """ NAT44 interface output feature VRF aware (in2out postrouting) """
Matus Fabian93d84c92017-07-19 08:06:01 -07003198 nat_ip_vrf10 = "10.0.0.10"
3199 nat_ip_vrf20 = "10.0.0.20"
3200
3201 self.vapi.ip_add_del_route(dst_address=self.pg3.remote_ip4n,
3202 dst_address_length=32,
3203 next_hop_address=self.pg3.remote_ip4n,
3204 next_hop_sw_if_index=self.pg3.sw_if_index,
3205 table_id=10)
3206 self.vapi.ip_add_del_route(dst_address=self.pg3.remote_ip4n,
3207 dst_address_length=32,
3208 next_hop_address=self.pg3.remote_ip4n,
3209 next_hop_sw_if_index=self.pg3.sw_if_index,
3210 table_id=20)
3211
Matus Fabian2ba92e32017-08-21 07:05:03 -07003212 self.nat44_add_address(nat_ip_vrf10, vrf_id=10)
3213 self.nat44_add_address(nat_ip_vrf20, vrf_id=20)
3214 self.vapi.nat44_interface_add_del_output_feature(self.pg4.sw_if_index)
3215 self.vapi.nat44_interface_add_del_output_feature(self.pg6.sw_if_index)
3216 self.vapi.nat44_interface_add_del_output_feature(self.pg3.sw_if_index,
3217 is_inside=0)
Matus Fabian93d84c92017-07-19 08:06:01 -07003218
3219 # in2out VRF 10
3220 pkts = self.create_stream_in(self.pg4, self.pg3)
3221 self.pg4.add_stream(pkts)
3222 self.pg_enable_capture(self.pg_interfaces)
3223 self.pg_start()
3224 capture = self.pg3.get_capture(len(pkts))
3225 self.verify_capture_out(capture, nat_ip=nat_ip_vrf10)
3226
3227 # out2in VRF 10
3228 pkts = self.create_stream_out(self.pg3, dst_ip=nat_ip_vrf10)
3229 self.pg3.add_stream(pkts)
3230 self.pg_enable_capture(self.pg_interfaces)
3231 self.pg_start()
3232 capture = self.pg4.get_capture(len(pkts))
3233 self.verify_capture_in(capture, self.pg4)
3234
3235 # in2out VRF 20
3236 pkts = self.create_stream_in(self.pg6, self.pg3)
3237 self.pg6.add_stream(pkts)
3238 self.pg_enable_capture(self.pg_interfaces)
3239 self.pg_start()
3240 capture = self.pg3.get_capture(len(pkts))
3241 self.verify_capture_out(capture, nat_ip=nat_ip_vrf20)
3242
3243 # out2in VRF 20
3244 pkts = self.create_stream_out(self.pg3, dst_ip=nat_ip_vrf20)
3245 self.pg3.add_stream(pkts)
3246 self.pg_enable_capture(self.pg_interfaces)
3247 self.pg_start()
3248 capture = self.pg6.get_capture(len(pkts))
3249 self.verify_capture_in(capture, self.pg6)
3250
Matus Fabian161c59c2017-07-21 03:46:03 -07003251 def test_output_feature_hairpinning(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07003252 """ NAT44 interface output feature hairpinning (in2out postrouting) """
Matus Fabian93d84c92017-07-19 08:06:01 -07003253 host = self.pg0.remote_hosts[0]
3254 server = self.pg0.remote_hosts[1]
3255 host_in_port = 1234
3256 host_out_port = 0
3257 server_in_port = 5678
3258 server_out_port = 8765
3259
Matus Fabian2ba92e32017-08-21 07:05:03 -07003260 self.nat44_add_address(self.nat_addr)
3261 self.vapi.nat44_interface_add_del_output_feature(self.pg0.sw_if_index)
3262 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
3263 is_inside=0)
Matus Fabian93d84c92017-07-19 08:06:01 -07003264
3265 # add static mapping for server
Matus Fabian2ba92e32017-08-21 07:05:03 -07003266 self.nat44_add_static_mapping(server.ip4, self.nat_addr,
3267 server_in_port, server_out_port,
3268 proto=IP_PROTOS.tcp)
Matus Fabian93d84c92017-07-19 08:06:01 -07003269
3270 # send packet from host to server
3271 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07003272 IP(src=host.ip4, dst=self.nat_addr) /
Matus Fabian93d84c92017-07-19 08:06:01 -07003273 TCP(sport=host_in_port, dport=server_out_port))
3274 self.pg0.add_stream(p)
3275 self.pg_enable_capture(self.pg_interfaces)
3276 self.pg_start()
3277 capture = self.pg0.get_capture(1)
3278 p = capture[0]
3279 try:
3280 ip = p[IP]
3281 tcp = p[TCP]
Matus Fabian2ba92e32017-08-21 07:05:03 -07003282 self.assertEqual(ip.src, self.nat_addr)
Matus Fabian93d84c92017-07-19 08:06:01 -07003283 self.assertEqual(ip.dst, server.ip4)
3284 self.assertNotEqual(tcp.sport, host_in_port)
3285 self.assertEqual(tcp.dport, server_in_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02003286 self.assert_packet_checksums_valid(p)
Matus Fabian93d84c92017-07-19 08:06:01 -07003287 host_out_port = tcp.sport
3288 except:
3289 self.logger.error(ppp("Unexpected or invalid packet:", p))
3290 raise
3291
3292 # send reply from server to host
3293 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07003294 IP(src=server.ip4, dst=self.nat_addr) /
Matus Fabian93d84c92017-07-19 08:06:01 -07003295 TCP(sport=server_in_port, dport=host_out_port))
3296 self.pg0.add_stream(p)
3297 self.pg_enable_capture(self.pg_interfaces)
3298 self.pg_start()
3299 capture = self.pg0.get_capture(1)
3300 p = capture[0]
3301 try:
3302 ip = p[IP]
3303 tcp = p[TCP]
Matus Fabian2ba92e32017-08-21 07:05:03 -07003304 self.assertEqual(ip.src, self.nat_addr)
Matus Fabian93d84c92017-07-19 08:06:01 -07003305 self.assertEqual(ip.dst, host.ip4)
3306 self.assertEqual(tcp.sport, server_out_port)
3307 self.assertEqual(tcp.dport, host_in_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02003308 self.assert_packet_checksums_valid(p)
Matus Fabian93d84c92017-07-19 08:06:01 -07003309 except:
Matus Fabiane82488f2018-01-18 03:38:45 -08003310 self.logger.error(ppp("Unexpected or invalid packet:", p))
Matus Fabian93d84c92017-07-19 08:06:01 -07003311 raise
3312
Matus Fabianf7ad5cb2018-01-30 03:04:17 -08003313 def test_output_feature_and_service(self):
3314 """ NAT44 interface output feature and services """
3315 external_addr = '1.2.3.4'
3316 external_port = 80
3317 local_port = 8080
3318
3319 self.vapi.nat44_forwarding_enable_disable(1)
3320 self.nat44_add_address(self.nat_addr)
Matus Fabiana15cd022018-04-24 05:23:56 -07003321 self.vapi.nat44_add_del_identity_mapping(ip=self.pg1.remote_ip4n)
Matus Fabianf7ad5cb2018-01-30 03:04:17 -08003322 self.nat44_add_static_mapping(self.pg0.remote_ip4, external_addr,
3323 local_port, external_port,
3324 proto=IP_PROTOS.tcp, out2in_only=1)
3325 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
Matus Fabiana15cd022018-04-24 05:23:56 -07003326 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
3327 is_inside=0)
Matus Fabianf7ad5cb2018-01-30 03:04:17 -08003328 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
3329 is_inside=0)
3330
3331 # from client to service
3332 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3333 IP(src=self.pg1.remote_ip4, dst=external_addr) /
3334 TCP(sport=12345, dport=external_port))
3335 self.pg1.add_stream(p)
3336 self.pg_enable_capture(self.pg_interfaces)
3337 self.pg_start()
3338 capture = self.pg0.get_capture(1)
3339 p = capture[0]
Matus Fabianf7ad5cb2018-01-30 03:04:17 -08003340 try:
3341 ip = p[IP]
3342 tcp = p[TCP]
3343 self.assertEqual(ip.dst, self.pg0.remote_ip4)
3344 self.assertEqual(tcp.dport, local_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02003345 self.assert_packet_checksums_valid(p)
Matus Fabianf7ad5cb2018-01-30 03:04:17 -08003346 except:
3347 self.logger.error(ppp("Unexpected or invalid packet:", p))
3348 raise
3349
3350 # from service back to client
3351 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3352 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3353 TCP(sport=local_port, dport=12345))
3354 self.pg0.add_stream(p)
3355 self.pg_enable_capture(self.pg_interfaces)
3356 self.pg_start()
3357 capture = self.pg1.get_capture(1)
3358 p = capture[0]
3359 try:
3360 ip = p[IP]
3361 tcp = p[TCP]
3362 self.assertEqual(ip.src, external_addr)
3363 self.assertEqual(tcp.sport, external_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02003364 self.assert_packet_checksums_valid(p)
Matus Fabianf7ad5cb2018-01-30 03:04:17 -08003365 except:
3366 self.logger.error(ppp("Unexpected or invalid packet:", p))
3367 raise
3368
3369 # from local network host to external network
Matus Fabian2aad8762018-03-07 04:57:22 -08003370 pkts = self.create_stream_in(self.pg0, self.pg1)
3371 self.pg0.add_stream(pkts)
Matus Fabianf7ad5cb2018-01-30 03:04:17 -08003372 self.pg_enable_capture(self.pg_interfaces)
3373 self.pg_start()
Matus Fabian2aad8762018-03-07 04:57:22 -08003374 capture = self.pg1.get_capture(len(pkts))
3375 self.verify_capture_out(capture)
3376 pkts = self.create_stream_in(self.pg0, self.pg1)
3377 self.pg0.add_stream(pkts)
3378 self.pg_enable_capture(self.pg_interfaces)
3379 self.pg_start()
3380 capture = self.pg1.get_capture(len(pkts))
3381 self.verify_capture_out(capture)
Matus Fabianf7ad5cb2018-01-30 03:04:17 -08003382
3383 # from external network back to local network host
Matus Fabian2aad8762018-03-07 04:57:22 -08003384 pkts = self.create_stream_out(self.pg1)
3385 self.pg1.add_stream(pkts)
Matus Fabianf7ad5cb2018-01-30 03:04:17 -08003386 self.pg_enable_capture(self.pg_interfaces)
3387 self.pg_start()
Matus Fabian2aad8762018-03-07 04:57:22 -08003388 capture = self.pg0.get_capture(len(pkts))
3389 self.verify_capture_in(capture, self.pg0)
Matus Fabianf7ad5cb2018-01-30 03:04:17 -08003390
Matus Fabian204591d2018-03-01 04:48:33 -08003391 def test_output_feature_and_service2(self):
3392 """ NAT44 interface output feature and service host direct access """
3393 self.vapi.nat44_forwarding_enable_disable(1)
3394 self.nat44_add_address(self.nat_addr)
3395 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
3396 is_inside=0)
3397
3398 # session initiaded from service host - translate
3399 pkts = self.create_stream_in(self.pg0, self.pg1)
3400 self.pg0.add_stream(pkts)
3401 self.pg_enable_capture(self.pg_interfaces)
3402 self.pg_start()
3403 capture = self.pg1.get_capture(len(pkts))
3404 self.verify_capture_out(capture)
3405
3406 pkts = self.create_stream_out(self.pg1)
3407 self.pg1.add_stream(pkts)
3408 self.pg_enable_capture(self.pg_interfaces)
3409 self.pg_start()
3410 capture = self.pg0.get_capture(len(pkts))
3411 self.verify_capture_in(capture, self.pg0)
3412
Matus Fabian204591d2018-03-01 04:48:33 -08003413 # session initiaded from remote host - do not translate
3414 pkts = self.create_stream_out(self.pg1,
3415 self.pg0.remote_ip4,
3416 use_inside_ports=True)
3417 self.pg1.add_stream(pkts)
3418 self.pg_enable_capture(self.pg_interfaces)
3419 self.pg_start()
3420 capture = self.pg0.get_capture(len(pkts))
3421 self.verify_capture_in(capture, self.pg0)
3422
3423 pkts = self.create_stream_in(self.pg0, self.pg1)
3424 self.pg0.add_stream(pkts)
3425 self.pg_enable_capture(self.pg_interfaces)
3426 self.pg_start()
3427 capture = self.pg1.get_capture(len(pkts))
3428 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
3429 same_port=True)
3430
Matus Fabian4d023c82018-03-22 05:50:47 -07003431 def test_output_feature_and_service3(self):
3432 """ NAT44 interface output feature and DST NAT """
3433 external_addr = '1.2.3.4'
3434 external_port = 80
3435 local_port = 8080
3436
3437 self.vapi.nat44_forwarding_enable_disable(1)
3438 self.nat44_add_address(self.nat_addr)
3439 self.nat44_add_static_mapping(self.pg1.remote_ip4, external_addr,
3440 local_port, external_port,
3441 proto=IP_PROTOS.tcp, out2in_only=1)
3442 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3443 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
3444 is_inside=0)
3445 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
3446 is_inside=0)
3447
3448 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3449 IP(src=self.pg0.remote_ip4, dst=external_addr) /
3450 TCP(sport=12345, dport=external_port))
3451 self.pg0.add_stream(p)
3452 self.pg_enable_capture(self.pg_interfaces)
3453 self.pg_start()
3454 capture = self.pg1.get_capture(1)
3455 p = capture[0]
3456 try:
3457 ip = p[IP]
3458 tcp = p[TCP]
3459 self.assertEqual(ip.src, self.pg0.remote_ip4)
3460 self.assertEqual(tcp.sport, 12345)
3461 self.assertEqual(ip.dst, self.pg1.remote_ip4)
3462 self.assertEqual(tcp.dport, local_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02003463 self.assert_packet_checksums_valid(p)
Matus Fabian4d023c82018-03-22 05:50:47 -07003464 except:
3465 self.logger.error(ppp("Unexpected or invalid packet:", p))
3466 raise
3467
3468 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3469 IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
3470 TCP(sport=local_port, dport=12345))
3471 self.pg1.add_stream(p)
3472 self.pg_enable_capture(self.pg_interfaces)
3473 self.pg_start()
3474 capture = self.pg0.get_capture(1)
3475 p = capture[0]
3476 try:
3477 ip = p[IP]
3478 tcp = p[TCP]
3479 self.assertEqual(ip.src, external_addr)
3480 self.assertEqual(tcp.sport, external_port)
3481 self.assertEqual(ip.dst, self.pg0.remote_ip4)
3482 self.assertEqual(tcp.dport, 12345)
Klement Sekerad81ae412018-05-16 10:52:54 +02003483 self.assert_packet_checksums_valid(p)
Matus Fabian4d023c82018-03-22 05:50:47 -07003484 except:
3485 self.logger.error(ppp("Unexpected or invalid packet:", p))
3486 raise
3487
Matus Fabian36ea2d62017-10-24 04:13:49 -07003488 def test_one_armed_nat44(self):
3489 """ One armed NAT44 """
3490 remote_host = self.pg9.remote_hosts[0]
3491 local_host = self.pg9.remote_hosts[1]
3492 external_port = 0
3493
3494 self.nat44_add_address(self.nat_addr)
3495 self.vapi.nat44_interface_add_del_feature(self.pg9.sw_if_index)
3496 self.vapi.nat44_interface_add_del_feature(self.pg9.sw_if_index,
3497 is_inside=0)
3498
3499 # in2out
3500 p = (Ether(src=self.pg9.remote_mac, dst=self.pg9.local_mac) /
3501 IP(src=local_host.ip4, dst=remote_host.ip4) /
3502 TCP(sport=12345, dport=80))
3503 self.pg9.add_stream(p)
3504 self.pg_enable_capture(self.pg_interfaces)
3505 self.pg_start()
3506 capture = self.pg9.get_capture(1)
3507 p = capture[0]
3508 try:
3509 ip = p[IP]
3510 tcp = p[TCP]
3511 self.assertEqual(ip.src, self.nat_addr)
3512 self.assertEqual(ip.dst, remote_host.ip4)
3513 self.assertNotEqual(tcp.sport, 12345)
3514 external_port = tcp.sport
3515 self.assertEqual(tcp.dport, 80)
Klement Sekerad81ae412018-05-16 10:52:54 +02003516 self.assert_packet_checksums_valid(p)
Matus Fabian36ea2d62017-10-24 04:13:49 -07003517 except:
3518 self.logger.error(ppp("Unexpected or invalid packet:", p))
3519 raise
3520
3521 # out2in
3522 p = (Ether(src=self.pg9.remote_mac, dst=self.pg9.local_mac) /
3523 IP(src=remote_host.ip4, dst=self.nat_addr) /
3524 TCP(sport=80, dport=external_port))
3525 self.pg9.add_stream(p)
3526 self.pg_enable_capture(self.pg_interfaces)
3527 self.pg_start()
3528 capture = self.pg9.get_capture(1)
3529 p = capture[0]
3530 try:
3531 ip = p[IP]
3532 tcp = p[TCP]
3533 self.assertEqual(ip.src, remote_host.ip4)
3534 self.assertEqual(ip.dst, local_host.ip4)
3535 self.assertEqual(tcp.sport, 80)
3536 self.assertEqual(tcp.dport, 12345)
Klement Sekerad81ae412018-05-16 10:52:54 +02003537 self.assert_packet_checksums_valid(p)
Matus Fabian36ea2d62017-10-24 04:13:49 -07003538 except:
3539 self.logger.error(ppp("Unexpected or invalid packet:", p))
3540 raise
3541
Matus Fabiand95c39e2018-01-23 06:07:01 -08003542 def test_one_armed_nat44_static(self):
3543 """ One armed NAT44 and 1:1 NAPT symmetrical rule """
3544 remote_host = self.pg9.remote_hosts[0]
3545 local_host = self.pg9.remote_hosts[1]
3546 external_port = 80
3547 local_port = 8080
3548 eh_port_in = 0
3549
3550 self.vapi.nat44_forwarding_enable_disable(1)
3551 self.nat44_add_address(self.nat_addr, twice_nat=1)
3552 self.nat44_add_static_mapping(local_host.ip4, self.nat_addr,
3553 local_port, external_port,
3554 proto=IP_PROTOS.tcp, out2in_only=1,
3555 twice_nat=1)
3556 self.vapi.nat44_interface_add_del_feature(self.pg9.sw_if_index)
3557 self.vapi.nat44_interface_add_del_feature(self.pg9.sw_if_index,
3558 is_inside=0)
3559
3560 # from client to service
3561 p = (Ether(src=self.pg9.remote_mac, dst=self.pg9.local_mac) /
3562 IP(src=remote_host.ip4, dst=self.nat_addr) /
3563 TCP(sport=12345, dport=external_port))
3564 self.pg9.add_stream(p)
3565 self.pg_enable_capture(self.pg_interfaces)
3566 self.pg_start()
3567 capture = self.pg9.get_capture(1)
3568 p = capture[0]
Matus Fabiand95c39e2018-01-23 06:07:01 -08003569 try:
3570 ip = p[IP]
3571 tcp = p[TCP]
3572 self.assertEqual(ip.dst, local_host.ip4)
3573 self.assertEqual(ip.src, self.nat_addr)
3574 self.assertEqual(tcp.dport, local_port)
3575 self.assertNotEqual(tcp.sport, 12345)
3576 eh_port_in = tcp.sport
Klement Sekerad81ae412018-05-16 10:52:54 +02003577 self.assert_packet_checksums_valid(p)
Matus Fabiand95c39e2018-01-23 06:07:01 -08003578 except:
3579 self.logger.error(ppp("Unexpected or invalid packet:", p))
3580 raise
3581
3582 # from service back to client
3583 p = (Ether(src=self.pg9.remote_mac, dst=self.pg9.local_mac) /
3584 IP(src=local_host.ip4, dst=self.nat_addr) /
3585 TCP(sport=local_port, dport=eh_port_in))
3586 self.pg9.add_stream(p)
3587 self.pg_enable_capture(self.pg_interfaces)
3588 self.pg_start()
3589 capture = self.pg9.get_capture(1)
3590 p = capture[0]
3591 try:
3592 ip = p[IP]
3593 tcp = p[TCP]
3594 self.assertEqual(ip.src, self.nat_addr)
3595 self.assertEqual(ip.dst, remote_host.ip4)
3596 self.assertEqual(tcp.sport, external_port)
3597 self.assertEqual(tcp.dport, 12345)
Klement Sekerad81ae412018-05-16 10:52:54 +02003598 self.assert_packet_checksums_valid(p)
Matus Fabiand95c39e2018-01-23 06:07:01 -08003599 except:
3600 self.logger.error(ppp("Unexpected or invalid packet:", p))
3601 raise
3602
Matus Fabian5ba86f72017-10-26 03:37:38 -07003603 def test_del_session(self):
3604 """ Delete NAT44 session """
3605 self.nat44_add_address(self.nat_addr)
3606 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3607 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3608 is_inside=0)
3609
3610 pkts = self.create_stream_in(self.pg0, self.pg1)
3611 self.pg0.add_stream(pkts)
3612 self.pg_enable_capture(self.pg_interfaces)
3613 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07003614 self.pg1.get_capture(len(pkts))
Matus Fabian5ba86f72017-10-26 03:37:38 -07003615
3616 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
3617 nsessions = len(sessions)
3618
3619 self.vapi.nat44_del_session(sessions[0].inside_ip_address,
3620 sessions[0].inside_port,
3621 sessions[0].protocol)
3622 self.vapi.nat44_del_session(sessions[1].outside_ip_address,
3623 sessions[1].outside_port,
3624 sessions[1].protocol,
3625 is_in=0)
3626
3627 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
3628 self.assertEqual(nsessions - len(sessions), 2)
3629
Matus Fabianefcd1e92017-08-15 06:59:19 -07003630 def test_set_get_reass(self):
3631 """ NAT44 set/get virtual fragmentation reassembly """
3632 reas_cfg1 = self.vapi.nat_get_reass()
3633
3634 self.vapi.nat_set_reass(timeout=reas_cfg1.ip4_timeout + 5,
3635 max_reass=reas_cfg1.ip4_max_reass * 2,
3636 max_frag=reas_cfg1.ip4_max_frag * 2)
3637
3638 reas_cfg2 = self.vapi.nat_get_reass()
3639
3640 self.assertEqual(reas_cfg1.ip4_timeout + 5, reas_cfg2.ip4_timeout)
3641 self.assertEqual(reas_cfg1.ip4_max_reass * 2, reas_cfg2.ip4_max_reass)
3642 self.assertEqual(reas_cfg1.ip4_max_frag * 2, reas_cfg2.ip4_max_frag)
3643
3644 self.vapi.nat_set_reass(drop_frag=1)
3645 self.assertTrue(self.vapi.nat_get_reass().ip4_drop_frag)
3646
3647 def test_frag_in_order(self):
3648 """ NAT44 translate fragments arriving in order """
3649 self.nat44_add_address(self.nat_addr)
3650 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3651 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3652 is_inside=0)
3653
3654 data = "A" * 4 + "B" * 16 + "C" * 3
3655 self.tcp_port_in = random.randint(1025, 65535)
3656
3657 reass = self.vapi.nat_reass_dump()
3658 reass_n_start = len(reass)
3659
3660 # in2out
3661 pkts = self.create_stream_frag(self.pg0,
3662 self.pg1.remote_ip4,
3663 self.tcp_port_in,
3664 20,
3665 data)
3666 self.pg0.add_stream(pkts)
3667 self.pg_enable_capture(self.pg_interfaces)
3668 self.pg_start()
3669 frags = self.pg1.get_capture(len(pkts))
3670 p = self.reass_frags_and_verify(frags,
3671 self.nat_addr,
3672 self.pg1.remote_ip4)
3673 self.assertEqual(p[TCP].dport, 20)
3674 self.assertNotEqual(p[TCP].sport, self.tcp_port_in)
3675 self.tcp_port_out = p[TCP].sport
3676 self.assertEqual(data, p[Raw].load)
3677
3678 # out2in
3679 pkts = self.create_stream_frag(self.pg1,
3680 self.nat_addr,
3681 20,
3682 self.tcp_port_out,
3683 data)
3684 self.pg1.add_stream(pkts)
3685 self.pg_enable_capture(self.pg_interfaces)
3686 self.pg_start()
3687 frags = self.pg0.get_capture(len(pkts))
3688 p = self.reass_frags_and_verify(frags,
3689 self.pg1.remote_ip4,
3690 self.pg0.remote_ip4)
3691 self.assertEqual(p[TCP].sport, 20)
3692 self.assertEqual(p[TCP].dport, self.tcp_port_in)
3693 self.assertEqual(data, p[Raw].load)
3694
3695 reass = self.vapi.nat_reass_dump()
3696 reass_n_end = len(reass)
3697
3698 self.assertEqual(reass_n_end - reass_n_start, 2)
3699
3700 def test_reass_hairpinning(self):
3701 """ NAT44 fragments hairpinning """
Matus Fabianefcd1e92017-08-15 06:59:19 -07003702 server = self.pg0.remote_hosts[1]
3703 host_in_port = random.randint(1025, 65535)
Matus Fabianefcd1e92017-08-15 06:59:19 -07003704 server_in_port = random.randint(1025, 65535)
3705 server_out_port = random.randint(1025, 65535)
3706 data = "A" * 4 + "B" * 16 + "C" * 3
3707
3708 self.nat44_add_address(self.nat_addr)
3709 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3710 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3711 is_inside=0)
3712 # add static mapping for server
3713 self.nat44_add_static_mapping(server.ip4, self.nat_addr,
3714 server_in_port, server_out_port,
3715 proto=IP_PROTOS.tcp)
3716
3717 # send packet from host to server
3718 pkts = self.create_stream_frag(self.pg0,
3719 self.nat_addr,
3720 host_in_port,
3721 server_out_port,
3722 data)
3723 self.pg0.add_stream(pkts)
3724 self.pg_enable_capture(self.pg_interfaces)
3725 self.pg_start()
3726 frags = self.pg0.get_capture(len(pkts))
3727 p = self.reass_frags_and_verify(frags,
3728 self.nat_addr,
3729 server.ip4)
3730 self.assertNotEqual(p[TCP].sport, host_in_port)
3731 self.assertEqual(p[TCP].dport, server_in_port)
3732 self.assertEqual(data, p[Raw].load)
3733
3734 def test_frag_out_of_order(self):
3735 """ NAT44 translate fragments arriving out of order """
3736 self.nat44_add_address(self.nat_addr)
3737 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3738 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3739 is_inside=0)
3740
3741 data = "A" * 4 + "B" * 16 + "C" * 3
3742 random.randint(1025, 65535)
3743
3744 # in2out
3745 pkts = self.create_stream_frag(self.pg0,
3746 self.pg1.remote_ip4,
3747 self.tcp_port_in,
3748 20,
3749 data)
3750 pkts.reverse()
3751 self.pg0.add_stream(pkts)
3752 self.pg_enable_capture(self.pg_interfaces)
3753 self.pg_start()
3754 frags = self.pg1.get_capture(len(pkts))
3755 p = self.reass_frags_and_verify(frags,
3756 self.nat_addr,
3757 self.pg1.remote_ip4)
3758 self.assertEqual(p[TCP].dport, 20)
3759 self.assertNotEqual(p[TCP].sport, self.tcp_port_in)
3760 self.tcp_port_out = p[TCP].sport
3761 self.assertEqual(data, p[Raw].load)
3762
3763 # out2in
3764 pkts = self.create_stream_frag(self.pg1,
3765 self.nat_addr,
3766 20,
3767 self.tcp_port_out,
3768 data)
3769 pkts.reverse()
3770 self.pg1.add_stream(pkts)
3771 self.pg_enable_capture(self.pg_interfaces)
3772 self.pg_start()
3773 frags = self.pg0.get_capture(len(pkts))
3774 p = self.reass_frags_and_verify(frags,
3775 self.pg1.remote_ip4,
3776 self.pg0.remote_ip4)
3777 self.assertEqual(p[TCP].sport, 20)
3778 self.assertEqual(p[TCP].dport, self.tcp_port_in)
3779 self.assertEqual(data, p[Raw].load)
3780
Matus Fabian27697102017-11-09 01:43:47 -08003781 def test_port_restricted(self):
3782 """ Port restricted NAT44 (MAP-E CE) """
3783 self.nat44_add_address(self.nat_addr)
3784 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3785 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3786 is_inside=0)
Matus Fabian51e759f2017-12-07 23:22:51 -08003787 self.vapi.cli("nat addr-port-assignment-alg map-e psid 10 "
Matus Fabian27697102017-11-09 01:43:47 -08003788 "psid-offset 6 psid-len 6")
3789
3790 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3791 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3792 TCP(sport=4567, dport=22))
3793 self.pg0.add_stream(p)
3794 self.pg_enable_capture(self.pg_interfaces)
3795 self.pg_start()
3796 capture = self.pg1.get_capture(1)
3797 p = capture[0]
3798 try:
3799 ip = p[IP]
3800 tcp = p[TCP]
3801 self.assertEqual(ip.dst, self.pg1.remote_ip4)
3802 self.assertEqual(ip.src, self.nat_addr)
3803 self.assertEqual(tcp.dport, 22)
3804 self.assertNotEqual(tcp.sport, 4567)
3805 self.assertEqual((tcp.sport >> 6) & 63, 10)
Klement Sekerad81ae412018-05-16 10:52:54 +02003806 self.assert_packet_checksums_valid(p)
Matus Fabian27697102017-11-09 01:43:47 -08003807 except:
3808 self.logger.error(ppp("Unexpected or invalid packet:", p))
3809 raise
3810
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02003811 def twice_nat_common(self, self_twice_nat=False, same_pg=False, lb=False,
3812 client_id=None):
Matus Fabianb932d262017-12-18 05:38:24 -08003813 twice_nat_addr = '10.0.1.3'
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02003814
Matus Fabianb932d262017-12-18 05:38:24 -08003815 port_in = 8080
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02003816 if lb:
3817 if not same_pg:
3818 port_in1 = port_in
3819 port_in2 = port_in
3820 else:
3821 port_in1 = port_in+1
3822 port_in2 = port_in+2
3823
Matus Fabianb932d262017-12-18 05:38:24 -08003824 port_out = 80
3825 eh_port_out = 4567
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02003826
3827 server1 = self.pg0.remote_hosts[0]
3828 server2 = self.pg0.remote_hosts[1]
3829 if lb and same_pg:
3830 server2 = server1
3831 if not lb:
3832 server = server1
3833
3834 pg0 = self.pg0
3835 if same_pg:
3836 pg1 = self.pg0
3837 else:
3838 pg1 = self.pg1
3839
3840 eh_translate = ((not self_twice_nat) or (not lb and same_pg) or
3841 client_id == 1)
3842
Matus Fabianb932d262017-12-18 05:38:24 -08003843 self.nat44_add_address(self.nat_addr)
3844 self.nat44_add_address(twice_nat_addr, twice_nat=1)
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02003845 if not lb:
3846 self.nat44_add_static_mapping(pg0.remote_ip4, self.nat_addr,
3847 port_in, port_out,
3848 proto=IP_PROTOS.tcp,
3849 twice_nat=int(not self_twice_nat),
3850 self_twice_nat=int(self_twice_nat))
3851 else:
3852 locals = [{'addr': server1.ip4n,
3853 'port': port_in1,
3854 'probability': 50},
3855 {'addr': server2.ip4n,
3856 'port': port_in2,
3857 'probability': 50}]
3858 out_addr_n = socket.inet_pton(socket.AF_INET, self.nat_addr)
3859 self.vapi.nat44_add_del_lb_static_mapping(out_addr_n,
3860 port_out,
3861 IP_PROTOS.tcp,
3862 twice_nat=int(
3863 not self_twice_nat),
3864 self_twice_nat=int(
3865 self_twice_nat),
3866 local_num=len(locals),
3867 locals=locals)
3868 self.vapi.nat44_interface_add_del_feature(pg0.sw_if_index)
3869 self.vapi.nat44_interface_add_del_feature(pg1.sw_if_index,
Matus Fabianb932d262017-12-18 05:38:24 -08003870 is_inside=0)
3871
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02003872 if same_pg:
3873 if not lb:
3874 client = server
3875 else:
3876 assert client_id is not None
3877 if client_id == 1:
3878 client = self.pg0.remote_hosts[0]
3879 elif client_id == 2:
3880 client = self.pg0.remote_hosts[1]
3881 else:
3882 client = pg1.remote_hosts[0]
3883 p = (Ether(src=pg1.remote_mac, dst=pg1.local_mac) /
3884 IP(src=client.ip4, dst=self.nat_addr) /
Matus Fabianb932d262017-12-18 05:38:24 -08003885 TCP(sport=eh_port_out, dport=port_out))
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02003886 pg1.add_stream(p)
Matus Fabianb932d262017-12-18 05:38:24 -08003887 self.pg_enable_capture(self.pg_interfaces)
3888 self.pg_start()
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02003889 capture = pg0.get_capture(1)
Matus Fabianb932d262017-12-18 05:38:24 -08003890 p = capture[0]
3891 try:
3892 ip = p[IP]
3893 tcp = p[TCP]
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02003894 if lb:
3895 if ip.dst == server1.ip4:
3896 server = server1
3897 port_in = port_in1
3898 else:
3899 server = server2
3900 port_in = port_in2
3901 self.assertEqual(ip.dst, server.ip4)
3902 if lb and same_pg:
3903 self.assertIn(tcp.dport, [port_in1, port_in2])
3904 else:
3905 self.assertEqual(tcp.dport, port_in)
3906 if eh_translate:
3907 self.assertEqual(ip.src, twice_nat_addr)
3908 self.assertNotEqual(tcp.sport, eh_port_out)
3909 else:
3910 self.assertEqual(ip.src, client.ip4)
3911 self.assertEqual(tcp.sport, eh_port_out)
3912 eh_addr_in = ip.src
Matus Fabianb932d262017-12-18 05:38:24 -08003913 eh_port_in = tcp.sport
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02003914 saved_port_in = tcp.dport
Klement Sekerad81ae412018-05-16 10:52:54 +02003915 self.assert_packet_checksums_valid(p)
Matus Fabianb932d262017-12-18 05:38:24 -08003916 except:
3917 self.logger.error(ppp("Unexpected or invalid packet:", p))
3918 raise
3919
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02003920 p = (Ether(src=server.mac, dst=pg0.local_mac) /
3921 IP(src=server.ip4, dst=eh_addr_in) /
3922 TCP(sport=saved_port_in, dport=eh_port_in))
3923 pg0.add_stream(p)
Matus Fabianb932d262017-12-18 05:38:24 -08003924 self.pg_enable_capture(self.pg_interfaces)
3925 self.pg_start()
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02003926 capture = pg1.get_capture(1)
Matus Fabianb932d262017-12-18 05:38:24 -08003927 p = capture[0]
3928 try:
3929 ip = p[IP]
3930 tcp = p[TCP]
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02003931 self.assertEqual(ip.dst, client.ip4)
Matus Fabianb932d262017-12-18 05:38:24 -08003932 self.assertEqual(ip.src, self.nat_addr)
3933 self.assertEqual(tcp.dport, eh_port_out)
3934 self.assertEqual(tcp.sport, port_out)
Klement Sekerad81ae412018-05-16 10:52:54 +02003935 self.assert_packet_checksums_valid(p)
Matus Fabianb932d262017-12-18 05:38:24 -08003936 except:
3937 self.logger.error(ppp("Unexpected or invalid packet:", p))
3938 raise
3939
Matus Fabian70a26ac2018-05-14 06:20:28 -07003940 if eh_translate:
3941 sessions = self.vapi.nat44_user_session_dump(server.ip4n, 0)
3942 self.assertEqual(len(sessions), 1)
3943 self.assertTrue(sessions[0].ext_host_valid)
3944 self.assertTrue(sessions[0].is_twicenat)
3945 self.vapi.nat44_del_session(
3946 sessions[0].inside_ip_address,
3947 sessions[0].inside_port,
3948 sessions[0].protocol,
3949 ext_host_address=sessions[0].ext_host_nat_address,
3950 ext_host_port=sessions[0].ext_host_nat_port)
3951 sessions = self.vapi.nat44_user_session_dump(server.ip4n, 0)
3952 self.assertEqual(len(sessions), 0)
3953
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02003954 def test_twice_nat(self):
3955 """ Twice NAT44 """
3956 self.twice_nat_common()
3957
3958 def test_self_twice_nat_positive(self):
3959 """ Self Twice NAT44 (positive test) """
3960 self.twice_nat_common(self_twice_nat=True, same_pg=True)
3961
3962 def test_self_twice_nat_negative(self):
3963 """ Self Twice NAT44 (negative test) """
3964 self.twice_nat_common(self_twice_nat=True)
3965
Matus Fabianb932d262017-12-18 05:38:24 -08003966 def test_twice_nat_lb(self):
3967 """ Twice NAT44 local service load balancing """
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02003968 self.twice_nat_common(lb=True)
Matus Fabianb932d262017-12-18 05:38:24 -08003969
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02003970 def test_self_twice_nat_lb_positive(self):
3971 """ Self Twice NAT44 local service load balancing (positive test) """
3972 self.twice_nat_common(lb=True, self_twice_nat=True, same_pg=True,
3973 client_id=1)
Matus Fabianb932d262017-12-18 05:38:24 -08003974
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02003975 def test_self_twice_nat_lb_negative(self):
3976 """ Self Twice NAT44 local service load balancing (negative test) """
3977 self.twice_nat_common(lb=True, self_twice_nat=True, same_pg=True,
3978 client_id=2)
Matus Fabianb932d262017-12-18 05:38:24 -08003979
3980 def test_twice_nat_interface_addr(self):
3981 """ Acquire twice NAT44 addresses from interface """
3982 self.vapi.nat44_add_interface_addr(self.pg7.sw_if_index, twice_nat=1)
3983
3984 # no address in NAT pool
3985 adresses = self.vapi.nat44_address_dump()
3986 self.assertEqual(0, len(adresses))
3987
3988 # configure interface address and check NAT address pool
3989 self.pg7.config_ip4()
3990 adresses = self.vapi.nat44_address_dump()
3991 self.assertEqual(1, len(adresses))
3992 self.assertEqual(adresses[0].ip_address[0:4], self.pg7.local_ip4n)
3993 self.assertEqual(adresses[0].twice_nat, 1)
3994
3995 # remove interface address and check NAT address pool
3996 self.pg7.unconfig_ip4()
3997 adresses = self.vapi.nat44_address_dump()
3998 self.assertEqual(0, len(adresses))
3999
Matus Fabiana431ad12018-01-04 04:03:14 -08004000 def test_ipfix_max_frags(self):
4001 """ IPFIX logging maximum fragments pending reassembly exceeded """
4002 self.nat44_add_address(self.nat_addr)
4003 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4004 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4005 is_inside=0)
4006 self.vapi.nat_set_reass(max_frag=0)
4007 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
4008 src_address=self.pg3.local_ip4n,
4009 path_mtu=512,
4010 template_interval=10)
4011 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
4012 src_port=self.ipfix_src_port)
4013
4014 data = "A" * 4 + "B" * 16 + "C" * 3
4015 self.tcp_port_in = random.randint(1025, 65535)
4016 pkts = self.create_stream_frag(self.pg0,
4017 self.pg1.remote_ip4,
4018 self.tcp_port_in,
4019 20,
4020 data)
4021 self.pg0.add_stream(pkts[-1])
4022 self.pg_enable_capture(self.pg_interfaces)
4023 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07004024 self.pg1.assert_nothing_captured()
4025 sleep(1)
Matus Fabiana431ad12018-01-04 04:03:14 -08004026 self.vapi.cli("ipfix flush") # FIXME this should be an API call
4027 capture = self.pg3.get_capture(9)
4028 ipfix = IPFIXDecoder()
4029 # first load template
4030 for p in capture:
4031 self.assertTrue(p.haslayer(IPFIX))
4032 self.assertEqual(p[IP].src, self.pg3.local_ip4)
4033 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
4034 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
4035 self.assertEqual(p[UDP].dport, 4739)
4036 self.assertEqual(p[IPFIX].observationDomainID,
4037 self.ipfix_domain_id)
4038 if p.haslayer(Template):
4039 ipfix.add_template(p.getlayer(Template))
4040 # verify events in data set
4041 for p in capture:
4042 if p.haslayer(Data):
4043 data = ipfix.decode_data_set(p.getlayer(Set))
4044 self.verify_ipfix_max_fragments_ip4(data, 0,
4045 self.pg0.remote_ip4n)
4046
Matus Fabianebdf1902018-05-04 03:57:42 -07004047 def test_tcp_session_close_in(self):
4048 """ Close TCP session from inside network """
Matus Fabian229c1aa2018-05-28 04:09:52 -07004049 self.tcp_port_out = 10505
Matus Fabianebdf1902018-05-04 03:57:42 -07004050 self.nat44_add_address(self.nat_addr)
Matus Fabian229c1aa2018-05-28 04:09:52 -07004051 self.nat44_add_static_mapping(self.pg0.remote_ip4,
4052 self.nat_addr,
4053 self.tcp_port_in,
4054 self.tcp_port_out,
4055 proto=IP_PROTOS.tcp,
4056 twice_nat=1)
Matus Fabianebdf1902018-05-04 03:57:42 -07004057 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4058 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4059 is_inside=0)
4060
4061 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
4062 start_sessnum = len(sessions)
4063
4064 self.initiate_tcp_session(self.pg0, self.pg1)
4065
Matus Fabian229c1aa2018-05-28 04:09:52 -07004066 # FIN packet in -> out
4067 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4068 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4069 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
4070 flags="FA", seq=100, ack=300))
4071 self.pg0.add_stream(p)
4072 self.pg_enable_capture(self.pg_interfaces)
4073 self.pg_start()
4074 self.pg1.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07004075
Matus Fabian229c1aa2018-05-28 04:09:52 -07004076 pkts = []
Matus Fabianebdf1902018-05-04 03:57:42 -07004077
Matus Fabian229c1aa2018-05-28 04:09:52 -07004078 # ACK packet out -> in
4079 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4080 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4081 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
4082 flags="A", seq=300, ack=101))
4083 pkts.append(p)
Matus Fabianebdf1902018-05-04 03:57:42 -07004084
Matus Fabian229c1aa2018-05-28 04:09:52 -07004085 # FIN packet out -> in
4086 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4087 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4088 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
4089 flags="FA", seq=300, ack=101))
4090 pkts.append(p)
Matus Fabianebdf1902018-05-04 03:57:42 -07004091
Matus Fabian229c1aa2018-05-28 04:09:52 -07004092 self.pg1.add_stream(pkts)
4093 self.pg_enable_capture(self.pg_interfaces)
4094 self.pg_start()
4095 self.pg0.get_capture(2)
Matus Fabianebdf1902018-05-04 03:57:42 -07004096
Matus Fabian229c1aa2018-05-28 04:09:52 -07004097 # ACK packet in -> out
4098 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4099 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4100 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
4101 flags="A", seq=101, ack=301))
4102 self.pg0.add_stream(p)
4103 self.pg_enable_capture(self.pg_interfaces)
4104 self.pg_start()
4105 self.pg1.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07004106
Matus Fabian229c1aa2018-05-28 04:09:52 -07004107 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n,
4108 0)
4109 self.assertEqual(len(sessions) - start_sessnum, 0)
Matus Fabianebdf1902018-05-04 03:57:42 -07004110
4111 def test_tcp_session_close_out(self):
4112 """ Close TCP session from outside network """
Matus Fabian229c1aa2018-05-28 04:09:52 -07004113 self.tcp_port_out = 10505
Matus Fabianebdf1902018-05-04 03:57:42 -07004114 self.nat44_add_address(self.nat_addr)
Matus Fabian229c1aa2018-05-28 04:09:52 -07004115 self.nat44_add_static_mapping(self.pg0.remote_ip4,
4116 self.nat_addr,
4117 self.tcp_port_in,
4118 self.tcp_port_out,
4119 proto=IP_PROTOS.tcp,
4120 twice_nat=1)
Matus Fabianebdf1902018-05-04 03:57:42 -07004121 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4122 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4123 is_inside=0)
4124
4125 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
4126 start_sessnum = len(sessions)
4127
4128 self.initiate_tcp_session(self.pg0, self.pg1)
4129
Matus Fabian229c1aa2018-05-28 04:09:52 -07004130 # FIN packet out -> in
4131 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4132 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4133 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
4134 flags="FA", seq=100, ack=300))
4135 self.pg1.add_stream(p)
4136 self.pg_enable_capture(self.pg_interfaces)
4137 self.pg_start()
4138 self.pg0.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07004139
Matus Fabian229c1aa2018-05-28 04:09:52 -07004140 # FIN+ACK packet in -> out
4141 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4142 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4143 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
4144 flags="FA", seq=300, ack=101))
Matus Fabianebdf1902018-05-04 03:57:42 -07004145
Matus Fabian229c1aa2018-05-28 04:09:52 -07004146 self.pg0.add_stream(p)
4147 self.pg_enable_capture(self.pg_interfaces)
4148 self.pg_start()
4149 self.pg1.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07004150
Matus Fabian229c1aa2018-05-28 04:09:52 -07004151 # ACK packet out -> in
4152 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4153 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4154 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
4155 flags="A", seq=101, ack=301))
4156 self.pg1.add_stream(p)
4157 self.pg_enable_capture(self.pg_interfaces)
4158 self.pg_start()
4159 self.pg0.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07004160
Matus Fabian229c1aa2018-05-28 04:09:52 -07004161 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n,
4162 0)
4163 self.assertEqual(len(sessions) - start_sessnum, 0)
Matus Fabianebdf1902018-05-04 03:57:42 -07004164
4165 def test_tcp_session_close_simultaneous(self):
4166 """ Close TCP session from inside network """
Matus Fabian229c1aa2018-05-28 04:09:52 -07004167 self.tcp_port_out = 10505
Matus Fabianebdf1902018-05-04 03:57:42 -07004168 self.nat44_add_address(self.nat_addr)
Matus Fabian229c1aa2018-05-28 04:09:52 -07004169 self.nat44_add_static_mapping(self.pg0.remote_ip4,
4170 self.nat_addr,
4171 self.tcp_port_in,
4172 self.tcp_port_out,
4173 proto=IP_PROTOS.tcp,
4174 twice_nat=1)
Matus Fabianebdf1902018-05-04 03:57:42 -07004175 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4176 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4177 is_inside=0)
4178
4179 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
4180 start_sessnum = len(sessions)
4181
4182 self.initiate_tcp_session(self.pg0, self.pg1)
4183
Matus Fabian229c1aa2018-05-28 04:09:52 -07004184 # FIN packet in -> out
4185 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4186 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4187 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
4188 flags="FA", seq=100, ack=300))
4189 self.pg0.add_stream(p)
4190 self.pg_enable_capture(self.pg_interfaces)
4191 self.pg_start()
4192 self.pg1.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07004193
Matus Fabian229c1aa2018-05-28 04:09:52 -07004194 # FIN packet out -> in
4195 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4196 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4197 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
4198 flags="FA", seq=300, ack=100))
4199 self.pg1.add_stream(p)
4200 self.pg_enable_capture(self.pg_interfaces)
4201 self.pg_start()
4202 self.pg0.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07004203
Matus Fabian229c1aa2018-05-28 04:09:52 -07004204 # ACK packet in -> out
4205 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4206 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4207 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
4208 flags="A", seq=101, ack=301))
4209 self.pg0.add_stream(p)
4210 self.pg_enable_capture(self.pg_interfaces)
4211 self.pg_start()
4212 self.pg1.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07004213
Matus Fabian229c1aa2018-05-28 04:09:52 -07004214 # ACK packet out -> in
4215 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4216 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4217 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
4218 flags="A", seq=301, ack=101))
4219 self.pg1.add_stream(p)
4220 self.pg_enable_capture(self.pg_interfaces)
4221 self.pg_start()
4222 self.pg0.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07004223
Matus Fabian229c1aa2018-05-28 04:09:52 -07004224 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n,
4225 0)
4226 self.assertEqual(len(sessions) - start_sessnum, 0)
Matus Fabianebdf1902018-05-04 03:57:42 -07004227
Matus Fabiande886752016-12-07 03:38:19 -08004228 def tearDown(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07004229 super(TestNAT44, self).tearDown()
Matus Fabiande886752016-12-07 03:38:19 -08004230 if not self.vpp_dead:
Matus Fabian82119542018-01-25 01:13:22 -08004231 self.logger.info(self.vapi.cli("show nat44 addresses"))
4232 self.logger.info(self.vapi.cli("show nat44 interfaces"))
4233 self.logger.info(self.vapi.cli("show nat44 static mappings"))
4234 self.logger.info(self.vapi.cli("show nat44 interface address"))
4235 self.logger.info(self.vapi.cli("show nat44 sessions detail"))
Matus Fabianefcd1e92017-08-15 06:59:19 -07004236 self.logger.info(self.vapi.cli("show nat virtual-reassembly"))
Matus Fabian229c1aa2018-05-28 04:09:52 -07004237 self.logger.info(self.vapi.cli("show nat44 hash tables detail"))
Matus Fabian51e759f2017-12-07 23:22:51 -08004238 self.vapi.cli("nat addr-port-assignment-alg default")
Matus Fabian2ba92e32017-08-21 07:05:03 -07004239 self.clear_nat44()
Matus Fabian229c1aa2018-05-28 04:09:52 -07004240 self.vapi.cli("clear logging")
Matus Fabiande886752016-12-07 03:38:19 -08004241
Matus Fabianeea28d72017-01-13 04:15:54 -08004242
Juraj Slobodacba69362017-12-19 02:09:32 +01004243class TestNAT44Out2InDPO(MethodHolder):
4244 """ NAT44 Test Cases using out2in DPO """
4245
4246 @classmethod
4247 def setUpConstants(cls):
4248 super(TestNAT44Out2InDPO, cls).setUpConstants()
4249 cls.vpp_cmdline.extend(["nat", "{", "out2in dpo", "}"])
4250
4251 @classmethod
4252 def setUpClass(cls):
4253 super(TestNAT44Out2InDPO, cls).setUpClass()
Matus Fabian229c1aa2018-05-28 04:09:52 -07004254 cls.vapi.cli("set log class nat level debug")
Juraj Slobodacba69362017-12-19 02:09:32 +01004255
4256 try:
4257 cls.tcp_port_in = 6303
4258 cls.tcp_port_out = 6303
4259 cls.udp_port_in = 6304
4260 cls.udp_port_out = 6304
4261 cls.icmp_id_in = 6305
4262 cls.icmp_id_out = 6305
4263 cls.nat_addr = '10.0.0.3'
4264 cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
4265 cls.dst_ip4 = '192.168.70.1'
4266
4267 cls.create_pg_interfaces(range(2))
4268
4269 cls.pg0.admin_up()
4270 cls.pg0.config_ip4()
4271 cls.pg0.resolve_arp()
4272
4273 cls.pg1.admin_up()
4274 cls.pg1.config_ip6()
4275 cls.pg1.resolve_ndp()
4276
4277 cls.vapi.ip_add_del_route(is_ipv6=True, dst_address='\x00'*16,
4278 dst_address_length=0,
4279 next_hop_address=cls.pg1.remote_ip6n,
4280 next_hop_sw_if_index=cls.pg1.sw_if_index)
4281
4282 except Exception:
4283 super(TestNAT44Out2InDPO, cls).tearDownClass()
4284 raise
4285
4286 def configure_xlat(self):
4287 self.dst_ip6_pfx = '1:2:3::'
4288 self.dst_ip6_pfx_n = socket.inet_pton(socket.AF_INET6,
4289 self.dst_ip6_pfx)
4290 self.dst_ip6_pfx_len = 96
4291 self.src_ip6_pfx = '4:5:6::'
4292 self.src_ip6_pfx_n = socket.inet_pton(socket.AF_INET6,
4293 self.src_ip6_pfx)
4294 self.src_ip6_pfx_len = 96
4295 self.vapi.map_add_domain(self.dst_ip6_pfx_n, self.dst_ip6_pfx_len,
4296 self.src_ip6_pfx_n, self.src_ip6_pfx_len,
4297 '\x00\x00\x00\x00', 0, is_translation=1,
4298 is_rfc6052=1)
4299
4300 def test_464xlat_ce(self):
4301 """ Test 464XLAT CE with NAT44 """
4302
4303 self.configure_xlat()
4304
4305 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4306 self.vapi.nat44_add_del_address_range(self.nat_addr_n, self.nat_addr_n)
4307
4308 out_src_ip6 = self.compose_ip6(self.dst_ip4, self.dst_ip6_pfx,
4309 self.dst_ip6_pfx_len)
4310 out_dst_ip6 = self.compose_ip6(self.nat_addr, self.src_ip6_pfx,
4311 self.src_ip6_pfx_len)
4312
4313 try:
4314 pkts = self.create_stream_in(self.pg0, self.pg1, self.dst_ip4)
4315 self.pg0.add_stream(pkts)
4316 self.pg_enable_capture(self.pg_interfaces)
4317 self.pg_start()
4318 capture = self.pg1.get_capture(len(pkts))
4319 self.verify_capture_out_ip6(capture, nat_ip=out_dst_ip6,
4320 dst_ip=out_src_ip6)
4321
4322 pkts = self.create_stream_out_ip6(self.pg1, out_src_ip6,
4323 out_dst_ip6)
4324 self.pg1.add_stream(pkts)
4325 self.pg_enable_capture(self.pg_interfaces)
4326 self.pg_start()
4327 capture = self.pg0.get_capture(len(pkts))
4328 self.verify_capture_in(capture, self.pg0)
4329 finally:
4330 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
4331 is_add=0)
4332 self.vapi.nat44_add_del_address_range(self.nat_addr_n,
4333 self.nat_addr_n, is_add=0)
4334
4335 def test_464xlat_ce_no_nat(self):
4336 """ Test 464XLAT CE without NAT44 """
4337
4338 self.configure_xlat()
4339
4340 out_src_ip6 = self.compose_ip6(self.dst_ip4, self.dst_ip6_pfx,
4341 self.dst_ip6_pfx_len)
4342 out_dst_ip6 = self.compose_ip6(self.pg0.remote_ip4, self.src_ip6_pfx,
4343 self.src_ip6_pfx_len)
4344
4345 pkts = self.create_stream_in(self.pg0, self.pg1, self.dst_ip4)
4346 self.pg0.add_stream(pkts)
4347 self.pg_enable_capture(self.pg_interfaces)
4348 self.pg_start()
4349 capture = self.pg1.get_capture(len(pkts))
4350 self.verify_capture_out_ip6(capture, dst_ip=out_src_ip6,
4351 nat_ip=out_dst_ip6, same_port=True)
4352
4353 pkts = self.create_stream_out_ip6(self.pg1, out_src_ip6, out_dst_ip6)
4354 self.pg1.add_stream(pkts)
4355 self.pg_enable_capture(self.pg_interfaces)
4356 self.pg_start()
4357 capture = self.pg0.get_capture(len(pkts))
4358 self.verify_capture_in(capture, self.pg0)
4359
4360
Martin Gálikd7f75cd2017-03-27 06:02:47 -07004361class TestDeterministicNAT(MethodHolder):
Matus Fabian066f0342017-02-10 03:48:01 -08004362 """ Deterministic NAT Test Cases """
4363
4364 @classmethod
4365 def setUpConstants(cls):
4366 super(TestDeterministicNAT, cls).setUpConstants()
Matus Fabian2ba92e32017-08-21 07:05:03 -07004367 cls.vpp_cmdline.extend(["nat", "{", "deterministic", "}"])
Matus Fabian066f0342017-02-10 03:48:01 -08004368
4369 @classmethod
4370 def setUpClass(cls):
4371 super(TestDeterministicNAT, cls).setUpClass()
Matus Fabian229c1aa2018-05-28 04:09:52 -07004372 cls.vapi.cli("set log class nat level debug")
Matus Fabian066f0342017-02-10 03:48:01 -08004373
4374 try:
Martin Gálik977c1cb2017-03-30 23:21:51 -07004375 cls.tcp_port_in = 6303
Martin Gálik9806eae2017-04-25 01:25:08 -07004376 cls.tcp_external_port = 6303
Martin Gálik977c1cb2017-03-30 23:21:51 -07004377 cls.udp_port_in = 6304
Martin Gálik9806eae2017-04-25 01:25:08 -07004378 cls.udp_external_port = 6304
Martin Gálik977c1cb2017-03-30 23:21:51 -07004379 cls.icmp_id_in = 6305
Matus Fabian2ba92e32017-08-21 07:05:03 -07004380 cls.nat_addr = '10.0.0.3'
Martin Gálik977c1cb2017-03-30 23:21:51 -07004381
Matus Fabian2f2db1c2017-04-18 05:29:59 -07004382 cls.create_pg_interfaces(range(3))
Matus Fabian066f0342017-02-10 03:48:01 -08004383 cls.interfaces = list(cls.pg_interfaces)
4384
4385 for i in cls.interfaces:
4386 i.admin_up()
4387 i.config_ip4()
4388 i.resolve_arp()
4389
Martin Gálik977c1cb2017-03-30 23:21:51 -07004390 cls.pg0.generate_remote_hosts(2)
4391 cls.pg0.configure_ipv4_neighbors()
4392
Matus Fabian066f0342017-02-10 03:48:01 -08004393 except Exception:
4394 super(TestDeterministicNAT, cls).tearDownClass()
4395 raise
4396
Martin Gálik977c1cb2017-03-30 23:21:51 -07004397 def create_stream_in(self, in_if, out_if, ttl=64):
4398 """
4399 Create packet stream for inside network
4400
4401 :param in_if: Inside interface
4402 :param out_if: Outside interface
4403 :param ttl: TTL of generated packets
4404 """
4405 pkts = []
4406 # TCP
4407 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
4408 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004409 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07004410 pkts.append(p)
4411
4412 # UDP
4413 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
4414 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004415 UDP(sport=self.udp_port_in, dport=self.udp_external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07004416 pkts.append(p)
4417
4418 # ICMP
4419 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
4420 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
4421 ICMP(id=self.icmp_id_in, type='echo-request'))
4422 pkts.append(p)
4423
4424 return pkts
4425
4426 def create_stream_out(self, out_if, dst_ip=None, ttl=64):
4427 """
4428 Create packet stream for outside network
4429
4430 :param out_if: Outside interface
Matus Fabian2ba92e32017-08-21 07:05:03 -07004431 :param dst_ip: Destination IP address (Default use global NAT address)
Martin Gálik977c1cb2017-03-30 23:21:51 -07004432 :param ttl: TTL of generated packets
4433 """
4434 if dst_ip is None:
Matus Fabian2ba92e32017-08-21 07:05:03 -07004435 dst_ip = self.nat_addr
Martin Gálik977c1cb2017-03-30 23:21:51 -07004436 pkts = []
4437 # TCP
4438 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
4439 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004440 TCP(dport=self.tcp_port_out, sport=self.tcp_external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07004441 pkts.append(p)
4442
4443 # UDP
4444 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
4445 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004446 UDP(dport=self.udp_port_out, sport=self.udp_external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07004447 pkts.append(p)
4448
4449 # ICMP
4450 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
4451 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
4452 ICMP(id=self.icmp_external_id, type='echo-reply'))
4453 pkts.append(p)
4454
4455 return pkts
4456
4457 def verify_capture_out(self, capture, nat_ip=None, packet_num=3):
4458 """
4459 Verify captured packets on outside network
4460
4461 :param capture: Captured packets
Matus Fabian2ba92e32017-08-21 07:05:03 -07004462 :param nat_ip: Translated IP address (Default use global NAT address)
Martin Gálik977c1cb2017-03-30 23:21:51 -07004463 :param same_port: Sorce port number is not translated (Default False)
4464 :param packet_num: Expected number of packets (Default 3)
4465 """
4466 if nat_ip is None:
Matus Fabian2ba92e32017-08-21 07:05:03 -07004467 nat_ip = self.nat_addr
Martin Gálik977c1cb2017-03-30 23:21:51 -07004468 self.assertEqual(packet_num, len(capture))
4469 for packet in capture:
4470 try:
4471 self.assertEqual(packet[IP].src, nat_ip)
4472 if packet.haslayer(TCP):
Martin Gálik9806eae2017-04-25 01:25:08 -07004473 self.tcp_port_out = packet[TCP].sport
Martin Gálik977c1cb2017-03-30 23:21:51 -07004474 elif packet.haslayer(UDP):
Martin Gálik9806eae2017-04-25 01:25:08 -07004475 self.udp_port_out = packet[UDP].sport
Martin Gálik977c1cb2017-03-30 23:21:51 -07004476 else:
4477 self.icmp_external_id = packet[ICMP].id
4478 except:
4479 self.logger.error(ppp("Unexpected or invalid packet "
4480 "(outside network):", packet))
4481 raise
4482
Matus Fabian2f2db1c2017-04-18 05:29:59 -07004483 def verify_ipfix_max_entries_per_user(self, data):
4484 """
4485 Verify IPFIX maximum entries per user exceeded event
4486
4487 :param data: Decoded IPFIX data records
4488 """
4489 self.assertEqual(1, len(data))
4490 record = data[0]
4491 # natEvent
4492 self.assertEqual(ord(record[230]), 13)
4493 # natQuotaExceededEvent
4494 self.assertEqual('\x03\x00\x00\x00', record[466])
Matus Fabiana431ad12018-01-04 04:03:14 -08004495 # maxEntriesPerUser
4496 self.assertEqual('\xe8\x03\x00\x00', record[473])
Matus Fabian2f2db1c2017-04-18 05:29:59 -07004497 # sourceIPv4Address
4498 self.assertEqual(self.pg0.remote_ip4n, record[8])
4499
Matus Fabian066f0342017-02-10 03:48:01 -08004500 def test_deterministic_mode(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07004501 """ NAT plugin run deterministic mode """
Matus Fabian066f0342017-02-10 03:48:01 -08004502 in_addr = '172.16.255.0'
4503 out_addr = '172.17.255.50'
4504 in_addr_t = '172.16.255.20'
4505 in_addr_n = socket.inet_aton(in_addr)
4506 out_addr_n = socket.inet_aton(out_addr)
4507 in_addr_t_n = socket.inet_aton(in_addr_t)
4508 in_plen = 24
4509 out_plen = 32
4510
Matus Fabian2ba92e32017-08-21 07:05:03 -07004511 nat_config = self.vapi.nat_show_config()
4512 self.assertEqual(1, nat_config.deterministic)
Matus Fabian066f0342017-02-10 03:48:01 -08004513
Matus Fabian2ba92e32017-08-21 07:05:03 -07004514 self.vapi.nat_det_add_del_map(in_addr_n, in_plen, out_addr_n, out_plen)
Matus Fabian066f0342017-02-10 03:48:01 -08004515
Matus Fabian2ba92e32017-08-21 07:05:03 -07004516 rep1 = self.vapi.nat_det_forward(in_addr_t_n)
Matus Fabian066f0342017-02-10 03:48:01 -08004517 self.assertEqual(rep1.out_addr[:4], out_addr_n)
Matus Fabian2ba92e32017-08-21 07:05:03 -07004518 rep2 = self.vapi.nat_det_reverse(out_addr_n, rep1.out_port_hi)
Matus Fabian066f0342017-02-10 03:48:01 -08004519 self.assertEqual(rep2.in_addr[:4], in_addr_t_n)
4520
Matus Fabian2ba92e32017-08-21 07:05:03 -07004521 deterministic_mappings = self.vapi.nat_det_map_dump()
Martin17a75cb2017-03-08 05:53:20 -08004522 self.assertEqual(len(deterministic_mappings), 1)
4523 dsm = deterministic_mappings[0]
4524 self.assertEqual(in_addr_n, dsm.in_addr[:4])
4525 self.assertEqual(in_plen, dsm.in_plen)
4526 self.assertEqual(out_addr_n, dsm.out_addr[:4])
4527 self.assertEqual(out_plen, dsm.out_plen)
4528
Matus Fabian2ba92e32017-08-21 07:05:03 -07004529 self.clear_nat_det()
4530 deterministic_mappings = self.vapi.nat_det_map_dump()
Martinb616e9f2017-03-14 02:25:45 -07004531 self.assertEqual(len(deterministic_mappings), 0)
4532
Matus Fabian6a0946f2017-04-12 03:36:13 -07004533 def test_set_timeouts(self):
4534 """ Set deterministic NAT timeouts """
Matus Fabian2ba92e32017-08-21 07:05:03 -07004535 timeouts_before = self.vapi.nat_det_get_timeouts()
Matus Fabian6a0946f2017-04-12 03:36:13 -07004536
Matus Fabian2ba92e32017-08-21 07:05:03 -07004537 self.vapi.nat_det_set_timeouts(timeouts_before.udp + 10,
4538 timeouts_before.tcp_established + 10,
4539 timeouts_before.tcp_transitory + 10,
4540 timeouts_before.icmp + 10)
Matus Fabian6a0946f2017-04-12 03:36:13 -07004541
Matus Fabian2ba92e32017-08-21 07:05:03 -07004542 timeouts_after = self.vapi.nat_det_get_timeouts()
Matus Fabian6a0946f2017-04-12 03:36:13 -07004543
4544 self.assertNotEqual(timeouts_before.udp, timeouts_after.udp)
4545 self.assertNotEqual(timeouts_before.icmp, timeouts_after.icmp)
4546 self.assertNotEqual(timeouts_before.tcp_established,
4547 timeouts_after.tcp_established)
4548 self.assertNotEqual(timeouts_before.tcp_transitory,
4549 timeouts_after.tcp_transitory)
4550
Martin Gálik977c1cb2017-03-30 23:21:51 -07004551 def test_det_in(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07004552 """ Deterministic NAT translation test (TCP, UDP, ICMP) """
Martin Gálik977c1cb2017-03-30 23:21:51 -07004553
4554 nat_ip = "10.0.0.10"
Martin Gálik977c1cb2017-03-30 23:21:51 -07004555
Matus Fabian2ba92e32017-08-21 07:05:03 -07004556 self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
4557 32,
4558 socket.inet_aton(nat_ip),
4559 32)
4560 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4561 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4562 is_inside=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07004563
4564 # in2out
4565 pkts = self.create_stream_in(self.pg0, self.pg1)
4566 self.pg0.add_stream(pkts)
4567 self.pg_enable_capture(self.pg_interfaces)
4568 self.pg_start()
4569 capture = self.pg1.get_capture(len(pkts))
4570 self.verify_capture_out(capture, nat_ip)
4571
4572 # out2in
4573 pkts = self.create_stream_out(self.pg1, nat_ip)
4574 self.pg1.add_stream(pkts)
4575 self.pg_enable_capture(self.pg_interfaces)
4576 self.pg_start()
4577 capture = self.pg0.get_capture(len(pkts))
4578 self.verify_capture_in(capture, self.pg0)
4579
Martin Gálik9806eae2017-04-25 01:25:08 -07004580 # session dump test
Matus Fabian2ba92e32017-08-21 07:05:03 -07004581 sessions = self.vapi.nat_det_session_dump(self.pg0.remote_ip4n)
Martin Gálik9806eae2017-04-25 01:25:08 -07004582 self.assertEqual(len(sessions), 3)
4583
4584 # TCP session
4585 s = sessions[0]
4586 self.assertEqual(s.ext_addr[:4], self.pg1.remote_ip4n)
4587 self.assertEqual(s.in_port, self.tcp_port_in)
4588 self.assertEqual(s.out_port, self.tcp_port_out)
4589 self.assertEqual(s.ext_port, self.tcp_external_port)
4590
4591 # UDP session
4592 s = sessions[1]
4593 self.assertEqual(s.ext_addr[:4], self.pg1.remote_ip4n)
4594 self.assertEqual(s.in_port, self.udp_port_in)
4595 self.assertEqual(s.out_port, self.udp_port_out)
4596 self.assertEqual(s.ext_port, self.udp_external_port)
4597
4598 # ICMP session
4599 s = sessions[2]
4600 self.assertEqual(s.ext_addr[:4], self.pg1.remote_ip4n)
4601 self.assertEqual(s.in_port, self.icmp_id_in)
4602 self.assertEqual(s.out_port, self.icmp_external_id)
4603
Martin Gálik977c1cb2017-03-30 23:21:51 -07004604 def test_multiple_users(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07004605 """ Deterministic NAT multiple users """
Martin Gálik977c1cb2017-03-30 23:21:51 -07004606
4607 nat_ip = "10.0.0.10"
4608 port_in = 80
Martin Gálik9806eae2017-04-25 01:25:08 -07004609 external_port = 6303
Martin Gálik977c1cb2017-03-30 23:21:51 -07004610
4611 host0 = self.pg0.remote_hosts[0]
4612 host1 = self.pg0.remote_hosts[1]
4613
Matus Fabian2ba92e32017-08-21 07:05:03 -07004614 self.vapi.nat_det_add_del_map(host0.ip4n,
4615 24,
4616 socket.inet_aton(nat_ip),
4617 32)
4618 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4619 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4620 is_inside=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07004621
4622 # host0 to out
4623 p = (Ether(src=host0.mac, dst=self.pg0.local_mac) /
4624 IP(src=host0.ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004625 TCP(sport=port_in, dport=external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07004626 self.pg0.add_stream(p)
4627 self.pg_enable_capture(self.pg_interfaces)
4628 self.pg_start()
4629 capture = self.pg1.get_capture(1)
4630 p = capture[0]
4631 try:
4632 ip = p[IP]
4633 tcp = p[TCP]
4634 self.assertEqual(ip.src, nat_ip)
4635 self.assertEqual(ip.dst, self.pg1.remote_ip4)
Martin Gálik9806eae2017-04-25 01:25:08 -07004636 self.assertEqual(tcp.dport, external_port)
4637 port_out0 = tcp.sport
Martin Gálik977c1cb2017-03-30 23:21:51 -07004638 except:
4639 self.logger.error(ppp("Unexpected or invalid packet:", p))
4640 raise
4641
4642 # host1 to out
4643 p = (Ether(src=host1.mac, dst=self.pg0.local_mac) /
4644 IP(src=host1.ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004645 TCP(sport=port_in, dport=external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07004646 self.pg0.add_stream(p)
4647 self.pg_enable_capture(self.pg_interfaces)
4648 self.pg_start()
4649 capture = self.pg1.get_capture(1)
4650 p = capture[0]
4651 try:
4652 ip = p[IP]
4653 tcp = p[TCP]
4654 self.assertEqual(ip.src, nat_ip)
4655 self.assertEqual(ip.dst, self.pg1.remote_ip4)
Martin Gálik9806eae2017-04-25 01:25:08 -07004656 self.assertEqual(tcp.dport, external_port)
4657 port_out1 = tcp.sport
Martin Gálik977c1cb2017-03-30 23:21:51 -07004658 except:
4659 self.logger.error(ppp("Unexpected or invalid packet:", p))
4660 raise
4661
Matus Fabian2ba92e32017-08-21 07:05:03 -07004662 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07004663 self.assertEqual(1, len(dms))
4664 self.assertEqual(2, dms[0].ses_num)
4665
4666 # out to host0
4667 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4668 IP(src=self.pg1.remote_ip4, dst=nat_ip) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004669 TCP(sport=external_port, dport=port_out0))
Martin Gálik977c1cb2017-03-30 23:21:51 -07004670 self.pg1.add_stream(p)
4671 self.pg_enable_capture(self.pg_interfaces)
4672 self.pg_start()
4673 capture = self.pg0.get_capture(1)
4674 p = capture[0]
4675 try:
4676 ip = p[IP]
4677 tcp = p[TCP]
4678 self.assertEqual(ip.src, self.pg1.remote_ip4)
4679 self.assertEqual(ip.dst, host0.ip4)
4680 self.assertEqual(tcp.dport, port_in)
Martin Gálik9806eae2017-04-25 01:25:08 -07004681 self.assertEqual(tcp.sport, external_port)
Martin Gálik977c1cb2017-03-30 23:21:51 -07004682 except:
4683 self.logger.error(ppp("Unexpected or invalid packet:", p))
4684 raise
4685
4686 # out to host1
4687 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4688 IP(src=self.pg1.remote_ip4, dst=nat_ip) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004689 TCP(sport=external_port, dport=port_out1))
Martin Gálik977c1cb2017-03-30 23:21:51 -07004690 self.pg1.add_stream(p)
4691 self.pg_enable_capture(self.pg_interfaces)
4692 self.pg_start()
4693 capture = self.pg0.get_capture(1)
4694 p = capture[0]
4695 try:
4696 ip = p[IP]
4697 tcp = p[TCP]
4698 self.assertEqual(ip.src, self.pg1.remote_ip4)
4699 self.assertEqual(ip.dst, host1.ip4)
4700 self.assertEqual(tcp.dport, port_in)
Martin Gálik9806eae2017-04-25 01:25:08 -07004701 self.assertEqual(tcp.sport, external_port)
Martin Gálik977c1cb2017-03-30 23:21:51 -07004702 except:
4703 self.logger.error(ppp("Unexpected or invalid packet", p))
4704 raise
4705
Martin Gálik6bc8c642017-04-19 01:12:27 -07004706 # session close api test
Matus Fabian2ba92e32017-08-21 07:05:03 -07004707 self.vapi.nat_det_close_session_out(socket.inet_aton(nat_ip),
4708 port_out1,
Martin Gálik6bc8c642017-04-19 01:12:27 -07004709 self.pg1.remote_ip4n,
Martin Gálik9806eae2017-04-25 01:25:08 -07004710 external_port)
Matus Fabian2ba92e32017-08-21 07:05:03 -07004711 dms = self.vapi.nat_det_map_dump()
4712 self.assertEqual(dms[0].ses_num, 1)
4713
4714 self.vapi.nat_det_close_session_in(host0.ip4n,
4715 port_in,
4716 self.pg1.remote_ip4n,
4717 external_port)
4718 dms = self.vapi.nat_det_map_dump()
Martin Gálik6bc8c642017-04-19 01:12:27 -07004719 self.assertEqual(dms[0].ses_num, 0)
4720
Martin Gálik977c1cb2017-03-30 23:21:51 -07004721 def test_tcp_session_close_detection_in(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07004722 """ Deterministic NAT TCP session close from inside network """
4723 self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
4724 32,
4725 socket.inet_aton(self.nat_addr),
4726 32)
4727 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4728 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4729 is_inside=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07004730
4731 self.initiate_tcp_session(self.pg0, self.pg1)
4732
4733 # close the session from inside
4734 try:
4735 # FIN packet in -> out
4736 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4737 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004738 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
Martin Gálik977c1cb2017-03-30 23:21:51 -07004739 flags="F"))
4740 self.pg0.add_stream(p)
4741 self.pg_enable_capture(self.pg_interfaces)
4742 self.pg_start()
4743 self.pg1.get_capture(1)
4744
4745 pkts = []
4746
4747 # ACK packet out -> in
4748 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07004749 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004750 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
Martin Gálik977c1cb2017-03-30 23:21:51 -07004751 flags="A"))
4752 pkts.append(p)
4753
4754 # FIN packet out -> in
4755 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07004756 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004757 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
Martin Gálik977c1cb2017-03-30 23:21:51 -07004758 flags="F"))
4759 pkts.append(p)
4760
4761 self.pg1.add_stream(pkts)
4762 self.pg_enable_capture(self.pg_interfaces)
4763 self.pg_start()
4764 self.pg0.get_capture(2)
4765
4766 # ACK packet in -> out
4767 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4768 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004769 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
Martin Gálik977c1cb2017-03-30 23:21:51 -07004770 flags="A"))
4771 self.pg0.add_stream(p)
4772 self.pg_enable_capture(self.pg_interfaces)
4773 self.pg_start()
4774 self.pg1.get_capture(1)
4775
Matus Fabian2ba92e32017-08-21 07:05:03 -07004776 # Check if deterministic NAT44 closed the session
4777 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07004778 self.assertEqual(0, dms[0].ses_num)
4779 except:
4780 self.logger.error("TCP session termination failed")
4781 raise
4782
4783 def test_tcp_session_close_detection_out(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07004784 """ Deterministic NAT TCP session close from outside network """
4785 self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
4786 32,
4787 socket.inet_aton(self.nat_addr),
4788 32)
4789 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4790 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4791 is_inside=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07004792
4793 self.initiate_tcp_session(self.pg0, self.pg1)
4794
4795 # close the session from outside
4796 try:
4797 # FIN packet out -> in
4798 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07004799 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004800 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
Martin Gálik977c1cb2017-03-30 23:21:51 -07004801 flags="F"))
4802 self.pg1.add_stream(p)
4803 self.pg_enable_capture(self.pg_interfaces)
4804 self.pg_start()
4805 self.pg0.get_capture(1)
4806
4807 pkts = []
4808
4809 # ACK packet in -> out
4810 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4811 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004812 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
Martin Gálik977c1cb2017-03-30 23:21:51 -07004813 flags="A"))
4814 pkts.append(p)
4815
4816 # ACK packet in -> out
4817 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4818 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004819 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
Martin Gálik977c1cb2017-03-30 23:21:51 -07004820 flags="F"))
4821 pkts.append(p)
4822
4823 self.pg0.add_stream(pkts)
4824 self.pg_enable_capture(self.pg_interfaces)
4825 self.pg_start()
4826 self.pg1.get_capture(2)
4827
4828 # ACK packet out -> in
4829 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07004830 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004831 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
Martin Gálik977c1cb2017-03-30 23:21:51 -07004832 flags="A"))
4833 self.pg1.add_stream(p)
4834 self.pg_enable_capture(self.pg_interfaces)
4835 self.pg_start()
4836 self.pg0.get_capture(1)
4837
Matus Fabian2ba92e32017-08-21 07:05:03 -07004838 # Check if deterministic NAT44 closed the session
4839 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07004840 self.assertEqual(0, dms[0].ses_num)
4841 except:
4842 self.logger.error("TCP session termination failed")
4843 raise
4844
4845 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
4846 def test_session_timeout(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07004847 """ Deterministic NAT session timeouts """
4848 self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
4849 32,
4850 socket.inet_aton(self.nat_addr),
4851 32)
4852 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4853 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4854 is_inside=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07004855
4856 self.initiate_tcp_session(self.pg0, self.pg1)
Matus Fabian2ba92e32017-08-21 07:05:03 -07004857 self.vapi.nat_det_set_timeouts(5, 5, 5, 5)
Martin Gálik977c1cb2017-03-30 23:21:51 -07004858 pkts = self.create_stream_in(self.pg0, self.pg1)
4859 self.pg0.add_stream(pkts)
4860 self.pg_enable_capture(self.pg_interfaces)
4861 self.pg_start()
4862 capture = self.pg1.get_capture(len(pkts))
4863 sleep(15)
4864
Matus Fabian2ba92e32017-08-21 07:05:03 -07004865 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07004866 self.assertEqual(0, dms[0].ses_num)
4867
Matus Fabian7c0aecc2017-07-03 01:21:38 -07004868 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
Martin Gálik977c1cb2017-03-30 23:21:51 -07004869 def test_session_limit_per_user(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07004870 """ Deterministic NAT maximum sessions per user limit """
4871 self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
4872 32,
4873 socket.inet_aton(self.nat_addr),
4874 32)
4875 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4876 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4877 is_inside=0)
Matus Fabian2f2db1c2017-04-18 05:29:59 -07004878 self.vapi.set_ipfix_exporter(collector_address=self.pg2.remote_ip4n,
4879 src_address=self.pg2.local_ip4n,
4880 path_mtu=512,
4881 template_interval=10)
Matus Fabian2ba92e32017-08-21 07:05:03 -07004882 self.vapi.nat_ipfix()
Martin Gálik977c1cb2017-03-30 23:21:51 -07004883
4884 pkts = []
4885 for port in range(1025, 2025):
4886 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4887 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4888 UDP(sport=port, dport=port))
4889 pkts.append(p)
4890
4891 self.pg0.add_stream(pkts)
4892 self.pg_enable_capture(self.pg_interfaces)
4893 self.pg_start()
4894 capture = self.pg1.get_capture(len(pkts))
4895
4896 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4897 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálikf7e655d2017-04-27 02:13:26 -07004898 UDP(sport=3001, dport=3002))
Martin Gálik977c1cb2017-03-30 23:21:51 -07004899 self.pg0.add_stream(p)
4900 self.pg_enable_capture(self.pg_interfaces)
4901 self.pg_start()
4902 capture = self.pg1.assert_nothing_captured()
4903
Martin Gálikf7e655d2017-04-27 02:13:26 -07004904 # verify ICMP error packet
4905 capture = self.pg0.get_capture(1)
4906 p = capture[0]
4907 self.assertTrue(p.haslayer(ICMP))
4908 icmp = p[ICMP]
4909 self.assertEqual(icmp.type, 3)
4910 self.assertEqual(icmp.code, 1)
4911 self.assertTrue(icmp.haslayer(IPerror))
4912 inner_ip = icmp[IPerror]
4913 self.assertEqual(inner_ip[UDPerror].sport, 3001)
4914 self.assertEqual(inner_ip[UDPerror].dport, 3002)
4915
Matus Fabian2ba92e32017-08-21 07:05:03 -07004916 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07004917
4918 self.assertEqual(1000, dms[0].ses_num)
4919
Matus Fabian2f2db1c2017-04-18 05:29:59 -07004920 # verify IPFIX logging
4921 self.vapi.cli("ipfix flush") # FIXME this should be an API call
Matus Fabian7c0aecc2017-07-03 01:21:38 -07004922 sleep(1)
Matus Fabian2f2db1c2017-04-18 05:29:59 -07004923 capture = self.pg2.get_capture(2)
4924 ipfix = IPFIXDecoder()
4925 # first load template
4926 for p in capture:
4927 self.assertTrue(p.haslayer(IPFIX))
4928 if p.haslayer(Template):
4929 ipfix.add_template(p.getlayer(Template))
4930 # verify events in data set
4931 for p in capture:
4932 if p.haslayer(Data):
4933 data = ipfix.decode_data_set(p.getlayer(Set))
4934 self.verify_ipfix_max_entries_per_user(data)
4935
Matus Fabian2ba92e32017-08-21 07:05:03 -07004936 def clear_nat_det(self):
Martin17a75cb2017-03-08 05:53:20 -08004937 """
Matus Fabian2ba92e32017-08-21 07:05:03 -07004938 Clear deterministic NAT configuration.
Martin17a75cb2017-03-08 05:53:20 -08004939 """
Matus Fabian2ba92e32017-08-21 07:05:03 -07004940 self.vapi.nat_ipfix(enable=0)
4941 self.vapi.nat_det_set_timeouts()
4942 deterministic_mappings = self.vapi.nat_det_map_dump()
Martin17a75cb2017-03-08 05:53:20 -08004943 for dsm in deterministic_mappings:
Matus Fabian2ba92e32017-08-21 07:05:03 -07004944 self.vapi.nat_det_add_del_map(dsm.in_addr,
4945 dsm.in_plen,
4946 dsm.out_addr,
4947 dsm.out_plen,
4948 is_add=0)
Martin17a75cb2017-03-08 05:53:20 -08004949
Matus Fabian2ba92e32017-08-21 07:05:03 -07004950 interfaces = self.vapi.nat44_interface_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07004951 for intf in interfaces:
Matus Fabian2ba92e32017-08-21 07:05:03 -07004952 self.vapi.nat44_interface_add_del_feature(intf.sw_if_index,
4953 intf.is_inside,
4954 is_add=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07004955
Matus Fabian066f0342017-02-10 03:48:01 -08004956 def tearDown(self):
4957 super(TestDeterministicNAT, self).tearDown()
4958 if not self.vpp_dead:
Matus Fabian82119542018-01-25 01:13:22 -08004959 self.logger.info(self.vapi.cli("show nat44 interfaces"))
4960 self.logger.info(
4961 self.vapi.cli("show nat44 deterministic mappings"))
4962 self.logger.info(
4963 self.vapi.cli("show nat44 deterministic timeouts"))
4964 self.logger.info(
4965 self.vapi.cli("show nat44 deterministic sessions"))
Matus Fabian2ba92e32017-08-21 07:05:03 -07004966 self.clear_nat_det()
Matus Fabian066f0342017-02-10 03:48:01 -08004967
Matus Fabian06596c52017-06-06 04:53:28 -07004968
4969class TestNAT64(MethodHolder):
4970 """ NAT64 Test Cases """
4971
4972 @classmethod
Matus Fabiana431ad12018-01-04 04:03:14 -08004973 def setUpConstants(cls):
4974 super(TestNAT64, cls).setUpConstants()
4975 cls.vpp_cmdline.extend(["nat", "{", "nat64 bib hash buckets 128",
4976 "nat64 st hash buckets 256", "}"])
4977
4978 @classmethod
Matus Fabian06596c52017-06-06 04:53:28 -07004979 def setUpClass(cls):
4980 super(TestNAT64, cls).setUpClass()
4981
4982 try:
4983 cls.tcp_port_in = 6303
4984 cls.tcp_port_out = 6303
4985 cls.udp_port_in = 6304
4986 cls.udp_port_out = 6304
4987 cls.icmp_id_in = 6305
4988 cls.icmp_id_out = 6305
4989 cls.nat_addr = '10.0.0.3'
4990 cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
Matus Fabian029f3d22017-06-15 02:28:50 -07004991 cls.vrf1_id = 10
4992 cls.vrf1_nat_addr = '10.0.10.3'
4993 cls.vrf1_nat_addr_n = socket.inet_pton(socket.AF_INET,
4994 cls.vrf1_nat_addr)
Matus Fabiana431ad12018-01-04 04:03:14 -08004995 cls.ipfix_src_port = 4739
4996 cls.ipfix_domain_id = 1
Matus Fabian06596c52017-06-06 04:53:28 -07004997
Matus Fabian0938dcf2017-11-08 01:59:38 -08004998 cls.create_pg_interfaces(range(5))
Matus Fabian06596c52017-06-06 04:53:28 -07004999 cls.ip6_interfaces = list(cls.pg_interfaces[0:1])
Matus Fabian029f3d22017-06-15 02:28:50 -07005000 cls.ip6_interfaces.append(cls.pg_interfaces[2])
Matus Fabian06596c52017-06-06 04:53:28 -07005001 cls.ip4_interfaces = list(cls.pg_interfaces[1:2])
5002
Neale Ranns15002542017-09-10 04:39:11 -07005003 cls.vapi.ip_table_add_del(cls.vrf1_id, is_add=1, is_ipv6=1)
5004
Matus Fabian029f3d22017-06-15 02:28:50 -07005005 cls.pg_interfaces[2].set_table_ip6(cls.vrf1_id)
5006
5007 cls.pg0.generate_remote_hosts(2)
5008
Matus Fabian06596c52017-06-06 04:53:28 -07005009 for i in cls.ip6_interfaces:
5010 i.admin_up()
5011 i.config_ip6()
Matus Fabian029f3d22017-06-15 02:28:50 -07005012 i.configure_ipv6_neighbors()
Matus Fabian06596c52017-06-06 04:53:28 -07005013
5014 for i in cls.ip4_interfaces:
5015 i.admin_up()
5016 i.config_ip4()
5017 i.resolve_arp()
5018
Matus Fabian36ea2d62017-10-24 04:13:49 -07005019 cls.pg3.admin_up()
5020 cls.pg3.config_ip4()
5021 cls.pg3.resolve_arp()
5022 cls.pg3.config_ip6()
5023 cls.pg3.configure_ipv6_neighbors()
5024
Matus Fabian06596c52017-06-06 04:53:28 -07005025 except Exception:
5026 super(TestNAT64, cls).tearDownClass()
5027 raise
5028
5029 def test_pool(self):
5030 """ Add/delete address to NAT64 pool """
5031 nat_addr = socket.inet_pton(socket.AF_INET, '1.2.3.4')
5032
5033 self.vapi.nat64_add_del_pool_addr_range(nat_addr, nat_addr)
5034
5035 addresses = self.vapi.nat64_pool_addr_dump()
5036 self.assertEqual(len(addresses), 1)
5037 self.assertEqual(addresses[0].address, nat_addr)
5038
5039 self.vapi.nat64_add_del_pool_addr_range(nat_addr, nat_addr, is_add=0)
5040
5041 addresses = self.vapi.nat64_pool_addr_dump()
5042 self.assertEqual(len(addresses), 0)
5043
5044 def test_interface(self):
5045 """ Enable/disable NAT64 feature on the interface """
5046 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
5047 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
5048
5049 interfaces = self.vapi.nat64_interface_dump()
5050 self.assertEqual(len(interfaces), 2)
5051 pg0_found = False
5052 pg1_found = False
5053 for intf in interfaces:
5054 if intf.sw_if_index == self.pg0.sw_if_index:
5055 self.assertEqual(intf.is_inside, 1)
5056 pg0_found = True
5057 elif intf.sw_if_index == self.pg1.sw_if_index:
5058 self.assertEqual(intf.is_inside, 0)
5059 pg1_found = True
5060 self.assertTrue(pg0_found)
5061 self.assertTrue(pg1_found)
5062
5063 features = self.vapi.cli("show interface features pg0")
5064 self.assertNotEqual(features.find('nat64-in2out'), -1)
5065 features = self.vapi.cli("show interface features pg1")
5066 self.assertNotEqual(features.find('nat64-out2in'), -1)
5067
5068 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index, is_add=0)
5069 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_add=0)
5070
5071 interfaces = self.vapi.nat64_interface_dump()
5072 self.assertEqual(len(interfaces), 0)
5073
5074 def test_static_bib(self):
5075 """ Add/delete static BIB entry """
5076 in_addr = socket.inet_pton(socket.AF_INET6,
5077 '2001:db8:85a3::8a2e:370:7334')
5078 out_addr = socket.inet_pton(socket.AF_INET, '10.1.1.3')
5079 in_port = 1234
5080 out_port = 5678
5081 proto = IP_PROTOS.tcp
5082
5083 self.vapi.nat64_add_del_static_bib(in_addr,
5084 out_addr,
5085 in_port,
5086 out_port,
5087 proto)
5088 bib = self.vapi.nat64_bib_dump(IP_PROTOS.tcp)
5089 static_bib_num = 0
5090 for bibe in bib:
5091 if bibe.is_static:
5092 static_bib_num += 1
5093 self.assertEqual(bibe.i_addr, in_addr)
5094 self.assertEqual(bibe.o_addr, out_addr)
5095 self.assertEqual(bibe.i_port, in_port)
5096 self.assertEqual(bibe.o_port, out_port)
5097 self.assertEqual(static_bib_num, 1)
5098
5099 self.vapi.nat64_add_del_static_bib(in_addr,
5100 out_addr,
5101 in_port,
5102 out_port,
5103 proto,
5104 is_add=0)
5105 bib = self.vapi.nat64_bib_dump(IP_PROTOS.tcp)
5106 static_bib_num = 0
5107 for bibe in bib:
5108 if bibe.is_static:
5109 static_bib_num += 1
5110 self.assertEqual(static_bib_num, 0)
5111
5112 def test_set_timeouts(self):
5113 """ Set NAT64 timeouts """
5114 # verify default values
5115 timeouts = self.vapi.nat64_get_timeouts()
5116 self.assertEqual(timeouts.udp, 300)
5117 self.assertEqual(timeouts.icmp, 60)
5118 self.assertEqual(timeouts.tcp_trans, 240)
5119 self.assertEqual(timeouts.tcp_est, 7440)
5120 self.assertEqual(timeouts.tcp_incoming_syn, 6)
5121
5122 # set and verify custom values
5123 self.vapi.nat64_set_timeouts(udp=200, icmp=30, tcp_trans=250,
5124 tcp_est=7450, tcp_incoming_syn=10)
5125 timeouts = self.vapi.nat64_get_timeouts()
5126 self.assertEqual(timeouts.udp, 200)
5127 self.assertEqual(timeouts.icmp, 30)
5128 self.assertEqual(timeouts.tcp_trans, 250)
5129 self.assertEqual(timeouts.tcp_est, 7450)
5130 self.assertEqual(timeouts.tcp_incoming_syn, 10)
5131
5132 def test_dynamic(self):
5133 """ NAT64 dynamic translation test """
5134 self.tcp_port_in = 6303
5135 self.udp_port_in = 6304
5136 self.icmp_id_in = 6305
5137
5138 ses_num_start = self.nat64_get_ses_num()
5139
5140 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
5141 self.nat_addr_n)
5142 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
5143 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
5144
5145 # in2out
5146 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
5147 self.pg0.add_stream(pkts)
5148 self.pg_enable_capture(self.pg_interfaces)
5149 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07005150 capture = self.pg1.get_capture(len(pkts))
5151 self.verify_capture_out(capture, nat_ip=self.nat_addr,
Matus Fabian06596c52017-06-06 04:53:28 -07005152 dst_ip=self.pg1.remote_ip4)
5153
5154 # out2in
5155 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
5156 self.pg1.add_stream(pkts)
5157 self.pg_enable_capture(self.pg_interfaces)
5158 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07005159 capture = self.pg0.get_capture(len(pkts))
Matus Fabian06596c52017-06-06 04:53:28 -07005160 ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
5161 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
5162
5163 # in2out
5164 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
5165 self.pg0.add_stream(pkts)
5166 self.pg_enable_capture(self.pg_interfaces)
5167 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07005168 capture = self.pg1.get_capture(len(pkts))
5169 self.verify_capture_out(capture, nat_ip=self.nat_addr,
Matus Fabian06596c52017-06-06 04:53:28 -07005170 dst_ip=self.pg1.remote_ip4)
5171
5172 # out2in
5173 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
5174 self.pg1.add_stream(pkts)
5175 self.pg_enable_capture(self.pg_interfaces)
5176 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07005177 capture = self.pg0.get_capture(len(pkts))
Matus Fabian06596c52017-06-06 04:53:28 -07005178 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
5179
5180 ses_num_end = self.nat64_get_ses_num()
5181
5182 self.assertEqual(ses_num_end - ses_num_start, 3)
5183
Matus Fabian029f3d22017-06-15 02:28:50 -07005184 # tenant with specific VRF
5185 self.vapi.nat64_add_del_pool_addr_range(self.vrf1_nat_addr_n,
5186 self.vrf1_nat_addr_n,
5187 vrf_id=self.vrf1_id)
5188 self.vapi.nat64_add_del_interface(self.pg2.sw_if_index)
5189
5190 pkts = self.create_stream_in_ip6(self.pg2, self.pg1)
5191 self.pg2.add_stream(pkts)
5192 self.pg_enable_capture(self.pg_interfaces)
5193 self.pg_start()
5194 capture = self.pg1.get_capture(len(pkts))
5195 self.verify_capture_out(capture, nat_ip=self.vrf1_nat_addr,
5196 dst_ip=self.pg1.remote_ip4)
5197
5198 pkts = self.create_stream_out(self.pg1, dst_ip=self.vrf1_nat_addr)
5199 self.pg1.add_stream(pkts)
5200 self.pg_enable_capture(self.pg_interfaces)
5201 self.pg_start()
5202 capture = self.pg2.get_capture(len(pkts))
5203 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg2.remote_ip6)
5204
Matus Fabian06596c52017-06-06 04:53:28 -07005205 def test_static(self):
5206 """ NAT64 static translation test """
5207 self.tcp_port_in = 60303
5208 self.udp_port_in = 60304
5209 self.icmp_id_in = 60305
5210 self.tcp_port_out = 60303
5211 self.udp_port_out = 60304
5212 self.icmp_id_out = 60305
5213
5214 ses_num_start = self.nat64_get_ses_num()
5215
5216 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
5217 self.nat_addr_n)
5218 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
5219 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
5220
5221 self.vapi.nat64_add_del_static_bib(self.pg0.remote_ip6n,
5222 self.nat_addr_n,
5223 self.tcp_port_in,
5224 self.tcp_port_out,
5225 IP_PROTOS.tcp)
5226 self.vapi.nat64_add_del_static_bib(self.pg0.remote_ip6n,
5227 self.nat_addr_n,
5228 self.udp_port_in,
5229 self.udp_port_out,
5230 IP_PROTOS.udp)
5231 self.vapi.nat64_add_del_static_bib(self.pg0.remote_ip6n,
5232 self.nat_addr_n,
5233 self.icmp_id_in,
5234 self.icmp_id_out,
5235 IP_PROTOS.icmp)
5236
5237 # in2out
5238 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
5239 self.pg0.add_stream(pkts)
5240 self.pg_enable_capture(self.pg_interfaces)
5241 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07005242 capture = self.pg1.get_capture(len(pkts))
5243 self.verify_capture_out(capture, nat_ip=self.nat_addr,
Matus Fabian06596c52017-06-06 04:53:28 -07005244 dst_ip=self.pg1.remote_ip4, same_port=True)
5245
5246 # out2in
5247 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
5248 self.pg1.add_stream(pkts)
5249 self.pg_enable_capture(self.pg_interfaces)
5250 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07005251 capture = self.pg0.get_capture(len(pkts))
Matus Fabian06596c52017-06-06 04:53:28 -07005252 ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
5253 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
5254
5255 ses_num_end = self.nat64_get_ses_num()
5256
5257 self.assertEqual(ses_num_end - ses_num_start, 3)
5258
5259 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
5260 def test_session_timeout(self):
5261 """ NAT64 session timeout """
5262 self.icmp_id_in = 1234
5263 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
5264 self.nat_addr_n)
5265 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
5266 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
5267 self.vapi.nat64_set_timeouts(icmp=5)
5268
5269 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
5270 self.pg0.add_stream(pkts)
5271 self.pg_enable_capture(self.pg_interfaces)
5272 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07005273 capture = self.pg1.get_capture(len(pkts))
Matus Fabian06596c52017-06-06 04:53:28 -07005274
5275 ses_num_before_timeout = self.nat64_get_ses_num()
5276
5277 sleep(15)
5278
5279 # ICMP session after timeout
5280 ses_num_after_timeout = self.nat64_get_ses_num()
5281 self.assertNotEqual(ses_num_before_timeout, ses_num_after_timeout)
5282
Matus Fabian732036d2017-06-08 05:24:28 -07005283 def test_icmp_error(self):
5284 """ NAT64 ICMP Error message translation """
5285 self.tcp_port_in = 6303
5286 self.udp_port_in = 6304
5287 self.icmp_id_in = 6305
5288
Matus Fabian732036d2017-06-08 05:24:28 -07005289 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
5290 self.nat_addr_n)
5291 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
5292 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
5293
5294 # send some packets to create sessions
5295 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
5296 self.pg0.add_stream(pkts)
5297 self.pg_enable_capture(self.pg_interfaces)
5298 self.pg_start()
5299 capture_ip4 = self.pg1.get_capture(len(pkts))
Matus Fabian029f3d22017-06-15 02:28:50 -07005300 self.verify_capture_out(capture_ip4,
Matus Fabian732036d2017-06-08 05:24:28 -07005301 nat_ip=self.nat_addr,
5302 dst_ip=self.pg1.remote_ip4)
5303
5304 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
5305 self.pg1.add_stream(pkts)
5306 self.pg_enable_capture(self.pg_interfaces)
5307 self.pg_start()
5308 capture_ip6 = self.pg0.get_capture(len(pkts))
5309 ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
5310 self.verify_capture_in_ip6(capture_ip6, ip[IPv6].src,
5311 self.pg0.remote_ip6)
5312
5313 # in2out
5314 pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5315 IPv6(src=self.pg0.remote_ip6, dst=ip[IPv6].src) /
5316 ICMPv6DestUnreach(code=1) /
5317 packet[IPv6] for packet in capture_ip6]
5318 self.pg0.add_stream(pkts)
5319 self.pg_enable_capture(self.pg_interfaces)
5320 self.pg_start()
5321 capture = self.pg1.get_capture(len(pkts))
5322 for packet in capture:
5323 try:
5324 self.assertEqual(packet[IP].src, self.nat_addr)
5325 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
5326 self.assertEqual(packet[ICMP].type, 3)
5327 self.assertEqual(packet[ICMP].code, 13)
5328 inner = packet[IPerror]
5329 self.assertEqual(inner.src, self.pg1.remote_ip4)
5330 self.assertEqual(inner.dst, self.nat_addr)
Klement Sekerad81ae412018-05-16 10:52:54 +02005331 self.assert_packet_checksums_valid(packet)
Matus Fabian732036d2017-06-08 05:24:28 -07005332 if inner.haslayer(TCPerror):
5333 self.assertEqual(inner[TCPerror].dport, self.tcp_port_out)
5334 elif inner.haslayer(UDPerror):
5335 self.assertEqual(inner[UDPerror].dport, self.udp_port_out)
5336 else:
5337 self.assertEqual(inner[ICMPerror].id, self.icmp_id_out)
5338 except:
5339 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5340 raise
5341
5342 # out2in
5343 pkts = [Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
5344 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5345 ICMP(type=3, code=13) /
5346 packet[IP] for packet in capture_ip4]
5347 self.pg1.add_stream(pkts)
5348 self.pg_enable_capture(self.pg_interfaces)
5349 self.pg_start()
5350 capture = self.pg0.get_capture(len(pkts))
5351 for packet in capture:
5352 try:
5353 self.assertEqual(packet[IPv6].src, ip.src)
5354 self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
5355 icmp = packet[ICMPv6DestUnreach]
5356 self.assertEqual(icmp.code, 1)
5357 inner = icmp[IPerror6]
5358 self.assertEqual(inner.src, self.pg0.remote_ip6)
5359 self.assertEqual(inner.dst, ip.src)
Klement Sekerad81ae412018-05-16 10:52:54 +02005360 self.assert_icmpv6_checksum_valid(packet)
Matus Fabian732036d2017-06-08 05:24:28 -07005361 if inner.haslayer(TCPerror):
5362 self.assertEqual(inner[TCPerror].sport, self.tcp_port_in)
5363 elif inner.haslayer(UDPerror):
5364 self.assertEqual(inner[UDPerror].sport, self.udp_port_in)
5365 else:
5366 self.assertEqual(inner[ICMPv6EchoRequest].id,
5367 self.icmp_id_in)
5368 except:
5369 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5370 raise
5371
Matus Fabian029f3d22017-06-15 02:28:50 -07005372 def test_hairpinning(self):
5373 """ NAT64 hairpinning """
5374
5375 client = self.pg0.remote_hosts[0]
5376 server = self.pg0.remote_hosts[1]
5377 server_tcp_in_port = 22
5378 server_tcp_out_port = 4022
5379 server_udp_in_port = 23
5380 server_udp_out_port = 4023
5381 client_tcp_in_port = 1234
5382 client_udp_in_port = 1235
5383 client_tcp_out_port = 0
5384 client_udp_out_port = 0
5385 ip = IPv6(src=''.join(['64:ff9b::', self.nat_addr]))
5386 nat_addr_ip6 = ip.src
5387
5388 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
5389 self.nat_addr_n)
5390 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
5391 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
5392
5393 self.vapi.nat64_add_del_static_bib(server.ip6n,
5394 self.nat_addr_n,
5395 server_tcp_in_port,
5396 server_tcp_out_port,
5397 IP_PROTOS.tcp)
5398 self.vapi.nat64_add_del_static_bib(server.ip6n,
5399 self.nat_addr_n,
5400 server_udp_in_port,
5401 server_udp_out_port,
5402 IP_PROTOS.udp)
5403
5404 # client to server
5405 pkts = []
5406 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5407 IPv6(src=client.ip6, dst=nat_addr_ip6) /
5408 TCP(sport=client_tcp_in_port, dport=server_tcp_out_port))
5409 pkts.append(p)
5410 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5411 IPv6(src=client.ip6, dst=nat_addr_ip6) /
5412 UDP(sport=client_udp_in_port, dport=server_udp_out_port))
5413 pkts.append(p)
5414 self.pg0.add_stream(pkts)
5415 self.pg_enable_capture(self.pg_interfaces)
5416 self.pg_start()
5417 capture = self.pg0.get_capture(len(pkts))
5418 for packet in capture:
5419 try:
5420 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
5421 self.assertEqual(packet[IPv6].dst, server.ip6)
Klement Sekerad81ae412018-05-16 10:52:54 +02005422 self.assert_packet_checksums_valid(packet)
Matus Fabian029f3d22017-06-15 02:28:50 -07005423 if packet.haslayer(TCP):
5424 self.assertNotEqual(packet[TCP].sport, client_tcp_in_port)
5425 self.assertEqual(packet[TCP].dport, server_tcp_in_port)
Matus Fabian029f3d22017-06-15 02:28:50 -07005426 client_tcp_out_port = packet[TCP].sport
5427 else:
5428 self.assertNotEqual(packet[UDP].sport, client_udp_in_port)
5429 self.assertEqual(packet[UDP].dport, server_udp_in_port)
Matus Fabian029f3d22017-06-15 02:28:50 -07005430 client_udp_out_port = packet[UDP].sport
5431 except:
5432 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5433 raise
5434
5435 # server to client
5436 pkts = []
5437 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5438 IPv6(src=server.ip6, dst=nat_addr_ip6) /
5439 TCP(sport=server_tcp_in_port, dport=client_tcp_out_port))
5440 pkts.append(p)
5441 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5442 IPv6(src=server.ip6, dst=nat_addr_ip6) /
5443 UDP(sport=server_udp_in_port, dport=client_udp_out_port))
5444 pkts.append(p)
5445 self.pg0.add_stream(pkts)
5446 self.pg_enable_capture(self.pg_interfaces)
5447 self.pg_start()
5448 capture = self.pg0.get_capture(len(pkts))
5449 for packet in capture:
5450 try:
5451 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
5452 self.assertEqual(packet[IPv6].dst, client.ip6)
Klement Sekerad81ae412018-05-16 10:52:54 +02005453 self.assert_packet_checksums_valid(packet)
Matus Fabian029f3d22017-06-15 02:28:50 -07005454 if packet.haslayer(TCP):
5455 self.assertEqual(packet[TCP].sport, server_tcp_out_port)
5456 self.assertEqual(packet[TCP].dport, client_tcp_in_port)
Matus Fabian029f3d22017-06-15 02:28:50 -07005457 else:
5458 self.assertEqual(packet[UDP].sport, server_udp_out_port)
5459 self.assertEqual(packet[UDP].dport, client_udp_in_port)
Matus Fabian029f3d22017-06-15 02:28:50 -07005460 except:
5461 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5462 raise
5463
5464 # ICMP error
5465 pkts = []
5466 pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5467 IPv6(src=client.ip6, dst=nat_addr_ip6) /
5468 ICMPv6DestUnreach(code=1) /
5469 packet[IPv6] for packet in capture]
5470 self.pg0.add_stream(pkts)
5471 self.pg_enable_capture(self.pg_interfaces)
5472 self.pg_start()
5473 capture = self.pg0.get_capture(len(pkts))
5474 for packet in capture:
5475 try:
5476 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
5477 self.assertEqual(packet[IPv6].dst, server.ip6)
5478 icmp = packet[ICMPv6DestUnreach]
5479 self.assertEqual(icmp.code, 1)
5480 inner = icmp[IPerror6]
5481 self.assertEqual(inner.src, server.ip6)
5482 self.assertEqual(inner.dst, nat_addr_ip6)
Klement Sekerad81ae412018-05-16 10:52:54 +02005483 self.assert_packet_checksums_valid(packet)
Matus Fabian029f3d22017-06-15 02:28:50 -07005484 if inner.haslayer(TCPerror):
5485 self.assertEqual(inner[TCPerror].sport, server_tcp_in_port)
5486 self.assertEqual(inner[TCPerror].dport,
5487 client_tcp_out_port)
5488 else:
5489 self.assertEqual(inner[UDPerror].sport, server_udp_in_port)
5490 self.assertEqual(inner[UDPerror].dport,
5491 client_udp_out_port)
5492 except:
5493 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5494 raise
5495
Matus Fabian428dc912017-06-21 06:15:18 -07005496 def test_prefix(self):
5497 """ NAT64 Network-Specific Prefix """
5498
5499 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
5500 self.nat_addr_n)
5501 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
5502 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
5503 self.vapi.nat64_add_del_pool_addr_range(self.vrf1_nat_addr_n,
5504 self.vrf1_nat_addr_n,
5505 vrf_id=self.vrf1_id)
5506 self.vapi.nat64_add_del_interface(self.pg2.sw_if_index)
5507
5508 # Add global prefix
5509 global_pref64 = "2001:db8::"
5510 global_pref64_n = socket.inet_pton(socket.AF_INET6, global_pref64)
5511 global_pref64_len = 32
5512 self.vapi.nat64_add_del_prefix(global_pref64_n, global_pref64_len)
5513
5514 prefix = self.vapi.nat64_prefix_dump()
5515 self.assertEqual(len(prefix), 1)
5516 self.assertEqual(prefix[0].prefix, global_pref64_n)
5517 self.assertEqual(prefix[0].prefix_len, global_pref64_len)
5518 self.assertEqual(prefix[0].vrf_id, 0)
5519
5520 # Add tenant specific prefix
5521 vrf1_pref64 = "2001:db8:122:300::"
5522 vrf1_pref64_n = socket.inet_pton(socket.AF_INET6, vrf1_pref64)
5523 vrf1_pref64_len = 56
5524 self.vapi.nat64_add_del_prefix(vrf1_pref64_n,
5525 vrf1_pref64_len,
5526 vrf_id=self.vrf1_id)
5527 prefix = self.vapi.nat64_prefix_dump()
5528 self.assertEqual(len(prefix), 2)
5529
5530 # Global prefix
5531 pkts = self.create_stream_in_ip6(self.pg0,
5532 self.pg1,
5533 pref=global_pref64,
5534 plen=global_pref64_len)
5535 self.pg0.add_stream(pkts)
5536 self.pg_enable_capture(self.pg_interfaces)
5537 self.pg_start()
5538 capture = self.pg1.get_capture(len(pkts))
5539 self.verify_capture_out(capture, nat_ip=self.nat_addr,
5540 dst_ip=self.pg1.remote_ip4)
5541
5542 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
5543 self.pg1.add_stream(pkts)
5544 self.pg_enable_capture(self.pg_interfaces)
5545 self.pg_start()
5546 capture = self.pg0.get_capture(len(pkts))
5547 dst_ip = self.compose_ip6(self.pg1.remote_ip4,
5548 global_pref64,
5549 global_pref64_len)
5550 self.verify_capture_in_ip6(capture, dst_ip, self.pg0.remote_ip6)
5551
5552 # Tenant specific prefix
5553 pkts = self.create_stream_in_ip6(self.pg2,
5554 self.pg1,
5555 pref=vrf1_pref64,
5556 plen=vrf1_pref64_len)
5557 self.pg2.add_stream(pkts)
5558 self.pg_enable_capture(self.pg_interfaces)
5559 self.pg_start()
5560 capture = self.pg1.get_capture(len(pkts))
5561 self.verify_capture_out(capture, nat_ip=self.vrf1_nat_addr,
5562 dst_ip=self.pg1.remote_ip4)
5563
5564 pkts = self.create_stream_out(self.pg1, dst_ip=self.vrf1_nat_addr)
5565 self.pg1.add_stream(pkts)
5566 self.pg_enable_capture(self.pg_interfaces)
5567 self.pg_start()
5568 capture = self.pg2.get_capture(len(pkts))
5569 dst_ip = self.compose_ip6(self.pg1.remote_ip4,
5570 vrf1_pref64,
5571 vrf1_pref64_len)
5572 self.verify_capture_in_ip6(capture, dst_ip, self.pg2.remote_ip6)
5573
Matus Fabianf8cd5812017-07-11 03:55:02 -07005574 def test_unknown_proto(self):
Matus Fabian7968e6c2017-07-06 05:37:49 -07005575 """ NAT64 translate packet with unknown protocol """
5576
5577 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
5578 self.nat_addr_n)
5579 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
5580 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
5581 remote_ip6 = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
5582
5583 # in2out
5584 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5585 IPv6(src=self.pg0.remote_ip6, dst=remote_ip6) /
5586 TCP(sport=self.tcp_port_in, dport=20))
5587 self.pg0.add_stream(p)
5588 self.pg_enable_capture(self.pg_interfaces)
5589 self.pg_start()
5590 p = self.pg1.get_capture(1)
5591
5592 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabianf8cd5812017-07-11 03:55:02 -07005593 IPv6(src=self.pg0.remote_ip6, dst=remote_ip6, nh=47) /
Matus Fabian7968e6c2017-07-06 05:37:49 -07005594 GRE() /
5595 IP(src=self.pg2.local_ip4, dst=self.pg2.remote_ip4) /
5596 TCP(sport=1234, dport=1234))
5597 self.pg0.add_stream(p)
5598 self.pg_enable_capture(self.pg_interfaces)
5599 self.pg_start()
5600 p = self.pg1.get_capture(1)
5601 packet = p[0]
5602 try:
5603 self.assertEqual(packet[IP].src, self.nat_addr)
5604 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
5605 self.assertTrue(packet.haslayer(GRE))
Klement Sekerad81ae412018-05-16 10:52:54 +02005606 self.assert_packet_checksums_valid(packet)
Matus Fabian7968e6c2017-07-06 05:37:49 -07005607 except:
5608 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5609 raise
5610
5611 # out2in
5612 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
5613 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5614 GRE() /
5615 IP(src=self.pg2.remote_ip4, dst=self.pg2.local_ip4) /
5616 TCP(sport=1234, dport=1234))
5617 self.pg1.add_stream(p)
5618 self.pg_enable_capture(self.pg_interfaces)
5619 self.pg_start()
5620 p = self.pg0.get_capture(1)
5621 packet = p[0]
5622 try:
5623 self.assertEqual(packet[IPv6].src, remote_ip6)
Matus Fabianf8cd5812017-07-11 03:55:02 -07005624 self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
5625 self.assertEqual(packet[IPv6].nh, 47)
Matus Fabian7968e6c2017-07-06 05:37:49 -07005626 except:
5627 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5628 raise
5629
Matus Fabianf8cd5812017-07-11 03:55:02 -07005630 def test_hairpinning_unknown_proto(self):
Matus Fabian7968e6c2017-07-06 05:37:49 -07005631 """ NAT64 translate packet with unknown protocol - hairpinning """
5632
5633 client = self.pg0.remote_hosts[0]
5634 server = self.pg0.remote_hosts[1]
5635 server_tcp_in_port = 22
5636 server_tcp_out_port = 4022
5637 client_tcp_in_port = 1234
Matus Fabianf8cd5812017-07-11 03:55:02 -07005638 client_tcp_out_port = 1235
5639 server_nat_ip = "10.0.0.100"
5640 client_nat_ip = "10.0.0.110"
5641 server_nat_ip_n = socket.inet_pton(socket.AF_INET, server_nat_ip)
5642 client_nat_ip_n = socket.inet_pton(socket.AF_INET, client_nat_ip)
5643 server_nat_ip6 = self.compose_ip6(server_nat_ip, '64:ff9b::', 96)
5644 client_nat_ip6 = self.compose_ip6(client_nat_ip, '64:ff9b::', 96)
Matus Fabian7968e6c2017-07-06 05:37:49 -07005645
Matus Fabianf8cd5812017-07-11 03:55:02 -07005646 self.vapi.nat64_add_del_pool_addr_range(server_nat_ip_n,
5647 client_nat_ip_n)
Matus Fabian7968e6c2017-07-06 05:37:49 -07005648 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
5649 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
5650
5651 self.vapi.nat64_add_del_static_bib(server.ip6n,
Matus Fabianf8cd5812017-07-11 03:55:02 -07005652 server_nat_ip_n,
Matus Fabian7968e6c2017-07-06 05:37:49 -07005653 server_tcp_in_port,
5654 server_tcp_out_port,
5655 IP_PROTOS.tcp)
5656
Matus Fabianf8cd5812017-07-11 03:55:02 -07005657 self.vapi.nat64_add_del_static_bib(server.ip6n,
5658 server_nat_ip_n,
5659 0,
5660 0,
5661 IP_PROTOS.gre)
5662
5663 self.vapi.nat64_add_del_static_bib(client.ip6n,
5664 client_nat_ip_n,
5665 client_tcp_in_port,
5666 client_tcp_out_port,
5667 IP_PROTOS.tcp)
5668
Matus Fabian7968e6c2017-07-06 05:37:49 -07005669 # client to server
5670 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabianf8cd5812017-07-11 03:55:02 -07005671 IPv6(src=client.ip6, dst=server_nat_ip6) /
Matus Fabian7968e6c2017-07-06 05:37:49 -07005672 TCP(sport=client_tcp_in_port, dport=server_tcp_out_port))
5673 self.pg0.add_stream(p)
5674 self.pg_enable_capture(self.pg_interfaces)
5675 self.pg_start()
5676 p = self.pg0.get_capture(1)
5677
5678 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabianf8cd5812017-07-11 03:55:02 -07005679 IPv6(src=client.ip6, dst=server_nat_ip6, nh=IP_PROTOS.gre) /
Matus Fabian7968e6c2017-07-06 05:37:49 -07005680 GRE() /
5681 IP(src=self.pg2.local_ip4, dst=self.pg2.remote_ip4) /
5682 TCP(sport=1234, dport=1234))
5683 self.pg0.add_stream(p)
5684 self.pg_enable_capture(self.pg_interfaces)
5685 self.pg_start()
5686 p = self.pg0.get_capture(1)
5687 packet = p[0]
5688 try:
Matus Fabianf8cd5812017-07-11 03:55:02 -07005689 self.assertEqual(packet[IPv6].src, client_nat_ip6)
Matus Fabian7968e6c2017-07-06 05:37:49 -07005690 self.assertEqual(packet[IPv6].dst, server.ip6)
Matus Fabianf8cd5812017-07-11 03:55:02 -07005691 self.assertEqual(packet[IPv6].nh, IP_PROTOS.gre)
Matus Fabian7968e6c2017-07-06 05:37:49 -07005692 except:
5693 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5694 raise
5695
5696 # server to client
5697 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabianf8cd5812017-07-11 03:55:02 -07005698 IPv6(src=server.ip6, dst=client_nat_ip6, nh=IP_PROTOS.gre) /
Matus Fabian7968e6c2017-07-06 05:37:49 -07005699 GRE() /
5700 IP(src=self.pg2.remote_ip4, dst=self.pg2.local_ip4) /
5701 TCP(sport=1234, dport=1234))
5702 self.pg0.add_stream(p)
5703 self.pg_enable_capture(self.pg_interfaces)
5704 self.pg_start()
5705 p = self.pg0.get_capture(1)
5706 packet = p[0]
5707 try:
Matus Fabianf8cd5812017-07-11 03:55:02 -07005708 self.assertEqual(packet[IPv6].src, server_nat_ip6)
Matus Fabian7968e6c2017-07-06 05:37:49 -07005709 self.assertEqual(packet[IPv6].dst, client.ip6)
Matus Fabianf8cd5812017-07-11 03:55:02 -07005710 self.assertEqual(packet[IPv6].nh, IP_PROTOS.gre)
Matus Fabian7968e6c2017-07-06 05:37:49 -07005711 except:
5712 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5713 raise
5714
Matus Fabian36ea2d62017-10-24 04:13:49 -07005715 def test_one_armed_nat64(self):
5716 """ One armed NAT64 """
5717 external_port = 0
5718 remote_host_ip6 = self.compose_ip6(self.pg3.remote_ip4,
5719 '64:ff9b::',
5720 96)
5721
5722 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
5723 self.nat_addr_n)
5724 self.vapi.nat64_add_del_interface(self.pg3.sw_if_index)
5725 self.vapi.nat64_add_del_interface(self.pg3.sw_if_index, is_inside=0)
5726
5727 # in2out
5728 p = (Ether(src=self.pg3.remote_mac, dst=self.pg3.local_mac) /
5729 IPv6(src=self.pg3.remote_ip6, dst=remote_host_ip6) /
5730 TCP(sport=12345, dport=80))
5731 self.pg3.add_stream(p)
5732 self.pg_enable_capture(self.pg_interfaces)
5733 self.pg_start()
5734 capture = self.pg3.get_capture(1)
5735 p = capture[0]
5736 try:
5737 ip = p[IP]
5738 tcp = p[TCP]
5739 self.assertEqual(ip.src, self.nat_addr)
5740 self.assertEqual(ip.dst, self.pg3.remote_ip4)
5741 self.assertNotEqual(tcp.sport, 12345)
5742 external_port = tcp.sport
5743 self.assertEqual(tcp.dport, 80)
Klement Sekerad81ae412018-05-16 10:52:54 +02005744 self.assert_packet_checksums_valid(p)
Matus Fabian36ea2d62017-10-24 04:13:49 -07005745 except:
5746 self.logger.error(ppp("Unexpected or invalid packet:", p))
5747 raise
5748
5749 # out2in
5750 p = (Ether(src=self.pg3.remote_mac, dst=self.pg3.local_mac) /
5751 IP(src=self.pg3.remote_ip4, dst=self.nat_addr) /
5752 TCP(sport=80, dport=external_port))
5753 self.pg3.add_stream(p)
5754 self.pg_enable_capture(self.pg_interfaces)
5755 self.pg_start()
5756 capture = self.pg3.get_capture(1)
5757 p = capture[0]
5758 try:
5759 ip = p[IPv6]
5760 tcp = p[TCP]
5761 self.assertEqual(ip.src, remote_host_ip6)
5762 self.assertEqual(ip.dst, self.pg3.remote_ip6)
5763 self.assertEqual(tcp.sport, 80)
5764 self.assertEqual(tcp.dport, 12345)
Klement Sekerad81ae412018-05-16 10:52:54 +02005765 self.assert_packet_checksums_valid(p)
Matus Fabian36ea2d62017-10-24 04:13:49 -07005766 except:
5767 self.logger.error(ppp("Unexpected or invalid packet:", p))
5768 raise
5769
Matus Fabianefcd1e92017-08-15 06:59:19 -07005770 def test_frag_in_order(self):
5771 """ NAT64 translate fragments arriving in order """
5772 self.tcp_port_in = random.randint(1025, 65535)
5773
5774 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
5775 self.nat_addr_n)
5776 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
5777 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
5778
5779 reass = self.vapi.nat_reass_dump()
5780 reass_n_start = len(reass)
5781
5782 # in2out
5783 data = 'a' * 200
5784 pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
5785 self.tcp_port_in, 20, data)
5786 self.pg0.add_stream(pkts)
5787 self.pg_enable_capture(self.pg_interfaces)
5788 self.pg_start()
5789 frags = self.pg1.get_capture(len(pkts))
5790 p = self.reass_frags_and_verify(frags,
5791 self.nat_addr,
5792 self.pg1.remote_ip4)
5793 self.assertEqual(p[TCP].dport, 20)
5794 self.assertNotEqual(p[TCP].sport, self.tcp_port_in)
5795 self.tcp_port_out = p[TCP].sport
5796 self.assertEqual(data, p[Raw].load)
5797
5798 # out2in
5799 data = "A" * 4 + "b" * 16 + "C" * 3
5800 pkts = self.create_stream_frag(self.pg1,
5801 self.nat_addr,
5802 20,
5803 self.tcp_port_out,
5804 data)
5805 self.pg1.add_stream(pkts)
5806 self.pg_enable_capture(self.pg_interfaces)
5807 self.pg_start()
5808 frags = self.pg0.get_capture(len(pkts))
5809 src = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
5810 p = self.reass_frags_and_verify_ip6(frags, src, self.pg0.remote_ip6)
5811 self.assertEqual(p[TCP].sport, 20)
5812 self.assertEqual(p[TCP].dport, self.tcp_port_in)
5813 self.assertEqual(data, p[Raw].load)
5814
5815 reass = self.vapi.nat_reass_dump()
5816 reass_n_end = len(reass)
5817
5818 self.assertEqual(reass_n_end - reass_n_start, 2)
5819
5820 def test_reass_hairpinning(self):
5821 """ NAT64 fragments hairpinning """
5822 data = 'a' * 200
Matus Fabianefcd1e92017-08-15 06:59:19 -07005823 server = self.pg0.remote_hosts[1]
5824 server_in_port = random.randint(1025, 65535)
5825 server_out_port = random.randint(1025, 65535)
5826 client_in_port = random.randint(1025, 65535)
5827 ip = IPv6(src=''.join(['64:ff9b::', self.nat_addr]))
5828 nat_addr_ip6 = ip.src
5829
5830 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
5831 self.nat_addr_n)
5832 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
5833 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
5834
5835 # add static BIB entry for server
5836 self.vapi.nat64_add_del_static_bib(server.ip6n,
5837 self.nat_addr_n,
5838 server_in_port,
5839 server_out_port,
5840 IP_PROTOS.tcp)
5841
5842 # send packet from host to server
5843 pkts = self.create_stream_frag_ip6(self.pg0,
5844 self.nat_addr,
5845 client_in_port,
5846 server_out_port,
5847 data)
5848 self.pg0.add_stream(pkts)
5849 self.pg_enable_capture(self.pg_interfaces)
5850 self.pg_start()
5851 frags = self.pg0.get_capture(len(pkts))
5852 p = self.reass_frags_and_verify_ip6(frags, nat_addr_ip6, server.ip6)
5853 self.assertNotEqual(p[TCP].sport, client_in_port)
5854 self.assertEqual(p[TCP].dport, server_in_port)
5855 self.assertEqual(data, p[Raw].load)
5856
5857 def test_frag_out_of_order(self):
5858 """ NAT64 translate fragments arriving out of order """
5859 self.tcp_port_in = random.randint(1025, 65535)
5860
5861 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
5862 self.nat_addr_n)
5863 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
5864 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
5865
5866 # in2out
5867 data = 'a' * 200
5868 pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
5869 self.tcp_port_in, 20, data)
5870 pkts.reverse()
5871 self.pg0.add_stream(pkts)
5872 self.pg_enable_capture(self.pg_interfaces)
5873 self.pg_start()
5874 frags = self.pg1.get_capture(len(pkts))
5875 p = self.reass_frags_and_verify(frags,
5876 self.nat_addr,
5877 self.pg1.remote_ip4)
5878 self.assertEqual(p[TCP].dport, 20)
5879 self.assertNotEqual(p[TCP].sport, self.tcp_port_in)
5880 self.tcp_port_out = p[TCP].sport
5881 self.assertEqual(data, p[Raw].load)
5882
5883 # out2in
5884 data = "A" * 4 + "B" * 16 + "C" * 3
5885 pkts = self.create_stream_frag(self.pg1,
5886 self.nat_addr,
5887 20,
5888 self.tcp_port_out,
5889 data)
5890 pkts.reverse()
5891 self.pg1.add_stream(pkts)
5892 self.pg_enable_capture(self.pg_interfaces)
5893 self.pg_start()
5894 frags = self.pg0.get_capture(len(pkts))
5895 src = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
5896 p = self.reass_frags_and_verify_ip6(frags, src, self.pg0.remote_ip6)
5897 self.assertEqual(p[TCP].sport, 20)
5898 self.assertEqual(p[TCP].dport, self.tcp_port_in)
5899 self.assertEqual(data, p[Raw].load)
5900
Matus Fabian0938dcf2017-11-08 01:59:38 -08005901 def test_interface_addr(self):
5902 """ Acquire NAT64 pool addresses from interface """
5903 self.vapi.nat64_add_interface_addr(self.pg4.sw_if_index)
5904
5905 # no address in NAT64 pool
5906 adresses = self.vapi.nat44_address_dump()
5907 self.assertEqual(0, len(adresses))
5908
5909 # configure interface address and check NAT64 address pool
5910 self.pg4.config_ip4()
5911 addresses = self.vapi.nat64_pool_addr_dump()
5912 self.assertEqual(len(addresses), 1)
5913 self.assertEqual(addresses[0].address, self.pg4.local_ip4n)
5914
5915 # remove interface address and check NAT64 address pool
5916 self.pg4.unconfig_ip4()
5917 addresses = self.vapi.nat64_pool_addr_dump()
5918 self.assertEqual(0, len(adresses))
5919
Matus Fabiana431ad12018-01-04 04:03:14 -08005920 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
5921 def test_ipfix_max_bibs_sessions(self):
5922 """ IPFIX logging maximum session and BIB entries exceeded """
5923 max_bibs = 1280
5924 max_sessions = 2560
5925 remote_host_ip6 = self.compose_ip6(self.pg1.remote_ip4,
5926 '64:ff9b::',
5927 96)
5928
5929 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
5930 self.nat_addr_n)
5931 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
5932 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
5933
5934 pkts = []
5935 src = ""
5936 for i in range(0, max_bibs):
5937 src = "fd01:aa::%x" % (i)
5938 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5939 IPv6(src=src, dst=remote_host_ip6) /
5940 TCP(sport=12345, dport=80))
5941 pkts.append(p)
5942 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5943 IPv6(src=src, dst=remote_host_ip6) /
5944 TCP(sport=12345, dport=22))
5945 pkts.append(p)
5946 self.pg0.add_stream(pkts)
5947 self.pg_enable_capture(self.pg_interfaces)
5948 self.pg_start()
5949 self.pg1.get_capture(max_sessions)
5950
5951 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
5952 src_address=self.pg3.local_ip4n,
5953 path_mtu=512,
5954 template_interval=10)
5955 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
5956 src_port=self.ipfix_src_port)
5957
5958 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5959 IPv6(src=src, dst=remote_host_ip6) /
5960 TCP(sport=12345, dport=25))
5961 self.pg0.add_stream(p)
5962 self.pg_enable_capture(self.pg_interfaces)
5963 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07005964 self.pg1.assert_nothing_captured()
5965 sleep(1)
Matus Fabiana431ad12018-01-04 04:03:14 -08005966 self.vapi.cli("ipfix flush") # FIXME this should be an API call
5967 capture = self.pg3.get_capture(9)
5968 ipfix = IPFIXDecoder()
5969 # first load template
5970 for p in capture:
5971 self.assertTrue(p.haslayer(IPFIX))
5972 self.assertEqual(p[IP].src, self.pg3.local_ip4)
5973 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
5974 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
5975 self.assertEqual(p[UDP].dport, 4739)
5976 self.assertEqual(p[IPFIX].observationDomainID,
5977 self.ipfix_domain_id)
5978 if p.haslayer(Template):
5979 ipfix.add_template(p.getlayer(Template))
5980 # verify events in data set
5981 for p in capture:
5982 if p.haslayer(Data):
5983 data = ipfix.decode_data_set(p.getlayer(Set))
5984 self.verify_ipfix_max_sessions(data, max_sessions)
5985
5986 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5987 IPv6(src=self.pg0.remote_ip6, dst=remote_host_ip6) /
5988 TCP(sport=12345, dport=80))
5989 self.pg0.add_stream(p)
5990 self.pg_enable_capture(self.pg_interfaces)
5991 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07005992 self.pg1.assert_nothing_captured()
5993 sleep(1)
Matus Fabiana431ad12018-01-04 04:03:14 -08005994 self.vapi.cli("ipfix flush") # FIXME this should be an API call
5995 capture = self.pg3.get_capture(1)
5996 # verify events in data set
5997 for p in capture:
5998 self.assertTrue(p.haslayer(IPFIX))
5999 self.assertEqual(p[IP].src, self.pg3.local_ip4)
6000 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
6001 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
6002 self.assertEqual(p[UDP].dport, 4739)
6003 self.assertEqual(p[IPFIX].observationDomainID,
6004 self.ipfix_domain_id)
6005 if p.haslayer(Data):
6006 data = ipfix.decode_data_set(p.getlayer(Set))
6007 self.verify_ipfix_max_bibs(data, max_bibs)
6008
6009 def test_ipfix_max_frags(self):
6010 """ IPFIX logging maximum fragments pending reassembly exceeded """
6011 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6012 self.nat_addr_n)
6013 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6014 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6015 self.vapi.nat_set_reass(max_frag=0, is_ip6=1)
6016 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
6017 src_address=self.pg3.local_ip4n,
6018 path_mtu=512,
6019 template_interval=10)
6020 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
6021 src_port=self.ipfix_src_port)
6022
6023 data = 'a' * 200
6024 pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
6025 self.tcp_port_in, 20, data)
6026 self.pg0.add_stream(pkts[-1])
6027 self.pg_enable_capture(self.pg_interfaces)
6028 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07006029 self.pg1.assert_nothing_captured()
6030 sleep(1)
Matus Fabiana431ad12018-01-04 04:03:14 -08006031 self.vapi.cli("ipfix flush") # FIXME this should be an API call
6032 capture = self.pg3.get_capture(9)
6033 ipfix = IPFIXDecoder()
6034 # first load template
6035 for p in capture:
6036 self.assertTrue(p.haslayer(IPFIX))
6037 self.assertEqual(p[IP].src, self.pg3.local_ip4)
6038 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
6039 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
6040 self.assertEqual(p[UDP].dport, 4739)
6041 self.assertEqual(p[IPFIX].observationDomainID,
6042 self.ipfix_domain_id)
6043 if p.haslayer(Template):
6044 ipfix.add_template(p.getlayer(Template))
6045 # verify events in data set
6046 for p in capture:
6047 if p.haslayer(Data):
6048 data = ipfix.decode_data_set(p.getlayer(Set))
6049 self.verify_ipfix_max_fragments_ip6(data, 0,
6050 self.pg0.remote_ip6n)
6051
6052 def test_ipfix_bib_ses(self):
6053 """ IPFIX logging NAT64 BIB/session create and delete events """
6054 self.tcp_port_in = random.randint(1025, 65535)
6055 remote_host_ip6 = self.compose_ip6(self.pg1.remote_ip4,
6056 '64:ff9b::',
6057 96)
6058
6059 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6060 self.nat_addr_n)
6061 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6062 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6063 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
6064 src_address=self.pg3.local_ip4n,
6065 path_mtu=512,
6066 template_interval=10)
6067 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
6068 src_port=self.ipfix_src_port)
6069
6070 # Create
6071 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6072 IPv6(src=self.pg0.remote_ip6, dst=remote_host_ip6) /
6073 TCP(sport=self.tcp_port_in, dport=25))
6074 self.pg0.add_stream(p)
6075 self.pg_enable_capture(self.pg_interfaces)
6076 self.pg_start()
6077 p = self.pg1.get_capture(1)
6078 self.tcp_port_out = p[0][TCP].sport
6079 self.vapi.cli("ipfix flush") # FIXME this should be an API call
6080 capture = self.pg3.get_capture(10)
6081 ipfix = IPFIXDecoder()
6082 # first load template
6083 for p in capture:
6084 self.assertTrue(p.haslayer(IPFIX))
6085 self.assertEqual(p[IP].src, self.pg3.local_ip4)
6086 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
6087 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
6088 self.assertEqual(p[UDP].dport, 4739)
6089 self.assertEqual(p[IPFIX].observationDomainID,
6090 self.ipfix_domain_id)
6091 if p.haslayer(Template):
6092 ipfix.add_template(p.getlayer(Template))
6093 # verify events in data set
6094 for p in capture:
6095 if p.haslayer(Data):
6096 data = ipfix.decode_data_set(p.getlayer(Set))
6097 if ord(data[0][230]) == 10:
6098 self.verify_ipfix_bib(data, 1, self.pg0.remote_ip6n)
6099 elif ord(data[0][230]) == 6:
6100 self.verify_ipfix_nat64_ses(data,
6101 1,
6102 self.pg0.remote_ip6n,
6103 self.pg1.remote_ip4,
6104 25)
6105 else:
6106 self.logger.error(ppp("Unexpected or invalid packet: ", p))
6107
6108 # Delete
6109 self.pg_enable_capture(self.pg_interfaces)
6110 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6111 self.nat_addr_n,
6112 is_add=0)
6113 self.vapi.cli("ipfix flush") # FIXME this should be an API call
6114 capture = self.pg3.get_capture(2)
6115 # verify events in data set
6116 for p in capture:
6117 self.assertTrue(p.haslayer(IPFIX))
6118 self.assertEqual(p[IP].src, self.pg3.local_ip4)
6119 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
6120 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
6121 self.assertEqual(p[UDP].dport, 4739)
6122 self.assertEqual(p[IPFIX].observationDomainID,
6123 self.ipfix_domain_id)
6124 if p.haslayer(Data):
6125 data = ipfix.decode_data_set(p.getlayer(Set))
6126 if ord(data[0][230]) == 11:
6127 self.verify_ipfix_bib(data, 0, self.pg0.remote_ip6n)
6128 elif ord(data[0][230]) == 7:
6129 self.verify_ipfix_nat64_ses(data,
6130 0,
6131 self.pg0.remote_ip6n,
6132 self.pg1.remote_ip4,
6133 25)
6134 else:
6135 self.logger.error(ppp("Unexpected or invalid packet: ", p))
6136
Matus Fabian06596c52017-06-06 04:53:28 -07006137 def nat64_get_ses_num(self):
6138 """
6139 Return number of active NAT64 sessions.
6140 """
Matus Fabianab9a59c2017-08-16 05:37:36 -07006141 st = self.vapi.nat64_st_dump()
6142 return len(st)
Matus Fabian06596c52017-06-06 04:53:28 -07006143
6144 def clear_nat64(self):
6145 """
6146 Clear NAT64 configuration.
6147 """
Matus Fabiana431ad12018-01-04 04:03:14 -08006148 self.vapi.nat_ipfix(enable=0, src_port=self.ipfix_src_port,
6149 domain_id=self.ipfix_domain_id)
6150 self.ipfix_src_port = 4739
6151 self.ipfix_domain_id = 1
6152
Matus Fabian06596c52017-06-06 04:53:28 -07006153 self.vapi.nat64_set_timeouts()
6154
6155 interfaces = self.vapi.nat64_interface_dump()
6156 for intf in interfaces:
Matus Fabian36ea2d62017-10-24 04:13:49 -07006157 if intf.is_inside > 1:
6158 self.vapi.nat64_add_del_interface(intf.sw_if_index,
6159 0,
6160 is_add=0)
Matus Fabian06596c52017-06-06 04:53:28 -07006161 self.vapi.nat64_add_del_interface(intf.sw_if_index,
6162 intf.is_inside,
6163 is_add=0)
6164
Matus Fabiana431ad12018-01-04 04:03:14 -08006165 bib = self.vapi.nat64_bib_dump(255)
Matus Fabian06596c52017-06-06 04:53:28 -07006166 for bibe in bib:
6167 if bibe.is_static:
6168 self.vapi.nat64_add_del_static_bib(bibe.i_addr,
6169 bibe.o_addr,
6170 bibe.i_port,
6171 bibe.o_port,
6172 bibe.proto,
6173 bibe.vrf_id,
6174 is_add=0)
6175
6176 adresses = self.vapi.nat64_pool_addr_dump()
6177 for addr in adresses:
6178 self.vapi.nat64_add_del_pool_addr_range(addr.address,
6179 addr.address,
Matus Fabian029f3d22017-06-15 02:28:50 -07006180 vrf_id=addr.vrf_id,
Matus Fabian06596c52017-06-06 04:53:28 -07006181 is_add=0)
6182
Matus Fabian428dc912017-06-21 06:15:18 -07006183 prefixes = self.vapi.nat64_prefix_dump()
6184 for prefix in prefixes:
6185 self.vapi.nat64_add_del_prefix(prefix.prefix,
6186 prefix.prefix_len,
6187 vrf_id=prefix.vrf_id,
6188 is_add=0)
6189
Matus Fabian06596c52017-06-06 04:53:28 -07006190 def tearDown(self):
6191 super(TestNAT64, self).tearDown()
6192 if not self.vpp_dead:
6193 self.logger.info(self.vapi.cli("show nat64 pool"))
6194 self.logger.info(self.vapi.cli("show nat64 interfaces"))
Matus Fabian428dc912017-06-21 06:15:18 -07006195 self.logger.info(self.vapi.cli("show nat64 prefix"))
Matus Fabianab9a59c2017-08-16 05:37:36 -07006196 self.logger.info(self.vapi.cli("show nat64 bib all"))
6197 self.logger.info(self.vapi.cli("show nat64 session table all"))
Matus Fabianefcd1e92017-08-15 06:59:19 -07006198 self.logger.info(self.vapi.cli("show nat virtual-reassembly"))
Matus Fabian06596c52017-06-06 04:53:28 -07006199 self.clear_nat64()
6200
Matus Fabian8ebe6252017-11-06 05:04:53 -08006201
6202class TestDSlite(MethodHolder):
6203 """ DS-Lite Test Cases """
6204
6205 @classmethod
6206 def setUpClass(cls):
6207 super(TestDSlite, cls).setUpClass()
6208
6209 try:
6210 cls.nat_addr = '10.0.0.3'
6211 cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
6212
6213 cls.create_pg_interfaces(range(2))
6214 cls.pg0.admin_up()
6215 cls.pg0.config_ip4()
6216 cls.pg0.resolve_arp()
6217 cls.pg1.admin_up()
6218 cls.pg1.config_ip6()
6219 cls.pg1.generate_remote_hosts(2)
6220 cls.pg1.configure_ipv6_neighbors()
6221
6222 except Exception:
6223 super(TestDSlite, cls).tearDownClass()
6224 raise
6225
6226 def test_dslite(self):
6227 """ Test DS-Lite """
6228 self.vapi.dslite_add_del_pool_addr_range(self.nat_addr_n,
6229 self.nat_addr_n)
6230 aftr_ip4 = '192.0.0.1'
6231 aftr_ip4_n = socket.inet_pton(socket.AF_INET, aftr_ip4)
6232 aftr_ip6 = '2001:db8:85a3::8a2e:370:1'
6233 aftr_ip6_n = socket.inet_pton(socket.AF_INET6, aftr_ip6)
6234 self.vapi.dslite_set_aftr_addr(aftr_ip6_n, aftr_ip4_n)
6235
6236 # UDP
6237 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
6238 IPv6(dst=aftr_ip6, src=self.pg1.remote_hosts[0].ip6) /
6239 IP(dst=self.pg0.remote_ip4, src='192.168.1.1') /
6240 UDP(sport=20000, dport=10000))
6241 self.pg1.add_stream(p)
6242 self.pg_enable_capture(self.pg_interfaces)
6243 self.pg_start()
6244 capture = self.pg0.get_capture(1)
6245 capture = capture[0]
6246 self.assertFalse(capture.haslayer(IPv6))
6247 self.assertEqual(capture[IP].src, self.nat_addr)
6248 self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
6249 self.assertNotEqual(capture[UDP].sport, 20000)
6250 self.assertEqual(capture[UDP].dport, 10000)
Klement Sekerad81ae412018-05-16 10:52:54 +02006251 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08006252 out_port = capture[UDP].sport
6253
6254 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6255 IP(dst=self.nat_addr, src=self.pg0.remote_ip4) /
6256 UDP(sport=10000, dport=out_port))
6257 self.pg0.add_stream(p)
6258 self.pg_enable_capture(self.pg_interfaces)
6259 self.pg_start()
6260 capture = self.pg1.get_capture(1)
6261 capture = capture[0]
6262 self.assertEqual(capture[IPv6].src, aftr_ip6)
6263 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[0].ip6)
6264 self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
6265 self.assertEqual(capture[IP].dst, '192.168.1.1')
6266 self.assertEqual(capture[UDP].sport, 10000)
6267 self.assertEqual(capture[UDP].dport, 20000)
Klement Sekerad81ae412018-05-16 10:52:54 +02006268 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08006269
6270 # TCP
6271 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
6272 IPv6(dst=aftr_ip6, src=self.pg1.remote_hosts[1].ip6) /
6273 IP(dst=self.pg0.remote_ip4, src='192.168.1.1') /
6274 TCP(sport=20001, dport=10001))
6275 self.pg1.add_stream(p)
6276 self.pg_enable_capture(self.pg_interfaces)
6277 self.pg_start()
6278 capture = self.pg0.get_capture(1)
6279 capture = capture[0]
6280 self.assertFalse(capture.haslayer(IPv6))
6281 self.assertEqual(capture[IP].src, self.nat_addr)
6282 self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
6283 self.assertNotEqual(capture[TCP].sport, 20001)
6284 self.assertEqual(capture[TCP].dport, 10001)
Klement Sekerad81ae412018-05-16 10:52:54 +02006285 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08006286 out_port = capture[TCP].sport
6287
6288 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6289 IP(dst=self.nat_addr, src=self.pg0.remote_ip4) /
6290 TCP(sport=10001, dport=out_port))
6291 self.pg0.add_stream(p)
6292 self.pg_enable_capture(self.pg_interfaces)
6293 self.pg_start()
6294 capture = self.pg1.get_capture(1)
6295 capture = capture[0]
6296 self.assertEqual(capture[IPv6].src, aftr_ip6)
6297 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[1].ip6)
6298 self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
6299 self.assertEqual(capture[IP].dst, '192.168.1.1')
6300 self.assertEqual(capture[TCP].sport, 10001)
6301 self.assertEqual(capture[TCP].dport, 20001)
Klement Sekerad81ae412018-05-16 10:52:54 +02006302 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08006303
6304 # ICMP
6305 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
6306 IPv6(dst=aftr_ip6, src=self.pg1.remote_hosts[1].ip6) /
6307 IP(dst=self.pg0.remote_ip4, src='192.168.1.1') /
6308 ICMP(id=4000, type='echo-request'))
6309 self.pg1.add_stream(p)
6310 self.pg_enable_capture(self.pg_interfaces)
6311 self.pg_start()
6312 capture = self.pg0.get_capture(1)
6313 capture = capture[0]
6314 self.assertFalse(capture.haslayer(IPv6))
6315 self.assertEqual(capture[IP].src, self.nat_addr)
6316 self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
6317 self.assertNotEqual(capture[ICMP].id, 4000)
Klement Sekerad81ae412018-05-16 10:52:54 +02006318 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08006319 out_id = capture[ICMP].id
6320
6321 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6322 IP(dst=self.nat_addr, src=self.pg0.remote_ip4) /
6323 ICMP(id=out_id, type='echo-reply'))
6324 self.pg0.add_stream(p)
6325 self.pg_enable_capture(self.pg_interfaces)
6326 self.pg_start()
6327 capture = self.pg1.get_capture(1)
6328 capture = capture[0]
6329 self.assertEqual(capture[IPv6].src, aftr_ip6)
6330 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[1].ip6)
6331 self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
6332 self.assertEqual(capture[IP].dst, '192.168.1.1')
6333 self.assertEqual(capture[ICMP].id, 4000)
Klement Sekerad81ae412018-05-16 10:52:54 +02006334 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08006335
Matus Fabian331acc62017-12-08 03:38:51 -08006336 # ping DS-Lite AFTR tunnel endpoint address
6337 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
6338 IPv6(src=self.pg1.remote_hosts[1].ip6, dst=aftr_ip6) /
6339 ICMPv6EchoRequest())
6340 self.pg1.add_stream(p)
6341 self.pg_enable_capture(self.pg_interfaces)
6342 self.pg_start()
6343 capture = self.pg1.get_capture(1)
6344 self.assertEqual(1, len(capture))
6345 capture = capture[0]
6346 self.assertEqual(capture[IPv6].src, aftr_ip6)
6347 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[1].ip6)
6348 self.assertTrue(capture.haslayer(ICMPv6EchoReply))
6349
Matus Fabian8ebe6252017-11-06 05:04:53 -08006350 def tearDown(self):
6351 super(TestDSlite, self).tearDown()
6352 if not self.vpp_dead:
6353 self.logger.info(self.vapi.cli("show dslite pool"))
6354 self.logger.info(
6355 self.vapi.cli("show dslite aftr-tunnel-endpoint-address"))
6356 self.logger.info(self.vapi.cli("show dslite sessions"))
6357
Juraj Slobodac5c6a332018-01-09 16:08:32 +01006358
6359class TestDSliteCE(MethodHolder):
6360 """ DS-Lite CE Test Cases """
6361
6362 @classmethod
6363 def setUpConstants(cls):
6364 super(TestDSliteCE, cls).setUpConstants()
6365 cls.vpp_cmdline.extend(["nat", "{", "dslite ce", "}"])
6366
6367 @classmethod
6368 def setUpClass(cls):
6369 super(TestDSliteCE, cls).setUpClass()
6370
6371 try:
6372 cls.create_pg_interfaces(range(2))
6373 cls.pg0.admin_up()
6374 cls.pg0.config_ip4()
6375 cls.pg0.resolve_arp()
6376 cls.pg1.admin_up()
6377 cls.pg1.config_ip6()
6378 cls.pg1.generate_remote_hosts(1)
6379 cls.pg1.configure_ipv6_neighbors()
6380
6381 except Exception:
6382 super(TestDSliteCE, cls).tearDownClass()
6383 raise
6384
6385 def test_dslite_ce(self):
6386 """ Test DS-Lite CE """
6387
6388 b4_ip4 = '192.0.0.2'
6389 b4_ip4_n = socket.inet_pton(socket.AF_INET, b4_ip4)
6390 b4_ip6 = '2001:db8:62aa::375e:f4c1:1'
6391 b4_ip6_n = socket.inet_pton(socket.AF_INET6, b4_ip6)
6392 self.vapi.dslite_set_b4_addr(b4_ip6_n, b4_ip4_n)
6393
6394 aftr_ip4 = '192.0.0.1'
6395 aftr_ip4_n = socket.inet_pton(socket.AF_INET, aftr_ip4)
6396 aftr_ip6 = '2001:db8:85a3::8a2e:370:1'
6397 aftr_ip6_n = socket.inet_pton(socket.AF_INET6, aftr_ip6)
6398 self.vapi.dslite_set_aftr_addr(aftr_ip6_n, aftr_ip4_n)
6399
6400 self.vapi.ip_add_del_route(dst_address=aftr_ip6_n,
6401 dst_address_length=128,
6402 next_hop_address=self.pg1.remote_ip6n,
6403 next_hop_sw_if_index=self.pg1.sw_if_index,
6404 is_ipv6=1)
6405
6406 # UDP encapsulation
6407 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6408 IP(dst=self.pg1.remote_ip4, src=self.pg0.remote_ip4) /
6409 UDP(sport=10000, dport=20000))
6410 self.pg0.add_stream(p)
6411 self.pg_enable_capture(self.pg_interfaces)
6412 self.pg_start()
6413 capture = self.pg1.get_capture(1)
6414 capture = capture[0]
6415 self.assertEqual(capture[IPv6].src, b4_ip6)
6416 self.assertEqual(capture[IPv6].dst, aftr_ip6)
6417 self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
6418 self.assertEqual(capture[IP].dst, self.pg1.remote_ip4)
6419 self.assertEqual(capture[UDP].sport, 10000)
6420 self.assertEqual(capture[UDP].dport, 20000)
Klement Sekerad81ae412018-05-16 10:52:54 +02006421 self.assert_packet_checksums_valid(capture)
Juraj Slobodac5c6a332018-01-09 16:08:32 +01006422
6423 # UDP decapsulation
6424 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
6425 IPv6(dst=b4_ip6, src=aftr_ip6) /
6426 IP(dst=self.pg0.remote_ip4, src=self.pg1.remote_ip4) /
6427 UDP(sport=20000, dport=10000))
6428 self.pg1.add_stream(p)
6429 self.pg_enable_capture(self.pg_interfaces)
6430 self.pg_start()
6431 capture = self.pg0.get_capture(1)
6432 capture = capture[0]
6433 self.assertFalse(capture.haslayer(IPv6))
6434 self.assertEqual(capture[IP].src, self.pg1.remote_ip4)
6435 self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
6436 self.assertEqual(capture[UDP].sport, 20000)
6437 self.assertEqual(capture[UDP].dport, 10000)
Klement Sekerad81ae412018-05-16 10:52:54 +02006438 self.assert_packet_checksums_valid(capture)
Juraj Slobodac5c6a332018-01-09 16:08:32 +01006439
6440 # ping DS-Lite B4 tunnel endpoint address
6441 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
6442 IPv6(src=self.pg1.remote_hosts[0].ip6, dst=b4_ip6) /
6443 ICMPv6EchoRequest())
6444 self.pg1.add_stream(p)
6445 self.pg_enable_capture(self.pg_interfaces)
6446 self.pg_start()
6447 capture = self.pg1.get_capture(1)
6448 self.assertEqual(1, len(capture))
6449 capture = capture[0]
6450 self.assertEqual(capture[IPv6].src, b4_ip6)
6451 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[0].ip6)
6452 self.assertTrue(capture.haslayer(ICMPv6EchoReply))
6453
6454 def tearDown(self):
6455 super(TestDSliteCE, self).tearDown()
6456 if not self.vpp_dead:
6457 self.logger.info(
6458 self.vapi.cli("show dslite aftr-tunnel-endpoint-address"))
6459 self.logger.info(
6460 self.vapi.cli("show dslite b4-tunnel-endpoint-address"))
6461
Matus Fabianf2a23cc2018-01-22 03:41:53 -08006462
6463class TestNAT66(MethodHolder):
6464 """ NAT66 Test Cases """
6465
6466 @classmethod
6467 def setUpClass(cls):
6468 super(TestNAT66, cls).setUpClass()
6469
6470 try:
6471 cls.nat_addr = 'fd01:ff::2'
6472 cls.nat_addr_n = socket.inet_pton(socket.AF_INET6, cls.nat_addr)
6473
6474 cls.create_pg_interfaces(range(2))
6475 cls.interfaces = list(cls.pg_interfaces)
6476
6477 for i in cls.interfaces:
6478 i.admin_up()
6479 i.config_ip6()
6480 i.configure_ipv6_neighbors()
6481
6482 except Exception:
6483 super(TestNAT66, cls).tearDownClass()
6484 raise
6485
6486 def test_static(self):
6487 """ 1:1 NAT66 test """
6488 self.vapi.nat66_add_del_interface(self.pg0.sw_if_index)
6489 self.vapi.nat66_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6490 self.vapi.nat66_add_del_static_mapping(self.pg0.remote_ip6n,
6491 self.nat_addr_n)
6492
6493 # in2out
6494 pkts = []
6495 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6496 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
6497 TCP())
6498 pkts.append(p)
6499 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6500 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
6501 UDP())
6502 pkts.append(p)
6503 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6504 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
6505 ICMPv6EchoRequest())
6506 pkts.append(p)
6507 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6508 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
6509 GRE() / IP() / TCP())
6510 pkts.append(p)
6511 self.pg0.add_stream(pkts)
6512 self.pg_enable_capture(self.pg_interfaces)
6513 self.pg_start()
6514 capture = self.pg1.get_capture(len(pkts))
6515 for packet in capture:
6516 try:
6517 self.assertEqual(packet[IPv6].src, self.nat_addr)
6518 self.assertEqual(packet[IPv6].dst, self.pg1.remote_ip6)
Klement Sekerad81ae412018-05-16 10:52:54 +02006519 self.assert_packet_checksums_valid(packet)
Matus Fabianf2a23cc2018-01-22 03:41:53 -08006520 except:
6521 self.logger.error(ppp("Unexpected or invalid packet:", packet))
6522 raise
6523
6524 # out2in
6525 pkts = []
6526 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
6527 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
6528 TCP())
6529 pkts.append(p)
6530 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
6531 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
6532 UDP())
6533 pkts.append(p)
6534 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
6535 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
6536 ICMPv6EchoReply())
6537 pkts.append(p)
6538 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
6539 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
6540 GRE() / IP() / TCP())
6541 pkts.append(p)
6542 self.pg1.add_stream(pkts)
6543 self.pg_enable_capture(self.pg_interfaces)
6544 self.pg_start()
6545 capture = self.pg0.get_capture(len(pkts))
6546 for packet in capture:
6547 try:
6548 self.assertEqual(packet[IPv6].src, self.pg1.remote_ip6)
6549 self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
Klement Sekerad81ae412018-05-16 10:52:54 +02006550 self.assert_packet_checksums_valid(packet)
Matus Fabianf2a23cc2018-01-22 03:41:53 -08006551 except:
6552 self.logger.error(ppp("Unexpected or invalid packet:", packet))
6553 raise
6554
6555 sm = self.vapi.nat66_static_mapping_dump()
6556 self.assertEqual(len(sm), 1)
6557 self.assertEqual(sm[0].total_pkts, 8)
6558
Juraj Sloboda9341e342018-04-13 12:00:46 +02006559 def test_check_no_translate(self):
6560 """ NAT66 translate only when egress interface is outside interface """
6561 self.vapi.nat66_add_del_interface(self.pg0.sw_if_index)
6562 self.vapi.nat66_add_del_interface(self.pg1.sw_if_index)
6563 self.vapi.nat66_add_del_static_mapping(self.pg0.remote_ip6n,
6564 self.nat_addr_n)
6565
6566 # in2out
6567 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6568 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
6569 UDP())
6570 self.pg0.add_stream([p])
6571 self.pg_enable_capture(self.pg_interfaces)
6572 self.pg_start()
6573 capture = self.pg1.get_capture(1)
6574 packet = capture[0]
6575 try:
6576 self.assertEqual(packet[IPv6].src, self.pg0.remote_ip6)
6577 self.assertEqual(packet[IPv6].dst, self.pg1.remote_ip6)
6578 except:
6579 self.logger.error(ppp("Unexpected or invalid packet:", packet))
6580 raise
6581
Matus Fabianf2a23cc2018-01-22 03:41:53 -08006582 def clear_nat66(self):
6583 """
6584 Clear NAT66 configuration.
6585 """
6586 interfaces = self.vapi.nat66_interface_dump()
6587 for intf in interfaces:
6588 self.vapi.nat66_add_del_interface(intf.sw_if_index,
6589 intf.is_inside,
6590 is_add=0)
6591
6592 static_mappings = self.vapi.nat66_static_mapping_dump()
6593 for sm in static_mappings:
6594 self.vapi.nat66_add_del_static_mapping(sm.local_ip_address,
6595 sm.external_ip_address,
6596 sm.vrf_id,
6597 is_add=0)
6598
6599 def tearDown(self):
6600 super(TestNAT66, self).tearDown()
6601 if not self.vpp_dead:
6602 self.logger.info(self.vapi.cli("show nat66 interfaces"))
6603 self.logger.info(self.vapi.cli("show nat66 static mappings"))
6604 self.clear_nat66()
6605
Klement Sekerad81ae412018-05-16 10:52:54 +02006606
Matus Fabiande886752016-12-07 03:38:19 -08006607if __name__ == '__main__':
6608 unittest.main(testRunner=VppTestRunner)