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