blob: 286c74a8037a4d88c0a532abf5e68816273d8bc9 [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 Fabiana6110b62018-06-13 05:39:07 -0700140
141 def nat44_add_static_mapping(self, local_ip, external_ip='0.0.0.0',
142 local_port=0, external_port=0, vrf_id=0,
143 is_add=1, external_sw_if_index=0xFFFFFFFF,
144 proto=0, twice_nat=0, self_twice_nat=0,
145 out2in_only=0, tag=""):
146 """
147 Add/delete NAT44 static mapping
148
149 :param local_ip: Local IP address
150 :param external_ip: External IP address
151 :param local_port: Local port number (Optional)
152 :param external_port: External port number (Optional)
153 :param vrf_id: VRF ID (Default 0)
154 :param is_add: 1 if add, 0 if delete (Default add)
155 :param external_sw_if_index: External interface instead of IP address
156 :param proto: IP protocol (Mandatory if port specified)
157 :param twice_nat: 1 if translate external host address and port
158 :param self_twice_nat: 1 if translate external host address and port
159 whenever external host address equals
160 local address of internal host
161 :param out2in_only: if 1 rule is matching only out2in direction
162 :param tag: Opaque string tag
163 """
164 addr_only = 1
165 if local_port and external_port:
166 addr_only = 0
167 l_ip = socket.inet_pton(socket.AF_INET, local_ip)
168 e_ip = socket.inet_pton(socket.AF_INET, external_ip)
169 self.vapi.nat44_add_del_static_mapping(
170 l_ip,
171 e_ip,
172 external_sw_if_index,
173 local_port,
174 external_port,
175 addr_only,
176 vrf_id,
177 proto,
178 twice_nat,
179 self_twice_nat,
180 out2in_only,
181 tag,
182 is_add)
183
184 def nat44_add_address(self, ip, is_add=1, vrf_id=0xFFFFFFFF, twice_nat=0):
185 """
186 Add/delete NAT44 address
187
188 :param ip: IP address
189 :param is_add: 1 if add, 0 if delete (Default add)
190 :param twice_nat: twice NAT address for extenal hosts
191 """
192 nat_addr = socket.inet_pton(socket.AF_INET, ip)
193 self.vapi.nat44_add_del_address_range(nat_addr, nat_addr, is_add,
194 vrf_id=vrf_id,
195 twice_nat=twice_nat)
196
Juraj Slobodacba69362017-12-19 02:09:32 +0100197 def create_stream_in(self, in_if, out_if, dst_ip=None, ttl=64):
Matus Fabiande886752016-12-07 03:38:19 -0800198 """
199 Create packet stream for inside network
200
201 :param in_if: Inside interface
202 :param out_if: Outside interface
Juraj Slobodacba69362017-12-19 02:09:32 +0100203 :param dst_ip: Destination address
Juraj Slobodab33f4132017-02-08 23:54:21 -0800204 :param ttl: TTL of generated packets
Matus Fabiande886752016-12-07 03:38:19 -0800205 """
Juraj Slobodacba69362017-12-19 02:09:32 +0100206 if dst_ip is None:
207 dst_ip = out_if.remote_ip4
208
Matus Fabiande886752016-12-07 03:38:19 -0800209 pkts = []
210 # TCP
211 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
Juraj Slobodacba69362017-12-19 02:09:32 +0100212 IP(src=in_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Matus Fabian06596c52017-06-06 04:53:28 -0700213 TCP(sport=self.tcp_port_in, dport=20))
Matus Fabiande886752016-12-07 03:38:19 -0800214 pkts.append(p)
215
216 # UDP
217 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
Juraj Slobodacba69362017-12-19 02:09:32 +0100218 IP(src=in_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Matus Fabian06596c52017-06-06 04:53:28 -0700219 UDP(sport=self.udp_port_in, dport=20))
Matus Fabiande886752016-12-07 03:38:19 -0800220 pkts.append(p)
221
222 # ICMP
223 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
Juraj Slobodacba69362017-12-19 02:09:32 +0100224 IP(src=in_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Matus Fabiande886752016-12-07 03:38:19 -0800225 ICMP(id=self.icmp_id_in, type='echo-request'))
226 pkts.append(p)
227
228 return pkts
229
Matus Fabian428dc912017-06-21 06:15:18 -0700230 def compose_ip6(self, ip4, pref, plen):
231 """
232 Compose IPv4-embedded IPv6 addresses
233
234 :param ip4: IPv4 address
235 :param pref: IPv6 prefix
236 :param plen: IPv6 prefix length
237 :returns: IPv4-embedded IPv6 addresses
238 """
239 pref_n = list(socket.inet_pton(socket.AF_INET6, pref))
240 ip4_n = list(socket.inet_pton(socket.AF_INET, ip4))
241 if plen == 32:
242 pref_n[4] = ip4_n[0]
243 pref_n[5] = ip4_n[1]
244 pref_n[6] = ip4_n[2]
245 pref_n[7] = ip4_n[3]
246 elif plen == 40:
247 pref_n[5] = ip4_n[0]
248 pref_n[6] = ip4_n[1]
249 pref_n[7] = ip4_n[2]
250 pref_n[9] = ip4_n[3]
251 elif plen == 48:
252 pref_n[6] = ip4_n[0]
253 pref_n[7] = ip4_n[1]
254 pref_n[9] = ip4_n[2]
255 pref_n[10] = ip4_n[3]
256 elif plen == 56:
257 pref_n[7] = ip4_n[0]
258 pref_n[9] = ip4_n[1]
259 pref_n[10] = ip4_n[2]
260 pref_n[11] = ip4_n[3]
261 elif plen == 64:
262 pref_n[9] = ip4_n[0]
263 pref_n[10] = ip4_n[1]
264 pref_n[11] = ip4_n[2]
265 pref_n[12] = ip4_n[3]
266 elif plen == 96:
267 pref_n[12] = ip4_n[0]
268 pref_n[13] = ip4_n[1]
269 pref_n[14] = ip4_n[2]
270 pref_n[15] = ip4_n[3]
271 return socket.inet_ntop(socket.AF_INET6, ''.join(pref_n))
272
Juraj Slobodacba69362017-12-19 02:09:32 +0100273 def extract_ip4(self, ip6, plen):
274 """
275 Extract IPv4 address embedded in IPv6 addresses
276
277 :param ip6: IPv6 address
278 :param plen: IPv6 prefix length
279 :returns: extracted IPv4 address
280 """
281 ip6_n = list(socket.inet_pton(socket.AF_INET6, ip6))
282 ip4_n = [None] * 4
283 if plen == 32:
284 ip4_n[0] = ip6_n[4]
285 ip4_n[1] = ip6_n[5]
286 ip4_n[2] = ip6_n[6]
287 ip4_n[3] = ip6_n[7]
288 elif plen == 40:
289 ip4_n[0] = ip6_n[5]
290 ip4_n[1] = ip6_n[6]
291 ip4_n[2] = ip6_n[7]
292 ip4_n[3] = ip6_n[9]
293 elif plen == 48:
294 ip4_n[0] = ip6_n[6]
295 ip4_n[1] = ip6_n[7]
296 ip4_n[2] = ip6_n[9]
297 ip4_n[3] = ip6_n[10]
298 elif plen == 56:
299 ip4_n[0] = ip6_n[7]
300 ip4_n[1] = ip6_n[9]
301 ip4_n[2] = ip6_n[10]
302 ip4_n[3] = ip6_n[11]
303 elif plen == 64:
304 ip4_n[0] = ip6_n[9]
305 ip4_n[1] = ip6_n[10]
306 ip4_n[2] = ip6_n[11]
307 ip4_n[3] = ip6_n[12]
308 elif plen == 96:
309 ip4_n[0] = ip6_n[12]
310 ip4_n[1] = ip6_n[13]
311 ip4_n[2] = ip6_n[14]
312 ip4_n[3] = ip6_n[15]
313 return socket.inet_ntop(socket.AF_INET, ''.join(ip4_n))
314
Matus Fabian428dc912017-06-21 06:15:18 -0700315 def create_stream_in_ip6(self, in_if, out_if, hlim=64, pref=None, plen=0):
Matus Fabian06596c52017-06-06 04:53:28 -0700316 """
317 Create IPv6 packet stream for inside network
318
319 :param in_if: Inside interface
320 :param out_if: Outside interface
321 :param ttl: Hop Limit of generated packets
Matus Fabian428dc912017-06-21 06:15:18 -0700322 :param pref: NAT64 prefix
323 :param plen: NAT64 prefix length
Matus Fabian06596c52017-06-06 04:53:28 -0700324 """
325 pkts = []
Matus Fabian428dc912017-06-21 06:15:18 -0700326 if pref is None:
327 dst = ''.join(['64:ff9b::', out_if.remote_ip4])
328 else:
329 dst = self.compose_ip6(out_if.remote_ip4, pref, plen)
330
Matus Fabian06596c52017-06-06 04:53:28 -0700331 # TCP
332 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
333 IPv6(src=in_if.remote_ip6, dst=dst, hlim=hlim) /
334 TCP(sport=self.tcp_port_in, dport=20))
335 pkts.append(p)
336
337 # UDP
338 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
339 IPv6(src=in_if.remote_ip6, dst=dst, hlim=hlim) /
340 UDP(sport=self.udp_port_in, dport=20))
341 pkts.append(p)
342
343 # ICMP
344 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
345 IPv6(src=in_if.remote_ip6, dst=dst, hlim=hlim) /
346 ICMPv6EchoRequest(id=self.icmp_id_in))
347 pkts.append(p)
348
349 return pkts
350
Juraj Sloboda7b929792017-11-23 13:20:48 +0100351 def create_stream_out(self, out_if, dst_ip=None, ttl=64,
352 use_inside_ports=False):
Matus Fabiande886752016-12-07 03:38:19 -0800353 """
354 Create packet stream for outside network
355
356 :param out_if: Outside interface
Matus Fabian2ba92e32017-08-21 07:05:03 -0700357 :param dst_ip: Destination IP address (Default use global NAT address)
Juraj Slobodab33f4132017-02-08 23:54:21 -0800358 :param ttl: TTL of generated packets
Juraj Sloboda7b929792017-11-23 13:20:48 +0100359 :param use_inside_ports: Use inside NAT ports as destination ports
360 instead of outside ports
Matus Fabiande886752016-12-07 03:38:19 -0800361 """
362 if dst_ip is None:
Matus Fabian2ba92e32017-08-21 07:05:03 -0700363 dst_ip = self.nat_addr
Juraj Sloboda7b929792017-11-23 13:20:48 +0100364 if not use_inside_ports:
365 tcp_port = self.tcp_port_out
366 udp_port = self.udp_port_out
367 icmp_id = self.icmp_id_out
368 else:
369 tcp_port = self.tcp_port_in
370 udp_port = self.udp_port_in
371 icmp_id = self.icmp_id_in
Matus Fabiande886752016-12-07 03:38:19 -0800372 pkts = []
373 # TCP
374 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
Juraj Slobodab33f4132017-02-08 23:54:21 -0800375 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Juraj Sloboda7b929792017-11-23 13:20:48 +0100376 TCP(dport=tcp_port, sport=20))
Matus Fabiande886752016-12-07 03:38:19 -0800377 pkts.append(p)
378
379 # UDP
380 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
Juraj Slobodab33f4132017-02-08 23:54:21 -0800381 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Juraj Sloboda7b929792017-11-23 13:20:48 +0100382 UDP(dport=udp_port, sport=20))
Matus Fabiande886752016-12-07 03:38:19 -0800383 pkts.append(p)
384
385 # ICMP
386 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
Juraj Slobodab33f4132017-02-08 23:54:21 -0800387 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Juraj Sloboda7b929792017-11-23 13:20:48 +0100388 ICMP(id=icmp_id, type='echo-reply'))
Matus Fabiande886752016-12-07 03:38:19 -0800389 pkts.append(p)
390
391 return pkts
392
Juraj Slobodacba69362017-12-19 02:09:32 +0100393 def create_stream_out_ip6(self, out_if, src_ip, dst_ip, hl=64):
394 """
395 Create packet stream for outside network
396
397 :param out_if: Outside interface
398 :param dst_ip: Destination IP address (Default use global NAT address)
399 :param hl: HL of generated packets
400 """
401 pkts = []
402 # TCP
403 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
404 IPv6(src=src_ip, dst=dst_ip, hlim=hl) /
405 TCP(dport=self.tcp_port_out, sport=20))
406 pkts.append(p)
407
408 # UDP
409 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
410 IPv6(src=src_ip, dst=dst_ip, hlim=hl) /
411 UDP(dport=self.udp_port_out, sport=20))
412 pkts.append(p)
413
414 # ICMP
415 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
416 IPv6(src=src_ip, dst=dst_ip, hlim=hl) /
417 ICMPv6EchoReply(id=self.icmp_id_out))
418 pkts.append(p)
419
420 return pkts
421
Matus Fabiande886752016-12-07 03:38:19 -0800422 def verify_capture_out(self, capture, nat_ip=None, same_port=False,
Juraj Slobodacba69362017-12-19 02:09:32 +0100423 packet_num=3, dst_ip=None, is_ip6=False):
Matus Fabiande886752016-12-07 03:38:19 -0800424 """
425 Verify captured packets on outside network
426
427 :param capture: Captured packets
Matus Fabian2ba92e32017-08-21 07:05:03 -0700428 :param nat_ip: Translated IP address (Default use global NAT address)
Matus Fabiande886752016-12-07 03:38:19 -0800429 :param same_port: Sorce port number is not translated (Default False)
430 :param packet_num: Expected number of packets (Default 3)
Matus Fabian06596c52017-06-06 04:53:28 -0700431 :param dst_ip: Destination IP address (Default do not verify)
Juraj Slobodacba69362017-12-19 02:09:32 +0100432 :param is_ip6: If L3 protocol is IPv6 (Default False)
Matus Fabiande886752016-12-07 03:38:19 -0800433 """
Juraj Slobodacba69362017-12-19 02:09:32 +0100434 if is_ip6:
435 IP46 = IPv6
436 ICMP46 = ICMPv6EchoRequest
437 else:
438 IP46 = IP
439 ICMP46 = ICMP
Matus Fabiande886752016-12-07 03:38:19 -0800440 if nat_ip is None:
Matus Fabian2ba92e32017-08-21 07:05:03 -0700441 nat_ip = self.nat_addr
Matus Fabiande886752016-12-07 03:38:19 -0800442 self.assertEqual(packet_num, len(capture))
443 for packet in capture:
444 try:
Juraj Slobodacba69362017-12-19 02:09:32 +0100445 if not is_ip6:
Klement Sekerad81ae412018-05-16 10:52:54 +0200446 self.assert_packet_checksums_valid(packet)
Juraj Slobodacba69362017-12-19 02:09:32 +0100447 self.assertEqual(packet[IP46].src, nat_ip)
Matus Fabian06596c52017-06-06 04:53:28 -0700448 if dst_ip is not None:
Juraj Slobodacba69362017-12-19 02:09:32 +0100449 self.assertEqual(packet[IP46].dst, dst_ip)
Matus Fabiande886752016-12-07 03:38:19 -0800450 if packet.haslayer(TCP):
451 if same_port:
452 self.assertEqual(packet[TCP].sport, self.tcp_port_in)
453 else:
Klement Sekerada505f62017-01-04 12:58:53 +0100454 self.assertNotEqual(
455 packet[TCP].sport, self.tcp_port_in)
Matus Fabiande886752016-12-07 03:38:19 -0800456 self.tcp_port_out = packet[TCP].sport
Klement Sekerad81ae412018-05-16 10:52:54 +0200457 self.assert_packet_checksums_valid(packet)
Matus Fabiande886752016-12-07 03:38:19 -0800458 elif packet.haslayer(UDP):
459 if same_port:
460 self.assertEqual(packet[UDP].sport, self.udp_port_in)
461 else:
Klement Sekerada505f62017-01-04 12:58:53 +0100462 self.assertNotEqual(
463 packet[UDP].sport, self.udp_port_in)
Matus Fabiande886752016-12-07 03:38:19 -0800464 self.udp_port_out = packet[UDP].sport
465 else:
466 if same_port:
Juraj Slobodacba69362017-12-19 02:09:32 +0100467 self.assertEqual(packet[ICMP46].id, self.icmp_id_in)
Matus Fabiande886752016-12-07 03:38:19 -0800468 else:
Juraj Slobodacba69362017-12-19 02:09:32 +0100469 self.assertNotEqual(packet[ICMP46].id, self.icmp_id_in)
470 self.icmp_id_out = packet[ICMP46].id
Klement Sekerad81ae412018-05-16 10:52:54 +0200471 self.assert_packet_checksums_valid(packet)
Matus Fabiande886752016-12-07 03:38:19 -0800472 except:
Klement Sekera9225dee2016-12-12 08:36:58 +0100473 self.logger.error(ppp("Unexpected or invalid packet "
474 "(outside network):", packet))
Matus Fabiande886752016-12-07 03:38:19 -0800475 raise
476
Juraj Slobodacba69362017-12-19 02:09:32 +0100477 def verify_capture_out_ip6(self, capture, nat_ip, same_port=False,
478 packet_num=3, dst_ip=None):
479 """
480 Verify captured packets on outside network
481
482 :param capture: Captured packets
483 :param nat_ip: Translated IP address
484 :param same_port: Sorce port number is not translated (Default False)
485 :param packet_num: Expected number of packets (Default 3)
486 :param dst_ip: Destination IP address (Default do not verify)
487 """
488 return self.verify_capture_out(capture, nat_ip, same_port, packet_num,
489 dst_ip, True)
490
Matus Fabiande886752016-12-07 03:38:19 -0800491 def verify_capture_in(self, capture, in_if, packet_num=3):
492 """
493 Verify captured packets on inside network
494
495 :param capture: Captured packets
496 :param in_if: Inside interface
497 :param packet_num: Expected number of packets (Default 3)
498 """
499 self.assertEqual(packet_num, len(capture))
500 for packet in capture:
501 try:
Klement Sekerad81ae412018-05-16 10:52:54 +0200502 self.assert_packet_checksums_valid(packet)
Matus Fabiande886752016-12-07 03:38:19 -0800503 self.assertEqual(packet[IP].dst, in_if.remote_ip4)
504 if packet.haslayer(TCP):
505 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
506 elif packet.haslayer(UDP):
507 self.assertEqual(packet[UDP].dport, self.udp_port_in)
508 else:
509 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
510 except:
Klement Sekera9225dee2016-12-12 08:36:58 +0100511 self.logger.error(ppp("Unexpected or invalid packet "
512 "(inside network):", packet))
Matus Fabiande886752016-12-07 03:38:19 -0800513 raise
514
Matus Fabian06596c52017-06-06 04:53:28 -0700515 def verify_capture_in_ip6(self, capture, src_ip, dst_ip, packet_num=3):
516 """
517 Verify captured IPv6 packets on inside network
518
519 :param capture: Captured packets
520 :param src_ip: Source IP
521 :param dst_ip: Destination IP address
522 :param packet_num: Expected number of packets (Default 3)
523 """
524 self.assertEqual(packet_num, len(capture))
525 for packet in capture:
526 try:
527 self.assertEqual(packet[IPv6].src, src_ip)
528 self.assertEqual(packet[IPv6].dst, dst_ip)
Klement Sekerad81ae412018-05-16 10:52:54 +0200529 self.assert_packet_checksums_valid(packet)
Matus Fabian06596c52017-06-06 04:53:28 -0700530 if packet.haslayer(TCP):
531 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
532 elif packet.haslayer(UDP):
533 self.assertEqual(packet[UDP].dport, self.udp_port_in)
534 else:
535 self.assertEqual(packet[ICMPv6EchoReply].id,
536 self.icmp_id_in)
537 except:
538 self.logger.error(ppp("Unexpected or invalid packet "
539 "(inside network):", packet))
540 raise
541
Matus Fabian675a69c2017-01-18 01:46:01 -0800542 def verify_capture_no_translation(self, capture, ingress_if, egress_if):
543 """
544 Verify captured packet that don't have to be translated
545
546 :param capture: Captured packets
547 :param ingress_if: Ingress interface
548 :param egress_if: Egress interface
549 """
550 for packet in capture:
551 try:
552 self.assertEqual(packet[IP].src, ingress_if.remote_ip4)
553 self.assertEqual(packet[IP].dst, egress_if.remote_ip4)
554 if packet.haslayer(TCP):
555 self.assertEqual(packet[TCP].sport, self.tcp_port_in)
556 elif packet.haslayer(UDP):
557 self.assertEqual(packet[UDP].sport, self.udp_port_in)
558 else:
559 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
560 except:
561 self.logger.error(ppp("Unexpected or invalid packet "
562 "(inside network):", packet))
563 raise
564
Juraj Slobodab33f4132017-02-08 23:54:21 -0800565 def verify_capture_out_with_icmp_errors(self, capture, src_ip=None,
566 packet_num=3, icmp_type=11):
567 """
568 Verify captured packets with ICMP errors on outside network
569
570 :param capture: Captured packets
571 :param src_ip: Translated IP address or IP address of VPP
Matus Fabian2ba92e32017-08-21 07:05:03 -0700572 (Default use global NAT address)
Juraj Slobodab33f4132017-02-08 23:54:21 -0800573 :param packet_num: Expected number of packets (Default 3)
574 :param icmp_type: Type of error ICMP packet
575 we are expecting (Default 11)
576 """
577 if src_ip is None:
Matus Fabian2ba92e32017-08-21 07:05:03 -0700578 src_ip = self.nat_addr
Juraj Slobodab33f4132017-02-08 23:54:21 -0800579 self.assertEqual(packet_num, len(capture))
580 for packet in capture:
581 try:
582 self.assertEqual(packet[IP].src, src_ip)
583 self.assertTrue(packet.haslayer(ICMP))
584 icmp = packet[ICMP]
585 self.assertEqual(icmp.type, icmp_type)
586 self.assertTrue(icmp.haslayer(IPerror))
587 inner_ip = icmp[IPerror]
588 if inner_ip.haslayer(TCPerror):
589 self.assertEqual(inner_ip[TCPerror].dport,
590 self.tcp_port_out)
591 elif inner_ip.haslayer(UDPerror):
592 self.assertEqual(inner_ip[UDPerror].dport,
593 self.udp_port_out)
594 else:
595 self.assertEqual(inner_ip[ICMPerror].id, self.icmp_id_out)
596 except:
597 self.logger.error(ppp("Unexpected or invalid packet "
598 "(outside network):", packet))
599 raise
600
601 def verify_capture_in_with_icmp_errors(self, capture, in_if, packet_num=3,
602 icmp_type=11):
603 """
604 Verify captured packets with ICMP errors on inside network
605
606 :param capture: Captured packets
607 :param in_if: Inside interface
608 :param packet_num: Expected number of packets (Default 3)
609 :param icmp_type: Type of error ICMP packet
610 we are expecting (Default 11)
611 """
612 self.assertEqual(packet_num, len(capture))
613 for packet in capture:
614 try:
615 self.assertEqual(packet[IP].dst, in_if.remote_ip4)
616 self.assertTrue(packet.haslayer(ICMP))
617 icmp = packet[ICMP]
618 self.assertEqual(icmp.type, icmp_type)
619 self.assertTrue(icmp.haslayer(IPerror))
620 inner_ip = icmp[IPerror]
621 if inner_ip.haslayer(TCPerror):
622 self.assertEqual(inner_ip[TCPerror].sport,
623 self.tcp_port_in)
624 elif inner_ip.haslayer(UDPerror):
625 self.assertEqual(inner_ip[UDPerror].sport,
626 self.udp_port_in)
627 else:
628 self.assertEqual(inner_ip[ICMPerror].id, self.icmp_id_in)
629 except:
630 self.logger.error(ppp("Unexpected or invalid packet "
631 "(inside network):", packet))
632 raise
633
Matus Fabianefcd1e92017-08-15 06:59:19 -0700634 def create_stream_frag(self, src_if, dst, sport, dport, data):
635 """
636 Create fragmented packet stream
637
638 :param src_if: Source interface
639 :param dst: Destination IPv4 address
640 :param sport: Source TCP port
641 :param dport: Destination TCP port
642 :param data: Payload data
643 :returns: Fragmets
644 """
645 id = random.randint(0, 65535)
646 p = (IP(src=src_if.remote_ip4, dst=dst) /
647 TCP(sport=sport, dport=dport) /
648 Raw(data))
649 p = p.__class__(str(p))
650 chksum = p['TCP'].chksum
651 pkts = []
652 p = (Ether(src=src_if.remote_mac, dst=src_if.local_mac) /
653 IP(src=src_if.remote_ip4, dst=dst, flags="MF", frag=0, id=id) /
654 TCP(sport=sport, dport=dport, chksum=chksum) /
655 Raw(data[0:4]))
656 pkts.append(p)
657 p = (Ether(src=src_if.remote_mac, dst=src_if.local_mac) /
658 IP(src=src_if.remote_ip4, dst=dst, flags="MF", frag=3, id=id,
659 proto=IP_PROTOS.tcp) /
660 Raw(data[4:20]))
661 pkts.append(p)
662 p = (Ether(src=src_if.remote_mac, dst=src_if.local_mac) /
663 IP(src=src_if.remote_ip4, dst=dst, frag=5, proto=IP_PROTOS.tcp,
664 id=id) /
665 Raw(data[20:]))
666 pkts.append(p)
667 return pkts
668
669 def create_stream_frag_ip6(self, src_if, dst, sport, dport, data,
670 pref=None, plen=0, frag_size=128):
671 """
672 Create fragmented packet stream
673
674 :param src_if: Source interface
675 :param dst: Destination IPv4 address
676 :param sport: Source TCP port
677 :param dport: Destination TCP port
678 :param data: Payload data
679 :param pref: NAT64 prefix
680 :param plen: NAT64 prefix length
681 :param fragsize: size of fragments
682 :returns: Fragmets
683 """
684 if pref is None:
685 dst_ip6 = ''.join(['64:ff9b::', dst])
686 else:
687 dst_ip6 = self.compose_ip6(dst, pref, plen)
688
689 p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
690 IPv6(src=src_if.remote_ip6, dst=dst_ip6) /
691 IPv6ExtHdrFragment(id=random.randint(0, 65535)) /
692 TCP(sport=sport, dport=dport) /
693 Raw(data))
694
695 return fragment6(p, frag_size)
696
697 def reass_frags_and_verify(self, frags, src, dst):
698 """
699 Reassemble and verify fragmented packet
700
701 :param frags: Captured fragments
702 :param src: Source IPv4 address to verify
703 :param dst: Destination IPv4 address to verify
704
705 :returns: Reassembled IPv4 packet
706 """
707 buffer = StringIO.StringIO()
708 for p in frags:
709 self.assertEqual(p[IP].src, src)
710 self.assertEqual(p[IP].dst, dst)
Klement Sekerad81ae412018-05-16 10:52:54 +0200711 self.assert_ip_checksum_valid(p)
Matus Fabianefcd1e92017-08-15 06:59:19 -0700712 buffer.seek(p[IP].frag * 8)
713 buffer.write(p[IP].payload)
714 ip = frags[0].getlayer(IP)
715 ip = IP(src=frags[0][IP].src, dst=frags[0][IP].dst,
716 proto=frags[0][IP].proto)
717 if ip.proto == IP_PROTOS.tcp:
718 p = (ip / TCP(buffer.getvalue()))
Klement Sekerad81ae412018-05-16 10:52:54 +0200719 self.assert_tcp_checksum_valid(p)
Matus Fabianefcd1e92017-08-15 06:59:19 -0700720 elif ip.proto == IP_PROTOS.udp:
721 p = (ip / UDP(buffer.getvalue()))
722 return p
723
724 def reass_frags_and_verify_ip6(self, frags, src, dst):
725 """
726 Reassemble and verify fragmented packet
727
728 :param frags: Captured fragments
729 :param src: Source IPv6 address to verify
730 :param dst: Destination IPv6 address to verify
731
732 :returns: Reassembled IPv6 packet
733 """
734 buffer = StringIO.StringIO()
735 for p in frags:
736 self.assertEqual(p[IPv6].src, src)
737 self.assertEqual(p[IPv6].dst, dst)
738 buffer.seek(p[IPv6ExtHdrFragment].offset * 8)
739 buffer.write(p[IPv6ExtHdrFragment].payload)
740 ip = IPv6(src=frags[0][IPv6].src, dst=frags[0][IPv6].dst,
741 nh=frags[0][IPv6ExtHdrFragment].nh)
742 if ip.nh == IP_PROTOS.tcp:
743 p = (ip / TCP(buffer.getvalue()))
Matus Fabianefcd1e92017-08-15 06:59:19 -0700744 elif ip.nh == IP_PROTOS.udp:
745 p = (ip / UDP(buffer.getvalue()))
Klement Sekerad81ae412018-05-16 10:52:54 +0200746 self.assert_packet_checksums_valid(p)
Matus Fabianefcd1e92017-08-15 06:59:19 -0700747 return p
748
Matus Fabianebdf1902018-05-04 03:57:42 -0700749 def initiate_tcp_session(self, in_if, out_if):
750 """
751 Initiates TCP session
752
753 :param in_if: Inside interface
754 :param out_if: Outside interface
755 """
756 try:
757 # SYN packet in->out
758 p = (Ether(src=in_if.remote_mac, dst=in_if.local_mac) /
759 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4) /
760 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
761 flags="S"))
762 in_if.add_stream(p)
763 self.pg_enable_capture(self.pg_interfaces)
764 self.pg_start()
765 capture = out_if.get_capture(1)
766 p = capture[0]
767 self.tcp_port_out = p[TCP].sport
768
769 # SYN + ACK packet out->in
770 p = (Ether(src=out_if.remote_mac, dst=out_if.local_mac) /
771 IP(src=out_if.remote_ip4, dst=self.nat_addr) /
772 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
773 flags="SA"))
774 out_if.add_stream(p)
775 self.pg_enable_capture(self.pg_interfaces)
776 self.pg_start()
777 in_if.get_capture(1)
778
779 # ACK packet in->out
780 p = (Ether(src=in_if.remote_mac, dst=in_if.local_mac) /
781 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4) /
782 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
783 flags="A"))
784 in_if.add_stream(p)
785 self.pg_enable_capture(self.pg_interfaces)
786 self.pg_start()
787 out_if.get_capture(1)
788
789 except:
790 self.logger.error("TCP 3 way handshake failed")
791 raise
792
Matus Fabianeea28d72017-01-13 04:15:54 -0800793 def verify_ipfix_nat44_ses(self, data):
794 """
795 Verify IPFIX NAT44 session create/delete event
796
797 :param data: Decoded IPFIX data records
798 """
799 nat44_ses_create_num = 0
800 nat44_ses_delete_num = 0
801 self.assertEqual(6, len(data))
802 for record in data:
803 # natEvent
804 self.assertIn(ord(record[230]), [4, 5])
805 if ord(record[230]) == 4:
806 nat44_ses_create_num += 1
807 else:
808 nat44_ses_delete_num += 1
809 # sourceIPv4Address
810 self.assertEqual(self.pg0.remote_ip4n, record[8])
811 # postNATSourceIPv4Address
Matus Fabian2ba92e32017-08-21 07:05:03 -0700812 self.assertEqual(socket.inet_pton(socket.AF_INET, self.nat_addr),
Matus Fabianeea28d72017-01-13 04:15:54 -0800813 record[225])
814 # ingressVRFID
815 self.assertEqual(struct.pack("!I", 0), record[234])
816 # protocolIdentifier/sourceTransportPort/postNAPTSourceTransportPort
817 if IP_PROTOS.icmp == ord(record[4]):
818 self.assertEqual(struct.pack("!H", self.icmp_id_in), record[7])
819 self.assertEqual(struct.pack("!H", self.icmp_id_out),
820 record[227])
821 elif IP_PROTOS.tcp == ord(record[4]):
822 self.assertEqual(struct.pack("!H", self.tcp_port_in),
823 record[7])
824 self.assertEqual(struct.pack("!H", self.tcp_port_out),
825 record[227])
826 elif IP_PROTOS.udp == ord(record[4]):
827 self.assertEqual(struct.pack("!H", self.udp_port_in),
828 record[7])
829 self.assertEqual(struct.pack("!H", self.udp_port_out),
830 record[227])
831 else:
832 self.fail("Invalid protocol")
833 self.assertEqual(3, nat44_ses_create_num)
834 self.assertEqual(3, nat44_ses_delete_num)
835
836 def verify_ipfix_addr_exhausted(self, data):
837 """
838 Verify IPFIX NAT addresses event
839
840 :param data: Decoded IPFIX data records
841 """
842 self.assertEqual(1, len(data))
843 record = data[0]
844 # natEvent
845 self.assertEqual(ord(record[230]), 3)
846 # natPoolID
847 self.assertEqual(struct.pack("!I", 0), record[283])
848
Matus Fabiana431ad12018-01-04 04:03:14 -0800849 def verify_ipfix_max_sessions(self, data, limit):
850 """
851 Verify IPFIX maximum session entries exceeded event
852
853 :param data: Decoded IPFIX data records
854 :param limit: Number of maximum session entries that can be created.
855 """
856 self.assertEqual(1, len(data))
857 record = data[0]
858 # natEvent
859 self.assertEqual(ord(record[230]), 13)
860 # natQuotaExceededEvent
861 self.assertEqual(struct.pack("I", 1), record[466])
862 # maxSessionEntries
863 self.assertEqual(struct.pack("I", limit), record[471])
864
865 def verify_ipfix_max_bibs(self, data, limit):
866 """
867 Verify IPFIX maximum BIB entries exceeded event
868
869 :param data: Decoded IPFIX data records
870 :param limit: Number of maximum BIB entries that can be created.
871 """
872 self.assertEqual(1, len(data))
873 record = data[0]
874 # natEvent
875 self.assertEqual(ord(record[230]), 13)
876 # natQuotaExceededEvent
877 self.assertEqual(struct.pack("I", 2), record[466])
878 # maxBIBEntries
879 self.assertEqual(struct.pack("I", limit), record[472])
880
881 def verify_ipfix_max_fragments_ip6(self, data, limit, src_addr):
882 """
883 Verify IPFIX maximum IPv6 fragments pending reassembly exceeded event
884
885 :param data: Decoded IPFIX data records
886 :param limit: Number of maximum fragments pending reassembly
887 :param src_addr: IPv6 source address
888 """
889 self.assertEqual(1, len(data))
890 record = data[0]
891 # natEvent
892 self.assertEqual(ord(record[230]), 13)
893 # natQuotaExceededEvent
894 self.assertEqual(struct.pack("I", 5), record[466])
895 # maxFragmentsPendingReassembly
896 self.assertEqual(struct.pack("I", limit), record[475])
897 # sourceIPv6Address
898 self.assertEqual(src_addr, record[27])
899
900 def verify_ipfix_max_fragments_ip4(self, data, limit, src_addr):
901 """
902 Verify IPFIX maximum IPv4 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: IPv4 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 # sourceIPv4Address
917 self.assertEqual(src_addr, record[8])
918
919 def verify_ipfix_bib(self, data, is_create, src_addr):
920 """
921 Verify IPFIX NAT64 BIB create and delete events
922
923 :param data: Decoded IPFIX data records
924 :param is_create: Create event if nonzero value otherwise delete event
925 :param src_addr: IPv6 source address
926 """
927 self.assertEqual(1, len(data))
928 record = data[0]
929 # natEvent
930 if is_create:
931 self.assertEqual(ord(record[230]), 10)
932 else:
933 self.assertEqual(ord(record[230]), 11)
934 # sourceIPv6Address
935 self.assertEqual(src_addr, record[27])
936 # postNATSourceIPv4Address
937 self.assertEqual(self.nat_addr_n, record[225])
938 # protocolIdentifier
939 self.assertEqual(IP_PROTOS.tcp, ord(record[4]))
940 # ingressVRFID
941 self.assertEqual(struct.pack("!I", 0), record[234])
942 # sourceTransportPort
943 self.assertEqual(struct.pack("!H", self.tcp_port_in), record[7])
944 # postNAPTSourceTransportPort
945 self.assertEqual(struct.pack("!H", self.tcp_port_out), record[227])
946
947 def verify_ipfix_nat64_ses(self, data, is_create, src_addr, dst_addr,
948 dst_port):
949 """
950 Verify IPFIX NAT64 session create and delete events
951
952 :param data: Decoded IPFIX data records
953 :param is_create: Create event if nonzero value otherwise delete event
954 :param src_addr: IPv6 source address
955 :param dst_addr: IPv4 destination address
956 :param dst_port: destination TCP port
957 """
958 self.assertEqual(1, len(data))
959 record = data[0]
960 # natEvent
961 if is_create:
962 self.assertEqual(ord(record[230]), 6)
963 else:
964 self.assertEqual(ord(record[230]), 7)
965 # sourceIPv6Address
966 self.assertEqual(src_addr, record[27])
967 # destinationIPv6Address
968 self.assertEqual(socket.inet_pton(socket.AF_INET6,
969 self.compose_ip6(dst_addr,
970 '64:ff9b::',
971 96)),
972 record[28])
973 # postNATSourceIPv4Address
974 self.assertEqual(self.nat_addr_n, record[225])
975 # postNATDestinationIPv4Address
976 self.assertEqual(socket.inet_pton(socket.AF_INET, dst_addr),
977 record[226])
978 # protocolIdentifier
979 self.assertEqual(IP_PROTOS.tcp, ord(record[4]))
980 # ingressVRFID
981 self.assertEqual(struct.pack("!I", 0), record[234])
982 # sourceTransportPort
983 self.assertEqual(struct.pack("!H", self.tcp_port_in), record[7])
984 # postNAPTSourceTransportPort
985 self.assertEqual(struct.pack("!H", self.tcp_port_out), record[227])
986 # destinationTransportPort
987 self.assertEqual(struct.pack("!H", dst_port), record[11])
988 # postNAPTDestinationTransportPort
989 self.assertEqual(struct.pack("!H", dst_port), record[228])
990
Matus Fabian68ba8802018-08-08 05:52:47 -0700991 def verify_no_nat44_user(self):
992 """ Verify that there is no NAT44 user """
993 users = self.vapi.nat44_user_dump()
994 self.assertEqual(len(users), 0)
995
Martin Gálikd7f75cd2017-03-27 06:02:47 -0700996
Matus Fabian2ba92e32017-08-21 07:05:03 -0700997class TestNAT44(MethodHolder):
998 """ NAT44 Test Cases """
Martin Gálikd7f75cd2017-03-27 06:02:47 -0700999
1000 @classmethod
1001 def setUpClass(cls):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001002 super(TestNAT44, cls).setUpClass()
Matus Fabian229c1aa2018-05-28 04:09:52 -07001003 cls.vapi.cli("set log class nat level debug")
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001004
1005 try:
1006 cls.tcp_port_in = 6303
1007 cls.tcp_port_out = 6303
1008 cls.udp_port_in = 6304
1009 cls.udp_port_out = 6304
1010 cls.icmp_id_in = 6305
1011 cls.icmp_id_out = 6305
Matus Fabian2ba92e32017-08-21 07:05:03 -07001012 cls.nat_addr = '10.0.0.3'
Juraj Sloboda7b929792017-11-23 13:20:48 +01001013 cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
Matus Fabian6631e9c2017-05-24 01:52:20 -07001014 cls.ipfix_src_port = 4739
1015 cls.ipfix_domain_id = 1
Matus Fabianebdf1902018-05-04 03:57:42 -07001016 cls.tcp_external_port = 80
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001017
Matus Fabian36ea2d62017-10-24 04:13:49 -07001018 cls.create_pg_interfaces(range(10))
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001019 cls.interfaces = list(cls.pg_interfaces[0:4])
1020
1021 for i in cls.interfaces:
1022 i.admin_up()
1023 i.config_ip4()
1024 i.resolve_arp()
1025
Matus Fabian6fa74c62017-06-05 05:55:48 -07001026 cls.pg0.generate_remote_hosts(3)
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001027 cls.pg0.configure_ipv4_neighbors()
1028
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02001029 cls.pg1.generate_remote_hosts(1)
1030 cls.pg1.configure_ipv4_neighbors()
1031
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001032 cls.overlapping_interfaces = list(list(cls.pg_interfaces[4:7]))
Neale Ranns15002542017-09-10 04:39:11 -07001033 cls.vapi.ip_table_add_del(10, is_add=1)
1034 cls.vapi.ip_table_add_del(20, is_add=1)
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001035
1036 cls.pg4._local_ip4 = "172.16.255.1"
1037 cls.pg4._local_ip4n = socket.inet_pton(socket.AF_INET, i.local_ip4)
1038 cls.pg4._remote_hosts[0]._ip4 = "172.16.255.2"
1039 cls.pg4.set_table_ip4(10)
Matus Fabian69126282017-08-14 23:39:58 -07001040 cls.pg5._local_ip4 = "172.17.255.3"
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001041 cls.pg5._local_ip4n = socket.inet_pton(socket.AF_INET, i.local_ip4)
Matus Fabian69126282017-08-14 23:39:58 -07001042 cls.pg5._remote_hosts[0]._ip4 = "172.17.255.4"
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001043 cls.pg5.set_table_ip4(10)
1044 cls.pg6._local_ip4 = "172.16.255.1"
1045 cls.pg6._local_ip4n = socket.inet_pton(socket.AF_INET, i.local_ip4)
1046 cls.pg6._remote_hosts[0]._ip4 = "172.16.255.2"
1047 cls.pg6.set_table_ip4(20)
1048 for i in cls.overlapping_interfaces:
1049 i.config_ip4()
1050 i.admin_up()
1051 i.resolve_arp()
1052
1053 cls.pg7.admin_up()
Martin Gálik406eb1d2017-05-04 04:35:04 -07001054 cls.pg8.admin_up()
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001055
Matus Fabian36ea2d62017-10-24 04:13:49 -07001056 cls.pg9.generate_remote_hosts(2)
1057 cls.pg9.config_ip4()
1058 ip_addr_n = socket.inet_pton(socket.AF_INET, "10.0.0.1")
1059 cls.vapi.sw_interface_add_del_address(cls.pg9.sw_if_index,
1060 ip_addr_n,
1061 24)
1062 cls.pg9.admin_up()
1063 cls.pg9.resolve_arp()
1064 cls.pg9._remote_hosts[1]._ip4 = cls.pg9._remote_hosts[0]._ip4
1065 cls.pg4._remote_ip4 = cls.pg9._remote_hosts[0]._ip4 = "10.0.0.2"
1066 cls.pg9.resolve_arp()
1067
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001068 except Exception:
Matus Fabian2ba92e32017-08-21 07:05:03 -07001069 super(TestNAT44, cls).tearDownClass()
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001070 raise
1071
Matus Fabiande886752016-12-07 03:38:19 -08001072 def test_dynamic(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001073 """ NAT44 dynamic translation test """
Matus Fabiande886752016-12-07 03:38:19 -08001074
Matus Fabian2ba92e32017-08-21 07:05:03 -07001075 self.nat44_add_address(self.nat_addr)
1076 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1077 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1078 is_inside=0)
Matus Fabiande886752016-12-07 03:38:19 -08001079
1080 # in2out
1081 pkts = self.create_stream_in(self.pg0, self.pg1)
1082 self.pg0.add_stream(pkts)
1083 self.pg_enable_capture(self.pg_interfaces)
1084 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001085 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001086 self.verify_capture_out(capture)
1087
1088 # out2in
1089 pkts = self.create_stream_out(self.pg1)
1090 self.pg1.add_stream(pkts)
1091 self.pg_enable_capture(self.pg_interfaces)
1092 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001093 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001094 self.verify_capture_in(capture, self.pg0)
1095
Juraj Slobodab33f4132017-02-08 23:54:21 -08001096 def test_dynamic_icmp_errors_in2out_ttl_1(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001097 """ NAT44 handling of client packets with TTL=1 """
Juraj Slobodab33f4132017-02-08 23:54:21 -08001098
Matus Fabian2ba92e32017-08-21 07:05:03 -07001099 self.nat44_add_address(self.nat_addr)
1100 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1101 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1102 is_inside=0)
Juraj Slobodab33f4132017-02-08 23:54:21 -08001103
1104 # Client side - generate traffic
1105 pkts = self.create_stream_in(self.pg0, self.pg1, ttl=1)
1106 self.pg0.add_stream(pkts)
1107 self.pg_enable_capture(self.pg_interfaces)
1108 self.pg_start()
1109
1110 # Client side - verify ICMP type 11 packets
1111 capture = self.pg0.get_capture(len(pkts))
1112 self.verify_capture_in_with_icmp_errors(capture, self.pg0)
1113
1114 def test_dynamic_icmp_errors_out2in_ttl_1(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001115 """ NAT44 handling of server packets with TTL=1 """
Juraj Slobodab33f4132017-02-08 23:54:21 -08001116
Matus Fabian2ba92e32017-08-21 07:05:03 -07001117 self.nat44_add_address(self.nat_addr)
1118 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1119 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1120 is_inside=0)
Juraj Slobodab33f4132017-02-08 23:54:21 -08001121
1122 # Client side - create sessions
1123 pkts = self.create_stream_in(self.pg0, self.pg1)
1124 self.pg0.add_stream(pkts)
1125 self.pg_enable_capture(self.pg_interfaces)
1126 self.pg_start()
1127
1128 # Server side - generate traffic
1129 capture = self.pg1.get_capture(len(pkts))
1130 self.verify_capture_out(capture)
1131 pkts = self.create_stream_out(self.pg1, ttl=1)
1132 self.pg1.add_stream(pkts)
1133 self.pg_enable_capture(self.pg_interfaces)
1134 self.pg_start()
1135
1136 # Server side - verify ICMP type 11 packets
1137 capture = self.pg1.get_capture(len(pkts))
1138 self.verify_capture_out_with_icmp_errors(capture,
1139 src_ip=self.pg1.local_ip4)
1140
1141 def test_dynamic_icmp_errors_in2out_ttl_2(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001142 """ NAT44 handling of error responses to client packets with TTL=2 """
Juraj Slobodab33f4132017-02-08 23:54:21 -08001143
Matus Fabian2ba92e32017-08-21 07:05:03 -07001144 self.nat44_add_address(self.nat_addr)
1145 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1146 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1147 is_inside=0)
Juraj Slobodab33f4132017-02-08 23:54:21 -08001148
1149 # Client side - generate traffic
1150 pkts = self.create_stream_in(self.pg0, self.pg1, ttl=2)
1151 self.pg0.add_stream(pkts)
1152 self.pg_enable_capture(self.pg_interfaces)
1153 self.pg_start()
1154
1155 # Server side - simulate ICMP type 11 response
1156 capture = self.pg1.get_capture(len(pkts))
1157 pkts = [Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07001158 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Juraj Slobodab33f4132017-02-08 23:54:21 -08001159 ICMP(type=11) / packet[IP] for packet in capture]
1160 self.pg1.add_stream(pkts)
1161 self.pg_enable_capture(self.pg_interfaces)
1162 self.pg_start()
1163
1164 # Client side - verify ICMP type 11 packets
1165 capture = self.pg0.get_capture(len(pkts))
1166 self.verify_capture_in_with_icmp_errors(capture, self.pg0)
1167
1168 def test_dynamic_icmp_errors_out2in_ttl_2(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001169 """ NAT44 handling of error responses to server packets with TTL=2 """
Juraj Slobodab33f4132017-02-08 23:54:21 -08001170
Matus Fabian2ba92e32017-08-21 07:05:03 -07001171 self.nat44_add_address(self.nat_addr)
1172 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1173 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1174 is_inside=0)
Juraj Slobodab33f4132017-02-08 23:54:21 -08001175
1176 # Client side - create sessions
1177 pkts = self.create_stream_in(self.pg0, self.pg1)
1178 self.pg0.add_stream(pkts)
1179 self.pg_enable_capture(self.pg_interfaces)
1180 self.pg_start()
1181
1182 # Server side - generate traffic
1183 capture = self.pg1.get_capture(len(pkts))
1184 self.verify_capture_out(capture)
1185 pkts = self.create_stream_out(self.pg1, ttl=2)
1186 self.pg1.add_stream(pkts)
1187 self.pg_enable_capture(self.pg_interfaces)
1188 self.pg_start()
1189
1190 # Client side - simulate ICMP type 11 response
1191 capture = self.pg0.get_capture(len(pkts))
1192 pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1193 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
1194 ICMP(type=11) / packet[IP] for packet in capture]
1195 self.pg0.add_stream(pkts)
1196 self.pg_enable_capture(self.pg_interfaces)
1197 self.pg_start()
1198
1199 # Server side - verify ICMP type 11 packets
1200 capture = self.pg1.get_capture(len(pkts))
1201 self.verify_capture_out_with_icmp_errors(capture)
1202
Juraj Sloboda665e4822017-02-16 17:17:19 -08001203 def test_ping_out_interface_from_outside(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001204 """ Ping NAT44 out interface from outside network """
Juraj Sloboda665e4822017-02-16 17:17:19 -08001205
Matus Fabian2ba92e32017-08-21 07:05:03 -07001206 self.nat44_add_address(self.nat_addr)
1207 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1208 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1209 is_inside=0)
Juraj Sloboda665e4822017-02-16 17:17:19 -08001210
1211 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1212 IP(src=self.pg1.remote_ip4, dst=self.pg1.local_ip4) /
1213 ICMP(id=self.icmp_id_out, type='echo-request'))
1214 pkts = [p]
1215 self.pg1.add_stream(pkts)
1216 self.pg_enable_capture(self.pg_interfaces)
1217 self.pg_start()
1218 capture = self.pg1.get_capture(len(pkts))
1219 self.assertEqual(1, len(capture))
1220 packet = capture[0]
1221 try:
1222 self.assertEqual(packet[IP].src, self.pg1.local_ip4)
1223 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
1224 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
1225 self.assertEqual(packet[ICMP].type, 0) # echo reply
1226 except:
1227 self.logger.error(ppp("Unexpected or invalid packet "
1228 "(outside network):", packet))
1229 raise
1230
Juraj Slobodad3677682017-04-14 03:24:45 +02001231 def test_ping_internal_host_from_outside(self):
1232 """ Ping internal host from outside network """
1233
Matus Fabian2ba92e32017-08-21 07:05:03 -07001234 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr)
1235 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1236 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1237 is_inside=0)
Juraj Slobodad3677682017-04-14 03:24:45 +02001238
1239 # out2in
1240 pkt = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07001241 IP(src=self.pg1.remote_ip4, dst=self.nat_addr, ttl=64) /
Juraj Slobodad3677682017-04-14 03:24:45 +02001242 ICMP(id=self.icmp_id_out, type='echo-request'))
1243 self.pg1.add_stream(pkt)
1244 self.pg_enable_capture(self.pg_interfaces)
1245 self.pg_start()
1246 capture = self.pg0.get_capture(1)
1247 self.verify_capture_in(capture, self.pg0, packet_num=1)
1248 self.assert_equal(capture[0][IP].proto, IP_PROTOS.icmp)
1249
1250 # in2out
1251 pkt = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1252 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4, ttl=64) /
1253 ICMP(id=self.icmp_id_in, type='echo-reply'))
1254 self.pg0.add_stream(pkt)
1255 self.pg_enable_capture(self.pg_interfaces)
1256 self.pg_start()
1257 capture = self.pg1.get_capture(1)
1258 self.verify_capture_out(capture, same_port=True, packet_num=1)
1259 self.assert_equal(capture[0][IP].proto, IP_PROTOS.icmp)
1260
Matus Fabianc79396e2018-07-23 00:05:22 -07001261 def test_forwarding(self):
Juraj Sloboda7b929792017-11-23 13:20:48 +01001262 """ NAT44 forwarding test """
1263
1264 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1265 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1266 is_inside=0)
1267 self.vapi.nat44_forwarding_enable_disable(1)
1268
1269 real_ip = self.pg0.remote_ip4n
1270 alias_ip = self.nat_addr_n
1271 self.vapi.nat44_add_del_static_mapping(local_ip=real_ip,
1272 external_ip=alias_ip)
1273
1274 try:
Matus Fabianc79396e2018-07-23 00:05:22 -07001275 # static mapping match
Juraj Sloboda7b929792017-11-23 13:20:48 +01001276
1277 pkts = self.create_stream_out(self.pg1)
1278 self.pg1.add_stream(pkts)
1279 self.pg_enable_capture(self.pg_interfaces)
1280 self.pg_start()
1281 capture = self.pg0.get_capture(len(pkts))
1282 self.verify_capture_in(capture, self.pg0)
1283
1284 pkts = self.create_stream_in(self.pg0, self.pg1)
1285 self.pg0.add_stream(pkts)
1286 self.pg_enable_capture(self.pg_interfaces)
1287 self.pg_start()
1288 capture = self.pg1.get_capture(len(pkts))
1289 self.verify_capture_out(capture, same_port=True)
1290
Matus Fabianc79396e2018-07-23 00:05:22 -07001291 # no static mapping match
Juraj Sloboda7b929792017-11-23 13:20:48 +01001292
1293 host0 = self.pg0.remote_hosts[0]
1294 self.pg0.remote_hosts[0] = self.pg0.remote_hosts[1]
1295 try:
1296 pkts = self.create_stream_out(self.pg1,
1297 dst_ip=self.pg0.remote_ip4,
1298 use_inside_ports=True)
1299 self.pg1.add_stream(pkts)
1300 self.pg_enable_capture(self.pg_interfaces)
1301 self.pg_start()
1302 capture = self.pg0.get_capture(len(pkts))
1303 self.verify_capture_in(capture, self.pg0)
1304
1305 pkts = self.create_stream_in(self.pg0, self.pg1)
1306 self.pg0.add_stream(pkts)
1307 self.pg_enable_capture(self.pg_interfaces)
1308 self.pg_start()
1309 capture = self.pg1.get_capture(len(pkts))
1310 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
1311 same_port=True)
1312 finally:
1313 self.pg0.remote_hosts[0] = host0
1314
1315 finally:
1316 self.vapi.nat44_forwarding_enable_disable(0)
1317 self.vapi.nat44_add_del_static_mapping(local_ip=real_ip,
1318 external_ip=alias_ip,
1319 is_add=0)
1320
Matus Fabiande886752016-12-07 03:38:19 -08001321 def test_static_in(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001322 """ 1:1 NAT initialized from inside network """
Matus Fabiande886752016-12-07 03:38:19 -08001323
1324 nat_ip = "10.0.0.10"
1325 self.tcp_port_out = 6303
1326 self.udp_port_out = 6304
1327 self.icmp_id_out = 6305
1328
Matus Fabian2ba92e32017-08-21 07:05:03 -07001329 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
1330 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1331 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1332 is_inside=0)
Matus Fabian5f224992018-01-25 21:59:16 -08001333 sm = self.vapi.nat44_static_mapping_dump()
1334 self.assertEqual(len(sm), 1)
1335 self.assertEqual((sm[0].tag).split('\0', 1)[0], '')
Matus Fabian9dba7812018-01-31 01:13:23 -08001336 self.assertEqual(sm[0].protocol, 0)
1337 self.assertEqual(sm[0].local_port, 0)
1338 self.assertEqual(sm[0].external_port, 0)
Matus Fabiande886752016-12-07 03:38:19 -08001339
1340 # in2out
1341 pkts = self.create_stream_in(self.pg0, self.pg1)
1342 self.pg0.add_stream(pkts)
1343 self.pg_enable_capture(self.pg_interfaces)
1344 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001345 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001346 self.verify_capture_out(capture, nat_ip, True)
1347
1348 # out2in
1349 pkts = self.create_stream_out(self.pg1, nat_ip)
1350 self.pg1.add_stream(pkts)
1351 self.pg_enable_capture(self.pg_interfaces)
1352 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001353 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001354 self.verify_capture_in(capture, self.pg0)
1355
1356 def test_static_out(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001357 """ 1:1 NAT initialized from outside network """
Matus Fabiande886752016-12-07 03:38:19 -08001358
1359 nat_ip = "10.0.0.20"
1360 self.tcp_port_out = 6303
1361 self.udp_port_out = 6304
1362 self.icmp_id_out = 6305
Matus Fabian5f224992018-01-25 21:59:16 -08001363 tag = "testTAG"
Matus Fabiande886752016-12-07 03:38:19 -08001364
Matus Fabian5f224992018-01-25 21:59:16 -08001365 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip, tag=tag)
Matus Fabian2ba92e32017-08-21 07:05:03 -07001366 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1367 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1368 is_inside=0)
Matus Fabian5f224992018-01-25 21:59:16 -08001369 sm = self.vapi.nat44_static_mapping_dump()
1370 self.assertEqual(len(sm), 1)
1371 self.assertEqual((sm[0].tag).split('\0', 1)[0], tag)
Matus Fabiande886752016-12-07 03:38:19 -08001372
1373 # out2in
1374 pkts = self.create_stream_out(self.pg1, nat_ip)
1375 self.pg1.add_stream(pkts)
1376 self.pg_enable_capture(self.pg_interfaces)
1377 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001378 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001379 self.verify_capture_in(capture, self.pg0)
1380
1381 # in2out
1382 pkts = self.create_stream_in(self.pg0, self.pg1)
1383 self.pg0.add_stream(pkts)
1384 self.pg_enable_capture(self.pg_interfaces)
1385 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001386 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001387 self.verify_capture_out(capture, nat_ip, True)
1388
1389 def test_static_with_port_in(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001390 """ 1:1 NAPT initialized from inside network """
Matus Fabiande886752016-12-07 03:38:19 -08001391
1392 self.tcp_port_out = 3606
1393 self.udp_port_out = 3607
1394 self.icmp_id_out = 3608
1395
Matus Fabian2ba92e32017-08-21 07:05:03 -07001396 self.nat44_add_address(self.nat_addr)
1397 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1398 self.tcp_port_in, self.tcp_port_out,
1399 proto=IP_PROTOS.tcp)
1400 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1401 self.udp_port_in, self.udp_port_out,
1402 proto=IP_PROTOS.udp)
1403 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1404 self.icmp_id_in, self.icmp_id_out,
1405 proto=IP_PROTOS.icmp)
1406 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1407 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1408 is_inside=0)
Matus Fabiande886752016-12-07 03:38:19 -08001409
1410 # in2out
1411 pkts = self.create_stream_in(self.pg0, self.pg1)
1412 self.pg0.add_stream(pkts)
1413 self.pg_enable_capture(self.pg_interfaces)
1414 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001415 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001416 self.verify_capture_out(capture)
1417
1418 # out2in
1419 pkts = self.create_stream_out(self.pg1)
1420 self.pg1.add_stream(pkts)
1421 self.pg_enable_capture(self.pg_interfaces)
1422 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001423 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001424 self.verify_capture_in(capture, self.pg0)
1425
1426 def test_static_with_port_out(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001427 """ 1:1 NAPT initialized from outside network """
Matus Fabiande886752016-12-07 03:38:19 -08001428
1429 self.tcp_port_out = 30606
1430 self.udp_port_out = 30607
1431 self.icmp_id_out = 30608
1432
Matus Fabian2ba92e32017-08-21 07:05:03 -07001433 self.nat44_add_address(self.nat_addr)
1434 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1435 self.tcp_port_in, self.tcp_port_out,
1436 proto=IP_PROTOS.tcp)
1437 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1438 self.udp_port_in, self.udp_port_out,
1439 proto=IP_PROTOS.udp)
1440 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1441 self.icmp_id_in, self.icmp_id_out,
1442 proto=IP_PROTOS.icmp)
1443 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1444 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1445 is_inside=0)
Matus Fabiande886752016-12-07 03:38:19 -08001446
1447 # out2in
1448 pkts = self.create_stream_out(self.pg1)
1449 self.pg1.add_stream(pkts)
1450 self.pg_enable_capture(self.pg_interfaces)
1451 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001452 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001453 self.verify_capture_in(capture, self.pg0)
1454
1455 # in2out
1456 pkts = self.create_stream_in(self.pg0, self.pg1)
1457 self.pg0.add_stream(pkts)
1458 self.pg_enable_capture(self.pg_interfaces)
1459 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001460 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001461 self.verify_capture_out(capture)
1462
1463 def test_static_vrf_aware(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001464 """ 1:1 NAT VRF awareness """
Matus Fabiande886752016-12-07 03:38:19 -08001465
1466 nat_ip1 = "10.0.0.30"
1467 nat_ip2 = "10.0.0.40"
1468 self.tcp_port_out = 6303
1469 self.udp_port_out = 6304
1470 self.icmp_id_out = 6305
1471
Matus Fabian2ba92e32017-08-21 07:05:03 -07001472 self.nat44_add_static_mapping(self.pg4.remote_ip4, nat_ip1,
1473 vrf_id=10)
1474 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip2,
1475 vrf_id=10)
1476 self.vapi.nat44_interface_add_del_feature(self.pg3.sw_if_index,
1477 is_inside=0)
1478 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1479 self.vapi.nat44_interface_add_del_feature(self.pg4.sw_if_index)
Matus Fabiande886752016-12-07 03:38:19 -08001480
Matus Fabian2ba92e32017-08-21 07:05:03 -07001481 # inside interface VRF match NAT44 static mapping VRF
Matus Fabiande886752016-12-07 03:38:19 -08001482 pkts = self.create_stream_in(self.pg4, self.pg3)
1483 self.pg4.add_stream(pkts)
1484 self.pg_enable_capture(self.pg_interfaces)
1485 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001486 capture = self.pg3.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001487 self.verify_capture_out(capture, nat_ip1, True)
1488
Matus Fabian2ba92e32017-08-21 07:05:03 -07001489 # inside interface VRF don't match NAT44 static mapping VRF (packets
Matus Fabiande886752016-12-07 03:38:19 -08001490 # are dropped)
1491 pkts = self.create_stream_in(self.pg0, self.pg3)
1492 self.pg0.add_stream(pkts)
1493 self.pg_enable_capture(self.pg_interfaces)
1494 self.pg_start()
Klement Sekera9225dee2016-12-12 08:36:58 +01001495 self.pg3.assert_nothing_captured()
Matus Fabiande886752016-12-07 03:38:19 -08001496
Matus Fabianb793d092018-01-31 05:50:21 -08001497 def test_dynamic_to_static(self):
1498 """ Switch from dynamic translation to 1:1NAT """
1499 nat_ip = "10.0.0.10"
1500 self.tcp_port_out = 6303
1501 self.udp_port_out = 6304
1502 self.icmp_id_out = 6305
1503
1504 self.nat44_add_address(self.nat_addr)
1505 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1506 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1507 is_inside=0)
1508
1509 # dynamic
1510 pkts = self.create_stream_in(self.pg0, self.pg1)
1511 self.pg0.add_stream(pkts)
1512 self.pg_enable_capture(self.pg_interfaces)
1513 self.pg_start()
1514 capture = self.pg1.get_capture(len(pkts))
1515 self.verify_capture_out(capture)
1516
1517 # 1:1NAT
1518 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
1519 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
1520 self.assertEqual(len(sessions), 0)
1521 pkts = self.create_stream_in(self.pg0, self.pg1)
1522 self.pg0.add_stream(pkts)
1523 self.pg_enable_capture(self.pg_interfaces)
1524 self.pg_start()
1525 capture = self.pg1.get_capture(len(pkts))
1526 self.verify_capture_out(capture, nat_ip, True)
1527
Matus Fabianab7a8052017-11-28 04:29:41 -08001528 def test_identity_nat(self):
1529 """ Identity NAT """
1530
1531 self.vapi.nat44_add_del_identity_mapping(ip=self.pg0.remote_ip4n)
1532 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1533 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1534 is_inside=0)
1535
1536 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
1537 IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
1538 TCP(sport=12345, dport=56789))
1539 self.pg1.add_stream(p)
1540 self.pg_enable_capture(self.pg_interfaces)
1541 self.pg_start()
1542 capture = self.pg0.get_capture(1)
1543 p = capture[0]
1544 try:
1545 ip = p[IP]
1546 tcp = p[TCP]
1547 self.assertEqual(ip.dst, self.pg0.remote_ip4)
1548 self.assertEqual(ip.src, self.pg1.remote_ip4)
1549 self.assertEqual(tcp.dport, 56789)
1550 self.assertEqual(tcp.sport, 12345)
Klement Sekerad81ae412018-05-16 10:52:54 +02001551 self.assert_packet_checksums_valid(p)
Matus Fabianab7a8052017-11-28 04:29:41 -08001552 except:
1553 self.logger.error(ppp("Unexpected or invalid packet:", p))
1554 raise
1555
Matus Fabiande886752016-12-07 03:38:19 -08001556 def test_multiple_inside_interfaces(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001557 """ NAT44 multiple non-overlapping address space inside interfaces """
Matus Fabiande886752016-12-07 03:38:19 -08001558
Matus Fabian2ba92e32017-08-21 07:05:03 -07001559 self.nat44_add_address(self.nat_addr)
1560 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1561 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
1562 self.vapi.nat44_interface_add_del_feature(self.pg3.sw_if_index,
1563 is_inside=0)
Matus Fabiande886752016-12-07 03:38:19 -08001564
Matus Fabian2ba92e32017-08-21 07:05:03 -07001565 # between two NAT44 inside interfaces (no translation)
Matus Fabian675a69c2017-01-18 01:46:01 -08001566 pkts = self.create_stream_in(self.pg0, self.pg1)
1567 self.pg0.add_stream(pkts)
1568 self.pg_enable_capture(self.pg_interfaces)
1569 self.pg_start()
1570 capture = self.pg1.get_capture(len(pkts))
1571 self.verify_capture_no_translation(capture, self.pg0, self.pg1)
1572
Matus Fabian2ba92e32017-08-21 07:05:03 -07001573 # from NAT44 inside to interface without NAT44 feature (no translation)
Matus Fabian675a69c2017-01-18 01:46:01 -08001574 pkts = self.create_stream_in(self.pg0, self.pg2)
1575 self.pg0.add_stream(pkts)
1576 self.pg_enable_capture(self.pg_interfaces)
1577 self.pg_start()
1578 capture = self.pg2.get_capture(len(pkts))
1579 self.verify_capture_no_translation(capture, self.pg0, self.pg2)
1580
Matus Fabiande886752016-12-07 03:38:19 -08001581 # in2out 1st interface
1582 pkts = self.create_stream_in(self.pg0, self.pg3)
1583 self.pg0.add_stream(pkts)
1584 self.pg_enable_capture(self.pg_interfaces)
1585 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001586 capture = self.pg3.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001587 self.verify_capture_out(capture)
1588
1589 # out2in 1st interface
1590 pkts = self.create_stream_out(self.pg3)
1591 self.pg3.add_stream(pkts)
1592 self.pg_enable_capture(self.pg_interfaces)
1593 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001594 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001595 self.verify_capture_in(capture, self.pg0)
1596
1597 # in2out 2nd interface
1598 pkts = self.create_stream_in(self.pg1, self.pg3)
1599 self.pg1.add_stream(pkts)
1600 self.pg_enable_capture(self.pg_interfaces)
1601 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001602 capture = self.pg3.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001603 self.verify_capture_out(capture)
1604
1605 # out2in 2nd interface
1606 pkts = self.create_stream_out(self.pg3)
1607 self.pg3.add_stream(pkts)
1608 self.pg_enable_capture(self.pg_interfaces)
1609 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001610 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001611 self.verify_capture_in(capture, self.pg1)
1612
Matus Fabiande886752016-12-07 03:38:19 -08001613 def test_inside_overlapping_interfaces(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001614 """ NAT44 multiple inside interfaces with overlapping address space """
Matus Fabiande886752016-12-07 03:38:19 -08001615
Matus Fabian675a69c2017-01-18 01:46:01 -08001616 static_nat_ip = "10.0.0.10"
Matus Fabian2ba92e32017-08-21 07:05:03 -07001617 self.nat44_add_address(self.nat_addr)
1618 self.vapi.nat44_interface_add_del_feature(self.pg3.sw_if_index,
1619 is_inside=0)
1620 self.vapi.nat44_interface_add_del_feature(self.pg4.sw_if_index)
1621 self.vapi.nat44_interface_add_del_feature(self.pg5.sw_if_index)
1622 self.vapi.nat44_interface_add_del_feature(self.pg6.sw_if_index)
1623 self.nat44_add_static_mapping(self.pg6.remote_ip4, static_nat_ip,
1624 vrf_id=20)
Matus Fabian675a69c2017-01-18 01:46:01 -08001625
Matus Fabian2ba92e32017-08-21 07:05:03 -07001626 # between NAT44 inside interfaces with same VRF (no translation)
Matus Fabian675a69c2017-01-18 01:46:01 -08001627 pkts = self.create_stream_in(self.pg4, self.pg5)
1628 self.pg4.add_stream(pkts)
1629 self.pg_enable_capture(self.pg_interfaces)
1630 self.pg_start()
1631 capture = self.pg5.get_capture(len(pkts))
1632 self.verify_capture_no_translation(capture, self.pg4, self.pg5)
1633
Matus Fabian2ba92e32017-08-21 07:05:03 -07001634 # between NAT44 inside interfaces with different VRF (hairpinning)
Matus Fabian675a69c2017-01-18 01:46:01 -08001635 p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
1636 IP(src=self.pg4.remote_ip4, dst=static_nat_ip) /
1637 TCP(sport=1234, dport=5678))
1638 self.pg4.add_stream(p)
1639 self.pg_enable_capture(self.pg_interfaces)
1640 self.pg_start()
1641 capture = self.pg6.get_capture(1)
1642 p = capture[0]
1643 try:
1644 ip = p[IP]
1645 tcp = p[TCP]
Matus Fabian2ba92e32017-08-21 07:05:03 -07001646 self.assertEqual(ip.src, self.nat_addr)
Matus Fabian675a69c2017-01-18 01:46:01 -08001647 self.assertEqual(ip.dst, self.pg6.remote_ip4)
1648 self.assertNotEqual(tcp.sport, 1234)
1649 self.assertEqual(tcp.dport, 5678)
1650 except:
1651 self.logger.error(ppp("Unexpected or invalid packet:", p))
1652 raise
Matus Fabiande886752016-12-07 03:38:19 -08001653
1654 # in2out 1st interface
1655 pkts = self.create_stream_in(self.pg4, self.pg3)
1656 self.pg4.add_stream(pkts)
1657 self.pg_enable_capture(self.pg_interfaces)
1658 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001659 capture = self.pg3.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001660 self.verify_capture_out(capture)
1661
1662 # out2in 1st interface
1663 pkts = self.create_stream_out(self.pg3)
1664 self.pg3.add_stream(pkts)
1665 self.pg_enable_capture(self.pg_interfaces)
1666 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001667 capture = self.pg4.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001668 self.verify_capture_in(capture, self.pg4)
1669
1670 # in2out 2nd interface
1671 pkts = self.create_stream_in(self.pg5, self.pg3)
1672 self.pg5.add_stream(pkts)
1673 self.pg_enable_capture(self.pg_interfaces)
1674 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001675 capture = self.pg3.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001676 self.verify_capture_out(capture)
1677
1678 # out2in 2nd interface
1679 pkts = self.create_stream_out(self.pg3)
1680 self.pg3.add_stream(pkts)
1681 self.pg_enable_capture(self.pg_interfaces)
1682 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001683 capture = self.pg5.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001684 self.verify_capture_in(capture, self.pg5)
1685
magalik23caa882017-02-08 23:25:45 -08001686 # pg5 session dump
Matus Fabian2ba92e32017-08-21 07:05:03 -07001687 addresses = self.vapi.nat44_address_dump()
magalik23caa882017-02-08 23:25:45 -08001688 self.assertEqual(len(addresses), 1)
Matus Fabian2ba92e32017-08-21 07:05:03 -07001689 sessions = self.vapi.nat44_user_session_dump(self.pg5.remote_ip4n, 10)
magalik23caa882017-02-08 23:25:45 -08001690 self.assertEqual(len(sessions), 3)
1691 for session in sessions:
1692 self.assertFalse(session.is_static)
1693 self.assertEqual(session.inside_ip_address[0:4],
1694 self.pg5.remote_ip4n)
1695 self.assertEqual(session.outside_ip_address,
1696 addresses[0].ip_address)
1697 self.assertEqual(sessions[0].protocol, IP_PROTOS.tcp)
1698 self.assertEqual(sessions[1].protocol, IP_PROTOS.udp)
1699 self.assertEqual(sessions[2].protocol, IP_PROTOS.icmp)
1700 self.assertEqual(sessions[0].inside_port, self.tcp_port_in)
1701 self.assertEqual(sessions[1].inside_port, self.udp_port_in)
1702 self.assertEqual(sessions[2].inside_port, self.icmp_id_in)
1703 self.assertEqual(sessions[0].outside_port, self.tcp_port_out)
1704 self.assertEqual(sessions[1].outside_port, self.udp_port_out)
1705 self.assertEqual(sessions[2].outside_port, self.icmp_id_out)
1706
Matus Fabiande886752016-12-07 03:38:19 -08001707 # in2out 3rd interface
1708 pkts = self.create_stream_in(self.pg6, self.pg3)
1709 self.pg6.add_stream(pkts)
1710 self.pg_enable_capture(self.pg_interfaces)
1711 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001712 capture = self.pg3.get_capture(len(pkts))
Matus Fabian675a69c2017-01-18 01:46:01 -08001713 self.verify_capture_out(capture, static_nat_ip, True)
Matus Fabiande886752016-12-07 03:38:19 -08001714
1715 # out2in 3rd interface
Matus Fabian675a69c2017-01-18 01:46:01 -08001716 pkts = self.create_stream_out(self.pg3, static_nat_ip)
Matus Fabiande886752016-12-07 03:38:19 -08001717 self.pg3.add_stream(pkts)
1718 self.pg_enable_capture(self.pg_interfaces)
1719 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001720 capture = self.pg6.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001721 self.verify_capture_in(capture, self.pg6)
1722
magalik23caa882017-02-08 23:25:45 -08001723 # general user and session dump verifications
Matus Fabian2ba92e32017-08-21 07:05:03 -07001724 users = self.vapi.nat44_user_dump()
magalik23caa882017-02-08 23:25:45 -08001725 self.assertTrue(len(users) >= 3)
Matus Fabian2ba92e32017-08-21 07:05:03 -07001726 addresses = self.vapi.nat44_address_dump()
magalik23caa882017-02-08 23:25:45 -08001727 self.assertEqual(len(addresses), 1)
1728 for user in users:
Matus Fabian2ba92e32017-08-21 07:05:03 -07001729 sessions = self.vapi.nat44_user_session_dump(user.ip_address,
1730 user.vrf_id)
magalik23caa882017-02-08 23:25:45 -08001731 for session in sessions:
1732 self.assertEqual(user.ip_address, session.inside_ip_address)
1733 self.assertTrue(session.total_bytes > session.total_pkts > 0)
1734 self.assertTrue(session.protocol in
1735 [IP_PROTOS.tcp, IP_PROTOS.udp,
1736 IP_PROTOS.icmp])
Matus Fabian70a26ac2018-05-14 06:20:28 -07001737 self.assertFalse(session.ext_host_valid)
magalik23caa882017-02-08 23:25:45 -08001738
1739 # pg4 session dump
Matus Fabian2ba92e32017-08-21 07:05:03 -07001740 sessions = self.vapi.nat44_user_session_dump(self.pg4.remote_ip4n, 10)
magalik23caa882017-02-08 23:25:45 -08001741 self.assertTrue(len(sessions) >= 4)
1742 for session in sessions:
1743 self.assertFalse(session.is_static)
1744 self.assertEqual(session.inside_ip_address[0:4],
1745 self.pg4.remote_ip4n)
1746 self.assertEqual(session.outside_ip_address,
1747 addresses[0].ip_address)
1748
1749 # pg6 session dump
Matus Fabian2ba92e32017-08-21 07:05:03 -07001750 sessions = self.vapi.nat44_user_session_dump(self.pg6.remote_ip4n, 20)
magalik23caa882017-02-08 23:25:45 -08001751 self.assertTrue(len(sessions) >= 3)
1752 for session in sessions:
1753 self.assertTrue(session.is_static)
1754 self.assertEqual(session.inside_ip_address[0:4],
1755 self.pg6.remote_ip4n)
1756 self.assertEqual(map(ord, session.outside_ip_address[0:4]),
1757 map(int, static_nat_ip.split('.')))
1758 self.assertTrue(session.inside_port in
1759 [self.tcp_port_in, self.udp_port_in,
1760 self.icmp_id_in])
1761
Matus Fabianf78a70d2016-12-12 04:30:39 -08001762 def test_hairpinning(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001763 """ NAT44 hairpinning - 1:1 NAPT """
Matus Fabianf78a70d2016-12-12 04:30:39 -08001764
1765 host = self.pg0.remote_hosts[0]
1766 server = self.pg0.remote_hosts[1]
1767 host_in_port = 1234
1768 host_out_port = 0
1769 server_in_port = 5678
1770 server_out_port = 8765
1771
Matus Fabian2ba92e32017-08-21 07:05:03 -07001772 self.nat44_add_address(self.nat_addr)
1773 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1774 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1775 is_inside=0)
Matus Fabianf78a70d2016-12-12 04:30:39 -08001776 # add static mapping for server
Matus Fabian2ba92e32017-08-21 07:05:03 -07001777 self.nat44_add_static_mapping(server.ip4, self.nat_addr,
1778 server_in_port, server_out_port,
1779 proto=IP_PROTOS.tcp)
Matus Fabianf78a70d2016-12-12 04:30:39 -08001780
1781 # send packet from host to server
1782 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07001783 IP(src=host.ip4, dst=self.nat_addr) /
Matus Fabianf78a70d2016-12-12 04:30:39 -08001784 TCP(sport=host_in_port, dport=server_out_port))
1785 self.pg0.add_stream(p)
1786 self.pg_enable_capture(self.pg_interfaces)
1787 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001788 capture = self.pg0.get_capture(1)
Matus Fabianf78a70d2016-12-12 04:30:39 -08001789 p = capture[0]
1790 try:
1791 ip = p[IP]
1792 tcp = p[TCP]
Matus Fabian2ba92e32017-08-21 07:05:03 -07001793 self.assertEqual(ip.src, self.nat_addr)
Matus Fabianf78a70d2016-12-12 04:30:39 -08001794 self.assertEqual(ip.dst, server.ip4)
1795 self.assertNotEqual(tcp.sport, host_in_port)
1796 self.assertEqual(tcp.dport, server_in_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02001797 self.assert_packet_checksums_valid(p)
Matus Fabianf78a70d2016-12-12 04:30:39 -08001798 host_out_port = tcp.sport
1799 except:
Klement Sekera9225dee2016-12-12 08:36:58 +01001800 self.logger.error(ppp("Unexpected or invalid packet:", p))
Matus Fabianf78a70d2016-12-12 04:30:39 -08001801 raise
1802
1803 # send reply from server to host
1804 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07001805 IP(src=server.ip4, dst=self.nat_addr) /
Matus Fabianf78a70d2016-12-12 04:30:39 -08001806 TCP(sport=server_in_port, dport=host_out_port))
1807 self.pg0.add_stream(p)
1808 self.pg_enable_capture(self.pg_interfaces)
1809 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001810 capture = self.pg0.get_capture(1)
Matus Fabianf78a70d2016-12-12 04:30:39 -08001811 p = capture[0]
1812 try:
1813 ip = p[IP]
1814 tcp = p[TCP]
Matus Fabian2ba92e32017-08-21 07:05:03 -07001815 self.assertEqual(ip.src, self.nat_addr)
Matus Fabianf78a70d2016-12-12 04:30:39 -08001816 self.assertEqual(ip.dst, host.ip4)
1817 self.assertEqual(tcp.sport, server_out_port)
1818 self.assertEqual(tcp.dport, host_in_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02001819 self.assert_packet_checksums_valid(p)
Matus Fabianf78a70d2016-12-12 04:30:39 -08001820 except:
Matus Fabiane82488f2018-01-18 03:38:45 -08001821 self.logger.error(ppp("Unexpected or invalid packet:", p))
Matus Fabianf78a70d2016-12-12 04:30:39 -08001822 raise
1823
Matus Fabian6fa74c62017-06-05 05:55:48 -07001824 def test_hairpinning2(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001825 """ NAT44 hairpinning - 1:1 NAT"""
Matus Fabian6fa74c62017-06-05 05:55:48 -07001826
1827 server1_nat_ip = "10.0.0.10"
1828 server2_nat_ip = "10.0.0.11"
1829 host = self.pg0.remote_hosts[0]
1830 server1 = self.pg0.remote_hosts[1]
1831 server2 = self.pg0.remote_hosts[2]
1832 server_tcp_port = 22
1833 server_udp_port = 20
1834
Matus Fabian2ba92e32017-08-21 07:05:03 -07001835 self.nat44_add_address(self.nat_addr)
1836 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1837 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1838 is_inside=0)
Matus Fabian6fa74c62017-06-05 05:55:48 -07001839
1840 # add static mapping for servers
Matus Fabian2ba92e32017-08-21 07:05:03 -07001841 self.nat44_add_static_mapping(server1.ip4, server1_nat_ip)
1842 self.nat44_add_static_mapping(server2.ip4, server2_nat_ip)
Matus Fabian6fa74c62017-06-05 05:55:48 -07001843
1844 # host to server1
1845 pkts = []
1846 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1847 IP(src=host.ip4, dst=server1_nat_ip) /
1848 TCP(sport=self.tcp_port_in, dport=server_tcp_port))
1849 pkts.append(p)
1850 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1851 IP(src=host.ip4, dst=server1_nat_ip) /
1852 UDP(sport=self.udp_port_in, dport=server_udp_port))
1853 pkts.append(p)
1854 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1855 IP(src=host.ip4, dst=server1_nat_ip) /
1856 ICMP(id=self.icmp_id_in, type='echo-request'))
1857 pkts.append(p)
1858 self.pg0.add_stream(pkts)
1859 self.pg_enable_capture(self.pg_interfaces)
1860 self.pg_start()
1861 capture = self.pg0.get_capture(len(pkts))
1862 for packet in capture:
1863 try:
Matus Fabian2ba92e32017-08-21 07:05:03 -07001864 self.assertEqual(packet[IP].src, self.nat_addr)
Matus Fabian6fa74c62017-06-05 05:55:48 -07001865 self.assertEqual(packet[IP].dst, server1.ip4)
1866 if packet.haslayer(TCP):
1867 self.assertNotEqual(packet[TCP].sport, self.tcp_port_in)
1868 self.assertEqual(packet[TCP].dport, server_tcp_port)
1869 self.tcp_port_out = packet[TCP].sport
Klement Sekerad81ae412018-05-16 10:52:54 +02001870 self.assert_packet_checksums_valid(packet)
Matus Fabian6fa74c62017-06-05 05:55:48 -07001871 elif packet.haslayer(UDP):
1872 self.assertNotEqual(packet[UDP].sport, self.udp_port_in)
1873 self.assertEqual(packet[UDP].dport, server_udp_port)
1874 self.udp_port_out = packet[UDP].sport
1875 else:
1876 self.assertNotEqual(packet[ICMP].id, self.icmp_id_in)
1877 self.icmp_id_out = packet[ICMP].id
1878 except:
1879 self.logger.error(ppp("Unexpected or invalid packet:", packet))
1880 raise
1881
1882 # server1 to host
1883 pkts = []
1884 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07001885 IP(src=server1.ip4, dst=self.nat_addr) /
Matus Fabian6fa74c62017-06-05 05:55:48 -07001886 TCP(sport=server_tcp_port, dport=self.tcp_port_out))
1887 pkts.append(p)
1888 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07001889 IP(src=server1.ip4, dst=self.nat_addr) /
Matus Fabian6fa74c62017-06-05 05:55:48 -07001890 UDP(sport=server_udp_port, dport=self.udp_port_out))
1891 pkts.append(p)
1892 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07001893 IP(src=server1.ip4, dst=self.nat_addr) /
Matus Fabian6fa74c62017-06-05 05:55:48 -07001894 ICMP(id=self.icmp_id_out, type='echo-reply'))
1895 pkts.append(p)
1896 self.pg0.add_stream(pkts)
1897 self.pg_enable_capture(self.pg_interfaces)
1898 self.pg_start()
1899 capture = self.pg0.get_capture(len(pkts))
1900 for packet in capture:
1901 try:
1902 self.assertEqual(packet[IP].src, server1_nat_ip)
1903 self.assertEqual(packet[IP].dst, host.ip4)
1904 if packet.haslayer(TCP):
1905 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
1906 self.assertEqual(packet[TCP].sport, server_tcp_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02001907 self.assert_packet_checksums_valid(packet)
Matus Fabian6fa74c62017-06-05 05:55:48 -07001908 elif packet.haslayer(UDP):
1909 self.assertEqual(packet[UDP].dport, self.udp_port_in)
1910 self.assertEqual(packet[UDP].sport, server_udp_port)
1911 else:
1912 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
1913 except:
1914 self.logger.error(ppp("Unexpected or invalid packet:", packet))
1915 raise
1916
1917 # server2 to server1
1918 pkts = []
1919 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1920 IP(src=server2.ip4, dst=server1_nat_ip) /
1921 TCP(sport=self.tcp_port_in, dport=server_tcp_port))
1922 pkts.append(p)
1923 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1924 IP(src=server2.ip4, dst=server1_nat_ip) /
1925 UDP(sport=self.udp_port_in, dport=server_udp_port))
1926 pkts.append(p)
1927 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1928 IP(src=server2.ip4, dst=server1_nat_ip) /
1929 ICMP(id=self.icmp_id_in, type='echo-request'))
1930 pkts.append(p)
1931 self.pg0.add_stream(pkts)
1932 self.pg_enable_capture(self.pg_interfaces)
1933 self.pg_start()
1934 capture = self.pg0.get_capture(len(pkts))
1935 for packet in capture:
1936 try:
1937 self.assertEqual(packet[IP].src, server2_nat_ip)
1938 self.assertEqual(packet[IP].dst, server1.ip4)
1939 if packet.haslayer(TCP):
1940 self.assertEqual(packet[TCP].sport, self.tcp_port_in)
1941 self.assertEqual(packet[TCP].dport, server_tcp_port)
1942 self.tcp_port_out = packet[TCP].sport
Klement Sekerad81ae412018-05-16 10:52:54 +02001943 self.assert_packet_checksums_valid(packet)
Matus Fabian6fa74c62017-06-05 05:55:48 -07001944 elif packet.haslayer(UDP):
1945 self.assertEqual(packet[UDP].sport, self.udp_port_in)
1946 self.assertEqual(packet[UDP].dport, server_udp_port)
1947 self.udp_port_out = packet[UDP].sport
1948 else:
1949 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
1950 self.icmp_id_out = packet[ICMP].id
1951 except:
1952 self.logger.error(ppp("Unexpected or invalid packet:", packet))
1953 raise
1954
1955 # server1 to server2
1956 pkts = []
1957 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1958 IP(src=server1.ip4, dst=server2_nat_ip) /
1959 TCP(sport=server_tcp_port, dport=self.tcp_port_out))
1960 pkts.append(p)
1961 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1962 IP(src=server1.ip4, dst=server2_nat_ip) /
1963 UDP(sport=server_udp_port, dport=self.udp_port_out))
1964 pkts.append(p)
1965 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1966 IP(src=server1.ip4, dst=server2_nat_ip) /
1967 ICMP(id=self.icmp_id_out, type='echo-reply'))
1968 pkts.append(p)
1969 self.pg0.add_stream(pkts)
1970 self.pg_enable_capture(self.pg_interfaces)
1971 self.pg_start()
1972 capture = self.pg0.get_capture(len(pkts))
1973 for packet in capture:
1974 try:
1975 self.assertEqual(packet[IP].src, server1_nat_ip)
1976 self.assertEqual(packet[IP].dst, server2.ip4)
1977 if packet.haslayer(TCP):
1978 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
1979 self.assertEqual(packet[TCP].sport, server_tcp_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02001980 self.assert_packet_checksums_valid(packet)
Matus Fabian6fa74c62017-06-05 05:55:48 -07001981 elif packet.haslayer(UDP):
1982 self.assertEqual(packet[UDP].dport, self.udp_port_in)
1983 self.assertEqual(packet[UDP].sport, server_udp_port)
1984 else:
1985 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
1986 except:
1987 self.logger.error(ppp("Unexpected or invalid packet:", packet))
1988 raise
1989
Matus Fabian9902fcd2016-12-21 23:58:46 -08001990 def test_max_translations_per_user(self):
1991 """ MAX translations per user - recycle the least recently used """
1992
Matus Fabian2ba92e32017-08-21 07:05:03 -07001993 self.nat44_add_address(self.nat_addr)
1994 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1995 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1996 is_inside=0)
Matus Fabian9902fcd2016-12-21 23:58:46 -08001997
1998 # get maximum number of translations per user
Matus Fabian2ba92e32017-08-21 07:05:03 -07001999 nat44_config = self.vapi.nat_show_config()
Matus Fabian9902fcd2016-12-21 23:58:46 -08002000
2001 # send more than maximum number of translations per user packets
Matus Fabian2ba92e32017-08-21 07:05:03 -07002002 pkts_num = nat44_config.max_translations_per_user + 5
Matus Fabian9902fcd2016-12-21 23:58:46 -08002003 pkts = []
2004 for port in range(0, pkts_num):
2005 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2006 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2007 TCP(sport=1025 + port))
2008 pkts.append(p)
2009 self.pg0.add_stream(pkts)
2010 self.pg_enable_capture(self.pg_interfaces)
2011 self.pg_start()
2012
2013 # verify number of translated packet
Klement Sekeradab231a2016-12-21 08:50:14 +01002014 self.pg1.get_capture(pkts_num)
Matus Fabian9902fcd2016-12-21 23:58:46 -08002015
Matus Fabian132dc492018-05-09 04:51:03 -07002016 users = self.vapi.nat44_user_dump()
2017 for user in users:
2018 if user.ip_address == self.pg0.remote_ip4n:
2019 self.assertEqual(user.nsessions,
2020 nat44_config.max_translations_per_user)
2021 self.assertEqual(user.nstaticsessions, 0)
2022
2023 tcp_port = 22
2024 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
2025 tcp_port, tcp_port,
2026 proto=IP_PROTOS.tcp)
2027 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2028 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2029 TCP(sport=tcp_port))
2030 self.pg0.add_stream(p)
2031 self.pg_enable_capture(self.pg_interfaces)
2032 self.pg_start()
2033 self.pg1.get_capture(1)
2034 users = self.vapi.nat44_user_dump()
2035 for user in users:
2036 if user.ip_address == self.pg0.remote_ip4n:
2037 self.assertEqual(user.nsessions,
2038 nat44_config.max_translations_per_user - 1)
2039 self.assertEqual(user.nstaticsessions, 1)
2040
Matus Fabian8bf68e82017-01-12 04:24:35 -08002041 def test_interface_addr(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002042 """ Acquire NAT44 addresses from interface """
2043 self.vapi.nat44_add_interface_addr(self.pg7.sw_if_index)
Matus Fabian8bf68e82017-01-12 04:24:35 -08002044
2045 # no address in NAT pool
Matus Fabian2ba92e32017-08-21 07:05:03 -07002046 adresses = self.vapi.nat44_address_dump()
Matus Fabian8bf68e82017-01-12 04:24:35 -08002047 self.assertEqual(0, len(adresses))
2048
2049 # configure interface address and check NAT address pool
2050 self.pg7.config_ip4()
Matus Fabian2ba92e32017-08-21 07:05:03 -07002051 adresses = self.vapi.nat44_address_dump()
Matus Fabian8bf68e82017-01-12 04:24:35 -08002052 self.assertEqual(1, len(adresses))
Matus Fabian36532bd2017-01-23 23:42:28 -08002053 self.assertEqual(adresses[0].ip_address[0:4], self.pg7.local_ip4n)
Matus Fabian8bf68e82017-01-12 04:24:35 -08002054
2055 # remove interface address and check NAT address pool
2056 self.pg7.unconfig_ip4()
Matus Fabian2ba92e32017-08-21 07:05:03 -07002057 adresses = self.vapi.nat44_address_dump()
Matus Fabian8bf68e82017-01-12 04:24:35 -08002058 self.assertEqual(0, len(adresses))
2059
Matus Fabian36532bd2017-01-23 23:42:28 -08002060 def test_interface_addr_static_mapping(self):
2061 """ Static mapping with addresses from interface """
Matus Fabian5f224992018-01-25 21:59:16 -08002062 tag = "testTAG"
2063
Matus Fabian2ba92e32017-08-21 07:05:03 -07002064 self.vapi.nat44_add_interface_addr(self.pg7.sw_if_index)
2065 self.nat44_add_static_mapping(
2066 '1.2.3.4',
Matus Fabian5f224992018-01-25 21:59:16 -08002067 external_sw_if_index=self.pg7.sw_if_index,
2068 tag=tag)
Matus Fabian36532bd2017-01-23 23:42:28 -08002069
Matus Fabiane22e5462017-02-14 23:33:43 -08002070 # static mappings with external interface
Matus Fabian2ba92e32017-08-21 07:05:03 -07002071 static_mappings = self.vapi.nat44_static_mapping_dump()
Matus Fabiane22e5462017-02-14 23:33:43 -08002072 self.assertEqual(1, len(static_mappings))
2073 self.assertEqual(self.pg7.sw_if_index,
2074 static_mappings[0].external_sw_if_index)
Matus Fabian5f224992018-01-25 21:59:16 -08002075 self.assertEqual((static_mappings[0].tag).split('\0', 1)[0], tag)
Matus Fabian36532bd2017-01-23 23:42:28 -08002076
2077 # configure interface address and check static mappings
2078 self.pg7.config_ip4()
Matus Fabian2ba92e32017-08-21 07:05:03 -07002079 static_mappings = self.vapi.nat44_static_mapping_dump()
Matus Fabianea2600a2018-03-28 04:06:26 -07002080 self.assertEqual(2, len(static_mappings))
2081 resolved = False
2082 for sm in static_mappings:
2083 if sm.external_sw_if_index == 0xFFFFFFFF:
2084 self.assertEqual(sm.external_ip_address[0:4],
2085 self.pg7.local_ip4n)
2086 self.assertEqual((sm.tag).split('\0', 1)[0], tag)
2087 resolved = True
2088 self.assertTrue(resolved)
Matus Fabian36532bd2017-01-23 23:42:28 -08002089
2090 # remove interface address and check static mappings
2091 self.pg7.unconfig_ip4()
Matus Fabian2ba92e32017-08-21 07:05:03 -07002092 static_mappings = self.vapi.nat44_static_mapping_dump()
Matus Fabianea2600a2018-03-28 04:06:26 -07002093 self.assertEqual(1, len(static_mappings))
2094 self.assertEqual(self.pg7.sw_if_index,
2095 static_mappings[0].external_sw_if_index)
2096 self.assertEqual((static_mappings[0].tag).split('\0', 1)[0], tag)
2097
2098 # configure interface address again and check static mappings
2099 self.pg7.config_ip4()
2100 static_mappings = self.vapi.nat44_static_mapping_dump()
2101 self.assertEqual(2, len(static_mappings))
2102 resolved = False
2103 for sm in static_mappings:
2104 if sm.external_sw_if_index == 0xFFFFFFFF:
2105 self.assertEqual(sm.external_ip_address[0:4],
2106 self.pg7.local_ip4n)
2107 self.assertEqual((sm.tag).split('\0', 1)[0], tag)
2108 resolved = True
2109 self.assertTrue(resolved)
2110
2111 # remove static mapping
2112 self.nat44_add_static_mapping(
2113 '1.2.3.4',
2114 external_sw_if_index=self.pg7.sw_if_index,
2115 tag=tag,
2116 is_add=0)
2117 static_mappings = self.vapi.nat44_static_mapping_dump()
Matus Fabian36532bd2017-01-23 23:42:28 -08002118 self.assertEqual(0, len(static_mappings))
2119
Matus Fabianab7a8052017-11-28 04:29:41 -08002120 def test_interface_addr_identity_nat(self):
2121 """ Identity NAT with addresses from interface """
2122
2123 port = 53053
2124 self.vapi.nat44_add_interface_addr(self.pg7.sw_if_index)
2125 self.vapi.nat44_add_del_identity_mapping(
2126 sw_if_index=self.pg7.sw_if_index,
2127 port=port,
2128 protocol=IP_PROTOS.tcp,
2129 addr_only=0)
2130
2131 # identity mappings with external interface
2132 identity_mappings = self.vapi.nat44_identity_mapping_dump()
2133 self.assertEqual(1, len(identity_mappings))
2134 self.assertEqual(self.pg7.sw_if_index,
2135 identity_mappings[0].sw_if_index)
2136
2137 # configure interface address and check identity mappings
2138 self.pg7.config_ip4()
2139 identity_mappings = self.vapi.nat44_identity_mapping_dump()
Matus Fabianea2600a2018-03-28 04:06:26 -07002140 resolved = False
2141 self.assertEqual(2, len(identity_mappings))
2142 for sm in identity_mappings:
2143 if sm.sw_if_index == 0xFFFFFFFF:
2144 self.assertEqual(identity_mappings[0].ip_address,
2145 self.pg7.local_ip4n)
2146 self.assertEqual(port, identity_mappings[0].port)
2147 self.assertEqual(IP_PROTOS.tcp, identity_mappings[0].protocol)
2148 resolved = True
2149 self.assertTrue(resolved)
Matus Fabianab7a8052017-11-28 04:29:41 -08002150
2151 # remove interface address and check identity mappings
2152 self.pg7.unconfig_ip4()
2153 identity_mappings = self.vapi.nat44_identity_mapping_dump()
Matus Fabianea2600a2018-03-28 04:06:26 -07002154 self.assertEqual(1, len(identity_mappings))
2155 self.assertEqual(self.pg7.sw_if_index,
2156 identity_mappings[0].sw_if_index)
Matus Fabianab7a8052017-11-28 04:29:41 -08002157
Matus Fabianeea28d72017-01-13 04:15:54 -08002158 def test_ipfix_nat44_sess(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002159 """ IPFIX logging NAT44 session created/delted """
Matus Fabian6631e9c2017-05-24 01:52:20 -07002160 self.ipfix_domain_id = 10
2161 self.ipfix_src_port = 20202
2162 colector_port = 30303
2163 bind_layers(UDP, IPFIX, dport=30303)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002164 self.nat44_add_address(self.nat_addr)
2165 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2166 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2167 is_inside=0)
Matus Fabianeea28d72017-01-13 04:15:54 -08002168 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
2169 src_address=self.pg3.local_ip4n,
2170 path_mtu=512,
Matus Fabian6631e9c2017-05-24 01:52:20 -07002171 template_interval=10,
2172 collector_port=colector_port)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002173 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
2174 src_port=self.ipfix_src_port)
Matus Fabianeea28d72017-01-13 04:15:54 -08002175
2176 pkts = self.create_stream_in(self.pg0, self.pg1)
2177 self.pg0.add_stream(pkts)
2178 self.pg_enable_capture(self.pg_interfaces)
2179 self.pg_start()
2180 capture = self.pg1.get_capture(len(pkts))
2181 self.verify_capture_out(capture)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002182 self.nat44_add_address(self.nat_addr, is_add=0)
Matus Fabianeea28d72017-01-13 04:15:54 -08002183 self.vapi.cli("ipfix flush") # FIXME this should be an API call
Matus Fabiana431ad12018-01-04 04:03:14 -08002184 capture = self.pg3.get_capture(9)
Matus Fabianeea28d72017-01-13 04:15:54 -08002185 ipfix = IPFIXDecoder()
2186 # first load template
2187 for p in capture:
2188 self.assertTrue(p.haslayer(IPFIX))
Matus Fabian6631e9c2017-05-24 01:52:20 -07002189 self.assertEqual(p[IP].src, self.pg3.local_ip4)
2190 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2191 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2192 self.assertEqual(p[UDP].dport, colector_port)
2193 self.assertEqual(p[IPFIX].observationDomainID,
2194 self.ipfix_domain_id)
Matus Fabianeea28d72017-01-13 04:15:54 -08002195 if p.haslayer(Template):
2196 ipfix.add_template(p.getlayer(Template))
2197 # verify events in data set
2198 for p in capture:
2199 if p.haslayer(Data):
2200 data = ipfix.decode_data_set(p.getlayer(Set))
2201 self.verify_ipfix_nat44_ses(data)
2202
2203 def test_ipfix_addr_exhausted(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002204 """ IPFIX logging NAT addresses exhausted """
2205 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2206 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2207 is_inside=0)
Matus Fabianeea28d72017-01-13 04:15:54 -08002208 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
2209 src_address=self.pg3.local_ip4n,
2210 path_mtu=512,
2211 template_interval=10)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002212 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
2213 src_port=self.ipfix_src_port)
Matus Fabianeea28d72017-01-13 04:15:54 -08002214
2215 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
2216 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2217 TCP(sport=3025))
2218 self.pg0.add_stream(p)
2219 self.pg_enable_capture(self.pg_interfaces)
2220 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07002221 self.pg1.assert_nothing_captured()
2222 sleep(1)
Matus Fabianeea28d72017-01-13 04:15:54 -08002223 self.vapi.cli("ipfix flush") # FIXME this should be an API call
Matus Fabiana431ad12018-01-04 04:03:14 -08002224 capture = self.pg3.get_capture(9)
Matus Fabianeea28d72017-01-13 04:15:54 -08002225 ipfix = IPFIXDecoder()
2226 # first load template
2227 for p in capture:
2228 self.assertTrue(p.haslayer(IPFIX))
Matus Fabian6631e9c2017-05-24 01:52:20 -07002229 self.assertEqual(p[IP].src, self.pg3.local_ip4)
2230 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2231 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2232 self.assertEqual(p[UDP].dport, 4739)
2233 self.assertEqual(p[IPFIX].observationDomainID,
2234 self.ipfix_domain_id)
Matus Fabianeea28d72017-01-13 04:15:54 -08002235 if p.haslayer(Template):
2236 ipfix.add_template(p.getlayer(Template))
2237 # verify events in data set
2238 for p in capture:
2239 if p.haslayer(Data):
2240 data = ipfix.decode_data_set(p.getlayer(Set))
2241 self.verify_ipfix_addr_exhausted(data)
2242
Matus Fabiana431ad12018-01-04 04:03:14 -08002243 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
2244 def test_ipfix_max_sessions(self):
2245 """ IPFIX logging maximum session entries exceeded """
2246 self.nat44_add_address(self.nat_addr)
2247 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2248 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2249 is_inside=0)
2250
2251 nat44_config = self.vapi.nat_show_config()
2252 max_sessions = 10 * nat44_config.translation_buckets
2253
2254 pkts = []
2255 for i in range(0, max_sessions):
2256 src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
2257 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2258 IP(src=src, dst=self.pg1.remote_ip4) /
2259 TCP(sport=1025))
2260 pkts.append(p)
2261 self.pg0.add_stream(pkts)
2262 self.pg_enable_capture(self.pg_interfaces)
2263 self.pg_start()
2264
2265 self.pg1.get_capture(max_sessions)
2266 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
2267 src_address=self.pg3.local_ip4n,
2268 path_mtu=512,
2269 template_interval=10)
2270 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
2271 src_port=self.ipfix_src_port)
2272
2273 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2274 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2275 TCP(sport=1025))
2276 self.pg0.add_stream(p)
2277 self.pg_enable_capture(self.pg_interfaces)
2278 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07002279 self.pg1.assert_nothing_captured()
2280 sleep(1)
Matus Fabiana431ad12018-01-04 04:03:14 -08002281 self.vapi.cli("ipfix flush") # FIXME this should be an API call
2282 capture = self.pg3.get_capture(9)
2283 ipfix = IPFIXDecoder()
2284 # first load template
2285 for p in capture:
2286 self.assertTrue(p.haslayer(IPFIX))
2287 self.assertEqual(p[IP].src, self.pg3.local_ip4)
2288 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2289 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2290 self.assertEqual(p[UDP].dport, 4739)
2291 self.assertEqual(p[IPFIX].observationDomainID,
2292 self.ipfix_domain_id)
2293 if p.haslayer(Template):
2294 ipfix.add_template(p.getlayer(Template))
2295 # verify events in data set
2296 for p in capture:
2297 if p.haslayer(Data):
2298 data = ipfix.decode_data_set(p.getlayer(Set))
2299 self.verify_ipfix_max_sessions(data, max_sessions)
2300
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002301 def test_pool_addr_fib(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002302 """ NAT44 add pool addresses to FIB """
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002303 static_addr = '10.0.0.10'
Matus Fabian2ba92e32017-08-21 07:05:03 -07002304 self.nat44_add_address(self.nat_addr)
2305 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2306 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2307 is_inside=0)
2308 self.nat44_add_static_mapping(self.pg0.remote_ip4, static_addr)
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002309
Matus Fabian2ba92e32017-08-21 07:05:03 -07002310 # NAT44 address
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002311 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002312 ARP(op=ARP.who_has, pdst=self.nat_addr,
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002313 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2314 self.pg1.add_stream(p)
2315 self.pg_enable_capture(self.pg_interfaces)
2316 self.pg_start()
2317 capture = self.pg1.get_capture(1)
2318 self.assertTrue(capture[0].haslayer(ARP))
2319 self.assertTrue(capture[0][ARP].op, ARP.is_at)
2320
2321 # 1:1 NAT address
2322 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2323 ARP(op=ARP.who_has, pdst=static_addr,
2324 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2325 self.pg1.add_stream(p)
2326 self.pg_enable_capture(self.pg_interfaces)
2327 self.pg_start()
2328 capture = self.pg1.get_capture(1)
2329 self.assertTrue(capture[0].haslayer(ARP))
2330 self.assertTrue(capture[0][ARP].op, ARP.is_at)
2331
Matus Fabian2ba92e32017-08-21 07:05:03 -07002332 # send ARP to non-NAT44 interface
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002333 p = (Ether(src=self.pg2.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002334 ARP(op=ARP.who_has, pdst=self.nat_addr,
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002335 psrc=self.pg2.remote_ip4, hwsrc=self.pg2.remote_mac))
2336 self.pg2.add_stream(p)
2337 self.pg_enable_capture(self.pg_interfaces)
2338 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07002339 self.pg1.assert_nothing_captured()
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002340
2341 # remove addresses and verify
Matus Fabian2ba92e32017-08-21 07:05:03 -07002342 self.nat44_add_address(self.nat_addr, is_add=0)
2343 self.nat44_add_static_mapping(self.pg0.remote_ip4, static_addr,
2344 is_add=0)
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002345
2346 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002347 ARP(op=ARP.who_has, pdst=self.nat_addr,
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002348 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2349 self.pg1.add_stream(p)
2350 self.pg_enable_capture(self.pg_interfaces)
2351 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07002352 self.pg1.assert_nothing_captured()
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002353
2354 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2355 ARP(op=ARP.who_has, pdst=static_addr,
2356 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2357 self.pg1.add_stream(p)
2358 self.pg_enable_capture(self.pg_interfaces)
2359 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07002360 self.pg1.assert_nothing_captured()
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002361
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002362 def test_vrf_mode(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002363 """ NAT44 tenant VRF aware address pool mode """
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002364
2365 vrf_id1 = 1
2366 vrf_id2 = 2
2367 nat_ip1 = "10.0.0.10"
2368 nat_ip2 = "10.0.0.11"
2369
2370 self.pg0.unconfig_ip4()
2371 self.pg1.unconfig_ip4()
Neale Ranns15002542017-09-10 04:39:11 -07002372 self.vapi.ip_table_add_del(vrf_id1, is_add=1)
2373 self.vapi.ip_table_add_del(vrf_id2, is_add=1)
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002374 self.pg0.set_table_ip4(vrf_id1)
2375 self.pg1.set_table_ip4(vrf_id2)
2376 self.pg0.config_ip4()
2377 self.pg1.config_ip4()
Matus Fabian8008d7c2018-07-09 01:34:20 -07002378 self.pg0.resolve_arp()
2379 self.pg1.resolve_arp()
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002380
Matus Fabian2ba92e32017-08-21 07:05:03 -07002381 self.nat44_add_address(nat_ip1, vrf_id=vrf_id1)
2382 self.nat44_add_address(nat_ip2, vrf_id=vrf_id2)
2383 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2384 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
2385 self.vapi.nat44_interface_add_del_feature(self.pg2.sw_if_index,
2386 is_inside=0)
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002387
Matus Fabian8008d7c2018-07-09 01:34:20 -07002388 try:
2389 # first VRF
2390 pkts = self.create_stream_in(self.pg0, self.pg2)
2391 self.pg0.add_stream(pkts)
2392 self.pg_enable_capture(self.pg_interfaces)
2393 self.pg_start()
2394 capture = self.pg2.get_capture(len(pkts))
2395 self.verify_capture_out(capture, nat_ip1)
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002396
Matus Fabian8008d7c2018-07-09 01:34:20 -07002397 # second VRF
2398 pkts = self.create_stream_in(self.pg1, self.pg2)
2399 self.pg1.add_stream(pkts)
2400 self.pg_enable_capture(self.pg_interfaces)
2401 self.pg_start()
2402 capture = self.pg2.get_capture(len(pkts))
2403 self.verify_capture_out(capture, nat_ip2)
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002404
Matus Fabian8008d7c2018-07-09 01:34:20 -07002405 finally:
2406 self.pg0.unconfig_ip4()
2407 self.pg1.unconfig_ip4()
2408 self.pg0.set_table_ip4(0)
2409 self.pg1.set_table_ip4(0)
2410 self.pg0.config_ip4()
2411 self.pg1.config_ip4()
2412 self.pg0.resolve_arp()
2413 self.pg1.resolve_arp()
2414 self.vapi.ip_table_add_del(vrf_id1, is_add=0)
2415 self.vapi.ip_table_add_del(vrf_id2, is_add=0)
Neale Ranns15002542017-09-10 04:39:11 -07002416
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002417 def test_vrf_feature_independent(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002418 """ NAT44 tenant VRF independent address pool mode """
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002419
2420 nat_ip1 = "10.0.0.10"
2421 nat_ip2 = "10.0.0.11"
2422
Matus Fabian2ba92e32017-08-21 07:05:03 -07002423 self.nat44_add_address(nat_ip1)
Matus Fabian51e759f2017-12-07 23:22:51 -08002424 self.nat44_add_address(nat_ip2, vrf_id=99)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002425 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2426 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
2427 self.vapi.nat44_interface_add_del_feature(self.pg2.sw_if_index,
2428 is_inside=0)
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002429
2430 # first VRF
2431 pkts = self.create_stream_in(self.pg0, self.pg2)
2432 self.pg0.add_stream(pkts)
2433 self.pg_enable_capture(self.pg_interfaces)
2434 self.pg_start()
2435 capture = self.pg2.get_capture(len(pkts))
2436 self.verify_capture_out(capture, nat_ip1)
2437
2438 # second VRF
2439 pkts = self.create_stream_in(self.pg1, self.pg2)
2440 self.pg1.add_stream(pkts)
2441 self.pg_enable_capture(self.pg_interfaces)
2442 self.pg_start()
2443 capture = self.pg2.get_capture(len(pkts))
2444 self.verify_capture_out(capture, nat_ip1)
2445
Martin Gálik406eb1d2017-05-04 04:35:04 -07002446 def test_dynamic_ipless_interfaces(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002447 """ NAT44 interfaces without configured IP address """
Martin Gálik406eb1d2017-05-04 04:35:04 -07002448
2449 self.vapi.ip_neighbor_add_del(self.pg7.sw_if_index,
Ole Troan895b6e82017-10-20 13:28:20 +02002450 mactobinary(self.pg7.remote_mac),
Martin Gálik406eb1d2017-05-04 04:35:04 -07002451 self.pg7.remote_ip4n,
2452 is_static=1)
2453 self.vapi.ip_neighbor_add_del(self.pg8.sw_if_index,
Ole Troan895b6e82017-10-20 13:28:20 +02002454 mactobinary(self.pg8.remote_mac),
Martin Gálik406eb1d2017-05-04 04:35:04 -07002455 self.pg8.remote_ip4n,
2456 is_static=1)
2457
2458 self.vapi.ip_add_del_route(dst_address=self.pg7.remote_ip4n,
2459 dst_address_length=32,
2460 next_hop_address=self.pg7.remote_ip4n,
2461 next_hop_sw_if_index=self.pg7.sw_if_index)
2462 self.vapi.ip_add_del_route(dst_address=self.pg8.remote_ip4n,
2463 dst_address_length=32,
2464 next_hop_address=self.pg8.remote_ip4n,
2465 next_hop_sw_if_index=self.pg8.sw_if_index)
2466
Matus Fabian2ba92e32017-08-21 07:05:03 -07002467 self.nat44_add_address(self.nat_addr)
2468 self.vapi.nat44_interface_add_del_feature(self.pg7.sw_if_index)
2469 self.vapi.nat44_interface_add_del_feature(self.pg8.sw_if_index,
2470 is_inside=0)
Martin Gálik406eb1d2017-05-04 04:35:04 -07002471
2472 # in2out
2473 pkts = self.create_stream_in(self.pg7, self.pg8)
2474 self.pg7.add_stream(pkts)
2475 self.pg_enable_capture(self.pg_interfaces)
2476 self.pg_start()
2477 capture = self.pg8.get_capture(len(pkts))
2478 self.verify_capture_out(capture)
2479
2480 # out2in
Matus Fabian2ba92e32017-08-21 07:05:03 -07002481 pkts = self.create_stream_out(self.pg8, self.nat_addr)
Martin Gálik406eb1d2017-05-04 04:35:04 -07002482 self.pg8.add_stream(pkts)
2483 self.pg_enable_capture(self.pg_interfaces)
2484 self.pg_start()
2485 capture = self.pg7.get_capture(len(pkts))
2486 self.verify_capture_in(capture, self.pg7)
2487
2488 def test_static_ipless_interfaces(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002489 """ NAT44 interfaces without configured IP address - 1:1 NAT """
Martin Gálik406eb1d2017-05-04 04:35:04 -07002490
2491 self.vapi.ip_neighbor_add_del(self.pg7.sw_if_index,
Ole Troan895b6e82017-10-20 13:28:20 +02002492 mactobinary(self.pg7.remote_mac),
Martin Gálik406eb1d2017-05-04 04:35:04 -07002493 self.pg7.remote_ip4n,
2494 is_static=1)
2495 self.vapi.ip_neighbor_add_del(self.pg8.sw_if_index,
Ole Troan895b6e82017-10-20 13:28:20 +02002496 mactobinary(self.pg8.remote_mac),
Martin Gálik406eb1d2017-05-04 04:35:04 -07002497 self.pg8.remote_ip4n,
2498 is_static=1)
2499
2500 self.vapi.ip_add_del_route(dst_address=self.pg7.remote_ip4n,
2501 dst_address_length=32,
2502 next_hop_address=self.pg7.remote_ip4n,
2503 next_hop_sw_if_index=self.pg7.sw_if_index)
2504 self.vapi.ip_add_del_route(dst_address=self.pg8.remote_ip4n,
2505 dst_address_length=32,
2506 next_hop_address=self.pg8.remote_ip4n,
2507 next_hop_sw_if_index=self.pg8.sw_if_index)
2508
Matus Fabian2ba92e32017-08-21 07:05:03 -07002509 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr)
2510 self.vapi.nat44_interface_add_del_feature(self.pg7.sw_if_index)
2511 self.vapi.nat44_interface_add_del_feature(self.pg8.sw_if_index,
2512 is_inside=0)
Martin Gálik406eb1d2017-05-04 04:35:04 -07002513
2514 # out2in
2515 pkts = self.create_stream_out(self.pg8)
2516 self.pg8.add_stream(pkts)
2517 self.pg_enable_capture(self.pg_interfaces)
2518 self.pg_start()
2519 capture = self.pg7.get_capture(len(pkts))
2520 self.verify_capture_in(capture, self.pg7)
2521
2522 # in2out
2523 pkts = self.create_stream_in(self.pg7, self.pg8)
2524 self.pg7.add_stream(pkts)
2525 self.pg_enable_capture(self.pg_interfaces)
2526 self.pg_start()
2527 capture = self.pg8.get_capture(len(pkts))
Matus Fabian2ba92e32017-08-21 07:05:03 -07002528 self.verify_capture_out(capture, self.nat_addr, True)
Martin Gálik406eb1d2017-05-04 04:35:04 -07002529
2530 def test_static_with_port_ipless_interfaces(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002531 """ NAT44 interfaces without configured IP address - 1:1 NAPT """
Martin Gálik406eb1d2017-05-04 04:35:04 -07002532
2533 self.tcp_port_out = 30606
2534 self.udp_port_out = 30607
2535 self.icmp_id_out = 30608
2536
2537 self.vapi.ip_neighbor_add_del(self.pg7.sw_if_index,
Ole Troan895b6e82017-10-20 13:28:20 +02002538 mactobinary(self.pg7.remote_mac),
Martin Gálik406eb1d2017-05-04 04:35:04 -07002539 self.pg7.remote_ip4n,
2540 is_static=1)
2541 self.vapi.ip_neighbor_add_del(self.pg8.sw_if_index,
Ole Troan895b6e82017-10-20 13:28:20 +02002542 mactobinary(self.pg8.remote_mac),
Martin Gálik406eb1d2017-05-04 04:35:04 -07002543 self.pg8.remote_ip4n,
2544 is_static=1)
2545
2546 self.vapi.ip_add_del_route(dst_address=self.pg7.remote_ip4n,
2547 dst_address_length=32,
2548 next_hop_address=self.pg7.remote_ip4n,
2549 next_hop_sw_if_index=self.pg7.sw_if_index)
2550 self.vapi.ip_add_del_route(dst_address=self.pg8.remote_ip4n,
2551 dst_address_length=32,
2552 next_hop_address=self.pg8.remote_ip4n,
2553 next_hop_sw_if_index=self.pg8.sw_if_index)
2554
Matus Fabian2ba92e32017-08-21 07:05:03 -07002555 self.nat44_add_address(self.nat_addr)
2556 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
2557 self.tcp_port_in, self.tcp_port_out,
2558 proto=IP_PROTOS.tcp)
2559 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
2560 self.udp_port_in, self.udp_port_out,
2561 proto=IP_PROTOS.udp)
2562 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
2563 self.icmp_id_in, self.icmp_id_out,
2564 proto=IP_PROTOS.icmp)
2565 self.vapi.nat44_interface_add_del_feature(self.pg7.sw_if_index)
2566 self.vapi.nat44_interface_add_del_feature(self.pg8.sw_if_index,
2567 is_inside=0)
Martin Gálik406eb1d2017-05-04 04:35:04 -07002568
2569 # out2in
2570 pkts = self.create_stream_out(self.pg8)
2571 self.pg8.add_stream(pkts)
2572 self.pg_enable_capture(self.pg_interfaces)
2573 self.pg_start()
2574 capture = self.pg7.get_capture(len(pkts))
2575 self.verify_capture_in(capture, self.pg7)
2576
2577 # in2out
2578 pkts = self.create_stream_in(self.pg7, self.pg8)
2579 self.pg7.add_stream(pkts)
2580 self.pg_enable_capture(self.pg_interfaces)
2581 self.pg_start()
2582 capture = self.pg8.get_capture(len(pkts))
2583 self.verify_capture_out(capture)
2584
Matus Fabian328dbc82017-06-19 04:28:04 -07002585 def test_static_unknown_proto(self):
2586 """ 1:1 NAT translate packet with unknown protocol """
2587 nat_ip = "10.0.0.10"
Matus Fabian2ba92e32017-08-21 07:05:03 -07002588 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
2589 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2590 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2591 is_inside=0)
Matus Fabian328dbc82017-06-19 04:28:04 -07002592
2593 # in2out
2594 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2595 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2596 GRE() /
Matus Fabian1e8db5f2017-06-20 01:45:49 -07002597 IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4) /
Matus Fabian328dbc82017-06-19 04:28:04 -07002598 TCP(sport=1234, dport=1234))
2599 self.pg0.add_stream(p)
2600 self.pg_enable_capture(self.pg_interfaces)
2601 self.pg_start()
2602 p = self.pg1.get_capture(1)
2603 packet = p[0]
2604 try:
2605 self.assertEqual(packet[IP].src, nat_ip)
2606 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
2607 self.assertTrue(packet.haslayer(GRE))
Klement Sekerad81ae412018-05-16 10:52:54 +02002608 self.assert_packet_checksums_valid(packet)
Matus Fabian328dbc82017-06-19 04:28:04 -07002609 except:
2610 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2611 raise
2612
2613 # out2in
2614 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
2615 IP(src=self.pg1.remote_ip4, dst=nat_ip) /
2616 GRE() /
Matus Fabian1e8db5f2017-06-20 01:45:49 -07002617 IP(src=self.pg3.remote_ip4, dst=self.pg2.remote_ip4) /
Matus Fabian328dbc82017-06-19 04:28:04 -07002618 TCP(sport=1234, dport=1234))
2619 self.pg1.add_stream(p)
2620 self.pg_enable_capture(self.pg_interfaces)
2621 self.pg_start()
2622 p = self.pg0.get_capture(1)
2623 packet = p[0]
2624 try:
2625 self.assertEqual(packet[IP].src, self.pg1.remote_ip4)
2626 self.assertEqual(packet[IP].dst, self.pg0.remote_ip4)
2627 self.assertTrue(packet.haslayer(GRE))
Klement Sekerad81ae412018-05-16 10:52:54 +02002628 self.assert_packet_checksums_valid(packet)
Matus Fabian328dbc82017-06-19 04:28:04 -07002629 except:
2630 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2631 raise
2632
Matus Fabian7968e6c2017-07-06 05:37:49 -07002633 def test_hairpinning_static_unknown_proto(self):
Matus Fabian1e8db5f2017-06-20 01:45:49 -07002634 """ 1:1 NAT translate packet with unknown protocol - hairpinning """
2635
2636 host = self.pg0.remote_hosts[0]
2637 server = self.pg0.remote_hosts[1]
2638
2639 host_nat_ip = "10.0.0.10"
2640 server_nat_ip = "10.0.0.11"
2641
Matus Fabian2ba92e32017-08-21 07:05:03 -07002642 self.nat44_add_static_mapping(host.ip4, host_nat_ip)
2643 self.nat44_add_static_mapping(server.ip4, server_nat_ip)
2644 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2645 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2646 is_inside=0)
Matus Fabian1e8db5f2017-06-20 01:45:49 -07002647
2648 # host to server
2649 p = (Ether(dst=self.pg0.local_mac, src=host.mac) /
2650 IP(src=host.ip4, dst=server_nat_ip) /
2651 GRE() /
2652 IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4) /
2653 TCP(sport=1234, dport=1234))
2654 self.pg0.add_stream(p)
2655 self.pg_enable_capture(self.pg_interfaces)
2656 self.pg_start()
2657 p = self.pg0.get_capture(1)
2658 packet = p[0]
2659 try:
2660 self.assertEqual(packet[IP].src, host_nat_ip)
2661 self.assertEqual(packet[IP].dst, server.ip4)
2662 self.assertTrue(packet.haslayer(GRE))
Klement Sekerad81ae412018-05-16 10:52:54 +02002663 self.assert_packet_checksums_valid(packet)
Matus Fabian1e8db5f2017-06-20 01:45:49 -07002664 except:
2665 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2666 raise
2667
2668 # server to host
2669 p = (Ether(dst=self.pg0.local_mac, src=server.mac) /
2670 IP(src=server.ip4, dst=host_nat_ip) /
2671 GRE() /
2672 IP(src=self.pg3.remote_ip4, dst=self.pg2.remote_ip4) /
2673 TCP(sport=1234, dport=1234))
2674 self.pg0.add_stream(p)
2675 self.pg_enable_capture(self.pg_interfaces)
2676 self.pg_start()
2677 p = self.pg0.get_capture(1)
2678 packet = p[0]
2679 try:
2680 self.assertEqual(packet[IP].src, server_nat_ip)
2681 self.assertEqual(packet[IP].dst, host.ip4)
2682 self.assertTrue(packet.haslayer(GRE))
Klement Sekerad81ae412018-05-16 10:52:54 +02002683 self.assert_packet_checksums_valid(packet)
Matus Fabian1e8db5f2017-06-20 01:45:49 -07002684 except:
2685 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2686 raise
2687
Matus Fabian93d84c92017-07-19 08:06:01 -07002688 def test_output_feature(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002689 """ NAT44 interface output feature (in2out postrouting) """
2690 self.nat44_add_address(self.nat_addr)
2691 self.vapi.nat44_interface_add_del_output_feature(self.pg0.sw_if_index)
Matus Fabianb2d2fc72017-09-10 22:17:47 -07002692 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index)
2693 self.vapi.nat44_interface_add_del_output_feature(self.pg3.sw_if_index,
Matus Fabian2ba92e32017-08-21 07:05:03 -07002694 is_inside=0)
Matus Fabian93d84c92017-07-19 08:06:01 -07002695
2696 # in2out
Matus Fabianb2d2fc72017-09-10 22:17:47 -07002697 pkts = self.create_stream_in(self.pg0, self.pg3)
Matus Fabian93d84c92017-07-19 08:06:01 -07002698 self.pg0.add_stream(pkts)
2699 self.pg_enable_capture(self.pg_interfaces)
2700 self.pg_start()
Matus Fabianb2d2fc72017-09-10 22:17:47 -07002701 capture = self.pg3.get_capture(len(pkts))
Matus Fabian93d84c92017-07-19 08:06:01 -07002702 self.verify_capture_out(capture)
2703
2704 # out2in
Matus Fabianb2d2fc72017-09-10 22:17:47 -07002705 pkts = self.create_stream_out(self.pg3)
2706 self.pg3.add_stream(pkts)
Matus Fabian93d84c92017-07-19 08:06:01 -07002707 self.pg_enable_capture(self.pg_interfaces)
2708 self.pg_start()
2709 capture = self.pg0.get_capture(len(pkts))
2710 self.verify_capture_in(capture, self.pg0)
2711
Matus Fabianb2d2fc72017-09-10 22:17:47 -07002712 # from non-NAT interface to NAT inside interface
2713 pkts = self.create_stream_in(self.pg2, self.pg0)
2714 self.pg2.add_stream(pkts)
2715 self.pg_enable_capture(self.pg_interfaces)
2716 self.pg_start()
2717 capture = self.pg0.get_capture(len(pkts))
2718 self.verify_capture_no_translation(capture, self.pg2, self.pg0)
2719
Matus Fabian93d84c92017-07-19 08:06:01 -07002720 def test_output_feature_vrf_aware(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002721 """ NAT44 interface output feature VRF aware (in2out postrouting) """
Matus Fabian93d84c92017-07-19 08:06:01 -07002722 nat_ip_vrf10 = "10.0.0.10"
2723 nat_ip_vrf20 = "10.0.0.20"
2724
2725 self.vapi.ip_add_del_route(dst_address=self.pg3.remote_ip4n,
2726 dst_address_length=32,
2727 next_hop_address=self.pg3.remote_ip4n,
2728 next_hop_sw_if_index=self.pg3.sw_if_index,
2729 table_id=10)
2730 self.vapi.ip_add_del_route(dst_address=self.pg3.remote_ip4n,
2731 dst_address_length=32,
2732 next_hop_address=self.pg3.remote_ip4n,
2733 next_hop_sw_if_index=self.pg3.sw_if_index,
2734 table_id=20)
2735
Matus Fabian2ba92e32017-08-21 07:05:03 -07002736 self.nat44_add_address(nat_ip_vrf10, vrf_id=10)
2737 self.nat44_add_address(nat_ip_vrf20, vrf_id=20)
2738 self.vapi.nat44_interface_add_del_output_feature(self.pg4.sw_if_index)
2739 self.vapi.nat44_interface_add_del_output_feature(self.pg6.sw_if_index)
2740 self.vapi.nat44_interface_add_del_output_feature(self.pg3.sw_if_index,
2741 is_inside=0)
Matus Fabian93d84c92017-07-19 08:06:01 -07002742
2743 # in2out VRF 10
2744 pkts = self.create_stream_in(self.pg4, self.pg3)
2745 self.pg4.add_stream(pkts)
2746 self.pg_enable_capture(self.pg_interfaces)
2747 self.pg_start()
2748 capture = self.pg3.get_capture(len(pkts))
2749 self.verify_capture_out(capture, nat_ip=nat_ip_vrf10)
2750
2751 # out2in VRF 10
2752 pkts = self.create_stream_out(self.pg3, dst_ip=nat_ip_vrf10)
2753 self.pg3.add_stream(pkts)
2754 self.pg_enable_capture(self.pg_interfaces)
2755 self.pg_start()
2756 capture = self.pg4.get_capture(len(pkts))
2757 self.verify_capture_in(capture, self.pg4)
2758
2759 # in2out VRF 20
2760 pkts = self.create_stream_in(self.pg6, self.pg3)
2761 self.pg6.add_stream(pkts)
2762 self.pg_enable_capture(self.pg_interfaces)
2763 self.pg_start()
2764 capture = self.pg3.get_capture(len(pkts))
2765 self.verify_capture_out(capture, nat_ip=nat_ip_vrf20)
2766
2767 # out2in VRF 20
2768 pkts = self.create_stream_out(self.pg3, dst_ip=nat_ip_vrf20)
2769 self.pg3.add_stream(pkts)
2770 self.pg_enable_capture(self.pg_interfaces)
2771 self.pg_start()
2772 capture = self.pg6.get_capture(len(pkts))
2773 self.verify_capture_in(capture, self.pg6)
2774
Matus Fabian161c59c2017-07-21 03:46:03 -07002775 def test_output_feature_hairpinning(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002776 """ NAT44 interface output feature hairpinning (in2out postrouting) """
Matus Fabian93d84c92017-07-19 08:06:01 -07002777 host = self.pg0.remote_hosts[0]
2778 server = self.pg0.remote_hosts[1]
2779 host_in_port = 1234
2780 host_out_port = 0
2781 server_in_port = 5678
2782 server_out_port = 8765
2783
Matus Fabian2ba92e32017-08-21 07:05:03 -07002784 self.nat44_add_address(self.nat_addr)
2785 self.vapi.nat44_interface_add_del_output_feature(self.pg0.sw_if_index)
2786 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
2787 is_inside=0)
Matus Fabian93d84c92017-07-19 08:06:01 -07002788
2789 # add static mapping for server
Matus Fabian2ba92e32017-08-21 07:05:03 -07002790 self.nat44_add_static_mapping(server.ip4, self.nat_addr,
2791 server_in_port, server_out_port,
2792 proto=IP_PROTOS.tcp)
Matus Fabian93d84c92017-07-19 08:06:01 -07002793
2794 # send packet from host to server
2795 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002796 IP(src=host.ip4, dst=self.nat_addr) /
Matus Fabian93d84c92017-07-19 08:06:01 -07002797 TCP(sport=host_in_port, dport=server_out_port))
2798 self.pg0.add_stream(p)
2799 self.pg_enable_capture(self.pg_interfaces)
2800 self.pg_start()
2801 capture = self.pg0.get_capture(1)
2802 p = capture[0]
2803 try:
2804 ip = p[IP]
2805 tcp = p[TCP]
Matus Fabian2ba92e32017-08-21 07:05:03 -07002806 self.assertEqual(ip.src, self.nat_addr)
Matus Fabian93d84c92017-07-19 08:06:01 -07002807 self.assertEqual(ip.dst, server.ip4)
2808 self.assertNotEqual(tcp.sport, host_in_port)
2809 self.assertEqual(tcp.dport, server_in_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02002810 self.assert_packet_checksums_valid(p)
Matus Fabian93d84c92017-07-19 08:06:01 -07002811 host_out_port = tcp.sport
2812 except:
2813 self.logger.error(ppp("Unexpected or invalid packet:", p))
2814 raise
2815
2816 # send reply from server to host
2817 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002818 IP(src=server.ip4, dst=self.nat_addr) /
Matus Fabian93d84c92017-07-19 08:06:01 -07002819 TCP(sport=server_in_port, dport=host_out_port))
2820 self.pg0.add_stream(p)
2821 self.pg_enable_capture(self.pg_interfaces)
2822 self.pg_start()
2823 capture = self.pg0.get_capture(1)
2824 p = capture[0]
2825 try:
2826 ip = p[IP]
2827 tcp = p[TCP]
Matus Fabian2ba92e32017-08-21 07:05:03 -07002828 self.assertEqual(ip.src, self.nat_addr)
Matus Fabian93d84c92017-07-19 08:06:01 -07002829 self.assertEqual(ip.dst, host.ip4)
2830 self.assertEqual(tcp.sport, server_out_port)
2831 self.assertEqual(tcp.dport, host_in_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02002832 self.assert_packet_checksums_valid(p)
Matus Fabian93d84c92017-07-19 08:06:01 -07002833 except:
Matus Fabiane82488f2018-01-18 03:38:45 -08002834 self.logger.error(ppp("Unexpected or invalid packet:", p))
Matus Fabian93d84c92017-07-19 08:06:01 -07002835 raise
2836
Matus Fabian36ea2d62017-10-24 04:13:49 -07002837 def test_one_armed_nat44(self):
2838 """ One armed NAT44 """
2839 remote_host = self.pg9.remote_hosts[0]
2840 local_host = self.pg9.remote_hosts[1]
2841 external_port = 0
2842
2843 self.nat44_add_address(self.nat_addr)
2844 self.vapi.nat44_interface_add_del_feature(self.pg9.sw_if_index)
2845 self.vapi.nat44_interface_add_del_feature(self.pg9.sw_if_index,
2846 is_inside=0)
2847
2848 # in2out
2849 p = (Ether(src=self.pg9.remote_mac, dst=self.pg9.local_mac) /
2850 IP(src=local_host.ip4, dst=remote_host.ip4) /
2851 TCP(sport=12345, dport=80))
2852 self.pg9.add_stream(p)
2853 self.pg_enable_capture(self.pg_interfaces)
2854 self.pg_start()
2855 capture = self.pg9.get_capture(1)
2856 p = capture[0]
2857 try:
2858 ip = p[IP]
2859 tcp = p[TCP]
2860 self.assertEqual(ip.src, self.nat_addr)
2861 self.assertEqual(ip.dst, remote_host.ip4)
2862 self.assertNotEqual(tcp.sport, 12345)
2863 external_port = tcp.sport
2864 self.assertEqual(tcp.dport, 80)
Klement Sekerad81ae412018-05-16 10:52:54 +02002865 self.assert_packet_checksums_valid(p)
Matus Fabian36ea2d62017-10-24 04:13:49 -07002866 except:
2867 self.logger.error(ppp("Unexpected or invalid packet:", p))
2868 raise
2869
2870 # out2in
2871 p = (Ether(src=self.pg9.remote_mac, dst=self.pg9.local_mac) /
2872 IP(src=remote_host.ip4, dst=self.nat_addr) /
2873 TCP(sport=80, dport=external_port))
2874 self.pg9.add_stream(p)
2875 self.pg_enable_capture(self.pg_interfaces)
2876 self.pg_start()
2877 capture = self.pg9.get_capture(1)
2878 p = capture[0]
2879 try:
2880 ip = p[IP]
2881 tcp = p[TCP]
2882 self.assertEqual(ip.src, remote_host.ip4)
2883 self.assertEqual(ip.dst, local_host.ip4)
2884 self.assertEqual(tcp.sport, 80)
2885 self.assertEqual(tcp.dport, 12345)
Klement Sekerad81ae412018-05-16 10:52:54 +02002886 self.assert_packet_checksums_valid(p)
Matus Fabian36ea2d62017-10-24 04:13:49 -07002887 except:
2888 self.logger.error(ppp("Unexpected or invalid packet:", p))
2889 raise
2890
Matus Fabian5ba86f72017-10-26 03:37:38 -07002891 def test_del_session(self):
2892 """ Delete NAT44 session """
2893 self.nat44_add_address(self.nat_addr)
2894 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2895 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2896 is_inside=0)
2897
2898 pkts = self.create_stream_in(self.pg0, self.pg1)
2899 self.pg0.add_stream(pkts)
2900 self.pg_enable_capture(self.pg_interfaces)
2901 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07002902 self.pg1.get_capture(len(pkts))
Matus Fabian5ba86f72017-10-26 03:37:38 -07002903
2904 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
2905 nsessions = len(sessions)
2906
2907 self.vapi.nat44_del_session(sessions[0].inside_ip_address,
2908 sessions[0].inside_port,
2909 sessions[0].protocol)
2910 self.vapi.nat44_del_session(sessions[1].outside_ip_address,
2911 sessions[1].outside_port,
2912 sessions[1].protocol,
2913 is_in=0)
2914
2915 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
2916 self.assertEqual(nsessions - len(sessions), 2)
2917
Matus Fabian68ba8802018-08-08 05:52:47 -07002918 self.vapi.nat44_del_session(sessions[0].inside_ip_address,
2919 sessions[0].inside_port,
2920 sessions[0].protocol)
2921
2922 self.verify_no_nat44_user()
2923
Matus Fabianefcd1e92017-08-15 06:59:19 -07002924 def test_set_get_reass(self):
2925 """ NAT44 set/get virtual fragmentation reassembly """
2926 reas_cfg1 = self.vapi.nat_get_reass()
2927
2928 self.vapi.nat_set_reass(timeout=reas_cfg1.ip4_timeout + 5,
2929 max_reass=reas_cfg1.ip4_max_reass * 2,
2930 max_frag=reas_cfg1.ip4_max_frag * 2)
2931
2932 reas_cfg2 = self.vapi.nat_get_reass()
2933
2934 self.assertEqual(reas_cfg1.ip4_timeout + 5, reas_cfg2.ip4_timeout)
2935 self.assertEqual(reas_cfg1.ip4_max_reass * 2, reas_cfg2.ip4_max_reass)
2936 self.assertEqual(reas_cfg1.ip4_max_frag * 2, reas_cfg2.ip4_max_frag)
2937
2938 self.vapi.nat_set_reass(drop_frag=1)
2939 self.assertTrue(self.vapi.nat_get_reass().ip4_drop_frag)
2940
2941 def test_frag_in_order(self):
2942 """ NAT44 translate fragments arriving in order """
2943 self.nat44_add_address(self.nat_addr)
2944 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2945 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2946 is_inside=0)
2947
2948 data = "A" * 4 + "B" * 16 + "C" * 3
2949 self.tcp_port_in = random.randint(1025, 65535)
2950
2951 reass = self.vapi.nat_reass_dump()
2952 reass_n_start = len(reass)
2953
2954 # in2out
2955 pkts = self.create_stream_frag(self.pg0,
2956 self.pg1.remote_ip4,
2957 self.tcp_port_in,
2958 20,
2959 data)
2960 self.pg0.add_stream(pkts)
2961 self.pg_enable_capture(self.pg_interfaces)
2962 self.pg_start()
2963 frags = self.pg1.get_capture(len(pkts))
2964 p = self.reass_frags_and_verify(frags,
2965 self.nat_addr,
2966 self.pg1.remote_ip4)
2967 self.assertEqual(p[TCP].dport, 20)
2968 self.assertNotEqual(p[TCP].sport, self.tcp_port_in)
2969 self.tcp_port_out = p[TCP].sport
2970 self.assertEqual(data, p[Raw].load)
2971
2972 # out2in
2973 pkts = self.create_stream_frag(self.pg1,
2974 self.nat_addr,
2975 20,
2976 self.tcp_port_out,
2977 data)
2978 self.pg1.add_stream(pkts)
2979 self.pg_enable_capture(self.pg_interfaces)
2980 self.pg_start()
2981 frags = self.pg0.get_capture(len(pkts))
2982 p = self.reass_frags_and_verify(frags,
2983 self.pg1.remote_ip4,
2984 self.pg0.remote_ip4)
2985 self.assertEqual(p[TCP].sport, 20)
2986 self.assertEqual(p[TCP].dport, self.tcp_port_in)
2987 self.assertEqual(data, p[Raw].load)
2988
2989 reass = self.vapi.nat_reass_dump()
2990 reass_n_end = len(reass)
2991
2992 self.assertEqual(reass_n_end - reass_n_start, 2)
2993
2994 def test_reass_hairpinning(self):
2995 """ NAT44 fragments hairpinning """
Matus Fabianefcd1e92017-08-15 06:59:19 -07002996 server = self.pg0.remote_hosts[1]
2997 host_in_port = random.randint(1025, 65535)
Matus Fabianefcd1e92017-08-15 06:59:19 -07002998 server_in_port = random.randint(1025, 65535)
2999 server_out_port = random.randint(1025, 65535)
3000 data = "A" * 4 + "B" * 16 + "C" * 3
3001
3002 self.nat44_add_address(self.nat_addr)
3003 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3004 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3005 is_inside=0)
3006 # add static mapping for server
3007 self.nat44_add_static_mapping(server.ip4, self.nat_addr,
3008 server_in_port, server_out_port,
3009 proto=IP_PROTOS.tcp)
3010
3011 # send packet from host to server
3012 pkts = self.create_stream_frag(self.pg0,
3013 self.nat_addr,
3014 host_in_port,
3015 server_out_port,
3016 data)
3017 self.pg0.add_stream(pkts)
3018 self.pg_enable_capture(self.pg_interfaces)
3019 self.pg_start()
3020 frags = self.pg0.get_capture(len(pkts))
3021 p = self.reass_frags_and_verify(frags,
3022 self.nat_addr,
3023 server.ip4)
3024 self.assertNotEqual(p[TCP].sport, host_in_port)
3025 self.assertEqual(p[TCP].dport, server_in_port)
3026 self.assertEqual(data, p[Raw].load)
3027
3028 def test_frag_out_of_order(self):
3029 """ NAT44 translate fragments arriving out of order """
3030 self.nat44_add_address(self.nat_addr)
3031 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3032 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3033 is_inside=0)
3034
3035 data = "A" * 4 + "B" * 16 + "C" * 3
3036 random.randint(1025, 65535)
3037
3038 # in2out
3039 pkts = self.create_stream_frag(self.pg0,
3040 self.pg1.remote_ip4,
3041 self.tcp_port_in,
3042 20,
3043 data)
3044 pkts.reverse()
3045 self.pg0.add_stream(pkts)
3046 self.pg_enable_capture(self.pg_interfaces)
3047 self.pg_start()
3048 frags = self.pg1.get_capture(len(pkts))
3049 p = self.reass_frags_and_verify(frags,
3050 self.nat_addr,
3051 self.pg1.remote_ip4)
3052 self.assertEqual(p[TCP].dport, 20)
3053 self.assertNotEqual(p[TCP].sport, self.tcp_port_in)
3054 self.tcp_port_out = p[TCP].sport
3055 self.assertEqual(data, p[Raw].load)
3056
3057 # out2in
3058 pkts = self.create_stream_frag(self.pg1,
3059 self.nat_addr,
3060 20,
3061 self.tcp_port_out,
3062 data)
3063 pkts.reverse()
3064 self.pg1.add_stream(pkts)
3065 self.pg_enable_capture(self.pg_interfaces)
3066 self.pg_start()
3067 frags = self.pg0.get_capture(len(pkts))
3068 p = self.reass_frags_and_verify(frags,
3069 self.pg1.remote_ip4,
3070 self.pg0.remote_ip4)
3071 self.assertEqual(p[TCP].sport, 20)
3072 self.assertEqual(p[TCP].dport, self.tcp_port_in)
3073 self.assertEqual(data, p[Raw].load)
3074
Matus Fabian27697102017-11-09 01:43:47 -08003075 def test_port_restricted(self):
3076 """ Port restricted NAT44 (MAP-E CE) """
3077 self.nat44_add_address(self.nat_addr)
3078 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3079 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3080 is_inside=0)
Matus Fabian51e759f2017-12-07 23:22:51 -08003081 self.vapi.cli("nat addr-port-assignment-alg map-e psid 10 "
Matus Fabian27697102017-11-09 01:43:47 -08003082 "psid-offset 6 psid-len 6")
3083
3084 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3085 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3086 TCP(sport=4567, dport=22))
3087 self.pg0.add_stream(p)
3088 self.pg_enable_capture(self.pg_interfaces)
3089 self.pg_start()
3090 capture = self.pg1.get_capture(1)
3091 p = capture[0]
3092 try:
3093 ip = p[IP]
3094 tcp = p[TCP]
3095 self.assertEqual(ip.dst, self.pg1.remote_ip4)
3096 self.assertEqual(ip.src, self.nat_addr)
3097 self.assertEqual(tcp.dport, 22)
3098 self.assertNotEqual(tcp.sport, 4567)
3099 self.assertEqual((tcp.sport >> 6) & 63, 10)
Klement Sekerad81ae412018-05-16 10:52:54 +02003100 self.assert_packet_checksums_valid(p)
Matus Fabian27697102017-11-09 01:43:47 -08003101 except:
3102 self.logger.error(ppp("Unexpected or invalid packet:", p))
3103 raise
3104
Matus Fabiana6110b62018-06-13 05:39:07 -07003105 def test_ipfix_max_frags(self):
3106 """ IPFIX logging maximum fragments pending reassembly exceeded """
3107 self.nat44_add_address(self.nat_addr)
3108 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3109 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3110 is_inside=0)
3111 self.vapi.nat_set_reass(max_frag=0)
3112 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
3113 src_address=self.pg3.local_ip4n,
3114 path_mtu=512,
3115 template_interval=10)
3116 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
3117 src_port=self.ipfix_src_port)
3118
3119 data = "A" * 4 + "B" * 16 + "C" * 3
3120 self.tcp_port_in = random.randint(1025, 65535)
3121 pkts = self.create_stream_frag(self.pg0,
3122 self.pg1.remote_ip4,
3123 self.tcp_port_in,
3124 20,
3125 data)
3126 self.pg0.add_stream(pkts[-1])
3127 self.pg_enable_capture(self.pg_interfaces)
3128 self.pg_start()
3129 self.pg1.assert_nothing_captured()
3130 sleep(1)
3131 self.vapi.cli("ipfix flush") # FIXME this should be an API call
3132 capture = self.pg3.get_capture(9)
3133 ipfix = IPFIXDecoder()
3134 # first load template
3135 for p in capture:
3136 self.assertTrue(p.haslayer(IPFIX))
3137 self.assertEqual(p[IP].src, self.pg3.local_ip4)
3138 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
3139 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
3140 self.assertEqual(p[UDP].dport, 4739)
3141 self.assertEqual(p[IPFIX].observationDomainID,
3142 self.ipfix_domain_id)
3143 if p.haslayer(Template):
3144 ipfix.add_template(p.getlayer(Template))
3145 # verify events in data set
3146 for p in capture:
3147 if p.haslayer(Data):
3148 data = ipfix.decode_data_set(p.getlayer(Set))
3149 self.verify_ipfix_max_fragments_ip4(data, 0,
3150 self.pg0.remote_ip4n)
3151
Matus Fabian8008d7c2018-07-09 01:34:20 -07003152 def test_multiple_outside_vrf(self):
3153 """ Multiple outside VRF """
3154 vrf_id1 = 1
3155 vrf_id2 = 2
3156
3157 self.pg1.unconfig_ip4()
3158 self.pg2.unconfig_ip4()
3159 self.vapi.ip_table_add_del(vrf_id1, is_add=1)
3160 self.vapi.ip_table_add_del(vrf_id2, is_add=1)
3161 self.pg1.set_table_ip4(vrf_id1)
3162 self.pg2.set_table_ip4(vrf_id2)
3163 self.pg1.config_ip4()
3164 self.pg2.config_ip4()
3165 self.pg1.resolve_arp()
3166 self.pg2.resolve_arp()
3167
3168 self.nat44_add_address(self.nat_addr)
3169 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3170 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3171 is_inside=0)
3172 self.vapi.nat44_interface_add_del_feature(self.pg2.sw_if_index,
3173 is_inside=0)
3174
3175 try:
3176 # first VRF
3177 pkts = self.create_stream_in(self.pg0, self.pg1)
3178 self.pg0.add_stream(pkts)
3179 self.pg_enable_capture(self.pg_interfaces)
3180 self.pg_start()
3181 capture = self.pg1.get_capture(len(pkts))
3182 self.verify_capture_out(capture, self.nat_addr)
3183
3184 pkts = self.create_stream_out(self.pg1, self.nat_addr)
3185 self.pg1.add_stream(pkts)
3186 self.pg_enable_capture(self.pg_interfaces)
3187 self.pg_start()
3188 capture = self.pg0.get_capture(len(pkts))
3189 self.verify_capture_in(capture, self.pg0)
3190
3191 self.tcp_port_in = 60303
3192 self.udp_port_in = 60304
3193 self.icmp_id_in = 60305
3194
3195 # second VRF
3196 pkts = self.create_stream_in(self.pg0, self.pg2)
3197 self.pg0.add_stream(pkts)
3198 self.pg_enable_capture(self.pg_interfaces)
3199 self.pg_start()
3200 capture = self.pg2.get_capture(len(pkts))
3201 self.verify_capture_out(capture, self.nat_addr)
3202
3203 pkts = self.create_stream_out(self.pg2, self.nat_addr)
3204 self.pg2.add_stream(pkts)
3205 self.pg_enable_capture(self.pg_interfaces)
3206 self.pg_start()
3207 capture = self.pg0.get_capture(len(pkts))
3208 self.verify_capture_in(capture, self.pg0)
3209
3210 finally:
3211 self.pg1.unconfig_ip4()
3212 self.pg2.unconfig_ip4()
3213 self.pg1.set_table_ip4(0)
3214 self.pg2.set_table_ip4(0)
3215 self.pg1.config_ip4()
3216 self.pg2.config_ip4()
3217 self.pg1.resolve_arp()
3218 self.pg2.resolve_arp()
3219
Matus Fabiana6110b62018-06-13 05:39:07 -07003220 def tearDown(self):
3221 super(TestNAT44, self).tearDown()
3222 if not self.vpp_dead:
3223 self.logger.info(self.vapi.cli("show nat44 addresses"))
3224 self.logger.info(self.vapi.cli("show nat44 interfaces"))
3225 self.logger.info(self.vapi.cli("show nat44 static mappings"))
3226 self.logger.info(self.vapi.cli("show nat44 interface address"))
3227 self.logger.info(self.vapi.cli("show nat44 sessions detail"))
3228 self.logger.info(self.vapi.cli("show nat virtual-reassembly"))
3229 self.logger.info(self.vapi.cli("show nat44 hash tables detail"))
3230 self.vapi.cli("nat addr-port-assignment-alg default")
3231 self.clear_nat44()
3232 self.vapi.cli("clear logging")
3233
3234
3235class TestNAT44EndpointDependent(MethodHolder):
3236 """ Endpoint-Dependent mapping and filtering test cases """
3237
3238 @classmethod
3239 def setUpConstants(cls):
3240 super(TestNAT44EndpointDependent, cls).setUpConstants()
3241 cls.vpp_cmdline.extend(["nat", "{", "endpoint-dependent", "}"])
3242
3243 @classmethod
3244 def setUpClass(cls):
3245 super(TestNAT44EndpointDependent, cls).setUpClass()
3246 cls.vapi.cli("set log class nat level debug")
3247 try:
3248 cls.tcp_port_in = 6303
3249 cls.tcp_port_out = 6303
3250 cls.udp_port_in = 6304
3251 cls.udp_port_out = 6304
3252 cls.icmp_id_in = 6305
3253 cls.icmp_id_out = 6305
3254 cls.nat_addr = '10.0.0.3'
3255 cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
3256 cls.ipfix_src_port = 4739
3257 cls.ipfix_domain_id = 1
3258 cls.tcp_external_port = 80
3259
Matus Fabian8008d7c2018-07-09 01:34:20 -07003260 cls.create_pg_interfaces(range(7))
Matus Fabiana6110b62018-06-13 05:39:07 -07003261 cls.interfaces = list(cls.pg_interfaces[0:3])
3262
3263 for i in cls.interfaces:
3264 i.admin_up()
3265 i.config_ip4()
3266 i.resolve_arp()
3267
3268 cls.pg0.generate_remote_hosts(3)
3269 cls.pg0.configure_ipv4_neighbors()
3270
3271 cls.pg3.admin_up()
3272
3273 cls.pg4.generate_remote_hosts(2)
3274 cls.pg4.config_ip4()
3275 ip_addr_n = socket.inet_pton(socket.AF_INET, "10.0.0.1")
3276 cls.vapi.sw_interface_add_del_address(cls.pg4.sw_if_index,
3277 ip_addr_n,
3278 24)
3279 cls.pg4.admin_up()
3280 cls.pg4.resolve_arp()
3281 cls.pg4._remote_hosts[1]._ip4 = cls.pg4._remote_hosts[0]._ip4
3282 cls.pg4.resolve_arp()
3283
Matus Fabian8008d7c2018-07-09 01:34:20 -07003284 zero_ip4n = socket.inet_pton(socket.AF_INET, "0.0.0.0")
3285 cls.vapi.ip_table_add_del(1, is_add=1)
3286
3287 cls.pg5._local_ip4 = "10.1.1.1"
3288 cls.pg5._local_ip4n = socket.inet_pton(socket.AF_INET,
3289 cls.pg5.local_ip4)
3290 cls.pg5._remote_hosts[0]._ip4 = "10.1.1.2"
3291 cls.pg5._remote_hosts[0]._ip4n = socket.inet_pton(
3292 socket.AF_INET, cls.pg5.remote_ip4)
3293 cls.pg5.set_table_ip4(1)
3294 cls.pg5.config_ip4()
3295 cls.pg5.admin_up()
3296 cls.vapi.ip_add_del_route(dst_address=cls.pg5.remote_ip4n,
3297 dst_address_length=32,
3298 table_id=1,
3299 next_hop_sw_if_index=cls.pg5.sw_if_index,
3300 next_hop_address=zero_ip4n)
3301
3302 cls.pg6._local_ip4 = "10.1.2.1"
3303 cls.pg6._local_ip4n = socket.inet_pton(socket.AF_INET,
3304 cls.pg6.local_ip4)
3305 cls.pg6._remote_hosts[0]._ip4 = "10.1.2.2"
3306 cls.pg6._remote_hosts[0]._ip4n = socket.inet_pton(
3307 socket.AF_INET, cls.pg6.remote_ip4)
3308 cls.pg6.set_table_ip4(1)
3309 cls.pg6.config_ip4()
3310 cls.pg6.admin_up()
3311 cls.vapi.ip_add_del_route(dst_address=cls.pg6.remote_ip4n,
3312 dst_address_length=32,
3313 table_id=1,
3314 next_hop_sw_if_index=cls.pg6.sw_if_index,
3315 next_hop_address=zero_ip4n)
3316
3317 cls.vapi.ip_add_del_route(dst_address=cls.pg6.remote_ip4n,
3318 dst_address_length=16,
3319 next_hop_address=zero_ip4n,
3320 table_id=0,
3321 next_hop_table_id=1)
3322 cls.vapi.ip_add_del_route(dst_address=zero_ip4n,
3323 dst_address_length=0,
3324 next_hop_address=zero_ip4n,
3325 table_id=1,
3326 next_hop_table_id=0)
3327 cls.vapi.ip_add_del_route(dst_address=zero_ip4n,
3328 dst_address_length=0,
3329 table_id=0,
3330 next_hop_sw_if_index=cls.pg1.sw_if_index,
3331 next_hop_address=cls.pg1.local_ip4n)
3332
3333 cls.pg5.resolve_arp()
3334 cls.pg6.resolve_arp()
3335
Matus Fabiana6110b62018-06-13 05:39:07 -07003336 except Exception:
3337 super(TestNAT44EndpointDependent, cls).tearDownClass()
3338 raise
3339
3340 def test_dynamic(self):
3341 """ NAT44 dynamic translation test """
3342
3343 self.nat44_add_address(self.nat_addr)
3344 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3345 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3346 is_inside=0)
3347
Matus Fabian69ce30d2018-08-22 01:27:10 -07003348 nat_config = self.vapi.nat_show_config()
3349 self.assertEqual(1, nat_config.endpoint_dependent)
3350
Matus Fabiana6110b62018-06-13 05:39:07 -07003351 # in2out
3352 pkts = self.create_stream_in(self.pg0, self.pg1)
3353 self.pg0.add_stream(pkts)
3354 self.pg_enable_capture(self.pg_interfaces)
3355 self.pg_start()
3356 capture = self.pg1.get_capture(len(pkts))
3357 self.verify_capture_out(capture)
3358
3359 # out2in
3360 pkts = self.create_stream_out(self.pg1)
3361 self.pg1.add_stream(pkts)
3362 self.pg_enable_capture(self.pg_interfaces)
3363 self.pg_start()
3364 capture = self.pg0.get_capture(len(pkts))
3365 self.verify_capture_in(capture, self.pg0)
3366
3367 def test_forwarding(self):
3368 """ NAT44 forwarding test """
3369
3370 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3371 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3372 is_inside=0)
3373 self.vapi.nat44_forwarding_enable_disable(1)
3374
3375 real_ip = self.pg0.remote_ip4n
3376 alias_ip = self.nat_addr_n
3377 self.vapi.nat44_add_del_static_mapping(local_ip=real_ip,
3378 external_ip=alias_ip)
3379
3380 try:
3381 # in2out - static mapping match
3382
3383 pkts = self.create_stream_out(self.pg1)
3384 self.pg1.add_stream(pkts)
3385 self.pg_enable_capture(self.pg_interfaces)
3386 self.pg_start()
3387 capture = self.pg0.get_capture(len(pkts))
3388 self.verify_capture_in(capture, self.pg0)
3389
3390 pkts = self.create_stream_in(self.pg0, self.pg1)
3391 self.pg0.add_stream(pkts)
3392 self.pg_enable_capture(self.pg_interfaces)
3393 self.pg_start()
3394 capture = self.pg1.get_capture(len(pkts))
3395 self.verify_capture_out(capture, same_port=True)
3396
3397 # in2out - no static mapping match
3398
3399 host0 = self.pg0.remote_hosts[0]
3400 self.pg0.remote_hosts[0] = self.pg0.remote_hosts[1]
3401 try:
3402 pkts = self.create_stream_out(self.pg1,
3403 dst_ip=self.pg0.remote_ip4,
3404 use_inside_ports=True)
3405 self.pg1.add_stream(pkts)
3406 self.pg_enable_capture(self.pg_interfaces)
3407 self.pg_start()
3408 capture = self.pg0.get_capture(len(pkts))
3409 self.verify_capture_in(capture, self.pg0)
3410
3411 pkts = self.create_stream_in(self.pg0, self.pg1)
3412 self.pg0.add_stream(pkts)
3413 self.pg_enable_capture(self.pg_interfaces)
3414 self.pg_start()
3415 capture = self.pg1.get_capture(len(pkts))
3416 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
3417 same_port=True)
3418 finally:
3419 self.pg0.remote_hosts[0] = host0
3420
3421 user = self.pg0.remote_hosts[1]
3422 sessions = self.vapi.nat44_user_session_dump(user.ip4n, 0)
3423 self.assertEqual(len(sessions), 3)
3424 self.assertTrue(sessions[0].ext_host_valid)
3425 self.vapi.nat44_del_session(
3426 sessions[0].inside_ip_address,
3427 sessions[0].inside_port,
3428 sessions[0].protocol,
3429 ext_host_address=sessions[0].ext_host_address,
3430 ext_host_port=sessions[0].ext_host_port)
3431 sessions = self.vapi.nat44_user_session_dump(user.ip4n, 0)
3432 self.assertEqual(len(sessions), 2)
3433
3434 finally:
3435 self.vapi.nat44_forwarding_enable_disable(0)
3436 self.vapi.nat44_add_del_static_mapping(local_ip=real_ip,
3437 external_ip=alias_ip,
3438 is_add=0)
3439
3440 def test_static_lb(self):
3441 """ NAT44 local service load balancing """
3442 external_addr_n = socket.inet_pton(socket.AF_INET, self.nat_addr)
3443 external_port = 80
3444 local_port = 8080
3445 server1 = self.pg0.remote_hosts[0]
3446 server2 = self.pg0.remote_hosts[1]
3447
3448 locals = [{'addr': server1.ip4n,
3449 'port': local_port,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07003450 'probability': 70,
3451 'vrf_id': 0},
Matus Fabiana6110b62018-06-13 05:39:07 -07003452 {'addr': server2.ip4n,
3453 'port': local_port,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07003454 'probability': 30,
3455 'vrf_id': 0}]
Matus Fabiana6110b62018-06-13 05:39:07 -07003456
3457 self.nat44_add_address(self.nat_addr)
3458 self.vapi.nat44_add_del_lb_static_mapping(external_addr_n,
3459 external_port,
3460 IP_PROTOS.tcp,
3461 local_num=len(locals),
3462 locals=locals)
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)
3466
3467 # from client to service
3468 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3469 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3470 TCP(sport=12345, dport=external_port))
3471 self.pg1.add_stream(p)
3472 self.pg_enable_capture(self.pg_interfaces)
3473 self.pg_start()
3474 capture = self.pg0.get_capture(1)
3475 p = capture[0]
3476 server = None
3477 try:
3478 ip = p[IP]
3479 tcp = p[TCP]
3480 self.assertIn(ip.dst, [server1.ip4, server2.ip4])
3481 if ip.dst == server1.ip4:
3482 server = server1
3483 else:
3484 server = server2
3485 self.assertEqual(tcp.dport, local_port)
3486 self.assert_packet_checksums_valid(p)
3487 except:
3488 self.logger.error(ppp("Unexpected or invalid packet:", p))
3489 raise
3490
3491 # from service back to client
3492 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
3493 IP(src=server.ip4, dst=self.pg1.remote_ip4) /
3494 TCP(sport=local_port, dport=12345))
3495 self.pg0.add_stream(p)
3496 self.pg_enable_capture(self.pg_interfaces)
3497 self.pg_start()
3498 capture = self.pg1.get_capture(1)
3499 p = capture[0]
3500 try:
3501 ip = p[IP]
3502 tcp = p[TCP]
3503 self.assertEqual(ip.src, self.nat_addr)
3504 self.assertEqual(tcp.sport, external_port)
3505 self.assert_packet_checksums_valid(p)
3506 except:
3507 self.logger.error(ppp("Unexpected or invalid packet:", p))
3508 raise
3509
3510 sessions = self.vapi.nat44_user_session_dump(server.ip4n, 0)
3511 self.assertEqual(len(sessions), 1)
3512 self.assertTrue(sessions[0].ext_host_valid)
3513 self.vapi.nat44_del_session(
3514 sessions[0].inside_ip_address,
3515 sessions[0].inside_port,
3516 sessions[0].protocol,
3517 ext_host_address=sessions[0].ext_host_address,
3518 ext_host_port=sessions[0].ext_host_port)
3519 sessions = self.vapi.nat44_user_session_dump(server.ip4n, 0)
3520 self.assertEqual(len(sessions), 0)
3521
3522 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
3523 def test_static_lb_multi_clients(self):
3524 """ NAT44 local service load balancing - multiple clients"""
3525
3526 external_addr_n = socket.inet_pton(socket.AF_INET, self.nat_addr)
3527 external_port = 80
3528 local_port = 8080
3529 server1 = self.pg0.remote_hosts[0]
3530 server2 = self.pg0.remote_hosts[1]
3531
3532 locals = [{'addr': server1.ip4n,
3533 'port': local_port,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07003534 'probability': 90,
3535 'vrf_id': 0},
Matus Fabiana6110b62018-06-13 05:39:07 -07003536 {'addr': server2.ip4n,
3537 'port': local_port,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07003538 'probability': 10,
3539 'vrf_id': 0}]
Matus Fabiana6110b62018-06-13 05:39:07 -07003540
3541 self.nat44_add_address(self.nat_addr)
3542 self.vapi.nat44_add_del_lb_static_mapping(external_addr_n,
3543 external_port,
3544 IP_PROTOS.tcp,
3545 local_num=len(locals),
3546 locals=locals)
3547 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3548 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3549 is_inside=0)
3550
3551 server1_n = 0
3552 server2_n = 0
3553 clients = ip4_range(self.pg1.remote_ip4, 10, 50)
3554 pkts = []
3555 for client in clients:
3556 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3557 IP(src=client, dst=self.nat_addr) /
3558 TCP(sport=12345, dport=external_port))
3559 pkts.append(p)
3560 self.pg1.add_stream(pkts)
3561 self.pg_enable_capture(self.pg_interfaces)
3562 self.pg_start()
3563 capture = self.pg0.get_capture(len(pkts))
3564 for p in capture:
3565 if p[IP].dst == server1.ip4:
3566 server1_n += 1
3567 else:
3568 server2_n += 1
3569 self.assertTrue(server1_n > server2_n)
3570
3571 def test_static_lb_2(self):
3572 """ NAT44 local service load balancing (asymmetrical rule) """
3573 external_addr_n = socket.inet_pton(socket.AF_INET, self.nat_addr)
3574 external_port = 80
3575 local_port = 8080
3576 server1 = self.pg0.remote_hosts[0]
3577 server2 = self.pg0.remote_hosts[1]
3578
3579 locals = [{'addr': server1.ip4n,
3580 'port': local_port,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07003581 'probability': 70,
3582 'vrf_id': 0},
Matus Fabiana6110b62018-06-13 05:39:07 -07003583 {'addr': server2.ip4n,
3584 'port': local_port,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07003585 'probability': 30,
3586 'vrf_id': 0}]
Matus Fabiana6110b62018-06-13 05:39:07 -07003587
3588 self.vapi.nat44_forwarding_enable_disable(1)
3589 self.vapi.nat44_add_del_lb_static_mapping(external_addr_n,
3590 external_port,
3591 IP_PROTOS.tcp,
3592 out2in_only=1,
3593 local_num=len(locals),
3594 locals=locals)
3595 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3596 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3597 is_inside=0)
3598
3599 # from client to service
3600 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3601 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3602 TCP(sport=12345, dport=external_port))
3603 self.pg1.add_stream(p)
3604 self.pg_enable_capture(self.pg_interfaces)
3605 self.pg_start()
3606 capture = self.pg0.get_capture(1)
3607 p = capture[0]
3608 server = None
3609 try:
3610 ip = p[IP]
3611 tcp = p[TCP]
3612 self.assertIn(ip.dst, [server1.ip4, server2.ip4])
3613 if ip.dst == server1.ip4:
3614 server = server1
3615 else:
3616 server = server2
3617 self.assertEqual(tcp.dport, local_port)
3618 self.assert_packet_checksums_valid(p)
3619 except:
3620 self.logger.error(ppp("Unexpected or invalid packet:", p))
3621 raise
3622
3623 # from service back to client
3624 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
3625 IP(src=server.ip4, dst=self.pg1.remote_ip4) /
3626 TCP(sport=local_port, dport=12345))
3627 self.pg0.add_stream(p)
3628 self.pg_enable_capture(self.pg_interfaces)
3629 self.pg_start()
3630 capture = self.pg1.get_capture(1)
3631 p = capture[0]
3632 try:
3633 ip = p[IP]
3634 tcp = p[TCP]
3635 self.assertEqual(ip.src, self.nat_addr)
3636 self.assertEqual(tcp.sport, external_port)
3637 self.assert_packet_checksums_valid(p)
3638 except:
3639 self.logger.error(ppp("Unexpected or invalid packet:", p))
3640 raise
3641
3642 # from client to server (no translation)
3643 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3644 IP(src=self.pg1.remote_ip4, dst=server1.ip4) /
3645 TCP(sport=12346, dport=local_port))
3646 self.pg1.add_stream(p)
3647 self.pg_enable_capture(self.pg_interfaces)
3648 self.pg_start()
3649 capture = self.pg0.get_capture(1)
3650 p = capture[0]
3651 server = None
3652 try:
3653 ip = p[IP]
3654 tcp = p[TCP]
3655 self.assertEqual(ip.dst, server1.ip4)
3656 self.assertEqual(tcp.dport, local_port)
3657 self.assert_packet_checksums_valid(p)
3658 except:
3659 self.logger.error(ppp("Unexpected or invalid packet:", p))
3660 raise
3661
3662 # from service back to client (no translation)
3663 p = (Ether(src=server1.mac, dst=self.pg0.local_mac) /
3664 IP(src=server1.ip4, dst=self.pg1.remote_ip4) /
3665 TCP(sport=local_port, dport=12346))
3666 self.pg0.add_stream(p)
3667 self.pg_enable_capture(self.pg_interfaces)
3668 self.pg_start()
3669 capture = self.pg1.get_capture(1)
3670 p = capture[0]
3671 try:
3672 ip = p[IP]
3673 tcp = p[TCP]
3674 self.assertEqual(ip.src, server1.ip4)
3675 self.assertEqual(tcp.sport, local_port)
3676 self.assert_packet_checksums_valid(p)
3677 except:
3678 self.logger.error(ppp("Unexpected or invalid packet:", p))
3679 raise
3680
3681 def test_unknown_proto(self):
3682 """ NAT44 translate packet with unknown protocol """
3683 self.nat44_add_address(self.nat_addr)
3684 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3685 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3686 is_inside=0)
3687
3688 # in2out
3689 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3690 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3691 TCP(sport=self.tcp_port_in, dport=20))
3692 self.pg0.add_stream(p)
3693 self.pg_enable_capture(self.pg_interfaces)
3694 self.pg_start()
3695 p = self.pg1.get_capture(1)
3696
3697 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3698 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3699 GRE() /
3700 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
3701 TCP(sport=1234, dport=1234))
3702 self.pg0.add_stream(p)
3703 self.pg_enable_capture(self.pg_interfaces)
3704 self.pg_start()
3705 p = self.pg1.get_capture(1)
3706 packet = p[0]
3707 try:
3708 self.assertEqual(packet[IP].src, self.nat_addr)
3709 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
3710 self.assertTrue(packet.haslayer(GRE))
3711 self.assert_packet_checksums_valid(packet)
3712 except:
3713 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3714 raise
3715
3716 # out2in
3717 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
3718 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3719 GRE() /
3720 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
3721 TCP(sport=1234, dport=1234))
3722 self.pg1.add_stream(p)
3723 self.pg_enable_capture(self.pg_interfaces)
3724 self.pg_start()
3725 p = self.pg0.get_capture(1)
3726 packet = p[0]
3727 try:
3728 self.assertEqual(packet[IP].src, self.pg1.remote_ip4)
3729 self.assertEqual(packet[IP].dst, self.pg0.remote_ip4)
3730 self.assertTrue(packet.haslayer(GRE))
3731 self.assert_packet_checksums_valid(packet)
3732 except:
3733 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3734 raise
3735
3736 def test_hairpinning_unknown_proto(self):
3737 """ NAT44 translate packet with unknown protocol - hairpinning """
3738 host = self.pg0.remote_hosts[0]
3739 server = self.pg0.remote_hosts[1]
3740 host_in_port = 1234
3741 server_out_port = 8765
3742 server_nat_ip = "10.0.0.11"
3743
3744 self.nat44_add_address(self.nat_addr)
3745 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3746 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3747 is_inside=0)
3748
3749 # add static mapping for server
3750 self.nat44_add_static_mapping(server.ip4, server_nat_ip)
3751
3752 # host to server
3753 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
3754 IP(src=host.ip4, dst=server_nat_ip) /
3755 TCP(sport=host_in_port, dport=server_out_port))
3756 self.pg0.add_stream(p)
3757 self.pg_enable_capture(self.pg_interfaces)
3758 self.pg_start()
3759 self.pg0.get_capture(1)
3760
3761 p = (Ether(dst=self.pg0.local_mac, src=host.mac) /
3762 IP(src=host.ip4, dst=server_nat_ip) /
3763 GRE() /
3764 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
3765 TCP(sport=1234, dport=1234))
3766 self.pg0.add_stream(p)
3767 self.pg_enable_capture(self.pg_interfaces)
3768 self.pg_start()
3769 p = self.pg0.get_capture(1)
3770 packet = p[0]
3771 try:
3772 self.assertEqual(packet[IP].src, self.nat_addr)
3773 self.assertEqual(packet[IP].dst, server.ip4)
3774 self.assertTrue(packet.haslayer(GRE))
3775 self.assert_packet_checksums_valid(packet)
3776 except:
3777 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3778 raise
3779
3780 # server to host
3781 p = (Ether(dst=self.pg0.local_mac, src=server.mac) /
3782 IP(src=server.ip4, dst=self.nat_addr) /
3783 GRE() /
3784 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
3785 TCP(sport=1234, dport=1234))
3786 self.pg0.add_stream(p)
3787 self.pg_enable_capture(self.pg_interfaces)
3788 self.pg_start()
3789 p = self.pg0.get_capture(1)
3790 packet = p[0]
3791 try:
3792 self.assertEqual(packet[IP].src, server_nat_ip)
3793 self.assertEqual(packet[IP].dst, host.ip4)
3794 self.assertTrue(packet.haslayer(GRE))
3795 self.assert_packet_checksums_valid(packet)
3796 except:
3797 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3798 raise
3799
3800 def test_output_feature_and_service(self):
3801 """ NAT44 interface output feature and services """
3802 external_addr = '1.2.3.4'
3803 external_port = 80
3804 local_port = 8080
3805
3806 self.vapi.nat44_forwarding_enable_disable(1)
3807 self.nat44_add_address(self.nat_addr)
3808 self.vapi.nat44_add_del_identity_mapping(ip=self.pg1.remote_ip4n)
3809 self.nat44_add_static_mapping(self.pg0.remote_ip4, external_addr,
3810 local_port, external_port,
3811 proto=IP_PROTOS.tcp, out2in_only=1)
3812 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3813 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
3814 is_inside=0)
3815 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
3816 is_inside=0)
3817
3818 # from client to service
3819 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3820 IP(src=self.pg1.remote_ip4, dst=external_addr) /
3821 TCP(sport=12345, dport=external_port))
3822 self.pg1.add_stream(p)
3823 self.pg_enable_capture(self.pg_interfaces)
3824 self.pg_start()
3825 capture = self.pg0.get_capture(1)
3826 p = capture[0]
3827 try:
3828 ip = p[IP]
3829 tcp = p[TCP]
3830 self.assertEqual(ip.dst, self.pg0.remote_ip4)
3831 self.assertEqual(tcp.dport, local_port)
3832 self.assert_packet_checksums_valid(p)
3833 except:
3834 self.logger.error(ppp("Unexpected or invalid packet:", p))
3835 raise
3836
3837 # from service back to client
3838 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3839 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3840 TCP(sport=local_port, dport=12345))
3841 self.pg0.add_stream(p)
3842 self.pg_enable_capture(self.pg_interfaces)
3843 self.pg_start()
3844 capture = self.pg1.get_capture(1)
3845 p = capture[0]
3846 try:
3847 ip = p[IP]
3848 tcp = p[TCP]
3849 self.assertEqual(ip.src, external_addr)
3850 self.assertEqual(tcp.sport, external_port)
3851 self.assert_packet_checksums_valid(p)
3852 except:
3853 self.logger.error(ppp("Unexpected or invalid packet:", p))
3854 raise
3855
3856 # from local network host to external network
3857 pkts = self.create_stream_in(self.pg0, self.pg1)
3858 self.pg0.add_stream(pkts)
3859 self.pg_enable_capture(self.pg_interfaces)
3860 self.pg_start()
3861 capture = self.pg1.get_capture(len(pkts))
3862 self.verify_capture_out(capture)
3863 pkts = self.create_stream_in(self.pg0, self.pg1)
3864 self.pg0.add_stream(pkts)
3865 self.pg_enable_capture(self.pg_interfaces)
3866 self.pg_start()
3867 capture = self.pg1.get_capture(len(pkts))
3868 self.verify_capture_out(capture)
3869
3870 # from external network back to local network host
3871 pkts = self.create_stream_out(self.pg1)
3872 self.pg1.add_stream(pkts)
3873 self.pg_enable_capture(self.pg_interfaces)
3874 self.pg_start()
3875 capture = self.pg0.get_capture(len(pkts))
3876 self.verify_capture_in(capture, self.pg0)
3877
3878 def test_output_feature_and_service2(self):
3879 """ NAT44 interface output feature and service host direct access """
3880 self.vapi.nat44_forwarding_enable_disable(1)
3881 self.nat44_add_address(self.nat_addr)
3882 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
3883 is_inside=0)
3884
3885 # session initiaded from service host - translate
3886 pkts = self.create_stream_in(self.pg0, self.pg1)
3887 self.pg0.add_stream(pkts)
3888 self.pg_enable_capture(self.pg_interfaces)
3889 self.pg_start()
3890 capture = self.pg1.get_capture(len(pkts))
3891 self.verify_capture_out(capture)
3892
3893 pkts = self.create_stream_out(self.pg1)
3894 self.pg1.add_stream(pkts)
3895 self.pg_enable_capture(self.pg_interfaces)
3896 self.pg_start()
3897 capture = self.pg0.get_capture(len(pkts))
3898 self.verify_capture_in(capture, self.pg0)
3899
3900 # session initiaded from remote host - do not translate
3901 self.tcp_port_in = 60303
3902 self.udp_port_in = 60304
3903 self.icmp_id_in = 60305
3904 pkts = self.create_stream_out(self.pg1,
3905 self.pg0.remote_ip4,
3906 use_inside_ports=True)
3907 self.pg1.add_stream(pkts)
3908 self.pg_enable_capture(self.pg_interfaces)
3909 self.pg_start()
3910 capture = self.pg0.get_capture(len(pkts))
3911 self.verify_capture_in(capture, self.pg0)
3912
3913 pkts = self.create_stream_in(self.pg0, self.pg1)
3914 self.pg0.add_stream(pkts)
3915 self.pg_enable_capture(self.pg_interfaces)
3916 self.pg_start()
3917 capture = self.pg1.get_capture(len(pkts))
3918 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
3919 same_port=True)
3920
3921 def test_output_feature_and_service3(self):
3922 """ NAT44 interface output feature and DST NAT """
3923 external_addr = '1.2.3.4'
3924 external_port = 80
3925 local_port = 8080
3926
3927 self.vapi.nat44_forwarding_enable_disable(1)
3928 self.nat44_add_address(self.nat_addr)
3929 self.nat44_add_static_mapping(self.pg1.remote_ip4, external_addr,
3930 local_port, external_port,
3931 proto=IP_PROTOS.tcp, out2in_only=1)
3932 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3933 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
3934 is_inside=0)
3935 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
3936 is_inside=0)
3937
3938 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3939 IP(src=self.pg0.remote_ip4, dst=external_addr) /
3940 TCP(sport=12345, dport=external_port))
3941 self.pg0.add_stream(p)
3942 self.pg_enable_capture(self.pg_interfaces)
3943 self.pg_start()
3944 capture = self.pg1.get_capture(1)
3945 p = capture[0]
3946 try:
3947 ip = p[IP]
3948 tcp = p[TCP]
3949 self.assertEqual(ip.src, self.pg0.remote_ip4)
3950 self.assertEqual(tcp.sport, 12345)
3951 self.assertEqual(ip.dst, self.pg1.remote_ip4)
3952 self.assertEqual(tcp.dport, local_port)
3953 self.assert_packet_checksums_valid(p)
3954 except:
3955 self.logger.error(ppp("Unexpected or invalid packet:", p))
3956 raise
3957
3958 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3959 IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
3960 TCP(sport=local_port, dport=12345))
3961 self.pg1.add_stream(p)
3962 self.pg_enable_capture(self.pg_interfaces)
3963 self.pg_start()
3964 capture = self.pg0.get_capture(1)
3965 p = capture[0]
3966 try:
3967 ip = p[IP]
3968 tcp = p[TCP]
3969 self.assertEqual(ip.src, external_addr)
3970 self.assertEqual(tcp.sport, external_port)
3971 self.assertEqual(ip.dst, self.pg0.remote_ip4)
3972 self.assertEqual(tcp.dport, 12345)
3973 self.assert_packet_checksums_valid(p)
3974 except:
3975 self.logger.error(ppp("Unexpected or invalid packet:", p))
3976 raise
3977
Matus Fabian182e37e2018-08-14 04:21:26 -07003978 def test_next_src_nat(self):
3979 """ On way back forward packet to nat44-in2out node. """
3980 twice_nat_addr = '10.0.1.3'
3981 external_port = 80
3982 local_port = 8080
3983 post_twice_nat_port = 0
3984
3985 self.vapi.nat44_forwarding_enable_disable(1)
3986 self.nat44_add_address(twice_nat_addr, twice_nat=1)
3987 self.nat44_add_static_mapping(self.pg6.remote_ip4, self.pg1.remote_ip4,
3988 local_port, external_port,
3989 proto=IP_PROTOS.tcp, out2in_only=1,
3990 self_twice_nat=1, vrf_id=1)
3991 self.vapi.nat44_interface_add_del_feature(self.pg6.sw_if_index,
3992 is_inside=0)
3993
3994 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
3995 IP(src=self.pg6.remote_ip4, dst=self.pg1.remote_ip4) /
3996 TCP(sport=12345, dport=external_port))
3997 self.pg6.add_stream(p)
3998 self.pg_enable_capture(self.pg_interfaces)
3999 self.pg_start()
4000 capture = self.pg6.get_capture(1)
4001 p = capture[0]
4002 try:
4003 ip = p[IP]
4004 tcp = p[TCP]
4005 self.assertEqual(ip.src, twice_nat_addr)
4006 self.assertNotEqual(tcp.sport, 12345)
4007 post_twice_nat_port = tcp.sport
4008 self.assertEqual(ip.dst, self.pg6.remote_ip4)
4009 self.assertEqual(tcp.dport, local_port)
4010 self.assert_packet_checksums_valid(p)
4011 except:
4012 self.logger.error(ppp("Unexpected or invalid packet:", p))
4013 raise
4014
4015 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
4016 IP(src=self.pg6.remote_ip4, dst=twice_nat_addr) /
4017 TCP(sport=local_port, dport=post_twice_nat_port))
4018 self.pg6.add_stream(p)
4019 self.pg_enable_capture(self.pg_interfaces)
4020 self.pg_start()
4021 capture = self.pg6.get_capture(1)
4022 p = capture[0]
4023 try:
4024 ip = p[IP]
4025 tcp = p[TCP]
4026 self.assertEqual(ip.src, self.pg1.remote_ip4)
4027 self.assertEqual(tcp.sport, external_port)
4028 self.assertEqual(ip.dst, self.pg6.remote_ip4)
4029 self.assertEqual(tcp.dport, 12345)
4030 self.assert_packet_checksums_valid(p)
4031 except:
4032 self.logger.error(ppp("Unexpected or invalid packet:", p))
4033 raise
4034
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004035 def twice_nat_common(self, self_twice_nat=False, same_pg=False, lb=False,
4036 client_id=None):
Matus Fabianb932d262017-12-18 05:38:24 -08004037 twice_nat_addr = '10.0.1.3'
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004038
Matus Fabianb932d262017-12-18 05:38:24 -08004039 port_in = 8080
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004040 if lb:
4041 if not same_pg:
4042 port_in1 = port_in
4043 port_in2 = port_in
4044 else:
4045 port_in1 = port_in+1
4046 port_in2 = port_in+2
4047
Matus Fabianb932d262017-12-18 05:38:24 -08004048 port_out = 80
4049 eh_port_out = 4567
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004050
4051 server1 = self.pg0.remote_hosts[0]
4052 server2 = self.pg0.remote_hosts[1]
4053 if lb and same_pg:
4054 server2 = server1
4055 if not lb:
4056 server = server1
4057
4058 pg0 = self.pg0
4059 if same_pg:
4060 pg1 = self.pg0
4061 else:
4062 pg1 = self.pg1
4063
4064 eh_translate = ((not self_twice_nat) or (not lb and same_pg) or
4065 client_id == 1)
4066
Matus Fabianb932d262017-12-18 05:38:24 -08004067 self.nat44_add_address(self.nat_addr)
4068 self.nat44_add_address(twice_nat_addr, twice_nat=1)
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004069 if not lb:
4070 self.nat44_add_static_mapping(pg0.remote_ip4, self.nat_addr,
4071 port_in, port_out,
4072 proto=IP_PROTOS.tcp,
4073 twice_nat=int(not self_twice_nat),
4074 self_twice_nat=int(self_twice_nat))
4075 else:
4076 locals = [{'addr': server1.ip4n,
4077 'port': port_in1,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07004078 'probability': 50,
4079 'vrf_id': 0},
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004080 {'addr': server2.ip4n,
4081 'port': port_in2,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07004082 'probability': 50,
4083 'vrf_id': 0}]
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004084 out_addr_n = socket.inet_pton(socket.AF_INET, self.nat_addr)
4085 self.vapi.nat44_add_del_lb_static_mapping(out_addr_n,
4086 port_out,
4087 IP_PROTOS.tcp,
4088 twice_nat=int(
4089 not self_twice_nat),
4090 self_twice_nat=int(
4091 self_twice_nat),
4092 local_num=len(locals),
4093 locals=locals)
4094 self.vapi.nat44_interface_add_del_feature(pg0.sw_if_index)
4095 self.vapi.nat44_interface_add_del_feature(pg1.sw_if_index,
Matus Fabianb932d262017-12-18 05:38:24 -08004096 is_inside=0)
4097
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004098 if same_pg:
4099 if not lb:
4100 client = server
4101 else:
4102 assert client_id is not None
4103 if client_id == 1:
4104 client = self.pg0.remote_hosts[0]
4105 elif client_id == 2:
4106 client = self.pg0.remote_hosts[1]
4107 else:
4108 client = pg1.remote_hosts[0]
4109 p = (Ether(src=pg1.remote_mac, dst=pg1.local_mac) /
4110 IP(src=client.ip4, dst=self.nat_addr) /
Matus Fabianb932d262017-12-18 05:38:24 -08004111 TCP(sport=eh_port_out, dport=port_out))
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004112 pg1.add_stream(p)
Matus Fabianb932d262017-12-18 05:38:24 -08004113 self.pg_enable_capture(self.pg_interfaces)
4114 self.pg_start()
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004115 capture = pg0.get_capture(1)
Matus Fabianb932d262017-12-18 05:38:24 -08004116 p = capture[0]
4117 try:
4118 ip = p[IP]
4119 tcp = p[TCP]
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004120 if lb:
4121 if ip.dst == server1.ip4:
4122 server = server1
4123 port_in = port_in1
4124 else:
4125 server = server2
4126 port_in = port_in2
4127 self.assertEqual(ip.dst, server.ip4)
4128 if lb and same_pg:
4129 self.assertIn(tcp.dport, [port_in1, port_in2])
4130 else:
4131 self.assertEqual(tcp.dport, port_in)
4132 if eh_translate:
4133 self.assertEqual(ip.src, twice_nat_addr)
4134 self.assertNotEqual(tcp.sport, eh_port_out)
4135 else:
4136 self.assertEqual(ip.src, client.ip4)
4137 self.assertEqual(tcp.sport, eh_port_out)
4138 eh_addr_in = ip.src
Matus Fabianb932d262017-12-18 05:38:24 -08004139 eh_port_in = tcp.sport
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004140 saved_port_in = tcp.dport
Klement Sekerad81ae412018-05-16 10:52:54 +02004141 self.assert_packet_checksums_valid(p)
Matus Fabianb932d262017-12-18 05:38:24 -08004142 except:
4143 self.logger.error(ppp("Unexpected or invalid packet:", p))
4144 raise
4145
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004146 p = (Ether(src=server.mac, dst=pg0.local_mac) /
4147 IP(src=server.ip4, dst=eh_addr_in) /
4148 TCP(sport=saved_port_in, dport=eh_port_in))
4149 pg0.add_stream(p)
Matus Fabianb932d262017-12-18 05:38:24 -08004150 self.pg_enable_capture(self.pg_interfaces)
4151 self.pg_start()
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004152 capture = pg1.get_capture(1)
Matus Fabianb932d262017-12-18 05:38:24 -08004153 p = capture[0]
4154 try:
4155 ip = p[IP]
4156 tcp = p[TCP]
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004157 self.assertEqual(ip.dst, client.ip4)
Matus Fabianb932d262017-12-18 05:38:24 -08004158 self.assertEqual(ip.src, self.nat_addr)
4159 self.assertEqual(tcp.dport, eh_port_out)
4160 self.assertEqual(tcp.sport, port_out)
Klement Sekerad81ae412018-05-16 10:52:54 +02004161 self.assert_packet_checksums_valid(p)
Matus Fabianb932d262017-12-18 05:38:24 -08004162 except:
4163 self.logger.error(ppp("Unexpected or invalid packet:", p))
4164 raise
4165
Matus Fabian70a26ac2018-05-14 06:20:28 -07004166 if eh_translate:
4167 sessions = self.vapi.nat44_user_session_dump(server.ip4n, 0)
4168 self.assertEqual(len(sessions), 1)
4169 self.assertTrue(sessions[0].ext_host_valid)
4170 self.assertTrue(sessions[0].is_twicenat)
4171 self.vapi.nat44_del_session(
4172 sessions[0].inside_ip_address,
4173 sessions[0].inside_port,
4174 sessions[0].protocol,
4175 ext_host_address=sessions[0].ext_host_nat_address,
4176 ext_host_port=sessions[0].ext_host_nat_port)
4177 sessions = self.vapi.nat44_user_session_dump(server.ip4n, 0)
4178 self.assertEqual(len(sessions), 0)
4179
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004180 def test_twice_nat(self):
4181 """ Twice NAT44 """
4182 self.twice_nat_common()
4183
4184 def test_self_twice_nat_positive(self):
4185 """ Self Twice NAT44 (positive test) """
4186 self.twice_nat_common(self_twice_nat=True, same_pg=True)
4187
4188 def test_self_twice_nat_negative(self):
4189 """ Self Twice NAT44 (negative test) """
4190 self.twice_nat_common(self_twice_nat=True)
4191
Matus Fabianb932d262017-12-18 05:38:24 -08004192 def test_twice_nat_lb(self):
4193 """ Twice NAT44 local service load balancing """
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004194 self.twice_nat_common(lb=True)
Matus Fabianb932d262017-12-18 05:38:24 -08004195
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004196 def test_self_twice_nat_lb_positive(self):
4197 """ Self Twice NAT44 local service load balancing (positive test) """
4198 self.twice_nat_common(lb=True, self_twice_nat=True, same_pg=True,
4199 client_id=1)
Matus Fabianb932d262017-12-18 05:38:24 -08004200
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004201 def test_self_twice_nat_lb_negative(self):
4202 """ Self Twice NAT44 local service load balancing (negative test) """
4203 self.twice_nat_common(lb=True, self_twice_nat=True, same_pg=True,
4204 client_id=2)
Matus Fabianb932d262017-12-18 05:38:24 -08004205
4206 def test_twice_nat_interface_addr(self):
4207 """ Acquire twice NAT44 addresses from interface """
Matus Fabiana6110b62018-06-13 05:39:07 -07004208 self.vapi.nat44_add_interface_addr(self.pg3.sw_if_index, twice_nat=1)
Matus Fabianb932d262017-12-18 05:38:24 -08004209
4210 # no address in NAT pool
4211 adresses = self.vapi.nat44_address_dump()
4212 self.assertEqual(0, len(adresses))
4213
4214 # configure interface address and check NAT address pool
Matus Fabiana6110b62018-06-13 05:39:07 -07004215 self.pg3.config_ip4()
Matus Fabianb932d262017-12-18 05:38:24 -08004216 adresses = self.vapi.nat44_address_dump()
4217 self.assertEqual(1, len(adresses))
Matus Fabiana6110b62018-06-13 05:39:07 -07004218 self.assertEqual(adresses[0].ip_address[0:4], self.pg3.local_ip4n)
Matus Fabianb932d262017-12-18 05:38:24 -08004219 self.assertEqual(adresses[0].twice_nat, 1)
4220
4221 # remove interface address and check NAT address pool
Matus Fabiana6110b62018-06-13 05:39:07 -07004222 self.pg3.unconfig_ip4()
Matus Fabianb932d262017-12-18 05:38:24 -08004223 adresses = self.vapi.nat44_address_dump()
4224 self.assertEqual(0, len(adresses))
4225
Matus Fabianebdf1902018-05-04 03:57:42 -07004226 def test_tcp_session_close_in(self):
4227 """ Close TCP session from inside network """
Matus Fabian229c1aa2018-05-28 04:09:52 -07004228 self.tcp_port_out = 10505
Matus Fabianebdf1902018-05-04 03:57:42 -07004229 self.nat44_add_address(self.nat_addr)
Matus Fabian229c1aa2018-05-28 04:09:52 -07004230 self.nat44_add_static_mapping(self.pg0.remote_ip4,
4231 self.nat_addr,
4232 self.tcp_port_in,
4233 self.tcp_port_out,
4234 proto=IP_PROTOS.tcp,
4235 twice_nat=1)
Matus Fabianebdf1902018-05-04 03:57:42 -07004236 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4237 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4238 is_inside=0)
4239
4240 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
4241 start_sessnum = len(sessions)
4242
4243 self.initiate_tcp_session(self.pg0, self.pg1)
4244
Matus Fabian229c1aa2018-05-28 04:09:52 -07004245 # FIN packet in -> out
4246 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4247 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4248 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
4249 flags="FA", seq=100, ack=300))
4250 self.pg0.add_stream(p)
4251 self.pg_enable_capture(self.pg_interfaces)
4252 self.pg_start()
4253 self.pg1.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07004254
Matus Fabian229c1aa2018-05-28 04:09:52 -07004255 pkts = []
Matus Fabianebdf1902018-05-04 03:57:42 -07004256
Matus Fabian229c1aa2018-05-28 04:09:52 -07004257 # ACK packet out -> in
4258 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4259 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4260 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
4261 flags="A", seq=300, ack=101))
4262 pkts.append(p)
Matus Fabianebdf1902018-05-04 03:57:42 -07004263
Matus Fabian229c1aa2018-05-28 04:09:52 -07004264 # FIN packet out -> in
4265 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4266 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4267 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
4268 flags="FA", seq=300, ack=101))
4269 pkts.append(p)
Matus Fabianebdf1902018-05-04 03:57:42 -07004270
Matus Fabian229c1aa2018-05-28 04:09:52 -07004271 self.pg1.add_stream(pkts)
4272 self.pg_enable_capture(self.pg_interfaces)
4273 self.pg_start()
4274 self.pg0.get_capture(2)
Matus Fabianebdf1902018-05-04 03:57:42 -07004275
Matus Fabian229c1aa2018-05-28 04:09:52 -07004276 # ACK packet in -> out
4277 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4278 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4279 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
4280 flags="A", seq=101, ack=301))
4281 self.pg0.add_stream(p)
4282 self.pg_enable_capture(self.pg_interfaces)
4283 self.pg_start()
4284 self.pg1.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07004285
Matus Fabian229c1aa2018-05-28 04:09:52 -07004286 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n,
4287 0)
4288 self.assertEqual(len(sessions) - start_sessnum, 0)
Matus Fabianebdf1902018-05-04 03:57:42 -07004289
4290 def test_tcp_session_close_out(self):
4291 """ Close TCP session from outside network """
Matus Fabian229c1aa2018-05-28 04:09:52 -07004292 self.tcp_port_out = 10505
Matus Fabianebdf1902018-05-04 03:57:42 -07004293 self.nat44_add_address(self.nat_addr)
Matus Fabian229c1aa2018-05-28 04:09:52 -07004294 self.nat44_add_static_mapping(self.pg0.remote_ip4,
4295 self.nat_addr,
4296 self.tcp_port_in,
4297 self.tcp_port_out,
4298 proto=IP_PROTOS.tcp,
4299 twice_nat=1)
Matus Fabianebdf1902018-05-04 03:57:42 -07004300 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4301 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4302 is_inside=0)
4303
4304 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
4305 start_sessnum = len(sessions)
4306
4307 self.initiate_tcp_session(self.pg0, self.pg1)
4308
Matus Fabian229c1aa2018-05-28 04:09:52 -07004309 # FIN packet out -> in
4310 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4311 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4312 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
4313 flags="FA", seq=100, ack=300))
4314 self.pg1.add_stream(p)
4315 self.pg_enable_capture(self.pg_interfaces)
4316 self.pg_start()
4317 self.pg0.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07004318
Matus Fabian229c1aa2018-05-28 04:09:52 -07004319 # FIN+ACK packet in -> out
4320 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4321 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4322 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
4323 flags="FA", seq=300, ack=101))
Matus Fabianebdf1902018-05-04 03:57:42 -07004324
Matus Fabian229c1aa2018-05-28 04:09:52 -07004325 self.pg0.add_stream(p)
4326 self.pg_enable_capture(self.pg_interfaces)
4327 self.pg_start()
4328 self.pg1.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07004329
Matus Fabian229c1aa2018-05-28 04:09:52 -07004330 # ACK packet out -> in
4331 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4332 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4333 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
4334 flags="A", seq=101, ack=301))
4335 self.pg1.add_stream(p)
4336 self.pg_enable_capture(self.pg_interfaces)
4337 self.pg_start()
4338 self.pg0.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07004339
Matus Fabian229c1aa2018-05-28 04:09:52 -07004340 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n,
4341 0)
4342 self.assertEqual(len(sessions) - start_sessnum, 0)
Matus Fabianebdf1902018-05-04 03:57:42 -07004343
4344 def test_tcp_session_close_simultaneous(self):
4345 """ Close TCP session from inside network """
Matus Fabian229c1aa2018-05-28 04:09:52 -07004346 self.tcp_port_out = 10505
Matus Fabianebdf1902018-05-04 03:57:42 -07004347 self.nat44_add_address(self.nat_addr)
Matus Fabian229c1aa2018-05-28 04:09:52 -07004348 self.nat44_add_static_mapping(self.pg0.remote_ip4,
4349 self.nat_addr,
4350 self.tcp_port_in,
4351 self.tcp_port_out,
4352 proto=IP_PROTOS.tcp,
4353 twice_nat=1)
Matus Fabianebdf1902018-05-04 03:57:42 -07004354 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4355 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4356 is_inside=0)
4357
4358 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
4359 start_sessnum = len(sessions)
4360
4361 self.initiate_tcp_session(self.pg0, self.pg1)
4362
Matus Fabian229c1aa2018-05-28 04:09:52 -07004363 # FIN packet in -> out
4364 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4365 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4366 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
4367 flags="FA", seq=100, ack=300))
4368 self.pg0.add_stream(p)
4369 self.pg_enable_capture(self.pg_interfaces)
4370 self.pg_start()
4371 self.pg1.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07004372
Matus Fabian229c1aa2018-05-28 04:09:52 -07004373 # FIN packet out -> in
4374 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4375 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4376 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
4377 flags="FA", seq=300, ack=100))
4378 self.pg1.add_stream(p)
4379 self.pg_enable_capture(self.pg_interfaces)
4380 self.pg_start()
4381 self.pg0.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07004382
Matus Fabian229c1aa2018-05-28 04:09:52 -07004383 # ACK packet in -> out
4384 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4385 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4386 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
4387 flags="A", seq=101, ack=301))
4388 self.pg0.add_stream(p)
4389 self.pg_enable_capture(self.pg_interfaces)
4390 self.pg_start()
4391 self.pg1.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07004392
Matus Fabian229c1aa2018-05-28 04:09:52 -07004393 # ACK packet out -> in
4394 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4395 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4396 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
4397 flags="A", seq=301, ack=101))
4398 self.pg1.add_stream(p)
4399 self.pg_enable_capture(self.pg_interfaces)
4400 self.pg_start()
4401 self.pg0.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07004402
Matus Fabian229c1aa2018-05-28 04:09:52 -07004403 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n,
4404 0)
4405 self.assertEqual(len(sessions) - start_sessnum, 0)
Matus Fabianebdf1902018-05-04 03:57:42 -07004406
Matus Fabiana6110b62018-06-13 05:39:07 -07004407 def test_one_armed_nat44_static(self):
4408 """ One armed NAT44 and 1:1 NAPT asymmetrical rule """
4409 remote_host = self.pg4.remote_hosts[0]
4410 local_host = self.pg4.remote_hosts[1]
4411 external_port = 80
4412 local_port = 8080
4413 eh_port_in = 0
4414
4415 self.vapi.nat44_forwarding_enable_disable(1)
4416 self.nat44_add_address(self.nat_addr, twice_nat=1)
4417 self.nat44_add_static_mapping(local_host.ip4, self.nat_addr,
4418 local_port, external_port,
4419 proto=IP_PROTOS.tcp, out2in_only=1,
4420 twice_nat=1)
4421 self.vapi.nat44_interface_add_del_feature(self.pg4.sw_if_index)
4422 self.vapi.nat44_interface_add_del_feature(self.pg4.sw_if_index,
4423 is_inside=0)
4424
4425 # from client to service
4426 p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
4427 IP(src=remote_host.ip4, dst=self.nat_addr) /
4428 TCP(sport=12345, dport=external_port))
4429 self.pg4.add_stream(p)
4430 self.pg_enable_capture(self.pg_interfaces)
4431 self.pg_start()
4432 capture = self.pg4.get_capture(1)
4433 p = capture[0]
4434 try:
4435 ip = p[IP]
4436 tcp = p[TCP]
4437 self.assertEqual(ip.dst, local_host.ip4)
4438 self.assertEqual(ip.src, self.nat_addr)
4439 self.assertEqual(tcp.dport, local_port)
4440 self.assertNotEqual(tcp.sport, 12345)
4441 eh_port_in = tcp.sport
4442 self.assert_packet_checksums_valid(p)
4443 except:
4444 self.logger.error(ppp("Unexpected or invalid packet:", p))
4445 raise
4446
4447 # from service back to client
4448 p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
4449 IP(src=local_host.ip4, dst=self.nat_addr) /
4450 TCP(sport=local_port, dport=eh_port_in))
4451 self.pg4.add_stream(p)
4452 self.pg_enable_capture(self.pg_interfaces)
4453 self.pg_start()
4454 capture = self.pg4.get_capture(1)
4455 p = capture[0]
4456 try:
4457 ip = p[IP]
4458 tcp = p[TCP]
4459 self.assertEqual(ip.src, self.nat_addr)
4460 self.assertEqual(ip.dst, remote_host.ip4)
4461 self.assertEqual(tcp.sport, external_port)
4462 self.assertEqual(tcp.dport, 12345)
4463 self.assert_packet_checksums_valid(p)
4464 except:
4465 self.logger.error(ppp("Unexpected or invalid packet:", p))
4466 raise
4467
4468 def test_static_with_port_out2(self):
4469 """ 1:1 NAPT asymmetrical rule """
4470
4471 external_port = 80
4472 local_port = 8080
4473
4474 self.vapi.nat44_forwarding_enable_disable(1)
4475 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
4476 local_port, external_port,
4477 proto=IP_PROTOS.tcp, out2in_only=1)
4478 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4479 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4480 is_inside=0)
4481
4482 # from client to service
4483 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4484 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4485 TCP(sport=12345, dport=external_port))
4486 self.pg1.add_stream(p)
4487 self.pg_enable_capture(self.pg_interfaces)
4488 self.pg_start()
4489 capture = self.pg0.get_capture(1)
4490 p = capture[0]
4491 try:
4492 ip = p[IP]
4493 tcp = p[TCP]
4494 self.assertEqual(ip.dst, self.pg0.remote_ip4)
4495 self.assertEqual(tcp.dport, local_port)
4496 self.assert_packet_checksums_valid(p)
4497 except:
4498 self.logger.error(ppp("Unexpected or invalid packet:", p))
4499 raise
4500
4501 # ICMP error
4502 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
4503 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4504 ICMP(type=11) / capture[0][IP])
4505 self.pg0.add_stream(p)
4506 self.pg_enable_capture(self.pg_interfaces)
4507 self.pg_start()
4508 capture = self.pg1.get_capture(1)
4509 p = capture[0]
4510 try:
4511 self.assertEqual(p[IP].src, self.nat_addr)
4512 inner = p[IPerror]
4513 self.assertEqual(inner.dst, self.nat_addr)
4514 self.assertEqual(inner[TCPerror].dport, external_port)
4515 except:
4516 self.logger.error(ppp("Unexpected or invalid packet:", p))
4517 raise
4518
4519 # from service back to client
4520 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4521 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4522 TCP(sport=local_port, dport=12345))
4523 self.pg0.add_stream(p)
4524 self.pg_enable_capture(self.pg_interfaces)
4525 self.pg_start()
4526 capture = self.pg1.get_capture(1)
4527 p = capture[0]
4528 try:
4529 ip = p[IP]
4530 tcp = p[TCP]
4531 self.assertEqual(ip.src, self.nat_addr)
4532 self.assertEqual(tcp.sport, external_port)
4533 self.assert_packet_checksums_valid(p)
4534 except:
4535 self.logger.error(ppp("Unexpected or invalid packet:", p))
4536 raise
4537
4538 # ICMP error
4539 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
4540 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4541 ICMP(type=11) / capture[0][IP])
4542 self.pg1.add_stream(p)
4543 self.pg_enable_capture(self.pg_interfaces)
4544 self.pg_start()
4545 capture = self.pg0.get_capture(1)
4546 p = capture[0]
4547 try:
4548 self.assertEqual(p[IP].dst, self.pg0.remote_ip4)
4549 inner = p[IPerror]
4550 self.assertEqual(inner.src, self.pg0.remote_ip4)
4551 self.assertEqual(inner[TCPerror].sport, local_port)
4552 except:
4553 self.logger.error(ppp("Unexpected or invalid packet:", p))
4554 raise
4555
4556 # from client to server (no translation)
4557 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4558 IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
4559 TCP(sport=12346, dport=local_port))
4560 self.pg1.add_stream(p)
4561 self.pg_enable_capture(self.pg_interfaces)
4562 self.pg_start()
4563 capture = self.pg0.get_capture(1)
4564 p = capture[0]
4565 try:
4566 ip = p[IP]
4567 tcp = p[TCP]
4568 self.assertEqual(ip.dst, self.pg0.remote_ip4)
4569 self.assertEqual(tcp.dport, local_port)
4570 self.assert_packet_checksums_valid(p)
4571 except:
4572 self.logger.error(ppp("Unexpected or invalid packet:", p))
4573 raise
4574
4575 # from service back to client (no translation)
4576 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4577 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4578 TCP(sport=local_port, dport=12346))
4579 self.pg0.add_stream(p)
4580 self.pg_enable_capture(self.pg_interfaces)
4581 self.pg_start()
4582 capture = self.pg1.get_capture(1)
4583 p = capture[0]
4584 try:
4585 ip = p[IP]
4586 tcp = p[TCP]
4587 self.assertEqual(ip.src, self.pg0.remote_ip4)
4588 self.assertEqual(tcp.sport, local_port)
4589 self.assert_packet_checksums_valid(p)
4590 except:
4591 self.logger.error(ppp("Unexpected or invalid packet:", p))
4592 raise
4593
Matus Fabian235a47e2018-06-25 16:42:36 -07004594 def test_output_feature(self):
4595 """ NAT44 interface output feature (in2out postrouting) """
4596 self.vapi.nat44_forwarding_enable_disable(1)
4597 self.nat44_add_address(self.nat_addr)
4598 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
4599 is_inside=0)
4600 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
4601 is_inside=0)
4602
4603 # in2out
4604 pkts = self.create_stream_in(self.pg0, self.pg1)
4605 self.pg0.add_stream(pkts)
4606 self.pg_enable_capture(self.pg_interfaces)
4607 self.pg_start()
4608 capture = self.pg1.get_capture(len(pkts))
4609 self.verify_capture_out(capture)
4610
4611 # out2in
4612 pkts = self.create_stream_out(self.pg1)
4613 self.pg1.add_stream(pkts)
4614 self.pg_enable_capture(self.pg_interfaces)
4615 self.pg_start()
4616 capture = self.pg0.get_capture(len(pkts))
4617 self.verify_capture_in(capture, self.pg0)
4618
Matus Fabian8008d7c2018-07-09 01:34:20 -07004619 def test_multiple_vrf(self):
4620 """ Multiple VRF setup """
4621 external_addr = '1.2.3.4'
4622 external_port = 80
4623 local_port = 8080
4624 port = 0
4625
4626 self.vapi.nat44_forwarding_enable_disable(1)
4627 self.nat44_add_address(self.nat_addr)
4628 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4629 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
4630 is_inside=0)
4631 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
4632 is_inside=0)
4633 self.vapi.nat44_interface_add_del_feature(self.pg5.sw_if_index)
4634 self.vapi.nat44_interface_add_del_feature(self.pg5.sw_if_index,
4635 is_inside=0)
4636 self.vapi.nat44_interface_add_del_feature(self.pg6.sw_if_index,
4637 is_inside=0)
4638 self.nat44_add_static_mapping(self.pg5.remote_ip4, external_addr,
4639 local_port, external_port, vrf_id=1,
4640 proto=IP_PROTOS.tcp, out2in_only=1)
4641 self.nat44_add_static_mapping(
4642 self.pg0.remote_ip4, external_sw_if_index=self.pg0.sw_if_index,
4643 local_port=local_port, vrf_id=0, external_port=external_port,
4644 proto=IP_PROTOS.tcp, out2in_only=1)
4645
4646 # from client to service (both VRF1)
4647 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
4648 IP(src=self.pg6.remote_ip4, dst=external_addr) /
4649 TCP(sport=12345, dport=external_port))
4650 self.pg6.add_stream(p)
4651 self.pg_enable_capture(self.pg_interfaces)
4652 self.pg_start()
4653 capture = self.pg5.get_capture(1)
4654 p = capture[0]
4655 try:
4656 ip = p[IP]
4657 tcp = p[TCP]
4658 self.assertEqual(ip.dst, self.pg5.remote_ip4)
4659 self.assertEqual(tcp.dport, local_port)
4660 self.assert_packet_checksums_valid(p)
4661 except:
4662 self.logger.error(ppp("Unexpected or invalid packet:", p))
4663 raise
4664
4665 # from service back to client (both VRF1)
4666 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
4667 IP(src=self.pg5.remote_ip4, dst=self.pg6.remote_ip4) /
4668 TCP(sport=local_port, dport=12345))
4669 self.pg5.add_stream(p)
4670 self.pg_enable_capture(self.pg_interfaces)
4671 self.pg_start()
4672 capture = self.pg6.get_capture(1)
4673 p = capture[0]
4674 try:
4675 ip = p[IP]
4676 tcp = p[TCP]
4677 self.assertEqual(ip.src, external_addr)
4678 self.assertEqual(tcp.sport, external_port)
4679 self.assert_packet_checksums_valid(p)
4680 except:
4681 self.logger.error(ppp("Unexpected or invalid packet:", p))
4682 raise
4683
4684 # dynamic NAT from VRF1 to VRF0 (output-feature)
4685 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
4686 IP(src=self.pg5.remote_ip4, dst=self.pg1.remote_ip4) /
4687 TCP(sport=2345, dport=22))
4688 self.pg5.add_stream(p)
4689 self.pg_enable_capture(self.pg_interfaces)
4690 self.pg_start()
4691 capture = self.pg1.get_capture(1)
4692 p = capture[0]
4693 try:
4694 ip = p[IP]
4695 tcp = p[TCP]
4696 self.assertEqual(ip.src, self.nat_addr)
4697 self.assertNotEqual(tcp.sport, 2345)
4698 self.assert_packet_checksums_valid(p)
4699 port = tcp.sport
4700 except:
4701 self.logger.error(ppp("Unexpected or invalid packet:", p))
4702 raise
4703
4704 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4705 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4706 TCP(sport=22, dport=port))
4707 self.pg1.add_stream(p)
4708 self.pg_enable_capture(self.pg_interfaces)
4709 self.pg_start()
4710 capture = self.pg5.get_capture(1)
4711 p = capture[0]
4712 try:
4713 ip = p[IP]
4714 tcp = p[TCP]
4715 self.assertEqual(ip.dst, self.pg5.remote_ip4)
4716 self.assertEqual(tcp.dport, 2345)
4717 self.assert_packet_checksums_valid(p)
4718 except:
4719 self.logger.error(ppp("Unexpected or invalid packet:", p))
4720 raise
4721
4722 # from client VRF1 to service VRF0
4723 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
4724 IP(src=self.pg6.remote_ip4, dst=self.pg0.local_ip4) /
4725 TCP(sport=12346, dport=external_port))
4726 self.pg6.add_stream(p)
4727 self.pg_enable_capture(self.pg_interfaces)
4728 self.pg_start()
4729 capture = self.pg0.get_capture(1)
4730 p = capture[0]
4731 try:
4732 ip = p[IP]
4733 tcp = p[TCP]
4734 self.assertEqual(ip.dst, self.pg0.remote_ip4)
4735 self.assertEqual(tcp.dport, local_port)
4736 self.assert_packet_checksums_valid(p)
4737 except:
4738 self.logger.error(ppp("Unexpected or invalid packet:", p))
4739 raise
4740
4741 # from service VRF0 back to client VRF1
4742 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4743 IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
4744 TCP(sport=local_port, dport=12346))
4745 self.pg0.add_stream(p)
4746 self.pg_enable_capture(self.pg_interfaces)
4747 self.pg_start()
4748 capture = self.pg6.get_capture(1)
4749 p = capture[0]
4750 try:
4751 ip = p[IP]
4752 tcp = p[TCP]
4753 self.assertEqual(ip.src, self.pg0.local_ip4)
4754 self.assertEqual(tcp.sport, external_port)
4755 self.assert_packet_checksums_valid(p)
4756 except:
4757 self.logger.error(ppp("Unexpected or invalid packet:", p))
4758 raise
4759
4760 # from client VRF0 to service VRF1
4761 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4762 IP(src=self.pg0.remote_ip4, dst=external_addr) /
4763 TCP(sport=12347, dport=external_port))
4764 self.pg0.add_stream(p)
4765 self.pg_enable_capture(self.pg_interfaces)
4766 self.pg_start()
4767 capture = self.pg5.get_capture(1)
4768 p = capture[0]
4769 try:
4770 ip = p[IP]
4771 tcp = p[TCP]
4772 self.assertEqual(ip.dst, self.pg5.remote_ip4)
4773 self.assertEqual(tcp.dport, local_port)
4774 self.assert_packet_checksums_valid(p)
4775 except:
4776 self.logger.error(ppp("Unexpected or invalid packet:", p))
4777 raise
4778
4779 # from service VRF1 back to client VRF0
4780 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
4781 IP(src=self.pg5.remote_ip4, dst=self.pg0.remote_ip4) /
4782 TCP(sport=local_port, dport=12347))
4783 self.pg5.add_stream(p)
4784 self.pg_enable_capture(self.pg_interfaces)
4785 self.pg_start()
4786 capture = self.pg0.get_capture(1)
4787 p = capture[0]
4788 try:
4789 ip = p[IP]
4790 tcp = p[TCP]
4791 self.assertEqual(ip.src, external_addr)
4792 self.assertEqual(tcp.sport, external_port)
4793 self.assert_packet_checksums_valid(p)
4794 except:
4795 self.logger.error(ppp("Unexpected or invalid packet:", p))
4796 raise
4797
4798 # from client to server (both VRF1, no translation)
4799 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
4800 IP(src=self.pg6.remote_ip4, dst=self.pg5.remote_ip4) /
4801 TCP(sport=12348, dport=local_port))
4802 self.pg6.add_stream(p)
4803 self.pg_enable_capture(self.pg_interfaces)
4804 self.pg_start()
4805 capture = self.pg5.get_capture(1)
4806 p = capture[0]
4807 try:
4808 ip = p[IP]
4809 tcp = p[TCP]
4810 self.assertEqual(ip.dst, self.pg5.remote_ip4)
4811 self.assertEqual(tcp.dport, local_port)
4812 self.assert_packet_checksums_valid(p)
4813 except:
4814 self.logger.error(ppp("Unexpected or invalid packet:", p))
4815 raise
4816
4817 # from server back to client (both VRF1, no translation)
4818 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
4819 IP(src=self.pg5.remote_ip4, dst=self.pg6.remote_ip4) /
4820 TCP(sport=local_port, dport=12348))
4821 self.pg5.add_stream(p)
4822 self.pg_enable_capture(self.pg_interfaces)
4823 self.pg_start()
4824 capture = self.pg6.get_capture(1)
4825 p = capture[0]
4826 try:
4827 ip = p[IP]
4828 tcp = p[TCP]
4829 self.assertEqual(ip.src, self.pg5.remote_ip4)
4830 self.assertEqual(tcp.sport, local_port)
4831 self.assert_packet_checksums_valid(p)
4832 except:
4833 self.logger.error(ppp("Unexpected or invalid packet:", p))
4834 raise
4835
4836 # from client VRF1 to server VRF0 (no translation)
4837 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4838 IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
4839 TCP(sport=local_port, dport=12349))
4840 self.pg0.add_stream(p)
4841 self.pg_enable_capture(self.pg_interfaces)
4842 self.pg_start()
4843 capture = self.pg6.get_capture(1)
4844 p = capture[0]
4845 try:
4846 ip = p[IP]
4847 tcp = p[TCP]
4848 self.assertEqual(ip.src, self.pg0.remote_ip4)
4849 self.assertEqual(tcp.sport, local_port)
4850 self.assert_packet_checksums_valid(p)
4851 except:
4852 self.logger.error(ppp("Unexpected or invalid packet:", p))
4853 raise
4854
4855 # from server VRF0 back to client VRF1 (no translation)
4856 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4857 IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
4858 TCP(sport=local_port, dport=12349))
4859 self.pg0.add_stream(p)
4860 self.pg_enable_capture(self.pg_interfaces)
4861 self.pg_start()
4862 capture = self.pg6.get_capture(1)
4863 p = capture[0]
4864 try:
4865 ip = p[IP]
4866 tcp = p[TCP]
4867 self.assertEqual(ip.src, self.pg0.remote_ip4)
4868 self.assertEqual(tcp.sport, local_port)
4869 self.assert_packet_checksums_valid(p)
4870 except:
4871 self.logger.error(ppp("Unexpected or invalid packet:", p))
4872 raise
4873
4874 # from client VRF0 to server VRF1 (no translation)
4875 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4876 IP(src=self.pg0.remote_ip4, dst=self.pg5.remote_ip4) /
4877 TCP(sport=12344, dport=local_port))
4878 self.pg0.add_stream(p)
4879 self.pg_enable_capture(self.pg_interfaces)
4880 self.pg_start()
4881 capture = self.pg5.get_capture(1)
4882 p = capture[0]
4883 try:
4884 ip = p[IP]
4885 tcp = p[TCP]
4886 self.assertEqual(ip.dst, self.pg5.remote_ip4)
4887 self.assertEqual(tcp.dport, local_port)
4888 self.assert_packet_checksums_valid(p)
4889 except:
4890 self.logger.error(ppp("Unexpected or invalid packet:", p))
4891 raise
4892
4893 # from server VRF1 back to client VRF0 (no translation)
4894 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
4895 IP(src=self.pg5.remote_ip4, dst=self.pg0.remote_ip4) /
4896 TCP(sport=local_port, dport=12344))
4897 self.pg5.add_stream(p)
4898 self.pg_enable_capture(self.pg_interfaces)
4899 self.pg_start()
4900 capture = self.pg0.get_capture(1)
4901 p = capture[0]
4902 try:
4903 ip = p[IP]
4904 tcp = p[TCP]
4905 self.assertEqual(ip.src, self.pg5.remote_ip4)
4906 self.assertEqual(tcp.sport, local_port)
4907 self.assert_packet_checksums_valid(p)
4908 except:
4909 self.logger.error(ppp("Unexpected or invalid packet:", p))
4910 raise
4911
Matus Fabiande886752016-12-07 03:38:19 -08004912 def tearDown(self):
Matus Fabiana6110b62018-06-13 05:39:07 -07004913 super(TestNAT44EndpointDependent, self).tearDown()
Matus Fabiande886752016-12-07 03:38:19 -08004914 if not self.vpp_dead:
Matus Fabian82119542018-01-25 01:13:22 -08004915 self.logger.info(self.vapi.cli("show nat44 addresses"))
4916 self.logger.info(self.vapi.cli("show nat44 interfaces"))
4917 self.logger.info(self.vapi.cli("show nat44 static mappings"))
4918 self.logger.info(self.vapi.cli("show nat44 interface address"))
4919 self.logger.info(self.vapi.cli("show nat44 sessions detail"))
Matus Fabian229c1aa2018-05-28 04:09:52 -07004920 self.logger.info(self.vapi.cli("show nat44 hash tables detail"))
Matus Fabian2ba92e32017-08-21 07:05:03 -07004921 self.clear_nat44()
Matus Fabian229c1aa2018-05-28 04:09:52 -07004922 self.vapi.cli("clear logging")
Matus Fabiande886752016-12-07 03:38:19 -08004923
Matus Fabianeea28d72017-01-13 04:15:54 -08004924
Juraj Slobodacba69362017-12-19 02:09:32 +01004925class TestNAT44Out2InDPO(MethodHolder):
4926 """ NAT44 Test Cases using out2in DPO """
4927
4928 @classmethod
4929 def setUpConstants(cls):
4930 super(TestNAT44Out2InDPO, cls).setUpConstants()
4931 cls.vpp_cmdline.extend(["nat", "{", "out2in dpo", "}"])
4932
4933 @classmethod
4934 def setUpClass(cls):
4935 super(TestNAT44Out2InDPO, cls).setUpClass()
Matus Fabian229c1aa2018-05-28 04:09:52 -07004936 cls.vapi.cli("set log class nat level debug")
Juraj Slobodacba69362017-12-19 02:09:32 +01004937
4938 try:
4939 cls.tcp_port_in = 6303
4940 cls.tcp_port_out = 6303
4941 cls.udp_port_in = 6304
4942 cls.udp_port_out = 6304
4943 cls.icmp_id_in = 6305
4944 cls.icmp_id_out = 6305
4945 cls.nat_addr = '10.0.0.3'
4946 cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
4947 cls.dst_ip4 = '192.168.70.1'
4948
4949 cls.create_pg_interfaces(range(2))
4950
4951 cls.pg0.admin_up()
4952 cls.pg0.config_ip4()
4953 cls.pg0.resolve_arp()
4954
4955 cls.pg1.admin_up()
4956 cls.pg1.config_ip6()
4957 cls.pg1.resolve_ndp()
4958
4959 cls.vapi.ip_add_del_route(is_ipv6=True, dst_address='\x00'*16,
4960 dst_address_length=0,
4961 next_hop_address=cls.pg1.remote_ip6n,
4962 next_hop_sw_if_index=cls.pg1.sw_if_index)
4963
4964 except Exception:
4965 super(TestNAT44Out2InDPO, cls).tearDownClass()
4966 raise
4967
4968 def configure_xlat(self):
4969 self.dst_ip6_pfx = '1:2:3::'
4970 self.dst_ip6_pfx_n = socket.inet_pton(socket.AF_INET6,
4971 self.dst_ip6_pfx)
4972 self.dst_ip6_pfx_len = 96
4973 self.src_ip6_pfx = '4:5:6::'
4974 self.src_ip6_pfx_n = socket.inet_pton(socket.AF_INET6,
4975 self.src_ip6_pfx)
4976 self.src_ip6_pfx_len = 96
4977 self.vapi.map_add_domain(self.dst_ip6_pfx_n, self.dst_ip6_pfx_len,
4978 self.src_ip6_pfx_n, self.src_ip6_pfx_len,
4979 '\x00\x00\x00\x00', 0, is_translation=1,
4980 is_rfc6052=1)
4981
4982 def test_464xlat_ce(self):
4983 """ Test 464XLAT CE with NAT44 """
4984
Matus Fabian69ce30d2018-08-22 01:27:10 -07004985 nat_config = self.vapi.nat_show_config()
4986 self.assertEqual(1, nat_config.out2in_dpo)
4987
Juraj Slobodacba69362017-12-19 02:09:32 +01004988 self.configure_xlat()
4989
4990 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4991 self.vapi.nat44_add_del_address_range(self.nat_addr_n, self.nat_addr_n)
4992
4993 out_src_ip6 = self.compose_ip6(self.dst_ip4, self.dst_ip6_pfx,
4994 self.dst_ip6_pfx_len)
4995 out_dst_ip6 = self.compose_ip6(self.nat_addr, self.src_ip6_pfx,
4996 self.src_ip6_pfx_len)
4997
4998 try:
4999 pkts = self.create_stream_in(self.pg0, self.pg1, self.dst_ip4)
5000 self.pg0.add_stream(pkts)
5001 self.pg_enable_capture(self.pg_interfaces)
5002 self.pg_start()
5003 capture = self.pg1.get_capture(len(pkts))
5004 self.verify_capture_out_ip6(capture, nat_ip=out_dst_ip6,
5005 dst_ip=out_src_ip6)
5006
5007 pkts = self.create_stream_out_ip6(self.pg1, out_src_ip6,
5008 out_dst_ip6)
5009 self.pg1.add_stream(pkts)
5010 self.pg_enable_capture(self.pg_interfaces)
5011 self.pg_start()
5012 capture = self.pg0.get_capture(len(pkts))
5013 self.verify_capture_in(capture, self.pg0)
5014 finally:
5015 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
5016 is_add=0)
5017 self.vapi.nat44_add_del_address_range(self.nat_addr_n,
5018 self.nat_addr_n, is_add=0)
5019
5020 def test_464xlat_ce_no_nat(self):
5021 """ Test 464XLAT CE without NAT44 """
5022
5023 self.configure_xlat()
5024
5025 out_src_ip6 = self.compose_ip6(self.dst_ip4, self.dst_ip6_pfx,
5026 self.dst_ip6_pfx_len)
5027 out_dst_ip6 = self.compose_ip6(self.pg0.remote_ip4, self.src_ip6_pfx,
5028 self.src_ip6_pfx_len)
5029
5030 pkts = self.create_stream_in(self.pg0, self.pg1, self.dst_ip4)
5031 self.pg0.add_stream(pkts)
5032 self.pg_enable_capture(self.pg_interfaces)
5033 self.pg_start()
5034 capture = self.pg1.get_capture(len(pkts))
5035 self.verify_capture_out_ip6(capture, dst_ip=out_src_ip6,
5036 nat_ip=out_dst_ip6, same_port=True)
5037
5038 pkts = self.create_stream_out_ip6(self.pg1, out_src_ip6, out_dst_ip6)
5039 self.pg1.add_stream(pkts)
5040 self.pg_enable_capture(self.pg_interfaces)
5041 self.pg_start()
5042 capture = self.pg0.get_capture(len(pkts))
5043 self.verify_capture_in(capture, self.pg0)
5044
5045
Martin Gálikd7f75cd2017-03-27 06:02:47 -07005046class TestDeterministicNAT(MethodHolder):
Matus Fabian066f0342017-02-10 03:48:01 -08005047 """ Deterministic NAT Test Cases """
5048
5049 @classmethod
5050 def setUpConstants(cls):
5051 super(TestDeterministicNAT, cls).setUpConstants()
Matus Fabian2ba92e32017-08-21 07:05:03 -07005052 cls.vpp_cmdline.extend(["nat", "{", "deterministic", "}"])
Matus Fabian066f0342017-02-10 03:48:01 -08005053
5054 @classmethod
5055 def setUpClass(cls):
5056 super(TestDeterministicNAT, cls).setUpClass()
Matus Fabian229c1aa2018-05-28 04:09:52 -07005057 cls.vapi.cli("set log class nat level debug")
Matus Fabian066f0342017-02-10 03:48:01 -08005058
5059 try:
Martin Gálik977c1cb2017-03-30 23:21:51 -07005060 cls.tcp_port_in = 6303
Martin Gálik9806eae2017-04-25 01:25:08 -07005061 cls.tcp_external_port = 6303
Martin Gálik977c1cb2017-03-30 23:21:51 -07005062 cls.udp_port_in = 6304
Martin Gálik9806eae2017-04-25 01:25:08 -07005063 cls.udp_external_port = 6304
Martin Gálik977c1cb2017-03-30 23:21:51 -07005064 cls.icmp_id_in = 6305
Matus Fabian2ba92e32017-08-21 07:05:03 -07005065 cls.nat_addr = '10.0.0.3'
Martin Gálik977c1cb2017-03-30 23:21:51 -07005066
Matus Fabian2f2db1c2017-04-18 05:29:59 -07005067 cls.create_pg_interfaces(range(3))
Matus Fabian066f0342017-02-10 03:48:01 -08005068 cls.interfaces = list(cls.pg_interfaces)
5069
5070 for i in cls.interfaces:
5071 i.admin_up()
5072 i.config_ip4()
5073 i.resolve_arp()
5074
Martin Gálik977c1cb2017-03-30 23:21:51 -07005075 cls.pg0.generate_remote_hosts(2)
5076 cls.pg0.configure_ipv4_neighbors()
5077
Matus Fabian066f0342017-02-10 03:48:01 -08005078 except Exception:
5079 super(TestDeterministicNAT, cls).tearDownClass()
5080 raise
5081
Martin Gálik977c1cb2017-03-30 23:21:51 -07005082 def create_stream_in(self, in_if, out_if, ttl=64):
5083 """
5084 Create packet stream for inside network
5085
5086 :param in_if: Inside interface
5087 :param out_if: Outside interface
5088 :param ttl: TTL of generated packets
5089 """
5090 pkts = []
5091 # TCP
5092 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
5093 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
Martin Gálik9806eae2017-04-25 01:25:08 -07005094 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07005095 pkts.append(p)
5096
5097 # UDP
5098 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
5099 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
Martin Gálik9806eae2017-04-25 01:25:08 -07005100 UDP(sport=self.udp_port_in, dport=self.udp_external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07005101 pkts.append(p)
5102
5103 # ICMP
5104 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
5105 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
5106 ICMP(id=self.icmp_id_in, type='echo-request'))
5107 pkts.append(p)
5108
5109 return pkts
5110
5111 def create_stream_out(self, out_if, dst_ip=None, ttl=64):
5112 """
5113 Create packet stream for outside network
5114
5115 :param out_if: Outside interface
Matus Fabian2ba92e32017-08-21 07:05:03 -07005116 :param dst_ip: Destination IP address (Default use global NAT address)
Martin Gálik977c1cb2017-03-30 23:21:51 -07005117 :param ttl: TTL of generated packets
5118 """
5119 if dst_ip is None:
Matus Fabian2ba92e32017-08-21 07:05:03 -07005120 dst_ip = self.nat_addr
Martin Gálik977c1cb2017-03-30 23:21:51 -07005121 pkts = []
5122 # TCP
5123 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
5124 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Martin Gálik9806eae2017-04-25 01:25:08 -07005125 TCP(dport=self.tcp_port_out, sport=self.tcp_external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07005126 pkts.append(p)
5127
5128 # UDP
5129 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
5130 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Martin Gálik9806eae2017-04-25 01:25:08 -07005131 UDP(dport=self.udp_port_out, sport=self.udp_external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07005132 pkts.append(p)
5133
5134 # ICMP
5135 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
5136 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
5137 ICMP(id=self.icmp_external_id, type='echo-reply'))
5138 pkts.append(p)
5139
5140 return pkts
5141
5142 def verify_capture_out(self, capture, nat_ip=None, packet_num=3):
5143 """
5144 Verify captured packets on outside network
5145
5146 :param capture: Captured packets
Matus Fabian2ba92e32017-08-21 07:05:03 -07005147 :param nat_ip: Translated IP address (Default use global NAT address)
Martin Gálik977c1cb2017-03-30 23:21:51 -07005148 :param same_port: Sorce port number is not translated (Default False)
5149 :param packet_num: Expected number of packets (Default 3)
5150 """
5151 if nat_ip is None:
Matus Fabian2ba92e32017-08-21 07:05:03 -07005152 nat_ip = self.nat_addr
Martin Gálik977c1cb2017-03-30 23:21:51 -07005153 self.assertEqual(packet_num, len(capture))
5154 for packet in capture:
5155 try:
5156 self.assertEqual(packet[IP].src, nat_ip)
5157 if packet.haslayer(TCP):
Martin Gálik9806eae2017-04-25 01:25:08 -07005158 self.tcp_port_out = packet[TCP].sport
Martin Gálik977c1cb2017-03-30 23:21:51 -07005159 elif packet.haslayer(UDP):
Martin Gálik9806eae2017-04-25 01:25:08 -07005160 self.udp_port_out = packet[UDP].sport
Martin Gálik977c1cb2017-03-30 23:21:51 -07005161 else:
5162 self.icmp_external_id = packet[ICMP].id
5163 except:
5164 self.logger.error(ppp("Unexpected or invalid packet "
5165 "(outside network):", packet))
5166 raise
5167
Matus Fabian2f2db1c2017-04-18 05:29:59 -07005168 def verify_ipfix_max_entries_per_user(self, data):
5169 """
5170 Verify IPFIX maximum entries per user exceeded event
5171
5172 :param data: Decoded IPFIX data records
5173 """
5174 self.assertEqual(1, len(data))
5175 record = data[0]
5176 # natEvent
5177 self.assertEqual(ord(record[230]), 13)
5178 # natQuotaExceededEvent
5179 self.assertEqual('\x03\x00\x00\x00', record[466])
Matus Fabiana431ad12018-01-04 04:03:14 -08005180 # maxEntriesPerUser
5181 self.assertEqual('\xe8\x03\x00\x00', record[473])
Matus Fabian2f2db1c2017-04-18 05:29:59 -07005182 # sourceIPv4Address
5183 self.assertEqual(self.pg0.remote_ip4n, record[8])
5184
Matus Fabian066f0342017-02-10 03:48:01 -08005185 def test_deterministic_mode(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07005186 """ NAT plugin run deterministic mode """
Matus Fabian066f0342017-02-10 03:48:01 -08005187 in_addr = '172.16.255.0'
5188 out_addr = '172.17.255.50'
5189 in_addr_t = '172.16.255.20'
5190 in_addr_n = socket.inet_aton(in_addr)
5191 out_addr_n = socket.inet_aton(out_addr)
5192 in_addr_t_n = socket.inet_aton(in_addr_t)
5193 in_plen = 24
5194 out_plen = 32
5195
Matus Fabian2ba92e32017-08-21 07:05:03 -07005196 nat_config = self.vapi.nat_show_config()
5197 self.assertEqual(1, nat_config.deterministic)
Matus Fabian066f0342017-02-10 03:48:01 -08005198
Matus Fabian2ba92e32017-08-21 07:05:03 -07005199 self.vapi.nat_det_add_del_map(in_addr_n, in_plen, out_addr_n, out_plen)
Matus Fabian066f0342017-02-10 03:48:01 -08005200
Matus Fabian2ba92e32017-08-21 07:05:03 -07005201 rep1 = self.vapi.nat_det_forward(in_addr_t_n)
Matus Fabian066f0342017-02-10 03:48:01 -08005202 self.assertEqual(rep1.out_addr[:4], out_addr_n)
Matus Fabian2ba92e32017-08-21 07:05:03 -07005203 rep2 = self.vapi.nat_det_reverse(out_addr_n, rep1.out_port_hi)
Matus Fabian066f0342017-02-10 03:48:01 -08005204 self.assertEqual(rep2.in_addr[:4], in_addr_t_n)
5205
Matus Fabian2ba92e32017-08-21 07:05:03 -07005206 deterministic_mappings = self.vapi.nat_det_map_dump()
Martin17a75cb2017-03-08 05:53:20 -08005207 self.assertEqual(len(deterministic_mappings), 1)
5208 dsm = deterministic_mappings[0]
5209 self.assertEqual(in_addr_n, dsm.in_addr[:4])
5210 self.assertEqual(in_plen, dsm.in_plen)
5211 self.assertEqual(out_addr_n, dsm.out_addr[:4])
5212 self.assertEqual(out_plen, dsm.out_plen)
5213
Matus Fabian2ba92e32017-08-21 07:05:03 -07005214 self.clear_nat_det()
5215 deterministic_mappings = self.vapi.nat_det_map_dump()
Martinb616e9f2017-03-14 02:25:45 -07005216 self.assertEqual(len(deterministic_mappings), 0)
5217
Matus Fabian6a0946f2017-04-12 03:36:13 -07005218 def test_set_timeouts(self):
5219 """ Set deterministic NAT timeouts """
Matus Fabian2ba92e32017-08-21 07:05:03 -07005220 timeouts_before = self.vapi.nat_det_get_timeouts()
Matus Fabian6a0946f2017-04-12 03:36:13 -07005221
Matus Fabian2ba92e32017-08-21 07:05:03 -07005222 self.vapi.nat_det_set_timeouts(timeouts_before.udp + 10,
5223 timeouts_before.tcp_established + 10,
5224 timeouts_before.tcp_transitory + 10,
5225 timeouts_before.icmp + 10)
Matus Fabian6a0946f2017-04-12 03:36:13 -07005226
Matus Fabian2ba92e32017-08-21 07:05:03 -07005227 timeouts_after = self.vapi.nat_det_get_timeouts()
Matus Fabian6a0946f2017-04-12 03:36:13 -07005228
5229 self.assertNotEqual(timeouts_before.udp, timeouts_after.udp)
5230 self.assertNotEqual(timeouts_before.icmp, timeouts_after.icmp)
5231 self.assertNotEqual(timeouts_before.tcp_established,
5232 timeouts_after.tcp_established)
5233 self.assertNotEqual(timeouts_before.tcp_transitory,
5234 timeouts_after.tcp_transitory)
5235
Martin Gálik977c1cb2017-03-30 23:21:51 -07005236 def test_det_in(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07005237 """ Deterministic NAT translation test (TCP, UDP, ICMP) """
Martin Gálik977c1cb2017-03-30 23:21:51 -07005238
5239 nat_ip = "10.0.0.10"
Martin Gálik977c1cb2017-03-30 23:21:51 -07005240
Matus Fabian2ba92e32017-08-21 07:05:03 -07005241 self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
5242 32,
5243 socket.inet_aton(nat_ip),
5244 32)
5245 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5246 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
5247 is_inside=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07005248
5249 # in2out
5250 pkts = self.create_stream_in(self.pg0, self.pg1)
5251 self.pg0.add_stream(pkts)
5252 self.pg_enable_capture(self.pg_interfaces)
5253 self.pg_start()
5254 capture = self.pg1.get_capture(len(pkts))
5255 self.verify_capture_out(capture, nat_ip)
5256
5257 # out2in
5258 pkts = self.create_stream_out(self.pg1, nat_ip)
5259 self.pg1.add_stream(pkts)
5260 self.pg_enable_capture(self.pg_interfaces)
5261 self.pg_start()
5262 capture = self.pg0.get_capture(len(pkts))
5263 self.verify_capture_in(capture, self.pg0)
5264
Martin Gálik9806eae2017-04-25 01:25:08 -07005265 # session dump test
Matus Fabian2ba92e32017-08-21 07:05:03 -07005266 sessions = self.vapi.nat_det_session_dump(self.pg0.remote_ip4n)
Martin Gálik9806eae2017-04-25 01:25:08 -07005267 self.assertEqual(len(sessions), 3)
5268
5269 # TCP session
5270 s = sessions[0]
5271 self.assertEqual(s.ext_addr[:4], self.pg1.remote_ip4n)
5272 self.assertEqual(s.in_port, self.tcp_port_in)
5273 self.assertEqual(s.out_port, self.tcp_port_out)
5274 self.assertEqual(s.ext_port, self.tcp_external_port)
5275
5276 # UDP session
5277 s = sessions[1]
5278 self.assertEqual(s.ext_addr[:4], self.pg1.remote_ip4n)
5279 self.assertEqual(s.in_port, self.udp_port_in)
5280 self.assertEqual(s.out_port, self.udp_port_out)
5281 self.assertEqual(s.ext_port, self.udp_external_port)
5282
5283 # ICMP session
5284 s = sessions[2]
5285 self.assertEqual(s.ext_addr[:4], self.pg1.remote_ip4n)
5286 self.assertEqual(s.in_port, self.icmp_id_in)
5287 self.assertEqual(s.out_port, self.icmp_external_id)
5288
Martin Gálik977c1cb2017-03-30 23:21:51 -07005289 def test_multiple_users(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07005290 """ Deterministic NAT multiple users """
Martin Gálik977c1cb2017-03-30 23:21:51 -07005291
5292 nat_ip = "10.0.0.10"
5293 port_in = 80
Martin Gálik9806eae2017-04-25 01:25:08 -07005294 external_port = 6303
Martin Gálik977c1cb2017-03-30 23:21:51 -07005295
5296 host0 = self.pg0.remote_hosts[0]
5297 host1 = self.pg0.remote_hosts[1]
5298
Matus Fabian2ba92e32017-08-21 07:05:03 -07005299 self.vapi.nat_det_add_del_map(host0.ip4n,
5300 24,
5301 socket.inet_aton(nat_ip),
5302 32)
5303 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5304 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
5305 is_inside=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07005306
5307 # host0 to out
5308 p = (Ether(src=host0.mac, dst=self.pg0.local_mac) /
5309 IP(src=host0.ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07005310 TCP(sport=port_in, dport=external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07005311 self.pg0.add_stream(p)
5312 self.pg_enable_capture(self.pg_interfaces)
5313 self.pg_start()
5314 capture = self.pg1.get_capture(1)
5315 p = capture[0]
5316 try:
5317 ip = p[IP]
5318 tcp = p[TCP]
5319 self.assertEqual(ip.src, nat_ip)
5320 self.assertEqual(ip.dst, self.pg1.remote_ip4)
Martin Gálik9806eae2017-04-25 01:25:08 -07005321 self.assertEqual(tcp.dport, external_port)
5322 port_out0 = tcp.sport
Martin Gálik977c1cb2017-03-30 23:21:51 -07005323 except:
5324 self.logger.error(ppp("Unexpected or invalid packet:", p))
5325 raise
5326
5327 # host1 to out
5328 p = (Ether(src=host1.mac, dst=self.pg0.local_mac) /
5329 IP(src=host1.ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07005330 TCP(sport=port_in, dport=external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07005331 self.pg0.add_stream(p)
5332 self.pg_enable_capture(self.pg_interfaces)
5333 self.pg_start()
5334 capture = self.pg1.get_capture(1)
5335 p = capture[0]
5336 try:
5337 ip = p[IP]
5338 tcp = p[TCP]
5339 self.assertEqual(ip.src, nat_ip)
5340 self.assertEqual(ip.dst, self.pg1.remote_ip4)
Martin Gálik9806eae2017-04-25 01:25:08 -07005341 self.assertEqual(tcp.dport, external_port)
5342 port_out1 = tcp.sport
Martin Gálik977c1cb2017-03-30 23:21:51 -07005343 except:
5344 self.logger.error(ppp("Unexpected or invalid packet:", p))
5345 raise
5346
Matus Fabian2ba92e32017-08-21 07:05:03 -07005347 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07005348 self.assertEqual(1, len(dms))
5349 self.assertEqual(2, dms[0].ses_num)
5350
5351 # out to host0
5352 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5353 IP(src=self.pg1.remote_ip4, dst=nat_ip) /
Martin Gálik9806eae2017-04-25 01:25:08 -07005354 TCP(sport=external_port, dport=port_out0))
Martin Gálik977c1cb2017-03-30 23:21:51 -07005355 self.pg1.add_stream(p)
5356 self.pg_enable_capture(self.pg_interfaces)
5357 self.pg_start()
5358 capture = self.pg0.get_capture(1)
5359 p = capture[0]
5360 try:
5361 ip = p[IP]
5362 tcp = p[TCP]
5363 self.assertEqual(ip.src, self.pg1.remote_ip4)
5364 self.assertEqual(ip.dst, host0.ip4)
5365 self.assertEqual(tcp.dport, port_in)
Martin Gálik9806eae2017-04-25 01:25:08 -07005366 self.assertEqual(tcp.sport, external_port)
Martin Gálik977c1cb2017-03-30 23:21:51 -07005367 except:
5368 self.logger.error(ppp("Unexpected or invalid packet:", p))
5369 raise
5370
5371 # out to host1
5372 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5373 IP(src=self.pg1.remote_ip4, dst=nat_ip) /
Martin Gálik9806eae2017-04-25 01:25:08 -07005374 TCP(sport=external_port, dport=port_out1))
Martin Gálik977c1cb2017-03-30 23:21:51 -07005375 self.pg1.add_stream(p)
5376 self.pg_enable_capture(self.pg_interfaces)
5377 self.pg_start()
5378 capture = self.pg0.get_capture(1)
5379 p = capture[0]
5380 try:
5381 ip = p[IP]
5382 tcp = p[TCP]
5383 self.assertEqual(ip.src, self.pg1.remote_ip4)
5384 self.assertEqual(ip.dst, host1.ip4)
5385 self.assertEqual(tcp.dport, port_in)
Martin Gálik9806eae2017-04-25 01:25:08 -07005386 self.assertEqual(tcp.sport, external_port)
Martin Gálik977c1cb2017-03-30 23:21:51 -07005387 except:
5388 self.logger.error(ppp("Unexpected or invalid packet", p))
5389 raise
5390
Martin Gálik6bc8c642017-04-19 01:12:27 -07005391 # session close api test
Matus Fabian2ba92e32017-08-21 07:05:03 -07005392 self.vapi.nat_det_close_session_out(socket.inet_aton(nat_ip),
5393 port_out1,
Martin Gálik6bc8c642017-04-19 01:12:27 -07005394 self.pg1.remote_ip4n,
Martin Gálik9806eae2017-04-25 01:25:08 -07005395 external_port)
Matus Fabian2ba92e32017-08-21 07:05:03 -07005396 dms = self.vapi.nat_det_map_dump()
5397 self.assertEqual(dms[0].ses_num, 1)
5398
5399 self.vapi.nat_det_close_session_in(host0.ip4n,
5400 port_in,
5401 self.pg1.remote_ip4n,
5402 external_port)
5403 dms = self.vapi.nat_det_map_dump()
Martin Gálik6bc8c642017-04-19 01:12:27 -07005404 self.assertEqual(dms[0].ses_num, 0)
5405
Martin Gálik977c1cb2017-03-30 23:21:51 -07005406 def test_tcp_session_close_detection_in(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07005407 """ Deterministic NAT TCP session close from inside network """
5408 self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
5409 32,
5410 socket.inet_aton(self.nat_addr),
5411 32)
5412 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5413 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
5414 is_inside=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07005415
5416 self.initiate_tcp_session(self.pg0, self.pg1)
5417
5418 # close the session from inside
5419 try:
5420 # FIN packet in -> out
5421 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5422 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07005423 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
Martin Gálik977c1cb2017-03-30 23:21:51 -07005424 flags="F"))
5425 self.pg0.add_stream(p)
5426 self.pg_enable_capture(self.pg_interfaces)
5427 self.pg_start()
5428 self.pg1.get_capture(1)
5429
5430 pkts = []
5431
5432 # ACK packet out -> in
5433 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07005434 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Martin Gálik9806eae2017-04-25 01:25:08 -07005435 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
Martin Gálik977c1cb2017-03-30 23:21:51 -07005436 flags="A"))
5437 pkts.append(p)
5438
5439 # FIN packet out -> in
5440 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07005441 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Martin Gálik9806eae2017-04-25 01:25:08 -07005442 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
Martin Gálik977c1cb2017-03-30 23:21:51 -07005443 flags="F"))
5444 pkts.append(p)
5445
5446 self.pg1.add_stream(pkts)
5447 self.pg_enable_capture(self.pg_interfaces)
5448 self.pg_start()
5449 self.pg0.get_capture(2)
5450
5451 # ACK packet in -> out
5452 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5453 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07005454 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
Martin Gálik977c1cb2017-03-30 23:21:51 -07005455 flags="A"))
5456 self.pg0.add_stream(p)
5457 self.pg_enable_capture(self.pg_interfaces)
5458 self.pg_start()
5459 self.pg1.get_capture(1)
5460
Matus Fabian2ba92e32017-08-21 07:05:03 -07005461 # Check if deterministic NAT44 closed the session
5462 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07005463 self.assertEqual(0, dms[0].ses_num)
5464 except:
5465 self.logger.error("TCP session termination failed")
5466 raise
5467
5468 def test_tcp_session_close_detection_out(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07005469 """ Deterministic NAT TCP session close from outside network """
5470 self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
5471 32,
5472 socket.inet_aton(self.nat_addr),
5473 32)
5474 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5475 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
5476 is_inside=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07005477
5478 self.initiate_tcp_session(self.pg0, self.pg1)
5479
5480 # close the session from outside
5481 try:
5482 # FIN packet out -> in
5483 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07005484 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Martin Gálik9806eae2017-04-25 01:25:08 -07005485 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
Martin Gálik977c1cb2017-03-30 23:21:51 -07005486 flags="F"))
5487 self.pg1.add_stream(p)
5488 self.pg_enable_capture(self.pg_interfaces)
5489 self.pg_start()
5490 self.pg0.get_capture(1)
5491
5492 pkts = []
5493
5494 # ACK packet in -> out
5495 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5496 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07005497 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
Martin Gálik977c1cb2017-03-30 23:21:51 -07005498 flags="A"))
5499 pkts.append(p)
5500
5501 # ACK packet in -> out
5502 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5503 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07005504 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
Martin Gálik977c1cb2017-03-30 23:21:51 -07005505 flags="F"))
5506 pkts.append(p)
5507
5508 self.pg0.add_stream(pkts)
5509 self.pg_enable_capture(self.pg_interfaces)
5510 self.pg_start()
5511 self.pg1.get_capture(2)
5512
5513 # ACK packet out -> in
5514 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07005515 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Martin Gálik9806eae2017-04-25 01:25:08 -07005516 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
Martin Gálik977c1cb2017-03-30 23:21:51 -07005517 flags="A"))
5518 self.pg1.add_stream(p)
5519 self.pg_enable_capture(self.pg_interfaces)
5520 self.pg_start()
5521 self.pg0.get_capture(1)
5522
Matus Fabian2ba92e32017-08-21 07:05:03 -07005523 # Check if deterministic NAT44 closed the session
5524 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07005525 self.assertEqual(0, dms[0].ses_num)
5526 except:
5527 self.logger.error("TCP session termination failed")
5528 raise
5529
5530 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
5531 def test_session_timeout(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07005532 """ Deterministic NAT session timeouts """
5533 self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
5534 32,
5535 socket.inet_aton(self.nat_addr),
5536 32)
5537 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5538 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
5539 is_inside=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07005540
5541 self.initiate_tcp_session(self.pg0, self.pg1)
Matus Fabian2ba92e32017-08-21 07:05:03 -07005542 self.vapi.nat_det_set_timeouts(5, 5, 5, 5)
Martin Gálik977c1cb2017-03-30 23:21:51 -07005543 pkts = self.create_stream_in(self.pg0, self.pg1)
5544 self.pg0.add_stream(pkts)
5545 self.pg_enable_capture(self.pg_interfaces)
5546 self.pg_start()
5547 capture = self.pg1.get_capture(len(pkts))
5548 sleep(15)
5549
Matus Fabian2ba92e32017-08-21 07:05:03 -07005550 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07005551 self.assertEqual(0, dms[0].ses_num)
5552
Matus Fabian7c0aecc2017-07-03 01:21:38 -07005553 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
Martin Gálik977c1cb2017-03-30 23:21:51 -07005554 def test_session_limit_per_user(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07005555 """ Deterministic NAT maximum sessions per user limit """
5556 self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
5557 32,
5558 socket.inet_aton(self.nat_addr),
5559 32)
5560 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5561 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
5562 is_inside=0)
Matus Fabian2f2db1c2017-04-18 05:29:59 -07005563 self.vapi.set_ipfix_exporter(collector_address=self.pg2.remote_ip4n,
5564 src_address=self.pg2.local_ip4n,
5565 path_mtu=512,
5566 template_interval=10)
Matus Fabian2ba92e32017-08-21 07:05:03 -07005567 self.vapi.nat_ipfix()
Martin Gálik977c1cb2017-03-30 23:21:51 -07005568
5569 pkts = []
5570 for port in range(1025, 2025):
5571 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5572 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5573 UDP(sport=port, dport=port))
5574 pkts.append(p)
5575
5576 self.pg0.add_stream(pkts)
5577 self.pg_enable_capture(self.pg_interfaces)
5578 self.pg_start()
5579 capture = self.pg1.get_capture(len(pkts))
5580
5581 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5582 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálikf7e655d2017-04-27 02:13:26 -07005583 UDP(sport=3001, dport=3002))
Martin Gálik977c1cb2017-03-30 23:21:51 -07005584 self.pg0.add_stream(p)
5585 self.pg_enable_capture(self.pg_interfaces)
5586 self.pg_start()
5587 capture = self.pg1.assert_nothing_captured()
5588
Martin Gálikf7e655d2017-04-27 02:13:26 -07005589 # verify ICMP error packet
5590 capture = self.pg0.get_capture(1)
5591 p = capture[0]
5592 self.assertTrue(p.haslayer(ICMP))
5593 icmp = p[ICMP]
5594 self.assertEqual(icmp.type, 3)
5595 self.assertEqual(icmp.code, 1)
5596 self.assertTrue(icmp.haslayer(IPerror))
5597 inner_ip = icmp[IPerror]
5598 self.assertEqual(inner_ip[UDPerror].sport, 3001)
5599 self.assertEqual(inner_ip[UDPerror].dport, 3002)
5600
Matus Fabian2ba92e32017-08-21 07:05:03 -07005601 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07005602
5603 self.assertEqual(1000, dms[0].ses_num)
5604
Matus Fabian2f2db1c2017-04-18 05:29:59 -07005605 # verify IPFIX logging
5606 self.vapi.cli("ipfix flush") # FIXME this should be an API call
Matus Fabian7c0aecc2017-07-03 01:21:38 -07005607 sleep(1)
Matus Fabian2f2db1c2017-04-18 05:29:59 -07005608 capture = self.pg2.get_capture(2)
5609 ipfix = IPFIXDecoder()
5610 # first load template
5611 for p in capture:
5612 self.assertTrue(p.haslayer(IPFIX))
5613 if p.haslayer(Template):
5614 ipfix.add_template(p.getlayer(Template))
5615 # verify events in data set
5616 for p in capture:
5617 if p.haslayer(Data):
5618 data = ipfix.decode_data_set(p.getlayer(Set))
5619 self.verify_ipfix_max_entries_per_user(data)
5620
Matus Fabian2ba92e32017-08-21 07:05:03 -07005621 def clear_nat_det(self):
Martin17a75cb2017-03-08 05:53:20 -08005622 """
Matus Fabian2ba92e32017-08-21 07:05:03 -07005623 Clear deterministic NAT configuration.
Martin17a75cb2017-03-08 05:53:20 -08005624 """
Matus Fabian2ba92e32017-08-21 07:05:03 -07005625 self.vapi.nat_ipfix(enable=0)
5626 self.vapi.nat_det_set_timeouts()
5627 deterministic_mappings = self.vapi.nat_det_map_dump()
Martin17a75cb2017-03-08 05:53:20 -08005628 for dsm in deterministic_mappings:
Matus Fabian2ba92e32017-08-21 07:05:03 -07005629 self.vapi.nat_det_add_del_map(dsm.in_addr,
5630 dsm.in_plen,
5631 dsm.out_addr,
5632 dsm.out_plen,
5633 is_add=0)
Martin17a75cb2017-03-08 05:53:20 -08005634
Matus Fabian2ba92e32017-08-21 07:05:03 -07005635 interfaces = self.vapi.nat44_interface_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07005636 for intf in interfaces:
Matus Fabian2ba92e32017-08-21 07:05:03 -07005637 self.vapi.nat44_interface_add_del_feature(intf.sw_if_index,
5638 intf.is_inside,
5639 is_add=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07005640
Matus Fabian066f0342017-02-10 03:48:01 -08005641 def tearDown(self):
5642 super(TestDeterministicNAT, self).tearDown()
5643 if not self.vpp_dead:
Matus Fabian82119542018-01-25 01:13:22 -08005644 self.logger.info(self.vapi.cli("show nat44 interfaces"))
5645 self.logger.info(
5646 self.vapi.cli("show nat44 deterministic mappings"))
5647 self.logger.info(
5648 self.vapi.cli("show nat44 deterministic timeouts"))
5649 self.logger.info(
5650 self.vapi.cli("show nat44 deterministic sessions"))
Matus Fabian2ba92e32017-08-21 07:05:03 -07005651 self.clear_nat_det()
Matus Fabian066f0342017-02-10 03:48:01 -08005652
Matus Fabian06596c52017-06-06 04:53:28 -07005653
5654class TestNAT64(MethodHolder):
5655 """ NAT64 Test Cases """
5656
5657 @classmethod
Matus Fabiana431ad12018-01-04 04:03:14 -08005658 def setUpConstants(cls):
5659 super(TestNAT64, cls).setUpConstants()
5660 cls.vpp_cmdline.extend(["nat", "{", "nat64 bib hash buckets 128",
5661 "nat64 st hash buckets 256", "}"])
5662
5663 @classmethod
Matus Fabian06596c52017-06-06 04:53:28 -07005664 def setUpClass(cls):
5665 super(TestNAT64, cls).setUpClass()
5666
5667 try:
5668 cls.tcp_port_in = 6303
5669 cls.tcp_port_out = 6303
5670 cls.udp_port_in = 6304
5671 cls.udp_port_out = 6304
5672 cls.icmp_id_in = 6305
5673 cls.icmp_id_out = 6305
5674 cls.nat_addr = '10.0.0.3'
5675 cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
Matus Fabian029f3d22017-06-15 02:28:50 -07005676 cls.vrf1_id = 10
5677 cls.vrf1_nat_addr = '10.0.10.3'
5678 cls.vrf1_nat_addr_n = socket.inet_pton(socket.AF_INET,
5679 cls.vrf1_nat_addr)
Matus Fabiana431ad12018-01-04 04:03:14 -08005680 cls.ipfix_src_port = 4739
5681 cls.ipfix_domain_id = 1
Matus Fabian06596c52017-06-06 04:53:28 -07005682
Juraj Slobodac746a152018-07-09 02:36:37 +02005683 cls.create_pg_interfaces(range(6))
Matus Fabian06596c52017-06-06 04:53:28 -07005684 cls.ip6_interfaces = list(cls.pg_interfaces[0:1])
Matus Fabian029f3d22017-06-15 02:28:50 -07005685 cls.ip6_interfaces.append(cls.pg_interfaces[2])
Matus Fabian06596c52017-06-06 04:53:28 -07005686 cls.ip4_interfaces = list(cls.pg_interfaces[1:2])
5687
Neale Ranns15002542017-09-10 04:39:11 -07005688 cls.vapi.ip_table_add_del(cls.vrf1_id, is_add=1, is_ipv6=1)
5689
Matus Fabian029f3d22017-06-15 02:28:50 -07005690 cls.pg_interfaces[2].set_table_ip6(cls.vrf1_id)
5691
5692 cls.pg0.generate_remote_hosts(2)
5693
Matus Fabian06596c52017-06-06 04:53:28 -07005694 for i in cls.ip6_interfaces:
5695 i.admin_up()
5696 i.config_ip6()
Matus Fabian029f3d22017-06-15 02:28:50 -07005697 i.configure_ipv6_neighbors()
Matus Fabian06596c52017-06-06 04:53:28 -07005698
5699 for i in cls.ip4_interfaces:
5700 i.admin_up()
5701 i.config_ip4()
5702 i.resolve_arp()
5703
Matus Fabian36ea2d62017-10-24 04:13:49 -07005704 cls.pg3.admin_up()
5705 cls.pg3.config_ip4()
5706 cls.pg3.resolve_arp()
5707 cls.pg3.config_ip6()
5708 cls.pg3.configure_ipv6_neighbors()
5709
Juraj Slobodac746a152018-07-09 02:36:37 +02005710 cls.pg5.admin_up()
5711 cls.pg5.config_ip6()
5712
Matus Fabian06596c52017-06-06 04:53:28 -07005713 except Exception:
5714 super(TestNAT64, cls).tearDownClass()
5715 raise
5716
Juraj Slobodac746a152018-07-09 02:36:37 +02005717 def test_nat64_inside_interface_handles_neighbor_advertisement(self):
5718 """ NAT64 inside interface handles Neighbor Advertisement """
5719
5720 self.vapi.nat64_add_del_interface(self.pg5.sw_if_index)
5721
5722 # Try to send ping
5723 ping = (Ether(dst=self.pg5.local_mac, src=self.pg5.remote_mac) /
5724 IPv6(src=self.pg5.remote_ip6, dst=self.pg5.local_ip6) /
5725 ICMPv6EchoRequest())
5726 pkts = [ping]
5727 self.pg5.add_stream(pkts)
5728 self.pg_enable_capture(self.pg_interfaces)
5729 self.pg_start()
5730
5731 # Wait for Neighbor Solicitation
5732 capture = self.pg5.get_capture(len(pkts))
5733 self.assertEqual(1, len(capture))
5734 packet = capture[0]
5735 try:
5736 self.assertEqual(packet[IPv6].src, self.pg5.local_ip6)
5737 self.assertTrue(packet.haslayer(ICMPv6ND_NS))
5738 tgt = packet[ICMPv6ND_NS].tgt
5739 except:
5740 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5741 raise
5742
5743 # Send Neighbor Advertisement
5744 p = (Ether(dst=self.pg5.local_mac, src=self.pg5.remote_mac) /
5745 IPv6(src=self.pg5.remote_ip6, dst=self.pg5.local_ip6) /
5746 ICMPv6ND_NA(tgt=tgt) /
5747 ICMPv6NDOptDstLLAddr(lladdr=self.pg5.remote_mac))
5748 pkts = [p]
5749 self.pg5.add_stream(pkts)
5750 self.pg_enable_capture(self.pg_interfaces)
5751 self.pg_start()
5752
5753 # Try to send ping again
5754 pkts = [ping]
5755 self.pg5.add_stream(pkts)
5756 self.pg_enable_capture(self.pg_interfaces)
5757 self.pg_start()
5758
5759 # Wait for ping reply
5760 capture = self.pg5.get_capture(len(pkts))
5761 self.assertEqual(1, len(capture))
5762 packet = capture[0]
5763 try:
5764 self.assertEqual(packet[IPv6].src, self.pg5.local_ip6)
5765 self.assertEqual(packet[IPv6].dst, self.pg5.remote_ip6)
5766 self.assertTrue(packet.haslayer(ICMPv6EchoReply))
5767 except:
5768 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5769 raise
5770
Matus Fabian06596c52017-06-06 04:53:28 -07005771 def test_pool(self):
5772 """ Add/delete address to NAT64 pool """
5773 nat_addr = socket.inet_pton(socket.AF_INET, '1.2.3.4')
5774
5775 self.vapi.nat64_add_del_pool_addr_range(nat_addr, nat_addr)
5776
5777 addresses = self.vapi.nat64_pool_addr_dump()
5778 self.assertEqual(len(addresses), 1)
5779 self.assertEqual(addresses[0].address, nat_addr)
5780
5781 self.vapi.nat64_add_del_pool_addr_range(nat_addr, nat_addr, is_add=0)
5782
5783 addresses = self.vapi.nat64_pool_addr_dump()
5784 self.assertEqual(len(addresses), 0)
5785
5786 def test_interface(self):
5787 """ Enable/disable NAT64 feature on the interface """
5788 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
5789 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
5790
5791 interfaces = self.vapi.nat64_interface_dump()
5792 self.assertEqual(len(interfaces), 2)
5793 pg0_found = False
5794 pg1_found = False
5795 for intf in interfaces:
5796 if intf.sw_if_index == self.pg0.sw_if_index:
5797 self.assertEqual(intf.is_inside, 1)
5798 pg0_found = True
5799 elif intf.sw_if_index == self.pg1.sw_if_index:
5800 self.assertEqual(intf.is_inside, 0)
5801 pg1_found = True
5802 self.assertTrue(pg0_found)
5803 self.assertTrue(pg1_found)
5804
5805 features = self.vapi.cli("show interface features pg0")
5806 self.assertNotEqual(features.find('nat64-in2out'), -1)
5807 features = self.vapi.cli("show interface features pg1")
5808 self.assertNotEqual(features.find('nat64-out2in'), -1)
5809
5810 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index, is_add=0)
5811 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_add=0)
5812
5813 interfaces = self.vapi.nat64_interface_dump()
5814 self.assertEqual(len(interfaces), 0)
5815
5816 def test_static_bib(self):
5817 """ Add/delete static BIB entry """
5818 in_addr = socket.inet_pton(socket.AF_INET6,
5819 '2001:db8:85a3::8a2e:370:7334')
5820 out_addr = socket.inet_pton(socket.AF_INET, '10.1.1.3')
5821 in_port = 1234
5822 out_port = 5678
5823 proto = IP_PROTOS.tcp
5824
5825 self.vapi.nat64_add_del_static_bib(in_addr,
5826 out_addr,
5827 in_port,
5828 out_port,
5829 proto)
5830 bib = self.vapi.nat64_bib_dump(IP_PROTOS.tcp)
5831 static_bib_num = 0
5832 for bibe in bib:
5833 if bibe.is_static:
5834 static_bib_num += 1
5835 self.assertEqual(bibe.i_addr, in_addr)
5836 self.assertEqual(bibe.o_addr, out_addr)
5837 self.assertEqual(bibe.i_port, in_port)
5838 self.assertEqual(bibe.o_port, out_port)
5839 self.assertEqual(static_bib_num, 1)
5840
5841 self.vapi.nat64_add_del_static_bib(in_addr,
5842 out_addr,
5843 in_port,
5844 out_port,
5845 proto,
5846 is_add=0)
5847 bib = self.vapi.nat64_bib_dump(IP_PROTOS.tcp)
5848 static_bib_num = 0
5849 for bibe in bib:
5850 if bibe.is_static:
5851 static_bib_num += 1
5852 self.assertEqual(static_bib_num, 0)
5853
5854 def test_set_timeouts(self):
5855 """ Set NAT64 timeouts """
5856 # verify default values
5857 timeouts = self.vapi.nat64_get_timeouts()
5858 self.assertEqual(timeouts.udp, 300)
5859 self.assertEqual(timeouts.icmp, 60)
5860 self.assertEqual(timeouts.tcp_trans, 240)
5861 self.assertEqual(timeouts.tcp_est, 7440)
5862 self.assertEqual(timeouts.tcp_incoming_syn, 6)
5863
5864 # set and verify custom values
5865 self.vapi.nat64_set_timeouts(udp=200, icmp=30, tcp_trans=250,
5866 tcp_est=7450, tcp_incoming_syn=10)
5867 timeouts = self.vapi.nat64_get_timeouts()
5868 self.assertEqual(timeouts.udp, 200)
5869 self.assertEqual(timeouts.icmp, 30)
5870 self.assertEqual(timeouts.tcp_trans, 250)
5871 self.assertEqual(timeouts.tcp_est, 7450)
5872 self.assertEqual(timeouts.tcp_incoming_syn, 10)
5873
5874 def test_dynamic(self):
5875 """ NAT64 dynamic translation test """
5876 self.tcp_port_in = 6303
5877 self.udp_port_in = 6304
5878 self.icmp_id_in = 6305
5879
5880 ses_num_start = self.nat64_get_ses_num()
5881
5882 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
5883 self.nat_addr_n)
5884 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
5885 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
5886
5887 # in2out
5888 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
5889 self.pg0.add_stream(pkts)
5890 self.pg_enable_capture(self.pg_interfaces)
5891 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07005892 capture = self.pg1.get_capture(len(pkts))
5893 self.verify_capture_out(capture, nat_ip=self.nat_addr,
Matus Fabian06596c52017-06-06 04:53:28 -07005894 dst_ip=self.pg1.remote_ip4)
5895
5896 # out2in
5897 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
5898 self.pg1.add_stream(pkts)
5899 self.pg_enable_capture(self.pg_interfaces)
5900 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07005901 capture = self.pg0.get_capture(len(pkts))
Matus Fabian06596c52017-06-06 04:53:28 -07005902 ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
5903 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
5904
5905 # in2out
5906 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
5907 self.pg0.add_stream(pkts)
5908 self.pg_enable_capture(self.pg_interfaces)
5909 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07005910 capture = self.pg1.get_capture(len(pkts))
5911 self.verify_capture_out(capture, nat_ip=self.nat_addr,
Matus Fabian06596c52017-06-06 04:53:28 -07005912 dst_ip=self.pg1.remote_ip4)
5913
5914 # out2in
5915 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
5916 self.pg1.add_stream(pkts)
5917 self.pg_enable_capture(self.pg_interfaces)
5918 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07005919 capture = self.pg0.get_capture(len(pkts))
Matus Fabian06596c52017-06-06 04:53:28 -07005920 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
5921
5922 ses_num_end = self.nat64_get_ses_num()
5923
5924 self.assertEqual(ses_num_end - ses_num_start, 3)
5925
Matus Fabian029f3d22017-06-15 02:28:50 -07005926 # tenant with specific VRF
5927 self.vapi.nat64_add_del_pool_addr_range(self.vrf1_nat_addr_n,
5928 self.vrf1_nat_addr_n,
5929 vrf_id=self.vrf1_id)
5930 self.vapi.nat64_add_del_interface(self.pg2.sw_if_index)
5931
5932 pkts = self.create_stream_in_ip6(self.pg2, self.pg1)
5933 self.pg2.add_stream(pkts)
5934 self.pg_enable_capture(self.pg_interfaces)
5935 self.pg_start()
5936 capture = self.pg1.get_capture(len(pkts))
5937 self.verify_capture_out(capture, nat_ip=self.vrf1_nat_addr,
5938 dst_ip=self.pg1.remote_ip4)
5939
5940 pkts = self.create_stream_out(self.pg1, dst_ip=self.vrf1_nat_addr)
5941 self.pg1.add_stream(pkts)
5942 self.pg_enable_capture(self.pg_interfaces)
5943 self.pg_start()
5944 capture = self.pg2.get_capture(len(pkts))
5945 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg2.remote_ip6)
5946
Matus Fabian06596c52017-06-06 04:53:28 -07005947 def test_static(self):
5948 """ NAT64 static translation test """
5949 self.tcp_port_in = 60303
5950 self.udp_port_in = 60304
5951 self.icmp_id_in = 60305
5952 self.tcp_port_out = 60303
5953 self.udp_port_out = 60304
5954 self.icmp_id_out = 60305
5955
5956 ses_num_start = self.nat64_get_ses_num()
5957
5958 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
5959 self.nat_addr_n)
5960 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
5961 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
5962
5963 self.vapi.nat64_add_del_static_bib(self.pg0.remote_ip6n,
5964 self.nat_addr_n,
5965 self.tcp_port_in,
5966 self.tcp_port_out,
5967 IP_PROTOS.tcp)
5968 self.vapi.nat64_add_del_static_bib(self.pg0.remote_ip6n,
5969 self.nat_addr_n,
5970 self.udp_port_in,
5971 self.udp_port_out,
5972 IP_PROTOS.udp)
5973 self.vapi.nat64_add_del_static_bib(self.pg0.remote_ip6n,
5974 self.nat_addr_n,
5975 self.icmp_id_in,
5976 self.icmp_id_out,
5977 IP_PROTOS.icmp)
5978
5979 # in2out
5980 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
5981 self.pg0.add_stream(pkts)
5982 self.pg_enable_capture(self.pg_interfaces)
5983 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07005984 capture = self.pg1.get_capture(len(pkts))
5985 self.verify_capture_out(capture, nat_ip=self.nat_addr,
Matus Fabian06596c52017-06-06 04:53:28 -07005986 dst_ip=self.pg1.remote_ip4, same_port=True)
5987
5988 # out2in
5989 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
5990 self.pg1.add_stream(pkts)
5991 self.pg_enable_capture(self.pg_interfaces)
5992 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07005993 capture = self.pg0.get_capture(len(pkts))
Matus Fabian06596c52017-06-06 04:53:28 -07005994 ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
5995 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
5996
5997 ses_num_end = self.nat64_get_ses_num()
5998
5999 self.assertEqual(ses_num_end - ses_num_start, 3)
6000
6001 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
6002 def test_session_timeout(self):
6003 """ NAT64 session timeout """
6004 self.icmp_id_in = 1234
6005 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6006 self.nat_addr_n)
6007 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6008 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
Matus Fabian8fed4242018-08-14 05:14:55 -07006009 self.vapi.nat64_set_timeouts(icmp=5, tcp_trans=5, tcp_est=5)
Matus Fabian06596c52017-06-06 04:53:28 -07006010
6011 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
6012 self.pg0.add_stream(pkts)
6013 self.pg_enable_capture(self.pg_interfaces)
6014 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07006015 capture = self.pg1.get_capture(len(pkts))
Matus Fabian06596c52017-06-06 04:53:28 -07006016
6017 ses_num_before_timeout = self.nat64_get_ses_num()
6018
6019 sleep(15)
6020
Matus Fabian8fed4242018-08-14 05:14:55 -07006021 # ICMP and TCP session after timeout
Matus Fabian06596c52017-06-06 04:53:28 -07006022 ses_num_after_timeout = self.nat64_get_ses_num()
Matus Fabian8fed4242018-08-14 05:14:55 -07006023 self.assertEqual(ses_num_before_timeout - ses_num_after_timeout, 2)
Matus Fabian06596c52017-06-06 04:53:28 -07006024
Matus Fabian732036d2017-06-08 05:24:28 -07006025 def test_icmp_error(self):
6026 """ NAT64 ICMP Error message translation """
6027 self.tcp_port_in = 6303
6028 self.udp_port_in = 6304
6029 self.icmp_id_in = 6305
6030
Matus Fabian732036d2017-06-08 05:24:28 -07006031 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6032 self.nat_addr_n)
6033 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6034 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6035
6036 # send some packets to create sessions
6037 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
6038 self.pg0.add_stream(pkts)
6039 self.pg_enable_capture(self.pg_interfaces)
6040 self.pg_start()
6041 capture_ip4 = self.pg1.get_capture(len(pkts))
Matus Fabian029f3d22017-06-15 02:28:50 -07006042 self.verify_capture_out(capture_ip4,
Matus Fabian732036d2017-06-08 05:24:28 -07006043 nat_ip=self.nat_addr,
6044 dst_ip=self.pg1.remote_ip4)
6045
6046 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
6047 self.pg1.add_stream(pkts)
6048 self.pg_enable_capture(self.pg_interfaces)
6049 self.pg_start()
6050 capture_ip6 = self.pg0.get_capture(len(pkts))
6051 ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
6052 self.verify_capture_in_ip6(capture_ip6, ip[IPv6].src,
6053 self.pg0.remote_ip6)
6054
6055 # in2out
6056 pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6057 IPv6(src=self.pg0.remote_ip6, dst=ip[IPv6].src) /
6058 ICMPv6DestUnreach(code=1) /
6059 packet[IPv6] for packet in capture_ip6]
6060 self.pg0.add_stream(pkts)
6061 self.pg_enable_capture(self.pg_interfaces)
6062 self.pg_start()
6063 capture = self.pg1.get_capture(len(pkts))
6064 for packet in capture:
6065 try:
6066 self.assertEqual(packet[IP].src, self.nat_addr)
6067 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
6068 self.assertEqual(packet[ICMP].type, 3)
6069 self.assertEqual(packet[ICMP].code, 13)
6070 inner = packet[IPerror]
6071 self.assertEqual(inner.src, self.pg1.remote_ip4)
6072 self.assertEqual(inner.dst, self.nat_addr)
Klement Sekerad81ae412018-05-16 10:52:54 +02006073 self.assert_packet_checksums_valid(packet)
Matus Fabian732036d2017-06-08 05:24:28 -07006074 if inner.haslayer(TCPerror):
6075 self.assertEqual(inner[TCPerror].dport, self.tcp_port_out)
6076 elif inner.haslayer(UDPerror):
6077 self.assertEqual(inner[UDPerror].dport, self.udp_port_out)
6078 else:
6079 self.assertEqual(inner[ICMPerror].id, self.icmp_id_out)
6080 except:
6081 self.logger.error(ppp("Unexpected or invalid packet:", packet))
6082 raise
6083
6084 # out2in
6085 pkts = [Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
6086 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6087 ICMP(type=3, code=13) /
6088 packet[IP] for packet in capture_ip4]
6089 self.pg1.add_stream(pkts)
6090 self.pg_enable_capture(self.pg_interfaces)
6091 self.pg_start()
6092 capture = self.pg0.get_capture(len(pkts))
6093 for packet in capture:
6094 try:
6095 self.assertEqual(packet[IPv6].src, ip.src)
6096 self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
6097 icmp = packet[ICMPv6DestUnreach]
6098 self.assertEqual(icmp.code, 1)
6099 inner = icmp[IPerror6]
6100 self.assertEqual(inner.src, self.pg0.remote_ip6)
6101 self.assertEqual(inner.dst, ip.src)
Klement Sekerad81ae412018-05-16 10:52:54 +02006102 self.assert_icmpv6_checksum_valid(packet)
Matus Fabian732036d2017-06-08 05:24:28 -07006103 if inner.haslayer(TCPerror):
6104 self.assertEqual(inner[TCPerror].sport, self.tcp_port_in)
6105 elif inner.haslayer(UDPerror):
6106 self.assertEqual(inner[UDPerror].sport, self.udp_port_in)
6107 else:
6108 self.assertEqual(inner[ICMPv6EchoRequest].id,
6109 self.icmp_id_in)
6110 except:
6111 self.logger.error(ppp("Unexpected or invalid packet:", packet))
6112 raise
6113
Matus Fabian029f3d22017-06-15 02:28:50 -07006114 def test_hairpinning(self):
6115 """ NAT64 hairpinning """
6116
6117 client = self.pg0.remote_hosts[0]
6118 server = self.pg0.remote_hosts[1]
6119 server_tcp_in_port = 22
6120 server_tcp_out_port = 4022
6121 server_udp_in_port = 23
6122 server_udp_out_port = 4023
6123 client_tcp_in_port = 1234
6124 client_udp_in_port = 1235
6125 client_tcp_out_port = 0
6126 client_udp_out_port = 0
6127 ip = IPv6(src=''.join(['64:ff9b::', self.nat_addr]))
6128 nat_addr_ip6 = ip.src
6129
6130 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6131 self.nat_addr_n)
6132 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6133 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6134
6135 self.vapi.nat64_add_del_static_bib(server.ip6n,
6136 self.nat_addr_n,
6137 server_tcp_in_port,
6138 server_tcp_out_port,
6139 IP_PROTOS.tcp)
6140 self.vapi.nat64_add_del_static_bib(server.ip6n,
6141 self.nat_addr_n,
6142 server_udp_in_port,
6143 server_udp_out_port,
6144 IP_PROTOS.udp)
6145
6146 # client to server
6147 pkts = []
6148 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6149 IPv6(src=client.ip6, dst=nat_addr_ip6) /
6150 TCP(sport=client_tcp_in_port, dport=server_tcp_out_port))
6151 pkts.append(p)
6152 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6153 IPv6(src=client.ip6, dst=nat_addr_ip6) /
6154 UDP(sport=client_udp_in_port, dport=server_udp_out_port))
6155 pkts.append(p)
6156 self.pg0.add_stream(pkts)
6157 self.pg_enable_capture(self.pg_interfaces)
6158 self.pg_start()
6159 capture = self.pg0.get_capture(len(pkts))
6160 for packet in capture:
6161 try:
6162 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
6163 self.assertEqual(packet[IPv6].dst, server.ip6)
Klement Sekerad81ae412018-05-16 10:52:54 +02006164 self.assert_packet_checksums_valid(packet)
Matus Fabian029f3d22017-06-15 02:28:50 -07006165 if packet.haslayer(TCP):
6166 self.assertNotEqual(packet[TCP].sport, client_tcp_in_port)
6167 self.assertEqual(packet[TCP].dport, server_tcp_in_port)
Matus Fabian029f3d22017-06-15 02:28:50 -07006168 client_tcp_out_port = packet[TCP].sport
6169 else:
6170 self.assertNotEqual(packet[UDP].sport, client_udp_in_port)
6171 self.assertEqual(packet[UDP].dport, server_udp_in_port)
Matus Fabian029f3d22017-06-15 02:28:50 -07006172 client_udp_out_port = packet[UDP].sport
6173 except:
6174 self.logger.error(ppp("Unexpected or invalid packet:", packet))
6175 raise
6176
6177 # server to client
6178 pkts = []
6179 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6180 IPv6(src=server.ip6, dst=nat_addr_ip6) /
6181 TCP(sport=server_tcp_in_port, dport=client_tcp_out_port))
6182 pkts.append(p)
6183 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6184 IPv6(src=server.ip6, dst=nat_addr_ip6) /
6185 UDP(sport=server_udp_in_port, dport=client_udp_out_port))
6186 pkts.append(p)
6187 self.pg0.add_stream(pkts)
6188 self.pg_enable_capture(self.pg_interfaces)
6189 self.pg_start()
6190 capture = self.pg0.get_capture(len(pkts))
6191 for packet in capture:
6192 try:
6193 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
6194 self.assertEqual(packet[IPv6].dst, client.ip6)
Klement Sekerad81ae412018-05-16 10:52:54 +02006195 self.assert_packet_checksums_valid(packet)
Matus Fabian029f3d22017-06-15 02:28:50 -07006196 if packet.haslayer(TCP):
6197 self.assertEqual(packet[TCP].sport, server_tcp_out_port)
6198 self.assertEqual(packet[TCP].dport, client_tcp_in_port)
Matus Fabian029f3d22017-06-15 02:28:50 -07006199 else:
6200 self.assertEqual(packet[UDP].sport, server_udp_out_port)
6201 self.assertEqual(packet[UDP].dport, client_udp_in_port)
Matus Fabian029f3d22017-06-15 02:28:50 -07006202 except:
6203 self.logger.error(ppp("Unexpected or invalid packet:", packet))
6204 raise
6205
6206 # ICMP error
6207 pkts = []
6208 pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6209 IPv6(src=client.ip6, dst=nat_addr_ip6) /
6210 ICMPv6DestUnreach(code=1) /
6211 packet[IPv6] for packet in capture]
6212 self.pg0.add_stream(pkts)
6213 self.pg_enable_capture(self.pg_interfaces)
6214 self.pg_start()
6215 capture = self.pg0.get_capture(len(pkts))
6216 for packet in capture:
6217 try:
6218 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
6219 self.assertEqual(packet[IPv6].dst, server.ip6)
6220 icmp = packet[ICMPv6DestUnreach]
6221 self.assertEqual(icmp.code, 1)
6222 inner = icmp[IPerror6]
6223 self.assertEqual(inner.src, server.ip6)
6224 self.assertEqual(inner.dst, nat_addr_ip6)
Klement Sekerad81ae412018-05-16 10:52:54 +02006225 self.assert_packet_checksums_valid(packet)
Matus Fabian029f3d22017-06-15 02:28:50 -07006226 if inner.haslayer(TCPerror):
6227 self.assertEqual(inner[TCPerror].sport, server_tcp_in_port)
6228 self.assertEqual(inner[TCPerror].dport,
6229 client_tcp_out_port)
6230 else:
6231 self.assertEqual(inner[UDPerror].sport, server_udp_in_port)
6232 self.assertEqual(inner[UDPerror].dport,
6233 client_udp_out_port)
6234 except:
6235 self.logger.error(ppp("Unexpected or invalid packet:", packet))
6236 raise
6237
Matus Fabian428dc912017-06-21 06:15:18 -07006238 def test_prefix(self):
6239 """ NAT64 Network-Specific Prefix """
6240
6241 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6242 self.nat_addr_n)
6243 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6244 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6245 self.vapi.nat64_add_del_pool_addr_range(self.vrf1_nat_addr_n,
6246 self.vrf1_nat_addr_n,
6247 vrf_id=self.vrf1_id)
6248 self.vapi.nat64_add_del_interface(self.pg2.sw_if_index)
6249
6250 # Add global prefix
6251 global_pref64 = "2001:db8::"
6252 global_pref64_n = socket.inet_pton(socket.AF_INET6, global_pref64)
6253 global_pref64_len = 32
6254 self.vapi.nat64_add_del_prefix(global_pref64_n, global_pref64_len)
6255
6256 prefix = self.vapi.nat64_prefix_dump()
6257 self.assertEqual(len(prefix), 1)
6258 self.assertEqual(prefix[0].prefix, global_pref64_n)
6259 self.assertEqual(prefix[0].prefix_len, global_pref64_len)
6260 self.assertEqual(prefix[0].vrf_id, 0)
6261
6262 # Add tenant specific prefix
6263 vrf1_pref64 = "2001:db8:122:300::"
6264 vrf1_pref64_n = socket.inet_pton(socket.AF_INET6, vrf1_pref64)
6265 vrf1_pref64_len = 56
6266 self.vapi.nat64_add_del_prefix(vrf1_pref64_n,
6267 vrf1_pref64_len,
6268 vrf_id=self.vrf1_id)
6269 prefix = self.vapi.nat64_prefix_dump()
6270 self.assertEqual(len(prefix), 2)
6271
6272 # Global prefix
6273 pkts = self.create_stream_in_ip6(self.pg0,
6274 self.pg1,
6275 pref=global_pref64,
6276 plen=global_pref64_len)
6277 self.pg0.add_stream(pkts)
6278 self.pg_enable_capture(self.pg_interfaces)
6279 self.pg_start()
6280 capture = self.pg1.get_capture(len(pkts))
6281 self.verify_capture_out(capture, nat_ip=self.nat_addr,
6282 dst_ip=self.pg1.remote_ip4)
6283
6284 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
6285 self.pg1.add_stream(pkts)
6286 self.pg_enable_capture(self.pg_interfaces)
6287 self.pg_start()
6288 capture = self.pg0.get_capture(len(pkts))
6289 dst_ip = self.compose_ip6(self.pg1.remote_ip4,
6290 global_pref64,
6291 global_pref64_len)
6292 self.verify_capture_in_ip6(capture, dst_ip, self.pg0.remote_ip6)
6293
6294 # Tenant specific prefix
6295 pkts = self.create_stream_in_ip6(self.pg2,
6296 self.pg1,
6297 pref=vrf1_pref64,
6298 plen=vrf1_pref64_len)
6299 self.pg2.add_stream(pkts)
6300 self.pg_enable_capture(self.pg_interfaces)
6301 self.pg_start()
6302 capture = self.pg1.get_capture(len(pkts))
6303 self.verify_capture_out(capture, nat_ip=self.vrf1_nat_addr,
6304 dst_ip=self.pg1.remote_ip4)
6305
6306 pkts = self.create_stream_out(self.pg1, dst_ip=self.vrf1_nat_addr)
6307 self.pg1.add_stream(pkts)
6308 self.pg_enable_capture(self.pg_interfaces)
6309 self.pg_start()
6310 capture = self.pg2.get_capture(len(pkts))
6311 dst_ip = self.compose_ip6(self.pg1.remote_ip4,
6312 vrf1_pref64,
6313 vrf1_pref64_len)
6314 self.verify_capture_in_ip6(capture, dst_ip, self.pg2.remote_ip6)
6315
Matus Fabianf8cd5812017-07-11 03:55:02 -07006316 def test_unknown_proto(self):
Matus Fabian7968e6c2017-07-06 05:37:49 -07006317 """ NAT64 translate packet with unknown protocol """
6318
6319 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6320 self.nat_addr_n)
6321 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6322 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6323 remote_ip6 = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
6324
6325 # in2out
6326 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6327 IPv6(src=self.pg0.remote_ip6, dst=remote_ip6) /
6328 TCP(sport=self.tcp_port_in, dport=20))
6329 self.pg0.add_stream(p)
6330 self.pg_enable_capture(self.pg_interfaces)
6331 self.pg_start()
6332 p = self.pg1.get_capture(1)
6333
6334 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabianf8cd5812017-07-11 03:55:02 -07006335 IPv6(src=self.pg0.remote_ip6, dst=remote_ip6, nh=47) /
Matus Fabian7968e6c2017-07-06 05:37:49 -07006336 GRE() /
6337 IP(src=self.pg2.local_ip4, dst=self.pg2.remote_ip4) /
6338 TCP(sport=1234, dport=1234))
6339 self.pg0.add_stream(p)
6340 self.pg_enable_capture(self.pg_interfaces)
6341 self.pg_start()
6342 p = self.pg1.get_capture(1)
6343 packet = p[0]
6344 try:
6345 self.assertEqual(packet[IP].src, self.nat_addr)
6346 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
6347 self.assertTrue(packet.haslayer(GRE))
Klement Sekerad81ae412018-05-16 10:52:54 +02006348 self.assert_packet_checksums_valid(packet)
Matus Fabian7968e6c2017-07-06 05:37:49 -07006349 except:
6350 self.logger.error(ppp("Unexpected or invalid packet:", packet))
6351 raise
6352
6353 # out2in
6354 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
6355 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6356 GRE() /
6357 IP(src=self.pg2.remote_ip4, dst=self.pg2.local_ip4) /
6358 TCP(sport=1234, dport=1234))
6359 self.pg1.add_stream(p)
6360 self.pg_enable_capture(self.pg_interfaces)
6361 self.pg_start()
6362 p = self.pg0.get_capture(1)
6363 packet = p[0]
6364 try:
6365 self.assertEqual(packet[IPv6].src, remote_ip6)
Matus Fabianf8cd5812017-07-11 03:55:02 -07006366 self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
6367 self.assertEqual(packet[IPv6].nh, 47)
Matus Fabian7968e6c2017-07-06 05:37:49 -07006368 except:
6369 self.logger.error(ppp("Unexpected or invalid packet:", packet))
6370 raise
6371
Matus Fabianf8cd5812017-07-11 03:55:02 -07006372 def test_hairpinning_unknown_proto(self):
Matus Fabian7968e6c2017-07-06 05:37:49 -07006373 """ NAT64 translate packet with unknown protocol - hairpinning """
6374
6375 client = self.pg0.remote_hosts[0]
6376 server = self.pg0.remote_hosts[1]
6377 server_tcp_in_port = 22
6378 server_tcp_out_port = 4022
6379 client_tcp_in_port = 1234
Matus Fabianf8cd5812017-07-11 03:55:02 -07006380 client_tcp_out_port = 1235
6381 server_nat_ip = "10.0.0.100"
6382 client_nat_ip = "10.0.0.110"
6383 server_nat_ip_n = socket.inet_pton(socket.AF_INET, server_nat_ip)
6384 client_nat_ip_n = socket.inet_pton(socket.AF_INET, client_nat_ip)
6385 server_nat_ip6 = self.compose_ip6(server_nat_ip, '64:ff9b::', 96)
6386 client_nat_ip6 = self.compose_ip6(client_nat_ip, '64:ff9b::', 96)
Matus Fabian7968e6c2017-07-06 05:37:49 -07006387
Matus Fabianf8cd5812017-07-11 03:55:02 -07006388 self.vapi.nat64_add_del_pool_addr_range(server_nat_ip_n,
6389 client_nat_ip_n)
Matus Fabian7968e6c2017-07-06 05:37:49 -07006390 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6391 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6392
6393 self.vapi.nat64_add_del_static_bib(server.ip6n,
Matus Fabianf8cd5812017-07-11 03:55:02 -07006394 server_nat_ip_n,
Matus Fabian7968e6c2017-07-06 05:37:49 -07006395 server_tcp_in_port,
6396 server_tcp_out_port,
6397 IP_PROTOS.tcp)
6398
Matus Fabianf8cd5812017-07-11 03:55:02 -07006399 self.vapi.nat64_add_del_static_bib(server.ip6n,
6400 server_nat_ip_n,
6401 0,
6402 0,
6403 IP_PROTOS.gre)
6404
6405 self.vapi.nat64_add_del_static_bib(client.ip6n,
6406 client_nat_ip_n,
6407 client_tcp_in_port,
6408 client_tcp_out_port,
6409 IP_PROTOS.tcp)
6410
Matus Fabian7968e6c2017-07-06 05:37:49 -07006411 # client to server
6412 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabianf8cd5812017-07-11 03:55:02 -07006413 IPv6(src=client.ip6, dst=server_nat_ip6) /
Matus Fabian7968e6c2017-07-06 05:37:49 -07006414 TCP(sport=client_tcp_in_port, dport=server_tcp_out_port))
6415 self.pg0.add_stream(p)
6416 self.pg_enable_capture(self.pg_interfaces)
6417 self.pg_start()
6418 p = self.pg0.get_capture(1)
6419
6420 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabianf8cd5812017-07-11 03:55:02 -07006421 IPv6(src=client.ip6, dst=server_nat_ip6, nh=IP_PROTOS.gre) /
Matus Fabian7968e6c2017-07-06 05:37:49 -07006422 GRE() /
6423 IP(src=self.pg2.local_ip4, dst=self.pg2.remote_ip4) /
6424 TCP(sport=1234, dport=1234))
6425 self.pg0.add_stream(p)
6426 self.pg_enable_capture(self.pg_interfaces)
6427 self.pg_start()
6428 p = self.pg0.get_capture(1)
6429 packet = p[0]
6430 try:
Matus Fabianf8cd5812017-07-11 03:55:02 -07006431 self.assertEqual(packet[IPv6].src, client_nat_ip6)
Matus Fabian7968e6c2017-07-06 05:37:49 -07006432 self.assertEqual(packet[IPv6].dst, server.ip6)
Matus Fabianf8cd5812017-07-11 03:55:02 -07006433 self.assertEqual(packet[IPv6].nh, IP_PROTOS.gre)
Matus Fabian7968e6c2017-07-06 05:37:49 -07006434 except:
6435 self.logger.error(ppp("Unexpected or invalid packet:", packet))
6436 raise
6437
6438 # server to client
6439 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabianf8cd5812017-07-11 03:55:02 -07006440 IPv6(src=server.ip6, dst=client_nat_ip6, nh=IP_PROTOS.gre) /
Matus Fabian7968e6c2017-07-06 05:37:49 -07006441 GRE() /
6442 IP(src=self.pg2.remote_ip4, dst=self.pg2.local_ip4) /
6443 TCP(sport=1234, dport=1234))
6444 self.pg0.add_stream(p)
6445 self.pg_enable_capture(self.pg_interfaces)
6446 self.pg_start()
6447 p = self.pg0.get_capture(1)
6448 packet = p[0]
6449 try:
Matus Fabianf8cd5812017-07-11 03:55:02 -07006450 self.assertEqual(packet[IPv6].src, server_nat_ip6)
Matus Fabian7968e6c2017-07-06 05:37:49 -07006451 self.assertEqual(packet[IPv6].dst, client.ip6)
Matus Fabianf8cd5812017-07-11 03:55:02 -07006452 self.assertEqual(packet[IPv6].nh, IP_PROTOS.gre)
Matus Fabian7968e6c2017-07-06 05:37:49 -07006453 except:
6454 self.logger.error(ppp("Unexpected or invalid packet:", packet))
6455 raise
6456
Matus Fabian36ea2d62017-10-24 04:13:49 -07006457 def test_one_armed_nat64(self):
6458 """ One armed NAT64 """
6459 external_port = 0
6460 remote_host_ip6 = self.compose_ip6(self.pg3.remote_ip4,
6461 '64:ff9b::',
6462 96)
6463
6464 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6465 self.nat_addr_n)
6466 self.vapi.nat64_add_del_interface(self.pg3.sw_if_index)
6467 self.vapi.nat64_add_del_interface(self.pg3.sw_if_index, is_inside=0)
6468
6469 # in2out
6470 p = (Ether(src=self.pg3.remote_mac, dst=self.pg3.local_mac) /
6471 IPv6(src=self.pg3.remote_ip6, dst=remote_host_ip6) /
6472 TCP(sport=12345, dport=80))
6473 self.pg3.add_stream(p)
6474 self.pg_enable_capture(self.pg_interfaces)
6475 self.pg_start()
6476 capture = self.pg3.get_capture(1)
6477 p = capture[0]
6478 try:
6479 ip = p[IP]
6480 tcp = p[TCP]
6481 self.assertEqual(ip.src, self.nat_addr)
6482 self.assertEqual(ip.dst, self.pg3.remote_ip4)
6483 self.assertNotEqual(tcp.sport, 12345)
6484 external_port = tcp.sport
6485 self.assertEqual(tcp.dport, 80)
Klement Sekerad81ae412018-05-16 10:52:54 +02006486 self.assert_packet_checksums_valid(p)
Matus Fabian36ea2d62017-10-24 04:13:49 -07006487 except:
6488 self.logger.error(ppp("Unexpected or invalid packet:", p))
6489 raise
6490
6491 # out2in
6492 p = (Ether(src=self.pg3.remote_mac, dst=self.pg3.local_mac) /
6493 IP(src=self.pg3.remote_ip4, dst=self.nat_addr) /
6494 TCP(sport=80, dport=external_port))
6495 self.pg3.add_stream(p)
6496 self.pg_enable_capture(self.pg_interfaces)
6497 self.pg_start()
6498 capture = self.pg3.get_capture(1)
6499 p = capture[0]
6500 try:
6501 ip = p[IPv6]
6502 tcp = p[TCP]
6503 self.assertEqual(ip.src, remote_host_ip6)
6504 self.assertEqual(ip.dst, self.pg3.remote_ip6)
6505 self.assertEqual(tcp.sport, 80)
6506 self.assertEqual(tcp.dport, 12345)
Klement Sekerad81ae412018-05-16 10:52:54 +02006507 self.assert_packet_checksums_valid(p)
Matus Fabian36ea2d62017-10-24 04:13:49 -07006508 except:
6509 self.logger.error(ppp("Unexpected or invalid packet:", p))
6510 raise
6511
Matus Fabianefcd1e92017-08-15 06:59:19 -07006512 def test_frag_in_order(self):
6513 """ NAT64 translate fragments arriving in order """
6514 self.tcp_port_in = random.randint(1025, 65535)
6515
6516 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6517 self.nat_addr_n)
6518 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6519 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6520
6521 reass = self.vapi.nat_reass_dump()
6522 reass_n_start = len(reass)
6523
6524 # in2out
6525 data = 'a' * 200
6526 pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
6527 self.tcp_port_in, 20, data)
6528 self.pg0.add_stream(pkts)
6529 self.pg_enable_capture(self.pg_interfaces)
6530 self.pg_start()
6531 frags = self.pg1.get_capture(len(pkts))
6532 p = self.reass_frags_and_verify(frags,
6533 self.nat_addr,
6534 self.pg1.remote_ip4)
6535 self.assertEqual(p[TCP].dport, 20)
6536 self.assertNotEqual(p[TCP].sport, self.tcp_port_in)
6537 self.tcp_port_out = p[TCP].sport
6538 self.assertEqual(data, p[Raw].load)
6539
6540 # out2in
6541 data = "A" * 4 + "b" * 16 + "C" * 3
6542 pkts = self.create_stream_frag(self.pg1,
6543 self.nat_addr,
6544 20,
6545 self.tcp_port_out,
6546 data)
6547 self.pg1.add_stream(pkts)
6548 self.pg_enable_capture(self.pg_interfaces)
6549 self.pg_start()
6550 frags = self.pg0.get_capture(len(pkts))
6551 src = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
6552 p = self.reass_frags_and_verify_ip6(frags, src, self.pg0.remote_ip6)
6553 self.assertEqual(p[TCP].sport, 20)
6554 self.assertEqual(p[TCP].dport, self.tcp_port_in)
6555 self.assertEqual(data, p[Raw].load)
6556
6557 reass = self.vapi.nat_reass_dump()
6558 reass_n_end = len(reass)
6559
6560 self.assertEqual(reass_n_end - reass_n_start, 2)
6561
6562 def test_reass_hairpinning(self):
6563 """ NAT64 fragments hairpinning """
6564 data = 'a' * 200
Matus Fabianefcd1e92017-08-15 06:59:19 -07006565 server = self.pg0.remote_hosts[1]
6566 server_in_port = random.randint(1025, 65535)
6567 server_out_port = random.randint(1025, 65535)
6568 client_in_port = random.randint(1025, 65535)
6569 ip = IPv6(src=''.join(['64:ff9b::', self.nat_addr]))
6570 nat_addr_ip6 = ip.src
6571
6572 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6573 self.nat_addr_n)
6574 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6575 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6576
6577 # add static BIB entry for server
6578 self.vapi.nat64_add_del_static_bib(server.ip6n,
6579 self.nat_addr_n,
6580 server_in_port,
6581 server_out_port,
6582 IP_PROTOS.tcp)
6583
6584 # send packet from host to server
6585 pkts = self.create_stream_frag_ip6(self.pg0,
6586 self.nat_addr,
6587 client_in_port,
6588 server_out_port,
6589 data)
6590 self.pg0.add_stream(pkts)
6591 self.pg_enable_capture(self.pg_interfaces)
6592 self.pg_start()
6593 frags = self.pg0.get_capture(len(pkts))
6594 p = self.reass_frags_and_verify_ip6(frags, nat_addr_ip6, server.ip6)
6595 self.assertNotEqual(p[TCP].sport, client_in_port)
6596 self.assertEqual(p[TCP].dport, server_in_port)
6597 self.assertEqual(data, p[Raw].load)
6598
6599 def test_frag_out_of_order(self):
6600 """ NAT64 translate fragments arriving out of order """
6601 self.tcp_port_in = random.randint(1025, 65535)
6602
6603 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6604 self.nat_addr_n)
6605 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6606 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6607
6608 # in2out
6609 data = 'a' * 200
6610 pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
6611 self.tcp_port_in, 20, data)
6612 pkts.reverse()
6613 self.pg0.add_stream(pkts)
6614 self.pg_enable_capture(self.pg_interfaces)
6615 self.pg_start()
6616 frags = self.pg1.get_capture(len(pkts))
6617 p = self.reass_frags_and_verify(frags,
6618 self.nat_addr,
6619 self.pg1.remote_ip4)
6620 self.assertEqual(p[TCP].dport, 20)
6621 self.assertNotEqual(p[TCP].sport, self.tcp_port_in)
6622 self.tcp_port_out = p[TCP].sport
6623 self.assertEqual(data, p[Raw].load)
6624
6625 # out2in
6626 data = "A" * 4 + "B" * 16 + "C" * 3
6627 pkts = self.create_stream_frag(self.pg1,
6628 self.nat_addr,
6629 20,
6630 self.tcp_port_out,
6631 data)
6632 pkts.reverse()
6633 self.pg1.add_stream(pkts)
6634 self.pg_enable_capture(self.pg_interfaces)
6635 self.pg_start()
6636 frags = self.pg0.get_capture(len(pkts))
6637 src = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
6638 p = self.reass_frags_and_verify_ip6(frags, src, self.pg0.remote_ip6)
6639 self.assertEqual(p[TCP].sport, 20)
6640 self.assertEqual(p[TCP].dport, self.tcp_port_in)
6641 self.assertEqual(data, p[Raw].load)
6642
Matus Fabian0938dcf2017-11-08 01:59:38 -08006643 def test_interface_addr(self):
6644 """ Acquire NAT64 pool addresses from interface """
6645 self.vapi.nat64_add_interface_addr(self.pg4.sw_if_index)
6646
6647 # no address in NAT64 pool
6648 adresses = self.vapi.nat44_address_dump()
6649 self.assertEqual(0, len(adresses))
6650
6651 # configure interface address and check NAT64 address pool
6652 self.pg4.config_ip4()
6653 addresses = self.vapi.nat64_pool_addr_dump()
6654 self.assertEqual(len(addresses), 1)
6655 self.assertEqual(addresses[0].address, self.pg4.local_ip4n)
6656
6657 # remove interface address and check NAT64 address pool
6658 self.pg4.unconfig_ip4()
6659 addresses = self.vapi.nat64_pool_addr_dump()
6660 self.assertEqual(0, len(adresses))
6661
Matus Fabiana431ad12018-01-04 04:03:14 -08006662 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
6663 def test_ipfix_max_bibs_sessions(self):
6664 """ IPFIX logging maximum session and BIB entries exceeded """
6665 max_bibs = 1280
6666 max_sessions = 2560
6667 remote_host_ip6 = self.compose_ip6(self.pg1.remote_ip4,
6668 '64:ff9b::',
6669 96)
6670
6671 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6672 self.nat_addr_n)
6673 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6674 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6675
6676 pkts = []
6677 src = ""
6678 for i in range(0, max_bibs):
6679 src = "fd01:aa::%x" % (i)
6680 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6681 IPv6(src=src, dst=remote_host_ip6) /
6682 TCP(sport=12345, dport=80))
6683 pkts.append(p)
6684 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6685 IPv6(src=src, dst=remote_host_ip6) /
6686 TCP(sport=12345, dport=22))
6687 pkts.append(p)
6688 self.pg0.add_stream(pkts)
6689 self.pg_enable_capture(self.pg_interfaces)
6690 self.pg_start()
6691 self.pg1.get_capture(max_sessions)
6692
6693 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
6694 src_address=self.pg3.local_ip4n,
6695 path_mtu=512,
6696 template_interval=10)
6697 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
6698 src_port=self.ipfix_src_port)
6699
6700 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6701 IPv6(src=src, dst=remote_host_ip6) /
6702 TCP(sport=12345, dport=25))
6703 self.pg0.add_stream(p)
6704 self.pg_enable_capture(self.pg_interfaces)
6705 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07006706 self.pg1.assert_nothing_captured()
6707 sleep(1)
Matus Fabiana431ad12018-01-04 04:03:14 -08006708 self.vapi.cli("ipfix flush") # FIXME this should be an API call
6709 capture = self.pg3.get_capture(9)
6710 ipfix = IPFIXDecoder()
6711 # first load template
6712 for p in capture:
6713 self.assertTrue(p.haslayer(IPFIX))
6714 self.assertEqual(p[IP].src, self.pg3.local_ip4)
6715 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
6716 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
6717 self.assertEqual(p[UDP].dport, 4739)
6718 self.assertEqual(p[IPFIX].observationDomainID,
6719 self.ipfix_domain_id)
6720 if p.haslayer(Template):
6721 ipfix.add_template(p.getlayer(Template))
6722 # verify events in data set
6723 for p in capture:
6724 if p.haslayer(Data):
6725 data = ipfix.decode_data_set(p.getlayer(Set))
6726 self.verify_ipfix_max_sessions(data, max_sessions)
6727
6728 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6729 IPv6(src=self.pg0.remote_ip6, dst=remote_host_ip6) /
6730 TCP(sport=12345, dport=80))
6731 self.pg0.add_stream(p)
6732 self.pg_enable_capture(self.pg_interfaces)
6733 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07006734 self.pg1.assert_nothing_captured()
6735 sleep(1)
Matus Fabiana431ad12018-01-04 04:03:14 -08006736 self.vapi.cli("ipfix flush") # FIXME this should be an API call
6737 capture = self.pg3.get_capture(1)
6738 # verify events in data set
6739 for p in capture:
6740 self.assertTrue(p.haslayer(IPFIX))
6741 self.assertEqual(p[IP].src, self.pg3.local_ip4)
6742 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
6743 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
6744 self.assertEqual(p[UDP].dport, 4739)
6745 self.assertEqual(p[IPFIX].observationDomainID,
6746 self.ipfix_domain_id)
6747 if p.haslayer(Data):
6748 data = ipfix.decode_data_set(p.getlayer(Set))
6749 self.verify_ipfix_max_bibs(data, max_bibs)
6750
6751 def test_ipfix_max_frags(self):
6752 """ IPFIX logging maximum fragments pending reassembly exceeded """
6753 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6754 self.nat_addr_n)
6755 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6756 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6757 self.vapi.nat_set_reass(max_frag=0, is_ip6=1)
6758 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
6759 src_address=self.pg3.local_ip4n,
6760 path_mtu=512,
6761 template_interval=10)
6762 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
6763 src_port=self.ipfix_src_port)
6764
6765 data = 'a' * 200
6766 pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
6767 self.tcp_port_in, 20, data)
6768 self.pg0.add_stream(pkts[-1])
6769 self.pg_enable_capture(self.pg_interfaces)
6770 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07006771 self.pg1.assert_nothing_captured()
6772 sleep(1)
Matus Fabiana431ad12018-01-04 04:03:14 -08006773 self.vapi.cli("ipfix flush") # FIXME this should be an API call
6774 capture = self.pg3.get_capture(9)
6775 ipfix = IPFIXDecoder()
6776 # first load template
6777 for p in capture:
6778 self.assertTrue(p.haslayer(IPFIX))
6779 self.assertEqual(p[IP].src, self.pg3.local_ip4)
6780 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
6781 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
6782 self.assertEqual(p[UDP].dport, 4739)
6783 self.assertEqual(p[IPFIX].observationDomainID,
6784 self.ipfix_domain_id)
6785 if p.haslayer(Template):
6786 ipfix.add_template(p.getlayer(Template))
6787 # verify events in data set
6788 for p in capture:
6789 if p.haslayer(Data):
6790 data = ipfix.decode_data_set(p.getlayer(Set))
6791 self.verify_ipfix_max_fragments_ip6(data, 0,
6792 self.pg0.remote_ip6n)
6793
6794 def test_ipfix_bib_ses(self):
6795 """ IPFIX logging NAT64 BIB/session create and delete events """
6796 self.tcp_port_in = random.randint(1025, 65535)
6797 remote_host_ip6 = self.compose_ip6(self.pg1.remote_ip4,
6798 '64:ff9b::',
6799 96)
6800
6801 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6802 self.nat_addr_n)
6803 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6804 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6805 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
6806 src_address=self.pg3.local_ip4n,
6807 path_mtu=512,
6808 template_interval=10)
6809 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
6810 src_port=self.ipfix_src_port)
6811
6812 # Create
6813 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6814 IPv6(src=self.pg0.remote_ip6, dst=remote_host_ip6) /
6815 TCP(sport=self.tcp_port_in, dport=25))
6816 self.pg0.add_stream(p)
6817 self.pg_enable_capture(self.pg_interfaces)
6818 self.pg_start()
6819 p = self.pg1.get_capture(1)
6820 self.tcp_port_out = p[0][TCP].sport
6821 self.vapi.cli("ipfix flush") # FIXME this should be an API call
6822 capture = self.pg3.get_capture(10)
6823 ipfix = IPFIXDecoder()
6824 # first load template
6825 for p in capture:
6826 self.assertTrue(p.haslayer(IPFIX))
6827 self.assertEqual(p[IP].src, self.pg3.local_ip4)
6828 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
6829 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
6830 self.assertEqual(p[UDP].dport, 4739)
6831 self.assertEqual(p[IPFIX].observationDomainID,
6832 self.ipfix_domain_id)
6833 if p.haslayer(Template):
6834 ipfix.add_template(p.getlayer(Template))
6835 # verify events in data set
6836 for p in capture:
6837 if p.haslayer(Data):
6838 data = ipfix.decode_data_set(p.getlayer(Set))
6839 if ord(data[0][230]) == 10:
6840 self.verify_ipfix_bib(data, 1, self.pg0.remote_ip6n)
6841 elif ord(data[0][230]) == 6:
6842 self.verify_ipfix_nat64_ses(data,
6843 1,
6844 self.pg0.remote_ip6n,
6845 self.pg1.remote_ip4,
6846 25)
6847 else:
6848 self.logger.error(ppp("Unexpected or invalid packet: ", p))
6849
6850 # Delete
6851 self.pg_enable_capture(self.pg_interfaces)
6852 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6853 self.nat_addr_n,
6854 is_add=0)
6855 self.vapi.cli("ipfix flush") # FIXME this should be an API call
6856 capture = self.pg3.get_capture(2)
6857 # verify events in data set
6858 for p in capture:
6859 self.assertTrue(p.haslayer(IPFIX))
6860 self.assertEqual(p[IP].src, self.pg3.local_ip4)
6861 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
6862 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
6863 self.assertEqual(p[UDP].dport, 4739)
6864 self.assertEqual(p[IPFIX].observationDomainID,
6865 self.ipfix_domain_id)
6866 if p.haslayer(Data):
6867 data = ipfix.decode_data_set(p.getlayer(Set))
6868 if ord(data[0][230]) == 11:
6869 self.verify_ipfix_bib(data, 0, self.pg0.remote_ip6n)
6870 elif ord(data[0][230]) == 7:
6871 self.verify_ipfix_nat64_ses(data,
6872 0,
6873 self.pg0.remote_ip6n,
6874 self.pg1.remote_ip4,
6875 25)
6876 else:
6877 self.logger.error(ppp("Unexpected or invalid packet: ", p))
6878
Matus Fabian06596c52017-06-06 04:53:28 -07006879 def nat64_get_ses_num(self):
6880 """
6881 Return number of active NAT64 sessions.
6882 """
Matus Fabianab9a59c2017-08-16 05:37:36 -07006883 st = self.vapi.nat64_st_dump()
6884 return len(st)
Matus Fabian06596c52017-06-06 04:53:28 -07006885
6886 def clear_nat64(self):
6887 """
6888 Clear NAT64 configuration.
6889 """
Matus Fabiana431ad12018-01-04 04:03:14 -08006890 self.vapi.nat_ipfix(enable=0, src_port=self.ipfix_src_port,
6891 domain_id=self.ipfix_domain_id)
6892 self.ipfix_src_port = 4739
6893 self.ipfix_domain_id = 1
6894
Matus Fabian06596c52017-06-06 04:53:28 -07006895 self.vapi.nat64_set_timeouts()
6896
6897 interfaces = self.vapi.nat64_interface_dump()
6898 for intf in interfaces:
Matus Fabian36ea2d62017-10-24 04:13:49 -07006899 if intf.is_inside > 1:
6900 self.vapi.nat64_add_del_interface(intf.sw_if_index,
6901 0,
6902 is_add=0)
Matus Fabian06596c52017-06-06 04:53:28 -07006903 self.vapi.nat64_add_del_interface(intf.sw_if_index,
6904 intf.is_inside,
6905 is_add=0)
6906
Matus Fabiana431ad12018-01-04 04:03:14 -08006907 bib = self.vapi.nat64_bib_dump(255)
Matus Fabian06596c52017-06-06 04:53:28 -07006908 for bibe in bib:
6909 if bibe.is_static:
6910 self.vapi.nat64_add_del_static_bib(bibe.i_addr,
6911 bibe.o_addr,
6912 bibe.i_port,
6913 bibe.o_port,
6914 bibe.proto,
6915 bibe.vrf_id,
6916 is_add=0)
6917
6918 adresses = self.vapi.nat64_pool_addr_dump()
6919 for addr in adresses:
6920 self.vapi.nat64_add_del_pool_addr_range(addr.address,
6921 addr.address,
Matus Fabian029f3d22017-06-15 02:28:50 -07006922 vrf_id=addr.vrf_id,
Matus Fabian06596c52017-06-06 04:53:28 -07006923 is_add=0)
6924
Matus Fabian428dc912017-06-21 06:15:18 -07006925 prefixes = self.vapi.nat64_prefix_dump()
6926 for prefix in prefixes:
6927 self.vapi.nat64_add_del_prefix(prefix.prefix,
6928 prefix.prefix_len,
6929 vrf_id=prefix.vrf_id,
6930 is_add=0)
6931
Matus Fabian06596c52017-06-06 04:53:28 -07006932 def tearDown(self):
6933 super(TestNAT64, self).tearDown()
6934 if not self.vpp_dead:
6935 self.logger.info(self.vapi.cli("show nat64 pool"))
6936 self.logger.info(self.vapi.cli("show nat64 interfaces"))
Matus Fabian428dc912017-06-21 06:15:18 -07006937 self.logger.info(self.vapi.cli("show nat64 prefix"))
Matus Fabianab9a59c2017-08-16 05:37:36 -07006938 self.logger.info(self.vapi.cli("show nat64 bib all"))
6939 self.logger.info(self.vapi.cli("show nat64 session table all"))
Matus Fabianefcd1e92017-08-15 06:59:19 -07006940 self.logger.info(self.vapi.cli("show nat virtual-reassembly"))
Matus Fabian06596c52017-06-06 04:53:28 -07006941 self.clear_nat64()
6942
Matus Fabian8ebe6252017-11-06 05:04:53 -08006943
6944class TestDSlite(MethodHolder):
6945 """ DS-Lite Test Cases """
6946
6947 @classmethod
6948 def setUpClass(cls):
6949 super(TestDSlite, cls).setUpClass()
6950
6951 try:
6952 cls.nat_addr = '10.0.0.3'
6953 cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
6954
6955 cls.create_pg_interfaces(range(2))
6956 cls.pg0.admin_up()
6957 cls.pg0.config_ip4()
6958 cls.pg0.resolve_arp()
6959 cls.pg1.admin_up()
6960 cls.pg1.config_ip6()
6961 cls.pg1.generate_remote_hosts(2)
6962 cls.pg1.configure_ipv6_neighbors()
6963
6964 except Exception:
6965 super(TestDSlite, cls).tearDownClass()
6966 raise
6967
6968 def test_dslite(self):
6969 """ Test DS-Lite """
Matus Fabian69ce30d2018-08-22 01:27:10 -07006970 nat_config = self.vapi.nat_show_config()
6971 self.assertEqual(0, nat_config.dslite_ce)
6972
Matus Fabian8ebe6252017-11-06 05:04:53 -08006973 self.vapi.dslite_add_del_pool_addr_range(self.nat_addr_n,
6974 self.nat_addr_n)
6975 aftr_ip4 = '192.0.0.1'
6976 aftr_ip4_n = socket.inet_pton(socket.AF_INET, aftr_ip4)
6977 aftr_ip6 = '2001:db8:85a3::8a2e:370:1'
6978 aftr_ip6_n = socket.inet_pton(socket.AF_INET6, aftr_ip6)
6979 self.vapi.dslite_set_aftr_addr(aftr_ip6_n, aftr_ip4_n)
6980
6981 # UDP
6982 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
6983 IPv6(dst=aftr_ip6, src=self.pg1.remote_hosts[0].ip6) /
6984 IP(dst=self.pg0.remote_ip4, src='192.168.1.1') /
6985 UDP(sport=20000, dport=10000))
6986 self.pg1.add_stream(p)
6987 self.pg_enable_capture(self.pg_interfaces)
6988 self.pg_start()
6989 capture = self.pg0.get_capture(1)
6990 capture = capture[0]
6991 self.assertFalse(capture.haslayer(IPv6))
6992 self.assertEqual(capture[IP].src, self.nat_addr)
6993 self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
6994 self.assertNotEqual(capture[UDP].sport, 20000)
6995 self.assertEqual(capture[UDP].dport, 10000)
Klement Sekerad81ae412018-05-16 10:52:54 +02006996 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08006997 out_port = capture[UDP].sport
6998
6999 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7000 IP(dst=self.nat_addr, src=self.pg0.remote_ip4) /
7001 UDP(sport=10000, dport=out_port))
7002 self.pg0.add_stream(p)
7003 self.pg_enable_capture(self.pg_interfaces)
7004 self.pg_start()
7005 capture = self.pg1.get_capture(1)
7006 capture = capture[0]
7007 self.assertEqual(capture[IPv6].src, aftr_ip6)
7008 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[0].ip6)
7009 self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
7010 self.assertEqual(capture[IP].dst, '192.168.1.1')
7011 self.assertEqual(capture[UDP].sport, 10000)
7012 self.assertEqual(capture[UDP].dport, 20000)
Klement Sekerad81ae412018-05-16 10:52:54 +02007013 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08007014
7015 # TCP
7016 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
7017 IPv6(dst=aftr_ip6, src=self.pg1.remote_hosts[1].ip6) /
7018 IP(dst=self.pg0.remote_ip4, src='192.168.1.1') /
7019 TCP(sport=20001, dport=10001))
7020 self.pg1.add_stream(p)
7021 self.pg_enable_capture(self.pg_interfaces)
7022 self.pg_start()
7023 capture = self.pg0.get_capture(1)
7024 capture = capture[0]
7025 self.assertFalse(capture.haslayer(IPv6))
7026 self.assertEqual(capture[IP].src, self.nat_addr)
7027 self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
7028 self.assertNotEqual(capture[TCP].sport, 20001)
7029 self.assertEqual(capture[TCP].dport, 10001)
Klement Sekerad81ae412018-05-16 10:52:54 +02007030 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08007031 out_port = capture[TCP].sport
7032
7033 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7034 IP(dst=self.nat_addr, src=self.pg0.remote_ip4) /
7035 TCP(sport=10001, dport=out_port))
7036 self.pg0.add_stream(p)
7037 self.pg_enable_capture(self.pg_interfaces)
7038 self.pg_start()
7039 capture = self.pg1.get_capture(1)
7040 capture = capture[0]
7041 self.assertEqual(capture[IPv6].src, aftr_ip6)
7042 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[1].ip6)
7043 self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
7044 self.assertEqual(capture[IP].dst, '192.168.1.1')
7045 self.assertEqual(capture[TCP].sport, 10001)
7046 self.assertEqual(capture[TCP].dport, 20001)
Klement Sekerad81ae412018-05-16 10:52:54 +02007047 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08007048
7049 # ICMP
7050 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
7051 IPv6(dst=aftr_ip6, src=self.pg1.remote_hosts[1].ip6) /
7052 IP(dst=self.pg0.remote_ip4, src='192.168.1.1') /
7053 ICMP(id=4000, type='echo-request'))
7054 self.pg1.add_stream(p)
7055 self.pg_enable_capture(self.pg_interfaces)
7056 self.pg_start()
7057 capture = self.pg0.get_capture(1)
7058 capture = capture[0]
7059 self.assertFalse(capture.haslayer(IPv6))
7060 self.assertEqual(capture[IP].src, self.nat_addr)
7061 self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
7062 self.assertNotEqual(capture[ICMP].id, 4000)
Klement Sekerad81ae412018-05-16 10:52:54 +02007063 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08007064 out_id = capture[ICMP].id
7065
7066 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7067 IP(dst=self.nat_addr, src=self.pg0.remote_ip4) /
7068 ICMP(id=out_id, type='echo-reply'))
7069 self.pg0.add_stream(p)
7070 self.pg_enable_capture(self.pg_interfaces)
7071 self.pg_start()
7072 capture = self.pg1.get_capture(1)
7073 capture = capture[0]
7074 self.assertEqual(capture[IPv6].src, aftr_ip6)
7075 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[1].ip6)
7076 self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
7077 self.assertEqual(capture[IP].dst, '192.168.1.1')
7078 self.assertEqual(capture[ICMP].id, 4000)
Klement Sekerad81ae412018-05-16 10:52:54 +02007079 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08007080
Matus Fabian331acc62017-12-08 03:38:51 -08007081 # ping DS-Lite AFTR tunnel endpoint address
7082 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
7083 IPv6(src=self.pg1.remote_hosts[1].ip6, dst=aftr_ip6) /
7084 ICMPv6EchoRequest())
7085 self.pg1.add_stream(p)
7086 self.pg_enable_capture(self.pg_interfaces)
7087 self.pg_start()
7088 capture = self.pg1.get_capture(1)
7089 self.assertEqual(1, len(capture))
7090 capture = capture[0]
7091 self.assertEqual(capture[IPv6].src, aftr_ip6)
7092 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[1].ip6)
7093 self.assertTrue(capture.haslayer(ICMPv6EchoReply))
7094
Matus Fabian8ebe6252017-11-06 05:04:53 -08007095 def tearDown(self):
7096 super(TestDSlite, self).tearDown()
7097 if not self.vpp_dead:
7098 self.logger.info(self.vapi.cli("show dslite pool"))
7099 self.logger.info(
7100 self.vapi.cli("show dslite aftr-tunnel-endpoint-address"))
7101 self.logger.info(self.vapi.cli("show dslite sessions"))
7102
Juraj Slobodac5c6a332018-01-09 16:08:32 +01007103
7104class TestDSliteCE(MethodHolder):
7105 """ DS-Lite CE Test Cases """
7106
7107 @classmethod
7108 def setUpConstants(cls):
7109 super(TestDSliteCE, cls).setUpConstants()
7110 cls.vpp_cmdline.extend(["nat", "{", "dslite ce", "}"])
7111
7112 @classmethod
7113 def setUpClass(cls):
7114 super(TestDSliteCE, cls).setUpClass()
7115
7116 try:
7117 cls.create_pg_interfaces(range(2))
7118 cls.pg0.admin_up()
7119 cls.pg0.config_ip4()
7120 cls.pg0.resolve_arp()
7121 cls.pg1.admin_up()
7122 cls.pg1.config_ip6()
7123 cls.pg1.generate_remote_hosts(1)
7124 cls.pg1.configure_ipv6_neighbors()
7125
7126 except Exception:
7127 super(TestDSliteCE, cls).tearDownClass()
7128 raise
7129
7130 def test_dslite_ce(self):
7131 """ Test DS-Lite CE """
7132
Matus Fabian69ce30d2018-08-22 01:27:10 -07007133 nat_config = self.vapi.nat_show_config()
7134 self.assertEqual(1, nat_config.dslite_ce)
7135
Juraj Slobodac5c6a332018-01-09 16:08:32 +01007136 b4_ip4 = '192.0.0.2'
7137 b4_ip4_n = socket.inet_pton(socket.AF_INET, b4_ip4)
7138 b4_ip6 = '2001:db8:62aa::375e:f4c1:1'
7139 b4_ip6_n = socket.inet_pton(socket.AF_INET6, b4_ip6)
7140 self.vapi.dslite_set_b4_addr(b4_ip6_n, b4_ip4_n)
7141
7142 aftr_ip4 = '192.0.0.1'
7143 aftr_ip4_n = socket.inet_pton(socket.AF_INET, aftr_ip4)
7144 aftr_ip6 = '2001:db8:85a3::8a2e:370:1'
7145 aftr_ip6_n = socket.inet_pton(socket.AF_INET6, aftr_ip6)
7146 self.vapi.dslite_set_aftr_addr(aftr_ip6_n, aftr_ip4_n)
7147
7148 self.vapi.ip_add_del_route(dst_address=aftr_ip6_n,
7149 dst_address_length=128,
7150 next_hop_address=self.pg1.remote_ip6n,
7151 next_hop_sw_if_index=self.pg1.sw_if_index,
7152 is_ipv6=1)
7153
7154 # UDP encapsulation
7155 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7156 IP(dst=self.pg1.remote_ip4, src=self.pg0.remote_ip4) /
7157 UDP(sport=10000, dport=20000))
7158 self.pg0.add_stream(p)
7159 self.pg_enable_capture(self.pg_interfaces)
7160 self.pg_start()
7161 capture = self.pg1.get_capture(1)
7162 capture = capture[0]
7163 self.assertEqual(capture[IPv6].src, b4_ip6)
7164 self.assertEqual(capture[IPv6].dst, aftr_ip6)
7165 self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
7166 self.assertEqual(capture[IP].dst, self.pg1.remote_ip4)
7167 self.assertEqual(capture[UDP].sport, 10000)
7168 self.assertEqual(capture[UDP].dport, 20000)
Klement Sekerad81ae412018-05-16 10:52:54 +02007169 self.assert_packet_checksums_valid(capture)
Juraj Slobodac5c6a332018-01-09 16:08:32 +01007170
7171 # UDP decapsulation
7172 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
7173 IPv6(dst=b4_ip6, src=aftr_ip6) /
7174 IP(dst=self.pg0.remote_ip4, src=self.pg1.remote_ip4) /
7175 UDP(sport=20000, dport=10000))
7176 self.pg1.add_stream(p)
7177 self.pg_enable_capture(self.pg_interfaces)
7178 self.pg_start()
7179 capture = self.pg0.get_capture(1)
7180 capture = capture[0]
7181 self.assertFalse(capture.haslayer(IPv6))
7182 self.assertEqual(capture[IP].src, self.pg1.remote_ip4)
7183 self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
7184 self.assertEqual(capture[UDP].sport, 20000)
7185 self.assertEqual(capture[UDP].dport, 10000)
Klement Sekerad81ae412018-05-16 10:52:54 +02007186 self.assert_packet_checksums_valid(capture)
Juraj Slobodac5c6a332018-01-09 16:08:32 +01007187
7188 # ping DS-Lite B4 tunnel endpoint address
7189 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
7190 IPv6(src=self.pg1.remote_hosts[0].ip6, dst=b4_ip6) /
7191 ICMPv6EchoRequest())
7192 self.pg1.add_stream(p)
7193 self.pg_enable_capture(self.pg_interfaces)
7194 self.pg_start()
7195 capture = self.pg1.get_capture(1)
7196 self.assertEqual(1, len(capture))
7197 capture = capture[0]
7198 self.assertEqual(capture[IPv6].src, b4_ip6)
7199 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[0].ip6)
7200 self.assertTrue(capture.haslayer(ICMPv6EchoReply))
7201
7202 def tearDown(self):
7203 super(TestDSliteCE, self).tearDown()
7204 if not self.vpp_dead:
7205 self.logger.info(
7206 self.vapi.cli("show dslite aftr-tunnel-endpoint-address"))
7207 self.logger.info(
7208 self.vapi.cli("show dslite b4-tunnel-endpoint-address"))
7209
Matus Fabianf2a23cc2018-01-22 03:41:53 -08007210
7211class TestNAT66(MethodHolder):
7212 """ NAT66 Test Cases """
7213
7214 @classmethod
7215 def setUpClass(cls):
7216 super(TestNAT66, cls).setUpClass()
7217
7218 try:
7219 cls.nat_addr = 'fd01:ff::2'
7220 cls.nat_addr_n = socket.inet_pton(socket.AF_INET6, cls.nat_addr)
7221
7222 cls.create_pg_interfaces(range(2))
7223 cls.interfaces = list(cls.pg_interfaces)
7224
7225 for i in cls.interfaces:
7226 i.admin_up()
7227 i.config_ip6()
7228 i.configure_ipv6_neighbors()
7229
7230 except Exception:
7231 super(TestNAT66, cls).tearDownClass()
7232 raise
7233
7234 def test_static(self):
7235 """ 1:1 NAT66 test """
7236 self.vapi.nat66_add_del_interface(self.pg0.sw_if_index)
7237 self.vapi.nat66_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7238 self.vapi.nat66_add_del_static_mapping(self.pg0.remote_ip6n,
7239 self.nat_addr_n)
7240
7241 # in2out
7242 pkts = []
7243 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7244 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
7245 TCP())
7246 pkts.append(p)
7247 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7248 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
7249 UDP())
7250 pkts.append(p)
7251 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7252 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
7253 ICMPv6EchoRequest())
7254 pkts.append(p)
7255 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7256 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
7257 GRE() / IP() / TCP())
7258 pkts.append(p)
7259 self.pg0.add_stream(pkts)
7260 self.pg_enable_capture(self.pg_interfaces)
7261 self.pg_start()
7262 capture = self.pg1.get_capture(len(pkts))
7263 for packet in capture:
7264 try:
7265 self.assertEqual(packet[IPv6].src, self.nat_addr)
7266 self.assertEqual(packet[IPv6].dst, self.pg1.remote_ip6)
Klement Sekerad81ae412018-05-16 10:52:54 +02007267 self.assert_packet_checksums_valid(packet)
Matus Fabianf2a23cc2018-01-22 03:41:53 -08007268 except:
7269 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7270 raise
7271
7272 # out2in
7273 pkts = []
7274 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
7275 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
7276 TCP())
7277 pkts.append(p)
7278 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
7279 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
7280 UDP())
7281 pkts.append(p)
7282 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
7283 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
7284 ICMPv6EchoReply())
7285 pkts.append(p)
7286 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
7287 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
7288 GRE() / IP() / TCP())
7289 pkts.append(p)
7290 self.pg1.add_stream(pkts)
7291 self.pg_enable_capture(self.pg_interfaces)
7292 self.pg_start()
7293 capture = self.pg0.get_capture(len(pkts))
7294 for packet in capture:
7295 try:
7296 self.assertEqual(packet[IPv6].src, self.pg1.remote_ip6)
7297 self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
Klement Sekerad81ae412018-05-16 10:52:54 +02007298 self.assert_packet_checksums_valid(packet)
Matus Fabianf2a23cc2018-01-22 03:41:53 -08007299 except:
7300 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7301 raise
7302
7303 sm = self.vapi.nat66_static_mapping_dump()
7304 self.assertEqual(len(sm), 1)
7305 self.assertEqual(sm[0].total_pkts, 8)
7306
Juraj Sloboda9341e342018-04-13 12:00:46 +02007307 def test_check_no_translate(self):
7308 """ NAT66 translate only when egress interface is outside interface """
7309 self.vapi.nat66_add_del_interface(self.pg0.sw_if_index)
7310 self.vapi.nat66_add_del_interface(self.pg1.sw_if_index)
7311 self.vapi.nat66_add_del_static_mapping(self.pg0.remote_ip6n,
7312 self.nat_addr_n)
7313
7314 # in2out
7315 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7316 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
7317 UDP())
7318 self.pg0.add_stream([p])
7319 self.pg_enable_capture(self.pg_interfaces)
7320 self.pg_start()
7321 capture = self.pg1.get_capture(1)
7322 packet = capture[0]
7323 try:
7324 self.assertEqual(packet[IPv6].src, self.pg0.remote_ip6)
7325 self.assertEqual(packet[IPv6].dst, self.pg1.remote_ip6)
7326 except:
7327 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7328 raise
7329
Matus Fabianf2a23cc2018-01-22 03:41:53 -08007330 def clear_nat66(self):
7331 """
7332 Clear NAT66 configuration.
7333 """
7334 interfaces = self.vapi.nat66_interface_dump()
7335 for intf in interfaces:
7336 self.vapi.nat66_add_del_interface(intf.sw_if_index,
7337 intf.is_inside,
7338 is_add=0)
7339
7340 static_mappings = self.vapi.nat66_static_mapping_dump()
7341 for sm in static_mappings:
7342 self.vapi.nat66_add_del_static_mapping(sm.local_ip_address,
7343 sm.external_ip_address,
7344 sm.vrf_id,
7345 is_add=0)
7346
7347 def tearDown(self):
7348 super(TestNAT66, self).tearDown()
7349 if not self.vpp_dead:
7350 self.logger.info(self.vapi.cli("show nat66 interfaces"))
7351 self.logger.info(self.vapi.cli("show nat66 static mappings"))
7352 self.clear_nat66()
7353
Klement Sekerad81ae412018-05-16 10:52:54 +02007354
Matus Fabiande886752016-12-07 03:38:19 -08007355if __name__ == '__main__':
7356 unittest.main(testRunner=VppTestRunner)