blob: b873074eccce6f1f5d8772339a3a967347233e85 [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 random
Matus Fabiande886752016-12-07 03:38:19 -08007
Martin Gálik977c1cb2017-03-30 23:21:51 -07008from framework import VppTestCase, VppTestRunner, running_extended_tests
Matus Fabiande886752016-12-07 03:38:19 -08009from scapy.layers.inet import IP, TCP, UDP, ICMP
Juraj Slobodab33f4132017-02-08 23:54:21 -080010from scapy.layers.inet import IPerror, TCPerror, UDPerror, ICMPerror
Juraj Slobodac746a152018-07-09 02:36:37 +020011from scapy.layers.inet6 import IPv6, ICMPv6EchoRequest, ICMPv6EchoReply, \
Paul Vinciguerra978aa642018-11-24 22:19:12 -080012 ICMPv6ND_NS, ICMPv6ND_NA, ICMPv6NDOptDstLLAddr, fragment6
Matus Fabianefcd1e92017-08-15 06:59:19 -070013from scapy.layers.inet6 import ICMPv6DestUnreach, IPerror6, IPv6ExtHdrFragment
Matus Fabian328dbc82017-06-19 04:28:04 -070014from scapy.layers.l2 import Ether, ARP, GRE
Matus Fabianeea28d72017-01-13 04:15:54 -080015from scapy.data import IP_PROTOS
Matus Fabianefcd1e92017-08-15 06:59:19 -070016from scapy.packet import bind_layers, Raw
Klement Sekera9225dee2016-12-12 08:36:58 +010017from util import ppp
Matus Fabianeea28d72017-01-13 04:15:54 -080018from ipfix import IPFIX, Set, Template, Data, IPFIXDecoder
Martin Gálik977c1cb2017-03-30 23:21:51 -070019from time import sleep
Matus Fabian704018c2017-09-04 02:17:18 -070020from util import ip4_range
Ole Troan7f991832018-12-06 17:35:12 +010021from vpp_mac import mactobinary
Matus Fabianad1f3e12018-11-28 21:26:34 -080022from syslog_rfc5424_parser import SyslogMessage, ParseError
23from syslog_rfc5424_parser.constants import SyslogFacility, SyslogSeverity
24from vpp_papi_provider import SYSLOG_SEVERITY
Ole Troan7f991832018-12-06 17:35:12 +010025from io import BytesIO
Matus Fabiande886752016-12-07 03:38:19 -080026
27
Martin Gálikd7f75cd2017-03-27 06:02:47 -070028class MethodHolder(VppTestCase):
Matus Fabian2ba92e32017-08-21 07:05:03 -070029 """ NAT create capture and verify method holder """
Matus Fabiande886752016-12-07 03:38:19 -080030
Matus Fabiana6110b62018-06-13 05:39:07 -070031 def clear_nat44(self):
32 """
33 Clear NAT44 configuration.
34 """
35 if hasattr(self, 'pg7') and hasattr(self, 'pg8'):
36 # I found no elegant way to do this
37 self.vapi.ip_add_del_route(
38 dst_address=self.pg7.remote_ip4n,
39 dst_address_length=32,
40 next_hop_address=self.pg7.remote_ip4n,
41 next_hop_sw_if_index=self.pg7.sw_if_index,
42 is_add=0)
43 self.vapi.ip_add_del_route(
44 dst_address=self.pg8.remote_ip4n,
45 dst_address_length=32,
46 next_hop_address=self.pg8.remote_ip4n,
47 next_hop_sw_if_index=self.pg8.sw_if_index,
48 is_add=0)
49
50 for intf in [self.pg7, self.pg8]:
51 neighbors = self.vapi.ip_neighbor_dump(intf.sw_if_index)
52 for n in neighbors:
53 self.vapi.ip_neighbor_add_del(intf.sw_if_index,
54 n.mac_address,
55 n.ip_address,
56 is_add=0)
57
58 if self.pg7.has_ip4_config:
59 self.pg7.unconfig_ip4()
60
61 self.vapi.nat44_forwarding_enable_disable(0)
62
63 interfaces = self.vapi.nat44_interface_addr_dump()
64 for intf in interfaces:
65 self.vapi.nat44_add_interface_addr(intf.sw_if_index,
66 twice_nat=intf.twice_nat,
67 is_add=0)
68
69 self.vapi.nat_ipfix(enable=0, src_port=self.ipfix_src_port,
70 domain_id=self.ipfix_domain_id)
71 self.ipfix_src_port = 4739
72 self.ipfix_domain_id = 1
73
Matus Fabianad1f3e12018-11-28 21:26:34 -080074 self.vapi.syslog_set_filter(SYSLOG_SEVERITY.EMERG)
75
Matus Fabiana6110b62018-06-13 05:39:07 -070076 interfaces = self.vapi.nat44_interface_dump()
77 for intf in interfaces:
78 if intf.is_inside > 1:
79 self.vapi.nat44_interface_add_del_feature(intf.sw_if_index,
80 0,
81 is_add=0)
82 self.vapi.nat44_interface_add_del_feature(intf.sw_if_index,
83 intf.is_inside,
84 is_add=0)
85
86 interfaces = self.vapi.nat44_interface_output_feature_dump()
87 for intf in interfaces:
88 self.vapi.nat44_interface_add_del_output_feature(intf.sw_if_index,
89 intf.is_inside,
90 is_add=0)
91
92 static_mappings = self.vapi.nat44_static_mapping_dump()
93 for sm in static_mappings:
94 self.vapi.nat44_add_del_static_mapping(
95 sm.local_ip_address,
96 sm.external_ip_address,
97 local_port=sm.local_port,
98 external_port=sm.external_port,
99 addr_only=sm.addr_only,
100 vrf_id=sm.vrf_id,
101 protocol=sm.protocol,
102 twice_nat=sm.twice_nat,
103 self_twice_nat=sm.self_twice_nat,
104 out2in_only=sm.out2in_only,
105 tag=sm.tag,
106 external_sw_if_index=sm.external_sw_if_index,
107 is_add=0)
108
109 lb_static_mappings = self.vapi.nat44_lb_static_mapping_dump()
110 for lb_sm in lb_static_mappings:
111 self.vapi.nat44_add_del_lb_static_mapping(
112 lb_sm.external_addr,
113 lb_sm.external_port,
114 lb_sm.protocol,
Matus Fabiana6110b62018-06-13 05:39:07 -0700115 twice_nat=lb_sm.twice_nat,
116 self_twice_nat=lb_sm.self_twice_nat,
117 out2in_only=lb_sm.out2in_only,
118 tag=lb_sm.tag,
119 is_add=0,
120 local_num=0,
121 locals=[])
122
123 identity_mappings = self.vapi.nat44_identity_mapping_dump()
124 for id_m in identity_mappings:
125 self.vapi.nat44_add_del_identity_mapping(
126 addr_only=id_m.addr_only,
127 ip=id_m.ip_address,
128 port=id_m.port,
129 sw_if_index=id_m.sw_if_index,
130 vrf_id=id_m.vrf_id,
131 protocol=id_m.protocol,
132 is_add=0)
133
134 adresses = self.vapi.nat44_address_dump()
135 for addr in adresses:
136 self.vapi.nat44_add_del_address_range(addr.ip_address,
137 addr.ip_address,
138 twice_nat=addr.twice_nat,
139 is_add=0)
140
141 self.vapi.nat_set_reass()
142 self.vapi.nat_set_reass(is_ip6=1)
Matus Fabian68ba8802018-08-08 05:52:47 -0700143 self.verify_no_nat44_user()
Matus Fabian878c6462018-08-23 00:33:35 -0700144 self.vapi.nat_set_timeouts()
Matus Fabian5d28c7a2018-09-04 03:55:45 -0700145 self.vapi.nat_set_addr_and_port_alloc_alg()
Matus Fabianbb4e0222018-09-13 02:36:25 -0700146 self.vapi.nat_set_mss_clamping()
Matus Fabiana6110b62018-06-13 05:39:07 -0700147
148 def nat44_add_static_mapping(self, local_ip, external_ip='0.0.0.0',
149 local_port=0, external_port=0, vrf_id=0,
150 is_add=1, external_sw_if_index=0xFFFFFFFF,
151 proto=0, twice_nat=0, self_twice_nat=0,
152 out2in_only=0, tag=""):
153 """
154 Add/delete NAT44 static mapping
155
156 :param local_ip: Local IP address
157 :param external_ip: External IP address
158 :param local_port: Local port number (Optional)
159 :param external_port: External port number (Optional)
160 :param vrf_id: VRF ID (Default 0)
161 :param is_add: 1 if add, 0 if delete (Default add)
162 :param external_sw_if_index: External interface instead of IP address
163 :param proto: IP protocol (Mandatory if port specified)
164 :param twice_nat: 1 if translate external host address and port
165 :param self_twice_nat: 1 if translate external host address and port
166 whenever external host address equals
167 local address of internal host
168 :param out2in_only: if 1 rule is matching only out2in direction
169 :param tag: Opaque string tag
170 """
171 addr_only = 1
172 if local_port and external_port:
173 addr_only = 0
174 l_ip = socket.inet_pton(socket.AF_INET, local_ip)
175 e_ip = socket.inet_pton(socket.AF_INET, external_ip)
176 self.vapi.nat44_add_del_static_mapping(
177 l_ip,
178 e_ip,
179 external_sw_if_index,
180 local_port,
181 external_port,
182 addr_only,
183 vrf_id,
184 proto,
185 twice_nat,
186 self_twice_nat,
187 out2in_only,
188 tag,
189 is_add)
190
191 def nat44_add_address(self, ip, is_add=1, vrf_id=0xFFFFFFFF, twice_nat=0):
192 """
193 Add/delete NAT44 address
194
195 :param ip: IP address
196 :param is_add: 1 if add, 0 if delete (Default add)
197 :param twice_nat: twice NAT address for extenal hosts
198 """
199 nat_addr = socket.inet_pton(socket.AF_INET, ip)
200 self.vapi.nat44_add_del_address_range(nat_addr, nat_addr, is_add,
201 vrf_id=vrf_id,
202 twice_nat=twice_nat)
203
Juraj Slobodacba69362017-12-19 02:09:32 +0100204 def create_stream_in(self, in_if, out_if, dst_ip=None, ttl=64):
Matus Fabiande886752016-12-07 03:38:19 -0800205 """
206 Create packet stream for inside network
207
208 :param in_if: Inside interface
209 :param out_if: Outside interface
Juraj Slobodacba69362017-12-19 02:09:32 +0100210 :param dst_ip: Destination address
Juraj Slobodab33f4132017-02-08 23:54:21 -0800211 :param ttl: TTL of generated packets
Matus Fabiande886752016-12-07 03:38:19 -0800212 """
Juraj Slobodacba69362017-12-19 02:09:32 +0100213 if dst_ip is None:
214 dst_ip = out_if.remote_ip4
215
Matus Fabiande886752016-12-07 03:38:19 -0800216 pkts = []
217 # TCP
218 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
Juraj Slobodacba69362017-12-19 02:09:32 +0100219 IP(src=in_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Matus Fabian06596c52017-06-06 04:53:28 -0700220 TCP(sport=self.tcp_port_in, dport=20))
Matus Fabiande886752016-12-07 03:38:19 -0800221 pkts.append(p)
222
223 # UDP
224 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
Juraj Slobodacba69362017-12-19 02:09:32 +0100225 IP(src=in_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Matus Fabian06596c52017-06-06 04:53:28 -0700226 UDP(sport=self.udp_port_in, dport=20))
Matus Fabiande886752016-12-07 03:38:19 -0800227 pkts.append(p)
228
229 # ICMP
230 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
Juraj Slobodacba69362017-12-19 02:09:32 +0100231 IP(src=in_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Matus Fabiande886752016-12-07 03:38:19 -0800232 ICMP(id=self.icmp_id_in, type='echo-request'))
233 pkts.append(p)
234
235 return pkts
236
Matus Fabian428dc912017-06-21 06:15:18 -0700237 def compose_ip6(self, ip4, pref, plen):
238 """
239 Compose IPv4-embedded IPv6 addresses
240
241 :param ip4: IPv4 address
242 :param pref: IPv6 prefix
243 :param plen: IPv6 prefix length
244 :returns: IPv4-embedded IPv6 addresses
245 """
246 pref_n = list(socket.inet_pton(socket.AF_INET6, pref))
247 ip4_n = list(socket.inet_pton(socket.AF_INET, ip4))
248 if plen == 32:
249 pref_n[4] = ip4_n[0]
250 pref_n[5] = ip4_n[1]
251 pref_n[6] = ip4_n[2]
252 pref_n[7] = ip4_n[3]
253 elif plen == 40:
254 pref_n[5] = ip4_n[0]
255 pref_n[6] = ip4_n[1]
256 pref_n[7] = ip4_n[2]
257 pref_n[9] = ip4_n[3]
258 elif plen == 48:
259 pref_n[6] = ip4_n[0]
260 pref_n[7] = ip4_n[1]
261 pref_n[9] = ip4_n[2]
262 pref_n[10] = ip4_n[3]
263 elif plen == 56:
264 pref_n[7] = ip4_n[0]
265 pref_n[9] = ip4_n[1]
266 pref_n[10] = ip4_n[2]
267 pref_n[11] = ip4_n[3]
268 elif plen == 64:
269 pref_n[9] = ip4_n[0]
270 pref_n[10] = ip4_n[1]
271 pref_n[11] = ip4_n[2]
272 pref_n[12] = ip4_n[3]
273 elif plen == 96:
274 pref_n[12] = ip4_n[0]
275 pref_n[13] = ip4_n[1]
276 pref_n[14] = ip4_n[2]
277 pref_n[15] = ip4_n[3]
278 return socket.inet_ntop(socket.AF_INET6, ''.join(pref_n))
279
Juraj Slobodacba69362017-12-19 02:09:32 +0100280 def extract_ip4(self, ip6, plen):
281 """
282 Extract IPv4 address embedded in IPv6 addresses
283
284 :param ip6: IPv6 address
285 :param plen: IPv6 prefix length
286 :returns: extracted IPv4 address
287 """
288 ip6_n = list(socket.inet_pton(socket.AF_INET6, ip6))
289 ip4_n = [None] * 4
290 if plen == 32:
291 ip4_n[0] = ip6_n[4]
292 ip4_n[1] = ip6_n[5]
293 ip4_n[2] = ip6_n[6]
294 ip4_n[3] = ip6_n[7]
295 elif plen == 40:
296 ip4_n[0] = ip6_n[5]
297 ip4_n[1] = ip6_n[6]
298 ip4_n[2] = ip6_n[7]
299 ip4_n[3] = ip6_n[9]
300 elif plen == 48:
301 ip4_n[0] = ip6_n[6]
302 ip4_n[1] = ip6_n[7]
303 ip4_n[2] = ip6_n[9]
304 ip4_n[3] = ip6_n[10]
305 elif plen == 56:
306 ip4_n[0] = ip6_n[7]
307 ip4_n[1] = ip6_n[9]
308 ip4_n[2] = ip6_n[10]
309 ip4_n[3] = ip6_n[11]
310 elif plen == 64:
311 ip4_n[0] = ip6_n[9]
312 ip4_n[1] = ip6_n[10]
313 ip4_n[2] = ip6_n[11]
314 ip4_n[3] = ip6_n[12]
315 elif plen == 96:
316 ip4_n[0] = ip6_n[12]
317 ip4_n[1] = ip6_n[13]
318 ip4_n[2] = ip6_n[14]
319 ip4_n[3] = ip6_n[15]
320 return socket.inet_ntop(socket.AF_INET, ''.join(ip4_n))
321
Matus Fabian428dc912017-06-21 06:15:18 -0700322 def create_stream_in_ip6(self, in_if, out_if, hlim=64, pref=None, plen=0):
Matus Fabian06596c52017-06-06 04:53:28 -0700323 """
324 Create IPv6 packet stream for inside network
325
326 :param in_if: Inside interface
327 :param out_if: Outside interface
328 :param ttl: Hop Limit of generated packets
Matus Fabian428dc912017-06-21 06:15:18 -0700329 :param pref: NAT64 prefix
330 :param plen: NAT64 prefix length
Matus Fabian06596c52017-06-06 04:53:28 -0700331 """
332 pkts = []
Matus Fabian428dc912017-06-21 06:15:18 -0700333 if pref is None:
334 dst = ''.join(['64:ff9b::', out_if.remote_ip4])
335 else:
336 dst = self.compose_ip6(out_if.remote_ip4, pref, plen)
337
Matus Fabian06596c52017-06-06 04:53:28 -0700338 # TCP
339 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
340 IPv6(src=in_if.remote_ip6, dst=dst, hlim=hlim) /
341 TCP(sport=self.tcp_port_in, dport=20))
342 pkts.append(p)
343
344 # UDP
345 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
346 IPv6(src=in_if.remote_ip6, dst=dst, hlim=hlim) /
347 UDP(sport=self.udp_port_in, dport=20))
348 pkts.append(p)
349
350 # ICMP
351 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
352 IPv6(src=in_if.remote_ip6, dst=dst, hlim=hlim) /
353 ICMPv6EchoRequest(id=self.icmp_id_in))
354 pkts.append(p)
355
356 return pkts
357
Juraj Sloboda7b929792017-11-23 13:20:48 +0100358 def create_stream_out(self, out_if, dst_ip=None, ttl=64,
359 use_inside_ports=False):
Matus Fabiande886752016-12-07 03:38:19 -0800360 """
361 Create packet stream for outside network
362
363 :param out_if: Outside interface
Matus Fabian2ba92e32017-08-21 07:05:03 -0700364 :param dst_ip: Destination IP address (Default use global NAT address)
Juraj Slobodab33f4132017-02-08 23:54:21 -0800365 :param ttl: TTL of generated packets
Juraj Sloboda7b929792017-11-23 13:20:48 +0100366 :param use_inside_ports: Use inside NAT ports as destination ports
367 instead of outside ports
Matus Fabiande886752016-12-07 03:38:19 -0800368 """
369 if dst_ip is None:
Matus Fabian2ba92e32017-08-21 07:05:03 -0700370 dst_ip = self.nat_addr
Juraj Sloboda7b929792017-11-23 13:20:48 +0100371 if not use_inside_ports:
372 tcp_port = self.tcp_port_out
373 udp_port = self.udp_port_out
374 icmp_id = self.icmp_id_out
375 else:
376 tcp_port = self.tcp_port_in
377 udp_port = self.udp_port_in
378 icmp_id = self.icmp_id_in
Matus Fabiande886752016-12-07 03:38:19 -0800379 pkts = []
380 # TCP
381 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
Juraj Slobodab33f4132017-02-08 23:54:21 -0800382 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Juraj Sloboda7b929792017-11-23 13:20:48 +0100383 TCP(dport=tcp_port, sport=20))
Matus Fabiande886752016-12-07 03:38:19 -0800384 pkts.append(p)
385
386 # UDP
387 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
Juraj Slobodab33f4132017-02-08 23:54:21 -0800388 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Juraj Sloboda7b929792017-11-23 13:20:48 +0100389 UDP(dport=udp_port, sport=20))
Matus Fabiande886752016-12-07 03:38:19 -0800390 pkts.append(p)
391
392 # ICMP
393 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
Juraj Slobodab33f4132017-02-08 23:54:21 -0800394 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Juraj Sloboda7b929792017-11-23 13:20:48 +0100395 ICMP(id=icmp_id, type='echo-reply'))
Matus Fabiande886752016-12-07 03:38:19 -0800396 pkts.append(p)
397
398 return pkts
399
Juraj Slobodacba69362017-12-19 02:09:32 +0100400 def create_stream_out_ip6(self, out_if, src_ip, dst_ip, hl=64):
401 """
402 Create packet stream for outside network
403
404 :param out_if: Outside interface
405 :param dst_ip: Destination IP address (Default use global NAT address)
406 :param hl: HL of generated packets
407 """
408 pkts = []
409 # TCP
410 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
411 IPv6(src=src_ip, dst=dst_ip, hlim=hl) /
412 TCP(dport=self.tcp_port_out, sport=20))
413 pkts.append(p)
414
415 # UDP
416 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
417 IPv6(src=src_ip, dst=dst_ip, hlim=hl) /
418 UDP(dport=self.udp_port_out, sport=20))
419 pkts.append(p)
420
421 # ICMP
422 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
423 IPv6(src=src_ip, dst=dst_ip, hlim=hl) /
424 ICMPv6EchoReply(id=self.icmp_id_out))
425 pkts.append(p)
426
427 return pkts
428
Matus Fabiande886752016-12-07 03:38:19 -0800429 def verify_capture_out(self, capture, nat_ip=None, same_port=False,
Matus Fabian05ca4a32018-09-04 23:45:13 -0700430 dst_ip=None, is_ip6=False):
Matus Fabiande886752016-12-07 03:38:19 -0800431 """
432 Verify captured packets on outside network
433
434 :param capture: Captured packets
Matus Fabian2ba92e32017-08-21 07:05:03 -0700435 :param nat_ip: Translated IP address (Default use global NAT address)
Matus Fabiande886752016-12-07 03:38:19 -0800436 :param same_port: Sorce port number is not translated (Default False)
Matus Fabian06596c52017-06-06 04:53:28 -0700437 :param dst_ip: Destination IP address (Default do not verify)
Juraj Slobodacba69362017-12-19 02:09:32 +0100438 :param is_ip6: If L3 protocol is IPv6 (Default False)
Matus Fabiande886752016-12-07 03:38:19 -0800439 """
Juraj Slobodacba69362017-12-19 02:09:32 +0100440 if is_ip6:
441 IP46 = IPv6
442 ICMP46 = ICMPv6EchoRequest
443 else:
444 IP46 = IP
445 ICMP46 = ICMP
Matus Fabiande886752016-12-07 03:38:19 -0800446 if nat_ip is None:
Matus Fabian2ba92e32017-08-21 07:05:03 -0700447 nat_ip = self.nat_addr
Matus Fabiande886752016-12-07 03:38:19 -0800448 for packet in capture:
449 try:
Juraj Slobodacba69362017-12-19 02:09:32 +0100450 if not is_ip6:
Klement Sekerad81ae412018-05-16 10:52:54 +0200451 self.assert_packet_checksums_valid(packet)
Juraj Slobodacba69362017-12-19 02:09:32 +0100452 self.assertEqual(packet[IP46].src, nat_ip)
Matus Fabian06596c52017-06-06 04:53:28 -0700453 if dst_ip is not None:
Juraj Slobodacba69362017-12-19 02:09:32 +0100454 self.assertEqual(packet[IP46].dst, dst_ip)
Matus Fabiande886752016-12-07 03:38:19 -0800455 if packet.haslayer(TCP):
456 if same_port:
457 self.assertEqual(packet[TCP].sport, self.tcp_port_in)
458 else:
Klement Sekerada505f62017-01-04 12:58:53 +0100459 self.assertNotEqual(
460 packet[TCP].sport, self.tcp_port_in)
Matus Fabiande886752016-12-07 03:38:19 -0800461 self.tcp_port_out = packet[TCP].sport
Klement Sekerad81ae412018-05-16 10:52:54 +0200462 self.assert_packet_checksums_valid(packet)
Matus Fabiande886752016-12-07 03:38:19 -0800463 elif packet.haslayer(UDP):
464 if same_port:
465 self.assertEqual(packet[UDP].sport, self.udp_port_in)
466 else:
Klement Sekerada505f62017-01-04 12:58:53 +0100467 self.assertNotEqual(
468 packet[UDP].sport, self.udp_port_in)
Matus Fabiande886752016-12-07 03:38:19 -0800469 self.udp_port_out = packet[UDP].sport
470 else:
471 if same_port:
Juraj Slobodacba69362017-12-19 02:09:32 +0100472 self.assertEqual(packet[ICMP46].id, self.icmp_id_in)
Matus Fabiande886752016-12-07 03:38:19 -0800473 else:
Juraj Slobodacba69362017-12-19 02:09:32 +0100474 self.assertNotEqual(packet[ICMP46].id, self.icmp_id_in)
475 self.icmp_id_out = packet[ICMP46].id
Klement Sekerad81ae412018-05-16 10:52:54 +0200476 self.assert_packet_checksums_valid(packet)
Matus Fabiande886752016-12-07 03:38:19 -0800477 except:
Klement Sekera9225dee2016-12-12 08:36:58 +0100478 self.logger.error(ppp("Unexpected or invalid packet "
479 "(outside network):", packet))
Matus Fabiande886752016-12-07 03:38:19 -0800480 raise
481
Juraj Slobodacba69362017-12-19 02:09:32 +0100482 def verify_capture_out_ip6(self, capture, nat_ip, same_port=False,
Matus Fabian05ca4a32018-09-04 23:45:13 -0700483 dst_ip=None):
Juraj Slobodacba69362017-12-19 02:09:32 +0100484 """
485 Verify captured packets on outside network
486
487 :param capture: Captured packets
488 :param nat_ip: Translated IP address
489 :param same_port: Sorce port number is not translated (Default False)
Juraj Slobodacba69362017-12-19 02:09:32 +0100490 :param dst_ip: Destination IP address (Default do not verify)
491 """
Matus Fabian05ca4a32018-09-04 23:45:13 -0700492 return self.verify_capture_out(capture, nat_ip, same_port, dst_ip,
493 True)
Juraj Slobodacba69362017-12-19 02:09:32 +0100494
Matus Fabian05ca4a32018-09-04 23:45:13 -0700495 def verify_capture_in(self, capture, in_if):
Matus Fabiande886752016-12-07 03:38:19 -0800496 """
497 Verify captured packets on inside network
498
499 :param capture: Captured packets
500 :param in_if: Inside interface
Matus Fabiande886752016-12-07 03:38:19 -0800501 """
Matus Fabiande886752016-12-07 03:38:19 -0800502 for packet in capture:
503 try:
Klement Sekerad81ae412018-05-16 10:52:54 +0200504 self.assert_packet_checksums_valid(packet)
Matus Fabiande886752016-12-07 03:38:19 -0800505 self.assertEqual(packet[IP].dst, in_if.remote_ip4)
506 if packet.haslayer(TCP):
507 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
508 elif packet.haslayer(UDP):
509 self.assertEqual(packet[UDP].dport, self.udp_port_in)
510 else:
511 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
512 except:
Klement Sekera9225dee2016-12-12 08:36:58 +0100513 self.logger.error(ppp("Unexpected or invalid packet "
514 "(inside network):", packet))
Matus Fabiande886752016-12-07 03:38:19 -0800515 raise
516
Matus Fabian05ca4a32018-09-04 23:45:13 -0700517 def verify_capture_in_ip6(self, capture, src_ip, dst_ip):
Matus Fabian06596c52017-06-06 04:53:28 -0700518 """
519 Verify captured IPv6 packets on inside network
520
521 :param capture: Captured packets
522 :param src_ip: Source IP
523 :param dst_ip: Destination IP address
Matus Fabian06596c52017-06-06 04:53:28 -0700524 """
Matus Fabian06596c52017-06-06 04:53:28 -0700525 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,
Matus Fabian05ca4a32018-09-04 23:45:13 -0700566 icmp_type=11):
Juraj Slobodab33f4132017-02-08 23:54:21 -0800567 """
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 icmp_type: Type of error ICMP packet
574 we are expecting (Default 11)
575 """
576 if src_ip is None:
Matus Fabian2ba92e32017-08-21 07:05:03 -0700577 src_ip = self.nat_addr
Juraj Slobodab33f4132017-02-08 23:54:21 -0800578 for packet in capture:
579 try:
580 self.assertEqual(packet[IP].src, src_ip)
Paul Vinciguerra978aa642018-11-24 22:19:12 -0800581 self.assertEqual(packet.haslayer(ICMP), 1)
Juraj Slobodab33f4132017-02-08 23:54:21 -0800582 icmp = packet[ICMP]
583 self.assertEqual(icmp.type, icmp_type)
584 self.assertTrue(icmp.haslayer(IPerror))
585 inner_ip = icmp[IPerror]
586 if inner_ip.haslayer(TCPerror):
587 self.assertEqual(inner_ip[TCPerror].dport,
588 self.tcp_port_out)
589 elif inner_ip.haslayer(UDPerror):
590 self.assertEqual(inner_ip[UDPerror].dport,
591 self.udp_port_out)
592 else:
593 self.assertEqual(inner_ip[ICMPerror].id, self.icmp_id_out)
594 except:
595 self.logger.error(ppp("Unexpected or invalid packet "
596 "(outside network):", packet))
597 raise
598
Matus Fabian05ca4a32018-09-04 23:45:13 -0700599 def verify_capture_in_with_icmp_errors(self, capture, in_if, icmp_type=11):
Juraj Slobodab33f4132017-02-08 23:54:21 -0800600 """
601 Verify captured packets with ICMP errors on inside network
602
603 :param capture: Captured packets
604 :param in_if: Inside interface
Juraj Slobodab33f4132017-02-08 23:54:21 -0800605 :param icmp_type: Type of error ICMP packet
606 we are expecting (Default 11)
607 """
Juraj Slobodab33f4132017-02-08 23:54:21 -0800608 for packet in capture:
609 try:
610 self.assertEqual(packet[IP].dst, in_if.remote_ip4)
Paul Vinciguerra978aa642018-11-24 22:19:12 -0800611 self.assertEqual(packet.haslayer(ICMP), 1)
Juraj Slobodab33f4132017-02-08 23:54:21 -0800612 icmp = packet[ICMP]
613 self.assertEqual(icmp.type, icmp_type)
614 self.assertTrue(icmp.haslayer(IPerror))
615 inner_ip = icmp[IPerror]
616 if inner_ip.haslayer(TCPerror):
617 self.assertEqual(inner_ip[TCPerror].sport,
618 self.tcp_port_in)
619 elif inner_ip.haslayer(UDPerror):
620 self.assertEqual(inner_ip[UDPerror].sport,
621 self.udp_port_in)
622 else:
623 self.assertEqual(inner_ip[ICMPerror].id, self.icmp_id_in)
624 except:
625 self.logger.error(ppp("Unexpected or invalid packet "
626 "(inside network):", packet))
627 raise
628
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200629 def create_stream_frag(self, src_if, dst, sport, dport, data,
630 proto=IP_PROTOS.tcp, echo_reply=False):
Matus Fabianefcd1e92017-08-15 06:59:19 -0700631 """
632 Create fragmented packet stream
633
634 :param src_if: Source interface
635 :param dst: Destination IPv4 address
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200636 :param sport: Source port
637 :param dport: Destination port
Matus Fabianefcd1e92017-08-15 06:59:19 -0700638 :param data: Payload data
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200639 :param proto: protocol (TCP, UDP, ICMP)
640 :param echo_reply: use echo_reply if protocol is ICMP
Matus Fabianefcd1e92017-08-15 06:59:19 -0700641 :returns: Fragmets
642 """
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200643 if proto == IP_PROTOS.tcp:
644 p = (IP(src=src_if.remote_ip4, dst=dst) /
645 TCP(sport=sport, dport=dport) /
646 Raw(data))
647 p = p.__class__(str(p))
648 chksum = p['TCP'].chksum
649 proto_header = TCP(sport=sport, dport=dport, chksum=chksum)
650 elif proto == IP_PROTOS.udp:
651 proto_header = UDP(sport=sport, dport=dport)
652 elif proto == IP_PROTOS.icmp:
653 if not echo_reply:
654 proto_header = ICMP(id=sport, type='echo-request')
655 else:
656 proto_header = ICMP(id=sport, type='echo-reply')
657 else:
658 raise Exception("Unsupported protocol")
Matus Fabianefcd1e92017-08-15 06:59:19 -0700659 id = random.randint(0, 65535)
Matus Fabianefcd1e92017-08-15 06:59:19 -0700660 pkts = []
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200661 if proto == IP_PROTOS.tcp:
662 raw = Raw(data[0:4])
663 else:
664 raw = Raw(data[0:16])
Matus Fabianefcd1e92017-08-15 06:59:19 -0700665 p = (Ether(src=src_if.remote_mac, dst=src_if.local_mac) /
666 IP(src=src_if.remote_ip4, dst=dst, flags="MF", frag=0, id=id) /
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200667 proto_header /
668 raw)
Matus Fabianefcd1e92017-08-15 06:59:19 -0700669 pkts.append(p)
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200670 if proto == IP_PROTOS.tcp:
671 raw = Raw(data[4:20])
672 else:
673 raw = Raw(data[16:32])
Matus Fabianefcd1e92017-08-15 06:59:19 -0700674 p = (Ether(src=src_if.remote_mac, dst=src_if.local_mac) /
675 IP(src=src_if.remote_ip4, dst=dst, flags="MF", frag=3, id=id,
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200676 proto=proto) /
677 raw)
Matus Fabianefcd1e92017-08-15 06:59:19 -0700678 pkts.append(p)
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200679 if proto == IP_PROTOS.tcp:
680 raw = Raw(data[20:])
681 else:
682 raw = Raw(data[32:])
Matus Fabianefcd1e92017-08-15 06:59:19 -0700683 p = (Ether(src=src_if.remote_mac, dst=src_if.local_mac) /
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200684 IP(src=src_if.remote_ip4, dst=dst, frag=5, proto=proto,
Matus Fabianefcd1e92017-08-15 06:59:19 -0700685 id=id) /
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200686 raw)
Matus Fabianefcd1e92017-08-15 06:59:19 -0700687 pkts.append(p)
688 return pkts
689
690 def create_stream_frag_ip6(self, src_if, dst, sport, dport, data,
691 pref=None, plen=0, frag_size=128):
692 """
693 Create fragmented packet stream
694
695 :param src_if: Source interface
696 :param dst: Destination IPv4 address
697 :param sport: Source TCP port
698 :param dport: Destination TCP port
699 :param data: Payload data
700 :param pref: NAT64 prefix
701 :param plen: NAT64 prefix length
702 :param fragsize: size of fragments
703 :returns: Fragmets
704 """
705 if pref is None:
706 dst_ip6 = ''.join(['64:ff9b::', dst])
707 else:
708 dst_ip6 = self.compose_ip6(dst, pref, plen)
709
710 p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
711 IPv6(src=src_if.remote_ip6, dst=dst_ip6) /
712 IPv6ExtHdrFragment(id=random.randint(0, 65535)) /
713 TCP(sport=sport, dport=dport) /
714 Raw(data))
715
716 return fragment6(p, frag_size)
717
718 def reass_frags_and_verify(self, frags, src, dst):
719 """
720 Reassemble and verify fragmented packet
721
722 :param frags: Captured fragments
723 :param src: Source IPv4 address to verify
724 :param dst: Destination IPv4 address to verify
725
726 :returns: Reassembled IPv4 packet
727 """
Ole Troan7f991832018-12-06 17:35:12 +0100728 buffer = BytesIO()
Matus Fabianefcd1e92017-08-15 06:59:19 -0700729 for p in frags:
730 self.assertEqual(p[IP].src, src)
731 self.assertEqual(p[IP].dst, dst)
Klement Sekerad81ae412018-05-16 10:52:54 +0200732 self.assert_ip_checksum_valid(p)
Matus Fabianefcd1e92017-08-15 06:59:19 -0700733 buffer.seek(p[IP].frag * 8)
Ole Troan7f991832018-12-06 17:35:12 +0100734 buffer.write(bytes(p[IP].payload))
Matus Fabianefcd1e92017-08-15 06:59:19 -0700735 ip = IP(src=frags[0][IP].src, dst=frags[0][IP].dst,
736 proto=frags[0][IP].proto)
737 if ip.proto == IP_PROTOS.tcp:
738 p = (ip / TCP(buffer.getvalue()))
Klement Sekerad81ae412018-05-16 10:52:54 +0200739 self.assert_tcp_checksum_valid(p)
Matus Fabianefcd1e92017-08-15 06:59:19 -0700740 elif ip.proto == IP_PROTOS.udp:
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200741 p = (ip / UDP(buffer.getvalue()[:8]) /
742 Raw(buffer.getvalue()[8:]))
743 elif ip.proto == IP_PROTOS.icmp:
744 p = (ip / ICMP(buffer.getvalue()))
Matus Fabianefcd1e92017-08-15 06:59:19 -0700745 return p
746
747 def reass_frags_and_verify_ip6(self, frags, src, dst):
748 """
749 Reassemble and verify fragmented packet
750
751 :param frags: Captured fragments
752 :param src: Source IPv6 address to verify
753 :param dst: Destination IPv6 address to verify
754
755 :returns: Reassembled IPv6 packet
756 """
Ole Troan7f991832018-12-06 17:35:12 +0100757 buffer = BytesIO()
Matus Fabianefcd1e92017-08-15 06:59:19 -0700758 for p in frags:
759 self.assertEqual(p[IPv6].src, src)
760 self.assertEqual(p[IPv6].dst, dst)
761 buffer.seek(p[IPv6ExtHdrFragment].offset * 8)
Ole Troan7f991832018-12-06 17:35:12 +0100762 buffer.write(bytes(p[IPv6ExtHdrFragment].payload))
Matus Fabianefcd1e92017-08-15 06:59:19 -0700763 ip = IPv6(src=frags[0][IPv6].src, dst=frags[0][IPv6].dst,
764 nh=frags[0][IPv6ExtHdrFragment].nh)
765 if ip.nh == IP_PROTOS.tcp:
766 p = (ip / TCP(buffer.getvalue()))
Matus Fabianefcd1e92017-08-15 06:59:19 -0700767 elif ip.nh == IP_PROTOS.udp:
768 p = (ip / UDP(buffer.getvalue()))
Klement Sekerad81ae412018-05-16 10:52:54 +0200769 self.assert_packet_checksums_valid(p)
Matus Fabianefcd1e92017-08-15 06:59:19 -0700770 return p
771
Matus Fabianebdf1902018-05-04 03:57:42 -0700772 def initiate_tcp_session(self, in_if, out_if):
773 """
774 Initiates TCP session
775
776 :param in_if: Inside interface
777 :param out_if: Outside interface
778 """
779 try:
780 # SYN packet in->out
781 p = (Ether(src=in_if.remote_mac, dst=in_if.local_mac) /
782 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4) /
783 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
784 flags="S"))
785 in_if.add_stream(p)
786 self.pg_enable_capture(self.pg_interfaces)
787 self.pg_start()
788 capture = out_if.get_capture(1)
789 p = capture[0]
790 self.tcp_port_out = p[TCP].sport
791
792 # SYN + ACK packet out->in
793 p = (Ether(src=out_if.remote_mac, dst=out_if.local_mac) /
794 IP(src=out_if.remote_ip4, dst=self.nat_addr) /
795 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
796 flags="SA"))
797 out_if.add_stream(p)
798 self.pg_enable_capture(self.pg_interfaces)
799 self.pg_start()
800 in_if.get_capture(1)
801
802 # ACK packet in->out
803 p = (Ether(src=in_if.remote_mac, dst=in_if.local_mac) /
804 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4) /
805 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
806 flags="A"))
807 in_if.add_stream(p)
808 self.pg_enable_capture(self.pg_interfaces)
809 self.pg_start()
810 out_if.get_capture(1)
811
812 except:
813 self.logger.error("TCP 3 way handshake failed")
814 raise
815
Matus Fabianeea28d72017-01-13 04:15:54 -0800816 def verify_ipfix_nat44_ses(self, data):
817 """
818 Verify IPFIX NAT44 session create/delete event
819
820 :param data: Decoded IPFIX data records
821 """
822 nat44_ses_create_num = 0
823 nat44_ses_delete_num = 0
824 self.assertEqual(6, len(data))
825 for record in data:
826 # natEvent
827 self.assertIn(ord(record[230]), [4, 5])
828 if ord(record[230]) == 4:
829 nat44_ses_create_num += 1
830 else:
831 nat44_ses_delete_num += 1
832 # sourceIPv4Address
833 self.assertEqual(self.pg0.remote_ip4n, record[8])
834 # postNATSourceIPv4Address
Matus Fabian2ba92e32017-08-21 07:05:03 -0700835 self.assertEqual(socket.inet_pton(socket.AF_INET, self.nat_addr),
Matus Fabianeea28d72017-01-13 04:15:54 -0800836 record[225])
837 # ingressVRFID
838 self.assertEqual(struct.pack("!I", 0), record[234])
839 # protocolIdentifier/sourceTransportPort/postNAPTSourceTransportPort
840 if IP_PROTOS.icmp == ord(record[4]):
841 self.assertEqual(struct.pack("!H", self.icmp_id_in), record[7])
842 self.assertEqual(struct.pack("!H", self.icmp_id_out),
843 record[227])
844 elif IP_PROTOS.tcp == ord(record[4]):
845 self.assertEqual(struct.pack("!H", self.tcp_port_in),
846 record[7])
847 self.assertEqual(struct.pack("!H", self.tcp_port_out),
848 record[227])
849 elif IP_PROTOS.udp == ord(record[4]):
850 self.assertEqual(struct.pack("!H", self.udp_port_in),
851 record[7])
852 self.assertEqual(struct.pack("!H", self.udp_port_out),
853 record[227])
854 else:
855 self.fail("Invalid protocol")
856 self.assertEqual(3, nat44_ses_create_num)
857 self.assertEqual(3, nat44_ses_delete_num)
858
859 def verify_ipfix_addr_exhausted(self, data):
860 """
861 Verify IPFIX NAT addresses event
862
863 :param data: Decoded IPFIX data records
864 """
865 self.assertEqual(1, len(data))
866 record = data[0]
867 # natEvent
868 self.assertEqual(ord(record[230]), 3)
869 # natPoolID
870 self.assertEqual(struct.pack("!I", 0), record[283])
871
Matus Fabiana431ad12018-01-04 04:03:14 -0800872 def verify_ipfix_max_sessions(self, data, limit):
873 """
874 Verify IPFIX maximum session entries exceeded event
875
876 :param data: Decoded IPFIX data records
877 :param limit: Number of maximum session entries that can be created.
878 """
879 self.assertEqual(1, len(data))
880 record = data[0]
881 # natEvent
882 self.assertEqual(ord(record[230]), 13)
883 # natQuotaExceededEvent
884 self.assertEqual(struct.pack("I", 1), record[466])
885 # maxSessionEntries
886 self.assertEqual(struct.pack("I", limit), record[471])
887
888 def verify_ipfix_max_bibs(self, data, limit):
889 """
890 Verify IPFIX maximum BIB entries exceeded event
891
892 :param data: Decoded IPFIX data records
893 :param limit: Number of maximum BIB entries that can be created.
894 """
895 self.assertEqual(1, len(data))
896 record = data[0]
897 # natEvent
898 self.assertEqual(ord(record[230]), 13)
899 # natQuotaExceededEvent
900 self.assertEqual(struct.pack("I", 2), record[466])
901 # maxBIBEntries
902 self.assertEqual(struct.pack("I", limit), record[472])
903
904 def verify_ipfix_max_fragments_ip6(self, data, limit, src_addr):
905 """
906 Verify IPFIX maximum IPv6 fragments pending reassembly exceeded event
907
908 :param data: Decoded IPFIX data records
909 :param limit: Number of maximum fragments pending reassembly
910 :param src_addr: IPv6 source address
911 """
912 self.assertEqual(1, len(data))
913 record = data[0]
914 # natEvent
915 self.assertEqual(ord(record[230]), 13)
916 # natQuotaExceededEvent
917 self.assertEqual(struct.pack("I", 5), record[466])
918 # maxFragmentsPendingReassembly
919 self.assertEqual(struct.pack("I", limit), record[475])
920 # sourceIPv6Address
921 self.assertEqual(src_addr, record[27])
922
923 def verify_ipfix_max_fragments_ip4(self, data, limit, src_addr):
924 """
925 Verify IPFIX maximum IPv4 fragments pending reassembly exceeded event
926
927 :param data: Decoded IPFIX data records
928 :param limit: Number of maximum fragments pending reassembly
929 :param src_addr: IPv4 source address
930 """
931 self.assertEqual(1, len(data))
932 record = data[0]
933 # natEvent
934 self.assertEqual(ord(record[230]), 13)
935 # natQuotaExceededEvent
936 self.assertEqual(struct.pack("I", 5), record[466])
937 # maxFragmentsPendingReassembly
938 self.assertEqual(struct.pack("I", limit), record[475])
939 # sourceIPv4Address
940 self.assertEqual(src_addr, record[8])
941
942 def verify_ipfix_bib(self, data, is_create, src_addr):
943 """
944 Verify IPFIX NAT64 BIB create and delete events
945
946 :param data: Decoded IPFIX data records
947 :param is_create: Create event if nonzero value otherwise delete event
948 :param src_addr: IPv6 source address
949 """
950 self.assertEqual(1, len(data))
951 record = data[0]
952 # natEvent
953 if is_create:
954 self.assertEqual(ord(record[230]), 10)
955 else:
956 self.assertEqual(ord(record[230]), 11)
957 # sourceIPv6Address
958 self.assertEqual(src_addr, record[27])
959 # postNATSourceIPv4Address
960 self.assertEqual(self.nat_addr_n, record[225])
961 # protocolIdentifier
962 self.assertEqual(IP_PROTOS.tcp, ord(record[4]))
963 # ingressVRFID
964 self.assertEqual(struct.pack("!I", 0), record[234])
965 # sourceTransportPort
966 self.assertEqual(struct.pack("!H", self.tcp_port_in), record[7])
967 # postNAPTSourceTransportPort
968 self.assertEqual(struct.pack("!H", self.tcp_port_out), record[227])
969
970 def verify_ipfix_nat64_ses(self, data, is_create, src_addr, dst_addr,
971 dst_port):
972 """
973 Verify IPFIX NAT64 session create and delete events
974
975 :param data: Decoded IPFIX data records
976 :param is_create: Create event if nonzero value otherwise delete event
977 :param src_addr: IPv6 source address
978 :param dst_addr: IPv4 destination address
979 :param dst_port: destination TCP port
980 """
981 self.assertEqual(1, len(data))
982 record = data[0]
983 # natEvent
984 if is_create:
985 self.assertEqual(ord(record[230]), 6)
986 else:
987 self.assertEqual(ord(record[230]), 7)
988 # sourceIPv6Address
989 self.assertEqual(src_addr, record[27])
990 # destinationIPv6Address
991 self.assertEqual(socket.inet_pton(socket.AF_INET6,
992 self.compose_ip6(dst_addr,
993 '64:ff9b::',
994 96)),
995 record[28])
996 # postNATSourceIPv4Address
997 self.assertEqual(self.nat_addr_n, record[225])
998 # postNATDestinationIPv4Address
999 self.assertEqual(socket.inet_pton(socket.AF_INET, dst_addr),
1000 record[226])
1001 # protocolIdentifier
1002 self.assertEqual(IP_PROTOS.tcp, ord(record[4]))
1003 # ingressVRFID
1004 self.assertEqual(struct.pack("!I", 0), record[234])
1005 # sourceTransportPort
1006 self.assertEqual(struct.pack("!H", self.tcp_port_in), record[7])
1007 # postNAPTSourceTransportPort
1008 self.assertEqual(struct.pack("!H", self.tcp_port_out), record[227])
1009 # destinationTransportPort
1010 self.assertEqual(struct.pack("!H", dst_port), record[11])
1011 # postNAPTDestinationTransportPort
1012 self.assertEqual(struct.pack("!H", dst_port), record[228])
1013
Matus Fabian68ba8802018-08-08 05:52:47 -07001014 def verify_no_nat44_user(self):
1015 """ Verify that there is no NAT44 user """
1016 users = self.vapi.nat44_user_dump()
1017 self.assertEqual(len(users), 0)
1018
Matus Fabian878c6462018-08-23 00:33:35 -07001019 def verify_ipfix_max_entries_per_user(self, data, limit, src_addr):
1020 """
1021 Verify IPFIX maximum entries per user exceeded event
1022
1023 :param data: Decoded IPFIX data records
1024 :param limit: Number of maximum entries per user
1025 :param src_addr: IPv4 source address
1026 """
1027 self.assertEqual(1, len(data))
1028 record = data[0]
1029 # natEvent
1030 self.assertEqual(ord(record[230]), 13)
1031 # natQuotaExceededEvent
1032 self.assertEqual(struct.pack("I", 3), record[466])
1033 # maxEntriesPerUser
1034 self.assertEqual(struct.pack("I", limit), record[473])
1035 # sourceIPv4Address
1036 self.assertEqual(src_addr, record[8])
1037
Matus Fabianad1f3e12018-11-28 21:26:34 -08001038 def verify_syslog_apmap(self, data, is_add=True):
1039 message = data.decode('utf-8')
1040 try:
1041 message = SyslogMessage.parse(message)
1042 self.assertEqual(message.severity, SyslogSeverity.info)
1043 self.assertEqual(message.appname, 'NAT')
1044 self.assertEqual(message.msgid, 'APMADD' if is_add else 'APMDEL')
1045 sd_params = message.sd.get('napmap')
1046 self.assertTrue(sd_params is not None)
1047 self.assertEqual(sd_params.get('IATYP'), 'IPv4')
1048 self.assertEqual(sd_params.get('ISADDR'), self.pg0.remote_ip4)
1049 self.assertEqual(sd_params.get('ISPORT'), "%d" % self.tcp_port_in)
1050 self.assertEqual(sd_params.get('XATYP'), 'IPv4')
1051 self.assertEqual(sd_params.get('XSADDR'), self.nat_addr)
1052 self.assertEqual(sd_params.get('XSPORT'), "%d" % self.tcp_port_out)
1053 self.assertEqual(sd_params.get('PROTO'), "%d" % IP_PROTOS.tcp)
1054 self.assertTrue(sd_params.get('SSUBIX') is not None)
1055 self.assertEqual(sd_params.get('SVLAN'), '0')
1056 except ParseError as e:
1057 self.logger.error(e)
1058
1059 def verify_syslog_sess(self, data, is_add=True, is_ip6=False):
1060 message = data.decode('utf-8')
1061 try:
1062 message = SyslogMessage.parse(message)
1063 self.assertEqual(message.severity, SyslogSeverity.info)
1064 self.assertEqual(message.appname, 'NAT')
1065 self.assertEqual(message.msgid, 'SADD' if is_add else 'SDEL')
1066 sd_params = message.sd.get('nsess')
1067 self.assertTrue(sd_params is not None)
1068 if is_ip6:
1069 self.assertEqual(sd_params.get('IATYP'), 'IPv6')
1070 self.assertEqual(sd_params.get('ISADDR'), self.pg0.remote_ip6)
1071 else:
1072 self.assertEqual(sd_params.get('IATYP'), 'IPv4')
1073 self.assertEqual(sd_params.get('ISADDR'), self.pg0.remote_ip4)
1074 self.assertTrue(sd_params.get('SSUBIX') is not None)
1075 self.assertEqual(sd_params.get('ISPORT'), "%d" % self.tcp_port_in)
1076 self.assertEqual(sd_params.get('XATYP'), 'IPv4')
1077 self.assertEqual(sd_params.get('XSADDR'), self.nat_addr)
1078 self.assertEqual(sd_params.get('XSPORT'), "%d" % self.tcp_port_out)
1079 self.assertEqual(sd_params.get('PROTO'), "%d" % IP_PROTOS.tcp)
1080 self.assertEqual(sd_params.get('SVLAN'), '0')
1081 self.assertEqual(sd_params.get('XDADDR'), self.pg1.remote_ip4)
1082 self.assertEqual(sd_params.get('XDPORT'),
1083 "%d" % self.tcp_external_port)
1084 except ParseError as e:
1085 self.logger.error(e)
1086
Matus Fabianbb4e0222018-09-13 02:36:25 -07001087 def verify_mss_value(self, pkt, mss):
1088 """
1089 Verify TCP MSS value
1090
1091 :param pkt:
1092 :param mss:
1093 """
1094 if not pkt.haslayer(IP) or not pkt.haslayer(TCP):
1095 raise TypeError("Not a TCP/IP packet")
1096
1097 for option in pkt[TCP].options:
1098 if option[0] == 'MSS':
1099 self.assertEqual(option[1], mss)
1100 self.assert_tcp_checksum_valid(pkt)
1101
Juraj Slobodafe0aa762018-07-23 12:22:54 +02001102 @staticmethod
1103 def proto2layer(proto):
1104 if proto == IP_PROTOS.tcp:
1105 return TCP
1106 elif proto == IP_PROTOS.udp:
1107 return UDP
1108 elif proto == IP_PROTOS.icmp:
1109 return ICMP
1110 else:
1111 raise Exception("Unsupported protocol")
1112
1113 def frag_in_order(self, proto=IP_PROTOS.tcp, dont_translate=False):
1114 layer = self.proto2layer(proto)
1115
1116 if proto == IP_PROTOS.tcp:
1117 data = "A" * 4 + "B" * 16 + "C" * 3
1118 else:
1119 data = "A" * 16 + "B" * 16 + "C" * 3
1120 self.port_in = random.randint(1025, 65535)
1121
1122 reass = self.vapi.nat_reass_dump()
1123 reass_n_start = len(reass)
1124
1125 # in2out
1126 pkts = self.create_stream_frag(self.pg0,
1127 self.pg1.remote_ip4,
1128 self.port_in,
1129 20,
1130 data,
1131 proto)
1132 self.pg0.add_stream(pkts)
1133 self.pg_enable_capture(self.pg_interfaces)
1134 self.pg_start()
1135 frags = self.pg1.get_capture(len(pkts))
1136 if not dont_translate:
1137 p = self.reass_frags_and_verify(frags,
1138 self.nat_addr,
1139 self.pg1.remote_ip4)
1140 else:
1141 p = self.reass_frags_and_verify(frags,
1142 self.pg0.remote_ip4,
1143 self.pg1.remote_ip4)
1144 if proto != IP_PROTOS.icmp:
1145 if not dont_translate:
1146 self.assertEqual(p[layer].dport, 20)
1147 self.assertNotEqual(p[layer].sport, self.port_in)
1148 else:
1149 self.assertEqual(p[layer].sport, self.port_in)
1150 else:
1151 if not dont_translate:
1152 self.assertNotEqual(p[layer].id, self.port_in)
1153 else:
1154 self.assertEqual(p[layer].id, self.port_in)
1155 self.assertEqual(data, p[Raw].load)
1156
1157 # out2in
1158 if not dont_translate:
1159 dst_addr = self.nat_addr
1160 else:
1161 dst_addr = self.pg0.remote_ip4
1162 if proto != IP_PROTOS.icmp:
1163 sport = 20
1164 dport = p[layer].sport
1165 else:
1166 sport = p[layer].id
1167 dport = 0
1168 pkts = self.create_stream_frag(self.pg1,
1169 dst_addr,
1170 sport,
1171 dport,
1172 data,
1173 proto,
1174 echo_reply=True)
1175 self.pg1.add_stream(pkts)
1176 self.pg_enable_capture(self.pg_interfaces)
1177 self.pg_start()
1178 frags = self.pg0.get_capture(len(pkts))
1179 p = self.reass_frags_and_verify(frags,
1180 self.pg1.remote_ip4,
1181 self.pg0.remote_ip4)
1182 if proto != IP_PROTOS.icmp:
1183 self.assertEqual(p[layer].sport, 20)
1184 self.assertEqual(p[layer].dport, self.port_in)
1185 else:
1186 self.assertEqual(p[layer].id, self.port_in)
1187 self.assertEqual(data, p[Raw].load)
1188
1189 reass = self.vapi.nat_reass_dump()
1190 reass_n_end = len(reass)
1191
1192 self.assertEqual(reass_n_end - reass_n_start, 2)
1193
1194 def frag_in_order_in_plus_out(self, proto=IP_PROTOS.tcp):
1195 layer = self.proto2layer(proto)
1196
1197 if proto == IP_PROTOS.tcp:
1198 data = "A" * 4 + "B" * 16 + "C" * 3
1199 else:
1200 data = "A" * 16 + "B" * 16 + "C" * 3
1201 self.port_in = random.randint(1025, 65535)
1202
1203 for i in range(2):
1204 reass = self.vapi.nat_reass_dump()
1205 reass_n_start = len(reass)
1206
1207 # out2in
1208 pkts = self.create_stream_frag(self.pg0,
1209 self.server_out_addr,
1210 self.port_in,
1211 self.server_out_port,
1212 data,
1213 proto)
1214 self.pg0.add_stream(pkts)
1215 self.pg_enable_capture(self.pg_interfaces)
1216 self.pg_start()
1217 frags = self.pg1.get_capture(len(pkts))
1218 p = self.reass_frags_and_verify(frags,
1219 self.pg0.remote_ip4,
1220 self.server_in_addr)
1221 if proto != IP_PROTOS.icmp:
1222 self.assertEqual(p[layer].sport, self.port_in)
1223 self.assertEqual(p[layer].dport, self.server_in_port)
1224 else:
1225 self.assertEqual(p[layer].id, self.port_in)
1226 self.assertEqual(data, p[Raw].load)
1227
1228 # in2out
1229 if proto != IP_PROTOS.icmp:
1230 pkts = self.create_stream_frag(self.pg1,
1231 self.pg0.remote_ip4,
1232 self.server_in_port,
1233 p[layer].sport,
1234 data,
1235 proto)
1236 else:
1237 pkts = self.create_stream_frag(self.pg1,
1238 self.pg0.remote_ip4,
1239 p[layer].id,
1240 0,
1241 data,
1242 proto,
1243 echo_reply=True)
1244 self.pg1.add_stream(pkts)
1245 self.pg_enable_capture(self.pg_interfaces)
1246 self.pg_start()
1247 frags = self.pg0.get_capture(len(pkts))
1248 p = self.reass_frags_and_verify(frags,
1249 self.server_out_addr,
1250 self.pg0.remote_ip4)
1251 if proto != IP_PROTOS.icmp:
1252 self.assertEqual(p[layer].sport, self.server_out_port)
1253 self.assertEqual(p[layer].dport, self.port_in)
1254 else:
1255 self.assertEqual(p[layer].id, self.port_in)
1256 self.assertEqual(data, p[Raw].load)
1257
1258 reass = self.vapi.nat_reass_dump()
1259 reass_n_end = len(reass)
1260
1261 self.assertEqual(reass_n_end - reass_n_start, 2)
1262
1263 def reass_hairpinning(self, proto=IP_PROTOS.tcp):
1264 layer = self.proto2layer(proto)
1265
1266 if proto == IP_PROTOS.tcp:
1267 data = "A" * 4 + "B" * 16 + "C" * 3
1268 else:
1269 data = "A" * 16 + "B" * 16 + "C" * 3
1270
1271 # send packet from host to server
1272 pkts = self.create_stream_frag(self.pg0,
1273 self.nat_addr,
1274 self.host_in_port,
1275 self.server_out_port,
1276 data,
1277 proto)
1278 self.pg0.add_stream(pkts)
1279 self.pg_enable_capture(self.pg_interfaces)
1280 self.pg_start()
1281 frags = self.pg0.get_capture(len(pkts))
1282 p = self.reass_frags_and_verify(frags,
1283 self.nat_addr,
1284 self.server.ip4)
1285 if proto != IP_PROTOS.icmp:
1286 self.assertNotEqual(p[layer].sport, self.host_in_port)
1287 self.assertEqual(p[layer].dport, self.server_in_port)
1288 else:
1289 self.assertNotEqual(p[layer].id, self.host_in_port)
1290 self.assertEqual(data, p[Raw].load)
1291
1292 def frag_out_of_order(self, proto=IP_PROTOS.tcp, dont_translate=False):
1293 layer = self.proto2layer(proto)
1294
1295 if proto == IP_PROTOS.tcp:
1296 data = "A" * 4 + "B" * 16 + "C" * 3
1297 else:
1298 data = "A" * 16 + "B" * 16 + "C" * 3
1299 self.port_in = random.randint(1025, 65535)
1300
1301 for i in range(2):
1302 # in2out
1303 pkts = self.create_stream_frag(self.pg0,
1304 self.pg1.remote_ip4,
1305 self.port_in,
1306 20,
1307 data,
1308 proto)
1309 pkts.reverse()
1310 self.pg0.add_stream(pkts)
1311 self.pg_enable_capture(self.pg_interfaces)
1312 self.pg_start()
1313 frags = self.pg1.get_capture(len(pkts))
1314 if not dont_translate:
1315 p = self.reass_frags_and_verify(frags,
1316 self.nat_addr,
1317 self.pg1.remote_ip4)
1318 else:
1319 p = self.reass_frags_and_verify(frags,
1320 self.pg0.remote_ip4,
1321 self.pg1.remote_ip4)
1322 if proto != IP_PROTOS.icmp:
1323 if not dont_translate:
1324 self.assertEqual(p[layer].dport, 20)
1325 self.assertNotEqual(p[layer].sport, self.port_in)
1326 else:
1327 self.assertEqual(p[layer].sport, self.port_in)
1328 else:
1329 if not dont_translate:
1330 self.assertNotEqual(p[layer].id, self.port_in)
1331 else:
1332 self.assertEqual(p[layer].id, self.port_in)
1333 self.assertEqual(data, p[Raw].load)
1334
1335 # out2in
1336 if not dont_translate:
1337 dst_addr = self.nat_addr
1338 else:
1339 dst_addr = self.pg0.remote_ip4
1340 if proto != IP_PROTOS.icmp:
1341 sport = 20
1342 dport = p[layer].sport
1343 else:
1344 sport = p[layer].id
1345 dport = 0
1346 pkts = self.create_stream_frag(self.pg1,
1347 dst_addr,
1348 sport,
1349 dport,
1350 data,
1351 proto,
1352 echo_reply=True)
1353 pkts.reverse()
1354 self.pg1.add_stream(pkts)
1355 self.pg_enable_capture(self.pg_interfaces)
1356 self.pg_start()
1357 frags = self.pg0.get_capture(len(pkts))
1358 p = self.reass_frags_and_verify(frags,
1359 self.pg1.remote_ip4,
1360 self.pg0.remote_ip4)
1361 if proto != IP_PROTOS.icmp:
1362 self.assertEqual(p[layer].sport, 20)
1363 self.assertEqual(p[layer].dport, self.port_in)
1364 else:
1365 self.assertEqual(p[layer].id, self.port_in)
1366 self.assertEqual(data, p[Raw].load)
1367
1368 def frag_out_of_order_in_plus_out(self, proto=IP_PROTOS.tcp):
1369 layer = self.proto2layer(proto)
1370
1371 if proto == IP_PROTOS.tcp:
1372 data = "A" * 4 + "B" * 16 + "C" * 3
1373 else:
1374 data = "A" * 16 + "B" * 16 + "C" * 3
1375 self.port_in = random.randint(1025, 65535)
1376
1377 for i in range(2):
1378 # out2in
1379 pkts = self.create_stream_frag(self.pg0,
1380 self.server_out_addr,
1381 self.port_in,
1382 self.server_out_port,
1383 data,
1384 proto)
1385 pkts.reverse()
1386 self.pg0.add_stream(pkts)
1387 self.pg_enable_capture(self.pg_interfaces)
1388 self.pg_start()
1389 frags = self.pg1.get_capture(len(pkts))
1390 p = self.reass_frags_and_verify(frags,
1391 self.pg0.remote_ip4,
1392 self.server_in_addr)
1393 if proto != IP_PROTOS.icmp:
1394 self.assertEqual(p[layer].dport, self.server_in_port)
1395 self.assertEqual(p[layer].sport, self.port_in)
1396 self.assertEqual(p[layer].dport, self.server_in_port)
1397 else:
1398 self.assertEqual(p[layer].id, self.port_in)
1399 self.assertEqual(data, p[Raw].load)
1400
1401 # in2out
1402 if proto != IP_PROTOS.icmp:
1403 pkts = self.create_stream_frag(self.pg1,
1404 self.pg0.remote_ip4,
1405 self.server_in_port,
1406 p[layer].sport,
1407 data,
1408 proto)
1409 else:
1410 pkts = self.create_stream_frag(self.pg1,
1411 self.pg0.remote_ip4,
1412 p[layer].id,
1413 0,
1414 data,
1415 proto,
1416 echo_reply=True)
1417 pkts.reverse()
1418 self.pg1.add_stream(pkts)
1419 self.pg_enable_capture(self.pg_interfaces)
1420 self.pg_start()
1421 frags = self.pg0.get_capture(len(pkts))
1422 p = self.reass_frags_and_verify(frags,
1423 self.server_out_addr,
1424 self.pg0.remote_ip4)
1425 if proto != IP_PROTOS.icmp:
1426 self.assertEqual(p[layer].sport, self.server_out_port)
1427 self.assertEqual(p[layer].dport, self.port_in)
1428 else:
1429 self.assertEqual(p[layer].id, self.port_in)
1430 self.assertEqual(data, p[Raw].load)
1431
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001432
Matus Fabian2ba92e32017-08-21 07:05:03 -07001433class TestNAT44(MethodHolder):
1434 """ NAT44 Test Cases """
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001435
1436 @classmethod
1437 def setUpClass(cls):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001438 super(TestNAT44, cls).setUpClass()
Matus Fabian229c1aa2018-05-28 04:09:52 -07001439 cls.vapi.cli("set log class nat level debug")
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001440
1441 try:
1442 cls.tcp_port_in = 6303
1443 cls.tcp_port_out = 6303
1444 cls.udp_port_in = 6304
1445 cls.udp_port_out = 6304
1446 cls.icmp_id_in = 6305
1447 cls.icmp_id_out = 6305
Matus Fabian2ba92e32017-08-21 07:05:03 -07001448 cls.nat_addr = '10.0.0.3'
Juraj Sloboda7b929792017-11-23 13:20:48 +01001449 cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
Matus Fabian6631e9c2017-05-24 01:52:20 -07001450 cls.ipfix_src_port = 4739
1451 cls.ipfix_domain_id = 1
Matus Fabianebdf1902018-05-04 03:57:42 -07001452 cls.tcp_external_port = 80
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001453
Matus Fabian36ea2d62017-10-24 04:13:49 -07001454 cls.create_pg_interfaces(range(10))
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001455 cls.interfaces = list(cls.pg_interfaces[0:4])
1456
1457 for i in cls.interfaces:
1458 i.admin_up()
1459 i.config_ip4()
1460 i.resolve_arp()
1461
Matus Fabian6fa74c62017-06-05 05:55:48 -07001462 cls.pg0.generate_remote_hosts(3)
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001463 cls.pg0.configure_ipv4_neighbors()
1464
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02001465 cls.pg1.generate_remote_hosts(1)
1466 cls.pg1.configure_ipv4_neighbors()
1467
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001468 cls.overlapping_interfaces = list(list(cls.pg_interfaces[4:7]))
Neale Ranns15002542017-09-10 04:39:11 -07001469 cls.vapi.ip_table_add_del(10, is_add=1)
1470 cls.vapi.ip_table_add_del(20, is_add=1)
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001471
1472 cls.pg4._local_ip4 = "172.16.255.1"
1473 cls.pg4._local_ip4n = socket.inet_pton(socket.AF_INET, i.local_ip4)
1474 cls.pg4._remote_hosts[0]._ip4 = "172.16.255.2"
1475 cls.pg4.set_table_ip4(10)
Matus Fabian69126282017-08-14 23:39:58 -07001476 cls.pg5._local_ip4 = "172.17.255.3"
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001477 cls.pg5._local_ip4n = socket.inet_pton(socket.AF_INET, i.local_ip4)
Matus Fabian69126282017-08-14 23:39:58 -07001478 cls.pg5._remote_hosts[0]._ip4 = "172.17.255.4"
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001479 cls.pg5.set_table_ip4(10)
1480 cls.pg6._local_ip4 = "172.16.255.1"
1481 cls.pg6._local_ip4n = socket.inet_pton(socket.AF_INET, i.local_ip4)
1482 cls.pg6._remote_hosts[0]._ip4 = "172.16.255.2"
1483 cls.pg6.set_table_ip4(20)
1484 for i in cls.overlapping_interfaces:
1485 i.config_ip4()
1486 i.admin_up()
1487 i.resolve_arp()
1488
1489 cls.pg7.admin_up()
Martin Gálik406eb1d2017-05-04 04:35:04 -07001490 cls.pg8.admin_up()
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001491
Matus Fabian36ea2d62017-10-24 04:13:49 -07001492 cls.pg9.generate_remote_hosts(2)
1493 cls.pg9.config_ip4()
1494 ip_addr_n = socket.inet_pton(socket.AF_INET, "10.0.0.1")
1495 cls.vapi.sw_interface_add_del_address(cls.pg9.sw_if_index,
1496 ip_addr_n,
1497 24)
1498 cls.pg9.admin_up()
1499 cls.pg9.resolve_arp()
1500 cls.pg9._remote_hosts[1]._ip4 = cls.pg9._remote_hosts[0]._ip4
1501 cls.pg4._remote_ip4 = cls.pg9._remote_hosts[0]._ip4 = "10.0.0.2"
1502 cls.pg9.resolve_arp()
1503
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001504 except Exception:
Matus Fabian2ba92e32017-08-21 07:05:03 -07001505 super(TestNAT44, cls).tearDownClass()
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001506 raise
1507
Matus Fabiande886752016-12-07 03:38:19 -08001508 def test_dynamic(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001509 """ NAT44 dynamic translation test """
Matus Fabiande886752016-12-07 03:38:19 -08001510
Matus Fabian2ba92e32017-08-21 07:05:03 -07001511 self.nat44_add_address(self.nat_addr)
1512 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1513 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1514 is_inside=0)
Matus Fabiande886752016-12-07 03:38:19 -08001515
1516 # in2out
1517 pkts = self.create_stream_in(self.pg0, self.pg1)
1518 self.pg0.add_stream(pkts)
1519 self.pg_enable_capture(self.pg_interfaces)
1520 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001521 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001522 self.verify_capture_out(capture)
1523
1524 # out2in
1525 pkts = self.create_stream_out(self.pg1)
1526 self.pg1.add_stream(pkts)
1527 self.pg_enable_capture(self.pg_interfaces)
1528 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001529 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001530 self.verify_capture_in(capture, self.pg0)
1531
Juraj Slobodab33f4132017-02-08 23:54:21 -08001532 def test_dynamic_icmp_errors_in2out_ttl_1(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001533 """ NAT44 handling of client packets with TTL=1 """
Juraj Slobodab33f4132017-02-08 23:54:21 -08001534
Matus Fabian2ba92e32017-08-21 07:05:03 -07001535 self.nat44_add_address(self.nat_addr)
1536 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1537 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1538 is_inside=0)
Juraj Slobodab33f4132017-02-08 23:54:21 -08001539
1540 # Client side - generate traffic
1541 pkts = self.create_stream_in(self.pg0, self.pg1, ttl=1)
1542 self.pg0.add_stream(pkts)
1543 self.pg_enable_capture(self.pg_interfaces)
1544 self.pg_start()
1545
1546 # Client side - verify ICMP type 11 packets
1547 capture = self.pg0.get_capture(len(pkts))
1548 self.verify_capture_in_with_icmp_errors(capture, self.pg0)
1549
1550 def test_dynamic_icmp_errors_out2in_ttl_1(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001551 """ NAT44 handling of server packets with TTL=1 """
Juraj Slobodab33f4132017-02-08 23:54:21 -08001552
Matus Fabian2ba92e32017-08-21 07:05:03 -07001553 self.nat44_add_address(self.nat_addr)
1554 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1555 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1556 is_inside=0)
Juraj Slobodab33f4132017-02-08 23:54:21 -08001557
1558 # Client side - create sessions
1559 pkts = self.create_stream_in(self.pg0, self.pg1)
1560 self.pg0.add_stream(pkts)
1561 self.pg_enable_capture(self.pg_interfaces)
1562 self.pg_start()
1563
1564 # Server side - generate traffic
1565 capture = self.pg1.get_capture(len(pkts))
1566 self.verify_capture_out(capture)
1567 pkts = self.create_stream_out(self.pg1, ttl=1)
1568 self.pg1.add_stream(pkts)
1569 self.pg_enable_capture(self.pg_interfaces)
1570 self.pg_start()
1571
1572 # Server side - verify ICMP type 11 packets
1573 capture = self.pg1.get_capture(len(pkts))
1574 self.verify_capture_out_with_icmp_errors(capture,
1575 src_ip=self.pg1.local_ip4)
1576
1577 def test_dynamic_icmp_errors_in2out_ttl_2(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001578 """ NAT44 handling of error responses to client packets with TTL=2 """
Juraj Slobodab33f4132017-02-08 23:54:21 -08001579
Matus Fabian2ba92e32017-08-21 07:05:03 -07001580 self.nat44_add_address(self.nat_addr)
1581 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1582 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1583 is_inside=0)
Juraj Slobodab33f4132017-02-08 23:54:21 -08001584
1585 # Client side - generate traffic
1586 pkts = self.create_stream_in(self.pg0, self.pg1, ttl=2)
1587 self.pg0.add_stream(pkts)
1588 self.pg_enable_capture(self.pg_interfaces)
1589 self.pg_start()
1590
1591 # Server side - simulate ICMP type 11 response
1592 capture = self.pg1.get_capture(len(pkts))
1593 pkts = [Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07001594 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Juraj Slobodab33f4132017-02-08 23:54:21 -08001595 ICMP(type=11) / packet[IP] for packet in capture]
1596 self.pg1.add_stream(pkts)
1597 self.pg_enable_capture(self.pg_interfaces)
1598 self.pg_start()
1599
1600 # Client side - verify ICMP type 11 packets
1601 capture = self.pg0.get_capture(len(pkts))
1602 self.verify_capture_in_with_icmp_errors(capture, self.pg0)
1603
1604 def test_dynamic_icmp_errors_out2in_ttl_2(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001605 """ NAT44 handling of error responses to server packets with TTL=2 """
Juraj Slobodab33f4132017-02-08 23:54:21 -08001606
Matus Fabian2ba92e32017-08-21 07:05:03 -07001607 self.nat44_add_address(self.nat_addr)
1608 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1609 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1610 is_inside=0)
Juraj Slobodab33f4132017-02-08 23:54:21 -08001611
1612 # Client side - create sessions
1613 pkts = self.create_stream_in(self.pg0, self.pg1)
1614 self.pg0.add_stream(pkts)
1615 self.pg_enable_capture(self.pg_interfaces)
1616 self.pg_start()
1617
1618 # Server side - generate traffic
1619 capture = self.pg1.get_capture(len(pkts))
1620 self.verify_capture_out(capture)
1621 pkts = self.create_stream_out(self.pg1, ttl=2)
1622 self.pg1.add_stream(pkts)
1623 self.pg_enable_capture(self.pg_interfaces)
1624 self.pg_start()
1625
1626 # Client side - simulate ICMP type 11 response
1627 capture = self.pg0.get_capture(len(pkts))
1628 pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1629 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
1630 ICMP(type=11) / packet[IP] for packet in capture]
1631 self.pg0.add_stream(pkts)
1632 self.pg_enable_capture(self.pg_interfaces)
1633 self.pg_start()
1634
1635 # Server side - verify ICMP type 11 packets
1636 capture = self.pg1.get_capture(len(pkts))
1637 self.verify_capture_out_with_icmp_errors(capture)
1638
Juraj Sloboda665e4822017-02-16 17:17:19 -08001639 def test_ping_out_interface_from_outside(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001640 """ Ping NAT44 out interface from outside network """
Juraj Sloboda665e4822017-02-16 17:17:19 -08001641
Matus Fabian2ba92e32017-08-21 07:05:03 -07001642 self.nat44_add_address(self.nat_addr)
1643 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1644 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1645 is_inside=0)
Juraj Sloboda665e4822017-02-16 17:17:19 -08001646
1647 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1648 IP(src=self.pg1.remote_ip4, dst=self.pg1.local_ip4) /
1649 ICMP(id=self.icmp_id_out, type='echo-request'))
1650 pkts = [p]
1651 self.pg1.add_stream(pkts)
1652 self.pg_enable_capture(self.pg_interfaces)
1653 self.pg_start()
1654 capture = self.pg1.get_capture(len(pkts))
Juraj Sloboda665e4822017-02-16 17:17:19 -08001655 packet = capture[0]
1656 try:
1657 self.assertEqual(packet[IP].src, self.pg1.local_ip4)
1658 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
1659 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
1660 self.assertEqual(packet[ICMP].type, 0) # echo reply
1661 except:
1662 self.logger.error(ppp("Unexpected or invalid packet "
1663 "(outside network):", packet))
1664 raise
1665
Juraj Slobodad3677682017-04-14 03:24:45 +02001666 def test_ping_internal_host_from_outside(self):
1667 """ Ping internal host from outside network """
1668
Matus Fabian2ba92e32017-08-21 07:05:03 -07001669 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr)
1670 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1671 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1672 is_inside=0)
Juraj Slobodad3677682017-04-14 03:24:45 +02001673
1674 # out2in
1675 pkt = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07001676 IP(src=self.pg1.remote_ip4, dst=self.nat_addr, ttl=64) /
Juraj Slobodad3677682017-04-14 03:24:45 +02001677 ICMP(id=self.icmp_id_out, type='echo-request'))
1678 self.pg1.add_stream(pkt)
1679 self.pg_enable_capture(self.pg_interfaces)
1680 self.pg_start()
1681 capture = self.pg0.get_capture(1)
Matus Fabian05ca4a32018-09-04 23:45:13 -07001682 self.verify_capture_in(capture, self.pg0)
Juraj Slobodad3677682017-04-14 03:24:45 +02001683 self.assert_equal(capture[0][IP].proto, IP_PROTOS.icmp)
1684
1685 # in2out
1686 pkt = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1687 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4, ttl=64) /
1688 ICMP(id=self.icmp_id_in, type='echo-reply'))
1689 self.pg0.add_stream(pkt)
1690 self.pg_enable_capture(self.pg_interfaces)
1691 self.pg_start()
1692 capture = self.pg1.get_capture(1)
Matus Fabian05ca4a32018-09-04 23:45:13 -07001693 self.verify_capture_out(capture, same_port=True)
Juraj Slobodad3677682017-04-14 03:24:45 +02001694 self.assert_equal(capture[0][IP].proto, IP_PROTOS.icmp)
1695
Matus Fabianc79396e2018-07-23 00:05:22 -07001696 def test_forwarding(self):
Juraj Sloboda7b929792017-11-23 13:20:48 +01001697 """ NAT44 forwarding test """
1698
1699 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1700 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1701 is_inside=0)
1702 self.vapi.nat44_forwarding_enable_disable(1)
1703
1704 real_ip = self.pg0.remote_ip4n
1705 alias_ip = self.nat_addr_n
1706 self.vapi.nat44_add_del_static_mapping(local_ip=real_ip,
1707 external_ip=alias_ip)
1708
1709 try:
Matus Fabianc79396e2018-07-23 00:05:22 -07001710 # static mapping match
Juraj Sloboda7b929792017-11-23 13:20:48 +01001711
1712 pkts = self.create_stream_out(self.pg1)
1713 self.pg1.add_stream(pkts)
1714 self.pg_enable_capture(self.pg_interfaces)
1715 self.pg_start()
1716 capture = self.pg0.get_capture(len(pkts))
1717 self.verify_capture_in(capture, self.pg0)
1718
1719 pkts = self.create_stream_in(self.pg0, self.pg1)
1720 self.pg0.add_stream(pkts)
1721 self.pg_enable_capture(self.pg_interfaces)
1722 self.pg_start()
1723 capture = self.pg1.get_capture(len(pkts))
1724 self.verify_capture_out(capture, same_port=True)
1725
Matus Fabianc79396e2018-07-23 00:05:22 -07001726 # no static mapping match
Juraj Sloboda7b929792017-11-23 13:20:48 +01001727
1728 host0 = self.pg0.remote_hosts[0]
1729 self.pg0.remote_hosts[0] = self.pg0.remote_hosts[1]
1730 try:
1731 pkts = self.create_stream_out(self.pg1,
1732 dst_ip=self.pg0.remote_ip4,
1733 use_inside_ports=True)
1734 self.pg1.add_stream(pkts)
1735 self.pg_enable_capture(self.pg_interfaces)
1736 self.pg_start()
1737 capture = self.pg0.get_capture(len(pkts))
1738 self.verify_capture_in(capture, self.pg0)
1739
1740 pkts = self.create_stream_in(self.pg0, self.pg1)
1741 self.pg0.add_stream(pkts)
1742 self.pg_enable_capture(self.pg_interfaces)
1743 self.pg_start()
1744 capture = self.pg1.get_capture(len(pkts))
1745 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
1746 same_port=True)
1747 finally:
1748 self.pg0.remote_hosts[0] = host0
1749
1750 finally:
1751 self.vapi.nat44_forwarding_enable_disable(0)
1752 self.vapi.nat44_add_del_static_mapping(local_ip=real_ip,
1753 external_ip=alias_ip,
1754 is_add=0)
1755
Matus Fabiande886752016-12-07 03:38:19 -08001756 def test_static_in(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001757 """ 1:1 NAT initialized from inside network """
Matus Fabiande886752016-12-07 03:38:19 -08001758
1759 nat_ip = "10.0.0.10"
1760 self.tcp_port_out = 6303
1761 self.udp_port_out = 6304
1762 self.icmp_id_out = 6305
1763
Matus Fabian2ba92e32017-08-21 07:05:03 -07001764 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
1765 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1766 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1767 is_inside=0)
Matus Fabian5f224992018-01-25 21:59:16 -08001768 sm = self.vapi.nat44_static_mapping_dump()
1769 self.assertEqual(len(sm), 1)
1770 self.assertEqual((sm[0].tag).split('\0', 1)[0], '')
Matus Fabian9dba7812018-01-31 01:13:23 -08001771 self.assertEqual(sm[0].protocol, 0)
1772 self.assertEqual(sm[0].local_port, 0)
1773 self.assertEqual(sm[0].external_port, 0)
Matus Fabiande886752016-12-07 03:38:19 -08001774
1775 # in2out
1776 pkts = self.create_stream_in(self.pg0, self.pg1)
1777 self.pg0.add_stream(pkts)
1778 self.pg_enable_capture(self.pg_interfaces)
1779 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001780 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001781 self.verify_capture_out(capture, nat_ip, True)
1782
1783 # out2in
1784 pkts = self.create_stream_out(self.pg1, nat_ip)
1785 self.pg1.add_stream(pkts)
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(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001789 self.verify_capture_in(capture, self.pg0)
1790
1791 def test_static_out(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001792 """ 1:1 NAT initialized from outside network """
Matus Fabiande886752016-12-07 03:38:19 -08001793
1794 nat_ip = "10.0.0.20"
1795 self.tcp_port_out = 6303
1796 self.udp_port_out = 6304
1797 self.icmp_id_out = 6305
Matus Fabian5f224992018-01-25 21:59:16 -08001798 tag = "testTAG"
Matus Fabiande886752016-12-07 03:38:19 -08001799
Matus Fabian5f224992018-01-25 21:59:16 -08001800 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip, tag=tag)
Matus Fabian2ba92e32017-08-21 07:05:03 -07001801 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1802 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1803 is_inside=0)
Matus Fabian5f224992018-01-25 21:59:16 -08001804 sm = self.vapi.nat44_static_mapping_dump()
1805 self.assertEqual(len(sm), 1)
1806 self.assertEqual((sm[0].tag).split('\0', 1)[0], tag)
Matus Fabiande886752016-12-07 03:38:19 -08001807
1808 # out2in
1809 pkts = self.create_stream_out(self.pg1, nat_ip)
1810 self.pg1.add_stream(pkts)
1811 self.pg_enable_capture(self.pg_interfaces)
1812 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001813 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001814 self.verify_capture_in(capture, self.pg0)
1815
1816 # in2out
1817 pkts = self.create_stream_in(self.pg0, self.pg1)
1818 self.pg0.add_stream(pkts)
1819 self.pg_enable_capture(self.pg_interfaces)
1820 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001821 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001822 self.verify_capture_out(capture, nat_ip, True)
1823
1824 def test_static_with_port_in(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001825 """ 1:1 NAPT initialized from inside network """
Matus Fabiande886752016-12-07 03:38:19 -08001826
1827 self.tcp_port_out = 3606
1828 self.udp_port_out = 3607
1829 self.icmp_id_out = 3608
1830
Matus Fabian2ba92e32017-08-21 07:05:03 -07001831 self.nat44_add_address(self.nat_addr)
1832 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1833 self.tcp_port_in, self.tcp_port_out,
1834 proto=IP_PROTOS.tcp)
1835 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1836 self.udp_port_in, self.udp_port_out,
1837 proto=IP_PROTOS.udp)
1838 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1839 self.icmp_id_in, self.icmp_id_out,
1840 proto=IP_PROTOS.icmp)
1841 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1842 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1843 is_inside=0)
Matus Fabiande886752016-12-07 03:38:19 -08001844
1845 # in2out
1846 pkts = self.create_stream_in(self.pg0, self.pg1)
1847 self.pg0.add_stream(pkts)
1848 self.pg_enable_capture(self.pg_interfaces)
1849 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001850 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001851 self.verify_capture_out(capture)
1852
1853 # out2in
1854 pkts = self.create_stream_out(self.pg1)
1855 self.pg1.add_stream(pkts)
1856 self.pg_enable_capture(self.pg_interfaces)
1857 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001858 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001859 self.verify_capture_in(capture, self.pg0)
1860
1861 def test_static_with_port_out(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001862 """ 1:1 NAPT initialized from outside network """
Matus Fabiande886752016-12-07 03:38:19 -08001863
1864 self.tcp_port_out = 30606
1865 self.udp_port_out = 30607
1866 self.icmp_id_out = 30608
1867
Matus Fabian2ba92e32017-08-21 07:05:03 -07001868 self.nat44_add_address(self.nat_addr)
1869 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1870 self.tcp_port_in, self.tcp_port_out,
1871 proto=IP_PROTOS.tcp)
1872 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1873 self.udp_port_in, self.udp_port_out,
1874 proto=IP_PROTOS.udp)
1875 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1876 self.icmp_id_in, self.icmp_id_out,
1877 proto=IP_PROTOS.icmp)
1878 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1879 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1880 is_inside=0)
Matus Fabiande886752016-12-07 03:38:19 -08001881
1882 # out2in
1883 pkts = self.create_stream_out(self.pg1)
1884 self.pg1.add_stream(pkts)
1885 self.pg_enable_capture(self.pg_interfaces)
1886 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001887 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001888 self.verify_capture_in(capture, self.pg0)
1889
1890 # in2out
1891 pkts = self.create_stream_in(self.pg0, self.pg1)
1892 self.pg0.add_stream(pkts)
1893 self.pg_enable_capture(self.pg_interfaces)
1894 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001895 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001896 self.verify_capture_out(capture)
1897
1898 def test_static_vrf_aware(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001899 """ 1:1 NAT VRF awareness """
Matus Fabiande886752016-12-07 03:38:19 -08001900
1901 nat_ip1 = "10.0.0.30"
1902 nat_ip2 = "10.0.0.40"
1903 self.tcp_port_out = 6303
1904 self.udp_port_out = 6304
1905 self.icmp_id_out = 6305
1906
Matus Fabian2ba92e32017-08-21 07:05:03 -07001907 self.nat44_add_static_mapping(self.pg4.remote_ip4, nat_ip1,
1908 vrf_id=10)
1909 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip2,
1910 vrf_id=10)
1911 self.vapi.nat44_interface_add_del_feature(self.pg3.sw_if_index,
1912 is_inside=0)
1913 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1914 self.vapi.nat44_interface_add_del_feature(self.pg4.sw_if_index)
Matus Fabiande886752016-12-07 03:38:19 -08001915
Matus Fabian2ba92e32017-08-21 07:05:03 -07001916 # inside interface VRF match NAT44 static mapping VRF
Matus Fabiande886752016-12-07 03:38:19 -08001917 pkts = self.create_stream_in(self.pg4, self.pg3)
1918 self.pg4.add_stream(pkts)
1919 self.pg_enable_capture(self.pg_interfaces)
1920 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001921 capture = self.pg3.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001922 self.verify_capture_out(capture, nat_ip1, True)
1923
Matus Fabian2ba92e32017-08-21 07:05:03 -07001924 # inside interface VRF don't match NAT44 static mapping VRF (packets
Matus Fabiande886752016-12-07 03:38:19 -08001925 # are dropped)
1926 pkts = self.create_stream_in(self.pg0, self.pg3)
1927 self.pg0.add_stream(pkts)
1928 self.pg_enable_capture(self.pg_interfaces)
1929 self.pg_start()
Klement Sekera9225dee2016-12-12 08:36:58 +01001930 self.pg3.assert_nothing_captured()
Matus Fabiande886752016-12-07 03:38:19 -08001931
Matus Fabianb793d092018-01-31 05:50:21 -08001932 def test_dynamic_to_static(self):
1933 """ Switch from dynamic translation to 1:1NAT """
1934 nat_ip = "10.0.0.10"
1935 self.tcp_port_out = 6303
1936 self.udp_port_out = 6304
1937 self.icmp_id_out = 6305
1938
1939 self.nat44_add_address(self.nat_addr)
1940 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1941 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1942 is_inside=0)
1943
1944 # dynamic
1945 pkts = self.create_stream_in(self.pg0, self.pg1)
1946 self.pg0.add_stream(pkts)
1947 self.pg_enable_capture(self.pg_interfaces)
1948 self.pg_start()
1949 capture = self.pg1.get_capture(len(pkts))
1950 self.verify_capture_out(capture)
1951
1952 # 1:1NAT
1953 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
1954 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
1955 self.assertEqual(len(sessions), 0)
1956 pkts = self.create_stream_in(self.pg0, self.pg1)
1957 self.pg0.add_stream(pkts)
1958 self.pg_enable_capture(self.pg_interfaces)
1959 self.pg_start()
1960 capture = self.pg1.get_capture(len(pkts))
1961 self.verify_capture_out(capture, nat_ip, True)
1962
Matus Fabianab7a8052017-11-28 04:29:41 -08001963 def test_identity_nat(self):
1964 """ Identity NAT """
1965
1966 self.vapi.nat44_add_del_identity_mapping(ip=self.pg0.remote_ip4n)
1967 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1968 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1969 is_inside=0)
1970
1971 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
1972 IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
1973 TCP(sport=12345, dport=56789))
1974 self.pg1.add_stream(p)
1975 self.pg_enable_capture(self.pg_interfaces)
1976 self.pg_start()
1977 capture = self.pg0.get_capture(1)
1978 p = capture[0]
1979 try:
1980 ip = p[IP]
1981 tcp = p[TCP]
1982 self.assertEqual(ip.dst, self.pg0.remote_ip4)
1983 self.assertEqual(ip.src, self.pg1.remote_ip4)
1984 self.assertEqual(tcp.dport, 56789)
1985 self.assertEqual(tcp.sport, 12345)
Klement Sekerad81ae412018-05-16 10:52:54 +02001986 self.assert_packet_checksums_valid(p)
Matus Fabianab7a8052017-11-28 04:29:41 -08001987 except:
1988 self.logger.error(ppp("Unexpected or invalid packet:", p))
1989 raise
1990
Matus Fabiane2f4e2f2018-10-07 21:28:23 -07001991 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
1992 self.assertEqual(len(sessions), 0)
Matus Fabian82b4ceb2018-10-11 04:28:48 -07001993 self.vapi.nat44_add_del_identity_mapping(ip=self.pg0.remote_ip4n,
1994 vrf_id=1)
1995 identity_mappings = self.vapi.nat44_identity_mapping_dump()
1996 self.assertEqual(len(identity_mappings), 2)
Matus Fabiane2f4e2f2018-10-07 21:28:23 -07001997
Matus Fabiande886752016-12-07 03:38:19 -08001998 def test_multiple_inside_interfaces(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001999 """ NAT44 multiple non-overlapping address space inside interfaces """
Matus Fabiande886752016-12-07 03:38:19 -08002000
Matus Fabian2ba92e32017-08-21 07:05:03 -07002001 self.nat44_add_address(self.nat_addr)
2002 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2003 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
2004 self.vapi.nat44_interface_add_del_feature(self.pg3.sw_if_index,
2005 is_inside=0)
Matus Fabiande886752016-12-07 03:38:19 -08002006
Matus Fabian2ba92e32017-08-21 07:05:03 -07002007 # between two NAT44 inside interfaces (no translation)
Matus Fabian675a69c2017-01-18 01:46:01 -08002008 pkts = self.create_stream_in(self.pg0, self.pg1)
2009 self.pg0.add_stream(pkts)
2010 self.pg_enable_capture(self.pg_interfaces)
2011 self.pg_start()
2012 capture = self.pg1.get_capture(len(pkts))
2013 self.verify_capture_no_translation(capture, self.pg0, self.pg1)
2014
Matus Fabian2ba92e32017-08-21 07:05:03 -07002015 # from NAT44 inside to interface without NAT44 feature (no translation)
Matus Fabian675a69c2017-01-18 01:46:01 -08002016 pkts = self.create_stream_in(self.pg0, self.pg2)
2017 self.pg0.add_stream(pkts)
2018 self.pg_enable_capture(self.pg_interfaces)
2019 self.pg_start()
2020 capture = self.pg2.get_capture(len(pkts))
2021 self.verify_capture_no_translation(capture, self.pg0, self.pg2)
2022
Matus Fabiande886752016-12-07 03:38:19 -08002023 # in2out 1st interface
2024 pkts = self.create_stream_in(self.pg0, self.pg3)
2025 self.pg0.add_stream(pkts)
2026 self.pg_enable_capture(self.pg_interfaces)
2027 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002028 capture = self.pg3.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002029 self.verify_capture_out(capture)
2030
2031 # out2in 1st interface
2032 pkts = self.create_stream_out(self.pg3)
2033 self.pg3.add_stream(pkts)
2034 self.pg_enable_capture(self.pg_interfaces)
2035 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002036 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002037 self.verify_capture_in(capture, self.pg0)
2038
2039 # in2out 2nd interface
2040 pkts = self.create_stream_in(self.pg1, self.pg3)
2041 self.pg1.add_stream(pkts)
2042 self.pg_enable_capture(self.pg_interfaces)
2043 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002044 capture = self.pg3.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002045 self.verify_capture_out(capture)
2046
2047 # out2in 2nd interface
2048 pkts = self.create_stream_out(self.pg3)
2049 self.pg3.add_stream(pkts)
2050 self.pg_enable_capture(self.pg_interfaces)
2051 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002052 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002053 self.verify_capture_in(capture, self.pg1)
2054
Matus Fabiande886752016-12-07 03:38:19 -08002055 def test_inside_overlapping_interfaces(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002056 """ NAT44 multiple inside interfaces with overlapping address space """
Matus Fabiande886752016-12-07 03:38:19 -08002057
Matus Fabian675a69c2017-01-18 01:46:01 -08002058 static_nat_ip = "10.0.0.10"
Matus Fabian2ba92e32017-08-21 07:05:03 -07002059 self.nat44_add_address(self.nat_addr)
2060 self.vapi.nat44_interface_add_del_feature(self.pg3.sw_if_index,
2061 is_inside=0)
2062 self.vapi.nat44_interface_add_del_feature(self.pg4.sw_if_index)
2063 self.vapi.nat44_interface_add_del_feature(self.pg5.sw_if_index)
2064 self.vapi.nat44_interface_add_del_feature(self.pg6.sw_if_index)
2065 self.nat44_add_static_mapping(self.pg6.remote_ip4, static_nat_ip,
2066 vrf_id=20)
Matus Fabian675a69c2017-01-18 01:46:01 -08002067
Matus Fabian2ba92e32017-08-21 07:05:03 -07002068 # between NAT44 inside interfaces with same VRF (no translation)
Matus Fabian675a69c2017-01-18 01:46:01 -08002069 pkts = self.create_stream_in(self.pg4, self.pg5)
2070 self.pg4.add_stream(pkts)
2071 self.pg_enable_capture(self.pg_interfaces)
2072 self.pg_start()
2073 capture = self.pg5.get_capture(len(pkts))
2074 self.verify_capture_no_translation(capture, self.pg4, self.pg5)
2075
Matus Fabian2ba92e32017-08-21 07:05:03 -07002076 # between NAT44 inside interfaces with different VRF (hairpinning)
Matus Fabian675a69c2017-01-18 01:46:01 -08002077 p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
2078 IP(src=self.pg4.remote_ip4, dst=static_nat_ip) /
2079 TCP(sport=1234, dport=5678))
2080 self.pg4.add_stream(p)
2081 self.pg_enable_capture(self.pg_interfaces)
2082 self.pg_start()
2083 capture = self.pg6.get_capture(1)
2084 p = capture[0]
2085 try:
2086 ip = p[IP]
2087 tcp = p[TCP]
Matus Fabian2ba92e32017-08-21 07:05:03 -07002088 self.assertEqual(ip.src, self.nat_addr)
Matus Fabian675a69c2017-01-18 01:46:01 -08002089 self.assertEqual(ip.dst, self.pg6.remote_ip4)
2090 self.assertNotEqual(tcp.sport, 1234)
2091 self.assertEqual(tcp.dport, 5678)
2092 except:
2093 self.logger.error(ppp("Unexpected or invalid packet:", p))
2094 raise
Matus Fabiande886752016-12-07 03:38:19 -08002095
2096 # in2out 1st interface
2097 pkts = self.create_stream_in(self.pg4, self.pg3)
2098 self.pg4.add_stream(pkts)
2099 self.pg_enable_capture(self.pg_interfaces)
2100 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002101 capture = self.pg3.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002102 self.verify_capture_out(capture)
2103
2104 # out2in 1st interface
2105 pkts = self.create_stream_out(self.pg3)
2106 self.pg3.add_stream(pkts)
2107 self.pg_enable_capture(self.pg_interfaces)
2108 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002109 capture = self.pg4.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002110 self.verify_capture_in(capture, self.pg4)
2111
2112 # in2out 2nd interface
2113 pkts = self.create_stream_in(self.pg5, self.pg3)
2114 self.pg5.add_stream(pkts)
2115 self.pg_enable_capture(self.pg_interfaces)
2116 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002117 capture = self.pg3.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002118 self.verify_capture_out(capture)
2119
2120 # out2in 2nd interface
2121 pkts = self.create_stream_out(self.pg3)
2122 self.pg3.add_stream(pkts)
2123 self.pg_enable_capture(self.pg_interfaces)
2124 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002125 capture = self.pg5.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002126 self.verify_capture_in(capture, self.pg5)
2127
magalik23caa882017-02-08 23:25:45 -08002128 # pg5 session dump
Matus Fabian2ba92e32017-08-21 07:05:03 -07002129 addresses = self.vapi.nat44_address_dump()
magalik23caa882017-02-08 23:25:45 -08002130 self.assertEqual(len(addresses), 1)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002131 sessions = self.vapi.nat44_user_session_dump(self.pg5.remote_ip4n, 10)
magalik23caa882017-02-08 23:25:45 -08002132 self.assertEqual(len(sessions), 3)
2133 for session in sessions:
2134 self.assertFalse(session.is_static)
2135 self.assertEqual(session.inside_ip_address[0:4],
2136 self.pg5.remote_ip4n)
2137 self.assertEqual(session.outside_ip_address,
2138 addresses[0].ip_address)
2139 self.assertEqual(sessions[0].protocol, IP_PROTOS.tcp)
2140 self.assertEqual(sessions[1].protocol, IP_PROTOS.udp)
2141 self.assertEqual(sessions[2].protocol, IP_PROTOS.icmp)
2142 self.assertEqual(sessions[0].inside_port, self.tcp_port_in)
2143 self.assertEqual(sessions[1].inside_port, self.udp_port_in)
2144 self.assertEqual(sessions[2].inside_port, self.icmp_id_in)
2145 self.assertEqual(sessions[0].outside_port, self.tcp_port_out)
2146 self.assertEqual(sessions[1].outside_port, self.udp_port_out)
2147 self.assertEqual(sessions[2].outside_port, self.icmp_id_out)
2148
Matus Fabiande886752016-12-07 03:38:19 -08002149 # in2out 3rd interface
2150 pkts = self.create_stream_in(self.pg6, self.pg3)
2151 self.pg6.add_stream(pkts)
2152 self.pg_enable_capture(self.pg_interfaces)
2153 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002154 capture = self.pg3.get_capture(len(pkts))
Matus Fabian675a69c2017-01-18 01:46:01 -08002155 self.verify_capture_out(capture, static_nat_ip, True)
Matus Fabiande886752016-12-07 03:38:19 -08002156
2157 # out2in 3rd interface
Matus Fabian675a69c2017-01-18 01:46:01 -08002158 pkts = self.create_stream_out(self.pg3, static_nat_ip)
Matus Fabiande886752016-12-07 03:38:19 -08002159 self.pg3.add_stream(pkts)
2160 self.pg_enable_capture(self.pg_interfaces)
2161 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002162 capture = self.pg6.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002163 self.verify_capture_in(capture, self.pg6)
2164
magalik23caa882017-02-08 23:25:45 -08002165 # general user and session dump verifications
Matus Fabian2ba92e32017-08-21 07:05:03 -07002166 users = self.vapi.nat44_user_dump()
Paul Vinciguerra3d2df212018-11-24 23:19:53 -08002167 self.assertGreaterEqual(len(users), 3)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002168 addresses = self.vapi.nat44_address_dump()
magalik23caa882017-02-08 23:25:45 -08002169 self.assertEqual(len(addresses), 1)
2170 for user in users:
Matus Fabian2ba92e32017-08-21 07:05:03 -07002171 sessions = self.vapi.nat44_user_session_dump(user.ip_address,
2172 user.vrf_id)
magalik23caa882017-02-08 23:25:45 -08002173 for session in sessions:
2174 self.assertEqual(user.ip_address, session.inside_ip_address)
2175 self.assertTrue(session.total_bytes > session.total_pkts > 0)
2176 self.assertTrue(session.protocol in
2177 [IP_PROTOS.tcp, IP_PROTOS.udp,
2178 IP_PROTOS.icmp])
Matus Fabian70a26ac2018-05-14 06:20:28 -07002179 self.assertFalse(session.ext_host_valid)
magalik23caa882017-02-08 23:25:45 -08002180
2181 # pg4 session dump
Matus Fabian2ba92e32017-08-21 07:05:03 -07002182 sessions = self.vapi.nat44_user_session_dump(self.pg4.remote_ip4n, 10)
Paul Vinciguerra3d2df212018-11-24 23:19:53 -08002183 self.assertGreaterEqual(len(sessions), 4)
magalik23caa882017-02-08 23:25:45 -08002184 for session in sessions:
2185 self.assertFalse(session.is_static)
2186 self.assertEqual(session.inside_ip_address[0:4],
2187 self.pg4.remote_ip4n)
2188 self.assertEqual(session.outside_ip_address,
2189 addresses[0].ip_address)
2190
2191 # pg6 session dump
Matus Fabian2ba92e32017-08-21 07:05:03 -07002192 sessions = self.vapi.nat44_user_session_dump(self.pg6.remote_ip4n, 20)
Paul Vinciguerra3d2df212018-11-24 23:19:53 -08002193 self.assertGreaterEqual(len(sessions), 3)
magalik23caa882017-02-08 23:25:45 -08002194 for session in sessions:
2195 self.assertTrue(session.is_static)
2196 self.assertEqual(session.inside_ip_address[0:4],
2197 self.pg6.remote_ip4n)
2198 self.assertEqual(map(ord, session.outside_ip_address[0:4]),
2199 map(int, static_nat_ip.split('.')))
2200 self.assertTrue(session.inside_port in
2201 [self.tcp_port_in, self.udp_port_in,
2202 self.icmp_id_in])
2203
Matus Fabianf78a70d2016-12-12 04:30:39 -08002204 def test_hairpinning(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002205 """ NAT44 hairpinning - 1:1 NAPT """
Matus Fabianf78a70d2016-12-12 04:30:39 -08002206
2207 host = self.pg0.remote_hosts[0]
2208 server = self.pg0.remote_hosts[1]
2209 host_in_port = 1234
2210 host_out_port = 0
2211 server_in_port = 5678
2212 server_out_port = 8765
2213
Matus Fabian2ba92e32017-08-21 07:05:03 -07002214 self.nat44_add_address(self.nat_addr)
2215 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2216 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2217 is_inside=0)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002218 # add static mapping for server
Matus Fabian2ba92e32017-08-21 07:05:03 -07002219 self.nat44_add_static_mapping(server.ip4, self.nat_addr,
2220 server_in_port, server_out_port,
2221 proto=IP_PROTOS.tcp)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002222
2223 # send packet from host to server
2224 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002225 IP(src=host.ip4, dst=self.nat_addr) /
Matus Fabianf78a70d2016-12-12 04:30:39 -08002226 TCP(sport=host_in_port, dport=server_out_port))
2227 self.pg0.add_stream(p)
2228 self.pg_enable_capture(self.pg_interfaces)
2229 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002230 capture = self.pg0.get_capture(1)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002231 p = capture[0]
2232 try:
2233 ip = p[IP]
2234 tcp = p[TCP]
Matus Fabian2ba92e32017-08-21 07:05:03 -07002235 self.assertEqual(ip.src, self.nat_addr)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002236 self.assertEqual(ip.dst, server.ip4)
2237 self.assertNotEqual(tcp.sport, host_in_port)
2238 self.assertEqual(tcp.dport, server_in_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02002239 self.assert_packet_checksums_valid(p)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002240 host_out_port = tcp.sport
2241 except:
Klement Sekera9225dee2016-12-12 08:36:58 +01002242 self.logger.error(ppp("Unexpected or invalid packet:", p))
Matus Fabianf78a70d2016-12-12 04:30:39 -08002243 raise
2244
2245 # send reply from server to host
2246 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002247 IP(src=server.ip4, dst=self.nat_addr) /
Matus Fabianf78a70d2016-12-12 04:30:39 -08002248 TCP(sport=server_in_port, dport=host_out_port))
2249 self.pg0.add_stream(p)
2250 self.pg_enable_capture(self.pg_interfaces)
2251 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002252 capture = self.pg0.get_capture(1)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002253 p = capture[0]
2254 try:
2255 ip = p[IP]
2256 tcp = p[TCP]
Matus Fabian2ba92e32017-08-21 07:05:03 -07002257 self.assertEqual(ip.src, self.nat_addr)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002258 self.assertEqual(ip.dst, host.ip4)
2259 self.assertEqual(tcp.sport, server_out_port)
2260 self.assertEqual(tcp.dport, host_in_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02002261 self.assert_packet_checksums_valid(p)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002262 except:
Matus Fabiane82488f2018-01-18 03:38:45 -08002263 self.logger.error(ppp("Unexpected or invalid packet:", p))
Matus Fabianf78a70d2016-12-12 04:30:39 -08002264 raise
2265
Matus Fabian6fa74c62017-06-05 05:55:48 -07002266 def test_hairpinning2(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002267 """ NAT44 hairpinning - 1:1 NAT"""
Matus Fabian6fa74c62017-06-05 05:55:48 -07002268
2269 server1_nat_ip = "10.0.0.10"
2270 server2_nat_ip = "10.0.0.11"
2271 host = self.pg0.remote_hosts[0]
2272 server1 = self.pg0.remote_hosts[1]
2273 server2 = self.pg0.remote_hosts[2]
2274 server_tcp_port = 22
2275 server_udp_port = 20
2276
Matus Fabian2ba92e32017-08-21 07:05:03 -07002277 self.nat44_add_address(self.nat_addr)
2278 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2279 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2280 is_inside=0)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002281
2282 # add static mapping for servers
Matus Fabian2ba92e32017-08-21 07:05:03 -07002283 self.nat44_add_static_mapping(server1.ip4, server1_nat_ip)
2284 self.nat44_add_static_mapping(server2.ip4, server2_nat_ip)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002285
2286 # host to server1
2287 pkts = []
2288 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2289 IP(src=host.ip4, dst=server1_nat_ip) /
2290 TCP(sport=self.tcp_port_in, dport=server_tcp_port))
2291 pkts.append(p)
2292 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2293 IP(src=host.ip4, dst=server1_nat_ip) /
2294 UDP(sport=self.udp_port_in, dport=server_udp_port))
2295 pkts.append(p)
2296 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2297 IP(src=host.ip4, dst=server1_nat_ip) /
2298 ICMP(id=self.icmp_id_in, type='echo-request'))
2299 pkts.append(p)
2300 self.pg0.add_stream(pkts)
2301 self.pg_enable_capture(self.pg_interfaces)
2302 self.pg_start()
2303 capture = self.pg0.get_capture(len(pkts))
2304 for packet in capture:
2305 try:
Matus Fabian2ba92e32017-08-21 07:05:03 -07002306 self.assertEqual(packet[IP].src, self.nat_addr)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002307 self.assertEqual(packet[IP].dst, server1.ip4)
2308 if packet.haslayer(TCP):
2309 self.assertNotEqual(packet[TCP].sport, self.tcp_port_in)
2310 self.assertEqual(packet[TCP].dport, server_tcp_port)
2311 self.tcp_port_out = packet[TCP].sport
Klement Sekerad81ae412018-05-16 10:52:54 +02002312 self.assert_packet_checksums_valid(packet)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002313 elif packet.haslayer(UDP):
2314 self.assertNotEqual(packet[UDP].sport, self.udp_port_in)
2315 self.assertEqual(packet[UDP].dport, server_udp_port)
2316 self.udp_port_out = packet[UDP].sport
2317 else:
2318 self.assertNotEqual(packet[ICMP].id, self.icmp_id_in)
2319 self.icmp_id_out = packet[ICMP].id
2320 except:
2321 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2322 raise
2323
2324 # server1 to host
2325 pkts = []
2326 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002327 IP(src=server1.ip4, dst=self.nat_addr) /
Matus Fabian6fa74c62017-06-05 05:55:48 -07002328 TCP(sport=server_tcp_port, dport=self.tcp_port_out))
2329 pkts.append(p)
2330 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002331 IP(src=server1.ip4, dst=self.nat_addr) /
Matus Fabian6fa74c62017-06-05 05:55:48 -07002332 UDP(sport=server_udp_port, dport=self.udp_port_out))
2333 pkts.append(p)
2334 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002335 IP(src=server1.ip4, dst=self.nat_addr) /
Matus Fabian6fa74c62017-06-05 05:55:48 -07002336 ICMP(id=self.icmp_id_out, type='echo-reply'))
2337 pkts.append(p)
2338 self.pg0.add_stream(pkts)
2339 self.pg_enable_capture(self.pg_interfaces)
2340 self.pg_start()
2341 capture = self.pg0.get_capture(len(pkts))
2342 for packet in capture:
2343 try:
2344 self.assertEqual(packet[IP].src, server1_nat_ip)
2345 self.assertEqual(packet[IP].dst, host.ip4)
2346 if packet.haslayer(TCP):
2347 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
2348 self.assertEqual(packet[TCP].sport, server_tcp_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02002349 self.assert_packet_checksums_valid(packet)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002350 elif packet.haslayer(UDP):
2351 self.assertEqual(packet[UDP].dport, self.udp_port_in)
2352 self.assertEqual(packet[UDP].sport, server_udp_port)
2353 else:
2354 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
2355 except:
2356 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2357 raise
2358
2359 # server2 to server1
2360 pkts = []
2361 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2362 IP(src=server2.ip4, dst=server1_nat_ip) /
2363 TCP(sport=self.tcp_port_in, dport=server_tcp_port))
2364 pkts.append(p)
2365 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2366 IP(src=server2.ip4, dst=server1_nat_ip) /
2367 UDP(sport=self.udp_port_in, dport=server_udp_port))
2368 pkts.append(p)
2369 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2370 IP(src=server2.ip4, dst=server1_nat_ip) /
2371 ICMP(id=self.icmp_id_in, type='echo-request'))
2372 pkts.append(p)
2373 self.pg0.add_stream(pkts)
2374 self.pg_enable_capture(self.pg_interfaces)
2375 self.pg_start()
2376 capture = self.pg0.get_capture(len(pkts))
2377 for packet in capture:
2378 try:
2379 self.assertEqual(packet[IP].src, server2_nat_ip)
2380 self.assertEqual(packet[IP].dst, server1.ip4)
2381 if packet.haslayer(TCP):
2382 self.assertEqual(packet[TCP].sport, self.tcp_port_in)
2383 self.assertEqual(packet[TCP].dport, server_tcp_port)
2384 self.tcp_port_out = packet[TCP].sport
Klement Sekerad81ae412018-05-16 10:52:54 +02002385 self.assert_packet_checksums_valid(packet)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002386 elif packet.haslayer(UDP):
2387 self.assertEqual(packet[UDP].sport, self.udp_port_in)
2388 self.assertEqual(packet[UDP].dport, server_udp_port)
2389 self.udp_port_out = packet[UDP].sport
2390 else:
2391 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
2392 self.icmp_id_out = packet[ICMP].id
2393 except:
2394 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2395 raise
2396
2397 # server1 to server2
2398 pkts = []
2399 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2400 IP(src=server1.ip4, dst=server2_nat_ip) /
2401 TCP(sport=server_tcp_port, dport=self.tcp_port_out))
2402 pkts.append(p)
2403 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2404 IP(src=server1.ip4, dst=server2_nat_ip) /
2405 UDP(sport=server_udp_port, dport=self.udp_port_out))
2406 pkts.append(p)
2407 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2408 IP(src=server1.ip4, dst=server2_nat_ip) /
2409 ICMP(id=self.icmp_id_out, type='echo-reply'))
2410 pkts.append(p)
2411 self.pg0.add_stream(pkts)
2412 self.pg_enable_capture(self.pg_interfaces)
2413 self.pg_start()
2414 capture = self.pg0.get_capture(len(pkts))
2415 for packet in capture:
2416 try:
2417 self.assertEqual(packet[IP].src, server1_nat_ip)
2418 self.assertEqual(packet[IP].dst, server2.ip4)
2419 if packet.haslayer(TCP):
2420 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
2421 self.assertEqual(packet[TCP].sport, server_tcp_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02002422 self.assert_packet_checksums_valid(packet)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002423 elif packet.haslayer(UDP):
2424 self.assertEqual(packet[UDP].dport, self.udp_port_in)
2425 self.assertEqual(packet[UDP].sport, server_udp_port)
2426 else:
2427 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
2428 except:
2429 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2430 raise
2431
Matus Fabian9902fcd2016-12-21 23:58:46 -08002432 def test_max_translations_per_user(self):
2433 """ MAX translations per user - recycle the least recently used """
2434
Matus Fabian2ba92e32017-08-21 07:05:03 -07002435 self.nat44_add_address(self.nat_addr)
2436 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2437 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2438 is_inside=0)
Matus Fabian9902fcd2016-12-21 23:58:46 -08002439
2440 # get maximum number of translations per user
Matus Fabian2ba92e32017-08-21 07:05:03 -07002441 nat44_config = self.vapi.nat_show_config()
Matus Fabian9902fcd2016-12-21 23:58:46 -08002442
2443 # send more than maximum number of translations per user packets
Matus Fabian2ba92e32017-08-21 07:05:03 -07002444 pkts_num = nat44_config.max_translations_per_user + 5
Matus Fabian9902fcd2016-12-21 23:58:46 -08002445 pkts = []
2446 for port in range(0, pkts_num):
2447 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2448 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2449 TCP(sport=1025 + port))
2450 pkts.append(p)
2451 self.pg0.add_stream(pkts)
2452 self.pg_enable_capture(self.pg_interfaces)
2453 self.pg_start()
2454
2455 # verify number of translated packet
Klement Sekeradab231a2016-12-21 08:50:14 +01002456 self.pg1.get_capture(pkts_num)
Matus Fabian9902fcd2016-12-21 23:58:46 -08002457
Matus Fabian132dc492018-05-09 04:51:03 -07002458 users = self.vapi.nat44_user_dump()
2459 for user in users:
2460 if user.ip_address == self.pg0.remote_ip4n:
2461 self.assertEqual(user.nsessions,
2462 nat44_config.max_translations_per_user)
2463 self.assertEqual(user.nstaticsessions, 0)
2464
2465 tcp_port = 22
2466 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
2467 tcp_port, tcp_port,
2468 proto=IP_PROTOS.tcp)
2469 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2470 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2471 TCP(sport=tcp_port))
2472 self.pg0.add_stream(p)
2473 self.pg_enable_capture(self.pg_interfaces)
2474 self.pg_start()
2475 self.pg1.get_capture(1)
2476 users = self.vapi.nat44_user_dump()
2477 for user in users:
2478 if user.ip_address == self.pg0.remote_ip4n:
2479 self.assertEqual(user.nsessions,
2480 nat44_config.max_translations_per_user - 1)
2481 self.assertEqual(user.nstaticsessions, 1)
2482
Matus Fabian8bf68e82017-01-12 04:24:35 -08002483 def test_interface_addr(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002484 """ Acquire NAT44 addresses from interface """
2485 self.vapi.nat44_add_interface_addr(self.pg7.sw_if_index)
Matus Fabian8bf68e82017-01-12 04:24:35 -08002486
2487 # no address in NAT pool
Matus Fabian2ba92e32017-08-21 07:05:03 -07002488 adresses = self.vapi.nat44_address_dump()
Matus Fabian8bf68e82017-01-12 04:24:35 -08002489 self.assertEqual(0, len(adresses))
2490
2491 # configure interface address and check NAT address pool
2492 self.pg7.config_ip4()
Matus Fabian2ba92e32017-08-21 07:05:03 -07002493 adresses = self.vapi.nat44_address_dump()
Matus Fabian8bf68e82017-01-12 04:24:35 -08002494 self.assertEqual(1, len(adresses))
Matus Fabian36532bd2017-01-23 23:42:28 -08002495 self.assertEqual(adresses[0].ip_address[0:4], self.pg7.local_ip4n)
Matus Fabian8bf68e82017-01-12 04:24:35 -08002496
2497 # remove interface address and check NAT address pool
2498 self.pg7.unconfig_ip4()
Matus Fabian2ba92e32017-08-21 07:05:03 -07002499 adresses = self.vapi.nat44_address_dump()
Matus Fabian8bf68e82017-01-12 04:24:35 -08002500 self.assertEqual(0, len(adresses))
2501
Matus Fabian36532bd2017-01-23 23:42:28 -08002502 def test_interface_addr_static_mapping(self):
2503 """ Static mapping with addresses from interface """
Matus Fabian5f224992018-01-25 21:59:16 -08002504 tag = "testTAG"
2505
Matus Fabian2ba92e32017-08-21 07:05:03 -07002506 self.vapi.nat44_add_interface_addr(self.pg7.sw_if_index)
2507 self.nat44_add_static_mapping(
2508 '1.2.3.4',
Matus Fabian5f224992018-01-25 21:59:16 -08002509 external_sw_if_index=self.pg7.sw_if_index,
2510 tag=tag)
Matus Fabian36532bd2017-01-23 23:42:28 -08002511
Matus Fabiane22e5462017-02-14 23:33:43 -08002512 # static mappings with external interface
Matus Fabian2ba92e32017-08-21 07:05:03 -07002513 static_mappings = self.vapi.nat44_static_mapping_dump()
Matus Fabiane22e5462017-02-14 23:33:43 -08002514 self.assertEqual(1, len(static_mappings))
2515 self.assertEqual(self.pg7.sw_if_index,
2516 static_mappings[0].external_sw_if_index)
Matus Fabian5f224992018-01-25 21:59:16 -08002517 self.assertEqual((static_mappings[0].tag).split('\0', 1)[0], tag)
Matus Fabian36532bd2017-01-23 23:42:28 -08002518
2519 # configure interface address and check static mappings
2520 self.pg7.config_ip4()
Matus Fabian2ba92e32017-08-21 07:05:03 -07002521 static_mappings = self.vapi.nat44_static_mapping_dump()
Matus Fabianea2600a2018-03-28 04:06:26 -07002522 self.assertEqual(2, len(static_mappings))
2523 resolved = False
2524 for sm in static_mappings:
2525 if sm.external_sw_if_index == 0xFFFFFFFF:
2526 self.assertEqual(sm.external_ip_address[0:4],
2527 self.pg7.local_ip4n)
2528 self.assertEqual((sm.tag).split('\0', 1)[0], tag)
2529 resolved = True
2530 self.assertTrue(resolved)
Matus Fabian36532bd2017-01-23 23:42:28 -08002531
2532 # remove interface address and check static mappings
2533 self.pg7.unconfig_ip4()
Matus Fabian2ba92e32017-08-21 07:05:03 -07002534 static_mappings = self.vapi.nat44_static_mapping_dump()
Matus Fabianea2600a2018-03-28 04:06:26 -07002535 self.assertEqual(1, len(static_mappings))
2536 self.assertEqual(self.pg7.sw_if_index,
2537 static_mappings[0].external_sw_if_index)
2538 self.assertEqual((static_mappings[0].tag).split('\0', 1)[0], tag)
2539
2540 # configure interface address again and check static mappings
2541 self.pg7.config_ip4()
2542 static_mappings = self.vapi.nat44_static_mapping_dump()
2543 self.assertEqual(2, len(static_mappings))
2544 resolved = False
2545 for sm in static_mappings:
2546 if sm.external_sw_if_index == 0xFFFFFFFF:
2547 self.assertEqual(sm.external_ip_address[0:4],
2548 self.pg7.local_ip4n)
2549 self.assertEqual((sm.tag).split('\0', 1)[0], tag)
2550 resolved = True
2551 self.assertTrue(resolved)
2552
2553 # remove static mapping
2554 self.nat44_add_static_mapping(
2555 '1.2.3.4',
2556 external_sw_if_index=self.pg7.sw_if_index,
2557 tag=tag,
2558 is_add=0)
2559 static_mappings = self.vapi.nat44_static_mapping_dump()
Matus Fabian36532bd2017-01-23 23:42:28 -08002560 self.assertEqual(0, len(static_mappings))
2561
Matus Fabianab7a8052017-11-28 04:29:41 -08002562 def test_interface_addr_identity_nat(self):
2563 """ Identity NAT with addresses from interface """
2564
2565 port = 53053
2566 self.vapi.nat44_add_interface_addr(self.pg7.sw_if_index)
2567 self.vapi.nat44_add_del_identity_mapping(
2568 sw_if_index=self.pg7.sw_if_index,
2569 port=port,
2570 protocol=IP_PROTOS.tcp,
2571 addr_only=0)
2572
2573 # identity mappings with external interface
2574 identity_mappings = self.vapi.nat44_identity_mapping_dump()
2575 self.assertEqual(1, len(identity_mappings))
2576 self.assertEqual(self.pg7.sw_if_index,
2577 identity_mappings[0].sw_if_index)
2578
2579 # configure interface address and check identity mappings
2580 self.pg7.config_ip4()
2581 identity_mappings = self.vapi.nat44_identity_mapping_dump()
Matus Fabianea2600a2018-03-28 04:06:26 -07002582 resolved = False
2583 self.assertEqual(2, len(identity_mappings))
2584 for sm in identity_mappings:
2585 if sm.sw_if_index == 0xFFFFFFFF:
2586 self.assertEqual(identity_mappings[0].ip_address,
2587 self.pg7.local_ip4n)
2588 self.assertEqual(port, identity_mappings[0].port)
2589 self.assertEqual(IP_PROTOS.tcp, identity_mappings[0].protocol)
2590 resolved = True
2591 self.assertTrue(resolved)
Matus Fabianab7a8052017-11-28 04:29:41 -08002592
2593 # remove interface address and check identity mappings
2594 self.pg7.unconfig_ip4()
2595 identity_mappings = self.vapi.nat44_identity_mapping_dump()
Matus Fabianea2600a2018-03-28 04:06:26 -07002596 self.assertEqual(1, len(identity_mappings))
2597 self.assertEqual(self.pg7.sw_if_index,
2598 identity_mappings[0].sw_if_index)
Matus Fabianab7a8052017-11-28 04:29:41 -08002599
Matus Fabianeea28d72017-01-13 04:15:54 -08002600 def test_ipfix_nat44_sess(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002601 """ IPFIX logging NAT44 session created/delted """
Matus Fabian6631e9c2017-05-24 01:52:20 -07002602 self.ipfix_domain_id = 10
2603 self.ipfix_src_port = 20202
2604 colector_port = 30303
2605 bind_layers(UDP, IPFIX, dport=30303)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002606 self.nat44_add_address(self.nat_addr)
2607 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2608 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2609 is_inside=0)
Matus Fabianeea28d72017-01-13 04:15:54 -08002610 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
2611 src_address=self.pg3.local_ip4n,
2612 path_mtu=512,
Matus Fabian6631e9c2017-05-24 01:52:20 -07002613 template_interval=10,
2614 collector_port=colector_port)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002615 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
2616 src_port=self.ipfix_src_port)
Matus Fabianeea28d72017-01-13 04:15:54 -08002617
2618 pkts = self.create_stream_in(self.pg0, self.pg1)
2619 self.pg0.add_stream(pkts)
2620 self.pg_enable_capture(self.pg_interfaces)
2621 self.pg_start()
2622 capture = self.pg1.get_capture(len(pkts))
2623 self.verify_capture_out(capture)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002624 self.nat44_add_address(self.nat_addr, is_add=0)
Matus Fabianeea28d72017-01-13 04:15:54 -08002625 self.vapi.cli("ipfix flush") # FIXME this should be an API call
Matus Fabiana431ad12018-01-04 04:03:14 -08002626 capture = self.pg3.get_capture(9)
Matus Fabianeea28d72017-01-13 04:15:54 -08002627 ipfix = IPFIXDecoder()
2628 # first load template
2629 for p in capture:
2630 self.assertTrue(p.haslayer(IPFIX))
Matus Fabian6631e9c2017-05-24 01:52:20 -07002631 self.assertEqual(p[IP].src, self.pg3.local_ip4)
2632 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2633 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2634 self.assertEqual(p[UDP].dport, colector_port)
2635 self.assertEqual(p[IPFIX].observationDomainID,
2636 self.ipfix_domain_id)
Matus Fabianeea28d72017-01-13 04:15:54 -08002637 if p.haslayer(Template):
2638 ipfix.add_template(p.getlayer(Template))
2639 # verify events in data set
2640 for p in capture:
2641 if p.haslayer(Data):
2642 data = ipfix.decode_data_set(p.getlayer(Set))
2643 self.verify_ipfix_nat44_ses(data)
2644
2645 def test_ipfix_addr_exhausted(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002646 """ IPFIX logging NAT addresses exhausted """
2647 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2648 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2649 is_inside=0)
Matus Fabianeea28d72017-01-13 04:15:54 -08002650 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
2651 src_address=self.pg3.local_ip4n,
2652 path_mtu=512,
2653 template_interval=10)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002654 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
2655 src_port=self.ipfix_src_port)
Matus Fabianeea28d72017-01-13 04:15:54 -08002656
2657 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
2658 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2659 TCP(sport=3025))
2660 self.pg0.add_stream(p)
2661 self.pg_enable_capture(self.pg_interfaces)
2662 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07002663 self.pg1.assert_nothing_captured()
2664 sleep(1)
Matus Fabianeea28d72017-01-13 04:15:54 -08002665 self.vapi.cli("ipfix flush") # FIXME this should be an API call
Matus Fabiana431ad12018-01-04 04:03:14 -08002666 capture = self.pg3.get_capture(9)
Matus Fabianeea28d72017-01-13 04:15:54 -08002667 ipfix = IPFIXDecoder()
2668 # first load template
2669 for p in capture:
2670 self.assertTrue(p.haslayer(IPFIX))
Matus Fabian6631e9c2017-05-24 01:52:20 -07002671 self.assertEqual(p[IP].src, self.pg3.local_ip4)
2672 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2673 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2674 self.assertEqual(p[UDP].dport, 4739)
2675 self.assertEqual(p[IPFIX].observationDomainID,
2676 self.ipfix_domain_id)
Matus Fabianeea28d72017-01-13 04:15:54 -08002677 if p.haslayer(Template):
2678 ipfix.add_template(p.getlayer(Template))
2679 # verify events in data set
2680 for p in capture:
2681 if p.haslayer(Data):
2682 data = ipfix.decode_data_set(p.getlayer(Set))
2683 self.verify_ipfix_addr_exhausted(data)
2684
Matus Fabiana431ad12018-01-04 04:03:14 -08002685 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
2686 def test_ipfix_max_sessions(self):
2687 """ IPFIX logging maximum session entries exceeded """
2688 self.nat44_add_address(self.nat_addr)
2689 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2690 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2691 is_inside=0)
2692
2693 nat44_config = self.vapi.nat_show_config()
2694 max_sessions = 10 * nat44_config.translation_buckets
2695
2696 pkts = []
2697 for i in range(0, max_sessions):
2698 src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
2699 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2700 IP(src=src, dst=self.pg1.remote_ip4) /
2701 TCP(sport=1025))
2702 pkts.append(p)
2703 self.pg0.add_stream(pkts)
2704 self.pg_enable_capture(self.pg_interfaces)
2705 self.pg_start()
2706
2707 self.pg1.get_capture(max_sessions)
2708 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
2709 src_address=self.pg3.local_ip4n,
2710 path_mtu=512,
2711 template_interval=10)
2712 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
2713 src_port=self.ipfix_src_port)
2714
2715 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2716 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2717 TCP(sport=1025))
2718 self.pg0.add_stream(p)
2719 self.pg_enable_capture(self.pg_interfaces)
2720 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07002721 self.pg1.assert_nothing_captured()
2722 sleep(1)
Matus Fabiana431ad12018-01-04 04:03:14 -08002723 self.vapi.cli("ipfix flush") # FIXME this should be an API call
2724 capture = self.pg3.get_capture(9)
2725 ipfix = IPFIXDecoder()
2726 # first load template
2727 for p in capture:
2728 self.assertTrue(p.haslayer(IPFIX))
2729 self.assertEqual(p[IP].src, self.pg3.local_ip4)
2730 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2731 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2732 self.assertEqual(p[UDP].dport, 4739)
2733 self.assertEqual(p[IPFIX].observationDomainID,
2734 self.ipfix_domain_id)
2735 if p.haslayer(Template):
2736 ipfix.add_template(p.getlayer(Template))
2737 # verify events in data set
2738 for p in capture:
2739 if p.haslayer(Data):
2740 data = ipfix.decode_data_set(p.getlayer(Set))
2741 self.verify_ipfix_max_sessions(data, max_sessions)
2742
Matus Fabianad1f3e12018-11-28 21:26:34 -08002743 def test_syslog_apmap(self):
2744 """ Test syslog address and port mapping creation and deletion """
2745 self.vapi.syslog_set_filter(SYSLOG_SEVERITY.INFO)
2746 self.vapi.syslog_set_sender(self.pg3.remote_ip4n, self.pg3.local_ip4n)
2747 self.nat44_add_address(self.nat_addr)
2748 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2749 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2750 is_inside=0)
2751
2752 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2753 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2754 TCP(sport=self.tcp_port_in, dport=20))
2755 self.pg0.add_stream(p)
2756 self.pg_enable_capture(self.pg_interfaces)
2757 self.pg_start()
2758 capture = self.pg1.get_capture(1)
2759 self.tcp_port_out = capture[0][TCP].sport
2760 capture = self.pg3.get_capture(1)
2761 self.verify_syslog_apmap(capture[0][Raw].load)
2762
2763 self.pg_enable_capture(self.pg_interfaces)
2764 self.pg_start()
2765 self.nat44_add_address(self.nat_addr, is_add=0)
2766 capture = self.pg3.get_capture(1)
2767 self.verify_syslog_apmap(capture[0][Raw].load, False)
2768
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002769 def test_pool_addr_fib(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002770 """ NAT44 add pool addresses to FIB """
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002771 static_addr = '10.0.0.10'
Matus Fabian2ba92e32017-08-21 07:05:03 -07002772 self.nat44_add_address(self.nat_addr)
2773 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2774 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2775 is_inside=0)
2776 self.nat44_add_static_mapping(self.pg0.remote_ip4, static_addr)
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002777
Matus Fabian2ba92e32017-08-21 07:05:03 -07002778 # NAT44 address
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002779 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002780 ARP(op=ARP.who_has, pdst=self.nat_addr,
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002781 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2782 self.pg1.add_stream(p)
2783 self.pg_enable_capture(self.pg_interfaces)
2784 self.pg_start()
2785 capture = self.pg1.get_capture(1)
2786 self.assertTrue(capture[0].haslayer(ARP))
2787 self.assertTrue(capture[0][ARP].op, ARP.is_at)
2788
2789 # 1:1 NAT address
2790 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2791 ARP(op=ARP.who_has, pdst=static_addr,
2792 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2793 self.pg1.add_stream(p)
2794 self.pg_enable_capture(self.pg_interfaces)
2795 self.pg_start()
2796 capture = self.pg1.get_capture(1)
2797 self.assertTrue(capture[0].haslayer(ARP))
2798 self.assertTrue(capture[0][ARP].op, ARP.is_at)
2799
Matus Fabian2ba92e32017-08-21 07:05:03 -07002800 # send ARP to non-NAT44 interface
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002801 p = (Ether(src=self.pg2.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002802 ARP(op=ARP.who_has, pdst=self.nat_addr,
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002803 psrc=self.pg2.remote_ip4, hwsrc=self.pg2.remote_mac))
2804 self.pg2.add_stream(p)
2805 self.pg_enable_capture(self.pg_interfaces)
2806 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07002807 self.pg1.assert_nothing_captured()
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002808
2809 # remove addresses and verify
Matus Fabian2ba92e32017-08-21 07:05:03 -07002810 self.nat44_add_address(self.nat_addr, is_add=0)
2811 self.nat44_add_static_mapping(self.pg0.remote_ip4, static_addr,
2812 is_add=0)
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002813
2814 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002815 ARP(op=ARP.who_has, pdst=self.nat_addr,
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002816 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2817 self.pg1.add_stream(p)
2818 self.pg_enable_capture(self.pg_interfaces)
2819 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07002820 self.pg1.assert_nothing_captured()
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002821
2822 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2823 ARP(op=ARP.who_has, pdst=static_addr,
2824 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2825 self.pg1.add_stream(p)
2826 self.pg_enable_capture(self.pg_interfaces)
2827 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07002828 self.pg1.assert_nothing_captured()
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002829
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002830 def test_vrf_mode(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002831 """ NAT44 tenant VRF aware address pool mode """
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002832
2833 vrf_id1 = 1
2834 vrf_id2 = 2
2835 nat_ip1 = "10.0.0.10"
2836 nat_ip2 = "10.0.0.11"
2837
2838 self.pg0.unconfig_ip4()
2839 self.pg1.unconfig_ip4()
Neale Ranns15002542017-09-10 04:39:11 -07002840 self.vapi.ip_table_add_del(vrf_id1, is_add=1)
2841 self.vapi.ip_table_add_del(vrf_id2, is_add=1)
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002842 self.pg0.set_table_ip4(vrf_id1)
2843 self.pg1.set_table_ip4(vrf_id2)
2844 self.pg0.config_ip4()
2845 self.pg1.config_ip4()
Matus Fabian8008d7c2018-07-09 01:34:20 -07002846 self.pg0.resolve_arp()
2847 self.pg1.resolve_arp()
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002848
Matus Fabian2ba92e32017-08-21 07:05:03 -07002849 self.nat44_add_address(nat_ip1, vrf_id=vrf_id1)
2850 self.nat44_add_address(nat_ip2, vrf_id=vrf_id2)
2851 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2852 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
2853 self.vapi.nat44_interface_add_del_feature(self.pg2.sw_if_index,
2854 is_inside=0)
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002855
Matus Fabian8008d7c2018-07-09 01:34:20 -07002856 try:
2857 # first VRF
2858 pkts = self.create_stream_in(self.pg0, self.pg2)
2859 self.pg0.add_stream(pkts)
2860 self.pg_enable_capture(self.pg_interfaces)
2861 self.pg_start()
2862 capture = self.pg2.get_capture(len(pkts))
2863 self.verify_capture_out(capture, nat_ip1)
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002864
Matus Fabian8008d7c2018-07-09 01:34:20 -07002865 # second VRF
2866 pkts = self.create_stream_in(self.pg1, self.pg2)
2867 self.pg1.add_stream(pkts)
2868 self.pg_enable_capture(self.pg_interfaces)
2869 self.pg_start()
2870 capture = self.pg2.get_capture(len(pkts))
2871 self.verify_capture_out(capture, nat_ip2)
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002872
Matus Fabian8008d7c2018-07-09 01:34:20 -07002873 finally:
2874 self.pg0.unconfig_ip4()
2875 self.pg1.unconfig_ip4()
2876 self.pg0.set_table_ip4(0)
2877 self.pg1.set_table_ip4(0)
2878 self.pg0.config_ip4()
2879 self.pg1.config_ip4()
2880 self.pg0.resolve_arp()
2881 self.pg1.resolve_arp()
2882 self.vapi.ip_table_add_del(vrf_id1, is_add=0)
2883 self.vapi.ip_table_add_del(vrf_id2, is_add=0)
Neale Ranns15002542017-09-10 04:39:11 -07002884
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002885 def test_vrf_feature_independent(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002886 """ NAT44 tenant VRF independent address pool mode """
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002887
2888 nat_ip1 = "10.0.0.10"
2889 nat_ip2 = "10.0.0.11"
2890
Matus Fabian2ba92e32017-08-21 07:05:03 -07002891 self.nat44_add_address(nat_ip1)
Matus Fabian51e759f2017-12-07 23:22:51 -08002892 self.nat44_add_address(nat_ip2, vrf_id=99)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002893 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2894 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
2895 self.vapi.nat44_interface_add_del_feature(self.pg2.sw_if_index,
2896 is_inside=0)
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002897
2898 # first VRF
2899 pkts = self.create_stream_in(self.pg0, self.pg2)
2900 self.pg0.add_stream(pkts)
2901 self.pg_enable_capture(self.pg_interfaces)
2902 self.pg_start()
2903 capture = self.pg2.get_capture(len(pkts))
2904 self.verify_capture_out(capture, nat_ip1)
2905
2906 # second VRF
2907 pkts = self.create_stream_in(self.pg1, self.pg2)
2908 self.pg1.add_stream(pkts)
2909 self.pg_enable_capture(self.pg_interfaces)
2910 self.pg_start()
2911 capture = self.pg2.get_capture(len(pkts))
2912 self.verify_capture_out(capture, nat_ip1)
2913
Martin Gálik406eb1d2017-05-04 04:35:04 -07002914 def test_dynamic_ipless_interfaces(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002915 """ NAT44 interfaces without configured IP address """
Martin Gálik406eb1d2017-05-04 04:35:04 -07002916
2917 self.vapi.ip_neighbor_add_del(self.pg7.sw_if_index,
Ole Troan895b6e82017-10-20 13:28:20 +02002918 mactobinary(self.pg7.remote_mac),
Martin Gálik406eb1d2017-05-04 04:35:04 -07002919 self.pg7.remote_ip4n,
2920 is_static=1)
2921 self.vapi.ip_neighbor_add_del(self.pg8.sw_if_index,
Ole Troan895b6e82017-10-20 13:28:20 +02002922 mactobinary(self.pg8.remote_mac),
Martin Gálik406eb1d2017-05-04 04:35:04 -07002923 self.pg8.remote_ip4n,
2924 is_static=1)
2925
2926 self.vapi.ip_add_del_route(dst_address=self.pg7.remote_ip4n,
2927 dst_address_length=32,
2928 next_hop_address=self.pg7.remote_ip4n,
2929 next_hop_sw_if_index=self.pg7.sw_if_index)
2930 self.vapi.ip_add_del_route(dst_address=self.pg8.remote_ip4n,
2931 dst_address_length=32,
2932 next_hop_address=self.pg8.remote_ip4n,
2933 next_hop_sw_if_index=self.pg8.sw_if_index)
2934
Matus Fabian2ba92e32017-08-21 07:05:03 -07002935 self.nat44_add_address(self.nat_addr)
2936 self.vapi.nat44_interface_add_del_feature(self.pg7.sw_if_index)
2937 self.vapi.nat44_interface_add_del_feature(self.pg8.sw_if_index,
2938 is_inside=0)
Martin Gálik406eb1d2017-05-04 04:35:04 -07002939
2940 # in2out
2941 pkts = self.create_stream_in(self.pg7, self.pg8)
2942 self.pg7.add_stream(pkts)
2943 self.pg_enable_capture(self.pg_interfaces)
2944 self.pg_start()
2945 capture = self.pg8.get_capture(len(pkts))
2946 self.verify_capture_out(capture)
2947
2948 # out2in
Matus Fabian2ba92e32017-08-21 07:05:03 -07002949 pkts = self.create_stream_out(self.pg8, self.nat_addr)
Martin Gálik406eb1d2017-05-04 04:35:04 -07002950 self.pg8.add_stream(pkts)
2951 self.pg_enable_capture(self.pg_interfaces)
2952 self.pg_start()
2953 capture = self.pg7.get_capture(len(pkts))
2954 self.verify_capture_in(capture, self.pg7)
2955
2956 def test_static_ipless_interfaces(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002957 """ NAT44 interfaces without configured IP address - 1:1 NAT """
Martin Gálik406eb1d2017-05-04 04:35:04 -07002958
2959 self.vapi.ip_neighbor_add_del(self.pg7.sw_if_index,
Ole Troan895b6e82017-10-20 13:28:20 +02002960 mactobinary(self.pg7.remote_mac),
Martin Gálik406eb1d2017-05-04 04:35:04 -07002961 self.pg7.remote_ip4n,
2962 is_static=1)
2963 self.vapi.ip_neighbor_add_del(self.pg8.sw_if_index,
Ole Troan895b6e82017-10-20 13:28:20 +02002964 mactobinary(self.pg8.remote_mac),
Martin Gálik406eb1d2017-05-04 04:35:04 -07002965 self.pg8.remote_ip4n,
2966 is_static=1)
2967
2968 self.vapi.ip_add_del_route(dst_address=self.pg7.remote_ip4n,
2969 dst_address_length=32,
2970 next_hop_address=self.pg7.remote_ip4n,
2971 next_hop_sw_if_index=self.pg7.sw_if_index)
2972 self.vapi.ip_add_del_route(dst_address=self.pg8.remote_ip4n,
2973 dst_address_length=32,
2974 next_hop_address=self.pg8.remote_ip4n,
2975 next_hop_sw_if_index=self.pg8.sw_if_index)
2976
Matus Fabian2ba92e32017-08-21 07:05:03 -07002977 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr)
2978 self.vapi.nat44_interface_add_del_feature(self.pg7.sw_if_index)
2979 self.vapi.nat44_interface_add_del_feature(self.pg8.sw_if_index,
2980 is_inside=0)
Martin Gálik406eb1d2017-05-04 04:35:04 -07002981
2982 # out2in
2983 pkts = self.create_stream_out(self.pg8)
2984 self.pg8.add_stream(pkts)
2985 self.pg_enable_capture(self.pg_interfaces)
2986 self.pg_start()
2987 capture = self.pg7.get_capture(len(pkts))
2988 self.verify_capture_in(capture, self.pg7)
2989
2990 # in2out
2991 pkts = self.create_stream_in(self.pg7, self.pg8)
2992 self.pg7.add_stream(pkts)
2993 self.pg_enable_capture(self.pg_interfaces)
2994 self.pg_start()
2995 capture = self.pg8.get_capture(len(pkts))
Matus Fabian2ba92e32017-08-21 07:05:03 -07002996 self.verify_capture_out(capture, self.nat_addr, True)
Martin Gálik406eb1d2017-05-04 04:35:04 -07002997
2998 def test_static_with_port_ipless_interfaces(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002999 """ NAT44 interfaces without configured IP address - 1:1 NAPT """
Martin Gálik406eb1d2017-05-04 04:35:04 -07003000
3001 self.tcp_port_out = 30606
3002 self.udp_port_out = 30607
3003 self.icmp_id_out = 30608
3004
3005 self.vapi.ip_neighbor_add_del(self.pg7.sw_if_index,
Ole Troan895b6e82017-10-20 13:28:20 +02003006 mactobinary(self.pg7.remote_mac),
Martin Gálik406eb1d2017-05-04 04:35:04 -07003007 self.pg7.remote_ip4n,
3008 is_static=1)
3009 self.vapi.ip_neighbor_add_del(self.pg8.sw_if_index,
Ole Troan895b6e82017-10-20 13:28:20 +02003010 mactobinary(self.pg8.remote_mac),
Martin Gálik406eb1d2017-05-04 04:35:04 -07003011 self.pg8.remote_ip4n,
3012 is_static=1)
3013
3014 self.vapi.ip_add_del_route(dst_address=self.pg7.remote_ip4n,
3015 dst_address_length=32,
3016 next_hop_address=self.pg7.remote_ip4n,
3017 next_hop_sw_if_index=self.pg7.sw_if_index)
3018 self.vapi.ip_add_del_route(dst_address=self.pg8.remote_ip4n,
3019 dst_address_length=32,
3020 next_hop_address=self.pg8.remote_ip4n,
3021 next_hop_sw_if_index=self.pg8.sw_if_index)
3022
Matus Fabian2ba92e32017-08-21 07:05:03 -07003023 self.nat44_add_address(self.nat_addr)
3024 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
3025 self.tcp_port_in, self.tcp_port_out,
3026 proto=IP_PROTOS.tcp)
3027 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
3028 self.udp_port_in, self.udp_port_out,
3029 proto=IP_PROTOS.udp)
3030 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
3031 self.icmp_id_in, self.icmp_id_out,
3032 proto=IP_PROTOS.icmp)
3033 self.vapi.nat44_interface_add_del_feature(self.pg7.sw_if_index)
3034 self.vapi.nat44_interface_add_del_feature(self.pg8.sw_if_index,
3035 is_inside=0)
Martin Gálik406eb1d2017-05-04 04:35:04 -07003036
3037 # out2in
3038 pkts = self.create_stream_out(self.pg8)
3039 self.pg8.add_stream(pkts)
3040 self.pg_enable_capture(self.pg_interfaces)
3041 self.pg_start()
3042 capture = self.pg7.get_capture(len(pkts))
3043 self.verify_capture_in(capture, self.pg7)
3044
3045 # in2out
3046 pkts = self.create_stream_in(self.pg7, self.pg8)
3047 self.pg7.add_stream(pkts)
3048 self.pg_enable_capture(self.pg_interfaces)
3049 self.pg_start()
3050 capture = self.pg8.get_capture(len(pkts))
3051 self.verify_capture_out(capture)
3052
Matus Fabian328dbc82017-06-19 04:28:04 -07003053 def test_static_unknown_proto(self):
3054 """ 1:1 NAT translate packet with unknown protocol """
3055 nat_ip = "10.0.0.10"
Matus Fabian2ba92e32017-08-21 07:05:03 -07003056 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
3057 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3058 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3059 is_inside=0)
Matus Fabian328dbc82017-06-19 04:28:04 -07003060
3061 # in2out
3062 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3063 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3064 GRE() /
Matus Fabian1e8db5f2017-06-20 01:45:49 -07003065 IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4) /
Matus Fabian328dbc82017-06-19 04:28:04 -07003066 TCP(sport=1234, dport=1234))
3067 self.pg0.add_stream(p)
3068 self.pg_enable_capture(self.pg_interfaces)
3069 self.pg_start()
3070 p = self.pg1.get_capture(1)
3071 packet = p[0]
3072 try:
3073 self.assertEqual(packet[IP].src, nat_ip)
3074 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
Paul Vinciguerra978aa642018-11-24 22:19:12 -08003075 self.assertEqual(packet.haslayer(GRE), 1)
Klement Sekerad81ae412018-05-16 10:52:54 +02003076 self.assert_packet_checksums_valid(packet)
Matus Fabian328dbc82017-06-19 04:28:04 -07003077 except:
3078 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3079 raise
3080
3081 # out2in
3082 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
3083 IP(src=self.pg1.remote_ip4, dst=nat_ip) /
3084 GRE() /
Matus Fabian1e8db5f2017-06-20 01:45:49 -07003085 IP(src=self.pg3.remote_ip4, dst=self.pg2.remote_ip4) /
Matus Fabian328dbc82017-06-19 04:28:04 -07003086 TCP(sport=1234, dport=1234))
3087 self.pg1.add_stream(p)
3088 self.pg_enable_capture(self.pg_interfaces)
3089 self.pg_start()
3090 p = self.pg0.get_capture(1)
3091 packet = p[0]
3092 try:
3093 self.assertEqual(packet[IP].src, self.pg1.remote_ip4)
3094 self.assertEqual(packet[IP].dst, self.pg0.remote_ip4)
Paul Vinciguerra978aa642018-11-24 22:19:12 -08003095 self.assertEqual(packet.haslayer(GRE), 1)
Klement Sekerad81ae412018-05-16 10:52:54 +02003096 self.assert_packet_checksums_valid(packet)
Matus Fabian328dbc82017-06-19 04:28:04 -07003097 except:
3098 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3099 raise
3100
Matus Fabian7968e6c2017-07-06 05:37:49 -07003101 def test_hairpinning_static_unknown_proto(self):
Matus Fabian1e8db5f2017-06-20 01:45:49 -07003102 """ 1:1 NAT translate packet with unknown protocol - hairpinning """
3103
3104 host = self.pg0.remote_hosts[0]
3105 server = self.pg0.remote_hosts[1]
3106
3107 host_nat_ip = "10.0.0.10"
3108 server_nat_ip = "10.0.0.11"
3109
Matus Fabian2ba92e32017-08-21 07:05:03 -07003110 self.nat44_add_static_mapping(host.ip4, host_nat_ip)
3111 self.nat44_add_static_mapping(server.ip4, server_nat_ip)
3112 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3113 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3114 is_inside=0)
Matus Fabian1e8db5f2017-06-20 01:45:49 -07003115
3116 # host to server
3117 p = (Ether(dst=self.pg0.local_mac, src=host.mac) /
3118 IP(src=host.ip4, dst=server_nat_ip) /
3119 GRE() /
3120 IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4) /
3121 TCP(sport=1234, dport=1234))
3122 self.pg0.add_stream(p)
3123 self.pg_enable_capture(self.pg_interfaces)
3124 self.pg_start()
3125 p = self.pg0.get_capture(1)
3126 packet = p[0]
3127 try:
3128 self.assertEqual(packet[IP].src, host_nat_ip)
3129 self.assertEqual(packet[IP].dst, server.ip4)
Paul Vinciguerra978aa642018-11-24 22:19:12 -08003130 self.assertEqual(packet.haslayer(GRE), 1)
Klement Sekerad81ae412018-05-16 10:52:54 +02003131 self.assert_packet_checksums_valid(packet)
Matus Fabian1e8db5f2017-06-20 01:45:49 -07003132 except:
3133 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3134 raise
3135
3136 # server to host
3137 p = (Ether(dst=self.pg0.local_mac, src=server.mac) /
3138 IP(src=server.ip4, dst=host_nat_ip) /
3139 GRE() /
3140 IP(src=self.pg3.remote_ip4, dst=self.pg2.remote_ip4) /
3141 TCP(sport=1234, dport=1234))
3142 self.pg0.add_stream(p)
3143 self.pg_enable_capture(self.pg_interfaces)
3144 self.pg_start()
3145 p = self.pg0.get_capture(1)
3146 packet = p[0]
3147 try:
3148 self.assertEqual(packet[IP].src, server_nat_ip)
3149 self.assertEqual(packet[IP].dst, host.ip4)
Paul Vinciguerra978aa642018-11-24 22:19:12 -08003150 self.assertEqual(packet.haslayer(GRE), 1)
Klement Sekerad81ae412018-05-16 10:52:54 +02003151 self.assert_packet_checksums_valid(packet)
Matus Fabian1e8db5f2017-06-20 01:45:49 -07003152 except:
3153 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3154 raise
3155
Matus Fabian93d84c92017-07-19 08:06:01 -07003156 def test_output_feature(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07003157 """ NAT44 interface output feature (in2out postrouting) """
3158 self.nat44_add_address(self.nat_addr)
3159 self.vapi.nat44_interface_add_del_output_feature(self.pg0.sw_if_index)
Matus Fabianb2d2fc72017-09-10 22:17:47 -07003160 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index)
3161 self.vapi.nat44_interface_add_del_output_feature(self.pg3.sw_if_index,
Matus Fabian2ba92e32017-08-21 07:05:03 -07003162 is_inside=0)
Matus Fabian93d84c92017-07-19 08:06:01 -07003163
3164 # in2out
Matus Fabianb2d2fc72017-09-10 22:17:47 -07003165 pkts = self.create_stream_in(self.pg0, self.pg3)
Matus Fabian93d84c92017-07-19 08:06:01 -07003166 self.pg0.add_stream(pkts)
3167 self.pg_enable_capture(self.pg_interfaces)
3168 self.pg_start()
Matus Fabianb2d2fc72017-09-10 22:17:47 -07003169 capture = self.pg3.get_capture(len(pkts))
Matus Fabian93d84c92017-07-19 08:06:01 -07003170 self.verify_capture_out(capture)
3171
3172 # out2in
Matus Fabianb2d2fc72017-09-10 22:17:47 -07003173 pkts = self.create_stream_out(self.pg3)
3174 self.pg3.add_stream(pkts)
Matus Fabian93d84c92017-07-19 08:06:01 -07003175 self.pg_enable_capture(self.pg_interfaces)
3176 self.pg_start()
3177 capture = self.pg0.get_capture(len(pkts))
3178 self.verify_capture_in(capture, self.pg0)
3179
Matus Fabianb2d2fc72017-09-10 22:17:47 -07003180 # from non-NAT interface to NAT inside interface
3181 pkts = self.create_stream_in(self.pg2, self.pg0)
3182 self.pg2.add_stream(pkts)
3183 self.pg_enable_capture(self.pg_interfaces)
3184 self.pg_start()
3185 capture = self.pg0.get_capture(len(pkts))
3186 self.verify_capture_no_translation(capture, self.pg2, self.pg0)
3187
Matus Fabian93d84c92017-07-19 08:06:01 -07003188 def test_output_feature_vrf_aware(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07003189 """ NAT44 interface output feature VRF aware (in2out postrouting) """
Matus Fabian93d84c92017-07-19 08:06:01 -07003190 nat_ip_vrf10 = "10.0.0.10"
3191 nat_ip_vrf20 = "10.0.0.20"
3192
3193 self.vapi.ip_add_del_route(dst_address=self.pg3.remote_ip4n,
3194 dst_address_length=32,
3195 next_hop_address=self.pg3.remote_ip4n,
3196 next_hop_sw_if_index=self.pg3.sw_if_index,
3197 table_id=10)
3198 self.vapi.ip_add_del_route(dst_address=self.pg3.remote_ip4n,
3199 dst_address_length=32,
3200 next_hop_address=self.pg3.remote_ip4n,
3201 next_hop_sw_if_index=self.pg3.sw_if_index,
3202 table_id=20)
3203
Matus Fabian2ba92e32017-08-21 07:05:03 -07003204 self.nat44_add_address(nat_ip_vrf10, vrf_id=10)
3205 self.nat44_add_address(nat_ip_vrf20, vrf_id=20)
3206 self.vapi.nat44_interface_add_del_output_feature(self.pg4.sw_if_index)
3207 self.vapi.nat44_interface_add_del_output_feature(self.pg6.sw_if_index)
3208 self.vapi.nat44_interface_add_del_output_feature(self.pg3.sw_if_index,
3209 is_inside=0)
Matus Fabian93d84c92017-07-19 08:06:01 -07003210
3211 # in2out VRF 10
3212 pkts = self.create_stream_in(self.pg4, self.pg3)
3213 self.pg4.add_stream(pkts)
3214 self.pg_enable_capture(self.pg_interfaces)
3215 self.pg_start()
3216 capture = self.pg3.get_capture(len(pkts))
3217 self.verify_capture_out(capture, nat_ip=nat_ip_vrf10)
3218
3219 # out2in VRF 10
3220 pkts = self.create_stream_out(self.pg3, dst_ip=nat_ip_vrf10)
3221 self.pg3.add_stream(pkts)
3222 self.pg_enable_capture(self.pg_interfaces)
3223 self.pg_start()
3224 capture = self.pg4.get_capture(len(pkts))
3225 self.verify_capture_in(capture, self.pg4)
3226
3227 # in2out VRF 20
3228 pkts = self.create_stream_in(self.pg6, self.pg3)
3229 self.pg6.add_stream(pkts)
3230 self.pg_enable_capture(self.pg_interfaces)
3231 self.pg_start()
3232 capture = self.pg3.get_capture(len(pkts))
3233 self.verify_capture_out(capture, nat_ip=nat_ip_vrf20)
3234
3235 # out2in VRF 20
3236 pkts = self.create_stream_out(self.pg3, dst_ip=nat_ip_vrf20)
3237 self.pg3.add_stream(pkts)
3238 self.pg_enable_capture(self.pg_interfaces)
3239 self.pg_start()
3240 capture = self.pg6.get_capture(len(pkts))
3241 self.verify_capture_in(capture, self.pg6)
3242
Matus Fabian161c59c2017-07-21 03:46:03 -07003243 def test_output_feature_hairpinning(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07003244 """ NAT44 interface output feature hairpinning (in2out postrouting) """
Matus Fabian93d84c92017-07-19 08:06:01 -07003245 host = self.pg0.remote_hosts[0]
3246 server = self.pg0.remote_hosts[1]
3247 host_in_port = 1234
3248 host_out_port = 0
3249 server_in_port = 5678
3250 server_out_port = 8765
3251
Matus Fabian2ba92e32017-08-21 07:05:03 -07003252 self.nat44_add_address(self.nat_addr)
3253 self.vapi.nat44_interface_add_del_output_feature(self.pg0.sw_if_index)
3254 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
3255 is_inside=0)
Matus Fabian93d84c92017-07-19 08:06:01 -07003256
3257 # add static mapping for server
Matus Fabian2ba92e32017-08-21 07:05:03 -07003258 self.nat44_add_static_mapping(server.ip4, self.nat_addr,
3259 server_in_port, server_out_port,
3260 proto=IP_PROTOS.tcp)
Matus Fabian93d84c92017-07-19 08:06:01 -07003261
3262 # send packet from host to server
3263 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07003264 IP(src=host.ip4, dst=self.nat_addr) /
Matus Fabian93d84c92017-07-19 08:06:01 -07003265 TCP(sport=host_in_port, dport=server_out_port))
3266 self.pg0.add_stream(p)
3267 self.pg_enable_capture(self.pg_interfaces)
3268 self.pg_start()
3269 capture = self.pg0.get_capture(1)
3270 p = capture[0]
3271 try:
3272 ip = p[IP]
3273 tcp = p[TCP]
Matus Fabian2ba92e32017-08-21 07:05:03 -07003274 self.assertEqual(ip.src, self.nat_addr)
Matus Fabian93d84c92017-07-19 08:06:01 -07003275 self.assertEqual(ip.dst, server.ip4)
3276 self.assertNotEqual(tcp.sport, host_in_port)
3277 self.assertEqual(tcp.dport, server_in_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02003278 self.assert_packet_checksums_valid(p)
Matus Fabian93d84c92017-07-19 08:06:01 -07003279 host_out_port = tcp.sport
3280 except:
3281 self.logger.error(ppp("Unexpected or invalid packet:", p))
3282 raise
3283
3284 # send reply from server to host
3285 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07003286 IP(src=server.ip4, dst=self.nat_addr) /
Matus Fabian93d84c92017-07-19 08:06:01 -07003287 TCP(sport=server_in_port, dport=host_out_port))
3288 self.pg0.add_stream(p)
3289 self.pg_enable_capture(self.pg_interfaces)
3290 self.pg_start()
3291 capture = self.pg0.get_capture(1)
3292 p = capture[0]
3293 try:
3294 ip = p[IP]
3295 tcp = p[TCP]
Matus Fabian2ba92e32017-08-21 07:05:03 -07003296 self.assertEqual(ip.src, self.nat_addr)
Matus Fabian93d84c92017-07-19 08:06:01 -07003297 self.assertEqual(ip.dst, host.ip4)
3298 self.assertEqual(tcp.sport, server_out_port)
3299 self.assertEqual(tcp.dport, host_in_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02003300 self.assert_packet_checksums_valid(p)
Matus Fabian93d84c92017-07-19 08:06:01 -07003301 except:
Matus Fabiane82488f2018-01-18 03:38:45 -08003302 self.logger.error(ppp("Unexpected or invalid packet:", p))
Matus Fabian93d84c92017-07-19 08:06:01 -07003303 raise
3304
Matus Fabian36ea2d62017-10-24 04:13:49 -07003305 def test_one_armed_nat44(self):
3306 """ One armed NAT44 """
3307 remote_host = self.pg9.remote_hosts[0]
3308 local_host = self.pg9.remote_hosts[1]
3309 external_port = 0
3310
3311 self.nat44_add_address(self.nat_addr)
3312 self.vapi.nat44_interface_add_del_feature(self.pg9.sw_if_index)
3313 self.vapi.nat44_interface_add_del_feature(self.pg9.sw_if_index,
3314 is_inside=0)
3315
3316 # in2out
3317 p = (Ether(src=self.pg9.remote_mac, dst=self.pg9.local_mac) /
3318 IP(src=local_host.ip4, dst=remote_host.ip4) /
3319 TCP(sport=12345, dport=80))
3320 self.pg9.add_stream(p)
3321 self.pg_enable_capture(self.pg_interfaces)
3322 self.pg_start()
3323 capture = self.pg9.get_capture(1)
3324 p = capture[0]
3325 try:
3326 ip = p[IP]
3327 tcp = p[TCP]
3328 self.assertEqual(ip.src, self.nat_addr)
3329 self.assertEqual(ip.dst, remote_host.ip4)
3330 self.assertNotEqual(tcp.sport, 12345)
3331 external_port = tcp.sport
3332 self.assertEqual(tcp.dport, 80)
Klement Sekerad81ae412018-05-16 10:52:54 +02003333 self.assert_packet_checksums_valid(p)
Matus Fabian36ea2d62017-10-24 04:13:49 -07003334 except:
3335 self.logger.error(ppp("Unexpected or invalid packet:", p))
3336 raise
3337
3338 # out2in
3339 p = (Ether(src=self.pg9.remote_mac, dst=self.pg9.local_mac) /
3340 IP(src=remote_host.ip4, dst=self.nat_addr) /
3341 TCP(sport=80, dport=external_port))
3342 self.pg9.add_stream(p)
3343 self.pg_enable_capture(self.pg_interfaces)
3344 self.pg_start()
3345 capture = self.pg9.get_capture(1)
3346 p = capture[0]
3347 try:
3348 ip = p[IP]
3349 tcp = p[TCP]
3350 self.assertEqual(ip.src, remote_host.ip4)
3351 self.assertEqual(ip.dst, local_host.ip4)
3352 self.assertEqual(tcp.sport, 80)
3353 self.assertEqual(tcp.dport, 12345)
Klement Sekerad81ae412018-05-16 10:52:54 +02003354 self.assert_packet_checksums_valid(p)
Matus Fabian36ea2d62017-10-24 04:13:49 -07003355 except:
3356 self.logger.error(ppp("Unexpected or invalid packet:", p))
3357 raise
3358
Matus Fabian5ba86f72017-10-26 03:37:38 -07003359 def test_del_session(self):
3360 """ Delete NAT44 session """
3361 self.nat44_add_address(self.nat_addr)
3362 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3363 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3364 is_inside=0)
3365
3366 pkts = self.create_stream_in(self.pg0, self.pg1)
3367 self.pg0.add_stream(pkts)
3368 self.pg_enable_capture(self.pg_interfaces)
3369 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07003370 self.pg1.get_capture(len(pkts))
Matus Fabian5ba86f72017-10-26 03:37:38 -07003371
3372 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
3373 nsessions = len(sessions)
3374
3375 self.vapi.nat44_del_session(sessions[0].inside_ip_address,
3376 sessions[0].inside_port,
3377 sessions[0].protocol)
3378 self.vapi.nat44_del_session(sessions[1].outside_ip_address,
3379 sessions[1].outside_port,
3380 sessions[1].protocol,
3381 is_in=0)
3382
3383 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
3384 self.assertEqual(nsessions - len(sessions), 2)
3385
Matus Fabian68ba8802018-08-08 05:52:47 -07003386 self.vapi.nat44_del_session(sessions[0].inside_ip_address,
3387 sessions[0].inside_port,
3388 sessions[0].protocol)
3389
3390 self.verify_no_nat44_user()
3391
Matus Fabianefcd1e92017-08-15 06:59:19 -07003392 def test_set_get_reass(self):
3393 """ NAT44 set/get virtual fragmentation reassembly """
3394 reas_cfg1 = self.vapi.nat_get_reass()
3395
3396 self.vapi.nat_set_reass(timeout=reas_cfg1.ip4_timeout + 5,
3397 max_reass=reas_cfg1.ip4_max_reass * 2,
3398 max_frag=reas_cfg1.ip4_max_frag * 2)
3399
3400 reas_cfg2 = self.vapi.nat_get_reass()
3401
3402 self.assertEqual(reas_cfg1.ip4_timeout + 5, reas_cfg2.ip4_timeout)
3403 self.assertEqual(reas_cfg1.ip4_max_reass * 2, reas_cfg2.ip4_max_reass)
3404 self.assertEqual(reas_cfg1.ip4_max_frag * 2, reas_cfg2.ip4_max_frag)
3405
3406 self.vapi.nat_set_reass(drop_frag=1)
3407 self.assertTrue(self.vapi.nat_get_reass().ip4_drop_frag)
3408
3409 def test_frag_in_order(self):
3410 """ NAT44 translate fragments arriving in order """
Juraj Slobodafe0aa762018-07-23 12:22:54 +02003411
Matus Fabianefcd1e92017-08-15 06:59:19 -07003412 self.nat44_add_address(self.nat_addr)
3413 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3414 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3415 is_inside=0)
3416
Matus Fabianda41d722018-10-19 04:01:19 -07003417 self.frag_in_order(proto=IP_PROTOS.tcp)
3418 self.frag_in_order(proto=IP_PROTOS.udp)
3419 self.frag_in_order(proto=IP_PROTOS.icmp)
Matus Fabianefcd1e92017-08-15 06:59:19 -07003420
Matus Fabian111add72018-11-20 02:19:05 -08003421 def test_frag_forwarding(self):
3422 """ NAT44 forwarding fragment test """
3423 self.vapi.nat44_add_interface_addr(self.pg1.sw_if_index)
3424 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3425 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3426 is_inside=0)
3427 self.vapi.nat44_forwarding_enable_disable(1)
3428
3429 data = "A" * 16 + "B" * 16 + "C" * 3
3430 pkts = self.create_stream_frag(self.pg1,
3431 self.pg0.remote_ip4,
3432 4789,
3433 4789,
3434 data,
3435 proto=IP_PROTOS.udp)
3436 self.pg1.add_stream(pkts)
3437 self.pg_enable_capture(self.pg_interfaces)
3438 self.pg_start()
3439 frags = self.pg0.get_capture(len(pkts))
3440 p = self.reass_frags_and_verify(frags,
3441 self.pg1.remote_ip4,
3442 self.pg0.remote_ip4)
3443 self.assertEqual(p[UDP].sport, 4789)
3444 self.assertEqual(p[UDP].dport, 4789)
3445 self.assertEqual(data, p[Raw].load)
3446
Matus Fabianefcd1e92017-08-15 06:59:19 -07003447 def test_reass_hairpinning(self):
3448 """ NAT44 fragments hairpinning """
Juraj Slobodafe0aa762018-07-23 12:22:54 +02003449
Matus Fabianda41d722018-10-19 04:01:19 -07003450 self.server = self.pg0.remote_hosts[1]
3451 self.host_in_port = random.randint(1025, 65535)
3452 self.server_in_port = random.randint(1025, 65535)
3453 self.server_out_port = random.randint(1025, 65535)
Matus Fabianefcd1e92017-08-15 06:59:19 -07003454
3455 self.nat44_add_address(self.nat_addr)
3456 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3457 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3458 is_inside=0)
3459 # add static mapping for server
Matus Fabianda41d722018-10-19 04:01:19 -07003460 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr,
3461 self.server_in_port,
3462 self.server_out_port,
Matus Fabianefcd1e92017-08-15 06:59:19 -07003463 proto=IP_PROTOS.tcp)
Matus Fabianda41d722018-10-19 04:01:19 -07003464 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr,
3465 self.server_in_port,
3466 self.server_out_port,
3467 proto=IP_PROTOS.udp)
3468 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr)
Matus Fabianefcd1e92017-08-15 06:59:19 -07003469
Matus Fabianda41d722018-10-19 04:01:19 -07003470 self.reass_hairpinning(proto=IP_PROTOS.tcp)
3471 self.reass_hairpinning(proto=IP_PROTOS.udp)
3472 self.reass_hairpinning(proto=IP_PROTOS.icmp)
Matus Fabianefcd1e92017-08-15 06:59:19 -07003473
3474 def test_frag_out_of_order(self):
3475 """ NAT44 translate fragments arriving out of order """
Juraj Slobodafe0aa762018-07-23 12:22:54 +02003476
Matus Fabianefcd1e92017-08-15 06:59:19 -07003477 self.nat44_add_address(self.nat_addr)
3478 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3479 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3480 is_inside=0)
3481
Matus Fabianda41d722018-10-19 04:01:19 -07003482 self.frag_out_of_order(proto=IP_PROTOS.tcp)
3483 self.frag_out_of_order(proto=IP_PROTOS.udp)
3484 self.frag_out_of_order(proto=IP_PROTOS.icmp)
Matus Fabianefcd1e92017-08-15 06:59:19 -07003485
Matus Fabian27697102017-11-09 01:43:47 -08003486 def test_port_restricted(self):
3487 """ Port restricted NAT44 (MAP-E CE) """
3488 self.nat44_add_address(self.nat_addr)
3489 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3490 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3491 is_inside=0)
Matus Fabian5d28c7a2018-09-04 03:55:45 -07003492 self.vapi.nat_set_addr_and_port_alloc_alg(alg=1,
3493 psid_offset=6,
3494 psid_length=6,
3495 psid=10)
Matus Fabian27697102017-11-09 01:43:47 -08003496
3497 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3498 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3499 TCP(sport=4567, dport=22))
3500 self.pg0.add_stream(p)
3501 self.pg_enable_capture(self.pg_interfaces)
3502 self.pg_start()
3503 capture = self.pg1.get_capture(1)
3504 p = capture[0]
3505 try:
3506 ip = p[IP]
3507 tcp = p[TCP]
3508 self.assertEqual(ip.dst, self.pg1.remote_ip4)
3509 self.assertEqual(ip.src, self.nat_addr)
3510 self.assertEqual(tcp.dport, 22)
3511 self.assertNotEqual(tcp.sport, 4567)
3512 self.assertEqual((tcp.sport >> 6) & 63, 10)
Klement Sekerad81ae412018-05-16 10:52:54 +02003513 self.assert_packet_checksums_valid(p)
Matus Fabian27697102017-11-09 01:43:47 -08003514 except:
3515 self.logger.error(ppp("Unexpected or invalid packet:", p))
3516 raise
3517
Matus Fabian5d28c7a2018-09-04 03:55:45 -07003518 def test_port_range(self):
3519 """ External address port range """
3520 self.nat44_add_address(self.nat_addr)
3521 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3522 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3523 is_inside=0)
3524 self.vapi.nat_set_addr_and_port_alloc_alg(alg=2,
3525 start_port=1025,
3526 end_port=1027)
3527
3528 pkts = []
3529 for port in range(0, 5):
3530 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3531 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3532 TCP(sport=1125 + port))
3533 pkts.append(p)
3534 self.pg0.add_stream(pkts)
3535 self.pg_enable_capture(self.pg_interfaces)
3536 self.pg_start()
3537 capture = self.pg1.get_capture(3)
3538 for p in capture:
3539 tcp = p[TCP]
3540 self.assertGreaterEqual(tcp.sport, 1025)
3541 self.assertLessEqual(tcp.sport, 1027)
3542
Matus Fabiana6110b62018-06-13 05:39:07 -07003543 def test_ipfix_max_frags(self):
3544 """ IPFIX logging maximum fragments pending reassembly exceeded """
3545 self.nat44_add_address(self.nat_addr)
3546 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3547 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3548 is_inside=0)
Matus Fabiana7f8b222018-09-05 06:01:55 -07003549 self.vapi.nat_set_reass(max_frag=1)
Matus Fabiana6110b62018-06-13 05:39:07 -07003550 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
3551 src_address=self.pg3.local_ip4n,
3552 path_mtu=512,
3553 template_interval=10)
3554 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
3555 src_port=self.ipfix_src_port)
3556
3557 data = "A" * 4 + "B" * 16 + "C" * 3
3558 self.tcp_port_in = random.randint(1025, 65535)
3559 pkts = self.create_stream_frag(self.pg0,
3560 self.pg1.remote_ip4,
3561 self.tcp_port_in,
3562 20,
3563 data)
Matus Fabiana7f8b222018-09-05 06:01:55 -07003564 pkts.reverse()
3565 self.pg0.add_stream(pkts)
Matus Fabiana6110b62018-06-13 05:39:07 -07003566 self.pg_enable_capture(self.pg_interfaces)
3567 self.pg_start()
3568 self.pg1.assert_nothing_captured()
3569 sleep(1)
3570 self.vapi.cli("ipfix flush") # FIXME this should be an API call
3571 capture = self.pg3.get_capture(9)
3572 ipfix = IPFIXDecoder()
3573 # first load template
3574 for p in capture:
3575 self.assertTrue(p.haslayer(IPFIX))
3576 self.assertEqual(p[IP].src, self.pg3.local_ip4)
3577 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
3578 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
3579 self.assertEqual(p[UDP].dport, 4739)
3580 self.assertEqual(p[IPFIX].observationDomainID,
3581 self.ipfix_domain_id)
3582 if p.haslayer(Template):
3583 ipfix.add_template(p.getlayer(Template))
3584 # verify events in data set
3585 for p in capture:
3586 if p.haslayer(Data):
3587 data = ipfix.decode_data_set(p.getlayer(Set))
Matus Fabiana7f8b222018-09-05 06:01:55 -07003588 self.verify_ipfix_max_fragments_ip4(data, 1,
Matus Fabiana6110b62018-06-13 05:39:07 -07003589 self.pg0.remote_ip4n)
3590
Matus Fabian8008d7c2018-07-09 01:34:20 -07003591 def test_multiple_outside_vrf(self):
3592 """ Multiple outside VRF """
3593 vrf_id1 = 1
3594 vrf_id2 = 2
3595
3596 self.pg1.unconfig_ip4()
3597 self.pg2.unconfig_ip4()
3598 self.vapi.ip_table_add_del(vrf_id1, is_add=1)
3599 self.vapi.ip_table_add_del(vrf_id2, is_add=1)
3600 self.pg1.set_table_ip4(vrf_id1)
3601 self.pg2.set_table_ip4(vrf_id2)
3602 self.pg1.config_ip4()
3603 self.pg2.config_ip4()
3604 self.pg1.resolve_arp()
3605 self.pg2.resolve_arp()
3606
3607 self.nat44_add_address(self.nat_addr)
3608 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3609 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3610 is_inside=0)
3611 self.vapi.nat44_interface_add_del_feature(self.pg2.sw_if_index,
3612 is_inside=0)
3613
3614 try:
3615 # first VRF
3616 pkts = self.create_stream_in(self.pg0, self.pg1)
3617 self.pg0.add_stream(pkts)
3618 self.pg_enable_capture(self.pg_interfaces)
3619 self.pg_start()
3620 capture = self.pg1.get_capture(len(pkts))
3621 self.verify_capture_out(capture, self.nat_addr)
3622
3623 pkts = self.create_stream_out(self.pg1, self.nat_addr)
3624 self.pg1.add_stream(pkts)
3625 self.pg_enable_capture(self.pg_interfaces)
3626 self.pg_start()
3627 capture = self.pg0.get_capture(len(pkts))
3628 self.verify_capture_in(capture, self.pg0)
3629
3630 self.tcp_port_in = 60303
3631 self.udp_port_in = 60304
3632 self.icmp_id_in = 60305
3633
3634 # second VRF
3635 pkts = self.create_stream_in(self.pg0, self.pg2)
3636 self.pg0.add_stream(pkts)
3637 self.pg_enable_capture(self.pg_interfaces)
3638 self.pg_start()
3639 capture = self.pg2.get_capture(len(pkts))
3640 self.verify_capture_out(capture, self.nat_addr)
3641
3642 pkts = self.create_stream_out(self.pg2, self.nat_addr)
3643 self.pg2.add_stream(pkts)
3644 self.pg_enable_capture(self.pg_interfaces)
3645 self.pg_start()
3646 capture = self.pg0.get_capture(len(pkts))
3647 self.verify_capture_in(capture, self.pg0)
3648
3649 finally:
3650 self.pg1.unconfig_ip4()
3651 self.pg2.unconfig_ip4()
3652 self.pg1.set_table_ip4(0)
3653 self.pg2.set_table_ip4(0)
3654 self.pg1.config_ip4()
3655 self.pg2.config_ip4()
3656 self.pg1.resolve_arp()
3657 self.pg2.resolve_arp()
3658
Matus Fabian878c6462018-08-23 00:33:35 -07003659 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
3660 def test_session_timeout(self):
3661 """ NAT44 session timeouts """
3662 self.nat44_add_address(self.nat_addr)
3663 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3664 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3665 is_inside=0)
3666 self.vapi.nat_set_timeouts(udp=5)
3667
3668 max_sessions = 1000
3669 pkts = []
3670 for i in range(0, max_sessions):
3671 src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
3672 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3673 IP(src=src, dst=self.pg1.remote_ip4) /
3674 UDP(sport=1025, dport=53))
3675 pkts.append(p)
3676 self.pg0.add_stream(pkts)
3677 self.pg_enable_capture(self.pg_interfaces)
3678 self.pg_start()
3679 self.pg1.get_capture(max_sessions)
3680
3681 sleep(6)
3682
3683 pkts = []
3684 for i in range(0, max_sessions):
3685 src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
3686 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3687 IP(src=src, dst=self.pg1.remote_ip4) /
3688 UDP(sport=1026, dport=53))
3689 pkts.append(p)
3690 self.pg0.add_stream(pkts)
3691 self.pg_enable_capture(self.pg_interfaces)
3692 self.pg_start()
3693 self.pg1.get_capture(max_sessions)
3694
3695 nsessions = 0
3696 users = self.vapi.nat44_user_dump()
3697 for user in users:
3698 nsessions = nsessions + user.nsessions
3699 self.assertLess(nsessions, 2 * max_sessions)
3700
Matus Fabianbb4e0222018-09-13 02:36:25 -07003701 def test_mss_clamping(self):
3702 """ TCP MSS clamping """
3703 self.nat44_add_address(self.nat_addr)
3704 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3705 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3706 is_inside=0)
3707
3708 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3709 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3710 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
3711 flags="S", options=[('MSS', 1400)]))
3712
3713 self.vapi.nat_set_mss_clamping(enable=1, mss_value=1000)
3714 self.pg0.add_stream(p)
3715 self.pg_enable_capture(self.pg_interfaces)
3716 self.pg_start()
3717 capture = self.pg1.get_capture(1)
3718 # Negotiated MSS value greater than configured - changed
3719 self.verify_mss_value(capture[0], 1000)
3720
3721 self.vapi.nat_set_mss_clamping(enable=0)
3722 self.pg0.add_stream(p)
3723 self.pg_enable_capture(self.pg_interfaces)
3724 self.pg_start()
3725 capture = self.pg1.get_capture(1)
3726 # MSS clamping disabled - negotiated MSS unchanged
3727 self.verify_mss_value(capture[0], 1400)
3728
3729 self.vapi.nat_set_mss_clamping(enable=1, mss_value=1500)
3730 self.pg0.add_stream(p)
3731 self.pg_enable_capture(self.pg_interfaces)
3732 self.pg_start()
3733 capture = self.pg1.get_capture(1)
3734 # Negotiated MSS value smaller than configured - unchanged
3735 self.verify_mss_value(capture[0], 1400)
3736
Matus Fabiana6110b62018-06-13 05:39:07 -07003737 def tearDown(self):
3738 super(TestNAT44, self).tearDown()
3739 if not self.vpp_dead:
3740 self.logger.info(self.vapi.cli("show nat44 addresses"))
3741 self.logger.info(self.vapi.cli("show nat44 interfaces"))
3742 self.logger.info(self.vapi.cli("show nat44 static mappings"))
3743 self.logger.info(self.vapi.cli("show nat44 interface address"))
3744 self.logger.info(self.vapi.cli("show nat44 sessions detail"))
3745 self.logger.info(self.vapi.cli("show nat virtual-reassembly"))
3746 self.logger.info(self.vapi.cli("show nat44 hash tables detail"))
Matus Fabian878c6462018-08-23 00:33:35 -07003747 self.logger.info(self.vapi.cli("show nat timeouts"))
Matus Fabian5d28c7a2018-09-04 03:55:45 -07003748 self.logger.info(
3749 self.vapi.cli("show nat addr-port-assignment-alg"))
Matus Fabiana6110b62018-06-13 05:39:07 -07003750 self.clear_nat44()
3751 self.vapi.cli("clear logging")
3752
3753
3754class TestNAT44EndpointDependent(MethodHolder):
3755 """ Endpoint-Dependent mapping and filtering test cases """
3756
3757 @classmethod
3758 def setUpConstants(cls):
3759 super(TestNAT44EndpointDependent, cls).setUpConstants()
3760 cls.vpp_cmdline.extend(["nat", "{", "endpoint-dependent", "}"])
3761
3762 @classmethod
3763 def setUpClass(cls):
3764 super(TestNAT44EndpointDependent, cls).setUpClass()
3765 cls.vapi.cli("set log class nat level debug")
3766 try:
3767 cls.tcp_port_in = 6303
3768 cls.tcp_port_out = 6303
3769 cls.udp_port_in = 6304
3770 cls.udp_port_out = 6304
3771 cls.icmp_id_in = 6305
3772 cls.icmp_id_out = 6305
3773 cls.nat_addr = '10.0.0.3'
3774 cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
3775 cls.ipfix_src_port = 4739
3776 cls.ipfix_domain_id = 1
3777 cls.tcp_external_port = 80
3778
Matus Fabian8008d7c2018-07-09 01:34:20 -07003779 cls.create_pg_interfaces(range(7))
Matus Fabiana6110b62018-06-13 05:39:07 -07003780 cls.interfaces = list(cls.pg_interfaces[0:3])
3781
3782 for i in cls.interfaces:
3783 i.admin_up()
3784 i.config_ip4()
3785 i.resolve_arp()
3786
3787 cls.pg0.generate_remote_hosts(3)
3788 cls.pg0.configure_ipv4_neighbors()
3789
3790 cls.pg3.admin_up()
3791
3792 cls.pg4.generate_remote_hosts(2)
3793 cls.pg4.config_ip4()
3794 ip_addr_n = socket.inet_pton(socket.AF_INET, "10.0.0.1")
3795 cls.vapi.sw_interface_add_del_address(cls.pg4.sw_if_index,
3796 ip_addr_n,
3797 24)
3798 cls.pg4.admin_up()
3799 cls.pg4.resolve_arp()
3800 cls.pg4._remote_hosts[1]._ip4 = cls.pg4._remote_hosts[0]._ip4
3801 cls.pg4.resolve_arp()
3802
Matus Fabian8008d7c2018-07-09 01:34:20 -07003803 zero_ip4n = socket.inet_pton(socket.AF_INET, "0.0.0.0")
3804 cls.vapi.ip_table_add_del(1, is_add=1)
3805
3806 cls.pg5._local_ip4 = "10.1.1.1"
3807 cls.pg5._local_ip4n = socket.inet_pton(socket.AF_INET,
3808 cls.pg5.local_ip4)
3809 cls.pg5._remote_hosts[0]._ip4 = "10.1.1.2"
3810 cls.pg5._remote_hosts[0]._ip4n = socket.inet_pton(
3811 socket.AF_INET, cls.pg5.remote_ip4)
3812 cls.pg5.set_table_ip4(1)
3813 cls.pg5.config_ip4()
3814 cls.pg5.admin_up()
3815 cls.vapi.ip_add_del_route(dst_address=cls.pg5.remote_ip4n,
3816 dst_address_length=32,
3817 table_id=1,
3818 next_hop_sw_if_index=cls.pg5.sw_if_index,
3819 next_hop_address=zero_ip4n)
3820
3821 cls.pg6._local_ip4 = "10.1.2.1"
3822 cls.pg6._local_ip4n = socket.inet_pton(socket.AF_INET,
3823 cls.pg6.local_ip4)
3824 cls.pg6._remote_hosts[0]._ip4 = "10.1.2.2"
3825 cls.pg6._remote_hosts[0]._ip4n = socket.inet_pton(
3826 socket.AF_INET, cls.pg6.remote_ip4)
3827 cls.pg6.set_table_ip4(1)
3828 cls.pg6.config_ip4()
3829 cls.pg6.admin_up()
3830 cls.vapi.ip_add_del_route(dst_address=cls.pg6.remote_ip4n,
3831 dst_address_length=32,
3832 table_id=1,
3833 next_hop_sw_if_index=cls.pg6.sw_if_index,
3834 next_hop_address=zero_ip4n)
3835
3836 cls.vapi.ip_add_del_route(dst_address=cls.pg6.remote_ip4n,
3837 dst_address_length=16,
3838 next_hop_address=zero_ip4n,
3839 table_id=0,
3840 next_hop_table_id=1)
3841 cls.vapi.ip_add_del_route(dst_address=zero_ip4n,
3842 dst_address_length=0,
3843 next_hop_address=zero_ip4n,
3844 table_id=1,
3845 next_hop_table_id=0)
3846 cls.vapi.ip_add_del_route(dst_address=zero_ip4n,
3847 dst_address_length=0,
3848 table_id=0,
3849 next_hop_sw_if_index=cls.pg1.sw_if_index,
3850 next_hop_address=cls.pg1.local_ip4n)
3851
3852 cls.pg5.resolve_arp()
3853 cls.pg6.resolve_arp()
3854
Matus Fabiana6110b62018-06-13 05:39:07 -07003855 except Exception:
3856 super(TestNAT44EndpointDependent, cls).tearDownClass()
3857 raise
3858
Juraj Slobodafe0aa762018-07-23 12:22:54 +02003859 def test_frag_in_order(self):
3860 """ NAT44 translate fragments arriving in order """
3861 self.nat44_add_address(self.nat_addr)
3862 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3863 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3864 is_inside=0)
3865 self.frag_in_order(proto=IP_PROTOS.tcp)
3866 self.frag_in_order(proto=IP_PROTOS.udp)
3867 self.frag_in_order(proto=IP_PROTOS.icmp)
3868
3869 def test_frag_in_order_dont_translate(self):
3870 """ NAT44 don't translate fragments arriving in order """
3871 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3872 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3873 is_inside=0)
3874 self.vapi.nat44_forwarding_enable_disable(enable=True)
3875 self.frag_in_order(proto=IP_PROTOS.tcp, dont_translate=True)
3876
3877 def test_frag_out_of_order(self):
3878 """ NAT44 translate fragments arriving out of order """
3879 self.nat44_add_address(self.nat_addr)
3880 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3881 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3882 is_inside=0)
3883 self.frag_out_of_order(proto=IP_PROTOS.tcp)
3884 self.frag_out_of_order(proto=IP_PROTOS.udp)
3885 self.frag_out_of_order(proto=IP_PROTOS.icmp)
3886
3887 def test_frag_out_of_order_dont_translate(self):
3888 """ NAT44 don't translate fragments arriving out of order """
3889 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3890 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3891 is_inside=0)
3892 self.vapi.nat44_forwarding_enable_disable(enable=True)
3893 self.frag_out_of_order(proto=IP_PROTOS.tcp, dont_translate=True)
3894
3895 def test_frag_in_order_in_plus_out(self):
3896 """ in+out interface fragments in order """
3897 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3898 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
3899 is_inside=0)
3900 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
3901 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3902 is_inside=0)
3903
3904 self.server = self.pg1.remote_hosts[0]
3905
3906 self.server_in_addr = self.server.ip4
3907 self.server_out_addr = '11.11.11.11'
3908 self.server_in_port = random.randint(1025, 65535)
3909 self.server_out_port = random.randint(1025, 65535)
3910
3911 self.nat44_add_address(self.server_out_addr)
3912
3913 # add static mappings for server
3914 self.nat44_add_static_mapping(self.server_in_addr,
3915 self.server_out_addr,
3916 self.server_in_port,
3917 self.server_out_port,
3918 proto=IP_PROTOS.tcp)
3919 self.nat44_add_static_mapping(self.server_in_addr,
3920 self.server_out_addr,
3921 self.server_in_port,
3922 self.server_out_port,
3923 proto=IP_PROTOS.udp)
3924 self.nat44_add_static_mapping(self.server_in_addr,
3925 self.server_out_addr,
3926 proto=IP_PROTOS.icmp)
3927
3928 self.vapi.nat_set_reass(timeout=10)
3929
3930 self.frag_in_order_in_plus_out(proto=IP_PROTOS.tcp)
3931 self.frag_in_order_in_plus_out(proto=IP_PROTOS.udp)
3932 self.frag_in_order_in_plus_out(proto=IP_PROTOS.icmp)
3933
3934 def test_frag_out_of_order_in_plus_out(self):
3935 """ in+out interface fragments out of order """
3936 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3937 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
3938 is_inside=0)
3939 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
3940 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3941 is_inside=0)
3942
3943 self.server = self.pg1.remote_hosts[0]
3944
3945 self.server_in_addr = self.server.ip4
3946 self.server_out_addr = '11.11.11.11'
3947 self.server_in_port = random.randint(1025, 65535)
3948 self.server_out_port = random.randint(1025, 65535)
3949
3950 self.nat44_add_address(self.server_out_addr)
3951
3952 # add static mappings for server
3953 self.nat44_add_static_mapping(self.server_in_addr,
3954 self.server_out_addr,
3955 self.server_in_port,
3956 self.server_out_port,
3957 proto=IP_PROTOS.tcp)
3958 self.nat44_add_static_mapping(self.server_in_addr,
3959 self.server_out_addr,
3960 self.server_in_port,
3961 self.server_out_port,
3962 proto=IP_PROTOS.udp)
3963 self.nat44_add_static_mapping(self.server_in_addr,
3964 self.server_out_addr,
3965 proto=IP_PROTOS.icmp)
3966
3967 self.vapi.nat_set_reass(timeout=10)
3968
3969 self.frag_out_of_order_in_plus_out(proto=IP_PROTOS.tcp)
3970 self.frag_out_of_order_in_plus_out(proto=IP_PROTOS.udp)
3971 self.frag_out_of_order_in_plus_out(proto=IP_PROTOS.icmp)
3972
3973 def test_reass_hairpinning(self):
3974 """ NAT44 fragments hairpinning """
3975 self.server = self.pg0.remote_hosts[1]
3976 self.host_in_port = random.randint(1025, 65535)
3977 self.server_in_port = random.randint(1025, 65535)
3978 self.server_out_port = random.randint(1025, 65535)
3979
3980 self.nat44_add_address(self.nat_addr)
3981 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3982 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3983 is_inside=0)
3984 # add static mapping for server
3985 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr,
3986 self.server_in_port,
3987 self.server_out_port,
3988 proto=IP_PROTOS.tcp)
3989 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr,
3990 self.server_in_port,
3991 self.server_out_port,
3992 proto=IP_PROTOS.udp)
Matus Fabianda41d722018-10-19 04:01:19 -07003993 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr)
Juraj Slobodafe0aa762018-07-23 12:22:54 +02003994
3995 self.reass_hairpinning(proto=IP_PROTOS.tcp)
3996 self.reass_hairpinning(proto=IP_PROTOS.udp)
3997 self.reass_hairpinning(proto=IP_PROTOS.icmp)
3998
Matus Fabiana6110b62018-06-13 05:39:07 -07003999 def test_dynamic(self):
4000 """ NAT44 dynamic translation test """
4001
4002 self.nat44_add_address(self.nat_addr)
4003 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4004 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4005 is_inside=0)
4006
Matus Fabian69ce30d2018-08-22 01:27:10 -07004007 nat_config = self.vapi.nat_show_config()
4008 self.assertEqual(1, nat_config.endpoint_dependent)
4009
Matus Fabiana6110b62018-06-13 05:39:07 -07004010 # in2out
4011 pkts = self.create_stream_in(self.pg0, self.pg1)
4012 self.pg0.add_stream(pkts)
4013 self.pg_enable_capture(self.pg_interfaces)
4014 self.pg_start()
4015 capture = self.pg1.get_capture(len(pkts))
4016 self.verify_capture_out(capture)
4017
4018 # out2in
4019 pkts = self.create_stream_out(self.pg1)
4020 self.pg1.add_stream(pkts)
4021 self.pg_enable_capture(self.pg_interfaces)
4022 self.pg_start()
4023 capture = self.pg0.get_capture(len(pkts))
4024 self.verify_capture_in(capture, self.pg0)
4025
4026 def test_forwarding(self):
4027 """ NAT44 forwarding test """
4028
4029 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4030 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4031 is_inside=0)
4032 self.vapi.nat44_forwarding_enable_disable(1)
4033
4034 real_ip = self.pg0.remote_ip4n
4035 alias_ip = self.nat_addr_n
4036 self.vapi.nat44_add_del_static_mapping(local_ip=real_ip,
4037 external_ip=alias_ip)
4038
4039 try:
4040 # in2out - static mapping match
4041
4042 pkts = self.create_stream_out(self.pg1)
4043 self.pg1.add_stream(pkts)
4044 self.pg_enable_capture(self.pg_interfaces)
4045 self.pg_start()
4046 capture = self.pg0.get_capture(len(pkts))
4047 self.verify_capture_in(capture, self.pg0)
4048
4049 pkts = self.create_stream_in(self.pg0, self.pg1)
4050 self.pg0.add_stream(pkts)
4051 self.pg_enable_capture(self.pg_interfaces)
4052 self.pg_start()
4053 capture = self.pg1.get_capture(len(pkts))
4054 self.verify_capture_out(capture, same_port=True)
4055
4056 # in2out - no static mapping match
4057
4058 host0 = self.pg0.remote_hosts[0]
4059 self.pg0.remote_hosts[0] = self.pg0.remote_hosts[1]
4060 try:
4061 pkts = self.create_stream_out(self.pg1,
4062 dst_ip=self.pg0.remote_ip4,
4063 use_inside_ports=True)
4064 self.pg1.add_stream(pkts)
4065 self.pg_enable_capture(self.pg_interfaces)
4066 self.pg_start()
4067 capture = self.pg0.get_capture(len(pkts))
4068 self.verify_capture_in(capture, self.pg0)
4069
4070 pkts = self.create_stream_in(self.pg0, self.pg1)
4071 self.pg0.add_stream(pkts)
4072 self.pg_enable_capture(self.pg_interfaces)
4073 self.pg_start()
4074 capture = self.pg1.get_capture(len(pkts))
4075 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
4076 same_port=True)
4077 finally:
4078 self.pg0.remote_hosts[0] = host0
4079
4080 user = self.pg0.remote_hosts[1]
4081 sessions = self.vapi.nat44_user_session_dump(user.ip4n, 0)
4082 self.assertEqual(len(sessions), 3)
4083 self.assertTrue(sessions[0].ext_host_valid)
4084 self.vapi.nat44_del_session(
4085 sessions[0].inside_ip_address,
4086 sessions[0].inside_port,
4087 sessions[0].protocol,
4088 ext_host_address=sessions[0].ext_host_address,
4089 ext_host_port=sessions[0].ext_host_port)
4090 sessions = self.vapi.nat44_user_session_dump(user.ip4n, 0)
4091 self.assertEqual(len(sessions), 2)
4092
4093 finally:
4094 self.vapi.nat44_forwarding_enable_disable(0)
4095 self.vapi.nat44_add_del_static_mapping(local_ip=real_ip,
4096 external_ip=alias_ip,
4097 is_add=0)
4098
4099 def test_static_lb(self):
4100 """ NAT44 local service load balancing """
4101 external_addr_n = socket.inet_pton(socket.AF_INET, self.nat_addr)
4102 external_port = 80
4103 local_port = 8080
4104 server1 = self.pg0.remote_hosts[0]
4105 server2 = self.pg0.remote_hosts[1]
4106
4107 locals = [{'addr': server1.ip4n,
4108 'port': local_port,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07004109 'probability': 70,
4110 'vrf_id': 0},
Matus Fabiana6110b62018-06-13 05:39:07 -07004111 {'addr': server2.ip4n,
4112 'port': local_port,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07004113 'probability': 30,
4114 'vrf_id': 0}]
Matus Fabiana6110b62018-06-13 05:39:07 -07004115
4116 self.nat44_add_address(self.nat_addr)
4117 self.vapi.nat44_add_del_lb_static_mapping(external_addr_n,
4118 external_port,
4119 IP_PROTOS.tcp,
4120 local_num=len(locals),
4121 locals=locals)
4122 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4123 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4124 is_inside=0)
4125
4126 # from client to service
4127 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4128 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4129 TCP(sport=12345, dport=external_port))
4130 self.pg1.add_stream(p)
4131 self.pg_enable_capture(self.pg_interfaces)
4132 self.pg_start()
4133 capture = self.pg0.get_capture(1)
4134 p = capture[0]
4135 server = None
4136 try:
4137 ip = p[IP]
4138 tcp = p[TCP]
4139 self.assertIn(ip.dst, [server1.ip4, server2.ip4])
4140 if ip.dst == server1.ip4:
4141 server = server1
4142 else:
4143 server = server2
4144 self.assertEqual(tcp.dport, local_port)
4145 self.assert_packet_checksums_valid(p)
4146 except:
4147 self.logger.error(ppp("Unexpected or invalid packet:", p))
4148 raise
4149
4150 # from service back to client
4151 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
4152 IP(src=server.ip4, dst=self.pg1.remote_ip4) /
4153 TCP(sport=local_port, dport=12345))
4154 self.pg0.add_stream(p)
4155 self.pg_enable_capture(self.pg_interfaces)
4156 self.pg_start()
4157 capture = self.pg1.get_capture(1)
4158 p = capture[0]
4159 try:
4160 ip = p[IP]
4161 tcp = p[TCP]
4162 self.assertEqual(ip.src, self.nat_addr)
4163 self.assertEqual(tcp.sport, external_port)
4164 self.assert_packet_checksums_valid(p)
4165 except:
4166 self.logger.error(ppp("Unexpected or invalid packet:", p))
4167 raise
4168
4169 sessions = self.vapi.nat44_user_session_dump(server.ip4n, 0)
4170 self.assertEqual(len(sessions), 1)
4171 self.assertTrue(sessions[0].ext_host_valid)
4172 self.vapi.nat44_del_session(
4173 sessions[0].inside_ip_address,
4174 sessions[0].inside_port,
4175 sessions[0].protocol,
4176 ext_host_address=sessions[0].ext_host_address,
4177 ext_host_port=sessions[0].ext_host_port)
4178 sessions = self.vapi.nat44_user_session_dump(server.ip4n, 0)
4179 self.assertEqual(len(sessions), 0)
4180
4181 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
4182 def test_static_lb_multi_clients(self):
4183 """ NAT44 local service load balancing - multiple clients"""
4184
4185 external_addr_n = socket.inet_pton(socket.AF_INET, self.nat_addr)
4186 external_port = 80
4187 local_port = 8080
4188 server1 = self.pg0.remote_hosts[0]
4189 server2 = self.pg0.remote_hosts[1]
4190
4191 locals = [{'addr': server1.ip4n,
4192 'port': local_port,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07004193 'probability': 90,
4194 'vrf_id': 0},
Matus Fabiana6110b62018-06-13 05:39:07 -07004195 {'addr': server2.ip4n,
4196 'port': local_port,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07004197 'probability': 10,
4198 'vrf_id': 0}]
Matus Fabiana6110b62018-06-13 05:39:07 -07004199
4200 self.nat44_add_address(self.nat_addr)
4201 self.vapi.nat44_add_del_lb_static_mapping(external_addr_n,
4202 external_port,
4203 IP_PROTOS.tcp,
4204 local_num=len(locals),
4205 locals=locals)
4206 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4207 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4208 is_inside=0)
4209
4210 server1_n = 0
4211 server2_n = 0
4212 clients = ip4_range(self.pg1.remote_ip4, 10, 50)
4213 pkts = []
4214 for client in clients:
4215 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4216 IP(src=client, dst=self.nat_addr) /
4217 TCP(sport=12345, dport=external_port))
4218 pkts.append(p)
4219 self.pg1.add_stream(pkts)
4220 self.pg_enable_capture(self.pg_interfaces)
4221 self.pg_start()
4222 capture = self.pg0.get_capture(len(pkts))
4223 for p in capture:
4224 if p[IP].dst == server1.ip4:
4225 server1_n += 1
4226 else:
4227 server2_n += 1
Paul Vinciguerra3d2df212018-11-24 23:19:53 -08004228 self.assertGreater(server1_n, server2_n)
Matus Fabiana6110b62018-06-13 05:39:07 -07004229
4230 def test_static_lb_2(self):
4231 """ NAT44 local service load balancing (asymmetrical rule) """
4232 external_addr_n = socket.inet_pton(socket.AF_INET, self.nat_addr)
4233 external_port = 80
4234 local_port = 8080
4235 server1 = self.pg0.remote_hosts[0]
4236 server2 = self.pg0.remote_hosts[1]
4237
4238 locals = [{'addr': server1.ip4n,
4239 'port': local_port,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07004240 'probability': 70,
4241 'vrf_id': 0},
Matus Fabiana6110b62018-06-13 05:39:07 -07004242 {'addr': server2.ip4n,
4243 'port': local_port,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07004244 'probability': 30,
4245 'vrf_id': 0}]
Matus Fabiana6110b62018-06-13 05:39:07 -07004246
4247 self.vapi.nat44_forwarding_enable_disable(1)
4248 self.vapi.nat44_add_del_lb_static_mapping(external_addr_n,
4249 external_port,
4250 IP_PROTOS.tcp,
4251 out2in_only=1,
4252 local_num=len(locals),
4253 locals=locals)
4254 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4255 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4256 is_inside=0)
4257
4258 # from client to service
4259 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4260 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4261 TCP(sport=12345, dport=external_port))
4262 self.pg1.add_stream(p)
4263 self.pg_enable_capture(self.pg_interfaces)
4264 self.pg_start()
4265 capture = self.pg0.get_capture(1)
4266 p = capture[0]
4267 server = None
4268 try:
4269 ip = p[IP]
4270 tcp = p[TCP]
4271 self.assertIn(ip.dst, [server1.ip4, server2.ip4])
4272 if ip.dst == server1.ip4:
4273 server = server1
4274 else:
4275 server = server2
4276 self.assertEqual(tcp.dport, local_port)
4277 self.assert_packet_checksums_valid(p)
4278 except:
4279 self.logger.error(ppp("Unexpected or invalid packet:", p))
4280 raise
4281
4282 # from service back to client
4283 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
4284 IP(src=server.ip4, dst=self.pg1.remote_ip4) /
4285 TCP(sport=local_port, dport=12345))
4286 self.pg0.add_stream(p)
4287 self.pg_enable_capture(self.pg_interfaces)
4288 self.pg_start()
4289 capture = self.pg1.get_capture(1)
4290 p = capture[0]
4291 try:
4292 ip = p[IP]
4293 tcp = p[TCP]
4294 self.assertEqual(ip.src, self.nat_addr)
4295 self.assertEqual(tcp.sport, external_port)
4296 self.assert_packet_checksums_valid(p)
4297 except:
4298 self.logger.error(ppp("Unexpected or invalid packet:", p))
4299 raise
4300
4301 # from client to server (no translation)
4302 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4303 IP(src=self.pg1.remote_ip4, dst=server1.ip4) /
4304 TCP(sport=12346, dport=local_port))
4305 self.pg1.add_stream(p)
4306 self.pg_enable_capture(self.pg_interfaces)
4307 self.pg_start()
4308 capture = self.pg0.get_capture(1)
4309 p = capture[0]
4310 server = None
4311 try:
4312 ip = p[IP]
4313 tcp = p[TCP]
4314 self.assertEqual(ip.dst, server1.ip4)
4315 self.assertEqual(tcp.dport, local_port)
4316 self.assert_packet_checksums_valid(p)
4317 except:
4318 self.logger.error(ppp("Unexpected or invalid packet:", p))
4319 raise
4320
4321 # from service back to client (no translation)
4322 p = (Ether(src=server1.mac, dst=self.pg0.local_mac) /
4323 IP(src=server1.ip4, dst=self.pg1.remote_ip4) /
4324 TCP(sport=local_port, dport=12346))
4325 self.pg0.add_stream(p)
4326 self.pg_enable_capture(self.pg_interfaces)
4327 self.pg_start()
4328 capture = self.pg1.get_capture(1)
4329 p = capture[0]
4330 try:
4331 ip = p[IP]
4332 tcp = p[TCP]
4333 self.assertEqual(ip.src, server1.ip4)
4334 self.assertEqual(tcp.sport, local_port)
4335 self.assert_packet_checksums_valid(p)
4336 except:
4337 self.logger.error(ppp("Unexpected or invalid packet:", p))
4338 raise
4339
Matus Fabianea5b5be2018-09-03 05:02:23 -07004340 def test_lb_affinity(self):
4341 """ NAT44 local service load balancing affinity """
4342 external_addr_n = socket.inet_pton(socket.AF_INET, self.nat_addr)
4343 external_port = 80
4344 local_port = 8080
4345 server1 = self.pg0.remote_hosts[0]
4346 server2 = self.pg0.remote_hosts[1]
4347
4348 locals = [{'addr': server1.ip4n,
4349 'port': local_port,
4350 'probability': 50,
4351 'vrf_id': 0},
4352 {'addr': server2.ip4n,
4353 'port': local_port,
4354 'probability': 50,
4355 'vrf_id': 0}]
4356
4357 self.nat44_add_address(self.nat_addr)
4358 self.vapi.nat44_add_del_lb_static_mapping(external_addr_n,
4359 external_port,
4360 IP_PROTOS.tcp,
4361 affinity=10800,
4362 local_num=len(locals),
4363 locals=locals)
4364 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4365 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4366 is_inside=0)
4367
4368 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
4369 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4370 TCP(sport=1025, dport=external_port))
4371 self.pg1.add_stream(p)
4372 self.pg_enable_capture(self.pg_interfaces)
4373 self.pg_start()
4374 capture = self.pg0.get_capture(1)
4375 backend = capture[0][IP].dst
4376
4377 sessions = self.vapi.nat44_user_session_dump(
4378 socket.inet_pton(socket.AF_INET, backend), 0)
4379 self.assertEqual(len(sessions), 1)
4380 self.assertTrue(sessions[0].ext_host_valid)
4381 self.vapi.nat44_del_session(
4382 sessions[0].inside_ip_address,
4383 sessions[0].inside_port,
4384 sessions[0].protocol,
4385 ext_host_address=sessions[0].ext_host_address,
4386 ext_host_port=sessions[0].ext_host_port)
4387
4388 pkts = []
4389 for port in range(1030, 1100):
4390 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
4391 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4392 TCP(sport=port, dport=external_port))
4393 pkts.append(p)
4394 self.pg1.add_stream(pkts)
4395 self.pg_enable_capture(self.pg_interfaces)
4396 self.pg_start()
4397 capture = self.pg0.get_capture(len(pkts))
4398 for p in capture:
4399 self.assertEqual(p[IP].dst, backend)
4400
Matus Fabiana6110b62018-06-13 05:39:07 -07004401 def test_unknown_proto(self):
4402 """ NAT44 translate packet with unknown protocol """
4403 self.nat44_add_address(self.nat_addr)
4404 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4405 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4406 is_inside=0)
4407
4408 # in2out
4409 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
4410 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4411 TCP(sport=self.tcp_port_in, dport=20))
4412 self.pg0.add_stream(p)
4413 self.pg_enable_capture(self.pg_interfaces)
4414 self.pg_start()
4415 p = self.pg1.get_capture(1)
4416
4417 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
4418 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4419 GRE() /
4420 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
4421 TCP(sport=1234, dport=1234))
4422 self.pg0.add_stream(p)
4423 self.pg_enable_capture(self.pg_interfaces)
4424 self.pg_start()
4425 p = self.pg1.get_capture(1)
4426 packet = p[0]
4427 try:
4428 self.assertEqual(packet[IP].src, self.nat_addr)
4429 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
Paul Vinciguerra978aa642018-11-24 22:19:12 -08004430 self.assertEqual(packet.haslayer(GRE), 1)
Matus Fabiana6110b62018-06-13 05:39:07 -07004431 self.assert_packet_checksums_valid(packet)
4432 except:
4433 self.logger.error(ppp("Unexpected or invalid packet:", packet))
4434 raise
4435
4436 # out2in
4437 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
4438 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4439 GRE() /
4440 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
4441 TCP(sport=1234, dport=1234))
4442 self.pg1.add_stream(p)
4443 self.pg_enable_capture(self.pg_interfaces)
4444 self.pg_start()
4445 p = self.pg0.get_capture(1)
4446 packet = p[0]
4447 try:
4448 self.assertEqual(packet[IP].src, self.pg1.remote_ip4)
4449 self.assertEqual(packet[IP].dst, self.pg0.remote_ip4)
Paul Vinciguerra978aa642018-11-24 22:19:12 -08004450 self.assertEqual(packet.haslayer(GRE), 1)
Matus Fabiana6110b62018-06-13 05:39:07 -07004451 self.assert_packet_checksums_valid(packet)
4452 except:
4453 self.logger.error(ppp("Unexpected or invalid packet:", packet))
4454 raise
4455
4456 def test_hairpinning_unknown_proto(self):
4457 """ NAT44 translate packet with unknown protocol - hairpinning """
4458 host = self.pg0.remote_hosts[0]
4459 server = self.pg0.remote_hosts[1]
4460 host_in_port = 1234
4461 server_out_port = 8765
4462 server_nat_ip = "10.0.0.11"
4463
4464 self.nat44_add_address(self.nat_addr)
4465 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4466 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4467 is_inside=0)
4468
4469 # add static mapping for server
4470 self.nat44_add_static_mapping(server.ip4, server_nat_ip)
4471
4472 # host to server
4473 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
4474 IP(src=host.ip4, dst=server_nat_ip) /
4475 TCP(sport=host_in_port, dport=server_out_port))
4476 self.pg0.add_stream(p)
4477 self.pg_enable_capture(self.pg_interfaces)
4478 self.pg_start()
4479 self.pg0.get_capture(1)
4480
4481 p = (Ether(dst=self.pg0.local_mac, src=host.mac) /
4482 IP(src=host.ip4, dst=server_nat_ip) /
4483 GRE() /
4484 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
4485 TCP(sport=1234, dport=1234))
4486 self.pg0.add_stream(p)
4487 self.pg_enable_capture(self.pg_interfaces)
4488 self.pg_start()
4489 p = self.pg0.get_capture(1)
4490 packet = p[0]
4491 try:
4492 self.assertEqual(packet[IP].src, self.nat_addr)
4493 self.assertEqual(packet[IP].dst, server.ip4)
Paul Vinciguerra978aa642018-11-24 22:19:12 -08004494 self.assertEqual(packet.haslayer(GRE), 1)
Matus Fabiana6110b62018-06-13 05:39:07 -07004495 self.assert_packet_checksums_valid(packet)
4496 except:
4497 self.logger.error(ppp("Unexpected or invalid packet:", packet))
4498 raise
4499
4500 # server to host
4501 p = (Ether(dst=self.pg0.local_mac, src=server.mac) /
4502 IP(src=server.ip4, dst=self.nat_addr) /
4503 GRE() /
4504 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
4505 TCP(sport=1234, dport=1234))
4506 self.pg0.add_stream(p)
4507 self.pg_enable_capture(self.pg_interfaces)
4508 self.pg_start()
4509 p = self.pg0.get_capture(1)
4510 packet = p[0]
4511 try:
4512 self.assertEqual(packet[IP].src, server_nat_ip)
4513 self.assertEqual(packet[IP].dst, host.ip4)
Paul Vinciguerra978aa642018-11-24 22:19:12 -08004514 self.assertEqual(packet.haslayer(GRE), 1)
Matus Fabiana6110b62018-06-13 05:39:07 -07004515 self.assert_packet_checksums_valid(packet)
4516 except:
4517 self.logger.error(ppp("Unexpected or invalid packet:", packet))
4518 raise
4519
4520 def test_output_feature_and_service(self):
4521 """ NAT44 interface output feature and services """
4522 external_addr = '1.2.3.4'
4523 external_port = 80
4524 local_port = 8080
4525
4526 self.vapi.nat44_forwarding_enable_disable(1)
4527 self.nat44_add_address(self.nat_addr)
4528 self.vapi.nat44_add_del_identity_mapping(ip=self.pg1.remote_ip4n)
4529 self.nat44_add_static_mapping(self.pg0.remote_ip4, external_addr,
4530 local_port, external_port,
4531 proto=IP_PROTOS.tcp, out2in_only=1)
4532 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4533 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
4534 is_inside=0)
4535 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
4536 is_inside=0)
4537
4538 # from client to service
4539 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4540 IP(src=self.pg1.remote_ip4, dst=external_addr) /
4541 TCP(sport=12345, dport=external_port))
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 ip = p[IP]
4549 tcp = p[TCP]
4550 self.assertEqual(ip.dst, self.pg0.remote_ip4)
4551 self.assertEqual(tcp.dport, local_port)
4552 self.assert_packet_checksums_valid(p)
4553 except:
4554 self.logger.error(ppp("Unexpected or invalid packet:", p))
4555 raise
4556
4557 # from service back to client
4558 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4559 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4560 TCP(sport=local_port, dport=12345))
4561 self.pg0.add_stream(p)
4562 self.pg_enable_capture(self.pg_interfaces)
4563 self.pg_start()
4564 capture = self.pg1.get_capture(1)
4565 p = capture[0]
4566 try:
4567 ip = p[IP]
4568 tcp = p[TCP]
4569 self.assertEqual(ip.src, external_addr)
4570 self.assertEqual(tcp.sport, external_port)
4571 self.assert_packet_checksums_valid(p)
4572 except:
4573 self.logger.error(ppp("Unexpected or invalid packet:", p))
4574 raise
4575
4576 # from local network host to external network
4577 pkts = self.create_stream_in(self.pg0, self.pg1)
4578 self.pg0.add_stream(pkts)
4579 self.pg_enable_capture(self.pg_interfaces)
4580 self.pg_start()
4581 capture = self.pg1.get_capture(len(pkts))
4582 self.verify_capture_out(capture)
4583 pkts = self.create_stream_in(self.pg0, self.pg1)
4584 self.pg0.add_stream(pkts)
4585 self.pg_enable_capture(self.pg_interfaces)
4586 self.pg_start()
4587 capture = self.pg1.get_capture(len(pkts))
4588 self.verify_capture_out(capture)
4589
4590 # from external network back to local network host
4591 pkts = self.create_stream_out(self.pg1)
4592 self.pg1.add_stream(pkts)
4593 self.pg_enable_capture(self.pg_interfaces)
4594 self.pg_start()
4595 capture = self.pg0.get_capture(len(pkts))
4596 self.verify_capture_in(capture, self.pg0)
4597
4598 def test_output_feature_and_service2(self):
4599 """ NAT44 interface output feature and service host direct access """
4600 self.vapi.nat44_forwarding_enable_disable(1)
4601 self.nat44_add_address(self.nat_addr)
4602 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
4603 is_inside=0)
4604
4605 # session initiaded from service host - translate
4606 pkts = self.create_stream_in(self.pg0, self.pg1)
4607 self.pg0.add_stream(pkts)
4608 self.pg_enable_capture(self.pg_interfaces)
4609 self.pg_start()
4610 capture = self.pg1.get_capture(len(pkts))
4611 self.verify_capture_out(capture)
4612
4613 pkts = self.create_stream_out(self.pg1)
4614 self.pg1.add_stream(pkts)
4615 self.pg_enable_capture(self.pg_interfaces)
4616 self.pg_start()
4617 capture = self.pg0.get_capture(len(pkts))
4618 self.verify_capture_in(capture, self.pg0)
4619
4620 # session initiaded from remote host - do not translate
4621 self.tcp_port_in = 60303
4622 self.udp_port_in = 60304
4623 self.icmp_id_in = 60305
4624 pkts = self.create_stream_out(self.pg1,
4625 self.pg0.remote_ip4,
4626 use_inside_ports=True)
4627 self.pg1.add_stream(pkts)
4628 self.pg_enable_capture(self.pg_interfaces)
4629 self.pg_start()
4630 capture = self.pg0.get_capture(len(pkts))
4631 self.verify_capture_in(capture, self.pg0)
4632
4633 pkts = self.create_stream_in(self.pg0, self.pg1)
4634 self.pg0.add_stream(pkts)
4635 self.pg_enable_capture(self.pg_interfaces)
4636 self.pg_start()
4637 capture = self.pg1.get_capture(len(pkts))
4638 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
4639 same_port=True)
4640
4641 def test_output_feature_and_service3(self):
4642 """ NAT44 interface output feature and DST NAT """
4643 external_addr = '1.2.3.4'
4644 external_port = 80
4645 local_port = 8080
4646
4647 self.vapi.nat44_forwarding_enable_disable(1)
4648 self.nat44_add_address(self.nat_addr)
4649 self.nat44_add_static_mapping(self.pg1.remote_ip4, external_addr,
4650 local_port, external_port,
4651 proto=IP_PROTOS.tcp, out2in_only=1)
4652 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4653 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
4654 is_inside=0)
4655 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
4656 is_inside=0)
4657
4658 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4659 IP(src=self.pg0.remote_ip4, dst=external_addr) /
4660 TCP(sport=12345, dport=external_port))
4661 self.pg0.add_stream(p)
4662 self.pg_enable_capture(self.pg_interfaces)
4663 self.pg_start()
4664 capture = self.pg1.get_capture(1)
4665 p = capture[0]
4666 try:
4667 ip = p[IP]
4668 tcp = p[TCP]
4669 self.assertEqual(ip.src, self.pg0.remote_ip4)
4670 self.assertEqual(tcp.sport, 12345)
4671 self.assertEqual(ip.dst, self.pg1.remote_ip4)
4672 self.assertEqual(tcp.dport, local_port)
4673 self.assert_packet_checksums_valid(p)
4674 except:
4675 self.logger.error(ppp("Unexpected or invalid packet:", p))
4676 raise
4677
4678 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4679 IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
4680 TCP(sport=local_port, dport=12345))
4681 self.pg1.add_stream(p)
4682 self.pg_enable_capture(self.pg_interfaces)
4683 self.pg_start()
4684 capture = self.pg0.get_capture(1)
4685 p = capture[0]
4686 try:
4687 ip = p[IP]
4688 tcp = p[TCP]
4689 self.assertEqual(ip.src, external_addr)
4690 self.assertEqual(tcp.sport, external_port)
4691 self.assertEqual(ip.dst, self.pg0.remote_ip4)
4692 self.assertEqual(tcp.dport, 12345)
4693 self.assert_packet_checksums_valid(p)
4694 except:
4695 self.logger.error(ppp("Unexpected or invalid packet:", p))
4696 raise
4697
Matus Fabian182e37e2018-08-14 04:21:26 -07004698 def test_next_src_nat(self):
4699 """ On way back forward packet to nat44-in2out node. """
4700 twice_nat_addr = '10.0.1.3'
4701 external_port = 80
4702 local_port = 8080
4703 post_twice_nat_port = 0
4704
4705 self.vapi.nat44_forwarding_enable_disable(1)
4706 self.nat44_add_address(twice_nat_addr, twice_nat=1)
4707 self.nat44_add_static_mapping(self.pg6.remote_ip4, self.pg1.remote_ip4,
4708 local_port, external_port,
4709 proto=IP_PROTOS.tcp, out2in_only=1,
4710 self_twice_nat=1, vrf_id=1)
4711 self.vapi.nat44_interface_add_del_feature(self.pg6.sw_if_index,
4712 is_inside=0)
4713
4714 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
4715 IP(src=self.pg6.remote_ip4, dst=self.pg1.remote_ip4) /
4716 TCP(sport=12345, dport=external_port))
4717 self.pg6.add_stream(p)
4718 self.pg_enable_capture(self.pg_interfaces)
4719 self.pg_start()
4720 capture = self.pg6.get_capture(1)
4721 p = capture[0]
4722 try:
4723 ip = p[IP]
4724 tcp = p[TCP]
4725 self.assertEqual(ip.src, twice_nat_addr)
4726 self.assertNotEqual(tcp.sport, 12345)
4727 post_twice_nat_port = tcp.sport
4728 self.assertEqual(ip.dst, self.pg6.remote_ip4)
4729 self.assertEqual(tcp.dport, local_port)
4730 self.assert_packet_checksums_valid(p)
4731 except:
4732 self.logger.error(ppp("Unexpected or invalid packet:", p))
4733 raise
4734
4735 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
4736 IP(src=self.pg6.remote_ip4, dst=twice_nat_addr) /
4737 TCP(sport=local_port, dport=post_twice_nat_port))
4738 self.pg6.add_stream(p)
4739 self.pg_enable_capture(self.pg_interfaces)
4740 self.pg_start()
4741 capture = self.pg6.get_capture(1)
4742 p = capture[0]
4743 try:
4744 ip = p[IP]
4745 tcp = p[TCP]
4746 self.assertEqual(ip.src, self.pg1.remote_ip4)
4747 self.assertEqual(tcp.sport, external_port)
4748 self.assertEqual(ip.dst, self.pg6.remote_ip4)
4749 self.assertEqual(tcp.dport, 12345)
4750 self.assert_packet_checksums_valid(p)
4751 except:
4752 self.logger.error(ppp("Unexpected or invalid packet:", p))
4753 raise
4754
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004755 def twice_nat_common(self, self_twice_nat=False, same_pg=False, lb=False,
4756 client_id=None):
Matus Fabianb932d262017-12-18 05:38:24 -08004757 twice_nat_addr = '10.0.1.3'
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004758
Matus Fabianb932d262017-12-18 05:38:24 -08004759 port_in = 8080
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004760 if lb:
4761 if not same_pg:
4762 port_in1 = port_in
4763 port_in2 = port_in
4764 else:
4765 port_in1 = port_in+1
4766 port_in2 = port_in+2
4767
Matus Fabianb932d262017-12-18 05:38:24 -08004768 port_out = 80
4769 eh_port_out = 4567
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004770
4771 server1 = self.pg0.remote_hosts[0]
4772 server2 = self.pg0.remote_hosts[1]
4773 if lb and same_pg:
4774 server2 = server1
4775 if not lb:
4776 server = server1
4777
4778 pg0 = self.pg0
4779 if same_pg:
4780 pg1 = self.pg0
4781 else:
4782 pg1 = self.pg1
4783
4784 eh_translate = ((not self_twice_nat) or (not lb and same_pg) or
4785 client_id == 1)
4786
Matus Fabianb932d262017-12-18 05:38:24 -08004787 self.nat44_add_address(self.nat_addr)
4788 self.nat44_add_address(twice_nat_addr, twice_nat=1)
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004789 if not lb:
4790 self.nat44_add_static_mapping(pg0.remote_ip4, self.nat_addr,
4791 port_in, port_out,
4792 proto=IP_PROTOS.tcp,
4793 twice_nat=int(not self_twice_nat),
4794 self_twice_nat=int(self_twice_nat))
4795 else:
4796 locals = [{'addr': server1.ip4n,
4797 'port': port_in1,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07004798 'probability': 50,
4799 'vrf_id': 0},
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004800 {'addr': server2.ip4n,
4801 'port': port_in2,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07004802 'probability': 50,
4803 'vrf_id': 0}]
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004804 out_addr_n = socket.inet_pton(socket.AF_INET, self.nat_addr)
4805 self.vapi.nat44_add_del_lb_static_mapping(out_addr_n,
4806 port_out,
4807 IP_PROTOS.tcp,
4808 twice_nat=int(
4809 not self_twice_nat),
4810 self_twice_nat=int(
4811 self_twice_nat),
4812 local_num=len(locals),
4813 locals=locals)
4814 self.vapi.nat44_interface_add_del_feature(pg0.sw_if_index)
4815 self.vapi.nat44_interface_add_del_feature(pg1.sw_if_index,
Matus Fabianb932d262017-12-18 05:38:24 -08004816 is_inside=0)
4817
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004818 if same_pg:
4819 if not lb:
4820 client = server
4821 else:
4822 assert client_id is not None
4823 if client_id == 1:
4824 client = self.pg0.remote_hosts[0]
4825 elif client_id == 2:
4826 client = self.pg0.remote_hosts[1]
4827 else:
4828 client = pg1.remote_hosts[0]
4829 p = (Ether(src=pg1.remote_mac, dst=pg1.local_mac) /
4830 IP(src=client.ip4, dst=self.nat_addr) /
Matus Fabianb932d262017-12-18 05:38:24 -08004831 TCP(sport=eh_port_out, dport=port_out))
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004832 pg1.add_stream(p)
Matus Fabianb932d262017-12-18 05:38:24 -08004833 self.pg_enable_capture(self.pg_interfaces)
4834 self.pg_start()
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004835 capture = pg0.get_capture(1)
Matus Fabianb932d262017-12-18 05:38:24 -08004836 p = capture[0]
4837 try:
4838 ip = p[IP]
4839 tcp = p[TCP]
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004840 if lb:
4841 if ip.dst == server1.ip4:
4842 server = server1
4843 port_in = port_in1
4844 else:
4845 server = server2
4846 port_in = port_in2
4847 self.assertEqual(ip.dst, server.ip4)
4848 if lb and same_pg:
4849 self.assertIn(tcp.dport, [port_in1, port_in2])
4850 else:
4851 self.assertEqual(tcp.dport, port_in)
4852 if eh_translate:
4853 self.assertEqual(ip.src, twice_nat_addr)
4854 self.assertNotEqual(tcp.sport, eh_port_out)
4855 else:
4856 self.assertEqual(ip.src, client.ip4)
4857 self.assertEqual(tcp.sport, eh_port_out)
4858 eh_addr_in = ip.src
Matus Fabianb932d262017-12-18 05:38:24 -08004859 eh_port_in = tcp.sport
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004860 saved_port_in = tcp.dport
Klement Sekerad81ae412018-05-16 10:52:54 +02004861 self.assert_packet_checksums_valid(p)
Matus Fabianb932d262017-12-18 05:38:24 -08004862 except:
4863 self.logger.error(ppp("Unexpected or invalid packet:", p))
4864 raise
4865
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004866 p = (Ether(src=server.mac, dst=pg0.local_mac) /
4867 IP(src=server.ip4, dst=eh_addr_in) /
4868 TCP(sport=saved_port_in, dport=eh_port_in))
4869 pg0.add_stream(p)
Matus Fabianb932d262017-12-18 05:38:24 -08004870 self.pg_enable_capture(self.pg_interfaces)
4871 self.pg_start()
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004872 capture = pg1.get_capture(1)
Matus Fabianb932d262017-12-18 05:38:24 -08004873 p = capture[0]
4874 try:
4875 ip = p[IP]
4876 tcp = p[TCP]
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004877 self.assertEqual(ip.dst, client.ip4)
Matus Fabianb932d262017-12-18 05:38:24 -08004878 self.assertEqual(ip.src, self.nat_addr)
4879 self.assertEqual(tcp.dport, eh_port_out)
4880 self.assertEqual(tcp.sport, port_out)
Klement Sekerad81ae412018-05-16 10:52:54 +02004881 self.assert_packet_checksums_valid(p)
Matus Fabianb932d262017-12-18 05:38:24 -08004882 except:
4883 self.logger.error(ppp("Unexpected or invalid packet:", p))
4884 raise
4885
Matus Fabian70a26ac2018-05-14 06:20:28 -07004886 if eh_translate:
4887 sessions = self.vapi.nat44_user_session_dump(server.ip4n, 0)
4888 self.assertEqual(len(sessions), 1)
4889 self.assertTrue(sessions[0].ext_host_valid)
4890 self.assertTrue(sessions[0].is_twicenat)
4891 self.vapi.nat44_del_session(
4892 sessions[0].inside_ip_address,
4893 sessions[0].inside_port,
4894 sessions[0].protocol,
4895 ext_host_address=sessions[0].ext_host_nat_address,
4896 ext_host_port=sessions[0].ext_host_nat_port)
4897 sessions = self.vapi.nat44_user_session_dump(server.ip4n, 0)
4898 self.assertEqual(len(sessions), 0)
4899
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004900 def test_twice_nat(self):
4901 """ Twice NAT44 """
4902 self.twice_nat_common()
4903
4904 def test_self_twice_nat_positive(self):
4905 """ Self Twice NAT44 (positive test) """
4906 self.twice_nat_common(self_twice_nat=True, same_pg=True)
4907
4908 def test_self_twice_nat_negative(self):
4909 """ Self Twice NAT44 (negative test) """
4910 self.twice_nat_common(self_twice_nat=True)
4911
Matus Fabianb932d262017-12-18 05:38:24 -08004912 def test_twice_nat_lb(self):
4913 """ Twice NAT44 local service load balancing """
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004914 self.twice_nat_common(lb=True)
Matus Fabianb932d262017-12-18 05:38:24 -08004915
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004916 def test_self_twice_nat_lb_positive(self):
4917 """ Self Twice NAT44 local service load balancing (positive test) """
4918 self.twice_nat_common(lb=True, self_twice_nat=True, same_pg=True,
4919 client_id=1)
Matus Fabianb932d262017-12-18 05:38:24 -08004920
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02004921 def test_self_twice_nat_lb_negative(self):
4922 """ Self Twice NAT44 local service load balancing (negative test) """
4923 self.twice_nat_common(lb=True, self_twice_nat=True, same_pg=True,
4924 client_id=2)
Matus Fabianb932d262017-12-18 05:38:24 -08004925
4926 def test_twice_nat_interface_addr(self):
4927 """ Acquire twice NAT44 addresses from interface """
Matus Fabiana6110b62018-06-13 05:39:07 -07004928 self.vapi.nat44_add_interface_addr(self.pg3.sw_if_index, twice_nat=1)
Matus Fabianb932d262017-12-18 05:38:24 -08004929
4930 # no address in NAT pool
4931 adresses = self.vapi.nat44_address_dump()
4932 self.assertEqual(0, len(adresses))
4933
4934 # configure interface address and check NAT address pool
Matus Fabiana6110b62018-06-13 05:39:07 -07004935 self.pg3.config_ip4()
Matus Fabianb932d262017-12-18 05:38:24 -08004936 adresses = self.vapi.nat44_address_dump()
4937 self.assertEqual(1, len(adresses))
Matus Fabiana6110b62018-06-13 05:39:07 -07004938 self.assertEqual(adresses[0].ip_address[0:4], self.pg3.local_ip4n)
Matus Fabianb932d262017-12-18 05:38:24 -08004939 self.assertEqual(adresses[0].twice_nat, 1)
4940
4941 # remove interface address and check NAT address pool
Matus Fabiana6110b62018-06-13 05:39:07 -07004942 self.pg3.unconfig_ip4()
Matus Fabianb932d262017-12-18 05:38:24 -08004943 adresses = self.vapi.nat44_address_dump()
4944 self.assertEqual(0, len(adresses))
4945
Matus Fabian6c01dce2018-11-16 04:41:31 -08004946 def test_tcp_close(self):
4947 """ Close TCP session from inside network - output feature """
4948 self.vapi.nat44_forwarding_enable_disable(1)
4949 self.nat44_add_address(self.pg1.local_ip4)
4950 twice_nat_addr = '10.0.1.3'
4951 service_ip = '192.168.16.150'
4952 self.nat44_add_address(twice_nat_addr, twice_nat=1)
4953 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4954 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
4955 is_inside=0)
4956 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
4957 is_inside=0)
4958 self.nat44_add_static_mapping(self.pg0.remote_ip4,
4959 service_ip,
4960 80,
4961 80,
4962 proto=IP_PROTOS.tcp,
4963 out2in_only=1,
4964 twice_nat=1)
4965 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
4966 start_sessnum = len(sessions)
4967
4968 # SYN packet out->in
4969 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4970 IP(src=self.pg1.remote_ip4, dst=service_ip) /
4971 TCP(sport=33898, dport=80, flags="S"))
4972 self.pg1.add_stream(p)
4973 self.pg_enable_capture(self.pg_interfaces)
4974 self.pg_start()
4975 capture = self.pg0.get_capture(1)
4976 p = capture[0]
4977 tcp_port = p[TCP].sport
4978
4979 # SYN + ACK packet in->out
4980 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4981 IP(src=self.pg0.remote_ip4, dst=twice_nat_addr) /
4982 TCP(sport=80, dport=tcp_port, flags="SA"))
4983 self.pg0.add_stream(p)
4984 self.pg_enable_capture(self.pg_interfaces)
4985 self.pg_start()
4986 self.pg1.get_capture(1)
4987
4988 # ACK packet out->in
4989 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4990 IP(src=self.pg1.remote_ip4, dst=service_ip) /
4991 TCP(sport=33898, dport=80, flags="A"))
4992 self.pg1.add_stream(p)
4993 self.pg_enable_capture(self.pg_interfaces)
4994 self.pg_start()
4995 self.pg0.get_capture(1)
4996
4997 # FIN packet in -> out
4998 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4999 IP(src=self.pg0.remote_ip4, dst=twice_nat_addr) /
5000 TCP(sport=80, dport=tcp_port, flags="FA", seq=100, ack=300))
5001 self.pg0.add_stream(p)
5002 self.pg_enable_capture(self.pg_interfaces)
5003 self.pg_start()
5004 self.pg1.get_capture(1)
5005
5006 # FIN+ACK packet out -> in
5007 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5008 IP(src=self.pg1.remote_ip4, dst=service_ip) /
5009 TCP(sport=33898, dport=80, flags="FA", seq=300, ack=101))
5010 self.pg1.add_stream(p)
5011 self.pg_enable_capture(self.pg_interfaces)
5012 self.pg_start()
5013 self.pg0.get_capture(1)
5014
5015 # ACK packet in -> out
5016 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5017 IP(src=self.pg0.remote_ip4, dst=twice_nat_addr) /
5018 TCP(sport=80, dport=tcp_port, flags="A", seq=101, ack=301))
5019 self.pg0.add_stream(p)
5020 self.pg_enable_capture(self.pg_interfaces)
5021 self.pg_start()
5022 self.pg1.get_capture(1)
5023
5024 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n,
5025 0)
5026 self.assertEqual(len(sessions) - start_sessnum, 0)
5027
Matus Fabianebdf1902018-05-04 03:57:42 -07005028 def test_tcp_session_close_in(self):
5029 """ Close TCP session from inside network """
Matus Fabian229c1aa2018-05-28 04:09:52 -07005030 self.tcp_port_out = 10505
Matus Fabianebdf1902018-05-04 03:57:42 -07005031 self.nat44_add_address(self.nat_addr)
Matus Fabian229c1aa2018-05-28 04:09:52 -07005032 self.nat44_add_static_mapping(self.pg0.remote_ip4,
5033 self.nat_addr,
5034 self.tcp_port_in,
5035 self.tcp_port_out,
5036 proto=IP_PROTOS.tcp,
5037 twice_nat=1)
Matus Fabianebdf1902018-05-04 03:57:42 -07005038 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5039 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
5040 is_inside=0)
5041
5042 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
5043 start_sessnum = len(sessions)
5044
5045 self.initiate_tcp_session(self.pg0, self.pg1)
5046
Matus Fabian229c1aa2018-05-28 04:09:52 -07005047 # FIN packet in -> out
5048 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5049 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5050 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
5051 flags="FA", seq=100, ack=300))
5052 self.pg0.add_stream(p)
5053 self.pg_enable_capture(self.pg_interfaces)
5054 self.pg_start()
5055 self.pg1.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07005056
Matus Fabian229c1aa2018-05-28 04:09:52 -07005057 pkts = []
Matus Fabianebdf1902018-05-04 03:57:42 -07005058
Matus Fabian229c1aa2018-05-28 04:09:52 -07005059 # ACK packet out -> in
5060 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5061 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5062 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
5063 flags="A", seq=300, ack=101))
5064 pkts.append(p)
Matus Fabianebdf1902018-05-04 03:57:42 -07005065
Matus Fabian229c1aa2018-05-28 04:09:52 -07005066 # FIN packet out -> in
5067 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5068 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5069 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
5070 flags="FA", seq=300, ack=101))
5071 pkts.append(p)
Matus Fabianebdf1902018-05-04 03:57:42 -07005072
Matus Fabian229c1aa2018-05-28 04:09:52 -07005073 self.pg1.add_stream(pkts)
5074 self.pg_enable_capture(self.pg_interfaces)
5075 self.pg_start()
5076 self.pg0.get_capture(2)
Matus Fabianebdf1902018-05-04 03:57:42 -07005077
Matus Fabian229c1aa2018-05-28 04:09:52 -07005078 # ACK packet in -> out
5079 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5080 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5081 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
5082 flags="A", seq=101, ack=301))
5083 self.pg0.add_stream(p)
5084 self.pg_enable_capture(self.pg_interfaces)
5085 self.pg_start()
5086 self.pg1.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07005087
Matus Fabian229c1aa2018-05-28 04:09:52 -07005088 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n,
5089 0)
5090 self.assertEqual(len(sessions) - start_sessnum, 0)
Matus Fabianebdf1902018-05-04 03:57:42 -07005091
5092 def test_tcp_session_close_out(self):
5093 """ Close TCP session from outside network """
Matus Fabian229c1aa2018-05-28 04:09:52 -07005094 self.tcp_port_out = 10505
Matus Fabianebdf1902018-05-04 03:57:42 -07005095 self.nat44_add_address(self.nat_addr)
Matus Fabian229c1aa2018-05-28 04:09:52 -07005096 self.nat44_add_static_mapping(self.pg0.remote_ip4,
5097 self.nat_addr,
5098 self.tcp_port_in,
5099 self.tcp_port_out,
5100 proto=IP_PROTOS.tcp,
5101 twice_nat=1)
Matus Fabianebdf1902018-05-04 03:57:42 -07005102 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5103 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
5104 is_inside=0)
5105
5106 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
5107 start_sessnum = len(sessions)
5108
5109 self.initiate_tcp_session(self.pg0, self.pg1)
5110
Matus Fabian229c1aa2018-05-28 04:09:52 -07005111 # FIN packet out -> in
5112 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5113 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5114 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
5115 flags="FA", seq=100, ack=300))
5116 self.pg1.add_stream(p)
5117 self.pg_enable_capture(self.pg_interfaces)
5118 self.pg_start()
5119 self.pg0.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07005120
Matus Fabian229c1aa2018-05-28 04:09:52 -07005121 # FIN+ACK packet in -> out
5122 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5123 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5124 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
5125 flags="FA", seq=300, ack=101))
Matus Fabianebdf1902018-05-04 03:57:42 -07005126
Matus Fabian229c1aa2018-05-28 04:09:52 -07005127 self.pg0.add_stream(p)
5128 self.pg_enable_capture(self.pg_interfaces)
5129 self.pg_start()
5130 self.pg1.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07005131
Matus Fabian229c1aa2018-05-28 04:09:52 -07005132 # ACK packet out -> in
5133 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5134 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5135 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
5136 flags="A", seq=101, ack=301))
5137 self.pg1.add_stream(p)
5138 self.pg_enable_capture(self.pg_interfaces)
5139 self.pg_start()
5140 self.pg0.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07005141
Matus Fabian229c1aa2018-05-28 04:09:52 -07005142 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n,
5143 0)
5144 self.assertEqual(len(sessions) - start_sessnum, 0)
Matus Fabianebdf1902018-05-04 03:57:42 -07005145
5146 def test_tcp_session_close_simultaneous(self):
5147 """ Close TCP session from inside network """
Matus Fabian229c1aa2018-05-28 04:09:52 -07005148 self.tcp_port_out = 10505
Matus Fabianebdf1902018-05-04 03:57:42 -07005149 self.nat44_add_address(self.nat_addr)
Matus Fabian229c1aa2018-05-28 04:09:52 -07005150 self.nat44_add_static_mapping(self.pg0.remote_ip4,
5151 self.nat_addr,
5152 self.tcp_port_in,
5153 self.tcp_port_out,
5154 proto=IP_PROTOS.tcp,
5155 twice_nat=1)
Matus Fabianebdf1902018-05-04 03:57:42 -07005156 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5157 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
5158 is_inside=0)
5159
5160 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
5161 start_sessnum = len(sessions)
5162
5163 self.initiate_tcp_session(self.pg0, self.pg1)
5164
Matus Fabian229c1aa2018-05-28 04:09:52 -07005165 # FIN packet in -> out
5166 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5167 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5168 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
5169 flags="FA", seq=100, ack=300))
5170 self.pg0.add_stream(p)
5171 self.pg_enable_capture(self.pg_interfaces)
5172 self.pg_start()
5173 self.pg1.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07005174
Matus Fabian229c1aa2018-05-28 04:09:52 -07005175 # FIN packet out -> in
5176 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5177 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5178 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
5179 flags="FA", seq=300, ack=100))
5180 self.pg1.add_stream(p)
5181 self.pg_enable_capture(self.pg_interfaces)
5182 self.pg_start()
5183 self.pg0.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07005184
Matus Fabian229c1aa2018-05-28 04:09:52 -07005185 # ACK packet in -> out
5186 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5187 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5188 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
5189 flags="A", seq=101, ack=301))
5190 self.pg0.add_stream(p)
5191 self.pg_enable_capture(self.pg_interfaces)
5192 self.pg_start()
5193 self.pg1.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07005194
Matus Fabian229c1aa2018-05-28 04:09:52 -07005195 # ACK packet out -> in
5196 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5197 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5198 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
5199 flags="A", seq=301, ack=101))
5200 self.pg1.add_stream(p)
5201 self.pg_enable_capture(self.pg_interfaces)
5202 self.pg_start()
5203 self.pg0.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07005204
Matus Fabian229c1aa2018-05-28 04:09:52 -07005205 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n,
5206 0)
5207 self.assertEqual(len(sessions) - start_sessnum, 0)
Matus Fabianebdf1902018-05-04 03:57:42 -07005208
Matus Fabiana6110b62018-06-13 05:39:07 -07005209 def test_one_armed_nat44_static(self):
5210 """ One armed NAT44 and 1:1 NAPT asymmetrical rule """
5211 remote_host = self.pg4.remote_hosts[0]
5212 local_host = self.pg4.remote_hosts[1]
5213 external_port = 80
5214 local_port = 8080
5215 eh_port_in = 0
5216
5217 self.vapi.nat44_forwarding_enable_disable(1)
5218 self.nat44_add_address(self.nat_addr, twice_nat=1)
5219 self.nat44_add_static_mapping(local_host.ip4, self.nat_addr,
5220 local_port, external_port,
5221 proto=IP_PROTOS.tcp, out2in_only=1,
5222 twice_nat=1)
5223 self.vapi.nat44_interface_add_del_feature(self.pg4.sw_if_index)
5224 self.vapi.nat44_interface_add_del_feature(self.pg4.sw_if_index,
5225 is_inside=0)
5226
5227 # from client to service
5228 p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
5229 IP(src=remote_host.ip4, dst=self.nat_addr) /
5230 TCP(sport=12345, dport=external_port))
5231 self.pg4.add_stream(p)
5232 self.pg_enable_capture(self.pg_interfaces)
5233 self.pg_start()
5234 capture = self.pg4.get_capture(1)
5235 p = capture[0]
5236 try:
5237 ip = p[IP]
5238 tcp = p[TCP]
5239 self.assertEqual(ip.dst, local_host.ip4)
5240 self.assertEqual(ip.src, self.nat_addr)
5241 self.assertEqual(tcp.dport, local_port)
5242 self.assertNotEqual(tcp.sport, 12345)
5243 eh_port_in = tcp.sport
5244 self.assert_packet_checksums_valid(p)
5245 except:
5246 self.logger.error(ppp("Unexpected or invalid packet:", p))
5247 raise
5248
5249 # from service back to client
5250 p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
5251 IP(src=local_host.ip4, dst=self.nat_addr) /
5252 TCP(sport=local_port, dport=eh_port_in))
5253 self.pg4.add_stream(p)
5254 self.pg_enable_capture(self.pg_interfaces)
5255 self.pg_start()
5256 capture = self.pg4.get_capture(1)
5257 p = capture[0]
5258 try:
5259 ip = p[IP]
5260 tcp = p[TCP]
5261 self.assertEqual(ip.src, self.nat_addr)
5262 self.assertEqual(ip.dst, remote_host.ip4)
5263 self.assertEqual(tcp.sport, external_port)
5264 self.assertEqual(tcp.dport, 12345)
5265 self.assert_packet_checksums_valid(p)
5266 except:
5267 self.logger.error(ppp("Unexpected or invalid packet:", p))
5268 raise
5269
5270 def test_static_with_port_out2(self):
5271 """ 1:1 NAPT asymmetrical rule """
5272
5273 external_port = 80
5274 local_port = 8080
5275
5276 self.vapi.nat44_forwarding_enable_disable(1)
5277 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
5278 local_port, external_port,
5279 proto=IP_PROTOS.tcp, out2in_only=1)
5280 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5281 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
5282 is_inside=0)
5283
5284 # from client to service
5285 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5286 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5287 TCP(sport=12345, dport=external_port))
5288 self.pg1.add_stream(p)
5289 self.pg_enable_capture(self.pg_interfaces)
5290 self.pg_start()
5291 capture = self.pg0.get_capture(1)
5292 p = capture[0]
5293 try:
5294 ip = p[IP]
5295 tcp = p[TCP]
5296 self.assertEqual(ip.dst, self.pg0.remote_ip4)
5297 self.assertEqual(tcp.dport, local_port)
5298 self.assert_packet_checksums_valid(p)
5299 except:
5300 self.logger.error(ppp("Unexpected or invalid packet:", p))
5301 raise
5302
5303 # ICMP error
5304 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5305 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5306 ICMP(type=11) / capture[0][IP])
5307 self.pg0.add_stream(p)
5308 self.pg_enable_capture(self.pg_interfaces)
5309 self.pg_start()
5310 capture = self.pg1.get_capture(1)
5311 p = capture[0]
5312 try:
5313 self.assertEqual(p[IP].src, self.nat_addr)
5314 inner = p[IPerror]
5315 self.assertEqual(inner.dst, self.nat_addr)
5316 self.assertEqual(inner[TCPerror].dport, external_port)
5317 except:
5318 self.logger.error(ppp("Unexpected or invalid packet:", p))
5319 raise
5320
5321 # from service back to client
5322 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5323 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5324 TCP(sport=local_port, dport=12345))
5325 self.pg0.add_stream(p)
5326 self.pg_enable_capture(self.pg_interfaces)
5327 self.pg_start()
5328 capture = self.pg1.get_capture(1)
5329 p = capture[0]
5330 try:
5331 ip = p[IP]
5332 tcp = p[TCP]
5333 self.assertEqual(ip.src, self.nat_addr)
5334 self.assertEqual(tcp.sport, external_port)
5335 self.assert_packet_checksums_valid(p)
5336 except:
5337 self.logger.error(ppp("Unexpected or invalid packet:", p))
5338 raise
5339
5340 # ICMP error
5341 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
5342 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5343 ICMP(type=11) / capture[0][IP])
5344 self.pg1.add_stream(p)
5345 self.pg_enable_capture(self.pg_interfaces)
5346 self.pg_start()
5347 capture = self.pg0.get_capture(1)
5348 p = capture[0]
5349 try:
5350 self.assertEqual(p[IP].dst, self.pg0.remote_ip4)
5351 inner = p[IPerror]
5352 self.assertEqual(inner.src, self.pg0.remote_ip4)
5353 self.assertEqual(inner[TCPerror].sport, local_port)
5354 except:
5355 self.logger.error(ppp("Unexpected or invalid packet:", p))
5356 raise
5357
5358 # from client to server (no translation)
5359 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5360 IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
5361 TCP(sport=12346, dport=local_port))
5362 self.pg1.add_stream(p)
5363 self.pg_enable_capture(self.pg_interfaces)
5364 self.pg_start()
5365 capture = self.pg0.get_capture(1)
5366 p = capture[0]
5367 try:
5368 ip = p[IP]
5369 tcp = p[TCP]
5370 self.assertEqual(ip.dst, self.pg0.remote_ip4)
5371 self.assertEqual(tcp.dport, local_port)
5372 self.assert_packet_checksums_valid(p)
5373 except:
5374 self.logger.error(ppp("Unexpected or invalid packet:", p))
5375 raise
5376
5377 # from service back to client (no translation)
5378 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5379 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5380 TCP(sport=local_port, dport=12346))
5381 self.pg0.add_stream(p)
5382 self.pg_enable_capture(self.pg_interfaces)
5383 self.pg_start()
5384 capture = self.pg1.get_capture(1)
5385 p = capture[0]
5386 try:
5387 ip = p[IP]
5388 tcp = p[TCP]
5389 self.assertEqual(ip.src, self.pg0.remote_ip4)
5390 self.assertEqual(tcp.sport, local_port)
5391 self.assert_packet_checksums_valid(p)
5392 except:
5393 self.logger.error(ppp("Unexpected or invalid packet:", p))
5394 raise
5395
Matus Fabian235a47e2018-06-25 16:42:36 -07005396 def test_output_feature(self):
5397 """ NAT44 interface output feature (in2out postrouting) """
5398 self.vapi.nat44_forwarding_enable_disable(1)
5399 self.nat44_add_address(self.nat_addr)
5400 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
5401 is_inside=0)
5402 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
5403 is_inside=0)
5404
5405 # in2out
5406 pkts = self.create_stream_in(self.pg0, self.pg1)
5407 self.pg0.add_stream(pkts)
5408 self.pg_enable_capture(self.pg_interfaces)
5409 self.pg_start()
5410 capture = self.pg1.get_capture(len(pkts))
5411 self.verify_capture_out(capture)
5412
5413 # out2in
5414 pkts = self.create_stream_out(self.pg1)
5415 self.pg1.add_stream(pkts)
5416 self.pg_enable_capture(self.pg_interfaces)
5417 self.pg_start()
5418 capture = self.pg0.get_capture(len(pkts))
5419 self.verify_capture_in(capture, self.pg0)
5420
Matus Fabian8008d7c2018-07-09 01:34:20 -07005421 def test_multiple_vrf(self):
5422 """ Multiple VRF setup """
5423 external_addr = '1.2.3.4'
5424 external_port = 80
5425 local_port = 8080
5426 port = 0
5427
5428 self.vapi.nat44_forwarding_enable_disable(1)
5429 self.nat44_add_address(self.nat_addr)
5430 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5431 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
5432 is_inside=0)
5433 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
5434 is_inside=0)
5435 self.vapi.nat44_interface_add_del_feature(self.pg5.sw_if_index)
5436 self.vapi.nat44_interface_add_del_feature(self.pg5.sw_if_index,
5437 is_inside=0)
5438 self.vapi.nat44_interface_add_del_feature(self.pg6.sw_if_index,
5439 is_inside=0)
5440 self.nat44_add_static_mapping(self.pg5.remote_ip4, external_addr,
5441 local_port, external_port, vrf_id=1,
5442 proto=IP_PROTOS.tcp, out2in_only=1)
5443 self.nat44_add_static_mapping(
5444 self.pg0.remote_ip4, external_sw_if_index=self.pg0.sw_if_index,
5445 local_port=local_port, vrf_id=0, external_port=external_port,
5446 proto=IP_PROTOS.tcp, out2in_only=1)
5447
5448 # from client to service (both VRF1)
5449 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
5450 IP(src=self.pg6.remote_ip4, dst=external_addr) /
5451 TCP(sport=12345, dport=external_port))
5452 self.pg6.add_stream(p)
5453 self.pg_enable_capture(self.pg_interfaces)
5454 self.pg_start()
5455 capture = self.pg5.get_capture(1)
5456 p = capture[0]
5457 try:
5458 ip = p[IP]
5459 tcp = p[TCP]
5460 self.assertEqual(ip.dst, self.pg5.remote_ip4)
5461 self.assertEqual(tcp.dport, local_port)
5462 self.assert_packet_checksums_valid(p)
5463 except:
5464 self.logger.error(ppp("Unexpected or invalid packet:", p))
5465 raise
5466
5467 # from service back to client (both VRF1)
5468 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
5469 IP(src=self.pg5.remote_ip4, dst=self.pg6.remote_ip4) /
5470 TCP(sport=local_port, dport=12345))
5471 self.pg5.add_stream(p)
5472 self.pg_enable_capture(self.pg_interfaces)
5473 self.pg_start()
5474 capture = self.pg6.get_capture(1)
5475 p = capture[0]
5476 try:
5477 ip = p[IP]
5478 tcp = p[TCP]
5479 self.assertEqual(ip.src, external_addr)
5480 self.assertEqual(tcp.sport, external_port)
5481 self.assert_packet_checksums_valid(p)
5482 except:
5483 self.logger.error(ppp("Unexpected or invalid packet:", p))
5484 raise
5485
5486 # dynamic NAT from VRF1 to VRF0 (output-feature)
5487 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
5488 IP(src=self.pg5.remote_ip4, dst=self.pg1.remote_ip4) /
5489 TCP(sport=2345, dport=22))
5490 self.pg5.add_stream(p)
5491 self.pg_enable_capture(self.pg_interfaces)
5492 self.pg_start()
5493 capture = self.pg1.get_capture(1)
5494 p = capture[0]
5495 try:
5496 ip = p[IP]
5497 tcp = p[TCP]
5498 self.assertEqual(ip.src, self.nat_addr)
5499 self.assertNotEqual(tcp.sport, 2345)
5500 self.assert_packet_checksums_valid(p)
5501 port = tcp.sport
5502 except:
5503 self.logger.error(ppp("Unexpected or invalid packet:", p))
5504 raise
5505
5506 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5507 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5508 TCP(sport=22, dport=port))
5509 self.pg1.add_stream(p)
5510 self.pg_enable_capture(self.pg_interfaces)
5511 self.pg_start()
5512 capture = self.pg5.get_capture(1)
5513 p = capture[0]
5514 try:
5515 ip = p[IP]
5516 tcp = p[TCP]
5517 self.assertEqual(ip.dst, self.pg5.remote_ip4)
5518 self.assertEqual(tcp.dport, 2345)
5519 self.assert_packet_checksums_valid(p)
5520 except:
5521 self.logger.error(ppp("Unexpected or invalid packet:", p))
5522 raise
5523
5524 # from client VRF1 to service VRF0
5525 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
5526 IP(src=self.pg6.remote_ip4, dst=self.pg0.local_ip4) /
5527 TCP(sport=12346, dport=external_port))
5528 self.pg6.add_stream(p)
5529 self.pg_enable_capture(self.pg_interfaces)
5530 self.pg_start()
5531 capture = self.pg0.get_capture(1)
5532 p = capture[0]
5533 try:
5534 ip = p[IP]
5535 tcp = p[TCP]
5536 self.assertEqual(ip.dst, self.pg0.remote_ip4)
5537 self.assertEqual(tcp.dport, local_port)
5538 self.assert_packet_checksums_valid(p)
5539 except:
5540 self.logger.error(ppp("Unexpected or invalid packet:", p))
5541 raise
5542
5543 # from service VRF0 back to client VRF1
5544 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5545 IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
5546 TCP(sport=local_port, dport=12346))
5547 self.pg0.add_stream(p)
5548 self.pg_enable_capture(self.pg_interfaces)
5549 self.pg_start()
5550 capture = self.pg6.get_capture(1)
5551 p = capture[0]
5552 try:
5553 ip = p[IP]
5554 tcp = p[TCP]
5555 self.assertEqual(ip.src, self.pg0.local_ip4)
5556 self.assertEqual(tcp.sport, external_port)
5557 self.assert_packet_checksums_valid(p)
5558 except:
5559 self.logger.error(ppp("Unexpected or invalid packet:", p))
5560 raise
5561
5562 # from client VRF0 to service VRF1
5563 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5564 IP(src=self.pg0.remote_ip4, dst=external_addr) /
5565 TCP(sport=12347, dport=external_port))
5566 self.pg0.add_stream(p)
5567 self.pg_enable_capture(self.pg_interfaces)
5568 self.pg_start()
5569 capture = self.pg5.get_capture(1)
5570 p = capture[0]
5571 try:
5572 ip = p[IP]
5573 tcp = p[TCP]
5574 self.assertEqual(ip.dst, self.pg5.remote_ip4)
5575 self.assertEqual(tcp.dport, local_port)
5576 self.assert_packet_checksums_valid(p)
5577 except:
5578 self.logger.error(ppp("Unexpected or invalid packet:", p))
5579 raise
5580
5581 # from service VRF1 back to client VRF0
5582 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
5583 IP(src=self.pg5.remote_ip4, dst=self.pg0.remote_ip4) /
5584 TCP(sport=local_port, dport=12347))
5585 self.pg5.add_stream(p)
5586 self.pg_enable_capture(self.pg_interfaces)
5587 self.pg_start()
5588 capture = self.pg0.get_capture(1)
5589 p = capture[0]
5590 try:
5591 ip = p[IP]
5592 tcp = p[TCP]
5593 self.assertEqual(ip.src, external_addr)
5594 self.assertEqual(tcp.sport, external_port)
5595 self.assert_packet_checksums_valid(p)
5596 except:
5597 self.logger.error(ppp("Unexpected or invalid packet:", p))
5598 raise
5599
5600 # from client to server (both VRF1, no translation)
5601 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
5602 IP(src=self.pg6.remote_ip4, dst=self.pg5.remote_ip4) /
5603 TCP(sport=12348, dport=local_port))
5604 self.pg6.add_stream(p)
5605 self.pg_enable_capture(self.pg_interfaces)
5606 self.pg_start()
5607 capture = self.pg5.get_capture(1)
5608 p = capture[0]
5609 try:
5610 ip = p[IP]
5611 tcp = p[TCP]
5612 self.assertEqual(ip.dst, self.pg5.remote_ip4)
5613 self.assertEqual(tcp.dport, local_port)
5614 self.assert_packet_checksums_valid(p)
5615 except:
5616 self.logger.error(ppp("Unexpected or invalid packet:", p))
5617 raise
5618
5619 # from server back to client (both VRF1, no translation)
5620 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
5621 IP(src=self.pg5.remote_ip4, dst=self.pg6.remote_ip4) /
5622 TCP(sport=local_port, dport=12348))
5623 self.pg5.add_stream(p)
5624 self.pg_enable_capture(self.pg_interfaces)
5625 self.pg_start()
5626 capture = self.pg6.get_capture(1)
5627 p = capture[0]
5628 try:
5629 ip = p[IP]
5630 tcp = p[TCP]
5631 self.assertEqual(ip.src, self.pg5.remote_ip4)
5632 self.assertEqual(tcp.sport, local_port)
5633 self.assert_packet_checksums_valid(p)
5634 except:
5635 self.logger.error(ppp("Unexpected or invalid packet:", p))
5636 raise
5637
5638 # from client VRF1 to server VRF0 (no translation)
5639 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5640 IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
5641 TCP(sport=local_port, dport=12349))
5642 self.pg0.add_stream(p)
5643 self.pg_enable_capture(self.pg_interfaces)
5644 self.pg_start()
5645 capture = self.pg6.get_capture(1)
5646 p = capture[0]
5647 try:
5648 ip = p[IP]
5649 tcp = p[TCP]
5650 self.assertEqual(ip.src, self.pg0.remote_ip4)
5651 self.assertEqual(tcp.sport, local_port)
5652 self.assert_packet_checksums_valid(p)
5653 except:
5654 self.logger.error(ppp("Unexpected or invalid packet:", p))
5655 raise
5656
5657 # from server VRF0 back to client VRF1 (no translation)
5658 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5659 IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
5660 TCP(sport=local_port, dport=12349))
5661 self.pg0.add_stream(p)
5662 self.pg_enable_capture(self.pg_interfaces)
5663 self.pg_start()
5664 capture = self.pg6.get_capture(1)
5665 p = capture[0]
5666 try:
5667 ip = p[IP]
5668 tcp = p[TCP]
5669 self.assertEqual(ip.src, self.pg0.remote_ip4)
5670 self.assertEqual(tcp.sport, local_port)
5671 self.assert_packet_checksums_valid(p)
5672 except:
5673 self.logger.error(ppp("Unexpected or invalid packet:", p))
5674 raise
5675
5676 # from client VRF0 to server VRF1 (no translation)
5677 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5678 IP(src=self.pg0.remote_ip4, dst=self.pg5.remote_ip4) /
5679 TCP(sport=12344, dport=local_port))
5680 self.pg0.add_stream(p)
5681 self.pg_enable_capture(self.pg_interfaces)
5682 self.pg_start()
5683 capture = self.pg5.get_capture(1)
5684 p = capture[0]
5685 try:
5686 ip = p[IP]
5687 tcp = p[TCP]
5688 self.assertEqual(ip.dst, self.pg5.remote_ip4)
5689 self.assertEqual(tcp.dport, local_port)
5690 self.assert_packet_checksums_valid(p)
5691 except:
5692 self.logger.error(ppp("Unexpected or invalid packet:", p))
5693 raise
5694
5695 # from server VRF1 back to client VRF0 (no translation)
5696 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
5697 IP(src=self.pg5.remote_ip4, dst=self.pg0.remote_ip4) /
5698 TCP(sport=local_port, dport=12344))
5699 self.pg5.add_stream(p)
5700 self.pg_enable_capture(self.pg_interfaces)
5701 self.pg_start()
5702 capture = self.pg0.get_capture(1)
5703 p = capture[0]
5704 try:
5705 ip = p[IP]
5706 tcp = p[TCP]
5707 self.assertEqual(ip.src, self.pg5.remote_ip4)
5708 self.assertEqual(tcp.sport, local_port)
5709 self.assert_packet_checksums_valid(p)
5710 except:
5711 self.logger.error(ppp("Unexpected or invalid packet:", p))
5712 raise
5713
Matus Fabian878c6462018-08-23 00:33:35 -07005714 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
5715 def test_session_timeout(self):
5716 """ NAT44 session timeouts """
5717 self.nat44_add_address(self.nat_addr)
5718 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5719 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
5720 is_inside=0)
5721 self.vapi.nat_set_timeouts(icmp=5)
5722
5723 max_sessions = 1000
5724 pkts = []
5725 for i in range(0, max_sessions):
5726 src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
5727 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5728 IP(src=src, dst=self.pg1.remote_ip4) /
5729 ICMP(id=1025, type='echo-request'))
5730 pkts.append(p)
5731 self.pg0.add_stream(pkts)
5732 self.pg_enable_capture(self.pg_interfaces)
5733 self.pg_start()
5734 self.pg1.get_capture(max_sessions)
5735
5736 sleep(10)
5737
5738 pkts = []
5739 for i in range(0, max_sessions):
Matus Fabian7f8a8db2018-11-22 00:12:15 -08005740 src = "10.11.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
Matus Fabian878c6462018-08-23 00:33:35 -07005741 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5742 IP(src=src, dst=self.pg1.remote_ip4) /
5743 ICMP(id=1026, type='echo-request'))
5744 pkts.append(p)
5745 self.pg0.add_stream(pkts)
5746 self.pg_enable_capture(self.pg_interfaces)
5747 self.pg_start()
5748 self.pg1.get_capture(max_sessions)
5749
5750 nsessions = 0
5751 users = self.vapi.nat44_user_dump()
5752 for user in users:
5753 nsessions = nsessions + user.nsessions
5754 self.assertLess(nsessions, 2 * max_sessions)
5755
5756 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
Matus Fabian15e8e682018-11-21 04:53:10 -08005757 def test_session_rst_timeout(self):
5758 """ NAT44 session RST timeouts """
5759 self.nat44_add_address(self.nat_addr)
5760 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5761 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
5762 is_inside=0)
5763 self.vapi.nat_set_timeouts(tcp_transitory=5)
5764
Matus Fabian15e8e682018-11-21 04:53:10 -08005765 self.initiate_tcp_session(self.pg0, self.pg1)
5766 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5767 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5768 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
5769 flags="R"))
5770 self.pg0.add_stream(p)
5771 self.pg_enable_capture(self.pg_interfaces)
5772 self.pg_start()
5773 self.pg1.get_capture(1)
5774
Matus Fabian15e8e682018-11-21 04:53:10 -08005775 sleep(6)
5776
5777 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5778 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5779 TCP(sport=self.tcp_port_in + 1, dport=self.tcp_external_port + 1,
5780 flags="S"))
5781 self.pg0.add_stream(p)
5782 self.pg_enable_capture(self.pg_interfaces)
5783 self.pg_start()
5784 self.pg1.get_capture(1)
5785
5786 nsessions = 0
5787 users = self.vapi.nat44_user_dump()
5788 self.assertEqual(len(users), 1)
5789 self.assertEqual(users[0].ip_address, self.pg0.remote_ip4n)
Matus Fabian7f8a8db2018-11-22 00:12:15 -08005790 self.assertEqual(users[0].nsessions, 1)
Matus Fabian15e8e682018-11-21 04:53:10 -08005791
5792 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
Matus Fabian878c6462018-08-23 00:33:35 -07005793 def test_session_limit_per_user(self):
5794 """ Maximum sessions per user limit """
5795 self.nat44_add_address(self.nat_addr)
5796 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5797 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
5798 is_inside=0)
5799 self.vapi.set_ipfix_exporter(collector_address=self.pg2.remote_ip4n,
5800 src_address=self.pg2.local_ip4n,
5801 path_mtu=512,
5802 template_interval=10)
Matus Fabian8fdc0152018-09-24 04:41:28 -07005803 self.vapi.nat_set_timeouts(udp=5)
Matus Fabian878c6462018-08-23 00:33:35 -07005804
5805 # get maximum number of translations per user
5806 nat44_config = self.vapi.nat_show_config()
5807
5808 pkts = []
5809 for port in range(0, nat44_config.max_translations_per_user):
5810 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5811 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5812 UDP(sport=1025 + port, dport=1025 + port))
5813 pkts.append(p)
5814
5815 self.pg0.add_stream(pkts)
5816 self.pg_enable_capture(self.pg_interfaces)
5817 self.pg_start()
5818 capture = self.pg1.get_capture(len(pkts))
5819
5820 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
5821 src_port=self.ipfix_src_port)
5822
5823 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5824 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5825 UDP(sport=3001, dport=3002))
5826 self.pg0.add_stream(p)
5827 self.pg_enable_capture(self.pg_interfaces)
5828 self.pg_start()
5829 capture = self.pg1.assert_nothing_captured()
5830
5831 # verify IPFIX logging
5832 self.vapi.cli("ipfix flush") # FIXME this should be an API call
5833 sleep(1)
5834 capture = self.pg2.get_capture(10)
5835 ipfix = IPFIXDecoder()
5836 # first load template
5837 for p in capture:
5838 self.assertTrue(p.haslayer(IPFIX))
5839 if p.haslayer(Template):
5840 ipfix.add_template(p.getlayer(Template))
5841 # verify events in data set
5842 for p in capture:
5843 if p.haslayer(Data):
5844 data = ipfix.decode_data_set(p.getlayer(Set))
5845 self.verify_ipfix_max_entries_per_user(
5846 data,
5847 nat44_config.max_translations_per_user,
5848 self.pg0.remote_ip4n)
5849
Matus Fabian8fdc0152018-09-24 04:41:28 -07005850 sleep(6)
5851 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5852 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5853 UDP(sport=3001, dport=3002))
5854 self.pg0.add_stream(p)
5855 self.pg_enable_capture(self.pg_interfaces)
5856 self.pg_start()
5857 self.pg1.get_capture(1)
5858
Matus Fabianad1f3e12018-11-28 21:26:34 -08005859 def test_syslog_sess(self):
5860 """ Test syslog session creation and deletion """
5861 self.vapi.syslog_set_filter(SYSLOG_SEVERITY.INFO)
5862 self.vapi.syslog_set_sender(self.pg2.remote_ip4n, self.pg2.local_ip4n)
5863 self.nat44_add_address(self.nat_addr)
5864 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5865 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
5866 is_inside=0)
5867
5868 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5869 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5870 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port))
5871 self.pg0.add_stream(p)
5872 self.pg_enable_capture(self.pg_interfaces)
5873 self.pg_start()
5874 capture = self.pg1.get_capture(1)
5875 self.tcp_port_out = capture[0][TCP].sport
5876 capture = self.pg2.get_capture(1)
5877 self.verify_syslog_sess(capture[0][Raw].load)
5878
5879 self.pg_enable_capture(self.pg_interfaces)
5880 self.pg_start()
5881 self.nat44_add_address(self.nat_addr, is_add=0)
5882 capture = self.pg2.get_capture(1)
5883 self.verify_syslog_sess(capture[0][Raw].load, False)
5884
Matus Fabiande886752016-12-07 03:38:19 -08005885 def tearDown(self):
Matus Fabiana6110b62018-06-13 05:39:07 -07005886 super(TestNAT44EndpointDependent, self).tearDown()
Matus Fabiande886752016-12-07 03:38:19 -08005887 if not self.vpp_dead:
Matus Fabian82119542018-01-25 01:13:22 -08005888 self.logger.info(self.vapi.cli("show nat44 addresses"))
5889 self.logger.info(self.vapi.cli("show nat44 interfaces"))
5890 self.logger.info(self.vapi.cli("show nat44 static mappings"))
5891 self.logger.info(self.vapi.cli("show nat44 interface address"))
5892 self.logger.info(self.vapi.cli("show nat44 sessions detail"))
Matus Fabian229c1aa2018-05-28 04:09:52 -07005893 self.logger.info(self.vapi.cli("show nat44 hash tables detail"))
Matus Fabian878c6462018-08-23 00:33:35 -07005894 self.logger.info(self.vapi.cli("show nat timeouts"))
Matus Fabian2ba92e32017-08-21 07:05:03 -07005895 self.clear_nat44()
Matus Fabian229c1aa2018-05-28 04:09:52 -07005896 self.vapi.cli("clear logging")
Matus Fabiande886752016-12-07 03:38:19 -08005897
Matus Fabianeea28d72017-01-13 04:15:54 -08005898
Juraj Slobodacba69362017-12-19 02:09:32 +01005899class TestNAT44Out2InDPO(MethodHolder):
5900 """ NAT44 Test Cases using out2in DPO """
5901
5902 @classmethod
5903 def setUpConstants(cls):
5904 super(TestNAT44Out2InDPO, cls).setUpConstants()
5905 cls.vpp_cmdline.extend(["nat", "{", "out2in dpo", "}"])
5906
5907 @classmethod
5908 def setUpClass(cls):
5909 super(TestNAT44Out2InDPO, cls).setUpClass()
Matus Fabian229c1aa2018-05-28 04:09:52 -07005910 cls.vapi.cli("set log class nat level debug")
Juraj Slobodacba69362017-12-19 02:09:32 +01005911
5912 try:
5913 cls.tcp_port_in = 6303
5914 cls.tcp_port_out = 6303
5915 cls.udp_port_in = 6304
5916 cls.udp_port_out = 6304
5917 cls.icmp_id_in = 6305
5918 cls.icmp_id_out = 6305
5919 cls.nat_addr = '10.0.0.3'
5920 cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
5921 cls.dst_ip4 = '192.168.70.1'
5922
5923 cls.create_pg_interfaces(range(2))
5924
5925 cls.pg0.admin_up()
5926 cls.pg0.config_ip4()
5927 cls.pg0.resolve_arp()
5928
5929 cls.pg1.admin_up()
5930 cls.pg1.config_ip6()
5931 cls.pg1.resolve_ndp()
5932
5933 cls.vapi.ip_add_del_route(is_ipv6=True, dst_address='\x00'*16,
5934 dst_address_length=0,
5935 next_hop_address=cls.pg1.remote_ip6n,
5936 next_hop_sw_if_index=cls.pg1.sw_if_index)
5937
5938 except Exception:
5939 super(TestNAT44Out2InDPO, cls).tearDownClass()
5940 raise
5941
5942 def configure_xlat(self):
5943 self.dst_ip6_pfx = '1:2:3::'
5944 self.dst_ip6_pfx_n = socket.inet_pton(socket.AF_INET6,
5945 self.dst_ip6_pfx)
5946 self.dst_ip6_pfx_len = 96
5947 self.src_ip6_pfx = '4:5:6::'
5948 self.src_ip6_pfx_n = socket.inet_pton(socket.AF_INET6,
5949 self.src_ip6_pfx)
5950 self.src_ip6_pfx_len = 96
5951 self.vapi.map_add_domain(self.dst_ip6_pfx_n, self.dst_ip6_pfx_len,
5952 self.src_ip6_pfx_n, self.src_ip6_pfx_len,
5953 '\x00\x00\x00\x00', 0, is_translation=1,
5954 is_rfc6052=1)
5955
Ole Troanffba3c32018-11-22 12:53:00 +01005956 @unittest.skip('Temporary disabled')
Juraj Slobodacba69362017-12-19 02:09:32 +01005957 def test_464xlat_ce(self):
5958 """ Test 464XLAT CE with NAT44 """
5959
Matus Fabian69ce30d2018-08-22 01:27:10 -07005960 nat_config = self.vapi.nat_show_config()
5961 self.assertEqual(1, nat_config.out2in_dpo)
5962
Juraj Slobodacba69362017-12-19 02:09:32 +01005963 self.configure_xlat()
5964
5965 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5966 self.vapi.nat44_add_del_address_range(self.nat_addr_n, self.nat_addr_n)
5967
5968 out_src_ip6 = self.compose_ip6(self.dst_ip4, self.dst_ip6_pfx,
5969 self.dst_ip6_pfx_len)
5970 out_dst_ip6 = self.compose_ip6(self.nat_addr, self.src_ip6_pfx,
5971 self.src_ip6_pfx_len)
5972
5973 try:
5974 pkts = self.create_stream_in(self.pg0, self.pg1, self.dst_ip4)
5975 self.pg0.add_stream(pkts)
5976 self.pg_enable_capture(self.pg_interfaces)
5977 self.pg_start()
5978 capture = self.pg1.get_capture(len(pkts))
5979 self.verify_capture_out_ip6(capture, nat_ip=out_dst_ip6,
5980 dst_ip=out_src_ip6)
5981
5982 pkts = self.create_stream_out_ip6(self.pg1, out_src_ip6,
5983 out_dst_ip6)
5984 self.pg1.add_stream(pkts)
5985 self.pg_enable_capture(self.pg_interfaces)
5986 self.pg_start()
5987 capture = self.pg0.get_capture(len(pkts))
5988 self.verify_capture_in(capture, self.pg0)
5989 finally:
5990 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
5991 is_add=0)
5992 self.vapi.nat44_add_del_address_range(self.nat_addr_n,
5993 self.nat_addr_n, is_add=0)
5994
Ole Troanffba3c32018-11-22 12:53:00 +01005995 @unittest.skip('Temporary disabled')
Juraj Slobodacba69362017-12-19 02:09:32 +01005996 def test_464xlat_ce_no_nat(self):
5997 """ Test 464XLAT CE without NAT44 """
5998
5999 self.configure_xlat()
6000
6001 out_src_ip6 = self.compose_ip6(self.dst_ip4, self.dst_ip6_pfx,
6002 self.dst_ip6_pfx_len)
6003 out_dst_ip6 = self.compose_ip6(self.pg0.remote_ip4, self.src_ip6_pfx,
6004 self.src_ip6_pfx_len)
6005
6006 pkts = self.create_stream_in(self.pg0, self.pg1, self.dst_ip4)
6007 self.pg0.add_stream(pkts)
6008 self.pg_enable_capture(self.pg_interfaces)
6009 self.pg_start()
6010 capture = self.pg1.get_capture(len(pkts))
6011 self.verify_capture_out_ip6(capture, dst_ip=out_src_ip6,
6012 nat_ip=out_dst_ip6, same_port=True)
6013
6014 pkts = self.create_stream_out_ip6(self.pg1, out_src_ip6, out_dst_ip6)
6015 self.pg1.add_stream(pkts)
6016 self.pg_enable_capture(self.pg_interfaces)
6017 self.pg_start()
6018 capture = self.pg0.get_capture(len(pkts))
6019 self.verify_capture_in(capture, self.pg0)
6020
6021
Martin Gálikd7f75cd2017-03-27 06:02:47 -07006022class TestDeterministicNAT(MethodHolder):
Matus Fabian066f0342017-02-10 03:48:01 -08006023 """ Deterministic NAT Test Cases """
6024
6025 @classmethod
6026 def setUpConstants(cls):
6027 super(TestDeterministicNAT, cls).setUpConstants()
Matus Fabian2ba92e32017-08-21 07:05:03 -07006028 cls.vpp_cmdline.extend(["nat", "{", "deterministic", "}"])
Matus Fabian066f0342017-02-10 03:48:01 -08006029
6030 @classmethod
6031 def setUpClass(cls):
6032 super(TestDeterministicNAT, cls).setUpClass()
Matus Fabian229c1aa2018-05-28 04:09:52 -07006033 cls.vapi.cli("set log class nat level debug")
Matus Fabian066f0342017-02-10 03:48:01 -08006034
6035 try:
Martin Gálik977c1cb2017-03-30 23:21:51 -07006036 cls.tcp_port_in = 6303
Martin Gálik9806eae2017-04-25 01:25:08 -07006037 cls.tcp_external_port = 6303
Martin Gálik977c1cb2017-03-30 23:21:51 -07006038 cls.udp_port_in = 6304
Martin Gálik9806eae2017-04-25 01:25:08 -07006039 cls.udp_external_port = 6304
Martin Gálik977c1cb2017-03-30 23:21:51 -07006040 cls.icmp_id_in = 6305
Matus Fabian2ba92e32017-08-21 07:05:03 -07006041 cls.nat_addr = '10.0.0.3'
Martin Gálik977c1cb2017-03-30 23:21:51 -07006042
Matus Fabian2f2db1c2017-04-18 05:29:59 -07006043 cls.create_pg_interfaces(range(3))
Matus Fabian066f0342017-02-10 03:48:01 -08006044 cls.interfaces = list(cls.pg_interfaces)
6045
6046 for i in cls.interfaces:
6047 i.admin_up()
6048 i.config_ip4()
6049 i.resolve_arp()
6050
Martin Gálik977c1cb2017-03-30 23:21:51 -07006051 cls.pg0.generate_remote_hosts(2)
6052 cls.pg0.configure_ipv4_neighbors()
6053
Matus Fabian066f0342017-02-10 03:48:01 -08006054 except Exception:
6055 super(TestDeterministicNAT, cls).tearDownClass()
6056 raise
6057
Martin Gálik977c1cb2017-03-30 23:21:51 -07006058 def create_stream_in(self, in_if, out_if, ttl=64):
6059 """
6060 Create packet stream for inside network
6061
6062 :param in_if: Inside interface
6063 :param out_if: Outside interface
6064 :param ttl: TTL of generated packets
6065 """
6066 pkts = []
6067 # TCP
6068 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
6069 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006070 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07006071 pkts.append(p)
6072
6073 # UDP
6074 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
6075 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006076 UDP(sport=self.udp_port_in, dport=self.udp_external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07006077 pkts.append(p)
6078
6079 # ICMP
6080 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
6081 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
6082 ICMP(id=self.icmp_id_in, type='echo-request'))
6083 pkts.append(p)
6084
6085 return pkts
6086
6087 def create_stream_out(self, out_if, dst_ip=None, ttl=64):
6088 """
6089 Create packet stream for outside network
6090
6091 :param out_if: Outside interface
Matus Fabian2ba92e32017-08-21 07:05:03 -07006092 :param dst_ip: Destination IP address (Default use global NAT address)
Martin Gálik977c1cb2017-03-30 23:21:51 -07006093 :param ttl: TTL of generated packets
6094 """
6095 if dst_ip is None:
Matus Fabian2ba92e32017-08-21 07:05:03 -07006096 dst_ip = self.nat_addr
Martin Gálik977c1cb2017-03-30 23:21:51 -07006097 pkts = []
6098 # TCP
6099 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
6100 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006101 TCP(dport=self.tcp_port_out, sport=self.tcp_external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07006102 pkts.append(p)
6103
6104 # UDP
6105 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
6106 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006107 UDP(dport=self.udp_port_out, sport=self.udp_external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07006108 pkts.append(p)
6109
6110 # ICMP
6111 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
6112 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
6113 ICMP(id=self.icmp_external_id, type='echo-reply'))
6114 pkts.append(p)
6115
6116 return pkts
6117
Matus Fabian05ca4a32018-09-04 23:45:13 -07006118 def verify_capture_out(self, capture, nat_ip=None):
Martin Gálik977c1cb2017-03-30 23:21:51 -07006119 """
6120 Verify captured packets on outside network
6121
6122 :param capture: Captured packets
Matus Fabian2ba92e32017-08-21 07:05:03 -07006123 :param nat_ip: Translated IP address (Default use global NAT address)
Martin Gálik977c1cb2017-03-30 23:21:51 -07006124 :param same_port: Sorce port number is not translated (Default False)
Martin Gálik977c1cb2017-03-30 23:21:51 -07006125 """
6126 if nat_ip is None:
Matus Fabian2ba92e32017-08-21 07:05:03 -07006127 nat_ip = self.nat_addr
Martin Gálik977c1cb2017-03-30 23:21:51 -07006128 for packet in capture:
6129 try:
6130 self.assertEqual(packet[IP].src, nat_ip)
6131 if packet.haslayer(TCP):
Martin Gálik9806eae2017-04-25 01:25:08 -07006132 self.tcp_port_out = packet[TCP].sport
Martin Gálik977c1cb2017-03-30 23:21:51 -07006133 elif packet.haslayer(UDP):
Martin Gálik9806eae2017-04-25 01:25:08 -07006134 self.udp_port_out = packet[UDP].sport
Martin Gálik977c1cb2017-03-30 23:21:51 -07006135 else:
6136 self.icmp_external_id = packet[ICMP].id
6137 except:
6138 self.logger.error(ppp("Unexpected or invalid packet "
6139 "(outside network):", packet))
6140 raise
6141
Matus Fabian066f0342017-02-10 03:48:01 -08006142 def test_deterministic_mode(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07006143 """ NAT plugin run deterministic mode """
Matus Fabian066f0342017-02-10 03:48:01 -08006144 in_addr = '172.16.255.0'
6145 out_addr = '172.17.255.50'
6146 in_addr_t = '172.16.255.20'
6147 in_addr_n = socket.inet_aton(in_addr)
6148 out_addr_n = socket.inet_aton(out_addr)
6149 in_addr_t_n = socket.inet_aton(in_addr_t)
6150 in_plen = 24
6151 out_plen = 32
6152
Matus Fabian2ba92e32017-08-21 07:05:03 -07006153 nat_config = self.vapi.nat_show_config()
6154 self.assertEqual(1, nat_config.deterministic)
Matus Fabian066f0342017-02-10 03:48:01 -08006155
Matus Fabian2ba92e32017-08-21 07:05:03 -07006156 self.vapi.nat_det_add_del_map(in_addr_n, in_plen, out_addr_n, out_plen)
Matus Fabian066f0342017-02-10 03:48:01 -08006157
Matus Fabian2ba92e32017-08-21 07:05:03 -07006158 rep1 = self.vapi.nat_det_forward(in_addr_t_n)
Matus Fabian066f0342017-02-10 03:48:01 -08006159 self.assertEqual(rep1.out_addr[:4], out_addr_n)
Matus Fabian2ba92e32017-08-21 07:05:03 -07006160 rep2 = self.vapi.nat_det_reverse(out_addr_n, rep1.out_port_hi)
Matus Fabian066f0342017-02-10 03:48:01 -08006161 self.assertEqual(rep2.in_addr[:4], in_addr_t_n)
6162
Matus Fabian2ba92e32017-08-21 07:05:03 -07006163 deterministic_mappings = self.vapi.nat_det_map_dump()
Martin17a75cb2017-03-08 05:53:20 -08006164 self.assertEqual(len(deterministic_mappings), 1)
6165 dsm = deterministic_mappings[0]
6166 self.assertEqual(in_addr_n, dsm.in_addr[:4])
6167 self.assertEqual(in_plen, dsm.in_plen)
6168 self.assertEqual(out_addr_n, dsm.out_addr[:4])
6169 self.assertEqual(out_plen, dsm.out_plen)
6170
Matus Fabian2ba92e32017-08-21 07:05:03 -07006171 self.clear_nat_det()
6172 deterministic_mappings = self.vapi.nat_det_map_dump()
Martinb616e9f2017-03-14 02:25:45 -07006173 self.assertEqual(len(deterministic_mappings), 0)
6174
Matus Fabian6a0946f2017-04-12 03:36:13 -07006175 def test_set_timeouts(self):
6176 """ Set deterministic NAT timeouts """
Matus Fabian878c6462018-08-23 00:33:35 -07006177 timeouts_before = self.vapi.nat_get_timeouts()
Matus Fabian6a0946f2017-04-12 03:36:13 -07006178
Matus Fabian878c6462018-08-23 00:33:35 -07006179 self.vapi.nat_set_timeouts(timeouts_before.udp + 10,
6180 timeouts_before.tcp_established + 10,
6181 timeouts_before.tcp_transitory + 10,
6182 timeouts_before.icmp + 10)
Matus Fabian6a0946f2017-04-12 03:36:13 -07006183
Matus Fabian878c6462018-08-23 00:33:35 -07006184 timeouts_after = self.vapi.nat_get_timeouts()
Matus Fabian6a0946f2017-04-12 03:36:13 -07006185
6186 self.assertNotEqual(timeouts_before.udp, timeouts_after.udp)
6187 self.assertNotEqual(timeouts_before.icmp, timeouts_after.icmp)
6188 self.assertNotEqual(timeouts_before.tcp_established,
6189 timeouts_after.tcp_established)
6190 self.assertNotEqual(timeouts_before.tcp_transitory,
6191 timeouts_after.tcp_transitory)
6192
Martin Gálik977c1cb2017-03-30 23:21:51 -07006193 def test_det_in(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07006194 """ Deterministic NAT translation test (TCP, UDP, ICMP) """
Martin Gálik977c1cb2017-03-30 23:21:51 -07006195
6196 nat_ip = "10.0.0.10"
Martin Gálik977c1cb2017-03-30 23:21:51 -07006197
Matus Fabian2ba92e32017-08-21 07:05:03 -07006198 self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
6199 32,
6200 socket.inet_aton(nat_ip),
6201 32)
6202 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
6203 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
6204 is_inside=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07006205
6206 # in2out
6207 pkts = self.create_stream_in(self.pg0, self.pg1)
6208 self.pg0.add_stream(pkts)
6209 self.pg_enable_capture(self.pg_interfaces)
6210 self.pg_start()
6211 capture = self.pg1.get_capture(len(pkts))
6212 self.verify_capture_out(capture, nat_ip)
6213
6214 # out2in
6215 pkts = self.create_stream_out(self.pg1, nat_ip)
6216 self.pg1.add_stream(pkts)
6217 self.pg_enable_capture(self.pg_interfaces)
6218 self.pg_start()
6219 capture = self.pg0.get_capture(len(pkts))
6220 self.verify_capture_in(capture, self.pg0)
6221
Martin Gálik9806eae2017-04-25 01:25:08 -07006222 # session dump test
Matus Fabian2ba92e32017-08-21 07:05:03 -07006223 sessions = self.vapi.nat_det_session_dump(self.pg0.remote_ip4n)
Martin Gálik9806eae2017-04-25 01:25:08 -07006224 self.assertEqual(len(sessions), 3)
6225
6226 # TCP session
6227 s = sessions[0]
6228 self.assertEqual(s.ext_addr[:4], self.pg1.remote_ip4n)
6229 self.assertEqual(s.in_port, self.tcp_port_in)
6230 self.assertEqual(s.out_port, self.tcp_port_out)
6231 self.assertEqual(s.ext_port, self.tcp_external_port)
6232
6233 # UDP session
6234 s = sessions[1]
6235 self.assertEqual(s.ext_addr[:4], self.pg1.remote_ip4n)
6236 self.assertEqual(s.in_port, self.udp_port_in)
6237 self.assertEqual(s.out_port, self.udp_port_out)
6238 self.assertEqual(s.ext_port, self.udp_external_port)
6239
6240 # ICMP session
6241 s = sessions[2]
6242 self.assertEqual(s.ext_addr[:4], self.pg1.remote_ip4n)
6243 self.assertEqual(s.in_port, self.icmp_id_in)
6244 self.assertEqual(s.out_port, self.icmp_external_id)
6245
Martin Gálik977c1cb2017-03-30 23:21:51 -07006246 def test_multiple_users(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07006247 """ Deterministic NAT multiple users """
Martin Gálik977c1cb2017-03-30 23:21:51 -07006248
6249 nat_ip = "10.0.0.10"
6250 port_in = 80
Martin Gálik9806eae2017-04-25 01:25:08 -07006251 external_port = 6303
Martin Gálik977c1cb2017-03-30 23:21:51 -07006252
6253 host0 = self.pg0.remote_hosts[0]
6254 host1 = self.pg0.remote_hosts[1]
6255
Matus Fabian2ba92e32017-08-21 07:05:03 -07006256 self.vapi.nat_det_add_del_map(host0.ip4n,
6257 24,
6258 socket.inet_aton(nat_ip),
6259 32)
6260 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
6261 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
6262 is_inside=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07006263
6264 # host0 to out
6265 p = (Ether(src=host0.mac, dst=self.pg0.local_mac) /
6266 IP(src=host0.ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006267 TCP(sport=port_in, dport=external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07006268 self.pg0.add_stream(p)
6269 self.pg_enable_capture(self.pg_interfaces)
6270 self.pg_start()
6271 capture = self.pg1.get_capture(1)
6272 p = capture[0]
6273 try:
6274 ip = p[IP]
6275 tcp = p[TCP]
6276 self.assertEqual(ip.src, nat_ip)
6277 self.assertEqual(ip.dst, self.pg1.remote_ip4)
Martin Gálik9806eae2017-04-25 01:25:08 -07006278 self.assertEqual(tcp.dport, external_port)
6279 port_out0 = tcp.sport
Martin Gálik977c1cb2017-03-30 23:21:51 -07006280 except:
6281 self.logger.error(ppp("Unexpected or invalid packet:", p))
6282 raise
6283
6284 # host1 to out
6285 p = (Ether(src=host1.mac, dst=self.pg0.local_mac) /
6286 IP(src=host1.ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006287 TCP(sport=port_in, dport=external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07006288 self.pg0.add_stream(p)
6289 self.pg_enable_capture(self.pg_interfaces)
6290 self.pg_start()
6291 capture = self.pg1.get_capture(1)
6292 p = capture[0]
6293 try:
6294 ip = p[IP]
6295 tcp = p[TCP]
6296 self.assertEqual(ip.src, nat_ip)
6297 self.assertEqual(ip.dst, self.pg1.remote_ip4)
Martin Gálik9806eae2017-04-25 01:25:08 -07006298 self.assertEqual(tcp.dport, external_port)
6299 port_out1 = tcp.sport
Martin Gálik977c1cb2017-03-30 23:21:51 -07006300 except:
6301 self.logger.error(ppp("Unexpected or invalid packet:", p))
6302 raise
6303
Matus Fabian2ba92e32017-08-21 07:05:03 -07006304 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07006305 self.assertEqual(1, len(dms))
6306 self.assertEqual(2, dms[0].ses_num)
6307
6308 # out to host0
6309 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6310 IP(src=self.pg1.remote_ip4, dst=nat_ip) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006311 TCP(sport=external_port, dport=port_out0))
Martin Gálik977c1cb2017-03-30 23:21:51 -07006312 self.pg1.add_stream(p)
6313 self.pg_enable_capture(self.pg_interfaces)
6314 self.pg_start()
6315 capture = self.pg0.get_capture(1)
6316 p = capture[0]
6317 try:
6318 ip = p[IP]
6319 tcp = p[TCP]
6320 self.assertEqual(ip.src, self.pg1.remote_ip4)
6321 self.assertEqual(ip.dst, host0.ip4)
6322 self.assertEqual(tcp.dport, port_in)
Martin Gálik9806eae2017-04-25 01:25:08 -07006323 self.assertEqual(tcp.sport, external_port)
Martin Gálik977c1cb2017-03-30 23:21:51 -07006324 except:
6325 self.logger.error(ppp("Unexpected or invalid packet:", p))
6326 raise
6327
6328 # out to host1
6329 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6330 IP(src=self.pg1.remote_ip4, dst=nat_ip) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006331 TCP(sport=external_port, dport=port_out1))
Martin Gálik977c1cb2017-03-30 23:21:51 -07006332 self.pg1.add_stream(p)
6333 self.pg_enable_capture(self.pg_interfaces)
6334 self.pg_start()
6335 capture = self.pg0.get_capture(1)
6336 p = capture[0]
6337 try:
6338 ip = p[IP]
6339 tcp = p[TCP]
6340 self.assertEqual(ip.src, self.pg1.remote_ip4)
6341 self.assertEqual(ip.dst, host1.ip4)
6342 self.assertEqual(tcp.dport, port_in)
Martin Gálik9806eae2017-04-25 01:25:08 -07006343 self.assertEqual(tcp.sport, external_port)
Martin Gálik977c1cb2017-03-30 23:21:51 -07006344 except:
6345 self.logger.error(ppp("Unexpected or invalid packet", p))
6346 raise
6347
Martin Gálik6bc8c642017-04-19 01:12:27 -07006348 # session close api test
Matus Fabian2ba92e32017-08-21 07:05:03 -07006349 self.vapi.nat_det_close_session_out(socket.inet_aton(nat_ip),
6350 port_out1,
Martin Gálik6bc8c642017-04-19 01:12:27 -07006351 self.pg1.remote_ip4n,
Martin Gálik9806eae2017-04-25 01:25:08 -07006352 external_port)
Matus Fabian2ba92e32017-08-21 07:05:03 -07006353 dms = self.vapi.nat_det_map_dump()
6354 self.assertEqual(dms[0].ses_num, 1)
6355
6356 self.vapi.nat_det_close_session_in(host0.ip4n,
6357 port_in,
6358 self.pg1.remote_ip4n,
6359 external_port)
6360 dms = self.vapi.nat_det_map_dump()
Martin Gálik6bc8c642017-04-19 01:12:27 -07006361 self.assertEqual(dms[0].ses_num, 0)
6362
Martin Gálik977c1cb2017-03-30 23:21:51 -07006363 def test_tcp_session_close_detection_in(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07006364 """ Deterministic NAT TCP session close from inside network """
6365 self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
6366 32,
6367 socket.inet_aton(self.nat_addr),
6368 32)
6369 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
6370 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
6371 is_inside=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07006372
6373 self.initiate_tcp_session(self.pg0, self.pg1)
6374
6375 # close the session from inside
6376 try:
6377 # FIN packet in -> out
6378 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6379 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006380 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
Martin Gálik977c1cb2017-03-30 23:21:51 -07006381 flags="F"))
6382 self.pg0.add_stream(p)
6383 self.pg_enable_capture(self.pg_interfaces)
6384 self.pg_start()
6385 self.pg1.get_capture(1)
6386
6387 pkts = []
6388
6389 # ACK packet out -> in
6390 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07006391 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006392 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
Martin Gálik977c1cb2017-03-30 23:21:51 -07006393 flags="A"))
6394 pkts.append(p)
6395
6396 # FIN packet out -> in
6397 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07006398 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006399 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
Martin Gálik977c1cb2017-03-30 23:21:51 -07006400 flags="F"))
6401 pkts.append(p)
6402
6403 self.pg1.add_stream(pkts)
6404 self.pg_enable_capture(self.pg_interfaces)
6405 self.pg_start()
6406 self.pg0.get_capture(2)
6407
6408 # ACK packet in -> out
6409 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6410 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006411 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
Martin Gálik977c1cb2017-03-30 23:21:51 -07006412 flags="A"))
6413 self.pg0.add_stream(p)
6414 self.pg_enable_capture(self.pg_interfaces)
6415 self.pg_start()
6416 self.pg1.get_capture(1)
6417
Matus Fabian2ba92e32017-08-21 07:05:03 -07006418 # Check if deterministic NAT44 closed the session
6419 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07006420 self.assertEqual(0, dms[0].ses_num)
6421 except:
6422 self.logger.error("TCP session termination failed")
6423 raise
6424
6425 def test_tcp_session_close_detection_out(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07006426 """ Deterministic NAT TCP session close from outside network """
6427 self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
6428 32,
6429 socket.inet_aton(self.nat_addr),
6430 32)
6431 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
6432 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
6433 is_inside=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07006434
6435 self.initiate_tcp_session(self.pg0, self.pg1)
6436
6437 # close the session from outside
6438 try:
6439 # FIN packet out -> in
6440 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07006441 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006442 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
Martin Gálik977c1cb2017-03-30 23:21:51 -07006443 flags="F"))
6444 self.pg1.add_stream(p)
6445 self.pg_enable_capture(self.pg_interfaces)
6446 self.pg_start()
6447 self.pg0.get_capture(1)
6448
6449 pkts = []
6450
6451 # ACK packet in -> out
6452 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6453 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006454 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
Martin Gálik977c1cb2017-03-30 23:21:51 -07006455 flags="A"))
6456 pkts.append(p)
6457
6458 # ACK packet in -> out
6459 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6460 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006461 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
Martin Gálik977c1cb2017-03-30 23:21:51 -07006462 flags="F"))
6463 pkts.append(p)
6464
6465 self.pg0.add_stream(pkts)
6466 self.pg_enable_capture(self.pg_interfaces)
6467 self.pg_start()
6468 self.pg1.get_capture(2)
6469
6470 # ACK packet out -> in
6471 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07006472 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006473 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
Martin Gálik977c1cb2017-03-30 23:21:51 -07006474 flags="A"))
6475 self.pg1.add_stream(p)
6476 self.pg_enable_capture(self.pg_interfaces)
6477 self.pg_start()
6478 self.pg0.get_capture(1)
6479
Matus Fabian2ba92e32017-08-21 07:05:03 -07006480 # Check if deterministic NAT44 closed the session
6481 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07006482 self.assertEqual(0, dms[0].ses_num)
6483 except:
6484 self.logger.error("TCP session termination failed")
6485 raise
6486
6487 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
6488 def test_session_timeout(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07006489 """ Deterministic NAT session timeouts """
6490 self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
6491 32,
6492 socket.inet_aton(self.nat_addr),
6493 32)
6494 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
6495 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
6496 is_inside=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07006497
6498 self.initiate_tcp_session(self.pg0, self.pg1)
Matus Fabian878c6462018-08-23 00:33:35 -07006499 self.vapi.nat_set_timeouts(5, 5, 5, 5)
Martin Gálik977c1cb2017-03-30 23:21:51 -07006500 pkts = self.create_stream_in(self.pg0, self.pg1)
6501 self.pg0.add_stream(pkts)
6502 self.pg_enable_capture(self.pg_interfaces)
6503 self.pg_start()
6504 capture = self.pg1.get_capture(len(pkts))
6505 sleep(15)
6506
Matus Fabian2ba92e32017-08-21 07:05:03 -07006507 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07006508 self.assertEqual(0, dms[0].ses_num)
6509
Matus Fabian7c0aecc2017-07-03 01:21:38 -07006510 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
Martin Gálik977c1cb2017-03-30 23:21:51 -07006511 def test_session_limit_per_user(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07006512 """ Deterministic NAT maximum sessions per user limit """
6513 self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
6514 32,
6515 socket.inet_aton(self.nat_addr),
6516 32)
6517 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
6518 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
6519 is_inside=0)
Matus Fabian2f2db1c2017-04-18 05:29:59 -07006520 self.vapi.set_ipfix_exporter(collector_address=self.pg2.remote_ip4n,
6521 src_address=self.pg2.local_ip4n,
6522 path_mtu=512,
6523 template_interval=10)
Matus Fabian2ba92e32017-08-21 07:05:03 -07006524 self.vapi.nat_ipfix()
Martin Gálik977c1cb2017-03-30 23:21:51 -07006525
6526 pkts = []
6527 for port in range(1025, 2025):
6528 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6529 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6530 UDP(sport=port, dport=port))
6531 pkts.append(p)
6532
6533 self.pg0.add_stream(pkts)
6534 self.pg_enable_capture(self.pg_interfaces)
6535 self.pg_start()
6536 capture = self.pg1.get_capture(len(pkts))
6537
6538 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6539 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálikf7e655d2017-04-27 02:13:26 -07006540 UDP(sport=3001, dport=3002))
Martin Gálik977c1cb2017-03-30 23:21:51 -07006541 self.pg0.add_stream(p)
6542 self.pg_enable_capture(self.pg_interfaces)
6543 self.pg_start()
6544 capture = self.pg1.assert_nothing_captured()
6545
Martin Gálikf7e655d2017-04-27 02:13:26 -07006546 # verify ICMP error packet
6547 capture = self.pg0.get_capture(1)
6548 p = capture[0]
6549 self.assertTrue(p.haslayer(ICMP))
6550 icmp = p[ICMP]
6551 self.assertEqual(icmp.type, 3)
6552 self.assertEqual(icmp.code, 1)
6553 self.assertTrue(icmp.haslayer(IPerror))
6554 inner_ip = icmp[IPerror]
6555 self.assertEqual(inner_ip[UDPerror].sport, 3001)
6556 self.assertEqual(inner_ip[UDPerror].dport, 3002)
6557
Matus Fabian2ba92e32017-08-21 07:05:03 -07006558 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07006559
6560 self.assertEqual(1000, dms[0].ses_num)
6561
Matus Fabian2f2db1c2017-04-18 05:29:59 -07006562 # verify IPFIX logging
6563 self.vapi.cli("ipfix flush") # FIXME this should be an API call
Matus Fabian7c0aecc2017-07-03 01:21:38 -07006564 sleep(1)
Matus Fabian2f2db1c2017-04-18 05:29:59 -07006565 capture = self.pg2.get_capture(2)
6566 ipfix = IPFIXDecoder()
6567 # first load template
6568 for p in capture:
6569 self.assertTrue(p.haslayer(IPFIX))
6570 if p.haslayer(Template):
6571 ipfix.add_template(p.getlayer(Template))
6572 # verify events in data set
6573 for p in capture:
6574 if p.haslayer(Data):
6575 data = ipfix.decode_data_set(p.getlayer(Set))
Matus Fabian878c6462018-08-23 00:33:35 -07006576 self.verify_ipfix_max_entries_per_user(data,
6577 1000,
6578 self.pg0.remote_ip4n)
Matus Fabian2f2db1c2017-04-18 05:29:59 -07006579
Matus Fabian2ba92e32017-08-21 07:05:03 -07006580 def clear_nat_det(self):
Martin17a75cb2017-03-08 05:53:20 -08006581 """
Matus Fabian2ba92e32017-08-21 07:05:03 -07006582 Clear deterministic NAT configuration.
Martin17a75cb2017-03-08 05:53:20 -08006583 """
Matus Fabian2ba92e32017-08-21 07:05:03 -07006584 self.vapi.nat_ipfix(enable=0)
Matus Fabian878c6462018-08-23 00:33:35 -07006585 self.vapi.nat_set_timeouts()
Matus Fabian2ba92e32017-08-21 07:05:03 -07006586 deterministic_mappings = self.vapi.nat_det_map_dump()
Martin17a75cb2017-03-08 05:53:20 -08006587 for dsm in deterministic_mappings:
Matus Fabian2ba92e32017-08-21 07:05:03 -07006588 self.vapi.nat_det_add_del_map(dsm.in_addr,
6589 dsm.in_plen,
6590 dsm.out_addr,
6591 dsm.out_plen,
6592 is_add=0)
Martin17a75cb2017-03-08 05:53:20 -08006593
Matus Fabian2ba92e32017-08-21 07:05:03 -07006594 interfaces = self.vapi.nat44_interface_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07006595 for intf in interfaces:
Matus Fabian2ba92e32017-08-21 07:05:03 -07006596 self.vapi.nat44_interface_add_del_feature(intf.sw_if_index,
6597 intf.is_inside,
6598 is_add=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07006599
Matus Fabian066f0342017-02-10 03:48:01 -08006600 def tearDown(self):
6601 super(TestDeterministicNAT, self).tearDown()
6602 if not self.vpp_dead:
Matus Fabian82119542018-01-25 01:13:22 -08006603 self.logger.info(self.vapi.cli("show nat44 interfaces"))
Matus Fabian878c6462018-08-23 00:33:35 -07006604 self.logger.info(self.vapi.cli("show nat timeouts"))
Matus Fabian82119542018-01-25 01:13:22 -08006605 self.logger.info(
6606 self.vapi.cli("show nat44 deterministic mappings"))
6607 self.logger.info(
Matus Fabian82119542018-01-25 01:13:22 -08006608 self.vapi.cli("show nat44 deterministic sessions"))
Matus Fabian2ba92e32017-08-21 07:05:03 -07006609 self.clear_nat_det()
Matus Fabian066f0342017-02-10 03:48:01 -08006610
Matus Fabian06596c52017-06-06 04:53:28 -07006611
6612class TestNAT64(MethodHolder):
6613 """ NAT64 Test Cases """
6614
6615 @classmethod
Matus Fabiana431ad12018-01-04 04:03:14 -08006616 def setUpConstants(cls):
6617 super(TestNAT64, cls).setUpConstants()
6618 cls.vpp_cmdline.extend(["nat", "{", "nat64 bib hash buckets 128",
6619 "nat64 st hash buckets 256", "}"])
6620
6621 @classmethod
Matus Fabian06596c52017-06-06 04:53:28 -07006622 def setUpClass(cls):
6623 super(TestNAT64, cls).setUpClass()
6624
6625 try:
6626 cls.tcp_port_in = 6303
6627 cls.tcp_port_out = 6303
6628 cls.udp_port_in = 6304
6629 cls.udp_port_out = 6304
6630 cls.icmp_id_in = 6305
6631 cls.icmp_id_out = 6305
Matus Fabianad1f3e12018-11-28 21:26:34 -08006632 cls.tcp_external_port = 80
Matus Fabian06596c52017-06-06 04:53:28 -07006633 cls.nat_addr = '10.0.0.3'
6634 cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
Matus Fabian029f3d22017-06-15 02:28:50 -07006635 cls.vrf1_id = 10
6636 cls.vrf1_nat_addr = '10.0.10.3'
6637 cls.vrf1_nat_addr_n = socket.inet_pton(socket.AF_INET,
6638 cls.vrf1_nat_addr)
Matus Fabiana431ad12018-01-04 04:03:14 -08006639 cls.ipfix_src_port = 4739
6640 cls.ipfix_domain_id = 1
Matus Fabian06596c52017-06-06 04:53:28 -07006641
Juraj Slobodac746a152018-07-09 02:36:37 +02006642 cls.create_pg_interfaces(range(6))
Matus Fabian06596c52017-06-06 04:53:28 -07006643 cls.ip6_interfaces = list(cls.pg_interfaces[0:1])
Matus Fabian029f3d22017-06-15 02:28:50 -07006644 cls.ip6_interfaces.append(cls.pg_interfaces[2])
Matus Fabian06596c52017-06-06 04:53:28 -07006645 cls.ip4_interfaces = list(cls.pg_interfaces[1:2])
6646
Neale Ranns15002542017-09-10 04:39:11 -07006647 cls.vapi.ip_table_add_del(cls.vrf1_id, is_add=1, is_ipv6=1)
6648
Matus Fabian029f3d22017-06-15 02:28:50 -07006649 cls.pg_interfaces[2].set_table_ip6(cls.vrf1_id)
6650
6651 cls.pg0.generate_remote_hosts(2)
6652
Matus Fabian06596c52017-06-06 04:53:28 -07006653 for i in cls.ip6_interfaces:
6654 i.admin_up()
6655 i.config_ip6()
Matus Fabian029f3d22017-06-15 02:28:50 -07006656 i.configure_ipv6_neighbors()
Matus Fabian06596c52017-06-06 04:53:28 -07006657
6658 for i in cls.ip4_interfaces:
6659 i.admin_up()
6660 i.config_ip4()
6661 i.resolve_arp()
6662
Matus Fabian36ea2d62017-10-24 04:13:49 -07006663 cls.pg3.admin_up()
6664 cls.pg3.config_ip4()
6665 cls.pg3.resolve_arp()
6666 cls.pg3.config_ip6()
6667 cls.pg3.configure_ipv6_neighbors()
6668
Juraj Slobodac746a152018-07-09 02:36:37 +02006669 cls.pg5.admin_up()
6670 cls.pg5.config_ip6()
6671
Matus Fabian06596c52017-06-06 04:53:28 -07006672 except Exception:
6673 super(TestNAT64, cls).tearDownClass()
6674 raise
6675
Juraj Slobodac746a152018-07-09 02:36:37 +02006676 def test_nat64_inside_interface_handles_neighbor_advertisement(self):
6677 """ NAT64 inside interface handles Neighbor Advertisement """
6678
6679 self.vapi.nat64_add_del_interface(self.pg5.sw_if_index)
6680
6681 # Try to send ping
6682 ping = (Ether(dst=self.pg5.local_mac, src=self.pg5.remote_mac) /
6683 IPv6(src=self.pg5.remote_ip6, dst=self.pg5.local_ip6) /
6684 ICMPv6EchoRequest())
6685 pkts = [ping]
6686 self.pg5.add_stream(pkts)
6687 self.pg_enable_capture(self.pg_interfaces)
6688 self.pg_start()
6689
6690 # Wait for Neighbor Solicitation
6691 capture = self.pg5.get_capture(len(pkts))
Juraj Slobodac746a152018-07-09 02:36:37 +02006692 packet = capture[0]
6693 try:
6694 self.assertEqual(packet[IPv6].src, self.pg5.local_ip6)
Paul Vinciguerra978aa642018-11-24 22:19:12 -08006695 self.assertEqual(packet.haslayer(ICMPv6ND_NS), 1)
Juraj Slobodac746a152018-07-09 02:36:37 +02006696 tgt = packet[ICMPv6ND_NS].tgt
6697 except:
6698 self.logger.error(ppp("Unexpected or invalid packet:", packet))
6699 raise
6700
6701 # Send Neighbor Advertisement
6702 p = (Ether(dst=self.pg5.local_mac, src=self.pg5.remote_mac) /
6703 IPv6(src=self.pg5.remote_ip6, dst=self.pg5.local_ip6) /
6704 ICMPv6ND_NA(tgt=tgt) /
6705 ICMPv6NDOptDstLLAddr(lladdr=self.pg5.remote_mac))
6706 pkts = [p]
6707 self.pg5.add_stream(pkts)
6708 self.pg_enable_capture(self.pg_interfaces)
6709 self.pg_start()
6710
6711 # Try to send ping again
6712 pkts = [ping]
6713 self.pg5.add_stream(pkts)
6714 self.pg_enable_capture(self.pg_interfaces)
6715 self.pg_start()
6716
6717 # Wait for ping reply
6718 capture = self.pg5.get_capture(len(pkts))
Juraj Slobodac746a152018-07-09 02:36:37 +02006719 packet = capture[0]
6720 try:
6721 self.assertEqual(packet[IPv6].src, self.pg5.local_ip6)
6722 self.assertEqual(packet[IPv6].dst, self.pg5.remote_ip6)
Paul Vinciguerra978aa642018-11-24 22:19:12 -08006723 self.assertEqual(packet.haslayer(ICMPv6EchoReply), 1)
Juraj Slobodac746a152018-07-09 02:36:37 +02006724 except:
6725 self.logger.error(ppp("Unexpected or invalid packet:", packet))
6726 raise
6727
Matus Fabian06596c52017-06-06 04:53:28 -07006728 def test_pool(self):
6729 """ Add/delete address to NAT64 pool """
6730 nat_addr = socket.inet_pton(socket.AF_INET, '1.2.3.4')
6731
6732 self.vapi.nat64_add_del_pool_addr_range(nat_addr, nat_addr)
6733
6734 addresses = self.vapi.nat64_pool_addr_dump()
6735 self.assertEqual(len(addresses), 1)
6736 self.assertEqual(addresses[0].address, nat_addr)
6737
6738 self.vapi.nat64_add_del_pool_addr_range(nat_addr, nat_addr, is_add=0)
6739
6740 addresses = self.vapi.nat64_pool_addr_dump()
6741 self.assertEqual(len(addresses), 0)
6742
6743 def test_interface(self):
6744 """ Enable/disable NAT64 feature on the interface """
6745 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6746 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6747
6748 interfaces = self.vapi.nat64_interface_dump()
6749 self.assertEqual(len(interfaces), 2)
6750 pg0_found = False
6751 pg1_found = False
6752 for intf in interfaces:
6753 if intf.sw_if_index == self.pg0.sw_if_index:
6754 self.assertEqual(intf.is_inside, 1)
6755 pg0_found = True
6756 elif intf.sw_if_index == self.pg1.sw_if_index:
6757 self.assertEqual(intf.is_inside, 0)
6758 pg1_found = True
6759 self.assertTrue(pg0_found)
6760 self.assertTrue(pg1_found)
6761
6762 features = self.vapi.cli("show interface features pg0")
6763 self.assertNotEqual(features.find('nat64-in2out'), -1)
6764 features = self.vapi.cli("show interface features pg1")
6765 self.assertNotEqual(features.find('nat64-out2in'), -1)
6766
6767 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index, is_add=0)
6768 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_add=0)
6769
6770 interfaces = self.vapi.nat64_interface_dump()
6771 self.assertEqual(len(interfaces), 0)
6772
6773 def test_static_bib(self):
6774 """ Add/delete static BIB entry """
6775 in_addr = socket.inet_pton(socket.AF_INET6,
6776 '2001:db8:85a3::8a2e:370:7334')
6777 out_addr = socket.inet_pton(socket.AF_INET, '10.1.1.3')
6778 in_port = 1234
6779 out_port = 5678
6780 proto = IP_PROTOS.tcp
6781
6782 self.vapi.nat64_add_del_static_bib(in_addr,
6783 out_addr,
6784 in_port,
6785 out_port,
6786 proto)
6787 bib = self.vapi.nat64_bib_dump(IP_PROTOS.tcp)
6788 static_bib_num = 0
6789 for bibe in bib:
6790 if bibe.is_static:
6791 static_bib_num += 1
6792 self.assertEqual(bibe.i_addr, in_addr)
6793 self.assertEqual(bibe.o_addr, out_addr)
6794 self.assertEqual(bibe.i_port, in_port)
6795 self.assertEqual(bibe.o_port, out_port)
6796 self.assertEqual(static_bib_num, 1)
6797
6798 self.vapi.nat64_add_del_static_bib(in_addr,
6799 out_addr,
6800 in_port,
6801 out_port,
6802 proto,
6803 is_add=0)
6804 bib = self.vapi.nat64_bib_dump(IP_PROTOS.tcp)
6805 static_bib_num = 0
6806 for bibe in bib:
6807 if bibe.is_static:
6808 static_bib_num += 1
6809 self.assertEqual(static_bib_num, 0)
6810
6811 def test_set_timeouts(self):
6812 """ Set NAT64 timeouts """
6813 # verify default values
Matus Fabian878c6462018-08-23 00:33:35 -07006814 timeouts = self.vapi.nat_get_timeouts()
Matus Fabian06596c52017-06-06 04:53:28 -07006815 self.assertEqual(timeouts.udp, 300)
6816 self.assertEqual(timeouts.icmp, 60)
Matus Fabian878c6462018-08-23 00:33:35 -07006817 self.assertEqual(timeouts.tcp_transitory, 240)
6818 self.assertEqual(timeouts.tcp_established, 7440)
Matus Fabian06596c52017-06-06 04:53:28 -07006819
6820 # set and verify custom values
Matus Fabian878c6462018-08-23 00:33:35 -07006821 self.vapi.nat_set_timeouts(udp=200, icmp=30, tcp_transitory=250,
6822 tcp_established=7450)
6823 timeouts = self.vapi.nat_get_timeouts()
Matus Fabian06596c52017-06-06 04:53:28 -07006824 self.assertEqual(timeouts.udp, 200)
6825 self.assertEqual(timeouts.icmp, 30)
Matus Fabian878c6462018-08-23 00:33:35 -07006826 self.assertEqual(timeouts.tcp_transitory, 250)
6827 self.assertEqual(timeouts.tcp_established, 7450)
Matus Fabian06596c52017-06-06 04:53:28 -07006828
6829 def test_dynamic(self):
6830 """ NAT64 dynamic translation test """
6831 self.tcp_port_in = 6303
6832 self.udp_port_in = 6304
6833 self.icmp_id_in = 6305
6834
6835 ses_num_start = self.nat64_get_ses_num()
6836
6837 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6838 self.nat_addr_n)
6839 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6840 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6841
6842 # in2out
6843 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
6844 self.pg0.add_stream(pkts)
6845 self.pg_enable_capture(self.pg_interfaces)
6846 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07006847 capture = self.pg1.get_capture(len(pkts))
6848 self.verify_capture_out(capture, nat_ip=self.nat_addr,
Matus Fabian06596c52017-06-06 04:53:28 -07006849 dst_ip=self.pg1.remote_ip4)
6850
6851 # out2in
6852 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
6853 self.pg1.add_stream(pkts)
6854 self.pg_enable_capture(self.pg_interfaces)
6855 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07006856 capture = self.pg0.get_capture(len(pkts))
Matus Fabian06596c52017-06-06 04:53:28 -07006857 ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
6858 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
6859
6860 # in2out
6861 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
6862 self.pg0.add_stream(pkts)
6863 self.pg_enable_capture(self.pg_interfaces)
6864 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07006865 capture = self.pg1.get_capture(len(pkts))
6866 self.verify_capture_out(capture, nat_ip=self.nat_addr,
Matus Fabian06596c52017-06-06 04:53:28 -07006867 dst_ip=self.pg1.remote_ip4)
6868
6869 # out2in
6870 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
6871 self.pg1.add_stream(pkts)
6872 self.pg_enable_capture(self.pg_interfaces)
6873 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07006874 capture = self.pg0.get_capture(len(pkts))
Matus Fabian06596c52017-06-06 04:53:28 -07006875 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
6876
6877 ses_num_end = self.nat64_get_ses_num()
6878
6879 self.assertEqual(ses_num_end - ses_num_start, 3)
6880
Matus Fabian029f3d22017-06-15 02:28:50 -07006881 # tenant with specific VRF
6882 self.vapi.nat64_add_del_pool_addr_range(self.vrf1_nat_addr_n,
6883 self.vrf1_nat_addr_n,
6884 vrf_id=self.vrf1_id)
6885 self.vapi.nat64_add_del_interface(self.pg2.sw_if_index)
6886
6887 pkts = self.create_stream_in_ip6(self.pg2, self.pg1)
6888 self.pg2.add_stream(pkts)
6889 self.pg_enable_capture(self.pg_interfaces)
6890 self.pg_start()
6891 capture = self.pg1.get_capture(len(pkts))
6892 self.verify_capture_out(capture, nat_ip=self.vrf1_nat_addr,
6893 dst_ip=self.pg1.remote_ip4)
6894
6895 pkts = self.create_stream_out(self.pg1, dst_ip=self.vrf1_nat_addr)
6896 self.pg1.add_stream(pkts)
6897 self.pg_enable_capture(self.pg_interfaces)
6898 self.pg_start()
6899 capture = self.pg2.get_capture(len(pkts))
6900 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg2.remote_ip6)
6901
Matus Fabian06596c52017-06-06 04:53:28 -07006902 def test_static(self):
6903 """ NAT64 static translation test """
6904 self.tcp_port_in = 60303
6905 self.udp_port_in = 60304
6906 self.icmp_id_in = 60305
6907 self.tcp_port_out = 60303
6908 self.udp_port_out = 60304
6909 self.icmp_id_out = 60305
6910
6911 ses_num_start = self.nat64_get_ses_num()
6912
6913 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6914 self.nat_addr_n)
6915 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6916 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6917
6918 self.vapi.nat64_add_del_static_bib(self.pg0.remote_ip6n,
6919 self.nat_addr_n,
6920 self.tcp_port_in,
6921 self.tcp_port_out,
6922 IP_PROTOS.tcp)
6923 self.vapi.nat64_add_del_static_bib(self.pg0.remote_ip6n,
6924 self.nat_addr_n,
6925 self.udp_port_in,
6926 self.udp_port_out,
6927 IP_PROTOS.udp)
6928 self.vapi.nat64_add_del_static_bib(self.pg0.remote_ip6n,
6929 self.nat_addr_n,
6930 self.icmp_id_in,
6931 self.icmp_id_out,
6932 IP_PROTOS.icmp)
6933
6934 # in2out
6935 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
6936 self.pg0.add_stream(pkts)
6937 self.pg_enable_capture(self.pg_interfaces)
6938 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07006939 capture = self.pg1.get_capture(len(pkts))
6940 self.verify_capture_out(capture, nat_ip=self.nat_addr,
Matus Fabian06596c52017-06-06 04:53:28 -07006941 dst_ip=self.pg1.remote_ip4, same_port=True)
6942
6943 # out2in
6944 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
6945 self.pg1.add_stream(pkts)
6946 self.pg_enable_capture(self.pg_interfaces)
6947 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07006948 capture = self.pg0.get_capture(len(pkts))
Matus Fabian06596c52017-06-06 04:53:28 -07006949 ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
6950 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
6951
6952 ses_num_end = self.nat64_get_ses_num()
6953
6954 self.assertEqual(ses_num_end - ses_num_start, 3)
6955
6956 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
6957 def test_session_timeout(self):
6958 """ NAT64 session timeout """
6959 self.icmp_id_in = 1234
6960 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6961 self.nat_addr_n)
6962 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6963 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
Matus Fabian878c6462018-08-23 00:33:35 -07006964 self.vapi.nat_set_timeouts(icmp=5, tcp_transitory=5, tcp_established=5)
Matus Fabian06596c52017-06-06 04:53:28 -07006965
6966 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
6967 self.pg0.add_stream(pkts)
6968 self.pg_enable_capture(self.pg_interfaces)
6969 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07006970 capture = self.pg1.get_capture(len(pkts))
Matus Fabian06596c52017-06-06 04:53:28 -07006971
6972 ses_num_before_timeout = self.nat64_get_ses_num()
6973
6974 sleep(15)
6975
Matus Fabian8fed4242018-08-14 05:14:55 -07006976 # ICMP and TCP session after timeout
Matus Fabian06596c52017-06-06 04:53:28 -07006977 ses_num_after_timeout = self.nat64_get_ses_num()
Matus Fabian8fed4242018-08-14 05:14:55 -07006978 self.assertEqual(ses_num_before_timeout - ses_num_after_timeout, 2)
Matus Fabian06596c52017-06-06 04:53:28 -07006979
Matus Fabian732036d2017-06-08 05:24:28 -07006980 def test_icmp_error(self):
6981 """ NAT64 ICMP Error message translation """
6982 self.tcp_port_in = 6303
6983 self.udp_port_in = 6304
6984 self.icmp_id_in = 6305
6985
Matus Fabian732036d2017-06-08 05:24:28 -07006986 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6987 self.nat_addr_n)
6988 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6989 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6990
6991 # send some packets to create sessions
6992 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
6993 self.pg0.add_stream(pkts)
6994 self.pg_enable_capture(self.pg_interfaces)
6995 self.pg_start()
6996 capture_ip4 = self.pg1.get_capture(len(pkts))
Matus Fabian029f3d22017-06-15 02:28:50 -07006997 self.verify_capture_out(capture_ip4,
Matus Fabian732036d2017-06-08 05:24:28 -07006998 nat_ip=self.nat_addr,
6999 dst_ip=self.pg1.remote_ip4)
7000
7001 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
7002 self.pg1.add_stream(pkts)
7003 self.pg_enable_capture(self.pg_interfaces)
7004 self.pg_start()
7005 capture_ip6 = self.pg0.get_capture(len(pkts))
7006 ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
7007 self.verify_capture_in_ip6(capture_ip6, ip[IPv6].src,
7008 self.pg0.remote_ip6)
7009
7010 # in2out
7011 pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7012 IPv6(src=self.pg0.remote_ip6, dst=ip[IPv6].src) /
7013 ICMPv6DestUnreach(code=1) /
7014 packet[IPv6] for packet in capture_ip6]
7015 self.pg0.add_stream(pkts)
7016 self.pg_enable_capture(self.pg_interfaces)
7017 self.pg_start()
7018 capture = self.pg1.get_capture(len(pkts))
7019 for packet in capture:
7020 try:
7021 self.assertEqual(packet[IP].src, self.nat_addr)
7022 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
7023 self.assertEqual(packet[ICMP].type, 3)
7024 self.assertEqual(packet[ICMP].code, 13)
7025 inner = packet[IPerror]
7026 self.assertEqual(inner.src, self.pg1.remote_ip4)
7027 self.assertEqual(inner.dst, self.nat_addr)
Klement Sekerad81ae412018-05-16 10:52:54 +02007028 self.assert_packet_checksums_valid(packet)
Matus Fabian732036d2017-06-08 05:24:28 -07007029 if inner.haslayer(TCPerror):
7030 self.assertEqual(inner[TCPerror].dport, self.tcp_port_out)
7031 elif inner.haslayer(UDPerror):
7032 self.assertEqual(inner[UDPerror].dport, self.udp_port_out)
7033 else:
7034 self.assertEqual(inner[ICMPerror].id, self.icmp_id_out)
7035 except:
7036 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7037 raise
7038
7039 # out2in
7040 pkts = [Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
7041 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
7042 ICMP(type=3, code=13) /
7043 packet[IP] for packet in capture_ip4]
7044 self.pg1.add_stream(pkts)
7045 self.pg_enable_capture(self.pg_interfaces)
7046 self.pg_start()
7047 capture = self.pg0.get_capture(len(pkts))
7048 for packet in capture:
7049 try:
7050 self.assertEqual(packet[IPv6].src, ip.src)
7051 self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
7052 icmp = packet[ICMPv6DestUnreach]
7053 self.assertEqual(icmp.code, 1)
7054 inner = icmp[IPerror6]
7055 self.assertEqual(inner.src, self.pg0.remote_ip6)
7056 self.assertEqual(inner.dst, ip.src)
Klement Sekerad81ae412018-05-16 10:52:54 +02007057 self.assert_icmpv6_checksum_valid(packet)
Matus Fabian732036d2017-06-08 05:24:28 -07007058 if inner.haslayer(TCPerror):
7059 self.assertEqual(inner[TCPerror].sport, self.tcp_port_in)
7060 elif inner.haslayer(UDPerror):
7061 self.assertEqual(inner[UDPerror].sport, self.udp_port_in)
7062 else:
7063 self.assertEqual(inner[ICMPv6EchoRequest].id,
7064 self.icmp_id_in)
7065 except:
7066 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7067 raise
7068
Matus Fabian029f3d22017-06-15 02:28:50 -07007069 def test_hairpinning(self):
7070 """ NAT64 hairpinning """
7071
7072 client = self.pg0.remote_hosts[0]
7073 server = self.pg0.remote_hosts[1]
7074 server_tcp_in_port = 22
7075 server_tcp_out_port = 4022
7076 server_udp_in_port = 23
7077 server_udp_out_port = 4023
7078 client_tcp_in_port = 1234
7079 client_udp_in_port = 1235
7080 client_tcp_out_port = 0
7081 client_udp_out_port = 0
7082 ip = IPv6(src=''.join(['64:ff9b::', self.nat_addr]))
7083 nat_addr_ip6 = ip.src
7084
7085 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7086 self.nat_addr_n)
7087 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7088 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7089
7090 self.vapi.nat64_add_del_static_bib(server.ip6n,
7091 self.nat_addr_n,
7092 server_tcp_in_port,
7093 server_tcp_out_port,
7094 IP_PROTOS.tcp)
7095 self.vapi.nat64_add_del_static_bib(server.ip6n,
7096 self.nat_addr_n,
7097 server_udp_in_port,
7098 server_udp_out_port,
7099 IP_PROTOS.udp)
7100
7101 # client to server
7102 pkts = []
7103 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7104 IPv6(src=client.ip6, dst=nat_addr_ip6) /
7105 TCP(sport=client_tcp_in_port, dport=server_tcp_out_port))
7106 pkts.append(p)
7107 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7108 IPv6(src=client.ip6, dst=nat_addr_ip6) /
7109 UDP(sport=client_udp_in_port, dport=server_udp_out_port))
7110 pkts.append(p)
7111 self.pg0.add_stream(pkts)
7112 self.pg_enable_capture(self.pg_interfaces)
7113 self.pg_start()
7114 capture = self.pg0.get_capture(len(pkts))
7115 for packet in capture:
7116 try:
7117 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
7118 self.assertEqual(packet[IPv6].dst, server.ip6)
Klement Sekerad81ae412018-05-16 10:52:54 +02007119 self.assert_packet_checksums_valid(packet)
Matus Fabian029f3d22017-06-15 02:28:50 -07007120 if packet.haslayer(TCP):
7121 self.assertNotEqual(packet[TCP].sport, client_tcp_in_port)
7122 self.assertEqual(packet[TCP].dport, server_tcp_in_port)
Matus Fabian029f3d22017-06-15 02:28:50 -07007123 client_tcp_out_port = packet[TCP].sport
7124 else:
7125 self.assertNotEqual(packet[UDP].sport, client_udp_in_port)
7126 self.assertEqual(packet[UDP].dport, server_udp_in_port)
Matus Fabian029f3d22017-06-15 02:28:50 -07007127 client_udp_out_port = packet[UDP].sport
7128 except:
7129 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7130 raise
7131
7132 # server to client
7133 pkts = []
7134 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7135 IPv6(src=server.ip6, dst=nat_addr_ip6) /
7136 TCP(sport=server_tcp_in_port, dport=client_tcp_out_port))
7137 pkts.append(p)
7138 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7139 IPv6(src=server.ip6, dst=nat_addr_ip6) /
7140 UDP(sport=server_udp_in_port, dport=client_udp_out_port))
7141 pkts.append(p)
7142 self.pg0.add_stream(pkts)
7143 self.pg_enable_capture(self.pg_interfaces)
7144 self.pg_start()
7145 capture = self.pg0.get_capture(len(pkts))
7146 for packet in capture:
7147 try:
7148 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
7149 self.assertEqual(packet[IPv6].dst, client.ip6)
Klement Sekerad81ae412018-05-16 10:52:54 +02007150 self.assert_packet_checksums_valid(packet)
Matus Fabian029f3d22017-06-15 02:28:50 -07007151 if packet.haslayer(TCP):
7152 self.assertEqual(packet[TCP].sport, server_tcp_out_port)
7153 self.assertEqual(packet[TCP].dport, client_tcp_in_port)
Matus Fabian029f3d22017-06-15 02:28:50 -07007154 else:
7155 self.assertEqual(packet[UDP].sport, server_udp_out_port)
7156 self.assertEqual(packet[UDP].dport, client_udp_in_port)
Matus Fabian029f3d22017-06-15 02:28:50 -07007157 except:
7158 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7159 raise
7160
7161 # ICMP error
7162 pkts = []
7163 pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7164 IPv6(src=client.ip6, dst=nat_addr_ip6) /
7165 ICMPv6DestUnreach(code=1) /
7166 packet[IPv6] for packet in capture]
7167 self.pg0.add_stream(pkts)
7168 self.pg_enable_capture(self.pg_interfaces)
7169 self.pg_start()
7170 capture = self.pg0.get_capture(len(pkts))
7171 for packet in capture:
7172 try:
7173 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
7174 self.assertEqual(packet[IPv6].dst, server.ip6)
7175 icmp = packet[ICMPv6DestUnreach]
7176 self.assertEqual(icmp.code, 1)
7177 inner = icmp[IPerror6]
7178 self.assertEqual(inner.src, server.ip6)
7179 self.assertEqual(inner.dst, nat_addr_ip6)
Klement Sekerad81ae412018-05-16 10:52:54 +02007180 self.assert_packet_checksums_valid(packet)
Matus Fabian029f3d22017-06-15 02:28:50 -07007181 if inner.haslayer(TCPerror):
7182 self.assertEqual(inner[TCPerror].sport, server_tcp_in_port)
7183 self.assertEqual(inner[TCPerror].dport,
7184 client_tcp_out_port)
7185 else:
7186 self.assertEqual(inner[UDPerror].sport, server_udp_in_port)
7187 self.assertEqual(inner[UDPerror].dport,
7188 client_udp_out_port)
7189 except:
7190 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7191 raise
7192
Matus Fabian428dc912017-06-21 06:15:18 -07007193 def test_prefix(self):
7194 """ NAT64 Network-Specific Prefix """
7195
7196 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7197 self.nat_addr_n)
7198 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7199 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7200 self.vapi.nat64_add_del_pool_addr_range(self.vrf1_nat_addr_n,
7201 self.vrf1_nat_addr_n,
7202 vrf_id=self.vrf1_id)
7203 self.vapi.nat64_add_del_interface(self.pg2.sw_if_index)
7204
7205 # Add global prefix
7206 global_pref64 = "2001:db8::"
7207 global_pref64_n = socket.inet_pton(socket.AF_INET6, global_pref64)
7208 global_pref64_len = 32
7209 self.vapi.nat64_add_del_prefix(global_pref64_n, global_pref64_len)
7210
7211 prefix = self.vapi.nat64_prefix_dump()
7212 self.assertEqual(len(prefix), 1)
7213 self.assertEqual(prefix[0].prefix, global_pref64_n)
7214 self.assertEqual(prefix[0].prefix_len, global_pref64_len)
7215 self.assertEqual(prefix[0].vrf_id, 0)
7216
7217 # Add tenant specific prefix
7218 vrf1_pref64 = "2001:db8:122:300::"
7219 vrf1_pref64_n = socket.inet_pton(socket.AF_INET6, vrf1_pref64)
7220 vrf1_pref64_len = 56
7221 self.vapi.nat64_add_del_prefix(vrf1_pref64_n,
7222 vrf1_pref64_len,
7223 vrf_id=self.vrf1_id)
7224 prefix = self.vapi.nat64_prefix_dump()
7225 self.assertEqual(len(prefix), 2)
7226
7227 # Global prefix
7228 pkts = self.create_stream_in_ip6(self.pg0,
7229 self.pg1,
7230 pref=global_pref64,
7231 plen=global_pref64_len)
7232 self.pg0.add_stream(pkts)
7233 self.pg_enable_capture(self.pg_interfaces)
7234 self.pg_start()
7235 capture = self.pg1.get_capture(len(pkts))
7236 self.verify_capture_out(capture, nat_ip=self.nat_addr,
7237 dst_ip=self.pg1.remote_ip4)
7238
7239 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
7240 self.pg1.add_stream(pkts)
7241 self.pg_enable_capture(self.pg_interfaces)
7242 self.pg_start()
7243 capture = self.pg0.get_capture(len(pkts))
7244 dst_ip = self.compose_ip6(self.pg1.remote_ip4,
7245 global_pref64,
7246 global_pref64_len)
7247 self.verify_capture_in_ip6(capture, dst_ip, self.pg0.remote_ip6)
7248
7249 # Tenant specific prefix
7250 pkts = self.create_stream_in_ip6(self.pg2,
7251 self.pg1,
7252 pref=vrf1_pref64,
7253 plen=vrf1_pref64_len)
7254 self.pg2.add_stream(pkts)
7255 self.pg_enable_capture(self.pg_interfaces)
7256 self.pg_start()
7257 capture = self.pg1.get_capture(len(pkts))
7258 self.verify_capture_out(capture, nat_ip=self.vrf1_nat_addr,
7259 dst_ip=self.pg1.remote_ip4)
7260
7261 pkts = self.create_stream_out(self.pg1, dst_ip=self.vrf1_nat_addr)
7262 self.pg1.add_stream(pkts)
7263 self.pg_enable_capture(self.pg_interfaces)
7264 self.pg_start()
7265 capture = self.pg2.get_capture(len(pkts))
7266 dst_ip = self.compose_ip6(self.pg1.remote_ip4,
7267 vrf1_pref64,
7268 vrf1_pref64_len)
7269 self.verify_capture_in_ip6(capture, dst_ip, self.pg2.remote_ip6)
7270
Matus Fabianf8cd5812017-07-11 03:55:02 -07007271 def test_unknown_proto(self):
Matus Fabian7968e6c2017-07-06 05:37:49 -07007272 """ NAT64 translate packet with unknown protocol """
7273
7274 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7275 self.nat_addr_n)
7276 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7277 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7278 remote_ip6 = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
7279
7280 # in2out
7281 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7282 IPv6(src=self.pg0.remote_ip6, dst=remote_ip6) /
7283 TCP(sport=self.tcp_port_in, dport=20))
7284 self.pg0.add_stream(p)
7285 self.pg_enable_capture(self.pg_interfaces)
7286 self.pg_start()
7287 p = self.pg1.get_capture(1)
7288
7289 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabianf8cd5812017-07-11 03:55:02 -07007290 IPv6(src=self.pg0.remote_ip6, dst=remote_ip6, nh=47) /
Matus Fabian7968e6c2017-07-06 05:37:49 -07007291 GRE() /
7292 IP(src=self.pg2.local_ip4, dst=self.pg2.remote_ip4) /
7293 TCP(sport=1234, dport=1234))
7294 self.pg0.add_stream(p)
7295 self.pg_enable_capture(self.pg_interfaces)
7296 self.pg_start()
7297 p = self.pg1.get_capture(1)
7298 packet = p[0]
7299 try:
7300 self.assertEqual(packet[IP].src, self.nat_addr)
7301 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
Paul Vinciguerra978aa642018-11-24 22:19:12 -08007302 self.assertEqual(packet.haslayer(GRE), 1)
Klement Sekerad81ae412018-05-16 10:52:54 +02007303 self.assert_packet_checksums_valid(packet)
Matus Fabian7968e6c2017-07-06 05:37:49 -07007304 except:
7305 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7306 raise
7307
7308 # out2in
7309 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
7310 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
7311 GRE() /
7312 IP(src=self.pg2.remote_ip4, dst=self.pg2.local_ip4) /
7313 TCP(sport=1234, dport=1234))
7314 self.pg1.add_stream(p)
7315 self.pg_enable_capture(self.pg_interfaces)
7316 self.pg_start()
7317 p = self.pg0.get_capture(1)
7318 packet = p[0]
7319 try:
7320 self.assertEqual(packet[IPv6].src, remote_ip6)
Matus Fabianf8cd5812017-07-11 03:55:02 -07007321 self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
7322 self.assertEqual(packet[IPv6].nh, 47)
Matus Fabian7968e6c2017-07-06 05:37:49 -07007323 except:
7324 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7325 raise
7326
Matus Fabianf8cd5812017-07-11 03:55:02 -07007327 def test_hairpinning_unknown_proto(self):
Matus Fabian7968e6c2017-07-06 05:37:49 -07007328 """ NAT64 translate packet with unknown protocol - hairpinning """
7329
7330 client = self.pg0.remote_hosts[0]
7331 server = self.pg0.remote_hosts[1]
7332 server_tcp_in_port = 22
7333 server_tcp_out_port = 4022
7334 client_tcp_in_port = 1234
Matus Fabianf8cd5812017-07-11 03:55:02 -07007335 client_tcp_out_port = 1235
7336 server_nat_ip = "10.0.0.100"
7337 client_nat_ip = "10.0.0.110"
7338 server_nat_ip_n = socket.inet_pton(socket.AF_INET, server_nat_ip)
7339 client_nat_ip_n = socket.inet_pton(socket.AF_INET, client_nat_ip)
7340 server_nat_ip6 = self.compose_ip6(server_nat_ip, '64:ff9b::', 96)
7341 client_nat_ip6 = self.compose_ip6(client_nat_ip, '64:ff9b::', 96)
Matus Fabian7968e6c2017-07-06 05:37:49 -07007342
Matus Fabianf8cd5812017-07-11 03:55:02 -07007343 self.vapi.nat64_add_del_pool_addr_range(server_nat_ip_n,
7344 client_nat_ip_n)
Matus Fabian7968e6c2017-07-06 05:37:49 -07007345 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7346 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7347
7348 self.vapi.nat64_add_del_static_bib(server.ip6n,
Matus Fabianf8cd5812017-07-11 03:55:02 -07007349 server_nat_ip_n,
Matus Fabian7968e6c2017-07-06 05:37:49 -07007350 server_tcp_in_port,
7351 server_tcp_out_port,
7352 IP_PROTOS.tcp)
7353
Matus Fabianf8cd5812017-07-11 03:55:02 -07007354 self.vapi.nat64_add_del_static_bib(server.ip6n,
7355 server_nat_ip_n,
7356 0,
7357 0,
7358 IP_PROTOS.gre)
7359
7360 self.vapi.nat64_add_del_static_bib(client.ip6n,
7361 client_nat_ip_n,
7362 client_tcp_in_port,
7363 client_tcp_out_port,
7364 IP_PROTOS.tcp)
7365
Matus Fabian7968e6c2017-07-06 05:37:49 -07007366 # client to server
7367 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabianf8cd5812017-07-11 03:55:02 -07007368 IPv6(src=client.ip6, dst=server_nat_ip6) /
Matus Fabian7968e6c2017-07-06 05:37:49 -07007369 TCP(sport=client_tcp_in_port, dport=server_tcp_out_port))
7370 self.pg0.add_stream(p)
7371 self.pg_enable_capture(self.pg_interfaces)
7372 self.pg_start()
7373 p = self.pg0.get_capture(1)
7374
7375 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabianf8cd5812017-07-11 03:55:02 -07007376 IPv6(src=client.ip6, dst=server_nat_ip6, nh=IP_PROTOS.gre) /
Matus Fabian7968e6c2017-07-06 05:37:49 -07007377 GRE() /
7378 IP(src=self.pg2.local_ip4, dst=self.pg2.remote_ip4) /
7379 TCP(sport=1234, dport=1234))
7380 self.pg0.add_stream(p)
7381 self.pg_enable_capture(self.pg_interfaces)
7382 self.pg_start()
7383 p = self.pg0.get_capture(1)
7384 packet = p[0]
7385 try:
Matus Fabianf8cd5812017-07-11 03:55:02 -07007386 self.assertEqual(packet[IPv6].src, client_nat_ip6)
Matus Fabian7968e6c2017-07-06 05:37:49 -07007387 self.assertEqual(packet[IPv6].dst, server.ip6)
Matus Fabianf8cd5812017-07-11 03:55:02 -07007388 self.assertEqual(packet[IPv6].nh, IP_PROTOS.gre)
Matus Fabian7968e6c2017-07-06 05:37:49 -07007389 except:
7390 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7391 raise
7392
7393 # server to client
7394 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabianf8cd5812017-07-11 03:55:02 -07007395 IPv6(src=server.ip6, dst=client_nat_ip6, nh=IP_PROTOS.gre) /
Matus Fabian7968e6c2017-07-06 05:37:49 -07007396 GRE() /
7397 IP(src=self.pg2.remote_ip4, dst=self.pg2.local_ip4) /
7398 TCP(sport=1234, dport=1234))
7399 self.pg0.add_stream(p)
7400 self.pg_enable_capture(self.pg_interfaces)
7401 self.pg_start()
7402 p = self.pg0.get_capture(1)
7403 packet = p[0]
7404 try:
Matus Fabianf8cd5812017-07-11 03:55:02 -07007405 self.assertEqual(packet[IPv6].src, server_nat_ip6)
Matus Fabian7968e6c2017-07-06 05:37:49 -07007406 self.assertEqual(packet[IPv6].dst, client.ip6)
Matus Fabianf8cd5812017-07-11 03:55:02 -07007407 self.assertEqual(packet[IPv6].nh, IP_PROTOS.gre)
Matus Fabian7968e6c2017-07-06 05:37:49 -07007408 except:
7409 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7410 raise
7411
Matus Fabian36ea2d62017-10-24 04:13:49 -07007412 def test_one_armed_nat64(self):
7413 """ One armed NAT64 """
7414 external_port = 0
7415 remote_host_ip6 = self.compose_ip6(self.pg3.remote_ip4,
7416 '64:ff9b::',
7417 96)
7418
7419 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7420 self.nat_addr_n)
7421 self.vapi.nat64_add_del_interface(self.pg3.sw_if_index)
7422 self.vapi.nat64_add_del_interface(self.pg3.sw_if_index, is_inside=0)
7423
7424 # in2out
7425 p = (Ether(src=self.pg3.remote_mac, dst=self.pg3.local_mac) /
7426 IPv6(src=self.pg3.remote_ip6, dst=remote_host_ip6) /
7427 TCP(sport=12345, dport=80))
7428 self.pg3.add_stream(p)
7429 self.pg_enable_capture(self.pg_interfaces)
7430 self.pg_start()
7431 capture = self.pg3.get_capture(1)
7432 p = capture[0]
7433 try:
7434 ip = p[IP]
7435 tcp = p[TCP]
7436 self.assertEqual(ip.src, self.nat_addr)
7437 self.assertEqual(ip.dst, self.pg3.remote_ip4)
7438 self.assertNotEqual(tcp.sport, 12345)
7439 external_port = tcp.sport
7440 self.assertEqual(tcp.dport, 80)
Klement Sekerad81ae412018-05-16 10:52:54 +02007441 self.assert_packet_checksums_valid(p)
Matus Fabian36ea2d62017-10-24 04:13:49 -07007442 except:
7443 self.logger.error(ppp("Unexpected or invalid packet:", p))
7444 raise
7445
7446 # out2in
7447 p = (Ether(src=self.pg3.remote_mac, dst=self.pg3.local_mac) /
7448 IP(src=self.pg3.remote_ip4, dst=self.nat_addr) /
7449 TCP(sport=80, dport=external_port))
7450 self.pg3.add_stream(p)
7451 self.pg_enable_capture(self.pg_interfaces)
7452 self.pg_start()
7453 capture = self.pg3.get_capture(1)
7454 p = capture[0]
7455 try:
7456 ip = p[IPv6]
7457 tcp = p[TCP]
7458 self.assertEqual(ip.src, remote_host_ip6)
7459 self.assertEqual(ip.dst, self.pg3.remote_ip6)
7460 self.assertEqual(tcp.sport, 80)
7461 self.assertEqual(tcp.dport, 12345)
Klement Sekerad81ae412018-05-16 10:52:54 +02007462 self.assert_packet_checksums_valid(p)
Matus Fabian36ea2d62017-10-24 04:13:49 -07007463 except:
7464 self.logger.error(ppp("Unexpected or invalid packet:", p))
7465 raise
7466
Matus Fabianefcd1e92017-08-15 06:59:19 -07007467 def test_frag_in_order(self):
7468 """ NAT64 translate fragments arriving in order """
7469 self.tcp_port_in = random.randint(1025, 65535)
7470
7471 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7472 self.nat_addr_n)
7473 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7474 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7475
7476 reass = self.vapi.nat_reass_dump()
7477 reass_n_start = len(reass)
7478
7479 # in2out
7480 data = 'a' * 200
7481 pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
7482 self.tcp_port_in, 20, data)
7483 self.pg0.add_stream(pkts)
7484 self.pg_enable_capture(self.pg_interfaces)
7485 self.pg_start()
7486 frags = self.pg1.get_capture(len(pkts))
7487 p = self.reass_frags_and_verify(frags,
7488 self.nat_addr,
7489 self.pg1.remote_ip4)
7490 self.assertEqual(p[TCP].dport, 20)
7491 self.assertNotEqual(p[TCP].sport, self.tcp_port_in)
7492 self.tcp_port_out = p[TCP].sport
7493 self.assertEqual(data, p[Raw].load)
7494
7495 # out2in
7496 data = "A" * 4 + "b" * 16 + "C" * 3
7497 pkts = self.create_stream_frag(self.pg1,
7498 self.nat_addr,
7499 20,
7500 self.tcp_port_out,
7501 data)
7502 self.pg1.add_stream(pkts)
7503 self.pg_enable_capture(self.pg_interfaces)
7504 self.pg_start()
7505 frags = self.pg0.get_capture(len(pkts))
7506 src = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
7507 p = self.reass_frags_and_verify_ip6(frags, src, self.pg0.remote_ip6)
7508 self.assertEqual(p[TCP].sport, 20)
7509 self.assertEqual(p[TCP].dport, self.tcp_port_in)
7510 self.assertEqual(data, p[Raw].load)
7511
7512 reass = self.vapi.nat_reass_dump()
7513 reass_n_end = len(reass)
7514
7515 self.assertEqual(reass_n_end - reass_n_start, 2)
7516
7517 def test_reass_hairpinning(self):
7518 """ NAT64 fragments hairpinning """
7519 data = 'a' * 200
Matus Fabianefcd1e92017-08-15 06:59:19 -07007520 server = self.pg0.remote_hosts[1]
7521 server_in_port = random.randint(1025, 65535)
7522 server_out_port = random.randint(1025, 65535)
7523 client_in_port = random.randint(1025, 65535)
7524 ip = IPv6(src=''.join(['64:ff9b::', self.nat_addr]))
7525 nat_addr_ip6 = ip.src
7526
7527 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7528 self.nat_addr_n)
7529 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7530 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7531
7532 # add static BIB entry for server
7533 self.vapi.nat64_add_del_static_bib(server.ip6n,
7534 self.nat_addr_n,
7535 server_in_port,
7536 server_out_port,
7537 IP_PROTOS.tcp)
7538
7539 # send packet from host to server
7540 pkts = self.create_stream_frag_ip6(self.pg0,
7541 self.nat_addr,
7542 client_in_port,
7543 server_out_port,
7544 data)
7545 self.pg0.add_stream(pkts)
7546 self.pg_enable_capture(self.pg_interfaces)
7547 self.pg_start()
7548 frags = self.pg0.get_capture(len(pkts))
7549 p = self.reass_frags_and_verify_ip6(frags, nat_addr_ip6, server.ip6)
7550 self.assertNotEqual(p[TCP].sport, client_in_port)
7551 self.assertEqual(p[TCP].dport, server_in_port)
7552 self.assertEqual(data, p[Raw].load)
7553
7554 def test_frag_out_of_order(self):
7555 """ NAT64 translate fragments arriving out of order """
7556 self.tcp_port_in = random.randint(1025, 65535)
7557
7558 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7559 self.nat_addr_n)
7560 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7561 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7562
7563 # in2out
7564 data = 'a' * 200
7565 pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
7566 self.tcp_port_in, 20, data)
7567 pkts.reverse()
7568 self.pg0.add_stream(pkts)
7569 self.pg_enable_capture(self.pg_interfaces)
7570 self.pg_start()
7571 frags = self.pg1.get_capture(len(pkts))
7572 p = self.reass_frags_and_verify(frags,
7573 self.nat_addr,
7574 self.pg1.remote_ip4)
7575 self.assertEqual(p[TCP].dport, 20)
7576 self.assertNotEqual(p[TCP].sport, self.tcp_port_in)
7577 self.tcp_port_out = p[TCP].sport
7578 self.assertEqual(data, p[Raw].load)
7579
7580 # out2in
7581 data = "A" * 4 + "B" * 16 + "C" * 3
7582 pkts = self.create_stream_frag(self.pg1,
7583 self.nat_addr,
7584 20,
7585 self.tcp_port_out,
7586 data)
7587 pkts.reverse()
7588 self.pg1.add_stream(pkts)
7589 self.pg_enable_capture(self.pg_interfaces)
7590 self.pg_start()
7591 frags = self.pg0.get_capture(len(pkts))
7592 src = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
7593 p = self.reass_frags_and_verify_ip6(frags, src, self.pg0.remote_ip6)
7594 self.assertEqual(p[TCP].sport, 20)
7595 self.assertEqual(p[TCP].dport, self.tcp_port_in)
7596 self.assertEqual(data, p[Raw].load)
7597
Matus Fabian0938dcf2017-11-08 01:59:38 -08007598 def test_interface_addr(self):
7599 """ Acquire NAT64 pool addresses from interface """
7600 self.vapi.nat64_add_interface_addr(self.pg4.sw_if_index)
7601
7602 # no address in NAT64 pool
7603 adresses = self.vapi.nat44_address_dump()
7604 self.assertEqual(0, len(adresses))
7605
7606 # configure interface address and check NAT64 address pool
7607 self.pg4.config_ip4()
7608 addresses = self.vapi.nat64_pool_addr_dump()
7609 self.assertEqual(len(addresses), 1)
7610 self.assertEqual(addresses[0].address, self.pg4.local_ip4n)
7611
7612 # remove interface address and check NAT64 address pool
7613 self.pg4.unconfig_ip4()
7614 addresses = self.vapi.nat64_pool_addr_dump()
7615 self.assertEqual(0, len(adresses))
7616
Matus Fabiana431ad12018-01-04 04:03:14 -08007617 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
7618 def test_ipfix_max_bibs_sessions(self):
7619 """ IPFIX logging maximum session and BIB entries exceeded """
7620 max_bibs = 1280
7621 max_sessions = 2560
7622 remote_host_ip6 = self.compose_ip6(self.pg1.remote_ip4,
7623 '64:ff9b::',
7624 96)
7625
7626 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7627 self.nat_addr_n)
7628 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7629 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7630
7631 pkts = []
7632 src = ""
7633 for i in range(0, max_bibs):
7634 src = "fd01:aa::%x" % (i)
7635 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7636 IPv6(src=src, dst=remote_host_ip6) /
7637 TCP(sport=12345, dport=80))
7638 pkts.append(p)
7639 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7640 IPv6(src=src, dst=remote_host_ip6) /
7641 TCP(sport=12345, dport=22))
7642 pkts.append(p)
7643 self.pg0.add_stream(pkts)
7644 self.pg_enable_capture(self.pg_interfaces)
7645 self.pg_start()
7646 self.pg1.get_capture(max_sessions)
7647
7648 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
7649 src_address=self.pg3.local_ip4n,
7650 path_mtu=512,
7651 template_interval=10)
7652 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
7653 src_port=self.ipfix_src_port)
7654
7655 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7656 IPv6(src=src, dst=remote_host_ip6) /
7657 TCP(sport=12345, dport=25))
7658 self.pg0.add_stream(p)
7659 self.pg_enable_capture(self.pg_interfaces)
7660 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07007661 self.pg1.assert_nothing_captured()
7662 sleep(1)
Matus Fabiana431ad12018-01-04 04:03:14 -08007663 self.vapi.cli("ipfix flush") # FIXME this should be an API call
7664 capture = self.pg3.get_capture(9)
7665 ipfix = IPFIXDecoder()
7666 # first load template
7667 for p in capture:
7668 self.assertTrue(p.haslayer(IPFIX))
7669 self.assertEqual(p[IP].src, self.pg3.local_ip4)
7670 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
7671 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
7672 self.assertEqual(p[UDP].dport, 4739)
7673 self.assertEqual(p[IPFIX].observationDomainID,
7674 self.ipfix_domain_id)
7675 if p.haslayer(Template):
7676 ipfix.add_template(p.getlayer(Template))
7677 # verify events in data set
7678 for p in capture:
7679 if p.haslayer(Data):
7680 data = ipfix.decode_data_set(p.getlayer(Set))
7681 self.verify_ipfix_max_sessions(data, max_sessions)
7682
7683 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7684 IPv6(src=self.pg0.remote_ip6, dst=remote_host_ip6) /
7685 TCP(sport=12345, dport=80))
7686 self.pg0.add_stream(p)
7687 self.pg_enable_capture(self.pg_interfaces)
7688 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07007689 self.pg1.assert_nothing_captured()
7690 sleep(1)
Matus Fabiana431ad12018-01-04 04:03:14 -08007691 self.vapi.cli("ipfix flush") # FIXME this should be an API call
7692 capture = self.pg3.get_capture(1)
7693 # verify events in data set
7694 for p in capture:
7695 self.assertTrue(p.haslayer(IPFIX))
7696 self.assertEqual(p[IP].src, self.pg3.local_ip4)
7697 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
7698 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
7699 self.assertEqual(p[UDP].dport, 4739)
7700 self.assertEqual(p[IPFIX].observationDomainID,
7701 self.ipfix_domain_id)
7702 if p.haslayer(Data):
7703 data = ipfix.decode_data_set(p.getlayer(Set))
7704 self.verify_ipfix_max_bibs(data, max_bibs)
7705
7706 def test_ipfix_max_frags(self):
7707 """ IPFIX logging maximum fragments pending reassembly exceeded """
7708 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7709 self.nat_addr_n)
7710 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7711 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
Matus Fabiana7f8b222018-09-05 06:01:55 -07007712 self.vapi.nat_set_reass(max_frag=1, is_ip6=1)
Matus Fabiana431ad12018-01-04 04:03:14 -08007713 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
7714 src_address=self.pg3.local_ip4n,
7715 path_mtu=512,
7716 template_interval=10)
7717 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
7718 src_port=self.ipfix_src_port)
7719
7720 data = 'a' * 200
7721 pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
7722 self.tcp_port_in, 20, data)
Matus Fabiana7f8b222018-09-05 06:01:55 -07007723 pkts.reverse()
7724 self.pg0.add_stream(pkts)
Matus Fabiana431ad12018-01-04 04:03:14 -08007725 self.pg_enable_capture(self.pg_interfaces)
7726 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07007727 self.pg1.assert_nothing_captured()
7728 sleep(1)
Matus Fabiana431ad12018-01-04 04:03:14 -08007729 self.vapi.cli("ipfix flush") # FIXME this should be an API call
7730 capture = self.pg3.get_capture(9)
7731 ipfix = IPFIXDecoder()
7732 # first load template
7733 for p in capture:
7734 self.assertTrue(p.haslayer(IPFIX))
7735 self.assertEqual(p[IP].src, self.pg3.local_ip4)
7736 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
7737 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
7738 self.assertEqual(p[UDP].dport, 4739)
7739 self.assertEqual(p[IPFIX].observationDomainID,
7740 self.ipfix_domain_id)
7741 if p.haslayer(Template):
7742 ipfix.add_template(p.getlayer(Template))
7743 # verify events in data set
7744 for p in capture:
7745 if p.haslayer(Data):
7746 data = ipfix.decode_data_set(p.getlayer(Set))
Matus Fabiana7f8b222018-09-05 06:01:55 -07007747 self.verify_ipfix_max_fragments_ip6(data, 1,
Matus Fabiana431ad12018-01-04 04:03:14 -08007748 self.pg0.remote_ip6n)
7749
7750 def test_ipfix_bib_ses(self):
7751 """ IPFIX logging NAT64 BIB/session create and delete events """
7752 self.tcp_port_in = random.randint(1025, 65535)
7753 remote_host_ip6 = self.compose_ip6(self.pg1.remote_ip4,
7754 '64:ff9b::',
7755 96)
7756
7757 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7758 self.nat_addr_n)
7759 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7760 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7761 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
7762 src_address=self.pg3.local_ip4n,
7763 path_mtu=512,
7764 template_interval=10)
7765 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
7766 src_port=self.ipfix_src_port)
7767
7768 # Create
7769 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7770 IPv6(src=self.pg0.remote_ip6, dst=remote_host_ip6) /
7771 TCP(sport=self.tcp_port_in, dport=25))
7772 self.pg0.add_stream(p)
7773 self.pg_enable_capture(self.pg_interfaces)
7774 self.pg_start()
7775 p = self.pg1.get_capture(1)
7776 self.tcp_port_out = p[0][TCP].sport
7777 self.vapi.cli("ipfix flush") # FIXME this should be an API call
7778 capture = self.pg3.get_capture(10)
7779 ipfix = IPFIXDecoder()
7780 # first load template
7781 for p in capture:
7782 self.assertTrue(p.haslayer(IPFIX))
7783 self.assertEqual(p[IP].src, self.pg3.local_ip4)
7784 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
7785 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
7786 self.assertEqual(p[UDP].dport, 4739)
7787 self.assertEqual(p[IPFIX].observationDomainID,
7788 self.ipfix_domain_id)
7789 if p.haslayer(Template):
7790 ipfix.add_template(p.getlayer(Template))
7791 # verify events in data set
7792 for p in capture:
7793 if p.haslayer(Data):
7794 data = ipfix.decode_data_set(p.getlayer(Set))
7795 if ord(data[0][230]) == 10:
7796 self.verify_ipfix_bib(data, 1, self.pg0.remote_ip6n)
7797 elif ord(data[0][230]) == 6:
7798 self.verify_ipfix_nat64_ses(data,
7799 1,
7800 self.pg0.remote_ip6n,
7801 self.pg1.remote_ip4,
7802 25)
7803 else:
7804 self.logger.error(ppp("Unexpected or invalid packet: ", p))
7805
7806 # Delete
7807 self.pg_enable_capture(self.pg_interfaces)
7808 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7809 self.nat_addr_n,
7810 is_add=0)
7811 self.vapi.cli("ipfix flush") # FIXME this should be an API call
7812 capture = self.pg3.get_capture(2)
7813 # verify events in data set
7814 for p in capture:
7815 self.assertTrue(p.haslayer(IPFIX))
7816 self.assertEqual(p[IP].src, self.pg3.local_ip4)
7817 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
7818 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
7819 self.assertEqual(p[UDP].dport, 4739)
7820 self.assertEqual(p[IPFIX].observationDomainID,
7821 self.ipfix_domain_id)
7822 if p.haslayer(Data):
7823 data = ipfix.decode_data_set(p.getlayer(Set))
7824 if ord(data[0][230]) == 11:
7825 self.verify_ipfix_bib(data, 0, self.pg0.remote_ip6n)
7826 elif ord(data[0][230]) == 7:
7827 self.verify_ipfix_nat64_ses(data,
7828 0,
7829 self.pg0.remote_ip6n,
7830 self.pg1.remote_ip4,
7831 25)
7832 else:
7833 self.logger.error(ppp("Unexpected or invalid packet: ", p))
7834
Matus Fabianad1f3e12018-11-28 21:26:34 -08007835 def test_syslog_sess(self):
7836 """ Test syslog session creation and deletion """
7837 self.tcp_port_in = random.randint(1025, 65535)
7838 remote_host_ip6 = self.compose_ip6(self.pg1.remote_ip4,
7839 '64:ff9b::',
7840 96)
7841
7842 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7843 self.nat_addr_n)
7844 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7845 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7846 self.vapi.syslog_set_filter(SYSLOG_SEVERITY.INFO)
7847 self.vapi.syslog_set_sender(self.pg3.remote_ip4n, self.pg3.local_ip4n)
7848
7849 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7850 IPv6(src=self.pg0.remote_ip6, dst=remote_host_ip6) /
7851 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port))
7852 self.pg0.add_stream(p)
7853 self.pg_enable_capture(self.pg_interfaces)
7854 self.pg_start()
7855 p = self.pg1.get_capture(1)
7856 self.tcp_port_out = p[0][TCP].sport
7857 capture = self.pg3.get_capture(1)
7858 self.verify_syslog_sess(capture[0][Raw].load, is_ip6=True)
7859
7860 self.pg_enable_capture(self.pg_interfaces)
7861 self.pg_start()
7862 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7863 self.nat_addr_n,
7864 is_add=0)
7865 capture = self.pg3.get_capture(1)
7866 self.verify_syslog_sess(capture[0][Raw].load, False, True)
7867
Matus Fabian06596c52017-06-06 04:53:28 -07007868 def nat64_get_ses_num(self):
7869 """
7870 Return number of active NAT64 sessions.
7871 """
Matus Fabianab9a59c2017-08-16 05:37:36 -07007872 st = self.vapi.nat64_st_dump()
7873 return len(st)
Matus Fabian06596c52017-06-06 04:53:28 -07007874
7875 def clear_nat64(self):
7876 """
7877 Clear NAT64 configuration.
7878 """
Matus Fabiana431ad12018-01-04 04:03:14 -08007879 self.vapi.nat_ipfix(enable=0, src_port=self.ipfix_src_port,
7880 domain_id=self.ipfix_domain_id)
7881 self.ipfix_src_port = 4739
7882 self.ipfix_domain_id = 1
7883
Matus Fabianad1f3e12018-11-28 21:26:34 -08007884 self.vapi.syslog_set_filter(SYSLOG_SEVERITY.EMERG)
7885
Matus Fabian878c6462018-08-23 00:33:35 -07007886 self.vapi.nat_set_timeouts()
Matus Fabian06596c52017-06-06 04:53:28 -07007887
7888 interfaces = self.vapi.nat64_interface_dump()
7889 for intf in interfaces:
Matus Fabian36ea2d62017-10-24 04:13:49 -07007890 if intf.is_inside > 1:
7891 self.vapi.nat64_add_del_interface(intf.sw_if_index,
7892 0,
7893 is_add=0)
Matus Fabian06596c52017-06-06 04:53:28 -07007894 self.vapi.nat64_add_del_interface(intf.sw_if_index,
7895 intf.is_inside,
7896 is_add=0)
7897
Matus Fabiana431ad12018-01-04 04:03:14 -08007898 bib = self.vapi.nat64_bib_dump(255)
Matus Fabian06596c52017-06-06 04:53:28 -07007899 for bibe in bib:
7900 if bibe.is_static:
7901 self.vapi.nat64_add_del_static_bib(bibe.i_addr,
7902 bibe.o_addr,
7903 bibe.i_port,
7904 bibe.o_port,
7905 bibe.proto,
7906 bibe.vrf_id,
7907 is_add=0)
7908
7909 adresses = self.vapi.nat64_pool_addr_dump()
7910 for addr in adresses:
7911 self.vapi.nat64_add_del_pool_addr_range(addr.address,
7912 addr.address,
Matus Fabian029f3d22017-06-15 02:28:50 -07007913 vrf_id=addr.vrf_id,
Matus Fabian06596c52017-06-06 04:53:28 -07007914 is_add=0)
7915
Matus Fabian428dc912017-06-21 06:15:18 -07007916 prefixes = self.vapi.nat64_prefix_dump()
7917 for prefix in prefixes:
7918 self.vapi.nat64_add_del_prefix(prefix.prefix,
7919 prefix.prefix_len,
7920 vrf_id=prefix.vrf_id,
7921 is_add=0)
7922
Matus Fabian06596c52017-06-06 04:53:28 -07007923 def tearDown(self):
7924 super(TestNAT64, self).tearDown()
7925 if not self.vpp_dead:
7926 self.logger.info(self.vapi.cli("show nat64 pool"))
7927 self.logger.info(self.vapi.cli("show nat64 interfaces"))
Matus Fabian428dc912017-06-21 06:15:18 -07007928 self.logger.info(self.vapi.cli("show nat64 prefix"))
Matus Fabianab9a59c2017-08-16 05:37:36 -07007929 self.logger.info(self.vapi.cli("show nat64 bib all"))
7930 self.logger.info(self.vapi.cli("show nat64 session table all"))
Matus Fabianefcd1e92017-08-15 06:59:19 -07007931 self.logger.info(self.vapi.cli("show nat virtual-reassembly"))
Matus Fabian06596c52017-06-06 04:53:28 -07007932 self.clear_nat64()
7933
Matus Fabian8ebe6252017-11-06 05:04:53 -08007934
7935class TestDSlite(MethodHolder):
7936 """ DS-Lite Test Cases """
7937
7938 @classmethod
7939 def setUpClass(cls):
7940 super(TestDSlite, cls).setUpClass()
7941
7942 try:
7943 cls.nat_addr = '10.0.0.3'
7944 cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
7945
Matus Fabianad1f3e12018-11-28 21:26:34 -08007946 cls.create_pg_interfaces(range(3))
Matus Fabian8ebe6252017-11-06 05:04:53 -08007947 cls.pg0.admin_up()
7948 cls.pg0.config_ip4()
7949 cls.pg0.resolve_arp()
7950 cls.pg1.admin_up()
7951 cls.pg1.config_ip6()
7952 cls.pg1.generate_remote_hosts(2)
7953 cls.pg1.configure_ipv6_neighbors()
Matus Fabianad1f3e12018-11-28 21:26:34 -08007954 cls.pg2.admin_up()
7955 cls.pg2.config_ip4()
7956 cls.pg2.resolve_arp()
Matus Fabian8ebe6252017-11-06 05:04:53 -08007957
7958 except Exception:
7959 super(TestDSlite, cls).tearDownClass()
7960 raise
7961
Matus Fabianad1f3e12018-11-28 21:26:34 -08007962 def verify_syslog_apmadd(self, data, isaddr, isport, xsaddr, xsport,
7963 sv6enc, proto):
7964 message = data.decode('utf-8')
7965 try:
7966 message = SyslogMessage.parse(message)
7967 self.assertEqual(message.severity, SyslogSeverity.info)
7968 self.assertEqual(message.appname, 'NAT')
7969 self.assertEqual(message.msgid, 'APMADD')
7970 sd_params = message.sd.get('napmap')
7971 self.assertTrue(sd_params is not None)
7972 self.assertEqual(sd_params.get('IATYP'), 'IPv4')
7973 self.assertEqual(sd_params.get('ISADDR'), isaddr)
7974 self.assertEqual(sd_params.get('ISPORT'), "%d" % isport)
7975 self.assertEqual(sd_params.get('XATYP'), 'IPv4')
7976 self.assertEqual(sd_params.get('XSADDR'), xsaddr)
7977 self.assertEqual(sd_params.get('XSPORT'), "%d" % xsport)
7978 self.assertEqual(sd_params.get('PROTO'), "%d" % proto)
7979 self.assertTrue(sd_params.get('SSUBIX') is not None)
7980 self.assertEqual(sd_params.get('SV6ENC'), sv6enc)
7981 except ParseError as e:
7982 self.logger.error(e)
7983
Matus Fabian8ebe6252017-11-06 05:04:53 -08007984 def test_dslite(self):
7985 """ Test DS-Lite """
Matus Fabian69ce30d2018-08-22 01:27:10 -07007986 nat_config = self.vapi.nat_show_config()
7987 self.assertEqual(0, nat_config.dslite_ce)
7988
Matus Fabian8ebe6252017-11-06 05:04:53 -08007989 self.vapi.dslite_add_del_pool_addr_range(self.nat_addr_n,
7990 self.nat_addr_n)
7991 aftr_ip4 = '192.0.0.1'
7992 aftr_ip4_n = socket.inet_pton(socket.AF_INET, aftr_ip4)
7993 aftr_ip6 = '2001:db8:85a3::8a2e:370:1'
7994 aftr_ip6_n = socket.inet_pton(socket.AF_INET6, aftr_ip6)
7995 self.vapi.dslite_set_aftr_addr(aftr_ip6_n, aftr_ip4_n)
Matus Fabianad1f3e12018-11-28 21:26:34 -08007996 self.vapi.syslog_set_sender(self.pg2.remote_ip4n, self.pg2.local_ip4n)
Matus Fabian8ebe6252017-11-06 05:04:53 -08007997
7998 # UDP
7999 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8000 IPv6(dst=aftr_ip6, src=self.pg1.remote_hosts[0].ip6) /
8001 IP(dst=self.pg0.remote_ip4, src='192.168.1.1') /
8002 UDP(sport=20000, dport=10000))
8003 self.pg1.add_stream(p)
8004 self.pg_enable_capture(self.pg_interfaces)
8005 self.pg_start()
8006 capture = self.pg0.get_capture(1)
8007 capture = capture[0]
8008 self.assertFalse(capture.haslayer(IPv6))
8009 self.assertEqual(capture[IP].src, self.nat_addr)
8010 self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
8011 self.assertNotEqual(capture[UDP].sport, 20000)
8012 self.assertEqual(capture[UDP].dport, 10000)
Klement Sekerad81ae412018-05-16 10:52:54 +02008013 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08008014 out_port = capture[UDP].sport
Matus Fabianad1f3e12018-11-28 21:26:34 -08008015 capture = self.pg2.get_capture(1)
8016 self.verify_syslog_apmadd(capture[0][Raw].load, '192.168.1.1',
8017 20000, self.nat_addr, out_port,
8018 self.pg1.remote_hosts[0].ip6, IP_PROTOS.udp)
Matus Fabian8ebe6252017-11-06 05:04:53 -08008019
8020 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8021 IP(dst=self.nat_addr, src=self.pg0.remote_ip4) /
8022 UDP(sport=10000, dport=out_port))
8023 self.pg0.add_stream(p)
8024 self.pg_enable_capture(self.pg_interfaces)
8025 self.pg_start()
8026 capture = self.pg1.get_capture(1)
8027 capture = capture[0]
8028 self.assertEqual(capture[IPv6].src, aftr_ip6)
8029 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[0].ip6)
8030 self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
8031 self.assertEqual(capture[IP].dst, '192.168.1.1')
8032 self.assertEqual(capture[UDP].sport, 10000)
8033 self.assertEqual(capture[UDP].dport, 20000)
Klement Sekerad81ae412018-05-16 10:52:54 +02008034 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08008035
8036 # TCP
8037 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8038 IPv6(dst=aftr_ip6, src=self.pg1.remote_hosts[1].ip6) /
8039 IP(dst=self.pg0.remote_ip4, src='192.168.1.1') /
8040 TCP(sport=20001, dport=10001))
8041 self.pg1.add_stream(p)
8042 self.pg_enable_capture(self.pg_interfaces)
8043 self.pg_start()
8044 capture = self.pg0.get_capture(1)
8045 capture = capture[0]
8046 self.assertFalse(capture.haslayer(IPv6))
8047 self.assertEqual(capture[IP].src, self.nat_addr)
8048 self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
8049 self.assertNotEqual(capture[TCP].sport, 20001)
8050 self.assertEqual(capture[TCP].dport, 10001)
Klement Sekerad81ae412018-05-16 10:52:54 +02008051 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08008052 out_port = capture[TCP].sport
8053
8054 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8055 IP(dst=self.nat_addr, src=self.pg0.remote_ip4) /
8056 TCP(sport=10001, dport=out_port))
8057 self.pg0.add_stream(p)
8058 self.pg_enable_capture(self.pg_interfaces)
8059 self.pg_start()
8060 capture = self.pg1.get_capture(1)
8061 capture = capture[0]
8062 self.assertEqual(capture[IPv6].src, aftr_ip6)
8063 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[1].ip6)
8064 self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
8065 self.assertEqual(capture[IP].dst, '192.168.1.1')
8066 self.assertEqual(capture[TCP].sport, 10001)
8067 self.assertEqual(capture[TCP].dport, 20001)
Klement Sekerad81ae412018-05-16 10:52:54 +02008068 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08008069
8070 # ICMP
8071 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8072 IPv6(dst=aftr_ip6, src=self.pg1.remote_hosts[1].ip6) /
8073 IP(dst=self.pg0.remote_ip4, src='192.168.1.1') /
8074 ICMP(id=4000, type='echo-request'))
8075 self.pg1.add_stream(p)
8076 self.pg_enable_capture(self.pg_interfaces)
8077 self.pg_start()
8078 capture = self.pg0.get_capture(1)
8079 capture = capture[0]
8080 self.assertFalse(capture.haslayer(IPv6))
8081 self.assertEqual(capture[IP].src, self.nat_addr)
8082 self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
8083 self.assertNotEqual(capture[ICMP].id, 4000)
Klement Sekerad81ae412018-05-16 10:52:54 +02008084 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08008085 out_id = capture[ICMP].id
8086
8087 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8088 IP(dst=self.nat_addr, src=self.pg0.remote_ip4) /
8089 ICMP(id=out_id, type='echo-reply'))
8090 self.pg0.add_stream(p)
8091 self.pg_enable_capture(self.pg_interfaces)
8092 self.pg_start()
8093 capture = self.pg1.get_capture(1)
8094 capture = capture[0]
8095 self.assertEqual(capture[IPv6].src, aftr_ip6)
8096 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[1].ip6)
8097 self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
8098 self.assertEqual(capture[IP].dst, '192.168.1.1')
8099 self.assertEqual(capture[ICMP].id, 4000)
Klement Sekerad81ae412018-05-16 10:52:54 +02008100 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08008101
Matus Fabian331acc62017-12-08 03:38:51 -08008102 # ping DS-Lite AFTR tunnel endpoint address
8103 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8104 IPv6(src=self.pg1.remote_hosts[1].ip6, dst=aftr_ip6) /
8105 ICMPv6EchoRequest())
8106 self.pg1.add_stream(p)
8107 self.pg_enable_capture(self.pg_interfaces)
8108 self.pg_start()
8109 capture = self.pg1.get_capture(1)
Matus Fabian331acc62017-12-08 03:38:51 -08008110 capture = capture[0]
8111 self.assertEqual(capture[IPv6].src, aftr_ip6)
8112 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[1].ip6)
8113 self.assertTrue(capture.haslayer(ICMPv6EchoReply))
8114
Matus Fabian8ebe6252017-11-06 05:04:53 -08008115 def tearDown(self):
8116 super(TestDSlite, self).tearDown()
8117 if not self.vpp_dead:
8118 self.logger.info(self.vapi.cli("show dslite pool"))
8119 self.logger.info(
8120 self.vapi.cli("show dslite aftr-tunnel-endpoint-address"))
8121 self.logger.info(self.vapi.cli("show dslite sessions"))
8122
Juraj Slobodac5c6a332018-01-09 16:08:32 +01008123
8124class TestDSliteCE(MethodHolder):
8125 """ DS-Lite CE Test Cases """
8126
8127 @classmethod
8128 def setUpConstants(cls):
8129 super(TestDSliteCE, cls).setUpConstants()
8130 cls.vpp_cmdline.extend(["nat", "{", "dslite ce", "}"])
8131
8132 @classmethod
8133 def setUpClass(cls):
8134 super(TestDSliteCE, cls).setUpClass()
8135
8136 try:
8137 cls.create_pg_interfaces(range(2))
8138 cls.pg0.admin_up()
8139 cls.pg0.config_ip4()
8140 cls.pg0.resolve_arp()
8141 cls.pg1.admin_up()
8142 cls.pg1.config_ip6()
8143 cls.pg1.generate_remote_hosts(1)
8144 cls.pg1.configure_ipv6_neighbors()
8145
8146 except Exception:
8147 super(TestDSliteCE, cls).tearDownClass()
8148 raise
8149
8150 def test_dslite_ce(self):
8151 """ Test DS-Lite CE """
8152
Matus Fabian69ce30d2018-08-22 01:27:10 -07008153 nat_config = self.vapi.nat_show_config()
8154 self.assertEqual(1, nat_config.dslite_ce)
8155
Juraj Slobodac5c6a332018-01-09 16:08:32 +01008156 b4_ip4 = '192.0.0.2'
8157 b4_ip4_n = socket.inet_pton(socket.AF_INET, b4_ip4)
8158 b4_ip6 = '2001:db8:62aa::375e:f4c1:1'
8159 b4_ip6_n = socket.inet_pton(socket.AF_INET6, b4_ip6)
8160 self.vapi.dslite_set_b4_addr(b4_ip6_n, b4_ip4_n)
8161
8162 aftr_ip4 = '192.0.0.1'
8163 aftr_ip4_n = socket.inet_pton(socket.AF_INET, aftr_ip4)
8164 aftr_ip6 = '2001:db8:85a3::8a2e:370:1'
8165 aftr_ip6_n = socket.inet_pton(socket.AF_INET6, aftr_ip6)
8166 self.vapi.dslite_set_aftr_addr(aftr_ip6_n, aftr_ip4_n)
8167
8168 self.vapi.ip_add_del_route(dst_address=aftr_ip6_n,
8169 dst_address_length=128,
8170 next_hop_address=self.pg1.remote_ip6n,
8171 next_hop_sw_if_index=self.pg1.sw_if_index,
8172 is_ipv6=1)
8173
8174 # UDP encapsulation
8175 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8176 IP(dst=self.pg1.remote_ip4, src=self.pg0.remote_ip4) /
8177 UDP(sport=10000, dport=20000))
8178 self.pg0.add_stream(p)
8179 self.pg_enable_capture(self.pg_interfaces)
8180 self.pg_start()
8181 capture = self.pg1.get_capture(1)
8182 capture = capture[0]
8183 self.assertEqual(capture[IPv6].src, b4_ip6)
8184 self.assertEqual(capture[IPv6].dst, aftr_ip6)
8185 self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
8186 self.assertEqual(capture[IP].dst, self.pg1.remote_ip4)
8187 self.assertEqual(capture[UDP].sport, 10000)
8188 self.assertEqual(capture[UDP].dport, 20000)
Klement Sekerad81ae412018-05-16 10:52:54 +02008189 self.assert_packet_checksums_valid(capture)
Juraj Slobodac5c6a332018-01-09 16:08:32 +01008190
8191 # UDP decapsulation
8192 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8193 IPv6(dst=b4_ip6, src=aftr_ip6) /
8194 IP(dst=self.pg0.remote_ip4, src=self.pg1.remote_ip4) /
8195 UDP(sport=20000, dport=10000))
8196 self.pg1.add_stream(p)
8197 self.pg_enable_capture(self.pg_interfaces)
8198 self.pg_start()
8199 capture = self.pg0.get_capture(1)
8200 capture = capture[0]
8201 self.assertFalse(capture.haslayer(IPv6))
8202 self.assertEqual(capture[IP].src, self.pg1.remote_ip4)
8203 self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
8204 self.assertEqual(capture[UDP].sport, 20000)
8205 self.assertEqual(capture[UDP].dport, 10000)
Klement Sekerad81ae412018-05-16 10:52:54 +02008206 self.assert_packet_checksums_valid(capture)
Juraj Slobodac5c6a332018-01-09 16:08:32 +01008207
8208 # ping DS-Lite B4 tunnel endpoint address
8209 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8210 IPv6(src=self.pg1.remote_hosts[0].ip6, dst=b4_ip6) /
8211 ICMPv6EchoRequest())
8212 self.pg1.add_stream(p)
8213 self.pg_enable_capture(self.pg_interfaces)
8214 self.pg_start()
8215 capture = self.pg1.get_capture(1)
Juraj Slobodac5c6a332018-01-09 16:08:32 +01008216 capture = capture[0]
8217 self.assertEqual(capture[IPv6].src, b4_ip6)
8218 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[0].ip6)
8219 self.assertTrue(capture.haslayer(ICMPv6EchoReply))
8220
8221 def tearDown(self):
8222 super(TestDSliteCE, self).tearDown()
8223 if not self.vpp_dead:
8224 self.logger.info(
8225 self.vapi.cli("show dslite aftr-tunnel-endpoint-address"))
8226 self.logger.info(
8227 self.vapi.cli("show dslite b4-tunnel-endpoint-address"))
8228
Matus Fabianf2a23cc2018-01-22 03:41:53 -08008229
8230class TestNAT66(MethodHolder):
8231 """ NAT66 Test Cases """
8232
8233 @classmethod
8234 def setUpClass(cls):
8235 super(TestNAT66, cls).setUpClass()
8236
8237 try:
8238 cls.nat_addr = 'fd01:ff::2'
8239 cls.nat_addr_n = socket.inet_pton(socket.AF_INET6, cls.nat_addr)
8240
8241 cls.create_pg_interfaces(range(2))
8242 cls.interfaces = list(cls.pg_interfaces)
8243
8244 for i in cls.interfaces:
8245 i.admin_up()
8246 i.config_ip6()
8247 i.configure_ipv6_neighbors()
8248
8249 except Exception:
8250 super(TestNAT66, cls).tearDownClass()
8251 raise
8252
8253 def test_static(self):
8254 """ 1:1 NAT66 test """
8255 self.vapi.nat66_add_del_interface(self.pg0.sw_if_index)
8256 self.vapi.nat66_add_del_interface(self.pg1.sw_if_index, is_inside=0)
8257 self.vapi.nat66_add_del_static_mapping(self.pg0.remote_ip6n,
8258 self.nat_addr_n)
8259
8260 # in2out
8261 pkts = []
8262 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8263 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
8264 TCP())
8265 pkts.append(p)
8266 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8267 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
8268 UDP())
8269 pkts.append(p)
8270 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8271 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
8272 ICMPv6EchoRequest())
8273 pkts.append(p)
8274 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8275 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
8276 GRE() / IP() / TCP())
8277 pkts.append(p)
8278 self.pg0.add_stream(pkts)
8279 self.pg_enable_capture(self.pg_interfaces)
8280 self.pg_start()
8281 capture = self.pg1.get_capture(len(pkts))
8282 for packet in capture:
8283 try:
8284 self.assertEqual(packet[IPv6].src, self.nat_addr)
8285 self.assertEqual(packet[IPv6].dst, self.pg1.remote_ip6)
Klement Sekerad81ae412018-05-16 10:52:54 +02008286 self.assert_packet_checksums_valid(packet)
Matus Fabianf2a23cc2018-01-22 03:41:53 -08008287 except:
8288 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8289 raise
8290
8291 # out2in
8292 pkts = []
8293 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8294 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
8295 TCP())
8296 pkts.append(p)
8297 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8298 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
8299 UDP())
8300 pkts.append(p)
8301 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8302 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
8303 ICMPv6EchoReply())
8304 pkts.append(p)
8305 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8306 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
8307 GRE() / IP() / TCP())
8308 pkts.append(p)
8309 self.pg1.add_stream(pkts)
8310 self.pg_enable_capture(self.pg_interfaces)
8311 self.pg_start()
8312 capture = self.pg0.get_capture(len(pkts))
8313 for packet in capture:
8314 try:
8315 self.assertEqual(packet[IPv6].src, self.pg1.remote_ip6)
8316 self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
Klement Sekerad81ae412018-05-16 10:52:54 +02008317 self.assert_packet_checksums_valid(packet)
Matus Fabianf2a23cc2018-01-22 03:41:53 -08008318 except:
8319 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8320 raise
8321
8322 sm = self.vapi.nat66_static_mapping_dump()
8323 self.assertEqual(len(sm), 1)
8324 self.assertEqual(sm[0].total_pkts, 8)
8325
Juraj Sloboda9341e342018-04-13 12:00:46 +02008326 def test_check_no_translate(self):
8327 """ NAT66 translate only when egress interface is outside interface """
8328 self.vapi.nat66_add_del_interface(self.pg0.sw_if_index)
8329 self.vapi.nat66_add_del_interface(self.pg1.sw_if_index)
8330 self.vapi.nat66_add_del_static_mapping(self.pg0.remote_ip6n,
8331 self.nat_addr_n)
8332
8333 # in2out
8334 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8335 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
8336 UDP())
8337 self.pg0.add_stream([p])
8338 self.pg_enable_capture(self.pg_interfaces)
8339 self.pg_start()
8340 capture = self.pg1.get_capture(1)
8341 packet = capture[0]
8342 try:
8343 self.assertEqual(packet[IPv6].src, self.pg0.remote_ip6)
8344 self.assertEqual(packet[IPv6].dst, self.pg1.remote_ip6)
8345 except:
8346 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8347 raise
8348
Matus Fabianf2a23cc2018-01-22 03:41:53 -08008349 def clear_nat66(self):
8350 """
8351 Clear NAT66 configuration.
8352 """
8353 interfaces = self.vapi.nat66_interface_dump()
8354 for intf in interfaces:
8355 self.vapi.nat66_add_del_interface(intf.sw_if_index,
8356 intf.is_inside,
8357 is_add=0)
8358
8359 static_mappings = self.vapi.nat66_static_mapping_dump()
8360 for sm in static_mappings:
8361 self.vapi.nat66_add_del_static_mapping(sm.local_ip_address,
8362 sm.external_ip_address,
8363 sm.vrf_id,
8364 is_add=0)
8365
8366 def tearDown(self):
8367 super(TestNAT66, self).tearDown()
8368 if not self.vpp_dead:
8369 self.logger.info(self.vapi.cli("show nat66 interfaces"))
8370 self.logger.info(self.vapi.cli("show nat66 static mappings"))
8371 self.clear_nat66()
8372
Klement Sekerad81ae412018-05-16 10:52:54 +02008373
Matus Fabiande886752016-12-07 03:38:19 -08008374if __name__ == '__main__':
8375 unittest.main(testRunner=VppTestRunner)