blob: 73e414ad1aed13c15159a368b59183190a1f5a6b [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
Matus Fabianea5b5be2018-09-03 05:02:23 -07003744 def test_lb_affinity(self):
3745 """ NAT44 local service load balancing affinity """
3746 external_addr_n = socket.inet_pton(socket.AF_INET, self.nat_addr)
3747 external_port = 80
3748 local_port = 8080
3749 server1 = self.pg0.remote_hosts[0]
3750 server2 = self.pg0.remote_hosts[1]
3751
3752 locals = [{'addr': server1.ip4n,
3753 'port': local_port,
3754 'probability': 50,
3755 'vrf_id': 0},
3756 {'addr': server2.ip4n,
3757 'port': local_port,
3758 'probability': 50,
3759 'vrf_id': 0}]
3760
3761 self.nat44_add_address(self.nat_addr)
3762 self.vapi.nat44_add_del_lb_static_mapping(external_addr_n,
3763 external_port,
3764 IP_PROTOS.tcp,
3765 affinity=10800,
3766 local_num=len(locals),
3767 locals=locals)
3768 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3769 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3770 is_inside=0)
3771
3772 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
3773 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3774 TCP(sport=1025, dport=external_port))
3775 self.pg1.add_stream(p)
3776 self.pg_enable_capture(self.pg_interfaces)
3777 self.pg_start()
3778 capture = self.pg0.get_capture(1)
3779 backend = capture[0][IP].dst
3780
3781 sessions = self.vapi.nat44_user_session_dump(
3782 socket.inet_pton(socket.AF_INET, backend), 0)
3783 self.assertEqual(len(sessions), 1)
3784 self.assertTrue(sessions[0].ext_host_valid)
3785 self.vapi.nat44_del_session(
3786 sessions[0].inside_ip_address,
3787 sessions[0].inside_port,
3788 sessions[0].protocol,
3789 ext_host_address=sessions[0].ext_host_address,
3790 ext_host_port=sessions[0].ext_host_port)
3791
3792 pkts = []
3793 for port in range(1030, 1100):
3794 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
3795 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3796 TCP(sport=port, dport=external_port))
3797 pkts.append(p)
3798 self.pg1.add_stream(pkts)
3799 self.pg_enable_capture(self.pg_interfaces)
3800 self.pg_start()
3801 capture = self.pg0.get_capture(len(pkts))
3802 for p in capture:
3803 self.assertEqual(p[IP].dst, backend)
3804
Matus Fabiana6110b62018-06-13 05:39:07 -07003805 def test_unknown_proto(self):
3806 """ NAT44 translate packet with unknown protocol """
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 # in2out
3813 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3814 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3815 TCP(sport=self.tcp_port_in, dport=20))
3816 self.pg0.add_stream(p)
3817 self.pg_enable_capture(self.pg_interfaces)
3818 self.pg_start()
3819 p = self.pg1.get_capture(1)
3820
3821 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3822 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3823 GRE() /
3824 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
3825 TCP(sport=1234, dport=1234))
3826 self.pg0.add_stream(p)
3827 self.pg_enable_capture(self.pg_interfaces)
3828 self.pg_start()
3829 p = self.pg1.get_capture(1)
3830 packet = p[0]
3831 try:
3832 self.assertEqual(packet[IP].src, self.nat_addr)
3833 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
3834 self.assertTrue(packet.haslayer(GRE))
3835 self.assert_packet_checksums_valid(packet)
3836 except:
3837 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3838 raise
3839
3840 # out2in
3841 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
3842 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3843 GRE() /
3844 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
3845 TCP(sport=1234, dport=1234))
3846 self.pg1.add_stream(p)
3847 self.pg_enable_capture(self.pg_interfaces)
3848 self.pg_start()
3849 p = self.pg0.get_capture(1)
3850 packet = p[0]
3851 try:
3852 self.assertEqual(packet[IP].src, self.pg1.remote_ip4)
3853 self.assertEqual(packet[IP].dst, self.pg0.remote_ip4)
3854 self.assertTrue(packet.haslayer(GRE))
3855 self.assert_packet_checksums_valid(packet)
3856 except:
3857 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3858 raise
3859
3860 def test_hairpinning_unknown_proto(self):
3861 """ NAT44 translate packet with unknown protocol - hairpinning """
3862 host = self.pg0.remote_hosts[0]
3863 server = self.pg0.remote_hosts[1]
3864 host_in_port = 1234
3865 server_out_port = 8765
3866 server_nat_ip = "10.0.0.11"
3867
3868 self.nat44_add_address(self.nat_addr)
3869 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3870 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3871 is_inside=0)
3872
3873 # add static mapping for server
3874 self.nat44_add_static_mapping(server.ip4, server_nat_ip)
3875
3876 # host to server
3877 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
3878 IP(src=host.ip4, dst=server_nat_ip) /
3879 TCP(sport=host_in_port, dport=server_out_port))
3880 self.pg0.add_stream(p)
3881 self.pg_enable_capture(self.pg_interfaces)
3882 self.pg_start()
3883 self.pg0.get_capture(1)
3884
3885 p = (Ether(dst=self.pg0.local_mac, src=host.mac) /
3886 IP(src=host.ip4, dst=server_nat_ip) /
3887 GRE() /
3888 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
3889 TCP(sport=1234, dport=1234))
3890 self.pg0.add_stream(p)
3891 self.pg_enable_capture(self.pg_interfaces)
3892 self.pg_start()
3893 p = self.pg0.get_capture(1)
3894 packet = p[0]
3895 try:
3896 self.assertEqual(packet[IP].src, self.nat_addr)
3897 self.assertEqual(packet[IP].dst, server.ip4)
3898 self.assertTrue(packet.haslayer(GRE))
3899 self.assert_packet_checksums_valid(packet)
3900 except:
3901 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3902 raise
3903
3904 # server to host
3905 p = (Ether(dst=self.pg0.local_mac, src=server.mac) /
3906 IP(src=server.ip4, dst=self.nat_addr) /
3907 GRE() /
3908 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
3909 TCP(sport=1234, dport=1234))
3910 self.pg0.add_stream(p)
3911 self.pg_enable_capture(self.pg_interfaces)
3912 self.pg_start()
3913 p = self.pg0.get_capture(1)
3914 packet = p[0]
3915 try:
3916 self.assertEqual(packet[IP].src, server_nat_ip)
3917 self.assertEqual(packet[IP].dst, host.ip4)
3918 self.assertTrue(packet.haslayer(GRE))
3919 self.assert_packet_checksums_valid(packet)
3920 except:
3921 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3922 raise
3923
3924 def test_output_feature_and_service(self):
3925 """ NAT44 interface output feature and services """
3926 external_addr = '1.2.3.4'
3927 external_port = 80
3928 local_port = 8080
3929
3930 self.vapi.nat44_forwarding_enable_disable(1)
3931 self.nat44_add_address(self.nat_addr)
3932 self.vapi.nat44_add_del_identity_mapping(ip=self.pg1.remote_ip4n)
3933 self.nat44_add_static_mapping(self.pg0.remote_ip4, external_addr,
3934 local_port, external_port,
3935 proto=IP_PROTOS.tcp, out2in_only=1)
3936 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3937 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
3938 is_inside=0)
3939 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
3940 is_inside=0)
3941
3942 # from client to service
3943 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3944 IP(src=self.pg1.remote_ip4, dst=external_addr) /
3945 TCP(sport=12345, dport=external_port))
3946 self.pg1.add_stream(p)
3947 self.pg_enable_capture(self.pg_interfaces)
3948 self.pg_start()
3949 capture = self.pg0.get_capture(1)
3950 p = capture[0]
3951 try:
3952 ip = p[IP]
3953 tcp = p[TCP]
3954 self.assertEqual(ip.dst, self.pg0.remote_ip4)
3955 self.assertEqual(tcp.dport, local_port)
3956 self.assert_packet_checksums_valid(p)
3957 except:
3958 self.logger.error(ppp("Unexpected or invalid packet:", p))
3959 raise
3960
3961 # from service back to client
3962 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3963 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3964 TCP(sport=local_port, dport=12345))
3965 self.pg0.add_stream(p)
3966 self.pg_enable_capture(self.pg_interfaces)
3967 self.pg_start()
3968 capture = self.pg1.get_capture(1)
3969 p = capture[0]
3970 try:
3971 ip = p[IP]
3972 tcp = p[TCP]
3973 self.assertEqual(ip.src, external_addr)
3974 self.assertEqual(tcp.sport, external_port)
3975 self.assert_packet_checksums_valid(p)
3976 except:
3977 self.logger.error(ppp("Unexpected or invalid packet:", p))
3978 raise
3979
3980 # from local network host to external network
3981 pkts = self.create_stream_in(self.pg0, self.pg1)
3982 self.pg0.add_stream(pkts)
3983 self.pg_enable_capture(self.pg_interfaces)
3984 self.pg_start()
3985 capture = self.pg1.get_capture(len(pkts))
3986 self.verify_capture_out(capture)
3987 pkts = self.create_stream_in(self.pg0, self.pg1)
3988 self.pg0.add_stream(pkts)
3989 self.pg_enable_capture(self.pg_interfaces)
3990 self.pg_start()
3991 capture = self.pg1.get_capture(len(pkts))
3992 self.verify_capture_out(capture)
3993
3994 # from external network back to local network host
3995 pkts = self.create_stream_out(self.pg1)
3996 self.pg1.add_stream(pkts)
3997 self.pg_enable_capture(self.pg_interfaces)
3998 self.pg_start()
3999 capture = self.pg0.get_capture(len(pkts))
4000 self.verify_capture_in(capture, self.pg0)
4001
4002 def test_output_feature_and_service2(self):
4003 """ NAT44 interface output feature and service host direct access """
4004 self.vapi.nat44_forwarding_enable_disable(1)
4005 self.nat44_add_address(self.nat_addr)
4006 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
4007 is_inside=0)
4008
4009 # session initiaded from service host - translate
4010 pkts = self.create_stream_in(self.pg0, self.pg1)
4011 self.pg0.add_stream(pkts)
4012 self.pg_enable_capture(self.pg_interfaces)
4013 self.pg_start()
4014 capture = self.pg1.get_capture(len(pkts))
4015 self.verify_capture_out(capture)
4016
4017 pkts = self.create_stream_out(self.pg1)
4018 self.pg1.add_stream(pkts)
4019 self.pg_enable_capture(self.pg_interfaces)
4020 self.pg_start()
4021 capture = self.pg0.get_capture(len(pkts))
4022 self.verify_capture_in(capture, self.pg0)
4023
4024 # session initiaded from remote host - do not translate
4025 self.tcp_port_in = 60303
4026 self.udp_port_in = 60304
4027 self.icmp_id_in = 60305
4028 pkts = self.create_stream_out(self.pg1,
4029 self.pg0.remote_ip4,
4030 use_inside_ports=True)
4031 self.pg1.add_stream(pkts)
4032 self.pg_enable_capture(self.pg_interfaces)
4033 self.pg_start()
4034 capture = self.pg0.get_capture(len(pkts))
4035 self.verify_capture_in(capture, self.pg0)
4036
4037 pkts = self.create_stream_in(self.pg0, self.pg1)
4038 self.pg0.add_stream(pkts)
4039 self.pg_enable_capture(self.pg_interfaces)
4040 self.pg_start()
4041 capture = self.pg1.get_capture(len(pkts))
4042 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
4043 same_port=True)
4044
4045 def test_output_feature_and_service3(self):
4046 """ NAT44 interface output feature and DST NAT """
4047 external_addr = '1.2.3.4'
4048 external_port = 80
4049 local_port = 8080
4050
4051 self.vapi.nat44_forwarding_enable_disable(1)
4052 self.nat44_add_address(self.nat_addr)
4053 self.nat44_add_static_mapping(self.pg1.remote_ip4, external_addr,
4054 local_port, external_port,
4055 proto=IP_PROTOS.tcp, out2in_only=1)
4056 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4057 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
4058 is_inside=0)
4059 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
4060 is_inside=0)
4061
4062 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4063 IP(src=self.pg0.remote_ip4, dst=external_addr) /
4064 TCP(sport=12345, dport=external_port))
4065 self.pg0.add_stream(p)
4066 self.pg_enable_capture(self.pg_interfaces)
4067 self.pg_start()
4068 capture = self.pg1.get_capture(1)
4069 p = capture[0]
4070 try:
4071 ip = p[IP]
4072 tcp = p[TCP]
4073 self.assertEqual(ip.src, self.pg0.remote_ip4)
4074 self.assertEqual(tcp.sport, 12345)
4075 self.assertEqual(ip.dst, self.pg1.remote_ip4)
4076 self.assertEqual(tcp.dport, local_port)
4077 self.assert_packet_checksums_valid(p)
4078 except:
4079 self.logger.error(ppp("Unexpected or invalid packet:", p))
4080 raise
4081
4082 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4083 IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
4084 TCP(sport=local_port, dport=12345))
4085 self.pg1.add_stream(p)
4086 self.pg_enable_capture(self.pg_interfaces)
4087 self.pg_start()
4088 capture = self.pg0.get_capture(1)
4089 p = capture[0]
4090 try:
4091 ip = p[IP]
4092 tcp = p[TCP]
4093 self.assertEqual(ip.src, external_addr)
4094 self.assertEqual(tcp.sport, external_port)
4095 self.assertEqual(ip.dst, self.pg0.remote_ip4)
4096 self.assertEqual(tcp.dport, 12345)
4097 self.assert_packet_checksums_valid(p)
4098 except:
4099 self.logger.error(ppp("Unexpected or invalid packet:", p))
4100 raise
4101
Matus Fabian182e37e2018-08-14 04:21:26 -07004102 def test_next_src_nat(self):
4103 """ On way back forward packet to nat44-in2out node. """
4104 twice_nat_addr = '10.0.1.3'
4105 external_port = 80
4106 local_port = 8080
4107 post_twice_nat_port = 0
4108
4109 self.vapi.nat44_forwarding_enable_disable(1)
4110 self.nat44_add_address(twice_nat_addr, twice_nat=1)
4111 self.nat44_add_static_mapping(self.pg6.remote_ip4, self.pg1.remote_ip4,
4112 local_port, external_port,
4113 proto=IP_PROTOS.tcp, out2in_only=1,
4114 self_twice_nat=1, vrf_id=1)
4115 self.vapi.nat44_interface_add_del_feature(self.pg6.sw_if_index,
4116 is_inside=0)
4117
4118 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
4119 IP(src=self.pg6.remote_ip4, dst=self.pg1.remote_ip4) /
4120 TCP(sport=12345, dport=external_port))
4121 self.pg6.add_stream(p)
4122 self.pg_enable_capture(self.pg_interfaces)
4123 self.pg_start()
4124 capture = self.pg6.get_capture(1)
4125 p = capture[0]
4126 try:
4127 ip = p[IP]
4128 tcp = p[TCP]
4129 self.assertEqual(ip.src, twice_nat_addr)
4130 self.assertNotEqual(tcp.sport, 12345)
4131 post_twice_nat_port = tcp.sport
4132 self.assertEqual(ip.dst, self.pg6.remote_ip4)
4133 self.assertEqual(tcp.dport, local_port)
4134 self.assert_packet_checksums_valid(p)
4135 except:
4136 self.logger.error(ppp("Unexpected or invalid packet:", p))
4137 raise
4138
4139 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
4140 IP(src=self.pg6.remote_ip4, dst=twice_nat_addr) /
4141 TCP(sport=local_port, dport=post_twice_nat_port))
4142 self.pg6.add_stream(p)
4143 self.pg_enable_capture(self.pg_interfaces)
4144 self.pg_start()
4145 capture = self.pg6.get_capture(1)
4146 p = capture[0]
4147 try:
4148 ip = p[IP]
4149 tcp = p[TCP]
4150 self.assertEqual(ip.src, self.pg1.remote_ip4)
4151 self.assertEqual(tcp.sport, external_port)
4152 self.assertEqual(ip.dst, self.pg6.remote_ip4)
4153 self.assertEqual(tcp.dport, 12345)
4154 self.assert_packet_checksums_valid(p)
4155 except:
4156 self.logger.error(ppp("Unexpected or invalid packet:", p))
4157 raise
4158
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004159 def twice_nat_common(self, self_twice_nat=False, same_pg=False, lb=False,
4160 client_id=None):
Matus Fabianb932d262017-12-18 05:38:24 -08004161 twice_nat_addr = '10.0.1.3'
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004162
Matus Fabianb932d262017-12-18 05:38:24 -08004163 port_in = 8080
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004164 if lb:
4165 if not same_pg:
4166 port_in1 = port_in
4167 port_in2 = port_in
4168 else:
4169 port_in1 = port_in+1
4170 port_in2 = port_in+2
4171
Matus Fabianb932d262017-12-18 05:38:24 -08004172 port_out = 80
4173 eh_port_out = 4567
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004174
4175 server1 = self.pg0.remote_hosts[0]
4176 server2 = self.pg0.remote_hosts[1]
4177 if lb and same_pg:
4178 server2 = server1
4179 if not lb:
4180 server = server1
4181
4182 pg0 = self.pg0
4183 if same_pg:
4184 pg1 = self.pg0
4185 else:
4186 pg1 = self.pg1
4187
4188 eh_translate = ((not self_twice_nat) or (not lb and same_pg) or
4189 client_id == 1)
4190
Matus Fabianb932d262017-12-18 05:38:24 -08004191 self.nat44_add_address(self.nat_addr)
4192 self.nat44_add_address(twice_nat_addr, twice_nat=1)
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004193 if not lb:
4194 self.nat44_add_static_mapping(pg0.remote_ip4, self.nat_addr,
4195 port_in, port_out,
4196 proto=IP_PROTOS.tcp,
4197 twice_nat=int(not self_twice_nat),
4198 self_twice_nat=int(self_twice_nat))
4199 else:
4200 locals = [{'addr': server1.ip4n,
4201 'port': port_in1,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07004202 'probability': 50,
4203 'vrf_id': 0},
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004204 {'addr': server2.ip4n,
4205 'port': port_in2,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07004206 'probability': 50,
4207 'vrf_id': 0}]
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004208 out_addr_n = socket.inet_pton(socket.AF_INET, self.nat_addr)
4209 self.vapi.nat44_add_del_lb_static_mapping(out_addr_n,
4210 port_out,
4211 IP_PROTOS.tcp,
4212 twice_nat=int(
4213 not self_twice_nat),
4214 self_twice_nat=int(
4215 self_twice_nat),
4216 local_num=len(locals),
4217 locals=locals)
4218 self.vapi.nat44_interface_add_del_feature(pg0.sw_if_index)
4219 self.vapi.nat44_interface_add_del_feature(pg1.sw_if_index,
Matus Fabianb932d262017-12-18 05:38:24 -08004220 is_inside=0)
4221
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004222 if same_pg:
4223 if not lb:
4224 client = server
4225 else:
4226 assert client_id is not None
4227 if client_id == 1:
4228 client = self.pg0.remote_hosts[0]
4229 elif client_id == 2:
4230 client = self.pg0.remote_hosts[1]
4231 else:
4232 client = pg1.remote_hosts[0]
4233 p = (Ether(src=pg1.remote_mac, dst=pg1.local_mac) /
4234 IP(src=client.ip4, dst=self.nat_addr) /
Matus Fabianb932d262017-12-18 05:38:24 -08004235 TCP(sport=eh_port_out, dport=port_out))
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004236 pg1.add_stream(p)
Matus Fabianb932d262017-12-18 05:38:24 -08004237 self.pg_enable_capture(self.pg_interfaces)
4238 self.pg_start()
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004239 capture = pg0.get_capture(1)
Matus Fabianb932d262017-12-18 05:38:24 -08004240 p = capture[0]
4241 try:
4242 ip = p[IP]
4243 tcp = p[TCP]
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004244 if lb:
4245 if ip.dst == server1.ip4:
4246 server = server1
4247 port_in = port_in1
4248 else:
4249 server = server2
4250 port_in = port_in2
4251 self.assertEqual(ip.dst, server.ip4)
4252 if lb and same_pg:
4253 self.assertIn(tcp.dport, [port_in1, port_in2])
4254 else:
4255 self.assertEqual(tcp.dport, port_in)
4256 if eh_translate:
4257 self.assertEqual(ip.src, twice_nat_addr)
4258 self.assertNotEqual(tcp.sport, eh_port_out)
4259 else:
4260 self.assertEqual(ip.src, client.ip4)
4261 self.assertEqual(tcp.sport, eh_port_out)
4262 eh_addr_in = ip.src
Matus Fabianb932d262017-12-18 05:38:24 -08004263 eh_port_in = tcp.sport
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004264 saved_port_in = tcp.dport
Klement Sekerad81ae412018-05-16 10:52:54 +02004265 self.assert_packet_checksums_valid(p)
Matus Fabianb932d262017-12-18 05:38:24 -08004266 except:
4267 self.logger.error(ppp("Unexpected or invalid packet:", p))
4268 raise
4269
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004270 p = (Ether(src=server.mac, dst=pg0.local_mac) /
4271 IP(src=server.ip4, dst=eh_addr_in) /
4272 TCP(sport=saved_port_in, dport=eh_port_in))
4273 pg0.add_stream(p)
Matus Fabianb932d262017-12-18 05:38:24 -08004274 self.pg_enable_capture(self.pg_interfaces)
4275 self.pg_start()
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004276 capture = pg1.get_capture(1)
Matus Fabianb932d262017-12-18 05:38:24 -08004277 p = capture[0]
4278 try:
4279 ip = p[IP]
4280 tcp = p[TCP]
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004281 self.assertEqual(ip.dst, client.ip4)
Matus Fabianb932d262017-12-18 05:38:24 -08004282 self.assertEqual(ip.src, self.nat_addr)
4283 self.assertEqual(tcp.dport, eh_port_out)
4284 self.assertEqual(tcp.sport, port_out)
Klement Sekerad81ae412018-05-16 10:52:54 +02004285 self.assert_packet_checksums_valid(p)
Matus Fabianb932d262017-12-18 05:38:24 -08004286 except:
4287 self.logger.error(ppp("Unexpected or invalid packet:", p))
4288 raise
4289
Matus Fabian70a26ac2018-05-14 06:20:28 -07004290 if eh_translate:
4291 sessions = self.vapi.nat44_user_session_dump(server.ip4n, 0)
4292 self.assertEqual(len(sessions), 1)
4293 self.assertTrue(sessions[0].ext_host_valid)
4294 self.assertTrue(sessions[0].is_twicenat)
4295 self.vapi.nat44_del_session(
4296 sessions[0].inside_ip_address,
4297 sessions[0].inside_port,
4298 sessions[0].protocol,
4299 ext_host_address=sessions[0].ext_host_nat_address,
4300 ext_host_port=sessions[0].ext_host_nat_port)
4301 sessions = self.vapi.nat44_user_session_dump(server.ip4n, 0)
4302 self.assertEqual(len(sessions), 0)
4303
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004304 def test_twice_nat(self):
4305 """ Twice NAT44 """
4306 self.twice_nat_common()
4307
4308 def test_self_twice_nat_positive(self):
4309 """ Self Twice NAT44 (positive test) """
4310 self.twice_nat_common(self_twice_nat=True, same_pg=True)
4311
4312 def test_self_twice_nat_negative(self):
4313 """ Self Twice NAT44 (negative test) """
4314 self.twice_nat_common(self_twice_nat=True)
4315
Matus Fabianb932d262017-12-18 05:38:24 -08004316 def test_twice_nat_lb(self):
4317 """ Twice NAT44 local service load balancing """
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004318 self.twice_nat_common(lb=True)
Matus Fabianb932d262017-12-18 05:38:24 -08004319
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004320 def test_self_twice_nat_lb_positive(self):
4321 """ Self Twice NAT44 local service load balancing (positive test) """
4322 self.twice_nat_common(lb=True, self_twice_nat=True, same_pg=True,
4323 client_id=1)
Matus Fabianb932d262017-12-18 05:38:24 -08004324
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004325 def test_self_twice_nat_lb_negative(self):
4326 """ Self Twice NAT44 local service load balancing (negative test) """
4327 self.twice_nat_common(lb=True, self_twice_nat=True, same_pg=True,
4328 client_id=2)
Matus Fabianb932d262017-12-18 05:38:24 -08004329
4330 def test_twice_nat_interface_addr(self):
4331 """ Acquire twice NAT44 addresses from interface """
Matus Fabiana6110b62018-06-13 05:39:07 -07004332 self.vapi.nat44_add_interface_addr(self.pg3.sw_if_index, twice_nat=1)
Matus Fabianb932d262017-12-18 05:38:24 -08004333
4334 # no address in NAT pool
4335 adresses = self.vapi.nat44_address_dump()
4336 self.assertEqual(0, len(adresses))
4337
4338 # configure interface address and check NAT address pool
Matus Fabiana6110b62018-06-13 05:39:07 -07004339 self.pg3.config_ip4()
Matus Fabianb932d262017-12-18 05:38:24 -08004340 adresses = self.vapi.nat44_address_dump()
4341 self.assertEqual(1, len(adresses))
Matus Fabiana6110b62018-06-13 05:39:07 -07004342 self.assertEqual(adresses[0].ip_address[0:4], self.pg3.local_ip4n)
Matus Fabianb932d262017-12-18 05:38:24 -08004343 self.assertEqual(adresses[0].twice_nat, 1)
4344
4345 # remove interface address and check NAT address pool
Matus Fabiana6110b62018-06-13 05:39:07 -07004346 self.pg3.unconfig_ip4()
Matus Fabianb932d262017-12-18 05:38:24 -08004347 adresses = self.vapi.nat44_address_dump()
4348 self.assertEqual(0, len(adresses))
4349
Matus Fabianebdf1902018-05-04 03:57:42 -07004350 def test_tcp_session_close_in(self):
4351 """ Close TCP session from inside network """
Matus Fabian229c1aa2018-05-28 04:09:52 -07004352 self.tcp_port_out = 10505
Matus Fabianebdf1902018-05-04 03:57:42 -07004353 self.nat44_add_address(self.nat_addr)
Matus Fabian229c1aa2018-05-28 04:09:52 -07004354 self.nat44_add_static_mapping(self.pg0.remote_ip4,
4355 self.nat_addr,
4356 self.tcp_port_in,
4357 self.tcp_port_out,
4358 proto=IP_PROTOS.tcp,
4359 twice_nat=1)
Matus Fabianebdf1902018-05-04 03:57:42 -07004360 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4361 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4362 is_inside=0)
4363
4364 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
4365 start_sessnum = len(sessions)
4366
4367 self.initiate_tcp_session(self.pg0, self.pg1)
4368
Matus Fabian229c1aa2018-05-28 04:09:52 -07004369 # FIN packet in -> out
4370 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4371 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4372 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
4373 flags="FA", seq=100, ack=300))
4374 self.pg0.add_stream(p)
4375 self.pg_enable_capture(self.pg_interfaces)
4376 self.pg_start()
4377 self.pg1.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07004378
Matus Fabian229c1aa2018-05-28 04:09:52 -07004379 pkts = []
Matus Fabianebdf1902018-05-04 03:57:42 -07004380
Matus Fabian229c1aa2018-05-28 04:09:52 -07004381 # ACK packet out -> in
4382 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4383 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4384 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
4385 flags="A", seq=300, ack=101))
4386 pkts.append(p)
Matus Fabianebdf1902018-05-04 03:57:42 -07004387
Matus Fabian229c1aa2018-05-28 04:09:52 -07004388 # FIN packet out -> in
4389 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4390 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4391 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
4392 flags="FA", seq=300, ack=101))
4393 pkts.append(p)
Matus Fabianebdf1902018-05-04 03:57:42 -07004394
Matus Fabian229c1aa2018-05-28 04:09:52 -07004395 self.pg1.add_stream(pkts)
4396 self.pg_enable_capture(self.pg_interfaces)
4397 self.pg_start()
4398 self.pg0.get_capture(2)
Matus Fabianebdf1902018-05-04 03:57:42 -07004399
Matus Fabian229c1aa2018-05-28 04:09:52 -07004400 # ACK packet in -> out
4401 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4402 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4403 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
4404 flags="A", seq=101, ack=301))
4405 self.pg0.add_stream(p)
4406 self.pg_enable_capture(self.pg_interfaces)
4407 self.pg_start()
4408 self.pg1.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07004409
Matus Fabian229c1aa2018-05-28 04:09:52 -07004410 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n,
4411 0)
4412 self.assertEqual(len(sessions) - start_sessnum, 0)
Matus Fabianebdf1902018-05-04 03:57:42 -07004413
4414 def test_tcp_session_close_out(self):
4415 """ Close TCP session from outside network """
Matus Fabian229c1aa2018-05-28 04:09:52 -07004416 self.tcp_port_out = 10505
Matus Fabianebdf1902018-05-04 03:57:42 -07004417 self.nat44_add_address(self.nat_addr)
Matus Fabian229c1aa2018-05-28 04:09:52 -07004418 self.nat44_add_static_mapping(self.pg0.remote_ip4,
4419 self.nat_addr,
4420 self.tcp_port_in,
4421 self.tcp_port_out,
4422 proto=IP_PROTOS.tcp,
4423 twice_nat=1)
Matus Fabianebdf1902018-05-04 03:57:42 -07004424 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4425 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4426 is_inside=0)
4427
4428 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
4429 start_sessnum = len(sessions)
4430
4431 self.initiate_tcp_session(self.pg0, self.pg1)
4432
Matus Fabian229c1aa2018-05-28 04:09:52 -07004433 # FIN packet out -> in
4434 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4435 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4436 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
4437 flags="FA", seq=100, ack=300))
4438 self.pg1.add_stream(p)
4439 self.pg_enable_capture(self.pg_interfaces)
4440 self.pg_start()
4441 self.pg0.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07004442
Matus Fabian229c1aa2018-05-28 04:09:52 -07004443 # FIN+ACK packet in -> out
4444 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4445 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4446 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
4447 flags="FA", seq=300, ack=101))
Matus Fabianebdf1902018-05-04 03:57:42 -07004448
Matus Fabian229c1aa2018-05-28 04:09:52 -07004449 self.pg0.add_stream(p)
4450 self.pg_enable_capture(self.pg_interfaces)
4451 self.pg_start()
4452 self.pg1.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07004453
Matus Fabian229c1aa2018-05-28 04:09:52 -07004454 # ACK packet out -> in
4455 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4456 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4457 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
4458 flags="A", seq=101, ack=301))
4459 self.pg1.add_stream(p)
4460 self.pg_enable_capture(self.pg_interfaces)
4461 self.pg_start()
4462 self.pg0.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07004463
Matus Fabian229c1aa2018-05-28 04:09:52 -07004464 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n,
4465 0)
4466 self.assertEqual(len(sessions) - start_sessnum, 0)
Matus Fabianebdf1902018-05-04 03:57:42 -07004467
4468 def test_tcp_session_close_simultaneous(self):
4469 """ Close TCP session from inside network """
Matus Fabian229c1aa2018-05-28 04:09:52 -07004470 self.tcp_port_out = 10505
Matus Fabianebdf1902018-05-04 03:57:42 -07004471 self.nat44_add_address(self.nat_addr)
Matus Fabian229c1aa2018-05-28 04:09:52 -07004472 self.nat44_add_static_mapping(self.pg0.remote_ip4,
4473 self.nat_addr,
4474 self.tcp_port_in,
4475 self.tcp_port_out,
4476 proto=IP_PROTOS.tcp,
4477 twice_nat=1)
Matus Fabianebdf1902018-05-04 03:57:42 -07004478 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4479 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4480 is_inside=0)
4481
4482 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
4483 start_sessnum = len(sessions)
4484
4485 self.initiate_tcp_session(self.pg0, self.pg1)
4486
Matus Fabian229c1aa2018-05-28 04:09:52 -07004487 # FIN packet in -> out
4488 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4489 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4490 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
4491 flags="FA", seq=100, ack=300))
4492 self.pg0.add_stream(p)
4493 self.pg_enable_capture(self.pg_interfaces)
4494 self.pg_start()
4495 self.pg1.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07004496
Matus Fabian229c1aa2018-05-28 04:09:52 -07004497 # FIN packet out -> in
4498 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4499 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4500 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
4501 flags="FA", seq=300, ack=100))
4502 self.pg1.add_stream(p)
4503 self.pg_enable_capture(self.pg_interfaces)
4504 self.pg_start()
4505 self.pg0.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07004506
Matus Fabian229c1aa2018-05-28 04:09:52 -07004507 # ACK packet in -> out
4508 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4509 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4510 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
4511 flags="A", seq=101, ack=301))
4512 self.pg0.add_stream(p)
4513 self.pg_enable_capture(self.pg_interfaces)
4514 self.pg_start()
4515 self.pg1.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07004516
Matus Fabian229c1aa2018-05-28 04:09:52 -07004517 # ACK packet out -> in
4518 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4519 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4520 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
4521 flags="A", seq=301, ack=101))
4522 self.pg1.add_stream(p)
4523 self.pg_enable_capture(self.pg_interfaces)
4524 self.pg_start()
4525 self.pg0.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07004526
Matus Fabian229c1aa2018-05-28 04:09:52 -07004527 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n,
4528 0)
4529 self.assertEqual(len(sessions) - start_sessnum, 0)
Matus Fabianebdf1902018-05-04 03:57:42 -07004530
Matus Fabiana6110b62018-06-13 05:39:07 -07004531 def test_one_armed_nat44_static(self):
4532 """ One armed NAT44 and 1:1 NAPT asymmetrical rule """
4533 remote_host = self.pg4.remote_hosts[0]
4534 local_host = self.pg4.remote_hosts[1]
4535 external_port = 80
4536 local_port = 8080
4537 eh_port_in = 0
4538
4539 self.vapi.nat44_forwarding_enable_disable(1)
4540 self.nat44_add_address(self.nat_addr, twice_nat=1)
4541 self.nat44_add_static_mapping(local_host.ip4, self.nat_addr,
4542 local_port, external_port,
4543 proto=IP_PROTOS.tcp, out2in_only=1,
4544 twice_nat=1)
4545 self.vapi.nat44_interface_add_del_feature(self.pg4.sw_if_index)
4546 self.vapi.nat44_interface_add_del_feature(self.pg4.sw_if_index,
4547 is_inside=0)
4548
4549 # from client to service
4550 p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
4551 IP(src=remote_host.ip4, dst=self.nat_addr) /
4552 TCP(sport=12345, dport=external_port))
4553 self.pg4.add_stream(p)
4554 self.pg_enable_capture(self.pg_interfaces)
4555 self.pg_start()
4556 capture = self.pg4.get_capture(1)
4557 p = capture[0]
4558 try:
4559 ip = p[IP]
4560 tcp = p[TCP]
4561 self.assertEqual(ip.dst, local_host.ip4)
4562 self.assertEqual(ip.src, self.nat_addr)
4563 self.assertEqual(tcp.dport, local_port)
4564 self.assertNotEqual(tcp.sport, 12345)
4565 eh_port_in = tcp.sport
4566 self.assert_packet_checksums_valid(p)
4567 except:
4568 self.logger.error(ppp("Unexpected or invalid packet:", p))
4569 raise
4570
4571 # from service back to client
4572 p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
4573 IP(src=local_host.ip4, dst=self.nat_addr) /
4574 TCP(sport=local_port, dport=eh_port_in))
4575 self.pg4.add_stream(p)
4576 self.pg_enable_capture(self.pg_interfaces)
4577 self.pg_start()
4578 capture = self.pg4.get_capture(1)
4579 p = capture[0]
4580 try:
4581 ip = p[IP]
4582 tcp = p[TCP]
4583 self.assertEqual(ip.src, self.nat_addr)
4584 self.assertEqual(ip.dst, remote_host.ip4)
4585 self.assertEqual(tcp.sport, external_port)
4586 self.assertEqual(tcp.dport, 12345)
4587 self.assert_packet_checksums_valid(p)
4588 except:
4589 self.logger.error(ppp("Unexpected or invalid packet:", p))
4590 raise
4591
4592 def test_static_with_port_out2(self):
4593 """ 1:1 NAPT asymmetrical rule """
4594
4595 external_port = 80
4596 local_port = 8080
4597
4598 self.vapi.nat44_forwarding_enable_disable(1)
4599 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
4600 local_port, external_port,
4601 proto=IP_PROTOS.tcp, out2in_only=1)
4602 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4603 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4604 is_inside=0)
4605
4606 # from client to service
4607 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4608 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4609 TCP(sport=12345, dport=external_port))
4610 self.pg1.add_stream(p)
4611 self.pg_enable_capture(self.pg_interfaces)
4612 self.pg_start()
4613 capture = self.pg0.get_capture(1)
4614 p = capture[0]
4615 try:
4616 ip = p[IP]
4617 tcp = p[TCP]
4618 self.assertEqual(ip.dst, self.pg0.remote_ip4)
4619 self.assertEqual(tcp.dport, local_port)
4620 self.assert_packet_checksums_valid(p)
4621 except:
4622 self.logger.error(ppp("Unexpected or invalid packet:", p))
4623 raise
4624
4625 # ICMP error
4626 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
4627 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4628 ICMP(type=11) / capture[0][IP])
4629 self.pg0.add_stream(p)
4630 self.pg_enable_capture(self.pg_interfaces)
4631 self.pg_start()
4632 capture = self.pg1.get_capture(1)
4633 p = capture[0]
4634 try:
4635 self.assertEqual(p[IP].src, self.nat_addr)
4636 inner = p[IPerror]
4637 self.assertEqual(inner.dst, self.nat_addr)
4638 self.assertEqual(inner[TCPerror].dport, external_port)
4639 except:
4640 self.logger.error(ppp("Unexpected or invalid packet:", p))
4641 raise
4642
4643 # from service back to client
4644 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4645 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4646 TCP(sport=local_port, dport=12345))
4647 self.pg0.add_stream(p)
4648 self.pg_enable_capture(self.pg_interfaces)
4649 self.pg_start()
4650 capture = self.pg1.get_capture(1)
4651 p = capture[0]
4652 try:
4653 ip = p[IP]
4654 tcp = p[TCP]
4655 self.assertEqual(ip.src, self.nat_addr)
4656 self.assertEqual(tcp.sport, external_port)
4657 self.assert_packet_checksums_valid(p)
4658 except:
4659 self.logger.error(ppp("Unexpected or invalid packet:", p))
4660 raise
4661
4662 # ICMP error
4663 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
4664 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4665 ICMP(type=11) / capture[0][IP])
4666 self.pg1.add_stream(p)
4667 self.pg_enable_capture(self.pg_interfaces)
4668 self.pg_start()
4669 capture = self.pg0.get_capture(1)
4670 p = capture[0]
4671 try:
4672 self.assertEqual(p[IP].dst, self.pg0.remote_ip4)
4673 inner = p[IPerror]
4674 self.assertEqual(inner.src, self.pg0.remote_ip4)
4675 self.assertEqual(inner[TCPerror].sport, local_port)
4676 except:
4677 self.logger.error(ppp("Unexpected or invalid packet:", p))
4678 raise
4679
4680 # from client to server (no translation)
4681 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4682 IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
4683 TCP(sport=12346, dport=local_port))
4684 self.pg1.add_stream(p)
4685 self.pg_enable_capture(self.pg_interfaces)
4686 self.pg_start()
4687 capture = self.pg0.get_capture(1)
4688 p = capture[0]
4689 try:
4690 ip = p[IP]
4691 tcp = p[TCP]
4692 self.assertEqual(ip.dst, self.pg0.remote_ip4)
4693 self.assertEqual(tcp.dport, local_port)
4694 self.assert_packet_checksums_valid(p)
4695 except:
4696 self.logger.error(ppp("Unexpected or invalid packet:", p))
4697 raise
4698
4699 # from service back to client (no translation)
4700 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4701 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4702 TCP(sport=local_port, dport=12346))
4703 self.pg0.add_stream(p)
4704 self.pg_enable_capture(self.pg_interfaces)
4705 self.pg_start()
4706 capture = self.pg1.get_capture(1)
4707 p = capture[0]
4708 try:
4709 ip = p[IP]
4710 tcp = p[TCP]
4711 self.assertEqual(ip.src, self.pg0.remote_ip4)
4712 self.assertEqual(tcp.sport, local_port)
4713 self.assert_packet_checksums_valid(p)
4714 except:
4715 self.logger.error(ppp("Unexpected or invalid packet:", p))
4716 raise
4717
Matus Fabian235a47e2018-06-25 16:42:36 -07004718 def test_output_feature(self):
4719 """ NAT44 interface output feature (in2out postrouting) """
4720 self.vapi.nat44_forwarding_enable_disable(1)
4721 self.nat44_add_address(self.nat_addr)
4722 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
4723 is_inside=0)
4724 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
4725 is_inside=0)
4726
4727 # in2out
4728 pkts = self.create_stream_in(self.pg0, self.pg1)
4729 self.pg0.add_stream(pkts)
4730 self.pg_enable_capture(self.pg_interfaces)
4731 self.pg_start()
4732 capture = self.pg1.get_capture(len(pkts))
4733 self.verify_capture_out(capture)
4734
4735 # out2in
4736 pkts = self.create_stream_out(self.pg1)
4737 self.pg1.add_stream(pkts)
4738 self.pg_enable_capture(self.pg_interfaces)
4739 self.pg_start()
4740 capture = self.pg0.get_capture(len(pkts))
4741 self.verify_capture_in(capture, self.pg0)
4742
Matus Fabian8008d7c2018-07-09 01:34:20 -07004743 def test_multiple_vrf(self):
4744 """ Multiple VRF setup """
4745 external_addr = '1.2.3.4'
4746 external_port = 80
4747 local_port = 8080
4748 port = 0
4749
4750 self.vapi.nat44_forwarding_enable_disable(1)
4751 self.nat44_add_address(self.nat_addr)
4752 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4753 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
4754 is_inside=0)
4755 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
4756 is_inside=0)
4757 self.vapi.nat44_interface_add_del_feature(self.pg5.sw_if_index)
4758 self.vapi.nat44_interface_add_del_feature(self.pg5.sw_if_index,
4759 is_inside=0)
4760 self.vapi.nat44_interface_add_del_feature(self.pg6.sw_if_index,
4761 is_inside=0)
4762 self.nat44_add_static_mapping(self.pg5.remote_ip4, external_addr,
4763 local_port, external_port, vrf_id=1,
4764 proto=IP_PROTOS.tcp, out2in_only=1)
4765 self.nat44_add_static_mapping(
4766 self.pg0.remote_ip4, external_sw_if_index=self.pg0.sw_if_index,
4767 local_port=local_port, vrf_id=0, external_port=external_port,
4768 proto=IP_PROTOS.tcp, out2in_only=1)
4769
4770 # from client to service (both VRF1)
4771 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
4772 IP(src=self.pg6.remote_ip4, dst=external_addr) /
4773 TCP(sport=12345, dport=external_port))
4774 self.pg6.add_stream(p)
4775 self.pg_enable_capture(self.pg_interfaces)
4776 self.pg_start()
4777 capture = self.pg5.get_capture(1)
4778 p = capture[0]
4779 try:
4780 ip = p[IP]
4781 tcp = p[TCP]
4782 self.assertEqual(ip.dst, self.pg5.remote_ip4)
4783 self.assertEqual(tcp.dport, local_port)
4784 self.assert_packet_checksums_valid(p)
4785 except:
4786 self.logger.error(ppp("Unexpected or invalid packet:", p))
4787 raise
4788
4789 # from service back to client (both VRF1)
4790 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
4791 IP(src=self.pg5.remote_ip4, dst=self.pg6.remote_ip4) /
4792 TCP(sport=local_port, dport=12345))
4793 self.pg5.add_stream(p)
4794 self.pg_enable_capture(self.pg_interfaces)
4795 self.pg_start()
4796 capture = self.pg6.get_capture(1)
4797 p = capture[0]
4798 try:
4799 ip = p[IP]
4800 tcp = p[TCP]
4801 self.assertEqual(ip.src, external_addr)
4802 self.assertEqual(tcp.sport, external_port)
4803 self.assert_packet_checksums_valid(p)
4804 except:
4805 self.logger.error(ppp("Unexpected or invalid packet:", p))
4806 raise
4807
4808 # dynamic NAT from VRF1 to VRF0 (output-feature)
4809 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
4810 IP(src=self.pg5.remote_ip4, dst=self.pg1.remote_ip4) /
4811 TCP(sport=2345, dport=22))
4812 self.pg5.add_stream(p)
4813 self.pg_enable_capture(self.pg_interfaces)
4814 self.pg_start()
4815 capture = self.pg1.get_capture(1)
4816 p = capture[0]
4817 try:
4818 ip = p[IP]
4819 tcp = p[TCP]
4820 self.assertEqual(ip.src, self.nat_addr)
4821 self.assertNotEqual(tcp.sport, 2345)
4822 self.assert_packet_checksums_valid(p)
4823 port = tcp.sport
4824 except:
4825 self.logger.error(ppp("Unexpected or invalid packet:", p))
4826 raise
4827
4828 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4829 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4830 TCP(sport=22, dport=port))
4831 self.pg1.add_stream(p)
4832 self.pg_enable_capture(self.pg_interfaces)
4833 self.pg_start()
4834 capture = self.pg5.get_capture(1)
4835 p = capture[0]
4836 try:
4837 ip = p[IP]
4838 tcp = p[TCP]
4839 self.assertEqual(ip.dst, self.pg5.remote_ip4)
4840 self.assertEqual(tcp.dport, 2345)
4841 self.assert_packet_checksums_valid(p)
4842 except:
4843 self.logger.error(ppp("Unexpected or invalid packet:", p))
4844 raise
4845
4846 # from client VRF1 to service VRF0
4847 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
4848 IP(src=self.pg6.remote_ip4, dst=self.pg0.local_ip4) /
4849 TCP(sport=12346, dport=external_port))
4850 self.pg6.add_stream(p)
4851 self.pg_enable_capture(self.pg_interfaces)
4852 self.pg_start()
4853 capture = self.pg0.get_capture(1)
4854 p = capture[0]
4855 try:
4856 ip = p[IP]
4857 tcp = p[TCP]
4858 self.assertEqual(ip.dst, self.pg0.remote_ip4)
4859 self.assertEqual(tcp.dport, local_port)
4860 self.assert_packet_checksums_valid(p)
4861 except:
4862 self.logger.error(ppp("Unexpected or invalid packet:", p))
4863 raise
4864
4865 # from service VRF0 back to client VRF1
4866 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4867 IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
4868 TCP(sport=local_port, dport=12346))
4869 self.pg0.add_stream(p)
4870 self.pg_enable_capture(self.pg_interfaces)
4871 self.pg_start()
4872 capture = self.pg6.get_capture(1)
4873 p = capture[0]
4874 try:
4875 ip = p[IP]
4876 tcp = p[TCP]
4877 self.assertEqual(ip.src, self.pg0.local_ip4)
4878 self.assertEqual(tcp.sport, external_port)
4879 self.assert_packet_checksums_valid(p)
4880 except:
4881 self.logger.error(ppp("Unexpected or invalid packet:", p))
4882 raise
4883
4884 # from client VRF0 to service VRF1
4885 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4886 IP(src=self.pg0.remote_ip4, dst=external_addr) /
4887 TCP(sport=12347, dport=external_port))
4888 self.pg0.add_stream(p)
4889 self.pg_enable_capture(self.pg_interfaces)
4890 self.pg_start()
4891 capture = self.pg5.get_capture(1)
4892 p = capture[0]
4893 try:
4894 ip = p[IP]
4895 tcp = p[TCP]
4896 self.assertEqual(ip.dst, self.pg5.remote_ip4)
4897 self.assertEqual(tcp.dport, local_port)
4898 self.assert_packet_checksums_valid(p)
4899 except:
4900 self.logger.error(ppp("Unexpected or invalid packet:", p))
4901 raise
4902
4903 # from service VRF1 back to client VRF0
4904 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
4905 IP(src=self.pg5.remote_ip4, dst=self.pg0.remote_ip4) /
4906 TCP(sport=local_port, dport=12347))
4907 self.pg5.add_stream(p)
4908 self.pg_enable_capture(self.pg_interfaces)
4909 self.pg_start()
4910 capture = self.pg0.get_capture(1)
4911 p = capture[0]
4912 try:
4913 ip = p[IP]
4914 tcp = p[TCP]
4915 self.assertEqual(ip.src, external_addr)
4916 self.assertEqual(tcp.sport, external_port)
4917 self.assert_packet_checksums_valid(p)
4918 except:
4919 self.logger.error(ppp("Unexpected or invalid packet:", p))
4920 raise
4921
4922 # from client to server (both VRF1, no translation)
4923 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
4924 IP(src=self.pg6.remote_ip4, dst=self.pg5.remote_ip4) /
4925 TCP(sport=12348, dport=local_port))
4926 self.pg6.add_stream(p)
4927 self.pg_enable_capture(self.pg_interfaces)
4928 self.pg_start()
4929 capture = self.pg5.get_capture(1)
4930 p = capture[0]
4931 try:
4932 ip = p[IP]
4933 tcp = p[TCP]
4934 self.assertEqual(ip.dst, self.pg5.remote_ip4)
4935 self.assertEqual(tcp.dport, local_port)
4936 self.assert_packet_checksums_valid(p)
4937 except:
4938 self.logger.error(ppp("Unexpected or invalid packet:", p))
4939 raise
4940
4941 # from server back to client (both VRF1, no translation)
4942 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
4943 IP(src=self.pg5.remote_ip4, dst=self.pg6.remote_ip4) /
4944 TCP(sport=local_port, dport=12348))
4945 self.pg5.add_stream(p)
4946 self.pg_enable_capture(self.pg_interfaces)
4947 self.pg_start()
4948 capture = self.pg6.get_capture(1)
4949 p = capture[0]
4950 try:
4951 ip = p[IP]
4952 tcp = p[TCP]
4953 self.assertEqual(ip.src, self.pg5.remote_ip4)
4954 self.assertEqual(tcp.sport, local_port)
4955 self.assert_packet_checksums_valid(p)
4956 except:
4957 self.logger.error(ppp("Unexpected or invalid packet:", p))
4958 raise
4959
4960 # from client VRF1 to server VRF0 (no translation)
4961 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4962 IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
4963 TCP(sport=local_port, dport=12349))
4964 self.pg0.add_stream(p)
4965 self.pg_enable_capture(self.pg_interfaces)
4966 self.pg_start()
4967 capture = self.pg6.get_capture(1)
4968 p = capture[0]
4969 try:
4970 ip = p[IP]
4971 tcp = p[TCP]
4972 self.assertEqual(ip.src, self.pg0.remote_ip4)
4973 self.assertEqual(tcp.sport, local_port)
4974 self.assert_packet_checksums_valid(p)
4975 except:
4976 self.logger.error(ppp("Unexpected or invalid packet:", p))
4977 raise
4978
4979 # from server VRF0 back to client VRF1 (no translation)
4980 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4981 IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
4982 TCP(sport=local_port, dport=12349))
4983 self.pg0.add_stream(p)
4984 self.pg_enable_capture(self.pg_interfaces)
4985 self.pg_start()
4986 capture = self.pg6.get_capture(1)
4987 p = capture[0]
4988 try:
4989 ip = p[IP]
4990 tcp = p[TCP]
4991 self.assertEqual(ip.src, self.pg0.remote_ip4)
4992 self.assertEqual(tcp.sport, local_port)
4993 self.assert_packet_checksums_valid(p)
4994 except:
4995 self.logger.error(ppp("Unexpected or invalid packet:", p))
4996 raise
4997
4998 # from client VRF0 to server VRF1 (no translation)
4999 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5000 IP(src=self.pg0.remote_ip4, dst=self.pg5.remote_ip4) /
5001 TCP(sport=12344, dport=local_port))
5002 self.pg0.add_stream(p)
5003 self.pg_enable_capture(self.pg_interfaces)
5004 self.pg_start()
5005 capture = self.pg5.get_capture(1)
5006 p = capture[0]
5007 try:
5008 ip = p[IP]
5009 tcp = p[TCP]
5010 self.assertEqual(ip.dst, self.pg5.remote_ip4)
5011 self.assertEqual(tcp.dport, local_port)
5012 self.assert_packet_checksums_valid(p)
5013 except:
5014 self.logger.error(ppp("Unexpected or invalid packet:", p))
5015 raise
5016
5017 # from server VRF1 back to client VRF0 (no translation)
5018 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
5019 IP(src=self.pg5.remote_ip4, dst=self.pg0.remote_ip4) /
5020 TCP(sport=local_port, dport=12344))
5021 self.pg5.add_stream(p)
5022 self.pg_enable_capture(self.pg_interfaces)
5023 self.pg_start()
5024 capture = self.pg0.get_capture(1)
5025 p = capture[0]
5026 try:
5027 ip = p[IP]
5028 tcp = p[TCP]
5029 self.assertEqual(ip.src, self.pg5.remote_ip4)
5030 self.assertEqual(tcp.sport, local_port)
5031 self.assert_packet_checksums_valid(p)
5032 except:
5033 self.logger.error(ppp("Unexpected or invalid packet:", p))
5034 raise
5035
Matus Fabian878c6462018-08-23 00:33:35 -07005036 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
5037 def test_session_timeout(self):
5038 """ NAT44 session timeouts """
5039 self.nat44_add_address(self.nat_addr)
5040 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5041 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
5042 is_inside=0)
5043 self.vapi.nat_set_timeouts(icmp=5)
5044
5045 max_sessions = 1000
5046 pkts = []
5047 for i in range(0, max_sessions):
5048 src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
5049 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5050 IP(src=src, dst=self.pg1.remote_ip4) /
5051 ICMP(id=1025, type='echo-request'))
5052 pkts.append(p)
5053 self.pg0.add_stream(pkts)
5054 self.pg_enable_capture(self.pg_interfaces)
5055 self.pg_start()
5056 self.pg1.get_capture(max_sessions)
5057
5058 sleep(10)
5059
5060 pkts = []
5061 for i in range(0, max_sessions):
5062 src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
5063 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5064 IP(src=src, dst=self.pg1.remote_ip4) /
5065 ICMP(id=1026, type='echo-request'))
5066 pkts.append(p)
5067 self.pg0.add_stream(pkts)
5068 self.pg_enable_capture(self.pg_interfaces)
5069 self.pg_start()
5070 self.pg1.get_capture(max_sessions)
5071
5072 nsessions = 0
5073 users = self.vapi.nat44_user_dump()
5074 for user in users:
5075 nsessions = nsessions + user.nsessions
5076 self.assertLess(nsessions, 2 * max_sessions)
5077
5078 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
5079 def test_session_limit_per_user(self):
5080 """ Maximum sessions per user limit """
5081 self.nat44_add_address(self.nat_addr)
5082 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5083 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
5084 is_inside=0)
5085 self.vapi.set_ipfix_exporter(collector_address=self.pg2.remote_ip4n,
5086 src_address=self.pg2.local_ip4n,
5087 path_mtu=512,
5088 template_interval=10)
5089
5090 # get maximum number of translations per user
5091 nat44_config = self.vapi.nat_show_config()
5092
5093 pkts = []
5094 for port in range(0, nat44_config.max_translations_per_user):
5095 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5096 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5097 UDP(sport=1025 + port, dport=1025 + port))
5098 pkts.append(p)
5099
5100 self.pg0.add_stream(pkts)
5101 self.pg_enable_capture(self.pg_interfaces)
5102 self.pg_start()
5103 capture = self.pg1.get_capture(len(pkts))
5104
5105 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
5106 src_port=self.ipfix_src_port)
5107
5108 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5109 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5110 UDP(sport=3001, dport=3002))
5111 self.pg0.add_stream(p)
5112 self.pg_enable_capture(self.pg_interfaces)
5113 self.pg_start()
5114 capture = self.pg1.assert_nothing_captured()
5115
5116 # verify IPFIX logging
5117 self.vapi.cli("ipfix flush") # FIXME this should be an API call
5118 sleep(1)
5119 capture = self.pg2.get_capture(10)
5120 ipfix = IPFIXDecoder()
5121 # first load template
5122 for p in capture:
5123 self.assertTrue(p.haslayer(IPFIX))
5124 if p.haslayer(Template):
5125 ipfix.add_template(p.getlayer(Template))
5126 # verify events in data set
5127 for p in capture:
5128 if p.haslayer(Data):
5129 data = ipfix.decode_data_set(p.getlayer(Set))
5130 self.verify_ipfix_max_entries_per_user(
5131 data,
5132 nat44_config.max_translations_per_user,
5133 self.pg0.remote_ip4n)
5134
Matus Fabiande886752016-12-07 03:38:19 -08005135 def tearDown(self):
Matus Fabiana6110b62018-06-13 05:39:07 -07005136 super(TestNAT44EndpointDependent, self).tearDown()
Matus Fabiande886752016-12-07 03:38:19 -08005137 if not self.vpp_dead:
Matus Fabian82119542018-01-25 01:13:22 -08005138 self.logger.info(self.vapi.cli("show nat44 addresses"))
5139 self.logger.info(self.vapi.cli("show nat44 interfaces"))
5140 self.logger.info(self.vapi.cli("show nat44 static mappings"))
5141 self.logger.info(self.vapi.cli("show nat44 interface address"))
5142 self.logger.info(self.vapi.cli("show nat44 sessions detail"))
Matus Fabian229c1aa2018-05-28 04:09:52 -07005143 self.logger.info(self.vapi.cli("show nat44 hash tables detail"))
Matus Fabian878c6462018-08-23 00:33:35 -07005144 self.logger.info(self.vapi.cli("show nat timeouts"))
Matus Fabian2ba92e32017-08-21 07:05:03 -07005145 self.clear_nat44()
Matus Fabian229c1aa2018-05-28 04:09:52 -07005146 self.vapi.cli("clear logging")
Matus Fabiande886752016-12-07 03:38:19 -08005147
Matus Fabianeea28d72017-01-13 04:15:54 -08005148
Juraj Slobodacba69362017-12-19 02:09:32 +01005149class TestNAT44Out2InDPO(MethodHolder):
5150 """ NAT44 Test Cases using out2in DPO """
5151
5152 @classmethod
5153 def setUpConstants(cls):
5154 super(TestNAT44Out2InDPO, cls).setUpConstants()
5155 cls.vpp_cmdline.extend(["nat", "{", "out2in dpo", "}"])
5156
5157 @classmethod
5158 def setUpClass(cls):
5159 super(TestNAT44Out2InDPO, cls).setUpClass()
Matus Fabian229c1aa2018-05-28 04:09:52 -07005160 cls.vapi.cli("set log class nat level debug")
Juraj Slobodacba69362017-12-19 02:09:32 +01005161
5162 try:
5163 cls.tcp_port_in = 6303
5164 cls.tcp_port_out = 6303
5165 cls.udp_port_in = 6304
5166 cls.udp_port_out = 6304
5167 cls.icmp_id_in = 6305
5168 cls.icmp_id_out = 6305
5169 cls.nat_addr = '10.0.0.3'
5170 cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
5171 cls.dst_ip4 = '192.168.70.1'
5172
5173 cls.create_pg_interfaces(range(2))
5174
5175 cls.pg0.admin_up()
5176 cls.pg0.config_ip4()
5177 cls.pg0.resolve_arp()
5178
5179 cls.pg1.admin_up()
5180 cls.pg1.config_ip6()
5181 cls.pg1.resolve_ndp()
5182
5183 cls.vapi.ip_add_del_route(is_ipv6=True, dst_address='\x00'*16,
5184 dst_address_length=0,
5185 next_hop_address=cls.pg1.remote_ip6n,
5186 next_hop_sw_if_index=cls.pg1.sw_if_index)
5187
5188 except Exception:
5189 super(TestNAT44Out2InDPO, cls).tearDownClass()
5190 raise
5191
5192 def configure_xlat(self):
5193 self.dst_ip6_pfx = '1:2:3::'
5194 self.dst_ip6_pfx_n = socket.inet_pton(socket.AF_INET6,
5195 self.dst_ip6_pfx)
5196 self.dst_ip6_pfx_len = 96
5197 self.src_ip6_pfx = '4:5:6::'
5198 self.src_ip6_pfx_n = socket.inet_pton(socket.AF_INET6,
5199 self.src_ip6_pfx)
5200 self.src_ip6_pfx_len = 96
5201 self.vapi.map_add_domain(self.dst_ip6_pfx_n, self.dst_ip6_pfx_len,
5202 self.src_ip6_pfx_n, self.src_ip6_pfx_len,
5203 '\x00\x00\x00\x00', 0, is_translation=1,
5204 is_rfc6052=1)
5205
5206 def test_464xlat_ce(self):
5207 """ Test 464XLAT CE with NAT44 """
5208
Matus Fabian69ce30d2018-08-22 01:27:10 -07005209 nat_config = self.vapi.nat_show_config()
5210 self.assertEqual(1, nat_config.out2in_dpo)
5211
Juraj Slobodacba69362017-12-19 02:09:32 +01005212 self.configure_xlat()
5213
5214 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5215 self.vapi.nat44_add_del_address_range(self.nat_addr_n, self.nat_addr_n)
5216
5217 out_src_ip6 = self.compose_ip6(self.dst_ip4, self.dst_ip6_pfx,
5218 self.dst_ip6_pfx_len)
5219 out_dst_ip6 = self.compose_ip6(self.nat_addr, self.src_ip6_pfx,
5220 self.src_ip6_pfx_len)
5221
5222 try:
5223 pkts = self.create_stream_in(self.pg0, self.pg1, self.dst_ip4)
5224 self.pg0.add_stream(pkts)
5225 self.pg_enable_capture(self.pg_interfaces)
5226 self.pg_start()
5227 capture = self.pg1.get_capture(len(pkts))
5228 self.verify_capture_out_ip6(capture, nat_ip=out_dst_ip6,
5229 dst_ip=out_src_ip6)
5230
5231 pkts = self.create_stream_out_ip6(self.pg1, out_src_ip6,
5232 out_dst_ip6)
5233 self.pg1.add_stream(pkts)
5234 self.pg_enable_capture(self.pg_interfaces)
5235 self.pg_start()
5236 capture = self.pg0.get_capture(len(pkts))
5237 self.verify_capture_in(capture, self.pg0)
5238 finally:
5239 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
5240 is_add=0)
5241 self.vapi.nat44_add_del_address_range(self.nat_addr_n,
5242 self.nat_addr_n, is_add=0)
5243
5244 def test_464xlat_ce_no_nat(self):
5245 """ Test 464XLAT CE without NAT44 """
5246
5247 self.configure_xlat()
5248
5249 out_src_ip6 = self.compose_ip6(self.dst_ip4, self.dst_ip6_pfx,
5250 self.dst_ip6_pfx_len)
5251 out_dst_ip6 = self.compose_ip6(self.pg0.remote_ip4, self.src_ip6_pfx,
5252 self.src_ip6_pfx_len)
5253
5254 pkts = self.create_stream_in(self.pg0, self.pg1, self.dst_ip4)
5255 self.pg0.add_stream(pkts)
5256 self.pg_enable_capture(self.pg_interfaces)
5257 self.pg_start()
5258 capture = self.pg1.get_capture(len(pkts))
5259 self.verify_capture_out_ip6(capture, dst_ip=out_src_ip6,
5260 nat_ip=out_dst_ip6, same_port=True)
5261
5262 pkts = self.create_stream_out_ip6(self.pg1, out_src_ip6, out_dst_ip6)
5263 self.pg1.add_stream(pkts)
5264 self.pg_enable_capture(self.pg_interfaces)
5265 self.pg_start()
5266 capture = self.pg0.get_capture(len(pkts))
5267 self.verify_capture_in(capture, self.pg0)
5268
5269
Martin Gálikd7f75cd2017-03-27 06:02:47 -07005270class TestDeterministicNAT(MethodHolder):
Matus Fabian066f0342017-02-10 03:48:01 -08005271 """ Deterministic NAT Test Cases """
5272
5273 @classmethod
5274 def setUpConstants(cls):
5275 super(TestDeterministicNAT, cls).setUpConstants()
Matus Fabian2ba92e32017-08-21 07:05:03 -07005276 cls.vpp_cmdline.extend(["nat", "{", "deterministic", "}"])
Matus Fabian066f0342017-02-10 03:48:01 -08005277
5278 @classmethod
5279 def setUpClass(cls):
5280 super(TestDeterministicNAT, cls).setUpClass()
Matus Fabian229c1aa2018-05-28 04:09:52 -07005281 cls.vapi.cli("set log class nat level debug")
Matus Fabian066f0342017-02-10 03:48:01 -08005282
5283 try:
Martin Gálik977c1cb2017-03-30 23:21:51 -07005284 cls.tcp_port_in = 6303
Martin Gálik9806eae2017-04-25 01:25:08 -07005285 cls.tcp_external_port = 6303
Martin Gálik977c1cb2017-03-30 23:21:51 -07005286 cls.udp_port_in = 6304
Martin Gálik9806eae2017-04-25 01:25:08 -07005287 cls.udp_external_port = 6304
Martin Gálik977c1cb2017-03-30 23:21:51 -07005288 cls.icmp_id_in = 6305
Matus Fabian2ba92e32017-08-21 07:05:03 -07005289 cls.nat_addr = '10.0.0.3'
Martin Gálik977c1cb2017-03-30 23:21:51 -07005290
Matus Fabian2f2db1c2017-04-18 05:29:59 -07005291 cls.create_pg_interfaces(range(3))
Matus Fabian066f0342017-02-10 03:48:01 -08005292 cls.interfaces = list(cls.pg_interfaces)
5293
5294 for i in cls.interfaces:
5295 i.admin_up()
5296 i.config_ip4()
5297 i.resolve_arp()
5298
Martin Gálik977c1cb2017-03-30 23:21:51 -07005299 cls.pg0.generate_remote_hosts(2)
5300 cls.pg0.configure_ipv4_neighbors()
5301
Matus Fabian066f0342017-02-10 03:48:01 -08005302 except Exception:
5303 super(TestDeterministicNAT, cls).tearDownClass()
5304 raise
5305
Martin Gálik977c1cb2017-03-30 23:21:51 -07005306 def create_stream_in(self, in_if, out_if, ttl=64):
5307 """
5308 Create packet stream for inside network
5309
5310 :param in_if: Inside interface
5311 :param out_if: Outside interface
5312 :param ttl: TTL of generated packets
5313 """
5314 pkts = []
5315 # TCP
5316 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
5317 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
Martin Gálik9806eae2017-04-25 01:25:08 -07005318 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07005319 pkts.append(p)
5320
5321 # UDP
5322 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
5323 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
Martin Gálik9806eae2017-04-25 01:25:08 -07005324 UDP(sport=self.udp_port_in, dport=self.udp_external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07005325 pkts.append(p)
5326
5327 # ICMP
5328 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
5329 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
5330 ICMP(id=self.icmp_id_in, type='echo-request'))
5331 pkts.append(p)
5332
5333 return pkts
5334
5335 def create_stream_out(self, out_if, dst_ip=None, ttl=64):
5336 """
5337 Create packet stream for outside network
5338
5339 :param out_if: Outside interface
Matus Fabian2ba92e32017-08-21 07:05:03 -07005340 :param dst_ip: Destination IP address (Default use global NAT address)
Martin Gálik977c1cb2017-03-30 23:21:51 -07005341 :param ttl: TTL of generated packets
5342 """
5343 if dst_ip is None:
Matus Fabian2ba92e32017-08-21 07:05:03 -07005344 dst_ip = self.nat_addr
Martin Gálik977c1cb2017-03-30 23:21:51 -07005345 pkts = []
5346 # TCP
5347 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
5348 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Martin Gálik9806eae2017-04-25 01:25:08 -07005349 TCP(dport=self.tcp_port_out, sport=self.tcp_external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07005350 pkts.append(p)
5351
5352 # UDP
5353 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
5354 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Martin Gálik9806eae2017-04-25 01:25:08 -07005355 UDP(dport=self.udp_port_out, sport=self.udp_external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07005356 pkts.append(p)
5357
5358 # ICMP
5359 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
5360 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
5361 ICMP(id=self.icmp_external_id, type='echo-reply'))
5362 pkts.append(p)
5363
5364 return pkts
5365
5366 def verify_capture_out(self, capture, nat_ip=None, packet_num=3):
5367 """
5368 Verify captured packets on outside network
5369
5370 :param capture: Captured packets
Matus Fabian2ba92e32017-08-21 07:05:03 -07005371 :param nat_ip: Translated IP address (Default use global NAT address)
Martin Gálik977c1cb2017-03-30 23:21:51 -07005372 :param same_port: Sorce port number is not translated (Default False)
5373 :param packet_num: Expected number of packets (Default 3)
5374 """
5375 if nat_ip is None:
Matus Fabian2ba92e32017-08-21 07:05:03 -07005376 nat_ip = self.nat_addr
Martin Gálik977c1cb2017-03-30 23:21:51 -07005377 self.assertEqual(packet_num, len(capture))
5378 for packet in capture:
5379 try:
5380 self.assertEqual(packet[IP].src, nat_ip)
5381 if packet.haslayer(TCP):
Martin Gálik9806eae2017-04-25 01:25:08 -07005382 self.tcp_port_out = packet[TCP].sport
Martin Gálik977c1cb2017-03-30 23:21:51 -07005383 elif packet.haslayer(UDP):
Martin Gálik9806eae2017-04-25 01:25:08 -07005384 self.udp_port_out = packet[UDP].sport
Martin Gálik977c1cb2017-03-30 23:21:51 -07005385 else:
5386 self.icmp_external_id = packet[ICMP].id
5387 except:
5388 self.logger.error(ppp("Unexpected or invalid packet "
5389 "(outside network):", packet))
5390 raise
5391
Matus Fabian066f0342017-02-10 03:48:01 -08005392 def test_deterministic_mode(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07005393 """ NAT plugin run deterministic mode """
Matus Fabian066f0342017-02-10 03:48:01 -08005394 in_addr = '172.16.255.0'
5395 out_addr = '172.17.255.50'
5396 in_addr_t = '172.16.255.20'
5397 in_addr_n = socket.inet_aton(in_addr)
5398 out_addr_n = socket.inet_aton(out_addr)
5399 in_addr_t_n = socket.inet_aton(in_addr_t)
5400 in_plen = 24
5401 out_plen = 32
5402
Matus Fabian2ba92e32017-08-21 07:05:03 -07005403 nat_config = self.vapi.nat_show_config()
5404 self.assertEqual(1, nat_config.deterministic)
Matus Fabian066f0342017-02-10 03:48:01 -08005405
Matus Fabian2ba92e32017-08-21 07:05:03 -07005406 self.vapi.nat_det_add_del_map(in_addr_n, in_plen, out_addr_n, out_plen)
Matus Fabian066f0342017-02-10 03:48:01 -08005407
Matus Fabian2ba92e32017-08-21 07:05:03 -07005408 rep1 = self.vapi.nat_det_forward(in_addr_t_n)
Matus Fabian066f0342017-02-10 03:48:01 -08005409 self.assertEqual(rep1.out_addr[:4], out_addr_n)
Matus Fabian2ba92e32017-08-21 07:05:03 -07005410 rep2 = self.vapi.nat_det_reverse(out_addr_n, rep1.out_port_hi)
Matus Fabian066f0342017-02-10 03:48:01 -08005411 self.assertEqual(rep2.in_addr[:4], in_addr_t_n)
5412
Matus Fabian2ba92e32017-08-21 07:05:03 -07005413 deterministic_mappings = self.vapi.nat_det_map_dump()
Martin17a75cb2017-03-08 05:53:20 -08005414 self.assertEqual(len(deterministic_mappings), 1)
5415 dsm = deterministic_mappings[0]
5416 self.assertEqual(in_addr_n, dsm.in_addr[:4])
5417 self.assertEqual(in_plen, dsm.in_plen)
5418 self.assertEqual(out_addr_n, dsm.out_addr[:4])
5419 self.assertEqual(out_plen, dsm.out_plen)
5420
Matus Fabian2ba92e32017-08-21 07:05:03 -07005421 self.clear_nat_det()
5422 deterministic_mappings = self.vapi.nat_det_map_dump()
Martinb616e9f2017-03-14 02:25:45 -07005423 self.assertEqual(len(deterministic_mappings), 0)
5424
Matus Fabian6a0946f2017-04-12 03:36:13 -07005425 def test_set_timeouts(self):
5426 """ Set deterministic NAT timeouts """
Matus Fabian878c6462018-08-23 00:33:35 -07005427 timeouts_before = self.vapi.nat_get_timeouts()
Matus Fabian6a0946f2017-04-12 03:36:13 -07005428
Matus Fabian878c6462018-08-23 00:33:35 -07005429 self.vapi.nat_set_timeouts(timeouts_before.udp + 10,
5430 timeouts_before.tcp_established + 10,
5431 timeouts_before.tcp_transitory + 10,
5432 timeouts_before.icmp + 10)
Matus Fabian6a0946f2017-04-12 03:36:13 -07005433
Matus Fabian878c6462018-08-23 00:33:35 -07005434 timeouts_after = self.vapi.nat_get_timeouts()
Matus Fabian6a0946f2017-04-12 03:36:13 -07005435
5436 self.assertNotEqual(timeouts_before.udp, timeouts_after.udp)
5437 self.assertNotEqual(timeouts_before.icmp, timeouts_after.icmp)
5438 self.assertNotEqual(timeouts_before.tcp_established,
5439 timeouts_after.tcp_established)
5440 self.assertNotEqual(timeouts_before.tcp_transitory,
5441 timeouts_after.tcp_transitory)
5442
Martin Gálik977c1cb2017-03-30 23:21:51 -07005443 def test_det_in(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07005444 """ Deterministic NAT translation test (TCP, UDP, ICMP) """
Martin Gálik977c1cb2017-03-30 23:21:51 -07005445
5446 nat_ip = "10.0.0.10"
Martin Gálik977c1cb2017-03-30 23:21:51 -07005447
Matus Fabian2ba92e32017-08-21 07:05:03 -07005448 self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
5449 32,
5450 socket.inet_aton(nat_ip),
5451 32)
5452 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5453 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
5454 is_inside=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07005455
5456 # in2out
5457 pkts = self.create_stream_in(self.pg0, self.pg1)
5458 self.pg0.add_stream(pkts)
5459 self.pg_enable_capture(self.pg_interfaces)
5460 self.pg_start()
5461 capture = self.pg1.get_capture(len(pkts))
5462 self.verify_capture_out(capture, nat_ip)
5463
5464 # out2in
5465 pkts = self.create_stream_out(self.pg1, nat_ip)
5466 self.pg1.add_stream(pkts)
5467 self.pg_enable_capture(self.pg_interfaces)
5468 self.pg_start()
5469 capture = self.pg0.get_capture(len(pkts))
5470 self.verify_capture_in(capture, self.pg0)
5471
Martin Gálik9806eae2017-04-25 01:25:08 -07005472 # session dump test
Matus Fabian2ba92e32017-08-21 07:05:03 -07005473 sessions = self.vapi.nat_det_session_dump(self.pg0.remote_ip4n)
Martin Gálik9806eae2017-04-25 01:25:08 -07005474 self.assertEqual(len(sessions), 3)
5475
5476 # TCP session
5477 s = sessions[0]
5478 self.assertEqual(s.ext_addr[:4], self.pg1.remote_ip4n)
5479 self.assertEqual(s.in_port, self.tcp_port_in)
5480 self.assertEqual(s.out_port, self.tcp_port_out)
5481 self.assertEqual(s.ext_port, self.tcp_external_port)
5482
5483 # UDP session
5484 s = sessions[1]
5485 self.assertEqual(s.ext_addr[:4], self.pg1.remote_ip4n)
5486 self.assertEqual(s.in_port, self.udp_port_in)
5487 self.assertEqual(s.out_port, self.udp_port_out)
5488 self.assertEqual(s.ext_port, self.udp_external_port)
5489
5490 # ICMP session
5491 s = sessions[2]
5492 self.assertEqual(s.ext_addr[:4], self.pg1.remote_ip4n)
5493 self.assertEqual(s.in_port, self.icmp_id_in)
5494 self.assertEqual(s.out_port, self.icmp_external_id)
5495
Martin Gálik977c1cb2017-03-30 23:21:51 -07005496 def test_multiple_users(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07005497 """ Deterministic NAT multiple users """
Martin Gálik977c1cb2017-03-30 23:21:51 -07005498
5499 nat_ip = "10.0.0.10"
5500 port_in = 80
Martin Gálik9806eae2017-04-25 01:25:08 -07005501 external_port = 6303
Martin Gálik977c1cb2017-03-30 23:21:51 -07005502
5503 host0 = self.pg0.remote_hosts[0]
5504 host1 = self.pg0.remote_hosts[1]
5505
Matus Fabian2ba92e32017-08-21 07:05:03 -07005506 self.vapi.nat_det_add_del_map(host0.ip4n,
5507 24,
5508 socket.inet_aton(nat_ip),
5509 32)
5510 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5511 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
5512 is_inside=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07005513
5514 # host0 to out
5515 p = (Ether(src=host0.mac, dst=self.pg0.local_mac) /
5516 IP(src=host0.ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07005517 TCP(sport=port_in, dport=external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07005518 self.pg0.add_stream(p)
5519 self.pg_enable_capture(self.pg_interfaces)
5520 self.pg_start()
5521 capture = self.pg1.get_capture(1)
5522 p = capture[0]
5523 try:
5524 ip = p[IP]
5525 tcp = p[TCP]
5526 self.assertEqual(ip.src, nat_ip)
5527 self.assertEqual(ip.dst, self.pg1.remote_ip4)
Martin Gálik9806eae2017-04-25 01:25:08 -07005528 self.assertEqual(tcp.dport, external_port)
5529 port_out0 = tcp.sport
Martin Gálik977c1cb2017-03-30 23:21:51 -07005530 except:
5531 self.logger.error(ppp("Unexpected or invalid packet:", p))
5532 raise
5533
5534 # host1 to out
5535 p = (Ether(src=host1.mac, dst=self.pg0.local_mac) /
5536 IP(src=host1.ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07005537 TCP(sport=port_in, dport=external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07005538 self.pg0.add_stream(p)
5539 self.pg_enable_capture(self.pg_interfaces)
5540 self.pg_start()
5541 capture = self.pg1.get_capture(1)
5542 p = capture[0]
5543 try:
5544 ip = p[IP]
5545 tcp = p[TCP]
5546 self.assertEqual(ip.src, nat_ip)
5547 self.assertEqual(ip.dst, self.pg1.remote_ip4)
Martin Gálik9806eae2017-04-25 01:25:08 -07005548 self.assertEqual(tcp.dport, external_port)
5549 port_out1 = tcp.sport
Martin Gálik977c1cb2017-03-30 23:21:51 -07005550 except:
5551 self.logger.error(ppp("Unexpected or invalid packet:", p))
5552 raise
5553
Matus Fabian2ba92e32017-08-21 07:05:03 -07005554 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07005555 self.assertEqual(1, len(dms))
5556 self.assertEqual(2, dms[0].ses_num)
5557
5558 # out to host0
5559 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5560 IP(src=self.pg1.remote_ip4, dst=nat_ip) /
Martin Gálik9806eae2017-04-25 01:25:08 -07005561 TCP(sport=external_port, dport=port_out0))
Martin Gálik977c1cb2017-03-30 23:21:51 -07005562 self.pg1.add_stream(p)
5563 self.pg_enable_capture(self.pg_interfaces)
5564 self.pg_start()
5565 capture = self.pg0.get_capture(1)
5566 p = capture[0]
5567 try:
5568 ip = p[IP]
5569 tcp = p[TCP]
5570 self.assertEqual(ip.src, self.pg1.remote_ip4)
5571 self.assertEqual(ip.dst, host0.ip4)
5572 self.assertEqual(tcp.dport, port_in)
Martin Gálik9806eae2017-04-25 01:25:08 -07005573 self.assertEqual(tcp.sport, external_port)
Martin Gálik977c1cb2017-03-30 23:21:51 -07005574 except:
5575 self.logger.error(ppp("Unexpected or invalid packet:", p))
5576 raise
5577
5578 # out to host1
5579 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5580 IP(src=self.pg1.remote_ip4, dst=nat_ip) /
Martin Gálik9806eae2017-04-25 01:25:08 -07005581 TCP(sport=external_port, dport=port_out1))
Martin Gálik977c1cb2017-03-30 23:21:51 -07005582 self.pg1.add_stream(p)
5583 self.pg_enable_capture(self.pg_interfaces)
5584 self.pg_start()
5585 capture = self.pg0.get_capture(1)
5586 p = capture[0]
5587 try:
5588 ip = p[IP]
5589 tcp = p[TCP]
5590 self.assertEqual(ip.src, self.pg1.remote_ip4)
5591 self.assertEqual(ip.dst, host1.ip4)
5592 self.assertEqual(tcp.dport, port_in)
Martin Gálik9806eae2017-04-25 01:25:08 -07005593 self.assertEqual(tcp.sport, external_port)
Martin Gálik977c1cb2017-03-30 23:21:51 -07005594 except:
5595 self.logger.error(ppp("Unexpected or invalid packet", p))
5596 raise
5597
Martin Gálik6bc8c642017-04-19 01:12:27 -07005598 # session close api test
Matus Fabian2ba92e32017-08-21 07:05:03 -07005599 self.vapi.nat_det_close_session_out(socket.inet_aton(nat_ip),
5600 port_out1,
Martin Gálik6bc8c642017-04-19 01:12:27 -07005601 self.pg1.remote_ip4n,
Martin Gálik9806eae2017-04-25 01:25:08 -07005602 external_port)
Matus Fabian2ba92e32017-08-21 07:05:03 -07005603 dms = self.vapi.nat_det_map_dump()
5604 self.assertEqual(dms[0].ses_num, 1)
5605
5606 self.vapi.nat_det_close_session_in(host0.ip4n,
5607 port_in,
5608 self.pg1.remote_ip4n,
5609 external_port)
5610 dms = self.vapi.nat_det_map_dump()
Martin Gálik6bc8c642017-04-19 01:12:27 -07005611 self.assertEqual(dms[0].ses_num, 0)
5612
Martin Gálik977c1cb2017-03-30 23:21:51 -07005613 def test_tcp_session_close_detection_in(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07005614 """ Deterministic NAT TCP session close from inside network """
5615 self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
5616 32,
5617 socket.inet_aton(self.nat_addr),
5618 32)
5619 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5620 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
5621 is_inside=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07005622
5623 self.initiate_tcp_session(self.pg0, self.pg1)
5624
5625 # close the session from inside
5626 try:
5627 # FIN packet in -> out
5628 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5629 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07005630 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
Martin Gálik977c1cb2017-03-30 23:21:51 -07005631 flags="F"))
5632 self.pg0.add_stream(p)
5633 self.pg_enable_capture(self.pg_interfaces)
5634 self.pg_start()
5635 self.pg1.get_capture(1)
5636
5637 pkts = []
5638
5639 # ACK packet out -> in
5640 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07005641 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Martin Gálik9806eae2017-04-25 01:25:08 -07005642 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
Martin Gálik977c1cb2017-03-30 23:21:51 -07005643 flags="A"))
5644 pkts.append(p)
5645
5646 # FIN packet out -> in
5647 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07005648 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Martin Gálik9806eae2017-04-25 01:25:08 -07005649 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
Martin Gálik977c1cb2017-03-30 23:21:51 -07005650 flags="F"))
5651 pkts.append(p)
5652
5653 self.pg1.add_stream(pkts)
5654 self.pg_enable_capture(self.pg_interfaces)
5655 self.pg_start()
5656 self.pg0.get_capture(2)
5657
5658 # ACK packet in -> out
5659 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5660 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07005661 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
Martin Gálik977c1cb2017-03-30 23:21:51 -07005662 flags="A"))
5663 self.pg0.add_stream(p)
5664 self.pg_enable_capture(self.pg_interfaces)
5665 self.pg_start()
5666 self.pg1.get_capture(1)
5667
Matus Fabian2ba92e32017-08-21 07:05:03 -07005668 # Check if deterministic NAT44 closed the session
5669 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07005670 self.assertEqual(0, dms[0].ses_num)
5671 except:
5672 self.logger.error("TCP session termination failed")
5673 raise
5674
5675 def test_tcp_session_close_detection_out(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07005676 """ Deterministic NAT TCP session close from outside network """
5677 self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
5678 32,
5679 socket.inet_aton(self.nat_addr),
5680 32)
5681 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5682 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
5683 is_inside=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07005684
5685 self.initiate_tcp_session(self.pg0, self.pg1)
5686
5687 # close the session from outside
5688 try:
5689 # FIN packet out -> in
5690 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07005691 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Martin Gálik9806eae2017-04-25 01:25:08 -07005692 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
Martin Gálik977c1cb2017-03-30 23:21:51 -07005693 flags="F"))
5694 self.pg1.add_stream(p)
5695 self.pg_enable_capture(self.pg_interfaces)
5696 self.pg_start()
5697 self.pg0.get_capture(1)
5698
5699 pkts = []
5700
5701 # ACK packet in -> out
5702 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5703 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07005704 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
Martin Gálik977c1cb2017-03-30 23:21:51 -07005705 flags="A"))
5706 pkts.append(p)
5707
5708 # ACK packet in -> out
5709 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5710 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07005711 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
Martin Gálik977c1cb2017-03-30 23:21:51 -07005712 flags="F"))
5713 pkts.append(p)
5714
5715 self.pg0.add_stream(pkts)
5716 self.pg_enable_capture(self.pg_interfaces)
5717 self.pg_start()
5718 self.pg1.get_capture(2)
5719
5720 # ACK packet out -> in
5721 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07005722 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Martin Gálik9806eae2017-04-25 01:25:08 -07005723 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
Martin Gálik977c1cb2017-03-30 23:21:51 -07005724 flags="A"))
5725 self.pg1.add_stream(p)
5726 self.pg_enable_capture(self.pg_interfaces)
5727 self.pg_start()
5728 self.pg0.get_capture(1)
5729
Matus Fabian2ba92e32017-08-21 07:05:03 -07005730 # Check if deterministic NAT44 closed the session
5731 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07005732 self.assertEqual(0, dms[0].ses_num)
5733 except:
5734 self.logger.error("TCP session termination failed")
5735 raise
5736
5737 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
5738 def test_session_timeout(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07005739 """ Deterministic NAT session timeouts """
5740 self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
5741 32,
5742 socket.inet_aton(self.nat_addr),
5743 32)
5744 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5745 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
5746 is_inside=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07005747
5748 self.initiate_tcp_session(self.pg0, self.pg1)
Matus Fabian878c6462018-08-23 00:33:35 -07005749 self.vapi.nat_set_timeouts(5, 5, 5, 5)
Martin Gálik977c1cb2017-03-30 23:21:51 -07005750 pkts = self.create_stream_in(self.pg0, self.pg1)
5751 self.pg0.add_stream(pkts)
5752 self.pg_enable_capture(self.pg_interfaces)
5753 self.pg_start()
5754 capture = self.pg1.get_capture(len(pkts))
5755 sleep(15)
5756
Matus Fabian2ba92e32017-08-21 07:05:03 -07005757 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07005758 self.assertEqual(0, dms[0].ses_num)
5759
Matus Fabian7c0aecc2017-07-03 01:21:38 -07005760 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
Martin Gálik977c1cb2017-03-30 23:21:51 -07005761 def test_session_limit_per_user(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07005762 """ Deterministic NAT maximum sessions per user limit """
5763 self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
5764 32,
5765 socket.inet_aton(self.nat_addr),
5766 32)
5767 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5768 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
5769 is_inside=0)
Matus Fabian2f2db1c2017-04-18 05:29:59 -07005770 self.vapi.set_ipfix_exporter(collector_address=self.pg2.remote_ip4n,
5771 src_address=self.pg2.local_ip4n,
5772 path_mtu=512,
5773 template_interval=10)
Matus Fabian2ba92e32017-08-21 07:05:03 -07005774 self.vapi.nat_ipfix()
Martin Gálik977c1cb2017-03-30 23:21:51 -07005775
5776 pkts = []
5777 for port in range(1025, 2025):
5778 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5779 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5780 UDP(sport=port, dport=port))
5781 pkts.append(p)
5782
5783 self.pg0.add_stream(pkts)
5784 self.pg_enable_capture(self.pg_interfaces)
5785 self.pg_start()
5786 capture = self.pg1.get_capture(len(pkts))
5787
5788 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5789 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálikf7e655d2017-04-27 02:13:26 -07005790 UDP(sport=3001, dport=3002))
Martin Gálik977c1cb2017-03-30 23:21:51 -07005791 self.pg0.add_stream(p)
5792 self.pg_enable_capture(self.pg_interfaces)
5793 self.pg_start()
5794 capture = self.pg1.assert_nothing_captured()
5795
Martin Gálikf7e655d2017-04-27 02:13:26 -07005796 # verify ICMP error packet
5797 capture = self.pg0.get_capture(1)
5798 p = capture[0]
5799 self.assertTrue(p.haslayer(ICMP))
5800 icmp = p[ICMP]
5801 self.assertEqual(icmp.type, 3)
5802 self.assertEqual(icmp.code, 1)
5803 self.assertTrue(icmp.haslayer(IPerror))
5804 inner_ip = icmp[IPerror]
5805 self.assertEqual(inner_ip[UDPerror].sport, 3001)
5806 self.assertEqual(inner_ip[UDPerror].dport, 3002)
5807
Matus Fabian2ba92e32017-08-21 07:05:03 -07005808 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07005809
5810 self.assertEqual(1000, dms[0].ses_num)
5811
Matus Fabian2f2db1c2017-04-18 05:29:59 -07005812 # verify IPFIX logging
5813 self.vapi.cli("ipfix flush") # FIXME this should be an API call
Matus Fabian7c0aecc2017-07-03 01:21:38 -07005814 sleep(1)
Matus Fabian2f2db1c2017-04-18 05:29:59 -07005815 capture = self.pg2.get_capture(2)
5816 ipfix = IPFIXDecoder()
5817 # first load template
5818 for p in capture:
5819 self.assertTrue(p.haslayer(IPFIX))
5820 if p.haslayer(Template):
5821 ipfix.add_template(p.getlayer(Template))
5822 # verify events in data set
5823 for p in capture:
5824 if p.haslayer(Data):
5825 data = ipfix.decode_data_set(p.getlayer(Set))
Matus Fabian878c6462018-08-23 00:33:35 -07005826 self.verify_ipfix_max_entries_per_user(data,
5827 1000,
5828 self.pg0.remote_ip4n)
Matus Fabian2f2db1c2017-04-18 05:29:59 -07005829
Matus Fabian2ba92e32017-08-21 07:05:03 -07005830 def clear_nat_det(self):
Martin17a75cb2017-03-08 05:53:20 -08005831 """
Matus Fabian2ba92e32017-08-21 07:05:03 -07005832 Clear deterministic NAT configuration.
Martin17a75cb2017-03-08 05:53:20 -08005833 """
Matus Fabian2ba92e32017-08-21 07:05:03 -07005834 self.vapi.nat_ipfix(enable=0)
Matus Fabian878c6462018-08-23 00:33:35 -07005835 self.vapi.nat_set_timeouts()
Matus Fabian2ba92e32017-08-21 07:05:03 -07005836 deterministic_mappings = self.vapi.nat_det_map_dump()
Martin17a75cb2017-03-08 05:53:20 -08005837 for dsm in deterministic_mappings:
Matus Fabian2ba92e32017-08-21 07:05:03 -07005838 self.vapi.nat_det_add_del_map(dsm.in_addr,
5839 dsm.in_plen,
5840 dsm.out_addr,
5841 dsm.out_plen,
5842 is_add=0)
Martin17a75cb2017-03-08 05:53:20 -08005843
Matus Fabian2ba92e32017-08-21 07:05:03 -07005844 interfaces = self.vapi.nat44_interface_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07005845 for intf in interfaces:
Matus Fabian2ba92e32017-08-21 07:05:03 -07005846 self.vapi.nat44_interface_add_del_feature(intf.sw_if_index,
5847 intf.is_inside,
5848 is_add=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07005849
Matus Fabian066f0342017-02-10 03:48:01 -08005850 def tearDown(self):
5851 super(TestDeterministicNAT, self).tearDown()
5852 if not self.vpp_dead:
Matus Fabian82119542018-01-25 01:13:22 -08005853 self.logger.info(self.vapi.cli("show nat44 interfaces"))
Matus Fabian878c6462018-08-23 00:33:35 -07005854 self.logger.info(self.vapi.cli("show nat timeouts"))
Matus Fabian82119542018-01-25 01:13:22 -08005855 self.logger.info(
5856 self.vapi.cli("show nat44 deterministic mappings"))
5857 self.logger.info(
Matus Fabian82119542018-01-25 01:13:22 -08005858 self.vapi.cli("show nat44 deterministic sessions"))
Matus Fabian2ba92e32017-08-21 07:05:03 -07005859 self.clear_nat_det()
Matus Fabian066f0342017-02-10 03:48:01 -08005860
Matus Fabian06596c52017-06-06 04:53:28 -07005861
5862class TestNAT64(MethodHolder):
5863 """ NAT64 Test Cases """
5864
5865 @classmethod
Matus Fabiana431ad12018-01-04 04:03:14 -08005866 def setUpConstants(cls):
5867 super(TestNAT64, cls).setUpConstants()
5868 cls.vpp_cmdline.extend(["nat", "{", "nat64 bib hash buckets 128",
5869 "nat64 st hash buckets 256", "}"])
5870
5871 @classmethod
Matus Fabian06596c52017-06-06 04:53:28 -07005872 def setUpClass(cls):
5873 super(TestNAT64, cls).setUpClass()
5874
5875 try:
5876 cls.tcp_port_in = 6303
5877 cls.tcp_port_out = 6303
5878 cls.udp_port_in = 6304
5879 cls.udp_port_out = 6304
5880 cls.icmp_id_in = 6305
5881 cls.icmp_id_out = 6305
5882 cls.nat_addr = '10.0.0.3'
5883 cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
Matus Fabian029f3d22017-06-15 02:28:50 -07005884 cls.vrf1_id = 10
5885 cls.vrf1_nat_addr = '10.0.10.3'
5886 cls.vrf1_nat_addr_n = socket.inet_pton(socket.AF_INET,
5887 cls.vrf1_nat_addr)
Matus Fabiana431ad12018-01-04 04:03:14 -08005888 cls.ipfix_src_port = 4739
5889 cls.ipfix_domain_id = 1
Matus Fabian06596c52017-06-06 04:53:28 -07005890
Juraj Slobodac746a152018-07-09 02:36:37 +02005891 cls.create_pg_interfaces(range(6))
Matus Fabian06596c52017-06-06 04:53:28 -07005892 cls.ip6_interfaces = list(cls.pg_interfaces[0:1])
Matus Fabian029f3d22017-06-15 02:28:50 -07005893 cls.ip6_interfaces.append(cls.pg_interfaces[2])
Matus Fabian06596c52017-06-06 04:53:28 -07005894 cls.ip4_interfaces = list(cls.pg_interfaces[1:2])
5895
Neale Ranns15002542017-09-10 04:39:11 -07005896 cls.vapi.ip_table_add_del(cls.vrf1_id, is_add=1, is_ipv6=1)
5897
Matus Fabian029f3d22017-06-15 02:28:50 -07005898 cls.pg_interfaces[2].set_table_ip6(cls.vrf1_id)
5899
5900 cls.pg0.generate_remote_hosts(2)
5901
Matus Fabian06596c52017-06-06 04:53:28 -07005902 for i in cls.ip6_interfaces:
5903 i.admin_up()
5904 i.config_ip6()
Matus Fabian029f3d22017-06-15 02:28:50 -07005905 i.configure_ipv6_neighbors()
Matus Fabian06596c52017-06-06 04:53:28 -07005906
5907 for i in cls.ip4_interfaces:
5908 i.admin_up()
5909 i.config_ip4()
5910 i.resolve_arp()
5911
Matus Fabian36ea2d62017-10-24 04:13:49 -07005912 cls.pg3.admin_up()
5913 cls.pg3.config_ip4()
5914 cls.pg3.resolve_arp()
5915 cls.pg3.config_ip6()
5916 cls.pg3.configure_ipv6_neighbors()
5917
Juraj Slobodac746a152018-07-09 02:36:37 +02005918 cls.pg5.admin_up()
5919 cls.pg5.config_ip6()
5920
Matus Fabian06596c52017-06-06 04:53:28 -07005921 except Exception:
5922 super(TestNAT64, cls).tearDownClass()
5923 raise
5924
Juraj Slobodac746a152018-07-09 02:36:37 +02005925 def test_nat64_inside_interface_handles_neighbor_advertisement(self):
5926 """ NAT64 inside interface handles Neighbor Advertisement """
5927
5928 self.vapi.nat64_add_del_interface(self.pg5.sw_if_index)
5929
5930 # Try to send ping
5931 ping = (Ether(dst=self.pg5.local_mac, src=self.pg5.remote_mac) /
5932 IPv6(src=self.pg5.remote_ip6, dst=self.pg5.local_ip6) /
5933 ICMPv6EchoRequest())
5934 pkts = [ping]
5935 self.pg5.add_stream(pkts)
5936 self.pg_enable_capture(self.pg_interfaces)
5937 self.pg_start()
5938
5939 # Wait for Neighbor Solicitation
5940 capture = self.pg5.get_capture(len(pkts))
5941 self.assertEqual(1, len(capture))
5942 packet = capture[0]
5943 try:
5944 self.assertEqual(packet[IPv6].src, self.pg5.local_ip6)
5945 self.assertTrue(packet.haslayer(ICMPv6ND_NS))
5946 tgt = packet[ICMPv6ND_NS].tgt
5947 except:
5948 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5949 raise
5950
5951 # Send Neighbor Advertisement
5952 p = (Ether(dst=self.pg5.local_mac, src=self.pg5.remote_mac) /
5953 IPv6(src=self.pg5.remote_ip6, dst=self.pg5.local_ip6) /
5954 ICMPv6ND_NA(tgt=tgt) /
5955 ICMPv6NDOptDstLLAddr(lladdr=self.pg5.remote_mac))
5956 pkts = [p]
5957 self.pg5.add_stream(pkts)
5958 self.pg_enable_capture(self.pg_interfaces)
5959 self.pg_start()
5960
5961 # Try to send ping again
5962 pkts = [ping]
5963 self.pg5.add_stream(pkts)
5964 self.pg_enable_capture(self.pg_interfaces)
5965 self.pg_start()
5966
5967 # Wait for ping reply
5968 capture = self.pg5.get_capture(len(pkts))
5969 self.assertEqual(1, len(capture))
5970 packet = capture[0]
5971 try:
5972 self.assertEqual(packet[IPv6].src, self.pg5.local_ip6)
5973 self.assertEqual(packet[IPv6].dst, self.pg5.remote_ip6)
5974 self.assertTrue(packet.haslayer(ICMPv6EchoReply))
5975 except:
5976 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5977 raise
5978
Matus Fabian06596c52017-06-06 04:53:28 -07005979 def test_pool(self):
5980 """ Add/delete address to NAT64 pool """
5981 nat_addr = socket.inet_pton(socket.AF_INET, '1.2.3.4')
5982
5983 self.vapi.nat64_add_del_pool_addr_range(nat_addr, nat_addr)
5984
5985 addresses = self.vapi.nat64_pool_addr_dump()
5986 self.assertEqual(len(addresses), 1)
5987 self.assertEqual(addresses[0].address, nat_addr)
5988
5989 self.vapi.nat64_add_del_pool_addr_range(nat_addr, nat_addr, is_add=0)
5990
5991 addresses = self.vapi.nat64_pool_addr_dump()
5992 self.assertEqual(len(addresses), 0)
5993
5994 def test_interface(self):
5995 """ Enable/disable NAT64 feature on the interface """
5996 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
5997 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
5998
5999 interfaces = self.vapi.nat64_interface_dump()
6000 self.assertEqual(len(interfaces), 2)
6001 pg0_found = False
6002 pg1_found = False
6003 for intf in interfaces:
6004 if intf.sw_if_index == self.pg0.sw_if_index:
6005 self.assertEqual(intf.is_inside, 1)
6006 pg0_found = True
6007 elif intf.sw_if_index == self.pg1.sw_if_index:
6008 self.assertEqual(intf.is_inside, 0)
6009 pg1_found = True
6010 self.assertTrue(pg0_found)
6011 self.assertTrue(pg1_found)
6012
6013 features = self.vapi.cli("show interface features pg0")
6014 self.assertNotEqual(features.find('nat64-in2out'), -1)
6015 features = self.vapi.cli("show interface features pg1")
6016 self.assertNotEqual(features.find('nat64-out2in'), -1)
6017
6018 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index, is_add=0)
6019 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_add=0)
6020
6021 interfaces = self.vapi.nat64_interface_dump()
6022 self.assertEqual(len(interfaces), 0)
6023
6024 def test_static_bib(self):
6025 """ Add/delete static BIB entry """
6026 in_addr = socket.inet_pton(socket.AF_INET6,
6027 '2001:db8:85a3::8a2e:370:7334')
6028 out_addr = socket.inet_pton(socket.AF_INET, '10.1.1.3')
6029 in_port = 1234
6030 out_port = 5678
6031 proto = IP_PROTOS.tcp
6032
6033 self.vapi.nat64_add_del_static_bib(in_addr,
6034 out_addr,
6035 in_port,
6036 out_port,
6037 proto)
6038 bib = self.vapi.nat64_bib_dump(IP_PROTOS.tcp)
6039 static_bib_num = 0
6040 for bibe in bib:
6041 if bibe.is_static:
6042 static_bib_num += 1
6043 self.assertEqual(bibe.i_addr, in_addr)
6044 self.assertEqual(bibe.o_addr, out_addr)
6045 self.assertEqual(bibe.i_port, in_port)
6046 self.assertEqual(bibe.o_port, out_port)
6047 self.assertEqual(static_bib_num, 1)
6048
6049 self.vapi.nat64_add_del_static_bib(in_addr,
6050 out_addr,
6051 in_port,
6052 out_port,
6053 proto,
6054 is_add=0)
6055 bib = self.vapi.nat64_bib_dump(IP_PROTOS.tcp)
6056 static_bib_num = 0
6057 for bibe in bib:
6058 if bibe.is_static:
6059 static_bib_num += 1
6060 self.assertEqual(static_bib_num, 0)
6061
6062 def test_set_timeouts(self):
6063 """ Set NAT64 timeouts """
6064 # verify default values
Matus Fabian878c6462018-08-23 00:33:35 -07006065 timeouts = self.vapi.nat_get_timeouts()
Matus Fabian06596c52017-06-06 04:53:28 -07006066 self.assertEqual(timeouts.udp, 300)
6067 self.assertEqual(timeouts.icmp, 60)
Matus Fabian878c6462018-08-23 00:33:35 -07006068 self.assertEqual(timeouts.tcp_transitory, 240)
6069 self.assertEqual(timeouts.tcp_established, 7440)
Matus Fabian06596c52017-06-06 04:53:28 -07006070
6071 # set and verify custom values
Matus Fabian878c6462018-08-23 00:33:35 -07006072 self.vapi.nat_set_timeouts(udp=200, icmp=30, tcp_transitory=250,
6073 tcp_established=7450)
6074 timeouts = self.vapi.nat_get_timeouts()
Matus Fabian06596c52017-06-06 04:53:28 -07006075 self.assertEqual(timeouts.udp, 200)
6076 self.assertEqual(timeouts.icmp, 30)
Matus Fabian878c6462018-08-23 00:33:35 -07006077 self.assertEqual(timeouts.tcp_transitory, 250)
6078 self.assertEqual(timeouts.tcp_established, 7450)
Matus Fabian06596c52017-06-06 04:53:28 -07006079
6080 def test_dynamic(self):
6081 """ NAT64 dynamic translation test """
6082 self.tcp_port_in = 6303
6083 self.udp_port_in = 6304
6084 self.icmp_id_in = 6305
6085
6086 ses_num_start = self.nat64_get_ses_num()
6087
6088 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6089 self.nat_addr_n)
6090 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6091 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6092
6093 # in2out
6094 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
6095 self.pg0.add_stream(pkts)
6096 self.pg_enable_capture(self.pg_interfaces)
6097 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07006098 capture = self.pg1.get_capture(len(pkts))
6099 self.verify_capture_out(capture, nat_ip=self.nat_addr,
Matus Fabian06596c52017-06-06 04:53:28 -07006100 dst_ip=self.pg1.remote_ip4)
6101
6102 # out2in
6103 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
6104 self.pg1.add_stream(pkts)
6105 self.pg_enable_capture(self.pg_interfaces)
6106 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07006107 capture = self.pg0.get_capture(len(pkts))
Matus Fabian06596c52017-06-06 04:53:28 -07006108 ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
6109 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
6110
6111 # in2out
6112 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
6113 self.pg0.add_stream(pkts)
6114 self.pg_enable_capture(self.pg_interfaces)
6115 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07006116 capture = self.pg1.get_capture(len(pkts))
6117 self.verify_capture_out(capture, nat_ip=self.nat_addr,
Matus Fabian06596c52017-06-06 04:53:28 -07006118 dst_ip=self.pg1.remote_ip4)
6119
6120 # out2in
6121 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
6122 self.pg1.add_stream(pkts)
6123 self.pg_enable_capture(self.pg_interfaces)
6124 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07006125 capture = self.pg0.get_capture(len(pkts))
Matus Fabian06596c52017-06-06 04:53:28 -07006126 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
6127
6128 ses_num_end = self.nat64_get_ses_num()
6129
6130 self.assertEqual(ses_num_end - ses_num_start, 3)
6131
Matus Fabian029f3d22017-06-15 02:28:50 -07006132 # tenant with specific VRF
6133 self.vapi.nat64_add_del_pool_addr_range(self.vrf1_nat_addr_n,
6134 self.vrf1_nat_addr_n,
6135 vrf_id=self.vrf1_id)
6136 self.vapi.nat64_add_del_interface(self.pg2.sw_if_index)
6137
6138 pkts = self.create_stream_in_ip6(self.pg2, self.pg1)
6139 self.pg2.add_stream(pkts)
6140 self.pg_enable_capture(self.pg_interfaces)
6141 self.pg_start()
6142 capture = self.pg1.get_capture(len(pkts))
6143 self.verify_capture_out(capture, nat_ip=self.vrf1_nat_addr,
6144 dst_ip=self.pg1.remote_ip4)
6145
6146 pkts = self.create_stream_out(self.pg1, dst_ip=self.vrf1_nat_addr)
6147 self.pg1.add_stream(pkts)
6148 self.pg_enable_capture(self.pg_interfaces)
6149 self.pg_start()
6150 capture = self.pg2.get_capture(len(pkts))
6151 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg2.remote_ip6)
6152
Matus Fabian06596c52017-06-06 04:53:28 -07006153 def test_static(self):
6154 """ NAT64 static translation test """
6155 self.tcp_port_in = 60303
6156 self.udp_port_in = 60304
6157 self.icmp_id_in = 60305
6158 self.tcp_port_out = 60303
6159 self.udp_port_out = 60304
6160 self.icmp_id_out = 60305
6161
6162 ses_num_start = self.nat64_get_ses_num()
6163
6164 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6165 self.nat_addr_n)
6166 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6167 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6168
6169 self.vapi.nat64_add_del_static_bib(self.pg0.remote_ip6n,
6170 self.nat_addr_n,
6171 self.tcp_port_in,
6172 self.tcp_port_out,
6173 IP_PROTOS.tcp)
6174 self.vapi.nat64_add_del_static_bib(self.pg0.remote_ip6n,
6175 self.nat_addr_n,
6176 self.udp_port_in,
6177 self.udp_port_out,
6178 IP_PROTOS.udp)
6179 self.vapi.nat64_add_del_static_bib(self.pg0.remote_ip6n,
6180 self.nat_addr_n,
6181 self.icmp_id_in,
6182 self.icmp_id_out,
6183 IP_PROTOS.icmp)
6184
6185 # in2out
6186 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
6187 self.pg0.add_stream(pkts)
6188 self.pg_enable_capture(self.pg_interfaces)
6189 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07006190 capture = self.pg1.get_capture(len(pkts))
6191 self.verify_capture_out(capture, nat_ip=self.nat_addr,
Matus Fabian06596c52017-06-06 04:53:28 -07006192 dst_ip=self.pg1.remote_ip4, same_port=True)
6193
6194 # out2in
6195 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
6196 self.pg1.add_stream(pkts)
6197 self.pg_enable_capture(self.pg_interfaces)
6198 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07006199 capture = self.pg0.get_capture(len(pkts))
Matus Fabian06596c52017-06-06 04:53:28 -07006200 ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
6201 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
6202
6203 ses_num_end = self.nat64_get_ses_num()
6204
6205 self.assertEqual(ses_num_end - ses_num_start, 3)
6206
6207 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
6208 def test_session_timeout(self):
6209 """ NAT64 session timeout """
6210 self.icmp_id_in = 1234
6211 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6212 self.nat_addr_n)
6213 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6214 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
Matus Fabian878c6462018-08-23 00:33:35 -07006215 self.vapi.nat_set_timeouts(icmp=5, tcp_transitory=5, tcp_established=5)
Matus Fabian06596c52017-06-06 04:53:28 -07006216
6217 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
6218 self.pg0.add_stream(pkts)
6219 self.pg_enable_capture(self.pg_interfaces)
6220 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07006221 capture = self.pg1.get_capture(len(pkts))
Matus Fabian06596c52017-06-06 04:53:28 -07006222
6223 ses_num_before_timeout = self.nat64_get_ses_num()
6224
6225 sleep(15)
6226
Matus Fabian8fed4242018-08-14 05:14:55 -07006227 # ICMP and TCP session after timeout
Matus Fabian06596c52017-06-06 04:53:28 -07006228 ses_num_after_timeout = self.nat64_get_ses_num()
Matus Fabian8fed4242018-08-14 05:14:55 -07006229 self.assertEqual(ses_num_before_timeout - ses_num_after_timeout, 2)
Matus Fabian06596c52017-06-06 04:53:28 -07006230
Matus Fabian732036d2017-06-08 05:24:28 -07006231 def test_icmp_error(self):
6232 """ NAT64 ICMP Error message translation """
6233 self.tcp_port_in = 6303
6234 self.udp_port_in = 6304
6235 self.icmp_id_in = 6305
6236
Matus Fabian732036d2017-06-08 05:24:28 -07006237 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6238 self.nat_addr_n)
6239 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6240 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6241
6242 # send some packets to create sessions
6243 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
6244 self.pg0.add_stream(pkts)
6245 self.pg_enable_capture(self.pg_interfaces)
6246 self.pg_start()
6247 capture_ip4 = self.pg1.get_capture(len(pkts))
Matus Fabian029f3d22017-06-15 02:28:50 -07006248 self.verify_capture_out(capture_ip4,
Matus Fabian732036d2017-06-08 05:24:28 -07006249 nat_ip=self.nat_addr,
6250 dst_ip=self.pg1.remote_ip4)
6251
6252 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
6253 self.pg1.add_stream(pkts)
6254 self.pg_enable_capture(self.pg_interfaces)
6255 self.pg_start()
6256 capture_ip6 = self.pg0.get_capture(len(pkts))
6257 ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
6258 self.verify_capture_in_ip6(capture_ip6, ip[IPv6].src,
6259 self.pg0.remote_ip6)
6260
6261 # in2out
6262 pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6263 IPv6(src=self.pg0.remote_ip6, dst=ip[IPv6].src) /
6264 ICMPv6DestUnreach(code=1) /
6265 packet[IPv6] for packet in capture_ip6]
6266 self.pg0.add_stream(pkts)
6267 self.pg_enable_capture(self.pg_interfaces)
6268 self.pg_start()
6269 capture = self.pg1.get_capture(len(pkts))
6270 for packet in capture:
6271 try:
6272 self.assertEqual(packet[IP].src, self.nat_addr)
6273 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
6274 self.assertEqual(packet[ICMP].type, 3)
6275 self.assertEqual(packet[ICMP].code, 13)
6276 inner = packet[IPerror]
6277 self.assertEqual(inner.src, self.pg1.remote_ip4)
6278 self.assertEqual(inner.dst, self.nat_addr)
Klement Sekerad81ae412018-05-16 10:52:54 +02006279 self.assert_packet_checksums_valid(packet)
Matus Fabian732036d2017-06-08 05:24:28 -07006280 if inner.haslayer(TCPerror):
6281 self.assertEqual(inner[TCPerror].dport, self.tcp_port_out)
6282 elif inner.haslayer(UDPerror):
6283 self.assertEqual(inner[UDPerror].dport, self.udp_port_out)
6284 else:
6285 self.assertEqual(inner[ICMPerror].id, self.icmp_id_out)
6286 except:
6287 self.logger.error(ppp("Unexpected or invalid packet:", packet))
6288 raise
6289
6290 # out2in
6291 pkts = [Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
6292 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6293 ICMP(type=3, code=13) /
6294 packet[IP] for packet in capture_ip4]
6295 self.pg1.add_stream(pkts)
6296 self.pg_enable_capture(self.pg_interfaces)
6297 self.pg_start()
6298 capture = self.pg0.get_capture(len(pkts))
6299 for packet in capture:
6300 try:
6301 self.assertEqual(packet[IPv6].src, ip.src)
6302 self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
6303 icmp = packet[ICMPv6DestUnreach]
6304 self.assertEqual(icmp.code, 1)
6305 inner = icmp[IPerror6]
6306 self.assertEqual(inner.src, self.pg0.remote_ip6)
6307 self.assertEqual(inner.dst, ip.src)
Klement Sekerad81ae412018-05-16 10:52:54 +02006308 self.assert_icmpv6_checksum_valid(packet)
Matus Fabian732036d2017-06-08 05:24:28 -07006309 if inner.haslayer(TCPerror):
6310 self.assertEqual(inner[TCPerror].sport, self.tcp_port_in)
6311 elif inner.haslayer(UDPerror):
6312 self.assertEqual(inner[UDPerror].sport, self.udp_port_in)
6313 else:
6314 self.assertEqual(inner[ICMPv6EchoRequest].id,
6315 self.icmp_id_in)
6316 except:
6317 self.logger.error(ppp("Unexpected or invalid packet:", packet))
6318 raise
6319
Matus Fabian029f3d22017-06-15 02:28:50 -07006320 def test_hairpinning(self):
6321 """ NAT64 hairpinning """
6322
6323 client = self.pg0.remote_hosts[0]
6324 server = self.pg0.remote_hosts[1]
6325 server_tcp_in_port = 22
6326 server_tcp_out_port = 4022
6327 server_udp_in_port = 23
6328 server_udp_out_port = 4023
6329 client_tcp_in_port = 1234
6330 client_udp_in_port = 1235
6331 client_tcp_out_port = 0
6332 client_udp_out_port = 0
6333 ip = IPv6(src=''.join(['64:ff9b::', self.nat_addr]))
6334 nat_addr_ip6 = ip.src
6335
6336 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6337 self.nat_addr_n)
6338 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6339 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6340
6341 self.vapi.nat64_add_del_static_bib(server.ip6n,
6342 self.nat_addr_n,
6343 server_tcp_in_port,
6344 server_tcp_out_port,
6345 IP_PROTOS.tcp)
6346 self.vapi.nat64_add_del_static_bib(server.ip6n,
6347 self.nat_addr_n,
6348 server_udp_in_port,
6349 server_udp_out_port,
6350 IP_PROTOS.udp)
6351
6352 # client to server
6353 pkts = []
6354 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6355 IPv6(src=client.ip6, dst=nat_addr_ip6) /
6356 TCP(sport=client_tcp_in_port, dport=server_tcp_out_port))
6357 pkts.append(p)
6358 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6359 IPv6(src=client.ip6, dst=nat_addr_ip6) /
6360 UDP(sport=client_udp_in_port, dport=server_udp_out_port))
6361 pkts.append(p)
6362 self.pg0.add_stream(pkts)
6363 self.pg_enable_capture(self.pg_interfaces)
6364 self.pg_start()
6365 capture = self.pg0.get_capture(len(pkts))
6366 for packet in capture:
6367 try:
6368 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
6369 self.assertEqual(packet[IPv6].dst, server.ip6)
Klement Sekerad81ae412018-05-16 10:52:54 +02006370 self.assert_packet_checksums_valid(packet)
Matus Fabian029f3d22017-06-15 02:28:50 -07006371 if packet.haslayer(TCP):
6372 self.assertNotEqual(packet[TCP].sport, client_tcp_in_port)
6373 self.assertEqual(packet[TCP].dport, server_tcp_in_port)
Matus Fabian029f3d22017-06-15 02:28:50 -07006374 client_tcp_out_port = packet[TCP].sport
6375 else:
6376 self.assertNotEqual(packet[UDP].sport, client_udp_in_port)
6377 self.assertEqual(packet[UDP].dport, server_udp_in_port)
Matus Fabian029f3d22017-06-15 02:28:50 -07006378 client_udp_out_port = packet[UDP].sport
6379 except:
6380 self.logger.error(ppp("Unexpected or invalid packet:", packet))
6381 raise
6382
6383 # server to client
6384 pkts = []
6385 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6386 IPv6(src=server.ip6, dst=nat_addr_ip6) /
6387 TCP(sport=server_tcp_in_port, dport=client_tcp_out_port))
6388 pkts.append(p)
6389 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6390 IPv6(src=server.ip6, dst=nat_addr_ip6) /
6391 UDP(sport=server_udp_in_port, dport=client_udp_out_port))
6392 pkts.append(p)
6393 self.pg0.add_stream(pkts)
6394 self.pg_enable_capture(self.pg_interfaces)
6395 self.pg_start()
6396 capture = self.pg0.get_capture(len(pkts))
6397 for packet in capture:
6398 try:
6399 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
6400 self.assertEqual(packet[IPv6].dst, client.ip6)
Klement Sekerad81ae412018-05-16 10:52:54 +02006401 self.assert_packet_checksums_valid(packet)
Matus Fabian029f3d22017-06-15 02:28:50 -07006402 if packet.haslayer(TCP):
6403 self.assertEqual(packet[TCP].sport, server_tcp_out_port)
6404 self.assertEqual(packet[TCP].dport, client_tcp_in_port)
Matus Fabian029f3d22017-06-15 02:28:50 -07006405 else:
6406 self.assertEqual(packet[UDP].sport, server_udp_out_port)
6407 self.assertEqual(packet[UDP].dport, client_udp_in_port)
Matus Fabian029f3d22017-06-15 02:28:50 -07006408 except:
6409 self.logger.error(ppp("Unexpected or invalid packet:", packet))
6410 raise
6411
6412 # ICMP error
6413 pkts = []
6414 pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6415 IPv6(src=client.ip6, dst=nat_addr_ip6) /
6416 ICMPv6DestUnreach(code=1) /
6417 packet[IPv6] for packet in capture]
6418 self.pg0.add_stream(pkts)
6419 self.pg_enable_capture(self.pg_interfaces)
6420 self.pg_start()
6421 capture = self.pg0.get_capture(len(pkts))
6422 for packet in capture:
6423 try:
6424 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
6425 self.assertEqual(packet[IPv6].dst, server.ip6)
6426 icmp = packet[ICMPv6DestUnreach]
6427 self.assertEqual(icmp.code, 1)
6428 inner = icmp[IPerror6]
6429 self.assertEqual(inner.src, server.ip6)
6430 self.assertEqual(inner.dst, nat_addr_ip6)
Klement Sekerad81ae412018-05-16 10:52:54 +02006431 self.assert_packet_checksums_valid(packet)
Matus Fabian029f3d22017-06-15 02:28:50 -07006432 if inner.haslayer(TCPerror):
6433 self.assertEqual(inner[TCPerror].sport, server_tcp_in_port)
6434 self.assertEqual(inner[TCPerror].dport,
6435 client_tcp_out_port)
6436 else:
6437 self.assertEqual(inner[UDPerror].sport, server_udp_in_port)
6438 self.assertEqual(inner[UDPerror].dport,
6439 client_udp_out_port)
6440 except:
6441 self.logger.error(ppp("Unexpected or invalid packet:", packet))
6442 raise
6443
Matus Fabian428dc912017-06-21 06:15:18 -07006444 def test_prefix(self):
6445 """ NAT64 Network-Specific Prefix """
6446
6447 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6448 self.nat_addr_n)
6449 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6450 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6451 self.vapi.nat64_add_del_pool_addr_range(self.vrf1_nat_addr_n,
6452 self.vrf1_nat_addr_n,
6453 vrf_id=self.vrf1_id)
6454 self.vapi.nat64_add_del_interface(self.pg2.sw_if_index)
6455
6456 # Add global prefix
6457 global_pref64 = "2001:db8::"
6458 global_pref64_n = socket.inet_pton(socket.AF_INET6, global_pref64)
6459 global_pref64_len = 32
6460 self.vapi.nat64_add_del_prefix(global_pref64_n, global_pref64_len)
6461
6462 prefix = self.vapi.nat64_prefix_dump()
6463 self.assertEqual(len(prefix), 1)
6464 self.assertEqual(prefix[0].prefix, global_pref64_n)
6465 self.assertEqual(prefix[0].prefix_len, global_pref64_len)
6466 self.assertEqual(prefix[0].vrf_id, 0)
6467
6468 # Add tenant specific prefix
6469 vrf1_pref64 = "2001:db8:122:300::"
6470 vrf1_pref64_n = socket.inet_pton(socket.AF_INET6, vrf1_pref64)
6471 vrf1_pref64_len = 56
6472 self.vapi.nat64_add_del_prefix(vrf1_pref64_n,
6473 vrf1_pref64_len,
6474 vrf_id=self.vrf1_id)
6475 prefix = self.vapi.nat64_prefix_dump()
6476 self.assertEqual(len(prefix), 2)
6477
6478 # Global prefix
6479 pkts = self.create_stream_in_ip6(self.pg0,
6480 self.pg1,
6481 pref=global_pref64,
6482 plen=global_pref64_len)
6483 self.pg0.add_stream(pkts)
6484 self.pg_enable_capture(self.pg_interfaces)
6485 self.pg_start()
6486 capture = self.pg1.get_capture(len(pkts))
6487 self.verify_capture_out(capture, nat_ip=self.nat_addr,
6488 dst_ip=self.pg1.remote_ip4)
6489
6490 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
6491 self.pg1.add_stream(pkts)
6492 self.pg_enable_capture(self.pg_interfaces)
6493 self.pg_start()
6494 capture = self.pg0.get_capture(len(pkts))
6495 dst_ip = self.compose_ip6(self.pg1.remote_ip4,
6496 global_pref64,
6497 global_pref64_len)
6498 self.verify_capture_in_ip6(capture, dst_ip, self.pg0.remote_ip6)
6499
6500 # Tenant specific prefix
6501 pkts = self.create_stream_in_ip6(self.pg2,
6502 self.pg1,
6503 pref=vrf1_pref64,
6504 plen=vrf1_pref64_len)
6505 self.pg2.add_stream(pkts)
6506 self.pg_enable_capture(self.pg_interfaces)
6507 self.pg_start()
6508 capture = self.pg1.get_capture(len(pkts))
6509 self.verify_capture_out(capture, nat_ip=self.vrf1_nat_addr,
6510 dst_ip=self.pg1.remote_ip4)
6511
6512 pkts = self.create_stream_out(self.pg1, dst_ip=self.vrf1_nat_addr)
6513 self.pg1.add_stream(pkts)
6514 self.pg_enable_capture(self.pg_interfaces)
6515 self.pg_start()
6516 capture = self.pg2.get_capture(len(pkts))
6517 dst_ip = self.compose_ip6(self.pg1.remote_ip4,
6518 vrf1_pref64,
6519 vrf1_pref64_len)
6520 self.verify_capture_in_ip6(capture, dst_ip, self.pg2.remote_ip6)
6521
Matus Fabianf8cd5812017-07-11 03:55:02 -07006522 def test_unknown_proto(self):
Matus Fabian7968e6c2017-07-06 05:37:49 -07006523 """ NAT64 translate packet with unknown protocol """
6524
6525 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6526 self.nat_addr_n)
6527 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6528 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6529 remote_ip6 = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
6530
6531 # in2out
6532 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6533 IPv6(src=self.pg0.remote_ip6, dst=remote_ip6) /
6534 TCP(sport=self.tcp_port_in, dport=20))
6535 self.pg0.add_stream(p)
6536 self.pg_enable_capture(self.pg_interfaces)
6537 self.pg_start()
6538 p = self.pg1.get_capture(1)
6539
6540 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabianf8cd5812017-07-11 03:55:02 -07006541 IPv6(src=self.pg0.remote_ip6, dst=remote_ip6, nh=47) /
Matus Fabian7968e6c2017-07-06 05:37:49 -07006542 GRE() /
6543 IP(src=self.pg2.local_ip4, dst=self.pg2.remote_ip4) /
6544 TCP(sport=1234, dport=1234))
6545 self.pg0.add_stream(p)
6546 self.pg_enable_capture(self.pg_interfaces)
6547 self.pg_start()
6548 p = self.pg1.get_capture(1)
6549 packet = p[0]
6550 try:
6551 self.assertEqual(packet[IP].src, self.nat_addr)
6552 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
6553 self.assertTrue(packet.haslayer(GRE))
Klement Sekerad81ae412018-05-16 10:52:54 +02006554 self.assert_packet_checksums_valid(packet)
Matus Fabian7968e6c2017-07-06 05:37:49 -07006555 except:
6556 self.logger.error(ppp("Unexpected or invalid packet:", packet))
6557 raise
6558
6559 # out2in
6560 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
6561 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6562 GRE() /
6563 IP(src=self.pg2.remote_ip4, dst=self.pg2.local_ip4) /
6564 TCP(sport=1234, dport=1234))
6565 self.pg1.add_stream(p)
6566 self.pg_enable_capture(self.pg_interfaces)
6567 self.pg_start()
6568 p = self.pg0.get_capture(1)
6569 packet = p[0]
6570 try:
6571 self.assertEqual(packet[IPv6].src, remote_ip6)
Matus Fabianf8cd5812017-07-11 03:55:02 -07006572 self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
6573 self.assertEqual(packet[IPv6].nh, 47)
Matus Fabian7968e6c2017-07-06 05:37:49 -07006574 except:
6575 self.logger.error(ppp("Unexpected or invalid packet:", packet))
6576 raise
6577
Matus Fabianf8cd5812017-07-11 03:55:02 -07006578 def test_hairpinning_unknown_proto(self):
Matus Fabian7968e6c2017-07-06 05:37:49 -07006579 """ NAT64 translate packet with unknown protocol - hairpinning """
6580
6581 client = self.pg0.remote_hosts[0]
6582 server = self.pg0.remote_hosts[1]
6583 server_tcp_in_port = 22
6584 server_tcp_out_port = 4022
6585 client_tcp_in_port = 1234
Matus Fabianf8cd5812017-07-11 03:55:02 -07006586 client_tcp_out_port = 1235
6587 server_nat_ip = "10.0.0.100"
6588 client_nat_ip = "10.0.0.110"
6589 server_nat_ip_n = socket.inet_pton(socket.AF_INET, server_nat_ip)
6590 client_nat_ip_n = socket.inet_pton(socket.AF_INET, client_nat_ip)
6591 server_nat_ip6 = self.compose_ip6(server_nat_ip, '64:ff9b::', 96)
6592 client_nat_ip6 = self.compose_ip6(client_nat_ip, '64:ff9b::', 96)
Matus Fabian7968e6c2017-07-06 05:37:49 -07006593
Matus Fabianf8cd5812017-07-11 03:55:02 -07006594 self.vapi.nat64_add_del_pool_addr_range(server_nat_ip_n,
6595 client_nat_ip_n)
Matus Fabian7968e6c2017-07-06 05:37:49 -07006596 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6597 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6598
6599 self.vapi.nat64_add_del_static_bib(server.ip6n,
Matus Fabianf8cd5812017-07-11 03:55:02 -07006600 server_nat_ip_n,
Matus Fabian7968e6c2017-07-06 05:37:49 -07006601 server_tcp_in_port,
6602 server_tcp_out_port,
6603 IP_PROTOS.tcp)
6604
Matus Fabianf8cd5812017-07-11 03:55:02 -07006605 self.vapi.nat64_add_del_static_bib(server.ip6n,
6606 server_nat_ip_n,
6607 0,
6608 0,
6609 IP_PROTOS.gre)
6610
6611 self.vapi.nat64_add_del_static_bib(client.ip6n,
6612 client_nat_ip_n,
6613 client_tcp_in_port,
6614 client_tcp_out_port,
6615 IP_PROTOS.tcp)
6616
Matus Fabian7968e6c2017-07-06 05:37:49 -07006617 # client to server
6618 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabianf8cd5812017-07-11 03:55:02 -07006619 IPv6(src=client.ip6, dst=server_nat_ip6) /
Matus Fabian7968e6c2017-07-06 05:37:49 -07006620 TCP(sport=client_tcp_in_port, dport=server_tcp_out_port))
6621 self.pg0.add_stream(p)
6622 self.pg_enable_capture(self.pg_interfaces)
6623 self.pg_start()
6624 p = self.pg0.get_capture(1)
6625
6626 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabianf8cd5812017-07-11 03:55:02 -07006627 IPv6(src=client.ip6, dst=server_nat_ip6, nh=IP_PROTOS.gre) /
Matus Fabian7968e6c2017-07-06 05:37:49 -07006628 GRE() /
6629 IP(src=self.pg2.local_ip4, dst=self.pg2.remote_ip4) /
6630 TCP(sport=1234, dport=1234))
6631 self.pg0.add_stream(p)
6632 self.pg_enable_capture(self.pg_interfaces)
6633 self.pg_start()
6634 p = self.pg0.get_capture(1)
6635 packet = p[0]
6636 try:
Matus Fabianf8cd5812017-07-11 03:55:02 -07006637 self.assertEqual(packet[IPv6].src, client_nat_ip6)
Matus Fabian7968e6c2017-07-06 05:37:49 -07006638 self.assertEqual(packet[IPv6].dst, server.ip6)
Matus Fabianf8cd5812017-07-11 03:55:02 -07006639 self.assertEqual(packet[IPv6].nh, IP_PROTOS.gre)
Matus Fabian7968e6c2017-07-06 05:37:49 -07006640 except:
6641 self.logger.error(ppp("Unexpected or invalid packet:", packet))
6642 raise
6643
6644 # server to client
6645 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabianf8cd5812017-07-11 03:55:02 -07006646 IPv6(src=server.ip6, dst=client_nat_ip6, nh=IP_PROTOS.gre) /
Matus Fabian7968e6c2017-07-06 05:37:49 -07006647 GRE() /
6648 IP(src=self.pg2.remote_ip4, dst=self.pg2.local_ip4) /
6649 TCP(sport=1234, dport=1234))
6650 self.pg0.add_stream(p)
6651 self.pg_enable_capture(self.pg_interfaces)
6652 self.pg_start()
6653 p = self.pg0.get_capture(1)
6654 packet = p[0]
6655 try:
Matus Fabianf8cd5812017-07-11 03:55:02 -07006656 self.assertEqual(packet[IPv6].src, server_nat_ip6)
Matus Fabian7968e6c2017-07-06 05:37:49 -07006657 self.assertEqual(packet[IPv6].dst, client.ip6)
Matus Fabianf8cd5812017-07-11 03:55:02 -07006658 self.assertEqual(packet[IPv6].nh, IP_PROTOS.gre)
Matus Fabian7968e6c2017-07-06 05:37:49 -07006659 except:
6660 self.logger.error(ppp("Unexpected or invalid packet:", packet))
6661 raise
6662
Matus Fabian36ea2d62017-10-24 04:13:49 -07006663 def test_one_armed_nat64(self):
6664 """ One armed NAT64 """
6665 external_port = 0
6666 remote_host_ip6 = self.compose_ip6(self.pg3.remote_ip4,
6667 '64:ff9b::',
6668 96)
6669
6670 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6671 self.nat_addr_n)
6672 self.vapi.nat64_add_del_interface(self.pg3.sw_if_index)
6673 self.vapi.nat64_add_del_interface(self.pg3.sw_if_index, is_inside=0)
6674
6675 # in2out
6676 p = (Ether(src=self.pg3.remote_mac, dst=self.pg3.local_mac) /
6677 IPv6(src=self.pg3.remote_ip6, dst=remote_host_ip6) /
6678 TCP(sport=12345, dport=80))
6679 self.pg3.add_stream(p)
6680 self.pg_enable_capture(self.pg_interfaces)
6681 self.pg_start()
6682 capture = self.pg3.get_capture(1)
6683 p = capture[0]
6684 try:
6685 ip = p[IP]
6686 tcp = p[TCP]
6687 self.assertEqual(ip.src, self.nat_addr)
6688 self.assertEqual(ip.dst, self.pg3.remote_ip4)
6689 self.assertNotEqual(tcp.sport, 12345)
6690 external_port = tcp.sport
6691 self.assertEqual(tcp.dport, 80)
Klement Sekerad81ae412018-05-16 10:52:54 +02006692 self.assert_packet_checksums_valid(p)
Matus Fabian36ea2d62017-10-24 04:13:49 -07006693 except:
6694 self.logger.error(ppp("Unexpected or invalid packet:", p))
6695 raise
6696
6697 # out2in
6698 p = (Ether(src=self.pg3.remote_mac, dst=self.pg3.local_mac) /
6699 IP(src=self.pg3.remote_ip4, dst=self.nat_addr) /
6700 TCP(sport=80, dport=external_port))
6701 self.pg3.add_stream(p)
6702 self.pg_enable_capture(self.pg_interfaces)
6703 self.pg_start()
6704 capture = self.pg3.get_capture(1)
6705 p = capture[0]
6706 try:
6707 ip = p[IPv6]
6708 tcp = p[TCP]
6709 self.assertEqual(ip.src, remote_host_ip6)
6710 self.assertEqual(ip.dst, self.pg3.remote_ip6)
6711 self.assertEqual(tcp.sport, 80)
6712 self.assertEqual(tcp.dport, 12345)
Klement Sekerad81ae412018-05-16 10:52:54 +02006713 self.assert_packet_checksums_valid(p)
Matus Fabian36ea2d62017-10-24 04:13:49 -07006714 except:
6715 self.logger.error(ppp("Unexpected or invalid packet:", p))
6716 raise
6717
Matus Fabianefcd1e92017-08-15 06:59:19 -07006718 def test_frag_in_order(self):
6719 """ NAT64 translate fragments arriving in order """
6720 self.tcp_port_in = random.randint(1025, 65535)
6721
6722 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6723 self.nat_addr_n)
6724 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6725 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6726
6727 reass = self.vapi.nat_reass_dump()
6728 reass_n_start = len(reass)
6729
6730 # in2out
6731 data = 'a' * 200
6732 pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
6733 self.tcp_port_in, 20, data)
6734 self.pg0.add_stream(pkts)
6735 self.pg_enable_capture(self.pg_interfaces)
6736 self.pg_start()
6737 frags = self.pg1.get_capture(len(pkts))
6738 p = self.reass_frags_and_verify(frags,
6739 self.nat_addr,
6740 self.pg1.remote_ip4)
6741 self.assertEqual(p[TCP].dport, 20)
6742 self.assertNotEqual(p[TCP].sport, self.tcp_port_in)
6743 self.tcp_port_out = p[TCP].sport
6744 self.assertEqual(data, p[Raw].load)
6745
6746 # out2in
6747 data = "A" * 4 + "b" * 16 + "C" * 3
6748 pkts = self.create_stream_frag(self.pg1,
6749 self.nat_addr,
6750 20,
6751 self.tcp_port_out,
6752 data)
6753 self.pg1.add_stream(pkts)
6754 self.pg_enable_capture(self.pg_interfaces)
6755 self.pg_start()
6756 frags = self.pg0.get_capture(len(pkts))
6757 src = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
6758 p = self.reass_frags_and_verify_ip6(frags, src, self.pg0.remote_ip6)
6759 self.assertEqual(p[TCP].sport, 20)
6760 self.assertEqual(p[TCP].dport, self.tcp_port_in)
6761 self.assertEqual(data, p[Raw].load)
6762
6763 reass = self.vapi.nat_reass_dump()
6764 reass_n_end = len(reass)
6765
6766 self.assertEqual(reass_n_end - reass_n_start, 2)
6767
6768 def test_reass_hairpinning(self):
6769 """ NAT64 fragments hairpinning """
6770 data = 'a' * 200
Matus Fabianefcd1e92017-08-15 06:59:19 -07006771 server = self.pg0.remote_hosts[1]
6772 server_in_port = random.randint(1025, 65535)
6773 server_out_port = random.randint(1025, 65535)
6774 client_in_port = random.randint(1025, 65535)
6775 ip = IPv6(src=''.join(['64:ff9b::', self.nat_addr]))
6776 nat_addr_ip6 = ip.src
6777
6778 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6779 self.nat_addr_n)
6780 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6781 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6782
6783 # add static BIB entry for server
6784 self.vapi.nat64_add_del_static_bib(server.ip6n,
6785 self.nat_addr_n,
6786 server_in_port,
6787 server_out_port,
6788 IP_PROTOS.tcp)
6789
6790 # send packet from host to server
6791 pkts = self.create_stream_frag_ip6(self.pg0,
6792 self.nat_addr,
6793 client_in_port,
6794 server_out_port,
6795 data)
6796 self.pg0.add_stream(pkts)
6797 self.pg_enable_capture(self.pg_interfaces)
6798 self.pg_start()
6799 frags = self.pg0.get_capture(len(pkts))
6800 p = self.reass_frags_and_verify_ip6(frags, nat_addr_ip6, server.ip6)
6801 self.assertNotEqual(p[TCP].sport, client_in_port)
6802 self.assertEqual(p[TCP].dport, server_in_port)
6803 self.assertEqual(data, p[Raw].load)
6804
6805 def test_frag_out_of_order(self):
6806 """ NAT64 translate fragments arriving out of order """
6807 self.tcp_port_in = random.randint(1025, 65535)
6808
6809 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6810 self.nat_addr_n)
6811 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6812 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6813
6814 # in2out
6815 data = 'a' * 200
6816 pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
6817 self.tcp_port_in, 20, data)
6818 pkts.reverse()
6819 self.pg0.add_stream(pkts)
6820 self.pg_enable_capture(self.pg_interfaces)
6821 self.pg_start()
6822 frags = self.pg1.get_capture(len(pkts))
6823 p = self.reass_frags_and_verify(frags,
6824 self.nat_addr,
6825 self.pg1.remote_ip4)
6826 self.assertEqual(p[TCP].dport, 20)
6827 self.assertNotEqual(p[TCP].sport, self.tcp_port_in)
6828 self.tcp_port_out = p[TCP].sport
6829 self.assertEqual(data, p[Raw].load)
6830
6831 # out2in
6832 data = "A" * 4 + "B" * 16 + "C" * 3
6833 pkts = self.create_stream_frag(self.pg1,
6834 self.nat_addr,
6835 20,
6836 self.tcp_port_out,
6837 data)
6838 pkts.reverse()
6839 self.pg1.add_stream(pkts)
6840 self.pg_enable_capture(self.pg_interfaces)
6841 self.pg_start()
6842 frags = self.pg0.get_capture(len(pkts))
6843 src = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
6844 p = self.reass_frags_and_verify_ip6(frags, src, self.pg0.remote_ip6)
6845 self.assertEqual(p[TCP].sport, 20)
6846 self.assertEqual(p[TCP].dport, self.tcp_port_in)
6847 self.assertEqual(data, p[Raw].load)
6848
Matus Fabian0938dcf2017-11-08 01:59:38 -08006849 def test_interface_addr(self):
6850 """ Acquire NAT64 pool addresses from interface """
6851 self.vapi.nat64_add_interface_addr(self.pg4.sw_if_index)
6852
6853 # no address in NAT64 pool
6854 adresses = self.vapi.nat44_address_dump()
6855 self.assertEqual(0, len(adresses))
6856
6857 # configure interface address and check NAT64 address pool
6858 self.pg4.config_ip4()
6859 addresses = self.vapi.nat64_pool_addr_dump()
6860 self.assertEqual(len(addresses), 1)
6861 self.assertEqual(addresses[0].address, self.pg4.local_ip4n)
6862
6863 # remove interface address and check NAT64 address pool
6864 self.pg4.unconfig_ip4()
6865 addresses = self.vapi.nat64_pool_addr_dump()
6866 self.assertEqual(0, len(adresses))
6867
Matus Fabiana431ad12018-01-04 04:03:14 -08006868 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
6869 def test_ipfix_max_bibs_sessions(self):
6870 """ IPFIX logging maximum session and BIB entries exceeded """
6871 max_bibs = 1280
6872 max_sessions = 2560
6873 remote_host_ip6 = self.compose_ip6(self.pg1.remote_ip4,
6874 '64:ff9b::',
6875 96)
6876
6877 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6878 self.nat_addr_n)
6879 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6880 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6881
6882 pkts = []
6883 src = ""
6884 for i in range(0, max_bibs):
6885 src = "fd01:aa::%x" % (i)
6886 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6887 IPv6(src=src, dst=remote_host_ip6) /
6888 TCP(sport=12345, dport=80))
6889 pkts.append(p)
6890 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6891 IPv6(src=src, dst=remote_host_ip6) /
6892 TCP(sport=12345, dport=22))
6893 pkts.append(p)
6894 self.pg0.add_stream(pkts)
6895 self.pg_enable_capture(self.pg_interfaces)
6896 self.pg_start()
6897 self.pg1.get_capture(max_sessions)
6898
6899 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
6900 src_address=self.pg3.local_ip4n,
6901 path_mtu=512,
6902 template_interval=10)
6903 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
6904 src_port=self.ipfix_src_port)
6905
6906 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6907 IPv6(src=src, dst=remote_host_ip6) /
6908 TCP(sport=12345, dport=25))
6909 self.pg0.add_stream(p)
6910 self.pg_enable_capture(self.pg_interfaces)
6911 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07006912 self.pg1.assert_nothing_captured()
6913 sleep(1)
Matus Fabiana431ad12018-01-04 04:03:14 -08006914 self.vapi.cli("ipfix flush") # FIXME this should be an API call
6915 capture = self.pg3.get_capture(9)
6916 ipfix = IPFIXDecoder()
6917 # first load template
6918 for p in capture:
6919 self.assertTrue(p.haslayer(IPFIX))
6920 self.assertEqual(p[IP].src, self.pg3.local_ip4)
6921 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
6922 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
6923 self.assertEqual(p[UDP].dport, 4739)
6924 self.assertEqual(p[IPFIX].observationDomainID,
6925 self.ipfix_domain_id)
6926 if p.haslayer(Template):
6927 ipfix.add_template(p.getlayer(Template))
6928 # verify events in data set
6929 for p in capture:
6930 if p.haslayer(Data):
6931 data = ipfix.decode_data_set(p.getlayer(Set))
6932 self.verify_ipfix_max_sessions(data, max_sessions)
6933
6934 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6935 IPv6(src=self.pg0.remote_ip6, dst=remote_host_ip6) /
6936 TCP(sport=12345, dport=80))
6937 self.pg0.add_stream(p)
6938 self.pg_enable_capture(self.pg_interfaces)
6939 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07006940 self.pg1.assert_nothing_captured()
6941 sleep(1)
Matus Fabiana431ad12018-01-04 04:03:14 -08006942 self.vapi.cli("ipfix flush") # FIXME this should be an API call
6943 capture = self.pg3.get_capture(1)
6944 # verify events in data set
6945 for p in capture:
6946 self.assertTrue(p.haslayer(IPFIX))
6947 self.assertEqual(p[IP].src, self.pg3.local_ip4)
6948 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
6949 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
6950 self.assertEqual(p[UDP].dport, 4739)
6951 self.assertEqual(p[IPFIX].observationDomainID,
6952 self.ipfix_domain_id)
6953 if p.haslayer(Data):
6954 data = ipfix.decode_data_set(p.getlayer(Set))
6955 self.verify_ipfix_max_bibs(data, max_bibs)
6956
6957 def test_ipfix_max_frags(self):
6958 """ IPFIX logging maximum fragments pending reassembly exceeded """
6959 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6960 self.nat_addr_n)
6961 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6962 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6963 self.vapi.nat_set_reass(max_frag=0, is_ip6=1)
6964 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
6965 src_address=self.pg3.local_ip4n,
6966 path_mtu=512,
6967 template_interval=10)
6968 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
6969 src_port=self.ipfix_src_port)
6970
6971 data = 'a' * 200
6972 pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
6973 self.tcp_port_in, 20, data)
6974 self.pg0.add_stream(pkts[-1])
6975 self.pg_enable_capture(self.pg_interfaces)
6976 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07006977 self.pg1.assert_nothing_captured()
6978 sleep(1)
Matus Fabiana431ad12018-01-04 04:03:14 -08006979 self.vapi.cli("ipfix flush") # FIXME this should be an API call
6980 capture = self.pg3.get_capture(9)
6981 ipfix = IPFIXDecoder()
6982 # first load template
6983 for p in capture:
6984 self.assertTrue(p.haslayer(IPFIX))
6985 self.assertEqual(p[IP].src, self.pg3.local_ip4)
6986 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
6987 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
6988 self.assertEqual(p[UDP].dport, 4739)
6989 self.assertEqual(p[IPFIX].observationDomainID,
6990 self.ipfix_domain_id)
6991 if p.haslayer(Template):
6992 ipfix.add_template(p.getlayer(Template))
6993 # verify events in data set
6994 for p in capture:
6995 if p.haslayer(Data):
6996 data = ipfix.decode_data_set(p.getlayer(Set))
6997 self.verify_ipfix_max_fragments_ip6(data, 0,
6998 self.pg0.remote_ip6n)
6999
7000 def test_ipfix_bib_ses(self):
7001 """ IPFIX logging NAT64 BIB/session create and delete events """
7002 self.tcp_port_in = random.randint(1025, 65535)
7003 remote_host_ip6 = self.compose_ip6(self.pg1.remote_ip4,
7004 '64:ff9b::',
7005 96)
7006
7007 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7008 self.nat_addr_n)
7009 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7010 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7011 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
7012 src_address=self.pg3.local_ip4n,
7013 path_mtu=512,
7014 template_interval=10)
7015 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
7016 src_port=self.ipfix_src_port)
7017
7018 # Create
7019 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7020 IPv6(src=self.pg0.remote_ip6, dst=remote_host_ip6) /
7021 TCP(sport=self.tcp_port_in, dport=25))
7022 self.pg0.add_stream(p)
7023 self.pg_enable_capture(self.pg_interfaces)
7024 self.pg_start()
7025 p = self.pg1.get_capture(1)
7026 self.tcp_port_out = p[0][TCP].sport
7027 self.vapi.cli("ipfix flush") # FIXME this should be an API call
7028 capture = self.pg3.get_capture(10)
7029 ipfix = IPFIXDecoder()
7030 # first load template
7031 for p in capture:
7032 self.assertTrue(p.haslayer(IPFIX))
7033 self.assertEqual(p[IP].src, self.pg3.local_ip4)
7034 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
7035 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
7036 self.assertEqual(p[UDP].dport, 4739)
7037 self.assertEqual(p[IPFIX].observationDomainID,
7038 self.ipfix_domain_id)
7039 if p.haslayer(Template):
7040 ipfix.add_template(p.getlayer(Template))
7041 # verify events in data set
7042 for p in capture:
7043 if p.haslayer(Data):
7044 data = ipfix.decode_data_set(p.getlayer(Set))
7045 if ord(data[0][230]) == 10:
7046 self.verify_ipfix_bib(data, 1, self.pg0.remote_ip6n)
7047 elif ord(data[0][230]) == 6:
7048 self.verify_ipfix_nat64_ses(data,
7049 1,
7050 self.pg0.remote_ip6n,
7051 self.pg1.remote_ip4,
7052 25)
7053 else:
7054 self.logger.error(ppp("Unexpected or invalid packet: ", p))
7055
7056 # Delete
7057 self.pg_enable_capture(self.pg_interfaces)
7058 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7059 self.nat_addr_n,
7060 is_add=0)
7061 self.vapi.cli("ipfix flush") # FIXME this should be an API call
7062 capture = self.pg3.get_capture(2)
7063 # verify events in data set
7064 for p in capture:
7065 self.assertTrue(p.haslayer(IPFIX))
7066 self.assertEqual(p[IP].src, self.pg3.local_ip4)
7067 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
7068 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
7069 self.assertEqual(p[UDP].dport, 4739)
7070 self.assertEqual(p[IPFIX].observationDomainID,
7071 self.ipfix_domain_id)
7072 if p.haslayer(Data):
7073 data = ipfix.decode_data_set(p.getlayer(Set))
7074 if ord(data[0][230]) == 11:
7075 self.verify_ipfix_bib(data, 0, self.pg0.remote_ip6n)
7076 elif ord(data[0][230]) == 7:
7077 self.verify_ipfix_nat64_ses(data,
7078 0,
7079 self.pg0.remote_ip6n,
7080 self.pg1.remote_ip4,
7081 25)
7082 else:
7083 self.logger.error(ppp("Unexpected or invalid packet: ", p))
7084
Matus Fabian06596c52017-06-06 04:53:28 -07007085 def nat64_get_ses_num(self):
7086 """
7087 Return number of active NAT64 sessions.
7088 """
Matus Fabianab9a59c2017-08-16 05:37:36 -07007089 st = self.vapi.nat64_st_dump()
7090 return len(st)
Matus Fabian06596c52017-06-06 04:53:28 -07007091
7092 def clear_nat64(self):
7093 """
7094 Clear NAT64 configuration.
7095 """
Matus Fabiana431ad12018-01-04 04:03:14 -08007096 self.vapi.nat_ipfix(enable=0, src_port=self.ipfix_src_port,
7097 domain_id=self.ipfix_domain_id)
7098 self.ipfix_src_port = 4739
7099 self.ipfix_domain_id = 1
7100
Matus Fabian878c6462018-08-23 00:33:35 -07007101 self.vapi.nat_set_timeouts()
Matus Fabian06596c52017-06-06 04:53:28 -07007102
7103 interfaces = self.vapi.nat64_interface_dump()
7104 for intf in interfaces:
Matus Fabian36ea2d62017-10-24 04:13:49 -07007105 if intf.is_inside > 1:
7106 self.vapi.nat64_add_del_interface(intf.sw_if_index,
7107 0,
7108 is_add=0)
Matus Fabian06596c52017-06-06 04:53:28 -07007109 self.vapi.nat64_add_del_interface(intf.sw_if_index,
7110 intf.is_inside,
7111 is_add=0)
7112
Matus Fabiana431ad12018-01-04 04:03:14 -08007113 bib = self.vapi.nat64_bib_dump(255)
Matus Fabian06596c52017-06-06 04:53:28 -07007114 for bibe in bib:
7115 if bibe.is_static:
7116 self.vapi.nat64_add_del_static_bib(bibe.i_addr,
7117 bibe.o_addr,
7118 bibe.i_port,
7119 bibe.o_port,
7120 bibe.proto,
7121 bibe.vrf_id,
7122 is_add=0)
7123
7124 adresses = self.vapi.nat64_pool_addr_dump()
7125 for addr in adresses:
7126 self.vapi.nat64_add_del_pool_addr_range(addr.address,
7127 addr.address,
Matus Fabian029f3d22017-06-15 02:28:50 -07007128 vrf_id=addr.vrf_id,
Matus Fabian06596c52017-06-06 04:53:28 -07007129 is_add=0)
7130
Matus Fabian428dc912017-06-21 06:15:18 -07007131 prefixes = self.vapi.nat64_prefix_dump()
7132 for prefix in prefixes:
7133 self.vapi.nat64_add_del_prefix(prefix.prefix,
7134 prefix.prefix_len,
7135 vrf_id=prefix.vrf_id,
7136 is_add=0)
7137
Matus Fabian06596c52017-06-06 04:53:28 -07007138 def tearDown(self):
7139 super(TestNAT64, self).tearDown()
7140 if not self.vpp_dead:
7141 self.logger.info(self.vapi.cli("show nat64 pool"))
7142 self.logger.info(self.vapi.cli("show nat64 interfaces"))
Matus Fabian428dc912017-06-21 06:15:18 -07007143 self.logger.info(self.vapi.cli("show nat64 prefix"))
Matus Fabianab9a59c2017-08-16 05:37:36 -07007144 self.logger.info(self.vapi.cli("show nat64 bib all"))
7145 self.logger.info(self.vapi.cli("show nat64 session table all"))
Matus Fabianefcd1e92017-08-15 06:59:19 -07007146 self.logger.info(self.vapi.cli("show nat virtual-reassembly"))
Matus Fabian06596c52017-06-06 04:53:28 -07007147 self.clear_nat64()
7148
Matus Fabian8ebe6252017-11-06 05:04:53 -08007149
7150class TestDSlite(MethodHolder):
7151 """ DS-Lite Test Cases """
7152
7153 @classmethod
7154 def setUpClass(cls):
7155 super(TestDSlite, cls).setUpClass()
7156
7157 try:
7158 cls.nat_addr = '10.0.0.3'
7159 cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
7160
7161 cls.create_pg_interfaces(range(2))
7162 cls.pg0.admin_up()
7163 cls.pg0.config_ip4()
7164 cls.pg0.resolve_arp()
7165 cls.pg1.admin_up()
7166 cls.pg1.config_ip6()
7167 cls.pg1.generate_remote_hosts(2)
7168 cls.pg1.configure_ipv6_neighbors()
7169
7170 except Exception:
7171 super(TestDSlite, cls).tearDownClass()
7172 raise
7173
7174 def test_dslite(self):
7175 """ Test DS-Lite """
Matus Fabian69ce30d2018-08-22 01:27:10 -07007176 nat_config = self.vapi.nat_show_config()
7177 self.assertEqual(0, nat_config.dslite_ce)
7178
Matus Fabian8ebe6252017-11-06 05:04:53 -08007179 self.vapi.dslite_add_del_pool_addr_range(self.nat_addr_n,
7180 self.nat_addr_n)
7181 aftr_ip4 = '192.0.0.1'
7182 aftr_ip4_n = socket.inet_pton(socket.AF_INET, aftr_ip4)
7183 aftr_ip6 = '2001:db8:85a3::8a2e:370:1'
7184 aftr_ip6_n = socket.inet_pton(socket.AF_INET6, aftr_ip6)
7185 self.vapi.dslite_set_aftr_addr(aftr_ip6_n, aftr_ip4_n)
7186
7187 # UDP
7188 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
7189 IPv6(dst=aftr_ip6, src=self.pg1.remote_hosts[0].ip6) /
7190 IP(dst=self.pg0.remote_ip4, src='192.168.1.1') /
7191 UDP(sport=20000, dport=10000))
7192 self.pg1.add_stream(p)
7193 self.pg_enable_capture(self.pg_interfaces)
7194 self.pg_start()
7195 capture = self.pg0.get_capture(1)
7196 capture = capture[0]
7197 self.assertFalse(capture.haslayer(IPv6))
7198 self.assertEqual(capture[IP].src, self.nat_addr)
7199 self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
7200 self.assertNotEqual(capture[UDP].sport, 20000)
7201 self.assertEqual(capture[UDP].dport, 10000)
Klement Sekerad81ae412018-05-16 10:52:54 +02007202 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08007203 out_port = capture[UDP].sport
7204
7205 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7206 IP(dst=self.nat_addr, src=self.pg0.remote_ip4) /
7207 UDP(sport=10000, dport=out_port))
7208 self.pg0.add_stream(p)
7209 self.pg_enable_capture(self.pg_interfaces)
7210 self.pg_start()
7211 capture = self.pg1.get_capture(1)
7212 capture = capture[0]
7213 self.assertEqual(capture[IPv6].src, aftr_ip6)
7214 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[0].ip6)
7215 self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
7216 self.assertEqual(capture[IP].dst, '192.168.1.1')
7217 self.assertEqual(capture[UDP].sport, 10000)
7218 self.assertEqual(capture[UDP].dport, 20000)
Klement Sekerad81ae412018-05-16 10:52:54 +02007219 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08007220
7221 # TCP
7222 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
7223 IPv6(dst=aftr_ip6, src=self.pg1.remote_hosts[1].ip6) /
7224 IP(dst=self.pg0.remote_ip4, src='192.168.1.1') /
7225 TCP(sport=20001, dport=10001))
7226 self.pg1.add_stream(p)
7227 self.pg_enable_capture(self.pg_interfaces)
7228 self.pg_start()
7229 capture = self.pg0.get_capture(1)
7230 capture = capture[0]
7231 self.assertFalse(capture.haslayer(IPv6))
7232 self.assertEqual(capture[IP].src, self.nat_addr)
7233 self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
7234 self.assertNotEqual(capture[TCP].sport, 20001)
7235 self.assertEqual(capture[TCP].dport, 10001)
Klement Sekerad81ae412018-05-16 10:52:54 +02007236 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08007237 out_port = capture[TCP].sport
7238
7239 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7240 IP(dst=self.nat_addr, src=self.pg0.remote_ip4) /
7241 TCP(sport=10001, dport=out_port))
7242 self.pg0.add_stream(p)
7243 self.pg_enable_capture(self.pg_interfaces)
7244 self.pg_start()
7245 capture = self.pg1.get_capture(1)
7246 capture = capture[0]
7247 self.assertEqual(capture[IPv6].src, aftr_ip6)
7248 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[1].ip6)
7249 self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
7250 self.assertEqual(capture[IP].dst, '192.168.1.1')
7251 self.assertEqual(capture[TCP].sport, 10001)
7252 self.assertEqual(capture[TCP].dport, 20001)
Klement Sekerad81ae412018-05-16 10:52:54 +02007253 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08007254
7255 # ICMP
7256 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
7257 IPv6(dst=aftr_ip6, src=self.pg1.remote_hosts[1].ip6) /
7258 IP(dst=self.pg0.remote_ip4, src='192.168.1.1') /
7259 ICMP(id=4000, type='echo-request'))
7260 self.pg1.add_stream(p)
7261 self.pg_enable_capture(self.pg_interfaces)
7262 self.pg_start()
7263 capture = self.pg0.get_capture(1)
7264 capture = capture[0]
7265 self.assertFalse(capture.haslayer(IPv6))
7266 self.assertEqual(capture[IP].src, self.nat_addr)
7267 self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
7268 self.assertNotEqual(capture[ICMP].id, 4000)
Klement Sekerad81ae412018-05-16 10:52:54 +02007269 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08007270 out_id = capture[ICMP].id
7271
7272 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7273 IP(dst=self.nat_addr, src=self.pg0.remote_ip4) /
7274 ICMP(id=out_id, type='echo-reply'))
7275 self.pg0.add_stream(p)
7276 self.pg_enable_capture(self.pg_interfaces)
7277 self.pg_start()
7278 capture = self.pg1.get_capture(1)
7279 capture = capture[0]
7280 self.assertEqual(capture[IPv6].src, aftr_ip6)
7281 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[1].ip6)
7282 self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
7283 self.assertEqual(capture[IP].dst, '192.168.1.1')
7284 self.assertEqual(capture[ICMP].id, 4000)
Klement Sekerad81ae412018-05-16 10:52:54 +02007285 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08007286
Matus Fabian331acc62017-12-08 03:38:51 -08007287 # ping DS-Lite AFTR tunnel endpoint address
7288 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
7289 IPv6(src=self.pg1.remote_hosts[1].ip6, dst=aftr_ip6) /
7290 ICMPv6EchoRequest())
7291 self.pg1.add_stream(p)
7292 self.pg_enable_capture(self.pg_interfaces)
7293 self.pg_start()
7294 capture = self.pg1.get_capture(1)
7295 self.assertEqual(1, len(capture))
7296 capture = capture[0]
7297 self.assertEqual(capture[IPv6].src, aftr_ip6)
7298 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[1].ip6)
7299 self.assertTrue(capture.haslayer(ICMPv6EchoReply))
7300
Matus Fabian8ebe6252017-11-06 05:04:53 -08007301 def tearDown(self):
7302 super(TestDSlite, self).tearDown()
7303 if not self.vpp_dead:
7304 self.logger.info(self.vapi.cli("show dslite pool"))
7305 self.logger.info(
7306 self.vapi.cli("show dslite aftr-tunnel-endpoint-address"))
7307 self.logger.info(self.vapi.cli("show dslite sessions"))
7308
Juraj Slobodac5c6a332018-01-09 16:08:32 +01007309
7310class TestDSliteCE(MethodHolder):
7311 """ DS-Lite CE Test Cases """
7312
7313 @classmethod
7314 def setUpConstants(cls):
7315 super(TestDSliteCE, cls).setUpConstants()
7316 cls.vpp_cmdline.extend(["nat", "{", "dslite ce", "}"])
7317
7318 @classmethod
7319 def setUpClass(cls):
7320 super(TestDSliteCE, cls).setUpClass()
7321
7322 try:
7323 cls.create_pg_interfaces(range(2))
7324 cls.pg0.admin_up()
7325 cls.pg0.config_ip4()
7326 cls.pg0.resolve_arp()
7327 cls.pg1.admin_up()
7328 cls.pg1.config_ip6()
7329 cls.pg1.generate_remote_hosts(1)
7330 cls.pg1.configure_ipv6_neighbors()
7331
7332 except Exception:
7333 super(TestDSliteCE, cls).tearDownClass()
7334 raise
7335
7336 def test_dslite_ce(self):
7337 """ Test DS-Lite CE """
7338
Matus Fabian69ce30d2018-08-22 01:27:10 -07007339 nat_config = self.vapi.nat_show_config()
7340 self.assertEqual(1, nat_config.dslite_ce)
7341
Juraj Slobodac5c6a332018-01-09 16:08:32 +01007342 b4_ip4 = '192.0.0.2'
7343 b4_ip4_n = socket.inet_pton(socket.AF_INET, b4_ip4)
7344 b4_ip6 = '2001:db8:62aa::375e:f4c1:1'
7345 b4_ip6_n = socket.inet_pton(socket.AF_INET6, b4_ip6)
7346 self.vapi.dslite_set_b4_addr(b4_ip6_n, b4_ip4_n)
7347
7348 aftr_ip4 = '192.0.0.1'
7349 aftr_ip4_n = socket.inet_pton(socket.AF_INET, aftr_ip4)
7350 aftr_ip6 = '2001:db8:85a3::8a2e:370:1'
7351 aftr_ip6_n = socket.inet_pton(socket.AF_INET6, aftr_ip6)
7352 self.vapi.dslite_set_aftr_addr(aftr_ip6_n, aftr_ip4_n)
7353
7354 self.vapi.ip_add_del_route(dst_address=aftr_ip6_n,
7355 dst_address_length=128,
7356 next_hop_address=self.pg1.remote_ip6n,
7357 next_hop_sw_if_index=self.pg1.sw_if_index,
7358 is_ipv6=1)
7359
7360 # UDP encapsulation
7361 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7362 IP(dst=self.pg1.remote_ip4, src=self.pg0.remote_ip4) /
7363 UDP(sport=10000, dport=20000))
7364 self.pg0.add_stream(p)
7365 self.pg_enable_capture(self.pg_interfaces)
7366 self.pg_start()
7367 capture = self.pg1.get_capture(1)
7368 capture = capture[0]
7369 self.assertEqual(capture[IPv6].src, b4_ip6)
7370 self.assertEqual(capture[IPv6].dst, aftr_ip6)
7371 self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
7372 self.assertEqual(capture[IP].dst, self.pg1.remote_ip4)
7373 self.assertEqual(capture[UDP].sport, 10000)
7374 self.assertEqual(capture[UDP].dport, 20000)
Klement Sekerad81ae412018-05-16 10:52:54 +02007375 self.assert_packet_checksums_valid(capture)
Juraj Slobodac5c6a332018-01-09 16:08:32 +01007376
7377 # UDP decapsulation
7378 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
7379 IPv6(dst=b4_ip6, src=aftr_ip6) /
7380 IP(dst=self.pg0.remote_ip4, src=self.pg1.remote_ip4) /
7381 UDP(sport=20000, dport=10000))
7382 self.pg1.add_stream(p)
7383 self.pg_enable_capture(self.pg_interfaces)
7384 self.pg_start()
7385 capture = self.pg0.get_capture(1)
7386 capture = capture[0]
7387 self.assertFalse(capture.haslayer(IPv6))
7388 self.assertEqual(capture[IP].src, self.pg1.remote_ip4)
7389 self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
7390 self.assertEqual(capture[UDP].sport, 20000)
7391 self.assertEqual(capture[UDP].dport, 10000)
Klement Sekerad81ae412018-05-16 10:52:54 +02007392 self.assert_packet_checksums_valid(capture)
Juraj Slobodac5c6a332018-01-09 16:08:32 +01007393
7394 # ping DS-Lite B4 tunnel endpoint address
7395 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
7396 IPv6(src=self.pg1.remote_hosts[0].ip6, dst=b4_ip6) /
7397 ICMPv6EchoRequest())
7398 self.pg1.add_stream(p)
7399 self.pg_enable_capture(self.pg_interfaces)
7400 self.pg_start()
7401 capture = self.pg1.get_capture(1)
7402 self.assertEqual(1, len(capture))
7403 capture = capture[0]
7404 self.assertEqual(capture[IPv6].src, b4_ip6)
7405 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[0].ip6)
7406 self.assertTrue(capture.haslayer(ICMPv6EchoReply))
7407
7408 def tearDown(self):
7409 super(TestDSliteCE, self).tearDown()
7410 if not self.vpp_dead:
7411 self.logger.info(
7412 self.vapi.cli("show dslite aftr-tunnel-endpoint-address"))
7413 self.logger.info(
7414 self.vapi.cli("show dslite b4-tunnel-endpoint-address"))
7415
Matus Fabianf2a23cc2018-01-22 03:41:53 -08007416
7417class TestNAT66(MethodHolder):
7418 """ NAT66 Test Cases """
7419
7420 @classmethod
7421 def setUpClass(cls):
7422 super(TestNAT66, cls).setUpClass()
7423
7424 try:
7425 cls.nat_addr = 'fd01:ff::2'
7426 cls.nat_addr_n = socket.inet_pton(socket.AF_INET6, cls.nat_addr)
7427
7428 cls.create_pg_interfaces(range(2))
7429 cls.interfaces = list(cls.pg_interfaces)
7430
7431 for i in cls.interfaces:
7432 i.admin_up()
7433 i.config_ip6()
7434 i.configure_ipv6_neighbors()
7435
7436 except Exception:
7437 super(TestNAT66, cls).tearDownClass()
7438 raise
7439
7440 def test_static(self):
7441 """ 1:1 NAT66 test """
7442 self.vapi.nat66_add_del_interface(self.pg0.sw_if_index)
7443 self.vapi.nat66_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7444 self.vapi.nat66_add_del_static_mapping(self.pg0.remote_ip6n,
7445 self.nat_addr_n)
7446
7447 # in2out
7448 pkts = []
7449 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7450 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
7451 TCP())
7452 pkts.append(p)
7453 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7454 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
7455 UDP())
7456 pkts.append(p)
7457 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7458 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
7459 ICMPv6EchoRequest())
7460 pkts.append(p)
7461 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7462 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
7463 GRE() / IP() / TCP())
7464 pkts.append(p)
7465 self.pg0.add_stream(pkts)
7466 self.pg_enable_capture(self.pg_interfaces)
7467 self.pg_start()
7468 capture = self.pg1.get_capture(len(pkts))
7469 for packet in capture:
7470 try:
7471 self.assertEqual(packet[IPv6].src, self.nat_addr)
7472 self.assertEqual(packet[IPv6].dst, self.pg1.remote_ip6)
Klement Sekerad81ae412018-05-16 10:52:54 +02007473 self.assert_packet_checksums_valid(packet)
Matus Fabianf2a23cc2018-01-22 03:41:53 -08007474 except:
7475 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7476 raise
7477
7478 # out2in
7479 pkts = []
7480 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
7481 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
7482 TCP())
7483 pkts.append(p)
7484 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
7485 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
7486 UDP())
7487 pkts.append(p)
7488 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
7489 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
7490 ICMPv6EchoReply())
7491 pkts.append(p)
7492 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
7493 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
7494 GRE() / IP() / TCP())
7495 pkts.append(p)
7496 self.pg1.add_stream(pkts)
7497 self.pg_enable_capture(self.pg_interfaces)
7498 self.pg_start()
7499 capture = self.pg0.get_capture(len(pkts))
7500 for packet in capture:
7501 try:
7502 self.assertEqual(packet[IPv6].src, self.pg1.remote_ip6)
7503 self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
Klement Sekerad81ae412018-05-16 10:52:54 +02007504 self.assert_packet_checksums_valid(packet)
Matus Fabianf2a23cc2018-01-22 03:41:53 -08007505 except:
7506 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7507 raise
7508
7509 sm = self.vapi.nat66_static_mapping_dump()
7510 self.assertEqual(len(sm), 1)
7511 self.assertEqual(sm[0].total_pkts, 8)
7512
Juraj Sloboda9341e342018-04-13 12:00:46 +02007513 def test_check_no_translate(self):
7514 """ NAT66 translate only when egress interface is outside interface """
7515 self.vapi.nat66_add_del_interface(self.pg0.sw_if_index)
7516 self.vapi.nat66_add_del_interface(self.pg1.sw_if_index)
7517 self.vapi.nat66_add_del_static_mapping(self.pg0.remote_ip6n,
7518 self.nat_addr_n)
7519
7520 # in2out
7521 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7522 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
7523 UDP())
7524 self.pg0.add_stream([p])
7525 self.pg_enable_capture(self.pg_interfaces)
7526 self.pg_start()
7527 capture = self.pg1.get_capture(1)
7528 packet = capture[0]
7529 try:
7530 self.assertEqual(packet[IPv6].src, self.pg0.remote_ip6)
7531 self.assertEqual(packet[IPv6].dst, self.pg1.remote_ip6)
7532 except:
7533 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7534 raise
7535
Matus Fabianf2a23cc2018-01-22 03:41:53 -08007536 def clear_nat66(self):
7537 """
7538 Clear NAT66 configuration.
7539 """
7540 interfaces = self.vapi.nat66_interface_dump()
7541 for intf in interfaces:
7542 self.vapi.nat66_add_del_interface(intf.sw_if_index,
7543 intf.is_inside,
7544 is_add=0)
7545
7546 static_mappings = self.vapi.nat66_static_mapping_dump()
7547 for sm in static_mappings:
7548 self.vapi.nat66_add_del_static_mapping(sm.local_ip_address,
7549 sm.external_ip_address,
7550 sm.vrf_id,
7551 is_add=0)
7552
7553 def tearDown(self):
7554 super(TestNAT66, self).tearDown()
7555 if not self.vpp_dead:
7556 self.logger.info(self.vapi.cli("show nat66 interfaces"))
7557 self.logger.info(self.vapi.cli("show nat66 static mappings"))
7558 self.clear_nat66()
7559
Klement Sekerad81ae412018-05-16 10:52:54 +02007560
Matus Fabiande886752016-12-07 03:38:19 -08007561if __name__ == '__main__':
7562 unittest.main(testRunner=VppTestRunner)