blob: 47e779b90260504db5a6a65950a81702fdc56125 [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)
3146 self.vapi.nat_set_reass(max_frag=0)
3147 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)
3161 self.pg0.add_stream(pkts[-1])
3162 self.pg_enable_capture(self.pg_interfaces)
3163 self.pg_start()
3164 self.pg1.assert_nothing_captured()
3165 sleep(1)
3166 self.vapi.cli("ipfix flush") # FIXME this should be an API call
3167 capture = self.pg3.get_capture(9)
3168 ipfix = IPFIXDecoder()
3169 # first load template
3170 for p in capture:
3171 self.assertTrue(p.haslayer(IPFIX))
3172 self.assertEqual(p[IP].src, self.pg3.local_ip4)
3173 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
3174 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
3175 self.assertEqual(p[UDP].dport, 4739)
3176 self.assertEqual(p[IPFIX].observationDomainID,
3177 self.ipfix_domain_id)
3178 if p.haslayer(Template):
3179 ipfix.add_template(p.getlayer(Template))
3180 # verify events in data set
3181 for p in capture:
3182 if p.haslayer(Data):
3183 data = ipfix.decode_data_set(p.getlayer(Set))
3184 self.verify_ipfix_max_fragments_ip4(data, 0,
3185 self.pg0.remote_ip4n)
3186
Matus Fabian8008d7c2018-07-09 01:34:20 -07003187 def test_multiple_outside_vrf(self):
3188 """ Multiple outside VRF """
3189 vrf_id1 = 1
3190 vrf_id2 = 2
3191
3192 self.pg1.unconfig_ip4()
3193 self.pg2.unconfig_ip4()
3194 self.vapi.ip_table_add_del(vrf_id1, is_add=1)
3195 self.vapi.ip_table_add_del(vrf_id2, is_add=1)
3196 self.pg1.set_table_ip4(vrf_id1)
3197 self.pg2.set_table_ip4(vrf_id2)
3198 self.pg1.config_ip4()
3199 self.pg2.config_ip4()
3200 self.pg1.resolve_arp()
3201 self.pg2.resolve_arp()
3202
3203 self.nat44_add_address(self.nat_addr)
3204 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3205 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3206 is_inside=0)
3207 self.vapi.nat44_interface_add_del_feature(self.pg2.sw_if_index,
3208 is_inside=0)
3209
3210 try:
3211 # first VRF
3212 pkts = self.create_stream_in(self.pg0, self.pg1)
3213 self.pg0.add_stream(pkts)
3214 self.pg_enable_capture(self.pg_interfaces)
3215 self.pg_start()
3216 capture = self.pg1.get_capture(len(pkts))
3217 self.verify_capture_out(capture, self.nat_addr)
3218
3219 pkts = self.create_stream_out(self.pg1, self.nat_addr)
3220 self.pg1.add_stream(pkts)
3221 self.pg_enable_capture(self.pg_interfaces)
3222 self.pg_start()
3223 capture = self.pg0.get_capture(len(pkts))
3224 self.verify_capture_in(capture, self.pg0)
3225
3226 self.tcp_port_in = 60303
3227 self.udp_port_in = 60304
3228 self.icmp_id_in = 60305
3229
3230 # second VRF
3231 pkts = self.create_stream_in(self.pg0, self.pg2)
3232 self.pg0.add_stream(pkts)
3233 self.pg_enable_capture(self.pg_interfaces)
3234 self.pg_start()
3235 capture = self.pg2.get_capture(len(pkts))
3236 self.verify_capture_out(capture, self.nat_addr)
3237
3238 pkts = self.create_stream_out(self.pg2, self.nat_addr)
3239 self.pg2.add_stream(pkts)
3240 self.pg_enable_capture(self.pg_interfaces)
3241 self.pg_start()
3242 capture = self.pg0.get_capture(len(pkts))
3243 self.verify_capture_in(capture, self.pg0)
3244
3245 finally:
3246 self.pg1.unconfig_ip4()
3247 self.pg2.unconfig_ip4()
3248 self.pg1.set_table_ip4(0)
3249 self.pg2.set_table_ip4(0)
3250 self.pg1.config_ip4()
3251 self.pg2.config_ip4()
3252 self.pg1.resolve_arp()
3253 self.pg2.resolve_arp()
3254
Matus Fabian878c6462018-08-23 00:33:35 -07003255 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
3256 def test_session_timeout(self):
3257 """ NAT44 session timeouts """
3258 self.nat44_add_address(self.nat_addr)
3259 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3260 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3261 is_inside=0)
3262 self.vapi.nat_set_timeouts(udp=5)
3263
3264 max_sessions = 1000
3265 pkts = []
3266 for i in range(0, max_sessions):
3267 src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
3268 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3269 IP(src=src, dst=self.pg1.remote_ip4) /
3270 UDP(sport=1025, dport=53))
3271 pkts.append(p)
3272 self.pg0.add_stream(pkts)
3273 self.pg_enable_capture(self.pg_interfaces)
3274 self.pg_start()
3275 self.pg1.get_capture(max_sessions)
3276
3277 sleep(6)
3278
3279 pkts = []
3280 for i in range(0, max_sessions):
3281 src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
3282 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3283 IP(src=src, dst=self.pg1.remote_ip4) /
3284 UDP(sport=1026, dport=53))
3285 pkts.append(p)
3286 self.pg0.add_stream(pkts)
3287 self.pg_enable_capture(self.pg_interfaces)
3288 self.pg_start()
3289 self.pg1.get_capture(max_sessions)
3290
3291 nsessions = 0
3292 users = self.vapi.nat44_user_dump()
3293 for user in users:
3294 nsessions = nsessions + user.nsessions
3295 self.assertLess(nsessions, 2 * max_sessions)
3296
Matus Fabiana6110b62018-06-13 05:39:07 -07003297 def tearDown(self):
3298 super(TestNAT44, self).tearDown()
3299 if not self.vpp_dead:
3300 self.logger.info(self.vapi.cli("show nat44 addresses"))
3301 self.logger.info(self.vapi.cli("show nat44 interfaces"))
3302 self.logger.info(self.vapi.cli("show nat44 static mappings"))
3303 self.logger.info(self.vapi.cli("show nat44 interface address"))
3304 self.logger.info(self.vapi.cli("show nat44 sessions detail"))
3305 self.logger.info(self.vapi.cli("show nat virtual-reassembly"))
3306 self.logger.info(self.vapi.cli("show nat44 hash tables detail"))
Matus Fabian878c6462018-08-23 00:33:35 -07003307 self.logger.info(self.vapi.cli("show nat timeouts"))
Matus Fabian5d28c7a2018-09-04 03:55:45 -07003308 self.logger.info(
3309 self.vapi.cli("show nat addr-port-assignment-alg"))
Matus Fabiana6110b62018-06-13 05:39:07 -07003310 self.clear_nat44()
3311 self.vapi.cli("clear logging")
3312
3313
3314class TestNAT44EndpointDependent(MethodHolder):
3315 """ Endpoint-Dependent mapping and filtering test cases """
3316
3317 @classmethod
3318 def setUpConstants(cls):
3319 super(TestNAT44EndpointDependent, cls).setUpConstants()
3320 cls.vpp_cmdline.extend(["nat", "{", "endpoint-dependent", "}"])
3321
3322 @classmethod
3323 def setUpClass(cls):
3324 super(TestNAT44EndpointDependent, cls).setUpClass()
3325 cls.vapi.cli("set log class nat level debug")
3326 try:
3327 cls.tcp_port_in = 6303
3328 cls.tcp_port_out = 6303
3329 cls.udp_port_in = 6304
3330 cls.udp_port_out = 6304
3331 cls.icmp_id_in = 6305
3332 cls.icmp_id_out = 6305
3333 cls.nat_addr = '10.0.0.3'
3334 cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
3335 cls.ipfix_src_port = 4739
3336 cls.ipfix_domain_id = 1
3337 cls.tcp_external_port = 80
3338
Matus Fabian8008d7c2018-07-09 01:34:20 -07003339 cls.create_pg_interfaces(range(7))
Matus Fabiana6110b62018-06-13 05:39:07 -07003340 cls.interfaces = list(cls.pg_interfaces[0:3])
3341
3342 for i in cls.interfaces:
3343 i.admin_up()
3344 i.config_ip4()
3345 i.resolve_arp()
3346
3347 cls.pg0.generate_remote_hosts(3)
3348 cls.pg0.configure_ipv4_neighbors()
3349
3350 cls.pg3.admin_up()
3351
3352 cls.pg4.generate_remote_hosts(2)
3353 cls.pg4.config_ip4()
3354 ip_addr_n = socket.inet_pton(socket.AF_INET, "10.0.0.1")
3355 cls.vapi.sw_interface_add_del_address(cls.pg4.sw_if_index,
3356 ip_addr_n,
3357 24)
3358 cls.pg4.admin_up()
3359 cls.pg4.resolve_arp()
3360 cls.pg4._remote_hosts[1]._ip4 = cls.pg4._remote_hosts[0]._ip4
3361 cls.pg4.resolve_arp()
3362
Matus Fabian8008d7c2018-07-09 01:34:20 -07003363 zero_ip4n = socket.inet_pton(socket.AF_INET, "0.0.0.0")
3364 cls.vapi.ip_table_add_del(1, is_add=1)
3365
3366 cls.pg5._local_ip4 = "10.1.1.1"
3367 cls.pg5._local_ip4n = socket.inet_pton(socket.AF_INET,
3368 cls.pg5.local_ip4)
3369 cls.pg5._remote_hosts[0]._ip4 = "10.1.1.2"
3370 cls.pg5._remote_hosts[0]._ip4n = socket.inet_pton(
3371 socket.AF_INET, cls.pg5.remote_ip4)
3372 cls.pg5.set_table_ip4(1)
3373 cls.pg5.config_ip4()
3374 cls.pg5.admin_up()
3375 cls.vapi.ip_add_del_route(dst_address=cls.pg5.remote_ip4n,
3376 dst_address_length=32,
3377 table_id=1,
3378 next_hop_sw_if_index=cls.pg5.sw_if_index,
3379 next_hop_address=zero_ip4n)
3380
3381 cls.pg6._local_ip4 = "10.1.2.1"
3382 cls.pg6._local_ip4n = socket.inet_pton(socket.AF_INET,
3383 cls.pg6.local_ip4)
3384 cls.pg6._remote_hosts[0]._ip4 = "10.1.2.2"
3385 cls.pg6._remote_hosts[0]._ip4n = socket.inet_pton(
3386 socket.AF_INET, cls.pg6.remote_ip4)
3387 cls.pg6.set_table_ip4(1)
3388 cls.pg6.config_ip4()
3389 cls.pg6.admin_up()
3390 cls.vapi.ip_add_del_route(dst_address=cls.pg6.remote_ip4n,
3391 dst_address_length=32,
3392 table_id=1,
3393 next_hop_sw_if_index=cls.pg6.sw_if_index,
3394 next_hop_address=zero_ip4n)
3395
3396 cls.vapi.ip_add_del_route(dst_address=cls.pg6.remote_ip4n,
3397 dst_address_length=16,
3398 next_hop_address=zero_ip4n,
3399 table_id=0,
3400 next_hop_table_id=1)
3401 cls.vapi.ip_add_del_route(dst_address=zero_ip4n,
3402 dst_address_length=0,
3403 next_hop_address=zero_ip4n,
3404 table_id=1,
3405 next_hop_table_id=0)
3406 cls.vapi.ip_add_del_route(dst_address=zero_ip4n,
3407 dst_address_length=0,
3408 table_id=0,
3409 next_hop_sw_if_index=cls.pg1.sw_if_index,
3410 next_hop_address=cls.pg1.local_ip4n)
3411
3412 cls.pg5.resolve_arp()
3413 cls.pg6.resolve_arp()
3414
Matus Fabiana6110b62018-06-13 05:39:07 -07003415 except Exception:
3416 super(TestNAT44EndpointDependent, cls).tearDownClass()
3417 raise
3418
3419 def test_dynamic(self):
3420 """ NAT44 dynamic translation test """
3421
3422 self.nat44_add_address(self.nat_addr)
3423 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3424 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3425 is_inside=0)
3426
Matus Fabian69ce30d2018-08-22 01:27:10 -07003427 nat_config = self.vapi.nat_show_config()
3428 self.assertEqual(1, nat_config.endpoint_dependent)
3429
Matus Fabiana6110b62018-06-13 05:39:07 -07003430 # in2out
3431 pkts = self.create_stream_in(self.pg0, self.pg1)
3432 self.pg0.add_stream(pkts)
3433 self.pg_enable_capture(self.pg_interfaces)
3434 self.pg_start()
3435 capture = self.pg1.get_capture(len(pkts))
3436 self.verify_capture_out(capture)
3437
3438 # out2in
3439 pkts = self.create_stream_out(self.pg1)
3440 self.pg1.add_stream(pkts)
3441 self.pg_enable_capture(self.pg_interfaces)
3442 self.pg_start()
3443 capture = self.pg0.get_capture(len(pkts))
3444 self.verify_capture_in(capture, self.pg0)
3445
3446 def test_forwarding(self):
3447 """ NAT44 forwarding test """
3448
3449 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3450 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3451 is_inside=0)
3452 self.vapi.nat44_forwarding_enable_disable(1)
3453
3454 real_ip = self.pg0.remote_ip4n
3455 alias_ip = self.nat_addr_n
3456 self.vapi.nat44_add_del_static_mapping(local_ip=real_ip,
3457 external_ip=alias_ip)
3458
3459 try:
3460 # in2out - static mapping match
3461
3462 pkts = self.create_stream_out(self.pg1)
3463 self.pg1.add_stream(pkts)
3464 self.pg_enable_capture(self.pg_interfaces)
3465 self.pg_start()
3466 capture = self.pg0.get_capture(len(pkts))
3467 self.verify_capture_in(capture, self.pg0)
3468
3469 pkts = self.create_stream_in(self.pg0, self.pg1)
3470 self.pg0.add_stream(pkts)
3471 self.pg_enable_capture(self.pg_interfaces)
3472 self.pg_start()
3473 capture = self.pg1.get_capture(len(pkts))
3474 self.verify_capture_out(capture, same_port=True)
3475
3476 # in2out - no static mapping match
3477
3478 host0 = self.pg0.remote_hosts[0]
3479 self.pg0.remote_hosts[0] = self.pg0.remote_hosts[1]
3480 try:
3481 pkts = self.create_stream_out(self.pg1,
3482 dst_ip=self.pg0.remote_ip4,
3483 use_inside_ports=True)
3484 self.pg1.add_stream(pkts)
3485 self.pg_enable_capture(self.pg_interfaces)
3486 self.pg_start()
3487 capture = self.pg0.get_capture(len(pkts))
3488 self.verify_capture_in(capture, self.pg0)
3489
3490 pkts = self.create_stream_in(self.pg0, self.pg1)
3491 self.pg0.add_stream(pkts)
3492 self.pg_enable_capture(self.pg_interfaces)
3493 self.pg_start()
3494 capture = self.pg1.get_capture(len(pkts))
3495 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
3496 same_port=True)
3497 finally:
3498 self.pg0.remote_hosts[0] = host0
3499
3500 user = self.pg0.remote_hosts[1]
3501 sessions = self.vapi.nat44_user_session_dump(user.ip4n, 0)
3502 self.assertEqual(len(sessions), 3)
3503 self.assertTrue(sessions[0].ext_host_valid)
3504 self.vapi.nat44_del_session(
3505 sessions[0].inside_ip_address,
3506 sessions[0].inside_port,
3507 sessions[0].protocol,
3508 ext_host_address=sessions[0].ext_host_address,
3509 ext_host_port=sessions[0].ext_host_port)
3510 sessions = self.vapi.nat44_user_session_dump(user.ip4n, 0)
3511 self.assertEqual(len(sessions), 2)
3512
3513 finally:
3514 self.vapi.nat44_forwarding_enable_disable(0)
3515 self.vapi.nat44_add_del_static_mapping(local_ip=real_ip,
3516 external_ip=alias_ip,
3517 is_add=0)
3518
3519 def test_static_lb(self):
3520 """ NAT44 local service load balancing """
3521 external_addr_n = socket.inet_pton(socket.AF_INET, self.nat_addr)
3522 external_port = 80
3523 local_port = 8080
3524 server1 = self.pg0.remote_hosts[0]
3525 server2 = self.pg0.remote_hosts[1]
3526
3527 locals = [{'addr': server1.ip4n,
3528 'port': local_port,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07003529 'probability': 70,
3530 'vrf_id': 0},
Matus Fabiana6110b62018-06-13 05:39:07 -07003531 {'addr': server2.ip4n,
3532 'port': local_port,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07003533 'probability': 30,
3534 'vrf_id': 0}]
Matus Fabiana6110b62018-06-13 05:39:07 -07003535
3536 self.nat44_add_address(self.nat_addr)
3537 self.vapi.nat44_add_del_lb_static_mapping(external_addr_n,
3538 external_port,
3539 IP_PROTOS.tcp,
3540 local_num=len(locals),
3541 locals=locals)
3542 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3543 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3544 is_inside=0)
3545
3546 # from client to service
3547 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3548 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3549 TCP(sport=12345, dport=external_port))
3550 self.pg1.add_stream(p)
3551 self.pg_enable_capture(self.pg_interfaces)
3552 self.pg_start()
3553 capture = self.pg0.get_capture(1)
3554 p = capture[0]
3555 server = None
3556 try:
3557 ip = p[IP]
3558 tcp = p[TCP]
3559 self.assertIn(ip.dst, [server1.ip4, server2.ip4])
3560 if ip.dst == server1.ip4:
3561 server = server1
3562 else:
3563 server = server2
3564 self.assertEqual(tcp.dport, local_port)
3565 self.assert_packet_checksums_valid(p)
3566 except:
3567 self.logger.error(ppp("Unexpected or invalid packet:", p))
3568 raise
3569
3570 # from service back to client
3571 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
3572 IP(src=server.ip4, dst=self.pg1.remote_ip4) /
3573 TCP(sport=local_port, dport=12345))
3574 self.pg0.add_stream(p)
3575 self.pg_enable_capture(self.pg_interfaces)
3576 self.pg_start()
3577 capture = self.pg1.get_capture(1)
3578 p = capture[0]
3579 try:
3580 ip = p[IP]
3581 tcp = p[TCP]
3582 self.assertEqual(ip.src, self.nat_addr)
3583 self.assertEqual(tcp.sport, external_port)
3584 self.assert_packet_checksums_valid(p)
3585 except:
3586 self.logger.error(ppp("Unexpected or invalid packet:", p))
3587 raise
3588
3589 sessions = self.vapi.nat44_user_session_dump(server.ip4n, 0)
3590 self.assertEqual(len(sessions), 1)
3591 self.assertTrue(sessions[0].ext_host_valid)
3592 self.vapi.nat44_del_session(
3593 sessions[0].inside_ip_address,
3594 sessions[0].inside_port,
3595 sessions[0].protocol,
3596 ext_host_address=sessions[0].ext_host_address,
3597 ext_host_port=sessions[0].ext_host_port)
3598 sessions = self.vapi.nat44_user_session_dump(server.ip4n, 0)
3599 self.assertEqual(len(sessions), 0)
3600
3601 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
3602 def test_static_lb_multi_clients(self):
3603 """ NAT44 local service load balancing - multiple clients"""
3604
3605 external_addr_n = socket.inet_pton(socket.AF_INET, self.nat_addr)
3606 external_port = 80
3607 local_port = 8080
3608 server1 = self.pg0.remote_hosts[0]
3609 server2 = self.pg0.remote_hosts[1]
3610
3611 locals = [{'addr': server1.ip4n,
3612 'port': local_port,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07003613 'probability': 90,
3614 'vrf_id': 0},
Matus Fabiana6110b62018-06-13 05:39:07 -07003615 {'addr': server2.ip4n,
3616 'port': local_port,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07003617 'probability': 10,
3618 'vrf_id': 0}]
Matus Fabiana6110b62018-06-13 05:39:07 -07003619
3620 self.nat44_add_address(self.nat_addr)
3621 self.vapi.nat44_add_del_lb_static_mapping(external_addr_n,
3622 external_port,
3623 IP_PROTOS.tcp,
3624 local_num=len(locals),
3625 locals=locals)
3626 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3627 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3628 is_inside=0)
3629
3630 server1_n = 0
3631 server2_n = 0
3632 clients = ip4_range(self.pg1.remote_ip4, 10, 50)
3633 pkts = []
3634 for client in clients:
3635 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3636 IP(src=client, dst=self.nat_addr) /
3637 TCP(sport=12345, dport=external_port))
3638 pkts.append(p)
3639 self.pg1.add_stream(pkts)
3640 self.pg_enable_capture(self.pg_interfaces)
3641 self.pg_start()
3642 capture = self.pg0.get_capture(len(pkts))
3643 for p in capture:
3644 if p[IP].dst == server1.ip4:
3645 server1_n += 1
3646 else:
3647 server2_n += 1
3648 self.assertTrue(server1_n > server2_n)
3649
3650 def test_static_lb_2(self):
3651 """ NAT44 local service load balancing (asymmetrical rule) """
3652 external_addr_n = socket.inet_pton(socket.AF_INET, self.nat_addr)
3653 external_port = 80
3654 local_port = 8080
3655 server1 = self.pg0.remote_hosts[0]
3656 server2 = self.pg0.remote_hosts[1]
3657
3658 locals = [{'addr': server1.ip4n,
3659 'port': local_port,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07003660 'probability': 70,
3661 'vrf_id': 0},
Matus Fabiana6110b62018-06-13 05:39:07 -07003662 {'addr': server2.ip4n,
3663 'port': local_port,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07003664 'probability': 30,
3665 'vrf_id': 0}]
Matus Fabiana6110b62018-06-13 05:39:07 -07003666
3667 self.vapi.nat44_forwarding_enable_disable(1)
3668 self.vapi.nat44_add_del_lb_static_mapping(external_addr_n,
3669 external_port,
3670 IP_PROTOS.tcp,
3671 out2in_only=1,
3672 local_num=len(locals),
3673 locals=locals)
3674 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3675 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3676 is_inside=0)
3677
3678 # from client to service
3679 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3680 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3681 TCP(sport=12345, dport=external_port))
3682 self.pg1.add_stream(p)
3683 self.pg_enable_capture(self.pg_interfaces)
3684 self.pg_start()
3685 capture = self.pg0.get_capture(1)
3686 p = capture[0]
3687 server = None
3688 try:
3689 ip = p[IP]
3690 tcp = p[TCP]
3691 self.assertIn(ip.dst, [server1.ip4, server2.ip4])
3692 if ip.dst == server1.ip4:
3693 server = server1
3694 else:
3695 server = server2
3696 self.assertEqual(tcp.dport, local_port)
3697 self.assert_packet_checksums_valid(p)
3698 except:
3699 self.logger.error(ppp("Unexpected or invalid packet:", p))
3700 raise
3701
3702 # from service back to client
3703 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
3704 IP(src=server.ip4, dst=self.pg1.remote_ip4) /
3705 TCP(sport=local_port, dport=12345))
3706 self.pg0.add_stream(p)
3707 self.pg_enable_capture(self.pg_interfaces)
3708 self.pg_start()
3709 capture = self.pg1.get_capture(1)
3710 p = capture[0]
3711 try:
3712 ip = p[IP]
3713 tcp = p[TCP]
3714 self.assertEqual(ip.src, self.nat_addr)
3715 self.assertEqual(tcp.sport, external_port)
3716 self.assert_packet_checksums_valid(p)
3717 except:
3718 self.logger.error(ppp("Unexpected or invalid packet:", p))
3719 raise
3720
3721 # from client to server (no translation)
3722 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3723 IP(src=self.pg1.remote_ip4, dst=server1.ip4) /
3724 TCP(sport=12346, dport=local_port))
3725 self.pg1.add_stream(p)
3726 self.pg_enable_capture(self.pg_interfaces)
3727 self.pg_start()
3728 capture = self.pg0.get_capture(1)
3729 p = capture[0]
3730 server = None
3731 try:
3732 ip = p[IP]
3733 tcp = p[TCP]
3734 self.assertEqual(ip.dst, server1.ip4)
3735 self.assertEqual(tcp.dport, local_port)
3736 self.assert_packet_checksums_valid(p)
3737 except:
3738 self.logger.error(ppp("Unexpected or invalid packet:", p))
3739 raise
3740
3741 # from service back to client (no translation)
3742 p = (Ether(src=server1.mac, dst=self.pg0.local_mac) /
3743 IP(src=server1.ip4, dst=self.pg1.remote_ip4) /
3744 TCP(sport=local_port, dport=12346))
3745 self.pg0.add_stream(p)
3746 self.pg_enable_capture(self.pg_interfaces)
3747 self.pg_start()
3748 capture = self.pg1.get_capture(1)
3749 p = capture[0]
3750 try:
3751 ip = p[IP]
3752 tcp = p[TCP]
3753 self.assertEqual(ip.src, server1.ip4)
3754 self.assertEqual(tcp.sport, local_port)
3755 self.assert_packet_checksums_valid(p)
3756 except:
3757 self.logger.error(ppp("Unexpected or invalid packet:", p))
3758 raise
3759
Matus Fabianea5b5be2018-09-03 05:02:23 -07003760 def test_lb_affinity(self):
3761 """ NAT44 local service load balancing affinity """
3762 external_addr_n = socket.inet_pton(socket.AF_INET, self.nat_addr)
3763 external_port = 80
3764 local_port = 8080
3765 server1 = self.pg0.remote_hosts[0]
3766 server2 = self.pg0.remote_hosts[1]
3767
3768 locals = [{'addr': server1.ip4n,
3769 'port': local_port,
3770 'probability': 50,
3771 'vrf_id': 0},
3772 {'addr': server2.ip4n,
3773 'port': local_port,
3774 'probability': 50,
3775 'vrf_id': 0}]
3776
3777 self.nat44_add_address(self.nat_addr)
3778 self.vapi.nat44_add_del_lb_static_mapping(external_addr_n,
3779 external_port,
3780 IP_PROTOS.tcp,
3781 affinity=10800,
3782 local_num=len(locals),
3783 locals=locals)
3784 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3785 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3786 is_inside=0)
3787
3788 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
3789 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3790 TCP(sport=1025, dport=external_port))
3791 self.pg1.add_stream(p)
3792 self.pg_enable_capture(self.pg_interfaces)
3793 self.pg_start()
3794 capture = self.pg0.get_capture(1)
3795 backend = capture[0][IP].dst
3796
3797 sessions = self.vapi.nat44_user_session_dump(
3798 socket.inet_pton(socket.AF_INET, backend), 0)
3799 self.assertEqual(len(sessions), 1)
3800 self.assertTrue(sessions[0].ext_host_valid)
3801 self.vapi.nat44_del_session(
3802 sessions[0].inside_ip_address,
3803 sessions[0].inside_port,
3804 sessions[0].protocol,
3805 ext_host_address=sessions[0].ext_host_address,
3806 ext_host_port=sessions[0].ext_host_port)
3807
3808 pkts = []
3809 for port in range(1030, 1100):
3810 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
3811 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3812 TCP(sport=port, dport=external_port))
3813 pkts.append(p)
3814 self.pg1.add_stream(pkts)
3815 self.pg_enable_capture(self.pg_interfaces)
3816 self.pg_start()
3817 capture = self.pg0.get_capture(len(pkts))
3818 for p in capture:
3819 self.assertEqual(p[IP].dst, backend)
3820
Matus Fabiana6110b62018-06-13 05:39:07 -07003821 def test_unknown_proto(self):
3822 """ NAT44 translate packet with unknown protocol """
3823 self.nat44_add_address(self.nat_addr)
3824 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3825 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3826 is_inside=0)
3827
3828 # in2out
3829 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3830 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3831 TCP(sport=self.tcp_port_in, dport=20))
3832 self.pg0.add_stream(p)
3833 self.pg_enable_capture(self.pg_interfaces)
3834 self.pg_start()
3835 p = self.pg1.get_capture(1)
3836
3837 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3838 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3839 GRE() /
3840 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
3841 TCP(sport=1234, dport=1234))
3842 self.pg0.add_stream(p)
3843 self.pg_enable_capture(self.pg_interfaces)
3844 self.pg_start()
3845 p = self.pg1.get_capture(1)
3846 packet = p[0]
3847 try:
3848 self.assertEqual(packet[IP].src, self.nat_addr)
3849 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
3850 self.assertTrue(packet.haslayer(GRE))
3851 self.assert_packet_checksums_valid(packet)
3852 except:
3853 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3854 raise
3855
3856 # out2in
3857 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
3858 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3859 GRE() /
3860 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
3861 TCP(sport=1234, dport=1234))
3862 self.pg1.add_stream(p)
3863 self.pg_enable_capture(self.pg_interfaces)
3864 self.pg_start()
3865 p = self.pg0.get_capture(1)
3866 packet = p[0]
3867 try:
3868 self.assertEqual(packet[IP].src, self.pg1.remote_ip4)
3869 self.assertEqual(packet[IP].dst, self.pg0.remote_ip4)
3870 self.assertTrue(packet.haslayer(GRE))
3871 self.assert_packet_checksums_valid(packet)
3872 except:
3873 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3874 raise
3875
3876 def test_hairpinning_unknown_proto(self):
3877 """ NAT44 translate packet with unknown protocol - hairpinning """
3878 host = self.pg0.remote_hosts[0]
3879 server = self.pg0.remote_hosts[1]
3880 host_in_port = 1234
3881 server_out_port = 8765
3882 server_nat_ip = "10.0.0.11"
3883
3884 self.nat44_add_address(self.nat_addr)
3885 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3886 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3887 is_inside=0)
3888
3889 # add static mapping for server
3890 self.nat44_add_static_mapping(server.ip4, server_nat_ip)
3891
3892 # host to server
3893 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
3894 IP(src=host.ip4, dst=server_nat_ip) /
3895 TCP(sport=host_in_port, dport=server_out_port))
3896 self.pg0.add_stream(p)
3897 self.pg_enable_capture(self.pg_interfaces)
3898 self.pg_start()
3899 self.pg0.get_capture(1)
3900
3901 p = (Ether(dst=self.pg0.local_mac, src=host.mac) /
3902 IP(src=host.ip4, dst=server_nat_ip) /
3903 GRE() /
3904 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
3905 TCP(sport=1234, dport=1234))
3906 self.pg0.add_stream(p)
3907 self.pg_enable_capture(self.pg_interfaces)
3908 self.pg_start()
3909 p = self.pg0.get_capture(1)
3910 packet = p[0]
3911 try:
3912 self.assertEqual(packet[IP].src, self.nat_addr)
3913 self.assertEqual(packet[IP].dst, server.ip4)
3914 self.assertTrue(packet.haslayer(GRE))
3915 self.assert_packet_checksums_valid(packet)
3916 except:
3917 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3918 raise
3919
3920 # server to host
3921 p = (Ether(dst=self.pg0.local_mac, src=server.mac) /
3922 IP(src=server.ip4, dst=self.nat_addr) /
3923 GRE() /
3924 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
3925 TCP(sport=1234, dport=1234))
3926 self.pg0.add_stream(p)
3927 self.pg_enable_capture(self.pg_interfaces)
3928 self.pg_start()
3929 p = self.pg0.get_capture(1)
3930 packet = p[0]
3931 try:
3932 self.assertEqual(packet[IP].src, server_nat_ip)
3933 self.assertEqual(packet[IP].dst, host.ip4)
3934 self.assertTrue(packet.haslayer(GRE))
3935 self.assert_packet_checksums_valid(packet)
3936 except:
3937 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3938 raise
3939
3940 def test_output_feature_and_service(self):
3941 """ NAT44 interface output feature and services """
3942 external_addr = '1.2.3.4'
3943 external_port = 80
3944 local_port = 8080
3945
3946 self.vapi.nat44_forwarding_enable_disable(1)
3947 self.nat44_add_address(self.nat_addr)
3948 self.vapi.nat44_add_del_identity_mapping(ip=self.pg1.remote_ip4n)
3949 self.nat44_add_static_mapping(self.pg0.remote_ip4, external_addr,
3950 local_port, external_port,
3951 proto=IP_PROTOS.tcp, out2in_only=1)
3952 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3953 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
3954 is_inside=0)
3955 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
3956 is_inside=0)
3957
3958 # from client to service
3959 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3960 IP(src=self.pg1.remote_ip4, dst=external_addr) /
3961 TCP(sport=12345, dport=external_port))
3962 self.pg1.add_stream(p)
3963 self.pg_enable_capture(self.pg_interfaces)
3964 self.pg_start()
3965 capture = self.pg0.get_capture(1)
3966 p = capture[0]
3967 try:
3968 ip = p[IP]
3969 tcp = p[TCP]
3970 self.assertEqual(ip.dst, self.pg0.remote_ip4)
3971 self.assertEqual(tcp.dport, local_port)
3972 self.assert_packet_checksums_valid(p)
3973 except:
3974 self.logger.error(ppp("Unexpected or invalid packet:", p))
3975 raise
3976
3977 # from service back to client
3978 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3979 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3980 TCP(sport=local_port, dport=12345))
3981 self.pg0.add_stream(p)
3982 self.pg_enable_capture(self.pg_interfaces)
3983 self.pg_start()
3984 capture = self.pg1.get_capture(1)
3985 p = capture[0]
3986 try:
3987 ip = p[IP]
3988 tcp = p[TCP]
3989 self.assertEqual(ip.src, external_addr)
3990 self.assertEqual(tcp.sport, external_port)
3991 self.assert_packet_checksums_valid(p)
3992 except:
3993 self.logger.error(ppp("Unexpected or invalid packet:", p))
3994 raise
3995
3996 # from local network host to external network
3997 pkts = self.create_stream_in(self.pg0, self.pg1)
3998 self.pg0.add_stream(pkts)
3999 self.pg_enable_capture(self.pg_interfaces)
4000 self.pg_start()
4001 capture = self.pg1.get_capture(len(pkts))
4002 self.verify_capture_out(capture)
4003 pkts = self.create_stream_in(self.pg0, self.pg1)
4004 self.pg0.add_stream(pkts)
4005 self.pg_enable_capture(self.pg_interfaces)
4006 self.pg_start()
4007 capture = self.pg1.get_capture(len(pkts))
4008 self.verify_capture_out(capture)
4009
4010 # from external network back to local network host
4011 pkts = self.create_stream_out(self.pg1)
4012 self.pg1.add_stream(pkts)
4013 self.pg_enable_capture(self.pg_interfaces)
4014 self.pg_start()
4015 capture = self.pg0.get_capture(len(pkts))
4016 self.verify_capture_in(capture, self.pg0)
4017
4018 def test_output_feature_and_service2(self):
4019 """ NAT44 interface output feature and service host direct access """
4020 self.vapi.nat44_forwarding_enable_disable(1)
4021 self.nat44_add_address(self.nat_addr)
4022 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
4023 is_inside=0)
4024
4025 # session initiaded from service host - translate
4026 pkts = self.create_stream_in(self.pg0, self.pg1)
4027 self.pg0.add_stream(pkts)
4028 self.pg_enable_capture(self.pg_interfaces)
4029 self.pg_start()
4030 capture = self.pg1.get_capture(len(pkts))
4031 self.verify_capture_out(capture)
4032
4033 pkts = self.create_stream_out(self.pg1)
4034 self.pg1.add_stream(pkts)
4035 self.pg_enable_capture(self.pg_interfaces)
4036 self.pg_start()
4037 capture = self.pg0.get_capture(len(pkts))
4038 self.verify_capture_in(capture, self.pg0)
4039
4040 # session initiaded from remote host - do not translate
4041 self.tcp_port_in = 60303
4042 self.udp_port_in = 60304
4043 self.icmp_id_in = 60305
4044 pkts = self.create_stream_out(self.pg1,
4045 self.pg0.remote_ip4,
4046 use_inside_ports=True)
4047 self.pg1.add_stream(pkts)
4048 self.pg_enable_capture(self.pg_interfaces)
4049 self.pg_start()
4050 capture = self.pg0.get_capture(len(pkts))
4051 self.verify_capture_in(capture, self.pg0)
4052
4053 pkts = self.create_stream_in(self.pg0, self.pg1)
4054 self.pg0.add_stream(pkts)
4055 self.pg_enable_capture(self.pg_interfaces)
4056 self.pg_start()
4057 capture = self.pg1.get_capture(len(pkts))
4058 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
4059 same_port=True)
4060
4061 def test_output_feature_and_service3(self):
4062 """ NAT44 interface output feature and DST NAT """
4063 external_addr = '1.2.3.4'
4064 external_port = 80
4065 local_port = 8080
4066
4067 self.vapi.nat44_forwarding_enable_disable(1)
4068 self.nat44_add_address(self.nat_addr)
4069 self.nat44_add_static_mapping(self.pg1.remote_ip4, external_addr,
4070 local_port, external_port,
4071 proto=IP_PROTOS.tcp, out2in_only=1)
4072 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4073 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
4074 is_inside=0)
4075 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
4076 is_inside=0)
4077
4078 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4079 IP(src=self.pg0.remote_ip4, dst=external_addr) /
4080 TCP(sport=12345, dport=external_port))
4081 self.pg0.add_stream(p)
4082 self.pg_enable_capture(self.pg_interfaces)
4083 self.pg_start()
4084 capture = self.pg1.get_capture(1)
4085 p = capture[0]
4086 try:
4087 ip = p[IP]
4088 tcp = p[TCP]
4089 self.assertEqual(ip.src, self.pg0.remote_ip4)
4090 self.assertEqual(tcp.sport, 12345)
4091 self.assertEqual(ip.dst, self.pg1.remote_ip4)
4092 self.assertEqual(tcp.dport, local_port)
4093 self.assert_packet_checksums_valid(p)
4094 except:
4095 self.logger.error(ppp("Unexpected or invalid packet:", p))
4096 raise
4097
4098 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4099 IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
4100 TCP(sport=local_port, dport=12345))
4101 self.pg1.add_stream(p)
4102 self.pg_enable_capture(self.pg_interfaces)
4103 self.pg_start()
4104 capture = self.pg0.get_capture(1)
4105 p = capture[0]
4106 try:
4107 ip = p[IP]
4108 tcp = p[TCP]
4109 self.assertEqual(ip.src, external_addr)
4110 self.assertEqual(tcp.sport, external_port)
4111 self.assertEqual(ip.dst, self.pg0.remote_ip4)
4112 self.assertEqual(tcp.dport, 12345)
4113 self.assert_packet_checksums_valid(p)
4114 except:
4115 self.logger.error(ppp("Unexpected or invalid packet:", p))
4116 raise
4117
Matus Fabian182e37e2018-08-14 04:21:26 -07004118 def test_next_src_nat(self):
4119 """ On way back forward packet to nat44-in2out node. """
4120 twice_nat_addr = '10.0.1.3'
4121 external_port = 80
4122 local_port = 8080
4123 post_twice_nat_port = 0
4124
4125 self.vapi.nat44_forwarding_enable_disable(1)
4126 self.nat44_add_address(twice_nat_addr, twice_nat=1)
4127 self.nat44_add_static_mapping(self.pg6.remote_ip4, self.pg1.remote_ip4,
4128 local_port, external_port,
4129 proto=IP_PROTOS.tcp, out2in_only=1,
4130 self_twice_nat=1, vrf_id=1)
4131 self.vapi.nat44_interface_add_del_feature(self.pg6.sw_if_index,
4132 is_inside=0)
4133
4134 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
4135 IP(src=self.pg6.remote_ip4, dst=self.pg1.remote_ip4) /
4136 TCP(sport=12345, dport=external_port))
4137 self.pg6.add_stream(p)
4138 self.pg_enable_capture(self.pg_interfaces)
4139 self.pg_start()
4140 capture = self.pg6.get_capture(1)
4141 p = capture[0]
4142 try:
4143 ip = p[IP]
4144 tcp = p[TCP]
4145 self.assertEqual(ip.src, twice_nat_addr)
4146 self.assertNotEqual(tcp.sport, 12345)
4147 post_twice_nat_port = tcp.sport
4148 self.assertEqual(ip.dst, self.pg6.remote_ip4)
4149 self.assertEqual(tcp.dport, local_port)
4150 self.assert_packet_checksums_valid(p)
4151 except:
4152 self.logger.error(ppp("Unexpected or invalid packet:", p))
4153 raise
4154
4155 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
4156 IP(src=self.pg6.remote_ip4, dst=twice_nat_addr) /
4157 TCP(sport=local_port, dport=post_twice_nat_port))
4158 self.pg6.add_stream(p)
4159 self.pg_enable_capture(self.pg_interfaces)
4160 self.pg_start()
4161 capture = self.pg6.get_capture(1)
4162 p = capture[0]
4163 try:
4164 ip = p[IP]
4165 tcp = p[TCP]
4166 self.assertEqual(ip.src, self.pg1.remote_ip4)
4167 self.assertEqual(tcp.sport, external_port)
4168 self.assertEqual(ip.dst, self.pg6.remote_ip4)
4169 self.assertEqual(tcp.dport, 12345)
4170 self.assert_packet_checksums_valid(p)
4171 except:
4172 self.logger.error(ppp("Unexpected or invalid packet:", p))
4173 raise
4174
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004175 def twice_nat_common(self, self_twice_nat=False, same_pg=False, lb=False,
4176 client_id=None):
Matus Fabianb932d262017-12-18 05:38:24 -08004177 twice_nat_addr = '10.0.1.3'
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004178
Matus Fabianb932d262017-12-18 05:38:24 -08004179 port_in = 8080
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004180 if lb:
4181 if not same_pg:
4182 port_in1 = port_in
4183 port_in2 = port_in
4184 else:
4185 port_in1 = port_in+1
4186 port_in2 = port_in+2
4187
Matus Fabianb932d262017-12-18 05:38:24 -08004188 port_out = 80
4189 eh_port_out = 4567
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004190
4191 server1 = self.pg0.remote_hosts[0]
4192 server2 = self.pg0.remote_hosts[1]
4193 if lb and same_pg:
4194 server2 = server1
4195 if not lb:
4196 server = server1
4197
4198 pg0 = self.pg0
4199 if same_pg:
4200 pg1 = self.pg0
4201 else:
4202 pg1 = self.pg1
4203
4204 eh_translate = ((not self_twice_nat) or (not lb and same_pg) or
4205 client_id == 1)
4206
Matus Fabianb932d262017-12-18 05:38:24 -08004207 self.nat44_add_address(self.nat_addr)
4208 self.nat44_add_address(twice_nat_addr, twice_nat=1)
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004209 if not lb:
4210 self.nat44_add_static_mapping(pg0.remote_ip4, self.nat_addr,
4211 port_in, port_out,
4212 proto=IP_PROTOS.tcp,
4213 twice_nat=int(not self_twice_nat),
4214 self_twice_nat=int(self_twice_nat))
4215 else:
4216 locals = [{'addr': server1.ip4n,
4217 'port': port_in1,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07004218 'probability': 50,
4219 'vrf_id': 0},
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004220 {'addr': server2.ip4n,
4221 'port': port_in2,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07004222 'probability': 50,
4223 'vrf_id': 0}]
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004224 out_addr_n = socket.inet_pton(socket.AF_INET, self.nat_addr)
4225 self.vapi.nat44_add_del_lb_static_mapping(out_addr_n,
4226 port_out,
4227 IP_PROTOS.tcp,
4228 twice_nat=int(
4229 not self_twice_nat),
4230 self_twice_nat=int(
4231 self_twice_nat),
4232 local_num=len(locals),
4233 locals=locals)
4234 self.vapi.nat44_interface_add_del_feature(pg0.sw_if_index)
4235 self.vapi.nat44_interface_add_del_feature(pg1.sw_if_index,
Matus Fabianb932d262017-12-18 05:38:24 -08004236 is_inside=0)
4237
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004238 if same_pg:
4239 if not lb:
4240 client = server
4241 else:
4242 assert client_id is not None
4243 if client_id == 1:
4244 client = self.pg0.remote_hosts[0]
4245 elif client_id == 2:
4246 client = self.pg0.remote_hosts[1]
4247 else:
4248 client = pg1.remote_hosts[0]
4249 p = (Ether(src=pg1.remote_mac, dst=pg1.local_mac) /
4250 IP(src=client.ip4, dst=self.nat_addr) /
Matus Fabianb932d262017-12-18 05:38:24 -08004251 TCP(sport=eh_port_out, dport=port_out))
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004252 pg1.add_stream(p)
Matus Fabianb932d262017-12-18 05:38:24 -08004253 self.pg_enable_capture(self.pg_interfaces)
4254 self.pg_start()
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004255 capture = pg0.get_capture(1)
Matus Fabianb932d262017-12-18 05:38:24 -08004256 p = capture[0]
4257 try:
4258 ip = p[IP]
4259 tcp = p[TCP]
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004260 if lb:
4261 if ip.dst == server1.ip4:
4262 server = server1
4263 port_in = port_in1
4264 else:
4265 server = server2
4266 port_in = port_in2
4267 self.assertEqual(ip.dst, server.ip4)
4268 if lb and same_pg:
4269 self.assertIn(tcp.dport, [port_in1, port_in2])
4270 else:
4271 self.assertEqual(tcp.dport, port_in)
4272 if eh_translate:
4273 self.assertEqual(ip.src, twice_nat_addr)
4274 self.assertNotEqual(tcp.sport, eh_port_out)
4275 else:
4276 self.assertEqual(ip.src, client.ip4)
4277 self.assertEqual(tcp.sport, eh_port_out)
4278 eh_addr_in = ip.src
Matus Fabianb932d262017-12-18 05:38:24 -08004279 eh_port_in = tcp.sport
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004280 saved_port_in = tcp.dport
Klement Sekerad81ae412018-05-16 10:52:54 +02004281 self.assert_packet_checksums_valid(p)
Matus Fabianb932d262017-12-18 05:38:24 -08004282 except:
4283 self.logger.error(ppp("Unexpected or invalid packet:", p))
4284 raise
4285
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004286 p = (Ether(src=server.mac, dst=pg0.local_mac) /
4287 IP(src=server.ip4, dst=eh_addr_in) /
4288 TCP(sport=saved_port_in, dport=eh_port_in))
4289 pg0.add_stream(p)
Matus Fabianb932d262017-12-18 05:38:24 -08004290 self.pg_enable_capture(self.pg_interfaces)
4291 self.pg_start()
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004292 capture = pg1.get_capture(1)
Matus Fabianb932d262017-12-18 05:38:24 -08004293 p = capture[0]
4294 try:
4295 ip = p[IP]
4296 tcp = p[TCP]
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004297 self.assertEqual(ip.dst, client.ip4)
Matus Fabianb932d262017-12-18 05:38:24 -08004298 self.assertEqual(ip.src, self.nat_addr)
4299 self.assertEqual(tcp.dport, eh_port_out)
4300 self.assertEqual(tcp.sport, port_out)
Klement Sekerad81ae412018-05-16 10:52:54 +02004301 self.assert_packet_checksums_valid(p)
Matus Fabianb932d262017-12-18 05:38:24 -08004302 except:
4303 self.logger.error(ppp("Unexpected or invalid packet:", p))
4304 raise
4305
Matus Fabian70a26ac2018-05-14 06:20:28 -07004306 if eh_translate:
4307 sessions = self.vapi.nat44_user_session_dump(server.ip4n, 0)
4308 self.assertEqual(len(sessions), 1)
4309 self.assertTrue(sessions[0].ext_host_valid)
4310 self.assertTrue(sessions[0].is_twicenat)
4311 self.vapi.nat44_del_session(
4312 sessions[0].inside_ip_address,
4313 sessions[0].inside_port,
4314 sessions[0].protocol,
4315 ext_host_address=sessions[0].ext_host_nat_address,
4316 ext_host_port=sessions[0].ext_host_nat_port)
4317 sessions = self.vapi.nat44_user_session_dump(server.ip4n, 0)
4318 self.assertEqual(len(sessions), 0)
4319
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004320 def test_twice_nat(self):
4321 """ Twice NAT44 """
4322 self.twice_nat_common()
4323
4324 def test_self_twice_nat_positive(self):
4325 """ Self Twice NAT44 (positive test) """
4326 self.twice_nat_common(self_twice_nat=True, same_pg=True)
4327
4328 def test_self_twice_nat_negative(self):
4329 """ Self Twice NAT44 (negative test) """
4330 self.twice_nat_common(self_twice_nat=True)
4331
Matus Fabianb932d262017-12-18 05:38:24 -08004332 def test_twice_nat_lb(self):
4333 """ Twice NAT44 local service load balancing """
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004334 self.twice_nat_common(lb=True)
Matus Fabianb932d262017-12-18 05:38:24 -08004335
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004336 def test_self_twice_nat_lb_positive(self):
4337 """ Self Twice NAT44 local service load balancing (positive test) """
4338 self.twice_nat_common(lb=True, self_twice_nat=True, same_pg=True,
4339 client_id=1)
Matus Fabianb932d262017-12-18 05:38:24 -08004340
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004341 def test_self_twice_nat_lb_negative(self):
4342 """ Self Twice NAT44 local service load balancing (negative test) """
4343 self.twice_nat_common(lb=True, self_twice_nat=True, same_pg=True,
4344 client_id=2)
Matus Fabianb932d262017-12-18 05:38:24 -08004345
4346 def test_twice_nat_interface_addr(self):
4347 """ Acquire twice NAT44 addresses from interface """
Matus Fabiana6110b62018-06-13 05:39:07 -07004348 self.vapi.nat44_add_interface_addr(self.pg3.sw_if_index, twice_nat=1)
Matus Fabianb932d262017-12-18 05:38:24 -08004349
4350 # no address in NAT pool
4351 adresses = self.vapi.nat44_address_dump()
4352 self.assertEqual(0, len(adresses))
4353
4354 # configure interface address and check NAT address pool
Matus Fabiana6110b62018-06-13 05:39:07 -07004355 self.pg3.config_ip4()
Matus Fabianb932d262017-12-18 05:38:24 -08004356 adresses = self.vapi.nat44_address_dump()
4357 self.assertEqual(1, len(adresses))
Matus Fabiana6110b62018-06-13 05:39:07 -07004358 self.assertEqual(adresses[0].ip_address[0:4], self.pg3.local_ip4n)
Matus Fabianb932d262017-12-18 05:38:24 -08004359 self.assertEqual(adresses[0].twice_nat, 1)
4360
4361 # remove interface address and check NAT address pool
Matus Fabiana6110b62018-06-13 05:39:07 -07004362 self.pg3.unconfig_ip4()
Matus Fabianb932d262017-12-18 05:38:24 -08004363 adresses = self.vapi.nat44_address_dump()
4364 self.assertEqual(0, len(adresses))
4365
Matus Fabianebdf1902018-05-04 03:57:42 -07004366 def test_tcp_session_close_in(self):
4367 """ Close TCP session from inside network """
Matus Fabian229c1aa2018-05-28 04:09:52 -07004368 self.tcp_port_out = 10505
Matus Fabianebdf1902018-05-04 03:57:42 -07004369 self.nat44_add_address(self.nat_addr)
Matus Fabian229c1aa2018-05-28 04:09:52 -07004370 self.nat44_add_static_mapping(self.pg0.remote_ip4,
4371 self.nat_addr,
4372 self.tcp_port_in,
4373 self.tcp_port_out,
4374 proto=IP_PROTOS.tcp,
4375 twice_nat=1)
Matus Fabianebdf1902018-05-04 03:57:42 -07004376 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4377 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4378 is_inside=0)
4379
4380 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
4381 start_sessnum = len(sessions)
4382
4383 self.initiate_tcp_session(self.pg0, self.pg1)
4384
Matus Fabian229c1aa2018-05-28 04:09:52 -07004385 # FIN packet in -> out
4386 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4387 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4388 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
4389 flags="FA", seq=100, ack=300))
4390 self.pg0.add_stream(p)
4391 self.pg_enable_capture(self.pg_interfaces)
4392 self.pg_start()
4393 self.pg1.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07004394
Matus Fabian229c1aa2018-05-28 04:09:52 -07004395 pkts = []
Matus Fabianebdf1902018-05-04 03:57:42 -07004396
Matus Fabian229c1aa2018-05-28 04:09:52 -07004397 # ACK packet out -> in
4398 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4399 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4400 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
4401 flags="A", seq=300, ack=101))
4402 pkts.append(p)
Matus Fabianebdf1902018-05-04 03:57:42 -07004403
Matus Fabian229c1aa2018-05-28 04:09:52 -07004404 # FIN packet out -> in
4405 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4406 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4407 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
4408 flags="FA", seq=300, ack=101))
4409 pkts.append(p)
Matus Fabianebdf1902018-05-04 03:57:42 -07004410
Matus Fabian229c1aa2018-05-28 04:09:52 -07004411 self.pg1.add_stream(pkts)
4412 self.pg_enable_capture(self.pg_interfaces)
4413 self.pg_start()
4414 self.pg0.get_capture(2)
Matus Fabianebdf1902018-05-04 03:57:42 -07004415
Matus Fabian229c1aa2018-05-28 04:09:52 -07004416 # ACK packet in -> out
4417 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4418 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4419 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
4420 flags="A", seq=101, ack=301))
4421 self.pg0.add_stream(p)
4422 self.pg_enable_capture(self.pg_interfaces)
4423 self.pg_start()
4424 self.pg1.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07004425
Matus Fabian229c1aa2018-05-28 04:09:52 -07004426 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n,
4427 0)
4428 self.assertEqual(len(sessions) - start_sessnum, 0)
Matus Fabianebdf1902018-05-04 03:57:42 -07004429
4430 def test_tcp_session_close_out(self):
4431 """ Close TCP session from outside network """
Matus Fabian229c1aa2018-05-28 04:09:52 -07004432 self.tcp_port_out = 10505
Matus Fabianebdf1902018-05-04 03:57:42 -07004433 self.nat44_add_address(self.nat_addr)
Matus Fabian229c1aa2018-05-28 04:09:52 -07004434 self.nat44_add_static_mapping(self.pg0.remote_ip4,
4435 self.nat_addr,
4436 self.tcp_port_in,
4437 self.tcp_port_out,
4438 proto=IP_PROTOS.tcp,
4439 twice_nat=1)
Matus Fabianebdf1902018-05-04 03:57:42 -07004440 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4441 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4442 is_inside=0)
4443
4444 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
4445 start_sessnum = len(sessions)
4446
4447 self.initiate_tcp_session(self.pg0, self.pg1)
4448
Matus Fabian229c1aa2018-05-28 04:09:52 -07004449 # FIN packet out -> in
4450 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4451 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4452 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
4453 flags="FA", seq=100, ack=300))
4454 self.pg1.add_stream(p)
4455 self.pg_enable_capture(self.pg_interfaces)
4456 self.pg_start()
4457 self.pg0.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07004458
Matus Fabian229c1aa2018-05-28 04:09:52 -07004459 # FIN+ACK packet in -> out
4460 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4461 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4462 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
4463 flags="FA", seq=300, ack=101))
Matus Fabianebdf1902018-05-04 03:57:42 -07004464
Matus Fabian229c1aa2018-05-28 04:09:52 -07004465 self.pg0.add_stream(p)
4466 self.pg_enable_capture(self.pg_interfaces)
4467 self.pg_start()
4468 self.pg1.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07004469
Matus Fabian229c1aa2018-05-28 04:09:52 -07004470 # ACK packet out -> in
4471 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4472 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4473 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
4474 flags="A", seq=101, ack=301))
4475 self.pg1.add_stream(p)
4476 self.pg_enable_capture(self.pg_interfaces)
4477 self.pg_start()
4478 self.pg0.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07004479
Matus Fabian229c1aa2018-05-28 04:09:52 -07004480 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n,
4481 0)
4482 self.assertEqual(len(sessions) - start_sessnum, 0)
Matus Fabianebdf1902018-05-04 03:57:42 -07004483
4484 def test_tcp_session_close_simultaneous(self):
4485 """ Close TCP session from inside network """
Matus Fabian229c1aa2018-05-28 04:09:52 -07004486 self.tcp_port_out = 10505
Matus Fabianebdf1902018-05-04 03:57:42 -07004487 self.nat44_add_address(self.nat_addr)
Matus Fabian229c1aa2018-05-28 04:09:52 -07004488 self.nat44_add_static_mapping(self.pg0.remote_ip4,
4489 self.nat_addr,
4490 self.tcp_port_in,
4491 self.tcp_port_out,
4492 proto=IP_PROTOS.tcp,
4493 twice_nat=1)
Matus Fabianebdf1902018-05-04 03:57:42 -07004494 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4495 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4496 is_inside=0)
4497
4498 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
4499 start_sessnum = len(sessions)
4500
4501 self.initiate_tcp_session(self.pg0, self.pg1)
4502
Matus Fabian229c1aa2018-05-28 04:09:52 -07004503 # FIN packet in -> out
4504 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4505 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4506 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
4507 flags="FA", seq=100, ack=300))
4508 self.pg0.add_stream(p)
4509 self.pg_enable_capture(self.pg_interfaces)
4510 self.pg_start()
4511 self.pg1.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07004512
Matus Fabian229c1aa2018-05-28 04:09:52 -07004513 # FIN packet out -> in
4514 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4515 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4516 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
4517 flags="FA", seq=300, ack=100))
4518 self.pg1.add_stream(p)
4519 self.pg_enable_capture(self.pg_interfaces)
4520 self.pg_start()
4521 self.pg0.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07004522
Matus Fabian229c1aa2018-05-28 04:09:52 -07004523 # ACK packet in -> out
4524 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4525 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4526 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
4527 flags="A", seq=101, ack=301))
4528 self.pg0.add_stream(p)
4529 self.pg_enable_capture(self.pg_interfaces)
4530 self.pg_start()
4531 self.pg1.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07004532
Matus Fabian229c1aa2018-05-28 04:09:52 -07004533 # ACK packet out -> in
4534 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4535 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4536 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
4537 flags="A", seq=301, ack=101))
4538 self.pg1.add_stream(p)
4539 self.pg_enable_capture(self.pg_interfaces)
4540 self.pg_start()
4541 self.pg0.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07004542
Matus Fabian229c1aa2018-05-28 04:09:52 -07004543 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n,
4544 0)
4545 self.assertEqual(len(sessions) - start_sessnum, 0)
Matus Fabianebdf1902018-05-04 03:57:42 -07004546
Matus Fabiana6110b62018-06-13 05:39:07 -07004547 def test_one_armed_nat44_static(self):
4548 """ One armed NAT44 and 1:1 NAPT asymmetrical rule """
4549 remote_host = self.pg4.remote_hosts[0]
4550 local_host = self.pg4.remote_hosts[1]
4551 external_port = 80
4552 local_port = 8080
4553 eh_port_in = 0
4554
4555 self.vapi.nat44_forwarding_enable_disable(1)
4556 self.nat44_add_address(self.nat_addr, twice_nat=1)
4557 self.nat44_add_static_mapping(local_host.ip4, self.nat_addr,
4558 local_port, external_port,
4559 proto=IP_PROTOS.tcp, out2in_only=1,
4560 twice_nat=1)
4561 self.vapi.nat44_interface_add_del_feature(self.pg4.sw_if_index)
4562 self.vapi.nat44_interface_add_del_feature(self.pg4.sw_if_index,
4563 is_inside=0)
4564
4565 # from client to service
4566 p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
4567 IP(src=remote_host.ip4, dst=self.nat_addr) /
4568 TCP(sport=12345, dport=external_port))
4569 self.pg4.add_stream(p)
4570 self.pg_enable_capture(self.pg_interfaces)
4571 self.pg_start()
4572 capture = self.pg4.get_capture(1)
4573 p = capture[0]
4574 try:
4575 ip = p[IP]
4576 tcp = p[TCP]
4577 self.assertEqual(ip.dst, local_host.ip4)
4578 self.assertEqual(ip.src, self.nat_addr)
4579 self.assertEqual(tcp.dport, local_port)
4580 self.assertNotEqual(tcp.sport, 12345)
4581 eh_port_in = tcp.sport
4582 self.assert_packet_checksums_valid(p)
4583 except:
4584 self.logger.error(ppp("Unexpected or invalid packet:", p))
4585 raise
4586
4587 # from service back to client
4588 p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
4589 IP(src=local_host.ip4, dst=self.nat_addr) /
4590 TCP(sport=local_port, dport=eh_port_in))
4591 self.pg4.add_stream(p)
4592 self.pg_enable_capture(self.pg_interfaces)
4593 self.pg_start()
4594 capture = self.pg4.get_capture(1)
4595 p = capture[0]
4596 try:
4597 ip = p[IP]
4598 tcp = p[TCP]
4599 self.assertEqual(ip.src, self.nat_addr)
4600 self.assertEqual(ip.dst, remote_host.ip4)
4601 self.assertEqual(tcp.sport, external_port)
4602 self.assertEqual(tcp.dport, 12345)
4603 self.assert_packet_checksums_valid(p)
4604 except:
4605 self.logger.error(ppp("Unexpected or invalid packet:", p))
4606 raise
4607
4608 def test_static_with_port_out2(self):
4609 """ 1:1 NAPT asymmetrical rule """
4610
4611 external_port = 80
4612 local_port = 8080
4613
4614 self.vapi.nat44_forwarding_enable_disable(1)
4615 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
4616 local_port, external_port,
4617 proto=IP_PROTOS.tcp, out2in_only=1)
4618 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4619 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4620 is_inside=0)
4621
4622 # from client to service
4623 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4624 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4625 TCP(sport=12345, dport=external_port))
4626 self.pg1.add_stream(p)
4627 self.pg_enable_capture(self.pg_interfaces)
4628 self.pg_start()
4629 capture = self.pg0.get_capture(1)
4630 p = capture[0]
4631 try:
4632 ip = p[IP]
4633 tcp = p[TCP]
4634 self.assertEqual(ip.dst, self.pg0.remote_ip4)
4635 self.assertEqual(tcp.dport, local_port)
4636 self.assert_packet_checksums_valid(p)
4637 except:
4638 self.logger.error(ppp("Unexpected or invalid packet:", p))
4639 raise
4640
4641 # ICMP error
4642 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
4643 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4644 ICMP(type=11) / capture[0][IP])
4645 self.pg0.add_stream(p)
4646 self.pg_enable_capture(self.pg_interfaces)
4647 self.pg_start()
4648 capture = self.pg1.get_capture(1)
4649 p = capture[0]
4650 try:
4651 self.assertEqual(p[IP].src, self.nat_addr)
4652 inner = p[IPerror]
4653 self.assertEqual(inner.dst, self.nat_addr)
4654 self.assertEqual(inner[TCPerror].dport, external_port)
4655 except:
4656 self.logger.error(ppp("Unexpected or invalid packet:", p))
4657 raise
4658
4659 # from service back to client
4660 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4661 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4662 TCP(sport=local_port, dport=12345))
4663 self.pg0.add_stream(p)
4664 self.pg_enable_capture(self.pg_interfaces)
4665 self.pg_start()
4666 capture = self.pg1.get_capture(1)
4667 p = capture[0]
4668 try:
4669 ip = p[IP]
4670 tcp = p[TCP]
4671 self.assertEqual(ip.src, self.nat_addr)
4672 self.assertEqual(tcp.sport, external_port)
4673 self.assert_packet_checksums_valid(p)
4674 except:
4675 self.logger.error(ppp("Unexpected or invalid packet:", p))
4676 raise
4677
4678 # ICMP error
4679 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
4680 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4681 ICMP(type=11) / capture[0][IP])
4682 self.pg1.add_stream(p)
4683 self.pg_enable_capture(self.pg_interfaces)
4684 self.pg_start()
4685 capture = self.pg0.get_capture(1)
4686 p = capture[0]
4687 try:
4688 self.assertEqual(p[IP].dst, self.pg0.remote_ip4)
4689 inner = p[IPerror]
4690 self.assertEqual(inner.src, self.pg0.remote_ip4)
4691 self.assertEqual(inner[TCPerror].sport, local_port)
4692 except:
4693 self.logger.error(ppp("Unexpected or invalid packet:", p))
4694 raise
4695
4696 # from client to server (no translation)
4697 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4698 IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
4699 TCP(sport=12346, dport=local_port))
4700 self.pg1.add_stream(p)
4701 self.pg_enable_capture(self.pg_interfaces)
4702 self.pg_start()
4703 capture = self.pg0.get_capture(1)
4704 p = capture[0]
4705 try:
4706 ip = p[IP]
4707 tcp = p[TCP]
4708 self.assertEqual(ip.dst, self.pg0.remote_ip4)
4709 self.assertEqual(tcp.dport, local_port)
4710 self.assert_packet_checksums_valid(p)
4711 except:
4712 self.logger.error(ppp("Unexpected or invalid packet:", p))
4713 raise
4714
4715 # from service back to client (no translation)
4716 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4717 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4718 TCP(sport=local_port, dport=12346))
4719 self.pg0.add_stream(p)
4720 self.pg_enable_capture(self.pg_interfaces)
4721 self.pg_start()
4722 capture = self.pg1.get_capture(1)
4723 p = capture[0]
4724 try:
4725 ip = p[IP]
4726 tcp = p[TCP]
4727 self.assertEqual(ip.src, self.pg0.remote_ip4)
4728 self.assertEqual(tcp.sport, local_port)
4729 self.assert_packet_checksums_valid(p)
4730 except:
4731 self.logger.error(ppp("Unexpected or invalid packet:", p))
4732 raise
4733
Matus Fabian235a47e2018-06-25 16:42:36 -07004734 def test_output_feature(self):
4735 """ NAT44 interface output feature (in2out postrouting) """
4736 self.vapi.nat44_forwarding_enable_disable(1)
4737 self.nat44_add_address(self.nat_addr)
4738 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
4739 is_inside=0)
4740 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
4741 is_inside=0)
4742
4743 # in2out
4744 pkts = self.create_stream_in(self.pg0, self.pg1)
4745 self.pg0.add_stream(pkts)
4746 self.pg_enable_capture(self.pg_interfaces)
4747 self.pg_start()
4748 capture = self.pg1.get_capture(len(pkts))
4749 self.verify_capture_out(capture)
4750
4751 # out2in
4752 pkts = self.create_stream_out(self.pg1)
4753 self.pg1.add_stream(pkts)
4754 self.pg_enable_capture(self.pg_interfaces)
4755 self.pg_start()
4756 capture = self.pg0.get_capture(len(pkts))
4757 self.verify_capture_in(capture, self.pg0)
4758
Matus Fabian8008d7c2018-07-09 01:34:20 -07004759 def test_multiple_vrf(self):
4760 """ Multiple VRF setup """
4761 external_addr = '1.2.3.4'
4762 external_port = 80
4763 local_port = 8080
4764 port = 0
4765
4766 self.vapi.nat44_forwarding_enable_disable(1)
4767 self.nat44_add_address(self.nat_addr)
4768 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4769 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
4770 is_inside=0)
4771 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
4772 is_inside=0)
4773 self.vapi.nat44_interface_add_del_feature(self.pg5.sw_if_index)
4774 self.vapi.nat44_interface_add_del_feature(self.pg5.sw_if_index,
4775 is_inside=0)
4776 self.vapi.nat44_interface_add_del_feature(self.pg6.sw_if_index,
4777 is_inside=0)
4778 self.nat44_add_static_mapping(self.pg5.remote_ip4, external_addr,
4779 local_port, external_port, vrf_id=1,
4780 proto=IP_PROTOS.tcp, out2in_only=1)
4781 self.nat44_add_static_mapping(
4782 self.pg0.remote_ip4, external_sw_if_index=self.pg0.sw_if_index,
4783 local_port=local_port, vrf_id=0, external_port=external_port,
4784 proto=IP_PROTOS.tcp, out2in_only=1)
4785
4786 # from client to service (both VRF1)
4787 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
4788 IP(src=self.pg6.remote_ip4, dst=external_addr) /
4789 TCP(sport=12345, dport=external_port))
4790 self.pg6.add_stream(p)
4791 self.pg_enable_capture(self.pg_interfaces)
4792 self.pg_start()
4793 capture = self.pg5.get_capture(1)
4794 p = capture[0]
4795 try:
4796 ip = p[IP]
4797 tcp = p[TCP]
4798 self.assertEqual(ip.dst, self.pg5.remote_ip4)
4799 self.assertEqual(tcp.dport, local_port)
4800 self.assert_packet_checksums_valid(p)
4801 except:
4802 self.logger.error(ppp("Unexpected or invalid packet:", p))
4803 raise
4804
4805 # from service back to client (both VRF1)
4806 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
4807 IP(src=self.pg5.remote_ip4, dst=self.pg6.remote_ip4) /
4808 TCP(sport=local_port, dport=12345))
4809 self.pg5.add_stream(p)
4810 self.pg_enable_capture(self.pg_interfaces)
4811 self.pg_start()
4812 capture = self.pg6.get_capture(1)
4813 p = capture[0]
4814 try:
4815 ip = p[IP]
4816 tcp = p[TCP]
4817 self.assertEqual(ip.src, external_addr)
4818 self.assertEqual(tcp.sport, external_port)
4819 self.assert_packet_checksums_valid(p)
4820 except:
4821 self.logger.error(ppp("Unexpected or invalid packet:", p))
4822 raise
4823
4824 # dynamic NAT from VRF1 to VRF0 (output-feature)
4825 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
4826 IP(src=self.pg5.remote_ip4, dst=self.pg1.remote_ip4) /
4827 TCP(sport=2345, dport=22))
4828 self.pg5.add_stream(p)
4829 self.pg_enable_capture(self.pg_interfaces)
4830 self.pg_start()
4831 capture = self.pg1.get_capture(1)
4832 p = capture[0]
4833 try:
4834 ip = p[IP]
4835 tcp = p[TCP]
4836 self.assertEqual(ip.src, self.nat_addr)
4837 self.assertNotEqual(tcp.sport, 2345)
4838 self.assert_packet_checksums_valid(p)
4839 port = tcp.sport
4840 except:
4841 self.logger.error(ppp("Unexpected or invalid packet:", p))
4842 raise
4843
4844 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4845 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4846 TCP(sport=22, dport=port))
4847 self.pg1.add_stream(p)
4848 self.pg_enable_capture(self.pg_interfaces)
4849 self.pg_start()
4850 capture = self.pg5.get_capture(1)
4851 p = capture[0]
4852 try:
4853 ip = p[IP]
4854 tcp = p[TCP]
4855 self.assertEqual(ip.dst, self.pg5.remote_ip4)
4856 self.assertEqual(tcp.dport, 2345)
4857 self.assert_packet_checksums_valid(p)
4858 except:
4859 self.logger.error(ppp("Unexpected or invalid packet:", p))
4860 raise
4861
4862 # from client VRF1 to service VRF0
4863 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
4864 IP(src=self.pg6.remote_ip4, dst=self.pg0.local_ip4) /
4865 TCP(sport=12346, dport=external_port))
4866 self.pg6.add_stream(p)
4867 self.pg_enable_capture(self.pg_interfaces)
4868 self.pg_start()
4869 capture = self.pg0.get_capture(1)
4870 p = capture[0]
4871 try:
4872 ip = p[IP]
4873 tcp = p[TCP]
4874 self.assertEqual(ip.dst, self.pg0.remote_ip4)
4875 self.assertEqual(tcp.dport, local_port)
4876 self.assert_packet_checksums_valid(p)
4877 except:
4878 self.logger.error(ppp("Unexpected or invalid packet:", p))
4879 raise
4880
4881 # from service VRF0 back to client VRF1
4882 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4883 IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
4884 TCP(sport=local_port, dport=12346))
4885 self.pg0.add_stream(p)
4886 self.pg_enable_capture(self.pg_interfaces)
4887 self.pg_start()
4888 capture = self.pg6.get_capture(1)
4889 p = capture[0]
4890 try:
4891 ip = p[IP]
4892 tcp = p[TCP]
4893 self.assertEqual(ip.src, self.pg0.local_ip4)
4894 self.assertEqual(tcp.sport, external_port)
4895 self.assert_packet_checksums_valid(p)
4896 except:
4897 self.logger.error(ppp("Unexpected or invalid packet:", p))
4898 raise
4899
4900 # from client VRF0 to service VRF1
4901 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4902 IP(src=self.pg0.remote_ip4, dst=external_addr) /
4903 TCP(sport=12347, dport=external_port))
4904 self.pg0.add_stream(p)
4905 self.pg_enable_capture(self.pg_interfaces)
4906 self.pg_start()
4907 capture = self.pg5.get_capture(1)
4908 p = capture[0]
4909 try:
4910 ip = p[IP]
4911 tcp = p[TCP]
4912 self.assertEqual(ip.dst, self.pg5.remote_ip4)
4913 self.assertEqual(tcp.dport, local_port)
4914 self.assert_packet_checksums_valid(p)
4915 except:
4916 self.logger.error(ppp("Unexpected or invalid packet:", p))
4917 raise
4918
4919 # from service VRF1 back to client VRF0
4920 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
4921 IP(src=self.pg5.remote_ip4, dst=self.pg0.remote_ip4) /
4922 TCP(sport=local_port, dport=12347))
4923 self.pg5.add_stream(p)
4924 self.pg_enable_capture(self.pg_interfaces)
4925 self.pg_start()
4926 capture = self.pg0.get_capture(1)
4927 p = capture[0]
4928 try:
4929 ip = p[IP]
4930 tcp = p[TCP]
4931 self.assertEqual(ip.src, external_addr)
4932 self.assertEqual(tcp.sport, external_port)
4933 self.assert_packet_checksums_valid(p)
4934 except:
4935 self.logger.error(ppp("Unexpected or invalid packet:", p))
4936 raise
4937
4938 # from client to server (both VRF1, no translation)
4939 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
4940 IP(src=self.pg6.remote_ip4, dst=self.pg5.remote_ip4) /
4941 TCP(sport=12348, dport=local_port))
4942 self.pg6.add_stream(p)
4943 self.pg_enable_capture(self.pg_interfaces)
4944 self.pg_start()
4945 capture = self.pg5.get_capture(1)
4946 p = capture[0]
4947 try:
4948 ip = p[IP]
4949 tcp = p[TCP]
4950 self.assertEqual(ip.dst, self.pg5.remote_ip4)
4951 self.assertEqual(tcp.dport, local_port)
4952 self.assert_packet_checksums_valid(p)
4953 except:
4954 self.logger.error(ppp("Unexpected or invalid packet:", p))
4955 raise
4956
4957 # from server back to client (both VRF1, no translation)
4958 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
4959 IP(src=self.pg5.remote_ip4, dst=self.pg6.remote_ip4) /
4960 TCP(sport=local_port, dport=12348))
4961 self.pg5.add_stream(p)
4962 self.pg_enable_capture(self.pg_interfaces)
4963 self.pg_start()
4964 capture = self.pg6.get_capture(1)
4965 p = capture[0]
4966 try:
4967 ip = p[IP]
4968 tcp = p[TCP]
4969 self.assertEqual(ip.src, self.pg5.remote_ip4)
4970 self.assertEqual(tcp.sport, local_port)
4971 self.assert_packet_checksums_valid(p)
4972 except:
4973 self.logger.error(ppp("Unexpected or invalid packet:", p))
4974 raise
4975
4976 # from client VRF1 to server VRF0 (no translation)
4977 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4978 IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
4979 TCP(sport=local_port, dport=12349))
4980 self.pg0.add_stream(p)
4981 self.pg_enable_capture(self.pg_interfaces)
4982 self.pg_start()
4983 capture = self.pg6.get_capture(1)
4984 p = capture[0]
4985 try:
4986 ip = p[IP]
4987 tcp = p[TCP]
4988 self.assertEqual(ip.src, self.pg0.remote_ip4)
4989 self.assertEqual(tcp.sport, local_port)
4990 self.assert_packet_checksums_valid(p)
4991 except:
4992 self.logger.error(ppp("Unexpected or invalid packet:", p))
4993 raise
4994
4995 # from server VRF0 back to client VRF1 (no translation)
4996 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4997 IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
4998 TCP(sport=local_port, dport=12349))
4999 self.pg0.add_stream(p)
5000 self.pg_enable_capture(self.pg_interfaces)
5001 self.pg_start()
5002 capture = self.pg6.get_capture(1)
5003 p = capture[0]
5004 try:
5005 ip = p[IP]
5006 tcp = p[TCP]
5007 self.assertEqual(ip.src, self.pg0.remote_ip4)
5008 self.assertEqual(tcp.sport, local_port)
5009 self.assert_packet_checksums_valid(p)
5010 except:
5011 self.logger.error(ppp("Unexpected or invalid packet:", p))
5012 raise
5013
5014 # from client VRF0 to server VRF1 (no translation)
5015 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5016 IP(src=self.pg0.remote_ip4, dst=self.pg5.remote_ip4) /
5017 TCP(sport=12344, dport=local_port))
5018 self.pg0.add_stream(p)
5019 self.pg_enable_capture(self.pg_interfaces)
5020 self.pg_start()
5021 capture = self.pg5.get_capture(1)
5022 p = capture[0]
5023 try:
5024 ip = p[IP]
5025 tcp = p[TCP]
5026 self.assertEqual(ip.dst, self.pg5.remote_ip4)
5027 self.assertEqual(tcp.dport, local_port)
5028 self.assert_packet_checksums_valid(p)
5029 except:
5030 self.logger.error(ppp("Unexpected or invalid packet:", p))
5031 raise
5032
5033 # from server VRF1 back to client VRF0 (no translation)
5034 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
5035 IP(src=self.pg5.remote_ip4, dst=self.pg0.remote_ip4) /
5036 TCP(sport=local_port, dport=12344))
5037 self.pg5.add_stream(p)
5038 self.pg_enable_capture(self.pg_interfaces)
5039 self.pg_start()
5040 capture = self.pg0.get_capture(1)
5041 p = capture[0]
5042 try:
5043 ip = p[IP]
5044 tcp = p[TCP]
5045 self.assertEqual(ip.src, self.pg5.remote_ip4)
5046 self.assertEqual(tcp.sport, local_port)
5047 self.assert_packet_checksums_valid(p)
5048 except:
5049 self.logger.error(ppp("Unexpected or invalid packet:", p))
5050 raise
5051
Matus Fabian878c6462018-08-23 00:33:35 -07005052 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
5053 def test_session_timeout(self):
5054 """ NAT44 session timeouts """
5055 self.nat44_add_address(self.nat_addr)
5056 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5057 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
5058 is_inside=0)
5059 self.vapi.nat_set_timeouts(icmp=5)
5060
5061 max_sessions = 1000
5062 pkts = []
5063 for i in range(0, max_sessions):
5064 src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
5065 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5066 IP(src=src, dst=self.pg1.remote_ip4) /
5067 ICMP(id=1025, type='echo-request'))
5068 pkts.append(p)
5069 self.pg0.add_stream(pkts)
5070 self.pg_enable_capture(self.pg_interfaces)
5071 self.pg_start()
5072 self.pg1.get_capture(max_sessions)
5073
5074 sleep(10)
5075
5076 pkts = []
5077 for i in range(0, max_sessions):
5078 src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
5079 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5080 IP(src=src, dst=self.pg1.remote_ip4) /
5081 ICMP(id=1026, type='echo-request'))
5082 pkts.append(p)
5083 self.pg0.add_stream(pkts)
5084 self.pg_enable_capture(self.pg_interfaces)
5085 self.pg_start()
5086 self.pg1.get_capture(max_sessions)
5087
5088 nsessions = 0
5089 users = self.vapi.nat44_user_dump()
5090 for user in users:
5091 nsessions = nsessions + user.nsessions
5092 self.assertLess(nsessions, 2 * max_sessions)
5093
5094 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
5095 def test_session_limit_per_user(self):
5096 """ Maximum sessions per user limit """
5097 self.nat44_add_address(self.nat_addr)
5098 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5099 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
5100 is_inside=0)
5101 self.vapi.set_ipfix_exporter(collector_address=self.pg2.remote_ip4n,
5102 src_address=self.pg2.local_ip4n,
5103 path_mtu=512,
5104 template_interval=10)
5105
5106 # get maximum number of translations per user
5107 nat44_config = self.vapi.nat_show_config()
5108
5109 pkts = []
5110 for port in range(0, nat44_config.max_translations_per_user):
5111 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5112 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5113 UDP(sport=1025 + port, dport=1025 + port))
5114 pkts.append(p)
5115
5116 self.pg0.add_stream(pkts)
5117 self.pg_enable_capture(self.pg_interfaces)
5118 self.pg_start()
5119 capture = self.pg1.get_capture(len(pkts))
5120
5121 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
5122 src_port=self.ipfix_src_port)
5123
5124 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5125 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5126 UDP(sport=3001, dport=3002))
5127 self.pg0.add_stream(p)
5128 self.pg_enable_capture(self.pg_interfaces)
5129 self.pg_start()
5130 capture = self.pg1.assert_nothing_captured()
5131
5132 # verify IPFIX logging
5133 self.vapi.cli("ipfix flush") # FIXME this should be an API call
5134 sleep(1)
5135 capture = self.pg2.get_capture(10)
5136 ipfix = IPFIXDecoder()
5137 # first load template
5138 for p in capture:
5139 self.assertTrue(p.haslayer(IPFIX))
5140 if p.haslayer(Template):
5141 ipfix.add_template(p.getlayer(Template))
5142 # verify events in data set
5143 for p in capture:
5144 if p.haslayer(Data):
5145 data = ipfix.decode_data_set(p.getlayer(Set))
5146 self.verify_ipfix_max_entries_per_user(
5147 data,
5148 nat44_config.max_translations_per_user,
5149 self.pg0.remote_ip4n)
5150
Matus Fabiande886752016-12-07 03:38:19 -08005151 def tearDown(self):
Matus Fabiana6110b62018-06-13 05:39:07 -07005152 super(TestNAT44EndpointDependent, self).tearDown()
Matus Fabiande886752016-12-07 03:38:19 -08005153 if not self.vpp_dead:
Matus Fabian82119542018-01-25 01:13:22 -08005154 self.logger.info(self.vapi.cli("show nat44 addresses"))
5155 self.logger.info(self.vapi.cli("show nat44 interfaces"))
5156 self.logger.info(self.vapi.cli("show nat44 static mappings"))
5157 self.logger.info(self.vapi.cli("show nat44 interface address"))
5158 self.logger.info(self.vapi.cli("show nat44 sessions detail"))
Matus Fabian229c1aa2018-05-28 04:09:52 -07005159 self.logger.info(self.vapi.cli("show nat44 hash tables detail"))
Matus Fabian878c6462018-08-23 00:33:35 -07005160 self.logger.info(self.vapi.cli("show nat timeouts"))
Matus Fabian2ba92e32017-08-21 07:05:03 -07005161 self.clear_nat44()
Matus Fabian229c1aa2018-05-28 04:09:52 -07005162 self.vapi.cli("clear logging")
Matus Fabiande886752016-12-07 03:38:19 -08005163
Matus Fabianeea28d72017-01-13 04:15:54 -08005164
Juraj Slobodacba69362017-12-19 02:09:32 +01005165class TestNAT44Out2InDPO(MethodHolder):
5166 """ NAT44 Test Cases using out2in DPO """
5167
5168 @classmethod
5169 def setUpConstants(cls):
5170 super(TestNAT44Out2InDPO, cls).setUpConstants()
5171 cls.vpp_cmdline.extend(["nat", "{", "out2in dpo", "}"])
5172
5173 @classmethod
5174 def setUpClass(cls):
5175 super(TestNAT44Out2InDPO, cls).setUpClass()
Matus Fabian229c1aa2018-05-28 04:09:52 -07005176 cls.vapi.cli("set log class nat level debug")
Juraj Slobodacba69362017-12-19 02:09:32 +01005177
5178 try:
5179 cls.tcp_port_in = 6303
5180 cls.tcp_port_out = 6303
5181 cls.udp_port_in = 6304
5182 cls.udp_port_out = 6304
5183 cls.icmp_id_in = 6305
5184 cls.icmp_id_out = 6305
5185 cls.nat_addr = '10.0.0.3'
5186 cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
5187 cls.dst_ip4 = '192.168.70.1'
5188
5189 cls.create_pg_interfaces(range(2))
5190
5191 cls.pg0.admin_up()
5192 cls.pg0.config_ip4()
5193 cls.pg0.resolve_arp()
5194
5195 cls.pg1.admin_up()
5196 cls.pg1.config_ip6()
5197 cls.pg1.resolve_ndp()
5198
5199 cls.vapi.ip_add_del_route(is_ipv6=True, dst_address='\x00'*16,
5200 dst_address_length=0,
5201 next_hop_address=cls.pg1.remote_ip6n,
5202 next_hop_sw_if_index=cls.pg1.sw_if_index)
5203
5204 except Exception:
5205 super(TestNAT44Out2InDPO, cls).tearDownClass()
5206 raise
5207
5208 def configure_xlat(self):
5209 self.dst_ip6_pfx = '1:2:3::'
5210 self.dst_ip6_pfx_n = socket.inet_pton(socket.AF_INET6,
5211 self.dst_ip6_pfx)
5212 self.dst_ip6_pfx_len = 96
5213 self.src_ip6_pfx = '4:5:6::'
5214 self.src_ip6_pfx_n = socket.inet_pton(socket.AF_INET6,
5215 self.src_ip6_pfx)
5216 self.src_ip6_pfx_len = 96
5217 self.vapi.map_add_domain(self.dst_ip6_pfx_n, self.dst_ip6_pfx_len,
5218 self.src_ip6_pfx_n, self.src_ip6_pfx_len,
5219 '\x00\x00\x00\x00', 0, is_translation=1,
5220 is_rfc6052=1)
5221
5222 def test_464xlat_ce(self):
5223 """ Test 464XLAT CE with NAT44 """
5224
Matus Fabian69ce30d2018-08-22 01:27:10 -07005225 nat_config = self.vapi.nat_show_config()
5226 self.assertEqual(1, nat_config.out2in_dpo)
5227
Juraj Slobodacba69362017-12-19 02:09:32 +01005228 self.configure_xlat()
5229
5230 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5231 self.vapi.nat44_add_del_address_range(self.nat_addr_n, self.nat_addr_n)
5232
5233 out_src_ip6 = self.compose_ip6(self.dst_ip4, self.dst_ip6_pfx,
5234 self.dst_ip6_pfx_len)
5235 out_dst_ip6 = self.compose_ip6(self.nat_addr, self.src_ip6_pfx,
5236 self.src_ip6_pfx_len)
5237
5238 try:
5239 pkts = self.create_stream_in(self.pg0, self.pg1, self.dst_ip4)
5240 self.pg0.add_stream(pkts)
5241 self.pg_enable_capture(self.pg_interfaces)
5242 self.pg_start()
5243 capture = self.pg1.get_capture(len(pkts))
5244 self.verify_capture_out_ip6(capture, nat_ip=out_dst_ip6,
5245 dst_ip=out_src_ip6)
5246
5247 pkts = self.create_stream_out_ip6(self.pg1, out_src_ip6,
5248 out_dst_ip6)
5249 self.pg1.add_stream(pkts)
5250 self.pg_enable_capture(self.pg_interfaces)
5251 self.pg_start()
5252 capture = self.pg0.get_capture(len(pkts))
5253 self.verify_capture_in(capture, self.pg0)
5254 finally:
5255 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
5256 is_add=0)
5257 self.vapi.nat44_add_del_address_range(self.nat_addr_n,
5258 self.nat_addr_n, is_add=0)
5259
5260 def test_464xlat_ce_no_nat(self):
5261 """ Test 464XLAT CE without NAT44 """
5262
5263 self.configure_xlat()
5264
5265 out_src_ip6 = self.compose_ip6(self.dst_ip4, self.dst_ip6_pfx,
5266 self.dst_ip6_pfx_len)
5267 out_dst_ip6 = self.compose_ip6(self.pg0.remote_ip4, self.src_ip6_pfx,
5268 self.src_ip6_pfx_len)
5269
5270 pkts = self.create_stream_in(self.pg0, self.pg1, self.dst_ip4)
5271 self.pg0.add_stream(pkts)
5272 self.pg_enable_capture(self.pg_interfaces)
5273 self.pg_start()
5274 capture = self.pg1.get_capture(len(pkts))
5275 self.verify_capture_out_ip6(capture, dst_ip=out_src_ip6,
5276 nat_ip=out_dst_ip6, same_port=True)
5277
5278 pkts = self.create_stream_out_ip6(self.pg1, out_src_ip6, out_dst_ip6)
5279 self.pg1.add_stream(pkts)
5280 self.pg_enable_capture(self.pg_interfaces)
5281 self.pg_start()
5282 capture = self.pg0.get_capture(len(pkts))
5283 self.verify_capture_in(capture, self.pg0)
5284
5285
Martin Gálikd7f75cd2017-03-27 06:02:47 -07005286class TestDeterministicNAT(MethodHolder):
Matus Fabian066f0342017-02-10 03:48:01 -08005287 """ Deterministic NAT Test Cases """
5288
5289 @classmethod
5290 def setUpConstants(cls):
5291 super(TestDeterministicNAT, cls).setUpConstants()
Matus Fabian2ba92e32017-08-21 07:05:03 -07005292 cls.vpp_cmdline.extend(["nat", "{", "deterministic", "}"])
Matus Fabian066f0342017-02-10 03:48:01 -08005293
5294 @classmethod
5295 def setUpClass(cls):
5296 super(TestDeterministicNAT, cls).setUpClass()
Matus Fabian229c1aa2018-05-28 04:09:52 -07005297 cls.vapi.cli("set log class nat level debug")
Matus Fabian066f0342017-02-10 03:48:01 -08005298
5299 try:
Martin Gálik977c1cb2017-03-30 23:21:51 -07005300 cls.tcp_port_in = 6303
Martin Gálik9806eae2017-04-25 01:25:08 -07005301 cls.tcp_external_port = 6303
Martin Gálik977c1cb2017-03-30 23:21:51 -07005302 cls.udp_port_in = 6304
Martin Gálik9806eae2017-04-25 01:25:08 -07005303 cls.udp_external_port = 6304
Martin Gálik977c1cb2017-03-30 23:21:51 -07005304 cls.icmp_id_in = 6305
Matus Fabian2ba92e32017-08-21 07:05:03 -07005305 cls.nat_addr = '10.0.0.3'
Martin Gálik977c1cb2017-03-30 23:21:51 -07005306
Matus Fabian2f2db1c2017-04-18 05:29:59 -07005307 cls.create_pg_interfaces(range(3))
Matus Fabian066f0342017-02-10 03:48:01 -08005308 cls.interfaces = list(cls.pg_interfaces)
5309
5310 for i in cls.interfaces:
5311 i.admin_up()
5312 i.config_ip4()
5313 i.resolve_arp()
5314
Martin Gálik977c1cb2017-03-30 23:21:51 -07005315 cls.pg0.generate_remote_hosts(2)
5316 cls.pg0.configure_ipv4_neighbors()
5317
Matus Fabian066f0342017-02-10 03:48:01 -08005318 except Exception:
5319 super(TestDeterministicNAT, cls).tearDownClass()
5320 raise
5321
Martin Gálik977c1cb2017-03-30 23:21:51 -07005322 def create_stream_in(self, in_if, out_if, ttl=64):
5323 """
5324 Create packet stream for inside network
5325
5326 :param in_if: Inside interface
5327 :param out_if: Outside interface
5328 :param ttl: TTL of generated packets
5329 """
5330 pkts = []
5331 # TCP
5332 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
5333 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
Martin Gálik9806eae2017-04-25 01:25:08 -07005334 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07005335 pkts.append(p)
5336
5337 # UDP
5338 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
5339 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
Martin Gálik9806eae2017-04-25 01:25:08 -07005340 UDP(sport=self.udp_port_in, dport=self.udp_external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07005341 pkts.append(p)
5342
5343 # ICMP
5344 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
5345 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
5346 ICMP(id=self.icmp_id_in, type='echo-request'))
5347 pkts.append(p)
5348
5349 return pkts
5350
5351 def create_stream_out(self, out_if, dst_ip=None, ttl=64):
5352 """
5353 Create packet stream for outside network
5354
5355 :param out_if: Outside interface
Matus Fabian2ba92e32017-08-21 07:05:03 -07005356 :param dst_ip: Destination IP address (Default use global NAT address)
Martin Gálik977c1cb2017-03-30 23:21:51 -07005357 :param ttl: TTL of generated packets
5358 """
5359 if dst_ip is None:
Matus Fabian2ba92e32017-08-21 07:05:03 -07005360 dst_ip = self.nat_addr
Martin Gálik977c1cb2017-03-30 23:21:51 -07005361 pkts = []
5362 # TCP
5363 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
5364 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Martin Gálik9806eae2017-04-25 01:25:08 -07005365 TCP(dport=self.tcp_port_out, sport=self.tcp_external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07005366 pkts.append(p)
5367
5368 # UDP
5369 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
5370 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Martin Gálik9806eae2017-04-25 01:25:08 -07005371 UDP(dport=self.udp_port_out, sport=self.udp_external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07005372 pkts.append(p)
5373
5374 # ICMP
5375 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
5376 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
5377 ICMP(id=self.icmp_external_id, type='echo-reply'))
5378 pkts.append(p)
5379
5380 return pkts
5381
Matus Fabian05ca4a32018-09-04 23:45:13 -07005382 def verify_capture_out(self, capture, nat_ip=None):
Martin Gálik977c1cb2017-03-30 23:21:51 -07005383 """
5384 Verify captured packets on outside network
5385
5386 :param capture: Captured packets
Matus Fabian2ba92e32017-08-21 07:05:03 -07005387 :param nat_ip: Translated IP address (Default use global NAT address)
Martin Gálik977c1cb2017-03-30 23:21:51 -07005388 :param same_port: Sorce port number is not translated (Default False)
Martin Gálik977c1cb2017-03-30 23:21:51 -07005389 """
5390 if nat_ip is None:
Matus Fabian2ba92e32017-08-21 07:05:03 -07005391 nat_ip = self.nat_addr
Martin Gálik977c1cb2017-03-30 23:21:51 -07005392 for packet in capture:
5393 try:
5394 self.assertEqual(packet[IP].src, nat_ip)
5395 if packet.haslayer(TCP):
Martin Gálik9806eae2017-04-25 01:25:08 -07005396 self.tcp_port_out = packet[TCP].sport
Martin Gálik977c1cb2017-03-30 23:21:51 -07005397 elif packet.haslayer(UDP):
Martin Gálik9806eae2017-04-25 01:25:08 -07005398 self.udp_port_out = packet[UDP].sport
Martin Gálik977c1cb2017-03-30 23:21:51 -07005399 else:
5400 self.icmp_external_id = packet[ICMP].id
5401 except:
5402 self.logger.error(ppp("Unexpected or invalid packet "
5403 "(outside network):", packet))
5404 raise
5405
Matus Fabian066f0342017-02-10 03:48:01 -08005406 def test_deterministic_mode(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07005407 """ NAT plugin run deterministic mode """
Matus Fabian066f0342017-02-10 03:48:01 -08005408 in_addr = '172.16.255.0'
5409 out_addr = '172.17.255.50'
5410 in_addr_t = '172.16.255.20'
5411 in_addr_n = socket.inet_aton(in_addr)
5412 out_addr_n = socket.inet_aton(out_addr)
5413 in_addr_t_n = socket.inet_aton(in_addr_t)
5414 in_plen = 24
5415 out_plen = 32
5416
Matus Fabian2ba92e32017-08-21 07:05:03 -07005417 nat_config = self.vapi.nat_show_config()
5418 self.assertEqual(1, nat_config.deterministic)
Matus Fabian066f0342017-02-10 03:48:01 -08005419
Matus Fabian2ba92e32017-08-21 07:05:03 -07005420 self.vapi.nat_det_add_del_map(in_addr_n, in_plen, out_addr_n, out_plen)
Matus Fabian066f0342017-02-10 03:48:01 -08005421
Matus Fabian2ba92e32017-08-21 07:05:03 -07005422 rep1 = self.vapi.nat_det_forward(in_addr_t_n)
Matus Fabian066f0342017-02-10 03:48:01 -08005423 self.assertEqual(rep1.out_addr[:4], out_addr_n)
Matus Fabian2ba92e32017-08-21 07:05:03 -07005424 rep2 = self.vapi.nat_det_reverse(out_addr_n, rep1.out_port_hi)
Matus Fabian066f0342017-02-10 03:48:01 -08005425 self.assertEqual(rep2.in_addr[:4], in_addr_t_n)
5426
Matus Fabian2ba92e32017-08-21 07:05:03 -07005427 deterministic_mappings = self.vapi.nat_det_map_dump()
Martin17a75cb2017-03-08 05:53:20 -08005428 self.assertEqual(len(deterministic_mappings), 1)
5429 dsm = deterministic_mappings[0]
5430 self.assertEqual(in_addr_n, dsm.in_addr[:4])
5431 self.assertEqual(in_plen, dsm.in_plen)
5432 self.assertEqual(out_addr_n, dsm.out_addr[:4])
5433 self.assertEqual(out_plen, dsm.out_plen)
5434
Matus Fabian2ba92e32017-08-21 07:05:03 -07005435 self.clear_nat_det()
5436 deterministic_mappings = self.vapi.nat_det_map_dump()
Martinb616e9f2017-03-14 02:25:45 -07005437 self.assertEqual(len(deterministic_mappings), 0)
5438
Matus Fabian6a0946f2017-04-12 03:36:13 -07005439 def test_set_timeouts(self):
5440 """ Set deterministic NAT timeouts """
Matus Fabian878c6462018-08-23 00:33:35 -07005441 timeouts_before = self.vapi.nat_get_timeouts()
Matus Fabian6a0946f2017-04-12 03:36:13 -07005442
Matus Fabian878c6462018-08-23 00:33:35 -07005443 self.vapi.nat_set_timeouts(timeouts_before.udp + 10,
5444 timeouts_before.tcp_established + 10,
5445 timeouts_before.tcp_transitory + 10,
5446 timeouts_before.icmp + 10)
Matus Fabian6a0946f2017-04-12 03:36:13 -07005447
Matus Fabian878c6462018-08-23 00:33:35 -07005448 timeouts_after = self.vapi.nat_get_timeouts()
Matus Fabian6a0946f2017-04-12 03:36:13 -07005449
5450 self.assertNotEqual(timeouts_before.udp, timeouts_after.udp)
5451 self.assertNotEqual(timeouts_before.icmp, timeouts_after.icmp)
5452 self.assertNotEqual(timeouts_before.tcp_established,
5453 timeouts_after.tcp_established)
5454 self.assertNotEqual(timeouts_before.tcp_transitory,
5455 timeouts_after.tcp_transitory)
5456
Martin Gálik977c1cb2017-03-30 23:21:51 -07005457 def test_det_in(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07005458 """ Deterministic NAT translation test (TCP, UDP, ICMP) """
Martin Gálik977c1cb2017-03-30 23:21:51 -07005459
5460 nat_ip = "10.0.0.10"
Martin Gálik977c1cb2017-03-30 23:21:51 -07005461
Matus Fabian2ba92e32017-08-21 07:05:03 -07005462 self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
5463 32,
5464 socket.inet_aton(nat_ip),
5465 32)
5466 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5467 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
5468 is_inside=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07005469
5470 # in2out
5471 pkts = self.create_stream_in(self.pg0, self.pg1)
5472 self.pg0.add_stream(pkts)
5473 self.pg_enable_capture(self.pg_interfaces)
5474 self.pg_start()
5475 capture = self.pg1.get_capture(len(pkts))
5476 self.verify_capture_out(capture, nat_ip)
5477
5478 # out2in
5479 pkts = self.create_stream_out(self.pg1, nat_ip)
5480 self.pg1.add_stream(pkts)
5481 self.pg_enable_capture(self.pg_interfaces)
5482 self.pg_start()
5483 capture = self.pg0.get_capture(len(pkts))
5484 self.verify_capture_in(capture, self.pg0)
5485
Martin Gálik9806eae2017-04-25 01:25:08 -07005486 # session dump test
Matus Fabian2ba92e32017-08-21 07:05:03 -07005487 sessions = self.vapi.nat_det_session_dump(self.pg0.remote_ip4n)
Martin Gálik9806eae2017-04-25 01:25:08 -07005488 self.assertEqual(len(sessions), 3)
5489
5490 # TCP session
5491 s = sessions[0]
5492 self.assertEqual(s.ext_addr[:4], self.pg1.remote_ip4n)
5493 self.assertEqual(s.in_port, self.tcp_port_in)
5494 self.assertEqual(s.out_port, self.tcp_port_out)
5495 self.assertEqual(s.ext_port, self.tcp_external_port)
5496
5497 # UDP session
5498 s = sessions[1]
5499 self.assertEqual(s.ext_addr[:4], self.pg1.remote_ip4n)
5500 self.assertEqual(s.in_port, self.udp_port_in)
5501 self.assertEqual(s.out_port, self.udp_port_out)
5502 self.assertEqual(s.ext_port, self.udp_external_port)
5503
5504 # ICMP session
5505 s = sessions[2]
5506 self.assertEqual(s.ext_addr[:4], self.pg1.remote_ip4n)
5507 self.assertEqual(s.in_port, self.icmp_id_in)
5508 self.assertEqual(s.out_port, self.icmp_external_id)
5509
Martin Gálik977c1cb2017-03-30 23:21:51 -07005510 def test_multiple_users(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07005511 """ Deterministic NAT multiple users """
Martin Gálik977c1cb2017-03-30 23:21:51 -07005512
5513 nat_ip = "10.0.0.10"
5514 port_in = 80
Martin Gálik9806eae2017-04-25 01:25:08 -07005515 external_port = 6303
Martin Gálik977c1cb2017-03-30 23:21:51 -07005516
5517 host0 = self.pg0.remote_hosts[0]
5518 host1 = self.pg0.remote_hosts[1]
5519
Matus Fabian2ba92e32017-08-21 07:05:03 -07005520 self.vapi.nat_det_add_del_map(host0.ip4n,
5521 24,
5522 socket.inet_aton(nat_ip),
5523 32)
5524 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5525 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
5526 is_inside=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07005527
5528 # host0 to out
5529 p = (Ether(src=host0.mac, dst=self.pg0.local_mac) /
5530 IP(src=host0.ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07005531 TCP(sport=port_in, dport=external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07005532 self.pg0.add_stream(p)
5533 self.pg_enable_capture(self.pg_interfaces)
5534 self.pg_start()
5535 capture = self.pg1.get_capture(1)
5536 p = capture[0]
5537 try:
5538 ip = p[IP]
5539 tcp = p[TCP]
5540 self.assertEqual(ip.src, nat_ip)
5541 self.assertEqual(ip.dst, self.pg1.remote_ip4)
Martin Gálik9806eae2017-04-25 01:25:08 -07005542 self.assertEqual(tcp.dport, external_port)
5543 port_out0 = tcp.sport
Martin Gálik977c1cb2017-03-30 23:21:51 -07005544 except:
5545 self.logger.error(ppp("Unexpected or invalid packet:", p))
5546 raise
5547
5548 # host1 to out
5549 p = (Ether(src=host1.mac, dst=self.pg0.local_mac) /
5550 IP(src=host1.ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07005551 TCP(sport=port_in, dport=external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07005552 self.pg0.add_stream(p)
5553 self.pg_enable_capture(self.pg_interfaces)
5554 self.pg_start()
5555 capture = self.pg1.get_capture(1)
5556 p = capture[0]
5557 try:
5558 ip = p[IP]
5559 tcp = p[TCP]
5560 self.assertEqual(ip.src, nat_ip)
5561 self.assertEqual(ip.dst, self.pg1.remote_ip4)
Martin Gálik9806eae2017-04-25 01:25:08 -07005562 self.assertEqual(tcp.dport, external_port)
5563 port_out1 = tcp.sport
Martin Gálik977c1cb2017-03-30 23:21:51 -07005564 except:
5565 self.logger.error(ppp("Unexpected or invalid packet:", p))
5566 raise
5567
Matus Fabian2ba92e32017-08-21 07:05:03 -07005568 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07005569 self.assertEqual(1, len(dms))
5570 self.assertEqual(2, dms[0].ses_num)
5571
5572 # out to host0
5573 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5574 IP(src=self.pg1.remote_ip4, dst=nat_ip) /
Martin Gálik9806eae2017-04-25 01:25:08 -07005575 TCP(sport=external_port, dport=port_out0))
Martin Gálik977c1cb2017-03-30 23:21:51 -07005576 self.pg1.add_stream(p)
5577 self.pg_enable_capture(self.pg_interfaces)
5578 self.pg_start()
5579 capture = self.pg0.get_capture(1)
5580 p = capture[0]
5581 try:
5582 ip = p[IP]
5583 tcp = p[TCP]
5584 self.assertEqual(ip.src, self.pg1.remote_ip4)
5585 self.assertEqual(ip.dst, host0.ip4)
5586 self.assertEqual(tcp.dport, port_in)
Martin Gálik9806eae2017-04-25 01:25:08 -07005587 self.assertEqual(tcp.sport, external_port)
Martin Gálik977c1cb2017-03-30 23:21:51 -07005588 except:
5589 self.logger.error(ppp("Unexpected or invalid packet:", p))
5590 raise
5591
5592 # out to host1
5593 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5594 IP(src=self.pg1.remote_ip4, dst=nat_ip) /
Martin Gálik9806eae2017-04-25 01:25:08 -07005595 TCP(sport=external_port, dport=port_out1))
Martin Gálik977c1cb2017-03-30 23:21:51 -07005596 self.pg1.add_stream(p)
5597 self.pg_enable_capture(self.pg_interfaces)
5598 self.pg_start()
5599 capture = self.pg0.get_capture(1)
5600 p = capture[0]
5601 try:
5602 ip = p[IP]
5603 tcp = p[TCP]
5604 self.assertEqual(ip.src, self.pg1.remote_ip4)
5605 self.assertEqual(ip.dst, host1.ip4)
5606 self.assertEqual(tcp.dport, port_in)
Martin Gálik9806eae2017-04-25 01:25:08 -07005607 self.assertEqual(tcp.sport, external_port)
Martin Gálik977c1cb2017-03-30 23:21:51 -07005608 except:
5609 self.logger.error(ppp("Unexpected or invalid packet", p))
5610 raise
5611
Martin Gálik6bc8c642017-04-19 01:12:27 -07005612 # session close api test
Matus Fabian2ba92e32017-08-21 07:05:03 -07005613 self.vapi.nat_det_close_session_out(socket.inet_aton(nat_ip),
5614 port_out1,
Martin Gálik6bc8c642017-04-19 01:12:27 -07005615 self.pg1.remote_ip4n,
Martin Gálik9806eae2017-04-25 01:25:08 -07005616 external_port)
Matus Fabian2ba92e32017-08-21 07:05:03 -07005617 dms = self.vapi.nat_det_map_dump()
5618 self.assertEqual(dms[0].ses_num, 1)
5619
5620 self.vapi.nat_det_close_session_in(host0.ip4n,
5621 port_in,
5622 self.pg1.remote_ip4n,
5623 external_port)
5624 dms = self.vapi.nat_det_map_dump()
Martin Gálik6bc8c642017-04-19 01:12:27 -07005625 self.assertEqual(dms[0].ses_num, 0)
5626
Martin Gálik977c1cb2017-03-30 23:21:51 -07005627 def test_tcp_session_close_detection_in(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07005628 """ Deterministic NAT TCP session close from inside network """
5629 self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
5630 32,
5631 socket.inet_aton(self.nat_addr),
5632 32)
5633 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5634 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
5635 is_inside=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07005636
5637 self.initiate_tcp_session(self.pg0, self.pg1)
5638
5639 # close the session from inside
5640 try:
5641 # FIN packet in -> out
5642 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5643 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07005644 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
Martin Gálik977c1cb2017-03-30 23:21:51 -07005645 flags="F"))
5646 self.pg0.add_stream(p)
5647 self.pg_enable_capture(self.pg_interfaces)
5648 self.pg_start()
5649 self.pg1.get_capture(1)
5650
5651 pkts = []
5652
5653 # ACK packet out -> in
5654 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07005655 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Martin Gálik9806eae2017-04-25 01:25:08 -07005656 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
Martin Gálik977c1cb2017-03-30 23:21:51 -07005657 flags="A"))
5658 pkts.append(p)
5659
5660 # FIN packet out -> in
5661 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07005662 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Martin Gálik9806eae2017-04-25 01:25:08 -07005663 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
Martin Gálik977c1cb2017-03-30 23:21:51 -07005664 flags="F"))
5665 pkts.append(p)
5666
5667 self.pg1.add_stream(pkts)
5668 self.pg_enable_capture(self.pg_interfaces)
5669 self.pg_start()
5670 self.pg0.get_capture(2)
5671
5672 # ACK packet in -> out
5673 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5674 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07005675 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
Martin Gálik977c1cb2017-03-30 23:21:51 -07005676 flags="A"))
5677 self.pg0.add_stream(p)
5678 self.pg_enable_capture(self.pg_interfaces)
5679 self.pg_start()
5680 self.pg1.get_capture(1)
5681
Matus Fabian2ba92e32017-08-21 07:05:03 -07005682 # Check if deterministic NAT44 closed the session
5683 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07005684 self.assertEqual(0, dms[0].ses_num)
5685 except:
5686 self.logger.error("TCP session termination failed")
5687 raise
5688
5689 def test_tcp_session_close_detection_out(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07005690 """ Deterministic NAT TCP session close from outside network """
5691 self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
5692 32,
5693 socket.inet_aton(self.nat_addr),
5694 32)
5695 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5696 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
5697 is_inside=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07005698
5699 self.initiate_tcp_session(self.pg0, self.pg1)
5700
5701 # close the session from outside
5702 try:
5703 # FIN packet out -> in
5704 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07005705 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Martin Gálik9806eae2017-04-25 01:25:08 -07005706 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
Martin Gálik977c1cb2017-03-30 23:21:51 -07005707 flags="F"))
5708 self.pg1.add_stream(p)
5709 self.pg_enable_capture(self.pg_interfaces)
5710 self.pg_start()
5711 self.pg0.get_capture(1)
5712
5713 pkts = []
5714
5715 # ACK packet in -> out
5716 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5717 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07005718 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
Martin Gálik977c1cb2017-03-30 23:21:51 -07005719 flags="A"))
5720 pkts.append(p)
5721
5722 # ACK packet in -> out
5723 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5724 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07005725 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
Martin Gálik977c1cb2017-03-30 23:21:51 -07005726 flags="F"))
5727 pkts.append(p)
5728
5729 self.pg0.add_stream(pkts)
5730 self.pg_enable_capture(self.pg_interfaces)
5731 self.pg_start()
5732 self.pg1.get_capture(2)
5733
5734 # ACK packet out -> in
5735 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07005736 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Martin Gálik9806eae2017-04-25 01:25:08 -07005737 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
Martin Gálik977c1cb2017-03-30 23:21:51 -07005738 flags="A"))
5739 self.pg1.add_stream(p)
5740 self.pg_enable_capture(self.pg_interfaces)
5741 self.pg_start()
5742 self.pg0.get_capture(1)
5743
Matus Fabian2ba92e32017-08-21 07:05:03 -07005744 # Check if deterministic NAT44 closed the session
5745 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07005746 self.assertEqual(0, dms[0].ses_num)
5747 except:
5748 self.logger.error("TCP session termination failed")
5749 raise
5750
5751 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
5752 def test_session_timeout(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07005753 """ Deterministic NAT session timeouts """
5754 self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
5755 32,
5756 socket.inet_aton(self.nat_addr),
5757 32)
5758 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5759 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
5760 is_inside=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07005761
5762 self.initiate_tcp_session(self.pg0, self.pg1)
Matus Fabian878c6462018-08-23 00:33:35 -07005763 self.vapi.nat_set_timeouts(5, 5, 5, 5)
Martin Gálik977c1cb2017-03-30 23:21:51 -07005764 pkts = self.create_stream_in(self.pg0, self.pg1)
5765 self.pg0.add_stream(pkts)
5766 self.pg_enable_capture(self.pg_interfaces)
5767 self.pg_start()
5768 capture = self.pg1.get_capture(len(pkts))
5769 sleep(15)
5770
Matus Fabian2ba92e32017-08-21 07:05:03 -07005771 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07005772 self.assertEqual(0, dms[0].ses_num)
5773
Matus Fabian7c0aecc2017-07-03 01:21:38 -07005774 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
Martin Gálik977c1cb2017-03-30 23:21:51 -07005775 def test_session_limit_per_user(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07005776 """ Deterministic NAT maximum sessions per user limit """
5777 self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
5778 32,
5779 socket.inet_aton(self.nat_addr),
5780 32)
5781 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5782 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
5783 is_inside=0)
Matus Fabian2f2db1c2017-04-18 05:29:59 -07005784 self.vapi.set_ipfix_exporter(collector_address=self.pg2.remote_ip4n,
5785 src_address=self.pg2.local_ip4n,
5786 path_mtu=512,
5787 template_interval=10)
Matus Fabian2ba92e32017-08-21 07:05:03 -07005788 self.vapi.nat_ipfix()
Martin Gálik977c1cb2017-03-30 23:21:51 -07005789
5790 pkts = []
5791 for port in range(1025, 2025):
5792 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5793 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5794 UDP(sport=port, dport=port))
5795 pkts.append(p)
5796
5797 self.pg0.add_stream(pkts)
5798 self.pg_enable_capture(self.pg_interfaces)
5799 self.pg_start()
5800 capture = self.pg1.get_capture(len(pkts))
5801
5802 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5803 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálikf7e655d2017-04-27 02:13:26 -07005804 UDP(sport=3001, dport=3002))
Martin Gálik977c1cb2017-03-30 23:21:51 -07005805 self.pg0.add_stream(p)
5806 self.pg_enable_capture(self.pg_interfaces)
5807 self.pg_start()
5808 capture = self.pg1.assert_nothing_captured()
5809
Martin Gálikf7e655d2017-04-27 02:13:26 -07005810 # verify ICMP error packet
5811 capture = self.pg0.get_capture(1)
5812 p = capture[0]
5813 self.assertTrue(p.haslayer(ICMP))
5814 icmp = p[ICMP]
5815 self.assertEqual(icmp.type, 3)
5816 self.assertEqual(icmp.code, 1)
5817 self.assertTrue(icmp.haslayer(IPerror))
5818 inner_ip = icmp[IPerror]
5819 self.assertEqual(inner_ip[UDPerror].sport, 3001)
5820 self.assertEqual(inner_ip[UDPerror].dport, 3002)
5821
Matus Fabian2ba92e32017-08-21 07:05:03 -07005822 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07005823
5824 self.assertEqual(1000, dms[0].ses_num)
5825
Matus Fabian2f2db1c2017-04-18 05:29:59 -07005826 # verify IPFIX logging
5827 self.vapi.cli("ipfix flush") # FIXME this should be an API call
Matus Fabian7c0aecc2017-07-03 01:21:38 -07005828 sleep(1)
Matus Fabian2f2db1c2017-04-18 05:29:59 -07005829 capture = self.pg2.get_capture(2)
5830 ipfix = IPFIXDecoder()
5831 # first load template
5832 for p in capture:
5833 self.assertTrue(p.haslayer(IPFIX))
5834 if p.haslayer(Template):
5835 ipfix.add_template(p.getlayer(Template))
5836 # verify events in data set
5837 for p in capture:
5838 if p.haslayer(Data):
5839 data = ipfix.decode_data_set(p.getlayer(Set))
Matus Fabian878c6462018-08-23 00:33:35 -07005840 self.verify_ipfix_max_entries_per_user(data,
5841 1000,
5842 self.pg0.remote_ip4n)
Matus Fabian2f2db1c2017-04-18 05:29:59 -07005843
Matus Fabian2ba92e32017-08-21 07:05:03 -07005844 def clear_nat_det(self):
Martin17a75cb2017-03-08 05:53:20 -08005845 """
Matus Fabian2ba92e32017-08-21 07:05:03 -07005846 Clear deterministic NAT configuration.
Martin17a75cb2017-03-08 05:53:20 -08005847 """
Matus Fabian2ba92e32017-08-21 07:05:03 -07005848 self.vapi.nat_ipfix(enable=0)
Matus Fabian878c6462018-08-23 00:33:35 -07005849 self.vapi.nat_set_timeouts()
Matus Fabian2ba92e32017-08-21 07:05:03 -07005850 deterministic_mappings = self.vapi.nat_det_map_dump()
Martin17a75cb2017-03-08 05:53:20 -08005851 for dsm in deterministic_mappings:
Matus Fabian2ba92e32017-08-21 07:05:03 -07005852 self.vapi.nat_det_add_del_map(dsm.in_addr,
5853 dsm.in_plen,
5854 dsm.out_addr,
5855 dsm.out_plen,
5856 is_add=0)
Martin17a75cb2017-03-08 05:53:20 -08005857
Matus Fabian2ba92e32017-08-21 07:05:03 -07005858 interfaces = self.vapi.nat44_interface_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07005859 for intf in interfaces:
Matus Fabian2ba92e32017-08-21 07:05:03 -07005860 self.vapi.nat44_interface_add_del_feature(intf.sw_if_index,
5861 intf.is_inside,
5862 is_add=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07005863
Matus Fabian066f0342017-02-10 03:48:01 -08005864 def tearDown(self):
5865 super(TestDeterministicNAT, self).tearDown()
5866 if not self.vpp_dead:
Matus Fabian82119542018-01-25 01:13:22 -08005867 self.logger.info(self.vapi.cli("show nat44 interfaces"))
Matus Fabian878c6462018-08-23 00:33:35 -07005868 self.logger.info(self.vapi.cli("show nat timeouts"))
Matus Fabian82119542018-01-25 01:13:22 -08005869 self.logger.info(
5870 self.vapi.cli("show nat44 deterministic mappings"))
5871 self.logger.info(
Matus Fabian82119542018-01-25 01:13:22 -08005872 self.vapi.cli("show nat44 deterministic sessions"))
Matus Fabian2ba92e32017-08-21 07:05:03 -07005873 self.clear_nat_det()
Matus Fabian066f0342017-02-10 03:48:01 -08005874
Matus Fabian06596c52017-06-06 04:53:28 -07005875
5876class TestNAT64(MethodHolder):
5877 """ NAT64 Test Cases """
5878
5879 @classmethod
Matus Fabiana431ad12018-01-04 04:03:14 -08005880 def setUpConstants(cls):
5881 super(TestNAT64, cls).setUpConstants()
5882 cls.vpp_cmdline.extend(["nat", "{", "nat64 bib hash buckets 128",
5883 "nat64 st hash buckets 256", "}"])
5884
5885 @classmethod
Matus Fabian06596c52017-06-06 04:53:28 -07005886 def setUpClass(cls):
5887 super(TestNAT64, cls).setUpClass()
5888
5889 try:
5890 cls.tcp_port_in = 6303
5891 cls.tcp_port_out = 6303
5892 cls.udp_port_in = 6304
5893 cls.udp_port_out = 6304
5894 cls.icmp_id_in = 6305
5895 cls.icmp_id_out = 6305
5896 cls.nat_addr = '10.0.0.3'
5897 cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
Matus Fabian029f3d22017-06-15 02:28:50 -07005898 cls.vrf1_id = 10
5899 cls.vrf1_nat_addr = '10.0.10.3'
5900 cls.vrf1_nat_addr_n = socket.inet_pton(socket.AF_INET,
5901 cls.vrf1_nat_addr)
Matus Fabiana431ad12018-01-04 04:03:14 -08005902 cls.ipfix_src_port = 4739
5903 cls.ipfix_domain_id = 1
Matus Fabian06596c52017-06-06 04:53:28 -07005904
Juraj Slobodac746a152018-07-09 02:36:37 +02005905 cls.create_pg_interfaces(range(6))
Matus Fabian06596c52017-06-06 04:53:28 -07005906 cls.ip6_interfaces = list(cls.pg_interfaces[0:1])
Matus Fabian029f3d22017-06-15 02:28:50 -07005907 cls.ip6_interfaces.append(cls.pg_interfaces[2])
Matus Fabian06596c52017-06-06 04:53:28 -07005908 cls.ip4_interfaces = list(cls.pg_interfaces[1:2])
5909
Neale Ranns15002542017-09-10 04:39:11 -07005910 cls.vapi.ip_table_add_del(cls.vrf1_id, is_add=1, is_ipv6=1)
5911
Matus Fabian029f3d22017-06-15 02:28:50 -07005912 cls.pg_interfaces[2].set_table_ip6(cls.vrf1_id)
5913
5914 cls.pg0.generate_remote_hosts(2)
5915
Matus Fabian06596c52017-06-06 04:53:28 -07005916 for i in cls.ip6_interfaces:
5917 i.admin_up()
5918 i.config_ip6()
Matus Fabian029f3d22017-06-15 02:28:50 -07005919 i.configure_ipv6_neighbors()
Matus Fabian06596c52017-06-06 04:53:28 -07005920
5921 for i in cls.ip4_interfaces:
5922 i.admin_up()
5923 i.config_ip4()
5924 i.resolve_arp()
5925
Matus Fabian36ea2d62017-10-24 04:13:49 -07005926 cls.pg3.admin_up()
5927 cls.pg3.config_ip4()
5928 cls.pg3.resolve_arp()
5929 cls.pg3.config_ip6()
5930 cls.pg3.configure_ipv6_neighbors()
5931
Juraj Slobodac746a152018-07-09 02:36:37 +02005932 cls.pg5.admin_up()
5933 cls.pg5.config_ip6()
5934
Matus Fabian06596c52017-06-06 04:53:28 -07005935 except Exception:
5936 super(TestNAT64, cls).tearDownClass()
5937 raise
5938
Juraj Slobodac746a152018-07-09 02:36:37 +02005939 def test_nat64_inside_interface_handles_neighbor_advertisement(self):
5940 """ NAT64 inside interface handles Neighbor Advertisement """
5941
5942 self.vapi.nat64_add_del_interface(self.pg5.sw_if_index)
5943
5944 # Try to send ping
5945 ping = (Ether(dst=self.pg5.local_mac, src=self.pg5.remote_mac) /
5946 IPv6(src=self.pg5.remote_ip6, dst=self.pg5.local_ip6) /
5947 ICMPv6EchoRequest())
5948 pkts = [ping]
5949 self.pg5.add_stream(pkts)
5950 self.pg_enable_capture(self.pg_interfaces)
5951 self.pg_start()
5952
5953 # Wait for Neighbor Solicitation
5954 capture = self.pg5.get_capture(len(pkts))
Juraj Slobodac746a152018-07-09 02:36:37 +02005955 packet = capture[0]
5956 try:
5957 self.assertEqual(packet[IPv6].src, self.pg5.local_ip6)
5958 self.assertTrue(packet.haslayer(ICMPv6ND_NS))
5959 tgt = packet[ICMPv6ND_NS].tgt
5960 except:
5961 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5962 raise
5963
5964 # Send Neighbor Advertisement
5965 p = (Ether(dst=self.pg5.local_mac, src=self.pg5.remote_mac) /
5966 IPv6(src=self.pg5.remote_ip6, dst=self.pg5.local_ip6) /
5967 ICMPv6ND_NA(tgt=tgt) /
5968 ICMPv6NDOptDstLLAddr(lladdr=self.pg5.remote_mac))
5969 pkts = [p]
5970 self.pg5.add_stream(pkts)
5971 self.pg_enable_capture(self.pg_interfaces)
5972 self.pg_start()
5973
5974 # Try to send ping again
5975 pkts = [ping]
5976 self.pg5.add_stream(pkts)
5977 self.pg_enable_capture(self.pg_interfaces)
5978 self.pg_start()
5979
5980 # Wait for ping reply
5981 capture = self.pg5.get_capture(len(pkts))
Juraj Slobodac746a152018-07-09 02:36:37 +02005982 packet = capture[0]
5983 try:
5984 self.assertEqual(packet[IPv6].src, self.pg5.local_ip6)
5985 self.assertEqual(packet[IPv6].dst, self.pg5.remote_ip6)
5986 self.assertTrue(packet.haslayer(ICMPv6EchoReply))
5987 except:
5988 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5989 raise
5990
Matus Fabian06596c52017-06-06 04:53:28 -07005991 def test_pool(self):
5992 """ Add/delete address to NAT64 pool """
5993 nat_addr = socket.inet_pton(socket.AF_INET, '1.2.3.4')
5994
5995 self.vapi.nat64_add_del_pool_addr_range(nat_addr, nat_addr)
5996
5997 addresses = self.vapi.nat64_pool_addr_dump()
5998 self.assertEqual(len(addresses), 1)
5999 self.assertEqual(addresses[0].address, nat_addr)
6000
6001 self.vapi.nat64_add_del_pool_addr_range(nat_addr, nat_addr, is_add=0)
6002
6003 addresses = self.vapi.nat64_pool_addr_dump()
6004 self.assertEqual(len(addresses), 0)
6005
6006 def test_interface(self):
6007 """ Enable/disable NAT64 feature on the interface """
6008 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6009 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6010
6011 interfaces = self.vapi.nat64_interface_dump()
6012 self.assertEqual(len(interfaces), 2)
6013 pg0_found = False
6014 pg1_found = False
6015 for intf in interfaces:
6016 if intf.sw_if_index == self.pg0.sw_if_index:
6017 self.assertEqual(intf.is_inside, 1)
6018 pg0_found = True
6019 elif intf.sw_if_index == self.pg1.sw_if_index:
6020 self.assertEqual(intf.is_inside, 0)
6021 pg1_found = True
6022 self.assertTrue(pg0_found)
6023 self.assertTrue(pg1_found)
6024
6025 features = self.vapi.cli("show interface features pg0")
6026 self.assertNotEqual(features.find('nat64-in2out'), -1)
6027 features = self.vapi.cli("show interface features pg1")
6028 self.assertNotEqual(features.find('nat64-out2in'), -1)
6029
6030 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index, is_add=0)
6031 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_add=0)
6032
6033 interfaces = self.vapi.nat64_interface_dump()
6034 self.assertEqual(len(interfaces), 0)
6035
6036 def test_static_bib(self):
6037 """ Add/delete static BIB entry """
6038 in_addr = socket.inet_pton(socket.AF_INET6,
6039 '2001:db8:85a3::8a2e:370:7334')
6040 out_addr = socket.inet_pton(socket.AF_INET, '10.1.1.3')
6041 in_port = 1234
6042 out_port = 5678
6043 proto = IP_PROTOS.tcp
6044
6045 self.vapi.nat64_add_del_static_bib(in_addr,
6046 out_addr,
6047 in_port,
6048 out_port,
6049 proto)
6050 bib = self.vapi.nat64_bib_dump(IP_PROTOS.tcp)
6051 static_bib_num = 0
6052 for bibe in bib:
6053 if bibe.is_static:
6054 static_bib_num += 1
6055 self.assertEqual(bibe.i_addr, in_addr)
6056 self.assertEqual(bibe.o_addr, out_addr)
6057 self.assertEqual(bibe.i_port, in_port)
6058 self.assertEqual(bibe.o_port, out_port)
6059 self.assertEqual(static_bib_num, 1)
6060
6061 self.vapi.nat64_add_del_static_bib(in_addr,
6062 out_addr,
6063 in_port,
6064 out_port,
6065 proto,
6066 is_add=0)
6067 bib = self.vapi.nat64_bib_dump(IP_PROTOS.tcp)
6068 static_bib_num = 0
6069 for bibe in bib:
6070 if bibe.is_static:
6071 static_bib_num += 1
6072 self.assertEqual(static_bib_num, 0)
6073
6074 def test_set_timeouts(self):
6075 """ Set NAT64 timeouts """
6076 # verify default values
Matus Fabian878c6462018-08-23 00:33:35 -07006077 timeouts = self.vapi.nat_get_timeouts()
Matus Fabian06596c52017-06-06 04:53:28 -07006078 self.assertEqual(timeouts.udp, 300)
6079 self.assertEqual(timeouts.icmp, 60)
Matus Fabian878c6462018-08-23 00:33:35 -07006080 self.assertEqual(timeouts.tcp_transitory, 240)
6081 self.assertEqual(timeouts.tcp_established, 7440)
Matus Fabian06596c52017-06-06 04:53:28 -07006082
6083 # set and verify custom values
Matus Fabian878c6462018-08-23 00:33:35 -07006084 self.vapi.nat_set_timeouts(udp=200, icmp=30, tcp_transitory=250,
6085 tcp_established=7450)
6086 timeouts = self.vapi.nat_get_timeouts()
Matus Fabian06596c52017-06-06 04:53:28 -07006087 self.assertEqual(timeouts.udp, 200)
6088 self.assertEqual(timeouts.icmp, 30)
Matus Fabian878c6462018-08-23 00:33:35 -07006089 self.assertEqual(timeouts.tcp_transitory, 250)
6090 self.assertEqual(timeouts.tcp_established, 7450)
Matus Fabian06596c52017-06-06 04:53:28 -07006091
6092 def test_dynamic(self):
6093 """ NAT64 dynamic translation test """
6094 self.tcp_port_in = 6303
6095 self.udp_port_in = 6304
6096 self.icmp_id_in = 6305
6097
6098 ses_num_start = self.nat64_get_ses_num()
6099
6100 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6101 self.nat_addr_n)
6102 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6103 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6104
6105 # in2out
6106 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
6107 self.pg0.add_stream(pkts)
6108 self.pg_enable_capture(self.pg_interfaces)
6109 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07006110 capture = self.pg1.get_capture(len(pkts))
6111 self.verify_capture_out(capture, nat_ip=self.nat_addr,
Matus Fabian06596c52017-06-06 04:53:28 -07006112 dst_ip=self.pg1.remote_ip4)
6113
6114 # out2in
6115 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
6116 self.pg1.add_stream(pkts)
6117 self.pg_enable_capture(self.pg_interfaces)
6118 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07006119 capture = self.pg0.get_capture(len(pkts))
Matus Fabian06596c52017-06-06 04:53:28 -07006120 ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
6121 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
6122
6123 # in2out
6124 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
6125 self.pg0.add_stream(pkts)
6126 self.pg_enable_capture(self.pg_interfaces)
6127 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07006128 capture = self.pg1.get_capture(len(pkts))
6129 self.verify_capture_out(capture, nat_ip=self.nat_addr,
Matus Fabian06596c52017-06-06 04:53:28 -07006130 dst_ip=self.pg1.remote_ip4)
6131
6132 # out2in
6133 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
6134 self.pg1.add_stream(pkts)
6135 self.pg_enable_capture(self.pg_interfaces)
6136 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07006137 capture = self.pg0.get_capture(len(pkts))
Matus Fabian06596c52017-06-06 04:53:28 -07006138 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
6139
6140 ses_num_end = self.nat64_get_ses_num()
6141
6142 self.assertEqual(ses_num_end - ses_num_start, 3)
6143
Matus Fabian029f3d22017-06-15 02:28:50 -07006144 # tenant with specific VRF
6145 self.vapi.nat64_add_del_pool_addr_range(self.vrf1_nat_addr_n,
6146 self.vrf1_nat_addr_n,
6147 vrf_id=self.vrf1_id)
6148 self.vapi.nat64_add_del_interface(self.pg2.sw_if_index)
6149
6150 pkts = self.create_stream_in_ip6(self.pg2, self.pg1)
6151 self.pg2.add_stream(pkts)
6152 self.pg_enable_capture(self.pg_interfaces)
6153 self.pg_start()
6154 capture = self.pg1.get_capture(len(pkts))
6155 self.verify_capture_out(capture, nat_ip=self.vrf1_nat_addr,
6156 dst_ip=self.pg1.remote_ip4)
6157
6158 pkts = self.create_stream_out(self.pg1, dst_ip=self.vrf1_nat_addr)
6159 self.pg1.add_stream(pkts)
6160 self.pg_enable_capture(self.pg_interfaces)
6161 self.pg_start()
6162 capture = self.pg2.get_capture(len(pkts))
6163 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg2.remote_ip6)
6164
Matus Fabian06596c52017-06-06 04:53:28 -07006165 def test_static(self):
6166 """ NAT64 static translation test """
6167 self.tcp_port_in = 60303
6168 self.udp_port_in = 60304
6169 self.icmp_id_in = 60305
6170 self.tcp_port_out = 60303
6171 self.udp_port_out = 60304
6172 self.icmp_id_out = 60305
6173
6174 ses_num_start = self.nat64_get_ses_num()
6175
6176 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6177 self.nat_addr_n)
6178 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6179 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6180
6181 self.vapi.nat64_add_del_static_bib(self.pg0.remote_ip6n,
6182 self.nat_addr_n,
6183 self.tcp_port_in,
6184 self.tcp_port_out,
6185 IP_PROTOS.tcp)
6186 self.vapi.nat64_add_del_static_bib(self.pg0.remote_ip6n,
6187 self.nat_addr_n,
6188 self.udp_port_in,
6189 self.udp_port_out,
6190 IP_PROTOS.udp)
6191 self.vapi.nat64_add_del_static_bib(self.pg0.remote_ip6n,
6192 self.nat_addr_n,
6193 self.icmp_id_in,
6194 self.icmp_id_out,
6195 IP_PROTOS.icmp)
6196
6197 # in2out
6198 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
6199 self.pg0.add_stream(pkts)
6200 self.pg_enable_capture(self.pg_interfaces)
6201 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07006202 capture = self.pg1.get_capture(len(pkts))
6203 self.verify_capture_out(capture, nat_ip=self.nat_addr,
Matus Fabian06596c52017-06-06 04:53:28 -07006204 dst_ip=self.pg1.remote_ip4, same_port=True)
6205
6206 # out2in
6207 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
6208 self.pg1.add_stream(pkts)
6209 self.pg_enable_capture(self.pg_interfaces)
6210 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07006211 capture = self.pg0.get_capture(len(pkts))
Matus Fabian06596c52017-06-06 04:53:28 -07006212 ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
6213 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
6214
6215 ses_num_end = self.nat64_get_ses_num()
6216
6217 self.assertEqual(ses_num_end - ses_num_start, 3)
6218
6219 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
6220 def test_session_timeout(self):
6221 """ NAT64 session timeout """
6222 self.icmp_id_in = 1234
6223 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6224 self.nat_addr_n)
6225 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6226 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
Matus Fabian878c6462018-08-23 00:33:35 -07006227 self.vapi.nat_set_timeouts(icmp=5, tcp_transitory=5, tcp_established=5)
Matus Fabian06596c52017-06-06 04:53:28 -07006228
6229 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
6230 self.pg0.add_stream(pkts)
6231 self.pg_enable_capture(self.pg_interfaces)
6232 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07006233 capture = self.pg1.get_capture(len(pkts))
Matus Fabian06596c52017-06-06 04:53:28 -07006234
6235 ses_num_before_timeout = self.nat64_get_ses_num()
6236
6237 sleep(15)
6238
Matus Fabian8fed4242018-08-14 05:14:55 -07006239 # ICMP and TCP session after timeout
Matus Fabian06596c52017-06-06 04:53:28 -07006240 ses_num_after_timeout = self.nat64_get_ses_num()
Matus Fabian8fed4242018-08-14 05:14:55 -07006241 self.assertEqual(ses_num_before_timeout - ses_num_after_timeout, 2)
Matus Fabian06596c52017-06-06 04:53:28 -07006242
Matus Fabian732036d2017-06-08 05:24:28 -07006243 def test_icmp_error(self):
6244 """ NAT64 ICMP Error message translation """
6245 self.tcp_port_in = 6303
6246 self.udp_port_in = 6304
6247 self.icmp_id_in = 6305
6248
Matus Fabian732036d2017-06-08 05:24:28 -07006249 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6250 self.nat_addr_n)
6251 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6252 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6253
6254 # send some packets to create sessions
6255 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
6256 self.pg0.add_stream(pkts)
6257 self.pg_enable_capture(self.pg_interfaces)
6258 self.pg_start()
6259 capture_ip4 = self.pg1.get_capture(len(pkts))
Matus Fabian029f3d22017-06-15 02:28:50 -07006260 self.verify_capture_out(capture_ip4,
Matus Fabian732036d2017-06-08 05:24:28 -07006261 nat_ip=self.nat_addr,
6262 dst_ip=self.pg1.remote_ip4)
6263
6264 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
6265 self.pg1.add_stream(pkts)
6266 self.pg_enable_capture(self.pg_interfaces)
6267 self.pg_start()
6268 capture_ip6 = self.pg0.get_capture(len(pkts))
6269 ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
6270 self.verify_capture_in_ip6(capture_ip6, ip[IPv6].src,
6271 self.pg0.remote_ip6)
6272
6273 # in2out
6274 pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6275 IPv6(src=self.pg0.remote_ip6, dst=ip[IPv6].src) /
6276 ICMPv6DestUnreach(code=1) /
6277 packet[IPv6] for packet in capture_ip6]
6278 self.pg0.add_stream(pkts)
6279 self.pg_enable_capture(self.pg_interfaces)
6280 self.pg_start()
6281 capture = self.pg1.get_capture(len(pkts))
6282 for packet in capture:
6283 try:
6284 self.assertEqual(packet[IP].src, self.nat_addr)
6285 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
6286 self.assertEqual(packet[ICMP].type, 3)
6287 self.assertEqual(packet[ICMP].code, 13)
6288 inner = packet[IPerror]
6289 self.assertEqual(inner.src, self.pg1.remote_ip4)
6290 self.assertEqual(inner.dst, self.nat_addr)
Klement Sekerad81ae412018-05-16 10:52:54 +02006291 self.assert_packet_checksums_valid(packet)
Matus Fabian732036d2017-06-08 05:24:28 -07006292 if inner.haslayer(TCPerror):
6293 self.assertEqual(inner[TCPerror].dport, self.tcp_port_out)
6294 elif inner.haslayer(UDPerror):
6295 self.assertEqual(inner[UDPerror].dport, self.udp_port_out)
6296 else:
6297 self.assertEqual(inner[ICMPerror].id, self.icmp_id_out)
6298 except:
6299 self.logger.error(ppp("Unexpected or invalid packet:", packet))
6300 raise
6301
6302 # out2in
6303 pkts = [Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
6304 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6305 ICMP(type=3, code=13) /
6306 packet[IP] for packet in capture_ip4]
6307 self.pg1.add_stream(pkts)
6308 self.pg_enable_capture(self.pg_interfaces)
6309 self.pg_start()
6310 capture = self.pg0.get_capture(len(pkts))
6311 for packet in capture:
6312 try:
6313 self.assertEqual(packet[IPv6].src, ip.src)
6314 self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
6315 icmp = packet[ICMPv6DestUnreach]
6316 self.assertEqual(icmp.code, 1)
6317 inner = icmp[IPerror6]
6318 self.assertEqual(inner.src, self.pg0.remote_ip6)
6319 self.assertEqual(inner.dst, ip.src)
Klement Sekerad81ae412018-05-16 10:52:54 +02006320 self.assert_icmpv6_checksum_valid(packet)
Matus Fabian732036d2017-06-08 05:24:28 -07006321 if inner.haslayer(TCPerror):
6322 self.assertEqual(inner[TCPerror].sport, self.tcp_port_in)
6323 elif inner.haslayer(UDPerror):
6324 self.assertEqual(inner[UDPerror].sport, self.udp_port_in)
6325 else:
6326 self.assertEqual(inner[ICMPv6EchoRequest].id,
6327 self.icmp_id_in)
6328 except:
6329 self.logger.error(ppp("Unexpected or invalid packet:", packet))
6330 raise
6331
Matus Fabian029f3d22017-06-15 02:28:50 -07006332 def test_hairpinning(self):
6333 """ NAT64 hairpinning """
6334
6335 client = self.pg0.remote_hosts[0]
6336 server = self.pg0.remote_hosts[1]
6337 server_tcp_in_port = 22
6338 server_tcp_out_port = 4022
6339 server_udp_in_port = 23
6340 server_udp_out_port = 4023
6341 client_tcp_in_port = 1234
6342 client_udp_in_port = 1235
6343 client_tcp_out_port = 0
6344 client_udp_out_port = 0
6345 ip = IPv6(src=''.join(['64:ff9b::', self.nat_addr]))
6346 nat_addr_ip6 = ip.src
6347
6348 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6349 self.nat_addr_n)
6350 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6351 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6352
6353 self.vapi.nat64_add_del_static_bib(server.ip6n,
6354 self.nat_addr_n,
6355 server_tcp_in_port,
6356 server_tcp_out_port,
6357 IP_PROTOS.tcp)
6358 self.vapi.nat64_add_del_static_bib(server.ip6n,
6359 self.nat_addr_n,
6360 server_udp_in_port,
6361 server_udp_out_port,
6362 IP_PROTOS.udp)
6363
6364 # client to server
6365 pkts = []
6366 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6367 IPv6(src=client.ip6, dst=nat_addr_ip6) /
6368 TCP(sport=client_tcp_in_port, dport=server_tcp_out_port))
6369 pkts.append(p)
6370 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6371 IPv6(src=client.ip6, dst=nat_addr_ip6) /
6372 UDP(sport=client_udp_in_port, dport=server_udp_out_port))
6373 pkts.append(p)
6374 self.pg0.add_stream(pkts)
6375 self.pg_enable_capture(self.pg_interfaces)
6376 self.pg_start()
6377 capture = self.pg0.get_capture(len(pkts))
6378 for packet in capture:
6379 try:
6380 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
6381 self.assertEqual(packet[IPv6].dst, server.ip6)
Klement Sekerad81ae412018-05-16 10:52:54 +02006382 self.assert_packet_checksums_valid(packet)
Matus Fabian029f3d22017-06-15 02:28:50 -07006383 if packet.haslayer(TCP):
6384 self.assertNotEqual(packet[TCP].sport, client_tcp_in_port)
6385 self.assertEqual(packet[TCP].dport, server_tcp_in_port)
Matus Fabian029f3d22017-06-15 02:28:50 -07006386 client_tcp_out_port = packet[TCP].sport
6387 else:
6388 self.assertNotEqual(packet[UDP].sport, client_udp_in_port)
6389 self.assertEqual(packet[UDP].dport, server_udp_in_port)
Matus Fabian029f3d22017-06-15 02:28:50 -07006390 client_udp_out_port = packet[UDP].sport
6391 except:
6392 self.logger.error(ppp("Unexpected or invalid packet:", packet))
6393 raise
6394
6395 # server to client
6396 pkts = []
6397 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6398 IPv6(src=server.ip6, dst=nat_addr_ip6) /
6399 TCP(sport=server_tcp_in_port, dport=client_tcp_out_port))
6400 pkts.append(p)
6401 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6402 IPv6(src=server.ip6, dst=nat_addr_ip6) /
6403 UDP(sport=server_udp_in_port, dport=client_udp_out_port))
6404 pkts.append(p)
6405 self.pg0.add_stream(pkts)
6406 self.pg_enable_capture(self.pg_interfaces)
6407 self.pg_start()
6408 capture = self.pg0.get_capture(len(pkts))
6409 for packet in capture:
6410 try:
6411 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
6412 self.assertEqual(packet[IPv6].dst, client.ip6)
Klement Sekerad81ae412018-05-16 10:52:54 +02006413 self.assert_packet_checksums_valid(packet)
Matus Fabian029f3d22017-06-15 02:28:50 -07006414 if packet.haslayer(TCP):
6415 self.assertEqual(packet[TCP].sport, server_tcp_out_port)
6416 self.assertEqual(packet[TCP].dport, client_tcp_in_port)
Matus Fabian029f3d22017-06-15 02:28:50 -07006417 else:
6418 self.assertEqual(packet[UDP].sport, server_udp_out_port)
6419 self.assertEqual(packet[UDP].dport, client_udp_in_port)
Matus Fabian029f3d22017-06-15 02:28:50 -07006420 except:
6421 self.logger.error(ppp("Unexpected or invalid packet:", packet))
6422 raise
6423
6424 # ICMP error
6425 pkts = []
6426 pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6427 IPv6(src=client.ip6, dst=nat_addr_ip6) /
6428 ICMPv6DestUnreach(code=1) /
6429 packet[IPv6] for packet in capture]
6430 self.pg0.add_stream(pkts)
6431 self.pg_enable_capture(self.pg_interfaces)
6432 self.pg_start()
6433 capture = self.pg0.get_capture(len(pkts))
6434 for packet in capture:
6435 try:
6436 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
6437 self.assertEqual(packet[IPv6].dst, server.ip6)
6438 icmp = packet[ICMPv6DestUnreach]
6439 self.assertEqual(icmp.code, 1)
6440 inner = icmp[IPerror6]
6441 self.assertEqual(inner.src, server.ip6)
6442 self.assertEqual(inner.dst, nat_addr_ip6)
Klement Sekerad81ae412018-05-16 10:52:54 +02006443 self.assert_packet_checksums_valid(packet)
Matus Fabian029f3d22017-06-15 02:28:50 -07006444 if inner.haslayer(TCPerror):
6445 self.assertEqual(inner[TCPerror].sport, server_tcp_in_port)
6446 self.assertEqual(inner[TCPerror].dport,
6447 client_tcp_out_port)
6448 else:
6449 self.assertEqual(inner[UDPerror].sport, server_udp_in_port)
6450 self.assertEqual(inner[UDPerror].dport,
6451 client_udp_out_port)
6452 except:
6453 self.logger.error(ppp("Unexpected or invalid packet:", packet))
6454 raise
6455
Matus Fabian428dc912017-06-21 06:15:18 -07006456 def test_prefix(self):
6457 """ NAT64 Network-Specific Prefix """
6458
6459 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6460 self.nat_addr_n)
6461 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6462 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6463 self.vapi.nat64_add_del_pool_addr_range(self.vrf1_nat_addr_n,
6464 self.vrf1_nat_addr_n,
6465 vrf_id=self.vrf1_id)
6466 self.vapi.nat64_add_del_interface(self.pg2.sw_if_index)
6467
6468 # Add global prefix
6469 global_pref64 = "2001:db8::"
6470 global_pref64_n = socket.inet_pton(socket.AF_INET6, global_pref64)
6471 global_pref64_len = 32
6472 self.vapi.nat64_add_del_prefix(global_pref64_n, global_pref64_len)
6473
6474 prefix = self.vapi.nat64_prefix_dump()
6475 self.assertEqual(len(prefix), 1)
6476 self.assertEqual(prefix[0].prefix, global_pref64_n)
6477 self.assertEqual(prefix[0].prefix_len, global_pref64_len)
6478 self.assertEqual(prefix[0].vrf_id, 0)
6479
6480 # Add tenant specific prefix
6481 vrf1_pref64 = "2001:db8:122:300::"
6482 vrf1_pref64_n = socket.inet_pton(socket.AF_INET6, vrf1_pref64)
6483 vrf1_pref64_len = 56
6484 self.vapi.nat64_add_del_prefix(vrf1_pref64_n,
6485 vrf1_pref64_len,
6486 vrf_id=self.vrf1_id)
6487 prefix = self.vapi.nat64_prefix_dump()
6488 self.assertEqual(len(prefix), 2)
6489
6490 # Global prefix
6491 pkts = self.create_stream_in_ip6(self.pg0,
6492 self.pg1,
6493 pref=global_pref64,
6494 plen=global_pref64_len)
6495 self.pg0.add_stream(pkts)
6496 self.pg_enable_capture(self.pg_interfaces)
6497 self.pg_start()
6498 capture = self.pg1.get_capture(len(pkts))
6499 self.verify_capture_out(capture, nat_ip=self.nat_addr,
6500 dst_ip=self.pg1.remote_ip4)
6501
6502 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
6503 self.pg1.add_stream(pkts)
6504 self.pg_enable_capture(self.pg_interfaces)
6505 self.pg_start()
6506 capture = self.pg0.get_capture(len(pkts))
6507 dst_ip = self.compose_ip6(self.pg1.remote_ip4,
6508 global_pref64,
6509 global_pref64_len)
6510 self.verify_capture_in_ip6(capture, dst_ip, self.pg0.remote_ip6)
6511
6512 # Tenant specific prefix
6513 pkts = self.create_stream_in_ip6(self.pg2,
6514 self.pg1,
6515 pref=vrf1_pref64,
6516 plen=vrf1_pref64_len)
6517 self.pg2.add_stream(pkts)
6518 self.pg_enable_capture(self.pg_interfaces)
6519 self.pg_start()
6520 capture = self.pg1.get_capture(len(pkts))
6521 self.verify_capture_out(capture, nat_ip=self.vrf1_nat_addr,
6522 dst_ip=self.pg1.remote_ip4)
6523
6524 pkts = self.create_stream_out(self.pg1, dst_ip=self.vrf1_nat_addr)
6525 self.pg1.add_stream(pkts)
6526 self.pg_enable_capture(self.pg_interfaces)
6527 self.pg_start()
6528 capture = self.pg2.get_capture(len(pkts))
6529 dst_ip = self.compose_ip6(self.pg1.remote_ip4,
6530 vrf1_pref64,
6531 vrf1_pref64_len)
6532 self.verify_capture_in_ip6(capture, dst_ip, self.pg2.remote_ip6)
6533
Matus Fabianf8cd5812017-07-11 03:55:02 -07006534 def test_unknown_proto(self):
Matus Fabian7968e6c2017-07-06 05:37:49 -07006535 """ NAT64 translate packet with unknown protocol """
6536
6537 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6538 self.nat_addr_n)
6539 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6540 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6541 remote_ip6 = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
6542
6543 # in2out
6544 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6545 IPv6(src=self.pg0.remote_ip6, dst=remote_ip6) /
6546 TCP(sport=self.tcp_port_in, dport=20))
6547 self.pg0.add_stream(p)
6548 self.pg_enable_capture(self.pg_interfaces)
6549 self.pg_start()
6550 p = self.pg1.get_capture(1)
6551
6552 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabianf8cd5812017-07-11 03:55:02 -07006553 IPv6(src=self.pg0.remote_ip6, dst=remote_ip6, nh=47) /
Matus Fabian7968e6c2017-07-06 05:37:49 -07006554 GRE() /
6555 IP(src=self.pg2.local_ip4, dst=self.pg2.remote_ip4) /
6556 TCP(sport=1234, dport=1234))
6557 self.pg0.add_stream(p)
6558 self.pg_enable_capture(self.pg_interfaces)
6559 self.pg_start()
6560 p = self.pg1.get_capture(1)
6561 packet = p[0]
6562 try:
6563 self.assertEqual(packet[IP].src, self.nat_addr)
6564 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
6565 self.assertTrue(packet.haslayer(GRE))
Klement Sekerad81ae412018-05-16 10:52:54 +02006566 self.assert_packet_checksums_valid(packet)
Matus Fabian7968e6c2017-07-06 05:37:49 -07006567 except:
6568 self.logger.error(ppp("Unexpected or invalid packet:", packet))
6569 raise
6570
6571 # out2in
6572 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
6573 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6574 GRE() /
6575 IP(src=self.pg2.remote_ip4, dst=self.pg2.local_ip4) /
6576 TCP(sport=1234, dport=1234))
6577 self.pg1.add_stream(p)
6578 self.pg_enable_capture(self.pg_interfaces)
6579 self.pg_start()
6580 p = self.pg0.get_capture(1)
6581 packet = p[0]
6582 try:
6583 self.assertEqual(packet[IPv6].src, remote_ip6)
Matus Fabianf8cd5812017-07-11 03:55:02 -07006584 self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
6585 self.assertEqual(packet[IPv6].nh, 47)
Matus Fabian7968e6c2017-07-06 05:37:49 -07006586 except:
6587 self.logger.error(ppp("Unexpected or invalid packet:", packet))
6588 raise
6589
Matus Fabianf8cd5812017-07-11 03:55:02 -07006590 def test_hairpinning_unknown_proto(self):
Matus Fabian7968e6c2017-07-06 05:37:49 -07006591 """ NAT64 translate packet with unknown protocol - hairpinning """
6592
6593 client = self.pg0.remote_hosts[0]
6594 server = self.pg0.remote_hosts[1]
6595 server_tcp_in_port = 22
6596 server_tcp_out_port = 4022
6597 client_tcp_in_port = 1234
Matus Fabianf8cd5812017-07-11 03:55:02 -07006598 client_tcp_out_port = 1235
6599 server_nat_ip = "10.0.0.100"
6600 client_nat_ip = "10.0.0.110"
6601 server_nat_ip_n = socket.inet_pton(socket.AF_INET, server_nat_ip)
6602 client_nat_ip_n = socket.inet_pton(socket.AF_INET, client_nat_ip)
6603 server_nat_ip6 = self.compose_ip6(server_nat_ip, '64:ff9b::', 96)
6604 client_nat_ip6 = self.compose_ip6(client_nat_ip, '64:ff9b::', 96)
Matus Fabian7968e6c2017-07-06 05:37:49 -07006605
Matus Fabianf8cd5812017-07-11 03:55:02 -07006606 self.vapi.nat64_add_del_pool_addr_range(server_nat_ip_n,
6607 client_nat_ip_n)
Matus Fabian7968e6c2017-07-06 05:37:49 -07006608 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6609 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6610
6611 self.vapi.nat64_add_del_static_bib(server.ip6n,
Matus Fabianf8cd5812017-07-11 03:55:02 -07006612 server_nat_ip_n,
Matus Fabian7968e6c2017-07-06 05:37:49 -07006613 server_tcp_in_port,
6614 server_tcp_out_port,
6615 IP_PROTOS.tcp)
6616
Matus Fabianf8cd5812017-07-11 03:55:02 -07006617 self.vapi.nat64_add_del_static_bib(server.ip6n,
6618 server_nat_ip_n,
6619 0,
6620 0,
6621 IP_PROTOS.gre)
6622
6623 self.vapi.nat64_add_del_static_bib(client.ip6n,
6624 client_nat_ip_n,
6625 client_tcp_in_port,
6626 client_tcp_out_port,
6627 IP_PROTOS.tcp)
6628
Matus Fabian7968e6c2017-07-06 05:37:49 -07006629 # client to server
6630 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabianf8cd5812017-07-11 03:55:02 -07006631 IPv6(src=client.ip6, dst=server_nat_ip6) /
Matus Fabian7968e6c2017-07-06 05:37:49 -07006632 TCP(sport=client_tcp_in_port, dport=server_tcp_out_port))
6633 self.pg0.add_stream(p)
6634 self.pg_enable_capture(self.pg_interfaces)
6635 self.pg_start()
6636 p = self.pg0.get_capture(1)
6637
6638 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabianf8cd5812017-07-11 03:55:02 -07006639 IPv6(src=client.ip6, dst=server_nat_ip6, nh=IP_PROTOS.gre) /
Matus Fabian7968e6c2017-07-06 05:37:49 -07006640 GRE() /
6641 IP(src=self.pg2.local_ip4, dst=self.pg2.remote_ip4) /
6642 TCP(sport=1234, dport=1234))
6643 self.pg0.add_stream(p)
6644 self.pg_enable_capture(self.pg_interfaces)
6645 self.pg_start()
6646 p = self.pg0.get_capture(1)
6647 packet = p[0]
6648 try:
Matus Fabianf8cd5812017-07-11 03:55:02 -07006649 self.assertEqual(packet[IPv6].src, client_nat_ip6)
Matus Fabian7968e6c2017-07-06 05:37:49 -07006650 self.assertEqual(packet[IPv6].dst, server.ip6)
Matus Fabianf8cd5812017-07-11 03:55:02 -07006651 self.assertEqual(packet[IPv6].nh, IP_PROTOS.gre)
Matus Fabian7968e6c2017-07-06 05:37:49 -07006652 except:
6653 self.logger.error(ppp("Unexpected or invalid packet:", packet))
6654 raise
6655
6656 # server to client
6657 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabianf8cd5812017-07-11 03:55:02 -07006658 IPv6(src=server.ip6, dst=client_nat_ip6, nh=IP_PROTOS.gre) /
Matus Fabian7968e6c2017-07-06 05:37:49 -07006659 GRE() /
6660 IP(src=self.pg2.remote_ip4, dst=self.pg2.local_ip4) /
6661 TCP(sport=1234, dport=1234))
6662 self.pg0.add_stream(p)
6663 self.pg_enable_capture(self.pg_interfaces)
6664 self.pg_start()
6665 p = self.pg0.get_capture(1)
6666 packet = p[0]
6667 try:
Matus Fabianf8cd5812017-07-11 03:55:02 -07006668 self.assertEqual(packet[IPv6].src, server_nat_ip6)
Matus Fabian7968e6c2017-07-06 05:37:49 -07006669 self.assertEqual(packet[IPv6].dst, client.ip6)
Matus Fabianf8cd5812017-07-11 03:55:02 -07006670 self.assertEqual(packet[IPv6].nh, IP_PROTOS.gre)
Matus Fabian7968e6c2017-07-06 05:37:49 -07006671 except:
6672 self.logger.error(ppp("Unexpected or invalid packet:", packet))
6673 raise
6674
Matus Fabian36ea2d62017-10-24 04:13:49 -07006675 def test_one_armed_nat64(self):
6676 """ One armed NAT64 """
6677 external_port = 0
6678 remote_host_ip6 = self.compose_ip6(self.pg3.remote_ip4,
6679 '64:ff9b::',
6680 96)
6681
6682 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6683 self.nat_addr_n)
6684 self.vapi.nat64_add_del_interface(self.pg3.sw_if_index)
6685 self.vapi.nat64_add_del_interface(self.pg3.sw_if_index, is_inside=0)
6686
6687 # in2out
6688 p = (Ether(src=self.pg3.remote_mac, dst=self.pg3.local_mac) /
6689 IPv6(src=self.pg3.remote_ip6, dst=remote_host_ip6) /
6690 TCP(sport=12345, dport=80))
6691 self.pg3.add_stream(p)
6692 self.pg_enable_capture(self.pg_interfaces)
6693 self.pg_start()
6694 capture = self.pg3.get_capture(1)
6695 p = capture[0]
6696 try:
6697 ip = p[IP]
6698 tcp = p[TCP]
6699 self.assertEqual(ip.src, self.nat_addr)
6700 self.assertEqual(ip.dst, self.pg3.remote_ip4)
6701 self.assertNotEqual(tcp.sport, 12345)
6702 external_port = tcp.sport
6703 self.assertEqual(tcp.dport, 80)
Klement Sekerad81ae412018-05-16 10:52:54 +02006704 self.assert_packet_checksums_valid(p)
Matus Fabian36ea2d62017-10-24 04:13:49 -07006705 except:
6706 self.logger.error(ppp("Unexpected or invalid packet:", p))
6707 raise
6708
6709 # out2in
6710 p = (Ether(src=self.pg3.remote_mac, dst=self.pg3.local_mac) /
6711 IP(src=self.pg3.remote_ip4, dst=self.nat_addr) /
6712 TCP(sport=80, dport=external_port))
6713 self.pg3.add_stream(p)
6714 self.pg_enable_capture(self.pg_interfaces)
6715 self.pg_start()
6716 capture = self.pg3.get_capture(1)
6717 p = capture[0]
6718 try:
6719 ip = p[IPv6]
6720 tcp = p[TCP]
6721 self.assertEqual(ip.src, remote_host_ip6)
6722 self.assertEqual(ip.dst, self.pg3.remote_ip6)
6723 self.assertEqual(tcp.sport, 80)
6724 self.assertEqual(tcp.dport, 12345)
Klement Sekerad81ae412018-05-16 10:52:54 +02006725 self.assert_packet_checksums_valid(p)
Matus Fabian36ea2d62017-10-24 04:13:49 -07006726 except:
6727 self.logger.error(ppp("Unexpected or invalid packet:", p))
6728 raise
6729
Matus Fabianefcd1e92017-08-15 06:59:19 -07006730 def test_frag_in_order(self):
6731 """ NAT64 translate fragments arriving in order """
6732 self.tcp_port_in = random.randint(1025, 65535)
6733
6734 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6735 self.nat_addr_n)
6736 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6737 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6738
6739 reass = self.vapi.nat_reass_dump()
6740 reass_n_start = len(reass)
6741
6742 # in2out
6743 data = 'a' * 200
6744 pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
6745 self.tcp_port_in, 20, data)
6746 self.pg0.add_stream(pkts)
6747 self.pg_enable_capture(self.pg_interfaces)
6748 self.pg_start()
6749 frags = self.pg1.get_capture(len(pkts))
6750 p = self.reass_frags_and_verify(frags,
6751 self.nat_addr,
6752 self.pg1.remote_ip4)
6753 self.assertEqual(p[TCP].dport, 20)
6754 self.assertNotEqual(p[TCP].sport, self.tcp_port_in)
6755 self.tcp_port_out = p[TCP].sport
6756 self.assertEqual(data, p[Raw].load)
6757
6758 # out2in
6759 data = "A" * 4 + "b" * 16 + "C" * 3
6760 pkts = self.create_stream_frag(self.pg1,
6761 self.nat_addr,
6762 20,
6763 self.tcp_port_out,
6764 data)
6765 self.pg1.add_stream(pkts)
6766 self.pg_enable_capture(self.pg_interfaces)
6767 self.pg_start()
6768 frags = self.pg0.get_capture(len(pkts))
6769 src = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
6770 p = self.reass_frags_and_verify_ip6(frags, src, self.pg0.remote_ip6)
6771 self.assertEqual(p[TCP].sport, 20)
6772 self.assertEqual(p[TCP].dport, self.tcp_port_in)
6773 self.assertEqual(data, p[Raw].load)
6774
6775 reass = self.vapi.nat_reass_dump()
6776 reass_n_end = len(reass)
6777
6778 self.assertEqual(reass_n_end - reass_n_start, 2)
6779
6780 def test_reass_hairpinning(self):
6781 """ NAT64 fragments hairpinning """
6782 data = 'a' * 200
Matus Fabianefcd1e92017-08-15 06:59:19 -07006783 server = self.pg0.remote_hosts[1]
6784 server_in_port = random.randint(1025, 65535)
6785 server_out_port = random.randint(1025, 65535)
6786 client_in_port = random.randint(1025, 65535)
6787 ip = IPv6(src=''.join(['64:ff9b::', self.nat_addr]))
6788 nat_addr_ip6 = ip.src
6789
6790 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6791 self.nat_addr_n)
6792 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6793 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6794
6795 # add static BIB entry for server
6796 self.vapi.nat64_add_del_static_bib(server.ip6n,
6797 self.nat_addr_n,
6798 server_in_port,
6799 server_out_port,
6800 IP_PROTOS.tcp)
6801
6802 # send packet from host to server
6803 pkts = self.create_stream_frag_ip6(self.pg0,
6804 self.nat_addr,
6805 client_in_port,
6806 server_out_port,
6807 data)
6808 self.pg0.add_stream(pkts)
6809 self.pg_enable_capture(self.pg_interfaces)
6810 self.pg_start()
6811 frags = self.pg0.get_capture(len(pkts))
6812 p = self.reass_frags_and_verify_ip6(frags, nat_addr_ip6, server.ip6)
6813 self.assertNotEqual(p[TCP].sport, client_in_port)
6814 self.assertEqual(p[TCP].dport, server_in_port)
6815 self.assertEqual(data, p[Raw].load)
6816
6817 def test_frag_out_of_order(self):
6818 """ NAT64 translate fragments arriving out of order """
6819 self.tcp_port_in = random.randint(1025, 65535)
6820
6821 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6822 self.nat_addr_n)
6823 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6824 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6825
6826 # in2out
6827 data = 'a' * 200
6828 pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
6829 self.tcp_port_in, 20, data)
6830 pkts.reverse()
6831 self.pg0.add_stream(pkts)
6832 self.pg_enable_capture(self.pg_interfaces)
6833 self.pg_start()
6834 frags = self.pg1.get_capture(len(pkts))
6835 p = self.reass_frags_and_verify(frags,
6836 self.nat_addr,
6837 self.pg1.remote_ip4)
6838 self.assertEqual(p[TCP].dport, 20)
6839 self.assertNotEqual(p[TCP].sport, self.tcp_port_in)
6840 self.tcp_port_out = p[TCP].sport
6841 self.assertEqual(data, p[Raw].load)
6842
6843 # out2in
6844 data = "A" * 4 + "B" * 16 + "C" * 3
6845 pkts = self.create_stream_frag(self.pg1,
6846 self.nat_addr,
6847 20,
6848 self.tcp_port_out,
6849 data)
6850 pkts.reverse()
6851 self.pg1.add_stream(pkts)
6852 self.pg_enable_capture(self.pg_interfaces)
6853 self.pg_start()
6854 frags = self.pg0.get_capture(len(pkts))
6855 src = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
6856 p = self.reass_frags_and_verify_ip6(frags, src, self.pg0.remote_ip6)
6857 self.assertEqual(p[TCP].sport, 20)
6858 self.assertEqual(p[TCP].dport, self.tcp_port_in)
6859 self.assertEqual(data, p[Raw].load)
6860
Matus Fabian0938dcf2017-11-08 01:59:38 -08006861 def test_interface_addr(self):
6862 """ Acquire NAT64 pool addresses from interface """
6863 self.vapi.nat64_add_interface_addr(self.pg4.sw_if_index)
6864
6865 # no address in NAT64 pool
6866 adresses = self.vapi.nat44_address_dump()
6867 self.assertEqual(0, len(adresses))
6868
6869 # configure interface address and check NAT64 address pool
6870 self.pg4.config_ip4()
6871 addresses = self.vapi.nat64_pool_addr_dump()
6872 self.assertEqual(len(addresses), 1)
6873 self.assertEqual(addresses[0].address, self.pg4.local_ip4n)
6874
6875 # remove interface address and check NAT64 address pool
6876 self.pg4.unconfig_ip4()
6877 addresses = self.vapi.nat64_pool_addr_dump()
6878 self.assertEqual(0, len(adresses))
6879
Matus Fabiana431ad12018-01-04 04:03:14 -08006880 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
6881 def test_ipfix_max_bibs_sessions(self):
6882 """ IPFIX logging maximum session and BIB entries exceeded """
6883 max_bibs = 1280
6884 max_sessions = 2560
6885 remote_host_ip6 = self.compose_ip6(self.pg1.remote_ip4,
6886 '64:ff9b::',
6887 96)
6888
6889 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6890 self.nat_addr_n)
6891 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6892 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6893
6894 pkts = []
6895 src = ""
6896 for i in range(0, max_bibs):
6897 src = "fd01:aa::%x" % (i)
6898 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6899 IPv6(src=src, dst=remote_host_ip6) /
6900 TCP(sport=12345, dport=80))
6901 pkts.append(p)
6902 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6903 IPv6(src=src, dst=remote_host_ip6) /
6904 TCP(sport=12345, dport=22))
6905 pkts.append(p)
6906 self.pg0.add_stream(pkts)
6907 self.pg_enable_capture(self.pg_interfaces)
6908 self.pg_start()
6909 self.pg1.get_capture(max_sessions)
6910
6911 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
6912 src_address=self.pg3.local_ip4n,
6913 path_mtu=512,
6914 template_interval=10)
6915 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
6916 src_port=self.ipfix_src_port)
6917
6918 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6919 IPv6(src=src, dst=remote_host_ip6) /
6920 TCP(sport=12345, dport=25))
6921 self.pg0.add_stream(p)
6922 self.pg_enable_capture(self.pg_interfaces)
6923 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07006924 self.pg1.assert_nothing_captured()
6925 sleep(1)
Matus Fabiana431ad12018-01-04 04:03:14 -08006926 self.vapi.cli("ipfix flush") # FIXME this should be an API call
6927 capture = self.pg3.get_capture(9)
6928 ipfix = IPFIXDecoder()
6929 # first load template
6930 for p in capture:
6931 self.assertTrue(p.haslayer(IPFIX))
6932 self.assertEqual(p[IP].src, self.pg3.local_ip4)
6933 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
6934 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
6935 self.assertEqual(p[UDP].dport, 4739)
6936 self.assertEqual(p[IPFIX].observationDomainID,
6937 self.ipfix_domain_id)
6938 if p.haslayer(Template):
6939 ipfix.add_template(p.getlayer(Template))
6940 # verify events in data set
6941 for p in capture:
6942 if p.haslayer(Data):
6943 data = ipfix.decode_data_set(p.getlayer(Set))
6944 self.verify_ipfix_max_sessions(data, max_sessions)
6945
6946 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6947 IPv6(src=self.pg0.remote_ip6, dst=remote_host_ip6) /
6948 TCP(sport=12345, dport=80))
6949 self.pg0.add_stream(p)
6950 self.pg_enable_capture(self.pg_interfaces)
6951 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07006952 self.pg1.assert_nothing_captured()
6953 sleep(1)
Matus Fabiana431ad12018-01-04 04:03:14 -08006954 self.vapi.cli("ipfix flush") # FIXME this should be an API call
6955 capture = self.pg3.get_capture(1)
6956 # verify events in data set
6957 for p in capture:
6958 self.assertTrue(p.haslayer(IPFIX))
6959 self.assertEqual(p[IP].src, self.pg3.local_ip4)
6960 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
6961 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
6962 self.assertEqual(p[UDP].dport, 4739)
6963 self.assertEqual(p[IPFIX].observationDomainID,
6964 self.ipfix_domain_id)
6965 if p.haslayer(Data):
6966 data = ipfix.decode_data_set(p.getlayer(Set))
6967 self.verify_ipfix_max_bibs(data, max_bibs)
6968
6969 def test_ipfix_max_frags(self):
6970 """ IPFIX logging maximum fragments pending reassembly exceeded """
6971 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6972 self.nat_addr_n)
6973 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6974 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6975 self.vapi.nat_set_reass(max_frag=0, is_ip6=1)
6976 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
6977 src_address=self.pg3.local_ip4n,
6978 path_mtu=512,
6979 template_interval=10)
6980 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
6981 src_port=self.ipfix_src_port)
6982
6983 data = 'a' * 200
6984 pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
6985 self.tcp_port_in, 20, data)
6986 self.pg0.add_stream(pkts[-1])
6987 self.pg_enable_capture(self.pg_interfaces)
6988 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07006989 self.pg1.assert_nothing_captured()
6990 sleep(1)
Matus Fabiana431ad12018-01-04 04:03:14 -08006991 self.vapi.cli("ipfix flush") # FIXME this should be an API call
6992 capture = self.pg3.get_capture(9)
6993 ipfix = IPFIXDecoder()
6994 # first load template
6995 for p in capture:
6996 self.assertTrue(p.haslayer(IPFIX))
6997 self.assertEqual(p[IP].src, self.pg3.local_ip4)
6998 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
6999 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
7000 self.assertEqual(p[UDP].dport, 4739)
7001 self.assertEqual(p[IPFIX].observationDomainID,
7002 self.ipfix_domain_id)
7003 if p.haslayer(Template):
7004 ipfix.add_template(p.getlayer(Template))
7005 # verify events in data set
7006 for p in capture:
7007 if p.haslayer(Data):
7008 data = ipfix.decode_data_set(p.getlayer(Set))
7009 self.verify_ipfix_max_fragments_ip6(data, 0,
7010 self.pg0.remote_ip6n)
7011
7012 def test_ipfix_bib_ses(self):
7013 """ IPFIX logging NAT64 BIB/session create and delete events """
7014 self.tcp_port_in = random.randint(1025, 65535)
7015 remote_host_ip6 = self.compose_ip6(self.pg1.remote_ip4,
7016 '64:ff9b::',
7017 96)
7018
7019 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7020 self.nat_addr_n)
7021 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7022 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7023 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
7024 src_address=self.pg3.local_ip4n,
7025 path_mtu=512,
7026 template_interval=10)
7027 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
7028 src_port=self.ipfix_src_port)
7029
7030 # Create
7031 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7032 IPv6(src=self.pg0.remote_ip6, dst=remote_host_ip6) /
7033 TCP(sport=self.tcp_port_in, dport=25))
7034 self.pg0.add_stream(p)
7035 self.pg_enable_capture(self.pg_interfaces)
7036 self.pg_start()
7037 p = self.pg1.get_capture(1)
7038 self.tcp_port_out = p[0][TCP].sport
7039 self.vapi.cli("ipfix flush") # FIXME this should be an API call
7040 capture = self.pg3.get_capture(10)
7041 ipfix = IPFIXDecoder()
7042 # first load template
7043 for p in capture:
7044 self.assertTrue(p.haslayer(IPFIX))
7045 self.assertEqual(p[IP].src, self.pg3.local_ip4)
7046 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
7047 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
7048 self.assertEqual(p[UDP].dport, 4739)
7049 self.assertEqual(p[IPFIX].observationDomainID,
7050 self.ipfix_domain_id)
7051 if p.haslayer(Template):
7052 ipfix.add_template(p.getlayer(Template))
7053 # verify events in data set
7054 for p in capture:
7055 if p.haslayer(Data):
7056 data = ipfix.decode_data_set(p.getlayer(Set))
7057 if ord(data[0][230]) == 10:
7058 self.verify_ipfix_bib(data, 1, self.pg0.remote_ip6n)
7059 elif ord(data[0][230]) == 6:
7060 self.verify_ipfix_nat64_ses(data,
7061 1,
7062 self.pg0.remote_ip6n,
7063 self.pg1.remote_ip4,
7064 25)
7065 else:
7066 self.logger.error(ppp("Unexpected or invalid packet: ", p))
7067
7068 # Delete
7069 self.pg_enable_capture(self.pg_interfaces)
7070 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7071 self.nat_addr_n,
7072 is_add=0)
7073 self.vapi.cli("ipfix flush") # FIXME this should be an API call
7074 capture = self.pg3.get_capture(2)
7075 # verify events in data set
7076 for p in capture:
7077 self.assertTrue(p.haslayer(IPFIX))
7078 self.assertEqual(p[IP].src, self.pg3.local_ip4)
7079 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
7080 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
7081 self.assertEqual(p[UDP].dport, 4739)
7082 self.assertEqual(p[IPFIX].observationDomainID,
7083 self.ipfix_domain_id)
7084 if p.haslayer(Data):
7085 data = ipfix.decode_data_set(p.getlayer(Set))
7086 if ord(data[0][230]) == 11:
7087 self.verify_ipfix_bib(data, 0, self.pg0.remote_ip6n)
7088 elif ord(data[0][230]) == 7:
7089 self.verify_ipfix_nat64_ses(data,
7090 0,
7091 self.pg0.remote_ip6n,
7092 self.pg1.remote_ip4,
7093 25)
7094 else:
7095 self.logger.error(ppp("Unexpected or invalid packet: ", p))
7096
Matus Fabian06596c52017-06-06 04:53:28 -07007097 def nat64_get_ses_num(self):
7098 """
7099 Return number of active NAT64 sessions.
7100 """
Matus Fabianab9a59c2017-08-16 05:37:36 -07007101 st = self.vapi.nat64_st_dump()
7102 return len(st)
Matus Fabian06596c52017-06-06 04:53:28 -07007103
7104 def clear_nat64(self):
7105 """
7106 Clear NAT64 configuration.
7107 """
Matus Fabiana431ad12018-01-04 04:03:14 -08007108 self.vapi.nat_ipfix(enable=0, src_port=self.ipfix_src_port,
7109 domain_id=self.ipfix_domain_id)
7110 self.ipfix_src_port = 4739
7111 self.ipfix_domain_id = 1
7112
Matus Fabian878c6462018-08-23 00:33:35 -07007113 self.vapi.nat_set_timeouts()
Matus Fabian06596c52017-06-06 04:53:28 -07007114
7115 interfaces = self.vapi.nat64_interface_dump()
7116 for intf in interfaces:
Matus Fabian36ea2d62017-10-24 04:13:49 -07007117 if intf.is_inside > 1:
7118 self.vapi.nat64_add_del_interface(intf.sw_if_index,
7119 0,
7120 is_add=0)
Matus Fabian06596c52017-06-06 04:53:28 -07007121 self.vapi.nat64_add_del_interface(intf.sw_if_index,
7122 intf.is_inside,
7123 is_add=0)
7124
Matus Fabiana431ad12018-01-04 04:03:14 -08007125 bib = self.vapi.nat64_bib_dump(255)
Matus Fabian06596c52017-06-06 04:53:28 -07007126 for bibe in bib:
7127 if bibe.is_static:
7128 self.vapi.nat64_add_del_static_bib(bibe.i_addr,
7129 bibe.o_addr,
7130 bibe.i_port,
7131 bibe.o_port,
7132 bibe.proto,
7133 bibe.vrf_id,
7134 is_add=0)
7135
7136 adresses = self.vapi.nat64_pool_addr_dump()
7137 for addr in adresses:
7138 self.vapi.nat64_add_del_pool_addr_range(addr.address,
7139 addr.address,
Matus Fabian029f3d22017-06-15 02:28:50 -07007140 vrf_id=addr.vrf_id,
Matus Fabian06596c52017-06-06 04:53:28 -07007141 is_add=0)
7142
Matus Fabian428dc912017-06-21 06:15:18 -07007143 prefixes = self.vapi.nat64_prefix_dump()
7144 for prefix in prefixes:
7145 self.vapi.nat64_add_del_prefix(prefix.prefix,
7146 prefix.prefix_len,
7147 vrf_id=prefix.vrf_id,
7148 is_add=0)
7149
Matus Fabian06596c52017-06-06 04:53:28 -07007150 def tearDown(self):
7151 super(TestNAT64, self).tearDown()
7152 if not self.vpp_dead:
7153 self.logger.info(self.vapi.cli("show nat64 pool"))
7154 self.logger.info(self.vapi.cli("show nat64 interfaces"))
Matus Fabian428dc912017-06-21 06:15:18 -07007155 self.logger.info(self.vapi.cli("show nat64 prefix"))
Matus Fabianab9a59c2017-08-16 05:37:36 -07007156 self.logger.info(self.vapi.cli("show nat64 bib all"))
7157 self.logger.info(self.vapi.cli("show nat64 session table all"))
Matus Fabianefcd1e92017-08-15 06:59:19 -07007158 self.logger.info(self.vapi.cli("show nat virtual-reassembly"))
Matus Fabian06596c52017-06-06 04:53:28 -07007159 self.clear_nat64()
7160
Matus Fabian8ebe6252017-11-06 05:04:53 -08007161
7162class TestDSlite(MethodHolder):
7163 """ DS-Lite Test Cases """
7164
7165 @classmethod
7166 def setUpClass(cls):
7167 super(TestDSlite, cls).setUpClass()
7168
7169 try:
7170 cls.nat_addr = '10.0.0.3'
7171 cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
7172
7173 cls.create_pg_interfaces(range(2))
7174 cls.pg0.admin_up()
7175 cls.pg0.config_ip4()
7176 cls.pg0.resolve_arp()
7177 cls.pg1.admin_up()
7178 cls.pg1.config_ip6()
7179 cls.pg1.generate_remote_hosts(2)
7180 cls.pg1.configure_ipv6_neighbors()
7181
7182 except Exception:
7183 super(TestDSlite, cls).tearDownClass()
7184 raise
7185
7186 def test_dslite(self):
7187 """ Test DS-Lite """
Matus Fabian69ce30d2018-08-22 01:27:10 -07007188 nat_config = self.vapi.nat_show_config()
7189 self.assertEqual(0, nat_config.dslite_ce)
7190
Matus Fabian8ebe6252017-11-06 05:04:53 -08007191 self.vapi.dslite_add_del_pool_addr_range(self.nat_addr_n,
7192 self.nat_addr_n)
7193 aftr_ip4 = '192.0.0.1'
7194 aftr_ip4_n = socket.inet_pton(socket.AF_INET, aftr_ip4)
7195 aftr_ip6 = '2001:db8:85a3::8a2e:370:1'
7196 aftr_ip6_n = socket.inet_pton(socket.AF_INET6, aftr_ip6)
7197 self.vapi.dslite_set_aftr_addr(aftr_ip6_n, aftr_ip4_n)
7198
7199 # UDP
7200 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
7201 IPv6(dst=aftr_ip6, src=self.pg1.remote_hosts[0].ip6) /
7202 IP(dst=self.pg0.remote_ip4, src='192.168.1.1') /
7203 UDP(sport=20000, dport=10000))
7204 self.pg1.add_stream(p)
7205 self.pg_enable_capture(self.pg_interfaces)
7206 self.pg_start()
7207 capture = self.pg0.get_capture(1)
7208 capture = capture[0]
7209 self.assertFalse(capture.haslayer(IPv6))
7210 self.assertEqual(capture[IP].src, self.nat_addr)
7211 self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
7212 self.assertNotEqual(capture[UDP].sport, 20000)
7213 self.assertEqual(capture[UDP].dport, 10000)
Klement Sekerad81ae412018-05-16 10:52:54 +02007214 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08007215 out_port = capture[UDP].sport
7216
7217 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7218 IP(dst=self.nat_addr, src=self.pg0.remote_ip4) /
7219 UDP(sport=10000, dport=out_port))
7220 self.pg0.add_stream(p)
7221 self.pg_enable_capture(self.pg_interfaces)
7222 self.pg_start()
7223 capture = self.pg1.get_capture(1)
7224 capture = capture[0]
7225 self.assertEqual(capture[IPv6].src, aftr_ip6)
7226 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[0].ip6)
7227 self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
7228 self.assertEqual(capture[IP].dst, '192.168.1.1')
7229 self.assertEqual(capture[UDP].sport, 10000)
7230 self.assertEqual(capture[UDP].dport, 20000)
Klement Sekerad81ae412018-05-16 10:52:54 +02007231 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08007232
7233 # TCP
7234 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
7235 IPv6(dst=aftr_ip6, src=self.pg1.remote_hosts[1].ip6) /
7236 IP(dst=self.pg0.remote_ip4, src='192.168.1.1') /
7237 TCP(sport=20001, dport=10001))
7238 self.pg1.add_stream(p)
7239 self.pg_enable_capture(self.pg_interfaces)
7240 self.pg_start()
7241 capture = self.pg0.get_capture(1)
7242 capture = capture[0]
7243 self.assertFalse(capture.haslayer(IPv6))
7244 self.assertEqual(capture[IP].src, self.nat_addr)
7245 self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
7246 self.assertNotEqual(capture[TCP].sport, 20001)
7247 self.assertEqual(capture[TCP].dport, 10001)
Klement Sekerad81ae412018-05-16 10:52:54 +02007248 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08007249 out_port = capture[TCP].sport
7250
7251 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7252 IP(dst=self.nat_addr, src=self.pg0.remote_ip4) /
7253 TCP(sport=10001, dport=out_port))
7254 self.pg0.add_stream(p)
7255 self.pg_enable_capture(self.pg_interfaces)
7256 self.pg_start()
7257 capture = self.pg1.get_capture(1)
7258 capture = capture[0]
7259 self.assertEqual(capture[IPv6].src, aftr_ip6)
7260 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[1].ip6)
7261 self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
7262 self.assertEqual(capture[IP].dst, '192.168.1.1')
7263 self.assertEqual(capture[TCP].sport, 10001)
7264 self.assertEqual(capture[TCP].dport, 20001)
Klement Sekerad81ae412018-05-16 10:52:54 +02007265 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08007266
7267 # ICMP
7268 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
7269 IPv6(dst=aftr_ip6, src=self.pg1.remote_hosts[1].ip6) /
7270 IP(dst=self.pg0.remote_ip4, src='192.168.1.1') /
7271 ICMP(id=4000, type='echo-request'))
7272 self.pg1.add_stream(p)
7273 self.pg_enable_capture(self.pg_interfaces)
7274 self.pg_start()
7275 capture = self.pg0.get_capture(1)
7276 capture = capture[0]
7277 self.assertFalse(capture.haslayer(IPv6))
7278 self.assertEqual(capture[IP].src, self.nat_addr)
7279 self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
7280 self.assertNotEqual(capture[ICMP].id, 4000)
Klement Sekerad81ae412018-05-16 10:52:54 +02007281 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08007282 out_id = capture[ICMP].id
7283
7284 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7285 IP(dst=self.nat_addr, src=self.pg0.remote_ip4) /
7286 ICMP(id=out_id, type='echo-reply'))
7287 self.pg0.add_stream(p)
7288 self.pg_enable_capture(self.pg_interfaces)
7289 self.pg_start()
7290 capture = self.pg1.get_capture(1)
7291 capture = capture[0]
7292 self.assertEqual(capture[IPv6].src, aftr_ip6)
7293 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[1].ip6)
7294 self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
7295 self.assertEqual(capture[IP].dst, '192.168.1.1')
7296 self.assertEqual(capture[ICMP].id, 4000)
Klement Sekerad81ae412018-05-16 10:52:54 +02007297 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08007298
Matus Fabian331acc62017-12-08 03:38:51 -08007299 # ping DS-Lite AFTR tunnel endpoint address
7300 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
7301 IPv6(src=self.pg1.remote_hosts[1].ip6, dst=aftr_ip6) /
7302 ICMPv6EchoRequest())
7303 self.pg1.add_stream(p)
7304 self.pg_enable_capture(self.pg_interfaces)
7305 self.pg_start()
7306 capture = self.pg1.get_capture(1)
Matus Fabian331acc62017-12-08 03:38:51 -08007307 capture = capture[0]
7308 self.assertEqual(capture[IPv6].src, aftr_ip6)
7309 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[1].ip6)
7310 self.assertTrue(capture.haslayer(ICMPv6EchoReply))
7311
Matus Fabian8ebe6252017-11-06 05:04:53 -08007312 def tearDown(self):
7313 super(TestDSlite, self).tearDown()
7314 if not self.vpp_dead:
7315 self.logger.info(self.vapi.cli("show dslite pool"))
7316 self.logger.info(
7317 self.vapi.cli("show dslite aftr-tunnel-endpoint-address"))
7318 self.logger.info(self.vapi.cli("show dslite sessions"))
7319
Juraj Slobodac5c6a332018-01-09 16:08:32 +01007320
7321class TestDSliteCE(MethodHolder):
7322 """ DS-Lite CE Test Cases """
7323
7324 @classmethod
7325 def setUpConstants(cls):
7326 super(TestDSliteCE, cls).setUpConstants()
7327 cls.vpp_cmdline.extend(["nat", "{", "dslite ce", "}"])
7328
7329 @classmethod
7330 def setUpClass(cls):
7331 super(TestDSliteCE, cls).setUpClass()
7332
7333 try:
7334 cls.create_pg_interfaces(range(2))
7335 cls.pg0.admin_up()
7336 cls.pg0.config_ip4()
7337 cls.pg0.resolve_arp()
7338 cls.pg1.admin_up()
7339 cls.pg1.config_ip6()
7340 cls.pg1.generate_remote_hosts(1)
7341 cls.pg1.configure_ipv6_neighbors()
7342
7343 except Exception:
7344 super(TestDSliteCE, cls).tearDownClass()
7345 raise
7346
7347 def test_dslite_ce(self):
7348 """ Test DS-Lite CE """
7349
Matus Fabian69ce30d2018-08-22 01:27:10 -07007350 nat_config = self.vapi.nat_show_config()
7351 self.assertEqual(1, nat_config.dslite_ce)
7352
Juraj Slobodac5c6a332018-01-09 16:08:32 +01007353 b4_ip4 = '192.0.0.2'
7354 b4_ip4_n = socket.inet_pton(socket.AF_INET, b4_ip4)
7355 b4_ip6 = '2001:db8:62aa::375e:f4c1:1'
7356 b4_ip6_n = socket.inet_pton(socket.AF_INET6, b4_ip6)
7357 self.vapi.dslite_set_b4_addr(b4_ip6_n, b4_ip4_n)
7358
7359 aftr_ip4 = '192.0.0.1'
7360 aftr_ip4_n = socket.inet_pton(socket.AF_INET, aftr_ip4)
7361 aftr_ip6 = '2001:db8:85a3::8a2e:370:1'
7362 aftr_ip6_n = socket.inet_pton(socket.AF_INET6, aftr_ip6)
7363 self.vapi.dslite_set_aftr_addr(aftr_ip6_n, aftr_ip4_n)
7364
7365 self.vapi.ip_add_del_route(dst_address=aftr_ip6_n,
7366 dst_address_length=128,
7367 next_hop_address=self.pg1.remote_ip6n,
7368 next_hop_sw_if_index=self.pg1.sw_if_index,
7369 is_ipv6=1)
7370
7371 # UDP encapsulation
7372 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7373 IP(dst=self.pg1.remote_ip4, src=self.pg0.remote_ip4) /
7374 UDP(sport=10000, dport=20000))
7375 self.pg0.add_stream(p)
7376 self.pg_enable_capture(self.pg_interfaces)
7377 self.pg_start()
7378 capture = self.pg1.get_capture(1)
7379 capture = capture[0]
7380 self.assertEqual(capture[IPv6].src, b4_ip6)
7381 self.assertEqual(capture[IPv6].dst, aftr_ip6)
7382 self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
7383 self.assertEqual(capture[IP].dst, self.pg1.remote_ip4)
7384 self.assertEqual(capture[UDP].sport, 10000)
7385 self.assertEqual(capture[UDP].dport, 20000)
Klement Sekerad81ae412018-05-16 10:52:54 +02007386 self.assert_packet_checksums_valid(capture)
Juraj Slobodac5c6a332018-01-09 16:08:32 +01007387
7388 # UDP decapsulation
7389 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
7390 IPv6(dst=b4_ip6, src=aftr_ip6) /
7391 IP(dst=self.pg0.remote_ip4, src=self.pg1.remote_ip4) /
7392 UDP(sport=20000, dport=10000))
7393 self.pg1.add_stream(p)
7394 self.pg_enable_capture(self.pg_interfaces)
7395 self.pg_start()
7396 capture = self.pg0.get_capture(1)
7397 capture = capture[0]
7398 self.assertFalse(capture.haslayer(IPv6))
7399 self.assertEqual(capture[IP].src, self.pg1.remote_ip4)
7400 self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
7401 self.assertEqual(capture[UDP].sport, 20000)
7402 self.assertEqual(capture[UDP].dport, 10000)
Klement Sekerad81ae412018-05-16 10:52:54 +02007403 self.assert_packet_checksums_valid(capture)
Juraj Slobodac5c6a332018-01-09 16:08:32 +01007404
7405 # ping DS-Lite B4 tunnel endpoint address
7406 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
7407 IPv6(src=self.pg1.remote_hosts[0].ip6, dst=b4_ip6) /
7408 ICMPv6EchoRequest())
7409 self.pg1.add_stream(p)
7410 self.pg_enable_capture(self.pg_interfaces)
7411 self.pg_start()
7412 capture = self.pg1.get_capture(1)
Juraj Slobodac5c6a332018-01-09 16:08:32 +01007413 capture = capture[0]
7414 self.assertEqual(capture[IPv6].src, b4_ip6)
7415 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[0].ip6)
7416 self.assertTrue(capture.haslayer(ICMPv6EchoReply))
7417
7418 def tearDown(self):
7419 super(TestDSliteCE, self).tearDown()
7420 if not self.vpp_dead:
7421 self.logger.info(
7422 self.vapi.cli("show dslite aftr-tunnel-endpoint-address"))
7423 self.logger.info(
7424 self.vapi.cli("show dslite b4-tunnel-endpoint-address"))
7425
Matus Fabianf2a23cc2018-01-22 03:41:53 -08007426
7427class TestNAT66(MethodHolder):
7428 """ NAT66 Test Cases """
7429
7430 @classmethod
7431 def setUpClass(cls):
7432 super(TestNAT66, cls).setUpClass()
7433
7434 try:
7435 cls.nat_addr = 'fd01:ff::2'
7436 cls.nat_addr_n = socket.inet_pton(socket.AF_INET6, cls.nat_addr)
7437
7438 cls.create_pg_interfaces(range(2))
7439 cls.interfaces = list(cls.pg_interfaces)
7440
7441 for i in cls.interfaces:
7442 i.admin_up()
7443 i.config_ip6()
7444 i.configure_ipv6_neighbors()
7445
7446 except Exception:
7447 super(TestNAT66, cls).tearDownClass()
7448 raise
7449
7450 def test_static(self):
7451 """ 1:1 NAT66 test """
7452 self.vapi.nat66_add_del_interface(self.pg0.sw_if_index)
7453 self.vapi.nat66_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7454 self.vapi.nat66_add_del_static_mapping(self.pg0.remote_ip6n,
7455 self.nat_addr_n)
7456
7457 # in2out
7458 pkts = []
7459 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7460 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
7461 TCP())
7462 pkts.append(p)
7463 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7464 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
7465 UDP())
7466 pkts.append(p)
7467 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7468 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
7469 ICMPv6EchoRequest())
7470 pkts.append(p)
7471 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7472 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
7473 GRE() / IP() / TCP())
7474 pkts.append(p)
7475 self.pg0.add_stream(pkts)
7476 self.pg_enable_capture(self.pg_interfaces)
7477 self.pg_start()
7478 capture = self.pg1.get_capture(len(pkts))
7479 for packet in capture:
7480 try:
7481 self.assertEqual(packet[IPv6].src, self.nat_addr)
7482 self.assertEqual(packet[IPv6].dst, self.pg1.remote_ip6)
Klement Sekerad81ae412018-05-16 10:52:54 +02007483 self.assert_packet_checksums_valid(packet)
Matus Fabianf2a23cc2018-01-22 03:41:53 -08007484 except:
7485 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7486 raise
7487
7488 # out2in
7489 pkts = []
7490 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
7491 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
7492 TCP())
7493 pkts.append(p)
7494 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
7495 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
7496 UDP())
7497 pkts.append(p)
7498 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
7499 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
7500 ICMPv6EchoReply())
7501 pkts.append(p)
7502 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
7503 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
7504 GRE() / IP() / TCP())
7505 pkts.append(p)
7506 self.pg1.add_stream(pkts)
7507 self.pg_enable_capture(self.pg_interfaces)
7508 self.pg_start()
7509 capture = self.pg0.get_capture(len(pkts))
7510 for packet in capture:
7511 try:
7512 self.assertEqual(packet[IPv6].src, self.pg1.remote_ip6)
7513 self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
Klement Sekerad81ae412018-05-16 10:52:54 +02007514 self.assert_packet_checksums_valid(packet)
Matus Fabianf2a23cc2018-01-22 03:41:53 -08007515 except:
7516 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7517 raise
7518
7519 sm = self.vapi.nat66_static_mapping_dump()
7520 self.assertEqual(len(sm), 1)
7521 self.assertEqual(sm[0].total_pkts, 8)
7522
Juraj Sloboda9341e342018-04-13 12:00:46 +02007523 def test_check_no_translate(self):
7524 """ NAT66 translate only when egress interface is outside interface """
7525 self.vapi.nat66_add_del_interface(self.pg0.sw_if_index)
7526 self.vapi.nat66_add_del_interface(self.pg1.sw_if_index)
7527 self.vapi.nat66_add_del_static_mapping(self.pg0.remote_ip6n,
7528 self.nat_addr_n)
7529
7530 # in2out
7531 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7532 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
7533 UDP())
7534 self.pg0.add_stream([p])
7535 self.pg_enable_capture(self.pg_interfaces)
7536 self.pg_start()
7537 capture = self.pg1.get_capture(1)
7538 packet = capture[0]
7539 try:
7540 self.assertEqual(packet[IPv6].src, self.pg0.remote_ip6)
7541 self.assertEqual(packet[IPv6].dst, self.pg1.remote_ip6)
7542 except:
7543 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7544 raise
7545
Matus Fabianf2a23cc2018-01-22 03:41:53 -08007546 def clear_nat66(self):
7547 """
7548 Clear NAT66 configuration.
7549 """
7550 interfaces = self.vapi.nat66_interface_dump()
7551 for intf in interfaces:
7552 self.vapi.nat66_add_del_interface(intf.sw_if_index,
7553 intf.is_inside,
7554 is_add=0)
7555
7556 static_mappings = self.vapi.nat66_static_mapping_dump()
7557 for sm in static_mappings:
7558 self.vapi.nat66_add_del_static_mapping(sm.local_ip_address,
7559 sm.external_ip_address,
7560 sm.vrf_id,
7561 is_add=0)
7562
7563 def tearDown(self):
7564 super(TestNAT66, self).tearDown()
7565 if not self.vpp_dead:
7566 self.logger.info(self.vapi.cli("show nat66 interfaces"))
7567 self.logger.info(self.vapi.cli("show nat66 static mappings"))
7568 self.clear_nat66()
7569
Klement Sekerad81ae412018-05-16 10:52:54 +02007570
Matus Fabiande886752016-12-07 03:38:19 -08007571if __name__ == '__main__':
7572 unittest.main(testRunner=VppTestRunner)