blob: 79d26224ad070641a601c74b270c262cedc58ff3 [file] [log] [blame]
Matus Fabiande886752016-12-07 03:38:19 -08001#!/usr/bin/env python
2
3import socket
4import unittest
Matus Fabianeea28d72017-01-13 04:15:54 -08005import struct
Matus Fabianefcd1e92017-08-15 06:59:19 -07006import StringIO
7import random
Matus Fabiande886752016-12-07 03:38:19 -08008
Martin Gálik977c1cb2017-03-30 23:21:51 -07009from framework import VppTestCase, VppTestRunner, running_extended_tests
Matus Fabiande886752016-12-07 03:38:19 -080010from scapy.layers.inet import IP, TCP, UDP, ICMP
Juraj Slobodab33f4132017-02-08 23:54:21 -080011from scapy.layers.inet import IPerror, TCPerror, UDPerror, ICMPerror
Juraj Slobodac746a152018-07-09 02:36:37 +020012from scapy.layers.inet6 import IPv6, ICMPv6EchoRequest, ICMPv6EchoReply, \
13 ICMPv6ND_NS, ICMPv6ND_NA, ICMPv6NDOptDstLLAddr
Matus Fabianefcd1e92017-08-15 06:59:19 -070014from scapy.layers.inet6 import ICMPv6DestUnreach, IPerror6, IPv6ExtHdrFragment
Matus Fabian328dbc82017-06-19 04:28:04 -070015from scapy.layers.l2 import Ether, ARP, GRE
Matus Fabianeea28d72017-01-13 04:15:54 -080016from scapy.data import IP_PROTOS
Matus Fabianefcd1e92017-08-15 06:59:19 -070017from scapy.packet import bind_layers, Raw
18from scapy.all import fragment6
Klement Sekera9225dee2016-12-12 08:36:58 +010019from util import ppp
Matus Fabianeea28d72017-01-13 04:15:54 -080020from ipfix import IPFIX, Set, Template, Data, IPFIXDecoder
Martin Gálik977c1cb2017-03-30 23:21:51 -070021from time import sleep
Matus Fabian704018c2017-09-04 02:17:18 -070022from util import ip4_range
Ole Troan895b6e82017-10-20 13:28:20 +020023from util import mactobinary
Matus Fabiande886752016-12-07 03:38:19 -080024
25
Martin Gálikd7f75cd2017-03-27 06:02:47 -070026class MethodHolder(VppTestCase):
Matus Fabian2ba92e32017-08-21 07:05:03 -070027 """ NAT create capture and verify method holder """
Matus Fabiande886752016-12-07 03:38:19 -080028
Matus Fabiana6110b62018-06-13 05:39:07 -070029 def clear_nat44(self):
30 """
31 Clear NAT44 configuration.
32 """
33 if hasattr(self, 'pg7') and hasattr(self, 'pg8'):
34 # I found no elegant way to do this
35 self.vapi.ip_add_del_route(
36 dst_address=self.pg7.remote_ip4n,
37 dst_address_length=32,
38 next_hop_address=self.pg7.remote_ip4n,
39 next_hop_sw_if_index=self.pg7.sw_if_index,
40 is_add=0)
41 self.vapi.ip_add_del_route(
42 dst_address=self.pg8.remote_ip4n,
43 dst_address_length=32,
44 next_hop_address=self.pg8.remote_ip4n,
45 next_hop_sw_if_index=self.pg8.sw_if_index,
46 is_add=0)
47
48 for intf in [self.pg7, self.pg8]:
49 neighbors = self.vapi.ip_neighbor_dump(intf.sw_if_index)
50 for n in neighbors:
51 self.vapi.ip_neighbor_add_del(intf.sw_if_index,
52 n.mac_address,
53 n.ip_address,
54 is_add=0)
55
56 if self.pg7.has_ip4_config:
57 self.pg7.unconfig_ip4()
58
59 self.vapi.nat44_forwarding_enable_disable(0)
60
61 interfaces = self.vapi.nat44_interface_addr_dump()
62 for intf in interfaces:
63 self.vapi.nat44_add_interface_addr(intf.sw_if_index,
64 twice_nat=intf.twice_nat,
65 is_add=0)
66
67 self.vapi.nat_ipfix(enable=0, src_port=self.ipfix_src_port,
68 domain_id=self.ipfix_domain_id)
69 self.ipfix_src_port = 4739
70 self.ipfix_domain_id = 1
71
72 interfaces = self.vapi.nat44_interface_dump()
73 for intf in interfaces:
74 if intf.is_inside > 1:
75 self.vapi.nat44_interface_add_del_feature(intf.sw_if_index,
76 0,
77 is_add=0)
78 self.vapi.nat44_interface_add_del_feature(intf.sw_if_index,
79 intf.is_inside,
80 is_add=0)
81
82 interfaces = self.vapi.nat44_interface_output_feature_dump()
83 for intf in interfaces:
84 self.vapi.nat44_interface_add_del_output_feature(intf.sw_if_index,
85 intf.is_inside,
86 is_add=0)
87
88 static_mappings = self.vapi.nat44_static_mapping_dump()
89 for sm in static_mappings:
90 self.vapi.nat44_add_del_static_mapping(
91 sm.local_ip_address,
92 sm.external_ip_address,
93 local_port=sm.local_port,
94 external_port=sm.external_port,
95 addr_only=sm.addr_only,
96 vrf_id=sm.vrf_id,
97 protocol=sm.protocol,
98 twice_nat=sm.twice_nat,
99 self_twice_nat=sm.self_twice_nat,
100 out2in_only=sm.out2in_only,
101 tag=sm.tag,
102 external_sw_if_index=sm.external_sw_if_index,
103 is_add=0)
104
105 lb_static_mappings = self.vapi.nat44_lb_static_mapping_dump()
106 for lb_sm in lb_static_mappings:
107 self.vapi.nat44_add_del_lb_static_mapping(
108 lb_sm.external_addr,
109 lb_sm.external_port,
110 lb_sm.protocol,
Matus Fabiana6110b62018-06-13 05:39:07 -0700111 twice_nat=lb_sm.twice_nat,
112 self_twice_nat=lb_sm.self_twice_nat,
113 out2in_only=lb_sm.out2in_only,
114 tag=lb_sm.tag,
115 is_add=0,
116 local_num=0,
117 locals=[])
118
119 identity_mappings = self.vapi.nat44_identity_mapping_dump()
120 for id_m in identity_mappings:
121 self.vapi.nat44_add_del_identity_mapping(
122 addr_only=id_m.addr_only,
123 ip=id_m.ip_address,
124 port=id_m.port,
125 sw_if_index=id_m.sw_if_index,
126 vrf_id=id_m.vrf_id,
127 protocol=id_m.protocol,
128 is_add=0)
129
130 adresses = self.vapi.nat44_address_dump()
131 for addr in adresses:
132 self.vapi.nat44_add_del_address_range(addr.ip_address,
133 addr.ip_address,
134 twice_nat=addr.twice_nat,
135 is_add=0)
136
137 self.vapi.nat_set_reass()
138 self.vapi.nat_set_reass(is_ip6=1)
Matus Fabian68ba8802018-08-08 05:52:47 -0700139 self.verify_no_nat44_user()
Matus Fabian878c6462018-08-23 00:33:35 -0700140 self.vapi.nat_set_timeouts()
Matus Fabiana6110b62018-06-13 05:39:07 -0700141
142 def nat44_add_static_mapping(self, local_ip, external_ip='0.0.0.0',
143 local_port=0, external_port=0, vrf_id=0,
144 is_add=1, external_sw_if_index=0xFFFFFFFF,
145 proto=0, twice_nat=0, self_twice_nat=0,
146 out2in_only=0, tag=""):
147 """
148 Add/delete NAT44 static mapping
149
150 :param local_ip: Local IP address
151 :param external_ip: External IP address
152 :param local_port: Local port number (Optional)
153 :param external_port: External port number (Optional)
154 :param vrf_id: VRF ID (Default 0)
155 :param is_add: 1 if add, 0 if delete (Default add)
156 :param external_sw_if_index: External interface instead of IP address
157 :param proto: IP protocol (Mandatory if port specified)
158 :param twice_nat: 1 if translate external host address and port
159 :param self_twice_nat: 1 if translate external host address and port
160 whenever external host address equals
161 local address of internal host
162 :param out2in_only: if 1 rule is matching only out2in direction
163 :param tag: Opaque string tag
164 """
165 addr_only = 1
166 if local_port and external_port:
167 addr_only = 0
168 l_ip = socket.inet_pton(socket.AF_INET, local_ip)
169 e_ip = socket.inet_pton(socket.AF_INET, external_ip)
170 self.vapi.nat44_add_del_static_mapping(
171 l_ip,
172 e_ip,
173 external_sw_if_index,
174 local_port,
175 external_port,
176 addr_only,
177 vrf_id,
178 proto,
179 twice_nat,
180 self_twice_nat,
181 out2in_only,
182 tag,
183 is_add)
184
185 def nat44_add_address(self, ip, is_add=1, vrf_id=0xFFFFFFFF, twice_nat=0):
186 """
187 Add/delete NAT44 address
188
189 :param ip: IP address
190 :param is_add: 1 if add, 0 if delete (Default add)
191 :param twice_nat: twice NAT address for extenal hosts
192 """
193 nat_addr = socket.inet_pton(socket.AF_INET, ip)
194 self.vapi.nat44_add_del_address_range(nat_addr, nat_addr, is_add,
195 vrf_id=vrf_id,
196 twice_nat=twice_nat)
197
Juraj Slobodacba69362017-12-19 02:09:32 +0100198 def create_stream_in(self, in_if, out_if, dst_ip=None, ttl=64):
Matus Fabiande886752016-12-07 03:38:19 -0800199 """
200 Create packet stream for inside network
201
202 :param in_if: Inside interface
203 :param out_if: Outside interface
Juraj Slobodacba69362017-12-19 02:09:32 +0100204 :param dst_ip: Destination address
Juraj Slobodab33f4132017-02-08 23:54:21 -0800205 :param ttl: TTL of generated packets
Matus Fabiande886752016-12-07 03:38:19 -0800206 """
Juraj Slobodacba69362017-12-19 02:09:32 +0100207 if dst_ip is None:
208 dst_ip = out_if.remote_ip4
209
Matus Fabiande886752016-12-07 03:38:19 -0800210 pkts = []
211 # TCP
212 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
Juraj Slobodacba69362017-12-19 02:09:32 +0100213 IP(src=in_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Matus Fabian06596c52017-06-06 04:53:28 -0700214 TCP(sport=self.tcp_port_in, dport=20))
Matus Fabiande886752016-12-07 03:38:19 -0800215 pkts.append(p)
216
217 # UDP
218 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
Juraj Slobodacba69362017-12-19 02:09:32 +0100219 IP(src=in_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Matus Fabian06596c52017-06-06 04:53:28 -0700220 UDP(sport=self.udp_port_in, dport=20))
Matus Fabiande886752016-12-07 03:38:19 -0800221 pkts.append(p)
222
223 # ICMP
224 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
Juraj Slobodacba69362017-12-19 02:09:32 +0100225 IP(src=in_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Matus Fabiande886752016-12-07 03:38:19 -0800226 ICMP(id=self.icmp_id_in, type='echo-request'))
227 pkts.append(p)
228
229 return pkts
230
Matus Fabian428dc912017-06-21 06:15:18 -0700231 def compose_ip6(self, ip4, pref, plen):
232 """
233 Compose IPv4-embedded IPv6 addresses
234
235 :param ip4: IPv4 address
236 :param pref: IPv6 prefix
237 :param plen: IPv6 prefix length
238 :returns: IPv4-embedded IPv6 addresses
239 """
240 pref_n = list(socket.inet_pton(socket.AF_INET6, pref))
241 ip4_n = list(socket.inet_pton(socket.AF_INET, ip4))
242 if plen == 32:
243 pref_n[4] = ip4_n[0]
244 pref_n[5] = ip4_n[1]
245 pref_n[6] = ip4_n[2]
246 pref_n[7] = ip4_n[3]
247 elif plen == 40:
248 pref_n[5] = ip4_n[0]
249 pref_n[6] = ip4_n[1]
250 pref_n[7] = ip4_n[2]
251 pref_n[9] = ip4_n[3]
252 elif plen == 48:
253 pref_n[6] = ip4_n[0]
254 pref_n[7] = ip4_n[1]
255 pref_n[9] = ip4_n[2]
256 pref_n[10] = ip4_n[3]
257 elif plen == 56:
258 pref_n[7] = ip4_n[0]
259 pref_n[9] = ip4_n[1]
260 pref_n[10] = ip4_n[2]
261 pref_n[11] = ip4_n[3]
262 elif plen == 64:
263 pref_n[9] = ip4_n[0]
264 pref_n[10] = ip4_n[1]
265 pref_n[11] = ip4_n[2]
266 pref_n[12] = ip4_n[3]
267 elif plen == 96:
268 pref_n[12] = ip4_n[0]
269 pref_n[13] = ip4_n[1]
270 pref_n[14] = ip4_n[2]
271 pref_n[15] = ip4_n[3]
272 return socket.inet_ntop(socket.AF_INET6, ''.join(pref_n))
273
Juraj Slobodacba69362017-12-19 02:09:32 +0100274 def extract_ip4(self, ip6, plen):
275 """
276 Extract IPv4 address embedded in IPv6 addresses
277
278 :param ip6: IPv6 address
279 :param plen: IPv6 prefix length
280 :returns: extracted IPv4 address
281 """
282 ip6_n = list(socket.inet_pton(socket.AF_INET6, ip6))
283 ip4_n = [None] * 4
284 if plen == 32:
285 ip4_n[0] = ip6_n[4]
286 ip4_n[1] = ip6_n[5]
287 ip4_n[2] = ip6_n[6]
288 ip4_n[3] = ip6_n[7]
289 elif plen == 40:
290 ip4_n[0] = ip6_n[5]
291 ip4_n[1] = ip6_n[6]
292 ip4_n[2] = ip6_n[7]
293 ip4_n[3] = ip6_n[9]
294 elif plen == 48:
295 ip4_n[0] = ip6_n[6]
296 ip4_n[1] = ip6_n[7]
297 ip4_n[2] = ip6_n[9]
298 ip4_n[3] = ip6_n[10]
299 elif plen == 56:
300 ip4_n[0] = ip6_n[7]
301 ip4_n[1] = ip6_n[9]
302 ip4_n[2] = ip6_n[10]
303 ip4_n[3] = ip6_n[11]
304 elif plen == 64:
305 ip4_n[0] = ip6_n[9]
306 ip4_n[1] = ip6_n[10]
307 ip4_n[2] = ip6_n[11]
308 ip4_n[3] = ip6_n[12]
309 elif plen == 96:
310 ip4_n[0] = ip6_n[12]
311 ip4_n[1] = ip6_n[13]
312 ip4_n[2] = ip6_n[14]
313 ip4_n[3] = ip6_n[15]
314 return socket.inet_ntop(socket.AF_INET, ''.join(ip4_n))
315
Matus Fabian428dc912017-06-21 06:15:18 -0700316 def create_stream_in_ip6(self, in_if, out_if, hlim=64, pref=None, plen=0):
Matus Fabian06596c52017-06-06 04:53:28 -0700317 """
318 Create IPv6 packet stream for inside network
319
320 :param in_if: Inside interface
321 :param out_if: Outside interface
322 :param ttl: Hop Limit of generated packets
Matus Fabian428dc912017-06-21 06:15:18 -0700323 :param pref: NAT64 prefix
324 :param plen: NAT64 prefix length
Matus Fabian06596c52017-06-06 04:53:28 -0700325 """
326 pkts = []
Matus Fabian428dc912017-06-21 06:15:18 -0700327 if pref is None:
328 dst = ''.join(['64:ff9b::', out_if.remote_ip4])
329 else:
330 dst = self.compose_ip6(out_if.remote_ip4, pref, plen)
331
Matus Fabian06596c52017-06-06 04:53:28 -0700332 # TCP
333 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
334 IPv6(src=in_if.remote_ip6, dst=dst, hlim=hlim) /
335 TCP(sport=self.tcp_port_in, dport=20))
336 pkts.append(p)
337
338 # UDP
339 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
340 IPv6(src=in_if.remote_ip6, dst=dst, hlim=hlim) /
341 UDP(sport=self.udp_port_in, dport=20))
342 pkts.append(p)
343
344 # ICMP
345 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
346 IPv6(src=in_if.remote_ip6, dst=dst, hlim=hlim) /
347 ICMPv6EchoRequest(id=self.icmp_id_in))
348 pkts.append(p)
349
350 return pkts
351
Juraj Sloboda7b929792017-11-23 13:20:48 +0100352 def create_stream_out(self, out_if, dst_ip=None, ttl=64,
353 use_inside_ports=False):
Matus Fabiande886752016-12-07 03:38:19 -0800354 """
355 Create packet stream for outside network
356
357 :param out_if: Outside interface
Matus Fabian2ba92e32017-08-21 07:05:03 -0700358 :param dst_ip: Destination IP address (Default use global NAT address)
Juraj Slobodab33f4132017-02-08 23:54:21 -0800359 :param ttl: TTL of generated packets
Juraj Sloboda7b929792017-11-23 13:20:48 +0100360 :param use_inside_ports: Use inside NAT ports as destination ports
361 instead of outside ports
Matus Fabiande886752016-12-07 03:38:19 -0800362 """
363 if dst_ip is None:
Matus Fabian2ba92e32017-08-21 07:05:03 -0700364 dst_ip = self.nat_addr
Juraj Sloboda7b929792017-11-23 13:20:48 +0100365 if not use_inside_ports:
366 tcp_port = self.tcp_port_out
367 udp_port = self.udp_port_out
368 icmp_id = self.icmp_id_out
369 else:
370 tcp_port = self.tcp_port_in
371 udp_port = self.udp_port_in
372 icmp_id = self.icmp_id_in
Matus Fabiande886752016-12-07 03:38:19 -0800373 pkts = []
374 # TCP
375 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
Juraj Slobodab33f4132017-02-08 23:54:21 -0800376 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Juraj Sloboda7b929792017-11-23 13:20:48 +0100377 TCP(dport=tcp_port, sport=20))
Matus Fabiande886752016-12-07 03:38:19 -0800378 pkts.append(p)
379
380 # UDP
381 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
Juraj Slobodab33f4132017-02-08 23:54:21 -0800382 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Juraj Sloboda7b929792017-11-23 13:20:48 +0100383 UDP(dport=udp_port, sport=20))
Matus Fabiande886752016-12-07 03:38:19 -0800384 pkts.append(p)
385
386 # ICMP
387 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
Juraj Slobodab33f4132017-02-08 23:54:21 -0800388 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Juraj Sloboda7b929792017-11-23 13:20:48 +0100389 ICMP(id=icmp_id, type='echo-reply'))
Matus Fabiande886752016-12-07 03:38:19 -0800390 pkts.append(p)
391
392 return pkts
393
Juraj Slobodacba69362017-12-19 02:09:32 +0100394 def create_stream_out_ip6(self, out_if, src_ip, dst_ip, hl=64):
395 """
396 Create packet stream for outside network
397
398 :param out_if: Outside interface
399 :param dst_ip: Destination IP address (Default use global NAT address)
400 :param hl: HL of generated packets
401 """
402 pkts = []
403 # TCP
404 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
405 IPv6(src=src_ip, dst=dst_ip, hlim=hl) /
406 TCP(dport=self.tcp_port_out, sport=20))
407 pkts.append(p)
408
409 # UDP
410 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
411 IPv6(src=src_ip, dst=dst_ip, hlim=hl) /
412 UDP(dport=self.udp_port_out, sport=20))
413 pkts.append(p)
414
415 # ICMP
416 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
417 IPv6(src=src_ip, dst=dst_ip, hlim=hl) /
418 ICMPv6EchoReply(id=self.icmp_id_out))
419 pkts.append(p)
420
421 return pkts
422
Matus Fabiande886752016-12-07 03:38:19 -0800423 def verify_capture_out(self, capture, nat_ip=None, same_port=False,
Juraj Slobodacba69362017-12-19 02:09:32 +0100424 packet_num=3, dst_ip=None, is_ip6=False):
Matus Fabiande886752016-12-07 03:38:19 -0800425 """
426 Verify captured packets on outside network
427
428 :param capture: Captured packets
Matus Fabian2ba92e32017-08-21 07:05:03 -0700429 :param nat_ip: Translated IP address (Default use global NAT address)
Matus Fabiande886752016-12-07 03:38:19 -0800430 :param same_port: Sorce port number is not translated (Default False)
431 :param packet_num: Expected number of packets (Default 3)
Matus Fabian06596c52017-06-06 04:53:28 -0700432 :param dst_ip: Destination IP address (Default do not verify)
Juraj Slobodacba69362017-12-19 02:09:32 +0100433 :param is_ip6: If L3 protocol is IPv6 (Default False)
Matus Fabiande886752016-12-07 03:38:19 -0800434 """
Juraj Slobodacba69362017-12-19 02:09:32 +0100435 if is_ip6:
436 IP46 = IPv6
437 ICMP46 = ICMPv6EchoRequest
438 else:
439 IP46 = IP
440 ICMP46 = ICMP
Matus Fabiande886752016-12-07 03:38:19 -0800441 if nat_ip is None:
Matus Fabian2ba92e32017-08-21 07:05:03 -0700442 nat_ip = self.nat_addr
Matus Fabiande886752016-12-07 03:38:19 -0800443 self.assertEqual(packet_num, len(capture))
444 for packet in capture:
445 try:
Juraj Slobodacba69362017-12-19 02:09:32 +0100446 if not is_ip6:
Klement Sekerad81ae412018-05-16 10:52:54 +0200447 self.assert_packet_checksums_valid(packet)
Juraj Slobodacba69362017-12-19 02:09:32 +0100448 self.assertEqual(packet[IP46].src, nat_ip)
Matus Fabian06596c52017-06-06 04:53:28 -0700449 if dst_ip is not None:
Juraj Slobodacba69362017-12-19 02:09:32 +0100450 self.assertEqual(packet[IP46].dst, dst_ip)
Matus Fabiande886752016-12-07 03:38:19 -0800451 if packet.haslayer(TCP):
452 if same_port:
453 self.assertEqual(packet[TCP].sport, self.tcp_port_in)
454 else:
Klement Sekerada505f62017-01-04 12:58:53 +0100455 self.assertNotEqual(
456 packet[TCP].sport, self.tcp_port_in)
Matus Fabiande886752016-12-07 03:38:19 -0800457 self.tcp_port_out = packet[TCP].sport
Klement Sekerad81ae412018-05-16 10:52:54 +0200458 self.assert_packet_checksums_valid(packet)
Matus Fabiande886752016-12-07 03:38:19 -0800459 elif packet.haslayer(UDP):
460 if same_port:
461 self.assertEqual(packet[UDP].sport, self.udp_port_in)
462 else:
Klement Sekerada505f62017-01-04 12:58:53 +0100463 self.assertNotEqual(
464 packet[UDP].sport, self.udp_port_in)
Matus Fabiande886752016-12-07 03:38:19 -0800465 self.udp_port_out = packet[UDP].sport
466 else:
467 if same_port:
Juraj Slobodacba69362017-12-19 02:09:32 +0100468 self.assertEqual(packet[ICMP46].id, self.icmp_id_in)
Matus Fabiande886752016-12-07 03:38:19 -0800469 else:
Juraj Slobodacba69362017-12-19 02:09:32 +0100470 self.assertNotEqual(packet[ICMP46].id, self.icmp_id_in)
471 self.icmp_id_out = packet[ICMP46].id
Klement Sekerad81ae412018-05-16 10:52:54 +0200472 self.assert_packet_checksums_valid(packet)
Matus Fabiande886752016-12-07 03:38:19 -0800473 except:
Klement Sekera9225dee2016-12-12 08:36:58 +0100474 self.logger.error(ppp("Unexpected or invalid packet "
475 "(outside network):", packet))
Matus Fabiande886752016-12-07 03:38:19 -0800476 raise
477
Juraj Slobodacba69362017-12-19 02:09:32 +0100478 def verify_capture_out_ip6(self, capture, nat_ip, same_port=False,
479 packet_num=3, dst_ip=None):
480 """
481 Verify captured packets on outside network
482
483 :param capture: Captured packets
484 :param nat_ip: Translated IP address
485 :param same_port: Sorce port number is not translated (Default False)
486 :param packet_num: Expected number of packets (Default 3)
487 :param dst_ip: Destination IP address (Default do not verify)
488 """
489 return self.verify_capture_out(capture, nat_ip, same_port, packet_num,
490 dst_ip, True)
491
Matus Fabiande886752016-12-07 03:38:19 -0800492 def verify_capture_in(self, capture, in_if, packet_num=3):
493 """
494 Verify captured packets on inside network
495
496 :param capture: Captured packets
497 :param in_if: Inside interface
498 :param packet_num: Expected number of packets (Default 3)
499 """
500 self.assertEqual(packet_num, len(capture))
501 for packet in capture:
502 try:
Klement Sekerad81ae412018-05-16 10:52:54 +0200503 self.assert_packet_checksums_valid(packet)
Matus Fabiande886752016-12-07 03:38:19 -0800504 self.assertEqual(packet[IP].dst, in_if.remote_ip4)
505 if packet.haslayer(TCP):
506 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
507 elif packet.haslayer(UDP):
508 self.assertEqual(packet[UDP].dport, self.udp_port_in)
509 else:
510 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
511 except:
Klement Sekera9225dee2016-12-12 08:36:58 +0100512 self.logger.error(ppp("Unexpected or invalid packet "
513 "(inside network):", packet))
Matus Fabiande886752016-12-07 03:38:19 -0800514 raise
515
Matus Fabian06596c52017-06-06 04:53:28 -0700516 def verify_capture_in_ip6(self, capture, src_ip, dst_ip, packet_num=3):
517 """
518 Verify captured IPv6 packets on inside network
519
520 :param capture: Captured packets
521 :param src_ip: Source IP
522 :param dst_ip: Destination IP address
523 :param packet_num: Expected number of packets (Default 3)
524 """
525 self.assertEqual(packet_num, len(capture))
526 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,
567 packet_num=3, icmp_type=11):
568 """
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 packet_num: Expected number of packets (Default 3)
575 :param icmp_type: Type of error ICMP packet
576 we are expecting (Default 11)
577 """
578 if src_ip is None:
Matus Fabian2ba92e32017-08-21 07:05:03 -0700579 src_ip = self.nat_addr
Juraj Slobodab33f4132017-02-08 23:54:21 -0800580 self.assertEqual(packet_num, len(capture))
581 for packet in capture:
582 try:
583 self.assertEqual(packet[IP].src, src_ip)
584 self.assertTrue(packet.haslayer(ICMP))
585 icmp = packet[ICMP]
586 self.assertEqual(icmp.type, icmp_type)
587 self.assertTrue(icmp.haslayer(IPerror))
588 inner_ip = icmp[IPerror]
589 if inner_ip.haslayer(TCPerror):
590 self.assertEqual(inner_ip[TCPerror].dport,
591 self.tcp_port_out)
592 elif inner_ip.haslayer(UDPerror):
593 self.assertEqual(inner_ip[UDPerror].dport,
594 self.udp_port_out)
595 else:
596 self.assertEqual(inner_ip[ICMPerror].id, self.icmp_id_out)
597 except:
598 self.logger.error(ppp("Unexpected or invalid packet "
599 "(outside network):", packet))
600 raise
601
602 def verify_capture_in_with_icmp_errors(self, capture, in_if, packet_num=3,
603 icmp_type=11):
604 """
605 Verify captured packets with ICMP errors on inside network
606
607 :param capture: Captured packets
608 :param in_if: Inside interface
609 :param packet_num: Expected number of packets (Default 3)
610 :param icmp_type: Type of error ICMP packet
611 we are expecting (Default 11)
612 """
613 self.assertEqual(packet_num, len(capture))
614 for packet in capture:
615 try:
616 self.assertEqual(packet[IP].dst, in_if.remote_ip4)
617 self.assertTrue(packet.haslayer(ICMP))
618 icmp = packet[ICMP]
619 self.assertEqual(icmp.type, icmp_type)
620 self.assertTrue(icmp.haslayer(IPerror))
621 inner_ip = icmp[IPerror]
622 if inner_ip.haslayer(TCPerror):
623 self.assertEqual(inner_ip[TCPerror].sport,
624 self.tcp_port_in)
625 elif inner_ip.haslayer(UDPerror):
626 self.assertEqual(inner_ip[UDPerror].sport,
627 self.udp_port_in)
628 else:
629 self.assertEqual(inner_ip[ICMPerror].id, self.icmp_id_in)
630 except:
631 self.logger.error(ppp("Unexpected or invalid packet "
632 "(inside network):", packet))
633 raise
634
Matus Fabianefcd1e92017-08-15 06:59:19 -0700635 def create_stream_frag(self, src_if, dst, sport, dport, data):
636 """
637 Create fragmented packet stream
638
639 :param src_if: Source interface
640 :param dst: Destination IPv4 address
641 :param sport: Source TCP port
642 :param dport: Destination TCP port
643 :param data: Payload data
644 :returns: Fragmets
645 """
646 id = random.randint(0, 65535)
647 p = (IP(src=src_if.remote_ip4, dst=dst) /
648 TCP(sport=sport, dport=dport) /
649 Raw(data))
650 p = p.__class__(str(p))
651 chksum = p['TCP'].chksum
652 pkts = []
653 p = (Ether(src=src_if.remote_mac, dst=src_if.local_mac) /
654 IP(src=src_if.remote_ip4, dst=dst, flags="MF", frag=0, id=id) /
655 TCP(sport=sport, dport=dport, chksum=chksum) /
656 Raw(data[0:4]))
657 pkts.append(p)
658 p = (Ether(src=src_if.remote_mac, dst=src_if.local_mac) /
659 IP(src=src_if.remote_ip4, dst=dst, flags="MF", frag=3, id=id,
660 proto=IP_PROTOS.tcp) /
661 Raw(data[4:20]))
662 pkts.append(p)
663 p = (Ether(src=src_if.remote_mac, dst=src_if.local_mac) /
664 IP(src=src_if.remote_ip4, dst=dst, frag=5, proto=IP_PROTOS.tcp,
665 id=id) /
666 Raw(data[20:]))
667 pkts.append(p)
668 return pkts
669
670 def create_stream_frag_ip6(self, src_if, dst, sport, dport, data,
671 pref=None, plen=0, frag_size=128):
672 """
673 Create fragmented packet stream
674
675 :param src_if: Source interface
676 :param dst: Destination IPv4 address
677 :param sport: Source TCP port
678 :param dport: Destination TCP port
679 :param data: Payload data
680 :param pref: NAT64 prefix
681 :param plen: NAT64 prefix length
682 :param fragsize: size of fragments
683 :returns: Fragmets
684 """
685 if pref is None:
686 dst_ip6 = ''.join(['64:ff9b::', dst])
687 else:
688 dst_ip6 = self.compose_ip6(dst, pref, plen)
689
690 p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
691 IPv6(src=src_if.remote_ip6, dst=dst_ip6) /
692 IPv6ExtHdrFragment(id=random.randint(0, 65535)) /
693 TCP(sport=sport, dport=dport) /
694 Raw(data))
695
696 return fragment6(p, frag_size)
697
698 def reass_frags_and_verify(self, frags, src, dst):
699 """
700 Reassemble and verify fragmented packet
701
702 :param frags: Captured fragments
703 :param src: Source IPv4 address to verify
704 :param dst: Destination IPv4 address to verify
705
706 :returns: Reassembled IPv4 packet
707 """
708 buffer = StringIO.StringIO()
709 for p in frags:
710 self.assertEqual(p[IP].src, src)
711 self.assertEqual(p[IP].dst, dst)
Klement Sekerad81ae412018-05-16 10:52:54 +0200712 self.assert_ip_checksum_valid(p)
Matus Fabianefcd1e92017-08-15 06:59:19 -0700713 buffer.seek(p[IP].frag * 8)
714 buffer.write(p[IP].payload)
715 ip = frags[0].getlayer(IP)
716 ip = IP(src=frags[0][IP].src, dst=frags[0][IP].dst,
717 proto=frags[0][IP].proto)
718 if ip.proto == IP_PROTOS.tcp:
719 p = (ip / TCP(buffer.getvalue()))
Klement Sekerad81ae412018-05-16 10:52:54 +0200720 self.assert_tcp_checksum_valid(p)
Matus Fabianefcd1e92017-08-15 06:59:19 -0700721 elif ip.proto == IP_PROTOS.udp:
722 p = (ip / UDP(buffer.getvalue()))
723 return p
724
725 def reass_frags_and_verify_ip6(self, frags, src, dst):
726 """
727 Reassemble and verify fragmented packet
728
729 :param frags: Captured fragments
730 :param src: Source IPv6 address to verify
731 :param dst: Destination IPv6 address to verify
732
733 :returns: Reassembled IPv6 packet
734 """
735 buffer = StringIO.StringIO()
736 for p in frags:
737 self.assertEqual(p[IPv6].src, src)
738 self.assertEqual(p[IPv6].dst, dst)
739 buffer.seek(p[IPv6ExtHdrFragment].offset * 8)
740 buffer.write(p[IPv6ExtHdrFragment].payload)
741 ip = IPv6(src=frags[0][IPv6].src, dst=frags[0][IPv6].dst,
742 nh=frags[0][IPv6ExtHdrFragment].nh)
743 if ip.nh == IP_PROTOS.tcp:
744 p = (ip / TCP(buffer.getvalue()))
Matus Fabianefcd1e92017-08-15 06:59:19 -0700745 elif ip.nh == IP_PROTOS.udp:
746 p = (ip / UDP(buffer.getvalue()))
Klement Sekerad81ae412018-05-16 10:52:54 +0200747 self.assert_packet_checksums_valid(p)
Matus Fabianefcd1e92017-08-15 06:59:19 -0700748 return p
749
Matus Fabianebdf1902018-05-04 03:57:42 -0700750 def initiate_tcp_session(self, in_if, out_if):
751 """
752 Initiates TCP session
753
754 :param in_if: Inside interface
755 :param out_if: Outside interface
756 """
757 try:
758 # SYN packet in->out
759 p = (Ether(src=in_if.remote_mac, dst=in_if.local_mac) /
760 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4) /
761 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
762 flags="S"))
763 in_if.add_stream(p)
764 self.pg_enable_capture(self.pg_interfaces)
765 self.pg_start()
766 capture = out_if.get_capture(1)
767 p = capture[0]
768 self.tcp_port_out = p[TCP].sport
769
770 # SYN + ACK packet out->in
771 p = (Ether(src=out_if.remote_mac, dst=out_if.local_mac) /
772 IP(src=out_if.remote_ip4, dst=self.nat_addr) /
773 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
774 flags="SA"))
775 out_if.add_stream(p)
776 self.pg_enable_capture(self.pg_interfaces)
777 self.pg_start()
778 in_if.get_capture(1)
779
780 # ACK packet in->out
781 p = (Ether(src=in_if.remote_mac, dst=in_if.local_mac) /
782 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4) /
783 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
784 flags="A"))
785 in_if.add_stream(p)
786 self.pg_enable_capture(self.pg_interfaces)
787 self.pg_start()
788 out_if.get_capture(1)
789
790 except:
791 self.logger.error("TCP 3 way handshake failed")
792 raise
793
Matus Fabianeea28d72017-01-13 04:15:54 -0800794 def verify_ipfix_nat44_ses(self, data):
795 """
796 Verify IPFIX NAT44 session create/delete event
797
798 :param data: Decoded IPFIX data records
799 """
800 nat44_ses_create_num = 0
801 nat44_ses_delete_num = 0
802 self.assertEqual(6, len(data))
803 for record in data:
804 # natEvent
805 self.assertIn(ord(record[230]), [4, 5])
806 if ord(record[230]) == 4:
807 nat44_ses_create_num += 1
808 else:
809 nat44_ses_delete_num += 1
810 # sourceIPv4Address
811 self.assertEqual(self.pg0.remote_ip4n, record[8])
812 # postNATSourceIPv4Address
Matus Fabian2ba92e32017-08-21 07:05:03 -0700813 self.assertEqual(socket.inet_pton(socket.AF_INET, self.nat_addr),
Matus Fabianeea28d72017-01-13 04:15:54 -0800814 record[225])
815 # ingressVRFID
816 self.assertEqual(struct.pack("!I", 0), record[234])
817 # protocolIdentifier/sourceTransportPort/postNAPTSourceTransportPort
818 if IP_PROTOS.icmp == ord(record[4]):
819 self.assertEqual(struct.pack("!H", self.icmp_id_in), record[7])
820 self.assertEqual(struct.pack("!H", self.icmp_id_out),
821 record[227])
822 elif IP_PROTOS.tcp == ord(record[4]):
823 self.assertEqual(struct.pack("!H", self.tcp_port_in),
824 record[7])
825 self.assertEqual(struct.pack("!H", self.tcp_port_out),
826 record[227])
827 elif IP_PROTOS.udp == ord(record[4]):
828 self.assertEqual(struct.pack("!H", self.udp_port_in),
829 record[7])
830 self.assertEqual(struct.pack("!H", self.udp_port_out),
831 record[227])
832 else:
833 self.fail("Invalid protocol")
834 self.assertEqual(3, nat44_ses_create_num)
835 self.assertEqual(3, nat44_ses_delete_num)
836
837 def verify_ipfix_addr_exhausted(self, data):
838 """
839 Verify IPFIX NAT addresses event
840
841 :param data: Decoded IPFIX data records
842 """
843 self.assertEqual(1, len(data))
844 record = data[0]
845 # natEvent
846 self.assertEqual(ord(record[230]), 3)
847 # natPoolID
848 self.assertEqual(struct.pack("!I", 0), record[283])
849
Matus Fabiana431ad12018-01-04 04:03:14 -0800850 def verify_ipfix_max_sessions(self, data, limit):
851 """
852 Verify IPFIX maximum session entries exceeded event
853
854 :param data: Decoded IPFIX data records
855 :param limit: Number of maximum session entries that can be created.
856 """
857 self.assertEqual(1, len(data))
858 record = data[0]
859 # natEvent
860 self.assertEqual(ord(record[230]), 13)
861 # natQuotaExceededEvent
862 self.assertEqual(struct.pack("I", 1), record[466])
863 # maxSessionEntries
864 self.assertEqual(struct.pack("I", limit), record[471])
865
866 def verify_ipfix_max_bibs(self, data, limit):
867 """
868 Verify IPFIX maximum BIB entries exceeded event
869
870 :param data: Decoded IPFIX data records
871 :param limit: Number of maximum BIB entries that can be created.
872 """
873 self.assertEqual(1, len(data))
874 record = data[0]
875 # natEvent
876 self.assertEqual(ord(record[230]), 13)
877 # natQuotaExceededEvent
878 self.assertEqual(struct.pack("I", 2), record[466])
879 # maxBIBEntries
880 self.assertEqual(struct.pack("I", limit), record[472])
881
882 def verify_ipfix_max_fragments_ip6(self, data, limit, src_addr):
883 """
884 Verify IPFIX maximum IPv6 fragments pending reassembly exceeded event
885
886 :param data: Decoded IPFIX data records
887 :param limit: Number of maximum fragments pending reassembly
888 :param src_addr: IPv6 source address
889 """
890 self.assertEqual(1, len(data))
891 record = data[0]
892 # natEvent
893 self.assertEqual(ord(record[230]), 13)
894 # natQuotaExceededEvent
895 self.assertEqual(struct.pack("I", 5), record[466])
896 # maxFragmentsPendingReassembly
897 self.assertEqual(struct.pack("I", limit), record[475])
898 # sourceIPv6Address
899 self.assertEqual(src_addr, record[27])
900
901 def verify_ipfix_max_fragments_ip4(self, data, limit, src_addr):
902 """
903 Verify IPFIX maximum IPv4 fragments pending reassembly exceeded event
904
905 :param data: Decoded IPFIX data records
906 :param limit: Number of maximum fragments pending reassembly
907 :param src_addr: IPv4 source address
908 """
909 self.assertEqual(1, len(data))
910 record = data[0]
911 # natEvent
912 self.assertEqual(ord(record[230]), 13)
913 # natQuotaExceededEvent
914 self.assertEqual(struct.pack("I", 5), record[466])
915 # maxFragmentsPendingReassembly
916 self.assertEqual(struct.pack("I", limit), record[475])
917 # sourceIPv4Address
918 self.assertEqual(src_addr, record[8])
919
920 def verify_ipfix_bib(self, data, is_create, src_addr):
921 """
922 Verify IPFIX NAT64 BIB create and delete events
923
924 :param data: Decoded IPFIX data records
925 :param is_create: Create event if nonzero value otherwise delete event
926 :param src_addr: IPv6 source address
927 """
928 self.assertEqual(1, len(data))
929 record = data[0]
930 # natEvent
931 if is_create:
932 self.assertEqual(ord(record[230]), 10)
933 else:
934 self.assertEqual(ord(record[230]), 11)
935 # sourceIPv6Address
936 self.assertEqual(src_addr, record[27])
937 # postNATSourceIPv4Address
938 self.assertEqual(self.nat_addr_n, record[225])
939 # protocolIdentifier
940 self.assertEqual(IP_PROTOS.tcp, ord(record[4]))
941 # ingressVRFID
942 self.assertEqual(struct.pack("!I", 0), record[234])
943 # sourceTransportPort
944 self.assertEqual(struct.pack("!H", self.tcp_port_in), record[7])
945 # postNAPTSourceTransportPort
946 self.assertEqual(struct.pack("!H", self.tcp_port_out), record[227])
947
948 def verify_ipfix_nat64_ses(self, data, is_create, src_addr, dst_addr,
949 dst_port):
950 """
951 Verify IPFIX NAT64 session create and delete events
952
953 :param data: Decoded IPFIX data records
954 :param is_create: Create event if nonzero value otherwise delete event
955 :param src_addr: IPv6 source address
956 :param dst_addr: IPv4 destination address
957 :param dst_port: destination TCP port
958 """
959 self.assertEqual(1, len(data))
960 record = data[0]
961 # natEvent
962 if is_create:
963 self.assertEqual(ord(record[230]), 6)
964 else:
965 self.assertEqual(ord(record[230]), 7)
966 # sourceIPv6Address
967 self.assertEqual(src_addr, record[27])
968 # destinationIPv6Address
969 self.assertEqual(socket.inet_pton(socket.AF_INET6,
970 self.compose_ip6(dst_addr,
971 '64:ff9b::',
972 96)),
973 record[28])
974 # postNATSourceIPv4Address
975 self.assertEqual(self.nat_addr_n, record[225])
976 # postNATDestinationIPv4Address
977 self.assertEqual(socket.inet_pton(socket.AF_INET, dst_addr),
978 record[226])
979 # protocolIdentifier
980 self.assertEqual(IP_PROTOS.tcp, ord(record[4]))
981 # ingressVRFID
982 self.assertEqual(struct.pack("!I", 0), record[234])
983 # sourceTransportPort
984 self.assertEqual(struct.pack("!H", self.tcp_port_in), record[7])
985 # postNAPTSourceTransportPort
986 self.assertEqual(struct.pack("!H", self.tcp_port_out), record[227])
987 # destinationTransportPort
988 self.assertEqual(struct.pack("!H", dst_port), record[11])
989 # postNAPTDestinationTransportPort
990 self.assertEqual(struct.pack("!H", dst_port), record[228])
991
Matus Fabian68ba8802018-08-08 05:52:47 -0700992 def verify_no_nat44_user(self):
993 """ Verify that there is no NAT44 user """
994 users = self.vapi.nat44_user_dump()
995 self.assertEqual(len(users), 0)
996
Matus Fabian878c6462018-08-23 00:33:35 -0700997 def verify_ipfix_max_entries_per_user(self, data, limit, src_addr):
998 """
999 Verify IPFIX maximum entries per user exceeded event
1000
1001 :param data: Decoded IPFIX data records
1002 :param limit: Number of maximum entries per user
1003 :param src_addr: IPv4 source address
1004 """
1005 self.assertEqual(1, len(data))
1006 record = data[0]
1007 # natEvent
1008 self.assertEqual(ord(record[230]), 13)
1009 # natQuotaExceededEvent
1010 self.assertEqual(struct.pack("I", 3), record[466])
1011 # maxEntriesPerUser
1012 self.assertEqual(struct.pack("I", limit), record[473])
1013 # sourceIPv4Address
1014 self.assertEqual(src_addr, record[8])
1015
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001016
Matus Fabian2ba92e32017-08-21 07:05:03 -07001017class TestNAT44(MethodHolder):
1018 """ NAT44 Test Cases """
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001019
1020 @classmethod
1021 def setUpClass(cls):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001022 super(TestNAT44, cls).setUpClass()
Matus Fabian229c1aa2018-05-28 04:09:52 -07001023 cls.vapi.cli("set log class nat level debug")
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001024
1025 try:
1026 cls.tcp_port_in = 6303
1027 cls.tcp_port_out = 6303
1028 cls.udp_port_in = 6304
1029 cls.udp_port_out = 6304
1030 cls.icmp_id_in = 6305
1031 cls.icmp_id_out = 6305
Matus Fabian2ba92e32017-08-21 07:05:03 -07001032 cls.nat_addr = '10.0.0.3'
Juraj Sloboda7b929792017-11-23 13:20:48 +01001033 cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
Matus Fabian6631e9c2017-05-24 01:52:20 -07001034 cls.ipfix_src_port = 4739
1035 cls.ipfix_domain_id = 1
Matus Fabianebdf1902018-05-04 03:57:42 -07001036 cls.tcp_external_port = 80
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001037
Matus Fabian36ea2d62017-10-24 04:13:49 -07001038 cls.create_pg_interfaces(range(10))
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001039 cls.interfaces = list(cls.pg_interfaces[0:4])
1040
1041 for i in cls.interfaces:
1042 i.admin_up()
1043 i.config_ip4()
1044 i.resolve_arp()
1045
Matus Fabian6fa74c62017-06-05 05:55:48 -07001046 cls.pg0.generate_remote_hosts(3)
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001047 cls.pg0.configure_ipv4_neighbors()
1048
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02001049 cls.pg1.generate_remote_hosts(1)
1050 cls.pg1.configure_ipv4_neighbors()
1051
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001052 cls.overlapping_interfaces = list(list(cls.pg_interfaces[4:7]))
Neale Ranns15002542017-09-10 04:39:11 -07001053 cls.vapi.ip_table_add_del(10, is_add=1)
1054 cls.vapi.ip_table_add_del(20, is_add=1)
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001055
1056 cls.pg4._local_ip4 = "172.16.255.1"
1057 cls.pg4._local_ip4n = socket.inet_pton(socket.AF_INET, i.local_ip4)
1058 cls.pg4._remote_hosts[0]._ip4 = "172.16.255.2"
1059 cls.pg4.set_table_ip4(10)
Matus Fabian69126282017-08-14 23:39:58 -07001060 cls.pg5._local_ip4 = "172.17.255.3"
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001061 cls.pg5._local_ip4n = socket.inet_pton(socket.AF_INET, i.local_ip4)
Matus Fabian69126282017-08-14 23:39:58 -07001062 cls.pg5._remote_hosts[0]._ip4 = "172.17.255.4"
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001063 cls.pg5.set_table_ip4(10)
1064 cls.pg6._local_ip4 = "172.16.255.1"
1065 cls.pg6._local_ip4n = socket.inet_pton(socket.AF_INET, i.local_ip4)
1066 cls.pg6._remote_hosts[0]._ip4 = "172.16.255.2"
1067 cls.pg6.set_table_ip4(20)
1068 for i in cls.overlapping_interfaces:
1069 i.config_ip4()
1070 i.admin_up()
1071 i.resolve_arp()
1072
1073 cls.pg7.admin_up()
Martin Gálik406eb1d2017-05-04 04:35:04 -07001074 cls.pg8.admin_up()
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001075
Matus Fabian36ea2d62017-10-24 04:13:49 -07001076 cls.pg9.generate_remote_hosts(2)
1077 cls.pg9.config_ip4()
1078 ip_addr_n = socket.inet_pton(socket.AF_INET, "10.0.0.1")
1079 cls.vapi.sw_interface_add_del_address(cls.pg9.sw_if_index,
1080 ip_addr_n,
1081 24)
1082 cls.pg9.admin_up()
1083 cls.pg9.resolve_arp()
1084 cls.pg9._remote_hosts[1]._ip4 = cls.pg9._remote_hosts[0]._ip4
1085 cls.pg4._remote_ip4 = cls.pg9._remote_hosts[0]._ip4 = "10.0.0.2"
1086 cls.pg9.resolve_arp()
1087
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001088 except Exception:
Matus Fabian2ba92e32017-08-21 07:05:03 -07001089 super(TestNAT44, cls).tearDownClass()
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001090 raise
1091
Matus Fabiande886752016-12-07 03:38:19 -08001092 def test_dynamic(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001093 """ NAT44 dynamic translation test """
Matus Fabiande886752016-12-07 03:38:19 -08001094
Matus Fabian2ba92e32017-08-21 07:05:03 -07001095 self.nat44_add_address(self.nat_addr)
1096 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1097 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1098 is_inside=0)
Matus Fabiande886752016-12-07 03:38:19 -08001099
1100 # in2out
1101 pkts = self.create_stream_in(self.pg0, self.pg1)
1102 self.pg0.add_stream(pkts)
1103 self.pg_enable_capture(self.pg_interfaces)
1104 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001105 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001106 self.verify_capture_out(capture)
1107
1108 # out2in
1109 pkts = self.create_stream_out(self.pg1)
1110 self.pg1.add_stream(pkts)
1111 self.pg_enable_capture(self.pg_interfaces)
1112 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001113 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001114 self.verify_capture_in(capture, self.pg0)
1115
Juraj Slobodab33f4132017-02-08 23:54:21 -08001116 def test_dynamic_icmp_errors_in2out_ttl_1(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001117 """ NAT44 handling of client packets with TTL=1 """
Juraj Slobodab33f4132017-02-08 23:54:21 -08001118
Matus Fabian2ba92e32017-08-21 07:05:03 -07001119 self.nat44_add_address(self.nat_addr)
1120 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1121 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1122 is_inside=0)
Juraj Slobodab33f4132017-02-08 23:54:21 -08001123
1124 # Client side - generate traffic
1125 pkts = self.create_stream_in(self.pg0, self.pg1, ttl=1)
1126 self.pg0.add_stream(pkts)
1127 self.pg_enable_capture(self.pg_interfaces)
1128 self.pg_start()
1129
1130 # Client side - verify ICMP type 11 packets
1131 capture = self.pg0.get_capture(len(pkts))
1132 self.verify_capture_in_with_icmp_errors(capture, self.pg0)
1133
1134 def test_dynamic_icmp_errors_out2in_ttl_1(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001135 """ NAT44 handling of server packets with TTL=1 """
Juraj Slobodab33f4132017-02-08 23:54:21 -08001136
Matus Fabian2ba92e32017-08-21 07:05:03 -07001137 self.nat44_add_address(self.nat_addr)
1138 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1139 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1140 is_inside=0)
Juraj Slobodab33f4132017-02-08 23:54:21 -08001141
1142 # Client side - create sessions
1143 pkts = self.create_stream_in(self.pg0, self.pg1)
1144 self.pg0.add_stream(pkts)
1145 self.pg_enable_capture(self.pg_interfaces)
1146 self.pg_start()
1147
1148 # Server side - generate traffic
1149 capture = self.pg1.get_capture(len(pkts))
1150 self.verify_capture_out(capture)
1151 pkts = self.create_stream_out(self.pg1, ttl=1)
1152 self.pg1.add_stream(pkts)
1153 self.pg_enable_capture(self.pg_interfaces)
1154 self.pg_start()
1155
1156 # Server side - verify ICMP type 11 packets
1157 capture = self.pg1.get_capture(len(pkts))
1158 self.verify_capture_out_with_icmp_errors(capture,
1159 src_ip=self.pg1.local_ip4)
1160
1161 def test_dynamic_icmp_errors_in2out_ttl_2(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001162 """ NAT44 handling of error responses to client packets with TTL=2 """
Juraj Slobodab33f4132017-02-08 23:54:21 -08001163
Matus Fabian2ba92e32017-08-21 07:05:03 -07001164 self.nat44_add_address(self.nat_addr)
1165 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1166 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1167 is_inside=0)
Juraj Slobodab33f4132017-02-08 23:54:21 -08001168
1169 # Client side - generate traffic
1170 pkts = self.create_stream_in(self.pg0, self.pg1, ttl=2)
1171 self.pg0.add_stream(pkts)
1172 self.pg_enable_capture(self.pg_interfaces)
1173 self.pg_start()
1174
1175 # Server side - simulate ICMP type 11 response
1176 capture = self.pg1.get_capture(len(pkts))
1177 pkts = [Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07001178 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Juraj Slobodab33f4132017-02-08 23:54:21 -08001179 ICMP(type=11) / packet[IP] for packet in capture]
1180 self.pg1.add_stream(pkts)
1181 self.pg_enable_capture(self.pg_interfaces)
1182 self.pg_start()
1183
1184 # Client side - verify ICMP type 11 packets
1185 capture = self.pg0.get_capture(len(pkts))
1186 self.verify_capture_in_with_icmp_errors(capture, self.pg0)
1187
1188 def test_dynamic_icmp_errors_out2in_ttl_2(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001189 """ NAT44 handling of error responses to server packets with TTL=2 """
Juraj Slobodab33f4132017-02-08 23:54:21 -08001190
Matus Fabian2ba92e32017-08-21 07:05:03 -07001191 self.nat44_add_address(self.nat_addr)
1192 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1193 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1194 is_inside=0)
Juraj Slobodab33f4132017-02-08 23:54:21 -08001195
1196 # Client side - create sessions
1197 pkts = self.create_stream_in(self.pg0, self.pg1)
1198 self.pg0.add_stream(pkts)
1199 self.pg_enable_capture(self.pg_interfaces)
1200 self.pg_start()
1201
1202 # Server side - generate traffic
1203 capture = self.pg1.get_capture(len(pkts))
1204 self.verify_capture_out(capture)
1205 pkts = self.create_stream_out(self.pg1, ttl=2)
1206 self.pg1.add_stream(pkts)
1207 self.pg_enable_capture(self.pg_interfaces)
1208 self.pg_start()
1209
1210 # Client side - simulate ICMP type 11 response
1211 capture = self.pg0.get_capture(len(pkts))
1212 pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1213 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
1214 ICMP(type=11) / packet[IP] for packet in capture]
1215 self.pg0.add_stream(pkts)
1216 self.pg_enable_capture(self.pg_interfaces)
1217 self.pg_start()
1218
1219 # Server side - verify ICMP type 11 packets
1220 capture = self.pg1.get_capture(len(pkts))
1221 self.verify_capture_out_with_icmp_errors(capture)
1222
Juraj Sloboda665e4822017-02-16 17:17:19 -08001223 def test_ping_out_interface_from_outside(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001224 """ Ping NAT44 out interface from outside network """
Juraj Sloboda665e4822017-02-16 17:17:19 -08001225
Matus Fabian2ba92e32017-08-21 07:05:03 -07001226 self.nat44_add_address(self.nat_addr)
1227 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1228 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1229 is_inside=0)
Juraj Sloboda665e4822017-02-16 17:17:19 -08001230
1231 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1232 IP(src=self.pg1.remote_ip4, dst=self.pg1.local_ip4) /
1233 ICMP(id=self.icmp_id_out, type='echo-request'))
1234 pkts = [p]
1235 self.pg1.add_stream(pkts)
1236 self.pg_enable_capture(self.pg_interfaces)
1237 self.pg_start()
1238 capture = self.pg1.get_capture(len(pkts))
1239 self.assertEqual(1, len(capture))
1240 packet = capture[0]
1241 try:
1242 self.assertEqual(packet[IP].src, self.pg1.local_ip4)
1243 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
1244 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
1245 self.assertEqual(packet[ICMP].type, 0) # echo reply
1246 except:
1247 self.logger.error(ppp("Unexpected or invalid packet "
1248 "(outside network):", packet))
1249 raise
1250
Juraj Slobodad3677682017-04-14 03:24:45 +02001251 def test_ping_internal_host_from_outside(self):
1252 """ Ping internal host from outside network """
1253
Matus Fabian2ba92e32017-08-21 07:05:03 -07001254 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr)
1255 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1256 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1257 is_inside=0)
Juraj Slobodad3677682017-04-14 03:24:45 +02001258
1259 # out2in
1260 pkt = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07001261 IP(src=self.pg1.remote_ip4, dst=self.nat_addr, ttl=64) /
Juraj Slobodad3677682017-04-14 03:24:45 +02001262 ICMP(id=self.icmp_id_out, type='echo-request'))
1263 self.pg1.add_stream(pkt)
1264 self.pg_enable_capture(self.pg_interfaces)
1265 self.pg_start()
1266 capture = self.pg0.get_capture(1)
1267 self.verify_capture_in(capture, self.pg0, packet_num=1)
1268 self.assert_equal(capture[0][IP].proto, IP_PROTOS.icmp)
1269
1270 # in2out
1271 pkt = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1272 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4, ttl=64) /
1273 ICMP(id=self.icmp_id_in, type='echo-reply'))
1274 self.pg0.add_stream(pkt)
1275 self.pg_enable_capture(self.pg_interfaces)
1276 self.pg_start()
1277 capture = self.pg1.get_capture(1)
1278 self.verify_capture_out(capture, same_port=True, packet_num=1)
1279 self.assert_equal(capture[0][IP].proto, IP_PROTOS.icmp)
1280
Matus Fabianc79396e2018-07-23 00:05:22 -07001281 def test_forwarding(self):
Juraj Sloboda7b929792017-11-23 13:20:48 +01001282 """ NAT44 forwarding test """
1283
1284 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1285 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1286 is_inside=0)
1287 self.vapi.nat44_forwarding_enable_disable(1)
1288
1289 real_ip = self.pg0.remote_ip4n
1290 alias_ip = self.nat_addr_n
1291 self.vapi.nat44_add_del_static_mapping(local_ip=real_ip,
1292 external_ip=alias_ip)
1293
1294 try:
Matus Fabianc79396e2018-07-23 00:05:22 -07001295 # static mapping match
Juraj Sloboda7b929792017-11-23 13:20:48 +01001296
1297 pkts = self.create_stream_out(self.pg1)
1298 self.pg1.add_stream(pkts)
1299 self.pg_enable_capture(self.pg_interfaces)
1300 self.pg_start()
1301 capture = self.pg0.get_capture(len(pkts))
1302 self.verify_capture_in(capture, self.pg0)
1303
1304 pkts = self.create_stream_in(self.pg0, self.pg1)
1305 self.pg0.add_stream(pkts)
1306 self.pg_enable_capture(self.pg_interfaces)
1307 self.pg_start()
1308 capture = self.pg1.get_capture(len(pkts))
1309 self.verify_capture_out(capture, same_port=True)
1310
Matus Fabianc79396e2018-07-23 00:05:22 -07001311 # no static mapping match
Juraj Sloboda7b929792017-11-23 13:20:48 +01001312
1313 host0 = self.pg0.remote_hosts[0]
1314 self.pg0.remote_hosts[0] = self.pg0.remote_hosts[1]
1315 try:
1316 pkts = self.create_stream_out(self.pg1,
1317 dst_ip=self.pg0.remote_ip4,
1318 use_inside_ports=True)
1319 self.pg1.add_stream(pkts)
1320 self.pg_enable_capture(self.pg_interfaces)
1321 self.pg_start()
1322 capture = self.pg0.get_capture(len(pkts))
1323 self.verify_capture_in(capture, self.pg0)
1324
1325 pkts = self.create_stream_in(self.pg0, self.pg1)
1326 self.pg0.add_stream(pkts)
1327 self.pg_enable_capture(self.pg_interfaces)
1328 self.pg_start()
1329 capture = self.pg1.get_capture(len(pkts))
1330 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
1331 same_port=True)
1332 finally:
1333 self.pg0.remote_hosts[0] = host0
1334
1335 finally:
1336 self.vapi.nat44_forwarding_enable_disable(0)
1337 self.vapi.nat44_add_del_static_mapping(local_ip=real_ip,
1338 external_ip=alias_ip,
1339 is_add=0)
1340
Matus Fabiande886752016-12-07 03:38:19 -08001341 def test_static_in(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001342 """ 1:1 NAT initialized from inside network """
Matus Fabiande886752016-12-07 03:38:19 -08001343
1344 nat_ip = "10.0.0.10"
1345 self.tcp_port_out = 6303
1346 self.udp_port_out = 6304
1347 self.icmp_id_out = 6305
1348
Matus Fabian2ba92e32017-08-21 07:05:03 -07001349 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
1350 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1351 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1352 is_inside=0)
Matus Fabian5f224992018-01-25 21:59:16 -08001353 sm = self.vapi.nat44_static_mapping_dump()
1354 self.assertEqual(len(sm), 1)
1355 self.assertEqual((sm[0].tag).split('\0', 1)[0], '')
Matus Fabian9dba7812018-01-31 01:13:23 -08001356 self.assertEqual(sm[0].protocol, 0)
1357 self.assertEqual(sm[0].local_port, 0)
1358 self.assertEqual(sm[0].external_port, 0)
Matus Fabiande886752016-12-07 03:38:19 -08001359
1360 # in2out
1361 pkts = self.create_stream_in(self.pg0, self.pg1)
1362 self.pg0.add_stream(pkts)
1363 self.pg_enable_capture(self.pg_interfaces)
1364 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001365 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001366 self.verify_capture_out(capture, nat_ip, True)
1367
1368 # out2in
1369 pkts = self.create_stream_out(self.pg1, nat_ip)
1370 self.pg1.add_stream(pkts)
1371 self.pg_enable_capture(self.pg_interfaces)
1372 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001373 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001374 self.verify_capture_in(capture, self.pg0)
1375
1376 def test_static_out(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001377 """ 1:1 NAT initialized from outside network """
Matus Fabiande886752016-12-07 03:38:19 -08001378
1379 nat_ip = "10.0.0.20"
1380 self.tcp_port_out = 6303
1381 self.udp_port_out = 6304
1382 self.icmp_id_out = 6305
Matus Fabian5f224992018-01-25 21:59:16 -08001383 tag = "testTAG"
Matus Fabiande886752016-12-07 03:38:19 -08001384
Matus Fabian5f224992018-01-25 21:59:16 -08001385 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip, tag=tag)
Matus Fabian2ba92e32017-08-21 07:05:03 -07001386 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1387 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1388 is_inside=0)
Matus Fabian5f224992018-01-25 21:59:16 -08001389 sm = self.vapi.nat44_static_mapping_dump()
1390 self.assertEqual(len(sm), 1)
1391 self.assertEqual((sm[0].tag).split('\0', 1)[0], tag)
Matus Fabiande886752016-12-07 03:38:19 -08001392
1393 # out2in
1394 pkts = self.create_stream_out(self.pg1, nat_ip)
1395 self.pg1.add_stream(pkts)
1396 self.pg_enable_capture(self.pg_interfaces)
1397 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001398 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001399 self.verify_capture_in(capture, self.pg0)
1400
1401 # in2out
1402 pkts = self.create_stream_in(self.pg0, self.pg1)
1403 self.pg0.add_stream(pkts)
1404 self.pg_enable_capture(self.pg_interfaces)
1405 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001406 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001407 self.verify_capture_out(capture, nat_ip, True)
1408
1409 def test_static_with_port_in(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001410 """ 1:1 NAPT initialized from inside network """
Matus Fabiande886752016-12-07 03:38:19 -08001411
1412 self.tcp_port_out = 3606
1413 self.udp_port_out = 3607
1414 self.icmp_id_out = 3608
1415
Matus Fabian2ba92e32017-08-21 07:05:03 -07001416 self.nat44_add_address(self.nat_addr)
1417 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1418 self.tcp_port_in, self.tcp_port_out,
1419 proto=IP_PROTOS.tcp)
1420 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1421 self.udp_port_in, self.udp_port_out,
1422 proto=IP_PROTOS.udp)
1423 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1424 self.icmp_id_in, self.icmp_id_out,
1425 proto=IP_PROTOS.icmp)
1426 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1427 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1428 is_inside=0)
Matus Fabiande886752016-12-07 03:38:19 -08001429
1430 # in2out
1431 pkts = self.create_stream_in(self.pg0, self.pg1)
1432 self.pg0.add_stream(pkts)
1433 self.pg_enable_capture(self.pg_interfaces)
1434 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001435 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001436 self.verify_capture_out(capture)
1437
1438 # out2in
1439 pkts = self.create_stream_out(self.pg1)
1440 self.pg1.add_stream(pkts)
1441 self.pg_enable_capture(self.pg_interfaces)
1442 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001443 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001444 self.verify_capture_in(capture, self.pg0)
1445
1446 def test_static_with_port_out(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001447 """ 1:1 NAPT initialized from outside network """
Matus Fabiande886752016-12-07 03:38:19 -08001448
1449 self.tcp_port_out = 30606
1450 self.udp_port_out = 30607
1451 self.icmp_id_out = 30608
1452
Matus Fabian2ba92e32017-08-21 07:05:03 -07001453 self.nat44_add_address(self.nat_addr)
1454 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1455 self.tcp_port_in, self.tcp_port_out,
1456 proto=IP_PROTOS.tcp)
1457 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1458 self.udp_port_in, self.udp_port_out,
1459 proto=IP_PROTOS.udp)
1460 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1461 self.icmp_id_in, self.icmp_id_out,
1462 proto=IP_PROTOS.icmp)
1463 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1464 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1465 is_inside=0)
Matus Fabiande886752016-12-07 03:38:19 -08001466
1467 # out2in
1468 pkts = self.create_stream_out(self.pg1)
1469 self.pg1.add_stream(pkts)
1470 self.pg_enable_capture(self.pg_interfaces)
1471 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001472 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001473 self.verify_capture_in(capture, self.pg0)
1474
1475 # in2out
1476 pkts = self.create_stream_in(self.pg0, self.pg1)
1477 self.pg0.add_stream(pkts)
1478 self.pg_enable_capture(self.pg_interfaces)
1479 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001480 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001481 self.verify_capture_out(capture)
1482
1483 def test_static_vrf_aware(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001484 """ 1:1 NAT VRF awareness """
Matus Fabiande886752016-12-07 03:38:19 -08001485
1486 nat_ip1 = "10.0.0.30"
1487 nat_ip2 = "10.0.0.40"
1488 self.tcp_port_out = 6303
1489 self.udp_port_out = 6304
1490 self.icmp_id_out = 6305
1491
Matus Fabian2ba92e32017-08-21 07:05:03 -07001492 self.nat44_add_static_mapping(self.pg4.remote_ip4, nat_ip1,
1493 vrf_id=10)
1494 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip2,
1495 vrf_id=10)
1496 self.vapi.nat44_interface_add_del_feature(self.pg3.sw_if_index,
1497 is_inside=0)
1498 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1499 self.vapi.nat44_interface_add_del_feature(self.pg4.sw_if_index)
Matus Fabiande886752016-12-07 03:38:19 -08001500
Matus Fabian2ba92e32017-08-21 07:05:03 -07001501 # inside interface VRF match NAT44 static mapping VRF
Matus Fabiande886752016-12-07 03:38:19 -08001502 pkts = self.create_stream_in(self.pg4, self.pg3)
1503 self.pg4.add_stream(pkts)
1504 self.pg_enable_capture(self.pg_interfaces)
1505 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001506 capture = self.pg3.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001507 self.verify_capture_out(capture, nat_ip1, True)
1508
Matus Fabian2ba92e32017-08-21 07:05:03 -07001509 # inside interface VRF don't match NAT44 static mapping VRF (packets
Matus Fabiande886752016-12-07 03:38:19 -08001510 # are dropped)
1511 pkts = self.create_stream_in(self.pg0, self.pg3)
1512 self.pg0.add_stream(pkts)
1513 self.pg_enable_capture(self.pg_interfaces)
1514 self.pg_start()
Klement Sekera9225dee2016-12-12 08:36:58 +01001515 self.pg3.assert_nothing_captured()
Matus Fabiande886752016-12-07 03:38:19 -08001516
Matus Fabianb793d092018-01-31 05:50:21 -08001517 def test_dynamic_to_static(self):
1518 """ Switch from dynamic translation to 1:1NAT """
1519 nat_ip = "10.0.0.10"
1520 self.tcp_port_out = 6303
1521 self.udp_port_out = 6304
1522 self.icmp_id_out = 6305
1523
1524 self.nat44_add_address(self.nat_addr)
1525 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1526 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1527 is_inside=0)
1528
1529 # dynamic
1530 pkts = self.create_stream_in(self.pg0, self.pg1)
1531 self.pg0.add_stream(pkts)
1532 self.pg_enable_capture(self.pg_interfaces)
1533 self.pg_start()
1534 capture = self.pg1.get_capture(len(pkts))
1535 self.verify_capture_out(capture)
1536
1537 # 1:1NAT
1538 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
1539 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
1540 self.assertEqual(len(sessions), 0)
1541 pkts = self.create_stream_in(self.pg0, self.pg1)
1542 self.pg0.add_stream(pkts)
1543 self.pg_enable_capture(self.pg_interfaces)
1544 self.pg_start()
1545 capture = self.pg1.get_capture(len(pkts))
1546 self.verify_capture_out(capture, nat_ip, True)
1547
Matus Fabianab7a8052017-11-28 04:29:41 -08001548 def test_identity_nat(self):
1549 """ Identity NAT """
1550
1551 self.vapi.nat44_add_del_identity_mapping(ip=self.pg0.remote_ip4n)
1552 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1553 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1554 is_inside=0)
1555
1556 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
1557 IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
1558 TCP(sport=12345, dport=56789))
1559 self.pg1.add_stream(p)
1560 self.pg_enable_capture(self.pg_interfaces)
1561 self.pg_start()
1562 capture = self.pg0.get_capture(1)
1563 p = capture[0]
1564 try:
1565 ip = p[IP]
1566 tcp = p[TCP]
1567 self.assertEqual(ip.dst, self.pg0.remote_ip4)
1568 self.assertEqual(ip.src, self.pg1.remote_ip4)
1569 self.assertEqual(tcp.dport, 56789)
1570 self.assertEqual(tcp.sport, 12345)
Klement Sekerad81ae412018-05-16 10:52:54 +02001571 self.assert_packet_checksums_valid(p)
Matus Fabianab7a8052017-11-28 04:29:41 -08001572 except:
1573 self.logger.error(ppp("Unexpected or invalid packet:", p))
1574 raise
1575
Matus Fabiande886752016-12-07 03:38:19 -08001576 def test_multiple_inside_interfaces(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001577 """ NAT44 multiple non-overlapping address space inside interfaces """
Matus Fabiande886752016-12-07 03:38:19 -08001578
Matus Fabian2ba92e32017-08-21 07:05:03 -07001579 self.nat44_add_address(self.nat_addr)
1580 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1581 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
1582 self.vapi.nat44_interface_add_del_feature(self.pg3.sw_if_index,
1583 is_inside=0)
Matus Fabiande886752016-12-07 03:38:19 -08001584
Matus Fabian2ba92e32017-08-21 07:05:03 -07001585 # between two NAT44 inside interfaces (no translation)
Matus Fabian675a69c2017-01-18 01:46:01 -08001586 pkts = self.create_stream_in(self.pg0, self.pg1)
1587 self.pg0.add_stream(pkts)
1588 self.pg_enable_capture(self.pg_interfaces)
1589 self.pg_start()
1590 capture = self.pg1.get_capture(len(pkts))
1591 self.verify_capture_no_translation(capture, self.pg0, self.pg1)
1592
Matus Fabian2ba92e32017-08-21 07:05:03 -07001593 # from NAT44 inside to interface without NAT44 feature (no translation)
Matus Fabian675a69c2017-01-18 01:46:01 -08001594 pkts = self.create_stream_in(self.pg0, self.pg2)
1595 self.pg0.add_stream(pkts)
1596 self.pg_enable_capture(self.pg_interfaces)
1597 self.pg_start()
1598 capture = self.pg2.get_capture(len(pkts))
1599 self.verify_capture_no_translation(capture, self.pg0, self.pg2)
1600
Matus Fabiande886752016-12-07 03:38:19 -08001601 # in2out 1st interface
1602 pkts = self.create_stream_in(self.pg0, self.pg3)
1603 self.pg0.add_stream(pkts)
1604 self.pg_enable_capture(self.pg_interfaces)
1605 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001606 capture = self.pg3.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001607 self.verify_capture_out(capture)
1608
1609 # out2in 1st interface
1610 pkts = self.create_stream_out(self.pg3)
1611 self.pg3.add_stream(pkts)
1612 self.pg_enable_capture(self.pg_interfaces)
1613 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001614 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001615 self.verify_capture_in(capture, self.pg0)
1616
1617 # in2out 2nd interface
1618 pkts = self.create_stream_in(self.pg1, self.pg3)
1619 self.pg1.add_stream(pkts)
1620 self.pg_enable_capture(self.pg_interfaces)
1621 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001622 capture = self.pg3.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001623 self.verify_capture_out(capture)
1624
1625 # out2in 2nd interface
1626 pkts = self.create_stream_out(self.pg3)
1627 self.pg3.add_stream(pkts)
1628 self.pg_enable_capture(self.pg_interfaces)
1629 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001630 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001631 self.verify_capture_in(capture, self.pg1)
1632
Matus Fabiande886752016-12-07 03:38:19 -08001633 def test_inside_overlapping_interfaces(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001634 """ NAT44 multiple inside interfaces with overlapping address space """
Matus Fabiande886752016-12-07 03:38:19 -08001635
Matus Fabian675a69c2017-01-18 01:46:01 -08001636 static_nat_ip = "10.0.0.10"
Matus Fabian2ba92e32017-08-21 07:05:03 -07001637 self.nat44_add_address(self.nat_addr)
1638 self.vapi.nat44_interface_add_del_feature(self.pg3.sw_if_index,
1639 is_inside=0)
1640 self.vapi.nat44_interface_add_del_feature(self.pg4.sw_if_index)
1641 self.vapi.nat44_interface_add_del_feature(self.pg5.sw_if_index)
1642 self.vapi.nat44_interface_add_del_feature(self.pg6.sw_if_index)
1643 self.nat44_add_static_mapping(self.pg6.remote_ip4, static_nat_ip,
1644 vrf_id=20)
Matus Fabian675a69c2017-01-18 01:46:01 -08001645
Matus Fabian2ba92e32017-08-21 07:05:03 -07001646 # between NAT44 inside interfaces with same VRF (no translation)
Matus Fabian675a69c2017-01-18 01:46:01 -08001647 pkts = self.create_stream_in(self.pg4, self.pg5)
1648 self.pg4.add_stream(pkts)
1649 self.pg_enable_capture(self.pg_interfaces)
1650 self.pg_start()
1651 capture = self.pg5.get_capture(len(pkts))
1652 self.verify_capture_no_translation(capture, self.pg4, self.pg5)
1653
Matus Fabian2ba92e32017-08-21 07:05:03 -07001654 # between NAT44 inside interfaces with different VRF (hairpinning)
Matus Fabian675a69c2017-01-18 01:46:01 -08001655 p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
1656 IP(src=self.pg4.remote_ip4, dst=static_nat_ip) /
1657 TCP(sport=1234, dport=5678))
1658 self.pg4.add_stream(p)
1659 self.pg_enable_capture(self.pg_interfaces)
1660 self.pg_start()
1661 capture = self.pg6.get_capture(1)
1662 p = capture[0]
1663 try:
1664 ip = p[IP]
1665 tcp = p[TCP]
Matus Fabian2ba92e32017-08-21 07:05:03 -07001666 self.assertEqual(ip.src, self.nat_addr)
Matus Fabian675a69c2017-01-18 01:46:01 -08001667 self.assertEqual(ip.dst, self.pg6.remote_ip4)
1668 self.assertNotEqual(tcp.sport, 1234)
1669 self.assertEqual(tcp.dport, 5678)
1670 except:
1671 self.logger.error(ppp("Unexpected or invalid packet:", p))
1672 raise
Matus Fabiande886752016-12-07 03:38:19 -08001673
1674 # in2out 1st interface
1675 pkts = self.create_stream_in(self.pg4, self.pg3)
1676 self.pg4.add_stream(pkts)
1677 self.pg_enable_capture(self.pg_interfaces)
1678 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001679 capture = self.pg3.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001680 self.verify_capture_out(capture)
1681
1682 # out2in 1st interface
1683 pkts = self.create_stream_out(self.pg3)
1684 self.pg3.add_stream(pkts)
1685 self.pg_enable_capture(self.pg_interfaces)
1686 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001687 capture = self.pg4.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001688 self.verify_capture_in(capture, self.pg4)
1689
1690 # in2out 2nd interface
1691 pkts = self.create_stream_in(self.pg5, self.pg3)
1692 self.pg5.add_stream(pkts)
1693 self.pg_enable_capture(self.pg_interfaces)
1694 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001695 capture = self.pg3.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001696 self.verify_capture_out(capture)
1697
1698 # out2in 2nd interface
1699 pkts = self.create_stream_out(self.pg3)
1700 self.pg3.add_stream(pkts)
1701 self.pg_enable_capture(self.pg_interfaces)
1702 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001703 capture = self.pg5.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001704 self.verify_capture_in(capture, self.pg5)
1705
magalik23caa882017-02-08 23:25:45 -08001706 # pg5 session dump
Matus Fabian2ba92e32017-08-21 07:05:03 -07001707 addresses = self.vapi.nat44_address_dump()
magalik23caa882017-02-08 23:25:45 -08001708 self.assertEqual(len(addresses), 1)
Matus Fabian2ba92e32017-08-21 07:05:03 -07001709 sessions = self.vapi.nat44_user_session_dump(self.pg5.remote_ip4n, 10)
magalik23caa882017-02-08 23:25:45 -08001710 self.assertEqual(len(sessions), 3)
1711 for session in sessions:
1712 self.assertFalse(session.is_static)
1713 self.assertEqual(session.inside_ip_address[0:4],
1714 self.pg5.remote_ip4n)
1715 self.assertEqual(session.outside_ip_address,
1716 addresses[0].ip_address)
1717 self.assertEqual(sessions[0].protocol, IP_PROTOS.tcp)
1718 self.assertEqual(sessions[1].protocol, IP_PROTOS.udp)
1719 self.assertEqual(sessions[2].protocol, IP_PROTOS.icmp)
1720 self.assertEqual(sessions[0].inside_port, self.tcp_port_in)
1721 self.assertEqual(sessions[1].inside_port, self.udp_port_in)
1722 self.assertEqual(sessions[2].inside_port, self.icmp_id_in)
1723 self.assertEqual(sessions[0].outside_port, self.tcp_port_out)
1724 self.assertEqual(sessions[1].outside_port, self.udp_port_out)
1725 self.assertEqual(sessions[2].outside_port, self.icmp_id_out)
1726
Matus Fabiande886752016-12-07 03:38:19 -08001727 # in2out 3rd interface
1728 pkts = self.create_stream_in(self.pg6, self.pg3)
1729 self.pg6.add_stream(pkts)
1730 self.pg_enable_capture(self.pg_interfaces)
1731 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001732 capture = self.pg3.get_capture(len(pkts))
Matus Fabian675a69c2017-01-18 01:46:01 -08001733 self.verify_capture_out(capture, static_nat_ip, True)
Matus Fabiande886752016-12-07 03:38:19 -08001734
1735 # out2in 3rd interface
Matus Fabian675a69c2017-01-18 01:46:01 -08001736 pkts = self.create_stream_out(self.pg3, static_nat_ip)
Matus Fabiande886752016-12-07 03:38:19 -08001737 self.pg3.add_stream(pkts)
1738 self.pg_enable_capture(self.pg_interfaces)
1739 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001740 capture = self.pg6.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001741 self.verify_capture_in(capture, self.pg6)
1742
magalik23caa882017-02-08 23:25:45 -08001743 # general user and session dump verifications
Matus Fabian2ba92e32017-08-21 07:05:03 -07001744 users = self.vapi.nat44_user_dump()
magalik23caa882017-02-08 23:25:45 -08001745 self.assertTrue(len(users) >= 3)
Matus Fabian2ba92e32017-08-21 07:05:03 -07001746 addresses = self.vapi.nat44_address_dump()
magalik23caa882017-02-08 23:25:45 -08001747 self.assertEqual(len(addresses), 1)
1748 for user in users:
Matus Fabian2ba92e32017-08-21 07:05:03 -07001749 sessions = self.vapi.nat44_user_session_dump(user.ip_address,
1750 user.vrf_id)
magalik23caa882017-02-08 23:25:45 -08001751 for session in sessions:
1752 self.assertEqual(user.ip_address, session.inside_ip_address)
1753 self.assertTrue(session.total_bytes > session.total_pkts > 0)
1754 self.assertTrue(session.protocol in
1755 [IP_PROTOS.tcp, IP_PROTOS.udp,
1756 IP_PROTOS.icmp])
Matus Fabian70a26ac2018-05-14 06:20:28 -07001757 self.assertFalse(session.ext_host_valid)
magalik23caa882017-02-08 23:25:45 -08001758
1759 # pg4 session dump
Matus Fabian2ba92e32017-08-21 07:05:03 -07001760 sessions = self.vapi.nat44_user_session_dump(self.pg4.remote_ip4n, 10)
magalik23caa882017-02-08 23:25:45 -08001761 self.assertTrue(len(sessions) >= 4)
1762 for session in sessions:
1763 self.assertFalse(session.is_static)
1764 self.assertEqual(session.inside_ip_address[0:4],
1765 self.pg4.remote_ip4n)
1766 self.assertEqual(session.outside_ip_address,
1767 addresses[0].ip_address)
1768
1769 # pg6 session dump
Matus Fabian2ba92e32017-08-21 07:05:03 -07001770 sessions = self.vapi.nat44_user_session_dump(self.pg6.remote_ip4n, 20)
magalik23caa882017-02-08 23:25:45 -08001771 self.assertTrue(len(sessions) >= 3)
1772 for session in sessions:
1773 self.assertTrue(session.is_static)
1774 self.assertEqual(session.inside_ip_address[0:4],
1775 self.pg6.remote_ip4n)
1776 self.assertEqual(map(ord, session.outside_ip_address[0:4]),
1777 map(int, static_nat_ip.split('.')))
1778 self.assertTrue(session.inside_port in
1779 [self.tcp_port_in, self.udp_port_in,
1780 self.icmp_id_in])
1781
Matus Fabianf78a70d2016-12-12 04:30:39 -08001782 def test_hairpinning(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001783 """ NAT44 hairpinning - 1:1 NAPT """
Matus Fabianf78a70d2016-12-12 04:30:39 -08001784
1785 host = self.pg0.remote_hosts[0]
1786 server = self.pg0.remote_hosts[1]
1787 host_in_port = 1234
1788 host_out_port = 0
1789 server_in_port = 5678
1790 server_out_port = 8765
1791
Matus Fabian2ba92e32017-08-21 07:05:03 -07001792 self.nat44_add_address(self.nat_addr)
1793 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1794 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1795 is_inside=0)
Matus Fabianf78a70d2016-12-12 04:30:39 -08001796 # add static mapping for server
Matus Fabian2ba92e32017-08-21 07:05:03 -07001797 self.nat44_add_static_mapping(server.ip4, self.nat_addr,
1798 server_in_port, server_out_port,
1799 proto=IP_PROTOS.tcp)
Matus Fabianf78a70d2016-12-12 04:30:39 -08001800
1801 # send packet from host to server
1802 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07001803 IP(src=host.ip4, dst=self.nat_addr) /
Matus Fabianf78a70d2016-12-12 04:30:39 -08001804 TCP(sport=host_in_port, dport=server_out_port))
1805 self.pg0.add_stream(p)
1806 self.pg_enable_capture(self.pg_interfaces)
1807 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001808 capture = self.pg0.get_capture(1)
Matus Fabianf78a70d2016-12-12 04:30:39 -08001809 p = capture[0]
1810 try:
1811 ip = p[IP]
1812 tcp = p[TCP]
Matus Fabian2ba92e32017-08-21 07:05:03 -07001813 self.assertEqual(ip.src, self.nat_addr)
Matus Fabianf78a70d2016-12-12 04:30:39 -08001814 self.assertEqual(ip.dst, server.ip4)
1815 self.assertNotEqual(tcp.sport, host_in_port)
1816 self.assertEqual(tcp.dport, server_in_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02001817 self.assert_packet_checksums_valid(p)
Matus Fabianf78a70d2016-12-12 04:30:39 -08001818 host_out_port = tcp.sport
1819 except:
Klement Sekera9225dee2016-12-12 08:36:58 +01001820 self.logger.error(ppp("Unexpected or invalid packet:", p))
Matus Fabianf78a70d2016-12-12 04:30:39 -08001821 raise
1822
1823 # send reply from server to host
1824 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07001825 IP(src=server.ip4, dst=self.nat_addr) /
Matus Fabianf78a70d2016-12-12 04:30:39 -08001826 TCP(sport=server_in_port, dport=host_out_port))
1827 self.pg0.add_stream(p)
1828 self.pg_enable_capture(self.pg_interfaces)
1829 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001830 capture = self.pg0.get_capture(1)
Matus Fabianf78a70d2016-12-12 04:30:39 -08001831 p = capture[0]
1832 try:
1833 ip = p[IP]
1834 tcp = p[TCP]
Matus Fabian2ba92e32017-08-21 07:05:03 -07001835 self.assertEqual(ip.src, self.nat_addr)
Matus Fabianf78a70d2016-12-12 04:30:39 -08001836 self.assertEqual(ip.dst, host.ip4)
1837 self.assertEqual(tcp.sport, server_out_port)
1838 self.assertEqual(tcp.dport, host_in_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02001839 self.assert_packet_checksums_valid(p)
Matus Fabianf78a70d2016-12-12 04:30:39 -08001840 except:
Matus Fabiane82488f2018-01-18 03:38:45 -08001841 self.logger.error(ppp("Unexpected or invalid packet:", p))
Matus Fabianf78a70d2016-12-12 04:30:39 -08001842 raise
1843
Matus Fabian6fa74c62017-06-05 05:55:48 -07001844 def test_hairpinning2(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001845 """ NAT44 hairpinning - 1:1 NAT"""
Matus Fabian6fa74c62017-06-05 05:55:48 -07001846
1847 server1_nat_ip = "10.0.0.10"
1848 server2_nat_ip = "10.0.0.11"
1849 host = self.pg0.remote_hosts[0]
1850 server1 = self.pg0.remote_hosts[1]
1851 server2 = self.pg0.remote_hosts[2]
1852 server_tcp_port = 22
1853 server_udp_port = 20
1854
Matus Fabian2ba92e32017-08-21 07:05:03 -07001855 self.nat44_add_address(self.nat_addr)
1856 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1857 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1858 is_inside=0)
Matus Fabian6fa74c62017-06-05 05:55:48 -07001859
1860 # add static mapping for servers
Matus Fabian2ba92e32017-08-21 07:05:03 -07001861 self.nat44_add_static_mapping(server1.ip4, server1_nat_ip)
1862 self.nat44_add_static_mapping(server2.ip4, server2_nat_ip)
Matus Fabian6fa74c62017-06-05 05:55:48 -07001863
1864 # host to server1
1865 pkts = []
1866 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1867 IP(src=host.ip4, dst=server1_nat_ip) /
1868 TCP(sport=self.tcp_port_in, dport=server_tcp_port))
1869 pkts.append(p)
1870 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1871 IP(src=host.ip4, dst=server1_nat_ip) /
1872 UDP(sport=self.udp_port_in, dport=server_udp_port))
1873 pkts.append(p)
1874 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1875 IP(src=host.ip4, dst=server1_nat_ip) /
1876 ICMP(id=self.icmp_id_in, type='echo-request'))
1877 pkts.append(p)
1878 self.pg0.add_stream(pkts)
1879 self.pg_enable_capture(self.pg_interfaces)
1880 self.pg_start()
1881 capture = self.pg0.get_capture(len(pkts))
1882 for packet in capture:
1883 try:
Matus Fabian2ba92e32017-08-21 07:05:03 -07001884 self.assertEqual(packet[IP].src, self.nat_addr)
Matus Fabian6fa74c62017-06-05 05:55:48 -07001885 self.assertEqual(packet[IP].dst, server1.ip4)
1886 if packet.haslayer(TCP):
1887 self.assertNotEqual(packet[TCP].sport, self.tcp_port_in)
1888 self.assertEqual(packet[TCP].dport, server_tcp_port)
1889 self.tcp_port_out = packet[TCP].sport
Klement Sekerad81ae412018-05-16 10:52:54 +02001890 self.assert_packet_checksums_valid(packet)
Matus Fabian6fa74c62017-06-05 05:55:48 -07001891 elif packet.haslayer(UDP):
1892 self.assertNotEqual(packet[UDP].sport, self.udp_port_in)
1893 self.assertEqual(packet[UDP].dport, server_udp_port)
1894 self.udp_port_out = packet[UDP].sport
1895 else:
1896 self.assertNotEqual(packet[ICMP].id, self.icmp_id_in)
1897 self.icmp_id_out = packet[ICMP].id
1898 except:
1899 self.logger.error(ppp("Unexpected or invalid packet:", packet))
1900 raise
1901
1902 # server1 to host
1903 pkts = []
1904 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07001905 IP(src=server1.ip4, dst=self.nat_addr) /
Matus Fabian6fa74c62017-06-05 05:55:48 -07001906 TCP(sport=server_tcp_port, dport=self.tcp_port_out))
1907 pkts.append(p)
1908 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07001909 IP(src=server1.ip4, dst=self.nat_addr) /
Matus Fabian6fa74c62017-06-05 05:55:48 -07001910 UDP(sport=server_udp_port, dport=self.udp_port_out))
1911 pkts.append(p)
1912 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07001913 IP(src=server1.ip4, dst=self.nat_addr) /
Matus Fabian6fa74c62017-06-05 05:55:48 -07001914 ICMP(id=self.icmp_id_out, type='echo-reply'))
1915 pkts.append(p)
1916 self.pg0.add_stream(pkts)
1917 self.pg_enable_capture(self.pg_interfaces)
1918 self.pg_start()
1919 capture = self.pg0.get_capture(len(pkts))
1920 for packet in capture:
1921 try:
1922 self.assertEqual(packet[IP].src, server1_nat_ip)
1923 self.assertEqual(packet[IP].dst, host.ip4)
1924 if packet.haslayer(TCP):
1925 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
1926 self.assertEqual(packet[TCP].sport, server_tcp_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02001927 self.assert_packet_checksums_valid(packet)
Matus Fabian6fa74c62017-06-05 05:55:48 -07001928 elif packet.haslayer(UDP):
1929 self.assertEqual(packet[UDP].dport, self.udp_port_in)
1930 self.assertEqual(packet[UDP].sport, server_udp_port)
1931 else:
1932 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
1933 except:
1934 self.logger.error(ppp("Unexpected or invalid packet:", packet))
1935 raise
1936
1937 # server2 to server1
1938 pkts = []
1939 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1940 IP(src=server2.ip4, dst=server1_nat_ip) /
1941 TCP(sport=self.tcp_port_in, dport=server_tcp_port))
1942 pkts.append(p)
1943 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1944 IP(src=server2.ip4, dst=server1_nat_ip) /
1945 UDP(sport=self.udp_port_in, dport=server_udp_port))
1946 pkts.append(p)
1947 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1948 IP(src=server2.ip4, dst=server1_nat_ip) /
1949 ICMP(id=self.icmp_id_in, type='echo-request'))
1950 pkts.append(p)
1951 self.pg0.add_stream(pkts)
1952 self.pg_enable_capture(self.pg_interfaces)
1953 self.pg_start()
1954 capture = self.pg0.get_capture(len(pkts))
1955 for packet in capture:
1956 try:
1957 self.assertEqual(packet[IP].src, server2_nat_ip)
1958 self.assertEqual(packet[IP].dst, server1.ip4)
1959 if packet.haslayer(TCP):
1960 self.assertEqual(packet[TCP].sport, self.tcp_port_in)
1961 self.assertEqual(packet[TCP].dport, server_tcp_port)
1962 self.tcp_port_out = packet[TCP].sport
Klement Sekerad81ae412018-05-16 10:52:54 +02001963 self.assert_packet_checksums_valid(packet)
Matus Fabian6fa74c62017-06-05 05:55:48 -07001964 elif packet.haslayer(UDP):
1965 self.assertEqual(packet[UDP].sport, self.udp_port_in)
1966 self.assertEqual(packet[UDP].dport, server_udp_port)
1967 self.udp_port_out = packet[UDP].sport
1968 else:
1969 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
1970 self.icmp_id_out = packet[ICMP].id
1971 except:
1972 self.logger.error(ppp("Unexpected or invalid packet:", packet))
1973 raise
1974
1975 # server1 to server2
1976 pkts = []
1977 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1978 IP(src=server1.ip4, dst=server2_nat_ip) /
1979 TCP(sport=server_tcp_port, dport=self.tcp_port_out))
1980 pkts.append(p)
1981 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1982 IP(src=server1.ip4, dst=server2_nat_ip) /
1983 UDP(sport=server_udp_port, dport=self.udp_port_out))
1984 pkts.append(p)
1985 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1986 IP(src=server1.ip4, dst=server2_nat_ip) /
1987 ICMP(id=self.icmp_id_out, type='echo-reply'))
1988 pkts.append(p)
1989 self.pg0.add_stream(pkts)
1990 self.pg_enable_capture(self.pg_interfaces)
1991 self.pg_start()
1992 capture = self.pg0.get_capture(len(pkts))
1993 for packet in capture:
1994 try:
1995 self.assertEqual(packet[IP].src, server1_nat_ip)
1996 self.assertEqual(packet[IP].dst, server2.ip4)
1997 if packet.haslayer(TCP):
1998 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
1999 self.assertEqual(packet[TCP].sport, server_tcp_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02002000 self.assert_packet_checksums_valid(packet)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002001 elif packet.haslayer(UDP):
2002 self.assertEqual(packet[UDP].dport, self.udp_port_in)
2003 self.assertEqual(packet[UDP].sport, server_udp_port)
2004 else:
2005 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
2006 except:
2007 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2008 raise
2009
Matus Fabian9902fcd2016-12-21 23:58:46 -08002010 def test_max_translations_per_user(self):
2011 """ MAX translations per user - recycle the least recently used """
2012
Matus Fabian2ba92e32017-08-21 07:05:03 -07002013 self.nat44_add_address(self.nat_addr)
2014 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2015 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2016 is_inside=0)
Matus Fabian9902fcd2016-12-21 23:58:46 -08002017
2018 # get maximum number of translations per user
Matus Fabian2ba92e32017-08-21 07:05:03 -07002019 nat44_config = self.vapi.nat_show_config()
Matus Fabian9902fcd2016-12-21 23:58:46 -08002020
2021 # send more than maximum number of translations per user packets
Matus Fabian2ba92e32017-08-21 07:05:03 -07002022 pkts_num = nat44_config.max_translations_per_user + 5
Matus Fabian9902fcd2016-12-21 23:58:46 -08002023 pkts = []
2024 for port in range(0, pkts_num):
2025 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2026 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2027 TCP(sport=1025 + port))
2028 pkts.append(p)
2029 self.pg0.add_stream(pkts)
2030 self.pg_enable_capture(self.pg_interfaces)
2031 self.pg_start()
2032
2033 # verify number of translated packet
Klement Sekeradab231a2016-12-21 08:50:14 +01002034 self.pg1.get_capture(pkts_num)
Matus Fabian9902fcd2016-12-21 23:58:46 -08002035
Matus Fabian132dc492018-05-09 04:51:03 -07002036 users = self.vapi.nat44_user_dump()
2037 for user in users:
2038 if user.ip_address == self.pg0.remote_ip4n:
2039 self.assertEqual(user.nsessions,
2040 nat44_config.max_translations_per_user)
2041 self.assertEqual(user.nstaticsessions, 0)
2042
2043 tcp_port = 22
2044 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
2045 tcp_port, tcp_port,
2046 proto=IP_PROTOS.tcp)
2047 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2048 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2049 TCP(sport=tcp_port))
2050 self.pg0.add_stream(p)
2051 self.pg_enable_capture(self.pg_interfaces)
2052 self.pg_start()
2053 self.pg1.get_capture(1)
2054 users = self.vapi.nat44_user_dump()
2055 for user in users:
2056 if user.ip_address == self.pg0.remote_ip4n:
2057 self.assertEqual(user.nsessions,
2058 nat44_config.max_translations_per_user - 1)
2059 self.assertEqual(user.nstaticsessions, 1)
2060
Matus Fabian8bf68e82017-01-12 04:24:35 -08002061 def test_interface_addr(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002062 """ Acquire NAT44 addresses from interface """
2063 self.vapi.nat44_add_interface_addr(self.pg7.sw_if_index)
Matus Fabian8bf68e82017-01-12 04:24:35 -08002064
2065 # no address in NAT pool
Matus Fabian2ba92e32017-08-21 07:05:03 -07002066 adresses = self.vapi.nat44_address_dump()
Matus Fabian8bf68e82017-01-12 04:24:35 -08002067 self.assertEqual(0, len(adresses))
2068
2069 # configure interface address and check NAT address pool
2070 self.pg7.config_ip4()
Matus Fabian2ba92e32017-08-21 07:05:03 -07002071 adresses = self.vapi.nat44_address_dump()
Matus Fabian8bf68e82017-01-12 04:24:35 -08002072 self.assertEqual(1, len(adresses))
Matus Fabian36532bd2017-01-23 23:42:28 -08002073 self.assertEqual(adresses[0].ip_address[0:4], self.pg7.local_ip4n)
Matus Fabian8bf68e82017-01-12 04:24:35 -08002074
2075 # remove interface address and check NAT address pool
2076 self.pg7.unconfig_ip4()
Matus Fabian2ba92e32017-08-21 07:05:03 -07002077 adresses = self.vapi.nat44_address_dump()
Matus Fabian8bf68e82017-01-12 04:24:35 -08002078 self.assertEqual(0, len(adresses))
2079
Matus Fabian36532bd2017-01-23 23:42:28 -08002080 def test_interface_addr_static_mapping(self):
2081 """ Static mapping with addresses from interface """
Matus Fabian5f224992018-01-25 21:59:16 -08002082 tag = "testTAG"
2083
Matus Fabian2ba92e32017-08-21 07:05:03 -07002084 self.vapi.nat44_add_interface_addr(self.pg7.sw_if_index)
2085 self.nat44_add_static_mapping(
2086 '1.2.3.4',
Matus Fabian5f224992018-01-25 21:59:16 -08002087 external_sw_if_index=self.pg7.sw_if_index,
2088 tag=tag)
Matus Fabian36532bd2017-01-23 23:42:28 -08002089
Matus Fabiane22e5462017-02-14 23:33:43 -08002090 # static mappings with external interface
Matus Fabian2ba92e32017-08-21 07:05:03 -07002091 static_mappings = self.vapi.nat44_static_mapping_dump()
Matus Fabiane22e5462017-02-14 23:33:43 -08002092 self.assertEqual(1, len(static_mappings))
2093 self.assertEqual(self.pg7.sw_if_index,
2094 static_mappings[0].external_sw_if_index)
Matus Fabian5f224992018-01-25 21:59:16 -08002095 self.assertEqual((static_mappings[0].tag).split('\0', 1)[0], tag)
Matus Fabian36532bd2017-01-23 23:42:28 -08002096
2097 # configure interface address and check static mappings
2098 self.pg7.config_ip4()
Matus Fabian2ba92e32017-08-21 07:05:03 -07002099 static_mappings = self.vapi.nat44_static_mapping_dump()
Matus Fabianea2600a2018-03-28 04:06:26 -07002100 self.assertEqual(2, len(static_mappings))
2101 resolved = False
2102 for sm in static_mappings:
2103 if sm.external_sw_if_index == 0xFFFFFFFF:
2104 self.assertEqual(sm.external_ip_address[0:4],
2105 self.pg7.local_ip4n)
2106 self.assertEqual((sm.tag).split('\0', 1)[0], tag)
2107 resolved = True
2108 self.assertTrue(resolved)
Matus Fabian36532bd2017-01-23 23:42:28 -08002109
2110 # remove interface address and check static mappings
2111 self.pg7.unconfig_ip4()
Matus Fabian2ba92e32017-08-21 07:05:03 -07002112 static_mappings = self.vapi.nat44_static_mapping_dump()
Matus Fabianea2600a2018-03-28 04:06:26 -07002113 self.assertEqual(1, len(static_mappings))
2114 self.assertEqual(self.pg7.sw_if_index,
2115 static_mappings[0].external_sw_if_index)
2116 self.assertEqual((static_mappings[0].tag).split('\0', 1)[0], tag)
2117
2118 # configure interface address again and check static mappings
2119 self.pg7.config_ip4()
2120 static_mappings = self.vapi.nat44_static_mapping_dump()
2121 self.assertEqual(2, len(static_mappings))
2122 resolved = False
2123 for sm in static_mappings:
2124 if sm.external_sw_if_index == 0xFFFFFFFF:
2125 self.assertEqual(sm.external_ip_address[0:4],
2126 self.pg7.local_ip4n)
2127 self.assertEqual((sm.tag).split('\0', 1)[0], tag)
2128 resolved = True
2129 self.assertTrue(resolved)
2130
2131 # remove static mapping
2132 self.nat44_add_static_mapping(
2133 '1.2.3.4',
2134 external_sw_if_index=self.pg7.sw_if_index,
2135 tag=tag,
2136 is_add=0)
2137 static_mappings = self.vapi.nat44_static_mapping_dump()
Matus Fabian36532bd2017-01-23 23:42:28 -08002138 self.assertEqual(0, len(static_mappings))
2139
Matus Fabianab7a8052017-11-28 04:29:41 -08002140 def test_interface_addr_identity_nat(self):
2141 """ Identity NAT with addresses from interface """
2142
2143 port = 53053
2144 self.vapi.nat44_add_interface_addr(self.pg7.sw_if_index)
2145 self.vapi.nat44_add_del_identity_mapping(
2146 sw_if_index=self.pg7.sw_if_index,
2147 port=port,
2148 protocol=IP_PROTOS.tcp,
2149 addr_only=0)
2150
2151 # identity mappings with external interface
2152 identity_mappings = self.vapi.nat44_identity_mapping_dump()
2153 self.assertEqual(1, len(identity_mappings))
2154 self.assertEqual(self.pg7.sw_if_index,
2155 identity_mappings[0].sw_if_index)
2156
2157 # configure interface address and check identity mappings
2158 self.pg7.config_ip4()
2159 identity_mappings = self.vapi.nat44_identity_mapping_dump()
Matus Fabianea2600a2018-03-28 04:06:26 -07002160 resolved = False
2161 self.assertEqual(2, len(identity_mappings))
2162 for sm in identity_mappings:
2163 if sm.sw_if_index == 0xFFFFFFFF:
2164 self.assertEqual(identity_mappings[0].ip_address,
2165 self.pg7.local_ip4n)
2166 self.assertEqual(port, identity_mappings[0].port)
2167 self.assertEqual(IP_PROTOS.tcp, identity_mappings[0].protocol)
2168 resolved = True
2169 self.assertTrue(resolved)
Matus Fabianab7a8052017-11-28 04:29:41 -08002170
2171 # remove interface address and check identity mappings
2172 self.pg7.unconfig_ip4()
2173 identity_mappings = self.vapi.nat44_identity_mapping_dump()
Matus Fabianea2600a2018-03-28 04:06:26 -07002174 self.assertEqual(1, len(identity_mappings))
2175 self.assertEqual(self.pg7.sw_if_index,
2176 identity_mappings[0].sw_if_index)
Matus Fabianab7a8052017-11-28 04:29:41 -08002177
Matus Fabianeea28d72017-01-13 04:15:54 -08002178 def test_ipfix_nat44_sess(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002179 """ IPFIX logging NAT44 session created/delted """
Matus Fabian6631e9c2017-05-24 01:52:20 -07002180 self.ipfix_domain_id = 10
2181 self.ipfix_src_port = 20202
2182 colector_port = 30303
2183 bind_layers(UDP, IPFIX, dport=30303)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002184 self.nat44_add_address(self.nat_addr)
2185 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2186 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2187 is_inside=0)
Matus Fabianeea28d72017-01-13 04:15:54 -08002188 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
2189 src_address=self.pg3.local_ip4n,
2190 path_mtu=512,
Matus Fabian6631e9c2017-05-24 01:52:20 -07002191 template_interval=10,
2192 collector_port=colector_port)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002193 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
2194 src_port=self.ipfix_src_port)
Matus Fabianeea28d72017-01-13 04:15:54 -08002195
2196 pkts = self.create_stream_in(self.pg0, self.pg1)
2197 self.pg0.add_stream(pkts)
2198 self.pg_enable_capture(self.pg_interfaces)
2199 self.pg_start()
2200 capture = self.pg1.get_capture(len(pkts))
2201 self.verify_capture_out(capture)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002202 self.nat44_add_address(self.nat_addr, is_add=0)
Matus Fabianeea28d72017-01-13 04:15:54 -08002203 self.vapi.cli("ipfix flush") # FIXME this should be an API call
Matus Fabiana431ad12018-01-04 04:03:14 -08002204 capture = self.pg3.get_capture(9)
Matus Fabianeea28d72017-01-13 04:15:54 -08002205 ipfix = IPFIXDecoder()
2206 # first load template
2207 for p in capture:
2208 self.assertTrue(p.haslayer(IPFIX))
Matus Fabian6631e9c2017-05-24 01:52:20 -07002209 self.assertEqual(p[IP].src, self.pg3.local_ip4)
2210 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2211 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2212 self.assertEqual(p[UDP].dport, colector_port)
2213 self.assertEqual(p[IPFIX].observationDomainID,
2214 self.ipfix_domain_id)
Matus Fabianeea28d72017-01-13 04:15:54 -08002215 if p.haslayer(Template):
2216 ipfix.add_template(p.getlayer(Template))
2217 # verify events in data set
2218 for p in capture:
2219 if p.haslayer(Data):
2220 data = ipfix.decode_data_set(p.getlayer(Set))
2221 self.verify_ipfix_nat44_ses(data)
2222
2223 def test_ipfix_addr_exhausted(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002224 """ IPFIX logging NAT addresses exhausted """
2225 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2226 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2227 is_inside=0)
Matus Fabianeea28d72017-01-13 04:15:54 -08002228 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
2229 src_address=self.pg3.local_ip4n,
2230 path_mtu=512,
2231 template_interval=10)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002232 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
2233 src_port=self.ipfix_src_port)
Matus Fabianeea28d72017-01-13 04:15:54 -08002234
2235 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
2236 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2237 TCP(sport=3025))
2238 self.pg0.add_stream(p)
2239 self.pg_enable_capture(self.pg_interfaces)
2240 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07002241 self.pg1.assert_nothing_captured()
2242 sleep(1)
Matus Fabianeea28d72017-01-13 04:15:54 -08002243 self.vapi.cli("ipfix flush") # FIXME this should be an API call
Matus Fabiana431ad12018-01-04 04:03:14 -08002244 capture = self.pg3.get_capture(9)
Matus Fabianeea28d72017-01-13 04:15:54 -08002245 ipfix = IPFIXDecoder()
2246 # first load template
2247 for p in capture:
2248 self.assertTrue(p.haslayer(IPFIX))
Matus Fabian6631e9c2017-05-24 01:52:20 -07002249 self.assertEqual(p[IP].src, self.pg3.local_ip4)
2250 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2251 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2252 self.assertEqual(p[UDP].dport, 4739)
2253 self.assertEqual(p[IPFIX].observationDomainID,
2254 self.ipfix_domain_id)
Matus Fabianeea28d72017-01-13 04:15:54 -08002255 if p.haslayer(Template):
2256 ipfix.add_template(p.getlayer(Template))
2257 # verify events in data set
2258 for p in capture:
2259 if p.haslayer(Data):
2260 data = ipfix.decode_data_set(p.getlayer(Set))
2261 self.verify_ipfix_addr_exhausted(data)
2262
Matus Fabiana431ad12018-01-04 04:03:14 -08002263 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
2264 def test_ipfix_max_sessions(self):
2265 """ IPFIX logging maximum session entries exceeded """
2266 self.nat44_add_address(self.nat_addr)
2267 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2268 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2269 is_inside=0)
2270
2271 nat44_config = self.vapi.nat_show_config()
2272 max_sessions = 10 * nat44_config.translation_buckets
2273
2274 pkts = []
2275 for i in range(0, max_sessions):
2276 src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
2277 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2278 IP(src=src, dst=self.pg1.remote_ip4) /
2279 TCP(sport=1025))
2280 pkts.append(p)
2281 self.pg0.add_stream(pkts)
2282 self.pg_enable_capture(self.pg_interfaces)
2283 self.pg_start()
2284
2285 self.pg1.get_capture(max_sessions)
2286 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
2287 src_address=self.pg3.local_ip4n,
2288 path_mtu=512,
2289 template_interval=10)
2290 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
2291 src_port=self.ipfix_src_port)
2292
2293 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2294 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2295 TCP(sport=1025))
2296 self.pg0.add_stream(p)
2297 self.pg_enable_capture(self.pg_interfaces)
2298 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07002299 self.pg1.assert_nothing_captured()
2300 sleep(1)
Matus Fabiana431ad12018-01-04 04:03:14 -08002301 self.vapi.cli("ipfix flush") # FIXME this should be an API call
2302 capture = self.pg3.get_capture(9)
2303 ipfix = IPFIXDecoder()
2304 # first load template
2305 for p in capture:
2306 self.assertTrue(p.haslayer(IPFIX))
2307 self.assertEqual(p[IP].src, self.pg3.local_ip4)
2308 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2309 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2310 self.assertEqual(p[UDP].dport, 4739)
2311 self.assertEqual(p[IPFIX].observationDomainID,
2312 self.ipfix_domain_id)
2313 if p.haslayer(Template):
2314 ipfix.add_template(p.getlayer(Template))
2315 # verify events in data set
2316 for p in capture:
2317 if p.haslayer(Data):
2318 data = ipfix.decode_data_set(p.getlayer(Set))
2319 self.verify_ipfix_max_sessions(data, max_sessions)
2320
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002321 def test_pool_addr_fib(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002322 """ NAT44 add pool addresses to FIB """
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002323 static_addr = '10.0.0.10'
Matus Fabian2ba92e32017-08-21 07:05:03 -07002324 self.nat44_add_address(self.nat_addr)
2325 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2326 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2327 is_inside=0)
2328 self.nat44_add_static_mapping(self.pg0.remote_ip4, static_addr)
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002329
Matus Fabian2ba92e32017-08-21 07:05:03 -07002330 # NAT44 address
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002331 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002332 ARP(op=ARP.who_has, pdst=self.nat_addr,
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002333 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2334 self.pg1.add_stream(p)
2335 self.pg_enable_capture(self.pg_interfaces)
2336 self.pg_start()
2337 capture = self.pg1.get_capture(1)
2338 self.assertTrue(capture[0].haslayer(ARP))
2339 self.assertTrue(capture[0][ARP].op, ARP.is_at)
2340
2341 # 1:1 NAT address
2342 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2343 ARP(op=ARP.who_has, pdst=static_addr,
2344 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2345 self.pg1.add_stream(p)
2346 self.pg_enable_capture(self.pg_interfaces)
2347 self.pg_start()
2348 capture = self.pg1.get_capture(1)
2349 self.assertTrue(capture[0].haslayer(ARP))
2350 self.assertTrue(capture[0][ARP].op, ARP.is_at)
2351
Matus Fabian2ba92e32017-08-21 07:05:03 -07002352 # send ARP to non-NAT44 interface
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002353 p = (Ether(src=self.pg2.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002354 ARP(op=ARP.who_has, pdst=self.nat_addr,
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002355 psrc=self.pg2.remote_ip4, hwsrc=self.pg2.remote_mac))
2356 self.pg2.add_stream(p)
2357 self.pg_enable_capture(self.pg_interfaces)
2358 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07002359 self.pg1.assert_nothing_captured()
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002360
2361 # remove addresses and verify
Matus Fabian2ba92e32017-08-21 07:05:03 -07002362 self.nat44_add_address(self.nat_addr, is_add=0)
2363 self.nat44_add_static_mapping(self.pg0.remote_ip4, static_addr,
2364 is_add=0)
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002365
2366 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002367 ARP(op=ARP.who_has, pdst=self.nat_addr,
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002368 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2369 self.pg1.add_stream(p)
2370 self.pg_enable_capture(self.pg_interfaces)
2371 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07002372 self.pg1.assert_nothing_captured()
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002373
2374 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2375 ARP(op=ARP.who_has, pdst=static_addr,
2376 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2377 self.pg1.add_stream(p)
2378 self.pg_enable_capture(self.pg_interfaces)
2379 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07002380 self.pg1.assert_nothing_captured()
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002381
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002382 def test_vrf_mode(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002383 """ NAT44 tenant VRF aware address pool mode """
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002384
2385 vrf_id1 = 1
2386 vrf_id2 = 2
2387 nat_ip1 = "10.0.0.10"
2388 nat_ip2 = "10.0.0.11"
2389
2390 self.pg0.unconfig_ip4()
2391 self.pg1.unconfig_ip4()
Neale Ranns15002542017-09-10 04:39:11 -07002392 self.vapi.ip_table_add_del(vrf_id1, is_add=1)
2393 self.vapi.ip_table_add_del(vrf_id2, is_add=1)
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002394 self.pg0.set_table_ip4(vrf_id1)
2395 self.pg1.set_table_ip4(vrf_id2)
2396 self.pg0.config_ip4()
2397 self.pg1.config_ip4()
Matus Fabian8008d7c2018-07-09 01:34:20 -07002398 self.pg0.resolve_arp()
2399 self.pg1.resolve_arp()
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002400
Matus Fabian2ba92e32017-08-21 07:05:03 -07002401 self.nat44_add_address(nat_ip1, vrf_id=vrf_id1)
2402 self.nat44_add_address(nat_ip2, vrf_id=vrf_id2)
2403 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2404 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
2405 self.vapi.nat44_interface_add_del_feature(self.pg2.sw_if_index,
2406 is_inside=0)
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002407
Matus Fabian8008d7c2018-07-09 01:34:20 -07002408 try:
2409 # first VRF
2410 pkts = self.create_stream_in(self.pg0, self.pg2)
2411 self.pg0.add_stream(pkts)
2412 self.pg_enable_capture(self.pg_interfaces)
2413 self.pg_start()
2414 capture = self.pg2.get_capture(len(pkts))
2415 self.verify_capture_out(capture, nat_ip1)
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002416
Matus Fabian8008d7c2018-07-09 01:34:20 -07002417 # second VRF
2418 pkts = self.create_stream_in(self.pg1, self.pg2)
2419 self.pg1.add_stream(pkts)
2420 self.pg_enable_capture(self.pg_interfaces)
2421 self.pg_start()
2422 capture = self.pg2.get_capture(len(pkts))
2423 self.verify_capture_out(capture, nat_ip2)
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002424
Matus Fabian8008d7c2018-07-09 01:34:20 -07002425 finally:
2426 self.pg0.unconfig_ip4()
2427 self.pg1.unconfig_ip4()
2428 self.pg0.set_table_ip4(0)
2429 self.pg1.set_table_ip4(0)
2430 self.pg0.config_ip4()
2431 self.pg1.config_ip4()
2432 self.pg0.resolve_arp()
2433 self.pg1.resolve_arp()
2434 self.vapi.ip_table_add_del(vrf_id1, is_add=0)
2435 self.vapi.ip_table_add_del(vrf_id2, is_add=0)
Neale Ranns15002542017-09-10 04:39:11 -07002436
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002437 def test_vrf_feature_independent(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002438 """ NAT44 tenant VRF independent address pool mode """
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002439
2440 nat_ip1 = "10.0.0.10"
2441 nat_ip2 = "10.0.0.11"
2442
Matus Fabian2ba92e32017-08-21 07:05:03 -07002443 self.nat44_add_address(nat_ip1)
Matus Fabian51e759f2017-12-07 23:22:51 -08002444 self.nat44_add_address(nat_ip2, vrf_id=99)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002445 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2446 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
2447 self.vapi.nat44_interface_add_del_feature(self.pg2.sw_if_index,
2448 is_inside=0)
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002449
2450 # first VRF
2451 pkts = self.create_stream_in(self.pg0, self.pg2)
2452 self.pg0.add_stream(pkts)
2453 self.pg_enable_capture(self.pg_interfaces)
2454 self.pg_start()
2455 capture = self.pg2.get_capture(len(pkts))
2456 self.verify_capture_out(capture, nat_ip1)
2457
2458 # second VRF
2459 pkts = self.create_stream_in(self.pg1, self.pg2)
2460 self.pg1.add_stream(pkts)
2461 self.pg_enable_capture(self.pg_interfaces)
2462 self.pg_start()
2463 capture = self.pg2.get_capture(len(pkts))
2464 self.verify_capture_out(capture, nat_ip1)
2465
Martin Gálik406eb1d2017-05-04 04:35:04 -07002466 def test_dynamic_ipless_interfaces(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002467 """ NAT44 interfaces without configured IP address """
Martin Gálik406eb1d2017-05-04 04:35:04 -07002468
2469 self.vapi.ip_neighbor_add_del(self.pg7.sw_if_index,
Ole Troan895b6e82017-10-20 13:28:20 +02002470 mactobinary(self.pg7.remote_mac),
Martin Gálik406eb1d2017-05-04 04:35:04 -07002471 self.pg7.remote_ip4n,
2472 is_static=1)
2473 self.vapi.ip_neighbor_add_del(self.pg8.sw_if_index,
Ole Troan895b6e82017-10-20 13:28:20 +02002474 mactobinary(self.pg8.remote_mac),
Martin Gálik406eb1d2017-05-04 04:35:04 -07002475 self.pg8.remote_ip4n,
2476 is_static=1)
2477
2478 self.vapi.ip_add_del_route(dst_address=self.pg7.remote_ip4n,
2479 dst_address_length=32,
2480 next_hop_address=self.pg7.remote_ip4n,
2481 next_hop_sw_if_index=self.pg7.sw_if_index)
2482 self.vapi.ip_add_del_route(dst_address=self.pg8.remote_ip4n,
2483 dst_address_length=32,
2484 next_hop_address=self.pg8.remote_ip4n,
2485 next_hop_sw_if_index=self.pg8.sw_if_index)
2486
Matus Fabian2ba92e32017-08-21 07:05:03 -07002487 self.nat44_add_address(self.nat_addr)
2488 self.vapi.nat44_interface_add_del_feature(self.pg7.sw_if_index)
2489 self.vapi.nat44_interface_add_del_feature(self.pg8.sw_if_index,
2490 is_inside=0)
Martin Gálik406eb1d2017-05-04 04:35:04 -07002491
2492 # in2out
2493 pkts = self.create_stream_in(self.pg7, self.pg8)
2494 self.pg7.add_stream(pkts)
2495 self.pg_enable_capture(self.pg_interfaces)
2496 self.pg_start()
2497 capture = self.pg8.get_capture(len(pkts))
2498 self.verify_capture_out(capture)
2499
2500 # out2in
Matus Fabian2ba92e32017-08-21 07:05:03 -07002501 pkts = self.create_stream_out(self.pg8, self.nat_addr)
Martin Gálik406eb1d2017-05-04 04:35:04 -07002502 self.pg8.add_stream(pkts)
2503 self.pg_enable_capture(self.pg_interfaces)
2504 self.pg_start()
2505 capture = self.pg7.get_capture(len(pkts))
2506 self.verify_capture_in(capture, self.pg7)
2507
2508 def test_static_ipless_interfaces(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002509 """ NAT44 interfaces without configured IP address - 1:1 NAT """
Martin Gálik406eb1d2017-05-04 04:35:04 -07002510
2511 self.vapi.ip_neighbor_add_del(self.pg7.sw_if_index,
Ole Troan895b6e82017-10-20 13:28:20 +02002512 mactobinary(self.pg7.remote_mac),
Martin Gálik406eb1d2017-05-04 04:35:04 -07002513 self.pg7.remote_ip4n,
2514 is_static=1)
2515 self.vapi.ip_neighbor_add_del(self.pg8.sw_if_index,
Ole Troan895b6e82017-10-20 13:28:20 +02002516 mactobinary(self.pg8.remote_mac),
Martin Gálik406eb1d2017-05-04 04:35:04 -07002517 self.pg8.remote_ip4n,
2518 is_static=1)
2519
2520 self.vapi.ip_add_del_route(dst_address=self.pg7.remote_ip4n,
2521 dst_address_length=32,
2522 next_hop_address=self.pg7.remote_ip4n,
2523 next_hop_sw_if_index=self.pg7.sw_if_index)
2524 self.vapi.ip_add_del_route(dst_address=self.pg8.remote_ip4n,
2525 dst_address_length=32,
2526 next_hop_address=self.pg8.remote_ip4n,
2527 next_hop_sw_if_index=self.pg8.sw_if_index)
2528
Matus Fabian2ba92e32017-08-21 07:05:03 -07002529 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr)
2530 self.vapi.nat44_interface_add_del_feature(self.pg7.sw_if_index)
2531 self.vapi.nat44_interface_add_del_feature(self.pg8.sw_if_index,
2532 is_inside=0)
Martin Gálik406eb1d2017-05-04 04:35:04 -07002533
2534 # out2in
2535 pkts = self.create_stream_out(self.pg8)
2536 self.pg8.add_stream(pkts)
2537 self.pg_enable_capture(self.pg_interfaces)
2538 self.pg_start()
2539 capture = self.pg7.get_capture(len(pkts))
2540 self.verify_capture_in(capture, self.pg7)
2541
2542 # in2out
2543 pkts = self.create_stream_in(self.pg7, self.pg8)
2544 self.pg7.add_stream(pkts)
2545 self.pg_enable_capture(self.pg_interfaces)
2546 self.pg_start()
2547 capture = self.pg8.get_capture(len(pkts))
Matus Fabian2ba92e32017-08-21 07:05:03 -07002548 self.verify_capture_out(capture, self.nat_addr, True)
Martin Gálik406eb1d2017-05-04 04:35:04 -07002549
2550 def test_static_with_port_ipless_interfaces(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002551 """ NAT44 interfaces without configured IP address - 1:1 NAPT """
Martin Gálik406eb1d2017-05-04 04:35:04 -07002552
2553 self.tcp_port_out = 30606
2554 self.udp_port_out = 30607
2555 self.icmp_id_out = 30608
2556
2557 self.vapi.ip_neighbor_add_del(self.pg7.sw_if_index,
Ole Troan895b6e82017-10-20 13:28:20 +02002558 mactobinary(self.pg7.remote_mac),
Martin Gálik406eb1d2017-05-04 04:35:04 -07002559 self.pg7.remote_ip4n,
2560 is_static=1)
2561 self.vapi.ip_neighbor_add_del(self.pg8.sw_if_index,
Ole Troan895b6e82017-10-20 13:28:20 +02002562 mactobinary(self.pg8.remote_mac),
Martin Gálik406eb1d2017-05-04 04:35:04 -07002563 self.pg8.remote_ip4n,
2564 is_static=1)
2565
2566 self.vapi.ip_add_del_route(dst_address=self.pg7.remote_ip4n,
2567 dst_address_length=32,
2568 next_hop_address=self.pg7.remote_ip4n,
2569 next_hop_sw_if_index=self.pg7.sw_if_index)
2570 self.vapi.ip_add_del_route(dst_address=self.pg8.remote_ip4n,
2571 dst_address_length=32,
2572 next_hop_address=self.pg8.remote_ip4n,
2573 next_hop_sw_if_index=self.pg8.sw_if_index)
2574
Matus Fabian2ba92e32017-08-21 07:05:03 -07002575 self.nat44_add_address(self.nat_addr)
2576 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
2577 self.tcp_port_in, self.tcp_port_out,
2578 proto=IP_PROTOS.tcp)
2579 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
2580 self.udp_port_in, self.udp_port_out,
2581 proto=IP_PROTOS.udp)
2582 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
2583 self.icmp_id_in, self.icmp_id_out,
2584 proto=IP_PROTOS.icmp)
2585 self.vapi.nat44_interface_add_del_feature(self.pg7.sw_if_index)
2586 self.vapi.nat44_interface_add_del_feature(self.pg8.sw_if_index,
2587 is_inside=0)
Martin Gálik406eb1d2017-05-04 04:35:04 -07002588
2589 # out2in
2590 pkts = self.create_stream_out(self.pg8)
2591 self.pg8.add_stream(pkts)
2592 self.pg_enable_capture(self.pg_interfaces)
2593 self.pg_start()
2594 capture = self.pg7.get_capture(len(pkts))
2595 self.verify_capture_in(capture, self.pg7)
2596
2597 # in2out
2598 pkts = self.create_stream_in(self.pg7, self.pg8)
2599 self.pg7.add_stream(pkts)
2600 self.pg_enable_capture(self.pg_interfaces)
2601 self.pg_start()
2602 capture = self.pg8.get_capture(len(pkts))
2603 self.verify_capture_out(capture)
2604
Matus Fabian328dbc82017-06-19 04:28:04 -07002605 def test_static_unknown_proto(self):
2606 """ 1:1 NAT translate packet with unknown protocol """
2607 nat_ip = "10.0.0.10"
Matus Fabian2ba92e32017-08-21 07:05:03 -07002608 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
2609 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2610 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2611 is_inside=0)
Matus Fabian328dbc82017-06-19 04:28:04 -07002612
2613 # in2out
2614 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2615 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2616 GRE() /
Matus Fabian1e8db5f2017-06-20 01:45:49 -07002617 IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4) /
Matus Fabian328dbc82017-06-19 04:28:04 -07002618 TCP(sport=1234, dport=1234))
2619 self.pg0.add_stream(p)
2620 self.pg_enable_capture(self.pg_interfaces)
2621 self.pg_start()
2622 p = self.pg1.get_capture(1)
2623 packet = p[0]
2624 try:
2625 self.assertEqual(packet[IP].src, nat_ip)
2626 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
2627 self.assertTrue(packet.haslayer(GRE))
Klement Sekerad81ae412018-05-16 10:52:54 +02002628 self.assert_packet_checksums_valid(packet)
Matus Fabian328dbc82017-06-19 04:28:04 -07002629 except:
2630 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2631 raise
2632
2633 # out2in
2634 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
2635 IP(src=self.pg1.remote_ip4, dst=nat_ip) /
2636 GRE() /
Matus Fabian1e8db5f2017-06-20 01:45:49 -07002637 IP(src=self.pg3.remote_ip4, dst=self.pg2.remote_ip4) /
Matus Fabian328dbc82017-06-19 04:28:04 -07002638 TCP(sport=1234, dport=1234))
2639 self.pg1.add_stream(p)
2640 self.pg_enable_capture(self.pg_interfaces)
2641 self.pg_start()
2642 p = self.pg0.get_capture(1)
2643 packet = p[0]
2644 try:
2645 self.assertEqual(packet[IP].src, self.pg1.remote_ip4)
2646 self.assertEqual(packet[IP].dst, self.pg0.remote_ip4)
2647 self.assertTrue(packet.haslayer(GRE))
Klement Sekerad81ae412018-05-16 10:52:54 +02002648 self.assert_packet_checksums_valid(packet)
Matus Fabian328dbc82017-06-19 04:28:04 -07002649 except:
2650 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2651 raise
2652
Matus Fabian7968e6c2017-07-06 05:37:49 -07002653 def test_hairpinning_static_unknown_proto(self):
Matus Fabian1e8db5f2017-06-20 01:45:49 -07002654 """ 1:1 NAT translate packet with unknown protocol - hairpinning """
2655
2656 host = self.pg0.remote_hosts[0]
2657 server = self.pg0.remote_hosts[1]
2658
2659 host_nat_ip = "10.0.0.10"
2660 server_nat_ip = "10.0.0.11"
2661
Matus Fabian2ba92e32017-08-21 07:05:03 -07002662 self.nat44_add_static_mapping(host.ip4, host_nat_ip)
2663 self.nat44_add_static_mapping(server.ip4, server_nat_ip)
2664 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2665 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2666 is_inside=0)
Matus Fabian1e8db5f2017-06-20 01:45:49 -07002667
2668 # host to server
2669 p = (Ether(dst=self.pg0.local_mac, src=host.mac) /
2670 IP(src=host.ip4, dst=server_nat_ip) /
2671 GRE() /
2672 IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4) /
2673 TCP(sport=1234, dport=1234))
2674 self.pg0.add_stream(p)
2675 self.pg_enable_capture(self.pg_interfaces)
2676 self.pg_start()
2677 p = self.pg0.get_capture(1)
2678 packet = p[0]
2679 try:
2680 self.assertEqual(packet[IP].src, host_nat_ip)
2681 self.assertEqual(packet[IP].dst, server.ip4)
2682 self.assertTrue(packet.haslayer(GRE))
Klement Sekerad81ae412018-05-16 10:52:54 +02002683 self.assert_packet_checksums_valid(packet)
Matus Fabian1e8db5f2017-06-20 01:45:49 -07002684 except:
2685 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2686 raise
2687
2688 # server to host
2689 p = (Ether(dst=self.pg0.local_mac, src=server.mac) /
2690 IP(src=server.ip4, dst=host_nat_ip) /
2691 GRE() /
2692 IP(src=self.pg3.remote_ip4, dst=self.pg2.remote_ip4) /
2693 TCP(sport=1234, dport=1234))
2694 self.pg0.add_stream(p)
2695 self.pg_enable_capture(self.pg_interfaces)
2696 self.pg_start()
2697 p = self.pg0.get_capture(1)
2698 packet = p[0]
2699 try:
2700 self.assertEqual(packet[IP].src, server_nat_ip)
2701 self.assertEqual(packet[IP].dst, host.ip4)
2702 self.assertTrue(packet.haslayer(GRE))
Klement Sekerad81ae412018-05-16 10:52:54 +02002703 self.assert_packet_checksums_valid(packet)
Matus Fabian1e8db5f2017-06-20 01:45:49 -07002704 except:
2705 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2706 raise
2707
Matus Fabian93d84c92017-07-19 08:06:01 -07002708 def test_output_feature(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002709 """ NAT44 interface output feature (in2out postrouting) """
2710 self.nat44_add_address(self.nat_addr)
2711 self.vapi.nat44_interface_add_del_output_feature(self.pg0.sw_if_index)
Matus Fabianb2d2fc72017-09-10 22:17:47 -07002712 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index)
2713 self.vapi.nat44_interface_add_del_output_feature(self.pg3.sw_if_index,
Matus Fabian2ba92e32017-08-21 07:05:03 -07002714 is_inside=0)
Matus Fabian93d84c92017-07-19 08:06:01 -07002715
2716 # in2out
Matus Fabianb2d2fc72017-09-10 22:17:47 -07002717 pkts = self.create_stream_in(self.pg0, self.pg3)
Matus Fabian93d84c92017-07-19 08:06:01 -07002718 self.pg0.add_stream(pkts)
2719 self.pg_enable_capture(self.pg_interfaces)
2720 self.pg_start()
Matus Fabianb2d2fc72017-09-10 22:17:47 -07002721 capture = self.pg3.get_capture(len(pkts))
Matus Fabian93d84c92017-07-19 08:06:01 -07002722 self.verify_capture_out(capture)
2723
2724 # out2in
Matus Fabianb2d2fc72017-09-10 22:17:47 -07002725 pkts = self.create_stream_out(self.pg3)
2726 self.pg3.add_stream(pkts)
Matus Fabian93d84c92017-07-19 08:06:01 -07002727 self.pg_enable_capture(self.pg_interfaces)
2728 self.pg_start()
2729 capture = self.pg0.get_capture(len(pkts))
2730 self.verify_capture_in(capture, self.pg0)
2731
Matus Fabianb2d2fc72017-09-10 22:17:47 -07002732 # from non-NAT interface to NAT inside interface
2733 pkts = self.create_stream_in(self.pg2, self.pg0)
2734 self.pg2.add_stream(pkts)
2735 self.pg_enable_capture(self.pg_interfaces)
2736 self.pg_start()
2737 capture = self.pg0.get_capture(len(pkts))
2738 self.verify_capture_no_translation(capture, self.pg2, self.pg0)
2739
Matus Fabian93d84c92017-07-19 08:06:01 -07002740 def test_output_feature_vrf_aware(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002741 """ NAT44 interface output feature VRF aware (in2out postrouting) """
Matus Fabian93d84c92017-07-19 08:06:01 -07002742 nat_ip_vrf10 = "10.0.0.10"
2743 nat_ip_vrf20 = "10.0.0.20"
2744
2745 self.vapi.ip_add_del_route(dst_address=self.pg3.remote_ip4n,
2746 dst_address_length=32,
2747 next_hop_address=self.pg3.remote_ip4n,
2748 next_hop_sw_if_index=self.pg3.sw_if_index,
2749 table_id=10)
2750 self.vapi.ip_add_del_route(dst_address=self.pg3.remote_ip4n,
2751 dst_address_length=32,
2752 next_hop_address=self.pg3.remote_ip4n,
2753 next_hop_sw_if_index=self.pg3.sw_if_index,
2754 table_id=20)
2755
Matus Fabian2ba92e32017-08-21 07:05:03 -07002756 self.nat44_add_address(nat_ip_vrf10, vrf_id=10)
2757 self.nat44_add_address(nat_ip_vrf20, vrf_id=20)
2758 self.vapi.nat44_interface_add_del_output_feature(self.pg4.sw_if_index)
2759 self.vapi.nat44_interface_add_del_output_feature(self.pg6.sw_if_index)
2760 self.vapi.nat44_interface_add_del_output_feature(self.pg3.sw_if_index,
2761 is_inside=0)
Matus Fabian93d84c92017-07-19 08:06:01 -07002762
2763 # in2out VRF 10
2764 pkts = self.create_stream_in(self.pg4, self.pg3)
2765 self.pg4.add_stream(pkts)
2766 self.pg_enable_capture(self.pg_interfaces)
2767 self.pg_start()
2768 capture = self.pg3.get_capture(len(pkts))
2769 self.verify_capture_out(capture, nat_ip=nat_ip_vrf10)
2770
2771 # out2in VRF 10
2772 pkts = self.create_stream_out(self.pg3, dst_ip=nat_ip_vrf10)
2773 self.pg3.add_stream(pkts)
2774 self.pg_enable_capture(self.pg_interfaces)
2775 self.pg_start()
2776 capture = self.pg4.get_capture(len(pkts))
2777 self.verify_capture_in(capture, self.pg4)
2778
2779 # in2out VRF 20
2780 pkts = self.create_stream_in(self.pg6, self.pg3)
2781 self.pg6.add_stream(pkts)
2782 self.pg_enable_capture(self.pg_interfaces)
2783 self.pg_start()
2784 capture = self.pg3.get_capture(len(pkts))
2785 self.verify_capture_out(capture, nat_ip=nat_ip_vrf20)
2786
2787 # out2in VRF 20
2788 pkts = self.create_stream_out(self.pg3, dst_ip=nat_ip_vrf20)
2789 self.pg3.add_stream(pkts)
2790 self.pg_enable_capture(self.pg_interfaces)
2791 self.pg_start()
2792 capture = self.pg6.get_capture(len(pkts))
2793 self.verify_capture_in(capture, self.pg6)
2794
Matus Fabian161c59c2017-07-21 03:46:03 -07002795 def test_output_feature_hairpinning(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002796 """ NAT44 interface output feature hairpinning (in2out postrouting) """
Matus Fabian93d84c92017-07-19 08:06:01 -07002797 host = self.pg0.remote_hosts[0]
2798 server = self.pg0.remote_hosts[1]
2799 host_in_port = 1234
2800 host_out_port = 0
2801 server_in_port = 5678
2802 server_out_port = 8765
2803
Matus Fabian2ba92e32017-08-21 07:05:03 -07002804 self.nat44_add_address(self.nat_addr)
2805 self.vapi.nat44_interface_add_del_output_feature(self.pg0.sw_if_index)
2806 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
2807 is_inside=0)
Matus Fabian93d84c92017-07-19 08:06:01 -07002808
2809 # add static mapping for server
Matus Fabian2ba92e32017-08-21 07:05:03 -07002810 self.nat44_add_static_mapping(server.ip4, self.nat_addr,
2811 server_in_port, server_out_port,
2812 proto=IP_PROTOS.tcp)
Matus Fabian93d84c92017-07-19 08:06:01 -07002813
2814 # send packet from host to server
2815 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002816 IP(src=host.ip4, dst=self.nat_addr) /
Matus Fabian93d84c92017-07-19 08:06:01 -07002817 TCP(sport=host_in_port, dport=server_out_port))
2818 self.pg0.add_stream(p)
2819 self.pg_enable_capture(self.pg_interfaces)
2820 self.pg_start()
2821 capture = self.pg0.get_capture(1)
2822 p = capture[0]
2823 try:
2824 ip = p[IP]
2825 tcp = p[TCP]
Matus Fabian2ba92e32017-08-21 07:05:03 -07002826 self.assertEqual(ip.src, self.nat_addr)
Matus Fabian93d84c92017-07-19 08:06:01 -07002827 self.assertEqual(ip.dst, server.ip4)
2828 self.assertNotEqual(tcp.sport, host_in_port)
2829 self.assertEqual(tcp.dport, server_in_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02002830 self.assert_packet_checksums_valid(p)
Matus Fabian93d84c92017-07-19 08:06:01 -07002831 host_out_port = tcp.sport
2832 except:
2833 self.logger.error(ppp("Unexpected or invalid packet:", p))
2834 raise
2835
2836 # send reply from server to host
2837 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002838 IP(src=server.ip4, dst=self.nat_addr) /
Matus Fabian93d84c92017-07-19 08:06:01 -07002839 TCP(sport=server_in_port, dport=host_out_port))
2840 self.pg0.add_stream(p)
2841 self.pg_enable_capture(self.pg_interfaces)
2842 self.pg_start()
2843 capture = self.pg0.get_capture(1)
2844 p = capture[0]
2845 try:
2846 ip = p[IP]
2847 tcp = p[TCP]
Matus Fabian2ba92e32017-08-21 07:05:03 -07002848 self.assertEqual(ip.src, self.nat_addr)
Matus Fabian93d84c92017-07-19 08:06:01 -07002849 self.assertEqual(ip.dst, host.ip4)
2850 self.assertEqual(tcp.sport, server_out_port)
2851 self.assertEqual(tcp.dport, host_in_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02002852 self.assert_packet_checksums_valid(p)
Matus Fabian93d84c92017-07-19 08:06:01 -07002853 except:
Matus Fabiane82488f2018-01-18 03:38:45 -08002854 self.logger.error(ppp("Unexpected or invalid packet:", p))
Matus Fabian93d84c92017-07-19 08:06:01 -07002855 raise
2856
Matus Fabian36ea2d62017-10-24 04:13:49 -07002857 def test_one_armed_nat44(self):
2858 """ One armed NAT44 """
2859 remote_host = self.pg9.remote_hosts[0]
2860 local_host = self.pg9.remote_hosts[1]
2861 external_port = 0
2862
2863 self.nat44_add_address(self.nat_addr)
2864 self.vapi.nat44_interface_add_del_feature(self.pg9.sw_if_index)
2865 self.vapi.nat44_interface_add_del_feature(self.pg9.sw_if_index,
2866 is_inside=0)
2867
2868 # in2out
2869 p = (Ether(src=self.pg9.remote_mac, dst=self.pg9.local_mac) /
2870 IP(src=local_host.ip4, dst=remote_host.ip4) /
2871 TCP(sport=12345, dport=80))
2872 self.pg9.add_stream(p)
2873 self.pg_enable_capture(self.pg_interfaces)
2874 self.pg_start()
2875 capture = self.pg9.get_capture(1)
2876 p = capture[0]
2877 try:
2878 ip = p[IP]
2879 tcp = p[TCP]
2880 self.assertEqual(ip.src, self.nat_addr)
2881 self.assertEqual(ip.dst, remote_host.ip4)
2882 self.assertNotEqual(tcp.sport, 12345)
2883 external_port = tcp.sport
2884 self.assertEqual(tcp.dport, 80)
Klement Sekerad81ae412018-05-16 10:52:54 +02002885 self.assert_packet_checksums_valid(p)
Matus Fabian36ea2d62017-10-24 04:13:49 -07002886 except:
2887 self.logger.error(ppp("Unexpected or invalid packet:", p))
2888 raise
2889
2890 # out2in
2891 p = (Ether(src=self.pg9.remote_mac, dst=self.pg9.local_mac) /
2892 IP(src=remote_host.ip4, dst=self.nat_addr) /
2893 TCP(sport=80, dport=external_port))
2894 self.pg9.add_stream(p)
2895 self.pg_enable_capture(self.pg_interfaces)
2896 self.pg_start()
2897 capture = self.pg9.get_capture(1)
2898 p = capture[0]
2899 try:
2900 ip = p[IP]
2901 tcp = p[TCP]
2902 self.assertEqual(ip.src, remote_host.ip4)
2903 self.assertEqual(ip.dst, local_host.ip4)
2904 self.assertEqual(tcp.sport, 80)
2905 self.assertEqual(tcp.dport, 12345)
Klement Sekerad81ae412018-05-16 10:52:54 +02002906 self.assert_packet_checksums_valid(p)
Matus Fabian36ea2d62017-10-24 04:13:49 -07002907 except:
2908 self.logger.error(ppp("Unexpected or invalid packet:", p))
2909 raise
2910
Matus Fabian5ba86f72017-10-26 03:37:38 -07002911 def test_del_session(self):
2912 """ Delete NAT44 session """
2913 self.nat44_add_address(self.nat_addr)
2914 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2915 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2916 is_inside=0)
2917
2918 pkts = self.create_stream_in(self.pg0, self.pg1)
2919 self.pg0.add_stream(pkts)
2920 self.pg_enable_capture(self.pg_interfaces)
2921 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07002922 self.pg1.get_capture(len(pkts))
Matus Fabian5ba86f72017-10-26 03:37:38 -07002923
2924 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
2925 nsessions = len(sessions)
2926
2927 self.vapi.nat44_del_session(sessions[0].inside_ip_address,
2928 sessions[0].inside_port,
2929 sessions[0].protocol)
2930 self.vapi.nat44_del_session(sessions[1].outside_ip_address,
2931 sessions[1].outside_port,
2932 sessions[1].protocol,
2933 is_in=0)
2934
2935 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
2936 self.assertEqual(nsessions - len(sessions), 2)
2937
Matus Fabian68ba8802018-08-08 05:52:47 -07002938 self.vapi.nat44_del_session(sessions[0].inside_ip_address,
2939 sessions[0].inside_port,
2940 sessions[0].protocol)
2941
2942 self.verify_no_nat44_user()
2943
Matus Fabianefcd1e92017-08-15 06:59:19 -07002944 def test_set_get_reass(self):
2945 """ NAT44 set/get virtual fragmentation reassembly """
2946 reas_cfg1 = self.vapi.nat_get_reass()
2947
2948 self.vapi.nat_set_reass(timeout=reas_cfg1.ip4_timeout + 5,
2949 max_reass=reas_cfg1.ip4_max_reass * 2,
2950 max_frag=reas_cfg1.ip4_max_frag * 2)
2951
2952 reas_cfg2 = self.vapi.nat_get_reass()
2953
2954 self.assertEqual(reas_cfg1.ip4_timeout + 5, reas_cfg2.ip4_timeout)
2955 self.assertEqual(reas_cfg1.ip4_max_reass * 2, reas_cfg2.ip4_max_reass)
2956 self.assertEqual(reas_cfg1.ip4_max_frag * 2, reas_cfg2.ip4_max_frag)
2957
2958 self.vapi.nat_set_reass(drop_frag=1)
2959 self.assertTrue(self.vapi.nat_get_reass().ip4_drop_frag)
2960
2961 def test_frag_in_order(self):
2962 """ NAT44 translate fragments arriving in order """
2963 self.nat44_add_address(self.nat_addr)
2964 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2965 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2966 is_inside=0)
2967
2968 data = "A" * 4 + "B" * 16 + "C" * 3
2969 self.tcp_port_in = random.randint(1025, 65535)
2970
2971 reass = self.vapi.nat_reass_dump()
2972 reass_n_start = len(reass)
2973
2974 # in2out
2975 pkts = self.create_stream_frag(self.pg0,
2976 self.pg1.remote_ip4,
2977 self.tcp_port_in,
2978 20,
2979 data)
2980 self.pg0.add_stream(pkts)
2981 self.pg_enable_capture(self.pg_interfaces)
2982 self.pg_start()
2983 frags = self.pg1.get_capture(len(pkts))
2984 p = self.reass_frags_and_verify(frags,
2985 self.nat_addr,
2986 self.pg1.remote_ip4)
2987 self.assertEqual(p[TCP].dport, 20)
2988 self.assertNotEqual(p[TCP].sport, self.tcp_port_in)
2989 self.tcp_port_out = p[TCP].sport
2990 self.assertEqual(data, p[Raw].load)
2991
2992 # out2in
2993 pkts = self.create_stream_frag(self.pg1,
2994 self.nat_addr,
2995 20,
2996 self.tcp_port_out,
2997 data)
2998 self.pg1.add_stream(pkts)
2999 self.pg_enable_capture(self.pg_interfaces)
3000 self.pg_start()
3001 frags = self.pg0.get_capture(len(pkts))
3002 p = self.reass_frags_and_verify(frags,
3003 self.pg1.remote_ip4,
3004 self.pg0.remote_ip4)
3005 self.assertEqual(p[TCP].sport, 20)
3006 self.assertEqual(p[TCP].dport, self.tcp_port_in)
3007 self.assertEqual(data, p[Raw].load)
3008
3009 reass = self.vapi.nat_reass_dump()
3010 reass_n_end = len(reass)
3011
3012 self.assertEqual(reass_n_end - reass_n_start, 2)
3013
3014 def test_reass_hairpinning(self):
3015 """ NAT44 fragments hairpinning """
Matus Fabianefcd1e92017-08-15 06:59:19 -07003016 server = self.pg0.remote_hosts[1]
3017 host_in_port = random.randint(1025, 65535)
Matus Fabianefcd1e92017-08-15 06:59:19 -07003018 server_in_port = random.randint(1025, 65535)
3019 server_out_port = random.randint(1025, 65535)
3020 data = "A" * 4 + "B" * 16 + "C" * 3
3021
3022 self.nat44_add_address(self.nat_addr)
3023 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3024 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3025 is_inside=0)
3026 # add static mapping for server
3027 self.nat44_add_static_mapping(server.ip4, self.nat_addr,
3028 server_in_port, server_out_port,
3029 proto=IP_PROTOS.tcp)
3030
3031 # send packet from host to server
3032 pkts = self.create_stream_frag(self.pg0,
3033 self.nat_addr,
3034 host_in_port,
3035 server_out_port,
3036 data)
3037 self.pg0.add_stream(pkts)
3038 self.pg_enable_capture(self.pg_interfaces)
3039 self.pg_start()
3040 frags = self.pg0.get_capture(len(pkts))
3041 p = self.reass_frags_and_verify(frags,
3042 self.nat_addr,
3043 server.ip4)
3044 self.assertNotEqual(p[TCP].sport, host_in_port)
3045 self.assertEqual(p[TCP].dport, server_in_port)
3046 self.assertEqual(data, p[Raw].load)
3047
3048 def test_frag_out_of_order(self):
3049 """ NAT44 translate fragments arriving out of order """
3050 self.nat44_add_address(self.nat_addr)
3051 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3052 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3053 is_inside=0)
3054
3055 data = "A" * 4 + "B" * 16 + "C" * 3
3056 random.randint(1025, 65535)
3057
3058 # in2out
3059 pkts = self.create_stream_frag(self.pg0,
3060 self.pg1.remote_ip4,
3061 self.tcp_port_in,
3062 20,
3063 data)
3064 pkts.reverse()
3065 self.pg0.add_stream(pkts)
3066 self.pg_enable_capture(self.pg_interfaces)
3067 self.pg_start()
3068 frags = self.pg1.get_capture(len(pkts))
3069 p = self.reass_frags_and_verify(frags,
3070 self.nat_addr,
3071 self.pg1.remote_ip4)
3072 self.assertEqual(p[TCP].dport, 20)
3073 self.assertNotEqual(p[TCP].sport, self.tcp_port_in)
3074 self.tcp_port_out = p[TCP].sport
3075 self.assertEqual(data, p[Raw].load)
3076
3077 # out2in
3078 pkts = self.create_stream_frag(self.pg1,
3079 self.nat_addr,
3080 20,
3081 self.tcp_port_out,
3082 data)
3083 pkts.reverse()
3084 self.pg1.add_stream(pkts)
3085 self.pg_enable_capture(self.pg_interfaces)
3086 self.pg_start()
3087 frags = self.pg0.get_capture(len(pkts))
3088 p = self.reass_frags_and_verify(frags,
3089 self.pg1.remote_ip4,
3090 self.pg0.remote_ip4)
3091 self.assertEqual(p[TCP].sport, 20)
3092 self.assertEqual(p[TCP].dport, self.tcp_port_in)
3093 self.assertEqual(data, p[Raw].load)
3094
Matus Fabian27697102017-11-09 01:43:47 -08003095 def test_port_restricted(self):
3096 """ Port restricted NAT44 (MAP-E CE) """
3097 self.nat44_add_address(self.nat_addr)
3098 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3099 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3100 is_inside=0)
Matus Fabian51e759f2017-12-07 23:22:51 -08003101 self.vapi.cli("nat addr-port-assignment-alg map-e psid 10 "
Matus Fabian27697102017-11-09 01:43:47 -08003102 "psid-offset 6 psid-len 6")
3103
3104 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3105 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3106 TCP(sport=4567, dport=22))
3107 self.pg0.add_stream(p)
3108 self.pg_enable_capture(self.pg_interfaces)
3109 self.pg_start()
3110 capture = self.pg1.get_capture(1)
3111 p = capture[0]
3112 try:
3113 ip = p[IP]
3114 tcp = p[TCP]
3115 self.assertEqual(ip.dst, self.pg1.remote_ip4)
3116 self.assertEqual(ip.src, self.nat_addr)
3117 self.assertEqual(tcp.dport, 22)
3118 self.assertNotEqual(tcp.sport, 4567)
3119 self.assertEqual((tcp.sport >> 6) & 63, 10)
Klement Sekerad81ae412018-05-16 10:52:54 +02003120 self.assert_packet_checksums_valid(p)
Matus Fabian27697102017-11-09 01:43:47 -08003121 except:
3122 self.logger.error(ppp("Unexpected or invalid packet:", p))
3123 raise
3124
Matus Fabiana6110b62018-06-13 05:39:07 -07003125 def test_ipfix_max_frags(self):
3126 """ IPFIX logging maximum fragments pending reassembly exceeded """
3127 self.nat44_add_address(self.nat_addr)
3128 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3129 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3130 is_inside=0)
3131 self.vapi.nat_set_reass(max_frag=0)
3132 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
3133 src_address=self.pg3.local_ip4n,
3134 path_mtu=512,
3135 template_interval=10)
3136 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
3137 src_port=self.ipfix_src_port)
3138
3139 data = "A" * 4 + "B" * 16 + "C" * 3
3140 self.tcp_port_in = random.randint(1025, 65535)
3141 pkts = self.create_stream_frag(self.pg0,
3142 self.pg1.remote_ip4,
3143 self.tcp_port_in,
3144 20,
3145 data)
3146 self.pg0.add_stream(pkts[-1])
3147 self.pg_enable_capture(self.pg_interfaces)
3148 self.pg_start()
3149 self.pg1.assert_nothing_captured()
3150 sleep(1)
3151 self.vapi.cli("ipfix flush") # FIXME this should be an API call
3152 capture = self.pg3.get_capture(9)
3153 ipfix = IPFIXDecoder()
3154 # first load template
3155 for p in capture:
3156 self.assertTrue(p.haslayer(IPFIX))
3157 self.assertEqual(p[IP].src, self.pg3.local_ip4)
3158 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
3159 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
3160 self.assertEqual(p[UDP].dport, 4739)
3161 self.assertEqual(p[IPFIX].observationDomainID,
3162 self.ipfix_domain_id)
3163 if p.haslayer(Template):
3164 ipfix.add_template(p.getlayer(Template))
3165 # verify events in data set
3166 for p in capture:
3167 if p.haslayer(Data):
3168 data = ipfix.decode_data_set(p.getlayer(Set))
3169 self.verify_ipfix_max_fragments_ip4(data, 0,
3170 self.pg0.remote_ip4n)
3171
Matus Fabian8008d7c2018-07-09 01:34:20 -07003172 def test_multiple_outside_vrf(self):
3173 """ Multiple outside VRF """
3174 vrf_id1 = 1
3175 vrf_id2 = 2
3176
3177 self.pg1.unconfig_ip4()
3178 self.pg2.unconfig_ip4()
3179 self.vapi.ip_table_add_del(vrf_id1, is_add=1)
3180 self.vapi.ip_table_add_del(vrf_id2, is_add=1)
3181 self.pg1.set_table_ip4(vrf_id1)
3182 self.pg2.set_table_ip4(vrf_id2)
3183 self.pg1.config_ip4()
3184 self.pg2.config_ip4()
3185 self.pg1.resolve_arp()
3186 self.pg2.resolve_arp()
3187
3188 self.nat44_add_address(self.nat_addr)
3189 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3190 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3191 is_inside=0)
3192 self.vapi.nat44_interface_add_del_feature(self.pg2.sw_if_index,
3193 is_inside=0)
3194
3195 try:
3196 # first VRF
3197 pkts = self.create_stream_in(self.pg0, self.pg1)
3198 self.pg0.add_stream(pkts)
3199 self.pg_enable_capture(self.pg_interfaces)
3200 self.pg_start()
3201 capture = self.pg1.get_capture(len(pkts))
3202 self.verify_capture_out(capture, self.nat_addr)
3203
3204 pkts = self.create_stream_out(self.pg1, self.nat_addr)
3205 self.pg1.add_stream(pkts)
3206 self.pg_enable_capture(self.pg_interfaces)
3207 self.pg_start()
3208 capture = self.pg0.get_capture(len(pkts))
3209 self.verify_capture_in(capture, self.pg0)
3210
3211 self.tcp_port_in = 60303
3212 self.udp_port_in = 60304
3213 self.icmp_id_in = 60305
3214
3215 # second VRF
3216 pkts = self.create_stream_in(self.pg0, self.pg2)
3217 self.pg0.add_stream(pkts)
3218 self.pg_enable_capture(self.pg_interfaces)
3219 self.pg_start()
3220 capture = self.pg2.get_capture(len(pkts))
3221 self.verify_capture_out(capture, self.nat_addr)
3222
3223 pkts = self.create_stream_out(self.pg2, self.nat_addr)
3224 self.pg2.add_stream(pkts)
3225 self.pg_enable_capture(self.pg_interfaces)
3226 self.pg_start()
3227 capture = self.pg0.get_capture(len(pkts))
3228 self.verify_capture_in(capture, self.pg0)
3229
3230 finally:
3231 self.pg1.unconfig_ip4()
3232 self.pg2.unconfig_ip4()
3233 self.pg1.set_table_ip4(0)
3234 self.pg2.set_table_ip4(0)
3235 self.pg1.config_ip4()
3236 self.pg2.config_ip4()
3237 self.pg1.resolve_arp()
3238 self.pg2.resolve_arp()
3239
Matus Fabian878c6462018-08-23 00:33:35 -07003240 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
3241 def test_session_timeout(self):
3242 """ NAT44 session timeouts """
3243 self.nat44_add_address(self.nat_addr)
3244 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3245 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3246 is_inside=0)
3247 self.vapi.nat_set_timeouts(udp=5)
3248
3249 max_sessions = 1000
3250 pkts = []
3251 for i in range(0, max_sessions):
3252 src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
3253 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3254 IP(src=src, dst=self.pg1.remote_ip4) /
3255 UDP(sport=1025, dport=53))
3256 pkts.append(p)
3257 self.pg0.add_stream(pkts)
3258 self.pg_enable_capture(self.pg_interfaces)
3259 self.pg_start()
3260 self.pg1.get_capture(max_sessions)
3261
3262 sleep(6)
3263
3264 pkts = []
3265 for i in range(0, max_sessions):
3266 src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
3267 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3268 IP(src=src, dst=self.pg1.remote_ip4) /
3269 UDP(sport=1026, dport=53))
3270 pkts.append(p)
3271 self.pg0.add_stream(pkts)
3272 self.pg_enable_capture(self.pg_interfaces)
3273 self.pg_start()
3274 self.pg1.get_capture(max_sessions)
3275
3276 nsessions = 0
3277 users = self.vapi.nat44_user_dump()
3278 for user in users:
3279 nsessions = nsessions + user.nsessions
3280 self.assertLess(nsessions, 2 * max_sessions)
3281
Matus Fabiana6110b62018-06-13 05:39:07 -07003282 def tearDown(self):
3283 super(TestNAT44, self).tearDown()
3284 if not self.vpp_dead:
3285 self.logger.info(self.vapi.cli("show nat44 addresses"))
3286 self.logger.info(self.vapi.cli("show nat44 interfaces"))
3287 self.logger.info(self.vapi.cli("show nat44 static mappings"))
3288 self.logger.info(self.vapi.cli("show nat44 interface address"))
3289 self.logger.info(self.vapi.cli("show nat44 sessions detail"))
3290 self.logger.info(self.vapi.cli("show nat virtual-reassembly"))
3291 self.logger.info(self.vapi.cli("show nat44 hash tables detail"))
Matus Fabian878c6462018-08-23 00:33:35 -07003292 self.logger.info(self.vapi.cli("show nat timeouts"))
Matus Fabiana6110b62018-06-13 05:39:07 -07003293 self.vapi.cli("nat addr-port-assignment-alg default")
3294 self.clear_nat44()
3295 self.vapi.cli("clear logging")
3296
3297
3298class TestNAT44EndpointDependent(MethodHolder):
3299 """ Endpoint-Dependent mapping and filtering test cases """
3300
3301 @classmethod
3302 def setUpConstants(cls):
3303 super(TestNAT44EndpointDependent, cls).setUpConstants()
3304 cls.vpp_cmdline.extend(["nat", "{", "endpoint-dependent", "}"])
3305
3306 @classmethod
3307 def setUpClass(cls):
3308 super(TestNAT44EndpointDependent, cls).setUpClass()
3309 cls.vapi.cli("set log class nat level debug")
3310 try:
3311 cls.tcp_port_in = 6303
3312 cls.tcp_port_out = 6303
3313 cls.udp_port_in = 6304
3314 cls.udp_port_out = 6304
3315 cls.icmp_id_in = 6305
3316 cls.icmp_id_out = 6305
3317 cls.nat_addr = '10.0.0.3'
3318 cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
3319 cls.ipfix_src_port = 4739
3320 cls.ipfix_domain_id = 1
3321 cls.tcp_external_port = 80
3322
Matus Fabian8008d7c2018-07-09 01:34:20 -07003323 cls.create_pg_interfaces(range(7))
Matus Fabiana6110b62018-06-13 05:39:07 -07003324 cls.interfaces = list(cls.pg_interfaces[0:3])
3325
3326 for i in cls.interfaces:
3327 i.admin_up()
3328 i.config_ip4()
3329 i.resolve_arp()
3330
3331 cls.pg0.generate_remote_hosts(3)
3332 cls.pg0.configure_ipv4_neighbors()
3333
3334 cls.pg3.admin_up()
3335
3336 cls.pg4.generate_remote_hosts(2)
3337 cls.pg4.config_ip4()
3338 ip_addr_n = socket.inet_pton(socket.AF_INET, "10.0.0.1")
3339 cls.vapi.sw_interface_add_del_address(cls.pg4.sw_if_index,
3340 ip_addr_n,
3341 24)
3342 cls.pg4.admin_up()
3343 cls.pg4.resolve_arp()
3344 cls.pg4._remote_hosts[1]._ip4 = cls.pg4._remote_hosts[0]._ip4
3345 cls.pg4.resolve_arp()
3346
Matus Fabian8008d7c2018-07-09 01:34:20 -07003347 zero_ip4n = socket.inet_pton(socket.AF_INET, "0.0.0.0")
3348 cls.vapi.ip_table_add_del(1, is_add=1)
3349
3350 cls.pg5._local_ip4 = "10.1.1.1"
3351 cls.pg5._local_ip4n = socket.inet_pton(socket.AF_INET,
3352 cls.pg5.local_ip4)
3353 cls.pg5._remote_hosts[0]._ip4 = "10.1.1.2"
3354 cls.pg5._remote_hosts[0]._ip4n = socket.inet_pton(
3355 socket.AF_INET, cls.pg5.remote_ip4)
3356 cls.pg5.set_table_ip4(1)
3357 cls.pg5.config_ip4()
3358 cls.pg5.admin_up()
3359 cls.vapi.ip_add_del_route(dst_address=cls.pg5.remote_ip4n,
3360 dst_address_length=32,
3361 table_id=1,
3362 next_hop_sw_if_index=cls.pg5.sw_if_index,
3363 next_hop_address=zero_ip4n)
3364
3365 cls.pg6._local_ip4 = "10.1.2.1"
3366 cls.pg6._local_ip4n = socket.inet_pton(socket.AF_INET,
3367 cls.pg6.local_ip4)
3368 cls.pg6._remote_hosts[0]._ip4 = "10.1.2.2"
3369 cls.pg6._remote_hosts[0]._ip4n = socket.inet_pton(
3370 socket.AF_INET, cls.pg6.remote_ip4)
3371 cls.pg6.set_table_ip4(1)
3372 cls.pg6.config_ip4()
3373 cls.pg6.admin_up()
3374 cls.vapi.ip_add_del_route(dst_address=cls.pg6.remote_ip4n,
3375 dst_address_length=32,
3376 table_id=1,
3377 next_hop_sw_if_index=cls.pg6.sw_if_index,
3378 next_hop_address=zero_ip4n)
3379
3380 cls.vapi.ip_add_del_route(dst_address=cls.pg6.remote_ip4n,
3381 dst_address_length=16,
3382 next_hop_address=zero_ip4n,
3383 table_id=0,
3384 next_hop_table_id=1)
3385 cls.vapi.ip_add_del_route(dst_address=zero_ip4n,
3386 dst_address_length=0,
3387 next_hop_address=zero_ip4n,
3388 table_id=1,
3389 next_hop_table_id=0)
3390 cls.vapi.ip_add_del_route(dst_address=zero_ip4n,
3391 dst_address_length=0,
3392 table_id=0,
3393 next_hop_sw_if_index=cls.pg1.sw_if_index,
3394 next_hop_address=cls.pg1.local_ip4n)
3395
3396 cls.pg5.resolve_arp()
3397 cls.pg6.resolve_arp()
3398
Matus Fabiana6110b62018-06-13 05:39:07 -07003399 except Exception:
3400 super(TestNAT44EndpointDependent, cls).tearDownClass()
3401 raise
3402
3403 def test_dynamic(self):
3404 """ NAT44 dynamic translation test """
3405
3406 self.nat44_add_address(self.nat_addr)
3407 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3408 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3409 is_inside=0)
3410
Matus Fabian69ce30d2018-08-22 01:27:10 -07003411 nat_config = self.vapi.nat_show_config()
3412 self.assertEqual(1, nat_config.endpoint_dependent)
3413
Matus Fabiana6110b62018-06-13 05:39:07 -07003414 # in2out
3415 pkts = self.create_stream_in(self.pg0, self.pg1)
3416 self.pg0.add_stream(pkts)
3417 self.pg_enable_capture(self.pg_interfaces)
3418 self.pg_start()
3419 capture = self.pg1.get_capture(len(pkts))
3420 self.verify_capture_out(capture)
3421
3422 # out2in
3423 pkts = self.create_stream_out(self.pg1)
3424 self.pg1.add_stream(pkts)
3425 self.pg_enable_capture(self.pg_interfaces)
3426 self.pg_start()
3427 capture = self.pg0.get_capture(len(pkts))
3428 self.verify_capture_in(capture, self.pg0)
3429
3430 def test_forwarding(self):
3431 """ NAT44 forwarding test """
3432
3433 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3434 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3435 is_inside=0)
3436 self.vapi.nat44_forwarding_enable_disable(1)
3437
3438 real_ip = self.pg0.remote_ip4n
3439 alias_ip = self.nat_addr_n
3440 self.vapi.nat44_add_del_static_mapping(local_ip=real_ip,
3441 external_ip=alias_ip)
3442
3443 try:
3444 # in2out - static mapping match
3445
3446 pkts = self.create_stream_out(self.pg1)
3447 self.pg1.add_stream(pkts)
3448 self.pg_enable_capture(self.pg_interfaces)
3449 self.pg_start()
3450 capture = self.pg0.get_capture(len(pkts))
3451 self.verify_capture_in(capture, self.pg0)
3452
3453 pkts = self.create_stream_in(self.pg0, self.pg1)
3454 self.pg0.add_stream(pkts)
3455 self.pg_enable_capture(self.pg_interfaces)
3456 self.pg_start()
3457 capture = self.pg1.get_capture(len(pkts))
3458 self.verify_capture_out(capture, same_port=True)
3459
3460 # in2out - no static mapping match
3461
3462 host0 = self.pg0.remote_hosts[0]
3463 self.pg0.remote_hosts[0] = self.pg0.remote_hosts[1]
3464 try:
3465 pkts = self.create_stream_out(self.pg1,
3466 dst_ip=self.pg0.remote_ip4,
3467 use_inside_ports=True)
3468 self.pg1.add_stream(pkts)
3469 self.pg_enable_capture(self.pg_interfaces)
3470 self.pg_start()
3471 capture = self.pg0.get_capture(len(pkts))
3472 self.verify_capture_in(capture, self.pg0)
3473
3474 pkts = self.create_stream_in(self.pg0, self.pg1)
3475 self.pg0.add_stream(pkts)
3476 self.pg_enable_capture(self.pg_interfaces)
3477 self.pg_start()
3478 capture = self.pg1.get_capture(len(pkts))
3479 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
3480 same_port=True)
3481 finally:
3482 self.pg0.remote_hosts[0] = host0
3483
3484 user = self.pg0.remote_hosts[1]
3485 sessions = self.vapi.nat44_user_session_dump(user.ip4n, 0)
3486 self.assertEqual(len(sessions), 3)
3487 self.assertTrue(sessions[0].ext_host_valid)
3488 self.vapi.nat44_del_session(
3489 sessions[0].inside_ip_address,
3490 sessions[0].inside_port,
3491 sessions[0].protocol,
3492 ext_host_address=sessions[0].ext_host_address,
3493 ext_host_port=sessions[0].ext_host_port)
3494 sessions = self.vapi.nat44_user_session_dump(user.ip4n, 0)
3495 self.assertEqual(len(sessions), 2)
3496
3497 finally:
3498 self.vapi.nat44_forwarding_enable_disable(0)
3499 self.vapi.nat44_add_del_static_mapping(local_ip=real_ip,
3500 external_ip=alias_ip,
3501 is_add=0)
3502
3503 def test_static_lb(self):
3504 """ NAT44 local service load balancing """
3505 external_addr_n = socket.inet_pton(socket.AF_INET, self.nat_addr)
3506 external_port = 80
3507 local_port = 8080
3508 server1 = self.pg0.remote_hosts[0]
3509 server2 = self.pg0.remote_hosts[1]
3510
3511 locals = [{'addr': server1.ip4n,
3512 'port': local_port,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07003513 'probability': 70,
3514 'vrf_id': 0},
Matus Fabiana6110b62018-06-13 05:39:07 -07003515 {'addr': server2.ip4n,
3516 'port': local_port,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07003517 'probability': 30,
3518 'vrf_id': 0}]
Matus Fabiana6110b62018-06-13 05:39:07 -07003519
3520 self.nat44_add_address(self.nat_addr)
3521 self.vapi.nat44_add_del_lb_static_mapping(external_addr_n,
3522 external_port,
3523 IP_PROTOS.tcp,
3524 local_num=len(locals),
3525 locals=locals)
3526 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3527 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3528 is_inside=0)
3529
3530 # from client to service
3531 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3532 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3533 TCP(sport=12345, dport=external_port))
3534 self.pg1.add_stream(p)
3535 self.pg_enable_capture(self.pg_interfaces)
3536 self.pg_start()
3537 capture = self.pg0.get_capture(1)
3538 p = capture[0]
3539 server = None
3540 try:
3541 ip = p[IP]
3542 tcp = p[TCP]
3543 self.assertIn(ip.dst, [server1.ip4, server2.ip4])
3544 if ip.dst == server1.ip4:
3545 server = server1
3546 else:
3547 server = server2
3548 self.assertEqual(tcp.dport, local_port)
3549 self.assert_packet_checksums_valid(p)
3550 except:
3551 self.logger.error(ppp("Unexpected or invalid packet:", p))
3552 raise
3553
3554 # from service back to client
3555 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
3556 IP(src=server.ip4, dst=self.pg1.remote_ip4) /
3557 TCP(sport=local_port, dport=12345))
3558 self.pg0.add_stream(p)
3559 self.pg_enable_capture(self.pg_interfaces)
3560 self.pg_start()
3561 capture = self.pg1.get_capture(1)
3562 p = capture[0]
3563 try:
3564 ip = p[IP]
3565 tcp = p[TCP]
3566 self.assertEqual(ip.src, self.nat_addr)
3567 self.assertEqual(tcp.sport, external_port)
3568 self.assert_packet_checksums_valid(p)
3569 except:
3570 self.logger.error(ppp("Unexpected or invalid packet:", p))
3571 raise
3572
3573 sessions = self.vapi.nat44_user_session_dump(server.ip4n, 0)
3574 self.assertEqual(len(sessions), 1)
3575 self.assertTrue(sessions[0].ext_host_valid)
3576 self.vapi.nat44_del_session(
3577 sessions[0].inside_ip_address,
3578 sessions[0].inside_port,
3579 sessions[0].protocol,
3580 ext_host_address=sessions[0].ext_host_address,
3581 ext_host_port=sessions[0].ext_host_port)
3582 sessions = self.vapi.nat44_user_session_dump(server.ip4n, 0)
3583 self.assertEqual(len(sessions), 0)
3584
3585 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
3586 def test_static_lb_multi_clients(self):
3587 """ NAT44 local service load balancing - multiple clients"""
3588
3589 external_addr_n = socket.inet_pton(socket.AF_INET, self.nat_addr)
3590 external_port = 80
3591 local_port = 8080
3592 server1 = self.pg0.remote_hosts[0]
3593 server2 = self.pg0.remote_hosts[1]
3594
3595 locals = [{'addr': server1.ip4n,
3596 'port': local_port,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07003597 'probability': 90,
3598 'vrf_id': 0},
Matus Fabiana6110b62018-06-13 05:39:07 -07003599 {'addr': server2.ip4n,
3600 'port': local_port,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07003601 'probability': 10,
3602 'vrf_id': 0}]
Matus Fabiana6110b62018-06-13 05:39:07 -07003603
3604 self.nat44_add_address(self.nat_addr)
3605 self.vapi.nat44_add_del_lb_static_mapping(external_addr_n,
3606 external_port,
3607 IP_PROTOS.tcp,
3608 local_num=len(locals),
3609 locals=locals)
3610 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3611 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3612 is_inside=0)
3613
3614 server1_n = 0
3615 server2_n = 0
3616 clients = ip4_range(self.pg1.remote_ip4, 10, 50)
3617 pkts = []
3618 for client in clients:
3619 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3620 IP(src=client, dst=self.nat_addr) /
3621 TCP(sport=12345, dport=external_port))
3622 pkts.append(p)
3623 self.pg1.add_stream(pkts)
3624 self.pg_enable_capture(self.pg_interfaces)
3625 self.pg_start()
3626 capture = self.pg0.get_capture(len(pkts))
3627 for p in capture:
3628 if p[IP].dst == server1.ip4:
3629 server1_n += 1
3630 else:
3631 server2_n += 1
3632 self.assertTrue(server1_n > server2_n)
3633
3634 def test_static_lb_2(self):
3635 """ NAT44 local service load balancing (asymmetrical rule) """
3636 external_addr_n = socket.inet_pton(socket.AF_INET, self.nat_addr)
3637 external_port = 80
3638 local_port = 8080
3639 server1 = self.pg0.remote_hosts[0]
3640 server2 = self.pg0.remote_hosts[1]
3641
3642 locals = [{'addr': server1.ip4n,
3643 'port': local_port,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07003644 'probability': 70,
3645 'vrf_id': 0},
Matus Fabiana6110b62018-06-13 05:39:07 -07003646 {'addr': server2.ip4n,
3647 'port': local_port,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07003648 'probability': 30,
3649 'vrf_id': 0}]
Matus Fabiana6110b62018-06-13 05:39:07 -07003650
3651 self.vapi.nat44_forwarding_enable_disable(1)
3652 self.vapi.nat44_add_del_lb_static_mapping(external_addr_n,
3653 external_port,
3654 IP_PROTOS.tcp,
3655 out2in_only=1,
3656 local_num=len(locals),
3657 locals=locals)
3658 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3659 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3660 is_inside=0)
3661
3662 # from client to service
3663 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3664 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3665 TCP(sport=12345, dport=external_port))
3666 self.pg1.add_stream(p)
3667 self.pg_enable_capture(self.pg_interfaces)
3668 self.pg_start()
3669 capture = self.pg0.get_capture(1)
3670 p = capture[0]
3671 server = None
3672 try:
3673 ip = p[IP]
3674 tcp = p[TCP]
3675 self.assertIn(ip.dst, [server1.ip4, server2.ip4])
3676 if ip.dst == server1.ip4:
3677 server = server1
3678 else:
3679 server = server2
3680 self.assertEqual(tcp.dport, local_port)
3681 self.assert_packet_checksums_valid(p)
3682 except:
3683 self.logger.error(ppp("Unexpected or invalid packet:", p))
3684 raise
3685
3686 # from service back to client
3687 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
3688 IP(src=server.ip4, dst=self.pg1.remote_ip4) /
3689 TCP(sport=local_port, dport=12345))
3690 self.pg0.add_stream(p)
3691 self.pg_enable_capture(self.pg_interfaces)
3692 self.pg_start()
3693 capture = self.pg1.get_capture(1)
3694 p = capture[0]
3695 try:
3696 ip = p[IP]
3697 tcp = p[TCP]
3698 self.assertEqual(ip.src, self.nat_addr)
3699 self.assertEqual(tcp.sport, external_port)
3700 self.assert_packet_checksums_valid(p)
3701 except:
3702 self.logger.error(ppp("Unexpected or invalid packet:", p))
3703 raise
3704
3705 # from client to server (no translation)
3706 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3707 IP(src=self.pg1.remote_ip4, dst=server1.ip4) /
3708 TCP(sport=12346, dport=local_port))
3709 self.pg1.add_stream(p)
3710 self.pg_enable_capture(self.pg_interfaces)
3711 self.pg_start()
3712 capture = self.pg0.get_capture(1)
3713 p = capture[0]
3714 server = None
3715 try:
3716 ip = p[IP]
3717 tcp = p[TCP]
3718 self.assertEqual(ip.dst, server1.ip4)
3719 self.assertEqual(tcp.dport, local_port)
3720 self.assert_packet_checksums_valid(p)
3721 except:
3722 self.logger.error(ppp("Unexpected or invalid packet:", p))
3723 raise
3724
3725 # from service back to client (no translation)
3726 p = (Ether(src=server1.mac, dst=self.pg0.local_mac) /
3727 IP(src=server1.ip4, dst=self.pg1.remote_ip4) /
3728 TCP(sport=local_port, dport=12346))
3729 self.pg0.add_stream(p)
3730 self.pg_enable_capture(self.pg_interfaces)
3731 self.pg_start()
3732 capture = self.pg1.get_capture(1)
3733 p = capture[0]
3734 try:
3735 ip = p[IP]
3736 tcp = p[TCP]
3737 self.assertEqual(ip.src, server1.ip4)
3738 self.assertEqual(tcp.sport, local_port)
3739 self.assert_packet_checksums_valid(p)
3740 except:
3741 self.logger.error(ppp("Unexpected or invalid packet:", p))
3742 raise
3743
3744 def test_unknown_proto(self):
3745 """ NAT44 translate packet with unknown protocol """
3746 self.nat44_add_address(self.nat_addr)
3747 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3748 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3749 is_inside=0)
3750
3751 # in2out
3752 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3753 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3754 TCP(sport=self.tcp_port_in, dport=20))
3755 self.pg0.add_stream(p)
3756 self.pg_enable_capture(self.pg_interfaces)
3757 self.pg_start()
3758 p = self.pg1.get_capture(1)
3759
3760 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3761 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3762 GRE() /
3763 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
3764 TCP(sport=1234, dport=1234))
3765 self.pg0.add_stream(p)
3766 self.pg_enable_capture(self.pg_interfaces)
3767 self.pg_start()
3768 p = self.pg1.get_capture(1)
3769 packet = p[0]
3770 try:
3771 self.assertEqual(packet[IP].src, self.nat_addr)
3772 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
3773 self.assertTrue(packet.haslayer(GRE))
3774 self.assert_packet_checksums_valid(packet)
3775 except:
3776 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3777 raise
3778
3779 # out2in
3780 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
3781 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3782 GRE() /
3783 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
3784 TCP(sport=1234, dport=1234))
3785 self.pg1.add_stream(p)
3786 self.pg_enable_capture(self.pg_interfaces)
3787 self.pg_start()
3788 p = self.pg0.get_capture(1)
3789 packet = p[0]
3790 try:
3791 self.assertEqual(packet[IP].src, self.pg1.remote_ip4)
3792 self.assertEqual(packet[IP].dst, self.pg0.remote_ip4)
3793 self.assertTrue(packet.haslayer(GRE))
3794 self.assert_packet_checksums_valid(packet)
3795 except:
3796 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3797 raise
3798
3799 def test_hairpinning_unknown_proto(self):
3800 """ NAT44 translate packet with unknown protocol - hairpinning """
3801 host = self.pg0.remote_hosts[0]
3802 server = self.pg0.remote_hosts[1]
3803 host_in_port = 1234
3804 server_out_port = 8765
3805 server_nat_ip = "10.0.0.11"
3806
3807 self.nat44_add_address(self.nat_addr)
3808 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3809 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3810 is_inside=0)
3811
3812 # add static mapping for server
3813 self.nat44_add_static_mapping(server.ip4, server_nat_ip)
3814
3815 # host to server
3816 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
3817 IP(src=host.ip4, dst=server_nat_ip) /
3818 TCP(sport=host_in_port, dport=server_out_port))
3819 self.pg0.add_stream(p)
3820 self.pg_enable_capture(self.pg_interfaces)
3821 self.pg_start()
3822 self.pg0.get_capture(1)
3823
3824 p = (Ether(dst=self.pg0.local_mac, src=host.mac) /
3825 IP(src=host.ip4, dst=server_nat_ip) /
3826 GRE() /
3827 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
3828 TCP(sport=1234, dport=1234))
3829 self.pg0.add_stream(p)
3830 self.pg_enable_capture(self.pg_interfaces)
3831 self.pg_start()
3832 p = self.pg0.get_capture(1)
3833 packet = p[0]
3834 try:
3835 self.assertEqual(packet[IP].src, self.nat_addr)
3836 self.assertEqual(packet[IP].dst, server.ip4)
3837 self.assertTrue(packet.haslayer(GRE))
3838 self.assert_packet_checksums_valid(packet)
3839 except:
3840 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3841 raise
3842
3843 # server to host
3844 p = (Ether(dst=self.pg0.local_mac, src=server.mac) /
3845 IP(src=server.ip4, dst=self.nat_addr) /
3846 GRE() /
3847 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
3848 TCP(sport=1234, dport=1234))
3849 self.pg0.add_stream(p)
3850 self.pg_enable_capture(self.pg_interfaces)
3851 self.pg_start()
3852 p = self.pg0.get_capture(1)
3853 packet = p[0]
3854 try:
3855 self.assertEqual(packet[IP].src, server_nat_ip)
3856 self.assertEqual(packet[IP].dst, host.ip4)
3857 self.assertTrue(packet.haslayer(GRE))
3858 self.assert_packet_checksums_valid(packet)
3859 except:
3860 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3861 raise
3862
3863 def test_output_feature_and_service(self):
3864 """ NAT44 interface output feature and services """
3865 external_addr = '1.2.3.4'
3866 external_port = 80
3867 local_port = 8080
3868
3869 self.vapi.nat44_forwarding_enable_disable(1)
3870 self.nat44_add_address(self.nat_addr)
3871 self.vapi.nat44_add_del_identity_mapping(ip=self.pg1.remote_ip4n)
3872 self.nat44_add_static_mapping(self.pg0.remote_ip4, external_addr,
3873 local_port, external_port,
3874 proto=IP_PROTOS.tcp, out2in_only=1)
3875 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3876 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
3877 is_inside=0)
3878 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
3879 is_inside=0)
3880
3881 # from client to service
3882 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3883 IP(src=self.pg1.remote_ip4, dst=external_addr) /
3884 TCP(sport=12345, dport=external_port))
3885 self.pg1.add_stream(p)
3886 self.pg_enable_capture(self.pg_interfaces)
3887 self.pg_start()
3888 capture = self.pg0.get_capture(1)
3889 p = capture[0]
3890 try:
3891 ip = p[IP]
3892 tcp = p[TCP]
3893 self.assertEqual(ip.dst, self.pg0.remote_ip4)
3894 self.assertEqual(tcp.dport, local_port)
3895 self.assert_packet_checksums_valid(p)
3896 except:
3897 self.logger.error(ppp("Unexpected or invalid packet:", p))
3898 raise
3899
3900 # from service back to client
3901 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3902 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3903 TCP(sport=local_port, dport=12345))
3904 self.pg0.add_stream(p)
3905 self.pg_enable_capture(self.pg_interfaces)
3906 self.pg_start()
3907 capture = self.pg1.get_capture(1)
3908 p = capture[0]
3909 try:
3910 ip = p[IP]
3911 tcp = p[TCP]
3912 self.assertEqual(ip.src, external_addr)
3913 self.assertEqual(tcp.sport, external_port)
3914 self.assert_packet_checksums_valid(p)
3915 except:
3916 self.logger.error(ppp("Unexpected or invalid packet:", p))
3917 raise
3918
3919 # from local network host to external network
3920 pkts = self.create_stream_in(self.pg0, self.pg1)
3921 self.pg0.add_stream(pkts)
3922 self.pg_enable_capture(self.pg_interfaces)
3923 self.pg_start()
3924 capture = self.pg1.get_capture(len(pkts))
3925 self.verify_capture_out(capture)
3926 pkts = self.create_stream_in(self.pg0, self.pg1)
3927 self.pg0.add_stream(pkts)
3928 self.pg_enable_capture(self.pg_interfaces)
3929 self.pg_start()
3930 capture = self.pg1.get_capture(len(pkts))
3931 self.verify_capture_out(capture)
3932
3933 # from external network back to local network host
3934 pkts = self.create_stream_out(self.pg1)
3935 self.pg1.add_stream(pkts)
3936 self.pg_enable_capture(self.pg_interfaces)
3937 self.pg_start()
3938 capture = self.pg0.get_capture(len(pkts))
3939 self.verify_capture_in(capture, self.pg0)
3940
3941 def test_output_feature_and_service2(self):
3942 """ NAT44 interface output feature and service host direct access """
3943 self.vapi.nat44_forwarding_enable_disable(1)
3944 self.nat44_add_address(self.nat_addr)
3945 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
3946 is_inside=0)
3947
3948 # session initiaded from service host - translate
3949 pkts = self.create_stream_in(self.pg0, self.pg1)
3950 self.pg0.add_stream(pkts)
3951 self.pg_enable_capture(self.pg_interfaces)
3952 self.pg_start()
3953 capture = self.pg1.get_capture(len(pkts))
3954 self.verify_capture_out(capture)
3955
3956 pkts = self.create_stream_out(self.pg1)
3957 self.pg1.add_stream(pkts)
3958 self.pg_enable_capture(self.pg_interfaces)
3959 self.pg_start()
3960 capture = self.pg0.get_capture(len(pkts))
3961 self.verify_capture_in(capture, self.pg0)
3962
3963 # session initiaded from remote host - do not translate
3964 self.tcp_port_in = 60303
3965 self.udp_port_in = 60304
3966 self.icmp_id_in = 60305
3967 pkts = self.create_stream_out(self.pg1,
3968 self.pg0.remote_ip4,
3969 use_inside_ports=True)
3970 self.pg1.add_stream(pkts)
3971 self.pg_enable_capture(self.pg_interfaces)
3972 self.pg_start()
3973 capture = self.pg0.get_capture(len(pkts))
3974 self.verify_capture_in(capture, self.pg0)
3975
3976 pkts = self.create_stream_in(self.pg0, self.pg1)
3977 self.pg0.add_stream(pkts)
3978 self.pg_enable_capture(self.pg_interfaces)
3979 self.pg_start()
3980 capture = self.pg1.get_capture(len(pkts))
3981 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
3982 same_port=True)
3983
3984 def test_output_feature_and_service3(self):
3985 """ NAT44 interface output feature and DST NAT """
3986 external_addr = '1.2.3.4'
3987 external_port = 80
3988 local_port = 8080
3989
3990 self.vapi.nat44_forwarding_enable_disable(1)
3991 self.nat44_add_address(self.nat_addr)
3992 self.nat44_add_static_mapping(self.pg1.remote_ip4, external_addr,
3993 local_port, external_port,
3994 proto=IP_PROTOS.tcp, out2in_only=1)
3995 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3996 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
3997 is_inside=0)
3998 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
3999 is_inside=0)
4000
4001 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4002 IP(src=self.pg0.remote_ip4, dst=external_addr) /
4003 TCP(sport=12345, dport=external_port))
4004 self.pg0.add_stream(p)
4005 self.pg_enable_capture(self.pg_interfaces)
4006 self.pg_start()
4007 capture = self.pg1.get_capture(1)
4008 p = capture[0]
4009 try:
4010 ip = p[IP]
4011 tcp = p[TCP]
4012 self.assertEqual(ip.src, self.pg0.remote_ip4)
4013 self.assertEqual(tcp.sport, 12345)
4014 self.assertEqual(ip.dst, self.pg1.remote_ip4)
4015 self.assertEqual(tcp.dport, local_port)
4016 self.assert_packet_checksums_valid(p)
4017 except:
4018 self.logger.error(ppp("Unexpected or invalid packet:", p))
4019 raise
4020
4021 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4022 IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
4023 TCP(sport=local_port, dport=12345))
4024 self.pg1.add_stream(p)
4025 self.pg_enable_capture(self.pg_interfaces)
4026 self.pg_start()
4027 capture = self.pg0.get_capture(1)
4028 p = capture[0]
4029 try:
4030 ip = p[IP]
4031 tcp = p[TCP]
4032 self.assertEqual(ip.src, external_addr)
4033 self.assertEqual(tcp.sport, external_port)
4034 self.assertEqual(ip.dst, self.pg0.remote_ip4)
4035 self.assertEqual(tcp.dport, 12345)
4036 self.assert_packet_checksums_valid(p)
4037 except:
4038 self.logger.error(ppp("Unexpected or invalid packet:", p))
4039 raise
4040
Matus Fabian182e37e2018-08-14 04:21:26 -07004041 def test_next_src_nat(self):
4042 """ On way back forward packet to nat44-in2out node. """
4043 twice_nat_addr = '10.0.1.3'
4044 external_port = 80
4045 local_port = 8080
4046 post_twice_nat_port = 0
4047
4048 self.vapi.nat44_forwarding_enable_disable(1)
4049 self.nat44_add_address(twice_nat_addr, twice_nat=1)
4050 self.nat44_add_static_mapping(self.pg6.remote_ip4, self.pg1.remote_ip4,
4051 local_port, external_port,
4052 proto=IP_PROTOS.tcp, out2in_only=1,
4053 self_twice_nat=1, vrf_id=1)
4054 self.vapi.nat44_interface_add_del_feature(self.pg6.sw_if_index,
4055 is_inside=0)
4056
4057 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
4058 IP(src=self.pg6.remote_ip4, dst=self.pg1.remote_ip4) /
4059 TCP(sport=12345, dport=external_port))
4060 self.pg6.add_stream(p)
4061 self.pg_enable_capture(self.pg_interfaces)
4062 self.pg_start()
4063 capture = self.pg6.get_capture(1)
4064 p = capture[0]
4065 try:
4066 ip = p[IP]
4067 tcp = p[TCP]
4068 self.assertEqual(ip.src, twice_nat_addr)
4069 self.assertNotEqual(tcp.sport, 12345)
4070 post_twice_nat_port = tcp.sport
4071 self.assertEqual(ip.dst, self.pg6.remote_ip4)
4072 self.assertEqual(tcp.dport, local_port)
4073 self.assert_packet_checksums_valid(p)
4074 except:
4075 self.logger.error(ppp("Unexpected or invalid packet:", p))
4076 raise
4077
4078 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
4079 IP(src=self.pg6.remote_ip4, dst=twice_nat_addr) /
4080 TCP(sport=local_port, dport=post_twice_nat_port))
4081 self.pg6.add_stream(p)
4082 self.pg_enable_capture(self.pg_interfaces)
4083 self.pg_start()
4084 capture = self.pg6.get_capture(1)
4085 p = capture[0]
4086 try:
4087 ip = p[IP]
4088 tcp = p[TCP]
4089 self.assertEqual(ip.src, self.pg1.remote_ip4)
4090 self.assertEqual(tcp.sport, external_port)
4091 self.assertEqual(ip.dst, self.pg6.remote_ip4)
4092 self.assertEqual(tcp.dport, 12345)
4093 self.assert_packet_checksums_valid(p)
4094 except:
4095 self.logger.error(ppp("Unexpected or invalid packet:", p))
4096 raise
4097
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004098 def twice_nat_common(self, self_twice_nat=False, same_pg=False, lb=False,
4099 client_id=None):
Matus Fabianb932d262017-12-18 05:38:24 -08004100 twice_nat_addr = '10.0.1.3'
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004101
Matus Fabianb932d262017-12-18 05:38:24 -08004102 port_in = 8080
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004103 if lb:
4104 if not same_pg:
4105 port_in1 = port_in
4106 port_in2 = port_in
4107 else:
4108 port_in1 = port_in+1
4109 port_in2 = port_in+2
4110
Matus Fabianb932d262017-12-18 05:38:24 -08004111 port_out = 80
4112 eh_port_out = 4567
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004113
4114 server1 = self.pg0.remote_hosts[0]
4115 server2 = self.pg0.remote_hosts[1]
4116 if lb and same_pg:
4117 server2 = server1
4118 if not lb:
4119 server = server1
4120
4121 pg0 = self.pg0
4122 if same_pg:
4123 pg1 = self.pg0
4124 else:
4125 pg1 = self.pg1
4126
4127 eh_translate = ((not self_twice_nat) or (not lb and same_pg) or
4128 client_id == 1)
4129
Matus Fabianb932d262017-12-18 05:38:24 -08004130 self.nat44_add_address(self.nat_addr)
4131 self.nat44_add_address(twice_nat_addr, twice_nat=1)
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004132 if not lb:
4133 self.nat44_add_static_mapping(pg0.remote_ip4, self.nat_addr,
4134 port_in, port_out,
4135 proto=IP_PROTOS.tcp,
4136 twice_nat=int(not self_twice_nat),
4137 self_twice_nat=int(self_twice_nat))
4138 else:
4139 locals = [{'addr': server1.ip4n,
4140 'port': port_in1,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07004141 'probability': 50,
4142 'vrf_id': 0},
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004143 {'addr': server2.ip4n,
4144 'port': port_in2,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07004145 'probability': 50,
4146 'vrf_id': 0}]
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004147 out_addr_n = socket.inet_pton(socket.AF_INET, self.nat_addr)
4148 self.vapi.nat44_add_del_lb_static_mapping(out_addr_n,
4149 port_out,
4150 IP_PROTOS.tcp,
4151 twice_nat=int(
4152 not self_twice_nat),
4153 self_twice_nat=int(
4154 self_twice_nat),
4155 local_num=len(locals),
4156 locals=locals)
4157 self.vapi.nat44_interface_add_del_feature(pg0.sw_if_index)
4158 self.vapi.nat44_interface_add_del_feature(pg1.sw_if_index,
Matus Fabianb932d262017-12-18 05:38:24 -08004159 is_inside=0)
4160
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004161 if same_pg:
4162 if not lb:
4163 client = server
4164 else:
4165 assert client_id is not None
4166 if client_id == 1:
4167 client = self.pg0.remote_hosts[0]
4168 elif client_id == 2:
4169 client = self.pg0.remote_hosts[1]
4170 else:
4171 client = pg1.remote_hosts[0]
4172 p = (Ether(src=pg1.remote_mac, dst=pg1.local_mac) /
4173 IP(src=client.ip4, dst=self.nat_addr) /
Matus Fabianb932d262017-12-18 05:38:24 -08004174 TCP(sport=eh_port_out, dport=port_out))
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004175 pg1.add_stream(p)
Matus Fabianb932d262017-12-18 05:38:24 -08004176 self.pg_enable_capture(self.pg_interfaces)
4177 self.pg_start()
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004178 capture = pg0.get_capture(1)
Matus Fabianb932d262017-12-18 05:38:24 -08004179 p = capture[0]
4180 try:
4181 ip = p[IP]
4182 tcp = p[TCP]
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004183 if lb:
4184 if ip.dst == server1.ip4:
4185 server = server1
4186 port_in = port_in1
4187 else:
4188 server = server2
4189 port_in = port_in2
4190 self.assertEqual(ip.dst, server.ip4)
4191 if lb and same_pg:
4192 self.assertIn(tcp.dport, [port_in1, port_in2])
4193 else:
4194 self.assertEqual(tcp.dport, port_in)
4195 if eh_translate:
4196 self.assertEqual(ip.src, twice_nat_addr)
4197 self.assertNotEqual(tcp.sport, eh_port_out)
4198 else:
4199 self.assertEqual(ip.src, client.ip4)
4200 self.assertEqual(tcp.sport, eh_port_out)
4201 eh_addr_in = ip.src
Matus Fabianb932d262017-12-18 05:38:24 -08004202 eh_port_in = tcp.sport
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004203 saved_port_in = tcp.dport
Klement Sekerad81ae412018-05-16 10:52:54 +02004204 self.assert_packet_checksums_valid(p)
Matus Fabianb932d262017-12-18 05:38:24 -08004205 except:
4206 self.logger.error(ppp("Unexpected or invalid packet:", p))
4207 raise
4208
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004209 p = (Ether(src=server.mac, dst=pg0.local_mac) /
4210 IP(src=server.ip4, dst=eh_addr_in) /
4211 TCP(sport=saved_port_in, dport=eh_port_in))
4212 pg0.add_stream(p)
Matus Fabianb932d262017-12-18 05:38:24 -08004213 self.pg_enable_capture(self.pg_interfaces)
4214 self.pg_start()
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004215 capture = pg1.get_capture(1)
Matus Fabianb932d262017-12-18 05:38:24 -08004216 p = capture[0]
4217 try:
4218 ip = p[IP]
4219 tcp = p[TCP]
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004220 self.assertEqual(ip.dst, client.ip4)
Matus Fabianb932d262017-12-18 05:38:24 -08004221 self.assertEqual(ip.src, self.nat_addr)
4222 self.assertEqual(tcp.dport, eh_port_out)
4223 self.assertEqual(tcp.sport, port_out)
Klement Sekerad81ae412018-05-16 10:52:54 +02004224 self.assert_packet_checksums_valid(p)
Matus Fabianb932d262017-12-18 05:38:24 -08004225 except:
4226 self.logger.error(ppp("Unexpected or invalid packet:", p))
4227 raise
4228
Matus Fabian70a26ac2018-05-14 06:20:28 -07004229 if eh_translate:
4230 sessions = self.vapi.nat44_user_session_dump(server.ip4n, 0)
4231 self.assertEqual(len(sessions), 1)
4232 self.assertTrue(sessions[0].ext_host_valid)
4233 self.assertTrue(sessions[0].is_twicenat)
4234 self.vapi.nat44_del_session(
4235 sessions[0].inside_ip_address,
4236 sessions[0].inside_port,
4237 sessions[0].protocol,
4238 ext_host_address=sessions[0].ext_host_nat_address,
4239 ext_host_port=sessions[0].ext_host_nat_port)
4240 sessions = self.vapi.nat44_user_session_dump(server.ip4n, 0)
4241 self.assertEqual(len(sessions), 0)
4242
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004243 def test_twice_nat(self):
4244 """ Twice NAT44 """
4245 self.twice_nat_common()
4246
4247 def test_self_twice_nat_positive(self):
4248 """ Self Twice NAT44 (positive test) """
4249 self.twice_nat_common(self_twice_nat=True, same_pg=True)
4250
4251 def test_self_twice_nat_negative(self):
4252 """ Self Twice NAT44 (negative test) """
4253 self.twice_nat_common(self_twice_nat=True)
4254
Matus Fabianb932d262017-12-18 05:38:24 -08004255 def test_twice_nat_lb(self):
4256 """ Twice NAT44 local service load balancing """
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004257 self.twice_nat_common(lb=True)
Matus Fabianb932d262017-12-18 05:38:24 -08004258
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004259 def test_self_twice_nat_lb_positive(self):
4260 """ Self Twice NAT44 local service load balancing (positive test) """
4261 self.twice_nat_common(lb=True, self_twice_nat=True, same_pg=True,
4262 client_id=1)
Matus Fabianb932d262017-12-18 05:38:24 -08004263
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004264 def test_self_twice_nat_lb_negative(self):
4265 """ Self Twice NAT44 local service load balancing (negative test) """
4266 self.twice_nat_common(lb=True, self_twice_nat=True, same_pg=True,
4267 client_id=2)
Matus Fabianb932d262017-12-18 05:38:24 -08004268
4269 def test_twice_nat_interface_addr(self):
4270 """ Acquire twice NAT44 addresses from interface """
Matus Fabiana6110b62018-06-13 05:39:07 -07004271 self.vapi.nat44_add_interface_addr(self.pg3.sw_if_index, twice_nat=1)
Matus Fabianb932d262017-12-18 05:38:24 -08004272
4273 # no address in NAT pool
4274 adresses = self.vapi.nat44_address_dump()
4275 self.assertEqual(0, len(adresses))
4276
4277 # configure interface address and check NAT address pool
Matus Fabiana6110b62018-06-13 05:39:07 -07004278 self.pg3.config_ip4()
Matus Fabianb932d262017-12-18 05:38:24 -08004279 adresses = self.vapi.nat44_address_dump()
4280 self.assertEqual(1, len(adresses))
Matus Fabiana6110b62018-06-13 05:39:07 -07004281 self.assertEqual(adresses[0].ip_address[0:4], self.pg3.local_ip4n)
Matus Fabianb932d262017-12-18 05:38:24 -08004282 self.assertEqual(adresses[0].twice_nat, 1)
4283
4284 # remove interface address and check NAT address pool
Matus Fabiana6110b62018-06-13 05:39:07 -07004285 self.pg3.unconfig_ip4()
Matus Fabianb932d262017-12-18 05:38:24 -08004286 adresses = self.vapi.nat44_address_dump()
4287 self.assertEqual(0, len(adresses))
4288
Matus Fabianebdf1902018-05-04 03:57:42 -07004289 def test_tcp_session_close_in(self):
4290 """ Close TCP session from inside network """
Matus Fabian229c1aa2018-05-28 04:09:52 -07004291 self.tcp_port_out = 10505
Matus Fabianebdf1902018-05-04 03:57:42 -07004292 self.nat44_add_address(self.nat_addr)
Matus Fabian229c1aa2018-05-28 04:09:52 -07004293 self.nat44_add_static_mapping(self.pg0.remote_ip4,
4294 self.nat_addr,
4295 self.tcp_port_in,
4296 self.tcp_port_out,
4297 proto=IP_PROTOS.tcp,
4298 twice_nat=1)
Matus Fabianebdf1902018-05-04 03:57:42 -07004299 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4300 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4301 is_inside=0)
4302
4303 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
4304 start_sessnum = len(sessions)
4305
4306 self.initiate_tcp_session(self.pg0, self.pg1)
4307
Matus Fabian229c1aa2018-05-28 04:09:52 -07004308 # FIN packet in -> out
4309 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4310 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4311 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
4312 flags="FA", seq=100, ack=300))
4313 self.pg0.add_stream(p)
4314 self.pg_enable_capture(self.pg_interfaces)
4315 self.pg_start()
4316 self.pg1.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07004317
Matus Fabian229c1aa2018-05-28 04:09:52 -07004318 pkts = []
Matus Fabianebdf1902018-05-04 03:57:42 -07004319
Matus Fabian229c1aa2018-05-28 04:09:52 -07004320 # ACK packet out -> in
4321 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4322 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4323 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
4324 flags="A", seq=300, ack=101))
4325 pkts.append(p)
Matus Fabianebdf1902018-05-04 03:57:42 -07004326
Matus Fabian229c1aa2018-05-28 04:09:52 -07004327 # FIN packet out -> in
4328 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4329 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4330 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
4331 flags="FA", seq=300, ack=101))
4332 pkts.append(p)
Matus Fabianebdf1902018-05-04 03:57:42 -07004333
Matus Fabian229c1aa2018-05-28 04:09:52 -07004334 self.pg1.add_stream(pkts)
4335 self.pg_enable_capture(self.pg_interfaces)
4336 self.pg_start()
4337 self.pg0.get_capture(2)
Matus Fabianebdf1902018-05-04 03:57:42 -07004338
Matus Fabian229c1aa2018-05-28 04:09:52 -07004339 # ACK packet in -> out
4340 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4341 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4342 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
4343 flags="A", seq=101, ack=301))
4344 self.pg0.add_stream(p)
4345 self.pg_enable_capture(self.pg_interfaces)
4346 self.pg_start()
4347 self.pg1.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07004348
Matus Fabian229c1aa2018-05-28 04:09:52 -07004349 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n,
4350 0)
4351 self.assertEqual(len(sessions) - start_sessnum, 0)
Matus Fabianebdf1902018-05-04 03:57:42 -07004352
4353 def test_tcp_session_close_out(self):
4354 """ Close TCP session from outside network """
Matus Fabian229c1aa2018-05-28 04:09:52 -07004355 self.tcp_port_out = 10505
Matus Fabianebdf1902018-05-04 03:57:42 -07004356 self.nat44_add_address(self.nat_addr)
Matus Fabian229c1aa2018-05-28 04:09:52 -07004357 self.nat44_add_static_mapping(self.pg0.remote_ip4,
4358 self.nat_addr,
4359 self.tcp_port_in,
4360 self.tcp_port_out,
4361 proto=IP_PROTOS.tcp,
4362 twice_nat=1)
Matus Fabianebdf1902018-05-04 03:57:42 -07004363 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4364 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4365 is_inside=0)
4366
4367 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
4368 start_sessnum = len(sessions)
4369
4370 self.initiate_tcp_session(self.pg0, self.pg1)
4371
Matus Fabian229c1aa2018-05-28 04:09:52 -07004372 # FIN packet out -> in
4373 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4374 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4375 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
4376 flags="FA", seq=100, ack=300))
4377 self.pg1.add_stream(p)
4378 self.pg_enable_capture(self.pg_interfaces)
4379 self.pg_start()
4380 self.pg0.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07004381
Matus Fabian229c1aa2018-05-28 04:09:52 -07004382 # FIN+ACK packet in -> out
4383 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4384 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4385 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
4386 flags="FA", seq=300, ack=101))
Matus Fabianebdf1902018-05-04 03:57:42 -07004387
Matus Fabian229c1aa2018-05-28 04:09:52 -07004388 self.pg0.add_stream(p)
4389 self.pg_enable_capture(self.pg_interfaces)
4390 self.pg_start()
4391 self.pg1.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07004392
Matus Fabian229c1aa2018-05-28 04:09:52 -07004393 # ACK packet out -> in
4394 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4395 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4396 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
4397 flags="A", seq=101, ack=301))
4398 self.pg1.add_stream(p)
4399 self.pg_enable_capture(self.pg_interfaces)
4400 self.pg_start()
4401 self.pg0.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07004402
Matus Fabian229c1aa2018-05-28 04:09:52 -07004403 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n,
4404 0)
4405 self.assertEqual(len(sessions) - start_sessnum, 0)
Matus Fabianebdf1902018-05-04 03:57:42 -07004406
4407 def test_tcp_session_close_simultaneous(self):
4408 """ Close TCP session from inside network """
Matus Fabian229c1aa2018-05-28 04:09:52 -07004409 self.tcp_port_out = 10505
Matus Fabianebdf1902018-05-04 03:57:42 -07004410 self.nat44_add_address(self.nat_addr)
Matus Fabian229c1aa2018-05-28 04:09:52 -07004411 self.nat44_add_static_mapping(self.pg0.remote_ip4,
4412 self.nat_addr,
4413 self.tcp_port_in,
4414 self.tcp_port_out,
4415 proto=IP_PROTOS.tcp,
4416 twice_nat=1)
Matus Fabianebdf1902018-05-04 03:57:42 -07004417 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4418 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4419 is_inside=0)
4420
4421 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
4422 start_sessnum = len(sessions)
4423
4424 self.initiate_tcp_session(self.pg0, self.pg1)
4425
Matus Fabian229c1aa2018-05-28 04:09:52 -07004426 # FIN packet in -> out
4427 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4428 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4429 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
4430 flags="FA", seq=100, ack=300))
4431 self.pg0.add_stream(p)
4432 self.pg_enable_capture(self.pg_interfaces)
4433 self.pg_start()
4434 self.pg1.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07004435
Matus Fabian229c1aa2018-05-28 04:09:52 -07004436 # FIN packet out -> in
4437 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4438 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4439 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
4440 flags="FA", seq=300, ack=100))
4441 self.pg1.add_stream(p)
4442 self.pg_enable_capture(self.pg_interfaces)
4443 self.pg_start()
4444 self.pg0.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07004445
Matus Fabian229c1aa2018-05-28 04:09:52 -07004446 # ACK packet in -> out
4447 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4448 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4449 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
4450 flags="A", seq=101, ack=301))
4451 self.pg0.add_stream(p)
4452 self.pg_enable_capture(self.pg_interfaces)
4453 self.pg_start()
4454 self.pg1.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07004455
Matus Fabian229c1aa2018-05-28 04:09:52 -07004456 # ACK packet out -> in
4457 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4458 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4459 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
4460 flags="A", seq=301, ack=101))
4461 self.pg1.add_stream(p)
4462 self.pg_enable_capture(self.pg_interfaces)
4463 self.pg_start()
4464 self.pg0.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07004465
Matus Fabian229c1aa2018-05-28 04:09:52 -07004466 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n,
4467 0)
4468 self.assertEqual(len(sessions) - start_sessnum, 0)
Matus Fabianebdf1902018-05-04 03:57:42 -07004469
Matus Fabiana6110b62018-06-13 05:39:07 -07004470 def test_one_armed_nat44_static(self):
4471 """ One armed NAT44 and 1:1 NAPT asymmetrical rule """
4472 remote_host = self.pg4.remote_hosts[0]
4473 local_host = self.pg4.remote_hosts[1]
4474 external_port = 80
4475 local_port = 8080
4476 eh_port_in = 0
4477
4478 self.vapi.nat44_forwarding_enable_disable(1)
4479 self.nat44_add_address(self.nat_addr, twice_nat=1)
4480 self.nat44_add_static_mapping(local_host.ip4, self.nat_addr,
4481 local_port, external_port,
4482 proto=IP_PROTOS.tcp, out2in_only=1,
4483 twice_nat=1)
4484 self.vapi.nat44_interface_add_del_feature(self.pg4.sw_if_index)
4485 self.vapi.nat44_interface_add_del_feature(self.pg4.sw_if_index,
4486 is_inside=0)
4487
4488 # from client to service
4489 p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
4490 IP(src=remote_host.ip4, dst=self.nat_addr) /
4491 TCP(sport=12345, dport=external_port))
4492 self.pg4.add_stream(p)
4493 self.pg_enable_capture(self.pg_interfaces)
4494 self.pg_start()
4495 capture = self.pg4.get_capture(1)
4496 p = capture[0]
4497 try:
4498 ip = p[IP]
4499 tcp = p[TCP]
4500 self.assertEqual(ip.dst, local_host.ip4)
4501 self.assertEqual(ip.src, self.nat_addr)
4502 self.assertEqual(tcp.dport, local_port)
4503 self.assertNotEqual(tcp.sport, 12345)
4504 eh_port_in = tcp.sport
4505 self.assert_packet_checksums_valid(p)
4506 except:
4507 self.logger.error(ppp("Unexpected or invalid packet:", p))
4508 raise
4509
4510 # from service back to client
4511 p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
4512 IP(src=local_host.ip4, dst=self.nat_addr) /
4513 TCP(sport=local_port, dport=eh_port_in))
4514 self.pg4.add_stream(p)
4515 self.pg_enable_capture(self.pg_interfaces)
4516 self.pg_start()
4517 capture = self.pg4.get_capture(1)
4518 p = capture[0]
4519 try:
4520 ip = p[IP]
4521 tcp = p[TCP]
4522 self.assertEqual(ip.src, self.nat_addr)
4523 self.assertEqual(ip.dst, remote_host.ip4)
4524 self.assertEqual(tcp.sport, external_port)
4525 self.assertEqual(tcp.dport, 12345)
4526 self.assert_packet_checksums_valid(p)
4527 except:
4528 self.logger.error(ppp("Unexpected or invalid packet:", p))
4529 raise
4530
4531 def test_static_with_port_out2(self):
4532 """ 1:1 NAPT asymmetrical rule """
4533
4534 external_port = 80
4535 local_port = 8080
4536
4537 self.vapi.nat44_forwarding_enable_disable(1)
4538 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
4539 local_port, external_port,
4540 proto=IP_PROTOS.tcp, out2in_only=1)
4541 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4542 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4543 is_inside=0)
4544
4545 # from client to service
4546 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4547 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4548 TCP(sport=12345, dport=external_port))
4549 self.pg1.add_stream(p)
4550 self.pg_enable_capture(self.pg_interfaces)
4551 self.pg_start()
4552 capture = self.pg0.get_capture(1)
4553 p = capture[0]
4554 try:
4555 ip = p[IP]
4556 tcp = p[TCP]
4557 self.assertEqual(ip.dst, self.pg0.remote_ip4)
4558 self.assertEqual(tcp.dport, local_port)
4559 self.assert_packet_checksums_valid(p)
4560 except:
4561 self.logger.error(ppp("Unexpected or invalid packet:", p))
4562 raise
4563
4564 # ICMP error
4565 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
4566 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4567 ICMP(type=11) / capture[0][IP])
4568 self.pg0.add_stream(p)
4569 self.pg_enable_capture(self.pg_interfaces)
4570 self.pg_start()
4571 capture = self.pg1.get_capture(1)
4572 p = capture[0]
4573 try:
4574 self.assertEqual(p[IP].src, self.nat_addr)
4575 inner = p[IPerror]
4576 self.assertEqual(inner.dst, self.nat_addr)
4577 self.assertEqual(inner[TCPerror].dport, external_port)
4578 except:
4579 self.logger.error(ppp("Unexpected or invalid packet:", p))
4580 raise
4581
4582 # from service back to client
4583 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4584 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4585 TCP(sport=local_port, dport=12345))
4586 self.pg0.add_stream(p)
4587 self.pg_enable_capture(self.pg_interfaces)
4588 self.pg_start()
4589 capture = self.pg1.get_capture(1)
4590 p = capture[0]
4591 try:
4592 ip = p[IP]
4593 tcp = p[TCP]
4594 self.assertEqual(ip.src, self.nat_addr)
4595 self.assertEqual(tcp.sport, external_port)
4596 self.assert_packet_checksums_valid(p)
4597 except:
4598 self.logger.error(ppp("Unexpected or invalid packet:", p))
4599 raise
4600
4601 # ICMP error
4602 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
4603 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4604 ICMP(type=11) / capture[0][IP])
4605 self.pg1.add_stream(p)
4606 self.pg_enable_capture(self.pg_interfaces)
4607 self.pg_start()
4608 capture = self.pg0.get_capture(1)
4609 p = capture[0]
4610 try:
4611 self.assertEqual(p[IP].dst, self.pg0.remote_ip4)
4612 inner = p[IPerror]
4613 self.assertEqual(inner.src, self.pg0.remote_ip4)
4614 self.assertEqual(inner[TCPerror].sport, local_port)
4615 except:
4616 self.logger.error(ppp("Unexpected or invalid packet:", p))
4617 raise
4618
4619 # from client to server (no translation)
4620 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4621 IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
4622 TCP(sport=12346, dport=local_port))
4623 self.pg1.add_stream(p)
4624 self.pg_enable_capture(self.pg_interfaces)
4625 self.pg_start()
4626 capture = self.pg0.get_capture(1)
4627 p = capture[0]
4628 try:
4629 ip = p[IP]
4630 tcp = p[TCP]
4631 self.assertEqual(ip.dst, self.pg0.remote_ip4)
4632 self.assertEqual(tcp.dport, local_port)
4633 self.assert_packet_checksums_valid(p)
4634 except:
4635 self.logger.error(ppp("Unexpected or invalid packet:", p))
4636 raise
4637
4638 # from service back to client (no translation)
4639 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4640 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4641 TCP(sport=local_port, dport=12346))
4642 self.pg0.add_stream(p)
4643 self.pg_enable_capture(self.pg_interfaces)
4644 self.pg_start()
4645 capture = self.pg1.get_capture(1)
4646 p = capture[0]
4647 try:
4648 ip = p[IP]
4649 tcp = p[TCP]
4650 self.assertEqual(ip.src, self.pg0.remote_ip4)
4651 self.assertEqual(tcp.sport, local_port)
4652 self.assert_packet_checksums_valid(p)
4653 except:
4654 self.logger.error(ppp("Unexpected or invalid packet:", p))
4655 raise
4656
Matus Fabian235a47e2018-06-25 16:42:36 -07004657 def test_output_feature(self):
4658 """ NAT44 interface output feature (in2out postrouting) """
4659 self.vapi.nat44_forwarding_enable_disable(1)
4660 self.nat44_add_address(self.nat_addr)
4661 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
4662 is_inside=0)
4663 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
4664 is_inside=0)
4665
4666 # in2out
4667 pkts = self.create_stream_in(self.pg0, self.pg1)
4668 self.pg0.add_stream(pkts)
4669 self.pg_enable_capture(self.pg_interfaces)
4670 self.pg_start()
4671 capture = self.pg1.get_capture(len(pkts))
4672 self.verify_capture_out(capture)
4673
4674 # out2in
4675 pkts = self.create_stream_out(self.pg1)
4676 self.pg1.add_stream(pkts)
4677 self.pg_enable_capture(self.pg_interfaces)
4678 self.pg_start()
4679 capture = self.pg0.get_capture(len(pkts))
4680 self.verify_capture_in(capture, self.pg0)
4681
Matus Fabian8008d7c2018-07-09 01:34:20 -07004682 def test_multiple_vrf(self):
4683 """ Multiple VRF setup """
4684 external_addr = '1.2.3.4'
4685 external_port = 80
4686 local_port = 8080
4687 port = 0
4688
4689 self.vapi.nat44_forwarding_enable_disable(1)
4690 self.nat44_add_address(self.nat_addr)
4691 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4692 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
4693 is_inside=0)
4694 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
4695 is_inside=0)
4696 self.vapi.nat44_interface_add_del_feature(self.pg5.sw_if_index)
4697 self.vapi.nat44_interface_add_del_feature(self.pg5.sw_if_index,
4698 is_inside=0)
4699 self.vapi.nat44_interface_add_del_feature(self.pg6.sw_if_index,
4700 is_inside=0)
4701 self.nat44_add_static_mapping(self.pg5.remote_ip4, external_addr,
4702 local_port, external_port, vrf_id=1,
4703 proto=IP_PROTOS.tcp, out2in_only=1)
4704 self.nat44_add_static_mapping(
4705 self.pg0.remote_ip4, external_sw_if_index=self.pg0.sw_if_index,
4706 local_port=local_port, vrf_id=0, external_port=external_port,
4707 proto=IP_PROTOS.tcp, out2in_only=1)
4708
4709 # from client to service (both VRF1)
4710 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
4711 IP(src=self.pg6.remote_ip4, dst=external_addr) /
4712 TCP(sport=12345, dport=external_port))
4713 self.pg6.add_stream(p)
4714 self.pg_enable_capture(self.pg_interfaces)
4715 self.pg_start()
4716 capture = self.pg5.get_capture(1)
4717 p = capture[0]
4718 try:
4719 ip = p[IP]
4720 tcp = p[TCP]
4721 self.assertEqual(ip.dst, self.pg5.remote_ip4)
4722 self.assertEqual(tcp.dport, local_port)
4723 self.assert_packet_checksums_valid(p)
4724 except:
4725 self.logger.error(ppp("Unexpected or invalid packet:", p))
4726 raise
4727
4728 # from service back to client (both VRF1)
4729 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
4730 IP(src=self.pg5.remote_ip4, dst=self.pg6.remote_ip4) /
4731 TCP(sport=local_port, dport=12345))
4732 self.pg5.add_stream(p)
4733 self.pg_enable_capture(self.pg_interfaces)
4734 self.pg_start()
4735 capture = self.pg6.get_capture(1)
4736 p = capture[0]
4737 try:
4738 ip = p[IP]
4739 tcp = p[TCP]
4740 self.assertEqual(ip.src, external_addr)
4741 self.assertEqual(tcp.sport, external_port)
4742 self.assert_packet_checksums_valid(p)
4743 except:
4744 self.logger.error(ppp("Unexpected or invalid packet:", p))
4745 raise
4746
4747 # dynamic NAT from VRF1 to VRF0 (output-feature)
4748 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
4749 IP(src=self.pg5.remote_ip4, dst=self.pg1.remote_ip4) /
4750 TCP(sport=2345, dport=22))
4751 self.pg5.add_stream(p)
4752 self.pg_enable_capture(self.pg_interfaces)
4753 self.pg_start()
4754 capture = self.pg1.get_capture(1)
4755 p = capture[0]
4756 try:
4757 ip = p[IP]
4758 tcp = p[TCP]
4759 self.assertEqual(ip.src, self.nat_addr)
4760 self.assertNotEqual(tcp.sport, 2345)
4761 self.assert_packet_checksums_valid(p)
4762 port = tcp.sport
4763 except:
4764 self.logger.error(ppp("Unexpected or invalid packet:", p))
4765 raise
4766
4767 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4768 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4769 TCP(sport=22, dport=port))
4770 self.pg1.add_stream(p)
4771 self.pg_enable_capture(self.pg_interfaces)
4772 self.pg_start()
4773 capture = self.pg5.get_capture(1)
4774 p = capture[0]
4775 try:
4776 ip = p[IP]
4777 tcp = p[TCP]
4778 self.assertEqual(ip.dst, self.pg5.remote_ip4)
4779 self.assertEqual(tcp.dport, 2345)
4780 self.assert_packet_checksums_valid(p)
4781 except:
4782 self.logger.error(ppp("Unexpected or invalid packet:", p))
4783 raise
4784
4785 # from client VRF1 to service VRF0
4786 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
4787 IP(src=self.pg6.remote_ip4, dst=self.pg0.local_ip4) /
4788 TCP(sport=12346, dport=external_port))
4789 self.pg6.add_stream(p)
4790 self.pg_enable_capture(self.pg_interfaces)
4791 self.pg_start()
4792 capture = self.pg0.get_capture(1)
4793 p = capture[0]
4794 try:
4795 ip = p[IP]
4796 tcp = p[TCP]
4797 self.assertEqual(ip.dst, self.pg0.remote_ip4)
4798 self.assertEqual(tcp.dport, local_port)
4799 self.assert_packet_checksums_valid(p)
4800 except:
4801 self.logger.error(ppp("Unexpected or invalid packet:", p))
4802 raise
4803
4804 # from service VRF0 back to client VRF1
4805 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4806 IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
4807 TCP(sport=local_port, dport=12346))
4808 self.pg0.add_stream(p)
4809 self.pg_enable_capture(self.pg_interfaces)
4810 self.pg_start()
4811 capture = self.pg6.get_capture(1)
4812 p = capture[0]
4813 try:
4814 ip = p[IP]
4815 tcp = p[TCP]
4816 self.assertEqual(ip.src, self.pg0.local_ip4)
4817 self.assertEqual(tcp.sport, external_port)
4818 self.assert_packet_checksums_valid(p)
4819 except:
4820 self.logger.error(ppp("Unexpected or invalid packet:", p))
4821 raise
4822
4823 # from client VRF0 to service VRF1
4824 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4825 IP(src=self.pg0.remote_ip4, dst=external_addr) /
4826 TCP(sport=12347, dport=external_port))
4827 self.pg0.add_stream(p)
4828 self.pg_enable_capture(self.pg_interfaces)
4829 self.pg_start()
4830 capture = self.pg5.get_capture(1)
4831 p = capture[0]
4832 try:
4833 ip = p[IP]
4834 tcp = p[TCP]
4835 self.assertEqual(ip.dst, self.pg5.remote_ip4)
4836 self.assertEqual(tcp.dport, local_port)
4837 self.assert_packet_checksums_valid(p)
4838 except:
4839 self.logger.error(ppp("Unexpected or invalid packet:", p))
4840 raise
4841
4842 # from service VRF1 back to client VRF0
4843 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
4844 IP(src=self.pg5.remote_ip4, dst=self.pg0.remote_ip4) /
4845 TCP(sport=local_port, dport=12347))
4846 self.pg5.add_stream(p)
4847 self.pg_enable_capture(self.pg_interfaces)
4848 self.pg_start()
4849 capture = self.pg0.get_capture(1)
4850 p = capture[0]
4851 try:
4852 ip = p[IP]
4853 tcp = p[TCP]
4854 self.assertEqual(ip.src, external_addr)
4855 self.assertEqual(tcp.sport, external_port)
4856 self.assert_packet_checksums_valid(p)
4857 except:
4858 self.logger.error(ppp("Unexpected or invalid packet:", p))
4859 raise
4860
4861 # from client to server (both VRF1, no translation)
4862 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
4863 IP(src=self.pg6.remote_ip4, dst=self.pg5.remote_ip4) /
4864 TCP(sport=12348, dport=local_port))
4865 self.pg6.add_stream(p)
4866 self.pg_enable_capture(self.pg_interfaces)
4867 self.pg_start()
4868 capture = self.pg5.get_capture(1)
4869 p = capture[0]
4870 try:
4871 ip = p[IP]
4872 tcp = p[TCP]
4873 self.assertEqual(ip.dst, self.pg5.remote_ip4)
4874 self.assertEqual(tcp.dport, local_port)
4875 self.assert_packet_checksums_valid(p)
4876 except:
4877 self.logger.error(ppp("Unexpected or invalid packet:", p))
4878 raise
4879
4880 # from server back to client (both VRF1, no translation)
4881 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
4882 IP(src=self.pg5.remote_ip4, dst=self.pg6.remote_ip4) /
4883 TCP(sport=local_port, dport=12348))
4884 self.pg5.add_stream(p)
4885 self.pg_enable_capture(self.pg_interfaces)
4886 self.pg_start()
4887 capture = self.pg6.get_capture(1)
4888 p = capture[0]
4889 try:
4890 ip = p[IP]
4891 tcp = p[TCP]
4892 self.assertEqual(ip.src, self.pg5.remote_ip4)
4893 self.assertEqual(tcp.sport, local_port)
4894 self.assert_packet_checksums_valid(p)
4895 except:
4896 self.logger.error(ppp("Unexpected or invalid packet:", p))
4897 raise
4898
4899 # from client VRF1 to server VRF0 (no translation)
4900 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4901 IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
4902 TCP(sport=local_port, dport=12349))
4903 self.pg0.add_stream(p)
4904 self.pg_enable_capture(self.pg_interfaces)
4905 self.pg_start()
4906 capture = self.pg6.get_capture(1)
4907 p = capture[0]
4908 try:
4909 ip = p[IP]
4910 tcp = p[TCP]
4911 self.assertEqual(ip.src, self.pg0.remote_ip4)
4912 self.assertEqual(tcp.sport, local_port)
4913 self.assert_packet_checksums_valid(p)
4914 except:
4915 self.logger.error(ppp("Unexpected or invalid packet:", p))
4916 raise
4917
4918 # from server VRF0 back to client VRF1 (no translation)
4919 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4920 IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
4921 TCP(sport=local_port, dport=12349))
4922 self.pg0.add_stream(p)
4923 self.pg_enable_capture(self.pg_interfaces)
4924 self.pg_start()
4925 capture = self.pg6.get_capture(1)
4926 p = capture[0]
4927 try:
4928 ip = p[IP]
4929 tcp = p[TCP]
4930 self.assertEqual(ip.src, self.pg0.remote_ip4)
4931 self.assertEqual(tcp.sport, local_port)
4932 self.assert_packet_checksums_valid(p)
4933 except:
4934 self.logger.error(ppp("Unexpected or invalid packet:", p))
4935 raise
4936
4937 # from client VRF0 to server VRF1 (no translation)
4938 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4939 IP(src=self.pg0.remote_ip4, dst=self.pg5.remote_ip4) /
4940 TCP(sport=12344, dport=local_port))
4941 self.pg0.add_stream(p)
4942 self.pg_enable_capture(self.pg_interfaces)
4943 self.pg_start()
4944 capture = self.pg5.get_capture(1)
4945 p = capture[0]
4946 try:
4947 ip = p[IP]
4948 tcp = p[TCP]
4949 self.assertEqual(ip.dst, self.pg5.remote_ip4)
4950 self.assertEqual(tcp.dport, local_port)
4951 self.assert_packet_checksums_valid(p)
4952 except:
4953 self.logger.error(ppp("Unexpected or invalid packet:", p))
4954 raise
4955
4956 # from server VRF1 back to client VRF0 (no translation)
4957 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
4958 IP(src=self.pg5.remote_ip4, dst=self.pg0.remote_ip4) /
4959 TCP(sport=local_port, dport=12344))
4960 self.pg5.add_stream(p)
4961 self.pg_enable_capture(self.pg_interfaces)
4962 self.pg_start()
4963 capture = self.pg0.get_capture(1)
4964 p = capture[0]
4965 try:
4966 ip = p[IP]
4967 tcp = p[TCP]
4968 self.assertEqual(ip.src, self.pg5.remote_ip4)
4969 self.assertEqual(tcp.sport, local_port)
4970 self.assert_packet_checksums_valid(p)
4971 except:
4972 self.logger.error(ppp("Unexpected or invalid packet:", p))
4973 raise
4974
Matus Fabian878c6462018-08-23 00:33:35 -07004975 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
4976 def test_session_timeout(self):
4977 """ NAT44 session timeouts """
4978 self.nat44_add_address(self.nat_addr)
4979 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4980 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4981 is_inside=0)
4982 self.vapi.nat_set_timeouts(icmp=5)
4983
4984 max_sessions = 1000
4985 pkts = []
4986 for i in range(0, max_sessions):
4987 src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
4988 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
4989 IP(src=src, dst=self.pg1.remote_ip4) /
4990 ICMP(id=1025, type='echo-request'))
4991 pkts.append(p)
4992 self.pg0.add_stream(pkts)
4993 self.pg_enable_capture(self.pg_interfaces)
4994 self.pg_start()
4995 self.pg1.get_capture(max_sessions)
4996
4997 sleep(10)
4998
4999 pkts = []
5000 for i in range(0, max_sessions):
5001 src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
5002 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5003 IP(src=src, dst=self.pg1.remote_ip4) /
5004 ICMP(id=1026, type='echo-request'))
5005 pkts.append(p)
5006 self.pg0.add_stream(pkts)
5007 self.pg_enable_capture(self.pg_interfaces)
5008 self.pg_start()
5009 self.pg1.get_capture(max_sessions)
5010
5011 nsessions = 0
5012 users = self.vapi.nat44_user_dump()
5013 for user in users:
5014 nsessions = nsessions + user.nsessions
5015 self.assertLess(nsessions, 2 * max_sessions)
5016
5017 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
5018 def test_session_limit_per_user(self):
5019 """ Maximum sessions per user limit """
5020 self.nat44_add_address(self.nat_addr)
5021 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5022 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
5023 is_inside=0)
5024 self.vapi.set_ipfix_exporter(collector_address=self.pg2.remote_ip4n,
5025 src_address=self.pg2.local_ip4n,
5026 path_mtu=512,
5027 template_interval=10)
5028
5029 # get maximum number of translations per user
5030 nat44_config = self.vapi.nat_show_config()
5031
5032 pkts = []
5033 for port in range(0, nat44_config.max_translations_per_user):
5034 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5035 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5036 UDP(sport=1025 + port, dport=1025 + port))
5037 pkts.append(p)
5038
5039 self.pg0.add_stream(pkts)
5040 self.pg_enable_capture(self.pg_interfaces)
5041 self.pg_start()
5042 capture = self.pg1.get_capture(len(pkts))
5043
5044 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
5045 src_port=self.ipfix_src_port)
5046
5047 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5048 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5049 UDP(sport=3001, dport=3002))
5050 self.pg0.add_stream(p)
5051 self.pg_enable_capture(self.pg_interfaces)
5052 self.pg_start()
5053 capture = self.pg1.assert_nothing_captured()
5054
5055 # verify IPFIX logging
5056 self.vapi.cli("ipfix flush") # FIXME this should be an API call
5057 sleep(1)
5058 capture = self.pg2.get_capture(10)
5059 ipfix = IPFIXDecoder()
5060 # first load template
5061 for p in capture:
5062 self.assertTrue(p.haslayer(IPFIX))
5063 if p.haslayer(Template):
5064 ipfix.add_template(p.getlayer(Template))
5065 # verify events in data set
5066 for p in capture:
5067 if p.haslayer(Data):
5068 data = ipfix.decode_data_set(p.getlayer(Set))
5069 self.verify_ipfix_max_entries_per_user(
5070 data,
5071 nat44_config.max_translations_per_user,
5072 self.pg0.remote_ip4n)
5073
Matus Fabiande886752016-12-07 03:38:19 -08005074 def tearDown(self):
Matus Fabiana6110b62018-06-13 05:39:07 -07005075 super(TestNAT44EndpointDependent, self).tearDown()
Matus Fabiande886752016-12-07 03:38:19 -08005076 if not self.vpp_dead:
Matus Fabian82119542018-01-25 01:13:22 -08005077 self.logger.info(self.vapi.cli("show nat44 addresses"))
5078 self.logger.info(self.vapi.cli("show nat44 interfaces"))
5079 self.logger.info(self.vapi.cli("show nat44 static mappings"))
5080 self.logger.info(self.vapi.cli("show nat44 interface address"))
5081 self.logger.info(self.vapi.cli("show nat44 sessions detail"))
Matus Fabian229c1aa2018-05-28 04:09:52 -07005082 self.logger.info(self.vapi.cli("show nat44 hash tables detail"))
Matus Fabian878c6462018-08-23 00:33:35 -07005083 self.logger.info(self.vapi.cli("show nat timeouts"))
Matus Fabian2ba92e32017-08-21 07:05:03 -07005084 self.clear_nat44()
Matus Fabian229c1aa2018-05-28 04:09:52 -07005085 self.vapi.cli("clear logging")
Matus Fabiande886752016-12-07 03:38:19 -08005086
Matus Fabianeea28d72017-01-13 04:15:54 -08005087
Juraj Slobodacba69362017-12-19 02:09:32 +01005088class TestNAT44Out2InDPO(MethodHolder):
5089 """ NAT44 Test Cases using out2in DPO """
5090
5091 @classmethod
5092 def setUpConstants(cls):
5093 super(TestNAT44Out2InDPO, cls).setUpConstants()
5094 cls.vpp_cmdline.extend(["nat", "{", "out2in dpo", "}"])
5095
5096 @classmethod
5097 def setUpClass(cls):
5098 super(TestNAT44Out2InDPO, cls).setUpClass()
Matus Fabian229c1aa2018-05-28 04:09:52 -07005099 cls.vapi.cli("set log class nat level debug")
Juraj Slobodacba69362017-12-19 02:09:32 +01005100
5101 try:
5102 cls.tcp_port_in = 6303
5103 cls.tcp_port_out = 6303
5104 cls.udp_port_in = 6304
5105 cls.udp_port_out = 6304
5106 cls.icmp_id_in = 6305
5107 cls.icmp_id_out = 6305
5108 cls.nat_addr = '10.0.0.3'
5109 cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
5110 cls.dst_ip4 = '192.168.70.1'
5111
5112 cls.create_pg_interfaces(range(2))
5113
5114 cls.pg0.admin_up()
5115 cls.pg0.config_ip4()
5116 cls.pg0.resolve_arp()
5117
5118 cls.pg1.admin_up()
5119 cls.pg1.config_ip6()
5120 cls.pg1.resolve_ndp()
5121
5122 cls.vapi.ip_add_del_route(is_ipv6=True, dst_address='\x00'*16,
5123 dst_address_length=0,
5124 next_hop_address=cls.pg1.remote_ip6n,
5125 next_hop_sw_if_index=cls.pg1.sw_if_index)
5126
5127 except Exception:
5128 super(TestNAT44Out2InDPO, cls).tearDownClass()
5129 raise
5130
5131 def configure_xlat(self):
5132 self.dst_ip6_pfx = '1:2:3::'
5133 self.dst_ip6_pfx_n = socket.inet_pton(socket.AF_INET6,
5134 self.dst_ip6_pfx)
5135 self.dst_ip6_pfx_len = 96
5136 self.src_ip6_pfx = '4:5:6::'
5137 self.src_ip6_pfx_n = socket.inet_pton(socket.AF_INET6,
5138 self.src_ip6_pfx)
5139 self.src_ip6_pfx_len = 96
5140 self.vapi.map_add_domain(self.dst_ip6_pfx_n, self.dst_ip6_pfx_len,
5141 self.src_ip6_pfx_n, self.src_ip6_pfx_len,
5142 '\x00\x00\x00\x00', 0, is_translation=1,
5143 is_rfc6052=1)
5144
5145 def test_464xlat_ce(self):
5146 """ Test 464XLAT CE with NAT44 """
5147
Matus Fabian69ce30d2018-08-22 01:27:10 -07005148 nat_config = self.vapi.nat_show_config()
5149 self.assertEqual(1, nat_config.out2in_dpo)
5150
Juraj Slobodacba69362017-12-19 02:09:32 +01005151 self.configure_xlat()
5152
5153 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5154 self.vapi.nat44_add_del_address_range(self.nat_addr_n, self.nat_addr_n)
5155
5156 out_src_ip6 = self.compose_ip6(self.dst_ip4, self.dst_ip6_pfx,
5157 self.dst_ip6_pfx_len)
5158 out_dst_ip6 = self.compose_ip6(self.nat_addr, self.src_ip6_pfx,
5159 self.src_ip6_pfx_len)
5160
5161 try:
5162 pkts = self.create_stream_in(self.pg0, self.pg1, self.dst_ip4)
5163 self.pg0.add_stream(pkts)
5164 self.pg_enable_capture(self.pg_interfaces)
5165 self.pg_start()
5166 capture = self.pg1.get_capture(len(pkts))
5167 self.verify_capture_out_ip6(capture, nat_ip=out_dst_ip6,
5168 dst_ip=out_src_ip6)
5169
5170 pkts = self.create_stream_out_ip6(self.pg1, out_src_ip6,
5171 out_dst_ip6)
5172 self.pg1.add_stream(pkts)
5173 self.pg_enable_capture(self.pg_interfaces)
5174 self.pg_start()
5175 capture = self.pg0.get_capture(len(pkts))
5176 self.verify_capture_in(capture, self.pg0)
5177 finally:
5178 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
5179 is_add=0)
5180 self.vapi.nat44_add_del_address_range(self.nat_addr_n,
5181 self.nat_addr_n, is_add=0)
5182
5183 def test_464xlat_ce_no_nat(self):
5184 """ Test 464XLAT CE without NAT44 """
5185
5186 self.configure_xlat()
5187
5188 out_src_ip6 = self.compose_ip6(self.dst_ip4, self.dst_ip6_pfx,
5189 self.dst_ip6_pfx_len)
5190 out_dst_ip6 = self.compose_ip6(self.pg0.remote_ip4, self.src_ip6_pfx,
5191 self.src_ip6_pfx_len)
5192
5193 pkts = self.create_stream_in(self.pg0, self.pg1, self.dst_ip4)
5194 self.pg0.add_stream(pkts)
5195 self.pg_enable_capture(self.pg_interfaces)
5196 self.pg_start()
5197 capture = self.pg1.get_capture(len(pkts))
5198 self.verify_capture_out_ip6(capture, dst_ip=out_src_ip6,
5199 nat_ip=out_dst_ip6, same_port=True)
5200
5201 pkts = self.create_stream_out_ip6(self.pg1, out_src_ip6, out_dst_ip6)
5202 self.pg1.add_stream(pkts)
5203 self.pg_enable_capture(self.pg_interfaces)
5204 self.pg_start()
5205 capture = self.pg0.get_capture(len(pkts))
5206 self.verify_capture_in(capture, self.pg0)
5207
5208
Martin Gálikd7f75cd2017-03-27 06:02:47 -07005209class TestDeterministicNAT(MethodHolder):
Matus Fabian066f0342017-02-10 03:48:01 -08005210 """ Deterministic NAT Test Cases """
5211
5212 @classmethod
5213 def setUpConstants(cls):
5214 super(TestDeterministicNAT, cls).setUpConstants()
Matus Fabian2ba92e32017-08-21 07:05:03 -07005215 cls.vpp_cmdline.extend(["nat", "{", "deterministic", "}"])
Matus Fabian066f0342017-02-10 03:48:01 -08005216
5217 @classmethod
5218 def setUpClass(cls):
5219 super(TestDeterministicNAT, cls).setUpClass()
Matus Fabian229c1aa2018-05-28 04:09:52 -07005220 cls.vapi.cli("set log class nat level debug")
Matus Fabian066f0342017-02-10 03:48:01 -08005221
5222 try:
Martin Gálik977c1cb2017-03-30 23:21:51 -07005223 cls.tcp_port_in = 6303
Martin Gálik9806eae2017-04-25 01:25:08 -07005224 cls.tcp_external_port = 6303
Martin Gálik977c1cb2017-03-30 23:21:51 -07005225 cls.udp_port_in = 6304
Martin Gálik9806eae2017-04-25 01:25:08 -07005226 cls.udp_external_port = 6304
Martin Gálik977c1cb2017-03-30 23:21:51 -07005227 cls.icmp_id_in = 6305
Matus Fabian2ba92e32017-08-21 07:05:03 -07005228 cls.nat_addr = '10.0.0.3'
Martin Gálik977c1cb2017-03-30 23:21:51 -07005229
Matus Fabian2f2db1c2017-04-18 05:29:59 -07005230 cls.create_pg_interfaces(range(3))
Matus Fabian066f0342017-02-10 03:48:01 -08005231 cls.interfaces = list(cls.pg_interfaces)
5232
5233 for i in cls.interfaces:
5234 i.admin_up()
5235 i.config_ip4()
5236 i.resolve_arp()
5237
Martin Gálik977c1cb2017-03-30 23:21:51 -07005238 cls.pg0.generate_remote_hosts(2)
5239 cls.pg0.configure_ipv4_neighbors()
5240
Matus Fabian066f0342017-02-10 03:48:01 -08005241 except Exception:
5242 super(TestDeterministicNAT, cls).tearDownClass()
5243 raise
5244
Martin Gálik977c1cb2017-03-30 23:21:51 -07005245 def create_stream_in(self, in_if, out_if, ttl=64):
5246 """
5247 Create packet stream for inside network
5248
5249 :param in_if: Inside interface
5250 :param out_if: Outside interface
5251 :param ttl: TTL of generated packets
5252 """
5253 pkts = []
5254 # TCP
5255 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
5256 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
Martin Gálik9806eae2017-04-25 01:25:08 -07005257 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07005258 pkts.append(p)
5259
5260 # UDP
5261 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
5262 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
Martin Gálik9806eae2017-04-25 01:25:08 -07005263 UDP(sport=self.udp_port_in, dport=self.udp_external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07005264 pkts.append(p)
5265
5266 # ICMP
5267 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
5268 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
5269 ICMP(id=self.icmp_id_in, type='echo-request'))
5270 pkts.append(p)
5271
5272 return pkts
5273
5274 def create_stream_out(self, out_if, dst_ip=None, ttl=64):
5275 """
5276 Create packet stream for outside network
5277
5278 :param out_if: Outside interface
Matus Fabian2ba92e32017-08-21 07:05:03 -07005279 :param dst_ip: Destination IP address (Default use global NAT address)
Martin Gálik977c1cb2017-03-30 23:21:51 -07005280 :param ttl: TTL of generated packets
5281 """
5282 if dst_ip is None:
Matus Fabian2ba92e32017-08-21 07:05:03 -07005283 dst_ip = self.nat_addr
Martin Gálik977c1cb2017-03-30 23:21:51 -07005284 pkts = []
5285 # TCP
5286 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
5287 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Martin Gálik9806eae2017-04-25 01:25:08 -07005288 TCP(dport=self.tcp_port_out, sport=self.tcp_external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07005289 pkts.append(p)
5290
5291 # UDP
5292 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
5293 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Martin Gálik9806eae2017-04-25 01:25:08 -07005294 UDP(dport=self.udp_port_out, sport=self.udp_external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07005295 pkts.append(p)
5296
5297 # ICMP
5298 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
5299 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
5300 ICMP(id=self.icmp_external_id, type='echo-reply'))
5301 pkts.append(p)
5302
5303 return pkts
5304
5305 def verify_capture_out(self, capture, nat_ip=None, packet_num=3):
5306 """
5307 Verify captured packets on outside network
5308
5309 :param capture: Captured packets
Matus Fabian2ba92e32017-08-21 07:05:03 -07005310 :param nat_ip: Translated IP address (Default use global NAT address)
Martin Gálik977c1cb2017-03-30 23:21:51 -07005311 :param same_port: Sorce port number is not translated (Default False)
5312 :param packet_num: Expected number of packets (Default 3)
5313 """
5314 if nat_ip is None:
Matus Fabian2ba92e32017-08-21 07:05:03 -07005315 nat_ip = self.nat_addr
Martin Gálik977c1cb2017-03-30 23:21:51 -07005316 self.assertEqual(packet_num, len(capture))
5317 for packet in capture:
5318 try:
5319 self.assertEqual(packet[IP].src, nat_ip)
5320 if packet.haslayer(TCP):
Martin Gálik9806eae2017-04-25 01:25:08 -07005321 self.tcp_port_out = packet[TCP].sport
Martin Gálik977c1cb2017-03-30 23:21:51 -07005322 elif packet.haslayer(UDP):
Martin Gálik9806eae2017-04-25 01:25:08 -07005323 self.udp_port_out = packet[UDP].sport
Martin Gálik977c1cb2017-03-30 23:21:51 -07005324 else:
5325 self.icmp_external_id = packet[ICMP].id
5326 except:
5327 self.logger.error(ppp("Unexpected or invalid packet "
5328 "(outside network):", packet))
5329 raise
5330
Matus Fabian066f0342017-02-10 03:48:01 -08005331 def test_deterministic_mode(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07005332 """ NAT plugin run deterministic mode """
Matus Fabian066f0342017-02-10 03:48:01 -08005333 in_addr = '172.16.255.0'
5334 out_addr = '172.17.255.50'
5335 in_addr_t = '172.16.255.20'
5336 in_addr_n = socket.inet_aton(in_addr)
5337 out_addr_n = socket.inet_aton(out_addr)
5338 in_addr_t_n = socket.inet_aton(in_addr_t)
5339 in_plen = 24
5340 out_plen = 32
5341
Matus Fabian2ba92e32017-08-21 07:05:03 -07005342 nat_config = self.vapi.nat_show_config()
5343 self.assertEqual(1, nat_config.deterministic)
Matus Fabian066f0342017-02-10 03:48:01 -08005344
Matus Fabian2ba92e32017-08-21 07:05:03 -07005345 self.vapi.nat_det_add_del_map(in_addr_n, in_plen, out_addr_n, out_plen)
Matus Fabian066f0342017-02-10 03:48:01 -08005346
Matus Fabian2ba92e32017-08-21 07:05:03 -07005347 rep1 = self.vapi.nat_det_forward(in_addr_t_n)
Matus Fabian066f0342017-02-10 03:48:01 -08005348 self.assertEqual(rep1.out_addr[:4], out_addr_n)
Matus Fabian2ba92e32017-08-21 07:05:03 -07005349 rep2 = self.vapi.nat_det_reverse(out_addr_n, rep1.out_port_hi)
Matus Fabian066f0342017-02-10 03:48:01 -08005350 self.assertEqual(rep2.in_addr[:4], in_addr_t_n)
5351
Matus Fabian2ba92e32017-08-21 07:05:03 -07005352 deterministic_mappings = self.vapi.nat_det_map_dump()
Martin17a75cb2017-03-08 05:53:20 -08005353 self.assertEqual(len(deterministic_mappings), 1)
5354 dsm = deterministic_mappings[0]
5355 self.assertEqual(in_addr_n, dsm.in_addr[:4])
5356 self.assertEqual(in_plen, dsm.in_plen)
5357 self.assertEqual(out_addr_n, dsm.out_addr[:4])
5358 self.assertEqual(out_plen, dsm.out_plen)
5359
Matus Fabian2ba92e32017-08-21 07:05:03 -07005360 self.clear_nat_det()
5361 deterministic_mappings = self.vapi.nat_det_map_dump()
Martinb616e9f2017-03-14 02:25:45 -07005362 self.assertEqual(len(deterministic_mappings), 0)
5363
Matus Fabian6a0946f2017-04-12 03:36:13 -07005364 def test_set_timeouts(self):
5365 """ Set deterministic NAT timeouts """
Matus Fabian878c6462018-08-23 00:33:35 -07005366 timeouts_before = self.vapi.nat_get_timeouts()
Matus Fabian6a0946f2017-04-12 03:36:13 -07005367
Matus Fabian878c6462018-08-23 00:33:35 -07005368 self.vapi.nat_set_timeouts(timeouts_before.udp + 10,
5369 timeouts_before.tcp_established + 10,
5370 timeouts_before.tcp_transitory + 10,
5371 timeouts_before.icmp + 10)
Matus Fabian6a0946f2017-04-12 03:36:13 -07005372
Matus Fabian878c6462018-08-23 00:33:35 -07005373 timeouts_after = self.vapi.nat_get_timeouts()
Matus Fabian6a0946f2017-04-12 03:36:13 -07005374
5375 self.assertNotEqual(timeouts_before.udp, timeouts_after.udp)
5376 self.assertNotEqual(timeouts_before.icmp, timeouts_after.icmp)
5377 self.assertNotEqual(timeouts_before.tcp_established,
5378 timeouts_after.tcp_established)
5379 self.assertNotEqual(timeouts_before.tcp_transitory,
5380 timeouts_after.tcp_transitory)
5381
Martin Gálik977c1cb2017-03-30 23:21:51 -07005382 def test_det_in(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07005383 """ Deterministic NAT translation test (TCP, UDP, ICMP) """
Martin Gálik977c1cb2017-03-30 23:21:51 -07005384
5385 nat_ip = "10.0.0.10"
Martin Gálik977c1cb2017-03-30 23:21:51 -07005386
Matus Fabian2ba92e32017-08-21 07:05:03 -07005387 self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
5388 32,
5389 socket.inet_aton(nat_ip),
5390 32)
5391 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5392 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
5393 is_inside=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07005394
5395 # in2out
5396 pkts = self.create_stream_in(self.pg0, self.pg1)
5397 self.pg0.add_stream(pkts)
5398 self.pg_enable_capture(self.pg_interfaces)
5399 self.pg_start()
5400 capture = self.pg1.get_capture(len(pkts))
5401 self.verify_capture_out(capture, nat_ip)
5402
5403 # out2in
5404 pkts = self.create_stream_out(self.pg1, nat_ip)
5405 self.pg1.add_stream(pkts)
5406 self.pg_enable_capture(self.pg_interfaces)
5407 self.pg_start()
5408 capture = self.pg0.get_capture(len(pkts))
5409 self.verify_capture_in(capture, self.pg0)
5410
Martin Gálik9806eae2017-04-25 01:25:08 -07005411 # session dump test
Matus Fabian2ba92e32017-08-21 07:05:03 -07005412 sessions = self.vapi.nat_det_session_dump(self.pg0.remote_ip4n)
Martin Gálik9806eae2017-04-25 01:25:08 -07005413 self.assertEqual(len(sessions), 3)
5414
5415 # TCP session
5416 s = sessions[0]
5417 self.assertEqual(s.ext_addr[:4], self.pg1.remote_ip4n)
5418 self.assertEqual(s.in_port, self.tcp_port_in)
5419 self.assertEqual(s.out_port, self.tcp_port_out)
5420 self.assertEqual(s.ext_port, self.tcp_external_port)
5421
5422 # UDP session
5423 s = sessions[1]
5424 self.assertEqual(s.ext_addr[:4], self.pg1.remote_ip4n)
5425 self.assertEqual(s.in_port, self.udp_port_in)
5426 self.assertEqual(s.out_port, self.udp_port_out)
5427 self.assertEqual(s.ext_port, self.udp_external_port)
5428
5429 # ICMP session
5430 s = sessions[2]
5431 self.assertEqual(s.ext_addr[:4], self.pg1.remote_ip4n)
5432 self.assertEqual(s.in_port, self.icmp_id_in)
5433 self.assertEqual(s.out_port, self.icmp_external_id)
5434
Martin Gálik977c1cb2017-03-30 23:21:51 -07005435 def test_multiple_users(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07005436 """ Deterministic NAT multiple users """
Martin Gálik977c1cb2017-03-30 23:21:51 -07005437
5438 nat_ip = "10.0.0.10"
5439 port_in = 80
Martin Gálik9806eae2017-04-25 01:25:08 -07005440 external_port = 6303
Martin Gálik977c1cb2017-03-30 23:21:51 -07005441
5442 host0 = self.pg0.remote_hosts[0]
5443 host1 = self.pg0.remote_hosts[1]
5444
Matus Fabian2ba92e32017-08-21 07:05:03 -07005445 self.vapi.nat_det_add_del_map(host0.ip4n,
5446 24,
5447 socket.inet_aton(nat_ip),
5448 32)
5449 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5450 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
5451 is_inside=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07005452
5453 # host0 to out
5454 p = (Ether(src=host0.mac, dst=self.pg0.local_mac) /
5455 IP(src=host0.ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07005456 TCP(sport=port_in, dport=external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07005457 self.pg0.add_stream(p)
5458 self.pg_enable_capture(self.pg_interfaces)
5459 self.pg_start()
5460 capture = self.pg1.get_capture(1)
5461 p = capture[0]
5462 try:
5463 ip = p[IP]
5464 tcp = p[TCP]
5465 self.assertEqual(ip.src, nat_ip)
5466 self.assertEqual(ip.dst, self.pg1.remote_ip4)
Martin Gálik9806eae2017-04-25 01:25:08 -07005467 self.assertEqual(tcp.dport, external_port)
5468 port_out0 = tcp.sport
Martin Gálik977c1cb2017-03-30 23:21:51 -07005469 except:
5470 self.logger.error(ppp("Unexpected or invalid packet:", p))
5471 raise
5472
5473 # host1 to out
5474 p = (Ether(src=host1.mac, dst=self.pg0.local_mac) /
5475 IP(src=host1.ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07005476 TCP(sport=port_in, dport=external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07005477 self.pg0.add_stream(p)
5478 self.pg_enable_capture(self.pg_interfaces)
5479 self.pg_start()
5480 capture = self.pg1.get_capture(1)
5481 p = capture[0]
5482 try:
5483 ip = p[IP]
5484 tcp = p[TCP]
5485 self.assertEqual(ip.src, nat_ip)
5486 self.assertEqual(ip.dst, self.pg1.remote_ip4)
Martin Gálik9806eae2017-04-25 01:25:08 -07005487 self.assertEqual(tcp.dport, external_port)
5488 port_out1 = tcp.sport
Martin Gálik977c1cb2017-03-30 23:21:51 -07005489 except:
5490 self.logger.error(ppp("Unexpected or invalid packet:", p))
5491 raise
5492
Matus Fabian2ba92e32017-08-21 07:05:03 -07005493 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07005494 self.assertEqual(1, len(dms))
5495 self.assertEqual(2, dms[0].ses_num)
5496
5497 # out to host0
5498 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5499 IP(src=self.pg1.remote_ip4, dst=nat_ip) /
Martin Gálik9806eae2017-04-25 01:25:08 -07005500 TCP(sport=external_port, dport=port_out0))
Martin Gálik977c1cb2017-03-30 23:21:51 -07005501 self.pg1.add_stream(p)
5502 self.pg_enable_capture(self.pg_interfaces)
5503 self.pg_start()
5504 capture = self.pg0.get_capture(1)
5505 p = capture[0]
5506 try:
5507 ip = p[IP]
5508 tcp = p[TCP]
5509 self.assertEqual(ip.src, self.pg1.remote_ip4)
5510 self.assertEqual(ip.dst, host0.ip4)
5511 self.assertEqual(tcp.dport, port_in)
Martin Gálik9806eae2017-04-25 01:25:08 -07005512 self.assertEqual(tcp.sport, external_port)
Martin Gálik977c1cb2017-03-30 23:21:51 -07005513 except:
5514 self.logger.error(ppp("Unexpected or invalid packet:", p))
5515 raise
5516
5517 # out to host1
5518 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5519 IP(src=self.pg1.remote_ip4, dst=nat_ip) /
Martin Gálik9806eae2017-04-25 01:25:08 -07005520 TCP(sport=external_port, dport=port_out1))
Martin Gálik977c1cb2017-03-30 23:21:51 -07005521 self.pg1.add_stream(p)
5522 self.pg_enable_capture(self.pg_interfaces)
5523 self.pg_start()
5524 capture = self.pg0.get_capture(1)
5525 p = capture[0]
5526 try:
5527 ip = p[IP]
5528 tcp = p[TCP]
5529 self.assertEqual(ip.src, self.pg1.remote_ip4)
5530 self.assertEqual(ip.dst, host1.ip4)
5531 self.assertEqual(tcp.dport, port_in)
Martin Gálik9806eae2017-04-25 01:25:08 -07005532 self.assertEqual(tcp.sport, external_port)
Martin Gálik977c1cb2017-03-30 23:21:51 -07005533 except:
5534 self.logger.error(ppp("Unexpected or invalid packet", p))
5535 raise
5536
Martin Gálik6bc8c642017-04-19 01:12:27 -07005537 # session close api test
Matus Fabian2ba92e32017-08-21 07:05:03 -07005538 self.vapi.nat_det_close_session_out(socket.inet_aton(nat_ip),
5539 port_out1,
Martin Gálik6bc8c642017-04-19 01:12:27 -07005540 self.pg1.remote_ip4n,
Martin Gálik9806eae2017-04-25 01:25:08 -07005541 external_port)
Matus Fabian2ba92e32017-08-21 07:05:03 -07005542 dms = self.vapi.nat_det_map_dump()
5543 self.assertEqual(dms[0].ses_num, 1)
5544
5545 self.vapi.nat_det_close_session_in(host0.ip4n,
5546 port_in,
5547 self.pg1.remote_ip4n,
5548 external_port)
5549 dms = self.vapi.nat_det_map_dump()
Martin Gálik6bc8c642017-04-19 01:12:27 -07005550 self.assertEqual(dms[0].ses_num, 0)
5551
Martin Gálik977c1cb2017-03-30 23:21:51 -07005552 def test_tcp_session_close_detection_in(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07005553 """ Deterministic NAT TCP session close from inside network """
5554 self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
5555 32,
5556 socket.inet_aton(self.nat_addr),
5557 32)
5558 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5559 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
5560 is_inside=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07005561
5562 self.initiate_tcp_session(self.pg0, self.pg1)
5563
5564 # close the session from inside
5565 try:
5566 # FIN packet in -> out
5567 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5568 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07005569 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
Martin Gálik977c1cb2017-03-30 23:21:51 -07005570 flags="F"))
5571 self.pg0.add_stream(p)
5572 self.pg_enable_capture(self.pg_interfaces)
5573 self.pg_start()
5574 self.pg1.get_capture(1)
5575
5576 pkts = []
5577
5578 # ACK packet out -> in
5579 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07005580 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Martin Gálik9806eae2017-04-25 01:25:08 -07005581 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
Martin Gálik977c1cb2017-03-30 23:21:51 -07005582 flags="A"))
5583 pkts.append(p)
5584
5585 # FIN packet out -> in
5586 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07005587 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Martin Gálik9806eae2017-04-25 01:25:08 -07005588 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
Martin Gálik977c1cb2017-03-30 23:21:51 -07005589 flags="F"))
5590 pkts.append(p)
5591
5592 self.pg1.add_stream(pkts)
5593 self.pg_enable_capture(self.pg_interfaces)
5594 self.pg_start()
5595 self.pg0.get_capture(2)
5596
5597 # ACK packet in -> out
5598 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5599 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07005600 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
Martin Gálik977c1cb2017-03-30 23:21:51 -07005601 flags="A"))
5602 self.pg0.add_stream(p)
5603 self.pg_enable_capture(self.pg_interfaces)
5604 self.pg_start()
5605 self.pg1.get_capture(1)
5606
Matus Fabian2ba92e32017-08-21 07:05:03 -07005607 # Check if deterministic NAT44 closed the session
5608 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07005609 self.assertEqual(0, dms[0].ses_num)
5610 except:
5611 self.logger.error("TCP session termination failed")
5612 raise
5613
5614 def test_tcp_session_close_detection_out(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07005615 """ Deterministic NAT TCP session close from outside network """
5616 self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
5617 32,
5618 socket.inet_aton(self.nat_addr),
5619 32)
5620 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5621 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
5622 is_inside=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07005623
5624 self.initiate_tcp_session(self.pg0, self.pg1)
5625
5626 # close the session from outside
5627 try:
5628 # FIN packet out -> in
5629 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07005630 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Martin Gálik9806eae2017-04-25 01:25:08 -07005631 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
Martin Gálik977c1cb2017-03-30 23:21:51 -07005632 flags="F"))
5633 self.pg1.add_stream(p)
5634 self.pg_enable_capture(self.pg_interfaces)
5635 self.pg_start()
5636 self.pg0.get_capture(1)
5637
5638 pkts = []
5639
5640 # ACK packet in -> out
5641 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5642 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07005643 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
Martin Gálik977c1cb2017-03-30 23:21:51 -07005644 flags="A"))
5645 pkts.append(p)
5646
5647 # ACK packet in -> out
5648 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5649 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07005650 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
Martin Gálik977c1cb2017-03-30 23:21:51 -07005651 flags="F"))
5652 pkts.append(p)
5653
5654 self.pg0.add_stream(pkts)
5655 self.pg_enable_capture(self.pg_interfaces)
5656 self.pg_start()
5657 self.pg1.get_capture(2)
5658
5659 # ACK packet out -> in
5660 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07005661 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Martin Gálik9806eae2017-04-25 01:25:08 -07005662 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
Martin Gálik977c1cb2017-03-30 23:21:51 -07005663 flags="A"))
5664 self.pg1.add_stream(p)
5665 self.pg_enable_capture(self.pg_interfaces)
5666 self.pg_start()
5667 self.pg0.get_capture(1)
5668
Matus Fabian2ba92e32017-08-21 07:05:03 -07005669 # Check if deterministic NAT44 closed the session
5670 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07005671 self.assertEqual(0, dms[0].ses_num)
5672 except:
5673 self.logger.error("TCP session termination failed")
5674 raise
5675
5676 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
5677 def test_session_timeout(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07005678 """ Deterministic NAT session timeouts """
5679 self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
5680 32,
5681 socket.inet_aton(self.nat_addr),
5682 32)
5683 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5684 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
5685 is_inside=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07005686
5687 self.initiate_tcp_session(self.pg0, self.pg1)
Matus Fabian878c6462018-08-23 00:33:35 -07005688 self.vapi.nat_set_timeouts(5, 5, 5, 5)
Martin Gálik977c1cb2017-03-30 23:21:51 -07005689 pkts = self.create_stream_in(self.pg0, self.pg1)
5690 self.pg0.add_stream(pkts)
5691 self.pg_enable_capture(self.pg_interfaces)
5692 self.pg_start()
5693 capture = self.pg1.get_capture(len(pkts))
5694 sleep(15)
5695
Matus Fabian2ba92e32017-08-21 07:05:03 -07005696 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07005697 self.assertEqual(0, dms[0].ses_num)
5698
Matus Fabian7c0aecc2017-07-03 01:21:38 -07005699 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
Martin Gálik977c1cb2017-03-30 23:21:51 -07005700 def test_session_limit_per_user(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07005701 """ Deterministic NAT maximum sessions per user limit """
5702 self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
5703 32,
5704 socket.inet_aton(self.nat_addr),
5705 32)
5706 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5707 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
5708 is_inside=0)
Matus Fabian2f2db1c2017-04-18 05:29:59 -07005709 self.vapi.set_ipfix_exporter(collector_address=self.pg2.remote_ip4n,
5710 src_address=self.pg2.local_ip4n,
5711 path_mtu=512,
5712 template_interval=10)
Matus Fabian2ba92e32017-08-21 07:05:03 -07005713 self.vapi.nat_ipfix()
Martin Gálik977c1cb2017-03-30 23:21:51 -07005714
5715 pkts = []
5716 for port in range(1025, 2025):
5717 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5718 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5719 UDP(sport=port, dport=port))
5720 pkts.append(p)
5721
5722 self.pg0.add_stream(pkts)
5723 self.pg_enable_capture(self.pg_interfaces)
5724 self.pg_start()
5725 capture = self.pg1.get_capture(len(pkts))
5726
5727 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5728 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálikf7e655d2017-04-27 02:13:26 -07005729 UDP(sport=3001, dport=3002))
Martin Gálik977c1cb2017-03-30 23:21:51 -07005730 self.pg0.add_stream(p)
5731 self.pg_enable_capture(self.pg_interfaces)
5732 self.pg_start()
5733 capture = self.pg1.assert_nothing_captured()
5734
Martin Gálikf7e655d2017-04-27 02:13:26 -07005735 # verify ICMP error packet
5736 capture = self.pg0.get_capture(1)
5737 p = capture[0]
5738 self.assertTrue(p.haslayer(ICMP))
5739 icmp = p[ICMP]
5740 self.assertEqual(icmp.type, 3)
5741 self.assertEqual(icmp.code, 1)
5742 self.assertTrue(icmp.haslayer(IPerror))
5743 inner_ip = icmp[IPerror]
5744 self.assertEqual(inner_ip[UDPerror].sport, 3001)
5745 self.assertEqual(inner_ip[UDPerror].dport, 3002)
5746
Matus Fabian2ba92e32017-08-21 07:05:03 -07005747 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07005748
5749 self.assertEqual(1000, dms[0].ses_num)
5750
Matus Fabian2f2db1c2017-04-18 05:29:59 -07005751 # verify IPFIX logging
5752 self.vapi.cli("ipfix flush") # FIXME this should be an API call
Matus Fabian7c0aecc2017-07-03 01:21:38 -07005753 sleep(1)
Matus Fabian2f2db1c2017-04-18 05:29:59 -07005754 capture = self.pg2.get_capture(2)
5755 ipfix = IPFIXDecoder()
5756 # first load template
5757 for p in capture:
5758 self.assertTrue(p.haslayer(IPFIX))
5759 if p.haslayer(Template):
5760 ipfix.add_template(p.getlayer(Template))
5761 # verify events in data set
5762 for p in capture:
5763 if p.haslayer(Data):
5764 data = ipfix.decode_data_set(p.getlayer(Set))
Matus Fabian878c6462018-08-23 00:33:35 -07005765 self.verify_ipfix_max_entries_per_user(data,
5766 1000,
5767 self.pg0.remote_ip4n)
Matus Fabian2f2db1c2017-04-18 05:29:59 -07005768
Matus Fabian2ba92e32017-08-21 07:05:03 -07005769 def clear_nat_det(self):
Martin17a75cb2017-03-08 05:53:20 -08005770 """
Matus Fabian2ba92e32017-08-21 07:05:03 -07005771 Clear deterministic NAT configuration.
Martin17a75cb2017-03-08 05:53:20 -08005772 """
Matus Fabian2ba92e32017-08-21 07:05:03 -07005773 self.vapi.nat_ipfix(enable=0)
Matus Fabian878c6462018-08-23 00:33:35 -07005774 self.vapi.nat_set_timeouts()
Matus Fabian2ba92e32017-08-21 07:05:03 -07005775 deterministic_mappings = self.vapi.nat_det_map_dump()
Martin17a75cb2017-03-08 05:53:20 -08005776 for dsm in deterministic_mappings:
Matus Fabian2ba92e32017-08-21 07:05:03 -07005777 self.vapi.nat_det_add_del_map(dsm.in_addr,
5778 dsm.in_plen,
5779 dsm.out_addr,
5780 dsm.out_plen,
5781 is_add=0)
Martin17a75cb2017-03-08 05:53:20 -08005782
Matus Fabian2ba92e32017-08-21 07:05:03 -07005783 interfaces = self.vapi.nat44_interface_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07005784 for intf in interfaces:
Matus Fabian2ba92e32017-08-21 07:05:03 -07005785 self.vapi.nat44_interface_add_del_feature(intf.sw_if_index,
5786 intf.is_inside,
5787 is_add=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07005788
Matus Fabian066f0342017-02-10 03:48:01 -08005789 def tearDown(self):
5790 super(TestDeterministicNAT, self).tearDown()
5791 if not self.vpp_dead:
Matus Fabian82119542018-01-25 01:13:22 -08005792 self.logger.info(self.vapi.cli("show nat44 interfaces"))
Matus Fabian878c6462018-08-23 00:33:35 -07005793 self.logger.info(self.vapi.cli("show nat timeouts"))
Matus Fabian82119542018-01-25 01:13:22 -08005794 self.logger.info(
5795 self.vapi.cli("show nat44 deterministic mappings"))
5796 self.logger.info(
Matus Fabian82119542018-01-25 01:13:22 -08005797 self.vapi.cli("show nat44 deterministic sessions"))
Matus Fabian2ba92e32017-08-21 07:05:03 -07005798 self.clear_nat_det()
Matus Fabian066f0342017-02-10 03:48:01 -08005799
Matus Fabian06596c52017-06-06 04:53:28 -07005800
5801class TestNAT64(MethodHolder):
5802 """ NAT64 Test Cases """
5803
5804 @classmethod
Matus Fabiana431ad12018-01-04 04:03:14 -08005805 def setUpConstants(cls):
5806 super(TestNAT64, cls).setUpConstants()
5807 cls.vpp_cmdline.extend(["nat", "{", "nat64 bib hash buckets 128",
5808 "nat64 st hash buckets 256", "}"])
5809
5810 @classmethod
Matus Fabian06596c52017-06-06 04:53:28 -07005811 def setUpClass(cls):
5812 super(TestNAT64, cls).setUpClass()
5813
5814 try:
5815 cls.tcp_port_in = 6303
5816 cls.tcp_port_out = 6303
5817 cls.udp_port_in = 6304
5818 cls.udp_port_out = 6304
5819 cls.icmp_id_in = 6305
5820 cls.icmp_id_out = 6305
5821 cls.nat_addr = '10.0.0.3'
5822 cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
Matus Fabian029f3d22017-06-15 02:28:50 -07005823 cls.vrf1_id = 10
5824 cls.vrf1_nat_addr = '10.0.10.3'
5825 cls.vrf1_nat_addr_n = socket.inet_pton(socket.AF_INET,
5826 cls.vrf1_nat_addr)
Matus Fabiana431ad12018-01-04 04:03:14 -08005827 cls.ipfix_src_port = 4739
5828 cls.ipfix_domain_id = 1
Matus Fabian06596c52017-06-06 04:53:28 -07005829
Juraj Slobodac746a152018-07-09 02:36:37 +02005830 cls.create_pg_interfaces(range(6))
Matus Fabian06596c52017-06-06 04:53:28 -07005831 cls.ip6_interfaces = list(cls.pg_interfaces[0:1])
Matus Fabian029f3d22017-06-15 02:28:50 -07005832 cls.ip6_interfaces.append(cls.pg_interfaces[2])
Matus Fabian06596c52017-06-06 04:53:28 -07005833 cls.ip4_interfaces = list(cls.pg_interfaces[1:2])
5834
Neale Ranns15002542017-09-10 04:39:11 -07005835 cls.vapi.ip_table_add_del(cls.vrf1_id, is_add=1, is_ipv6=1)
5836
Matus Fabian029f3d22017-06-15 02:28:50 -07005837 cls.pg_interfaces[2].set_table_ip6(cls.vrf1_id)
5838
5839 cls.pg0.generate_remote_hosts(2)
5840
Matus Fabian06596c52017-06-06 04:53:28 -07005841 for i in cls.ip6_interfaces:
5842 i.admin_up()
5843 i.config_ip6()
Matus Fabian029f3d22017-06-15 02:28:50 -07005844 i.configure_ipv6_neighbors()
Matus Fabian06596c52017-06-06 04:53:28 -07005845
5846 for i in cls.ip4_interfaces:
5847 i.admin_up()
5848 i.config_ip4()
5849 i.resolve_arp()
5850
Matus Fabian36ea2d62017-10-24 04:13:49 -07005851 cls.pg3.admin_up()
5852 cls.pg3.config_ip4()
5853 cls.pg3.resolve_arp()
5854 cls.pg3.config_ip6()
5855 cls.pg3.configure_ipv6_neighbors()
5856
Juraj Slobodac746a152018-07-09 02:36:37 +02005857 cls.pg5.admin_up()
5858 cls.pg5.config_ip6()
5859
Matus Fabian06596c52017-06-06 04:53:28 -07005860 except Exception:
5861 super(TestNAT64, cls).tearDownClass()
5862 raise
5863
Juraj Slobodac746a152018-07-09 02:36:37 +02005864 def test_nat64_inside_interface_handles_neighbor_advertisement(self):
5865 """ NAT64 inside interface handles Neighbor Advertisement """
5866
5867 self.vapi.nat64_add_del_interface(self.pg5.sw_if_index)
5868
5869 # Try to send ping
5870 ping = (Ether(dst=self.pg5.local_mac, src=self.pg5.remote_mac) /
5871 IPv6(src=self.pg5.remote_ip6, dst=self.pg5.local_ip6) /
5872 ICMPv6EchoRequest())
5873 pkts = [ping]
5874 self.pg5.add_stream(pkts)
5875 self.pg_enable_capture(self.pg_interfaces)
5876 self.pg_start()
5877
5878 # Wait for Neighbor Solicitation
5879 capture = self.pg5.get_capture(len(pkts))
5880 self.assertEqual(1, len(capture))
5881 packet = capture[0]
5882 try:
5883 self.assertEqual(packet[IPv6].src, self.pg5.local_ip6)
5884 self.assertTrue(packet.haslayer(ICMPv6ND_NS))
5885 tgt = packet[ICMPv6ND_NS].tgt
5886 except:
5887 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5888 raise
5889
5890 # Send Neighbor Advertisement
5891 p = (Ether(dst=self.pg5.local_mac, src=self.pg5.remote_mac) /
5892 IPv6(src=self.pg5.remote_ip6, dst=self.pg5.local_ip6) /
5893 ICMPv6ND_NA(tgt=tgt) /
5894 ICMPv6NDOptDstLLAddr(lladdr=self.pg5.remote_mac))
5895 pkts = [p]
5896 self.pg5.add_stream(pkts)
5897 self.pg_enable_capture(self.pg_interfaces)
5898 self.pg_start()
5899
5900 # Try to send ping again
5901 pkts = [ping]
5902 self.pg5.add_stream(pkts)
5903 self.pg_enable_capture(self.pg_interfaces)
5904 self.pg_start()
5905
5906 # Wait for ping reply
5907 capture = self.pg5.get_capture(len(pkts))
5908 self.assertEqual(1, len(capture))
5909 packet = capture[0]
5910 try:
5911 self.assertEqual(packet[IPv6].src, self.pg5.local_ip6)
5912 self.assertEqual(packet[IPv6].dst, self.pg5.remote_ip6)
5913 self.assertTrue(packet.haslayer(ICMPv6EchoReply))
5914 except:
5915 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5916 raise
5917
Matus Fabian06596c52017-06-06 04:53:28 -07005918 def test_pool(self):
5919 """ Add/delete address to NAT64 pool """
5920 nat_addr = socket.inet_pton(socket.AF_INET, '1.2.3.4')
5921
5922 self.vapi.nat64_add_del_pool_addr_range(nat_addr, nat_addr)
5923
5924 addresses = self.vapi.nat64_pool_addr_dump()
5925 self.assertEqual(len(addresses), 1)
5926 self.assertEqual(addresses[0].address, nat_addr)
5927
5928 self.vapi.nat64_add_del_pool_addr_range(nat_addr, nat_addr, is_add=0)
5929
5930 addresses = self.vapi.nat64_pool_addr_dump()
5931 self.assertEqual(len(addresses), 0)
5932
5933 def test_interface(self):
5934 """ Enable/disable NAT64 feature on the interface """
5935 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
5936 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
5937
5938 interfaces = self.vapi.nat64_interface_dump()
5939 self.assertEqual(len(interfaces), 2)
5940 pg0_found = False
5941 pg1_found = False
5942 for intf in interfaces:
5943 if intf.sw_if_index == self.pg0.sw_if_index:
5944 self.assertEqual(intf.is_inside, 1)
5945 pg0_found = True
5946 elif intf.sw_if_index == self.pg1.sw_if_index:
5947 self.assertEqual(intf.is_inside, 0)
5948 pg1_found = True
5949 self.assertTrue(pg0_found)
5950 self.assertTrue(pg1_found)
5951
5952 features = self.vapi.cli("show interface features pg0")
5953 self.assertNotEqual(features.find('nat64-in2out'), -1)
5954 features = self.vapi.cli("show interface features pg1")
5955 self.assertNotEqual(features.find('nat64-out2in'), -1)
5956
5957 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index, is_add=0)
5958 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_add=0)
5959
5960 interfaces = self.vapi.nat64_interface_dump()
5961 self.assertEqual(len(interfaces), 0)
5962
5963 def test_static_bib(self):
5964 """ Add/delete static BIB entry """
5965 in_addr = socket.inet_pton(socket.AF_INET6,
5966 '2001:db8:85a3::8a2e:370:7334')
5967 out_addr = socket.inet_pton(socket.AF_INET, '10.1.1.3')
5968 in_port = 1234
5969 out_port = 5678
5970 proto = IP_PROTOS.tcp
5971
5972 self.vapi.nat64_add_del_static_bib(in_addr,
5973 out_addr,
5974 in_port,
5975 out_port,
5976 proto)
5977 bib = self.vapi.nat64_bib_dump(IP_PROTOS.tcp)
5978 static_bib_num = 0
5979 for bibe in bib:
5980 if bibe.is_static:
5981 static_bib_num += 1
5982 self.assertEqual(bibe.i_addr, in_addr)
5983 self.assertEqual(bibe.o_addr, out_addr)
5984 self.assertEqual(bibe.i_port, in_port)
5985 self.assertEqual(bibe.o_port, out_port)
5986 self.assertEqual(static_bib_num, 1)
5987
5988 self.vapi.nat64_add_del_static_bib(in_addr,
5989 out_addr,
5990 in_port,
5991 out_port,
5992 proto,
5993 is_add=0)
5994 bib = self.vapi.nat64_bib_dump(IP_PROTOS.tcp)
5995 static_bib_num = 0
5996 for bibe in bib:
5997 if bibe.is_static:
5998 static_bib_num += 1
5999 self.assertEqual(static_bib_num, 0)
6000
6001 def test_set_timeouts(self):
6002 """ Set NAT64 timeouts """
6003 # verify default values
Matus Fabian878c6462018-08-23 00:33:35 -07006004 timeouts = self.vapi.nat_get_timeouts()
Matus Fabian06596c52017-06-06 04:53:28 -07006005 self.assertEqual(timeouts.udp, 300)
6006 self.assertEqual(timeouts.icmp, 60)
Matus Fabian878c6462018-08-23 00:33:35 -07006007 self.assertEqual(timeouts.tcp_transitory, 240)
6008 self.assertEqual(timeouts.tcp_established, 7440)
Matus Fabian06596c52017-06-06 04:53:28 -07006009
6010 # set and verify custom values
Matus Fabian878c6462018-08-23 00:33:35 -07006011 self.vapi.nat_set_timeouts(udp=200, icmp=30, tcp_transitory=250,
6012 tcp_established=7450)
6013 timeouts = self.vapi.nat_get_timeouts()
Matus Fabian06596c52017-06-06 04:53:28 -07006014 self.assertEqual(timeouts.udp, 200)
6015 self.assertEqual(timeouts.icmp, 30)
Matus Fabian878c6462018-08-23 00:33:35 -07006016 self.assertEqual(timeouts.tcp_transitory, 250)
6017 self.assertEqual(timeouts.tcp_established, 7450)
Matus Fabian06596c52017-06-06 04:53:28 -07006018
6019 def test_dynamic(self):
6020 """ NAT64 dynamic translation test """
6021 self.tcp_port_in = 6303
6022 self.udp_port_in = 6304
6023 self.icmp_id_in = 6305
6024
6025 ses_num_start = self.nat64_get_ses_num()
6026
6027 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6028 self.nat_addr_n)
6029 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6030 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6031
6032 # in2out
6033 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
6034 self.pg0.add_stream(pkts)
6035 self.pg_enable_capture(self.pg_interfaces)
6036 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07006037 capture = self.pg1.get_capture(len(pkts))
6038 self.verify_capture_out(capture, nat_ip=self.nat_addr,
Matus Fabian06596c52017-06-06 04:53:28 -07006039 dst_ip=self.pg1.remote_ip4)
6040
6041 # out2in
6042 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
6043 self.pg1.add_stream(pkts)
6044 self.pg_enable_capture(self.pg_interfaces)
6045 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07006046 capture = self.pg0.get_capture(len(pkts))
Matus Fabian06596c52017-06-06 04:53:28 -07006047 ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
6048 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
6049
6050 # in2out
6051 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
6052 self.pg0.add_stream(pkts)
6053 self.pg_enable_capture(self.pg_interfaces)
6054 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07006055 capture = self.pg1.get_capture(len(pkts))
6056 self.verify_capture_out(capture, nat_ip=self.nat_addr,
Matus Fabian06596c52017-06-06 04:53:28 -07006057 dst_ip=self.pg1.remote_ip4)
6058
6059 # out2in
6060 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
6061 self.pg1.add_stream(pkts)
6062 self.pg_enable_capture(self.pg_interfaces)
6063 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07006064 capture = self.pg0.get_capture(len(pkts))
Matus Fabian06596c52017-06-06 04:53:28 -07006065 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
6066
6067 ses_num_end = self.nat64_get_ses_num()
6068
6069 self.assertEqual(ses_num_end - ses_num_start, 3)
6070
Matus Fabian029f3d22017-06-15 02:28:50 -07006071 # tenant with specific VRF
6072 self.vapi.nat64_add_del_pool_addr_range(self.vrf1_nat_addr_n,
6073 self.vrf1_nat_addr_n,
6074 vrf_id=self.vrf1_id)
6075 self.vapi.nat64_add_del_interface(self.pg2.sw_if_index)
6076
6077 pkts = self.create_stream_in_ip6(self.pg2, self.pg1)
6078 self.pg2.add_stream(pkts)
6079 self.pg_enable_capture(self.pg_interfaces)
6080 self.pg_start()
6081 capture = self.pg1.get_capture(len(pkts))
6082 self.verify_capture_out(capture, nat_ip=self.vrf1_nat_addr,
6083 dst_ip=self.pg1.remote_ip4)
6084
6085 pkts = self.create_stream_out(self.pg1, dst_ip=self.vrf1_nat_addr)
6086 self.pg1.add_stream(pkts)
6087 self.pg_enable_capture(self.pg_interfaces)
6088 self.pg_start()
6089 capture = self.pg2.get_capture(len(pkts))
6090 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg2.remote_ip6)
6091
Matus Fabian06596c52017-06-06 04:53:28 -07006092 def test_static(self):
6093 """ NAT64 static translation test """
6094 self.tcp_port_in = 60303
6095 self.udp_port_in = 60304
6096 self.icmp_id_in = 60305
6097 self.tcp_port_out = 60303
6098 self.udp_port_out = 60304
6099 self.icmp_id_out = 60305
6100
6101 ses_num_start = self.nat64_get_ses_num()
6102
6103 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6104 self.nat_addr_n)
6105 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6106 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6107
6108 self.vapi.nat64_add_del_static_bib(self.pg0.remote_ip6n,
6109 self.nat_addr_n,
6110 self.tcp_port_in,
6111 self.tcp_port_out,
6112 IP_PROTOS.tcp)
6113 self.vapi.nat64_add_del_static_bib(self.pg0.remote_ip6n,
6114 self.nat_addr_n,
6115 self.udp_port_in,
6116 self.udp_port_out,
6117 IP_PROTOS.udp)
6118 self.vapi.nat64_add_del_static_bib(self.pg0.remote_ip6n,
6119 self.nat_addr_n,
6120 self.icmp_id_in,
6121 self.icmp_id_out,
6122 IP_PROTOS.icmp)
6123
6124 # in2out
6125 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
6126 self.pg0.add_stream(pkts)
6127 self.pg_enable_capture(self.pg_interfaces)
6128 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07006129 capture = self.pg1.get_capture(len(pkts))
6130 self.verify_capture_out(capture, nat_ip=self.nat_addr,
Matus Fabian06596c52017-06-06 04:53:28 -07006131 dst_ip=self.pg1.remote_ip4, same_port=True)
6132
6133 # out2in
6134 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
6135 self.pg1.add_stream(pkts)
6136 self.pg_enable_capture(self.pg_interfaces)
6137 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07006138 capture = self.pg0.get_capture(len(pkts))
Matus Fabian06596c52017-06-06 04:53:28 -07006139 ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
6140 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
6141
6142 ses_num_end = self.nat64_get_ses_num()
6143
6144 self.assertEqual(ses_num_end - ses_num_start, 3)
6145
6146 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
6147 def test_session_timeout(self):
6148 """ NAT64 session timeout """
6149 self.icmp_id_in = 1234
6150 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6151 self.nat_addr_n)
6152 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6153 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
Matus Fabian878c6462018-08-23 00:33:35 -07006154 self.vapi.nat_set_timeouts(icmp=5, tcp_transitory=5, tcp_established=5)
Matus Fabian06596c52017-06-06 04:53:28 -07006155
6156 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
6157 self.pg0.add_stream(pkts)
6158 self.pg_enable_capture(self.pg_interfaces)
6159 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07006160 capture = self.pg1.get_capture(len(pkts))
Matus Fabian06596c52017-06-06 04:53:28 -07006161
6162 ses_num_before_timeout = self.nat64_get_ses_num()
6163
6164 sleep(15)
6165
Matus Fabian8fed4242018-08-14 05:14:55 -07006166 # ICMP and TCP session after timeout
Matus Fabian06596c52017-06-06 04:53:28 -07006167 ses_num_after_timeout = self.nat64_get_ses_num()
Matus Fabian8fed4242018-08-14 05:14:55 -07006168 self.assertEqual(ses_num_before_timeout - ses_num_after_timeout, 2)
Matus Fabian06596c52017-06-06 04:53:28 -07006169
Matus Fabian732036d2017-06-08 05:24:28 -07006170 def test_icmp_error(self):
6171 """ NAT64 ICMP Error message translation """
6172 self.tcp_port_in = 6303
6173 self.udp_port_in = 6304
6174 self.icmp_id_in = 6305
6175
Matus Fabian732036d2017-06-08 05:24:28 -07006176 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6177 self.nat_addr_n)
6178 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6179 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6180
6181 # send some packets to create sessions
6182 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
6183 self.pg0.add_stream(pkts)
6184 self.pg_enable_capture(self.pg_interfaces)
6185 self.pg_start()
6186 capture_ip4 = self.pg1.get_capture(len(pkts))
Matus Fabian029f3d22017-06-15 02:28:50 -07006187 self.verify_capture_out(capture_ip4,
Matus Fabian732036d2017-06-08 05:24:28 -07006188 nat_ip=self.nat_addr,
6189 dst_ip=self.pg1.remote_ip4)
6190
6191 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
6192 self.pg1.add_stream(pkts)
6193 self.pg_enable_capture(self.pg_interfaces)
6194 self.pg_start()
6195 capture_ip6 = self.pg0.get_capture(len(pkts))
6196 ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
6197 self.verify_capture_in_ip6(capture_ip6, ip[IPv6].src,
6198 self.pg0.remote_ip6)
6199
6200 # in2out
6201 pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6202 IPv6(src=self.pg0.remote_ip6, dst=ip[IPv6].src) /
6203 ICMPv6DestUnreach(code=1) /
6204 packet[IPv6] for packet in capture_ip6]
6205 self.pg0.add_stream(pkts)
6206 self.pg_enable_capture(self.pg_interfaces)
6207 self.pg_start()
6208 capture = self.pg1.get_capture(len(pkts))
6209 for packet in capture:
6210 try:
6211 self.assertEqual(packet[IP].src, self.nat_addr)
6212 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
6213 self.assertEqual(packet[ICMP].type, 3)
6214 self.assertEqual(packet[ICMP].code, 13)
6215 inner = packet[IPerror]
6216 self.assertEqual(inner.src, self.pg1.remote_ip4)
6217 self.assertEqual(inner.dst, self.nat_addr)
Klement Sekerad81ae412018-05-16 10:52:54 +02006218 self.assert_packet_checksums_valid(packet)
Matus Fabian732036d2017-06-08 05:24:28 -07006219 if inner.haslayer(TCPerror):
6220 self.assertEqual(inner[TCPerror].dport, self.tcp_port_out)
6221 elif inner.haslayer(UDPerror):
6222 self.assertEqual(inner[UDPerror].dport, self.udp_port_out)
6223 else:
6224 self.assertEqual(inner[ICMPerror].id, self.icmp_id_out)
6225 except:
6226 self.logger.error(ppp("Unexpected or invalid packet:", packet))
6227 raise
6228
6229 # out2in
6230 pkts = [Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
6231 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6232 ICMP(type=3, code=13) /
6233 packet[IP] for packet in capture_ip4]
6234 self.pg1.add_stream(pkts)
6235 self.pg_enable_capture(self.pg_interfaces)
6236 self.pg_start()
6237 capture = self.pg0.get_capture(len(pkts))
6238 for packet in capture:
6239 try:
6240 self.assertEqual(packet[IPv6].src, ip.src)
6241 self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
6242 icmp = packet[ICMPv6DestUnreach]
6243 self.assertEqual(icmp.code, 1)
6244 inner = icmp[IPerror6]
6245 self.assertEqual(inner.src, self.pg0.remote_ip6)
6246 self.assertEqual(inner.dst, ip.src)
Klement Sekerad81ae412018-05-16 10:52:54 +02006247 self.assert_icmpv6_checksum_valid(packet)
Matus Fabian732036d2017-06-08 05:24:28 -07006248 if inner.haslayer(TCPerror):
6249 self.assertEqual(inner[TCPerror].sport, self.tcp_port_in)
6250 elif inner.haslayer(UDPerror):
6251 self.assertEqual(inner[UDPerror].sport, self.udp_port_in)
6252 else:
6253 self.assertEqual(inner[ICMPv6EchoRequest].id,
6254 self.icmp_id_in)
6255 except:
6256 self.logger.error(ppp("Unexpected or invalid packet:", packet))
6257 raise
6258
Matus Fabian029f3d22017-06-15 02:28:50 -07006259 def test_hairpinning(self):
6260 """ NAT64 hairpinning """
6261
6262 client = self.pg0.remote_hosts[0]
6263 server = self.pg0.remote_hosts[1]
6264 server_tcp_in_port = 22
6265 server_tcp_out_port = 4022
6266 server_udp_in_port = 23
6267 server_udp_out_port = 4023
6268 client_tcp_in_port = 1234
6269 client_udp_in_port = 1235
6270 client_tcp_out_port = 0
6271 client_udp_out_port = 0
6272 ip = IPv6(src=''.join(['64:ff9b::', self.nat_addr]))
6273 nat_addr_ip6 = ip.src
6274
6275 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6276 self.nat_addr_n)
6277 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6278 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6279
6280 self.vapi.nat64_add_del_static_bib(server.ip6n,
6281 self.nat_addr_n,
6282 server_tcp_in_port,
6283 server_tcp_out_port,
6284 IP_PROTOS.tcp)
6285 self.vapi.nat64_add_del_static_bib(server.ip6n,
6286 self.nat_addr_n,
6287 server_udp_in_port,
6288 server_udp_out_port,
6289 IP_PROTOS.udp)
6290
6291 # client to server
6292 pkts = []
6293 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6294 IPv6(src=client.ip6, dst=nat_addr_ip6) /
6295 TCP(sport=client_tcp_in_port, dport=server_tcp_out_port))
6296 pkts.append(p)
6297 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6298 IPv6(src=client.ip6, dst=nat_addr_ip6) /
6299 UDP(sport=client_udp_in_port, dport=server_udp_out_port))
6300 pkts.append(p)
6301 self.pg0.add_stream(pkts)
6302 self.pg_enable_capture(self.pg_interfaces)
6303 self.pg_start()
6304 capture = self.pg0.get_capture(len(pkts))
6305 for packet in capture:
6306 try:
6307 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
6308 self.assertEqual(packet[IPv6].dst, server.ip6)
Klement Sekerad81ae412018-05-16 10:52:54 +02006309 self.assert_packet_checksums_valid(packet)
Matus Fabian029f3d22017-06-15 02:28:50 -07006310 if packet.haslayer(TCP):
6311 self.assertNotEqual(packet[TCP].sport, client_tcp_in_port)
6312 self.assertEqual(packet[TCP].dport, server_tcp_in_port)
Matus Fabian029f3d22017-06-15 02:28:50 -07006313 client_tcp_out_port = packet[TCP].sport
6314 else:
6315 self.assertNotEqual(packet[UDP].sport, client_udp_in_port)
6316 self.assertEqual(packet[UDP].dport, server_udp_in_port)
Matus Fabian029f3d22017-06-15 02:28:50 -07006317 client_udp_out_port = packet[UDP].sport
6318 except:
6319 self.logger.error(ppp("Unexpected or invalid packet:", packet))
6320 raise
6321
6322 # server to client
6323 pkts = []
6324 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6325 IPv6(src=server.ip6, dst=nat_addr_ip6) /
6326 TCP(sport=server_tcp_in_port, dport=client_tcp_out_port))
6327 pkts.append(p)
6328 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6329 IPv6(src=server.ip6, dst=nat_addr_ip6) /
6330 UDP(sport=server_udp_in_port, dport=client_udp_out_port))
6331 pkts.append(p)
6332 self.pg0.add_stream(pkts)
6333 self.pg_enable_capture(self.pg_interfaces)
6334 self.pg_start()
6335 capture = self.pg0.get_capture(len(pkts))
6336 for packet in capture:
6337 try:
6338 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
6339 self.assertEqual(packet[IPv6].dst, client.ip6)
Klement Sekerad81ae412018-05-16 10:52:54 +02006340 self.assert_packet_checksums_valid(packet)
Matus Fabian029f3d22017-06-15 02:28:50 -07006341 if packet.haslayer(TCP):
6342 self.assertEqual(packet[TCP].sport, server_tcp_out_port)
6343 self.assertEqual(packet[TCP].dport, client_tcp_in_port)
Matus Fabian029f3d22017-06-15 02:28:50 -07006344 else:
6345 self.assertEqual(packet[UDP].sport, server_udp_out_port)
6346 self.assertEqual(packet[UDP].dport, client_udp_in_port)
Matus Fabian029f3d22017-06-15 02:28:50 -07006347 except:
6348 self.logger.error(ppp("Unexpected or invalid packet:", packet))
6349 raise
6350
6351 # ICMP error
6352 pkts = []
6353 pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6354 IPv6(src=client.ip6, dst=nat_addr_ip6) /
6355 ICMPv6DestUnreach(code=1) /
6356 packet[IPv6] for packet in capture]
6357 self.pg0.add_stream(pkts)
6358 self.pg_enable_capture(self.pg_interfaces)
6359 self.pg_start()
6360 capture = self.pg0.get_capture(len(pkts))
6361 for packet in capture:
6362 try:
6363 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
6364 self.assertEqual(packet[IPv6].dst, server.ip6)
6365 icmp = packet[ICMPv6DestUnreach]
6366 self.assertEqual(icmp.code, 1)
6367 inner = icmp[IPerror6]
6368 self.assertEqual(inner.src, server.ip6)
6369 self.assertEqual(inner.dst, nat_addr_ip6)
Klement Sekerad81ae412018-05-16 10:52:54 +02006370 self.assert_packet_checksums_valid(packet)
Matus Fabian029f3d22017-06-15 02:28:50 -07006371 if inner.haslayer(TCPerror):
6372 self.assertEqual(inner[TCPerror].sport, server_tcp_in_port)
6373 self.assertEqual(inner[TCPerror].dport,
6374 client_tcp_out_port)
6375 else:
6376 self.assertEqual(inner[UDPerror].sport, server_udp_in_port)
6377 self.assertEqual(inner[UDPerror].dport,
6378 client_udp_out_port)
6379 except:
6380 self.logger.error(ppp("Unexpected or invalid packet:", packet))
6381 raise
6382
Matus Fabian428dc912017-06-21 06:15:18 -07006383 def test_prefix(self):
6384 """ NAT64 Network-Specific Prefix """
6385
6386 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6387 self.nat_addr_n)
6388 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6389 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6390 self.vapi.nat64_add_del_pool_addr_range(self.vrf1_nat_addr_n,
6391 self.vrf1_nat_addr_n,
6392 vrf_id=self.vrf1_id)
6393 self.vapi.nat64_add_del_interface(self.pg2.sw_if_index)
6394
6395 # Add global prefix
6396 global_pref64 = "2001:db8::"
6397 global_pref64_n = socket.inet_pton(socket.AF_INET6, global_pref64)
6398 global_pref64_len = 32
6399 self.vapi.nat64_add_del_prefix(global_pref64_n, global_pref64_len)
6400
6401 prefix = self.vapi.nat64_prefix_dump()
6402 self.assertEqual(len(prefix), 1)
6403 self.assertEqual(prefix[0].prefix, global_pref64_n)
6404 self.assertEqual(prefix[0].prefix_len, global_pref64_len)
6405 self.assertEqual(prefix[0].vrf_id, 0)
6406
6407 # Add tenant specific prefix
6408 vrf1_pref64 = "2001:db8:122:300::"
6409 vrf1_pref64_n = socket.inet_pton(socket.AF_INET6, vrf1_pref64)
6410 vrf1_pref64_len = 56
6411 self.vapi.nat64_add_del_prefix(vrf1_pref64_n,
6412 vrf1_pref64_len,
6413 vrf_id=self.vrf1_id)
6414 prefix = self.vapi.nat64_prefix_dump()
6415 self.assertEqual(len(prefix), 2)
6416
6417 # Global prefix
6418 pkts = self.create_stream_in_ip6(self.pg0,
6419 self.pg1,
6420 pref=global_pref64,
6421 plen=global_pref64_len)
6422 self.pg0.add_stream(pkts)
6423 self.pg_enable_capture(self.pg_interfaces)
6424 self.pg_start()
6425 capture = self.pg1.get_capture(len(pkts))
6426 self.verify_capture_out(capture, nat_ip=self.nat_addr,
6427 dst_ip=self.pg1.remote_ip4)
6428
6429 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
6430 self.pg1.add_stream(pkts)
6431 self.pg_enable_capture(self.pg_interfaces)
6432 self.pg_start()
6433 capture = self.pg0.get_capture(len(pkts))
6434 dst_ip = self.compose_ip6(self.pg1.remote_ip4,
6435 global_pref64,
6436 global_pref64_len)
6437 self.verify_capture_in_ip6(capture, dst_ip, self.pg0.remote_ip6)
6438
6439 # Tenant specific prefix
6440 pkts = self.create_stream_in_ip6(self.pg2,
6441 self.pg1,
6442 pref=vrf1_pref64,
6443 plen=vrf1_pref64_len)
6444 self.pg2.add_stream(pkts)
6445 self.pg_enable_capture(self.pg_interfaces)
6446 self.pg_start()
6447 capture = self.pg1.get_capture(len(pkts))
6448 self.verify_capture_out(capture, nat_ip=self.vrf1_nat_addr,
6449 dst_ip=self.pg1.remote_ip4)
6450
6451 pkts = self.create_stream_out(self.pg1, dst_ip=self.vrf1_nat_addr)
6452 self.pg1.add_stream(pkts)
6453 self.pg_enable_capture(self.pg_interfaces)
6454 self.pg_start()
6455 capture = self.pg2.get_capture(len(pkts))
6456 dst_ip = self.compose_ip6(self.pg1.remote_ip4,
6457 vrf1_pref64,
6458 vrf1_pref64_len)
6459 self.verify_capture_in_ip6(capture, dst_ip, self.pg2.remote_ip6)
6460
Matus Fabianf8cd5812017-07-11 03:55:02 -07006461 def test_unknown_proto(self):
Matus Fabian7968e6c2017-07-06 05:37:49 -07006462 """ NAT64 translate packet with unknown protocol """
6463
6464 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6465 self.nat_addr_n)
6466 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6467 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6468 remote_ip6 = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
6469
6470 # in2out
6471 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6472 IPv6(src=self.pg0.remote_ip6, dst=remote_ip6) /
6473 TCP(sport=self.tcp_port_in, dport=20))
6474 self.pg0.add_stream(p)
6475 self.pg_enable_capture(self.pg_interfaces)
6476 self.pg_start()
6477 p = self.pg1.get_capture(1)
6478
6479 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabianf8cd5812017-07-11 03:55:02 -07006480 IPv6(src=self.pg0.remote_ip6, dst=remote_ip6, nh=47) /
Matus Fabian7968e6c2017-07-06 05:37:49 -07006481 GRE() /
6482 IP(src=self.pg2.local_ip4, dst=self.pg2.remote_ip4) /
6483 TCP(sport=1234, dport=1234))
6484 self.pg0.add_stream(p)
6485 self.pg_enable_capture(self.pg_interfaces)
6486 self.pg_start()
6487 p = self.pg1.get_capture(1)
6488 packet = p[0]
6489 try:
6490 self.assertEqual(packet[IP].src, self.nat_addr)
6491 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
6492 self.assertTrue(packet.haslayer(GRE))
Klement Sekerad81ae412018-05-16 10:52:54 +02006493 self.assert_packet_checksums_valid(packet)
Matus Fabian7968e6c2017-07-06 05:37:49 -07006494 except:
6495 self.logger.error(ppp("Unexpected or invalid packet:", packet))
6496 raise
6497
6498 # out2in
6499 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
6500 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6501 GRE() /
6502 IP(src=self.pg2.remote_ip4, dst=self.pg2.local_ip4) /
6503 TCP(sport=1234, dport=1234))
6504 self.pg1.add_stream(p)
6505 self.pg_enable_capture(self.pg_interfaces)
6506 self.pg_start()
6507 p = self.pg0.get_capture(1)
6508 packet = p[0]
6509 try:
6510 self.assertEqual(packet[IPv6].src, remote_ip6)
Matus Fabianf8cd5812017-07-11 03:55:02 -07006511 self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
6512 self.assertEqual(packet[IPv6].nh, 47)
Matus Fabian7968e6c2017-07-06 05:37:49 -07006513 except:
6514 self.logger.error(ppp("Unexpected or invalid packet:", packet))
6515 raise
6516
Matus Fabianf8cd5812017-07-11 03:55:02 -07006517 def test_hairpinning_unknown_proto(self):
Matus Fabian7968e6c2017-07-06 05:37:49 -07006518 """ NAT64 translate packet with unknown protocol - hairpinning """
6519
6520 client = self.pg0.remote_hosts[0]
6521 server = self.pg0.remote_hosts[1]
6522 server_tcp_in_port = 22
6523 server_tcp_out_port = 4022
6524 client_tcp_in_port = 1234
Matus Fabianf8cd5812017-07-11 03:55:02 -07006525 client_tcp_out_port = 1235
6526 server_nat_ip = "10.0.0.100"
6527 client_nat_ip = "10.0.0.110"
6528 server_nat_ip_n = socket.inet_pton(socket.AF_INET, server_nat_ip)
6529 client_nat_ip_n = socket.inet_pton(socket.AF_INET, client_nat_ip)
6530 server_nat_ip6 = self.compose_ip6(server_nat_ip, '64:ff9b::', 96)
6531 client_nat_ip6 = self.compose_ip6(client_nat_ip, '64:ff9b::', 96)
Matus Fabian7968e6c2017-07-06 05:37:49 -07006532
Matus Fabianf8cd5812017-07-11 03:55:02 -07006533 self.vapi.nat64_add_del_pool_addr_range(server_nat_ip_n,
6534 client_nat_ip_n)
Matus Fabian7968e6c2017-07-06 05:37:49 -07006535 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6536 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6537
6538 self.vapi.nat64_add_del_static_bib(server.ip6n,
Matus Fabianf8cd5812017-07-11 03:55:02 -07006539 server_nat_ip_n,
Matus Fabian7968e6c2017-07-06 05:37:49 -07006540 server_tcp_in_port,
6541 server_tcp_out_port,
6542 IP_PROTOS.tcp)
6543
Matus Fabianf8cd5812017-07-11 03:55:02 -07006544 self.vapi.nat64_add_del_static_bib(server.ip6n,
6545 server_nat_ip_n,
6546 0,
6547 0,
6548 IP_PROTOS.gre)
6549
6550 self.vapi.nat64_add_del_static_bib(client.ip6n,
6551 client_nat_ip_n,
6552 client_tcp_in_port,
6553 client_tcp_out_port,
6554 IP_PROTOS.tcp)
6555
Matus Fabian7968e6c2017-07-06 05:37:49 -07006556 # client to server
6557 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabianf8cd5812017-07-11 03:55:02 -07006558 IPv6(src=client.ip6, dst=server_nat_ip6) /
Matus Fabian7968e6c2017-07-06 05:37:49 -07006559 TCP(sport=client_tcp_in_port, dport=server_tcp_out_port))
6560 self.pg0.add_stream(p)
6561 self.pg_enable_capture(self.pg_interfaces)
6562 self.pg_start()
6563 p = self.pg0.get_capture(1)
6564
6565 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabianf8cd5812017-07-11 03:55:02 -07006566 IPv6(src=client.ip6, dst=server_nat_ip6, nh=IP_PROTOS.gre) /
Matus Fabian7968e6c2017-07-06 05:37:49 -07006567 GRE() /
6568 IP(src=self.pg2.local_ip4, dst=self.pg2.remote_ip4) /
6569 TCP(sport=1234, dport=1234))
6570 self.pg0.add_stream(p)
6571 self.pg_enable_capture(self.pg_interfaces)
6572 self.pg_start()
6573 p = self.pg0.get_capture(1)
6574 packet = p[0]
6575 try:
Matus Fabianf8cd5812017-07-11 03:55:02 -07006576 self.assertEqual(packet[IPv6].src, client_nat_ip6)
Matus Fabian7968e6c2017-07-06 05:37:49 -07006577 self.assertEqual(packet[IPv6].dst, server.ip6)
Matus Fabianf8cd5812017-07-11 03:55:02 -07006578 self.assertEqual(packet[IPv6].nh, IP_PROTOS.gre)
Matus Fabian7968e6c2017-07-06 05:37:49 -07006579 except:
6580 self.logger.error(ppp("Unexpected or invalid packet:", packet))
6581 raise
6582
6583 # server to client
6584 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabianf8cd5812017-07-11 03:55:02 -07006585 IPv6(src=server.ip6, dst=client_nat_ip6, nh=IP_PROTOS.gre) /
Matus Fabian7968e6c2017-07-06 05:37:49 -07006586 GRE() /
6587 IP(src=self.pg2.remote_ip4, dst=self.pg2.local_ip4) /
6588 TCP(sport=1234, dport=1234))
6589 self.pg0.add_stream(p)
6590 self.pg_enable_capture(self.pg_interfaces)
6591 self.pg_start()
6592 p = self.pg0.get_capture(1)
6593 packet = p[0]
6594 try:
Matus Fabianf8cd5812017-07-11 03:55:02 -07006595 self.assertEqual(packet[IPv6].src, server_nat_ip6)
Matus Fabian7968e6c2017-07-06 05:37:49 -07006596 self.assertEqual(packet[IPv6].dst, client.ip6)
Matus Fabianf8cd5812017-07-11 03:55:02 -07006597 self.assertEqual(packet[IPv6].nh, IP_PROTOS.gre)
Matus Fabian7968e6c2017-07-06 05:37:49 -07006598 except:
6599 self.logger.error(ppp("Unexpected or invalid packet:", packet))
6600 raise
6601
Matus Fabian36ea2d62017-10-24 04:13:49 -07006602 def test_one_armed_nat64(self):
6603 """ One armed NAT64 """
6604 external_port = 0
6605 remote_host_ip6 = self.compose_ip6(self.pg3.remote_ip4,
6606 '64:ff9b::',
6607 96)
6608
6609 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6610 self.nat_addr_n)
6611 self.vapi.nat64_add_del_interface(self.pg3.sw_if_index)
6612 self.vapi.nat64_add_del_interface(self.pg3.sw_if_index, is_inside=0)
6613
6614 # in2out
6615 p = (Ether(src=self.pg3.remote_mac, dst=self.pg3.local_mac) /
6616 IPv6(src=self.pg3.remote_ip6, dst=remote_host_ip6) /
6617 TCP(sport=12345, dport=80))
6618 self.pg3.add_stream(p)
6619 self.pg_enable_capture(self.pg_interfaces)
6620 self.pg_start()
6621 capture = self.pg3.get_capture(1)
6622 p = capture[0]
6623 try:
6624 ip = p[IP]
6625 tcp = p[TCP]
6626 self.assertEqual(ip.src, self.nat_addr)
6627 self.assertEqual(ip.dst, self.pg3.remote_ip4)
6628 self.assertNotEqual(tcp.sport, 12345)
6629 external_port = tcp.sport
6630 self.assertEqual(tcp.dport, 80)
Klement Sekerad81ae412018-05-16 10:52:54 +02006631 self.assert_packet_checksums_valid(p)
Matus Fabian36ea2d62017-10-24 04:13:49 -07006632 except:
6633 self.logger.error(ppp("Unexpected or invalid packet:", p))
6634 raise
6635
6636 # out2in
6637 p = (Ether(src=self.pg3.remote_mac, dst=self.pg3.local_mac) /
6638 IP(src=self.pg3.remote_ip4, dst=self.nat_addr) /
6639 TCP(sport=80, dport=external_port))
6640 self.pg3.add_stream(p)
6641 self.pg_enable_capture(self.pg_interfaces)
6642 self.pg_start()
6643 capture = self.pg3.get_capture(1)
6644 p = capture[0]
6645 try:
6646 ip = p[IPv6]
6647 tcp = p[TCP]
6648 self.assertEqual(ip.src, remote_host_ip6)
6649 self.assertEqual(ip.dst, self.pg3.remote_ip6)
6650 self.assertEqual(tcp.sport, 80)
6651 self.assertEqual(tcp.dport, 12345)
Klement Sekerad81ae412018-05-16 10:52:54 +02006652 self.assert_packet_checksums_valid(p)
Matus Fabian36ea2d62017-10-24 04:13:49 -07006653 except:
6654 self.logger.error(ppp("Unexpected or invalid packet:", p))
6655 raise
6656
Matus Fabianefcd1e92017-08-15 06:59:19 -07006657 def test_frag_in_order(self):
6658 """ NAT64 translate fragments arriving in order """
6659 self.tcp_port_in = random.randint(1025, 65535)
6660
6661 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6662 self.nat_addr_n)
6663 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6664 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6665
6666 reass = self.vapi.nat_reass_dump()
6667 reass_n_start = len(reass)
6668
6669 # in2out
6670 data = 'a' * 200
6671 pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
6672 self.tcp_port_in, 20, data)
6673 self.pg0.add_stream(pkts)
6674 self.pg_enable_capture(self.pg_interfaces)
6675 self.pg_start()
6676 frags = self.pg1.get_capture(len(pkts))
6677 p = self.reass_frags_and_verify(frags,
6678 self.nat_addr,
6679 self.pg1.remote_ip4)
6680 self.assertEqual(p[TCP].dport, 20)
6681 self.assertNotEqual(p[TCP].sport, self.tcp_port_in)
6682 self.tcp_port_out = p[TCP].sport
6683 self.assertEqual(data, p[Raw].load)
6684
6685 # out2in
6686 data = "A" * 4 + "b" * 16 + "C" * 3
6687 pkts = self.create_stream_frag(self.pg1,
6688 self.nat_addr,
6689 20,
6690 self.tcp_port_out,
6691 data)
6692 self.pg1.add_stream(pkts)
6693 self.pg_enable_capture(self.pg_interfaces)
6694 self.pg_start()
6695 frags = self.pg0.get_capture(len(pkts))
6696 src = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
6697 p = self.reass_frags_and_verify_ip6(frags, src, self.pg0.remote_ip6)
6698 self.assertEqual(p[TCP].sport, 20)
6699 self.assertEqual(p[TCP].dport, self.tcp_port_in)
6700 self.assertEqual(data, p[Raw].load)
6701
6702 reass = self.vapi.nat_reass_dump()
6703 reass_n_end = len(reass)
6704
6705 self.assertEqual(reass_n_end - reass_n_start, 2)
6706
6707 def test_reass_hairpinning(self):
6708 """ NAT64 fragments hairpinning """
6709 data = 'a' * 200
Matus Fabianefcd1e92017-08-15 06:59:19 -07006710 server = self.pg0.remote_hosts[1]
6711 server_in_port = random.randint(1025, 65535)
6712 server_out_port = random.randint(1025, 65535)
6713 client_in_port = random.randint(1025, 65535)
6714 ip = IPv6(src=''.join(['64:ff9b::', self.nat_addr]))
6715 nat_addr_ip6 = ip.src
6716
6717 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6718 self.nat_addr_n)
6719 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6720 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6721
6722 # add static BIB entry for server
6723 self.vapi.nat64_add_del_static_bib(server.ip6n,
6724 self.nat_addr_n,
6725 server_in_port,
6726 server_out_port,
6727 IP_PROTOS.tcp)
6728
6729 # send packet from host to server
6730 pkts = self.create_stream_frag_ip6(self.pg0,
6731 self.nat_addr,
6732 client_in_port,
6733 server_out_port,
6734 data)
6735 self.pg0.add_stream(pkts)
6736 self.pg_enable_capture(self.pg_interfaces)
6737 self.pg_start()
6738 frags = self.pg0.get_capture(len(pkts))
6739 p = self.reass_frags_and_verify_ip6(frags, nat_addr_ip6, server.ip6)
6740 self.assertNotEqual(p[TCP].sport, client_in_port)
6741 self.assertEqual(p[TCP].dport, server_in_port)
6742 self.assertEqual(data, p[Raw].load)
6743
6744 def test_frag_out_of_order(self):
6745 """ NAT64 translate fragments arriving out of order """
6746 self.tcp_port_in = random.randint(1025, 65535)
6747
6748 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6749 self.nat_addr_n)
6750 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6751 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6752
6753 # in2out
6754 data = 'a' * 200
6755 pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
6756 self.tcp_port_in, 20, data)
6757 pkts.reverse()
6758 self.pg0.add_stream(pkts)
6759 self.pg_enable_capture(self.pg_interfaces)
6760 self.pg_start()
6761 frags = self.pg1.get_capture(len(pkts))
6762 p = self.reass_frags_and_verify(frags,
6763 self.nat_addr,
6764 self.pg1.remote_ip4)
6765 self.assertEqual(p[TCP].dport, 20)
6766 self.assertNotEqual(p[TCP].sport, self.tcp_port_in)
6767 self.tcp_port_out = p[TCP].sport
6768 self.assertEqual(data, p[Raw].load)
6769
6770 # out2in
6771 data = "A" * 4 + "B" * 16 + "C" * 3
6772 pkts = self.create_stream_frag(self.pg1,
6773 self.nat_addr,
6774 20,
6775 self.tcp_port_out,
6776 data)
6777 pkts.reverse()
6778 self.pg1.add_stream(pkts)
6779 self.pg_enable_capture(self.pg_interfaces)
6780 self.pg_start()
6781 frags = self.pg0.get_capture(len(pkts))
6782 src = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
6783 p = self.reass_frags_and_verify_ip6(frags, src, self.pg0.remote_ip6)
6784 self.assertEqual(p[TCP].sport, 20)
6785 self.assertEqual(p[TCP].dport, self.tcp_port_in)
6786 self.assertEqual(data, p[Raw].load)
6787
Matus Fabian0938dcf2017-11-08 01:59:38 -08006788 def test_interface_addr(self):
6789 """ Acquire NAT64 pool addresses from interface """
6790 self.vapi.nat64_add_interface_addr(self.pg4.sw_if_index)
6791
6792 # no address in NAT64 pool
6793 adresses = self.vapi.nat44_address_dump()
6794 self.assertEqual(0, len(adresses))
6795
6796 # configure interface address and check NAT64 address pool
6797 self.pg4.config_ip4()
6798 addresses = self.vapi.nat64_pool_addr_dump()
6799 self.assertEqual(len(addresses), 1)
6800 self.assertEqual(addresses[0].address, self.pg4.local_ip4n)
6801
6802 # remove interface address and check NAT64 address pool
6803 self.pg4.unconfig_ip4()
6804 addresses = self.vapi.nat64_pool_addr_dump()
6805 self.assertEqual(0, len(adresses))
6806
Matus Fabiana431ad12018-01-04 04:03:14 -08006807 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
6808 def test_ipfix_max_bibs_sessions(self):
6809 """ IPFIX logging maximum session and BIB entries exceeded """
6810 max_bibs = 1280
6811 max_sessions = 2560
6812 remote_host_ip6 = self.compose_ip6(self.pg1.remote_ip4,
6813 '64:ff9b::',
6814 96)
6815
6816 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6817 self.nat_addr_n)
6818 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6819 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6820
6821 pkts = []
6822 src = ""
6823 for i in range(0, max_bibs):
6824 src = "fd01:aa::%x" % (i)
6825 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6826 IPv6(src=src, dst=remote_host_ip6) /
6827 TCP(sport=12345, dport=80))
6828 pkts.append(p)
6829 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6830 IPv6(src=src, dst=remote_host_ip6) /
6831 TCP(sport=12345, dport=22))
6832 pkts.append(p)
6833 self.pg0.add_stream(pkts)
6834 self.pg_enable_capture(self.pg_interfaces)
6835 self.pg_start()
6836 self.pg1.get_capture(max_sessions)
6837
6838 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
6839 src_address=self.pg3.local_ip4n,
6840 path_mtu=512,
6841 template_interval=10)
6842 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
6843 src_port=self.ipfix_src_port)
6844
6845 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6846 IPv6(src=src, dst=remote_host_ip6) /
6847 TCP(sport=12345, dport=25))
6848 self.pg0.add_stream(p)
6849 self.pg_enable_capture(self.pg_interfaces)
6850 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07006851 self.pg1.assert_nothing_captured()
6852 sleep(1)
Matus Fabiana431ad12018-01-04 04:03:14 -08006853 self.vapi.cli("ipfix flush") # FIXME this should be an API call
6854 capture = self.pg3.get_capture(9)
6855 ipfix = IPFIXDecoder()
6856 # first load template
6857 for p in capture:
6858 self.assertTrue(p.haslayer(IPFIX))
6859 self.assertEqual(p[IP].src, self.pg3.local_ip4)
6860 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
6861 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
6862 self.assertEqual(p[UDP].dport, 4739)
6863 self.assertEqual(p[IPFIX].observationDomainID,
6864 self.ipfix_domain_id)
6865 if p.haslayer(Template):
6866 ipfix.add_template(p.getlayer(Template))
6867 # verify events in data set
6868 for p in capture:
6869 if p.haslayer(Data):
6870 data = ipfix.decode_data_set(p.getlayer(Set))
6871 self.verify_ipfix_max_sessions(data, max_sessions)
6872
6873 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6874 IPv6(src=self.pg0.remote_ip6, dst=remote_host_ip6) /
6875 TCP(sport=12345, dport=80))
6876 self.pg0.add_stream(p)
6877 self.pg_enable_capture(self.pg_interfaces)
6878 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07006879 self.pg1.assert_nothing_captured()
6880 sleep(1)
Matus Fabiana431ad12018-01-04 04:03:14 -08006881 self.vapi.cli("ipfix flush") # FIXME this should be an API call
6882 capture = self.pg3.get_capture(1)
6883 # verify events in data set
6884 for p in capture:
6885 self.assertTrue(p.haslayer(IPFIX))
6886 self.assertEqual(p[IP].src, self.pg3.local_ip4)
6887 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
6888 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
6889 self.assertEqual(p[UDP].dport, 4739)
6890 self.assertEqual(p[IPFIX].observationDomainID,
6891 self.ipfix_domain_id)
6892 if p.haslayer(Data):
6893 data = ipfix.decode_data_set(p.getlayer(Set))
6894 self.verify_ipfix_max_bibs(data, max_bibs)
6895
6896 def test_ipfix_max_frags(self):
6897 """ IPFIX logging maximum fragments pending reassembly exceeded """
6898 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6899 self.nat_addr_n)
6900 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6901 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6902 self.vapi.nat_set_reass(max_frag=0, is_ip6=1)
6903 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
6904 src_address=self.pg3.local_ip4n,
6905 path_mtu=512,
6906 template_interval=10)
6907 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
6908 src_port=self.ipfix_src_port)
6909
6910 data = 'a' * 200
6911 pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
6912 self.tcp_port_in, 20, data)
6913 self.pg0.add_stream(pkts[-1])
6914 self.pg_enable_capture(self.pg_interfaces)
6915 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07006916 self.pg1.assert_nothing_captured()
6917 sleep(1)
Matus Fabiana431ad12018-01-04 04:03:14 -08006918 self.vapi.cli("ipfix flush") # FIXME this should be an API call
6919 capture = self.pg3.get_capture(9)
6920 ipfix = IPFIXDecoder()
6921 # first load template
6922 for p in capture:
6923 self.assertTrue(p.haslayer(IPFIX))
6924 self.assertEqual(p[IP].src, self.pg3.local_ip4)
6925 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
6926 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
6927 self.assertEqual(p[UDP].dport, 4739)
6928 self.assertEqual(p[IPFIX].observationDomainID,
6929 self.ipfix_domain_id)
6930 if p.haslayer(Template):
6931 ipfix.add_template(p.getlayer(Template))
6932 # verify events in data set
6933 for p in capture:
6934 if p.haslayer(Data):
6935 data = ipfix.decode_data_set(p.getlayer(Set))
6936 self.verify_ipfix_max_fragments_ip6(data, 0,
6937 self.pg0.remote_ip6n)
6938
6939 def test_ipfix_bib_ses(self):
6940 """ IPFIX logging NAT64 BIB/session create and delete events """
6941 self.tcp_port_in = random.randint(1025, 65535)
6942 remote_host_ip6 = self.compose_ip6(self.pg1.remote_ip4,
6943 '64:ff9b::',
6944 96)
6945
6946 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6947 self.nat_addr_n)
6948 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6949 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6950 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
6951 src_address=self.pg3.local_ip4n,
6952 path_mtu=512,
6953 template_interval=10)
6954 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
6955 src_port=self.ipfix_src_port)
6956
6957 # Create
6958 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6959 IPv6(src=self.pg0.remote_ip6, dst=remote_host_ip6) /
6960 TCP(sport=self.tcp_port_in, dport=25))
6961 self.pg0.add_stream(p)
6962 self.pg_enable_capture(self.pg_interfaces)
6963 self.pg_start()
6964 p = self.pg1.get_capture(1)
6965 self.tcp_port_out = p[0][TCP].sport
6966 self.vapi.cli("ipfix flush") # FIXME this should be an API call
6967 capture = self.pg3.get_capture(10)
6968 ipfix = IPFIXDecoder()
6969 # first load template
6970 for p in capture:
6971 self.assertTrue(p.haslayer(IPFIX))
6972 self.assertEqual(p[IP].src, self.pg3.local_ip4)
6973 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
6974 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
6975 self.assertEqual(p[UDP].dport, 4739)
6976 self.assertEqual(p[IPFIX].observationDomainID,
6977 self.ipfix_domain_id)
6978 if p.haslayer(Template):
6979 ipfix.add_template(p.getlayer(Template))
6980 # verify events in data set
6981 for p in capture:
6982 if p.haslayer(Data):
6983 data = ipfix.decode_data_set(p.getlayer(Set))
6984 if ord(data[0][230]) == 10:
6985 self.verify_ipfix_bib(data, 1, self.pg0.remote_ip6n)
6986 elif ord(data[0][230]) == 6:
6987 self.verify_ipfix_nat64_ses(data,
6988 1,
6989 self.pg0.remote_ip6n,
6990 self.pg1.remote_ip4,
6991 25)
6992 else:
6993 self.logger.error(ppp("Unexpected or invalid packet: ", p))
6994
6995 # Delete
6996 self.pg_enable_capture(self.pg_interfaces)
6997 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6998 self.nat_addr_n,
6999 is_add=0)
7000 self.vapi.cli("ipfix flush") # FIXME this should be an API call
7001 capture = self.pg3.get_capture(2)
7002 # verify events in data set
7003 for p in capture:
7004 self.assertTrue(p.haslayer(IPFIX))
7005 self.assertEqual(p[IP].src, self.pg3.local_ip4)
7006 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
7007 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
7008 self.assertEqual(p[UDP].dport, 4739)
7009 self.assertEqual(p[IPFIX].observationDomainID,
7010 self.ipfix_domain_id)
7011 if p.haslayer(Data):
7012 data = ipfix.decode_data_set(p.getlayer(Set))
7013 if ord(data[0][230]) == 11:
7014 self.verify_ipfix_bib(data, 0, self.pg0.remote_ip6n)
7015 elif ord(data[0][230]) == 7:
7016 self.verify_ipfix_nat64_ses(data,
7017 0,
7018 self.pg0.remote_ip6n,
7019 self.pg1.remote_ip4,
7020 25)
7021 else:
7022 self.logger.error(ppp("Unexpected or invalid packet: ", p))
7023
Matus Fabian06596c52017-06-06 04:53:28 -07007024 def nat64_get_ses_num(self):
7025 """
7026 Return number of active NAT64 sessions.
7027 """
Matus Fabianab9a59c2017-08-16 05:37:36 -07007028 st = self.vapi.nat64_st_dump()
7029 return len(st)
Matus Fabian06596c52017-06-06 04:53:28 -07007030
7031 def clear_nat64(self):
7032 """
7033 Clear NAT64 configuration.
7034 """
Matus Fabiana431ad12018-01-04 04:03:14 -08007035 self.vapi.nat_ipfix(enable=0, src_port=self.ipfix_src_port,
7036 domain_id=self.ipfix_domain_id)
7037 self.ipfix_src_port = 4739
7038 self.ipfix_domain_id = 1
7039
Matus Fabian878c6462018-08-23 00:33:35 -07007040 self.vapi.nat_set_timeouts()
Matus Fabian06596c52017-06-06 04:53:28 -07007041
7042 interfaces = self.vapi.nat64_interface_dump()
7043 for intf in interfaces:
Matus Fabian36ea2d62017-10-24 04:13:49 -07007044 if intf.is_inside > 1:
7045 self.vapi.nat64_add_del_interface(intf.sw_if_index,
7046 0,
7047 is_add=0)
Matus Fabian06596c52017-06-06 04:53:28 -07007048 self.vapi.nat64_add_del_interface(intf.sw_if_index,
7049 intf.is_inside,
7050 is_add=0)
7051
Matus Fabiana431ad12018-01-04 04:03:14 -08007052 bib = self.vapi.nat64_bib_dump(255)
Matus Fabian06596c52017-06-06 04:53:28 -07007053 for bibe in bib:
7054 if bibe.is_static:
7055 self.vapi.nat64_add_del_static_bib(bibe.i_addr,
7056 bibe.o_addr,
7057 bibe.i_port,
7058 bibe.o_port,
7059 bibe.proto,
7060 bibe.vrf_id,
7061 is_add=0)
7062
7063 adresses = self.vapi.nat64_pool_addr_dump()
7064 for addr in adresses:
7065 self.vapi.nat64_add_del_pool_addr_range(addr.address,
7066 addr.address,
Matus Fabian029f3d22017-06-15 02:28:50 -07007067 vrf_id=addr.vrf_id,
Matus Fabian06596c52017-06-06 04:53:28 -07007068 is_add=0)
7069
Matus Fabian428dc912017-06-21 06:15:18 -07007070 prefixes = self.vapi.nat64_prefix_dump()
7071 for prefix in prefixes:
7072 self.vapi.nat64_add_del_prefix(prefix.prefix,
7073 prefix.prefix_len,
7074 vrf_id=prefix.vrf_id,
7075 is_add=0)
7076
Matus Fabian06596c52017-06-06 04:53:28 -07007077 def tearDown(self):
7078 super(TestNAT64, self).tearDown()
7079 if not self.vpp_dead:
7080 self.logger.info(self.vapi.cli("show nat64 pool"))
7081 self.logger.info(self.vapi.cli("show nat64 interfaces"))
Matus Fabian428dc912017-06-21 06:15:18 -07007082 self.logger.info(self.vapi.cli("show nat64 prefix"))
Matus Fabianab9a59c2017-08-16 05:37:36 -07007083 self.logger.info(self.vapi.cli("show nat64 bib all"))
7084 self.logger.info(self.vapi.cli("show nat64 session table all"))
Matus Fabianefcd1e92017-08-15 06:59:19 -07007085 self.logger.info(self.vapi.cli("show nat virtual-reassembly"))
Matus Fabian06596c52017-06-06 04:53:28 -07007086 self.clear_nat64()
7087
Matus Fabian8ebe6252017-11-06 05:04:53 -08007088
7089class TestDSlite(MethodHolder):
7090 """ DS-Lite Test Cases """
7091
7092 @classmethod
7093 def setUpClass(cls):
7094 super(TestDSlite, cls).setUpClass()
7095
7096 try:
7097 cls.nat_addr = '10.0.0.3'
7098 cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
7099
7100 cls.create_pg_interfaces(range(2))
7101 cls.pg0.admin_up()
7102 cls.pg0.config_ip4()
7103 cls.pg0.resolve_arp()
7104 cls.pg1.admin_up()
7105 cls.pg1.config_ip6()
7106 cls.pg1.generate_remote_hosts(2)
7107 cls.pg1.configure_ipv6_neighbors()
7108
7109 except Exception:
7110 super(TestDSlite, cls).tearDownClass()
7111 raise
7112
7113 def test_dslite(self):
7114 """ Test DS-Lite """
Matus Fabian69ce30d2018-08-22 01:27:10 -07007115 nat_config = self.vapi.nat_show_config()
7116 self.assertEqual(0, nat_config.dslite_ce)
7117
Matus Fabian8ebe6252017-11-06 05:04:53 -08007118 self.vapi.dslite_add_del_pool_addr_range(self.nat_addr_n,
7119 self.nat_addr_n)
7120 aftr_ip4 = '192.0.0.1'
7121 aftr_ip4_n = socket.inet_pton(socket.AF_INET, aftr_ip4)
7122 aftr_ip6 = '2001:db8:85a3::8a2e:370:1'
7123 aftr_ip6_n = socket.inet_pton(socket.AF_INET6, aftr_ip6)
7124 self.vapi.dslite_set_aftr_addr(aftr_ip6_n, aftr_ip4_n)
7125
7126 # UDP
7127 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
7128 IPv6(dst=aftr_ip6, src=self.pg1.remote_hosts[0].ip6) /
7129 IP(dst=self.pg0.remote_ip4, src='192.168.1.1') /
7130 UDP(sport=20000, dport=10000))
7131 self.pg1.add_stream(p)
7132 self.pg_enable_capture(self.pg_interfaces)
7133 self.pg_start()
7134 capture = self.pg0.get_capture(1)
7135 capture = capture[0]
7136 self.assertFalse(capture.haslayer(IPv6))
7137 self.assertEqual(capture[IP].src, self.nat_addr)
7138 self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
7139 self.assertNotEqual(capture[UDP].sport, 20000)
7140 self.assertEqual(capture[UDP].dport, 10000)
Klement Sekerad81ae412018-05-16 10:52:54 +02007141 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08007142 out_port = capture[UDP].sport
7143
7144 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7145 IP(dst=self.nat_addr, src=self.pg0.remote_ip4) /
7146 UDP(sport=10000, dport=out_port))
7147 self.pg0.add_stream(p)
7148 self.pg_enable_capture(self.pg_interfaces)
7149 self.pg_start()
7150 capture = self.pg1.get_capture(1)
7151 capture = capture[0]
7152 self.assertEqual(capture[IPv6].src, aftr_ip6)
7153 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[0].ip6)
7154 self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
7155 self.assertEqual(capture[IP].dst, '192.168.1.1')
7156 self.assertEqual(capture[UDP].sport, 10000)
7157 self.assertEqual(capture[UDP].dport, 20000)
Klement Sekerad81ae412018-05-16 10:52:54 +02007158 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08007159
7160 # TCP
7161 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
7162 IPv6(dst=aftr_ip6, src=self.pg1.remote_hosts[1].ip6) /
7163 IP(dst=self.pg0.remote_ip4, src='192.168.1.1') /
7164 TCP(sport=20001, dport=10001))
7165 self.pg1.add_stream(p)
7166 self.pg_enable_capture(self.pg_interfaces)
7167 self.pg_start()
7168 capture = self.pg0.get_capture(1)
7169 capture = capture[0]
7170 self.assertFalse(capture.haslayer(IPv6))
7171 self.assertEqual(capture[IP].src, self.nat_addr)
7172 self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
7173 self.assertNotEqual(capture[TCP].sport, 20001)
7174 self.assertEqual(capture[TCP].dport, 10001)
Klement Sekerad81ae412018-05-16 10:52:54 +02007175 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08007176 out_port = capture[TCP].sport
7177
7178 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7179 IP(dst=self.nat_addr, src=self.pg0.remote_ip4) /
7180 TCP(sport=10001, dport=out_port))
7181 self.pg0.add_stream(p)
7182 self.pg_enable_capture(self.pg_interfaces)
7183 self.pg_start()
7184 capture = self.pg1.get_capture(1)
7185 capture = capture[0]
7186 self.assertEqual(capture[IPv6].src, aftr_ip6)
7187 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[1].ip6)
7188 self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
7189 self.assertEqual(capture[IP].dst, '192.168.1.1')
7190 self.assertEqual(capture[TCP].sport, 10001)
7191 self.assertEqual(capture[TCP].dport, 20001)
Klement Sekerad81ae412018-05-16 10:52:54 +02007192 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08007193
7194 # ICMP
7195 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
7196 IPv6(dst=aftr_ip6, src=self.pg1.remote_hosts[1].ip6) /
7197 IP(dst=self.pg0.remote_ip4, src='192.168.1.1') /
7198 ICMP(id=4000, type='echo-request'))
7199 self.pg1.add_stream(p)
7200 self.pg_enable_capture(self.pg_interfaces)
7201 self.pg_start()
7202 capture = self.pg0.get_capture(1)
7203 capture = capture[0]
7204 self.assertFalse(capture.haslayer(IPv6))
7205 self.assertEqual(capture[IP].src, self.nat_addr)
7206 self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
7207 self.assertNotEqual(capture[ICMP].id, 4000)
Klement Sekerad81ae412018-05-16 10:52:54 +02007208 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08007209 out_id = capture[ICMP].id
7210
7211 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7212 IP(dst=self.nat_addr, src=self.pg0.remote_ip4) /
7213 ICMP(id=out_id, type='echo-reply'))
7214 self.pg0.add_stream(p)
7215 self.pg_enable_capture(self.pg_interfaces)
7216 self.pg_start()
7217 capture = self.pg1.get_capture(1)
7218 capture = capture[0]
7219 self.assertEqual(capture[IPv6].src, aftr_ip6)
7220 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[1].ip6)
7221 self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
7222 self.assertEqual(capture[IP].dst, '192.168.1.1')
7223 self.assertEqual(capture[ICMP].id, 4000)
Klement Sekerad81ae412018-05-16 10:52:54 +02007224 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08007225
Matus Fabian331acc62017-12-08 03:38:51 -08007226 # ping DS-Lite AFTR tunnel endpoint address
7227 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
7228 IPv6(src=self.pg1.remote_hosts[1].ip6, dst=aftr_ip6) /
7229 ICMPv6EchoRequest())
7230 self.pg1.add_stream(p)
7231 self.pg_enable_capture(self.pg_interfaces)
7232 self.pg_start()
7233 capture = self.pg1.get_capture(1)
7234 self.assertEqual(1, len(capture))
7235 capture = capture[0]
7236 self.assertEqual(capture[IPv6].src, aftr_ip6)
7237 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[1].ip6)
7238 self.assertTrue(capture.haslayer(ICMPv6EchoReply))
7239
Matus Fabian8ebe6252017-11-06 05:04:53 -08007240 def tearDown(self):
7241 super(TestDSlite, self).tearDown()
7242 if not self.vpp_dead:
7243 self.logger.info(self.vapi.cli("show dslite pool"))
7244 self.logger.info(
7245 self.vapi.cli("show dslite aftr-tunnel-endpoint-address"))
7246 self.logger.info(self.vapi.cli("show dslite sessions"))
7247
Juraj Slobodac5c6a332018-01-09 16:08:32 +01007248
7249class TestDSliteCE(MethodHolder):
7250 """ DS-Lite CE Test Cases """
7251
7252 @classmethod
7253 def setUpConstants(cls):
7254 super(TestDSliteCE, cls).setUpConstants()
7255 cls.vpp_cmdline.extend(["nat", "{", "dslite ce", "}"])
7256
7257 @classmethod
7258 def setUpClass(cls):
7259 super(TestDSliteCE, cls).setUpClass()
7260
7261 try:
7262 cls.create_pg_interfaces(range(2))
7263 cls.pg0.admin_up()
7264 cls.pg0.config_ip4()
7265 cls.pg0.resolve_arp()
7266 cls.pg1.admin_up()
7267 cls.pg1.config_ip6()
7268 cls.pg1.generate_remote_hosts(1)
7269 cls.pg1.configure_ipv6_neighbors()
7270
7271 except Exception:
7272 super(TestDSliteCE, cls).tearDownClass()
7273 raise
7274
7275 def test_dslite_ce(self):
7276 """ Test DS-Lite CE """
7277
Matus Fabian69ce30d2018-08-22 01:27:10 -07007278 nat_config = self.vapi.nat_show_config()
7279 self.assertEqual(1, nat_config.dslite_ce)
7280
Juraj Slobodac5c6a332018-01-09 16:08:32 +01007281 b4_ip4 = '192.0.0.2'
7282 b4_ip4_n = socket.inet_pton(socket.AF_INET, b4_ip4)
7283 b4_ip6 = '2001:db8:62aa::375e:f4c1:1'
7284 b4_ip6_n = socket.inet_pton(socket.AF_INET6, b4_ip6)
7285 self.vapi.dslite_set_b4_addr(b4_ip6_n, b4_ip4_n)
7286
7287 aftr_ip4 = '192.0.0.1'
7288 aftr_ip4_n = socket.inet_pton(socket.AF_INET, aftr_ip4)
7289 aftr_ip6 = '2001:db8:85a3::8a2e:370:1'
7290 aftr_ip6_n = socket.inet_pton(socket.AF_INET6, aftr_ip6)
7291 self.vapi.dslite_set_aftr_addr(aftr_ip6_n, aftr_ip4_n)
7292
7293 self.vapi.ip_add_del_route(dst_address=aftr_ip6_n,
7294 dst_address_length=128,
7295 next_hop_address=self.pg1.remote_ip6n,
7296 next_hop_sw_if_index=self.pg1.sw_if_index,
7297 is_ipv6=1)
7298
7299 # UDP encapsulation
7300 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7301 IP(dst=self.pg1.remote_ip4, src=self.pg0.remote_ip4) /
7302 UDP(sport=10000, dport=20000))
7303 self.pg0.add_stream(p)
7304 self.pg_enable_capture(self.pg_interfaces)
7305 self.pg_start()
7306 capture = self.pg1.get_capture(1)
7307 capture = capture[0]
7308 self.assertEqual(capture[IPv6].src, b4_ip6)
7309 self.assertEqual(capture[IPv6].dst, aftr_ip6)
7310 self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
7311 self.assertEqual(capture[IP].dst, self.pg1.remote_ip4)
7312 self.assertEqual(capture[UDP].sport, 10000)
7313 self.assertEqual(capture[UDP].dport, 20000)
Klement Sekerad81ae412018-05-16 10:52:54 +02007314 self.assert_packet_checksums_valid(capture)
Juraj Slobodac5c6a332018-01-09 16:08:32 +01007315
7316 # UDP decapsulation
7317 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
7318 IPv6(dst=b4_ip6, src=aftr_ip6) /
7319 IP(dst=self.pg0.remote_ip4, src=self.pg1.remote_ip4) /
7320 UDP(sport=20000, dport=10000))
7321 self.pg1.add_stream(p)
7322 self.pg_enable_capture(self.pg_interfaces)
7323 self.pg_start()
7324 capture = self.pg0.get_capture(1)
7325 capture = capture[0]
7326 self.assertFalse(capture.haslayer(IPv6))
7327 self.assertEqual(capture[IP].src, self.pg1.remote_ip4)
7328 self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
7329 self.assertEqual(capture[UDP].sport, 20000)
7330 self.assertEqual(capture[UDP].dport, 10000)
Klement Sekerad81ae412018-05-16 10:52:54 +02007331 self.assert_packet_checksums_valid(capture)
Juraj Slobodac5c6a332018-01-09 16:08:32 +01007332
7333 # ping DS-Lite B4 tunnel endpoint address
7334 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
7335 IPv6(src=self.pg1.remote_hosts[0].ip6, dst=b4_ip6) /
7336 ICMPv6EchoRequest())
7337 self.pg1.add_stream(p)
7338 self.pg_enable_capture(self.pg_interfaces)
7339 self.pg_start()
7340 capture = self.pg1.get_capture(1)
7341 self.assertEqual(1, len(capture))
7342 capture = capture[0]
7343 self.assertEqual(capture[IPv6].src, b4_ip6)
7344 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[0].ip6)
7345 self.assertTrue(capture.haslayer(ICMPv6EchoReply))
7346
7347 def tearDown(self):
7348 super(TestDSliteCE, self).tearDown()
7349 if not self.vpp_dead:
7350 self.logger.info(
7351 self.vapi.cli("show dslite aftr-tunnel-endpoint-address"))
7352 self.logger.info(
7353 self.vapi.cli("show dslite b4-tunnel-endpoint-address"))
7354
Matus Fabianf2a23cc2018-01-22 03:41:53 -08007355
7356class TestNAT66(MethodHolder):
7357 """ NAT66 Test Cases """
7358
7359 @classmethod
7360 def setUpClass(cls):
7361 super(TestNAT66, cls).setUpClass()
7362
7363 try:
7364 cls.nat_addr = 'fd01:ff::2'
7365 cls.nat_addr_n = socket.inet_pton(socket.AF_INET6, cls.nat_addr)
7366
7367 cls.create_pg_interfaces(range(2))
7368 cls.interfaces = list(cls.pg_interfaces)
7369
7370 for i in cls.interfaces:
7371 i.admin_up()
7372 i.config_ip6()
7373 i.configure_ipv6_neighbors()
7374
7375 except Exception:
7376 super(TestNAT66, cls).tearDownClass()
7377 raise
7378
7379 def test_static(self):
7380 """ 1:1 NAT66 test """
7381 self.vapi.nat66_add_del_interface(self.pg0.sw_if_index)
7382 self.vapi.nat66_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7383 self.vapi.nat66_add_del_static_mapping(self.pg0.remote_ip6n,
7384 self.nat_addr_n)
7385
7386 # in2out
7387 pkts = []
7388 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7389 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
7390 TCP())
7391 pkts.append(p)
7392 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7393 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
7394 UDP())
7395 pkts.append(p)
7396 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7397 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
7398 ICMPv6EchoRequest())
7399 pkts.append(p)
7400 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7401 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
7402 GRE() / IP() / TCP())
7403 pkts.append(p)
7404 self.pg0.add_stream(pkts)
7405 self.pg_enable_capture(self.pg_interfaces)
7406 self.pg_start()
7407 capture = self.pg1.get_capture(len(pkts))
7408 for packet in capture:
7409 try:
7410 self.assertEqual(packet[IPv6].src, self.nat_addr)
7411 self.assertEqual(packet[IPv6].dst, self.pg1.remote_ip6)
Klement Sekerad81ae412018-05-16 10:52:54 +02007412 self.assert_packet_checksums_valid(packet)
Matus Fabianf2a23cc2018-01-22 03:41:53 -08007413 except:
7414 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7415 raise
7416
7417 # out2in
7418 pkts = []
7419 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
7420 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
7421 TCP())
7422 pkts.append(p)
7423 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
7424 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
7425 UDP())
7426 pkts.append(p)
7427 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
7428 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
7429 ICMPv6EchoReply())
7430 pkts.append(p)
7431 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
7432 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
7433 GRE() / IP() / TCP())
7434 pkts.append(p)
7435 self.pg1.add_stream(pkts)
7436 self.pg_enable_capture(self.pg_interfaces)
7437 self.pg_start()
7438 capture = self.pg0.get_capture(len(pkts))
7439 for packet in capture:
7440 try:
7441 self.assertEqual(packet[IPv6].src, self.pg1.remote_ip6)
7442 self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
Klement Sekerad81ae412018-05-16 10:52:54 +02007443 self.assert_packet_checksums_valid(packet)
Matus Fabianf2a23cc2018-01-22 03:41:53 -08007444 except:
7445 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7446 raise
7447
7448 sm = self.vapi.nat66_static_mapping_dump()
7449 self.assertEqual(len(sm), 1)
7450 self.assertEqual(sm[0].total_pkts, 8)
7451
Juraj Sloboda9341e342018-04-13 12:00:46 +02007452 def test_check_no_translate(self):
7453 """ NAT66 translate only when egress interface is outside interface """
7454 self.vapi.nat66_add_del_interface(self.pg0.sw_if_index)
7455 self.vapi.nat66_add_del_interface(self.pg1.sw_if_index)
7456 self.vapi.nat66_add_del_static_mapping(self.pg0.remote_ip6n,
7457 self.nat_addr_n)
7458
7459 # in2out
7460 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7461 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
7462 UDP())
7463 self.pg0.add_stream([p])
7464 self.pg_enable_capture(self.pg_interfaces)
7465 self.pg_start()
7466 capture = self.pg1.get_capture(1)
7467 packet = capture[0]
7468 try:
7469 self.assertEqual(packet[IPv6].src, self.pg0.remote_ip6)
7470 self.assertEqual(packet[IPv6].dst, self.pg1.remote_ip6)
7471 except:
7472 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7473 raise
7474
Matus Fabianf2a23cc2018-01-22 03:41:53 -08007475 def clear_nat66(self):
7476 """
7477 Clear NAT66 configuration.
7478 """
7479 interfaces = self.vapi.nat66_interface_dump()
7480 for intf in interfaces:
7481 self.vapi.nat66_add_del_interface(intf.sw_if_index,
7482 intf.is_inside,
7483 is_add=0)
7484
7485 static_mappings = self.vapi.nat66_static_mapping_dump()
7486 for sm in static_mappings:
7487 self.vapi.nat66_add_del_static_mapping(sm.local_ip_address,
7488 sm.external_ip_address,
7489 sm.vrf_id,
7490 is_add=0)
7491
7492 def tearDown(self):
7493 super(TestNAT66, self).tearDown()
7494 if not self.vpp_dead:
7495 self.logger.info(self.vapi.cli("show nat66 interfaces"))
7496 self.logger.info(self.vapi.cli("show nat66 static mappings"))
7497 self.clear_nat66()
7498
Klement Sekerad81ae412018-05-16 10:52:54 +02007499
Matus Fabiande886752016-12-07 03:38:19 -08007500if __name__ == '__main__':
7501 unittest.main(testRunner=VppTestRunner)