blob: 9092b4796bb8f47ddaaf6a75594bb4eff8060ccc [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
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200625 def create_stream_frag(self, src_if, dst, sport, dport, data,
626 proto=IP_PROTOS.tcp, echo_reply=False):
Matus Fabianefcd1e92017-08-15 06:59:19 -0700627 """
628 Create fragmented packet stream
629
630 :param src_if: Source interface
631 :param dst: Destination IPv4 address
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200632 :param sport: Source port
633 :param dport: Destination port
Matus Fabianefcd1e92017-08-15 06:59:19 -0700634 :param data: Payload data
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200635 :param proto: protocol (TCP, UDP, ICMP)
636 :param echo_reply: use echo_reply if protocol is ICMP
Matus Fabianefcd1e92017-08-15 06:59:19 -0700637 :returns: Fragmets
638 """
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200639 if proto == IP_PROTOS.tcp:
640 p = (IP(src=src_if.remote_ip4, dst=dst) /
641 TCP(sport=sport, dport=dport) /
642 Raw(data))
643 p = p.__class__(str(p))
644 chksum = p['TCP'].chksum
645 proto_header = TCP(sport=sport, dport=dport, chksum=chksum)
646 elif proto == IP_PROTOS.udp:
647 proto_header = UDP(sport=sport, dport=dport)
648 elif proto == IP_PROTOS.icmp:
649 if not echo_reply:
650 proto_header = ICMP(id=sport, type='echo-request')
651 else:
652 proto_header = ICMP(id=sport, type='echo-reply')
653 else:
654 raise Exception("Unsupported protocol")
Matus Fabianefcd1e92017-08-15 06:59:19 -0700655 id = random.randint(0, 65535)
Matus Fabianefcd1e92017-08-15 06:59:19 -0700656 pkts = []
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200657 if proto == IP_PROTOS.tcp:
658 raw = Raw(data[0:4])
659 else:
660 raw = Raw(data[0:16])
Matus Fabianefcd1e92017-08-15 06:59:19 -0700661 p = (Ether(src=src_if.remote_mac, dst=src_if.local_mac) /
662 IP(src=src_if.remote_ip4, dst=dst, flags="MF", frag=0, id=id) /
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200663 proto_header /
664 raw)
Matus Fabianefcd1e92017-08-15 06:59:19 -0700665 pkts.append(p)
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200666 if proto == IP_PROTOS.tcp:
667 raw = Raw(data[4:20])
668 else:
669 raw = Raw(data[16:32])
Matus Fabianefcd1e92017-08-15 06:59:19 -0700670 p = (Ether(src=src_if.remote_mac, dst=src_if.local_mac) /
671 IP(src=src_if.remote_ip4, dst=dst, flags="MF", frag=3, id=id,
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200672 proto=proto) /
673 raw)
Matus Fabianefcd1e92017-08-15 06:59:19 -0700674 pkts.append(p)
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200675 if proto == IP_PROTOS.tcp:
676 raw = Raw(data[20:])
677 else:
678 raw = Raw(data[32:])
Matus Fabianefcd1e92017-08-15 06:59:19 -0700679 p = (Ether(src=src_if.remote_mac, dst=src_if.local_mac) /
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200680 IP(src=src_if.remote_ip4, dst=dst, frag=5, proto=proto,
Matus Fabianefcd1e92017-08-15 06:59:19 -0700681 id=id) /
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200682 raw)
Matus Fabianefcd1e92017-08-15 06:59:19 -0700683 pkts.append(p)
684 return pkts
685
686 def create_stream_frag_ip6(self, src_if, dst, sport, dport, data,
687 pref=None, plen=0, frag_size=128):
688 """
689 Create fragmented packet stream
690
691 :param src_if: Source interface
692 :param dst: Destination IPv4 address
693 :param sport: Source TCP port
694 :param dport: Destination TCP port
695 :param data: Payload data
696 :param pref: NAT64 prefix
697 :param plen: NAT64 prefix length
698 :param fragsize: size of fragments
699 :returns: Fragmets
700 """
701 if pref is None:
702 dst_ip6 = ''.join(['64:ff9b::', dst])
703 else:
704 dst_ip6 = self.compose_ip6(dst, pref, plen)
705
706 p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
707 IPv6(src=src_if.remote_ip6, dst=dst_ip6) /
708 IPv6ExtHdrFragment(id=random.randint(0, 65535)) /
709 TCP(sport=sport, dport=dport) /
710 Raw(data))
711
712 return fragment6(p, frag_size)
713
714 def reass_frags_and_verify(self, frags, src, dst):
715 """
716 Reassemble and verify fragmented packet
717
718 :param frags: Captured fragments
719 :param src: Source IPv4 address to verify
720 :param dst: Destination IPv4 address to verify
721
722 :returns: Reassembled IPv4 packet
723 """
724 buffer = StringIO.StringIO()
725 for p in frags:
726 self.assertEqual(p[IP].src, src)
727 self.assertEqual(p[IP].dst, dst)
Klement Sekerad81ae412018-05-16 10:52:54 +0200728 self.assert_ip_checksum_valid(p)
Matus Fabianefcd1e92017-08-15 06:59:19 -0700729 buffer.seek(p[IP].frag * 8)
730 buffer.write(p[IP].payload)
Matus Fabianefcd1e92017-08-15 06:59:19 -0700731 ip = IP(src=frags[0][IP].src, dst=frags[0][IP].dst,
732 proto=frags[0][IP].proto)
733 if ip.proto == IP_PROTOS.tcp:
734 p = (ip / TCP(buffer.getvalue()))
Klement Sekerad81ae412018-05-16 10:52:54 +0200735 self.assert_tcp_checksum_valid(p)
Matus Fabianefcd1e92017-08-15 06:59:19 -0700736 elif ip.proto == IP_PROTOS.udp:
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200737 p = (ip / UDP(buffer.getvalue()[:8]) /
738 Raw(buffer.getvalue()[8:]))
739 elif ip.proto == IP_PROTOS.icmp:
740 p = (ip / ICMP(buffer.getvalue()))
Matus Fabianefcd1e92017-08-15 06:59:19 -0700741 return p
742
743 def reass_frags_and_verify_ip6(self, frags, src, dst):
744 """
745 Reassemble and verify fragmented packet
746
747 :param frags: Captured fragments
748 :param src: Source IPv6 address to verify
749 :param dst: Destination IPv6 address to verify
750
751 :returns: Reassembled IPv6 packet
752 """
753 buffer = StringIO.StringIO()
754 for p in frags:
755 self.assertEqual(p[IPv6].src, src)
756 self.assertEqual(p[IPv6].dst, dst)
757 buffer.seek(p[IPv6ExtHdrFragment].offset * 8)
758 buffer.write(p[IPv6ExtHdrFragment].payload)
759 ip = IPv6(src=frags[0][IPv6].src, dst=frags[0][IPv6].dst,
760 nh=frags[0][IPv6ExtHdrFragment].nh)
761 if ip.nh == IP_PROTOS.tcp:
762 p = (ip / TCP(buffer.getvalue()))
Matus Fabianefcd1e92017-08-15 06:59:19 -0700763 elif ip.nh == IP_PROTOS.udp:
764 p = (ip / UDP(buffer.getvalue()))
Klement Sekerad81ae412018-05-16 10:52:54 +0200765 self.assert_packet_checksums_valid(p)
Matus Fabianefcd1e92017-08-15 06:59:19 -0700766 return p
767
Matus Fabianebdf1902018-05-04 03:57:42 -0700768 def initiate_tcp_session(self, in_if, out_if):
769 """
770 Initiates TCP session
771
772 :param in_if: Inside interface
773 :param out_if: Outside interface
774 """
775 try:
776 # SYN packet in->out
777 p = (Ether(src=in_if.remote_mac, dst=in_if.local_mac) /
778 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4) /
779 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
780 flags="S"))
781 in_if.add_stream(p)
782 self.pg_enable_capture(self.pg_interfaces)
783 self.pg_start()
784 capture = out_if.get_capture(1)
785 p = capture[0]
786 self.tcp_port_out = p[TCP].sport
787
788 # SYN + ACK packet out->in
789 p = (Ether(src=out_if.remote_mac, dst=out_if.local_mac) /
790 IP(src=out_if.remote_ip4, dst=self.nat_addr) /
791 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
792 flags="SA"))
793 out_if.add_stream(p)
794 self.pg_enable_capture(self.pg_interfaces)
795 self.pg_start()
796 in_if.get_capture(1)
797
798 # ACK packet in->out
799 p = (Ether(src=in_if.remote_mac, dst=in_if.local_mac) /
800 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4) /
801 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
802 flags="A"))
803 in_if.add_stream(p)
804 self.pg_enable_capture(self.pg_interfaces)
805 self.pg_start()
806 out_if.get_capture(1)
807
808 except:
809 self.logger.error("TCP 3 way handshake failed")
810 raise
811
Matus Fabianeea28d72017-01-13 04:15:54 -0800812 def verify_ipfix_nat44_ses(self, data):
813 """
814 Verify IPFIX NAT44 session create/delete event
815
816 :param data: Decoded IPFIX data records
817 """
818 nat44_ses_create_num = 0
819 nat44_ses_delete_num = 0
820 self.assertEqual(6, len(data))
821 for record in data:
822 # natEvent
823 self.assertIn(ord(record[230]), [4, 5])
824 if ord(record[230]) == 4:
825 nat44_ses_create_num += 1
826 else:
827 nat44_ses_delete_num += 1
828 # sourceIPv4Address
829 self.assertEqual(self.pg0.remote_ip4n, record[8])
830 # postNATSourceIPv4Address
Matus Fabian2ba92e32017-08-21 07:05:03 -0700831 self.assertEqual(socket.inet_pton(socket.AF_INET, self.nat_addr),
Matus Fabianeea28d72017-01-13 04:15:54 -0800832 record[225])
833 # ingressVRFID
834 self.assertEqual(struct.pack("!I", 0), record[234])
835 # protocolIdentifier/sourceTransportPort/postNAPTSourceTransportPort
836 if IP_PROTOS.icmp == ord(record[4]):
837 self.assertEqual(struct.pack("!H", self.icmp_id_in), record[7])
838 self.assertEqual(struct.pack("!H", self.icmp_id_out),
839 record[227])
840 elif IP_PROTOS.tcp == ord(record[4]):
841 self.assertEqual(struct.pack("!H", self.tcp_port_in),
842 record[7])
843 self.assertEqual(struct.pack("!H", self.tcp_port_out),
844 record[227])
845 elif IP_PROTOS.udp == ord(record[4]):
846 self.assertEqual(struct.pack("!H", self.udp_port_in),
847 record[7])
848 self.assertEqual(struct.pack("!H", self.udp_port_out),
849 record[227])
850 else:
851 self.fail("Invalid protocol")
852 self.assertEqual(3, nat44_ses_create_num)
853 self.assertEqual(3, nat44_ses_delete_num)
854
855 def verify_ipfix_addr_exhausted(self, data):
856 """
857 Verify IPFIX NAT addresses event
858
859 :param data: Decoded IPFIX data records
860 """
861 self.assertEqual(1, len(data))
862 record = data[0]
863 # natEvent
864 self.assertEqual(ord(record[230]), 3)
865 # natPoolID
866 self.assertEqual(struct.pack("!I", 0), record[283])
867
Matus Fabiana431ad12018-01-04 04:03:14 -0800868 def verify_ipfix_max_sessions(self, data, limit):
869 """
870 Verify IPFIX maximum session entries exceeded event
871
872 :param data: Decoded IPFIX data records
873 :param limit: Number of maximum session entries that can be created.
874 """
875 self.assertEqual(1, len(data))
876 record = data[0]
877 # natEvent
878 self.assertEqual(ord(record[230]), 13)
879 # natQuotaExceededEvent
880 self.assertEqual(struct.pack("I", 1), record[466])
881 # maxSessionEntries
882 self.assertEqual(struct.pack("I", limit), record[471])
883
884 def verify_ipfix_max_bibs(self, data, limit):
885 """
886 Verify IPFIX maximum BIB entries exceeded event
887
888 :param data: Decoded IPFIX data records
889 :param limit: Number of maximum BIB entries that can be created.
890 """
891 self.assertEqual(1, len(data))
892 record = data[0]
893 # natEvent
894 self.assertEqual(ord(record[230]), 13)
895 # natQuotaExceededEvent
896 self.assertEqual(struct.pack("I", 2), record[466])
897 # maxBIBEntries
898 self.assertEqual(struct.pack("I", limit), record[472])
899
900 def verify_ipfix_max_fragments_ip6(self, data, limit, src_addr):
901 """
902 Verify IPFIX maximum IPv6 fragments pending reassembly exceeded event
903
904 :param data: Decoded IPFIX data records
905 :param limit: Number of maximum fragments pending reassembly
906 :param src_addr: IPv6 source address
907 """
908 self.assertEqual(1, len(data))
909 record = data[0]
910 # natEvent
911 self.assertEqual(ord(record[230]), 13)
912 # natQuotaExceededEvent
913 self.assertEqual(struct.pack("I", 5), record[466])
914 # maxFragmentsPendingReassembly
915 self.assertEqual(struct.pack("I", limit), record[475])
916 # sourceIPv6Address
917 self.assertEqual(src_addr, record[27])
918
919 def verify_ipfix_max_fragments_ip4(self, data, limit, src_addr):
920 """
921 Verify IPFIX maximum IPv4 fragments pending reassembly exceeded event
922
923 :param data: Decoded IPFIX data records
924 :param limit: Number of maximum fragments pending reassembly
925 :param src_addr: IPv4 source address
926 """
927 self.assertEqual(1, len(data))
928 record = data[0]
929 # natEvent
930 self.assertEqual(ord(record[230]), 13)
931 # natQuotaExceededEvent
932 self.assertEqual(struct.pack("I", 5), record[466])
933 # maxFragmentsPendingReassembly
934 self.assertEqual(struct.pack("I", limit), record[475])
935 # sourceIPv4Address
936 self.assertEqual(src_addr, record[8])
937
938 def verify_ipfix_bib(self, data, is_create, src_addr):
939 """
940 Verify IPFIX NAT64 BIB create and delete events
941
942 :param data: Decoded IPFIX data records
943 :param is_create: Create event if nonzero value otherwise delete event
944 :param src_addr: IPv6 source address
945 """
946 self.assertEqual(1, len(data))
947 record = data[0]
948 # natEvent
949 if is_create:
950 self.assertEqual(ord(record[230]), 10)
951 else:
952 self.assertEqual(ord(record[230]), 11)
953 # sourceIPv6Address
954 self.assertEqual(src_addr, record[27])
955 # postNATSourceIPv4Address
956 self.assertEqual(self.nat_addr_n, record[225])
957 # protocolIdentifier
958 self.assertEqual(IP_PROTOS.tcp, ord(record[4]))
959 # ingressVRFID
960 self.assertEqual(struct.pack("!I", 0), record[234])
961 # sourceTransportPort
962 self.assertEqual(struct.pack("!H", self.tcp_port_in), record[7])
963 # postNAPTSourceTransportPort
964 self.assertEqual(struct.pack("!H", self.tcp_port_out), record[227])
965
966 def verify_ipfix_nat64_ses(self, data, is_create, src_addr, dst_addr,
967 dst_port):
968 """
969 Verify IPFIX NAT64 session create and delete events
970
971 :param data: Decoded IPFIX data records
972 :param is_create: Create event if nonzero value otherwise delete event
973 :param src_addr: IPv6 source address
974 :param dst_addr: IPv4 destination address
975 :param dst_port: destination TCP port
976 """
977 self.assertEqual(1, len(data))
978 record = data[0]
979 # natEvent
980 if is_create:
981 self.assertEqual(ord(record[230]), 6)
982 else:
983 self.assertEqual(ord(record[230]), 7)
984 # sourceIPv6Address
985 self.assertEqual(src_addr, record[27])
986 # destinationIPv6Address
987 self.assertEqual(socket.inet_pton(socket.AF_INET6,
988 self.compose_ip6(dst_addr,
989 '64:ff9b::',
990 96)),
991 record[28])
992 # postNATSourceIPv4Address
993 self.assertEqual(self.nat_addr_n, record[225])
994 # postNATDestinationIPv4Address
995 self.assertEqual(socket.inet_pton(socket.AF_INET, dst_addr),
996 record[226])
997 # protocolIdentifier
998 self.assertEqual(IP_PROTOS.tcp, ord(record[4]))
999 # ingressVRFID
1000 self.assertEqual(struct.pack("!I", 0), record[234])
1001 # sourceTransportPort
1002 self.assertEqual(struct.pack("!H", self.tcp_port_in), record[7])
1003 # postNAPTSourceTransportPort
1004 self.assertEqual(struct.pack("!H", self.tcp_port_out), record[227])
1005 # destinationTransportPort
1006 self.assertEqual(struct.pack("!H", dst_port), record[11])
1007 # postNAPTDestinationTransportPort
1008 self.assertEqual(struct.pack("!H", dst_port), record[228])
1009
Matus Fabian68ba8802018-08-08 05:52:47 -07001010 def verify_no_nat44_user(self):
1011 """ Verify that there is no NAT44 user """
1012 users = self.vapi.nat44_user_dump()
1013 self.assertEqual(len(users), 0)
1014
Matus Fabian878c6462018-08-23 00:33:35 -07001015 def verify_ipfix_max_entries_per_user(self, data, limit, src_addr):
1016 """
1017 Verify IPFIX maximum entries per user exceeded event
1018
1019 :param data: Decoded IPFIX data records
1020 :param limit: Number of maximum entries per user
1021 :param src_addr: IPv4 source address
1022 """
1023 self.assertEqual(1, len(data))
1024 record = data[0]
1025 # natEvent
1026 self.assertEqual(ord(record[230]), 13)
1027 # natQuotaExceededEvent
1028 self.assertEqual(struct.pack("I", 3), record[466])
1029 # maxEntriesPerUser
1030 self.assertEqual(struct.pack("I", limit), record[473])
1031 # sourceIPv4Address
1032 self.assertEqual(src_addr, record[8])
1033
Matus Fabianbb4e0222018-09-13 02:36:25 -07001034 def verify_mss_value(self, pkt, mss):
1035 """
1036 Verify TCP MSS value
1037
1038 :param pkt:
1039 :param mss:
1040 """
1041 if not pkt.haslayer(IP) or not pkt.haslayer(TCP):
1042 raise TypeError("Not a TCP/IP packet")
1043
1044 for option in pkt[TCP].options:
1045 if option[0] == 'MSS':
1046 self.assertEqual(option[1], mss)
1047 self.assert_tcp_checksum_valid(pkt)
1048
Juraj Slobodafe0aa762018-07-23 12:22:54 +02001049 @staticmethod
1050 def proto2layer(proto):
1051 if proto == IP_PROTOS.tcp:
1052 return TCP
1053 elif proto == IP_PROTOS.udp:
1054 return UDP
1055 elif proto == IP_PROTOS.icmp:
1056 return ICMP
1057 else:
1058 raise Exception("Unsupported protocol")
1059
1060 def frag_in_order(self, proto=IP_PROTOS.tcp, dont_translate=False):
1061 layer = self.proto2layer(proto)
1062
1063 if proto == IP_PROTOS.tcp:
1064 data = "A" * 4 + "B" * 16 + "C" * 3
1065 else:
1066 data = "A" * 16 + "B" * 16 + "C" * 3
1067 self.port_in = random.randint(1025, 65535)
1068
1069 reass = self.vapi.nat_reass_dump()
1070 reass_n_start = len(reass)
1071
1072 # in2out
1073 pkts = self.create_stream_frag(self.pg0,
1074 self.pg1.remote_ip4,
1075 self.port_in,
1076 20,
1077 data,
1078 proto)
1079 self.pg0.add_stream(pkts)
1080 self.pg_enable_capture(self.pg_interfaces)
1081 self.pg_start()
1082 frags = self.pg1.get_capture(len(pkts))
1083 if not dont_translate:
1084 p = self.reass_frags_and_verify(frags,
1085 self.nat_addr,
1086 self.pg1.remote_ip4)
1087 else:
1088 p = self.reass_frags_and_verify(frags,
1089 self.pg0.remote_ip4,
1090 self.pg1.remote_ip4)
1091 if proto != IP_PROTOS.icmp:
1092 if not dont_translate:
1093 self.assertEqual(p[layer].dport, 20)
1094 self.assertNotEqual(p[layer].sport, self.port_in)
1095 else:
1096 self.assertEqual(p[layer].sport, self.port_in)
1097 else:
1098 if not dont_translate:
1099 self.assertNotEqual(p[layer].id, self.port_in)
1100 else:
1101 self.assertEqual(p[layer].id, self.port_in)
1102 self.assertEqual(data, p[Raw].load)
1103
1104 # out2in
1105 if not dont_translate:
1106 dst_addr = self.nat_addr
1107 else:
1108 dst_addr = self.pg0.remote_ip4
1109 if proto != IP_PROTOS.icmp:
1110 sport = 20
1111 dport = p[layer].sport
1112 else:
1113 sport = p[layer].id
1114 dport = 0
1115 pkts = self.create_stream_frag(self.pg1,
1116 dst_addr,
1117 sport,
1118 dport,
1119 data,
1120 proto,
1121 echo_reply=True)
1122 self.pg1.add_stream(pkts)
1123 self.pg_enable_capture(self.pg_interfaces)
1124 self.pg_start()
1125 frags = self.pg0.get_capture(len(pkts))
1126 p = self.reass_frags_and_verify(frags,
1127 self.pg1.remote_ip4,
1128 self.pg0.remote_ip4)
1129 if proto != IP_PROTOS.icmp:
1130 self.assertEqual(p[layer].sport, 20)
1131 self.assertEqual(p[layer].dport, self.port_in)
1132 else:
1133 self.assertEqual(p[layer].id, self.port_in)
1134 self.assertEqual(data, p[Raw].load)
1135
1136 reass = self.vapi.nat_reass_dump()
1137 reass_n_end = len(reass)
1138
1139 self.assertEqual(reass_n_end - reass_n_start, 2)
1140
1141 def frag_in_order_in_plus_out(self, proto=IP_PROTOS.tcp):
1142 layer = self.proto2layer(proto)
1143
1144 if proto == IP_PROTOS.tcp:
1145 data = "A" * 4 + "B" * 16 + "C" * 3
1146 else:
1147 data = "A" * 16 + "B" * 16 + "C" * 3
1148 self.port_in = random.randint(1025, 65535)
1149
1150 for i in range(2):
1151 reass = self.vapi.nat_reass_dump()
1152 reass_n_start = len(reass)
1153
1154 # out2in
1155 pkts = self.create_stream_frag(self.pg0,
1156 self.server_out_addr,
1157 self.port_in,
1158 self.server_out_port,
1159 data,
1160 proto)
1161 self.pg0.add_stream(pkts)
1162 self.pg_enable_capture(self.pg_interfaces)
1163 self.pg_start()
1164 frags = self.pg1.get_capture(len(pkts))
1165 p = self.reass_frags_and_verify(frags,
1166 self.pg0.remote_ip4,
1167 self.server_in_addr)
1168 if proto != IP_PROTOS.icmp:
1169 self.assertEqual(p[layer].sport, self.port_in)
1170 self.assertEqual(p[layer].dport, self.server_in_port)
1171 else:
1172 self.assertEqual(p[layer].id, self.port_in)
1173 self.assertEqual(data, p[Raw].load)
1174
1175 # in2out
1176 if proto != IP_PROTOS.icmp:
1177 pkts = self.create_stream_frag(self.pg1,
1178 self.pg0.remote_ip4,
1179 self.server_in_port,
1180 p[layer].sport,
1181 data,
1182 proto)
1183 else:
1184 pkts = self.create_stream_frag(self.pg1,
1185 self.pg0.remote_ip4,
1186 p[layer].id,
1187 0,
1188 data,
1189 proto,
1190 echo_reply=True)
1191 self.pg1.add_stream(pkts)
1192 self.pg_enable_capture(self.pg_interfaces)
1193 self.pg_start()
1194 frags = self.pg0.get_capture(len(pkts))
1195 p = self.reass_frags_and_verify(frags,
1196 self.server_out_addr,
1197 self.pg0.remote_ip4)
1198 if proto != IP_PROTOS.icmp:
1199 self.assertEqual(p[layer].sport, self.server_out_port)
1200 self.assertEqual(p[layer].dport, self.port_in)
1201 else:
1202 self.assertEqual(p[layer].id, self.port_in)
1203 self.assertEqual(data, p[Raw].load)
1204
1205 reass = self.vapi.nat_reass_dump()
1206 reass_n_end = len(reass)
1207
1208 self.assertEqual(reass_n_end - reass_n_start, 2)
1209
1210 def reass_hairpinning(self, proto=IP_PROTOS.tcp):
1211 layer = self.proto2layer(proto)
1212
1213 if proto == IP_PROTOS.tcp:
1214 data = "A" * 4 + "B" * 16 + "C" * 3
1215 else:
1216 data = "A" * 16 + "B" * 16 + "C" * 3
1217
1218 # send packet from host to server
1219 pkts = self.create_stream_frag(self.pg0,
1220 self.nat_addr,
1221 self.host_in_port,
1222 self.server_out_port,
1223 data,
1224 proto)
1225 self.pg0.add_stream(pkts)
1226 self.pg_enable_capture(self.pg_interfaces)
1227 self.pg_start()
1228 frags = self.pg0.get_capture(len(pkts))
1229 p = self.reass_frags_and_verify(frags,
1230 self.nat_addr,
1231 self.server.ip4)
1232 if proto != IP_PROTOS.icmp:
1233 self.assertNotEqual(p[layer].sport, self.host_in_port)
1234 self.assertEqual(p[layer].dport, self.server_in_port)
1235 else:
1236 self.assertNotEqual(p[layer].id, self.host_in_port)
1237 self.assertEqual(data, p[Raw].load)
1238
1239 def frag_out_of_order(self, proto=IP_PROTOS.tcp, dont_translate=False):
1240 layer = self.proto2layer(proto)
1241
1242 if proto == IP_PROTOS.tcp:
1243 data = "A" * 4 + "B" * 16 + "C" * 3
1244 else:
1245 data = "A" * 16 + "B" * 16 + "C" * 3
1246 self.port_in = random.randint(1025, 65535)
1247
1248 for i in range(2):
1249 # in2out
1250 pkts = self.create_stream_frag(self.pg0,
1251 self.pg1.remote_ip4,
1252 self.port_in,
1253 20,
1254 data,
1255 proto)
1256 pkts.reverse()
1257 self.pg0.add_stream(pkts)
1258 self.pg_enable_capture(self.pg_interfaces)
1259 self.pg_start()
1260 frags = self.pg1.get_capture(len(pkts))
1261 if not dont_translate:
1262 p = self.reass_frags_and_verify(frags,
1263 self.nat_addr,
1264 self.pg1.remote_ip4)
1265 else:
1266 p = self.reass_frags_and_verify(frags,
1267 self.pg0.remote_ip4,
1268 self.pg1.remote_ip4)
1269 if proto != IP_PROTOS.icmp:
1270 if not dont_translate:
1271 self.assertEqual(p[layer].dport, 20)
1272 self.assertNotEqual(p[layer].sport, self.port_in)
1273 else:
1274 self.assertEqual(p[layer].sport, self.port_in)
1275 else:
1276 if not dont_translate:
1277 self.assertNotEqual(p[layer].id, self.port_in)
1278 else:
1279 self.assertEqual(p[layer].id, self.port_in)
1280 self.assertEqual(data, p[Raw].load)
1281
1282 # out2in
1283 if not dont_translate:
1284 dst_addr = self.nat_addr
1285 else:
1286 dst_addr = self.pg0.remote_ip4
1287 if proto != IP_PROTOS.icmp:
1288 sport = 20
1289 dport = p[layer].sport
1290 else:
1291 sport = p[layer].id
1292 dport = 0
1293 pkts = self.create_stream_frag(self.pg1,
1294 dst_addr,
1295 sport,
1296 dport,
1297 data,
1298 proto,
1299 echo_reply=True)
1300 pkts.reverse()
1301 self.pg1.add_stream(pkts)
1302 self.pg_enable_capture(self.pg_interfaces)
1303 self.pg_start()
1304 frags = self.pg0.get_capture(len(pkts))
1305 p = self.reass_frags_and_verify(frags,
1306 self.pg1.remote_ip4,
1307 self.pg0.remote_ip4)
1308 if proto != IP_PROTOS.icmp:
1309 self.assertEqual(p[layer].sport, 20)
1310 self.assertEqual(p[layer].dport, self.port_in)
1311 else:
1312 self.assertEqual(p[layer].id, self.port_in)
1313 self.assertEqual(data, p[Raw].load)
1314
1315 def frag_out_of_order_in_plus_out(self, proto=IP_PROTOS.tcp):
1316 layer = self.proto2layer(proto)
1317
1318 if proto == IP_PROTOS.tcp:
1319 data = "A" * 4 + "B" * 16 + "C" * 3
1320 else:
1321 data = "A" * 16 + "B" * 16 + "C" * 3
1322 self.port_in = random.randint(1025, 65535)
1323
1324 for i in range(2):
1325 # out2in
1326 pkts = self.create_stream_frag(self.pg0,
1327 self.server_out_addr,
1328 self.port_in,
1329 self.server_out_port,
1330 data,
1331 proto)
1332 pkts.reverse()
1333 self.pg0.add_stream(pkts)
1334 self.pg_enable_capture(self.pg_interfaces)
1335 self.pg_start()
1336 frags = self.pg1.get_capture(len(pkts))
1337 p = self.reass_frags_and_verify(frags,
1338 self.pg0.remote_ip4,
1339 self.server_in_addr)
1340 if proto != IP_PROTOS.icmp:
1341 self.assertEqual(p[layer].dport, self.server_in_port)
1342 self.assertEqual(p[layer].sport, self.port_in)
1343 self.assertEqual(p[layer].dport, self.server_in_port)
1344 else:
1345 self.assertEqual(p[layer].id, self.port_in)
1346 self.assertEqual(data, p[Raw].load)
1347
1348 # in2out
1349 if proto != IP_PROTOS.icmp:
1350 pkts = self.create_stream_frag(self.pg1,
1351 self.pg0.remote_ip4,
1352 self.server_in_port,
1353 p[layer].sport,
1354 data,
1355 proto)
1356 else:
1357 pkts = self.create_stream_frag(self.pg1,
1358 self.pg0.remote_ip4,
1359 p[layer].id,
1360 0,
1361 data,
1362 proto,
1363 echo_reply=True)
1364 pkts.reverse()
1365 self.pg1.add_stream(pkts)
1366 self.pg_enable_capture(self.pg_interfaces)
1367 self.pg_start()
1368 frags = self.pg0.get_capture(len(pkts))
1369 p = self.reass_frags_and_verify(frags,
1370 self.server_out_addr,
1371 self.pg0.remote_ip4)
1372 if proto != IP_PROTOS.icmp:
1373 self.assertEqual(p[layer].sport, self.server_out_port)
1374 self.assertEqual(p[layer].dport, self.port_in)
1375 else:
1376 self.assertEqual(p[layer].id, self.port_in)
1377 self.assertEqual(data, p[Raw].load)
1378
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001379
Matus Fabian2ba92e32017-08-21 07:05:03 -07001380class TestNAT44(MethodHolder):
1381 """ NAT44 Test Cases """
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001382
1383 @classmethod
1384 def setUpClass(cls):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001385 super(TestNAT44, cls).setUpClass()
Matus Fabian229c1aa2018-05-28 04:09:52 -07001386 cls.vapi.cli("set log class nat level debug")
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001387
1388 try:
1389 cls.tcp_port_in = 6303
1390 cls.tcp_port_out = 6303
1391 cls.udp_port_in = 6304
1392 cls.udp_port_out = 6304
1393 cls.icmp_id_in = 6305
1394 cls.icmp_id_out = 6305
Matus Fabian2ba92e32017-08-21 07:05:03 -07001395 cls.nat_addr = '10.0.0.3'
Juraj Sloboda7b929792017-11-23 13:20:48 +01001396 cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
Matus Fabian6631e9c2017-05-24 01:52:20 -07001397 cls.ipfix_src_port = 4739
1398 cls.ipfix_domain_id = 1
Matus Fabianebdf1902018-05-04 03:57:42 -07001399 cls.tcp_external_port = 80
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001400
Matus Fabian36ea2d62017-10-24 04:13:49 -07001401 cls.create_pg_interfaces(range(10))
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001402 cls.interfaces = list(cls.pg_interfaces[0:4])
1403
1404 for i in cls.interfaces:
1405 i.admin_up()
1406 i.config_ip4()
1407 i.resolve_arp()
1408
Matus Fabian6fa74c62017-06-05 05:55:48 -07001409 cls.pg0.generate_remote_hosts(3)
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001410 cls.pg0.configure_ipv4_neighbors()
1411
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02001412 cls.pg1.generate_remote_hosts(1)
1413 cls.pg1.configure_ipv4_neighbors()
1414
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001415 cls.overlapping_interfaces = list(list(cls.pg_interfaces[4:7]))
Neale Ranns15002542017-09-10 04:39:11 -07001416 cls.vapi.ip_table_add_del(10, is_add=1)
1417 cls.vapi.ip_table_add_del(20, is_add=1)
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001418
1419 cls.pg4._local_ip4 = "172.16.255.1"
1420 cls.pg4._local_ip4n = socket.inet_pton(socket.AF_INET, i.local_ip4)
1421 cls.pg4._remote_hosts[0]._ip4 = "172.16.255.2"
1422 cls.pg4.set_table_ip4(10)
Matus Fabian69126282017-08-14 23:39:58 -07001423 cls.pg5._local_ip4 = "172.17.255.3"
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001424 cls.pg5._local_ip4n = socket.inet_pton(socket.AF_INET, i.local_ip4)
Matus Fabian69126282017-08-14 23:39:58 -07001425 cls.pg5._remote_hosts[0]._ip4 = "172.17.255.4"
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001426 cls.pg5.set_table_ip4(10)
1427 cls.pg6._local_ip4 = "172.16.255.1"
1428 cls.pg6._local_ip4n = socket.inet_pton(socket.AF_INET, i.local_ip4)
1429 cls.pg6._remote_hosts[0]._ip4 = "172.16.255.2"
1430 cls.pg6.set_table_ip4(20)
1431 for i in cls.overlapping_interfaces:
1432 i.config_ip4()
1433 i.admin_up()
1434 i.resolve_arp()
1435
1436 cls.pg7.admin_up()
Martin Gálik406eb1d2017-05-04 04:35:04 -07001437 cls.pg8.admin_up()
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001438
Matus Fabian36ea2d62017-10-24 04:13:49 -07001439 cls.pg9.generate_remote_hosts(2)
1440 cls.pg9.config_ip4()
1441 ip_addr_n = socket.inet_pton(socket.AF_INET, "10.0.0.1")
1442 cls.vapi.sw_interface_add_del_address(cls.pg9.sw_if_index,
1443 ip_addr_n,
1444 24)
1445 cls.pg9.admin_up()
1446 cls.pg9.resolve_arp()
1447 cls.pg9._remote_hosts[1]._ip4 = cls.pg9._remote_hosts[0]._ip4
1448 cls.pg4._remote_ip4 = cls.pg9._remote_hosts[0]._ip4 = "10.0.0.2"
1449 cls.pg9.resolve_arp()
1450
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001451 except Exception:
Matus Fabian2ba92e32017-08-21 07:05:03 -07001452 super(TestNAT44, cls).tearDownClass()
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001453 raise
1454
Matus Fabiande886752016-12-07 03:38:19 -08001455 def test_dynamic(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001456 """ NAT44 dynamic translation test """
Matus Fabiande886752016-12-07 03:38:19 -08001457
Matus Fabian2ba92e32017-08-21 07:05:03 -07001458 self.nat44_add_address(self.nat_addr)
1459 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1460 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1461 is_inside=0)
Matus Fabiande886752016-12-07 03:38:19 -08001462
1463 # in2out
1464 pkts = self.create_stream_in(self.pg0, self.pg1)
1465 self.pg0.add_stream(pkts)
1466 self.pg_enable_capture(self.pg_interfaces)
1467 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001468 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001469 self.verify_capture_out(capture)
1470
1471 # 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
Juraj Slobodab33f4132017-02-08 23:54:21 -08001479 def test_dynamic_icmp_errors_in2out_ttl_1(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001480 """ NAT44 handling of client packets with TTL=1 """
Juraj Slobodab33f4132017-02-08 23:54:21 -08001481
Matus Fabian2ba92e32017-08-21 07:05:03 -07001482 self.nat44_add_address(self.nat_addr)
1483 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1484 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1485 is_inside=0)
Juraj Slobodab33f4132017-02-08 23:54:21 -08001486
1487 # Client side - generate traffic
1488 pkts = self.create_stream_in(self.pg0, self.pg1, ttl=1)
1489 self.pg0.add_stream(pkts)
1490 self.pg_enable_capture(self.pg_interfaces)
1491 self.pg_start()
1492
1493 # Client side - verify ICMP type 11 packets
1494 capture = self.pg0.get_capture(len(pkts))
1495 self.verify_capture_in_with_icmp_errors(capture, self.pg0)
1496
1497 def test_dynamic_icmp_errors_out2in_ttl_1(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001498 """ NAT44 handling of server packets with TTL=1 """
Juraj Slobodab33f4132017-02-08 23:54:21 -08001499
Matus Fabian2ba92e32017-08-21 07:05:03 -07001500 self.nat44_add_address(self.nat_addr)
1501 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1502 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1503 is_inside=0)
Juraj Slobodab33f4132017-02-08 23:54:21 -08001504
1505 # Client side - create sessions
1506 pkts = self.create_stream_in(self.pg0, self.pg1)
1507 self.pg0.add_stream(pkts)
1508 self.pg_enable_capture(self.pg_interfaces)
1509 self.pg_start()
1510
1511 # Server side - generate traffic
1512 capture = self.pg1.get_capture(len(pkts))
1513 self.verify_capture_out(capture)
1514 pkts = self.create_stream_out(self.pg1, ttl=1)
1515 self.pg1.add_stream(pkts)
1516 self.pg_enable_capture(self.pg_interfaces)
1517 self.pg_start()
1518
1519 # Server side - verify ICMP type 11 packets
1520 capture = self.pg1.get_capture(len(pkts))
1521 self.verify_capture_out_with_icmp_errors(capture,
1522 src_ip=self.pg1.local_ip4)
1523
1524 def test_dynamic_icmp_errors_in2out_ttl_2(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001525 """ NAT44 handling of error responses to client packets with TTL=2 """
Juraj Slobodab33f4132017-02-08 23:54:21 -08001526
Matus Fabian2ba92e32017-08-21 07:05:03 -07001527 self.nat44_add_address(self.nat_addr)
1528 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1529 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1530 is_inside=0)
Juraj Slobodab33f4132017-02-08 23:54:21 -08001531
1532 # Client side - generate traffic
1533 pkts = self.create_stream_in(self.pg0, self.pg1, ttl=2)
1534 self.pg0.add_stream(pkts)
1535 self.pg_enable_capture(self.pg_interfaces)
1536 self.pg_start()
1537
1538 # Server side - simulate ICMP type 11 response
1539 capture = self.pg1.get_capture(len(pkts))
1540 pkts = [Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07001541 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Juraj Slobodab33f4132017-02-08 23:54:21 -08001542 ICMP(type=11) / packet[IP] for packet in capture]
1543 self.pg1.add_stream(pkts)
1544 self.pg_enable_capture(self.pg_interfaces)
1545 self.pg_start()
1546
1547 # Client side - verify ICMP type 11 packets
1548 capture = self.pg0.get_capture(len(pkts))
1549 self.verify_capture_in_with_icmp_errors(capture, self.pg0)
1550
1551 def test_dynamic_icmp_errors_out2in_ttl_2(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001552 """ NAT44 handling of error responses to server packets with TTL=2 """
Juraj Slobodab33f4132017-02-08 23:54:21 -08001553
Matus Fabian2ba92e32017-08-21 07:05:03 -07001554 self.nat44_add_address(self.nat_addr)
1555 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1556 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1557 is_inside=0)
Juraj Slobodab33f4132017-02-08 23:54:21 -08001558
1559 # Client side - create sessions
1560 pkts = self.create_stream_in(self.pg0, self.pg1)
1561 self.pg0.add_stream(pkts)
1562 self.pg_enable_capture(self.pg_interfaces)
1563 self.pg_start()
1564
1565 # Server side - generate traffic
1566 capture = self.pg1.get_capture(len(pkts))
1567 self.verify_capture_out(capture)
1568 pkts = self.create_stream_out(self.pg1, ttl=2)
1569 self.pg1.add_stream(pkts)
1570 self.pg_enable_capture(self.pg_interfaces)
1571 self.pg_start()
1572
1573 # Client side - simulate ICMP type 11 response
1574 capture = self.pg0.get_capture(len(pkts))
1575 pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1576 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
1577 ICMP(type=11) / packet[IP] for packet in capture]
1578 self.pg0.add_stream(pkts)
1579 self.pg_enable_capture(self.pg_interfaces)
1580 self.pg_start()
1581
1582 # Server side - verify ICMP type 11 packets
1583 capture = self.pg1.get_capture(len(pkts))
1584 self.verify_capture_out_with_icmp_errors(capture)
1585
Juraj Sloboda665e4822017-02-16 17:17:19 -08001586 def test_ping_out_interface_from_outside(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001587 """ Ping NAT44 out interface from outside network """
Juraj Sloboda665e4822017-02-16 17:17:19 -08001588
Matus Fabian2ba92e32017-08-21 07:05:03 -07001589 self.nat44_add_address(self.nat_addr)
1590 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1591 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1592 is_inside=0)
Juraj Sloboda665e4822017-02-16 17:17:19 -08001593
1594 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1595 IP(src=self.pg1.remote_ip4, dst=self.pg1.local_ip4) /
1596 ICMP(id=self.icmp_id_out, type='echo-request'))
1597 pkts = [p]
1598 self.pg1.add_stream(pkts)
1599 self.pg_enable_capture(self.pg_interfaces)
1600 self.pg_start()
1601 capture = self.pg1.get_capture(len(pkts))
Juraj Sloboda665e4822017-02-16 17:17:19 -08001602 packet = capture[0]
1603 try:
1604 self.assertEqual(packet[IP].src, self.pg1.local_ip4)
1605 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
1606 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
1607 self.assertEqual(packet[ICMP].type, 0) # echo reply
1608 except:
1609 self.logger.error(ppp("Unexpected or invalid packet "
1610 "(outside network):", packet))
1611 raise
1612
Juraj Slobodad3677682017-04-14 03:24:45 +02001613 def test_ping_internal_host_from_outside(self):
1614 """ Ping internal host from outside network """
1615
Matus Fabian2ba92e32017-08-21 07:05:03 -07001616 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr)
1617 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1618 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1619 is_inside=0)
Juraj Slobodad3677682017-04-14 03:24:45 +02001620
1621 # out2in
1622 pkt = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07001623 IP(src=self.pg1.remote_ip4, dst=self.nat_addr, ttl=64) /
Juraj Slobodad3677682017-04-14 03:24:45 +02001624 ICMP(id=self.icmp_id_out, type='echo-request'))
1625 self.pg1.add_stream(pkt)
1626 self.pg_enable_capture(self.pg_interfaces)
1627 self.pg_start()
1628 capture = self.pg0.get_capture(1)
Matus Fabian05ca4a32018-09-04 23:45:13 -07001629 self.verify_capture_in(capture, self.pg0)
Juraj Slobodad3677682017-04-14 03:24:45 +02001630 self.assert_equal(capture[0][IP].proto, IP_PROTOS.icmp)
1631
1632 # in2out
1633 pkt = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1634 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4, ttl=64) /
1635 ICMP(id=self.icmp_id_in, type='echo-reply'))
1636 self.pg0.add_stream(pkt)
1637 self.pg_enable_capture(self.pg_interfaces)
1638 self.pg_start()
1639 capture = self.pg1.get_capture(1)
Matus Fabian05ca4a32018-09-04 23:45:13 -07001640 self.verify_capture_out(capture, same_port=True)
Juraj Slobodad3677682017-04-14 03:24:45 +02001641 self.assert_equal(capture[0][IP].proto, IP_PROTOS.icmp)
1642
Matus Fabianc79396e2018-07-23 00:05:22 -07001643 def test_forwarding(self):
Juraj Sloboda7b929792017-11-23 13:20:48 +01001644 """ NAT44 forwarding test """
1645
1646 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1647 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1648 is_inside=0)
1649 self.vapi.nat44_forwarding_enable_disable(1)
1650
1651 real_ip = self.pg0.remote_ip4n
1652 alias_ip = self.nat_addr_n
1653 self.vapi.nat44_add_del_static_mapping(local_ip=real_ip,
1654 external_ip=alias_ip)
1655
1656 try:
Matus Fabianc79396e2018-07-23 00:05:22 -07001657 # static mapping match
Juraj Sloboda7b929792017-11-23 13:20:48 +01001658
1659 pkts = self.create_stream_out(self.pg1)
1660 self.pg1.add_stream(pkts)
1661 self.pg_enable_capture(self.pg_interfaces)
1662 self.pg_start()
1663 capture = self.pg0.get_capture(len(pkts))
1664 self.verify_capture_in(capture, self.pg0)
1665
1666 pkts = self.create_stream_in(self.pg0, self.pg1)
1667 self.pg0.add_stream(pkts)
1668 self.pg_enable_capture(self.pg_interfaces)
1669 self.pg_start()
1670 capture = self.pg1.get_capture(len(pkts))
1671 self.verify_capture_out(capture, same_port=True)
1672
Matus Fabianc79396e2018-07-23 00:05:22 -07001673 # no static mapping match
Juraj Sloboda7b929792017-11-23 13:20:48 +01001674
1675 host0 = self.pg0.remote_hosts[0]
1676 self.pg0.remote_hosts[0] = self.pg0.remote_hosts[1]
1677 try:
1678 pkts = self.create_stream_out(self.pg1,
1679 dst_ip=self.pg0.remote_ip4,
1680 use_inside_ports=True)
1681 self.pg1.add_stream(pkts)
1682 self.pg_enable_capture(self.pg_interfaces)
1683 self.pg_start()
1684 capture = self.pg0.get_capture(len(pkts))
1685 self.verify_capture_in(capture, self.pg0)
1686
1687 pkts = self.create_stream_in(self.pg0, self.pg1)
1688 self.pg0.add_stream(pkts)
1689 self.pg_enable_capture(self.pg_interfaces)
1690 self.pg_start()
1691 capture = self.pg1.get_capture(len(pkts))
1692 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
1693 same_port=True)
1694 finally:
1695 self.pg0.remote_hosts[0] = host0
1696
1697 finally:
1698 self.vapi.nat44_forwarding_enable_disable(0)
1699 self.vapi.nat44_add_del_static_mapping(local_ip=real_ip,
1700 external_ip=alias_ip,
1701 is_add=0)
1702
Matus Fabiande886752016-12-07 03:38:19 -08001703 def test_static_in(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001704 """ 1:1 NAT initialized from inside network """
Matus Fabiande886752016-12-07 03:38:19 -08001705
1706 nat_ip = "10.0.0.10"
1707 self.tcp_port_out = 6303
1708 self.udp_port_out = 6304
1709 self.icmp_id_out = 6305
1710
Matus Fabian2ba92e32017-08-21 07:05:03 -07001711 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
1712 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1713 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1714 is_inside=0)
Matus Fabian5f224992018-01-25 21:59:16 -08001715 sm = self.vapi.nat44_static_mapping_dump()
1716 self.assertEqual(len(sm), 1)
1717 self.assertEqual((sm[0].tag).split('\0', 1)[0], '')
Matus Fabian9dba7812018-01-31 01:13:23 -08001718 self.assertEqual(sm[0].protocol, 0)
1719 self.assertEqual(sm[0].local_port, 0)
1720 self.assertEqual(sm[0].external_port, 0)
Matus Fabiande886752016-12-07 03:38:19 -08001721
1722 # in2out
1723 pkts = self.create_stream_in(self.pg0, self.pg1)
1724 self.pg0.add_stream(pkts)
1725 self.pg_enable_capture(self.pg_interfaces)
1726 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001727 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001728 self.verify_capture_out(capture, nat_ip, True)
1729
1730 # out2in
1731 pkts = self.create_stream_out(self.pg1, nat_ip)
1732 self.pg1.add_stream(pkts)
1733 self.pg_enable_capture(self.pg_interfaces)
1734 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001735 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001736 self.verify_capture_in(capture, self.pg0)
1737
1738 def test_static_out(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001739 """ 1:1 NAT initialized from outside network """
Matus Fabiande886752016-12-07 03:38:19 -08001740
1741 nat_ip = "10.0.0.20"
1742 self.tcp_port_out = 6303
1743 self.udp_port_out = 6304
1744 self.icmp_id_out = 6305
Matus Fabian5f224992018-01-25 21:59:16 -08001745 tag = "testTAG"
Matus Fabiande886752016-12-07 03:38:19 -08001746
Matus Fabian5f224992018-01-25 21:59:16 -08001747 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip, tag=tag)
Matus Fabian2ba92e32017-08-21 07:05:03 -07001748 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1749 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1750 is_inside=0)
Matus Fabian5f224992018-01-25 21:59:16 -08001751 sm = self.vapi.nat44_static_mapping_dump()
1752 self.assertEqual(len(sm), 1)
1753 self.assertEqual((sm[0].tag).split('\0', 1)[0], tag)
Matus Fabiande886752016-12-07 03:38:19 -08001754
1755 # out2in
1756 pkts = self.create_stream_out(self.pg1, nat_ip)
1757 self.pg1.add_stream(pkts)
1758 self.pg_enable_capture(self.pg_interfaces)
1759 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001760 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001761 self.verify_capture_in(capture, self.pg0)
1762
1763 # in2out
1764 pkts = self.create_stream_in(self.pg0, self.pg1)
1765 self.pg0.add_stream(pkts)
1766 self.pg_enable_capture(self.pg_interfaces)
1767 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001768 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001769 self.verify_capture_out(capture, nat_ip, True)
1770
1771 def test_static_with_port_in(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001772 """ 1:1 NAPT initialized from inside network """
Matus Fabiande886752016-12-07 03:38:19 -08001773
1774 self.tcp_port_out = 3606
1775 self.udp_port_out = 3607
1776 self.icmp_id_out = 3608
1777
Matus Fabian2ba92e32017-08-21 07:05:03 -07001778 self.nat44_add_address(self.nat_addr)
1779 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1780 self.tcp_port_in, self.tcp_port_out,
1781 proto=IP_PROTOS.tcp)
1782 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1783 self.udp_port_in, self.udp_port_out,
1784 proto=IP_PROTOS.udp)
1785 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1786 self.icmp_id_in, self.icmp_id_out,
1787 proto=IP_PROTOS.icmp)
1788 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1789 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1790 is_inside=0)
Matus Fabiande886752016-12-07 03:38:19 -08001791
1792 # in2out
1793 pkts = self.create_stream_in(self.pg0, self.pg1)
1794 self.pg0.add_stream(pkts)
1795 self.pg_enable_capture(self.pg_interfaces)
1796 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001797 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001798 self.verify_capture_out(capture)
1799
1800 # out2in
1801 pkts = self.create_stream_out(self.pg1)
1802 self.pg1.add_stream(pkts)
1803 self.pg_enable_capture(self.pg_interfaces)
1804 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001805 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001806 self.verify_capture_in(capture, self.pg0)
1807
1808 def test_static_with_port_out(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001809 """ 1:1 NAPT initialized from outside network """
Matus Fabiande886752016-12-07 03:38:19 -08001810
1811 self.tcp_port_out = 30606
1812 self.udp_port_out = 30607
1813 self.icmp_id_out = 30608
1814
Matus Fabian2ba92e32017-08-21 07:05:03 -07001815 self.nat44_add_address(self.nat_addr)
1816 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1817 self.tcp_port_in, self.tcp_port_out,
1818 proto=IP_PROTOS.tcp)
1819 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1820 self.udp_port_in, self.udp_port_out,
1821 proto=IP_PROTOS.udp)
1822 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1823 self.icmp_id_in, self.icmp_id_out,
1824 proto=IP_PROTOS.icmp)
1825 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1826 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1827 is_inside=0)
Matus Fabiande886752016-12-07 03:38:19 -08001828
1829 # out2in
1830 pkts = self.create_stream_out(self.pg1)
1831 self.pg1.add_stream(pkts)
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(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001835 self.verify_capture_in(capture, self.pg0)
1836
1837 # in2out
1838 pkts = self.create_stream_in(self.pg0, self.pg1)
1839 self.pg0.add_stream(pkts)
1840 self.pg_enable_capture(self.pg_interfaces)
1841 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001842 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001843 self.verify_capture_out(capture)
1844
1845 def test_static_vrf_aware(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001846 """ 1:1 NAT VRF awareness """
Matus Fabiande886752016-12-07 03:38:19 -08001847
1848 nat_ip1 = "10.0.0.30"
1849 nat_ip2 = "10.0.0.40"
1850 self.tcp_port_out = 6303
1851 self.udp_port_out = 6304
1852 self.icmp_id_out = 6305
1853
Matus Fabian2ba92e32017-08-21 07:05:03 -07001854 self.nat44_add_static_mapping(self.pg4.remote_ip4, nat_ip1,
1855 vrf_id=10)
1856 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip2,
1857 vrf_id=10)
1858 self.vapi.nat44_interface_add_del_feature(self.pg3.sw_if_index,
1859 is_inside=0)
1860 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1861 self.vapi.nat44_interface_add_del_feature(self.pg4.sw_if_index)
Matus Fabiande886752016-12-07 03:38:19 -08001862
Matus Fabian2ba92e32017-08-21 07:05:03 -07001863 # inside interface VRF match NAT44 static mapping VRF
Matus Fabiande886752016-12-07 03:38:19 -08001864 pkts = self.create_stream_in(self.pg4, self.pg3)
1865 self.pg4.add_stream(pkts)
1866 self.pg_enable_capture(self.pg_interfaces)
1867 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001868 capture = self.pg3.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001869 self.verify_capture_out(capture, nat_ip1, True)
1870
Matus Fabian2ba92e32017-08-21 07:05:03 -07001871 # inside interface VRF don't match NAT44 static mapping VRF (packets
Matus Fabiande886752016-12-07 03:38:19 -08001872 # are dropped)
1873 pkts = self.create_stream_in(self.pg0, self.pg3)
1874 self.pg0.add_stream(pkts)
1875 self.pg_enable_capture(self.pg_interfaces)
1876 self.pg_start()
Klement Sekera9225dee2016-12-12 08:36:58 +01001877 self.pg3.assert_nothing_captured()
Matus Fabiande886752016-12-07 03:38:19 -08001878
Matus Fabianb793d092018-01-31 05:50:21 -08001879 def test_dynamic_to_static(self):
1880 """ Switch from dynamic translation to 1:1NAT """
1881 nat_ip = "10.0.0.10"
1882 self.tcp_port_out = 6303
1883 self.udp_port_out = 6304
1884 self.icmp_id_out = 6305
1885
1886 self.nat44_add_address(self.nat_addr)
1887 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1888 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1889 is_inside=0)
1890
1891 # dynamic
1892 pkts = self.create_stream_in(self.pg0, self.pg1)
1893 self.pg0.add_stream(pkts)
1894 self.pg_enable_capture(self.pg_interfaces)
1895 self.pg_start()
1896 capture = self.pg1.get_capture(len(pkts))
1897 self.verify_capture_out(capture)
1898
1899 # 1:1NAT
1900 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
1901 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
1902 self.assertEqual(len(sessions), 0)
1903 pkts = self.create_stream_in(self.pg0, self.pg1)
1904 self.pg0.add_stream(pkts)
1905 self.pg_enable_capture(self.pg_interfaces)
1906 self.pg_start()
1907 capture = self.pg1.get_capture(len(pkts))
1908 self.verify_capture_out(capture, nat_ip, True)
1909
Matus Fabianab7a8052017-11-28 04:29:41 -08001910 def test_identity_nat(self):
1911 """ Identity NAT """
1912
1913 self.vapi.nat44_add_del_identity_mapping(ip=self.pg0.remote_ip4n)
1914 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1915 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1916 is_inside=0)
1917
1918 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
1919 IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
1920 TCP(sport=12345, dport=56789))
1921 self.pg1.add_stream(p)
1922 self.pg_enable_capture(self.pg_interfaces)
1923 self.pg_start()
1924 capture = self.pg0.get_capture(1)
1925 p = capture[0]
1926 try:
1927 ip = p[IP]
1928 tcp = p[TCP]
1929 self.assertEqual(ip.dst, self.pg0.remote_ip4)
1930 self.assertEqual(ip.src, self.pg1.remote_ip4)
1931 self.assertEqual(tcp.dport, 56789)
1932 self.assertEqual(tcp.sport, 12345)
Klement Sekerad81ae412018-05-16 10:52:54 +02001933 self.assert_packet_checksums_valid(p)
Matus Fabianab7a8052017-11-28 04:29:41 -08001934 except:
1935 self.logger.error(ppp("Unexpected or invalid packet:", p))
1936 raise
1937
Matus Fabiande886752016-12-07 03:38:19 -08001938 def test_multiple_inside_interfaces(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001939 """ NAT44 multiple non-overlapping address space inside interfaces """
Matus Fabiande886752016-12-07 03:38:19 -08001940
Matus Fabian2ba92e32017-08-21 07:05:03 -07001941 self.nat44_add_address(self.nat_addr)
1942 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1943 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
1944 self.vapi.nat44_interface_add_del_feature(self.pg3.sw_if_index,
1945 is_inside=0)
Matus Fabiande886752016-12-07 03:38:19 -08001946
Matus Fabian2ba92e32017-08-21 07:05:03 -07001947 # between two NAT44 inside interfaces (no translation)
Matus Fabian675a69c2017-01-18 01:46:01 -08001948 pkts = self.create_stream_in(self.pg0, self.pg1)
1949 self.pg0.add_stream(pkts)
1950 self.pg_enable_capture(self.pg_interfaces)
1951 self.pg_start()
1952 capture = self.pg1.get_capture(len(pkts))
1953 self.verify_capture_no_translation(capture, self.pg0, self.pg1)
1954
Matus Fabian2ba92e32017-08-21 07:05:03 -07001955 # from NAT44 inside to interface without NAT44 feature (no translation)
Matus Fabian675a69c2017-01-18 01:46:01 -08001956 pkts = self.create_stream_in(self.pg0, self.pg2)
1957 self.pg0.add_stream(pkts)
1958 self.pg_enable_capture(self.pg_interfaces)
1959 self.pg_start()
1960 capture = self.pg2.get_capture(len(pkts))
1961 self.verify_capture_no_translation(capture, self.pg0, self.pg2)
1962
Matus Fabiande886752016-12-07 03:38:19 -08001963 # in2out 1st interface
1964 pkts = self.create_stream_in(self.pg0, self.pg3)
1965 self.pg0.add_stream(pkts)
1966 self.pg_enable_capture(self.pg_interfaces)
1967 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001968 capture = self.pg3.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001969 self.verify_capture_out(capture)
1970
1971 # out2in 1st interface
1972 pkts = self.create_stream_out(self.pg3)
1973 self.pg3.add_stream(pkts)
1974 self.pg_enable_capture(self.pg_interfaces)
1975 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001976 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001977 self.verify_capture_in(capture, self.pg0)
1978
1979 # in2out 2nd interface
1980 pkts = self.create_stream_in(self.pg1, self.pg3)
1981 self.pg1.add_stream(pkts)
1982 self.pg_enable_capture(self.pg_interfaces)
1983 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001984 capture = self.pg3.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001985 self.verify_capture_out(capture)
1986
1987 # out2in 2nd interface
1988 pkts = self.create_stream_out(self.pg3)
1989 self.pg3.add_stream(pkts)
1990 self.pg_enable_capture(self.pg_interfaces)
1991 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001992 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001993 self.verify_capture_in(capture, self.pg1)
1994
Matus Fabiande886752016-12-07 03:38:19 -08001995 def test_inside_overlapping_interfaces(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001996 """ NAT44 multiple inside interfaces with overlapping address space """
Matus Fabiande886752016-12-07 03:38:19 -08001997
Matus Fabian675a69c2017-01-18 01:46:01 -08001998 static_nat_ip = "10.0.0.10"
Matus Fabian2ba92e32017-08-21 07:05:03 -07001999 self.nat44_add_address(self.nat_addr)
2000 self.vapi.nat44_interface_add_del_feature(self.pg3.sw_if_index,
2001 is_inside=0)
2002 self.vapi.nat44_interface_add_del_feature(self.pg4.sw_if_index)
2003 self.vapi.nat44_interface_add_del_feature(self.pg5.sw_if_index)
2004 self.vapi.nat44_interface_add_del_feature(self.pg6.sw_if_index)
2005 self.nat44_add_static_mapping(self.pg6.remote_ip4, static_nat_ip,
2006 vrf_id=20)
Matus Fabian675a69c2017-01-18 01:46:01 -08002007
Matus Fabian2ba92e32017-08-21 07:05:03 -07002008 # between NAT44 inside interfaces with same VRF (no translation)
Matus Fabian675a69c2017-01-18 01:46:01 -08002009 pkts = self.create_stream_in(self.pg4, self.pg5)
2010 self.pg4.add_stream(pkts)
2011 self.pg_enable_capture(self.pg_interfaces)
2012 self.pg_start()
2013 capture = self.pg5.get_capture(len(pkts))
2014 self.verify_capture_no_translation(capture, self.pg4, self.pg5)
2015
Matus Fabian2ba92e32017-08-21 07:05:03 -07002016 # between NAT44 inside interfaces with different VRF (hairpinning)
Matus Fabian675a69c2017-01-18 01:46:01 -08002017 p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
2018 IP(src=self.pg4.remote_ip4, dst=static_nat_ip) /
2019 TCP(sport=1234, dport=5678))
2020 self.pg4.add_stream(p)
2021 self.pg_enable_capture(self.pg_interfaces)
2022 self.pg_start()
2023 capture = self.pg6.get_capture(1)
2024 p = capture[0]
2025 try:
2026 ip = p[IP]
2027 tcp = p[TCP]
Matus Fabian2ba92e32017-08-21 07:05:03 -07002028 self.assertEqual(ip.src, self.nat_addr)
Matus Fabian675a69c2017-01-18 01:46:01 -08002029 self.assertEqual(ip.dst, self.pg6.remote_ip4)
2030 self.assertNotEqual(tcp.sport, 1234)
2031 self.assertEqual(tcp.dport, 5678)
2032 except:
2033 self.logger.error(ppp("Unexpected or invalid packet:", p))
2034 raise
Matus Fabiande886752016-12-07 03:38:19 -08002035
2036 # in2out 1st interface
2037 pkts = self.create_stream_in(self.pg4, self.pg3)
2038 self.pg4.add_stream(pkts)
2039 self.pg_enable_capture(self.pg_interfaces)
2040 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002041 capture = self.pg3.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002042 self.verify_capture_out(capture)
2043
2044 # out2in 1st interface
2045 pkts = self.create_stream_out(self.pg3)
2046 self.pg3.add_stream(pkts)
2047 self.pg_enable_capture(self.pg_interfaces)
2048 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002049 capture = self.pg4.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002050 self.verify_capture_in(capture, self.pg4)
2051
2052 # in2out 2nd interface
2053 pkts = self.create_stream_in(self.pg5, self.pg3)
2054 self.pg5.add_stream(pkts)
2055 self.pg_enable_capture(self.pg_interfaces)
2056 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002057 capture = self.pg3.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002058 self.verify_capture_out(capture)
2059
2060 # out2in 2nd interface
2061 pkts = self.create_stream_out(self.pg3)
2062 self.pg3.add_stream(pkts)
2063 self.pg_enable_capture(self.pg_interfaces)
2064 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002065 capture = self.pg5.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002066 self.verify_capture_in(capture, self.pg5)
2067
magalik23caa882017-02-08 23:25:45 -08002068 # pg5 session dump
Matus Fabian2ba92e32017-08-21 07:05:03 -07002069 addresses = self.vapi.nat44_address_dump()
magalik23caa882017-02-08 23:25:45 -08002070 self.assertEqual(len(addresses), 1)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002071 sessions = self.vapi.nat44_user_session_dump(self.pg5.remote_ip4n, 10)
magalik23caa882017-02-08 23:25:45 -08002072 self.assertEqual(len(sessions), 3)
2073 for session in sessions:
2074 self.assertFalse(session.is_static)
2075 self.assertEqual(session.inside_ip_address[0:4],
2076 self.pg5.remote_ip4n)
2077 self.assertEqual(session.outside_ip_address,
2078 addresses[0].ip_address)
2079 self.assertEqual(sessions[0].protocol, IP_PROTOS.tcp)
2080 self.assertEqual(sessions[1].protocol, IP_PROTOS.udp)
2081 self.assertEqual(sessions[2].protocol, IP_PROTOS.icmp)
2082 self.assertEqual(sessions[0].inside_port, self.tcp_port_in)
2083 self.assertEqual(sessions[1].inside_port, self.udp_port_in)
2084 self.assertEqual(sessions[2].inside_port, self.icmp_id_in)
2085 self.assertEqual(sessions[0].outside_port, self.tcp_port_out)
2086 self.assertEqual(sessions[1].outside_port, self.udp_port_out)
2087 self.assertEqual(sessions[2].outside_port, self.icmp_id_out)
2088
Matus Fabiande886752016-12-07 03:38:19 -08002089 # in2out 3rd interface
2090 pkts = self.create_stream_in(self.pg6, self.pg3)
2091 self.pg6.add_stream(pkts)
2092 self.pg_enable_capture(self.pg_interfaces)
2093 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002094 capture = self.pg3.get_capture(len(pkts))
Matus Fabian675a69c2017-01-18 01:46:01 -08002095 self.verify_capture_out(capture, static_nat_ip, True)
Matus Fabiande886752016-12-07 03:38:19 -08002096
2097 # out2in 3rd interface
Matus Fabian675a69c2017-01-18 01:46:01 -08002098 pkts = self.create_stream_out(self.pg3, static_nat_ip)
Matus Fabiande886752016-12-07 03:38:19 -08002099 self.pg3.add_stream(pkts)
2100 self.pg_enable_capture(self.pg_interfaces)
2101 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002102 capture = self.pg6.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002103 self.verify_capture_in(capture, self.pg6)
2104
magalik23caa882017-02-08 23:25:45 -08002105 # general user and session dump verifications
Matus Fabian2ba92e32017-08-21 07:05:03 -07002106 users = self.vapi.nat44_user_dump()
magalik23caa882017-02-08 23:25:45 -08002107 self.assertTrue(len(users) >= 3)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002108 addresses = self.vapi.nat44_address_dump()
magalik23caa882017-02-08 23:25:45 -08002109 self.assertEqual(len(addresses), 1)
2110 for user in users:
Matus Fabian2ba92e32017-08-21 07:05:03 -07002111 sessions = self.vapi.nat44_user_session_dump(user.ip_address,
2112 user.vrf_id)
magalik23caa882017-02-08 23:25:45 -08002113 for session in sessions:
2114 self.assertEqual(user.ip_address, session.inside_ip_address)
2115 self.assertTrue(session.total_bytes > session.total_pkts > 0)
2116 self.assertTrue(session.protocol in
2117 [IP_PROTOS.tcp, IP_PROTOS.udp,
2118 IP_PROTOS.icmp])
Matus Fabian70a26ac2018-05-14 06:20:28 -07002119 self.assertFalse(session.ext_host_valid)
magalik23caa882017-02-08 23:25:45 -08002120
2121 # pg4 session dump
Matus Fabian2ba92e32017-08-21 07:05:03 -07002122 sessions = self.vapi.nat44_user_session_dump(self.pg4.remote_ip4n, 10)
magalik23caa882017-02-08 23:25:45 -08002123 self.assertTrue(len(sessions) >= 4)
2124 for session in sessions:
2125 self.assertFalse(session.is_static)
2126 self.assertEqual(session.inside_ip_address[0:4],
2127 self.pg4.remote_ip4n)
2128 self.assertEqual(session.outside_ip_address,
2129 addresses[0].ip_address)
2130
2131 # pg6 session dump
Matus Fabian2ba92e32017-08-21 07:05:03 -07002132 sessions = self.vapi.nat44_user_session_dump(self.pg6.remote_ip4n, 20)
magalik23caa882017-02-08 23:25:45 -08002133 self.assertTrue(len(sessions) >= 3)
2134 for session in sessions:
2135 self.assertTrue(session.is_static)
2136 self.assertEqual(session.inside_ip_address[0:4],
2137 self.pg6.remote_ip4n)
2138 self.assertEqual(map(ord, session.outside_ip_address[0:4]),
2139 map(int, static_nat_ip.split('.')))
2140 self.assertTrue(session.inside_port in
2141 [self.tcp_port_in, self.udp_port_in,
2142 self.icmp_id_in])
2143
Matus Fabianf78a70d2016-12-12 04:30:39 -08002144 def test_hairpinning(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002145 """ NAT44 hairpinning - 1:1 NAPT """
Matus Fabianf78a70d2016-12-12 04:30:39 -08002146
2147 host = self.pg0.remote_hosts[0]
2148 server = self.pg0.remote_hosts[1]
2149 host_in_port = 1234
2150 host_out_port = 0
2151 server_in_port = 5678
2152 server_out_port = 8765
2153
Matus Fabian2ba92e32017-08-21 07:05:03 -07002154 self.nat44_add_address(self.nat_addr)
2155 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2156 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2157 is_inside=0)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002158 # add static mapping for server
Matus Fabian2ba92e32017-08-21 07:05:03 -07002159 self.nat44_add_static_mapping(server.ip4, self.nat_addr,
2160 server_in_port, server_out_port,
2161 proto=IP_PROTOS.tcp)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002162
2163 # send packet from host to server
2164 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002165 IP(src=host.ip4, dst=self.nat_addr) /
Matus Fabianf78a70d2016-12-12 04:30:39 -08002166 TCP(sport=host_in_port, dport=server_out_port))
2167 self.pg0.add_stream(p)
2168 self.pg_enable_capture(self.pg_interfaces)
2169 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002170 capture = self.pg0.get_capture(1)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002171 p = capture[0]
2172 try:
2173 ip = p[IP]
2174 tcp = p[TCP]
Matus Fabian2ba92e32017-08-21 07:05:03 -07002175 self.assertEqual(ip.src, self.nat_addr)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002176 self.assertEqual(ip.dst, server.ip4)
2177 self.assertNotEqual(tcp.sport, host_in_port)
2178 self.assertEqual(tcp.dport, server_in_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02002179 self.assert_packet_checksums_valid(p)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002180 host_out_port = tcp.sport
2181 except:
Klement Sekera9225dee2016-12-12 08:36:58 +01002182 self.logger.error(ppp("Unexpected or invalid packet:", p))
Matus Fabianf78a70d2016-12-12 04:30:39 -08002183 raise
2184
2185 # send reply from server to host
2186 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002187 IP(src=server.ip4, dst=self.nat_addr) /
Matus Fabianf78a70d2016-12-12 04:30:39 -08002188 TCP(sport=server_in_port, dport=host_out_port))
2189 self.pg0.add_stream(p)
2190 self.pg_enable_capture(self.pg_interfaces)
2191 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002192 capture = self.pg0.get_capture(1)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002193 p = capture[0]
2194 try:
2195 ip = p[IP]
2196 tcp = p[TCP]
Matus Fabian2ba92e32017-08-21 07:05:03 -07002197 self.assertEqual(ip.src, self.nat_addr)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002198 self.assertEqual(ip.dst, host.ip4)
2199 self.assertEqual(tcp.sport, server_out_port)
2200 self.assertEqual(tcp.dport, host_in_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02002201 self.assert_packet_checksums_valid(p)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002202 except:
Matus Fabiane82488f2018-01-18 03:38:45 -08002203 self.logger.error(ppp("Unexpected or invalid packet:", p))
Matus Fabianf78a70d2016-12-12 04:30:39 -08002204 raise
2205
Matus Fabian6fa74c62017-06-05 05:55:48 -07002206 def test_hairpinning2(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002207 """ NAT44 hairpinning - 1:1 NAT"""
Matus Fabian6fa74c62017-06-05 05:55:48 -07002208
2209 server1_nat_ip = "10.0.0.10"
2210 server2_nat_ip = "10.0.0.11"
2211 host = self.pg0.remote_hosts[0]
2212 server1 = self.pg0.remote_hosts[1]
2213 server2 = self.pg0.remote_hosts[2]
2214 server_tcp_port = 22
2215 server_udp_port = 20
2216
Matus Fabian2ba92e32017-08-21 07:05:03 -07002217 self.nat44_add_address(self.nat_addr)
2218 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2219 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2220 is_inside=0)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002221
2222 # add static mapping for servers
Matus Fabian2ba92e32017-08-21 07:05:03 -07002223 self.nat44_add_static_mapping(server1.ip4, server1_nat_ip)
2224 self.nat44_add_static_mapping(server2.ip4, server2_nat_ip)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002225
2226 # host to server1
2227 pkts = []
2228 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2229 IP(src=host.ip4, dst=server1_nat_ip) /
2230 TCP(sport=self.tcp_port_in, dport=server_tcp_port))
2231 pkts.append(p)
2232 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2233 IP(src=host.ip4, dst=server1_nat_ip) /
2234 UDP(sport=self.udp_port_in, dport=server_udp_port))
2235 pkts.append(p)
2236 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2237 IP(src=host.ip4, dst=server1_nat_ip) /
2238 ICMP(id=self.icmp_id_in, type='echo-request'))
2239 pkts.append(p)
2240 self.pg0.add_stream(pkts)
2241 self.pg_enable_capture(self.pg_interfaces)
2242 self.pg_start()
2243 capture = self.pg0.get_capture(len(pkts))
2244 for packet in capture:
2245 try:
Matus Fabian2ba92e32017-08-21 07:05:03 -07002246 self.assertEqual(packet[IP].src, self.nat_addr)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002247 self.assertEqual(packet[IP].dst, server1.ip4)
2248 if packet.haslayer(TCP):
2249 self.assertNotEqual(packet[TCP].sport, self.tcp_port_in)
2250 self.assertEqual(packet[TCP].dport, server_tcp_port)
2251 self.tcp_port_out = packet[TCP].sport
Klement Sekerad81ae412018-05-16 10:52:54 +02002252 self.assert_packet_checksums_valid(packet)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002253 elif packet.haslayer(UDP):
2254 self.assertNotEqual(packet[UDP].sport, self.udp_port_in)
2255 self.assertEqual(packet[UDP].dport, server_udp_port)
2256 self.udp_port_out = packet[UDP].sport
2257 else:
2258 self.assertNotEqual(packet[ICMP].id, self.icmp_id_in)
2259 self.icmp_id_out = packet[ICMP].id
2260 except:
2261 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2262 raise
2263
2264 # server1 to host
2265 pkts = []
2266 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002267 IP(src=server1.ip4, dst=self.nat_addr) /
Matus Fabian6fa74c62017-06-05 05:55:48 -07002268 TCP(sport=server_tcp_port, dport=self.tcp_port_out))
2269 pkts.append(p)
2270 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002271 IP(src=server1.ip4, dst=self.nat_addr) /
Matus Fabian6fa74c62017-06-05 05:55:48 -07002272 UDP(sport=server_udp_port, dport=self.udp_port_out))
2273 pkts.append(p)
2274 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002275 IP(src=server1.ip4, dst=self.nat_addr) /
Matus Fabian6fa74c62017-06-05 05:55:48 -07002276 ICMP(id=self.icmp_id_out, type='echo-reply'))
2277 pkts.append(p)
2278 self.pg0.add_stream(pkts)
2279 self.pg_enable_capture(self.pg_interfaces)
2280 self.pg_start()
2281 capture = self.pg0.get_capture(len(pkts))
2282 for packet in capture:
2283 try:
2284 self.assertEqual(packet[IP].src, server1_nat_ip)
2285 self.assertEqual(packet[IP].dst, host.ip4)
2286 if packet.haslayer(TCP):
2287 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
2288 self.assertEqual(packet[TCP].sport, server_tcp_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02002289 self.assert_packet_checksums_valid(packet)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002290 elif packet.haslayer(UDP):
2291 self.assertEqual(packet[UDP].dport, self.udp_port_in)
2292 self.assertEqual(packet[UDP].sport, server_udp_port)
2293 else:
2294 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
2295 except:
2296 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2297 raise
2298
2299 # server2 to server1
2300 pkts = []
2301 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2302 IP(src=server2.ip4, dst=server1_nat_ip) /
2303 TCP(sport=self.tcp_port_in, dport=server_tcp_port))
2304 pkts.append(p)
2305 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2306 IP(src=server2.ip4, dst=server1_nat_ip) /
2307 UDP(sport=self.udp_port_in, dport=server_udp_port))
2308 pkts.append(p)
2309 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2310 IP(src=server2.ip4, dst=server1_nat_ip) /
2311 ICMP(id=self.icmp_id_in, type='echo-request'))
2312 pkts.append(p)
2313 self.pg0.add_stream(pkts)
2314 self.pg_enable_capture(self.pg_interfaces)
2315 self.pg_start()
2316 capture = self.pg0.get_capture(len(pkts))
2317 for packet in capture:
2318 try:
2319 self.assertEqual(packet[IP].src, server2_nat_ip)
2320 self.assertEqual(packet[IP].dst, server1.ip4)
2321 if packet.haslayer(TCP):
2322 self.assertEqual(packet[TCP].sport, self.tcp_port_in)
2323 self.assertEqual(packet[TCP].dport, server_tcp_port)
2324 self.tcp_port_out = packet[TCP].sport
Klement Sekerad81ae412018-05-16 10:52:54 +02002325 self.assert_packet_checksums_valid(packet)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002326 elif packet.haslayer(UDP):
2327 self.assertEqual(packet[UDP].sport, self.udp_port_in)
2328 self.assertEqual(packet[UDP].dport, server_udp_port)
2329 self.udp_port_out = packet[UDP].sport
2330 else:
2331 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
2332 self.icmp_id_out = packet[ICMP].id
2333 except:
2334 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2335 raise
2336
2337 # server1 to server2
2338 pkts = []
2339 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2340 IP(src=server1.ip4, dst=server2_nat_ip) /
2341 TCP(sport=server_tcp_port, dport=self.tcp_port_out))
2342 pkts.append(p)
2343 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2344 IP(src=server1.ip4, dst=server2_nat_ip) /
2345 UDP(sport=server_udp_port, dport=self.udp_port_out))
2346 pkts.append(p)
2347 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2348 IP(src=server1.ip4, dst=server2_nat_ip) /
2349 ICMP(id=self.icmp_id_out, type='echo-reply'))
2350 pkts.append(p)
2351 self.pg0.add_stream(pkts)
2352 self.pg_enable_capture(self.pg_interfaces)
2353 self.pg_start()
2354 capture = self.pg0.get_capture(len(pkts))
2355 for packet in capture:
2356 try:
2357 self.assertEqual(packet[IP].src, server1_nat_ip)
2358 self.assertEqual(packet[IP].dst, server2.ip4)
2359 if packet.haslayer(TCP):
2360 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
2361 self.assertEqual(packet[TCP].sport, server_tcp_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02002362 self.assert_packet_checksums_valid(packet)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002363 elif packet.haslayer(UDP):
2364 self.assertEqual(packet[UDP].dport, self.udp_port_in)
2365 self.assertEqual(packet[UDP].sport, server_udp_port)
2366 else:
2367 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
2368 except:
2369 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2370 raise
2371
Matus Fabian9902fcd2016-12-21 23:58:46 -08002372 def test_max_translations_per_user(self):
2373 """ MAX translations per user - recycle the least recently used """
2374
Matus Fabian2ba92e32017-08-21 07:05:03 -07002375 self.nat44_add_address(self.nat_addr)
2376 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2377 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2378 is_inside=0)
Matus Fabian9902fcd2016-12-21 23:58:46 -08002379
2380 # get maximum number of translations per user
Matus Fabian2ba92e32017-08-21 07:05:03 -07002381 nat44_config = self.vapi.nat_show_config()
Matus Fabian9902fcd2016-12-21 23:58:46 -08002382
2383 # send more than maximum number of translations per user packets
Matus Fabian2ba92e32017-08-21 07:05:03 -07002384 pkts_num = nat44_config.max_translations_per_user + 5
Matus Fabian9902fcd2016-12-21 23:58:46 -08002385 pkts = []
2386 for port in range(0, pkts_num):
2387 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2388 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2389 TCP(sport=1025 + port))
2390 pkts.append(p)
2391 self.pg0.add_stream(pkts)
2392 self.pg_enable_capture(self.pg_interfaces)
2393 self.pg_start()
2394
2395 # verify number of translated packet
Klement Sekeradab231a2016-12-21 08:50:14 +01002396 self.pg1.get_capture(pkts_num)
Matus Fabian9902fcd2016-12-21 23:58:46 -08002397
Matus Fabian132dc492018-05-09 04:51:03 -07002398 users = self.vapi.nat44_user_dump()
2399 for user in users:
2400 if user.ip_address == self.pg0.remote_ip4n:
2401 self.assertEqual(user.nsessions,
2402 nat44_config.max_translations_per_user)
2403 self.assertEqual(user.nstaticsessions, 0)
2404
2405 tcp_port = 22
2406 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
2407 tcp_port, tcp_port,
2408 proto=IP_PROTOS.tcp)
2409 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2410 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2411 TCP(sport=tcp_port))
2412 self.pg0.add_stream(p)
2413 self.pg_enable_capture(self.pg_interfaces)
2414 self.pg_start()
2415 self.pg1.get_capture(1)
2416 users = self.vapi.nat44_user_dump()
2417 for user in users:
2418 if user.ip_address == self.pg0.remote_ip4n:
2419 self.assertEqual(user.nsessions,
2420 nat44_config.max_translations_per_user - 1)
2421 self.assertEqual(user.nstaticsessions, 1)
2422
Matus Fabian8bf68e82017-01-12 04:24:35 -08002423 def test_interface_addr(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002424 """ Acquire NAT44 addresses from interface """
2425 self.vapi.nat44_add_interface_addr(self.pg7.sw_if_index)
Matus Fabian8bf68e82017-01-12 04:24:35 -08002426
2427 # no address in NAT pool
Matus Fabian2ba92e32017-08-21 07:05:03 -07002428 adresses = self.vapi.nat44_address_dump()
Matus Fabian8bf68e82017-01-12 04:24:35 -08002429 self.assertEqual(0, len(adresses))
2430
2431 # configure interface address and check NAT address pool
2432 self.pg7.config_ip4()
Matus Fabian2ba92e32017-08-21 07:05:03 -07002433 adresses = self.vapi.nat44_address_dump()
Matus Fabian8bf68e82017-01-12 04:24:35 -08002434 self.assertEqual(1, len(adresses))
Matus Fabian36532bd2017-01-23 23:42:28 -08002435 self.assertEqual(adresses[0].ip_address[0:4], self.pg7.local_ip4n)
Matus Fabian8bf68e82017-01-12 04:24:35 -08002436
2437 # remove interface address and check NAT address pool
2438 self.pg7.unconfig_ip4()
Matus Fabian2ba92e32017-08-21 07:05:03 -07002439 adresses = self.vapi.nat44_address_dump()
Matus Fabian8bf68e82017-01-12 04:24:35 -08002440 self.assertEqual(0, len(adresses))
2441
Matus Fabian36532bd2017-01-23 23:42:28 -08002442 def test_interface_addr_static_mapping(self):
2443 """ Static mapping with addresses from interface """
Matus Fabian5f224992018-01-25 21:59:16 -08002444 tag = "testTAG"
2445
Matus Fabian2ba92e32017-08-21 07:05:03 -07002446 self.vapi.nat44_add_interface_addr(self.pg7.sw_if_index)
2447 self.nat44_add_static_mapping(
2448 '1.2.3.4',
Matus Fabian5f224992018-01-25 21:59:16 -08002449 external_sw_if_index=self.pg7.sw_if_index,
2450 tag=tag)
Matus Fabian36532bd2017-01-23 23:42:28 -08002451
Matus Fabiane22e5462017-02-14 23:33:43 -08002452 # static mappings with external interface
Matus Fabian2ba92e32017-08-21 07:05:03 -07002453 static_mappings = self.vapi.nat44_static_mapping_dump()
Matus Fabiane22e5462017-02-14 23:33:43 -08002454 self.assertEqual(1, len(static_mappings))
2455 self.assertEqual(self.pg7.sw_if_index,
2456 static_mappings[0].external_sw_if_index)
Matus Fabian5f224992018-01-25 21:59:16 -08002457 self.assertEqual((static_mappings[0].tag).split('\0', 1)[0], tag)
Matus Fabian36532bd2017-01-23 23:42:28 -08002458
2459 # configure interface address and check static mappings
2460 self.pg7.config_ip4()
Matus Fabian2ba92e32017-08-21 07:05:03 -07002461 static_mappings = self.vapi.nat44_static_mapping_dump()
Matus Fabianea2600a2018-03-28 04:06:26 -07002462 self.assertEqual(2, len(static_mappings))
2463 resolved = False
2464 for sm in static_mappings:
2465 if sm.external_sw_if_index == 0xFFFFFFFF:
2466 self.assertEqual(sm.external_ip_address[0:4],
2467 self.pg7.local_ip4n)
2468 self.assertEqual((sm.tag).split('\0', 1)[0], tag)
2469 resolved = True
2470 self.assertTrue(resolved)
Matus Fabian36532bd2017-01-23 23:42:28 -08002471
2472 # remove interface address and check static mappings
2473 self.pg7.unconfig_ip4()
Matus Fabian2ba92e32017-08-21 07:05:03 -07002474 static_mappings = self.vapi.nat44_static_mapping_dump()
Matus Fabianea2600a2018-03-28 04:06:26 -07002475 self.assertEqual(1, len(static_mappings))
2476 self.assertEqual(self.pg7.sw_if_index,
2477 static_mappings[0].external_sw_if_index)
2478 self.assertEqual((static_mappings[0].tag).split('\0', 1)[0], tag)
2479
2480 # configure interface address again and check static mappings
2481 self.pg7.config_ip4()
2482 static_mappings = self.vapi.nat44_static_mapping_dump()
2483 self.assertEqual(2, len(static_mappings))
2484 resolved = False
2485 for sm in static_mappings:
2486 if sm.external_sw_if_index == 0xFFFFFFFF:
2487 self.assertEqual(sm.external_ip_address[0:4],
2488 self.pg7.local_ip4n)
2489 self.assertEqual((sm.tag).split('\0', 1)[0], tag)
2490 resolved = True
2491 self.assertTrue(resolved)
2492
2493 # remove static mapping
2494 self.nat44_add_static_mapping(
2495 '1.2.3.4',
2496 external_sw_if_index=self.pg7.sw_if_index,
2497 tag=tag,
2498 is_add=0)
2499 static_mappings = self.vapi.nat44_static_mapping_dump()
Matus Fabian36532bd2017-01-23 23:42:28 -08002500 self.assertEqual(0, len(static_mappings))
2501
Matus Fabianab7a8052017-11-28 04:29:41 -08002502 def test_interface_addr_identity_nat(self):
2503 """ Identity NAT with addresses from interface """
2504
2505 port = 53053
2506 self.vapi.nat44_add_interface_addr(self.pg7.sw_if_index)
2507 self.vapi.nat44_add_del_identity_mapping(
2508 sw_if_index=self.pg7.sw_if_index,
2509 port=port,
2510 protocol=IP_PROTOS.tcp,
2511 addr_only=0)
2512
2513 # identity mappings with external interface
2514 identity_mappings = self.vapi.nat44_identity_mapping_dump()
2515 self.assertEqual(1, len(identity_mappings))
2516 self.assertEqual(self.pg7.sw_if_index,
2517 identity_mappings[0].sw_if_index)
2518
2519 # configure interface address and check identity mappings
2520 self.pg7.config_ip4()
2521 identity_mappings = self.vapi.nat44_identity_mapping_dump()
Matus Fabianea2600a2018-03-28 04:06:26 -07002522 resolved = False
2523 self.assertEqual(2, len(identity_mappings))
2524 for sm in identity_mappings:
2525 if sm.sw_if_index == 0xFFFFFFFF:
2526 self.assertEqual(identity_mappings[0].ip_address,
2527 self.pg7.local_ip4n)
2528 self.assertEqual(port, identity_mappings[0].port)
2529 self.assertEqual(IP_PROTOS.tcp, identity_mappings[0].protocol)
2530 resolved = True
2531 self.assertTrue(resolved)
Matus Fabianab7a8052017-11-28 04:29:41 -08002532
2533 # remove interface address and check identity mappings
2534 self.pg7.unconfig_ip4()
2535 identity_mappings = self.vapi.nat44_identity_mapping_dump()
Matus Fabianea2600a2018-03-28 04:06:26 -07002536 self.assertEqual(1, len(identity_mappings))
2537 self.assertEqual(self.pg7.sw_if_index,
2538 identity_mappings[0].sw_if_index)
Matus Fabianab7a8052017-11-28 04:29:41 -08002539
Matus Fabianeea28d72017-01-13 04:15:54 -08002540 def test_ipfix_nat44_sess(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002541 """ IPFIX logging NAT44 session created/delted """
Matus Fabian6631e9c2017-05-24 01:52:20 -07002542 self.ipfix_domain_id = 10
2543 self.ipfix_src_port = 20202
2544 colector_port = 30303
2545 bind_layers(UDP, IPFIX, dport=30303)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002546 self.nat44_add_address(self.nat_addr)
2547 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2548 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2549 is_inside=0)
Matus Fabianeea28d72017-01-13 04:15:54 -08002550 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
2551 src_address=self.pg3.local_ip4n,
2552 path_mtu=512,
Matus Fabian6631e9c2017-05-24 01:52:20 -07002553 template_interval=10,
2554 collector_port=colector_port)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002555 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
2556 src_port=self.ipfix_src_port)
Matus Fabianeea28d72017-01-13 04:15:54 -08002557
2558 pkts = self.create_stream_in(self.pg0, self.pg1)
2559 self.pg0.add_stream(pkts)
2560 self.pg_enable_capture(self.pg_interfaces)
2561 self.pg_start()
2562 capture = self.pg1.get_capture(len(pkts))
2563 self.verify_capture_out(capture)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002564 self.nat44_add_address(self.nat_addr, is_add=0)
Matus Fabianeea28d72017-01-13 04:15:54 -08002565 self.vapi.cli("ipfix flush") # FIXME this should be an API call
Matus Fabiana431ad12018-01-04 04:03:14 -08002566 capture = self.pg3.get_capture(9)
Matus Fabianeea28d72017-01-13 04:15:54 -08002567 ipfix = IPFIXDecoder()
2568 # first load template
2569 for p in capture:
2570 self.assertTrue(p.haslayer(IPFIX))
Matus Fabian6631e9c2017-05-24 01:52:20 -07002571 self.assertEqual(p[IP].src, self.pg3.local_ip4)
2572 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2573 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2574 self.assertEqual(p[UDP].dport, colector_port)
2575 self.assertEqual(p[IPFIX].observationDomainID,
2576 self.ipfix_domain_id)
Matus Fabianeea28d72017-01-13 04:15:54 -08002577 if p.haslayer(Template):
2578 ipfix.add_template(p.getlayer(Template))
2579 # verify events in data set
2580 for p in capture:
2581 if p.haslayer(Data):
2582 data = ipfix.decode_data_set(p.getlayer(Set))
2583 self.verify_ipfix_nat44_ses(data)
2584
2585 def test_ipfix_addr_exhausted(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002586 """ IPFIX logging NAT addresses exhausted """
2587 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2588 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2589 is_inside=0)
Matus Fabianeea28d72017-01-13 04:15:54 -08002590 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
2591 src_address=self.pg3.local_ip4n,
2592 path_mtu=512,
2593 template_interval=10)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002594 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
2595 src_port=self.ipfix_src_port)
Matus Fabianeea28d72017-01-13 04:15:54 -08002596
2597 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
2598 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2599 TCP(sport=3025))
2600 self.pg0.add_stream(p)
2601 self.pg_enable_capture(self.pg_interfaces)
2602 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07002603 self.pg1.assert_nothing_captured()
2604 sleep(1)
Matus Fabianeea28d72017-01-13 04:15:54 -08002605 self.vapi.cli("ipfix flush") # FIXME this should be an API call
Matus Fabiana431ad12018-01-04 04:03:14 -08002606 capture = self.pg3.get_capture(9)
Matus Fabianeea28d72017-01-13 04:15:54 -08002607 ipfix = IPFIXDecoder()
2608 # first load template
2609 for p in capture:
2610 self.assertTrue(p.haslayer(IPFIX))
Matus Fabian6631e9c2017-05-24 01:52:20 -07002611 self.assertEqual(p[IP].src, self.pg3.local_ip4)
2612 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2613 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2614 self.assertEqual(p[UDP].dport, 4739)
2615 self.assertEqual(p[IPFIX].observationDomainID,
2616 self.ipfix_domain_id)
Matus Fabianeea28d72017-01-13 04:15:54 -08002617 if p.haslayer(Template):
2618 ipfix.add_template(p.getlayer(Template))
2619 # verify events in data set
2620 for p in capture:
2621 if p.haslayer(Data):
2622 data = ipfix.decode_data_set(p.getlayer(Set))
2623 self.verify_ipfix_addr_exhausted(data)
2624
Matus Fabiana431ad12018-01-04 04:03:14 -08002625 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
2626 def test_ipfix_max_sessions(self):
2627 """ IPFIX logging maximum session entries exceeded """
2628 self.nat44_add_address(self.nat_addr)
2629 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2630 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2631 is_inside=0)
2632
2633 nat44_config = self.vapi.nat_show_config()
2634 max_sessions = 10 * nat44_config.translation_buckets
2635
2636 pkts = []
2637 for i in range(0, max_sessions):
2638 src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
2639 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2640 IP(src=src, dst=self.pg1.remote_ip4) /
2641 TCP(sport=1025))
2642 pkts.append(p)
2643 self.pg0.add_stream(pkts)
2644 self.pg_enable_capture(self.pg_interfaces)
2645 self.pg_start()
2646
2647 self.pg1.get_capture(max_sessions)
2648 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
2649 src_address=self.pg3.local_ip4n,
2650 path_mtu=512,
2651 template_interval=10)
2652 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
2653 src_port=self.ipfix_src_port)
2654
2655 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2656 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2657 TCP(sport=1025))
2658 self.pg0.add_stream(p)
2659 self.pg_enable_capture(self.pg_interfaces)
2660 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07002661 self.pg1.assert_nothing_captured()
2662 sleep(1)
Matus Fabiana431ad12018-01-04 04:03:14 -08002663 self.vapi.cli("ipfix flush") # FIXME this should be an API call
2664 capture = self.pg3.get_capture(9)
2665 ipfix = IPFIXDecoder()
2666 # first load template
2667 for p in capture:
2668 self.assertTrue(p.haslayer(IPFIX))
2669 self.assertEqual(p[IP].src, self.pg3.local_ip4)
2670 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2671 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2672 self.assertEqual(p[UDP].dport, 4739)
2673 self.assertEqual(p[IPFIX].observationDomainID,
2674 self.ipfix_domain_id)
2675 if p.haslayer(Template):
2676 ipfix.add_template(p.getlayer(Template))
2677 # verify events in data set
2678 for p in capture:
2679 if p.haslayer(Data):
2680 data = ipfix.decode_data_set(p.getlayer(Set))
2681 self.verify_ipfix_max_sessions(data, max_sessions)
2682
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002683 def test_pool_addr_fib(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002684 """ NAT44 add pool addresses to FIB """
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002685 static_addr = '10.0.0.10'
Matus Fabian2ba92e32017-08-21 07:05:03 -07002686 self.nat44_add_address(self.nat_addr)
2687 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2688 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2689 is_inside=0)
2690 self.nat44_add_static_mapping(self.pg0.remote_ip4, static_addr)
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002691
Matus Fabian2ba92e32017-08-21 07:05:03 -07002692 # NAT44 address
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002693 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002694 ARP(op=ARP.who_has, pdst=self.nat_addr,
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002695 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2696 self.pg1.add_stream(p)
2697 self.pg_enable_capture(self.pg_interfaces)
2698 self.pg_start()
2699 capture = self.pg1.get_capture(1)
2700 self.assertTrue(capture[0].haslayer(ARP))
2701 self.assertTrue(capture[0][ARP].op, ARP.is_at)
2702
2703 # 1:1 NAT address
2704 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2705 ARP(op=ARP.who_has, pdst=static_addr,
2706 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2707 self.pg1.add_stream(p)
2708 self.pg_enable_capture(self.pg_interfaces)
2709 self.pg_start()
2710 capture = self.pg1.get_capture(1)
2711 self.assertTrue(capture[0].haslayer(ARP))
2712 self.assertTrue(capture[0][ARP].op, ARP.is_at)
2713
Matus Fabian2ba92e32017-08-21 07:05:03 -07002714 # send ARP to non-NAT44 interface
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002715 p = (Ether(src=self.pg2.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002716 ARP(op=ARP.who_has, pdst=self.nat_addr,
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002717 psrc=self.pg2.remote_ip4, hwsrc=self.pg2.remote_mac))
2718 self.pg2.add_stream(p)
2719 self.pg_enable_capture(self.pg_interfaces)
2720 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07002721 self.pg1.assert_nothing_captured()
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002722
2723 # remove addresses and verify
Matus Fabian2ba92e32017-08-21 07:05:03 -07002724 self.nat44_add_address(self.nat_addr, is_add=0)
2725 self.nat44_add_static_mapping(self.pg0.remote_ip4, static_addr,
2726 is_add=0)
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002727
2728 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002729 ARP(op=ARP.who_has, pdst=self.nat_addr,
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002730 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2731 self.pg1.add_stream(p)
2732 self.pg_enable_capture(self.pg_interfaces)
2733 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07002734 self.pg1.assert_nothing_captured()
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002735
2736 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2737 ARP(op=ARP.who_has, pdst=static_addr,
2738 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2739 self.pg1.add_stream(p)
2740 self.pg_enable_capture(self.pg_interfaces)
2741 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07002742 self.pg1.assert_nothing_captured()
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002743
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002744 def test_vrf_mode(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002745 """ NAT44 tenant VRF aware address pool mode """
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002746
2747 vrf_id1 = 1
2748 vrf_id2 = 2
2749 nat_ip1 = "10.0.0.10"
2750 nat_ip2 = "10.0.0.11"
2751
2752 self.pg0.unconfig_ip4()
2753 self.pg1.unconfig_ip4()
Neale Ranns15002542017-09-10 04:39:11 -07002754 self.vapi.ip_table_add_del(vrf_id1, is_add=1)
2755 self.vapi.ip_table_add_del(vrf_id2, is_add=1)
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002756 self.pg0.set_table_ip4(vrf_id1)
2757 self.pg1.set_table_ip4(vrf_id2)
2758 self.pg0.config_ip4()
2759 self.pg1.config_ip4()
Matus Fabian8008d7c2018-07-09 01:34:20 -07002760 self.pg0.resolve_arp()
2761 self.pg1.resolve_arp()
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002762
Matus Fabian2ba92e32017-08-21 07:05:03 -07002763 self.nat44_add_address(nat_ip1, vrf_id=vrf_id1)
2764 self.nat44_add_address(nat_ip2, vrf_id=vrf_id2)
2765 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2766 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
2767 self.vapi.nat44_interface_add_del_feature(self.pg2.sw_if_index,
2768 is_inside=0)
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002769
Matus Fabian8008d7c2018-07-09 01:34:20 -07002770 try:
2771 # first VRF
2772 pkts = self.create_stream_in(self.pg0, self.pg2)
2773 self.pg0.add_stream(pkts)
2774 self.pg_enable_capture(self.pg_interfaces)
2775 self.pg_start()
2776 capture = self.pg2.get_capture(len(pkts))
2777 self.verify_capture_out(capture, nat_ip1)
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002778
Matus Fabian8008d7c2018-07-09 01:34:20 -07002779 # second VRF
2780 pkts = self.create_stream_in(self.pg1, self.pg2)
2781 self.pg1.add_stream(pkts)
2782 self.pg_enable_capture(self.pg_interfaces)
2783 self.pg_start()
2784 capture = self.pg2.get_capture(len(pkts))
2785 self.verify_capture_out(capture, nat_ip2)
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002786
Matus Fabian8008d7c2018-07-09 01:34:20 -07002787 finally:
2788 self.pg0.unconfig_ip4()
2789 self.pg1.unconfig_ip4()
2790 self.pg0.set_table_ip4(0)
2791 self.pg1.set_table_ip4(0)
2792 self.pg0.config_ip4()
2793 self.pg1.config_ip4()
2794 self.pg0.resolve_arp()
2795 self.pg1.resolve_arp()
2796 self.vapi.ip_table_add_del(vrf_id1, is_add=0)
2797 self.vapi.ip_table_add_del(vrf_id2, is_add=0)
Neale Ranns15002542017-09-10 04:39:11 -07002798
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002799 def test_vrf_feature_independent(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002800 """ NAT44 tenant VRF independent address pool mode """
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002801
2802 nat_ip1 = "10.0.0.10"
2803 nat_ip2 = "10.0.0.11"
2804
Matus Fabian2ba92e32017-08-21 07:05:03 -07002805 self.nat44_add_address(nat_ip1)
Matus Fabian51e759f2017-12-07 23:22:51 -08002806 self.nat44_add_address(nat_ip2, vrf_id=99)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002807 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2808 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
2809 self.vapi.nat44_interface_add_del_feature(self.pg2.sw_if_index,
2810 is_inside=0)
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002811
2812 # first VRF
2813 pkts = self.create_stream_in(self.pg0, self.pg2)
2814 self.pg0.add_stream(pkts)
2815 self.pg_enable_capture(self.pg_interfaces)
2816 self.pg_start()
2817 capture = self.pg2.get_capture(len(pkts))
2818 self.verify_capture_out(capture, nat_ip1)
2819
2820 # second VRF
2821 pkts = self.create_stream_in(self.pg1, self.pg2)
2822 self.pg1.add_stream(pkts)
2823 self.pg_enable_capture(self.pg_interfaces)
2824 self.pg_start()
2825 capture = self.pg2.get_capture(len(pkts))
2826 self.verify_capture_out(capture, nat_ip1)
2827
Martin Gálik406eb1d2017-05-04 04:35:04 -07002828 def test_dynamic_ipless_interfaces(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002829 """ NAT44 interfaces without configured IP address """
Martin Gálik406eb1d2017-05-04 04:35:04 -07002830
2831 self.vapi.ip_neighbor_add_del(self.pg7.sw_if_index,
Ole Troan895b6e82017-10-20 13:28:20 +02002832 mactobinary(self.pg7.remote_mac),
Martin Gálik406eb1d2017-05-04 04:35:04 -07002833 self.pg7.remote_ip4n,
2834 is_static=1)
2835 self.vapi.ip_neighbor_add_del(self.pg8.sw_if_index,
Ole Troan895b6e82017-10-20 13:28:20 +02002836 mactobinary(self.pg8.remote_mac),
Martin Gálik406eb1d2017-05-04 04:35:04 -07002837 self.pg8.remote_ip4n,
2838 is_static=1)
2839
2840 self.vapi.ip_add_del_route(dst_address=self.pg7.remote_ip4n,
2841 dst_address_length=32,
2842 next_hop_address=self.pg7.remote_ip4n,
2843 next_hop_sw_if_index=self.pg7.sw_if_index)
2844 self.vapi.ip_add_del_route(dst_address=self.pg8.remote_ip4n,
2845 dst_address_length=32,
2846 next_hop_address=self.pg8.remote_ip4n,
2847 next_hop_sw_if_index=self.pg8.sw_if_index)
2848
Matus Fabian2ba92e32017-08-21 07:05:03 -07002849 self.nat44_add_address(self.nat_addr)
2850 self.vapi.nat44_interface_add_del_feature(self.pg7.sw_if_index)
2851 self.vapi.nat44_interface_add_del_feature(self.pg8.sw_if_index,
2852 is_inside=0)
Martin Gálik406eb1d2017-05-04 04:35:04 -07002853
2854 # in2out
2855 pkts = self.create_stream_in(self.pg7, self.pg8)
2856 self.pg7.add_stream(pkts)
2857 self.pg_enable_capture(self.pg_interfaces)
2858 self.pg_start()
2859 capture = self.pg8.get_capture(len(pkts))
2860 self.verify_capture_out(capture)
2861
2862 # out2in
Matus Fabian2ba92e32017-08-21 07:05:03 -07002863 pkts = self.create_stream_out(self.pg8, self.nat_addr)
Martin Gálik406eb1d2017-05-04 04:35:04 -07002864 self.pg8.add_stream(pkts)
2865 self.pg_enable_capture(self.pg_interfaces)
2866 self.pg_start()
2867 capture = self.pg7.get_capture(len(pkts))
2868 self.verify_capture_in(capture, self.pg7)
2869
2870 def test_static_ipless_interfaces(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002871 """ NAT44 interfaces without configured IP address - 1:1 NAT """
Martin Gálik406eb1d2017-05-04 04:35:04 -07002872
2873 self.vapi.ip_neighbor_add_del(self.pg7.sw_if_index,
Ole Troan895b6e82017-10-20 13:28:20 +02002874 mactobinary(self.pg7.remote_mac),
Martin Gálik406eb1d2017-05-04 04:35:04 -07002875 self.pg7.remote_ip4n,
2876 is_static=1)
2877 self.vapi.ip_neighbor_add_del(self.pg8.sw_if_index,
Ole Troan895b6e82017-10-20 13:28:20 +02002878 mactobinary(self.pg8.remote_mac),
Martin Gálik406eb1d2017-05-04 04:35:04 -07002879 self.pg8.remote_ip4n,
2880 is_static=1)
2881
2882 self.vapi.ip_add_del_route(dst_address=self.pg7.remote_ip4n,
2883 dst_address_length=32,
2884 next_hop_address=self.pg7.remote_ip4n,
2885 next_hop_sw_if_index=self.pg7.sw_if_index)
2886 self.vapi.ip_add_del_route(dst_address=self.pg8.remote_ip4n,
2887 dst_address_length=32,
2888 next_hop_address=self.pg8.remote_ip4n,
2889 next_hop_sw_if_index=self.pg8.sw_if_index)
2890
Matus Fabian2ba92e32017-08-21 07:05:03 -07002891 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr)
2892 self.vapi.nat44_interface_add_del_feature(self.pg7.sw_if_index)
2893 self.vapi.nat44_interface_add_del_feature(self.pg8.sw_if_index,
2894 is_inside=0)
Martin Gálik406eb1d2017-05-04 04:35:04 -07002895
2896 # out2in
2897 pkts = self.create_stream_out(self.pg8)
2898 self.pg8.add_stream(pkts)
2899 self.pg_enable_capture(self.pg_interfaces)
2900 self.pg_start()
2901 capture = self.pg7.get_capture(len(pkts))
2902 self.verify_capture_in(capture, self.pg7)
2903
2904 # in2out
2905 pkts = self.create_stream_in(self.pg7, self.pg8)
2906 self.pg7.add_stream(pkts)
2907 self.pg_enable_capture(self.pg_interfaces)
2908 self.pg_start()
2909 capture = self.pg8.get_capture(len(pkts))
Matus Fabian2ba92e32017-08-21 07:05:03 -07002910 self.verify_capture_out(capture, self.nat_addr, True)
Martin Gálik406eb1d2017-05-04 04:35:04 -07002911
2912 def test_static_with_port_ipless_interfaces(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002913 """ NAT44 interfaces without configured IP address - 1:1 NAPT """
Martin Gálik406eb1d2017-05-04 04:35:04 -07002914
2915 self.tcp_port_out = 30606
2916 self.udp_port_out = 30607
2917 self.icmp_id_out = 30608
2918
2919 self.vapi.ip_neighbor_add_del(self.pg7.sw_if_index,
Ole Troan895b6e82017-10-20 13:28:20 +02002920 mactobinary(self.pg7.remote_mac),
Martin Gálik406eb1d2017-05-04 04:35:04 -07002921 self.pg7.remote_ip4n,
2922 is_static=1)
2923 self.vapi.ip_neighbor_add_del(self.pg8.sw_if_index,
Ole Troan895b6e82017-10-20 13:28:20 +02002924 mactobinary(self.pg8.remote_mac),
Martin Gálik406eb1d2017-05-04 04:35:04 -07002925 self.pg8.remote_ip4n,
2926 is_static=1)
2927
2928 self.vapi.ip_add_del_route(dst_address=self.pg7.remote_ip4n,
2929 dst_address_length=32,
2930 next_hop_address=self.pg7.remote_ip4n,
2931 next_hop_sw_if_index=self.pg7.sw_if_index)
2932 self.vapi.ip_add_del_route(dst_address=self.pg8.remote_ip4n,
2933 dst_address_length=32,
2934 next_hop_address=self.pg8.remote_ip4n,
2935 next_hop_sw_if_index=self.pg8.sw_if_index)
2936
Matus Fabian2ba92e32017-08-21 07:05:03 -07002937 self.nat44_add_address(self.nat_addr)
2938 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
2939 self.tcp_port_in, self.tcp_port_out,
2940 proto=IP_PROTOS.tcp)
2941 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
2942 self.udp_port_in, self.udp_port_out,
2943 proto=IP_PROTOS.udp)
2944 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
2945 self.icmp_id_in, self.icmp_id_out,
2946 proto=IP_PROTOS.icmp)
2947 self.vapi.nat44_interface_add_del_feature(self.pg7.sw_if_index)
2948 self.vapi.nat44_interface_add_del_feature(self.pg8.sw_if_index,
2949 is_inside=0)
Martin Gálik406eb1d2017-05-04 04:35:04 -07002950
2951 # out2in
2952 pkts = self.create_stream_out(self.pg8)
2953 self.pg8.add_stream(pkts)
2954 self.pg_enable_capture(self.pg_interfaces)
2955 self.pg_start()
2956 capture = self.pg7.get_capture(len(pkts))
2957 self.verify_capture_in(capture, self.pg7)
2958
2959 # in2out
2960 pkts = self.create_stream_in(self.pg7, self.pg8)
2961 self.pg7.add_stream(pkts)
2962 self.pg_enable_capture(self.pg_interfaces)
2963 self.pg_start()
2964 capture = self.pg8.get_capture(len(pkts))
2965 self.verify_capture_out(capture)
2966
Matus Fabian328dbc82017-06-19 04:28:04 -07002967 def test_static_unknown_proto(self):
2968 """ 1:1 NAT translate packet with unknown protocol """
2969 nat_ip = "10.0.0.10"
Matus Fabian2ba92e32017-08-21 07:05:03 -07002970 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
2971 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2972 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2973 is_inside=0)
Matus Fabian328dbc82017-06-19 04:28:04 -07002974
2975 # in2out
2976 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2977 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2978 GRE() /
Matus Fabian1e8db5f2017-06-20 01:45:49 -07002979 IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4) /
Matus Fabian328dbc82017-06-19 04:28:04 -07002980 TCP(sport=1234, dport=1234))
2981 self.pg0.add_stream(p)
2982 self.pg_enable_capture(self.pg_interfaces)
2983 self.pg_start()
2984 p = self.pg1.get_capture(1)
2985 packet = p[0]
2986 try:
2987 self.assertEqual(packet[IP].src, nat_ip)
2988 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
2989 self.assertTrue(packet.haslayer(GRE))
Klement Sekerad81ae412018-05-16 10:52:54 +02002990 self.assert_packet_checksums_valid(packet)
Matus Fabian328dbc82017-06-19 04:28:04 -07002991 except:
2992 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2993 raise
2994
2995 # out2in
2996 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
2997 IP(src=self.pg1.remote_ip4, dst=nat_ip) /
2998 GRE() /
Matus Fabian1e8db5f2017-06-20 01:45:49 -07002999 IP(src=self.pg3.remote_ip4, dst=self.pg2.remote_ip4) /
Matus Fabian328dbc82017-06-19 04:28:04 -07003000 TCP(sport=1234, dport=1234))
3001 self.pg1.add_stream(p)
3002 self.pg_enable_capture(self.pg_interfaces)
3003 self.pg_start()
3004 p = self.pg0.get_capture(1)
3005 packet = p[0]
3006 try:
3007 self.assertEqual(packet[IP].src, self.pg1.remote_ip4)
3008 self.assertEqual(packet[IP].dst, self.pg0.remote_ip4)
3009 self.assertTrue(packet.haslayer(GRE))
Klement Sekerad81ae412018-05-16 10:52:54 +02003010 self.assert_packet_checksums_valid(packet)
Matus Fabian328dbc82017-06-19 04:28:04 -07003011 except:
3012 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3013 raise
3014
Matus Fabian7968e6c2017-07-06 05:37:49 -07003015 def test_hairpinning_static_unknown_proto(self):
Matus Fabian1e8db5f2017-06-20 01:45:49 -07003016 """ 1:1 NAT translate packet with unknown protocol - hairpinning """
3017
3018 host = self.pg0.remote_hosts[0]
3019 server = self.pg0.remote_hosts[1]
3020
3021 host_nat_ip = "10.0.0.10"
3022 server_nat_ip = "10.0.0.11"
3023
Matus Fabian2ba92e32017-08-21 07:05:03 -07003024 self.nat44_add_static_mapping(host.ip4, host_nat_ip)
3025 self.nat44_add_static_mapping(server.ip4, server_nat_ip)
3026 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3027 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3028 is_inside=0)
Matus Fabian1e8db5f2017-06-20 01:45:49 -07003029
3030 # host to server
3031 p = (Ether(dst=self.pg0.local_mac, src=host.mac) /
3032 IP(src=host.ip4, dst=server_nat_ip) /
3033 GRE() /
3034 IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4) /
3035 TCP(sport=1234, dport=1234))
3036 self.pg0.add_stream(p)
3037 self.pg_enable_capture(self.pg_interfaces)
3038 self.pg_start()
3039 p = self.pg0.get_capture(1)
3040 packet = p[0]
3041 try:
3042 self.assertEqual(packet[IP].src, host_nat_ip)
3043 self.assertEqual(packet[IP].dst, server.ip4)
3044 self.assertTrue(packet.haslayer(GRE))
Klement Sekerad81ae412018-05-16 10:52:54 +02003045 self.assert_packet_checksums_valid(packet)
Matus Fabian1e8db5f2017-06-20 01:45:49 -07003046 except:
3047 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3048 raise
3049
3050 # server to host
3051 p = (Ether(dst=self.pg0.local_mac, src=server.mac) /
3052 IP(src=server.ip4, dst=host_nat_ip) /
3053 GRE() /
3054 IP(src=self.pg3.remote_ip4, dst=self.pg2.remote_ip4) /
3055 TCP(sport=1234, dport=1234))
3056 self.pg0.add_stream(p)
3057 self.pg_enable_capture(self.pg_interfaces)
3058 self.pg_start()
3059 p = self.pg0.get_capture(1)
3060 packet = p[0]
3061 try:
3062 self.assertEqual(packet[IP].src, server_nat_ip)
3063 self.assertEqual(packet[IP].dst, host.ip4)
3064 self.assertTrue(packet.haslayer(GRE))
Klement Sekerad81ae412018-05-16 10:52:54 +02003065 self.assert_packet_checksums_valid(packet)
Matus Fabian1e8db5f2017-06-20 01:45:49 -07003066 except:
3067 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3068 raise
3069
Matus Fabian93d84c92017-07-19 08:06:01 -07003070 def test_output_feature(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07003071 """ NAT44 interface output feature (in2out postrouting) """
3072 self.nat44_add_address(self.nat_addr)
3073 self.vapi.nat44_interface_add_del_output_feature(self.pg0.sw_if_index)
Matus Fabianb2d2fc72017-09-10 22:17:47 -07003074 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index)
3075 self.vapi.nat44_interface_add_del_output_feature(self.pg3.sw_if_index,
Matus Fabian2ba92e32017-08-21 07:05:03 -07003076 is_inside=0)
Matus Fabian93d84c92017-07-19 08:06:01 -07003077
3078 # in2out
Matus Fabianb2d2fc72017-09-10 22:17:47 -07003079 pkts = self.create_stream_in(self.pg0, self.pg3)
Matus Fabian93d84c92017-07-19 08:06:01 -07003080 self.pg0.add_stream(pkts)
3081 self.pg_enable_capture(self.pg_interfaces)
3082 self.pg_start()
Matus Fabianb2d2fc72017-09-10 22:17:47 -07003083 capture = self.pg3.get_capture(len(pkts))
Matus Fabian93d84c92017-07-19 08:06:01 -07003084 self.verify_capture_out(capture)
3085
3086 # out2in
Matus Fabianb2d2fc72017-09-10 22:17:47 -07003087 pkts = self.create_stream_out(self.pg3)
3088 self.pg3.add_stream(pkts)
Matus Fabian93d84c92017-07-19 08:06:01 -07003089 self.pg_enable_capture(self.pg_interfaces)
3090 self.pg_start()
3091 capture = self.pg0.get_capture(len(pkts))
3092 self.verify_capture_in(capture, self.pg0)
3093
Matus Fabianb2d2fc72017-09-10 22:17:47 -07003094 # from non-NAT interface to NAT inside interface
3095 pkts = self.create_stream_in(self.pg2, self.pg0)
3096 self.pg2.add_stream(pkts)
3097 self.pg_enable_capture(self.pg_interfaces)
3098 self.pg_start()
3099 capture = self.pg0.get_capture(len(pkts))
3100 self.verify_capture_no_translation(capture, self.pg2, self.pg0)
3101
Matus Fabian93d84c92017-07-19 08:06:01 -07003102 def test_output_feature_vrf_aware(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07003103 """ NAT44 interface output feature VRF aware (in2out postrouting) """
Matus Fabian93d84c92017-07-19 08:06:01 -07003104 nat_ip_vrf10 = "10.0.0.10"
3105 nat_ip_vrf20 = "10.0.0.20"
3106
3107 self.vapi.ip_add_del_route(dst_address=self.pg3.remote_ip4n,
3108 dst_address_length=32,
3109 next_hop_address=self.pg3.remote_ip4n,
3110 next_hop_sw_if_index=self.pg3.sw_if_index,
3111 table_id=10)
3112 self.vapi.ip_add_del_route(dst_address=self.pg3.remote_ip4n,
3113 dst_address_length=32,
3114 next_hop_address=self.pg3.remote_ip4n,
3115 next_hop_sw_if_index=self.pg3.sw_if_index,
3116 table_id=20)
3117
Matus Fabian2ba92e32017-08-21 07:05:03 -07003118 self.nat44_add_address(nat_ip_vrf10, vrf_id=10)
3119 self.nat44_add_address(nat_ip_vrf20, vrf_id=20)
3120 self.vapi.nat44_interface_add_del_output_feature(self.pg4.sw_if_index)
3121 self.vapi.nat44_interface_add_del_output_feature(self.pg6.sw_if_index)
3122 self.vapi.nat44_interface_add_del_output_feature(self.pg3.sw_if_index,
3123 is_inside=0)
Matus Fabian93d84c92017-07-19 08:06:01 -07003124
3125 # in2out VRF 10
3126 pkts = self.create_stream_in(self.pg4, self.pg3)
3127 self.pg4.add_stream(pkts)
3128 self.pg_enable_capture(self.pg_interfaces)
3129 self.pg_start()
3130 capture = self.pg3.get_capture(len(pkts))
3131 self.verify_capture_out(capture, nat_ip=nat_ip_vrf10)
3132
3133 # out2in VRF 10
3134 pkts = self.create_stream_out(self.pg3, dst_ip=nat_ip_vrf10)
3135 self.pg3.add_stream(pkts)
3136 self.pg_enable_capture(self.pg_interfaces)
3137 self.pg_start()
3138 capture = self.pg4.get_capture(len(pkts))
3139 self.verify_capture_in(capture, self.pg4)
3140
3141 # in2out VRF 20
3142 pkts = self.create_stream_in(self.pg6, self.pg3)
3143 self.pg6.add_stream(pkts)
3144 self.pg_enable_capture(self.pg_interfaces)
3145 self.pg_start()
3146 capture = self.pg3.get_capture(len(pkts))
3147 self.verify_capture_out(capture, nat_ip=nat_ip_vrf20)
3148
3149 # out2in VRF 20
3150 pkts = self.create_stream_out(self.pg3, dst_ip=nat_ip_vrf20)
3151 self.pg3.add_stream(pkts)
3152 self.pg_enable_capture(self.pg_interfaces)
3153 self.pg_start()
3154 capture = self.pg6.get_capture(len(pkts))
3155 self.verify_capture_in(capture, self.pg6)
3156
Matus Fabian161c59c2017-07-21 03:46:03 -07003157 def test_output_feature_hairpinning(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07003158 """ NAT44 interface output feature hairpinning (in2out postrouting) """
Matus Fabian93d84c92017-07-19 08:06:01 -07003159 host = self.pg0.remote_hosts[0]
3160 server = self.pg0.remote_hosts[1]
3161 host_in_port = 1234
3162 host_out_port = 0
3163 server_in_port = 5678
3164 server_out_port = 8765
3165
Matus Fabian2ba92e32017-08-21 07:05:03 -07003166 self.nat44_add_address(self.nat_addr)
3167 self.vapi.nat44_interface_add_del_output_feature(self.pg0.sw_if_index)
3168 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
3169 is_inside=0)
Matus Fabian93d84c92017-07-19 08:06:01 -07003170
3171 # add static mapping for server
Matus Fabian2ba92e32017-08-21 07:05:03 -07003172 self.nat44_add_static_mapping(server.ip4, self.nat_addr,
3173 server_in_port, server_out_port,
3174 proto=IP_PROTOS.tcp)
Matus Fabian93d84c92017-07-19 08:06:01 -07003175
3176 # send packet from host to server
3177 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07003178 IP(src=host.ip4, dst=self.nat_addr) /
Matus Fabian93d84c92017-07-19 08:06:01 -07003179 TCP(sport=host_in_port, dport=server_out_port))
3180 self.pg0.add_stream(p)
3181 self.pg_enable_capture(self.pg_interfaces)
3182 self.pg_start()
3183 capture = self.pg0.get_capture(1)
3184 p = capture[0]
3185 try:
3186 ip = p[IP]
3187 tcp = p[TCP]
Matus Fabian2ba92e32017-08-21 07:05:03 -07003188 self.assertEqual(ip.src, self.nat_addr)
Matus Fabian93d84c92017-07-19 08:06:01 -07003189 self.assertEqual(ip.dst, server.ip4)
3190 self.assertNotEqual(tcp.sport, host_in_port)
3191 self.assertEqual(tcp.dport, server_in_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02003192 self.assert_packet_checksums_valid(p)
Matus Fabian93d84c92017-07-19 08:06:01 -07003193 host_out_port = tcp.sport
3194 except:
3195 self.logger.error(ppp("Unexpected or invalid packet:", p))
3196 raise
3197
3198 # send reply from server to host
3199 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07003200 IP(src=server.ip4, dst=self.nat_addr) /
Matus Fabian93d84c92017-07-19 08:06:01 -07003201 TCP(sport=server_in_port, dport=host_out_port))
3202 self.pg0.add_stream(p)
3203 self.pg_enable_capture(self.pg_interfaces)
3204 self.pg_start()
3205 capture = self.pg0.get_capture(1)
3206 p = capture[0]
3207 try:
3208 ip = p[IP]
3209 tcp = p[TCP]
Matus Fabian2ba92e32017-08-21 07:05:03 -07003210 self.assertEqual(ip.src, self.nat_addr)
Matus Fabian93d84c92017-07-19 08:06:01 -07003211 self.assertEqual(ip.dst, host.ip4)
3212 self.assertEqual(tcp.sport, server_out_port)
3213 self.assertEqual(tcp.dport, host_in_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02003214 self.assert_packet_checksums_valid(p)
Matus Fabian93d84c92017-07-19 08:06:01 -07003215 except:
Matus Fabiane82488f2018-01-18 03:38:45 -08003216 self.logger.error(ppp("Unexpected or invalid packet:", p))
Matus Fabian93d84c92017-07-19 08:06:01 -07003217 raise
3218
Matus Fabian36ea2d62017-10-24 04:13:49 -07003219 def test_one_armed_nat44(self):
3220 """ One armed NAT44 """
3221 remote_host = self.pg9.remote_hosts[0]
3222 local_host = self.pg9.remote_hosts[1]
3223 external_port = 0
3224
3225 self.nat44_add_address(self.nat_addr)
3226 self.vapi.nat44_interface_add_del_feature(self.pg9.sw_if_index)
3227 self.vapi.nat44_interface_add_del_feature(self.pg9.sw_if_index,
3228 is_inside=0)
3229
3230 # in2out
3231 p = (Ether(src=self.pg9.remote_mac, dst=self.pg9.local_mac) /
3232 IP(src=local_host.ip4, dst=remote_host.ip4) /
3233 TCP(sport=12345, dport=80))
3234 self.pg9.add_stream(p)
3235 self.pg_enable_capture(self.pg_interfaces)
3236 self.pg_start()
3237 capture = self.pg9.get_capture(1)
3238 p = capture[0]
3239 try:
3240 ip = p[IP]
3241 tcp = p[TCP]
3242 self.assertEqual(ip.src, self.nat_addr)
3243 self.assertEqual(ip.dst, remote_host.ip4)
3244 self.assertNotEqual(tcp.sport, 12345)
3245 external_port = tcp.sport
3246 self.assertEqual(tcp.dport, 80)
Klement Sekerad81ae412018-05-16 10:52:54 +02003247 self.assert_packet_checksums_valid(p)
Matus Fabian36ea2d62017-10-24 04:13:49 -07003248 except:
3249 self.logger.error(ppp("Unexpected or invalid packet:", p))
3250 raise
3251
3252 # out2in
3253 p = (Ether(src=self.pg9.remote_mac, dst=self.pg9.local_mac) /
3254 IP(src=remote_host.ip4, dst=self.nat_addr) /
3255 TCP(sport=80, dport=external_port))
3256 self.pg9.add_stream(p)
3257 self.pg_enable_capture(self.pg_interfaces)
3258 self.pg_start()
3259 capture = self.pg9.get_capture(1)
3260 p = capture[0]
3261 try:
3262 ip = p[IP]
3263 tcp = p[TCP]
3264 self.assertEqual(ip.src, remote_host.ip4)
3265 self.assertEqual(ip.dst, local_host.ip4)
3266 self.assertEqual(tcp.sport, 80)
3267 self.assertEqual(tcp.dport, 12345)
Klement Sekerad81ae412018-05-16 10:52:54 +02003268 self.assert_packet_checksums_valid(p)
Matus Fabian36ea2d62017-10-24 04:13:49 -07003269 except:
3270 self.logger.error(ppp("Unexpected or invalid packet:", p))
3271 raise
3272
Matus Fabian5ba86f72017-10-26 03:37:38 -07003273 def test_del_session(self):
3274 """ Delete NAT44 session """
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
3280 pkts = self.create_stream_in(self.pg0, self.pg1)
3281 self.pg0.add_stream(pkts)
3282 self.pg_enable_capture(self.pg_interfaces)
3283 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07003284 self.pg1.get_capture(len(pkts))
Matus Fabian5ba86f72017-10-26 03:37:38 -07003285
3286 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
3287 nsessions = len(sessions)
3288
3289 self.vapi.nat44_del_session(sessions[0].inside_ip_address,
3290 sessions[0].inside_port,
3291 sessions[0].protocol)
3292 self.vapi.nat44_del_session(sessions[1].outside_ip_address,
3293 sessions[1].outside_port,
3294 sessions[1].protocol,
3295 is_in=0)
3296
3297 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
3298 self.assertEqual(nsessions - len(sessions), 2)
3299
Matus Fabian68ba8802018-08-08 05:52:47 -07003300 self.vapi.nat44_del_session(sessions[0].inside_ip_address,
3301 sessions[0].inside_port,
3302 sessions[0].protocol)
3303
3304 self.verify_no_nat44_user()
3305
Matus Fabianefcd1e92017-08-15 06:59:19 -07003306 def test_set_get_reass(self):
3307 """ NAT44 set/get virtual fragmentation reassembly """
3308 reas_cfg1 = self.vapi.nat_get_reass()
3309
3310 self.vapi.nat_set_reass(timeout=reas_cfg1.ip4_timeout + 5,
3311 max_reass=reas_cfg1.ip4_max_reass * 2,
3312 max_frag=reas_cfg1.ip4_max_frag * 2)
3313
3314 reas_cfg2 = self.vapi.nat_get_reass()
3315
3316 self.assertEqual(reas_cfg1.ip4_timeout + 5, reas_cfg2.ip4_timeout)
3317 self.assertEqual(reas_cfg1.ip4_max_reass * 2, reas_cfg2.ip4_max_reass)
3318 self.assertEqual(reas_cfg1.ip4_max_frag * 2, reas_cfg2.ip4_max_frag)
3319
3320 self.vapi.nat_set_reass(drop_frag=1)
3321 self.assertTrue(self.vapi.nat_get_reass().ip4_drop_frag)
3322
3323 def test_frag_in_order(self):
3324 """ NAT44 translate fragments arriving in order """
Juraj Slobodafe0aa762018-07-23 12:22:54 +02003325
Matus Fabianefcd1e92017-08-15 06:59:19 -07003326 self.nat44_add_address(self.nat_addr)
3327 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3328 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3329 is_inside=0)
3330
3331 data = "A" * 4 + "B" * 16 + "C" * 3
3332 self.tcp_port_in = random.randint(1025, 65535)
3333
3334 reass = self.vapi.nat_reass_dump()
3335 reass_n_start = len(reass)
3336
3337 # in2out
3338 pkts = self.create_stream_frag(self.pg0,
3339 self.pg1.remote_ip4,
3340 self.tcp_port_in,
3341 20,
3342 data)
3343 self.pg0.add_stream(pkts)
3344 self.pg_enable_capture(self.pg_interfaces)
3345 self.pg_start()
3346 frags = self.pg1.get_capture(len(pkts))
3347 p = self.reass_frags_and_verify(frags,
3348 self.nat_addr,
3349 self.pg1.remote_ip4)
3350 self.assertEqual(p[TCP].dport, 20)
3351 self.assertNotEqual(p[TCP].sport, self.tcp_port_in)
3352 self.tcp_port_out = p[TCP].sport
3353 self.assertEqual(data, p[Raw].load)
3354
3355 # out2in
3356 pkts = self.create_stream_frag(self.pg1,
3357 self.nat_addr,
3358 20,
3359 self.tcp_port_out,
3360 data)
3361 self.pg1.add_stream(pkts)
3362 self.pg_enable_capture(self.pg_interfaces)
3363 self.pg_start()
3364 frags = self.pg0.get_capture(len(pkts))
3365 p = self.reass_frags_and_verify(frags,
3366 self.pg1.remote_ip4,
3367 self.pg0.remote_ip4)
3368 self.assertEqual(p[TCP].sport, 20)
3369 self.assertEqual(p[TCP].dport, self.tcp_port_in)
3370 self.assertEqual(data, p[Raw].load)
3371
3372 reass = self.vapi.nat_reass_dump()
3373 reass_n_end = len(reass)
3374
3375 self.assertEqual(reass_n_end - reass_n_start, 2)
3376
3377 def test_reass_hairpinning(self):
3378 """ NAT44 fragments hairpinning """
Juraj Slobodafe0aa762018-07-23 12:22:54 +02003379
Matus Fabianefcd1e92017-08-15 06:59:19 -07003380 server = self.pg0.remote_hosts[1]
3381 host_in_port = random.randint(1025, 65535)
Matus Fabianefcd1e92017-08-15 06:59:19 -07003382 server_in_port = random.randint(1025, 65535)
3383 server_out_port = random.randint(1025, 65535)
3384 data = "A" * 4 + "B" * 16 + "C" * 3
3385
3386 self.nat44_add_address(self.nat_addr)
3387 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3388 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3389 is_inside=0)
3390 # add static mapping for server
3391 self.nat44_add_static_mapping(server.ip4, self.nat_addr,
3392 server_in_port, server_out_port,
3393 proto=IP_PROTOS.tcp)
3394
3395 # send packet from host to server
3396 pkts = self.create_stream_frag(self.pg0,
3397 self.nat_addr,
3398 host_in_port,
3399 server_out_port,
3400 data)
3401 self.pg0.add_stream(pkts)
3402 self.pg_enable_capture(self.pg_interfaces)
3403 self.pg_start()
3404 frags = self.pg0.get_capture(len(pkts))
3405 p = self.reass_frags_and_verify(frags,
3406 self.nat_addr,
3407 server.ip4)
3408 self.assertNotEqual(p[TCP].sport, host_in_port)
3409 self.assertEqual(p[TCP].dport, server_in_port)
3410 self.assertEqual(data, p[Raw].load)
3411
3412 def test_frag_out_of_order(self):
3413 """ NAT44 translate fragments arriving out of order """
Juraj Slobodafe0aa762018-07-23 12:22:54 +02003414
Matus Fabianefcd1e92017-08-15 06:59:19 -07003415 self.nat44_add_address(self.nat_addr)
3416 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3417 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3418 is_inside=0)
3419
3420 data = "A" * 4 + "B" * 16 + "C" * 3
3421 random.randint(1025, 65535)
3422
3423 # in2out
3424 pkts = self.create_stream_frag(self.pg0,
3425 self.pg1.remote_ip4,
3426 self.tcp_port_in,
3427 20,
3428 data)
3429 pkts.reverse()
3430 self.pg0.add_stream(pkts)
3431 self.pg_enable_capture(self.pg_interfaces)
3432 self.pg_start()
3433 frags = self.pg1.get_capture(len(pkts))
3434 p = self.reass_frags_and_verify(frags,
3435 self.nat_addr,
3436 self.pg1.remote_ip4)
3437 self.assertEqual(p[TCP].dport, 20)
3438 self.assertNotEqual(p[TCP].sport, self.tcp_port_in)
3439 self.tcp_port_out = p[TCP].sport
3440 self.assertEqual(data, p[Raw].load)
3441
3442 # out2in
3443 pkts = self.create_stream_frag(self.pg1,
3444 self.nat_addr,
3445 20,
3446 self.tcp_port_out,
3447 data)
3448 pkts.reverse()
3449 self.pg1.add_stream(pkts)
3450 self.pg_enable_capture(self.pg_interfaces)
3451 self.pg_start()
3452 frags = self.pg0.get_capture(len(pkts))
3453 p = self.reass_frags_and_verify(frags,
3454 self.pg1.remote_ip4,
3455 self.pg0.remote_ip4)
3456 self.assertEqual(p[TCP].sport, 20)
3457 self.assertEqual(p[TCP].dport, self.tcp_port_in)
3458 self.assertEqual(data, p[Raw].load)
3459
Matus Fabian27697102017-11-09 01:43:47 -08003460 def test_port_restricted(self):
3461 """ Port restricted NAT44 (MAP-E CE) """
3462 self.nat44_add_address(self.nat_addr)
3463 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3464 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3465 is_inside=0)
Matus Fabian5d28c7a2018-09-04 03:55:45 -07003466 self.vapi.nat_set_addr_and_port_alloc_alg(alg=1,
3467 psid_offset=6,
3468 psid_length=6,
3469 psid=10)
Matus Fabian27697102017-11-09 01:43:47 -08003470
3471 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3472 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3473 TCP(sport=4567, dport=22))
3474 self.pg0.add_stream(p)
3475 self.pg_enable_capture(self.pg_interfaces)
3476 self.pg_start()
3477 capture = self.pg1.get_capture(1)
3478 p = capture[0]
3479 try:
3480 ip = p[IP]
3481 tcp = p[TCP]
3482 self.assertEqual(ip.dst, self.pg1.remote_ip4)
3483 self.assertEqual(ip.src, self.nat_addr)
3484 self.assertEqual(tcp.dport, 22)
3485 self.assertNotEqual(tcp.sport, 4567)
3486 self.assertEqual((tcp.sport >> 6) & 63, 10)
Klement Sekerad81ae412018-05-16 10:52:54 +02003487 self.assert_packet_checksums_valid(p)
Matus Fabian27697102017-11-09 01:43:47 -08003488 except:
3489 self.logger.error(ppp("Unexpected or invalid packet:", p))
3490 raise
3491
Matus Fabian5d28c7a2018-09-04 03:55:45 -07003492 def test_port_range(self):
3493 """ External address port range """
3494 self.nat44_add_address(self.nat_addr)
3495 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3496 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3497 is_inside=0)
3498 self.vapi.nat_set_addr_and_port_alloc_alg(alg=2,
3499 start_port=1025,
3500 end_port=1027)
3501
3502 pkts = []
3503 for port in range(0, 5):
3504 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3505 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3506 TCP(sport=1125 + port))
3507 pkts.append(p)
3508 self.pg0.add_stream(pkts)
3509 self.pg_enable_capture(self.pg_interfaces)
3510 self.pg_start()
3511 capture = self.pg1.get_capture(3)
3512 for p in capture:
3513 tcp = p[TCP]
3514 self.assertGreaterEqual(tcp.sport, 1025)
3515 self.assertLessEqual(tcp.sport, 1027)
3516
Matus Fabiana6110b62018-06-13 05:39:07 -07003517 def test_ipfix_max_frags(self):
3518 """ IPFIX logging maximum fragments pending reassembly exceeded """
3519 self.nat44_add_address(self.nat_addr)
3520 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3521 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3522 is_inside=0)
Matus Fabiana7f8b222018-09-05 06:01:55 -07003523 self.vapi.nat_set_reass(max_frag=1)
Matus Fabiana6110b62018-06-13 05:39:07 -07003524 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
3525 src_address=self.pg3.local_ip4n,
3526 path_mtu=512,
3527 template_interval=10)
3528 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
3529 src_port=self.ipfix_src_port)
3530
3531 data = "A" * 4 + "B" * 16 + "C" * 3
3532 self.tcp_port_in = random.randint(1025, 65535)
3533 pkts = self.create_stream_frag(self.pg0,
3534 self.pg1.remote_ip4,
3535 self.tcp_port_in,
3536 20,
3537 data)
Matus Fabiana7f8b222018-09-05 06:01:55 -07003538 pkts.reverse()
3539 self.pg0.add_stream(pkts)
Matus Fabiana6110b62018-06-13 05:39:07 -07003540 self.pg_enable_capture(self.pg_interfaces)
3541 self.pg_start()
3542 self.pg1.assert_nothing_captured()
3543 sleep(1)
3544 self.vapi.cli("ipfix flush") # FIXME this should be an API call
3545 capture = self.pg3.get_capture(9)
3546 ipfix = IPFIXDecoder()
3547 # first load template
3548 for p in capture:
3549 self.assertTrue(p.haslayer(IPFIX))
3550 self.assertEqual(p[IP].src, self.pg3.local_ip4)
3551 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
3552 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
3553 self.assertEqual(p[UDP].dport, 4739)
3554 self.assertEqual(p[IPFIX].observationDomainID,
3555 self.ipfix_domain_id)
3556 if p.haslayer(Template):
3557 ipfix.add_template(p.getlayer(Template))
3558 # verify events in data set
3559 for p in capture:
3560 if p.haslayer(Data):
3561 data = ipfix.decode_data_set(p.getlayer(Set))
Matus Fabiana7f8b222018-09-05 06:01:55 -07003562 self.verify_ipfix_max_fragments_ip4(data, 1,
Matus Fabiana6110b62018-06-13 05:39:07 -07003563 self.pg0.remote_ip4n)
3564
Matus Fabian8008d7c2018-07-09 01:34:20 -07003565 def test_multiple_outside_vrf(self):
3566 """ Multiple outside VRF """
3567 vrf_id1 = 1
3568 vrf_id2 = 2
3569
3570 self.pg1.unconfig_ip4()
3571 self.pg2.unconfig_ip4()
3572 self.vapi.ip_table_add_del(vrf_id1, is_add=1)
3573 self.vapi.ip_table_add_del(vrf_id2, is_add=1)
3574 self.pg1.set_table_ip4(vrf_id1)
3575 self.pg2.set_table_ip4(vrf_id2)
3576 self.pg1.config_ip4()
3577 self.pg2.config_ip4()
3578 self.pg1.resolve_arp()
3579 self.pg2.resolve_arp()
3580
3581 self.nat44_add_address(self.nat_addr)
3582 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3583 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3584 is_inside=0)
3585 self.vapi.nat44_interface_add_del_feature(self.pg2.sw_if_index,
3586 is_inside=0)
3587
3588 try:
3589 # first VRF
3590 pkts = self.create_stream_in(self.pg0, self.pg1)
3591 self.pg0.add_stream(pkts)
3592 self.pg_enable_capture(self.pg_interfaces)
3593 self.pg_start()
3594 capture = self.pg1.get_capture(len(pkts))
3595 self.verify_capture_out(capture, self.nat_addr)
3596
3597 pkts = self.create_stream_out(self.pg1, self.nat_addr)
3598 self.pg1.add_stream(pkts)
3599 self.pg_enable_capture(self.pg_interfaces)
3600 self.pg_start()
3601 capture = self.pg0.get_capture(len(pkts))
3602 self.verify_capture_in(capture, self.pg0)
3603
3604 self.tcp_port_in = 60303
3605 self.udp_port_in = 60304
3606 self.icmp_id_in = 60305
3607
3608 # second VRF
3609 pkts = self.create_stream_in(self.pg0, self.pg2)
3610 self.pg0.add_stream(pkts)
3611 self.pg_enable_capture(self.pg_interfaces)
3612 self.pg_start()
3613 capture = self.pg2.get_capture(len(pkts))
3614 self.verify_capture_out(capture, self.nat_addr)
3615
3616 pkts = self.create_stream_out(self.pg2, self.nat_addr)
3617 self.pg2.add_stream(pkts)
3618 self.pg_enable_capture(self.pg_interfaces)
3619 self.pg_start()
3620 capture = self.pg0.get_capture(len(pkts))
3621 self.verify_capture_in(capture, self.pg0)
3622
3623 finally:
3624 self.pg1.unconfig_ip4()
3625 self.pg2.unconfig_ip4()
3626 self.pg1.set_table_ip4(0)
3627 self.pg2.set_table_ip4(0)
3628 self.pg1.config_ip4()
3629 self.pg2.config_ip4()
3630 self.pg1.resolve_arp()
3631 self.pg2.resolve_arp()
3632
Matus Fabian878c6462018-08-23 00:33:35 -07003633 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
3634 def test_session_timeout(self):
3635 """ NAT44 session timeouts """
3636 self.nat44_add_address(self.nat_addr)
3637 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3638 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3639 is_inside=0)
3640 self.vapi.nat_set_timeouts(udp=5)
3641
3642 max_sessions = 1000
3643 pkts = []
3644 for i in range(0, max_sessions):
3645 src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
3646 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3647 IP(src=src, dst=self.pg1.remote_ip4) /
3648 UDP(sport=1025, dport=53))
3649 pkts.append(p)
3650 self.pg0.add_stream(pkts)
3651 self.pg_enable_capture(self.pg_interfaces)
3652 self.pg_start()
3653 self.pg1.get_capture(max_sessions)
3654
3655 sleep(6)
3656
3657 pkts = []
3658 for i in range(0, max_sessions):
3659 src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
3660 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3661 IP(src=src, dst=self.pg1.remote_ip4) /
3662 UDP(sport=1026, dport=53))
3663 pkts.append(p)
3664 self.pg0.add_stream(pkts)
3665 self.pg_enable_capture(self.pg_interfaces)
3666 self.pg_start()
3667 self.pg1.get_capture(max_sessions)
3668
3669 nsessions = 0
3670 users = self.vapi.nat44_user_dump()
3671 for user in users:
3672 nsessions = nsessions + user.nsessions
3673 self.assertLess(nsessions, 2 * max_sessions)
3674
Matus Fabianbb4e0222018-09-13 02:36:25 -07003675 def test_mss_clamping(self):
3676 """ TCP MSS clamping """
3677 self.nat44_add_address(self.nat_addr)
3678 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3679 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3680 is_inside=0)
3681
3682 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3683 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3684 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
3685 flags="S", options=[('MSS', 1400)]))
3686
3687 self.vapi.nat_set_mss_clamping(enable=1, mss_value=1000)
3688 self.pg0.add_stream(p)
3689 self.pg_enable_capture(self.pg_interfaces)
3690 self.pg_start()
3691 capture = self.pg1.get_capture(1)
3692 # Negotiated MSS value greater than configured - changed
3693 self.verify_mss_value(capture[0], 1000)
3694
3695 self.vapi.nat_set_mss_clamping(enable=0)
3696 self.pg0.add_stream(p)
3697 self.pg_enable_capture(self.pg_interfaces)
3698 self.pg_start()
3699 capture = self.pg1.get_capture(1)
3700 # MSS clamping disabled - negotiated MSS unchanged
3701 self.verify_mss_value(capture[0], 1400)
3702
3703 self.vapi.nat_set_mss_clamping(enable=1, mss_value=1500)
3704 self.pg0.add_stream(p)
3705 self.pg_enable_capture(self.pg_interfaces)
3706 self.pg_start()
3707 capture = self.pg1.get_capture(1)
3708 # Negotiated MSS value smaller than configured - unchanged
3709 self.verify_mss_value(capture[0], 1400)
3710
Matus Fabiana6110b62018-06-13 05:39:07 -07003711 def tearDown(self):
3712 super(TestNAT44, self).tearDown()
3713 if not self.vpp_dead:
3714 self.logger.info(self.vapi.cli("show nat44 addresses"))
3715 self.logger.info(self.vapi.cli("show nat44 interfaces"))
3716 self.logger.info(self.vapi.cli("show nat44 static mappings"))
3717 self.logger.info(self.vapi.cli("show nat44 interface address"))
3718 self.logger.info(self.vapi.cli("show nat44 sessions detail"))
3719 self.logger.info(self.vapi.cli("show nat virtual-reassembly"))
3720 self.logger.info(self.vapi.cli("show nat44 hash tables detail"))
Matus Fabian878c6462018-08-23 00:33:35 -07003721 self.logger.info(self.vapi.cli("show nat timeouts"))
Matus Fabian5d28c7a2018-09-04 03:55:45 -07003722 self.logger.info(
3723 self.vapi.cli("show nat addr-port-assignment-alg"))
Matus Fabiana6110b62018-06-13 05:39:07 -07003724 self.clear_nat44()
3725 self.vapi.cli("clear logging")
3726
3727
3728class TestNAT44EndpointDependent(MethodHolder):
3729 """ Endpoint-Dependent mapping and filtering test cases """
3730
3731 @classmethod
3732 def setUpConstants(cls):
3733 super(TestNAT44EndpointDependent, cls).setUpConstants()
3734 cls.vpp_cmdline.extend(["nat", "{", "endpoint-dependent", "}"])
3735
3736 @classmethod
3737 def setUpClass(cls):
3738 super(TestNAT44EndpointDependent, cls).setUpClass()
3739 cls.vapi.cli("set log class nat level debug")
3740 try:
3741 cls.tcp_port_in = 6303
3742 cls.tcp_port_out = 6303
3743 cls.udp_port_in = 6304
3744 cls.udp_port_out = 6304
3745 cls.icmp_id_in = 6305
3746 cls.icmp_id_out = 6305
3747 cls.nat_addr = '10.0.0.3'
3748 cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
3749 cls.ipfix_src_port = 4739
3750 cls.ipfix_domain_id = 1
3751 cls.tcp_external_port = 80
3752
Matus Fabian8008d7c2018-07-09 01:34:20 -07003753 cls.create_pg_interfaces(range(7))
Matus Fabiana6110b62018-06-13 05:39:07 -07003754 cls.interfaces = list(cls.pg_interfaces[0:3])
3755
3756 for i in cls.interfaces:
3757 i.admin_up()
3758 i.config_ip4()
3759 i.resolve_arp()
3760
3761 cls.pg0.generate_remote_hosts(3)
3762 cls.pg0.configure_ipv4_neighbors()
3763
3764 cls.pg3.admin_up()
3765
3766 cls.pg4.generate_remote_hosts(2)
3767 cls.pg4.config_ip4()
3768 ip_addr_n = socket.inet_pton(socket.AF_INET, "10.0.0.1")
3769 cls.vapi.sw_interface_add_del_address(cls.pg4.sw_if_index,
3770 ip_addr_n,
3771 24)
3772 cls.pg4.admin_up()
3773 cls.pg4.resolve_arp()
3774 cls.pg4._remote_hosts[1]._ip4 = cls.pg4._remote_hosts[0]._ip4
3775 cls.pg4.resolve_arp()
3776
Matus Fabian8008d7c2018-07-09 01:34:20 -07003777 zero_ip4n = socket.inet_pton(socket.AF_INET, "0.0.0.0")
3778 cls.vapi.ip_table_add_del(1, is_add=1)
3779
3780 cls.pg5._local_ip4 = "10.1.1.1"
3781 cls.pg5._local_ip4n = socket.inet_pton(socket.AF_INET,
3782 cls.pg5.local_ip4)
3783 cls.pg5._remote_hosts[0]._ip4 = "10.1.1.2"
3784 cls.pg5._remote_hosts[0]._ip4n = socket.inet_pton(
3785 socket.AF_INET, cls.pg5.remote_ip4)
3786 cls.pg5.set_table_ip4(1)
3787 cls.pg5.config_ip4()
3788 cls.pg5.admin_up()
3789 cls.vapi.ip_add_del_route(dst_address=cls.pg5.remote_ip4n,
3790 dst_address_length=32,
3791 table_id=1,
3792 next_hop_sw_if_index=cls.pg5.sw_if_index,
3793 next_hop_address=zero_ip4n)
3794
3795 cls.pg6._local_ip4 = "10.1.2.1"
3796 cls.pg6._local_ip4n = socket.inet_pton(socket.AF_INET,
3797 cls.pg6.local_ip4)
3798 cls.pg6._remote_hosts[0]._ip4 = "10.1.2.2"
3799 cls.pg6._remote_hosts[0]._ip4n = socket.inet_pton(
3800 socket.AF_INET, cls.pg6.remote_ip4)
3801 cls.pg6.set_table_ip4(1)
3802 cls.pg6.config_ip4()
3803 cls.pg6.admin_up()
3804 cls.vapi.ip_add_del_route(dst_address=cls.pg6.remote_ip4n,
3805 dst_address_length=32,
3806 table_id=1,
3807 next_hop_sw_if_index=cls.pg6.sw_if_index,
3808 next_hop_address=zero_ip4n)
3809
3810 cls.vapi.ip_add_del_route(dst_address=cls.pg6.remote_ip4n,
3811 dst_address_length=16,
3812 next_hop_address=zero_ip4n,
3813 table_id=0,
3814 next_hop_table_id=1)
3815 cls.vapi.ip_add_del_route(dst_address=zero_ip4n,
3816 dst_address_length=0,
3817 next_hop_address=zero_ip4n,
3818 table_id=1,
3819 next_hop_table_id=0)
3820 cls.vapi.ip_add_del_route(dst_address=zero_ip4n,
3821 dst_address_length=0,
3822 table_id=0,
3823 next_hop_sw_if_index=cls.pg1.sw_if_index,
3824 next_hop_address=cls.pg1.local_ip4n)
3825
3826 cls.pg5.resolve_arp()
3827 cls.pg6.resolve_arp()
3828
Matus Fabiana6110b62018-06-13 05:39:07 -07003829 except Exception:
3830 super(TestNAT44EndpointDependent, cls).tearDownClass()
3831 raise
3832
Juraj Slobodafe0aa762018-07-23 12:22:54 +02003833 def test_frag_in_order(self):
3834 """ NAT44 translate fragments arriving in order """
3835 self.nat44_add_address(self.nat_addr)
3836 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3837 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3838 is_inside=0)
3839 self.frag_in_order(proto=IP_PROTOS.tcp)
3840 self.frag_in_order(proto=IP_PROTOS.udp)
3841 self.frag_in_order(proto=IP_PROTOS.icmp)
3842
3843 def test_frag_in_order_dont_translate(self):
3844 """ NAT44 don't translate fragments arriving in order """
3845 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3846 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3847 is_inside=0)
3848 self.vapi.nat44_forwarding_enable_disable(enable=True)
3849 self.frag_in_order(proto=IP_PROTOS.tcp, dont_translate=True)
3850
3851 def test_frag_out_of_order(self):
3852 """ NAT44 translate fragments arriving out of order """
3853 self.nat44_add_address(self.nat_addr)
3854 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3855 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3856 is_inside=0)
3857 self.frag_out_of_order(proto=IP_PROTOS.tcp)
3858 self.frag_out_of_order(proto=IP_PROTOS.udp)
3859 self.frag_out_of_order(proto=IP_PROTOS.icmp)
3860
3861 def test_frag_out_of_order_dont_translate(self):
3862 """ NAT44 don't translate fragments arriving out of order """
3863 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3864 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3865 is_inside=0)
3866 self.vapi.nat44_forwarding_enable_disable(enable=True)
3867 self.frag_out_of_order(proto=IP_PROTOS.tcp, dont_translate=True)
3868
3869 def test_frag_in_order_in_plus_out(self):
3870 """ in+out interface fragments in order """
3871 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3872 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
3873 is_inside=0)
3874 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
3875 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3876 is_inside=0)
3877
3878 self.server = self.pg1.remote_hosts[0]
3879
3880 self.server_in_addr = self.server.ip4
3881 self.server_out_addr = '11.11.11.11'
3882 self.server_in_port = random.randint(1025, 65535)
3883 self.server_out_port = random.randint(1025, 65535)
3884
3885 self.nat44_add_address(self.server_out_addr)
3886
3887 # add static mappings for server
3888 self.nat44_add_static_mapping(self.server_in_addr,
3889 self.server_out_addr,
3890 self.server_in_port,
3891 self.server_out_port,
3892 proto=IP_PROTOS.tcp)
3893 self.nat44_add_static_mapping(self.server_in_addr,
3894 self.server_out_addr,
3895 self.server_in_port,
3896 self.server_out_port,
3897 proto=IP_PROTOS.udp)
3898 self.nat44_add_static_mapping(self.server_in_addr,
3899 self.server_out_addr,
3900 proto=IP_PROTOS.icmp)
3901
3902 self.vapi.nat_set_reass(timeout=10)
3903
3904 self.frag_in_order_in_plus_out(proto=IP_PROTOS.tcp)
3905 self.frag_in_order_in_plus_out(proto=IP_PROTOS.udp)
3906 self.frag_in_order_in_plus_out(proto=IP_PROTOS.icmp)
3907
3908 def test_frag_out_of_order_in_plus_out(self):
3909 """ in+out interface fragments out of order """
3910 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3911 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
3912 is_inside=0)
3913 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
3914 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3915 is_inside=0)
3916
3917 self.server = self.pg1.remote_hosts[0]
3918
3919 self.server_in_addr = self.server.ip4
3920 self.server_out_addr = '11.11.11.11'
3921 self.server_in_port = random.randint(1025, 65535)
3922 self.server_out_port = random.randint(1025, 65535)
3923
3924 self.nat44_add_address(self.server_out_addr)
3925
3926 # add static mappings for server
3927 self.nat44_add_static_mapping(self.server_in_addr,
3928 self.server_out_addr,
3929 self.server_in_port,
3930 self.server_out_port,
3931 proto=IP_PROTOS.tcp)
3932 self.nat44_add_static_mapping(self.server_in_addr,
3933 self.server_out_addr,
3934 self.server_in_port,
3935 self.server_out_port,
3936 proto=IP_PROTOS.udp)
3937 self.nat44_add_static_mapping(self.server_in_addr,
3938 self.server_out_addr,
3939 proto=IP_PROTOS.icmp)
3940
3941 self.vapi.nat_set_reass(timeout=10)
3942
3943 self.frag_out_of_order_in_plus_out(proto=IP_PROTOS.tcp)
3944 self.frag_out_of_order_in_plus_out(proto=IP_PROTOS.udp)
3945 self.frag_out_of_order_in_plus_out(proto=IP_PROTOS.icmp)
3946
3947 def test_reass_hairpinning(self):
3948 """ NAT44 fragments hairpinning """
3949 self.server = self.pg0.remote_hosts[1]
3950 self.host_in_port = random.randint(1025, 65535)
3951 self.server_in_port = random.randint(1025, 65535)
3952 self.server_out_port = random.randint(1025, 65535)
3953
3954 self.nat44_add_address(self.nat_addr)
3955 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3956 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3957 is_inside=0)
3958 # add static mapping for server
3959 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr,
3960 self.server_in_port,
3961 self.server_out_port,
3962 proto=IP_PROTOS.tcp)
3963 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr,
3964 self.server_in_port,
3965 self.server_out_port,
3966 proto=IP_PROTOS.udp)
3967 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr,
3968 proto=IP_PROTOS.icmp)
3969
3970 self.reass_hairpinning(proto=IP_PROTOS.tcp)
3971 self.reass_hairpinning(proto=IP_PROTOS.udp)
3972 self.reass_hairpinning(proto=IP_PROTOS.icmp)
3973
Matus Fabiana6110b62018-06-13 05:39:07 -07003974 def test_dynamic(self):
3975 """ NAT44 dynamic translation test """
3976
3977 self.nat44_add_address(self.nat_addr)
3978 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3979 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3980 is_inside=0)
3981
Matus Fabian69ce30d2018-08-22 01:27:10 -07003982 nat_config = self.vapi.nat_show_config()
3983 self.assertEqual(1, nat_config.endpoint_dependent)
3984
Matus Fabiana6110b62018-06-13 05:39:07 -07003985 # in2out
3986 pkts = self.create_stream_in(self.pg0, self.pg1)
3987 self.pg0.add_stream(pkts)
3988 self.pg_enable_capture(self.pg_interfaces)
3989 self.pg_start()
3990 capture = self.pg1.get_capture(len(pkts))
3991 self.verify_capture_out(capture)
3992
3993 # out2in
3994 pkts = self.create_stream_out(self.pg1)
3995 self.pg1.add_stream(pkts)
3996 self.pg_enable_capture(self.pg_interfaces)
3997 self.pg_start()
3998 capture = self.pg0.get_capture(len(pkts))
3999 self.verify_capture_in(capture, self.pg0)
4000
4001 def test_forwarding(self):
4002 """ NAT44 forwarding test """
4003
4004 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4005 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4006 is_inside=0)
4007 self.vapi.nat44_forwarding_enable_disable(1)
4008
4009 real_ip = self.pg0.remote_ip4n
4010 alias_ip = self.nat_addr_n
4011 self.vapi.nat44_add_del_static_mapping(local_ip=real_ip,
4012 external_ip=alias_ip)
4013
4014 try:
4015 # in2out - static mapping match
4016
4017 pkts = self.create_stream_out(self.pg1)
4018 self.pg1.add_stream(pkts)
4019 self.pg_enable_capture(self.pg_interfaces)
4020 self.pg_start()
4021 capture = self.pg0.get_capture(len(pkts))
4022 self.verify_capture_in(capture, self.pg0)
4023
4024 pkts = self.create_stream_in(self.pg0, self.pg1)
4025 self.pg0.add_stream(pkts)
4026 self.pg_enable_capture(self.pg_interfaces)
4027 self.pg_start()
4028 capture = self.pg1.get_capture(len(pkts))
4029 self.verify_capture_out(capture, same_port=True)
4030
4031 # in2out - no static mapping match
4032
4033 host0 = self.pg0.remote_hosts[0]
4034 self.pg0.remote_hosts[0] = self.pg0.remote_hosts[1]
4035 try:
4036 pkts = self.create_stream_out(self.pg1,
4037 dst_ip=self.pg0.remote_ip4,
4038 use_inside_ports=True)
4039 self.pg1.add_stream(pkts)
4040 self.pg_enable_capture(self.pg_interfaces)
4041 self.pg_start()
4042 capture = self.pg0.get_capture(len(pkts))
4043 self.verify_capture_in(capture, self.pg0)
4044
4045 pkts = self.create_stream_in(self.pg0, self.pg1)
4046 self.pg0.add_stream(pkts)
4047 self.pg_enable_capture(self.pg_interfaces)
4048 self.pg_start()
4049 capture = self.pg1.get_capture(len(pkts))
4050 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
4051 same_port=True)
4052 finally:
4053 self.pg0.remote_hosts[0] = host0
4054
4055 user = self.pg0.remote_hosts[1]
4056 sessions = self.vapi.nat44_user_session_dump(user.ip4n, 0)
4057 self.assertEqual(len(sessions), 3)
4058 self.assertTrue(sessions[0].ext_host_valid)
4059 self.vapi.nat44_del_session(
4060 sessions[0].inside_ip_address,
4061 sessions[0].inside_port,
4062 sessions[0].protocol,
4063 ext_host_address=sessions[0].ext_host_address,
4064 ext_host_port=sessions[0].ext_host_port)
4065 sessions = self.vapi.nat44_user_session_dump(user.ip4n, 0)
4066 self.assertEqual(len(sessions), 2)
4067
4068 finally:
4069 self.vapi.nat44_forwarding_enable_disable(0)
4070 self.vapi.nat44_add_del_static_mapping(local_ip=real_ip,
4071 external_ip=alias_ip,
4072 is_add=0)
4073
4074 def test_static_lb(self):
4075 """ NAT44 local service load balancing """
4076 external_addr_n = socket.inet_pton(socket.AF_INET, self.nat_addr)
4077 external_port = 80
4078 local_port = 8080
4079 server1 = self.pg0.remote_hosts[0]
4080 server2 = self.pg0.remote_hosts[1]
4081
4082 locals = [{'addr': server1.ip4n,
4083 'port': local_port,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07004084 'probability': 70,
4085 'vrf_id': 0},
Matus Fabiana6110b62018-06-13 05:39:07 -07004086 {'addr': server2.ip4n,
4087 'port': local_port,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07004088 'probability': 30,
4089 'vrf_id': 0}]
Matus Fabiana6110b62018-06-13 05:39:07 -07004090
4091 self.nat44_add_address(self.nat_addr)
4092 self.vapi.nat44_add_del_lb_static_mapping(external_addr_n,
4093 external_port,
4094 IP_PROTOS.tcp,
4095 local_num=len(locals),
4096 locals=locals)
4097 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4098 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4099 is_inside=0)
4100
4101 # from client to service
4102 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4103 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4104 TCP(sport=12345, dport=external_port))
4105 self.pg1.add_stream(p)
4106 self.pg_enable_capture(self.pg_interfaces)
4107 self.pg_start()
4108 capture = self.pg0.get_capture(1)
4109 p = capture[0]
4110 server = None
4111 try:
4112 ip = p[IP]
4113 tcp = p[TCP]
4114 self.assertIn(ip.dst, [server1.ip4, server2.ip4])
4115 if ip.dst == server1.ip4:
4116 server = server1
4117 else:
4118 server = server2
4119 self.assertEqual(tcp.dport, local_port)
4120 self.assert_packet_checksums_valid(p)
4121 except:
4122 self.logger.error(ppp("Unexpected or invalid packet:", p))
4123 raise
4124
4125 # from service back to client
4126 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
4127 IP(src=server.ip4, dst=self.pg1.remote_ip4) /
4128 TCP(sport=local_port, dport=12345))
4129 self.pg0.add_stream(p)
4130 self.pg_enable_capture(self.pg_interfaces)
4131 self.pg_start()
4132 capture = self.pg1.get_capture(1)
4133 p = capture[0]
4134 try:
4135 ip = p[IP]
4136 tcp = p[TCP]
4137 self.assertEqual(ip.src, self.nat_addr)
4138 self.assertEqual(tcp.sport, external_port)
4139 self.assert_packet_checksums_valid(p)
4140 except:
4141 self.logger.error(ppp("Unexpected or invalid packet:", p))
4142 raise
4143
4144 sessions = self.vapi.nat44_user_session_dump(server.ip4n, 0)
4145 self.assertEqual(len(sessions), 1)
4146 self.assertTrue(sessions[0].ext_host_valid)
4147 self.vapi.nat44_del_session(
4148 sessions[0].inside_ip_address,
4149 sessions[0].inside_port,
4150 sessions[0].protocol,
4151 ext_host_address=sessions[0].ext_host_address,
4152 ext_host_port=sessions[0].ext_host_port)
4153 sessions = self.vapi.nat44_user_session_dump(server.ip4n, 0)
4154 self.assertEqual(len(sessions), 0)
4155
4156 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
4157 def test_static_lb_multi_clients(self):
4158 """ NAT44 local service load balancing - multiple clients"""
4159
4160 external_addr_n = socket.inet_pton(socket.AF_INET, self.nat_addr)
4161 external_port = 80
4162 local_port = 8080
4163 server1 = self.pg0.remote_hosts[0]
4164 server2 = self.pg0.remote_hosts[1]
4165
4166 locals = [{'addr': server1.ip4n,
4167 'port': local_port,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07004168 'probability': 90,
4169 'vrf_id': 0},
Matus Fabiana6110b62018-06-13 05:39:07 -07004170 {'addr': server2.ip4n,
4171 'port': local_port,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07004172 'probability': 10,
4173 'vrf_id': 0}]
Matus Fabiana6110b62018-06-13 05:39:07 -07004174
4175 self.nat44_add_address(self.nat_addr)
4176 self.vapi.nat44_add_del_lb_static_mapping(external_addr_n,
4177 external_port,
4178 IP_PROTOS.tcp,
4179 local_num=len(locals),
4180 locals=locals)
4181 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4182 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4183 is_inside=0)
4184
4185 server1_n = 0
4186 server2_n = 0
4187 clients = ip4_range(self.pg1.remote_ip4, 10, 50)
4188 pkts = []
4189 for client in clients:
4190 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4191 IP(src=client, dst=self.nat_addr) /
4192 TCP(sport=12345, dport=external_port))
4193 pkts.append(p)
4194 self.pg1.add_stream(pkts)
4195 self.pg_enable_capture(self.pg_interfaces)
4196 self.pg_start()
4197 capture = self.pg0.get_capture(len(pkts))
4198 for p in capture:
4199 if p[IP].dst == server1.ip4:
4200 server1_n += 1
4201 else:
4202 server2_n += 1
4203 self.assertTrue(server1_n > server2_n)
4204
4205 def test_static_lb_2(self):
4206 """ NAT44 local service load balancing (asymmetrical rule) """
4207 external_addr_n = socket.inet_pton(socket.AF_INET, self.nat_addr)
4208 external_port = 80
4209 local_port = 8080
4210 server1 = self.pg0.remote_hosts[0]
4211 server2 = self.pg0.remote_hosts[1]
4212
4213 locals = [{'addr': server1.ip4n,
4214 'port': local_port,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07004215 'probability': 70,
4216 'vrf_id': 0},
Matus Fabiana6110b62018-06-13 05:39:07 -07004217 {'addr': server2.ip4n,
4218 'port': local_port,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07004219 'probability': 30,
4220 'vrf_id': 0}]
Matus Fabiana6110b62018-06-13 05:39:07 -07004221
4222 self.vapi.nat44_forwarding_enable_disable(1)
4223 self.vapi.nat44_add_del_lb_static_mapping(external_addr_n,
4224 external_port,
4225 IP_PROTOS.tcp,
4226 out2in_only=1,
4227 local_num=len(locals),
4228 locals=locals)
4229 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4230 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4231 is_inside=0)
4232
4233 # from client to service
4234 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4235 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4236 TCP(sport=12345, dport=external_port))
4237 self.pg1.add_stream(p)
4238 self.pg_enable_capture(self.pg_interfaces)
4239 self.pg_start()
4240 capture = self.pg0.get_capture(1)
4241 p = capture[0]
4242 server = None
4243 try:
4244 ip = p[IP]
4245 tcp = p[TCP]
4246 self.assertIn(ip.dst, [server1.ip4, server2.ip4])
4247 if ip.dst == server1.ip4:
4248 server = server1
4249 else:
4250 server = server2
4251 self.assertEqual(tcp.dport, local_port)
4252 self.assert_packet_checksums_valid(p)
4253 except:
4254 self.logger.error(ppp("Unexpected or invalid packet:", p))
4255 raise
4256
4257 # from service back to client
4258 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
4259 IP(src=server.ip4, dst=self.pg1.remote_ip4) /
4260 TCP(sport=local_port, dport=12345))
4261 self.pg0.add_stream(p)
4262 self.pg_enable_capture(self.pg_interfaces)
4263 self.pg_start()
4264 capture = self.pg1.get_capture(1)
4265 p = capture[0]
4266 try:
4267 ip = p[IP]
4268 tcp = p[TCP]
4269 self.assertEqual(ip.src, self.nat_addr)
4270 self.assertEqual(tcp.sport, external_port)
4271 self.assert_packet_checksums_valid(p)
4272 except:
4273 self.logger.error(ppp("Unexpected or invalid packet:", p))
4274 raise
4275
4276 # from client to server (no translation)
4277 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4278 IP(src=self.pg1.remote_ip4, dst=server1.ip4) /
4279 TCP(sport=12346, dport=local_port))
4280 self.pg1.add_stream(p)
4281 self.pg_enable_capture(self.pg_interfaces)
4282 self.pg_start()
4283 capture = self.pg0.get_capture(1)
4284 p = capture[0]
4285 server = None
4286 try:
4287 ip = p[IP]
4288 tcp = p[TCP]
4289 self.assertEqual(ip.dst, server1.ip4)
4290 self.assertEqual(tcp.dport, local_port)
4291 self.assert_packet_checksums_valid(p)
4292 except:
4293 self.logger.error(ppp("Unexpected or invalid packet:", p))
4294 raise
4295
4296 # from service back to client (no translation)
4297 p = (Ether(src=server1.mac, dst=self.pg0.local_mac) /
4298 IP(src=server1.ip4, dst=self.pg1.remote_ip4) /
4299 TCP(sport=local_port, dport=12346))
4300 self.pg0.add_stream(p)
4301 self.pg_enable_capture(self.pg_interfaces)
4302 self.pg_start()
4303 capture = self.pg1.get_capture(1)
4304 p = capture[0]
4305 try:
4306 ip = p[IP]
4307 tcp = p[TCP]
4308 self.assertEqual(ip.src, server1.ip4)
4309 self.assertEqual(tcp.sport, local_port)
4310 self.assert_packet_checksums_valid(p)
4311 except:
4312 self.logger.error(ppp("Unexpected or invalid packet:", p))
4313 raise
4314
Matus Fabianea5b5be2018-09-03 05:02:23 -07004315 def test_lb_affinity(self):
4316 """ NAT44 local service load balancing affinity """
4317 external_addr_n = socket.inet_pton(socket.AF_INET, self.nat_addr)
4318 external_port = 80
4319 local_port = 8080
4320 server1 = self.pg0.remote_hosts[0]
4321 server2 = self.pg0.remote_hosts[1]
4322
4323 locals = [{'addr': server1.ip4n,
4324 'port': local_port,
4325 'probability': 50,
4326 'vrf_id': 0},
4327 {'addr': server2.ip4n,
4328 'port': local_port,
4329 'probability': 50,
4330 'vrf_id': 0}]
4331
4332 self.nat44_add_address(self.nat_addr)
4333 self.vapi.nat44_add_del_lb_static_mapping(external_addr_n,
4334 external_port,
4335 IP_PROTOS.tcp,
4336 affinity=10800,
4337 local_num=len(locals),
4338 locals=locals)
4339 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4340 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4341 is_inside=0)
4342
4343 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
4344 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4345 TCP(sport=1025, dport=external_port))
4346 self.pg1.add_stream(p)
4347 self.pg_enable_capture(self.pg_interfaces)
4348 self.pg_start()
4349 capture = self.pg0.get_capture(1)
4350 backend = capture[0][IP].dst
4351
4352 sessions = self.vapi.nat44_user_session_dump(
4353 socket.inet_pton(socket.AF_INET, backend), 0)
4354 self.assertEqual(len(sessions), 1)
4355 self.assertTrue(sessions[0].ext_host_valid)
4356 self.vapi.nat44_del_session(
4357 sessions[0].inside_ip_address,
4358 sessions[0].inside_port,
4359 sessions[0].protocol,
4360 ext_host_address=sessions[0].ext_host_address,
4361 ext_host_port=sessions[0].ext_host_port)
4362
4363 pkts = []
4364 for port in range(1030, 1100):
4365 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
4366 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4367 TCP(sport=port, dport=external_port))
4368 pkts.append(p)
4369 self.pg1.add_stream(pkts)
4370 self.pg_enable_capture(self.pg_interfaces)
4371 self.pg_start()
4372 capture = self.pg0.get_capture(len(pkts))
4373 for p in capture:
4374 self.assertEqual(p[IP].dst, backend)
4375
Matus Fabiana6110b62018-06-13 05:39:07 -07004376 def test_unknown_proto(self):
4377 """ NAT44 translate packet with unknown protocol """
4378 self.nat44_add_address(self.nat_addr)
4379 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4380 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4381 is_inside=0)
4382
4383 # in2out
4384 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
4385 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4386 TCP(sport=self.tcp_port_in, dport=20))
4387 self.pg0.add_stream(p)
4388 self.pg_enable_capture(self.pg_interfaces)
4389 self.pg_start()
4390 p = self.pg1.get_capture(1)
4391
4392 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
4393 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4394 GRE() /
4395 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
4396 TCP(sport=1234, dport=1234))
4397 self.pg0.add_stream(p)
4398 self.pg_enable_capture(self.pg_interfaces)
4399 self.pg_start()
4400 p = self.pg1.get_capture(1)
4401 packet = p[0]
4402 try:
4403 self.assertEqual(packet[IP].src, self.nat_addr)
4404 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
4405 self.assertTrue(packet.haslayer(GRE))
4406 self.assert_packet_checksums_valid(packet)
4407 except:
4408 self.logger.error(ppp("Unexpected or invalid packet:", packet))
4409 raise
4410
4411 # out2in
4412 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
4413 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4414 GRE() /
4415 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
4416 TCP(sport=1234, dport=1234))
4417 self.pg1.add_stream(p)
4418 self.pg_enable_capture(self.pg_interfaces)
4419 self.pg_start()
4420 p = self.pg0.get_capture(1)
4421 packet = p[0]
4422 try:
4423 self.assertEqual(packet[IP].src, self.pg1.remote_ip4)
4424 self.assertEqual(packet[IP].dst, self.pg0.remote_ip4)
4425 self.assertTrue(packet.haslayer(GRE))
4426 self.assert_packet_checksums_valid(packet)
4427 except:
4428 self.logger.error(ppp("Unexpected or invalid packet:", packet))
4429 raise
4430
4431 def test_hairpinning_unknown_proto(self):
4432 """ NAT44 translate packet with unknown protocol - hairpinning """
4433 host = self.pg0.remote_hosts[0]
4434 server = self.pg0.remote_hosts[1]
4435 host_in_port = 1234
4436 server_out_port = 8765
4437 server_nat_ip = "10.0.0.11"
4438
4439 self.nat44_add_address(self.nat_addr)
4440 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4441 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4442 is_inside=0)
4443
4444 # add static mapping for server
4445 self.nat44_add_static_mapping(server.ip4, server_nat_ip)
4446
4447 # host to server
4448 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
4449 IP(src=host.ip4, dst=server_nat_ip) /
4450 TCP(sport=host_in_port, dport=server_out_port))
4451 self.pg0.add_stream(p)
4452 self.pg_enable_capture(self.pg_interfaces)
4453 self.pg_start()
4454 self.pg0.get_capture(1)
4455
4456 p = (Ether(dst=self.pg0.local_mac, src=host.mac) /
4457 IP(src=host.ip4, dst=server_nat_ip) /
4458 GRE() /
4459 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
4460 TCP(sport=1234, dport=1234))
4461 self.pg0.add_stream(p)
4462 self.pg_enable_capture(self.pg_interfaces)
4463 self.pg_start()
4464 p = self.pg0.get_capture(1)
4465 packet = p[0]
4466 try:
4467 self.assertEqual(packet[IP].src, self.nat_addr)
4468 self.assertEqual(packet[IP].dst, server.ip4)
4469 self.assertTrue(packet.haslayer(GRE))
4470 self.assert_packet_checksums_valid(packet)
4471 except:
4472 self.logger.error(ppp("Unexpected or invalid packet:", packet))
4473 raise
4474
4475 # server to host
4476 p = (Ether(dst=self.pg0.local_mac, src=server.mac) /
4477 IP(src=server.ip4, dst=self.nat_addr) /
4478 GRE() /
4479 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
4480 TCP(sport=1234, dport=1234))
4481 self.pg0.add_stream(p)
4482 self.pg_enable_capture(self.pg_interfaces)
4483 self.pg_start()
4484 p = self.pg0.get_capture(1)
4485 packet = p[0]
4486 try:
4487 self.assertEqual(packet[IP].src, server_nat_ip)
4488 self.assertEqual(packet[IP].dst, host.ip4)
4489 self.assertTrue(packet.haslayer(GRE))
4490 self.assert_packet_checksums_valid(packet)
4491 except:
4492 self.logger.error(ppp("Unexpected or invalid packet:", packet))
4493 raise
4494
4495 def test_output_feature_and_service(self):
4496 """ NAT44 interface output feature and services """
4497 external_addr = '1.2.3.4'
4498 external_port = 80
4499 local_port = 8080
4500
4501 self.vapi.nat44_forwarding_enable_disable(1)
4502 self.nat44_add_address(self.nat_addr)
4503 self.vapi.nat44_add_del_identity_mapping(ip=self.pg1.remote_ip4n)
4504 self.nat44_add_static_mapping(self.pg0.remote_ip4, external_addr,
4505 local_port, external_port,
4506 proto=IP_PROTOS.tcp, out2in_only=1)
4507 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4508 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
4509 is_inside=0)
4510 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
4511 is_inside=0)
4512
4513 # from client to service
4514 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4515 IP(src=self.pg1.remote_ip4, dst=external_addr) /
4516 TCP(sport=12345, dport=external_port))
4517 self.pg1.add_stream(p)
4518 self.pg_enable_capture(self.pg_interfaces)
4519 self.pg_start()
4520 capture = self.pg0.get_capture(1)
4521 p = capture[0]
4522 try:
4523 ip = p[IP]
4524 tcp = p[TCP]
4525 self.assertEqual(ip.dst, self.pg0.remote_ip4)
4526 self.assertEqual(tcp.dport, local_port)
4527 self.assert_packet_checksums_valid(p)
4528 except:
4529 self.logger.error(ppp("Unexpected or invalid packet:", p))
4530 raise
4531
4532 # from service back to client
4533 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4534 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4535 TCP(sport=local_port, dport=12345))
4536 self.pg0.add_stream(p)
4537 self.pg_enable_capture(self.pg_interfaces)
4538 self.pg_start()
4539 capture = self.pg1.get_capture(1)
4540 p = capture[0]
4541 try:
4542 ip = p[IP]
4543 tcp = p[TCP]
4544 self.assertEqual(ip.src, external_addr)
4545 self.assertEqual(tcp.sport, external_port)
4546 self.assert_packet_checksums_valid(p)
4547 except:
4548 self.logger.error(ppp("Unexpected or invalid packet:", p))
4549 raise
4550
4551 # from local network host to external network
4552 pkts = self.create_stream_in(self.pg0, self.pg1)
4553 self.pg0.add_stream(pkts)
4554 self.pg_enable_capture(self.pg_interfaces)
4555 self.pg_start()
4556 capture = self.pg1.get_capture(len(pkts))
4557 self.verify_capture_out(capture)
4558 pkts = self.create_stream_in(self.pg0, self.pg1)
4559 self.pg0.add_stream(pkts)
4560 self.pg_enable_capture(self.pg_interfaces)
4561 self.pg_start()
4562 capture = self.pg1.get_capture(len(pkts))
4563 self.verify_capture_out(capture)
4564
4565 # from external network back to local network host
4566 pkts = self.create_stream_out(self.pg1)
4567 self.pg1.add_stream(pkts)
4568 self.pg_enable_capture(self.pg_interfaces)
4569 self.pg_start()
4570 capture = self.pg0.get_capture(len(pkts))
4571 self.verify_capture_in(capture, self.pg0)
4572
4573 def test_output_feature_and_service2(self):
4574 """ NAT44 interface output feature and service host direct access """
4575 self.vapi.nat44_forwarding_enable_disable(1)
4576 self.nat44_add_address(self.nat_addr)
4577 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
4578 is_inside=0)
4579
4580 # session initiaded from service host - translate
4581 pkts = self.create_stream_in(self.pg0, self.pg1)
4582 self.pg0.add_stream(pkts)
4583 self.pg_enable_capture(self.pg_interfaces)
4584 self.pg_start()
4585 capture = self.pg1.get_capture(len(pkts))
4586 self.verify_capture_out(capture)
4587
4588 pkts = self.create_stream_out(self.pg1)
4589 self.pg1.add_stream(pkts)
4590 self.pg_enable_capture(self.pg_interfaces)
4591 self.pg_start()
4592 capture = self.pg0.get_capture(len(pkts))
4593 self.verify_capture_in(capture, self.pg0)
4594
4595 # session initiaded from remote host - do not translate
4596 self.tcp_port_in = 60303
4597 self.udp_port_in = 60304
4598 self.icmp_id_in = 60305
4599 pkts = self.create_stream_out(self.pg1,
4600 self.pg0.remote_ip4,
4601 use_inside_ports=True)
4602 self.pg1.add_stream(pkts)
4603 self.pg_enable_capture(self.pg_interfaces)
4604 self.pg_start()
4605 capture = self.pg0.get_capture(len(pkts))
4606 self.verify_capture_in(capture, self.pg0)
4607
4608 pkts = self.create_stream_in(self.pg0, self.pg1)
4609 self.pg0.add_stream(pkts)
4610 self.pg_enable_capture(self.pg_interfaces)
4611 self.pg_start()
4612 capture = self.pg1.get_capture(len(pkts))
4613 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
4614 same_port=True)
4615
4616 def test_output_feature_and_service3(self):
4617 """ NAT44 interface output feature and DST NAT """
4618 external_addr = '1.2.3.4'
4619 external_port = 80
4620 local_port = 8080
4621
4622 self.vapi.nat44_forwarding_enable_disable(1)
4623 self.nat44_add_address(self.nat_addr)
4624 self.nat44_add_static_mapping(self.pg1.remote_ip4, external_addr,
4625 local_port, external_port,
4626 proto=IP_PROTOS.tcp, out2in_only=1)
4627 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4628 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
4629 is_inside=0)
4630 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
4631 is_inside=0)
4632
4633 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4634 IP(src=self.pg0.remote_ip4, dst=external_addr) /
4635 TCP(sport=12345, dport=external_port))
4636 self.pg0.add_stream(p)
4637 self.pg_enable_capture(self.pg_interfaces)
4638 self.pg_start()
4639 capture = self.pg1.get_capture(1)
4640 p = capture[0]
4641 try:
4642 ip = p[IP]
4643 tcp = p[TCP]
4644 self.assertEqual(ip.src, self.pg0.remote_ip4)
4645 self.assertEqual(tcp.sport, 12345)
4646 self.assertEqual(ip.dst, self.pg1.remote_ip4)
4647 self.assertEqual(tcp.dport, local_port)
4648 self.assert_packet_checksums_valid(p)
4649 except:
4650 self.logger.error(ppp("Unexpected or invalid packet:", p))
4651 raise
4652
4653 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4654 IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
4655 TCP(sport=local_port, dport=12345))
4656 self.pg1.add_stream(p)
4657 self.pg_enable_capture(self.pg_interfaces)
4658 self.pg_start()
4659 capture = self.pg0.get_capture(1)
4660 p = capture[0]
4661 try:
4662 ip = p[IP]
4663 tcp = p[TCP]
4664 self.assertEqual(ip.src, external_addr)
4665 self.assertEqual(tcp.sport, external_port)
4666 self.assertEqual(ip.dst, self.pg0.remote_ip4)
4667 self.assertEqual(tcp.dport, 12345)
4668 self.assert_packet_checksums_valid(p)
4669 except:
4670 self.logger.error(ppp("Unexpected or invalid packet:", p))
4671 raise
4672
Matus Fabian182e37e2018-08-14 04:21:26 -07004673 def test_next_src_nat(self):
4674 """ On way back forward packet to nat44-in2out node. """
4675 twice_nat_addr = '10.0.1.3'
4676 external_port = 80
4677 local_port = 8080
4678 post_twice_nat_port = 0
4679
4680 self.vapi.nat44_forwarding_enable_disable(1)
4681 self.nat44_add_address(twice_nat_addr, twice_nat=1)
4682 self.nat44_add_static_mapping(self.pg6.remote_ip4, self.pg1.remote_ip4,
4683 local_port, external_port,
4684 proto=IP_PROTOS.tcp, out2in_only=1,
4685 self_twice_nat=1, vrf_id=1)
4686 self.vapi.nat44_interface_add_del_feature(self.pg6.sw_if_index,
4687 is_inside=0)
4688
4689 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
4690 IP(src=self.pg6.remote_ip4, dst=self.pg1.remote_ip4) /
4691 TCP(sport=12345, dport=external_port))
4692 self.pg6.add_stream(p)
4693 self.pg_enable_capture(self.pg_interfaces)
4694 self.pg_start()
4695 capture = self.pg6.get_capture(1)
4696 p = capture[0]
4697 try:
4698 ip = p[IP]
4699 tcp = p[TCP]
4700 self.assertEqual(ip.src, twice_nat_addr)
4701 self.assertNotEqual(tcp.sport, 12345)
4702 post_twice_nat_port = tcp.sport
4703 self.assertEqual(ip.dst, self.pg6.remote_ip4)
4704 self.assertEqual(tcp.dport, local_port)
4705 self.assert_packet_checksums_valid(p)
4706 except:
4707 self.logger.error(ppp("Unexpected or invalid packet:", p))
4708 raise
4709
4710 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
4711 IP(src=self.pg6.remote_ip4, dst=twice_nat_addr) /
4712 TCP(sport=local_port, dport=post_twice_nat_port))
4713 self.pg6.add_stream(p)
4714 self.pg_enable_capture(self.pg_interfaces)
4715 self.pg_start()
4716 capture = self.pg6.get_capture(1)
4717 p = capture[0]
4718 try:
4719 ip = p[IP]
4720 tcp = p[TCP]
4721 self.assertEqual(ip.src, self.pg1.remote_ip4)
4722 self.assertEqual(tcp.sport, external_port)
4723 self.assertEqual(ip.dst, self.pg6.remote_ip4)
4724 self.assertEqual(tcp.dport, 12345)
4725 self.assert_packet_checksums_valid(p)
4726 except:
4727 self.logger.error(ppp("Unexpected or invalid packet:", p))
4728 raise
4729
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004730 def twice_nat_common(self, self_twice_nat=False, same_pg=False, lb=False,
4731 client_id=None):
Matus Fabianb932d262017-12-18 05:38:24 -08004732 twice_nat_addr = '10.0.1.3'
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004733
Matus Fabianb932d262017-12-18 05:38:24 -08004734 port_in = 8080
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004735 if lb:
4736 if not same_pg:
4737 port_in1 = port_in
4738 port_in2 = port_in
4739 else:
4740 port_in1 = port_in+1
4741 port_in2 = port_in+2
4742
Matus Fabianb932d262017-12-18 05:38:24 -08004743 port_out = 80
4744 eh_port_out = 4567
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004745
4746 server1 = self.pg0.remote_hosts[0]
4747 server2 = self.pg0.remote_hosts[1]
4748 if lb and same_pg:
4749 server2 = server1
4750 if not lb:
4751 server = server1
4752
4753 pg0 = self.pg0
4754 if same_pg:
4755 pg1 = self.pg0
4756 else:
4757 pg1 = self.pg1
4758
4759 eh_translate = ((not self_twice_nat) or (not lb and same_pg) or
4760 client_id == 1)
4761
Matus Fabianb932d262017-12-18 05:38:24 -08004762 self.nat44_add_address(self.nat_addr)
4763 self.nat44_add_address(twice_nat_addr, twice_nat=1)
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004764 if not lb:
4765 self.nat44_add_static_mapping(pg0.remote_ip4, self.nat_addr,
4766 port_in, port_out,
4767 proto=IP_PROTOS.tcp,
4768 twice_nat=int(not self_twice_nat),
4769 self_twice_nat=int(self_twice_nat))
4770 else:
4771 locals = [{'addr': server1.ip4n,
4772 'port': port_in1,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07004773 'probability': 50,
4774 'vrf_id': 0},
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004775 {'addr': server2.ip4n,
4776 'port': port_in2,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07004777 'probability': 50,
4778 'vrf_id': 0}]
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004779 out_addr_n = socket.inet_pton(socket.AF_INET, self.nat_addr)
4780 self.vapi.nat44_add_del_lb_static_mapping(out_addr_n,
4781 port_out,
4782 IP_PROTOS.tcp,
4783 twice_nat=int(
4784 not self_twice_nat),
4785 self_twice_nat=int(
4786 self_twice_nat),
4787 local_num=len(locals),
4788 locals=locals)
4789 self.vapi.nat44_interface_add_del_feature(pg0.sw_if_index)
4790 self.vapi.nat44_interface_add_del_feature(pg1.sw_if_index,
Matus Fabianb932d262017-12-18 05:38:24 -08004791 is_inside=0)
4792
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004793 if same_pg:
4794 if not lb:
4795 client = server
4796 else:
4797 assert client_id is not None
4798 if client_id == 1:
4799 client = self.pg0.remote_hosts[0]
4800 elif client_id == 2:
4801 client = self.pg0.remote_hosts[1]
4802 else:
4803 client = pg1.remote_hosts[0]
4804 p = (Ether(src=pg1.remote_mac, dst=pg1.local_mac) /
4805 IP(src=client.ip4, dst=self.nat_addr) /
Matus Fabianb932d262017-12-18 05:38:24 -08004806 TCP(sport=eh_port_out, dport=port_out))
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004807 pg1.add_stream(p)
Matus Fabianb932d262017-12-18 05:38:24 -08004808 self.pg_enable_capture(self.pg_interfaces)
4809 self.pg_start()
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004810 capture = pg0.get_capture(1)
Matus Fabianb932d262017-12-18 05:38:24 -08004811 p = capture[0]
4812 try:
4813 ip = p[IP]
4814 tcp = p[TCP]
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004815 if lb:
4816 if ip.dst == server1.ip4:
4817 server = server1
4818 port_in = port_in1
4819 else:
4820 server = server2
4821 port_in = port_in2
4822 self.assertEqual(ip.dst, server.ip4)
4823 if lb and same_pg:
4824 self.assertIn(tcp.dport, [port_in1, port_in2])
4825 else:
4826 self.assertEqual(tcp.dport, port_in)
4827 if eh_translate:
4828 self.assertEqual(ip.src, twice_nat_addr)
4829 self.assertNotEqual(tcp.sport, eh_port_out)
4830 else:
4831 self.assertEqual(ip.src, client.ip4)
4832 self.assertEqual(tcp.sport, eh_port_out)
4833 eh_addr_in = ip.src
Matus Fabianb932d262017-12-18 05:38:24 -08004834 eh_port_in = tcp.sport
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004835 saved_port_in = tcp.dport
Klement Sekerad81ae412018-05-16 10:52:54 +02004836 self.assert_packet_checksums_valid(p)
Matus Fabianb932d262017-12-18 05:38:24 -08004837 except:
4838 self.logger.error(ppp("Unexpected or invalid packet:", p))
4839 raise
4840
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004841 p = (Ether(src=server.mac, dst=pg0.local_mac) /
4842 IP(src=server.ip4, dst=eh_addr_in) /
4843 TCP(sport=saved_port_in, dport=eh_port_in))
4844 pg0.add_stream(p)
Matus Fabianb932d262017-12-18 05:38:24 -08004845 self.pg_enable_capture(self.pg_interfaces)
4846 self.pg_start()
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004847 capture = pg1.get_capture(1)
Matus Fabianb932d262017-12-18 05:38:24 -08004848 p = capture[0]
4849 try:
4850 ip = p[IP]
4851 tcp = p[TCP]
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004852 self.assertEqual(ip.dst, client.ip4)
Matus Fabianb932d262017-12-18 05:38:24 -08004853 self.assertEqual(ip.src, self.nat_addr)
4854 self.assertEqual(tcp.dport, eh_port_out)
4855 self.assertEqual(tcp.sport, port_out)
Klement Sekerad81ae412018-05-16 10:52:54 +02004856 self.assert_packet_checksums_valid(p)
Matus Fabianb932d262017-12-18 05:38:24 -08004857 except:
4858 self.logger.error(ppp("Unexpected or invalid packet:", p))
4859 raise
4860
Matus Fabian70a26ac2018-05-14 06:20:28 -07004861 if eh_translate:
4862 sessions = self.vapi.nat44_user_session_dump(server.ip4n, 0)
4863 self.assertEqual(len(sessions), 1)
4864 self.assertTrue(sessions[0].ext_host_valid)
4865 self.assertTrue(sessions[0].is_twicenat)
4866 self.vapi.nat44_del_session(
4867 sessions[0].inside_ip_address,
4868 sessions[0].inside_port,
4869 sessions[0].protocol,
4870 ext_host_address=sessions[0].ext_host_nat_address,
4871 ext_host_port=sessions[0].ext_host_nat_port)
4872 sessions = self.vapi.nat44_user_session_dump(server.ip4n, 0)
4873 self.assertEqual(len(sessions), 0)
4874
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004875 def test_twice_nat(self):
4876 """ Twice NAT44 """
4877 self.twice_nat_common()
4878
4879 def test_self_twice_nat_positive(self):
4880 """ Self Twice NAT44 (positive test) """
4881 self.twice_nat_common(self_twice_nat=True, same_pg=True)
4882
4883 def test_self_twice_nat_negative(self):
4884 """ Self Twice NAT44 (negative test) """
4885 self.twice_nat_common(self_twice_nat=True)
4886
Matus Fabianb932d262017-12-18 05:38:24 -08004887 def test_twice_nat_lb(self):
4888 """ Twice NAT44 local service load balancing """
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004889 self.twice_nat_common(lb=True)
Matus Fabianb932d262017-12-18 05:38:24 -08004890
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004891 def test_self_twice_nat_lb_positive(self):
4892 """ Self Twice NAT44 local service load balancing (positive test) """
4893 self.twice_nat_common(lb=True, self_twice_nat=True, same_pg=True,
4894 client_id=1)
Matus Fabianb932d262017-12-18 05:38:24 -08004895
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004896 def test_self_twice_nat_lb_negative(self):
4897 """ Self Twice NAT44 local service load balancing (negative test) """
4898 self.twice_nat_common(lb=True, self_twice_nat=True, same_pg=True,
4899 client_id=2)
Matus Fabianb932d262017-12-18 05:38:24 -08004900
4901 def test_twice_nat_interface_addr(self):
4902 """ Acquire twice NAT44 addresses from interface """
Matus Fabiana6110b62018-06-13 05:39:07 -07004903 self.vapi.nat44_add_interface_addr(self.pg3.sw_if_index, twice_nat=1)
Matus Fabianb932d262017-12-18 05:38:24 -08004904
4905 # no address in NAT pool
4906 adresses = self.vapi.nat44_address_dump()
4907 self.assertEqual(0, len(adresses))
4908
4909 # configure interface address and check NAT address pool
Matus Fabiana6110b62018-06-13 05:39:07 -07004910 self.pg3.config_ip4()
Matus Fabianb932d262017-12-18 05:38:24 -08004911 adresses = self.vapi.nat44_address_dump()
4912 self.assertEqual(1, len(adresses))
Matus Fabiana6110b62018-06-13 05:39:07 -07004913 self.assertEqual(adresses[0].ip_address[0:4], self.pg3.local_ip4n)
Matus Fabianb932d262017-12-18 05:38:24 -08004914 self.assertEqual(adresses[0].twice_nat, 1)
4915
4916 # remove interface address and check NAT address pool
Matus Fabiana6110b62018-06-13 05:39:07 -07004917 self.pg3.unconfig_ip4()
Matus Fabianb932d262017-12-18 05:38:24 -08004918 adresses = self.vapi.nat44_address_dump()
4919 self.assertEqual(0, len(adresses))
4920
Matus Fabianebdf1902018-05-04 03:57:42 -07004921 def test_tcp_session_close_in(self):
4922 """ Close TCP session from inside network """
Matus Fabian229c1aa2018-05-28 04:09:52 -07004923 self.tcp_port_out = 10505
Matus Fabianebdf1902018-05-04 03:57:42 -07004924 self.nat44_add_address(self.nat_addr)
Matus Fabian229c1aa2018-05-28 04:09:52 -07004925 self.nat44_add_static_mapping(self.pg0.remote_ip4,
4926 self.nat_addr,
4927 self.tcp_port_in,
4928 self.tcp_port_out,
4929 proto=IP_PROTOS.tcp,
4930 twice_nat=1)
Matus Fabianebdf1902018-05-04 03:57:42 -07004931 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4932 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4933 is_inside=0)
4934
4935 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
4936 start_sessnum = len(sessions)
4937
4938 self.initiate_tcp_session(self.pg0, self.pg1)
4939
Matus Fabian229c1aa2018-05-28 04:09:52 -07004940 # FIN packet in -> out
4941 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4942 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4943 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
4944 flags="FA", seq=100, ack=300))
4945 self.pg0.add_stream(p)
4946 self.pg_enable_capture(self.pg_interfaces)
4947 self.pg_start()
4948 self.pg1.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07004949
Matus Fabian229c1aa2018-05-28 04:09:52 -07004950 pkts = []
Matus Fabianebdf1902018-05-04 03:57:42 -07004951
Matus Fabian229c1aa2018-05-28 04:09:52 -07004952 # ACK packet out -> in
4953 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4954 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4955 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
4956 flags="A", seq=300, ack=101))
4957 pkts.append(p)
Matus Fabianebdf1902018-05-04 03:57:42 -07004958
Matus Fabian229c1aa2018-05-28 04:09:52 -07004959 # FIN packet out -> in
4960 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4961 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4962 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
4963 flags="FA", seq=300, ack=101))
4964 pkts.append(p)
Matus Fabianebdf1902018-05-04 03:57:42 -07004965
Matus Fabian229c1aa2018-05-28 04:09:52 -07004966 self.pg1.add_stream(pkts)
4967 self.pg_enable_capture(self.pg_interfaces)
4968 self.pg_start()
4969 self.pg0.get_capture(2)
Matus Fabianebdf1902018-05-04 03:57:42 -07004970
Matus Fabian229c1aa2018-05-28 04:09:52 -07004971 # ACK packet in -> out
4972 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4973 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4974 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
4975 flags="A", seq=101, ack=301))
4976 self.pg0.add_stream(p)
4977 self.pg_enable_capture(self.pg_interfaces)
4978 self.pg_start()
4979 self.pg1.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07004980
Matus Fabian229c1aa2018-05-28 04:09:52 -07004981 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n,
4982 0)
4983 self.assertEqual(len(sessions) - start_sessnum, 0)
Matus Fabianebdf1902018-05-04 03:57:42 -07004984
4985 def test_tcp_session_close_out(self):
4986 """ Close TCP session from outside network """
Matus Fabian229c1aa2018-05-28 04:09:52 -07004987 self.tcp_port_out = 10505
Matus Fabianebdf1902018-05-04 03:57:42 -07004988 self.nat44_add_address(self.nat_addr)
Matus Fabian229c1aa2018-05-28 04:09:52 -07004989 self.nat44_add_static_mapping(self.pg0.remote_ip4,
4990 self.nat_addr,
4991 self.tcp_port_in,
4992 self.tcp_port_out,
4993 proto=IP_PROTOS.tcp,
4994 twice_nat=1)
Matus Fabianebdf1902018-05-04 03:57:42 -07004995 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4996 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4997 is_inside=0)
4998
4999 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
5000 start_sessnum = len(sessions)
5001
5002 self.initiate_tcp_session(self.pg0, self.pg1)
5003
Matus Fabian229c1aa2018-05-28 04:09:52 -07005004 # FIN packet out -> in
5005 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5006 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5007 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
5008 flags="FA", seq=100, ack=300))
5009 self.pg1.add_stream(p)
5010 self.pg_enable_capture(self.pg_interfaces)
5011 self.pg_start()
5012 self.pg0.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07005013
Matus Fabian229c1aa2018-05-28 04:09:52 -07005014 # FIN+ACK packet in -> out
5015 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5016 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5017 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
5018 flags="FA", seq=300, ack=101))
Matus Fabianebdf1902018-05-04 03:57:42 -07005019
Matus Fabian229c1aa2018-05-28 04:09:52 -07005020 self.pg0.add_stream(p)
5021 self.pg_enable_capture(self.pg_interfaces)
5022 self.pg_start()
5023 self.pg1.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07005024
Matus Fabian229c1aa2018-05-28 04:09:52 -07005025 # ACK packet out -> in
5026 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5027 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5028 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
5029 flags="A", seq=101, ack=301))
5030 self.pg1.add_stream(p)
5031 self.pg_enable_capture(self.pg_interfaces)
5032 self.pg_start()
5033 self.pg0.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07005034
Matus Fabian229c1aa2018-05-28 04:09:52 -07005035 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n,
5036 0)
5037 self.assertEqual(len(sessions) - start_sessnum, 0)
Matus Fabianebdf1902018-05-04 03:57:42 -07005038
5039 def test_tcp_session_close_simultaneous(self):
5040 """ Close TCP session from inside network """
Matus Fabian229c1aa2018-05-28 04:09:52 -07005041 self.tcp_port_out = 10505
Matus Fabianebdf1902018-05-04 03:57:42 -07005042 self.nat44_add_address(self.nat_addr)
Matus Fabian229c1aa2018-05-28 04:09:52 -07005043 self.nat44_add_static_mapping(self.pg0.remote_ip4,
5044 self.nat_addr,
5045 self.tcp_port_in,
5046 self.tcp_port_out,
5047 proto=IP_PROTOS.tcp,
5048 twice_nat=1)
Matus Fabianebdf1902018-05-04 03:57:42 -07005049 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5050 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
5051 is_inside=0)
5052
5053 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
5054 start_sessnum = len(sessions)
5055
5056 self.initiate_tcp_session(self.pg0, self.pg1)
5057
Matus Fabian229c1aa2018-05-28 04:09:52 -07005058 # FIN packet in -> out
5059 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5060 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5061 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
5062 flags="FA", seq=100, ack=300))
5063 self.pg0.add_stream(p)
5064 self.pg_enable_capture(self.pg_interfaces)
5065 self.pg_start()
5066 self.pg1.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07005067
Matus Fabian229c1aa2018-05-28 04:09:52 -07005068 # FIN packet out -> in
5069 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5070 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5071 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
5072 flags="FA", seq=300, ack=100))
5073 self.pg1.add_stream(p)
5074 self.pg_enable_capture(self.pg_interfaces)
5075 self.pg_start()
5076 self.pg0.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07005077
Matus Fabian229c1aa2018-05-28 04:09:52 -07005078 # ACK packet in -> out
5079 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5080 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5081 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
5082 flags="A", seq=101, ack=301))
5083 self.pg0.add_stream(p)
5084 self.pg_enable_capture(self.pg_interfaces)
5085 self.pg_start()
5086 self.pg1.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07005087
Matus Fabian229c1aa2018-05-28 04:09:52 -07005088 # ACK packet out -> in
5089 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5090 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5091 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
5092 flags="A", seq=301, ack=101))
5093 self.pg1.add_stream(p)
5094 self.pg_enable_capture(self.pg_interfaces)
5095 self.pg_start()
5096 self.pg0.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07005097
Matus Fabian229c1aa2018-05-28 04:09:52 -07005098 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n,
5099 0)
5100 self.assertEqual(len(sessions) - start_sessnum, 0)
Matus Fabianebdf1902018-05-04 03:57:42 -07005101
Matus Fabiana6110b62018-06-13 05:39:07 -07005102 def test_one_armed_nat44_static(self):
5103 """ One armed NAT44 and 1:1 NAPT asymmetrical rule """
5104 remote_host = self.pg4.remote_hosts[0]
5105 local_host = self.pg4.remote_hosts[1]
5106 external_port = 80
5107 local_port = 8080
5108 eh_port_in = 0
5109
5110 self.vapi.nat44_forwarding_enable_disable(1)
5111 self.nat44_add_address(self.nat_addr, twice_nat=1)
5112 self.nat44_add_static_mapping(local_host.ip4, self.nat_addr,
5113 local_port, external_port,
5114 proto=IP_PROTOS.tcp, out2in_only=1,
5115 twice_nat=1)
5116 self.vapi.nat44_interface_add_del_feature(self.pg4.sw_if_index)
5117 self.vapi.nat44_interface_add_del_feature(self.pg4.sw_if_index,
5118 is_inside=0)
5119
5120 # from client to service
5121 p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
5122 IP(src=remote_host.ip4, dst=self.nat_addr) /
5123 TCP(sport=12345, dport=external_port))
5124 self.pg4.add_stream(p)
5125 self.pg_enable_capture(self.pg_interfaces)
5126 self.pg_start()
5127 capture = self.pg4.get_capture(1)
5128 p = capture[0]
5129 try:
5130 ip = p[IP]
5131 tcp = p[TCP]
5132 self.assertEqual(ip.dst, local_host.ip4)
5133 self.assertEqual(ip.src, self.nat_addr)
5134 self.assertEqual(tcp.dport, local_port)
5135 self.assertNotEqual(tcp.sport, 12345)
5136 eh_port_in = tcp.sport
5137 self.assert_packet_checksums_valid(p)
5138 except:
5139 self.logger.error(ppp("Unexpected or invalid packet:", p))
5140 raise
5141
5142 # from service back to client
5143 p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
5144 IP(src=local_host.ip4, dst=self.nat_addr) /
5145 TCP(sport=local_port, dport=eh_port_in))
5146 self.pg4.add_stream(p)
5147 self.pg_enable_capture(self.pg_interfaces)
5148 self.pg_start()
5149 capture = self.pg4.get_capture(1)
5150 p = capture[0]
5151 try:
5152 ip = p[IP]
5153 tcp = p[TCP]
5154 self.assertEqual(ip.src, self.nat_addr)
5155 self.assertEqual(ip.dst, remote_host.ip4)
5156 self.assertEqual(tcp.sport, external_port)
5157 self.assertEqual(tcp.dport, 12345)
5158 self.assert_packet_checksums_valid(p)
5159 except:
5160 self.logger.error(ppp("Unexpected or invalid packet:", p))
5161 raise
5162
5163 def test_static_with_port_out2(self):
5164 """ 1:1 NAPT asymmetrical rule """
5165
5166 external_port = 80
5167 local_port = 8080
5168
5169 self.vapi.nat44_forwarding_enable_disable(1)
5170 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
5171 local_port, external_port,
5172 proto=IP_PROTOS.tcp, out2in_only=1)
5173 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5174 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
5175 is_inside=0)
5176
5177 # from client to service
5178 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5179 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5180 TCP(sport=12345, dport=external_port))
5181 self.pg1.add_stream(p)
5182 self.pg_enable_capture(self.pg_interfaces)
5183 self.pg_start()
5184 capture = self.pg0.get_capture(1)
5185 p = capture[0]
5186 try:
5187 ip = p[IP]
5188 tcp = p[TCP]
5189 self.assertEqual(ip.dst, self.pg0.remote_ip4)
5190 self.assertEqual(tcp.dport, local_port)
5191 self.assert_packet_checksums_valid(p)
5192 except:
5193 self.logger.error(ppp("Unexpected or invalid packet:", p))
5194 raise
5195
5196 # ICMP error
5197 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5198 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5199 ICMP(type=11) / capture[0][IP])
5200 self.pg0.add_stream(p)
5201 self.pg_enable_capture(self.pg_interfaces)
5202 self.pg_start()
5203 capture = self.pg1.get_capture(1)
5204 p = capture[0]
5205 try:
5206 self.assertEqual(p[IP].src, self.nat_addr)
5207 inner = p[IPerror]
5208 self.assertEqual(inner.dst, self.nat_addr)
5209 self.assertEqual(inner[TCPerror].dport, external_port)
5210 except:
5211 self.logger.error(ppp("Unexpected or invalid packet:", p))
5212 raise
5213
5214 # from service back to client
5215 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5216 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5217 TCP(sport=local_port, dport=12345))
5218 self.pg0.add_stream(p)
5219 self.pg_enable_capture(self.pg_interfaces)
5220 self.pg_start()
5221 capture = self.pg1.get_capture(1)
5222 p = capture[0]
5223 try:
5224 ip = p[IP]
5225 tcp = p[TCP]
5226 self.assertEqual(ip.src, self.nat_addr)
5227 self.assertEqual(tcp.sport, external_port)
5228 self.assert_packet_checksums_valid(p)
5229 except:
5230 self.logger.error(ppp("Unexpected or invalid packet:", p))
5231 raise
5232
5233 # ICMP error
5234 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
5235 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5236 ICMP(type=11) / capture[0][IP])
5237 self.pg1.add_stream(p)
5238 self.pg_enable_capture(self.pg_interfaces)
5239 self.pg_start()
5240 capture = self.pg0.get_capture(1)
5241 p = capture[0]
5242 try:
5243 self.assertEqual(p[IP].dst, self.pg0.remote_ip4)
5244 inner = p[IPerror]
5245 self.assertEqual(inner.src, self.pg0.remote_ip4)
5246 self.assertEqual(inner[TCPerror].sport, local_port)
5247 except:
5248 self.logger.error(ppp("Unexpected or invalid packet:", p))
5249 raise
5250
5251 # from client to server (no translation)
5252 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5253 IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
5254 TCP(sport=12346, dport=local_port))
5255 self.pg1.add_stream(p)
5256 self.pg_enable_capture(self.pg_interfaces)
5257 self.pg_start()
5258 capture = self.pg0.get_capture(1)
5259 p = capture[0]
5260 try:
5261 ip = p[IP]
5262 tcp = p[TCP]
5263 self.assertEqual(ip.dst, self.pg0.remote_ip4)
5264 self.assertEqual(tcp.dport, local_port)
5265 self.assert_packet_checksums_valid(p)
5266 except:
5267 self.logger.error(ppp("Unexpected or invalid packet:", p))
5268 raise
5269
5270 # from service back to client (no translation)
5271 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5272 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5273 TCP(sport=local_port, dport=12346))
5274 self.pg0.add_stream(p)
5275 self.pg_enable_capture(self.pg_interfaces)
5276 self.pg_start()
5277 capture = self.pg1.get_capture(1)
5278 p = capture[0]
5279 try:
5280 ip = p[IP]
5281 tcp = p[TCP]
5282 self.assertEqual(ip.src, self.pg0.remote_ip4)
5283 self.assertEqual(tcp.sport, local_port)
5284 self.assert_packet_checksums_valid(p)
5285 except:
5286 self.logger.error(ppp("Unexpected or invalid packet:", p))
5287 raise
5288
Matus Fabian235a47e2018-06-25 16:42:36 -07005289 def test_output_feature(self):
5290 """ NAT44 interface output feature (in2out postrouting) """
5291 self.vapi.nat44_forwarding_enable_disable(1)
5292 self.nat44_add_address(self.nat_addr)
5293 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
5294 is_inside=0)
5295 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
5296 is_inside=0)
5297
5298 # in2out
5299 pkts = self.create_stream_in(self.pg0, self.pg1)
5300 self.pg0.add_stream(pkts)
5301 self.pg_enable_capture(self.pg_interfaces)
5302 self.pg_start()
5303 capture = self.pg1.get_capture(len(pkts))
5304 self.verify_capture_out(capture)
5305
5306 # out2in
5307 pkts = self.create_stream_out(self.pg1)
5308 self.pg1.add_stream(pkts)
5309 self.pg_enable_capture(self.pg_interfaces)
5310 self.pg_start()
5311 capture = self.pg0.get_capture(len(pkts))
5312 self.verify_capture_in(capture, self.pg0)
5313
Matus Fabian8008d7c2018-07-09 01:34:20 -07005314 def test_multiple_vrf(self):
5315 """ Multiple VRF setup """
5316 external_addr = '1.2.3.4'
5317 external_port = 80
5318 local_port = 8080
5319 port = 0
5320
5321 self.vapi.nat44_forwarding_enable_disable(1)
5322 self.nat44_add_address(self.nat_addr)
5323 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5324 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
5325 is_inside=0)
5326 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
5327 is_inside=0)
5328 self.vapi.nat44_interface_add_del_feature(self.pg5.sw_if_index)
5329 self.vapi.nat44_interface_add_del_feature(self.pg5.sw_if_index,
5330 is_inside=0)
5331 self.vapi.nat44_interface_add_del_feature(self.pg6.sw_if_index,
5332 is_inside=0)
5333 self.nat44_add_static_mapping(self.pg5.remote_ip4, external_addr,
5334 local_port, external_port, vrf_id=1,
5335 proto=IP_PROTOS.tcp, out2in_only=1)
5336 self.nat44_add_static_mapping(
5337 self.pg0.remote_ip4, external_sw_if_index=self.pg0.sw_if_index,
5338 local_port=local_port, vrf_id=0, external_port=external_port,
5339 proto=IP_PROTOS.tcp, out2in_only=1)
5340
5341 # from client to service (both VRF1)
5342 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
5343 IP(src=self.pg6.remote_ip4, dst=external_addr) /
5344 TCP(sport=12345, dport=external_port))
5345 self.pg6.add_stream(p)
5346 self.pg_enable_capture(self.pg_interfaces)
5347 self.pg_start()
5348 capture = self.pg5.get_capture(1)
5349 p = capture[0]
5350 try:
5351 ip = p[IP]
5352 tcp = p[TCP]
5353 self.assertEqual(ip.dst, self.pg5.remote_ip4)
5354 self.assertEqual(tcp.dport, local_port)
5355 self.assert_packet_checksums_valid(p)
5356 except:
5357 self.logger.error(ppp("Unexpected or invalid packet:", p))
5358 raise
5359
5360 # from service back to client (both VRF1)
5361 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
5362 IP(src=self.pg5.remote_ip4, dst=self.pg6.remote_ip4) /
5363 TCP(sport=local_port, dport=12345))
5364 self.pg5.add_stream(p)
5365 self.pg_enable_capture(self.pg_interfaces)
5366 self.pg_start()
5367 capture = self.pg6.get_capture(1)
5368 p = capture[0]
5369 try:
5370 ip = p[IP]
5371 tcp = p[TCP]
5372 self.assertEqual(ip.src, external_addr)
5373 self.assertEqual(tcp.sport, external_port)
5374 self.assert_packet_checksums_valid(p)
5375 except:
5376 self.logger.error(ppp("Unexpected or invalid packet:", p))
5377 raise
5378
5379 # dynamic NAT from VRF1 to VRF0 (output-feature)
5380 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
5381 IP(src=self.pg5.remote_ip4, dst=self.pg1.remote_ip4) /
5382 TCP(sport=2345, dport=22))
5383 self.pg5.add_stream(p)
5384 self.pg_enable_capture(self.pg_interfaces)
5385 self.pg_start()
5386 capture = self.pg1.get_capture(1)
5387 p = capture[0]
5388 try:
5389 ip = p[IP]
5390 tcp = p[TCP]
5391 self.assertEqual(ip.src, self.nat_addr)
5392 self.assertNotEqual(tcp.sport, 2345)
5393 self.assert_packet_checksums_valid(p)
5394 port = tcp.sport
5395 except:
5396 self.logger.error(ppp("Unexpected or invalid packet:", p))
5397 raise
5398
5399 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5400 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5401 TCP(sport=22, dport=port))
5402 self.pg1.add_stream(p)
5403 self.pg_enable_capture(self.pg_interfaces)
5404 self.pg_start()
5405 capture = self.pg5.get_capture(1)
5406 p = capture[0]
5407 try:
5408 ip = p[IP]
5409 tcp = p[TCP]
5410 self.assertEqual(ip.dst, self.pg5.remote_ip4)
5411 self.assertEqual(tcp.dport, 2345)
5412 self.assert_packet_checksums_valid(p)
5413 except:
5414 self.logger.error(ppp("Unexpected or invalid packet:", p))
5415 raise
5416
5417 # from client VRF1 to service VRF0
5418 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
5419 IP(src=self.pg6.remote_ip4, dst=self.pg0.local_ip4) /
5420 TCP(sport=12346, dport=external_port))
5421 self.pg6.add_stream(p)
5422 self.pg_enable_capture(self.pg_interfaces)
5423 self.pg_start()
5424 capture = self.pg0.get_capture(1)
5425 p = capture[0]
5426 try:
5427 ip = p[IP]
5428 tcp = p[TCP]
5429 self.assertEqual(ip.dst, self.pg0.remote_ip4)
5430 self.assertEqual(tcp.dport, local_port)
5431 self.assert_packet_checksums_valid(p)
5432 except:
5433 self.logger.error(ppp("Unexpected or invalid packet:", p))
5434 raise
5435
5436 # from service VRF0 back to client VRF1
5437 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5438 IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
5439 TCP(sport=local_port, dport=12346))
5440 self.pg0.add_stream(p)
5441 self.pg_enable_capture(self.pg_interfaces)
5442 self.pg_start()
5443 capture = self.pg6.get_capture(1)
5444 p = capture[0]
5445 try:
5446 ip = p[IP]
5447 tcp = p[TCP]
5448 self.assertEqual(ip.src, self.pg0.local_ip4)
5449 self.assertEqual(tcp.sport, external_port)
5450 self.assert_packet_checksums_valid(p)
5451 except:
5452 self.logger.error(ppp("Unexpected or invalid packet:", p))
5453 raise
5454
5455 # from client VRF0 to service VRF1
5456 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5457 IP(src=self.pg0.remote_ip4, dst=external_addr) /
5458 TCP(sport=12347, dport=external_port))
5459 self.pg0.add_stream(p)
5460 self.pg_enable_capture(self.pg_interfaces)
5461 self.pg_start()
5462 capture = self.pg5.get_capture(1)
5463 p = capture[0]
5464 try:
5465 ip = p[IP]
5466 tcp = p[TCP]
5467 self.assertEqual(ip.dst, self.pg5.remote_ip4)
5468 self.assertEqual(tcp.dport, local_port)
5469 self.assert_packet_checksums_valid(p)
5470 except:
5471 self.logger.error(ppp("Unexpected or invalid packet:", p))
5472 raise
5473
5474 # from service VRF1 back to client VRF0
5475 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
5476 IP(src=self.pg5.remote_ip4, dst=self.pg0.remote_ip4) /
5477 TCP(sport=local_port, dport=12347))
5478 self.pg5.add_stream(p)
5479 self.pg_enable_capture(self.pg_interfaces)
5480 self.pg_start()
5481 capture = self.pg0.get_capture(1)
5482 p = capture[0]
5483 try:
5484 ip = p[IP]
5485 tcp = p[TCP]
5486 self.assertEqual(ip.src, external_addr)
5487 self.assertEqual(tcp.sport, external_port)
5488 self.assert_packet_checksums_valid(p)
5489 except:
5490 self.logger.error(ppp("Unexpected or invalid packet:", p))
5491 raise
5492
5493 # from client to server (both VRF1, no translation)
5494 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
5495 IP(src=self.pg6.remote_ip4, dst=self.pg5.remote_ip4) /
5496 TCP(sport=12348, dport=local_port))
5497 self.pg6.add_stream(p)
5498 self.pg_enable_capture(self.pg_interfaces)
5499 self.pg_start()
5500 capture = self.pg5.get_capture(1)
5501 p = capture[0]
5502 try:
5503 ip = p[IP]
5504 tcp = p[TCP]
5505 self.assertEqual(ip.dst, self.pg5.remote_ip4)
5506 self.assertEqual(tcp.dport, local_port)
5507 self.assert_packet_checksums_valid(p)
5508 except:
5509 self.logger.error(ppp("Unexpected or invalid packet:", p))
5510 raise
5511
5512 # from server back to client (both VRF1, no translation)
5513 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
5514 IP(src=self.pg5.remote_ip4, dst=self.pg6.remote_ip4) /
5515 TCP(sport=local_port, dport=12348))
5516 self.pg5.add_stream(p)
5517 self.pg_enable_capture(self.pg_interfaces)
5518 self.pg_start()
5519 capture = self.pg6.get_capture(1)
5520 p = capture[0]
5521 try:
5522 ip = p[IP]
5523 tcp = p[TCP]
5524 self.assertEqual(ip.src, self.pg5.remote_ip4)
5525 self.assertEqual(tcp.sport, local_port)
5526 self.assert_packet_checksums_valid(p)
5527 except:
5528 self.logger.error(ppp("Unexpected or invalid packet:", p))
5529 raise
5530
5531 # from client VRF1 to server VRF0 (no translation)
5532 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5533 IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
5534 TCP(sport=local_port, dport=12349))
5535 self.pg0.add_stream(p)
5536 self.pg_enable_capture(self.pg_interfaces)
5537 self.pg_start()
5538 capture = self.pg6.get_capture(1)
5539 p = capture[0]
5540 try:
5541 ip = p[IP]
5542 tcp = p[TCP]
5543 self.assertEqual(ip.src, self.pg0.remote_ip4)
5544 self.assertEqual(tcp.sport, local_port)
5545 self.assert_packet_checksums_valid(p)
5546 except:
5547 self.logger.error(ppp("Unexpected or invalid packet:", p))
5548 raise
5549
5550 # from server VRF0 back to client VRF1 (no translation)
5551 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5552 IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
5553 TCP(sport=local_port, dport=12349))
5554 self.pg0.add_stream(p)
5555 self.pg_enable_capture(self.pg_interfaces)
5556 self.pg_start()
5557 capture = self.pg6.get_capture(1)
5558 p = capture[0]
5559 try:
5560 ip = p[IP]
5561 tcp = p[TCP]
5562 self.assertEqual(ip.src, self.pg0.remote_ip4)
5563 self.assertEqual(tcp.sport, local_port)
5564 self.assert_packet_checksums_valid(p)
5565 except:
5566 self.logger.error(ppp("Unexpected or invalid packet:", p))
5567 raise
5568
5569 # from client VRF0 to server VRF1 (no translation)
5570 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5571 IP(src=self.pg0.remote_ip4, dst=self.pg5.remote_ip4) /
5572 TCP(sport=12344, dport=local_port))
5573 self.pg0.add_stream(p)
5574 self.pg_enable_capture(self.pg_interfaces)
5575 self.pg_start()
5576 capture = self.pg5.get_capture(1)
5577 p = capture[0]
5578 try:
5579 ip = p[IP]
5580 tcp = p[TCP]
5581 self.assertEqual(ip.dst, self.pg5.remote_ip4)
5582 self.assertEqual(tcp.dport, local_port)
5583 self.assert_packet_checksums_valid(p)
5584 except:
5585 self.logger.error(ppp("Unexpected or invalid packet:", p))
5586 raise
5587
5588 # from server VRF1 back to client VRF0 (no translation)
5589 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
5590 IP(src=self.pg5.remote_ip4, dst=self.pg0.remote_ip4) /
5591 TCP(sport=local_port, dport=12344))
5592 self.pg5.add_stream(p)
5593 self.pg_enable_capture(self.pg_interfaces)
5594 self.pg_start()
5595 capture = self.pg0.get_capture(1)
5596 p = capture[0]
5597 try:
5598 ip = p[IP]
5599 tcp = p[TCP]
5600 self.assertEqual(ip.src, self.pg5.remote_ip4)
5601 self.assertEqual(tcp.sport, local_port)
5602 self.assert_packet_checksums_valid(p)
5603 except:
5604 self.logger.error(ppp("Unexpected or invalid packet:", p))
5605 raise
5606
Matus Fabian878c6462018-08-23 00:33:35 -07005607 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
5608 def test_session_timeout(self):
5609 """ NAT44 session timeouts """
5610 self.nat44_add_address(self.nat_addr)
5611 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5612 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
5613 is_inside=0)
5614 self.vapi.nat_set_timeouts(icmp=5)
5615
5616 max_sessions = 1000
5617 pkts = []
5618 for i in range(0, max_sessions):
5619 src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
5620 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5621 IP(src=src, dst=self.pg1.remote_ip4) /
5622 ICMP(id=1025, type='echo-request'))
5623 pkts.append(p)
5624 self.pg0.add_stream(pkts)
5625 self.pg_enable_capture(self.pg_interfaces)
5626 self.pg_start()
5627 self.pg1.get_capture(max_sessions)
5628
5629 sleep(10)
5630
5631 pkts = []
5632 for i in range(0, max_sessions):
5633 src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
5634 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5635 IP(src=src, dst=self.pg1.remote_ip4) /
5636 ICMP(id=1026, type='echo-request'))
5637 pkts.append(p)
5638 self.pg0.add_stream(pkts)
5639 self.pg_enable_capture(self.pg_interfaces)
5640 self.pg_start()
5641 self.pg1.get_capture(max_sessions)
5642
5643 nsessions = 0
5644 users = self.vapi.nat44_user_dump()
5645 for user in users:
5646 nsessions = nsessions + user.nsessions
5647 self.assertLess(nsessions, 2 * max_sessions)
5648
5649 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
5650 def test_session_limit_per_user(self):
5651 """ Maximum sessions per user limit """
5652 self.nat44_add_address(self.nat_addr)
5653 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5654 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
5655 is_inside=0)
5656 self.vapi.set_ipfix_exporter(collector_address=self.pg2.remote_ip4n,
5657 src_address=self.pg2.local_ip4n,
5658 path_mtu=512,
5659 template_interval=10)
Matus Fabian8fdc0152018-09-24 04:41:28 -07005660 self.vapi.nat_set_timeouts(udp=5)
Matus Fabian878c6462018-08-23 00:33:35 -07005661
5662 # get maximum number of translations per user
5663 nat44_config = self.vapi.nat_show_config()
5664
5665 pkts = []
5666 for port in range(0, nat44_config.max_translations_per_user):
5667 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5668 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5669 UDP(sport=1025 + port, dport=1025 + port))
5670 pkts.append(p)
5671
5672 self.pg0.add_stream(pkts)
5673 self.pg_enable_capture(self.pg_interfaces)
5674 self.pg_start()
5675 capture = self.pg1.get_capture(len(pkts))
5676
5677 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
5678 src_port=self.ipfix_src_port)
5679
5680 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5681 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5682 UDP(sport=3001, dport=3002))
5683 self.pg0.add_stream(p)
5684 self.pg_enable_capture(self.pg_interfaces)
5685 self.pg_start()
5686 capture = self.pg1.assert_nothing_captured()
5687
5688 # verify IPFIX logging
5689 self.vapi.cli("ipfix flush") # FIXME this should be an API call
5690 sleep(1)
5691 capture = self.pg2.get_capture(10)
5692 ipfix = IPFIXDecoder()
5693 # first load template
5694 for p in capture:
5695 self.assertTrue(p.haslayer(IPFIX))
5696 if p.haslayer(Template):
5697 ipfix.add_template(p.getlayer(Template))
5698 # verify events in data set
5699 for p in capture:
5700 if p.haslayer(Data):
5701 data = ipfix.decode_data_set(p.getlayer(Set))
5702 self.verify_ipfix_max_entries_per_user(
5703 data,
5704 nat44_config.max_translations_per_user,
5705 self.pg0.remote_ip4n)
5706
Matus Fabian8fdc0152018-09-24 04:41:28 -07005707 sleep(6)
5708 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5709 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5710 UDP(sport=3001, dport=3002))
5711 self.pg0.add_stream(p)
5712 self.pg_enable_capture(self.pg_interfaces)
5713 self.pg_start()
5714 self.pg1.get_capture(1)
5715
Matus Fabiande886752016-12-07 03:38:19 -08005716 def tearDown(self):
Matus Fabiana6110b62018-06-13 05:39:07 -07005717 super(TestNAT44EndpointDependent, self).tearDown()
Matus Fabiande886752016-12-07 03:38:19 -08005718 if not self.vpp_dead:
Matus Fabian82119542018-01-25 01:13:22 -08005719 self.logger.info(self.vapi.cli("show nat44 addresses"))
5720 self.logger.info(self.vapi.cli("show nat44 interfaces"))
5721 self.logger.info(self.vapi.cli("show nat44 static mappings"))
5722 self.logger.info(self.vapi.cli("show nat44 interface address"))
5723 self.logger.info(self.vapi.cli("show nat44 sessions detail"))
Matus Fabian229c1aa2018-05-28 04:09:52 -07005724 self.logger.info(self.vapi.cli("show nat44 hash tables detail"))
Matus Fabian878c6462018-08-23 00:33:35 -07005725 self.logger.info(self.vapi.cli("show nat timeouts"))
Matus Fabian2ba92e32017-08-21 07:05:03 -07005726 self.clear_nat44()
Matus Fabian229c1aa2018-05-28 04:09:52 -07005727 self.vapi.cli("clear logging")
Matus Fabiande886752016-12-07 03:38:19 -08005728
Matus Fabianeea28d72017-01-13 04:15:54 -08005729
Juraj Slobodacba69362017-12-19 02:09:32 +01005730class TestNAT44Out2InDPO(MethodHolder):
5731 """ NAT44 Test Cases using out2in DPO """
5732
5733 @classmethod
5734 def setUpConstants(cls):
5735 super(TestNAT44Out2InDPO, cls).setUpConstants()
5736 cls.vpp_cmdline.extend(["nat", "{", "out2in dpo", "}"])
5737
5738 @classmethod
5739 def setUpClass(cls):
5740 super(TestNAT44Out2InDPO, cls).setUpClass()
Matus Fabian229c1aa2018-05-28 04:09:52 -07005741 cls.vapi.cli("set log class nat level debug")
Juraj Slobodacba69362017-12-19 02:09:32 +01005742
5743 try:
5744 cls.tcp_port_in = 6303
5745 cls.tcp_port_out = 6303
5746 cls.udp_port_in = 6304
5747 cls.udp_port_out = 6304
5748 cls.icmp_id_in = 6305
5749 cls.icmp_id_out = 6305
5750 cls.nat_addr = '10.0.0.3'
5751 cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
5752 cls.dst_ip4 = '192.168.70.1'
5753
5754 cls.create_pg_interfaces(range(2))
5755
5756 cls.pg0.admin_up()
5757 cls.pg0.config_ip4()
5758 cls.pg0.resolve_arp()
5759
5760 cls.pg1.admin_up()
5761 cls.pg1.config_ip6()
5762 cls.pg1.resolve_ndp()
5763
5764 cls.vapi.ip_add_del_route(is_ipv6=True, dst_address='\x00'*16,
5765 dst_address_length=0,
5766 next_hop_address=cls.pg1.remote_ip6n,
5767 next_hop_sw_if_index=cls.pg1.sw_if_index)
5768
5769 except Exception:
5770 super(TestNAT44Out2InDPO, cls).tearDownClass()
5771 raise
5772
5773 def configure_xlat(self):
5774 self.dst_ip6_pfx = '1:2:3::'
5775 self.dst_ip6_pfx_n = socket.inet_pton(socket.AF_INET6,
5776 self.dst_ip6_pfx)
5777 self.dst_ip6_pfx_len = 96
5778 self.src_ip6_pfx = '4:5:6::'
5779 self.src_ip6_pfx_n = socket.inet_pton(socket.AF_INET6,
5780 self.src_ip6_pfx)
5781 self.src_ip6_pfx_len = 96
5782 self.vapi.map_add_domain(self.dst_ip6_pfx_n, self.dst_ip6_pfx_len,
5783 self.src_ip6_pfx_n, self.src_ip6_pfx_len,
5784 '\x00\x00\x00\x00', 0, is_translation=1,
5785 is_rfc6052=1)
5786
5787 def test_464xlat_ce(self):
5788 """ Test 464XLAT CE with NAT44 """
5789
Matus Fabian69ce30d2018-08-22 01:27:10 -07005790 nat_config = self.vapi.nat_show_config()
5791 self.assertEqual(1, nat_config.out2in_dpo)
5792
Juraj Slobodacba69362017-12-19 02:09:32 +01005793 self.configure_xlat()
5794
5795 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5796 self.vapi.nat44_add_del_address_range(self.nat_addr_n, self.nat_addr_n)
5797
5798 out_src_ip6 = self.compose_ip6(self.dst_ip4, self.dst_ip6_pfx,
5799 self.dst_ip6_pfx_len)
5800 out_dst_ip6 = self.compose_ip6(self.nat_addr, self.src_ip6_pfx,
5801 self.src_ip6_pfx_len)
5802
5803 try:
5804 pkts = self.create_stream_in(self.pg0, self.pg1, self.dst_ip4)
5805 self.pg0.add_stream(pkts)
5806 self.pg_enable_capture(self.pg_interfaces)
5807 self.pg_start()
5808 capture = self.pg1.get_capture(len(pkts))
5809 self.verify_capture_out_ip6(capture, nat_ip=out_dst_ip6,
5810 dst_ip=out_src_ip6)
5811
5812 pkts = self.create_stream_out_ip6(self.pg1, out_src_ip6,
5813 out_dst_ip6)
5814 self.pg1.add_stream(pkts)
5815 self.pg_enable_capture(self.pg_interfaces)
5816 self.pg_start()
5817 capture = self.pg0.get_capture(len(pkts))
5818 self.verify_capture_in(capture, self.pg0)
5819 finally:
5820 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
5821 is_add=0)
5822 self.vapi.nat44_add_del_address_range(self.nat_addr_n,
5823 self.nat_addr_n, is_add=0)
5824
5825 def test_464xlat_ce_no_nat(self):
5826 """ Test 464XLAT CE without NAT44 """
5827
5828 self.configure_xlat()
5829
5830 out_src_ip6 = self.compose_ip6(self.dst_ip4, self.dst_ip6_pfx,
5831 self.dst_ip6_pfx_len)
5832 out_dst_ip6 = self.compose_ip6(self.pg0.remote_ip4, self.src_ip6_pfx,
5833 self.src_ip6_pfx_len)
5834
5835 pkts = self.create_stream_in(self.pg0, self.pg1, self.dst_ip4)
5836 self.pg0.add_stream(pkts)
5837 self.pg_enable_capture(self.pg_interfaces)
5838 self.pg_start()
5839 capture = self.pg1.get_capture(len(pkts))
5840 self.verify_capture_out_ip6(capture, dst_ip=out_src_ip6,
5841 nat_ip=out_dst_ip6, same_port=True)
5842
5843 pkts = self.create_stream_out_ip6(self.pg1, out_src_ip6, out_dst_ip6)
5844 self.pg1.add_stream(pkts)
5845 self.pg_enable_capture(self.pg_interfaces)
5846 self.pg_start()
5847 capture = self.pg0.get_capture(len(pkts))
5848 self.verify_capture_in(capture, self.pg0)
5849
5850
Martin Gálikd7f75cd2017-03-27 06:02:47 -07005851class TestDeterministicNAT(MethodHolder):
Matus Fabian066f0342017-02-10 03:48:01 -08005852 """ Deterministic NAT Test Cases """
5853
5854 @classmethod
5855 def setUpConstants(cls):
5856 super(TestDeterministicNAT, cls).setUpConstants()
Matus Fabian2ba92e32017-08-21 07:05:03 -07005857 cls.vpp_cmdline.extend(["nat", "{", "deterministic", "}"])
Matus Fabian066f0342017-02-10 03:48:01 -08005858
5859 @classmethod
5860 def setUpClass(cls):
5861 super(TestDeterministicNAT, cls).setUpClass()
Matus Fabian229c1aa2018-05-28 04:09:52 -07005862 cls.vapi.cli("set log class nat level debug")
Matus Fabian066f0342017-02-10 03:48:01 -08005863
5864 try:
Martin Gálik977c1cb2017-03-30 23:21:51 -07005865 cls.tcp_port_in = 6303
Martin Gálik9806eae2017-04-25 01:25:08 -07005866 cls.tcp_external_port = 6303
Martin Gálik977c1cb2017-03-30 23:21:51 -07005867 cls.udp_port_in = 6304
Martin Gálik9806eae2017-04-25 01:25:08 -07005868 cls.udp_external_port = 6304
Martin Gálik977c1cb2017-03-30 23:21:51 -07005869 cls.icmp_id_in = 6305
Matus Fabian2ba92e32017-08-21 07:05:03 -07005870 cls.nat_addr = '10.0.0.3'
Martin Gálik977c1cb2017-03-30 23:21:51 -07005871
Matus Fabian2f2db1c2017-04-18 05:29:59 -07005872 cls.create_pg_interfaces(range(3))
Matus Fabian066f0342017-02-10 03:48:01 -08005873 cls.interfaces = list(cls.pg_interfaces)
5874
5875 for i in cls.interfaces:
5876 i.admin_up()
5877 i.config_ip4()
5878 i.resolve_arp()
5879
Martin Gálik977c1cb2017-03-30 23:21:51 -07005880 cls.pg0.generate_remote_hosts(2)
5881 cls.pg0.configure_ipv4_neighbors()
5882
Matus Fabian066f0342017-02-10 03:48:01 -08005883 except Exception:
5884 super(TestDeterministicNAT, cls).tearDownClass()
5885 raise
5886
Martin Gálik977c1cb2017-03-30 23:21:51 -07005887 def create_stream_in(self, in_if, out_if, ttl=64):
5888 """
5889 Create packet stream for inside network
5890
5891 :param in_if: Inside interface
5892 :param out_if: Outside interface
5893 :param ttl: TTL of generated packets
5894 """
5895 pkts = []
5896 # TCP
5897 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
5898 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
Martin Gálik9806eae2017-04-25 01:25:08 -07005899 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07005900 pkts.append(p)
5901
5902 # UDP
5903 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
5904 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
Martin Gálik9806eae2017-04-25 01:25:08 -07005905 UDP(sport=self.udp_port_in, dport=self.udp_external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07005906 pkts.append(p)
5907
5908 # ICMP
5909 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
5910 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
5911 ICMP(id=self.icmp_id_in, type='echo-request'))
5912 pkts.append(p)
5913
5914 return pkts
5915
5916 def create_stream_out(self, out_if, dst_ip=None, ttl=64):
5917 """
5918 Create packet stream for outside network
5919
5920 :param out_if: Outside interface
Matus Fabian2ba92e32017-08-21 07:05:03 -07005921 :param dst_ip: Destination IP address (Default use global NAT address)
Martin Gálik977c1cb2017-03-30 23:21:51 -07005922 :param ttl: TTL of generated packets
5923 """
5924 if dst_ip is None:
Matus Fabian2ba92e32017-08-21 07:05:03 -07005925 dst_ip = self.nat_addr
Martin Gálik977c1cb2017-03-30 23:21:51 -07005926 pkts = []
5927 # TCP
5928 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
5929 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Martin Gálik9806eae2017-04-25 01:25:08 -07005930 TCP(dport=self.tcp_port_out, sport=self.tcp_external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07005931 pkts.append(p)
5932
5933 # UDP
5934 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
5935 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Martin Gálik9806eae2017-04-25 01:25:08 -07005936 UDP(dport=self.udp_port_out, sport=self.udp_external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07005937 pkts.append(p)
5938
5939 # ICMP
5940 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
5941 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
5942 ICMP(id=self.icmp_external_id, type='echo-reply'))
5943 pkts.append(p)
5944
5945 return pkts
5946
Matus Fabian05ca4a32018-09-04 23:45:13 -07005947 def verify_capture_out(self, capture, nat_ip=None):
Martin Gálik977c1cb2017-03-30 23:21:51 -07005948 """
5949 Verify captured packets on outside network
5950
5951 :param capture: Captured packets
Matus Fabian2ba92e32017-08-21 07:05:03 -07005952 :param nat_ip: Translated IP address (Default use global NAT address)
Martin Gálik977c1cb2017-03-30 23:21:51 -07005953 :param same_port: Sorce port number is not translated (Default False)
Martin Gálik977c1cb2017-03-30 23:21:51 -07005954 """
5955 if nat_ip is None:
Matus Fabian2ba92e32017-08-21 07:05:03 -07005956 nat_ip = self.nat_addr
Martin Gálik977c1cb2017-03-30 23:21:51 -07005957 for packet in capture:
5958 try:
5959 self.assertEqual(packet[IP].src, nat_ip)
5960 if packet.haslayer(TCP):
Martin Gálik9806eae2017-04-25 01:25:08 -07005961 self.tcp_port_out = packet[TCP].sport
Martin Gálik977c1cb2017-03-30 23:21:51 -07005962 elif packet.haslayer(UDP):
Martin Gálik9806eae2017-04-25 01:25:08 -07005963 self.udp_port_out = packet[UDP].sport
Martin Gálik977c1cb2017-03-30 23:21:51 -07005964 else:
5965 self.icmp_external_id = packet[ICMP].id
5966 except:
5967 self.logger.error(ppp("Unexpected or invalid packet "
5968 "(outside network):", packet))
5969 raise
5970
Matus Fabian066f0342017-02-10 03:48:01 -08005971 def test_deterministic_mode(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07005972 """ NAT plugin run deterministic mode """
Matus Fabian066f0342017-02-10 03:48:01 -08005973 in_addr = '172.16.255.0'
5974 out_addr = '172.17.255.50'
5975 in_addr_t = '172.16.255.20'
5976 in_addr_n = socket.inet_aton(in_addr)
5977 out_addr_n = socket.inet_aton(out_addr)
5978 in_addr_t_n = socket.inet_aton(in_addr_t)
5979 in_plen = 24
5980 out_plen = 32
5981
Matus Fabian2ba92e32017-08-21 07:05:03 -07005982 nat_config = self.vapi.nat_show_config()
5983 self.assertEqual(1, nat_config.deterministic)
Matus Fabian066f0342017-02-10 03:48:01 -08005984
Matus Fabian2ba92e32017-08-21 07:05:03 -07005985 self.vapi.nat_det_add_del_map(in_addr_n, in_plen, out_addr_n, out_plen)
Matus Fabian066f0342017-02-10 03:48:01 -08005986
Matus Fabian2ba92e32017-08-21 07:05:03 -07005987 rep1 = self.vapi.nat_det_forward(in_addr_t_n)
Matus Fabian066f0342017-02-10 03:48:01 -08005988 self.assertEqual(rep1.out_addr[:4], out_addr_n)
Matus Fabian2ba92e32017-08-21 07:05:03 -07005989 rep2 = self.vapi.nat_det_reverse(out_addr_n, rep1.out_port_hi)
Matus Fabian066f0342017-02-10 03:48:01 -08005990 self.assertEqual(rep2.in_addr[:4], in_addr_t_n)
5991
Matus Fabian2ba92e32017-08-21 07:05:03 -07005992 deterministic_mappings = self.vapi.nat_det_map_dump()
Martin17a75cb2017-03-08 05:53:20 -08005993 self.assertEqual(len(deterministic_mappings), 1)
5994 dsm = deterministic_mappings[0]
5995 self.assertEqual(in_addr_n, dsm.in_addr[:4])
5996 self.assertEqual(in_plen, dsm.in_plen)
5997 self.assertEqual(out_addr_n, dsm.out_addr[:4])
5998 self.assertEqual(out_plen, dsm.out_plen)
5999
Matus Fabian2ba92e32017-08-21 07:05:03 -07006000 self.clear_nat_det()
6001 deterministic_mappings = self.vapi.nat_det_map_dump()
Martinb616e9f2017-03-14 02:25:45 -07006002 self.assertEqual(len(deterministic_mappings), 0)
6003
Matus Fabian6a0946f2017-04-12 03:36:13 -07006004 def test_set_timeouts(self):
6005 """ Set deterministic NAT timeouts """
Matus Fabian878c6462018-08-23 00:33:35 -07006006 timeouts_before = self.vapi.nat_get_timeouts()
Matus Fabian6a0946f2017-04-12 03:36:13 -07006007
Matus Fabian878c6462018-08-23 00:33:35 -07006008 self.vapi.nat_set_timeouts(timeouts_before.udp + 10,
6009 timeouts_before.tcp_established + 10,
6010 timeouts_before.tcp_transitory + 10,
6011 timeouts_before.icmp + 10)
Matus Fabian6a0946f2017-04-12 03:36:13 -07006012
Matus Fabian878c6462018-08-23 00:33:35 -07006013 timeouts_after = self.vapi.nat_get_timeouts()
Matus Fabian6a0946f2017-04-12 03:36:13 -07006014
6015 self.assertNotEqual(timeouts_before.udp, timeouts_after.udp)
6016 self.assertNotEqual(timeouts_before.icmp, timeouts_after.icmp)
6017 self.assertNotEqual(timeouts_before.tcp_established,
6018 timeouts_after.tcp_established)
6019 self.assertNotEqual(timeouts_before.tcp_transitory,
6020 timeouts_after.tcp_transitory)
6021
Martin Gálik977c1cb2017-03-30 23:21:51 -07006022 def test_det_in(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07006023 """ Deterministic NAT translation test (TCP, UDP, ICMP) """
Martin Gálik977c1cb2017-03-30 23:21:51 -07006024
6025 nat_ip = "10.0.0.10"
Martin Gálik977c1cb2017-03-30 23:21:51 -07006026
Matus Fabian2ba92e32017-08-21 07:05:03 -07006027 self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
6028 32,
6029 socket.inet_aton(nat_ip),
6030 32)
6031 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
6032 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
6033 is_inside=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07006034
6035 # in2out
6036 pkts = self.create_stream_in(self.pg0, self.pg1)
6037 self.pg0.add_stream(pkts)
6038 self.pg_enable_capture(self.pg_interfaces)
6039 self.pg_start()
6040 capture = self.pg1.get_capture(len(pkts))
6041 self.verify_capture_out(capture, nat_ip)
6042
6043 # out2in
6044 pkts = self.create_stream_out(self.pg1, nat_ip)
6045 self.pg1.add_stream(pkts)
6046 self.pg_enable_capture(self.pg_interfaces)
6047 self.pg_start()
6048 capture = self.pg0.get_capture(len(pkts))
6049 self.verify_capture_in(capture, self.pg0)
6050
Martin Gálik9806eae2017-04-25 01:25:08 -07006051 # session dump test
Matus Fabian2ba92e32017-08-21 07:05:03 -07006052 sessions = self.vapi.nat_det_session_dump(self.pg0.remote_ip4n)
Martin Gálik9806eae2017-04-25 01:25:08 -07006053 self.assertEqual(len(sessions), 3)
6054
6055 # TCP session
6056 s = sessions[0]
6057 self.assertEqual(s.ext_addr[:4], self.pg1.remote_ip4n)
6058 self.assertEqual(s.in_port, self.tcp_port_in)
6059 self.assertEqual(s.out_port, self.tcp_port_out)
6060 self.assertEqual(s.ext_port, self.tcp_external_port)
6061
6062 # UDP session
6063 s = sessions[1]
6064 self.assertEqual(s.ext_addr[:4], self.pg1.remote_ip4n)
6065 self.assertEqual(s.in_port, self.udp_port_in)
6066 self.assertEqual(s.out_port, self.udp_port_out)
6067 self.assertEqual(s.ext_port, self.udp_external_port)
6068
6069 # ICMP session
6070 s = sessions[2]
6071 self.assertEqual(s.ext_addr[:4], self.pg1.remote_ip4n)
6072 self.assertEqual(s.in_port, self.icmp_id_in)
6073 self.assertEqual(s.out_port, self.icmp_external_id)
6074
Martin Gálik977c1cb2017-03-30 23:21:51 -07006075 def test_multiple_users(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07006076 """ Deterministic NAT multiple users """
Martin Gálik977c1cb2017-03-30 23:21:51 -07006077
6078 nat_ip = "10.0.0.10"
6079 port_in = 80
Martin Gálik9806eae2017-04-25 01:25:08 -07006080 external_port = 6303
Martin Gálik977c1cb2017-03-30 23:21:51 -07006081
6082 host0 = self.pg0.remote_hosts[0]
6083 host1 = self.pg0.remote_hosts[1]
6084
Matus Fabian2ba92e32017-08-21 07:05:03 -07006085 self.vapi.nat_det_add_del_map(host0.ip4n,
6086 24,
6087 socket.inet_aton(nat_ip),
6088 32)
6089 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
6090 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
6091 is_inside=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07006092
6093 # host0 to out
6094 p = (Ether(src=host0.mac, dst=self.pg0.local_mac) /
6095 IP(src=host0.ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006096 TCP(sport=port_in, dport=external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07006097 self.pg0.add_stream(p)
6098 self.pg_enable_capture(self.pg_interfaces)
6099 self.pg_start()
6100 capture = self.pg1.get_capture(1)
6101 p = capture[0]
6102 try:
6103 ip = p[IP]
6104 tcp = p[TCP]
6105 self.assertEqual(ip.src, nat_ip)
6106 self.assertEqual(ip.dst, self.pg1.remote_ip4)
Martin Gálik9806eae2017-04-25 01:25:08 -07006107 self.assertEqual(tcp.dport, external_port)
6108 port_out0 = tcp.sport
Martin Gálik977c1cb2017-03-30 23:21:51 -07006109 except:
6110 self.logger.error(ppp("Unexpected or invalid packet:", p))
6111 raise
6112
6113 # host1 to out
6114 p = (Ether(src=host1.mac, dst=self.pg0.local_mac) /
6115 IP(src=host1.ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006116 TCP(sport=port_in, dport=external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07006117 self.pg0.add_stream(p)
6118 self.pg_enable_capture(self.pg_interfaces)
6119 self.pg_start()
6120 capture = self.pg1.get_capture(1)
6121 p = capture[0]
6122 try:
6123 ip = p[IP]
6124 tcp = p[TCP]
6125 self.assertEqual(ip.src, nat_ip)
6126 self.assertEqual(ip.dst, self.pg1.remote_ip4)
Martin Gálik9806eae2017-04-25 01:25:08 -07006127 self.assertEqual(tcp.dport, external_port)
6128 port_out1 = tcp.sport
Martin Gálik977c1cb2017-03-30 23:21:51 -07006129 except:
6130 self.logger.error(ppp("Unexpected or invalid packet:", p))
6131 raise
6132
Matus Fabian2ba92e32017-08-21 07:05:03 -07006133 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07006134 self.assertEqual(1, len(dms))
6135 self.assertEqual(2, dms[0].ses_num)
6136
6137 # out to host0
6138 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6139 IP(src=self.pg1.remote_ip4, dst=nat_ip) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006140 TCP(sport=external_port, dport=port_out0))
Martin Gálik977c1cb2017-03-30 23:21:51 -07006141 self.pg1.add_stream(p)
6142 self.pg_enable_capture(self.pg_interfaces)
6143 self.pg_start()
6144 capture = self.pg0.get_capture(1)
6145 p = capture[0]
6146 try:
6147 ip = p[IP]
6148 tcp = p[TCP]
6149 self.assertEqual(ip.src, self.pg1.remote_ip4)
6150 self.assertEqual(ip.dst, host0.ip4)
6151 self.assertEqual(tcp.dport, port_in)
Martin Gálik9806eae2017-04-25 01:25:08 -07006152 self.assertEqual(tcp.sport, external_port)
Martin Gálik977c1cb2017-03-30 23:21:51 -07006153 except:
6154 self.logger.error(ppp("Unexpected or invalid packet:", p))
6155 raise
6156
6157 # out to host1
6158 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6159 IP(src=self.pg1.remote_ip4, dst=nat_ip) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006160 TCP(sport=external_port, dport=port_out1))
Martin Gálik977c1cb2017-03-30 23:21:51 -07006161 self.pg1.add_stream(p)
6162 self.pg_enable_capture(self.pg_interfaces)
6163 self.pg_start()
6164 capture = self.pg0.get_capture(1)
6165 p = capture[0]
6166 try:
6167 ip = p[IP]
6168 tcp = p[TCP]
6169 self.assertEqual(ip.src, self.pg1.remote_ip4)
6170 self.assertEqual(ip.dst, host1.ip4)
6171 self.assertEqual(tcp.dport, port_in)
Martin Gálik9806eae2017-04-25 01:25:08 -07006172 self.assertEqual(tcp.sport, external_port)
Martin Gálik977c1cb2017-03-30 23:21:51 -07006173 except:
6174 self.logger.error(ppp("Unexpected or invalid packet", p))
6175 raise
6176
Martin Gálik6bc8c642017-04-19 01:12:27 -07006177 # session close api test
Matus Fabian2ba92e32017-08-21 07:05:03 -07006178 self.vapi.nat_det_close_session_out(socket.inet_aton(nat_ip),
6179 port_out1,
Martin Gálik6bc8c642017-04-19 01:12:27 -07006180 self.pg1.remote_ip4n,
Martin Gálik9806eae2017-04-25 01:25:08 -07006181 external_port)
Matus Fabian2ba92e32017-08-21 07:05:03 -07006182 dms = self.vapi.nat_det_map_dump()
6183 self.assertEqual(dms[0].ses_num, 1)
6184
6185 self.vapi.nat_det_close_session_in(host0.ip4n,
6186 port_in,
6187 self.pg1.remote_ip4n,
6188 external_port)
6189 dms = self.vapi.nat_det_map_dump()
Martin Gálik6bc8c642017-04-19 01:12:27 -07006190 self.assertEqual(dms[0].ses_num, 0)
6191
Martin Gálik977c1cb2017-03-30 23:21:51 -07006192 def test_tcp_session_close_detection_in(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07006193 """ Deterministic NAT TCP session close from inside network """
6194 self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
6195 32,
6196 socket.inet_aton(self.nat_addr),
6197 32)
6198 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
6199 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
6200 is_inside=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07006201
6202 self.initiate_tcp_session(self.pg0, self.pg1)
6203
6204 # close the session from inside
6205 try:
6206 # FIN packet in -> out
6207 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6208 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006209 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
Martin Gálik977c1cb2017-03-30 23:21:51 -07006210 flags="F"))
6211 self.pg0.add_stream(p)
6212 self.pg_enable_capture(self.pg_interfaces)
6213 self.pg_start()
6214 self.pg1.get_capture(1)
6215
6216 pkts = []
6217
6218 # ACK packet out -> in
6219 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07006220 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006221 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
Martin Gálik977c1cb2017-03-30 23:21:51 -07006222 flags="A"))
6223 pkts.append(p)
6224
6225 # FIN packet out -> in
6226 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07006227 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006228 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
Martin Gálik977c1cb2017-03-30 23:21:51 -07006229 flags="F"))
6230 pkts.append(p)
6231
6232 self.pg1.add_stream(pkts)
6233 self.pg_enable_capture(self.pg_interfaces)
6234 self.pg_start()
6235 self.pg0.get_capture(2)
6236
6237 # ACK packet in -> out
6238 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6239 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006240 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
Martin Gálik977c1cb2017-03-30 23:21:51 -07006241 flags="A"))
6242 self.pg0.add_stream(p)
6243 self.pg_enable_capture(self.pg_interfaces)
6244 self.pg_start()
6245 self.pg1.get_capture(1)
6246
Matus Fabian2ba92e32017-08-21 07:05:03 -07006247 # Check if deterministic NAT44 closed the session
6248 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07006249 self.assertEqual(0, dms[0].ses_num)
6250 except:
6251 self.logger.error("TCP session termination failed")
6252 raise
6253
6254 def test_tcp_session_close_detection_out(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07006255 """ Deterministic NAT TCP session close from outside network """
6256 self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
6257 32,
6258 socket.inet_aton(self.nat_addr),
6259 32)
6260 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
6261 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
6262 is_inside=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07006263
6264 self.initiate_tcp_session(self.pg0, self.pg1)
6265
6266 # close the session from outside
6267 try:
6268 # FIN packet out -> in
6269 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07006270 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006271 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
Martin Gálik977c1cb2017-03-30 23:21:51 -07006272 flags="F"))
6273 self.pg1.add_stream(p)
6274 self.pg_enable_capture(self.pg_interfaces)
6275 self.pg_start()
6276 self.pg0.get_capture(1)
6277
6278 pkts = []
6279
6280 # ACK packet in -> out
6281 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6282 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006283 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
Martin Gálik977c1cb2017-03-30 23:21:51 -07006284 flags="A"))
6285 pkts.append(p)
6286
6287 # ACK packet in -> out
6288 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6289 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006290 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
Martin Gálik977c1cb2017-03-30 23:21:51 -07006291 flags="F"))
6292 pkts.append(p)
6293
6294 self.pg0.add_stream(pkts)
6295 self.pg_enable_capture(self.pg_interfaces)
6296 self.pg_start()
6297 self.pg1.get_capture(2)
6298
6299 # ACK packet out -> in
6300 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07006301 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006302 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
Martin Gálik977c1cb2017-03-30 23:21:51 -07006303 flags="A"))
6304 self.pg1.add_stream(p)
6305 self.pg_enable_capture(self.pg_interfaces)
6306 self.pg_start()
6307 self.pg0.get_capture(1)
6308
Matus Fabian2ba92e32017-08-21 07:05:03 -07006309 # Check if deterministic NAT44 closed the session
6310 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07006311 self.assertEqual(0, dms[0].ses_num)
6312 except:
6313 self.logger.error("TCP session termination failed")
6314 raise
6315
6316 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
6317 def test_session_timeout(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07006318 """ Deterministic NAT session timeouts """
6319 self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
6320 32,
6321 socket.inet_aton(self.nat_addr),
6322 32)
6323 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
6324 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
6325 is_inside=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07006326
6327 self.initiate_tcp_session(self.pg0, self.pg1)
Matus Fabian878c6462018-08-23 00:33:35 -07006328 self.vapi.nat_set_timeouts(5, 5, 5, 5)
Martin Gálik977c1cb2017-03-30 23:21:51 -07006329 pkts = self.create_stream_in(self.pg0, self.pg1)
6330 self.pg0.add_stream(pkts)
6331 self.pg_enable_capture(self.pg_interfaces)
6332 self.pg_start()
6333 capture = self.pg1.get_capture(len(pkts))
6334 sleep(15)
6335
Matus Fabian2ba92e32017-08-21 07:05:03 -07006336 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07006337 self.assertEqual(0, dms[0].ses_num)
6338
Matus Fabian7c0aecc2017-07-03 01:21:38 -07006339 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
Martin Gálik977c1cb2017-03-30 23:21:51 -07006340 def test_session_limit_per_user(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07006341 """ Deterministic NAT maximum sessions per user limit """
6342 self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
6343 32,
6344 socket.inet_aton(self.nat_addr),
6345 32)
6346 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
6347 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
6348 is_inside=0)
Matus Fabian2f2db1c2017-04-18 05:29:59 -07006349 self.vapi.set_ipfix_exporter(collector_address=self.pg2.remote_ip4n,
6350 src_address=self.pg2.local_ip4n,
6351 path_mtu=512,
6352 template_interval=10)
Matus Fabian2ba92e32017-08-21 07:05:03 -07006353 self.vapi.nat_ipfix()
Martin Gálik977c1cb2017-03-30 23:21:51 -07006354
6355 pkts = []
6356 for port in range(1025, 2025):
6357 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6358 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6359 UDP(sport=port, dport=port))
6360 pkts.append(p)
6361
6362 self.pg0.add_stream(pkts)
6363 self.pg_enable_capture(self.pg_interfaces)
6364 self.pg_start()
6365 capture = self.pg1.get_capture(len(pkts))
6366
6367 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6368 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálikf7e655d2017-04-27 02:13:26 -07006369 UDP(sport=3001, dport=3002))
Martin Gálik977c1cb2017-03-30 23:21:51 -07006370 self.pg0.add_stream(p)
6371 self.pg_enable_capture(self.pg_interfaces)
6372 self.pg_start()
6373 capture = self.pg1.assert_nothing_captured()
6374
Martin Gálikf7e655d2017-04-27 02:13:26 -07006375 # verify ICMP error packet
6376 capture = self.pg0.get_capture(1)
6377 p = capture[0]
6378 self.assertTrue(p.haslayer(ICMP))
6379 icmp = p[ICMP]
6380 self.assertEqual(icmp.type, 3)
6381 self.assertEqual(icmp.code, 1)
6382 self.assertTrue(icmp.haslayer(IPerror))
6383 inner_ip = icmp[IPerror]
6384 self.assertEqual(inner_ip[UDPerror].sport, 3001)
6385 self.assertEqual(inner_ip[UDPerror].dport, 3002)
6386
Matus Fabian2ba92e32017-08-21 07:05:03 -07006387 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07006388
6389 self.assertEqual(1000, dms[0].ses_num)
6390
Matus Fabian2f2db1c2017-04-18 05:29:59 -07006391 # verify IPFIX logging
6392 self.vapi.cli("ipfix flush") # FIXME this should be an API call
Matus Fabian7c0aecc2017-07-03 01:21:38 -07006393 sleep(1)
Matus Fabian2f2db1c2017-04-18 05:29:59 -07006394 capture = self.pg2.get_capture(2)
6395 ipfix = IPFIXDecoder()
6396 # first load template
6397 for p in capture:
6398 self.assertTrue(p.haslayer(IPFIX))
6399 if p.haslayer(Template):
6400 ipfix.add_template(p.getlayer(Template))
6401 # verify events in data set
6402 for p in capture:
6403 if p.haslayer(Data):
6404 data = ipfix.decode_data_set(p.getlayer(Set))
Matus Fabian878c6462018-08-23 00:33:35 -07006405 self.verify_ipfix_max_entries_per_user(data,
6406 1000,
6407 self.pg0.remote_ip4n)
Matus Fabian2f2db1c2017-04-18 05:29:59 -07006408
Matus Fabian2ba92e32017-08-21 07:05:03 -07006409 def clear_nat_det(self):
Martin17a75cb2017-03-08 05:53:20 -08006410 """
Matus Fabian2ba92e32017-08-21 07:05:03 -07006411 Clear deterministic NAT configuration.
Martin17a75cb2017-03-08 05:53:20 -08006412 """
Matus Fabian2ba92e32017-08-21 07:05:03 -07006413 self.vapi.nat_ipfix(enable=0)
Matus Fabian878c6462018-08-23 00:33:35 -07006414 self.vapi.nat_set_timeouts()
Matus Fabian2ba92e32017-08-21 07:05:03 -07006415 deterministic_mappings = self.vapi.nat_det_map_dump()
Martin17a75cb2017-03-08 05:53:20 -08006416 for dsm in deterministic_mappings:
Matus Fabian2ba92e32017-08-21 07:05:03 -07006417 self.vapi.nat_det_add_del_map(dsm.in_addr,
6418 dsm.in_plen,
6419 dsm.out_addr,
6420 dsm.out_plen,
6421 is_add=0)
Martin17a75cb2017-03-08 05:53:20 -08006422
Matus Fabian2ba92e32017-08-21 07:05:03 -07006423 interfaces = self.vapi.nat44_interface_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07006424 for intf in interfaces:
Matus Fabian2ba92e32017-08-21 07:05:03 -07006425 self.vapi.nat44_interface_add_del_feature(intf.sw_if_index,
6426 intf.is_inside,
6427 is_add=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07006428
Matus Fabian066f0342017-02-10 03:48:01 -08006429 def tearDown(self):
6430 super(TestDeterministicNAT, self).tearDown()
6431 if not self.vpp_dead:
Matus Fabian82119542018-01-25 01:13:22 -08006432 self.logger.info(self.vapi.cli("show nat44 interfaces"))
Matus Fabian878c6462018-08-23 00:33:35 -07006433 self.logger.info(self.vapi.cli("show nat timeouts"))
Matus Fabian82119542018-01-25 01:13:22 -08006434 self.logger.info(
6435 self.vapi.cli("show nat44 deterministic mappings"))
6436 self.logger.info(
Matus Fabian82119542018-01-25 01:13:22 -08006437 self.vapi.cli("show nat44 deterministic sessions"))
Matus Fabian2ba92e32017-08-21 07:05:03 -07006438 self.clear_nat_det()
Matus Fabian066f0342017-02-10 03:48:01 -08006439
Matus Fabian06596c52017-06-06 04:53:28 -07006440
6441class TestNAT64(MethodHolder):
6442 """ NAT64 Test Cases """
6443
6444 @classmethod
Matus Fabiana431ad12018-01-04 04:03:14 -08006445 def setUpConstants(cls):
6446 super(TestNAT64, cls).setUpConstants()
6447 cls.vpp_cmdline.extend(["nat", "{", "nat64 bib hash buckets 128",
6448 "nat64 st hash buckets 256", "}"])
6449
6450 @classmethod
Matus Fabian06596c52017-06-06 04:53:28 -07006451 def setUpClass(cls):
6452 super(TestNAT64, cls).setUpClass()
6453
6454 try:
6455 cls.tcp_port_in = 6303
6456 cls.tcp_port_out = 6303
6457 cls.udp_port_in = 6304
6458 cls.udp_port_out = 6304
6459 cls.icmp_id_in = 6305
6460 cls.icmp_id_out = 6305
6461 cls.nat_addr = '10.0.0.3'
6462 cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
Matus Fabian029f3d22017-06-15 02:28:50 -07006463 cls.vrf1_id = 10
6464 cls.vrf1_nat_addr = '10.0.10.3'
6465 cls.vrf1_nat_addr_n = socket.inet_pton(socket.AF_INET,
6466 cls.vrf1_nat_addr)
Matus Fabiana431ad12018-01-04 04:03:14 -08006467 cls.ipfix_src_port = 4739
6468 cls.ipfix_domain_id = 1
Matus Fabian06596c52017-06-06 04:53:28 -07006469
Juraj Slobodac746a152018-07-09 02:36:37 +02006470 cls.create_pg_interfaces(range(6))
Matus Fabian06596c52017-06-06 04:53:28 -07006471 cls.ip6_interfaces = list(cls.pg_interfaces[0:1])
Matus Fabian029f3d22017-06-15 02:28:50 -07006472 cls.ip6_interfaces.append(cls.pg_interfaces[2])
Matus Fabian06596c52017-06-06 04:53:28 -07006473 cls.ip4_interfaces = list(cls.pg_interfaces[1:2])
6474
Neale Ranns15002542017-09-10 04:39:11 -07006475 cls.vapi.ip_table_add_del(cls.vrf1_id, is_add=1, is_ipv6=1)
6476
Matus Fabian029f3d22017-06-15 02:28:50 -07006477 cls.pg_interfaces[2].set_table_ip6(cls.vrf1_id)
6478
6479 cls.pg0.generate_remote_hosts(2)
6480
Matus Fabian06596c52017-06-06 04:53:28 -07006481 for i in cls.ip6_interfaces:
6482 i.admin_up()
6483 i.config_ip6()
Matus Fabian029f3d22017-06-15 02:28:50 -07006484 i.configure_ipv6_neighbors()
Matus Fabian06596c52017-06-06 04:53:28 -07006485
6486 for i in cls.ip4_interfaces:
6487 i.admin_up()
6488 i.config_ip4()
6489 i.resolve_arp()
6490
Matus Fabian36ea2d62017-10-24 04:13:49 -07006491 cls.pg3.admin_up()
6492 cls.pg3.config_ip4()
6493 cls.pg3.resolve_arp()
6494 cls.pg3.config_ip6()
6495 cls.pg3.configure_ipv6_neighbors()
6496
Juraj Slobodac746a152018-07-09 02:36:37 +02006497 cls.pg5.admin_up()
6498 cls.pg5.config_ip6()
6499
Matus Fabian06596c52017-06-06 04:53:28 -07006500 except Exception:
6501 super(TestNAT64, cls).tearDownClass()
6502 raise
6503
Juraj Slobodac746a152018-07-09 02:36:37 +02006504 def test_nat64_inside_interface_handles_neighbor_advertisement(self):
6505 """ NAT64 inside interface handles Neighbor Advertisement """
6506
6507 self.vapi.nat64_add_del_interface(self.pg5.sw_if_index)
6508
6509 # Try to send ping
6510 ping = (Ether(dst=self.pg5.local_mac, src=self.pg5.remote_mac) /
6511 IPv6(src=self.pg5.remote_ip6, dst=self.pg5.local_ip6) /
6512 ICMPv6EchoRequest())
6513 pkts = [ping]
6514 self.pg5.add_stream(pkts)
6515 self.pg_enable_capture(self.pg_interfaces)
6516 self.pg_start()
6517
6518 # Wait for Neighbor Solicitation
6519 capture = self.pg5.get_capture(len(pkts))
Juraj Slobodac746a152018-07-09 02:36:37 +02006520 packet = capture[0]
6521 try:
6522 self.assertEqual(packet[IPv6].src, self.pg5.local_ip6)
6523 self.assertTrue(packet.haslayer(ICMPv6ND_NS))
6524 tgt = packet[ICMPv6ND_NS].tgt
6525 except:
6526 self.logger.error(ppp("Unexpected or invalid packet:", packet))
6527 raise
6528
6529 # Send Neighbor Advertisement
6530 p = (Ether(dst=self.pg5.local_mac, src=self.pg5.remote_mac) /
6531 IPv6(src=self.pg5.remote_ip6, dst=self.pg5.local_ip6) /
6532 ICMPv6ND_NA(tgt=tgt) /
6533 ICMPv6NDOptDstLLAddr(lladdr=self.pg5.remote_mac))
6534 pkts = [p]
6535 self.pg5.add_stream(pkts)
6536 self.pg_enable_capture(self.pg_interfaces)
6537 self.pg_start()
6538
6539 # Try to send ping again
6540 pkts = [ping]
6541 self.pg5.add_stream(pkts)
6542 self.pg_enable_capture(self.pg_interfaces)
6543 self.pg_start()
6544
6545 # Wait for ping reply
6546 capture = self.pg5.get_capture(len(pkts))
Juraj Slobodac746a152018-07-09 02:36:37 +02006547 packet = capture[0]
6548 try:
6549 self.assertEqual(packet[IPv6].src, self.pg5.local_ip6)
6550 self.assertEqual(packet[IPv6].dst, self.pg5.remote_ip6)
6551 self.assertTrue(packet.haslayer(ICMPv6EchoReply))
6552 except:
6553 self.logger.error(ppp("Unexpected or invalid packet:", packet))
6554 raise
6555
Matus Fabian06596c52017-06-06 04:53:28 -07006556 def test_pool(self):
6557 """ Add/delete address to NAT64 pool """
6558 nat_addr = socket.inet_pton(socket.AF_INET, '1.2.3.4')
6559
6560 self.vapi.nat64_add_del_pool_addr_range(nat_addr, nat_addr)
6561
6562 addresses = self.vapi.nat64_pool_addr_dump()
6563 self.assertEqual(len(addresses), 1)
6564 self.assertEqual(addresses[0].address, nat_addr)
6565
6566 self.vapi.nat64_add_del_pool_addr_range(nat_addr, nat_addr, is_add=0)
6567
6568 addresses = self.vapi.nat64_pool_addr_dump()
6569 self.assertEqual(len(addresses), 0)
6570
6571 def test_interface(self):
6572 """ Enable/disable NAT64 feature on the interface """
6573 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6574 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6575
6576 interfaces = self.vapi.nat64_interface_dump()
6577 self.assertEqual(len(interfaces), 2)
6578 pg0_found = False
6579 pg1_found = False
6580 for intf in interfaces:
6581 if intf.sw_if_index == self.pg0.sw_if_index:
6582 self.assertEqual(intf.is_inside, 1)
6583 pg0_found = True
6584 elif intf.sw_if_index == self.pg1.sw_if_index:
6585 self.assertEqual(intf.is_inside, 0)
6586 pg1_found = True
6587 self.assertTrue(pg0_found)
6588 self.assertTrue(pg1_found)
6589
6590 features = self.vapi.cli("show interface features pg0")
6591 self.assertNotEqual(features.find('nat64-in2out'), -1)
6592 features = self.vapi.cli("show interface features pg1")
6593 self.assertNotEqual(features.find('nat64-out2in'), -1)
6594
6595 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index, is_add=0)
6596 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_add=0)
6597
6598 interfaces = self.vapi.nat64_interface_dump()
6599 self.assertEqual(len(interfaces), 0)
6600
6601 def test_static_bib(self):
6602 """ Add/delete static BIB entry """
6603 in_addr = socket.inet_pton(socket.AF_INET6,
6604 '2001:db8:85a3::8a2e:370:7334')
6605 out_addr = socket.inet_pton(socket.AF_INET, '10.1.1.3')
6606 in_port = 1234
6607 out_port = 5678
6608 proto = IP_PROTOS.tcp
6609
6610 self.vapi.nat64_add_del_static_bib(in_addr,
6611 out_addr,
6612 in_port,
6613 out_port,
6614 proto)
6615 bib = self.vapi.nat64_bib_dump(IP_PROTOS.tcp)
6616 static_bib_num = 0
6617 for bibe in bib:
6618 if bibe.is_static:
6619 static_bib_num += 1
6620 self.assertEqual(bibe.i_addr, in_addr)
6621 self.assertEqual(bibe.o_addr, out_addr)
6622 self.assertEqual(bibe.i_port, in_port)
6623 self.assertEqual(bibe.o_port, out_port)
6624 self.assertEqual(static_bib_num, 1)
6625
6626 self.vapi.nat64_add_del_static_bib(in_addr,
6627 out_addr,
6628 in_port,
6629 out_port,
6630 proto,
6631 is_add=0)
6632 bib = self.vapi.nat64_bib_dump(IP_PROTOS.tcp)
6633 static_bib_num = 0
6634 for bibe in bib:
6635 if bibe.is_static:
6636 static_bib_num += 1
6637 self.assertEqual(static_bib_num, 0)
6638
6639 def test_set_timeouts(self):
6640 """ Set NAT64 timeouts """
6641 # verify default values
Matus Fabian878c6462018-08-23 00:33:35 -07006642 timeouts = self.vapi.nat_get_timeouts()
Matus Fabian06596c52017-06-06 04:53:28 -07006643 self.assertEqual(timeouts.udp, 300)
6644 self.assertEqual(timeouts.icmp, 60)
Matus Fabian878c6462018-08-23 00:33:35 -07006645 self.assertEqual(timeouts.tcp_transitory, 240)
6646 self.assertEqual(timeouts.tcp_established, 7440)
Matus Fabian06596c52017-06-06 04:53:28 -07006647
6648 # set and verify custom values
Matus Fabian878c6462018-08-23 00:33:35 -07006649 self.vapi.nat_set_timeouts(udp=200, icmp=30, tcp_transitory=250,
6650 tcp_established=7450)
6651 timeouts = self.vapi.nat_get_timeouts()
Matus Fabian06596c52017-06-06 04:53:28 -07006652 self.assertEqual(timeouts.udp, 200)
6653 self.assertEqual(timeouts.icmp, 30)
Matus Fabian878c6462018-08-23 00:33:35 -07006654 self.assertEqual(timeouts.tcp_transitory, 250)
6655 self.assertEqual(timeouts.tcp_established, 7450)
Matus Fabian06596c52017-06-06 04:53:28 -07006656
6657 def test_dynamic(self):
6658 """ NAT64 dynamic translation test """
6659 self.tcp_port_in = 6303
6660 self.udp_port_in = 6304
6661 self.icmp_id_in = 6305
6662
6663 ses_num_start = self.nat64_get_ses_num()
6664
6665 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6666 self.nat_addr_n)
6667 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6668 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6669
6670 # in2out
6671 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
6672 self.pg0.add_stream(pkts)
6673 self.pg_enable_capture(self.pg_interfaces)
6674 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07006675 capture = self.pg1.get_capture(len(pkts))
6676 self.verify_capture_out(capture, nat_ip=self.nat_addr,
Matus Fabian06596c52017-06-06 04:53:28 -07006677 dst_ip=self.pg1.remote_ip4)
6678
6679 # out2in
6680 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
6681 self.pg1.add_stream(pkts)
6682 self.pg_enable_capture(self.pg_interfaces)
6683 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07006684 capture = self.pg0.get_capture(len(pkts))
Matus Fabian06596c52017-06-06 04:53:28 -07006685 ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
6686 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
6687
6688 # in2out
6689 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
6690 self.pg0.add_stream(pkts)
6691 self.pg_enable_capture(self.pg_interfaces)
6692 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07006693 capture = self.pg1.get_capture(len(pkts))
6694 self.verify_capture_out(capture, nat_ip=self.nat_addr,
Matus Fabian06596c52017-06-06 04:53:28 -07006695 dst_ip=self.pg1.remote_ip4)
6696
6697 # out2in
6698 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
6699 self.pg1.add_stream(pkts)
6700 self.pg_enable_capture(self.pg_interfaces)
6701 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07006702 capture = self.pg0.get_capture(len(pkts))
Matus Fabian06596c52017-06-06 04:53:28 -07006703 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
6704
6705 ses_num_end = self.nat64_get_ses_num()
6706
6707 self.assertEqual(ses_num_end - ses_num_start, 3)
6708
Matus Fabian029f3d22017-06-15 02:28:50 -07006709 # tenant with specific VRF
6710 self.vapi.nat64_add_del_pool_addr_range(self.vrf1_nat_addr_n,
6711 self.vrf1_nat_addr_n,
6712 vrf_id=self.vrf1_id)
6713 self.vapi.nat64_add_del_interface(self.pg2.sw_if_index)
6714
6715 pkts = self.create_stream_in_ip6(self.pg2, self.pg1)
6716 self.pg2.add_stream(pkts)
6717 self.pg_enable_capture(self.pg_interfaces)
6718 self.pg_start()
6719 capture = self.pg1.get_capture(len(pkts))
6720 self.verify_capture_out(capture, nat_ip=self.vrf1_nat_addr,
6721 dst_ip=self.pg1.remote_ip4)
6722
6723 pkts = self.create_stream_out(self.pg1, dst_ip=self.vrf1_nat_addr)
6724 self.pg1.add_stream(pkts)
6725 self.pg_enable_capture(self.pg_interfaces)
6726 self.pg_start()
6727 capture = self.pg2.get_capture(len(pkts))
6728 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg2.remote_ip6)
6729
Matus Fabian06596c52017-06-06 04:53:28 -07006730 def test_static(self):
6731 """ NAT64 static translation test """
6732 self.tcp_port_in = 60303
6733 self.udp_port_in = 60304
6734 self.icmp_id_in = 60305
6735 self.tcp_port_out = 60303
6736 self.udp_port_out = 60304
6737 self.icmp_id_out = 60305
6738
6739 ses_num_start = self.nat64_get_ses_num()
6740
6741 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6742 self.nat_addr_n)
6743 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6744 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6745
6746 self.vapi.nat64_add_del_static_bib(self.pg0.remote_ip6n,
6747 self.nat_addr_n,
6748 self.tcp_port_in,
6749 self.tcp_port_out,
6750 IP_PROTOS.tcp)
6751 self.vapi.nat64_add_del_static_bib(self.pg0.remote_ip6n,
6752 self.nat_addr_n,
6753 self.udp_port_in,
6754 self.udp_port_out,
6755 IP_PROTOS.udp)
6756 self.vapi.nat64_add_del_static_bib(self.pg0.remote_ip6n,
6757 self.nat_addr_n,
6758 self.icmp_id_in,
6759 self.icmp_id_out,
6760 IP_PROTOS.icmp)
6761
6762 # in2out
6763 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
6764 self.pg0.add_stream(pkts)
6765 self.pg_enable_capture(self.pg_interfaces)
6766 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07006767 capture = self.pg1.get_capture(len(pkts))
6768 self.verify_capture_out(capture, nat_ip=self.nat_addr,
Matus Fabian06596c52017-06-06 04:53:28 -07006769 dst_ip=self.pg1.remote_ip4, same_port=True)
6770
6771 # out2in
6772 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
6773 self.pg1.add_stream(pkts)
6774 self.pg_enable_capture(self.pg_interfaces)
6775 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07006776 capture = self.pg0.get_capture(len(pkts))
Matus Fabian06596c52017-06-06 04:53:28 -07006777 ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
6778 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
6779
6780 ses_num_end = self.nat64_get_ses_num()
6781
6782 self.assertEqual(ses_num_end - ses_num_start, 3)
6783
6784 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
6785 def test_session_timeout(self):
6786 """ NAT64 session timeout """
6787 self.icmp_id_in = 1234
6788 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6789 self.nat_addr_n)
6790 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6791 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
Matus Fabian878c6462018-08-23 00:33:35 -07006792 self.vapi.nat_set_timeouts(icmp=5, tcp_transitory=5, tcp_established=5)
Matus Fabian06596c52017-06-06 04:53:28 -07006793
6794 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
6795 self.pg0.add_stream(pkts)
6796 self.pg_enable_capture(self.pg_interfaces)
6797 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07006798 capture = self.pg1.get_capture(len(pkts))
Matus Fabian06596c52017-06-06 04:53:28 -07006799
6800 ses_num_before_timeout = self.nat64_get_ses_num()
6801
6802 sleep(15)
6803
Matus Fabian8fed4242018-08-14 05:14:55 -07006804 # ICMP and TCP session after timeout
Matus Fabian06596c52017-06-06 04:53:28 -07006805 ses_num_after_timeout = self.nat64_get_ses_num()
Matus Fabian8fed4242018-08-14 05:14:55 -07006806 self.assertEqual(ses_num_before_timeout - ses_num_after_timeout, 2)
Matus Fabian06596c52017-06-06 04:53:28 -07006807
Matus Fabian732036d2017-06-08 05:24:28 -07006808 def test_icmp_error(self):
6809 """ NAT64 ICMP Error message translation """
6810 self.tcp_port_in = 6303
6811 self.udp_port_in = 6304
6812 self.icmp_id_in = 6305
6813
Matus Fabian732036d2017-06-08 05:24:28 -07006814 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6815 self.nat_addr_n)
6816 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6817 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6818
6819 # send some packets to create sessions
6820 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
6821 self.pg0.add_stream(pkts)
6822 self.pg_enable_capture(self.pg_interfaces)
6823 self.pg_start()
6824 capture_ip4 = self.pg1.get_capture(len(pkts))
Matus Fabian029f3d22017-06-15 02:28:50 -07006825 self.verify_capture_out(capture_ip4,
Matus Fabian732036d2017-06-08 05:24:28 -07006826 nat_ip=self.nat_addr,
6827 dst_ip=self.pg1.remote_ip4)
6828
6829 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
6830 self.pg1.add_stream(pkts)
6831 self.pg_enable_capture(self.pg_interfaces)
6832 self.pg_start()
6833 capture_ip6 = self.pg0.get_capture(len(pkts))
6834 ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
6835 self.verify_capture_in_ip6(capture_ip6, ip[IPv6].src,
6836 self.pg0.remote_ip6)
6837
6838 # in2out
6839 pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6840 IPv6(src=self.pg0.remote_ip6, dst=ip[IPv6].src) /
6841 ICMPv6DestUnreach(code=1) /
6842 packet[IPv6] for packet in capture_ip6]
6843 self.pg0.add_stream(pkts)
6844 self.pg_enable_capture(self.pg_interfaces)
6845 self.pg_start()
6846 capture = self.pg1.get_capture(len(pkts))
6847 for packet in capture:
6848 try:
6849 self.assertEqual(packet[IP].src, self.nat_addr)
6850 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
6851 self.assertEqual(packet[ICMP].type, 3)
6852 self.assertEqual(packet[ICMP].code, 13)
6853 inner = packet[IPerror]
6854 self.assertEqual(inner.src, self.pg1.remote_ip4)
6855 self.assertEqual(inner.dst, self.nat_addr)
Klement Sekerad81ae412018-05-16 10:52:54 +02006856 self.assert_packet_checksums_valid(packet)
Matus Fabian732036d2017-06-08 05:24:28 -07006857 if inner.haslayer(TCPerror):
6858 self.assertEqual(inner[TCPerror].dport, self.tcp_port_out)
6859 elif inner.haslayer(UDPerror):
6860 self.assertEqual(inner[UDPerror].dport, self.udp_port_out)
6861 else:
6862 self.assertEqual(inner[ICMPerror].id, self.icmp_id_out)
6863 except:
6864 self.logger.error(ppp("Unexpected or invalid packet:", packet))
6865 raise
6866
6867 # out2in
6868 pkts = [Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
6869 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6870 ICMP(type=3, code=13) /
6871 packet[IP] for packet in capture_ip4]
6872 self.pg1.add_stream(pkts)
6873 self.pg_enable_capture(self.pg_interfaces)
6874 self.pg_start()
6875 capture = self.pg0.get_capture(len(pkts))
6876 for packet in capture:
6877 try:
6878 self.assertEqual(packet[IPv6].src, ip.src)
6879 self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
6880 icmp = packet[ICMPv6DestUnreach]
6881 self.assertEqual(icmp.code, 1)
6882 inner = icmp[IPerror6]
6883 self.assertEqual(inner.src, self.pg0.remote_ip6)
6884 self.assertEqual(inner.dst, ip.src)
Klement Sekerad81ae412018-05-16 10:52:54 +02006885 self.assert_icmpv6_checksum_valid(packet)
Matus Fabian732036d2017-06-08 05:24:28 -07006886 if inner.haslayer(TCPerror):
6887 self.assertEqual(inner[TCPerror].sport, self.tcp_port_in)
6888 elif inner.haslayer(UDPerror):
6889 self.assertEqual(inner[UDPerror].sport, self.udp_port_in)
6890 else:
6891 self.assertEqual(inner[ICMPv6EchoRequest].id,
6892 self.icmp_id_in)
6893 except:
6894 self.logger.error(ppp("Unexpected or invalid packet:", packet))
6895 raise
6896
Matus Fabian029f3d22017-06-15 02:28:50 -07006897 def test_hairpinning(self):
6898 """ NAT64 hairpinning """
6899
6900 client = self.pg0.remote_hosts[0]
6901 server = self.pg0.remote_hosts[1]
6902 server_tcp_in_port = 22
6903 server_tcp_out_port = 4022
6904 server_udp_in_port = 23
6905 server_udp_out_port = 4023
6906 client_tcp_in_port = 1234
6907 client_udp_in_port = 1235
6908 client_tcp_out_port = 0
6909 client_udp_out_port = 0
6910 ip = IPv6(src=''.join(['64:ff9b::', self.nat_addr]))
6911 nat_addr_ip6 = ip.src
6912
6913 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6914 self.nat_addr_n)
6915 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6916 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6917
6918 self.vapi.nat64_add_del_static_bib(server.ip6n,
6919 self.nat_addr_n,
6920 server_tcp_in_port,
6921 server_tcp_out_port,
6922 IP_PROTOS.tcp)
6923 self.vapi.nat64_add_del_static_bib(server.ip6n,
6924 self.nat_addr_n,
6925 server_udp_in_port,
6926 server_udp_out_port,
6927 IP_PROTOS.udp)
6928
6929 # client to server
6930 pkts = []
6931 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6932 IPv6(src=client.ip6, dst=nat_addr_ip6) /
6933 TCP(sport=client_tcp_in_port, dport=server_tcp_out_port))
6934 pkts.append(p)
6935 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6936 IPv6(src=client.ip6, dst=nat_addr_ip6) /
6937 UDP(sport=client_udp_in_port, dport=server_udp_out_port))
6938 pkts.append(p)
6939 self.pg0.add_stream(pkts)
6940 self.pg_enable_capture(self.pg_interfaces)
6941 self.pg_start()
6942 capture = self.pg0.get_capture(len(pkts))
6943 for packet in capture:
6944 try:
6945 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
6946 self.assertEqual(packet[IPv6].dst, server.ip6)
Klement Sekerad81ae412018-05-16 10:52:54 +02006947 self.assert_packet_checksums_valid(packet)
Matus Fabian029f3d22017-06-15 02:28:50 -07006948 if packet.haslayer(TCP):
6949 self.assertNotEqual(packet[TCP].sport, client_tcp_in_port)
6950 self.assertEqual(packet[TCP].dport, server_tcp_in_port)
Matus Fabian029f3d22017-06-15 02:28:50 -07006951 client_tcp_out_port = packet[TCP].sport
6952 else:
6953 self.assertNotEqual(packet[UDP].sport, client_udp_in_port)
6954 self.assertEqual(packet[UDP].dport, server_udp_in_port)
Matus Fabian029f3d22017-06-15 02:28:50 -07006955 client_udp_out_port = packet[UDP].sport
6956 except:
6957 self.logger.error(ppp("Unexpected or invalid packet:", packet))
6958 raise
6959
6960 # server to client
6961 pkts = []
6962 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6963 IPv6(src=server.ip6, dst=nat_addr_ip6) /
6964 TCP(sport=server_tcp_in_port, dport=client_tcp_out_port))
6965 pkts.append(p)
6966 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6967 IPv6(src=server.ip6, dst=nat_addr_ip6) /
6968 UDP(sport=server_udp_in_port, dport=client_udp_out_port))
6969 pkts.append(p)
6970 self.pg0.add_stream(pkts)
6971 self.pg_enable_capture(self.pg_interfaces)
6972 self.pg_start()
6973 capture = self.pg0.get_capture(len(pkts))
6974 for packet in capture:
6975 try:
6976 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
6977 self.assertEqual(packet[IPv6].dst, client.ip6)
Klement Sekerad81ae412018-05-16 10:52:54 +02006978 self.assert_packet_checksums_valid(packet)
Matus Fabian029f3d22017-06-15 02:28:50 -07006979 if packet.haslayer(TCP):
6980 self.assertEqual(packet[TCP].sport, server_tcp_out_port)
6981 self.assertEqual(packet[TCP].dport, client_tcp_in_port)
Matus Fabian029f3d22017-06-15 02:28:50 -07006982 else:
6983 self.assertEqual(packet[UDP].sport, server_udp_out_port)
6984 self.assertEqual(packet[UDP].dport, client_udp_in_port)
Matus Fabian029f3d22017-06-15 02:28:50 -07006985 except:
6986 self.logger.error(ppp("Unexpected or invalid packet:", packet))
6987 raise
6988
6989 # ICMP error
6990 pkts = []
6991 pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6992 IPv6(src=client.ip6, dst=nat_addr_ip6) /
6993 ICMPv6DestUnreach(code=1) /
6994 packet[IPv6] for packet in capture]
6995 self.pg0.add_stream(pkts)
6996 self.pg_enable_capture(self.pg_interfaces)
6997 self.pg_start()
6998 capture = self.pg0.get_capture(len(pkts))
6999 for packet in capture:
7000 try:
7001 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
7002 self.assertEqual(packet[IPv6].dst, server.ip6)
7003 icmp = packet[ICMPv6DestUnreach]
7004 self.assertEqual(icmp.code, 1)
7005 inner = icmp[IPerror6]
7006 self.assertEqual(inner.src, server.ip6)
7007 self.assertEqual(inner.dst, nat_addr_ip6)
Klement Sekerad81ae412018-05-16 10:52:54 +02007008 self.assert_packet_checksums_valid(packet)
Matus Fabian029f3d22017-06-15 02:28:50 -07007009 if inner.haslayer(TCPerror):
7010 self.assertEqual(inner[TCPerror].sport, server_tcp_in_port)
7011 self.assertEqual(inner[TCPerror].dport,
7012 client_tcp_out_port)
7013 else:
7014 self.assertEqual(inner[UDPerror].sport, server_udp_in_port)
7015 self.assertEqual(inner[UDPerror].dport,
7016 client_udp_out_port)
7017 except:
7018 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7019 raise
7020
Matus Fabian428dc912017-06-21 06:15:18 -07007021 def test_prefix(self):
7022 """ NAT64 Network-Specific Prefix """
7023
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)
7028 self.vapi.nat64_add_del_pool_addr_range(self.vrf1_nat_addr_n,
7029 self.vrf1_nat_addr_n,
7030 vrf_id=self.vrf1_id)
7031 self.vapi.nat64_add_del_interface(self.pg2.sw_if_index)
7032
7033 # Add global prefix
7034 global_pref64 = "2001:db8::"
7035 global_pref64_n = socket.inet_pton(socket.AF_INET6, global_pref64)
7036 global_pref64_len = 32
7037 self.vapi.nat64_add_del_prefix(global_pref64_n, global_pref64_len)
7038
7039 prefix = self.vapi.nat64_prefix_dump()
7040 self.assertEqual(len(prefix), 1)
7041 self.assertEqual(prefix[0].prefix, global_pref64_n)
7042 self.assertEqual(prefix[0].prefix_len, global_pref64_len)
7043 self.assertEqual(prefix[0].vrf_id, 0)
7044
7045 # Add tenant specific prefix
7046 vrf1_pref64 = "2001:db8:122:300::"
7047 vrf1_pref64_n = socket.inet_pton(socket.AF_INET6, vrf1_pref64)
7048 vrf1_pref64_len = 56
7049 self.vapi.nat64_add_del_prefix(vrf1_pref64_n,
7050 vrf1_pref64_len,
7051 vrf_id=self.vrf1_id)
7052 prefix = self.vapi.nat64_prefix_dump()
7053 self.assertEqual(len(prefix), 2)
7054
7055 # Global prefix
7056 pkts = self.create_stream_in_ip6(self.pg0,
7057 self.pg1,
7058 pref=global_pref64,
7059 plen=global_pref64_len)
7060 self.pg0.add_stream(pkts)
7061 self.pg_enable_capture(self.pg_interfaces)
7062 self.pg_start()
7063 capture = self.pg1.get_capture(len(pkts))
7064 self.verify_capture_out(capture, nat_ip=self.nat_addr,
7065 dst_ip=self.pg1.remote_ip4)
7066
7067 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
7068 self.pg1.add_stream(pkts)
7069 self.pg_enable_capture(self.pg_interfaces)
7070 self.pg_start()
7071 capture = self.pg0.get_capture(len(pkts))
7072 dst_ip = self.compose_ip6(self.pg1.remote_ip4,
7073 global_pref64,
7074 global_pref64_len)
7075 self.verify_capture_in_ip6(capture, dst_ip, self.pg0.remote_ip6)
7076
7077 # Tenant specific prefix
7078 pkts = self.create_stream_in_ip6(self.pg2,
7079 self.pg1,
7080 pref=vrf1_pref64,
7081 plen=vrf1_pref64_len)
7082 self.pg2.add_stream(pkts)
7083 self.pg_enable_capture(self.pg_interfaces)
7084 self.pg_start()
7085 capture = self.pg1.get_capture(len(pkts))
7086 self.verify_capture_out(capture, nat_ip=self.vrf1_nat_addr,
7087 dst_ip=self.pg1.remote_ip4)
7088
7089 pkts = self.create_stream_out(self.pg1, dst_ip=self.vrf1_nat_addr)
7090 self.pg1.add_stream(pkts)
7091 self.pg_enable_capture(self.pg_interfaces)
7092 self.pg_start()
7093 capture = self.pg2.get_capture(len(pkts))
7094 dst_ip = self.compose_ip6(self.pg1.remote_ip4,
7095 vrf1_pref64,
7096 vrf1_pref64_len)
7097 self.verify_capture_in_ip6(capture, dst_ip, self.pg2.remote_ip6)
7098
Matus Fabianf8cd5812017-07-11 03:55:02 -07007099 def test_unknown_proto(self):
Matus Fabian7968e6c2017-07-06 05:37:49 -07007100 """ NAT64 translate packet with unknown protocol """
7101
7102 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7103 self.nat_addr_n)
7104 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7105 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7106 remote_ip6 = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
7107
7108 # in2out
7109 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7110 IPv6(src=self.pg0.remote_ip6, dst=remote_ip6) /
7111 TCP(sport=self.tcp_port_in, dport=20))
7112 self.pg0.add_stream(p)
7113 self.pg_enable_capture(self.pg_interfaces)
7114 self.pg_start()
7115 p = self.pg1.get_capture(1)
7116
7117 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabianf8cd5812017-07-11 03:55:02 -07007118 IPv6(src=self.pg0.remote_ip6, dst=remote_ip6, nh=47) /
Matus Fabian7968e6c2017-07-06 05:37:49 -07007119 GRE() /
7120 IP(src=self.pg2.local_ip4, dst=self.pg2.remote_ip4) /
7121 TCP(sport=1234, dport=1234))
7122 self.pg0.add_stream(p)
7123 self.pg_enable_capture(self.pg_interfaces)
7124 self.pg_start()
7125 p = self.pg1.get_capture(1)
7126 packet = p[0]
7127 try:
7128 self.assertEqual(packet[IP].src, self.nat_addr)
7129 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
7130 self.assertTrue(packet.haslayer(GRE))
Klement Sekerad81ae412018-05-16 10:52:54 +02007131 self.assert_packet_checksums_valid(packet)
Matus Fabian7968e6c2017-07-06 05:37:49 -07007132 except:
7133 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7134 raise
7135
7136 # out2in
7137 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
7138 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
7139 GRE() /
7140 IP(src=self.pg2.remote_ip4, dst=self.pg2.local_ip4) /
7141 TCP(sport=1234, dport=1234))
7142 self.pg1.add_stream(p)
7143 self.pg_enable_capture(self.pg_interfaces)
7144 self.pg_start()
7145 p = self.pg0.get_capture(1)
7146 packet = p[0]
7147 try:
7148 self.assertEqual(packet[IPv6].src, remote_ip6)
Matus Fabianf8cd5812017-07-11 03:55:02 -07007149 self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
7150 self.assertEqual(packet[IPv6].nh, 47)
Matus Fabian7968e6c2017-07-06 05:37:49 -07007151 except:
7152 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7153 raise
7154
Matus Fabianf8cd5812017-07-11 03:55:02 -07007155 def test_hairpinning_unknown_proto(self):
Matus Fabian7968e6c2017-07-06 05:37:49 -07007156 """ NAT64 translate packet with unknown protocol - hairpinning """
7157
7158 client = self.pg0.remote_hosts[0]
7159 server = self.pg0.remote_hosts[1]
7160 server_tcp_in_port = 22
7161 server_tcp_out_port = 4022
7162 client_tcp_in_port = 1234
Matus Fabianf8cd5812017-07-11 03:55:02 -07007163 client_tcp_out_port = 1235
7164 server_nat_ip = "10.0.0.100"
7165 client_nat_ip = "10.0.0.110"
7166 server_nat_ip_n = socket.inet_pton(socket.AF_INET, server_nat_ip)
7167 client_nat_ip_n = socket.inet_pton(socket.AF_INET, client_nat_ip)
7168 server_nat_ip6 = self.compose_ip6(server_nat_ip, '64:ff9b::', 96)
7169 client_nat_ip6 = self.compose_ip6(client_nat_ip, '64:ff9b::', 96)
Matus Fabian7968e6c2017-07-06 05:37:49 -07007170
Matus Fabianf8cd5812017-07-11 03:55:02 -07007171 self.vapi.nat64_add_del_pool_addr_range(server_nat_ip_n,
7172 client_nat_ip_n)
Matus Fabian7968e6c2017-07-06 05:37:49 -07007173 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7174 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7175
7176 self.vapi.nat64_add_del_static_bib(server.ip6n,
Matus Fabianf8cd5812017-07-11 03:55:02 -07007177 server_nat_ip_n,
Matus Fabian7968e6c2017-07-06 05:37:49 -07007178 server_tcp_in_port,
7179 server_tcp_out_port,
7180 IP_PROTOS.tcp)
7181
Matus Fabianf8cd5812017-07-11 03:55:02 -07007182 self.vapi.nat64_add_del_static_bib(server.ip6n,
7183 server_nat_ip_n,
7184 0,
7185 0,
7186 IP_PROTOS.gre)
7187
7188 self.vapi.nat64_add_del_static_bib(client.ip6n,
7189 client_nat_ip_n,
7190 client_tcp_in_port,
7191 client_tcp_out_port,
7192 IP_PROTOS.tcp)
7193
Matus Fabian7968e6c2017-07-06 05:37:49 -07007194 # client to server
7195 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabianf8cd5812017-07-11 03:55:02 -07007196 IPv6(src=client.ip6, dst=server_nat_ip6) /
Matus Fabian7968e6c2017-07-06 05:37:49 -07007197 TCP(sport=client_tcp_in_port, dport=server_tcp_out_port))
7198 self.pg0.add_stream(p)
7199 self.pg_enable_capture(self.pg_interfaces)
7200 self.pg_start()
7201 p = self.pg0.get_capture(1)
7202
7203 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabianf8cd5812017-07-11 03:55:02 -07007204 IPv6(src=client.ip6, dst=server_nat_ip6, nh=IP_PROTOS.gre) /
Matus Fabian7968e6c2017-07-06 05:37:49 -07007205 GRE() /
7206 IP(src=self.pg2.local_ip4, dst=self.pg2.remote_ip4) /
7207 TCP(sport=1234, dport=1234))
7208 self.pg0.add_stream(p)
7209 self.pg_enable_capture(self.pg_interfaces)
7210 self.pg_start()
7211 p = self.pg0.get_capture(1)
7212 packet = p[0]
7213 try:
Matus Fabianf8cd5812017-07-11 03:55:02 -07007214 self.assertEqual(packet[IPv6].src, client_nat_ip6)
Matus Fabian7968e6c2017-07-06 05:37:49 -07007215 self.assertEqual(packet[IPv6].dst, server.ip6)
Matus Fabianf8cd5812017-07-11 03:55:02 -07007216 self.assertEqual(packet[IPv6].nh, IP_PROTOS.gre)
Matus Fabian7968e6c2017-07-06 05:37:49 -07007217 except:
7218 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7219 raise
7220
7221 # server to client
7222 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabianf8cd5812017-07-11 03:55:02 -07007223 IPv6(src=server.ip6, dst=client_nat_ip6, nh=IP_PROTOS.gre) /
Matus Fabian7968e6c2017-07-06 05:37:49 -07007224 GRE() /
7225 IP(src=self.pg2.remote_ip4, dst=self.pg2.local_ip4) /
7226 TCP(sport=1234, dport=1234))
7227 self.pg0.add_stream(p)
7228 self.pg_enable_capture(self.pg_interfaces)
7229 self.pg_start()
7230 p = self.pg0.get_capture(1)
7231 packet = p[0]
7232 try:
Matus Fabianf8cd5812017-07-11 03:55:02 -07007233 self.assertEqual(packet[IPv6].src, server_nat_ip6)
Matus Fabian7968e6c2017-07-06 05:37:49 -07007234 self.assertEqual(packet[IPv6].dst, client.ip6)
Matus Fabianf8cd5812017-07-11 03:55:02 -07007235 self.assertEqual(packet[IPv6].nh, IP_PROTOS.gre)
Matus Fabian7968e6c2017-07-06 05:37:49 -07007236 except:
7237 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7238 raise
7239
Matus Fabian36ea2d62017-10-24 04:13:49 -07007240 def test_one_armed_nat64(self):
7241 """ One armed NAT64 """
7242 external_port = 0
7243 remote_host_ip6 = self.compose_ip6(self.pg3.remote_ip4,
7244 '64:ff9b::',
7245 96)
7246
7247 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7248 self.nat_addr_n)
7249 self.vapi.nat64_add_del_interface(self.pg3.sw_if_index)
7250 self.vapi.nat64_add_del_interface(self.pg3.sw_if_index, is_inside=0)
7251
7252 # in2out
7253 p = (Ether(src=self.pg3.remote_mac, dst=self.pg3.local_mac) /
7254 IPv6(src=self.pg3.remote_ip6, dst=remote_host_ip6) /
7255 TCP(sport=12345, dport=80))
7256 self.pg3.add_stream(p)
7257 self.pg_enable_capture(self.pg_interfaces)
7258 self.pg_start()
7259 capture = self.pg3.get_capture(1)
7260 p = capture[0]
7261 try:
7262 ip = p[IP]
7263 tcp = p[TCP]
7264 self.assertEqual(ip.src, self.nat_addr)
7265 self.assertEqual(ip.dst, self.pg3.remote_ip4)
7266 self.assertNotEqual(tcp.sport, 12345)
7267 external_port = tcp.sport
7268 self.assertEqual(tcp.dport, 80)
Klement Sekerad81ae412018-05-16 10:52:54 +02007269 self.assert_packet_checksums_valid(p)
Matus Fabian36ea2d62017-10-24 04:13:49 -07007270 except:
7271 self.logger.error(ppp("Unexpected or invalid packet:", p))
7272 raise
7273
7274 # out2in
7275 p = (Ether(src=self.pg3.remote_mac, dst=self.pg3.local_mac) /
7276 IP(src=self.pg3.remote_ip4, dst=self.nat_addr) /
7277 TCP(sport=80, dport=external_port))
7278 self.pg3.add_stream(p)
7279 self.pg_enable_capture(self.pg_interfaces)
7280 self.pg_start()
7281 capture = self.pg3.get_capture(1)
7282 p = capture[0]
7283 try:
7284 ip = p[IPv6]
7285 tcp = p[TCP]
7286 self.assertEqual(ip.src, remote_host_ip6)
7287 self.assertEqual(ip.dst, self.pg3.remote_ip6)
7288 self.assertEqual(tcp.sport, 80)
7289 self.assertEqual(tcp.dport, 12345)
Klement Sekerad81ae412018-05-16 10:52:54 +02007290 self.assert_packet_checksums_valid(p)
Matus Fabian36ea2d62017-10-24 04:13:49 -07007291 except:
7292 self.logger.error(ppp("Unexpected or invalid packet:", p))
7293 raise
7294
Matus Fabianefcd1e92017-08-15 06:59:19 -07007295 def test_frag_in_order(self):
7296 """ NAT64 translate fragments arriving in order """
7297 self.tcp_port_in = random.randint(1025, 65535)
7298
7299 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7300 self.nat_addr_n)
7301 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7302 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7303
7304 reass = self.vapi.nat_reass_dump()
7305 reass_n_start = len(reass)
7306
7307 # in2out
7308 data = 'a' * 200
7309 pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
7310 self.tcp_port_in, 20, data)
7311 self.pg0.add_stream(pkts)
7312 self.pg_enable_capture(self.pg_interfaces)
7313 self.pg_start()
7314 frags = self.pg1.get_capture(len(pkts))
7315 p = self.reass_frags_and_verify(frags,
7316 self.nat_addr,
7317 self.pg1.remote_ip4)
7318 self.assertEqual(p[TCP].dport, 20)
7319 self.assertNotEqual(p[TCP].sport, self.tcp_port_in)
7320 self.tcp_port_out = p[TCP].sport
7321 self.assertEqual(data, p[Raw].load)
7322
7323 # out2in
7324 data = "A" * 4 + "b" * 16 + "C" * 3
7325 pkts = self.create_stream_frag(self.pg1,
7326 self.nat_addr,
7327 20,
7328 self.tcp_port_out,
7329 data)
7330 self.pg1.add_stream(pkts)
7331 self.pg_enable_capture(self.pg_interfaces)
7332 self.pg_start()
7333 frags = self.pg0.get_capture(len(pkts))
7334 src = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
7335 p = self.reass_frags_and_verify_ip6(frags, src, self.pg0.remote_ip6)
7336 self.assertEqual(p[TCP].sport, 20)
7337 self.assertEqual(p[TCP].dport, self.tcp_port_in)
7338 self.assertEqual(data, p[Raw].load)
7339
7340 reass = self.vapi.nat_reass_dump()
7341 reass_n_end = len(reass)
7342
7343 self.assertEqual(reass_n_end - reass_n_start, 2)
7344
7345 def test_reass_hairpinning(self):
7346 """ NAT64 fragments hairpinning """
7347 data = 'a' * 200
Matus Fabianefcd1e92017-08-15 06:59:19 -07007348 server = self.pg0.remote_hosts[1]
7349 server_in_port = random.randint(1025, 65535)
7350 server_out_port = random.randint(1025, 65535)
7351 client_in_port = random.randint(1025, 65535)
7352 ip = IPv6(src=''.join(['64:ff9b::', self.nat_addr]))
7353 nat_addr_ip6 = ip.src
7354
7355 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7356 self.nat_addr_n)
7357 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7358 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7359
7360 # add static BIB entry for server
7361 self.vapi.nat64_add_del_static_bib(server.ip6n,
7362 self.nat_addr_n,
7363 server_in_port,
7364 server_out_port,
7365 IP_PROTOS.tcp)
7366
7367 # send packet from host to server
7368 pkts = self.create_stream_frag_ip6(self.pg0,
7369 self.nat_addr,
7370 client_in_port,
7371 server_out_port,
7372 data)
7373 self.pg0.add_stream(pkts)
7374 self.pg_enable_capture(self.pg_interfaces)
7375 self.pg_start()
7376 frags = self.pg0.get_capture(len(pkts))
7377 p = self.reass_frags_and_verify_ip6(frags, nat_addr_ip6, server.ip6)
7378 self.assertNotEqual(p[TCP].sport, client_in_port)
7379 self.assertEqual(p[TCP].dport, server_in_port)
7380 self.assertEqual(data, p[Raw].load)
7381
7382 def test_frag_out_of_order(self):
7383 """ NAT64 translate fragments arriving out of order """
7384 self.tcp_port_in = random.randint(1025, 65535)
7385
7386 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7387 self.nat_addr_n)
7388 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7389 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7390
7391 # in2out
7392 data = 'a' * 200
7393 pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
7394 self.tcp_port_in, 20, data)
7395 pkts.reverse()
7396 self.pg0.add_stream(pkts)
7397 self.pg_enable_capture(self.pg_interfaces)
7398 self.pg_start()
7399 frags = self.pg1.get_capture(len(pkts))
7400 p = self.reass_frags_and_verify(frags,
7401 self.nat_addr,
7402 self.pg1.remote_ip4)
7403 self.assertEqual(p[TCP].dport, 20)
7404 self.assertNotEqual(p[TCP].sport, self.tcp_port_in)
7405 self.tcp_port_out = p[TCP].sport
7406 self.assertEqual(data, p[Raw].load)
7407
7408 # out2in
7409 data = "A" * 4 + "B" * 16 + "C" * 3
7410 pkts = self.create_stream_frag(self.pg1,
7411 self.nat_addr,
7412 20,
7413 self.tcp_port_out,
7414 data)
7415 pkts.reverse()
7416 self.pg1.add_stream(pkts)
7417 self.pg_enable_capture(self.pg_interfaces)
7418 self.pg_start()
7419 frags = self.pg0.get_capture(len(pkts))
7420 src = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
7421 p = self.reass_frags_and_verify_ip6(frags, src, self.pg0.remote_ip6)
7422 self.assertEqual(p[TCP].sport, 20)
7423 self.assertEqual(p[TCP].dport, self.tcp_port_in)
7424 self.assertEqual(data, p[Raw].load)
7425
Matus Fabian0938dcf2017-11-08 01:59:38 -08007426 def test_interface_addr(self):
7427 """ Acquire NAT64 pool addresses from interface """
7428 self.vapi.nat64_add_interface_addr(self.pg4.sw_if_index)
7429
7430 # no address in NAT64 pool
7431 adresses = self.vapi.nat44_address_dump()
7432 self.assertEqual(0, len(adresses))
7433
7434 # configure interface address and check NAT64 address pool
7435 self.pg4.config_ip4()
7436 addresses = self.vapi.nat64_pool_addr_dump()
7437 self.assertEqual(len(addresses), 1)
7438 self.assertEqual(addresses[0].address, self.pg4.local_ip4n)
7439
7440 # remove interface address and check NAT64 address pool
7441 self.pg4.unconfig_ip4()
7442 addresses = self.vapi.nat64_pool_addr_dump()
7443 self.assertEqual(0, len(adresses))
7444
Matus Fabiana431ad12018-01-04 04:03:14 -08007445 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
7446 def test_ipfix_max_bibs_sessions(self):
7447 """ IPFIX logging maximum session and BIB entries exceeded """
7448 max_bibs = 1280
7449 max_sessions = 2560
7450 remote_host_ip6 = self.compose_ip6(self.pg1.remote_ip4,
7451 '64:ff9b::',
7452 96)
7453
7454 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7455 self.nat_addr_n)
7456 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7457 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7458
7459 pkts = []
7460 src = ""
7461 for i in range(0, max_bibs):
7462 src = "fd01:aa::%x" % (i)
7463 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7464 IPv6(src=src, dst=remote_host_ip6) /
7465 TCP(sport=12345, dport=80))
7466 pkts.append(p)
7467 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7468 IPv6(src=src, dst=remote_host_ip6) /
7469 TCP(sport=12345, dport=22))
7470 pkts.append(p)
7471 self.pg0.add_stream(pkts)
7472 self.pg_enable_capture(self.pg_interfaces)
7473 self.pg_start()
7474 self.pg1.get_capture(max_sessions)
7475
7476 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
7477 src_address=self.pg3.local_ip4n,
7478 path_mtu=512,
7479 template_interval=10)
7480 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
7481 src_port=self.ipfix_src_port)
7482
7483 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7484 IPv6(src=src, dst=remote_host_ip6) /
7485 TCP(sport=12345, dport=25))
7486 self.pg0.add_stream(p)
7487 self.pg_enable_capture(self.pg_interfaces)
7488 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07007489 self.pg1.assert_nothing_captured()
7490 sleep(1)
Matus Fabiana431ad12018-01-04 04:03:14 -08007491 self.vapi.cli("ipfix flush") # FIXME this should be an API call
7492 capture = self.pg3.get_capture(9)
7493 ipfix = IPFIXDecoder()
7494 # first load template
7495 for p in capture:
7496 self.assertTrue(p.haslayer(IPFIX))
7497 self.assertEqual(p[IP].src, self.pg3.local_ip4)
7498 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
7499 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
7500 self.assertEqual(p[UDP].dport, 4739)
7501 self.assertEqual(p[IPFIX].observationDomainID,
7502 self.ipfix_domain_id)
7503 if p.haslayer(Template):
7504 ipfix.add_template(p.getlayer(Template))
7505 # verify events in data set
7506 for p in capture:
7507 if p.haslayer(Data):
7508 data = ipfix.decode_data_set(p.getlayer(Set))
7509 self.verify_ipfix_max_sessions(data, max_sessions)
7510
7511 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7512 IPv6(src=self.pg0.remote_ip6, dst=remote_host_ip6) /
7513 TCP(sport=12345, dport=80))
7514 self.pg0.add_stream(p)
7515 self.pg_enable_capture(self.pg_interfaces)
7516 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07007517 self.pg1.assert_nothing_captured()
7518 sleep(1)
Matus Fabiana431ad12018-01-04 04:03:14 -08007519 self.vapi.cli("ipfix flush") # FIXME this should be an API call
7520 capture = self.pg3.get_capture(1)
7521 # verify events in data set
7522 for p in capture:
7523 self.assertTrue(p.haslayer(IPFIX))
7524 self.assertEqual(p[IP].src, self.pg3.local_ip4)
7525 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
7526 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
7527 self.assertEqual(p[UDP].dport, 4739)
7528 self.assertEqual(p[IPFIX].observationDomainID,
7529 self.ipfix_domain_id)
7530 if p.haslayer(Data):
7531 data = ipfix.decode_data_set(p.getlayer(Set))
7532 self.verify_ipfix_max_bibs(data, max_bibs)
7533
7534 def test_ipfix_max_frags(self):
7535 """ IPFIX logging maximum fragments pending reassembly exceeded """
7536 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7537 self.nat_addr_n)
7538 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7539 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
Matus Fabiana7f8b222018-09-05 06:01:55 -07007540 self.vapi.nat_set_reass(max_frag=1, is_ip6=1)
Matus Fabiana431ad12018-01-04 04:03:14 -08007541 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
7542 src_address=self.pg3.local_ip4n,
7543 path_mtu=512,
7544 template_interval=10)
7545 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
7546 src_port=self.ipfix_src_port)
7547
7548 data = 'a' * 200
7549 pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
7550 self.tcp_port_in, 20, data)
Matus Fabiana7f8b222018-09-05 06:01:55 -07007551 pkts.reverse()
7552 self.pg0.add_stream(pkts)
Matus Fabiana431ad12018-01-04 04:03:14 -08007553 self.pg_enable_capture(self.pg_interfaces)
7554 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07007555 self.pg1.assert_nothing_captured()
7556 sleep(1)
Matus Fabiana431ad12018-01-04 04:03:14 -08007557 self.vapi.cli("ipfix flush") # FIXME this should be an API call
7558 capture = self.pg3.get_capture(9)
7559 ipfix = IPFIXDecoder()
7560 # first load template
7561 for p in capture:
7562 self.assertTrue(p.haslayer(IPFIX))
7563 self.assertEqual(p[IP].src, self.pg3.local_ip4)
7564 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
7565 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
7566 self.assertEqual(p[UDP].dport, 4739)
7567 self.assertEqual(p[IPFIX].observationDomainID,
7568 self.ipfix_domain_id)
7569 if p.haslayer(Template):
7570 ipfix.add_template(p.getlayer(Template))
7571 # verify events in data set
7572 for p in capture:
7573 if p.haslayer(Data):
7574 data = ipfix.decode_data_set(p.getlayer(Set))
Matus Fabiana7f8b222018-09-05 06:01:55 -07007575 self.verify_ipfix_max_fragments_ip6(data, 1,
Matus Fabiana431ad12018-01-04 04:03:14 -08007576 self.pg0.remote_ip6n)
7577
7578 def test_ipfix_bib_ses(self):
7579 """ IPFIX logging NAT64 BIB/session create and delete events """
7580 self.tcp_port_in = random.randint(1025, 65535)
7581 remote_host_ip6 = self.compose_ip6(self.pg1.remote_ip4,
7582 '64:ff9b::',
7583 96)
7584
7585 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7586 self.nat_addr_n)
7587 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7588 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7589 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
7590 src_address=self.pg3.local_ip4n,
7591 path_mtu=512,
7592 template_interval=10)
7593 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
7594 src_port=self.ipfix_src_port)
7595
7596 # Create
7597 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7598 IPv6(src=self.pg0.remote_ip6, dst=remote_host_ip6) /
7599 TCP(sport=self.tcp_port_in, dport=25))
7600 self.pg0.add_stream(p)
7601 self.pg_enable_capture(self.pg_interfaces)
7602 self.pg_start()
7603 p = self.pg1.get_capture(1)
7604 self.tcp_port_out = p[0][TCP].sport
7605 self.vapi.cli("ipfix flush") # FIXME this should be an API call
7606 capture = self.pg3.get_capture(10)
7607 ipfix = IPFIXDecoder()
7608 # first load template
7609 for p in capture:
7610 self.assertTrue(p.haslayer(IPFIX))
7611 self.assertEqual(p[IP].src, self.pg3.local_ip4)
7612 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
7613 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
7614 self.assertEqual(p[UDP].dport, 4739)
7615 self.assertEqual(p[IPFIX].observationDomainID,
7616 self.ipfix_domain_id)
7617 if p.haslayer(Template):
7618 ipfix.add_template(p.getlayer(Template))
7619 # verify events in data set
7620 for p in capture:
7621 if p.haslayer(Data):
7622 data = ipfix.decode_data_set(p.getlayer(Set))
7623 if ord(data[0][230]) == 10:
7624 self.verify_ipfix_bib(data, 1, self.pg0.remote_ip6n)
7625 elif ord(data[0][230]) == 6:
7626 self.verify_ipfix_nat64_ses(data,
7627 1,
7628 self.pg0.remote_ip6n,
7629 self.pg1.remote_ip4,
7630 25)
7631 else:
7632 self.logger.error(ppp("Unexpected or invalid packet: ", p))
7633
7634 # Delete
7635 self.pg_enable_capture(self.pg_interfaces)
7636 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7637 self.nat_addr_n,
7638 is_add=0)
7639 self.vapi.cli("ipfix flush") # FIXME this should be an API call
7640 capture = self.pg3.get_capture(2)
7641 # verify events in data set
7642 for p in capture:
7643 self.assertTrue(p.haslayer(IPFIX))
7644 self.assertEqual(p[IP].src, self.pg3.local_ip4)
7645 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
7646 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
7647 self.assertEqual(p[UDP].dport, 4739)
7648 self.assertEqual(p[IPFIX].observationDomainID,
7649 self.ipfix_domain_id)
7650 if p.haslayer(Data):
7651 data = ipfix.decode_data_set(p.getlayer(Set))
7652 if ord(data[0][230]) == 11:
7653 self.verify_ipfix_bib(data, 0, self.pg0.remote_ip6n)
7654 elif ord(data[0][230]) == 7:
7655 self.verify_ipfix_nat64_ses(data,
7656 0,
7657 self.pg0.remote_ip6n,
7658 self.pg1.remote_ip4,
7659 25)
7660 else:
7661 self.logger.error(ppp("Unexpected or invalid packet: ", p))
7662
Matus Fabian06596c52017-06-06 04:53:28 -07007663 def nat64_get_ses_num(self):
7664 """
7665 Return number of active NAT64 sessions.
7666 """
Matus Fabianab9a59c2017-08-16 05:37:36 -07007667 st = self.vapi.nat64_st_dump()
7668 return len(st)
Matus Fabian06596c52017-06-06 04:53:28 -07007669
7670 def clear_nat64(self):
7671 """
7672 Clear NAT64 configuration.
7673 """
Matus Fabiana431ad12018-01-04 04:03:14 -08007674 self.vapi.nat_ipfix(enable=0, src_port=self.ipfix_src_port,
7675 domain_id=self.ipfix_domain_id)
7676 self.ipfix_src_port = 4739
7677 self.ipfix_domain_id = 1
7678
Matus Fabian878c6462018-08-23 00:33:35 -07007679 self.vapi.nat_set_timeouts()
Matus Fabian06596c52017-06-06 04:53:28 -07007680
7681 interfaces = self.vapi.nat64_interface_dump()
7682 for intf in interfaces:
Matus Fabian36ea2d62017-10-24 04:13:49 -07007683 if intf.is_inside > 1:
7684 self.vapi.nat64_add_del_interface(intf.sw_if_index,
7685 0,
7686 is_add=0)
Matus Fabian06596c52017-06-06 04:53:28 -07007687 self.vapi.nat64_add_del_interface(intf.sw_if_index,
7688 intf.is_inside,
7689 is_add=0)
7690
Matus Fabiana431ad12018-01-04 04:03:14 -08007691 bib = self.vapi.nat64_bib_dump(255)
Matus Fabian06596c52017-06-06 04:53:28 -07007692 for bibe in bib:
7693 if bibe.is_static:
7694 self.vapi.nat64_add_del_static_bib(bibe.i_addr,
7695 bibe.o_addr,
7696 bibe.i_port,
7697 bibe.o_port,
7698 bibe.proto,
7699 bibe.vrf_id,
7700 is_add=0)
7701
7702 adresses = self.vapi.nat64_pool_addr_dump()
7703 for addr in adresses:
7704 self.vapi.nat64_add_del_pool_addr_range(addr.address,
7705 addr.address,
Matus Fabian029f3d22017-06-15 02:28:50 -07007706 vrf_id=addr.vrf_id,
Matus Fabian06596c52017-06-06 04:53:28 -07007707 is_add=0)
7708
Matus Fabian428dc912017-06-21 06:15:18 -07007709 prefixes = self.vapi.nat64_prefix_dump()
7710 for prefix in prefixes:
7711 self.vapi.nat64_add_del_prefix(prefix.prefix,
7712 prefix.prefix_len,
7713 vrf_id=prefix.vrf_id,
7714 is_add=0)
7715
Matus Fabian06596c52017-06-06 04:53:28 -07007716 def tearDown(self):
7717 super(TestNAT64, self).tearDown()
7718 if not self.vpp_dead:
7719 self.logger.info(self.vapi.cli("show nat64 pool"))
7720 self.logger.info(self.vapi.cli("show nat64 interfaces"))
Matus Fabian428dc912017-06-21 06:15:18 -07007721 self.logger.info(self.vapi.cli("show nat64 prefix"))
Matus Fabianab9a59c2017-08-16 05:37:36 -07007722 self.logger.info(self.vapi.cli("show nat64 bib all"))
7723 self.logger.info(self.vapi.cli("show nat64 session table all"))
Matus Fabianefcd1e92017-08-15 06:59:19 -07007724 self.logger.info(self.vapi.cli("show nat virtual-reassembly"))
Matus Fabian06596c52017-06-06 04:53:28 -07007725 self.clear_nat64()
7726
Matus Fabian8ebe6252017-11-06 05:04:53 -08007727
7728class TestDSlite(MethodHolder):
7729 """ DS-Lite Test Cases """
7730
7731 @classmethod
7732 def setUpClass(cls):
7733 super(TestDSlite, cls).setUpClass()
7734
7735 try:
7736 cls.nat_addr = '10.0.0.3'
7737 cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
7738
7739 cls.create_pg_interfaces(range(2))
7740 cls.pg0.admin_up()
7741 cls.pg0.config_ip4()
7742 cls.pg0.resolve_arp()
7743 cls.pg1.admin_up()
7744 cls.pg1.config_ip6()
7745 cls.pg1.generate_remote_hosts(2)
7746 cls.pg1.configure_ipv6_neighbors()
7747
7748 except Exception:
7749 super(TestDSlite, cls).tearDownClass()
7750 raise
7751
7752 def test_dslite(self):
7753 """ Test DS-Lite """
Matus Fabian69ce30d2018-08-22 01:27:10 -07007754 nat_config = self.vapi.nat_show_config()
7755 self.assertEqual(0, nat_config.dslite_ce)
7756
Matus Fabian8ebe6252017-11-06 05:04:53 -08007757 self.vapi.dslite_add_del_pool_addr_range(self.nat_addr_n,
7758 self.nat_addr_n)
7759 aftr_ip4 = '192.0.0.1'
7760 aftr_ip4_n = socket.inet_pton(socket.AF_INET, aftr_ip4)
7761 aftr_ip6 = '2001:db8:85a3::8a2e:370:1'
7762 aftr_ip6_n = socket.inet_pton(socket.AF_INET6, aftr_ip6)
7763 self.vapi.dslite_set_aftr_addr(aftr_ip6_n, aftr_ip4_n)
7764
7765 # UDP
7766 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
7767 IPv6(dst=aftr_ip6, src=self.pg1.remote_hosts[0].ip6) /
7768 IP(dst=self.pg0.remote_ip4, src='192.168.1.1') /
7769 UDP(sport=20000, dport=10000))
7770 self.pg1.add_stream(p)
7771 self.pg_enable_capture(self.pg_interfaces)
7772 self.pg_start()
7773 capture = self.pg0.get_capture(1)
7774 capture = capture[0]
7775 self.assertFalse(capture.haslayer(IPv6))
7776 self.assertEqual(capture[IP].src, self.nat_addr)
7777 self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
7778 self.assertNotEqual(capture[UDP].sport, 20000)
7779 self.assertEqual(capture[UDP].dport, 10000)
Klement Sekerad81ae412018-05-16 10:52:54 +02007780 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08007781 out_port = capture[UDP].sport
7782
7783 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7784 IP(dst=self.nat_addr, src=self.pg0.remote_ip4) /
7785 UDP(sport=10000, dport=out_port))
7786 self.pg0.add_stream(p)
7787 self.pg_enable_capture(self.pg_interfaces)
7788 self.pg_start()
7789 capture = self.pg1.get_capture(1)
7790 capture = capture[0]
7791 self.assertEqual(capture[IPv6].src, aftr_ip6)
7792 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[0].ip6)
7793 self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
7794 self.assertEqual(capture[IP].dst, '192.168.1.1')
7795 self.assertEqual(capture[UDP].sport, 10000)
7796 self.assertEqual(capture[UDP].dport, 20000)
Klement Sekerad81ae412018-05-16 10:52:54 +02007797 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08007798
7799 # TCP
7800 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
7801 IPv6(dst=aftr_ip6, src=self.pg1.remote_hosts[1].ip6) /
7802 IP(dst=self.pg0.remote_ip4, src='192.168.1.1') /
7803 TCP(sport=20001, dport=10001))
7804 self.pg1.add_stream(p)
7805 self.pg_enable_capture(self.pg_interfaces)
7806 self.pg_start()
7807 capture = self.pg0.get_capture(1)
7808 capture = capture[0]
7809 self.assertFalse(capture.haslayer(IPv6))
7810 self.assertEqual(capture[IP].src, self.nat_addr)
7811 self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
7812 self.assertNotEqual(capture[TCP].sport, 20001)
7813 self.assertEqual(capture[TCP].dport, 10001)
Klement Sekerad81ae412018-05-16 10:52:54 +02007814 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08007815 out_port = capture[TCP].sport
7816
7817 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7818 IP(dst=self.nat_addr, src=self.pg0.remote_ip4) /
7819 TCP(sport=10001, dport=out_port))
7820 self.pg0.add_stream(p)
7821 self.pg_enable_capture(self.pg_interfaces)
7822 self.pg_start()
7823 capture = self.pg1.get_capture(1)
7824 capture = capture[0]
7825 self.assertEqual(capture[IPv6].src, aftr_ip6)
7826 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[1].ip6)
7827 self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
7828 self.assertEqual(capture[IP].dst, '192.168.1.1')
7829 self.assertEqual(capture[TCP].sport, 10001)
7830 self.assertEqual(capture[TCP].dport, 20001)
Klement Sekerad81ae412018-05-16 10:52:54 +02007831 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08007832
7833 # ICMP
7834 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
7835 IPv6(dst=aftr_ip6, src=self.pg1.remote_hosts[1].ip6) /
7836 IP(dst=self.pg0.remote_ip4, src='192.168.1.1') /
7837 ICMP(id=4000, type='echo-request'))
7838 self.pg1.add_stream(p)
7839 self.pg_enable_capture(self.pg_interfaces)
7840 self.pg_start()
7841 capture = self.pg0.get_capture(1)
7842 capture = capture[0]
7843 self.assertFalse(capture.haslayer(IPv6))
7844 self.assertEqual(capture[IP].src, self.nat_addr)
7845 self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
7846 self.assertNotEqual(capture[ICMP].id, 4000)
Klement Sekerad81ae412018-05-16 10:52:54 +02007847 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08007848 out_id = capture[ICMP].id
7849
7850 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7851 IP(dst=self.nat_addr, src=self.pg0.remote_ip4) /
7852 ICMP(id=out_id, type='echo-reply'))
7853 self.pg0.add_stream(p)
7854 self.pg_enable_capture(self.pg_interfaces)
7855 self.pg_start()
7856 capture = self.pg1.get_capture(1)
7857 capture = capture[0]
7858 self.assertEqual(capture[IPv6].src, aftr_ip6)
7859 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[1].ip6)
7860 self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
7861 self.assertEqual(capture[IP].dst, '192.168.1.1')
7862 self.assertEqual(capture[ICMP].id, 4000)
Klement Sekerad81ae412018-05-16 10:52:54 +02007863 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08007864
Matus Fabian331acc62017-12-08 03:38:51 -08007865 # ping DS-Lite AFTR tunnel endpoint address
7866 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
7867 IPv6(src=self.pg1.remote_hosts[1].ip6, dst=aftr_ip6) /
7868 ICMPv6EchoRequest())
7869 self.pg1.add_stream(p)
7870 self.pg_enable_capture(self.pg_interfaces)
7871 self.pg_start()
7872 capture = self.pg1.get_capture(1)
Matus Fabian331acc62017-12-08 03:38:51 -08007873 capture = capture[0]
7874 self.assertEqual(capture[IPv6].src, aftr_ip6)
7875 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[1].ip6)
7876 self.assertTrue(capture.haslayer(ICMPv6EchoReply))
7877
Matus Fabian8ebe6252017-11-06 05:04:53 -08007878 def tearDown(self):
7879 super(TestDSlite, self).tearDown()
7880 if not self.vpp_dead:
7881 self.logger.info(self.vapi.cli("show dslite pool"))
7882 self.logger.info(
7883 self.vapi.cli("show dslite aftr-tunnel-endpoint-address"))
7884 self.logger.info(self.vapi.cli("show dslite sessions"))
7885
Juraj Slobodac5c6a332018-01-09 16:08:32 +01007886
7887class TestDSliteCE(MethodHolder):
7888 """ DS-Lite CE Test Cases """
7889
7890 @classmethod
7891 def setUpConstants(cls):
7892 super(TestDSliteCE, cls).setUpConstants()
7893 cls.vpp_cmdline.extend(["nat", "{", "dslite ce", "}"])
7894
7895 @classmethod
7896 def setUpClass(cls):
7897 super(TestDSliteCE, cls).setUpClass()
7898
7899 try:
7900 cls.create_pg_interfaces(range(2))
7901 cls.pg0.admin_up()
7902 cls.pg0.config_ip4()
7903 cls.pg0.resolve_arp()
7904 cls.pg1.admin_up()
7905 cls.pg1.config_ip6()
7906 cls.pg1.generate_remote_hosts(1)
7907 cls.pg1.configure_ipv6_neighbors()
7908
7909 except Exception:
7910 super(TestDSliteCE, cls).tearDownClass()
7911 raise
7912
7913 def test_dslite_ce(self):
7914 """ Test DS-Lite CE """
7915
Matus Fabian69ce30d2018-08-22 01:27:10 -07007916 nat_config = self.vapi.nat_show_config()
7917 self.assertEqual(1, nat_config.dslite_ce)
7918
Juraj Slobodac5c6a332018-01-09 16:08:32 +01007919 b4_ip4 = '192.0.0.2'
7920 b4_ip4_n = socket.inet_pton(socket.AF_INET, b4_ip4)
7921 b4_ip6 = '2001:db8:62aa::375e:f4c1:1'
7922 b4_ip6_n = socket.inet_pton(socket.AF_INET6, b4_ip6)
7923 self.vapi.dslite_set_b4_addr(b4_ip6_n, b4_ip4_n)
7924
7925 aftr_ip4 = '192.0.0.1'
7926 aftr_ip4_n = socket.inet_pton(socket.AF_INET, aftr_ip4)
7927 aftr_ip6 = '2001:db8:85a3::8a2e:370:1'
7928 aftr_ip6_n = socket.inet_pton(socket.AF_INET6, aftr_ip6)
7929 self.vapi.dslite_set_aftr_addr(aftr_ip6_n, aftr_ip4_n)
7930
7931 self.vapi.ip_add_del_route(dst_address=aftr_ip6_n,
7932 dst_address_length=128,
7933 next_hop_address=self.pg1.remote_ip6n,
7934 next_hop_sw_if_index=self.pg1.sw_if_index,
7935 is_ipv6=1)
7936
7937 # UDP encapsulation
7938 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7939 IP(dst=self.pg1.remote_ip4, src=self.pg0.remote_ip4) /
7940 UDP(sport=10000, dport=20000))
7941 self.pg0.add_stream(p)
7942 self.pg_enable_capture(self.pg_interfaces)
7943 self.pg_start()
7944 capture = self.pg1.get_capture(1)
7945 capture = capture[0]
7946 self.assertEqual(capture[IPv6].src, b4_ip6)
7947 self.assertEqual(capture[IPv6].dst, aftr_ip6)
7948 self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
7949 self.assertEqual(capture[IP].dst, self.pg1.remote_ip4)
7950 self.assertEqual(capture[UDP].sport, 10000)
7951 self.assertEqual(capture[UDP].dport, 20000)
Klement Sekerad81ae412018-05-16 10:52:54 +02007952 self.assert_packet_checksums_valid(capture)
Juraj Slobodac5c6a332018-01-09 16:08:32 +01007953
7954 # UDP decapsulation
7955 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
7956 IPv6(dst=b4_ip6, src=aftr_ip6) /
7957 IP(dst=self.pg0.remote_ip4, src=self.pg1.remote_ip4) /
7958 UDP(sport=20000, dport=10000))
7959 self.pg1.add_stream(p)
7960 self.pg_enable_capture(self.pg_interfaces)
7961 self.pg_start()
7962 capture = self.pg0.get_capture(1)
7963 capture = capture[0]
7964 self.assertFalse(capture.haslayer(IPv6))
7965 self.assertEqual(capture[IP].src, self.pg1.remote_ip4)
7966 self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
7967 self.assertEqual(capture[UDP].sport, 20000)
7968 self.assertEqual(capture[UDP].dport, 10000)
Klement Sekerad81ae412018-05-16 10:52:54 +02007969 self.assert_packet_checksums_valid(capture)
Juraj Slobodac5c6a332018-01-09 16:08:32 +01007970
7971 # ping DS-Lite B4 tunnel endpoint address
7972 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
7973 IPv6(src=self.pg1.remote_hosts[0].ip6, dst=b4_ip6) /
7974 ICMPv6EchoRequest())
7975 self.pg1.add_stream(p)
7976 self.pg_enable_capture(self.pg_interfaces)
7977 self.pg_start()
7978 capture = self.pg1.get_capture(1)
Juraj Slobodac5c6a332018-01-09 16:08:32 +01007979 capture = capture[0]
7980 self.assertEqual(capture[IPv6].src, b4_ip6)
7981 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[0].ip6)
7982 self.assertTrue(capture.haslayer(ICMPv6EchoReply))
7983
7984 def tearDown(self):
7985 super(TestDSliteCE, self).tearDown()
7986 if not self.vpp_dead:
7987 self.logger.info(
7988 self.vapi.cli("show dslite aftr-tunnel-endpoint-address"))
7989 self.logger.info(
7990 self.vapi.cli("show dslite b4-tunnel-endpoint-address"))
7991
Matus Fabianf2a23cc2018-01-22 03:41:53 -08007992
7993class TestNAT66(MethodHolder):
7994 """ NAT66 Test Cases """
7995
7996 @classmethod
7997 def setUpClass(cls):
7998 super(TestNAT66, cls).setUpClass()
7999
8000 try:
8001 cls.nat_addr = 'fd01:ff::2'
8002 cls.nat_addr_n = socket.inet_pton(socket.AF_INET6, cls.nat_addr)
8003
8004 cls.create_pg_interfaces(range(2))
8005 cls.interfaces = list(cls.pg_interfaces)
8006
8007 for i in cls.interfaces:
8008 i.admin_up()
8009 i.config_ip6()
8010 i.configure_ipv6_neighbors()
8011
8012 except Exception:
8013 super(TestNAT66, cls).tearDownClass()
8014 raise
8015
8016 def test_static(self):
8017 """ 1:1 NAT66 test """
8018 self.vapi.nat66_add_del_interface(self.pg0.sw_if_index)
8019 self.vapi.nat66_add_del_interface(self.pg1.sw_if_index, is_inside=0)
8020 self.vapi.nat66_add_del_static_mapping(self.pg0.remote_ip6n,
8021 self.nat_addr_n)
8022
8023 # in2out
8024 pkts = []
8025 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8026 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
8027 TCP())
8028 pkts.append(p)
8029 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8030 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
8031 UDP())
8032 pkts.append(p)
8033 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8034 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
8035 ICMPv6EchoRequest())
8036 pkts.append(p)
8037 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8038 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
8039 GRE() / IP() / TCP())
8040 pkts.append(p)
8041 self.pg0.add_stream(pkts)
8042 self.pg_enable_capture(self.pg_interfaces)
8043 self.pg_start()
8044 capture = self.pg1.get_capture(len(pkts))
8045 for packet in capture:
8046 try:
8047 self.assertEqual(packet[IPv6].src, self.nat_addr)
8048 self.assertEqual(packet[IPv6].dst, self.pg1.remote_ip6)
Klement Sekerad81ae412018-05-16 10:52:54 +02008049 self.assert_packet_checksums_valid(packet)
Matus Fabianf2a23cc2018-01-22 03:41:53 -08008050 except:
8051 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8052 raise
8053
8054 # out2in
8055 pkts = []
8056 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8057 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
8058 TCP())
8059 pkts.append(p)
8060 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8061 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
8062 UDP())
8063 pkts.append(p)
8064 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8065 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
8066 ICMPv6EchoReply())
8067 pkts.append(p)
8068 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8069 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
8070 GRE() / IP() / TCP())
8071 pkts.append(p)
8072 self.pg1.add_stream(pkts)
8073 self.pg_enable_capture(self.pg_interfaces)
8074 self.pg_start()
8075 capture = self.pg0.get_capture(len(pkts))
8076 for packet in capture:
8077 try:
8078 self.assertEqual(packet[IPv6].src, self.pg1.remote_ip6)
8079 self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
Klement Sekerad81ae412018-05-16 10:52:54 +02008080 self.assert_packet_checksums_valid(packet)
Matus Fabianf2a23cc2018-01-22 03:41:53 -08008081 except:
8082 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8083 raise
8084
8085 sm = self.vapi.nat66_static_mapping_dump()
8086 self.assertEqual(len(sm), 1)
8087 self.assertEqual(sm[0].total_pkts, 8)
8088
Juraj Sloboda9341e342018-04-13 12:00:46 +02008089 def test_check_no_translate(self):
8090 """ NAT66 translate only when egress interface is outside interface """
8091 self.vapi.nat66_add_del_interface(self.pg0.sw_if_index)
8092 self.vapi.nat66_add_del_interface(self.pg1.sw_if_index)
8093 self.vapi.nat66_add_del_static_mapping(self.pg0.remote_ip6n,
8094 self.nat_addr_n)
8095
8096 # in2out
8097 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8098 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
8099 UDP())
8100 self.pg0.add_stream([p])
8101 self.pg_enable_capture(self.pg_interfaces)
8102 self.pg_start()
8103 capture = self.pg1.get_capture(1)
8104 packet = capture[0]
8105 try:
8106 self.assertEqual(packet[IPv6].src, self.pg0.remote_ip6)
8107 self.assertEqual(packet[IPv6].dst, self.pg1.remote_ip6)
8108 except:
8109 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8110 raise
8111
Matus Fabianf2a23cc2018-01-22 03:41:53 -08008112 def clear_nat66(self):
8113 """
8114 Clear NAT66 configuration.
8115 """
8116 interfaces = self.vapi.nat66_interface_dump()
8117 for intf in interfaces:
8118 self.vapi.nat66_add_del_interface(intf.sw_if_index,
8119 intf.is_inside,
8120 is_add=0)
8121
8122 static_mappings = self.vapi.nat66_static_mapping_dump()
8123 for sm in static_mappings:
8124 self.vapi.nat66_add_del_static_mapping(sm.local_ip_address,
8125 sm.external_ip_address,
8126 sm.vrf_id,
8127 is_add=0)
8128
8129 def tearDown(self):
8130 super(TestNAT66, self).tearDown()
8131 if not self.vpp_dead:
8132 self.logger.info(self.vapi.cli("show nat66 interfaces"))
8133 self.logger.info(self.vapi.cli("show nat66 static mappings"))
8134 self.clear_nat66()
8135
Klement Sekerad81ae412018-05-16 10:52:54 +02008136
Matus Fabiande886752016-12-07 03:38:19 -08008137if __name__ == '__main__':
8138 unittest.main(testRunner=VppTestRunner)