blob: e2f34657d2535dd2a9c659242b30bd0eb71e2a6f [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()
Martin Gálikd7f75cd2017-03-27 06:02:47 -0700829
830 try:
831 cls.tcp_port_in = 6303
832 cls.tcp_port_out = 6303
833 cls.udp_port_in = 6304
834 cls.udp_port_out = 6304
835 cls.icmp_id_in = 6305
836 cls.icmp_id_out = 6305
Matus Fabian2ba92e32017-08-21 07:05:03 -0700837 cls.nat_addr = '10.0.0.3'
Juraj Sloboda7b929792017-11-23 13:20:48 +0100838 cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
Matus Fabian6631e9c2017-05-24 01:52:20 -0700839 cls.ipfix_src_port = 4739
840 cls.ipfix_domain_id = 1
Matus Fabianebdf1902018-05-04 03:57:42 -0700841 cls.tcp_external_port = 80
Martin Gálikd7f75cd2017-03-27 06:02:47 -0700842
Matus Fabian36ea2d62017-10-24 04:13:49 -0700843 cls.create_pg_interfaces(range(10))
Martin Gálikd7f75cd2017-03-27 06:02:47 -0700844 cls.interfaces = list(cls.pg_interfaces[0:4])
845
846 for i in cls.interfaces:
847 i.admin_up()
848 i.config_ip4()
849 i.resolve_arp()
850
Matus Fabian6fa74c62017-06-05 05:55:48 -0700851 cls.pg0.generate_remote_hosts(3)
Martin Gálikd7f75cd2017-03-27 06:02:47 -0700852 cls.pg0.configure_ipv4_neighbors()
853
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +0200854 cls.pg1.generate_remote_hosts(1)
855 cls.pg1.configure_ipv4_neighbors()
856
Martin Gálikd7f75cd2017-03-27 06:02:47 -0700857 cls.overlapping_interfaces = list(list(cls.pg_interfaces[4:7]))
Neale Ranns15002542017-09-10 04:39:11 -0700858 cls.vapi.ip_table_add_del(10, is_add=1)
859 cls.vapi.ip_table_add_del(20, is_add=1)
Martin Gálikd7f75cd2017-03-27 06:02:47 -0700860
861 cls.pg4._local_ip4 = "172.16.255.1"
862 cls.pg4._local_ip4n = socket.inet_pton(socket.AF_INET, i.local_ip4)
863 cls.pg4._remote_hosts[0]._ip4 = "172.16.255.2"
864 cls.pg4.set_table_ip4(10)
Matus Fabian69126282017-08-14 23:39:58 -0700865 cls.pg5._local_ip4 = "172.17.255.3"
Martin Gálikd7f75cd2017-03-27 06:02:47 -0700866 cls.pg5._local_ip4n = socket.inet_pton(socket.AF_INET, i.local_ip4)
Matus Fabian69126282017-08-14 23:39:58 -0700867 cls.pg5._remote_hosts[0]._ip4 = "172.17.255.4"
Martin Gálikd7f75cd2017-03-27 06:02:47 -0700868 cls.pg5.set_table_ip4(10)
869 cls.pg6._local_ip4 = "172.16.255.1"
870 cls.pg6._local_ip4n = socket.inet_pton(socket.AF_INET, i.local_ip4)
871 cls.pg6._remote_hosts[0]._ip4 = "172.16.255.2"
872 cls.pg6.set_table_ip4(20)
873 for i in cls.overlapping_interfaces:
874 i.config_ip4()
875 i.admin_up()
876 i.resolve_arp()
877
878 cls.pg7.admin_up()
Martin Gálik406eb1d2017-05-04 04:35:04 -0700879 cls.pg8.admin_up()
Martin Gálikd7f75cd2017-03-27 06:02:47 -0700880
Matus Fabian36ea2d62017-10-24 04:13:49 -0700881 cls.pg9.generate_remote_hosts(2)
882 cls.pg9.config_ip4()
883 ip_addr_n = socket.inet_pton(socket.AF_INET, "10.0.0.1")
884 cls.vapi.sw_interface_add_del_address(cls.pg9.sw_if_index,
885 ip_addr_n,
886 24)
887 cls.pg9.admin_up()
888 cls.pg9.resolve_arp()
889 cls.pg9._remote_hosts[1]._ip4 = cls.pg9._remote_hosts[0]._ip4
890 cls.pg4._remote_ip4 = cls.pg9._remote_hosts[0]._ip4 = "10.0.0.2"
891 cls.pg9.resolve_arp()
892
Martin Gálikd7f75cd2017-03-27 06:02:47 -0700893 except Exception:
Matus Fabian2ba92e32017-08-21 07:05:03 -0700894 super(TestNAT44, cls).tearDownClass()
Martin Gálikd7f75cd2017-03-27 06:02:47 -0700895 raise
896
Matus Fabian2ba92e32017-08-21 07:05:03 -0700897 def clear_nat44(self):
Matus Fabiande886752016-12-07 03:38:19 -0800898 """
Matus Fabian2ba92e32017-08-21 07:05:03 -0700899 Clear NAT44 configuration.
Matus Fabiande886752016-12-07 03:38:19 -0800900 """
Martin Gálik406eb1d2017-05-04 04:35:04 -0700901 # I found no elegant way to do this
902 self.vapi.ip_add_del_route(dst_address=self.pg7.remote_ip4n,
903 dst_address_length=32,
904 next_hop_address=self.pg7.remote_ip4n,
905 next_hop_sw_if_index=self.pg7.sw_if_index,
906 is_add=0)
907 self.vapi.ip_add_del_route(dst_address=self.pg8.remote_ip4n,
908 dst_address_length=32,
909 next_hop_address=self.pg8.remote_ip4n,
910 next_hop_sw_if_index=self.pg8.sw_if_index,
911 is_add=0)
912
913 for intf in [self.pg7, self.pg8]:
914 neighbors = self.vapi.ip_neighbor_dump(intf.sw_if_index)
915 for n in neighbors:
916 self.vapi.ip_neighbor_add_del(intf.sw_if_index,
917 n.mac_address,
918 n.ip_address,
919 is_add=0)
920
Matus Fabian36532bd2017-01-23 23:42:28 -0800921 if self.pg7.has_ip4_config:
922 self.pg7.unconfig_ip4()
923
Matus Fabian240b5ef2018-01-11 04:09:17 -0800924 self.vapi.nat44_forwarding_enable_disable(0)
925
Matus Fabian2ba92e32017-08-21 07:05:03 -0700926 interfaces = self.vapi.nat44_interface_addr_dump()
Matus Fabian8bf68e82017-01-12 04:24:35 -0800927 for intf in interfaces:
Matus Fabianb932d262017-12-18 05:38:24 -0800928 self.vapi.nat44_add_interface_addr(intf.sw_if_index,
929 twice_nat=intf.twice_nat,
930 is_add=0)
Matus Fabian8bf68e82017-01-12 04:24:35 -0800931
Matus Fabian2ba92e32017-08-21 07:05:03 -0700932 self.vapi.nat_ipfix(enable=0, src_port=self.ipfix_src_port,
933 domain_id=self.ipfix_domain_id)
Matus Fabian6631e9c2017-05-24 01:52:20 -0700934 self.ipfix_src_port = 4739
935 self.ipfix_domain_id = 1
Matus Fabianeea28d72017-01-13 04:15:54 -0800936
Matus Fabian2ba92e32017-08-21 07:05:03 -0700937 interfaces = self.vapi.nat44_interface_dump()
Matus Fabiande886752016-12-07 03:38:19 -0800938 for intf in interfaces:
Matus Fabian36ea2d62017-10-24 04:13:49 -0700939 if intf.is_inside > 1:
940 self.vapi.nat44_interface_add_del_feature(intf.sw_if_index,
941 0,
942 is_add=0)
Matus Fabian2ba92e32017-08-21 07:05:03 -0700943 self.vapi.nat44_interface_add_del_feature(intf.sw_if_index,
944 intf.is_inside,
945 is_add=0)
Matus Fabiande886752016-12-07 03:38:19 -0800946
Matus Fabian2ba92e32017-08-21 07:05:03 -0700947 interfaces = self.vapi.nat44_interface_output_feature_dump()
Matus Fabian93d84c92017-07-19 08:06:01 -0700948 for intf in interfaces:
Matus Fabian2ba92e32017-08-21 07:05:03 -0700949 self.vapi.nat44_interface_add_del_output_feature(intf.sw_if_index,
950 intf.is_inside,
951 is_add=0)
Matus Fabian93d84c92017-07-19 08:06:01 -0700952
Matus Fabian2ba92e32017-08-21 07:05:03 -0700953 static_mappings = self.vapi.nat44_static_mapping_dump()
Matus Fabiande886752016-12-07 03:38:19 -0800954 for sm in static_mappings:
Matus Fabian2ba92e32017-08-21 07:05:03 -0700955 self.vapi.nat44_add_del_static_mapping(
956 sm.local_ip_address,
957 sm.external_ip_address,
958 local_port=sm.local_port,
959 external_port=sm.external_port,
960 addr_only=sm.addr_only,
961 vrf_id=sm.vrf_id,
962 protocol=sm.protocol,
Matus Fabianb932d262017-12-18 05:38:24 -0800963 twice_nat=sm.twice_nat,
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +0200964 self_twice_nat=sm.self_twice_nat,
Matus Fabiane82488f2018-01-18 03:38:45 -0800965 out2in_only=sm.out2in_only,
Matus Fabian5f224992018-01-25 21:59:16 -0800966 tag=sm.tag,
Matus Fabianea2600a2018-03-28 04:06:26 -0700967 external_sw_if_index=sm.external_sw_if_index,
Matus Fabian2ba92e32017-08-21 07:05:03 -0700968 is_add=0)
Matus Fabiande886752016-12-07 03:38:19 -0800969
Matus Fabian704018c2017-09-04 02:17:18 -0700970 lb_static_mappings = self.vapi.nat44_lb_static_mapping_dump()
971 for lb_sm in lb_static_mappings:
972 self.vapi.nat44_add_del_lb_static_mapping(
973 lb_sm.external_addr,
974 lb_sm.external_port,
975 lb_sm.protocol,
Matus Fabianb932d262017-12-18 05:38:24 -0800976 vrf_id=lb_sm.vrf_id,
977 twice_nat=lb_sm.twice_nat,
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +0200978 self_twice_nat=lb_sm.self_twice_nat,
Matus Fabian240b5ef2018-01-11 04:09:17 -0800979 out2in_only=lb_sm.out2in_only,
Matus Fabian5f224992018-01-25 21:59:16 -0800980 tag=lb_sm.tag,
Ole Troan895b6e82017-10-20 13:28:20 +0200981 is_add=0,
982 local_num=0,
983 locals=[])
Matus Fabian704018c2017-09-04 02:17:18 -0700984
Matus Fabianab7a8052017-11-28 04:29:41 -0800985 identity_mappings = self.vapi.nat44_identity_mapping_dump()
986 for id_m in identity_mappings:
987 self.vapi.nat44_add_del_identity_mapping(
988 addr_only=id_m.addr_only,
989 ip=id_m.ip_address,
990 port=id_m.port,
991 sw_if_index=id_m.sw_if_index,
992 vrf_id=id_m.vrf_id,
993 protocol=id_m.protocol,
994 is_add=0)
995
Matus Fabian2ba92e32017-08-21 07:05:03 -0700996 adresses = self.vapi.nat44_address_dump()
Matus Fabiande886752016-12-07 03:38:19 -0800997 for addr in adresses:
Matus Fabian2ba92e32017-08-21 07:05:03 -0700998 self.vapi.nat44_add_del_address_range(addr.ip_address,
999 addr.ip_address,
Matus Fabianb932d262017-12-18 05:38:24 -08001000 twice_nat=addr.twice_nat,
Matus Fabian2ba92e32017-08-21 07:05:03 -07001001 is_add=0)
Matus Fabiande886752016-12-07 03:38:19 -08001002
Matus Fabianefcd1e92017-08-15 06:59:19 -07001003 self.vapi.nat_set_reass()
1004 self.vapi.nat_set_reass(is_ip6=1)
1005
Matus Fabian2ba92e32017-08-21 07:05:03 -07001006 def nat44_add_static_mapping(self, local_ip, external_ip='0.0.0.0',
1007 local_port=0, external_port=0, vrf_id=0,
1008 is_add=1, external_sw_if_index=0xFFFFFFFF,
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02001009 proto=0, twice_nat=0, self_twice_nat=0,
1010 out2in_only=0, tag=""):
Matus Fabiande886752016-12-07 03:38:19 -08001011 """
Matus Fabian2ba92e32017-08-21 07:05:03 -07001012 Add/delete NAT44 static mapping
Matus Fabiande886752016-12-07 03:38:19 -08001013
1014 :param local_ip: Local IP address
1015 :param external_ip: External IP address
1016 :param local_port: Local port number (Optional)
1017 :param external_port: External port number (Optional)
1018 :param vrf_id: VRF ID (Default 0)
1019 :param is_add: 1 if add, 0 if delete (Default add)
Matus Fabian36532bd2017-01-23 23:42:28 -08001020 :param external_sw_if_index: External interface instead of IP address
Matus Fabian09d96f42017-02-02 01:43:00 -08001021 :param proto: IP protocol (Mandatory if port specified)
Matus Fabianb932d262017-12-18 05:38:24 -08001022 :param twice_nat: 1 if translate external host address and port
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02001023 :param self_twice_nat: 1 if translate external host address and port
1024 whenever external host address equals
1025 local address of internal host
Matus Fabiane82488f2018-01-18 03:38:45 -08001026 :param out2in_only: if 1 rule is matching only out2in direction
Matus Fabian5f224992018-01-25 21:59:16 -08001027 :param tag: Opaque string tag
Matus Fabiande886752016-12-07 03:38:19 -08001028 """
1029 addr_only = 1
1030 if local_port and external_port:
1031 addr_only = 0
1032 l_ip = socket.inet_pton(socket.AF_INET, local_ip)
1033 e_ip = socket.inet_pton(socket.AF_INET, external_ip)
Matus Fabian2ba92e32017-08-21 07:05:03 -07001034 self.vapi.nat44_add_del_static_mapping(
Klement Sekerada505f62017-01-04 12:58:53 +01001035 l_ip,
1036 e_ip,
Matus Fabian36532bd2017-01-23 23:42:28 -08001037 external_sw_if_index,
Klement Sekerada505f62017-01-04 12:58:53 +01001038 local_port,
1039 external_port,
1040 addr_only,
1041 vrf_id,
Matus Fabian09d96f42017-02-02 01:43:00 -08001042 proto,
Matus Fabianb932d262017-12-18 05:38:24 -08001043 twice_nat,
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02001044 self_twice_nat,
Matus Fabiane82488f2018-01-18 03:38:45 -08001045 out2in_only,
Matus Fabian5f224992018-01-25 21:59:16 -08001046 tag,
Klement Sekerada505f62017-01-04 12:58:53 +01001047 is_add)
Matus Fabiande886752016-12-07 03:38:19 -08001048
Matus Fabianb932d262017-12-18 05:38:24 -08001049 def nat44_add_address(self, ip, is_add=1, vrf_id=0xFFFFFFFF, twice_nat=0):
Matus Fabiande886752016-12-07 03:38:19 -08001050 """
Matus Fabian2ba92e32017-08-21 07:05:03 -07001051 Add/delete NAT44 address
Matus Fabiande886752016-12-07 03:38:19 -08001052
1053 :param ip: IP address
1054 :param is_add: 1 if add, 0 if delete (Default add)
Matus Fabianb932d262017-12-18 05:38:24 -08001055 :param twice_nat: twice NAT address for extenal hosts
Matus Fabiande886752016-12-07 03:38:19 -08001056 """
Matus Fabian2ba92e32017-08-21 07:05:03 -07001057 nat_addr = socket.inet_pton(socket.AF_INET, ip)
1058 self.vapi.nat44_add_del_address_range(nat_addr, nat_addr, is_add,
Matus Fabianb932d262017-12-18 05:38:24 -08001059 vrf_id=vrf_id,
1060 twice_nat=twice_nat)
Matus Fabiande886752016-12-07 03:38:19 -08001061
1062 def test_dynamic(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001063 """ NAT44 dynamic translation test """
Matus Fabiande886752016-12-07 03:38:19 -08001064
Matus Fabian2ba92e32017-08-21 07:05:03 -07001065 self.nat44_add_address(self.nat_addr)
1066 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1067 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1068 is_inside=0)
Matus Fabiande886752016-12-07 03:38:19 -08001069
1070 # in2out
1071 pkts = self.create_stream_in(self.pg0, self.pg1)
1072 self.pg0.add_stream(pkts)
1073 self.pg_enable_capture(self.pg_interfaces)
1074 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001075 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001076 self.verify_capture_out(capture)
1077
1078 # out2in
1079 pkts = self.create_stream_out(self.pg1)
1080 self.pg1.add_stream(pkts)
1081 self.pg_enable_capture(self.pg_interfaces)
1082 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001083 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001084 self.verify_capture_in(capture, self.pg0)
1085
Juraj Slobodab33f4132017-02-08 23:54:21 -08001086 def test_dynamic_icmp_errors_in2out_ttl_1(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001087 """ NAT44 handling of client packets with TTL=1 """
Juraj Slobodab33f4132017-02-08 23:54:21 -08001088
Matus Fabian2ba92e32017-08-21 07:05:03 -07001089 self.nat44_add_address(self.nat_addr)
1090 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1091 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1092 is_inside=0)
Juraj Slobodab33f4132017-02-08 23:54:21 -08001093
1094 # Client side - generate traffic
1095 pkts = self.create_stream_in(self.pg0, self.pg1, ttl=1)
1096 self.pg0.add_stream(pkts)
1097 self.pg_enable_capture(self.pg_interfaces)
1098 self.pg_start()
1099
1100 # Client side - verify ICMP type 11 packets
1101 capture = self.pg0.get_capture(len(pkts))
1102 self.verify_capture_in_with_icmp_errors(capture, self.pg0)
1103
1104 def test_dynamic_icmp_errors_out2in_ttl_1(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001105 """ NAT44 handling of server packets with TTL=1 """
Juraj Slobodab33f4132017-02-08 23:54:21 -08001106
Matus Fabian2ba92e32017-08-21 07:05:03 -07001107 self.nat44_add_address(self.nat_addr)
1108 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1109 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1110 is_inside=0)
Juraj Slobodab33f4132017-02-08 23:54:21 -08001111
1112 # Client side - create sessions
1113 pkts = self.create_stream_in(self.pg0, self.pg1)
1114 self.pg0.add_stream(pkts)
1115 self.pg_enable_capture(self.pg_interfaces)
1116 self.pg_start()
1117
1118 # Server side - generate traffic
1119 capture = self.pg1.get_capture(len(pkts))
1120 self.verify_capture_out(capture)
1121 pkts = self.create_stream_out(self.pg1, ttl=1)
1122 self.pg1.add_stream(pkts)
1123 self.pg_enable_capture(self.pg_interfaces)
1124 self.pg_start()
1125
1126 # Server side - verify ICMP type 11 packets
1127 capture = self.pg1.get_capture(len(pkts))
1128 self.verify_capture_out_with_icmp_errors(capture,
1129 src_ip=self.pg1.local_ip4)
1130
1131 def test_dynamic_icmp_errors_in2out_ttl_2(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001132 """ NAT44 handling of error responses to client packets with TTL=2 """
Juraj Slobodab33f4132017-02-08 23:54:21 -08001133
Matus Fabian2ba92e32017-08-21 07:05:03 -07001134 self.nat44_add_address(self.nat_addr)
1135 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1136 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1137 is_inside=0)
Juraj Slobodab33f4132017-02-08 23:54:21 -08001138
1139 # Client side - generate traffic
1140 pkts = self.create_stream_in(self.pg0, self.pg1, ttl=2)
1141 self.pg0.add_stream(pkts)
1142 self.pg_enable_capture(self.pg_interfaces)
1143 self.pg_start()
1144
1145 # Server side - simulate ICMP type 11 response
1146 capture = self.pg1.get_capture(len(pkts))
1147 pkts = [Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07001148 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Juraj Slobodab33f4132017-02-08 23:54:21 -08001149 ICMP(type=11) / packet[IP] for packet in capture]
1150 self.pg1.add_stream(pkts)
1151 self.pg_enable_capture(self.pg_interfaces)
1152 self.pg_start()
1153
1154 # Client side - verify ICMP type 11 packets
1155 capture = self.pg0.get_capture(len(pkts))
1156 self.verify_capture_in_with_icmp_errors(capture, self.pg0)
1157
1158 def test_dynamic_icmp_errors_out2in_ttl_2(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001159 """ NAT44 handling of error responses to server packets with TTL=2 """
Juraj Slobodab33f4132017-02-08 23:54:21 -08001160
Matus Fabian2ba92e32017-08-21 07:05:03 -07001161 self.nat44_add_address(self.nat_addr)
1162 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1163 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1164 is_inside=0)
Juraj Slobodab33f4132017-02-08 23:54:21 -08001165
1166 # Client side - create sessions
1167 pkts = self.create_stream_in(self.pg0, self.pg1)
1168 self.pg0.add_stream(pkts)
1169 self.pg_enable_capture(self.pg_interfaces)
1170 self.pg_start()
1171
1172 # Server side - generate traffic
1173 capture = self.pg1.get_capture(len(pkts))
1174 self.verify_capture_out(capture)
1175 pkts = self.create_stream_out(self.pg1, ttl=2)
1176 self.pg1.add_stream(pkts)
1177 self.pg_enable_capture(self.pg_interfaces)
1178 self.pg_start()
1179
1180 # Client side - simulate ICMP type 11 response
1181 capture = self.pg0.get_capture(len(pkts))
1182 pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1183 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
1184 ICMP(type=11) / packet[IP] for packet in capture]
1185 self.pg0.add_stream(pkts)
1186 self.pg_enable_capture(self.pg_interfaces)
1187 self.pg_start()
1188
1189 # Server side - verify ICMP type 11 packets
1190 capture = self.pg1.get_capture(len(pkts))
1191 self.verify_capture_out_with_icmp_errors(capture)
1192
Juraj Sloboda665e4822017-02-16 17:17:19 -08001193 def test_ping_out_interface_from_outside(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001194 """ Ping NAT44 out interface from outside network """
Juraj Sloboda665e4822017-02-16 17:17:19 -08001195
Matus Fabian2ba92e32017-08-21 07:05:03 -07001196 self.nat44_add_address(self.nat_addr)
1197 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1198 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1199 is_inside=0)
Juraj Sloboda665e4822017-02-16 17:17:19 -08001200
1201 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1202 IP(src=self.pg1.remote_ip4, dst=self.pg1.local_ip4) /
1203 ICMP(id=self.icmp_id_out, type='echo-request'))
1204 pkts = [p]
1205 self.pg1.add_stream(pkts)
1206 self.pg_enable_capture(self.pg_interfaces)
1207 self.pg_start()
1208 capture = self.pg1.get_capture(len(pkts))
1209 self.assertEqual(1, len(capture))
1210 packet = capture[0]
1211 try:
1212 self.assertEqual(packet[IP].src, self.pg1.local_ip4)
1213 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
1214 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
1215 self.assertEqual(packet[ICMP].type, 0) # echo reply
1216 except:
1217 self.logger.error(ppp("Unexpected or invalid packet "
1218 "(outside network):", packet))
1219 raise
1220
Juraj Slobodad3677682017-04-14 03:24:45 +02001221 def test_ping_internal_host_from_outside(self):
1222 """ Ping internal host from outside network """
1223
Matus Fabian2ba92e32017-08-21 07:05:03 -07001224 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr)
1225 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1226 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1227 is_inside=0)
Juraj Slobodad3677682017-04-14 03:24:45 +02001228
1229 # out2in
1230 pkt = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07001231 IP(src=self.pg1.remote_ip4, dst=self.nat_addr, ttl=64) /
Juraj Slobodad3677682017-04-14 03:24:45 +02001232 ICMP(id=self.icmp_id_out, type='echo-request'))
1233 self.pg1.add_stream(pkt)
1234 self.pg_enable_capture(self.pg_interfaces)
1235 self.pg_start()
1236 capture = self.pg0.get_capture(1)
1237 self.verify_capture_in(capture, self.pg0, packet_num=1)
1238 self.assert_equal(capture[0][IP].proto, IP_PROTOS.icmp)
1239
1240 # in2out
1241 pkt = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1242 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4, ttl=64) /
1243 ICMP(id=self.icmp_id_in, type='echo-reply'))
1244 self.pg0.add_stream(pkt)
1245 self.pg_enable_capture(self.pg_interfaces)
1246 self.pg_start()
1247 capture = self.pg1.get_capture(1)
1248 self.verify_capture_out(capture, same_port=True, packet_num=1)
1249 self.assert_equal(capture[0][IP].proto, IP_PROTOS.icmp)
1250
Juraj Sloboda7b929792017-11-23 13:20:48 +01001251 def test_forwarding(self):
1252 """ NAT44 forwarding test """
1253
1254 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1255 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1256 is_inside=0)
1257 self.vapi.nat44_forwarding_enable_disable(1)
1258
1259 real_ip = self.pg0.remote_ip4n
1260 alias_ip = self.nat_addr_n
1261 self.vapi.nat44_add_del_static_mapping(local_ip=real_ip,
1262 external_ip=alias_ip)
1263
1264 try:
1265 # in2out - static mapping match
1266
1267 pkts = self.create_stream_out(self.pg1)
1268 self.pg1.add_stream(pkts)
1269 self.pg_enable_capture(self.pg_interfaces)
1270 self.pg_start()
1271 capture = self.pg0.get_capture(len(pkts))
1272 self.verify_capture_in(capture, self.pg0)
1273
1274 pkts = self.create_stream_in(self.pg0, self.pg1)
1275 self.pg0.add_stream(pkts)
1276 self.pg_enable_capture(self.pg_interfaces)
1277 self.pg_start()
1278 capture = self.pg1.get_capture(len(pkts))
1279 self.verify_capture_out(capture, same_port=True)
1280
1281 # in2out - no static mapping match
1282
1283 host0 = self.pg0.remote_hosts[0]
1284 self.pg0.remote_hosts[0] = self.pg0.remote_hosts[1]
1285 try:
1286 pkts = self.create_stream_out(self.pg1,
1287 dst_ip=self.pg0.remote_ip4,
1288 use_inside_ports=True)
1289 self.pg1.add_stream(pkts)
1290 self.pg_enable_capture(self.pg_interfaces)
1291 self.pg_start()
1292 capture = self.pg0.get_capture(len(pkts))
1293 self.verify_capture_in(capture, self.pg0)
1294
1295 pkts = self.create_stream_in(self.pg0, self.pg1)
1296 self.pg0.add_stream(pkts)
1297 self.pg_enable_capture(self.pg_interfaces)
1298 self.pg_start()
1299 capture = self.pg1.get_capture(len(pkts))
1300 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
1301 same_port=True)
1302 finally:
1303 self.pg0.remote_hosts[0] = host0
1304
Matus Fabian70a26ac2018-05-14 06:20:28 -07001305 user = self.pg0.remote_hosts[1]
1306 sessions = self.vapi.nat44_user_session_dump(user.ip4n, 0)
1307 self.assertEqual(len(sessions), 3)
1308 self.assertTrue(sessions[0].ext_host_valid)
1309 self.vapi.nat44_del_session(
1310 sessions[0].inside_ip_address,
1311 sessions[0].inside_port,
1312 sessions[0].protocol,
1313 ext_host_address=sessions[0].ext_host_address,
1314 ext_host_port=sessions[0].ext_host_port)
1315 sessions = self.vapi.nat44_user_session_dump(user.ip4n, 0)
1316 self.assertEqual(len(sessions), 2)
1317
Juraj Sloboda7b929792017-11-23 13:20:48 +01001318 finally:
1319 self.vapi.nat44_forwarding_enable_disable(0)
1320 self.vapi.nat44_add_del_static_mapping(local_ip=real_ip,
1321 external_ip=alias_ip,
1322 is_add=0)
1323
Matus Fabiande886752016-12-07 03:38:19 -08001324 def test_static_in(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001325 """ 1:1 NAT initialized from inside network """
Matus Fabiande886752016-12-07 03:38:19 -08001326
1327 nat_ip = "10.0.0.10"
1328 self.tcp_port_out = 6303
1329 self.udp_port_out = 6304
1330 self.icmp_id_out = 6305
1331
Matus Fabian2ba92e32017-08-21 07:05:03 -07001332 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
1333 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1334 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1335 is_inside=0)
Matus Fabian5f224992018-01-25 21:59:16 -08001336 sm = self.vapi.nat44_static_mapping_dump()
1337 self.assertEqual(len(sm), 1)
1338 self.assertEqual((sm[0].tag).split('\0', 1)[0], '')
Matus Fabian9dba7812018-01-31 01:13:23 -08001339 self.assertEqual(sm[0].protocol, 0)
1340 self.assertEqual(sm[0].local_port, 0)
1341 self.assertEqual(sm[0].external_port, 0)
Matus Fabiande886752016-12-07 03:38:19 -08001342
1343 # in2out
1344 pkts = self.create_stream_in(self.pg0, self.pg1)
1345 self.pg0.add_stream(pkts)
1346 self.pg_enable_capture(self.pg_interfaces)
1347 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001348 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001349 self.verify_capture_out(capture, nat_ip, True)
1350
1351 # out2in
1352 pkts = self.create_stream_out(self.pg1, nat_ip)
1353 self.pg1.add_stream(pkts)
1354 self.pg_enable_capture(self.pg_interfaces)
1355 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001356 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001357 self.verify_capture_in(capture, self.pg0)
1358
1359 def test_static_out(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001360 """ 1:1 NAT initialized from outside network """
Matus Fabiande886752016-12-07 03:38:19 -08001361
1362 nat_ip = "10.0.0.20"
1363 self.tcp_port_out = 6303
1364 self.udp_port_out = 6304
1365 self.icmp_id_out = 6305
Matus Fabian5f224992018-01-25 21:59:16 -08001366 tag = "testTAG"
Matus Fabiande886752016-12-07 03:38:19 -08001367
Matus Fabian5f224992018-01-25 21:59:16 -08001368 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip, tag=tag)
Matus Fabian2ba92e32017-08-21 07:05:03 -07001369 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1370 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1371 is_inside=0)
Matus Fabian5f224992018-01-25 21:59:16 -08001372 sm = self.vapi.nat44_static_mapping_dump()
1373 self.assertEqual(len(sm), 1)
1374 self.assertEqual((sm[0].tag).split('\0', 1)[0], tag)
Matus Fabiande886752016-12-07 03:38:19 -08001375
1376 # out2in
1377 pkts = self.create_stream_out(self.pg1, nat_ip)
1378 self.pg1.add_stream(pkts)
1379 self.pg_enable_capture(self.pg_interfaces)
1380 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001381 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001382 self.verify_capture_in(capture, self.pg0)
1383
1384 # in2out
1385 pkts = self.create_stream_in(self.pg0, self.pg1)
1386 self.pg0.add_stream(pkts)
1387 self.pg_enable_capture(self.pg_interfaces)
1388 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001389 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001390 self.verify_capture_out(capture, nat_ip, True)
1391
1392 def test_static_with_port_in(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001393 """ 1:1 NAPT initialized from inside network """
Matus Fabiande886752016-12-07 03:38:19 -08001394
1395 self.tcp_port_out = 3606
1396 self.udp_port_out = 3607
1397 self.icmp_id_out = 3608
1398
Matus Fabian2ba92e32017-08-21 07:05:03 -07001399 self.nat44_add_address(self.nat_addr)
1400 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1401 self.tcp_port_in, self.tcp_port_out,
1402 proto=IP_PROTOS.tcp)
1403 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1404 self.udp_port_in, self.udp_port_out,
1405 proto=IP_PROTOS.udp)
1406 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1407 self.icmp_id_in, self.icmp_id_out,
1408 proto=IP_PROTOS.icmp)
1409 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1410 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1411 is_inside=0)
Matus Fabiande886752016-12-07 03:38:19 -08001412
1413 # in2out
1414 pkts = self.create_stream_in(self.pg0, self.pg1)
1415 self.pg0.add_stream(pkts)
1416 self.pg_enable_capture(self.pg_interfaces)
1417 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001418 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001419 self.verify_capture_out(capture)
1420
1421 # out2in
1422 pkts = self.create_stream_out(self.pg1)
1423 self.pg1.add_stream(pkts)
1424 self.pg_enable_capture(self.pg_interfaces)
1425 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001426 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001427 self.verify_capture_in(capture, self.pg0)
1428
1429 def test_static_with_port_out(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001430 """ 1:1 NAPT initialized from outside network """
Matus Fabiande886752016-12-07 03:38:19 -08001431
1432 self.tcp_port_out = 30606
1433 self.udp_port_out = 30607
1434 self.icmp_id_out = 30608
1435
Matus Fabian2ba92e32017-08-21 07:05:03 -07001436 self.nat44_add_address(self.nat_addr)
1437 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1438 self.tcp_port_in, self.tcp_port_out,
1439 proto=IP_PROTOS.tcp)
1440 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1441 self.udp_port_in, self.udp_port_out,
1442 proto=IP_PROTOS.udp)
1443 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1444 self.icmp_id_in, self.icmp_id_out,
1445 proto=IP_PROTOS.icmp)
1446 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1447 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1448 is_inside=0)
Matus Fabiande886752016-12-07 03:38:19 -08001449
1450 # out2in
1451 pkts = self.create_stream_out(self.pg1)
1452 self.pg1.add_stream(pkts)
1453 self.pg_enable_capture(self.pg_interfaces)
1454 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001455 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001456 self.verify_capture_in(capture, self.pg0)
1457
1458 # in2out
1459 pkts = self.create_stream_in(self.pg0, self.pg1)
1460 self.pg0.add_stream(pkts)
1461 self.pg_enable_capture(self.pg_interfaces)
1462 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001463 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001464 self.verify_capture_out(capture)
1465
Matus Fabiane82488f2018-01-18 03:38:45 -08001466 def test_static_with_port_out2(self):
1467 """ 1:1 NAPT symmetrical rule """
1468
1469 external_port = 80
1470 local_port = 8080
1471
1472 self.vapi.nat44_forwarding_enable_disable(1)
1473 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1474 local_port, external_port,
1475 proto=IP_PROTOS.tcp, out2in_only=1)
1476 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1477 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1478 is_inside=0)
1479
1480 # from client to service
1481 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
1482 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
1483 TCP(sport=12345, dport=external_port))
1484 self.pg1.add_stream(p)
1485 self.pg_enable_capture(self.pg_interfaces)
1486 self.pg_start()
1487 capture = self.pg0.get_capture(1)
1488 p = capture[0]
Matus Fabiane82488f2018-01-18 03:38:45 -08001489 try:
1490 ip = p[IP]
1491 tcp = p[TCP]
1492 self.assertEqual(ip.dst, self.pg0.remote_ip4)
1493 self.assertEqual(tcp.dport, local_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02001494 self.assert_packet_checksums_valid(p)
Matus Fabiane82488f2018-01-18 03:38:45 -08001495 except:
1496 self.logger.error(ppp("Unexpected or invalid packet:", p))
1497 raise
1498
Matus Fabian87233b52018-01-26 03:17:01 -08001499 # ICMP error
1500 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1501 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
1502 ICMP(type=11) / capture[0][IP])
1503 self.pg0.add_stream(p)
1504 self.pg_enable_capture(self.pg_interfaces)
1505 self.pg_start()
1506 capture = self.pg1.get_capture(1)
1507 p = capture[0]
1508 try:
1509 self.assertEqual(p[IP].src, self.nat_addr)
1510 inner = p[IPerror]
1511 self.assertEqual(inner.dst, self.nat_addr)
1512 self.assertEqual(inner[TCPerror].dport, external_port)
1513 except:
1514 self.logger.error(ppp("Unexpected or invalid packet:", p))
1515 raise
1516
Matus Fabiane82488f2018-01-18 03:38:45 -08001517 # from service back to client
1518 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
1519 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
1520 TCP(sport=local_port, dport=12345))
1521 self.pg0.add_stream(p)
1522 self.pg_enable_capture(self.pg_interfaces)
1523 self.pg_start()
1524 capture = self.pg1.get_capture(1)
1525 p = capture[0]
1526 try:
1527 ip = p[IP]
1528 tcp = p[TCP]
1529 self.assertEqual(ip.src, self.nat_addr)
1530 self.assertEqual(tcp.sport, external_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02001531 self.assert_packet_checksums_valid(p)
Matus Fabiane82488f2018-01-18 03:38:45 -08001532 except:
1533 self.logger.error(ppp("Unexpected or invalid packet:", p))
1534 raise
1535
Matus Fabian87233b52018-01-26 03:17:01 -08001536 # ICMP error
1537 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1538 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
1539 ICMP(type=11) / capture[0][IP])
1540 self.pg1.add_stream(p)
1541 self.pg_enable_capture(self.pg_interfaces)
1542 self.pg_start()
1543 capture = self.pg0.get_capture(1)
1544 p = capture[0]
1545 try:
1546 self.assertEqual(p[IP].dst, self.pg0.remote_ip4)
1547 inner = p[IPerror]
1548 self.assertEqual(inner.src, self.pg0.remote_ip4)
1549 self.assertEqual(inner[TCPerror].sport, local_port)
1550 except:
1551 self.logger.error(ppp("Unexpected or invalid packet:", p))
1552 raise
1553
Matus Fabiane82488f2018-01-18 03:38:45 -08001554 # from client to server (no translation)
1555 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
1556 IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
1557 TCP(sport=12346, dport=local_port))
1558 self.pg1.add_stream(p)
1559 self.pg_enable_capture(self.pg_interfaces)
1560 self.pg_start()
1561 capture = self.pg0.get_capture(1)
1562 p = capture[0]
Matus Fabiane82488f2018-01-18 03:38:45 -08001563 try:
1564 ip = p[IP]
1565 tcp = p[TCP]
1566 self.assertEqual(ip.dst, self.pg0.remote_ip4)
1567 self.assertEqual(tcp.dport, local_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02001568 self.assert_packet_checksums_valid(p)
Matus Fabiane82488f2018-01-18 03:38:45 -08001569 except:
1570 self.logger.error(ppp("Unexpected or invalid packet:", p))
1571 raise
1572
1573 # from service back to client (no translation)
1574 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
1575 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
1576 TCP(sport=local_port, dport=12346))
1577 self.pg0.add_stream(p)
1578 self.pg_enable_capture(self.pg_interfaces)
1579 self.pg_start()
1580 capture = self.pg1.get_capture(1)
1581 p = capture[0]
1582 try:
1583 ip = p[IP]
1584 tcp = p[TCP]
1585 self.assertEqual(ip.src, self.pg0.remote_ip4)
1586 self.assertEqual(tcp.sport, local_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02001587 self.assert_packet_checksums_valid(p)
Matus Fabiane82488f2018-01-18 03:38:45 -08001588 except:
1589 self.logger.error(ppp("Unexpected or invalid packet:", p))
1590 raise
1591
Matus Fabiande886752016-12-07 03:38:19 -08001592 def test_static_vrf_aware(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001593 """ 1:1 NAT VRF awareness """
Matus Fabiande886752016-12-07 03:38:19 -08001594
1595 nat_ip1 = "10.0.0.30"
1596 nat_ip2 = "10.0.0.40"
1597 self.tcp_port_out = 6303
1598 self.udp_port_out = 6304
1599 self.icmp_id_out = 6305
1600
Matus Fabian2ba92e32017-08-21 07:05:03 -07001601 self.nat44_add_static_mapping(self.pg4.remote_ip4, nat_ip1,
1602 vrf_id=10)
1603 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip2,
1604 vrf_id=10)
1605 self.vapi.nat44_interface_add_del_feature(self.pg3.sw_if_index,
1606 is_inside=0)
1607 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1608 self.vapi.nat44_interface_add_del_feature(self.pg4.sw_if_index)
Matus Fabiande886752016-12-07 03:38:19 -08001609
Matus Fabian2ba92e32017-08-21 07:05:03 -07001610 # inside interface VRF match NAT44 static mapping VRF
Matus Fabiande886752016-12-07 03:38:19 -08001611 pkts = self.create_stream_in(self.pg4, self.pg3)
1612 self.pg4.add_stream(pkts)
1613 self.pg_enable_capture(self.pg_interfaces)
1614 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001615 capture = self.pg3.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001616 self.verify_capture_out(capture, nat_ip1, True)
1617
Matus Fabian2ba92e32017-08-21 07:05:03 -07001618 # inside interface VRF don't match NAT44 static mapping VRF (packets
Matus Fabiande886752016-12-07 03:38:19 -08001619 # are dropped)
1620 pkts = self.create_stream_in(self.pg0, self.pg3)
1621 self.pg0.add_stream(pkts)
1622 self.pg_enable_capture(self.pg_interfaces)
1623 self.pg_start()
Klement Sekera9225dee2016-12-12 08:36:58 +01001624 self.pg3.assert_nothing_captured()
Matus Fabiande886752016-12-07 03:38:19 -08001625
Matus Fabianb793d092018-01-31 05:50:21 -08001626 def test_dynamic_to_static(self):
1627 """ Switch from dynamic translation to 1:1NAT """
1628 nat_ip = "10.0.0.10"
1629 self.tcp_port_out = 6303
1630 self.udp_port_out = 6304
1631 self.icmp_id_out = 6305
1632
1633 self.nat44_add_address(self.nat_addr)
1634 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1635 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1636 is_inside=0)
1637
1638 # dynamic
1639 pkts = self.create_stream_in(self.pg0, self.pg1)
1640 self.pg0.add_stream(pkts)
1641 self.pg_enable_capture(self.pg_interfaces)
1642 self.pg_start()
1643 capture = self.pg1.get_capture(len(pkts))
1644 self.verify_capture_out(capture)
1645
1646 # 1:1NAT
1647 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
1648 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
1649 self.assertEqual(len(sessions), 0)
1650 pkts = self.create_stream_in(self.pg0, self.pg1)
1651 self.pg0.add_stream(pkts)
1652 self.pg_enable_capture(self.pg_interfaces)
1653 self.pg_start()
1654 capture = self.pg1.get_capture(len(pkts))
1655 self.verify_capture_out(capture, nat_ip, True)
1656
Matus Fabianab7a8052017-11-28 04:29:41 -08001657 def test_identity_nat(self):
1658 """ Identity NAT """
1659
1660 self.vapi.nat44_add_del_identity_mapping(ip=self.pg0.remote_ip4n)
1661 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1662 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1663 is_inside=0)
1664
1665 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
1666 IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
1667 TCP(sport=12345, dport=56789))
1668 self.pg1.add_stream(p)
1669 self.pg_enable_capture(self.pg_interfaces)
1670 self.pg_start()
1671 capture = self.pg0.get_capture(1)
1672 p = capture[0]
1673 try:
1674 ip = p[IP]
1675 tcp = p[TCP]
1676 self.assertEqual(ip.dst, self.pg0.remote_ip4)
1677 self.assertEqual(ip.src, self.pg1.remote_ip4)
1678 self.assertEqual(tcp.dport, 56789)
1679 self.assertEqual(tcp.sport, 12345)
Klement Sekerad81ae412018-05-16 10:52:54 +02001680 self.assert_packet_checksums_valid(p)
Matus Fabianab7a8052017-11-28 04:29:41 -08001681 except:
1682 self.logger.error(ppp("Unexpected or invalid packet:", p))
1683 raise
1684
Matus Fabian704018c2017-09-04 02:17:18 -07001685 def test_static_lb(self):
1686 """ NAT44 local service load balancing """
1687 external_addr_n = socket.inet_pton(socket.AF_INET, self.nat_addr)
1688 external_port = 80
1689 local_port = 8080
1690 server1 = self.pg0.remote_hosts[0]
1691 server2 = self.pg0.remote_hosts[1]
1692
1693 locals = [{'addr': server1.ip4n,
1694 'port': local_port,
1695 'probability': 70},
1696 {'addr': server2.ip4n,
1697 'port': local_port,
1698 'probability': 30}]
1699
1700 self.nat44_add_address(self.nat_addr)
1701 self.vapi.nat44_add_del_lb_static_mapping(external_addr_n,
1702 external_port,
1703 IP_PROTOS.tcp,
1704 local_num=len(locals),
1705 locals=locals)
1706 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1707 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1708 is_inside=0)
1709
1710 # from client to service
1711 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
1712 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
1713 TCP(sport=12345, dport=external_port))
1714 self.pg1.add_stream(p)
1715 self.pg_enable_capture(self.pg_interfaces)
1716 self.pg_start()
1717 capture = self.pg0.get_capture(1)
1718 p = capture[0]
1719 server = None
1720 try:
1721 ip = p[IP]
1722 tcp = p[TCP]
1723 self.assertIn(ip.dst, [server1.ip4, server2.ip4])
1724 if ip.dst == server1.ip4:
1725 server = server1
1726 else:
1727 server = server2
1728 self.assertEqual(tcp.dport, local_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02001729 self.assert_packet_checksums_valid(p)
Matus Fabian704018c2017-09-04 02:17:18 -07001730 except:
1731 self.logger.error(ppp("Unexpected or invalid packet:", p))
1732 raise
1733
1734 # from service back to client
1735 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
1736 IP(src=server.ip4, dst=self.pg1.remote_ip4) /
1737 TCP(sport=local_port, dport=12345))
1738 self.pg0.add_stream(p)
1739 self.pg_enable_capture(self.pg_interfaces)
1740 self.pg_start()
1741 capture = self.pg1.get_capture(1)
1742 p = capture[0]
1743 try:
1744 ip = p[IP]
1745 tcp = p[TCP]
1746 self.assertEqual(ip.src, self.nat_addr)
1747 self.assertEqual(tcp.sport, external_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02001748 self.assert_packet_checksums_valid(p)
Matus Fabian704018c2017-09-04 02:17:18 -07001749 except:
1750 self.logger.error(ppp("Unexpected or invalid packet:", p))
1751 raise
1752
Matus Fabian70a26ac2018-05-14 06:20:28 -07001753 sessions = self.vapi.nat44_user_session_dump(server.ip4n, 0)
1754 self.assertEqual(len(sessions), 1)
1755 self.assertTrue(sessions[0].ext_host_valid)
1756 self.vapi.nat44_del_session(
1757 sessions[0].inside_ip_address,
1758 sessions[0].inside_port,
1759 sessions[0].protocol,
1760 ext_host_address=sessions[0].ext_host_address,
1761 ext_host_port=sessions[0].ext_host_port)
1762 sessions = self.vapi.nat44_user_session_dump(server.ip4n, 0)
1763 self.assertEqual(len(sessions), 0)
1764
Matus Fabian2aad8762018-03-07 04:57:22 -08001765 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
1766 def test_static_lb_multi_clients(self):
1767 """ NAT44 local service load balancing - multiple clients"""
1768
1769 external_addr_n = socket.inet_pton(socket.AF_INET, self.nat_addr)
1770 external_port = 80
1771 local_port = 8080
1772 server1 = self.pg0.remote_hosts[0]
1773 server2 = self.pg0.remote_hosts[1]
1774
1775 locals = [{'addr': server1.ip4n,
1776 'port': local_port,
1777 'probability': 90},
1778 {'addr': server2.ip4n,
1779 'port': local_port,
1780 'probability': 10}]
1781
1782 self.nat44_add_address(self.nat_addr)
1783 self.vapi.nat44_add_del_lb_static_mapping(external_addr_n,
1784 external_port,
1785 IP_PROTOS.tcp,
1786 local_num=len(locals),
1787 locals=locals)
1788 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1789 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1790 is_inside=0)
1791
Matus Fabian704018c2017-09-04 02:17:18 -07001792 server1_n = 0
1793 server2_n = 0
Matus Fabian2aad8762018-03-07 04:57:22 -08001794 clients = ip4_range(self.pg1.remote_ip4, 10, 50)
Matus Fabian704018c2017-09-04 02:17:18 -07001795 pkts = []
1796 for client in clients:
1797 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
1798 IP(src=client, dst=self.nat_addr) /
1799 TCP(sport=12345, dport=external_port))
1800 pkts.append(p)
1801 self.pg1.add_stream(pkts)
1802 self.pg_enable_capture(self.pg_interfaces)
1803 self.pg_start()
1804 capture = self.pg0.get_capture(len(pkts))
1805 for p in capture:
1806 if p[IP].dst == server1.ip4:
1807 server1_n += 1
1808 else:
1809 server2_n += 1
1810 self.assertTrue(server1_n > server2_n)
1811
Matus Fabian240b5ef2018-01-11 04:09:17 -08001812 def test_static_lb_2(self):
1813 """ NAT44 local service load balancing (asymmetrical rule) """
1814 external_addr_n = socket.inet_pton(socket.AF_INET, self.nat_addr)
1815 external_port = 80
1816 local_port = 8080
1817 server1 = self.pg0.remote_hosts[0]
1818 server2 = self.pg0.remote_hosts[1]
1819
1820 locals = [{'addr': server1.ip4n,
1821 'port': local_port,
1822 'probability': 70},
1823 {'addr': server2.ip4n,
1824 'port': local_port,
1825 'probability': 30}]
1826
1827 self.vapi.nat44_forwarding_enable_disable(1)
1828 self.vapi.nat44_add_del_lb_static_mapping(external_addr_n,
1829 external_port,
1830 IP_PROTOS.tcp,
1831 out2in_only=1,
1832 local_num=len(locals),
1833 locals=locals)
1834 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1835 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1836 is_inside=0)
1837
1838 # from client to service
1839 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
1840 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
1841 TCP(sport=12345, dport=external_port))
1842 self.pg1.add_stream(p)
1843 self.pg_enable_capture(self.pg_interfaces)
1844 self.pg_start()
1845 capture = self.pg0.get_capture(1)
1846 p = capture[0]
1847 server = None
1848 try:
1849 ip = p[IP]
1850 tcp = p[TCP]
1851 self.assertIn(ip.dst, [server1.ip4, server2.ip4])
1852 if ip.dst == server1.ip4:
1853 server = server1
1854 else:
1855 server = server2
1856 self.assertEqual(tcp.dport, local_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02001857 self.assert_packet_checksums_valid(p)
Matus Fabian240b5ef2018-01-11 04:09:17 -08001858 except:
1859 self.logger.error(ppp("Unexpected or invalid packet:", p))
1860 raise
1861
1862 # from service back to client
1863 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
1864 IP(src=server.ip4, dst=self.pg1.remote_ip4) /
1865 TCP(sport=local_port, dport=12345))
1866 self.pg0.add_stream(p)
1867 self.pg_enable_capture(self.pg_interfaces)
1868 self.pg_start()
1869 capture = self.pg1.get_capture(1)
1870 p = capture[0]
1871 try:
1872 ip = p[IP]
1873 tcp = p[TCP]
1874 self.assertEqual(ip.src, self.nat_addr)
1875 self.assertEqual(tcp.sport, external_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02001876 self.assert_packet_checksums_valid(p)
Matus Fabian240b5ef2018-01-11 04:09:17 -08001877 except:
1878 self.logger.error(ppp("Unexpected or invalid packet:", p))
1879 raise
1880
1881 # from client to server (no translation)
1882 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
1883 IP(src=self.pg1.remote_ip4, dst=server1.ip4) /
1884 TCP(sport=12346, dport=local_port))
1885 self.pg1.add_stream(p)
1886 self.pg_enable_capture(self.pg_interfaces)
1887 self.pg_start()
1888 capture = self.pg0.get_capture(1)
1889 p = capture[0]
1890 server = None
1891 try:
1892 ip = p[IP]
1893 tcp = p[TCP]
1894 self.assertEqual(ip.dst, server1.ip4)
1895 self.assertEqual(tcp.dport, local_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02001896 self.assert_packet_checksums_valid(p)
Matus Fabian240b5ef2018-01-11 04:09:17 -08001897 except:
1898 self.logger.error(ppp("Unexpected or invalid packet:", p))
1899 raise
1900
1901 # from service back to client (no translation)
1902 p = (Ether(src=server1.mac, dst=self.pg0.local_mac) /
1903 IP(src=server1.ip4, dst=self.pg1.remote_ip4) /
1904 TCP(sport=local_port, dport=12346))
1905 self.pg0.add_stream(p)
1906 self.pg_enable_capture(self.pg_interfaces)
1907 self.pg_start()
1908 capture = self.pg1.get_capture(1)
1909 p = capture[0]
1910 try:
1911 ip = p[IP]
1912 tcp = p[TCP]
1913 self.assertEqual(ip.src, server1.ip4)
1914 self.assertEqual(tcp.sport, local_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02001915 self.assert_packet_checksums_valid(p)
Matus Fabian240b5ef2018-01-11 04:09:17 -08001916 except:
1917 self.logger.error(ppp("Unexpected or invalid packet:", p))
1918 raise
1919
Matus Fabiande886752016-12-07 03:38:19 -08001920 def test_multiple_inside_interfaces(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001921 """ NAT44 multiple non-overlapping address space inside interfaces """
Matus Fabiande886752016-12-07 03:38:19 -08001922
Matus Fabian2ba92e32017-08-21 07:05:03 -07001923 self.nat44_add_address(self.nat_addr)
1924 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1925 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
1926 self.vapi.nat44_interface_add_del_feature(self.pg3.sw_if_index,
1927 is_inside=0)
Matus Fabiande886752016-12-07 03:38:19 -08001928
Matus Fabian2ba92e32017-08-21 07:05:03 -07001929 # between two NAT44 inside interfaces (no translation)
Matus Fabian675a69c2017-01-18 01:46:01 -08001930 pkts = self.create_stream_in(self.pg0, self.pg1)
1931 self.pg0.add_stream(pkts)
1932 self.pg_enable_capture(self.pg_interfaces)
1933 self.pg_start()
1934 capture = self.pg1.get_capture(len(pkts))
1935 self.verify_capture_no_translation(capture, self.pg0, self.pg1)
1936
Matus Fabian2ba92e32017-08-21 07:05:03 -07001937 # from NAT44 inside to interface without NAT44 feature (no translation)
Matus Fabian675a69c2017-01-18 01:46:01 -08001938 pkts = self.create_stream_in(self.pg0, self.pg2)
1939 self.pg0.add_stream(pkts)
1940 self.pg_enable_capture(self.pg_interfaces)
1941 self.pg_start()
1942 capture = self.pg2.get_capture(len(pkts))
1943 self.verify_capture_no_translation(capture, self.pg0, self.pg2)
1944
Matus Fabiande886752016-12-07 03:38:19 -08001945 # in2out 1st interface
1946 pkts = self.create_stream_in(self.pg0, self.pg3)
1947 self.pg0.add_stream(pkts)
1948 self.pg_enable_capture(self.pg_interfaces)
1949 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001950 capture = self.pg3.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001951 self.verify_capture_out(capture)
1952
1953 # out2in 1st interface
1954 pkts = self.create_stream_out(self.pg3)
1955 self.pg3.add_stream(pkts)
1956 self.pg_enable_capture(self.pg_interfaces)
1957 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001958 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001959 self.verify_capture_in(capture, self.pg0)
1960
1961 # in2out 2nd interface
1962 pkts = self.create_stream_in(self.pg1, self.pg3)
1963 self.pg1.add_stream(pkts)
1964 self.pg_enable_capture(self.pg_interfaces)
1965 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001966 capture = self.pg3.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001967 self.verify_capture_out(capture)
1968
1969 # out2in 2nd interface
1970 pkts = self.create_stream_out(self.pg3)
1971 self.pg3.add_stream(pkts)
1972 self.pg_enable_capture(self.pg_interfaces)
1973 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001974 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001975 self.verify_capture_in(capture, self.pg1)
1976
Matus Fabiande886752016-12-07 03:38:19 -08001977 def test_inside_overlapping_interfaces(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001978 """ NAT44 multiple inside interfaces with overlapping address space """
Matus Fabiande886752016-12-07 03:38:19 -08001979
Matus Fabian675a69c2017-01-18 01:46:01 -08001980 static_nat_ip = "10.0.0.10"
Matus Fabian2ba92e32017-08-21 07:05:03 -07001981 self.nat44_add_address(self.nat_addr)
1982 self.vapi.nat44_interface_add_del_feature(self.pg3.sw_if_index,
1983 is_inside=0)
1984 self.vapi.nat44_interface_add_del_feature(self.pg4.sw_if_index)
1985 self.vapi.nat44_interface_add_del_feature(self.pg5.sw_if_index)
1986 self.vapi.nat44_interface_add_del_feature(self.pg6.sw_if_index)
1987 self.nat44_add_static_mapping(self.pg6.remote_ip4, static_nat_ip,
1988 vrf_id=20)
Matus Fabian675a69c2017-01-18 01:46:01 -08001989
Matus Fabian2ba92e32017-08-21 07:05:03 -07001990 # between NAT44 inside interfaces with same VRF (no translation)
Matus Fabian675a69c2017-01-18 01:46:01 -08001991 pkts = self.create_stream_in(self.pg4, self.pg5)
1992 self.pg4.add_stream(pkts)
1993 self.pg_enable_capture(self.pg_interfaces)
1994 self.pg_start()
1995 capture = self.pg5.get_capture(len(pkts))
1996 self.verify_capture_no_translation(capture, self.pg4, self.pg5)
1997
Matus Fabian2ba92e32017-08-21 07:05:03 -07001998 # between NAT44 inside interfaces with different VRF (hairpinning)
Matus Fabian675a69c2017-01-18 01:46:01 -08001999 p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
2000 IP(src=self.pg4.remote_ip4, dst=static_nat_ip) /
2001 TCP(sport=1234, dport=5678))
2002 self.pg4.add_stream(p)
2003 self.pg_enable_capture(self.pg_interfaces)
2004 self.pg_start()
2005 capture = self.pg6.get_capture(1)
2006 p = capture[0]
2007 try:
2008 ip = p[IP]
2009 tcp = p[TCP]
Matus Fabian2ba92e32017-08-21 07:05:03 -07002010 self.assertEqual(ip.src, self.nat_addr)
Matus Fabian675a69c2017-01-18 01:46:01 -08002011 self.assertEqual(ip.dst, self.pg6.remote_ip4)
2012 self.assertNotEqual(tcp.sport, 1234)
2013 self.assertEqual(tcp.dport, 5678)
2014 except:
2015 self.logger.error(ppp("Unexpected or invalid packet:", p))
2016 raise
Matus Fabiande886752016-12-07 03:38:19 -08002017
2018 # in2out 1st interface
2019 pkts = self.create_stream_in(self.pg4, self.pg3)
2020 self.pg4.add_stream(pkts)
2021 self.pg_enable_capture(self.pg_interfaces)
2022 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002023 capture = self.pg3.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002024 self.verify_capture_out(capture)
2025
2026 # out2in 1st interface
2027 pkts = self.create_stream_out(self.pg3)
2028 self.pg3.add_stream(pkts)
2029 self.pg_enable_capture(self.pg_interfaces)
2030 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002031 capture = self.pg4.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002032 self.verify_capture_in(capture, self.pg4)
2033
2034 # in2out 2nd interface
2035 pkts = self.create_stream_in(self.pg5, self.pg3)
2036 self.pg5.add_stream(pkts)
2037 self.pg_enable_capture(self.pg_interfaces)
2038 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002039 capture = self.pg3.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002040 self.verify_capture_out(capture)
2041
2042 # out2in 2nd interface
2043 pkts = self.create_stream_out(self.pg3)
2044 self.pg3.add_stream(pkts)
2045 self.pg_enable_capture(self.pg_interfaces)
2046 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002047 capture = self.pg5.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002048 self.verify_capture_in(capture, self.pg5)
2049
magalik23caa882017-02-08 23:25:45 -08002050 # pg5 session dump
Matus Fabian2ba92e32017-08-21 07:05:03 -07002051 addresses = self.vapi.nat44_address_dump()
magalik23caa882017-02-08 23:25:45 -08002052 self.assertEqual(len(addresses), 1)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002053 sessions = self.vapi.nat44_user_session_dump(self.pg5.remote_ip4n, 10)
magalik23caa882017-02-08 23:25:45 -08002054 self.assertEqual(len(sessions), 3)
2055 for session in sessions:
2056 self.assertFalse(session.is_static)
2057 self.assertEqual(session.inside_ip_address[0:4],
2058 self.pg5.remote_ip4n)
2059 self.assertEqual(session.outside_ip_address,
2060 addresses[0].ip_address)
2061 self.assertEqual(sessions[0].protocol, IP_PROTOS.tcp)
2062 self.assertEqual(sessions[1].protocol, IP_PROTOS.udp)
2063 self.assertEqual(sessions[2].protocol, IP_PROTOS.icmp)
2064 self.assertEqual(sessions[0].inside_port, self.tcp_port_in)
2065 self.assertEqual(sessions[1].inside_port, self.udp_port_in)
2066 self.assertEqual(sessions[2].inside_port, self.icmp_id_in)
2067 self.assertEqual(sessions[0].outside_port, self.tcp_port_out)
2068 self.assertEqual(sessions[1].outside_port, self.udp_port_out)
2069 self.assertEqual(sessions[2].outside_port, self.icmp_id_out)
2070
Matus Fabiande886752016-12-07 03:38:19 -08002071 # in2out 3rd interface
2072 pkts = self.create_stream_in(self.pg6, self.pg3)
2073 self.pg6.add_stream(pkts)
2074 self.pg_enable_capture(self.pg_interfaces)
2075 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002076 capture = self.pg3.get_capture(len(pkts))
Matus Fabian675a69c2017-01-18 01:46:01 -08002077 self.verify_capture_out(capture, static_nat_ip, True)
Matus Fabiande886752016-12-07 03:38:19 -08002078
2079 # out2in 3rd interface
Matus Fabian675a69c2017-01-18 01:46:01 -08002080 pkts = self.create_stream_out(self.pg3, static_nat_ip)
Matus Fabiande886752016-12-07 03:38:19 -08002081 self.pg3.add_stream(pkts)
2082 self.pg_enable_capture(self.pg_interfaces)
2083 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002084 capture = self.pg6.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002085 self.verify_capture_in(capture, self.pg6)
2086
magalik23caa882017-02-08 23:25:45 -08002087 # general user and session dump verifications
Matus Fabian2ba92e32017-08-21 07:05:03 -07002088 users = self.vapi.nat44_user_dump()
magalik23caa882017-02-08 23:25:45 -08002089 self.assertTrue(len(users) >= 3)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002090 addresses = self.vapi.nat44_address_dump()
magalik23caa882017-02-08 23:25:45 -08002091 self.assertEqual(len(addresses), 1)
2092 for user in users:
Matus Fabian2ba92e32017-08-21 07:05:03 -07002093 sessions = self.vapi.nat44_user_session_dump(user.ip_address,
2094 user.vrf_id)
magalik23caa882017-02-08 23:25:45 -08002095 for session in sessions:
2096 self.assertEqual(user.ip_address, session.inside_ip_address)
2097 self.assertTrue(session.total_bytes > session.total_pkts > 0)
2098 self.assertTrue(session.protocol in
2099 [IP_PROTOS.tcp, IP_PROTOS.udp,
2100 IP_PROTOS.icmp])
Matus Fabian70a26ac2018-05-14 06:20:28 -07002101 self.assertFalse(session.ext_host_valid)
magalik23caa882017-02-08 23:25:45 -08002102
2103 # pg4 session dump
Matus Fabian2ba92e32017-08-21 07:05:03 -07002104 sessions = self.vapi.nat44_user_session_dump(self.pg4.remote_ip4n, 10)
magalik23caa882017-02-08 23:25:45 -08002105 self.assertTrue(len(sessions) >= 4)
2106 for session in sessions:
2107 self.assertFalse(session.is_static)
2108 self.assertEqual(session.inside_ip_address[0:4],
2109 self.pg4.remote_ip4n)
2110 self.assertEqual(session.outside_ip_address,
2111 addresses[0].ip_address)
2112
2113 # pg6 session dump
Matus Fabian2ba92e32017-08-21 07:05:03 -07002114 sessions = self.vapi.nat44_user_session_dump(self.pg6.remote_ip4n, 20)
magalik23caa882017-02-08 23:25:45 -08002115 self.assertTrue(len(sessions) >= 3)
2116 for session in sessions:
2117 self.assertTrue(session.is_static)
2118 self.assertEqual(session.inside_ip_address[0:4],
2119 self.pg6.remote_ip4n)
2120 self.assertEqual(map(ord, session.outside_ip_address[0:4]),
2121 map(int, static_nat_ip.split('.')))
2122 self.assertTrue(session.inside_port in
2123 [self.tcp_port_in, self.udp_port_in,
2124 self.icmp_id_in])
2125
Matus Fabianf78a70d2016-12-12 04:30:39 -08002126 def test_hairpinning(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002127 """ NAT44 hairpinning - 1:1 NAPT """
Matus Fabianf78a70d2016-12-12 04:30:39 -08002128
2129 host = self.pg0.remote_hosts[0]
2130 server = self.pg0.remote_hosts[1]
2131 host_in_port = 1234
2132 host_out_port = 0
2133 server_in_port = 5678
2134 server_out_port = 8765
2135
Matus Fabian2ba92e32017-08-21 07:05:03 -07002136 self.nat44_add_address(self.nat_addr)
2137 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2138 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2139 is_inside=0)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002140 # add static mapping for server
Matus Fabian2ba92e32017-08-21 07:05:03 -07002141 self.nat44_add_static_mapping(server.ip4, self.nat_addr,
2142 server_in_port, server_out_port,
2143 proto=IP_PROTOS.tcp)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002144
2145 # send packet from host to server
2146 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002147 IP(src=host.ip4, dst=self.nat_addr) /
Matus Fabianf78a70d2016-12-12 04:30:39 -08002148 TCP(sport=host_in_port, dport=server_out_port))
2149 self.pg0.add_stream(p)
2150 self.pg_enable_capture(self.pg_interfaces)
2151 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002152 capture = self.pg0.get_capture(1)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002153 p = capture[0]
2154 try:
2155 ip = p[IP]
2156 tcp = p[TCP]
Matus Fabian2ba92e32017-08-21 07:05:03 -07002157 self.assertEqual(ip.src, self.nat_addr)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002158 self.assertEqual(ip.dst, server.ip4)
2159 self.assertNotEqual(tcp.sport, host_in_port)
2160 self.assertEqual(tcp.dport, server_in_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02002161 self.assert_packet_checksums_valid(p)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002162 host_out_port = tcp.sport
2163 except:
Klement Sekera9225dee2016-12-12 08:36:58 +01002164 self.logger.error(ppp("Unexpected or invalid packet:", p))
Matus Fabianf78a70d2016-12-12 04:30:39 -08002165 raise
2166
2167 # send reply from server to host
2168 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002169 IP(src=server.ip4, dst=self.nat_addr) /
Matus Fabianf78a70d2016-12-12 04:30:39 -08002170 TCP(sport=server_in_port, dport=host_out_port))
2171 self.pg0.add_stream(p)
2172 self.pg_enable_capture(self.pg_interfaces)
2173 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002174 capture = self.pg0.get_capture(1)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002175 p = capture[0]
2176 try:
2177 ip = p[IP]
2178 tcp = p[TCP]
Matus Fabian2ba92e32017-08-21 07:05:03 -07002179 self.assertEqual(ip.src, self.nat_addr)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002180 self.assertEqual(ip.dst, host.ip4)
2181 self.assertEqual(tcp.sport, server_out_port)
2182 self.assertEqual(tcp.dport, host_in_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02002183 self.assert_packet_checksums_valid(p)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002184 except:
Matus Fabiane82488f2018-01-18 03:38:45 -08002185 self.logger.error(ppp("Unexpected or invalid packet:", p))
Matus Fabianf78a70d2016-12-12 04:30:39 -08002186 raise
2187
Matus Fabian6fa74c62017-06-05 05:55:48 -07002188 def test_hairpinning2(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002189 """ NAT44 hairpinning - 1:1 NAT"""
Matus Fabian6fa74c62017-06-05 05:55:48 -07002190
2191 server1_nat_ip = "10.0.0.10"
2192 server2_nat_ip = "10.0.0.11"
2193 host = self.pg0.remote_hosts[0]
2194 server1 = self.pg0.remote_hosts[1]
2195 server2 = self.pg0.remote_hosts[2]
2196 server_tcp_port = 22
2197 server_udp_port = 20
2198
Matus Fabian2ba92e32017-08-21 07:05:03 -07002199 self.nat44_add_address(self.nat_addr)
2200 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2201 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2202 is_inside=0)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002203
2204 # add static mapping for servers
Matus Fabian2ba92e32017-08-21 07:05:03 -07002205 self.nat44_add_static_mapping(server1.ip4, server1_nat_ip)
2206 self.nat44_add_static_mapping(server2.ip4, server2_nat_ip)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002207
2208 # host to server1
2209 pkts = []
2210 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2211 IP(src=host.ip4, dst=server1_nat_ip) /
2212 TCP(sport=self.tcp_port_in, dport=server_tcp_port))
2213 pkts.append(p)
2214 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2215 IP(src=host.ip4, dst=server1_nat_ip) /
2216 UDP(sport=self.udp_port_in, dport=server_udp_port))
2217 pkts.append(p)
2218 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2219 IP(src=host.ip4, dst=server1_nat_ip) /
2220 ICMP(id=self.icmp_id_in, type='echo-request'))
2221 pkts.append(p)
2222 self.pg0.add_stream(pkts)
2223 self.pg_enable_capture(self.pg_interfaces)
2224 self.pg_start()
2225 capture = self.pg0.get_capture(len(pkts))
2226 for packet in capture:
2227 try:
Matus Fabian2ba92e32017-08-21 07:05:03 -07002228 self.assertEqual(packet[IP].src, self.nat_addr)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002229 self.assertEqual(packet[IP].dst, server1.ip4)
2230 if packet.haslayer(TCP):
2231 self.assertNotEqual(packet[TCP].sport, self.tcp_port_in)
2232 self.assertEqual(packet[TCP].dport, server_tcp_port)
2233 self.tcp_port_out = packet[TCP].sport
Klement Sekerad81ae412018-05-16 10:52:54 +02002234 self.assert_packet_checksums_valid(packet)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002235 elif packet.haslayer(UDP):
2236 self.assertNotEqual(packet[UDP].sport, self.udp_port_in)
2237 self.assertEqual(packet[UDP].dport, server_udp_port)
2238 self.udp_port_out = packet[UDP].sport
2239 else:
2240 self.assertNotEqual(packet[ICMP].id, self.icmp_id_in)
2241 self.icmp_id_out = packet[ICMP].id
2242 except:
2243 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2244 raise
2245
2246 # server1 to host
2247 pkts = []
2248 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002249 IP(src=server1.ip4, dst=self.nat_addr) /
Matus Fabian6fa74c62017-06-05 05:55:48 -07002250 TCP(sport=server_tcp_port, dport=self.tcp_port_out))
2251 pkts.append(p)
2252 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002253 IP(src=server1.ip4, dst=self.nat_addr) /
Matus Fabian6fa74c62017-06-05 05:55:48 -07002254 UDP(sport=server_udp_port, dport=self.udp_port_out))
2255 pkts.append(p)
2256 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002257 IP(src=server1.ip4, dst=self.nat_addr) /
Matus Fabian6fa74c62017-06-05 05:55:48 -07002258 ICMP(id=self.icmp_id_out, type='echo-reply'))
2259 pkts.append(p)
2260 self.pg0.add_stream(pkts)
2261 self.pg_enable_capture(self.pg_interfaces)
2262 self.pg_start()
2263 capture = self.pg0.get_capture(len(pkts))
2264 for packet in capture:
2265 try:
2266 self.assertEqual(packet[IP].src, server1_nat_ip)
2267 self.assertEqual(packet[IP].dst, host.ip4)
2268 if packet.haslayer(TCP):
2269 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
2270 self.assertEqual(packet[TCP].sport, server_tcp_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02002271 self.assert_packet_checksums_valid(packet)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002272 elif packet.haslayer(UDP):
2273 self.assertEqual(packet[UDP].dport, self.udp_port_in)
2274 self.assertEqual(packet[UDP].sport, server_udp_port)
2275 else:
2276 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
2277 except:
2278 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2279 raise
2280
2281 # server2 to server1
2282 pkts = []
2283 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2284 IP(src=server2.ip4, dst=server1_nat_ip) /
2285 TCP(sport=self.tcp_port_in, dport=server_tcp_port))
2286 pkts.append(p)
2287 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2288 IP(src=server2.ip4, dst=server1_nat_ip) /
2289 UDP(sport=self.udp_port_in, dport=server_udp_port))
2290 pkts.append(p)
2291 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2292 IP(src=server2.ip4, dst=server1_nat_ip) /
2293 ICMP(id=self.icmp_id_in, type='echo-request'))
2294 pkts.append(p)
2295 self.pg0.add_stream(pkts)
2296 self.pg_enable_capture(self.pg_interfaces)
2297 self.pg_start()
2298 capture = self.pg0.get_capture(len(pkts))
2299 for packet in capture:
2300 try:
2301 self.assertEqual(packet[IP].src, server2_nat_ip)
2302 self.assertEqual(packet[IP].dst, server1.ip4)
2303 if packet.haslayer(TCP):
2304 self.assertEqual(packet[TCP].sport, self.tcp_port_in)
2305 self.assertEqual(packet[TCP].dport, server_tcp_port)
2306 self.tcp_port_out = packet[TCP].sport
Klement Sekerad81ae412018-05-16 10:52:54 +02002307 self.assert_packet_checksums_valid(packet)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002308 elif packet.haslayer(UDP):
2309 self.assertEqual(packet[UDP].sport, self.udp_port_in)
2310 self.assertEqual(packet[UDP].dport, server_udp_port)
2311 self.udp_port_out = packet[UDP].sport
2312 else:
2313 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
2314 self.icmp_id_out = packet[ICMP].id
2315 except:
2316 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2317 raise
2318
2319 # server1 to server2
2320 pkts = []
2321 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2322 IP(src=server1.ip4, dst=server2_nat_ip) /
2323 TCP(sport=server_tcp_port, dport=self.tcp_port_out))
2324 pkts.append(p)
2325 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2326 IP(src=server1.ip4, dst=server2_nat_ip) /
2327 UDP(sport=server_udp_port, dport=self.udp_port_out))
2328 pkts.append(p)
2329 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2330 IP(src=server1.ip4, dst=server2_nat_ip) /
2331 ICMP(id=self.icmp_id_out, type='echo-reply'))
2332 pkts.append(p)
2333 self.pg0.add_stream(pkts)
2334 self.pg_enable_capture(self.pg_interfaces)
2335 self.pg_start()
2336 capture = self.pg0.get_capture(len(pkts))
2337 for packet in capture:
2338 try:
2339 self.assertEqual(packet[IP].src, server1_nat_ip)
2340 self.assertEqual(packet[IP].dst, server2.ip4)
2341 if packet.haslayer(TCP):
2342 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
2343 self.assertEqual(packet[TCP].sport, server_tcp_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02002344 self.assert_packet_checksums_valid(packet)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002345 elif packet.haslayer(UDP):
2346 self.assertEqual(packet[UDP].dport, self.udp_port_in)
2347 self.assertEqual(packet[UDP].sport, server_udp_port)
2348 else:
2349 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
2350 except:
2351 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2352 raise
2353
Matus Fabian9902fcd2016-12-21 23:58:46 -08002354 def test_max_translations_per_user(self):
2355 """ MAX translations per user - recycle the least recently used """
2356
Matus Fabian2ba92e32017-08-21 07:05:03 -07002357 self.nat44_add_address(self.nat_addr)
2358 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2359 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2360 is_inside=0)
Matus Fabian9902fcd2016-12-21 23:58:46 -08002361
2362 # get maximum number of translations per user
Matus Fabian2ba92e32017-08-21 07:05:03 -07002363 nat44_config = self.vapi.nat_show_config()
Matus Fabian9902fcd2016-12-21 23:58:46 -08002364
2365 # send more than maximum number of translations per user packets
Matus Fabian2ba92e32017-08-21 07:05:03 -07002366 pkts_num = nat44_config.max_translations_per_user + 5
Matus Fabian9902fcd2016-12-21 23:58:46 -08002367 pkts = []
2368 for port in range(0, pkts_num):
2369 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2370 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2371 TCP(sport=1025 + port))
2372 pkts.append(p)
2373 self.pg0.add_stream(pkts)
2374 self.pg_enable_capture(self.pg_interfaces)
2375 self.pg_start()
2376
2377 # verify number of translated packet
Klement Sekeradab231a2016-12-21 08:50:14 +01002378 self.pg1.get_capture(pkts_num)
Matus Fabian9902fcd2016-12-21 23:58:46 -08002379
Matus Fabian132dc492018-05-09 04:51:03 -07002380 users = self.vapi.nat44_user_dump()
2381 for user in users:
2382 if user.ip_address == self.pg0.remote_ip4n:
2383 self.assertEqual(user.nsessions,
2384 nat44_config.max_translations_per_user)
2385 self.assertEqual(user.nstaticsessions, 0)
2386
2387 tcp_port = 22
2388 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
2389 tcp_port, tcp_port,
2390 proto=IP_PROTOS.tcp)
2391 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2392 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2393 TCP(sport=tcp_port))
2394 self.pg0.add_stream(p)
2395 self.pg_enable_capture(self.pg_interfaces)
2396 self.pg_start()
2397 self.pg1.get_capture(1)
2398 users = self.vapi.nat44_user_dump()
2399 for user in users:
2400 if user.ip_address == self.pg0.remote_ip4n:
2401 self.assertEqual(user.nsessions,
2402 nat44_config.max_translations_per_user - 1)
2403 self.assertEqual(user.nstaticsessions, 1)
2404
Matus Fabian8bf68e82017-01-12 04:24:35 -08002405 def test_interface_addr(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002406 """ Acquire NAT44 addresses from interface """
2407 self.vapi.nat44_add_interface_addr(self.pg7.sw_if_index)
Matus Fabian8bf68e82017-01-12 04:24:35 -08002408
2409 # no address in NAT pool
Matus Fabian2ba92e32017-08-21 07:05:03 -07002410 adresses = self.vapi.nat44_address_dump()
Matus Fabian8bf68e82017-01-12 04:24:35 -08002411 self.assertEqual(0, len(adresses))
2412
2413 # configure interface address and check NAT address pool
2414 self.pg7.config_ip4()
Matus Fabian2ba92e32017-08-21 07:05:03 -07002415 adresses = self.vapi.nat44_address_dump()
Matus Fabian8bf68e82017-01-12 04:24:35 -08002416 self.assertEqual(1, len(adresses))
Matus Fabian36532bd2017-01-23 23:42:28 -08002417 self.assertEqual(adresses[0].ip_address[0:4], self.pg7.local_ip4n)
Matus Fabian8bf68e82017-01-12 04:24:35 -08002418
2419 # remove interface address and check NAT address pool
2420 self.pg7.unconfig_ip4()
Matus Fabian2ba92e32017-08-21 07:05:03 -07002421 adresses = self.vapi.nat44_address_dump()
Matus Fabian8bf68e82017-01-12 04:24:35 -08002422 self.assertEqual(0, len(adresses))
2423
Matus Fabian36532bd2017-01-23 23:42:28 -08002424 def test_interface_addr_static_mapping(self):
2425 """ Static mapping with addresses from interface """
Matus Fabian5f224992018-01-25 21:59:16 -08002426 tag = "testTAG"
2427
Matus Fabian2ba92e32017-08-21 07:05:03 -07002428 self.vapi.nat44_add_interface_addr(self.pg7.sw_if_index)
2429 self.nat44_add_static_mapping(
2430 '1.2.3.4',
Matus Fabian5f224992018-01-25 21:59:16 -08002431 external_sw_if_index=self.pg7.sw_if_index,
2432 tag=tag)
Matus Fabian36532bd2017-01-23 23:42:28 -08002433
Matus Fabiane22e5462017-02-14 23:33:43 -08002434 # static mappings with external interface
Matus Fabian2ba92e32017-08-21 07:05:03 -07002435 static_mappings = self.vapi.nat44_static_mapping_dump()
Matus Fabiane22e5462017-02-14 23:33:43 -08002436 self.assertEqual(1, len(static_mappings))
2437 self.assertEqual(self.pg7.sw_if_index,
2438 static_mappings[0].external_sw_if_index)
Matus Fabian5f224992018-01-25 21:59:16 -08002439 self.assertEqual((static_mappings[0].tag).split('\0', 1)[0], tag)
Matus Fabian36532bd2017-01-23 23:42:28 -08002440
2441 # configure interface address and check static mappings
2442 self.pg7.config_ip4()
Matus Fabian2ba92e32017-08-21 07:05:03 -07002443 static_mappings = self.vapi.nat44_static_mapping_dump()
Matus Fabianea2600a2018-03-28 04:06:26 -07002444 self.assertEqual(2, len(static_mappings))
2445 resolved = False
2446 for sm in static_mappings:
2447 if sm.external_sw_if_index == 0xFFFFFFFF:
2448 self.assertEqual(sm.external_ip_address[0:4],
2449 self.pg7.local_ip4n)
2450 self.assertEqual((sm.tag).split('\0', 1)[0], tag)
2451 resolved = True
2452 self.assertTrue(resolved)
Matus Fabian36532bd2017-01-23 23:42:28 -08002453
2454 # remove interface address and check static mappings
2455 self.pg7.unconfig_ip4()
Matus Fabian2ba92e32017-08-21 07:05:03 -07002456 static_mappings = self.vapi.nat44_static_mapping_dump()
Matus Fabianea2600a2018-03-28 04:06:26 -07002457 self.assertEqual(1, len(static_mappings))
2458 self.assertEqual(self.pg7.sw_if_index,
2459 static_mappings[0].external_sw_if_index)
2460 self.assertEqual((static_mappings[0].tag).split('\0', 1)[0], tag)
2461
2462 # configure interface address again and check static mappings
2463 self.pg7.config_ip4()
2464 static_mappings = self.vapi.nat44_static_mapping_dump()
2465 self.assertEqual(2, len(static_mappings))
2466 resolved = False
2467 for sm in static_mappings:
2468 if sm.external_sw_if_index == 0xFFFFFFFF:
2469 self.assertEqual(sm.external_ip_address[0:4],
2470 self.pg7.local_ip4n)
2471 self.assertEqual((sm.tag).split('\0', 1)[0], tag)
2472 resolved = True
2473 self.assertTrue(resolved)
2474
2475 # remove static mapping
2476 self.nat44_add_static_mapping(
2477 '1.2.3.4',
2478 external_sw_if_index=self.pg7.sw_if_index,
2479 tag=tag,
2480 is_add=0)
2481 static_mappings = self.vapi.nat44_static_mapping_dump()
Matus Fabian36532bd2017-01-23 23:42:28 -08002482 self.assertEqual(0, len(static_mappings))
2483
Matus Fabianab7a8052017-11-28 04:29:41 -08002484 def test_interface_addr_identity_nat(self):
2485 """ Identity NAT with addresses from interface """
2486
2487 port = 53053
2488 self.vapi.nat44_add_interface_addr(self.pg7.sw_if_index)
2489 self.vapi.nat44_add_del_identity_mapping(
2490 sw_if_index=self.pg7.sw_if_index,
2491 port=port,
2492 protocol=IP_PROTOS.tcp,
2493 addr_only=0)
2494
2495 # identity mappings with external interface
2496 identity_mappings = self.vapi.nat44_identity_mapping_dump()
2497 self.assertEqual(1, len(identity_mappings))
2498 self.assertEqual(self.pg7.sw_if_index,
2499 identity_mappings[0].sw_if_index)
2500
2501 # configure interface address and check identity mappings
2502 self.pg7.config_ip4()
2503 identity_mappings = self.vapi.nat44_identity_mapping_dump()
Matus Fabianea2600a2018-03-28 04:06:26 -07002504 resolved = False
2505 self.assertEqual(2, len(identity_mappings))
2506 for sm in identity_mappings:
2507 if sm.sw_if_index == 0xFFFFFFFF:
2508 self.assertEqual(identity_mappings[0].ip_address,
2509 self.pg7.local_ip4n)
2510 self.assertEqual(port, identity_mappings[0].port)
2511 self.assertEqual(IP_PROTOS.tcp, identity_mappings[0].protocol)
2512 resolved = True
2513 self.assertTrue(resolved)
Matus Fabianab7a8052017-11-28 04:29:41 -08002514
2515 # remove interface address and check identity mappings
2516 self.pg7.unconfig_ip4()
2517 identity_mappings = self.vapi.nat44_identity_mapping_dump()
Matus Fabianea2600a2018-03-28 04:06:26 -07002518 self.assertEqual(1, len(identity_mappings))
2519 self.assertEqual(self.pg7.sw_if_index,
2520 identity_mappings[0].sw_if_index)
Matus Fabianab7a8052017-11-28 04:29:41 -08002521
Matus Fabianeea28d72017-01-13 04:15:54 -08002522 def test_ipfix_nat44_sess(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002523 """ IPFIX logging NAT44 session created/delted """
Matus Fabian6631e9c2017-05-24 01:52:20 -07002524 self.ipfix_domain_id = 10
2525 self.ipfix_src_port = 20202
2526 colector_port = 30303
2527 bind_layers(UDP, IPFIX, dport=30303)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002528 self.nat44_add_address(self.nat_addr)
2529 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2530 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2531 is_inside=0)
Matus Fabianeea28d72017-01-13 04:15:54 -08002532 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
2533 src_address=self.pg3.local_ip4n,
2534 path_mtu=512,
Matus Fabian6631e9c2017-05-24 01:52:20 -07002535 template_interval=10,
2536 collector_port=colector_port)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002537 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
2538 src_port=self.ipfix_src_port)
Matus Fabianeea28d72017-01-13 04:15:54 -08002539
2540 pkts = self.create_stream_in(self.pg0, self.pg1)
2541 self.pg0.add_stream(pkts)
2542 self.pg_enable_capture(self.pg_interfaces)
2543 self.pg_start()
2544 capture = self.pg1.get_capture(len(pkts))
2545 self.verify_capture_out(capture)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002546 self.nat44_add_address(self.nat_addr, is_add=0)
Matus Fabianeea28d72017-01-13 04:15:54 -08002547 self.vapi.cli("ipfix flush") # FIXME this should be an API call
Matus Fabiana431ad12018-01-04 04:03:14 -08002548 capture = self.pg3.get_capture(9)
Matus Fabianeea28d72017-01-13 04:15:54 -08002549 ipfix = IPFIXDecoder()
2550 # first load template
2551 for p in capture:
2552 self.assertTrue(p.haslayer(IPFIX))
Matus Fabian6631e9c2017-05-24 01:52:20 -07002553 self.assertEqual(p[IP].src, self.pg3.local_ip4)
2554 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2555 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2556 self.assertEqual(p[UDP].dport, colector_port)
2557 self.assertEqual(p[IPFIX].observationDomainID,
2558 self.ipfix_domain_id)
Matus Fabianeea28d72017-01-13 04:15:54 -08002559 if p.haslayer(Template):
2560 ipfix.add_template(p.getlayer(Template))
2561 # verify events in data set
2562 for p in capture:
2563 if p.haslayer(Data):
2564 data = ipfix.decode_data_set(p.getlayer(Set))
2565 self.verify_ipfix_nat44_ses(data)
2566
2567 def test_ipfix_addr_exhausted(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002568 """ IPFIX logging NAT addresses exhausted """
2569 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2570 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2571 is_inside=0)
Matus Fabianeea28d72017-01-13 04:15:54 -08002572 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
2573 src_address=self.pg3.local_ip4n,
2574 path_mtu=512,
2575 template_interval=10)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002576 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
2577 src_port=self.ipfix_src_port)
Matus Fabianeea28d72017-01-13 04:15:54 -08002578
2579 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
2580 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2581 TCP(sport=3025))
2582 self.pg0.add_stream(p)
2583 self.pg_enable_capture(self.pg_interfaces)
2584 self.pg_start()
2585 capture = self.pg1.get_capture(0)
2586 self.vapi.cli("ipfix flush") # FIXME this should be an API call
Matus Fabiana431ad12018-01-04 04:03:14 -08002587 capture = self.pg3.get_capture(9)
Matus Fabianeea28d72017-01-13 04:15:54 -08002588 ipfix = IPFIXDecoder()
2589 # first load template
2590 for p in capture:
2591 self.assertTrue(p.haslayer(IPFIX))
Matus Fabian6631e9c2017-05-24 01:52:20 -07002592 self.assertEqual(p[IP].src, self.pg3.local_ip4)
2593 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2594 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2595 self.assertEqual(p[UDP].dport, 4739)
2596 self.assertEqual(p[IPFIX].observationDomainID,
2597 self.ipfix_domain_id)
Matus Fabianeea28d72017-01-13 04:15:54 -08002598 if p.haslayer(Template):
2599 ipfix.add_template(p.getlayer(Template))
2600 # verify events in data set
2601 for p in capture:
2602 if p.haslayer(Data):
2603 data = ipfix.decode_data_set(p.getlayer(Set))
2604 self.verify_ipfix_addr_exhausted(data)
2605
Matus Fabiana431ad12018-01-04 04:03:14 -08002606 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
2607 def test_ipfix_max_sessions(self):
2608 """ IPFIX logging maximum session entries exceeded """
2609 self.nat44_add_address(self.nat_addr)
2610 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2611 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2612 is_inside=0)
2613
2614 nat44_config = self.vapi.nat_show_config()
2615 max_sessions = 10 * nat44_config.translation_buckets
2616
2617 pkts = []
2618 for i in range(0, max_sessions):
2619 src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
2620 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2621 IP(src=src, dst=self.pg1.remote_ip4) /
2622 TCP(sport=1025))
2623 pkts.append(p)
2624 self.pg0.add_stream(pkts)
2625 self.pg_enable_capture(self.pg_interfaces)
2626 self.pg_start()
2627
2628 self.pg1.get_capture(max_sessions)
2629 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
2630 src_address=self.pg3.local_ip4n,
2631 path_mtu=512,
2632 template_interval=10)
2633 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
2634 src_port=self.ipfix_src_port)
2635
2636 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2637 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2638 TCP(sport=1025))
2639 self.pg0.add_stream(p)
2640 self.pg_enable_capture(self.pg_interfaces)
2641 self.pg_start()
2642 self.pg1.get_capture(0)
2643 self.vapi.cli("ipfix flush") # FIXME this should be an API call
2644 capture = self.pg3.get_capture(9)
2645 ipfix = IPFIXDecoder()
2646 # first load template
2647 for p in capture:
2648 self.assertTrue(p.haslayer(IPFIX))
2649 self.assertEqual(p[IP].src, self.pg3.local_ip4)
2650 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2651 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2652 self.assertEqual(p[UDP].dport, 4739)
2653 self.assertEqual(p[IPFIX].observationDomainID,
2654 self.ipfix_domain_id)
2655 if p.haslayer(Template):
2656 ipfix.add_template(p.getlayer(Template))
2657 # verify events in data set
2658 for p in capture:
2659 if p.haslayer(Data):
2660 data = ipfix.decode_data_set(p.getlayer(Set))
2661 self.verify_ipfix_max_sessions(data, max_sessions)
2662
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002663 def test_pool_addr_fib(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002664 """ NAT44 add pool addresses to FIB """
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002665 static_addr = '10.0.0.10'
Matus Fabian2ba92e32017-08-21 07:05:03 -07002666 self.nat44_add_address(self.nat_addr)
2667 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2668 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2669 is_inside=0)
2670 self.nat44_add_static_mapping(self.pg0.remote_ip4, static_addr)
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002671
Matus Fabian2ba92e32017-08-21 07:05:03 -07002672 # NAT44 address
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002673 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002674 ARP(op=ARP.who_has, pdst=self.nat_addr,
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002675 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2676 self.pg1.add_stream(p)
2677 self.pg_enable_capture(self.pg_interfaces)
2678 self.pg_start()
2679 capture = self.pg1.get_capture(1)
2680 self.assertTrue(capture[0].haslayer(ARP))
2681 self.assertTrue(capture[0][ARP].op, ARP.is_at)
2682
2683 # 1:1 NAT address
2684 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2685 ARP(op=ARP.who_has, pdst=static_addr,
2686 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2687 self.pg1.add_stream(p)
2688 self.pg_enable_capture(self.pg_interfaces)
2689 self.pg_start()
2690 capture = self.pg1.get_capture(1)
2691 self.assertTrue(capture[0].haslayer(ARP))
2692 self.assertTrue(capture[0][ARP].op, ARP.is_at)
2693
Matus Fabian2ba92e32017-08-21 07:05:03 -07002694 # send ARP to non-NAT44 interface
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002695 p = (Ether(src=self.pg2.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002696 ARP(op=ARP.who_has, pdst=self.nat_addr,
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002697 psrc=self.pg2.remote_ip4, hwsrc=self.pg2.remote_mac))
2698 self.pg2.add_stream(p)
2699 self.pg_enable_capture(self.pg_interfaces)
2700 self.pg_start()
2701 capture = self.pg1.get_capture(0)
2702
2703 # remove addresses and verify
Matus Fabian2ba92e32017-08-21 07:05:03 -07002704 self.nat44_add_address(self.nat_addr, is_add=0)
2705 self.nat44_add_static_mapping(self.pg0.remote_ip4, static_addr,
2706 is_add=0)
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002707
2708 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002709 ARP(op=ARP.who_has, pdst=self.nat_addr,
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002710 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2711 self.pg1.add_stream(p)
2712 self.pg_enable_capture(self.pg_interfaces)
2713 self.pg_start()
2714 capture = self.pg1.get_capture(0)
2715
2716 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2717 ARP(op=ARP.who_has, pdst=static_addr,
2718 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2719 self.pg1.add_stream(p)
2720 self.pg_enable_capture(self.pg_interfaces)
2721 self.pg_start()
2722 capture = self.pg1.get_capture(0)
2723
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002724 def test_vrf_mode(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002725 """ NAT44 tenant VRF aware address pool mode """
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002726
2727 vrf_id1 = 1
2728 vrf_id2 = 2
2729 nat_ip1 = "10.0.0.10"
2730 nat_ip2 = "10.0.0.11"
2731
2732 self.pg0.unconfig_ip4()
2733 self.pg1.unconfig_ip4()
Neale Ranns15002542017-09-10 04:39:11 -07002734 self.vapi.ip_table_add_del(vrf_id1, is_add=1)
2735 self.vapi.ip_table_add_del(vrf_id2, is_add=1)
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002736 self.pg0.set_table_ip4(vrf_id1)
2737 self.pg1.set_table_ip4(vrf_id2)
2738 self.pg0.config_ip4()
2739 self.pg1.config_ip4()
2740
Matus Fabian2ba92e32017-08-21 07:05:03 -07002741 self.nat44_add_address(nat_ip1, vrf_id=vrf_id1)
2742 self.nat44_add_address(nat_ip2, vrf_id=vrf_id2)
2743 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2744 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
2745 self.vapi.nat44_interface_add_del_feature(self.pg2.sw_if_index,
2746 is_inside=0)
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002747
2748 # first VRF
2749 pkts = self.create_stream_in(self.pg0, self.pg2)
2750 self.pg0.add_stream(pkts)
2751 self.pg_enable_capture(self.pg_interfaces)
2752 self.pg_start()
2753 capture = self.pg2.get_capture(len(pkts))
2754 self.verify_capture_out(capture, nat_ip1)
2755
2756 # second VRF
2757 pkts = self.create_stream_in(self.pg1, self.pg2)
2758 self.pg1.add_stream(pkts)
2759 self.pg_enable_capture(self.pg_interfaces)
2760 self.pg_start()
2761 capture = self.pg2.get_capture(len(pkts))
2762 self.verify_capture_out(capture, nat_ip2)
2763
Neale Ranns15002542017-09-10 04:39:11 -07002764 self.pg0.unconfig_ip4()
2765 self.pg1.unconfig_ip4()
2766 self.pg0.set_table_ip4(0)
2767 self.pg1.set_table_ip4(0)
2768 self.vapi.ip_table_add_del(vrf_id1, is_add=0)
2769 self.vapi.ip_table_add_del(vrf_id2, is_add=0)
2770
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002771 def test_vrf_feature_independent(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002772 """ NAT44 tenant VRF independent address pool mode """
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002773
2774 nat_ip1 = "10.0.0.10"
2775 nat_ip2 = "10.0.0.11"
2776
Matus Fabian2ba92e32017-08-21 07:05:03 -07002777 self.nat44_add_address(nat_ip1)
Matus Fabian51e759f2017-12-07 23:22:51 -08002778 self.nat44_add_address(nat_ip2, vrf_id=99)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002779 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2780 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
2781 self.vapi.nat44_interface_add_del_feature(self.pg2.sw_if_index,
2782 is_inside=0)
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002783
2784 # first VRF
2785 pkts = self.create_stream_in(self.pg0, self.pg2)
2786 self.pg0.add_stream(pkts)
2787 self.pg_enable_capture(self.pg_interfaces)
2788 self.pg_start()
2789 capture = self.pg2.get_capture(len(pkts))
2790 self.verify_capture_out(capture, nat_ip1)
2791
2792 # second VRF
2793 pkts = self.create_stream_in(self.pg1, self.pg2)
2794 self.pg1.add_stream(pkts)
2795 self.pg_enable_capture(self.pg_interfaces)
2796 self.pg_start()
2797 capture = self.pg2.get_capture(len(pkts))
2798 self.verify_capture_out(capture, nat_ip1)
2799
Martin Gálik406eb1d2017-05-04 04:35:04 -07002800 def test_dynamic_ipless_interfaces(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002801 """ NAT44 interfaces without configured IP address """
Martin Gálik406eb1d2017-05-04 04:35:04 -07002802
2803 self.vapi.ip_neighbor_add_del(self.pg7.sw_if_index,
Ole Troan895b6e82017-10-20 13:28:20 +02002804 mactobinary(self.pg7.remote_mac),
Martin Gálik406eb1d2017-05-04 04:35:04 -07002805 self.pg7.remote_ip4n,
2806 is_static=1)
2807 self.vapi.ip_neighbor_add_del(self.pg8.sw_if_index,
Ole Troan895b6e82017-10-20 13:28:20 +02002808 mactobinary(self.pg8.remote_mac),
Martin Gálik406eb1d2017-05-04 04:35:04 -07002809 self.pg8.remote_ip4n,
2810 is_static=1)
2811
2812 self.vapi.ip_add_del_route(dst_address=self.pg7.remote_ip4n,
2813 dst_address_length=32,
2814 next_hop_address=self.pg7.remote_ip4n,
2815 next_hop_sw_if_index=self.pg7.sw_if_index)
2816 self.vapi.ip_add_del_route(dst_address=self.pg8.remote_ip4n,
2817 dst_address_length=32,
2818 next_hop_address=self.pg8.remote_ip4n,
2819 next_hop_sw_if_index=self.pg8.sw_if_index)
2820
Matus Fabian2ba92e32017-08-21 07:05:03 -07002821 self.nat44_add_address(self.nat_addr)
2822 self.vapi.nat44_interface_add_del_feature(self.pg7.sw_if_index)
2823 self.vapi.nat44_interface_add_del_feature(self.pg8.sw_if_index,
2824 is_inside=0)
Martin Gálik406eb1d2017-05-04 04:35:04 -07002825
2826 # in2out
2827 pkts = self.create_stream_in(self.pg7, self.pg8)
2828 self.pg7.add_stream(pkts)
2829 self.pg_enable_capture(self.pg_interfaces)
2830 self.pg_start()
2831 capture = self.pg8.get_capture(len(pkts))
2832 self.verify_capture_out(capture)
2833
2834 # out2in
Matus Fabian2ba92e32017-08-21 07:05:03 -07002835 pkts = self.create_stream_out(self.pg8, self.nat_addr)
Martin Gálik406eb1d2017-05-04 04:35:04 -07002836 self.pg8.add_stream(pkts)
2837 self.pg_enable_capture(self.pg_interfaces)
2838 self.pg_start()
2839 capture = self.pg7.get_capture(len(pkts))
2840 self.verify_capture_in(capture, self.pg7)
2841
2842 def test_static_ipless_interfaces(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002843 """ NAT44 interfaces without configured IP address - 1:1 NAT """
Martin Gálik406eb1d2017-05-04 04:35:04 -07002844
2845 self.vapi.ip_neighbor_add_del(self.pg7.sw_if_index,
Ole Troan895b6e82017-10-20 13:28:20 +02002846 mactobinary(self.pg7.remote_mac),
Martin Gálik406eb1d2017-05-04 04:35:04 -07002847 self.pg7.remote_ip4n,
2848 is_static=1)
2849 self.vapi.ip_neighbor_add_del(self.pg8.sw_if_index,
Ole Troan895b6e82017-10-20 13:28:20 +02002850 mactobinary(self.pg8.remote_mac),
Martin Gálik406eb1d2017-05-04 04:35:04 -07002851 self.pg8.remote_ip4n,
2852 is_static=1)
2853
2854 self.vapi.ip_add_del_route(dst_address=self.pg7.remote_ip4n,
2855 dst_address_length=32,
2856 next_hop_address=self.pg7.remote_ip4n,
2857 next_hop_sw_if_index=self.pg7.sw_if_index)
2858 self.vapi.ip_add_del_route(dst_address=self.pg8.remote_ip4n,
2859 dst_address_length=32,
2860 next_hop_address=self.pg8.remote_ip4n,
2861 next_hop_sw_if_index=self.pg8.sw_if_index)
2862
Matus Fabian2ba92e32017-08-21 07:05:03 -07002863 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr)
2864 self.vapi.nat44_interface_add_del_feature(self.pg7.sw_if_index)
2865 self.vapi.nat44_interface_add_del_feature(self.pg8.sw_if_index,
2866 is_inside=0)
Martin Gálik406eb1d2017-05-04 04:35:04 -07002867
2868 # out2in
2869 pkts = self.create_stream_out(self.pg8)
2870 self.pg8.add_stream(pkts)
2871 self.pg_enable_capture(self.pg_interfaces)
2872 self.pg_start()
2873 capture = self.pg7.get_capture(len(pkts))
2874 self.verify_capture_in(capture, self.pg7)
2875
2876 # in2out
2877 pkts = self.create_stream_in(self.pg7, self.pg8)
2878 self.pg7.add_stream(pkts)
2879 self.pg_enable_capture(self.pg_interfaces)
2880 self.pg_start()
2881 capture = self.pg8.get_capture(len(pkts))
Matus Fabian2ba92e32017-08-21 07:05:03 -07002882 self.verify_capture_out(capture, self.nat_addr, True)
Martin Gálik406eb1d2017-05-04 04:35:04 -07002883
2884 def test_static_with_port_ipless_interfaces(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002885 """ NAT44 interfaces without configured IP address - 1:1 NAPT """
Martin Gálik406eb1d2017-05-04 04:35:04 -07002886
2887 self.tcp_port_out = 30606
2888 self.udp_port_out = 30607
2889 self.icmp_id_out = 30608
2890
2891 self.vapi.ip_neighbor_add_del(self.pg7.sw_if_index,
Ole Troan895b6e82017-10-20 13:28:20 +02002892 mactobinary(self.pg7.remote_mac),
Martin Gálik406eb1d2017-05-04 04:35:04 -07002893 self.pg7.remote_ip4n,
2894 is_static=1)
2895 self.vapi.ip_neighbor_add_del(self.pg8.sw_if_index,
Ole Troan895b6e82017-10-20 13:28:20 +02002896 mactobinary(self.pg8.remote_mac),
Martin Gálik406eb1d2017-05-04 04:35:04 -07002897 self.pg8.remote_ip4n,
2898 is_static=1)
2899
2900 self.vapi.ip_add_del_route(dst_address=self.pg7.remote_ip4n,
2901 dst_address_length=32,
2902 next_hop_address=self.pg7.remote_ip4n,
2903 next_hop_sw_if_index=self.pg7.sw_if_index)
2904 self.vapi.ip_add_del_route(dst_address=self.pg8.remote_ip4n,
2905 dst_address_length=32,
2906 next_hop_address=self.pg8.remote_ip4n,
2907 next_hop_sw_if_index=self.pg8.sw_if_index)
2908
Matus Fabian2ba92e32017-08-21 07:05:03 -07002909 self.nat44_add_address(self.nat_addr)
2910 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
2911 self.tcp_port_in, self.tcp_port_out,
2912 proto=IP_PROTOS.tcp)
2913 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
2914 self.udp_port_in, self.udp_port_out,
2915 proto=IP_PROTOS.udp)
2916 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
2917 self.icmp_id_in, self.icmp_id_out,
2918 proto=IP_PROTOS.icmp)
2919 self.vapi.nat44_interface_add_del_feature(self.pg7.sw_if_index)
2920 self.vapi.nat44_interface_add_del_feature(self.pg8.sw_if_index,
2921 is_inside=0)
Martin Gálik406eb1d2017-05-04 04:35:04 -07002922
2923 # out2in
2924 pkts = self.create_stream_out(self.pg8)
2925 self.pg8.add_stream(pkts)
2926 self.pg_enable_capture(self.pg_interfaces)
2927 self.pg_start()
2928 capture = self.pg7.get_capture(len(pkts))
2929 self.verify_capture_in(capture, self.pg7)
2930
2931 # in2out
2932 pkts = self.create_stream_in(self.pg7, self.pg8)
2933 self.pg7.add_stream(pkts)
2934 self.pg_enable_capture(self.pg_interfaces)
2935 self.pg_start()
2936 capture = self.pg8.get_capture(len(pkts))
2937 self.verify_capture_out(capture)
2938
Matus Fabian328dbc82017-06-19 04:28:04 -07002939 def test_static_unknown_proto(self):
2940 """ 1:1 NAT translate packet with unknown protocol """
2941 nat_ip = "10.0.0.10"
Matus Fabian2ba92e32017-08-21 07:05:03 -07002942 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
2943 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2944 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2945 is_inside=0)
Matus Fabian328dbc82017-06-19 04:28:04 -07002946
2947 # in2out
2948 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2949 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2950 GRE() /
Matus Fabian1e8db5f2017-06-20 01:45:49 -07002951 IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4) /
Matus Fabian328dbc82017-06-19 04:28:04 -07002952 TCP(sport=1234, dport=1234))
2953 self.pg0.add_stream(p)
2954 self.pg_enable_capture(self.pg_interfaces)
2955 self.pg_start()
2956 p = self.pg1.get_capture(1)
2957 packet = p[0]
2958 try:
2959 self.assertEqual(packet[IP].src, nat_ip)
2960 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
2961 self.assertTrue(packet.haslayer(GRE))
Klement Sekerad81ae412018-05-16 10:52:54 +02002962 self.assert_packet_checksums_valid(packet)
Matus Fabian328dbc82017-06-19 04:28:04 -07002963 except:
2964 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2965 raise
2966
2967 # out2in
2968 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
2969 IP(src=self.pg1.remote_ip4, dst=nat_ip) /
2970 GRE() /
Matus Fabian1e8db5f2017-06-20 01:45:49 -07002971 IP(src=self.pg3.remote_ip4, dst=self.pg2.remote_ip4) /
Matus Fabian328dbc82017-06-19 04:28:04 -07002972 TCP(sport=1234, dport=1234))
2973 self.pg1.add_stream(p)
2974 self.pg_enable_capture(self.pg_interfaces)
2975 self.pg_start()
2976 p = self.pg0.get_capture(1)
2977 packet = p[0]
2978 try:
2979 self.assertEqual(packet[IP].src, self.pg1.remote_ip4)
2980 self.assertEqual(packet[IP].dst, self.pg0.remote_ip4)
2981 self.assertTrue(packet.haslayer(GRE))
Klement Sekerad81ae412018-05-16 10:52:54 +02002982 self.assert_packet_checksums_valid(packet)
Matus Fabian328dbc82017-06-19 04:28:04 -07002983 except:
2984 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2985 raise
2986
Matus Fabian7968e6c2017-07-06 05:37:49 -07002987 def test_hairpinning_static_unknown_proto(self):
Matus Fabian1e8db5f2017-06-20 01:45:49 -07002988 """ 1:1 NAT translate packet with unknown protocol - hairpinning """
2989
2990 host = self.pg0.remote_hosts[0]
2991 server = self.pg0.remote_hosts[1]
2992
2993 host_nat_ip = "10.0.0.10"
2994 server_nat_ip = "10.0.0.11"
2995
Matus Fabian2ba92e32017-08-21 07:05:03 -07002996 self.nat44_add_static_mapping(host.ip4, host_nat_ip)
2997 self.nat44_add_static_mapping(server.ip4, server_nat_ip)
2998 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2999 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3000 is_inside=0)
Matus Fabian1e8db5f2017-06-20 01:45:49 -07003001
3002 # host to server
3003 p = (Ether(dst=self.pg0.local_mac, src=host.mac) /
3004 IP(src=host.ip4, dst=server_nat_ip) /
3005 GRE() /
3006 IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4) /
3007 TCP(sport=1234, dport=1234))
3008 self.pg0.add_stream(p)
3009 self.pg_enable_capture(self.pg_interfaces)
3010 self.pg_start()
3011 p = self.pg0.get_capture(1)
3012 packet = p[0]
3013 try:
3014 self.assertEqual(packet[IP].src, host_nat_ip)
3015 self.assertEqual(packet[IP].dst, server.ip4)
3016 self.assertTrue(packet.haslayer(GRE))
Klement Sekerad81ae412018-05-16 10:52:54 +02003017 self.assert_packet_checksums_valid(packet)
Matus Fabian1e8db5f2017-06-20 01:45:49 -07003018 except:
3019 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3020 raise
3021
3022 # server to host
3023 p = (Ether(dst=self.pg0.local_mac, src=server.mac) /
3024 IP(src=server.ip4, dst=host_nat_ip) /
3025 GRE() /
3026 IP(src=self.pg3.remote_ip4, dst=self.pg2.remote_ip4) /
3027 TCP(sport=1234, dport=1234))
3028 self.pg0.add_stream(p)
3029 self.pg_enable_capture(self.pg_interfaces)
3030 self.pg_start()
3031 p = self.pg0.get_capture(1)
3032 packet = p[0]
3033 try:
3034 self.assertEqual(packet[IP].src, server_nat_ip)
3035 self.assertEqual(packet[IP].dst, host.ip4)
3036 self.assertTrue(packet.haslayer(GRE))
Klement Sekerad81ae412018-05-16 10:52:54 +02003037 self.assert_packet_checksums_valid(packet)
Matus Fabian1e8db5f2017-06-20 01:45:49 -07003038 except:
3039 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3040 raise
3041
Matus Fabian7968e6c2017-07-06 05:37:49 -07003042 def test_unknown_proto(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07003043 """ NAT44 translate packet with unknown protocol """
3044 self.nat44_add_address(self.nat_addr)
3045 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3046 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3047 is_inside=0)
Matus Fabian7968e6c2017-07-06 05:37:49 -07003048
3049 # in2out
3050 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3051 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3052 TCP(sport=self.tcp_port_in, dport=20))
3053 self.pg0.add_stream(p)
3054 self.pg_enable_capture(self.pg_interfaces)
3055 self.pg_start()
3056 p = self.pg1.get_capture(1)
3057
3058 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3059 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3060 GRE() /
3061 IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4) /
3062 TCP(sport=1234, dport=1234))
3063 self.pg0.add_stream(p)
3064 self.pg_enable_capture(self.pg_interfaces)
3065 self.pg_start()
3066 p = self.pg1.get_capture(1)
3067 packet = p[0]
3068 try:
Matus Fabian2ba92e32017-08-21 07:05:03 -07003069 self.assertEqual(packet[IP].src, self.nat_addr)
Matus Fabian7968e6c2017-07-06 05:37:49 -07003070 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
3071 self.assertTrue(packet.haslayer(GRE))
Klement Sekerad81ae412018-05-16 10:52:54 +02003072 self.assert_packet_checksums_valid(packet)
Matus Fabian7968e6c2017-07-06 05:37:49 -07003073 except:
3074 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3075 raise
3076
3077 # out2in
3078 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07003079 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Matus Fabian7968e6c2017-07-06 05:37:49 -07003080 GRE() /
3081 IP(src=self.pg3.remote_ip4, dst=self.pg2.remote_ip4) /
3082 TCP(sport=1234, dport=1234))
3083 self.pg1.add_stream(p)
3084 self.pg_enable_capture(self.pg_interfaces)
3085 self.pg_start()
3086 p = self.pg0.get_capture(1)
3087 packet = p[0]
3088 try:
3089 self.assertEqual(packet[IP].src, self.pg1.remote_ip4)
3090 self.assertEqual(packet[IP].dst, self.pg0.remote_ip4)
3091 self.assertTrue(packet.haslayer(GRE))
Klement Sekerad81ae412018-05-16 10:52:54 +02003092 self.assert_packet_checksums_valid(packet)
Matus Fabian7968e6c2017-07-06 05:37:49 -07003093 except:
3094 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3095 raise
3096
3097 def test_hairpinning_unknown_proto(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07003098 """ NAT44 translate packet with unknown protocol - hairpinning """
Matus Fabian7968e6c2017-07-06 05:37:49 -07003099 host = self.pg0.remote_hosts[0]
3100 server = self.pg0.remote_hosts[1]
3101 host_in_port = 1234
Matus Fabian7968e6c2017-07-06 05:37:49 -07003102 server_out_port = 8765
3103 server_nat_ip = "10.0.0.11"
3104
Matus Fabian2ba92e32017-08-21 07:05:03 -07003105 self.nat44_add_address(self.nat_addr)
3106 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3107 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3108 is_inside=0)
Matus Fabian7968e6c2017-07-06 05:37:49 -07003109
3110 # add static mapping for server
Matus Fabian2ba92e32017-08-21 07:05:03 -07003111 self.nat44_add_static_mapping(server.ip4, server_nat_ip)
Matus Fabian7968e6c2017-07-06 05:37:49 -07003112
3113 # host to server
3114 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
3115 IP(src=host.ip4, dst=server_nat_ip) /
3116 TCP(sport=host_in_port, dport=server_out_port))
3117 self.pg0.add_stream(p)
3118 self.pg_enable_capture(self.pg_interfaces)
3119 self.pg_start()
3120 capture = self.pg0.get_capture(1)
3121
3122 p = (Ether(dst=self.pg0.local_mac, src=host.mac) /
3123 IP(src=host.ip4, dst=server_nat_ip) /
3124 GRE() /
3125 IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4) /
3126 TCP(sport=1234, dport=1234))
3127 self.pg0.add_stream(p)
3128 self.pg_enable_capture(self.pg_interfaces)
3129 self.pg_start()
3130 p = self.pg0.get_capture(1)
3131 packet = p[0]
3132 try:
Matus Fabian2ba92e32017-08-21 07:05:03 -07003133 self.assertEqual(packet[IP].src, self.nat_addr)
Matus Fabian7968e6c2017-07-06 05:37:49 -07003134 self.assertEqual(packet[IP].dst, server.ip4)
3135 self.assertTrue(packet.haslayer(GRE))
Klement Sekerad81ae412018-05-16 10:52:54 +02003136 self.assert_packet_checksums_valid(packet)
Matus Fabian7968e6c2017-07-06 05:37:49 -07003137 except:
3138 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3139 raise
3140
3141 # server to host
3142 p = (Ether(dst=self.pg0.local_mac, src=server.mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07003143 IP(src=server.ip4, dst=self.nat_addr) /
Matus Fabian7968e6c2017-07-06 05:37:49 -07003144 GRE() /
3145 IP(src=self.pg3.remote_ip4, dst=self.pg2.remote_ip4) /
3146 TCP(sport=1234, dport=1234))
3147 self.pg0.add_stream(p)
3148 self.pg_enable_capture(self.pg_interfaces)
3149 self.pg_start()
3150 p = self.pg0.get_capture(1)
3151 packet = p[0]
3152 try:
3153 self.assertEqual(packet[IP].src, server_nat_ip)
3154 self.assertEqual(packet[IP].dst, host.ip4)
3155 self.assertTrue(packet.haslayer(GRE))
Klement Sekerad81ae412018-05-16 10:52:54 +02003156 self.assert_packet_checksums_valid(packet)
Matus Fabian7968e6c2017-07-06 05:37:49 -07003157 except:
3158 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3159 raise
3160
Matus Fabian93d84c92017-07-19 08:06:01 -07003161 def test_output_feature(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07003162 """ NAT44 interface output feature (in2out postrouting) """
3163 self.nat44_add_address(self.nat_addr)
3164 self.vapi.nat44_interface_add_del_output_feature(self.pg0.sw_if_index)
Matus Fabianb2d2fc72017-09-10 22:17:47 -07003165 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index)
3166 self.vapi.nat44_interface_add_del_output_feature(self.pg3.sw_if_index,
Matus Fabian2ba92e32017-08-21 07:05:03 -07003167 is_inside=0)
Matus Fabian93d84c92017-07-19 08:06:01 -07003168
3169 # in2out
Matus Fabianb2d2fc72017-09-10 22:17:47 -07003170 pkts = self.create_stream_in(self.pg0, self.pg3)
Matus Fabian93d84c92017-07-19 08:06:01 -07003171 self.pg0.add_stream(pkts)
3172 self.pg_enable_capture(self.pg_interfaces)
3173 self.pg_start()
Matus Fabianb2d2fc72017-09-10 22:17:47 -07003174 capture = self.pg3.get_capture(len(pkts))
Matus Fabian93d84c92017-07-19 08:06:01 -07003175 self.verify_capture_out(capture)
3176
3177 # out2in
Matus Fabianb2d2fc72017-09-10 22:17:47 -07003178 pkts = self.create_stream_out(self.pg3)
3179 self.pg3.add_stream(pkts)
Matus Fabian93d84c92017-07-19 08:06:01 -07003180 self.pg_enable_capture(self.pg_interfaces)
3181 self.pg_start()
3182 capture = self.pg0.get_capture(len(pkts))
3183 self.verify_capture_in(capture, self.pg0)
3184
Matus Fabianb2d2fc72017-09-10 22:17:47 -07003185 # from non-NAT interface to NAT inside interface
3186 pkts = self.create_stream_in(self.pg2, self.pg0)
3187 self.pg2.add_stream(pkts)
3188 self.pg_enable_capture(self.pg_interfaces)
3189 self.pg_start()
3190 capture = self.pg0.get_capture(len(pkts))
3191 self.verify_capture_no_translation(capture, self.pg2, self.pg0)
3192
Matus Fabian93d84c92017-07-19 08:06:01 -07003193 def test_output_feature_vrf_aware(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07003194 """ NAT44 interface output feature VRF aware (in2out postrouting) """
Matus Fabian93d84c92017-07-19 08:06:01 -07003195 nat_ip_vrf10 = "10.0.0.10"
3196 nat_ip_vrf20 = "10.0.0.20"
3197
3198 self.vapi.ip_add_del_route(dst_address=self.pg3.remote_ip4n,
3199 dst_address_length=32,
3200 next_hop_address=self.pg3.remote_ip4n,
3201 next_hop_sw_if_index=self.pg3.sw_if_index,
3202 table_id=10)
3203 self.vapi.ip_add_del_route(dst_address=self.pg3.remote_ip4n,
3204 dst_address_length=32,
3205 next_hop_address=self.pg3.remote_ip4n,
3206 next_hop_sw_if_index=self.pg3.sw_if_index,
3207 table_id=20)
3208
Matus Fabian2ba92e32017-08-21 07:05:03 -07003209 self.nat44_add_address(nat_ip_vrf10, vrf_id=10)
3210 self.nat44_add_address(nat_ip_vrf20, vrf_id=20)
3211 self.vapi.nat44_interface_add_del_output_feature(self.pg4.sw_if_index)
3212 self.vapi.nat44_interface_add_del_output_feature(self.pg6.sw_if_index)
3213 self.vapi.nat44_interface_add_del_output_feature(self.pg3.sw_if_index,
3214 is_inside=0)
Matus Fabian93d84c92017-07-19 08:06:01 -07003215
3216 # in2out VRF 10
3217 pkts = self.create_stream_in(self.pg4, self.pg3)
3218 self.pg4.add_stream(pkts)
3219 self.pg_enable_capture(self.pg_interfaces)
3220 self.pg_start()
3221 capture = self.pg3.get_capture(len(pkts))
3222 self.verify_capture_out(capture, nat_ip=nat_ip_vrf10)
3223
3224 # out2in VRF 10
3225 pkts = self.create_stream_out(self.pg3, dst_ip=nat_ip_vrf10)
3226 self.pg3.add_stream(pkts)
3227 self.pg_enable_capture(self.pg_interfaces)
3228 self.pg_start()
3229 capture = self.pg4.get_capture(len(pkts))
3230 self.verify_capture_in(capture, self.pg4)
3231
3232 # in2out VRF 20
3233 pkts = self.create_stream_in(self.pg6, self.pg3)
3234 self.pg6.add_stream(pkts)
3235 self.pg_enable_capture(self.pg_interfaces)
3236 self.pg_start()
3237 capture = self.pg3.get_capture(len(pkts))
3238 self.verify_capture_out(capture, nat_ip=nat_ip_vrf20)
3239
3240 # out2in VRF 20
3241 pkts = self.create_stream_out(self.pg3, dst_ip=nat_ip_vrf20)
3242 self.pg3.add_stream(pkts)
3243 self.pg_enable_capture(self.pg_interfaces)
3244 self.pg_start()
3245 capture = self.pg6.get_capture(len(pkts))
3246 self.verify_capture_in(capture, self.pg6)
3247
Matus Fabian161c59c2017-07-21 03:46:03 -07003248 def test_output_feature_hairpinning(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07003249 """ NAT44 interface output feature hairpinning (in2out postrouting) """
Matus Fabian93d84c92017-07-19 08:06:01 -07003250 host = self.pg0.remote_hosts[0]
3251 server = self.pg0.remote_hosts[1]
3252 host_in_port = 1234
3253 host_out_port = 0
3254 server_in_port = 5678
3255 server_out_port = 8765
3256
Matus Fabian2ba92e32017-08-21 07:05:03 -07003257 self.nat44_add_address(self.nat_addr)
3258 self.vapi.nat44_interface_add_del_output_feature(self.pg0.sw_if_index)
3259 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
3260 is_inside=0)
Matus Fabian93d84c92017-07-19 08:06:01 -07003261
3262 # add static mapping for server
Matus Fabian2ba92e32017-08-21 07:05:03 -07003263 self.nat44_add_static_mapping(server.ip4, self.nat_addr,
3264 server_in_port, server_out_port,
3265 proto=IP_PROTOS.tcp)
Matus Fabian93d84c92017-07-19 08:06:01 -07003266
3267 # send packet from host to server
3268 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07003269 IP(src=host.ip4, dst=self.nat_addr) /
Matus Fabian93d84c92017-07-19 08:06:01 -07003270 TCP(sport=host_in_port, dport=server_out_port))
3271 self.pg0.add_stream(p)
3272 self.pg_enable_capture(self.pg_interfaces)
3273 self.pg_start()
3274 capture = self.pg0.get_capture(1)
3275 p = capture[0]
3276 try:
3277 ip = p[IP]
3278 tcp = p[TCP]
Matus Fabian2ba92e32017-08-21 07:05:03 -07003279 self.assertEqual(ip.src, self.nat_addr)
Matus Fabian93d84c92017-07-19 08:06:01 -07003280 self.assertEqual(ip.dst, server.ip4)
3281 self.assertNotEqual(tcp.sport, host_in_port)
3282 self.assertEqual(tcp.dport, server_in_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02003283 self.assert_packet_checksums_valid(p)
Matus Fabian93d84c92017-07-19 08:06:01 -07003284 host_out_port = tcp.sport
3285 except:
3286 self.logger.error(ppp("Unexpected or invalid packet:", p))
3287 raise
3288
3289 # send reply from server to host
3290 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07003291 IP(src=server.ip4, dst=self.nat_addr) /
Matus Fabian93d84c92017-07-19 08:06:01 -07003292 TCP(sport=server_in_port, dport=host_out_port))
3293 self.pg0.add_stream(p)
3294 self.pg_enable_capture(self.pg_interfaces)
3295 self.pg_start()
3296 capture = self.pg0.get_capture(1)
3297 p = capture[0]
3298 try:
3299 ip = p[IP]
3300 tcp = p[TCP]
Matus Fabian2ba92e32017-08-21 07:05:03 -07003301 self.assertEqual(ip.src, self.nat_addr)
Matus Fabian93d84c92017-07-19 08:06:01 -07003302 self.assertEqual(ip.dst, host.ip4)
3303 self.assertEqual(tcp.sport, server_out_port)
3304 self.assertEqual(tcp.dport, host_in_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02003305 self.assert_packet_checksums_valid(p)
Matus Fabian93d84c92017-07-19 08:06:01 -07003306 except:
Matus Fabiane82488f2018-01-18 03:38:45 -08003307 self.logger.error(ppp("Unexpected or invalid packet:", p))
Matus Fabian93d84c92017-07-19 08:06:01 -07003308 raise
3309
Matus Fabianf7ad5cb2018-01-30 03:04:17 -08003310 def test_output_feature_and_service(self):
3311 """ NAT44 interface output feature and services """
3312 external_addr = '1.2.3.4'
3313 external_port = 80
3314 local_port = 8080
3315
3316 self.vapi.nat44_forwarding_enable_disable(1)
3317 self.nat44_add_address(self.nat_addr)
Matus Fabiana15cd022018-04-24 05:23:56 -07003318 self.vapi.nat44_add_del_identity_mapping(ip=self.pg1.remote_ip4n)
Matus Fabianf7ad5cb2018-01-30 03:04:17 -08003319 self.nat44_add_static_mapping(self.pg0.remote_ip4, external_addr,
3320 local_port, external_port,
3321 proto=IP_PROTOS.tcp, out2in_only=1)
3322 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
Matus Fabiana15cd022018-04-24 05:23:56 -07003323 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
3324 is_inside=0)
Matus Fabianf7ad5cb2018-01-30 03:04:17 -08003325 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
3326 is_inside=0)
3327
3328 # from client to service
3329 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3330 IP(src=self.pg1.remote_ip4, dst=external_addr) /
3331 TCP(sport=12345, dport=external_port))
3332 self.pg1.add_stream(p)
3333 self.pg_enable_capture(self.pg_interfaces)
3334 self.pg_start()
3335 capture = self.pg0.get_capture(1)
3336 p = capture[0]
Matus Fabianf7ad5cb2018-01-30 03:04:17 -08003337 try:
3338 ip = p[IP]
3339 tcp = p[TCP]
3340 self.assertEqual(ip.dst, self.pg0.remote_ip4)
3341 self.assertEqual(tcp.dport, local_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02003342 self.assert_packet_checksums_valid(p)
Matus Fabianf7ad5cb2018-01-30 03:04:17 -08003343 except:
3344 self.logger.error(ppp("Unexpected or invalid packet:", p))
3345 raise
3346
3347 # from service back to client
3348 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3349 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3350 TCP(sport=local_port, dport=12345))
3351 self.pg0.add_stream(p)
3352 self.pg_enable_capture(self.pg_interfaces)
3353 self.pg_start()
3354 capture = self.pg1.get_capture(1)
3355 p = capture[0]
3356 try:
3357 ip = p[IP]
3358 tcp = p[TCP]
3359 self.assertEqual(ip.src, external_addr)
3360 self.assertEqual(tcp.sport, external_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02003361 self.assert_packet_checksums_valid(p)
Matus Fabianf7ad5cb2018-01-30 03:04:17 -08003362 except:
3363 self.logger.error(ppp("Unexpected or invalid packet:", p))
3364 raise
3365
3366 # from local network host to external network
Matus Fabian2aad8762018-03-07 04:57:22 -08003367 pkts = self.create_stream_in(self.pg0, self.pg1)
3368 self.pg0.add_stream(pkts)
Matus Fabianf7ad5cb2018-01-30 03:04:17 -08003369 self.pg_enable_capture(self.pg_interfaces)
3370 self.pg_start()
Matus Fabian2aad8762018-03-07 04:57:22 -08003371 capture = self.pg1.get_capture(len(pkts))
3372 self.verify_capture_out(capture)
3373 pkts = self.create_stream_in(self.pg0, self.pg1)
3374 self.pg0.add_stream(pkts)
3375 self.pg_enable_capture(self.pg_interfaces)
3376 self.pg_start()
3377 capture = self.pg1.get_capture(len(pkts))
3378 self.verify_capture_out(capture)
Matus Fabianf7ad5cb2018-01-30 03:04:17 -08003379
3380 # from external network back to local network host
Matus Fabian2aad8762018-03-07 04:57:22 -08003381 pkts = self.create_stream_out(self.pg1)
3382 self.pg1.add_stream(pkts)
Matus Fabianf7ad5cb2018-01-30 03:04:17 -08003383 self.pg_enable_capture(self.pg_interfaces)
3384 self.pg_start()
Matus Fabian2aad8762018-03-07 04:57:22 -08003385 capture = self.pg0.get_capture(len(pkts))
3386 self.verify_capture_in(capture, self.pg0)
Matus Fabianf7ad5cb2018-01-30 03:04:17 -08003387
Matus Fabian204591d2018-03-01 04:48:33 -08003388 def test_output_feature_and_service2(self):
3389 """ NAT44 interface output feature and service host direct access """
3390 self.vapi.nat44_forwarding_enable_disable(1)
3391 self.nat44_add_address(self.nat_addr)
3392 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
3393 is_inside=0)
3394
3395 # session initiaded from service host - translate
3396 pkts = self.create_stream_in(self.pg0, self.pg1)
3397 self.pg0.add_stream(pkts)
3398 self.pg_enable_capture(self.pg_interfaces)
3399 self.pg_start()
3400 capture = self.pg1.get_capture(len(pkts))
3401 self.verify_capture_out(capture)
3402
3403 pkts = self.create_stream_out(self.pg1)
3404 self.pg1.add_stream(pkts)
3405 self.pg_enable_capture(self.pg_interfaces)
3406 self.pg_start()
3407 capture = self.pg0.get_capture(len(pkts))
3408 self.verify_capture_in(capture, self.pg0)
3409
Matus Fabian204591d2018-03-01 04:48:33 -08003410 # session initiaded from remote host - do not translate
3411 pkts = self.create_stream_out(self.pg1,
3412 self.pg0.remote_ip4,
3413 use_inside_ports=True)
3414 self.pg1.add_stream(pkts)
3415 self.pg_enable_capture(self.pg_interfaces)
3416 self.pg_start()
3417 capture = self.pg0.get_capture(len(pkts))
3418 self.verify_capture_in(capture, self.pg0)
3419
3420 pkts = self.create_stream_in(self.pg0, self.pg1)
3421 self.pg0.add_stream(pkts)
3422 self.pg_enable_capture(self.pg_interfaces)
3423 self.pg_start()
3424 capture = self.pg1.get_capture(len(pkts))
3425 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
3426 same_port=True)
3427
Matus Fabian4d023c82018-03-22 05:50:47 -07003428 def test_output_feature_and_service3(self):
3429 """ NAT44 interface output feature and DST NAT """
3430 external_addr = '1.2.3.4'
3431 external_port = 80
3432 local_port = 8080
3433
3434 self.vapi.nat44_forwarding_enable_disable(1)
3435 self.nat44_add_address(self.nat_addr)
3436 self.nat44_add_static_mapping(self.pg1.remote_ip4, external_addr,
3437 local_port, external_port,
3438 proto=IP_PROTOS.tcp, out2in_only=1)
3439 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3440 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
3441 is_inside=0)
3442 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
3443 is_inside=0)
3444
3445 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3446 IP(src=self.pg0.remote_ip4, dst=external_addr) /
3447 TCP(sport=12345, dport=external_port))
3448 self.pg0.add_stream(p)
3449 self.pg_enable_capture(self.pg_interfaces)
3450 self.pg_start()
3451 capture = self.pg1.get_capture(1)
3452 p = capture[0]
3453 try:
3454 ip = p[IP]
3455 tcp = p[TCP]
3456 self.assertEqual(ip.src, self.pg0.remote_ip4)
3457 self.assertEqual(tcp.sport, 12345)
3458 self.assertEqual(ip.dst, self.pg1.remote_ip4)
3459 self.assertEqual(tcp.dport, local_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02003460 self.assert_packet_checksums_valid(p)
Matus Fabian4d023c82018-03-22 05:50:47 -07003461 except:
3462 self.logger.error(ppp("Unexpected or invalid packet:", p))
3463 raise
3464
3465 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3466 IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
3467 TCP(sport=local_port, dport=12345))
3468 self.pg1.add_stream(p)
3469 self.pg_enable_capture(self.pg_interfaces)
3470 self.pg_start()
3471 capture = self.pg0.get_capture(1)
3472 p = capture[0]
3473 try:
3474 ip = p[IP]
3475 tcp = p[TCP]
3476 self.assertEqual(ip.src, external_addr)
3477 self.assertEqual(tcp.sport, external_port)
3478 self.assertEqual(ip.dst, self.pg0.remote_ip4)
3479 self.assertEqual(tcp.dport, 12345)
Klement Sekerad81ae412018-05-16 10:52:54 +02003480 self.assert_packet_checksums_valid(p)
Matus Fabian4d023c82018-03-22 05:50:47 -07003481 except:
3482 self.logger.error(ppp("Unexpected or invalid packet:", p))
3483 raise
3484
Matus Fabian36ea2d62017-10-24 04:13:49 -07003485 def test_one_armed_nat44(self):
3486 """ One armed NAT44 """
3487 remote_host = self.pg9.remote_hosts[0]
3488 local_host = self.pg9.remote_hosts[1]
3489 external_port = 0
3490
3491 self.nat44_add_address(self.nat_addr)
3492 self.vapi.nat44_interface_add_del_feature(self.pg9.sw_if_index)
3493 self.vapi.nat44_interface_add_del_feature(self.pg9.sw_if_index,
3494 is_inside=0)
3495
3496 # in2out
3497 p = (Ether(src=self.pg9.remote_mac, dst=self.pg9.local_mac) /
3498 IP(src=local_host.ip4, dst=remote_host.ip4) /
3499 TCP(sport=12345, dport=80))
3500 self.pg9.add_stream(p)
3501 self.pg_enable_capture(self.pg_interfaces)
3502 self.pg_start()
3503 capture = self.pg9.get_capture(1)
3504 p = capture[0]
3505 try:
3506 ip = p[IP]
3507 tcp = p[TCP]
3508 self.assertEqual(ip.src, self.nat_addr)
3509 self.assertEqual(ip.dst, remote_host.ip4)
3510 self.assertNotEqual(tcp.sport, 12345)
3511 external_port = tcp.sport
3512 self.assertEqual(tcp.dport, 80)
Klement Sekerad81ae412018-05-16 10:52:54 +02003513 self.assert_packet_checksums_valid(p)
Matus Fabian36ea2d62017-10-24 04:13:49 -07003514 except:
3515 self.logger.error(ppp("Unexpected or invalid packet:", p))
3516 raise
3517
3518 # out2in
3519 p = (Ether(src=self.pg9.remote_mac, dst=self.pg9.local_mac) /
3520 IP(src=remote_host.ip4, dst=self.nat_addr) /
3521 TCP(sport=80, dport=external_port))
3522 self.pg9.add_stream(p)
3523 self.pg_enable_capture(self.pg_interfaces)
3524 self.pg_start()
3525 capture = self.pg9.get_capture(1)
3526 p = capture[0]
3527 try:
3528 ip = p[IP]
3529 tcp = p[TCP]
3530 self.assertEqual(ip.src, remote_host.ip4)
3531 self.assertEqual(ip.dst, local_host.ip4)
3532 self.assertEqual(tcp.sport, 80)
3533 self.assertEqual(tcp.dport, 12345)
Klement Sekerad81ae412018-05-16 10:52:54 +02003534 self.assert_packet_checksums_valid(p)
Matus Fabian36ea2d62017-10-24 04:13:49 -07003535 except:
3536 self.logger.error(ppp("Unexpected or invalid packet:", p))
3537 raise
3538
Matus Fabiand95c39e2018-01-23 06:07:01 -08003539 def test_one_armed_nat44_static(self):
3540 """ One armed NAT44 and 1:1 NAPT symmetrical rule """
3541 remote_host = self.pg9.remote_hosts[0]
3542 local_host = self.pg9.remote_hosts[1]
3543 external_port = 80
3544 local_port = 8080
3545 eh_port_in = 0
3546
3547 self.vapi.nat44_forwarding_enable_disable(1)
3548 self.nat44_add_address(self.nat_addr, twice_nat=1)
3549 self.nat44_add_static_mapping(local_host.ip4, self.nat_addr,
3550 local_port, external_port,
3551 proto=IP_PROTOS.tcp, out2in_only=1,
3552 twice_nat=1)
3553 self.vapi.nat44_interface_add_del_feature(self.pg9.sw_if_index)
3554 self.vapi.nat44_interface_add_del_feature(self.pg9.sw_if_index,
3555 is_inside=0)
3556
3557 # from client to service
3558 p = (Ether(src=self.pg9.remote_mac, dst=self.pg9.local_mac) /
3559 IP(src=remote_host.ip4, dst=self.nat_addr) /
3560 TCP(sport=12345, dport=external_port))
3561 self.pg9.add_stream(p)
3562 self.pg_enable_capture(self.pg_interfaces)
3563 self.pg_start()
3564 capture = self.pg9.get_capture(1)
3565 p = capture[0]
Matus Fabiand95c39e2018-01-23 06:07:01 -08003566 try:
3567 ip = p[IP]
3568 tcp = p[TCP]
3569 self.assertEqual(ip.dst, local_host.ip4)
3570 self.assertEqual(ip.src, self.nat_addr)
3571 self.assertEqual(tcp.dport, local_port)
3572 self.assertNotEqual(tcp.sport, 12345)
3573 eh_port_in = tcp.sport
Klement Sekerad81ae412018-05-16 10:52:54 +02003574 self.assert_packet_checksums_valid(p)
Matus Fabiand95c39e2018-01-23 06:07:01 -08003575 except:
3576 self.logger.error(ppp("Unexpected or invalid packet:", p))
3577 raise
3578
3579 # from service back to client
3580 p = (Ether(src=self.pg9.remote_mac, dst=self.pg9.local_mac) /
3581 IP(src=local_host.ip4, dst=self.nat_addr) /
3582 TCP(sport=local_port, dport=eh_port_in))
3583 self.pg9.add_stream(p)
3584 self.pg_enable_capture(self.pg_interfaces)
3585 self.pg_start()
3586 capture = self.pg9.get_capture(1)
3587 p = capture[0]
3588 try:
3589 ip = p[IP]
3590 tcp = p[TCP]
3591 self.assertEqual(ip.src, self.nat_addr)
3592 self.assertEqual(ip.dst, remote_host.ip4)
3593 self.assertEqual(tcp.sport, external_port)
3594 self.assertEqual(tcp.dport, 12345)
Klement Sekerad81ae412018-05-16 10:52:54 +02003595 self.assert_packet_checksums_valid(p)
Matus Fabiand95c39e2018-01-23 06:07:01 -08003596 except:
3597 self.logger.error(ppp("Unexpected or invalid packet:", p))
3598 raise
3599
Matus Fabian5ba86f72017-10-26 03:37:38 -07003600 def test_del_session(self):
3601 """ Delete NAT44 session """
3602 self.nat44_add_address(self.nat_addr)
3603 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3604 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3605 is_inside=0)
3606
3607 pkts = self.create_stream_in(self.pg0, self.pg1)
3608 self.pg0.add_stream(pkts)
3609 self.pg_enable_capture(self.pg_interfaces)
3610 self.pg_start()
3611 capture = self.pg1.get_capture(len(pkts))
3612
3613 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
3614 nsessions = len(sessions)
3615
3616 self.vapi.nat44_del_session(sessions[0].inside_ip_address,
3617 sessions[0].inside_port,
3618 sessions[0].protocol)
3619 self.vapi.nat44_del_session(sessions[1].outside_ip_address,
3620 sessions[1].outside_port,
3621 sessions[1].protocol,
3622 is_in=0)
3623
3624 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
3625 self.assertEqual(nsessions - len(sessions), 2)
3626
Matus Fabianefcd1e92017-08-15 06:59:19 -07003627 def test_set_get_reass(self):
3628 """ NAT44 set/get virtual fragmentation reassembly """
3629 reas_cfg1 = self.vapi.nat_get_reass()
3630
3631 self.vapi.nat_set_reass(timeout=reas_cfg1.ip4_timeout + 5,
3632 max_reass=reas_cfg1.ip4_max_reass * 2,
3633 max_frag=reas_cfg1.ip4_max_frag * 2)
3634
3635 reas_cfg2 = self.vapi.nat_get_reass()
3636
3637 self.assertEqual(reas_cfg1.ip4_timeout + 5, reas_cfg2.ip4_timeout)
3638 self.assertEqual(reas_cfg1.ip4_max_reass * 2, reas_cfg2.ip4_max_reass)
3639 self.assertEqual(reas_cfg1.ip4_max_frag * 2, reas_cfg2.ip4_max_frag)
3640
3641 self.vapi.nat_set_reass(drop_frag=1)
3642 self.assertTrue(self.vapi.nat_get_reass().ip4_drop_frag)
3643
3644 def test_frag_in_order(self):
3645 """ NAT44 translate fragments arriving in order """
3646 self.nat44_add_address(self.nat_addr)
3647 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3648 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3649 is_inside=0)
3650
3651 data = "A" * 4 + "B" * 16 + "C" * 3
3652 self.tcp_port_in = random.randint(1025, 65535)
3653
3654 reass = self.vapi.nat_reass_dump()
3655 reass_n_start = len(reass)
3656
3657 # in2out
3658 pkts = self.create_stream_frag(self.pg0,
3659 self.pg1.remote_ip4,
3660 self.tcp_port_in,
3661 20,
3662 data)
3663 self.pg0.add_stream(pkts)
3664 self.pg_enable_capture(self.pg_interfaces)
3665 self.pg_start()
3666 frags = self.pg1.get_capture(len(pkts))
3667 p = self.reass_frags_and_verify(frags,
3668 self.nat_addr,
3669 self.pg1.remote_ip4)
3670 self.assertEqual(p[TCP].dport, 20)
3671 self.assertNotEqual(p[TCP].sport, self.tcp_port_in)
3672 self.tcp_port_out = p[TCP].sport
3673 self.assertEqual(data, p[Raw].load)
3674
3675 # out2in
3676 pkts = self.create_stream_frag(self.pg1,
3677 self.nat_addr,
3678 20,
3679 self.tcp_port_out,
3680 data)
3681 self.pg1.add_stream(pkts)
3682 self.pg_enable_capture(self.pg_interfaces)
3683 self.pg_start()
3684 frags = self.pg0.get_capture(len(pkts))
3685 p = self.reass_frags_and_verify(frags,
3686 self.pg1.remote_ip4,
3687 self.pg0.remote_ip4)
3688 self.assertEqual(p[TCP].sport, 20)
3689 self.assertEqual(p[TCP].dport, self.tcp_port_in)
3690 self.assertEqual(data, p[Raw].load)
3691
3692 reass = self.vapi.nat_reass_dump()
3693 reass_n_end = len(reass)
3694
3695 self.assertEqual(reass_n_end - reass_n_start, 2)
3696
3697 def test_reass_hairpinning(self):
3698 """ NAT44 fragments hairpinning """
Matus Fabianefcd1e92017-08-15 06:59:19 -07003699 server = self.pg0.remote_hosts[1]
3700 host_in_port = random.randint(1025, 65535)
Matus Fabianefcd1e92017-08-15 06:59:19 -07003701 server_in_port = random.randint(1025, 65535)
3702 server_out_port = random.randint(1025, 65535)
3703 data = "A" * 4 + "B" * 16 + "C" * 3
3704
3705 self.nat44_add_address(self.nat_addr)
3706 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3707 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3708 is_inside=0)
3709 # add static mapping for server
3710 self.nat44_add_static_mapping(server.ip4, self.nat_addr,
3711 server_in_port, server_out_port,
3712 proto=IP_PROTOS.tcp)
3713
3714 # send packet from host to server
3715 pkts = self.create_stream_frag(self.pg0,
3716 self.nat_addr,
3717 host_in_port,
3718 server_out_port,
3719 data)
3720 self.pg0.add_stream(pkts)
3721 self.pg_enable_capture(self.pg_interfaces)
3722 self.pg_start()
3723 frags = self.pg0.get_capture(len(pkts))
3724 p = self.reass_frags_and_verify(frags,
3725 self.nat_addr,
3726 server.ip4)
3727 self.assertNotEqual(p[TCP].sport, host_in_port)
3728 self.assertEqual(p[TCP].dport, server_in_port)
3729 self.assertEqual(data, p[Raw].load)
3730
3731 def test_frag_out_of_order(self):
3732 """ NAT44 translate fragments arriving out of order """
3733 self.nat44_add_address(self.nat_addr)
3734 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3735 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3736 is_inside=0)
3737
3738 data = "A" * 4 + "B" * 16 + "C" * 3
3739 random.randint(1025, 65535)
3740
3741 # in2out
3742 pkts = self.create_stream_frag(self.pg0,
3743 self.pg1.remote_ip4,
3744 self.tcp_port_in,
3745 20,
3746 data)
3747 pkts.reverse()
3748 self.pg0.add_stream(pkts)
3749 self.pg_enable_capture(self.pg_interfaces)
3750 self.pg_start()
3751 frags = self.pg1.get_capture(len(pkts))
3752 p = self.reass_frags_and_verify(frags,
3753 self.nat_addr,
3754 self.pg1.remote_ip4)
3755 self.assertEqual(p[TCP].dport, 20)
3756 self.assertNotEqual(p[TCP].sport, self.tcp_port_in)
3757 self.tcp_port_out = p[TCP].sport
3758 self.assertEqual(data, p[Raw].load)
3759
3760 # out2in
3761 pkts = self.create_stream_frag(self.pg1,
3762 self.nat_addr,
3763 20,
3764 self.tcp_port_out,
3765 data)
3766 pkts.reverse()
3767 self.pg1.add_stream(pkts)
3768 self.pg_enable_capture(self.pg_interfaces)
3769 self.pg_start()
3770 frags = self.pg0.get_capture(len(pkts))
3771 p = self.reass_frags_and_verify(frags,
3772 self.pg1.remote_ip4,
3773 self.pg0.remote_ip4)
3774 self.assertEqual(p[TCP].sport, 20)
3775 self.assertEqual(p[TCP].dport, self.tcp_port_in)
3776 self.assertEqual(data, p[Raw].load)
3777
Matus Fabian27697102017-11-09 01:43:47 -08003778 def test_port_restricted(self):
3779 """ Port restricted NAT44 (MAP-E CE) """
3780 self.nat44_add_address(self.nat_addr)
3781 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3782 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3783 is_inside=0)
Matus Fabian51e759f2017-12-07 23:22:51 -08003784 self.vapi.cli("nat addr-port-assignment-alg map-e psid 10 "
Matus Fabian27697102017-11-09 01:43:47 -08003785 "psid-offset 6 psid-len 6")
3786
3787 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3788 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3789 TCP(sport=4567, dport=22))
3790 self.pg0.add_stream(p)
3791 self.pg_enable_capture(self.pg_interfaces)
3792 self.pg_start()
3793 capture = self.pg1.get_capture(1)
3794 p = capture[0]
3795 try:
3796 ip = p[IP]
3797 tcp = p[TCP]
3798 self.assertEqual(ip.dst, self.pg1.remote_ip4)
3799 self.assertEqual(ip.src, self.nat_addr)
3800 self.assertEqual(tcp.dport, 22)
3801 self.assertNotEqual(tcp.sport, 4567)
3802 self.assertEqual((tcp.sport >> 6) & 63, 10)
Klement Sekerad81ae412018-05-16 10:52:54 +02003803 self.assert_packet_checksums_valid(p)
Matus Fabian27697102017-11-09 01:43:47 -08003804 except:
3805 self.logger.error(ppp("Unexpected or invalid packet:", p))
3806 raise
3807
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02003808 def twice_nat_common(self, self_twice_nat=False, same_pg=False, lb=False,
3809 client_id=None):
Matus Fabianb932d262017-12-18 05:38:24 -08003810 twice_nat_addr = '10.0.1.3'
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02003811
Matus Fabianb932d262017-12-18 05:38:24 -08003812 port_in = 8080
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02003813 if lb:
3814 if not same_pg:
3815 port_in1 = port_in
3816 port_in2 = port_in
3817 else:
3818 port_in1 = port_in+1
3819 port_in2 = port_in+2
3820
Matus Fabianb932d262017-12-18 05:38:24 -08003821 port_out = 80
3822 eh_port_out = 4567
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02003823
3824 server1 = self.pg0.remote_hosts[0]
3825 server2 = self.pg0.remote_hosts[1]
3826 if lb and same_pg:
3827 server2 = server1
3828 if not lb:
3829 server = server1
3830
3831 pg0 = self.pg0
3832 if same_pg:
3833 pg1 = self.pg0
3834 else:
3835 pg1 = self.pg1
3836
3837 eh_translate = ((not self_twice_nat) or (not lb and same_pg) or
3838 client_id == 1)
3839
Matus Fabianb932d262017-12-18 05:38:24 -08003840 self.nat44_add_address(self.nat_addr)
3841 self.nat44_add_address(twice_nat_addr, twice_nat=1)
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02003842 if not lb:
3843 self.nat44_add_static_mapping(pg0.remote_ip4, self.nat_addr,
3844 port_in, port_out,
3845 proto=IP_PROTOS.tcp,
3846 twice_nat=int(not self_twice_nat),
3847 self_twice_nat=int(self_twice_nat))
3848 else:
3849 locals = [{'addr': server1.ip4n,
3850 'port': port_in1,
3851 'probability': 50},
3852 {'addr': server2.ip4n,
3853 'port': port_in2,
3854 'probability': 50}]
3855 out_addr_n = socket.inet_pton(socket.AF_INET, self.nat_addr)
3856 self.vapi.nat44_add_del_lb_static_mapping(out_addr_n,
3857 port_out,
3858 IP_PROTOS.tcp,
3859 twice_nat=int(
3860 not self_twice_nat),
3861 self_twice_nat=int(
3862 self_twice_nat),
3863 local_num=len(locals),
3864 locals=locals)
3865 self.vapi.nat44_interface_add_del_feature(pg0.sw_if_index)
3866 self.vapi.nat44_interface_add_del_feature(pg1.sw_if_index,
Matus Fabianb932d262017-12-18 05:38:24 -08003867 is_inside=0)
3868
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02003869 if same_pg:
3870 if not lb:
3871 client = server
3872 else:
3873 assert client_id is not None
3874 if client_id == 1:
3875 client = self.pg0.remote_hosts[0]
3876 elif client_id == 2:
3877 client = self.pg0.remote_hosts[1]
3878 else:
3879 client = pg1.remote_hosts[0]
3880 p = (Ether(src=pg1.remote_mac, dst=pg1.local_mac) /
3881 IP(src=client.ip4, dst=self.nat_addr) /
Matus Fabianb932d262017-12-18 05:38:24 -08003882 TCP(sport=eh_port_out, dport=port_out))
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02003883 pg1.add_stream(p)
Matus Fabianb932d262017-12-18 05:38:24 -08003884 self.pg_enable_capture(self.pg_interfaces)
3885 self.pg_start()
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02003886 capture = pg0.get_capture(1)
Matus Fabianb932d262017-12-18 05:38:24 -08003887 p = capture[0]
3888 try:
3889 ip = p[IP]
3890 tcp = p[TCP]
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02003891 if lb:
3892 if ip.dst == server1.ip4:
3893 server = server1
3894 port_in = port_in1
3895 else:
3896 server = server2
3897 port_in = port_in2
3898 self.assertEqual(ip.dst, server.ip4)
3899 if lb and same_pg:
3900 self.assertIn(tcp.dport, [port_in1, port_in2])
3901 else:
3902 self.assertEqual(tcp.dport, port_in)
3903 if eh_translate:
3904 self.assertEqual(ip.src, twice_nat_addr)
3905 self.assertNotEqual(tcp.sport, eh_port_out)
3906 else:
3907 self.assertEqual(ip.src, client.ip4)
3908 self.assertEqual(tcp.sport, eh_port_out)
3909 eh_addr_in = ip.src
Matus Fabianb932d262017-12-18 05:38:24 -08003910 eh_port_in = tcp.sport
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02003911 saved_port_in = tcp.dport
Klement Sekerad81ae412018-05-16 10:52:54 +02003912 self.assert_packet_checksums_valid(p)
Matus Fabianb932d262017-12-18 05:38:24 -08003913 except:
3914 self.logger.error(ppp("Unexpected or invalid packet:", p))
3915 raise
3916
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02003917 p = (Ether(src=server.mac, dst=pg0.local_mac) /
3918 IP(src=server.ip4, dst=eh_addr_in) /
3919 TCP(sport=saved_port_in, dport=eh_port_in))
3920 pg0.add_stream(p)
Matus Fabianb932d262017-12-18 05:38:24 -08003921 self.pg_enable_capture(self.pg_interfaces)
3922 self.pg_start()
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02003923 capture = pg1.get_capture(1)
Matus Fabianb932d262017-12-18 05:38:24 -08003924 p = capture[0]
3925 try:
3926 ip = p[IP]
3927 tcp = p[TCP]
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02003928 self.assertEqual(ip.dst, client.ip4)
Matus Fabianb932d262017-12-18 05:38:24 -08003929 self.assertEqual(ip.src, self.nat_addr)
3930 self.assertEqual(tcp.dport, eh_port_out)
3931 self.assertEqual(tcp.sport, port_out)
Klement Sekerad81ae412018-05-16 10:52:54 +02003932 self.assert_packet_checksums_valid(p)
Matus Fabianb932d262017-12-18 05:38:24 -08003933 except:
3934 self.logger.error(ppp("Unexpected or invalid packet:", p))
3935 raise
3936
Matus Fabian70a26ac2018-05-14 06:20:28 -07003937 if eh_translate:
3938 sessions = self.vapi.nat44_user_session_dump(server.ip4n, 0)
3939 self.assertEqual(len(sessions), 1)
3940 self.assertTrue(sessions[0].ext_host_valid)
3941 self.assertTrue(sessions[0].is_twicenat)
3942 self.vapi.nat44_del_session(
3943 sessions[0].inside_ip_address,
3944 sessions[0].inside_port,
3945 sessions[0].protocol,
3946 ext_host_address=sessions[0].ext_host_nat_address,
3947 ext_host_port=sessions[0].ext_host_nat_port)
3948 sessions = self.vapi.nat44_user_session_dump(server.ip4n, 0)
3949 self.assertEqual(len(sessions), 0)
3950
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02003951 def test_twice_nat(self):
3952 """ Twice NAT44 """
3953 self.twice_nat_common()
3954
3955 def test_self_twice_nat_positive(self):
3956 """ Self Twice NAT44 (positive test) """
3957 self.twice_nat_common(self_twice_nat=True, same_pg=True)
3958
3959 def test_self_twice_nat_negative(self):
3960 """ Self Twice NAT44 (negative test) """
3961 self.twice_nat_common(self_twice_nat=True)
3962
Matus Fabianb932d262017-12-18 05:38:24 -08003963 def test_twice_nat_lb(self):
3964 """ Twice NAT44 local service load balancing """
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02003965 self.twice_nat_common(lb=True)
Matus Fabianb932d262017-12-18 05:38:24 -08003966
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02003967 def test_self_twice_nat_lb_positive(self):
3968 """ Self Twice NAT44 local service load balancing (positive test) """
3969 self.twice_nat_common(lb=True, self_twice_nat=True, same_pg=True,
3970 client_id=1)
Matus Fabianb932d262017-12-18 05:38:24 -08003971
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02003972 def test_self_twice_nat_lb_negative(self):
3973 """ Self Twice NAT44 local service load balancing (negative test) """
3974 self.twice_nat_common(lb=True, self_twice_nat=True, same_pg=True,
3975 client_id=2)
Matus Fabianb932d262017-12-18 05:38:24 -08003976
3977 def test_twice_nat_interface_addr(self):
3978 """ Acquire twice NAT44 addresses from interface """
3979 self.vapi.nat44_add_interface_addr(self.pg7.sw_if_index, twice_nat=1)
3980
3981 # no address in NAT pool
3982 adresses = self.vapi.nat44_address_dump()
3983 self.assertEqual(0, len(adresses))
3984
3985 # configure interface address and check NAT address pool
3986 self.pg7.config_ip4()
3987 adresses = self.vapi.nat44_address_dump()
3988 self.assertEqual(1, len(adresses))
3989 self.assertEqual(adresses[0].ip_address[0:4], self.pg7.local_ip4n)
3990 self.assertEqual(adresses[0].twice_nat, 1)
3991
3992 # remove interface address and check NAT address pool
3993 self.pg7.unconfig_ip4()
3994 adresses = self.vapi.nat44_address_dump()
3995 self.assertEqual(0, len(adresses))
3996
Matus Fabiana431ad12018-01-04 04:03:14 -08003997 def test_ipfix_max_frags(self):
3998 """ IPFIX logging maximum fragments pending reassembly exceeded """
3999 self.nat44_add_address(self.nat_addr)
4000 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4001 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4002 is_inside=0)
4003 self.vapi.nat_set_reass(max_frag=0)
4004 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
4005 src_address=self.pg3.local_ip4n,
4006 path_mtu=512,
4007 template_interval=10)
4008 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
4009 src_port=self.ipfix_src_port)
4010
4011 data = "A" * 4 + "B" * 16 + "C" * 3
4012 self.tcp_port_in = random.randint(1025, 65535)
4013 pkts = self.create_stream_frag(self.pg0,
4014 self.pg1.remote_ip4,
4015 self.tcp_port_in,
4016 20,
4017 data)
4018 self.pg0.add_stream(pkts[-1])
4019 self.pg_enable_capture(self.pg_interfaces)
4020 self.pg_start()
4021 frags = self.pg1.get_capture(0)
4022 self.vapi.cli("ipfix flush") # FIXME this should be an API call
4023 capture = self.pg3.get_capture(9)
4024 ipfix = IPFIXDecoder()
4025 # first load template
4026 for p in capture:
4027 self.assertTrue(p.haslayer(IPFIX))
4028 self.assertEqual(p[IP].src, self.pg3.local_ip4)
4029 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
4030 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
4031 self.assertEqual(p[UDP].dport, 4739)
4032 self.assertEqual(p[IPFIX].observationDomainID,
4033 self.ipfix_domain_id)
4034 if p.haslayer(Template):
4035 ipfix.add_template(p.getlayer(Template))
4036 # verify events in data set
4037 for p in capture:
4038 if p.haslayer(Data):
4039 data = ipfix.decode_data_set(p.getlayer(Set))
4040 self.verify_ipfix_max_fragments_ip4(data, 0,
4041 self.pg0.remote_ip4n)
4042
Matus Fabianebdf1902018-05-04 03:57:42 -07004043 def test_tcp_session_close_in(self):
4044 """ Close TCP session from inside network """
4045 self.nat44_add_address(self.nat_addr)
4046 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4047 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4048 is_inside=0)
4049
4050 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
4051 start_sessnum = len(sessions)
4052
4053 self.initiate_tcp_session(self.pg0, self.pg1)
4054
4055 # close the session from inside
4056 try:
4057 # FIN packet in -> out
4058 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4059 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4060 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
Matus Fabian70a26ac2018-05-14 06:20:28 -07004061 flags="FA", seq=100, ack=300))
Matus Fabianebdf1902018-05-04 03:57:42 -07004062 self.pg0.add_stream(p)
4063 self.pg_enable_capture(self.pg_interfaces)
4064 self.pg_start()
4065 self.pg1.get_capture(1)
4066
4067 pkts = []
4068
4069 # ACK packet out -> in
4070 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4071 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4072 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
Matus Fabian70a26ac2018-05-14 06:20:28 -07004073 flags="A", seq=300, ack=101))
Matus Fabianebdf1902018-05-04 03:57:42 -07004074 pkts.append(p)
4075
4076 # FIN packet out -> in
4077 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4078 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4079 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
Matus Fabian70a26ac2018-05-14 06:20:28 -07004080 flags="FA", seq=300, ack=101))
Matus Fabianebdf1902018-05-04 03:57:42 -07004081 pkts.append(p)
4082
4083 self.pg1.add_stream(pkts)
4084 self.pg_enable_capture(self.pg_interfaces)
4085 self.pg_start()
4086 self.pg0.get_capture(2)
4087
4088 # ACK packet in -> out
4089 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4090 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4091 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
Matus Fabian70a26ac2018-05-14 06:20:28 -07004092 flags="A", seq=101, ack=301))
Matus Fabianebdf1902018-05-04 03:57:42 -07004093 self.pg0.add_stream(p)
4094 self.pg_enable_capture(self.pg_interfaces)
4095 self.pg_start()
4096 self.pg1.get_capture(1)
4097
4098 self.initiate_tcp_session(self.pg0, self.pg1)
4099 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n,
4100 0)
Matus Fabian17e5cfb2018-05-10 22:48:53 -07004101 self.assertEqual(len(sessions) - start_sessnum, 1)
Matus Fabianebdf1902018-05-04 03:57:42 -07004102 except:
4103 self.logger.error("TCP session termination failed")
4104 raise
4105
4106 def test_tcp_session_close_out(self):
4107 """ Close TCP session from outside network """
4108 self.nat44_add_address(self.nat_addr)
4109 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4110 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4111 is_inside=0)
4112
4113 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
4114 start_sessnum = len(sessions)
4115
4116 self.initiate_tcp_session(self.pg0, self.pg1)
4117
4118 # close the session from outside
4119 try:
4120 # FIN packet out -> in
4121 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4122 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4123 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
Matus Fabian70a26ac2018-05-14 06:20:28 -07004124 flags="FA", seq=100, ack=300))
Matus Fabianebdf1902018-05-04 03:57:42 -07004125 self.pg1.add_stream(p)
4126 self.pg_enable_capture(self.pg_interfaces)
4127 self.pg_start()
4128 self.pg0.get_capture(1)
4129
Matus Fabian70a26ac2018-05-14 06:20:28 -07004130 # FIN+ACK packet in -> out
Matus Fabianebdf1902018-05-04 03:57:42 -07004131 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4132 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4133 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
Matus Fabian70a26ac2018-05-14 06:20:28 -07004134 flags="FA", seq=300, ack=101))
Matus Fabianebdf1902018-05-04 03:57:42 -07004135
Matus Fabian70a26ac2018-05-14 06:20:28 -07004136 self.pg0.add_stream(p)
Matus Fabianebdf1902018-05-04 03:57:42 -07004137 self.pg_enable_capture(self.pg_interfaces)
4138 self.pg_start()
Matus Fabian70a26ac2018-05-14 06:20:28 -07004139 self.pg1.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07004140
4141 # ACK packet out -> in
4142 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4143 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4144 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
Matus Fabian70a26ac2018-05-14 06:20:28 -07004145 flags="A", seq=101, ack=301))
Matus Fabianebdf1902018-05-04 03:57:42 -07004146 self.pg1.add_stream(p)
4147 self.pg_enable_capture(self.pg_interfaces)
4148 self.pg_start()
4149 self.pg0.get_capture(1)
4150
4151 self.initiate_tcp_session(self.pg0, self.pg1)
4152 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n,
4153 0)
Matus Fabian17e5cfb2018-05-10 22:48:53 -07004154 self.assertEqual(len(sessions) - start_sessnum, 1)
Matus Fabianebdf1902018-05-04 03:57:42 -07004155 except:
4156 self.logger.error("TCP session termination failed")
4157 raise
4158
4159 def test_tcp_session_close_simultaneous(self):
4160 """ Close TCP session from inside network """
4161 self.nat44_add_address(self.nat_addr)
4162 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4163 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4164 is_inside=0)
4165
4166 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
4167 start_sessnum = len(sessions)
4168
4169 self.initiate_tcp_session(self.pg0, self.pg1)
4170
4171 # close the session from inside
4172 try:
4173 # FIN packet in -> out
4174 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4175 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4176 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
Matus Fabian70a26ac2018-05-14 06:20:28 -07004177 flags="FA", seq=100, ack=300))
Matus Fabianebdf1902018-05-04 03:57:42 -07004178 self.pg0.add_stream(p)
4179 self.pg_enable_capture(self.pg_interfaces)
4180 self.pg_start()
4181 self.pg1.get_capture(1)
4182
4183 # FIN packet out -> in
4184 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4185 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4186 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
Matus Fabian70a26ac2018-05-14 06:20:28 -07004187 flags="FA", seq=300, ack=100))
Matus Fabianebdf1902018-05-04 03:57:42 -07004188 self.pg1.add_stream(p)
4189 self.pg_enable_capture(self.pg_interfaces)
4190 self.pg_start()
4191 self.pg0.get_capture(1)
4192
4193 # ACK packet in -> out
4194 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4195 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4196 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
Matus Fabian70a26ac2018-05-14 06:20:28 -07004197 flags="A", seq=101, ack=301))
Matus Fabianebdf1902018-05-04 03:57:42 -07004198 self.pg0.add_stream(p)
4199 self.pg_enable_capture(self.pg_interfaces)
4200 self.pg_start()
4201 self.pg1.get_capture(1)
4202
4203 # ACK packet out -> in
4204 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4205 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4206 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
Matus Fabian70a26ac2018-05-14 06:20:28 -07004207 flags="A", seq=301, ack=101))
Matus Fabianebdf1902018-05-04 03:57:42 -07004208 self.pg1.add_stream(p)
4209 self.pg_enable_capture(self.pg_interfaces)
4210 self.pg_start()
4211 self.pg0.get_capture(1)
4212
4213 self.initiate_tcp_session(self.pg0, self.pg1)
4214 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n,
4215 0)
Matus Fabian17e5cfb2018-05-10 22:48:53 -07004216 self.assertEqual(len(sessions) - start_sessnum, 1)
Matus Fabianebdf1902018-05-04 03:57:42 -07004217 except:
4218 self.logger.error("TCP session termination failed")
4219 raise
4220
Matus Fabiande886752016-12-07 03:38:19 -08004221 def tearDown(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07004222 super(TestNAT44, self).tearDown()
Matus Fabiande886752016-12-07 03:38:19 -08004223 if not self.vpp_dead:
Matus Fabian82119542018-01-25 01:13:22 -08004224 self.logger.info(self.vapi.cli("show nat44 addresses"))
4225 self.logger.info(self.vapi.cli("show nat44 interfaces"))
4226 self.logger.info(self.vapi.cli("show nat44 static mappings"))
4227 self.logger.info(self.vapi.cli("show nat44 interface address"))
4228 self.logger.info(self.vapi.cli("show nat44 sessions detail"))
Matus Fabianefcd1e92017-08-15 06:59:19 -07004229 self.logger.info(self.vapi.cli("show nat virtual-reassembly"))
Matus Fabian51e759f2017-12-07 23:22:51 -08004230 self.vapi.cli("nat addr-port-assignment-alg default")
Matus Fabian2ba92e32017-08-21 07:05:03 -07004231 self.clear_nat44()
Matus Fabiande886752016-12-07 03:38:19 -08004232
Matus Fabianeea28d72017-01-13 04:15:54 -08004233
Juraj Slobodacba69362017-12-19 02:09:32 +01004234class TestNAT44Out2InDPO(MethodHolder):
4235 """ NAT44 Test Cases using out2in DPO """
4236
4237 @classmethod
4238 def setUpConstants(cls):
4239 super(TestNAT44Out2InDPO, cls).setUpConstants()
4240 cls.vpp_cmdline.extend(["nat", "{", "out2in dpo", "}"])
4241
4242 @classmethod
4243 def setUpClass(cls):
4244 super(TestNAT44Out2InDPO, cls).setUpClass()
4245
4246 try:
4247 cls.tcp_port_in = 6303
4248 cls.tcp_port_out = 6303
4249 cls.udp_port_in = 6304
4250 cls.udp_port_out = 6304
4251 cls.icmp_id_in = 6305
4252 cls.icmp_id_out = 6305
4253 cls.nat_addr = '10.0.0.3'
4254 cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
4255 cls.dst_ip4 = '192.168.70.1'
4256
4257 cls.create_pg_interfaces(range(2))
4258
4259 cls.pg0.admin_up()
4260 cls.pg0.config_ip4()
4261 cls.pg0.resolve_arp()
4262
4263 cls.pg1.admin_up()
4264 cls.pg1.config_ip6()
4265 cls.pg1.resolve_ndp()
4266
4267 cls.vapi.ip_add_del_route(is_ipv6=True, dst_address='\x00'*16,
4268 dst_address_length=0,
4269 next_hop_address=cls.pg1.remote_ip6n,
4270 next_hop_sw_if_index=cls.pg1.sw_if_index)
4271
4272 except Exception:
4273 super(TestNAT44Out2InDPO, cls).tearDownClass()
4274 raise
4275
4276 def configure_xlat(self):
4277 self.dst_ip6_pfx = '1:2:3::'
4278 self.dst_ip6_pfx_n = socket.inet_pton(socket.AF_INET6,
4279 self.dst_ip6_pfx)
4280 self.dst_ip6_pfx_len = 96
4281 self.src_ip6_pfx = '4:5:6::'
4282 self.src_ip6_pfx_n = socket.inet_pton(socket.AF_INET6,
4283 self.src_ip6_pfx)
4284 self.src_ip6_pfx_len = 96
4285 self.vapi.map_add_domain(self.dst_ip6_pfx_n, self.dst_ip6_pfx_len,
4286 self.src_ip6_pfx_n, self.src_ip6_pfx_len,
4287 '\x00\x00\x00\x00', 0, is_translation=1,
4288 is_rfc6052=1)
4289
4290 def test_464xlat_ce(self):
4291 """ Test 464XLAT CE with NAT44 """
4292
4293 self.configure_xlat()
4294
4295 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4296 self.vapi.nat44_add_del_address_range(self.nat_addr_n, self.nat_addr_n)
4297
4298 out_src_ip6 = self.compose_ip6(self.dst_ip4, self.dst_ip6_pfx,
4299 self.dst_ip6_pfx_len)
4300 out_dst_ip6 = self.compose_ip6(self.nat_addr, self.src_ip6_pfx,
4301 self.src_ip6_pfx_len)
4302
4303 try:
4304 pkts = self.create_stream_in(self.pg0, self.pg1, self.dst_ip4)
4305 self.pg0.add_stream(pkts)
4306 self.pg_enable_capture(self.pg_interfaces)
4307 self.pg_start()
4308 capture = self.pg1.get_capture(len(pkts))
4309 self.verify_capture_out_ip6(capture, nat_ip=out_dst_ip6,
4310 dst_ip=out_src_ip6)
4311
4312 pkts = self.create_stream_out_ip6(self.pg1, out_src_ip6,
4313 out_dst_ip6)
4314 self.pg1.add_stream(pkts)
4315 self.pg_enable_capture(self.pg_interfaces)
4316 self.pg_start()
4317 capture = self.pg0.get_capture(len(pkts))
4318 self.verify_capture_in(capture, self.pg0)
4319 finally:
4320 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
4321 is_add=0)
4322 self.vapi.nat44_add_del_address_range(self.nat_addr_n,
4323 self.nat_addr_n, is_add=0)
4324
4325 def test_464xlat_ce_no_nat(self):
4326 """ Test 464XLAT CE without NAT44 """
4327
4328 self.configure_xlat()
4329
4330 out_src_ip6 = self.compose_ip6(self.dst_ip4, self.dst_ip6_pfx,
4331 self.dst_ip6_pfx_len)
4332 out_dst_ip6 = self.compose_ip6(self.pg0.remote_ip4, self.src_ip6_pfx,
4333 self.src_ip6_pfx_len)
4334
4335 pkts = self.create_stream_in(self.pg0, self.pg1, self.dst_ip4)
4336 self.pg0.add_stream(pkts)
4337 self.pg_enable_capture(self.pg_interfaces)
4338 self.pg_start()
4339 capture = self.pg1.get_capture(len(pkts))
4340 self.verify_capture_out_ip6(capture, dst_ip=out_src_ip6,
4341 nat_ip=out_dst_ip6, same_port=True)
4342
4343 pkts = self.create_stream_out_ip6(self.pg1, out_src_ip6, out_dst_ip6)
4344 self.pg1.add_stream(pkts)
4345 self.pg_enable_capture(self.pg_interfaces)
4346 self.pg_start()
4347 capture = self.pg0.get_capture(len(pkts))
4348 self.verify_capture_in(capture, self.pg0)
4349
4350
Martin Gálikd7f75cd2017-03-27 06:02:47 -07004351class TestDeterministicNAT(MethodHolder):
Matus Fabian066f0342017-02-10 03:48:01 -08004352 """ Deterministic NAT Test Cases """
4353
4354 @classmethod
4355 def setUpConstants(cls):
4356 super(TestDeterministicNAT, cls).setUpConstants()
Matus Fabian2ba92e32017-08-21 07:05:03 -07004357 cls.vpp_cmdline.extend(["nat", "{", "deterministic", "}"])
Matus Fabian066f0342017-02-10 03:48:01 -08004358
4359 @classmethod
4360 def setUpClass(cls):
4361 super(TestDeterministicNAT, cls).setUpClass()
4362
4363 try:
Martin Gálik977c1cb2017-03-30 23:21:51 -07004364 cls.tcp_port_in = 6303
Martin Gálik9806eae2017-04-25 01:25:08 -07004365 cls.tcp_external_port = 6303
Martin Gálik977c1cb2017-03-30 23:21:51 -07004366 cls.udp_port_in = 6304
Martin Gálik9806eae2017-04-25 01:25:08 -07004367 cls.udp_external_port = 6304
Martin Gálik977c1cb2017-03-30 23:21:51 -07004368 cls.icmp_id_in = 6305
Matus Fabian2ba92e32017-08-21 07:05:03 -07004369 cls.nat_addr = '10.0.0.3'
Martin Gálik977c1cb2017-03-30 23:21:51 -07004370
Matus Fabian2f2db1c2017-04-18 05:29:59 -07004371 cls.create_pg_interfaces(range(3))
Matus Fabian066f0342017-02-10 03:48:01 -08004372 cls.interfaces = list(cls.pg_interfaces)
4373
4374 for i in cls.interfaces:
4375 i.admin_up()
4376 i.config_ip4()
4377 i.resolve_arp()
4378
Martin Gálik977c1cb2017-03-30 23:21:51 -07004379 cls.pg0.generate_remote_hosts(2)
4380 cls.pg0.configure_ipv4_neighbors()
4381
Matus Fabian066f0342017-02-10 03:48:01 -08004382 except Exception:
4383 super(TestDeterministicNAT, cls).tearDownClass()
4384 raise
4385
Martin Gálik977c1cb2017-03-30 23:21:51 -07004386 def create_stream_in(self, in_if, out_if, ttl=64):
4387 """
4388 Create packet stream for inside network
4389
4390 :param in_if: Inside interface
4391 :param out_if: Outside interface
4392 :param ttl: TTL of generated packets
4393 """
4394 pkts = []
4395 # TCP
4396 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
4397 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004398 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07004399 pkts.append(p)
4400
4401 # UDP
4402 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
4403 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004404 UDP(sport=self.udp_port_in, dport=self.udp_external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07004405 pkts.append(p)
4406
4407 # ICMP
4408 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
4409 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
4410 ICMP(id=self.icmp_id_in, type='echo-request'))
4411 pkts.append(p)
4412
4413 return pkts
4414
4415 def create_stream_out(self, out_if, dst_ip=None, ttl=64):
4416 """
4417 Create packet stream for outside network
4418
4419 :param out_if: Outside interface
Matus Fabian2ba92e32017-08-21 07:05:03 -07004420 :param dst_ip: Destination IP address (Default use global NAT address)
Martin Gálik977c1cb2017-03-30 23:21:51 -07004421 :param ttl: TTL of generated packets
4422 """
4423 if dst_ip is None:
Matus Fabian2ba92e32017-08-21 07:05:03 -07004424 dst_ip = self.nat_addr
Martin Gálik977c1cb2017-03-30 23:21:51 -07004425 pkts = []
4426 # TCP
4427 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
4428 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004429 TCP(dport=self.tcp_port_out, sport=self.tcp_external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07004430 pkts.append(p)
4431
4432 # UDP
4433 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
4434 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004435 UDP(dport=self.udp_port_out, sport=self.udp_external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07004436 pkts.append(p)
4437
4438 # ICMP
4439 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
4440 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
4441 ICMP(id=self.icmp_external_id, type='echo-reply'))
4442 pkts.append(p)
4443
4444 return pkts
4445
4446 def verify_capture_out(self, capture, nat_ip=None, packet_num=3):
4447 """
4448 Verify captured packets on outside network
4449
4450 :param capture: Captured packets
Matus Fabian2ba92e32017-08-21 07:05:03 -07004451 :param nat_ip: Translated IP address (Default use global NAT address)
Martin Gálik977c1cb2017-03-30 23:21:51 -07004452 :param same_port: Sorce port number is not translated (Default False)
4453 :param packet_num: Expected number of packets (Default 3)
4454 """
4455 if nat_ip is None:
Matus Fabian2ba92e32017-08-21 07:05:03 -07004456 nat_ip = self.nat_addr
Martin Gálik977c1cb2017-03-30 23:21:51 -07004457 self.assertEqual(packet_num, len(capture))
4458 for packet in capture:
4459 try:
4460 self.assertEqual(packet[IP].src, nat_ip)
4461 if packet.haslayer(TCP):
Martin Gálik9806eae2017-04-25 01:25:08 -07004462 self.tcp_port_out = packet[TCP].sport
Martin Gálik977c1cb2017-03-30 23:21:51 -07004463 elif packet.haslayer(UDP):
Martin Gálik9806eae2017-04-25 01:25:08 -07004464 self.udp_port_out = packet[UDP].sport
Martin Gálik977c1cb2017-03-30 23:21:51 -07004465 else:
4466 self.icmp_external_id = packet[ICMP].id
4467 except:
4468 self.logger.error(ppp("Unexpected or invalid packet "
4469 "(outside network):", packet))
4470 raise
4471
Matus Fabian2f2db1c2017-04-18 05:29:59 -07004472 def verify_ipfix_max_entries_per_user(self, data):
4473 """
4474 Verify IPFIX maximum entries per user exceeded event
4475
4476 :param data: Decoded IPFIX data records
4477 """
4478 self.assertEqual(1, len(data))
4479 record = data[0]
4480 # natEvent
4481 self.assertEqual(ord(record[230]), 13)
4482 # natQuotaExceededEvent
4483 self.assertEqual('\x03\x00\x00\x00', record[466])
Matus Fabiana431ad12018-01-04 04:03:14 -08004484 # maxEntriesPerUser
4485 self.assertEqual('\xe8\x03\x00\x00', record[473])
Matus Fabian2f2db1c2017-04-18 05:29:59 -07004486 # sourceIPv4Address
4487 self.assertEqual(self.pg0.remote_ip4n, record[8])
4488
Matus Fabian066f0342017-02-10 03:48:01 -08004489 def test_deterministic_mode(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07004490 """ NAT plugin run deterministic mode """
Matus Fabian066f0342017-02-10 03:48:01 -08004491 in_addr = '172.16.255.0'
4492 out_addr = '172.17.255.50'
4493 in_addr_t = '172.16.255.20'
4494 in_addr_n = socket.inet_aton(in_addr)
4495 out_addr_n = socket.inet_aton(out_addr)
4496 in_addr_t_n = socket.inet_aton(in_addr_t)
4497 in_plen = 24
4498 out_plen = 32
4499
Matus Fabian2ba92e32017-08-21 07:05:03 -07004500 nat_config = self.vapi.nat_show_config()
4501 self.assertEqual(1, nat_config.deterministic)
Matus Fabian066f0342017-02-10 03:48:01 -08004502
Matus Fabian2ba92e32017-08-21 07:05:03 -07004503 self.vapi.nat_det_add_del_map(in_addr_n, in_plen, out_addr_n, out_plen)
Matus Fabian066f0342017-02-10 03:48:01 -08004504
Matus Fabian2ba92e32017-08-21 07:05:03 -07004505 rep1 = self.vapi.nat_det_forward(in_addr_t_n)
Matus Fabian066f0342017-02-10 03:48:01 -08004506 self.assertEqual(rep1.out_addr[:4], out_addr_n)
Matus Fabian2ba92e32017-08-21 07:05:03 -07004507 rep2 = self.vapi.nat_det_reverse(out_addr_n, rep1.out_port_hi)
Matus Fabian066f0342017-02-10 03:48:01 -08004508 self.assertEqual(rep2.in_addr[:4], in_addr_t_n)
4509
Matus Fabian2ba92e32017-08-21 07:05:03 -07004510 deterministic_mappings = self.vapi.nat_det_map_dump()
Martin17a75cb2017-03-08 05:53:20 -08004511 self.assertEqual(len(deterministic_mappings), 1)
4512 dsm = deterministic_mappings[0]
4513 self.assertEqual(in_addr_n, dsm.in_addr[:4])
4514 self.assertEqual(in_plen, dsm.in_plen)
4515 self.assertEqual(out_addr_n, dsm.out_addr[:4])
4516 self.assertEqual(out_plen, dsm.out_plen)
4517
Matus Fabian2ba92e32017-08-21 07:05:03 -07004518 self.clear_nat_det()
4519 deterministic_mappings = self.vapi.nat_det_map_dump()
Martinb616e9f2017-03-14 02:25:45 -07004520 self.assertEqual(len(deterministic_mappings), 0)
4521
Matus Fabian6a0946f2017-04-12 03:36:13 -07004522 def test_set_timeouts(self):
4523 """ Set deterministic NAT timeouts """
Matus Fabian2ba92e32017-08-21 07:05:03 -07004524 timeouts_before = self.vapi.nat_det_get_timeouts()
Matus Fabian6a0946f2017-04-12 03:36:13 -07004525
Matus Fabian2ba92e32017-08-21 07:05:03 -07004526 self.vapi.nat_det_set_timeouts(timeouts_before.udp + 10,
4527 timeouts_before.tcp_established + 10,
4528 timeouts_before.tcp_transitory + 10,
4529 timeouts_before.icmp + 10)
Matus Fabian6a0946f2017-04-12 03:36:13 -07004530
Matus Fabian2ba92e32017-08-21 07:05:03 -07004531 timeouts_after = self.vapi.nat_det_get_timeouts()
Matus Fabian6a0946f2017-04-12 03:36:13 -07004532
4533 self.assertNotEqual(timeouts_before.udp, timeouts_after.udp)
4534 self.assertNotEqual(timeouts_before.icmp, timeouts_after.icmp)
4535 self.assertNotEqual(timeouts_before.tcp_established,
4536 timeouts_after.tcp_established)
4537 self.assertNotEqual(timeouts_before.tcp_transitory,
4538 timeouts_after.tcp_transitory)
4539
Martin Gálik977c1cb2017-03-30 23:21:51 -07004540 def test_det_in(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07004541 """ Deterministic NAT translation test (TCP, UDP, ICMP) """
Martin Gálik977c1cb2017-03-30 23:21:51 -07004542
4543 nat_ip = "10.0.0.10"
Martin Gálik977c1cb2017-03-30 23:21:51 -07004544
Matus Fabian2ba92e32017-08-21 07:05:03 -07004545 self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
4546 32,
4547 socket.inet_aton(nat_ip),
4548 32)
4549 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4550 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4551 is_inside=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07004552
4553 # in2out
4554 pkts = self.create_stream_in(self.pg0, self.pg1)
4555 self.pg0.add_stream(pkts)
4556 self.pg_enable_capture(self.pg_interfaces)
4557 self.pg_start()
4558 capture = self.pg1.get_capture(len(pkts))
4559 self.verify_capture_out(capture, nat_ip)
4560
4561 # out2in
4562 pkts = self.create_stream_out(self.pg1, nat_ip)
4563 self.pg1.add_stream(pkts)
4564 self.pg_enable_capture(self.pg_interfaces)
4565 self.pg_start()
4566 capture = self.pg0.get_capture(len(pkts))
4567 self.verify_capture_in(capture, self.pg0)
4568
Martin Gálik9806eae2017-04-25 01:25:08 -07004569 # session dump test
Matus Fabian2ba92e32017-08-21 07:05:03 -07004570 sessions = self.vapi.nat_det_session_dump(self.pg0.remote_ip4n)
Martin Gálik9806eae2017-04-25 01:25:08 -07004571 self.assertEqual(len(sessions), 3)
4572
4573 # TCP session
4574 s = sessions[0]
4575 self.assertEqual(s.ext_addr[:4], self.pg1.remote_ip4n)
4576 self.assertEqual(s.in_port, self.tcp_port_in)
4577 self.assertEqual(s.out_port, self.tcp_port_out)
4578 self.assertEqual(s.ext_port, self.tcp_external_port)
4579
4580 # UDP session
4581 s = sessions[1]
4582 self.assertEqual(s.ext_addr[:4], self.pg1.remote_ip4n)
4583 self.assertEqual(s.in_port, self.udp_port_in)
4584 self.assertEqual(s.out_port, self.udp_port_out)
4585 self.assertEqual(s.ext_port, self.udp_external_port)
4586
4587 # ICMP session
4588 s = sessions[2]
4589 self.assertEqual(s.ext_addr[:4], self.pg1.remote_ip4n)
4590 self.assertEqual(s.in_port, self.icmp_id_in)
4591 self.assertEqual(s.out_port, self.icmp_external_id)
4592
Martin Gálik977c1cb2017-03-30 23:21:51 -07004593 def test_multiple_users(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07004594 """ Deterministic NAT multiple users """
Martin Gálik977c1cb2017-03-30 23:21:51 -07004595
4596 nat_ip = "10.0.0.10"
4597 port_in = 80
Martin Gálik9806eae2017-04-25 01:25:08 -07004598 external_port = 6303
Martin Gálik977c1cb2017-03-30 23:21:51 -07004599
4600 host0 = self.pg0.remote_hosts[0]
4601 host1 = self.pg0.remote_hosts[1]
4602
Matus Fabian2ba92e32017-08-21 07:05:03 -07004603 self.vapi.nat_det_add_del_map(host0.ip4n,
4604 24,
4605 socket.inet_aton(nat_ip),
4606 32)
4607 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4608 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4609 is_inside=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07004610
4611 # host0 to out
4612 p = (Ether(src=host0.mac, dst=self.pg0.local_mac) /
4613 IP(src=host0.ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004614 TCP(sport=port_in, dport=external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07004615 self.pg0.add_stream(p)
4616 self.pg_enable_capture(self.pg_interfaces)
4617 self.pg_start()
4618 capture = self.pg1.get_capture(1)
4619 p = capture[0]
4620 try:
4621 ip = p[IP]
4622 tcp = p[TCP]
4623 self.assertEqual(ip.src, nat_ip)
4624 self.assertEqual(ip.dst, self.pg1.remote_ip4)
Martin Gálik9806eae2017-04-25 01:25:08 -07004625 self.assertEqual(tcp.dport, external_port)
4626 port_out0 = tcp.sport
Martin Gálik977c1cb2017-03-30 23:21:51 -07004627 except:
4628 self.logger.error(ppp("Unexpected or invalid packet:", p))
4629 raise
4630
4631 # host1 to out
4632 p = (Ether(src=host1.mac, dst=self.pg0.local_mac) /
4633 IP(src=host1.ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004634 TCP(sport=port_in, dport=external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07004635 self.pg0.add_stream(p)
4636 self.pg_enable_capture(self.pg_interfaces)
4637 self.pg_start()
4638 capture = self.pg1.get_capture(1)
4639 p = capture[0]
4640 try:
4641 ip = p[IP]
4642 tcp = p[TCP]
4643 self.assertEqual(ip.src, nat_ip)
4644 self.assertEqual(ip.dst, self.pg1.remote_ip4)
Martin Gálik9806eae2017-04-25 01:25:08 -07004645 self.assertEqual(tcp.dport, external_port)
4646 port_out1 = tcp.sport
Martin Gálik977c1cb2017-03-30 23:21:51 -07004647 except:
4648 self.logger.error(ppp("Unexpected or invalid packet:", p))
4649 raise
4650
Matus Fabian2ba92e32017-08-21 07:05:03 -07004651 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07004652 self.assertEqual(1, len(dms))
4653 self.assertEqual(2, dms[0].ses_num)
4654
4655 # out to host0
4656 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4657 IP(src=self.pg1.remote_ip4, dst=nat_ip) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004658 TCP(sport=external_port, dport=port_out0))
Martin Gálik977c1cb2017-03-30 23:21:51 -07004659 self.pg1.add_stream(p)
4660 self.pg_enable_capture(self.pg_interfaces)
4661 self.pg_start()
4662 capture = self.pg0.get_capture(1)
4663 p = capture[0]
4664 try:
4665 ip = p[IP]
4666 tcp = p[TCP]
4667 self.assertEqual(ip.src, self.pg1.remote_ip4)
4668 self.assertEqual(ip.dst, host0.ip4)
4669 self.assertEqual(tcp.dport, port_in)
Martin Gálik9806eae2017-04-25 01:25:08 -07004670 self.assertEqual(tcp.sport, external_port)
Martin Gálik977c1cb2017-03-30 23:21:51 -07004671 except:
4672 self.logger.error(ppp("Unexpected or invalid packet:", p))
4673 raise
4674
4675 # out to host1
4676 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4677 IP(src=self.pg1.remote_ip4, dst=nat_ip) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004678 TCP(sport=external_port, dport=port_out1))
Martin Gálik977c1cb2017-03-30 23:21:51 -07004679 self.pg1.add_stream(p)
4680 self.pg_enable_capture(self.pg_interfaces)
4681 self.pg_start()
4682 capture = self.pg0.get_capture(1)
4683 p = capture[0]
4684 try:
4685 ip = p[IP]
4686 tcp = p[TCP]
4687 self.assertEqual(ip.src, self.pg1.remote_ip4)
4688 self.assertEqual(ip.dst, host1.ip4)
4689 self.assertEqual(tcp.dport, port_in)
Martin Gálik9806eae2017-04-25 01:25:08 -07004690 self.assertEqual(tcp.sport, external_port)
Martin Gálik977c1cb2017-03-30 23:21:51 -07004691 except:
4692 self.logger.error(ppp("Unexpected or invalid packet", p))
4693 raise
4694
Martin Gálik6bc8c642017-04-19 01:12:27 -07004695 # session close api test
Matus Fabian2ba92e32017-08-21 07:05:03 -07004696 self.vapi.nat_det_close_session_out(socket.inet_aton(nat_ip),
4697 port_out1,
Martin Gálik6bc8c642017-04-19 01:12:27 -07004698 self.pg1.remote_ip4n,
Martin Gálik9806eae2017-04-25 01:25:08 -07004699 external_port)
Matus Fabian2ba92e32017-08-21 07:05:03 -07004700 dms = self.vapi.nat_det_map_dump()
4701 self.assertEqual(dms[0].ses_num, 1)
4702
4703 self.vapi.nat_det_close_session_in(host0.ip4n,
4704 port_in,
4705 self.pg1.remote_ip4n,
4706 external_port)
4707 dms = self.vapi.nat_det_map_dump()
Martin Gálik6bc8c642017-04-19 01:12:27 -07004708 self.assertEqual(dms[0].ses_num, 0)
4709
Martin Gálik977c1cb2017-03-30 23:21:51 -07004710 def test_tcp_session_close_detection_in(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07004711 """ Deterministic NAT TCP session close from inside network """
4712 self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
4713 32,
4714 socket.inet_aton(self.nat_addr),
4715 32)
4716 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4717 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4718 is_inside=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07004719
4720 self.initiate_tcp_session(self.pg0, self.pg1)
4721
4722 # close the session from inside
4723 try:
4724 # FIN packet in -> out
4725 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4726 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004727 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
Martin Gálik977c1cb2017-03-30 23:21:51 -07004728 flags="F"))
4729 self.pg0.add_stream(p)
4730 self.pg_enable_capture(self.pg_interfaces)
4731 self.pg_start()
4732 self.pg1.get_capture(1)
4733
4734 pkts = []
4735
4736 # ACK packet out -> in
4737 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07004738 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004739 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
Martin Gálik977c1cb2017-03-30 23:21:51 -07004740 flags="A"))
4741 pkts.append(p)
4742
4743 # FIN packet out -> in
4744 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07004745 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004746 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
Martin Gálik977c1cb2017-03-30 23:21:51 -07004747 flags="F"))
4748 pkts.append(p)
4749
4750 self.pg1.add_stream(pkts)
4751 self.pg_enable_capture(self.pg_interfaces)
4752 self.pg_start()
4753 self.pg0.get_capture(2)
4754
4755 # ACK packet in -> out
4756 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4757 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004758 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
Martin Gálik977c1cb2017-03-30 23:21:51 -07004759 flags="A"))
4760 self.pg0.add_stream(p)
4761 self.pg_enable_capture(self.pg_interfaces)
4762 self.pg_start()
4763 self.pg1.get_capture(1)
4764
Matus Fabian2ba92e32017-08-21 07:05:03 -07004765 # Check if deterministic NAT44 closed the session
4766 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07004767 self.assertEqual(0, dms[0].ses_num)
4768 except:
4769 self.logger.error("TCP session termination failed")
4770 raise
4771
4772 def test_tcp_session_close_detection_out(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07004773 """ Deterministic NAT TCP session close from outside network """
4774 self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
4775 32,
4776 socket.inet_aton(self.nat_addr),
4777 32)
4778 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4779 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4780 is_inside=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07004781
4782 self.initiate_tcp_session(self.pg0, self.pg1)
4783
4784 # close the session from outside
4785 try:
4786 # FIN packet out -> in
4787 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07004788 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004789 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
Martin Gálik977c1cb2017-03-30 23:21:51 -07004790 flags="F"))
4791 self.pg1.add_stream(p)
4792 self.pg_enable_capture(self.pg_interfaces)
4793 self.pg_start()
4794 self.pg0.get_capture(1)
4795
4796 pkts = []
4797
4798 # ACK packet in -> out
4799 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4800 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004801 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
Martin Gálik977c1cb2017-03-30 23:21:51 -07004802 flags="A"))
4803 pkts.append(p)
4804
4805 # ACK packet in -> out
4806 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4807 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004808 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
Martin Gálik977c1cb2017-03-30 23:21:51 -07004809 flags="F"))
4810 pkts.append(p)
4811
4812 self.pg0.add_stream(pkts)
4813 self.pg_enable_capture(self.pg_interfaces)
4814 self.pg_start()
4815 self.pg1.get_capture(2)
4816
4817 # ACK packet out -> in
4818 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07004819 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Martin Gálik9806eae2017-04-25 01:25:08 -07004820 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
Martin Gálik977c1cb2017-03-30 23:21:51 -07004821 flags="A"))
4822 self.pg1.add_stream(p)
4823 self.pg_enable_capture(self.pg_interfaces)
4824 self.pg_start()
4825 self.pg0.get_capture(1)
4826
Matus Fabian2ba92e32017-08-21 07:05:03 -07004827 # Check if deterministic NAT44 closed the session
4828 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07004829 self.assertEqual(0, dms[0].ses_num)
4830 except:
4831 self.logger.error("TCP session termination failed")
4832 raise
4833
4834 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
4835 def test_session_timeout(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07004836 """ Deterministic NAT session timeouts """
4837 self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
4838 32,
4839 socket.inet_aton(self.nat_addr),
4840 32)
4841 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4842 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4843 is_inside=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07004844
4845 self.initiate_tcp_session(self.pg0, self.pg1)
Matus Fabian2ba92e32017-08-21 07:05:03 -07004846 self.vapi.nat_det_set_timeouts(5, 5, 5, 5)
Martin Gálik977c1cb2017-03-30 23:21:51 -07004847 pkts = self.create_stream_in(self.pg0, self.pg1)
4848 self.pg0.add_stream(pkts)
4849 self.pg_enable_capture(self.pg_interfaces)
4850 self.pg_start()
4851 capture = self.pg1.get_capture(len(pkts))
4852 sleep(15)
4853
Matus Fabian2ba92e32017-08-21 07:05:03 -07004854 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07004855 self.assertEqual(0, dms[0].ses_num)
4856
Matus Fabian7c0aecc2017-07-03 01:21:38 -07004857 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
Martin Gálik977c1cb2017-03-30 23:21:51 -07004858 def test_session_limit_per_user(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07004859 """ Deterministic NAT maximum sessions per user limit """
4860 self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
4861 32,
4862 socket.inet_aton(self.nat_addr),
4863 32)
4864 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4865 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4866 is_inside=0)
Matus Fabian2f2db1c2017-04-18 05:29:59 -07004867 self.vapi.set_ipfix_exporter(collector_address=self.pg2.remote_ip4n,
4868 src_address=self.pg2.local_ip4n,
4869 path_mtu=512,
4870 template_interval=10)
Matus Fabian2ba92e32017-08-21 07:05:03 -07004871 self.vapi.nat_ipfix()
Martin Gálik977c1cb2017-03-30 23:21:51 -07004872
4873 pkts = []
4874 for port in range(1025, 2025):
4875 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4876 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4877 UDP(sport=port, dport=port))
4878 pkts.append(p)
4879
4880 self.pg0.add_stream(pkts)
4881 self.pg_enable_capture(self.pg_interfaces)
4882 self.pg_start()
4883 capture = self.pg1.get_capture(len(pkts))
4884
4885 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4886 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálikf7e655d2017-04-27 02:13:26 -07004887 UDP(sport=3001, dport=3002))
Martin Gálik977c1cb2017-03-30 23:21:51 -07004888 self.pg0.add_stream(p)
4889 self.pg_enable_capture(self.pg_interfaces)
4890 self.pg_start()
4891 capture = self.pg1.assert_nothing_captured()
4892
Martin Gálikf7e655d2017-04-27 02:13:26 -07004893 # verify ICMP error packet
4894 capture = self.pg0.get_capture(1)
4895 p = capture[0]
4896 self.assertTrue(p.haslayer(ICMP))
4897 icmp = p[ICMP]
4898 self.assertEqual(icmp.type, 3)
4899 self.assertEqual(icmp.code, 1)
4900 self.assertTrue(icmp.haslayer(IPerror))
4901 inner_ip = icmp[IPerror]
4902 self.assertEqual(inner_ip[UDPerror].sport, 3001)
4903 self.assertEqual(inner_ip[UDPerror].dport, 3002)
4904
Matus Fabian2ba92e32017-08-21 07:05:03 -07004905 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07004906
4907 self.assertEqual(1000, dms[0].ses_num)
4908
Matus Fabian2f2db1c2017-04-18 05:29:59 -07004909 # verify IPFIX logging
4910 self.vapi.cli("ipfix flush") # FIXME this should be an API call
Matus Fabian7c0aecc2017-07-03 01:21:38 -07004911 sleep(1)
Matus Fabian2f2db1c2017-04-18 05:29:59 -07004912 capture = self.pg2.get_capture(2)
4913 ipfix = IPFIXDecoder()
4914 # first load template
4915 for p in capture:
4916 self.assertTrue(p.haslayer(IPFIX))
4917 if p.haslayer(Template):
4918 ipfix.add_template(p.getlayer(Template))
4919 # verify events in data set
4920 for p in capture:
4921 if p.haslayer(Data):
4922 data = ipfix.decode_data_set(p.getlayer(Set))
4923 self.verify_ipfix_max_entries_per_user(data)
4924
Matus Fabian2ba92e32017-08-21 07:05:03 -07004925 def clear_nat_det(self):
Martin17a75cb2017-03-08 05:53:20 -08004926 """
Matus Fabian2ba92e32017-08-21 07:05:03 -07004927 Clear deterministic NAT configuration.
Martin17a75cb2017-03-08 05:53:20 -08004928 """
Matus Fabian2ba92e32017-08-21 07:05:03 -07004929 self.vapi.nat_ipfix(enable=0)
4930 self.vapi.nat_det_set_timeouts()
4931 deterministic_mappings = self.vapi.nat_det_map_dump()
Martin17a75cb2017-03-08 05:53:20 -08004932 for dsm in deterministic_mappings:
Matus Fabian2ba92e32017-08-21 07:05:03 -07004933 self.vapi.nat_det_add_del_map(dsm.in_addr,
4934 dsm.in_plen,
4935 dsm.out_addr,
4936 dsm.out_plen,
4937 is_add=0)
Martin17a75cb2017-03-08 05:53:20 -08004938
Matus Fabian2ba92e32017-08-21 07:05:03 -07004939 interfaces = self.vapi.nat44_interface_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07004940 for intf in interfaces:
Matus Fabian2ba92e32017-08-21 07:05:03 -07004941 self.vapi.nat44_interface_add_del_feature(intf.sw_if_index,
4942 intf.is_inside,
4943 is_add=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07004944
Matus Fabian066f0342017-02-10 03:48:01 -08004945 def tearDown(self):
4946 super(TestDeterministicNAT, self).tearDown()
4947 if not self.vpp_dead:
Matus Fabian82119542018-01-25 01:13:22 -08004948 self.logger.info(self.vapi.cli("show nat44 interfaces"))
4949 self.logger.info(
4950 self.vapi.cli("show nat44 deterministic mappings"))
4951 self.logger.info(
4952 self.vapi.cli("show nat44 deterministic timeouts"))
4953 self.logger.info(
4954 self.vapi.cli("show nat44 deterministic sessions"))
Matus Fabian2ba92e32017-08-21 07:05:03 -07004955 self.clear_nat_det()
Matus Fabian066f0342017-02-10 03:48:01 -08004956
Matus Fabian06596c52017-06-06 04:53:28 -07004957
4958class TestNAT64(MethodHolder):
4959 """ NAT64 Test Cases """
4960
4961 @classmethod
Matus Fabiana431ad12018-01-04 04:03:14 -08004962 def setUpConstants(cls):
4963 super(TestNAT64, cls).setUpConstants()
4964 cls.vpp_cmdline.extend(["nat", "{", "nat64 bib hash buckets 128",
4965 "nat64 st hash buckets 256", "}"])
4966
4967 @classmethod
Matus Fabian06596c52017-06-06 04:53:28 -07004968 def setUpClass(cls):
4969 super(TestNAT64, cls).setUpClass()
4970
4971 try:
4972 cls.tcp_port_in = 6303
4973 cls.tcp_port_out = 6303
4974 cls.udp_port_in = 6304
4975 cls.udp_port_out = 6304
4976 cls.icmp_id_in = 6305
4977 cls.icmp_id_out = 6305
4978 cls.nat_addr = '10.0.0.3'
4979 cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
Matus Fabian029f3d22017-06-15 02:28:50 -07004980 cls.vrf1_id = 10
4981 cls.vrf1_nat_addr = '10.0.10.3'
4982 cls.vrf1_nat_addr_n = socket.inet_pton(socket.AF_INET,
4983 cls.vrf1_nat_addr)
Matus Fabiana431ad12018-01-04 04:03:14 -08004984 cls.ipfix_src_port = 4739
4985 cls.ipfix_domain_id = 1
Matus Fabian06596c52017-06-06 04:53:28 -07004986
Matus Fabian0938dcf2017-11-08 01:59:38 -08004987 cls.create_pg_interfaces(range(5))
Matus Fabian06596c52017-06-06 04:53:28 -07004988 cls.ip6_interfaces = list(cls.pg_interfaces[0:1])
Matus Fabian029f3d22017-06-15 02:28:50 -07004989 cls.ip6_interfaces.append(cls.pg_interfaces[2])
Matus Fabian06596c52017-06-06 04:53:28 -07004990 cls.ip4_interfaces = list(cls.pg_interfaces[1:2])
4991
Neale Ranns15002542017-09-10 04:39:11 -07004992 cls.vapi.ip_table_add_del(cls.vrf1_id, is_add=1, is_ipv6=1)
4993
Matus Fabian029f3d22017-06-15 02:28:50 -07004994 cls.pg_interfaces[2].set_table_ip6(cls.vrf1_id)
4995
4996 cls.pg0.generate_remote_hosts(2)
4997
Matus Fabian06596c52017-06-06 04:53:28 -07004998 for i in cls.ip6_interfaces:
4999 i.admin_up()
5000 i.config_ip6()
Matus Fabian029f3d22017-06-15 02:28:50 -07005001 i.configure_ipv6_neighbors()
Matus Fabian06596c52017-06-06 04:53:28 -07005002
5003 for i in cls.ip4_interfaces:
5004 i.admin_up()
5005 i.config_ip4()
5006 i.resolve_arp()
5007
Matus Fabian36ea2d62017-10-24 04:13:49 -07005008 cls.pg3.admin_up()
5009 cls.pg3.config_ip4()
5010 cls.pg3.resolve_arp()
5011 cls.pg3.config_ip6()
5012 cls.pg3.configure_ipv6_neighbors()
5013
Matus Fabian06596c52017-06-06 04:53:28 -07005014 except Exception:
5015 super(TestNAT64, cls).tearDownClass()
5016 raise
5017
5018 def test_pool(self):
5019 """ Add/delete address to NAT64 pool """
5020 nat_addr = socket.inet_pton(socket.AF_INET, '1.2.3.4')
5021
5022 self.vapi.nat64_add_del_pool_addr_range(nat_addr, nat_addr)
5023
5024 addresses = self.vapi.nat64_pool_addr_dump()
5025 self.assertEqual(len(addresses), 1)
5026 self.assertEqual(addresses[0].address, nat_addr)
5027
5028 self.vapi.nat64_add_del_pool_addr_range(nat_addr, nat_addr, is_add=0)
5029
5030 addresses = self.vapi.nat64_pool_addr_dump()
5031 self.assertEqual(len(addresses), 0)
5032
5033 def test_interface(self):
5034 """ Enable/disable NAT64 feature on the interface """
5035 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
5036 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
5037
5038 interfaces = self.vapi.nat64_interface_dump()
5039 self.assertEqual(len(interfaces), 2)
5040 pg0_found = False
5041 pg1_found = False
5042 for intf in interfaces:
5043 if intf.sw_if_index == self.pg0.sw_if_index:
5044 self.assertEqual(intf.is_inside, 1)
5045 pg0_found = True
5046 elif intf.sw_if_index == self.pg1.sw_if_index:
5047 self.assertEqual(intf.is_inside, 0)
5048 pg1_found = True
5049 self.assertTrue(pg0_found)
5050 self.assertTrue(pg1_found)
5051
5052 features = self.vapi.cli("show interface features pg0")
5053 self.assertNotEqual(features.find('nat64-in2out'), -1)
5054 features = self.vapi.cli("show interface features pg1")
5055 self.assertNotEqual(features.find('nat64-out2in'), -1)
5056
5057 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index, is_add=0)
5058 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_add=0)
5059
5060 interfaces = self.vapi.nat64_interface_dump()
5061 self.assertEqual(len(interfaces), 0)
5062
5063 def test_static_bib(self):
5064 """ Add/delete static BIB entry """
5065 in_addr = socket.inet_pton(socket.AF_INET6,
5066 '2001:db8:85a3::8a2e:370:7334')
5067 out_addr = socket.inet_pton(socket.AF_INET, '10.1.1.3')
5068 in_port = 1234
5069 out_port = 5678
5070 proto = IP_PROTOS.tcp
5071
5072 self.vapi.nat64_add_del_static_bib(in_addr,
5073 out_addr,
5074 in_port,
5075 out_port,
5076 proto)
5077 bib = self.vapi.nat64_bib_dump(IP_PROTOS.tcp)
5078 static_bib_num = 0
5079 for bibe in bib:
5080 if bibe.is_static:
5081 static_bib_num += 1
5082 self.assertEqual(bibe.i_addr, in_addr)
5083 self.assertEqual(bibe.o_addr, out_addr)
5084 self.assertEqual(bibe.i_port, in_port)
5085 self.assertEqual(bibe.o_port, out_port)
5086 self.assertEqual(static_bib_num, 1)
5087
5088 self.vapi.nat64_add_del_static_bib(in_addr,
5089 out_addr,
5090 in_port,
5091 out_port,
5092 proto,
5093 is_add=0)
5094 bib = self.vapi.nat64_bib_dump(IP_PROTOS.tcp)
5095 static_bib_num = 0
5096 for bibe in bib:
5097 if bibe.is_static:
5098 static_bib_num += 1
5099 self.assertEqual(static_bib_num, 0)
5100
5101 def test_set_timeouts(self):
5102 """ Set NAT64 timeouts """
5103 # verify default values
5104 timeouts = self.vapi.nat64_get_timeouts()
5105 self.assertEqual(timeouts.udp, 300)
5106 self.assertEqual(timeouts.icmp, 60)
5107 self.assertEqual(timeouts.tcp_trans, 240)
5108 self.assertEqual(timeouts.tcp_est, 7440)
5109 self.assertEqual(timeouts.tcp_incoming_syn, 6)
5110
5111 # set and verify custom values
5112 self.vapi.nat64_set_timeouts(udp=200, icmp=30, tcp_trans=250,
5113 tcp_est=7450, tcp_incoming_syn=10)
5114 timeouts = self.vapi.nat64_get_timeouts()
5115 self.assertEqual(timeouts.udp, 200)
5116 self.assertEqual(timeouts.icmp, 30)
5117 self.assertEqual(timeouts.tcp_trans, 250)
5118 self.assertEqual(timeouts.tcp_est, 7450)
5119 self.assertEqual(timeouts.tcp_incoming_syn, 10)
5120
5121 def test_dynamic(self):
5122 """ NAT64 dynamic translation test """
5123 self.tcp_port_in = 6303
5124 self.udp_port_in = 6304
5125 self.icmp_id_in = 6305
5126
5127 ses_num_start = self.nat64_get_ses_num()
5128
5129 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
5130 self.nat_addr_n)
5131 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
5132 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
5133
5134 # in2out
5135 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
5136 self.pg0.add_stream(pkts)
5137 self.pg_enable_capture(self.pg_interfaces)
5138 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07005139 capture = self.pg1.get_capture(len(pkts))
5140 self.verify_capture_out(capture, nat_ip=self.nat_addr,
Matus Fabian06596c52017-06-06 04:53:28 -07005141 dst_ip=self.pg1.remote_ip4)
5142
5143 # out2in
5144 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
5145 self.pg1.add_stream(pkts)
5146 self.pg_enable_capture(self.pg_interfaces)
5147 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07005148 capture = self.pg0.get_capture(len(pkts))
Matus Fabian06596c52017-06-06 04:53:28 -07005149 ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
5150 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
5151
5152 # in2out
5153 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
5154 self.pg0.add_stream(pkts)
5155 self.pg_enable_capture(self.pg_interfaces)
5156 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07005157 capture = self.pg1.get_capture(len(pkts))
5158 self.verify_capture_out(capture, nat_ip=self.nat_addr,
Matus Fabian06596c52017-06-06 04:53:28 -07005159 dst_ip=self.pg1.remote_ip4)
5160
5161 # out2in
5162 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
5163 self.pg1.add_stream(pkts)
5164 self.pg_enable_capture(self.pg_interfaces)
5165 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07005166 capture = self.pg0.get_capture(len(pkts))
Matus Fabian06596c52017-06-06 04:53:28 -07005167 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
5168
5169 ses_num_end = self.nat64_get_ses_num()
5170
5171 self.assertEqual(ses_num_end - ses_num_start, 3)
5172
Matus Fabian029f3d22017-06-15 02:28:50 -07005173 # tenant with specific VRF
5174 self.vapi.nat64_add_del_pool_addr_range(self.vrf1_nat_addr_n,
5175 self.vrf1_nat_addr_n,
5176 vrf_id=self.vrf1_id)
5177 self.vapi.nat64_add_del_interface(self.pg2.sw_if_index)
5178
5179 pkts = self.create_stream_in_ip6(self.pg2, self.pg1)
5180 self.pg2.add_stream(pkts)
5181 self.pg_enable_capture(self.pg_interfaces)
5182 self.pg_start()
5183 capture = self.pg1.get_capture(len(pkts))
5184 self.verify_capture_out(capture, nat_ip=self.vrf1_nat_addr,
5185 dst_ip=self.pg1.remote_ip4)
5186
5187 pkts = self.create_stream_out(self.pg1, dst_ip=self.vrf1_nat_addr)
5188 self.pg1.add_stream(pkts)
5189 self.pg_enable_capture(self.pg_interfaces)
5190 self.pg_start()
5191 capture = self.pg2.get_capture(len(pkts))
5192 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg2.remote_ip6)
5193
Matus Fabian06596c52017-06-06 04:53:28 -07005194 def test_static(self):
5195 """ NAT64 static translation test """
5196 self.tcp_port_in = 60303
5197 self.udp_port_in = 60304
5198 self.icmp_id_in = 60305
5199 self.tcp_port_out = 60303
5200 self.udp_port_out = 60304
5201 self.icmp_id_out = 60305
5202
5203 ses_num_start = self.nat64_get_ses_num()
5204
5205 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
5206 self.nat_addr_n)
5207 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
5208 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
5209
5210 self.vapi.nat64_add_del_static_bib(self.pg0.remote_ip6n,
5211 self.nat_addr_n,
5212 self.tcp_port_in,
5213 self.tcp_port_out,
5214 IP_PROTOS.tcp)
5215 self.vapi.nat64_add_del_static_bib(self.pg0.remote_ip6n,
5216 self.nat_addr_n,
5217 self.udp_port_in,
5218 self.udp_port_out,
5219 IP_PROTOS.udp)
5220 self.vapi.nat64_add_del_static_bib(self.pg0.remote_ip6n,
5221 self.nat_addr_n,
5222 self.icmp_id_in,
5223 self.icmp_id_out,
5224 IP_PROTOS.icmp)
5225
5226 # in2out
5227 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
5228 self.pg0.add_stream(pkts)
5229 self.pg_enable_capture(self.pg_interfaces)
5230 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07005231 capture = self.pg1.get_capture(len(pkts))
5232 self.verify_capture_out(capture, nat_ip=self.nat_addr,
Matus Fabian06596c52017-06-06 04:53:28 -07005233 dst_ip=self.pg1.remote_ip4, same_port=True)
5234
5235 # out2in
5236 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
5237 self.pg1.add_stream(pkts)
5238 self.pg_enable_capture(self.pg_interfaces)
5239 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07005240 capture = self.pg0.get_capture(len(pkts))
Matus Fabian06596c52017-06-06 04:53:28 -07005241 ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
5242 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
5243
5244 ses_num_end = self.nat64_get_ses_num()
5245
5246 self.assertEqual(ses_num_end - ses_num_start, 3)
5247
5248 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
5249 def test_session_timeout(self):
5250 """ NAT64 session timeout """
5251 self.icmp_id_in = 1234
5252 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
5253 self.nat_addr_n)
5254 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
5255 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
5256 self.vapi.nat64_set_timeouts(icmp=5)
5257
5258 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
5259 self.pg0.add_stream(pkts)
5260 self.pg_enable_capture(self.pg_interfaces)
5261 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07005262 capture = self.pg1.get_capture(len(pkts))
Matus Fabian06596c52017-06-06 04:53:28 -07005263
5264 ses_num_before_timeout = self.nat64_get_ses_num()
5265
5266 sleep(15)
5267
5268 # ICMP session after timeout
5269 ses_num_after_timeout = self.nat64_get_ses_num()
5270 self.assertNotEqual(ses_num_before_timeout, ses_num_after_timeout)
5271
Matus Fabian732036d2017-06-08 05:24:28 -07005272 def test_icmp_error(self):
5273 """ NAT64 ICMP Error message translation """
5274 self.tcp_port_in = 6303
5275 self.udp_port_in = 6304
5276 self.icmp_id_in = 6305
5277
Matus Fabian732036d2017-06-08 05:24:28 -07005278 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
5279 self.nat_addr_n)
5280 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
5281 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
5282
5283 # send some packets to create sessions
5284 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
5285 self.pg0.add_stream(pkts)
5286 self.pg_enable_capture(self.pg_interfaces)
5287 self.pg_start()
5288 capture_ip4 = self.pg1.get_capture(len(pkts))
Matus Fabian029f3d22017-06-15 02:28:50 -07005289 self.verify_capture_out(capture_ip4,
Matus Fabian732036d2017-06-08 05:24:28 -07005290 nat_ip=self.nat_addr,
5291 dst_ip=self.pg1.remote_ip4)
5292
5293 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
5294 self.pg1.add_stream(pkts)
5295 self.pg_enable_capture(self.pg_interfaces)
5296 self.pg_start()
5297 capture_ip6 = self.pg0.get_capture(len(pkts))
5298 ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
5299 self.verify_capture_in_ip6(capture_ip6, ip[IPv6].src,
5300 self.pg0.remote_ip6)
5301
5302 # in2out
5303 pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5304 IPv6(src=self.pg0.remote_ip6, dst=ip[IPv6].src) /
5305 ICMPv6DestUnreach(code=1) /
5306 packet[IPv6] for packet in capture_ip6]
5307 self.pg0.add_stream(pkts)
5308 self.pg_enable_capture(self.pg_interfaces)
5309 self.pg_start()
5310 capture = self.pg1.get_capture(len(pkts))
5311 for packet in capture:
5312 try:
5313 self.assertEqual(packet[IP].src, self.nat_addr)
5314 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
5315 self.assertEqual(packet[ICMP].type, 3)
5316 self.assertEqual(packet[ICMP].code, 13)
5317 inner = packet[IPerror]
5318 self.assertEqual(inner.src, self.pg1.remote_ip4)
5319 self.assertEqual(inner.dst, self.nat_addr)
Klement Sekerad81ae412018-05-16 10:52:54 +02005320 self.assert_packet_checksums_valid(packet)
Matus Fabian732036d2017-06-08 05:24:28 -07005321 if inner.haslayer(TCPerror):
5322 self.assertEqual(inner[TCPerror].dport, self.tcp_port_out)
5323 elif inner.haslayer(UDPerror):
5324 self.assertEqual(inner[UDPerror].dport, self.udp_port_out)
5325 else:
5326 self.assertEqual(inner[ICMPerror].id, self.icmp_id_out)
5327 except:
5328 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5329 raise
5330
5331 # out2in
5332 pkts = [Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
5333 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5334 ICMP(type=3, code=13) /
5335 packet[IP] for packet in capture_ip4]
5336 self.pg1.add_stream(pkts)
5337 self.pg_enable_capture(self.pg_interfaces)
5338 self.pg_start()
5339 capture = self.pg0.get_capture(len(pkts))
5340 for packet in capture:
5341 try:
5342 self.assertEqual(packet[IPv6].src, ip.src)
5343 self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
5344 icmp = packet[ICMPv6DestUnreach]
5345 self.assertEqual(icmp.code, 1)
5346 inner = icmp[IPerror6]
5347 self.assertEqual(inner.src, self.pg0.remote_ip6)
5348 self.assertEqual(inner.dst, ip.src)
Klement Sekerad81ae412018-05-16 10:52:54 +02005349 self.assert_icmpv6_checksum_valid(packet)
Matus Fabian732036d2017-06-08 05:24:28 -07005350 if inner.haslayer(TCPerror):
5351 self.assertEqual(inner[TCPerror].sport, self.tcp_port_in)
5352 elif inner.haslayer(UDPerror):
5353 self.assertEqual(inner[UDPerror].sport, self.udp_port_in)
5354 else:
5355 self.assertEqual(inner[ICMPv6EchoRequest].id,
5356 self.icmp_id_in)
5357 except:
5358 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5359 raise
5360
Matus Fabian029f3d22017-06-15 02:28:50 -07005361 def test_hairpinning(self):
5362 """ NAT64 hairpinning """
5363
5364 client = self.pg0.remote_hosts[0]
5365 server = self.pg0.remote_hosts[1]
5366 server_tcp_in_port = 22
5367 server_tcp_out_port = 4022
5368 server_udp_in_port = 23
5369 server_udp_out_port = 4023
5370 client_tcp_in_port = 1234
5371 client_udp_in_port = 1235
5372 client_tcp_out_port = 0
5373 client_udp_out_port = 0
5374 ip = IPv6(src=''.join(['64:ff9b::', self.nat_addr]))
5375 nat_addr_ip6 = ip.src
5376
5377 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
5378 self.nat_addr_n)
5379 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
5380 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
5381
5382 self.vapi.nat64_add_del_static_bib(server.ip6n,
5383 self.nat_addr_n,
5384 server_tcp_in_port,
5385 server_tcp_out_port,
5386 IP_PROTOS.tcp)
5387 self.vapi.nat64_add_del_static_bib(server.ip6n,
5388 self.nat_addr_n,
5389 server_udp_in_port,
5390 server_udp_out_port,
5391 IP_PROTOS.udp)
5392
5393 # client to server
5394 pkts = []
5395 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5396 IPv6(src=client.ip6, dst=nat_addr_ip6) /
5397 TCP(sport=client_tcp_in_port, dport=server_tcp_out_port))
5398 pkts.append(p)
5399 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5400 IPv6(src=client.ip6, dst=nat_addr_ip6) /
5401 UDP(sport=client_udp_in_port, dport=server_udp_out_port))
5402 pkts.append(p)
5403 self.pg0.add_stream(pkts)
5404 self.pg_enable_capture(self.pg_interfaces)
5405 self.pg_start()
5406 capture = self.pg0.get_capture(len(pkts))
5407 for packet in capture:
5408 try:
5409 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
5410 self.assertEqual(packet[IPv6].dst, server.ip6)
Klement Sekerad81ae412018-05-16 10:52:54 +02005411 self.assert_packet_checksums_valid(packet)
Matus Fabian029f3d22017-06-15 02:28:50 -07005412 if packet.haslayer(TCP):
5413 self.assertNotEqual(packet[TCP].sport, client_tcp_in_port)
5414 self.assertEqual(packet[TCP].dport, server_tcp_in_port)
Matus Fabian029f3d22017-06-15 02:28:50 -07005415 client_tcp_out_port = packet[TCP].sport
5416 else:
5417 self.assertNotEqual(packet[UDP].sport, client_udp_in_port)
5418 self.assertEqual(packet[UDP].dport, server_udp_in_port)
Matus Fabian029f3d22017-06-15 02:28:50 -07005419 client_udp_out_port = packet[UDP].sport
5420 except:
5421 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5422 raise
5423
5424 # server to client
5425 pkts = []
5426 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5427 IPv6(src=server.ip6, dst=nat_addr_ip6) /
5428 TCP(sport=server_tcp_in_port, dport=client_tcp_out_port))
5429 pkts.append(p)
5430 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5431 IPv6(src=server.ip6, dst=nat_addr_ip6) /
5432 UDP(sport=server_udp_in_port, dport=client_udp_out_port))
5433 pkts.append(p)
5434 self.pg0.add_stream(pkts)
5435 self.pg_enable_capture(self.pg_interfaces)
5436 self.pg_start()
5437 capture = self.pg0.get_capture(len(pkts))
5438 for packet in capture:
5439 try:
5440 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
5441 self.assertEqual(packet[IPv6].dst, client.ip6)
Klement Sekerad81ae412018-05-16 10:52:54 +02005442 self.assert_packet_checksums_valid(packet)
Matus Fabian029f3d22017-06-15 02:28:50 -07005443 if packet.haslayer(TCP):
5444 self.assertEqual(packet[TCP].sport, server_tcp_out_port)
5445 self.assertEqual(packet[TCP].dport, client_tcp_in_port)
Matus Fabian029f3d22017-06-15 02:28:50 -07005446 else:
5447 self.assertEqual(packet[UDP].sport, server_udp_out_port)
5448 self.assertEqual(packet[UDP].dport, client_udp_in_port)
Matus Fabian029f3d22017-06-15 02:28:50 -07005449 except:
5450 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5451 raise
5452
5453 # ICMP error
5454 pkts = []
5455 pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5456 IPv6(src=client.ip6, dst=nat_addr_ip6) /
5457 ICMPv6DestUnreach(code=1) /
5458 packet[IPv6] for packet in capture]
5459 self.pg0.add_stream(pkts)
5460 self.pg_enable_capture(self.pg_interfaces)
5461 self.pg_start()
5462 capture = self.pg0.get_capture(len(pkts))
5463 for packet in capture:
5464 try:
5465 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
5466 self.assertEqual(packet[IPv6].dst, server.ip6)
5467 icmp = packet[ICMPv6DestUnreach]
5468 self.assertEqual(icmp.code, 1)
5469 inner = icmp[IPerror6]
5470 self.assertEqual(inner.src, server.ip6)
5471 self.assertEqual(inner.dst, nat_addr_ip6)
Klement Sekerad81ae412018-05-16 10:52:54 +02005472 self.assert_packet_checksums_valid(packet)
Matus Fabian029f3d22017-06-15 02:28:50 -07005473 if inner.haslayer(TCPerror):
5474 self.assertEqual(inner[TCPerror].sport, server_tcp_in_port)
5475 self.assertEqual(inner[TCPerror].dport,
5476 client_tcp_out_port)
5477 else:
5478 self.assertEqual(inner[UDPerror].sport, server_udp_in_port)
5479 self.assertEqual(inner[UDPerror].dport,
5480 client_udp_out_port)
5481 except:
5482 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5483 raise
5484
Matus Fabian428dc912017-06-21 06:15:18 -07005485 def test_prefix(self):
5486 """ NAT64 Network-Specific Prefix """
5487
5488 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
5489 self.nat_addr_n)
5490 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
5491 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
5492 self.vapi.nat64_add_del_pool_addr_range(self.vrf1_nat_addr_n,
5493 self.vrf1_nat_addr_n,
5494 vrf_id=self.vrf1_id)
5495 self.vapi.nat64_add_del_interface(self.pg2.sw_if_index)
5496
5497 # Add global prefix
5498 global_pref64 = "2001:db8::"
5499 global_pref64_n = socket.inet_pton(socket.AF_INET6, global_pref64)
5500 global_pref64_len = 32
5501 self.vapi.nat64_add_del_prefix(global_pref64_n, global_pref64_len)
5502
5503 prefix = self.vapi.nat64_prefix_dump()
5504 self.assertEqual(len(prefix), 1)
5505 self.assertEqual(prefix[0].prefix, global_pref64_n)
5506 self.assertEqual(prefix[0].prefix_len, global_pref64_len)
5507 self.assertEqual(prefix[0].vrf_id, 0)
5508
5509 # Add tenant specific prefix
5510 vrf1_pref64 = "2001:db8:122:300::"
5511 vrf1_pref64_n = socket.inet_pton(socket.AF_INET6, vrf1_pref64)
5512 vrf1_pref64_len = 56
5513 self.vapi.nat64_add_del_prefix(vrf1_pref64_n,
5514 vrf1_pref64_len,
5515 vrf_id=self.vrf1_id)
5516 prefix = self.vapi.nat64_prefix_dump()
5517 self.assertEqual(len(prefix), 2)
5518
5519 # Global prefix
5520 pkts = self.create_stream_in_ip6(self.pg0,
5521 self.pg1,
5522 pref=global_pref64,
5523 plen=global_pref64_len)
5524 self.pg0.add_stream(pkts)
5525 self.pg_enable_capture(self.pg_interfaces)
5526 self.pg_start()
5527 capture = self.pg1.get_capture(len(pkts))
5528 self.verify_capture_out(capture, nat_ip=self.nat_addr,
5529 dst_ip=self.pg1.remote_ip4)
5530
5531 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
5532 self.pg1.add_stream(pkts)
5533 self.pg_enable_capture(self.pg_interfaces)
5534 self.pg_start()
5535 capture = self.pg0.get_capture(len(pkts))
5536 dst_ip = self.compose_ip6(self.pg1.remote_ip4,
5537 global_pref64,
5538 global_pref64_len)
5539 self.verify_capture_in_ip6(capture, dst_ip, self.pg0.remote_ip6)
5540
5541 # Tenant specific prefix
5542 pkts = self.create_stream_in_ip6(self.pg2,
5543 self.pg1,
5544 pref=vrf1_pref64,
5545 plen=vrf1_pref64_len)
5546 self.pg2.add_stream(pkts)
5547 self.pg_enable_capture(self.pg_interfaces)
5548 self.pg_start()
5549 capture = self.pg1.get_capture(len(pkts))
5550 self.verify_capture_out(capture, nat_ip=self.vrf1_nat_addr,
5551 dst_ip=self.pg1.remote_ip4)
5552
5553 pkts = self.create_stream_out(self.pg1, dst_ip=self.vrf1_nat_addr)
5554 self.pg1.add_stream(pkts)
5555 self.pg_enable_capture(self.pg_interfaces)
5556 self.pg_start()
5557 capture = self.pg2.get_capture(len(pkts))
5558 dst_ip = self.compose_ip6(self.pg1.remote_ip4,
5559 vrf1_pref64,
5560 vrf1_pref64_len)
5561 self.verify_capture_in_ip6(capture, dst_ip, self.pg2.remote_ip6)
5562
Matus Fabianf8cd5812017-07-11 03:55:02 -07005563 def test_unknown_proto(self):
Matus Fabian7968e6c2017-07-06 05:37:49 -07005564 """ NAT64 translate packet with unknown protocol """
5565
5566 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
5567 self.nat_addr_n)
5568 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
5569 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
5570 remote_ip6 = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
5571
5572 # in2out
5573 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5574 IPv6(src=self.pg0.remote_ip6, dst=remote_ip6) /
5575 TCP(sport=self.tcp_port_in, dport=20))
5576 self.pg0.add_stream(p)
5577 self.pg_enable_capture(self.pg_interfaces)
5578 self.pg_start()
5579 p = self.pg1.get_capture(1)
5580
5581 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabianf8cd5812017-07-11 03:55:02 -07005582 IPv6(src=self.pg0.remote_ip6, dst=remote_ip6, nh=47) /
Matus Fabian7968e6c2017-07-06 05:37:49 -07005583 GRE() /
5584 IP(src=self.pg2.local_ip4, dst=self.pg2.remote_ip4) /
5585 TCP(sport=1234, dport=1234))
5586 self.pg0.add_stream(p)
5587 self.pg_enable_capture(self.pg_interfaces)
5588 self.pg_start()
5589 p = self.pg1.get_capture(1)
5590 packet = p[0]
5591 try:
5592 self.assertEqual(packet[IP].src, self.nat_addr)
5593 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
5594 self.assertTrue(packet.haslayer(GRE))
Klement Sekerad81ae412018-05-16 10:52:54 +02005595 self.assert_packet_checksums_valid(packet)
Matus Fabian7968e6c2017-07-06 05:37:49 -07005596 except:
5597 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5598 raise
5599
5600 # out2in
5601 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
5602 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5603 GRE() /
5604 IP(src=self.pg2.remote_ip4, dst=self.pg2.local_ip4) /
5605 TCP(sport=1234, dport=1234))
5606 self.pg1.add_stream(p)
5607 self.pg_enable_capture(self.pg_interfaces)
5608 self.pg_start()
5609 p = self.pg0.get_capture(1)
5610 packet = p[0]
5611 try:
5612 self.assertEqual(packet[IPv6].src, remote_ip6)
Matus Fabianf8cd5812017-07-11 03:55:02 -07005613 self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
5614 self.assertEqual(packet[IPv6].nh, 47)
Matus Fabian7968e6c2017-07-06 05:37:49 -07005615 except:
5616 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5617 raise
5618
Matus Fabianf8cd5812017-07-11 03:55:02 -07005619 def test_hairpinning_unknown_proto(self):
Matus Fabian7968e6c2017-07-06 05:37:49 -07005620 """ NAT64 translate packet with unknown protocol - hairpinning """
5621
5622 client = self.pg0.remote_hosts[0]
5623 server = self.pg0.remote_hosts[1]
5624 server_tcp_in_port = 22
5625 server_tcp_out_port = 4022
5626 client_tcp_in_port = 1234
Matus Fabianf8cd5812017-07-11 03:55:02 -07005627 client_tcp_out_port = 1235
5628 server_nat_ip = "10.0.0.100"
5629 client_nat_ip = "10.0.0.110"
5630 server_nat_ip_n = socket.inet_pton(socket.AF_INET, server_nat_ip)
5631 client_nat_ip_n = socket.inet_pton(socket.AF_INET, client_nat_ip)
5632 server_nat_ip6 = self.compose_ip6(server_nat_ip, '64:ff9b::', 96)
5633 client_nat_ip6 = self.compose_ip6(client_nat_ip, '64:ff9b::', 96)
Matus Fabian7968e6c2017-07-06 05:37:49 -07005634
Matus Fabianf8cd5812017-07-11 03:55:02 -07005635 self.vapi.nat64_add_del_pool_addr_range(server_nat_ip_n,
5636 client_nat_ip_n)
Matus Fabian7968e6c2017-07-06 05:37:49 -07005637 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
5638 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
5639
5640 self.vapi.nat64_add_del_static_bib(server.ip6n,
Matus Fabianf8cd5812017-07-11 03:55:02 -07005641 server_nat_ip_n,
Matus Fabian7968e6c2017-07-06 05:37:49 -07005642 server_tcp_in_port,
5643 server_tcp_out_port,
5644 IP_PROTOS.tcp)
5645
Matus Fabianf8cd5812017-07-11 03:55:02 -07005646 self.vapi.nat64_add_del_static_bib(server.ip6n,
5647 server_nat_ip_n,
5648 0,
5649 0,
5650 IP_PROTOS.gre)
5651
5652 self.vapi.nat64_add_del_static_bib(client.ip6n,
5653 client_nat_ip_n,
5654 client_tcp_in_port,
5655 client_tcp_out_port,
5656 IP_PROTOS.tcp)
5657
Matus Fabian7968e6c2017-07-06 05:37:49 -07005658 # client to server
5659 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabianf8cd5812017-07-11 03:55:02 -07005660 IPv6(src=client.ip6, dst=server_nat_ip6) /
Matus Fabian7968e6c2017-07-06 05:37:49 -07005661 TCP(sport=client_tcp_in_port, dport=server_tcp_out_port))
5662 self.pg0.add_stream(p)
5663 self.pg_enable_capture(self.pg_interfaces)
5664 self.pg_start()
5665 p = self.pg0.get_capture(1)
5666
5667 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabianf8cd5812017-07-11 03:55:02 -07005668 IPv6(src=client.ip6, dst=server_nat_ip6, nh=IP_PROTOS.gre) /
Matus Fabian7968e6c2017-07-06 05:37:49 -07005669 GRE() /
5670 IP(src=self.pg2.local_ip4, dst=self.pg2.remote_ip4) /
5671 TCP(sport=1234, dport=1234))
5672 self.pg0.add_stream(p)
5673 self.pg_enable_capture(self.pg_interfaces)
5674 self.pg_start()
5675 p = self.pg0.get_capture(1)
5676 packet = p[0]
5677 try:
Matus Fabianf8cd5812017-07-11 03:55:02 -07005678 self.assertEqual(packet[IPv6].src, client_nat_ip6)
Matus Fabian7968e6c2017-07-06 05:37:49 -07005679 self.assertEqual(packet[IPv6].dst, server.ip6)
Matus Fabianf8cd5812017-07-11 03:55:02 -07005680 self.assertEqual(packet[IPv6].nh, IP_PROTOS.gre)
Matus Fabian7968e6c2017-07-06 05:37:49 -07005681 except:
5682 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5683 raise
5684
5685 # server to client
5686 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabianf8cd5812017-07-11 03:55:02 -07005687 IPv6(src=server.ip6, dst=client_nat_ip6, nh=IP_PROTOS.gre) /
Matus Fabian7968e6c2017-07-06 05:37:49 -07005688 GRE() /
5689 IP(src=self.pg2.remote_ip4, dst=self.pg2.local_ip4) /
5690 TCP(sport=1234, dport=1234))
5691 self.pg0.add_stream(p)
5692 self.pg_enable_capture(self.pg_interfaces)
5693 self.pg_start()
5694 p = self.pg0.get_capture(1)
5695 packet = p[0]
5696 try:
Matus Fabianf8cd5812017-07-11 03:55:02 -07005697 self.assertEqual(packet[IPv6].src, server_nat_ip6)
Matus Fabian7968e6c2017-07-06 05:37:49 -07005698 self.assertEqual(packet[IPv6].dst, client.ip6)
Matus Fabianf8cd5812017-07-11 03:55:02 -07005699 self.assertEqual(packet[IPv6].nh, IP_PROTOS.gre)
Matus Fabian7968e6c2017-07-06 05:37:49 -07005700 except:
5701 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5702 raise
5703
Matus Fabian36ea2d62017-10-24 04:13:49 -07005704 def test_one_armed_nat64(self):
5705 """ One armed NAT64 """
5706 external_port = 0
5707 remote_host_ip6 = self.compose_ip6(self.pg3.remote_ip4,
5708 '64:ff9b::',
5709 96)
5710
5711 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
5712 self.nat_addr_n)
5713 self.vapi.nat64_add_del_interface(self.pg3.sw_if_index)
5714 self.vapi.nat64_add_del_interface(self.pg3.sw_if_index, is_inside=0)
5715
5716 # in2out
5717 p = (Ether(src=self.pg3.remote_mac, dst=self.pg3.local_mac) /
5718 IPv6(src=self.pg3.remote_ip6, dst=remote_host_ip6) /
5719 TCP(sport=12345, dport=80))
5720 self.pg3.add_stream(p)
5721 self.pg_enable_capture(self.pg_interfaces)
5722 self.pg_start()
5723 capture = self.pg3.get_capture(1)
5724 p = capture[0]
5725 try:
5726 ip = p[IP]
5727 tcp = p[TCP]
5728 self.assertEqual(ip.src, self.nat_addr)
5729 self.assertEqual(ip.dst, self.pg3.remote_ip4)
5730 self.assertNotEqual(tcp.sport, 12345)
5731 external_port = tcp.sport
5732 self.assertEqual(tcp.dport, 80)
Klement Sekerad81ae412018-05-16 10:52:54 +02005733 self.assert_packet_checksums_valid(p)
Matus Fabian36ea2d62017-10-24 04:13:49 -07005734 except:
5735 self.logger.error(ppp("Unexpected or invalid packet:", p))
5736 raise
5737
5738 # out2in
5739 p = (Ether(src=self.pg3.remote_mac, dst=self.pg3.local_mac) /
5740 IP(src=self.pg3.remote_ip4, dst=self.nat_addr) /
5741 TCP(sport=80, dport=external_port))
5742 self.pg3.add_stream(p)
5743 self.pg_enable_capture(self.pg_interfaces)
5744 self.pg_start()
5745 capture = self.pg3.get_capture(1)
5746 p = capture[0]
5747 try:
5748 ip = p[IPv6]
5749 tcp = p[TCP]
5750 self.assertEqual(ip.src, remote_host_ip6)
5751 self.assertEqual(ip.dst, self.pg3.remote_ip6)
5752 self.assertEqual(tcp.sport, 80)
5753 self.assertEqual(tcp.dport, 12345)
Klement Sekerad81ae412018-05-16 10:52:54 +02005754 self.assert_packet_checksums_valid(p)
Matus Fabian36ea2d62017-10-24 04:13:49 -07005755 except:
5756 self.logger.error(ppp("Unexpected or invalid packet:", p))
5757 raise
5758
Matus Fabianefcd1e92017-08-15 06:59:19 -07005759 def test_frag_in_order(self):
5760 """ NAT64 translate fragments arriving in order """
5761 self.tcp_port_in = random.randint(1025, 65535)
5762
5763 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
5764 self.nat_addr_n)
5765 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
5766 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
5767
5768 reass = self.vapi.nat_reass_dump()
5769 reass_n_start = len(reass)
5770
5771 # in2out
5772 data = 'a' * 200
5773 pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
5774 self.tcp_port_in, 20, data)
5775 self.pg0.add_stream(pkts)
5776 self.pg_enable_capture(self.pg_interfaces)
5777 self.pg_start()
5778 frags = self.pg1.get_capture(len(pkts))
5779 p = self.reass_frags_and_verify(frags,
5780 self.nat_addr,
5781 self.pg1.remote_ip4)
5782 self.assertEqual(p[TCP].dport, 20)
5783 self.assertNotEqual(p[TCP].sport, self.tcp_port_in)
5784 self.tcp_port_out = p[TCP].sport
5785 self.assertEqual(data, p[Raw].load)
5786
5787 # out2in
5788 data = "A" * 4 + "b" * 16 + "C" * 3
5789 pkts = self.create_stream_frag(self.pg1,
5790 self.nat_addr,
5791 20,
5792 self.tcp_port_out,
5793 data)
5794 self.pg1.add_stream(pkts)
5795 self.pg_enable_capture(self.pg_interfaces)
5796 self.pg_start()
5797 frags = self.pg0.get_capture(len(pkts))
5798 src = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
5799 p = self.reass_frags_and_verify_ip6(frags, src, self.pg0.remote_ip6)
5800 self.assertEqual(p[TCP].sport, 20)
5801 self.assertEqual(p[TCP].dport, self.tcp_port_in)
5802 self.assertEqual(data, p[Raw].load)
5803
5804 reass = self.vapi.nat_reass_dump()
5805 reass_n_end = len(reass)
5806
5807 self.assertEqual(reass_n_end - reass_n_start, 2)
5808
5809 def test_reass_hairpinning(self):
5810 """ NAT64 fragments hairpinning """
5811 data = 'a' * 200
Matus Fabianefcd1e92017-08-15 06:59:19 -07005812 server = self.pg0.remote_hosts[1]
5813 server_in_port = random.randint(1025, 65535)
5814 server_out_port = random.randint(1025, 65535)
5815 client_in_port = random.randint(1025, 65535)
5816 ip = IPv6(src=''.join(['64:ff9b::', self.nat_addr]))
5817 nat_addr_ip6 = ip.src
5818
5819 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
5820 self.nat_addr_n)
5821 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
5822 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
5823
5824 # add static BIB entry for server
5825 self.vapi.nat64_add_del_static_bib(server.ip6n,
5826 self.nat_addr_n,
5827 server_in_port,
5828 server_out_port,
5829 IP_PROTOS.tcp)
5830
5831 # send packet from host to server
5832 pkts = self.create_stream_frag_ip6(self.pg0,
5833 self.nat_addr,
5834 client_in_port,
5835 server_out_port,
5836 data)
5837 self.pg0.add_stream(pkts)
5838 self.pg_enable_capture(self.pg_interfaces)
5839 self.pg_start()
5840 frags = self.pg0.get_capture(len(pkts))
5841 p = self.reass_frags_and_verify_ip6(frags, nat_addr_ip6, server.ip6)
5842 self.assertNotEqual(p[TCP].sport, client_in_port)
5843 self.assertEqual(p[TCP].dport, server_in_port)
5844 self.assertEqual(data, p[Raw].load)
5845
5846 def test_frag_out_of_order(self):
5847 """ NAT64 translate fragments arriving out of order """
5848 self.tcp_port_in = random.randint(1025, 65535)
5849
5850 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
5851 self.nat_addr_n)
5852 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
5853 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
5854
5855 # in2out
5856 data = 'a' * 200
5857 pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
5858 self.tcp_port_in, 20, data)
5859 pkts.reverse()
5860 self.pg0.add_stream(pkts)
5861 self.pg_enable_capture(self.pg_interfaces)
5862 self.pg_start()
5863 frags = self.pg1.get_capture(len(pkts))
5864 p = self.reass_frags_and_verify(frags,
5865 self.nat_addr,
5866 self.pg1.remote_ip4)
5867 self.assertEqual(p[TCP].dport, 20)
5868 self.assertNotEqual(p[TCP].sport, self.tcp_port_in)
5869 self.tcp_port_out = p[TCP].sport
5870 self.assertEqual(data, p[Raw].load)
5871
5872 # out2in
5873 data = "A" * 4 + "B" * 16 + "C" * 3
5874 pkts = self.create_stream_frag(self.pg1,
5875 self.nat_addr,
5876 20,
5877 self.tcp_port_out,
5878 data)
5879 pkts.reverse()
5880 self.pg1.add_stream(pkts)
5881 self.pg_enable_capture(self.pg_interfaces)
5882 self.pg_start()
5883 frags = self.pg0.get_capture(len(pkts))
5884 src = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
5885 p = self.reass_frags_and_verify_ip6(frags, src, self.pg0.remote_ip6)
5886 self.assertEqual(p[TCP].sport, 20)
5887 self.assertEqual(p[TCP].dport, self.tcp_port_in)
5888 self.assertEqual(data, p[Raw].load)
5889
Matus Fabian0938dcf2017-11-08 01:59:38 -08005890 def test_interface_addr(self):
5891 """ Acquire NAT64 pool addresses from interface """
5892 self.vapi.nat64_add_interface_addr(self.pg4.sw_if_index)
5893
5894 # no address in NAT64 pool
5895 adresses = self.vapi.nat44_address_dump()
5896 self.assertEqual(0, len(adresses))
5897
5898 # configure interface address and check NAT64 address pool
5899 self.pg4.config_ip4()
5900 addresses = self.vapi.nat64_pool_addr_dump()
5901 self.assertEqual(len(addresses), 1)
5902 self.assertEqual(addresses[0].address, self.pg4.local_ip4n)
5903
5904 # remove interface address and check NAT64 address pool
5905 self.pg4.unconfig_ip4()
5906 addresses = self.vapi.nat64_pool_addr_dump()
5907 self.assertEqual(0, len(adresses))
5908
Matus Fabiana431ad12018-01-04 04:03:14 -08005909 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
5910 def test_ipfix_max_bibs_sessions(self):
5911 """ IPFIX logging maximum session and BIB entries exceeded """
5912 max_bibs = 1280
5913 max_sessions = 2560
5914 remote_host_ip6 = self.compose_ip6(self.pg1.remote_ip4,
5915 '64:ff9b::',
5916 96)
5917
5918 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
5919 self.nat_addr_n)
5920 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
5921 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
5922
5923 pkts = []
5924 src = ""
5925 for i in range(0, max_bibs):
5926 src = "fd01:aa::%x" % (i)
5927 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5928 IPv6(src=src, dst=remote_host_ip6) /
5929 TCP(sport=12345, dport=80))
5930 pkts.append(p)
5931 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5932 IPv6(src=src, dst=remote_host_ip6) /
5933 TCP(sport=12345, dport=22))
5934 pkts.append(p)
5935 self.pg0.add_stream(pkts)
5936 self.pg_enable_capture(self.pg_interfaces)
5937 self.pg_start()
5938 self.pg1.get_capture(max_sessions)
5939
5940 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
5941 src_address=self.pg3.local_ip4n,
5942 path_mtu=512,
5943 template_interval=10)
5944 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
5945 src_port=self.ipfix_src_port)
5946
5947 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5948 IPv6(src=src, dst=remote_host_ip6) /
5949 TCP(sport=12345, dport=25))
5950 self.pg0.add_stream(p)
5951 self.pg_enable_capture(self.pg_interfaces)
5952 self.pg_start()
5953 self.pg1.get_capture(0)
5954 self.vapi.cli("ipfix flush") # FIXME this should be an API call
5955 capture = self.pg3.get_capture(9)
5956 ipfix = IPFIXDecoder()
5957 # first load template
5958 for p in capture:
5959 self.assertTrue(p.haslayer(IPFIX))
5960 self.assertEqual(p[IP].src, self.pg3.local_ip4)
5961 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
5962 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
5963 self.assertEqual(p[UDP].dport, 4739)
5964 self.assertEqual(p[IPFIX].observationDomainID,
5965 self.ipfix_domain_id)
5966 if p.haslayer(Template):
5967 ipfix.add_template(p.getlayer(Template))
5968 # verify events in data set
5969 for p in capture:
5970 if p.haslayer(Data):
5971 data = ipfix.decode_data_set(p.getlayer(Set))
5972 self.verify_ipfix_max_sessions(data, max_sessions)
5973
5974 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5975 IPv6(src=self.pg0.remote_ip6, dst=remote_host_ip6) /
5976 TCP(sport=12345, dport=80))
5977 self.pg0.add_stream(p)
5978 self.pg_enable_capture(self.pg_interfaces)
5979 self.pg_start()
5980 self.pg1.get_capture(0)
5981 self.vapi.cli("ipfix flush") # FIXME this should be an API call
5982 capture = self.pg3.get_capture(1)
5983 # verify events in data set
5984 for p in capture:
5985 self.assertTrue(p.haslayer(IPFIX))
5986 self.assertEqual(p[IP].src, self.pg3.local_ip4)
5987 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
5988 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
5989 self.assertEqual(p[UDP].dport, 4739)
5990 self.assertEqual(p[IPFIX].observationDomainID,
5991 self.ipfix_domain_id)
5992 if p.haslayer(Data):
5993 data = ipfix.decode_data_set(p.getlayer(Set))
5994 self.verify_ipfix_max_bibs(data, max_bibs)
5995
5996 def test_ipfix_max_frags(self):
5997 """ IPFIX logging maximum fragments pending reassembly exceeded """
5998 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
5999 self.nat_addr_n)
6000 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6001 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6002 self.vapi.nat_set_reass(max_frag=0, is_ip6=1)
6003 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
6004 src_address=self.pg3.local_ip4n,
6005 path_mtu=512,
6006 template_interval=10)
6007 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
6008 src_port=self.ipfix_src_port)
6009
6010 data = 'a' * 200
6011 pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
6012 self.tcp_port_in, 20, data)
6013 self.pg0.add_stream(pkts[-1])
6014 self.pg_enable_capture(self.pg_interfaces)
6015 self.pg_start()
6016 self.pg1.get_capture(0)
6017 self.vapi.cli("ipfix flush") # FIXME this should be an API call
6018 capture = self.pg3.get_capture(9)
6019 ipfix = IPFIXDecoder()
6020 # first load template
6021 for p in capture:
6022 self.assertTrue(p.haslayer(IPFIX))
6023 self.assertEqual(p[IP].src, self.pg3.local_ip4)
6024 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
6025 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
6026 self.assertEqual(p[UDP].dport, 4739)
6027 self.assertEqual(p[IPFIX].observationDomainID,
6028 self.ipfix_domain_id)
6029 if p.haslayer(Template):
6030 ipfix.add_template(p.getlayer(Template))
6031 # verify events in data set
6032 for p in capture:
6033 if p.haslayer(Data):
6034 data = ipfix.decode_data_set(p.getlayer(Set))
6035 self.verify_ipfix_max_fragments_ip6(data, 0,
6036 self.pg0.remote_ip6n)
6037
6038 def test_ipfix_bib_ses(self):
6039 """ IPFIX logging NAT64 BIB/session create and delete events """
6040 self.tcp_port_in = random.randint(1025, 65535)
6041 remote_host_ip6 = self.compose_ip6(self.pg1.remote_ip4,
6042 '64:ff9b::',
6043 96)
6044
6045 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6046 self.nat_addr_n)
6047 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6048 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6049 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
6050 src_address=self.pg3.local_ip4n,
6051 path_mtu=512,
6052 template_interval=10)
6053 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
6054 src_port=self.ipfix_src_port)
6055
6056 # Create
6057 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6058 IPv6(src=self.pg0.remote_ip6, dst=remote_host_ip6) /
6059 TCP(sport=self.tcp_port_in, dport=25))
6060 self.pg0.add_stream(p)
6061 self.pg_enable_capture(self.pg_interfaces)
6062 self.pg_start()
6063 p = self.pg1.get_capture(1)
6064 self.tcp_port_out = p[0][TCP].sport
6065 self.vapi.cli("ipfix flush") # FIXME this should be an API call
6066 capture = self.pg3.get_capture(10)
6067 ipfix = IPFIXDecoder()
6068 # first load template
6069 for p in capture:
6070 self.assertTrue(p.haslayer(IPFIX))
6071 self.assertEqual(p[IP].src, self.pg3.local_ip4)
6072 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
6073 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
6074 self.assertEqual(p[UDP].dport, 4739)
6075 self.assertEqual(p[IPFIX].observationDomainID,
6076 self.ipfix_domain_id)
6077 if p.haslayer(Template):
6078 ipfix.add_template(p.getlayer(Template))
6079 # verify events in data set
6080 for p in capture:
6081 if p.haslayer(Data):
6082 data = ipfix.decode_data_set(p.getlayer(Set))
6083 if ord(data[0][230]) == 10:
6084 self.verify_ipfix_bib(data, 1, self.pg0.remote_ip6n)
6085 elif ord(data[0][230]) == 6:
6086 self.verify_ipfix_nat64_ses(data,
6087 1,
6088 self.pg0.remote_ip6n,
6089 self.pg1.remote_ip4,
6090 25)
6091 else:
6092 self.logger.error(ppp("Unexpected or invalid packet: ", p))
6093
6094 # Delete
6095 self.pg_enable_capture(self.pg_interfaces)
6096 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6097 self.nat_addr_n,
6098 is_add=0)
6099 self.vapi.cli("ipfix flush") # FIXME this should be an API call
6100 capture = self.pg3.get_capture(2)
6101 # verify events in data set
6102 for p in capture:
6103 self.assertTrue(p.haslayer(IPFIX))
6104 self.assertEqual(p[IP].src, self.pg3.local_ip4)
6105 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
6106 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
6107 self.assertEqual(p[UDP].dport, 4739)
6108 self.assertEqual(p[IPFIX].observationDomainID,
6109 self.ipfix_domain_id)
6110 if p.haslayer(Data):
6111 data = ipfix.decode_data_set(p.getlayer(Set))
6112 if ord(data[0][230]) == 11:
6113 self.verify_ipfix_bib(data, 0, self.pg0.remote_ip6n)
6114 elif ord(data[0][230]) == 7:
6115 self.verify_ipfix_nat64_ses(data,
6116 0,
6117 self.pg0.remote_ip6n,
6118 self.pg1.remote_ip4,
6119 25)
6120 else:
6121 self.logger.error(ppp("Unexpected or invalid packet: ", p))
6122
Matus Fabian06596c52017-06-06 04:53:28 -07006123 def nat64_get_ses_num(self):
6124 """
6125 Return number of active NAT64 sessions.
6126 """
Matus Fabianab9a59c2017-08-16 05:37:36 -07006127 st = self.vapi.nat64_st_dump()
6128 return len(st)
Matus Fabian06596c52017-06-06 04:53:28 -07006129
6130 def clear_nat64(self):
6131 """
6132 Clear NAT64 configuration.
6133 """
Matus Fabiana431ad12018-01-04 04:03:14 -08006134 self.vapi.nat_ipfix(enable=0, src_port=self.ipfix_src_port,
6135 domain_id=self.ipfix_domain_id)
6136 self.ipfix_src_port = 4739
6137 self.ipfix_domain_id = 1
6138
Matus Fabian06596c52017-06-06 04:53:28 -07006139 self.vapi.nat64_set_timeouts()
6140
6141 interfaces = self.vapi.nat64_interface_dump()
6142 for intf in interfaces:
Matus Fabian36ea2d62017-10-24 04:13:49 -07006143 if intf.is_inside > 1:
6144 self.vapi.nat64_add_del_interface(intf.sw_if_index,
6145 0,
6146 is_add=0)
Matus Fabian06596c52017-06-06 04:53:28 -07006147 self.vapi.nat64_add_del_interface(intf.sw_if_index,
6148 intf.is_inside,
6149 is_add=0)
6150
Matus Fabiana431ad12018-01-04 04:03:14 -08006151 bib = self.vapi.nat64_bib_dump(255)
Matus Fabian06596c52017-06-06 04:53:28 -07006152 for bibe in bib:
6153 if bibe.is_static:
6154 self.vapi.nat64_add_del_static_bib(bibe.i_addr,
6155 bibe.o_addr,
6156 bibe.i_port,
6157 bibe.o_port,
6158 bibe.proto,
6159 bibe.vrf_id,
6160 is_add=0)
6161
6162 adresses = self.vapi.nat64_pool_addr_dump()
6163 for addr in adresses:
6164 self.vapi.nat64_add_del_pool_addr_range(addr.address,
6165 addr.address,
Matus Fabian029f3d22017-06-15 02:28:50 -07006166 vrf_id=addr.vrf_id,
Matus Fabian06596c52017-06-06 04:53:28 -07006167 is_add=0)
6168
Matus Fabian428dc912017-06-21 06:15:18 -07006169 prefixes = self.vapi.nat64_prefix_dump()
6170 for prefix in prefixes:
6171 self.vapi.nat64_add_del_prefix(prefix.prefix,
6172 prefix.prefix_len,
6173 vrf_id=prefix.vrf_id,
6174 is_add=0)
6175
Matus Fabian06596c52017-06-06 04:53:28 -07006176 def tearDown(self):
6177 super(TestNAT64, self).tearDown()
6178 if not self.vpp_dead:
6179 self.logger.info(self.vapi.cli("show nat64 pool"))
6180 self.logger.info(self.vapi.cli("show nat64 interfaces"))
Matus Fabian428dc912017-06-21 06:15:18 -07006181 self.logger.info(self.vapi.cli("show nat64 prefix"))
Matus Fabianab9a59c2017-08-16 05:37:36 -07006182 self.logger.info(self.vapi.cli("show nat64 bib all"))
6183 self.logger.info(self.vapi.cli("show nat64 session table all"))
Matus Fabianefcd1e92017-08-15 06:59:19 -07006184 self.logger.info(self.vapi.cli("show nat virtual-reassembly"))
Matus Fabian06596c52017-06-06 04:53:28 -07006185 self.clear_nat64()
6186
Matus Fabian8ebe6252017-11-06 05:04:53 -08006187
6188class TestDSlite(MethodHolder):
6189 """ DS-Lite Test Cases """
6190
6191 @classmethod
6192 def setUpClass(cls):
6193 super(TestDSlite, cls).setUpClass()
6194
6195 try:
6196 cls.nat_addr = '10.0.0.3'
6197 cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
6198
6199 cls.create_pg_interfaces(range(2))
6200 cls.pg0.admin_up()
6201 cls.pg0.config_ip4()
6202 cls.pg0.resolve_arp()
6203 cls.pg1.admin_up()
6204 cls.pg1.config_ip6()
6205 cls.pg1.generate_remote_hosts(2)
6206 cls.pg1.configure_ipv6_neighbors()
6207
6208 except Exception:
6209 super(TestDSlite, cls).tearDownClass()
6210 raise
6211
6212 def test_dslite(self):
6213 """ Test DS-Lite """
6214 self.vapi.dslite_add_del_pool_addr_range(self.nat_addr_n,
6215 self.nat_addr_n)
6216 aftr_ip4 = '192.0.0.1'
6217 aftr_ip4_n = socket.inet_pton(socket.AF_INET, aftr_ip4)
6218 aftr_ip6 = '2001:db8:85a3::8a2e:370:1'
6219 aftr_ip6_n = socket.inet_pton(socket.AF_INET6, aftr_ip6)
6220 self.vapi.dslite_set_aftr_addr(aftr_ip6_n, aftr_ip4_n)
6221
6222 # UDP
6223 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
6224 IPv6(dst=aftr_ip6, src=self.pg1.remote_hosts[0].ip6) /
6225 IP(dst=self.pg0.remote_ip4, src='192.168.1.1') /
6226 UDP(sport=20000, dport=10000))
6227 self.pg1.add_stream(p)
6228 self.pg_enable_capture(self.pg_interfaces)
6229 self.pg_start()
6230 capture = self.pg0.get_capture(1)
6231 capture = capture[0]
6232 self.assertFalse(capture.haslayer(IPv6))
6233 self.assertEqual(capture[IP].src, self.nat_addr)
6234 self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
6235 self.assertNotEqual(capture[UDP].sport, 20000)
6236 self.assertEqual(capture[UDP].dport, 10000)
Klement Sekerad81ae412018-05-16 10:52:54 +02006237 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08006238 out_port = capture[UDP].sport
6239
6240 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6241 IP(dst=self.nat_addr, src=self.pg0.remote_ip4) /
6242 UDP(sport=10000, dport=out_port))
6243 self.pg0.add_stream(p)
6244 self.pg_enable_capture(self.pg_interfaces)
6245 self.pg_start()
6246 capture = self.pg1.get_capture(1)
6247 capture = capture[0]
6248 self.assertEqual(capture[IPv6].src, aftr_ip6)
6249 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[0].ip6)
6250 self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
6251 self.assertEqual(capture[IP].dst, '192.168.1.1')
6252 self.assertEqual(capture[UDP].sport, 10000)
6253 self.assertEqual(capture[UDP].dport, 20000)
Klement Sekerad81ae412018-05-16 10:52:54 +02006254 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08006255
6256 # TCP
6257 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
6258 IPv6(dst=aftr_ip6, src=self.pg1.remote_hosts[1].ip6) /
6259 IP(dst=self.pg0.remote_ip4, src='192.168.1.1') /
6260 TCP(sport=20001, dport=10001))
6261 self.pg1.add_stream(p)
6262 self.pg_enable_capture(self.pg_interfaces)
6263 self.pg_start()
6264 capture = self.pg0.get_capture(1)
6265 capture = capture[0]
6266 self.assertFalse(capture.haslayer(IPv6))
6267 self.assertEqual(capture[IP].src, self.nat_addr)
6268 self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
6269 self.assertNotEqual(capture[TCP].sport, 20001)
6270 self.assertEqual(capture[TCP].dport, 10001)
Klement Sekerad81ae412018-05-16 10:52:54 +02006271 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08006272 out_port = capture[TCP].sport
6273
6274 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6275 IP(dst=self.nat_addr, src=self.pg0.remote_ip4) /
6276 TCP(sport=10001, dport=out_port))
6277 self.pg0.add_stream(p)
6278 self.pg_enable_capture(self.pg_interfaces)
6279 self.pg_start()
6280 capture = self.pg1.get_capture(1)
6281 capture = capture[0]
6282 self.assertEqual(capture[IPv6].src, aftr_ip6)
6283 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[1].ip6)
6284 self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
6285 self.assertEqual(capture[IP].dst, '192.168.1.1')
6286 self.assertEqual(capture[TCP].sport, 10001)
6287 self.assertEqual(capture[TCP].dport, 20001)
Klement Sekerad81ae412018-05-16 10:52:54 +02006288 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08006289
6290 # ICMP
6291 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
6292 IPv6(dst=aftr_ip6, src=self.pg1.remote_hosts[1].ip6) /
6293 IP(dst=self.pg0.remote_ip4, src='192.168.1.1') /
6294 ICMP(id=4000, type='echo-request'))
6295 self.pg1.add_stream(p)
6296 self.pg_enable_capture(self.pg_interfaces)
6297 self.pg_start()
6298 capture = self.pg0.get_capture(1)
6299 capture = capture[0]
6300 self.assertFalse(capture.haslayer(IPv6))
6301 self.assertEqual(capture[IP].src, self.nat_addr)
6302 self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
6303 self.assertNotEqual(capture[ICMP].id, 4000)
Klement Sekerad81ae412018-05-16 10:52:54 +02006304 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08006305 out_id = capture[ICMP].id
6306
6307 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6308 IP(dst=self.nat_addr, src=self.pg0.remote_ip4) /
6309 ICMP(id=out_id, type='echo-reply'))
6310 self.pg0.add_stream(p)
6311 self.pg_enable_capture(self.pg_interfaces)
6312 self.pg_start()
6313 capture = self.pg1.get_capture(1)
6314 capture = capture[0]
6315 self.assertEqual(capture[IPv6].src, aftr_ip6)
6316 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[1].ip6)
6317 self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
6318 self.assertEqual(capture[IP].dst, '192.168.1.1')
6319 self.assertEqual(capture[ICMP].id, 4000)
Klement Sekerad81ae412018-05-16 10:52:54 +02006320 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08006321
Matus Fabian331acc62017-12-08 03:38:51 -08006322 # ping DS-Lite AFTR tunnel endpoint address
6323 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
6324 IPv6(src=self.pg1.remote_hosts[1].ip6, dst=aftr_ip6) /
6325 ICMPv6EchoRequest())
6326 self.pg1.add_stream(p)
6327 self.pg_enable_capture(self.pg_interfaces)
6328 self.pg_start()
6329 capture = self.pg1.get_capture(1)
6330 self.assertEqual(1, len(capture))
6331 capture = capture[0]
6332 self.assertEqual(capture[IPv6].src, aftr_ip6)
6333 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[1].ip6)
6334 self.assertTrue(capture.haslayer(ICMPv6EchoReply))
6335
Matus Fabian8ebe6252017-11-06 05:04:53 -08006336 def tearDown(self):
6337 super(TestDSlite, self).tearDown()
6338 if not self.vpp_dead:
6339 self.logger.info(self.vapi.cli("show dslite pool"))
6340 self.logger.info(
6341 self.vapi.cli("show dslite aftr-tunnel-endpoint-address"))
6342 self.logger.info(self.vapi.cli("show dslite sessions"))
6343
Juraj Slobodac5c6a332018-01-09 16:08:32 +01006344
6345class TestDSliteCE(MethodHolder):
6346 """ DS-Lite CE Test Cases """
6347
6348 @classmethod
6349 def setUpConstants(cls):
6350 super(TestDSliteCE, cls).setUpConstants()
6351 cls.vpp_cmdline.extend(["nat", "{", "dslite ce", "}"])
6352
6353 @classmethod
6354 def setUpClass(cls):
6355 super(TestDSliteCE, cls).setUpClass()
6356
6357 try:
6358 cls.create_pg_interfaces(range(2))
6359 cls.pg0.admin_up()
6360 cls.pg0.config_ip4()
6361 cls.pg0.resolve_arp()
6362 cls.pg1.admin_up()
6363 cls.pg1.config_ip6()
6364 cls.pg1.generate_remote_hosts(1)
6365 cls.pg1.configure_ipv6_neighbors()
6366
6367 except Exception:
6368 super(TestDSliteCE, cls).tearDownClass()
6369 raise
6370
6371 def test_dslite_ce(self):
6372 """ Test DS-Lite CE """
6373
6374 b4_ip4 = '192.0.0.2'
6375 b4_ip4_n = socket.inet_pton(socket.AF_INET, b4_ip4)
6376 b4_ip6 = '2001:db8:62aa::375e:f4c1:1'
6377 b4_ip6_n = socket.inet_pton(socket.AF_INET6, b4_ip6)
6378 self.vapi.dslite_set_b4_addr(b4_ip6_n, b4_ip4_n)
6379
6380 aftr_ip4 = '192.0.0.1'
6381 aftr_ip4_n = socket.inet_pton(socket.AF_INET, aftr_ip4)
6382 aftr_ip6 = '2001:db8:85a3::8a2e:370:1'
6383 aftr_ip6_n = socket.inet_pton(socket.AF_INET6, aftr_ip6)
6384 self.vapi.dslite_set_aftr_addr(aftr_ip6_n, aftr_ip4_n)
6385
6386 self.vapi.ip_add_del_route(dst_address=aftr_ip6_n,
6387 dst_address_length=128,
6388 next_hop_address=self.pg1.remote_ip6n,
6389 next_hop_sw_if_index=self.pg1.sw_if_index,
6390 is_ipv6=1)
6391
6392 # UDP encapsulation
6393 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6394 IP(dst=self.pg1.remote_ip4, src=self.pg0.remote_ip4) /
6395 UDP(sport=10000, dport=20000))
6396 self.pg0.add_stream(p)
6397 self.pg_enable_capture(self.pg_interfaces)
6398 self.pg_start()
6399 capture = self.pg1.get_capture(1)
6400 capture = capture[0]
6401 self.assertEqual(capture[IPv6].src, b4_ip6)
6402 self.assertEqual(capture[IPv6].dst, aftr_ip6)
6403 self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
6404 self.assertEqual(capture[IP].dst, self.pg1.remote_ip4)
6405 self.assertEqual(capture[UDP].sport, 10000)
6406 self.assertEqual(capture[UDP].dport, 20000)
Klement Sekerad81ae412018-05-16 10:52:54 +02006407 self.assert_packet_checksums_valid(capture)
Juraj Slobodac5c6a332018-01-09 16:08:32 +01006408
6409 # UDP decapsulation
6410 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
6411 IPv6(dst=b4_ip6, src=aftr_ip6) /
6412 IP(dst=self.pg0.remote_ip4, src=self.pg1.remote_ip4) /
6413 UDP(sport=20000, dport=10000))
6414 self.pg1.add_stream(p)
6415 self.pg_enable_capture(self.pg_interfaces)
6416 self.pg_start()
6417 capture = self.pg0.get_capture(1)
6418 capture = capture[0]
6419 self.assertFalse(capture.haslayer(IPv6))
6420 self.assertEqual(capture[IP].src, self.pg1.remote_ip4)
6421 self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
6422 self.assertEqual(capture[UDP].sport, 20000)
6423 self.assertEqual(capture[UDP].dport, 10000)
Klement Sekerad81ae412018-05-16 10:52:54 +02006424 self.assert_packet_checksums_valid(capture)
Juraj Slobodac5c6a332018-01-09 16:08:32 +01006425
6426 # ping DS-Lite B4 tunnel endpoint address
6427 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
6428 IPv6(src=self.pg1.remote_hosts[0].ip6, dst=b4_ip6) /
6429 ICMPv6EchoRequest())
6430 self.pg1.add_stream(p)
6431 self.pg_enable_capture(self.pg_interfaces)
6432 self.pg_start()
6433 capture = self.pg1.get_capture(1)
6434 self.assertEqual(1, len(capture))
6435 capture = capture[0]
6436 self.assertEqual(capture[IPv6].src, b4_ip6)
6437 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[0].ip6)
6438 self.assertTrue(capture.haslayer(ICMPv6EchoReply))
6439
6440 def tearDown(self):
6441 super(TestDSliteCE, self).tearDown()
6442 if not self.vpp_dead:
6443 self.logger.info(
6444 self.vapi.cli("show dslite aftr-tunnel-endpoint-address"))
6445 self.logger.info(
6446 self.vapi.cli("show dslite b4-tunnel-endpoint-address"))
6447
Matus Fabianf2a23cc2018-01-22 03:41:53 -08006448
6449class TestNAT66(MethodHolder):
6450 """ NAT66 Test Cases """
6451
6452 @classmethod
6453 def setUpClass(cls):
6454 super(TestNAT66, cls).setUpClass()
6455
6456 try:
6457 cls.nat_addr = 'fd01:ff::2'
6458 cls.nat_addr_n = socket.inet_pton(socket.AF_INET6, cls.nat_addr)
6459
6460 cls.create_pg_interfaces(range(2))
6461 cls.interfaces = list(cls.pg_interfaces)
6462
6463 for i in cls.interfaces:
6464 i.admin_up()
6465 i.config_ip6()
6466 i.configure_ipv6_neighbors()
6467
6468 except Exception:
6469 super(TestNAT66, cls).tearDownClass()
6470 raise
6471
6472 def test_static(self):
6473 """ 1:1 NAT66 test """
6474 self.vapi.nat66_add_del_interface(self.pg0.sw_if_index)
6475 self.vapi.nat66_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6476 self.vapi.nat66_add_del_static_mapping(self.pg0.remote_ip6n,
6477 self.nat_addr_n)
6478
6479 # in2out
6480 pkts = []
6481 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6482 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
6483 TCP())
6484 pkts.append(p)
6485 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6486 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
6487 UDP())
6488 pkts.append(p)
6489 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6490 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
6491 ICMPv6EchoRequest())
6492 pkts.append(p)
6493 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6494 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
6495 GRE() / IP() / TCP())
6496 pkts.append(p)
6497 self.pg0.add_stream(pkts)
6498 self.pg_enable_capture(self.pg_interfaces)
6499 self.pg_start()
6500 capture = self.pg1.get_capture(len(pkts))
6501 for packet in capture:
6502 try:
6503 self.assertEqual(packet[IPv6].src, self.nat_addr)
6504 self.assertEqual(packet[IPv6].dst, self.pg1.remote_ip6)
Klement Sekerad81ae412018-05-16 10:52:54 +02006505 self.assert_packet_checksums_valid(packet)
Matus Fabianf2a23cc2018-01-22 03:41:53 -08006506 except:
6507 self.logger.error(ppp("Unexpected or invalid packet:", packet))
6508 raise
6509
6510 # out2in
6511 pkts = []
6512 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
6513 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
6514 TCP())
6515 pkts.append(p)
6516 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
6517 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
6518 UDP())
6519 pkts.append(p)
6520 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
6521 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
6522 ICMPv6EchoReply())
6523 pkts.append(p)
6524 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
6525 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
6526 GRE() / IP() / TCP())
6527 pkts.append(p)
6528 self.pg1.add_stream(pkts)
6529 self.pg_enable_capture(self.pg_interfaces)
6530 self.pg_start()
6531 capture = self.pg0.get_capture(len(pkts))
6532 for packet in capture:
6533 try:
6534 self.assertEqual(packet[IPv6].src, self.pg1.remote_ip6)
6535 self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
Klement Sekerad81ae412018-05-16 10:52:54 +02006536 self.assert_packet_checksums_valid(packet)
Matus Fabianf2a23cc2018-01-22 03:41:53 -08006537 except:
6538 self.logger.error(ppp("Unexpected or invalid packet:", packet))
6539 raise
6540
6541 sm = self.vapi.nat66_static_mapping_dump()
6542 self.assertEqual(len(sm), 1)
6543 self.assertEqual(sm[0].total_pkts, 8)
6544
Juraj Sloboda9341e342018-04-13 12:00:46 +02006545 def test_check_no_translate(self):
6546 """ NAT66 translate only when egress interface is outside interface """
6547 self.vapi.nat66_add_del_interface(self.pg0.sw_if_index)
6548 self.vapi.nat66_add_del_interface(self.pg1.sw_if_index)
6549 self.vapi.nat66_add_del_static_mapping(self.pg0.remote_ip6n,
6550 self.nat_addr_n)
6551
6552 # in2out
6553 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6554 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
6555 UDP())
6556 self.pg0.add_stream([p])
6557 self.pg_enable_capture(self.pg_interfaces)
6558 self.pg_start()
6559 capture = self.pg1.get_capture(1)
6560 packet = capture[0]
6561 try:
6562 self.assertEqual(packet[IPv6].src, self.pg0.remote_ip6)
6563 self.assertEqual(packet[IPv6].dst, self.pg1.remote_ip6)
6564 except:
6565 self.logger.error(ppp("Unexpected or invalid packet:", packet))
6566 raise
6567
Matus Fabianf2a23cc2018-01-22 03:41:53 -08006568 def clear_nat66(self):
6569 """
6570 Clear NAT66 configuration.
6571 """
6572 interfaces = self.vapi.nat66_interface_dump()
6573 for intf in interfaces:
6574 self.vapi.nat66_add_del_interface(intf.sw_if_index,
6575 intf.is_inside,
6576 is_add=0)
6577
6578 static_mappings = self.vapi.nat66_static_mapping_dump()
6579 for sm in static_mappings:
6580 self.vapi.nat66_add_del_static_mapping(sm.local_ip_address,
6581 sm.external_ip_address,
6582 sm.vrf_id,
6583 is_add=0)
6584
6585 def tearDown(self):
6586 super(TestNAT66, self).tearDown()
6587 if not self.vpp_dead:
6588 self.logger.info(self.vapi.cli("show nat66 interfaces"))
6589 self.logger.info(self.vapi.cli("show nat66 static mappings"))
6590 self.clear_nat66()
6591
Klement Sekerad81ae412018-05-16 10:52:54 +02006592
Matus Fabiande886752016-12-07 03:38:19 -08006593if __name__ == '__main__':
6594 unittest.main(testRunner=VppTestRunner)