blob: a705bd98fc016de7fde5dd5c19a5f26271140951 [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 Fabianbb4e0222018-09-13 02:36:25 -0700142 self.vapi.nat_set_mss_clamping()
Matus Fabiana6110b62018-06-13 05:39:07 -0700143
144 def nat44_add_static_mapping(self, local_ip, external_ip='0.0.0.0',
145 local_port=0, external_port=0, vrf_id=0,
146 is_add=1, external_sw_if_index=0xFFFFFFFF,
147 proto=0, twice_nat=0, self_twice_nat=0,
148 out2in_only=0, tag=""):
149 """
150 Add/delete NAT44 static mapping
151
152 :param local_ip: Local IP address
153 :param external_ip: External IP address
154 :param local_port: Local port number (Optional)
155 :param external_port: External port number (Optional)
156 :param vrf_id: VRF ID (Default 0)
157 :param is_add: 1 if add, 0 if delete (Default add)
158 :param external_sw_if_index: External interface instead of IP address
159 :param proto: IP protocol (Mandatory if port specified)
160 :param twice_nat: 1 if translate external host address and port
161 :param self_twice_nat: 1 if translate external host address and port
162 whenever external host address equals
163 local address of internal host
164 :param out2in_only: if 1 rule is matching only out2in direction
165 :param tag: Opaque string tag
166 """
167 addr_only = 1
168 if local_port and external_port:
169 addr_only = 0
170 l_ip = socket.inet_pton(socket.AF_INET, local_ip)
171 e_ip = socket.inet_pton(socket.AF_INET, external_ip)
172 self.vapi.nat44_add_del_static_mapping(
173 l_ip,
174 e_ip,
175 external_sw_if_index,
176 local_port,
177 external_port,
178 addr_only,
179 vrf_id,
180 proto,
181 twice_nat,
182 self_twice_nat,
183 out2in_only,
184 tag,
185 is_add)
186
187 def nat44_add_address(self, ip, is_add=1, vrf_id=0xFFFFFFFF, twice_nat=0):
188 """
189 Add/delete NAT44 address
190
191 :param ip: IP address
192 :param is_add: 1 if add, 0 if delete (Default add)
193 :param twice_nat: twice NAT address for extenal hosts
194 """
195 nat_addr = socket.inet_pton(socket.AF_INET, ip)
196 self.vapi.nat44_add_del_address_range(nat_addr, nat_addr, is_add,
197 vrf_id=vrf_id,
198 twice_nat=twice_nat)
199
Juraj Slobodacba69362017-12-19 02:09:32 +0100200 def create_stream_in(self, in_if, out_if, dst_ip=None, ttl=64):
Matus Fabiande886752016-12-07 03:38:19 -0800201 """
202 Create packet stream for inside network
203
204 :param in_if: Inside interface
205 :param out_if: Outside interface
Juraj Slobodacba69362017-12-19 02:09:32 +0100206 :param dst_ip: Destination address
Juraj Slobodab33f4132017-02-08 23:54:21 -0800207 :param ttl: TTL of generated packets
Matus Fabiande886752016-12-07 03:38:19 -0800208 """
Juraj Slobodacba69362017-12-19 02:09:32 +0100209 if dst_ip is None:
210 dst_ip = out_if.remote_ip4
211
Matus Fabiande886752016-12-07 03:38:19 -0800212 pkts = []
213 # TCP
214 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
Juraj Slobodacba69362017-12-19 02:09:32 +0100215 IP(src=in_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Matus Fabian06596c52017-06-06 04:53:28 -0700216 TCP(sport=self.tcp_port_in, dport=20))
Matus Fabiande886752016-12-07 03:38:19 -0800217 pkts.append(p)
218
219 # UDP
220 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
Juraj Slobodacba69362017-12-19 02:09:32 +0100221 IP(src=in_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Matus Fabian06596c52017-06-06 04:53:28 -0700222 UDP(sport=self.udp_port_in, dport=20))
Matus Fabiande886752016-12-07 03:38:19 -0800223 pkts.append(p)
224
225 # ICMP
226 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
Juraj Slobodacba69362017-12-19 02:09:32 +0100227 IP(src=in_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Matus Fabiande886752016-12-07 03:38:19 -0800228 ICMP(id=self.icmp_id_in, type='echo-request'))
229 pkts.append(p)
230
231 return pkts
232
Matus Fabian428dc912017-06-21 06:15:18 -0700233 def compose_ip6(self, ip4, pref, plen):
234 """
235 Compose IPv4-embedded IPv6 addresses
236
237 :param ip4: IPv4 address
238 :param pref: IPv6 prefix
239 :param plen: IPv6 prefix length
240 :returns: IPv4-embedded IPv6 addresses
241 """
242 pref_n = list(socket.inet_pton(socket.AF_INET6, pref))
243 ip4_n = list(socket.inet_pton(socket.AF_INET, ip4))
244 if plen == 32:
245 pref_n[4] = ip4_n[0]
246 pref_n[5] = ip4_n[1]
247 pref_n[6] = ip4_n[2]
248 pref_n[7] = ip4_n[3]
249 elif plen == 40:
250 pref_n[5] = ip4_n[0]
251 pref_n[6] = ip4_n[1]
252 pref_n[7] = ip4_n[2]
253 pref_n[9] = ip4_n[3]
254 elif plen == 48:
255 pref_n[6] = ip4_n[0]
256 pref_n[7] = ip4_n[1]
257 pref_n[9] = ip4_n[2]
258 pref_n[10] = ip4_n[3]
259 elif plen == 56:
260 pref_n[7] = ip4_n[0]
261 pref_n[9] = ip4_n[1]
262 pref_n[10] = ip4_n[2]
263 pref_n[11] = ip4_n[3]
264 elif plen == 64:
265 pref_n[9] = ip4_n[0]
266 pref_n[10] = ip4_n[1]
267 pref_n[11] = ip4_n[2]
268 pref_n[12] = ip4_n[3]
269 elif plen == 96:
270 pref_n[12] = ip4_n[0]
271 pref_n[13] = ip4_n[1]
272 pref_n[14] = ip4_n[2]
273 pref_n[15] = ip4_n[3]
274 return socket.inet_ntop(socket.AF_INET6, ''.join(pref_n))
275
Juraj Slobodacba69362017-12-19 02:09:32 +0100276 def extract_ip4(self, ip6, plen):
277 """
278 Extract IPv4 address embedded in IPv6 addresses
279
280 :param ip6: IPv6 address
281 :param plen: IPv6 prefix length
282 :returns: extracted IPv4 address
283 """
284 ip6_n = list(socket.inet_pton(socket.AF_INET6, ip6))
285 ip4_n = [None] * 4
286 if plen == 32:
287 ip4_n[0] = ip6_n[4]
288 ip4_n[1] = ip6_n[5]
289 ip4_n[2] = ip6_n[6]
290 ip4_n[3] = ip6_n[7]
291 elif plen == 40:
292 ip4_n[0] = ip6_n[5]
293 ip4_n[1] = ip6_n[6]
294 ip4_n[2] = ip6_n[7]
295 ip4_n[3] = ip6_n[9]
296 elif plen == 48:
297 ip4_n[0] = ip6_n[6]
298 ip4_n[1] = ip6_n[7]
299 ip4_n[2] = ip6_n[9]
300 ip4_n[3] = ip6_n[10]
301 elif plen == 56:
302 ip4_n[0] = ip6_n[7]
303 ip4_n[1] = ip6_n[9]
304 ip4_n[2] = ip6_n[10]
305 ip4_n[3] = ip6_n[11]
306 elif plen == 64:
307 ip4_n[0] = ip6_n[9]
308 ip4_n[1] = ip6_n[10]
309 ip4_n[2] = ip6_n[11]
310 ip4_n[3] = ip6_n[12]
311 elif plen == 96:
312 ip4_n[0] = ip6_n[12]
313 ip4_n[1] = ip6_n[13]
314 ip4_n[2] = ip6_n[14]
315 ip4_n[3] = ip6_n[15]
316 return socket.inet_ntop(socket.AF_INET, ''.join(ip4_n))
317
Matus Fabian428dc912017-06-21 06:15:18 -0700318 def create_stream_in_ip6(self, in_if, out_if, hlim=64, pref=None, plen=0):
Matus Fabian06596c52017-06-06 04:53:28 -0700319 """
320 Create IPv6 packet stream for inside network
321
322 :param in_if: Inside interface
323 :param out_if: Outside interface
324 :param ttl: Hop Limit of generated packets
Matus Fabian428dc912017-06-21 06:15:18 -0700325 :param pref: NAT64 prefix
326 :param plen: NAT64 prefix length
Matus Fabian06596c52017-06-06 04:53:28 -0700327 """
328 pkts = []
Matus Fabian428dc912017-06-21 06:15:18 -0700329 if pref is None:
330 dst = ''.join(['64:ff9b::', out_if.remote_ip4])
331 else:
332 dst = self.compose_ip6(out_if.remote_ip4, pref, plen)
333
Matus Fabian06596c52017-06-06 04:53:28 -0700334 # TCP
335 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
336 IPv6(src=in_if.remote_ip6, dst=dst, hlim=hlim) /
337 TCP(sport=self.tcp_port_in, dport=20))
338 pkts.append(p)
339
340 # UDP
341 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
342 IPv6(src=in_if.remote_ip6, dst=dst, hlim=hlim) /
343 UDP(sport=self.udp_port_in, dport=20))
344 pkts.append(p)
345
346 # ICMP
347 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
348 IPv6(src=in_if.remote_ip6, dst=dst, hlim=hlim) /
349 ICMPv6EchoRequest(id=self.icmp_id_in))
350 pkts.append(p)
351
352 return pkts
353
Juraj Sloboda7b929792017-11-23 13:20:48 +0100354 def create_stream_out(self, out_if, dst_ip=None, ttl=64,
355 use_inside_ports=False):
Matus Fabiande886752016-12-07 03:38:19 -0800356 """
357 Create packet stream for outside network
358
359 :param out_if: Outside interface
Matus Fabian2ba92e32017-08-21 07:05:03 -0700360 :param dst_ip: Destination IP address (Default use global NAT address)
Juraj Slobodab33f4132017-02-08 23:54:21 -0800361 :param ttl: TTL of generated packets
Juraj Sloboda7b929792017-11-23 13:20:48 +0100362 :param use_inside_ports: Use inside NAT ports as destination ports
363 instead of outside ports
Matus Fabiande886752016-12-07 03:38:19 -0800364 """
365 if dst_ip is None:
Matus Fabian2ba92e32017-08-21 07:05:03 -0700366 dst_ip = self.nat_addr
Juraj Sloboda7b929792017-11-23 13:20:48 +0100367 if not use_inside_ports:
368 tcp_port = self.tcp_port_out
369 udp_port = self.udp_port_out
370 icmp_id = self.icmp_id_out
371 else:
372 tcp_port = self.tcp_port_in
373 udp_port = self.udp_port_in
374 icmp_id = self.icmp_id_in
Matus Fabiande886752016-12-07 03:38:19 -0800375 pkts = []
376 # TCP
377 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
Juraj Slobodab33f4132017-02-08 23:54:21 -0800378 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Juraj Sloboda7b929792017-11-23 13:20:48 +0100379 TCP(dport=tcp_port, sport=20))
Matus Fabiande886752016-12-07 03:38:19 -0800380 pkts.append(p)
381
382 # UDP
383 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
Juraj Slobodab33f4132017-02-08 23:54:21 -0800384 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Juraj Sloboda7b929792017-11-23 13:20:48 +0100385 UDP(dport=udp_port, sport=20))
Matus Fabiande886752016-12-07 03:38:19 -0800386 pkts.append(p)
387
388 # ICMP
389 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
Juraj Slobodab33f4132017-02-08 23:54:21 -0800390 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Juraj Sloboda7b929792017-11-23 13:20:48 +0100391 ICMP(id=icmp_id, type='echo-reply'))
Matus Fabiande886752016-12-07 03:38:19 -0800392 pkts.append(p)
393
394 return pkts
395
Juraj Slobodacba69362017-12-19 02:09:32 +0100396 def create_stream_out_ip6(self, out_if, src_ip, dst_ip, hl=64):
397 """
398 Create packet stream for outside network
399
400 :param out_if: Outside interface
401 :param dst_ip: Destination IP address (Default use global NAT address)
402 :param hl: HL of generated packets
403 """
404 pkts = []
405 # TCP
406 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
407 IPv6(src=src_ip, dst=dst_ip, hlim=hl) /
408 TCP(dport=self.tcp_port_out, sport=20))
409 pkts.append(p)
410
411 # UDP
412 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
413 IPv6(src=src_ip, dst=dst_ip, hlim=hl) /
414 UDP(dport=self.udp_port_out, sport=20))
415 pkts.append(p)
416
417 # ICMP
418 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
419 IPv6(src=src_ip, dst=dst_ip, hlim=hl) /
420 ICMPv6EchoReply(id=self.icmp_id_out))
421 pkts.append(p)
422
423 return pkts
424
Matus Fabiande886752016-12-07 03:38:19 -0800425 def verify_capture_out(self, capture, nat_ip=None, same_port=False,
Matus Fabian05ca4a32018-09-04 23:45:13 -0700426 dst_ip=None, is_ip6=False):
Matus Fabiande886752016-12-07 03:38:19 -0800427 """
428 Verify captured packets on outside network
429
430 :param capture: Captured packets
Matus Fabian2ba92e32017-08-21 07:05:03 -0700431 :param nat_ip: Translated IP address (Default use global NAT address)
Matus Fabiande886752016-12-07 03:38:19 -0800432 :param same_port: Sorce port number is not translated (Default False)
Matus Fabian06596c52017-06-06 04:53:28 -0700433 :param dst_ip: Destination IP address (Default do not verify)
Juraj Slobodacba69362017-12-19 02:09:32 +0100434 :param is_ip6: If L3 protocol is IPv6 (Default False)
Matus Fabiande886752016-12-07 03:38:19 -0800435 """
Juraj Slobodacba69362017-12-19 02:09:32 +0100436 if is_ip6:
437 IP46 = IPv6
438 ICMP46 = ICMPv6EchoRequest
439 else:
440 IP46 = IP
441 ICMP46 = ICMP
Matus Fabiande886752016-12-07 03:38:19 -0800442 if nat_ip is None:
Matus Fabian2ba92e32017-08-21 07:05:03 -0700443 nat_ip = self.nat_addr
Matus Fabiande886752016-12-07 03:38:19 -0800444 for packet in capture:
445 try:
Juraj Slobodacba69362017-12-19 02:09:32 +0100446 if not is_ip6:
Klement Sekerad81ae412018-05-16 10:52:54 +0200447 self.assert_packet_checksums_valid(packet)
Juraj Slobodacba69362017-12-19 02:09:32 +0100448 self.assertEqual(packet[IP46].src, nat_ip)
Matus Fabian06596c52017-06-06 04:53:28 -0700449 if dst_ip is not None:
Juraj Slobodacba69362017-12-19 02:09:32 +0100450 self.assertEqual(packet[IP46].dst, dst_ip)
Matus Fabiande886752016-12-07 03:38:19 -0800451 if packet.haslayer(TCP):
452 if same_port:
453 self.assertEqual(packet[TCP].sport, self.tcp_port_in)
454 else:
Klement Sekerada505f62017-01-04 12:58:53 +0100455 self.assertNotEqual(
456 packet[TCP].sport, self.tcp_port_in)
Matus Fabiande886752016-12-07 03:38:19 -0800457 self.tcp_port_out = packet[TCP].sport
Klement Sekerad81ae412018-05-16 10:52:54 +0200458 self.assert_packet_checksums_valid(packet)
Matus Fabiande886752016-12-07 03:38:19 -0800459 elif packet.haslayer(UDP):
460 if same_port:
461 self.assertEqual(packet[UDP].sport, self.udp_port_in)
462 else:
Klement Sekerada505f62017-01-04 12:58:53 +0100463 self.assertNotEqual(
464 packet[UDP].sport, self.udp_port_in)
Matus Fabiande886752016-12-07 03:38:19 -0800465 self.udp_port_out = packet[UDP].sport
466 else:
467 if same_port:
Juraj Slobodacba69362017-12-19 02:09:32 +0100468 self.assertEqual(packet[ICMP46].id, self.icmp_id_in)
Matus Fabiande886752016-12-07 03:38:19 -0800469 else:
Juraj Slobodacba69362017-12-19 02:09:32 +0100470 self.assertNotEqual(packet[ICMP46].id, self.icmp_id_in)
471 self.icmp_id_out = packet[ICMP46].id
Klement Sekerad81ae412018-05-16 10:52:54 +0200472 self.assert_packet_checksums_valid(packet)
Matus Fabiande886752016-12-07 03:38:19 -0800473 except:
Klement Sekera9225dee2016-12-12 08:36:58 +0100474 self.logger.error(ppp("Unexpected or invalid packet "
475 "(outside network):", packet))
Matus Fabiande886752016-12-07 03:38:19 -0800476 raise
477
Juraj Slobodacba69362017-12-19 02:09:32 +0100478 def verify_capture_out_ip6(self, capture, nat_ip, same_port=False,
Matus Fabian05ca4a32018-09-04 23:45:13 -0700479 dst_ip=None):
Juraj Slobodacba69362017-12-19 02:09:32 +0100480 """
481 Verify captured packets on outside network
482
483 :param capture: Captured packets
484 :param nat_ip: Translated IP address
485 :param same_port: Sorce port number is not translated (Default False)
Juraj Slobodacba69362017-12-19 02:09:32 +0100486 :param dst_ip: Destination IP address (Default do not verify)
487 """
Matus Fabian05ca4a32018-09-04 23:45:13 -0700488 return self.verify_capture_out(capture, nat_ip, same_port, dst_ip,
489 True)
Juraj Slobodacba69362017-12-19 02:09:32 +0100490
Matus Fabian05ca4a32018-09-04 23:45:13 -0700491 def verify_capture_in(self, capture, in_if):
Matus Fabiande886752016-12-07 03:38:19 -0800492 """
493 Verify captured packets on inside network
494
495 :param capture: Captured packets
496 :param in_if: Inside interface
Matus Fabiande886752016-12-07 03:38:19 -0800497 """
Matus Fabiande886752016-12-07 03:38:19 -0800498 for packet in capture:
499 try:
Klement Sekerad81ae412018-05-16 10:52:54 +0200500 self.assert_packet_checksums_valid(packet)
Matus Fabiande886752016-12-07 03:38:19 -0800501 self.assertEqual(packet[IP].dst, in_if.remote_ip4)
502 if packet.haslayer(TCP):
503 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
504 elif packet.haslayer(UDP):
505 self.assertEqual(packet[UDP].dport, self.udp_port_in)
506 else:
507 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
508 except:
Klement Sekera9225dee2016-12-12 08:36:58 +0100509 self.logger.error(ppp("Unexpected or invalid packet "
510 "(inside network):", packet))
Matus Fabiande886752016-12-07 03:38:19 -0800511 raise
512
Matus Fabian05ca4a32018-09-04 23:45:13 -0700513 def verify_capture_in_ip6(self, capture, src_ip, dst_ip):
Matus Fabian06596c52017-06-06 04:53:28 -0700514 """
515 Verify captured IPv6 packets on inside network
516
517 :param capture: Captured packets
518 :param src_ip: Source IP
519 :param dst_ip: Destination IP address
Matus Fabian06596c52017-06-06 04:53:28 -0700520 """
Matus Fabian06596c52017-06-06 04:53:28 -0700521 for packet in capture:
522 try:
523 self.assertEqual(packet[IPv6].src, src_ip)
524 self.assertEqual(packet[IPv6].dst, dst_ip)
Klement Sekerad81ae412018-05-16 10:52:54 +0200525 self.assert_packet_checksums_valid(packet)
Matus Fabian06596c52017-06-06 04:53:28 -0700526 if packet.haslayer(TCP):
527 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
528 elif packet.haslayer(UDP):
529 self.assertEqual(packet[UDP].dport, self.udp_port_in)
530 else:
531 self.assertEqual(packet[ICMPv6EchoReply].id,
532 self.icmp_id_in)
533 except:
534 self.logger.error(ppp("Unexpected or invalid packet "
535 "(inside network):", packet))
536 raise
537
Matus Fabian675a69c2017-01-18 01:46:01 -0800538 def verify_capture_no_translation(self, capture, ingress_if, egress_if):
539 """
540 Verify captured packet that don't have to be translated
541
542 :param capture: Captured packets
543 :param ingress_if: Ingress interface
544 :param egress_if: Egress interface
545 """
546 for packet in capture:
547 try:
548 self.assertEqual(packet[IP].src, ingress_if.remote_ip4)
549 self.assertEqual(packet[IP].dst, egress_if.remote_ip4)
550 if packet.haslayer(TCP):
551 self.assertEqual(packet[TCP].sport, self.tcp_port_in)
552 elif packet.haslayer(UDP):
553 self.assertEqual(packet[UDP].sport, self.udp_port_in)
554 else:
555 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
556 except:
557 self.logger.error(ppp("Unexpected or invalid packet "
558 "(inside network):", packet))
559 raise
560
Juraj Slobodab33f4132017-02-08 23:54:21 -0800561 def verify_capture_out_with_icmp_errors(self, capture, src_ip=None,
Matus Fabian05ca4a32018-09-04 23:45:13 -0700562 icmp_type=11):
Juraj Slobodab33f4132017-02-08 23:54:21 -0800563 """
564 Verify captured packets with ICMP errors on outside network
565
566 :param capture: Captured packets
567 :param src_ip: Translated IP address or IP address of VPP
Matus Fabian2ba92e32017-08-21 07:05:03 -0700568 (Default use global NAT address)
Juraj Slobodab33f4132017-02-08 23:54:21 -0800569 :param icmp_type: Type of error ICMP packet
570 we are expecting (Default 11)
571 """
572 if src_ip is None:
Matus Fabian2ba92e32017-08-21 07:05:03 -0700573 src_ip = self.nat_addr
Juraj Slobodab33f4132017-02-08 23:54:21 -0800574 for packet in capture:
575 try:
576 self.assertEqual(packet[IP].src, src_ip)
577 self.assertTrue(packet.haslayer(ICMP))
578 icmp = packet[ICMP]
579 self.assertEqual(icmp.type, icmp_type)
580 self.assertTrue(icmp.haslayer(IPerror))
581 inner_ip = icmp[IPerror]
582 if inner_ip.haslayer(TCPerror):
583 self.assertEqual(inner_ip[TCPerror].dport,
584 self.tcp_port_out)
585 elif inner_ip.haslayer(UDPerror):
586 self.assertEqual(inner_ip[UDPerror].dport,
587 self.udp_port_out)
588 else:
589 self.assertEqual(inner_ip[ICMPerror].id, self.icmp_id_out)
590 except:
591 self.logger.error(ppp("Unexpected or invalid packet "
592 "(outside network):", packet))
593 raise
594
Matus Fabian05ca4a32018-09-04 23:45:13 -0700595 def verify_capture_in_with_icmp_errors(self, capture, in_if, icmp_type=11):
Juraj Slobodab33f4132017-02-08 23:54:21 -0800596 """
597 Verify captured packets with ICMP errors on inside network
598
599 :param capture: Captured packets
600 :param in_if: Inside interface
Juraj Slobodab33f4132017-02-08 23:54:21 -0800601 :param icmp_type: Type of error ICMP packet
602 we are expecting (Default 11)
603 """
Juraj Slobodab33f4132017-02-08 23:54:21 -0800604 for packet in capture:
605 try:
606 self.assertEqual(packet[IP].dst, in_if.remote_ip4)
607 self.assertTrue(packet.haslayer(ICMP))
608 icmp = packet[ICMP]
609 self.assertEqual(icmp.type, icmp_type)
610 self.assertTrue(icmp.haslayer(IPerror))
611 inner_ip = icmp[IPerror]
612 if inner_ip.haslayer(TCPerror):
613 self.assertEqual(inner_ip[TCPerror].sport,
614 self.tcp_port_in)
615 elif inner_ip.haslayer(UDPerror):
616 self.assertEqual(inner_ip[UDPerror].sport,
617 self.udp_port_in)
618 else:
619 self.assertEqual(inner_ip[ICMPerror].id, self.icmp_id_in)
620 except:
621 self.logger.error(ppp("Unexpected or invalid packet "
622 "(inside network):", packet))
623 raise
624
Matus Fabianefcd1e92017-08-15 06:59:19 -0700625 def create_stream_frag(self, src_if, dst, sport, dport, data):
626 """
627 Create fragmented packet stream
628
629 :param src_if: Source interface
630 :param dst: Destination IPv4 address
631 :param sport: Source TCP port
632 :param dport: Destination TCP port
633 :param data: Payload data
634 :returns: Fragmets
635 """
636 id = random.randint(0, 65535)
637 p = (IP(src=src_if.remote_ip4, dst=dst) /
638 TCP(sport=sport, dport=dport) /
639 Raw(data))
640 p = p.__class__(str(p))
641 chksum = p['TCP'].chksum
642 pkts = []
643 p = (Ether(src=src_if.remote_mac, dst=src_if.local_mac) /
644 IP(src=src_if.remote_ip4, dst=dst, flags="MF", frag=0, id=id) /
645 TCP(sport=sport, dport=dport, chksum=chksum) /
646 Raw(data[0:4]))
647 pkts.append(p)
648 p = (Ether(src=src_if.remote_mac, dst=src_if.local_mac) /
649 IP(src=src_if.remote_ip4, dst=dst, flags="MF", frag=3, id=id,
650 proto=IP_PROTOS.tcp) /
651 Raw(data[4:20]))
652 pkts.append(p)
653 p = (Ether(src=src_if.remote_mac, dst=src_if.local_mac) /
654 IP(src=src_if.remote_ip4, dst=dst, frag=5, proto=IP_PROTOS.tcp,
655 id=id) /
656 Raw(data[20:]))
657 pkts.append(p)
658 return pkts
659
660 def create_stream_frag_ip6(self, src_if, dst, sport, dport, data,
661 pref=None, plen=0, frag_size=128):
662 """
663 Create fragmented packet stream
664
665 :param src_if: Source interface
666 :param dst: Destination IPv4 address
667 :param sport: Source TCP port
668 :param dport: Destination TCP port
669 :param data: Payload data
670 :param pref: NAT64 prefix
671 :param plen: NAT64 prefix length
672 :param fragsize: size of fragments
673 :returns: Fragmets
674 """
675 if pref is None:
676 dst_ip6 = ''.join(['64:ff9b::', dst])
677 else:
678 dst_ip6 = self.compose_ip6(dst, pref, plen)
679
680 p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
681 IPv6(src=src_if.remote_ip6, dst=dst_ip6) /
682 IPv6ExtHdrFragment(id=random.randint(0, 65535)) /
683 TCP(sport=sport, dport=dport) /
684 Raw(data))
685
686 return fragment6(p, frag_size)
687
688 def reass_frags_and_verify(self, frags, src, dst):
689 """
690 Reassemble and verify fragmented packet
691
692 :param frags: Captured fragments
693 :param src: Source IPv4 address to verify
694 :param dst: Destination IPv4 address to verify
695
696 :returns: Reassembled IPv4 packet
697 """
698 buffer = StringIO.StringIO()
699 for p in frags:
700 self.assertEqual(p[IP].src, src)
701 self.assertEqual(p[IP].dst, dst)
Klement Sekerad81ae412018-05-16 10:52:54 +0200702 self.assert_ip_checksum_valid(p)
Matus Fabianefcd1e92017-08-15 06:59:19 -0700703 buffer.seek(p[IP].frag * 8)
704 buffer.write(p[IP].payload)
705 ip = frags[0].getlayer(IP)
706 ip = IP(src=frags[0][IP].src, dst=frags[0][IP].dst,
707 proto=frags[0][IP].proto)
708 if ip.proto == IP_PROTOS.tcp:
709 p = (ip / TCP(buffer.getvalue()))
Klement Sekerad81ae412018-05-16 10:52:54 +0200710 self.assert_tcp_checksum_valid(p)
Matus Fabianefcd1e92017-08-15 06:59:19 -0700711 elif ip.proto == IP_PROTOS.udp:
712 p = (ip / UDP(buffer.getvalue()))
713 return p
714
715 def reass_frags_and_verify_ip6(self, frags, src, dst):
716 """
717 Reassemble and verify fragmented packet
718
719 :param frags: Captured fragments
720 :param src: Source IPv6 address to verify
721 :param dst: Destination IPv6 address to verify
722
723 :returns: Reassembled IPv6 packet
724 """
725 buffer = StringIO.StringIO()
726 for p in frags:
727 self.assertEqual(p[IPv6].src, src)
728 self.assertEqual(p[IPv6].dst, dst)
729 buffer.seek(p[IPv6ExtHdrFragment].offset * 8)
730 buffer.write(p[IPv6ExtHdrFragment].payload)
731 ip = IPv6(src=frags[0][IPv6].src, dst=frags[0][IPv6].dst,
732 nh=frags[0][IPv6ExtHdrFragment].nh)
733 if ip.nh == IP_PROTOS.tcp:
734 p = (ip / TCP(buffer.getvalue()))
Matus Fabianefcd1e92017-08-15 06:59:19 -0700735 elif ip.nh == IP_PROTOS.udp:
736 p = (ip / UDP(buffer.getvalue()))
Klement Sekerad81ae412018-05-16 10:52:54 +0200737 self.assert_packet_checksums_valid(p)
Matus Fabianefcd1e92017-08-15 06:59:19 -0700738 return p
739
Matus Fabianebdf1902018-05-04 03:57:42 -0700740 def initiate_tcp_session(self, in_if, out_if):
741 """
742 Initiates TCP session
743
744 :param in_if: Inside interface
745 :param out_if: Outside interface
746 """
747 try:
748 # SYN packet in->out
749 p = (Ether(src=in_if.remote_mac, dst=in_if.local_mac) /
750 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4) /
751 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
752 flags="S"))
753 in_if.add_stream(p)
754 self.pg_enable_capture(self.pg_interfaces)
755 self.pg_start()
756 capture = out_if.get_capture(1)
757 p = capture[0]
758 self.tcp_port_out = p[TCP].sport
759
760 # SYN + ACK packet out->in
761 p = (Ether(src=out_if.remote_mac, dst=out_if.local_mac) /
762 IP(src=out_if.remote_ip4, dst=self.nat_addr) /
763 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
764 flags="SA"))
765 out_if.add_stream(p)
766 self.pg_enable_capture(self.pg_interfaces)
767 self.pg_start()
768 in_if.get_capture(1)
769
770 # ACK packet in->out
771 p = (Ether(src=in_if.remote_mac, dst=in_if.local_mac) /
772 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4) /
773 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
774 flags="A"))
775 in_if.add_stream(p)
776 self.pg_enable_capture(self.pg_interfaces)
777 self.pg_start()
778 out_if.get_capture(1)
779
780 except:
781 self.logger.error("TCP 3 way handshake failed")
782 raise
783
Matus Fabianeea28d72017-01-13 04:15:54 -0800784 def verify_ipfix_nat44_ses(self, data):
785 """
786 Verify IPFIX NAT44 session create/delete event
787
788 :param data: Decoded IPFIX data records
789 """
790 nat44_ses_create_num = 0
791 nat44_ses_delete_num = 0
792 self.assertEqual(6, len(data))
793 for record in data:
794 # natEvent
795 self.assertIn(ord(record[230]), [4, 5])
796 if ord(record[230]) == 4:
797 nat44_ses_create_num += 1
798 else:
799 nat44_ses_delete_num += 1
800 # sourceIPv4Address
801 self.assertEqual(self.pg0.remote_ip4n, record[8])
802 # postNATSourceIPv4Address
Matus Fabian2ba92e32017-08-21 07:05:03 -0700803 self.assertEqual(socket.inet_pton(socket.AF_INET, self.nat_addr),
Matus Fabianeea28d72017-01-13 04:15:54 -0800804 record[225])
805 # ingressVRFID
806 self.assertEqual(struct.pack("!I", 0), record[234])
807 # protocolIdentifier/sourceTransportPort/postNAPTSourceTransportPort
808 if IP_PROTOS.icmp == ord(record[4]):
809 self.assertEqual(struct.pack("!H", self.icmp_id_in), record[7])
810 self.assertEqual(struct.pack("!H", self.icmp_id_out),
811 record[227])
812 elif IP_PROTOS.tcp == ord(record[4]):
813 self.assertEqual(struct.pack("!H", self.tcp_port_in),
814 record[7])
815 self.assertEqual(struct.pack("!H", self.tcp_port_out),
816 record[227])
817 elif IP_PROTOS.udp == ord(record[4]):
818 self.assertEqual(struct.pack("!H", self.udp_port_in),
819 record[7])
820 self.assertEqual(struct.pack("!H", self.udp_port_out),
821 record[227])
822 else:
823 self.fail("Invalid protocol")
824 self.assertEqual(3, nat44_ses_create_num)
825 self.assertEqual(3, nat44_ses_delete_num)
826
827 def verify_ipfix_addr_exhausted(self, data):
828 """
829 Verify IPFIX NAT addresses event
830
831 :param data: Decoded IPFIX data records
832 """
833 self.assertEqual(1, len(data))
834 record = data[0]
835 # natEvent
836 self.assertEqual(ord(record[230]), 3)
837 # natPoolID
838 self.assertEqual(struct.pack("!I", 0), record[283])
839
Matus Fabiana431ad12018-01-04 04:03:14 -0800840 def verify_ipfix_max_sessions(self, data, limit):
841 """
842 Verify IPFIX maximum session entries exceeded event
843
844 :param data: Decoded IPFIX data records
845 :param limit: Number of maximum session entries that can be created.
846 """
847 self.assertEqual(1, len(data))
848 record = data[0]
849 # natEvent
850 self.assertEqual(ord(record[230]), 13)
851 # natQuotaExceededEvent
852 self.assertEqual(struct.pack("I", 1), record[466])
853 # maxSessionEntries
854 self.assertEqual(struct.pack("I", limit), record[471])
855
856 def verify_ipfix_max_bibs(self, data, limit):
857 """
858 Verify IPFIX maximum BIB entries exceeded event
859
860 :param data: Decoded IPFIX data records
861 :param limit: Number of maximum BIB entries that can be created.
862 """
863 self.assertEqual(1, len(data))
864 record = data[0]
865 # natEvent
866 self.assertEqual(ord(record[230]), 13)
867 # natQuotaExceededEvent
868 self.assertEqual(struct.pack("I", 2), record[466])
869 # maxBIBEntries
870 self.assertEqual(struct.pack("I", limit), record[472])
871
872 def verify_ipfix_max_fragments_ip6(self, data, limit, src_addr):
873 """
874 Verify IPFIX maximum IPv6 fragments pending reassembly exceeded event
875
876 :param data: Decoded IPFIX data records
877 :param limit: Number of maximum fragments pending reassembly
878 :param src_addr: IPv6 source address
879 """
880 self.assertEqual(1, len(data))
881 record = data[0]
882 # natEvent
883 self.assertEqual(ord(record[230]), 13)
884 # natQuotaExceededEvent
885 self.assertEqual(struct.pack("I", 5), record[466])
886 # maxFragmentsPendingReassembly
887 self.assertEqual(struct.pack("I", limit), record[475])
888 # sourceIPv6Address
889 self.assertEqual(src_addr, record[27])
890
891 def verify_ipfix_max_fragments_ip4(self, data, limit, src_addr):
892 """
893 Verify IPFIX maximum IPv4 fragments pending reassembly exceeded event
894
895 :param data: Decoded IPFIX data records
896 :param limit: Number of maximum fragments pending reassembly
897 :param src_addr: IPv4 source address
898 """
899 self.assertEqual(1, len(data))
900 record = data[0]
901 # natEvent
902 self.assertEqual(ord(record[230]), 13)
903 # natQuotaExceededEvent
904 self.assertEqual(struct.pack("I", 5), record[466])
905 # maxFragmentsPendingReassembly
906 self.assertEqual(struct.pack("I", limit), record[475])
907 # sourceIPv4Address
908 self.assertEqual(src_addr, record[8])
909
910 def verify_ipfix_bib(self, data, is_create, src_addr):
911 """
912 Verify IPFIX NAT64 BIB create and delete events
913
914 :param data: Decoded IPFIX data records
915 :param is_create: Create event if nonzero value otherwise delete event
916 :param src_addr: IPv6 source address
917 """
918 self.assertEqual(1, len(data))
919 record = data[0]
920 # natEvent
921 if is_create:
922 self.assertEqual(ord(record[230]), 10)
923 else:
924 self.assertEqual(ord(record[230]), 11)
925 # sourceIPv6Address
926 self.assertEqual(src_addr, record[27])
927 # postNATSourceIPv4Address
928 self.assertEqual(self.nat_addr_n, record[225])
929 # protocolIdentifier
930 self.assertEqual(IP_PROTOS.tcp, ord(record[4]))
931 # ingressVRFID
932 self.assertEqual(struct.pack("!I", 0), record[234])
933 # sourceTransportPort
934 self.assertEqual(struct.pack("!H", self.tcp_port_in), record[7])
935 # postNAPTSourceTransportPort
936 self.assertEqual(struct.pack("!H", self.tcp_port_out), record[227])
937
938 def verify_ipfix_nat64_ses(self, data, is_create, src_addr, dst_addr,
939 dst_port):
940 """
941 Verify IPFIX NAT64 session create and delete events
942
943 :param data: Decoded IPFIX data records
944 :param is_create: Create event if nonzero value otherwise delete event
945 :param src_addr: IPv6 source address
946 :param dst_addr: IPv4 destination address
947 :param dst_port: destination TCP port
948 """
949 self.assertEqual(1, len(data))
950 record = data[0]
951 # natEvent
952 if is_create:
953 self.assertEqual(ord(record[230]), 6)
954 else:
955 self.assertEqual(ord(record[230]), 7)
956 # sourceIPv6Address
957 self.assertEqual(src_addr, record[27])
958 # destinationIPv6Address
959 self.assertEqual(socket.inet_pton(socket.AF_INET6,
960 self.compose_ip6(dst_addr,
961 '64:ff9b::',
962 96)),
963 record[28])
964 # postNATSourceIPv4Address
965 self.assertEqual(self.nat_addr_n, record[225])
966 # postNATDestinationIPv4Address
967 self.assertEqual(socket.inet_pton(socket.AF_INET, dst_addr),
968 record[226])
969 # protocolIdentifier
970 self.assertEqual(IP_PROTOS.tcp, ord(record[4]))
971 # ingressVRFID
972 self.assertEqual(struct.pack("!I", 0), record[234])
973 # sourceTransportPort
974 self.assertEqual(struct.pack("!H", self.tcp_port_in), record[7])
975 # postNAPTSourceTransportPort
976 self.assertEqual(struct.pack("!H", self.tcp_port_out), record[227])
977 # destinationTransportPort
978 self.assertEqual(struct.pack("!H", dst_port), record[11])
979 # postNAPTDestinationTransportPort
980 self.assertEqual(struct.pack("!H", dst_port), record[228])
981
Matus Fabian68ba8802018-08-08 05:52:47 -0700982 def verify_no_nat44_user(self):
983 """ Verify that there is no NAT44 user """
984 users = self.vapi.nat44_user_dump()
985 self.assertEqual(len(users), 0)
986
Matus Fabian878c6462018-08-23 00:33:35 -0700987 def verify_ipfix_max_entries_per_user(self, data, limit, src_addr):
988 """
989 Verify IPFIX maximum entries per user exceeded event
990
991 :param data: Decoded IPFIX data records
992 :param limit: Number of maximum entries per user
993 :param src_addr: IPv4 source address
994 """
995 self.assertEqual(1, len(data))
996 record = data[0]
997 # natEvent
998 self.assertEqual(ord(record[230]), 13)
999 # natQuotaExceededEvent
1000 self.assertEqual(struct.pack("I", 3), record[466])
1001 # maxEntriesPerUser
1002 self.assertEqual(struct.pack("I", limit), record[473])
1003 # sourceIPv4Address
1004 self.assertEqual(src_addr, record[8])
1005
Matus Fabianbb4e0222018-09-13 02:36:25 -07001006 def verify_mss_value(self, pkt, mss):
1007 """
1008 Verify TCP MSS value
1009
1010 :param pkt:
1011 :param mss:
1012 """
1013 if not pkt.haslayer(IP) or not pkt.haslayer(TCP):
1014 raise TypeError("Not a TCP/IP packet")
1015
1016 for option in pkt[TCP].options:
1017 if option[0] == 'MSS':
1018 self.assertEqual(option[1], mss)
1019 self.assert_tcp_checksum_valid(pkt)
1020
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001021
Matus Fabian2ba92e32017-08-21 07:05:03 -07001022class TestNAT44(MethodHolder):
1023 """ NAT44 Test Cases """
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001024
1025 @classmethod
1026 def setUpClass(cls):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001027 super(TestNAT44, cls).setUpClass()
Matus Fabian229c1aa2018-05-28 04:09:52 -07001028 cls.vapi.cli("set log class nat level debug")
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001029
1030 try:
1031 cls.tcp_port_in = 6303
1032 cls.tcp_port_out = 6303
1033 cls.udp_port_in = 6304
1034 cls.udp_port_out = 6304
1035 cls.icmp_id_in = 6305
1036 cls.icmp_id_out = 6305
Matus Fabian2ba92e32017-08-21 07:05:03 -07001037 cls.nat_addr = '10.0.0.3'
Juraj Sloboda7b929792017-11-23 13:20:48 +01001038 cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
Matus Fabian6631e9c2017-05-24 01:52:20 -07001039 cls.ipfix_src_port = 4739
1040 cls.ipfix_domain_id = 1
Matus Fabianebdf1902018-05-04 03:57:42 -07001041 cls.tcp_external_port = 80
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001042
Matus Fabian36ea2d62017-10-24 04:13:49 -07001043 cls.create_pg_interfaces(range(10))
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001044 cls.interfaces = list(cls.pg_interfaces[0:4])
1045
1046 for i in cls.interfaces:
1047 i.admin_up()
1048 i.config_ip4()
1049 i.resolve_arp()
1050
Matus Fabian6fa74c62017-06-05 05:55:48 -07001051 cls.pg0.generate_remote_hosts(3)
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001052 cls.pg0.configure_ipv4_neighbors()
1053
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02001054 cls.pg1.generate_remote_hosts(1)
1055 cls.pg1.configure_ipv4_neighbors()
1056
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001057 cls.overlapping_interfaces = list(list(cls.pg_interfaces[4:7]))
Neale Ranns15002542017-09-10 04:39:11 -07001058 cls.vapi.ip_table_add_del(10, is_add=1)
1059 cls.vapi.ip_table_add_del(20, is_add=1)
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001060
1061 cls.pg4._local_ip4 = "172.16.255.1"
1062 cls.pg4._local_ip4n = socket.inet_pton(socket.AF_INET, i.local_ip4)
1063 cls.pg4._remote_hosts[0]._ip4 = "172.16.255.2"
1064 cls.pg4.set_table_ip4(10)
Matus Fabian69126282017-08-14 23:39:58 -07001065 cls.pg5._local_ip4 = "172.17.255.3"
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001066 cls.pg5._local_ip4n = socket.inet_pton(socket.AF_INET, i.local_ip4)
Matus Fabian69126282017-08-14 23:39:58 -07001067 cls.pg5._remote_hosts[0]._ip4 = "172.17.255.4"
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001068 cls.pg5.set_table_ip4(10)
1069 cls.pg6._local_ip4 = "172.16.255.1"
1070 cls.pg6._local_ip4n = socket.inet_pton(socket.AF_INET, i.local_ip4)
1071 cls.pg6._remote_hosts[0]._ip4 = "172.16.255.2"
1072 cls.pg6.set_table_ip4(20)
1073 for i in cls.overlapping_interfaces:
1074 i.config_ip4()
1075 i.admin_up()
1076 i.resolve_arp()
1077
1078 cls.pg7.admin_up()
Martin Gálik406eb1d2017-05-04 04:35:04 -07001079 cls.pg8.admin_up()
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001080
Matus Fabian36ea2d62017-10-24 04:13:49 -07001081 cls.pg9.generate_remote_hosts(2)
1082 cls.pg9.config_ip4()
1083 ip_addr_n = socket.inet_pton(socket.AF_INET, "10.0.0.1")
1084 cls.vapi.sw_interface_add_del_address(cls.pg9.sw_if_index,
1085 ip_addr_n,
1086 24)
1087 cls.pg9.admin_up()
1088 cls.pg9.resolve_arp()
1089 cls.pg9._remote_hosts[1]._ip4 = cls.pg9._remote_hosts[0]._ip4
1090 cls.pg4._remote_ip4 = cls.pg9._remote_hosts[0]._ip4 = "10.0.0.2"
1091 cls.pg9.resolve_arp()
1092
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001093 except Exception:
Matus Fabian2ba92e32017-08-21 07:05:03 -07001094 super(TestNAT44, cls).tearDownClass()
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001095 raise
1096
Matus Fabiande886752016-12-07 03:38:19 -08001097 def test_dynamic(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001098 """ NAT44 dynamic translation test """
Matus Fabiande886752016-12-07 03:38:19 -08001099
Matus Fabian2ba92e32017-08-21 07:05:03 -07001100 self.nat44_add_address(self.nat_addr)
1101 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1102 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1103 is_inside=0)
Matus Fabiande886752016-12-07 03:38:19 -08001104
1105 # in2out
1106 pkts = self.create_stream_in(self.pg0, self.pg1)
1107 self.pg0.add_stream(pkts)
1108 self.pg_enable_capture(self.pg_interfaces)
1109 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001110 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001111 self.verify_capture_out(capture)
1112
1113 # out2in
1114 pkts = self.create_stream_out(self.pg1)
1115 self.pg1.add_stream(pkts)
1116 self.pg_enable_capture(self.pg_interfaces)
1117 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001118 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001119 self.verify_capture_in(capture, self.pg0)
1120
Juraj Slobodab33f4132017-02-08 23:54:21 -08001121 def test_dynamic_icmp_errors_in2out_ttl_1(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001122 """ NAT44 handling of client packets with TTL=1 """
Juraj Slobodab33f4132017-02-08 23:54:21 -08001123
Matus Fabian2ba92e32017-08-21 07:05:03 -07001124 self.nat44_add_address(self.nat_addr)
1125 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1126 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1127 is_inside=0)
Juraj Slobodab33f4132017-02-08 23:54:21 -08001128
1129 # Client side - generate traffic
1130 pkts = self.create_stream_in(self.pg0, self.pg1, ttl=1)
1131 self.pg0.add_stream(pkts)
1132 self.pg_enable_capture(self.pg_interfaces)
1133 self.pg_start()
1134
1135 # Client side - verify ICMP type 11 packets
1136 capture = self.pg0.get_capture(len(pkts))
1137 self.verify_capture_in_with_icmp_errors(capture, self.pg0)
1138
1139 def test_dynamic_icmp_errors_out2in_ttl_1(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001140 """ NAT44 handling of server packets with TTL=1 """
Juraj Slobodab33f4132017-02-08 23:54:21 -08001141
Matus Fabian2ba92e32017-08-21 07:05:03 -07001142 self.nat44_add_address(self.nat_addr)
1143 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1144 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1145 is_inside=0)
Juraj Slobodab33f4132017-02-08 23:54:21 -08001146
1147 # Client side - create sessions
1148 pkts = self.create_stream_in(self.pg0, self.pg1)
1149 self.pg0.add_stream(pkts)
1150 self.pg_enable_capture(self.pg_interfaces)
1151 self.pg_start()
1152
1153 # Server side - generate traffic
1154 capture = self.pg1.get_capture(len(pkts))
1155 self.verify_capture_out(capture)
1156 pkts = self.create_stream_out(self.pg1, ttl=1)
1157 self.pg1.add_stream(pkts)
1158 self.pg_enable_capture(self.pg_interfaces)
1159 self.pg_start()
1160
1161 # Server side - verify ICMP type 11 packets
1162 capture = self.pg1.get_capture(len(pkts))
1163 self.verify_capture_out_with_icmp_errors(capture,
1164 src_ip=self.pg1.local_ip4)
1165
1166 def test_dynamic_icmp_errors_in2out_ttl_2(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001167 """ NAT44 handling of error responses to client packets with TTL=2 """
Juraj Slobodab33f4132017-02-08 23:54:21 -08001168
Matus Fabian2ba92e32017-08-21 07:05:03 -07001169 self.nat44_add_address(self.nat_addr)
1170 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1171 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1172 is_inside=0)
Juraj Slobodab33f4132017-02-08 23:54:21 -08001173
1174 # Client side - generate traffic
1175 pkts = self.create_stream_in(self.pg0, self.pg1, ttl=2)
1176 self.pg0.add_stream(pkts)
1177 self.pg_enable_capture(self.pg_interfaces)
1178 self.pg_start()
1179
1180 # Server side - simulate ICMP type 11 response
1181 capture = self.pg1.get_capture(len(pkts))
1182 pkts = [Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07001183 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Juraj Slobodab33f4132017-02-08 23:54:21 -08001184 ICMP(type=11) / packet[IP] for packet in capture]
1185 self.pg1.add_stream(pkts)
1186 self.pg_enable_capture(self.pg_interfaces)
1187 self.pg_start()
1188
1189 # Client side - verify ICMP type 11 packets
1190 capture = self.pg0.get_capture(len(pkts))
1191 self.verify_capture_in_with_icmp_errors(capture, self.pg0)
1192
1193 def test_dynamic_icmp_errors_out2in_ttl_2(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001194 """ NAT44 handling of error responses to server packets with TTL=2 """
Juraj Slobodab33f4132017-02-08 23:54:21 -08001195
Matus Fabian2ba92e32017-08-21 07:05:03 -07001196 self.nat44_add_address(self.nat_addr)
1197 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1198 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1199 is_inside=0)
Juraj Slobodab33f4132017-02-08 23:54:21 -08001200
1201 # Client side - create sessions
1202 pkts = self.create_stream_in(self.pg0, self.pg1)
1203 self.pg0.add_stream(pkts)
1204 self.pg_enable_capture(self.pg_interfaces)
1205 self.pg_start()
1206
1207 # Server side - generate traffic
1208 capture = self.pg1.get_capture(len(pkts))
1209 self.verify_capture_out(capture)
1210 pkts = self.create_stream_out(self.pg1, ttl=2)
1211 self.pg1.add_stream(pkts)
1212 self.pg_enable_capture(self.pg_interfaces)
1213 self.pg_start()
1214
1215 # Client side - simulate ICMP type 11 response
1216 capture = self.pg0.get_capture(len(pkts))
1217 pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1218 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
1219 ICMP(type=11) / packet[IP] for packet in capture]
1220 self.pg0.add_stream(pkts)
1221 self.pg_enable_capture(self.pg_interfaces)
1222 self.pg_start()
1223
1224 # Server side - verify ICMP type 11 packets
1225 capture = self.pg1.get_capture(len(pkts))
1226 self.verify_capture_out_with_icmp_errors(capture)
1227
Juraj Sloboda665e4822017-02-16 17:17:19 -08001228 def test_ping_out_interface_from_outside(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001229 """ Ping NAT44 out interface from outside network """
Juraj Sloboda665e4822017-02-16 17:17:19 -08001230
Matus Fabian2ba92e32017-08-21 07:05:03 -07001231 self.nat44_add_address(self.nat_addr)
1232 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1233 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1234 is_inside=0)
Juraj Sloboda665e4822017-02-16 17:17:19 -08001235
1236 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1237 IP(src=self.pg1.remote_ip4, dst=self.pg1.local_ip4) /
1238 ICMP(id=self.icmp_id_out, type='echo-request'))
1239 pkts = [p]
1240 self.pg1.add_stream(pkts)
1241 self.pg_enable_capture(self.pg_interfaces)
1242 self.pg_start()
1243 capture = self.pg1.get_capture(len(pkts))
Juraj Sloboda665e4822017-02-16 17:17:19 -08001244 packet = capture[0]
1245 try:
1246 self.assertEqual(packet[IP].src, self.pg1.local_ip4)
1247 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
1248 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
1249 self.assertEqual(packet[ICMP].type, 0) # echo reply
1250 except:
1251 self.logger.error(ppp("Unexpected or invalid packet "
1252 "(outside network):", packet))
1253 raise
1254
Juraj Slobodad3677682017-04-14 03:24:45 +02001255 def test_ping_internal_host_from_outside(self):
1256 """ Ping internal host from outside network """
1257
Matus Fabian2ba92e32017-08-21 07:05:03 -07001258 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr)
1259 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1260 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1261 is_inside=0)
Juraj Slobodad3677682017-04-14 03:24:45 +02001262
1263 # out2in
1264 pkt = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07001265 IP(src=self.pg1.remote_ip4, dst=self.nat_addr, ttl=64) /
Juraj Slobodad3677682017-04-14 03:24:45 +02001266 ICMP(id=self.icmp_id_out, type='echo-request'))
1267 self.pg1.add_stream(pkt)
1268 self.pg_enable_capture(self.pg_interfaces)
1269 self.pg_start()
1270 capture = self.pg0.get_capture(1)
Matus Fabian05ca4a32018-09-04 23:45:13 -07001271 self.verify_capture_in(capture, self.pg0)
Juraj Slobodad3677682017-04-14 03:24:45 +02001272 self.assert_equal(capture[0][IP].proto, IP_PROTOS.icmp)
1273
1274 # in2out
1275 pkt = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1276 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4, ttl=64) /
1277 ICMP(id=self.icmp_id_in, type='echo-reply'))
1278 self.pg0.add_stream(pkt)
1279 self.pg_enable_capture(self.pg_interfaces)
1280 self.pg_start()
1281 capture = self.pg1.get_capture(1)
Matus Fabian05ca4a32018-09-04 23:45:13 -07001282 self.verify_capture_out(capture, same_port=True)
Juraj Slobodad3677682017-04-14 03:24:45 +02001283 self.assert_equal(capture[0][IP].proto, IP_PROTOS.icmp)
1284
Matus Fabianc79396e2018-07-23 00:05:22 -07001285 def test_forwarding(self):
Juraj Sloboda7b929792017-11-23 13:20:48 +01001286 """ NAT44 forwarding test """
1287
1288 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1289 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1290 is_inside=0)
1291 self.vapi.nat44_forwarding_enable_disable(1)
1292
1293 real_ip = self.pg0.remote_ip4n
1294 alias_ip = self.nat_addr_n
1295 self.vapi.nat44_add_del_static_mapping(local_ip=real_ip,
1296 external_ip=alias_ip)
1297
1298 try:
Matus Fabianc79396e2018-07-23 00:05:22 -07001299 # static mapping match
Juraj Sloboda7b929792017-11-23 13:20:48 +01001300
1301 pkts = self.create_stream_out(self.pg1)
1302 self.pg1.add_stream(pkts)
1303 self.pg_enable_capture(self.pg_interfaces)
1304 self.pg_start()
1305 capture = self.pg0.get_capture(len(pkts))
1306 self.verify_capture_in(capture, self.pg0)
1307
1308 pkts = self.create_stream_in(self.pg0, self.pg1)
1309 self.pg0.add_stream(pkts)
1310 self.pg_enable_capture(self.pg_interfaces)
1311 self.pg_start()
1312 capture = self.pg1.get_capture(len(pkts))
1313 self.verify_capture_out(capture, same_port=True)
1314
Matus Fabianc79396e2018-07-23 00:05:22 -07001315 # no static mapping match
Juraj Sloboda7b929792017-11-23 13:20:48 +01001316
1317 host0 = self.pg0.remote_hosts[0]
1318 self.pg0.remote_hosts[0] = self.pg0.remote_hosts[1]
1319 try:
1320 pkts = self.create_stream_out(self.pg1,
1321 dst_ip=self.pg0.remote_ip4,
1322 use_inside_ports=True)
1323 self.pg1.add_stream(pkts)
1324 self.pg_enable_capture(self.pg_interfaces)
1325 self.pg_start()
1326 capture = self.pg0.get_capture(len(pkts))
1327 self.verify_capture_in(capture, self.pg0)
1328
1329 pkts = self.create_stream_in(self.pg0, self.pg1)
1330 self.pg0.add_stream(pkts)
1331 self.pg_enable_capture(self.pg_interfaces)
1332 self.pg_start()
1333 capture = self.pg1.get_capture(len(pkts))
1334 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
1335 same_port=True)
1336 finally:
1337 self.pg0.remote_hosts[0] = host0
1338
1339 finally:
1340 self.vapi.nat44_forwarding_enable_disable(0)
1341 self.vapi.nat44_add_del_static_mapping(local_ip=real_ip,
1342 external_ip=alias_ip,
1343 is_add=0)
1344
Matus Fabiande886752016-12-07 03:38:19 -08001345 def test_static_in(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001346 """ 1:1 NAT initialized from inside network """
Matus Fabiande886752016-12-07 03:38:19 -08001347
1348 nat_ip = "10.0.0.10"
1349 self.tcp_port_out = 6303
1350 self.udp_port_out = 6304
1351 self.icmp_id_out = 6305
1352
Matus Fabian2ba92e32017-08-21 07:05:03 -07001353 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
1354 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1355 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1356 is_inside=0)
Matus Fabian5f224992018-01-25 21:59:16 -08001357 sm = self.vapi.nat44_static_mapping_dump()
1358 self.assertEqual(len(sm), 1)
1359 self.assertEqual((sm[0].tag).split('\0', 1)[0], '')
Matus Fabian9dba7812018-01-31 01:13:23 -08001360 self.assertEqual(sm[0].protocol, 0)
1361 self.assertEqual(sm[0].local_port, 0)
1362 self.assertEqual(sm[0].external_port, 0)
Matus Fabiande886752016-12-07 03:38:19 -08001363
1364 # in2out
1365 pkts = self.create_stream_in(self.pg0, self.pg1)
1366 self.pg0.add_stream(pkts)
1367 self.pg_enable_capture(self.pg_interfaces)
1368 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001369 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001370 self.verify_capture_out(capture, nat_ip, True)
1371
1372 # out2in
1373 pkts = self.create_stream_out(self.pg1, nat_ip)
1374 self.pg1.add_stream(pkts)
1375 self.pg_enable_capture(self.pg_interfaces)
1376 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001377 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001378 self.verify_capture_in(capture, self.pg0)
1379
1380 def test_static_out(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001381 """ 1:1 NAT initialized from outside network """
Matus Fabiande886752016-12-07 03:38:19 -08001382
1383 nat_ip = "10.0.0.20"
1384 self.tcp_port_out = 6303
1385 self.udp_port_out = 6304
1386 self.icmp_id_out = 6305
Matus Fabian5f224992018-01-25 21:59:16 -08001387 tag = "testTAG"
Matus Fabiande886752016-12-07 03:38:19 -08001388
Matus Fabian5f224992018-01-25 21:59:16 -08001389 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip, tag=tag)
Matus Fabian2ba92e32017-08-21 07:05:03 -07001390 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1391 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1392 is_inside=0)
Matus Fabian5f224992018-01-25 21:59:16 -08001393 sm = self.vapi.nat44_static_mapping_dump()
1394 self.assertEqual(len(sm), 1)
1395 self.assertEqual((sm[0].tag).split('\0', 1)[0], tag)
Matus Fabiande886752016-12-07 03:38:19 -08001396
1397 # out2in
1398 pkts = self.create_stream_out(self.pg1, nat_ip)
1399 self.pg1.add_stream(pkts)
1400 self.pg_enable_capture(self.pg_interfaces)
1401 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001402 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001403 self.verify_capture_in(capture, self.pg0)
1404
1405 # in2out
1406 pkts = self.create_stream_in(self.pg0, self.pg1)
1407 self.pg0.add_stream(pkts)
1408 self.pg_enable_capture(self.pg_interfaces)
1409 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001410 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001411 self.verify_capture_out(capture, nat_ip, True)
1412
1413 def test_static_with_port_in(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001414 """ 1:1 NAPT initialized from inside network """
Matus Fabiande886752016-12-07 03:38:19 -08001415
1416 self.tcp_port_out = 3606
1417 self.udp_port_out = 3607
1418 self.icmp_id_out = 3608
1419
Matus Fabian2ba92e32017-08-21 07:05:03 -07001420 self.nat44_add_address(self.nat_addr)
1421 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1422 self.tcp_port_in, self.tcp_port_out,
1423 proto=IP_PROTOS.tcp)
1424 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1425 self.udp_port_in, self.udp_port_out,
1426 proto=IP_PROTOS.udp)
1427 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1428 self.icmp_id_in, self.icmp_id_out,
1429 proto=IP_PROTOS.icmp)
1430 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1431 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1432 is_inside=0)
Matus Fabiande886752016-12-07 03:38:19 -08001433
1434 # in2out
1435 pkts = self.create_stream_in(self.pg0, self.pg1)
1436 self.pg0.add_stream(pkts)
1437 self.pg_enable_capture(self.pg_interfaces)
1438 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001439 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001440 self.verify_capture_out(capture)
1441
1442 # out2in
1443 pkts = self.create_stream_out(self.pg1)
1444 self.pg1.add_stream(pkts)
1445 self.pg_enable_capture(self.pg_interfaces)
1446 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001447 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001448 self.verify_capture_in(capture, self.pg0)
1449
1450 def test_static_with_port_out(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001451 """ 1:1 NAPT initialized from outside network """
Matus Fabiande886752016-12-07 03:38:19 -08001452
1453 self.tcp_port_out = 30606
1454 self.udp_port_out = 30607
1455 self.icmp_id_out = 30608
1456
Matus Fabian2ba92e32017-08-21 07:05:03 -07001457 self.nat44_add_address(self.nat_addr)
1458 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1459 self.tcp_port_in, self.tcp_port_out,
1460 proto=IP_PROTOS.tcp)
1461 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1462 self.udp_port_in, self.udp_port_out,
1463 proto=IP_PROTOS.udp)
1464 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1465 self.icmp_id_in, self.icmp_id_out,
1466 proto=IP_PROTOS.icmp)
1467 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1468 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1469 is_inside=0)
Matus Fabiande886752016-12-07 03:38:19 -08001470
1471 # out2in
1472 pkts = self.create_stream_out(self.pg1)
1473 self.pg1.add_stream(pkts)
1474 self.pg_enable_capture(self.pg_interfaces)
1475 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001476 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001477 self.verify_capture_in(capture, self.pg0)
1478
1479 # in2out
1480 pkts = self.create_stream_in(self.pg0, self.pg1)
1481 self.pg0.add_stream(pkts)
1482 self.pg_enable_capture(self.pg_interfaces)
1483 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001484 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001485 self.verify_capture_out(capture)
1486
1487 def test_static_vrf_aware(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001488 """ 1:1 NAT VRF awareness """
Matus Fabiande886752016-12-07 03:38:19 -08001489
1490 nat_ip1 = "10.0.0.30"
1491 nat_ip2 = "10.0.0.40"
1492 self.tcp_port_out = 6303
1493 self.udp_port_out = 6304
1494 self.icmp_id_out = 6305
1495
Matus Fabian2ba92e32017-08-21 07:05:03 -07001496 self.nat44_add_static_mapping(self.pg4.remote_ip4, nat_ip1,
1497 vrf_id=10)
1498 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip2,
1499 vrf_id=10)
1500 self.vapi.nat44_interface_add_del_feature(self.pg3.sw_if_index,
1501 is_inside=0)
1502 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1503 self.vapi.nat44_interface_add_del_feature(self.pg4.sw_if_index)
Matus Fabiande886752016-12-07 03:38:19 -08001504
Matus Fabian2ba92e32017-08-21 07:05:03 -07001505 # inside interface VRF match NAT44 static mapping VRF
Matus Fabiande886752016-12-07 03:38:19 -08001506 pkts = self.create_stream_in(self.pg4, self.pg3)
1507 self.pg4.add_stream(pkts)
1508 self.pg_enable_capture(self.pg_interfaces)
1509 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001510 capture = self.pg3.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001511 self.verify_capture_out(capture, nat_ip1, True)
1512
Matus Fabian2ba92e32017-08-21 07:05:03 -07001513 # inside interface VRF don't match NAT44 static mapping VRF (packets
Matus Fabiande886752016-12-07 03:38:19 -08001514 # are dropped)
1515 pkts = self.create_stream_in(self.pg0, self.pg3)
1516 self.pg0.add_stream(pkts)
1517 self.pg_enable_capture(self.pg_interfaces)
1518 self.pg_start()
Klement Sekera9225dee2016-12-12 08:36:58 +01001519 self.pg3.assert_nothing_captured()
Matus Fabiande886752016-12-07 03:38:19 -08001520
Matus Fabianb793d092018-01-31 05:50:21 -08001521 def test_dynamic_to_static(self):
1522 """ Switch from dynamic translation to 1:1NAT """
1523 nat_ip = "10.0.0.10"
1524 self.tcp_port_out = 6303
1525 self.udp_port_out = 6304
1526 self.icmp_id_out = 6305
1527
1528 self.nat44_add_address(self.nat_addr)
1529 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1530 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1531 is_inside=0)
1532
1533 # dynamic
1534 pkts = self.create_stream_in(self.pg0, self.pg1)
1535 self.pg0.add_stream(pkts)
1536 self.pg_enable_capture(self.pg_interfaces)
1537 self.pg_start()
1538 capture = self.pg1.get_capture(len(pkts))
1539 self.verify_capture_out(capture)
1540
1541 # 1:1NAT
1542 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
1543 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
1544 self.assertEqual(len(sessions), 0)
1545 pkts = self.create_stream_in(self.pg0, self.pg1)
1546 self.pg0.add_stream(pkts)
1547 self.pg_enable_capture(self.pg_interfaces)
1548 self.pg_start()
1549 capture = self.pg1.get_capture(len(pkts))
1550 self.verify_capture_out(capture, nat_ip, True)
1551
Matus Fabianab7a8052017-11-28 04:29:41 -08001552 def test_identity_nat(self):
1553 """ Identity NAT """
1554
1555 self.vapi.nat44_add_del_identity_mapping(ip=self.pg0.remote_ip4n)
1556 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1557 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1558 is_inside=0)
1559
1560 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
1561 IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
1562 TCP(sport=12345, dport=56789))
1563 self.pg1.add_stream(p)
1564 self.pg_enable_capture(self.pg_interfaces)
1565 self.pg_start()
1566 capture = self.pg0.get_capture(1)
1567 p = capture[0]
1568 try:
1569 ip = p[IP]
1570 tcp = p[TCP]
1571 self.assertEqual(ip.dst, self.pg0.remote_ip4)
1572 self.assertEqual(ip.src, self.pg1.remote_ip4)
1573 self.assertEqual(tcp.dport, 56789)
1574 self.assertEqual(tcp.sport, 12345)
Klement Sekerad81ae412018-05-16 10:52:54 +02001575 self.assert_packet_checksums_valid(p)
Matus Fabianab7a8052017-11-28 04:29:41 -08001576 except:
1577 self.logger.error(ppp("Unexpected or invalid packet:", p))
1578 raise
1579
Matus Fabiande886752016-12-07 03:38:19 -08001580 def test_multiple_inside_interfaces(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001581 """ NAT44 multiple non-overlapping address space inside interfaces """
Matus Fabiande886752016-12-07 03:38:19 -08001582
Matus Fabian2ba92e32017-08-21 07:05:03 -07001583 self.nat44_add_address(self.nat_addr)
1584 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1585 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
1586 self.vapi.nat44_interface_add_del_feature(self.pg3.sw_if_index,
1587 is_inside=0)
Matus Fabiande886752016-12-07 03:38:19 -08001588
Matus Fabian2ba92e32017-08-21 07:05:03 -07001589 # between two NAT44 inside interfaces (no translation)
Matus Fabian675a69c2017-01-18 01:46:01 -08001590 pkts = self.create_stream_in(self.pg0, self.pg1)
1591 self.pg0.add_stream(pkts)
1592 self.pg_enable_capture(self.pg_interfaces)
1593 self.pg_start()
1594 capture = self.pg1.get_capture(len(pkts))
1595 self.verify_capture_no_translation(capture, self.pg0, self.pg1)
1596
Matus Fabian2ba92e32017-08-21 07:05:03 -07001597 # from NAT44 inside to interface without NAT44 feature (no translation)
Matus Fabian675a69c2017-01-18 01:46:01 -08001598 pkts = self.create_stream_in(self.pg0, self.pg2)
1599 self.pg0.add_stream(pkts)
1600 self.pg_enable_capture(self.pg_interfaces)
1601 self.pg_start()
1602 capture = self.pg2.get_capture(len(pkts))
1603 self.verify_capture_no_translation(capture, self.pg0, self.pg2)
1604
Matus Fabiande886752016-12-07 03:38:19 -08001605 # in2out 1st interface
1606 pkts = self.create_stream_in(self.pg0, self.pg3)
1607 self.pg0.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 1st 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.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001619 self.verify_capture_in(capture, self.pg0)
1620
1621 # in2out 2nd interface
1622 pkts = self.create_stream_in(self.pg1, self.pg3)
1623 self.pg1.add_stream(pkts)
1624 self.pg_enable_capture(self.pg_interfaces)
1625 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001626 capture = self.pg3.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001627 self.verify_capture_out(capture)
1628
1629 # out2in 2nd interface
1630 pkts = self.create_stream_out(self.pg3)
1631 self.pg3.add_stream(pkts)
1632 self.pg_enable_capture(self.pg_interfaces)
1633 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001634 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001635 self.verify_capture_in(capture, self.pg1)
1636
Matus Fabiande886752016-12-07 03:38:19 -08001637 def test_inside_overlapping_interfaces(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001638 """ NAT44 multiple inside interfaces with overlapping address space """
Matus Fabiande886752016-12-07 03:38:19 -08001639
Matus Fabian675a69c2017-01-18 01:46:01 -08001640 static_nat_ip = "10.0.0.10"
Matus Fabian2ba92e32017-08-21 07:05:03 -07001641 self.nat44_add_address(self.nat_addr)
1642 self.vapi.nat44_interface_add_del_feature(self.pg3.sw_if_index,
1643 is_inside=0)
1644 self.vapi.nat44_interface_add_del_feature(self.pg4.sw_if_index)
1645 self.vapi.nat44_interface_add_del_feature(self.pg5.sw_if_index)
1646 self.vapi.nat44_interface_add_del_feature(self.pg6.sw_if_index)
1647 self.nat44_add_static_mapping(self.pg6.remote_ip4, static_nat_ip,
1648 vrf_id=20)
Matus Fabian675a69c2017-01-18 01:46:01 -08001649
Matus Fabian2ba92e32017-08-21 07:05:03 -07001650 # between NAT44 inside interfaces with same VRF (no translation)
Matus Fabian675a69c2017-01-18 01:46:01 -08001651 pkts = self.create_stream_in(self.pg4, self.pg5)
1652 self.pg4.add_stream(pkts)
1653 self.pg_enable_capture(self.pg_interfaces)
1654 self.pg_start()
1655 capture = self.pg5.get_capture(len(pkts))
1656 self.verify_capture_no_translation(capture, self.pg4, self.pg5)
1657
Matus Fabian2ba92e32017-08-21 07:05:03 -07001658 # between NAT44 inside interfaces with different VRF (hairpinning)
Matus Fabian675a69c2017-01-18 01:46:01 -08001659 p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
1660 IP(src=self.pg4.remote_ip4, dst=static_nat_ip) /
1661 TCP(sport=1234, dport=5678))
1662 self.pg4.add_stream(p)
1663 self.pg_enable_capture(self.pg_interfaces)
1664 self.pg_start()
1665 capture = self.pg6.get_capture(1)
1666 p = capture[0]
1667 try:
1668 ip = p[IP]
1669 tcp = p[TCP]
Matus Fabian2ba92e32017-08-21 07:05:03 -07001670 self.assertEqual(ip.src, self.nat_addr)
Matus Fabian675a69c2017-01-18 01:46:01 -08001671 self.assertEqual(ip.dst, self.pg6.remote_ip4)
1672 self.assertNotEqual(tcp.sport, 1234)
1673 self.assertEqual(tcp.dport, 5678)
1674 except:
1675 self.logger.error(ppp("Unexpected or invalid packet:", p))
1676 raise
Matus Fabiande886752016-12-07 03:38:19 -08001677
1678 # in2out 1st interface
1679 pkts = self.create_stream_in(self.pg4, self.pg3)
1680 self.pg4.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 1st 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.pg4.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001692 self.verify_capture_in(capture, self.pg4)
1693
1694 # in2out 2nd interface
1695 pkts = self.create_stream_in(self.pg5, self.pg3)
1696 self.pg5.add_stream(pkts)
1697 self.pg_enable_capture(self.pg_interfaces)
1698 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001699 capture = self.pg3.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001700 self.verify_capture_out(capture)
1701
1702 # out2in 2nd interface
1703 pkts = self.create_stream_out(self.pg3)
1704 self.pg3.add_stream(pkts)
1705 self.pg_enable_capture(self.pg_interfaces)
1706 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001707 capture = self.pg5.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001708 self.verify_capture_in(capture, self.pg5)
1709
magalik23caa882017-02-08 23:25:45 -08001710 # pg5 session dump
Matus Fabian2ba92e32017-08-21 07:05:03 -07001711 addresses = self.vapi.nat44_address_dump()
magalik23caa882017-02-08 23:25:45 -08001712 self.assertEqual(len(addresses), 1)
Matus Fabian2ba92e32017-08-21 07:05:03 -07001713 sessions = self.vapi.nat44_user_session_dump(self.pg5.remote_ip4n, 10)
magalik23caa882017-02-08 23:25:45 -08001714 self.assertEqual(len(sessions), 3)
1715 for session in sessions:
1716 self.assertFalse(session.is_static)
1717 self.assertEqual(session.inside_ip_address[0:4],
1718 self.pg5.remote_ip4n)
1719 self.assertEqual(session.outside_ip_address,
1720 addresses[0].ip_address)
1721 self.assertEqual(sessions[0].protocol, IP_PROTOS.tcp)
1722 self.assertEqual(sessions[1].protocol, IP_PROTOS.udp)
1723 self.assertEqual(sessions[2].protocol, IP_PROTOS.icmp)
1724 self.assertEqual(sessions[0].inside_port, self.tcp_port_in)
1725 self.assertEqual(sessions[1].inside_port, self.udp_port_in)
1726 self.assertEqual(sessions[2].inside_port, self.icmp_id_in)
1727 self.assertEqual(sessions[0].outside_port, self.tcp_port_out)
1728 self.assertEqual(sessions[1].outside_port, self.udp_port_out)
1729 self.assertEqual(sessions[2].outside_port, self.icmp_id_out)
1730
Matus Fabiande886752016-12-07 03:38:19 -08001731 # in2out 3rd interface
1732 pkts = self.create_stream_in(self.pg6, self.pg3)
1733 self.pg6.add_stream(pkts)
1734 self.pg_enable_capture(self.pg_interfaces)
1735 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001736 capture = self.pg3.get_capture(len(pkts))
Matus Fabian675a69c2017-01-18 01:46:01 -08001737 self.verify_capture_out(capture, static_nat_ip, True)
Matus Fabiande886752016-12-07 03:38:19 -08001738
1739 # out2in 3rd interface
Matus Fabian675a69c2017-01-18 01:46:01 -08001740 pkts = self.create_stream_out(self.pg3, static_nat_ip)
Matus Fabiande886752016-12-07 03:38:19 -08001741 self.pg3.add_stream(pkts)
1742 self.pg_enable_capture(self.pg_interfaces)
1743 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001744 capture = self.pg6.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001745 self.verify_capture_in(capture, self.pg6)
1746
magalik23caa882017-02-08 23:25:45 -08001747 # general user and session dump verifications
Matus Fabian2ba92e32017-08-21 07:05:03 -07001748 users = self.vapi.nat44_user_dump()
magalik23caa882017-02-08 23:25:45 -08001749 self.assertTrue(len(users) >= 3)
Matus Fabian2ba92e32017-08-21 07:05:03 -07001750 addresses = self.vapi.nat44_address_dump()
magalik23caa882017-02-08 23:25:45 -08001751 self.assertEqual(len(addresses), 1)
1752 for user in users:
Matus Fabian2ba92e32017-08-21 07:05:03 -07001753 sessions = self.vapi.nat44_user_session_dump(user.ip_address,
1754 user.vrf_id)
magalik23caa882017-02-08 23:25:45 -08001755 for session in sessions:
1756 self.assertEqual(user.ip_address, session.inside_ip_address)
1757 self.assertTrue(session.total_bytes > session.total_pkts > 0)
1758 self.assertTrue(session.protocol in
1759 [IP_PROTOS.tcp, IP_PROTOS.udp,
1760 IP_PROTOS.icmp])
Matus Fabian70a26ac2018-05-14 06:20:28 -07001761 self.assertFalse(session.ext_host_valid)
magalik23caa882017-02-08 23:25:45 -08001762
1763 # pg4 session dump
Matus Fabian2ba92e32017-08-21 07:05:03 -07001764 sessions = self.vapi.nat44_user_session_dump(self.pg4.remote_ip4n, 10)
magalik23caa882017-02-08 23:25:45 -08001765 self.assertTrue(len(sessions) >= 4)
1766 for session in sessions:
1767 self.assertFalse(session.is_static)
1768 self.assertEqual(session.inside_ip_address[0:4],
1769 self.pg4.remote_ip4n)
1770 self.assertEqual(session.outside_ip_address,
1771 addresses[0].ip_address)
1772
1773 # pg6 session dump
Matus Fabian2ba92e32017-08-21 07:05:03 -07001774 sessions = self.vapi.nat44_user_session_dump(self.pg6.remote_ip4n, 20)
magalik23caa882017-02-08 23:25:45 -08001775 self.assertTrue(len(sessions) >= 3)
1776 for session in sessions:
1777 self.assertTrue(session.is_static)
1778 self.assertEqual(session.inside_ip_address[0:4],
1779 self.pg6.remote_ip4n)
1780 self.assertEqual(map(ord, session.outside_ip_address[0:4]),
1781 map(int, static_nat_ip.split('.')))
1782 self.assertTrue(session.inside_port in
1783 [self.tcp_port_in, self.udp_port_in,
1784 self.icmp_id_in])
1785
Matus Fabianf78a70d2016-12-12 04:30:39 -08001786 def test_hairpinning(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001787 """ NAT44 hairpinning - 1:1 NAPT """
Matus Fabianf78a70d2016-12-12 04:30:39 -08001788
1789 host = self.pg0.remote_hosts[0]
1790 server = self.pg0.remote_hosts[1]
1791 host_in_port = 1234
1792 host_out_port = 0
1793 server_in_port = 5678
1794 server_out_port = 8765
1795
Matus Fabian2ba92e32017-08-21 07:05:03 -07001796 self.nat44_add_address(self.nat_addr)
1797 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1798 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1799 is_inside=0)
Matus Fabianf78a70d2016-12-12 04:30:39 -08001800 # add static mapping for server
Matus Fabian2ba92e32017-08-21 07:05:03 -07001801 self.nat44_add_static_mapping(server.ip4, self.nat_addr,
1802 server_in_port, server_out_port,
1803 proto=IP_PROTOS.tcp)
Matus Fabianf78a70d2016-12-12 04:30:39 -08001804
1805 # send packet from host to server
1806 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07001807 IP(src=host.ip4, dst=self.nat_addr) /
Matus Fabianf78a70d2016-12-12 04:30:39 -08001808 TCP(sport=host_in_port, dport=server_out_port))
1809 self.pg0.add_stream(p)
1810 self.pg_enable_capture(self.pg_interfaces)
1811 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001812 capture = self.pg0.get_capture(1)
Matus Fabianf78a70d2016-12-12 04:30:39 -08001813 p = capture[0]
1814 try:
1815 ip = p[IP]
1816 tcp = p[TCP]
Matus Fabian2ba92e32017-08-21 07:05:03 -07001817 self.assertEqual(ip.src, self.nat_addr)
Matus Fabianf78a70d2016-12-12 04:30:39 -08001818 self.assertEqual(ip.dst, server.ip4)
1819 self.assertNotEqual(tcp.sport, host_in_port)
1820 self.assertEqual(tcp.dport, server_in_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02001821 self.assert_packet_checksums_valid(p)
Matus Fabianf78a70d2016-12-12 04:30:39 -08001822 host_out_port = tcp.sport
1823 except:
Klement Sekera9225dee2016-12-12 08:36:58 +01001824 self.logger.error(ppp("Unexpected or invalid packet:", p))
Matus Fabianf78a70d2016-12-12 04:30:39 -08001825 raise
1826
1827 # send reply from server to host
1828 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07001829 IP(src=server.ip4, dst=self.nat_addr) /
Matus Fabianf78a70d2016-12-12 04:30:39 -08001830 TCP(sport=server_in_port, dport=host_out_port))
1831 self.pg0.add_stream(p)
1832 self.pg_enable_capture(self.pg_interfaces)
1833 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001834 capture = self.pg0.get_capture(1)
Matus Fabianf78a70d2016-12-12 04:30:39 -08001835 p = capture[0]
1836 try:
1837 ip = p[IP]
1838 tcp = p[TCP]
Matus Fabian2ba92e32017-08-21 07:05:03 -07001839 self.assertEqual(ip.src, self.nat_addr)
Matus Fabianf78a70d2016-12-12 04:30:39 -08001840 self.assertEqual(ip.dst, host.ip4)
1841 self.assertEqual(tcp.sport, server_out_port)
1842 self.assertEqual(tcp.dport, host_in_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02001843 self.assert_packet_checksums_valid(p)
Matus Fabianf78a70d2016-12-12 04:30:39 -08001844 except:
Matus Fabiane82488f2018-01-18 03:38:45 -08001845 self.logger.error(ppp("Unexpected or invalid packet:", p))
Matus Fabianf78a70d2016-12-12 04:30:39 -08001846 raise
1847
Matus Fabian6fa74c62017-06-05 05:55:48 -07001848 def test_hairpinning2(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001849 """ NAT44 hairpinning - 1:1 NAT"""
Matus Fabian6fa74c62017-06-05 05:55:48 -07001850
1851 server1_nat_ip = "10.0.0.10"
1852 server2_nat_ip = "10.0.0.11"
1853 host = self.pg0.remote_hosts[0]
1854 server1 = self.pg0.remote_hosts[1]
1855 server2 = self.pg0.remote_hosts[2]
1856 server_tcp_port = 22
1857 server_udp_port = 20
1858
Matus Fabian2ba92e32017-08-21 07:05:03 -07001859 self.nat44_add_address(self.nat_addr)
1860 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1861 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1862 is_inside=0)
Matus Fabian6fa74c62017-06-05 05:55:48 -07001863
1864 # add static mapping for servers
Matus Fabian2ba92e32017-08-21 07:05:03 -07001865 self.nat44_add_static_mapping(server1.ip4, server1_nat_ip)
1866 self.nat44_add_static_mapping(server2.ip4, server2_nat_ip)
Matus Fabian6fa74c62017-06-05 05:55:48 -07001867
1868 # host to server1
1869 pkts = []
1870 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1871 IP(src=host.ip4, dst=server1_nat_ip) /
1872 TCP(sport=self.tcp_port_in, dport=server_tcp_port))
1873 pkts.append(p)
1874 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1875 IP(src=host.ip4, dst=server1_nat_ip) /
1876 UDP(sport=self.udp_port_in, dport=server_udp_port))
1877 pkts.append(p)
1878 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1879 IP(src=host.ip4, dst=server1_nat_ip) /
1880 ICMP(id=self.icmp_id_in, type='echo-request'))
1881 pkts.append(p)
1882 self.pg0.add_stream(pkts)
1883 self.pg_enable_capture(self.pg_interfaces)
1884 self.pg_start()
1885 capture = self.pg0.get_capture(len(pkts))
1886 for packet in capture:
1887 try:
Matus Fabian2ba92e32017-08-21 07:05:03 -07001888 self.assertEqual(packet[IP].src, self.nat_addr)
Matus Fabian6fa74c62017-06-05 05:55:48 -07001889 self.assertEqual(packet[IP].dst, server1.ip4)
1890 if packet.haslayer(TCP):
1891 self.assertNotEqual(packet[TCP].sport, self.tcp_port_in)
1892 self.assertEqual(packet[TCP].dport, server_tcp_port)
1893 self.tcp_port_out = packet[TCP].sport
Klement Sekerad81ae412018-05-16 10:52:54 +02001894 self.assert_packet_checksums_valid(packet)
Matus Fabian6fa74c62017-06-05 05:55:48 -07001895 elif packet.haslayer(UDP):
1896 self.assertNotEqual(packet[UDP].sport, self.udp_port_in)
1897 self.assertEqual(packet[UDP].dport, server_udp_port)
1898 self.udp_port_out = packet[UDP].sport
1899 else:
1900 self.assertNotEqual(packet[ICMP].id, self.icmp_id_in)
1901 self.icmp_id_out = packet[ICMP].id
1902 except:
1903 self.logger.error(ppp("Unexpected or invalid packet:", packet))
1904 raise
1905
1906 # server1 to host
1907 pkts = []
1908 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07001909 IP(src=server1.ip4, dst=self.nat_addr) /
Matus Fabian6fa74c62017-06-05 05:55:48 -07001910 TCP(sport=server_tcp_port, dport=self.tcp_port_out))
1911 pkts.append(p)
1912 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07001913 IP(src=server1.ip4, dst=self.nat_addr) /
Matus Fabian6fa74c62017-06-05 05:55:48 -07001914 UDP(sport=server_udp_port, dport=self.udp_port_out))
1915 pkts.append(p)
1916 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07001917 IP(src=server1.ip4, dst=self.nat_addr) /
Matus Fabian6fa74c62017-06-05 05:55:48 -07001918 ICMP(id=self.icmp_id_out, type='echo-reply'))
1919 pkts.append(p)
1920 self.pg0.add_stream(pkts)
1921 self.pg_enable_capture(self.pg_interfaces)
1922 self.pg_start()
1923 capture = self.pg0.get_capture(len(pkts))
1924 for packet in capture:
1925 try:
1926 self.assertEqual(packet[IP].src, server1_nat_ip)
1927 self.assertEqual(packet[IP].dst, host.ip4)
1928 if packet.haslayer(TCP):
1929 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
1930 self.assertEqual(packet[TCP].sport, server_tcp_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02001931 self.assert_packet_checksums_valid(packet)
Matus Fabian6fa74c62017-06-05 05:55:48 -07001932 elif packet.haslayer(UDP):
1933 self.assertEqual(packet[UDP].dport, self.udp_port_in)
1934 self.assertEqual(packet[UDP].sport, server_udp_port)
1935 else:
1936 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
1937 except:
1938 self.logger.error(ppp("Unexpected or invalid packet:", packet))
1939 raise
1940
1941 # server2 to server1
1942 pkts = []
1943 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1944 IP(src=server2.ip4, dst=server1_nat_ip) /
1945 TCP(sport=self.tcp_port_in, dport=server_tcp_port))
1946 pkts.append(p)
1947 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1948 IP(src=server2.ip4, dst=server1_nat_ip) /
1949 UDP(sport=self.udp_port_in, dport=server_udp_port))
1950 pkts.append(p)
1951 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1952 IP(src=server2.ip4, dst=server1_nat_ip) /
1953 ICMP(id=self.icmp_id_in, type='echo-request'))
1954 pkts.append(p)
1955 self.pg0.add_stream(pkts)
1956 self.pg_enable_capture(self.pg_interfaces)
1957 self.pg_start()
1958 capture = self.pg0.get_capture(len(pkts))
1959 for packet in capture:
1960 try:
1961 self.assertEqual(packet[IP].src, server2_nat_ip)
1962 self.assertEqual(packet[IP].dst, server1.ip4)
1963 if packet.haslayer(TCP):
1964 self.assertEqual(packet[TCP].sport, self.tcp_port_in)
1965 self.assertEqual(packet[TCP].dport, server_tcp_port)
1966 self.tcp_port_out = packet[TCP].sport
Klement Sekerad81ae412018-05-16 10:52:54 +02001967 self.assert_packet_checksums_valid(packet)
Matus Fabian6fa74c62017-06-05 05:55:48 -07001968 elif packet.haslayer(UDP):
1969 self.assertEqual(packet[UDP].sport, self.udp_port_in)
1970 self.assertEqual(packet[UDP].dport, server_udp_port)
1971 self.udp_port_out = packet[UDP].sport
1972 else:
1973 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
1974 self.icmp_id_out = packet[ICMP].id
1975 except:
1976 self.logger.error(ppp("Unexpected or invalid packet:", packet))
1977 raise
1978
1979 # server1 to server2
1980 pkts = []
1981 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1982 IP(src=server1.ip4, dst=server2_nat_ip) /
1983 TCP(sport=server_tcp_port, dport=self.tcp_port_out))
1984 pkts.append(p)
1985 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1986 IP(src=server1.ip4, dst=server2_nat_ip) /
1987 UDP(sport=server_udp_port, dport=self.udp_port_out))
1988 pkts.append(p)
1989 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1990 IP(src=server1.ip4, dst=server2_nat_ip) /
1991 ICMP(id=self.icmp_id_out, type='echo-reply'))
1992 pkts.append(p)
1993 self.pg0.add_stream(pkts)
1994 self.pg_enable_capture(self.pg_interfaces)
1995 self.pg_start()
1996 capture = self.pg0.get_capture(len(pkts))
1997 for packet in capture:
1998 try:
1999 self.assertEqual(packet[IP].src, server1_nat_ip)
2000 self.assertEqual(packet[IP].dst, server2.ip4)
2001 if packet.haslayer(TCP):
2002 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
2003 self.assertEqual(packet[TCP].sport, server_tcp_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02002004 self.assert_packet_checksums_valid(packet)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002005 elif packet.haslayer(UDP):
2006 self.assertEqual(packet[UDP].dport, self.udp_port_in)
2007 self.assertEqual(packet[UDP].sport, server_udp_port)
2008 else:
2009 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
2010 except:
2011 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2012 raise
2013
Matus Fabian9902fcd2016-12-21 23:58:46 -08002014 def test_max_translations_per_user(self):
2015 """ MAX translations per user - recycle the least recently used """
2016
Matus Fabian2ba92e32017-08-21 07:05:03 -07002017 self.nat44_add_address(self.nat_addr)
2018 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2019 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2020 is_inside=0)
Matus Fabian9902fcd2016-12-21 23:58:46 -08002021
2022 # get maximum number of translations per user
Matus Fabian2ba92e32017-08-21 07:05:03 -07002023 nat44_config = self.vapi.nat_show_config()
Matus Fabian9902fcd2016-12-21 23:58:46 -08002024
2025 # send more than maximum number of translations per user packets
Matus Fabian2ba92e32017-08-21 07:05:03 -07002026 pkts_num = nat44_config.max_translations_per_user + 5
Matus Fabian9902fcd2016-12-21 23:58:46 -08002027 pkts = []
2028 for port in range(0, pkts_num):
2029 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2030 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2031 TCP(sport=1025 + port))
2032 pkts.append(p)
2033 self.pg0.add_stream(pkts)
2034 self.pg_enable_capture(self.pg_interfaces)
2035 self.pg_start()
2036
2037 # verify number of translated packet
Klement Sekeradab231a2016-12-21 08:50:14 +01002038 self.pg1.get_capture(pkts_num)
Matus Fabian9902fcd2016-12-21 23:58:46 -08002039
Matus Fabian132dc492018-05-09 04:51:03 -07002040 users = self.vapi.nat44_user_dump()
2041 for user in users:
2042 if user.ip_address == self.pg0.remote_ip4n:
2043 self.assertEqual(user.nsessions,
2044 nat44_config.max_translations_per_user)
2045 self.assertEqual(user.nstaticsessions, 0)
2046
2047 tcp_port = 22
2048 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
2049 tcp_port, tcp_port,
2050 proto=IP_PROTOS.tcp)
2051 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2052 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2053 TCP(sport=tcp_port))
2054 self.pg0.add_stream(p)
2055 self.pg_enable_capture(self.pg_interfaces)
2056 self.pg_start()
2057 self.pg1.get_capture(1)
2058 users = self.vapi.nat44_user_dump()
2059 for user in users:
2060 if user.ip_address == self.pg0.remote_ip4n:
2061 self.assertEqual(user.nsessions,
2062 nat44_config.max_translations_per_user - 1)
2063 self.assertEqual(user.nstaticsessions, 1)
2064
Matus Fabian8bf68e82017-01-12 04:24:35 -08002065 def test_interface_addr(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002066 """ Acquire NAT44 addresses from interface """
2067 self.vapi.nat44_add_interface_addr(self.pg7.sw_if_index)
Matus Fabian8bf68e82017-01-12 04:24:35 -08002068
2069 # no address in NAT pool
Matus Fabian2ba92e32017-08-21 07:05:03 -07002070 adresses = self.vapi.nat44_address_dump()
Matus Fabian8bf68e82017-01-12 04:24:35 -08002071 self.assertEqual(0, len(adresses))
2072
2073 # configure interface address and check NAT address pool
2074 self.pg7.config_ip4()
Matus Fabian2ba92e32017-08-21 07:05:03 -07002075 adresses = self.vapi.nat44_address_dump()
Matus Fabian8bf68e82017-01-12 04:24:35 -08002076 self.assertEqual(1, len(adresses))
Matus Fabian36532bd2017-01-23 23:42:28 -08002077 self.assertEqual(adresses[0].ip_address[0:4], self.pg7.local_ip4n)
Matus Fabian8bf68e82017-01-12 04:24:35 -08002078
2079 # remove interface address and check NAT address pool
2080 self.pg7.unconfig_ip4()
Matus Fabian2ba92e32017-08-21 07:05:03 -07002081 adresses = self.vapi.nat44_address_dump()
Matus Fabian8bf68e82017-01-12 04:24:35 -08002082 self.assertEqual(0, len(adresses))
2083
Matus Fabian36532bd2017-01-23 23:42:28 -08002084 def test_interface_addr_static_mapping(self):
2085 """ Static mapping with addresses from interface """
Matus Fabian5f224992018-01-25 21:59:16 -08002086 tag = "testTAG"
2087
Matus Fabian2ba92e32017-08-21 07:05:03 -07002088 self.vapi.nat44_add_interface_addr(self.pg7.sw_if_index)
2089 self.nat44_add_static_mapping(
2090 '1.2.3.4',
Matus Fabian5f224992018-01-25 21:59:16 -08002091 external_sw_if_index=self.pg7.sw_if_index,
2092 tag=tag)
Matus Fabian36532bd2017-01-23 23:42:28 -08002093
Matus Fabiane22e5462017-02-14 23:33:43 -08002094 # static mappings with external interface
Matus Fabian2ba92e32017-08-21 07:05:03 -07002095 static_mappings = self.vapi.nat44_static_mapping_dump()
Matus Fabiane22e5462017-02-14 23:33:43 -08002096 self.assertEqual(1, len(static_mappings))
2097 self.assertEqual(self.pg7.sw_if_index,
2098 static_mappings[0].external_sw_if_index)
Matus Fabian5f224992018-01-25 21:59:16 -08002099 self.assertEqual((static_mappings[0].tag).split('\0', 1)[0], tag)
Matus Fabian36532bd2017-01-23 23:42:28 -08002100
2101 # configure interface address and check static mappings
2102 self.pg7.config_ip4()
Matus Fabian2ba92e32017-08-21 07:05:03 -07002103 static_mappings = self.vapi.nat44_static_mapping_dump()
Matus Fabianea2600a2018-03-28 04:06:26 -07002104 self.assertEqual(2, len(static_mappings))
2105 resolved = False
2106 for sm in static_mappings:
2107 if sm.external_sw_if_index == 0xFFFFFFFF:
2108 self.assertEqual(sm.external_ip_address[0:4],
2109 self.pg7.local_ip4n)
2110 self.assertEqual((sm.tag).split('\0', 1)[0], tag)
2111 resolved = True
2112 self.assertTrue(resolved)
Matus Fabian36532bd2017-01-23 23:42:28 -08002113
2114 # remove interface address and check static mappings
2115 self.pg7.unconfig_ip4()
Matus Fabian2ba92e32017-08-21 07:05:03 -07002116 static_mappings = self.vapi.nat44_static_mapping_dump()
Matus Fabianea2600a2018-03-28 04:06:26 -07002117 self.assertEqual(1, len(static_mappings))
2118 self.assertEqual(self.pg7.sw_if_index,
2119 static_mappings[0].external_sw_if_index)
2120 self.assertEqual((static_mappings[0].tag).split('\0', 1)[0], tag)
2121
2122 # configure interface address again and check static mappings
2123 self.pg7.config_ip4()
2124 static_mappings = self.vapi.nat44_static_mapping_dump()
2125 self.assertEqual(2, len(static_mappings))
2126 resolved = False
2127 for sm in static_mappings:
2128 if sm.external_sw_if_index == 0xFFFFFFFF:
2129 self.assertEqual(sm.external_ip_address[0:4],
2130 self.pg7.local_ip4n)
2131 self.assertEqual((sm.tag).split('\0', 1)[0], tag)
2132 resolved = True
2133 self.assertTrue(resolved)
2134
2135 # remove static mapping
2136 self.nat44_add_static_mapping(
2137 '1.2.3.4',
2138 external_sw_if_index=self.pg7.sw_if_index,
2139 tag=tag,
2140 is_add=0)
2141 static_mappings = self.vapi.nat44_static_mapping_dump()
Matus Fabian36532bd2017-01-23 23:42:28 -08002142 self.assertEqual(0, len(static_mappings))
2143
Matus Fabianab7a8052017-11-28 04:29:41 -08002144 def test_interface_addr_identity_nat(self):
2145 """ Identity NAT with addresses from interface """
2146
2147 port = 53053
2148 self.vapi.nat44_add_interface_addr(self.pg7.sw_if_index)
2149 self.vapi.nat44_add_del_identity_mapping(
2150 sw_if_index=self.pg7.sw_if_index,
2151 port=port,
2152 protocol=IP_PROTOS.tcp,
2153 addr_only=0)
2154
2155 # identity mappings with external interface
2156 identity_mappings = self.vapi.nat44_identity_mapping_dump()
2157 self.assertEqual(1, len(identity_mappings))
2158 self.assertEqual(self.pg7.sw_if_index,
2159 identity_mappings[0].sw_if_index)
2160
2161 # configure interface address and check identity mappings
2162 self.pg7.config_ip4()
2163 identity_mappings = self.vapi.nat44_identity_mapping_dump()
Matus Fabianea2600a2018-03-28 04:06:26 -07002164 resolved = False
2165 self.assertEqual(2, len(identity_mappings))
2166 for sm in identity_mappings:
2167 if sm.sw_if_index == 0xFFFFFFFF:
2168 self.assertEqual(identity_mappings[0].ip_address,
2169 self.pg7.local_ip4n)
2170 self.assertEqual(port, identity_mappings[0].port)
2171 self.assertEqual(IP_PROTOS.tcp, identity_mappings[0].protocol)
2172 resolved = True
2173 self.assertTrue(resolved)
Matus Fabianab7a8052017-11-28 04:29:41 -08002174
2175 # remove interface address and check identity mappings
2176 self.pg7.unconfig_ip4()
2177 identity_mappings = self.vapi.nat44_identity_mapping_dump()
Matus Fabianea2600a2018-03-28 04:06:26 -07002178 self.assertEqual(1, len(identity_mappings))
2179 self.assertEqual(self.pg7.sw_if_index,
2180 identity_mappings[0].sw_if_index)
Matus Fabianab7a8052017-11-28 04:29:41 -08002181
Matus Fabianeea28d72017-01-13 04:15:54 -08002182 def test_ipfix_nat44_sess(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002183 """ IPFIX logging NAT44 session created/delted """
Matus Fabian6631e9c2017-05-24 01:52:20 -07002184 self.ipfix_domain_id = 10
2185 self.ipfix_src_port = 20202
2186 colector_port = 30303
2187 bind_layers(UDP, IPFIX, dport=30303)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002188 self.nat44_add_address(self.nat_addr)
2189 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2190 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2191 is_inside=0)
Matus Fabianeea28d72017-01-13 04:15:54 -08002192 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
2193 src_address=self.pg3.local_ip4n,
2194 path_mtu=512,
Matus Fabian6631e9c2017-05-24 01:52:20 -07002195 template_interval=10,
2196 collector_port=colector_port)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002197 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
2198 src_port=self.ipfix_src_port)
Matus Fabianeea28d72017-01-13 04:15:54 -08002199
2200 pkts = self.create_stream_in(self.pg0, self.pg1)
2201 self.pg0.add_stream(pkts)
2202 self.pg_enable_capture(self.pg_interfaces)
2203 self.pg_start()
2204 capture = self.pg1.get_capture(len(pkts))
2205 self.verify_capture_out(capture)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002206 self.nat44_add_address(self.nat_addr, is_add=0)
Matus Fabianeea28d72017-01-13 04:15:54 -08002207 self.vapi.cli("ipfix flush") # FIXME this should be an API call
Matus Fabiana431ad12018-01-04 04:03:14 -08002208 capture = self.pg3.get_capture(9)
Matus Fabianeea28d72017-01-13 04:15:54 -08002209 ipfix = IPFIXDecoder()
2210 # first load template
2211 for p in capture:
2212 self.assertTrue(p.haslayer(IPFIX))
Matus Fabian6631e9c2017-05-24 01:52:20 -07002213 self.assertEqual(p[IP].src, self.pg3.local_ip4)
2214 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2215 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2216 self.assertEqual(p[UDP].dport, colector_port)
2217 self.assertEqual(p[IPFIX].observationDomainID,
2218 self.ipfix_domain_id)
Matus Fabianeea28d72017-01-13 04:15:54 -08002219 if p.haslayer(Template):
2220 ipfix.add_template(p.getlayer(Template))
2221 # verify events in data set
2222 for p in capture:
2223 if p.haslayer(Data):
2224 data = ipfix.decode_data_set(p.getlayer(Set))
2225 self.verify_ipfix_nat44_ses(data)
2226
2227 def test_ipfix_addr_exhausted(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002228 """ IPFIX logging NAT addresses exhausted """
2229 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2230 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2231 is_inside=0)
Matus Fabianeea28d72017-01-13 04:15:54 -08002232 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
2233 src_address=self.pg3.local_ip4n,
2234 path_mtu=512,
2235 template_interval=10)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002236 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
2237 src_port=self.ipfix_src_port)
Matus Fabianeea28d72017-01-13 04:15:54 -08002238
2239 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
2240 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2241 TCP(sport=3025))
2242 self.pg0.add_stream(p)
2243 self.pg_enable_capture(self.pg_interfaces)
2244 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07002245 self.pg1.assert_nothing_captured()
2246 sleep(1)
Matus Fabianeea28d72017-01-13 04:15:54 -08002247 self.vapi.cli("ipfix flush") # FIXME this should be an API call
Matus Fabiana431ad12018-01-04 04:03:14 -08002248 capture = self.pg3.get_capture(9)
Matus Fabianeea28d72017-01-13 04:15:54 -08002249 ipfix = IPFIXDecoder()
2250 # first load template
2251 for p in capture:
2252 self.assertTrue(p.haslayer(IPFIX))
Matus Fabian6631e9c2017-05-24 01:52:20 -07002253 self.assertEqual(p[IP].src, self.pg3.local_ip4)
2254 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2255 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2256 self.assertEqual(p[UDP].dport, 4739)
2257 self.assertEqual(p[IPFIX].observationDomainID,
2258 self.ipfix_domain_id)
Matus Fabianeea28d72017-01-13 04:15:54 -08002259 if p.haslayer(Template):
2260 ipfix.add_template(p.getlayer(Template))
2261 # verify events in data set
2262 for p in capture:
2263 if p.haslayer(Data):
2264 data = ipfix.decode_data_set(p.getlayer(Set))
2265 self.verify_ipfix_addr_exhausted(data)
2266
Matus Fabiana431ad12018-01-04 04:03:14 -08002267 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
2268 def test_ipfix_max_sessions(self):
2269 """ IPFIX logging maximum session entries exceeded """
2270 self.nat44_add_address(self.nat_addr)
2271 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2272 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2273 is_inside=0)
2274
2275 nat44_config = self.vapi.nat_show_config()
2276 max_sessions = 10 * nat44_config.translation_buckets
2277
2278 pkts = []
2279 for i in range(0, max_sessions):
2280 src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
2281 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2282 IP(src=src, dst=self.pg1.remote_ip4) /
2283 TCP(sport=1025))
2284 pkts.append(p)
2285 self.pg0.add_stream(pkts)
2286 self.pg_enable_capture(self.pg_interfaces)
2287 self.pg_start()
2288
2289 self.pg1.get_capture(max_sessions)
2290 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
2291 src_address=self.pg3.local_ip4n,
2292 path_mtu=512,
2293 template_interval=10)
2294 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
2295 src_port=self.ipfix_src_port)
2296
2297 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2298 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2299 TCP(sport=1025))
2300 self.pg0.add_stream(p)
2301 self.pg_enable_capture(self.pg_interfaces)
2302 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07002303 self.pg1.assert_nothing_captured()
2304 sleep(1)
Matus Fabiana431ad12018-01-04 04:03:14 -08002305 self.vapi.cli("ipfix flush") # FIXME this should be an API call
2306 capture = self.pg3.get_capture(9)
2307 ipfix = IPFIXDecoder()
2308 # first load template
2309 for p in capture:
2310 self.assertTrue(p.haslayer(IPFIX))
2311 self.assertEqual(p[IP].src, self.pg3.local_ip4)
2312 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2313 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2314 self.assertEqual(p[UDP].dport, 4739)
2315 self.assertEqual(p[IPFIX].observationDomainID,
2316 self.ipfix_domain_id)
2317 if p.haslayer(Template):
2318 ipfix.add_template(p.getlayer(Template))
2319 # verify events in data set
2320 for p in capture:
2321 if p.haslayer(Data):
2322 data = ipfix.decode_data_set(p.getlayer(Set))
2323 self.verify_ipfix_max_sessions(data, max_sessions)
2324
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002325 def test_pool_addr_fib(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002326 """ NAT44 add pool addresses to FIB """
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002327 static_addr = '10.0.0.10'
Matus Fabian2ba92e32017-08-21 07:05:03 -07002328 self.nat44_add_address(self.nat_addr)
2329 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2330 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2331 is_inside=0)
2332 self.nat44_add_static_mapping(self.pg0.remote_ip4, static_addr)
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002333
Matus Fabian2ba92e32017-08-21 07:05:03 -07002334 # NAT44 address
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002335 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002336 ARP(op=ARP.who_has, pdst=self.nat_addr,
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002337 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2338 self.pg1.add_stream(p)
2339 self.pg_enable_capture(self.pg_interfaces)
2340 self.pg_start()
2341 capture = self.pg1.get_capture(1)
2342 self.assertTrue(capture[0].haslayer(ARP))
2343 self.assertTrue(capture[0][ARP].op, ARP.is_at)
2344
2345 # 1:1 NAT address
2346 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2347 ARP(op=ARP.who_has, pdst=static_addr,
2348 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2349 self.pg1.add_stream(p)
2350 self.pg_enable_capture(self.pg_interfaces)
2351 self.pg_start()
2352 capture = self.pg1.get_capture(1)
2353 self.assertTrue(capture[0].haslayer(ARP))
2354 self.assertTrue(capture[0][ARP].op, ARP.is_at)
2355
Matus Fabian2ba92e32017-08-21 07:05:03 -07002356 # send ARP to non-NAT44 interface
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002357 p = (Ether(src=self.pg2.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002358 ARP(op=ARP.who_has, pdst=self.nat_addr,
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002359 psrc=self.pg2.remote_ip4, hwsrc=self.pg2.remote_mac))
2360 self.pg2.add_stream(p)
2361 self.pg_enable_capture(self.pg_interfaces)
2362 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07002363 self.pg1.assert_nothing_captured()
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002364
2365 # remove addresses and verify
Matus Fabian2ba92e32017-08-21 07:05:03 -07002366 self.nat44_add_address(self.nat_addr, is_add=0)
2367 self.nat44_add_static_mapping(self.pg0.remote_ip4, static_addr,
2368 is_add=0)
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002369
2370 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002371 ARP(op=ARP.who_has, pdst=self.nat_addr,
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002372 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2373 self.pg1.add_stream(p)
2374 self.pg_enable_capture(self.pg_interfaces)
2375 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07002376 self.pg1.assert_nothing_captured()
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002377
2378 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2379 ARP(op=ARP.who_has, pdst=static_addr,
2380 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2381 self.pg1.add_stream(p)
2382 self.pg_enable_capture(self.pg_interfaces)
2383 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07002384 self.pg1.assert_nothing_captured()
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002385
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002386 def test_vrf_mode(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002387 """ NAT44 tenant VRF aware address pool mode """
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002388
2389 vrf_id1 = 1
2390 vrf_id2 = 2
2391 nat_ip1 = "10.0.0.10"
2392 nat_ip2 = "10.0.0.11"
2393
2394 self.pg0.unconfig_ip4()
2395 self.pg1.unconfig_ip4()
Neale Ranns15002542017-09-10 04:39:11 -07002396 self.vapi.ip_table_add_del(vrf_id1, is_add=1)
2397 self.vapi.ip_table_add_del(vrf_id2, is_add=1)
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002398 self.pg0.set_table_ip4(vrf_id1)
2399 self.pg1.set_table_ip4(vrf_id2)
2400 self.pg0.config_ip4()
2401 self.pg1.config_ip4()
Matus Fabian8008d7c2018-07-09 01:34:20 -07002402 self.pg0.resolve_arp()
2403 self.pg1.resolve_arp()
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002404
Matus Fabian2ba92e32017-08-21 07:05:03 -07002405 self.nat44_add_address(nat_ip1, vrf_id=vrf_id1)
2406 self.nat44_add_address(nat_ip2, vrf_id=vrf_id2)
2407 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2408 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
2409 self.vapi.nat44_interface_add_del_feature(self.pg2.sw_if_index,
2410 is_inside=0)
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002411
Matus Fabian8008d7c2018-07-09 01:34:20 -07002412 try:
2413 # first VRF
2414 pkts = self.create_stream_in(self.pg0, self.pg2)
2415 self.pg0.add_stream(pkts)
2416 self.pg_enable_capture(self.pg_interfaces)
2417 self.pg_start()
2418 capture = self.pg2.get_capture(len(pkts))
2419 self.verify_capture_out(capture, nat_ip1)
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002420
Matus Fabian8008d7c2018-07-09 01:34:20 -07002421 # second VRF
2422 pkts = self.create_stream_in(self.pg1, self.pg2)
2423 self.pg1.add_stream(pkts)
2424 self.pg_enable_capture(self.pg_interfaces)
2425 self.pg_start()
2426 capture = self.pg2.get_capture(len(pkts))
2427 self.verify_capture_out(capture, nat_ip2)
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002428
Matus Fabian8008d7c2018-07-09 01:34:20 -07002429 finally:
2430 self.pg0.unconfig_ip4()
2431 self.pg1.unconfig_ip4()
2432 self.pg0.set_table_ip4(0)
2433 self.pg1.set_table_ip4(0)
2434 self.pg0.config_ip4()
2435 self.pg1.config_ip4()
2436 self.pg0.resolve_arp()
2437 self.pg1.resolve_arp()
2438 self.vapi.ip_table_add_del(vrf_id1, is_add=0)
2439 self.vapi.ip_table_add_del(vrf_id2, is_add=0)
Neale Ranns15002542017-09-10 04:39:11 -07002440
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002441 def test_vrf_feature_independent(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002442 """ NAT44 tenant VRF independent address pool mode """
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002443
2444 nat_ip1 = "10.0.0.10"
2445 nat_ip2 = "10.0.0.11"
2446
Matus Fabian2ba92e32017-08-21 07:05:03 -07002447 self.nat44_add_address(nat_ip1)
Matus Fabian51e759f2017-12-07 23:22:51 -08002448 self.nat44_add_address(nat_ip2, vrf_id=99)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002449 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2450 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
2451 self.vapi.nat44_interface_add_del_feature(self.pg2.sw_if_index,
2452 is_inside=0)
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002453
2454 # first VRF
2455 pkts = self.create_stream_in(self.pg0, self.pg2)
2456 self.pg0.add_stream(pkts)
2457 self.pg_enable_capture(self.pg_interfaces)
2458 self.pg_start()
2459 capture = self.pg2.get_capture(len(pkts))
2460 self.verify_capture_out(capture, nat_ip1)
2461
2462 # second VRF
2463 pkts = self.create_stream_in(self.pg1, self.pg2)
2464 self.pg1.add_stream(pkts)
2465 self.pg_enable_capture(self.pg_interfaces)
2466 self.pg_start()
2467 capture = self.pg2.get_capture(len(pkts))
2468 self.verify_capture_out(capture, nat_ip1)
2469
Martin Gálik406eb1d2017-05-04 04:35:04 -07002470 def test_dynamic_ipless_interfaces(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002471 """ NAT44 interfaces without configured IP address """
Martin Gálik406eb1d2017-05-04 04:35:04 -07002472
2473 self.vapi.ip_neighbor_add_del(self.pg7.sw_if_index,
Ole Troan895b6e82017-10-20 13:28:20 +02002474 mactobinary(self.pg7.remote_mac),
Martin Gálik406eb1d2017-05-04 04:35:04 -07002475 self.pg7.remote_ip4n,
2476 is_static=1)
2477 self.vapi.ip_neighbor_add_del(self.pg8.sw_if_index,
Ole Troan895b6e82017-10-20 13:28:20 +02002478 mactobinary(self.pg8.remote_mac),
Martin Gálik406eb1d2017-05-04 04:35:04 -07002479 self.pg8.remote_ip4n,
2480 is_static=1)
2481
2482 self.vapi.ip_add_del_route(dst_address=self.pg7.remote_ip4n,
2483 dst_address_length=32,
2484 next_hop_address=self.pg7.remote_ip4n,
2485 next_hop_sw_if_index=self.pg7.sw_if_index)
2486 self.vapi.ip_add_del_route(dst_address=self.pg8.remote_ip4n,
2487 dst_address_length=32,
2488 next_hop_address=self.pg8.remote_ip4n,
2489 next_hop_sw_if_index=self.pg8.sw_if_index)
2490
Matus Fabian2ba92e32017-08-21 07:05:03 -07002491 self.nat44_add_address(self.nat_addr)
2492 self.vapi.nat44_interface_add_del_feature(self.pg7.sw_if_index)
2493 self.vapi.nat44_interface_add_del_feature(self.pg8.sw_if_index,
2494 is_inside=0)
Martin Gálik406eb1d2017-05-04 04:35:04 -07002495
2496 # in2out
2497 pkts = self.create_stream_in(self.pg7, self.pg8)
2498 self.pg7.add_stream(pkts)
2499 self.pg_enable_capture(self.pg_interfaces)
2500 self.pg_start()
2501 capture = self.pg8.get_capture(len(pkts))
2502 self.verify_capture_out(capture)
2503
2504 # out2in
Matus Fabian2ba92e32017-08-21 07:05:03 -07002505 pkts = self.create_stream_out(self.pg8, self.nat_addr)
Martin Gálik406eb1d2017-05-04 04:35:04 -07002506 self.pg8.add_stream(pkts)
2507 self.pg_enable_capture(self.pg_interfaces)
2508 self.pg_start()
2509 capture = self.pg7.get_capture(len(pkts))
2510 self.verify_capture_in(capture, self.pg7)
2511
2512 def test_static_ipless_interfaces(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002513 """ NAT44 interfaces without configured IP address - 1:1 NAT """
Martin Gálik406eb1d2017-05-04 04:35:04 -07002514
2515 self.vapi.ip_neighbor_add_del(self.pg7.sw_if_index,
Ole Troan895b6e82017-10-20 13:28:20 +02002516 mactobinary(self.pg7.remote_mac),
Martin Gálik406eb1d2017-05-04 04:35:04 -07002517 self.pg7.remote_ip4n,
2518 is_static=1)
2519 self.vapi.ip_neighbor_add_del(self.pg8.sw_if_index,
Ole Troan895b6e82017-10-20 13:28:20 +02002520 mactobinary(self.pg8.remote_mac),
Martin Gálik406eb1d2017-05-04 04:35:04 -07002521 self.pg8.remote_ip4n,
2522 is_static=1)
2523
2524 self.vapi.ip_add_del_route(dst_address=self.pg7.remote_ip4n,
2525 dst_address_length=32,
2526 next_hop_address=self.pg7.remote_ip4n,
2527 next_hop_sw_if_index=self.pg7.sw_if_index)
2528 self.vapi.ip_add_del_route(dst_address=self.pg8.remote_ip4n,
2529 dst_address_length=32,
2530 next_hop_address=self.pg8.remote_ip4n,
2531 next_hop_sw_if_index=self.pg8.sw_if_index)
2532
Matus Fabian2ba92e32017-08-21 07:05:03 -07002533 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr)
2534 self.vapi.nat44_interface_add_del_feature(self.pg7.sw_if_index)
2535 self.vapi.nat44_interface_add_del_feature(self.pg8.sw_if_index,
2536 is_inside=0)
Martin Gálik406eb1d2017-05-04 04:35:04 -07002537
2538 # out2in
2539 pkts = self.create_stream_out(self.pg8)
2540 self.pg8.add_stream(pkts)
2541 self.pg_enable_capture(self.pg_interfaces)
2542 self.pg_start()
2543 capture = self.pg7.get_capture(len(pkts))
2544 self.verify_capture_in(capture, self.pg7)
2545
2546 # in2out
2547 pkts = self.create_stream_in(self.pg7, self.pg8)
2548 self.pg7.add_stream(pkts)
2549 self.pg_enable_capture(self.pg_interfaces)
2550 self.pg_start()
2551 capture = self.pg8.get_capture(len(pkts))
Matus Fabian2ba92e32017-08-21 07:05:03 -07002552 self.verify_capture_out(capture, self.nat_addr, True)
Martin Gálik406eb1d2017-05-04 04:35:04 -07002553
2554 def test_static_with_port_ipless_interfaces(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002555 """ NAT44 interfaces without configured IP address - 1:1 NAPT """
Martin Gálik406eb1d2017-05-04 04:35:04 -07002556
2557 self.tcp_port_out = 30606
2558 self.udp_port_out = 30607
2559 self.icmp_id_out = 30608
2560
2561 self.vapi.ip_neighbor_add_del(self.pg7.sw_if_index,
Ole Troan895b6e82017-10-20 13:28:20 +02002562 mactobinary(self.pg7.remote_mac),
Martin Gálik406eb1d2017-05-04 04:35:04 -07002563 self.pg7.remote_ip4n,
2564 is_static=1)
2565 self.vapi.ip_neighbor_add_del(self.pg8.sw_if_index,
Ole Troan895b6e82017-10-20 13:28:20 +02002566 mactobinary(self.pg8.remote_mac),
Martin Gálik406eb1d2017-05-04 04:35:04 -07002567 self.pg8.remote_ip4n,
2568 is_static=1)
2569
2570 self.vapi.ip_add_del_route(dst_address=self.pg7.remote_ip4n,
2571 dst_address_length=32,
2572 next_hop_address=self.pg7.remote_ip4n,
2573 next_hop_sw_if_index=self.pg7.sw_if_index)
2574 self.vapi.ip_add_del_route(dst_address=self.pg8.remote_ip4n,
2575 dst_address_length=32,
2576 next_hop_address=self.pg8.remote_ip4n,
2577 next_hop_sw_if_index=self.pg8.sw_if_index)
2578
Matus Fabian2ba92e32017-08-21 07:05:03 -07002579 self.nat44_add_address(self.nat_addr)
2580 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
2581 self.tcp_port_in, self.tcp_port_out,
2582 proto=IP_PROTOS.tcp)
2583 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
2584 self.udp_port_in, self.udp_port_out,
2585 proto=IP_PROTOS.udp)
2586 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
2587 self.icmp_id_in, self.icmp_id_out,
2588 proto=IP_PROTOS.icmp)
2589 self.vapi.nat44_interface_add_del_feature(self.pg7.sw_if_index)
2590 self.vapi.nat44_interface_add_del_feature(self.pg8.sw_if_index,
2591 is_inside=0)
Martin Gálik406eb1d2017-05-04 04:35:04 -07002592
2593 # out2in
2594 pkts = self.create_stream_out(self.pg8)
2595 self.pg8.add_stream(pkts)
2596 self.pg_enable_capture(self.pg_interfaces)
2597 self.pg_start()
2598 capture = self.pg7.get_capture(len(pkts))
2599 self.verify_capture_in(capture, self.pg7)
2600
2601 # in2out
2602 pkts = self.create_stream_in(self.pg7, self.pg8)
2603 self.pg7.add_stream(pkts)
2604 self.pg_enable_capture(self.pg_interfaces)
2605 self.pg_start()
2606 capture = self.pg8.get_capture(len(pkts))
2607 self.verify_capture_out(capture)
2608
Matus Fabian328dbc82017-06-19 04:28:04 -07002609 def test_static_unknown_proto(self):
2610 """ 1:1 NAT translate packet with unknown protocol """
2611 nat_ip = "10.0.0.10"
Matus Fabian2ba92e32017-08-21 07:05:03 -07002612 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
2613 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2614 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2615 is_inside=0)
Matus Fabian328dbc82017-06-19 04:28:04 -07002616
2617 # in2out
2618 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2619 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2620 GRE() /
Matus Fabian1e8db5f2017-06-20 01:45:49 -07002621 IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4) /
Matus Fabian328dbc82017-06-19 04:28:04 -07002622 TCP(sport=1234, dport=1234))
2623 self.pg0.add_stream(p)
2624 self.pg_enable_capture(self.pg_interfaces)
2625 self.pg_start()
2626 p = self.pg1.get_capture(1)
2627 packet = p[0]
2628 try:
2629 self.assertEqual(packet[IP].src, nat_ip)
2630 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
2631 self.assertTrue(packet.haslayer(GRE))
Klement Sekerad81ae412018-05-16 10:52:54 +02002632 self.assert_packet_checksums_valid(packet)
Matus Fabian328dbc82017-06-19 04:28:04 -07002633 except:
2634 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2635 raise
2636
2637 # out2in
2638 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
2639 IP(src=self.pg1.remote_ip4, dst=nat_ip) /
2640 GRE() /
Matus Fabian1e8db5f2017-06-20 01:45:49 -07002641 IP(src=self.pg3.remote_ip4, dst=self.pg2.remote_ip4) /
Matus Fabian328dbc82017-06-19 04:28:04 -07002642 TCP(sport=1234, dport=1234))
2643 self.pg1.add_stream(p)
2644 self.pg_enable_capture(self.pg_interfaces)
2645 self.pg_start()
2646 p = self.pg0.get_capture(1)
2647 packet = p[0]
2648 try:
2649 self.assertEqual(packet[IP].src, self.pg1.remote_ip4)
2650 self.assertEqual(packet[IP].dst, self.pg0.remote_ip4)
2651 self.assertTrue(packet.haslayer(GRE))
Klement Sekerad81ae412018-05-16 10:52:54 +02002652 self.assert_packet_checksums_valid(packet)
Matus Fabian328dbc82017-06-19 04:28:04 -07002653 except:
2654 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2655 raise
2656
Matus Fabian7968e6c2017-07-06 05:37:49 -07002657 def test_hairpinning_static_unknown_proto(self):
Matus Fabian1e8db5f2017-06-20 01:45:49 -07002658 """ 1:1 NAT translate packet with unknown protocol - hairpinning """
2659
2660 host = self.pg0.remote_hosts[0]
2661 server = self.pg0.remote_hosts[1]
2662
2663 host_nat_ip = "10.0.0.10"
2664 server_nat_ip = "10.0.0.11"
2665
Matus Fabian2ba92e32017-08-21 07:05:03 -07002666 self.nat44_add_static_mapping(host.ip4, host_nat_ip)
2667 self.nat44_add_static_mapping(server.ip4, server_nat_ip)
2668 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2669 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2670 is_inside=0)
Matus Fabian1e8db5f2017-06-20 01:45:49 -07002671
2672 # host to server
2673 p = (Ether(dst=self.pg0.local_mac, src=host.mac) /
2674 IP(src=host.ip4, dst=server_nat_ip) /
2675 GRE() /
2676 IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4) /
2677 TCP(sport=1234, dport=1234))
2678 self.pg0.add_stream(p)
2679 self.pg_enable_capture(self.pg_interfaces)
2680 self.pg_start()
2681 p = self.pg0.get_capture(1)
2682 packet = p[0]
2683 try:
2684 self.assertEqual(packet[IP].src, host_nat_ip)
2685 self.assertEqual(packet[IP].dst, server.ip4)
2686 self.assertTrue(packet.haslayer(GRE))
Klement Sekerad81ae412018-05-16 10:52:54 +02002687 self.assert_packet_checksums_valid(packet)
Matus Fabian1e8db5f2017-06-20 01:45:49 -07002688 except:
2689 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2690 raise
2691
2692 # server to host
2693 p = (Ether(dst=self.pg0.local_mac, src=server.mac) /
2694 IP(src=server.ip4, dst=host_nat_ip) /
2695 GRE() /
2696 IP(src=self.pg3.remote_ip4, dst=self.pg2.remote_ip4) /
2697 TCP(sport=1234, dport=1234))
2698 self.pg0.add_stream(p)
2699 self.pg_enable_capture(self.pg_interfaces)
2700 self.pg_start()
2701 p = self.pg0.get_capture(1)
2702 packet = p[0]
2703 try:
2704 self.assertEqual(packet[IP].src, server_nat_ip)
2705 self.assertEqual(packet[IP].dst, host.ip4)
2706 self.assertTrue(packet.haslayer(GRE))
Klement Sekerad81ae412018-05-16 10:52:54 +02002707 self.assert_packet_checksums_valid(packet)
Matus Fabian1e8db5f2017-06-20 01:45:49 -07002708 except:
2709 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2710 raise
2711
Matus Fabian93d84c92017-07-19 08:06:01 -07002712 def test_output_feature(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002713 """ NAT44 interface output feature (in2out postrouting) """
2714 self.nat44_add_address(self.nat_addr)
2715 self.vapi.nat44_interface_add_del_output_feature(self.pg0.sw_if_index)
Matus Fabianb2d2fc72017-09-10 22:17:47 -07002716 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index)
2717 self.vapi.nat44_interface_add_del_output_feature(self.pg3.sw_if_index,
Matus Fabian2ba92e32017-08-21 07:05:03 -07002718 is_inside=0)
Matus Fabian93d84c92017-07-19 08:06:01 -07002719
2720 # in2out
Matus Fabianb2d2fc72017-09-10 22:17:47 -07002721 pkts = self.create_stream_in(self.pg0, self.pg3)
Matus Fabian93d84c92017-07-19 08:06:01 -07002722 self.pg0.add_stream(pkts)
2723 self.pg_enable_capture(self.pg_interfaces)
2724 self.pg_start()
Matus Fabianb2d2fc72017-09-10 22:17:47 -07002725 capture = self.pg3.get_capture(len(pkts))
Matus Fabian93d84c92017-07-19 08:06:01 -07002726 self.verify_capture_out(capture)
2727
2728 # out2in
Matus Fabianb2d2fc72017-09-10 22:17:47 -07002729 pkts = self.create_stream_out(self.pg3)
2730 self.pg3.add_stream(pkts)
Matus Fabian93d84c92017-07-19 08:06:01 -07002731 self.pg_enable_capture(self.pg_interfaces)
2732 self.pg_start()
2733 capture = self.pg0.get_capture(len(pkts))
2734 self.verify_capture_in(capture, self.pg0)
2735
Matus Fabianb2d2fc72017-09-10 22:17:47 -07002736 # from non-NAT interface to NAT inside interface
2737 pkts = self.create_stream_in(self.pg2, self.pg0)
2738 self.pg2.add_stream(pkts)
2739 self.pg_enable_capture(self.pg_interfaces)
2740 self.pg_start()
2741 capture = self.pg0.get_capture(len(pkts))
2742 self.verify_capture_no_translation(capture, self.pg2, self.pg0)
2743
Matus Fabian93d84c92017-07-19 08:06:01 -07002744 def test_output_feature_vrf_aware(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002745 """ NAT44 interface output feature VRF aware (in2out postrouting) """
Matus Fabian93d84c92017-07-19 08:06:01 -07002746 nat_ip_vrf10 = "10.0.0.10"
2747 nat_ip_vrf20 = "10.0.0.20"
2748
2749 self.vapi.ip_add_del_route(dst_address=self.pg3.remote_ip4n,
2750 dst_address_length=32,
2751 next_hop_address=self.pg3.remote_ip4n,
2752 next_hop_sw_if_index=self.pg3.sw_if_index,
2753 table_id=10)
2754 self.vapi.ip_add_del_route(dst_address=self.pg3.remote_ip4n,
2755 dst_address_length=32,
2756 next_hop_address=self.pg3.remote_ip4n,
2757 next_hop_sw_if_index=self.pg3.sw_if_index,
2758 table_id=20)
2759
Matus Fabian2ba92e32017-08-21 07:05:03 -07002760 self.nat44_add_address(nat_ip_vrf10, vrf_id=10)
2761 self.nat44_add_address(nat_ip_vrf20, vrf_id=20)
2762 self.vapi.nat44_interface_add_del_output_feature(self.pg4.sw_if_index)
2763 self.vapi.nat44_interface_add_del_output_feature(self.pg6.sw_if_index)
2764 self.vapi.nat44_interface_add_del_output_feature(self.pg3.sw_if_index,
2765 is_inside=0)
Matus Fabian93d84c92017-07-19 08:06:01 -07002766
2767 # in2out VRF 10
2768 pkts = self.create_stream_in(self.pg4, self.pg3)
2769 self.pg4.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_vrf10)
2774
2775 # out2in VRF 10
2776 pkts = self.create_stream_out(self.pg3, dst_ip=nat_ip_vrf10)
2777 self.pg3.add_stream(pkts)
2778 self.pg_enable_capture(self.pg_interfaces)
2779 self.pg_start()
2780 capture = self.pg4.get_capture(len(pkts))
2781 self.verify_capture_in(capture, self.pg4)
2782
2783 # in2out VRF 20
2784 pkts = self.create_stream_in(self.pg6, self.pg3)
2785 self.pg6.add_stream(pkts)
2786 self.pg_enable_capture(self.pg_interfaces)
2787 self.pg_start()
2788 capture = self.pg3.get_capture(len(pkts))
2789 self.verify_capture_out(capture, nat_ip=nat_ip_vrf20)
2790
2791 # out2in VRF 20
2792 pkts = self.create_stream_out(self.pg3, dst_ip=nat_ip_vrf20)
2793 self.pg3.add_stream(pkts)
2794 self.pg_enable_capture(self.pg_interfaces)
2795 self.pg_start()
2796 capture = self.pg6.get_capture(len(pkts))
2797 self.verify_capture_in(capture, self.pg6)
2798
Matus Fabian161c59c2017-07-21 03:46:03 -07002799 def test_output_feature_hairpinning(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002800 """ NAT44 interface output feature hairpinning (in2out postrouting) """
Matus Fabian93d84c92017-07-19 08:06:01 -07002801 host = self.pg0.remote_hosts[0]
2802 server = self.pg0.remote_hosts[1]
2803 host_in_port = 1234
2804 host_out_port = 0
2805 server_in_port = 5678
2806 server_out_port = 8765
2807
Matus Fabian2ba92e32017-08-21 07:05:03 -07002808 self.nat44_add_address(self.nat_addr)
2809 self.vapi.nat44_interface_add_del_output_feature(self.pg0.sw_if_index)
2810 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
2811 is_inside=0)
Matus Fabian93d84c92017-07-19 08:06:01 -07002812
2813 # add static mapping for server
Matus Fabian2ba92e32017-08-21 07:05:03 -07002814 self.nat44_add_static_mapping(server.ip4, self.nat_addr,
2815 server_in_port, server_out_port,
2816 proto=IP_PROTOS.tcp)
Matus Fabian93d84c92017-07-19 08:06:01 -07002817
2818 # send packet from host to server
2819 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002820 IP(src=host.ip4, dst=self.nat_addr) /
Matus Fabian93d84c92017-07-19 08:06:01 -07002821 TCP(sport=host_in_port, dport=server_out_port))
2822 self.pg0.add_stream(p)
2823 self.pg_enable_capture(self.pg_interfaces)
2824 self.pg_start()
2825 capture = self.pg0.get_capture(1)
2826 p = capture[0]
2827 try:
2828 ip = p[IP]
2829 tcp = p[TCP]
Matus Fabian2ba92e32017-08-21 07:05:03 -07002830 self.assertEqual(ip.src, self.nat_addr)
Matus Fabian93d84c92017-07-19 08:06:01 -07002831 self.assertEqual(ip.dst, server.ip4)
2832 self.assertNotEqual(tcp.sport, host_in_port)
2833 self.assertEqual(tcp.dport, server_in_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02002834 self.assert_packet_checksums_valid(p)
Matus Fabian93d84c92017-07-19 08:06:01 -07002835 host_out_port = tcp.sport
2836 except:
2837 self.logger.error(ppp("Unexpected or invalid packet:", p))
2838 raise
2839
2840 # send reply from server to host
2841 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002842 IP(src=server.ip4, dst=self.nat_addr) /
Matus Fabian93d84c92017-07-19 08:06:01 -07002843 TCP(sport=server_in_port, dport=host_out_port))
2844 self.pg0.add_stream(p)
2845 self.pg_enable_capture(self.pg_interfaces)
2846 self.pg_start()
2847 capture = self.pg0.get_capture(1)
2848 p = capture[0]
2849 try:
2850 ip = p[IP]
2851 tcp = p[TCP]
Matus Fabian2ba92e32017-08-21 07:05:03 -07002852 self.assertEqual(ip.src, self.nat_addr)
Matus Fabian93d84c92017-07-19 08:06:01 -07002853 self.assertEqual(ip.dst, host.ip4)
2854 self.assertEqual(tcp.sport, server_out_port)
2855 self.assertEqual(tcp.dport, host_in_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02002856 self.assert_packet_checksums_valid(p)
Matus Fabian93d84c92017-07-19 08:06:01 -07002857 except:
Matus Fabiane82488f2018-01-18 03:38:45 -08002858 self.logger.error(ppp("Unexpected or invalid packet:", p))
Matus Fabian93d84c92017-07-19 08:06:01 -07002859 raise
2860
Matus Fabian36ea2d62017-10-24 04:13:49 -07002861 def test_one_armed_nat44(self):
2862 """ One armed NAT44 """
2863 remote_host = self.pg9.remote_hosts[0]
2864 local_host = self.pg9.remote_hosts[1]
2865 external_port = 0
2866
2867 self.nat44_add_address(self.nat_addr)
2868 self.vapi.nat44_interface_add_del_feature(self.pg9.sw_if_index)
2869 self.vapi.nat44_interface_add_del_feature(self.pg9.sw_if_index,
2870 is_inside=0)
2871
2872 # in2out
2873 p = (Ether(src=self.pg9.remote_mac, dst=self.pg9.local_mac) /
2874 IP(src=local_host.ip4, dst=remote_host.ip4) /
2875 TCP(sport=12345, dport=80))
2876 self.pg9.add_stream(p)
2877 self.pg_enable_capture(self.pg_interfaces)
2878 self.pg_start()
2879 capture = self.pg9.get_capture(1)
2880 p = capture[0]
2881 try:
2882 ip = p[IP]
2883 tcp = p[TCP]
2884 self.assertEqual(ip.src, self.nat_addr)
2885 self.assertEqual(ip.dst, remote_host.ip4)
2886 self.assertNotEqual(tcp.sport, 12345)
2887 external_port = tcp.sport
2888 self.assertEqual(tcp.dport, 80)
Klement Sekerad81ae412018-05-16 10:52:54 +02002889 self.assert_packet_checksums_valid(p)
Matus Fabian36ea2d62017-10-24 04:13:49 -07002890 except:
2891 self.logger.error(ppp("Unexpected or invalid packet:", p))
2892 raise
2893
2894 # out2in
2895 p = (Ether(src=self.pg9.remote_mac, dst=self.pg9.local_mac) /
2896 IP(src=remote_host.ip4, dst=self.nat_addr) /
2897 TCP(sport=80, dport=external_port))
2898 self.pg9.add_stream(p)
2899 self.pg_enable_capture(self.pg_interfaces)
2900 self.pg_start()
2901 capture = self.pg9.get_capture(1)
2902 p = capture[0]
2903 try:
2904 ip = p[IP]
2905 tcp = p[TCP]
2906 self.assertEqual(ip.src, remote_host.ip4)
2907 self.assertEqual(ip.dst, local_host.ip4)
2908 self.assertEqual(tcp.sport, 80)
2909 self.assertEqual(tcp.dport, 12345)
Klement Sekerad81ae412018-05-16 10:52:54 +02002910 self.assert_packet_checksums_valid(p)
Matus Fabian36ea2d62017-10-24 04:13:49 -07002911 except:
2912 self.logger.error(ppp("Unexpected or invalid packet:", p))
2913 raise
2914
Matus Fabian5ba86f72017-10-26 03:37:38 -07002915 def test_del_session(self):
2916 """ Delete NAT44 session """
2917 self.nat44_add_address(self.nat_addr)
2918 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2919 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2920 is_inside=0)
2921
2922 pkts = self.create_stream_in(self.pg0, self.pg1)
2923 self.pg0.add_stream(pkts)
2924 self.pg_enable_capture(self.pg_interfaces)
2925 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07002926 self.pg1.get_capture(len(pkts))
Matus Fabian5ba86f72017-10-26 03:37:38 -07002927
2928 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
2929 nsessions = len(sessions)
2930
2931 self.vapi.nat44_del_session(sessions[0].inside_ip_address,
2932 sessions[0].inside_port,
2933 sessions[0].protocol)
2934 self.vapi.nat44_del_session(sessions[1].outside_ip_address,
2935 sessions[1].outside_port,
2936 sessions[1].protocol,
2937 is_in=0)
2938
2939 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
2940 self.assertEqual(nsessions - len(sessions), 2)
2941
Matus Fabian68ba8802018-08-08 05:52:47 -07002942 self.vapi.nat44_del_session(sessions[0].inside_ip_address,
2943 sessions[0].inside_port,
2944 sessions[0].protocol)
2945
2946 self.verify_no_nat44_user()
2947
Matus Fabianefcd1e92017-08-15 06:59:19 -07002948 def test_set_get_reass(self):
2949 """ NAT44 set/get virtual fragmentation reassembly """
2950 reas_cfg1 = self.vapi.nat_get_reass()
2951
2952 self.vapi.nat_set_reass(timeout=reas_cfg1.ip4_timeout + 5,
2953 max_reass=reas_cfg1.ip4_max_reass * 2,
2954 max_frag=reas_cfg1.ip4_max_frag * 2)
2955
2956 reas_cfg2 = self.vapi.nat_get_reass()
2957
2958 self.assertEqual(reas_cfg1.ip4_timeout + 5, reas_cfg2.ip4_timeout)
2959 self.assertEqual(reas_cfg1.ip4_max_reass * 2, reas_cfg2.ip4_max_reass)
2960 self.assertEqual(reas_cfg1.ip4_max_frag * 2, reas_cfg2.ip4_max_frag)
2961
2962 self.vapi.nat_set_reass(drop_frag=1)
2963 self.assertTrue(self.vapi.nat_get_reass().ip4_drop_frag)
2964
2965 def test_frag_in_order(self):
2966 """ NAT44 translate fragments arriving in order """
2967 self.nat44_add_address(self.nat_addr)
2968 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2969 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2970 is_inside=0)
2971
2972 data = "A" * 4 + "B" * 16 + "C" * 3
2973 self.tcp_port_in = random.randint(1025, 65535)
2974
2975 reass = self.vapi.nat_reass_dump()
2976 reass_n_start = len(reass)
2977
2978 # in2out
2979 pkts = self.create_stream_frag(self.pg0,
2980 self.pg1.remote_ip4,
2981 self.tcp_port_in,
2982 20,
2983 data)
2984 self.pg0.add_stream(pkts)
2985 self.pg_enable_capture(self.pg_interfaces)
2986 self.pg_start()
2987 frags = self.pg1.get_capture(len(pkts))
2988 p = self.reass_frags_and_verify(frags,
2989 self.nat_addr,
2990 self.pg1.remote_ip4)
2991 self.assertEqual(p[TCP].dport, 20)
2992 self.assertNotEqual(p[TCP].sport, self.tcp_port_in)
2993 self.tcp_port_out = p[TCP].sport
2994 self.assertEqual(data, p[Raw].load)
2995
2996 # out2in
2997 pkts = self.create_stream_frag(self.pg1,
2998 self.nat_addr,
2999 20,
3000 self.tcp_port_out,
3001 data)
3002 self.pg1.add_stream(pkts)
3003 self.pg_enable_capture(self.pg_interfaces)
3004 self.pg_start()
3005 frags = self.pg0.get_capture(len(pkts))
3006 p = self.reass_frags_and_verify(frags,
3007 self.pg1.remote_ip4,
3008 self.pg0.remote_ip4)
3009 self.assertEqual(p[TCP].sport, 20)
3010 self.assertEqual(p[TCP].dport, self.tcp_port_in)
3011 self.assertEqual(data, p[Raw].load)
3012
3013 reass = self.vapi.nat_reass_dump()
3014 reass_n_end = len(reass)
3015
3016 self.assertEqual(reass_n_end - reass_n_start, 2)
3017
3018 def test_reass_hairpinning(self):
3019 """ NAT44 fragments hairpinning """
Matus Fabianefcd1e92017-08-15 06:59:19 -07003020 server = self.pg0.remote_hosts[1]
3021 host_in_port = random.randint(1025, 65535)
Matus Fabianefcd1e92017-08-15 06:59:19 -07003022 server_in_port = random.randint(1025, 65535)
3023 server_out_port = random.randint(1025, 65535)
3024 data = "A" * 4 + "B" * 16 + "C" * 3
3025
3026 self.nat44_add_address(self.nat_addr)
3027 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3028 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3029 is_inside=0)
3030 # add static mapping for server
3031 self.nat44_add_static_mapping(server.ip4, self.nat_addr,
3032 server_in_port, server_out_port,
3033 proto=IP_PROTOS.tcp)
3034
3035 # send packet from host to server
3036 pkts = self.create_stream_frag(self.pg0,
3037 self.nat_addr,
3038 host_in_port,
3039 server_out_port,
3040 data)
3041 self.pg0.add_stream(pkts)
3042 self.pg_enable_capture(self.pg_interfaces)
3043 self.pg_start()
3044 frags = self.pg0.get_capture(len(pkts))
3045 p = self.reass_frags_and_verify(frags,
3046 self.nat_addr,
3047 server.ip4)
3048 self.assertNotEqual(p[TCP].sport, host_in_port)
3049 self.assertEqual(p[TCP].dport, server_in_port)
3050 self.assertEqual(data, p[Raw].load)
3051
3052 def test_frag_out_of_order(self):
3053 """ NAT44 translate fragments arriving out of order """
3054 self.nat44_add_address(self.nat_addr)
3055 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3056 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3057 is_inside=0)
3058
3059 data = "A" * 4 + "B" * 16 + "C" * 3
3060 random.randint(1025, 65535)
3061
3062 # in2out
3063 pkts = self.create_stream_frag(self.pg0,
3064 self.pg1.remote_ip4,
3065 self.tcp_port_in,
3066 20,
3067 data)
3068 pkts.reverse()
3069 self.pg0.add_stream(pkts)
3070 self.pg_enable_capture(self.pg_interfaces)
3071 self.pg_start()
3072 frags = self.pg1.get_capture(len(pkts))
3073 p = self.reass_frags_and_verify(frags,
3074 self.nat_addr,
3075 self.pg1.remote_ip4)
3076 self.assertEqual(p[TCP].dport, 20)
3077 self.assertNotEqual(p[TCP].sport, self.tcp_port_in)
3078 self.tcp_port_out = p[TCP].sport
3079 self.assertEqual(data, p[Raw].load)
3080
3081 # out2in
3082 pkts = self.create_stream_frag(self.pg1,
3083 self.nat_addr,
3084 20,
3085 self.tcp_port_out,
3086 data)
3087 pkts.reverse()
3088 self.pg1.add_stream(pkts)
3089 self.pg_enable_capture(self.pg_interfaces)
3090 self.pg_start()
3091 frags = self.pg0.get_capture(len(pkts))
3092 p = self.reass_frags_and_verify(frags,
3093 self.pg1.remote_ip4,
3094 self.pg0.remote_ip4)
3095 self.assertEqual(p[TCP].sport, 20)
3096 self.assertEqual(p[TCP].dport, self.tcp_port_in)
3097 self.assertEqual(data, p[Raw].load)
3098
Matus Fabian27697102017-11-09 01:43:47 -08003099 def test_port_restricted(self):
3100 """ Port restricted NAT44 (MAP-E CE) """
3101 self.nat44_add_address(self.nat_addr)
3102 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3103 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3104 is_inside=0)
Matus Fabian5d28c7a2018-09-04 03:55:45 -07003105 self.vapi.nat_set_addr_and_port_alloc_alg(alg=1,
3106 psid_offset=6,
3107 psid_length=6,
3108 psid=10)
Matus Fabian27697102017-11-09 01:43:47 -08003109
3110 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3111 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3112 TCP(sport=4567, dport=22))
3113 self.pg0.add_stream(p)
3114 self.pg_enable_capture(self.pg_interfaces)
3115 self.pg_start()
3116 capture = self.pg1.get_capture(1)
3117 p = capture[0]
3118 try:
3119 ip = p[IP]
3120 tcp = p[TCP]
3121 self.assertEqual(ip.dst, self.pg1.remote_ip4)
3122 self.assertEqual(ip.src, self.nat_addr)
3123 self.assertEqual(tcp.dport, 22)
3124 self.assertNotEqual(tcp.sport, 4567)
3125 self.assertEqual((tcp.sport >> 6) & 63, 10)
Klement Sekerad81ae412018-05-16 10:52:54 +02003126 self.assert_packet_checksums_valid(p)
Matus Fabian27697102017-11-09 01:43:47 -08003127 except:
3128 self.logger.error(ppp("Unexpected or invalid packet:", p))
3129 raise
3130
Matus Fabian5d28c7a2018-09-04 03:55:45 -07003131 def test_port_range(self):
3132 """ External address port range """
3133 self.nat44_add_address(self.nat_addr)
3134 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3135 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3136 is_inside=0)
3137 self.vapi.nat_set_addr_and_port_alloc_alg(alg=2,
3138 start_port=1025,
3139 end_port=1027)
3140
3141 pkts = []
3142 for port in range(0, 5):
3143 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3144 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3145 TCP(sport=1125 + port))
3146 pkts.append(p)
3147 self.pg0.add_stream(pkts)
3148 self.pg_enable_capture(self.pg_interfaces)
3149 self.pg_start()
3150 capture = self.pg1.get_capture(3)
3151 for p in capture:
3152 tcp = p[TCP]
3153 self.assertGreaterEqual(tcp.sport, 1025)
3154 self.assertLessEqual(tcp.sport, 1027)
3155
Matus Fabiana6110b62018-06-13 05:39:07 -07003156 def test_ipfix_max_frags(self):
3157 """ IPFIX logging maximum fragments pending reassembly exceeded """
3158 self.nat44_add_address(self.nat_addr)
3159 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3160 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3161 is_inside=0)
Matus Fabiana7f8b222018-09-05 06:01:55 -07003162 self.vapi.nat_set_reass(max_frag=1)
Matus Fabiana6110b62018-06-13 05:39:07 -07003163 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
3164 src_address=self.pg3.local_ip4n,
3165 path_mtu=512,
3166 template_interval=10)
3167 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
3168 src_port=self.ipfix_src_port)
3169
3170 data = "A" * 4 + "B" * 16 + "C" * 3
3171 self.tcp_port_in = random.randint(1025, 65535)
3172 pkts = self.create_stream_frag(self.pg0,
3173 self.pg1.remote_ip4,
3174 self.tcp_port_in,
3175 20,
3176 data)
Matus Fabiana7f8b222018-09-05 06:01:55 -07003177 pkts.reverse()
3178 self.pg0.add_stream(pkts)
Matus Fabiana6110b62018-06-13 05:39:07 -07003179 self.pg_enable_capture(self.pg_interfaces)
3180 self.pg_start()
3181 self.pg1.assert_nothing_captured()
3182 sleep(1)
3183 self.vapi.cli("ipfix flush") # FIXME this should be an API call
3184 capture = self.pg3.get_capture(9)
3185 ipfix = IPFIXDecoder()
3186 # first load template
3187 for p in capture:
3188 self.assertTrue(p.haslayer(IPFIX))
3189 self.assertEqual(p[IP].src, self.pg3.local_ip4)
3190 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
3191 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
3192 self.assertEqual(p[UDP].dport, 4739)
3193 self.assertEqual(p[IPFIX].observationDomainID,
3194 self.ipfix_domain_id)
3195 if p.haslayer(Template):
3196 ipfix.add_template(p.getlayer(Template))
3197 # verify events in data set
3198 for p in capture:
3199 if p.haslayer(Data):
3200 data = ipfix.decode_data_set(p.getlayer(Set))
Matus Fabiana7f8b222018-09-05 06:01:55 -07003201 self.verify_ipfix_max_fragments_ip4(data, 1,
Matus Fabiana6110b62018-06-13 05:39:07 -07003202 self.pg0.remote_ip4n)
3203
Matus Fabian8008d7c2018-07-09 01:34:20 -07003204 def test_multiple_outside_vrf(self):
3205 """ Multiple outside VRF """
3206 vrf_id1 = 1
3207 vrf_id2 = 2
3208
3209 self.pg1.unconfig_ip4()
3210 self.pg2.unconfig_ip4()
3211 self.vapi.ip_table_add_del(vrf_id1, is_add=1)
3212 self.vapi.ip_table_add_del(vrf_id2, is_add=1)
3213 self.pg1.set_table_ip4(vrf_id1)
3214 self.pg2.set_table_ip4(vrf_id2)
3215 self.pg1.config_ip4()
3216 self.pg2.config_ip4()
3217 self.pg1.resolve_arp()
3218 self.pg2.resolve_arp()
3219
3220 self.nat44_add_address(self.nat_addr)
3221 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3222 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3223 is_inside=0)
3224 self.vapi.nat44_interface_add_del_feature(self.pg2.sw_if_index,
3225 is_inside=0)
3226
3227 try:
3228 # first VRF
3229 pkts = self.create_stream_in(self.pg0, self.pg1)
3230 self.pg0.add_stream(pkts)
3231 self.pg_enable_capture(self.pg_interfaces)
3232 self.pg_start()
3233 capture = self.pg1.get_capture(len(pkts))
3234 self.verify_capture_out(capture, self.nat_addr)
3235
3236 pkts = self.create_stream_out(self.pg1, self.nat_addr)
3237 self.pg1.add_stream(pkts)
3238 self.pg_enable_capture(self.pg_interfaces)
3239 self.pg_start()
3240 capture = self.pg0.get_capture(len(pkts))
3241 self.verify_capture_in(capture, self.pg0)
3242
3243 self.tcp_port_in = 60303
3244 self.udp_port_in = 60304
3245 self.icmp_id_in = 60305
3246
3247 # second VRF
3248 pkts = self.create_stream_in(self.pg0, self.pg2)
3249 self.pg0.add_stream(pkts)
3250 self.pg_enable_capture(self.pg_interfaces)
3251 self.pg_start()
3252 capture = self.pg2.get_capture(len(pkts))
3253 self.verify_capture_out(capture, self.nat_addr)
3254
3255 pkts = self.create_stream_out(self.pg2, self.nat_addr)
3256 self.pg2.add_stream(pkts)
3257 self.pg_enable_capture(self.pg_interfaces)
3258 self.pg_start()
3259 capture = self.pg0.get_capture(len(pkts))
3260 self.verify_capture_in(capture, self.pg0)
3261
3262 finally:
3263 self.pg1.unconfig_ip4()
3264 self.pg2.unconfig_ip4()
3265 self.pg1.set_table_ip4(0)
3266 self.pg2.set_table_ip4(0)
3267 self.pg1.config_ip4()
3268 self.pg2.config_ip4()
3269 self.pg1.resolve_arp()
3270 self.pg2.resolve_arp()
3271
Matus Fabian878c6462018-08-23 00:33:35 -07003272 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
3273 def test_session_timeout(self):
3274 """ NAT44 session timeouts """
3275 self.nat44_add_address(self.nat_addr)
3276 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3277 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3278 is_inside=0)
3279 self.vapi.nat_set_timeouts(udp=5)
3280
3281 max_sessions = 1000
3282 pkts = []
3283 for i in range(0, max_sessions):
3284 src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
3285 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3286 IP(src=src, dst=self.pg1.remote_ip4) /
3287 UDP(sport=1025, dport=53))
3288 pkts.append(p)
3289 self.pg0.add_stream(pkts)
3290 self.pg_enable_capture(self.pg_interfaces)
3291 self.pg_start()
3292 self.pg1.get_capture(max_sessions)
3293
3294 sleep(6)
3295
3296 pkts = []
3297 for i in range(0, max_sessions):
3298 src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
3299 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3300 IP(src=src, dst=self.pg1.remote_ip4) /
3301 UDP(sport=1026, dport=53))
3302 pkts.append(p)
3303 self.pg0.add_stream(pkts)
3304 self.pg_enable_capture(self.pg_interfaces)
3305 self.pg_start()
3306 self.pg1.get_capture(max_sessions)
3307
3308 nsessions = 0
3309 users = self.vapi.nat44_user_dump()
3310 for user in users:
3311 nsessions = nsessions + user.nsessions
3312 self.assertLess(nsessions, 2 * max_sessions)
3313
Matus Fabianbb4e0222018-09-13 02:36:25 -07003314 def test_mss_clamping(self):
3315 """ TCP MSS clamping """
3316 self.nat44_add_address(self.nat_addr)
3317 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3318 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3319 is_inside=0)
3320
3321 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3322 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3323 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
3324 flags="S", options=[('MSS', 1400)]))
3325
3326 self.vapi.nat_set_mss_clamping(enable=1, mss_value=1000)
3327 self.pg0.add_stream(p)
3328 self.pg_enable_capture(self.pg_interfaces)
3329 self.pg_start()
3330 capture = self.pg1.get_capture(1)
3331 # Negotiated MSS value greater than configured - changed
3332 self.verify_mss_value(capture[0], 1000)
3333
3334 self.vapi.nat_set_mss_clamping(enable=0)
3335 self.pg0.add_stream(p)
3336 self.pg_enable_capture(self.pg_interfaces)
3337 self.pg_start()
3338 capture = self.pg1.get_capture(1)
3339 # MSS clamping disabled - negotiated MSS unchanged
3340 self.verify_mss_value(capture[0], 1400)
3341
3342 self.vapi.nat_set_mss_clamping(enable=1, mss_value=1500)
3343 self.pg0.add_stream(p)
3344 self.pg_enable_capture(self.pg_interfaces)
3345 self.pg_start()
3346 capture = self.pg1.get_capture(1)
3347 # Negotiated MSS value smaller than configured - unchanged
3348 self.verify_mss_value(capture[0], 1400)
3349
Matus Fabiana6110b62018-06-13 05:39:07 -07003350 def tearDown(self):
3351 super(TestNAT44, self).tearDown()
3352 if not self.vpp_dead:
3353 self.logger.info(self.vapi.cli("show nat44 addresses"))
3354 self.logger.info(self.vapi.cli("show nat44 interfaces"))
3355 self.logger.info(self.vapi.cli("show nat44 static mappings"))
3356 self.logger.info(self.vapi.cli("show nat44 interface address"))
3357 self.logger.info(self.vapi.cli("show nat44 sessions detail"))
3358 self.logger.info(self.vapi.cli("show nat virtual-reassembly"))
3359 self.logger.info(self.vapi.cli("show nat44 hash tables detail"))
Matus Fabian878c6462018-08-23 00:33:35 -07003360 self.logger.info(self.vapi.cli("show nat timeouts"))
Matus Fabian5d28c7a2018-09-04 03:55:45 -07003361 self.logger.info(
3362 self.vapi.cli("show nat addr-port-assignment-alg"))
Matus Fabiana6110b62018-06-13 05:39:07 -07003363 self.clear_nat44()
3364 self.vapi.cli("clear logging")
3365
3366
3367class TestNAT44EndpointDependent(MethodHolder):
3368 """ Endpoint-Dependent mapping and filtering test cases """
3369
3370 @classmethod
3371 def setUpConstants(cls):
3372 super(TestNAT44EndpointDependent, cls).setUpConstants()
3373 cls.vpp_cmdline.extend(["nat", "{", "endpoint-dependent", "}"])
3374
3375 @classmethod
3376 def setUpClass(cls):
3377 super(TestNAT44EndpointDependent, cls).setUpClass()
3378 cls.vapi.cli("set log class nat level debug")
3379 try:
3380 cls.tcp_port_in = 6303
3381 cls.tcp_port_out = 6303
3382 cls.udp_port_in = 6304
3383 cls.udp_port_out = 6304
3384 cls.icmp_id_in = 6305
3385 cls.icmp_id_out = 6305
3386 cls.nat_addr = '10.0.0.3'
3387 cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
3388 cls.ipfix_src_port = 4739
3389 cls.ipfix_domain_id = 1
3390 cls.tcp_external_port = 80
3391
Matus Fabian8008d7c2018-07-09 01:34:20 -07003392 cls.create_pg_interfaces(range(7))
Matus Fabiana6110b62018-06-13 05:39:07 -07003393 cls.interfaces = list(cls.pg_interfaces[0:3])
3394
3395 for i in cls.interfaces:
3396 i.admin_up()
3397 i.config_ip4()
3398 i.resolve_arp()
3399
3400 cls.pg0.generate_remote_hosts(3)
3401 cls.pg0.configure_ipv4_neighbors()
3402
3403 cls.pg3.admin_up()
3404
3405 cls.pg4.generate_remote_hosts(2)
3406 cls.pg4.config_ip4()
3407 ip_addr_n = socket.inet_pton(socket.AF_INET, "10.0.0.1")
3408 cls.vapi.sw_interface_add_del_address(cls.pg4.sw_if_index,
3409 ip_addr_n,
3410 24)
3411 cls.pg4.admin_up()
3412 cls.pg4.resolve_arp()
3413 cls.pg4._remote_hosts[1]._ip4 = cls.pg4._remote_hosts[0]._ip4
3414 cls.pg4.resolve_arp()
3415
Matus Fabian8008d7c2018-07-09 01:34:20 -07003416 zero_ip4n = socket.inet_pton(socket.AF_INET, "0.0.0.0")
3417 cls.vapi.ip_table_add_del(1, is_add=1)
3418
3419 cls.pg5._local_ip4 = "10.1.1.1"
3420 cls.pg5._local_ip4n = socket.inet_pton(socket.AF_INET,
3421 cls.pg5.local_ip4)
3422 cls.pg5._remote_hosts[0]._ip4 = "10.1.1.2"
3423 cls.pg5._remote_hosts[0]._ip4n = socket.inet_pton(
3424 socket.AF_INET, cls.pg5.remote_ip4)
3425 cls.pg5.set_table_ip4(1)
3426 cls.pg5.config_ip4()
3427 cls.pg5.admin_up()
3428 cls.vapi.ip_add_del_route(dst_address=cls.pg5.remote_ip4n,
3429 dst_address_length=32,
3430 table_id=1,
3431 next_hop_sw_if_index=cls.pg5.sw_if_index,
3432 next_hop_address=zero_ip4n)
3433
3434 cls.pg6._local_ip4 = "10.1.2.1"
3435 cls.pg6._local_ip4n = socket.inet_pton(socket.AF_INET,
3436 cls.pg6.local_ip4)
3437 cls.pg6._remote_hosts[0]._ip4 = "10.1.2.2"
3438 cls.pg6._remote_hosts[0]._ip4n = socket.inet_pton(
3439 socket.AF_INET, cls.pg6.remote_ip4)
3440 cls.pg6.set_table_ip4(1)
3441 cls.pg6.config_ip4()
3442 cls.pg6.admin_up()
3443 cls.vapi.ip_add_del_route(dst_address=cls.pg6.remote_ip4n,
3444 dst_address_length=32,
3445 table_id=1,
3446 next_hop_sw_if_index=cls.pg6.sw_if_index,
3447 next_hop_address=zero_ip4n)
3448
3449 cls.vapi.ip_add_del_route(dst_address=cls.pg6.remote_ip4n,
3450 dst_address_length=16,
3451 next_hop_address=zero_ip4n,
3452 table_id=0,
3453 next_hop_table_id=1)
3454 cls.vapi.ip_add_del_route(dst_address=zero_ip4n,
3455 dst_address_length=0,
3456 next_hop_address=zero_ip4n,
3457 table_id=1,
3458 next_hop_table_id=0)
3459 cls.vapi.ip_add_del_route(dst_address=zero_ip4n,
3460 dst_address_length=0,
3461 table_id=0,
3462 next_hop_sw_if_index=cls.pg1.sw_if_index,
3463 next_hop_address=cls.pg1.local_ip4n)
3464
3465 cls.pg5.resolve_arp()
3466 cls.pg6.resolve_arp()
3467
Matus Fabiana6110b62018-06-13 05:39:07 -07003468 except Exception:
3469 super(TestNAT44EndpointDependent, cls).tearDownClass()
3470 raise
3471
3472 def test_dynamic(self):
3473 """ NAT44 dynamic translation test """
3474
3475 self.nat44_add_address(self.nat_addr)
3476 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3477 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3478 is_inside=0)
3479
Matus Fabian69ce30d2018-08-22 01:27:10 -07003480 nat_config = self.vapi.nat_show_config()
3481 self.assertEqual(1, nat_config.endpoint_dependent)
3482
Matus Fabiana6110b62018-06-13 05:39:07 -07003483 # in2out
3484 pkts = self.create_stream_in(self.pg0, self.pg1)
3485 self.pg0.add_stream(pkts)
3486 self.pg_enable_capture(self.pg_interfaces)
3487 self.pg_start()
3488 capture = self.pg1.get_capture(len(pkts))
3489 self.verify_capture_out(capture)
3490
3491 # out2in
3492 pkts = self.create_stream_out(self.pg1)
3493 self.pg1.add_stream(pkts)
3494 self.pg_enable_capture(self.pg_interfaces)
3495 self.pg_start()
3496 capture = self.pg0.get_capture(len(pkts))
3497 self.verify_capture_in(capture, self.pg0)
3498
3499 def test_forwarding(self):
3500 """ NAT44 forwarding test """
3501
3502 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3503 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3504 is_inside=0)
3505 self.vapi.nat44_forwarding_enable_disable(1)
3506
3507 real_ip = self.pg0.remote_ip4n
3508 alias_ip = self.nat_addr_n
3509 self.vapi.nat44_add_del_static_mapping(local_ip=real_ip,
3510 external_ip=alias_ip)
3511
3512 try:
3513 # in2out - static mapping match
3514
3515 pkts = self.create_stream_out(self.pg1)
3516 self.pg1.add_stream(pkts)
3517 self.pg_enable_capture(self.pg_interfaces)
3518 self.pg_start()
3519 capture = self.pg0.get_capture(len(pkts))
3520 self.verify_capture_in(capture, self.pg0)
3521
3522 pkts = self.create_stream_in(self.pg0, self.pg1)
3523 self.pg0.add_stream(pkts)
3524 self.pg_enable_capture(self.pg_interfaces)
3525 self.pg_start()
3526 capture = self.pg1.get_capture(len(pkts))
3527 self.verify_capture_out(capture, same_port=True)
3528
3529 # in2out - no static mapping match
3530
3531 host0 = self.pg0.remote_hosts[0]
3532 self.pg0.remote_hosts[0] = self.pg0.remote_hosts[1]
3533 try:
3534 pkts = self.create_stream_out(self.pg1,
3535 dst_ip=self.pg0.remote_ip4,
3536 use_inside_ports=True)
3537 self.pg1.add_stream(pkts)
3538 self.pg_enable_capture(self.pg_interfaces)
3539 self.pg_start()
3540 capture = self.pg0.get_capture(len(pkts))
3541 self.verify_capture_in(capture, self.pg0)
3542
3543 pkts = self.create_stream_in(self.pg0, self.pg1)
3544 self.pg0.add_stream(pkts)
3545 self.pg_enable_capture(self.pg_interfaces)
3546 self.pg_start()
3547 capture = self.pg1.get_capture(len(pkts))
3548 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
3549 same_port=True)
3550 finally:
3551 self.pg0.remote_hosts[0] = host0
3552
3553 user = self.pg0.remote_hosts[1]
3554 sessions = self.vapi.nat44_user_session_dump(user.ip4n, 0)
3555 self.assertEqual(len(sessions), 3)
3556 self.assertTrue(sessions[0].ext_host_valid)
3557 self.vapi.nat44_del_session(
3558 sessions[0].inside_ip_address,
3559 sessions[0].inside_port,
3560 sessions[0].protocol,
3561 ext_host_address=sessions[0].ext_host_address,
3562 ext_host_port=sessions[0].ext_host_port)
3563 sessions = self.vapi.nat44_user_session_dump(user.ip4n, 0)
3564 self.assertEqual(len(sessions), 2)
3565
3566 finally:
3567 self.vapi.nat44_forwarding_enable_disable(0)
3568 self.vapi.nat44_add_del_static_mapping(local_ip=real_ip,
3569 external_ip=alias_ip,
3570 is_add=0)
3571
3572 def test_static_lb(self):
3573 """ NAT44 local service load balancing """
3574 external_addr_n = socket.inet_pton(socket.AF_INET, self.nat_addr)
3575 external_port = 80
3576 local_port = 8080
3577 server1 = self.pg0.remote_hosts[0]
3578 server2 = self.pg0.remote_hosts[1]
3579
3580 locals = [{'addr': server1.ip4n,
3581 'port': local_port,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07003582 'probability': 70,
3583 'vrf_id': 0},
Matus Fabiana6110b62018-06-13 05:39:07 -07003584 {'addr': server2.ip4n,
3585 'port': local_port,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07003586 'probability': 30,
3587 'vrf_id': 0}]
Matus Fabiana6110b62018-06-13 05:39:07 -07003588
3589 self.nat44_add_address(self.nat_addr)
3590 self.vapi.nat44_add_del_lb_static_mapping(external_addr_n,
3591 external_port,
3592 IP_PROTOS.tcp,
3593 local_num=len(locals),
3594 locals=locals)
3595 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3596 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3597 is_inside=0)
3598
3599 # from client to service
3600 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3601 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3602 TCP(sport=12345, dport=external_port))
3603 self.pg1.add_stream(p)
3604 self.pg_enable_capture(self.pg_interfaces)
3605 self.pg_start()
3606 capture = self.pg0.get_capture(1)
3607 p = capture[0]
3608 server = None
3609 try:
3610 ip = p[IP]
3611 tcp = p[TCP]
3612 self.assertIn(ip.dst, [server1.ip4, server2.ip4])
3613 if ip.dst == server1.ip4:
3614 server = server1
3615 else:
3616 server = server2
3617 self.assertEqual(tcp.dport, local_port)
3618 self.assert_packet_checksums_valid(p)
3619 except:
3620 self.logger.error(ppp("Unexpected or invalid packet:", p))
3621 raise
3622
3623 # from service back to client
3624 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
3625 IP(src=server.ip4, dst=self.pg1.remote_ip4) /
3626 TCP(sport=local_port, dport=12345))
3627 self.pg0.add_stream(p)
3628 self.pg_enable_capture(self.pg_interfaces)
3629 self.pg_start()
3630 capture = self.pg1.get_capture(1)
3631 p = capture[0]
3632 try:
3633 ip = p[IP]
3634 tcp = p[TCP]
3635 self.assertEqual(ip.src, self.nat_addr)
3636 self.assertEqual(tcp.sport, external_port)
3637 self.assert_packet_checksums_valid(p)
3638 except:
3639 self.logger.error(ppp("Unexpected or invalid packet:", p))
3640 raise
3641
3642 sessions = self.vapi.nat44_user_session_dump(server.ip4n, 0)
3643 self.assertEqual(len(sessions), 1)
3644 self.assertTrue(sessions[0].ext_host_valid)
3645 self.vapi.nat44_del_session(
3646 sessions[0].inside_ip_address,
3647 sessions[0].inside_port,
3648 sessions[0].protocol,
3649 ext_host_address=sessions[0].ext_host_address,
3650 ext_host_port=sessions[0].ext_host_port)
3651 sessions = self.vapi.nat44_user_session_dump(server.ip4n, 0)
3652 self.assertEqual(len(sessions), 0)
3653
3654 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
3655 def test_static_lb_multi_clients(self):
3656 """ NAT44 local service load balancing - multiple clients"""
3657
3658 external_addr_n = socket.inet_pton(socket.AF_INET, self.nat_addr)
3659 external_port = 80
3660 local_port = 8080
3661 server1 = self.pg0.remote_hosts[0]
3662 server2 = self.pg0.remote_hosts[1]
3663
3664 locals = [{'addr': server1.ip4n,
3665 'port': local_port,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07003666 'probability': 90,
3667 'vrf_id': 0},
Matus Fabiana6110b62018-06-13 05:39:07 -07003668 {'addr': server2.ip4n,
3669 'port': local_port,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07003670 'probability': 10,
3671 'vrf_id': 0}]
Matus Fabiana6110b62018-06-13 05:39:07 -07003672
3673 self.nat44_add_address(self.nat_addr)
3674 self.vapi.nat44_add_del_lb_static_mapping(external_addr_n,
3675 external_port,
3676 IP_PROTOS.tcp,
3677 local_num=len(locals),
3678 locals=locals)
3679 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3680 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3681 is_inside=0)
3682
3683 server1_n = 0
3684 server2_n = 0
3685 clients = ip4_range(self.pg1.remote_ip4, 10, 50)
3686 pkts = []
3687 for client in clients:
3688 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3689 IP(src=client, dst=self.nat_addr) /
3690 TCP(sport=12345, dport=external_port))
3691 pkts.append(p)
3692 self.pg1.add_stream(pkts)
3693 self.pg_enable_capture(self.pg_interfaces)
3694 self.pg_start()
3695 capture = self.pg0.get_capture(len(pkts))
3696 for p in capture:
3697 if p[IP].dst == server1.ip4:
3698 server1_n += 1
3699 else:
3700 server2_n += 1
3701 self.assertTrue(server1_n > server2_n)
3702
3703 def test_static_lb_2(self):
3704 """ NAT44 local service load balancing (asymmetrical rule) """
3705 external_addr_n = socket.inet_pton(socket.AF_INET, self.nat_addr)
3706 external_port = 80
3707 local_port = 8080
3708 server1 = self.pg0.remote_hosts[0]
3709 server2 = self.pg0.remote_hosts[1]
3710
3711 locals = [{'addr': server1.ip4n,
3712 'port': local_port,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07003713 'probability': 70,
3714 'vrf_id': 0},
Matus Fabiana6110b62018-06-13 05:39:07 -07003715 {'addr': server2.ip4n,
3716 'port': local_port,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07003717 'probability': 30,
3718 'vrf_id': 0}]
Matus Fabiana6110b62018-06-13 05:39:07 -07003719
3720 self.vapi.nat44_forwarding_enable_disable(1)
3721 self.vapi.nat44_add_del_lb_static_mapping(external_addr_n,
3722 external_port,
3723 IP_PROTOS.tcp,
3724 out2in_only=1,
3725 local_num=len(locals),
3726 locals=locals)
3727 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3728 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3729 is_inside=0)
3730
3731 # from client to service
3732 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3733 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3734 TCP(sport=12345, dport=external_port))
3735 self.pg1.add_stream(p)
3736 self.pg_enable_capture(self.pg_interfaces)
3737 self.pg_start()
3738 capture = self.pg0.get_capture(1)
3739 p = capture[0]
3740 server = None
3741 try:
3742 ip = p[IP]
3743 tcp = p[TCP]
3744 self.assertIn(ip.dst, [server1.ip4, server2.ip4])
3745 if ip.dst == server1.ip4:
3746 server = server1
3747 else:
3748 server = server2
3749 self.assertEqual(tcp.dport, local_port)
3750 self.assert_packet_checksums_valid(p)
3751 except:
3752 self.logger.error(ppp("Unexpected or invalid packet:", p))
3753 raise
3754
3755 # from service back to client
3756 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
3757 IP(src=server.ip4, dst=self.pg1.remote_ip4) /
3758 TCP(sport=local_port, dport=12345))
3759 self.pg0.add_stream(p)
3760 self.pg_enable_capture(self.pg_interfaces)
3761 self.pg_start()
3762 capture = self.pg1.get_capture(1)
3763 p = capture[0]
3764 try:
3765 ip = p[IP]
3766 tcp = p[TCP]
3767 self.assertEqual(ip.src, self.nat_addr)
3768 self.assertEqual(tcp.sport, external_port)
3769 self.assert_packet_checksums_valid(p)
3770 except:
3771 self.logger.error(ppp("Unexpected or invalid packet:", p))
3772 raise
3773
3774 # from client to server (no translation)
3775 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3776 IP(src=self.pg1.remote_ip4, dst=server1.ip4) /
3777 TCP(sport=12346, dport=local_port))
3778 self.pg1.add_stream(p)
3779 self.pg_enable_capture(self.pg_interfaces)
3780 self.pg_start()
3781 capture = self.pg0.get_capture(1)
3782 p = capture[0]
3783 server = None
3784 try:
3785 ip = p[IP]
3786 tcp = p[TCP]
3787 self.assertEqual(ip.dst, server1.ip4)
3788 self.assertEqual(tcp.dport, local_port)
3789 self.assert_packet_checksums_valid(p)
3790 except:
3791 self.logger.error(ppp("Unexpected or invalid packet:", p))
3792 raise
3793
3794 # from service back to client (no translation)
3795 p = (Ether(src=server1.mac, dst=self.pg0.local_mac) /
3796 IP(src=server1.ip4, dst=self.pg1.remote_ip4) /
3797 TCP(sport=local_port, dport=12346))
3798 self.pg0.add_stream(p)
3799 self.pg_enable_capture(self.pg_interfaces)
3800 self.pg_start()
3801 capture = self.pg1.get_capture(1)
3802 p = capture[0]
3803 try:
3804 ip = p[IP]
3805 tcp = p[TCP]
3806 self.assertEqual(ip.src, server1.ip4)
3807 self.assertEqual(tcp.sport, local_port)
3808 self.assert_packet_checksums_valid(p)
3809 except:
3810 self.logger.error(ppp("Unexpected or invalid packet:", p))
3811 raise
3812
Matus Fabianea5b5be2018-09-03 05:02:23 -07003813 def test_lb_affinity(self):
3814 """ NAT44 local service load balancing affinity """
3815 external_addr_n = socket.inet_pton(socket.AF_INET, self.nat_addr)
3816 external_port = 80
3817 local_port = 8080
3818 server1 = self.pg0.remote_hosts[0]
3819 server2 = self.pg0.remote_hosts[1]
3820
3821 locals = [{'addr': server1.ip4n,
3822 'port': local_port,
3823 'probability': 50,
3824 'vrf_id': 0},
3825 {'addr': server2.ip4n,
3826 'port': local_port,
3827 'probability': 50,
3828 'vrf_id': 0}]
3829
3830 self.nat44_add_address(self.nat_addr)
3831 self.vapi.nat44_add_del_lb_static_mapping(external_addr_n,
3832 external_port,
3833 IP_PROTOS.tcp,
3834 affinity=10800,
3835 local_num=len(locals),
3836 locals=locals)
3837 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3838 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3839 is_inside=0)
3840
3841 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
3842 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3843 TCP(sport=1025, dport=external_port))
3844 self.pg1.add_stream(p)
3845 self.pg_enable_capture(self.pg_interfaces)
3846 self.pg_start()
3847 capture = self.pg0.get_capture(1)
3848 backend = capture[0][IP].dst
3849
3850 sessions = self.vapi.nat44_user_session_dump(
3851 socket.inet_pton(socket.AF_INET, backend), 0)
3852 self.assertEqual(len(sessions), 1)
3853 self.assertTrue(sessions[0].ext_host_valid)
3854 self.vapi.nat44_del_session(
3855 sessions[0].inside_ip_address,
3856 sessions[0].inside_port,
3857 sessions[0].protocol,
3858 ext_host_address=sessions[0].ext_host_address,
3859 ext_host_port=sessions[0].ext_host_port)
3860
3861 pkts = []
3862 for port in range(1030, 1100):
3863 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
3864 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3865 TCP(sport=port, dport=external_port))
3866 pkts.append(p)
3867 self.pg1.add_stream(pkts)
3868 self.pg_enable_capture(self.pg_interfaces)
3869 self.pg_start()
3870 capture = self.pg0.get_capture(len(pkts))
3871 for p in capture:
3872 self.assertEqual(p[IP].dst, backend)
3873
Matus Fabiana6110b62018-06-13 05:39:07 -07003874 def test_unknown_proto(self):
3875 """ NAT44 translate packet with unknown protocol """
3876 self.nat44_add_address(self.nat_addr)
3877 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3878 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3879 is_inside=0)
3880
3881 # in2out
3882 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3883 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3884 TCP(sport=self.tcp_port_in, dport=20))
3885 self.pg0.add_stream(p)
3886 self.pg_enable_capture(self.pg_interfaces)
3887 self.pg_start()
3888 p = self.pg1.get_capture(1)
3889
3890 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3891 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3892 GRE() /
3893 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
3894 TCP(sport=1234, dport=1234))
3895 self.pg0.add_stream(p)
3896 self.pg_enable_capture(self.pg_interfaces)
3897 self.pg_start()
3898 p = self.pg1.get_capture(1)
3899 packet = p[0]
3900 try:
3901 self.assertEqual(packet[IP].src, self.nat_addr)
3902 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
3903 self.assertTrue(packet.haslayer(GRE))
3904 self.assert_packet_checksums_valid(packet)
3905 except:
3906 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3907 raise
3908
3909 # out2in
3910 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
3911 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3912 GRE() /
3913 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
3914 TCP(sport=1234, dport=1234))
3915 self.pg1.add_stream(p)
3916 self.pg_enable_capture(self.pg_interfaces)
3917 self.pg_start()
3918 p = self.pg0.get_capture(1)
3919 packet = p[0]
3920 try:
3921 self.assertEqual(packet[IP].src, self.pg1.remote_ip4)
3922 self.assertEqual(packet[IP].dst, self.pg0.remote_ip4)
3923 self.assertTrue(packet.haslayer(GRE))
3924 self.assert_packet_checksums_valid(packet)
3925 except:
3926 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3927 raise
3928
3929 def test_hairpinning_unknown_proto(self):
3930 """ NAT44 translate packet with unknown protocol - hairpinning """
3931 host = self.pg0.remote_hosts[0]
3932 server = self.pg0.remote_hosts[1]
3933 host_in_port = 1234
3934 server_out_port = 8765
3935 server_nat_ip = "10.0.0.11"
3936
3937 self.nat44_add_address(self.nat_addr)
3938 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3939 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3940 is_inside=0)
3941
3942 # add static mapping for server
3943 self.nat44_add_static_mapping(server.ip4, server_nat_ip)
3944
3945 # host to server
3946 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
3947 IP(src=host.ip4, dst=server_nat_ip) /
3948 TCP(sport=host_in_port, dport=server_out_port))
3949 self.pg0.add_stream(p)
3950 self.pg_enable_capture(self.pg_interfaces)
3951 self.pg_start()
3952 self.pg0.get_capture(1)
3953
3954 p = (Ether(dst=self.pg0.local_mac, src=host.mac) /
3955 IP(src=host.ip4, dst=server_nat_ip) /
3956 GRE() /
3957 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
3958 TCP(sport=1234, dport=1234))
3959 self.pg0.add_stream(p)
3960 self.pg_enable_capture(self.pg_interfaces)
3961 self.pg_start()
3962 p = self.pg0.get_capture(1)
3963 packet = p[0]
3964 try:
3965 self.assertEqual(packet[IP].src, self.nat_addr)
3966 self.assertEqual(packet[IP].dst, server.ip4)
3967 self.assertTrue(packet.haslayer(GRE))
3968 self.assert_packet_checksums_valid(packet)
3969 except:
3970 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3971 raise
3972
3973 # server to host
3974 p = (Ether(dst=self.pg0.local_mac, src=server.mac) /
3975 IP(src=server.ip4, dst=self.nat_addr) /
3976 GRE() /
3977 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
3978 TCP(sport=1234, dport=1234))
3979 self.pg0.add_stream(p)
3980 self.pg_enable_capture(self.pg_interfaces)
3981 self.pg_start()
3982 p = self.pg0.get_capture(1)
3983 packet = p[0]
3984 try:
3985 self.assertEqual(packet[IP].src, server_nat_ip)
3986 self.assertEqual(packet[IP].dst, host.ip4)
3987 self.assertTrue(packet.haslayer(GRE))
3988 self.assert_packet_checksums_valid(packet)
3989 except:
3990 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3991 raise
3992
3993 def test_output_feature_and_service(self):
3994 """ NAT44 interface output feature and services """
3995 external_addr = '1.2.3.4'
3996 external_port = 80
3997 local_port = 8080
3998
3999 self.vapi.nat44_forwarding_enable_disable(1)
4000 self.nat44_add_address(self.nat_addr)
4001 self.vapi.nat44_add_del_identity_mapping(ip=self.pg1.remote_ip4n)
4002 self.nat44_add_static_mapping(self.pg0.remote_ip4, external_addr,
4003 local_port, external_port,
4004 proto=IP_PROTOS.tcp, out2in_only=1)
4005 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4006 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
4007 is_inside=0)
4008 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
4009 is_inside=0)
4010
4011 # from client to service
4012 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4013 IP(src=self.pg1.remote_ip4, dst=external_addr) /
4014 TCP(sport=12345, dport=external_port))
4015 self.pg1.add_stream(p)
4016 self.pg_enable_capture(self.pg_interfaces)
4017 self.pg_start()
4018 capture = self.pg0.get_capture(1)
4019 p = capture[0]
4020 try:
4021 ip = p[IP]
4022 tcp = p[TCP]
4023 self.assertEqual(ip.dst, self.pg0.remote_ip4)
4024 self.assertEqual(tcp.dport, local_port)
4025 self.assert_packet_checksums_valid(p)
4026 except:
4027 self.logger.error(ppp("Unexpected or invalid packet:", p))
4028 raise
4029
4030 # from service back to client
4031 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4032 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4033 TCP(sport=local_port, dport=12345))
4034 self.pg0.add_stream(p)
4035 self.pg_enable_capture(self.pg_interfaces)
4036 self.pg_start()
4037 capture = self.pg1.get_capture(1)
4038 p = capture[0]
4039 try:
4040 ip = p[IP]
4041 tcp = p[TCP]
4042 self.assertEqual(ip.src, external_addr)
4043 self.assertEqual(tcp.sport, external_port)
4044 self.assert_packet_checksums_valid(p)
4045 except:
4046 self.logger.error(ppp("Unexpected or invalid packet:", p))
4047 raise
4048
4049 # from local network host to external network
4050 pkts = self.create_stream_in(self.pg0, self.pg1)
4051 self.pg0.add_stream(pkts)
4052 self.pg_enable_capture(self.pg_interfaces)
4053 self.pg_start()
4054 capture = self.pg1.get_capture(len(pkts))
4055 self.verify_capture_out(capture)
4056 pkts = self.create_stream_in(self.pg0, self.pg1)
4057 self.pg0.add_stream(pkts)
4058 self.pg_enable_capture(self.pg_interfaces)
4059 self.pg_start()
4060 capture = self.pg1.get_capture(len(pkts))
4061 self.verify_capture_out(capture)
4062
4063 # from external network back to local network host
4064 pkts = self.create_stream_out(self.pg1)
4065 self.pg1.add_stream(pkts)
4066 self.pg_enable_capture(self.pg_interfaces)
4067 self.pg_start()
4068 capture = self.pg0.get_capture(len(pkts))
4069 self.verify_capture_in(capture, self.pg0)
4070
4071 def test_output_feature_and_service2(self):
4072 """ NAT44 interface output feature and service host direct access """
4073 self.vapi.nat44_forwarding_enable_disable(1)
4074 self.nat44_add_address(self.nat_addr)
4075 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
4076 is_inside=0)
4077
4078 # session initiaded from service host - translate
4079 pkts = self.create_stream_in(self.pg0, self.pg1)
4080 self.pg0.add_stream(pkts)
4081 self.pg_enable_capture(self.pg_interfaces)
4082 self.pg_start()
4083 capture = self.pg1.get_capture(len(pkts))
4084 self.verify_capture_out(capture)
4085
4086 pkts = self.create_stream_out(self.pg1)
4087 self.pg1.add_stream(pkts)
4088 self.pg_enable_capture(self.pg_interfaces)
4089 self.pg_start()
4090 capture = self.pg0.get_capture(len(pkts))
4091 self.verify_capture_in(capture, self.pg0)
4092
4093 # session initiaded from remote host - do not translate
4094 self.tcp_port_in = 60303
4095 self.udp_port_in = 60304
4096 self.icmp_id_in = 60305
4097 pkts = self.create_stream_out(self.pg1,
4098 self.pg0.remote_ip4,
4099 use_inside_ports=True)
4100 self.pg1.add_stream(pkts)
4101 self.pg_enable_capture(self.pg_interfaces)
4102 self.pg_start()
4103 capture = self.pg0.get_capture(len(pkts))
4104 self.verify_capture_in(capture, self.pg0)
4105
4106 pkts = self.create_stream_in(self.pg0, self.pg1)
4107 self.pg0.add_stream(pkts)
4108 self.pg_enable_capture(self.pg_interfaces)
4109 self.pg_start()
4110 capture = self.pg1.get_capture(len(pkts))
4111 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
4112 same_port=True)
4113
4114 def test_output_feature_and_service3(self):
4115 """ NAT44 interface output feature and DST NAT """
4116 external_addr = '1.2.3.4'
4117 external_port = 80
4118 local_port = 8080
4119
4120 self.vapi.nat44_forwarding_enable_disable(1)
4121 self.nat44_add_address(self.nat_addr)
4122 self.nat44_add_static_mapping(self.pg1.remote_ip4, external_addr,
4123 local_port, external_port,
4124 proto=IP_PROTOS.tcp, out2in_only=1)
4125 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4126 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
4127 is_inside=0)
4128 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
4129 is_inside=0)
4130
4131 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4132 IP(src=self.pg0.remote_ip4, dst=external_addr) /
4133 TCP(sport=12345, dport=external_port))
4134 self.pg0.add_stream(p)
4135 self.pg_enable_capture(self.pg_interfaces)
4136 self.pg_start()
4137 capture = self.pg1.get_capture(1)
4138 p = capture[0]
4139 try:
4140 ip = p[IP]
4141 tcp = p[TCP]
4142 self.assertEqual(ip.src, self.pg0.remote_ip4)
4143 self.assertEqual(tcp.sport, 12345)
4144 self.assertEqual(ip.dst, self.pg1.remote_ip4)
4145 self.assertEqual(tcp.dport, local_port)
4146 self.assert_packet_checksums_valid(p)
4147 except:
4148 self.logger.error(ppp("Unexpected or invalid packet:", p))
4149 raise
4150
4151 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4152 IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
4153 TCP(sport=local_port, dport=12345))
4154 self.pg1.add_stream(p)
4155 self.pg_enable_capture(self.pg_interfaces)
4156 self.pg_start()
4157 capture = self.pg0.get_capture(1)
4158 p = capture[0]
4159 try:
4160 ip = p[IP]
4161 tcp = p[TCP]
4162 self.assertEqual(ip.src, external_addr)
4163 self.assertEqual(tcp.sport, external_port)
4164 self.assertEqual(ip.dst, self.pg0.remote_ip4)
4165 self.assertEqual(tcp.dport, 12345)
4166 self.assert_packet_checksums_valid(p)
4167 except:
4168 self.logger.error(ppp("Unexpected or invalid packet:", p))
4169 raise
4170
Matus Fabian182e37e2018-08-14 04:21:26 -07004171 def test_next_src_nat(self):
4172 """ On way back forward packet to nat44-in2out node. """
4173 twice_nat_addr = '10.0.1.3'
4174 external_port = 80
4175 local_port = 8080
4176 post_twice_nat_port = 0
4177
4178 self.vapi.nat44_forwarding_enable_disable(1)
4179 self.nat44_add_address(twice_nat_addr, twice_nat=1)
4180 self.nat44_add_static_mapping(self.pg6.remote_ip4, self.pg1.remote_ip4,
4181 local_port, external_port,
4182 proto=IP_PROTOS.tcp, out2in_only=1,
4183 self_twice_nat=1, vrf_id=1)
4184 self.vapi.nat44_interface_add_del_feature(self.pg6.sw_if_index,
4185 is_inside=0)
4186
4187 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
4188 IP(src=self.pg6.remote_ip4, dst=self.pg1.remote_ip4) /
4189 TCP(sport=12345, dport=external_port))
4190 self.pg6.add_stream(p)
4191 self.pg_enable_capture(self.pg_interfaces)
4192 self.pg_start()
4193 capture = self.pg6.get_capture(1)
4194 p = capture[0]
4195 try:
4196 ip = p[IP]
4197 tcp = p[TCP]
4198 self.assertEqual(ip.src, twice_nat_addr)
4199 self.assertNotEqual(tcp.sport, 12345)
4200 post_twice_nat_port = tcp.sport
4201 self.assertEqual(ip.dst, self.pg6.remote_ip4)
4202 self.assertEqual(tcp.dport, local_port)
4203 self.assert_packet_checksums_valid(p)
4204 except:
4205 self.logger.error(ppp("Unexpected or invalid packet:", p))
4206 raise
4207
4208 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
4209 IP(src=self.pg6.remote_ip4, dst=twice_nat_addr) /
4210 TCP(sport=local_port, dport=post_twice_nat_port))
4211 self.pg6.add_stream(p)
4212 self.pg_enable_capture(self.pg_interfaces)
4213 self.pg_start()
4214 capture = self.pg6.get_capture(1)
4215 p = capture[0]
4216 try:
4217 ip = p[IP]
4218 tcp = p[TCP]
4219 self.assertEqual(ip.src, self.pg1.remote_ip4)
4220 self.assertEqual(tcp.sport, external_port)
4221 self.assertEqual(ip.dst, self.pg6.remote_ip4)
4222 self.assertEqual(tcp.dport, 12345)
4223 self.assert_packet_checksums_valid(p)
4224 except:
4225 self.logger.error(ppp("Unexpected or invalid packet:", p))
4226 raise
4227
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004228 def twice_nat_common(self, self_twice_nat=False, same_pg=False, lb=False,
4229 client_id=None):
Matus Fabianb932d262017-12-18 05:38:24 -08004230 twice_nat_addr = '10.0.1.3'
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004231
Matus Fabianb932d262017-12-18 05:38:24 -08004232 port_in = 8080
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004233 if lb:
4234 if not same_pg:
4235 port_in1 = port_in
4236 port_in2 = port_in
4237 else:
4238 port_in1 = port_in+1
4239 port_in2 = port_in+2
4240
Matus Fabianb932d262017-12-18 05:38:24 -08004241 port_out = 80
4242 eh_port_out = 4567
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004243
4244 server1 = self.pg0.remote_hosts[0]
4245 server2 = self.pg0.remote_hosts[1]
4246 if lb and same_pg:
4247 server2 = server1
4248 if not lb:
4249 server = server1
4250
4251 pg0 = self.pg0
4252 if same_pg:
4253 pg1 = self.pg0
4254 else:
4255 pg1 = self.pg1
4256
4257 eh_translate = ((not self_twice_nat) or (not lb and same_pg) or
4258 client_id == 1)
4259
Matus Fabianb932d262017-12-18 05:38:24 -08004260 self.nat44_add_address(self.nat_addr)
4261 self.nat44_add_address(twice_nat_addr, twice_nat=1)
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004262 if not lb:
4263 self.nat44_add_static_mapping(pg0.remote_ip4, self.nat_addr,
4264 port_in, port_out,
4265 proto=IP_PROTOS.tcp,
4266 twice_nat=int(not self_twice_nat),
4267 self_twice_nat=int(self_twice_nat))
4268 else:
4269 locals = [{'addr': server1.ip4n,
4270 'port': port_in1,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07004271 'probability': 50,
4272 'vrf_id': 0},
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004273 {'addr': server2.ip4n,
4274 'port': port_in2,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07004275 'probability': 50,
4276 'vrf_id': 0}]
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004277 out_addr_n = socket.inet_pton(socket.AF_INET, self.nat_addr)
4278 self.vapi.nat44_add_del_lb_static_mapping(out_addr_n,
4279 port_out,
4280 IP_PROTOS.tcp,
4281 twice_nat=int(
4282 not self_twice_nat),
4283 self_twice_nat=int(
4284 self_twice_nat),
4285 local_num=len(locals),
4286 locals=locals)
4287 self.vapi.nat44_interface_add_del_feature(pg0.sw_if_index)
4288 self.vapi.nat44_interface_add_del_feature(pg1.sw_if_index,
Matus Fabianb932d262017-12-18 05:38:24 -08004289 is_inside=0)
4290
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004291 if same_pg:
4292 if not lb:
4293 client = server
4294 else:
4295 assert client_id is not None
4296 if client_id == 1:
4297 client = self.pg0.remote_hosts[0]
4298 elif client_id == 2:
4299 client = self.pg0.remote_hosts[1]
4300 else:
4301 client = pg1.remote_hosts[0]
4302 p = (Ether(src=pg1.remote_mac, dst=pg1.local_mac) /
4303 IP(src=client.ip4, dst=self.nat_addr) /
Matus Fabianb932d262017-12-18 05:38:24 -08004304 TCP(sport=eh_port_out, dport=port_out))
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004305 pg1.add_stream(p)
Matus Fabianb932d262017-12-18 05:38:24 -08004306 self.pg_enable_capture(self.pg_interfaces)
4307 self.pg_start()
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004308 capture = pg0.get_capture(1)
Matus Fabianb932d262017-12-18 05:38:24 -08004309 p = capture[0]
4310 try:
4311 ip = p[IP]
4312 tcp = p[TCP]
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004313 if lb:
4314 if ip.dst == server1.ip4:
4315 server = server1
4316 port_in = port_in1
4317 else:
4318 server = server2
4319 port_in = port_in2
4320 self.assertEqual(ip.dst, server.ip4)
4321 if lb and same_pg:
4322 self.assertIn(tcp.dport, [port_in1, port_in2])
4323 else:
4324 self.assertEqual(tcp.dport, port_in)
4325 if eh_translate:
4326 self.assertEqual(ip.src, twice_nat_addr)
4327 self.assertNotEqual(tcp.sport, eh_port_out)
4328 else:
4329 self.assertEqual(ip.src, client.ip4)
4330 self.assertEqual(tcp.sport, eh_port_out)
4331 eh_addr_in = ip.src
Matus Fabianb932d262017-12-18 05:38:24 -08004332 eh_port_in = tcp.sport
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004333 saved_port_in = tcp.dport
Klement Sekerad81ae412018-05-16 10:52:54 +02004334 self.assert_packet_checksums_valid(p)
Matus Fabianb932d262017-12-18 05:38:24 -08004335 except:
4336 self.logger.error(ppp("Unexpected or invalid packet:", p))
4337 raise
4338
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004339 p = (Ether(src=server.mac, dst=pg0.local_mac) /
4340 IP(src=server.ip4, dst=eh_addr_in) /
4341 TCP(sport=saved_port_in, dport=eh_port_in))
4342 pg0.add_stream(p)
Matus Fabianb932d262017-12-18 05:38:24 -08004343 self.pg_enable_capture(self.pg_interfaces)
4344 self.pg_start()
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004345 capture = pg1.get_capture(1)
Matus Fabianb932d262017-12-18 05:38:24 -08004346 p = capture[0]
4347 try:
4348 ip = p[IP]
4349 tcp = p[TCP]
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004350 self.assertEqual(ip.dst, client.ip4)
Matus Fabianb932d262017-12-18 05:38:24 -08004351 self.assertEqual(ip.src, self.nat_addr)
4352 self.assertEqual(tcp.dport, eh_port_out)
4353 self.assertEqual(tcp.sport, port_out)
Klement Sekerad81ae412018-05-16 10:52:54 +02004354 self.assert_packet_checksums_valid(p)
Matus Fabianb932d262017-12-18 05:38:24 -08004355 except:
4356 self.logger.error(ppp("Unexpected or invalid packet:", p))
4357 raise
4358
Matus Fabian70a26ac2018-05-14 06:20:28 -07004359 if eh_translate:
4360 sessions = self.vapi.nat44_user_session_dump(server.ip4n, 0)
4361 self.assertEqual(len(sessions), 1)
4362 self.assertTrue(sessions[0].ext_host_valid)
4363 self.assertTrue(sessions[0].is_twicenat)
4364 self.vapi.nat44_del_session(
4365 sessions[0].inside_ip_address,
4366 sessions[0].inside_port,
4367 sessions[0].protocol,
4368 ext_host_address=sessions[0].ext_host_nat_address,
4369 ext_host_port=sessions[0].ext_host_nat_port)
4370 sessions = self.vapi.nat44_user_session_dump(server.ip4n, 0)
4371 self.assertEqual(len(sessions), 0)
4372
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004373 def test_twice_nat(self):
4374 """ Twice NAT44 """
4375 self.twice_nat_common()
4376
4377 def test_self_twice_nat_positive(self):
4378 """ Self Twice NAT44 (positive test) """
4379 self.twice_nat_common(self_twice_nat=True, same_pg=True)
4380
4381 def test_self_twice_nat_negative(self):
4382 """ Self Twice NAT44 (negative test) """
4383 self.twice_nat_common(self_twice_nat=True)
4384
Matus Fabianb932d262017-12-18 05:38:24 -08004385 def test_twice_nat_lb(self):
4386 """ Twice NAT44 local service load balancing """
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004387 self.twice_nat_common(lb=True)
Matus Fabianb932d262017-12-18 05:38:24 -08004388
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004389 def test_self_twice_nat_lb_positive(self):
4390 """ Self Twice NAT44 local service load balancing (positive test) """
4391 self.twice_nat_common(lb=True, self_twice_nat=True, same_pg=True,
4392 client_id=1)
Matus Fabianb932d262017-12-18 05:38:24 -08004393
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004394 def test_self_twice_nat_lb_negative(self):
4395 """ Self Twice NAT44 local service load balancing (negative test) """
4396 self.twice_nat_common(lb=True, self_twice_nat=True, same_pg=True,
4397 client_id=2)
Matus Fabianb932d262017-12-18 05:38:24 -08004398
4399 def test_twice_nat_interface_addr(self):
4400 """ Acquire twice NAT44 addresses from interface """
Matus Fabiana6110b62018-06-13 05:39:07 -07004401 self.vapi.nat44_add_interface_addr(self.pg3.sw_if_index, twice_nat=1)
Matus Fabianb932d262017-12-18 05:38:24 -08004402
4403 # no address in NAT pool
4404 adresses = self.vapi.nat44_address_dump()
4405 self.assertEqual(0, len(adresses))
4406
4407 # configure interface address and check NAT address pool
Matus Fabiana6110b62018-06-13 05:39:07 -07004408 self.pg3.config_ip4()
Matus Fabianb932d262017-12-18 05:38:24 -08004409 adresses = self.vapi.nat44_address_dump()
4410 self.assertEqual(1, len(adresses))
Matus Fabiana6110b62018-06-13 05:39:07 -07004411 self.assertEqual(adresses[0].ip_address[0:4], self.pg3.local_ip4n)
Matus Fabianb932d262017-12-18 05:38:24 -08004412 self.assertEqual(adresses[0].twice_nat, 1)
4413
4414 # remove interface address and check NAT address pool
Matus Fabiana6110b62018-06-13 05:39:07 -07004415 self.pg3.unconfig_ip4()
Matus Fabianb932d262017-12-18 05:38:24 -08004416 adresses = self.vapi.nat44_address_dump()
4417 self.assertEqual(0, len(adresses))
4418
Matus Fabianebdf1902018-05-04 03:57:42 -07004419 def test_tcp_session_close_in(self):
4420 """ Close TCP session from inside network """
Matus Fabian229c1aa2018-05-28 04:09:52 -07004421 self.tcp_port_out = 10505
Matus Fabianebdf1902018-05-04 03:57:42 -07004422 self.nat44_add_address(self.nat_addr)
Matus Fabian229c1aa2018-05-28 04:09:52 -07004423 self.nat44_add_static_mapping(self.pg0.remote_ip4,
4424 self.nat_addr,
4425 self.tcp_port_in,
4426 self.tcp_port_out,
4427 proto=IP_PROTOS.tcp,
4428 twice_nat=1)
Matus Fabianebdf1902018-05-04 03:57:42 -07004429 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4430 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4431 is_inside=0)
4432
4433 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
4434 start_sessnum = len(sessions)
4435
4436 self.initiate_tcp_session(self.pg0, self.pg1)
4437
Matus Fabian229c1aa2018-05-28 04:09:52 -07004438 # FIN packet in -> out
4439 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4440 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4441 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
4442 flags="FA", seq=100, ack=300))
4443 self.pg0.add_stream(p)
4444 self.pg_enable_capture(self.pg_interfaces)
4445 self.pg_start()
4446 self.pg1.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07004447
Matus Fabian229c1aa2018-05-28 04:09:52 -07004448 pkts = []
Matus Fabianebdf1902018-05-04 03:57:42 -07004449
Matus Fabian229c1aa2018-05-28 04:09:52 -07004450 # ACK packet out -> in
4451 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4452 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4453 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
4454 flags="A", seq=300, ack=101))
4455 pkts.append(p)
Matus Fabianebdf1902018-05-04 03:57:42 -07004456
Matus Fabian229c1aa2018-05-28 04:09:52 -07004457 # FIN packet out -> in
4458 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4459 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4460 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
4461 flags="FA", seq=300, ack=101))
4462 pkts.append(p)
Matus Fabianebdf1902018-05-04 03:57:42 -07004463
Matus Fabian229c1aa2018-05-28 04:09:52 -07004464 self.pg1.add_stream(pkts)
4465 self.pg_enable_capture(self.pg_interfaces)
4466 self.pg_start()
4467 self.pg0.get_capture(2)
Matus Fabianebdf1902018-05-04 03:57:42 -07004468
Matus Fabian229c1aa2018-05-28 04:09:52 -07004469 # ACK packet in -> out
4470 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4471 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4472 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
4473 flags="A", seq=101, ack=301))
4474 self.pg0.add_stream(p)
4475 self.pg_enable_capture(self.pg_interfaces)
4476 self.pg_start()
4477 self.pg1.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07004478
Matus Fabian229c1aa2018-05-28 04:09:52 -07004479 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n,
4480 0)
4481 self.assertEqual(len(sessions) - start_sessnum, 0)
Matus Fabianebdf1902018-05-04 03:57:42 -07004482
4483 def test_tcp_session_close_out(self):
4484 """ Close TCP session from outside network """
Matus Fabian229c1aa2018-05-28 04:09:52 -07004485 self.tcp_port_out = 10505
Matus Fabianebdf1902018-05-04 03:57:42 -07004486 self.nat44_add_address(self.nat_addr)
Matus Fabian229c1aa2018-05-28 04:09:52 -07004487 self.nat44_add_static_mapping(self.pg0.remote_ip4,
4488 self.nat_addr,
4489 self.tcp_port_in,
4490 self.tcp_port_out,
4491 proto=IP_PROTOS.tcp,
4492 twice_nat=1)
Matus Fabianebdf1902018-05-04 03:57:42 -07004493 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4494 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4495 is_inside=0)
4496
4497 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
4498 start_sessnum = len(sessions)
4499
4500 self.initiate_tcp_session(self.pg0, self.pg1)
4501
Matus Fabian229c1aa2018-05-28 04:09:52 -07004502 # FIN packet out -> in
4503 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4504 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4505 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
4506 flags="FA", seq=100, ack=300))
4507 self.pg1.add_stream(p)
4508 self.pg_enable_capture(self.pg_interfaces)
4509 self.pg_start()
4510 self.pg0.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07004511
Matus Fabian229c1aa2018-05-28 04:09:52 -07004512 # FIN+ACK packet in -> out
4513 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4514 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4515 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
4516 flags="FA", seq=300, ack=101))
Matus Fabianebdf1902018-05-04 03:57:42 -07004517
Matus Fabian229c1aa2018-05-28 04:09:52 -07004518 self.pg0.add_stream(p)
4519 self.pg_enable_capture(self.pg_interfaces)
4520 self.pg_start()
4521 self.pg1.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07004522
Matus Fabian229c1aa2018-05-28 04:09:52 -07004523 # ACK packet out -> in
4524 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4525 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4526 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
4527 flags="A", seq=101, ack=301))
4528 self.pg1.add_stream(p)
4529 self.pg_enable_capture(self.pg_interfaces)
4530 self.pg_start()
4531 self.pg0.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07004532
Matus Fabian229c1aa2018-05-28 04:09:52 -07004533 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n,
4534 0)
4535 self.assertEqual(len(sessions) - start_sessnum, 0)
Matus Fabianebdf1902018-05-04 03:57:42 -07004536
4537 def test_tcp_session_close_simultaneous(self):
4538 """ Close TCP session from inside network """
Matus Fabian229c1aa2018-05-28 04:09:52 -07004539 self.tcp_port_out = 10505
Matus Fabianebdf1902018-05-04 03:57:42 -07004540 self.nat44_add_address(self.nat_addr)
Matus Fabian229c1aa2018-05-28 04:09:52 -07004541 self.nat44_add_static_mapping(self.pg0.remote_ip4,
4542 self.nat_addr,
4543 self.tcp_port_in,
4544 self.tcp_port_out,
4545 proto=IP_PROTOS.tcp,
4546 twice_nat=1)
Matus Fabianebdf1902018-05-04 03:57:42 -07004547 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4548 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4549 is_inside=0)
4550
4551 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
4552 start_sessnum = len(sessions)
4553
4554 self.initiate_tcp_session(self.pg0, self.pg1)
4555
Matus Fabian229c1aa2018-05-28 04:09:52 -07004556 # FIN packet in -> out
4557 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4558 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4559 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
4560 flags="FA", seq=100, ack=300))
4561 self.pg0.add_stream(p)
4562 self.pg_enable_capture(self.pg_interfaces)
4563 self.pg_start()
4564 self.pg1.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07004565
Matus Fabian229c1aa2018-05-28 04:09:52 -07004566 # FIN packet out -> in
4567 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4568 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4569 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
4570 flags="FA", seq=300, ack=100))
4571 self.pg1.add_stream(p)
4572 self.pg_enable_capture(self.pg_interfaces)
4573 self.pg_start()
4574 self.pg0.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07004575
Matus Fabian229c1aa2018-05-28 04:09:52 -07004576 # ACK packet in -> out
4577 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4578 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4579 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
4580 flags="A", seq=101, ack=301))
4581 self.pg0.add_stream(p)
4582 self.pg_enable_capture(self.pg_interfaces)
4583 self.pg_start()
4584 self.pg1.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07004585
Matus Fabian229c1aa2018-05-28 04:09:52 -07004586 # ACK packet out -> in
4587 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4588 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4589 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
4590 flags="A", seq=301, ack=101))
4591 self.pg1.add_stream(p)
4592 self.pg_enable_capture(self.pg_interfaces)
4593 self.pg_start()
4594 self.pg0.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07004595
Matus Fabian229c1aa2018-05-28 04:09:52 -07004596 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n,
4597 0)
4598 self.assertEqual(len(sessions) - start_sessnum, 0)
Matus Fabianebdf1902018-05-04 03:57:42 -07004599
Matus Fabiana6110b62018-06-13 05:39:07 -07004600 def test_one_armed_nat44_static(self):
4601 """ One armed NAT44 and 1:1 NAPT asymmetrical rule """
4602 remote_host = self.pg4.remote_hosts[0]
4603 local_host = self.pg4.remote_hosts[1]
4604 external_port = 80
4605 local_port = 8080
4606 eh_port_in = 0
4607
4608 self.vapi.nat44_forwarding_enable_disable(1)
4609 self.nat44_add_address(self.nat_addr, twice_nat=1)
4610 self.nat44_add_static_mapping(local_host.ip4, self.nat_addr,
4611 local_port, external_port,
4612 proto=IP_PROTOS.tcp, out2in_only=1,
4613 twice_nat=1)
4614 self.vapi.nat44_interface_add_del_feature(self.pg4.sw_if_index)
4615 self.vapi.nat44_interface_add_del_feature(self.pg4.sw_if_index,
4616 is_inside=0)
4617
4618 # from client to service
4619 p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
4620 IP(src=remote_host.ip4, dst=self.nat_addr) /
4621 TCP(sport=12345, dport=external_port))
4622 self.pg4.add_stream(p)
4623 self.pg_enable_capture(self.pg_interfaces)
4624 self.pg_start()
4625 capture = self.pg4.get_capture(1)
4626 p = capture[0]
4627 try:
4628 ip = p[IP]
4629 tcp = p[TCP]
4630 self.assertEqual(ip.dst, local_host.ip4)
4631 self.assertEqual(ip.src, self.nat_addr)
4632 self.assertEqual(tcp.dport, local_port)
4633 self.assertNotEqual(tcp.sport, 12345)
4634 eh_port_in = tcp.sport
4635 self.assert_packet_checksums_valid(p)
4636 except:
4637 self.logger.error(ppp("Unexpected or invalid packet:", p))
4638 raise
4639
4640 # from service back to client
4641 p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
4642 IP(src=local_host.ip4, dst=self.nat_addr) /
4643 TCP(sport=local_port, dport=eh_port_in))
4644 self.pg4.add_stream(p)
4645 self.pg_enable_capture(self.pg_interfaces)
4646 self.pg_start()
4647 capture = self.pg4.get_capture(1)
4648 p = capture[0]
4649 try:
4650 ip = p[IP]
4651 tcp = p[TCP]
4652 self.assertEqual(ip.src, self.nat_addr)
4653 self.assertEqual(ip.dst, remote_host.ip4)
4654 self.assertEqual(tcp.sport, external_port)
4655 self.assertEqual(tcp.dport, 12345)
4656 self.assert_packet_checksums_valid(p)
4657 except:
4658 self.logger.error(ppp("Unexpected or invalid packet:", p))
4659 raise
4660
4661 def test_static_with_port_out2(self):
4662 """ 1:1 NAPT asymmetrical rule """
4663
4664 external_port = 80
4665 local_port = 8080
4666
4667 self.vapi.nat44_forwarding_enable_disable(1)
4668 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
4669 local_port, external_port,
4670 proto=IP_PROTOS.tcp, out2in_only=1)
4671 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4672 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4673 is_inside=0)
4674
4675 # from client to service
4676 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4677 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4678 TCP(sport=12345, dport=external_port))
4679 self.pg1.add_stream(p)
4680 self.pg_enable_capture(self.pg_interfaces)
4681 self.pg_start()
4682 capture = self.pg0.get_capture(1)
4683 p = capture[0]
4684 try:
4685 ip = p[IP]
4686 tcp = p[TCP]
4687 self.assertEqual(ip.dst, self.pg0.remote_ip4)
4688 self.assertEqual(tcp.dport, local_port)
4689 self.assert_packet_checksums_valid(p)
4690 except:
4691 self.logger.error(ppp("Unexpected or invalid packet:", p))
4692 raise
4693
4694 # ICMP error
4695 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
4696 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4697 ICMP(type=11) / capture[0][IP])
4698 self.pg0.add_stream(p)
4699 self.pg_enable_capture(self.pg_interfaces)
4700 self.pg_start()
4701 capture = self.pg1.get_capture(1)
4702 p = capture[0]
4703 try:
4704 self.assertEqual(p[IP].src, self.nat_addr)
4705 inner = p[IPerror]
4706 self.assertEqual(inner.dst, self.nat_addr)
4707 self.assertEqual(inner[TCPerror].dport, external_port)
4708 except:
4709 self.logger.error(ppp("Unexpected or invalid packet:", p))
4710 raise
4711
4712 # from service back to client
4713 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4714 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4715 TCP(sport=local_port, dport=12345))
4716 self.pg0.add_stream(p)
4717 self.pg_enable_capture(self.pg_interfaces)
4718 self.pg_start()
4719 capture = self.pg1.get_capture(1)
4720 p = capture[0]
4721 try:
4722 ip = p[IP]
4723 tcp = p[TCP]
4724 self.assertEqual(ip.src, self.nat_addr)
4725 self.assertEqual(tcp.sport, external_port)
4726 self.assert_packet_checksums_valid(p)
4727 except:
4728 self.logger.error(ppp("Unexpected or invalid packet:", p))
4729 raise
4730
4731 # ICMP error
4732 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
4733 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4734 ICMP(type=11) / capture[0][IP])
4735 self.pg1.add_stream(p)
4736 self.pg_enable_capture(self.pg_interfaces)
4737 self.pg_start()
4738 capture = self.pg0.get_capture(1)
4739 p = capture[0]
4740 try:
4741 self.assertEqual(p[IP].dst, self.pg0.remote_ip4)
4742 inner = p[IPerror]
4743 self.assertEqual(inner.src, self.pg0.remote_ip4)
4744 self.assertEqual(inner[TCPerror].sport, local_port)
4745 except:
4746 self.logger.error(ppp("Unexpected or invalid packet:", p))
4747 raise
4748
4749 # from client to server (no translation)
4750 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4751 IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
4752 TCP(sport=12346, dport=local_port))
4753 self.pg1.add_stream(p)
4754 self.pg_enable_capture(self.pg_interfaces)
4755 self.pg_start()
4756 capture = self.pg0.get_capture(1)
4757 p = capture[0]
4758 try:
4759 ip = p[IP]
4760 tcp = p[TCP]
4761 self.assertEqual(ip.dst, self.pg0.remote_ip4)
4762 self.assertEqual(tcp.dport, local_port)
4763 self.assert_packet_checksums_valid(p)
4764 except:
4765 self.logger.error(ppp("Unexpected or invalid packet:", p))
4766 raise
4767
4768 # from service back to client (no translation)
4769 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4770 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4771 TCP(sport=local_port, dport=12346))
4772 self.pg0.add_stream(p)
4773 self.pg_enable_capture(self.pg_interfaces)
4774 self.pg_start()
4775 capture = self.pg1.get_capture(1)
4776 p = capture[0]
4777 try:
4778 ip = p[IP]
4779 tcp = p[TCP]
4780 self.assertEqual(ip.src, self.pg0.remote_ip4)
4781 self.assertEqual(tcp.sport, local_port)
4782 self.assert_packet_checksums_valid(p)
4783 except:
4784 self.logger.error(ppp("Unexpected or invalid packet:", p))
4785 raise
4786
Matus Fabian235a47e2018-06-25 16:42:36 -07004787 def test_output_feature(self):
4788 """ NAT44 interface output feature (in2out postrouting) """
4789 self.vapi.nat44_forwarding_enable_disable(1)
4790 self.nat44_add_address(self.nat_addr)
4791 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
4792 is_inside=0)
4793 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
4794 is_inside=0)
4795
4796 # in2out
4797 pkts = self.create_stream_in(self.pg0, self.pg1)
4798 self.pg0.add_stream(pkts)
4799 self.pg_enable_capture(self.pg_interfaces)
4800 self.pg_start()
4801 capture = self.pg1.get_capture(len(pkts))
4802 self.verify_capture_out(capture)
4803
4804 # out2in
4805 pkts = self.create_stream_out(self.pg1)
4806 self.pg1.add_stream(pkts)
4807 self.pg_enable_capture(self.pg_interfaces)
4808 self.pg_start()
4809 capture = self.pg0.get_capture(len(pkts))
4810 self.verify_capture_in(capture, self.pg0)
4811
Matus Fabian8008d7c2018-07-09 01:34:20 -07004812 def test_multiple_vrf(self):
4813 """ Multiple VRF setup """
4814 external_addr = '1.2.3.4'
4815 external_port = 80
4816 local_port = 8080
4817 port = 0
4818
4819 self.vapi.nat44_forwarding_enable_disable(1)
4820 self.nat44_add_address(self.nat_addr)
4821 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4822 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
4823 is_inside=0)
4824 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
4825 is_inside=0)
4826 self.vapi.nat44_interface_add_del_feature(self.pg5.sw_if_index)
4827 self.vapi.nat44_interface_add_del_feature(self.pg5.sw_if_index,
4828 is_inside=0)
4829 self.vapi.nat44_interface_add_del_feature(self.pg6.sw_if_index,
4830 is_inside=0)
4831 self.nat44_add_static_mapping(self.pg5.remote_ip4, external_addr,
4832 local_port, external_port, vrf_id=1,
4833 proto=IP_PROTOS.tcp, out2in_only=1)
4834 self.nat44_add_static_mapping(
4835 self.pg0.remote_ip4, external_sw_if_index=self.pg0.sw_if_index,
4836 local_port=local_port, vrf_id=0, external_port=external_port,
4837 proto=IP_PROTOS.tcp, out2in_only=1)
4838
4839 # from client to service (both VRF1)
4840 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
4841 IP(src=self.pg6.remote_ip4, dst=external_addr) /
4842 TCP(sport=12345, dport=external_port))
4843 self.pg6.add_stream(p)
4844 self.pg_enable_capture(self.pg_interfaces)
4845 self.pg_start()
4846 capture = self.pg5.get_capture(1)
4847 p = capture[0]
4848 try:
4849 ip = p[IP]
4850 tcp = p[TCP]
4851 self.assertEqual(ip.dst, self.pg5.remote_ip4)
4852 self.assertEqual(tcp.dport, local_port)
4853 self.assert_packet_checksums_valid(p)
4854 except:
4855 self.logger.error(ppp("Unexpected or invalid packet:", p))
4856 raise
4857
4858 # from service back to client (both VRF1)
4859 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
4860 IP(src=self.pg5.remote_ip4, dst=self.pg6.remote_ip4) /
4861 TCP(sport=local_port, dport=12345))
4862 self.pg5.add_stream(p)
4863 self.pg_enable_capture(self.pg_interfaces)
4864 self.pg_start()
4865 capture = self.pg6.get_capture(1)
4866 p = capture[0]
4867 try:
4868 ip = p[IP]
4869 tcp = p[TCP]
4870 self.assertEqual(ip.src, external_addr)
4871 self.assertEqual(tcp.sport, external_port)
4872 self.assert_packet_checksums_valid(p)
4873 except:
4874 self.logger.error(ppp("Unexpected or invalid packet:", p))
4875 raise
4876
4877 # dynamic NAT from VRF1 to VRF0 (output-feature)
4878 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
4879 IP(src=self.pg5.remote_ip4, dst=self.pg1.remote_ip4) /
4880 TCP(sport=2345, dport=22))
4881 self.pg5.add_stream(p)
4882 self.pg_enable_capture(self.pg_interfaces)
4883 self.pg_start()
4884 capture = self.pg1.get_capture(1)
4885 p = capture[0]
4886 try:
4887 ip = p[IP]
4888 tcp = p[TCP]
4889 self.assertEqual(ip.src, self.nat_addr)
4890 self.assertNotEqual(tcp.sport, 2345)
4891 self.assert_packet_checksums_valid(p)
4892 port = tcp.sport
4893 except:
4894 self.logger.error(ppp("Unexpected or invalid packet:", p))
4895 raise
4896
4897 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4898 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4899 TCP(sport=22, dport=port))
4900 self.pg1.add_stream(p)
4901 self.pg_enable_capture(self.pg_interfaces)
4902 self.pg_start()
4903 capture = self.pg5.get_capture(1)
4904 p = capture[0]
4905 try:
4906 ip = p[IP]
4907 tcp = p[TCP]
4908 self.assertEqual(ip.dst, self.pg5.remote_ip4)
4909 self.assertEqual(tcp.dport, 2345)
4910 self.assert_packet_checksums_valid(p)
4911 except:
4912 self.logger.error(ppp("Unexpected or invalid packet:", p))
4913 raise
4914
4915 # from client VRF1 to service VRF0
4916 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
4917 IP(src=self.pg6.remote_ip4, dst=self.pg0.local_ip4) /
4918 TCP(sport=12346, dport=external_port))
4919 self.pg6.add_stream(p)
4920 self.pg_enable_capture(self.pg_interfaces)
4921 self.pg_start()
4922 capture = self.pg0.get_capture(1)
4923 p = capture[0]
4924 try:
4925 ip = p[IP]
4926 tcp = p[TCP]
4927 self.assertEqual(ip.dst, self.pg0.remote_ip4)
4928 self.assertEqual(tcp.dport, local_port)
4929 self.assert_packet_checksums_valid(p)
4930 except:
4931 self.logger.error(ppp("Unexpected or invalid packet:", p))
4932 raise
4933
4934 # from service VRF0 back to client VRF1
4935 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4936 IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
4937 TCP(sport=local_port, dport=12346))
4938 self.pg0.add_stream(p)
4939 self.pg_enable_capture(self.pg_interfaces)
4940 self.pg_start()
4941 capture = self.pg6.get_capture(1)
4942 p = capture[0]
4943 try:
4944 ip = p[IP]
4945 tcp = p[TCP]
4946 self.assertEqual(ip.src, self.pg0.local_ip4)
4947 self.assertEqual(tcp.sport, external_port)
4948 self.assert_packet_checksums_valid(p)
4949 except:
4950 self.logger.error(ppp("Unexpected or invalid packet:", p))
4951 raise
4952
4953 # from client VRF0 to service VRF1
4954 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4955 IP(src=self.pg0.remote_ip4, dst=external_addr) /
4956 TCP(sport=12347, dport=external_port))
4957 self.pg0.add_stream(p)
4958 self.pg_enable_capture(self.pg_interfaces)
4959 self.pg_start()
4960 capture = self.pg5.get_capture(1)
4961 p = capture[0]
4962 try:
4963 ip = p[IP]
4964 tcp = p[TCP]
4965 self.assertEqual(ip.dst, self.pg5.remote_ip4)
4966 self.assertEqual(tcp.dport, local_port)
4967 self.assert_packet_checksums_valid(p)
4968 except:
4969 self.logger.error(ppp("Unexpected or invalid packet:", p))
4970 raise
4971
4972 # from service VRF1 back to client VRF0
4973 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
4974 IP(src=self.pg5.remote_ip4, dst=self.pg0.remote_ip4) /
4975 TCP(sport=local_port, dport=12347))
4976 self.pg5.add_stream(p)
4977 self.pg_enable_capture(self.pg_interfaces)
4978 self.pg_start()
4979 capture = self.pg0.get_capture(1)
4980 p = capture[0]
4981 try:
4982 ip = p[IP]
4983 tcp = p[TCP]
4984 self.assertEqual(ip.src, external_addr)
4985 self.assertEqual(tcp.sport, external_port)
4986 self.assert_packet_checksums_valid(p)
4987 except:
4988 self.logger.error(ppp("Unexpected or invalid packet:", p))
4989 raise
4990
4991 # from client to server (both VRF1, no translation)
4992 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
4993 IP(src=self.pg6.remote_ip4, dst=self.pg5.remote_ip4) /
4994 TCP(sport=12348, dport=local_port))
4995 self.pg6.add_stream(p)
4996 self.pg_enable_capture(self.pg_interfaces)
4997 self.pg_start()
4998 capture = self.pg5.get_capture(1)
4999 p = capture[0]
5000 try:
5001 ip = p[IP]
5002 tcp = p[TCP]
5003 self.assertEqual(ip.dst, self.pg5.remote_ip4)
5004 self.assertEqual(tcp.dport, local_port)
5005 self.assert_packet_checksums_valid(p)
5006 except:
5007 self.logger.error(ppp("Unexpected or invalid packet:", p))
5008 raise
5009
5010 # from server back to client (both VRF1, no translation)
5011 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
5012 IP(src=self.pg5.remote_ip4, dst=self.pg6.remote_ip4) /
5013 TCP(sport=local_port, dport=12348))
5014 self.pg5.add_stream(p)
5015 self.pg_enable_capture(self.pg_interfaces)
5016 self.pg_start()
5017 capture = self.pg6.get_capture(1)
5018 p = capture[0]
5019 try:
5020 ip = p[IP]
5021 tcp = p[TCP]
5022 self.assertEqual(ip.src, self.pg5.remote_ip4)
5023 self.assertEqual(tcp.sport, local_port)
5024 self.assert_packet_checksums_valid(p)
5025 except:
5026 self.logger.error(ppp("Unexpected or invalid packet:", p))
5027 raise
5028
5029 # from client VRF1 to server VRF0 (no translation)
5030 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5031 IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
5032 TCP(sport=local_port, dport=12349))
5033 self.pg0.add_stream(p)
5034 self.pg_enable_capture(self.pg_interfaces)
5035 self.pg_start()
5036 capture = self.pg6.get_capture(1)
5037 p = capture[0]
5038 try:
5039 ip = p[IP]
5040 tcp = p[TCP]
5041 self.assertEqual(ip.src, self.pg0.remote_ip4)
5042 self.assertEqual(tcp.sport, local_port)
5043 self.assert_packet_checksums_valid(p)
5044 except:
5045 self.logger.error(ppp("Unexpected or invalid packet:", p))
5046 raise
5047
5048 # from server VRF0 back to client VRF1 (no translation)
5049 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5050 IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
5051 TCP(sport=local_port, dport=12349))
5052 self.pg0.add_stream(p)
5053 self.pg_enable_capture(self.pg_interfaces)
5054 self.pg_start()
5055 capture = self.pg6.get_capture(1)
5056 p = capture[0]
5057 try:
5058 ip = p[IP]
5059 tcp = p[TCP]
5060 self.assertEqual(ip.src, self.pg0.remote_ip4)
5061 self.assertEqual(tcp.sport, local_port)
5062 self.assert_packet_checksums_valid(p)
5063 except:
5064 self.logger.error(ppp("Unexpected or invalid packet:", p))
5065 raise
5066
5067 # from client VRF0 to server VRF1 (no translation)
5068 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5069 IP(src=self.pg0.remote_ip4, dst=self.pg5.remote_ip4) /
5070 TCP(sport=12344, dport=local_port))
5071 self.pg0.add_stream(p)
5072 self.pg_enable_capture(self.pg_interfaces)
5073 self.pg_start()
5074 capture = self.pg5.get_capture(1)
5075 p = capture[0]
5076 try:
5077 ip = p[IP]
5078 tcp = p[TCP]
5079 self.assertEqual(ip.dst, self.pg5.remote_ip4)
5080 self.assertEqual(tcp.dport, local_port)
5081 self.assert_packet_checksums_valid(p)
5082 except:
5083 self.logger.error(ppp("Unexpected or invalid packet:", p))
5084 raise
5085
5086 # from server VRF1 back to client VRF0 (no translation)
5087 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
5088 IP(src=self.pg5.remote_ip4, dst=self.pg0.remote_ip4) /
5089 TCP(sport=local_port, dport=12344))
5090 self.pg5.add_stream(p)
5091 self.pg_enable_capture(self.pg_interfaces)
5092 self.pg_start()
5093 capture = self.pg0.get_capture(1)
5094 p = capture[0]
5095 try:
5096 ip = p[IP]
5097 tcp = p[TCP]
5098 self.assertEqual(ip.src, self.pg5.remote_ip4)
5099 self.assertEqual(tcp.sport, local_port)
5100 self.assert_packet_checksums_valid(p)
5101 except:
5102 self.logger.error(ppp("Unexpected or invalid packet:", p))
5103 raise
5104
Matus Fabian878c6462018-08-23 00:33:35 -07005105 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
5106 def test_session_timeout(self):
5107 """ NAT44 session timeouts """
5108 self.nat44_add_address(self.nat_addr)
5109 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5110 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
5111 is_inside=0)
5112 self.vapi.nat_set_timeouts(icmp=5)
5113
5114 max_sessions = 1000
5115 pkts = []
5116 for i in range(0, max_sessions):
5117 src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
5118 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5119 IP(src=src, dst=self.pg1.remote_ip4) /
5120 ICMP(id=1025, type='echo-request'))
5121 pkts.append(p)
5122 self.pg0.add_stream(pkts)
5123 self.pg_enable_capture(self.pg_interfaces)
5124 self.pg_start()
5125 self.pg1.get_capture(max_sessions)
5126
5127 sleep(10)
5128
5129 pkts = []
5130 for i in range(0, max_sessions):
5131 src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
5132 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5133 IP(src=src, dst=self.pg1.remote_ip4) /
5134 ICMP(id=1026, type='echo-request'))
5135 pkts.append(p)
5136 self.pg0.add_stream(pkts)
5137 self.pg_enable_capture(self.pg_interfaces)
5138 self.pg_start()
5139 self.pg1.get_capture(max_sessions)
5140
5141 nsessions = 0
5142 users = self.vapi.nat44_user_dump()
5143 for user in users:
5144 nsessions = nsessions + user.nsessions
5145 self.assertLess(nsessions, 2 * max_sessions)
5146
5147 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
5148 def test_session_limit_per_user(self):
5149 """ Maximum sessions per user limit """
5150 self.nat44_add_address(self.nat_addr)
5151 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5152 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
5153 is_inside=0)
5154 self.vapi.set_ipfix_exporter(collector_address=self.pg2.remote_ip4n,
5155 src_address=self.pg2.local_ip4n,
5156 path_mtu=512,
5157 template_interval=10)
5158
5159 # get maximum number of translations per user
5160 nat44_config = self.vapi.nat_show_config()
5161
5162 pkts = []
5163 for port in range(0, nat44_config.max_translations_per_user):
5164 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5165 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5166 UDP(sport=1025 + port, dport=1025 + port))
5167 pkts.append(p)
5168
5169 self.pg0.add_stream(pkts)
5170 self.pg_enable_capture(self.pg_interfaces)
5171 self.pg_start()
5172 capture = self.pg1.get_capture(len(pkts))
5173
5174 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
5175 src_port=self.ipfix_src_port)
5176
5177 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5178 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5179 UDP(sport=3001, dport=3002))
5180 self.pg0.add_stream(p)
5181 self.pg_enable_capture(self.pg_interfaces)
5182 self.pg_start()
5183 capture = self.pg1.assert_nothing_captured()
5184
5185 # verify IPFIX logging
5186 self.vapi.cli("ipfix flush") # FIXME this should be an API call
5187 sleep(1)
5188 capture = self.pg2.get_capture(10)
5189 ipfix = IPFIXDecoder()
5190 # first load template
5191 for p in capture:
5192 self.assertTrue(p.haslayer(IPFIX))
5193 if p.haslayer(Template):
5194 ipfix.add_template(p.getlayer(Template))
5195 # verify events in data set
5196 for p in capture:
5197 if p.haslayer(Data):
5198 data = ipfix.decode_data_set(p.getlayer(Set))
5199 self.verify_ipfix_max_entries_per_user(
5200 data,
5201 nat44_config.max_translations_per_user,
5202 self.pg0.remote_ip4n)
5203
Matus Fabiande886752016-12-07 03:38:19 -08005204 def tearDown(self):
Matus Fabiana6110b62018-06-13 05:39:07 -07005205 super(TestNAT44EndpointDependent, self).tearDown()
Matus Fabiande886752016-12-07 03:38:19 -08005206 if not self.vpp_dead:
Matus Fabian82119542018-01-25 01:13:22 -08005207 self.logger.info(self.vapi.cli("show nat44 addresses"))
5208 self.logger.info(self.vapi.cli("show nat44 interfaces"))
5209 self.logger.info(self.vapi.cli("show nat44 static mappings"))
5210 self.logger.info(self.vapi.cli("show nat44 interface address"))
5211 self.logger.info(self.vapi.cli("show nat44 sessions detail"))
Matus Fabian229c1aa2018-05-28 04:09:52 -07005212 self.logger.info(self.vapi.cli("show nat44 hash tables detail"))
Matus Fabian878c6462018-08-23 00:33:35 -07005213 self.logger.info(self.vapi.cli("show nat timeouts"))
Matus Fabian2ba92e32017-08-21 07:05:03 -07005214 self.clear_nat44()
Matus Fabian229c1aa2018-05-28 04:09:52 -07005215 self.vapi.cli("clear logging")
Matus Fabiande886752016-12-07 03:38:19 -08005216
Matus Fabianeea28d72017-01-13 04:15:54 -08005217
Juraj Slobodacba69362017-12-19 02:09:32 +01005218class TestNAT44Out2InDPO(MethodHolder):
5219 """ NAT44 Test Cases using out2in DPO """
5220
5221 @classmethod
5222 def setUpConstants(cls):
5223 super(TestNAT44Out2InDPO, cls).setUpConstants()
5224 cls.vpp_cmdline.extend(["nat", "{", "out2in dpo", "}"])
5225
5226 @classmethod
5227 def setUpClass(cls):
5228 super(TestNAT44Out2InDPO, cls).setUpClass()
Matus Fabian229c1aa2018-05-28 04:09:52 -07005229 cls.vapi.cli("set log class nat level debug")
Juraj Slobodacba69362017-12-19 02:09:32 +01005230
5231 try:
5232 cls.tcp_port_in = 6303
5233 cls.tcp_port_out = 6303
5234 cls.udp_port_in = 6304
5235 cls.udp_port_out = 6304
5236 cls.icmp_id_in = 6305
5237 cls.icmp_id_out = 6305
5238 cls.nat_addr = '10.0.0.3'
5239 cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
5240 cls.dst_ip4 = '192.168.70.1'
5241
5242 cls.create_pg_interfaces(range(2))
5243
5244 cls.pg0.admin_up()
5245 cls.pg0.config_ip4()
5246 cls.pg0.resolve_arp()
5247
5248 cls.pg1.admin_up()
5249 cls.pg1.config_ip6()
5250 cls.pg1.resolve_ndp()
5251
5252 cls.vapi.ip_add_del_route(is_ipv6=True, dst_address='\x00'*16,
5253 dst_address_length=0,
5254 next_hop_address=cls.pg1.remote_ip6n,
5255 next_hop_sw_if_index=cls.pg1.sw_if_index)
5256
5257 except Exception:
5258 super(TestNAT44Out2InDPO, cls).tearDownClass()
5259 raise
5260
5261 def configure_xlat(self):
5262 self.dst_ip6_pfx = '1:2:3::'
5263 self.dst_ip6_pfx_n = socket.inet_pton(socket.AF_INET6,
5264 self.dst_ip6_pfx)
5265 self.dst_ip6_pfx_len = 96
5266 self.src_ip6_pfx = '4:5:6::'
5267 self.src_ip6_pfx_n = socket.inet_pton(socket.AF_INET6,
5268 self.src_ip6_pfx)
5269 self.src_ip6_pfx_len = 96
5270 self.vapi.map_add_domain(self.dst_ip6_pfx_n, self.dst_ip6_pfx_len,
5271 self.src_ip6_pfx_n, self.src_ip6_pfx_len,
5272 '\x00\x00\x00\x00', 0, is_translation=1,
5273 is_rfc6052=1)
5274
5275 def test_464xlat_ce(self):
5276 """ Test 464XLAT CE with NAT44 """
5277
Matus Fabian69ce30d2018-08-22 01:27:10 -07005278 nat_config = self.vapi.nat_show_config()
5279 self.assertEqual(1, nat_config.out2in_dpo)
5280
Juraj Slobodacba69362017-12-19 02:09:32 +01005281 self.configure_xlat()
5282
5283 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5284 self.vapi.nat44_add_del_address_range(self.nat_addr_n, self.nat_addr_n)
5285
5286 out_src_ip6 = self.compose_ip6(self.dst_ip4, self.dst_ip6_pfx,
5287 self.dst_ip6_pfx_len)
5288 out_dst_ip6 = self.compose_ip6(self.nat_addr, self.src_ip6_pfx,
5289 self.src_ip6_pfx_len)
5290
5291 try:
5292 pkts = self.create_stream_in(self.pg0, self.pg1, self.dst_ip4)
5293 self.pg0.add_stream(pkts)
5294 self.pg_enable_capture(self.pg_interfaces)
5295 self.pg_start()
5296 capture = self.pg1.get_capture(len(pkts))
5297 self.verify_capture_out_ip6(capture, nat_ip=out_dst_ip6,
5298 dst_ip=out_src_ip6)
5299
5300 pkts = self.create_stream_out_ip6(self.pg1, out_src_ip6,
5301 out_dst_ip6)
5302 self.pg1.add_stream(pkts)
5303 self.pg_enable_capture(self.pg_interfaces)
5304 self.pg_start()
5305 capture = self.pg0.get_capture(len(pkts))
5306 self.verify_capture_in(capture, self.pg0)
5307 finally:
5308 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
5309 is_add=0)
5310 self.vapi.nat44_add_del_address_range(self.nat_addr_n,
5311 self.nat_addr_n, is_add=0)
5312
5313 def test_464xlat_ce_no_nat(self):
5314 """ Test 464XLAT CE without NAT44 """
5315
5316 self.configure_xlat()
5317
5318 out_src_ip6 = self.compose_ip6(self.dst_ip4, self.dst_ip6_pfx,
5319 self.dst_ip6_pfx_len)
5320 out_dst_ip6 = self.compose_ip6(self.pg0.remote_ip4, self.src_ip6_pfx,
5321 self.src_ip6_pfx_len)
5322
5323 pkts = self.create_stream_in(self.pg0, self.pg1, self.dst_ip4)
5324 self.pg0.add_stream(pkts)
5325 self.pg_enable_capture(self.pg_interfaces)
5326 self.pg_start()
5327 capture = self.pg1.get_capture(len(pkts))
5328 self.verify_capture_out_ip6(capture, dst_ip=out_src_ip6,
5329 nat_ip=out_dst_ip6, same_port=True)
5330
5331 pkts = self.create_stream_out_ip6(self.pg1, out_src_ip6, out_dst_ip6)
5332 self.pg1.add_stream(pkts)
5333 self.pg_enable_capture(self.pg_interfaces)
5334 self.pg_start()
5335 capture = self.pg0.get_capture(len(pkts))
5336 self.verify_capture_in(capture, self.pg0)
5337
5338
Martin Gálikd7f75cd2017-03-27 06:02:47 -07005339class TestDeterministicNAT(MethodHolder):
Matus Fabian066f0342017-02-10 03:48:01 -08005340 """ Deterministic NAT Test Cases """
5341
5342 @classmethod
5343 def setUpConstants(cls):
5344 super(TestDeterministicNAT, cls).setUpConstants()
Matus Fabian2ba92e32017-08-21 07:05:03 -07005345 cls.vpp_cmdline.extend(["nat", "{", "deterministic", "}"])
Matus Fabian066f0342017-02-10 03:48:01 -08005346
5347 @classmethod
5348 def setUpClass(cls):
5349 super(TestDeterministicNAT, cls).setUpClass()
Matus Fabian229c1aa2018-05-28 04:09:52 -07005350 cls.vapi.cli("set log class nat level debug")
Matus Fabian066f0342017-02-10 03:48:01 -08005351
5352 try:
Martin Gálik977c1cb2017-03-30 23:21:51 -07005353 cls.tcp_port_in = 6303
Martin Gálik9806eae2017-04-25 01:25:08 -07005354 cls.tcp_external_port = 6303
Martin Gálik977c1cb2017-03-30 23:21:51 -07005355 cls.udp_port_in = 6304
Martin Gálik9806eae2017-04-25 01:25:08 -07005356 cls.udp_external_port = 6304
Martin Gálik977c1cb2017-03-30 23:21:51 -07005357 cls.icmp_id_in = 6305
Matus Fabian2ba92e32017-08-21 07:05:03 -07005358 cls.nat_addr = '10.0.0.3'
Martin Gálik977c1cb2017-03-30 23:21:51 -07005359
Matus Fabian2f2db1c2017-04-18 05:29:59 -07005360 cls.create_pg_interfaces(range(3))
Matus Fabian066f0342017-02-10 03:48:01 -08005361 cls.interfaces = list(cls.pg_interfaces)
5362
5363 for i in cls.interfaces:
5364 i.admin_up()
5365 i.config_ip4()
5366 i.resolve_arp()
5367
Martin Gálik977c1cb2017-03-30 23:21:51 -07005368 cls.pg0.generate_remote_hosts(2)
5369 cls.pg0.configure_ipv4_neighbors()
5370
Matus Fabian066f0342017-02-10 03:48:01 -08005371 except Exception:
5372 super(TestDeterministicNAT, cls).tearDownClass()
5373 raise
5374
Martin Gálik977c1cb2017-03-30 23:21:51 -07005375 def create_stream_in(self, in_if, out_if, ttl=64):
5376 """
5377 Create packet stream for inside network
5378
5379 :param in_if: Inside interface
5380 :param out_if: Outside interface
5381 :param ttl: TTL of generated packets
5382 """
5383 pkts = []
5384 # TCP
5385 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
5386 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
Martin Gálik9806eae2017-04-25 01:25:08 -07005387 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07005388 pkts.append(p)
5389
5390 # UDP
5391 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
5392 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
Martin Gálik9806eae2017-04-25 01:25:08 -07005393 UDP(sport=self.udp_port_in, dport=self.udp_external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07005394 pkts.append(p)
5395
5396 # ICMP
5397 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
5398 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
5399 ICMP(id=self.icmp_id_in, type='echo-request'))
5400 pkts.append(p)
5401
5402 return pkts
5403
5404 def create_stream_out(self, out_if, dst_ip=None, ttl=64):
5405 """
5406 Create packet stream for outside network
5407
5408 :param out_if: Outside interface
Matus Fabian2ba92e32017-08-21 07:05:03 -07005409 :param dst_ip: Destination IP address (Default use global NAT address)
Martin Gálik977c1cb2017-03-30 23:21:51 -07005410 :param ttl: TTL of generated packets
5411 """
5412 if dst_ip is None:
Matus Fabian2ba92e32017-08-21 07:05:03 -07005413 dst_ip = self.nat_addr
Martin Gálik977c1cb2017-03-30 23:21:51 -07005414 pkts = []
5415 # TCP
5416 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
5417 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Martin Gálik9806eae2017-04-25 01:25:08 -07005418 TCP(dport=self.tcp_port_out, sport=self.tcp_external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07005419 pkts.append(p)
5420
5421 # UDP
5422 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
5423 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Martin Gálik9806eae2017-04-25 01:25:08 -07005424 UDP(dport=self.udp_port_out, sport=self.udp_external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07005425 pkts.append(p)
5426
5427 # ICMP
5428 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
5429 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
5430 ICMP(id=self.icmp_external_id, type='echo-reply'))
5431 pkts.append(p)
5432
5433 return pkts
5434
Matus Fabian05ca4a32018-09-04 23:45:13 -07005435 def verify_capture_out(self, capture, nat_ip=None):
Martin Gálik977c1cb2017-03-30 23:21:51 -07005436 """
5437 Verify captured packets on outside network
5438
5439 :param capture: Captured packets
Matus Fabian2ba92e32017-08-21 07:05:03 -07005440 :param nat_ip: Translated IP address (Default use global NAT address)
Martin Gálik977c1cb2017-03-30 23:21:51 -07005441 :param same_port: Sorce port number is not translated (Default False)
Martin Gálik977c1cb2017-03-30 23:21:51 -07005442 """
5443 if nat_ip is None:
Matus Fabian2ba92e32017-08-21 07:05:03 -07005444 nat_ip = self.nat_addr
Martin Gálik977c1cb2017-03-30 23:21:51 -07005445 for packet in capture:
5446 try:
5447 self.assertEqual(packet[IP].src, nat_ip)
5448 if packet.haslayer(TCP):
Martin Gálik9806eae2017-04-25 01:25:08 -07005449 self.tcp_port_out = packet[TCP].sport
Martin Gálik977c1cb2017-03-30 23:21:51 -07005450 elif packet.haslayer(UDP):
Martin Gálik9806eae2017-04-25 01:25:08 -07005451 self.udp_port_out = packet[UDP].sport
Martin Gálik977c1cb2017-03-30 23:21:51 -07005452 else:
5453 self.icmp_external_id = packet[ICMP].id
5454 except:
5455 self.logger.error(ppp("Unexpected or invalid packet "
5456 "(outside network):", packet))
5457 raise
5458
Matus Fabian066f0342017-02-10 03:48:01 -08005459 def test_deterministic_mode(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07005460 """ NAT plugin run deterministic mode """
Matus Fabian066f0342017-02-10 03:48:01 -08005461 in_addr = '172.16.255.0'
5462 out_addr = '172.17.255.50'
5463 in_addr_t = '172.16.255.20'
5464 in_addr_n = socket.inet_aton(in_addr)
5465 out_addr_n = socket.inet_aton(out_addr)
5466 in_addr_t_n = socket.inet_aton(in_addr_t)
5467 in_plen = 24
5468 out_plen = 32
5469
Matus Fabian2ba92e32017-08-21 07:05:03 -07005470 nat_config = self.vapi.nat_show_config()
5471 self.assertEqual(1, nat_config.deterministic)
Matus Fabian066f0342017-02-10 03:48:01 -08005472
Matus Fabian2ba92e32017-08-21 07:05:03 -07005473 self.vapi.nat_det_add_del_map(in_addr_n, in_plen, out_addr_n, out_plen)
Matus Fabian066f0342017-02-10 03:48:01 -08005474
Matus Fabian2ba92e32017-08-21 07:05:03 -07005475 rep1 = self.vapi.nat_det_forward(in_addr_t_n)
Matus Fabian066f0342017-02-10 03:48:01 -08005476 self.assertEqual(rep1.out_addr[:4], out_addr_n)
Matus Fabian2ba92e32017-08-21 07:05:03 -07005477 rep2 = self.vapi.nat_det_reverse(out_addr_n, rep1.out_port_hi)
Matus Fabian066f0342017-02-10 03:48:01 -08005478 self.assertEqual(rep2.in_addr[:4], in_addr_t_n)
5479
Matus Fabian2ba92e32017-08-21 07:05:03 -07005480 deterministic_mappings = self.vapi.nat_det_map_dump()
Martin17a75cb2017-03-08 05:53:20 -08005481 self.assertEqual(len(deterministic_mappings), 1)
5482 dsm = deterministic_mappings[0]
5483 self.assertEqual(in_addr_n, dsm.in_addr[:4])
5484 self.assertEqual(in_plen, dsm.in_plen)
5485 self.assertEqual(out_addr_n, dsm.out_addr[:4])
5486 self.assertEqual(out_plen, dsm.out_plen)
5487
Matus Fabian2ba92e32017-08-21 07:05:03 -07005488 self.clear_nat_det()
5489 deterministic_mappings = self.vapi.nat_det_map_dump()
Martinb616e9f2017-03-14 02:25:45 -07005490 self.assertEqual(len(deterministic_mappings), 0)
5491
Matus Fabian6a0946f2017-04-12 03:36:13 -07005492 def test_set_timeouts(self):
5493 """ Set deterministic NAT timeouts """
Matus Fabian878c6462018-08-23 00:33:35 -07005494 timeouts_before = self.vapi.nat_get_timeouts()
Matus Fabian6a0946f2017-04-12 03:36:13 -07005495
Matus Fabian878c6462018-08-23 00:33:35 -07005496 self.vapi.nat_set_timeouts(timeouts_before.udp + 10,
5497 timeouts_before.tcp_established + 10,
5498 timeouts_before.tcp_transitory + 10,
5499 timeouts_before.icmp + 10)
Matus Fabian6a0946f2017-04-12 03:36:13 -07005500
Matus Fabian878c6462018-08-23 00:33:35 -07005501 timeouts_after = self.vapi.nat_get_timeouts()
Matus Fabian6a0946f2017-04-12 03:36:13 -07005502
5503 self.assertNotEqual(timeouts_before.udp, timeouts_after.udp)
5504 self.assertNotEqual(timeouts_before.icmp, timeouts_after.icmp)
5505 self.assertNotEqual(timeouts_before.tcp_established,
5506 timeouts_after.tcp_established)
5507 self.assertNotEqual(timeouts_before.tcp_transitory,
5508 timeouts_after.tcp_transitory)
5509
Martin Gálik977c1cb2017-03-30 23:21:51 -07005510 def test_det_in(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07005511 """ Deterministic NAT translation test (TCP, UDP, ICMP) """
Martin Gálik977c1cb2017-03-30 23:21:51 -07005512
5513 nat_ip = "10.0.0.10"
Martin Gálik977c1cb2017-03-30 23:21:51 -07005514
Matus Fabian2ba92e32017-08-21 07:05:03 -07005515 self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
5516 32,
5517 socket.inet_aton(nat_ip),
5518 32)
5519 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5520 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
5521 is_inside=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07005522
5523 # in2out
5524 pkts = self.create_stream_in(self.pg0, self.pg1)
5525 self.pg0.add_stream(pkts)
5526 self.pg_enable_capture(self.pg_interfaces)
5527 self.pg_start()
5528 capture = self.pg1.get_capture(len(pkts))
5529 self.verify_capture_out(capture, nat_ip)
5530
5531 # out2in
5532 pkts = self.create_stream_out(self.pg1, nat_ip)
5533 self.pg1.add_stream(pkts)
5534 self.pg_enable_capture(self.pg_interfaces)
5535 self.pg_start()
5536 capture = self.pg0.get_capture(len(pkts))
5537 self.verify_capture_in(capture, self.pg0)
5538
Martin Gálik9806eae2017-04-25 01:25:08 -07005539 # session dump test
Matus Fabian2ba92e32017-08-21 07:05:03 -07005540 sessions = self.vapi.nat_det_session_dump(self.pg0.remote_ip4n)
Martin Gálik9806eae2017-04-25 01:25:08 -07005541 self.assertEqual(len(sessions), 3)
5542
5543 # TCP session
5544 s = sessions[0]
5545 self.assertEqual(s.ext_addr[:4], self.pg1.remote_ip4n)
5546 self.assertEqual(s.in_port, self.tcp_port_in)
5547 self.assertEqual(s.out_port, self.tcp_port_out)
5548 self.assertEqual(s.ext_port, self.tcp_external_port)
5549
5550 # UDP session
5551 s = sessions[1]
5552 self.assertEqual(s.ext_addr[:4], self.pg1.remote_ip4n)
5553 self.assertEqual(s.in_port, self.udp_port_in)
5554 self.assertEqual(s.out_port, self.udp_port_out)
5555 self.assertEqual(s.ext_port, self.udp_external_port)
5556
5557 # ICMP session
5558 s = sessions[2]
5559 self.assertEqual(s.ext_addr[:4], self.pg1.remote_ip4n)
5560 self.assertEqual(s.in_port, self.icmp_id_in)
5561 self.assertEqual(s.out_port, self.icmp_external_id)
5562
Martin Gálik977c1cb2017-03-30 23:21:51 -07005563 def test_multiple_users(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07005564 """ Deterministic NAT multiple users """
Martin Gálik977c1cb2017-03-30 23:21:51 -07005565
5566 nat_ip = "10.0.0.10"
5567 port_in = 80
Martin Gálik9806eae2017-04-25 01:25:08 -07005568 external_port = 6303
Martin Gálik977c1cb2017-03-30 23:21:51 -07005569
5570 host0 = self.pg0.remote_hosts[0]
5571 host1 = self.pg0.remote_hosts[1]
5572
Matus Fabian2ba92e32017-08-21 07:05:03 -07005573 self.vapi.nat_det_add_del_map(host0.ip4n,
5574 24,
5575 socket.inet_aton(nat_ip),
5576 32)
5577 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5578 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
5579 is_inside=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07005580
5581 # host0 to out
5582 p = (Ether(src=host0.mac, dst=self.pg0.local_mac) /
5583 IP(src=host0.ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07005584 TCP(sport=port_in, dport=external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07005585 self.pg0.add_stream(p)
5586 self.pg_enable_capture(self.pg_interfaces)
5587 self.pg_start()
5588 capture = self.pg1.get_capture(1)
5589 p = capture[0]
5590 try:
5591 ip = p[IP]
5592 tcp = p[TCP]
5593 self.assertEqual(ip.src, nat_ip)
5594 self.assertEqual(ip.dst, self.pg1.remote_ip4)
Martin Gálik9806eae2017-04-25 01:25:08 -07005595 self.assertEqual(tcp.dport, external_port)
5596 port_out0 = tcp.sport
Martin Gálik977c1cb2017-03-30 23:21:51 -07005597 except:
5598 self.logger.error(ppp("Unexpected or invalid packet:", p))
5599 raise
5600
5601 # host1 to out
5602 p = (Ether(src=host1.mac, dst=self.pg0.local_mac) /
5603 IP(src=host1.ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07005604 TCP(sport=port_in, dport=external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07005605 self.pg0.add_stream(p)
5606 self.pg_enable_capture(self.pg_interfaces)
5607 self.pg_start()
5608 capture = self.pg1.get_capture(1)
5609 p = capture[0]
5610 try:
5611 ip = p[IP]
5612 tcp = p[TCP]
5613 self.assertEqual(ip.src, nat_ip)
5614 self.assertEqual(ip.dst, self.pg1.remote_ip4)
Martin Gálik9806eae2017-04-25 01:25:08 -07005615 self.assertEqual(tcp.dport, external_port)
5616 port_out1 = tcp.sport
Martin Gálik977c1cb2017-03-30 23:21:51 -07005617 except:
5618 self.logger.error(ppp("Unexpected or invalid packet:", p))
5619 raise
5620
Matus Fabian2ba92e32017-08-21 07:05:03 -07005621 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07005622 self.assertEqual(1, len(dms))
5623 self.assertEqual(2, dms[0].ses_num)
5624
5625 # out to host0
5626 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5627 IP(src=self.pg1.remote_ip4, dst=nat_ip) /
Martin Gálik9806eae2017-04-25 01:25:08 -07005628 TCP(sport=external_port, dport=port_out0))
Martin Gálik977c1cb2017-03-30 23:21:51 -07005629 self.pg1.add_stream(p)
5630 self.pg_enable_capture(self.pg_interfaces)
5631 self.pg_start()
5632 capture = self.pg0.get_capture(1)
5633 p = capture[0]
5634 try:
5635 ip = p[IP]
5636 tcp = p[TCP]
5637 self.assertEqual(ip.src, self.pg1.remote_ip4)
5638 self.assertEqual(ip.dst, host0.ip4)
5639 self.assertEqual(tcp.dport, port_in)
Martin Gálik9806eae2017-04-25 01:25:08 -07005640 self.assertEqual(tcp.sport, external_port)
Martin Gálik977c1cb2017-03-30 23:21:51 -07005641 except:
5642 self.logger.error(ppp("Unexpected or invalid packet:", p))
5643 raise
5644
5645 # out to host1
5646 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5647 IP(src=self.pg1.remote_ip4, dst=nat_ip) /
Martin Gálik9806eae2017-04-25 01:25:08 -07005648 TCP(sport=external_port, dport=port_out1))
Martin Gálik977c1cb2017-03-30 23:21:51 -07005649 self.pg1.add_stream(p)
5650 self.pg_enable_capture(self.pg_interfaces)
5651 self.pg_start()
5652 capture = self.pg0.get_capture(1)
5653 p = capture[0]
5654 try:
5655 ip = p[IP]
5656 tcp = p[TCP]
5657 self.assertEqual(ip.src, self.pg1.remote_ip4)
5658 self.assertEqual(ip.dst, host1.ip4)
5659 self.assertEqual(tcp.dport, port_in)
Martin Gálik9806eae2017-04-25 01:25:08 -07005660 self.assertEqual(tcp.sport, external_port)
Martin Gálik977c1cb2017-03-30 23:21:51 -07005661 except:
5662 self.logger.error(ppp("Unexpected or invalid packet", p))
5663 raise
5664
Martin Gálik6bc8c642017-04-19 01:12:27 -07005665 # session close api test
Matus Fabian2ba92e32017-08-21 07:05:03 -07005666 self.vapi.nat_det_close_session_out(socket.inet_aton(nat_ip),
5667 port_out1,
Martin Gálik6bc8c642017-04-19 01:12:27 -07005668 self.pg1.remote_ip4n,
Martin Gálik9806eae2017-04-25 01:25:08 -07005669 external_port)
Matus Fabian2ba92e32017-08-21 07:05:03 -07005670 dms = self.vapi.nat_det_map_dump()
5671 self.assertEqual(dms[0].ses_num, 1)
5672
5673 self.vapi.nat_det_close_session_in(host0.ip4n,
5674 port_in,
5675 self.pg1.remote_ip4n,
5676 external_port)
5677 dms = self.vapi.nat_det_map_dump()
Martin Gálik6bc8c642017-04-19 01:12:27 -07005678 self.assertEqual(dms[0].ses_num, 0)
5679
Martin Gálik977c1cb2017-03-30 23:21:51 -07005680 def test_tcp_session_close_detection_in(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07005681 """ Deterministic NAT TCP session close from inside network """
5682 self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
5683 32,
5684 socket.inet_aton(self.nat_addr),
5685 32)
5686 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5687 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
5688 is_inside=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07005689
5690 self.initiate_tcp_session(self.pg0, self.pg1)
5691
5692 # close the session from inside
5693 try:
5694 # FIN packet in -> out
5695 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5696 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07005697 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
Martin Gálik977c1cb2017-03-30 23:21:51 -07005698 flags="F"))
5699 self.pg0.add_stream(p)
5700 self.pg_enable_capture(self.pg_interfaces)
5701 self.pg_start()
5702 self.pg1.get_capture(1)
5703
5704 pkts = []
5705
5706 # ACK packet out -> in
5707 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07005708 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Martin Gálik9806eae2017-04-25 01:25:08 -07005709 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
Martin Gálik977c1cb2017-03-30 23:21:51 -07005710 flags="A"))
5711 pkts.append(p)
5712
5713 # FIN packet out -> in
5714 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07005715 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Martin Gálik9806eae2017-04-25 01:25:08 -07005716 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
Martin Gálik977c1cb2017-03-30 23:21:51 -07005717 flags="F"))
5718 pkts.append(p)
5719
5720 self.pg1.add_stream(pkts)
5721 self.pg_enable_capture(self.pg_interfaces)
5722 self.pg_start()
5723 self.pg0.get_capture(2)
5724
5725 # ACK packet in -> out
5726 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5727 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07005728 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
Martin Gálik977c1cb2017-03-30 23:21:51 -07005729 flags="A"))
5730 self.pg0.add_stream(p)
5731 self.pg_enable_capture(self.pg_interfaces)
5732 self.pg_start()
5733 self.pg1.get_capture(1)
5734
Matus Fabian2ba92e32017-08-21 07:05:03 -07005735 # Check if deterministic NAT44 closed the session
5736 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07005737 self.assertEqual(0, dms[0].ses_num)
5738 except:
5739 self.logger.error("TCP session termination failed")
5740 raise
5741
5742 def test_tcp_session_close_detection_out(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07005743 """ Deterministic NAT TCP session close from outside network """
5744 self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
5745 32,
5746 socket.inet_aton(self.nat_addr),
5747 32)
5748 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5749 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
5750 is_inside=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07005751
5752 self.initiate_tcp_session(self.pg0, self.pg1)
5753
5754 # close the session from outside
5755 try:
5756 # FIN packet out -> in
5757 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07005758 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Martin Gálik9806eae2017-04-25 01:25:08 -07005759 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
Martin Gálik977c1cb2017-03-30 23:21:51 -07005760 flags="F"))
5761 self.pg1.add_stream(p)
5762 self.pg_enable_capture(self.pg_interfaces)
5763 self.pg_start()
5764 self.pg0.get_capture(1)
5765
5766 pkts = []
5767
5768 # ACK packet in -> out
5769 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5770 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07005771 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
Martin Gálik977c1cb2017-03-30 23:21:51 -07005772 flags="A"))
5773 pkts.append(p)
5774
5775 # ACK packet in -> out
5776 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5777 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07005778 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
Martin Gálik977c1cb2017-03-30 23:21:51 -07005779 flags="F"))
5780 pkts.append(p)
5781
5782 self.pg0.add_stream(pkts)
5783 self.pg_enable_capture(self.pg_interfaces)
5784 self.pg_start()
5785 self.pg1.get_capture(2)
5786
5787 # ACK packet out -> in
5788 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07005789 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Martin Gálik9806eae2017-04-25 01:25:08 -07005790 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
Martin Gálik977c1cb2017-03-30 23:21:51 -07005791 flags="A"))
5792 self.pg1.add_stream(p)
5793 self.pg_enable_capture(self.pg_interfaces)
5794 self.pg_start()
5795 self.pg0.get_capture(1)
5796
Matus Fabian2ba92e32017-08-21 07:05:03 -07005797 # Check if deterministic NAT44 closed the session
5798 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07005799 self.assertEqual(0, dms[0].ses_num)
5800 except:
5801 self.logger.error("TCP session termination failed")
5802 raise
5803
5804 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
5805 def test_session_timeout(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07005806 """ Deterministic NAT session timeouts """
5807 self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
5808 32,
5809 socket.inet_aton(self.nat_addr),
5810 32)
5811 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5812 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
5813 is_inside=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07005814
5815 self.initiate_tcp_session(self.pg0, self.pg1)
Matus Fabian878c6462018-08-23 00:33:35 -07005816 self.vapi.nat_set_timeouts(5, 5, 5, 5)
Martin Gálik977c1cb2017-03-30 23:21:51 -07005817 pkts = self.create_stream_in(self.pg0, self.pg1)
5818 self.pg0.add_stream(pkts)
5819 self.pg_enable_capture(self.pg_interfaces)
5820 self.pg_start()
5821 capture = self.pg1.get_capture(len(pkts))
5822 sleep(15)
5823
Matus Fabian2ba92e32017-08-21 07:05:03 -07005824 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07005825 self.assertEqual(0, dms[0].ses_num)
5826
Matus Fabian7c0aecc2017-07-03 01:21:38 -07005827 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
Martin Gálik977c1cb2017-03-30 23:21:51 -07005828 def test_session_limit_per_user(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07005829 """ Deterministic NAT maximum sessions per user limit """
5830 self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
5831 32,
5832 socket.inet_aton(self.nat_addr),
5833 32)
5834 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5835 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
5836 is_inside=0)
Matus Fabian2f2db1c2017-04-18 05:29:59 -07005837 self.vapi.set_ipfix_exporter(collector_address=self.pg2.remote_ip4n,
5838 src_address=self.pg2.local_ip4n,
5839 path_mtu=512,
5840 template_interval=10)
Matus Fabian2ba92e32017-08-21 07:05:03 -07005841 self.vapi.nat_ipfix()
Martin Gálik977c1cb2017-03-30 23:21:51 -07005842
5843 pkts = []
5844 for port in range(1025, 2025):
5845 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5846 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5847 UDP(sport=port, dport=port))
5848 pkts.append(p)
5849
5850 self.pg0.add_stream(pkts)
5851 self.pg_enable_capture(self.pg_interfaces)
5852 self.pg_start()
5853 capture = self.pg1.get_capture(len(pkts))
5854
5855 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5856 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálikf7e655d2017-04-27 02:13:26 -07005857 UDP(sport=3001, dport=3002))
Martin Gálik977c1cb2017-03-30 23:21:51 -07005858 self.pg0.add_stream(p)
5859 self.pg_enable_capture(self.pg_interfaces)
5860 self.pg_start()
5861 capture = self.pg1.assert_nothing_captured()
5862
Martin Gálikf7e655d2017-04-27 02:13:26 -07005863 # verify ICMP error packet
5864 capture = self.pg0.get_capture(1)
5865 p = capture[0]
5866 self.assertTrue(p.haslayer(ICMP))
5867 icmp = p[ICMP]
5868 self.assertEqual(icmp.type, 3)
5869 self.assertEqual(icmp.code, 1)
5870 self.assertTrue(icmp.haslayer(IPerror))
5871 inner_ip = icmp[IPerror]
5872 self.assertEqual(inner_ip[UDPerror].sport, 3001)
5873 self.assertEqual(inner_ip[UDPerror].dport, 3002)
5874
Matus Fabian2ba92e32017-08-21 07:05:03 -07005875 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07005876
5877 self.assertEqual(1000, dms[0].ses_num)
5878
Matus Fabian2f2db1c2017-04-18 05:29:59 -07005879 # verify IPFIX logging
5880 self.vapi.cli("ipfix flush") # FIXME this should be an API call
Matus Fabian7c0aecc2017-07-03 01:21:38 -07005881 sleep(1)
Matus Fabian2f2db1c2017-04-18 05:29:59 -07005882 capture = self.pg2.get_capture(2)
5883 ipfix = IPFIXDecoder()
5884 # first load template
5885 for p in capture:
5886 self.assertTrue(p.haslayer(IPFIX))
5887 if p.haslayer(Template):
5888 ipfix.add_template(p.getlayer(Template))
5889 # verify events in data set
5890 for p in capture:
5891 if p.haslayer(Data):
5892 data = ipfix.decode_data_set(p.getlayer(Set))
Matus Fabian878c6462018-08-23 00:33:35 -07005893 self.verify_ipfix_max_entries_per_user(data,
5894 1000,
5895 self.pg0.remote_ip4n)
Matus Fabian2f2db1c2017-04-18 05:29:59 -07005896
Matus Fabian2ba92e32017-08-21 07:05:03 -07005897 def clear_nat_det(self):
Martin17a75cb2017-03-08 05:53:20 -08005898 """
Matus Fabian2ba92e32017-08-21 07:05:03 -07005899 Clear deterministic NAT configuration.
Martin17a75cb2017-03-08 05:53:20 -08005900 """
Matus Fabian2ba92e32017-08-21 07:05:03 -07005901 self.vapi.nat_ipfix(enable=0)
Matus Fabian878c6462018-08-23 00:33:35 -07005902 self.vapi.nat_set_timeouts()
Matus Fabian2ba92e32017-08-21 07:05:03 -07005903 deterministic_mappings = self.vapi.nat_det_map_dump()
Martin17a75cb2017-03-08 05:53:20 -08005904 for dsm in deterministic_mappings:
Matus Fabian2ba92e32017-08-21 07:05:03 -07005905 self.vapi.nat_det_add_del_map(dsm.in_addr,
5906 dsm.in_plen,
5907 dsm.out_addr,
5908 dsm.out_plen,
5909 is_add=0)
Martin17a75cb2017-03-08 05:53:20 -08005910
Matus Fabian2ba92e32017-08-21 07:05:03 -07005911 interfaces = self.vapi.nat44_interface_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07005912 for intf in interfaces:
Matus Fabian2ba92e32017-08-21 07:05:03 -07005913 self.vapi.nat44_interface_add_del_feature(intf.sw_if_index,
5914 intf.is_inside,
5915 is_add=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07005916
Matus Fabian066f0342017-02-10 03:48:01 -08005917 def tearDown(self):
5918 super(TestDeterministicNAT, self).tearDown()
5919 if not self.vpp_dead:
Matus Fabian82119542018-01-25 01:13:22 -08005920 self.logger.info(self.vapi.cli("show nat44 interfaces"))
Matus Fabian878c6462018-08-23 00:33:35 -07005921 self.logger.info(self.vapi.cli("show nat timeouts"))
Matus Fabian82119542018-01-25 01:13:22 -08005922 self.logger.info(
5923 self.vapi.cli("show nat44 deterministic mappings"))
5924 self.logger.info(
Matus Fabian82119542018-01-25 01:13:22 -08005925 self.vapi.cli("show nat44 deterministic sessions"))
Matus Fabian2ba92e32017-08-21 07:05:03 -07005926 self.clear_nat_det()
Matus Fabian066f0342017-02-10 03:48:01 -08005927
Matus Fabian06596c52017-06-06 04:53:28 -07005928
5929class TestNAT64(MethodHolder):
5930 """ NAT64 Test Cases """
5931
5932 @classmethod
Matus Fabiana431ad12018-01-04 04:03:14 -08005933 def setUpConstants(cls):
5934 super(TestNAT64, cls).setUpConstants()
5935 cls.vpp_cmdline.extend(["nat", "{", "nat64 bib hash buckets 128",
5936 "nat64 st hash buckets 256", "}"])
5937
5938 @classmethod
Matus Fabian06596c52017-06-06 04:53:28 -07005939 def setUpClass(cls):
5940 super(TestNAT64, cls).setUpClass()
5941
5942 try:
5943 cls.tcp_port_in = 6303
5944 cls.tcp_port_out = 6303
5945 cls.udp_port_in = 6304
5946 cls.udp_port_out = 6304
5947 cls.icmp_id_in = 6305
5948 cls.icmp_id_out = 6305
5949 cls.nat_addr = '10.0.0.3'
5950 cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
Matus Fabian029f3d22017-06-15 02:28:50 -07005951 cls.vrf1_id = 10
5952 cls.vrf1_nat_addr = '10.0.10.3'
5953 cls.vrf1_nat_addr_n = socket.inet_pton(socket.AF_INET,
5954 cls.vrf1_nat_addr)
Matus Fabiana431ad12018-01-04 04:03:14 -08005955 cls.ipfix_src_port = 4739
5956 cls.ipfix_domain_id = 1
Matus Fabian06596c52017-06-06 04:53:28 -07005957
Juraj Slobodac746a152018-07-09 02:36:37 +02005958 cls.create_pg_interfaces(range(6))
Matus Fabian06596c52017-06-06 04:53:28 -07005959 cls.ip6_interfaces = list(cls.pg_interfaces[0:1])
Matus Fabian029f3d22017-06-15 02:28:50 -07005960 cls.ip6_interfaces.append(cls.pg_interfaces[2])
Matus Fabian06596c52017-06-06 04:53:28 -07005961 cls.ip4_interfaces = list(cls.pg_interfaces[1:2])
5962
Neale Ranns15002542017-09-10 04:39:11 -07005963 cls.vapi.ip_table_add_del(cls.vrf1_id, is_add=1, is_ipv6=1)
5964
Matus Fabian029f3d22017-06-15 02:28:50 -07005965 cls.pg_interfaces[2].set_table_ip6(cls.vrf1_id)
5966
5967 cls.pg0.generate_remote_hosts(2)
5968
Matus Fabian06596c52017-06-06 04:53:28 -07005969 for i in cls.ip6_interfaces:
5970 i.admin_up()
5971 i.config_ip6()
Matus Fabian029f3d22017-06-15 02:28:50 -07005972 i.configure_ipv6_neighbors()
Matus Fabian06596c52017-06-06 04:53:28 -07005973
5974 for i in cls.ip4_interfaces:
5975 i.admin_up()
5976 i.config_ip4()
5977 i.resolve_arp()
5978
Matus Fabian36ea2d62017-10-24 04:13:49 -07005979 cls.pg3.admin_up()
5980 cls.pg3.config_ip4()
5981 cls.pg3.resolve_arp()
5982 cls.pg3.config_ip6()
5983 cls.pg3.configure_ipv6_neighbors()
5984
Juraj Slobodac746a152018-07-09 02:36:37 +02005985 cls.pg5.admin_up()
5986 cls.pg5.config_ip6()
5987
Matus Fabian06596c52017-06-06 04:53:28 -07005988 except Exception:
5989 super(TestNAT64, cls).tearDownClass()
5990 raise
5991
Juraj Slobodac746a152018-07-09 02:36:37 +02005992 def test_nat64_inside_interface_handles_neighbor_advertisement(self):
5993 """ NAT64 inside interface handles Neighbor Advertisement """
5994
5995 self.vapi.nat64_add_del_interface(self.pg5.sw_if_index)
5996
5997 # Try to send ping
5998 ping = (Ether(dst=self.pg5.local_mac, src=self.pg5.remote_mac) /
5999 IPv6(src=self.pg5.remote_ip6, dst=self.pg5.local_ip6) /
6000 ICMPv6EchoRequest())
6001 pkts = [ping]
6002 self.pg5.add_stream(pkts)
6003 self.pg_enable_capture(self.pg_interfaces)
6004 self.pg_start()
6005
6006 # Wait for Neighbor Solicitation
6007 capture = self.pg5.get_capture(len(pkts))
Juraj Slobodac746a152018-07-09 02:36:37 +02006008 packet = capture[0]
6009 try:
6010 self.assertEqual(packet[IPv6].src, self.pg5.local_ip6)
6011 self.assertTrue(packet.haslayer(ICMPv6ND_NS))
6012 tgt = packet[ICMPv6ND_NS].tgt
6013 except:
6014 self.logger.error(ppp("Unexpected or invalid packet:", packet))
6015 raise
6016
6017 # Send Neighbor Advertisement
6018 p = (Ether(dst=self.pg5.local_mac, src=self.pg5.remote_mac) /
6019 IPv6(src=self.pg5.remote_ip6, dst=self.pg5.local_ip6) /
6020 ICMPv6ND_NA(tgt=tgt) /
6021 ICMPv6NDOptDstLLAddr(lladdr=self.pg5.remote_mac))
6022 pkts = [p]
6023 self.pg5.add_stream(pkts)
6024 self.pg_enable_capture(self.pg_interfaces)
6025 self.pg_start()
6026
6027 # Try to send ping again
6028 pkts = [ping]
6029 self.pg5.add_stream(pkts)
6030 self.pg_enable_capture(self.pg_interfaces)
6031 self.pg_start()
6032
6033 # Wait for ping reply
6034 capture = self.pg5.get_capture(len(pkts))
Juraj Slobodac746a152018-07-09 02:36:37 +02006035 packet = capture[0]
6036 try:
6037 self.assertEqual(packet[IPv6].src, self.pg5.local_ip6)
6038 self.assertEqual(packet[IPv6].dst, self.pg5.remote_ip6)
6039 self.assertTrue(packet.haslayer(ICMPv6EchoReply))
6040 except:
6041 self.logger.error(ppp("Unexpected or invalid packet:", packet))
6042 raise
6043
Matus Fabian06596c52017-06-06 04:53:28 -07006044 def test_pool(self):
6045 """ Add/delete address to NAT64 pool """
6046 nat_addr = socket.inet_pton(socket.AF_INET, '1.2.3.4')
6047
6048 self.vapi.nat64_add_del_pool_addr_range(nat_addr, nat_addr)
6049
6050 addresses = self.vapi.nat64_pool_addr_dump()
6051 self.assertEqual(len(addresses), 1)
6052 self.assertEqual(addresses[0].address, nat_addr)
6053
6054 self.vapi.nat64_add_del_pool_addr_range(nat_addr, nat_addr, is_add=0)
6055
6056 addresses = self.vapi.nat64_pool_addr_dump()
6057 self.assertEqual(len(addresses), 0)
6058
6059 def test_interface(self):
6060 """ Enable/disable NAT64 feature on the interface """
6061 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6062 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6063
6064 interfaces = self.vapi.nat64_interface_dump()
6065 self.assertEqual(len(interfaces), 2)
6066 pg0_found = False
6067 pg1_found = False
6068 for intf in interfaces:
6069 if intf.sw_if_index == self.pg0.sw_if_index:
6070 self.assertEqual(intf.is_inside, 1)
6071 pg0_found = True
6072 elif intf.sw_if_index == self.pg1.sw_if_index:
6073 self.assertEqual(intf.is_inside, 0)
6074 pg1_found = True
6075 self.assertTrue(pg0_found)
6076 self.assertTrue(pg1_found)
6077
6078 features = self.vapi.cli("show interface features pg0")
6079 self.assertNotEqual(features.find('nat64-in2out'), -1)
6080 features = self.vapi.cli("show interface features pg1")
6081 self.assertNotEqual(features.find('nat64-out2in'), -1)
6082
6083 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index, is_add=0)
6084 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_add=0)
6085
6086 interfaces = self.vapi.nat64_interface_dump()
6087 self.assertEqual(len(interfaces), 0)
6088
6089 def test_static_bib(self):
6090 """ Add/delete static BIB entry """
6091 in_addr = socket.inet_pton(socket.AF_INET6,
6092 '2001:db8:85a3::8a2e:370:7334')
6093 out_addr = socket.inet_pton(socket.AF_INET, '10.1.1.3')
6094 in_port = 1234
6095 out_port = 5678
6096 proto = IP_PROTOS.tcp
6097
6098 self.vapi.nat64_add_del_static_bib(in_addr,
6099 out_addr,
6100 in_port,
6101 out_port,
6102 proto)
6103 bib = self.vapi.nat64_bib_dump(IP_PROTOS.tcp)
6104 static_bib_num = 0
6105 for bibe in bib:
6106 if bibe.is_static:
6107 static_bib_num += 1
6108 self.assertEqual(bibe.i_addr, in_addr)
6109 self.assertEqual(bibe.o_addr, out_addr)
6110 self.assertEqual(bibe.i_port, in_port)
6111 self.assertEqual(bibe.o_port, out_port)
6112 self.assertEqual(static_bib_num, 1)
6113
6114 self.vapi.nat64_add_del_static_bib(in_addr,
6115 out_addr,
6116 in_port,
6117 out_port,
6118 proto,
6119 is_add=0)
6120 bib = self.vapi.nat64_bib_dump(IP_PROTOS.tcp)
6121 static_bib_num = 0
6122 for bibe in bib:
6123 if bibe.is_static:
6124 static_bib_num += 1
6125 self.assertEqual(static_bib_num, 0)
6126
6127 def test_set_timeouts(self):
6128 """ Set NAT64 timeouts """
6129 # verify default values
Matus Fabian878c6462018-08-23 00:33:35 -07006130 timeouts = self.vapi.nat_get_timeouts()
Matus Fabian06596c52017-06-06 04:53:28 -07006131 self.assertEqual(timeouts.udp, 300)
6132 self.assertEqual(timeouts.icmp, 60)
Matus Fabian878c6462018-08-23 00:33:35 -07006133 self.assertEqual(timeouts.tcp_transitory, 240)
6134 self.assertEqual(timeouts.tcp_established, 7440)
Matus Fabian06596c52017-06-06 04:53:28 -07006135
6136 # set and verify custom values
Matus Fabian878c6462018-08-23 00:33:35 -07006137 self.vapi.nat_set_timeouts(udp=200, icmp=30, tcp_transitory=250,
6138 tcp_established=7450)
6139 timeouts = self.vapi.nat_get_timeouts()
Matus Fabian06596c52017-06-06 04:53:28 -07006140 self.assertEqual(timeouts.udp, 200)
6141 self.assertEqual(timeouts.icmp, 30)
Matus Fabian878c6462018-08-23 00:33:35 -07006142 self.assertEqual(timeouts.tcp_transitory, 250)
6143 self.assertEqual(timeouts.tcp_established, 7450)
Matus Fabian06596c52017-06-06 04:53:28 -07006144
6145 def test_dynamic(self):
6146 """ NAT64 dynamic translation test """
6147 self.tcp_port_in = 6303
6148 self.udp_port_in = 6304
6149 self.icmp_id_in = 6305
6150
6151 ses_num_start = self.nat64_get_ses_num()
6152
6153 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6154 self.nat_addr_n)
6155 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6156 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6157
6158 # in2out
6159 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
6160 self.pg0.add_stream(pkts)
6161 self.pg_enable_capture(self.pg_interfaces)
6162 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07006163 capture = self.pg1.get_capture(len(pkts))
6164 self.verify_capture_out(capture, nat_ip=self.nat_addr,
Matus Fabian06596c52017-06-06 04:53:28 -07006165 dst_ip=self.pg1.remote_ip4)
6166
6167 # out2in
6168 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
6169 self.pg1.add_stream(pkts)
6170 self.pg_enable_capture(self.pg_interfaces)
6171 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07006172 capture = self.pg0.get_capture(len(pkts))
Matus Fabian06596c52017-06-06 04:53:28 -07006173 ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
6174 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
6175
6176 # in2out
6177 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
6178 self.pg0.add_stream(pkts)
6179 self.pg_enable_capture(self.pg_interfaces)
6180 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07006181 capture = self.pg1.get_capture(len(pkts))
6182 self.verify_capture_out(capture, nat_ip=self.nat_addr,
Matus Fabian06596c52017-06-06 04:53:28 -07006183 dst_ip=self.pg1.remote_ip4)
6184
6185 # out2in
6186 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
6187 self.pg1.add_stream(pkts)
6188 self.pg_enable_capture(self.pg_interfaces)
6189 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07006190 capture = self.pg0.get_capture(len(pkts))
Matus Fabian06596c52017-06-06 04:53:28 -07006191 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
6192
6193 ses_num_end = self.nat64_get_ses_num()
6194
6195 self.assertEqual(ses_num_end - ses_num_start, 3)
6196
Matus Fabian029f3d22017-06-15 02:28:50 -07006197 # tenant with specific VRF
6198 self.vapi.nat64_add_del_pool_addr_range(self.vrf1_nat_addr_n,
6199 self.vrf1_nat_addr_n,
6200 vrf_id=self.vrf1_id)
6201 self.vapi.nat64_add_del_interface(self.pg2.sw_if_index)
6202
6203 pkts = self.create_stream_in_ip6(self.pg2, self.pg1)
6204 self.pg2.add_stream(pkts)
6205 self.pg_enable_capture(self.pg_interfaces)
6206 self.pg_start()
6207 capture = self.pg1.get_capture(len(pkts))
6208 self.verify_capture_out(capture, nat_ip=self.vrf1_nat_addr,
6209 dst_ip=self.pg1.remote_ip4)
6210
6211 pkts = self.create_stream_out(self.pg1, dst_ip=self.vrf1_nat_addr)
6212 self.pg1.add_stream(pkts)
6213 self.pg_enable_capture(self.pg_interfaces)
6214 self.pg_start()
6215 capture = self.pg2.get_capture(len(pkts))
6216 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg2.remote_ip6)
6217
Matus Fabian06596c52017-06-06 04:53:28 -07006218 def test_static(self):
6219 """ NAT64 static translation test """
6220 self.tcp_port_in = 60303
6221 self.udp_port_in = 60304
6222 self.icmp_id_in = 60305
6223 self.tcp_port_out = 60303
6224 self.udp_port_out = 60304
6225 self.icmp_id_out = 60305
6226
6227 ses_num_start = self.nat64_get_ses_num()
6228
6229 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6230 self.nat_addr_n)
6231 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6232 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6233
6234 self.vapi.nat64_add_del_static_bib(self.pg0.remote_ip6n,
6235 self.nat_addr_n,
6236 self.tcp_port_in,
6237 self.tcp_port_out,
6238 IP_PROTOS.tcp)
6239 self.vapi.nat64_add_del_static_bib(self.pg0.remote_ip6n,
6240 self.nat_addr_n,
6241 self.udp_port_in,
6242 self.udp_port_out,
6243 IP_PROTOS.udp)
6244 self.vapi.nat64_add_del_static_bib(self.pg0.remote_ip6n,
6245 self.nat_addr_n,
6246 self.icmp_id_in,
6247 self.icmp_id_out,
6248 IP_PROTOS.icmp)
6249
6250 # in2out
6251 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
6252 self.pg0.add_stream(pkts)
6253 self.pg_enable_capture(self.pg_interfaces)
6254 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07006255 capture = self.pg1.get_capture(len(pkts))
6256 self.verify_capture_out(capture, nat_ip=self.nat_addr,
Matus Fabian06596c52017-06-06 04:53:28 -07006257 dst_ip=self.pg1.remote_ip4, same_port=True)
6258
6259 # out2in
6260 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
6261 self.pg1.add_stream(pkts)
6262 self.pg_enable_capture(self.pg_interfaces)
6263 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07006264 capture = self.pg0.get_capture(len(pkts))
Matus Fabian06596c52017-06-06 04:53:28 -07006265 ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
6266 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
6267
6268 ses_num_end = self.nat64_get_ses_num()
6269
6270 self.assertEqual(ses_num_end - ses_num_start, 3)
6271
6272 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
6273 def test_session_timeout(self):
6274 """ NAT64 session timeout """
6275 self.icmp_id_in = 1234
6276 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6277 self.nat_addr_n)
6278 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6279 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
Matus Fabian878c6462018-08-23 00:33:35 -07006280 self.vapi.nat_set_timeouts(icmp=5, tcp_transitory=5, tcp_established=5)
Matus Fabian06596c52017-06-06 04:53:28 -07006281
6282 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
6283 self.pg0.add_stream(pkts)
6284 self.pg_enable_capture(self.pg_interfaces)
6285 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07006286 capture = self.pg1.get_capture(len(pkts))
Matus Fabian06596c52017-06-06 04:53:28 -07006287
6288 ses_num_before_timeout = self.nat64_get_ses_num()
6289
6290 sleep(15)
6291
Matus Fabian8fed4242018-08-14 05:14:55 -07006292 # ICMP and TCP session after timeout
Matus Fabian06596c52017-06-06 04:53:28 -07006293 ses_num_after_timeout = self.nat64_get_ses_num()
Matus Fabian8fed4242018-08-14 05:14:55 -07006294 self.assertEqual(ses_num_before_timeout - ses_num_after_timeout, 2)
Matus Fabian06596c52017-06-06 04:53:28 -07006295
Matus Fabian732036d2017-06-08 05:24:28 -07006296 def test_icmp_error(self):
6297 """ NAT64 ICMP Error message translation """
6298 self.tcp_port_in = 6303
6299 self.udp_port_in = 6304
6300 self.icmp_id_in = 6305
6301
Matus Fabian732036d2017-06-08 05:24:28 -07006302 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6303 self.nat_addr_n)
6304 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6305 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6306
6307 # send some packets to create sessions
6308 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
6309 self.pg0.add_stream(pkts)
6310 self.pg_enable_capture(self.pg_interfaces)
6311 self.pg_start()
6312 capture_ip4 = self.pg1.get_capture(len(pkts))
Matus Fabian029f3d22017-06-15 02:28:50 -07006313 self.verify_capture_out(capture_ip4,
Matus Fabian732036d2017-06-08 05:24:28 -07006314 nat_ip=self.nat_addr,
6315 dst_ip=self.pg1.remote_ip4)
6316
6317 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
6318 self.pg1.add_stream(pkts)
6319 self.pg_enable_capture(self.pg_interfaces)
6320 self.pg_start()
6321 capture_ip6 = self.pg0.get_capture(len(pkts))
6322 ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
6323 self.verify_capture_in_ip6(capture_ip6, ip[IPv6].src,
6324 self.pg0.remote_ip6)
6325
6326 # in2out
6327 pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6328 IPv6(src=self.pg0.remote_ip6, dst=ip[IPv6].src) /
6329 ICMPv6DestUnreach(code=1) /
6330 packet[IPv6] for packet in capture_ip6]
6331 self.pg0.add_stream(pkts)
6332 self.pg_enable_capture(self.pg_interfaces)
6333 self.pg_start()
6334 capture = self.pg1.get_capture(len(pkts))
6335 for packet in capture:
6336 try:
6337 self.assertEqual(packet[IP].src, self.nat_addr)
6338 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
6339 self.assertEqual(packet[ICMP].type, 3)
6340 self.assertEqual(packet[ICMP].code, 13)
6341 inner = packet[IPerror]
6342 self.assertEqual(inner.src, self.pg1.remote_ip4)
6343 self.assertEqual(inner.dst, self.nat_addr)
Klement Sekerad81ae412018-05-16 10:52:54 +02006344 self.assert_packet_checksums_valid(packet)
Matus Fabian732036d2017-06-08 05:24:28 -07006345 if inner.haslayer(TCPerror):
6346 self.assertEqual(inner[TCPerror].dport, self.tcp_port_out)
6347 elif inner.haslayer(UDPerror):
6348 self.assertEqual(inner[UDPerror].dport, self.udp_port_out)
6349 else:
6350 self.assertEqual(inner[ICMPerror].id, self.icmp_id_out)
6351 except:
6352 self.logger.error(ppp("Unexpected or invalid packet:", packet))
6353 raise
6354
6355 # out2in
6356 pkts = [Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
6357 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6358 ICMP(type=3, code=13) /
6359 packet[IP] for packet in capture_ip4]
6360 self.pg1.add_stream(pkts)
6361 self.pg_enable_capture(self.pg_interfaces)
6362 self.pg_start()
6363 capture = self.pg0.get_capture(len(pkts))
6364 for packet in capture:
6365 try:
6366 self.assertEqual(packet[IPv6].src, ip.src)
6367 self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
6368 icmp = packet[ICMPv6DestUnreach]
6369 self.assertEqual(icmp.code, 1)
6370 inner = icmp[IPerror6]
6371 self.assertEqual(inner.src, self.pg0.remote_ip6)
6372 self.assertEqual(inner.dst, ip.src)
Klement Sekerad81ae412018-05-16 10:52:54 +02006373 self.assert_icmpv6_checksum_valid(packet)
Matus Fabian732036d2017-06-08 05:24:28 -07006374 if inner.haslayer(TCPerror):
6375 self.assertEqual(inner[TCPerror].sport, self.tcp_port_in)
6376 elif inner.haslayer(UDPerror):
6377 self.assertEqual(inner[UDPerror].sport, self.udp_port_in)
6378 else:
6379 self.assertEqual(inner[ICMPv6EchoRequest].id,
6380 self.icmp_id_in)
6381 except:
6382 self.logger.error(ppp("Unexpected or invalid packet:", packet))
6383 raise
6384
Matus Fabian029f3d22017-06-15 02:28:50 -07006385 def test_hairpinning(self):
6386 """ NAT64 hairpinning """
6387
6388 client = self.pg0.remote_hosts[0]
6389 server = self.pg0.remote_hosts[1]
6390 server_tcp_in_port = 22
6391 server_tcp_out_port = 4022
6392 server_udp_in_port = 23
6393 server_udp_out_port = 4023
6394 client_tcp_in_port = 1234
6395 client_udp_in_port = 1235
6396 client_tcp_out_port = 0
6397 client_udp_out_port = 0
6398 ip = IPv6(src=''.join(['64:ff9b::', self.nat_addr]))
6399 nat_addr_ip6 = ip.src
6400
6401 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6402 self.nat_addr_n)
6403 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6404 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6405
6406 self.vapi.nat64_add_del_static_bib(server.ip6n,
6407 self.nat_addr_n,
6408 server_tcp_in_port,
6409 server_tcp_out_port,
6410 IP_PROTOS.tcp)
6411 self.vapi.nat64_add_del_static_bib(server.ip6n,
6412 self.nat_addr_n,
6413 server_udp_in_port,
6414 server_udp_out_port,
6415 IP_PROTOS.udp)
6416
6417 # client to server
6418 pkts = []
6419 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6420 IPv6(src=client.ip6, dst=nat_addr_ip6) /
6421 TCP(sport=client_tcp_in_port, dport=server_tcp_out_port))
6422 pkts.append(p)
6423 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6424 IPv6(src=client.ip6, dst=nat_addr_ip6) /
6425 UDP(sport=client_udp_in_port, dport=server_udp_out_port))
6426 pkts.append(p)
6427 self.pg0.add_stream(pkts)
6428 self.pg_enable_capture(self.pg_interfaces)
6429 self.pg_start()
6430 capture = self.pg0.get_capture(len(pkts))
6431 for packet in capture:
6432 try:
6433 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
6434 self.assertEqual(packet[IPv6].dst, server.ip6)
Klement Sekerad81ae412018-05-16 10:52:54 +02006435 self.assert_packet_checksums_valid(packet)
Matus Fabian029f3d22017-06-15 02:28:50 -07006436 if packet.haslayer(TCP):
6437 self.assertNotEqual(packet[TCP].sport, client_tcp_in_port)
6438 self.assertEqual(packet[TCP].dport, server_tcp_in_port)
Matus Fabian029f3d22017-06-15 02:28:50 -07006439 client_tcp_out_port = packet[TCP].sport
6440 else:
6441 self.assertNotEqual(packet[UDP].sport, client_udp_in_port)
6442 self.assertEqual(packet[UDP].dport, server_udp_in_port)
Matus Fabian029f3d22017-06-15 02:28:50 -07006443 client_udp_out_port = packet[UDP].sport
6444 except:
6445 self.logger.error(ppp("Unexpected or invalid packet:", packet))
6446 raise
6447
6448 # server to client
6449 pkts = []
6450 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6451 IPv6(src=server.ip6, dst=nat_addr_ip6) /
6452 TCP(sport=server_tcp_in_port, dport=client_tcp_out_port))
6453 pkts.append(p)
6454 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6455 IPv6(src=server.ip6, dst=nat_addr_ip6) /
6456 UDP(sport=server_udp_in_port, dport=client_udp_out_port))
6457 pkts.append(p)
6458 self.pg0.add_stream(pkts)
6459 self.pg_enable_capture(self.pg_interfaces)
6460 self.pg_start()
6461 capture = self.pg0.get_capture(len(pkts))
6462 for packet in capture:
6463 try:
6464 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
6465 self.assertEqual(packet[IPv6].dst, client.ip6)
Klement Sekerad81ae412018-05-16 10:52:54 +02006466 self.assert_packet_checksums_valid(packet)
Matus Fabian029f3d22017-06-15 02:28:50 -07006467 if packet.haslayer(TCP):
6468 self.assertEqual(packet[TCP].sport, server_tcp_out_port)
6469 self.assertEqual(packet[TCP].dport, client_tcp_in_port)
Matus Fabian029f3d22017-06-15 02:28:50 -07006470 else:
6471 self.assertEqual(packet[UDP].sport, server_udp_out_port)
6472 self.assertEqual(packet[UDP].dport, client_udp_in_port)
Matus Fabian029f3d22017-06-15 02:28:50 -07006473 except:
6474 self.logger.error(ppp("Unexpected or invalid packet:", packet))
6475 raise
6476
6477 # ICMP error
6478 pkts = []
6479 pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6480 IPv6(src=client.ip6, dst=nat_addr_ip6) /
6481 ICMPv6DestUnreach(code=1) /
6482 packet[IPv6] for packet in capture]
6483 self.pg0.add_stream(pkts)
6484 self.pg_enable_capture(self.pg_interfaces)
6485 self.pg_start()
6486 capture = self.pg0.get_capture(len(pkts))
6487 for packet in capture:
6488 try:
6489 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
6490 self.assertEqual(packet[IPv6].dst, server.ip6)
6491 icmp = packet[ICMPv6DestUnreach]
6492 self.assertEqual(icmp.code, 1)
6493 inner = icmp[IPerror6]
6494 self.assertEqual(inner.src, server.ip6)
6495 self.assertEqual(inner.dst, nat_addr_ip6)
Klement Sekerad81ae412018-05-16 10:52:54 +02006496 self.assert_packet_checksums_valid(packet)
Matus Fabian029f3d22017-06-15 02:28:50 -07006497 if inner.haslayer(TCPerror):
6498 self.assertEqual(inner[TCPerror].sport, server_tcp_in_port)
6499 self.assertEqual(inner[TCPerror].dport,
6500 client_tcp_out_port)
6501 else:
6502 self.assertEqual(inner[UDPerror].sport, server_udp_in_port)
6503 self.assertEqual(inner[UDPerror].dport,
6504 client_udp_out_port)
6505 except:
6506 self.logger.error(ppp("Unexpected or invalid packet:", packet))
6507 raise
6508
Matus Fabian428dc912017-06-21 06:15:18 -07006509 def test_prefix(self):
6510 """ NAT64 Network-Specific Prefix """
6511
6512 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6513 self.nat_addr_n)
6514 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6515 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6516 self.vapi.nat64_add_del_pool_addr_range(self.vrf1_nat_addr_n,
6517 self.vrf1_nat_addr_n,
6518 vrf_id=self.vrf1_id)
6519 self.vapi.nat64_add_del_interface(self.pg2.sw_if_index)
6520
6521 # Add global prefix
6522 global_pref64 = "2001:db8::"
6523 global_pref64_n = socket.inet_pton(socket.AF_INET6, global_pref64)
6524 global_pref64_len = 32
6525 self.vapi.nat64_add_del_prefix(global_pref64_n, global_pref64_len)
6526
6527 prefix = self.vapi.nat64_prefix_dump()
6528 self.assertEqual(len(prefix), 1)
6529 self.assertEqual(prefix[0].prefix, global_pref64_n)
6530 self.assertEqual(prefix[0].prefix_len, global_pref64_len)
6531 self.assertEqual(prefix[0].vrf_id, 0)
6532
6533 # Add tenant specific prefix
6534 vrf1_pref64 = "2001:db8:122:300::"
6535 vrf1_pref64_n = socket.inet_pton(socket.AF_INET6, vrf1_pref64)
6536 vrf1_pref64_len = 56
6537 self.vapi.nat64_add_del_prefix(vrf1_pref64_n,
6538 vrf1_pref64_len,
6539 vrf_id=self.vrf1_id)
6540 prefix = self.vapi.nat64_prefix_dump()
6541 self.assertEqual(len(prefix), 2)
6542
6543 # Global prefix
6544 pkts = self.create_stream_in_ip6(self.pg0,
6545 self.pg1,
6546 pref=global_pref64,
6547 plen=global_pref64_len)
6548 self.pg0.add_stream(pkts)
6549 self.pg_enable_capture(self.pg_interfaces)
6550 self.pg_start()
6551 capture = self.pg1.get_capture(len(pkts))
6552 self.verify_capture_out(capture, nat_ip=self.nat_addr,
6553 dst_ip=self.pg1.remote_ip4)
6554
6555 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
6556 self.pg1.add_stream(pkts)
6557 self.pg_enable_capture(self.pg_interfaces)
6558 self.pg_start()
6559 capture = self.pg0.get_capture(len(pkts))
6560 dst_ip = self.compose_ip6(self.pg1.remote_ip4,
6561 global_pref64,
6562 global_pref64_len)
6563 self.verify_capture_in_ip6(capture, dst_ip, self.pg0.remote_ip6)
6564
6565 # Tenant specific prefix
6566 pkts = self.create_stream_in_ip6(self.pg2,
6567 self.pg1,
6568 pref=vrf1_pref64,
6569 plen=vrf1_pref64_len)
6570 self.pg2.add_stream(pkts)
6571 self.pg_enable_capture(self.pg_interfaces)
6572 self.pg_start()
6573 capture = self.pg1.get_capture(len(pkts))
6574 self.verify_capture_out(capture, nat_ip=self.vrf1_nat_addr,
6575 dst_ip=self.pg1.remote_ip4)
6576
6577 pkts = self.create_stream_out(self.pg1, dst_ip=self.vrf1_nat_addr)
6578 self.pg1.add_stream(pkts)
6579 self.pg_enable_capture(self.pg_interfaces)
6580 self.pg_start()
6581 capture = self.pg2.get_capture(len(pkts))
6582 dst_ip = self.compose_ip6(self.pg1.remote_ip4,
6583 vrf1_pref64,
6584 vrf1_pref64_len)
6585 self.verify_capture_in_ip6(capture, dst_ip, self.pg2.remote_ip6)
6586
Matus Fabianf8cd5812017-07-11 03:55:02 -07006587 def test_unknown_proto(self):
Matus Fabian7968e6c2017-07-06 05:37:49 -07006588 """ NAT64 translate packet with unknown protocol """
6589
6590 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6591 self.nat_addr_n)
6592 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6593 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6594 remote_ip6 = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
6595
6596 # in2out
6597 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6598 IPv6(src=self.pg0.remote_ip6, dst=remote_ip6) /
6599 TCP(sport=self.tcp_port_in, dport=20))
6600 self.pg0.add_stream(p)
6601 self.pg_enable_capture(self.pg_interfaces)
6602 self.pg_start()
6603 p = self.pg1.get_capture(1)
6604
6605 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabianf8cd5812017-07-11 03:55:02 -07006606 IPv6(src=self.pg0.remote_ip6, dst=remote_ip6, nh=47) /
Matus Fabian7968e6c2017-07-06 05:37:49 -07006607 GRE() /
6608 IP(src=self.pg2.local_ip4, dst=self.pg2.remote_ip4) /
6609 TCP(sport=1234, dport=1234))
6610 self.pg0.add_stream(p)
6611 self.pg_enable_capture(self.pg_interfaces)
6612 self.pg_start()
6613 p = self.pg1.get_capture(1)
6614 packet = p[0]
6615 try:
6616 self.assertEqual(packet[IP].src, self.nat_addr)
6617 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
6618 self.assertTrue(packet.haslayer(GRE))
Klement Sekerad81ae412018-05-16 10:52:54 +02006619 self.assert_packet_checksums_valid(packet)
Matus Fabian7968e6c2017-07-06 05:37:49 -07006620 except:
6621 self.logger.error(ppp("Unexpected or invalid packet:", packet))
6622 raise
6623
6624 # out2in
6625 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
6626 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6627 GRE() /
6628 IP(src=self.pg2.remote_ip4, dst=self.pg2.local_ip4) /
6629 TCP(sport=1234, dport=1234))
6630 self.pg1.add_stream(p)
6631 self.pg_enable_capture(self.pg_interfaces)
6632 self.pg_start()
6633 p = self.pg0.get_capture(1)
6634 packet = p[0]
6635 try:
6636 self.assertEqual(packet[IPv6].src, remote_ip6)
Matus Fabianf8cd5812017-07-11 03:55:02 -07006637 self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
6638 self.assertEqual(packet[IPv6].nh, 47)
Matus Fabian7968e6c2017-07-06 05:37:49 -07006639 except:
6640 self.logger.error(ppp("Unexpected or invalid packet:", packet))
6641 raise
6642
Matus Fabianf8cd5812017-07-11 03:55:02 -07006643 def test_hairpinning_unknown_proto(self):
Matus Fabian7968e6c2017-07-06 05:37:49 -07006644 """ NAT64 translate packet with unknown protocol - hairpinning """
6645
6646 client = self.pg0.remote_hosts[0]
6647 server = self.pg0.remote_hosts[1]
6648 server_tcp_in_port = 22
6649 server_tcp_out_port = 4022
6650 client_tcp_in_port = 1234
Matus Fabianf8cd5812017-07-11 03:55:02 -07006651 client_tcp_out_port = 1235
6652 server_nat_ip = "10.0.0.100"
6653 client_nat_ip = "10.0.0.110"
6654 server_nat_ip_n = socket.inet_pton(socket.AF_INET, server_nat_ip)
6655 client_nat_ip_n = socket.inet_pton(socket.AF_INET, client_nat_ip)
6656 server_nat_ip6 = self.compose_ip6(server_nat_ip, '64:ff9b::', 96)
6657 client_nat_ip6 = self.compose_ip6(client_nat_ip, '64:ff9b::', 96)
Matus Fabian7968e6c2017-07-06 05:37:49 -07006658
Matus Fabianf8cd5812017-07-11 03:55:02 -07006659 self.vapi.nat64_add_del_pool_addr_range(server_nat_ip_n,
6660 client_nat_ip_n)
Matus Fabian7968e6c2017-07-06 05:37:49 -07006661 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6662 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6663
6664 self.vapi.nat64_add_del_static_bib(server.ip6n,
Matus Fabianf8cd5812017-07-11 03:55:02 -07006665 server_nat_ip_n,
Matus Fabian7968e6c2017-07-06 05:37:49 -07006666 server_tcp_in_port,
6667 server_tcp_out_port,
6668 IP_PROTOS.tcp)
6669
Matus Fabianf8cd5812017-07-11 03:55:02 -07006670 self.vapi.nat64_add_del_static_bib(server.ip6n,
6671 server_nat_ip_n,
6672 0,
6673 0,
6674 IP_PROTOS.gre)
6675
6676 self.vapi.nat64_add_del_static_bib(client.ip6n,
6677 client_nat_ip_n,
6678 client_tcp_in_port,
6679 client_tcp_out_port,
6680 IP_PROTOS.tcp)
6681
Matus Fabian7968e6c2017-07-06 05:37:49 -07006682 # client to server
6683 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabianf8cd5812017-07-11 03:55:02 -07006684 IPv6(src=client.ip6, dst=server_nat_ip6) /
Matus Fabian7968e6c2017-07-06 05:37:49 -07006685 TCP(sport=client_tcp_in_port, dport=server_tcp_out_port))
6686 self.pg0.add_stream(p)
6687 self.pg_enable_capture(self.pg_interfaces)
6688 self.pg_start()
6689 p = self.pg0.get_capture(1)
6690
6691 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabianf8cd5812017-07-11 03:55:02 -07006692 IPv6(src=client.ip6, dst=server_nat_ip6, nh=IP_PROTOS.gre) /
Matus Fabian7968e6c2017-07-06 05:37:49 -07006693 GRE() /
6694 IP(src=self.pg2.local_ip4, dst=self.pg2.remote_ip4) /
6695 TCP(sport=1234, dport=1234))
6696 self.pg0.add_stream(p)
6697 self.pg_enable_capture(self.pg_interfaces)
6698 self.pg_start()
6699 p = self.pg0.get_capture(1)
6700 packet = p[0]
6701 try:
Matus Fabianf8cd5812017-07-11 03:55:02 -07006702 self.assertEqual(packet[IPv6].src, client_nat_ip6)
Matus Fabian7968e6c2017-07-06 05:37:49 -07006703 self.assertEqual(packet[IPv6].dst, server.ip6)
Matus Fabianf8cd5812017-07-11 03:55:02 -07006704 self.assertEqual(packet[IPv6].nh, IP_PROTOS.gre)
Matus Fabian7968e6c2017-07-06 05:37:49 -07006705 except:
6706 self.logger.error(ppp("Unexpected or invalid packet:", packet))
6707 raise
6708
6709 # server to client
6710 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabianf8cd5812017-07-11 03:55:02 -07006711 IPv6(src=server.ip6, dst=client_nat_ip6, nh=IP_PROTOS.gre) /
Matus Fabian7968e6c2017-07-06 05:37:49 -07006712 GRE() /
6713 IP(src=self.pg2.remote_ip4, dst=self.pg2.local_ip4) /
6714 TCP(sport=1234, dport=1234))
6715 self.pg0.add_stream(p)
6716 self.pg_enable_capture(self.pg_interfaces)
6717 self.pg_start()
6718 p = self.pg0.get_capture(1)
6719 packet = p[0]
6720 try:
Matus Fabianf8cd5812017-07-11 03:55:02 -07006721 self.assertEqual(packet[IPv6].src, server_nat_ip6)
Matus Fabian7968e6c2017-07-06 05:37:49 -07006722 self.assertEqual(packet[IPv6].dst, client.ip6)
Matus Fabianf8cd5812017-07-11 03:55:02 -07006723 self.assertEqual(packet[IPv6].nh, IP_PROTOS.gre)
Matus Fabian7968e6c2017-07-06 05:37:49 -07006724 except:
6725 self.logger.error(ppp("Unexpected or invalid packet:", packet))
6726 raise
6727
Matus Fabian36ea2d62017-10-24 04:13:49 -07006728 def test_one_armed_nat64(self):
6729 """ One armed NAT64 """
6730 external_port = 0
6731 remote_host_ip6 = self.compose_ip6(self.pg3.remote_ip4,
6732 '64:ff9b::',
6733 96)
6734
6735 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6736 self.nat_addr_n)
6737 self.vapi.nat64_add_del_interface(self.pg3.sw_if_index)
6738 self.vapi.nat64_add_del_interface(self.pg3.sw_if_index, is_inside=0)
6739
6740 # in2out
6741 p = (Ether(src=self.pg3.remote_mac, dst=self.pg3.local_mac) /
6742 IPv6(src=self.pg3.remote_ip6, dst=remote_host_ip6) /
6743 TCP(sport=12345, dport=80))
6744 self.pg3.add_stream(p)
6745 self.pg_enable_capture(self.pg_interfaces)
6746 self.pg_start()
6747 capture = self.pg3.get_capture(1)
6748 p = capture[0]
6749 try:
6750 ip = p[IP]
6751 tcp = p[TCP]
6752 self.assertEqual(ip.src, self.nat_addr)
6753 self.assertEqual(ip.dst, self.pg3.remote_ip4)
6754 self.assertNotEqual(tcp.sport, 12345)
6755 external_port = tcp.sport
6756 self.assertEqual(tcp.dport, 80)
Klement Sekerad81ae412018-05-16 10:52:54 +02006757 self.assert_packet_checksums_valid(p)
Matus Fabian36ea2d62017-10-24 04:13:49 -07006758 except:
6759 self.logger.error(ppp("Unexpected or invalid packet:", p))
6760 raise
6761
6762 # out2in
6763 p = (Ether(src=self.pg3.remote_mac, dst=self.pg3.local_mac) /
6764 IP(src=self.pg3.remote_ip4, dst=self.nat_addr) /
6765 TCP(sport=80, dport=external_port))
6766 self.pg3.add_stream(p)
6767 self.pg_enable_capture(self.pg_interfaces)
6768 self.pg_start()
6769 capture = self.pg3.get_capture(1)
6770 p = capture[0]
6771 try:
6772 ip = p[IPv6]
6773 tcp = p[TCP]
6774 self.assertEqual(ip.src, remote_host_ip6)
6775 self.assertEqual(ip.dst, self.pg3.remote_ip6)
6776 self.assertEqual(tcp.sport, 80)
6777 self.assertEqual(tcp.dport, 12345)
Klement Sekerad81ae412018-05-16 10:52:54 +02006778 self.assert_packet_checksums_valid(p)
Matus Fabian36ea2d62017-10-24 04:13:49 -07006779 except:
6780 self.logger.error(ppp("Unexpected or invalid packet:", p))
6781 raise
6782
Matus Fabianefcd1e92017-08-15 06:59:19 -07006783 def test_frag_in_order(self):
6784 """ NAT64 translate fragments arriving in order """
6785 self.tcp_port_in = random.randint(1025, 65535)
6786
6787 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6788 self.nat_addr_n)
6789 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6790 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6791
6792 reass = self.vapi.nat_reass_dump()
6793 reass_n_start = len(reass)
6794
6795 # in2out
6796 data = 'a' * 200
6797 pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
6798 self.tcp_port_in, 20, data)
6799 self.pg0.add_stream(pkts)
6800 self.pg_enable_capture(self.pg_interfaces)
6801 self.pg_start()
6802 frags = self.pg1.get_capture(len(pkts))
6803 p = self.reass_frags_and_verify(frags,
6804 self.nat_addr,
6805 self.pg1.remote_ip4)
6806 self.assertEqual(p[TCP].dport, 20)
6807 self.assertNotEqual(p[TCP].sport, self.tcp_port_in)
6808 self.tcp_port_out = p[TCP].sport
6809 self.assertEqual(data, p[Raw].load)
6810
6811 # out2in
6812 data = "A" * 4 + "b" * 16 + "C" * 3
6813 pkts = self.create_stream_frag(self.pg1,
6814 self.nat_addr,
6815 20,
6816 self.tcp_port_out,
6817 data)
6818 self.pg1.add_stream(pkts)
6819 self.pg_enable_capture(self.pg_interfaces)
6820 self.pg_start()
6821 frags = self.pg0.get_capture(len(pkts))
6822 src = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
6823 p = self.reass_frags_and_verify_ip6(frags, src, self.pg0.remote_ip6)
6824 self.assertEqual(p[TCP].sport, 20)
6825 self.assertEqual(p[TCP].dport, self.tcp_port_in)
6826 self.assertEqual(data, p[Raw].load)
6827
6828 reass = self.vapi.nat_reass_dump()
6829 reass_n_end = len(reass)
6830
6831 self.assertEqual(reass_n_end - reass_n_start, 2)
6832
6833 def test_reass_hairpinning(self):
6834 """ NAT64 fragments hairpinning """
6835 data = 'a' * 200
Matus Fabianefcd1e92017-08-15 06:59:19 -07006836 server = self.pg0.remote_hosts[1]
6837 server_in_port = random.randint(1025, 65535)
6838 server_out_port = random.randint(1025, 65535)
6839 client_in_port = random.randint(1025, 65535)
6840 ip = IPv6(src=''.join(['64:ff9b::', self.nat_addr]))
6841 nat_addr_ip6 = ip.src
6842
6843 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6844 self.nat_addr_n)
6845 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6846 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6847
6848 # add static BIB entry for server
6849 self.vapi.nat64_add_del_static_bib(server.ip6n,
6850 self.nat_addr_n,
6851 server_in_port,
6852 server_out_port,
6853 IP_PROTOS.tcp)
6854
6855 # send packet from host to server
6856 pkts = self.create_stream_frag_ip6(self.pg0,
6857 self.nat_addr,
6858 client_in_port,
6859 server_out_port,
6860 data)
6861 self.pg0.add_stream(pkts)
6862 self.pg_enable_capture(self.pg_interfaces)
6863 self.pg_start()
6864 frags = self.pg0.get_capture(len(pkts))
6865 p = self.reass_frags_and_verify_ip6(frags, nat_addr_ip6, server.ip6)
6866 self.assertNotEqual(p[TCP].sport, client_in_port)
6867 self.assertEqual(p[TCP].dport, server_in_port)
6868 self.assertEqual(data, p[Raw].load)
6869
6870 def test_frag_out_of_order(self):
6871 """ NAT64 translate fragments arriving out of order """
6872 self.tcp_port_in = random.randint(1025, 65535)
6873
6874 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6875 self.nat_addr_n)
6876 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6877 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6878
6879 # in2out
6880 data = 'a' * 200
6881 pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
6882 self.tcp_port_in, 20, data)
6883 pkts.reverse()
6884 self.pg0.add_stream(pkts)
6885 self.pg_enable_capture(self.pg_interfaces)
6886 self.pg_start()
6887 frags = self.pg1.get_capture(len(pkts))
6888 p = self.reass_frags_and_verify(frags,
6889 self.nat_addr,
6890 self.pg1.remote_ip4)
6891 self.assertEqual(p[TCP].dport, 20)
6892 self.assertNotEqual(p[TCP].sport, self.tcp_port_in)
6893 self.tcp_port_out = p[TCP].sport
6894 self.assertEqual(data, p[Raw].load)
6895
6896 # out2in
6897 data = "A" * 4 + "B" * 16 + "C" * 3
6898 pkts = self.create_stream_frag(self.pg1,
6899 self.nat_addr,
6900 20,
6901 self.tcp_port_out,
6902 data)
6903 pkts.reverse()
6904 self.pg1.add_stream(pkts)
6905 self.pg_enable_capture(self.pg_interfaces)
6906 self.pg_start()
6907 frags = self.pg0.get_capture(len(pkts))
6908 src = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
6909 p = self.reass_frags_and_verify_ip6(frags, src, self.pg0.remote_ip6)
6910 self.assertEqual(p[TCP].sport, 20)
6911 self.assertEqual(p[TCP].dport, self.tcp_port_in)
6912 self.assertEqual(data, p[Raw].load)
6913
Matus Fabian0938dcf2017-11-08 01:59:38 -08006914 def test_interface_addr(self):
6915 """ Acquire NAT64 pool addresses from interface """
6916 self.vapi.nat64_add_interface_addr(self.pg4.sw_if_index)
6917
6918 # no address in NAT64 pool
6919 adresses = self.vapi.nat44_address_dump()
6920 self.assertEqual(0, len(adresses))
6921
6922 # configure interface address and check NAT64 address pool
6923 self.pg4.config_ip4()
6924 addresses = self.vapi.nat64_pool_addr_dump()
6925 self.assertEqual(len(addresses), 1)
6926 self.assertEqual(addresses[0].address, self.pg4.local_ip4n)
6927
6928 # remove interface address and check NAT64 address pool
6929 self.pg4.unconfig_ip4()
6930 addresses = self.vapi.nat64_pool_addr_dump()
6931 self.assertEqual(0, len(adresses))
6932
Matus Fabiana431ad12018-01-04 04:03:14 -08006933 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
6934 def test_ipfix_max_bibs_sessions(self):
6935 """ IPFIX logging maximum session and BIB entries exceeded """
6936 max_bibs = 1280
6937 max_sessions = 2560
6938 remote_host_ip6 = self.compose_ip6(self.pg1.remote_ip4,
6939 '64:ff9b::',
6940 96)
6941
6942 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6943 self.nat_addr_n)
6944 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6945 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6946
6947 pkts = []
6948 src = ""
6949 for i in range(0, max_bibs):
6950 src = "fd01:aa::%x" % (i)
6951 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6952 IPv6(src=src, dst=remote_host_ip6) /
6953 TCP(sport=12345, dport=80))
6954 pkts.append(p)
6955 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6956 IPv6(src=src, dst=remote_host_ip6) /
6957 TCP(sport=12345, dport=22))
6958 pkts.append(p)
6959 self.pg0.add_stream(pkts)
6960 self.pg_enable_capture(self.pg_interfaces)
6961 self.pg_start()
6962 self.pg1.get_capture(max_sessions)
6963
6964 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
6965 src_address=self.pg3.local_ip4n,
6966 path_mtu=512,
6967 template_interval=10)
6968 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
6969 src_port=self.ipfix_src_port)
6970
6971 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6972 IPv6(src=src, dst=remote_host_ip6) /
6973 TCP(sport=12345, dport=25))
6974 self.pg0.add_stream(p)
6975 self.pg_enable_capture(self.pg_interfaces)
6976 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07006977 self.pg1.assert_nothing_captured()
6978 sleep(1)
Matus Fabiana431ad12018-01-04 04:03:14 -08006979 self.vapi.cli("ipfix flush") # FIXME this should be an API call
6980 capture = self.pg3.get_capture(9)
6981 ipfix = IPFIXDecoder()
6982 # first load template
6983 for p in capture:
6984 self.assertTrue(p.haslayer(IPFIX))
6985 self.assertEqual(p[IP].src, self.pg3.local_ip4)
6986 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
6987 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
6988 self.assertEqual(p[UDP].dport, 4739)
6989 self.assertEqual(p[IPFIX].observationDomainID,
6990 self.ipfix_domain_id)
6991 if p.haslayer(Template):
6992 ipfix.add_template(p.getlayer(Template))
6993 # verify events in data set
6994 for p in capture:
6995 if p.haslayer(Data):
6996 data = ipfix.decode_data_set(p.getlayer(Set))
6997 self.verify_ipfix_max_sessions(data, max_sessions)
6998
6999 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7000 IPv6(src=self.pg0.remote_ip6, dst=remote_host_ip6) /
7001 TCP(sport=12345, dport=80))
7002 self.pg0.add_stream(p)
7003 self.pg_enable_capture(self.pg_interfaces)
7004 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07007005 self.pg1.assert_nothing_captured()
7006 sleep(1)
Matus Fabiana431ad12018-01-04 04:03:14 -08007007 self.vapi.cli("ipfix flush") # FIXME this should be an API call
7008 capture = self.pg3.get_capture(1)
7009 # verify events in data set
7010 for p in capture:
7011 self.assertTrue(p.haslayer(IPFIX))
7012 self.assertEqual(p[IP].src, self.pg3.local_ip4)
7013 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
7014 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
7015 self.assertEqual(p[UDP].dport, 4739)
7016 self.assertEqual(p[IPFIX].observationDomainID,
7017 self.ipfix_domain_id)
7018 if p.haslayer(Data):
7019 data = ipfix.decode_data_set(p.getlayer(Set))
7020 self.verify_ipfix_max_bibs(data, max_bibs)
7021
7022 def test_ipfix_max_frags(self):
7023 """ IPFIX logging maximum fragments pending reassembly exceeded """
7024 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7025 self.nat_addr_n)
7026 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7027 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
Matus Fabiana7f8b222018-09-05 06:01:55 -07007028 self.vapi.nat_set_reass(max_frag=1, is_ip6=1)
Matus Fabiana431ad12018-01-04 04:03:14 -08007029 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
7030 src_address=self.pg3.local_ip4n,
7031 path_mtu=512,
7032 template_interval=10)
7033 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
7034 src_port=self.ipfix_src_port)
7035
7036 data = 'a' * 200
7037 pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
7038 self.tcp_port_in, 20, data)
Matus Fabiana7f8b222018-09-05 06:01:55 -07007039 pkts.reverse()
7040 self.pg0.add_stream(pkts)
Matus Fabiana431ad12018-01-04 04:03:14 -08007041 self.pg_enable_capture(self.pg_interfaces)
7042 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07007043 self.pg1.assert_nothing_captured()
7044 sleep(1)
Matus Fabiana431ad12018-01-04 04:03:14 -08007045 self.vapi.cli("ipfix flush") # FIXME this should be an API call
7046 capture = self.pg3.get_capture(9)
7047 ipfix = IPFIXDecoder()
7048 # first load template
7049 for p in capture:
7050 self.assertTrue(p.haslayer(IPFIX))
7051 self.assertEqual(p[IP].src, self.pg3.local_ip4)
7052 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
7053 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
7054 self.assertEqual(p[UDP].dport, 4739)
7055 self.assertEqual(p[IPFIX].observationDomainID,
7056 self.ipfix_domain_id)
7057 if p.haslayer(Template):
7058 ipfix.add_template(p.getlayer(Template))
7059 # verify events in data set
7060 for p in capture:
7061 if p.haslayer(Data):
7062 data = ipfix.decode_data_set(p.getlayer(Set))
Matus Fabiana7f8b222018-09-05 06:01:55 -07007063 self.verify_ipfix_max_fragments_ip6(data, 1,
Matus Fabiana431ad12018-01-04 04:03:14 -08007064 self.pg0.remote_ip6n)
7065
7066 def test_ipfix_bib_ses(self):
7067 """ IPFIX logging NAT64 BIB/session create and delete events """
7068 self.tcp_port_in = random.randint(1025, 65535)
7069 remote_host_ip6 = self.compose_ip6(self.pg1.remote_ip4,
7070 '64:ff9b::',
7071 96)
7072
7073 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7074 self.nat_addr_n)
7075 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7076 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7077 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
7078 src_address=self.pg3.local_ip4n,
7079 path_mtu=512,
7080 template_interval=10)
7081 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
7082 src_port=self.ipfix_src_port)
7083
7084 # Create
7085 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7086 IPv6(src=self.pg0.remote_ip6, dst=remote_host_ip6) /
7087 TCP(sport=self.tcp_port_in, dport=25))
7088 self.pg0.add_stream(p)
7089 self.pg_enable_capture(self.pg_interfaces)
7090 self.pg_start()
7091 p = self.pg1.get_capture(1)
7092 self.tcp_port_out = p[0][TCP].sport
7093 self.vapi.cli("ipfix flush") # FIXME this should be an API call
7094 capture = self.pg3.get_capture(10)
7095 ipfix = IPFIXDecoder()
7096 # first load template
7097 for p in capture:
7098 self.assertTrue(p.haslayer(IPFIX))
7099 self.assertEqual(p[IP].src, self.pg3.local_ip4)
7100 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
7101 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
7102 self.assertEqual(p[UDP].dport, 4739)
7103 self.assertEqual(p[IPFIX].observationDomainID,
7104 self.ipfix_domain_id)
7105 if p.haslayer(Template):
7106 ipfix.add_template(p.getlayer(Template))
7107 # verify events in data set
7108 for p in capture:
7109 if p.haslayer(Data):
7110 data = ipfix.decode_data_set(p.getlayer(Set))
7111 if ord(data[0][230]) == 10:
7112 self.verify_ipfix_bib(data, 1, self.pg0.remote_ip6n)
7113 elif ord(data[0][230]) == 6:
7114 self.verify_ipfix_nat64_ses(data,
7115 1,
7116 self.pg0.remote_ip6n,
7117 self.pg1.remote_ip4,
7118 25)
7119 else:
7120 self.logger.error(ppp("Unexpected or invalid packet: ", p))
7121
7122 # Delete
7123 self.pg_enable_capture(self.pg_interfaces)
7124 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7125 self.nat_addr_n,
7126 is_add=0)
7127 self.vapi.cli("ipfix flush") # FIXME this should be an API call
7128 capture = self.pg3.get_capture(2)
7129 # verify events in data set
7130 for p in capture:
7131 self.assertTrue(p.haslayer(IPFIX))
7132 self.assertEqual(p[IP].src, self.pg3.local_ip4)
7133 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
7134 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
7135 self.assertEqual(p[UDP].dport, 4739)
7136 self.assertEqual(p[IPFIX].observationDomainID,
7137 self.ipfix_domain_id)
7138 if p.haslayer(Data):
7139 data = ipfix.decode_data_set(p.getlayer(Set))
7140 if ord(data[0][230]) == 11:
7141 self.verify_ipfix_bib(data, 0, self.pg0.remote_ip6n)
7142 elif ord(data[0][230]) == 7:
7143 self.verify_ipfix_nat64_ses(data,
7144 0,
7145 self.pg0.remote_ip6n,
7146 self.pg1.remote_ip4,
7147 25)
7148 else:
7149 self.logger.error(ppp("Unexpected or invalid packet: ", p))
7150
Matus Fabian06596c52017-06-06 04:53:28 -07007151 def nat64_get_ses_num(self):
7152 """
7153 Return number of active NAT64 sessions.
7154 """
Matus Fabianab9a59c2017-08-16 05:37:36 -07007155 st = self.vapi.nat64_st_dump()
7156 return len(st)
Matus Fabian06596c52017-06-06 04:53:28 -07007157
7158 def clear_nat64(self):
7159 """
7160 Clear NAT64 configuration.
7161 """
Matus Fabiana431ad12018-01-04 04:03:14 -08007162 self.vapi.nat_ipfix(enable=0, src_port=self.ipfix_src_port,
7163 domain_id=self.ipfix_domain_id)
7164 self.ipfix_src_port = 4739
7165 self.ipfix_domain_id = 1
7166
Matus Fabian878c6462018-08-23 00:33:35 -07007167 self.vapi.nat_set_timeouts()
Matus Fabian06596c52017-06-06 04:53:28 -07007168
7169 interfaces = self.vapi.nat64_interface_dump()
7170 for intf in interfaces:
Matus Fabian36ea2d62017-10-24 04:13:49 -07007171 if intf.is_inside > 1:
7172 self.vapi.nat64_add_del_interface(intf.sw_if_index,
7173 0,
7174 is_add=0)
Matus Fabian06596c52017-06-06 04:53:28 -07007175 self.vapi.nat64_add_del_interface(intf.sw_if_index,
7176 intf.is_inside,
7177 is_add=0)
7178
Matus Fabiana431ad12018-01-04 04:03:14 -08007179 bib = self.vapi.nat64_bib_dump(255)
Matus Fabian06596c52017-06-06 04:53:28 -07007180 for bibe in bib:
7181 if bibe.is_static:
7182 self.vapi.nat64_add_del_static_bib(bibe.i_addr,
7183 bibe.o_addr,
7184 bibe.i_port,
7185 bibe.o_port,
7186 bibe.proto,
7187 bibe.vrf_id,
7188 is_add=0)
7189
7190 adresses = self.vapi.nat64_pool_addr_dump()
7191 for addr in adresses:
7192 self.vapi.nat64_add_del_pool_addr_range(addr.address,
7193 addr.address,
Matus Fabian029f3d22017-06-15 02:28:50 -07007194 vrf_id=addr.vrf_id,
Matus Fabian06596c52017-06-06 04:53:28 -07007195 is_add=0)
7196
Matus Fabian428dc912017-06-21 06:15:18 -07007197 prefixes = self.vapi.nat64_prefix_dump()
7198 for prefix in prefixes:
7199 self.vapi.nat64_add_del_prefix(prefix.prefix,
7200 prefix.prefix_len,
7201 vrf_id=prefix.vrf_id,
7202 is_add=0)
7203
Matus Fabian06596c52017-06-06 04:53:28 -07007204 def tearDown(self):
7205 super(TestNAT64, self).tearDown()
7206 if not self.vpp_dead:
7207 self.logger.info(self.vapi.cli("show nat64 pool"))
7208 self.logger.info(self.vapi.cli("show nat64 interfaces"))
Matus Fabian428dc912017-06-21 06:15:18 -07007209 self.logger.info(self.vapi.cli("show nat64 prefix"))
Matus Fabianab9a59c2017-08-16 05:37:36 -07007210 self.logger.info(self.vapi.cli("show nat64 bib all"))
7211 self.logger.info(self.vapi.cli("show nat64 session table all"))
Matus Fabianefcd1e92017-08-15 06:59:19 -07007212 self.logger.info(self.vapi.cli("show nat virtual-reassembly"))
Matus Fabian06596c52017-06-06 04:53:28 -07007213 self.clear_nat64()
7214
Matus Fabian8ebe6252017-11-06 05:04:53 -08007215
7216class TestDSlite(MethodHolder):
7217 """ DS-Lite Test Cases """
7218
7219 @classmethod
7220 def setUpClass(cls):
7221 super(TestDSlite, cls).setUpClass()
7222
7223 try:
7224 cls.nat_addr = '10.0.0.3'
7225 cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
7226
7227 cls.create_pg_interfaces(range(2))
7228 cls.pg0.admin_up()
7229 cls.pg0.config_ip4()
7230 cls.pg0.resolve_arp()
7231 cls.pg1.admin_up()
7232 cls.pg1.config_ip6()
7233 cls.pg1.generate_remote_hosts(2)
7234 cls.pg1.configure_ipv6_neighbors()
7235
7236 except Exception:
7237 super(TestDSlite, cls).tearDownClass()
7238 raise
7239
7240 def test_dslite(self):
7241 """ Test DS-Lite """
Matus Fabian69ce30d2018-08-22 01:27:10 -07007242 nat_config = self.vapi.nat_show_config()
7243 self.assertEqual(0, nat_config.dslite_ce)
7244
Matus Fabian8ebe6252017-11-06 05:04:53 -08007245 self.vapi.dslite_add_del_pool_addr_range(self.nat_addr_n,
7246 self.nat_addr_n)
7247 aftr_ip4 = '192.0.0.1'
7248 aftr_ip4_n = socket.inet_pton(socket.AF_INET, aftr_ip4)
7249 aftr_ip6 = '2001:db8:85a3::8a2e:370:1'
7250 aftr_ip6_n = socket.inet_pton(socket.AF_INET6, aftr_ip6)
7251 self.vapi.dslite_set_aftr_addr(aftr_ip6_n, aftr_ip4_n)
7252
7253 # UDP
7254 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
7255 IPv6(dst=aftr_ip6, src=self.pg1.remote_hosts[0].ip6) /
7256 IP(dst=self.pg0.remote_ip4, src='192.168.1.1') /
7257 UDP(sport=20000, dport=10000))
7258 self.pg1.add_stream(p)
7259 self.pg_enable_capture(self.pg_interfaces)
7260 self.pg_start()
7261 capture = self.pg0.get_capture(1)
7262 capture = capture[0]
7263 self.assertFalse(capture.haslayer(IPv6))
7264 self.assertEqual(capture[IP].src, self.nat_addr)
7265 self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
7266 self.assertNotEqual(capture[UDP].sport, 20000)
7267 self.assertEqual(capture[UDP].dport, 10000)
Klement Sekerad81ae412018-05-16 10:52:54 +02007268 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08007269 out_port = capture[UDP].sport
7270
7271 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7272 IP(dst=self.nat_addr, src=self.pg0.remote_ip4) /
7273 UDP(sport=10000, dport=out_port))
7274 self.pg0.add_stream(p)
7275 self.pg_enable_capture(self.pg_interfaces)
7276 self.pg_start()
7277 capture = self.pg1.get_capture(1)
7278 capture = capture[0]
7279 self.assertEqual(capture[IPv6].src, aftr_ip6)
7280 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[0].ip6)
7281 self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
7282 self.assertEqual(capture[IP].dst, '192.168.1.1')
7283 self.assertEqual(capture[UDP].sport, 10000)
7284 self.assertEqual(capture[UDP].dport, 20000)
Klement Sekerad81ae412018-05-16 10:52:54 +02007285 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08007286
7287 # TCP
7288 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
7289 IPv6(dst=aftr_ip6, src=self.pg1.remote_hosts[1].ip6) /
7290 IP(dst=self.pg0.remote_ip4, src='192.168.1.1') /
7291 TCP(sport=20001, dport=10001))
7292 self.pg1.add_stream(p)
7293 self.pg_enable_capture(self.pg_interfaces)
7294 self.pg_start()
7295 capture = self.pg0.get_capture(1)
7296 capture = capture[0]
7297 self.assertFalse(capture.haslayer(IPv6))
7298 self.assertEqual(capture[IP].src, self.nat_addr)
7299 self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
7300 self.assertNotEqual(capture[TCP].sport, 20001)
7301 self.assertEqual(capture[TCP].dport, 10001)
Klement Sekerad81ae412018-05-16 10:52:54 +02007302 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08007303 out_port = capture[TCP].sport
7304
7305 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7306 IP(dst=self.nat_addr, src=self.pg0.remote_ip4) /
7307 TCP(sport=10001, dport=out_port))
7308 self.pg0.add_stream(p)
7309 self.pg_enable_capture(self.pg_interfaces)
7310 self.pg_start()
7311 capture = self.pg1.get_capture(1)
7312 capture = capture[0]
7313 self.assertEqual(capture[IPv6].src, aftr_ip6)
7314 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[1].ip6)
7315 self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
7316 self.assertEqual(capture[IP].dst, '192.168.1.1')
7317 self.assertEqual(capture[TCP].sport, 10001)
7318 self.assertEqual(capture[TCP].dport, 20001)
Klement Sekerad81ae412018-05-16 10:52:54 +02007319 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08007320
7321 # ICMP
7322 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
7323 IPv6(dst=aftr_ip6, src=self.pg1.remote_hosts[1].ip6) /
7324 IP(dst=self.pg0.remote_ip4, src='192.168.1.1') /
7325 ICMP(id=4000, type='echo-request'))
7326 self.pg1.add_stream(p)
7327 self.pg_enable_capture(self.pg_interfaces)
7328 self.pg_start()
7329 capture = self.pg0.get_capture(1)
7330 capture = capture[0]
7331 self.assertFalse(capture.haslayer(IPv6))
7332 self.assertEqual(capture[IP].src, self.nat_addr)
7333 self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
7334 self.assertNotEqual(capture[ICMP].id, 4000)
Klement Sekerad81ae412018-05-16 10:52:54 +02007335 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08007336 out_id = capture[ICMP].id
7337
7338 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7339 IP(dst=self.nat_addr, src=self.pg0.remote_ip4) /
7340 ICMP(id=out_id, type='echo-reply'))
7341 self.pg0.add_stream(p)
7342 self.pg_enable_capture(self.pg_interfaces)
7343 self.pg_start()
7344 capture = self.pg1.get_capture(1)
7345 capture = capture[0]
7346 self.assertEqual(capture[IPv6].src, aftr_ip6)
7347 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[1].ip6)
7348 self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
7349 self.assertEqual(capture[IP].dst, '192.168.1.1')
7350 self.assertEqual(capture[ICMP].id, 4000)
Klement Sekerad81ae412018-05-16 10:52:54 +02007351 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08007352
Matus Fabian331acc62017-12-08 03:38:51 -08007353 # ping DS-Lite AFTR tunnel endpoint address
7354 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
7355 IPv6(src=self.pg1.remote_hosts[1].ip6, dst=aftr_ip6) /
7356 ICMPv6EchoRequest())
7357 self.pg1.add_stream(p)
7358 self.pg_enable_capture(self.pg_interfaces)
7359 self.pg_start()
7360 capture = self.pg1.get_capture(1)
Matus Fabian331acc62017-12-08 03:38:51 -08007361 capture = capture[0]
7362 self.assertEqual(capture[IPv6].src, aftr_ip6)
7363 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[1].ip6)
7364 self.assertTrue(capture.haslayer(ICMPv6EchoReply))
7365
Matus Fabian8ebe6252017-11-06 05:04:53 -08007366 def tearDown(self):
7367 super(TestDSlite, self).tearDown()
7368 if not self.vpp_dead:
7369 self.logger.info(self.vapi.cli("show dslite pool"))
7370 self.logger.info(
7371 self.vapi.cli("show dslite aftr-tunnel-endpoint-address"))
7372 self.logger.info(self.vapi.cli("show dslite sessions"))
7373
Juraj Slobodac5c6a332018-01-09 16:08:32 +01007374
7375class TestDSliteCE(MethodHolder):
7376 """ DS-Lite CE Test Cases """
7377
7378 @classmethod
7379 def setUpConstants(cls):
7380 super(TestDSliteCE, cls).setUpConstants()
7381 cls.vpp_cmdline.extend(["nat", "{", "dslite ce", "}"])
7382
7383 @classmethod
7384 def setUpClass(cls):
7385 super(TestDSliteCE, cls).setUpClass()
7386
7387 try:
7388 cls.create_pg_interfaces(range(2))
7389 cls.pg0.admin_up()
7390 cls.pg0.config_ip4()
7391 cls.pg0.resolve_arp()
7392 cls.pg1.admin_up()
7393 cls.pg1.config_ip6()
7394 cls.pg1.generate_remote_hosts(1)
7395 cls.pg1.configure_ipv6_neighbors()
7396
7397 except Exception:
7398 super(TestDSliteCE, cls).tearDownClass()
7399 raise
7400
7401 def test_dslite_ce(self):
7402 """ Test DS-Lite CE """
7403
Matus Fabian69ce30d2018-08-22 01:27:10 -07007404 nat_config = self.vapi.nat_show_config()
7405 self.assertEqual(1, nat_config.dslite_ce)
7406
Juraj Slobodac5c6a332018-01-09 16:08:32 +01007407 b4_ip4 = '192.0.0.2'
7408 b4_ip4_n = socket.inet_pton(socket.AF_INET, b4_ip4)
7409 b4_ip6 = '2001:db8:62aa::375e:f4c1:1'
7410 b4_ip6_n = socket.inet_pton(socket.AF_INET6, b4_ip6)
7411 self.vapi.dslite_set_b4_addr(b4_ip6_n, b4_ip4_n)
7412
7413 aftr_ip4 = '192.0.0.1'
7414 aftr_ip4_n = socket.inet_pton(socket.AF_INET, aftr_ip4)
7415 aftr_ip6 = '2001:db8:85a3::8a2e:370:1'
7416 aftr_ip6_n = socket.inet_pton(socket.AF_INET6, aftr_ip6)
7417 self.vapi.dslite_set_aftr_addr(aftr_ip6_n, aftr_ip4_n)
7418
7419 self.vapi.ip_add_del_route(dst_address=aftr_ip6_n,
7420 dst_address_length=128,
7421 next_hop_address=self.pg1.remote_ip6n,
7422 next_hop_sw_if_index=self.pg1.sw_if_index,
7423 is_ipv6=1)
7424
7425 # UDP encapsulation
7426 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7427 IP(dst=self.pg1.remote_ip4, src=self.pg0.remote_ip4) /
7428 UDP(sport=10000, dport=20000))
7429 self.pg0.add_stream(p)
7430 self.pg_enable_capture(self.pg_interfaces)
7431 self.pg_start()
7432 capture = self.pg1.get_capture(1)
7433 capture = capture[0]
7434 self.assertEqual(capture[IPv6].src, b4_ip6)
7435 self.assertEqual(capture[IPv6].dst, aftr_ip6)
7436 self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
7437 self.assertEqual(capture[IP].dst, self.pg1.remote_ip4)
7438 self.assertEqual(capture[UDP].sport, 10000)
7439 self.assertEqual(capture[UDP].dport, 20000)
Klement Sekerad81ae412018-05-16 10:52:54 +02007440 self.assert_packet_checksums_valid(capture)
Juraj Slobodac5c6a332018-01-09 16:08:32 +01007441
7442 # UDP decapsulation
7443 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
7444 IPv6(dst=b4_ip6, src=aftr_ip6) /
7445 IP(dst=self.pg0.remote_ip4, src=self.pg1.remote_ip4) /
7446 UDP(sport=20000, dport=10000))
7447 self.pg1.add_stream(p)
7448 self.pg_enable_capture(self.pg_interfaces)
7449 self.pg_start()
7450 capture = self.pg0.get_capture(1)
7451 capture = capture[0]
7452 self.assertFalse(capture.haslayer(IPv6))
7453 self.assertEqual(capture[IP].src, self.pg1.remote_ip4)
7454 self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
7455 self.assertEqual(capture[UDP].sport, 20000)
7456 self.assertEqual(capture[UDP].dport, 10000)
Klement Sekerad81ae412018-05-16 10:52:54 +02007457 self.assert_packet_checksums_valid(capture)
Juraj Slobodac5c6a332018-01-09 16:08:32 +01007458
7459 # ping DS-Lite B4 tunnel endpoint address
7460 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
7461 IPv6(src=self.pg1.remote_hosts[0].ip6, dst=b4_ip6) /
7462 ICMPv6EchoRequest())
7463 self.pg1.add_stream(p)
7464 self.pg_enable_capture(self.pg_interfaces)
7465 self.pg_start()
7466 capture = self.pg1.get_capture(1)
Juraj Slobodac5c6a332018-01-09 16:08:32 +01007467 capture = capture[0]
7468 self.assertEqual(capture[IPv6].src, b4_ip6)
7469 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[0].ip6)
7470 self.assertTrue(capture.haslayer(ICMPv6EchoReply))
7471
7472 def tearDown(self):
7473 super(TestDSliteCE, self).tearDown()
7474 if not self.vpp_dead:
7475 self.logger.info(
7476 self.vapi.cli("show dslite aftr-tunnel-endpoint-address"))
7477 self.logger.info(
7478 self.vapi.cli("show dslite b4-tunnel-endpoint-address"))
7479
Matus Fabianf2a23cc2018-01-22 03:41:53 -08007480
7481class TestNAT66(MethodHolder):
7482 """ NAT66 Test Cases """
7483
7484 @classmethod
7485 def setUpClass(cls):
7486 super(TestNAT66, cls).setUpClass()
7487
7488 try:
7489 cls.nat_addr = 'fd01:ff::2'
7490 cls.nat_addr_n = socket.inet_pton(socket.AF_INET6, cls.nat_addr)
7491
7492 cls.create_pg_interfaces(range(2))
7493 cls.interfaces = list(cls.pg_interfaces)
7494
7495 for i in cls.interfaces:
7496 i.admin_up()
7497 i.config_ip6()
7498 i.configure_ipv6_neighbors()
7499
7500 except Exception:
7501 super(TestNAT66, cls).tearDownClass()
7502 raise
7503
7504 def test_static(self):
7505 """ 1:1 NAT66 test """
7506 self.vapi.nat66_add_del_interface(self.pg0.sw_if_index)
7507 self.vapi.nat66_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7508 self.vapi.nat66_add_del_static_mapping(self.pg0.remote_ip6n,
7509 self.nat_addr_n)
7510
7511 # in2out
7512 pkts = []
7513 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7514 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
7515 TCP())
7516 pkts.append(p)
7517 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7518 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
7519 UDP())
7520 pkts.append(p)
7521 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7522 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
7523 ICMPv6EchoRequest())
7524 pkts.append(p)
7525 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7526 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
7527 GRE() / IP() / TCP())
7528 pkts.append(p)
7529 self.pg0.add_stream(pkts)
7530 self.pg_enable_capture(self.pg_interfaces)
7531 self.pg_start()
7532 capture = self.pg1.get_capture(len(pkts))
7533 for packet in capture:
7534 try:
7535 self.assertEqual(packet[IPv6].src, self.nat_addr)
7536 self.assertEqual(packet[IPv6].dst, self.pg1.remote_ip6)
Klement Sekerad81ae412018-05-16 10:52:54 +02007537 self.assert_packet_checksums_valid(packet)
Matus Fabianf2a23cc2018-01-22 03:41:53 -08007538 except:
7539 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7540 raise
7541
7542 # out2in
7543 pkts = []
7544 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
7545 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
7546 TCP())
7547 pkts.append(p)
7548 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
7549 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
7550 UDP())
7551 pkts.append(p)
7552 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
7553 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
7554 ICMPv6EchoReply())
7555 pkts.append(p)
7556 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
7557 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
7558 GRE() / IP() / TCP())
7559 pkts.append(p)
7560 self.pg1.add_stream(pkts)
7561 self.pg_enable_capture(self.pg_interfaces)
7562 self.pg_start()
7563 capture = self.pg0.get_capture(len(pkts))
7564 for packet in capture:
7565 try:
7566 self.assertEqual(packet[IPv6].src, self.pg1.remote_ip6)
7567 self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
Klement Sekerad81ae412018-05-16 10:52:54 +02007568 self.assert_packet_checksums_valid(packet)
Matus Fabianf2a23cc2018-01-22 03:41:53 -08007569 except:
7570 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7571 raise
7572
7573 sm = self.vapi.nat66_static_mapping_dump()
7574 self.assertEqual(len(sm), 1)
7575 self.assertEqual(sm[0].total_pkts, 8)
7576
Juraj Sloboda9341e342018-04-13 12:00:46 +02007577 def test_check_no_translate(self):
7578 """ NAT66 translate only when egress interface is outside interface """
7579 self.vapi.nat66_add_del_interface(self.pg0.sw_if_index)
7580 self.vapi.nat66_add_del_interface(self.pg1.sw_if_index)
7581 self.vapi.nat66_add_del_static_mapping(self.pg0.remote_ip6n,
7582 self.nat_addr_n)
7583
7584 # in2out
7585 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7586 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
7587 UDP())
7588 self.pg0.add_stream([p])
7589 self.pg_enable_capture(self.pg_interfaces)
7590 self.pg_start()
7591 capture = self.pg1.get_capture(1)
7592 packet = capture[0]
7593 try:
7594 self.assertEqual(packet[IPv6].src, self.pg0.remote_ip6)
7595 self.assertEqual(packet[IPv6].dst, self.pg1.remote_ip6)
7596 except:
7597 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7598 raise
7599
Matus Fabianf2a23cc2018-01-22 03:41:53 -08007600 def clear_nat66(self):
7601 """
7602 Clear NAT66 configuration.
7603 """
7604 interfaces = self.vapi.nat66_interface_dump()
7605 for intf in interfaces:
7606 self.vapi.nat66_add_del_interface(intf.sw_if_index,
7607 intf.is_inside,
7608 is_add=0)
7609
7610 static_mappings = self.vapi.nat66_static_mapping_dump()
7611 for sm in static_mappings:
7612 self.vapi.nat66_add_del_static_mapping(sm.local_ip_address,
7613 sm.external_ip_address,
7614 sm.vrf_id,
7615 is_add=0)
7616
7617 def tearDown(self):
7618 super(TestNAT66, self).tearDown()
7619 if not self.vpp_dead:
7620 self.logger.info(self.vapi.cli("show nat66 interfaces"))
7621 self.logger.info(self.vapi.cli("show nat66 static mappings"))
7622 self.clear_nat66()
7623
Klement Sekerad81ae412018-05-16 10:52:54 +02007624
Matus Fabiande886752016-12-07 03:38:19 -08007625if __name__ == '__main__':
7626 unittest.main(testRunner=VppTestRunner)