blob: b7b80c95c2a6dac710254d0b6558fb20bc9dd62e [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 Fabianad1f3e12018-11-28 21:26:34 -080024from syslog_rfc5424_parser import SyslogMessage, ParseError
25from syslog_rfc5424_parser.constants import SyslogFacility, SyslogSeverity
26from vpp_papi_provider import SYSLOG_SEVERITY
Matus Fabiande886752016-12-07 03:38:19 -080027
28
Martin Gálikd7f75cd2017-03-27 06:02:47 -070029class MethodHolder(VppTestCase):
Matus Fabian2ba92e32017-08-21 07:05:03 -070030 """ NAT create capture and verify method holder """
Matus Fabiande886752016-12-07 03:38:19 -080031
Matus Fabiana6110b62018-06-13 05:39:07 -070032 def clear_nat44(self):
33 """
34 Clear NAT44 configuration.
35 """
36 if hasattr(self, 'pg7') and hasattr(self, 'pg8'):
37 # I found no elegant way to do this
38 self.vapi.ip_add_del_route(
39 dst_address=self.pg7.remote_ip4n,
40 dst_address_length=32,
41 next_hop_address=self.pg7.remote_ip4n,
42 next_hop_sw_if_index=self.pg7.sw_if_index,
43 is_add=0)
44 self.vapi.ip_add_del_route(
45 dst_address=self.pg8.remote_ip4n,
46 dst_address_length=32,
47 next_hop_address=self.pg8.remote_ip4n,
48 next_hop_sw_if_index=self.pg8.sw_if_index,
49 is_add=0)
50
51 for intf in [self.pg7, self.pg8]:
52 neighbors = self.vapi.ip_neighbor_dump(intf.sw_if_index)
53 for n in neighbors:
54 self.vapi.ip_neighbor_add_del(intf.sw_if_index,
55 n.mac_address,
56 n.ip_address,
57 is_add=0)
58
59 if self.pg7.has_ip4_config:
60 self.pg7.unconfig_ip4()
61
62 self.vapi.nat44_forwarding_enable_disable(0)
63
64 interfaces = self.vapi.nat44_interface_addr_dump()
65 for intf in interfaces:
66 self.vapi.nat44_add_interface_addr(intf.sw_if_index,
67 twice_nat=intf.twice_nat,
68 is_add=0)
69
70 self.vapi.nat_ipfix(enable=0, src_port=self.ipfix_src_port,
71 domain_id=self.ipfix_domain_id)
72 self.ipfix_src_port = 4739
73 self.ipfix_domain_id = 1
74
Matus Fabianad1f3e12018-11-28 21:26:34 -080075 self.vapi.syslog_set_filter(SYSLOG_SEVERITY.EMERG)
76
Matus Fabiana6110b62018-06-13 05:39:07 -070077 interfaces = self.vapi.nat44_interface_dump()
78 for intf in interfaces:
79 if intf.is_inside > 1:
80 self.vapi.nat44_interface_add_del_feature(intf.sw_if_index,
81 0,
82 is_add=0)
83 self.vapi.nat44_interface_add_del_feature(intf.sw_if_index,
84 intf.is_inside,
85 is_add=0)
86
87 interfaces = self.vapi.nat44_interface_output_feature_dump()
88 for intf in interfaces:
89 self.vapi.nat44_interface_add_del_output_feature(intf.sw_if_index,
90 intf.is_inside,
91 is_add=0)
92
93 static_mappings = self.vapi.nat44_static_mapping_dump()
94 for sm in static_mappings:
95 self.vapi.nat44_add_del_static_mapping(
96 sm.local_ip_address,
97 sm.external_ip_address,
98 local_port=sm.local_port,
99 external_port=sm.external_port,
100 addr_only=sm.addr_only,
101 vrf_id=sm.vrf_id,
102 protocol=sm.protocol,
103 twice_nat=sm.twice_nat,
104 self_twice_nat=sm.self_twice_nat,
105 out2in_only=sm.out2in_only,
106 tag=sm.tag,
107 external_sw_if_index=sm.external_sw_if_index,
108 is_add=0)
109
110 lb_static_mappings = self.vapi.nat44_lb_static_mapping_dump()
111 for lb_sm in lb_static_mappings:
112 self.vapi.nat44_add_del_lb_static_mapping(
113 lb_sm.external_addr,
114 lb_sm.external_port,
115 lb_sm.protocol,
Matus Fabiana6110b62018-06-13 05:39:07 -0700116 twice_nat=lb_sm.twice_nat,
117 self_twice_nat=lb_sm.self_twice_nat,
118 out2in_only=lb_sm.out2in_only,
119 tag=lb_sm.tag,
120 is_add=0,
121 local_num=0,
122 locals=[])
123
124 identity_mappings = self.vapi.nat44_identity_mapping_dump()
125 for id_m in identity_mappings:
126 self.vapi.nat44_add_del_identity_mapping(
127 addr_only=id_m.addr_only,
128 ip=id_m.ip_address,
129 port=id_m.port,
130 sw_if_index=id_m.sw_if_index,
131 vrf_id=id_m.vrf_id,
132 protocol=id_m.protocol,
133 is_add=0)
134
135 adresses = self.vapi.nat44_address_dump()
136 for addr in adresses:
137 self.vapi.nat44_add_del_address_range(addr.ip_address,
138 addr.ip_address,
139 twice_nat=addr.twice_nat,
140 is_add=0)
141
142 self.vapi.nat_set_reass()
143 self.vapi.nat_set_reass(is_ip6=1)
Matus Fabian68ba8802018-08-08 05:52:47 -0700144 self.verify_no_nat44_user()
Matus Fabian878c6462018-08-23 00:33:35 -0700145 self.vapi.nat_set_timeouts()
Matus Fabian5d28c7a2018-09-04 03:55:45 -0700146 self.vapi.nat_set_addr_and_port_alloc_alg()
Matus Fabianbb4e0222018-09-13 02:36:25 -0700147 self.vapi.nat_set_mss_clamping()
Matus Fabiana6110b62018-06-13 05:39:07 -0700148
149 def nat44_add_static_mapping(self, local_ip, external_ip='0.0.0.0',
150 local_port=0, external_port=0, vrf_id=0,
151 is_add=1, external_sw_if_index=0xFFFFFFFF,
152 proto=0, twice_nat=0, self_twice_nat=0,
153 out2in_only=0, tag=""):
154 """
155 Add/delete NAT44 static mapping
156
157 :param local_ip: Local IP address
158 :param external_ip: External IP address
159 :param local_port: Local port number (Optional)
160 :param external_port: External port number (Optional)
161 :param vrf_id: VRF ID (Default 0)
162 :param is_add: 1 if add, 0 if delete (Default add)
163 :param external_sw_if_index: External interface instead of IP address
164 :param proto: IP protocol (Mandatory if port specified)
165 :param twice_nat: 1 if translate external host address and port
166 :param self_twice_nat: 1 if translate external host address and port
167 whenever external host address equals
168 local address of internal host
169 :param out2in_only: if 1 rule is matching only out2in direction
170 :param tag: Opaque string tag
171 """
172 addr_only = 1
173 if local_port and external_port:
174 addr_only = 0
175 l_ip = socket.inet_pton(socket.AF_INET, local_ip)
176 e_ip = socket.inet_pton(socket.AF_INET, external_ip)
177 self.vapi.nat44_add_del_static_mapping(
178 l_ip,
179 e_ip,
180 external_sw_if_index,
181 local_port,
182 external_port,
183 addr_only,
184 vrf_id,
185 proto,
186 twice_nat,
187 self_twice_nat,
188 out2in_only,
189 tag,
190 is_add)
191
192 def nat44_add_address(self, ip, is_add=1, vrf_id=0xFFFFFFFF, twice_nat=0):
193 """
194 Add/delete NAT44 address
195
196 :param ip: IP address
197 :param is_add: 1 if add, 0 if delete (Default add)
198 :param twice_nat: twice NAT address for extenal hosts
199 """
200 nat_addr = socket.inet_pton(socket.AF_INET, ip)
201 self.vapi.nat44_add_del_address_range(nat_addr, nat_addr, is_add,
202 vrf_id=vrf_id,
203 twice_nat=twice_nat)
204
Juraj Slobodacba69362017-12-19 02:09:32 +0100205 def create_stream_in(self, in_if, out_if, dst_ip=None, ttl=64):
Matus Fabiande886752016-12-07 03:38:19 -0800206 """
207 Create packet stream for inside network
208
209 :param in_if: Inside interface
210 :param out_if: Outside interface
Juraj Slobodacba69362017-12-19 02:09:32 +0100211 :param dst_ip: Destination address
Juraj Slobodab33f4132017-02-08 23:54:21 -0800212 :param ttl: TTL of generated packets
Matus Fabiande886752016-12-07 03:38:19 -0800213 """
Juraj Slobodacba69362017-12-19 02:09:32 +0100214 if dst_ip is None:
215 dst_ip = out_if.remote_ip4
216
Matus Fabiande886752016-12-07 03:38:19 -0800217 pkts = []
218 # TCP
219 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
Juraj Slobodacba69362017-12-19 02:09:32 +0100220 IP(src=in_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Matus Fabian06596c52017-06-06 04:53:28 -0700221 TCP(sport=self.tcp_port_in, dport=20))
Matus Fabiande886752016-12-07 03:38:19 -0800222 pkts.append(p)
223
224 # UDP
225 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
Juraj Slobodacba69362017-12-19 02:09:32 +0100226 IP(src=in_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Matus Fabian06596c52017-06-06 04:53:28 -0700227 UDP(sport=self.udp_port_in, dport=20))
Matus Fabiande886752016-12-07 03:38:19 -0800228 pkts.append(p)
229
230 # ICMP
231 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
Juraj Slobodacba69362017-12-19 02:09:32 +0100232 IP(src=in_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Matus Fabiande886752016-12-07 03:38:19 -0800233 ICMP(id=self.icmp_id_in, type='echo-request'))
234 pkts.append(p)
235
236 return pkts
237
Matus Fabian428dc912017-06-21 06:15:18 -0700238 def compose_ip6(self, ip4, pref, plen):
239 """
240 Compose IPv4-embedded IPv6 addresses
241
242 :param ip4: IPv4 address
243 :param pref: IPv6 prefix
244 :param plen: IPv6 prefix length
245 :returns: IPv4-embedded IPv6 addresses
246 """
247 pref_n = list(socket.inet_pton(socket.AF_INET6, pref))
248 ip4_n = list(socket.inet_pton(socket.AF_INET, ip4))
249 if plen == 32:
250 pref_n[4] = ip4_n[0]
251 pref_n[5] = ip4_n[1]
252 pref_n[6] = ip4_n[2]
253 pref_n[7] = ip4_n[3]
254 elif plen == 40:
255 pref_n[5] = ip4_n[0]
256 pref_n[6] = ip4_n[1]
257 pref_n[7] = ip4_n[2]
258 pref_n[9] = ip4_n[3]
259 elif plen == 48:
260 pref_n[6] = ip4_n[0]
261 pref_n[7] = ip4_n[1]
262 pref_n[9] = ip4_n[2]
263 pref_n[10] = ip4_n[3]
264 elif plen == 56:
265 pref_n[7] = ip4_n[0]
266 pref_n[9] = ip4_n[1]
267 pref_n[10] = ip4_n[2]
268 pref_n[11] = ip4_n[3]
269 elif plen == 64:
270 pref_n[9] = ip4_n[0]
271 pref_n[10] = ip4_n[1]
272 pref_n[11] = ip4_n[2]
273 pref_n[12] = ip4_n[3]
274 elif plen == 96:
275 pref_n[12] = ip4_n[0]
276 pref_n[13] = ip4_n[1]
277 pref_n[14] = ip4_n[2]
278 pref_n[15] = ip4_n[3]
279 return socket.inet_ntop(socket.AF_INET6, ''.join(pref_n))
280
Juraj Slobodacba69362017-12-19 02:09:32 +0100281 def extract_ip4(self, ip6, plen):
282 """
283 Extract IPv4 address embedded in IPv6 addresses
284
285 :param ip6: IPv6 address
286 :param plen: IPv6 prefix length
287 :returns: extracted IPv4 address
288 """
289 ip6_n = list(socket.inet_pton(socket.AF_INET6, ip6))
290 ip4_n = [None] * 4
291 if plen == 32:
292 ip4_n[0] = ip6_n[4]
293 ip4_n[1] = ip6_n[5]
294 ip4_n[2] = ip6_n[6]
295 ip4_n[3] = ip6_n[7]
296 elif plen == 40:
297 ip4_n[0] = ip6_n[5]
298 ip4_n[1] = ip6_n[6]
299 ip4_n[2] = ip6_n[7]
300 ip4_n[3] = ip6_n[9]
301 elif plen == 48:
302 ip4_n[0] = ip6_n[6]
303 ip4_n[1] = ip6_n[7]
304 ip4_n[2] = ip6_n[9]
305 ip4_n[3] = ip6_n[10]
306 elif plen == 56:
307 ip4_n[0] = ip6_n[7]
308 ip4_n[1] = ip6_n[9]
309 ip4_n[2] = ip6_n[10]
310 ip4_n[3] = ip6_n[11]
311 elif plen == 64:
312 ip4_n[0] = ip6_n[9]
313 ip4_n[1] = ip6_n[10]
314 ip4_n[2] = ip6_n[11]
315 ip4_n[3] = ip6_n[12]
316 elif plen == 96:
317 ip4_n[0] = ip6_n[12]
318 ip4_n[1] = ip6_n[13]
319 ip4_n[2] = ip6_n[14]
320 ip4_n[3] = ip6_n[15]
321 return socket.inet_ntop(socket.AF_INET, ''.join(ip4_n))
322
Matus Fabian428dc912017-06-21 06:15:18 -0700323 def create_stream_in_ip6(self, in_if, out_if, hlim=64, pref=None, plen=0):
Matus Fabian06596c52017-06-06 04:53:28 -0700324 """
325 Create IPv6 packet stream for inside network
326
327 :param in_if: Inside interface
328 :param out_if: Outside interface
329 :param ttl: Hop Limit of generated packets
Matus Fabian428dc912017-06-21 06:15:18 -0700330 :param pref: NAT64 prefix
331 :param plen: NAT64 prefix length
Matus Fabian06596c52017-06-06 04:53:28 -0700332 """
333 pkts = []
Matus Fabian428dc912017-06-21 06:15:18 -0700334 if pref is None:
335 dst = ''.join(['64:ff9b::', out_if.remote_ip4])
336 else:
337 dst = self.compose_ip6(out_if.remote_ip4, pref, plen)
338
Matus Fabian06596c52017-06-06 04:53:28 -0700339 # TCP
340 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
341 IPv6(src=in_if.remote_ip6, dst=dst, hlim=hlim) /
342 TCP(sport=self.tcp_port_in, dport=20))
343 pkts.append(p)
344
345 # UDP
346 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
347 IPv6(src=in_if.remote_ip6, dst=dst, hlim=hlim) /
348 UDP(sport=self.udp_port_in, dport=20))
349 pkts.append(p)
350
351 # ICMP
352 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
353 IPv6(src=in_if.remote_ip6, dst=dst, hlim=hlim) /
354 ICMPv6EchoRequest(id=self.icmp_id_in))
355 pkts.append(p)
356
357 return pkts
358
Juraj Sloboda7b929792017-11-23 13:20:48 +0100359 def create_stream_out(self, out_if, dst_ip=None, ttl=64,
360 use_inside_ports=False):
Matus Fabiande886752016-12-07 03:38:19 -0800361 """
362 Create packet stream for outside network
363
364 :param out_if: Outside interface
Matus Fabian2ba92e32017-08-21 07:05:03 -0700365 :param dst_ip: Destination IP address (Default use global NAT address)
Juraj Slobodab33f4132017-02-08 23:54:21 -0800366 :param ttl: TTL of generated packets
Juraj Sloboda7b929792017-11-23 13:20:48 +0100367 :param use_inside_ports: Use inside NAT ports as destination ports
368 instead of outside ports
Matus Fabiande886752016-12-07 03:38:19 -0800369 """
370 if dst_ip is None:
Matus Fabian2ba92e32017-08-21 07:05:03 -0700371 dst_ip = self.nat_addr
Juraj Sloboda7b929792017-11-23 13:20:48 +0100372 if not use_inside_ports:
373 tcp_port = self.tcp_port_out
374 udp_port = self.udp_port_out
375 icmp_id = self.icmp_id_out
376 else:
377 tcp_port = self.tcp_port_in
378 udp_port = self.udp_port_in
379 icmp_id = self.icmp_id_in
Matus Fabiande886752016-12-07 03:38:19 -0800380 pkts = []
381 # TCP
382 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
Juraj Slobodab33f4132017-02-08 23:54:21 -0800383 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Juraj Sloboda7b929792017-11-23 13:20:48 +0100384 TCP(dport=tcp_port, sport=20))
Matus Fabiande886752016-12-07 03:38:19 -0800385 pkts.append(p)
386
387 # UDP
388 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
Juraj Slobodab33f4132017-02-08 23:54:21 -0800389 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Juraj Sloboda7b929792017-11-23 13:20:48 +0100390 UDP(dport=udp_port, sport=20))
Matus Fabiande886752016-12-07 03:38:19 -0800391 pkts.append(p)
392
393 # ICMP
394 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
Juraj Slobodab33f4132017-02-08 23:54:21 -0800395 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Juraj Sloboda7b929792017-11-23 13:20:48 +0100396 ICMP(id=icmp_id, type='echo-reply'))
Matus Fabiande886752016-12-07 03:38:19 -0800397 pkts.append(p)
398
399 return pkts
400
Juraj Slobodacba69362017-12-19 02:09:32 +0100401 def create_stream_out_ip6(self, out_if, src_ip, dst_ip, hl=64):
402 """
403 Create packet stream for outside network
404
405 :param out_if: Outside interface
406 :param dst_ip: Destination IP address (Default use global NAT address)
407 :param hl: HL of generated packets
408 """
409 pkts = []
410 # TCP
411 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
412 IPv6(src=src_ip, dst=dst_ip, hlim=hl) /
413 TCP(dport=self.tcp_port_out, sport=20))
414 pkts.append(p)
415
416 # UDP
417 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
418 IPv6(src=src_ip, dst=dst_ip, hlim=hl) /
419 UDP(dport=self.udp_port_out, sport=20))
420 pkts.append(p)
421
422 # ICMP
423 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
424 IPv6(src=src_ip, dst=dst_ip, hlim=hl) /
425 ICMPv6EchoReply(id=self.icmp_id_out))
426 pkts.append(p)
427
428 return pkts
429
Matus Fabiande886752016-12-07 03:38:19 -0800430 def verify_capture_out(self, capture, nat_ip=None, same_port=False,
Matus Fabian05ca4a32018-09-04 23:45:13 -0700431 dst_ip=None, is_ip6=False):
Matus Fabiande886752016-12-07 03:38:19 -0800432 """
433 Verify captured packets on outside network
434
435 :param capture: Captured packets
Matus Fabian2ba92e32017-08-21 07:05:03 -0700436 :param nat_ip: Translated IP address (Default use global NAT address)
Matus Fabiande886752016-12-07 03:38:19 -0800437 :param same_port: Sorce port number is not translated (Default False)
Matus Fabian06596c52017-06-06 04:53:28 -0700438 :param dst_ip: Destination IP address (Default do not verify)
Juraj Slobodacba69362017-12-19 02:09:32 +0100439 :param is_ip6: If L3 protocol is IPv6 (Default False)
Matus Fabiande886752016-12-07 03:38:19 -0800440 """
Juraj Slobodacba69362017-12-19 02:09:32 +0100441 if is_ip6:
442 IP46 = IPv6
443 ICMP46 = ICMPv6EchoRequest
444 else:
445 IP46 = IP
446 ICMP46 = ICMP
Matus Fabiande886752016-12-07 03:38:19 -0800447 if nat_ip is None:
Matus Fabian2ba92e32017-08-21 07:05:03 -0700448 nat_ip = self.nat_addr
Matus Fabiande886752016-12-07 03:38:19 -0800449 for packet in capture:
450 try:
Juraj Slobodacba69362017-12-19 02:09:32 +0100451 if not is_ip6:
Klement Sekerad81ae412018-05-16 10:52:54 +0200452 self.assert_packet_checksums_valid(packet)
Juraj Slobodacba69362017-12-19 02:09:32 +0100453 self.assertEqual(packet[IP46].src, nat_ip)
Matus Fabian06596c52017-06-06 04:53:28 -0700454 if dst_ip is not None:
Juraj Slobodacba69362017-12-19 02:09:32 +0100455 self.assertEqual(packet[IP46].dst, dst_ip)
Matus Fabiande886752016-12-07 03:38:19 -0800456 if packet.haslayer(TCP):
457 if same_port:
458 self.assertEqual(packet[TCP].sport, self.tcp_port_in)
459 else:
Klement Sekerada505f62017-01-04 12:58:53 +0100460 self.assertNotEqual(
461 packet[TCP].sport, self.tcp_port_in)
Matus Fabiande886752016-12-07 03:38:19 -0800462 self.tcp_port_out = packet[TCP].sport
Klement Sekerad81ae412018-05-16 10:52:54 +0200463 self.assert_packet_checksums_valid(packet)
Matus Fabiande886752016-12-07 03:38:19 -0800464 elif packet.haslayer(UDP):
465 if same_port:
466 self.assertEqual(packet[UDP].sport, self.udp_port_in)
467 else:
Klement Sekerada505f62017-01-04 12:58:53 +0100468 self.assertNotEqual(
469 packet[UDP].sport, self.udp_port_in)
Matus Fabiande886752016-12-07 03:38:19 -0800470 self.udp_port_out = packet[UDP].sport
471 else:
472 if same_port:
Juraj Slobodacba69362017-12-19 02:09:32 +0100473 self.assertEqual(packet[ICMP46].id, self.icmp_id_in)
Matus Fabiande886752016-12-07 03:38:19 -0800474 else:
Juraj Slobodacba69362017-12-19 02:09:32 +0100475 self.assertNotEqual(packet[ICMP46].id, self.icmp_id_in)
476 self.icmp_id_out = packet[ICMP46].id
Klement Sekerad81ae412018-05-16 10:52:54 +0200477 self.assert_packet_checksums_valid(packet)
Matus Fabiande886752016-12-07 03:38:19 -0800478 except:
Klement Sekera9225dee2016-12-12 08:36:58 +0100479 self.logger.error(ppp("Unexpected or invalid packet "
480 "(outside network):", packet))
Matus Fabiande886752016-12-07 03:38:19 -0800481 raise
482
Juraj Slobodacba69362017-12-19 02:09:32 +0100483 def verify_capture_out_ip6(self, capture, nat_ip, same_port=False,
Matus Fabian05ca4a32018-09-04 23:45:13 -0700484 dst_ip=None):
Juraj Slobodacba69362017-12-19 02:09:32 +0100485 """
486 Verify captured packets on outside network
487
488 :param capture: Captured packets
489 :param nat_ip: Translated IP address
490 :param same_port: Sorce port number is not translated (Default False)
Juraj Slobodacba69362017-12-19 02:09:32 +0100491 :param dst_ip: Destination IP address (Default do not verify)
492 """
Matus Fabian05ca4a32018-09-04 23:45:13 -0700493 return self.verify_capture_out(capture, nat_ip, same_port, dst_ip,
494 True)
Juraj Slobodacba69362017-12-19 02:09:32 +0100495
Matus Fabian05ca4a32018-09-04 23:45:13 -0700496 def verify_capture_in(self, capture, in_if):
Matus Fabiande886752016-12-07 03:38:19 -0800497 """
498 Verify captured packets on inside network
499
500 :param capture: Captured packets
501 :param in_if: Inside interface
Matus Fabiande886752016-12-07 03:38:19 -0800502 """
Matus Fabiande886752016-12-07 03:38:19 -0800503 for packet in capture:
504 try:
Klement Sekerad81ae412018-05-16 10:52:54 +0200505 self.assert_packet_checksums_valid(packet)
Matus Fabiande886752016-12-07 03:38:19 -0800506 self.assertEqual(packet[IP].dst, in_if.remote_ip4)
507 if packet.haslayer(TCP):
508 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
509 elif packet.haslayer(UDP):
510 self.assertEqual(packet[UDP].dport, self.udp_port_in)
511 else:
512 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
513 except:
Klement Sekera9225dee2016-12-12 08:36:58 +0100514 self.logger.error(ppp("Unexpected or invalid packet "
515 "(inside network):", packet))
Matus Fabiande886752016-12-07 03:38:19 -0800516 raise
517
Matus Fabian05ca4a32018-09-04 23:45:13 -0700518 def verify_capture_in_ip6(self, capture, src_ip, dst_ip):
Matus Fabian06596c52017-06-06 04:53:28 -0700519 """
520 Verify captured IPv6 packets on inside network
521
522 :param capture: Captured packets
523 :param src_ip: Source IP
524 :param dst_ip: Destination IP address
Matus Fabian06596c52017-06-06 04:53:28 -0700525 """
Matus Fabian06596c52017-06-06 04:53:28 -0700526 for packet in capture:
527 try:
528 self.assertEqual(packet[IPv6].src, src_ip)
529 self.assertEqual(packet[IPv6].dst, dst_ip)
Klement Sekerad81ae412018-05-16 10:52:54 +0200530 self.assert_packet_checksums_valid(packet)
Matus Fabian06596c52017-06-06 04:53:28 -0700531 if packet.haslayer(TCP):
532 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
533 elif packet.haslayer(UDP):
534 self.assertEqual(packet[UDP].dport, self.udp_port_in)
535 else:
536 self.assertEqual(packet[ICMPv6EchoReply].id,
537 self.icmp_id_in)
538 except:
539 self.logger.error(ppp("Unexpected or invalid packet "
540 "(inside network):", packet))
541 raise
542
Matus Fabian675a69c2017-01-18 01:46:01 -0800543 def verify_capture_no_translation(self, capture, ingress_if, egress_if):
544 """
545 Verify captured packet that don't have to be translated
546
547 :param capture: Captured packets
548 :param ingress_if: Ingress interface
549 :param egress_if: Egress interface
550 """
551 for packet in capture:
552 try:
553 self.assertEqual(packet[IP].src, ingress_if.remote_ip4)
554 self.assertEqual(packet[IP].dst, egress_if.remote_ip4)
555 if packet.haslayer(TCP):
556 self.assertEqual(packet[TCP].sport, self.tcp_port_in)
557 elif packet.haslayer(UDP):
558 self.assertEqual(packet[UDP].sport, self.udp_port_in)
559 else:
560 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
561 except:
562 self.logger.error(ppp("Unexpected or invalid packet "
563 "(inside network):", packet))
564 raise
565
Juraj Slobodab33f4132017-02-08 23:54:21 -0800566 def verify_capture_out_with_icmp_errors(self, capture, src_ip=None,
Matus Fabian05ca4a32018-09-04 23:45:13 -0700567 icmp_type=11):
Juraj Slobodab33f4132017-02-08 23:54:21 -0800568 """
569 Verify captured packets with ICMP errors on outside network
570
571 :param capture: Captured packets
572 :param src_ip: Translated IP address or IP address of VPP
Matus Fabian2ba92e32017-08-21 07:05:03 -0700573 (Default use global NAT address)
Juraj Slobodab33f4132017-02-08 23:54:21 -0800574 :param icmp_type: Type of error ICMP packet
575 we are expecting (Default 11)
576 """
577 if src_ip is None:
Matus Fabian2ba92e32017-08-21 07:05:03 -0700578 src_ip = self.nat_addr
Juraj Slobodab33f4132017-02-08 23:54:21 -0800579 for packet in capture:
580 try:
581 self.assertEqual(packet[IP].src, src_ip)
582 self.assertTrue(packet.haslayer(ICMP))
583 icmp = packet[ICMP]
584 self.assertEqual(icmp.type, icmp_type)
585 self.assertTrue(icmp.haslayer(IPerror))
586 inner_ip = icmp[IPerror]
587 if inner_ip.haslayer(TCPerror):
588 self.assertEqual(inner_ip[TCPerror].dport,
589 self.tcp_port_out)
590 elif inner_ip.haslayer(UDPerror):
591 self.assertEqual(inner_ip[UDPerror].dport,
592 self.udp_port_out)
593 else:
594 self.assertEqual(inner_ip[ICMPerror].id, self.icmp_id_out)
595 except:
596 self.logger.error(ppp("Unexpected or invalid packet "
597 "(outside network):", packet))
598 raise
599
Matus Fabian05ca4a32018-09-04 23:45:13 -0700600 def verify_capture_in_with_icmp_errors(self, capture, in_if, icmp_type=11):
Juraj Slobodab33f4132017-02-08 23:54:21 -0800601 """
602 Verify captured packets with ICMP errors on inside network
603
604 :param capture: Captured packets
605 :param in_if: Inside interface
Juraj Slobodab33f4132017-02-08 23:54:21 -0800606 :param icmp_type: Type of error ICMP packet
607 we are expecting (Default 11)
608 """
Juraj Slobodab33f4132017-02-08 23:54:21 -0800609 for packet in capture:
610 try:
611 self.assertEqual(packet[IP].dst, in_if.remote_ip4)
612 self.assertTrue(packet.haslayer(ICMP))
613 icmp = packet[ICMP]
614 self.assertEqual(icmp.type, icmp_type)
615 self.assertTrue(icmp.haslayer(IPerror))
616 inner_ip = icmp[IPerror]
617 if inner_ip.haslayer(TCPerror):
618 self.assertEqual(inner_ip[TCPerror].sport,
619 self.tcp_port_in)
620 elif inner_ip.haslayer(UDPerror):
621 self.assertEqual(inner_ip[UDPerror].sport,
622 self.udp_port_in)
623 else:
624 self.assertEqual(inner_ip[ICMPerror].id, self.icmp_id_in)
625 except:
626 self.logger.error(ppp("Unexpected or invalid packet "
627 "(inside network):", packet))
628 raise
629
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200630 def create_stream_frag(self, src_if, dst, sport, dport, data,
631 proto=IP_PROTOS.tcp, echo_reply=False):
Matus Fabianefcd1e92017-08-15 06:59:19 -0700632 """
633 Create fragmented packet stream
634
635 :param src_if: Source interface
636 :param dst: Destination IPv4 address
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200637 :param sport: Source port
638 :param dport: Destination port
Matus Fabianefcd1e92017-08-15 06:59:19 -0700639 :param data: Payload data
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200640 :param proto: protocol (TCP, UDP, ICMP)
641 :param echo_reply: use echo_reply if protocol is ICMP
Matus Fabianefcd1e92017-08-15 06:59:19 -0700642 :returns: Fragmets
643 """
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200644 if proto == IP_PROTOS.tcp:
645 p = (IP(src=src_if.remote_ip4, dst=dst) /
646 TCP(sport=sport, dport=dport) /
647 Raw(data))
648 p = p.__class__(str(p))
649 chksum = p['TCP'].chksum
650 proto_header = TCP(sport=sport, dport=dport, chksum=chksum)
651 elif proto == IP_PROTOS.udp:
652 proto_header = UDP(sport=sport, dport=dport)
653 elif proto == IP_PROTOS.icmp:
654 if not echo_reply:
655 proto_header = ICMP(id=sport, type='echo-request')
656 else:
657 proto_header = ICMP(id=sport, type='echo-reply')
658 else:
659 raise Exception("Unsupported protocol")
Matus Fabianefcd1e92017-08-15 06:59:19 -0700660 id = random.randint(0, 65535)
Matus Fabianefcd1e92017-08-15 06:59:19 -0700661 pkts = []
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200662 if proto == IP_PROTOS.tcp:
663 raw = Raw(data[0:4])
664 else:
665 raw = Raw(data[0:16])
Matus Fabianefcd1e92017-08-15 06:59:19 -0700666 p = (Ether(src=src_if.remote_mac, dst=src_if.local_mac) /
667 IP(src=src_if.remote_ip4, dst=dst, flags="MF", frag=0, id=id) /
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200668 proto_header /
669 raw)
Matus Fabianefcd1e92017-08-15 06:59:19 -0700670 pkts.append(p)
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200671 if proto == IP_PROTOS.tcp:
672 raw = Raw(data[4:20])
673 else:
674 raw = Raw(data[16:32])
Matus Fabianefcd1e92017-08-15 06:59:19 -0700675 p = (Ether(src=src_if.remote_mac, dst=src_if.local_mac) /
676 IP(src=src_if.remote_ip4, dst=dst, flags="MF", frag=3, id=id,
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200677 proto=proto) /
678 raw)
Matus Fabianefcd1e92017-08-15 06:59:19 -0700679 pkts.append(p)
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200680 if proto == IP_PROTOS.tcp:
681 raw = Raw(data[20:])
682 else:
683 raw = Raw(data[32:])
Matus Fabianefcd1e92017-08-15 06:59:19 -0700684 p = (Ether(src=src_if.remote_mac, dst=src_if.local_mac) /
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200685 IP(src=src_if.remote_ip4, dst=dst, frag=5, proto=proto,
Matus Fabianefcd1e92017-08-15 06:59:19 -0700686 id=id) /
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200687 raw)
Matus Fabianefcd1e92017-08-15 06:59:19 -0700688 pkts.append(p)
689 return pkts
690
691 def create_stream_frag_ip6(self, src_if, dst, sport, dport, data,
692 pref=None, plen=0, frag_size=128):
693 """
694 Create fragmented packet stream
695
696 :param src_if: Source interface
697 :param dst: Destination IPv4 address
698 :param sport: Source TCP port
699 :param dport: Destination TCP port
700 :param data: Payload data
701 :param pref: NAT64 prefix
702 :param plen: NAT64 prefix length
703 :param fragsize: size of fragments
704 :returns: Fragmets
705 """
706 if pref is None:
707 dst_ip6 = ''.join(['64:ff9b::', dst])
708 else:
709 dst_ip6 = self.compose_ip6(dst, pref, plen)
710
711 p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
712 IPv6(src=src_if.remote_ip6, dst=dst_ip6) /
713 IPv6ExtHdrFragment(id=random.randint(0, 65535)) /
714 TCP(sport=sport, dport=dport) /
715 Raw(data))
716
717 return fragment6(p, frag_size)
718
719 def reass_frags_and_verify(self, frags, src, dst):
720 """
721 Reassemble and verify fragmented packet
722
723 :param frags: Captured fragments
724 :param src: Source IPv4 address to verify
725 :param dst: Destination IPv4 address to verify
726
727 :returns: Reassembled IPv4 packet
728 """
729 buffer = StringIO.StringIO()
730 for p in frags:
731 self.assertEqual(p[IP].src, src)
732 self.assertEqual(p[IP].dst, dst)
Klement Sekerad81ae412018-05-16 10:52:54 +0200733 self.assert_ip_checksum_valid(p)
Matus Fabianefcd1e92017-08-15 06:59:19 -0700734 buffer.seek(p[IP].frag * 8)
735 buffer.write(p[IP].payload)
Matus Fabianefcd1e92017-08-15 06:59:19 -0700736 ip = IP(src=frags[0][IP].src, dst=frags[0][IP].dst,
737 proto=frags[0][IP].proto)
738 if ip.proto == IP_PROTOS.tcp:
739 p = (ip / TCP(buffer.getvalue()))
Klement Sekerad81ae412018-05-16 10:52:54 +0200740 self.assert_tcp_checksum_valid(p)
Matus Fabianefcd1e92017-08-15 06:59:19 -0700741 elif ip.proto == IP_PROTOS.udp:
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200742 p = (ip / UDP(buffer.getvalue()[:8]) /
743 Raw(buffer.getvalue()[8:]))
744 elif ip.proto == IP_PROTOS.icmp:
745 p = (ip / ICMP(buffer.getvalue()))
Matus Fabianefcd1e92017-08-15 06:59:19 -0700746 return p
747
748 def reass_frags_and_verify_ip6(self, frags, src, dst):
749 """
750 Reassemble and verify fragmented packet
751
752 :param frags: Captured fragments
753 :param src: Source IPv6 address to verify
754 :param dst: Destination IPv6 address to verify
755
756 :returns: Reassembled IPv6 packet
757 """
758 buffer = StringIO.StringIO()
759 for p in frags:
760 self.assertEqual(p[IPv6].src, src)
761 self.assertEqual(p[IPv6].dst, dst)
762 buffer.seek(p[IPv6ExtHdrFragment].offset * 8)
763 buffer.write(p[IPv6ExtHdrFragment].payload)
764 ip = IPv6(src=frags[0][IPv6].src, dst=frags[0][IPv6].dst,
765 nh=frags[0][IPv6ExtHdrFragment].nh)
766 if ip.nh == IP_PROTOS.tcp:
767 p = (ip / TCP(buffer.getvalue()))
Matus Fabianefcd1e92017-08-15 06:59:19 -0700768 elif ip.nh == IP_PROTOS.udp:
769 p = (ip / UDP(buffer.getvalue()))
Klement Sekerad81ae412018-05-16 10:52:54 +0200770 self.assert_packet_checksums_valid(p)
Matus Fabianefcd1e92017-08-15 06:59:19 -0700771 return p
772
Matus Fabianebdf1902018-05-04 03:57:42 -0700773 def initiate_tcp_session(self, in_if, out_if):
774 """
775 Initiates TCP session
776
777 :param in_if: Inside interface
778 :param out_if: Outside interface
779 """
780 try:
781 # SYN packet in->out
782 p = (Ether(src=in_if.remote_mac, dst=in_if.local_mac) /
783 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4) /
784 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
785 flags="S"))
786 in_if.add_stream(p)
787 self.pg_enable_capture(self.pg_interfaces)
788 self.pg_start()
789 capture = out_if.get_capture(1)
790 p = capture[0]
791 self.tcp_port_out = p[TCP].sport
792
793 # SYN + ACK packet out->in
794 p = (Ether(src=out_if.remote_mac, dst=out_if.local_mac) /
795 IP(src=out_if.remote_ip4, dst=self.nat_addr) /
796 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
797 flags="SA"))
798 out_if.add_stream(p)
799 self.pg_enable_capture(self.pg_interfaces)
800 self.pg_start()
801 in_if.get_capture(1)
802
803 # ACK packet in->out
804 p = (Ether(src=in_if.remote_mac, dst=in_if.local_mac) /
805 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4) /
806 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
807 flags="A"))
808 in_if.add_stream(p)
809 self.pg_enable_capture(self.pg_interfaces)
810 self.pg_start()
811 out_if.get_capture(1)
812
813 except:
814 self.logger.error("TCP 3 way handshake failed")
815 raise
816
Matus Fabianeea28d72017-01-13 04:15:54 -0800817 def verify_ipfix_nat44_ses(self, data):
818 """
819 Verify IPFIX NAT44 session create/delete event
820
821 :param data: Decoded IPFIX data records
822 """
823 nat44_ses_create_num = 0
824 nat44_ses_delete_num = 0
825 self.assertEqual(6, len(data))
826 for record in data:
827 # natEvent
828 self.assertIn(ord(record[230]), [4, 5])
829 if ord(record[230]) == 4:
830 nat44_ses_create_num += 1
831 else:
832 nat44_ses_delete_num += 1
833 # sourceIPv4Address
834 self.assertEqual(self.pg0.remote_ip4n, record[8])
835 # postNATSourceIPv4Address
Matus Fabian2ba92e32017-08-21 07:05:03 -0700836 self.assertEqual(socket.inet_pton(socket.AF_INET, self.nat_addr),
Matus Fabianeea28d72017-01-13 04:15:54 -0800837 record[225])
838 # ingressVRFID
839 self.assertEqual(struct.pack("!I", 0), record[234])
840 # protocolIdentifier/sourceTransportPort/postNAPTSourceTransportPort
841 if IP_PROTOS.icmp == ord(record[4]):
842 self.assertEqual(struct.pack("!H", self.icmp_id_in), record[7])
843 self.assertEqual(struct.pack("!H", self.icmp_id_out),
844 record[227])
845 elif IP_PROTOS.tcp == ord(record[4]):
846 self.assertEqual(struct.pack("!H", self.tcp_port_in),
847 record[7])
848 self.assertEqual(struct.pack("!H", self.tcp_port_out),
849 record[227])
850 elif IP_PROTOS.udp == ord(record[4]):
851 self.assertEqual(struct.pack("!H", self.udp_port_in),
852 record[7])
853 self.assertEqual(struct.pack("!H", self.udp_port_out),
854 record[227])
855 else:
856 self.fail("Invalid protocol")
857 self.assertEqual(3, nat44_ses_create_num)
858 self.assertEqual(3, nat44_ses_delete_num)
859
860 def verify_ipfix_addr_exhausted(self, data):
861 """
862 Verify IPFIX NAT addresses event
863
864 :param data: Decoded IPFIX data records
865 """
866 self.assertEqual(1, len(data))
867 record = data[0]
868 # natEvent
869 self.assertEqual(ord(record[230]), 3)
870 # natPoolID
871 self.assertEqual(struct.pack("!I", 0), record[283])
872
Matus Fabiana431ad12018-01-04 04:03:14 -0800873 def verify_ipfix_max_sessions(self, data, limit):
874 """
875 Verify IPFIX maximum session entries exceeded event
876
877 :param data: Decoded IPFIX data records
878 :param limit: Number of maximum session entries that can be created.
879 """
880 self.assertEqual(1, len(data))
881 record = data[0]
882 # natEvent
883 self.assertEqual(ord(record[230]), 13)
884 # natQuotaExceededEvent
885 self.assertEqual(struct.pack("I", 1), record[466])
886 # maxSessionEntries
887 self.assertEqual(struct.pack("I", limit), record[471])
888
889 def verify_ipfix_max_bibs(self, data, limit):
890 """
891 Verify IPFIX maximum BIB entries exceeded event
892
893 :param data: Decoded IPFIX data records
894 :param limit: Number of maximum BIB entries that can be created.
895 """
896 self.assertEqual(1, len(data))
897 record = data[0]
898 # natEvent
899 self.assertEqual(ord(record[230]), 13)
900 # natQuotaExceededEvent
901 self.assertEqual(struct.pack("I", 2), record[466])
902 # maxBIBEntries
903 self.assertEqual(struct.pack("I", limit), record[472])
904
905 def verify_ipfix_max_fragments_ip6(self, data, limit, src_addr):
906 """
907 Verify IPFIX maximum IPv6 fragments pending reassembly exceeded event
908
909 :param data: Decoded IPFIX data records
910 :param limit: Number of maximum fragments pending reassembly
911 :param src_addr: IPv6 source address
912 """
913 self.assertEqual(1, len(data))
914 record = data[0]
915 # natEvent
916 self.assertEqual(ord(record[230]), 13)
917 # natQuotaExceededEvent
918 self.assertEqual(struct.pack("I", 5), record[466])
919 # maxFragmentsPendingReassembly
920 self.assertEqual(struct.pack("I", limit), record[475])
921 # sourceIPv6Address
922 self.assertEqual(src_addr, record[27])
923
924 def verify_ipfix_max_fragments_ip4(self, data, limit, src_addr):
925 """
926 Verify IPFIX maximum IPv4 fragments pending reassembly exceeded event
927
928 :param data: Decoded IPFIX data records
929 :param limit: Number of maximum fragments pending reassembly
930 :param src_addr: IPv4 source address
931 """
932 self.assertEqual(1, len(data))
933 record = data[0]
934 # natEvent
935 self.assertEqual(ord(record[230]), 13)
936 # natQuotaExceededEvent
937 self.assertEqual(struct.pack("I", 5), record[466])
938 # maxFragmentsPendingReassembly
939 self.assertEqual(struct.pack("I", limit), record[475])
940 # sourceIPv4Address
941 self.assertEqual(src_addr, record[8])
942
943 def verify_ipfix_bib(self, data, is_create, src_addr):
944 """
945 Verify IPFIX NAT64 BIB create and delete events
946
947 :param data: Decoded IPFIX data records
948 :param is_create: Create event if nonzero value otherwise delete event
949 :param src_addr: IPv6 source address
950 """
951 self.assertEqual(1, len(data))
952 record = data[0]
953 # natEvent
954 if is_create:
955 self.assertEqual(ord(record[230]), 10)
956 else:
957 self.assertEqual(ord(record[230]), 11)
958 # sourceIPv6Address
959 self.assertEqual(src_addr, record[27])
960 # postNATSourceIPv4Address
961 self.assertEqual(self.nat_addr_n, record[225])
962 # protocolIdentifier
963 self.assertEqual(IP_PROTOS.tcp, ord(record[4]))
964 # ingressVRFID
965 self.assertEqual(struct.pack("!I", 0), record[234])
966 # sourceTransportPort
967 self.assertEqual(struct.pack("!H", self.tcp_port_in), record[7])
968 # postNAPTSourceTransportPort
969 self.assertEqual(struct.pack("!H", self.tcp_port_out), record[227])
970
971 def verify_ipfix_nat64_ses(self, data, is_create, src_addr, dst_addr,
972 dst_port):
973 """
974 Verify IPFIX NAT64 session create and delete events
975
976 :param data: Decoded IPFIX data records
977 :param is_create: Create event if nonzero value otherwise delete event
978 :param src_addr: IPv6 source address
979 :param dst_addr: IPv4 destination address
980 :param dst_port: destination TCP port
981 """
982 self.assertEqual(1, len(data))
983 record = data[0]
984 # natEvent
985 if is_create:
986 self.assertEqual(ord(record[230]), 6)
987 else:
988 self.assertEqual(ord(record[230]), 7)
989 # sourceIPv6Address
990 self.assertEqual(src_addr, record[27])
991 # destinationIPv6Address
992 self.assertEqual(socket.inet_pton(socket.AF_INET6,
993 self.compose_ip6(dst_addr,
994 '64:ff9b::',
995 96)),
996 record[28])
997 # postNATSourceIPv4Address
998 self.assertEqual(self.nat_addr_n, record[225])
999 # postNATDestinationIPv4Address
1000 self.assertEqual(socket.inet_pton(socket.AF_INET, dst_addr),
1001 record[226])
1002 # protocolIdentifier
1003 self.assertEqual(IP_PROTOS.tcp, ord(record[4]))
1004 # ingressVRFID
1005 self.assertEqual(struct.pack("!I", 0), record[234])
1006 # sourceTransportPort
1007 self.assertEqual(struct.pack("!H", self.tcp_port_in), record[7])
1008 # postNAPTSourceTransportPort
1009 self.assertEqual(struct.pack("!H", self.tcp_port_out), record[227])
1010 # destinationTransportPort
1011 self.assertEqual(struct.pack("!H", dst_port), record[11])
1012 # postNAPTDestinationTransportPort
1013 self.assertEqual(struct.pack("!H", dst_port), record[228])
1014
Matus Fabian68ba8802018-08-08 05:52:47 -07001015 def verify_no_nat44_user(self):
1016 """ Verify that there is no NAT44 user """
1017 users = self.vapi.nat44_user_dump()
1018 self.assertEqual(len(users), 0)
1019
Matus Fabian878c6462018-08-23 00:33:35 -07001020 def verify_ipfix_max_entries_per_user(self, data, limit, src_addr):
1021 """
1022 Verify IPFIX maximum entries per user exceeded event
1023
1024 :param data: Decoded IPFIX data records
1025 :param limit: Number of maximum entries per user
1026 :param src_addr: IPv4 source address
1027 """
1028 self.assertEqual(1, len(data))
1029 record = data[0]
1030 # natEvent
1031 self.assertEqual(ord(record[230]), 13)
1032 # natQuotaExceededEvent
1033 self.assertEqual(struct.pack("I", 3), record[466])
1034 # maxEntriesPerUser
1035 self.assertEqual(struct.pack("I", limit), record[473])
1036 # sourceIPv4Address
1037 self.assertEqual(src_addr, record[8])
1038
Matus Fabianad1f3e12018-11-28 21:26:34 -08001039 def verify_syslog_apmap(self, data, is_add=True):
1040 message = data.decode('utf-8')
1041 try:
1042 message = SyslogMessage.parse(message)
1043 self.assertEqual(message.severity, SyslogSeverity.info)
1044 self.assertEqual(message.appname, 'NAT')
1045 self.assertEqual(message.msgid, 'APMADD' if is_add else 'APMDEL')
1046 sd_params = message.sd.get('napmap')
1047 self.assertTrue(sd_params is not None)
1048 self.assertEqual(sd_params.get('IATYP'), 'IPv4')
1049 self.assertEqual(sd_params.get('ISADDR'), self.pg0.remote_ip4)
1050 self.assertEqual(sd_params.get('ISPORT'), "%d" % self.tcp_port_in)
1051 self.assertEqual(sd_params.get('XATYP'), 'IPv4')
1052 self.assertEqual(sd_params.get('XSADDR'), self.nat_addr)
1053 self.assertEqual(sd_params.get('XSPORT'), "%d" % self.tcp_port_out)
1054 self.assertEqual(sd_params.get('PROTO'), "%d" % IP_PROTOS.tcp)
1055 self.assertTrue(sd_params.get('SSUBIX') is not None)
1056 self.assertEqual(sd_params.get('SVLAN'), '0')
1057 except ParseError as e:
1058 self.logger.error(e)
1059
1060 def verify_syslog_sess(self, data, is_add=True, is_ip6=False):
1061 message = data.decode('utf-8')
1062 try:
1063 message = SyslogMessage.parse(message)
1064 self.assertEqual(message.severity, SyslogSeverity.info)
1065 self.assertEqual(message.appname, 'NAT')
1066 self.assertEqual(message.msgid, 'SADD' if is_add else 'SDEL')
1067 sd_params = message.sd.get('nsess')
1068 self.assertTrue(sd_params is not None)
1069 if is_ip6:
1070 self.assertEqual(sd_params.get('IATYP'), 'IPv6')
1071 self.assertEqual(sd_params.get('ISADDR'), self.pg0.remote_ip6)
1072 else:
1073 self.assertEqual(sd_params.get('IATYP'), 'IPv4')
1074 self.assertEqual(sd_params.get('ISADDR'), self.pg0.remote_ip4)
1075 self.assertTrue(sd_params.get('SSUBIX') is not None)
1076 self.assertEqual(sd_params.get('ISPORT'), "%d" % self.tcp_port_in)
1077 self.assertEqual(sd_params.get('XATYP'), 'IPv4')
1078 self.assertEqual(sd_params.get('XSADDR'), self.nat_addr)
1079 self.assertEqual(sd_params.get('XSPORT'), "%d" % self.tcp_port_out)
1080 self.assertEqual(sd_params.get('PROTO'), "%d" % IP_PROTOS.tcp)
1081 self.assertEqual(sd_params.get('SVLAN'), '0')
1082 self.assertEqual(sd_params.get('XDADDR'), self.pg1.remote_ip4)
1083 self.assertEqual(sd_params.get('XDPORT'),
1084 "%d" % self.tcp_external_port)
1085 except ParseError as e:
1086 self.logger.error(e)
1087
Matus Fabianbb4e0222018-09-13 02:36:25 -07001088 def verify_mss_value(self, pkt, mss):
1089 """
1090 Verify TCP MSS value
1091
1092 :param pkt:
1093 :param mss:
1094 """
1095 if not pkt.haslayer(IP) or not pkt.haslayer(TCP):
1096 raise TypeError("Not a TCP/IP packet")
1097
1098 for option in pkt[TCP].options:
1099 if option[0] == 'MSS':
1100 self.assertEqual(option[1], mss)
1101 self.assert_tcp_checksum_valid(pkt)
1102
Juraj Slobodafe0aa762018-07-23 12:22:54 +02001103 @staticmethod
1104 def proto2layer(proto):
1105 if proto == IP_PROTOS.tcp:
1106 return TCP
1107 elif proto == IP_PROTOS.udp:
1108 return UDP
1109 elif proto == IP_PROTOS.icmp:
1110 return ICMP
1111 else:
1112 raise Exception("Unsupported protocol")
1113
1114 def frag_in_order(self, proto=IP_PROTOS.tcp, dont_translate=False):
1115 layer = self.proto2layer(proto)
1116
1117 if proto == IP_PROTOS.tcp:
1118 data = "A" * 4 + "B" * 16 + "C" * 3
1119 else:
1120 data = "A" * 16 + "B" * 16 + "C" * 3
1121 self.port_in = random.randint(1025, 65535)
1122
1123 reass = self.vapi.nat_reass_dump()
1124 reass_n_start = len(reass)
1125
1126 # in2out
1127 pkts = self.create_stream_frag(self.pg0,
1128 self.pg1.remote_ip4,
1129 self.port_in,
1130 20,
1131 data,
1132 proto)
1133 self.pg0.add_stream(pkts)
1134 self.pg_enable_capture(self.pg_interfaces)
1135 self.pg_start()
1136 frags = self.pg1.get_capture(len(pkts))
1137 if not dont_translate:
1138 p = self.reass_frags_and_verify(frags,
1139 self.nat_addr,
1140 self.pg1.remote_ip4)
1141 else:
1142 p = self.reass_frags_and_verify(frags,
1143 self.pg0.remote_ip4,
1144 self.pg1.remote_ip4)
1145 if proto != IP_PROTOS.icmp:
1146 if not dont_translate:
1147 self.assertEqual(p[layer].dport, 20)
1148 self.assertNotEqual(p[layer].sport, self.port_in)
1149 else:
1150 self.assertEqual(p[layer].sport, self.port_in)
1151 else:
1152 if not dont_translate:
1153 self.assertNotEqual(p[layer].id, self.port_in)
1154 else:
1155 self.assertEqual(p[layer].id, self.port_in)
1156 self.assertEqual(data, p[Raw].load)
1157
1158 # out2in
1159 if not dont_translate:
1160 dst_addr = self.nat_addr
1161 else:
1162 dst_addr = self.pg0.remote_ip4
1163 if proto != IP_PROTOS.icmp:
1164 sport = 20
1165 dport = p[layer].sport
1166 else:
1167 sport = p[layer].id
1168 dport = 0
1169 pkts = self.create_stream_frag(self.pg1,
1170 dst_addr,
1171 sport,
1172 dport,
1173 data,
1174 proto,
1175 echo_reply=True)
1176 self.pg1.add_stream(pkts)
1177 self.pg_enable_capture(self.pg_interfaces)
1178 self.pg_start()
1179 frags = self.pg0.get_capture(len(pkts))
1180 p = self.reass_frags_and_verify(frags,
1181 self.pg1.remote_ip4,
1182 self.pg0.remote_ip4)
1183 if proto != IP_PROTOS.icmp:
1184 self.assertEqual(p[layer].sport, 20)
1185 self.assertEqual(p[layer].dport, self.port_in)
1186 else:
1187 self.assertEqual(p[layer].id, self.port_in)
1188 self.assertEqual(data, p[Raw].load)
1189
1190 reass = self.vapi.nat_reass_dump()
1191 reass_n_end = len(reass)
1192
1193 self.assertEqual(reass_n_end - reass_n_start, 2)
1194
1195 def frag_in_order_in_plus_out(self, proto=IP_PROTOS.tcp):
1196 layer = self.proto2layer(proto)
1197
1198 if proto == IP_PROTOS.tcp:
1199 data = "A" * 4 + "B" * 16 + "C" * 3
1200 else:
1201 data = "A" * 16 + "B" * 16 + "C" * 3
1202 self.port_in = random.randint(1025, 65535)
1203
1204 for i in range(2):
1205 reass = self.vapi.nat_reass_dump()
1206 reass_n_start = len(reass)
1207
1208 # out2in
1209 pkts = self.create_stream_frag(self.pg0,
1210 self.server_out_addr,
1211 self.port_in,
1212 self.server_out_port,
1213 data,
1214 proto)
1215 self.pg0.add_stream(pkts)
1216 self.pg_enable_capture(self.pg_interfaces)
1217 self.pg_start()
1218 frags = self.pg1.get_capture(len(pkts))
1219 p = self.reass_frags_and_verify(frags,
1220 self.pg0.remote_ip4,
1221 self.server_in_addr)
1222 if proto != IP_PROTOS.icmp:
1223 self.assertEqual(p[layer].sport, self.port_in)
1224 self.assertEqual(p[layer].dport, self.server_in_port)
1225 else:
1226 self.assertEqual(p[layer].id, self.port_in)
1227 self.assertEqual(data, p[Raw].load)
1228
1229 # in2out
1230 if proto != IP_PROTOS.icmp:
1231 pkts = self.create_stream_frag(self.pg1,
1232 self.pg0.remote_ip4,
1233 self.server_in_port,
1234 p[layer].sport,
1235 data,
1236 proto)
1237 else:
1238 pkts = self.create_stream_frag(self.pg1,
1239 self.pg0.remote_ip4,
1240 p[layer].id,
1241 0,
1242 data,
1243 proto,
1244 echo_reply=True)
1245 self.pg1.add_stream(pkts)
1246 self.pg_enable_capture(self.pg_interfaces)
1247 self.pg_start()
1248 frags = self.pg0.get_capture(len(pkts))
1249 p = self.reass_frags_and_verify(frags,
1250 self.server_out_addr,
1251 self.pg0.remote_ip4)
1252 if proto != IP_PROTOS.icmp:
1253 self.assertEqual(p[layer].sport, self.server_out_port)
1254 self.assertEqual(p[layer].dport, self.port_in)
1255 else:
1256 self.assertEqual(p[layer].id, self.port_in)
1257 self.assertEqual(data, p[Raw].load)
1258
1259 reass = self.vapi.nat_reass_dump()
1260 reass_n_end = len(reass)
1261
1262 self.assertEqual(reass_n_end - reass_n_start, 2)
1263
1264 def reass_hairpinning(self, proto=IP_PROTOS.tcp):
1265 layer = self.proto2layer(proto)
1266
1267 if proto == IP_PROTOS.tcp:
1268 data = "A" * 4 + "B" * 16 + "C" * 3
1269 else:
1270 data = "A" * 16 + "B" * 16 + "C" * 3
1271
1272 # send packet from host to server
1273 pkts = self.create_stream_frag(self.pg0,
1274 self.nat_addr,
1275 self.host_in_port,
1276 self.server_out_port,
1277 data,
1278 proto)
1279 self.pg0.add_stream(pkts)
1280 self.pg_enable_capture(self.pg_interfaces)
1281 self.pg_start()
1282 frags = self.pg0.get_capture(len(pkts))
1283 p = self.reass_frags_and_verify(frags,
1284 self.nat_addr,
1285 self.server.ip4)
1286 if proto != IP_PROTOS.icmp:
1287 self.assertNotEqual(p[layer].sport, self.host_in_port)
1288 self.assertEqual(p[layer].dport, self.server_in_port)
1289 else:
1290 self.assertNotEqual(p[layer].id, self.host_in_port)
1291 self.assertEqual(data, p[Raw].load)
1292
1293 def frag_out_of_order(self, proto=IP_PROTOS.tcp, dont_translate=False):
1294 layer = self.proto2layer(proto)
1295
1296 if proto == IP_PROTOS.tcp:
1297 data = "A" * 4 + "B" * 16 + "C" * 3
1298 else:
1299 data = "A" * 16 + "B" * 16 + "C" * 3
1300 self.port_in = random.randint(1025, 65535)
1301
1302 for i in range(2):
1303 # in2out
1304 pkts = self.create_stream_frag(self.pg0,
1305 self.pg1.remote_ip4,
1306 self.port_in,
1307 20,
1308 data,
1309 proto)
1310 pkts.reverse()
1311 self.pg0.add_stream(pkts)
1312 self.pg_enable_capture(self.pg_interfaces)
1313 self.pg_start()
1314 frags = self.pg1.get_capture(len(pkts))
1315 if not dont_translate:
1316 p = self.reass_frags_and_verify(frags,
1317 self.nat_addr,
1318 self.pg1.remote_ip4)
1319 else:
1320 p = self.reass_frags_and_verify(frags,
1321 self.pg0.remote_ip4,
1322 self.pg1.remote_ip4)
1323 if proto != IP_PROTOS.icmp:
1324 if not dont_translate:
1325 self.assertEqual(p[layer].dport, 20)
1326 self.assertNotEqual(p[layer].sport, self.port_in)
1327 else:
1328 self.assertEqual(p[layer].sport, self.port_in)
1329 else:
1330 if not dont_translate:
1331 self.assertNotEqual(p[layer].id, self.port_in)
1332 else:
1333 self.assertEqual(p[layer].id, self.port_in)
1334 self.assertEqual(data, p[Raw].load)
1335
1336 # out2in
1337 if not dont_translate:
1338 dst_addr = self.nat_addr
1339 else:
1340 dst_addr = self.pg0.remote_ip4
1341 if proto != IP_PROTOS.icmp:
1342 sport = 20
1343 dport = p[layer].sport
1344 else:
1345 sport = p[layer].id
1346 dport = 0
1347 pkts = self.create_stream_frag(self.pg1,
1348 dst_addr,
1349 sport,
1350 dport,
1351 data,
1352 proto,
1353 echo_reply=True)
1354 pkts.reverse()
1355 self.pg1.add_stream(pkts)
1356 self.pg_enable_capture(self.pg_interfaces)
1357 self.pg_start()
1358 frags = self.pg0.get_capture(len(pkts))
1359 p = self.reass_frags_and_verify(frags,
1360 self.pg1.remote_ip4,
1361 self.pg0.remote_ip4)
1362 if proto != IP_PROTOS.icmp:
1363 self.assertEqual(p[layer].sport, 20)
1364 self.assertEqual(p[layer].dport, self.port_in)
1365 else:
1366 self.assertEqual(p[layer].id, self.port_in)
1367 self.assertEqual(data, p[Raw].load)
1368
1369 def frag_out_of_order_in_plus_out(self, proto=IP_PROTOS.tcp):
1370 layer = self.proto2layer(proto)
1371
1372 if proto == IP_PROTOS.tcp:
1373 data = "A" * 4 + "B" * 16 + "C" * 3
1374 else:
1375 data = "A" * 16 + "B" * 16 + "C" * 3
1376 self.port_in = random.randint(1025, 65535)
1377
1378 for i in range(2):
1379 # out2in
1380 pkts = self.create_stream_frag(self.pg0,
1381 self.server_out_addr,
1382 self.port_in,
1383 self.server_out_port,
1384 data,
1385 proto)
1386 pkts.reverse()
1387 self.pg0.add_stream(pkts)
1388 self.pg_enable_capture(self.pg_interfaces)
1389 self.pg_start()
1390 frags = self.pg1.get_capture(len(pkts))
1391 p = self.reass_frags_and_verify(frags,
1392 self.pg0.remote_ip4,
1393 self.server_in_addr)
1394 if proto != IP_PROTOS.icmp:
1395 self.assertEqual(p[layer].dport, self.server_in_port)
1396 self.assertEqual(p[layer].sport, self.port_in)
1397 self.assertEqual(p[layer].dport, self.server_in_port)
1398 else:
1399 self.assertEqual(p[layer].id, self.port_in)
1400 self.assertEqual(data, p[Raw].load)
1401
1402 # in2out
1403 if proto != IP_PROTOS.icmp:
1404 pkts = self.create_stream_frag(self.pg1,
1405 self.pg0.remote_ip4,
1406 self.server_in_port,
1407 p[layer].sport,
1408 data,
1409 proto)
1410 else:
1411 pkts = self.create_stream_frag(self.pg1,
1412 self.pg0.remote_ip4,
1413 p[layer].id,
1414 0,
1415 data,
1416 proto,
1417 echo_reply=True)
1418 pkts.reverse()
1419 self.pg1.add_stream(pkts)
1420 self.pg_enable_capture(self.pg_interfaces)
1421 self.pg_start()
1422 frags = self.pg0.get_capture(len(pkts))
1423 p = self.reass_frags_and_verify(frags,
1424 self.server_out_addr,
1425 self.pg0.remote_ip4)
1426 if proto != IP_PROTOS.icmp:
1427 self.assertEqual(p[layer].sport, self.server_out_port)
1428 self.assertEqual(p[layer].dport, self.port_in)
1429 else:
1430 self.assertEqual(p[layer].id, self.port_in)
1431 self.assertEqual(data, p[Raw].load)
1432
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001433
Matus Fabian2ba92e32017-08-21 07:05:03 -07001434class TestNAT44(MethodHolder):
1435 """ NAT44 Test Cases """
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001436
1437 @classmethod
1438 def setUpClass(cls):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001439 super(TestNAT44, cls).setUpClass()
Matus Fabian229c1aa2018-05-28 04:09:52 -07001440 cls.vapi.cli("set log class nat level debug")
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001441
1442 try:
1443 cls.tcp_port_in = 6303
1444 cls.tcp_port_out = 6303
1445 cls.udp_port_in = 6304
1446 cls.udp_port_out = 6304
1447 cls.icmp_id_in = 6305
1448 cls.icmp_id_out = 6305
Matus Fabian2ba92e32017-08-21 07:05:03 -07001449 cls.nat_addr = '10.0.0.3'
Juraj Sloboda7b929792017-11-23 13:20:48 +01001450 cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
Matus Fabian6631e9c2017-05-24 01:52:20 -07001451 cls.ipfix_src_port = 4739
1452 cls.ipfix_domain_id = 1
Matus Fabianebdf1902018-05-04 03:57:42 -07001453 cls.tcp_external_port = 80
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001454
Matus Fabian36ea2d62017-10-24 04:13:49 -07001455 cls.create_pg_interfaces(range(10))
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001456 cls.interfaces = list(cls.pg_interfaces[0:4])
1457
1458 for i in cls.interfaces:
1459 i.admin_up()
1460 i.config_ip4()
1461 i.resolve_arp()
1462
Matus Fabian6fa74c62017-06-05 05:55:48 -07001463 cls.pg0.generate_remote_hosts(3)
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001464 cls.pg0.configure_ipv4_neighbors()
1465
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02001466 cls.pg1.generate_remote_hosts(1)
1467 cls.pg1.configure_ipv4_neighbors()
1468
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001469 cls.overlapping_interfaces = list(list(cls.pg_interfaces[4:7]))
Neale Ranns15002542017-09-10 04:39:11 -07001470 cls.vapi.ip_table_add_del(10, is_add=1)
1471 cls.vapi.ip_table_add_del(20, is_add=1)
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001472
1473 cls.pg4._local_ip4 = "172.16.255.1"
1474 cls.pg4._local_ip4n = socket.inet_pton(socket.AF_INET, i.local_ip4)
1475 cls.pg4._remote_hosts[0]._ip4 = "172.16.255.2"
1476 cls.pg4.set_table_ip4(10)
Matus Fabian69126282017-08-14 23:39:58 -07001477 cls.pg5._local_ip4 = "172.17.255.3"
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001478 cls.pg5._local_ip4n = socket.inet_pton(socket.AF_INET, i.local_ip4)
Matus Fabian69126282017-08-14 23:39:58 -07001479 cls.pg5._remote_hosts[0]._ip4 = "172.17.255.4"
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001480 cls.pg5.set_table_ip4(10)
1481 cls.pg6._local_ip4 = "172.16.255.1"
1482 cls.pg6._local_ip4n = socket.inet_pton(socket.AF_INET, i.local_ip4)
1483 cls.pg6._remote_hosts[0]._ip4 = "172.16.255.2"
1484 cls.pg6.set_table_ip4(20)
1485 for i in cls.overlapping_interfaces:
1486 i.config_ip4()
1487 i.admin_up()
1488 i.resolve_arp()
1489
1490 cls.pg7.admin_up()
Martin Gálik406eb1d2017-05-04 04:35:04 -07001491 cls.pg8.admin_up()
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001492
Matus Fabian36ea2d62017-10-24 04:13:49 -07001493 cls.pg9.generate_remote_hosts(2)
1494 cls.pg9.config_ip4()
1495 ip_addr_n = socket.inet_pton(socket.AF_INET, "10.0.0.1")
1496 cls.vapi.sw_interface_add_del_address(cls.pg9.sw_if_index,
1497 ip_addr_n,
1498 24)
1499 cls.pg9.admin_up()
1500 cls.pg9.resolve_arp()
1501 cls.pg9._remote_hosts[1]._ip4 = cls.pg9._remote_hosts[0]._ip4
1502 cls.pg4._remote_ip4 = cls.pg9._remote_hosts[0]._ip4 = "10.0.0.2"
1503 cls.pg9.resolve_arp()
1504
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001505 except Exception:
Matus Fabian2ba92e32017-08-21 07:05:03 -07001506 super(TestNAT44, cls).tearDownClass()
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001507 raise
1508
Matus Fabiande886752016-12-07 03:38:19 -08001509 def test_dynamic(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001510 """ NAT44 dynamic translation test """
Matus Fabiande886752016-12-07 03:38:19 -08001511
Matus Fabian2ba92e32017-08-21 07:05:03 -07001512 self.nat44_add_address(self.nat_addr)
1513 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1514 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1515 is_inside=0)
Matus Fabiande886752016-12-07 03:38:19 -08001516
1517 # in2out
1518 pkts = self.create_stream_in(self.pg0, self.pg1)
1519 self.pg0.add_stream(pkts)
1520 self.pg_enable_capture(self.pg_interfaces)
1521 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001522 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001523 self.verify_capture_out(capture)
1524
1525 # out2in
1526 pkts = self.create_stream_out(self.pg1)
1527 self.pg1.add_stream(pkts)
1528 self.pg_enable_capture(self.pg_interfaces)
1529 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001530 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001531 self.verify_capture_in(capture, self.pg0)
1532
Juraj Slobodab33f4132017-02-08 23:54:21 -08001533 def test_dynamic_icmp_errors_in2out_ttl_1(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001534 """ NAT44 handling of client packets with TTL=1 """
Juraj Slobodab33f4132017-02-08 23:54:21 -08001535
Matus Fabian2ba92e32017-08-21 07:05:03 -07001536 self.nat44_add_address(self.nat_addr)
1537 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1538 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1539 is_inside=0)
Juraj Slobodab33f4132017-02-08 23:54:21 -08001540
1541 # Client side - generate traffic
1542 pkts = self.create_stream_in(self.pg0, self.pg1, ttl=1)
1543 self.pg0.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_1(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001552 """ NAT44 handling of server packets with TTL=1 """
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=1)
1569 self.pg1.add_stream(pkts)
1570 self.pg_enable_capture(self.pg_interfaces)
1571 self.pg_start()
1572
1573 # Server side - verify ICMP type 11 packets
1574 capture = self.pg1.get_capture(len(pkts))
1575 self.verify_capture_out_with_icmp_errors(capture,
1576 src_ip=self.pg1.local_ip4)
1577
1578 def test_dynamic_icmp_errors_in2out_ttl_2(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001579 """ NAT44 handling of error responses to client packets with TTL=2 """
Juraj Slobodab33f4132017-02-08 23:54:21 -08001580
Matus Fabian2ba92e32017-08-21 07:05:03 -07001581 self.nat44_add_address(self.nat_addr)
1582 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1583 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1584 is_inside=0)
Juraj Slobodab33f4132017-02-08 23:54:21 -08001585
1586 # Client side - generate traffic
1587 pkts = self.create_stream_in(self.pg0, self.pg1, ttl=2)
1588 self.pg0.add_stream(pkts)
1589 self.pg_enable_capture(self.pg_interfaces)
1590 self.pg_start()
1591
1592 # Server side - simulate ICMP type 11 response
1593 capture = self.pg1.get_capture(len(pkts))
1594 pkts = [Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07001595 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Juraj Slobodab33f4132017-02-08 23:54:21 -08001596 ICMP(type=11) / packet[IP] for packet in capture]
1597 self.pg1.add_stream(pkts)
1598 self.pg_enable_capture(self.pg_interfaces)
1599 self.pg_start()
1600
1601 # Client side - verify ICMP type 11 packets
1602 capture = self.pg0.get_capture(len(pkts))
1603 self.verify_capture_in_with_icmp_errors(capture, self.pg0)
1604
1605 def test_dynamic_icmp_errors_out2in_ttl_2(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001606 """ NAT44 handling of error responses to server packets with TTL=2 """
Juraj Slobodab33f4132017-02-08 23:54:21 -08001607
Matus Fabian2ba92e32017-08-21 07:05:03 -07001608 self.nat44_add_address(self.nat_addr)
1609 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1610 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1611 is_inside=0)
Juraj Slobodab33f4132017-02-08 23:54:21 -08001612
1613 # Client side - create sessions
1614 pkts = self.create_stream_in(self.pg0, self.pg1)
1615 self.pg0.add_stream(pkts)
1616 self.pg_enable_capture(self.pg_interfaces)
1617 self.pg_start()
1618
1619 # Server side - generate traffic
1620 capture = self.pg1.get_capture(len(pkts))
1621 self.verify_capture_out(capture)
1622 pkts = self.create_stream_out(self.pg1, ttl=2)
1623 self.pg1.add_stream(pkts)
1624 self.pg_enable_capture(self.pg_interfaces)
1625 self.pg_start()
1626
1627 # Client side - simulate ICMP type 11 response
1628 capture = self.pg0.get_capture(len(pkts))
1629 pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1630 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
1631 ICMP(type=11) / packet[IP] for packet in capture]
1632 self.pg0.add_stream(pkts)
1633 self.pg_enable_capture(self.pg_interfaces)
1634 self.pg_start()
1635
1636 # Server side - verify ICMP type 11 packets
1637 capture = self.pg1.get_capture(len(pkts))
1638 self.verify_capture_out_with_icmp_errors(capture)
1639
Juraj Sloboda665e4822017-02-16 17:17:19 -08001640 def test_ping_out_interface_from_outside(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001641 """ Ping NAT44 out interface from outside network """
Juraj Sloboda665e4822017-02-16 17:17:19 -08001642
Matus Fabian2ba92e32017-08-21 07:05:03 -07001643 self.nat44_add_address(self.nat_addr)
1644 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1645 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1646 is_inside=0)
Juraj Sloboda665e4822017-02-16 17:17:19 -08001647
1648 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1649 IP(src=self.pg1.remote_ip4, dst=self.pg1.local_ip4) /
1650 ICMP(id=self.icmp_id_out, type='echo-request'))
1651 pkts = [p]
1652 self.pg1.add_stream(pkts)
1653 self.pg_enable_capture(self.pg_interfaces)
1654 self.pg_start()
1655 capture = self.pg1.get_capture(len(pkts))
Juraj Sloboda665e4822017-02-16 17:17:19 -08001656 packet = capture[0]
1657 try:
1658 self.assertEqual(packet[IP].src, self.pg1.local_ip4)
1659 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
1660 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
1661 self.assertEqual(packet[ICMP].type, 0) # echo reply
1662 except:
1663 self.logger.error(ppp("Unexpected or invalid packet "
1664 "(outside network):", packet))
1665 raise
1666
Juraj Slobodad3677682017-04-14 03:24:45 +02001667 def test_ping_internal_host_from_outside(self):
1668 """ Ping internal host from outside network """
1669
Matus Fabian2ba92e32017-08-21 07:05:03 -07001670 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr)
1671 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1672 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1673 is_inside=0)
Juraj Slobodad3677682017-04-14 03:24:45 +02001674
1675 # out2in
1676 pkt = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07001677 IP(src=self.pg1.remote_ip4, dst=self.nat_addr, ttl=64) /
Juraj Slobodad3677682017-04-14 03:24:45 +02001678 ICMP(id=self.icmp_id_out, type='echo-request'))
1679 self.pg1.add_stream(pkt)
1680 self.pg_enable_capture(self.pg_interfaces)
1681 self.pg_start()
1682 capture = self.pg0.get_capture(1)
Matus Fabian05ca4a32018-09-04 23:45:13 -07001683 self.verify_capture_in(capture, self.pg0)
Juraj Slobodad3677682017-04-14 03:24:45 +02001684 self.assert_equal(capture[0][IP].proto, IP_PROTOS.icmp)
1685
1686 # in2out
1687 pkt = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1688 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4, ttl=64) /
1689 ICMP(id=self.icmp_id_in, type='echo-reply'))
1690 self.pg0.add_stream(pkt)
1691 self.pg_enable_capture(self.pg_interfaces)
1692 self.pg_start()
1693 capture = self.pg1.get_capture(1)
Matus Fabian05ca4a32018-09-04 23:45:13 -07001694 self.verify_capture_out(capture, same_port=True)
Juraj Slobodad3677682017-04-14 03:24:45 +02001695 self.assert_equal(capture[0][IP].proto, IP_PROTOS.icmp)
1696
Matus Fabianc79396e2018-07-23 00:05:22 -07001697 def test_forwarding(self):
Juraj Sloboda7b929792017-11-23 13:20:48 +01001698 """ NAT44 forwarding test """
1699
1700 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1701 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1702 is_inside=0)
1703 self.vapi.nat44_forwarding_enable_disable(1)
1704
1705 real_ip = self.pg0.remote_ip4n
1706 alias_ip = self.nat_addr_n
1707 self.vapi.nat44_add_del_static_mapping(local_ip=real_ip,
1708 external_ip=alias_ip)
1709
1710 try:
Matus Fabianc79396e2018-07-23 00:05:22 -07001711 # static mapping match
Juraj Sloboda7b929792017-11-23 13:20:48 +01001712
1713 pkts = self.create_stream_out(self.pg1)
1714 self.pg1.add_stream(pkts)
1715 self.pg_enable_capture(self.pg_interfaces)
1716 self.pg_start()
1717 capture = self.pg0.get_capture(len(pkts))
1718 self.verify_capture_in(capture, self.pg0)
1719
1720 pkts = self.create_stream_in(self.pg0, self.pg1)
1721 self.pg0.add_stream(pkts)
1722 self.pg_enable_capture(self.pg_interfaces)
1723 self.pg_start()
1724 capture = self.pg1.get_capture(len(pkts))
1725 self.verify_capture_out(capture, same_port=True)
1726
Matus Fabianc79396e2018-07-23 00:05:22 -07001727 # no static mapping match
Juraj Sloboda7b929792017-11-23 13:20:48 +01001728
1729 host0 = self.pg0.remote_hosts[0]
1730 self.pg0.remote_hosts[0] = self.pg0.remote_hosts[1]
1731 try:
1732 pkts = self.create_stream_out(self.pg1,
1733 dst_ip=self.pg0.remote_ip4,
1734 use_inside_ports=True)
1735 self.pg1.add_stream(pkts)
1736 self.pg_enable_capture(self.pg_interfaces)
1737 self.pg_start()
1738 capture = self.pg0.get_capture(len(pkts))
1739 self.verify_capture_in(capture, self.pg0)
1740
1741 pkts = self.create_stream_in(self.pg0, self.pg1)
1742 self.pg0.add_stream(pkts)
1743 self.pg_enable_capture(self.pg_interfaces)
1744 self.pg_start()
1745 capture = self.pg1.get_capture(len(pkts))
1746 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
1747 same_port=True)
1748 finally:
1749 self.pg0.remote_hosts[0] = host0
1750
1751 finally:
1752 self.vapi.nat44_forwarding_enable_disable(0)
1753 self.vapi.nat44_add_del_static_mapping(local_ip=real_ip,
1754 external_ip=alias_ip,
1755 is_add=0)
1756
Matus Fabiande886752016-12-07 03:38:19 -08001757 def test_static_in(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001758 """ 1:1 NAT initialized from inside network """
Matus Fabiande886752016-12-07 03:38:19 -08001759
1760 nat_ip = "10.0.0.10"
1761 self.tcp_port_out = 6303
1762 self.udp_port_out = 6304
1763 self.icmp_id_out = 6305
1764
Matus Fabian2ba92e32017-08-21 07:05:03 -07001765 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
1766 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1767 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1768 is_inside=0)
Matus Fabian5f224992018-01-25 21:59:16 -08001769 sm = self.vapi.nat44_static_mapping_dump()
1770 self.assertEqual(len(sm), 1)
1771 self.assertEqual((sm[0].tag).split('\0', 1)[0], '')
Matus Fabian9dba7812018-01-31 01:13:23 -08001772 self.assertEqual(sm[0].protocol, 0)
1773 self.assertEqual(sm[0].local_port, 0)
1774 self.assertEqual(sm[0].external_port, 0)
Matus Fabiande886752016-12-07 03:38:19 -08001775
1776 # in2out
1777 pkts = self.create_stream_in(self.pg0, self.pg1)
1778 self.pg0.add_stream(pkts)
1779 self.pg_enable_capture(self.pg_interfaces)
1780 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001781 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001782 self.verify_capture_out(capture, nat_ip, True)
1783
1784 # out2in
1785 pkts = self.create_stream_out(self.pg1, nat_ip)
1786 self.pg1.add_stream(pkts)
1787 self.pg_enable_capture(self.pg_interfaces)
1788 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001789 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001790 self.verify_capture_in(capture, self.pg0)
1791
1792 def test_static_out(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001793 """ 1:1 NAT initialized from outside network """
Matus Fabiande886752016-12-07 03:38:19 -08001794
1795 nat_ip = "10.0.0.20"
1796 self.tcp_port_out = 6303
1797 self.udp_port_out = 6304
1798 self.icmp_id_out = 6305
Matus Fabian5f224992018-01-25 21:59:16 -08001799 tag = "testTAG"
Matus Fabiande886752016-12-07 03:38:19 -08001800
Matus Fabian5f224992018-01-25 21:59:16 -08001801 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip, tag=tag)
Matus Fabian2ba92e32017-08-21 07:05:03 -07001802 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1803 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1804 is_inside=0)
Matus Fabian5f224992018-01-25 21:59:16 -08001805 sm = self.vapi.nat44_static_mapping_dump()
1806 self.assertEqual(len(sm), 1)
1807 self.assertEqual((sm[0].tag).split('\0', 1)[0], tag)
Matus Fabiande886752016-12-07 03:38:19 -08001808
1809 # out2in
1810 pkts = self.create_stream_out(self.pg1, nat_ip)
1811 self.pg1.add_stream(pkts)
1812 self.pg_enable_capture(self.pg_interfaces)
1813 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001814 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001815 self.verify_capture_in(capture, self.pg0)
1816
1817 # in2out
1818 pkts = self.create_stream_in(self.pg0, self.pg1)
1819 self.pg0.add_stream(pkts)
1820 self.pg_enable_capture(self.pg_interfaces)
1821 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001822 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001823 self.verify_capture_out(capture, nat_ip, True)
1824
1825 def test_static_with_port_in(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001826 """ 1:1 NAPT initialized from inside network """
Matus Fabiande886752016-12-07 03:38:19 -08001827
1828 self.tcp_port_out = 3606
1829 self.udp_port_out = 3607
1830 self.icmp_id_out = 3608
1831
Matus Fabian2ba92e32017-08-21 07:05:03 -07001832 self.nat44_add_address(self.nat_addr)
1833 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1834 self.tcp_port_in, self.tcp_port_out,
1835 proto=IP_PROTOS.tcp)
1836 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1837 self.udp_port_in, self.udp_port_out,
1838 proto=IP_PROTOS.udp)
1839 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1840 self.icmp_id_in, self.icmp_id_out,
1841 proto=IP_PROTOS.icmp)
1842 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1843 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1844 is_inside=0)
Matus Fabiande886752016-12-07 03:38:19 -08001845
1846 # in2out
1847 pkts = self.create_stream_in(self.pg0, self.pg1)
1848 self.pg0.add_stream(pkts)
1849 self.pg_enable_capture(self.pg_interfaces)
1850 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001851 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001852 self.verify_capture_out(capture)
1853
1854 # out2in
1855 pkts = self.create_stream_out(self.pg1)
1856 self.pg1.add_stream(pkts)
1857 self.pg_enable_capture(self.pg_interfaces)
1858 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001859 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001860 self.verify_capture_in(capture, self.pg0)
1861
1862 def test_static_with_port_out(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001863 """ 1:1 NAPT initialized from outside network """
Matus Fabiande886752016-12-07 03:38:19 -08001864
1865 self.tcp_port_out = 30606
1866 self.udp_port_out = 30607
1867 self.icmp_id_out = 30608
1868
Matus Fabian2ba92e32017-08-21 07:05:03 -07001869 self.nat44_add_address(self.nat_addr)
1870 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1871 self.tcp_port_in, self.tcp_port_out,
1872 proto=IP_PROTOS.tcp)
1873 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1874 self.udp_port_in, self.udp_port_out,
1875 proto=IP_PROTOS.udp)
1876 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1877 self.icmp_id_in, self.icmp_id_out,
1878 proto=IP_PROTOS.icmp)
1879 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1880 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1881 is_inside=0)
Matus Fabiande886752016-12-07 03:38:19 -08001882
1883 # out2in
1884 pkts = self.create_stream_out(self.pg1)
1885 self.pg1.add_stream(pkts)
1886 self.pg_enable_capture(self.pg_interfaces)
1887 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001888 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001889 self.verify_capture_in(capture, self.pg0)
1890
1891 # in2out
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()
Klement Sekeradab231a2016-12-21 08:50:14 +01001896 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001897 self.verify_capture_out(capture)
1898
1899 def test_static_vrf_aware(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001900 """ 1:1 NAT VRF awareness """
Matus Fabiande886752016-12-07 03:38:19 -08001901
1902 nat_ip1 = "10.0.0.30"
1903 nat_ip2 = "10.0.0.40"
1904 self.tcp_port_out = 6303
1905 self.udp_port_out = 6304
1906 self.icmp_id_out = 6305
1907
Matus Fabian2ba92e32017-08-21 07:05:03 -07001908 self.nat44_add_static_mapping(self.pg4.remote_ip4, nat_ip1,
1909 vrf_id=10)
1910 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip2,
1911 vrf_id=10)
1912 self.vapi.nat44_interface_add_del_feature(self.pg3.sw_if_index,
1913 is_inside=0)
1914 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1915 self.vapi.nat44_interface_add_del_feature(self.pg4.sw_if_index)
Matus Fabiande886752016-12-07 03:38:19 -08001916
Matus Fabian2ba92e32017-08-21 07:05:03 -07001917 # inside interface VRF match NAT44 static mapping VRF
Matus Fabiande886752016-12-07 03:38:19 -08001918 pkts = self.create_stream_in(self.pg4, self.pg3)
1919 self.pg4.add_stream(pkts)
1920 self.pg_enable_capture(self.pg_interfaces)
1921 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001922 capture = self.pg3.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001923 self.verify_capture_out(capture, nat_ip1, True)
1924
Matus Fabian2ba92e32017-08-21 07:05:03 -07001925 # inside interface VRF don't match NAT44 static mapping VRF (packets
Matus Fabiande886752016-12-07 03:38:19 -08001926 # are dropped)
1927 pkts = self.create_stream_in(self.pg0, self.pg3)
1928 self.pg0.add_stream(pkts)
1929 self.pg_enable_capture(self.pg_interfaces)
1930 self.pg_start()
Klement Sekera9225dee2016-12-12 08:36:58 +01001931 self.pg3.assert_nothing_captured()
Matus Fabiande886752016-12-07 03:38:19 -08001932
Matus Fabianb793d092018-01-31 05:50:21 -08001933 def test_dynamic_to_static(self):
1934 """ Switch from dynamic translation to 1:1NAT """
1935 nat_ip = "10.0.0.10"
1936 self.tcp_port_out = 6303
1937 self.udp_port_out = 6304
1938 self.icmp_id_out = 6305
1939
1940 self.nat44_add_address(self.nat_addr)
1941 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1942 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1943 is_inside=0)
1944
1945 # dynamic
1946 pkts = self.create_stream_in(self.pg0, self.pg1)
1947 self.pg0.add_stream(pkts)
1948 self.pg_enable_capture(self.pg_interfaces)
1949 self.pg_start()
1950 capture = self.pg1.get_capture(len(pkts))
1951 self.verify_capture_out(capture)
1952
1953 # 1:1NAT
1954 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
1955 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
1956 self.assertEqual(len(sessions), 0)
1957 pkts = self.create_stream_in(self.pg0, self.pg1)
1958 self.pg0.add_stream(pkts)
1959 self.pg_enable_capture(self.pg_interfaces)
1960 self.pg_start()
1961 capture = self.pg1.get_capture(len(pkts))
1962 self.verify_capture_out(capture, nat_ip, True)
1963
Matus Fabianab7a8052017-11-28 04:29:41 -08001964 def test_identity_nat(self):
1965 """ Identity NAT """
1966
1967 self.vapi.nat44_add_del_identity_mapping(ip=self.pg0.remote_ip4n)
1968 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1969 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1970 is_inside=0)
1971
1972 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
1973 IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
1974 TCP(sport=12345, dport=56789))
1975 self.pg1.add_stream(p)
1976 self.pg_enable_capture(self.pg_interfaces)
1977 self.pg_start()
1978 capture = self.pg0.get_capture(1)
1979 p = capture[0]
1980 try:
1981 ip = p[IP]
1982 tcp = p[TCP]
1983 self.assertEqual(ip.dst, self.pg0.remote_ip4)
1984 self.assertEqual(ip.src, self.pg1.remote_ip4)
1985 self.assertEqual(tcp.dport, 56789)
1986 self.assertEqual(tcp.sport, 12345)
Klement Sekerad81ae412018-05-16 10:52:54 +02001987 self.assert_packet_checksums_valid(p)
Matus Fabianab7a8052017-11-28 04:29:41 -08001988 except:
1989 self.logger.error(ppp("Unexpected or invalid packet:", p))
1990 raise
1991
Matus Fabiane2f4e2f2018-10-07 21:28:23 -07001992 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
1993 self.assertEqual(len(sessions), 0)
Matus Fabian82b4ceb2018-10-11 04:28:48 -07001994 self.vapi.nat44_add_del_identity_mapping(ip=self.pg0.remote_ip4n,
1995 vrf_id=1)
1996 identity_mappings = self.vapi.nat44_identity_mapping_dump()
1997 self.assertEqual(len(identity_mappings), 2)
Matus Fabiane2f4e2f2018-10-07 21:28:23 -07001998
Matus Fabiande886752016-12-07 03:38:19 -08001999 def test_multiple_inside_interfaces(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002000 """ NAT44 multiple non-overlapping address space inside interfaces """
Matus Fabiande886752016-12-07 03:38:19 -08002001
Matus Fabian2ba92e32017-08-21 07:05:03 -07002002 self.nat44_add_address(self.nat_addr)
2003 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2004 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
2005 self.vapi.nat44_interface_add_del_feature(self.pg3.sw_if_index,
2006 is_inside=0)
Matus Fabiande886752016-12-07 03:38:19 -08002007
Matus Fabian2ba92e32017-08-21 07:05:03 -07002008 # between two NAT44 inside interfaces (no translation)
Matus Fabian675a69c2017-01-18 01:46:01 -08002009 pkts = self.create_stream_in(self.pg0, self.pg1)
2010 self.pg0.add_stream(pkts)
2011 self.pg_enable_capture(self.pg_interfaces)
2012 self.pg_start()
2013 capture = self.pg1.get_capture(len(pkts))
2014 self.verify_capture_no_translation(capture, self.pg0, self.pg1)
2015
Matus Fabian2ba92e32017-08-21 07:05:03 -07002016 # from NAT44 inside to interface without NAT44 feature (no translation)
Matus Fabian675a69c2017-01-18 01:46:01 -08002017 pkts = self.create_stream_in(self.pg0, self.pg2)
2018 self.pg0.add_stream(pkts)
2019 self.pg_enable_capture(self.pg_interfaces)
2020 self.pg_start()
2021 capture = self.pg2.get_capture(len(pkts))
2022 self.verify_capture_no_translation(capture, self.pg0, self.pg2)
2023
Matus Fabiande886752016-12-07 03:38:19 -08002024 # in2out 1st interface
2025 pkts = self.create_stream_in(self.pg0, self.pg3)
2026 self.pg0.add_stream(pkts)
2027 self.pg_enable_capture(self.pg_interfaces)
2028 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002029 capture = self.pg3.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002030 self.verify_capture_out(capture)
2031
2032 # out2in 1st interface
2033 pkts = self.create_stream_out(self.pg3)
2034 self.pg3.add_stream(pkts)
2035 self.pg_enable_capture(self.pg_interfaces)
2036 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002037 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002038 self.verify_capture_in(capture, self.pg0)
2039
2040 # in2out 2nd interface
2041 pkts = self.create_stream_in(self.pg1, self.pg3)
2042 self.pg1.add_stream(pkts)
2043 self.pg_enable_capture(self.pg_interfaces)
2044 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002045 capture = self.pg3.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002046 self.verify_capture_out(capture)
2047
2048 # out2in 2nd interface
2049 pkts = self.create_stream_out(self.pg3)
2050 self.pg3.add_stream(pkts)
2051 self.pg_enable_capture(self.pg_interfaces)
2052 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002053 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002054 self.verify_capture_in(capture, self.pg1)
2055
Matus Fabiande886752016-12-07 03:38:19 -08002056 def test_inside_overlapping_interfaces(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002057 """ NAT44 multiple inside interfaces with overlapping address space """
Matus Fabiande886752016-12-07 03:38:19 -08002058
Matus Fabian675a69c2017-01-18 01:46:01 -08002059 static_nat_ip = "10.0.0.10"
Matus Fabian2ba92e32017-08-21 07:05:03 -07002060 self.nat44_add_address(self.nat_addr)
2061 self.vapi.nat44_interface_add_del_feature(self.pg3.sw_if_index,
2062 is_inside=0)
2063 self.vapi.nat44_interface_add_del_feature(self.pg4.sw_if_index)
2064 self.vapi.nat44_interface_add_del_feature(self.pg5.sw_if_index)
2065 self.vapi.nat44_interface_add_del_feature(self.pg6.sw_if_index)
2066 self.nat44_add_static_mapping(self.pg6.remote_ip4, static_nat_ip,
2067 vrf_id=20)
Matus Fabian675a69c2017-01-18 01:46:01 -08002068
Matus Fabian2ba92e32017-08-21 07:05:03 -07002069 # between NAT44 inside interfaces with same VRF (no translation)
Matus Fabian675a69c2017-01-18 01:46:01 -08002070 pkts = self.create_stream_in(self.pg4, self.pg5)
2071 self.pg4.add_stream(pkts)
2072 self.pg_enable_capture(self.pg_interfaces)
2073 self.pg_start()
2074 capture = self.pg5.get_capture(len(pkts))
2075 self.verify_capture_no_translation(capture, self.pg4, self.pg5)
2076
Matus Fabian2ba92e32017-08-21 07:05:03 -07002077 # between NAT44 inside interfaces with different VRF (hairpinning)
Matus Fabian675a69c2017-01-18 01:46:01 -08002078 p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
2079 IP(src=self.pg4.remote_ip4, dst=static_nat_ip) /
2080 TCP(sport=1234, dport=5678))
2081 self.pg4.add_stream(p)
2082 self.pg_enable_capture(self.pg_interfaces)
2083 self.pg_start()
2084 capture = self.pg6.get_capture(1)
2085 p = capture[0]
2086 try:
2087 ip = p[IP]
2088 tcp = p[TCP]
Matus Fabian2ba92e32017-08-21 07:05:03 -07002089 self.assertEqual(ip.src, self.nat_addr)
Matus Fabian675a69c2017-01-18 01:46:01 -08002090 self.assertEqual(ip.dst, self.pg6.remote_ip4)
2091 self.assertNotEqual(tcp.sport, 1234)
2092 self.assertEqual(tcp.dport, 5678)
2093 except:
2094 self.logger.error(ppp("Unexpected or invalid packet:", p))
2095 raise
Matus Fabiande886752016-12-07 03:38:19 -08002096
2097 # in2out 1st interface
2098 pkts = self.create_stream_in(self.pg4, self.pg3)
2099 self.pg4.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.pg3.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002103 self.verify_capture_out(capture)
2104
2105 # out2in 1st interface
2106 pkts = self.create_stream_out(self.pg3)
2107 self.pg3.add_stream(pkts)
2108 self.pg_enable_capture(self.pg_interfaces)
2109 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002110 capture = self.pg4.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002111 self.verify_capture_in(capture, self.pg4)
2112
2113 # in2out 2nd interface
2114 pkts = self.create_stream_in(self.pg5, self.pg3)
2115 self.pg5.add_stream(pkts)
2116 self.pg_enable_capture(self.pg_interfaces)
2117 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002118 capture = self.pg3.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002119 self.verify_capture_out(capture)
2120
2121 # out2in 2nd interface
2122 pkts = self.create_stream_out(self.pg3)
2123 self.pg3.add_stream(pkts)
2124 self.pg_enable_capture(self.pg_interfaces)
2125 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002126 capture = self.pg5.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002127 self.verify_capture_in(capture, self.pg5)
2128
magalik23caa882017-02-08 23:25:45 -08002129 # pg5 session dump
Matus Fabian2ba92e32017-08-21 07:05:03 -07002130 addresses = self.vapi.nat44_address_dump()
magalik23caa882017-02-08 23:25:45 -08002131 self.assertEqual(len(addresses), 1)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002132 sessions = self.vapi.nat44_user_session_dump(self.pg5.remote_ip4n, 10)
magalik23caa882017-02-08 23:25:45 -08002133 self.assertEqual(len(sessions), 3)
2134 for session in sessions:
2135 self.assertFalse(session.is_static)
2136 self.assertEqual(session.inside_ip_address[0:4],
2137 self.pg5.remote_ip4n)
2138 self.assertEqual(session.outside_ip_address,
2139 addresses[0].ip_address)
2140 self.assertEqual(sessions[0].protocol, IP_PROTOS.tcp)
2141 self.assertEqual(sessions[1].protocol, IP_PROTOS.udp)
2142 self.assertEqual(sessions[2].protocol, IP_PROTOS.icmp)
2143 self.assertEqual(sessions[0].inside_port, self.tcp_port_in)
2144 self.assertEqual(sessions[1].inside_port, self.udp_port_in)
2145 self.assertEqual(sessions[2].inside_port, self.icmp_id_in)
2146 self.assertEqual(sessions[0].outside_port, self.tcp_port_out)
2147 self.assertEqual(sessions[1].outside_port, self.udp_port_out)
2148 self.assertEqual(sessions[2].outside_port, self.icmp_id_out)
2149
Matus Fabiande886752016-12-07 03:38:19 -08002150 # in2out 3rd interface
2151 pkts = self.create_stream_in(self.pg6, self.pg3)
2152 self.pg6.add_stream(pkts)
2153 self.pg_enable_capture(self.pg_interfaces)
2154 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002155 capture = self.pg3.get_capture(len(pkts))
Matus Fabian675a69c2017-01-18 01:46:01 -08002156 self.verify_capture_out(capture, static_nat_ip, True)
Matus Fabiande886752016-12-07 03:38:19 -08002157
2158 # out2in 3rd interface
Matus Fabian675a69c2017-01-18 01:46:01 -08002159 pkts = self.create_stream_out(self.pg3, static_nat_ip)
Matus Fabiande886752016-12-07 03:38:19 -08002160 self.pg3.add_stream(pkts)
2161 self.pg_enable_capture(self.pg_interfaces)
2162 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002163 capture = self.pg6.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002164 self.verify_capture_in(capture, self.pg6)
2165
magalik23caa882017-02-08 23:25:45 -08002166 # general user and session dump verifications
Matus Fabian2ba92e32017-08-21 07:05:03 -07002167 users = self.vapi.nat44_user_dump()
Paul Vinciguerra3d2df212018-11-24 23:19:53 -08002168 self.assertGreaterEqual(len(users), 3)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002169 addresses = self.vapi.nat44_address_dump()
magalik23caa882017-02-08 23:25:45 -08002170 self.assertEqual(len(addresses), 1)
2171 for user in users:
Matus Fabian2ba92e32017-08-21 07:05:03 -07002172 sessions = self.vapi.nat44_user_session_dump(user.ip_address,
2173 user.vrf_id)
magalik23caa882017-02-08 23:25:45 -08002174 for session in sessions:
2175 self.assertEqual(user.ip_address, session.inside_ip_address)
2176 self.assertTrue(session.total_bytes > session.total_pkts > 0)
2177 self.assertTrue(session.protocol in
2178 [IP_PROTOS.tcp, IP_PROTOS.udp,
2179 IP_PROTOS.icmp])
Matus Fabian70a26ac2018-05-14 06:20:28 -07002180 self.assertFalse(session.ext_host_valid)
magalik23caa882017-02-08 23:25:45 -08002181
2182 # pg4 session dump
Matus Fabian2ba92e32017-08-21 07:05:03 -07002183 sessions = self.vapi.nat44_user_session_dump(self.pg4.remote_ip4n, 10)
Paul Vinciguerra3d2df212018-11-24 23:19:53 -08002184 self.assertGreaterEqual(len(sessions), 4)
magalik23caa882017-02-08 23:25:45 -08002185 for session in sessions:
2186 self.assertFalse(session.is_static)
2187 self.assertEqual(session.inside_ip_address[0:4],
2188 self.pg4.remote_ip4n)
2189 self.assertEqual(session.outside_ip_address,
2190 addresses[0].ip_address)
2191
2192 # pg6 session dump
Matus Fabian2ba92e32017-08-21 07:05:03 -07002193 sessions = self.vapi.nat44_user_session_dump(self.pg6.remote_ip4n, 20)
Paul Vinciguerra3d2df212018-11-24 23:19:53 -08002194 self.assertGreaterEqual(len(sessions), 3)
magalik23caa882017-02-08 23:25:45 -08002195 for session in sessions:
2196 self.assertTrue(session.is_static)
2197 self.assertEqual(session.inside_ip_address[0:4],
2198 self.pg6.remote_ip4n)
2199 self.assertEqual(map(ord, session.outside_ip_address[0:4]),
2200 map(int, static_nat_ip.split('.')))
2201 self.assertTrue(session.inside_port in
2202 [self.tcp_port_in, self.udp_port_in,
2203 self.icmp_id_in])
2204
Matus Fabianf78a70d2016-12-12 04:30:39 -08002205 def test_hairpinning(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002206 """ NAT44 hairpinning - 1:1 NAPT """
Matus Fabianf78a70d2016-12-12 04:30:39 -08002207
2208 host = self.pg0.remote_hosts[0]
2209 server = self.pg0.remote_hosts[1]
2210 host_in_port = 1234
2211 host_out_port = 0
2212 server_in_port = 5678
2213 server_out_port = 8765
2214
Matus Fabian2ba92e32017-08-21 07:05:03 -07002215 self.nat44_add_address(self.nat_addr)
2216 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2217 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2218 is_inside=0)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002219 # add static mapping for server
Matus Fabian2ba92e32017-08-21 07:05:03 -07002220 self.nat44_add_static_mapping(server.ip4, self.nat_addr,
2221 server_in_port, server_out_port,
2222 proto=IP_PROTOS.tcp)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002223
2224 # send packet from host to server
2225 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002226 IP(src=host.ip4, dst=self.nat_addr) /
Matus Fabianf78a70d2016-12-12 04:30:39 -08002227 TCP(sport=host_in_port, dport=server_out_port))
2228 self.pg0.add_stream(p)
2229 self.pg_enable_capture(self.pg_interfaces)
2230 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002231 capture = self.pg0.get_capture(1)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002232 p = capture[0]
2233 try:
2234 ip = p[IP]
2235 tcp = p[TCP]
Matus Fabian2ba92e32017-08-21 07:05:03 -07002236 self.assertEqual(ip.src, self.nat_addr)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002237 self.assertEqual(ip.dst, server.ip4)
2238 self.assertNotEqual(tcp.sport, host_in_port)
2239 self.assertEqual(tcp.dport, server_in_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02002240 self.assert_packet_checksums_valid(p)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002241 host_out_port = tcp.sport
2242 except:
Klement Sekera9225dee2016-12-12 08:36:58 +01002243 self.logger.error(ppp("Unexpected or invalid packet:", p))
Matus Fabianf78a70d2016-12-12 04:30:39 -08002244 raise
2245
2246 # send reply from server to host
2247 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002248 IP(src=server.ip4, dst=self.nat_addr) /
Matus Fabianf78a70d2016-12-12 04:30:39 -08002249 TCP(sport=server_in_port, dport=host_out_port))
2250 self.pg0.add_stream(p)
2251 self.pg_enable_capture(self.pg_interfaces)
2252 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002253 capture = self.pg0.get_capture(1)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002254 p = capture[0]
2255 try:
2256 ip = p[IP]
2257 tcp = p[TCP]
Matus Fabian2ba92e32017-08-21 07:05:03 -07002258 self.assertEqual(ip.src, self.nat_addr)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002259 self.assertEqual(ip.dst, host.ip4)
2260 self.assertEqual(tcp.sport, server_out_port)
2261 self.assertEqual(tcp.dport, host_in_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02002262 self.assert_packet_checksums_valid(p)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002263 except:
Matus Fabiane82488f2018-01-18 03:38:45 -08002264 self.logger.error(ppp("Unexpected or invalid packet:", p))
Matus Fabianf78a70d2016-12-12 04:30:39 -08002265 raise
2266
Matus Fabian6fa74c62017-06-05 05:55:48 -07002267 def test_hairpinning2(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002268 """ NAT44 hairpinning - 1:1 NAT"""
Matus Fabian6fa74c62017-06-05 05:55:48 -07002269
2270 server1_nat_ip = "10.0.0.10"
2271 server2_nat_ip = "10.0.0.11"
2272 host = self.pg0.remote_hosts[0]
2273 server1 = self.pg0.remote_hosts[1]
2274 server2 = self.pg0.remote_hosts[2]
2275 server_tcp_port = 22
2276 server_udp_port = 20
2277
Matus Fabian2ba92e32017-08-21 07:05:03 -07002278 self.nat44_add_address(self.nat_addr)
2279 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2280 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2281 is_inside=0)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002282
2283 # add static mapping for servers
Matus Fabian2ba92e32017-08-21 07:05:03 -07002284 self.nat44_add_static_mapping(server1.ip4, server1_nat_ip)
2285 self.nat44_add_static_mapping(server2.ip4, server2_nat_ip)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002286
2287 # host to server1
2288 pkts = []
2289 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2290 IP(src=host.ip4, dst=server1_nat_ip) /
2291 TCP(sport=self.tcp_port_in, dport=server_tcp_port))
2292 pkts.append(p)
2293 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2294 IP(src=host.ip4, dst=server1_nat_ip) /
2295 UDP(sport=self.udp_port_in, dport=server_udp_port))
2296 pkts.append(p)
2297 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2298 IP(src=host.ip4, dst=server1_nat_ip) /
2299 ICMP(id=self.icmp_id_in, type='echo-request'))
2300 pkts.append(p)
2301 self.pg0.add_stream(pkts)
2302 self.pg_enable_capture(self.pg_interfaces)
2303 self.pg_start()
2304 capture = self.pg0.get_capture(len(pkts))
2305 for packet in capture:
2306 try:
Matus Fabian2ba92e32017-08-21 07:05:03 -07002307 self.assertEqual(packet[IP].src, self.nat_addr)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002308 self.assertEqual(packet[IP].dst, server1.ip4)
2309 if packet.haslayer(TCP):
2310 self.assertNotEqual(packet[TCP].sport, self.tcp_port_in)
2311 self.assertEqual(packet[TCP].dport, server_tcp_port)
2312 self.tcp_port_out = packet[TCP].sport
Klement Sekerad81ae412018-05-16 10:52:54 +02002313 self.assert_packet_checksums_valid(packet)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002314 elif packet.haslayer(UDP):
2315 self.assertNotEqual(packet[UDP].sport, self.udp_port_in)
2316 self.assertEqual(packet[UDP].dport, server_udp_port)
2317 self.udp_port_out = packet[UDP].sport
2318 else:
2319 self.assertNotEqual(packet[ICMP].id, self.icmp_id_in)
2320 self.icmp_id_out = packet[ICMP].id
2321 except:
2322 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2323 raise
2324
2325 # server1 to host
2326 pkts = []
2327 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002328 IP(src=server1.ip4, dst=self.nat_addr) /
Matus Fabian6fa74c62017-06-05 05:55:48 -07002329 TCP(sport=server_tcp_port, dport=self.tcp_port_out))
2330 pkts.append(p)
2331 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002332 IP(src=server1.ip4, dst=self.nat_addr) /
Matus Fabian6fa74c62017-06-05 05:55:48 -07002333 UDP(sport=server_udp_port, dport=self.udp_port_out))
2334 pkts.append(p)
2335 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002336 IP(src=server1.ip4, dst=self.nat_addr) /
Matus Fabian6fa74c62017-06-05 05:55:48 -07002337 ICMP(id=self.icmp_id_out, type='echo-reply'))
2338 pkts.append(p)
2339 self.pg0.add_stream(pkts)
2340 self.pg_enable_capture(self.pg_interfaces)
2341 self.pg_start()
2342 capture = self.pg0.get_capture(len(pkts))
2343 for packet in capture:
2344 try:
2345 self.assertEqual(packet[IP].src, server1_nat_ip)
2346 self.assertEqual(packet[IP].dst, host.ip4)
2347 if packet.haslayer(TCP):
2348 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
2349 self.assertEqual(packet[TCP].sport, server_tcp_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02002350 self.assert_packet_checksums_valid(packet)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002351 elif packet.haslayer(UDP):
2352 self.assertEqual(packet[UDP].dport, self.udp_port_in)
2353 self.assertEqual(packet[UDP].sport, server_udp_port)
2354 else:
2355 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
2356 except:
2357 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2358 raise
2359
2360 # server2 to server1
2361 pkts = []
2362 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2363 IP(src=server2.ip4, dst=server1_nat_ip) /
2364 TCP(sport=self.tcp_port_in, dport=server_tcp_port))
2365 pkts.append(p)
2366 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2367 IP(src=server2.ip4, dst=server1_nat_ip) /
2368 UDP(sport=self.udp_port_in, dport=server_udp_port))
2369 pkts.append(p)
2370 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2371 IP(src=server2.ip4, dst=server1_nat_ip) /
2372 ICMP(id=self.icmp_id_in, type='echo-request'))
2373 pkts.append(p)
2374 self.pg0.add_stream(pkts)
2375 self.pg_enable_capture(self.pg_interfaces)
2376 self.pg_start()
2377 capture = self.pg0.get_capture(len(pkts))
2378 for packet in capture:
2379 try:
2380 self.assertEqual(packet[IP].src, server2_nat_ip)
2381 self.assertEqual(packet[IP].dst, server1.ip4)
2382 if packet.haslayer(TCP):
2383 self.assertEqual(packet[TCP].sport, self.tcp_port_in)
2384 self.assertEqual(packet[TCP].dport, server_tcp_port)
2385 self.tcp_port_out = packet[TCP].sport
Klement Sekerad81ae412018-05-16 10:52:54 +02002386 self.assert_packet_checksums_valid(packet)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002387 elif packet.haslayer(UDP):
2388 self.assertEqual(packet[UDP].sport, self.udp_port_in)
2389 self.assertEqual(packet[UDP].dport, server_udp_port)
2390 self.udp_port_out = packet[UDP].sport
2391 else:
2392 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
2393 self.icmp_id_out = packet[ICMP].id
2394 except:
2395 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2396 raise
2397
2398 # server1 to server2
2399 pkts = []
2400 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2401 IP(src=server1.ip4, dst=server2_nat_ip) /
2402 TCP(sport=server_tcp_port, dport=self.tcp_port_out))
2403 pkts.append(p)
2404 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2405 IP(src=server1.ip4, dst=server2_nat_ip) /
2406 UDP(sport=server_udp_port, dport=self.udp_port_out))
2407 pkts.append(p)
2408 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2409 IP(src=server1.ip4, dst=server2_nat_ip) /
2410 ICMP(id=self.icmp_id_out, type='echo-reply'))
2411 pkts.append(p)
2412 self.pg0.add_stream(pkts)
2413 self.pg_enable_capture(self.pg_interfaces)
2414 self.pg_start()
2415 capture = self.pg0.get_capture(len(pkts))
2416 for packet in capture:
2417 try:
2418 self.assertEqual(packet[IP].src, server1_nat_ip)
2419 self.assertEqual(packet[IP].dst, server2.ip4)
2420 if packet.haslayer(TCP):
2421 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
2422 self.assertEqual(packet[TCP].sport, server_tcp_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02002423 self.assert_packet_checksums_valid(packet)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002424 elif packet.haslayer(UDP):
2425 self.assertEqual(packet[UDP].dport, self.udp_port_in)
2426 self.assertEqual(packet[UDP].sport, server_udp_port)
2427 else:
2428 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
2429 except:
2430 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2431 raise
2432
Matus Fabian9902fcd2016-12-21 23:58:46 -08002433 def test_max_translations_per_user(self):
2434 """ MAX translations per user - recycle the least recently used """
2435
Matus Fabian2ba92e32017-08-21 07:05:03 -07002436 self.nat44_add_address(self.nat_addr)
2437 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2438 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2439 is_inside=0)
Matus Fabian9902fcd2016-12-21 23:58:46 -08002440
2441 # get maximum number of translations per user
Matus Fabian2ba92e32017-08-21 07:05:03 -07002442 nat44_config = self.vapi.nat_show_config()
Matus Fabian9902fcd2016-12-21 23:58:46 -08002443
2444 # send more than maximum number of translations per user packets
Matus Fabian2ba92e32017-08-21 07:05:03 -07002445 pkts_num = nat44_config.max_translations_per_user + 5
Matus Fabian9902fcd2016-12-21 23:58:46 -08002446 pkts = []
2447 for port in range(0, pkts_num):
2448 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2449 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2450 TCP(sport=1025 + port))
2451 pkts.append(p)
2452 self.pg0.add_stream(pkts)
2453 self.pg_enable_capture(self.pg_interfaces)
2454 self.pg_start()
2455
2456 # verify number of translated packet
Klement Sekeradab231a2016-12-21 08:50:14 +01002457 self.pg1.get_capture(pkts_num)
Matus Fabian9902fcd2016-12-21 23:58:46 -08002458
Matus Fabian132dc492018-05-09 04:51:03 -07002459 users = self.vapi.nat44_user_dump()
2460 for user in users:
2461 if user.ip_address == self.pg0.remote_ip4n:
2462 self.assertEqual(user.nsessions,
2463 nat44_config.max_translations_per_user)
2464 self.assertEqual(user.nstaticsessions, 0)
2465
2466 tcp_port = 22
2467 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
2468 tcp_port, tcp_port,
2469 proto=IP_PROTOS.tcp)
2470 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2471 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2472 TCP(sport=tcp_port))
2473 self.pg0.add_stream(p)
2474 self.pg_enable_capture(self.pg_interfaces)
2475 self.pg_start()
2476 self.pg1.get_capture(1)
2477 users = self.vapi.nat44_user_dump()
2478 for user in users:
2479 if user.ip_address == self.pg0.remote_ip4n:
2480 self.assertEqual(user.nsessions,
2481 nat44_config.max_translations_per_user - 1)
2482 self.assertEqual(user.nstaticsessions, 1)
2483
Matus Fabian8bf68e82017-01-12 04:24:35 -08002484 def test_interface_addr(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002485 """ Acquire NAT44 addresses from interface """
2486 self.vapi.nat44_add_interface_addr(self.pg7.sw_if_index)
Matus Fabian8bf68e82017-01-12 04:24:35 -08002487
2488 # no address in NAT pool
Matus Fabian2ba92e32017-08-21 07:05:03 -07002489 adresses = self.vapi.nat44_address_dump()
Matus Fabian8bf68e82017-01-12 04:24:35 -08002490 self.assertEqual(0, len(adresses))
2491
2492 # configure interface address and check NAT address pool
2493 self.pg7.config_ip4()
Matus Fabian2ba92e32017-08-21 07:05:03 -07002494 adresses = self.vapi.nat44_address_dump()
Matus Fabian8bf68e82017-01-12 04:24:35 -08002495 self.assertEqual(1, len(adresses))
Matus Fabian36532bd2017-01-23 23:42:28 -08002496 self.assertEqual(adresses[0].ip_address[0:4], self.pg7.local_ip4n)
Matus Fabian8bf68e82017-01-12 04:24:35 -08002497
2498 # remove interface address and check NAT address pool
2499 self.pg7.unconfig_ip4()
Matus Fabian2ba92e32017-08-21 07:05:03 -07002500 adresses = self.vapi.nat44_address_dump()
Matus Fabian8bf68e82017-01-12 04:24:35 -08002501 self.assertEqual(0, len(adresses))
2502
Matus Fabian36532bd2017-01-23 23:42:28 -08002503 def test_interface_addr_static_mapping(self):
2504 """ Static mapping with addresses from interface """
Matus Fabian5f224992018-01-25 21:59:16 -08002505 tag = "testTAG"
2506
Matus Fabian2ba92e32017-08-21 07:05:03 -07002507 self.vapi.nat44_add_interface_addr(self.pg7.sw_if_index)
2508 self.nat44_add_static_mapping(
2509 '1.2.3.4',
Matus Fabian5f224992018-01-25 21:59:16 -08002510 external_sw_if_index=self.pg7.sw_if_index,
2511 tag=tag)
Matus Fabian36532bd2017-01-23 23:42:28 -08002512
Matus Fabiane22e5462017-02-14 23:33:43 -08002513 # static mappings with external interface
Matus Fabian2ba92e32017-08-21 07:05:03 -07002514 static_mappings = self.vapi.nat44_static_mapping_dump()
Matus Fabiane22e5462017-02-14 23:33:43 -08002515 self.assertEqual(1, len(static_mappings))
2516 self.assertEqual(self.pg7.sw_if_index,
2517 static_mappings[0].external_sw_if_index)
Matus Fabian5f224992018-01-25 21:59:16 -08002518 self.assertEqual((static_mappings[0].tag).split('\0', 1)[0], tag)
Matus Fabian36532bd2017-01-23 23:42:28 -08002519
2520 # configure interface address and check static mappings
2521 self.pg7.config_ip4()
Matus Fabian2ba92e32017-08-21 07:05:03 -07002522 static_mappings = self.vapi.nat44_static_mapping_dump()
Matus Fabianea2600a2018-03-28 04:06:26 -07002523 self.assertEqual(2, len(static_mappings))
2524 resolved = False
2525 for sm in static_mappings:
2526 if sm.external_sw_if_index == 0xFFFFFFFF:
2527 self.assertEqual(sm.external_ip_address[0:4],
2528 self.pg7.local_ip4n)
2529 self.assertEqual((sm.tag).split('\0', 1)[0], tag)
2530 resolved = True
2531 self.assertTrue(resolved)
Matus Fabian36532bd2017-01-23 23:42:28 -08002532
2533 # remove interface address and check static mappings
2534 self.pg7.unconfig_ip4()
Matus Fabian2ba92e32017-08-21 07:05:03 -07002535 static_mappings = self.vapi.nat44_static_mapping_dump()
Matus Fabianea2600a2018-03-28 04:06:26 -07002536 self.assertEqual(1, len(static_mappings))
2537 self.assertEqual(self.pg7.sw_if_index,
2538 static_mappings[0].external_sw_if_index)
2539 self.assertEqual((static_mappings[0].tag).split('\0', 1)[0], tag)
2540
2541 # configure interface address again and check static mappings
2542 self.pg7.config_ip4()
2543 static_mappings = self.vapi.nat44_static_mapping_dump()
2544 self.assertEqual(2, len(static_mappings))
2545 resolved = False
2546 for sm in static_mappings:
2547 if sm.external_sw_if_index == 0xFFFFFFFF:
2548 self.assertEqual(sm.external_ip_address[0:4],
2549 self.pg7.local_ip4n)
2550 self.assertEqual((sm.tag).split('\0', 1)[0], tag)
2551 resolved = True
2552 self.assertTrue(resolved)
2553
2554 # remove static mapping
2555 self.nat44_add_static_mapping(
2556 '1.2.3.4',
2557 external_sw_if_index=self.pg7.sw_if_index,
2558 tag=tag,
2559 is_add=0)
2560 static_mappings = self.vapi.nat44_static_mapping_dump()
Matus Fabian36532bd2017-01-23 23:42:28 -08002561 self.assertEqual(0, len(static_mappings))
2562
Matus Fabianab7a8052017-11-28 04:29:41 -08002563 def test_interface_addr_identity_nat(self):
2564 """ Identity NAT with addresses from interface """
2565
2566 port = 53053
2567 self.vapi.nat44_add_interface_addr(self.pg7.sw_if_index)
2568 self.vapi.nat44_add_del_identity_mapping(
2569 sw_if_index=self.pg7.sw_if_index,
2570 port=port,
2571 protocol=IP_PROTOS.tcp,
2572 addr_only=0)
2573
2574 # identity mappings with external interface
2575 identity_mappings = self.vapi.nat44_identity_mapping_dump()
2576 self.assertEqual(1, len(identity_mappings))
2577 self.assertEqual(self.pg7.sw_if_index,
2578 identity_mappings[0].sw_if_index)
2579
2580 # configure interface address and check identity mappings
2581 self.pg7.config_ip4()
2582 identity_mappings = self.vapi.nat44_identity_mapping_dump()
Matus Fabianea2600a2018-03-28 04:06:26 -07002583 resolved = False
2584 self.assertEqual(2, len(identity_mappings))
2585 for sm in identity_mappings:
2586 if sm.sw_if_index == 0xFFFFFFFF:
2587 self.assertEqual(identity_mappings[0].ip_address,
2588 self.pg7.local_ip4n)
2589 self.assertEqual(port, identity_mappings[0].port)
2590 self.assertEqual(IP_PROTOS.tcp, identity_mappings[0].protocol)
2591 resolved = True
2592 self.assertTrue(resolved)
Matus Fabianab7a8052017-11-28 04:29:41 -08002593
2594 # remove interface address and check identity mappings
2595 self.pg7.unconfig_ip4()
2596 identity_mappings = self.vapi.nat44_identity_mapping_dump()
Matus Fabianea2600a2018-03-28 04:06:26 -07002597 self.assertEqual(1, len(identity_mappings))
2598 self.assertEqual(self.pg7.sw_if_index,
2599 identity_mappings[0].sw_if_index)
Matus Fabianab7a8052017-11-28 04:29:41 -08002600
Matus Fabianeea28d72017-01-13 04:15:54 -08002601 def test_ipfix_nat44_sess(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002602 """ IPFIX logging NAT44 session created/delted """
Matus Fabian6631e9c2017-05-24 01:52:20 -07002603 self.ipfix_domain_id = 10
2604 self.ipfix_src_port = 20202
2605 colector_port = 30303
2606 bind_layers(UDP, IPFIX, dport=30303)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002607 self.nat44_add_address(self.nat_addr)
2608 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2609 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2610 is_inside=0)
Matus Fabianeea28d72017-01-13 04:15:54 -08002611 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
2612 src_address=self.pg3.local_ip4n,
2613 path_mtu=512,
Matus Fabian6631e9c2017-05-24 01:52:20 -07002614 template_interval=10,
2615 collector_port=colector_port)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002616 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
2617 src_port=self.ipfix_src_port)
Matus Fabianeea28d72017-01-13 04:15:54 -08002618
2619 pkts = self.create_stream_in(self.pg0, self.pg1)
2620 self.pg0.add_stream(pkts)
2621 self.pg_enable_capture(self.pg_interfaces)
2622 self.pg_start()
2623 capture = self.pg1.get_capture(len(pkts))
2624 self.verify_capture_out(capture)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002625 self.nat44_add_address(self.nat_addr, is_add=0)
Matus Fabianeea28d72017-01-13 04:15:54 -08002626 self.vapi.cli("ipfix flush") # FIXME this should be an API call
Matus Fabiana431ad12018-01-04 04:03:14 -08002627 capture = self.pg3.get_capture(9)
Matus Fabianeea28d72017-01-13 04:15:54 -08002628 ipfix = IPFIXDecoder()
2629 # first load template
2630 for p in capture:
2631 self.assertTrue(p.haslayer(IPFIX))
Matus Fabian6631e9c2017-05-24 01:52:20 -07002632 self.assertEqual(p[IP].src, self.pg3.local_ip4)
2633 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2634 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2635 self.assertEqual(p[UDP].dport, colector_port)
2636 self.assertEqual(p[IPFIX].observationDomainID,
2637 self.ipfix_domain_id)
Matus Fabianeea28d72017-01-13 04:15:54 -08002638 if p.haslayer(Template):
2639 ipfix.add_template(p.getlayer(Template))
2640 # verify events in data set
2641 for p in capture:
2642 if p.haslayer(Data):
2643 data = ipfix.decode_data_set(p.getlayer(Set))
2644 self.verify_ipfix_nat44_ses(data)
2645
2646 def test_ipfix_addr_exhausted(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002647 """ IPFIX logging NAT addresses exhausted """
2648 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2649 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2650 is_inside=0)
Matus Fabianeea28d72017-01-13 04:15:54 -08002651 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
2652 src_address=self.pg3.local_ip4n,
2653 path_mtu=512,
2654 template_interval=10)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002655 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
2656 src_port=self.ipfix_src_port)
Matus Fabianeea28d72017-01-13 04:15:54 -08002657
2658 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
2659 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2660 TCP(sport=3025))
2661 self.pg0.add_stream(p)
2662 self.pg_enable_capture(self.pg_interfaces)
2663 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07002664 self.pg1.assert_nothing_captured()
2665 sleep(1)
Matus Fabianeea28d72017-01-13 04:15:54 -08002666 self.vapi.cli("ipfix flush") # FIXME this should be an API call
Matus Fabiana431ad12018-01-04 04:03:14 -08002667 capture = self.pg3.get_capture(9)
Matus Fabianeea28d72017-01-13 04:15:54 -08002668 ipfix = IPFIXDecoder()
2669 # first load template
2670 for p in capture:
2671 self.assertTrue(p.haslayer(IPFIX))
Matus Fabian6631e9c2017-05-24 01:52:20 -07002672 self.assertEqual(p[IP].src, self.pg3.local_ip4)
2673 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2674 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2675 self.assertEqual(p[UDP].dport, 4739)
2676 self.assertEqual(p[IPFIX].observationDomainID,
2677 self.ipfix_domain_id)
Matus Fabianeea28d72017-01-13 04:15:54 -08002678 if p.haslayer(Template):
2679 ipfix.add_template(p.getlayer(Template))
2680 # verify events in data set
2681 for p in capture:
2682 if p.haslayer(Data):
2683 data = ipfix.decode_data_set(p.getlayer(Set))
2684 self.verify_ipfix_addr_exhausted(data)
2685
Matus Fabiana431ad12018-01-04 04:03:14 -08002686 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
2687 def test_ipfix_max_sessions(self):
2688 """ IPFIX logging maximum session entries exceeded """
2689 self.nat44_add_address(self.nat_addr)
2690 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2691 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2692 is_inside=0)
2693
2694 nat44_config = self.vapi.nat_show_config()
2695 max_sessions = 10 * nat44_config.translation_buckets
2696
2697 pkts = []
2698 for i in range(0, max_sessions):
2699 src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
2700 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2701 IP(src=src, dst=self.pg1.remote_ip4) /
2702 TCP(sport=1025))
2703 pkts.append(p)
2704 self.pg0.add_stream(pkts)
2705 self.pg_enable_capture(self.pg_interfaces)
2706 self.pg_start()
2707
2708 self.pg1.get_capture(max_sessions)
2709 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
2710 src_address=self.pg3.local_ip4n,
2711 path_mtu=512,
2712 template_interval=10)
2713 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
2714 src_port=self.ipfix_src_port)
2715
2716 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2717 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2718 TCP(sport=1025))
2719 self.pg0.add_stream(p)
2720 self.pg_enable_capture(self.pg_interfaces)
2721 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07002722 self.pg1.assert_nothing_captured()
2723 sleep(1)
Matus Fabiana431ad12018-01-04 04:03:14 -08002724 self.vapi.cli("ipfix flush") # FIXME this should be an API call
2725 capture = self.pg3.get_capture(9)
2726 ipfix = IPFIXDecoder()
2727 # first load template
2728 for p in capture:
2729 self.assertTrue(p.haslayer(IPFIX))
2730 self.assertEqual(p[IP].src, self.pg3.local_ip4)
2731 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2732 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2733 self.assertEqual(p[UDP].dport, 4739)
2734 self.assertEqual(p[IPFIX].observationDomainID,
2735 self.ipfix_domain_id)
2736 if p.haslayer(Template):
2737 ipfix.add_template(p.getlayer(Template))
2738 # verify events in data set
2739 for p in capture:
2740 if p.haslayer(Data):
2741 data = ipfix.decode_data_set(p.getlayer(Set))
2742 self.verify_ipfix_max_sessions(data, max_sessions)
2743
Matus Fabianad1f3e12018-11-28 21:26:34 -08002744 def test_syslog_apmap(self):
2745 """ Test syslog address and port mapping creation and deletion """
2746 self.vapi.syslog_set_filter(SYSLOG_SEVERITY.INFO)
2747 self.vapi.syslog_set_sender(self.pg3.remote_ip4n, self.pg3.local_ip4n)
2748 self.nat44_add_address(self.nat_addr)
2749 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2750 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2751 is_inside=0)
2752
2753 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2754 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2755 TCP(sport=self.tcp_port_in, dport=20))
2756 self.pg0.add_stream(p)
2757 self.pg_enable_capture(self.pg_interfaces)
2758 self.pg_start()
2759 capture = self.pg1.get_capture(1)
2760 self.tcp_port_out = capture[0][TCP].sport
2761 capture = self.pg3.get_capture(1)
2762 self.verify_syslog_apmap(capture[0][Raw].load)
2763
2764 self.pg_enable_capture(self.pg_interfaces)
2765 self.pg_start()
2766 self.nat44_add_address(self.nat_addr, is_add=0)
2767 capture = self.pg3.get_capture(1)
2768 self.verify_syslog_apmap(capture[0][Raw].load, False)
2769
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002770 def test_pool_addr_fib(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002771 """ NAT44 add pool addresses to FIB """
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002772 static_addr = '10.0.0.10'
Matus Fabian2ba92e32017-08-21 07:05:03 -07002773 self.nat44_add_address(self.nat_addr)
2774 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2775 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2776 is_inside=0)
2777 self.nat44_add_static_mapping(self.pg0.remote_ip4, static_addr)
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002778
Matus Fabian2ba92e32017-08-21 07:05:03 -07002779 # NAT44 address
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002780 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002781 ARP(op=ARP.who_has, pdst=self.nat_addr,
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002782 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2783 self.pg1.add_stream(p)
2784 self.pg_enable_capture(self.pg_interfaces)
2785 self.pg_start()
2786 capture = self.pg1.get_capture(1)
2787 self.assertTrue(capture[0].haslayer(ARP))
2788 self.assertTrue(capture[0][ARP].op, ARP.is_at)
2789
2790 # 1:1 NAT address
2791 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2792 ARP(op=ARP.who_has, pdst=static_addr,
2793 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2794 self.pg1.add_stream(p)
2795 self.pg_enable_capture(self.pg_interfaces)
2796 self.pg_start()
2797 capture = self.pg1.get_capture(1)
2798 self.assertTrue(capture[0].haslayer(ARP))
2799 self.assertTrue(capture[0][ARP].op, ARP.is_at)
2800
Matus Fabian2ba92e32017-08-21 07:05:03 -07002801 # send ARP to non-NAT44 interface
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002802 p = (Ether(src=self.pg2.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002803 ARP(op=ARP.who_has, pdst=self.nat_addr,
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002804 psrc=self.pg2.remote_ip4, hwsrc=self.pg2.remote_mac))
2805 self.pg2.add_stream(p)
2806 self.pg_enable_capture(self.pg_interfaces)
2807 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07002808 self.pg1.assert_nothing_captured()
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002809
2810 # remove addresses and verify
Matus Fabian2ba92e32017-08-21 07:05:03 -07002811 self.nat44_add_address(self.nat_addr, is_add=0)
2812 self.nat44_add_static_mapping(self.pg0.remote_ip4, static_addr,
2813 is_add=0)
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002814
2815 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002816 ARP(op=ARP.who_has, pdst=self.nat_addr,
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002817 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2818 self.pg1.add_stream(p)
2819 self.pg_enable_capture(self.pg_interfaces)
2820 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07002821 self.pg1.assert_nothing_captured()
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002822
2823 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2824 ARP(op=ARP.who_has, pdst=static_addr,
2825 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2826 self.pg1.add_stream(p)
2827 self.pg_enable_capture(self.pg_interfaces)
2828 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07002829 self.pg1.assert_nothing_captured()
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002830
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002831 def test_vrf_mode(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002832 """ NAT44 tenant VRF aware address pool mode """
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002833
2834 vrf_id1 = 1
2835 vrf_id2 = 2
2836 nat_ip1 = "10.0.0.10"
2837 nat_ip2 = "10.0.0.11"
2838
2839 self.pg0.unconfig_ip4()
2840 self.pg1.unconfig_ip4()
Neale Ranns15002542017-09-10 04:39:11 -07002841 self.vapi.ip_table_add_del(vrf_id1, is_add=1)
2842 self.vapi.ip_table_add_del(vrf_id2, is_add=1)
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002843 self.pg0.set_table_ip4(vrf_id1)
2844 self.pg1.set_table_ip4(vrf_id2)
2845 self.pg0.config_ip4()
2846 self.pg1.config_ip4()
Matus Fabian8008d7c2018-07-09 01:34:20 -07002847 self.pg0.resolve_arp()
2848 self.pg1.resolve_arp()
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002849
Matus Fabian2ba92e32017-08-21 07:05:03 -07002850 self.nat44_add_address(nat_ip1, vrf_id=vrf_id1)
2851 self.nat44_add_address(nat_ip2, vrf_id=vrf_id2)
2852 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2853 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
2854 self.vapi.nat44_interface_add_del_feature(self.pg2.sw_if_index,
2855 is_inside=0)
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002856
Matus Fabian8008d7c2018-07-09 01:34:20 -07002857 try:
2858 # first VRF
2859 pkts = self.create_stream_in(self.pg0, self.pg2)
2860 self.pg0.add_stream(pkts)
2861 self.pg_enable_capture(self.pg_interfaces)
2862 self.pg_start()
2863 capture = self.pg2.get_capture(len(pkts))
2864 self.verify_capture_out(capture, nat_ip1)
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002865
Matus Fabian8008d7c2018-07-09 01:34:20 -07002866 # second VRF
2867 pkts = self.create_stream_in(self.pg1, self.pg2)
2868 self.pg1.add_stream(pkts)
2869 self.pg_enable_capture(self.pg_interfaces)
2870 self.pg_start()
2871 capture = self.pg2.get_capture(len(pkts))
2872 self.verify_capture_out(capture, nat_ip2)
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002873
Matus Fabian8008d7c2018-07-09 01:34:20 -07002874 finally:
2875 self.pg0.unconfig_ip4()
2876 self.pg1.unconfig_ip4()
2877 self.pg0.set_table_ip4(0)
2878 self.pg1.set_table_ip4(0)
2879 self.pg0.config_ip4()
2880 self.pg1.config_ip4()
2881 self.pg0.resolve_arp()
2882 self.pg1.resolve_arp()
2883 self.vapi.ip_table_add_del(vrf_id1, is_add=0)
2884 self.vapi.ip_table_add_del(vrf_id2, is_add=0)
Neale Ranns15002542017-09-10 04:39:11 -07002885
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002886 def test_vrf_feature_independent(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002887 """ NAT44 tenant VRF independent address pool mode """
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002888
2889 nat_ip1 = "10.0.0.10"
2890 nat_ip2 = "10.0.0.11"
2891
Matus Fabian2ba92e32017-08-21 07:05:03 -07002892 self.nat44_add_address(nat_ip1)
Matus Fabian51e759f2017-12-07 23:22:51 -08002893 self.nat44_add_address(nat_ip2, vrf_id=99)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002894 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2895 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
2896 self.vapi.nat44_interface_add_del_feature(self.pg2.sw_if_index,
2897 is_inside=0)
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002898
2899 # first VRF
2900 pkts = self.create_stream_in(self.pg0, self.pg2)
2901 self.pg0.add_stream(pkts)
2902 self.pg_enable_capture(self.pg_interfaces)
2903 self.pg_start()
2904 capture = self.pg2.get_capture(len(pkts))
2905 self.verify_capture_out(capture, nat_ip1)
2906
2907 # second VRF
2908 pkts = self.create_stream_in(self.pg1, self.pg2)
2909 self.pg1.add_stream(pkts)
2910 self.pg_enable_capture(self.pg_interfaces)
2911 self.pg_start()
2912 capture = self.pg2.get_capture(len(pkts))
2913 self.verify_capture_out(capture, nat_ip1)
2914
Martin Gálik406eb1d2017-05-04 04:35:04 -07002915 def test_dynamic_ipless_interfaces(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002916 """ NAT44 interfaces without configured IP address """
Martin Gálik406eb1d2017-05-04 04:35:04 -07002917
2918 self.vapi.ip_neighbor_add_del(self.pg7.sw_if_index,
Ole Troan895b6e82017-10-20 13:28:20 +02002919 mactobinary(self.pg7.remote_mac),
Martin Gálik406eb1d2017-05-04 04:35:04 -07002920 self.pg7.remote_ip4n,
2921 is_static=1)
2922 self.vapi.ip_neighbor_add_del(self.pg8.sw_if_index,
Ole Troan895b6e82017-10-20 13:28:20 +02002923 mactobinary(self.pg8.remote_mac),
Martin Gálik406eb1d2017-05-04 04:35:04 -07002924 self.pg8.remote_ip4n,
2925 is_static=1)
2926
2927 self.vapi.ip_add_del_route(dst_address=self.pg7.remote_ip4n,
2928 dst_address_length=32,
2929 next_hop_address=self.pg7.remote_ip4n,
2930 next_hop_sw_if_index=self.pg7.sw_if_index)
2931 self.vapi.ip_add_del_route(dst_address=self.pg8.remote_ip4n,
2932 dst_address_length=32,
2933 next_hop_address=self.pg8.remote_ip4n,
2934 next_hop_sw_if_index=self.pg8.sw_if_index)
2935
Matus Fabian2ba92e32017-08-21 07:05:03 -07002936 self.nat44_add_address(self.nat_addr)
2937 self.vapi.nat44_interface_add_del_feature(self.pg7.sw_if_index)
2938 self.vapi.nat44_interface_add_del_feature(self.pg8.sw_if_index,
2939 is_inside=0)
Martin Gálik406eb1d2017-05-04 04:35:04 -07002940
2941 # in2out
2942 pkts = self.create_stream_in(self.pg7, self.pg8)
2943 self.pg7.add_stream(pkts)
2944 self.pg_enable_capture(self.pg_interfaces)
2945 self.pg_start()
2946 capture = self.pg8.get_capture(len(pkts))
2947 self.verify_capture_out(capture)
2948
2949 # out2in
Matus Fabian2ba92e32017-08-21 07:05:03 -07002950 pkts = self.create_stream_out(self.pg8, self.nat_addr)
Martin Gálik406eb1d2017-05-04 04:35:04 -07002951 self.pg8.add_stream(pkts)
2952 self.pg_enable_capture(self.pg_interfaces)
2953 self.pg_start()
2954 capture = self.pg7.get_capture(len(pkts))
2955 self.verify_capture_in(capture, self.pg7)
2956
2957 def test_static_ipless_interfaces(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002958 """ NAT44 interfaces without configured IP address - 1:1 NAT """
Martin Gálik406eb1d2017-05-04 04:35:04 -07002959
2960 self.vapi.ip_neighbor_add_del(self.pg7.sw_if_index,
Ole Troan895b6e82017-10-20 13:28:20 +02002961 mactobinary(self.pg7.remote_mac),
Martin Gálik406eb1d2017-05-04 04:35:04 -07002962 self.pg7.remote_ip4n,
2963 is_static=1)
2964 self.vapi.ip_neighbor_add_del(self.pg8.sw_if_index,
Ole Troan895b6e82017-10-20 13:28:20 +02002965 mactobinary(self.pg8.remote_mac),
Martin Gálik406eb1d2017-05-04 04:35:04 -07002966 self.pg8.remote_ip4n,
2967 is_static=1)
2968
2969 self.vapi.ip_add_del_route(dst_address=self.pg7.remote_ip4n,
2970 dst_address_length=32,
2971 next_hop_address=self.pg7.remote_ip4n,
2972 next_hop_sw_if_index=self.pg7.sw_if_index)
2973 self.vapi.ip_add_del_route(dst_address=self.pg8.remote_ip4n,
2974 dst_address_length=32,
2975 next_hop_address=self.pg8.remote_ip4n,
2976 next_hop_sw_if_index=self.pg8.sw_if_index)
2977
Matus Fabian2ba92e32017-08-21 07:05:03 -07002978 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr)
2979 self.vapi.nat44_interface_add_del_feature(self.pg7.sw_if_index)
2980 self.vapi.nat44_interface_add_del_feature(self.pg8.sw_if_index,
2981 is_inside=0)
Martin Gálik406eb1d2017-05-04 04:35:04 -07002982
2983 # out2in
2984 pkts = self.create_stream_out(self.pg8)
2985 self.pg8.add_stream(pkts)
2986 self.pg_enable_capture(self.pg_interfaces)
2987 self.pg_start()
2988 capture = self.pg7.get_capture(len(pkts))
2989 self.verify_capture_in(capture, self.pg7)
2990
2991 # in2out
2992 pkts = self.create_stream_in(self.pg7, self.pg8)
2993 self.pg7.add_stream(pkts)
2994 self.pg_enable_capture(self.pg_interfaces)
2995 self.pg_start()
2996 capture = self.pg8.get_capture(len(pkts))
Matus Fabian2ba92e32017-08-21 07:05:03 -07002997 self.verify_capture_out(capture, self.nat_addr, True)
Martin Gálik406eb1d2017-05-04 04:35:04 -07002998
2999 def test_static_with_port_ipless_interfaces(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07003000 """ NAT44 interfaces without configured IP address - 1:1 NAPT """
Martin Gálik406eb1d2017-05-04 04:35:04 -07003001
3002 self.tcp_port_out = 30606
3003 self.udp_port_out = 30607
3004 self.icmp_id_out = 30608
3005
3006 self.vapi.ip_neighbor_add_del(self.pg7.sw_if_index,
Ole Troan895b6e82017-10-20 13:28:20 +02003007 mactobinary(self.pg7.remote_mac),
Martin Gálik406eb1d2017-05-04 04:35:04 -07003008 self.pg7.remote_ip4n,
3009 is_static=1)
3010 self.vapi.ip_neighbor_add_del(self.pg8.sw_if_index,
Ole Troan895b6e82017-10-20 13:28:20 +02003011 mactobinary(self.pg8.remote_mac),
Martin Gálik406eb1d2017-05-04 04:35:04 -07003012 self.pg8.remote_ip4n,
3013 is_static=1)
3014
3015 self.vapi.ip_add_del_route(dst_address=self.pg7.remote_ip4n,
3016 dst_address_length=32,
3017 next_hop_address=self.pg7.remote_ip4n,
3018 next_hop_sw_if_index=self.pg7.sw_if_index)
3019 self.vapi.ip_add_del_route(dst_address=self.pg8.remote_ip4n,
3020 dst_address_length=32,
3021 next_hop_address=self.pg8.remote_ip4n,
3022 next_hop_sw_if_index=self.pg8.sw_if_index)
3023
Matus Fabian2ba92e32017-08-21 07:05:03 -07003024 self.nat44_add_address(self.nat_addr)
3025 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
3026 self.tcp_port_in, self.tcp_port_out,
3027 proto=IP_PROTOS.tcp)
3028 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
3029 self.udp_port_in, self.udp_port_out,
3030 proto=IP_PROTOS.udp)
3031 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
3032 self.icmp_id_in, self.icmp_id_out,
3033 proto=IP_PROTOS.icmp)
3034 self.vapi.nat44_interface_add_del_feature(self.pg7.sw_if_index)
3035 self.vapi.nat44_interface_add_del_feature(self.pg8.sw_if_index,
3036 is_inside=0)
Martin Gálik406eb1d2017-05-04 04:35:04 -07003037
3038 # out2in
3039 pkts = self.create_stream_out(self.pg8)
3040 self.pg8.add_stream(pkts)
3041 self.pg_enable_capture(self.pg_interfaces)
3042 self.pg_start()
3043 capture = self.pg7.get_capture(len(pkts))
3044 self.verify_capture_in(capture, self.pg7)
3045
3046 # in2out
3047 pkts = self.create_stream_in(self.pg7, self.pg8)
3048 self.pg7.add_stream(pkts)
3049 self.pg_enable_capture(self.pg_interfaces)
3050 self.pg_start()
3051 capture = self.pg8.get_capture(len(pkts))
3052 self.verify_capture_out(capture)
3053
Matus Fabian328dbc82017-06-19 04:28:04 -07003054 def test_static_unknown_proto(self):
3055 """ 1:1 NAT translate packet with unknown protocol """
3056 nat_ip = "10.0.0.10"
Matus Fabian2ba92e32017-08-21 07:05:03 -07003057 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
3058 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3059 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3060 is_inside=0)
Matus Fabian328dbc82017-06-19 04:28:04 -07003061
3062 # in2out
3063 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3064 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3065 GRE() /
Matus Fabian1e8db5f2017-06-20 01:45:49 -07003066 IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4) /
Matus Fabian328dbc82017-06-19 04:28:04 -07003067 TCP(sport=1234, dport=1234))
3068 self.pg0.add_stream(p)
3069 self.pg_enable_capture(self.pg_interfaces)
3070 self.pg_start()
3071 p = self.pg1.get_capture(1)
3072 packet = p[0]
3073 try:
3074 self.assertEqual(packet[IP].src, nat_ip)
3075 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
3076 self.assertTrue(packet.haslayer(GRE))
Klement Sekerad81ae412018-05-16 10:52:54 +02003077 self.assert_packet_checksums_valid(packet)
Matus Fabian328dbc82017-06-19 04:28:04 -07003078 except:
3079 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3080 raise
3081
3082 # out2in
3083 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
3084 IP(src=self.pg1.remote_ip4, dst=nat_ip) /
3085 GRE() /
Matus Fabian1e8db5f2017-06-20 01:45:49 -07003086 IP(src=self.pg3.remote_ip4, dst=self.pg2.remote_ip4) /
Matus Fabian328dbc82017-06-19 04:28:04 -07003087 TCP(sport=1234, dport=1234))
3088 self.pg1.add_stream(p)
3089 self.pg_enable_capture(self.pg_interfaces)
3090 self.pg_start()
3091 p = self.pg0.get_capture(1)
3092 packet = p[0]
3093 try:
3094 self.assertEqual(packet[IP].src, self.pg1.remote_ip4)
3095 self.assertEqual(packet[IP].dst, self.pg0.remote_ip4)
3096 self.assertTrue(packet.haslayer(GRE))
Klement Sekerad81ae412018-05-16 10:52:54 +02003097 self.assert_packet_checksums_valid(packet)
Matus Fabian328dbc82017-06-19 04:28:04 -07003098 except:
3099 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3100 raise
3101
Matus Fabian7968e6c2017-07-06 05:37:49 -07003102 def test_hairpinning_static_unknown_proto(self):
Matus Fabian1e8db5f2017-06-20 01:45:49 -07003103 """ 1:1 NAT translate packet with unknown protocol - hairpinning """
3104
3105 host = self.pg0.remote_hosts[0]
3106 server = self.pg0.remote_hosts[1]
3107
3108 host_nat_ip = "10.0.0.10"
3109 server_nat_ip = "10.0.0.11"
3110
Matus Fabian2ba92e32017-08-21 07:05:03 -07003111 self.nat44_add_static_mapping(host.ip4, host_nat_ip)
3112 self.nat44_add_static_mapping(server.ip4, server_nat_ip)
3113 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3114 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3115 is_inside=0)
Matus Fabian1e8db5f2017-06-20 01:45:49 -07003116
3117 # host to server
3118 p = (Ether(dst=self.pg0.local_mac, src=host.mac) /
3119 IP(src=host.ip4, dst=server_nat_ip) /
3120 GRE() /
3121 IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4) /
3122 TCP(sport=1234, dport=1234))
3123 self.pg0.add_stream(p)
3124 self.pg_enable_capture(self.pg_interfaces)
3125 self.pg_start()
3126 p = self.pg0.get_capture(1)
3127 packet = p[0]
3128 try:
3129 self.assertEqual(packet[IP].src, host_nat_ip)
3130 self.assertEqual(packet[IP].dst, server.ip4)
3131 self.assertTrue(packet.haslayer(GRE))
Klement Sekerad81ae412018-05-16 10:52:54 +02003132 self.assert_packet_checksums_valid(packet)
Matus Fabian1e8db5f2017-06-20 01:45:49 -07003133 except:
3134 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3135 raise
3136
3137 # server to host
3138 p = (Ether(dst=self.pg0.local_mac, src=server.mac) /
3139 IP(src=server.ip4, dst=host_nat_ip) /
3140 GRE() /
3141 IP(src=self.pg3.remote_ip4, dst=self.pg2.remote_ip4) /
3142 TCP(sport=1234, dport=1234))
3143 self.pg0.add_stream(p)
3144 self.pg_enable_capture(self.pg_interfaces)
3145 self.pg_start()
3146 p = self.pg0.get_capture(1)
3147 packet = p[0]
3148 try:
3149 self.assertEqual(packet[IP].src, server_nat_ip)
3150 self.assertEqual(packet[IP].dst, host.ip4)
3151 self.assertTrue(packet.haslayer(GRE))
Klement Sekerad81ae412018-05-16 10:52:54 +02003152 self.assert_packet_checksums_valid(packet)
Matus Fabian1e8db5f2017-06-20 01:45:49 -07003153 except:
3154 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3155 raise
3156
Matus Fabian93d84c92017-07-19 08:06:01 -07003157 def test_output_feature(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07003158 """ NAT44 interface output feature (in2out postrouting) """
3159 self.nat44_add_address(self.nat_addr)
3160 self.vapi.nat44_interface_add_del_output_feature(self.pg0.sw_if_index)
Matus Fabianb2d2fc72017-09-10 22:17:47 -07003161 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index)
3162 self.vapi.nat44_interface_add_del_output_feature(self.pg3.sw_if_index,
Matus Fabian2ba92e32017-08-21 07:05:03 -07003163 is_inside=0)
Matus Fabian93d84c92017-07-19 08:06:01 -07003164
3165 # in2out
Matus Fabianb2d2fc72017-09-10 22:17:47 -07003166 pkts = self.create_stream_in(self.pg0, self.pg3)
Matus Fabian93d84c92017-07-19 08:06:01 -07003167 self.pg0.add_stream(pkts)
3168 self.pg_enable_capture(self.pg_interfaces)
3169 self.pg_start()
Matus Fabianb2d2fc72017-09-10 22:17:47 -07003170 capture = self.pg3.get_capture(len(pkts))
Matus Fabian93d84c92017-07-19 08:06:01 -07003171 self.verify_capture_out(capture)
3172
3173 # out2in
Matus Fabianb2d2fc72017-09-10 22:17:47 -07003174 pkts = self.create_stream_out(self.pg3)
3175 self.pg3.add_stream(pkts)
Matus Fabian93d84c92017-07-19 08:06:01 -07003176 self.pg_enable_capture(self.pg_interfaces)
3177 self.pg_start()
3178 capture = self.pg0.get_capture(len(pkts))
3179 self.verify_capture_in(capture, self.pg0)
3180
Matus Fabianb2d2fc72017-09-10 22:17:47 -07003181 # from non-NAT interface to NAT inside interface
3182 pkts = self.create_stream_in(self.pg2, self.pg0)
3183 self.pg2.add_stream(pkts)
3184 self.pg_enable_capture(self.pg_interfaces)
3185 self.pg_start()
3186 capture = self.pg0.get_capture(len(pkts))
3187 self.verify_capture_no_translation(capture, self.pg2, self.pg0)
3188
Matus Fabian93d84c92017-07-19 08:06:01 -07003189 def test_output_feature_vrf_aware(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07003190 """ NAT44 interface output feature VRF aware (in2out postrouting) """
Matus Fabian93d84c92017-07-19 08:06:01 -07003191 nat_ip_vrf10 = "10.0.0.10"
3192 nat_ip_vrf20 = "10.0.0.20"
3193
3194 self.vapi.ip_add_del_route(dst_address=self.pg3.remote_ip4n,
3195 dst_address_length=32,
3196 next_hop_address=self.pg3.remote_ip4n,
3197 next_hop_sw_if_index=self.pg3.sw_if_index,
3198 table_id=10)
3199 self.vapi.ip_add_del_route(dst_address=self.pg3.remote_ip4n,
3200 dst_address_length=32,
3201 next_hop_address=self.pg3.remote_ip4n,
3202 next_hop_sw_if_index=self.pg3.sw_if_index,
3203 table_id=20)
3204
Matus Fabian2ba92e32017-08-21 07:05:03 -07003205 self.nat44_add_address(nat_ip_vrf10, vrf_id=10)
3206 self.nat44_add_address(nat_ip_vrf20, vrf_id=20)
3207 self.vapi.nat44_interface_add_del_output_feature(self.pg4.sw_if_index)
3208 self.vapi.nat44_interface_add_del_output_feature(self.pg6.sw_if_index)
3209 self.vapi.nat44_interface_add_del_output_feature(self.pg3.sw_if_index,
3210 is_inside=0)
Matus Fabian93d84c92017-07-19 08:06:01 -07003211
3212 # in2out VRF 10
3213 pkts = self.create_stream_in(self.pg4, self.pg3)
3214 self.pg4.add_stream(pkts)
3215 self.pg_enable_capture(self.pg_interfaces)
3216 self.pg_start()
3217 capture = self.pg3.get_capture(len(pkts))
3218 self.verify_capture_out(capture, nat_ip=nat_ip_vrf10)
3219
3220 # out2in VRF 10
3221 pkts = self.create_stream_out(self.pg3, dst_ip=nat_ip_vrf10)
3222 self.pg3.add_stream(pkts)
3223 self.pg_enable_capture(self.pg_interfaces)
3224 self.pg_start()
3225 capture = self.pg4.get_capture(len(pkts))
3226 self.verify_capture_in(capture, self.pg4)
3227
3228 # in2out VRF 20
3229 pkts = self.create_stream_in(self.pg6, self.pg3)
3230 self.pg6.add_stream(pkts)
3231 self.pg_enable_capture(self.pg_interfaces)
3232 self.pg_start()
3233 capture = self.pg3.get_capture(len(pkts))
3234 self.verify_capture_out(capture, nat_ip=nat_ip_vrf20)
3235
3236 # out2in VRF 20
3237 pkts = self.create_stream_out(self.pg3, dst_ip=nat_ip_vrf20)
3238 self.pg3.add_stream(pkts)
3239 self.pg_enable_capture(self.pg_interfaces)
3240 self.pg_start()
3241 capture = self.pg6.get_capture(len(pkts))
3242 self.verify_capture_in(capture, self.pg6)
3243
Matus Fabian161c59c2017-07-21 03:46:03 -07003244 def test_output_feature_hairpinning(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07003245 """ NAT44 interface output feature hairpinning (in2out postrouting) """
Matus Fabian93d84c92017-07-19 08:06:01 -07003246 host = self.pg0.remote_hosts[0]
3247 server = self.pg0.remote_hosts[1]
3248 host_in_port = 1234
3249 host_out_port = 0
3250 server_in_port = 5678
3251 server_out_port = 8765
3252
Matus Fabian2ba92e32017-08-21 07:05:03 -07003253 self.nat44_add_address(self.nat_addr)
3254 self.vapi.nat44_interface_add_del_output_feature(self.pg0.sw_if_index)
3255 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
3256 is_inside=0)
Matus Fabian93d84c92017-07-19 08:06:01 -07003257
3258 # add static mapping for server
Matus Fabian2ba92e32017-08-21 07:05:03 -07003259 self.nat44_add_static_mapping(server.ip4, self.nat_addr,
3260 server_in_port, server_out_port,
3261 proto=IP_PROTOS.tcp)
Matus Fabian93d84c92017-07-19 08:06:01 -07003262
3263 # send packet from host to server
3264 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07003265 IP(src=host.ip4, dst=self.nat_addr) /
Matus Fabian93d84c92017-07-19 08:06:01 -07003266 TCP(sport=host_in_port, dport=server_out_port))
3267 self.pg0.add_stream(p)
3268 self.pg_enable_capture(self.pg_interfaces)
3269 self.pg_start()
3270 capture = self.pg0.get_capture(1)
3271 p = capture[0]
3272 try:
3273 ip = p[IP]
3274 tcp = p[TCP]
Matus Fabian2ba92e32017-08-21 07:05:03 -07003275 self.assertEqual(ip.src, self.nat_addr)
Matus Fabian93d84c92017-07-19 08:06:01 -07003276 self.assertEqual(ip.dst, server.ip4)
3277 self.assertNotEqual(tcp.sport, host_in_port)
3278 self.assertEqual(tcp.dport, server_in_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02003279 self.assert_packet_checksums_valid(p)
Matus Fabian93d84c92017-07-19 08:06:01 -07003280 host_out_port = tcp.sport
3281 except:
3282 self.logger.error(ppp("Unexpected or invalid packet:", p))
3283 raise
3284
3285 # send reply from server to host
3286 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07003287 IP(src=server.ip4, dst=self.nat_addr) /
Matus Fabian93d84c92017-07-19 08:06:01 -07003288 TCP(sport=server_in_port, dport=host_out_port))
3289 self.pg0.add_stream(p)
3290 self.pg_enable_capture(self.pg_interfaces)
3291 self.pg_start()
3292 capture = self.pg0.get_capture(1)
3293 p = capture[0]
3294 try:
3295 ip = p[IP]
3296 tcp = p[TCP]
Matus Fabian2ba92e32017-08-21 07:05:03 -07003297 self.assertEqual(ip.src, self.nat_addr)
Matus Fabian93d84c92017-07-19 08:06:01 -07003298 self.assertEqual(ip.dst, host.ip4)
3299 self.assertEqual(tcp.sport, server_out_port)
3300 self.assertEqual(tcp.dport, host_in_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02003301 self.assert_packet_checksums_valid(p)
Matus Fabian93d84c92017-07-19 08:06:01 -07003302 except:
Matus Fabiane82488f2018-01-18 03:38:45 -08003303 self.logger.error(ppp("Unexpected or invalid packet:", p))
Matus Fabian93d84c92017-07-19 08:06:01 -07003304 raise
3305
Matus Fabian36ea2d62017-10-24 04:13:49 -07003306 def test_one_armed_nat44(self):
3307 """ One armed NAT44 """
3308 remote_host = self.pg9.remote_hosts[0]
3309 local_host = self.pg9.remote_hosts[1]
3310 external_port = 0
3311
3312 self.nat44_add_address(self.nat_addr)
3313 self.vapi.nat44_interface_add_del_feature(self.pg9.sw_if_index)
3314 self.vapi.nat44_interface_add_del_feature(self.pg9.sw_if_index,
3315 is_inside=0)
3316
3317 # in2out
3318 p = (Ether(src=self.pg9.remote_mac, dst=self.pg9.local_mac) /
3319 IP(src=local_host.ip4, dst=remote_host.ip4) /
3320 TCP(sport=12345, dport=80))
3321 self.pg9.add_stream(p)
3322 self.pg_enable_capture(self.pg_interfaces)
3323 self.pg_start()
3324 capture = self.pg9.get_capture(1)
3325 p = capture[0]
3326 try:
3327 ip = p[IP]
3328 tcp = p[TCP]
3329 self.assertEqual(ip.src, self.nat_addr)
3330 self.assertEqual(ip.dst, remote_host.ip4)
3331 self.assertNotEqual(tcp.sport, 12345)
3332 external_port = tcp.sport
3333 self.assertEqual(tcp.dport, 80)
Klement Sekerad81ae412018-05-16 10:52:54 +02003334 self.assert_packet_checksums_valid(p)
Matus Fabian36ea2d62017-10-24 04:13:49 -07003335 except:
3336 self.logger.error(ppp("Unexpected or invalid packet:", p))
3337 raise
3338
3339 # out2in
3340 p = (Ether(src=self.pg9.remote_mac, dst=self.pg9.local_mac) /
3341 IP(src=remote_host.ip4, dst=self.nat_addr) /
3342 TCP(sport=80, dport=external_port))
3343 self.pg9.add_stream(p)
3344 self.pg_enable_capture(self.pg_interfaces)
3345 self.pg_start()
3346 capture = self.pg9.get_capture(1)
3347 p = capture[0]
3348 try:
3349 ip = p[IP]
3350 tcp = p[TCP]
3351 self.assertEqual(ip.src, remote_host.ip4)
3352 self.assertEqual(ip.dst, local_host.ip4)
3353 self.assertEqual(tcp.sport, 80)
3354 self.assertEqual(tcp.dport, 12345)
Klement Sekerad81ae412018-05-16 10:52:54 +02003355 self.assert_packet_checksums_valid(p)
Matus Fabian36ea2d62017-10-24 04:13:49 -07003356 except:
3357 self.logger.error(ppp("Unexpected or invalid packet:", p))
3358 raise
3359
Matus Fabian5ba86f72017-10-26 03:37:38 -07003360 def test_del_session(self):
3361 """ Delete NAT44 session """
3362 self.nat44_add_address(self.nat_addr)
3363 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3364 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3365 is_inside=0)
3366
3367 pkts = self.create_stream_in(self.pg0, self.pg1)
3368 self.pg0.add_stream(pkts)
3369 self.pg_enable_capture(self.pg_interfaces)
3370 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07003371 self.pg1.get_capture(len(pkts))
Matus Fabian5ba86f72017-10-26 03:37:38 -07003372
3373 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
3374 nsessions = len(sessions)
3375
3376 self.vapi.nat44_del_session(sessions[0].inside_ip_address,
3377 sessions[0].inside_port,
3378 sessions[0].protocol)
3379 self.vapi.nat44_del_session(sessions[1].outside_ip_address,
3380 sessions[1].outside_port,
3381 sessions[1].protocol,
3382 is_in=0)
3383
3384 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
3385 self.assertEqual(nsessions - len(sessions), 2)
3386
Matus Fabian68ba8802018-08-08 05:52:47 -07003387 self.vapi.nat44_del_session(sessions[0].inside_ip_address,
3388 sessions[0].inside_port,
3389 sessions[0].protocol)
3390
3391 self.verify_no_nat44_user()
3392
Matus Fabianefcd1e92017-08-15 06:59:19 -07003393 def test_set_get_reass(self):
3394 """ NAT44 set/get virtual fragmentation reassembly """
3395 reas_cfg1 = self.vapi.nat_get_reass()
3396
3397 self.vapi.nat_set_reass(timeout=reas_cfg1.ip4_timeout + 5,
3398 max_reass=reas_cfg1.ip4_max_reass * 2,
3399 max_frag=reas_cfg1.ip4_max_frag * 2)
3400
3401 reas_cfg2 = self.vapi.nat_get_reass()
3402
3403 self.assertEqual(reas_cfg1.ip4_timeout + 5, reas_cfg2.ip4_timeout)
3404 self.assertEqual(reas_cfg1.ip4_max_reass * 2, reas_cfg2.ip4_max_reass)
3405 self.assertEqual(reas_cfg1.ip4_max_frag * 2, reas_cfg2.ip4_max_frag)
3406
3407 self.vapi.nat_set_reass(drop_frag=1)
3408 self.assertTrue(self.vapi.nat_get_reass().ip4_drop_frag)
3409
3410 def test_frag_in_order(self):
3411 """ NAT44 translate fragments arriving in order """
Juraj Slobodafe0aa762018-07-23 12:22:54 +02003412
Matus Fabianefcd1e92017-08-15 06:59:19 -07003413 self.nat44_add_address(self.nat_addr)
3414 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3415 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3416 is_inside=0)
3417
Matus Fabianda41d722018-10-19 04:01:19 -07003418 self.frag_in_order(proto=IP_PROTOS.tcp)
3419 self.frag_in_order(proto=IP_PROTOS.udp)
3420 self.frag_in_order(proto=IP_PROTOS.icmp)
Matus Fabianefcd1e92017-08-15 06:59:19 -07003421
Matus Fabian111add72018-11-20 02:19:05 -08003422 def test_frag_forwarding(self):
3423 """ NAT44 forwarding fragment test """
3424 self.vapi.nat44_add_interface_addr(self.pg1.sw_if_index)
3425 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3426 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3427 is_inside=0)
3428 self.vapi.nat44_forwarding_enable_disable(1)
3429
3430 data = "A" * 16 + "B" * 16 + "C" * 3
3431 pkts = self.create_stream_frag(self.pg1,
3432 self.pg0.remote_ip4,
3433 4789,
3434 4789,
3435 data,
3436 proto=IP_PROTOS.udp)
3437 self.pg1.add_stream(pkts)
3438 self.pg_enable_capture(self.pg_interfaces)
3439 self.pg_start()
3440 frags = self.pg0.get_capture(len(pkts))
3441 p = self.reass_frags_and_verify(frags,
3442 self.pg1.remote_ip4,
3443 self.pg0.remote_ip4)
3444 self.assertEqual(p[UDP].sport, 4789)
3445 self.assertEqual(p[UDP].dport, 4789)
3446 self.assertEqual(data, p[Raw].load)
3447
Matus Fabianefcd1e92017-08-15 06:59:19 -07003448 def test_reass_hairpinning(self):
3449 """ NAT44 fragments hairpinning """
Juraj Slobodafe0aa762018-07-23 12:22:54 +02003450
Matus Fabianda41d722018-10-19 04:01:19 -07003451 self.server = self.pg0.remote_hosts[1]
3452 self.host_in_port = random.randint(1025, 65535)
3453 self.server_in_port = random.randint(1025, 65535)
3454 self.server_out_port = random.randint(1025, 65535)
Matus Fabianefcd1e92017-08-15 06:59:19 -07003455
3456 self.nat44_add_address(self.nat_addr)
3457 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3458 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3459 is_inside=0)
3460 # add static mapping for server
Matus Fabianda41d722018-10-19 04:01:19 -07003461 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr,
3462 self.server_in_port,
3463 self.server_out_port,
Matus Fabianefcd1e92017-08-15 06:59:19 -07003464 proto=IP_PROTOS.tcp)
Matus Fabianda41d722018-10-19 04:01:19 -07003465 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr,
3466 self.server_in_port,
3467 self.server_out_port,
3468 proto=IP_PROTOS.udp)
3469 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr)
Matus Fabianefcd1e92017-08-15 06:59:19 -07003470
Matus Fabianda41d722018-10-19 04:01:19 -07003471 self.reass_hairpinning(proto=IP_PROTOS.tcp)
3472 self.reass_hairpinning(proto=IP_PROTOS.udp)
3473 self.reass_hairpinning(proto=IP_PROTOS.icmp)
Matus Fabianefcd1e92017-08-15 06:59:19 -07003474
3475 def test_frag_out_of_order(self):
3476 """ NAT44 translate fragments arriving out of order """
Juraj Slobodafe0aa762018-07-23 12:22:54 +02003477
Matus Fabianefcd1e92017-08-15 06:59:19 -07003478 self.nat44_add_address(self.nat_addr)
3479 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3480 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3481 is_inside=0)
3482
Matus Fabianda41d722018-10-19 04:01:19 -07003483 self.frag_out_of_order(proto=IP_PROTOS.tcp)
3484 self.frag_out_of_order(proto=IP_PROTOS.udp)
3485 self.frag_out_of_order(proto=IP_PROTOS.icmp)
Matus Fabianefcd1e92017-08-15 06:59:19 -07003486
Matus Fabian27697102017-11-09 01:43:47 -08003487 def test_port_restricted(self):
3488 """ Port restricted NAT44 (MAP-E CE) """
3489 self.nat44_add_address(self.nat_addr)
3490 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3491 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3492 is_inside=0)
Matus Fabian5d28c7a2018-09-04 03:55:45 -07003493 self.vapi.nat_set_addr_and_port_alloc_alg(alg=1,
3494 psid_offset=6,
3495 psid_length=6,
3496 psid=10)
Matus Fabian27697102017-11-09 01:43:47 -08003497
3498 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3499 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3500 TCP(sport=4567, dport=22))
3501 self.pg0.add_stream(p)
3502 self.pg_enable_capture(self.pg_interfaces)
3503 self.pg_start()
3504 capture = self.pg1.get_capture(1)
3505 p = capture[0]
3506 try:
3507 ip = p[IP]
3508 tcp = p[TCP]
3509 self.assertEqual(ip.dst, self.pg1.remote_ip4)
3510 self.assertEqual(ip.src, self.nat_addr)
3511 self.assertEqual(tcp.dport, 22)
3512 self.assertNotEqual(tcp.sport, 4567)
3513 self.assertEqual((tcp.sport >> 6) & 63, 10)
Klement Sekerad81ae412018-05-16 10:52:54 +02003514 self.assert_packet_checksums_valid(p)
Matus Fabian27697102017-11-09 01:43:47 -08003515 except:
3516 self.logger.error(ppp("Unexpected or invalid packet:", p))
3517 raise
3518
Matus Fabian5d28c7a2018-09-04 03:55:45 -07003519 def test_port_range(self):
3520 """ External address port range """
3521 self.nat44_add_address(self.nat_addr)
3522 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3523 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3524 is_inside=0)
3525 self.vapi.nat_set_addr_and_port_alloc_alg(alg=2,
3526 start_port=1025,
3527 end_port=1027)
3528
3529 pkts = []
3530 for port in range(0, 5):
3531 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3532 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3533 TCP(sport=1125 + port))
3534 pkts.append(p)
3535 self.pg0.add_stream(pkts)
3536 self.pg_enable_capture(self.pg_interfaces)
3537 self.pg_start()
3538 capture = self.pg1.get_capture(3)
3539 for p in capture:
3540 tcp = p[TCP]
3541 self.assertGreaterEqual(tcp.sport, 1025)
3542 self.assertLessEqual(tcp.sport, 1027)
3543
Matus Fabiana6110b62018-06-13 05:39:07 -07003544 def test_ipfix_max_frags(self):
3545 """ IPFIX logging maximum fragments pending reassembly exceeded """
3546 self.nat44_add_address(self.nat_addr)
3547 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3548 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3549 is_inside=0)
Matus Fabiana7f8b222018-09-05 06:01:55 -07003550 self.vapi.nat_set_reass(max_frag=1)
Matus Fabiana6110b62018-06-13 05:39:07 -07003551 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
3552 src_address=self.pg3.local_ip4n,
3553 path_mtu=512,
3554 template_interval=10)
3555 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
3556 src_port=self.ipfix_src_port)
3557
3558 data = "A" * 4 + "B" * 16 + "C" * 3
3559 self.tcp_port_in = random.randint(1025, 65535)
3560 pkts = self.create_stream_frag(self.pg0,
3561 self.pg1.remote_ip4,
3562 self.tcp_port_in,
3563 20,
3564 data)
Matus Fabiana7f8b222018-09-05 06:01:55 -07003565 pkts.reverse()
3566 self.pg0.add_stream(pkts)
Matus Fabiana6110b62018-06-13 05:39:07 -07003567 self.pg_enable_capture(self.pg_interfaces)
3568 self.pg_start()
3569 self.pg1.assert_nothing_captured()
3570 sleep(1)
3571 self.vapi.cli("ipfix flush") # FIXME this should be an API call
3572 capture = self.pg3.get_capture(9)
3573 ipfix = IPFIXDecoder()
3574 # first load template
3575 for p in capture:
3576 self.assertTrue(p.haslayer(IPFIX))
3577 self.assertEqual(p[IP].src, self.pg3.local_ip4)
3578 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
3579 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
3580 self.assertEqual(p[UDP].dport, 4739)
3581 self.assertEqual(p[IPFIX].observationDomainID,
3582 self.ipfix_domain_id)
3583 if p.haslayer(Template):
3584 ipfix.add_template(p.getlayer(Template))
3585 # verify events in data set
3586 for p in capture:
3587 if p.haslayer(Data):
3588 data = ipfix.decode_data_set(p.getlayer(Set))
Matus Fabiana7f8b222018-09-05 06:01:55 -07003589 self.verify_ipfix_max_fragments_ip4(data, 1,
Matus Fabiana6110b62018-06-13 05:39:07 -07003590 self.pg0.remote_ip4n)
3591
Matus Fabian8008d7c2018-07-09 01:34:20 -07003592 def test_multiple_outside_vrf(self):
3593 """ Multiple outside VRF """
3594 vrf_id1 = 1
3595 vrf_id2 = 2
3596
3597 self.pg1.unconfig_ip4()
3598 self.pg2.unconfig_ip4()
3599 self.vapi.ip_table_add_del(vrf_id1, is_add=1)
3600 self.vapi.ip_table_add_del(vrf_id2, is_add=1)
3601 self.pg1.set_table_ip4(vrf_id1)
3602 self.pg2.set_table_ip4(vrf_id2)
3603 self.pg1.config_ip4()
3604 self.pg2.config_ip4()
3605 self.pg1.resolve_arp()
3606 self.pg2.resolve_arp()
3607
3608 self.nat44_add_address(self.nat_addr)
3609 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3610 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3611 is_inside=0)
3612 self.vapi.nat44_interface_add_del_feature(self.pg2.sw_if_index,
3613 is_inside=0)
3614
3615 try:
3616 # first VRF
3617 pkts = self.create_stream_in(self.pg0, self.pg1)
3618 self.pg0.add_stream(pkts)
3619 self.pg_enable_capture(self.pg_interfaces)
3620 self.pg_start()
3621 capture = self.pg1.get_capture(len(pkts))
3622 self.verify_capture_out(capture, self.nat_addr)
3623
3624 pkts = self.create_stream_out(self.pg1, self.nat_addr)
3625 self.pg1.add_stream(pkts)
3626 self.pg_enable_capture(self.pg_interfaces)
3627 self.pg_start()
3628 capture = self.pg0.get_capture(len(pkts))
3629 self.verify_capture_in(capture, self.pg0)
3630
3631 self.tcp_port_in = 60303
3632 self.udp_port_in = 60304
3633 self.icmp_id_in = 60305
3634
3635 # second VRF
3636 pkts = self.create_stream_in(self.pg0, self.pg2)
3637 self.pg0.add_stream(pkts)
3638 self.pg_enable_capture(self.pg_interfaces)
3639 self.pg_start()
3640 capture = self.pg2.get_capture(len(pkts))
3641 self.verify_capture_out(capture, self.nat_addr)
3642
3643 pkts = self.create_stream_out(self.pg2, self.nat_addr)
3644 self.pg2.add_stream(pkts)
3645 self.pg_enable_capture(self.pg_interfaces)
3646 self.pg_start()
3647 capture = self.pg0.get_capture(len(pkts))
3648 self.verify_capture_in(capture, self.pg0)
3649
3650 finally:
3651 self.pg1.unconfig_ip4()
3652 self.pg2.unconfig_ip4()
3653 self.pg1.set_table_ip4(0)
3654 self.pg2.set_table_ip4(0)
3655 self.pg1.config_ip4()
3656 self.pg2.config_ip4()
3657 self.pg1.resolve_arp()
3658 self.pg2.resolve_arp()
3659
Matus Fabian878c6462018-08-23 00:33:35 -07003660 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
3661 def test_session_timeout(self):
3662 """ NAT44 session timeouts """
3663 self.nat44_add_address(self.nat_addr)
3664 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3665 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3666 is_inside=0)
3667 self.vapi.nat_set_timeouts(udp=5)
3668
3669 max_sessions = 1000
3670 pkts = []
3671 for i in range(0, max_sessions):
3672 src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
3673 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3674 IP(src=src, dst=self.pg1.remote_ip4) /
3675 UDP(sport=1025, dport=53))
3676 pkts.append(p)
3677 self.pg0.add_stream(pkts)
3678 self.pg_enable_capture(self.pg_interfaces)
3679 self.pg_start()
3680 self.pg1.get_capture(max_sessions)
3681
3682 sleep(6)
3683
3684 pkts = []
3685 for i in range(0, max_sessions):
3686 src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
3687 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3688 IP(src=src, dst=self.pg1.remote_ip4) /
3689 UDP(sport=1026, dport=53))
3690 pkts.append(p)
3691 self.pg0.add_stream(pkts)
3692 self.pg_enable_capture(self.pg_interfaces)
3693 self.pg_start()
3694 self.pg1.get_capture(max_sessions)
3695
3696 nsessions = 0
3697 users = self.vapi.nat44_user_dump()
3698 for user in users:
3699 nsessions = nsessions + user.nsessions
3700 self.assertLess(nsessions, 2 * max_sessions)
3701
Matus Fabianbb4e0222018-09-13 02:36:25 -07003702 def test_mss_clamping(self):
3703 """ TCP MSS clamping """
3704 self.nat44_add_address(self.nat_addr)
3705 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3706 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3707 is_inside=0)
3708
3709 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3710 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3711 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
3712 flags="S", options=[('MSS', 1400)]))
3713
3714 self.vapi.nat_set_mss_clamping(enable=1, mss_value=1000)
3715 self.pg0.add_stream(p)
3716 self.pg_enable_capture(self.pg_interfaces)
3717 self.pg_start()
3718 capture = self.pg1.get_capture(1)
3719 # Negotiated MSS value greater than configured - changed
3720 self.verify_mss_value(capture[0], 1000)
3721
3722 self.vapi.nat_set_mss_clamping(enable=0)
3723 self.pg0.add_stream(p)
3724 self.pg_enable_capture(self.pg_interfaces)
3725 self.pg_start()
3726 capture = self.pg1.get_capture(1)
3727 # MSS clamping disabled - negotiated MSS unchanged
3728 self.verify_mss_value(capture[0], 1400)
3729
3730 self.vapi.nat_set_mss_clamping(enable=1, mss_value=1500)
3731 self.pg0.add_stream(p)
3732 self.pg_enable_capture(self.pg_interfaces)
3733 self.pg_start()
3734 capture = self.pg1.get_capture(1)
3735 # Negotiated MSS value smaller than configured - unchanged
3736 self.verify_mss_value(capture[0], 1400)
3737
Matus Fabiana6110b62018-06-13 05:39:07 -07003738 def tearDown(self):
3739 super(TestNAT44, self).tearDown()
3740 if not self.vpp_dead:
3741 self.logger.info(self.vapi.cli("show nat44 addresses"))
3742 self.logger.info(self.vapi.cli("show nat44 interfaces"))
3743 self.logger.info(self.vapi.cli("show nat44 static mappings"))
3744 self.logger.info(self.vapi.cli("show nat44 interface address"))
3745 self.logger.info(self.vapi.cli("show nat44 sessions detail"))
3746 self.logger.info(self.vapi.cli("show nat virtual-reassembly"))
3747 self.logger.info(self.vapi.cli("show nat44 hash tables detail"))
Matus Fabian878c6462018-08-23 00:33:35 -07003748 self.logger.info(self.vapi.cli("show nat timeouts"))
Matus Fabian5d28c7a2018-09-04 03:55:45 -07003749 self.logger.info(
3750 self.vapi.cli("show nat addr-port-assignment-alg"))
Matus Fabiana6110b62018-06-13 05:39:07 -07003751 self.clear_nat44()
3752 self.vapi.cli("clear logging")
3753
3754
3755class TestNAT44EndpointDependent(MethodHolder):
3756 """ Endpoint-Dependent mapping and filtering test cases """
3757
3758 @classmethod
3759 def setUpConstants(cls):
3760 super(TestNAT44EndpointDependent, cls).setUpConstants()
3761 cls.vpp_cmdline.extend(["nat", "{", "endpoint-dependent", "}"])
3762
3763 @classmethod
3764 def setUpClass(cls):
3765 super(TestNAT44EndpointDependent, cls).setUpClass()
3766 cls.vapi.cli("set log class nat level debug")
3767 try:
3768 cls.tcp_port_in = 6303
3769 cls.tcp_port_out = 6303
3770 cls.udp_port_in = 6304
3771 cls.udp_port_out = 6304
3772 cls.icmp_id_in = 6305
3773 cls.icmp_id_out = 6305
3774 cls.nat_addr = '10.0.0.3'
3775 cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
3776 cls.ipfix_src_port = 4739
3777 cls.ipfix_domain_id = 1
3778 cls.tcp_external_port = 80
3779
Matus Fabian8008d7c2018-07-09 01:34:20 -07003780 cls.create_pg_interfaces(range(7))
Matus Fabiana6110b62018-06-13 05:39:07 -07003781 cls.interfaces = list(cls.pg_interfaces[0:3])
3782
3783 for i in cls.interfaces:
3784 i.admin_up()
3785 i.config_ip4()
3786 i.resolve_arp()
3787
3788 cls.pg0.generate_remote_hosts(3)
3789 cls.pg0.configure_ipv4_neighbors()
3790
3791 cls.pg3.admin_up()
3792
3793 cls.pg4.generate_remote_hosts(2)
3794 cls.pg4.config_ip4()
3795 ip_addr_n = socket.inet_pton(socket.AF_INET, "10.0.0.1")
3796 cls.vapi.sw_interface_add_del_address(cls.pg4.sw_if_index,
3797 ip_addr_n,
3798 24)
3799 cls.pg4.admin_up()
3800 cls.pg4.resolve_arp()
3801 cls.pg4._remote_hosts[1]._ip4 = cls.pg4._remote_hosts[0]._ip4
3802 cls.pg4.resolve_arp()
3803
Matus Fabian8008d7c2018-07-09 01:34:20 -07003804 zero_ip4n = socket.inet_pton(socket.AF_INET, "0.0.0.0")
3805 cls.vapi.ip_table_add_del(1, is_add=1)
3806
3807 cls.pg5._local_ip4 = "10.1.1.1"
3808 cls.pg5._local_ip4n = socket.inet_pton(socket.AF_INET,
3809 cls.pg5.local_ip4)
3810 cls.pg5._remote_hosts[0]._ip4 = "10.1.1.2"
3811 cls.pg5._remote_hosts[0]._ip4n = socket.inet_pton(
3812 socket.AF_INET, cls.pg5.remote_ip4)
3813 cls.pg5.set_table_ip4(1)
3814 cls.pg5.config_ip4()
3815 cls.pg5.admin_up()
3816 cls.vapi.ip_add_del_route(dst_address=cls.pg5.remote_ip4n,
3817 dst_address_length=32,
3818 table_id=1,
3819 next_hop_sw_if_index=cls.pg5.sw_if_index,
3820 next_hop_address=zero_ip4n)
3821
3822 cls.pg6._local_ip4 = "10.1.2.1"
3823 cls.pg6._local_ip4n = socket.inet_pton(socket.AF_INET,
3824 cls.pg6.local_ip4)
3825 cls.pg6._remote_hosts[0]._ip4 = "10.1.2.2"
3826 cls.pg6._remote_hosts[0]._ip4n = socket.inet_pton(
3827 socket.AF_INET, cls.pg6.remote_ip4)
3828 cls.pg6.set_table_ip4(1)
3829 cls.pg6.config_ip4()
3830 cls.pg6.admin_up()
3831 cls.vapi.ip_add_del_route(dst_address=cls.pg6.remote_ip4n,
3832 dst_address_length=32,
3833 table_id=1,
3834 next_hop_sw_if_index=cls.pg6.sw_if_index,
3835 next_hop_address=zero_ip4n)
3836
3837 cls.vapi.ip_add_del_route(dst_address=cls.pg6.remote_ip4n,
3838 dst_address_length=16,
3839 next_hop_address=zero_ip4n,
3840 table_id=0,
3841 next_hop_table_id=1)
3842 cls.vapi.ip_add_del_route(dst_address=zero_ip4n,
3843 dst_address_length=0,
3844 next_hop_address=zero_ip4n,
3845 table_id=1,
3846 next_hop_table_id=0)
3847 cls.vapi.ip_add_del_route(dst_address=zero_ip4n,
3848 dst_address_length=0,
3849 table_id=0,
3850 next_hop_sw_if_index=cls.pg1.sw_if_index,
3851 next_hop_address=cls.pg1.local_ip4n)
3852
3853 cls.pg5.resolve_arp()
3854 cls.pg6.resolve_arp()
3855
Matus Fabiana6110b62018-06-13 05:39:07 -07003856 except Exception:
3857 super(TestNAT44EndpointDependent, cls).tearDownClass()
3858 raise
3859
Juraj Slobodafe0aa762018-07-23 12:22:54 +02003860 def test_frag_in_order(self):
3861 """ NAT44 translate fragments arriving in order """
3862 self.nat44_add_address(self.nat_addr)
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.frag_in_order(proto=IP_PROTOS.tcp)
3867 self.frag_in_order(proto=IP_PROTOS.udp)
3868 self.frag_in_order(proto=IP_PROTOS.icmp)
3869
3870 def test_frag_in_order_dont_translate(self):
3871 """ NAT44 don't translate fragments arriving in order """
3872 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3873 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3874 is_inside=0)
3875 self.vapi.nat44_forwarding_enable_disable(enable=True)
3876 self.frag_in_order(proto=IP_PROTOS.tcp, dont_translate=True)
3877
3878 def test_frag_out_of_order(self):
3879 """ NAT44 translate fragments arriving out of order """
3880 self.nat44_add_address(self.nat_addr)
3881 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3882 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3883 is_inside=0)
3884 self.frag_out_of_order(proto=IP_PROTOS.tcp)
3885 self.frag_out_of_order(proto=IP_PROTOS.udp)
3886 self.frag_out_of_order(proto=IP_PROTOS.icmp)
3887
3888 def test_frag_out_of_order_dont_translate(self):
3889 """ NAT44 don't translate fragments arriving out of order """
3890 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3891 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3892 is_inside=0)
3893 self.vapi.nat44_forwarding_enable_disable(enable=True)
3894 self.frag_out_of_order(proto=IP_PROTOS.tcp, dont_translate=True)
3895
3896 def test_frag_in_order_in_plus_out(self):
3897 """ in+out interface fragments in order """
3898 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3899 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
3900 is_inside=0)
3901 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
3902 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3903 is_inside=0)
3904
3905 self.server = self.pg1.remote_hosts[0]
3906
3907 self.server_in_addr = self.server.ip4
3908 self.server_out_addr = '11.11.11.11'
3909 self.server_in_port = random.randint(1025, 65535)
3910 self.server_out_port = random.randint(1025, 65535)
3911
3912 self.nat44_add_address(self.server_out_addr)
3913
3914 # add static mappings for server
3915 self.nat44_add_static_mapping(self.server_in_addr,
3916 self.server_out_addr,
3917 self.server_in_port,
3918 self.server_out_port,
3919 proto=IP_PROTOS.tcp)
3920 self.nat44_add_static_mapping(self.server_in_addr,
3921 self.server_out_addr,
3922 self.server_in_port,
3923 self.server_out_port,
3924 proto=IP_PROTOS.udp)
3925 self.nat44_add_static_mapping(self.server_in_addr,
3926 self.server_out_addr,
3927 proto=IP_PROTOS.icmp)
3928
3929 self.vapi.nat_set_reass(timeout=10)
3930
3931 self.frag_in_order_in_plus_out(proto=IP_PROTOS.tcp)
3932 self.frag_in_order_in_plus_out(proto=IP_PROTOS.udp)
3933 self.frag_in_order_in_plus_out(proto=IP_PROTOS.icmp)
3934
3935 def test_frag_out_of_order_in_plus_out(self):
3936 """ in+out interface fragments out of order """
3937 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3938 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
3939 is_inside=0)
3940 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
3941 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3942 is_inside=0)
3943
3944 self.server = self.pg1.remote_hosts[0]
3945
3946 self.server_in_addr = self.server.ip4
3947 self.server_out_addr = '11.11.11.11'
3948 self.server_in_port = random.randint(1025, 65535)
3949 self.server_out_port = random.randint(1025, 65535)
3950
3951 self.nat44_add_address(self.server_out_addr)
3952
3953 # add static mappings for server
3954 self.nat44_add_static_mapping(self.server_in_addr,
3955 self.server_out_addr,
3956 self.server_in_port,
3957 self.server_out_port,
3958 proto=IP_PROTOS.tcp)
3959 self.nat44_add_static_mapping(self.server_in_addr,
3960 self.server_out_addr,
3961 self.server_in_port,
3962 self.server_out_port,
3963 proto=IP_PROTOS.udp)
3964 self.nat44_add_static_mapping(self.server_in_addr,
3965 self.server_out_addr,
3966 proto=IP_PROTOS.icmp)
3967
3968 self.vapi.nat_set_reass(timeout=10)
3969
3970 self.frag_out_of_order_in_plus_out(proto=IP_PROTOS.tcp)
3971 self.frag_out_of_order_in_plus_out(proto=IP_PROTOS.udp)
3972 self.frag_out_of_order_in_plus_out(proto=IP_PROTOS.icmp)
3973
3974 def test_reass_hairpinning(self):
3975 """ NAT44 fragments hairpinning """
3976 self.server = self.pg0.remote_hosts[1]
3977 self.host_in_port = random.randint(1025, 65535)
3978 self.server_in_port = random.randint(1025, 65535)
3979 self.server_out_port = random.randint(1025, 65535)
3980
3981 self.nat44_add_address(self.nat_addr)
3982 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3983 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3984 is_inside=0)
3985 # add static mapping for server
3986 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr,
3987 self.server_in_port,
3988 self.server_out_port,
3989 proto=IP_PROTOS.tcp)
3990 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr,
3991 self.server_in_port,
3992 self.server_out_port,
3993 proto=IP_PROTOS.udp)
Matus Fabianda41d722018-10-19 04:01:19 -07003994 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr)
Juraj Slobodafe0aa762018-07-23 12:22:54 +02003995
3996 self.reass_hairpinning(proto=IP_PROTOS.tcp)
3997 self.reass_hairpinning(proto=IP_PROTOS.udp)
3998 self.reass_hairpinning(proto=IP_PROTOS.icmp)
3999
Matus Fabiana6110b62018-06-13 05:39:07 -07004000 def test_dynamic(self):
4001 """ NAT44 dynamic translation test """
4002
4003 self.nat44_add_address(self.nat_addr)
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
Matus Fabian69ce30d2018-08-22 01:27:10 -07004008 nat_config = self.vapi.nat_show_config()
4009 self.assertEqual(1, nat_config.endpoint_dependent)
4010
Matus Fabiana6110b62018-06-13 05:39:07 -07004011 # in2out
4012 pkts = self.create_stream_in(self.pg0, self.pg1)
4013 self.pg0.add_stream(pkts)
4014 self.pg_enable_capture(self.pg_interfaces)
4015 self.pg_start()
4016 capture = self.pg1.get_capture(len(pkts))
4017 self.verify_capture_out(capture)
4018
4019 # out2in
4020 pkts = self.create_stream_out(self.pg1)
4021 self.pg1.add_stream(pkts)
4022 self.pg_enable_capture(self.pg_interfaces)
4023 self.pg_start()
4024 capture = self.pg0.get_capture(len(pkts))
4025 self.verify_capture_in(capture, self.pg0)
4026
4027 def test_forwarding(self):
4028 """ NAT44 forwarding test """
4029
4030 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4031 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4032 is_inside=0)
4033 self.vapi.nat44_forwarding_enable_disable(1)
4034
4035 real_ip = self.pg0.remote_ip4n
4036 alias_ip = self.nat_addr_n
4037 self.vapi.nat44_add_del_static_mapping(local_ip=real_ip,
4038 external_ip=alias_ip)
4039
4040 try:
4041 # in2out - static mapping match
4042
4043 pkts = self.create_stream_out(self.pg1)
4044 self.pg1.add_stream(pkts)
4045 self.pg_enable_capture(self.pg_interfaces)
4046 self.pg_start()
4047 capture = self.pg0.get_capture(len(pkts))
4048 self.verify_capture_in(capture, self.pg0)
4049
4050 pkts = self.create_stream_in(self.pg0, self.pg1)
4051 self.pg0.add_stream(pkts)
4052 self.pg_enable_capture(self.pg_interfaces)
4053 self.pg_start()
4054 capture = self.pg1.get_capture(len(pkts))
4055 self.verify_capture_out(capture, same_port=True)
4056
4057 # in2out - no static mapping match
4058
4059 host0 = self.pg0.remote_hosts[0]
4060 self.pg0.remote_hosts[0] = self.pg0.remote_hosts[1]
4061 try:
4062 pkts = self.create_stream_out(self.pg1,
4063 dst_ip=self.pg0.remote_ip4,
4064 use_inside_ports=True)
4065 self.pg1.add_stream(pkts)
4066 self.pg_enable_capture(self.pg_interfaces)
4067 self.pg_start()
4068 capture = self.pg0.get_capture(len(pkts))
4069 self.verify_capture_in(capture, self.pg0)
4070
4071 pkts = self.create_stream_in(self.pg0, self.pg1)
4072 self.pg0.add_stream(pkts)
4073 self.pg_enable_capture(self.pg_interfaces)
4074 self.pg_start()
4075 capture = self.pg1.get_capture(len(pkts))
4076 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
4077 same_port=True)
4078 finally:
4079 self.pg0.remote_hosts[0] = host0
4080
4081 user = self.pg0.remote_hosts[1]
4082 sessions = self.vapi.nat44_user_session_dump(user.ip4n, 0)
4083 self.assertEqual(len(sessions), 3)
4084 self.assertTrue(sessions[0].ext_host_valid)
4085 self.vapi.nat44_del_session(
4086 sessions[0].inside_ip_address,
4087 sessions[0].inside_port,
4088 sessions[0].protocol,
4089 ext_host_address=sessions[0].ext_host_address,
4090 ext_host_port=sessions[0].ext_host_port)
4091 sessions = self.vapi.nat44_user_session_dump(user.ip4n, 0)
4092 self.assertEqual(len(sessions), 2)
4093
4094 finally:
4095 self.vapi.nat44_forwarding_enable_disable(0)
4096 self.vapi.nat44_add_del_static_mapping(local_ip=real_ip,
4097 external_ip=alias_ip,
4098 is_add=0)
4099
4100 def test_static_lb(self):
4101 """ NAT44 local service load balancing """
4102 external_addr_n = socket.inet_pton(socket.AF_INET, self.nat_addr)
4103 external_port = 80
4104 local_port = 8080
4105 server1 = self.pg0.remote_hosts[0]
4106 server2 = self.pg0.remote_hosts[1]
4107
4108 locals = [{'addr': server1.ip4n,
4109 'port': local_port,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07004110 'probability': 70,
4111 'vrf_id': 0},
Matus Fabiana6110b62018-06-13 05:39:07 -07004112 {'addr': server2.ip4n,
4113 'port': local_port,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07004114 'probability': 30,
4115 'vrf_id': 0}]
Matus Fabiana6110b62018-06-13 05:39:07 -07004116
4117 self.nat44_add_address(self.nat_addr)
4118 self.vapi.nat44_add_del_lb_static_mapping(external_addr_n,
4119 external_port,
4120 IP_PROTOS.tcp,
4121 local_num=len(locals),
4122 locals=locals)
4123 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4124 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4125 is_inside=0)
4126
4127 # from client to service
4128 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4129 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4130 TCP(sport=12345, dport=external_port))
4131 self.pg1.add_stream(p)
4132 self.pg_enable_capture(self.pg_interfaces)
4133 self.pg_start()
4134 capture = self.pg0.get_capture(1)
4135 p = capture[0]
4136 server = None
4137 try:
4138 ip = p[IP]
4139 tcp = p[TCP]
4140 self.assertIn(ip.dst, [server1.ip4, server2.ip4])
4141 if ip.dst == server1.ip4:
4142 server = server1
4143 else:
4144 server = server2
4145 self.assertEqual(tcp.dport, local_port)
4146 self.assert_packet_checksums_valid(p)
4147 except:
4148 self.logger.error(ppp("Unexpected or invalid packet:", p))
4149 raise
4150
4151 # from service back to client
4152 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
4153 IP(src=server.ip4, dst=self.pg1.remote_ip4) /
4154 TCP(sport=local_port, dport=12345))
4155 self.pg0.add_stream(p)
4156 self.pg_enable_capture(self.pg_interfaces)
4157 self.pg_start()
4158 capture = self.pg1.get_capture(1)
4159 p = capture[0]
4160 try:
4161 ip = p[IP]
4162 tcp = p[TCP]
4163 self.assertEqual(ip.src, self.nat_addr)
4164 self.assertEqual(tcp.sport, external_port)
4165 self.assert_packet_checksums_valid(p)
4166 except:
4167 self.logger.error(ppp("Unexpected or invalid packet:", p))
4168 raise
4169
4170 sessions = self.vapi.nat44_user_session_dump(server.ip4n, 0)
4171 self.assertEqual(len(sessions), 1)
4172 self.assertTrue(sessions[0].ext_host_valid)
4173 self.vapi.nat44_del_session(
4174 sessions[0].inside_ip_address,
4175 sessions[0].inside_port,
4176 sessions[0].protocol,
4177 ext_host_address=sessions[0].ext_host_address,
4178 ext_host_port=sessions[0].ext_host_port)
4179 sessions = self.vapi.nat44_user_session_dump(server.ip4n, 0)
4180 self.assertEqual(len(sessions), 0)
4181
4182 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
4183 def test_static_lb_multi_clients(self):
4184 """ NAT44 local service load balancing - multiple clients"""
4185
4186 external_addr_n = socket.inet_pton(socket.AF_INET, self.nat_addr)
4187 external_port = 80
4188 local_port = 8080
4189 server1 = self.pg0.remote_hosts[0]
4190 server2 = self.pg0.remote_hosts[1]
4191
4192 locals = [{'addr': server1.ip4n,
4193 'port': local_port,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07004194 'probability': 90,
4195 'vrf_id': 0},
Matus Fabiana6110b62018-06-13 05:39:07 -07004196 {'addr': server2.ip4n,
4197 'port': local_port,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07004198 'probability': 10,
4199 'vrf_id': 0}]
Matus Fabiana6110b62018-06-13 05:39:07 -07004200
4201 self.nat44_add_address(self.nat_addr)
4202 self.vapi.nat44_add_del_lb_static_mapping(external_addr_n,
4203 external_port,
4204 IP_PROTOS.tcp,
4205 local_num=len(locals),
4206 locals=locals)
4207 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4208 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4209 is_inside=0)
4210
4211 server1_n = 0
4212 server2_n = 0
4213 clients = ip4_range(self.pg1.remote_ip4, 10, 50)
4214 pkts = []
4215 for client in clients:
4216 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4217 IP(src=client, dst=self.nat_addr) /
4218 TCP(sport=12345, dport=external_port))
4219 pkts.append(p)
4220 self.pg1.add_stream(pkts)
4221 self.pg_enable_capture(self.pg_interfaces)
4222 self.pg_start()
4223 capture = self.pg0.get_capture(len(pkts))
4224 for p in capture:
4225 if p[IP].dst == server1.ip4:
4226 server1_n += 1
4227 else:
4228 server2_n += 1
Paul Vinciguerra3d2df212018-11-24 23:19:53 -08004229 self.assertGreater(server1_n, server2_n)
Matus Fabiana6110b62018-06-13 05:39:07 -07004230
4231 def test_static_lb_2(self):
4232 """ NAT44 local service load balancing (asymmetrical rule) """
4233 external_addr_n = socket.inet_pton(socket.AF_INET, self.nat_addr)
4234 external_port = 80
4235 local_port = 8080
4236 server1 = self.pg0.remote_hosts[0]
4237 server2 = self.pg0.remote_hosts[1]
4238
4239 locals = [{'addr': server1.ip4n,
4240 'port': local_port,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07004241 'probability': 70,
4242 'vrf_id': 0},
Matus Fabiana6110b62018-06-13 05:39:07 -07004243 {'addr': server2.ip4n,
4244 'port': local_port,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07004245 'probability': 30,
4246 'vrf_id': 0}]
Matus Fabiana6110b62018-06-13 05:39:07 -07004247
4248 self.vapi.nat44_forwarding_enable_disable(1)
4249 self.vapi.nat44_add_del_lb_static_mapping(external_addr_n,
4250 external_port,
4251 IP_PROTOS.tcp,
4252 out2in_only=1,
4253 local_num=len(locals),
4254 locals=locals)
4255 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4256 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4257 is_inside=0)
4258
4259 # from client to service
4260 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4261 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4262 TCP(sport=12345, dport=external_port))
4263 self.pg1.add_stream(p)
4264 self.pg_enable_capture(self.pg_interfaces)
4265 self.pg_start()
4266 capture = self.pg0.get_capture(1)
4267 p = capture[0]
4268 server = None
4269 try:
4270 ip = p[IP]
4271 tcp = p[TCP]
4272 self.assertIn(ip.dst, [server1.ip4, server2.ip4])
4273 if ip.dst == server1.ip4:
4274 server = server1
4275 else:
4276 server = server2
4277 self.assertEqual(tcp.dport, local_port)
4278 self.assert_packet_checksums_valid(p)
4279 except:
4280 self.logger.error(ppp("Unexpected or invalid packet:", p))
4281 raise
4282
4283 # from service back to client
4284 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
4285 IP(src=server.ip4, dst=self.pg1.remote_ip4) /
4286 TCP(sport=local_port, dport=12345))
4287 self.pg0.add_stream(p)
4288 self.pg_enable_capture(self.pg_interfaces)
4289 self.pg_start()
4290 capture = self.pg1.get_capture(1)
4291 p = capture[0]
4292 try:
4293 ip = p[IP]
4294 tcp = p[TCP]
4295 self.assertEqual(ip.src, self.nat_addr)
4296 self.assertEqual(tcp.sport, external_port)
4297 self.assert_packet_checksums_valid(p)
4298 except:
4299 self.logger.error(ppp("Unexpected or invalid packet:", p))
4300 raise
4301
4302 # from client to server (no translation)
4303 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4304 IP(src=self.pg1.remote_ip4, dst=server1.ip4) /
4305 TCP(sport=12346, dport=local_port))
4306 self.pg1.add_stream(p)
4307 self.pg_enable_capture(self.pg_interfaces)
4308 self.pg_start()
4309 capture = self.pg0.get_capture(1)
4310 p = capture[0]
4311 server = None
4312 try:
4313 ip = p[IP]
4314 tcp = p[TCP]
4315 self.assertEqual(ip.dst, server1.ip4)
4316 self.assertEqual(tcp.dport, local_port)
4317 self.assert_packet_checksums_valid(p)
4318 except:
4319 self.logger.error(ppp("Unexpected or invalid packet:", p))
4320 raise
4321
4322 # from service back to client (no translation)
4323 p = (Ether(src=server1.mac, dst=self.pg0.local_mac) /
4324 IP(src=server1.ip4, dst=self.pg1.remote_ip4) /
4325 TCP(sport=local_port, dport=12346))
4326 self.pg0.add_stream(p)
4327 self.pg_enable_capture(self.pg_interfaces)
4328 self.pg_start()
4329 capture = self.pg1.get_capture(1)
4330 p = capture[0]
4331 try:
4332 ip = p[IP]
4333 tcp = p[TCP]
4334 self.assertEqual(ip.src, server1.ip4)
4335 self.assertEqual(tcp.sport, local_port)
4336 self.assert_packet_checksums_valid(p)
4337 except:
4338 self.logger.error(ppp("Unexpected or invalid packet:", p))
4339 raise
4340
Matus Fabianea5b5be2018-09-03 05:02:23 -07004341 def test_lb_affinity(self):
4342 """ NAT44 local service load balancing affinity """
4343 external_addr_n = socket.inet_pton(socket.AF_INET, self.nat_addr)
4344 external_port = 80
4345 local_port = 8080
4346 server1 = self.pg0.remote_hosts[0]
4347 server2 = self.pg0.remote_hosts[1]
4348
4349 locals = [{'addr': server1.ip4n,
4350 'port': local_port,
4351 'probability': 50,
4352 'vrf_id': 0},
4353 {'addr': server2.ip4n,
4354 'port': local_port,
4355 'probability': 50,
4356 'vrf_id': 0}]
4357
4358 self.nat44_add_address(self.nat_addr)
4359 self.vapi.nat44_add_del_lb_static_mapping(external_addr_n,
4360 external_port,
4361 IP_PROTOS.tcp,
4362 affinity=10800,
4363 local_num=len(locals),
4364 locals=locals)
4365 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4366 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4367 is_inside=0)
4368
4369 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
4370 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4371 TCP(sport=1025, dport=external_port))
4372 self.pg1.add_stream(p)
4373 self.pg_enable_capture(self.pg_interfaces)
4374 self.pg_start()
4375 capture = self.pg0.get_capture(1)
4376 backend = capture[0][IP].dst
4377
4378 sessions = self.vapi.nat44_user_session_dump(
4379 socket.inet_pton(socket.AF_INET, backend), 0)
4380 self.assertEqual(len(sessions), 1)
4381 self.assertTrue(sessions[0].ext_host_valid)
4382 self.vapi.nat44_del_session(
4383 sessions[0].inside_ip_address,
4384 sessions[0].inside_port,
4385 sessions[0].protocol,
4386 ext_host_address=sessions[0].ext_host_address,
4387 ext_host_port=sessions[0].ext_host_port)
4388
4389 pkts = []
4390 for port in range(1030, 1100):
4391 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
4392 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4393 TCP(sport=port, dport=external_port))
4394 pkts.append(p)
4395 self.pg1.add_stream(pkts)
4396 self.pg_enable_capture(self.pg_interfaces)
4397 self.pg_start()
4398 capture = self.pg0.get_capture(len(pkts))
4399 for p in capture:
4400 self.assertEqual(p[IP].dst, backend)
4401
Matus Fabiana6110b62018-06-13 05:39:07 -07004402 def test_unknown_proto(self):
4403 """ NAT44 translate packet with unknown protocol """
4404 self.nat44_add_address(self.nat_addr)
4405 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4406 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4407 is_inside=0)
4408
4409 # in2out
4410 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
4411 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4412 TCP(sport=self.tcp_port_in, dport=20))
4413 self.pg0.add_stream(p)
4414 self.pg_enable_capture(self.pg_interfaces)
4415 self.pg_start()
4416 p = self.pg1.get_capture(1)
4417
4418 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
4419 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4420 GRE() /
4421 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
4422 TCP(sport=1234, dport=1234))
4423 self.pg0.add_stream(p)
4424 self.pg_enable_capture(self.pg_interfaces)
4425 self.pg_start()
4426 p = self.pg1.get_capture(1)
4427 packet = p[0]
4428 try:
4429 self.assertEqual(packet[IP].src, self.nat_addr)
4430 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
4431 self.assertTrue(packet.haslayer(GRE))
4432 self.assert_packet_checksums_valid(packet)
4433 except:
4434 self.logger.error(ppp("Unexpected or invalid packet:", packet))
4435 raise
4436
4437 # out2in
4438 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
4439 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4440 GRE() /
4441 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
4442 TCP(sport=1234, dport=1234))
4443 self.pg1.add_stream(p)
4444 self.pg_enable_capture(self.pg_interfaces)
4445 self.pg_start()
4446 p = self.pg0.get_capture(1)
4447 packet = p[0]
4448 try:
4449 self.assertEqual(packet[IP].src, self.pg1.remote_ip4)
4450 self.assertEqual(packet[IP].dst, self.pg0.remote_ip4)
4451 self.assertTrue(packet.haslayer(GRE))
4452 self.assert_packet_checksums_valid(packet)
4453 except:
4454 self.logger.error(ppp("Unexpected or invalid packet:", packet))
4455 raise
4456
4457 def test_hairpinning_unknown_proto(self):
4458 """ NAT44 translate packet with unknown protocol - hairpinning """
4459 host = self.pg0.remote_hosts[0]
4460 server = self.pg0.remote_hosts[1]
4461 host_in_port = 1234
4462 server_out_port = 8765
4463 server_nat_ip = "10.0.0.11"
4464
4465 self.nat44_add_address(self.nat_addr)
4466 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4467 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4468 is_inside=0)
4469
4470 # add static mapping for server
4471 self.nat44_add_static_mapping(server.ip4, server_nat_ip)
4472
4473 # host to server
4474 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
4475 IP(src=host.ip4, dst=server_nat_ip) /
4476 TCP(sport=host_in_port, dport=server_out_port))
4477 self.pg0.add_stream(p)
4478 self.pg_enable_capture(self.pg_interfaces)
4479 self.pg_start()
4480 self.pg0.get_capture(1)
4481
4482 p = (Ether(dst=self.pg0.local_mac, src=host.mac) /
4483 IP(src=host.ip4, dst=server_nat_ip) /
4484 GRE() /
4485 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
4486 TCP(sport=1234, dport=1234))
4487 self.pg0.add_stream(p)
4488 self.pg_enable_capture(self.pg_interfaces)
4489 self.pg_start()
4490 p = self.pg0.get_capture(1)
4491 packet = p[0]
4492 try:
4493 self.assertEqual(packet[IP].src, self.nat_addr)
4494 self.assertEqual(packet[IP].dst, server.ip4)
4495 self.assertTrue(packet.haslayer(GRE))
4496 self.assert_packet_checksums_valid(packet)
4497 except:
4498 self.logger.error(ppp("Unexpected or invalid packet:", packet))
4499 raise
4500
4501 # server to host
4502 p = (Ether(dst=self.pg0.local_mac, src=server.mac) /
4503 IP(src=server.ip4, dst=self.nat_addr) /
4504 GRE() /
4505 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
4506 TCP(sport=1234, dport=1234))
4507 self.pg0.add_stream(p)
4508 self.pg_enable_capture(self.pg_interfaces)
4509 self.pg_start()
4510 p = self.pg0.get_capture(1)
4511 packet = p[0]
4512 try:
4513 self.assertEqual(packet[IP].src, server_nat_ip)
4514 self.assertEqual(packet[IP].dst, host.ip4)
4515 self.assertTrue(packet.haslayer(GRE))
4516 self.assert_packet_checksums_valid(packet)
4517 except:
4518 self.logger.error(ppp("Unexpected or invalid packet:", packet))
4519 raise
4520
4521 def test_output_feature_and_service(self):
4522 """ NAT44 interface output feature and services """
4523 external_addr = '1.2.3.4'
4524 external_port = 80
4525 local_port = 8080
4526
4527 self.vapi.nat44_forwarding_enable_disable(1)
4528 self.nat44_add_address(self.nat_addr)
4529 self.vapi.nat44_add_del_identity_mapping(ip=self.pg1.remote_ip4n)
4530 self.nat44_add_static_mapping(self.pg0.remote_ip4, external_addr,
4531 local_port, external_port,
4532 proto=IP_PROTOS.tcp, out2in_only=1)
4533 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4534 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
4535 is_inside=0)
4536 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
4537 is_inside=0)
4538
4539 # from client to service
4540 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4541 IP(src=self.pg1.remote_ip4, dst=external_addr) /
4542 TCP(sport=12345, dport=external_port))
4543 self.pg1.add_stream(p)
4544 self.pg_enable_capture(self.pg_interfaces)
4545 self.pg_start()
4546 capture = self.pg0.get_capture(1)
4547 p = capture[0]
4548 try:
4549 ip = p[IP]
4550 tcp = p[TCP]
4551 self.assertEqual(ip.dst, self.pg0.remote_ip4)
4552 self.assertEqual(tcp.dport, local_port)
4553 self.assert_packet_checksums_valid(p)
4554 except:
4555 self.logger.error(ppp("Unexpected or invalid packet:", p))
4556 raise
4557
4558 # from service back to client
4559 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4560 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4561 TCP(sport=local_port, dport=12345))
4562 self.pg0.add_stream(p)
4563 self.pg_enable_capture(self.pg_interfaces)
4564 self.pg_start()
4565 capture = self.pg1.get_capture(1)
4566 p = capture[0]
4567 try:
4568 ip = p[IP]
4569 tcp = p[TCP]
4570 self.assertEqual(ip.src, external_addr)
4571 self.assertEqual(tcp.sport, external_port)
4572 self.assert_packet_checksums_valid(p)
4573 except:
4574 self.logger.error(ppp("Unexpected or invalid packet:", p))
4575 raise
4576
4577 # from local network host to external network
4578 pkts = self.create_stream_in(self.pg0, self.pg1)
4579 self.pg0.add_stream(pkts)
4580 self.pg_enable_capture(self.pg_interfaces)
4581 self.pg_start()
4582 capture = self.pg1.get_capture(len(pkts))
4583 self.verify_capture_out(capture)
4584 pkts = self.create_stream_in(self.pg0, self.pg1)
4585 self.pg0.add_stream(pkts)
4586 self.pg_enable_capture(self.pg_interfaces)
4587 self.pg_start()
4588 capture = self.pg1.get_capture(len(pkts))
4589 self.verify_capture_out(capture)
4590
4591 # from external network back to local network host
4592 pkts = self.create_stream_out(self.pg1)
4593 self.pg1.add_stream(pkts)
4594 self.pg_enable_capture(self.pg_interfaces)
4595 self.pg_start()
4596 capture = self.pg0.get_capture(len(pkts))
4597 self.verify_capture_in(capture, self.pg0)
4598
4599 def test_output_feature_and_service2(self):
4600 """ NAT44 interface output feature and service host direct access """
4601 self.vapi.nat44_forwarding_enable_disable(1)
4602 self.nat44_add_address(self.nat_addr)
4603 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
4604 is_inside=0)
4605
4606 # session initiaded from service host - translate
4607 pkts = self.create_stream_in(self.pg0, self.pg1)
4608 self.pg0.add_stream(pkts)
4609 self.pg_enable_capture(self.pg_interfaces)
4610 self.pg_start()
4611 capture = self.pg1.get_capture(len(pkts))
4612 self.verify_capture_out(capture)
4613
4614 pkts = self.create_stream_out(self.pg1)
4615 self.pg1.add_stream(pkts)
4616 self.pg_enable_capture(self.pg_interfaces)
4617 self.pg_start()
4618 capture = self.pg0.get_capture(len(pkts))
4619 self.verify_capture_in(capture, self.pg0)
4620
4621 # session initiaded from remote host - do not translate
4622 self.tcp_port_in = 60303
4623 self.udp_port_in = 60304
4624 self.icmp_id_in = 60305
4625 pkts = self.create_stream_out(self.pg1,
4626 self.pg0.remote_ip4,
4627 use_inside_ports=True)
4628 self.pg1.add_stream(pkts)
4629 self.pg_enable_capture(self.pg_interfaces)
4630 self.pg_start()
4631 capture = self.pg0.get_capture(len(pkts))
4632 self.verify_capture_in(capture, self.pg0)
4633
4634 pkts = self.create_stream_in(self.pg0, self.pg1)
4635 self.pg0.add_stream(pkts)
4636 self.pg_enable_capture(self.pg_interfaces)
4637 self.pg_start()
4638 capture = self.pg1.get_capture(len(pkts))
4639 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
4640 same_port=True)
4641
4642 def test_output_feature_and_service3(self):
4643 """ NAT44 interface output feature and DST NAT """
4644 external_addr = '1.2.3.4'
4645 external_port = 80
4646 local_port = 8080
4647
4648 self.vapi.nat44_forwarding_enable_disable(1)
4649 self.nat44_add_address(self.nat_addr)
4650 self.nat44_add_static_mapping(self.pg1.remote_ip4, external_addr,
4651 local_port, external_port,
4652 proto=IP_PROTOS.tcp, out2in_only=1)
4653 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4654 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
4655 is_inside=0)
4656 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
4657 is_inside=0)
4658
4659 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4660 IP(src=self.pg0.remote_ip4, dst=external_addr) /
4661 TCP(sport=12345, dport=external_port))
4662 self.pg0.add_stream(p)
4663 self.pg_enable_capture(self.pg_interfaces)
4664 self.pg_start()
4665 capture = self.pg1.get_capture(1)
4666 p = capture[0]
4667 try:
4668 ip = p[IP]
4669 tcp = p[TCP]
4670 self.assertEqual(ip.src, self.pg0.remote_ip4)
4671 self.assertEqual(tcp.sport, 12345)
4672 self.assertEqual(ip.dst, self.pg1.remote_ip4)
4673 self.assertEqual(tcp.dport, local_port)
4674 self.assert_packet_checksums_valid(p)
4675 except:
4676 self.logger.error(ppp("Unexpected or invalid packet:", p))
4677 raise
4678
4679 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4680 IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
4681 TCP(sport=local_port, dport=12345))
4682 self.pg1.add_stream(p)
4683 self.pg_enable_capture(self.pg_interfaces)
4684 self.pg_start()
4685 capture = self.pg0.get_capture(1)
4686 p = capture[0]
4687 try:
4688 ip = p[IP]
4689 tcp = p[TCP]
4690 self.assertEqual(ip.src, external_addr)
4691 self.assertEqual(tcp.sport, external_port)
4692 self.assertEqual(ip.dst, self.pg0.remote_ip4)
4693 self.assertEqual(tcp.dport, 12345)
4694 self.assert_packet_checksums_valid(p)
4695 except:
4696 self.logger.error(ppp("Unexpected or invalid packet:", p))
4697 raise
4698
Matus Fabian182e37e2018-08-14 04:21:26 -07004699 def test_next_src_nat(self):
4700 """ On way back forward packet to nat44-in2out node. """
4701 twice_nat_addr = '10.0.1.3'
4702 external_port = 80
4703 local_port = 8080
4704 post_twice_nat_port = 0
4705
4706 self.vapi.nat44_forwarding_enable_disable(1)
4707 self.nat44_add_address(twice_nat_addr, twice_nat=1)
4708 self.nat44_add_static_mapping(self.pg6.remote_ip4, self.pg1.remote_ip4,
4709 local_port, external_port,
4710 proto=IP_PROTOS.tcp, out2in_only=1,
4711 self_twice_nat=1, vrf_id=1)
4712 self.vapi.nat44_interface_add_del_feature(self.pg6.sw_if_index,
4713 is_inside=0)
4714
4715 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
4716 IP(src=self.pg6.remote_ip4, dst=self.pg1.remote_ip4) /
4717 TCP(sport=12345, dport=external_port))
4718 self.pg6.add_stream(p)
4719 self.pg_enable_capture(self.pg_interfaces)
4720 self.pg_start()
4721 capture = self.pg6.get_capture(1)
4722 p = capture[0]
4723 try:
4724 ip = p[IP]
4725 tcp = p[TCP]
4726 self.assertEqual(ip.src, twice_nat_addr)
4727 self.assertNotEqual(tcp.sport, 12345)
4728 post_twice_nat_port = tcp.sport
4729 self.assertEqual(ip.dst, self.pg6.remote_ip4)
4730 self.assertEqual(tcp.dport, local_port)
4731 self.assert_packet_checksums_valid(p)
4732 except:
4733 self.logger.error(ppp("Unexpected or invalid packet:", p))
4734 raise
4735
4736 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
4737 IP(src=self.pg6.remote_ip4, dst=twice_nat_addr) /
4738 TCP(sport=local_port, dport=post_twice_nat_port))
4739 self.pg6.add_stream(p)
4740 self.pg_enable_capture(self.pg_interfaces)
4741 self.pg_start()
4742 capture = self.pg6.get_capture(1)
4743 p = capture[0]
4744 try:
4745 ip = p[IP]
4746 tcp = p[TCP]
4747 self.assertEqual(ip.src, self.pg1.remote_ip4)
4748 self.assertEqual(tcp.sport, external_port)
4749 self.assertEqual(ip.dst, self.pg6.remote_ip4)
4750 self.assertEqual(tcp.dport, 12345)
4751 self.assert_packet_checksums_valid(p)
4752 except:
4753 self.logger.error(ppp("Unexpected or invalid packet:", p))
4754 raise
4755
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004756 def twice_nat_common(self, self_twice_nat=False, same_pg=False, lb=False,
4757 client_id=None):
Matus Fabianb932d262017-12-18 05:38:24 -08004758 twice_nat_addr = '10.0.1.3'
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004759
Matus Fabianb932d262017-12-18 05:38:24 -08004760 port_in = 8080
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004761 if lb:
4762 if not same_pg:
4763 port_in1 = port_in
4764 port_in2 = port_in
4765 else:
4766 port_in1 = port_in+1
4767 port_in2 = port_in+2
4768
Matus Fabianb932d262017-12-18 05:38:24 -08004769 port_out = 80
4770 eh_port_out = 4567
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004771
4772 server1 = self.pg0.remote_hosts[0]
4773 server2 = self.pg0.remote_hosts[1]
4774 if lb and same_pg:
4775 server2 = server1
4776 if not lb:
4777 server = server1
4778
4779 pg0 = self.pg0
4780 if same_pg:
4781 pg1 = self.pg0
4782 else:
4783 pg1 = self.pg1
4784
4785 eh_translate = ((not self_twice_nat) or (not lb and same_pg) or
4786 client_id == 1)
4787
Matus Fabianb932d262017-12-18 05:38:24 -08004788 self.nat44_add_address(self.nat_addr)
4789 self.nat44_add_address(twice_nat_addr, twice_nat=1)
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004790 if not lb:
4791 self.nat44_add_static_mapping(pg0.remote_ip4, self.nat_addr,
4792 port_in, port_out,
4793 proto=IP_PROTOS.tcp,
4794 twice_nat=int(not self_twice_nat),
4795 self_twice_nat=int(self_twice_nat))
4796 else:
4797 locals = [{'addr': server1.ip4n,
4798 'port': port_in1,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07004799 'probability': 50,
4800 'vrf_id': 0},
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004801 {'addr': server2.ip4n,
4802 'port': port_in2,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07004803 'probability': 50,
4804 'vrf_id': 0}]
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004805 out_addr_n = socket.inet_pton(socket.AF_INET, self.nat_addr)
4806 self.vapi.nat44_add_del_lb_static_mapping(out_addr_n,
4807 port_out,
4808 IP_PROTOS.tcp,
4809 twice_nat=int(
4810 not self_twice_nat),
4811 self_twice_nat=int(
4812 self_twice_nat),
4813 local_num=len(locals),
4814 locals=locals)
4815 self.vapi.nat44_interface_add_del_feature(pg0.sw_if_index)
4816 self.vapi.nat44_interface_add_del_feature(pg1.sw_if_index,
Matus Fabianb932d262017-12-18 05:38:24 -08004817 is_inside=0)
4818
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004819 if same_pg:
4820 if not lb:
4821 client = server
4822 else:
4823 assert client_id is not None
4824 if client_id == 1:
4825 client = self.pg0.remote_hosts[0]
4826 elif client_id == 2:
4827 client = self.pg0.remote_hosts[1]
4828 else:
4829 client = pg1.remote_hosts[0]
4830 p = (Ether(src=pg1.remote_mac, dst=pg1.local_mac) /
4831 IP(src=client.ip4, dst=self.nat_addr) /
Matus Fabianb932d262017-12-18 05:38:24 -08004832 TCP(sport=eh_port_out, dport=port_out))
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004833 pg1.add_stream(p)
Matus Fabianb932d262017-12-18 05:38:24 -08004834 self.pg_enable_capture(self.pg_interfaces)
4835 self.pg_start()
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004836 capture = pg0.get_capture(1)
Matus Fabianb932d262017-12-18 05:38:24 -08004837 p = capture[0]
4838 try:
4839 ip = p[IP]
4840 tcp = p[TCP]
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004841 if lb:
4842 if ip.dst == server1.ip4:
4843 server = server1
4844 port_in = port_in1
4845 else:
4846 server = server2
4847 port_in = port_in2
4848 self.assertEqual(ip.dst, server.ip4)
4849 if lb and same_pg:
4850 self.assertIn(tcp.dport, [port_in1, port_in2])
4851 else:
4852 self.assertEqual(tcp.dport, port_in)
4853 if eh_translate:
4854 self.assertEqual(ip.src, twice_nat_addr)
4855 self.assertNotEqual(tcp.sport, eh_port_out)
4856 else:
4857 self.assertEqual(ip.src, client.ip4)
4858 self.assertEqual(tcp.sport, eh_port_out)
4859 eh_addr_in = ip.src
Matus Fabianb932d262017-12-18 05:38:24 -08004860 eh_port_in = tcp.sport
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004861 saved_port_in = tcp.dport
Klement Sekerad81ae412018-05-16 10:52:54 +02004862 self.assert_packet_checksums_valid(p)
Matus Fabianb932d262017-12-18 05:38:24 -08004863 except:
4864 self.logger.error(ppp("Unexpected or invalid packet:", p))
4865 raise
4866
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004867 p = (Ether(src=server.mac, dst=pg0.local_mac) /
4868 IP(src=server.ip4, dst=eh_addr_in) /
4869 TCP(sport=saved_port_in, dport=eh_port_in))
4870 pg0.add_stream(p)
Matus Fabianb932d262017-12-18 05:38:24 -08004871 self.pg_enable_capture(self.pg_interfaces)
4872 self.pg_start()
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004873 capture = pg1.get_capture(1)
Matus Fabianb932d262017-12-18 05:38:24 -08004874 p = capture[0]
4875 try:
4876 ip = p[IP]
4877 tcp = p[TCP]
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004878 self.assertEqual(ip.dst, client.ip4)
Matus Fabianb932d262017-12-18 05:38:24 -08004879 self.assertEqual(ip.src, self.nat_addr)
4880 self.assertEqual(tcp.dport, eh_port_out)
4881 self.assertEqual(tcp.sport, port_out)
Klement Sekerad81ae412018-05-16 10:52:54 +02004882 self.assert_packet_checksums_valid(p)
Matus Fabianb932d262017-12-18 05:38:24 -08004883 except:
4884 self.logger.error(ppp("Unexpected or invalid packet:", p))
4885 raise
4886
Matus Fabian70a26ac2018-05-14 06:20:28 -07004887 if eh_translate:
4888 sessions = self.vapi.nat44_user_session_dump(server.ip4n, 0)
4889 self.assertEqual(len(sessions), 1)
4890 self.assertTrue(sessions[0].ext_host_valid)
4891 self.assertTrue(sessions[0].is_twicenat)
4892 self.vapi.nat44_del_session(
4893 sessions[0].inside_ip_address,
4894 sessions[0].inside_port,
4895 sessions[0].protocol,
4896 ext_host_address=sessions[0].ext_host_nat_address,
4897 ext_host_port=sessions[0].ext_host_nat_port)
4898 sessions = self.vapi.nat44_user_session_dump(server.ip4n, 0)
4899 self.assertEqual(len(sessions), 0)
4900
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004901 def test_twice_nat(self):
4902 """ Twice NAT44 """
4903 self.twice_nat_common()
4904
4905 def test_self_twice_nat_positive(self):
4906 """ Self Twice NAT44 (positive test) """
4907 self.twice_nat_common(self_twice_nat=True, same_pg=True)
4908
4909 def test_self_twice_nat_negative(self):
4910 """ Self Twice NAT44 (negative test) """
4911 self.twice_nat_common(self_twice_nat=True)
4912
Matus Fabianb932d262017-12-18 05:38:24 -08004913 def test_twice_nat_lb(self):
4914 """ Twice NAT44 local service load balancing """
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004915 self.twice_nat_common(lb=True)
Matus Fabianb932d262017-12-18 05:38:24 -08004916
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004917 def test_self_twice_nat_lb_positive(self):
4918 """ Self Twice NAT44 local service load balancing (positive test) """
4919 self.twice_nat_common(lb=True, self_twice_nat=True, same_pg=True,
4920 client_id=1)
Matus Fabianb932d262017-12-18 05:38:24 -08004921
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004922 def test_self_twice_nat_lb_negative(self):
4923 """ Self Twice NAT44 local service load balancing (negative test) """
4924 self.twice_nat_common(lb=True, self_twice_nat=True, same_pg=True,
4925 client_id=2)
Matus Fabianb932d262017-12-18 05:38:24 -08004926
4927 def test_twice_nat_interface_addr(self):
4928 """ Acquire twice NAT44 addresses from interface """
Matus Fabiana6110b62018-06-13 05:39:07 -07004929 self.vapi.nat44_add_interface_addr(self.pg3.sw_if_index, twice_nat=1)
Matus Fabianb932d262017-12-18 05:38:24 -08004930
4931 # no address in NAT pool
4932 adresses = self.vapi.nat44_address_dump()
4933 self.assertEqual(0, len(adresses))
4934
4935 # configure interface address and check NAT address pool
Matus Fabiana6110b62018-06-13 05:39:07 -07004936 self.pg3.config_ip4()
Matus Fabianb932d262017-12-18 05:38:24 -08004937 adresses = self.vapi.nat44_address_dump()
4938 self.assertEqual(1, len(adresses))
Matus Fabiana6110b62018-06-13 05:39:07 -07004939 self.assertEqual(adresses[0].ip_address[0:4], self.pg3.local_ip4n)
Matus Fabianb932d262017-12-18 05:38:24 -08004940 self.assertEqual(adresses[0].twice_nat, 1)
4941
4942 # remove interface address and check NAT address pool
Matus Fabiana6110b62018-06-13 05:39:07 -07004943 self.pg3.unconfig_ip4()
Matus Fabianb932d262017-12-18 05:38:24 -08004944 adresses = self.vapi.nat44_address_dump()
4945 self.assertEqual(0, len(adresses))
4946
Matus Fabian6c01dce2018-11-16 04:41:31 -08004947 def test_tcp_close(self):
4948 """ Close TCP session from inside network - output feature """
4949 self.vapi.nat44_forwarding_enable_disable(1)
4950 self.nat44_add_address(self.pg1.local_ip4)
4951 twice_nat_addr = '10.0.1.3'
4952 service_ip = '192.168.16.150'
4953 self.nat44_add_address(twice_nat_addr, twice_nat=1)
4954 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4955 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
4956 is_inside=0)
4957 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
4958 is_inside=0)
4959 self.nat44_add_static_mapping(self.pg0.remote_ip4,
4960 service_ip,
4961 80,
4962 80,
4963 proto=IP_PROTOS.tcp,
4964 out2in_only=1,
4965 twice_nat=1)
4966 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
4967 start_sessnum = len(sessions)
4968
4969 # SYN packet out->in
4970 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4971 IP(src=self.pg1.remote_ip4, dst=service_ip) /
4972 TCP(sport=33898, dport=80, flags="S"))
4973 self.pg1.add_stream(p)
4974 self.pg_enable_capture(self.pg_interfaces)
4975 self.pg_start()
4976 capture = self.pg0.get_capture(1)
4977 p = capture[0]
4978 tcp_port = p[TCP].sport
4979
4980 # SYN + ACK packet in->out
4981 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4982 IP(src=self.pg0.remote_ip4, dst=twice_nat_addr) /
4983 TCP(sport=80, dport=tcp_port, flags="SA"))
4984 self.pg0.add_stream(p)
4985 self.pg_enable_capture(self.pg_interfaces)
4986 self.pg_start()
4987 self.pg1.get_capture(1)
4988
4989 # ACK packet out->in
4990 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4991 IP(src=self.pg1.remote_ip4, dst=service_ip) /
4992 TCP(sport=33898, dport=80, flags="A"))
4993 self.pg1.add_stream(p)
4994 self.pg_enable_capture(self.pg_interfaces)
4995 self.pg_start()
4996 self.pg0.get_capture(1)
4997
4998 # FIN packet in -> out
4999 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5000 IP(src=self.pg0.remote_ip4, dst=twice_nat_addr) /
5001 TCP(sport=80, dport=tcp_port, flags="FA", seq=100, ack=300))
5002 self.pg0.add_stream(p)
5003 self.pg_enable_capture(self.pg_interfaces)
5004 self.pg_start()
5005 self.pg1.get_capture(1)
5006
5007 # FIN+ACK packet out -> in
5008 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5009 IP(src=self.pg1.remote_ip4, dst=service_ip) /
5010 TCP(sport=33898, dport=80, flags="FA", seq=300, ack=101))
5011 self.pg1.add_stream(p)
5012 self.pg_enable_capture(self.pg_interfaces)
5013 self.pg_start()
5014 self.pg0.get_capture(1)
5015
5016 # ACK packet in -> out
5017 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5018 IP(src=self.pg0.remote_ip4, dst=twice_nat_addr) /
5019 TCP(sport=80, dport=tcp_port, flags="A", seq=101, ack=301))
5020 self.pg0.add_stream(p)
5021 self.pg_enable_capture(self.pg_interfaces)
5022 self.pg_start()
5023 self.pg1.get_capture(1)
5024
5025 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n,
5026 0)
5027 self.assertEqual(len(sessions) - start_sessnum, 0)
5028
Matus Fabianebdf1902018-05-04 03:57:42 -07005029 def test_tcp_session_close_in(self):
5030 """ Close TCP session from inside network """
Matus Fabian229c1aa2018-05-28 04:09:52 -07005031 self.tcp_port_out = 10505
Matus Fabianebdf1902018-05-04 03:57:42 -07005032 self.nat44_add_address(self.nat_addr)
Matus Fabian229c1aa2018-05-28 04:09:52 -07005033 self.nat44_add_static_mapping(self.pg0.remote_ip4,
5034 self.nat_addr,
5035 self.tcp_port_in,
5036 self.tcp_port_out,
5037 proto=IP_PROTOS.tcp,
5038 twice_nat=1)
Matus Fabianebdf1902018-05-04 03:57:42 -07005039 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5040 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
5041 is_inside=0)
5042
5043 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
5044 start_sessnum = len(sessions)
5045
5046 self.initiate_tcp_session(self.pg0, self.pg1)
5047
Matus Fabian229c1aa2018-05-28 04:09:52 -07005048 # FIN packet in -> out
5049 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5050 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5051 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
5052 flags="FA", seq=100, ack=300))
5053 self.pg0.add_stream(p)
5054 self.pg_enable_capture(self.pg_interfaces)
5055 self.pg_start()
5056 self.pg1.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07005057
Matus Fabian229c1aa2018-05-28 04:09:52 -07005058 pkts = []
Matus Fabianebdf1902018-05-04 03:57:42 -07005059
Matus Fabian229c1aa2018-05-28 04:09:52 -07005060 # ACK packet out -> in
5061 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5062 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5063 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
5064 flags="A", seq=300, ack=101))
5065 pkts.append(p)
Matus Fabianebdf1902018-05-04 03:57:42 -07005066
Matus Fabian229c1aa2018-05-28 04:09:52 -07005067 # FIN packet out -> in
5068 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5069 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5070 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
5071 flags="FA", seq=300, ack=101))
5072 pkts.append(p)
Matus Fabianebdf1902018-05-04 03:57:42 -07005073
Matus Fabian229c1aa2018-05-28 04:09:52 -07005074 self.pg1.add_stream(pkts)
5075 self.pg_enable_capture(self.pg_interfaces)
5076 self.pg_start()
5077 self.pg0.get_capture(2)
Matus Fabianebdf1902018-05-04 03:57:42 -07005078
Matus Fabian229c1aa2018-05-28 04:09:52 -07005079 # ACK packet in -> out
5080 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5081 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5082 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
5083 flags="A", seq=101, ack=301))
5084 self.pg0.add_stream(p)
5085 self.pg_enable_capture(self.pg_interfaces)
5086 self.pg_start()
5087 self.pg1.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07005088
Matus Fabian229c1aa2018-05-28 04:09:52 -07005089 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n,
5090 0)
5091 self.assertEqual(len(sessions) - start_sessnum, 0)
Matus Fabianebdf1902018-05-04 03:57:42 -07005092
5093 def test_tcp_session_close_out(self):
5094 """ Close TCP session from outside network """
Matus Fabian229c1aa2018-05-28 04:09:52 -07005095 self.tcp_port_out = 10505
Matus Fabianebdf1902018-05-04 03:57:42 -07005096 self.nat44_add_address(self.nat_addr)
Matus Fabian229c1aa2018-05-28 04:09:52 -07005097 self.nat44_add_static_mapping(self.pg0.remote_ip4,
5098 self.nat_addr,
5099 self.tcp_port_in,
5100 self.tcp_port_out,
5101 proto=IP_PROTOS.tcp,
5102 twice_nat=1)
Matus Fabianebdf1902018-05-04 03:57:42 -07005103 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5104 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
5105 is_inside=0)
5106
5107 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
5108 start_sessnum = len(sessions)
5109
5110 self.initiate_tcp_session(self.pg0, self.pg1)
5111
Matus Fabian229c1aa2018-05-28 04:09:52 -07005112 # FIN packet out -> in
5113 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5114 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5115 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
5116 flags="FA", seq=100, ack=300))
5117 self.pg1.add_stream(p)
5118 self.pg_enable_capture(self.pg_interfaces)
5119 self.pg_start()
5120 self.pg0.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07005121
Matus Fabian229c1aa2018-05-28 04:09:52 -07005122 # FIN+ACK packet in -> out
5123 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5124 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5125 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
5126 flags="FA", seq=300, ack=101))
Matus Fabianebdf1902018-05-04 03:57:42 -07005127
Matus Fabian229c1aa2018-05-28 04:09:52 -07005128 self.pg0.add_stream(p)
5129 self.pg_enable_capture(self.pg_interfaces)
5130 self.pg_start()
5131 self.pg1.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07005132
Matus Fabian229c1aa2018-05-28 04:09:52 -07005133 # ACK packet out -> in
5134 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5135 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5136 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
5137 flags="A", seq=101, ack=301))
5138 self.pg1.add_stream(p)
5139 self.pg_enable_capture(self.pg_interfaces)
5140 self.pg_start()
5141 self.pg0.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07005142
Matus Fabian229c1aa2018-05-28 04:09:52 -07005143 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n,
5144 0)
5145 self.assertEqual(len(sessions) - start_sessnum, 0)
Matus Fabianebdf1902018-05-04 03:57:42 -07005146
5147 def test_tcp_session_close_simultaneous(self):
5148 """ Close TCP session from inside network """
Matus Fabian229c1aa2018-05-28 04:09:52 -07005149 self.tcp_port_out = 10505
Matus Fabianebdf1902018-05-04 03:57:42 -07005150 self.nat44_add_address(self.nat_addr)
Matus Fabian229c1aa2018-05-28 04:09:52 -07005151 self.nat44_add_static_mapping(self.pg0.remote_ip4,
5152 self.nat_addr,
5153 self.tcp_port_in,
5154 self.tcp_port_out,
5155 proto=IP_PROTOS.tcp,
5156 twice_nat=1)
Matus Fabianebdf1902018-05-04 03:57:42 -07005157 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5158 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
5159 is_inside=0)
5160
5161 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
5162 start_sessnum = len(sessions)
5163
5164 self.initiate_tcp_session(self.pg0, self.pg1)
5165
Matus Fabian229c1aa2018-05-28 04:09:52 -07005166 # FIN packet in -> out
5167 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5168 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5169 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
5170 flags="FA", seq=100, ack=300))
5171 self.pg0.add_stream(p)
5172 self.pg_enable_capture(self.pg_interfaces)
5173 self.pg_start()
5174 self.pg1.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07005175
Matus Fabian229c1aa2018-05-28 04:09:52 -07005176 # FIN packet out -> in
5177 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5178 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5179 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
5180 flags="FA", seq=300, ack=100))
5181 self.pg1.add_stream(p)
5182 self.pg_enable_capture(self.pg_interfaces)
5183 self.pg_start()
5184 self.pg0.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07005185
Matus Fabian229c1aa2018-05-28 04:09:52 -07005186 # ACK packet in -> out
5187 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5188 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5189 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
5190 flags="A", seq=101, ack=301))
5191 self.pg0.add_stream(p)
5192 self.pg_enable_capture(self.pg_interfaces)
5193 self.pg_start()
5194 self.pg1.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07005195
Matus Fabian229c1aa2018-05-28 04:09:52 -07005196 # ACK packet out -> in
5197 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5198 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5199 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
5200 flags="A", seq=301, ack=101))
5201 self.pg1.add_stream(p)
5202 self.pg_enable_capture(self.pg_interfaces)
5203 self.pg_start()
5204 self.pg0.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07005205
Matus Fabian229c1aa2018-05-28 04:09:52 -07005206 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n,
5207 0)
5208 self.assertEqual(len(sessions) - start_sessnum, 0)
Matus Fabianebdf1902018-05-04 03:57:42 -07005209
Matus Fabiana6110b62018-06-13 05:39:07 -07005210 def test_one_armed_nat44_static(self):
5211 """ One armed NAT44 and 1:1 NAPT asymmetrical rule """
5212 remote_host = self.pg4.remote_hosts[0]
5213 local_host = self.pg4.remote_hosts[1]
5214 external_port = 80
5215 local_port = 8080
5216 eh_port_in = 0
5217
5218 self.vapi.nat44_forwarding_enable_disable(1)
5219 self.nat44_add_address(self.nat_addr, twice_nat=1)
5220 self.nat44_add_static_mapping(local_host.ip4, self.nat_addr,
5221 local_port, external_port,
5222 proto=IP_PROTOS.tcp, out2in_only=1,
5223 twice_nat=1)
5224 self.vapi.nat44_interface_add_del_feature(self.pg4.sw_if_index)
5225 self.vapi.nat44_interface_add_del_feature(self.pg4.sw_if_index,
5226 is_inside=0)
5227
5228 # from client to service
5229 p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
5230 IP(src=remote_host.ip4, dst=self.nat_addr) /
5231 TCP(sport=12345, dport=external_port))
5232 self.pg4.add_stream(p)
5233 self.pg_enable_capture(self.pg_interfaces)
5234 self.pg_start()
5235 capture = self.pg4.get_capture(1)
5236 p = capture[0]
5237 try:
5238 ip = p[IP]
5239 tcp = p[TCP]
5240 self.assertEqual(ip.dst, local_host.ip4)
5241 self.assertEqual(ip.src, self.nat_addr)
5242 self.assertEqual(tcp.dport, local_port)
5243 self.assertNotEqual(tcp.sport, 12345)
5244 eh_port_in = tcp.sport
5245 self.assert_packet_checksums_valid(p)
5246 except:
5247 self.logger.error(ppp("Unexpected or invalid packet:", p))
5248 raise
5249
5250 # from service back to client
5251 p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
5252 IP(src=local_host.ip4, dst=self.nat_addr) /
5253 TCP(sport=local_port, dport=eh_port_in))
5254 self.pg4.add_stream(p)
5255 self.pg_enable_capture(self.pg_interfaces)
5256 self.pg_start()
5257 capture = self.pg4.get_capture(1)
5258 p = capture[0]
5259 try:
5260 ip = p[IP]
5261 tcp = p[TCP]
5262 self.assertEqual(ip.src, self.nat_addr)
5263 self.assertEqual(ip.dst, remote_host.ip4)
5264 self.assertEqual(tcp.sport, external_port)
5265 self.assertEqual(tcp.dport, 12345)
5266 self.assert_packet_checksums_valid(p)
5267 except:
5268 self.logger.error(ppp("Unexpected or invalid packet:", p))
5269 raise
5270
5271 def test_static_with_port_out2(self):
5272 """ 1:1 NAPT asymmetrical rule """
5273
5274 external_port = 80
5275 local_port = 8080
5276
5277 self.vapi.nat44_forwarding_enable_disable(1)
5278 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
5279 local_port, external_port,
5280 proto=IP_PROTOS.tcp, out2in_only=1)
5281 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5282 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
5283 is_inside=0)
5284
5285 # from client to service
5286 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5287 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5288 TCP(sport=12345, dport=external_port))
5289 self.pg1.add_stream(p)
5290 self.pg_enable_capture(self.pg_interfaces)
5291 self.pg_start()
5292 capture = self.pg0.get_capture(1)
5293 p = capture[0]
5294 try:
5295 ip = p[IP]
5296 tcp = p[TCP]
5297 self.assertEqual(ip.dst, self.pg0.remote_ip4)
5298 self.assertEqual(tcp.dport, local_port)
5299 self.assert_packet_checksums_valid(p)
5300 except:
5301 self.logger.error(ppp("Unexpected or invalid packet:", p))
5302 raise
5303
5304 # ICMP error
5305 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5306 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5307 ICMP(type=11) / capture[0][IP])
5308 self.pg0.add_stream(p)
5309 self.pg_enable_capture(self.pg_interfaces)
5310 self.pg_start()
5311 capture = self.pg1.get_capture(1)
5312 p = capture[0]
5313 try:
5314 self.assertEqual(p[IP].src, self.nat_addr)
5315 inner = p[IPerror]
5316 self.assertEqual(inner.dst, self.nat_addr)
5317 self.assertEqual(inner[TCPerror].dport, external_port)
5318 except:
5319 self.logger.error(ppp("Unexpected or invalid packet:", p))
5320 raise
5321
5322 # from service back to client
5323 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5324 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5325 TCP(sport=local_port, dport=12345))
5326 self.pg0.add_stream(p)
5327 self.pg_enable_capture(self.pg_interfaces)
5328 self.pg_start()
5329 capture = self.pg1.get_capture(1)
5330 p = capture[0]
5331 try:
5332 ip = p[IP]
5333 tcp = p[TCP]
5334 self.assertEqual(ip.src, self.nat_addr)
5335 self.assertEqual(tcp.sport, external_port)
5336 self.assert_packet_checksums_valid(p)
5337 except:
5338 self.logger.error(ppp("Unexpected or invalid packet:", p))
5339 raise
5340
5341 # ICMP error
5342 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
5343 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5344 ICMP(type=11) / capture[0][IP])
5345 self.pg1.add_stream(p)
5346 self.pg_enable_capture(self.pg_interfaces)
5347 self.pg_start()
5348 capture = self.pg0.get_capture(1)
5349 p = capture[0]
5350 try:
5351 self.assertEqual(p[IP].dst, self.pg0.remote_ip4)
5352 inner = p[IPerror]
5353 self.assertEqual(inner.src, self.pg0.remote_ip4)
5354 self.assertEqual(inner[TCPerror].sport, local_port)
5355 except:
5356 self.logger.error(ppp("Unexpected or invalid packet:", p))
5357 raise
5358
5359 # from client to server (no translation)
5360 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5361 IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
5362 TCP(sport=12346, dport=local_port))
5363 self.pg1.add_stream(p)
5364 self.pg_enable_capture(self.pg_interfaces)
5365 self.pg_start()
5366 capture = self.pg0.get_capture(1)
5367 p = capture[0]
5368 try:
5369 ip = p[IP]
5370 tcp = p[TCP]
5371 self.assertEqual(ip.dst, self.pg0.remote_ip4)
5372 self.assertEqual(tcp.dport, local_port)
5373 self.assert_packet_checksums_valid(p)
5374 except:
5375 self.logger.error(ppp("Unexpected or invalid packet:", p))
5376 raise
5377
5378 # from service back to client (no translation)
5379 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5380 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5381 TCP(sport=local_port, dport=12346))
5382 self.pg0.add_stream(p)
5383 self.pg_enable_capture(self.pg_interfaces)
5384 self.pg_start()
5385 capture = self.pg1.get_capture(1)
5386 p = capture[0]
5387 try:
5388 ip = p[IP]
5389 tcp = p[TCP]
5390 self.assertEqual(ip.src, self.pg0.remote_ip4)
5391 self.assertEqual(tcp.sport, local_port)
5392 self.assert_packet_checksums_valid(p)
5393 except:
5394 self.logger.error(ppp("Unexpected or invalid packet:", p))
5395 raise
5396
Matus Fabian235a47e2018-06-25 16:42:36 -07005397 def test_output_feature(self):
5398 """ NAT44 interface output feature (in2out postrouting) """
5399 self.vapi.nat44_forwarding_enable_disable(1)
5400 self.nat44_add_address(self.nat_addr)
5401 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
5402 is_inside=0)
5403 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
5404 is_inside=0)
5405
5406 # in2out
5407 pkts = self.create_stream_in(self.pg0, self.pg1)
5408 self.pg0.add_stream(pkts)
5409 self.pg_enable_capture(self.pg_interfaces)
5410 self.pg_start()
5411 capture = self.pg1.get_capture(len(pkts))
5412 self.verify_capture_out(capture)
5413
5414 # out2in
5415 pkts = self.create_stream_out(self.pg1)
5416 self.pg1.add_stream(pkts)
5417 self.pg_enable_capture(self.pg_interfaces)
5418 self.pg_start()
5419 capture = self.pg0.get_capture(len(pkts))
5420 self.verify_capture_in(capture, self.pg0)
5421
Matus Fabian8008d7c2018-07-09 01:34:20 -07005422 def test_multiple_vrf(self):
5423 """ Multiple VRF setup """
5424 external_addr = '1.2.3.4'
5425 external_port = 80
5426 local_port = 8080
5427 port = 0
5428
5429 self.vapi.nat44_forwarding_enable_disable(1)
5430 self.nat44_add_address(self.nat_addr)
5431 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5432 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
5433 is_inside=0)
5434 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
5435 is_inside=0)
5436 self.vapi.nat44_interface_add_del_feature(self.pg5.sw_if_index)
5437 self.vapi.nat44_interface_add_del_feature(self.pg5.sw_if_index,
5438 is_inside=0)
5439 self.vapi.nat44_interface_add_del_feature(self.pg6.sw_if_index,
5440 is_inside=0)
5441 self.nat44_add_static_mapping(self.pg5.remote_ip4, external_addr,
5442 local_port, external_port, vrf_id=1,
5443 proto=IP_PROTOS.tcp, out2in_only=1)
5444 self.nat44_add_static_mapping(
5445 self.pg0.remote_ip4, external_sw_if_index=self.pg0.sw_if_index,
5446 local_port=local_port, vrf_id=0, external_port=external_port,
5447 proto=IP_PROTOS.tcp, out2in_only=1)
5448
5449 # from client to service (both VRF1)
5450 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
5451 IP(src=self.pg6.remote_ip4, dst=external_addr) /
5452 TCP(sport=12345, dport=external_port))
5453 self.pg6.add_stream(p)
5454 self.pg_enable_capture(self.pg_interfaces)
5455 self.pg_start()
5456 capture = self.pg5.get_capture(1)
5457 p = capture[0]
5458 try:
5459 ip = p[IP]
5460 tcp = p[TCP]
5461 self.assertEqual(ip.dst, self.pg5.remote_ip4)
5462 self.assertEqual(tcp.dport, local_port)
5463 self.assert_packet_checksums_valid(p)
5464 except:
5465 self.logger.error(ppp("Unexpected or invalid packet:", p))
5466 raise
5467
5468 # from service back to client (both VRF1)
5469 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
5470 IP(src=self.pg5.remote_ip4, dst=self.pg6.remote_ip4) /
5471 TCP(sport=local_port, dport=12345))
5472 self.pg5.add_stream(p)
5473 self.pg_enable_capture(self.pg_interfaces)
5474 self.pg_start()
5475 capture = self.pg6.get_capture(1)
5476 p = capture[0]
5477 try:
5478 ip = p[IP]
5479 tcp = p[TCP]
5480 self.assertEqual(ip.src, external_addr)
5481 self.assertEqual(tcp.sport, external_port)
5482 self.assert_packet_checksums_valid(p)
5483 except:
5484 self.logger.error(ppp("Unexpected or invalid packet:", p))
5485 raise
5486
5487 # dynamic NAT from VRF1 to VRF0 (output-feature)
5488 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
5489 IP(src=self.pg5.remote_ip4, dst=self.pg1.remote_ip4) /
5490 TCP(sport=2345, dport=22))
5491 self.pg5.add_stream(p)
5492 self.pg_enable_capture(self.pg_interfaces)
5493 self.pg_start()
5494 capture = self.pg1.get_capture(1)
5495 p = capture[0]
5496 try:
5497 ip = p[IP]
5498 tcp = p[TCP]
5499 self.assertEqual(ip.src, self.nat_addr)
5500 self.assertNotEqual(tcp.sport, 2345)
5501 self.assert_packet_checksums_valid(p)
5502 port = tcp.sport
5503 except:
5504 self.logger.error(ppp("Unexpected or invalid packet:", p))
5505 raise
5506
5507 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5508 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5509 TCP(sport=22, dport=port))
5510 self.pg1.add_stream(p)
5511 self.pg_enable_capture(self.pg_interfaces)
5512 self.pg_start()
5513 capture = self.pg5.get_capture(1)
5514 p = capture[0]
5515 try:
5516 ip = p[IP]
5517 tcp = p[TCP]
5518 self.assertEqual(ip.dst, self.pg5.remote_ip4)
5519 self.assertEqual(tcp.dport, 2345)
5520 self.assert_packet_checksums_valid(p)
5521 except:
5522 self.logger.error(ppp("Unexpected or invalid packet:", p))
5523 raise
5524
5525 # from client VRF1 to service VRF0
5526 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
5527 IP(src=self.pg6.remote_ip4, dst=self.pg0.local_ip4) /
5528 TCP(sport=12346, dport=external_port))
5529 self.pg6.add_stream(p)
5530 self.pg_enable_capture(self.pg_interfaces)
5531 self.pg_start()
5532 capture = self.pg0.get_capture(1)
5533 p = capture[0]
5534 try:
5535 ip = p[IP]
5536 tcp = p[TCP]
5537 self.assertEqual(ip.dst, self.pg0.remote_ip4)
5538 self.assertEqual(tcp.dport, local_port)
5539 self.assert_packet_checksums_valid(p)
5540 except:
5541 self.logger.error(ppp("Unexpected or invalid packet:", p))
5542 raise
5543
5544 # from service VRF0 back to client VRF1
5545 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5546 IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
5547 TCP(sport=local_port, dport=12346))
5548 self.pg0.add_stream(p)
5549 self.pg_enable_capture(self.pg_interfaces)
5550 self.pg_start()
5551 capture = self.pg6.get_capture(1)
5552 p = capture[0]
5553 try:
5554 ip = p[IP]
5555 tcp = p[TCP]
5556 self.assertEqual(ip.src, self.pg0.local_ip4)
5557 self.assertEqual(tcp.sport, external_port)
5558 self.assert_packet_checksums_valid(p)
5559 except:
5560 self.logger.error(ppp("Unexpected or invalid packet:", p))
5561 raise
5562
5563 # from client VRF0 to service VRF1
5564 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5565 IP(src=self.pg0.remote_ip4, dst=external_addr) /
5566 TCP(sport=12347, dport=external_port))
5567 self.pg0.add_stream(p)
5568 self.pg_enable_capture(self.pg_interfaces)
5569 self.pg_start()
5570 capture = self.pg5.get_capture(1)
5571 p = capture[0]
5572 try:
5573 ip = p[IP]
5574 tcp = p[TCP]
5575 self.assertEqual(ip.dst, self.pg5.remote_ip4)
5576 self.assertEqual(tcp.dport, local_port)
5577 self.assert_packet_checksums_valid(p)
5578 except:
5579 self.logger.error(ppp("Unexpected or invalid packet:", p))
5580 raise
5581
5582 # from service VRF1 back to client VRF0
5583 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
5584 IP(src=self.pg5.remote_ip4, dst=self.pg0.remote_ip4) /
5585 TCP(sport=local_port, dport=12347))
5586 self.pg5.add_stream(p)
5587 self.pg_enable_capture(self.pg_interfaces)
5588 self.pg_start()
5589 capture = self.pg0.get_capture(1)
5590 p = capture[0]
5591 try:
5592 ip = p[IP]
5593 tcp = p[TCP]
5594 self.assertEqual(ip.src, external_addr)
5595 self.assertEqual(tcp.sport, external_port)
5596 self.assert_packet_checksums_valid(p)
5597 except:
5598 self.logger.error(ppp("Unexpected or invalid packet:", p))
5599 raise
5600
5601 # from client to server (both VRF1, no translation)
5602 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
5603 IP(src=self.pg6.remote_ip4, dst=self.pg5.remote_ip4) /
5604 TCP(sport=12348, dport=local_port))
5605 self.pg6.add_stream(p)
5606 self.pg_enable_capture(self.pg_interfaces)
5607 self.pg_start()
5608 capture = self.pg5.get_capture(1)
5609 p = capture[0]
5610 try:
5611 ip = p[IP]
5612 tcp = p[TCP]
5613 self.assertEqual(ip.dst, self.pg5.remote_ip4)
5614 self.assertEqual(tcp.dport, local_port)
5615 self.assert_packet_checksums_valid(p)
5616 except:
5617 self.logger.error(ppp("Unexpected or invalid packet:", p))
5618 raise
5619
5620 # from server back to client (both VRF1, no translation)
5621 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
5622 IP(src=self.pg5.remote_ip4, dst=self.pg6.remote_ip4) /
5623 TCP(sport=local_port, dport=12348))
5624 self.pg5.add_stream(p)
5625 self.pg_enable_capture(self.pg_interfaces)
5626 self.pg_start()
5627 capture = self.pg6.get_capture(1)
5628 p = capture[0]
5629 try:
5630 ip = p[IP]
5631 tcp = p[TCP]
5632 self.assertEqual(ip.src, self.pg5.remote_ip4)
5633 self.assertEqual(tcp.sport, local_port)
5634 self.assert_packet_checksums_valid(p)
5635 except:
5636 self.logger.error(ppp("Unexpected or invalid packet:", p))
5637 raise
5638
5639 # from client VRF1 to server VRF0 (no translation)
5640 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5641 IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
5642 TCP(sport=local_port, dport=12349))
5643 self.pg0.add_stream(p)
5644 self.pg_enable_capture(self.pg_interfaces)
5645 self.pg_start()
5646 capture = self.pg6.get_capture(1)
5647 p = capture[0]
5648 try:
5649 ip = p[IP]
5650 tcp = p[TCP]
5651 self.assertEqual(ip.src, self.pg0.remote_ip4)
5652 self.assertEqual(tcp.sport, local_port)
5653 self.assert_packet_checksums_valid(p)
5654 except:
5655 self.logger.error(ppp("Unexpected or invalid packet:", p))
5656 raise
5657
5658 # from server VRF0 back to client VRF1 (no translation)
5659 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5660 IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
5661 TCP(sport=local_port, dport=12349))
5662 self.pg0.add_stream(p)
5663 self.pg_enable_capture(self.pg_interfaces)
5664 self.pg_start()
5665 capture = self.pg6.get_capture(1)
5666 p = capture[0]
5667 try:
5668 ip = p[IP]
5669 tcp = p[TCP]
5670 self.assertEqual(ip.src, self.pg0.remote_ip4)
5671 self.assertEqual(tcp.sport, local_port)
5672 self.assert_packet_checksums_valid(p)
5673 except:
5674 self.logger.error(ppp("Unexpected or invalid packet:", p))
5675 raise
5676
5677 # from client VRF0 to server VRF1 (no translation)
5678 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5679 IP(src=self.pg0.remote_ip4, dst=self.pg5.remote_ip4) /
5680 TCP(sport=12344, dport=local_port))
5681 self.pg0.add_stream(p)
5682 self.pg_enable_capture(self.pg_interfaces)
5683 self.pg_start()
5684 capture = self.pg5.get_capture(1)
5685 p = capture[0]
5686 try:
5687 ip = p[IP]
5688 tcp = p[TCP]
5689 self.assertEqual(ip.dst, self.pg5.remote_ip4)
5690 self.assertEqual(tcp.dport, local_port)
5691 self.assert_packet_checksums_valid(p)
5692 except:
5693 self.logger.error(ppp("Unexpected or invalid packet:", p))
5694 raise
5695
5696 # from server VRF1 back to client VRF0 (no translation)
5697 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
5698 IP(src=self.pg5.remote_ip4, dst=self.pg0.remote_ip4) /
5699 TCP(sport=local_port, dport=12344))
5700 self.pg5.add_stream(p)
5701 self.pg_enable_capture(self.pg_interfaces)
5702 self.pg_start()
5703 capture = self.pg0.get_capture(1)
5704 p = capture[0]
5705 try:
5706 ip = p[IP]
5707 tcp = p[TCP]
5708 self.assertEqual(ip.src, self.pg5.remote_ip4)
5709 self.assertEqual(tcp.sport, local_port)
5710 self.assert_packet_checksums_valid(p)
5711 except:
5712 self.logger.error(ppp("Unexpected or invalid packet:", p))
5713 raise
5714
Matus Fabian878c6462018-08-23 00:33:35 -07005715 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
5716 def test_session_timeout(self):
5717 """ NAT44 session timeouts """
5718 self.nat44_add_address(self.nat_addr)
5719 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5720 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
5721 is_inside=0)
5722 self.vapi.nat_set_timeouts(icmp=5)
5723
5724 max_sessions = 1000
5725 pkts = []
5726 for i in range(0, max_sessions):
5727 src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
5728 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5729 IP(src=src, dst=self.pg1.remote_ip4) /
5730 ICMP(id=1025, type='echo-request'))
5731 pkts.append(p)
5732 self.pg0.add_stream(pkts)
5733 self.pg_enable_capture(self.pg_interfaces)
5734 self.pg_start()
5735 self.pg1.get_capture(max_sessions)
5736
5737 sleep(10)
5738
5739 pkts = []
5740 for i in range(0, max_sessions):
Matus Fabian7f8a8db2018-11-22 00:12:15 -08005741 src = "10.11.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
Matus Fabian878c6462018-08-23 00:33:35 -07005742 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5743 IP(src=src, dst=self.pg1.remote_ip4) /
5744 ICMP(id=1026, type='echo-request'))
5745 pkts.append(p)
5746 self.pg0.add_stream(pkts)
5747 self.pg_enable_capture(self.pg_interfaces)
5748 self.pg_start()
5749 self.pg1.get_capture(max_sessions)
5750
5751 nsessions = 0
5752 users = self.vapi.nat44_user_dump()
5753 for user in users:
5754 nsessions = nsessions + user.nsessions
5755 self.assertLess(nsessions, 2 * max_sessions)
5756
5757 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
Matus Fabian15e8e682018-11-21 04:53:10 -08005758 def test_session_rst_timeout(self):
5759 """ NAT44 session RST timeouts """
5760 self.nat44_add_address(self.nat_addr)
5761 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5762 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
5763 is_inside=0)
5764 self.vapi.nat_set_timeouts(tcp_transitory=5)
5765
Matus Fabian15e8e682018-11-21 04:53:10 -08005766 self.initiate_tcp_session(self.pg0, self.pg1)
5767 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5768 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5769 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
5770 flags="R"))
5771 self.pg0.add_stream(p)
5772 self.pg_enable_capture(self.pg_interfaces)
5773 self.pg_start()
5774 self.pg1.get_capture(1)
5775
Matus Fabian15e8e682018-11-21 04:53:10 -08005776 sleep(6)
5777
5778 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5779 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5780 TCP(sport=self.tcp_port_in + 1, dport=self.tcp_external_port + 1,
5781 flags="S"))
5782 self.pg0.add_stream(p)
5783 self.pg_enable_capture(self.pg_interfaces)
5784 self.pg_start()
5785 self.pg1.get_capture(1)
5786
5787 nsessions = 0
5788 users = self.vapi.nat44_user_dump()
5789 self.assertEqual(len(users), 1)
5790 self.assertEqual(users[0].ip_address, self.pg0.remote_ip4n)
Matus Fabian7f8a8db2018-11-22 00:12:15 -08005791 self.assertEqual(users[0].nsessions, 1)
Matus Fabian15e8e682018-11-21 04:53:10 -08005792
5793 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
Matus Fabian878c6462018-08-23 00:33:35 -07005794 def test_session_limit_per_user(self):
5795 """ Maximum sessions per user limit """
5796 self.nat44_add_address(self.nat_addr)
5797 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5798 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
5799 is_inside=0)
5800 self.vapi.set_ipfix_exporter(collector_address=self.pg2.remote_ip4n,
5801 src_address=self.pg2.local_ip4n,
5802 path_mtu=512,
5803 template_interval=10)
Matus Fabian8fdc0152018-09-24 04:41:28 -07005804 self.vapi.nat_set_timeouts(udp=5)
Matus Fabian878c6462018-08-23 00:33:35 -07005805
5806 # get maximum number of translations per user
5807 nat44_config = self.vapi.nat_show_config()
5808
5809 pkts = []
5810 for port in range(0, nat44_config.max_translations_per_user):
5811 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5812 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5813 UDP(sport=1025 + port, dport=1025 + port))
5814 pkts.append(p)
5815
5816 self.pg0.add_stream(pkts)
5817 self.pg_enable_capture(self.pg_interfaces)
5818 self.pg_start()
5819 capture = self.pg1.get_capture(len(pkts))
5820
5821 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
5822 src_port=self.ipfix_src_port)
5823
5824 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5825 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5826 UDP(sport=3001, dport=3002))
5827 self.pg0.add_stream(p)
5828 self.pg_enable_capture(self.pg_interfaces)
5829 self.pg_start()
5830 capture = self.pg1.assert_nothing_captured()
5831
5832 # verify IPFIX logging
5833 self.vapi.cli("ipfix flush") # FIXME this should be an API call
5834 sleep(1)
5835 capture = self.pg2.get_capture(10)
5836 ipfix = IPFIXDecoder()
5837 # first load template
5838 for p in capture:
5839 self.assertTrue(p.haslayer(IPFIX))
5840 if p.haslayer(Template):
5841 ipfix.add_template(p.getlayer(Template))
5842 # verify events in data set
5843 for p in capture:
5844 if p.haslayer(Data):
5845 data = ipfix.decode_data_set(p.getlayer(Set))
5846 self.verify_ipfix_max_entries_per_user(
5847 data,
5848 nat44_config.max_translations_per_user,
5849 self.pg0.remote_ip4n)
5850
Matus Fabian8fdc0152018-09-24 04:41:28 -07005851 sleep(6)
5852 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5853 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5854 UDP(sport=3001, dport=3002))
5855 self.pg0.add_stream(p)
5856 self.pg_enable_capture(self.pg_interfaces)
5857 self.pg_start()
5858 self.pg1.get_capture(1)
5859
Matus Fabianad1f3e12018-11-28 21:26:34 -08005860 def test_syslog_sess(self):
5861 """ Test syslog session creation and deletion """
5862 self.vapi.syslog_set_filter(SYSLOG_SEVERITY.INFO)
5863 self.vapi.syslog_set_sender(self.pg2.remote_ip4n, self.pg2.local_ip4n)
5864 self.nat44_add_address(self.nat_addr)
5865 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5866 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
5867 is_inside=0)
5868
5869 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5870 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5871 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port))
5872 self.pg0.add_stream(p)
5873 self.pg_enable_capture(self.pg_interfaces)
5874 self.pg_start()
5875 capture = self.pg1.get_capture(1)
5876 self.tcp_port_out = capture[0][TCP].sport
5877 capture = self.pg2.get_capture(1)
5878 self.verify_syslog_sess(capture[0][Raw].load)
5879
5880 self.pg_enable_capture(self.pg_interfaces)
5881 self.pg_start()
5882 self.nat44_add_address(self.nat_addr, is_add=0)
5883 capture = self.pg2.get_capture(1)
5884 self.verify_syslog_sess(capture[0][Raw].load, False)
5885
Matus Fabiande886752016-12-07 03:38:19 -08005886 def tearDown(self):
Matus Fabiana6110b62018-06-13 05:39:07 -07005887 super(TestNAT44EndpointDependent, self).tearDown()
Matus Fabiande886752016-12-07 03:38:19 -08005888 if not self.vpp_dead:
Matus Fabian82119542018-01-25 01:13:22 -08005889 self.logger.info(self.vapi.cli("show nat44 addresses"))
5890 self.logger.info(self.vapi.cli("show nat44 interfaces"))
5891 self.logger.info(self.vapi.cli("show nat44 static mappings"))
5892 self.logger.info(self.vapi.cli("show nat44 interface address"))
5893 self.logger.info(self.vapi.cli("show nat44 sessions detail"))
Matus Fabian229c1aa2018-05-28 04:09:52 -07005894 self.logger.info(self.vapi.cli("show nat44 hash tables detail"))
Matus Fabian878c6462018-08-23 00:33:35 -07005895 self.logger.info(self.vapi.cli("show nat timeouts"))
Matus Fabian2ba92e32017-08-21 07:05:03 -07005896 self.clear_nat44()
Matus Fabian229c1aa2018-05-28 04:09:52 -07005897 self.vapi.cli("clear logging")
Matus Fabiande886752016-12-07 03:38:19 -08005898
Matus Fabianeea28d72017-01-13 04:15:54 -08005899
Juraj Slobodacba69362017-12-19 02:09:32 +01005900class TestNAT44Out2InDPO(MethodHolder):
5901 """ NAT44 Test Cases using out2in DPO """
5902
5903 @classmethod
5904 def setUpConstants(cls):
5905 super(TestNAT44Out2InDPO, cls).setUpConstants()
5906 cls.vpp_cmdline.extend(["nat", "{", "out2in dpo", "}"])
5907
5908 @classmethod
5909 def setUpClass(cls):
5910 super(TestNAT44Out2InDPO, cls).setUpClass()
Matus Fabian229c1aa2018-05-28 04:09:52 -07005911 cls.vapi.cli("set log class nat level debug")
Juraj Slobodacba69362017-12-19 02:09:32 +01005912
5913 try:
5914 cls.tcp_port_in = 6303
5915 cls.tcp_port_out = 6303
5916 cls.udp_port_in = 6304
5917 cls.udp_port_out = 6304
5918 cls.icmp_id_in = 6305
5919 cls.icmp_id_out = 6305
5920 cls.nat_addr = '10.0.0.3'
5921 cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
5922 cls.dst_ip4 = '192.168.70.1'
5923
5924 cls.create_pg_interfaces(range(2))
5925
5926 cls.pg0.admin_up()
5927 cls.pg0.config_ip4()
5928 cls.pg0.resolve_arp()
5929
5930 cls.pg1.admin_up()
5931 cls.pg1.config_ip6()
5932 cls.pg1.resolve_ndp()
5933
5934 cls.vapi.ip_add_del_route(is_ipv6=True, dst_address='\x00'*16,
5935 dst_address_length=0,
5936 next_hop_address=cls.pg1.remote_ip6n,
5937 next_hop_sw_if_index=cls.pg1.sw_if_index)
5938
5939 except Exception:
5940 super(TestNAT44Out2InDPO, cls).tearDownClass()
5941 raise
5942
5943 def configure_xlat(self):
5944 self.dst_ip6_pfx = '1:2:3::'
5945 self.dst_ip6_pfx_n = socket.inet_pton(socket.AF_INET6,
5946 self.dst_ip6_pfx)
5947 self.dst_ip6_pfx_len = 96
5948 self.src_ip6_pfx = '4:5:6::'
5949 self.src_ip6_pfx_n = socket.inet_pton(socket.AF_INET6,
5950 self.src_ip6_pfx)
5951 self.src_ip6_pfx_len = 96
5952 self.vapi.map_add_domain(self.dst_ip6_pfx_n, self.dst_ip6_pfx_len,
5953 self.src_ip6_pfx_n, self.src_ip6_pfx_len,
5954 '\x00\x00\x00\x00', 0, is_translation=1,
5955 is_rfc6052=1)
5956
Ole Troanffba3c32018-11-22 12:53:00 +01005957 @unittest.skip('Temporary disabled')
Juraj Slobodacba69362017-12-19 02:09:32 +01005958 def test_464xlat_ce(self):
5959 """ Test 464XLAT CE with NAT44 """
5960
Matus Fabian69ce30d2018-08-22 01:27:10 -07005961 nat_config = self.vapi.nat_show_config()
5962 self.assertEqual(1, nat_config.out2in_dpo)
5963
Juraj Slobodacba69362017-12-19 02:09:32 +01005964 self.configure_xlat()
5965
5966 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5967 self.vapi.nat44_add_del_address_range(self.nat_addr_n, self.nat_addr_n)
5968
5969 out_src_ip6 = self.compose_ip6(self.dst_ip4, self.dst_ip6_pfx,
5970 self.dst_ip6_pfx_len)
5971 out_dst_ip6 = self.compose_ip6(self.nat_addr, self.src_ip6_pfx,
5972 self.src_ip6_pfx_len)
5973
5974 try:
5975 pkts = self.create_stream_in(self.pg0, self.pg1, self.dst_ip4)
5976 self.pg0.add_stream(pkts)
5977 self.pg_enable_capture(self.pg_interfaces)
5978 self.pg_start()
5979 capture = self.pg1.get_capture(len(pkts))
5980 self.verify_capture_out_ip6(capture, nat_ip=out_dst_ip6,
5981 dst_ip=out_src_ip6)
5982
5983 pkts = self.create_stream_out_ip6(self.pg1, out_src_ip6,
5984 out_dst_ip6)
5985 self.pg1.add_stream(pkts)
5986 self.pg_enable_capture(self.pg_interfaces)
5987 self.pg_start()
5988 capture = self.pg0.get_capture(len(pkts))
5989 self.verify_capture_in(capture, self.pg0)
5990 finally:
5991 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
5992 is_add=0)
5993 self.vapi.nat44_add_del_address_range(self.nat_addr_n,
5994 self.nat_addr_n, is_add=0)
5995
Ole Troanffba3c32018-11-22 12:53:00 +01005996 @unittest.skip('Temporary disabled')
Juraj Slobodacba69362017-12-19 02:09:32 +01005997 def test_464xlat_ce_no_nat(self):
5998 """ Test 464XLAT CE without NAT44 """
5999
6000 self.configure_xlat()
6001
6002 out_src_ip6 = self.compose_ip6(self.dst_ip4, self.dst_ip6_pfx,
6003 self.dst_ip6_pfx_len)
6004 out_dst_ip6 = self.compose_ip6(self.pg0.remote_ip4, self.src_ip6_pfx,
6005 self.src_ip6_pfx_len)
6006
6007 pkts = self.create_stream_in(self.pg0, self.pg1, self.dst_ip4)
6008 self.pg0.add_stream(pkts)
6009 self.pg_enable_capture(self.pg_interfaces)
6010 self.pg_start()
6011 capture = self.pg1.get_capture(len(pkts))
6012 self.verify_capture_out_ip6(capture, dst_ip=out_src_ip6,
6013 nat_ip=out_dst_ip6, same_port=True)
6014
6015 pkts = self.create_stream_out_ip6(self.pg1, out_src_ip6, out_dst_ip6)
6016 self.pg1.add_stream(pkts)
6017 self.pg_enable_capture(self.pg_interfaces)
6018 self.pg_start()
6019 capture = self.pg0.get_capture(len(pkts))
6020 self.verify_capture_in(capture, self.pg0)
6021
6022
Martin Gálikd7f75cd2017-03-27 06:02:47 -07006023class TestDeterministicNAT(MethodHolder):
Matus Fabian066f0342017-02-10 03:48:01 -08006024 """ Deterministic NAT Test Cases """
6025
6026 @classmethod
6027 def setUpConstants(cls):
6028 super(TestDeterministicNAT, cls).setUpConstants()
Matus Fabian2ba92e32017-08-21 07:05:03 -07006029 cls.vpp_cmdline.extend(["nat", "{", "deterministic", "}"])
Matus Fabian066f0342017-02-10 03:48:01 -08006030
6031 @classmethod
6032 def setUpClass(cls):
6033 super(TestDeterministicNAT, cls).setUpClass()
Matus Fabian229c1aa2018-05-28 04:09:52 -07006034 cls.vapi.cli("set log class nat level debug")
Matus Fabian066f0342017-02-10 03:48:01 -08006035
6036 try:
Martin Gálik977c1cb2017-03-30 23:21:51 -07006037 cls.tcp_port_in = 6303
Martin Gálik9806eae2017-04-25 01:25:08 -07006038 cls.tcp_external_port = 6303
Martin Gálik977c1cb2017-03-30 23:21:51 -07006039 cls.udp_port_in = 6304
Martin Gálik9806eae2017-04-25 01:25:08 -07006040 cls.udp_external_port = 6304
Martin Gálik977c1cb2017-03-30 23:21:51 -07006041 cls.icmp_id_in = 6305
Matus Fabian2ba92e32017-08-21 07:05:03 -07006042 cls.nat_addr = '10.0.0.3'
Martin Gálik977c1cb2017-03-30 23:21:51 -07006043
Matus Fabian2f2db1c2017-04-18 05:29:59 -07006044 cls.create_pg_interfaces(range(3))
Matus Fabian066f0342017-02-10 03:48:01 -08006045 cls.interfaces = list(cls.pg_interfaces)
6046
6047 for i in cls.interfaces:
6048 i.admin_up()
6049 i.config_ip4()
6050 i.resolve_arp()
6051
Martin Gálik977c1cb2017-03-30 23:21:51 -07006052 cls.pg0.generate_remote_hosts(2)
6053 cls.pg0.configure_ipv4_neighbors()
6054
Matus Fabian066f0342017-02-10 03:48:01 -08006055 except Exception:
6056 super(TestDeterministicNAT, cls).tearDownClass()
6057 raise
6058
Martin Gálik977c1cb2017-03-30 23:21:51 -07006059 def create_stream_in(self, in_if, out_if, ttl=64):
6060 """
6061 Create packet stream for inside network
6062
6063 :param in_if: Inside interface
6064 :param out_if: Outside interface
6065 :param ttl: TTL of generated packets
6066 """
6067 pkts = []
6068 # TCP
6069 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
6070 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006071 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07006072 pkts.append(p)
6073
6074 # UDP
6075 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
6076 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006077 UDP(sport=self.udp_port_in, dport=self.udp_external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07006078 pkts.append(p)
6079
6080 # ICMP
6081 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
6082 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
6083 ICMP(id=self.icmp_id_in, type='echo-request'))
6084 pkts.append(p)
6085
6086 return pkts
6087
6088 def create_stream_out(self, out_if, dst_ip=None, ttl=64):
6089 """
6090 Create packet stream for outside network
6091
6092 :param out_if: Outside interface
Matus Fabian2ba92e32017-08-21 07:05:03 -07006093 :param dst_ip: Destination IP address (Default use global NAT address)
Martin Gálik977c1cb2017-03-30 23:21:51 -07006094 :param ttl: TTL of generated packets
6095 """
6096 if dst_ip is None:
Matus Fabian2ba92e32017-08-21 07:05:03 -07006097 dst_ip = self.nat_addr
Martin Gálik977c1cb2017-03-30 23:21:51 -07006098 pkts = []
6099 # TCP
6100 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
6101 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006102 TCP(dport=self.tcp_port_out, sport=self.tcp_external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07006103 pkts.append(p)
6104
6105 # UDP
6106 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
6107 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006108 UDP(dport=self.udp_port_out, sport=self.udp_external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07006109 pkts.append(p)
6110
6111 # ICMP
6112 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
6113 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
6114 ICMP(id=self.icmp_external_id, type='echo-reply'))
6115 pkts.append(p)
6116
6117 return pkts
6118
Matus Fabian05ca4a32018-09-04 23:45:13 -07006119 def verify_capture_out(self, capture, nat_ip=None):
Martin Gálik977c1cb2017-03-30 23:21:51 -07006120 """
6121 Verify captured packets on outside network
6122
6123 :param capture: Captured packets
Matus Fabian2ba92e32017-08-21 07:05:03 -07006124 :param nat_ip: Translated IP address (Default use global NAT address)
Martin Gálik977c1cb2017-03-30 23:21:51 -07006125 :param same_port: Sorce port number is not translated (Default False)
Martin Gálik977c1cb2017-03-30 23:21:51 -07006126 """
6127 if nat_ip is None:
Matus Fabian2ba92e32017-08-21 07:05:03 -07006128 nat_ip = self.nat_addr
Martin Gálik977c1cb2017-03-30 23:21:51 -07006129 for packet in capture:
6130 try:
6131 self.assertEqual(packet[IP].src, nat_ip)
6132 if packet.haslayer(TCP):
Martin Gálik9806eae2017-04-25 01:25:08 -07006133 self.tcp_port_out = packet[TCP].sport
Martin Gálik977c1cb2017-03-30 23:21:51 -07006134 elif packet.haslayer(UDP):
Martin Gálik9806eae2017-04-25 01:25:08 -07006135 self.udp_port_out = packet[UDP].sport
Martin Gálik977c1cb2017-03-30 23:21:51 -07006136 else:
6137 self.icmp_external_id = packet[ICMP].id
6138 except:
6139 self.logger.error(ppp("Unexpected or invalid packet "
6140 "(outside network):", packet))
6141 raise
6142
Matus Fabian066f0342017-02-10 03:48:01 -08006143 def test_deterministic_mode(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07006144 """ NAT plugin run deterministic mode """
Matus Fabian066f0342017-02-10 03:48:01 -08006145 in_addr = '172.16.255.0'
6146 out_addr = '172.17.255.50'
6147 in_addr_t = '172.16.255.20'
6148 in_addr_n = socket.inet_aton(in_addr)
6149 out_addr_n = socket.inet_aton(out_addr)
6150 in_addr_t_n = socket.inet_aton(in_addr_t)
6151 in_plen = 24
6152 out_plen = 32
6153
Matus Fabian2ba92e32017-08-21 07:05:03 -07006154 nat_config = self.vapi.nat_show_config()
6155 self.assertEqual(1, nat_config.deterministic)
Matus Fabian066f0342017-02-10 03:48:01 -08006156
Matus Fabian2ba92e32017-08-21 07:05:03 -07006157 self.vapi.nat_det_add_del_map(in_addr_n, in_plen, out_addr_n, out_plen)
Matus Fabian066f0342017-02-10 03:48:01 -08006158
Matus Fabian2ba92e32017-08-21 07:05:03 -07006159 rep1 = self.vapi.nat_det_forward(in_addr_t_n)
Matus Fabian066f0342017-02-10 03:48:01 -08006160 self.assertEqual(rep1.out_addr[:4], out_addr_n)
Matus Fabian2ba92e32017-08-21 07:05:03 -07006161 rep2 = self.vapi.nat_det_reverse(out_addr_n, rep1.out_port_hi)
Matus Fabian066f0342017-02-10 03:48:01 -08006162 self.assertEqual(rep2.in_addr[:4], in_addr_t_n)
6163
Matus Fabian2ba92e32017-08-21 07:05:03 -07006164 deterministic_mappings = self.vapi.nat_det_map_dump()
Martin17a75cb2017-03-08 05:53:20 -08006165 self.assertEqual(len(deterministic_mappings), 1)
6166 dsm = deterministic_mappings[0]
6167 self.assertEqual(in_addr_n, dsm.in_addr[:4])
6168 self.assertEqual(in_plen, dsm.in_plen)
6169 self.assertEqual(out_addr_n, dsm.out_addr[:4])
6170 self.assertEqual(out_plen, dsm.out_plen)
6171
Matus Fabian2ba92e32017-08-21 07:05:03 -07006172 self.clear_nat_det()
6173 deterministic_mappings = self.vapi.nat_det_map_dump()
Martinb616e9f2017-03-14 02:25:45 -07006174 self.assertEqual(len(deterministic_mappings), 0)
6175
Matus Fabian6a0946f2017-04-12 03:36:13 -07006176 def test_set_timeouts(self):
6177 """ Set deterministic NAT timeouts """
Matus Fabian878c6462018-08-23 00:33:35 -07006178 timeouts_before = self.vapi.nat_get_timeouts()
Matus Fabian6a0946f2017-04-12 03:36:13 -07006179
Matus Fabian878c6462018-08-23 00:33:35 -07006180 self.vapi.nat_set_timeouts(timeouts_before.udp + 10,
6181 timeouts_before.tcp_established + 10,
6182 timeouts_before.tcp_transitory + 10,
6183 timeouts_before.icmp + 10)
Matus Fabian6a0946f2017-04-12 03:36:13 -07006184
Matus Fabian878c6462018-08-23 00:33:35 -07006185 timeouts_after = self.vapi.nat_get_timeouts()
Matus Fabian6a0946f2017-04-12 03:36:13 -07006186
6187 self.assertNotEqual(timeouts_before.udp, timeouts_after.udp)
6188 self.assertNotEqual(timeouts_before.icmp, timeouts_after.icmp)
6189 self.assertNotEqual(timeouts_before.tcp_established,
6190 timeouts_after.tcp_established)
6191 self.assertNotEqual(timeouts_before.tcp_transitory,
6192 timeouts_after.tcp_transitory)
6193
Martin Gálik977c1cb2017-03-30 23:21:51 -07006194 def test_det_in(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07006195 """ Deterministic NAT translation test (TCP, UDP, ICMP) """
Martin Gálik977c1cb2017-03-30 23:21:51 -07006196
6197 nat_ip = "10.0.0.10"
Martin Gálik977c1cb2017-03-30 23:21:51 -07006198
Matus Fabian2ba92e32017-08-21 07:05:03 -07006199 self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
6200 32,
6201 socket.inet_aton(nat_ip),
6202 32)
6203 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
6204 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
6205 is_inside=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07006206
6207 # in2out
6208 pkts = self.create_stream_in(self.pg0, self.pg1)
6209 self.pg0.add_stream(pkts)
6210 self.pg_enable_capture(self.pg_interfaces)
6211 self.pg_start()
6212 capture = self.pg1.get_capture(len(pkts))
6213 self.verify_capture_out(capture, nat_ip)
6214
6215 # out2in
6216 pkts = self.create_stream_out(self.pg1, nat_ip)
6217 self.pg1.add_stream(pkts)
6218 self.pg_enable_capture(self.pg_interfaces)
6219 self.pg_start()
6220 capture = self.pg0.get_capture(len(pkts))
6221 self.verify_capture_in(capture, self.pg0)
6222
Martin Gálik9806eae2017-04-25 01:25:08 -07006223 # session dump test
Matus Fabian2ba92e32017-08-21 07:05:03 -07006224 sessions = self.vapi.nat_det_session_dump(self.pg0.remote_ip4n)
Martin Gálik9806eae2017-04-25 01:25:08 -07006225 self.assertEqual(len(sessions), 3)
6226
6227 # TCP session
6228 s = sessions[0]
6229 self.assertEqual(s.ext_addr[:4], self.pg1.remote_ip4n)
6230 self.assertEqual(s.in_port, self.tcp_port_in)
6231 self.assertEqual(s.out_port, self.tcp_port_out)
6232 self.assertEqual(s.ext_port, self.tcp_external_port)
6233
6234 # UDP session
6235 s = sessions[1]
6236 self.assertEqual(s.ext_addr[:4], self.pg1.remote_ip4n)
6237 self.assertEqual(s.in_port, self.udp_port_in)
6238 self.assertEqual(s.out_port, self.udp_port_out)
6239 self.assertEqual(s.ext_port, self.udp_external_port)
6240
6241 # ICMP session
6242 s = sessions[2]
6243 self.assertEqual(s.ext_addr[:4], self.pg1.remote_ip4n)
6244 self.assertEqual(s.in_port, self.icmp_id_in)
6245 self.assertEqual(s.out_port, self.icmp_external_id)
6246
Martin Gálik977c1cb2017-03-30 23:21:51 -07006247 def test_multiple_users(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07006248 """ Deterministic NAT multiple users """
Martin Gálik977c1cb2017-03-30 23:21:51 -07006249
6250 nat_ip = "10.0.0.10"
6251 port_in = 80
Martin Gálik9806eae2017-04-25 01:25:08 -07006252 external_port = 6303
Martin Gálik977c1cb2017-03-30 23:21:51 -07006253
6254 host0 = self.pg0.remote_hosts[0]
6255 host1 = self.pg0.remote_hosts[1]
6256
Matus Fabian2ba92e32017-08-21 07:05:03 -07006257 self.vapi.nat_det_add_del_map(host0.ip4n,
6258 24,
6259 socket.inet_aton(nat_ip),
6260 32)
6261 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
6262 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
6263 is_inside=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07006264
6265 # host0 to out
6266 p = (Ether(src=host0.mac, dst=self.pg0.local_mac) /
6267 IP(src=host0.ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006268 TCP(sport=port_in, dport=external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07006269 self.pg0.add_stream(p)
6270 self.pg_enable_capture(self.pg_interfaces)
6271 self.pg_start()
6272 capture = self.pg1.get_capture(1)
6273 p = capture[0]
6274 try:
6275 ip = p[IP]
6276 tcp = p[TCP]
6277 self.assertEqual(ip.src, nat_ip)
6278 self.assertEqual(ip.dst, self.pg1.remote_ip4)
Martin Gálik9806eae2017-04-25 01:25:08 -07006279 self.assertEqual(tcp.dport, external_port)
6280 port_out0 = tcp.sport
Martin Gálik977c1cb2017-03-30 23:21:51 -07006281 except:
6282 self.logger.error(ppp("Unexpected or invalid packet:", p))
6283 raise
6284
6285 # host1 to out
6286 p = (Ether(src=host1.mac, dst=self.pg0.local_mac) /
6287 IP(src=host1.ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006288 TCP(sport=port_in, dport=external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07006289 self.pg0.add_stream(p)
6290 self.pg_enable_capture(self.pg_interfaces)
6291 self.pg_start()
6292 capture = self.pg1.get_capture(1)
6293 p = capture[0]
6294 try:
6295 ip = p[IP]
6296 tcp = p[TCP]
6297 self.assertEqual(ip.src, nat_ip)
6298 self.assertEqual(ip.dst, self.pg1.remote_ip4)
Martin Gálik9806eae2017-04-25 01:25:08 -07006299 self.assertEqual(tcp.dport, external_port)
6300 port_out1 = tcp.sport
Martin Gálik977c1cb2017-03-30 23:21:51 -07006301 except:
6302 self.logger.error(ppp("Unexpected or invalid packet:", p))
6303 raise
6304
Matus Fabian2ba92e32017-08-21 07:05:03 -07006305 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07006306 self.assertEqual(1, len(dms))
6307 self.assertEqual(2, dms[0].ses_num)
6308
6309 # out to host0
6310 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6311 IP(src=self.pg1.remote_ip4, dst=nat_ip) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006312 TCP(sport=external_port, dport=port_out0))
Martin Gálik977c1cb2017-03-30 23:21:51 -07006313 self.pg1.add_stream(p)
6314 self.pg_enable_capture(self.pg_interfaces)
6315 self.pg_start()
6316 capture = self.pg0.get_capture(1)
6317 p = capture[0]
6318 try:
6319 ip = p[IP]
6320 tcp = p[TCP]
6321 self.assertEqual(ip.src, self.pg1.remote_ip4)
6322 self.assertEqual(ip.dst, host0.ip4)
6323 self.assertEqual(tcp.dport, port_in)
Martin Gálik9806eae2017-04-25 01:25:08 -07006324 self.assertEqual(tcp.sport, external_port)
Martin Gálik977c1cb2017-03-30 23:21:51 -07006325 except:
6326 self.logger.error(ppp("Unexpected or invalid packet:", p))
6327 raise
6328
6329 # out to host1
6330 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6331 IP(src=self.pg1.remote_ip4, dst=nat_ip) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006332 TCP(sport=external_port, dport=port_out1))
Martin Gálik977c1cb2017-03-30 23:21:51 -07006333 self.pg1.add_stream(p)
6334 self.pg_enable_capture(self.pg_interfaces)
6335 self.pg_start()
6336 capture = self.pg0.get_capture(1)
6337 p = capture[0]
6338 try:
6339 ip = p[IP]
6340 tcp = p[TCP]
6341 self.assertEqual(ip.src, self.pg1.remote_ip4)
6342 self.assertEqual(ip.dst, host1.ip4)
6343 self.assertEqual(tcp.dport, port_in)
Martin Gálik9806eae2017-04-25 01:25:08 -07006344 self.assertEqual(tcp.sport, external_port)
Martin Gálik977c1cb2017-03-30 23:21:51 -07006345 except:
6346 self.logger.error(ppp("Unexpected or invalid packet", p))
6347 raise
6348
Martin Gálik6bc8c642017-04-19 01:12:27 -07006349 # session close api test
Matus Fabian2ba92e32017-08-21 07:05:03 -07006350 self.vapi.nat_det_close_session_out(socket.inet_aton(nat_ip),
6351 port_out1,
Martin Gálik6bc8c642017-04-19 01:12:27 -07006352 self.pg1.remote_ip4n,
Martin Gálik9806eae2017-04-25 01:25:08 -07006353 external_port)
Matus Fabian2ba92e32017-08-21 07:05:03 -07006354 dms = self.vapi.nat_det_map_dump()
6355 self.assertEqual(dms[0].ses_num, 1)
6356
6357 self.vapi.nat_det_close_session_in(host0.ip4n,
6358 port_in,
6359 self.pg1.remote_ip4n,
6360 external_port)
6361 dms = self.vapi.nat_det_map_dump()
Martin Gálik6bc8c642017-04-19 01:12:27 -07006362 self.assertEqual(dms[0].ses_num, 0)
6363
Martin Gálik977c1cb2017-03-30 23:21:51 -07006364 def test_tcp_session_close_detection_in(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07006365 """ Deterministic NAT TCP session close from inside network """
6366 self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
6367 32,
6368 socket.inet_aton(self.nat_addr),
6369 32)
6370 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
6371 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
6372 is_inside=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07006373
6374 self.initiate_tcp_session(self.pg0, self.pg1)
6375
6376 # close the session from inside
6377 try:
6378 # FIN packet in -> out
6379 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6380 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006381 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
Martin Gálik977c1cb2017-03-30 23:21:51 -07006382 flags="F"))
6383 self.pg0.add_stream(p)
6384 self.pg_enable_capture(self.pg_interfaces)
6385 self.pg_start()
6386 self.pg1.get_capture(1)
6387
6388 pkts = []
6389
6390 # ACK packet out -> in
6391 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07006392 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006393 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
Martin Gálik977c1cb2017-03-30 23:21:51 -07006394 flags="A"))
6395 pkts.append(p)
6396
6397 # FIN packet out -> in
6398 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07006399 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006400 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
Martin Gálik977c1cb2017-03-30 23:21:51 -07006401 flags="F"))
6402 pkts.append(p)
6403
6404 self.pg1.add_stream(pkts)
6405 self.pg_enable_capture(self.pg_interfaces)
6406 self.pg_start()
6407 self.pg0.get_capture(2)
6408
6409 # ACK packet in -> out
6410 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6411 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006412 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
Martin Gálik977c1cb2017-03-30 23:21:51 -07006413 flags="A"))
6414 self.pg0.add_stream(p)
6415 self.pg_enable_capture(self.pg_interfaces)
6416 self.pg_start()
6417 self.pg1.get_capture(1)
6418
Matus Fabian2ba92e32017-08-21 07:05:03 -07006419 # Check if deterministic NAT44 closed the session
6420 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07006421 self.assertEqual(0, dms[0].ses_num)
6422 except:
6423 self.logger.error("TCP session termination failed")
6424 raise
6425
6426 def test_tcp_session_close_detection_out(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07006427 """ Deterministic NAT TCP session close from outside network """
6428 self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
6429 32,
6430 socket.inet_aton(self.nat_addr),
6431 32)
6432 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
6433 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
6434 is_inside=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07006435
6436 self.initiate_tcp_session(self.pg0, self.pg1)
6437
6438 # close the session from outside
6439 try:
6440 # FIN packet out -> in
6441 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07006442 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006443 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
Martin Gálik977c1cb2017-03-30 23:21:51 -07006444 flags="F"))
6445 self.pg1.add_stream(p)
6446 self.pg_enable_capture(self.pg_interfaces)
6447 self.pg_start()
6448 self.pg0.get_capture(1)
6449
6450 pkts = []
6451
6452 # ACK packet in -> out
6453 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6454 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006455 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
Martin Gálik977c1cb2017-03-30 23:21:51 -07006456 flags="A"))
6457 pkts.append(p)
6458
6459 # ACK packet in -> out
6460 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6461 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006462 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
Martin Gálik977c1cb2017-03-30 23:21:51 -07006463 flags="F"))
6464 pkts.append(p)
6465
6466 self.pg0.add_stream(pkts)
6467 self.pg_enable_capture(self.pg_interfaces)
6468 self.pg_start()
6469 self.pg1.get_capture(2)
6470
6471 # ACK packet out -> in
6472 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07006473 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006474 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
Martin Gálik977c1cb2017-03-30 23:21:51 -07006475 flags="A"))
6476 self.pg1.add_stream(p)
6477 self.pg_enable_capture(self.pg_interfaces)
6478 self.pg_start()
6479 self.pg0.get_capture(1)
6480
Matus Fabian2ba92e32017-08-21 07:05:03 -07006481 # Check if deterministic NAT44 closed the session
6482 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07006483 self.assertEqual(0, dms[0].ses_num)
6484 except:
6485 self.logger.error("TCP session termination failed")
6486 raise
6487
6488 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
6489 def test_session_timeout(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07006490 """ Deterministic NAT session timeouts """
6491 self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
6492 32,
6493 socket.inet_aton(self.nat_addr),
6494 32)
6495 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
6496 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
6497 is_inside=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07006498
6499 self.initiate_tcp_session(self.pg0, self.pg1)
Matus Fabian878c6462018-08-23 00:33:35 -07006500 self.vapi.nat_set_timeouts(5, 5, 5, 5)
Martin Gálik977c1cb2017-03-30 23:21:51 -07006501 pkts = self.create_stream_in(self.pg0, self.pg1)
6502 self.pg0.add_stream(pkts)
6503 self.pg_enable_capture(self.pg_interfaces)
6504 self.pg_start()
6505 capture = self.pg1.get_capture(len(pkts))
6506 sleep(15)
6507
Matus Fabian2ba92e32017-08-21 07:05:03 -07006508 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07006509 self.assertEqual(0, dms[0].ses_num)
6510
Matus Fabian7c0aecc2017-07-03 01:21:38 -07006511 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
Martin Gálik977c1cb2017-03-30 23:21:51 -07006512 def test_session_limit_per_user(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07006513 """ Deterministic NAT maximum sessions per user limit """
6514 self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
6515 32,
6516 socket.inet_aton(self.nat_addr),
6517 32)
6518 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
6519 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
6520 is_inside=0)
Matus Fabian2f2db1c2017-04-18 05:29:59 -07006521 self.vapi.set_ipfix_exporter(collector_address=self.pg2.remote_ip4n,
6522 src_address=self.pg2.local_ip4n,
6523 path_mtu=512,
6524 template_interval=10)
Matus Fabian2ba92e32017-08-21 07:05:03 -07006525 self.vapi.nat_ipfix()
Martin Gálik977c1cb2017-03-30 23:21:51 -07006526
6527 pkts = []
6528 for port in range(1025, 2025):
6529 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6530 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6531 UDP(sport=port, dport=port))
6532 pkts.append(p)
6533
6534 self.pg0.add_stream(pkts)
6535 self.pg_enable_capture(self.pg_interfaces)
6536 self.pg_start()
6537 capture = self.pg1.get_capture(len(pkts))
6538
6539 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6540 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálikf7e655d2017-04-27 02:13:26 -07006541 UDP(sport=3001, dport=3002))
Martin Gálik977c1cb2017-03-30 23:21:51 -07006542 self.pg0.add_stream(p)
6543 self.pg_enable_capture(self.pg_interfaces)
6544 self.pg_start()
6545 capture = self.pg1.assert_nothing_captured()
6546
Martin Gálikf7e655d2017-04-27 02:13:26 -07006547 # verify ICMP error packet
6548 capture = self.pg0.get_capture(1)
6549 p = capture[0]
6550 self.assertTrue(p.haslayer(ICMP))
6551 icmp = p[ICMP]
6552 self.assertEqual(icmp.type, 3)
6553 self.assertEqual(icmp.code, 1)
6554 self.assertTrue(icmp.haslayer(IPerror))
6555 inner_ip = icmp[IPerror]
6556 self.assertEqual(inner_ip[UDPerror].sport, 3001)
6557 self.assertEqual(inner_ip[UDPerror].dport, 3002)
6558
Matus Fabian2ba92e32017-08-21 07:05:03 -07006559 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07006560
6561 self.assertEqual(1000, dms[0].ses_num)
6562
Matus Fabian2f2db1c2017-04-18 05:29:59 -07006563 # verify IPFIX logging
6564 self.vapi.cli("ipfix flush") # FIXME this should be an API call
Matus Fabian7c0aecc2017-07-03 01:21:38 -07006565 sleep(1)
Matus Fabian2f2db1c2017-04-18 05:29:59 -07006566 capture = self.pg2.get_capture(2)
6567 ipfix = IPFIXDecoder()
6568 # first load template
6569 for p in capture:
6570 self.assertTrue(p.haslayer(IPFIX))
6571 if p.haslayer(Template):
6572 ipfix.add_template(p.getlayer(Template))
6573 # verify events in data set
6574 for p in capture:
6575 if p.haslayer(Data):
6576 data = ipfix.decode_data_set(p.getlayer(Set))
Matus Fabian878c6462018-08-23 00:33:35 -07006577 self.verify_ipfix_max_entries_per_user(data,
6578 1000,
6579 self.pg0.remote_ip4n)
Matus Fabian2f2db1c2017-04-18 05:29:59 -07006580
Matus Fabian2ba92e32017-08-21 07:05:03 -07006581 def clear_nat_det(self):
Martin17a75cb2017-03-08 05:53:20 -08006582 """
Matus Fabian2ba92e32017-08-21 07:05:03 -07006583 Clear deterministic NAT configuration.
Martin17a75cb2017-03-08 05:53:20 -08006584 """
Matus Fabian2ba92e32017-08-21 07:05:03 -07006585 self.vapi.nat_ipfix(enable=0)
Matus Fabian878c6462018-08-23 00:33:35 -07006586 self.vapi.nat_set_timeouts()
Matus Fabian2ba92e32017-08-21 07:05:03 -07006587 deterministic_mappings = self.vapi.nat_det_map_dump()
Martin17a75cb2017-03-08 05:53:20 -08006588 for dsm in deterministic_mappings:
Matus Fabian2ba92e32017-08-21 07:05:03 -07006589 self.vapi.nat_det_add_del_map(dsm.in_addr,
6590 dsm.in_plen,
6591 dsm.out_addr,
6592 dsm.out_plen,
6593 is_add=0)
Martin17a75cb2017-03-08 05:53:20 -08006594
Matus Fabian2ba92e32017-08-21 07:05:03 -07006595 interfaces = self.vapi.nat44_interface_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07006596 for intf in interfaces:
Matus Fabian2ba92e32017-08-21 07:05:03 -07006597 self.vapi.nat44_interface_add_del_feature(intf.sw_if_index,
6598 intf.is_inside,
6599 is_add=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07006600
Matus Fabian066f0342017-02-10 03:48:01 -08006601 def tearDown(self):
6602 super(TestDeterministicNAT, self).tearDown()
6603 if not self.vpp_dead:
Matus Fabian82119542018-01-25 01:13:22 -08006604 self.logger.info(self.vapi.cli("show nat44 interfaces"))
Matus Fabian878c6462018-08-23 00:33:35 -07006605 self.logger.info(self.vapi.cli("show nat timeouts"))
Matus Fabian82119542018-01-25 01:13:22 -08006606 self.logger.info(
6607 self.vapi.cli("show nat44 deterministic mappings"))
6608 self.logger.info(
Matus Fabian82119542018-01-25 01:13:22 -08006609 self.vapi.cli("show nat44 deterministic sessions"))
Matus Fabian2ba92e32017-08-21 07:05:03 -07006610 self.clear_nat_det()
Matus Fabian066f0342017-02-10 03:48:01 -08006611
Matus Fabian06596c52017-06-06 04:53:28 -07006612
6613class TestNAT64(MethodHolder):
6614 """ NAT64 Test Cases """
6615
6616 @classmethod
Matus Fabiana431ad12018-01-04 04:03:14 -08006617 def setUpConstants(cls):
6618 super(TestNAT64, cls).setUpConstants()
6619 cls.vpp_cmdline.extend(["nat", "{", "nat64 bib hash buckets 128",
6620 "nat64 st hash buckets 256", "}"])
6621
6622 @classmethod
Matus Fabian06596c52017-06-06 04:53:28 -07006623 def setUpClass(cls):
6624 super(TestNAT64, cls).setUpClass()
6625
6626 try:
6627 cls.tcp_port_in = 6303
6628 cls.tcp_port_out = 6303
6629 cls.udp_port_in = 6304
6630 cls.udp_port_out = 6304
6631 cls.icmp_id_in = 6305
6632 cls.icmp_id_out = 6305
Matus Fabianad1f3e12018-11-28 21:26:34 -08006633 cls.tcp_external_port = 80
Matus Fabian06596c52017-06-06 04:53:28 -07006634 cls.nat_addr = '10.0.0.3'
6635 cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
Matus Fabian029f3d22017-06-15 02:28:50 -07006636 cls.vrf1_id = 10
6637 cls.vrf1_nat_addr = '10.0.10.3'
6638 cls.vrf1_nat_addr_n = socket.inet_pton(socket.AF_INET,
6639 cls.vrf1_nat_addr)
Matus Fabiana431ad12018-01-04 04:03:14 -08006640 cls.ipfix_src_port = 4739
6641 cls.ipfix_domain_id = 1
Matus Fabian06596c52017-06-06 04:53:28 -07006642
Juraj Slobodac746a152018-07-09 02:36:37 +02006643 cls.create_pg_interfaces(range(6))
Matus Fabian06596c52017-06-06 04:53:28 -07006644 cls.ip6_interfaces = list(cls.pg_interfaces[0:1])
Matus Fabian029f3d22017-06-15 02:28:50 -07006645 cls.ip6_interfaces.append(cls.pg_interfaces[2])
Matus Fabian06596c52017-06-06 04:53:28 -07006646 cls.ip4_interfaces = list(cls.pg_interfaces[1:2])
6647
Neale Ranns15002542017-09-10 04:39:11 -07006648 cls.vapi.ip_table_add_del(cls.vrf1_id, is_add=1, is_ipv6=1)
6649
Matus Fabian029f3d22017-06-15 02:28:50 -07006650 cls.pg_interfaces[2].set_table_ip6(cls.vrf1_id)
6651
6652 cls.pg0.generate_remote_hosts(2)
6653
Matus Fabian06596c52017-06-06 04:53:28 -07006654 for i in cls.ip6_interfaces:
6655 i.admin_up()
6656 i.config_ip6()
Matus Fabian029f3d22017-06-15 02:28:50 -07006657 i.configure_ipv6_neighbors()
Matus Fabian06596c52017-06-06 04:53:28 -07006658
6659 for i in cls.ip4_interfaces:
6660 i.admin_up()
6661 i.config_ip4()
6662 i.resolve_arp()
6663
Matus Fabian36ea2d62017-10-24 04:13:49 -07006664 cls.pg3.admin_up()
6665 cls.pg3.config_ip4()
6666 cls.pg3.resolve_arp()
6667 cls.pg3.config_ip6()
6668 cls.pg3.configure_ipv6_neighbors()
6669
Juraj Slobodac746a152018-07-09 02:36:37 +02006670 cls.pg5.admin_up()
6671 cls.pg5.config_ip6()
6672
Matus Fabian06596c52017-06-06 04:53:28 -07006673 except Exception:
6674 super(TestNAT64, cls).tearDownClass()
6675 raise
6676
Juraj Slobodac746a152018-07-09 02:36:37 +02006677 def test_nat64_inside_interface_handles_neighbor_advertisement(self):
6678 """ NAT64 inside interface handles Neighbor Advertisement """
6679
6680 self.vapi.nat64_add_del_interface(self.pg5.sw_if_index)
6681
6682 # Try to send ping
6683 ping = (Ether(dst=self.pg5.local_mac, src=self.pg5.remote_mac) /
6684 IPv6(src=self.pg5.remote_ip6, dst=self.pg5.local_ip6) /
6685 ICMPv6EchoRequest())
6686 pkts = [ping]
6687 self.pg5.add_stream(pkts)
6688 self.pg_enable_capture(self.pg_interfaces)
6689 self.pg_start()
6690
6691 # Wait for Neighbor Solicitation
6692 capture = self.pg5.get_capture(len(pkts))
Juraj Slobodac746a152018-07-09 02:36:37 +02006693 packet = capture[0]
6694 try:
6695 self.assertEqual(packet[IPv6].src, self.pg5.local_ip6)
6696 self.assertTrue(packet.haslayer(ICMPv6ND_NS))
6697 tgt = packet[ICMPv6ND_NS].tgt
6698 except:
6699 self.logger.error(ppp("Unexpected or invalid packet:", packet))
6700 raise
6701
6702 # Send Neighbor Advertisement
6703 p = (Ether(dst=self.pg5.local_mac, src=self.pg5.remote_mac) /
6704 IPv6(src=self.pg5.remote_ip6, dst=self.pg5.local_ip6) /
6705 ICMPv6ND_NA(tgt=tgt) /
6706 ICMPv6NDOptDstLLAddr(lladdr=self.pg5.remote_mac))
6707 pkts = [p]
6708 self.pg5.add_stream(pkts)
6709 self.pg_enable_capture(self.pg_interfaces)
6710 self.pg_start()
6711
6712 # Try to send ping again
6713 pkts = [ping]
6714 self.pg5.add_stream(pkts)
6715 self.pg_enable_capture(self.pg_interfaces)
6716 self.pg_start()
6717
6718 # Wait for ping reply
6719 capture = self.pg5.get_capture(len(pkts))
Juraj Slobodac746a152018-07-09 02:36:37 +02006720 packet = capture[0]
6721 try:
6722 self.assertEqual(packet[IPv6].src, self.pg5.local_ip6)
6723 self.assertEqual(packet[IPv6].dst, self.pg5.remote_ip6)
6724 self.assertTrue(packet.haslayer(ICMPv6EchoReply))
6725 except:
6726 self.logger.error(ppp("Unexpected or invalid packet:", packet))
6727 raise
6728
Matus Fabian06596c52017-06-06 04:53:28 -07006729 def test_pool(self):
6730 """ Add/delete address to NAT64 pool """
6731 nat_addr = socket.inet_pton(socket.AF_INET, '1.2.3.4')
6732
6733 self.vapi.nat64_add_del_pool_addr_range(nat_addr, nat_addr)
6734
6735 addresses = self.vapi.nat64_pool_addr_dump()
6736 self.assertEqual(len(addresses), 1)
6737 self.assertEqual(addresses[0].address, nat_addr)
6738
6739 self.vapi.nat64_add_del_pool_addr_range(nat_addr, nat_addr, is_add=0)
6740
6741 addresses = self.vapi.nat64_pool_addr_dump()
6742 self.assertEqual(len(addresses), 0)
6743
6744 def test_interface(self):
6745 """ Enable/disable NAT64 feature on the interface """
6746 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6747 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6748
6749 interfaces = self.vapi.nat64_interface_dump()
6750 self.assertEqual(len(interfaces), 2)
6751 pg0_found = False
6752 pg1_found = False
6753 for intf in interfaces:
6754 if intf.sw_if_index == self.pg0.sw_if_index:
6755 self.assertEqual(intf.is_inside, 1)
6756 pg0_found = True
6757 elif intf.sw_if_index == self.pg1.sw_if_index:
6758 self.assertEqual(intf.is_inside, 0)
6759 pg1_found = True
6760 self.assertTrue(pg0_found)
6761 self.assertTrue(pg1_found)
6762
6763 features = self.vapi.cli("show interface features pg0")
6764 self.assertNotEqual(features.find('nat64-in2out'), -1)
6765 features = self.vapi.cli("show interface features pg1")
6766 self.assertNotEqual(features.find('nat64-out2in'), -1)
6767
6768 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index, is_add=0)
6769 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_add=0)
6770
6771 interfaces = self.vapi.nat64_interface_dump()
6772 self.assertEqual(len(interfaces), 0)
6773
6774 def test_static_bib(self):
6775 """ Add/delete static BIB entry """
6776 in_addr = socket.inet_pton(socket.AF_INET6,
6777 '2001:db8:85a3::8a2e:370:7334')
6778 out_addr = socket.inet_pton(socket.AF_INET, '10.1.1.3')
6779 in_port = 1234
6780 out_port = 5678
6781 proto = IP_PROTOS.tcp
6782
6783 self.vapi.nat64_add_del_static_bib(in_addr,
6784 out_addr,
6785 in_port,
6786 out_port,
6787 proto)
6788 bib = self.vapi.nat64_bib_dump(IP_PROTOS.tcp)
6789 static_bib_num = 0
6790 for bibe in bib:
6791 if bibe.is_static:
6792 static_bib_num += 1
6793 self.assertEqual(bibe.i_addr, in_addr)
6794 self.assertEqual(bibe.o_addr, out_addr)
6795 self.assertEqual(bibe.i_port, in_port)
6796 self.assertEqual(bibe.o_port, out_port)
6797 self.assertEqual(static_bib_num, 1)
6798
6799 self.vapi.nat64_add_del_static_bib(in_addr,
6800 out_addr,
6801 in_port,
6802 out_port,
6803 proto,
6804 is_add=0)
6805 bib = self.vapi.nat64_bib_dump(IP_PROTOS.tcp)
6806 static_bib_num = 0
6807 for bibe in bib:
6808 if bibe.is_static:
6809 static_bib_num += 1
6810 self.assertEqual(static_bib_num, 0)
6811
6812 def test_set_timeouts(self):
6813 """ Set NAT64 timeouts """
6814 # verify default values
Matus Fabian878c6462018-08-23 00:33:35 -07006815 timeouts = self.vapi.nat_get_timeouts()
Matus Fabian06596c52017-06-06 04:53:28 -07006816 self.assertEqual(timeouts.udp, 300)
6817 self.assertEqual(timeouts.icmp, 60)
Matus Fabian878c6462018-08-23 00:33:35 -07006818 self.assertEqual(timeouts.tcp_transitory, 240)
6819 self.assertEqual(timeouts.tcp_established, 7440)
Matus Fabian06596c52017-06-06 04:53:28 -07006820
6821 # set and verify custom values
Matus Fabian878c6462018-08-23 00:33:35 -07006822 self.vapi.nat_set_timeouts(udp=200, icmp=30, tcp_transitory=250,
6823 tcp_established=7450)
6824 timeouts = self.vapi.nat_get_timeouts()
Matus Fabian06596c52017-06-06 04:53:28 -07006825 self.assertEqual(timeouts.udp, 200)
6826 self.assertEqual(timeouts.icmp, 30)
Matus Fabian878c6462018-08-23 00:33:35 -07006827 self.assertEqual(timeouts.tcp_transitory, 250)
6828 self.assertEqual(timeouts.tcp_established, 7450)
Matus Fabian06596c52017-06-06 04:53:28 -07006829
6830 def test_dynamic(self):
6831 """ NAT64 dynamic translation test """
6832 self.tcp_port_in = 6303
6833 self.udp_port_in = 6304
6834 self.icmp_id_in = 6305
6835
6836 ses_num_start = self.nat64_get_ses_num()
6837
6838 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6839 self.nat_addr_n)
6840 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6841 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6842
6843 # in2out
6844 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
6845 self.pg0.add_stream(pkts)
6846 self.pg_enable_capture(self.pg_interfaces)
6847 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07006848 capture = self.pg1.get_capture(len(pkts))
6849 self.verify_capture_out(capture, nat_ip=self.nat_addr,
Matus Fabian06596c52017-06-06 04:53:28 -07006850 dst_ip=self.pg1.remote_ip4)
6851
6852 # out2in
6853 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
6854 self.pg1.add_stream(pkts)
6855 self.pg_enable_capture(self.pg_interfaces)
6856 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07006857 capture = self.pg0.get_capture(len(pkts))
Matus Fabian06596c52017-06-06 04:53:28 -07006858 ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
6859 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
6860
6861 # in2out
6862 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
6863 self.pg0.add_stream(pkts)
6864 self.pg_enable_capture(self.pg_interfaces)
6865 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07006866 capture = self.pg1.get_capture(len(pkts))
6867 self.verify_capture_out(capture, nat_ip=self.nat_addr,
Matus Fabian06596c52017-06-06 04:53:28 -07006868 dst_ip=self.pg1.remote_ip4)
6869
6870 # out2in
6871 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
6872 self.pg1.add_stream(pkts)
6873 self.pg_enable_capture(self.pg_interfaces)
6874 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07006875 capture = self.pg0.get_capture(len(pkts))
Matus Fabian06596c52017-06-06 04:53:28 -07006876 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
6877
6878 ses_num_end = self.nat64_get_ses_num()
6879
6880 self.assertEqual(ses_num_end - ses_num_start, 3)
6881
Matus Fabian029f3d22017-06-15 02:28:50 -07006882 # tenant with specific VRF
6883 self.vapi.nat64_add_del_pool_addr_range(self.vrf1_nat_addr_n,
6884 self.vrf1_nat_addr_n,
6885 vrf_id=self.vrf1_id)
6886 self.vapi.nat64_add_del_interface(self.pg2.sw_if_index)
6887
6888 pkts = self.create_stream_in_ip6(self.pg2, self.pg1)
6889 self.pg2.add_stream(pkts)
6890 self.pg_enable_capture(self.pg_interfaces)
6891 self.pg_start()
6892 capture = self.pg1.get_capture(len(pkts))
6893 self.verify_capture_out(capture, nat_ip=self.vrf1_nat_addr,
6894 dst_ip=self.pg1.remote_ip4)
6895
6896 pkts = self.create_stream_out(self.pg1, dst_ip=self.vrf1_nat_addr)
6897 self.pg1.add_stream(pkts)
6898 self.pg_enable_capture(self.pg_interfaces)
6899 self.pg_start()
6900 capture = self.pg2.get_capture(len(pkts))
6901 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg2.remote_ip6)
6902
Matus Fabian06596c52017-06-06 04:53:28 -07006903 def test_static(self):
6904 """ NAT64 static translation test """
6905 self.tcp_port_in = 60303
6906 self.udp_port_in = 60304
6907 self.icmp_id_in = 60305
6908 self.tcp_port_out = 60303
6909 self.udp_port_out = 60304
6910 self.icmp_id_out = 60305
6911
6912 ses_num_start = self.nat64_get_ses_num()
6913
6914 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6915 self.nat_addr_n)
6916 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6917 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6918
6919 self.vapi.nat64_add_del_static_bib(self.pg0.remote_ip6n,
6920 self.nat_addr_n,
6921 self.tcp_port_in,
6922 self.tcp_port_out,
6923 IP_PROTOS.tcp)
6924 self.vapi.nat64_add_del_static_bib(self.pg0.remote_ip6n,
6925 self.nat_addr_n,
6926 self.udp_port_in,
6927 self.udp_port_out,
6928 IP_PROTOS.udp)
6929 self.vapi.nat64_add_del_static_bib(self.pg0.remote_ip6n,
6930 self.nat_addr_n,
6931 self.icmp_id_in,
6932 self.icmp_id_out,
6933 IP_PROTOS.icmp)
6934
6935 # in2out
6936 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
6937 self.pg0.add_stream(pkts)
6938 self.pg_enable_capture(self.pg_interfaces)
6939 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07006940 capture = self.pg1.get_capture(len(pkts))
6941 self.verify_capture_out(capture, nat_ip=self.nat_addr,
Matus Fabian06596c52017-06-06 04:53:28 -07006942 dst_ip=self.pg1.remote_ip4, same_port=True)
6943
6944 # out2in
6945 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
6946 self.pg1.add_stream(pkts)
6947 self.pg_enable_capture(self.pg_interfaces)
6948 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07006949 capture = self.pg0.get_capture(len(pkts))
Matus Fabian06596c52017-06-06 04:53:28 -07006950 ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
6951 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
6952
6953 ses_num_end = self.nat64_get_ses_num()
6954
6955 self.assertEqual(ses_num_end - ses_num_start, 3)
6956
6957 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
6958 def test_session_timeout(self):
6959 """ NAT64 session timeout """
6960 self.icmp_id_in = 1234
6961 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6962 self.nat_addr_n)
6963 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6964 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
Matus Fabian878c6462018-08-23 00:33:35 -07006965 self.vapi.nat_set_timeouts(icmp=5, tcp_transitory=5, tcp_established=5)
Matus Fabian06596c52017-06-06 04:53:28 -07006966
6967 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
6968 self.pg0.add_stream(pkts)
6969 self.pg_enable_capture(self.pg_interfaces)
6970 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07006971 capture = self.pg1.get_capture(len(pkts))
Matus Fabian06596c52017-06-06 04:53:28 -07006972
6973 ses_num_before_timeout = self.nat64_get_ses_num()
6974
6975 sleep(15)
6976
Matus Fabian8fed4242018-08-14 05:14:55 -07006977 # ICMP and TCP session after timeout
Matus Fabian06596c52017-06-06 04:53:28 -07006978 ses_num_after_timeout = self.nat64_get_ses_num()
Matus Fabian8fed4242018-08-14 05:14:55 -07006979 self.assertEqual(ses_num_before_timeout - ses_num_after_timeout, 2)
Matus Fabian06596c52017-06-06 04:53:28 -07006980
Matus Fabian732036d2017-06-08 05:24:28 -07006981 def test_icmp_error(self):
6982 """ NAT64 ICMP Error message translation """
6983 self.tcp_port_in = 6303
6984 self.udp_port_in = 6304
6985 self.icmp_id_in = 6305
6986
Matus Fabian732036d2017-06-08 05:24:28 -07006987 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6988 self.nat_addr_n)
6989 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6990 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6991
6992 # send some packets to create sessions
6993 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
6994 self.pg0.add_stream(pkts)
6995 self.pg_enable_capture(self.pg_interfaces)
6996 self.pg_start()
6997 capture_ip4 = self.pg1.get_capture(len(pkts))
Matus Fabian029f3d22017-06-15 02:28:50 -07006998 self.verify_capture_out(capture_ip4,
Matus Fabian732036d2017-06-08 05:24:28 -07006999 nat_ip=self.nat_addr,
7000 dst_ip=self.pg1.remote_ip4)
7001
7002 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
7003 self.pg1.add_stream(pkts)
7004 self.pg_enable_capture(self.pg_interfaces)
7005 self.pg_start()
7006 capture_ip6 = self.pg0.get_capture(len(pkts))
7007 ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
7008 self.verify_capture_in_ip6(capture_ip6, ip[IPv6].src,
7009 self.pg0.remote_ip6)
7010
7011 # in2out
7012 pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7013 IPv6(src=self.pg0.remote_ip6, dst=ip[IPv6].src) /
7014 ICMPv6DestUnreach(code=1) /
7015 packet[IPv6] for packet in capture_ip6]
7016 self.pg0.add_stream(pkts)
7017 self.pg_enable_capture(self.pg_interfaces)
7018 self.pg_start()
7019 capture = self.pg1.get_capture(len(pkts))
7020 for packet in capture:
7021 try:
7022 self.assertEqual(packet[IP].src, self.nat_addr)
7023 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
7024 self.assertEqual(packet[ICMP].type, 3)
7025 self.assertEqual(packet[ICMP].code, 13)
7026 inner = packet[IPerror]
7027 self.assertEqual(inner.src, self.pg1.remote_ip4)
7028 self.assertEqual(inner.dst, self.nat_addr)
Klement Sekerad81ae412018-05-16 10:52:54 +02007029 self.assert_packet_checksums_valid(packet)
Matus Fabian732036d2017-06-08 05:24:28 -07007030 if inner.haslayer(TCPerror):
7031 self.assertEqual(inner[TCPerror].dport, self.tcp_port_out)
7032 elif inner.haslayer(UDPerror):
7033 self.assertEqual(inner[UDPerror].dport, self.udp_port_out)
7034 else:
7035 self.assertEqual(inner[ICMPerror].id, self.icmp_id_out)
7036 except:
7037 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7038 raise
7039
7040 # out2in
7041 pkts = [Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
7042 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
7043 ICMP(type=3, code=13) /
7044 packet[IP] for packet in capture_ip4]
7045 self.pg1.add_stream(pkts)
7046 self.pg_enable_capture(self.pg_interfaces)
7047 self.pg_start()
7048 capture = self.pg0.get_capture(len(pkts))
7049 for packet in capture:
7050 try:
7051 self.assertEqual(packet[IPv6].src, ip.src)
7052 self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
7053 icmp = packet[ICMPv6DestUnreach]
7054 self.assertEqual(icmp.code, 1)
7055 inner = icmp[IPerror6]
7056 self.assertEqual(inner.src, self.pg0.remote_ip6)
7057 self.assertEqual(inner.dst, ip.src)
Klement Sekerad81ae412018-05-16 10:52:54 +02007058 self.assert_icmpv6_checksum_valid(packet)
Matus Fabian732036d2017-06-08 05:24:28 -07007059 if inner.haslayer(TCPerror):
7060 self.assertEqual(inner[TCPerror].sport, self.tcp_port_in)
7061 elif inner.haslayer(UDPerror):
7062 self.assertEqual(inner[UDPerror].sport, self.udp_port_in)
7063 else:
7064 self.assertEqual(inner[ICMPv6EchoRequest].id,
7065 self.icmp_id_in)
7066 except:
7067 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7068 raise
7069
Matus Fabian029f3d22017-06-15 02:28:50 -07007070 def test_hairpinning(self):
7071 """ NAT64 hairpinning """
7072
7073 client = self.pg0.remote_hosts[0]
7074 server = self.pg0.remote_hosts[1]
7075 server_tcp_in_port = 22
7076 server_tcp_out_port = 4022
7077 server_udp_in_port = 23
7078 server_udp_out_port = 4023
7079 client_tcp_in_port = 1234
7080 client_udp_in_port = 1235
7081 client_tcp_out_port = 0
7082 client_udp_out_port = 0
7083 ip = IPv6(src=''.join(['64:ff9b::', self.nat_addr]))
7084 nat_addr_ip6 = ip.src
7085
7086 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7087 self.nat_addr_n)
7088 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7089 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7090
7091 self.vapi.nat64_add_del_static_bib(server.ip6n,
7092 self.nat_addr_n,
7093 server_tcp_in_port,
7094 server_tcp_out_port,
7095 IP_PROTOS.tcp)
7096 self.vapi.nat64_add_del_static_bib(server.ip6n,
7097 self.nat_addr_n,
7098 server_udp_in_port,
7099 server_udp_out_port,
7100 IP_PROTOS.udp)
7101
7102 # client to server
7103 pkts = []
7104 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7105 IPv6(src=client.ip6, dst=nat_addr_ip6) /
7106 TCP(sport=client_tcp_in_port, dport=server_tcp_out_port))
7107 pkts.append(p)
7108 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7109 IPv6(src=client.ip6, dst=nat_addr_ip6) /
7110 UDP(sport=client_udp_in_port, dport=server_udp_out_port))
7111 pkts.append(p)
7112 self.pg0.add_stream(pkts)
7113 self.pg_enable_capture(self.pg_interfaces)
7114 self.pg_start()
7115 capture = self.pg0.get_capture(len(pkts))
7116 for packet in capture:
7117 try:
7118 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
7119 self.assertEqual(packet[IPv6].dst, server.ip6)
Klement Sekerad81ae412018-05-16 10:52:54 +02007120 self.assert_packet_checksums_valid(packet)
Matus Fabian029f3d22017-06-15 02:28:50 -07007121 if packet.haslayer(TCP):
7122 self.assertNotEqual(packet[TCP].sport, client_tcp_in_port)
7123 self.assertEqual(packet[TCP].dport, server_tcp_in_port)
Matus Fabian029f3d22017-06-15 02:28:50 -07007124 client_tcp_out_port = packet[TCP].sport
7125 else:
7126 self.assertNotEqual(packet[UDP].sport, client_udp_in_port)
7127 self.assertEqual(packet[UDP].dport, server_udp_in_port)
Matus Fabian029f3d22017-06-15 02:28:50 -07007128 client_udp_out_port = packet[UDP].sport
7129 except:
7130 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7131 raise
7132
7133 # server to client
7134 pkts = []
7135 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7136 IPv6(src=server.ip6, dst=nat_addr_ip6) /
7137 TCP(sport=server_tcp_in_port, dport=client_tcp_out_port))
7138 pkts.append(p)
7139 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7140 IPv6(src=server.ip6, dst=nat_addr_ip6) /
7141 UDP(sport=server_udp_in_port, dport=client_udp_out_port))
7142 pkts.append(p)
7143 self.pg0.add_stream(pkts)
7144 self.pg_enable_capture(self.pg_interfaces)
7145 self.pg_start()
7146 capture = self.pg0.get_capture(len(pkts))
7147 for packet in capture:
7148 try:
7149 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
7150 self.assertEqual(packet[IPv6].dst, client.ip6)
Klement Sekerad81ae412018-05-16 10:52:54 +02007151 self.assert_packet_checksums_valid(packet)
Matus Fabian029f3d22017-06-15 02:28:50 -07007152 if packet.haslayer(TCP):
7153 self.assertEqual(packet[TCP].sport, server_tcp_out_port)
7154 self.assertEqual(packet[TCP].dport, client_tcp_in_port)
Matus Fabian029f3d22017-06-15 02:28:50 -07007155 else:
7156 self.assertEqual(packet[UDP].sport, server_udp_out_port)
7157 self.assertEqual(packet[UDP].dport, client_udp_in_port)
Matus Fabian029f3d22017-06-15 02:28:50 -07007158 except:
7159 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7160 raise
7161
7162 # ICMP error
7163 pkts = []
7164 pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7165 IPv6(src=client.ip6, dst=nat_addr_ip6) /
7166 ICMPv6DestUnreach(code=1) /
7167 packet[IPv6] for packet in capture]
7168 self.pg0.add_stream(pkts)
7169 self.pg_enable_capture(self.pg_interfaces)
7170 self.pg_start()
7171 capture = self.pg0.get_capture(len(pkts))
7172 for packet in capture:
7173 try:
7174 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
7175 self.assertEqual(packet[IPv6].dst, server.ip6)
7176 icmp = packet[ICMPv6DestUnreach]
7177 self.assertEqual(icmp.code, 1)
7178 inner = icmp[IPerror6]
7179 self.assertEqual(inner.src, server.ip6)
7180 self.assertEqual(inner.dst, nat_addr_ip6)
Klement Sekerad81ae412018-05-16 10:52:54 +02007181 self.assert_packet_checksums_valid(packet)
Matus Fabian029f3d22017-06-15 02:28:50 -07007182 if inner.haslayer(TCPerror):
7183 self.assertEqual(inner[TCPerror].sport, server_tcp_in_port)
7184 self.assertEqual(inner[TCPerror].dport,
7185 client_tcp_out_port)
7186 else:
7187 self.assertEqual(inner[UDPerror].sport, server_udp_in_port)
7188 self.assertEqual(inner[UDPerror].dport,
7189 client_udp_out_port)
7190 except:
7191 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7192 raise
7193
Matus Fabian428dc912017-06-21 06:15:18 -07007194 def test_prefix(self):
7195 """ NAT64 Network-Specific Prefix """
7196
7197 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7198 self.nat_addr_n)
7199 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7200 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7201 self.vapi.nat64_add_del_pool_addr_range(self.vrf1_nat_addr_n,
7202 self.vrf1_nat_addr_n,
7203 vrf_id=self.vrf1_id)
7204 self.vapi.nat64_add_del_interface(self.pg2.sw_if_index)
7205
7206 # Add global prefix
7207 global_pref64 = "2001:db8::"
7208 global_pref64_n = socket.inet_pton(socket.AF_INET6, global_pref64)
7209 global_pref64_len = 32
7210 self.vapi.nat64_add_del_prefix(global_pref64_n, global_pref64_len)
7211
7212 prefix = self.vapi.nat64_prefix_dump()
7213 self.assertEqual(len(prefix), 1)
7214 self.assertEqual(prefix[0].prefix, global_pref64_n)
7215 self.assertEqual(prefix[0].prefix_len, global_pref64_len)
7216 self.assertEqual(prefix[0].vrf_id, 0)
7217
7218 # Add tenant specific prefix
7219 vrf1_pref64 = "2001:db8:122:300::"
7220 vrf1_pref64_n = socket.inet_pton(socket.AF_INET6, vrf1_pref64)
7221 vrf1_pref64_len = 56
7222 self.vapi.nat64_add_del_prefix(vrf1_pref64_n,
7223 vrf1_pref64_len,
7224 vrf_id=self.vrf1_id)
7225 prefix = self.vapi.nat64_prefix_dump()
7226 self.assertEqual(len(prefix), 2)
7227
7228 # Global prefix
7229 pkts = self.create_stream_in_ip6(self.pg0,
7230 self.pg1,
7231 pref=global_pref64,
7232 plen=global_pref64_len)
7233 self.pg0.add_stream(pkts)
7234 self.pg_enable_capture(self.pg_interfaces)
7235 self.pg_start()
7236 capture = self.pg1.get_capture(len(pkts))
7237 self.verify_capture_out(capture, nat_ip=self.nat_addr,
7238 dst_ip=self.pg1.remote_ip4)
7239
7240 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
7241 self.pg1.add_stream(pkts)
7242 self.pg_enable_capture(self.pg_interfaces)
7243 self.pg_start()
7244 capture = self.pg0.get_capture(len(pkts))
7245 dst_ip = self.compose_ip6(self.pg1.remote_ip4,
7246 global_pref64,
7247 global_pref64_len)
7248 self.verify_capture_in_ip6(capture, dst_ip, self.pg0.remote_ip6)
7249
7250 # Tenant specific prefix
7251 pkts = self.create_stream_in_ip6(self.pg2,
7252 self.pg1,
7253 pref=vrf1_pref64,
7254 plen=vrf1_pref64_len)
7255 self.pg2.add_stream(pkts)
7256 self.pg_enable_capture(self.pg_interfaces)
7257 self.pg_start()
7258 capture = self.pg1.get_capture(len(pkts))
7259 self.verify_capture_out(capture, nat_ip=self.vrf1_nat_addr,
7260 dst_ip=self.pg1.remote_ip4)
7261
7262 pkts = self.create_stream_out(self.pg1, dst_ip=self.vrf1_nat_addr)
7263 self.pg1.add_stream(pkts)
7264 self.pg_enable_capture(self.pg_interfaces)
7265 self.pg_start()
7266 capture = self.pg2.get_capture(len(pkts))
7267 dst_ip = self.compose_ip6(self.pg1.remote_ip4,
7268 vrf1_pref64,
7269 vrf1_pref64_len)
7270 self.verify_capture_in_ip6(capture, dst_ip, self.pg2.remote_ip6)
7271
Matus Fabianf8cd5812017-07-11 03:55:02 -07007272 def test_unknown_proto(self):
Matus Fabian7968e6c2017-07-06 05:37:49 -07007273 """ NAT64 translate packet with unknown protocol """
7274
7275 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7276 self.nat_addr_n)
7277 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7278 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7279 remote_ip6 = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
7280
7281 # in2out
7282 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7283 IPv6(src=self.pg0.remote_ip6, dst=remote_ip6) /
7284 TCP(sport=self.tcp_port_in, dport=20))
7285 self.pg0.add_stream(p)
7286 self.pg_enable_capture(self.pg_interfaces)
7287 self.pg_start()
7288 p = self.pg1.get_capture(1)
7289
7290 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabianf8cd5812017-07-11 03:55:02 -07007291 IPv6(src=self.pg0.remote_ip6, dst=remote_ip6, nh=47) /
Matus Fabian7968e6c2017-07-06 05:37:49 -07007292 GRE() /
7293 IP(src=self.pg2.local_ip4, dst=self.pg2.remote_ip4) /
7294 TCP(sport=1234, dport=1234))
7295 self.pg0.add_stream(p)
7296 self.pg_enable_capture(self.pg_interfaces)
7297 self.pg_start()
7298 p = self.pg1.get_capture(1)
7299 packet = p[0]
7300 try:
7301 self.assertEqual(packet[IP].src, self.nat_addr)
7302 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
7303 self.assertTrue(packet.haslayer(GRE))
Klement Sekerad81ae412018-05-16 10:52:54 +02007304 self.assert_packet_checksums_valid(packet)
Matus Fabian7968e6c2017-07-06 05:37:49 -07007305 except:
7306 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7307 raise
7308
7309 # out2in
7310 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
7311 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
7312 GRE() /
7313 IP(src=self.pg2.remote_ip4, dst=self.pg2.local_ip4) /
7314 TCP(sport=1234, dport=1234))
7315 self.pg1.add_stream(p)
7316 self.pg_enable_capture(self.pg_interfaces)
7317 self.pg_start()
7318 p = self.pg0.get_capture(1)
7319 packet = p[0]
7320 try:
7321 self.assertEqual(packet[IPv6].src, remote_ip6)
Matus Fabianf8cd5812017-07-11 03:55:02 -07007322 self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
7323 self.assertEqual(packet[IPv6].nh, 47)
Matus Fabian7968e6c2017-07-06 05:37:49 -07007324 except:
7325 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7326 raise
7327
Matus Fabianf8cd5812017-07-11 03:55:02 -07007328 def test_hairpinning_unknown_proto(self):
Matus Fabian7968e6c2017-07-06 05:37:49 -07007329 """ NAT64 translate packet with unknown protocol - hairpinning """
7330
7331 client = self.pg0.remote_hosts[0]
7332 server = self.pg0.remote_hosts[1]
7333 server_tcp_in_port = 22
7334 server_tcp_out_port = 4022
7335 client_tcp_in_port = 1234
Matus Fabianf8cd5812017-07-11 03:55:02 -07007336 client_tcp_out_port = 1235
7337 server_nat_ip = "10.0.0.100"
7338 client_nat_ip = "10.0.0.110"
7339 server_nat_ip_n = socket.inet_pton(socket.AF_INET, server_nat_ip)
7340 client_nat_ip_n = socket.inet_pton(socket.AF_INET, client_nat_ip)
7341 server_nat_ip6 = self.compose_ip6(server_nat_ip, '64:ff9b::', 96)
7342 client_nat_ip6 = self.compose_ip6(client_nat_ip, '64:ff9b::', 96)
Matus Fabian7968e6c2017-07-06 05:37:49 -07007343
Matus Fabianf8cd5812017-07-11 03:55:02 -07007344 self.vapi.nat64_add_del_pool_addr_range(server_nat_ip_n,
7345 client_nat_ip_n)
Matus Fabian7968e6c2017-07-06 05:37:49 -07007346 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7347 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7348
7349 self.vapi.nat64_add_del_static_bib(server.ip6n,
Matus Fabianf8cd5812017-07-11 03:55:02 -07007350 server_nat_ip_n,
Matus Fabian7968e6c2017-07-06 05:37:49 -07007351 server_tcp_in_port,
7352 server_tcp_out_port,
7353 IP_PROTOS.tcp)
7354
Matus Fabianf8cd5812017-07-11 03:55:02 -07007355 self.vapi.nat64_add_del_static_bib(server.ip6n,
7356 server_nat_ip_n,
7357 0,
7358 0,
7359 IP_PROTOS.gre)
7360
7361 self.vapi.nat64_add_del_static_bib(client.ip6n,
7362 client_nat_ip_n,
7363 client_tcp_in_port,
7364 client_tcp_out_port,
7365 IP_PROTOS.tcp)
7366
Matus Fabian7968e6c2017-07-06 05:37:49 -07007367 # client to server
7368 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabianf8cd5812017-07-11 03:55:02 -07007369 IPv6(src=client.ip6, dst=server_nat_ip6) /
Matus Fabian7968e6c2017-07-06 05:37:49 -07007370 TCP(sport=client_tcp_in_port, dport=server_tcp_out_port))
7371 self.pg0.add_stream(p)
7372 self.pg_enable_capture(self.pg_interfaces)
7373 self.pg_start()
7374 p = self.pg0.get_capture(1)
7375
7376 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabianf8cd5812017-07-11 03:55:02 -07007377 IPv6(src=client.ip6, dst=server_nat_ip6, nh=IP_PROTOS.gre) /
Matus Fabian7968e6c2017-07-06 05:37:49 -07007378 GRE() /
7379 IP(src=self.pg2.local_ip4, dst=self.pg2.remote_ip4) /
7380 TCP(sport=1234, dport=1234))
7381 self.pg0.add_stream(p)
7382 self.pg_enable_capture(self.pg_interfaces)
7383 self.pg_start()
7384 p = self.pg0.get_capture(1)
7385 packet = p[0]
7386 try:
Matus Fabianf8cd5812017-07-11 03:55:02 -07007387 self.assertEqual(packet[IPv6].src, client_nat_ip6)
Matus Fabian7968e6c2017-07-06 05:37:49 -07007388 self.assertEqual(packet[IPv6].dst, server.ip6)
Matus Fabianf8cd5812017-07-11 03:55:02 -07007389 self.assertEqual(packet[IPv6].nh, IP_PROTOS.gre)
Matus Fabian7968e6c2017-07-06 05:37:49 -07007390 except:
7391 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7392 raise
7393
7394 # server to client
7395 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabianf8cd5812017-07-11 03:55:02 -07007396 IPv6(src=server.ip6, dst=client_nat_ip6, nh=IP_PROTOS.gre) /
Matus Fabian7968e6c2017-07-06 05:37:49 -07007397 GRE() /
7398 IP(src=self.pg2.remote_ip4, dst=self.pg2.local_ip4) /
7399 TCP(sport=1234, dport=1234))
7400 self.pg0.add_stream(p)
7401 self.pg_enable_capture(self.pg_interfaces)
7402 self.pg_start()
7403 p = self.pg0.get_capture(1)
7404 packet = p[0]
7405 try:
Matus Fabianf8cd5812017-07-11 03:55:02 -07007406 self.assertEqual(packet[IPv6].src, server_nat_ip6)
Matus Fabian7968e6c2017-07-06 05:37:49 -07007407 self.assertEqual(packet[IPv6].dst, client.ip6)
Matus Fabianf8cd5812017-07-11 03:55:02 -07007408 self.assertEqual(packet[IPv6].nh, IP_PROTOS.gre)
Matus Fabian7968e6c2017-07-06 05:37:49 -07007409 except:
7410 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7411 raise
7412
Matus Fabian36ea2d62017-10-24 04:13:49 -07007413 def test_one_armed_nat64(self):
7414 """ One armed NAT64 """
7415 external_port = 0
7416 remote_host_ip6 = self.compose_ip6(self.pg3.remote_ip4,
7417 '64:ff9b::',
7418 96)
7419
7420 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7421 self.nat_addr_n)
7422 self.vapi.nat64_add_del_interface(self.pg3.sw_if_index)
7423 self.vapi.nat64_add_del_interface(self.pg3.sw_if_index, is_inside=0)
7424
7425 # in2out
7426 p = (Ether(src=self.pg3.remote_mac, dst=self.pg3.local_mac) /
7427 IPv6(src=self.pg3.remote_ip6, dst=remote_host_ip6) /
7428 TCP(sport=12345, dport=80))
7429 self.pg3.add_stream(p)
7430 self.pg_enable_capture(self.pg_interfaces)
7431 self.pg_start()
7432 capture = self.pg3.get_capture(1)
7433 p = capture[0]
7434 try:
7435 ip = p[IP]
7436 tcp = p[TCP]
7437 self.assertEqual(ip.src, self.nat_addr)
7438 self.assertEqual(ip.dst, self.pg3.remote_ip4)
7439 self.assertNotEqual(tcp.sport, 12345)
7440 external_port = tcp.sport
7441 self.assertEqual(tcp.dport, 80)
Klement Sekerad81ae412018-05-16 10:52:54 +02007442 self.assert_packet_checksums_valid(p)
Matus Fabian36ea2d62017-10-24 04:13:49 -07007443 except:
7444 self.logger.error(ppp("Unexpected or invalid packet:", p))
7445 raise
7446
7447 # out2in
7448 p = (Ether(src=self.pg3.remote_mac, dst=self.pg3.local_mac) /
7449 IP(src=self.pg3.remote_ip4, dst=self.nat_addr) /
7450 TCP(sport=80, dport=external_port))
7451 self.pg3.add_stream(p)
7452 self.pg_enable_capture(self.pg_interfaces)
7453 self.pg_start()
7454 capture = self.pg3.get_capture(1)
7455 p = capture[0]
7456 try:
7457 ip = p[IPv6]
7458 tcp = p[TCP]
7459 self.assertEqual(ip.src, remote_host_ip6)
7460 self.assertEqual(ip.dst, self.pg3.remote_ip6)
7461 self.assertEqual(tcp.sport, 80)
7462 self.assertEqual(tcp.dport, 12345)
Klement Sekerad81ae412018-05-16 10:52:54 +02007463 self.assert_packet_checksums_valid(p)
Matus Fabian36ea2d62017-10-24 04:13:49 -07007464 except:
7465 self.logger.error(ppp("Unexpected or invalid packet:", p))
7466 raise
7467
Matus Fabianefcd1e92017-08-15 06:59:19 -07007468 def test_frag_in_order(self):
7469 """ NAT64 translate fragments arriving in order """
7470 self.tcp_port_in = random.randint(1025, 65535)
7471
7472 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7473 self.nat_addr_n)
7474 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7475 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7476
7477 reass = self.vapi.nat_reass_dump()
7478 reass_n_start = len(reass)
7479
7480 # in2out
7481 data = 'a' * 200
7482 pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
7483 self.tcp_port_in, 20, data)
7484 self.pg0.add_stream(pkts)
7485 self.pg_enable_capture(self.pg_interfaces)
7486 self.pg_start()
7487 frags = self.pg1.get_capture(len(pkts))
7488 p = self.reass_frags_and_verify(frags,
7489 self.nat_addr,
7490 self.pg1.remote_ip4)
7491 self.assertEqual(p[TCP].dport, 20)
7492 self.assertNotEqual(p[TCP].sport, self.tcp_port_in)
7493 self.tcp_port_out = p[TCP].sport
7494 self.assertEqual(data, p[Raw].load)
7495
7496 # out2in
7497 data = "A" * 4 + "b" * 16 + "C" * 3
7498 pkts = self.create_stream_frag(self.pg1,
7499 self.nat_addr,
7500 20,
7501 self.tcp_port_out,
7502 data)
7503 self.pg1.add_stream(pkts)
7504 self.pg_enable_capture(self.pg_interfaces)
7505 self.pg_start()
7506 frags = self.pg0.get_capture(len(pkts))
7507 src = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
7508 p = self.reass_frags_and_verify_ip6(frags, src, self.pg0.remote_ip6)
7509 self.assertEqual(p[TCP].sport, 20)
7510 self.assertEqual(p[TCP].dport, self.tcp_port_in)
7511 self.assertEqual(data, p[Raw].load)
7512
7513 reass = self.vapi.nat_reass_dump()
7514 reass_n_end = len(reass)
7515
7516 self.assertEqual(reass_n_end - reass_n_start, 2)
7517
7518 def test_reass_hairpinning(self):
7519 """ NAT64 fragments hairpinning """
7520 data = 'a' * 200
Matus Fabianefcd1e92017-08-15 06:59:19 -07007521 server = self.pg0.remote_hosts[1]
7522 server_in_port = random.randint(1025, 65535)
7523 server_out_port = random.randint(1025, 65535)
7524 client_in_port = random.randint(1025, 65535)
7525 ip = IPv6(src=''.join(['64:ff9b::', self.nat_addr]))
7526 nat_addr_ip6 = ip.src
7527
7528 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7529 self.nat_addr_n)
7530 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7531 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7532
7533 # add static BIB entry for server
7534 self.vapi.nat64_add_del_static_bib(server.ip6n,
7535 self.nat_addr_n,
7536 server_in_port,
7537 server_out_port,
7538 IP_PROTOS.tcp)
7539
7540 # send packet from host to server
7541 pkts = self.create_stream_frag_ip6(self.pg0,
7542 self.nat_addr,
7543 client_in_port,
7544 server_out_port,
7545 data)
7546 self.pg0.add_stream(pkts)
7547 self.pg_enable_capture(self.pg_interfaces)
7548 self.pg_start()
7549 frags = self.pg0.get_capture(len(pkts))
7550 p = self.reass_frags_and_verify_ip6(frags, nat_addr_ip6, server.ip6)
7551 self.assertNotEqual(p[TCP].sport, client_in_port)
7552 self.assertEqual(p[TCP].dport, server_in_port)
7553 self.assertEqual(data, p[Raw].load)
7554
7555 def test_frag_out_of_order(self):
7556 """ NAT64 translate fragments arriving out of order """
7557 self.tcp_port_in = random.randint(1025, 65535)
7558
7559 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7560 self.nat_addr_n)
7561 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7562 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7563
7564 # in2out
7565 data = 'a' * 200
7566 pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
7567 self.tcp_port_in, 20, data)
7568 pkts.reverse()
7569 self.pg0.add_stream(pkts)
7570 self.pg_enable_capture(self.pg_interfaces)
7571 self.pg_start()
7572 frags = self.pg1.get_capture(len(pkts))
7573 p = self.reass_frags_and_verify(frags,
7574 self.nat_addr,
7575 self.pg1.remote_ip4)
7576 self.assertEqual(p[TCP].dport, 20)
7577 self.assertNotEqual(p[TCP].sport, self.tcp_port_in)
7578 self.tcp_port_out = p[TCP].sport
7579 self.assertEqual(data, p[Raw].load)
7580
7581 # out2in
7582 data = "A" * 4 + "B" * 16 + "C" * 3
7583 pkts = self.create_stream_frag(self.pg1,
7584 self.nat_addr,
7585 20,
7586 self.tcp_port_out,
7587 data)
7588 pkts.reverse()
7589 self.pg1.add_stream(pkts)
7590 self.pg_enable_capture(self.pg_interfaces)
7591 self.pg_start()
7592 frags = self.pg0.get_capture(len(pkts))
7593 src = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
7594 p = self.reass_frags_and_verify_ip6(frags, src, self.pg0.remote_ip6)
7595 self.assertEqual(p[TCP].sport, 20)
7596 self.assertEqual(p[TCP].dport, self.tcp_port_in)
7597 self.assertEqual(data, p[Raw].load)
7598
Matus Fabian0938dcf2017-11-08 01:59:38 -08007599 def test_interface_addr(self):
7600 """ Acquire NAT64 pool addresses from interface """
7601 self.vapi.nat64_add_interface_addr(self.pg4.sw_if_index)
7602
7603 # no address in NAT64 pool
7604 adresses = self.vapi.nat44_address_dump()
7605 self.assertEqual(0, len(adresses))
7606
7607 # configure interface address and check NAT64 address pool
7608 self.pg4.config_ip4()
7609 addresses = self.vapi.nat64_pool_addr_dump()
7610 self.assertEqual(len(addresses), 1)
7611 self.assertEqual(addresses[0].address, self.pg4.local_ip4n)
7612
7613 # remove interface address and check NAT64 address pool
7614 self.pg4.unconfig_ip4()
7615 addresses = self.vapi.nat64_pool_addr_dump()
7616 self.assertEqual(0, len(adresses))
7617
Matus Fabiana431ad12018-01-04 04:03:14 -08007618 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
7619 def test_ipfix_max_bibs_sessions(self):
7620 """ IPFIX logging maximum session and BIB entries exceeded """
7621 max_bibs = 1280
7622 max_sessions = 2560
7623 remote_host_ip6 = self.compose_ip6(self.pg1.remote_ip4,
7624 '64:ff9b::',
7625 96)
7626
7627 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7628 self.nat_addr_n)
7629 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7630 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7631
7632 pkts = []
7633 src = ""
7634 for i in range(0, max_bibs):
7635 src = "fd01:aa::%x" % (i)
7636 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7637 IPv6(src=src, dst=remote_host_ip6) /
7638 TCP(sport=12345, dport=80))
7639 pkts.append(p)
7640 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7641 IPv6(src=src, dst=remote_host_ip6) /
7642 TCP(sport=12345, dport=22))
7643 pkts.append(p)
7644 self.pg0.add_stream(pkts)
7645 self.pg_enable_capture(self.pg_interfaces)
7646 self.pg_start()
7647 self.pg1.get_capture(max_sessions)
7648
7649 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
7650 src_address=self.pg3.local_ip4n,
7651 path_mtu=512,
7652 template_interval=10)
7653 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
7654 src_port=self.ipfix_src_port)
7655
7656 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7657 IPv6(src=src, dst=remote_host_ip6) /
7658 TCP(sport=12345, dport=25))
7659 self.pg0.add_stream(p)
7660 self.pg_enable_capture(self.pg_interfaces)
7661 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07007662 self.pg1.assert_nothing_captured()
7663 sleep(1)
Matus Fabiana431ad12018-01-04 04:03:14 -08007664 self.vapi.cli("ipfix flush") # FIXME this should be an API call
7665 capture = self.pg3.get_capture(9)
7666 ipfix = IPFIXDecoder()
7667 # first load template
7668 for p in capture:
7669 self.assertTrue(p.haslayer(IPFIX))
7670 self.assertEqual(p[IP].src, self.pg3.local_ip4)
7671 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
7672 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
7673 self.assertEqual(p[UDP].dport, 4739)
7674 self.assertEqual(p[IPFIX].observationDomainID,
7675 self.ipfix_domain_id)
7676 if p.haslayer(Template):
7677 ipfix.add_template(p.getlayer(Template))
7678 # verify events in data set
7679 for p in capture:
7680 if p.haslayer(Data):
7681 data = ipfix.decode_data_set(p.getlayer(Set))
7682 self.verify_ipfix_max_sessions(data, max_sessions)
7683
7684 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7685 IPv6(src=self.pg0.remote_ip6, dst=remote_host_ip6) /
7686 TCP(sport=12345, dport=80))
7687 self.pg0.add_stream(p)
7688 self.pg_enable_capture(self.pg_interfaces)
7689 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07007690 self.pg1.assert_nothing_captured()
7691 sleep(1)
Matus Fabiana431ad12018-01-04 04:03:14 -08007692 self.vapi.cli("ipfix flush") # FIXME this should be an API call
7693 capture = self.pg3.get_capture(1)
7694 # verify events in data set
7695 for p in capture:
7696 self.assertTrue(p.haslayer(IPFIX))
7697 self.assertEqual(p[IP].src, self.pg3.local_ip4)
7698 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
7699 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
7700 self.assertEqual(p[UDP].dport, 4739)
7701 self.assertEqual(p[IPFIX].observationDomainID,
7702 self.ipfix_domain_id)
7703 if p.haslayer(Data):
7704 data = ipfix.decode_data_set(p.getlayer(Set))
7705 self.verify_ipfix_max_bibs(data, max_bibs)
7706
7707 def test_ipfix_max_frags(self):
7708 """ IPFIX logging maximum fragments pending reassembly exceeded """
7709 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7710 self.nat_addr_n)
7711 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7712 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
Matus Fabiana7f8b222018-09-05 06:01:55 -07007713 self.vapi.nat_set_reass(max_frag=1, is_ip6=1)
Matus Fabiana431ad12018-01-04 04:03:14 -08007714 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
7715 src_address=self.pg3.local_ip4n,
7716 path_mtu=512,
7717 template_interval=10)
7718 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
7719 src_port=self.ipfix_src_port)
7720
7721 data = 'a' * 200
7722 pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
7723 self.tcp_port_in, 20, data)
Matus Fabiana7f8b222018-09-05 06:01:55 -07007724 pkts.reverse()
7725 self.pg0.add_stream(pkts)
Matus Fabiana431ad12018-01-04 04:03:14 -08007726 self.pg_enable_capture(self.pg_interfaces)
7727 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07007728 self.pg1.assert_nothing_captured()
7729 sleep(1)
Matus Fabiana431ad12018-01-04 04:03:14 -08007730 self.vapi.cli("ipfix flush") # FIXME this should be an API call
7731 capture = self.pg3.get_capture(9)
7732 ipfix = IPFIXDecoder()
7733 # first load template
7734 for p in capture:
7735 self.assertTrue(p.haslayer(IPFIX))
7736 self.assertEqual(p[IP].src, self.pg3.local_ip4)
7737 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
7738 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
7739 self.assertEqual(p[UDP].dport, 4739)
7740 self.assertEqual(p[IPFIX].observationDomainID,
7741 self.ipfix_domain_id)
7742 if p.haslayer(Template):
7743 ipfix.add_template(p.getlayer(Template))
7744 # verify events in data set
7745 for p in capture:
7746 if p.haslayer(Data):
7747 data = ipfix.decode_data_set(p.getlayer(Set))
Matus Fabiana7f8b222018-09-05 06:01:55 -07007748 self.verify_ipfix_max_fragments_ip6(data, 1,
Matus Fabiana431ad12018-01-04 04:03:14 -08007749 self.pg0.remote_ip6n)
7750
7751 def test_ipfix_bib_ses(self):
7752 """ IPFIX logging NAT64 BIB/session create and delete events """
7753 self.tcp_port_in = random.randint(1025, 65535)
7754 remote_host_ip6 = self.compose_ip6(self.pg1.remote_ip4,
7755 '64:ff9b::',
7756 96)
7757
7758 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7759 self.nat_addr_n)
7760 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7761 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7762 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
7763 src_address=self.pg3.local_ip4n,
7764 path_mtu=512,
7765 template_interval=10)
7766 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
7767 src_port=self.ipfix_src_port)
7768
7769 # Create
7770 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7771 IPv6(src=self.pg0.remote_ip6, dst=remote_host_ip6) /
7772 TCP(sport=self.tcp_port_in, dport=25))
7773 self.pg0.add_stream(p)
7774 self.pg_enable_capture(self.pg_interfaces)
7775 self.pg_start()
7776 p = self.pg1.get_capture(1)
7777 self.tcp_port_out = p[0][TCP].sport
7778 self.vapi.cli("ipfix flush") # FIXME this should be an API call
7779 capture = self.pg3.get_capture(10)
7780 ipfix = IPFIXDecoder()
7781 # first load template
7782 for p in capture:
7783 self.assertTrue(p.haslayer(IPFIX))
7784 self.assertEqual(p[IP].src, self.pg3.local_ip4)
7785 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
7786 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
7787 self.assertEqual(p[UDP].dport, 4739)
7788 self.assertEqual(p[IPFIX].observationDomainID,
7789 self.ipfix_domain_id)
7790 if p.haslayer(Template):
7791 ipfix.add_template(p.getlayer(Template))
7792 # verify events in data set
7793 for p in capture:
7794 if p.haslayer(Data):
7795 data = ipfix.decode_data_set(p.getlayer(Set))
7796 if ord(data[0][230]) == 10:
7797 self.verify_ipfix_bib(data, 1, self.pg0.remote_ip6n)
7798 elif ord(data[0][230]) == 6:
7799 self.verify_ipfix_nat64_ses(data,
7800 1,
7801 self.pg0.remote_ip6n,
7802 self.pg1.remote_ip4,
7803 25)
7804 else:
7805 self.logger.error(ppp("Unexpected or invalid packet: ", p))
7806
7807 # Delete
7808 self.pg_enable_capture(self.pg_interfaces)
7809 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7810 self.nat_addr_n,
7811 is_add=0)
7812 self.vapi.cli("ipfix flush") # FIXME this should be an API call
7813 capture = self.pg3.get_capture(2)
7814 # verify events in data set
7815 for p in capture:
7816 self.assertTrue(p.haslayer(IPFIX))
7817 self.assertEqual(p[IP].src, self.pg3.local_ip4)
7818 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
7819 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
7820 self.assertEqual(p[UDP].dport, 4739)
7821 self.assertEqual(p[IPFIX].observationDomainID,
7822 self.ipfix_domain_id)
7823 if p.haslayer(Data):
7824 data = ipfix.decode_data_set(p.getlayer(Set))
7825 if ord(data[0][230]) == 11:
7826 self.verify_ipfix_bib(data, 0, self.pg0.remote_ip6n)
7827 elif ord(data[0][230]) == 7:
7828 self.verify_ipfix_nat64_ses(data,
7829 0,
7830 self.pg0.remote_ip6n,
7831 self.pg1.remote_ip4,
7832 25)
7833 else:
7834 self.logger.error(ppp("Unexpected or invalid packet: ", p))
7835
Matus Fabianad1f3e12018-11-28 21:26:34 -08007836 def test_syslog_sess(self):
7837 """ Test syslog session creation and deletion """
7838 self.tcp_port_in = random.randint(1025, 65535)
7839 remote_host_ip6 = self.compose_ip6(self.pg1.remote_ip4,
7840 '64:ff9b::',
7841 96)
7842
7843 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7844 self.nat_addr_n)
7845 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7846 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7847 self.vapi.syslog_set_filter(SYSLOG_SEVERITY.INFO)
7848 self.vapi.syslog_set_sender(self.pg3.remote_ip4n, self.pg3.local_ip4n)
7849
7850 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7851 IPv6(src=self.pg0.remote_ip6, dst=remote_host_ip6) /
7852 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port))
7853 self.pg0.add_stream(p)
7854 self.pg_enable_capture(self.pg_interfaces)
7855 self.pg_start()
7856 p = self.pg1.get_capture(1)
7857 self.tcp_port_out = p[0][TCP].sport
7858 capture = self.pg3.get_capture(1)
7859 self.verify_syslog_sess(capture[0][Raw].load, is_ip6=True)
7860
7861 self.pg_enable_capture(self.pg_interfaces)
7862 self.pg_start()
7863 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7864 self.nat_addr_n,
7865 is_add=0)
7866 capture = self.pg3.get_capture(1)
7867 self.verify_syslog_sess(capture[0][Raw].load, False, True)
7868
Matus Fabian06596c52017-06-06 04:53:28 -07007869 def nat64_get_ses_num(self):
7870 """
7871 Return number of active NAT64 sessions.
7872 """
Matus Fabianab9a59c2017-08-16 05:37:36 -07007873 st = self.vapi.nat64_st_dump()
7874 return len(st)
Matus Fabian06596c52017-06-06 04:53:28 -07007875
7876 def clear_nat64(self):
7877 """
7878 Clear NAT64 configuration.
7879 """
Matus Fabiana431ad12018-01-04 04:03:14 -08007880 self.vapi.nat_ipfix(enable=0, src_port=self.ipfix_src_port,
7881 domain_id=self.ipfix_domain_id)
7882 self.ipfix_src_port = 4739
7883 self.ipfix_domain_id = 1
7884
Matus Fabianad1f3e12018-11-28 21:26:34 -08007885 self.vapi.syslog_set_filter(SYSLOG_SEVERITY.EMERG)
7886
Matus Fabian878c6462018-08-23 00:33:35 -07007887 self.vapi.nat_set_timeouts()
Matus Fabian06596c52017-06-06 04:53:28 -07007888
7889 interfaces = self.vapi.nat64_interface_dump()
7890 for intf in interfaces:
Matus Fabian36ea2d62017-10-24 04:13:49 -07007891 if intf.is_inside > 1:
7892 self.vapi.nat64_add_del_interface(intf.sw_if_index,
7893 0,
7894 is_add=0)
Matus Fabian06596c52017-06-06 04:53:28 -07007895 self.vapi.nat64_add_del_interface(intf.sw_if_index,
7896 intf.is_inside,
7897 is_add=0)
7898
Matus Fabiana431ad12018-01-04 04:03:14 -08007899 bib = self.vapi.nat64_bib_dump(255)
Matus Fabian06596c52017-06-06 04:53:28 -07007900 for bibe in bib:
7901 if bibe.is_static:
7902 self.vapi.nat64_add_del_static_bib(bibe.i_addr,
7903 bibe.o_addr,
7904 bibe.i_port,
7905 bibe.o_port,
7906 bibe.proto,
7907 bibe.vrf_id,
7908 is_add=0)
7909
7910 adresses = self.vapi.nat64_pool_addr_dump()
7911 for addr in adresses:
7912 self.vapi.nat64_add_del_pool_addr_range(addr.address,
7913 addr.address,
Matus Fabian029f3d22017-06-15 02:28:50 -07007914 vrf_id=addr.vrf_id,
Matus Fabian06596c52017-06-06 04:53:28 -07007915 is_add=0)
7916
Matus Fabian428dc912017-06-21 06:15:18 -07007917 prefixes = self.vapi.nat64_prefix_dump()
7918 for prefix in prefixes:
7919 self.vapi.nat64_add_del_prefix(prefix.prefix,
7920 prefix.prefix_len,
7921 vrf_id=prefix.vrf_id,
7922 is_add=0)
7923
Matus Fabian06596c52017-06-06 04:53:28 -07007924 def tearDown(self):
7925 super(TestNAT64, self).tearDown()
7926 if not self.vpp_dead:
7927 self.logger.info(self.vapi.cli("show nat64 pool"))
7928 self.logger.info(self.vapi.cli("show nat64 interfaces"))
Matus Fabian428dc912017-06-21 06:15:18 -07007929 self.logger.info(self.vapi.cli("show nat64 prefix"))
Matus Fabianab9a59c2017-08-16 05:37:36 -07007930 self.logger.info(self.vapi.cli("show nat64 bib all"))
7931 self.logger.info(self.vapi.cli("show nat64 session table all"))
Matus Fabianefcd1e92017-08-15 06:59:19 -07007932 self.logger.info(self.vapi.cli("show nat virtual-reassembly"))
Matus Fabian06596c52017-06-06 04:53:28 -07007933 self.clear_nat64()
7934
Matus Fabian8ebe6252017-11-06 05:04:53 -08007935
7936class TestDSlite(MethodHolder):
7937 """ DS-Lite Test Cases """
7938
7939 @classmethod
7940 def setUpClass(cls):
7941 super(TestDSlite, cls).setUpClass()
7942
7943 try:
7944 cls.nat_addr = '10.0.0.3'
7945 cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
7946
Matus Fabianad1f3e12018-11-28 21:26:34 -08007947 cls.create_pg_interfaces(range(3))
Matus Fabian8ebe6252017-11-06 05:04:53 -08007948 cls.pg0.admin_up()
7949 cls.pg0.config_ip4()
7950 cls.pg0.resolve_arp()
7951 cls.pg1.admin_up()
7952 cls.pg1.config_ip6()
7953 cls.pg1.generate_remote_hosts(2)
7954 cls.pg1.configure_ipv6_neighbors()
Matus Fabianad1f3e12018-11-28 21:26:34 -08007955 cls.pg2.admin_up()
7956 cls.pg2.config_ip4()
7957 cls.pg2.resolve_arp()
Matus Fabian8ebe6252017-11-06 05:04:53 -08007958
7959 except Exception:
7960 super(TestDSlite, cls).tearDownClass()
7961 raise
7962
Matus Fabianad1f3e12018-11-28 21:26:34 -08007963 def verify_syslog_apmadd(self, data, isaddr, isport, xsaddr, xsport,
7964 sv6enc, proto):
7965 message = data.decode('utf-8')
7966 try:
7967 message = SyslogMessage.parse(message)
7968 self.assertEqual(message.severity, SyslogSeverity.info)
7969 self.assertEqual(message.appname, 'NAT')
7970 self.assertEqual(message.msgid, 'APMADD')
7971 sd_params = message.sd.get('napmap')
7972 self.assertTrue(sd_params is not None)
7973 self.assertEqual(sd_params.get('IATYP'), 'IPv4')
7974 self.assertEqual(sd_params.get('ISADDR'), isaddr)
7975 self.assertEqual(sd_params.get('ISPORT'), "%d" % isport)
7976 self.assertEqual(sd_params.get('XATYP'), 'IPv4')
7977 self.assertEqual(sd_params.get('XSADDR'), xsaddr)
7978 self.assertEqual(sd_params.get('XSPORT'), "%d" % xsport)
7979 self.assertEqual(sd_params.get('PROTO'), "%d" % proto)
7980 self.assertTrue(sd_params.get('SSUBIX') is not None)
7981 self.assertEqual(sd_params.get('SV6ENC'), sv6enc)
7982 except ParseError as e:
7983 self.logger.error(e)
7984
Matus Fabian8ebe6252017-11-06 05:04:53 -08007985 def test_dslite(self):
7986 """ Test DS-Lite """
Matus Fabian69ce30d2018-08-22 01:27:10 -07007987 nat_config = self.vapi.nat_show_config()
7988 self.assertEqual(0, nat_config.dslite_ce)
7989
Matus Fabian8ebe6252017-11-06 05:04:53 -08007990 self.vapi.dslite_add_del_pool_addr_range(self.nat_addr_n,
7991 self.nat_addr_n)
7992 aftr_ip4 = '192.0.0.1'
7993 aftr_ip4_n = socket.inet_pton(socket.AF_INET, aftr_ip4)
7994 aftr_ip6 = '2001:db8:85a3::8a2e:370:1'
7995 aftr_ip6_n = socket.inet_pton(socket.AF_INET6, aftr_ip6)
7996 self.vapi.dslite_set_aftr_addr(aftr_ip6_n, aftr_ip4_n)
Matus Fabianad1f3e12018-11-28 21:26:34 -08007997 self.vapi.syslog_set_sender(self.pg2.remote_ip4n, self.pg2.local_ip4n)
Matus Fabian8ebe6252017-11-06 05:04:53 -08007998
7999 # UDP
8000 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8001 IPv6(dst=aftr_ip6, src=self.pg1.remote_hosts[0].ip6) /
8002 IP(dst=self.pg0.remote_ip4, src='192.168.1.1') /
8003 UDP(sport=20000, dport=10000))
8004 self.pg1.add_stream(p)
8005 self.pg_enable_capture(self.pg_interfaces)
8006 self.pg_start()
8007 capture = self.pg0.get_capture(1)
8008 capture = capture[0]
8009 self.assertFalse(capture.haslayer(IPv6))
8010 self.assertEqual(capture[IP].src, self.nat_addr)
8011 self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
8012 self.assertNotEqual(capture[UDP].sport, 20000)
8013 self.assertEqual(capture[UDP].dport, 10000)
Klement Sekerad81ae412018-05-16 10:52:54 +02008014 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08008015 out_port = capture[UDP].sport
Matus Fabianad1f3e12018-11-28 21:26:34 -08008016 capture = self.pg2.get_capture(1)
8017 self.verify_syslog_apmadd(capture[0][Raw].load, '192.168.1.1',
8018 20000, self.nat_addr, out_port,
8019 self.pg1.remote_hosts[0].ip6, IP_PROTOS.udp)
Matus Fabian8ebe6252017-11-06 05:04:53 -08008020
8021 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8022 IP(dst=self.nat_addr, src=self.pg0.remote_ip4) /
8023 UDP(sport=10000, dport=out_port))
8024 self.pg0.add_stream(p)
8025 self.pg_enable_capture(self.pg_interfaces)
8026 self.pg_start()
8027 capture = self.pg1.get_capture(1)
8028 capture = capture[0]
8029 self.assertEqual(capture[IPv6].src, aftr_ip6)
8030 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[0].ip6)
8031 self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
8032 self.assertEqual(capture[IP].dst, '192.168.1.1')
8033 self.assertEqual(capture[UDP].sport, 10000)
8034 self.assertEqual(capture[UDP].dport, 20000)
Klement Sekerad81ae412018-05-16 10:52:54 +02008035 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08008036
8037 # TCP
8038 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8039 IPv6(dst=aftr_ip6, src=self.pg1.remote_hosts[1].ip6) /
8040 IP(dst=self.pg0.remote_ip4, src='192.168.1.1') /
8041 TCP(sport=20001, dport=10001))
8042 self.pg1.add_stream(p)
8043 self.pg_enable_capture(self.pg_interfaces)
8044 self.pg_start()
8045 capture = self.pg0.get_capture(1)
8046 capture = capture[0]
8047 self.assertFalse(capture.haslayer(IPv6))
8048 self.assertEqual(capture[IP].src, self.nat_addr)
8049 self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
8050 self.assertNotEqual(capture[TCP].sport, 20001)
8051 self.assertEqual(capture[TCP].dport, 10001)
Klement Sekerad81ae412018-05-16 10:52:54 +02008052 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08008053 out_port = capture[TCP].sport
8054
8055 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8056 IP(dst=self.nat_addr, src=self.pg0.remote_ip4) /
8057 TCP(sport=10001, dport=out_port))
8058 self.pg0.add_stream(p)
8059 self.pg_enable_capture(self.pg_interfaces)
8060 self.pg_start()
8061 capture = self.pg1.get_capture(1)
8062 capture = capture[0]
8063 self.assertEqual(capture[IPv6].src, aftr_ip6)
8064 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[1].ip6)
8065 self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
8066 self.assertEqual(capture[IP].dst, '192.168.1.1')
8067 self.assertEqual(capture[TCP].sport, 10001)
8068 self.assertEqual(capture[TCP].dport, 20001)
Klement Sekerad81ae412018-05-16 10:52:54 +02008069 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08008070
8071 # ICMP
8072 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8073 IPv6(dst=aftr_ip6, src=self.pg1.remote_hosts[1].ip6) /
8074 IP(dst=self.pg0.remote_ip4, src='192.168.1.1') /
8075 ICMP(id=4000, type='echo-request'))
8076 self.pg1.add_stream(p)
8077 self.pg_enable_capture(self.pg_interfaces)
8078 self.pg_start()
8079 capture = self.pg0.get_capture(1)
8080 capture = capture[0]
8081 self.assertFalse(capture.haslayer(IPv6))
8082 self.assertEqual(capture[IP].src, self.nat_addr)
8083 self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
8084 self.assertNotEqual(capture[ICMP].id, 4000)
Klement Sekerad81ae412018-05-16 10:52:54 +02008085 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08008086 out_id = capture[ICMP].id
8087
8088 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8089 IP(dst=self.nat_addr, src=self.pg0.remote_ip4) /
8090 ICMP(id=out_id, type='echo-reply'))
8091 self.pg0.add_stream(p)
8092 self.pg_enable_capture(self.pg_interfaces)
8093 self.pg_start()
8094 capture = self.pg1.get_capture(1)
8095 capture = capture[0]
8096 self.assertEqual(capture[IPv6].src, aftr_ip6)
8097 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[1].ip6)
8098 self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
8099 self.assertEqual(capture[IP].dst, '192.168.1.1')
8100 self.assertEqual(capture[ICMP].id, 4000)
Klement Sekerad81ae412018-05-16 10:52:54 +02008101 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08008102
Matus Fabian331acc62017-12-08 03:38:51 -08008103 # ping DS-Lite AFTR tunnel endpoint address
8104 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8105 IPv6(src=self.pg1.remote_hosts[1].ip6, dst=aftr_ip6) /
8106 ICMPv6EchoRequest())
8107 self.pg1.add_stream(p)
8108 self.pg_enable_capture(self.pg_interfaces)
8109 self.pg_start()
8110 capture = self.pg1.get_capture(1)
Matus Fabian331acc62017-12-08 03:38:51 -08008111 capture = capture[0]
8112 self.assertEqual(capture[IPv6].src, aftr_ip6)
8113 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[1].ip6)
8114 self.assertTrue(capture.haslayer(ICMPv6EchoReply))
8115
Matus Fabian8ebe6252017-11-06 05:04:53 -08008116 def tearDown(self):
8117 super(TestDSlite, self).tearDown()
8118 if not self.vpp_dead:
8119 self.logger.info(self.vapi.cli("show dslite pool"))
8120 self.logger.info(
8121 self.vapi.cli("show dslite aftr-tunnel-endpoint-address"))
8122 self.logger.info(self.vapi.cli("show dslite sessions"))
8123
Juraj Slobodac5c6a332018-01-09 16:08:32 +01008124
8125class TestDSliteCE(MethodHolder):
8126 """ DS-Lite CE Test Cases """
8127
8128 @classmethod
8129 def setUpConstants(cls):
8130 super(TestDSliteCE, cls).setUpConstants()
8131 cls.vpp_cmdline.extend(["nat", "{", "dslite ce", "}"])
8132
8133 @classmethod
8134 def setUpClass(cls):
8135 super(TestDSliteCE, cls).setUpClass()
8136
8137 try:
8138 cls.create_pg_interfaces(range(2))
8139 cls.pg0.admin_up()
8140 cls.pg0.config_ip4()
8141 cls.pg0.resolve_arp()
8142 cls.pg1.admin_up()
8143 cls.pg1.config_ip6()
8144 cls.pg1.generate_remote_hosts(1)
8145 cls.pg1.configure_ipv6_neighbors()
8146
8147 except Exception:
8148 super(TestDSliteCE, cls).tearDownClass()
8149 raise
8150
8151 def test_dslite_ce(self):
8152 """ Test DS-Lite CE """
8153
Matus Fabian69ce30d2018-08-22 01:27:10 -07008154 nat_config = self.vapi.nat_show_config()
8155 self.assertEqual(1, nat_config.dslite_ce)
8156
Juraj Slobodac5c6a332018-01-09 16:08:32 +01008157 b4_ip4 = '192.0.0.2'
8158 b4_ip4_n = socket.inet_pton(socket.AF_INET, b4_ip4)
8159 b4_ip6 = '2001:db8:62aa::375e:f4c1:1'
8160 b4_ip6_n = socket.inet_pton(socket.AF_INET6, b4_ip6)
8161 self.vapi.dslite_set_b4_addr(b4_ip6_n, b4_ip4_n)
8162
8163 aftr_ip4 = '192.0.0.1'
8164 aftr_ip4_n = socket.inet_pton(socket.AF_INET, aftr_ip4)
8165 aftr_ip6 = '2001:db8:85a3::8a2e:370:1'
8166 aftr_ip6_n = socket.inet_pton(socket.AF_INET6, aftr_ip6)
8167 self.vapi.dslite_set_aftr_addr(aftr_ip6_n, aftr_ip4_n)
8168
8169 self.vapi.ip_add_del_route(dst_address=aftr_ip6_n,
8170 dst_address_length=128,
8171 next_hop_address=self.pg1.remote_ip6n,
8172 next_hop_sw_if_index=self.pg1.sw_if_index,
8173 is_ipv6=1)
8174
8175 # UDP encapsulation
8176 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8177 IP(dst=self.pg1.remote_ip4, src=self.pg0.remote_ip4) /
8178 UDP(sport=10000, dport=20000))
8179 self.pg0.add_stream(p)
8180 self.pg_enable_capture(self.pg_interfaces)
8181 self.pg_start()
8182 capture = self.pg1.get_capture(1)
8183 capture = capture[0]
8184 self.assertEqual(capture[IPv6].src, b4_ip6)
8185 self.assertEqual(capture[IPv6].dst, aftr_ip6)
8186 self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
8187 self.assertEqual(capture[IP].dst, self.pg1.remote_ip4)
8188 self.assertEqual(capture[UDP].sport, 10000)
8189 self.assertEqual(capture[UDP].dport, 20000)
Klement Sekerad81ae412018-05-16 10:52:54 +02008190 self.assert_packet_checksums_valid(capture)
Juraj Slobodac5c6a332018-01-09 16:08:32 +01008191
8192 # UDP decapsulation
8193 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8194 IPv6(dst=b4_ip6, src=aftr_ip6) /
8195 IP(dst=self.pg0.remote_ip4, src=self.pg1.remote_ip4) /
8196 UDP(sport=20000, dport=10000))
8197 self.pg1.add_stream(p)
8198 self.pg_enable_capture(self.pg_interfaces)
8199 self.pg_start()
8200 capture = self.pg0.get_capture(1)
8201 capture = capture[0]
8202 self.assertFalse(capture.haslayer(IPv6))
8203 self.assertEqual(capture[IP].src, self.pg1.remote_ip4)
8204 self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
8205 self.assertEqual(capture[UDP].sport, 20000)
8206 self.assertEqual(capture[UDP].dport, 10000)
Klement Sekerad81ae412018-05-16 10:52:54 +02008207 self.assert_packet_checksums_valid(capture)
Juraj Slobodac5c6a332018-01-09 16:08:32 +01008208
8209 # ping DS-Lite B4 tunnel endpoint address
8210 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8211 IPv6(src=self.pg1.remote_hosts[0].ip6, dst=b4_ip6) /
8212 ICMPv6EchoRequest())
8213 self.pg1.add_stream(p)
8214 self.pg_enable_capture(self.pg_interfaces)
8215 self.pg_start()
8216 capture = self.pg1.get_capture(1)
Juraj Slobodac5c6a332018-01-09 16:08:32 +01008217 capture = capture[0]
8218 self.assertEqual(capture[IPv6].src, b4_ip6)
8219 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[0].ip6)
8220 self.assertTrue(capture.haslayer(ICMPv6EchoReply))
8221
8222 def tearDown(self):
8223 super(TestDSliteCE, self).tearDown()
8224 if not self.vpp_dead:
8225 self.logger.info(
8226 self.vapi.cli("show dslite aftr-tunnel-endpoint-address"))
8227 self.logger.info(
8228 self.vapi.cli("show dslite b4-tunnel-endpoint-address"))
8229
Matus Fabianf2a23cc2018-01-22 03:41:53 -08008230
8231class TestNAT66(MethodHolder):
8232 """ NAT66 Test Cases """
8233
8234 @classmethod
8235 def setUpClass(cls):
8236 super(TestNAT66, cls).setUpClass()
8237
8238 try:
8239 cls.nat_addr = 'fd01:ff::2'
8240 cls.nat_addr_n = socket.inet_pton(socket.AF_INET6, cls.nat_addr)
8241
8242 cls.create_pg_interfaces(range(2))
8243 cls.interfaces = list(cls.pg_interfaces)
8244
8245 for i in cls.interfaces:
8246 i.admin_up()
8247 i.config_ip6()
8248 i.configure_ipv6_neighbors()
8249
8250 except Exception:
8251 super(TestNAT66, cls).tearDownClass()
8252 raise
8253
8254 def test_static(self):
8255 """ 1:1 NAT66 test """
8256 self.vapi.nat66_add_del_interface(self.pg0.sw_if_index)
8257 self.vapi.nat66_add_del_interface(self.pg1.sw_if_index, is_inside=0)
8258 self.vapi.nat66_add_del_static_mapping(self.pg0.remote_ip6n,
8259 self.nat_addr_n)
8260
8261 # in2out
8262 pkts = []
8263 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8264 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
8265 TCP())
8266 pkts.append(p)
8267 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8268 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
8269 UDP())
8270 pkts.append(p)
8271 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8272 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
8273 ICMPv6EchoRequest())
8274 pkts.append(p)
8275 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8276 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
8277 GRE() / IP() / TCP())
8278 pkts.append(p)
8279 self.pg0.add_stream(pkts)
8280 self.pg_enable_capture(self.pg_interfaces)
8281 self.pg_start()
8282 capture = self.pg1.get_capture(len(pkts))
8283 for packet in capture:
8284 try:
8285 self.assertEqual(packet[IPv6].src, self.nat_addr)
8286 self.assertEqual(packet[IPv6].dst, self.pg1.remote_ip6)
Klement Sekerad81ae412018-05-16 10:52:54 +02008287 self.assert_packet_checksums_valid(packet)
Matus Fabianf2a23cc2018-01-22 03:41:53 -08008288 except:
8289 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8290 raise
8291
8292 # out2in
8293 pkts = []
8294 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8295 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
8296 TCP())
8297 pkts.append(p)
8298 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8299 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
8300 UDP())
8301 pkts.append(p)
8302 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8303 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
8304 ICMPv6EchoReply())
8305 pkts.append(p)
8306 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8307 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
8308 GRE() / IP() / TCP())
8309 pkts.append(p)
8310 self.pg1.add_stream(pkts)
8311 self.pg_enable_capture(self.pg_interfaces)
8312 self.pg_start()
8313 capture = self.pg0.get_capture(len(pkts))
8314 for packet in capture:
8315 try:
8316 self.assertEqual(packet[IPv6].src, self.pg1.remote_ip6)
8317 self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
Klement Sekerad81ae412018-05-16 10:52:54 +02008318 self.assert_packet_checksums_valid(packet)
Matus Fabianf2a23cc2018-01-22 03:41:53 -08008319 except:
8320 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8321 raise
8322
8323 sm = self.vapi.nat66_static_mapping_dump()
8324 self.assertEqual(len(sm), 1)
8325 self.assertEqual(sm[0].total_pkts, 8)
8326
Juraj Sloboda9341e342018-04-13 12:00:46 +02008327 def test_check_no_translate(self):
8328 """ NAT66 translate only when egress interface is outside interface """
8329 self.vapi.nat66_add_del_interface(self.pg0.sw_if_index)
8330 self.vapi.nat66_add_del_interface(self.pg1.sw_if_index)
8331 self.vapi.nat66_add_del_static_mapping(self.pg0.remote_ip6n,
8332 self.nat_addr_n)
8333
8334 # in2out
8335 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8336 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
8337 UDP())
8338 self.pg0.add_stream([p])
8339 self.pg_enable_capture(self.pg_interfaces)
8340 self.pg_start()
8341 capture = self.pg1.get_capture(1)
8342 packet = capture[0]
8343 try:
8344 self.assertEqual(packet[IPv6].src, self.pg0.remote_ip6)
8345 self.assertEqual(packet[IPv6].dst, self.pg1.remote_ip6)
8346 except:
8347 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8348 raise
8349
Matus Fabianf2a23cc2018-01-22 03:41:53 -08008350 def clear_nat66(self):
8351 """
8352 Clear NAT66 configuration.
8353 """
8354 interfaces = self.vapi.nat66_interface_dump()
8355 for intf in interfaces:
8356 self.vapi.nat66_add_del_interface(intf.sw_if_index,
8357 intf.is_inside,
8358 is_add=0)
8359
8360 static_mappings = self.vapi.nat66_static_mapping_dump()
8361 for sm in static_mappings:
8362 self.vapi.nat66_add_del_static_mapping(sm.local_ip_address,
8363 sm.external_ip_address,
8364 sm.vrf_id,
8365 is_add=0)
8366
8367 def tearDown(self):
8368 super(TestNAT66, self).tearDown()
8369 if not self.vpp_dead:
8370 self.logger.info(self.vapi.cli("show nat66 interfaces"))
8371 self.logger.info(self.vapi.cli("show nat66 static mappings"))
8372 self.clear_nat66()
8373
Klement Sekerad81ae412018-05-16 10:52:54 +02008374
Matus Fabiande886752016-12-07 03:38:19 -08008375if __name__ == '__main__':
8376 unittest.main(testRunner=VppTestRunner)