blob: 5baadd8986313f3872f853332a0d6cdbd2bf7e10 [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
Juraj Slobodac746a152018-07-09 02:36:37 +020012from scapy.layers.inet6 import IPv6, ICMPv6EchoRequest, ICMPv6EchoReply, \
13 ICMPv6ND_NS, ICMPv6ND_NA, ICMPv6NDOptDstLLAddr
Matus Fabianefcd1e92017-08-15 06:59:19 -070014from scapy.layers.inet6 import ICMPv6DestUnreach, IPerror6, IPv6ExtHdrFragment
Matus Fabian328dbc82017-06-19 04:28:04 -070015from scapy.layers.l2 import Ether, ARP, GRE
Matus Fabianeea28d72017-01-13 04:15:54 -080016from scapy.data import IP_PROTOS
Matus Fabianefcd1e92017-08-15 06:59:19 -070017from scapy.packet import bind_layers, Raw
18from scapy.all import fragment6
Klement Sekera9225dee2016-12-12 08:36:58 +010019from util import ppp
Matus Fabianeea28d72017-01-13 04:15:54 -080020from ipfix import IPFIX, Set, Template, Data, IPFIXDecoder
Martin Gálik977c1cb2017-03-30 23:21:51 -070021from time import sleep
Matus Fabian704018c2017-09-04 02:17:18 -070022from util import ip4_range
Ole Troan895b6e82017-10-20 13:28:20 +020023from util import mactobinary
Matus Fabiande886752016-12-07 03:38:19 -080024
25
Martin Gálikd7f75cd2017-03-27 06:02:47 -070026class MethodHolder(VppTestCase):
Matus Fabian2ba92e32017-08-21 07:05:03 -070027 """ NAT create capture and verify method holder """
Matus Fabiande886752016-12-07 03:38:19 -080028
Matus Fabiana6110b62018-06-13 05:39:07 -070029 def clear_nat44(self):
30 """
31 Clear NAT44 configuration.
32 """
33 if hasattr(self, 'pg7') and hasattr(self, 'pg8'):
34 # I found no elegant way to do this
35 self.vapi.ip_add_del_route(
36 dst_address=self.pg7.remote_ip4n,
37 dst_address_length=32,
38 next_hop_address=self.pg7.remote_ip4n,
39 next_hop_sw_if_index=self.pg7.sw_if_index,
40 is_add=0)
41 self.vapi.ip_add_del_route(
42 dst_address=self.pg8.remote_ip4n,
43 dst_address_length=32,
44 next_hop_address=self.pg8.remote_ip4n,
45 next_hop_sw_if_index=self.pg8.sw_if_index,
46 is_add=0)
47
48 for intf in [self.pg7, self.pg8]:
49 neighbors = self.vapi.ip_neighbor_dump(intf.sw_if_index)
50 for n in neighbors:
51 self.vapi.ip_neighbor_add_del(intf.sw_if_index,
52 n.mac_address,
53 n.ip_address,
54 is_add=0)
55
56 if self.pg7.has_ip4_config:
57 self.pg7.unconfig_ip4()
58
59 self.vapi.nat44_forwarding_enable_disable(0)
60
61 interfaces = self.vapi.nat44_interface_addr_dump()
62 for intf in interfaces:
63 self.vapi.nat44_add_interface_addr(intf.sw_if_index,
64 twice_nat=intf.twice_nat,
65 is_add=0)
66
67 self.vapi.nat_ipfix(enable=0, src_port=self.ipfix_src_port,
68 domain_id=self.ipfix_domain_id)
69 self.ipfix_src_port = 4739
70 self.ipfix_domain_id = 1
71
72 interfaces = self.vapi.nat44_interface_dump()
73 for intf in interfaces:
74 if intf.is_inside > 1:
75 self.vapi.nat44_interface_add_del_feature(intf.sw_if_index,
76 0,
77 is_add=0)
78 self.vapi.nat44_interface_add_del_feature(intf.sw_if_index,
79 intf.is_inside,
80 is_add=0)
81
82 interfaces = self.vapi.nat44_interface_output_feature_dump()
83 for intf in interfaces:
84 self.vapi.nat44_interface_add_del_output_feature(intf.sw_if_index,
85 intf.is_inside,
86 is_add=0)
87
88 static_mappings = self.vapi.nat44_static_mapping_dump()
89 for sm in static_mappings:
90 self.vapi.nat44_add_del_static_mapping(
91 sm.local_ip_address,
92 sm.external_ip_address,
93 local_port=sm.local_port,
94 external_port=sm.external_port,
95 addr_only=sm.addr_only,
96 vrf_id=sm.vrf_id,
97 protocol=sm.protocol,
98 twice_nat=sm.twice_nat,
99 self_twice_nat=sm.self_twice_nat,
100 out2in_only=sm.out2in_only,
101 tag=sm.tag,
102 external_sw_if_index=sm.external_sw_if_index,
103 is_add=0)
104
105 lb_static_mappings = self.vapi.nat44_lb_static_mapping_dump()
106 for lb_sm in lb_static_mappings:
107 self.vapi.nat44_add_del_lb_static_mapping(
108 lb_sm.external_addr,
109 lb_sm.external_port,
110 lb_sm.protocol,
Matus Fabiana6110b62018-06-13 05:39:07 -0700111 twice_nat=lb_sm.twice_nat,
112 self_twice_nat=lb_sm.self_twice_nat,
113 out2in_only=lb_sm.out2in_only,
114 tag=lb_sm.tag,
115 is_add=0,
116 local_num=0,
117 locals=[])
118
119 identity_mappings = self.vapi.nat44_identity_mapping_dump()
120 for id_m in identity_mappings:
121 self.vapi.nat44_add_del_identity_mapping(
122 addr_only=id_m.addr_only,
123 ip=id_m.ip_address,
124 port=id_m.port,
125 sw_if_index=id_m.sw_if_index,
126 vrf_id=id_m.vrf_id,
127 protocol=id_m.protocol,
128 is_add=0)
129
130 adresses = self.vapi.nat44_address_dump()
131 for addr in adresses:
132 self.vapi.nat44_add_del_address_range(addr.ip_address,
133 addr.ip_address,
134 twice_nat=addr.twice_nat,
135 is_add=0)
136
137 self.vapi.nat_set_reass()
138 self.vapi.nat_set_reass(is_ip6=1)
Matus Fabian68ba8802018-08-08 05:52:47 -0700139 self.verify_no_nat44_user()
Matus Fabian878c6462018-08-23 00:33:35 -0700140 self.vapi.nat_set_timeouts()
Matus Fabian5d28c7a2018-09-04 03:55:45 -0700141 self.vapi.nat_set_addr_and_port_alloc_alg()
Matus Fabiana6110b62018-06-13 05:39:07 -0700142
143 def nat44_add_static_mapping(self, local_ip, external_ip='0.0.0.0',
144 local_port=0, external_port=0, vrf_id=0,
145 is_add=1, external_sw_if_index=0xFFFFFFFF,
146 proto=0, twice_nat=0, self_twice_nat=0,
147 out2in_only=0, tag=""):
148 """
149 Add/delete NAT44 static mapping
150
151 :param local_ip: Local IP address
152 :param external_ip: External IP address
153 :param local_port: Local port number (Optional)
154 :param external_port: External port number (Optional)
155 :param vrf_id: VRF ID (Default 0)
156 :param is_add: 1 if add, 0 if delete (Default add)
157 :param external_sw_if_index: External interface instead of IP address
158 :param proto: IP protocol (Mandatory if port specified)
159 :param twice_nat: 1 if translate external host address and port
160 :param self_twice_nat: 1 if translate external host address and port
161 whenever external host address equals
162 local address of internal host
163 :param out2in_only: if 1 rule is matching only out2in direction
164 :param tag: Opaque string tag
165 """
166 addr_only = 1
167 if local_port and external_port:
168 addr_only = 0
169 l_ip = socket.inet_pton(socket.AF_INET, local_ip)
170 e_ip = socket.inet_pton(socket.AF_INET, external_ip)
171 self.vapi.nat44_add_del_static_mapping(
172 l_ip,
173 e_ip,
174 external_sw_if_index,
175 local_port,
176 external_port,
177 addr_only,
178 vrf_id,
179 proto,
180 twice_nat,
181 self_twice_nat,
182 out2in_only,
183 tag,
184 is_add)
185
186 def nat44_add_address(self, ip, is_add=1, vrf_id=0xFFFFFFFF, twice_nat=0):
187 """
188 Add/delete NAT44 address
189
190 :param ip: IP address
191 :param is_add: 1 if add, 0 if delete (Default add)
192 :param twice_nat: twice NAT address for extenal hosts
193 """
194 nat_addr = socket.inet_pton(socket.AF_INET, ip)
195 self.vapi.nat44_add_del_address_range(nat_addr, nat_addr, is_add,
196 vrf_id=vrf_id,
197 twice_nat=twice_nat)
198
Juraj Slobodacba69362017-12-19 02:09:32 +0100199 def create_stream_in(self, in_if, out_if, dst_ip=None, ttl=64):
Matus Fabiande886752016-12-07 03:38:19 -0800200 """
201 Create packet stream for inside network
202
203 :param in_if: Inside interface
204 :param out_if: Outside interface
Juraj Slobodacba69362017-12-19 02:09:32 +0100205 :param dst_ip: Destination address
Juraj Slobodab33f4132017-02-08 23:54:21 -0800206 :param ttl: TTL of generated packets
Matus Fabiande886752016-12-07 03:38:19 -0800207 """
Juraj Slobodacba69362017-12-19 02:09:32 +0100208 if dst_ip is None:
209 dst_ip = out_if.remote_ip4
210
Matus Fabiande886752016-12-07 03:38:19 -0800211 pkts = []
212 # TCP
213 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
Juraj Slobodacba69362017-12-19 02:09:32 +0100214 IP(src=in_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Matus Fabian06596c52017-06-06 04:53:28 -0700215 TCP(sport=self.tcp_port_in, dport=20))
Matus Fabiande886752016-12-07 03:38:19 -0800216 pkts.append(p)
217
218 # UDP
219 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
Juraj Slobodacba69362017-12-19 02:09:32 +0100220 IP(src=in_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Matus Fabian06596c52017-06-06 04:53:28 -0700221 UDP(sport=self.udp_port_in, dport=20))
Matus Fabiande886752016-12-07 03:38:19 -0800222 pkts.append(p)
223
224 # ICMP
225 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
Juraj Slobodacba69362017-12-19 02:09:32 +0100226 IP(src=in_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Matus Fabiande886752016-12-07 03:38:19 -0800227 ICMP(id=self.icmp_id_in, type='echo-request'))
228 pkts.append(p)
229
230 return pkts
231
Matus Fabian428dc912017-06-21 06:15:18 -0700232 def compose_ip6(self, ip4, pref, plen):
233 """
234 Compose IPv4-embedded IPv6 addresses
235
236 :param ip4: IPv4 address
237 :param pref: IPv6 prefix
238 :param plen: IPv6 prefix length
239 :returns: IPv4-embedded IPv6 addresses
240 """
241 pref_n = list(socket.inet_pton(socket.AF_INET6, pref))
242 ip4_n = list(socket.inet_pton(socket.AF_INET, ip4))
243 if plen == 32:
244 pref_n[4] = ip4_n[0]
245 pref_n[5] = ip4_n[1]
246 pref_n[6] = ip4_n[2]
247 pref_n[7] = ip4_n[3]
248 elif plen == 40:
249 pref_n[5] = ip4_n[0]
250 pref_n[6] = ip4_n[1]
251 pref_n[7] = ip4_n[2]
252 pref_n[9] = ip4_n[3]
253 elif plen == 48:
254 pref_n[6] = ip4_n[0]
255 pref_n[7] = ip4_n[1]
256 pref_n[9] = ip4_n[2]
257 pref_n[10] = ip4_n[3]
258 elif plen == 56:
259 pref_n[7] = ip4_n[0]
260 pref_n[9] = ip4_n[1]
261 pref_n[10] = ip4_n[2]
262 pref_n[11] = ip4_n[3]
263 elif plen == 64:
264 pref_n[9] = ip4_n[0]
265 pref_n[10] = ip4_n[1]
266 pref_n[11] = ip4_n[2]
267 pref_n[12] = ip4_n[3]
268 elif plen == 96:
269 pref_n[12] = ip4_n[0]
270 pref_n[13] = ip4_n[1]
271 pref_n[14] = ip4_n[2]
272 pref_n[15] = ip4_n[3]
273 return socket.inet_ntop(socket.AF_INET6, ''.join(pref_n))
274
Juraj Slobodacba69362017-12-19 02:09:32 +0100275 def extract_ip4(self, ip6, plen):
276 """
277 Extract IPv4 address embedded in IPv6 addresses
278
279 :param ip6: IPv6 address
280 :param plen: IPv6 prefix length
281 :returns: extracted IPv4 address
282 """
283 ip6_n = list(socket.inet_pton(socket.AF_INET6, ip6))
284 ip4_n = [None] * 4
285 if plen == 32:
286 ip4_n[0] = ip6_n[4]
287 ip4_n[1] = ip6_n[5]
288 ip4_n[2] = ip6_n[6]
289 ip4_n[3] = ip6_n[7]
290 elif plen == 40:
291 ip4_n[0] = ip6_n[5]
292 ip4_n[1] = ip6_n[6]
293 ip4_n[2] = ip6_n[7]
294 ip4_n[3] = ip6_n[9]
295 elif plen == 48:
296 ip4_n[0] = ip6_n[6]
297 ip4_n[1] = ip6_n[7]
298 ip4_n[2] = ip6_n[9]
299 ip4_n[3] = ip6_n[10]
300 elif plen == 56:
301 ip4_n[0] = ip6_n[7]
302 ip4_n[1] = ip6_n[9]
303 ip4_n[2] = ip6_n[10]
304 ip4_n[3] = ip6_n[11]
305 elif plen == 64:
306 ip4_n[0] = ip6_n[9]
307 ip4_n[1] = ip6_n[10]
308 ip4_n[2] = ip6_n[11]
309 ip4_n[3] = ip6_n[12]
310 elif plen == 96:
311 ip4_n[0] = ip6_n[12]
312 ip4_n[1] = ip6_n[13]
313 ip4_n[2] = ip6_n[14]
314 ip4_n[3] = ip6_n[15]
315 return socket.inet_ntop(socket.AF_INET, ''.join(ip4_n))
316
Matus Fabian428dc912017-06-21 06:15:18 -0700317 def create_stream_in_ip6(self, in_if, out_if, hlim=64, pref=None, plen=0):
Matus Fabian06596c52017-06-06 04:53:28 -0700318 """
319 Create IPv6 packet stream for inside network
320
321 :param in_if: Inside interface
322 :param out_if: Outside interface
323 :param ttl: Hop Limit of generated packets
Matus Fabian428dc912017-06-21 06:15:18 -0700324 :param pref: NAT64 prefix
325 :param plen: NAT64 prefix length
Matus Fabian06596c52017-06-06 04:53:28 -0700326 """
327 pkts = []
Matus Fabian428dc912017-06-21 06:15:18 -0700328 if pref is None:
329 dst = ''.join(['64:ff9b::', out_if.remote_ip4])
330 else:
331 dst = self.compose_ip6(out_if.remote_ip4, pref, plen)
332
Matus Fabian06596c52017-06-06 04:53:28 -0700333 # TCP
334 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
335 IPv6(src=in_if.remote_ip6, dst=dst, hlim=hlim) /
336 TCP(sport=self.tcp_port_in, dport=20))
337 pkts.append(p)
338
339 # UDP
340 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
341 IPv6(src=in_if.remote_ip6, dst=dst, hlim=hlim) /
342 UDP(sport=self.udp_port_in, dport=20))
343 pkts.append(p)
344
345 # ICMP
346 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
347 IPv6(src=in_if.remote_ip6, dst=dst, hlim=hlim) /
348 ICMPv6EchoRequest(id=self.icmp_id_in))
349 pkts.append(p)
350
351 return pkts
352
Juraj Sloboda7b929792017-11-23 13:20:48 +0100353 def create_stream_out(self, out_if, dst_ip=None, ttl=64,
354 use_inside_ports=False):
Matus Fabiande886752016-12-07 03:38:19 -0800355 """
356 Create packet stream for outside network
357
358 :param out_if: Outside interface
Matus Fabian2ba92e32017-08-21 07:05:03 -0700359 :param dst_ip: Destination IP address (Default use global NAT address)
Juraj Slobodab33f4132017-02-08 23:54:21 -0800360 :param ttl: TTL of generated packets
Juraj Sloboda7b929792017-11-23 13:20:48 +0100361 :param use_inside_ports: Use inside NAT ports as destination ports
362 instead of outside ports
Matus Fabiande886752016-12-07 03:38:19 -0800363 """
364 if dst_ip is None:
Matus Fabian2ba92e32017-08-21 07:05:03 -0700365 dst_ip = self.nat_addr
Juraj Sloboda7b929792017-11-23 13:20:48 +0100366 if not use_inside_ports:
367 tcp_port = self.tcp_port_out
368 udp_port = self.udp_port_out
369 icmp_id = self.icmp_id_out
370 else:
371 tcp_port = self.tcp_port_in
372 udp_port = self.udp_port_in
373 icmp_id = self.icmp_id_in
Matus Fabiande886752016-12-07 03:38:19 -0800374 pkts = []
375 # TCP
376 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
Juraj Slobodab33f4132017-02-08 23:54:21 -0800377 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Juraj Sloboda7b929792017-11-23 13:20:48 +0100378 TCP(dport=tcp_port, sport=20))
Matus Fabiande886752016-12-07 03:38:19 -0800379 pkts.append(p)
380
381 # UDP
382 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
Juraj Slobodab33f4132017-02-08 23:54:21 -0800383 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Juraj Sloboda7b929792017-11-23 13:20:48 +0100384 UDP(dport=udp_port, sport=20))
Matus Fabiande886752016-12-07 03:38:19 -0800385 pkts.append(p)
386
387 # ICMP
388 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
Juraj Slobodab33f4132017-02-08 23:54:21 -0800389 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Juraj Sloboda7b929792017-11-23 13:20:48 +0100390 ICMP(id=icmp_id, type='echo-reply'))
Matus Fabiande886752016-12-07 03:38:19 -0800391 pkts.append(p)
392
393 return pkts
394
Juraj Slobodacba69362017-12-19 02:09:32 +0100395 def create_stream_out_ip6(self, out_if, src_ip, dst_ip, hl=64):
396 """
397 Create packet stream for outside network
398
399 :param out_if: Outside interface
400 :param dst_ip: Destination IP address (Default use global NAT address)
401 :param hl: HL of generated packets
402 """
403 pkts = []
404 # TCP
405 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
406 IPv6(src=src_ip, dst=dst_ip, hlim=hl) /
407 TCP(dport=self.tcp_port_out, sport=20))
408 pkts.append(p)
409
410 # UDP
411 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
412 IPv6(src=src_ip, dst=dst_ip, hlim=hl) /
413 UDP(dport=self.udp_port_out, sport=20))
414 pkts.append(p)
415
416 # ICMP
417 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
418 IPv6(src=src_ip, dst=dst_ip, hlim=hl) /
419 ICMPv6EchoReply(id=self.icmp_id_out))
420 pkts.append(p)
421
422 return pkts
423
Matus Fabiande886752016-12-07 03:38:19 -0800424 def verify_capture_out(self, capture, nat_ip=None, same_port=False,
Matus Fabian05ca4a32018-09-04 23:45:13 -0700425 dst_ip=None, is_ip6=False):
Matus Fabiande886752016-12-07 03:38:19 -0800426 """
427 Verify captured packets on outside network
428
429 :param capture: Captured packets
Matus Fabian2ba92e32017-08-21 07:05:03 -0700430 :param nat_ip: Translated IP address (Default use global NAT address)
Matus Fabiande886752016-12-07 03:38:19 -0800431 :param same_port: Sorce port number is not translated (Default False)
Matus Fabian06596c52017-06-06 04:53:28 -0700432 :param dst_ip: Destination IP address (Default do not verify)
Juraj Slobodacba69362017-12-19 02:09:32 +0100433 :param is_ip6: If L3 protocol is IPv6 (Default False)
Matus Fabiande886752016-12-07 03:38:19 -0800434 """
Juraj Slobodacba69362017-12-19 02:09:32 +0100435 if is_ip6:
436 IP46 = IPv6
437 ICMP46 = ICMPv6EchoRequest
438 else:
439 IP46 = IP
440 ICMP46 = ICMP
Matus Fabiande886752016-12-07 03:38:19 -0800441 if nat_ip is None:
Matus Fabian2ba92e32017-08-21 07:05:03 -0700442 nat_ip = self.nat_addr
Matus Fabiande886752016-12-07 03:38:19 -0800443 for packet in capture:
444 try:
Juraj Slobodacba69362017-12-19 02:09:32 +0100445 if not is_ip6:
Klement Sekerad81ae412018-05-16 10:52:54 +0200446 self.assert_packet_checksums_valid(packet)
Juraj Slobodacba69362017-12-19 02:09:32 +0100447 self.assertEqual(packet[IP46].src, nat_ip)
Matus Fabian06596c52017-06-06 04:53:28 -0700448 if dst_ip is not None:
Juraj Slobodacba69362017-12-19 02:09:32 +0100449 self.assertEqual(packet[IP46].dst, dst_ip)
Matus Fabiande886752016-12-07 03:38:19 -0800450 if packet.haslayer(TCP):
451 if same_port:
452 self.assertEqual(packet[TCP].sport, self.tcp_port_in)
453 else:
Klement Sekerada505f62017-01-04 12:58:53 +0100454 self.assertNotEqual(
455 packet[TCP].sport, self.tcp_port_in)
Matus Fabiande886752016-12-07 03:38:19 -0800456 self.tcp_port_out = packet[TCP].sport
Klement Sekerad81ae412018-05-16 10:52:54 +0200457 self.assert_packet_checksums_valid(packet)
Matus Fabiande886752016-12-07 03:38:19 -0800458 elif packet.haslayer(UDP):
459 if same_port:
460 self.assertEqual(packet[UDP].sport, self.udp_port_in)
461 else:
Klement Sekerada505f62017-01-04 12:58:53 +0100462 self.assertNotEqual(
463 packet[UDP].sport, self.udp_port_in)
Matus Fabiande886752016-12-07 03:38:19 -0800464 self.udp_port_out = packet[UDP].sport
465 else:
466 if same_port:
Juraj Slobodacba69362017-12-19 02:09:32 +0100467 self.assertEqual(packet[ICMP46].id, self.icmp_id_in)
Matus Fabiande886752016-12-07 03:38:19 -0800468 else:
Juraj Slobodacba69362017-12-19 02:09:32 +0100469 self.assertNotEqual(packet[ICMP46].id, self.icmp_id_in)
470 self.icmp_id_out = packet[ICMP46].id
Klement Sekerad81ae412018-05-16 10:52:54 +0200471 self.assert_packet_checksums_valid(packet)
Matus Fabiande886752016-12-07 03:38:19 -0800472 except:
Klement Sekera9225dee2016-12-12 08:36:58 +0100473 self.logger.error(ppp("Unexpected or invalid packet "
474 "(outside network):", packet))
Matus Fabiande886752016-12-07 03:38:19 -0800475 raise
476
Juraj Slobodacba69362017-12-19 02:09:32 +0100477 def verify_capture_out_ip6(self, capture, nat_ip, same_port=False,
Matus Fabian05ca4a32018-09-04 23:45:13 -0700478 dst_ip=None):
Juraj Slobodacba69362017-12-19 02:09:32 +0100479 """
480 Verify captured packets on outside network
481
482 :param capture: Captured packets
483 :param nat_ip: Translated IP address
484 :param same_port: Sorce port number is not translated (Default False)
Juraj Slobodacba69362017-12-19 02:09:32 +0100485 :param dst_ip: Destination IP address (Default do not verify)
486 """
Matus Fabian05ca4a32018-09-04 23:45:13 -0700487 return self.verify_capture_out(capture, nat_ip, same_port, dst_ip,
488 True)
Juraj Slobodacba69362017-12-19 02:09:32 +0100489
Matus Fabian05ca4a32018-09-04 23:45:13 -0700490 def verify_capture_in(self, capture, in_if):
Matus Fabiande886752016-12-07 03:38:19 -0800491 """
492 Verify captured packets on inside network
493
494 :param capture: Captured packets
495 :param in_if: Inside interface
Matus Fabiande886752016-12-07 03:38:19 -0800496 """
Matus Fabiande886752016-12-07 03:38:19 -0800497 for packet in capture:
498 try:
Klement Sekerad81ae412018-05-16 10:52:54 +0200499 self.assert_packet_checksums_valid(packet)
Matus Fabiande886752016-12-07 03:38:19 -0800500 self.assertEqual(packet[IP].dst, in_if.remote_ip4)
501 if packet.haslayer(TCP):
502 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
503 elif packet.haslayer(UDP):
504 self.assertEqual(packet[UDP].dport, self.udp_port_in)
505 else:
506 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
507 except:
Klement Sekera9225dee2016-12-12 08:36:58 +0100508 self.logger.error(ppp("Unexpected or invalid packet "
509 "(inside network):", packet))
Matus Fabiande886752016-12-07 03:38:19 -0800510 raise
511
Matus Fabian05ca4a32018-09-04 23:45:13 -0700512 def verify_capture_in_ip6(self, capture, src_ip, dst_ip):
Matus Fabian06596c52017-06-06 04:53:28 -0700513 """
514 Verify captured IPv6 packets on inside network
515
516 :param capture: Captured packets
517 :param src_ip: Source IP
518 :param dst_ip: Destination IP address
Matus Fabian06596c52017-06-06 04:53:28 -0700519 """
Matus Fabian06596c52017-06-06 04:53:28 -0700520 for packet in capture:
521 try:
522 self.assertEqual(packet[IPv6].src, src_ip)
523 self.assertEqual(packet[IPv6].dst, dst_ip)
Klement Sekerad81ae412018-05-16 10:52:54 +0200524 self.assert_packet_checksums_valid(packet)
Matus Fabian06596c52017-06-06 04:53:28 -0700525 if packet.haslayer(TCP):
526 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
527 elif packet.haslayer(UDP):
528 self.assertEqual(packet[UDP].dport, self.udp_port_in)
529 else:
530 self.assertEqual(packet[ICMPv6EchoReply].id,
531 self.icmp_id_in)
532 except:
533 self.logger.error(ppp("Unexpected or invalid packet "
534 "(inside network):", packet))
535 raise
536
Matus Fabian675a69c2017-01-18 01:46:01 -0800537 def verify_capture_no_translation(self, capture, ingress_if, egress_if):
538 """
539 Verify captured packet that don't have to be translated
540
541 :param capture: Captured packets
542 :param ingress_if: Ingress interface
543 :param egress_if: Egress interface
544 """
545 for packet in capture:
546 try:
547 self.assertEqual(packet[IP].src, ingress_if.remote_ip4)
548 self.assertEqual(packet[IP].dst, egress_if.remote_ip4)
549 if packet.haslayer(TCP):
550 self.assertEqual(packet[TCP].sport, self.tcp_port_in)
551 elif packet.haslayer(UDP):
552 self.assertEqual(packet[UDP].sport, self.udp_port_in)
553 else:
554 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
555 except:
556 self.logger.error(ppp("Unexpected or invalid packet "
557 "(inside network):", packet))
558 raise
559
Juraj Slobodab33f4132017-02-08 23:54:21 -0800560 def verify_capture_out_with_icmp_errors(self, capture, src_ip=None,
Matus Fabian05ca4a32018-09-04 23:45:13 -0700561 icmp_type=11):
Juraj Slobodab33f4132017-02-08 23:54:21 -0800562 """
563 Verify captured packets with ICMP errors on outside network
564
565 :param capture: Captured packets
566 :param src_ip: Translated IP address or IP address of VPP
Matus Fabian2ba92e32017-08-21 07:05:03 -0700567 (Default use global NAT address)
Juraj Slobodab33f4132017-02-08 23:54:21 -0800568 :param icmp_type: Type of error ICMP packet
569 we are expecting (Default 11)
570 """
571 if src_ip is None:
Matus Fabian2ba92e32017-08-21 07:05:03 -0700572 src_ip = self.nat_addr
Juraj Slobodab33f4132017-02-08 23:54:21 -0800573 for packet in capture:
574 try:
575 self.assertEqual(packet[IP].src, src_ip)
576 self.assertTrue(packet.haslayer(ICMP))
577 icmp = packet[ICMP]
578 self.assertEqual(icmp.type, icmp_type)
579 self.assertTrue(icmp.haslayer(IPerror))
580 inner_ip = icmp[IPerror]
581 if inner_ip.haslayer(TCPerror):
582 self.assertEqual(inner_ip[TCPerror].dport,
583 self.tcp_port_out)
584 elif inner_ip.haslayer(UDPerror):
585 self.assertEqual(inner_ip[UDPerror].dport,
586 self.udp_port_out)
587 else:
588 self.assertEqual(inner_ip[ICMPerror].id, self.icmp_id_out)
589 except:
590 self.logger.error(ppp("Unexpected or invalid packet "
591 "(outside network):", packet))
592 raise
593
Matus Fabian05ca4a32018-09-04 23:45:13 -0700594 def verify_capture_in_with_icmp_errors(self, capture, in_if, icmp_type=11):
Juraj Slobodab33f4132017-02-08 23:54:21 -0800595 """
596 Verify captured packets with ICMP errors on inside network
597
598 :param capture: Captured packets
599 :param in_if: Inside interface
Juraj Slobodab33f4132017-02-08 23:54:21 -0800600 :param icmp_type: Type of error ICMP packet
601 we are expecting (Default 11)
602 """
Juraj Slobodab33f4132017-02-08 23:54:21 -0800603 for packet in capture:
604 try:
605 self.assertEqual(packet[IP].dst, in_if.remote_ip4)
606 self.assertTrue(packet.haslayer(ICMP))
607 icmp = packet[ICMP]
608 self.assertEqual(icmp.type, icmp_type)
609 self.assertTrue(icmp.haslayer(IPerror))
610 inner_ip = icmp[IPerror]
611 if inner_ip.haslayer(TCPerror):
612 self.assertEqual(inner_ip[TCPerror].sport,
613 self.tcp_port_in)
614 elif inner_ip.haslayer(UDPerror):
615 self.assertEqual(inner_ip[UDPerror].sport,
616 self.udp_port_in)
617 else:
618 self.assertEqual(inner_ip[ICMPerror].id, self.icmp_id_in)
619 except:
620 self.logger.error(ppp("Unexpected or invalid packet "
621 "(inside network):", packet))
622 raise
623
Matus Fabianefcd1e92017-08-15 06:59:19 -0700624 def create_stream_frag(self, src_if, dst, sport, dport, data):
625 """
626 Create fragmented packet stream
627
628 :param src_if: Source interface
629 :param dst: Destination IPv4 address
630 :param sport: Source TCP port
631 :param dport: Destination TCP port
632 :param data: Payload data
633 :returns: Fragmets
634 """
635 id = random.randint(0, 65535)
636 p = (IP(src=src_if.remote_ip4, dst=dst) /
637 TCP(sport=sport, dport=dport) /
638 Raw(data))
639 p = p.__class__(str(p))
640 chksum = p['TCP'].chksum
641 pkts = []
642 p = (Ether(src=src_if.remote_mac, dst=src_if.local_mac) /
643 IP(src=src_if.remote_ip4, dst=dst, flags="MF", frag=0, id=id) /
644 TCP(sport=sport, dport=dport, chksum=chksum) /
645 Raw(data[0:4]))
646 pkts.append(p)
647 p = (Ether(src=src_if.remote_mac, dst=src_if.local_mac) /
648 IP(src=src_if.remote_ip4, dst=dst, flags="MF", frag=3, id=id,
649 proto=IP_PROTOS.tcp) /
650 Raw(data[4:20]))
651 pkts.append(p)
652 p = (Ether(src=src_if.remote_mac, dst=src_if.local_mac) /
653 IP(src=src_if.remote_ip4, dst=dst, frag=5, proto=IP_PROTOS.tcp,
654 id=id) /
655 Raw(data[20:]))
656 pkts.append(p)
657 return pkts
658
659 def create_stream_frag_ip6(self, src_if, dst, sport, dport, data,
660 pref=None, plen=0, frag_size=128):
661 """
662 Create fragmented packet stream
663
664 :param src_if: Source interface
665 :param dst: Destination IPv4 address
666 :param sport: Source TCP port
667 :param dport: Destination TCP port
668 :param data: Payload data
669 :param pref: NAT64 prefix
670 :param plen: NAT64 prefix length
671 :param fragsize: size of fragments
672 :returns: Fragmets
673 """
674 if pref is None:
675 dst_ip6 = ''.join(['64:ff9b::', dst])
676 else:
677 dst_ip6 = self.compose_ip6(dst, pref, plen)
678
679 p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
680 IPv6(src=src_if.remote_ip6, dst=dst_ip6) /
681 IPv6ExtHdrFragment(id=random.randint(0, 65535)) /
682 TCP(sport=sport, dport=dport) /
683 Raw(data))
684
685 return fragment6(p, frag_size)
686
687 def reass_frags_and_verify(self, frags, src, dst):
688 """
689 Reassemble and verify fragmented packet
690
691 :param frags: Captured fragments
692 :param src: Source IPv4 address to verify
693 :param dst: Destination IPv4 address to verify
694
695 :returns: Reassembled IPv4 packet
696 """
697 buffer = StringIO.StringIO()
698 for p in frags:
699 self.assertEqual(p[IP].src, src)
700 self.assertEqual(p[IP].dst, dst)
Klement Sekerad81ae412018-05-16 10:52:54 +0200701 self.assert_ip_checksum_valid(p)
Matus Fabianefcd1e92017-08-15 06:59:19 -0700702 buffer.seek(p[IP].frag * 8)
703 buffer.write(p[IP].payload)
704 ip = frags[0].getlayer(IP)
705 ip = IP(src=frags[0][IP].src, dst=frags[0][IP].dst,
706 proto=frags[0][IP].proto)
707 if ip.proto == IP_PROTOS.tcp:
708 p = (ip / TCP(buffer.getvalue()))
Klement Sekerad81ae412018-05-16 10:52:54 +0200709 self.assert_tcp_checksum_valid(p)
Matus Fabianefcd1e92017-08-15 06:59:19 -0700710 elif ip.proto == IP_PROTOS.udp:
711 p = (ip / UDP(buffer.getvalue()))
712 return p
713
714 def reass_frags_and_verify_ip6(self, frags, src, dst):
715 """
716 Reassemble and verify fragmented packet
717
718 :param frags: Captured fragments
719 :param src: Source IPv6 address to verify
720 :param dst: Destination IPv6 address to verify
721
722 :returns: Reassembled IPv6 packet
723 """
724 buffer = StringIO.StringIO()
725 for p in frags:
726 self.assertEqual(p[IPv6].src, src)
727 self.assertEqual(p[IPv6].dst, dst)
728 buffer.seek(p[IPv6ExtHdrFragment].offset * 8)
729 buffer.write(p[IPv6ExtHdrFragment].payload)
730 ip = IPv6(src=frags[0][IPv6].src, dst=frags[0][IPv6].dst,
731 nh=frags[0][IPv6ExtHdrFragment].nh)
732 if ip.nh == IP_PROTOS.tcp:
733 p = (ip / TCP(buffer.getvalue()))
Matus Fabianefcd1e92017-08-15 06:59:19 -0700734 elif ip.nh == IP_PROTOS.udp:
735 p = (ip / UDP(buffer.getvalue()))
Klement Sekerad81ae412018-05-16 10:52:54 +0200736 self.assert_packet_checksums_valid(p)
Matus Fabianefcd1e92017-08-15 06:59:19 -0700737 return p
738
Matus Fabianebdf1902018-05-04 03:57:42 -0700739 def initiate_tcp_session(self, in_if, out_if):
740 """
741 Initiates TCP session
742
743 :param in_if: Inside interface
744 :param out_if: Outside interface
745 """
746 try:
747 # SYN packet in->out
748 p = (Ether(src=in_if.remote_mac, dst=in_if.local_mac) /
749 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4) /
750 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
751 flags="S"))
752 in_if.add_stream(p)
753 self.pg_enable_capture(self.pg_interfaces)
754 self.pg_start()
755 capture = out_if.get_capture(1)
756 p = capture[0]
757 self.tcp_port_out = p[TCP].sport
758
759 # SYN + ACK packet out->in
760 p = (Ether(src=out_if.remote_mac, dst=out_if.local_mac) /
761 IP(src=out_if.remote_ip4, dst=self.nat_addr) /
762 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
763 flags="SA"))
764 out_if.add_stream(p)
765 self.pg_enable_capture(self.pg_interfaces)
766 self.pg_start()
767 in_if.get_capture(1)
768
769 # ACK packet in->out
770 p = (Ether(src=in_if.remote_mac, dst=in_if.local_mac) /
771 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4) /
772 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
773 flags="A"))
774 in_if.add_stream(p)
775 self.pg_enable_capture(self.pg_interfaces)
776 self.pg_start()
777 out_if.get_capture(1)
778
779 except:
780 self.logger.error("TCP 3 way handshake failed")
781 raise
782
Matus Fabianeea28d72017-01-13 04:15:54 -0800783 def verify_ipfix_nat44_ses(self, data):
784 """
785 Verify IPFIX NAT44 session create/delete event
786
787 :param data: Decoded IPFIX data records
788 """
789 nat44_ses_create_num = 0
790 nat44_ses_delete_num = 0
791 self.assertEqual(6, len(data))
792 for record in data:
793 # natEvent
794 self.assertIn(ord(record[230]), [4, 5])
795 if ord(record[230]) == 4:
796 nat44_ses_create_num += 1
797 else:
798 nat44_ses_delete_num += 1
799 # sourceIPv4Address
800 self.assertEqual(self.pg0.remote_ip4n, record[8])
801 # postNATSourceIPv4Address
Matus Fabian2ba92e32017-08-21 07:05:03 -0700802 self.assertEqual(socket.inet_pton(socket.AF_INET, self.nat_addr),
Matus Fabianeea28d72017-01-13 04:15:54 -0800803 record[225])
804 # ingressVRFID
805 self.assertEqual(struct.pack("!I", 0), record[234])
806 # protocolIdentifier/sourceTransportPort/postNAPTSourceTransportPort
807 if IP_PROTOS.icmp == ord(record[4]):
808 self.assertEqual(struct.pack("!H", self.icmp_id_in), record[7])
809 self.assertEqual(struct.pack("!H", self.icmp_id_out),
810 record[227])
811 elif IP_PROTOS.tcp == ord(record[4]):
812 self.assertEqual(struct.pack("!H", self.tcp_port_in),
813 record[7])
814 self.assertEqual(struct.pack("!H", self.tcp_port_out),
815 record[227])
816 elif IP_PROTOS.udp == ord(record[4]):
817 self.assertEqual(struct.pack("!H", self.udp_port_in),
818 record[7])
819 self.assertEqual(struct.pack("!H", self.udp_port_out),
820 record[227])
821 else:
822 self.fail("Invalid protocol")
823 self.assertEqual(3, nat44_ses_create_num)
824 self.assertEqual(3, nat44_ses_delete_num)
825
826 def verify_ipfix_addr_exhausted(self, data):
827 """
828 Verify IPFIX NAT addresses event
829
830 :param data: Decoded IPFIX data records
831 """
832 self.assertEqual(1, len(data))
833 record = data[0]
834 # natEvent
835 self.assertEqual(ord(record[230]), 3)
836 # natPoolID
837 self.assertEqual(struct.pack("!I", 0), record[283])
838
Matus Fabiana431ad12018-01-04 04:03:14 -0800839 def verify_ipfix_max_sessions(self, data, limit):
840 """
841 Verify IPFIX maximum session entries exceeded event
842
843 :param data: Decoded IPFIX data records
844 :param limit: Number of maximum session entries that can be created.
845 """
846 self.assertEqual(1, len(data))
847 record = data[0]
848 # natEvent
849 self.assertEqual(ord(record[230]), 13)
850 # natQuotaExceededEvent
851 self.assertEqual(struct.pack("I", 1), record[466])
852 # maxSessionEntries
853 self.assertEqual(struct.pack("I", limit), record[471])
854
855 def verify_ipfix_max_bibs(self, data, limit):
856 """
857 Verify IPFIX maximum BIB entries exceeded event
858
859 :param data: Decoded IPFIX data records
860 :param limit: Number of maximum BIB entries that can be created.
861 """
862 self.assertEqual(1, len(data))
863 record = data[0]
864 # natEvent
865 self.assertEqual(ord(record[230]), 13)
866 # natQuotaExceededEvent
867 self.assertEqual(struct.pack("I", 2), record[466])
868 # maxBIBEntries
869 self.assertEqual(struct.pack("I", limit), record[472])
870
871 def verify_ipfix_max_fragments_ip6(self, data, limit, src_addr):
872 """
873 Verify IPFIX maximum IPv6 fragments pending reassembly exceeded event
874
875 :param data: Decoded IPFIX data records
876 :param limit: Number of maximum fragments pending reassembly
877 :param src_addr: IPv6 source address
878 """
879 self.assertEqual(1, len(data))
880 record = data[0]
881 # natEvent
882 self.assertEqual(ord(record[230]), 13)
883 # natQuotaExceededEvent
884 self.assertEqual(struct.pack("I", 5), record[466])
885 # maxFragmentsPendingReassembly
886 self.assertEqual(struct.pack("I", limit), record[475])
887 # sourceIPv6Address
888 self.assertEqual(src_addr, record[27])
889
890 def verify_ipfix_max_fragments_ip4(self, data, limit, src_addr):
891 """
892 Verify IPFIX maximum IPv4 fragments pending reassembly exceeded event
893
894 :param data: Decoded IPFIX data records
895 :param limit: Number of maximum fragments pending reassembly
896 :param src_addr: IPv4 source address
897 """
898 self.assertEqual(1, len(data))
899 record = data[0]
900 # natEvent
901 self.assertEqual(ord(record[230]), 13)
902 # natQuotaExceededEvent
903 self.assertEqual(struct.pack("I", 5), record[466])
904 # maxFragmentsPendingReassembly
905 self.assertEqual(struct.pack("I", limit), record[475])
906 # sourceIPv4Address
907 self.assertEqual(src_addr, record[8])
908
909 def verify_ipfix_bib(self, data, is_create, src_addr):
910 """
911 Verify IPFIX NAT64 BIB create and delete events
912
913 :param data: Decoded IPFIX data records
914 :param is_create: Create event if nonzero value otherwise delete event
915 :param src_addr: IPv6 source address
916 """
917 self.assertEqual(1, len(data))
918 record = data[0]
919 # natEvent
920 if is_create:
921 self.assertEqual(ord(record[230]), 10)
922 else:
923 self.assertEqual(ord(record[230]), 11)
924 # sourceIPv6Address
925 self.assertEqual(src_addr, record[27])
926 # postNATSourceIPv4Address
927 self.assertEqual(self.nat_addr_n, record[225])
928 # protocolIdentifier
929 self.assertEqual(IP_PROTOS.tcp, ord(record[4]))
930 # ingressVRFID
931 self.assertEqual(struct.pack("!I", 0), record[234])
932 # sourceTransportPort
933 self.assertEqual(struct.pack("!H", self.tcp_port_in), record[7])
934 # postNAPTSourceTransportPort
935 self.assertEqual(struct.pack("!H", self.tcp_port_out), record[227])
936
937 def verify_ipfix_nat64_ses(self, data, is_create, src_addr, dst_addr,
938 dst_port):
939 """
940 Verify IPFIX NAT64 session create and delete events
941
942 :param data: Decoded IPFIX data records
943 :param is_create: Create event if nonzero value otherwise delete event
944 :param src_addr: IPv6 source address
945 :param dst_addr: IPv4 destination address
946 :param dst_port: destination TCP port
947 """
948 self.assertEqual(1, len(data))
949 record = data[0]
950 # natEvent
951 if is_create:
952 self.assertEqual(ord(record[230]), 6)
953 else:
954 self.assertEqual(ord(record[230]), 7)
955 # sourceIPv6Address
956 self.assertEqual(src_addr, record[27])
957 # destinationIPv6Address
958 self.assertEqual(socket.inet_pton(socket.AF_INET6,
959 self.compose_ip6(dst_addr,
960 '64:ff9b::',
961 96)),
962 record[28])
963 # postNATSourceIPv4Address
964 self.assertEqual(self.nat_addr_n, record[225])
965 # postNATDestinationIPv4Address
966 self.assertEqual(socket.inet_pton(socket.AF_INET, dst_addr),
967 record[226])
968 # protocolIdentifier
969 self.assertEqual(IP_PROTOS.tcp, ord(record[4]))
970 # ingressVRFID
971 self.assertEqual(struct.pack("!I", 0), record[234])
972 # sourceTransportPort
973 self.assertEqual(struct.pack("!H", self.tcp_port_in), record[7])
974 # postNAPTSourceTransportPort
975 self.assertEqual(struct.pack("!H", self.tcp_port_out), record[227])
976 # destinationTransportPort
977 self.assertEqual(struct.pack("!H", dst_port), record[11])
978 # postNAPTDestinationTransportPort
979 self.assertEqual(struct.pack("!H", dst_port), record[228])
980
Matus Fabian68ba8802018-08-08 05:52:47 -0700981 def verify_no_nat44_user(self):
982 """ Verify that there is no NAT44 user """
983 users = self.vapi.nat44_user_dump()
984 self.assertEqual(len(users), 0)
985
Matus Fabian878c6462018-08-23 00:33:35 -0700986 def verify_ipfix_max_entries_per_user(self, data, limit, src_addr):
987 """
988 Verify IPFIX maximum entries per user exceeded event
989
990 :param data: Decoded IPFIX data records
991 :param limit: Number of maximum entries per user
992 :param src_addr: IPv4 source address
993 """
994 self.assertEqual(1, len(data))
995 record = data[0]
996 # natEvent
997 self.assertEqual(ord(record[230]), 13)
998 # natQuotaExceededEvent
999 self.assertEqual(struct.pack("I", 3), record[466])
1000 # maxEntriesPerUser
1001 self.assertEqual(struct.pack("I", limit), record[473])
1002 # sourceIPv4Address
1003 self.assertEqual(src_addr, record[8])
1004
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001005
Matus Fabian2ba92e32017-08-21 07:05:03 -07001006class TestNAT44(MethodHolder):
1007 """ NAT44 Test Cases """
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001008
1009 @classmethod
1010 def setUpClass(cls):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001011 super(TestNAT44, cls).setUpClass()
Matus Fabian229c1aa2018-05-28 04:09:52 -07001012 cls.vapi.cli("set log class nat level debug")
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001013
1014 try:
1015 cls.tcp_port_in = 6303
1016 cls.tcp_port_out = 6303
1017 cls.udp_port_in = 6304
1018 cls.udp_port_out = 6304
1019 cls.icmp_id_in = 6305
1020 cls.icmp_id_out = 6305
Matus Fabian2ba92e32017-08-21 07:05:03 -07001021 cls.nat_addr = '10.0.0.3'
Juraj Sloboda7b929792017-11-23 13:20:48 +01001022 cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
Matus Fabian6631e9c2017-05-24 01:52:20 -07001023 cls.ipfix_src_port = 4739
1024 cls.ipfix_domain_id = 1
Matus Fabianebdf1902018-05-04 03:57:42 -07001025 cls.tcp_external_port = 80
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001026
Matus Fabian36ea2d62017-10-24 04:13:49 -07001027 cls.create_pg_interfaces(range(10))
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001028 cls.interfaces = list(cls.pg_interfaces[0:4])
1029
1030 for i in cls.interfaces:
1031 i.admin_up()
1032 i.config_ip4()
1033 i.resolve_arp()
1034
Matus Fabian6fa74c62017-06-05 05:55:48 -07001035 cls.pg0.generate_remote_hosts(3)
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001036 cls.pg0.configure_ipv4_neighbors()
1037
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02001038 cls.pg1.generate_remote_hosts(1)
1039 cls.pg1.configure_ipv4_neighbors()
1040
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001041 cls.overlapping_interfaces = list(list(cls.pg_interfaces[4:7]))
Neale Ranns15002542017-09-10 04:39:11 -07001042 cls.vapi.ip_table_add_del(10, is_add=1)
1043 cls.vapi.ip_table_add_del(20, is_add=1)
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001044
1045 cls.pg4._local_ip4 = "172.16.255.1"
1046 cls.pg4._local_ip4n = socket.inet_pton(socket.AF_INET, i.local_ip4)
1047 cls.pg4._remote_hosts[0]._ip4 = "172.16.255.2"
1048 cls.pg4.set_table_ip4(10)
Matus Fabian69126282017-08-14 23:39:58 -07001049 cls.pg5._local_ip4 = "172.17.255.3"
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001050 cls.pg5._local_ip4n = socket.inet_pton(socket.AF_INET, i.local_ip4)
Matus Fabian69126282017-08-14 23:39:58 -07001051 cls.pg5._remote_hosts[0]._ip4 = "172.17.255.4"
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001052 cls.pg5.set_table_ip4(10)
1053 cls.pg6._local_ip4 = "172.16.255.1"
1054 cls.pg6._local_ip4n = socket.inet_pton(socket.AF_INET, i.local_ip4)
1055 cls.pg6._remote_hosts[0]._ip4 = "172.16.255.2"
1056 cls.pg6.set_table_ip4(20)
1057 for i in cls.overlapping_interfaces:
1058 i.config_ip4()
1059 i.admin_up()
1060 i.resolve_arp()
1061
1062 cls.pg7.admin_up()
Martin Gálik406eb1d2017-05-04 04:35:04 -07001063 cls.pg8.admin_up()
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001064
Matus Fabian36ea2d62017-10-24 04:13:49 -07001065 cls.pg9.generate_remote_hosts(2)
1066 cls.pg9.config_ip4()
1067 ip_addr_n = socket.inet_pton(socket.AF_INET, "10.0.0.1")
1068 cls.vapi.sw_interface_add_del_address(cls.pg9.sw_if_index,
1069 ip_addr_n,
1070 24)
1071 cls.pg9.admin_up()
1072 cls.pg9.resolve_arp()
1073 cls.pg9._remote_hosts[1]._ip4 = cls.pg9._remote_hosts[0]._ip4
1074 cls.pg4._remote_ip4 = cls.pg9._remote_hosts[0]._ip4 = "10.0.0.2"
1075 cls.pg9.resolve_arp()
1076
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001077 except Exception:
Matus Fabian2ba92e32017-08-21 07:05:03 -07001078 super(TestNAT44, cls).tearDownClass()
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001079 raise
1080
Matus Fabiande886752016-12-07 03:38:19 -08001081 def test_dynamic(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001082 """ NAT44 dynamic translation test """
Matus Fabiande886752016-12-07 03:38:19 -08001083
Matus Fabian2ba92e32017-08-21 07:05:03 -07001084 self.nat44_add_address(self.nat_addr)
1085 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1086 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1087 is_inside=0)
Matus Fabiande886752016-12-07 03:38:19 -08001088
1089 # in2out
1090 pkts = self.create_stream_in(self.pg0, self.pg1)
1091 self.pg0.add_stream(pkts)
1092 self.pg_enable_capture(self.pg_interfaces)
1093 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001094 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001095 self.verify_capture_out(capture)
1096
1097 # out2in
1098 pkts = self.create_stream_out(self.pg1)
1099 self.pg1.add_stream(pkts)
1100 self.pg_enable_capture(self.pg_interfaces)
1101 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001102 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001103 self.verify_capture_in(capture, self.pg0)
1104
Juraj Slobodab33f4132017-02-08 23:54:21 -08001105 def test_dynamic_icmp_errors_in2out_ttl_1(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001106 """ NAT44 handling of client packets with TTL=1 """
Juraj Slobodab33f4132017-02-08 23:54:21 -08001107
Matus Fabian2ba92e32017-08-21 07:05:03 -07001108 self.nat44_add_address(self.nat_addr)
1109 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1110 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1111 is_inside=0)
Juraj Slobodab33f4132017-02-08 23:54:21 -08001112
1113 # Client side - generate traffic
1114 pkts = self.create_stream_in(self.pg0, self.pg1, ttl=1)
1115 self.pg0.add_stream(pkts)
1116 self.pg_enable_capture(self.pg_interfaces)
1117 self.pg_start()
1118
1119 # Client side - verify ICMP type 11 packets
1120 capture = self.pg0.get_capture(len(pkts))
1121 self.verify_capture_in_with_icmp_errors(capture, self.pg0)
1122
1123 def test_dynamic_icmp_errors_out2in_ttl_1(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001124 """ NAT44 handling of server packets with TTL=1 """
Juraj Slobodab33f4132017-02-08 23:54:21 -08001125
Matus Fabian2ba92e32017-08-21 07:05:03 -07001126 self.nat44_add_address(self.nat_addr)
1127 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1128 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1129 is_inside=0)
Juraj Slobodab33f4132017-02-08 23:54:21 -08001130
1131 # Client side - create sessions
1132 pkts = self.create_stream_in(self.pg0, self.pg1)
1133 self.pg0.add_stream(pkts)
1134 self.pg_enable_capture(self.pg_interfaces)
1135 self.pg_start()
1136
1137 # Server side - generate traffic
1138 capture = self.pg1.get_capture(len(pkts))
1139 self.verify_capture_out(capture)
1140 pkts = self.create_stream_out(self.pg1, ttl=1)
1141 self.pg1.add_stream(pkts)
1142 self.pg_enable_capture(self.pg_interfaces)
1143 self.pg_start()
1144
1145 # Server side - verify ICMP type 11 packets
1146 capture = self.pg1.get_capture(len(pkts))
1147 self.verify_capture_out_with_icmp_errors(capture,
1148 src_ip=self.pg1.local_ip4)
1149
1150 def test_dynamic_icmp_errors_in2out_ttl_2(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001151 """ NAT44 handling of error responses to client packets with TTL=2 """
Juraj Slobodab33f4132017-02-08 23:54:21 -08001152
Matus Fabian2ba92e32017-08-21 07:05:03 -07001153 self.nat44_add_address(self.nat_addr)
1154 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1155 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1156 is_inside=0)
Juraj Slobodab33f4132017-02-08 23:54:21 -08001157
1158 # Client side - generate traffic
1159 pkts = self.create_stream_in(self.pg0, self.pg1, ttl=2)
1160 self.pg0.add_stream(pkts)
1161 self.pg_enable_capture(self.pg_interfaces)
1162 self.pg_start()
1163
1164 # Server side - simulate ICMP type 11 response
1165 capture = self.pg1.get_capture(len(pkts))
1166 pkts = [Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07001167 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Juraj Slobodab33f4132017-02-08 23:54:21 -08001168 ICMP(type=11) / packet[IP] for packet in capture]
1169 self.pg1.add_stream(pkts)
1170 self.pg_enable_capture(self.pg_interfaces)
1171 self.pg_start()
1172
1173 # Client side - verify ICMP type 11 packets
1174 capture = self.pg0.get_capture(len(pkts))
1175 self.verify_capture_in_with_icmp_errors(capture, self.pg0)
1176
1177 def test_dynamic_icmp_errors_out2in_ttl_2(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001178 """ NAT44 handling of error responses to server packets with TTL=2 """
Juraj Slobodab33f4132017-02-08 23:54:21 -08001179
Matus Fabian2ba92e32017-08-21 07:05:03 -07001180 self.nat44_add_address(self.nat_addr)
1181 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1182 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1183 is_inside=0)
Juraj Slobodab33f4132017-02-08 23:54:21 -08001184
1185 # Client side - create sessions
1186 pkts = self.create_stream_in(self.pg0, self.pg1)
1187 self.pg0.add_stream(pkts)
1188 self.pg_enable_capture(self.pg_interfaces)
1189 self.pg_start()
1190
1191 # Server side - generate traffic
1192 capture = self.pg1.get_capture(len(pkts))
1193 self.verify_capture_out(capture)
1194 pkts = self.create_stream_out(self.pg1, ttl=2)
1195 self.pg1.add_stream(pkts)
1196 self.pg_enable_capture(self.pg_interfaces)
1197 self.pg_start()
1198
1199 # Client side - simulate ICMP type 11 response
1200 capture = self.pg0.get_capture(len(pkts))
1201 pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1202 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
1203 ICMP(type=11) / packet[IP] for packet in capture]
1204 self.pg0.add_stream(pkts)
1205 self.pg_enable_capture(self.pg_interfaces)
1206 self.pg_start()
1207
1208 # Server side - verify ICMP type 11 packets
1209 capture = self.pg1.get_capture(len(pkts))
1210 self.verify_capture_out_with_icmp_errors(capture)
1211
Juraj Sloboda665e4822017-02-16 17:17:19 -08001212 def test_ping_out_interface_from_outside(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001213 """ Ping NAT44 out interface from outside network """
Juraj Sloboda665e4822017-02-16 17:17:19 -08001214
Matus Fabian2ba92e32017-08-21 07:05:03 -07001215 self.nat44_add_address(self.nat_addr)
1216 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1217 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1218 is_inside=0)
Juraj Sloboda665e4822017-02-16 17:17:19 -08001219
1220 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1221 IP(src=self.pg1.remote_ip4, dst=self.pg1.local_ip4) /
1222 ICMP(id=self.icmp_id_out, type='echo-request'))
1223 pkts = [p]
1224 self.pg1.add_stream(pkts)
1225 self.pg_enable_capture(self.pg_interfaces)
1226 self.pg_start()
1227 capture = self.pg1.get_capture(len(pkts))
Juraj Sloboda665e4822017-02-16 17:17:19 -08001228 packet = capture[0]
1229 try:
1230 self.assertEqual(packet[IP].src, self.pg1.local_ip4)
1231 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
1232 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
1233 self.assertEqual(packet[ICMP].type, 0) # echo reply
1234 except:
1235 self.logger.error(ppp("Unexpected or invalid packet "
1236 "(outside network):", packet))
1237 raise
1238
Juraj Slobodad3677682017-04-14 03:24:45 +02001239 def test_ping_internal_host_from_outside(self):
1240 """ Ping internal host from outside network """
1241
Matus Fabian2ba92e32017-08-21 07:05:03 -07001242 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr)
1243 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1244 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1245 is_inside=0)
Juraj Slobodad3677682017-04-14 03:24:45 +02001246
1247 # out2in
1248 pkt = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07001249 IP(src=self.pg1.remote_ip4, dst=self.nat_addr, ttl=64) /
Juraj Slobodad3677682017-04-14 03:24:45 +02001250 ICMP(id=self.icmp_id_out, type='echo-request'))
1251 self.pg1.add_stream(pkt)
1252 self.pg_enable_capture(self.pg_interfaces)
1253 self.pg_start()
1254 capture = self.pg0.get_capture(1)
Matus Fabian05ca4a32018-09-04 23:45:13 -07001255 self.verify_capture_in(capture, self.pg0)
Juraj Slobodad3677682017-04-14 03:24:45 +02001256 self.assert_equal(capture[0][IP].proto, IP_PROTOS.icmp)
1257
1258 # in2out
1259 pkt = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1260 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4, ttl=64) /
1261 ICMP(id=self.icmp_id_in, type='echo-reply'))
1262 self.pg0.add_stream(pkt)
1263 self.pg_enable_capture(self.pg_interfaces)
1264 self.pg_start()
1265 capture = self.pg1.get_capture(1)
Matus Fabian05ca4a32018-09-04 23:45:13 -07001266 self.verify_capture_out(capture, same_port=True)
Juraj Slobodad3677682017-04-14 03:24:45 +02001267 self.assert_equal(capture[0][IP].proto, IP_PROTOS.icmp)
1268
Matus Fabianc79396e2018-07-23 00:05:22 -07001269 def test_forwarding(self):
Juraj Sloboda7b929792017-11-23 13:20:48 +01001270 """ NAT44 forwarding test """
1271
1272 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1273 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1274 is_inside=0)
1275 self.vapi.nat44_forwarding_enable_disable(1)
1276
1277 real_ip = self.pg0.remote_ip4n
1278 alias_ip = self.nat_addr_n
1279 self.vapi.nat44_add_del_static_mapping(local_ip=real_ip,
1280 external_ip=alias_ip)
1281
1282 try:
Matus Fabianc79396e2018-07-23 00:05:22 -07001283 # static mapping match
Juraj Sloboda7b929792017-11-23 13:20:48 +01001284
1285 pkts = self.create_stream_out(self.pg1)
1286 self.pg1.add_stream(pkts)
1287 self.pg_enable_capture(self.pg_interfaces)
1288 self.pg_start()
1289 capture = self.pg0.get_capture(len(pkts))
1290 self.verify_capture_in(capture, self.pg0)
1291
1292 pkts = self.create_stream_in(self.pg0, self.pg1)
1293 self.pg0.add_stream(pkts)
1294 self.pg_enable_capture(self.pg_interfaces)
1295 self.pg_start()
1296 capture = self.pg1.get_capture(len(pkts))
1297 self.verify_capture_out(capture, same_port=True)
1298
Matus Fabianc79396e2018-07-23 00:05:22 -07001299 # no static mapping match
Juraj Sloboda7b929792017-11-23 13:20:48 +01001300
1301 host0 = self.pg0.remote_hosts[0]
1302 self.pg0.remote_hosts[0] = self.pg0.remote_hosts[1]
1303 try:
1304 pkts = self.create_stream_out(self.pg1,
1305 dst_ip=self.pg0.remote_ip4,
1306 use_inside_ports=True)
1307 self.pg1.add_stream(pkts)
1308 self.pg_enable_capture(self.pg_interfaces)
1309 self.pg_start()
1310 capture = self.pg0.get_capture(len(pkts))
1311 self.verify_capture_in(capture, self.pg0)
1312
1313 pkts = self.create_stream_in(self.pg0, self.pg1)
1314 self.pg0.add_stream(pkts)
1315 self.pg_enable_capture(self.pg_interfaces)
1316 self.pg_start()
1317 capture = self.pg1.get_capture(len(pkts))
1318 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
1319 same_port=True)
1320 finally:
1321 self.pg0.remote_hosts[0] = host0
1322
1323 finally:
1324 self.vapi.nat44_forwarding_enable_disable(0)
1325 self.vapi.nat44_add_del_static_mapping(local_ip=real_ip,
1326 external_ip=alias_ip,
1327 is_add=0)
1328
Matus Fabiande886752016-12-07 03:38:19 -08001329 def test_static_in(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001330 """ 1:1 NAT initialized from inside network """
Matus Fabiande886752016-12-07 03:38:19 -08001331
1332 nat_ip = "10.0.0.10"
1333 self.tcp_port_out = 6303
1334 self.udp_port_out = 6304
1335 self.icmp_id_out = 6305
1336
Matus Fabian2ba92e32017-08-21 07:05:03 -07001337 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
1338 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1339 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1340 is_inside=0)
Matus Fabian5f224992018-01-25 21:59:16 -08001341 sm = self.vapi.nat44_static_mapping_dump()
1342 self.assertEqual(len(sm), 1)
1343 self.assertEqual((sm[0].tag).split('\0', 1)[0], '')
Matus Fabian9dba7812018-01-31 01:13:23 -08001344 self.assertEqual(sm[0].protocol, 0)
1345 self.assertEqual(sm[0].local_port, 0)
1346 self.assertEqual(sm[0].external_port, 0)
Matus Fabiande886752016-12-07 03:38:19 -08001347
1348 # in2out
1349 pkts = self.create_stream_in(self.pg0, self.pg1)
1350 self.pg0.add_stream(pkts)
1351 self.pg_enable_capture(self.pg_interfaces)
1352 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001353 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001354 self.verify_capture_out(capture, nat_ip, True)
1355
1356 # out2in
1357 pkts = self.create_stream_out(self.pg1, nat_ip)
1358 self.pg1.add_stream(pkts)
1359 self.pg_enable_capture(self.pg_interfaces)
1360 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001361 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001362 self.verify_capture_in(capture, self.pg0)
1363
1364 def test_static_out(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001365 """ 1:1 NAT initialized from outside network """
Matus Fabiande886752016-12-07 03:38:19 -08001366
1367 nat_ip = "10.0.0.20"
1368 self.tcp_port_out = 6303
1369 self.udp_port_out = 6304
1370 self.icmp_id_out = 6305
Matus Fabian5f224992018-01-25 21:59:16 -08001371 tag = "testTAG"
Matus Fabiande886752016-12-07 03:38:19 -08001372
Matus Fabian5f224992018-01-25 21:59:16 -08001373 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip, tag=tag)
Matus Fabian2ba92e32017-08-21 07:05:03 -07001374 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1375 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1376 is_inside=0)
Matus Fabian5f224992018-01-25 21:59:16 -08001377 sm = self.vapi.nat44_static_mapping_dump()
1378 self.assertEqual(len(sm), 1)
1379 self.assertEqual((sm[0].tag).split('\0', 1)[0], tag)
Matus Fabiande886752016-12-07 03:38:19 -08001380
1381 # out2in
1382 pkts = self.create_stream_out(self.pg1, nat_ip)
1383 self.pg1.add_stream(pkts)
1384 self.pg_enable_capture(self.pg_interfaces)
1385 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001386 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001387 self.verify_capture_in(capture, self.pg0)
1388
1389 # in2out
1390 pkts = self.create_stream_in(self.pg0, self.pg1)
1391 self.pg0.add_stream(pkts)
1392 self.pg_enable_capture(self.pg_interfaces)
1393 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001394 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001395 self.verify_capture_out(capture, nat_ip, True)
1396
1397 def test_static_with_port_in(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001398 """ 1:1 NAPT initialized from inside network """
Matus Fabiande886752016-12-07 03:38:19 -08001399
1400 self.tcp_port_out = 3606
1401 self.udp_port_out = 3607
1402 self.icmp_id_out = 3608
1403
Matus Fabian2ba92e32017-08-21 07:05:03 -07001404 self.nat44_add_address(self.nat_addr)
1405 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1406 self.tcp_port_in, self.tcp_port_out,
1407 proto=IP_PROTOS.tcp)
1408 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1409 self.udp_port_in, self.udp_port_out,
1410 proto=IP_PROTOS.udp)
1411 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1412 self.icmp_id_in, self.icmp_id_out,
1413 proto=IP_PROTOS.icmp)
1414 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1415 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1416 is_inside=0)
Matus Fabiande886752016-12-07 03:38:19 -08001417
1418 # in2out
1419 pkts = self.create_stream_in(self.pg0, self.pg1)
1420 self.pg0.add_stream(pkts)
1421 self.pg_enable_capture(self.pg_interfaces)
1422 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001423 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001424 self.verify_capture_out(capture)
1425
1426 # out2in
1427 pkts = self.create_stream_out(self.pg1)
1428 self.pg1.add_stream(pkts)
1429 self.pg_enable_capture(self.pg_interfaces)
1430 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001431 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001432 self.verify_capture_in(capture, self.pg0)
1433
1434 def test_static_with_port_out(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001435 """ 1:1 NAPT initialized from outside network """
Matus Fabiande886752016-12-07 03:38:19 -08001436
1437 self.tcp_port_out = 30606
1438 self.udp_port_out = 30607
1439 self.icmp_id_out = 30608
1440
Matus Fabian2ba92e32017-08-21 07:05:03 -07001441 self.nat44_add_address(self.nat_addr)
1442 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1443 self.tcp_port_in, self.tcp_port_out,
1444 proto=IP_PROTOS.tcp)
1445 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1446 self.udp_port_in, self.udp_port_out,
1447 proto=IP_PROTOS.udp)
1448 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1449 self.icmp_id_in, self.icmp_id_out,
1450 proto=IP_PROTOS.icmp)
1451 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1452 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1453 is_inside=0)
Matus Fabiande886752016-12-07 03:38:19 -08001454
1455 # out2in
1456 pkts = self.create_stream_out(self.pg1)
1457 self.pg1.add_stream(pkts)
1458 self.pg_enable_capture(self.pg_interfaces)
1459 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001460 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001461 self.verify_capture_in(capture, self.pg0)
1462
1463 # in2out
1464 pkts = self.create_stream_in(self.pg0, self.pg1)
1465 self.pg0.add_stream(pkts)
1466 self.pg_enable_capture(self.pg_interfaces)
1467 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001468 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001469 self.verify_capture_out(capture)
1470
1471 def test_static_vrf_aware(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001472 """ 1:1 NAT VRF awareness """
Matus Fabiande886752016-12-07 03:38:19 -08001473
1474 nat_ip1 = "10.0.0.30"
1475 nat_ip2 = "10.0.0.40"
1476 self.tcp_port_out = 6303
1477 self.udp_port_out = 6304
1478 self.icmp_id_out = 6305
1479
Matus Fabian2ba92e32017-08-21 07:05:03 -07001480 self.nat44_add_static_mapping(self.pg4.remote_ip4, nat_ip1,
1481 vrf_id=10)
1482 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip2,
1483 vrf_id=10)
1484 self.vapi.nat44_interface_add_del_feature(self.pg3.sw_if_index,
1485 is_inside=0)
1486 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1487 self.vapi.nat44_interface_add_del_feature(self.pg4.sw_if_index)
Matus Fabiande886752016-12-07 03:38:19 -08001488
Matus Fabian2ba92e32017-08-21 07:05:03 -07001489 # inside interface VRF match NAT44 static mapping VRF
Matus Fabiande886752016-12-07 03:38:19 -08001490 pkts = self.create_stream_in(self.pg4, self.pg3)
1491 self.pg4.add_stream(pkts)
1492 self.pg_enable_capture(self.pg_interfaces)
1493 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001494 capture = self.pg3.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001495 self.verify_capture_out(capture, nat_ip1, True)
1496
Matus Fabian2ba92e32017-08-21 07:05:03 -07001497 # inside interface VRF don't match NAT44 static mapping VRF (packets
Matus Fabiande886752016-12-07 03:38:19 -08001498 # are dropped)
1499 pkts = self.create_stream_in(self.pg0, self.pg3)
1500 self.pg0.add_stream(pkts)
1501 self.pg_enable_capture(self.pg_interfaces)
1502 self.pg_start()
Klement Sekera9225dee2016-12-12 08:36:58 +01001503 self.pg3.assert_nothing_captured()
Matus Fabiande886752016-12-07 03:38:19 -08001504
Matus Fabianb793d092018-01-31 05:50:21 -08001505 def test_dynamic_to_static(self):
1506 """ Switch from dynamic translation to 1:1NAT """
1507 nat_ip = "10.0.0.10"
1508 self.tcp_port_out = 6303
1509 self.udp_port_out = 6304
1510 self.icmp_id_out = 6305
1511
1512 self.nat44_add_address(self.nat_addr)
1513 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1514 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1515 is_inside=0)
1516
1517 # dynamic
1518 pkts = self.create_stream_in(self.pg0, self.pg1)
1519 self.pg0.add_stream(pkts)
1520 self.pg_enable_capture(self.pg_interfaces)
1521 self.pg_start()
1522 capture = self.pg1.get_capture(len(pkts))
1523 self.verify_capture_out(capture)
1524
1525 # 1:1NAT
1526 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
1527 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
1528 self.assertEqual(len(sessions), 0)
1529 pkts = self.create_stream_in(self.pg0, self.pg1)
1530 self.pg0.add_stream(pkts)
1531 self.pg_enable_capture(self.pg_interfaces)
1532 self.pg_start()
1533 capture = self.pg1.get_capture(len(pkts))
1534 self.verify_capture_out(capture, nat_ip, True)
1535
Matus Fabianab7a8052017-11-28 04:29:41 -08001536 def test_identity_nat(self):
1537 """ Identity NAT """
1538
1539 self.vapi.nat44_add_del_identity_mapping(ip=self.pg0.remote_ip4n)
1540 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1541 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1542 is_inside=0)
1543
1544 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
1545 IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
1546 TCP(sport=12345, dport=56789))
1547 self.pg1.add_stream(p)
1548 self.pg_enable_capture(self.pg_interfaces)
1549 self.pg_start()
1550 capture = self.pg0.get_capture(1)
1551 p = capture[0]
1552 try:
1553 ip = p[IP]
1554 tcp = p[TCP]
1555 self.assertEqual(ip.dst, self.pg0.remote_ip4)
1556 self.assertEqual(ip.src, self.pg1.remote_ip4)
1557 self.assertEqual(tcp.dport, 56789)
1558 self.assertEqual(tcp.sport, 12345)
Klement Sekerad81ae412018-05-16 10:52:54 +02001559 self.assert_packet_checksums_valid(p)
Matus Fabianab7a8052017-11-28 04:29:41 -08001560 except:
1561 self.logger.error(ppp("Unexpected or invalid packet:", p))
1562 raise
1563
Matus Fabiande886752016-12-07 03:38:19 -08001564 def test_multiple_inside_interfaces(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001565 """ NAT44 multiple non-overlapping address space inside interfaces """
Matus Fabiande886752016-12-07 03:38:19 -08001566
Matus Fabian2ba92e32017-08-21 07:05:03 -07001567 self.nat44_add_address(self.nat_addr)
1568 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1569 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
1570 self.vapi.nat44_interface_add_del_feature(self.pg3.sw_if_index,
1571 is_inside=0)
Matus Fabiande886752016-12-07 03:38:19 -08001572
Matus Fabian2ba92e32017-08-21 07:05:03 -07001573 # between two NAT44 inside interfaces (no translation)
Matus Fabian675a69c2017-01-18 01:46:01 -08001574 pkts = self.create_stream_in(self.pg0, self.pg1)
1575 self.pg0.add_stream(pkts)
1576 self.pg_enable_capture(self.pg_interfaces)
1577 self.pg_start()
1578 capture = self.pg1.get_capture(len(pkts))
1579 self.verify_capture_no_translation(capture, self.pg0, self.pg1)
1580
Matus Fabian2ba92e32017-08-21 07:05:03 -07001581 # from NAT44 inside to interface without NAT44 feature (no translation)
Matus Fabian675a69c2017-01-18 01:46:01 -08001582 pkts = self.create_stream_in(self.pg0, self.pg2)
1583 self.pg0.add_stream(pkts)
1584 self.pg_enable_capture(self.pg_interfaces)
1585 self.pg_start()
1586 capture = self.pg2.get_capture(len(pkts))
1587 self.verify_capture_no_translation(capture, self.pg0, self.pg2)
1588
Matus Fabiande886752016-12-07 03:38:19 -08001589 # in2out 1st interface
1590 pkts = self.create_stream_in(self.pg0, self.pg3)
1591 self.pg0.add_stream(pkts)
1592 self.pg_enable_capture(self.pg_interfaces)
1593 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001594 capture = self.pg3.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001595 self.verify_capture_out(capture)
1596
1597 # out2in 1st interface
1598 pkts = self.create_stream_out(self.pg3)
1599 self.pg3.add_stream(pkts)
1600 self.pg_enable_capture(self.pg_interfaces)
1601 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001602 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001603 self.verify_capture_in(capture, self.pg0)
1604
1605 # in2out 2nd interface
1606 pkts = self.create_stream_in(self.pg1, self.pg3)
1607 self.pg1.add_stream(pkts)
1608 self.pg_enable_capture(self.pg_interfaces)
1609 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001610 capture = self.pg3.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001611 self.verify_capture_out(capture)
1612
1613 # out2in 2nd interface
1614 pkts = self.create_stream_out(self.pg3)
1615 self.pg3.add_stream(pkts)
1616 self.pg_enable_capture(self.pg_interfaces)
1617 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001618 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001619 self.verify_capture_in(capture, self.pg1)
1620
Matus Fabiande886752016-12-07 03:38:19 -08001621 def test_inside_overlapping_interfaces(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001622 """ NAT44 multiple inside interfaces with overlapping address space """
Matus Fabiande886752016-12-07 03:38:19 -08001623
Matus Fabian675a69c2017-01-18 01:46:01 -08001624 static_nat_ip = "10.0.0.10"
Matus Fabian2ba92e32017-08-21 07:05:03 -07001625 self.nat44_add_address(self.nat_addr)
1626 self.vapi.nat44_interface_add_del_feature(self.pg3.sw_if_index,
1627 is_inside=0)
1628 self.vapi.nat44_interface_add_del_feature(self.pg4.sw_if_index)
1629 self.vapi.nat44_interface_add_del_feature(self.pg5.sw_if_index)
1630 self.vapi.nat44_interface_add_del_feature(self.pg6.sw_if_index)
1631 self.nat44_add_static_mapping(self.pg6.remote_ip4, static_nat_ip,
1632 vrf_id=20)
Matus Fabian675a69c2017-01-18 01:46:01 -08001633
Matus Fabian2ba92e32017-08-21 07:05:03 -07001634 # between NAT44 inside interfaces with same VRF (no translation)
Matus Fabian675a69c2017-01-18 01:46:01 -08001635 pkts = self.create_stream_in(self.pg4, self.pg5)
1636 self.pg4.add_stream(pkts)
1637 self.pg_enable_capture(self.pg_interfaces)
1638 self.pg_start()
1639 capture = self.pg5.get_capture(len(pkts))
1640 self.verify_capture_no_translation(capture, self.pg4, self.pg5)
1641
Matus Fabian2ba92e32017-08-21 07:05:03 -07001642 # between NAT44 inside interfaces with different VRF (hairpinning)
Matus Fabian675a69c2017-01-18 01:46:01 -08001643 p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
1644 IP(src=self.pg4.remote_ip4, dst=static_nat_ip) /
1645 TCP(sport=1234, dport=5678))
1646 self.pg4.add_stream(p)
1647 self.pg_enable_capture(self.pg_interfaces)
1648 self.pg_start()
1649 capture = self.pg6.get_capture(1)
1650 p = capture[0]
1651 try:
1652 ip = p[IP]
1653 tcp = p[TCP]
Matus Fabian2ba92e32017-08-21 07:05:03 -07001654 self.assertEqual(ip.src, self.nat_addr)
Matus Fabian675a69c2017-01-18 01:46:01 -08001655 self.assertEqual(ip.dst, self.pg6.remote_ip4)
1656 self.assertNotEqual(tcp.sport, 1234)
1657 self.assertEqual(tcp.dport, 5678)
1658 except:
1659 self.logger.error(ppp("Unexpected or invalid packet:", p))
1660 raise
Matus Fabiande886752016-12-07 03:38:19 -08001661
1662 # in2out 1st interface
1663 pkts = self.create_stream_in(self.pg4, self.pg3)
1664 self.pg4.add_stream(pkts)
1665 self.pg_enable_capture(self.pg_interfaces)
1666 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001667 capture = self.pg3.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001668 self.verify_capture_out(capture)
1669
1670 # out2in 1st interface
1671 pkts = self.create_stream_out(self.pg3)
1672 self.pg3.add_stream(pkts)
1673 self.pg_enable_capture(self.pg_interfaces)
1674 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001675 capture = self.pg4.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001676 self.verify_capture_in(capture, self.pg4)
1677
1678 # in2out 2nd interface
1679 pkts = self.create_stream_in(self.pg5, self.pg3)
1680 self.pg5.add_stream(pkts)
1681 self.pg_enable_capture(self.pg_interfaces)
1682 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001683 capture = self.pg3.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001684 self.verify_capture_out(capture)
1685
1686 # out2in 2nd interface
1687 pkts = self.create_stream_out(self.pg3)
1688 self.pg3.add_stream(pkts)
1689 self.pg_enable_capture(self.pg_interfaces)
1690 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001691 capture = self.pg5.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001692 self.verify_capture_in(capture, self.pg5)
1693
magalik23caa882017-02-08 23:25:45 -08001694 # pg5 session dump
Matus Fabian2ba92e32017-08-21 07:05:03 -07001695 addresses = self.vapi.nat44_address_dump()
magalik23caa882017-02-08 23:25:45 -08001696 self.assertEqual(len(addresses), 1)
Matus Fabian2ba92e32017-08-21 07:05:03 -07001697 sessions = self.vapi.nat44_user_session_dump(self.pg5.remote_ip4n, 10)
magalik23caa882017-02-08 23:25:45 -08001698 self.assertEqual(len(sessions), 3)
1699 for session in sessions:
1700 self.assertFalse(session.is_static)
1701 self.assertEqual(session.inside_ip_address[0:4],
1702 self.pg5.remote_ip4n)
1703 self.assertEqual(session.outside_ip_address,
1704 addresses[0].ip_address)
1705 self.assertEqual(sessions[0].protocol, IP_PROTOS.tcp)
1706 self.assertEqual(sessions[1].protocol, IP_PROTOS.udp)
1707 self.assertEqual(sessions[2].protocol, IP_PROTOS.icmp)
1708 self.assertEqual(sessions[0].inside_port, self.tcp_port_in)
1709 self.assertEqual(sessions[1].inside_port, self.udp_port_in)
1710 self.assertEqual(sessions[2].inside_port, self.icmp_id_in)
1711 self.assertEqual(sessions[0].outside_port, self.tcp_port_out)
1712 self.assertEqual(sessions[1].outside_port, self.udp_port_out)
1713 self.assertEqual(sessions[2].outside_port, self.icmp_id_out)
1714
Matus Fabiande886752016-12-07 03:38:19 -08001715 # in2out 3rd interface
1716 pkts = self.create_stream_in(self.pg6, self.pg3)
1717 self.pg6.add_stream(pkts)
1718 self.pg_enable_capture(self.pg_interfaces)
1719 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001720 capture = self.pg3.get_capture(len(pkts))
Matus Fabian675a69c2017-01-18 01:46:01 -08001721 self.verify_capture_out(capture, static_nat_ip, True)
Matus Fabiande886752016-12-07 03:38:19 -08001722
1723 # out2in 3rd interface
Matus Fabian675a69c2017-01-18 01:46:01 -08001724 pkts = self.create_stream_out(self.pg3, static_nat_ip)
Matus Fabiande886752016-12-07 03:38:19 -08001725 self.pg3.add_stream(pkts)
1726 self.pg_enable_capture(self.pg_interfaces)
1727 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001728 capture = self.pg6.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001729 self.verify_capture_in(capture, self.pg6)
1730
magalik23caa882017-02-08 23:25:45 -08001731 # general user and session dump verifications
Matus Fabian2ba92e32017-08-21 07:05:03 -07001732 users = self.vapi.nat44_user_dump()
magalik23caa882017-02-08 23:25:45 -08001733 self.assertTrue(len(users) >= 3)
Matus Fabian2ba92e32017-08-21 07:05:03 -07001734 addresses = self.vapi.nat44_address_dump()
magalik23caa882017-02-08 23:25:45 -08001735 self.assertEqual(len(addresses), 1)
1736 for user in users:
Matus Fabian2ba92e32017-08-21 07:05:03 -07001737 sessions = self.vapi.nat44_user_session_dump(user.ip_address,
1738 user.vrf_id)
magalik23caa882017-02-08 23:25:45 -08001739 for session in sessions:
1740 self.assertEqual(user.ip_address, session.inside_ip_address)
1741 self.assertTrue(session.total_bytes > session.total_pkts > 0)
1742 self.assertTrue(session.protocol in
1743 [IP_PROTOS.tcp, IP_PROTOS.udp,
1744 IP_PROTOS.icmp])
Matus Fabian70a26ac2018-05-14 06:20:28 -07001745 self.assertFalse(session.ext_host_valid)
magalik23caa882017-02-08 23:25:45 -08001746
1747 # pg4 session dump
Matus Fabian2ba92e32017-08-21 07:05:03 -07001748 sessions = self.vapi.nat44_user_session_dump(self.pg4.remote_ip4n, 10)
magalik23caa882017-02-08 23:25:45 -08001749 self.assertTrue(len(sessions) >= 4)
1750 for session in sessions:
1751 self.assertFalse(session.is_static)
1752 self.assertEqual(session.inside_ip_address[0:4],
1753 self.pg4.remote_ip4n)
1754 self.assertEqual(session.outside_ip_address,
1755 addresses[0].ip_address)
1756
1757 # pg6 session dump
Matus Fabian2ba92e32017-08-21 07:05:03 -07001758 sessions = self.vapi.nat44_user_session_dump(self.pg6.remote_ip4n, 20)
magalik23caa882017-02-08 23:25:45 -08001759 self.assertTrue(len(sessions) >= 3)
1760 for session in sessions:
1761 self.assertTrue(session.is_static)
1762 self.assertEqual(session.inside_ip_address[0:4],
1763 self.pg6.remote_ip4n)
1764 self.assertEqual(map(ord, session.outside_ip_address[0:4]),
1765 map(int, static_nat_ip.split('.')))
1766 self.assertTrue(session.inside_port in
1767 [self.tcp_port_in, self.udp_port_in,
1768 self.icmp_id_in])
1769
Matus Fabianf78a70d2016-12-12 04:30:39 -08001770 def test_hairpinning(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001771 """ NAT44 hairpinning - 1:1 NAPT """
Matus Fabianf78a70d2016-12-12 04:30:39 -08001772
1773 host = self.pg0.remote_hosts[0]
1774 server = self.pg0.remote_hosts[1]
1775 host_in_port = 1234
1776 host_out_port = 0
1777 server_in_port = 5678
1778 server_out_port = 8765
1779
Matus Fabian2ba92e32017-08-21 07:05:03 -07001780 self.nat44_add_address(self.nat_addr)
1781 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1782 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1783 is_inside=0)
Matus Fabianf78a70d2016-12-12 04:30:39 -08001784 # add static mapping for server
Matus Fabian2ba92e32017-08-21 07:05:03 -07001785 self.nat44_add_static_mapping(server.ip4, self.nat_addr,
1786 server_in_port, server_out_port,
1787 proto=IP_PROTOS.tcp)
Matus Fabianf78a70d2016-12-12 04:30:39 -08001788
1789 # send packet from host to server
1790 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07001791 IP(src=host.ip4, dst=self.nat_addr) /
Matus Fabianf78a70d2016-12-12 04:30:39 -08001792 TCP(sport=host_in_port, dport=server_out_port))
1793 self.pg0.add_stream(p)
1794 self.pg_enable_capture(self.pg_interfaces)
1795 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001796 capture = self.pg0.get_capture(1)
Matus Fabianf78a70d2016-12-12 04:30:39 -08001797 p = capture[0]
1798 try:
1799 ip = p[IP]
1800 tcp = p[TCP]
Matus Fabian2ba92e32017-08-21 07:05:03 -07001801 self.assertEqual(ip.src, self.nat_addr)
Matus Fabianf78a70d2016-12-12 04:30:39 -08001802 self.assertEqual(ip.dst, server.ip4)
1803 self.assertNotEqual(tcp.sport, host_in_port)
1804 self.assertEqual(tcp.dport, server_in_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02001805 self.assert_packet_checksums_valid(p)
Matus Fabianf78a70d2016-12-12 04:30:39 -08001806 host_out_port = tcp.sport
1807 except:
Klement Sekera9225dee2016-12-12 08:36:58 +01001808 self.logger.error(ppp("Unexpected or invalid packet:", p))
Matus Fabianf78a70d2016-12-12 04:30:39 -08001809 raise
1810
1811 # send reply from server to host
1812 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07001813 IP(src=server.ip4, dst=self.nat_addr) /
Matus Fabianf78a70d2016-12-12 04:30:39 -08001814 TCP(sport=server_in_port, dport=host_out_port))
1815 self.pg0.add_stream(p)
1816 self.pg_enable_capture(self.pg_interfaces)
1817 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001818 capture = self.pg0.get_capture(1)
Matus Fabianf78a70d2016-12-12 04:30:39 -08001819 p = capture[0]
1820 try:
1821 ip = p[IP]
1822 tcp = p[TCP]
Matus Fabian2ba92e32017-08-21 07:05:03 -07001823 self.assertEqual(ip.src, self.nat_addr)
Matus Fabianf78a70d2016-12-12 04:30:39 -08001824 self.assertEqual(ip.dst, host.ip4)
1825 self.assertEqual(tcp.sport, server_out_port)
1826 self.assertEqual(tcp.dport, host_in_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02001827 self.assert_packet_checksums_valid(p)
Matus Fabianf78a70d2016-12-12 04:30:39 -08001828 except:
Matus Fabiane82488f2018-01-18 03:38:45 -08001829 self.logger.error(ppp("Unexpected or invalid packet:", p))
Matus Fabianf78a70d2016-12-12 04:30:39 -08001830 raise
1831
Matus Fabian6fa74c62017-06-05 05:55:48 -07001832 def test_hairpinning2(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001833 """ NAT44 hairpinning - 1:1 NAT"""
Matus Fabian6fa74c62017-06-05 05:55:48 -07001834
1835 server1_nat_ip = "10.0.0.10"
1836 server2_nat_ip = "10.0.0.11"
1837 host = self.pg0.remote_hosts[0]
1838 server1 = self.pg0.remote_hosts[1]
1839 server2 = self.pg0.remote_hosts[2]
1840 server_tcp_port = 22
1841 server_udp_port = 20
1842
Matus Fabian2ba92e32017-08-21 07:05:03 -07001843 self.nat44_add_address(self.nat_addr)
1844 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1845 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1846 is_inside=0)
Matus Fabian6fa74c62017-06-05 05:55:48 -07001847
1848 # add static mapping for servers
Matus Fabian2ba92e32017-08-21 07:05:03 -07001849 self.nat44_add_static_mapping(server1.ip4, server1_nat_ip)
1850 self.nat44_add_static_mapping(server2.ip4, server2_nat_ip)
Matus Fabian6fa74c62017-06-05 05:55:48 -07001851
1852 # host to server1
1853 pkts = []
1854 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1855 IP(src=host.ip4, dst=server1_nat_ip) /
1856 TCP(sport=self.tcp_port_in, dport=server_tcp_port))
1857 pkts.append(p)
1858 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1859 IP(src=host.ip4, dst=server1_nat_ip) /
1860 UDP(sport=self.udp_port_in, dport=server_udp_port))
1861 pkts.append(p)
1862 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1863 IP(src=host.ip4, dst=server1_nat_ip) /
1864 ICMP(id=self.icmp_id_in, type='echo-request'))
1865 pkts.append(p)
1866 self.pg0.add_stream(pkts)
1867 self.pg_enable_capture(self.pg_interfaces)
1868 self.pg_start()
1869 capture = self.pg0.get_capture(len(pkts))
1870 for packet in capture:
1871 try:
Matus Fabian2ba92e32017-08-21 07:05:03 -07001872 self.assertEqual(packet[IP].src, self.nat_addr)
Matus Fabian6fa74c62017-06-05 05:55:48 -07001873 self.assertEqual(packet[IP].dst, server1.ip4)
1874 if packet.haslayer(TCP):
1875 self.assertNotEqual(packet[TCP].sport, self.tcp_port_in)
1876 self.assertEqual(packet[TCP].dport, server_tcp_port)
1877 self.tcp_port_out = packet[TCP].sport
Klement Sekerad81ae412018-05-16 10:52:54 +02001878 self.assert_packet_checksums_valid(packet)
Matus Fabian6fa74c62017-06-05 05:55:48 -07001879 elif packet.haslayer(UDP):
1880 self.assertNotEqual(packet[UDP].sport, self.udp_port_in)
1881 self.assertEqual(packet[UDP].dport, server_udp_port)
1882 self.udp_port_out = packet[UDP].sport
1883 else:
1884 self.assertNotEqual(packet[ICMP].id, self.icmp_id_in)
1885 self.icmp_id_out = packet[ICMP].id
1886 except:
1887 self.logger.error(ppp("Unexpected or invalid packet:", packet))
1888 raise
1889
1890 # server1 to host
1891 pkts = []
1892 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07001893 IP(src=server1.ip4, dst=self.nat_addr) /
Matus Fabian6fa74c62017-06-05 05:55:48 -07001894 TCP(sport=server_tcp_port, dport=self.tcp_port_out))
1895 pkts.append(p)
1896 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07001897 IP(src=server1.ip4, dst=self.nat_addr) /
Matus Fabian6fa74c62017-06-05 05:55:48 -07001898 UDP(sport=server_udp_port, dport=self.udp_port_out))
1899 pkts.append(p)
1900 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07001901 IP(src=server1.ip4, dst=self.nat_addr) /
Matus Fabian6fa74c62017-06-05 05:55:48 -07001902 ICMP(id=self.icmp_id_out, type='echo-reply'))
1903 pkts.append(p)
1904 self.pg0.add_stream(pkts)
1905 self.pg_enable_capture(self.pg_interfaces)
1906 self.pg_start()
1907 capture = self.pg0.get_capture(len(pkts))
1908 for packet in capture:
1909 try:
1910 self.assertEqual(packet[IP].src, server1_nat_ip)
1911 self.assertEqual(packet[IP].dst, host.ip4)
1912 if packet.haslayer(TCP):
1913 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
1914 self.assertEqual(packet[TCP].sport, server_tcp_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02001915 self.assert_packet_checksums_valid(packet)
Matus Fabian6fa74c62017-06-05 05:55:48 -07001916 elif packet.haslayer(UDP):
1917 self.assertEqual(packet[UDP].dport, self.udp_port_in)
1918 self.assertEqual(packet[UDP].sport, server_udp_port)
1919 else:
1920 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
1921 except:
1922 self.logger.error(ppp("Unexpected or invalid packet:", packet))
1923 raise
1924
1925 # server2 to server1
1926 pkts = []
1927 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1928 IP(src=server2.ip4, dst=server1_nat_ip) /
1929 TCP(sport=self.tcp_port_in, dport=server_tcp_port))
1930 pkts.append(p)
1931 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1932 IP(src=server2.ip4, dst=server1_nat_ip) /
1933 UDP(sport=self.udp_port_in, dport=server_udp_port))
1934 pkts.append(p)
1935 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1936 IP(src=server2.ip4, dst=server1_nat_ip) /
1937 ICMP(id=self.icmp_id_in, type='echo-request'))
1938 pkts.append(p)
1939 self.pg0.add_stream(pkts)
1940 self.pg_enable_capture(self.pg_interfaces)
1941 self.pg_start()
1942 capture = self.pg0.get_capture(len(pkts))
1943 for packet in capture:
1944 try:
1945 self.assertEqual(packet[IP].src, server2_nat_ip)
1946 self.assertEqual(packet[IP].dst, server1.ip4)
1947 if packet.haslayer(TCP):
1948 self.assertEqual(packet[TCP].sport, self.tcp_port_in)
1949 self.assertEqual(packet[TCP].dport, server_tcp_port)
1950 self.tcp_port_out = packet[TCP].sport
Klement Sekerad81ae412018-05-16 10:52:54 +02001951 self.assert_packet_checksums_valid(packet)
Matus Fabian6fa74c62017-06-05 05:55:48 -07001952 elif packet.haslayer(UDP):
1953 self.assertEqual(packet[UDP].sport, self.udp_port_in)
1954 self.assertEqual(packet[UDP].dport, server_udp_port)
1955 self.udp_port_out = packet[UDP].sport
1956 else:
1957 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
1958 self.icmp_id_out = packet[ICMP].id
1959 except:
1960 self.logger.error(ppp("Unexpected or invalid packet:", packet))
1961 raise
1962
1963 # server1 to server2
1964 pkts = []
1965 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1966 IP(src=server1.ip4, dst=server2_nat_ip) /
1967 TCP(sport=server_tcp_port, dport=self.tcp_port_out))
1968 pkts.append(p)
1969 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1970 IP(src=server1.ip4, dst=server2_nat_ip) /
1971 UDP(sport=server_udp_port, dport=self.udp_port_out))
1972 pkts.append(p)
1973 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1974 IP(src=server1.ip4, dst=server2_nat_ip) /
1975 ICMP(id=self.icmp_id_out, type='echo-reply'))
1976 pkts.append(p)
1977 self.pg0.add_stream(pkts)
1978 self.pg_enable_capture(self.pg_interfaces)
1979 self.pg_start()
1980 capture = self.pg0.get_capture(len(pkts))
1981 for packet in capture:
1982 try:
1983 self.assertEqual(packet[IP].src, server1_nat_ip)
1984 self.assertEqual(packet[IP].dst, server2.ip4)
1985 if packet.haslayer(TCP):
1986 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
1987 self.assertEqual(packet[TCP].sport, server_tcp_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02001988 self.assert_packet_checksums_valid(packet)
Matus Fabian6fa74c62017-06-05 05:55:48 -07001989 elif packet.haslayer(UDP):
1990 self.assertEqual(packet[UDP].dport, self.udp_port_in)
1991 self.assertEqual(packet[UDP].sport, server_udp_port)
1992 else:
1993 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
1994 except:
1995 self.logger.error(ppp("Unexpected or invalid packet:", packet))
1996 raise
1997
Matus Fabian9902fcd2016-12-21 23:58:46 -08001998 def test_max_translations_per_user(self):
1999 """ MAX translations per user - recycle the least recently used """
2000
Matus Fabian2ba92e32017-08-21 07:05:03 -07002001 self.nat44_add_address(self.nat_addr)
2002 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2003 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2004 is_inside=0)
Matus Fabian9902fcd2016-12-21 23:58:46 -08002005
2006 # get maximum number of translations per user
Matus Fabian2ba92e32017-08-21 07:05:03 -07002007 nat44_config = self.vapi.nat_show_config()
Matus Fabian9902fcd2016-12-21 23:58:46 -08002008
2009 # send more than maximum number of translations per user packets
Matus Fabian2ba92e32017-08-21 07:05:03 -07002010 pkts_num = nat44_config.max_translations_per_user + 5
Matus Fabian9902fcd2016-12-21 23:58:46 -08002011 pkts = []
2012 for port in range(0, pkts_num):
2013 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2014 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2015 TCP(sport=1025 + port))
2016 pkts.append(p)
2017 self.pg0.add_stream(pkts)
2018 self.pg_enable_capture(self.pg_interfaces)
2019 self.pg_start()
2020
2021 # verify number of translated packet
Klement Sekeradab231a2016-12-21 08:50:14 +01002022 self.pg1.get_capture(pkts_num)
Matus Fabian9902fcd2016-12-21 23:58:46 -08002023
Matus Fabian132dc492018-05-09 04:51:03 -07002024 users = self.vapi.nat44_user_dump()
2025 for user in users:
2026 if user.ip_address == self.pg0.remote_ip4n:
2027 self.assertEqual(user.nsessions,
2028 nat44_config.max_translations_per_user)
2029 self.assertEqual(user.nstaticsessions, 0)
2030
2031 tcp_port = 22
2032 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
2033 tcp_port, tcp_port,
2034 proto=IP_PROTOS.tcp)
2035 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2036 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2037 TCP(sport=tcp_port))
2038 self.pg0.add_stream(p)
2039 self.pg_enable_capture(self.pg_interfaces)
2040 self.pg_start()
2041 self.pg1.get_capture(1)
2042 users = self.vapi.nat44_user_dump()
2043 for user in users:
2044 if user.ip_address == self.pg0.remote_ip4n:
2045 self.assertEqual(user.nsessions,
2046 nat44_config.max_translations_per_user - 1)
2047 self.assertEqual(user.nstaticsessions, 1)
2048
Matus Fabian8bf68e82017-01-12 04:24:35 -08002049 def test_interface_addr(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002050 """ Acquire NAT44 addresses from interface """
2051 self.vapi.nat44_add_interface_addr(self.pg7.sw_if_index)
Matus Fabian8bf68e82017-01-12 04:24:35 -08002052
2053 # no address in NAT pool
Matus Fabian2ba92e32017-08-21 07:05:03 -07002054 adresses = self.vapi.nat44_address_dump()
Matus Fabian8bf68e82017-01-12 04:24:35 -08002055 self.assertEqual(0, len(adresses))
2056
2057 # configure interface address and check NAT address pool
2058 self.pg7.config_ip4()
Matus Fabian2ba92e32017-08-21 07:05:03 -07002059 adresses = self.vapi.nat44_address_dump()
Matus Fabian8bf68e82017-01-12 04:24:35 -08002060 self.assertEqual(1, len(adresses))
Matus Fabian36532bd2017-01-23 23:42:28 -08002061 self.assertEqual(adresses[0].ip_address[0:4], self.pg7.local_ip4n)
Matus Fabian8bf68e82017-01-12 04:24:35 -08002062
2063 # remove interface address and check NAT address pool
2064 self.pg7.unconfig_ip4()
Matus Fabian2ba92e32017-08-21 07:05:03 -07002065 adresses = self.vapi.nat44_address_dump()
Matus Fabian8bf68e82017-01-12 04:24:35 -08002066 self.assertEqual(0, len(adresses))
2067
Matus Fabian36532bd2017-01-23 23:42:28 -08002068 def test_interface_addr_static_mapping(self):
2069 """ Static mapping with addresses from interface """
Matus Fabian5f224992018-01-25 21:59:16 -08002070 tag = "testTAG"
2071
Matus Fabian2ba92e32017-08-21 07:05:03 -07002072 self.vapi.nat44_add_interface_addr(self.pg7.sw_if_index)
2073 self.nat44_add_static_mapping(
2074 '1.2.3.4',
Matus Fabian5f224992018-01-25 21:59:16 -08002075 external_sw_if_index=self.pg7.sw_if_index,
2076 tag=tag)
Matus Fabian36532bd2017-01-23 23:42:28 -08002077
Matus Fabiane22e5462017-02-14 23:33:43 -08002078 # static mappings with external interface
Matus Fabian2ba92e32017-08-21 07:05:03 -07002079 static_mappings = self.vapi.nat44_static_mapping_dump()
Matus Fabiane22e5462017-02-14 23:33:43 -08002080 self.assertEqual(1, len(static_mappings))
2081 self.assertEqual(self.pg7.sw_if_index,
2082 static_mappings[0].external_sw_if_index)
Matus Fabian5f224992018-01-25 21:59:16 -08002083 self.assertEqual((static_mappings[0].tag).split('\0', 1)[0], tag)
Matus Fabian36532bd2017-01-23 23:42:28 -08002084
2085 # configure interface address and check static mappings
2086 self.pg7.config_ip4()
Matus Fabian2ba92e32017-08-21 07:05:03 -07002087 static_mappings = self.vapi.nat44_static_mapping_dump()
Matus Fabianea2600a2018-03-28 04:06:26 -07002088 self.assertEqual(2, len(static_mappings))
2089 resolved = False
2090 for sm in static_mappings:
2091 if sm.external_sw_if_index == 0xFFFFFFFF:
2092 self.assertEqual(sm.external_ip_address[0:4],
2093 self.pg7.local_ip4n)
2094 self.assertEqual((sm.tag).split('\0', 1)[0], tag)
2095 resolved = True
2096 self.assertTrue(resolved)
Matus Fabian36532bd2017-01-23 23:42:28 -08002097
2098 # remove interface address and check static mappings
2099 self.pg7.unconfig_ip4()
Matus Fabian2ba92e32017-08-21 07:05:03 -07002100 static_mappings = self.vapi.nat44_static_mapping_dump()
Matus Fabianea2600a2018-03-28 04:06:26 -07002101 self.assertEqual(1, len(static_mappings))
2102 self.assertEqual(self.pg7.sw_if_index,
2103 static_mappings[0].external_sw_if_index)
2104 self.assertEqual((static_mappings[0].tag).split('\0', 1)[0], tag)
2105
2106 # configure interface address again and check static mappings
2107 self.pg7.config_ip4()
2108 static_mappings = self.vapi.nat44_static_mapping_dump()
2109 self.assertEqual(2, len(static_mappings))
2110 resolved = False
2111 for sm in static_mappings:
2112 if sm.external_sw_if_index == 0xFFFFFFFF:
2113 self.assertEqual(sm.external_ip_address[0:4],
2114 self.pg7.local_ip4n)
2115 self.assertEqual((sm.tag).split('\0', 1)[0], tag)
2116 resolved = True
2117 self.assertTrue(resolved)
2118
2119 # remove static mapping
2120 self.nat44_add_static_mapping(
2121 '1.2.3.4',
2122 external_sw_if_index=self.pg7.sw_if_index,
2123 tag=tag,
2124 is_add=0)
2125 static_mappings = self.vapi.nat44_static_mapping_dump()
Matus Fabian36532bd2017-01-23 23:42:28 -08002126 self.assertEqual(0, len(static_mappings))
2127
Matus Fabianab7a8052017-11-28 04:29:41 -08002128 def test_interface_addr_identity_nat(self):
2129 """ Identity NAT with addresses from interface """
2130
2131 port = 53053
2132 self.vapi.nat44_add_interface_addr(self.pg7.sw_if_index)
2133 self.vapi.nat44_add_del_identity_mapping(
2134 sw_if_index=self.pg7.sw_if_index,
2135 port=port,
2136 protocol=IP_PROTOS.tcp,
2137 addr_only=0)
2138
2139 # identity mappings with external interface
2140 identity_mappings = self.vapi.nat44_identity_mapping_dump()
2141 self.assertEqual(1, len(identity_mappings))
2142 self.assertEqual(self.pg7.sw_if_index,
2143 identity_mappings[0].sw_if_index)
2144
2145 # configure interface address and check identity mappings
2146 self.pg7.config_ip4()
2147 identity_mappings = self.vapi.nat44_identity_mapping_dump()
Matus Fabianea2600a2018-03-28 04:06:26 -07002148 resolved = False
2149 self.assertEqual(2, len(identity_mappings))
2150 for sm in identity_mappings:
2151 if sm.sw_if_index == 0xFFFFFFFF:
2152 self.assertEqual(identity_mappings[0].ip_address,
2153 self.pg7.local_ip4n)
2154 self.assertEqual(port, identity_mappings[0].port)
2155 self.assertEqual(IP_PROTOS.tcp, identity_mappings[0].protocol)
2156 resolved = True
2157 self.assertTrue(resolved)
Matus Fabianab7a8052017-11-28 04:29:41 -08002158
2159 # remove interface address and check identity mappings
2160 self.pg7.unconfig_ip4()
2161 identity_mappings = self.vapi.nat44_identity_mapping_dump()
Matus Fabianea2600a2018-03-28 04:06:26 -07002162 self.assertEqual(1, len(identity_mappings))
2163 self.assertEqual(self.pg7.sw_if_index,
2164 identity_mappings[0].sw_if_index)
Matus Fabianab7a8052017-11-28 04:29:41 -08002165
Matus Fabianeea28d72017-01-13 04:15:54 -08002166 def test_ipfix_nat44_sess(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002167 """ IPFIX logging NAT44 session created/delted """
Matus Fabian6631e9c2017-05-24 01:52:20 -07002168 self.ipfix_domain_id = 10
2169 self.ipfix_src_port = 20202
2170 colector_port = 30303
2171 bind_layers(UDP, IPFIX, dport=30303)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002172 self.nat44_add_address(self.nat_addr)
2173 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2174 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2175 is_inside=0)
Matus Fabianeea28d72017-01-13 04:15:54 -08002176 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
2177 src_address=self.pg3.local_ip4n,
2178 path_mtu=512,
Matus Fabian6631e9c2017-05-24 01:52:20 -07002179 template_interval=10,
2180 collector_port=colector_port)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002181 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
2182 src_port=self.ipfix_src_port)
Matus Fabianeea28d72017-01-13 04:15:54 -08002183
2184 pkts = self.create_stream_in(self.pg0, self.pg1)
2185 self.pg0.add_stream(pkts)
2186 self.pg_enable_capture(self.pg_interfaces)
2187 self.pg_start()
2188 capture = self.pg1.get_capture(len(pkts))
2189 self.verify_capture_out(capture)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002190 self.nat44_add_address(self.nat_addr, is_add=0)
Matus Fabianeea28d72017-01-13 04:15:54 -08002191 self.vapi.cli("ipfix flush") # FIXME this should be an API call
Matus Fabiana431ad12018-01-04 04:03:14 -08002192 capture = self.pg3.get_capture(9)
Matus Fabianeea28d72017-01-13 04:15:54 -08002193 ipfix = IPFIXDecoder()
2194 # first load template
2195 for p in capture:
2196 self.assertTrue(p.haslayer(IPFIX))
Matus Fabian6631e9c2017-05-24 01:52:20 -07002197 self.assertEqual(p[IP].src, self.pg3.local_ip4)
2198 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2199 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2200 self.assertEqual(p[UDP].dport, colector_port)
2201 self.assertEqual(p[IPFIX].observationDomainID,
2202 self.ipfix_domain_id)
Matus Fabianeea28d72017-01-13 04:15:54 -08002203 if p.haslayer(Template):
2204 ipfix.add_template(p.getlayer(Template))
2205 # verify events in data set
2206 for p in capture:
2207 if p.haslayer(Data):
2208 data = ipfix.decode_data_set(p.getlayer(Set))
2209 self.verify_ipfix_nat44_ses(data)
2210
2211 def test_ipfix_addr_exhausted(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002212 """ IPFIX logging NAT addresses exhausted """
2213 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2214 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2215 is_inside=0)
Matus Fabianeea28d72017-01-13 04:15:54 -08002216 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
2217 src_address=self.pg3.local_ip4n,
2218 path_mtu=512,
2219 template_interval=10)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002220 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
2221 src_port=self.ipfix_src_port)
Matus Fabianeea28d72017-01-13 04:15:54 -08002222
2223 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
2224 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2225 TCP(sport=3025))
2226 self.pg0.add_stream(p)
2227 self.pg_enable_capture(self.pg_interfaces)
2228 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07002229 self.pg1.assert_nothing_captured()
2230 sleep(1)
Matus Fabianeea28d72017-01-13 04:15:54 -08002231 self.vapi.cli("ipfix flush") # FIXME this should be an API call
Matus Fabiana431ad12018-01-04 04:03:14 -08002232 capture = self.pg3.get_capture(9)
Matus Fabianeea28d72017-01-13 04:15:54 -08002233 ipfix = IPFIXDecoder()
2234 # first load template
2235 for p in capture:
2236 self.assertTrue(p.haslayer(IPFIX))
Matus Fabian6631e9c2017-05-24 01:52:20 -07002237 self.assertEqual(p[IP].src, self.pg3.local_ip4)
2238 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2239 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2240 self.assertEqual(p[UDP].dport, 4739)
2241 self.assertEqual(p[IPFIX].observationDomainID,
2242 self.ipfix_domain_id)
Matus Fabianeea28d72017-01-13 04:15:54 -08002243 if p.haslayer(Template):
2244 ipfix.add_template(p.getlayer(Template))
2245 # verify events in data set
2246 for p in capture:
2247 if p.haslayer(Data):
2248 data = ipfix.decode_data_set(p.getlayer(Set))
2249 self.verify_ipfix_addr_exhausted(data)
2250
Matus Fabiana431ad12018-01-04 04:03:14 -08002251 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
2252 def test_ipfix_max_sessions(self):
2253 """ IPFIX logging maximum session entries exceeded """
2254 self.nat44_add_address(self.nat_addr)
2255 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2256 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2257 is_inside=0)
2258
2259 nat44_config = self.vapi.nat_show_config()
2260 max_sessions = 10 * nat44_config.translation_buckets
2261
2262 pkts = []
2263 for i in range(0, max_sessions):
2264 src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
2265 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2266 IP(src=src, dst=self.pg1.remote_ip4) /
2267 TCP(sport=1025))
2268 pkts.append(p)
2269 self.pg0.add_stream(pkts)
2270 self.pg_enable_capture(self.pg_interfaces)
2271 self.pg_start()
2272
2273 self.pg1.get_capture(max_sessions)
2274 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
2275 src_address=self.pg3.local_ip4n,
2276 path_mtu=512,
2277 template_interval=10)
2278 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
2279 src_port=self.ipfix_src_port)
2280
2281 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2282 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2283 TCP(sport=1025))
2284 self.pg0.add_stream(p)
2285 self.pg_enable_capture(self.pg_interfaces)
2286 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07002287 self.pg1.assert_nothing_captured()
2288 sleep(1)
Matus Fabiana431ad12018-01-04 04:03:14 -08002289 self.vapi.cli("ipfix flush") # FIXME this should be an API call
2290 capture = self.pg3.get_capture(9)
2291 ipfix = IPFIXDecoder()
2292 # first load template
2293 for p in capture:
2294 self.assertTrue(p.haslayer(IPFIX))
2295 self.assertEqual(p[IP].src, self.pg3.local_ip4)
2296 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2297 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2298 self.assertEqual(p[UDP].dport, 4739)
2299 self.assertEqual(p[IPFIX].observationDomainID,
2300 self.ipfix_domain_id)
2301 if p.haslayer(Template):
2302 ipfix.add_template(p.getlayer(Template))
2303 # verify events in data set
2304 for p in capture:
2305 if p.haslayer(Data):
2306 data = ipfix.decode_data_set(p.getlayer(Set))
2307 self.verify_ipfix_max_sessions(data, max_sessions)
2308
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002309 def test_pool_addr_fib(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002310 """ NAT44 add pool addresses to FIB """
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002311 static_addr = '10.0.0.10'
Matus Fabian2ba92e32017-08-21 07:05:03 -07002312 self.nat44_add_address(self.nat_addr)
2313 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2314 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2315 is_inside=0)
2316 self.nat44_add_static_mapping(self.pg0.remote_ip4, static_addr)
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002317
Matus Fabian2ba92e32017-08-21 07:05:03 -07002318 # NAT44 address
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002319 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002320 ARP(op=ARP.who_has, pdst=self.nat_addr,
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002321 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2322 self.pg1.add_stream(p)
2323 self.pg_enable_capture(self.pg_interfaces)
2324 self.pg_start()
2325 capture = self.pg1.get_capture(1)
2326 self.assertTrue(capture[0].haslayer(ARP))
2327 self.assertTrue(capture[0][ARP].op, ARP.is_at)
2328
2329 # 1:1 NAT address
2330 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2331 ARP(op=ARP.who_has, pdst=static_addr,
2332 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2333 self.pg1.add_stream(p)
2334 self.pg_enable_capture(self.pg_interfaces)
2335 self.pg_start()
2336 capture = self.pg1.get_capture(1)
2337 self.assertTrue(capture[0].haslayer(ARP))
2338 self.assertTrue(capture[0][ARP].op, ARP.is_at)
2339
Matus Fabian2ba92e32017-08-21 07:05:03 -07002340 # send ARP to non-NAT44 interface
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002341 p = (Ether(src=self.pg2.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002342 ARP(op=ARP.who_has, pdst=self.nat_addr,
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002343 psrc=self.pg2.remote_ip4, hwsrc=self.pg2.remote_mac))
2344 self.pg2.add_stream(p)
2345 self.pg_enable_capture(self.pg_interfaces)
2346 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07002347 self.pg1.assert_nothing_captured()
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002348
2349 # remove addresses and verify
Matus Fabian2ba92e32017-08-21 07:05:03 -07002350 self.nat44_add_address(self.nat_addr, is_add=0)
2351 self.nat44_add_static_mapping(self.pg0.remote_ip4, static_addr,
2352 is_add=0)
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002353
2354 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002355 ARP(op=ARP.who_has, pdst=self.nat_addr,
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002356 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2357 self.pg1.add_stream(p)
2358 self.pg_enable_capture(self.pg_interfaces)
2359 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07002360 self.pg1.assert_nothing_captured()
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002361
2362 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2363 ARP(op=ARP.who_has, pdst=static_addr,
2364 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2365 self.pg1.add_stream(p)
2366 self.pg_enable_capture(self.pg_interfaces)
2367 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07002368 self.pg1.assert_nothing_captured()
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002369
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002370 def test_vrf_mode(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002371 """ NAT44 tenant VRF aware address pool mode """
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002372
2373 vrf_id1 = 1
2374 vrf_id2 = 2
2375 nat_ip1 = "10.0.0.10"
2376 nat_ip2 = "10.0.0.11"
2377
2378 self.pg0.unconfig_ip4()
2379 self.pg1.unconfig_ip4()
Neale Ranns15002542017-09-10 04:39:11 -07002380 self.vapi.ip_table_add_del(vrf_id1, is_add=1)
2381 self.vapi.ip_table_add_del(vrf_id2, is_add=1)
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002382 self.pg0.set_table_ip4(vrf_id1)
2383 self.pg1.set_table_ip4(vrf_id2)
2384 self.pg0.config_ip4()
2385 self.pg1.config_ip4()
Matus Fabian8008d7c2018-07-09 01:34:20 -07002386 self.pg0.resolve_arp()
2387 self.pg1.resolve_arp()
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002388
Matus Fabian2ba92e32017-08-21 07:05:03 -07002389 self.nat44_add_address(nat_ip1, vrf_id=vrf_id1)
2390 self.nat44_add_address(nat_ip2, vrf_id=vrf_id2)
2391 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2392 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
2393 self.vapi.nat44_interface_add_del_feature(self.pg2.sw_if_index,
2394 is_inside=0)
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002395
Matus Fabian8008d7c2018-07-09 01:34:20 -07002396 try:
2397 # first VRF
2398 pkts = self.create_stream_in(self.pg0, self.pg2)
2399 self.pg0.add_stream(pkts)
2400 self.pg_enable_capture(self.pg_interfaces)
2401 self.pg_start()
2402 capture = self.pg2.get_capture(len(pkts))
2403 self.verify_capture_out(capture, nat_ip1)
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002404
Matus Fabian8008d7c2018-07-09 01:34:20 -07002405 # second VRF
2406 pkts = self.create_stream_in(self.pg1, self.pg2)
2407 self.pg1.add_stream(pkts)
2408 self.pg_enable_capture(self.pg_interfaces)
2409 self.pg_start()
2410 capture = self.pg2.get_capture(len(pkts))
2411 self.verify_capture_out(capture, nat_ip2)
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002412
Matus Fabian8008d7c2018-07-09 01:34:20 -07002413 finally:
2414 self.pg0.unconfig_ip4()
2415 self.pg1.unconfig_ip4()
2416 self.pg0.set_table_ip4(0)
2417 self.pg1.set_table_ip4(0)
2418 self.pg0.config_ip4()
2419 self.pg1.config_ip4()
2420 self.pg0.resolve_arp()
2421 self.pg1.resolve_arp()
2422 self.vapi.ip_table_add_del(vrf_id1, is_add=0)
2423 self.vapi.ip_table_add_del(vrf_id2, is_add=0)
Neale Ranns15002542017-09-10 04:39:11 -07002424
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002425 def test_vrf_feature_independent(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002426 """ NAT44 tenant VRF independent address pool mode """
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002427
2428 nat_ip1 = "10.0.0.10"
2429 nat_ip2 = "10.0.0.11"
2430
Matus Fabian2ba92e32017-08-21 07:05:03 -07002431 self.nat44_add_address(nat_ip1)
Matus Fabian51e759f2017-12-07 23:22:51 -08002432 self.nat44_add_address(nat_ip2, vrf_id=99)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002433 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2434 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
2435 self.vapi.nat44_interface_add_del_feature(self.pg2.sw_if_index,
2436 is_inside=0)
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002437
2438 # first VRF
2439 pkts = self.create_stream_in(self.pg0, self.pg2)
2440 self.pg0.add_stream(pkts)
2441 self.pg_enable_capture(self.pg_interfaces)
2442 self.pg_start()
2443 capture = self.pg2.get_capture(len(pkts))
2444 self.verify_capture_out(capture, nat_ip1)
2445
2446 # second VRF
2447 pkts = self.create_stream_in(self.pg1, self.pg2)
2448 self.pg1.add_stream(pkts)
2449 self.pg_enable_capture(self.pg_interfaces)
2450 self.pg_start()
2451 capture = self.pg2.get_capture(len(pkts))
2452 self.verify_capture_out(capture, nat_ip1)
2453
Martin Gálik406eb1d2017-05-04 04:35:04 -07002454 def test_dynamic_ipless_interfaces(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002455 """ NAT44 interfaces without configured IP address """
Martin Gálik406eb1d2017-05-04 04:35:04 -07002456
2457 self.vapi.ip_neighbor_add_del(self.pg7.sw_if_index,
Ole Troan895b6e82017-10-20 13:28:20 +02002458 mactobinary(self.pg7.remote_mac),
Martin Gálik406eb1d2017-05-04 04:35:04 -07002459 self.pg7.remote_ip4n,
2460 is_static=1)
2461 self.vapi.ip_neighbor_add_del(self.pg8.sw_if_index,
Ole Troan895b6e82017-10-20 13:28:20 +02002462 mactobinary(self.pg8.remote_mac),
Martin Gálik406eb1d2017-05-04 04:35:04 -07002463 self.pg8.remote_ip4n,
2464 is_static=1)
2465
2466 self.vapi.ip_add_del_route(dst_address=self.pg7.remote_ip4n,
2467 dst_address_length=32,
2468 next_hop_address=self.pg7.remote_ip4n,
2469 next_hop_sw_if_index=self.pg7.sw_if_index)
2470 self.vapi.ip_add_del_route(dst_address=self.pg8.remote_ip4n,
2471 dst_address_length=32,
2472 next_hop_address=self.pg8.remote_ip4n,
2473 next_hop_sw_if_index=self.pg8.sw_if_index)
2474
Matus Fabian2ba92e32017-08-21 07:05:03 -07002475 self.nat44_add_address(self.nat_addr)
2476 self.vapi.nat44_interface_add_del_feature(self.pg7.sw_if_index)
2477 self.vapi.nat44_interface_add_del_feature(self.pg8.sw_if_index,
2478 is_inside=0)
Martin Gálik406eb1d2017-05-04 04:35:04 -07002479
2480 # in2out
2481 pkts = self.create_stream_in(self.pg7, self.pg8)
2482 self.pg7.add_stream(pkts)
2483 self.pg_enable_capture(self.pg_interfaces)
2484 self.pg_start()
2485 capture = self.pg8.get_capture(len(pkts))
2486 self.verify_capture_out(capture)
2487
2488 # out2in
Matus Fabian2ba92e32017-08-21 07:05:03 -07002489 pkts = self.create_stream_out(self.pg8, self.nat_addr)
Martin Gálik406eb1d2017-05-04 04:35:04 -07002490 self.pg8.add_stream(pkts)
2491 self.pg_enable_capture(self.pg_interfaces)
2492 self.pg_start()
2493 capture = self.pg7.get_capture(len(pkts))
2494 self.verify_capture_in(capture, self.pg7)
2495
2496 def test_static_ipless_interfaces(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002497 """ NAT44 interfaces without configured IP address - 1:1 NAT """
Martin Gálik406eb1d2017-05-04 04:35:04 -07002498
2499 self.vapi.ip_neighbor_add_del(self.pg7.sw_if_index,
Ole Troan895b6e82017-10-20 13:28:20 +02002500 mactobinary(self.pg7.remote_mac),
Martin Gálik406eb1d2017-05-04 04:35:04 -07002501 self.pg7.remote_ip4n,
2502 is_static=1)
2503 self.vapi.ip_neighbor_add_del(self.pg8.sw_if_index,
Ole Troan895b6e82017-10-20 13:28:20 +02002504 mactobinary(self.pg8.remote_mac),
Martin Gálik406eb1d2017-05-04 04:35:04 -07002505 self.pg8.remote_ip4n,
2506 is_static=1)
2507
2508 self.vapi.ip_add_del_route(dst_address=self.pg7.remote_ip4n,
2509 dst_address_length=32,
2510 next_hop_address=self.pg7.remote_ip4n,
2511 next_hop_sw_if_index=self.pg7.sw_if_index)
2512 self.vapi.ip_add_del_route(dst_address=self.pg8.remote_ip4n,
2513 dst_address_length=32,
2514 next_hop_address=self.pg8.remote_ip4n,
2515 next_hop_sw_if_index=self.pg8.sw_if_index)
2516
Matus Fabian2ba92e32017-08-21 07:05:03 -07002517 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr)
2518 self.vapi.nat44_interface_add_del_feature(self.pg7.sw_if_index)
2519 self.vapi.nat44_interface_add_del_feature(self.pg8.sw_if_index,
2520 is_inside=0)
Martin Gálik406eb1d2017-05-04 04:35:04 -07002521
2522 # out2in
2523 pkts = self.create_stream_out(self.pg8)
2524 self.pg8.add_stream(pkts)
2525 self.pg_enable_capture(self.pg_interfaces)
2526 self.pg_start()
2527 capture = self.pg7.get_capture(len(pkts))
2528 self.verify_capture_in(capture, self.pg7)
2529
2530 # in2out
2531 pkts = self.create_stream_in(self.pg7, self.pg8)
2532 self.pg7.add_stream(pkts)
2533 self.pg_enable_capture(self.pg_interfaces)
2534 self.pg_start()
2535 capture = self.pg8.get_capture(len(pkts))
Matus Fabian2ba92e32017-08-21 07:05:03 -07002536 self.verify_capture_out(capture, self.nat_addr, True)
Martin Gálik406eb1d2017-05-04 04:35:04 -07002537
2538 def test_static_with_port_ipless_interfaces(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002539 """ NAT44 interfaces without configured IP address - 1:1 NAPT """
Martin Gálik406eb1d2017-05-04 04:35:04 -07002540
2541 self.tcp_port_out = 30606
2542 self.udp_port_out = 30607
2543 self.icmp_id_out = 30608
2544
2545 self.vapi.ip_neighbor_add_del(self.pg7.sw_if_index,
Ole Troan895b6e82017-10-20 13:28:20 +02002546 mactobinary(self.pg7.remote_mac),
Martin Gálik406eb1d2017-05-04 04:35:04 -07002547 self.pg7.remote_ip4n,
2548 is_static=1)
2549 self.vapi.ip_neighbor_add_del(self.pg8.sw_if_index,
Ole Troan895b6e82017-10-20 13:28:20 +02002550 mactobinary(self.pg8.remote_mac),
Martin Gálik406eb1d2017-05-04 04:35:04 -07002551 self.pg8.remote_ip4n,
2552 is_static=1)
2553
2554 self.vapi.ip_add_del_route(dst_address=self.pg7.remote_ip4n,
2555 dst_address_length=32,
2556 next_hop_address=self.pg7.remote_ip4n,
2557 next_hop_sw_if_index=self.pg7.sw_if_index)
2558 self.vapi.ip_add_del_route(dst_address=self.pg8.remote_ip4n,
2559 dst_address_length=32,
2560 next_hop_address=self.pg8.remote_ip4n,
2561 next_hop_sw_if_index=self.pg8.sw_if_index)
2562
Matus Fabian2ba92e32017-08-21 07:05:03 -07002563 self.nat44_add_address(self.nat_addr)
2564 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
2565 self.tcp_port_in, self.tcp_port_out,
2566 proto=IP_PROTOS.tcp)
2567 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
2568 self.udp_port_in, self.udp_port_out,
2569 proto=IP_PROTOS.udp)
2570 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
2571 self.icmp_id_in, self.icmp_id_out,
2572 proto=IP_PROTOS.icmp)
2573 self.vapi.nat44_interface_add_del_feature(self.pg7.sw_if_index)
2574 self.vapi.nat44_interface_add_del_feature(self.pg8.sw_if_index,
2575 is_inside=0)
Martin Gálik406eb1d2017-05-04 04:35:04 -07002576
2577 # out2in
2578 pkts = self.create_stream_out(self.pg8)
2579 self.pg8.add_stream(pkts)
2580 self.pg_enable_capture(self.pg_interfaces)
2581 self.pg_start()
2582 capture = self.pg7.get_capture(len(pkts))
2583 self.verify_capture_in(capture, self.pg7)
2584
2585 # in2out
2586 pkts = self.create_stream_in(self.pg7, self.pg8)
2587 self.pg7.add_stream(pkts)
2588 self.pg_enable_capture(self.pg_interfaces)
2589 self.pg_start()
2590 capture = self.pg8.get_capture(len(pkts))
2591 self.verify_capture_out(capture)
2592
Matus Fabian328dbc82017-06-19 04:28:04 -07002593 def test_static_unknown_proto(self):
2594 """ 1:1 NAT translate packet with unknown protocol """
2595 nat_ip = "10.0.0.10"
Matus Fabian2ba92e32017-08-21 07:05:03 -07002596 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
2597 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2598 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2599 is_inside=0)
Matus Fabian328dbc82017-06-19 04:28:04 -07002600
2601 # in2out
2602 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2603 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2604 GRE() /
Matus Fabian1e8db5f2017-06-20 01:45:49 -07002605 IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4) /
Matus Fabian328dbc82017-06-19 04:28:04 -07002606 TCP(sport=1234, dport=1234))
2607 self.pg0.add_stream(p)
2608 self.pg_enable_capture(self.pg_interfaces)
2609 self.pg_start()
2610 p = self.pg1.get_capture(1)
2611 packet = p[0]
2612 try:
2613 self.assertEqual(packet[IP].src, nat_ip)
2614 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
2615 self.assertTrue(packet.haslayer(GRE))
Klement Sekerad81ae412018-05-16 10:52:54 +02002616 self.assert_packet_checksums_valid(packet)
Matus Fabian328dbc82017-06-19 04:28:04 -07002617 except:
2618 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2619 raise
2620
2621 # out2in
2622 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
2623 IP(src=self.pg1.remote_ip4, dst=nat_ip) /
2624 GRE() /
Matus Fabian1e8db5f2017-06-20 01:45:49 -07002625 IP(src=self.pg3.remote_ip4, dst=self.pg2.remote_ip4) /
Matus Fabian328dbc82017-06-19 04:28:04 -07002626 TCP(sport=1234, dport=1234))
2627 self.pg1.add_stream(p)
2628 self.pg_enable_capture(self.pg_interfaces)
2629 self.pg_start()
2630 p = self.pg0.get_capture(1)
2631 packet = p[0]
2632 try:
2633 self.assertEqual(packet[IP].src, self.pg1.remote_ip4)
2634 self.assertEqual(packet[IP].dst, self.pg0.remote_ip4)
2635 self.assertTrue(packet.haslayer(GRE))
Klement Sekerad81ae412018-05-16 10:52:54 +02002636 self.assert_packet_checksums_valid(packet)
Matus Fabian328dbc82017-06-19 04:28:04 -07002637 except:
2638 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2639 raise
2640
Matus Fabian7968e6c2017-07-06 05:37:49 -07002641 def test_hairpinning_static_unknown_proto(self):
Matus Fabian1e8db5f2017-06-20 01:45:49 -07002642 """ 1:1 NAT translate packet with unknown protocol - hairpinning """
2643
2644 host = self.pg0.remote_hosts[0]
2645 server = self.pg0.remote_hosts[1]
2646
2647 host_nat_ip = "10.0.0.10"
2648 server_nat_ip = "10.0.0.11"
2649
Matus Fabian2ba92e32017-08-21 07:05:03 -07002650 self.nat44_add_static_mapping(host.ip4, host_nat_ip)
2651 self.nat44_add_static_mapping(server.ip4, server_nat_ip)
2652 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2653 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2654 is_inside=0)
Matus Fabian1e8db5f2017-06-20 01:45:49 -07002655
2656 # host to server
2657 p = (Ether(dst=self.pg0.local_mac, src=host.mac) /
2658 IP(src=host.ip4, dst=server_nat_ip) /
2659 GRE() /
2660 IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4) /
2661 TCP(sport=1234, dport=1234))
2662 self.pg0.add_stream(p)
2663 self.pg_enable_capture(self.pg_interfaces)
2664 self.pg_start()
2665 p = self.pg0.get_capture(1)
2666 packet = p[0]
2667 try:
2668 self.assertEqual(packet[IP].src, host_nat_ip)
2669 self.assertEqual(packet[IP].dst, server.ip4)
2670 self.assertTrue(packet.haslayer(GRE))
Klement Sekerad81ae412018-05-16 10:52:54 +02002671 self.assert_packet_checksums_valid(packet)
Matus Fabian1e8db5f2017-06-20 01:45:49 -07002672 except:
2673 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2674 raise
2675
2676 # server to host
2677 p = (Ether(dst=self.pg0.local_mac, src=server.mac) /
2678 IP(src=server.ip4, dst=host_nat_ip) /
2679 GRE() /
2680 IP(src=self.pg3.remote_ip4, dst=self.pg2.remote_ip4) /
2681 TCP(sport=1234, dport=1234))
2682 self.pg0.add_stream(p)
2683 self.pg_enable_capture(self.pg_interfaces)
2684 self.pg_start()
2685 p = self.pg0.get_capture(1)
2686 packet = p[0]
2687 try:
2688 self.assertEqual(packet[IP].src, server_nat_ip)
2689 self.assertEqual(packet[IP].dst, host.ip4)
2690 self.assertTrue(packet.haslayer(GRE))
Klement Sekerad81ae412018-05-16 10:52:54 +02002691 self.assert_packet_checksums_valid(packet)
Matus Fabian1e8db5f2017-06-20 01:45:49 -07002692 except:
2693 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2694 raise
2695
Matus Fabian93d84c92017-07-19 08:06:01 -07002696 def test_output_feature(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002697 """ NAT44 interface output feature (in2out postrouting) """
2698 self.nat44_add_address(self.nat_addr)
2699 self.vapi.nat44_interface_add_del_output_feature(self.pg0.sw_if_index)
Matus Fabianb2d2fc72017-09-10 22:17:47 -07002700 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index)
2701 self.vapi.nat44_interface_add_del_output_feature(self.pg3.sw_if_index,
Matus Fabian2ba92e32017-08-21 07:05:03 -07002702 is_inside=0)
Matus Fabian93d84c92017-07-19 08:06:01 -07002703
2704 # in2out
Matus Fabianb2d2fc72017-09-10 22:17:47 -07002705 pkts = self.create_stream_in(self.pg0, self.pg3)
Matus Fabian93d84c92017-07-19 08:06:01 -07002706 self.pg0.add_stream(pkts)
2707 self.pg_enable_capture(self.pg_interfaces)
2708 self.pg_start()
Matus Fabianb2d2fc72017-09-10 22:17:47 -07002709 capture = self.pg3.get_capture(len(pkts))
Matus Fabian93d84c92017-07-19 08:06:01 -07002710 self.verify_capture_out(capture)
2711
2712 # out2in
Matus Fabianb2d2fc72017-09-10 22:17:47 -07002713 pkts = self.create_stream_out(self.pg3)
2714 self.pg3.add_stream(pkts)
Matus Fabian93d84c92017-07-19 08:06:01 -07002715 self.pg_enable_capture(self.pg_interfaces)
2716 self.pg_start()
2717 capture = self.pg0.get_capture(len(pkts))
2718 self.verify_capture_in(capture, self.pg0)
2719
Matus Fabianb2d2fc72017-09-10 22:17:47 -07002720 # from non-NAT interface to NAT inside interface
2721 pkts = self.create_stream_in(self.pg2, self.pg0)
2722 self.pg2.add_stream(pkts)
2723 self.pg_enable_capture(self.pg_interfaces)
2724 self.pg_start()
2725 capture = self.pg0.get_capture(len(pkts))
2726 self.verify_capture_no_translation(capture, self.pg2, self.pg0)
2727
Matus Fabian93d84c92017-07-19 08:06:01 -07002728 def test_output_feature_vrf_aware(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002729 """ NAT44 interface output feature VRF aware (in2out postrouting) """
Matus Fabian93d84c92017-07-19 08:06:01 -07002730 nat_ip_vrf10 = "10.0.0.10"
2731 nat_ip_vrf20 = "10.0.0.20"
2732
2733 self.vapi.ip_add_del_route(dst_address=self.pg3.remote_ip4n,
2734 dst_address_length=32,
2735 next_hop_address=self.pg3.remote_ip4n,
2736 next_hop_sw_if_index=self.pg3.sw_if_index,
2737 table_id=10)
2738 self.vapi.ip_add_del_route(dst_address=self.pg3.remote_ip4n,
2739 dst_address_length=32,
2740 next_hop_address=self.pg3.remote_ip4n,
2741 next_hop_sw_if_index=self.pg3.sw_if_index,
2742 table_id=20)
2743
Matus Fabian2ba92e32017-08-21 07:05:03 -07002744 self.nat44_add_address(nat_ip_vrf10, vrf_id=10)
2745 self.nat44_add_address(nat_ip_vrf20, vrf_id=20)
2746 self.vapi.nat44_interface_add_del_output_feature(self.pg4.sw_if_index)
2747 self.vapi.nat44_interface_add_del_output_feature(self.pg6.sw_if_index)
2748 self.vapi.nat44_interface_add_del_output_feature(self.pg3.sw_if_index,
2749 is_inside=0)
Matus Fabian93d84c92017-07-19 08:06:01 -07002750
2751 # in2out VRF 10
2752 pkts = self.create_stream_in(self.pg4, self.pg3)
2753 self.pg4.add_stream(pkts)
2754 self.pg_enable_capture(self.pg_interfaces)
2755 self.pg_start()
2756 capture = self.pg3.get_capture(len(pkts))
2757 self.verify_capture_out(capture, nat_ip=nat_ip_vrf10)
2758
2759 # out2in VRF 10
2760 pkts = self.create_stream_out(self.pg3, dst_ip=nat_ip_vrf10)
2761 self.pg3.add_stream(pkts)
2762 self.pg_enable_capture(self.pg_interfaces)
2763 self.pg_start()
2764 capture = self.pg4.get_capture(len(pkts))
2765 self.verify_capture_in(capture, self.pg4)
2766
2767 # in2out VRF 20
2768 pkts = self.create_stream_in(self.pg6, self.pg3)
2769 self.pg6.add_stream(pkts)
2770 self.pg_enable_capture(self.pg_interfaces)
2771 self.pg_start()
2772 capture = self.pg3.get_capture(len(pkts))
2773 self.verify_capture_out(capture, nat_ip=nat_ip_vrf20)
2774
2775 # out2in VRF 20
2776 pkts = self.create_stream_out(self.pg3, dst_ip=nat_ip_vrf20)
2777 self.pg3.add_stream(pkts)
2778 self.pg_enable_capture(self.pg_interfaces)
2779 self.pg_start()
2780 capture = self.pg6.get_capture(len(pkts))
2781 self.verify_capture_in(capture, self.pg6)
2782
Matus Fabian161c59c2017-07-21 03:46:03 -07002783 def test_output_feature_hairpinning(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002784 """ NAT44 interface output feature hairpinning (in2out postrouting) """
Matus Fabian93d84c92017-07-19 08:06:01 -07002785 host = self.pg0.remote_hosts[0]
2786 server = self.pg0.remote_hosts[1]
2787 host_in_port = 1234
2788 host_out_port = 0
2789 server_in_port = 5678
2790 server_out_port = 8765
2791
Matus Fabian2ba92e32017-08-21 07:05:03 -07002792 self.nat44_add_address(self.nat_addr)
2793 self.vapi.nat44_interface_add_del_output_feature(self.pg0.sw_if_index)
2794 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
2795 is_inside=0)
Matus Fabian93d84c92017-07-19 08:06:01 -07002796
2797 # add static mapping for server
Matus Fabian2ba92e32017-08-21 07:05:03 -07002798 self.nat44_add_static_mapping(server.ip4, self.nat_addr,
2799 server_in_port, server_out_port,
2800 proto=IP_PROTOS.tcp)
Matus Fabian93d84c92017-07-19 08:06:01 -07002801
2802 # send packet from host to server
2803 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002804 IP(src=host.ip4, dst=self.nat_addr) /
Matus Fabian93d84c92017-07-19 08:06:01 -07002805 TCP(sport=host_in_port, dport=server_out_port))
2806 self.pg0.add_stream(p)
2807 self.pg_enable_capture(self.pg_interfaces)
2808 self.pg_start()
2809 capture = self.pg0.get_capture(1)
2810 p = capture[0]
2811 try:
2812 ip = p[IP]
2813 tcp = p[TCP]
Matus Fabian2ba92e32017-08-21 07:05:03 -07002814 self.assertEqual(ip.src, self.nat_addr)
Matus Fabian93d84c92017-07-19 08:06:01 -07002815 self.assertEqual(ip.dst, server.ip4)
2816 self.assertNotEqual(tcp.sport, host_in_port)
2817 self.assertEqual(tcp.dport, server_in_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02002818 self.assert_packet_checksums_valid(p)
Matus Fabian93d84c92017-07-19 08:06:01 -07002819 host_out_port = tcp.sport
2820 except:
2821 self.logger.error(ppp("Unexpected or invalid packet:", p))
2822 raise
2823
2824 # send reply from server to host
2825 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002826 IP(src=server.ip4, dst=self.nat_addr) /
Matus Fabian93d84c92017-07-19 08:06:01 -07002827 TCP(sport=server_in_port, dport=host_out_port))
2828 self.pg0.add_stream(p)
2829 self.pg_enable_capture(self.pg_interfaces)
2830 self.pg_start()
2831 capture = self.pg0.get_capture(1)
2832 p = capture[0]
2833 try:
2834 ip = p[IP]
2835 tcp = p[TCP]
Matus Fabian2ba92e32017-08-21 07:05:03 -07002836 self.assertEqual(ip.src, self.nat_addr)
Matus Fabian93d84c92017-07-19 08:06:01 -07002837 self.assertEqual(ip.dst, host.ip4)
2838 self.assertEqual(tcp.sport, server_out_port)
2839 self.assertEqual(tcp.dport, host_in_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02002840 self.assert_packet_checksums_valid(p)
Matus Fabian93d84c92017-07-19 08:06:01 -07002841 except:
Matus Fabiane82488f2018-01-18 03:38:45 -08002842 self.logger.error(ppp("Unexpected or invalid packet:", p))
Matus Fabian93d84c92017-07-19 08:06:01 -07002843 raise
2844
Matus Fabian36ea2d62017-10-24 04:13:49 -07002845 def test_one_armed_nat44(self):
2846 """ One armed NAT44 """
2847 remote_host = self.pg9.remote_hosts[0]
2848 local_host = self.pg9.remote_hosts[1]
2849 external_port = 0
2850
2851 self.nat44_add_address(self.nat_addr)
2852 self.vapi.nat44_interface_add_del_feature(self.pg9.sw_if_index)
2853 self.vapi.nat44_interface_add_del_feature(self.pg9.sw_if_index,
2854 is_inside=0)
2855
2856 # in2out
2857 p = (Ether(src=self.pg9.remote_mac, dst=self.pg9.local_mac) /
2858 IP(src=local_host.ip4, dst=remote_host.ip4) /
2859 TCP(sport=12345, dport=80))
2860 self.pg9.add_stream(p)
2861 self.pg_enable_capture(self.pg_interfaces)
2862 self.pg_start()
2863 capture = self.pg9.get_capture(1)
2864 p = capture[0]
2865 try:
2866 ip = p[IP]
2867 tcp = p[TCP]
2868 self.assertEqual(ip.src, self.nat_addr)
2869 self.assertEqual(ip.dst, remote_host.ip4)
2870 self.assertNotEqual(tcp.sport, 12345)
2871 external_port = tcp.sport
2872 self.assertEqual(tcp.dport, 80)
Klement Sekerad81ae412018-05-16 10:52:54 +02002873 self.assert_packet_checksums_valid(p)
Matus Fabian36ea2d62017-10-24 04:13:49 -07002874 except:
2875 self.logger.error(ppp("Unexpected or invalid packet:", p))
2876 raise
2877
2878 # out2in
2879 p = (Ether(src=self.pg9.remote_mac, dst=self.pg9.local_mac) /
2880 IP(src=remote_host.ip4, dst=self.nat_addr) /
2881 TCP(sport=80, dport=external_port))
2882 self.pg9.add_stream(p)
2883 self.pg_enable_capture(self.pg_interfaces)
2884 self.pg_start()
2885 capture = self.pg9.get_capture(1)
2886 p = capture[0]
2887 try:
2888 ip = p[IP]
2889 tcp = p[TCP]
2890 self.assertEqual(ip.src, remote_host.ip4)
2891 self.assertEqual(ip.dst, local_host.ip4)
2892 self.assertEqual(tcp.sport, 80)
2893 self.assertEqual(tcp.dport, 12345)
Klement Sekerad81ae412018-05-16 10:52:54 +02002894 self.assert_packet_checksums_valid(p)
Matus Fabian36ea2d62017-10-24 04:13:49 -07002895 except:
2896 self.logger.error(ppp("Unexpected or invalid packet:", p))
2897 raise
2898
Matus Fabian5ba86f72017-10-26 03:37:38 -07002899 def test_del_session(self):
2900 """ Delete NAT44 session """
2901 self.nat44_add_address(self.nat_addr)
2902 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2903 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2904 is_inside=0)
2905
2906 pkts = self.create_stream_in(self.pg0, self.pg1)
2907 self.pg0.add_stream(pkts)
2908 self.pg_enable_capture(self.pg_interfaces)
2909 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07002910 self.pg1.get_capture(len(pkts))
Matus Fabian5ba86f72017-10-26 03:37:38 -07002911
2912 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
2913 nsessions = len(sessions)
2914
2915 self.vapi.nat44_del_session(sessions[0].inside_ip_address,
2916 sessions[0].inside_port,
2917 sessions[0].protocol)
2918 self.vapi.nat44_del_session(sessions[1].outside_ip_address,
2919 sessions[1].outside_port,
2920 sessions[1].protocol,
2921 is_in=0)
2922
2923 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
2924 self.assertEqual(nsessions - len(sessions), 2)
2925
Matus Fabian68ba8802018-08-08 05:52:47 -07002926 self.vapi.nat44_del_session(sessions[0].inside_ip_address,
2927 sessions[0].inside_port,
2928 sessions[0].protocol)
2929
2930 self.verify_no_nat44_user()
2931
Matus Fabianefcd1e92017-08-15 06:59:19 -07002932 def test_set_get_reass(self):
2933 """ NAT44 set/get virtual fragmentation reassembly """
2934 reas_cfg1 = self.vapi.nat_get_reass()
2935
2936 self.vapi.nat_set_reass(timeout=reas_cfg1.ip4_timeout + 5,
2937 max_reass=reas_cfg1.ip4_max_reass * 2,
2938 max_frag=reas_cfg1.ip4_max_frag * 2)
2939
2940 reas_cfg2 = self.vapi.nat_get_reass()
2941
2942 self.assertEqual(reas_cfg1.ip4_timeout + 5, reas_cfg2.ip4_timeout)
2943 self.assertEqual(reas_cfg1.ip4_max_reass * 2, reas_cfg2.ip4_max_reass)
2944 self.assertEqual(reas_cfg1.ip4_max_frag * 2, reas_cfg2.ip4_max_frag)
2945
2946 self.vapi.nat_set_reass(drop_frag=1)
2947 self.assertTrue(self.vapi.nat_get_reass().ip4_drop_frag)
2948
2949 def test_frag_in_order(self):
2950 """ NAT44 translate fragments arriving in order """
2951 self.nat44_add_address(self.nat_addr)
2952 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2953 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2954 is_inside=0)
2955
2956 data = "A" * 4 + "B" * 16 + "C" * 3
2957 self.tcp_port_in = random.randint(1025, 65535)
2958
2959 reass = self.vapi.nat_reass_dump()
2960 reass_n_start = len(reass)
2961
2962 # in2out
2963 pkts = self.create_stream_frag(self.pg0,
2964 self.pg1.remote_ip4,
2965 self.tcp_port_in,
2966 20,
2967 data)
2968 self.pg0.add_stream(pkts)
2969 self.pg_enable_capture(self.pg_interfaces)
2970 self.pg_start()
2971 frags = self.pg1.get_capture(len(pkts))
2972 p = self.reass_frags_and_verify(frags,
2973 self.nat_addr,
2974 self.pg1.remote_ip4)
2975 self.assertEqual(p[TCP].dport, 20)
2976 self.assertNotEqual(p[TCP].sport, self.tcp_port_in)
2977 self.tcp_port_out = p[TCP].sport
2978 self.assertEqual(data, p[Raw].load)
2979
2980 # out2in
2981 pkts = self.create_stream_frag(self.pg1,
2982 self.nat_addr,
2983 20,
2984 self.tcp_port_out,
2985 data)
2986 self.pg1.add_stream(pkts)
2987 self.pg_enable_capture(self.pg_interfaces)
2988 self.pg_start()
2989 frags = self.pg0.get_capture(len(pkts))
2990 p = self.reass_frags_and_verify(frags,
2991 self.pg1.remote_ip4,
2992 self.pg0.remote_ip4)
2993 self.assertEqual(p[TCP].sport, 20)
2994 self.assertEqual(p[TCP].dport, self.tcp_port_in)
2995 self.assertEqual(data, p[Raw].load)
2996
2997 reass = self.vapi.nat_reass_dump()
2998 reass_n_end = len(reass)
2999
3000 self.assertEqual(reass_n_end - reass_n_start, 2)
3001
3002 def test_reass_hairpinning(self):
3003 """ NAT44 fragments hairpinning """
Matus Fabianefcd1e92017-08-15 06:59:19 -07003004 server = self.pg0.remote_hosts[1]
3005 host_in_port = random.randint(1025, 65535)
Matus Fabianefcd1e92017-08-15 06:59:19 -07003006 server_in_port = random.randint(1025, 65535)
3007 server_out_port = random.randint(1025, 65535)
3008 data = "A" * 4 + "B" * 16 + "C" * 3
3009
3010 self.nat44_add_address(self.nat_addr)
3011 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3012 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3013 is_inside=0)
3014 # add static mapping for server
3015 self.nat44_add_static_mapping(server.ip4, self.nat_addr,
3016 server_in_port, server_out_port,
3017 proto=IP_PROTOS.tcp)
3018
3019 # send packet from host to server
3020 pkts = self.create_stream_frag(self.pg0,
3021 self.nat_addr,
3022 host_in_port,
3023 server_out_port,
3024 data)
3025 self.pg0.add_stream(pkts)
3026 self.pg_enable_capture(self.pg_interfaces)
3027 self.pg_start()
3028 frags = self.pg0.get_capture(len(pkts))
3029 p = self.reass_frags_and_verify(frags,
3030 self.nat_addr,
3031 server.ip4)
3032 self.assertNotEqual(p[TCP].sport, host_in_port)
3033 self.assertEqual(p[TCP].dport, server_in_port)
3034 self.assertEqual(data, p[Raw].load)
3035
3036 def test_frag_out_of_order(self):
3037 """ NAT44 translate fragments arriving out of order """
3038 self.nat44_add_address(self.nat_addr)
3039 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3040 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3041 is_inside=0)
3042
3043 data = "A" * 4 + "B" * 16 + "C" * 3
3044 random.randint(1025, 65535)
3045
3046 # in2out
3047 pkts = self.create_stream_frag(self.pg0,
3048 self.pg1.remote_ip4,
3049 self.tcp_port_in,
3050 20,
3051 data)
3052 pkts.reverse()
3053 self.pg0.add_stream(pkts)
3054 self.pg_enable_capture(self.pg_interfaces)
3055 self.pg_start()
3056 frags = self.pg1.get_capture(len(pkts))
3057 p = self.reass_frags_and_verify(frags,
3058 self.nat_addr,
3059 self.pg1.remote_ip4)
3060 self.assertEqual(p[TCP].dport, 20)
3061 self.assertNotEqual(p[TCP].sport, self.tcp_port_in)
3062 self.tcp_port_out = p[TCP].sport
3063 self.assertEqual(data, p[Raw].load)
3064
3065 # out2in
3066 pkts = self.create_stream_frag(self.pg1,
3067 self.nat_addr,
3068 20,
3069 self.tcp_port_out,
3070 data)
3071 pkts.reverse()
3072 self.pg1.add_stream(pkts)
3073 self.pg_enable_capture(self.pg_interfaces)
3074 self.pg_start()
3075 frags = self.pg0.get_capture(len(pkts))
3076 p = self.reass_frags_and_verify(frags,
3077 self.pg1.remote_ip4,
3078 self.pg0.remote_ip4)
3079 self.assertEqual(p[TCP].sport, 20)
3080 self.assertEqual(p[TCP].dport, self.tcp_port_in)
3081 self.assertEqual(data, p[Raw].load)
3082
Matus Fabian27697102017-11-09 01:43:47 -08003083 def test_port_restricted(self):
3084 """ Port restricted NAT44 (MAP-E CE) """
3085 self.nat44_add_address(self.nat_addr)
3086 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3087 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3088 is_inside=0)
Matus Fabian5d28c7a2018-09-04 03:55:45 -07003089 self.vapi.nat_set_addr_and_port_alloc_alg(alg=1,
3090 psid_offset=6,
3091 psid_length=6,
3092 psid=10)
Matus Fabian27697102017-11-09 01:43:47 -08003093
3094 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3095 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3096 TCP(sport=4567, dport=22))
3097 self.pg0.add_stream(p)
3098 self.pg_enable_capture(self.pg_interfaces)
3099 self.pg_start()
3100 capture = self.pg1.get_capture(1)
3101 p = capture[0]
3102 try:
3103 ip = p[IP]
3104 tcp = p[TCP]
3105 self.assertEqual(ip.dst, self.pg1.remote_ip4)
3106 self.assertEqual(ip.src, self.nat_addr)
3107 self.assertEqual(tcp.dport, 22)
3108 self.assertNotEqual(tcp.sport, 4567)
3109 self.assertEqual((tcp.sport >> 6) & 63, 10)
Klement Sekerad81ae412018-05-16 10:52:54 +02003110 self.assert_packet_checksums_valid(p)
Matus Fabian27697102017-11-09 01:43:47 -08003111 except:
3112 self.logger.error(ppp("Unexpected or invalid packet:", p))
3113 raise
3114
Matus Fabian5d28c7a2018-09-04 03:55:45 -07003115 def test_port_range(self):
3116 """ External address port range """
3117 self.nat44_add_address(self.nat_addr)
3118 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3119 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3120 is_inside=0)
3121 self.vapi.nat_set_addr_and_port_alloc_alg(alg=2,
3122 start_port=1025,
3123 end_port=1027)
3124
3125 pkts = []
3126 for port in range(0, 5):
3127 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3128 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3129 TCP(sport=1125 + port))
3130 pkts.append(p)
3131 self.pg0.add_stream(pkts)
3132 self.pg_enable_capture(self.pg_interfaces)
3133 self.pg_start()
3134 capture = self.pg1.get_capture(3)
3135 for p in capture:
3136 tcp = p[TCP]
3137 self.assertGreaterEqual(tcp.sport, 1025)
3138 self.assertLessEqual(tcp.sport, 1027)
3139
Matus Fabiana6110b62018-06-13 05:39:07 -07003140 def test_ipfix_max_frags(self):
3141 """ IPFIX logging maximum fragments pending reassembly exceeded """
3142 self.nat44_add_address(self.nat_addr)
3143 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3144 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3145 is_inside=0)
Matus Fabiana7f8b222018-09-05 06:01:55 -07003146 self.vapi.nat_set_reass(max_frag=1)
Matus Fabiana6110b62018-06-13 05:39:07 -07003147 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
3148 src_address=self.pg3.local_ip4n,
3149 path_mtu=512,
3150 template_interval=10)
3151 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
3152 src_port=self.ipfix_src_port)
3153
3154 data = "A" * 4 + "B" * 16 + "C" * 3
3155 self.tcp_port_in = random.randint(1025, 65535)
3156 pkts = self.create_stream_frag(self.pg0,
3157 self.pg1.remote_ip4,
3158 self.tcp_port_in,
3159 20,
3160 data)
Matus Fabiana7f8b222018-09-05 06:01:55 -07003161 pkts.reverse()
3162 self.pg0.add_stream(pkts)
Matus Fabiana6110b62018-06-13 05:39:07 -07003163 self.pg_enable_capture(self.pg_interfaces)
3164 self.pg_start()
3165 self.pg1.assert_nothing_captured()
3166 sleep(1)
3167 self.vapi.cli("ipfix flush") # FIXME this should be an API call
3168 capture = self.pg3.get_capture(9)
3169 ipfix = IPFIXDecoder()
3170 # first load template
3171 for p in capture:
3172 self.assertTrue(p.haslayer(IPFIX))
3173 self.assertEqual(p[IP].src, self.pg3.local_ip4)
3174 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
3175 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
3176 self.assertEqual(p[UDP].dport, 4739)
3177 self.assertEqual(p[IPFIX].observationDomainID,
3178 self.ipfix_domain_id)
3179 if p.haslayer(Template):
3180 ipfix.add_template(p.getlayer(Template))
3181 # verify events in data set
3182 for p in capture:
3183 if p.haslayer(Data):
3184 data = ipfix.decode_data_set(p.getlayer(Set))
Matus Fabiana7f8b222018-09-05 06:01:55 -07003185 self.verify_ipfix_max_fragments_ip4(data, 1,
Matus Fabiana6110b62018-06-13 05:39:07 -07003186 self.pg0.remote_ip4n)
3187
Matus Fabian8008d7c2018-07-09 01:34:20 -07003188 def test_multiple_outside_vrf(self):
3189 """ Multiple outside VRF """
3190 vrf_id1 = 1
3191 vrf_id2 = 2
3192
3193 self.pg1.unconfig_ip4()
3194 self.pg2.unconfig_ip4()
3195 self.vapi.ip_table_add_del(vrf_id1, is_add=1)
3196 self.vapi.ip_table_add_del(vrf_id2, is_add=1)
3197 self.pg1.set_table_ip4(vrf_id1)
3198 self.pg2.set_table_ip4(vrf_id2)
3199 self.pg1.config_ip4()
3200 self.pg2.config_ip4()
3201 self.pg1.resolve_arp()
3202 self.pg2.resolve_arp()
3203
3204 self.nat44_add_address(self.nat_addr)
3205 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3206 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3207 is_inside=0)
3208 self.vapi.nat44_interface_add_del_feature(self.pg2.sw_if_index,
3209 is_inside=0)
3210
3211 try:
3212 # first VRF
3213 pkts = self.create_stream_in(self.pg0, self.pg1)
3214 self.pg0.add_stream(pkts)
3215 self.pg_enable_capture(self.pg_interfaces)
3216 self.pg_start()
3217 capture = self.pg1.get_capture(len(pkts))
3218 self.verify_capture_out(capture, self.nat_addr)
3219
3220 pkts = self.create_stream_out(self.pg1, self.nat_addr)
3221 self.pg1.add_stream(pkts)
3222 self.pg_enable_capture(self.pg_interfaces)
3223 self.pg_start()
3224 capture = self.pg0.get_capture(len(pkts))
3225 self.verify_capture_in(capture, self.pg0)
3226
3227 self.tcp_port_in = 60303
3228 self.udp_port_in = 60304
3229 self.icmp_id_in = 60305
3230
3231 # second VRF
3232 pkts = self.create_stream_in(self.pg0, self.pg2)
3233 self.pg0.add_stream(pkts)
3234 self.pg_enable_capture(self.pg_interfaces)
3235 self.pg_start()
3236 capture = self.pg2.get_capture(len(pkts))
3237 self.verify_capture_out(capture, self.nat_addr)
3238
3239 pkts = self.create_stream_out(self.pg2, self.nat_addr)
3240 self.pg2.add_stream(pkts)
3241 self.pg_enable_capture(self.pg_interfaces)
3242 self.pg_start()
3243 capture = self.pg0.get_capture(len(pkts))
3244 self.verify_capture_in(capture, self.pg0)
3245
3246 finally:
3247 self.pg1.unconfig_ip4()
3248 self.pg2.unconfig_ip4()
3249 self.pg1.set_table_ip4(0)
3250 self.pg2.set_table_ip4(0)
3251 self.pg1.config_ip4()
3252 self.pg2.config_ip4()
3253 self.pg1.resolve_arp()
3254 self.pg2.resolve_arp()
3255
Matus Fabian878c6462018-08-23 00:33:35 -07003256 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
3257 def test_session_timeout(self):
3258 """ NAT44 session timeouts """
3259 self.nat44_add_address(self.nat_addr)
3260 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3261 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3262 is_inside=0)
3263 self.vapi.nat_set_timeouts(udp=5)
3264
3265 max_sessions = 1000
3266 pkts = []
3267 for i in range(0, max_sessions):
3268 src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
3269 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3270 IP(src=src, dst=self.pg1.remote_ip4) /
3271 UDP(sport=1025, dport=53))
3272 pkts.append(p)
3273 self.pg0.add_stream(pkts)
3274 self.pg_enable_capture(self.pg_interfaces)
3275 self.pg_start()
3276 self.pg1.get_capture(max_sessions)
3277
3278 sleep(6)
3279
3280 pkts = []
3281 for i in range(0, max_sessions):
3282 src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
3283 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3284 IP(src=src, dst=self.pg1.remote_ip4) /
3285 UDP(sport=1026, dport=53))
3286 pkts.append(p)
3287 self.pg0.add_stream(pkts)
3288 self.pg_enable_capture(self.pg_interfaces)
3289 self.pg_start()
3290 self.pg1.get_capture(max_sessions)
3291
3292 nsessions = 0
3293 users = self.vapi.nat44_user_dump()
3294 for user in users:
3295 nsessions = nsessions + user.nsessions
3296 self.assertLess(nsessions, 2 * max_sessions)
3297
Matus Fabiana6110b62018-06-13 05:39:07 -07003298 def tearDown(self):
3299 super(TestNAT44, self).tearDown()
3300 if not self.vpp_dead:
3301 self.logger.info(self.vapi.cli("show nat44 addresses"))
3302 self.logger.info(self.vapi.cli("show nat44 interfaces"))
3303 self.logger.info(self.vapi.cli("show nat44 static mappings"))
3304 self.logger.info(self.vapi.cli("show nat44 interface address"))
3305 self.logger.info(self.vapi.cli("show nat44 sessions detail"))
3306 self.logger.info(self.vapi.cli("show nat virtual-reassembly"))
3307 self.logger.info(self.vapi.cli("show nat44 hash tables detail"))
Matus Fabian878c6462018-08-23 00:33:35 -07003308 self.logger.info(self.vapi.cli("show nat timeouts"))
Matus Fabian5d28c7a2018-09-04 03:55:45 -07003309 self.logger.info(
3310 self.vapi.cli("show nat addr-port-assignment-alg"))
Matus Fabiana6110b62018-06-13 05:39:07 -07003311 self.clear_nat44()
3312 self.vapi.cli("clear logging")
3313
3314
3315class TestNAT44EndpointDependent(MethodHolder):
3316 """ Endpoint-Dependent mapping and filtering test cases """
3317
3318 @classmethod
3319 def setUpConstants(cls):
3320 super(TestNAT44EndpointDependent, cls).setUpConstants()
3321 cls.vpp_cmdline.extend(["nat", "{", "endpoint-dependent", "}"])
3322
3323 @classmethod
3324 def setUpClass(cls):
3325 super(TestNAT44EndpointDependent, cls).setUpClass()
3326 cls.vapi.cli("set log class nat level debug")
3327 try:
3328 cls.tcp_port_in = 6303
3329 cls.tcp_port_out = 6303
3330 cls.udp_port_in = 6304
3331 cls.udp_port_out = 6304
3332 cls.icmp_id_in = 6305
3333 cls.icmp_id_out = 6305
3334 cls.nat_addr = '10.0.0.3'
3335 cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
3336 cls.ipfix_src_port = 4739
3337 cls.ipfix_domain_id = 1
3338 cls.tcp_external_port = 80
3339
Matus Fabian8008d7c2018-07-09 01:34:20 -07003340 cls.create_pg_interfaces(range(7))
Matus Fabiana6110b62018-06-13 05:39:07 -07003341 cls.interfaces = list(cls.pg_interfaces[0:3])
3342
3343 for i in cls.interfaces:
3344 i.admin_up()
3345 i.config_ip4()
3346 i.resolve_arp()
3347
3348 cls.pg0.generate_remote_hosts(3)
3349 cls.pg0.configure_ipv4_neighbors()
3350
3351 cls.pg3.admin_up()
3352
3353 cls.pg4.generate_remote_hosts(2)
3354 cls.pg4.config_ip4()
3355 ip_addr_n = socket.inet_pton(socket.AF_INET, "10.0.0.1")
3356 cls.vapi.sw_interface_add_del_address(cls.pg4.sw_if_index,
3357 ip_addr_n,
3358 24)
3359 cls.pg4.admin_up()
3360 cls.pg4.resolve_arp()
3361 cls.pg4._remote_hosts[1]._ip4 = cls.pg4._remote_hosts[0]._ip4
3362 cls.pg4.resolve_arp()
3363
Matus Fabian8008d7c2018-07-09 01:34:20 -07003364 zero_ip4n = socket.inet_pton(socket.AF_INET, "0.0.0.0")
3365 cls.vapi.ip_table_add_del(1, is_add=1)
3366
3367 cls.pg5._local_ip4 = "10.1.1.1"
3368 cls.pg5._local_ip4n = socket.inet_pton(socket.AF_INET,
3369 cls.pg5.local_ip4)
3370 cls.pg5._remote_hosts[0]._ip4 = "10.1.1.2"
3371 cls.pg5._remote_hosts[0]._ip4n = socket.inet_pton(
3372 socket.AF_INET, cls.pg5.remote_ip4)
3373 cls.pg5.set_table_ip4(1)
3374 cls.pg5.config_ip4()
3375 cls.pg5.admin_up()
3376 cls.vapi.ip_add_del_route(dst_address=cls.pg5.remote_ip4n,
3377 dst_address_length=32,
3378 table_id=1,
3379 next_hop_sw_if_index=cls.pg5.sw_if_index,
3380 next_hop_address=zero_ip4n)
3381
3382 cls.pg6._local_ip4 = "10.1.2.1"
3383 cls.pg6._local_ip4n = socket.inet_pton(socket.AF_INET,
3384 cls.pg6.local_ip4)
3385 cls.pg6._remote_hosts[0]._ip4 = "10.1.2.2"
3386 cls.pg6._remote_hosts[0]._ip4n = socket.inet_pton(
3387 socket.AF_INET, cls.pg6.remote_ip4)
3388 cls.pg6.set_table_ip4(1)
3389 cls.pg6.config_ip4()
3390 cls.pg6.admin_up()
3391 cls.vapi.ip_add_del_route(dst_address=cls.pg6.remote_ip4n,
3392 dst_address_length=32,
3393 table_id=1,
3394 next_hop_sw_if_index=cls.pg6.sw_if_index,
3395 next_hop_address=zero_ip4n)
3396
3397 cls.vapi.ip_add_del_route(dst_address=cls.pg6.remote_ip4n,
3398 dst_address_length=16,
3399 next_hop_address=zero_ip4n,
3400 table_id=0,
3401 next_hop_table_id=1)
3402 cls.vapi.ip_add_del_route(dst_address=zero_ip4n,
3403 dst_address_length=0,
3404 next_hop_address=zero_ip4n,
3405 table_id=1,
3406 next_hop_table_id=0)
3407 cls.vapi.ip_add_del_route(dst_address=zero_ip4n,
3408 dst_address_length=0,
3409 table_id=0,
3410 next_hop_sw_if_index=cls.pg1.sw_if_index,
3411 next_hop_address=cls.pg1.local_ip4n)
3412
3413 cls.pg5.resolve_arp()
3414 cls.pg6.resolve_arp()
3415
Matus Fabiana6110b62018-06-13 05:39:07 -07003416 except Exception:
3417 super(TestNAT44EndpointDependent, cls).tearDownClass()
3418 raise
3419
3420 def test_dynamic(self):
3421 """ NAT44 dynamic translation test """
3422
3423 self.nat44_add_address(self.nat_addr)
3424 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3425 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3426 is_inside=0)
3427
Matus Fabian69ce30d2018-08-22 01:27:10 -07003428 nat_config = self.vapi.nat_show_config()
3429 self.assertEqual(1, nat_config.endpoint_dependent)
3430
Matus Fabiana6110b62018-06-13 05:39:07 -07003431 # in2out
3432 pkts = self.create_stream_in(self.pg0, self.pg1)
3433 self.pg0.add_stream(pkts)
3434 self.pg_enable_capture(self.pg_interfaces)
3435 self.pg_start()
3436 capture = self.pg1.get_capture(len(pkts))
3437 self.verify_capture_out(capture)
3438
3439 # out2in
3440 pkts = self.create_stream_out(self.pg1)
3441 self.pg1.add_stream(pkts)
3442 self.pg_enable_capture(self.pg_interfaces)
3443 self.pg_start()
3444 capture = self.pg0.get_capture(len(pkts))
3445 self.verify_capture_in(capture, self.pg0)
3446
3447 def test_forwarding(self):
3448 """ NAT44 forwarding test """
3449
3450 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3451 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3452 is_inside=0)
3453 self.vapi.nat44_forwarding_enable_disable(1)
3454
3455 real_ip = self.pg0.remote_ip4n
3456 alias_ip = self.nat_addr_n
3457 self.vapi.nat44_add_del_static_mapping(local_ip=real_ip,
3458 external_ip=alias_ip)
3459
3460 try:
3461 # in2out - static mapping match
3462
3463 pkts = self.create_stream_out(self.pg1)
3464 self.pg1.add_stream(pkts)
3465 self.pg_enable_capture(self.pg_interfaces)
3466 self.pg_start()
3467 capture = self.pg0.get_capture(len(pkts))
3468 self.verify_capture_in(capture, self.pg0)
3469
3470 pkts = self.create_stream_in(self.pg0, self.pg1)
3471 self.pg0.add_stream(pkts)
3472 self.pg_enable_capture(self.pg_interfaces)
3473 self.pg_start()
3474 capture = self.pg1.get_capture(len(pkts))
3475 self.verify_capture_out(capture, same_port=True)
3476
3477 # in2out - no static mapping match
3478
3479 host0 = self.pg0.remote_hosts[0]
3480 self.pg0.remote_hosts[0] = self.pg0.remote_hosts[1]
3481 try:
3482 pkts = self.create_stream_out(self.pg1,
3483 dst_ip=self.pg0.remote_ip4,
3484 use_inside_ports=True)
3485 self.pg1.add_stream(pkts)
3486 self.pg_enable_capture(self.pg_interfaces)
3487 self.pg_start()
3488 capture = self.pg0.get_capture(len(pkts))
3489 self.verify_capture_in(capture, self.pg0)
3490
3491 pkts = self.create_stream_in(self.pg0, self.pg1)
3492 self.pg0.add_stream(pkts)
3493 self.pg_enable_capture(self.pg_interfaces)
3494 self.pg_start()
3495 capture = self.pg1.get_capture(len(pkts))
3496 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
3497 same_port=True)
3498 finally:
3499 self.pg0.remote_hosts[0] = host0
3500
3501 user = self.pg0.remote_hosts[1]
3502 sessions = self.vapi.nat44_user_session_dump(user.ip4n, 0)
3503 self.assertEqual(len(sessions), 3)
3504 self.assertTrue(sessions[0].ext_host_valid)
3505 self.vapi.nat44_del_session(
3506 sessions[0].inside_ip_address,
3507 sessions[0].inside_port,
3508 sessions[0].protocol,
3509 ext_host_address=sessions[0].ext_host_address,
3510 ext_host_port=sessions[0].ext_host_port)
3511 sessions = self.vapi.nat44_user_session_dump(user.ip4n, 0)
3512 self.assertEqual(len(sessions), 2)
3513
3514 finally:
3515 self.vapi.nat44_forwarding_enable_disable(0)
3516 self.vapi.nat44_add_del_static_mapping(local_ip=real_ip,
3517 external_ip=alias_ip,
3518 is_add=0)
3519
3520 def test_static_lb(self):
3521 """ NAT44 local service load balancing """
3522 external_addr_n = socket.inet_pton(socket.AF_INET, self.nat_addr)
3523 external_port = 80
3524 local_port = 8080
3525 server1 = self.pg0.remote_hosts[0]
3526 server2 = self.pg0.remote_hosts[1]
3527
3528 locals = [{'addr': server1.ip4n,
3529 'port': local_port,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07003530 'probability': 70,
3531 'vrf_id': 0},
Matus Fabiana6110b62018-06-13 05:39:07 -07003532 {'addr': server2.ip4n,
3533 'port': local_port,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07003534 'probability': 30,
3535 'vrf_id': 0}]
Matus Fabiana6110b62018-06-13 05:39:07 -07003536
3537 self.nat44_add_address(self.nat_addr)
3538 self.vapi.nat44_add_del_lb_static_mapping(external_addr_n,
3539 external_port,
3540 IP_PROTOS.tcp,
3541 local_num=len(locals),
3542 locals=locals)
3543 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3544 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3545 is_inside=0)
3546
3547 # from client to service
3548 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3549 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3550 TCP(sport=12345, dport=external_port))
3551 self.pg1.add_stream(p)
3552 self.pg_enable_capture(self.pg_interfaces)
3553 self.pg_start()
3554 capture = self.pg0.get_capture(1)
3555 p = capture[0]
3556 server = None
3557 try:
3558 ip = p[IP]
3559 tcp = p[TCP]
3560 self.assertIn(ip.dst, [server1.ip4, server2.ip4])
3561 if ip.dst == server1.ip4:
3562 server = server1
3563 else:
3564 server = server2
3565 self.assertEqual(tcp.dport, local_port)
3566 self.assert_packet_checksums_valid(p)
3567 except:
3568 self.logger.error(ppp("Unexpected or invalid packet:", p))
3569 raise
3570
3571 # from service back to client
3572 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
3573 IP(src=server.ip4, dst=self.pg1.remote_ip4) /
3574 TCP(sport=local_port, dport=12345))
3575 self.pg0.add_stream(p)
3576 self.pg_enable_capture(self.pg_interfaces)
3577 self.pg_start()
3578 capture = self.pg1.get_capture(1)
3579 p = capture[0]
3580 try:
3581 ip = p[IP]
3582 tcp = p[TCP]
3583 self.assertEqual(ip.src, self.nat_addr)
3584 self.assertEqual(tcp.sport, external_port)
3585 self.assert_packet_checksums_valid(p)
3586 except:
3587 self.logger.error(ppp("Unexpected or invalid packet:", p))
3588 raise
3589
3590 sessions = self.vapi.nat44_user_session_dump(server.ip4n, 0)
3591 self.assertEqual(len(sessions), 1)
3592 self.assertTrue(sessions[0].ext_host_valid)
3593 self.vapi.nat44_del_session(
3594 sessions[0].inside_ip_address,
3595 sessions[0].inside_port,
3596 sessions[0].protocol,
3597 ext_host_address=sessions[0].ext_host_address,
3598 ext_host_port=sessions[0].ext_host_port)
3599 sessions = self.vapi.nat44_user_session_dump(server.ip4n, 0)
3600 self.assertEqual(len(sessions), 0)
3601
3602 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
3603 def test_static_lb_multi_clients(self):
3604 """ NAT44 local service load balancing - multiple clients"""
3605
3606 external_addr_n = socket.inet_pton(socket.AF_INET, self.nat_addr)
3607 external_port = 80
3608 local_port = 8080
3609 server1 = self.pg0.remote_hosts[0]
3610 server2 = self.pg0.remote_hosts[1]
3611
3612 locals = [{'addr': server1.ip4n,
3613 'port': local_port,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07003614 'probability': 90,
3615 'vrf_id': 0},
Matus Fabiana6110b62018-06-13 05:39:07 -07003616 {'addr': server2.ip4n,
3617 'port': local_port,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07003618 'probability': 10,
3619 'vrf_id': 0}]
Matus Fabiana6110b62018-06-13 05:39:07 -07003620
3621 self.nat44_add_address(self.nat_addr)
3622 self.vapi.nat44_add_del_lb_static_mapping(external_addr_n,
3623 external_port,
3624 IP_PROTOS.tcp,
3625 local_num=len(locals),
3626 locals=locals)
3627 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3628 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3629 is_inside=0)
3630
3631 server1_n = 0
3632 server2_n = 0
3633 clients = ip4_range(self.pg1.remote_ip4, 10, 50)
3634 pkts = []
3635 for client in clients:
3636 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3637 IP(src=client, dst=self.nat_addr) /
3638 TCP(sport=12345, dport=external_port))
3639 pkts.append(p)
3640 self.pg1.add_stream(pkts)
3641 self.pg_enable_capture(self.pg_interfaces)
3642 self.pg_start()
3643 capture = self.pg0.get_capture(len(pkts))
3644 for p in capture:
3645 if p[IP].dst == server1.ip4:
3646 server1_n += 1
3647 else:
3648 server2_n += 1
3649 self.assertTrue(server1_n > server2_n)
3650
3651 def test_static_lb_2(self):
3652 """ NAT44 local service load balancing (asymmetrical rule) """
3653 external_addr_n = socket.inet_pton(socket.AF_INET, self.nat_addr)
3654 external_port = 80
3655 local_port = 8080
3656 server1 = self.pg0.remote_hosts[0]
3657 server2 = self.pg0.remote_hosts[1]
3658
3659 locals = [{'addr': server1.ip4n,
3660 'port': local_port,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07003661 'probability': 70,
3662 'vrf_id': 0},
Matus Fabiana6110b62018-06-13 05:39:07 -07003663 {'addr': server2.ip4n,
3664 'port': local_port,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07003665 'probability': 30,
3666 'vrf_id': 0}]
Matus Fabiana6110b62018-06-13 05:39:07 -07003667
3668 self.vapi.nat44_forwarding_enable_disable(1)
3669 self.vapi.nat44_add_del_lb_static_mapping(external_addr_n,
3670 external_port,
3671 IP_PROTOS.tcp,
3672 out2in_only=1,
3673 local_num=len(locals),
3674 locals=locals)
3675 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3676 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3677 is_inside=0)
3678
3679 # from client to service
3680 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3681 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3682 TCP(sport=12345, dport=external_port))
3683 self.pg1.add_stream(p)
3684 self.pg_enable_capture(self.pg_interfaces)
3685 self.pg_start()
3686 capture = self.pg0.get_capture(1)
3687 p = capture[0]
3688 server = None
3689 try:
3690 ip = p[IP]
3691 tcp = p[TCP]
3692 self.assertIn(ip.dst, [server1.ip4, server2.ip4])
3693 if ip.dst == server1.ip4:
3694 server = server1
3695 else:
3696 server = server2
3697 self.assertEqual(tcp.dport, local_port)
3698 self.assert_packet_checksums_valid(p)
3699 except:
3700 self.logger.error(ppp("Unexpected or invalid packet:", p))
3701 raise
3702
3703 # from service back to client
3704 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
3705 IP(src=server.ip4, dst=self.pg1.remote_ip4) /
3706 TCP(sport=local_port, dport=12345))
3707 self.pg0.add_stream(p)
3708 self.pg_enable_capture(self.pg_interfaces)
3709 self.pg_start()
3710 capture = self.pg1.get_capture(1)
3711 p = capture[0]
3712 try:
3713 ip = p[IP]
3714 tcp = p[TCP]
3715 self.assertEqual(ip.src, self.nat_addr)
3716 self.assertEqual(tcp.sport, external_port)
3717 self.assert_packet_checksums_valid(p)
3718 except:
3719 self.logger.error(ppp("Unexpected or invalid packet:", p))
3720 raise
3721
3722 # from client to server (no translation)
3723 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3724 IP(src=self.pg1.remote_ip4, dst=server1.ip4) /
3725 TCP(sport=12346, dport=local_port))
3726 self.pg1.add_stream(p)
3727 self.pg_enable_capture(self.pg_interfaces)
3728 self.pg_start()
3729 capture = self.pg0.get_capture(1)
3730 p = capture[0]
3731 server = None
3732 try:
3733 ip = p[IP]
3734 tcp = p[TCP]
3735 self.assertEqual(ip.dst, server1.ip4)
3736 self.assertEqual(tcp.dport, local_port)
3737 self.assert_packet_checksums_valid(p)
3738 except:
3739 self.logger.error(ppp("Unexpected or invalid packet:", p))
3740 raise
3741
3742 # from service back to client (no translation)
3743 p = (Ether(src=server1.mac, dst=self.pg0.local_mac) /
3744 IP(src=server1.ip4, dst=self.pg1.remote_ip4) /
3745 TCP(sport=local_port, dport=12346))
3746 self.pg0.add_stream(p)
3747 self.pg_enable_capture(self.pg_interfaces)
3748 self.pg_start()
3749 capture = self.pg1.get_capture(1)
3750 p = capture[0]
3751 try:
3752 ip = p[IP]
3753 tcp = p[TCP]
3754 self.assertEqual(ip.src, server1.ip4)
3755 self.assertEqual(tcp.sport, local_port)
3756 self.assert_packet_checksums_valid(p)
3757 except:
3758 self.logger.error(ppp("Unexpected or invalid packet:", p))
3759 raise
3760
Matus Fabianea5b5be2018-09-03 05:02:23 -07003761 def test_lb_affinity(self):
3762 """ NAT44 local service load balancing affinity """
3763 external_addr_n = socket.inet_pton(socket.AF_INET, self.nat_addr)
3764 external_port = 80
3765 local_port = 8080
3766 server1 = self.pg0.remote_hosts[0]
3767 server2 = self.pg0.remote_hosts[1]
3768
3769 locals = [{'addr': server1.ip4n,
3770 'port': local_port,
3771 'probability': 50,
3772 'vrf_id': 0},
3773 {'addr': server2.ip4n,
3774 'port': local_port,
3775 'probability': 50,
3776 'vrf_id': 0}]
3777
3778 self.nat44_add_address(self.nat_addr)
3779 self.vapi.nat44_add_del_lb_static_mapping(external_addr_n,
3780 external_port,
3781 IP_PROTOS.tcp,
3782 affinity=10800,
3783 local_num=len(locals),
3784 locals=locals)
3785 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3786 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3787 is_inside=0)
3788
3789 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
3790 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3791 TCP(sport=1025, dport=external_port))
3792 self.pg1.add_stream(p)
3793 self.pg_enable_capture(self.pg_interfaces)
3794 self.pg_start()
3795 capture = self.pg0.get_capture(1)
3796 backend = capture[0][IP].dst
3797
3798 sessions = self.vapi.nat44_user_session_dump(
3799 socket.inet_pton(socket.AF_INET, backend), 0)
3800 self.assertEqual(len(sessions), 1)
3801 self.assertTrue(sessions[0].ext_host_valid)
3802 self.vapi.nat44_del_session(
3803 sessions[0].inside_ip_address,
3804 sessions[0].inside_port,
3805 sessions[0].protocol,
3806 ext_host_address=sessions[0].ext_host_address,
3807 ext_host_port=sessions[0].ext_host_port)
3808
3809 pkts = []
3810 for port in range(1030, 1100):
3811 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
3812 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3813 TCP(sport=port, dport=external_port))
3814 pkts.append(p)
3815 self.pg1.add_stream(pkts)
3816 self.pg_enable_capture(self.pg_interfaces)
3817 self.pg_start()
3818 capture = self.pg0.get_capture(len(pkts))
3819 for p in capture:
3820 self.assertEqual(p[IP].dst, backend)
3821
Matus Fabiana6110b62018-06-13 05:39:07 -07003822 def test_unknown_proto(self):
3823 """ NAT44 translate packet with unknown protocol """
3824 self.nat44_add_address(self.nat_addr)
3825 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3826 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3827 is_inside=0)
3828
3829 # in2out
3830 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3831 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3832 TCP(sport=self.tcp_port_in, dport=20))
3833 self.pg0.add_stream(p)
3834 self.pg_enable_capture(self.pg_interfaces)
3835 self.pg_start()
3836 p = self.pg1.get_capture(1)
3837
3838 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3839 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3840 GRE() /
3841 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
3842 TCP(sport=1234, dport=1234))
3843 self.pg0.add_stream(p)
3844 self.pg_enable_capture(self.pg_interfaces)
3845 self.pg_start()
3846 p = self.pg1.get_capture(1)
3847 packet = p[0]
3848 try:
3849 self.assertEqual(packet[IP].src, self.nat_addr)
3850 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
3851 self.assertTrue(packet.haslayer(GRE))
3852 self.assert_packet_checksums_valid(packet)
3853 except:
3854 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3855 raise
3856
3857 # out2in
3858 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
3859 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3860 GRE() /
3861 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
3862 TCP(sport=1234, dport=1234))
3863 self.pg1.add_stream(p)
3864 self.pg_enable_capture(self.pg_interfaces)
3865 self.pg_start()
3866 p = self.pg0.get_capture(1)
3867 packet = p[0]
3868 try:
3869 self.assertEqual(packet[IP].src, self.pg1.remote_ip4)
3870 self.assertEqual(packet[IP].dst, self.pg0.remote_ip4)
3871 self.assertTrue(packet.haslayer(GRE))
3872 self.assert_packet_checksums_valid(packet)
3873 except:
3874 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3875 raise
3876
3877 def test_hairpinning_unknown_proto(self):
3878 """ NAT44 translate packet with unknown protocol - hairpinning """
3879 host = self.pg0.remote_hosts[0]
3880 server = self.pg0.remote_hosts[1]
3881 host_in_port = 1234
3882 server_out_port = 8765
3883 server_nat_ip = "10.0.0.11"
3884
3885 self.nat44_add_address(self.nat_addr)
3886 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3887 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3888 is_inside=0)
3889
3890 # add static mapping for server
3891 self.nat44_add_static_mapping(server.ip4, server_nat_ip)
3892
3893 # host to server
3894 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
3895 IP(src=host.ip4, dst=server_nat_ip) /
3896 TCP(sport=host_in_port, dport=server_out_port))
3897 self.pg0.add_stream(p)
3898 self.pg_enable_capture(self.pg_interfaces)
3899 self.pg_start()
3900 self.pg0.get_capture(1)
3901
3902 p = (Ether(dst=self.pg0.local_mac, src=host.mac) /
3903 IP(src=host.ip4, dst=server_nat_ip) /
3904 GRE() /
3905 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
3906 TCP(sport=1234, dport=1234))
3907 self.pg0.add_stream(p)
3908 self.pg_enable_capture(self.pg_interfaces)
3909 self.pg_start()
3910 p = self.pg0.get_capture(1)
3911 packet = p[0]
3912 try:
3913 self.assertEqual(packet[IP].src, self.nat_addr)
3914 self.assertEqual(packet[IP].dst, server.ip4)
3915 self.assertTrue(packet.haslayer(GRE))
3916 self.assert_packet_checksums_valid(packet)
3917 except:
3918 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3919 raise
3920
3921 # server to host
3922 p = (Ether(dst=self.pg0.local_mac, src=server.mac) /
3923 IP(src=server.ip4, dst=self.nat_addr) /
3924 GRE() /
3925 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
3926 TCP(sport=1234, dport=1234))
3927 self.pg0.add_stream(p)
3928 self.pg_enable_capture(self.pg_interfaces)
3929 self.pg_start()
3930 p = self.pg0.get_capture(1)
3931 packet = p[0]
3932 try:
3933 self.assertEqual(packet[IP].src, server_nat_ip)
3934 self.assertEqual(packet[IP].dst, host.ip4)
3935 self.assertTrue(packet.haslayer(GRE))
3936 self.assert_packet_checksums_valid(packet)
3937 except:
3938 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3939 raise
3940
3941 def test_output_feature_and_service(self):
3942 """ NAT44 interface output feature and services """
3943 external_addr = '1.2.3.4'
3944 external_port = 80
3945 local_port = 8080
3946
3947 self.vapi.nat44_forwarding_enable_disable(1)
3948 self.nat44_add_address(self.nat_addr)
3949 self.vapi.nat44_add_del_identity_mapping(ip=self.pg1.remote_ip4n)
3950 self.nat44_add_static_mapping(self.pg0.remote_ip4, external_addr,
3951 local_port, external_port,
3952 proto=IP_PROTOS.tcp, out2in_only=1)
3953 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3954 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
3955 is_inside=0)
3956 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
3957 is_inside=0)
3958
3959 # from client to service
3960 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3961 IP(src=self.pg1.remote_ip4, dst=external_addr) /
3962 TCP(sport=12345, dport=external_port))
3963 self.pg1.add_stream(p)
3964 self.pg_enable_capture(self.pg_interfaces)
3965 self.pg_start()
3966 capture = self.pg0.get_capture(1)
3967 p = capture[0]
3968 try:
3969 ip = p[IP]
3970 tcp = p[TCP]
3971 self.assertEqual(ip.dst, self.pg0.remote_ip4)
3972 self.assertEqual(tcp.dport, local_port)
3973 self.assert_packet_checksums_valid(p)
3974 except:
3975 self.logger.error(ppp("Unexpected or invalid packet:", p))
3976 raise
3977
3978 # from service back to client
3979 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3980 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3981 TCP(sport=local_port, dport=12345))
3982 self.pg0.add_stream(p)
3983 self.pg_enable_capture(self.pg_interfaces)
3984 self.pg_start()
3985 capture = self.pg1.get_capture(1)
3986 p = capture[0]
3987 try:
3988 ip = p[IP]
3989 tcp = p[TCP]
3990 self.assertEqual(ip.src, external_addr)
3991 self.assertEqual(tcp.sport, external_port)
3992 self.assert_packet_checksums_valid(p)
3993 except:
3994 self.logger.error(ppp("Unexpected or invalid packet:", p))
3995 raise
3996
3997 # from local network host to external network
3998 pkts = self.create_stream_in(self.pg0, self.pg1)
3999 self.pg0.add_stream(pkts)
4000 self.pg_enable_capture(self.pg_interfaces)
4001 self.pg_start()
4002 capture = self.pg1.get_capture(len(pkts))
4003 self.verify_capture_out(capture)
4004 pkts = self.create_stream_in(self.pg0, self.pg1)
4005 self.pg0.add_stream(pkts)
4006 self.pg_enable_capture(self.pg_interfaces)
4007 self.pg_start()
4008 capture = self.pg1.get_capture(len(pkts))
4009 self.verify_capture_out(capture)
4010
4011 # from external network back to local network host
4012 pkts = self.create_stream_out(self.pg1)
4013 self.pg1.add_stream(pkts)
4014 self.pg_enable_capture(self.pg_interfaces)
4015 self.pg_start()
4016 capture = self.pg0.get_capture(len(pkts))
4017 self.verify_capture_in(capture, self.pg0)
4018
4019 def test_output_feature_and_service2(self):
4020 """ NAT44 interface output feature and service host direct access """
4021 self.vapi.nat44_forwarding_enable_disable(1)
4022 self.nat44_add_address(self.nat_addr)
4023 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
4024 is_inside=0)
4025
4026 # session initiaded from service host - translate
4027 pkts = self.create_stream_in(self.pg0, self.pg1)
4028 self.pg0.add_stream(pkts)
4029 self.pg_enable_capture(self.pg_interfaces)
4030 self.pg_start()
4031 capture = self.pg1.get_capture(len(pkts))
4032 self.verify_capture_out(capture)
4033
4034 pkts = self.create_stream_out(self.pg1)
4035 self.pg1.add_stream(pkts)
4036 self.pg_enable_capture(self.pg_interfaces)
4037 self.pg_start()
4038 capture = self.pg0.get_capture(len(pkts))
4039 self.verify_capture_in(capture, self.pg0)
4040
4041 # session initiaded from remote host - do not translate
4042 self.tcp_port_in = 60303
4043 self.udp_port_in = 60304
4044 self.icmp_id_in = 60305
4045 pkts = self.create_stream_out(self.pg1,
4046 self.pg0.remote_ip4,
4047 use_inside_ports=True)
4048 self.pg1.add_stream(pkts)
4049 self.pg_enable_capture(self.pg_interfaces)
4050 self.pg_start()
4051 capture = self.pg0.get_capture(len(pkts))
4052 self.verify_capture_in(capture, self.pg0)
4053
4054 pkts = self.create_stream_in(self.pg0, self.pg1)
4055 self.pg0.add_stream(pkts)
4056 self.pg_enable_capture(self.pg_interfaces)
4057 self.pg_start()
4058 capture = self.pg1.get_capture(len(pkts))
4059 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
4060 same_port=True)
4061
4062 def test_output_feature_and_service3(self):
4063 """ NAT44 interface output feature and DST NAT """
4064 external_addr = '1.2.3.4'
4065 external_port = 80
4066 local_port = 8080
4067
4068 self.vapi.nat44_forwarding_enable_disable(1)
4069 self.nat44_add_address(self.nat_addr)
4070 self.nat44_add_static_mapping(self.pg1.remote_ip4, external_addr,
4071 local_port, external_port,
4072 proto=IP_PROTOS.tcp, out2in_only=1)
4073 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4074 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
4075 is_inside=0)
4076 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
4077 is_inside=0)
4078
4079 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4080 IP(src=self.pg0.remote_ip4, dst=external_addr) /
4081 TCP(sport=12345, dport=external_port))
4082 self.pg0.add_stream(p)
4083 self.pg_enable_capture(self.pg_interfaces)
4084 self.pg_start()
4085 capture = self.pg1.get_capture(1)
4086 p = capture[0]
4087 try:
4088 ip = p[IP]
4089 tcp = p[TCP]
4090 self.assertEqual(ip.src, self.pg0.remote_ip4)
4091 self.assertEqual(tcp.sport, 12345)
4092 self.assertEqual(ip.dst, self.pg1.remote_ip4)
4093 self.assertEqual(tcp.dport, local_port)
4094 self.assert_packet_checksums_valid(p)
4095 except:
4096 self.logger.error(ppp("Unexpected or invalid packet:", p))
4097 raise
4098
4099 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4100 IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
4101 TCP(sport=local_port, dport=12345))
4102 self.pg1.add_stream(p)
4103 self.pg_enable_capture(self.pg_interfaces)
4104 self.pg_start()
4105 capture = self.pg0.get_capture(1)
4106 p = capture[0]
4107 try:
4108 ip = p[IP]
4109 tcp = p[TCP]
4110 self.assertEqual(ip.src, external_addr)
4111 self.assertEqual(tcp.sport, external_port)
4112 self.assertEqual(ip.dst, self.pg0.remote_ip4)
4113 self.assertEqual(tcp.dport, 12345)
4114 self.assert_packet_checksums_valid(p)
4115 except:
4116 self.logger.error(ppp("Unexpected or invalid packet:", p))
4117 raise
4118
Matus Fabian182e37e2018-08-14 04:21:26 -07004119 def test_next_src_nat(self):
4120 """ On way back forward packet to nat44-in2out node. """
4121 twice_nat_addr = '10.0.1.3'
4122 external_port = 80
4123 local_port = 8080
4124 post_twice_nat_port = 0
4125
4126 self.vapi.nat44_forwarding_enable_disable(1)
4127 self.nat44_add_address(twice_nat_addr, twice_nat=1)
4128 self.nat44_add_static_mapping(self.pg6.remote_ip4, self.pg1.remote_ip4,
4129 local_port, external_port,
4130 proto=IP_PROTOS.tcp, out2in_only=1,
4131 self_twice_nat=1, vrf_id=1)
4132 self.vapi.nat44_interface_add_del_feature(self.pg6.sw_if_index,
4133 is_inside=0)
4134
4135 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
4136 IP(src=self.pg6.remote_ip4, dst=self.pg1.remote_ip4) /
4137 TCP(sport=12345, dport=external_port))
4138 self.pg6.add_stream(p)
4139 self.pg_enable_capture(self.pg_interfaces)
4140 self.pg_start()
4141 capture = self.pg6.get_capture(1)
4142 p = capture[0]
4143 try:
4144 ip = p[IP]
4145 tcp = p[TCP]
4146 self.assertEqual(ip.src, twice_nat_addr)
4147 self.assertNotEqual(tcp.sport, 12345)
4148 post_twice_nat_port = tcp.sport
4149 self.assertEqual(ip.dst, self.pg6.remote_ip4)
4150 self.assertEqual(tcp.dport, local_port)
4151 self.assert_packet_checksums_valid(p)
4152 except:
4153 self.logger.error(ppp("Unexpected or invalid packet:", p))
4154 raise
4155
4156 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
4157 IP(src=self.pg6.remote_ip4, dst=twice_nat_addr) /
4158 TCP(sport=local_port, dport=post_twice_nat_port))
4159 self.pg6.add_stream(p)
4160 self.pg_enable_capture(self.pg_interfaces)
4161 self.pg_start()
4162 capture = self.pg6.get_capture(1)
4163 p = capture[0]
4164 try:
4165 ip = p[IP]
4166 tcp = p[TCP]
4167 self.assertEqual(ip.src, self.pg1.remote_ip4)
4168 self.assertEqual(tcp.sport, external_port)
4169 self.assertEqual(ip.dst, self.pg6.remote_ip4)
4170 self.assertEqual(tcp.dport, 12345)
4171 self.assert_packet_checksums_valid(p)
4172 except:
4173 self.logger.error(ppp("Unexpected or invalid packet:", p))
4174 raise
4175
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004176 def twice_nat_common(self, self_twice_nat=False, same_pg=False, lb=False,
4177 client_id=None):
Matus Fabianb932d262017-12-18 05:38:24 -08004178 twice_nat_addr = '10.0.1.3'
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004179
Matus Fabianb932d262017-12-18 05:38:24 -08004180 port_in = 8080
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004181 if lb:
4182 if not same_pg:
4183 port_in1 = port_in
4184 port_in2 = port_in
4185 else:
4186 port_in1 = port_in+1
4187 port_in2 = port_in+2
4188
Matus Fabianb932d262017-12-18 05:38:24 -08004189 port_out = 80
4190 eh_port_out = 4567
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004191
4192 server1 = self.pg0.remote_hosts[0]
4193 server2 = self.pg0.remote_hosts[1]
4194 if lb and same_pg:
4195 server2 = server1
4196 if not lb:
4197 server = server1
4198
4199 pg0 = self.pg0
4200 if same_pg:
4201 pg1 = self.pg0
4202 else:
4203 pg1 = self.pg1
4204
4205 eh_translate = ((not self_twice_nat) or (not lb and same_pg) or
4206 client_id == 1)
4207
Matus Fabianb932d262017-12-18 05:38:24 -08004208 self.nat44_add_address(self.nat_addr)
4209 self.nat44_add_address(twice_nat_addr, twice_nat=1)
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004210 if not lb:
4211 self.nat44_add_static_mapping(pg0.remote_ip4, self.nat_addr,
4212 port_in, port_out,
4213 proto=IP_PROTOS.tcp,
4214 twice_nat=int(not self_twice_nat),
4215 self_twice_nat=int(self_twice_nat))
4216 else:
4217 locals = [{'addr': server1.ip4n,
4218 'port': port_in1,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07004219 'probability': 50,
4220 'vrf_id': 0},
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004221 {'addr': server2.ip4n,
4222 'port': port_in2,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07004223 'probability': 50,
4224 'vrf_id': 0}]
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004225 out_addr_n = socket.inet_pton(socket.AF_INET, self.nat_addr)
4226 self.vapi.nat44_add_del_lb_static_mapping(out_addr_n,
4227 port_out,
4228 IP_PROTOS.tcp,
4229 twice_nat=int(
4230 not self_twice_nat),
4231 self_twice_nat=int(
4232 self_twice_nat),
4233 local_num=len(locals),
4234 locals=locals)
4235 self.vapi.nat44_interface_add_del_feature(pg0.sw_if_index)
4236 self.vapi.nat44_interface_add_del_feature(pg1.sw_if_index,
Matus Fabianb932d262017-12-18 05:38:24 -08004237 is_inside=0)
4238
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004239 if same_pg:
4240 if not lb:
4241 client = server
4242 else:
4243 assert client_id is not None
4244 if client_id == 1:
4245 client = self.pg0.remote_hosts[0]
4246 elif client_id == 2:
4247 client = self.pg0.remote_hosts[1]
4248 else:
4249 client = pg1.remote_hosts[0]
4250 p = (Ether(src=pg1.remote_mac, dst=pg1.local_mac) /
4251 IP(src=client.ip4, dst=self.nat_addr) /
Matus Fabianb932d262017-12-18 05:38:24 -08004252 TCP(sport=eh_port_out, dport=port_out))
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004253 pg1.add_stream(p)
Matus Fabianb932d262017-12-18 05:38:24 -08004254 self.pg_enable_capture(self.pg_interfaces)
4255 self.pg_start()
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004256 capture = pg0.get_capture(1)
Matus Fabianb932d262017-12-18 05:38:24 -08004257 p = capture[0]
4258 try:
4259 ip = p[IP]
4260 tcp = p[TCP]
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004261 if lb:
4262 if ip.dst == server1.ip4:
4263 server = server1
4264 port_in = port_in1
4265 else:
4266 server = server2
4267 port_in = port_in2
4268 self.assertEqual(ip.dst, server.ip4)
4269 if lb and same_pg:
4270 self.assertIn(tcp.dport, [port_in1, port_in2])
4271 else:
4272 self.assertEqual(tcp.dport, port_in)
4273 if eh_translate:
4274 self.assertEqual(ip.src, twice_nat_addr)
4275 self.assertNotEqual(tcp.sport, eh_port_out)
4276 else:
4277 self.assertEqual(ip.src, client.ip4)
4278 self.assertEqual(tcp.sport, eh_port_out)
4279 eh_addr_in = ip.src
Matus Fabianb932d262017-12-18 05:38:24 -08004280 eh_port_in = tcp.sport
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004281 saved_port_in = tcp.dport
Klement Sekerad81ae412018-05-16 10:52:54 +02004282 self.assert_packet_checksums_valid(p)
Matus Fabianb932d262017-12-18 05:38:24 -08004283 except:
4284 self.logger.error(ppp("Unexpected or invalid packet:", p))
4285 raise
4286
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004287 p = (Ether(src=server.mac, dst=pg0.local_mac) /
4288 IP(src=server.ip4, dst=eh_addr_in) /
4289 TCP(sport=saved_port_in, dport=eh_port_in))
4290 pg0.add_stream(p)
Matus Fabianb932d262017-12-18 05:38:24 -08004291 self.pg_enable_capture(self.pg_interfaces)
4292 self.pg_start()
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004293 capture = pg1.get_capture(1)
Matus Fabianb932d262017-12-18 05:38:24 -08004294 p = capture[0]
4295 try:
4296 ip = p[IP]
4297 tcp = p[TCP]
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004298 self.assertEqual(ip.dst, client.ip4)
Matus Fabianb932d262017-12-18 05:38:24 -08004299 self.assertEqual(ip.src, self.nat_addr)
4300 self.assertEqual(tcp.dport, eh_port_out)
4301 self.assertEqual(tcp.sport, port_out)
Klement Sekerad81ae412018-05-16 10:52:54 +02004302 self.assert_packet_checksums_valid(p)
Matus Fabianb932d262017-12-18 05:38:24 -08004303 except:
4304 self.logger.error(ppp("Unexpected or invalid packet:", p))
4305 raise
4306
Matus Fabian70a26ac2018-05-14 06:20:28 -07004307 if eh_translate:
4308 sessions = self.vapi.nat44_user_session_dump(server.ip4n, 0)
4309 self.assertEqual(len(sessions), 1)
4310 self.assertTrue(sessions[0].ext_host_valid)
4311 self.assertTrue(sessions[0].is_twicenat)
4312 self.vapi.nat44_del_session(
4313 sessions[0].inside_ip_address,
4314 sessions[0].inside_port,
4315 sessions[0].protocol,
4316 ext_host_address=sessions[0].ext_host_nat_address,
4317 ext_host_port=sessions[0].ext_host_nat_port)
4318 sessions = self.vapi.nat44_user_session_dump(server.ip4n, 0)
4319 self.assertEqual(len(sessions), 0)
4320
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004321 def test_twice_nat(self):
4322 """ Twice NAT44 """
4323 self.twice_nat_common()
4324
4325 def test_self_twice_nat_positive(self):
4326 """ Self Twice NAT44 (positive test) """
4327 self.twice_nat_common(self_twice_nat=True, same_pg=True)
4328
4329 def test_self_twice_nat_negative(self):
4330 """ Self Twice NAT44 (negative test) """
4331 self.twice_nat_common(self_twice_nat=True)
4332
Matus Fabianb932d262017-12-18 05:38:24 -08004333 def test_twice_nat_lb(self):
4334 """ Twice NAT44 local service load balancing """
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004335 self.twice_nat_common(lb=True)
Matus Fabianb932d262017-12-18 05:38:24 -08004336
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004337 def test_self_twice_nat_lb_positive(self):
4338 """ Self Twice NAT44 local service load balancing (positive test) """
4339 self.twice_nat_common(lb=True, self_twice_nat=True, same_pg=True,
4340 client_id=1)
Matus Fabianb932d262017-12-18 05:38:24 -08004341
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004342 def test_self_twice_nat_lb_negative(self):
4343 """ Self Twice NAT44 local service load balancing (negative test) """
4344 self.twice_nat_common(lb=True, self_twice_nat=True, same_pg=True,
4345 client_id=2)
Matus Fabianb932d262017-12-18 05:38:24 -08004346
4347 def test_twice_nat_interface_addr(self):
4348 """ Acquire twice NAT44 addresses from interface """
Matus Fabiana6110b62018-06-13 05:39:07 -07004349 self.vapi.nat44_add_interface_addr(self.pg3.sw_if_index, twice_nat=1)
Matus Fabianb932d262017-12-18 05:38:24 -08004350
4351 # no address in NAT pool
4352 adresses = self.vapi.nat44_address_dump()
4353 self.assertEqual(0, len(adresses))
4354
4355 # configure interface address and check NAT address pool
Matus Fabiana6110b62018-06-13 05:39:07 -07004356 self.pg3.config_ip4()
Matus Fabianb932d262017-12-18 05:38:24 -08004357 adresses = self.vapi.nat44_address_dump()
4358 self.assertEqual(1, len(adresses))
Matus Fabiana6110b62018-06-13 05:39:07 -07004359 self.assertEqual(adresses[0].ip_address[0:4], self.pg3.local_ip4n)
Matus Fabianb932d262017-12-18 05:38:24 -08004360 self.assertEqual(adresses[0].twice_nat, 1)
4361
4362 # remove interface address and check NAT address pool
Matus Fabiana6110b62018-06-13 05:39:07 -07004363 self.pg3.unconfig_ip4()
Matus Fabianb932d262017-12-18 05:38:24 -08004364 adresses = self.vapi.nat44_address_dump()
4365 self.assertEqual(0, len(adresses))
4366
Matus Fabianebdf1902018-05-04 03:57:42 -07004367 def test_tcp_session_close_in(self):
4368 """ Close TCP session from inside network """
Matus Fabian229c1aa2018-05-28 04:09:52 -07004369 self.tcp_port_out = 10505
Matus Fabianebdf1902018-05-04 03:57:42 -07004370 self.nat44_add_address(self.nat_addr)
Matus Fabian229c1aa2018-05-28 04:09:52 -07004371 self.nat44_add_static_mapping(self.pg0.remote_ip4,
4372 self.nat_addr,
4373 self.tcp_port_in,
4374 self.tcp_port_out,
4375 proto=IP_PROTOS.tcp,
4376 twice_nat=1)
Matus Fabianebdf1902018-05-04 03:57:42 -07004377 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4378 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4379 is_inside=0)
4380
4381 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
4382 start_sessnum = len(sessions)
4383
4384 self.initiate_tcp_session(self.pg0, self.pg1)
4385
Matus Fabian229c1aa2018-05-28 04:09:52 -07004386 # FIN packet in -> out
4387 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4388 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4389 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
4390 flags="FA", seq=100, ack=300))
4391 self.pg0.add_stream(p)
4392 self.pg_enable_capture(self.pg_interfaces)
4393 self.pg_start()
4394 self.pg1.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07004395
Matus Fabian229c1aa2018-05-28 04:09:52 -07004396 pkts = []
Matus Fabianebdf1902018-05-04 03:57:42 -07004397
Matus Fabian229c1aa2018-05-28 04:09:52 -07004398 # ACK packet out -> in
4399 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4400 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4401 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
4402 flags="A", seq=300, ack=101))
4403 pkts.append(p)
Matus Fabianebdf1902018-05-04 03:57:42 -07004404
Matus Fabian229c1aa2018-05-28 04:09:52 -07004405 # FIN packet out -> in
4406 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4407 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4408 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
4409 flags="FA", seq=300, ack=101))
4410 pkts.append(p)
Matus Fabianebdf1902018-05-04 03:57:42 -07004411
Matus Fabian229c1aa2018-05-28 04:09:52 -07004412 self.pg1.add_stream(pkts)
4413 self.pg_enable_capture(self.pg_interfaces)
4414 self.pg_start()
4415 self.pg0.get_capture(2)
Matus Fabianebdf1902018-05-04 03:57:42 -07004416
Matus Fabian229c1aa2018-05-28 04:09:52 -07004417 # ACK packet in -> out
4418 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4419 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4420 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
4421 flags="A", seq=101, ack=301))
4422 self.pg0.add_stream(p)
4423 self.pg_enable_capture(self.pg_interfaces)
4424 self.pg_start()
4425 self.pg1.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07004426
Matus Fabian229c1aa2018-05-28 04:09:52 -07004427 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n,
4428 0)
4429 self.assertEqual(len(sessions) - start_sessnum, 0)
Matus Fabianebdf1902018-05-04 03:57:42 -07004430
4431 def test_tcp_session_close_out(self):
4432 """ Close TCP session from outside network """
Matus Fabian229c1aa2018-05-28 04:09:52 -07004433 self.tcp_port_out = 10505
Matus Fabianebdf1902018-05-04 03:57:42 -07004434 self.nat44_add_address(self.nat_addr)
Matus Fabian229c1aa2018-05-28 04:09:52 -07004435 self.nat44_add_static_mapping(self.pg0.remote_ip4,
4436 self.nat_addr,
4437 self.tcp_port_in,
4438 self.tcp_port_out,
4439 proto=IP_PROTOS.tcp,
4440 twice_nat=1)
Matus Fabianebdf1902018-05-04 03:57:42 -07004441 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4442 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4443 is_inside=0)
4444
4445 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
4446 start_sessnum = len(sessions)
4447
4448 self.initiate_tcp_session(self.pg0, self.pg1)
4449
Matus Fabian229c1aa2018-05-28 04:09:52 -07004450 # FIN packet out -> in
4451 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4452 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4453 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
4454 flags="FA", seq=100, ack=300))
4455 self.pg1.add_stream(p)
4456 self.pg_enable_capture(self.pg_interfaces)
4457 self.pg_start()
4458 self.pg0.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07004459
Matus Fabian229c1aa2018-05-28 04:09:52 -07004460 # FIN+ACK packet in -> out
4461 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4462 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4463 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
4464 flags="FA", seq=300, ack=101))
Matus Fabianebdf1902018-05-04 03:57:42 -07004465
Matus Fabian229c1aa2018-05-28 04:09:52 -07004466 self.pg0.add_stream(p)
4467 self.pg_enable_capture(self.pg_interfaces)
4468 self.pg_start()
4469 self.pg1.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07004470
Matus Fabian229c1aa2018-05-28 04:09:52 -07004471 # ACK packet out -> in
4472 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4473 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4474 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
4475 flags="A", seq=101, ack=301))
4476 self.pg1.add_stream(p)
4477 self.pg_enable_capture(self.pg_interfaces)
4478 self.pg_start()
4479 self.pg0.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07004480
Matus Fabian229c1aa2018-05-28 04:09:52 -07004481 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n,
4482 0)
4483 self.assertEqual(len(sessions) - start_sessnum, 0)
Matus Fabianebdf1902018-05-04 03:57:42 -07004484
4485 def test_tcp_session_close_simultaneous(self):
4486 """ Close TCP session from inside network """
Matus Fabian229c1aa2018-05-28 04:09:52 -07004487 self.tcp_port_out = 10505
Matus Fabianebdf1902018-05-04 03:57:42 -07004488 self.nat44_add_address(self.nat_addr)
Matus Fabian229c1aa2018-05-28 04:09:52 -07004489 self.nat44_add_static_mapping(self.pg0.remote_ip4,
4490 self.nat_addr,
4491 self.tcp_port_in,
4492 self.tcp_port_out,
4493 proto=IP_PROTOS.tcp,
4494 twice_nat=1)
Matus Fabianebdf1902018-05-04 03:57:42 -07004495 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4496 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4497 is_inside=0)
4498
4499 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
4500 start_sessnum = len(sessions)
4501
4502 self.initiate_tcp_session(self.pg0, self.pg1)
4503
Matus Fabian229c1aa2018-05-28 04:09:52 -07004504 # FIN packet in -> out
4505 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4506 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4507 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
4508 flags="FA", seq=100, ack=300))
4509 self.pg0.add_stream(p)
4510 self.pg_enable_capture(self.pg_interfaces)
4511 self.pg_start()
4512 self.pg1.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07004513
Matus Fabian229c1aa2018-05-28 04:09:52 -07004514 # FIN packet out -> in
4515 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4516 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4517 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
4518 flags="FA", seq=300, ack=100))
4519 self.pg1.add_stream(p)
4520 self.pg_enable_capture(self.pg_interfaces)
4521 self.pg_start()
4522 self.pg0.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07004523
Matus Fabian229c1aa2018-05-28 04:09:52 -07004524 # ACK packet in -> out
4525 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4526 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4527 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
4528 flags="A", seq=101, ack=301))
4529 self.pg0.add_stream(p)
4530 self.pg_enable_capture(self.pg_interfaces)
4531 self.pg_start()
4532 self.pg1.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07004533
Matus Fabian229c1aa2018-05-28 04:09:52 -07004534 # ACK packet out -> in
4535 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4536 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4537 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
4538 flags="A", seq=301, ack=101))
4539 self.pg1.add_stream(p)
4540 self.pg_enable_capture(self.pg_interfaces)
4541 self.pg_start()
4542 self.pg0.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07004543
Matus Fabian229c1aa2018-05-28 04:09:52 -07004544 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n,
4545 0)
4546 self.assertEqual(len(sessions) - start_sessnum, 0)
Matus Fabianebdf1902018-05-04 03:57:42 -07004547
Matus Fabiana6110b62018-06-13 05:39:07 -07004548 def test_one_armed_nat44_static(self):
4549 """ One armed NAT44 and 1:1 NAPT asymmetrical rule """
4550 remote_host = self.pg4.remote_hosts[0]
4551 local_host = self.pg4.remote_hosts[1]
4552 external_port = 80
4553 local_port = 8080
4554 eh_port_in = 0
4555
4556 self.vapi.nat44_forwarding_enable_disable(1)
4557 self.nat44_add_address(self.nat_addr, twice_nat=1)
4558 self.nat44_add_static_mapping(local_host.ip4, self.nat_addr,
4559 local_port, external_port,
4560 proto=IP_PROTOS.tcp, out2in_only=1,
4561 twice_nat=1)
4562 self.vapi.nat44_interface_add_del_feature(self.pg4.sw_if_index)
4563 self.vapi.nat44_interface_add_del_feature(self.pg4.sw_if_index,
4564 is_inside=0)
4565
4566 # from client to service
4567 p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
4568 IP(src=remote_host.ip4, dst=self.nat_addr) /
4569 TCP(sport=12345, dport=external_port))
4570 self.pg4.add_stream(p)
4571 self.pg_enable_capture(self.pg_interfaces)
4572 self.pg_start()
4573 capture = self.pg4.get_capture(1)
4574 p = capture[0]
4575 try:
4576 ip = p[IP]
4577 tcp = p[TCP]
4578 self.assertEqual(ip.dst, local_host.ip4)
4579 self.assertEqual(ip.src, self.nat_addr)
4580 self.assertEqual(tcp.dport, local_port)
4581 self.assertNotEqual(tcp.sport, 12345)
4582 eh_port_in = tcp.sport
4583 self.assert_packet_checksums_valid(p)
4584 except:
4585 self.logger.error(ppp("Unexpected or invalid packet:", p))
4586 raise
4587
4588 # from service back to client
4589 p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
4590 IP(src=local_host.ip4, dst=self.nat_addr) /
4591 TCP(sport=local_port, dport=eh_port_in))
4592 self.pg4.add_stream(p)
4593 self.pg_enable_capture(self.pg_interfaces)
4594 self.pg_start()
4595 capture = self.pg4.get_capture(1)
4596 p = capture[0]
4597 try:
4598 ip = p[IP]
4599 tcp = p[TCP]
4600 self.assertEqual(ip.src, self.nat_addr)
4601 self.assertEqual(ip.dst, remote_host.ip4)
4602 self.assertEqual(tcp.sport, external_port)
4603 self.assertEqual(tcp.dport, 12345)
4604 self.assert_packet_checksums_valid(p)
4605 except:
4606 self.logger.error(ppp("Unexpected or invalid packet:", p))
4607 raise
4608
4609 def test_static_with_port_out2(self):
4610 """ 1:1 NAPT asymmetrical rule """
4611
4612 external_port = 80
4613 local_port = 8080
4614
4615 self.vapi.nat44_forwarding_enable_disable(1)
4616 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
4617 local_port, external_port,
4618 proto=IP_PROTOS.tcp, out2in_only=1)
4619 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4620 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4621 is_inside=0)
4622
4623 # from client to service
4624 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4625 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4626 TCP(sport=12345, dport=external_port))
4627 self.pg1.add_stream(p)
4628 self.pg_enable_capture(self.pg_interfaces)
4629 self.pg_start()
4630 capture = self.pg0.get_capture(1)
4631 p = capture[0]
4632 try:
4633 ip = p[IP]
4634 tcp = p[TCP]
4635 self.assertEqual(ip.dst, self.pg0.remote_ip4)
4636 self.assertEqual(tcp.dport, local_port)
4637 self.assert_packet_checksums_valid(p)
4638 except:
4639 self.logger.error(ppp("Unexpected or invalid packet:", p))
4640 raise
4641
4642 # ICMP error
4643 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
4644 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4645 ICMP(type=11) / capture[0][IP])
4646 self.pg0.add_stream(p)
4647 self.pg_enable_capture(self.pg_interfaces)
4648 self.pg_start()
4649 capture = self.pg1.get_capture(1)
4650 p = capture[0]
4651 try:
4652 self.assertEqual(p[IP].src, self.nat_addr)
4653 inner = p[IPerror]
4654 self.assertEqual(inner.dst, self.nat_addr)
4655 self.assertEqual(inner[TCPerror].dport, external_port)
4656 except:
4657 self.logger.error(ppp("Unexpected or invalid packet:", p))
4658 raise
4659
4660 # from service back to client
4661 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4662 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4663 TCP(sport=local_port, dport=12345))
4664 self.pg0.add_stream(p)
4665 self.pg_enable_capture(self.pg_interfaces)
4666 self.pg_start()
4667 capture = self.pg1.get_capture(1)
4668 p = capture[0]
4669 try:
4670 ip = p[IP]
4671 tcp = p[TCP]
4672 self.assertEqual(ip.src, self.nat_addr)
4673 self.assertEqual(tcp.sport, external_port)
4674 self.assert_packet_checksums_valid(p)
4675 except:
4676 self.logger.error(ppp("Unexpected or invalid packet:", p))
4677 raise
4678
4679 # ICMP error
4680 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
4681 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4682 ICMP(type=11) / capture[0][IP])
4683 self.pg1.add_stream(p)
4684 self.pg_enable_capture(self.pg_interfaces)
4685 self.pg_start()
4686 capture = self.pg0.get_capture(1)
4687 p = capture[0]
4688 try:
4689 self.assertEqual(p[IP].dst, self.pg0.remote_ip4)
4690 inner = p[IPerror]
4691 self.assertEqual(inner.src, self.pg0.remote_ip4)
4692 self.assertEqual(inner[TCPerror].sport, local_port)
4693 except:
4694 self.logger.error(ppp("Unexpected or invalid packet:", p))
4695 raise
4696
4697 # from client to server (no translation)
4698 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4699 IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
4700 TCP(sport=12346, dport=local_port))
4701 self.pg1.add_stream(p)
4702 self.pg_enable_capture(self.pg_interfaces)
4703 self.pg_start()
4704 capture = self.pg0.get_capture(1)
4705 p = capture[0]
4706 try:
4707 ip = p[IP]
4708 tcp = p[TCP]
4709 self.assertEqual(ip.dst, self.pg0.remote_ip4)
4710 self.assertEqual(tcp.dport, local_port)
4711 self.assert_packet_checksums_valid(p)
4712 except:
4713 self.logger.error(ppp("Unexpected or invalid packet:", p))
4714 raise
4715
4716 # from service back to client (no translation)
4717 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4718 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4719 TCP(sport=local_port, dport=12346))
4720 self.pg0.add_stream(p)
4721 self.pg_enable_capture(self.pg_interfaces)
4722 self.pg_start()
4723 capture = self.pg1.get_capture(1)
4724 p = capture[0]
4725 try:
4726 ip = p[IP]
4727 tcp = p[TCP]
4728 self.assertEqual(ip.src, self.pg0.remote_ip4)
4729 self.assertEqual(tcp.sport, local_port)
4730 self.assert_packet_checksums_valid(p)
4731 except:
4732 self.logger.error(ppp("Unexpected or invalid packet:", p))
4733 raise
4734
Matus Fabian235a47e2018-06-25 16:42:36 -07004735 def test_output_feature(self):
4736 """ NAT44 interface output feature (in2out postrouting) """
4737 self.vapi.nat44_forwarding_enable_disable(1)
4738 self.nat44_add_address(self.nat_addr)
4739 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
4740 is_inside=0)
4741 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
4742 is_inside=0)
4743
4744 # in2out
4745 pkts = self.create_stream_in(self.pg0, self.pg1)
4746 self.pg0.add_stream(pkts)
4747 self.pg_enable_capture(self.pg_interfaces)
4748 self.pg_start()
4749 capture = self.pg1.get_capture(len(pkts))
4750 self.verify_capture_out(capture)
4751
4752 # out2in
4753 pkts = self.create_stream_out(self.pg1)
4754 self.pg1.add_stream(pkts)
4755 self.pg_enable_capture(self.pg_interfaces)
4756 self.pg_start()
4757 capture = self.pg0.get_capture(len(pkts))
4758 self.verify_capture_in(capture, self.pg0)
4759
Matus Fabian8008d7c2018-07-09 01:34:20 -07004760 def test_multiple_vrf(self):
4761 """ Multiple VRF setup """
4762 external_addr = '1.2.3.4'
4763 external_port = 80
4764 local_port = 8080
4765 port = 0
4766
4767 self.vapi.nat44_forwarding_enable_disable(1)
4768 self.nat44_add_address(self.nat_addr)
4769 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4770 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
4771 is_inside=0)
4772 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
4773 is_inside=0)
4774 self.vapi.nat44_interface_add_del_feature(self.pg5.sw_if_index)
4775 self.vapi.nat44_interface_add_del_feature(self.pg5.sw_if_index,
4776 is_inside=0)
4777 self.vapi.nat44_interface_add_del_feature(self.pg6.sw_if_index,
4778 is_inside=0)
4779 self.nat44_add_static_mapping(self.pg5.remote_ip4, external_addr,
4780 local_port, external_port, vrf_id=1,
4781 proto=IP_PROTOS.tcp, out2in_only=1)
4782 self.nat44_add_static_mapping(
4783 self.pg0.remote_ip4, external_sw_if_index=self.pg0.sw_if_index,
4784 local_port=local_port, vrf_id=0, external_port=external_port,
4785 proto=IP_PROTOS.tcp, out2in_only=1)
4786
4787 # from client to service (both VRF1)
4788 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
4789 IP(src=self.pg6.remote_ip4, dst=external_addr) /
4790 TCP(sport=12345, dport=external_port))
4791 self.pg6.add_stream(p)
4792 self.pg_enable_capture(self.pg_interfaces)
4793 self.pg_start()
4794 capture = self.pg5.get_capture(1)
4795 p = capture[0]
4796 try:
4797 ip = p[IP]
4798 tcp = p[TCP]
4799 self.assertEqual(ip.dst, self.pg5.remote_ip4)
4800 self.assertEqual(tcp.dport, local_port)
4801 self.assert_packet_checksums_valid(p)
4802 except:
4803 self.logger.error(ppp("Unexpected or invalid packet:", p))
4804 raise
4805
4806 # from service back to client (both VRF1)
4807 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
4808 IP(src=self.pg5.remote_ip4, dst=self.pg6.remote_ip4) /
4809 TCP(sport=local_port, dport=12345))
4810 self.pg5.add_stream(p)
4811 self.pg_enable_capture(self.pg_interfaces)
4812 self.pg_start()
4813 capture = self.pg6.get_capture(1)
4814 p = capture[0]
4815 try:
4816 ip = p[IP]
4817 tcp = p[TCP]
4818 self.assertEqual(ip.src, external_addr)
4819 self.assertEqual(tcp.sport, external_port)
4820 self.assert_packet_checksums_valid(p)
4821 except:
4822 self.logger.error(ppp("Unexpected or invalid packet:", p))
4823 raise
4824
4825 # dynamic NAT from VRF1 to VRF0 (output-feature)
4826 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
4827 IP(src=self.pg5.remote_ip4, dst=self.pg1.remote_ip4) /
4828 TCP(sport=2345, dport=22))
4829 self.pg5.add_stream(p)
4830 self.pg_enable_capture(self.pg_interfaces)
4831 self.pg_start()
4832 capture = self.pg1.get_capture(1)
4833 p = capture[0]
4834 try:
4835 ip = p[IP]
4836 tcp = p[TCP]
4837 self.assertEqual(ip.src, self.nat_addr)
4838 self.assertNotEqual(tcp.sport, 2345)
4839 self.assert_packet_checksums_valid(p)
4840 port = tcp.sport
4841 except:
4842 self.logger.error(ppp("Unexpected or invalid packet:", p))
4843 raise
4844
4845 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4846 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4847 TCP(sport=22, dport=port))
4848 self.pg1.add_stream(p)
4849 self.pg_enable_capture(self.pg_interfaces)
4850 self.pg_start()
4851 capture = self.pg5.get_capture(1)
4852 p = capture[0]
4853 try:
4854 ip = p[IP]
4855 tcp = p[TCP]
4856 self.assertEqual(ip.dst, self.pg5.remote_ip4)
4857 self.assertEqual(tcp.dport, 2345)
4858 self.assert_packet_checksums_valid(p)
4859 except:
4860 self.logger.error(ppp("Unexpected or invalid packet:", p))
4861 raise
4862
4863 # from client VRF1 to service VRF0
4864 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
4865 IP(src=self.pg6.remote_ip4, dst=self.pg0.local_ip4) /
4866 TCP(sport=12346, dport=external_port))
4867 self.pg6.add_stream(p)
4868 self.pg_enable_capture(self.pg_interfaces)
4869 self.pg_start()
4870 capture = self.pg0.get_capture(1)
4871 p = capture[0]
4872 try:
4873 ip = p[IP]
4874 tcp = p[TCP]
4875 self.assertEqual(ip.dst, self.pg0.remote_ip4)
4876 self.assertEqual(tcp.dport, local_port)
4877 self.assert_packet_checksums_valid(p)
4878 except:
4879 self.logger.error(ppp("Unexpected or invalid packet:", p))
4880 raise
4881
4882 # from service VRF0 back to client VRF1
4883 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4884 IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
4885 TCP(sport=local_port, dport=12346))
4886 self.pg0.add_stream(p)
4887 self.pg_enable_capture(self.pg_interfaces)
4888 self.pg_start()
4889 capture = self.pg6.get_capture(1)
4890 p = capture[0]
4891 try:
4892 ip = p[IP]
4893 tcp = p[TCP]
4894 self.assertEqual(ip.src, self.pg0.local_ip4)
4895 self.assertEqual(tcp.sport, external_port)
4896 self.assert_packet_checksums_valid(p)
4897 except:
4898 self.logger.error(ppp("Unexpected or invalid packet:", p))
4899 raise
4900
4901 # from client VRF0 to service VRF1
4902 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4903 IP(src=self.pg0.remote_ip4, dst=external_addr) /
4904 TCP(sport=12347, dport=external_port))
4905 self.pg0.add_stream(p)
4906 self.pg_enable_capture(self.pg_interfaces)
4907 self.pg_start()
4908 capture = self.pg5.get_capture(1)
4909 p = capture[0]
4910 try:
4911 ip = p[IP]
4912 tcp = p[TCP]
4913 self.assertEqual(ip.dst, self.pg5.remote_ip4)
4914 self.assertEqual(tcp.dport, local_port)
4915 self.assert_packet_checksums_valid(p)
4916 except:
4917 self.logger.error(ppp("Unexpected or invalid packet:", p))
4918 raise
4919
4920 # from service VRF1 back to client VRF0
4921 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
4922 IP(src=self.pg5.remote_ip4, dst=self.pg0.remote_ip4) /
4923 TCP(sport=local_port, dport=12347))
4924 self.pg5.add_stream(p)
4925 self.pg_enable_capture(self.pg_interfaces)
4926 self.pg_start()
4927 capture = self.pg0.get_capture(1)
4928 p = capture[0]
4929 try:
4930 ip = p[IP]
4931 tcp = p[TCP]
4932 self.assertEqual(ip.src, external_addr)
4933 self.assertEqual(tcp.sport, external_port)
4934 self.assert_packet_checksums_valid(p)
4935 except:
4936 self.logger.error(ppp("Unexpected or invalid packet:", p))
4937 raise
4938
4939 # from client to server (both VRF1, no translation)
4940 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
4941 IP(src=self.pg6.remote_ip4, dst=self.pg5.remote_ip4) /
4942 TCP(sport=12348, dport=local_port))
4943 self.pg6.add_stream(p)
4944 self.pg_enable_capture(self.pg_interfaces)
4945 self.pg_start()
4946 capture = self.pg5.get_capture(1)
4947 p = capture[0]
4948 try:
4949 ip = p[IP]
4950 tcp = p[TCP]
4951 self.assertEqual(ip.dst, self.pg5.remote_ip4)
4952 self.assertEqual(tcp.dport, local_port)
4953 self.assert_packet_checksums_valid(p)
4954 except:
4955 self.logger.error(ppp("Unexpected or invalid packet:", p))
4956 raise
4957
4958 # from server back to client (both VRF1, no translation)
4959 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
4960 IP(src=self.pg5.remote_ip4, dst=self.pg6.remote_ip4) /
4961 TCP(sport=local_port, dport=12348))
4962 self.pg5.add_stream(p)
4963 self.pg_enable_capture(self.pg_interfaces)
4964 self.pg_start()
4965 capture = self.pg6.get_capture(1)
4966 p = capture[0]
4967 try:
4968 ip = p[IP]
4969 tcp = p[TCP]
4970 self.assertEqual(ip.src, self.pg5.remote_ip4)
4971 self.assertEqual(tcp.sport, local_port)
4972 self.assert_packet_checksums_valid(p)
4973 except:
4974 self.logger.error(ppp("Unexpected or invalid packet:", p))
4975 raise
4976
4977 # from client VRF1 to server VRF0 (no translation)
4978 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4979 IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
4980 TCP(sport=local_port, dport=12349))
4981 self.pg0.add_stream(p)
4982 self.pg_enable_capture(self.pg_interfaces)
4983 self.pg_start()
4984 capture = self.pg6.get_capture(1)
4985 p = capture[0]
4986 try:
4987 ip = p[IP]
4988 tcp = p[TCP]
4989 self.assertEqual(ip.src, self.pg0.remote_ip4)
4990 self.assertEqual(tcp.sport, local_port)
4991 self.assert_packet_checksums_valid(p)
4992 except:
4993 self.logger.error(ppp("Unexpected or invalid packet:", p))
4994 raise
4995
4996 # from server VRF0 back to client VRF1 (no translation)
4997 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4998 IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
4999 TCP(sport=local_port, dport=12349))
5000 self.pg0.add_stream(p)
5001 self.pg_enable_capture(self.pg_interfaces)
5002 self.pg_start()
5003 capture = self.pg6.get_capture(1)
5004 p = capture[0]
5005 try:
5006 ip = p[IP]
5007 tcp = p[TCP]
5008 self.assertEqual(ip.src, self.pg0.remote_ip4)
5009 self.assertEqual(tcp.sport, local_port)
5010 self.assert_packet_checksums_valid(p)
5011 except:
5012 self.logger.error(ppp("Unexpected or invalid packet:", p))
5013 raise
5014
5015 # from client VRF0 to server VRF1 (no translation)
5016 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5017 IP(src=self.pg0.remote_ip4, dst=self.pg5.remote_ip4) /
5018 TCP(sport=12344, dport=local_port))
5019 self.pg0.add_stream(p)
5020 self.pg_enable_capture(self.pg_interfaces)
5021 self.pg_start()
5022 capture = self.pg5.get_capture(1)
5023 p = capture[0]
5024 try:
5025 ip = p[IP]
5026 tcp = p[TCP]
5027 self.assertEqual(ip.dst, self.pg5.remote_ip4)
5028 self.assertEqual(tcp.dport, local_port)
5029 self.assert_packet_checksums_valid(p)
5030 except:
5031 self.logger.error(ppp("Unexpected or invalid packet:", p))
5032 raise
5033
5034 # from server VRF1 back to client VRF0 (no translation)
5035 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
5036 IP(src=self.pg5.remote_ip4, dst=self.pg0.remote_ip4) /
5037 TCP(sport=local_port, dport=12344))
5038 self.pg5.add_stream(p)
5039 self.pg_enable_capture(self.pg_interfaces)
5040 self.pg_start()
5041 capture = self.pg0.get_capture(1)
5042 p = capture[0]
5043 try:
5044 ip = p[IP]
5045 tcp = p[TCP]
5046 self.assertEqual(ip.src, self.pg5.remote_ip4)
5047 self.assertEqual(tcp.sport, local_port)
5048 self.assert_packet_checksums_valid(p)
5049 except:
5050 self.logger.error(ppp("Unexpected or invalid packet:", p))
5051 raise
5052
Matus Fabian878c6462018-08-23 00:33:35 -07005053 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
5054 def test_session_timeout(self):
5055 """ NAT44 session timeouts """
5056 self.nat44_add_address(self.nat_addr)
5057 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5058 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
5059 is_inside=0)
5060 self.vapi.nat_set_timeouts(icmp=5)
5061
5062 max_sessions = 1000
5063 pkts = []
5064 for i in range(0, max_sessions):
5065 src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
5066 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5067 IP(src=src, dst=self.pg1.remote_ip4) /
5068 ICMP(id=1025, type='echo-request'))
5069 pkts.append(p)
5070 self.pg0.add_stream(pkts)
5071 self.pg_enable_capture(self.pg_interfaces)
5072 self.pg_start()
5073 self.pg1.get_capture(max_sessions)
5074
5075 sleep(10)
5076
5077 pkts = []
5078 for i in range(0, max_sessions):
5079 src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
5080 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5081 IP(src=src, dst=self.pg1.remote_ip4) /
5082 ICMP(id=1026, type='echo-request'))
5083 pkts.append(p)
5084 self.pg0.add_stream(pkts)
5085 self.pg_enable_capture(self.pg_interfaces)
5086 self.pg_start()
5087 self.pg1.get_capture(max_sessions)
5088
5089 nsessions = 0
5090 users = self.vapi.nat44_user_dump()
5091 for user in users:
5092 nsessions = nsessions + user.nsessions
5093 self.assertLess(nsessions, 2 * max_sessions)
5094
5095 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
5096 def test_session_limit_per_user(self):
5097 """ Maximum sessions per user limit """
5098 self.nat44_add_address(self.nat_addr)
5099 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5100 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
5101 is_inside=0)
5102 self.vapi.set_ipfix_exporter(collector_address=self.pg2.remote_ip4n,
5103 src_address=self.pg2.local_ip4n,
5104 path_mtu=512,
5105 template_interval=10)
5106
5107 # get maximum number of translations per user
5108 nat44_config = self.vapi.nat_show_config()
5109
5110 pkts = []
5111 for port in range(0, nat44_config.max_translations_per_user):
5112 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5113 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5114 UDP(sport=1025 + port, dport=1025 + port))
5115 pkts.append(p)
5116
5117 self.pg0.add_stream(pkts)
5118 self.pg_enable_capture(self.pg_interfaces)
5119 self.pg_start()
5120 capture = self.pg1.get_capture(len(pkts))
5121
5122 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
5123 src_port=self.ipfix_src_port)
5124
5125 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5126 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5127 UDP(sport=3001, dport=3002))
5128 self.pg0.add_stream(p)
5129 self.pg_enable_capture(self.pg_interfaces)
5130 self.pg_start()
5131 capture = self.pg1.assert_nothing_captured()
5132
5133 # verify IPFIX logging
5134 self.vapi.cli("ipfix flush") # FIXME this should be an API call
5135 sleep(1)
5136 capture = self.pg2.get_capture(10)
5137 ipfix = IPFIXDecoder()
5138 # first load template
5139 for p in capture:
5140 self.assertTrue(p.haslayer(IPFIX))
5141 if p.haslayer(Template):
5142 ipfix.add_template(p.getlayer(Template))
5143 # verify events in data set
5144 for p in capture:
5145 if p.haslayer(Data):
5146 data = ipfix.decode_data_set(p.getlayer(Set))
5147 self.verify_ipfix_max_entries_per_user(
5148 data,
5149 nat44_config.max_translations_per_user,
5150 self.pg0.remote_ip4n)
5151
Matus Fabiande886752016-12-07 03:38:19 -08005152 def tearDown(self):
Matus Fabiana6110b62018-06-13 05:39:07 -07005153 super(TestNAT44EndpointDependent, self).tearDown()
Matus Fabiande886752016-12-07 03:38:19 -08005154 if not self.vpp_dead:
Matus Fabian82119542018-01-25 01:13:22 -08005155 self.logger.info(self.vapi.cli("show nat44 addresses"))
5156 self.logger.info(self.vapi.cli("show nat44 interfaces"))
5157 self.logger.info(self.vapi.cli("show nat44 static mappings"))
5158 self.logger.info(self.vapi.cli("show nat44 interface address"))
5159 self.logger.info(self.vapi.cli("show nat44 sessions detail"))
Matus Fabian229c1aa2018-05-28 04:09:52 -07005160 self.logger.info(self.vapi.cli("show nat44 hash tables detail"))
Matus Fabian878c6462018-08-23 00:33:35 -07005161 self.logger.info(self.vapi.cli("show nat timeouts"))
Matus Fabian2ba92e32017-08-21 07:05:03 -07005162 self.clear_nat44()
Matus Fabian229c1aa2018-05-28 04:09:52 -07005163 self.vapi.cli("clear logging")
Matus Fabiande886752016-12-07 03:38:19 -08005164
Matus Fabianeea28d72017-01-13 04:15:54 -08005165
Juraj Slobodacba69362017-12-19 02:09:32 +01005166class TestNAT44Out2InDPO(MethodHolder):
5167 """ NAT44 Test Cases using out2in DPO """
5168
5169 @classmethod
5170 def setUpConstants(cls):
5171 super(TestNAT44Out2InDPO, cls).setUpConstants()
5172 cls.vpp_cmdline.extend(["nat", "{", "out2in dpo", "}"])
5173
5174 @classmethod
5175 def setUpClass(cls):
5176 super(TestNAT44Out2InDPO, cls).setUpClass()
Matus Fabian229c1aa2018-05-28 04:09:52 -07005177 cls.vapi.cli("set log class nat level debug")
Juraj Slobodacba69362017-12-19 02:09:32 +01005178
5179 try:
5180 cls.tcp_port_in = 6303
5181 cls.tcp_port_out = 6303
5182 cls.udp_port_in = 6304
5183 cls.udp_port_out = 6304
5184 cls.icmp_id_in = 6305
5185 cls.icmp_id_out = 6305
5186 cls.nat_addr = '10.0.0.3'
5187 cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
5188 cls.dst_ip4 = '192.168.70.1'
5189
5190 cls.create_pg_interfaces(range(2))
5191
5192 cls.pg0.admin_up()
5193 cls.pg0.config_ip4()
5194 cls.pg0.resolve_arp()
5195
5196 cls.pg1.admin_up()
5197 cls.pg1.config_ip6()
5198 cls.pg1.resolve_ndp()
5199
5200 cls.vapi.ip_add_del_route(is_ipv6=True, dst_address='\x00'*16,
5201 dst_address_length=0,
5202 next_hop_address=cls.pg1.remote_ip6n,
5203 next_hop_sw_if_index=cls.pg1.sw_if_index)
5204
5205 except Exception:
5206 super(TestNAT44Out2InDPO, cls).tearDownClass()
5207 raise
5208
5209 def configure_xlat(self):
5210 self.dst_ip6_pfx = '1:2:3::'
5211 self.dst_ip6_pfx_n = socket.inet_pton(socket.AF_INET6,
5212 self.dst_ip6_pfx)
5213 self.dst_ip6_pfx_len = 96
5214 self.src_ip6_pfx = '4:5:6::'
5215 self.src_ip6_pfx_n = socket.inet_pton(socket.AF_INET6,
5216 self.src_ip6_pfx)
5217 self.src_ip6_pfx_len = 96
5218 self.vapi.map_add_domain(self.dst_ip6_pfx_n, self.dst_ip6_pfx_len,
5219 self.src_ip6_pfx_n, self.src_ip6_pfx_len,
5220 '\x00\x00\x00\x00', 0, is_translation=1,
5221 is_rfc6052=1)
5222
5223 def test_464xlat_ce(self):
5224 """ Test 464XLAT CE with NAT44 """
5225
Matus Fabian69ce30d2018-08-22 01:27:10 -07005226 nat_config = self.vapi.nat_show_config()
5227 self.assertEqual(1, nat_config.out2in_dpo)
5228
Juraj Slobodacba69362017-12-19 02:09:32 +01005229 self.configure_xlat()
5230
5231 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5232 self.vapi.nat44_add_del_address_range(self.nat_addr_n, self.nat_addr_n)
5233
5234 out_src_ip6 = self.compose_ip6(self.dst_ip4, self.dst_ip6_pfx,
5235 self.dst_ip6_pfx_len)
5236 out_dst_ip6 = self.compose_ip6(self.nat_addr, self.src_ip6_pfx,
5237 self.src_ip6_pfx_len)
5238
5239 try:
5240 pkts = self.create_stream_in(self.pg0, self.pg1, self.dst_ip4)
5241 self.pg0.add_stream(pkts)
5242 self.pg_enable_capture(self.pg_interfaces)
5243 self.pg_start()
5244 capture = self.pg1.get_capture(len(pkts))
5245 self.verify_capture_out_ip6(capture, nat_ip=out_dst_ip6,
5246 dst_ip=out_src_ip6)
5247
5248 pkts = self.create_stream_out_ip6(self.pg1, out_src_ip6,
5249 out_dst_ip6)
5250 self.pg1.add_stream(pkts)
5251 self.pg_enable_capture(self.pg_interfaces)
5252 self.pg_start()
5253 capture = self.pg0.get_capture(len(pkts))
5254 self.verify_capture_in(capture, self.pg0)
5255 finally:
5256 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
5257 is_add=0)
5258 self.vapi.nat44_add_del_address_range(self.nat_addr_n,
5259 self.nat_addr_n, is_add=0)
5260
5261 def test_464xlat_ce_no_nat(self):
5262 """ Test 464XLAT CE without NAT44 """
5263
5264 self.configure_xlat()
5265
5266 out_src_ip6 = self.compose_ip6(self.dst_ip4, self.dst_ip6_pfx,
5267 self.dst_ip6_pfx_len)
5268 out_dst_ip6 = self.compose_ip6(self.pg0.remote_ip4, self.src_ip6_pfx,
5269 self.src_ip6_pfx_len)
5270
5271 pkts = self.create_stream_in(self.pg0, self.pg1, self.dst_ip4)
5272 self.pg0.add_stream(pkts)
5273 self.pg_enable_capture(self.pg_interfaces)
5274 self.pg_start()
5275 capture = self.pg1.get_capture(len(pkts))
5276 self.verify_capture_out_ip6(capture, dst_ip=out_src_ip6,
5277 nat_ip=out_dst_ip6, same_port=True)
5278
5279 pkts = self.create_stream_out_ip6(self.pg1, out_src_ip6, out_dst_ip6)
5280 self.pg1.add_stream(pkts)
5281 self.pg_enable_capture(self.pg_interfaces)
5282 self.pg_start()
5283 capture = self.pg0.get_capture(len(pkts))
5284 self.verify_capture_in(capture, self.pg0)
5285
5286
Martin Gálikd7f75cd2017-03-27 06:02:47 -07005287class TestDeterministicNAT(MethodHolder):
Matus Fabian066f0342017-02-10 03:48:01 -08005288 """ Deterministic NAT Test Cases """
5289
5290 @classmethod
5291 def setUpConstants(cls):
5292 super(TestDeterministicNAT, cls).setUpConstants()
Matus Fabian2ba92e32017-08-21 07:05:03 -07005293 cls.vpp_cmdline.extend(["nat", "{", "deterministic", "}"])
Matus Fabian066f0342017-02-10 03:48:01 -08005294
5295 @classmethod
5296 def setUpClass(cls):
5297 super(TestDeterministicNAT, cls).setUpClass()
Matus Fabian229c1aa2018-05-28 04:09:52 -07005298 cls.vapi.cli("set log class nat level debug")
Matus Fabian066f0342017-02-10 03:48:01 -08005299
5300 try:
Martin Gálik977c1cb2017-03-30 23:21:51 -07005301 cls.tcp_port_in = 6303
Martin Gálik9806eae2017-04-25 01:25:08 -07005302 cls.tcp_external_port = 6303
Martin Gálik977c1cb2017-03-30 23:21:51 -07005303 cls.udp_port_in = 6304
Martin Gálik9806eae2017-04-25 01:25:08 -07005304 cls.udp_external_port = 6304
Martin Gálik977c1cb2017-03-30 23:21:51 -07005305 cls.icmp_id_in = 6305
Matus Fabian2ba92e32017-08-21 07:05:03 -07005306 cls.nat_addr = '10.0.0.3'
Martin Gálik977c1cb2017-03-30 23:21:51 -07005307
Matus Fabian2f2db1c2017-04-18 05:29:59 -07005308 cls.create_pg_interfaces(range(3))
Matus Fabian066f0342017-02-10 03:48:01 -08005309 cls.interfaces = list(cls.pg_interfaces)
5310
5311 for i in cls.interfaces:
5312 i.admin_up()
5313 i.config_ip4()
5314 i.resolve_arp()
5315
Martin Gálik977c1cb2017-03-30 23:21:51 -07005316 cls.pg0.generate_remote_hosts(2)
5317 cls.pg0.configure_ipv4_neighbors()
5318
Matus Fabian066f0342017-02-10 03:48:01 -08005319 except Exception:
5320 super(TestDeterministicNAT, cls).tearDownClass()
5321 raise
5322
Martin Gálik977c1cb2017-03-30 23:21:51 -07005323 def create_stream_in(self, in_if, out_if, ttl=64):
5324 """
5325 Create packet stream for inside network
5326
5327 :param in_if: Inside interface
5328 :param out_if: Outside interface
5329 :param ttl: TTL of generated packets
5330 """
5331 pkts = []
5332 # TCP
5333 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
5334 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
Martin Gálik9806eae2017-04-25 01:25:08 -07005335 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07005336 pkts.append(p)
5337
5338 # UDP
5339 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
5340 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
Martin Gálik9806eae2017-04-25 01:25:08 -07005341 UDP(sport=self.udp_port_in, dport=self.udp_external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07005342 pkts.append(p)
5343
5344 # ICMP
5345 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
5346 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
5347 ICMP(id=self.icmp_id_in, type='echo-request'))
5348 pkts.append(p)
5349
5350 return pkts
5351
5352 def create_stream_out(self, out_if, dst_ip=None, ttl=64):
5353 """
5354 Create packet stream for outside network
5355
5356 :param out_if: Outside interface
Matus Fabian2ba92e32017-08-21 07:05:03 -07005357 :param dst_ip: Destination IP address (Default use global NAT address)
Martin Gálik977c1cb2017-03-30 23:21:51 -07005358 :param ttl: TTL of generated packets
5359 """
5360 if dst_ip is None:
Matus Fabian2ba92e32017-08-21 07:05:03 -07005361 dst_ip = self.nat_addr
Martin Gálik977c1cb2017-03-30 23:21:51 -07005362 pkts = []
5363 # TCP
5364 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
5365 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Martin Gálik9806eae2017-04-25 01:25:08 -07005366 TCP(dport=self.tcp_port_out, sport=self.tcp_external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07005367 pkts.append(p)
5368
5369 # UDP
5370 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
5371 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Martin Gálik9806eae2017-04-25 01:25:08 -07005372 UDP(dport=self.udp_port_out, sport=self.udp_external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07005373 pkts.append(p)
5374
5375 # ICMP
5376 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
5377 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
5378 ICMP(id=self.icmp_external_id, type='echo-reply'))
5379 pkts.append(p)
5380
5381 return pkts
5382
Matus Fabian05ca4a32018-09-04 23:45:13 -07005383 def verify_capture_out(self, capture, nat_ip=None):
Martin Gálik977c1cb2017-03-30 23:21:51 -07005384 """
5385 Verify captured packets on outside network
5386
5387 :param capture: Captured packets
Matus Fabian2ba92e32017-08-21 07:05:03 -07005388 :param nat_ip: Translated IP address (Default use global NAT address)
Martin Gálik977c1cb2017-03-30 23:21:51 -07005389 :param same_port: Sorce port number is not translated (Default False)
Martin Gálik977c1cb2017-03-30 23:21:51 -07005390 """
5391 if nat_ip is None:
Matus Fabian2ba92e32017-08-21 07:05:03 -07005392 nat_ip = self.nat_addr
Martin Gálik977c1cb2017-03-30 23:21:51 -07005393 for packet in capture:
5394 try:
5395 self.assertEqual(packet[IP].src, nat_ip)
5396 if packet.haslayer(TCP):
Martin Gálik9806eae2017-04-25 01:25:08 -07005397 self.tcp_port_out = packet[TCP].sport
Martin Gálik977c1cb2017-03-30 23:21:51 -07005398 elif packet.haslayer(UDP):
Martin Gálik9806eae2017-04-25 01:25:08 -07005399 self.udp_port_out = packet[UDP].sport
Martin Gálik977c1cb2017-03-30 23:21:51 -07005400 else:
5401 self.icmp_external_id = packet[ICMP].id
5402 except:
5403 self.logger.error(ppp("Unexpected or invalid packet "
5404 "(outside network):", packet))
5405 raise
5406
Matus Fabian066f0342017-02-10 03:48:01 -08005407 def test_deterministic_mode(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07005408 """ NAT plugin run deterministic mode """
Matus Fabian066f0342017-02-10 03:48:01 -08005409 in_addr = '172.16.255.0'
5410 out_addr = '172.17.255.50'
5411 in_addr_t = '172.16.255.20'
5412 in_addr_n = socket.inet_aton(in_addr)
5413 out_addr_n = socket.inet_aton(out_addr)
5414 in_addr_t_n = socket.inet_aton(in_addr_t)
5415 in_plen = 24
5416 out_plen = 32
5417
Matus Fabian2ba92e32017-08-21 07:05:03 -07005418 nat_config = self.vapi.nat_show_config()
5419 self.assertEqual(1, nat_config.deterministic)
Matus Fabian066f0342017-02-10 03:48:01 -08005420
Matus Fabian2ba92e32017-08-21 07:05:03 -07005421 self.vapi.nat_det_add_del_map(in_addr_n, in_plen, out_addr_n, out_plen)
Matus Fabian066f0342017-02-10 03:48:01 -08005422
Matus Fabian2ba92e32017-08-21 07:05:03 -07005423 rep1 = self.vapi.nat_det_forward(in_addr_t_n)
Matus Fabian066f0342017-02-10 03:48:01 -08005424 self.assertEqual(rep1.out_addr[:4], out_addr_n)
Matus Fabian2ba92e32017-08-21 07:05:03 -07005425 rep2 = self.vapi.nat_det_reverse(out_addr_n, rep1.out_port_hi)
Matus Fabian066f0342017-02-10 03:48:01 -08005426 self.assertEqual(rep2.in_addr[:4], in_addr_t_n)
5427
Matus Fabian2ba92e32017-08-21 07:05:03 -07005428 deterministic_mappings = self.vapi.nat_det_map_dump()
Martin17a75cb2017-03-08 05:53:20 -08005429 self.assertEqual(len(deterministic_mappings), 1)
5430 dsm = deterministic_mappings[0]
5431 self.assertEqual(in_addr_n, dsm.in_addr[:4])
5432 self.assertEqual(in_plen, dsm.in_plen)
5433 self.assertEqual(out_addr_n, dsm.out_addr[:4])
5434 self.assertEqual(out_plen, dsm.out_plen)
5435
Matus Fabian2ba92e32017-08-21 07:05:03 -07005436 self.clear_nat_det()
5437 deterministic_mappings = self.vapi.nat_det_map_dump()
Martinb616e9f2017-03-14 02:25:45 -07005438 self.assertEqual(len(deterministic_mappings), 0)
5439
Matus Fabian6a0946f2017-04-12 03:36:13 -07005440 def test_set_timeouts(self):
5441 """ Set deterministic NAT timeouts """
Matus Fabian878c6462018-08-23 00:33:35 -07005442 timeouts_before = self.vapi.nat_get_timeouts()
Matus Fabian6a0946f2017-04-12 03:36:13 -07005443
Matus Fabian878c6462018-08-23 00:33:35 -07005444 self.vapi.nat_set_timeouts(timeouts_before.udp + 10,
5445 timeouts_before.tcp_established + 10,
5446 timeouts_before.tcp_transitory + 10,
5447 timeouts_before.icmp + 10)
Matus Fabian6a0946f2017-04-12 03:36:13 -07005448
Matus Fabian878c6462018-08-23 00:33:35 -07005449 timeouts_after = self.vapi.nat_get_timeouts()
Matus Fabian6a0946f2017-04-12 03:36:13 -07005450
5451 self.assertNotEqual(timeouts_before.udp, timeouts_after.udp)
5452 self.assertNotEqual(timeouts_before.icmp, timeouts_after.icmp)
5453 self.assertNotEqual(timeouts_before.tcp_established,
5454 timeouts_after.tcp_established)
5455 self.assertNotEqual(timeouts_before.tcp_transitory,
5456 timeouts_after.tcp_transitory)
5457
Martin Gálik977c1cb2017-03-30 23:21:51 -07005458 def test_det_in(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07005459 """ Deterministic NAT translation test (TCP, UDP, ICMP) """
Martin Gálik977c1cb2017-03-30 23:21:51 -07005460
5461 nat_ip = "10.0.0.10"
Martin Gálik977c1cb2017-03-30 23:21:51 -07005462
Matus Fabian2ba92e32017-08-21 07:05:03 -07005463 self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
5464 32,
5465 socket.inet_aton(nat_ip),
5466 32)
5467 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5468 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
5469 is_inside=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07005470
5471 # in2out
5472 pkts = self.create_stream_in(self.pg0, self.pg1)
5473 self.pg0.add_stream(pkts)
5474 self.pg_enable_capture(self.pg_interfaces)
5475 self.pg_start()
5476 capture = self.pg1.get_capture(len(pkts))
5477 self.verify_capture_out(capture, nat_ip)
5478
5479 # out2in
5480 pkts = self.create_stream_out(self.pg1, nat_ip)
5481 self.pg1.add_stream(pkts)
5482 self.pg_enable_capture(self.pg_interfaces)
5483 self.pg_start()
5484 capture = self.pg0.get_capture(len(pkts))
5485 self.verify_capture_in(capture, self.pg0)
5486
Martin Gálik9806eae2017-04-25 01:25:08 -07005487 # session dump test
Matus Fabian2ba92e32017-08-21 07:05:03 -07005488 sessions = self.vapi.nat_det_session_dump(self.pg0.remote_ip4n)
Martin Gálik9806eae2017-04-25 01:25:08 -07005489 self.assertEqual(len(sessions), 3)
5490
5491 # TCP session
5492 s = sessions[0]
5493 self.assertEqual(s.ext_addr[:4], self.pg1.remote_ip4n)
5494 self.assertEqual(s.in_port, self.tcp_port_in)
5495 self.assertEqual(s.out_port, self.tcp_port_out)
5496 self.assertEqual(s.ext_port, self.tcp_external_port)
5497
5498 # UDP session
5499 s = sessions[1]
5500 self.assertEqual(s.ext_addr[:4], self.pg1.remote_ip4n)
5501 self.assertEqual(s.in_port, self.udp_port_in)
5502 self.assertEqual(s.out_port, self.udp_port_out)
5503 self.assertEqual(s.ext_port, self.udp_external_port)
5504
5505 # ICMP session
5506 s = sessions[2]
5507 self.assertEqual(s.ext_addr[:4], self.pg1.remote_ip4n)
5508 self.assertEqual(s.in_port, self.icmp_id_in)
5509 self.assertEqual(s.out_port, self.icmp_external_id)
5510
Martin Gálik977c1cb2017-03-30 23:21:51 -07005511 def test_multiple_users(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07005512 """ Deterministic NAT multiple users """
Martin Gálik977c1cb2017-03-30 23:21:51 -07005513
5514 nat_ip = "10.0.0.10"
5515 port_in = 80
Martin Gálik9806eae2017-04-25 01:25:08 -07005516 external_port = 6303
Martin Gálik977c1cb2017-03-30 23:21:51 -07005517
5518 host0 = self.pg0.remote_hosts[0]
5519 host1 = self.pg0.remote_hosts[1]
5520
Matus Fabian2ba92e32017-08-21 07:05:03 -07005521 self.vapi.nat_det_add_del_map(host0.ip4n,
5522 24,
5523 socket.inet_aton(nat_ip),
5524 32)
5525 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5526 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
5527 is_inside=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07005528
5529 # host0 to out
5530 p = (Ether(src=host0.mac, dst=self.pg0.local_mac) /
5531 IP(src=host0.ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07005532 TCP(sport=port_in, dport=external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07005533 self.pg0.add_stream(p)
5534 self.pg_enable_capture(self.pg_interfaces)
5535 self.pg_start()
5536 capture = self.pg1.get_capture(1)
5537 p = capture[0]
5538 try:
5539 ip = p[IP]
5540 tcp = p[TCP]
5541 self.assertEqual(ip.src, nat_ip)
5542 self.assertEqual(ip.dst, self.pg1.remote_ip4)
Martin Gálik9806eae2017-04-25 01:25:08 -07005543 self.assertEqual(tcp.dport, external_port)
5544 port_out0 = tcp.sport
Martin Gálik977c1cb2017-03-30 23:21:51 -07005545 except:
5546 self.logger.error(ppp("Unexpected or invalid packet:", p))
5547 raise
5548
5549 # host1 to out
5550 p = (Ether(src=host1.mac, dst=self.pg0.local_mac) /
5551 IP(src=host1.ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07005552 TCP(sport=port_in, dport=external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07005553 self.pg0.add_stream(p)
5554 self.pg_enable_capture(self.pg_interfaces)
5555 self.pg_start()
5556 capture = self.pg1.get_capture(1)
5557 p = capture[0]
5558 try:
5559 ip = p[IP]
5560 tcp = p[TCP]
5561 self.assertEqual(ip.src, nat_ip)
5562 self.assertEqual(ip.dst, self.pg1.remote_ip4)
Martin Gálik9806eae2017-04-25 01:25:08 -07005563 self.assertEqual(tcp.dport, external_port)
5564 port_out1 = tcp.sport
Martin Gálik977c1cb2017-03-30 23:21:51 -07005565 except:
5566 self.logger.error(ppp("Unexpected or invalid packet:", p))
5567 raise
5568
Matus Fabian2ba92e32017-08-21 07:05:03 -07005569 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07005570 self.assertEqual(1, len(dms))
5571 self.assertEqual(2, dms[0].ses_num)
5572
5573 # out to host0
5574 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5575 IP(src=self.pg1.remote_ip4, dst=nat_ip) /
Martin Gálik9806eae2017-04-25 01:25:08 -07005576 TCP(sport=external_port, dport=port_out0))
Martin Gálik977c1cb2017-03-30 23:21:51 -07005577 self.pg1.add_stream(p)
5578 self.pg_enable_capture(self.pg_interfaces)
5579 self.pg_start()
5580 capture = self.pg0.get_capture(1)
5581 p = capture[0]
5582 try:
5583 ip = p[IP]
5584 tcp = p[TCP]
5585 self.assertEqual(ip.src, self.pg1.remote_ip4)
5586 self.assertEqual(ip.dst, host0.ip4)
5587 self.assertEqual(tcp.dport, port_in)
Martin Gálik9806eae2017-04-25 01:25:08 -07005588 self.assertEqual(tcp.sport, external_port)
Martin Gálik977c1cb2017-03-30 23:21:51 -07005589 except:
5590 self.logger.error(ppp("Unexpected or invalid packet:", p))
5591 raise
5592
5593 # out to host1
5594 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5595 IP(src=self.pg1.remote_ip4, dst=nat_ip) /
Martin Gálik9806eae2017-04-25 01:25:08 -07005596 TCP(sport=external_port, dport=port_out1))
Martin Gálik977c1cb2017-03-30 23:21:51 -07005597 self.pg1.add_stream(p)
5598 self.pg_enable_capture(self.pg_interfaces)
5599 self.pg_start()
5600 capture = self.pg0.get_capture(1)
5601 p = capture[0]
5602 try:
5603 ip = p[IP]
5604 tcp = p[TCP]
5605 self.assertEqual(ip.src, self.pg1.remote_ip4)
5606 self.assertEqual(ip.dst, host1.ip4)
5607 self.assertEqual(tcp.dport, port_in)
Martin Gálik9806eae2017-04-25 01:25:08 -07005608 self.assertEqual(tcp.sport, external_port)
Martin Gálik977c1cb2017-03-30 23:21:51 -07005609 except:
5610 self.logger.error(ppp("Unexpected or invalid packet", p))
5611 raise
5612
Martin Gálik6bc8c642017-04-19 01:12:27 -07005613 # session close api test
Matus Fabian2ba92e32017-08-21 07:05:03 -07005614 self.vapi.nat_det_close_session_out(socket.inet_aton(nat_ip),
5615 port_out1,
Martin Gálik6bc8c642017-04-19 01:12:27 -07005616 self.pg1.remote_ip4n,
Martin Gálik9806eae2017-04-25 01:25:08 -07005617 external_port)
Matus Fabian2ba92e32017-08-21 07:05:03 -07005618 dms = self.vapi.nat_det_map_dump()
5619 self.assertEqual(dms[0].ses_num, 1)
5620
5621 self.vapi.nat_det_close_session_in(host0.ip4n,
5622 port_in,
5623 self.pg1.remote_ip4n,
5624 external_port)
5625 dms = self.vapi.nat_det_map_dump()
Martin Gálik6bc8c642017-04-19 01:12:27 -07005626 self.assertEqual(dms[0].ses_num, 0)
5627
Martin Gálik977c1cb2017-03-30 23:21:51 -07005628 def test_tcp_session_close_detection_in(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07005629 """ Deterministic NAT TCP session close from inside network """
5630 self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
5631 32,
5632 socket.inet_aton(self.nat_addr),
5633 32)
5634 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5635 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
5636 is_inside=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07005637
5638 self.initiate_tcp_session(self.pg0, self.pg1)
5639
5640 # close the session from inside
5641 try:
5642 # FIN packet in -> out
5643 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5644 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07005645 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
Martin Gálik977c1cb2017-03-30 23:21:51 -07005646 flags="F"))
5647 self.pg0.add_stream(p)
5648 self.pg_enable_capture(self.pg_interfaces)
5649 self.pg_start()
5650 self.pg1.get_capture(1)
5651
5652 pkts = []
5653
5654 # ACK packet out -> in
5655 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07005656 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Martin Gálik9806eae2017-04-25 01:25:08 -07005657 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
Martin Gálik977c1cb2017-03-30 23:21:51 -07005658 flags="A"))
5659 pkts.append(p)
5660
5661 # FIN packet out -> in
5662 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07005663 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Martin Gálik9806eae2017-04-25 01:25:08 -07005664 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
Martin Gálik977c1cb2017-03-30 23:21:51 -07005665 flags="F"))
5666 pkts.append(p)
5667
5668 self.pg1.add_stream(pkts)
5669 self.pg_enable_capture(self.pg_interfaces)
5670 self.pg_start()
5671 self.pg0.get_capture(2)
5672
5673 # ACK packet in -> out
5674 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5675 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07005676 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
Martin Gálik977c1cb2017-03-30 23:21:51 -07005677 flags="A"))
5678 self.pg0.add_stream(p)
5679 self.pg_enable_capture(self.pg_interfaces)
5680 self.pg_start()
5681 self.pg1.get_capture(1)
5682
Matus Fabian2ba92e32017-08-21 07:05:03 -07005683 # Check if deterministic NAT44 closed the session
5684 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07005685 self.assertEqual(0, dms[0].ses_num)
5686 except:
5687 self.logger.error("TCP session termination failed")
5688 raise
5689
5690 def test_tcp_session_close_detection_out(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07005691 """ Deterministic NAT TCP session close from outside network """
5692 self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
5693 32,
5694 socket.inet_aton(self.nat_addr),
5695 32)
5696 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5697 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
5698 is_inside=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07005699
5700 self.initiate_tcp_session(self.pg0, self.pg1)
5701
5702 # close the session from outside
5703 try:
5704 # FIN packet out -> in
5705 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07005706 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Martin Gálik9806eae2017-04-25 01:25:08 -07005707 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
Martin Gálik977c1cb2017-03-30 23:21:51 -07005708 flags="F"))
5709 self.pg1.add_stream(p)
5710 self.pg_enable_capture(self.pg_interfaces)
5711 self.pg_start()
5712 self.pg0.get_capture(1)
5713
5714 pkts = []
5715
5716 # ACK packet in -> out
5717 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5718 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07005719 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
Martin Gálik977c1cb2017-03-30 23:21:51 -07005720 flags="A"))
5721 pkts.append(p)
5722
5723 # ACK packet in -> out
5724 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5725 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07005726 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
Martin Gálik977c1cb2017-03-30 23:21:51 -07005727 flags="F"))
5728 pkts.append(p)
5729
5730 self.pg0.add_stream(pkts)
5731 self.pg_enable_capture(self.pg_interfaces)
5732 self.pg_start()
5733 self.pg1.get_capture(2)
5734
5735 # ACK packet out -> in
5736 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07005737 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Martin Gálik9806eae2017-04-25 01:25:08 -07005738 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
Martin Gálik977c1cb2017-03-30 23:21:51 -07005739 flags="A"))
5740 self.pg1.add_stream(p)
5741 self.pg_enable_capture(self.pg_interfaces)
5742 self.pg_start()
5743 self.pg0.get_capture(1)
5744
Matus Fabian2ba92e32017-08-21 07:05:03 -07005745 # Check if deterministic NAT44 closed the session
5746 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07005747 self.assertEqual(0, dms[0].ses_num)
5748 except:
5749 self.logger.error("TCP session termination failed")
5750 raise
5751
5752 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
5753 def test_session_timeout(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07005754 """ Deterministic NAT session timeouts """
5755 self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
5756 32,
5757 socket.inet_aton(self.nat_addr),
5758 32)
5759 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5760 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
5761 is_inside=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07005762
5763 self.initiate_tcp_session(self.pg0, self.pg1)
Matus Fabian878c6462018-08-23 00:33:35 -07005764 self.vapi.nat_set_timeouts(5, 5, 5, 5)
Martin Gálik977c1cb2017-03-30 23:21:51 -07005765 pkts = self.create_stream_in(self.pg0, self.pg1)
5766 self.pg0.add_stream(pkts)
5767 self.pg_enable_capture(self.pg_interfaces)
5768 self.pg_start()
5769 capture = self.pg1.get_capture(len(pkts))
5770 sleep(15)
5771
Matus Fabian2ba92e32017-08-21 07:05:03 -07005772 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07005773 self.assertEqual(0, dms[0].ses_num)
5774
Matus Fabian7c0aecc2017-07-03 01:21:38 -07005775 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
Martin Gálik977c1cb2017-03-30 23:21:51 -07005776 def test_session_limit_per_user(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07005777 """ Deterministic NAT maximum sessions per user limit """
5778 self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
5779 32,
5780 socket.inet_aton(self.nat_addr),
5781 32)
5782 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5783 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
5784 is_inside=0)
Matus Fabian2f2db1c2017-04-18 05:29:59 -07005785 self.vapi.set_ipfix_exporter(collector_address=self.pg2.remote_ip4n,
5786 src_address=self.pg2.local_ip4n,
5787 path_mtu=512,
5788 template_interval=10)
Matus Fabian2ba92e32017-08-21 07:05:03 -07005789 self.vapi.nat_ipfix()
Martin Gálik977c1cb2017-03-30 23:21:51 -07005790
5791 pkts = []
5792 for port in range(1025, 2025):
5793 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5794 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5795 UDP(sport=port, dport=port))
5796 pkts.append(p)
5797
5798 self.pg0.add_stream(pkts)
5799 self.pg_enable_capture(self.pg_interfaces)
5800 self.pg_start()
5801 capture = self.pg1.get_capture(len(pkts))
5802
5803 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5804 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálikf7e655d2017-04-27 02:13:26 -07005805 UDP(sport=3001, dport=3002))
Martin Gálik977c1cb2017-03-30 23:21:51 -07005806 self.pg0.add_stream(p)
5807 self.pg_enable_capture(self.pg_interfaces)
5808 self.pg_start()
5809 capture = self.pg1.assert_nothing_captured()
5810
Martin Gálikf7e655d2017-04-27 02:13:26 -07005811 # verify ICMP error packet
5812 capture = self.pg0.get_capture(1)
5813 p = capture[0]
5814 self.assertTrue(p.haslayer(ICMP))
5815 icmp = p[ICMP]
5816 self.assertEqual(icmp.type, 3)
5817 self.assertEqual(icmp.code, 1)
5818 self.assertTrue(icmp.haslayer(IPerror))
5819 inner_ip = icmp[IPerror]
5820 self.assertEqual(inner_ip[UDPerror].sport, 3001)
5821 self.assertEqual(inner_ip[UDPerror].dport, 3002)
5822
Matus Fabian2ba92e32017-08-21 07:05:03 -07005823 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07005824
5825 self.assertEqual(1000, dms[0].ses_num)
5826
Matus Fabian2f2db1c2017-04-18 05:29:59 -07005827 # verify IPFIX logging
5828 self.vapi.cli("ipfix flush") # FIXME this should be an API call
Matus Fabian7c0aecc2017-07-03 01:21:38 -07005829 sleep(1)
Matus Fabian2f2db1c2017-04-18 05:29:59 -07005830 capture = self.pg2.get_capture(2)
5831 ipfix = IPFIXDecoder()
5832 # first load template
5833 for p in capture:
5834 self.assertTrue(p.haslayer(IPFIX))
5835 if p.haslayer(Template):
5836 ipfix.add_template(p.getlayer(Template))
5837 # verify events in data set
5838 for p in capture:
5839 if p.haslayer(Data):
5840 data = ipfix.decode_data_set(p.getlayer(Set))
Matus Fabian878c6462018-08-23 00:33:35 -07005841 self.verify_ipfix_max_entries_per_user(data,
5842 1000,
5843 self.pg0.remote_ip4n)
Matus Fabian2f2db1c2017-04-18 05:29:59 -07005844
Matus Fabian2ba92e32017-08-21 07:05:03 -07005845 def clear_nat_det(self):
Martin17a75cb2017-03-08 05:53:20 -08005846 """
Matus Fabian2ba92e32017-08-21 07:05:03 -07005847 Clear deterministic NAT configuration.
Martin17a75cb2017-03-08 05:53:20 -08005848 """
Matus Fabian2ba92e32017-08-21 07:05:03 -07005849 self.vapi.nat_ipfix(enable=0)
Matus Fabian878c6462018-08-23 00:33:35 -07005850 self.vapi.nat_set_timeouts()
Matus Fabian2ba92e32017-08-21 07:05:03 -07005851 deterministic_mappings = self.vapi.nat_det_map_dump()
Martin17a75cb2017-03-08 05:53:20 -08005852 for dsm in deterministic_mappings:
Matus Fabian2ba92e32017-08-21 07:05:03 -07005853 self.vapi.nat_det_add_del_map(dsm.in_addr,
5854 dsm.in_plen,
5855 dsm.out_addr,
5856 dsm.out_plen,
5857 is_add=0)
Martin17a75cb2017-03-08 05:53:20 -08005858
Matus Fabian2ba92e32017-08-21 07:05:03 -07005859 interfaces = self.vapi.nat44_interface_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07005860 for intf in interfaces:
Matus Fabian2ba92e32017-08-21 07:05:03 -07005861 self.vapi.nat44_interface_add_del_feature(intf.sw_if_index,
5862 intf.is_inside,
5863 is_add=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07005864
Matus Fabian066f0342017-02-10 03:48:01 -08005865 def tearDown(self):
5866 super(TestDeterministicNAT, self).tearDown()
5867 if not self.vpp_dead:
Matus Fabian82119542018-01-25 01:13:22 -08005868 self.logger.info(self.vapi.cli("show nat44 interfaces"))
Matus Fabian878c6462018-08-23 00:33:35 -07005869 self.logger.info(self.vapi.cli("show nat timeouts"))
Matus Fabian82119542018-01-25 01:13:22 -08005870 self.logger.info(
5871 self.vapi.cli("show nat44 deterministic mappings"))
5872 self.logger.info(
Matus Fabian82119542018-01-25 01:13:22 -08005873 self.vapi.cli("show nat44 deterministic sessions"))
Matus Fabian2ba92e32017-08-21 07:05:03 -07005874 self.clear_nat_det()
Matus Fabian066f0342017-02-10 03:48:01 -08005875
Matus Fabian06596c52017-06-06 04:53:28 -07005876
5877class TestNAT64(MethodHolder):
5878 """ NAT64 Test Cases """
5879
5880 @classmethod
Matus Fabiana431ad12018-01-04 04:03:14 -08005881 def setUpConstants(cls):
5882 super(TestNAT64, cls).setUpConstants()
5883 cls.vpp_cmdline.extend(["nat", "{", "nat64 bib hash buckets 128",
5884 "nat64 st hash buckets 256", "}"])
5885
5886 @classmethod
Matus Fabian06596c52017-06-06 04:53:28 -07005887 def setUpClass(cls):
5888 super(TestNAT64, cls).setUpClass()
5889
5890 try:
5891 cls.tcp_port_in = 6303
5892 cls.tcp_port_out = 6303
5893 cls.udp_port_in = 6304
5894 cls.udp_port_out = 6304
5895 cls.icmp_id_in = 6305
5896 cls.icmp_id_out = 6305
5897 cls.nat_addr = '10.0.0.3'
5898 cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
Matus Fabian029f3d22017-06-15 02:28:50 -07005899 cls.vrf1_id = 10
5900 cls.vrf1_nat_addr = '10.0.10.3'
5901 cls.vrf1_nat_addr_n = socket.inet_pton(socket.AF_INET,
5902 cls.vrf1_nat_addr)
Matus Fabiana431ad12018-01-04 04:03:14 -08005903 cls.ipfix_src_port = 4739
5904 cls.ipfix_domain_id = 1
Matus Fabian06596c52017-06-06 04:53:28 -07005905
Juraj Slobodac746a152018-07-09 02:36:37 +02005906 cls.create_pg_interfaces(range(6))
Matus Fabian06596c52017-06-06 04:53:28 -07005907 cls.ip6_interfaces = list(cls.pg_interfaces[0:1])
Matus Fabian029f3d22017-06-15 02:28:50 -07005908 cls.ip6_interfaces.append(cls.pg_interfaces[2])
Matus Fabian06596c52017-06-06 04:53:28 -07005909 cls.ip4_interfaces = list(cls.pg_interfaces[1:2])
5910
Neale Ranns15002542017-09-10 04:39:11 -07005911 cls.vapi.ip_table_add_del(cls.vrf1_id, is_add=1, is_ipv6=1)
5912
Matus Fabian029f3d22017-06-15 02:28:50 -07005913 cls.pg_interfaces[2].set_table_ip6(cls.vrf1_id)
5914
5915 cls.pg0.generate_remote_hosts(2)
5916
Matus Fabian06596c52017-06-06 04:53:28 -07005917 for i in cls.ip6_interfaces:
5918 i.admin_up()
5919 i.config_ip6()
Matus Fabian029f3d22017-06-15 02:28:50 -07005920 i.configure_ipv6_neighbors()
Matus Fabian06596c52017-06-06 04:53:28 -07005921
5922 for i in cls.ip4_interfaces:
5923 i.admin_up()
5924 i.config_ip4()
5925 i.resolve_arp()
5926
Matus Fabian36ea2d62017-10-24 04:13:49 -07005927 cls.pg3.admin_up()
5928 cls.pg3.config_ip4()
5929 cls.pg3.resolve_arp()
5930 cls.pg3.config_ip6()
5931 cls.pg3.configure_ipv6_neighbors()
5932
Juraj Slobodac746a152018-07-09 02:36:37 +02005933 cls.pg5.admin_up()
5934 cls.pg5.config_ip6()
5935
Matus Fabian06596c52017-06-06 04:53:28 -07005936 except Exception:
5937 super(TestNAT64, cls).tearDownClass()
5938 raise
5939
Juraj Slobodac746a152018-07-09 02:36:37 +02005940 def test_nat64_inside_interface_handles_neighbor_advertisement(self):
5941 """ NAT64 inside interface handles Neighbor Advertisement """
5942
5943 self.vapi.nat64_add_del_interface(self.pg5.sw_if_index)
5944
5945 # Try to send ping
5946 ping = (Ether(dst=self.pg5.local_mac, src=self.pg5.remote_mac) /
5947 IPv6(src=self.pg5.remote_ip6, dst=self.pg5.local_ip6) /
5948 ICMPv6EchoRequest())
5949 pkts = [ping]
5950 self.pg5.add_stream(pkts)
5951 self.pg_enable_capture(self.pg_interfaces)
5952 self.pg_start()
5953
5954 # Wait for Neighbor Solicitation
5955 capture = self.pg5.get_capture(len(pkts))
Juraj Slobodac746a152018-07-09 02:36:37 +02005956 packet = capture[0]
5957 try:
5958 self.assertEqual(packet[IPv6].src, self.pg5.local_ip6)
5959 self.assertTrue(packet.haslayer(ICMPv6ND_NS))
5960 tgt = packet[ICMPv6ND_NS].tgt
5961 except:
5962 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5963 raise
5964
5965 # Send Neighbor Advertisement
5966 p = (Ether(dst=self.pg5.local_mac, src=self.pg5.remote_mac) /
5967 IPv6(src=self.pg5.remote_ip6, dst=self.pg5.local_ip6) /
5968 ICMPv6ND_NA(tgt=tgt) /
5969 ICMPv6NDOptDstLLAddr(lladdr=self.pg5.remote_mac))
5970 pkts = [p]
5971 self.pg5.add_stream(pkts)
5972 self.pg_enable_capture(self.pg_interfaces)
5973 self.pg_start()
5974
5975 # Try to send ping again
5976 pkts = [ping]
5977 self.pg5.add_stream(pkts)
5978 self.pg_enable_capture(self.pg_interfaces)
5979 self.pg_start()
5980
5981 # Wait for ping reply
5982 capture = self.pg5.get_capture(len(pkts))
Juraj Slobodac746a152018-07-09 02:36:37 +02005983 packet = capture[0]
5984 try:
5985 self.assertEqual(packet[IPv6].src, self.pg5.local_ip6)
5986 self.assertEqual(packet[IPv6].dst, self.pg5.remote_ip6)
5987 self.assertTrue(packet.haslayer(ICMPv6EchoReply))
5988 except:
5989 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5990 raise
5991
Matus Fabian06596c52017-06-06 04:53:28 -07005992 def test_pool(self):
5993 """ Add/delete address to NAT64 pool """
5994 nat_addr = socket.inet_pton(socket.AF_INET, '1.2.3.4')
5995
5996 self.vapi.nat64_add_del_pool_addr_range(nat_addr, nat_addr)
5997
5998 addresses = self.vapi.nat64_pool_addr_dump()
5999 self.assertEqual(len(addresses), 1)
6000 self.assertEqual(addresses[0].address, nat_addr)
6001
6002 self.vapi.nat64_add_del_pool_addr_range(nat_addr, nat_addr, is_add=0)
6003
6004 addresses = self.vapi.nat64_pool_addr_dump()
6005 self.assertEqual(len(addresses), 0)
6006
6007 def test_interface(self):
6008 """ Enable/disable NAT64 feature on the interface """
6009 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6010 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6011
6012 interfaces = self.vapi.nat64_interface_dump()
6013 self.assertEqual(len(interfaces), 2)
6014 pg0_found = False
6015 pg1_found = False
6016 for intf in interfaces:
6017 if intf.sw_if_index == self.pg0.sw_if_index:
6018 self.assertEqual(intf.is_inside, 1)
6019 pg0_found = True
6020 elif intf.sw_if_index == self.pg1.sw_if_index:
6021 self.assertEqual(intf.is_inside, 0)
6022 pg1_found = True
6023 self.assertTrue(pg0_found)
6024 self.assertTrue(pg1_found)
6025
6026 features = self.vapi.cli("show interface features pg0")
6027 self.assertNotEqual(features.find('nat64-in2out'), -1)
6028 features = self.vapi.cli("show interface features pg1")
6029 self.assertNotEqual(features.find('nat64-out2in'), -1)
6030
6031 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index, is_add=0)
6032 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_add=0)
6033
6034 interfaces = self.vapi.nat64_interface_dump()
6035 self.assertEqual(len(interfaces), 0)
6036
6037 def test_static_bib(self):
6038 """ Add/delete static BIB entry """
6039 in_addr = socket.inet_pton(socket.AF_INET6,
6040 '2001:db8:85a3::8a2e:370:7334')
6041 out_addr = socket.inet_pton(socket.AF_INET, '10.1.1.3')
6042 in_port = 1234
6043 out_port = 5678
6044 proto = IP_PROTOS.tcp
6045
6046 self.vapi.nat64_add_del_static_bib(in_addr,
6047 out_addr,
6048 in_port,
6049 out_port,
6050 proto)
6051 bib = self.vapi.nat64_bib_dump(IP_PROTOS.tcp)
6052 static_bib_num = 0
6053 for bibe in bib:
6054 if bibe.is_static:
6055 static_bib_num += 1
6056 self.assertEqual(bibe.i_addr, in_addr)
6057 self.assertEqual(bibe.o_addr, out_addr)
6058 self.assertEqual(bibe.i_port, in_port)
6059 self.assertEqual(bibe.o_port, out_port)
6060 self.assertEqual(static_bib_num, 1)
6061
6062 self.vapi.nat64_add_del_static_bib(in_addr,
6063 out_addr,
6064 in_port,
6065 out_port,
6066 proto,
6067 is_add=0)
6068 bib = self.vapi.nat64_bib_dump(IP_PROTOS.tcp)
6069 static_bib_num = 0
6070 for bibe in bib:
6071 if bibe.is_static:
6072 static_bib_num += 1
6073 self.assertEqual(static_bib_num, 0)
6074
6075 def test_set_timeouts(self):
6076 """ Set NAT64 timeouts """
6077 # verify default values
Matus Fabian878c6462018-08-23 00:33:35 -07006078 timeouts = self.vapi.nat_get_timeouts()
Matus Fabian06596c52017-06-06 04:53:28 -07006079 self.assertEqual(timeouts.udp, 300)
6080 self.assertEqual(timeouts.icmp, 60)
Matus Fabian878c6462018-08-23 00:33:35 -07006081 self.assertEqual(timeouts.tcp_transitory, 240)
6082 self.assertEqual(timeouts.tcp_established, 7440)
Matus Fabian06596c52017-06-06 04:53:28 -07006083
6084 # set and verify custom values
Matus Fabian878c6462018-08-23 00:33:35 -07006085 self.vapi.nat_set_timeouts(udp=200, icmp=30, tcp_transitory=250,
6086 tcp_established=7450)
6087 timeouts = self.vapi.nat_get_timeouts()
Matus Fabian06596c52017-06-06 04:53:28 -07006088 self.assertEqual(timeouts.udp, 200)
6089 self.assertEqual(timeouts.icmp, 30)
Matus Fabian878c6462018-08-23 00:33:35 -07006090 self.assertEqual(timeouts.tcp_transitory, 250)
6091 self.assertEqual(timeouts.tcp_established, 7450)
Matus Fabian06596c52017-06-06 04:53:28 -07006092
6093 def test_dynamic(self):
6094 """ NAT64 dynamic translation test """
6095 self.tcp_port_in = 6303
6096 self.udp_port_in = 6304
6097 self.icmp_id_in = 6305
6098
6099 ses_num_start = self.nat64_get_ses_num()
6100
6101 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6102 self.nat_addr_n)
6103 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6104 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6105
6106 # in2out
6107 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
6108 self.pg0.add_stream(pkts)
6109 self.pg_enable_capture(self.pg_interfaces)
6110 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07006111 capture = self.pg1.get_capture(len(pkts))
6112 self.verify_capture_out(capture, nat_ip=self.nat_addr,
Matus Fabian06596c52017-06-06 04:53:28 -07006113 dst_ip=self.pg1.remote_ip4)
6114
6115 # out2in
6116 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
6117 self.pg1.add_stream(pkts)
6118 self.pg_enable_capture(self.pg_interfaces)
6119 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07006120 capture = self.pg0.get_capture(len(pkts))
Matus Fabian06596c52017-06-06 04:53:28 -07006121 ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
6122 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
6123
6124 # in2out
6125 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
6126 self.pg0.add_stream(pkts)
6127 self.pg_enable_capture(self.pg_interfaces)
6128 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07006129 capture = self.pg1.get_capture(len(pkts))
6130 self.verify_capture_out(capture, nat_ip=self.nat_addr,
Matus Fabian06596c52017-06-06 04:53:28 -07006131 dst_ip=self.pg1.remote_ip4)
6132
6133 # out2in
6134 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
6135 self.pg1.add_stream(pkts)
6136 self.pg_enable_capture(self.pg_interfaces)
6137 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07006138 capture = self.pg0.get_capture(len(pkts))
Matus Fabian06596c52017-06-06 04:53:28 -07006139 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
6140
6141 ses_num_end = self.nat64_get_ses_num()
6142
6143 self.assertEqual(ses_num_end - ses_num_start, 3)
6144
Matus Fabian029f3d22017-06-15 02:28:50 -07006145 # tenant with specific VRF
6146 self.vapi.nat64_add_del_pool_addr_range(self.vrf1_nat_addr_n,
6147 self.vrf1_nat_addr_n,
6148 vrf_id=self.vrf1_id)
6149 self.vapi.nat64_add_del_interface(self.pg2.sw_if_index)
6150
6151 pkts = self.create_stream_in_ip6(self.pg2, self.pg1)
6152 self.pg2.add_stream(pkts)
6153 self.pg_enable_capture(self.pg_interfaces)
6154 self.pg_start()
6155 capture = self.pg1.get_capture(len(pkts))
6156 self.verify_capture_out(capture, nat_ip=self.vrf1_nat_addr,
6157 dst_ip=self.pg1.remote_ip4)
6158
6159 pkts = self.create_stream_out(self.pg1, dst_ip=self.vrf1_nat_addr)
6160 self.pg1.add_stream(pkts)
6161 self.pg_enable_capture(self.pg_interfaces)
6162 self.pg_start()
6163 capture = self.pg2.get_capture(len(pkts))
6164 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg2.remote_ip6)
6165
Matus Fabian06596c52017-06-06 04:53:28 -07006166 def test_static(self):
6167 """ NAT64 static translation test """
6168 self.tcp_port_in = 60303
6169 self.udp_port_in = 60304
6170 self.icmp_id_in = 60305
6171 self.tcp_port_out = 60303
6172 self.udp_port_out = 60304
6173 self.icmp_id_out = 60305
6174
6175 ses_num_start = self.nat64_get_ses_num()
6176
6177 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6178 self.nat_addr_n)
6179 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6180 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6181
6182 self.vapi.nat64_add_del_static_bib(self.pg0.remote_ip6n,
6183 self.nat_addr_n,
6184 self.tcp_port_in,
6185 self.tcp_port_out,
6186 IP_PROTOS.tcp)
6187 self.vapi.nat64_add_del_static_bib(self.pg0.remote_ip6n,
6188 self.nat_addr_n,
6189 self.udp_port_in,
6190 self.udp_port_out,
6191 IP_PROTOS.udp)
6192 self.vapi.nat64_add_del_static_bib(self.pg0.remote_ip6n,
6193 self.nat_addr_n,
6194 self.icmp_id_in,
6195 self.icmp_id_out,
6196 IP_PROTOS.icmp)
6197
6198 # in2out
6199 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
6200 self.pg0.add_stream(pkts)
6201 self.pg_enable_capture(self.pg_interfaces)
6202 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07006203 capture = self.pg1.get_capture(len(pkts))
6204 self.verify_capture_out(capture, nat_ip=self.nat_addr,
Matus Fabian06596c52017-06-06 04:53:28 -07006205 dst_ip=self.pg1.remote_ip4, same_port=True)
6206
6207 # out2in
6208 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
6209 self.pg1.add_stream(pkts)
6210 self.pg_enable_capture(self.pg_interfaces)
6211 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07006212 capture = self.pg0.get_capture(len(pkts))
Matus Fabian06596c52017-06-06 04:53:28 -07006213 ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
6214 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
6215
6216 ses_num_end = self.nat64_get_ses_num()
6217
6218 self.assertEqual(ses_num_end - ses_num_start, 3)
6219
6220 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
6221 def test_session_timeout(self):
6222 """ NAT64 session timeout """
6223 self.icmp_id_in = 1234
6224 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6225 self.nat_addr_n)
6226 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6227 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
Matus Fabian878c6462018-08-23 00:33:35 -07006228 self.vapi.nat_set_timeouts(icmp=5, tcp_transitory=5, tcp_established=5)
Matus Fabian06596c52017-06-06 04:53:28 -07006229
6230 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
6231 self.pg0.add_stream(pkts)
6232 self.pg_enable_capture(self.pg_interfaces)
6233 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07006234 capture = self.pg1.get_capture(len(pkts))
Matus Fabian06596c52017-06-06 04:53:28 -07006235
6236 ses_num_before_timeout = self.nat64_get_ses_num()
6237
6238 sleep(15)
6239
Matus Fabian8fed4242018-08-14 05:14:55 -07006240 # ICMP and TCP session after timeout
Matus Fabian06596c52017-06-06 04:53:28 -07006241 ses_num_after_timeout = self.nat64_get_ses_num()
Matus Fabian8fed4242018-08-14 05:14:55 -07006242 self.assertEqual(ses_num_before_timeout - ses_num_after_timeout, 2)
Matus Fabian06596c52017-06-06 04:53:28 -07006243
Matus Fabian732036d2017-06-08 05:24:28 -07006244 def test_icmp_error(self):
6245 """ NAT64 ICMP Error message translation """
6246 self.tcp_port_in = 6303
6247 self.udp_port_in = 6304
6248 self.icmp_id_in = 6305
6249
Matus Fabian732036d2017-06-08 05:24:28 -07006250 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6251 self.nat_addr_n)
6252 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6253 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6254
6255 # send some packets to create sessions
6256 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
6257 self.pg0.add_stream(pkts)
6258 self.pg_enable_capture(self.pg_interfaces)
6259 self.pg_start()
6260 capture_ip4 = self.pg1.get_capture(len(pkts))
Matus Fabian029f3d22017-06-15 02:28:50 -07006261 self.verify_capture_out(capture_ip4,
Matus Fabian732036d2017-06-08 05:24:28 -07006262 nat_ip=self.nat_addr,
6263 dst_ip=self.pg1.remote_ip4)
6264
6265 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
6266 self.pg1.add_stream(pkts)
6267 self.pg_enable_capture(self.pg_interfaces)
6268 self.pg_start()
6269 capture_ip6 = self.pg0.get_capture(len(pkts))
6270 ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
6271 self.verify_capture_in_ip6(capture_ip6, ip[IPv6].src,
6272 self.pg0.remote_ip6)
6273
6274 # in2out
6275 pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6276 IPv6(src=self.pg0.remote_ip6, dst=ip[IPv6].src) /
6277 ICMPv6DestUnreach(code=1) /
6278 packet[IPv6] for packet in capture_ip6]
6279 self.pg0.add_stream(pkts)
6280 self.pg_enable_capture(self.pg_interfaces)
6281 self.pg_start()
6282 capture = self.pg1.get_capture(len(pkts))
6283 for packet in capture:
6284 try:
6285 self.assertEqual(packet[IP].src, self.nat_addr)
6286 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
6287 self.assertEqual(packet[ICMP].type, 3)
6288 self.assertEqual(packet[ICMP].code, 13)
6289 inner = packet[IPerror]
6290 self.assertEqual(inner.src, self.pg1.remote_ip4)
6291 self.assertEqual(inner.dst, self.nat_addr)
Klement Sekerad81ae412018-05-16 10:52:54 +02006292 self.assert_packet_checksums_valid(packet)
Matus Fabian732036d2017-06-08 05:24:28 -07006293 if inner.haslayer(TCPerror):
6294 self.assertEqual(inner[TCPerror].dport, self.tcp_port_out)
6295 elif inner.haslayer(UDPerror):
6296 self.assertEqual(inner[UDPerror].dport, self.udp_port_out)
6297 else:
6298 self.assertEqual(inner[ICMPerror].id, self.icmp_id_out)
6299 except:
6300 self.logger.error(ppp("Unexpected or invalid packet:", packet))
6301 raise
6302
6303 # out2in
6304 pkts = [Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
6305 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6306 ICMP(type=3, code=13) /
6307 packet[IP] for packet in capture_ip4]
6308 self.pg1.add_stream(pkts)
6309 self.pg_enable_capture(self.pg_interfaces)
6310 self.pg_start()
6311 capture = self.pg0.get_capture(len(pkts))
6312 for packet in capture:
6313 try:
6314 self.assertEqual(packet[IPv6].src, ip.src)
6315 self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
6316 icmp = packet[ICMPv6DestUnreach]
6317 self.assertEqual(icmp.code, 1)
6318 inner = icmp[IPerror6]
6319 self.assertEqual(inner.src, self.pg0.remote_ip6)
6320 self.assertEqual(inner.dst, ip.src)
Klement Sekerad81ae412018-05-16 10:52:54 +02006321 self.assert_icmpv6_checksum_valid(packet)
Matus Fabian732036d2017-06-08 05:24:28 -07006322 if inner.haslayer(TCPerror):
6323 self.assertEqual(inner[TCPerror].sport, self.tcp_port_in)
6324 elif inner.haslayer(UDPerror):
6325 self.assertEqual(inner[UDPerror].sport, self.udp_port_in)
6326 else:
6327 self.assertEqual(inner[ICMPv6EchoRequest].id,
6328 self.icmp_id_in)
6329 except:
6330 self.logger.error(ppp("Unexpected or invalid packet:", packet))
6331 raise
6332
Matus Fabian029f3d22017-06-15 02:28:50 -07006333 def test_hairpinning(self):
6334 """ NAT64 hairpinning """
6335
6336 client = self.pg0.remote_hosts[0]
6337 server = self.pg0.remote_hosts[1]
6338 server_tcp_in_port = 22
6339 server_tcp_out_port = 4022
6340 server_udp_in_port = 23
6341 server_udp_out_port = 4023
6342 client_tcp_in_port = 1234
6343 client_udp_in_port = 1235
6344 client_tcp_out_port = 0
6345 client_udp_out_port = 0
6346 ip = IPv6(src=''.join(['64:ff9b::', self.nat_addr]))
6347 nat_addr_ip6 = ip.src
6348
6349 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6350 self.nat_addr_n)
6351 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6352 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6353
6354 self.vapi.nat64_add_del_static_bib(server.ip6n,
6355 self.nat_addr_n,
6356 server_tcp_in_port,
6357 server_tcp_out_port,
6358 IP_PROTOS.tcp)
6359 self.vapi.nat64_add_del_static_bib(server.ip6n,
6360 self.nat_addr_n,
6361 server_udp_in_port,
6362 server_udp_out_port,
6363 IP_PROTOS.udp)
6364
6365 # client to server
6366 pkts = []
6367 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6368 IPv6(src=client.ip6, dst=nat_addr_ip6) /
6369 TCP(sport=client_tcp_in_port, dport=server_tcp_out_port))
6370 pkts.append(p)
6371 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6372 IPv6(src=client.ip6, dst=nat_addr_ip6) /
6373 UDP(sport=client_udp_in_port, dport=server_udp_out_port))
6374 pkts.append(p)
6375 self.pg0.add_stream(pkts)
6376 self.pg_enable_capture(self.pg_interfaces)
6377 self.pg_start()
6378 capture = self.pg0.get_capture(len(pkts))
6379 for packet in capture:
6380 try:
6381 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
6382 self.assertEqual(packet[IPv6].dst, server.ip6)
Klement Sekerad81ae412018-05-16 10:52:54 +02006383 self.assert_packet_checksums_valid(packet)
Matus Fabian029f3d22017-06-15 02:28:50 -07006384 if packet.haslayer(TCP):
6385 self.assertNotEqual(packet[TCP].sport, client_tcp_in_port)
6386 self.assertEqual(packet[TCP].dport, server_tcp_in_port)
Matus Fabian029f3d22017-06-15 02:28:50 -07006387 client_tcp_out_port = packet[TCP].sport
6388 else:
6389 self.assertNotEqual(packet[UDP].sport, client_udp_in_port)
6390 self.assertEqual(packet[UDP].dport, server_udp_in_port)
Matus Fabian029f3d22017-06-15 02:28:50 -07006391 client_udp_out_port = packet[UDP].sport
6392 except:
6393 self.logger.error(ppp("Unexpected or invalid packet:", packet))
6394 raise
6395
6396 # server to client
6397 pkts = []
6398 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6399 IPv6(src=server.ip6, dst=nat_addr_ip6) /
6400 TCP(sport=server_tcp_in_port, dport=client_tcp_out_port))
6401 pkts.append(p)
6402 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6403 IPv6(src=server.ip6, dst=nat_addr_ip6) /
6404 UDP(sport=server_udp_in_port, dport=client_udp_out_port))
6405 pkts.append(p)
6406 self.pg0.add_stream(pkts)
6407 self.pg_enable_capture(self.pg_interfaces)
6408 self.pg_start()
6409 capture = self.pg0.get_capture(len(pkts))
6410 for packet in capture:
6411 try:
6412 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
6413 self.assertEqual(packet[IPv6].dst, client.ip6)
Klement Sekerad81ae412018-05-16 10:52:54 +02006414 self.assert_packet_checksums_valid(packet)
Matus Fabian029f3d22017-06-15 02:28:50 -07006415 if packet.haslayer(TCP):
6416 self.assertEqual(packet[TCP].sport, server_tcp_out_port)
6417 self.assertEqual(packet[TCP].dport, client_tcp_in_port)
Matus Fabian029f3d22017-06-15 02:28:50 -07006418 else:
6419 self.assertEqual(packet[UDP].sport, server_udp_out_port)
6420 self.assertEqual(packet[UDP].dport, client_udp_in_port)
Matus Fabian029f3d22017-06-15 02:28:50 -07006421 except:
6422 self.logger.error(ppp("Unexpected or invalid packet:", packet))
6423 raise
6424
6425 # ICMP error
6426 pkts = []
6427 pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6428 IPv6(src=client.ip6, dst=nat_addr_ip6) /
6429 ICMPv6DestUnreach(code=1) /
6430 packet[IPv6] for packet in capture]
6431 self.pg0.add_stream(pkts)
6432 self.pg_enable_capture(self.pg_interfaces)
6433 self.pg_start()
6434 capture = self.pg0.get_capture(len(pkts))
6435 for packet in capture:
6436 try:
6437 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
6438 self.assertEqual(packet[IPv6].dst, server.ip6)
6439 icmp = packet[ICMPv6DestUnreach]
6440 self.assertEqual(icmp.code, 1)
6441 inner = icmp[IPerror6]
6442 self.assertEqual(inner.src, server.ip6)
6443 self.assertEqual(inner.dst, nat_addr_ip6)
Klement Sekerad81ae412018-05-16 10:52:54 +02006444 self.assert_packet_checksums_valid(packet)
Matus Fabian029f3d22017-06-15 02:28:50 -07006445 if inner.haslayer(TCPerror):
6446 self.assertEqual(inner[TCPerror].sport, server_tcp_in_port)
6447 self.assertEqual(inner[TCPerror].dport,
6448 client_tcp_out_port)
6449 else:
6450 self.assertEqual(inner[UDPerror].sport, server_udp_in_port)
6451 self.assertEqual(inner[UDPerror].dport,
6452 client_udp_out_port)
6453 except:
6454 self.logger.error(ppp("Unexpected or invalid packet:", packet))
6455 raise
6456
Matus Fabian428dc912017-06-21 06:15:18 -07006457 def test_prefix(self):
6458 """ NAT64 Network-Specific Prefix """
6459
6460 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6461 self.nat_addr_n)
6462 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6463 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6464 self.vapi.nat64_add_del_pool_addr_range(self.vrf1_nat_addr_n,
6465 self.vrf1_nat_addr_n,
6466 vrf_id=self.vrf1_id)
6467 self.vapi.nat64_add_del_interface(self.pg2.sw_if_index)
6468
6469 # Add global prefix
6470 global_pref64 = "2001:db8::"
6471 global_pref64_n = socket.inet_pton(socket.AF_INET6, global_pref64)
6472 global_pref64_len = 32
6473 self.vapi.nat64_add_del_prefix(global_pref64_n, global_pref64_len)
6474
6475 prefix = self.vapi.nat64_prefix_dump()
6476 self.assertEqual(len(prefix), 1)
6477 self.assertEqual(prefix[0].prefix, global_pref64_n)
6478 self.assertEqual(prefix[0].prefix_len, global_pref64_len)
6479 self.assertEqual(prefix[0].vrf_id, 0)
6480
6481 # Add tenant specific prefix
6482 vrf1_pref64 = "2001:db8:122:300::"
6483 vrf1_pref64_n = socket.inet_pton(socket.AF_INET6, vrf1_pref64)
6484 vrf1_pref64_len = 56
6485 self.vapi.nat64_add_del_prefix(vrf1_pref64_n,
6486 vrf1_pref64_len,
6487 vrf_id=self.vrf1_id)
6488 prefix = self.vapi.nat64_prefix_dump()
6489 self.assertEqual(len(prefix), 2)
6490
6491 # Global prefix
6492 pkts = self.create_stream_in_ip6(self.pg0,
6493 self.pg1,
6494 pref=global_pref64,
6495 plen=global_pref64_len)
6496 self.pg0.add_stream(pkts)
6497 self.pg_enable_capture(self.pg_interfaces)
6498 self.pg_start()
6499 capture = self.pg1.get_capture(len(pkts))
6500 self.verify_capture_out(capture, nat_ip=self.nat_addr,
6501 dst_ip=self.pg1.remote_ip4)
6502
6503 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
6504 self.pg1.add_stream(pkts)
6505 self.pg_enable_capture(self.pg_interfaces)
6506 self.pg_start()
6507 capture = self.pg0.get_capture(len(pkts))
6508 dst_ip = self.compose_ip6(self.pg1.remote_ip4,
6509 global_pref64,
6510 global_pref64_len)
6511 self.verify_capture_in_ip6(capture, dst_ip, self.pg0.remote_ip6)
6512
6513 # Tenant specific prefix
6514 pkts = self.create_stream_in_ip6(self.pg2,
6515 self.pg1,
6516 pref=vrf1_pref64,
6517 plen=vrf1_pref64_len)
6518 self.pg2.add_stream(pkts)
6519 self.pg_enable_capture(self.pg_interfaces)
6520 self.pg_start()
6521 capture = self.pg1.get_capture(len(pkts))
6522 self.verify_capture_out(capture, nat_ip=self.vrf1_nat_addr,
6523 dst_ip=self.pg1.remote_ip4)
6524
6525 pkts = self.create_stream_out(self.pg1, dst_ip=self.vrf1_nat_addr)
6526 self.pg1.add_stream(pkts)
6527 self.pg_enable_capture(self.pg_interfaces)
6528 self.pg_start()
6529 capture = self.pg2.get_capture(len(pkts))
6530 dst_ip = self.compose_ip6(self.pg1.remote_ip4,
6531 vrf1_pref64,
6532 vrf1_pref64_len)
6533 self.verify_capture_in_ip6(capture, dst_ip, self.pg2.remote_ip6)
6534
Matus Fabianf8cd5812017-07-11 03:55:02 -07006535 def test_unknown_proto(self):
Matus Fabian7968e6c2017-07-06 05:37:49 -07006536 """ NAT64 translate packet with unknown protocol """
6537
6538 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6539 self.nat_addr_n)
6540 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6541 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6542 remote_ip6 = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
6543
6544 # in2out
6545 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6546 IPv6(src=self.pg0.remote_ip6, dst=remote_ip6) /
6547 TCP(sport=self.tcp_port_in, dport=20))
6548 self.pg0.add_stream(p)
6549 self.pg_enable_capture(self.pg_interfaces)
6550 self.pg_start()
6551 p = self.pg1.get_capture(1)
6552
6553 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabianf8cd5812017-07-11 03:55:02 -07006554 IPv6(src=self.pg0.remote_ip6, dst=remote_ip6, nh=47) /
Matus Fabian7968e6c2017-07-06 05:37:49 -07006555 GRE() /
6556 IP(src=self.pg2.local_ip4, dst=self.pg2.remote_ip4) /
6557 TCP(sport=1234, dport=1234))
6558 self.pg0.add_stream(p)
6559 self.pg_enable_capture(self.pg_interfaces)
6560 self.pg_start()
6561 p = self.pg1.get_capture(1)
6562 packet = p[0]
6563 try:
6564 self.assertEqual(packet[IP].src, self.nat_addr)
6565 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
6566 self.assertTrue(packet.haslayer(GRE))
Klement Sekerad81ae412018-05-16 10:52:54 +02006567 self.assert_packet_checksums_valid(packet)
Matus Fabian7968e6c2017-07-06 05:37:49 -07006568 except:
6569 self.logger.error(ppp("Unexpected or invalid packet:", packet))
6570 raise
6571
6572 # out2in
6573 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
6574 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6575 GRE() /
6576 IP(src=self.pg2.remote_ip4, dst=self.pg2.local_ip4) /
6577 TCP(sport=1234, dport=1234))
6578 self.pg1.add_stream(p)
6579 self.pg_enable_capture(self.pg_interfaces)
6580 self.pg_start()
6581 p = self.pg0.get_capture(1)
6582 packet = p[0]
6583 try:
6584 self.assertEqual(packet[IPv6].src, remote_ip6)
Matus Fabianf8cd5812017-07-11 03:55:02 -07006585 self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
6586 self.assertEqual(packet[IPv6].nh, 47)
Matus Fabian7968e6c2017-07-06 05:37:49 -07006587 except:
6588 self.logger.error(ppp("Unexpected or invalid packet:", packet))
6589 raise
6590
Matus Fabianf8cd5812017-07-11 03:55:02 -07006591 def test_hairpinning_unknown_proto(self):
Matus Fabian7968e6c2017-07-06 05:37:49 -07006592 """ NAT64 translate packet with unknown protocol - hairpinning """
6593
6594 client = self.pg0.remote_hosts[0]
6595 server = self.pg0.remote_hosts[1]
6596 server_tcp_in_port = 22
6597 server_tcp_out_port = 4022
6598 client_tcp_in_port = 1234
Matus Fabianf8cd5812017-07-11 03:55:02 -07006599 client_tcp_out_port = 1235
6600 server_nat_ip = "10.0.0.100"
6601 client_nat_ip = "10.0.0.110"
6602 server_nat_ip_n = socket.inet_pton(socket.AF_INET, server_nat_ip)
6603 client_nat_ip_n = socket.inet_pton(socket.AF_INET, client_nat_ip)
6604 server_nat_ip6 = self.compose_ip6(server_nat_ip, '64:ff9b::', 96)
6605 client_nat_ip6 = self.compose_ip6(client_nat_ip, '64:ff9b::', 96)
Matus Fabian7968e6c2017-07-06 05:37:49 -07006606
Matus Fabianf8cd5812017-07-11 03:55:02 -07006607 self.vapi.nat64_add_del_pool_addr_range(server_nat_ip_n,
6608 client_nat_ip_n)
Matus Fabian7968e6c2017-07-06 05:37:49 -07006609 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6610 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6611
6612 self.vapi.nat64_add_del_static_bib(server.ip6n,
Matus Fabianf8cd5812017-07-11 03:55:02 -07006613 server_nat_ip_n,
Matus Fabian7968e6c2017-07-06 05:37:49 -07006614 server_tcp_in_port,
6615 server_tcp_out_port,
6616 IP_PROTOS.tcp)
6617
Matus Fabianf8cd5812017-07-11 03:55:02 -07006618 self.vapi.nat64_add_del_static_bib(server.ip6n,
6619 server_nat_ip_n,
6620 0,
6621 0,
6622 IP_PROTOS.gre)
6623
6624 self.vapi.nat64_add_del_static_bib(client.ip6n,
6625 client_nat_ip_n,
6626 client_tcp_in_port,
6627 client_tcp_out_port,
6628 IP_PROTOS.tcp)
6629
Matus Fabian7968e6c2017-07-06 05:37:49 -07006630 # client to server
6631 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabianf8cd5812017-07-11 03:55:02 -07006632 IPv6(src=client.ip6, dst=server_nat_ip6) /
Matus Fabian7968e6c2017-07-06 05:37:49 -07006633 TCP(sport=client_tcp_in_port, dport=server_tcp_out_port))
6634 self.pg0.add_stream(p)
6635 self.pg_enable_capture(self.pg_interfaces)
6636 self.pg_start()
6637 p = self.pg0.get_capture(1)
6638
6639 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabianf8cd5812017-07-11 03:55:02 -07006640 IPv6(src=client.ip6, dst=server_nat_ip6, nh=IP_PROTOS.gre) /
Matus Fabian7968e6c2017-07-06 05:37:49 -07006641 GRE() /
6642 IP(src=self.pg2.local_ip4, dst=self.pg2.remote_ip4) /
6643 TCP(sport=1234, dport=1234))
6644 self.pg0.add_stream(p)
6645 self.pg_enable_capture(self.pg_interfaces)
6646 self.pg_start()
6647 p = self.pg0.get_capture(1)
6648 packet = p[0]
6649 try:
Matus Fabianf8cd5812017-07-11 03:55:02 -07006650 self.assertEqual(packet[IPv6].src, client_nat_ip6)
Matus Fabian7968e6c2017-07-06 05:37:49 -07006651 self.assertEqual(packet[IPv6].dst, server.ip6)
Matus Fabianf8cd5812017-07-11 03:55:02 -07006652 self.assertEqual(packet[IPv6].nh, IP_PROTOS.gre)
Matus Fabian7968e6c2017-07-06 05:37:49 -07006653 except:
6654 self.logger.error(ppp("Unexpected or invalid packet:", packet))
6655 raise
6656
6657 # server to client
6658 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabianf8cd5812017-07-11 03:55:02 -07006659 IPv6(src=server.ip6, dst=client_nat_ip6, nh=IP_PROTOS.gre) /
Matus Fabian7968e6c2017-07-06 05:37:49 -07006660 GRE() /
6661 IP(src=self.pg2.remote_ip4, dst=self.pg2.local_ip4) /
6662 TCP(sport=1234, dport=1234))
6663 self.pg0.add_stream(p)
6664 self.pg_enable_capture(self.pg_interfaces)
6665 self.pg_start()
6666 p = self.pg0.get_capture(1)
6667 packet = p[0]
6668 try:
Matus Fabianf8cd5812017-07-11 03:55:02 -07006669 self.assertEqual(packet[IPv6].src, server_nat_ip6)
Matus Fabian7968e6c2017-07-06 05:37:49 -07006670 self.assertEqual(packet[IPv6].dst, client.ip6)
Matus Fabianf8cd5812017-07-11 03:55:02 -07006671 self.assertEqual(packet[IPv6].nh, IP_PROTOS.gre)
Matus Fabian7968e6c2017-07-06 05:37:49 -07006672 except:
6673 self.logger.error(ppp("Unexpected or invalid packet:", packet))
6674 raise
6675
Matus Fabian36ea2d62017-10-24 04:13:49 -07006676 def test_one_armed_nat64(self):
6677 """ One armed NAT64 """
6678 external_port = 0
6679 remote_host_ip6 = self.compose_ip6(self.pg3.remote_ip4,
6680 '64:ff9b::',
6681 96)
6682
6683 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6684 self.nat_addr_n)
6685 self.vapi.nat64_add_del_interface(self.pg3.sw_if_index)
6686 self.vapi.nat64_add_del_interface(self.pg3.sw_if_index, is_inside=0)
6687
6688 # in2out
6689 p = (Ether(src=self.pg3.remote_mac, dst=self.pg3.local_mac) /
6690 IPv6(src=self.pg3.remote_ip6, dst=remote_host_ip6) /
6691 TCP(sport=12345, dport=80))
6692 self.pg3.add_stream(p)
6693 self.pg_enable_capture(self.pg_interfaces)
6694 self.pg_start()
6695 capture = self.pg3.get_capture(1)
6696 p = capture[0]
6697 try:
6698 ip = p[IP]
6699 tcp = p[TCP]
6700 self.assertEqual(ip.src, self.nat_addr)
6701 self.assertEqual(ip.dst, self.pg3.remote_ip4)
6702 self.assertNotEqual(tcp.sport, 12345)
6703 external_port = tcp.sport
6704 self.assertEqual(tcp.dport, 80)
Klement Sekerad81ae412018-05-16 10:52:54 +02006705 self.assert_packet_checksums_valid(p)
Matus Fabian36ea2d62017-10-24 04:13:49 -07006706 except:
6707 self.logger.error(ppp("Unexpected or invalid packet:", p))
6708 raise
6709
6710 # out2in
6711 p = (Ether(src=self.pg3.remote_mac, dst=self.pg3.local_mac) /
6712 IP(src=self.pg3.remote_ip4, dst=self.nat_addr) /
6713 TCP(sport=80, dport=external_port))
6714 self.pg3.add_stream(p)
6715 self.pg_enable_capture(self.pg_interfaces)
6716 self.pg_start()
6717 capture = self.pg3.get_capture(1)
6718 p = capture[0]
6719 try:
6720 ip = p[IPv6]
6721 tcp = p[TCP]
6722 self.assertEqual(ip.src, remote_host_ip6)
6723 self.assertEqual(ip.dst, self.pg3.remote_ip6)
6724 self.assertEqual(tcp.sport, 80)
6725 self.assertEqual(tcp.dport, 12345)
Klement Sekerad81ae412018-05-16 10:52:54 +02006726 self.assert_packet_checksums_valid(p)
Matus Fabian36ea2d62017-10-24 04:13:49 -07006727 except:
6728 self.logger.error(ppp("Unexpected or invalid packet:", p))
6729 raise
6730
Matus Fabianefcd1e92017-08-15 06:59:19 -07006731 def test_frag_in_order(self):
6732 """ NAT64 translate fragments arriving in order """
6733 self.tcp_port_in = random.randint(1025, 65535)
6734
6735 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6736 self.nat_addr_n)
6737 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6738 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6739
6740 reass = self.vapi.nat_reass_dump()
6741 reass_n_start = len(reass)
6742
6743 # in2out
6744 data = 'a' * 200
6745 pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
6746 self.tcp_port_in, 20, data)
6747 self.pg0.add_stream(pkts)
6748 self.pg_enable_capture(self.pg_interfaces)
6749 self.pg_start()
6750 frags = self.pg1.get_capture(len(pkts))
6751 p = self.reass_frags_and_verify(frags,
6752 self.nat_addr,
6753 self.pg1.remote_ip4)
6754 self.assertEqual(p[TCP].dport, 20)
6755 self.assertNotEqual(p[TCP].sport, self.tcp_port_in)
6756 self.tcp_port_out = p[TCP].sport
6757 self.assertEqual(data, p[Raw].load)
6758
6759 # out2in
6760 data = "A" * 4 + "b" * 16 + "C" * 3
6761 pkts = self.create_stream_frag(self.pg1,
6762 self.nat_addr,
6763 20,
6764 self.tcp_port_out,
6765 data)
6766 self.pg1.add_stream(pkts)
6767 self.pg_enable_capture(self.pg_interfaces)
6768 self.pg_start()
6769 frags = self.pg0.get_capture(len(pkts))
6770 src = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
6771 p = self.reass_frags_and_verify_ip6(frags, src, self.pg0.remote_ip6)
6772 self.assertEqual(p[TCP].sport, 20)
6773 self.assertEqual(p[TCP].dport, self.tcp_port_in)
6774 self.assertEqual(data, p[Raw].load)
6775
6776 reass = self.vapi.nat_reass_dump()
6777 reass_n_end = len(reass)
6778
6779 self.assertEqual(reass_n_end - reass_n_start, 2)
6780
6781 def test_reass_hairpinning(self):
6782 """ NAT64 fragments hairpinning """
6783 data = 'a' * 200
Matus Fabianefcd1e92017-08-15 06:59:19 -07006784 server = self.pg0.remote_hosts[1]
6785 server_in_port = random.randint(1025, 65535)
6786 server_out_port = random.randint(1025, 65535)
6787 client_in_port = random.randint(1025, 65535)
6788 ip = IPv6(src=''.join(['64:ff9b::', self.nat_addr]))
6789 nat_addr_ip6 = ip.src
6790
6791 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6792 self.nat_addr_n)
6793 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6794 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6795
6796 # add static BIB entry for server
6797 self.vapi.nat64_add_del_static_bib(server.ip6n,
6798 self.nat_addr_n,
6799 server_in_port,
6800 server_out_port,
6801 IP_PROTOS.tcp)
6802
6803 # send packet from host to server
6804 pkts = self.create_stream_frag_ip6(self.pg0,
6805 self.nat_addr,
6806 client_in_port,
6807 server_out_port,
6808 data)
6809 self.pg0.add_stream(pkts)
6810 self.pg_enable_capture(self.pg_interfaces)
6811 self.pg_start()
6812 frags = self.pg0.get_capture(len(pkts))
6813 p = self.reass_frags_and_verify_ip6(frags, nat_addr_ip6, server.ip6)
6814 self.assertNotEqual(p[TCP].sport, client_in_port)
6815 self.assertEqual(p[TCP].dport, server_in_port)
6816 self.assertEqual(data, p[Raw].load)
6817
6818 def test_frag_out_of_order(self):
6819 """ NAT64 translate fragments arriving out of order """
6820 self.tcp_port_in = random.randint(1025, 65535)
6821
6822 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6823 self.nat_addr_n)
6824 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6825 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6826
6827 # in2out
6828 data = 'a' * 200
6829 pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
6830 self.tcp_port_in, 20, data)
6831 pkts.reverse()
6832 self.pg0.add_stream(pkts)
6833 self.pg_enable_capture(self.pg_interfaces)
6834 self.pg_start()
6835 frags = self.pg1.get_capture(len(pkts))
6836 p = self.reass_frags_and_verify(frags,
6837 self.nat_addr,
6838 self.pg1.remote_ip4)
6839 self.assertEqual(p[TCP].dport, 20)
6840 self.assertNotEqual(p[TCP].sport, self.tcp_port_in)
6841 self.tcp_port_out = p[TCP].sport
6842 self.assertEqual(data, p[Raw].load)
6843
6844 # out2in
6845 data = "A" * 4 + "B" * 16 + "C" * 3
6846 pkts = self.create_stream_frag(self.pg1,
6847 self.nat_addr,
6848 20,
6849 self.tcp_port_out,
6850 data)
6851 pkts.reverse()
6852 self.pg1.add_stream(pkts)
6853 self.pg_enable_capture(self.pg_interfaces)
6854 self.pg_start()
6855 frags = self.pg0.get_capture(len(pkts))
6856 src = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
6857 p = self.reass_frags_and_verify_ip6(frags, src, self.pg0.remote_ip6)
6858 self.assertEqual(p[TCP].sport, 20)
6859 self.assertEqual(p[TCP].dport, self.tcp_port_in)
6860 self.assertEqual(data, p[Raw].load)
6861
Matus Fabian0938dcf2017-11-08 01:59:38 -08006862 def test_interface_addr(self):
6863 """ Acquire NAT64 pool addresses from interface """
6864 self.vapi.nat64_add_interface_addr(self.pg4.sw_if_index)
6865
6866 # no address in NAT64 pool
6867 adresses = self.vapi.nat44_address_dump()
6868 self.assertEqual(0, len(adresses))
6869
6870 # configure interface address and check NAT64 address pool
6871 self.pg4.config_ip4()
6872 addresses = self.vapi.nat64_pool_addr_dump()
6873 self.assertEqual(len(addresses), 1)
6874 self.assertEqual(addresses[0].address, self.pg4.local_ip4n)
6875
6876 # remove interface address and check NAT64 address pool
6877 self.pg4.unconfig_ip4()
6878 addresses = self.vapi.nat64_pool_addr_dump()
6879 self.assertEqual(0, len(adresses))
6880
Matus Fabiana431ad12018-01-04 04:03:14 -08006881 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
6882 def test_ipfix_max_bibs_sessions(self):
6883 """ IPFIX logging maximum session and BIB entries exceeded """
6884 max_bibs = 1280
6885 max_sessions = 2560
6886 remote_host_ip6 = self.compose_ip6(self.pg1.remote_ip4,
6887 '64:ff9b::',
6888 96)
6889
6890 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6891 self.nat_addr_n)
6892 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6893 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6894
6895 pkts = []
6896 src = ""
6897 for i in range(0, max_bibs):
6898 src = "fd01:aa::%x" % (i)
6899 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6900 IPv6(src=src, dst=remote_host_ip6) /
6901 TCP(sport=12345, dport=80))
6902 pkts.append(p)
6903 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6904 IPv6(src=src, dst=remote_host_ip6) /
6905 TCP(sport=12345, dport=22))
6906 pkts.append(p)
6907 self.pg0.add_stream(pkts)
6908 self.pg_enable_capture(self.pg_interfaces)
6909 self.pg_start()
6910 self.pg1.get_capture(max_sessions)
6911
6912 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
6913 src_address=self.pg3.local_ip4n,
6914 path_mtu=512,
6915 template_interval=10)
6916 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
6917 src_port=self.ipfix_src_port)
6918
6919 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6920 IPv6(src=src, dst=remote_host_ip6) /
6921 TCP(sport=12345, dport=25))
6922 self.pg0.add_stream(p)
6923 self.pg_enable_capture(self.pg_interfaces)
6924 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07006925 self.pg1.assert_nothing_captured()
6926 sleep(1)
Matus Fabiana431ad12018-01-04 04:03:14 -08006927 self.vapi.cli("ipfix flush") # FIXME this should be an API call
6928 capture = self.pg3.get_capture(9)
6929 ipfix = IPFIXDecoder()
6930 # first load template
6931 for p in capture:
6932 self.assertTrue(p.haslayer(IPFIX))
6933 self.assertEqual(p[IP].src, self.pg3.local_ip4)
6934 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
6935 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
6936 self.assertEqual(p[UDP].dport, 4739)
6937 self.assertEqual(p[IPFIX].observationDomainID,
6938 self.ipfix_domain_id)
6939 if p.haslayer(Template):
6940 ipfix.add_template(p.getlayer(Template))
6941 # verify events in data set
6942 for p in capture:
6943 if p.haslayer(Data):
6944 data = ipfix.decode_data_set(p.getlayer(Set))
6945 self.verify_ipfix_max_sessions(data, max_sessions)
6946
6947 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6948 IPv6(src=self.pg0.remote_ip6, dst=remote_host_ip6) /
6949 TCP(sport=12345, dport=80))
6950 self.pg0.add_stream(p)
6951 self.pg_enable_capture(self.pg_interfaces)
6952 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07006953 self.pg1.assert_nothing_captured()
6954 sleep(1)
Matus Fabiana431ad12018-01-04 04:03:14 -08006955 self.vapi.cli("ipfix flush") # FIXME this should be an API call
6956 capture = self.pg3.get_capture(1)
6957 # verify events in data set
6958 for p in capture:
6959 self.assertTrue(p.haslayer(IPFIX))
6960 self.assertEqual(p[IP].src, self.pg3.local_ip4)
6961 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
6962 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
6963 self.assertEqual(p[UDP].dport, 4739)
6964 self.assertEqual(p[IPFIX].observationDomainID,
6965 self.ipfix_domain_id)
6966 if p.haslayer(Data):
6967 data = ipfix.decode_data_set(p.getlayer(Set))
6968 self.verify_ipfix_max_bibs(data, max_bibs)
6969
6970 def test_ipfix_max_frags(self):
6971 """ IPFIX logging maximum fragments pending reassembly exceeded """
6972 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6973 self.nat_addr_n)
6974 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6975 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
Matus Fabiana7f8b222018-09-05 06:01:55 -07006976 self.vapi.nat_set_reass(max_frag=1, is_ip6=1)
Matus Fabiana431ad12018-01-04 04:03:14 -08006977 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
6978 src_address=self.pg3.local_ip4n,
6979 path_mtu=512,
6980 template_interval=10)
6981 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
6982 src_port=self.ipfix_src_port)
6983
6984 data = 'a' * 200
6985 pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
6986 self.tcp_port_in, 20, data)
Matus Fabiana7f8b222018-09-05 06:01:55 -07006987 pkts.reverse()
6988 self.pg0.add_stream(pkts)
Matus Fabiana431ad12018-01-04 04:03:14 -08006989 self.pg_enable_capture(self.pg_interfaces)
6990 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07006991 self.pg1.assert_nothing_captured()
6992 sleep(1)
Matus Fabiana431ad12018-01-04 04:03:14 -08006993 self.vapi.cli("ipfix flush") # FIXME this should be an API call
6994 capture = self.pg3.get_capture(9)
6995 ipfix = IPFIXDecoder()
6996 # first load template
6997 for p in capture:
6998 self.assertTrue(p.haslayer(IPFIX))
6999 self.assertEqual(p[IP].src, self.pg3.local_ip4)
7000 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
7001 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
7002 self.assertEqual(p[UDP].dport, 4739)
7003 self.assertEqual(p[IPFIX].observationDomainID,
7004 self.ipfix_domain_id)
7005 if p.haslayer(Template):
7006 ipfix.add_template(p.getlayer(Template))
7007 # verify events in data set
7008 for p in capture:
7009 if p.haslayer(Data):
7010 data = ipfix.decode_data_set(p.getlayer(Set))
Matus Fabiana7f8b222018-09-05 06:01:55 -07007011 self.verify_ipfix_max_fragments_ip6(data, 1,
Matus Fabiana431ad12018-01-04 04:03:14 -08007012 self.pg0.remote_ip6n)
7013
7014 def test_ipfix_bib_ses(self):
7015 """ IPFIX logging NAT64 BIB/session create and delete events """
7016 self.tcp_port_in = random.randint(1025, 65535)
7017 remote_host_ip6 = self.compose_ip6(self.pg1.remote_ip4,
7018 '64:ff9b::',
7019 96)
7020
7021 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7022 self.nat_addr_n)
7023 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7024 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7025 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
7026 src_address=self.pg3.local_ip4n,
7027 path_mtu=512,
7028 template_interval=10)
7029 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
7030 src_port=self.ipfix_src_port)
7031
7032 # Create
7033 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7034 IPv6(src=self.pg0.remote_ip6, dst=remote_host_ip6) /
7035 TCP(sport=self.tcp_port_in, dport=25))
7036 self.pg0.add_stream(p)
7037 self.pg_enable_capture(self.pg_interfaces)
7038 self.pg_start()
7039 p = self.pg1.get_capture(1)
7040 self.tcp_port_out = p[0][TCP].sport
7041 self.vapi.cli("ipfix flush") # FIXME this should be an API call
7042 capture = self.pg3.get_capture(10)
7043 ipfix = IPFIXDecoder()
7044 # first load template
7045 for p in capture:
7046 self.assertTrue(p.haslayer(IPFIX))
7047 self.assertEqual(p[IP].src, self.pg3.local_ip4)
7048 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
7049 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
7050 self.assertEqual(p[UDP].dport, 4739)
7051 self.assertEqual(p[IPFIX].observationDomainID,
7052 self.ipfix_domain_id)
7053 if p.haslayer(Template):
7054 ipfix.add_template(p.getlayer(Template))
7055 # verify events in data set
7056 for p in capture:
7057 if p.haslayer(Data):
7058 data = ipfix.decode_data_set(p.getlayer(Set))
7059 if ord(data[0][230]) == 10:
7060 self.verify_ipfix_bib(data, 1, self.pg0.remote_ip6n)
7061 elif ord(data[0][230]) == 6:
7062 self.verify_ipfix_nat64_ses(data,
7063 1,
7064 self.pg0.remote_ip6n,
7065 self.pg1.remote_ip4,
7066 25)
7067 else:
7068 self.logger.error(ppp("Unexpected or invalid packet: ", p))
7069
7070 # Delete
7071 self.pg_enable_capture(self.pg_interfaces)
7072 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7073 self.nat_addr_n,
7074 is_add=0)
7075 self.vapi.cli("ipfix flush") # FIXME this should be an API call
7076 capture = self.pg3.get_capture(2)
7077 # verify events in data set
7078 for p in capture:
7079 self.assertTrue(p.haslayer(IPFIX))
7080 self.assertEqual(p[IP].src, self.pg3.local_ip4)
7081 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
7082 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
7083 self.assertEqual(p[UDP].dport, 4739)
7084 self.assertEqual(p[IPFIX].observationDomainID,
7085 self.ipfix_domain_id)
7086 if p.haslayer(Data):
7087 data = ipfix.decode_data_set(p.getlayer(Set))
7088 if ord(data[0][230]) == 11:
7089 self.verify_ipfix_bib(data, 0, self.pg0.remote_ip6n)
7090 elif ord(data[0][230]) == 7:
7091 self.verify_ipfix_nat64_ses(data,
7092 0,
7093 self.pg0.remote_ip6n,
7094 self.pg1.remote_ip4,
7095 25)
7096 else:
7097 self.logger.error(ppp("Unexpected or invalid packet: ", p))
7098
Matus Fabian06596c52017-06-06 04:53:28 -07007099 def nat64_get_ses_num(self):
7100 """
7101 Return number of active NAT64 sessions.
7102 """
Matus Fabianab9a59c2017-08-16 05:37:36 -07007103 st = self.vapi.nat64_st_dump()
7104 return len(st)
Matus Fabian06596c52017-06-06 04:53:28 -07007105
7106 def clear_nat64(self):
7107 """
7108 Clear NAT64 configuration.
7109 """
Matus Fabiana431ad12018-01-04 04:03:14 -08007110 self.vapi.nat_ipfix(enable=0, src_port=self.ipfix_src_port,
7111 domain_id=self.ipfix_domain_id)
7112 self.ipfix_src_port = 4739
7113 self.ipfix_domain_id = 1
7114
Matus Fabian878c6462018-08-23 00:33:35 -07007115 self.vapi.nat_set_timeouts()
Matus Fabian06596c52017-06-06 04:53:28 -07007116
7117 interfaces = self.vapi.nat64_interface_dump()
7118 for intf in interfaces:
Matus Fabian36ea2d62017-10-24 04:13:49 -07007119 if intf.is_inside > 1:
7120 self.vapi.nat64_add_del_interface(intf.sw_if_index,
7121 0,
7122 is_add=0)
Matus Fabian06596c52017-06-06 04:53:28 -07007123 self.vapi.nat64_add_del_interface(intf.sw_if_index,
7124 intf.is_inside,
7125 is_add=0)
7126
Matus Fabiana431ad12018-01-04 04:03:14 -08007127 bib = self.vapi.nat64_bib_dump(255)
Matus Fabian06596c52017-06-06 04:53:28 -07007128 for bibe in bib:
7129 if bibe.is_static:
7130 self.vapi.nat64_add_del_static_bib(bibe.i_addr,
7131 bibe.o_addr,
7132 bibe.i_port,
7133 bibe.o_port,
7134 bibe.proto,
7135 bibe.vrf_id,
7136 is_add=0)
7137
7138 adresses = self.vapi.nat64_pool_addr_dump()
7139 for addr in adresses:
7140 self.vapi.nat64_add_del_pool_addr_range(addr.address,
7141 addr.address,
Matus Fabian029f3d22017-06-15 02:28:50 -07007142 vrf_id=addr.vrf_id,
Matus Fabian06596c52017-06-06 04:53:28 -07007143 is_add=0)
7144
Matus Fabian428dc912017-06-21 06:15:18 -07007145 prefixes = self.vapi.nat64_prefix_dump()
7146 for prefix in prefixes:
7147 self.vapi.nat64_add_del_prefix(prefix.prefix,
7148 prefix.prefix_len,
7149 vrf_id=prefix.vrf_id,
7150 is_add=0)
7151
Matus Fabian06596c52017-06-06 04:53:28 -07007152 def tearDown(self):
7153 super(TestNAT64, self).tearDown()
7154 if not self.vpp_dead:
7155 self.logger.info(self.vapi.cli("show nat64 pool"))
7156 self.logger.info(self.vapi.cli("show nat64 interfaces"))
Matus Fabian428dc912017-06-21 06:15:18 -07007157 self.logger.info(self.vapi.cli("show nat64 prefix"))
Matus Fabianab9a59c2017-08-16 05:37:36 -07007158 self.logger.info(self.vapi.cli("show nat64 bib all"))
7159 self.logger.info(self.vapi.cli("show nat64 session table all"))
Matus Fabianefcd1e92017-08-15 06:59:19 -07007160 self.logger.info(self.vapi.cli("show nat virtual-reassembly"))
Matus Fabian06596c52017-06-06 04:53:28 -07007161 self.clear_nat64()
7162
Matus Fabian8ebe6252017-11-06 05:04:53 -08007163
7164class TestDSlite(MethodHolder):
7165 """ DS-Lite Test Cases """
7166
7167 @classmethod
7168 def setUpClass(cls):
7169 super(TestDSlite, cls).setUpClass()
7170
7171 try:
7172 cls.nat_addr = '10.0.0.3'
7173 cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
7174
7175 cls.create_pg_interfaces(range(2))
7176 cls.pg0.admin_up()
7177 cls.pg0.config_ip4()
7178 cls.pg0.resolve_arp()
7179 cls.pg1.admin_up()
7180 cls.pg1.config_ip6()
7181 cls.pg1.generate_remote_hosts(2)
7182 cls.pg1.configure_ipv6_neighbors()
7183
7184 except Exception:
7185 super(TestDSlite, cls).tearDownClass()
7186 raise
7187
7188 def test_dslite(self):
7189 """ Test DS-Lite """
Matus Fabian69ce30d2018-08-22 01:27:10 -07007190 nat_config = self.vapi.nat_show_config()
7191 self.assertEqual(0, nat_config.dslite_ce)
7192
Matus Fabian8ebe6252017-11-06 05:04:53 -08007193 self.vapi.dslite_add_del_pool_addr_range(self.nat_addr_n,
7194 self.nat_addr_n)
7195 aftr_ip4 = '192.0.0.1'
7196 aftr_ip4_n = socket.inet_pton(socket.AF_INET, aftr_ip4)
7197 aftr_ip6 = '2001:db8:85a3::8a2e:370:1'
7198 aftr_ip6_n = socket.inet_pton(socket.AF_INET6, aftr_ip6)
7199 self.vapi.dslite_set_aftr_addr(aftr_ip6_n, aftr_ip4_n)
7200
7201 # UDP
7202 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
7203 IPv6(dst=aftr_ip6, src=self.pg1.remote_hosts[0].ip6) /
7204 IP(dst=self.pg0.remote_ip4, src='192.168.1.1') /
7205 UDP(sport=20000, dport=10000))
7206 self.pg1.add_stream(p)
7207 self.pg_enable_capture(self.pg_interfaces)
7208 self.pg_start()
7209 capture = self.pg0.get_capture(1)
7210 capture = capture[0]
7211 self.assertFalse(capture.haslayer(IPv6))
7212 self.assertEqual(capture[IP].src, self.nat_addr)
7213 self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
7214 self.assertNotEqual(capture[UDP].sport, 20000)
7215 self.assertEqual(capture[UDP].dport, 10000)
Klement Sekerad81ae412018-05-16 10:52:54 +02007216 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08007217 out_port = capture[UDP].sport
7218
7219 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7220 IP(dst=self.nat_addr, src=self.pg0.remote_ip4) /
7221 UDP(sport=10000, dport=out_port))
7222 self.pg0.add_stream(p)
7223 self.pg_enable_capture(self.pg_interfaces)
7224 self.pg_start()
7225 capture = self.pg1.get_capture(1)
7226 capture = capture[0]
7227 self.assertEqual(capture[IPv6].src, aftr_ip6)
7228 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[0].ip6)
7229 self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
7230 self.assertEqual(capture[IP].dst, '192.168.1.1')
7231 self.assertEqual(capture[UDP].sport, 10000)
7232 self.assertEqual(capture[UDP].dport, 20000)
Klement Sekerad81ae412018-05-16 10:52:54 +02007233 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08007234
7235 # TCP
7236 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
7237 IPv6(dst=aftr_ip6, src=self.pg1.remote_hosts[1].ip6) /
7238 IP(dst=self.pg0.remote_ip4, src='192.168.1.1') /
7239 TCP(sport=20001, dport=10001))
7240 self.pg1.add_stream(p)
7241 self.pg_enable_capture(self.pg_interfaces)
7242 self.pg_start()
7243 capture = self.pg0.get_capture(1)
7244 capture = capture[0]
7245 self.assertFalse(capture.haslayer(IPv6))
7246 self.assertEqual(capture[IP].src, self.nat_addr)
7247 self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
7248 self.assertNotEqual(capture[TCP].sport, 20001)
7249 self.assertEqual(capture[TCP].dport, 10001)
Klement Sekerad81ae412018-05-16 10:52:54 +02007250 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08007251 out_port = capture[TCP].sport
7252
7253 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7254 IP(dst=self.nat_addr, src=self.pg0.remote_ip4) /
7255 TCP(sport=10001, dport=out_port))
7256 self.pg0.add_stream(p)
7257 self.pg_enable_capture(self.pg_interfaces)
7258 self.pg_start()
7259 capture = self.pg1.get_capture(1)
7260 capture = capture[0]
7261 self.assertEqual(capture[IPv6].src, aftr_ip6)
7262 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[1].ip6)
7263 self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
7264 self.assertEqual(capture[IP].dst, '192.168.1.1')
7265 self.assertEqual(capture[TCP].sport, 10001)
7266 self.assertEqual(capture[TCP].dport, 20001)
Klement Sekerad81ae412018-05-16 10:52:54 +02007267 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08007268
7269 # ICMP
7270 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
7271 IPv6(dst=aftr_ip6, src=self.pg1.remote_hosts[1].ip6) /
7272 IP(dst=self.pg0.remote_ip4, src='192.168.1.1') /
7273 ICMP(id=4000, type='echo-request'))
7274 self.pg1.add_stream(p)
7275 self.pg_enable_capture(self.pg_interfaces)
7276 self.pg_start()
7277 capture = self.pg0.get_capture(1)
7278 capture = capture[0]
7279 self.assertFalse(capture.haslayer(IPv6))
7280 self.assertEqual(capture[IP].src, self.nat_addr)
7281 self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
7282 self.assertNotEqual(capture[ICMP].id, 4000)
Klement Sekerad81ae412018-05-16 10:52:54 +02007283 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08007284 out_id = capture[ICMP].id
7285
7286 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7287 IP(dst=self.nat_addr, src=self.pg0.remote_ip4) /
7288 ICMP(id=out_id, type='echo-reply'))
7289 self.pg0.add_stream(p)
7290 self.pg_enable_capture(self.pg_interfaces)
7291 self.pg_start()
7292 capture = self.pg1.get_capture(1)
7293 capture = capture[0]
7294 self.assertEqual(capture[IPv6].src, aftr_ip6)
7295 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[1].ip6)
7296 self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
7297 self.assertEqual(capture[IP].dst, '192.168.1.1')
7298 self.assertEqual(capture[ICMP].id, 4000)
Klement Sekerad81ae412018-05-16 10:52:54 +02007299 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08007300
Matus Fabian331acc62017-12-08 03:38:51 -08007301 # ping DS-Lite AFTR tunnel endpoint address
7302 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
7303 IPv6(src=self.pg1.remote_hosts[1].ip6, dst=aftr_ip6) /
7304 ICMPv6EchoRequest())
7305 self.pg1.add_stream(p)
7306 self.pg_enable_capture(self.pg_interfaces)
7307 self.pg_start()
7308 capture = self.pg1.get_capture(1)
Matus Fabian331acc62017-12-08 03:38:51 -08007309 capture = capture[0]
7310 self.assertEqual(capture[IPv6].src, aftr_ip6)
7311 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[1].ip6)
7312 self.assertTrue(capture.haslayer(ICMPv6EchoReply))
7313
Matus Fabian8ebe6252017-11-06 05:04:53 -08007314 def tearDown(self):
7315 super(TestDSlite, self).tearDown()
7316 if not self.vpp_dead:
7317 self.logger.info(self.vapi.cli("show dslite pool"))
7318 self.logger.info(
7319 self.vapi.cli("show dslite aftr-tunnel-endpoint-address"))
7320 self.logger.info(self.vapi.cli("show dslite sessions"))
7321
Juraj Slobodac5c6a332018-01-09 16:08:32 +01007322
7323class TestDSliteCE(MethodHolder):
7324 """ DS-Lite CE Test Cases """
7325
7326 @classmethod
7327 def setUpConstants(cls):
7328 super(TestDSliteCE, cls).setUpConstants()
7329 cls.vpp_cmdline.extend(["nat", "{", "dslite ce", "}"])
7330
7331 @classmethod
7332 def setUpClass(cls):
7333 super(TestDSliteCE, cls).setUpClass()
7334
7335 try:
7336 cls.create_pg_interfaces(range(2))
7337 cls.pg0.admin_up()
7338 cls.pg0.config_ip4()
7339 cls.pg0.resolve_arp()
7340 cls.pg1.admin_up()
7341 cls.pg1.config_ip6()
7342 cls.pg1.generate_remote_hosts(1)
7343 cls.pg1.configure_ipv6_neighbors()
7344
7345 except Exception:
7346 super(TestDSliteCE, cls).tearDownClass()
7347 raise
7348
7349 def test_dslite_ce(self):
7350 """ Test DS-Lite CE """
7351
Matus Fabian69ce30d2018-08-22 01:27:10 -07007352 nat_config = self.vapi.nat_show_config()
7353 self.assertEqual(1, nat_config.dslite_ce)
7354
Juraj Slobodac5c6a332018-01-09 16:08:32 +01007355 b4_ip4 = '192.0.0.2'
7356 b4_ip4_n = socket.inet_pton(socket.AF_INET, b4_ip4)
7357 b4_ip6 = '2001:db8:62aa::375e:f4c1:1'
7358 b4_ip6_n = socket.inet_pton(socket.AF_INET6, b4_ip6)
7359 self.vapi.dslite_set_b4_addr(b4_ip6_n, b4_ip4_n)
7360
7361 aftr_ip4 = '192.0.0.1'
7362 aftr_ip4_n = socket.inet_pton(socket.AF_INET, aftr_ip4)
7363 aftr_ip6 = '2001:db8:85a3::8a2e:370:1'
7364 aftr_ip6_n = socket.inet_pton(socket.AF_INET6, aftr_ip6)
7365 self.vapi.dslite_set_aftr_addr(aftr_ip6_n, aftr_ip4_n)
7366
7367 self.vapi.ip_add_del_route(dst_address=aftr_ip6_n,
7368 dst_address_length=128,
7369 next_hop_address=self.pg1.remote_ip6n,
7370 next_hop_sw_if_index=self.pg1.sw_if_index,
7371 is_ipv6=1)
7372
7373 # UDP encapsulation
7374 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7375 IP(dst=self.pg1.remote_ip4, src=self.pg0.remote_ip4) /
7376 UDP(sport=10000, dport=20000))
7377 self.pg0.add_stream(p)
7378 self.pg_enable_capture(self.pg_interfaces)
7379 self.pg_start()
7380 capture = self.pg1.get_capture(1)
7381 capture = capture[0]
7382 self.assertEqual(capture[IPv6].src, b4_ip6)
7383 self.assertEqual(capture[IPv6].dst, aftr_ip6)
7384 self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
7385 self.assertEqual(capture[IP].dst, self.pg1.remote_ip4)
7386 self.assertEqual(capture[UDP].sport, 10000)
7387 self.assertEqual(capture[UDP].dport, 20000)
Klement Sekerad81ae412018-05-16 10:52:54 +02007388 self.assert_packet_checksums_valid(capture)
Juraj Slobodac5c6a332018-01-09 16:08:32 +01007389
7390 # UDP decapsulation
7391 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
7392 IPv6(dst=b4_ip6, src=aftr_ip6) /
7393 IP(dst=self.pg0.remote_ip4, src=self.pg1.remote_ip4) /
7394 UDP(sport=20000, dport=10000))
7395 self.pg1.add_stream(p)
7396 self.pg_enable_capture(self.pg_interfaces)
7397 self.pg_start()
7398 capture = self.pg0.get_capture(1)
7399 capture = capture[0]
7400 self.assertFalse(capture.haslayer(IPv6))
7401 self.assertEqual(capture[IP].src, self.pg1.remote_ip4)
7402 self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
7403 self.assertEqual(capture[UDP].sport, 20000)
7404 self.assertEqual(capture[UDP].dport, 10000)
Klement Sekerad81ae412018-05-16 10:52:54 +02007405 self.assert_packet_checksums_valid(capture)
Juraj Slobodac5c6a332018-01-09 16:08:32 +01007406
7407 # ping DS-Lite B4 tunnel endpoint address
7408 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
7409 IPv6(src=self.pg1.remote_hosts[0].ip6, dst=b4_ip6) /
7410 ICMPv6EchoRequest())
7411 self.pg1.add_stream(p)
7412 self.pg_enable_capture(self.pg_interfaces)
7413 self.pg_start()
7414 capture = self.pg1.get_capture(1)
Juraj Slobodac5c6a332018-01-09 16:08:32 +01007415 capture = capture[0]
7416 self.assertEqual(capture[IPv6].src, b4_ip6)
7417 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[0].ip6)
7418 self.assertTrue(capture.haslayer(ICMPv6EchoReply))
7419
7420 def tearDown(self):
7421 super(TestDSliteCE, self).tearDown()
7422 if not self.vpp_dead:
7423 self.logger.info(
7424 self.vapi.cli("show dslite aftr-tunnel-endpoint-address"))
7425 self.logger.info(
7426 self.vapi.cli("show dslite b4-tunnel-endpoint-address"))
7427
Matus Fabianf2a23cc2018-01-22 03:41:53 -08007428
7429class TestNAT66(MethodHolder):
7430 """ NAT66 Test Cases """
7431
7432 @classmethod
7433 def setUpClass(cls):
7434 super(TestNAT66, cls).setUpClass()
7435
7436 try:
7437 cls.nat_addr = 'fd01:ff::2'
7438 cls.nat_addr_n = socket.inet_pton(socket.AF_INET6, cls.nat_addr)
7439
7440 cls.create_pg_interfaces(range(2))
7441 cls.interfaces = list(cls.pg_interfaces)
7442
7443 for i in cls.interfaces:
7444 i.admin_up()
7445 i.config_ip6()
7446 i.configure_ipv6_neighbors()
7447
7448 except Exception:
7449 super(TestNAT66, cls).tearDownClass()
7450 raise
7451
7452 def test_static(self):
7453 """ 1:1 NAT66 test """
7454 self.vapi.nat66_add_del_interface(self.pg0.sw_if_index)
7455 self.vapi.nat66_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7456 self.vapi.nat66_add_del_static_mapping(self.pg0.remote_ip6n,
7457 self.nat_addr_n)
7458
7459 # in2out
7460 pkts = []
7461 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7462 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
7463 TCP())
7464 pkts.append(p)
7465 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7466 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
7467 UDP())
7468 pkts.append(p)
7469 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7470 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
7471 ICMPv6EchoRequest())
7472 pkts.append(p)
7473 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7474 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
7475 GRE() / IP() / TCP())
7476 pkts.append(p)
7477 self.pg0.add_stream(pkts)
7478 self.pg_enable_capture(self.pg_interfaces)
7479 self.pg_start()
7480 capture = self.pg1.get_capture(len(pkts))
7481 for packet in capture:
7482 try:
7483 self.assertEqual(packet[IPv6].src, self.nat_addr)
7484 self.assertEqual(packet[IPv6].dst, self.pg1.remote_ip6)
Klement Sekerad81ae412018-05-16 10:52:54 +02007485 self.assert_packet_checksums_valid(packet)
Matus Fabianf2a23cc2018-01-22 03:41:53 -08007486 except:
7487 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7488 raise
7489
7490 # out2in
7491 pkts = []
7492 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
7493 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
7494 TCP())
7495 pkts.append(p)
7496 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
7497 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
7498 UDP())
7499 pkts.append(p)
7500 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
7501 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
7502 ICMPv6EchoReply())
7503 pkts.append(p)
7504 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
7505 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
7506 GRE() / IP() / TCP())
7507 pkts.append(p)
7508 self.pg1.add_stream(pkts)
7509 self.pg_enable_capture(self.pg_interfaces)
7510 self.pg_start()
7511 capture = self.pg0.get_capture(len(pkts))
7512 for packet in capture:
7513 try:
7514 self.assertEqual(packet[IPv6].src, self.pg1.remote_ip6)
7515 self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
Klement Sekerad81ae412018-05-16 10:52:54 +02007516 self.assert_packet_checksums_valid(packet)
Matus Fabianf2a23cc2018-01-22 03:41:53 -08007517 except:
7518 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7519 raise
7520
7521 sm = self.vapi.nat66_static_mapping_dump()
7522 self.assertEqual(len(sm), 1)
7523 self.assertEqual(sm[0].total_pkts, 8)
7524
Juraj Sloboda9341e342018-04-13 12:00:46 +02007525 def test_check_no_translate(self):
7526 """ NAT66 translate only when egress interface is outside interface """
7527 self.vapi.nat66_add_del_interface(self.pg0.sw_if_index)
7528 self.vapi.nat66_add_del_interface(self.pg1.sw_if_index)
7529 self.vapi.nat66_add_del_static_mapping(self.pg0.remote_ip6n,
7530 self.nat_addr_n)
7531
7532 # in2out
7533 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7534 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
7535 UDP())
7536 self.pg0.add_stream([p])
7537 self.pg_enable_capture(self.pg_interfaces)
7538 self.pg_start()
7539 capture = self.pg1.get_capture(1)
7540 packet = capture[0]
7541 try:
7542 self.assertEqual(packet[IPv6].src, self.pg0.remote_ip6)
7543 self.assertEqual(packet[IPv6].dst, self.pg1.remote_ip6)
7544 except:
7545 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7546 raise
7547
Matus Fabianf2a23cc2018-01-22 03:41:53 -08007548 def clear_nat66(self):
7549 """
7550 Clear NAT66 configuration.
7551 """
7552 interfaces = self.vapi.nat66_interface_dump()
7553 for intf in interfaces:
7554 self.vapi.nat66_add_del_interface(intf.sw_if_index,
7555 intf.is_inside,
7556 is_add=0)
7557
7558 static_mappings = self.vapi.nat66_static_mapping_dump()
7559 for sm in static_mappings:
7560 self.vapi.nat66_add_del_static_mapping(sm.local_ip_address,
7561 sm.external_ip_address,
7562 sm.vrf_id,
7563 is_add=0)
7564
7565 def tearDown(self):
7566 super(TestNAT66, self).tearDown()
7567 if not self.vpp_dead:
7568 self.logger.info(self.vapi.cli("show nat66 interfaces"))
7569 self.logger.info(self.vapi.cli("show nat66 static mappings"))
7570 self.clear_nat66()
7571
Klement Sekerad81ae412018-05-16 10:52:54 +02007572
Matus Fabiande886752016-12-07 03:38:19 -08007573if __name__ == '__main__':
7574 unittest.main(testRunner=VppTestRunner)