blob: 160890a078eece1baed58dc26903d4d9701d0de2 [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
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07009
10import scapy.compat
Matus Fabiande886752016-12-07 03:38:19 -080011from scapy.layers.inet import IP, TCP, UDP, ICMP
Juraj Slobodab33f4132017-02-08 23:54:21 -080012from scapy.layers.inet import IPerror, TCPerror, UDPerror, ICMPerror
Juraj Slobodac746a152018-07-09 02:36:37 +020013from scapy.layers.inet6 import IPv6, ICMPv6EchoRequest, ICMPv6EchoReply, \
Paul Vinciguerra978aa642018-11-24 22:19:12 -080014 ICMPv6ND_NS, ICMPv6ND_NA, ICMPv6NDOptDstLLAddr, fragment6
Matus Fabianefcd1e92017-08-15 06:59:19 -070015from scapy.layers.inet6 import ICMPv6DestUnreach, IPerror6, IPv6ExtHdrFragment
Matus Fabian328dbc82017-06-19 04:28:04 -070016from scapy.layers.l2 import Ether, ARP, GRE
Matus Fabianeea28d72017-01-13 04:15:54 -080017from scapy.data import IP_PROTOS
Matus Fabianefcd1e92017-08-15 06:59:19 -070018from scapy.packet import bind_layers, Raw
Klement Sekera9225dee2016-12-12 08:36:58 +010019from util import ppp
Matus Fabianeea28d72017-01-13 04:15:54 -080020from ipfix import IPFIX, Set, Template, Data, IPFIXDecoder
Martin Gálik977c1cb2017-03-30 23:21:51 -070021from time import sleep
Matus Fabian704018c2017-09-04 02:17:18 -070022from util import ip4_range
Ole Troan8006c6a2018-12-17 12:02:26 +010023from vpp_papi import mac_pton
Matus Fabianad1f3e12018-11-28 21:26:34 -080024from syslog_rfc5424_parser import SyslogMessage, ParseError
25from syslog_rfc5424_parser.constants import SyslogFacility, SyslogSeverity
26from vpp_papi_provider import SYSLOG_SEVERITY
Ole Troan7f991832018-12-06 17:35:12 +010027from io import BytesIO
Neale Ranns37029302018-08-10 05:30:06 -070028from vpp_papi import VppEnum
Matus Fabian34931eb2019-02-26 09:05:23 -080029from scapy.all import bind_layers, Packet, ByteEnumField, ShortField, \
30 IPField, IntField, LongField, XByteField, FlagsField, FieldLenField, \
31 PacketListField
32
33
34# NAT HA protocol event data
35class Event(Packet):
36 name = "Event"
37 fields_desc = [ByteEnumField("event_type", None,
38 {1: "add", 2: "del", 3: "refresh"}),
39 ByteEnumField("protocol", None,
40 {0: "udp", 1: "tcp", 2: "icmp"}),
41 ShortField("flags", 0),
42 IPField("in_addr", None),
43 IPField("out_addr", None),
44 ShortField("in_port", None),
45 ShortField("out_port", None),
46 IPField("eh_addr", None),
47 IPField("ehn_addr", None),
48 ShortField("eh_port", None),
49 ShortField("ehn_port", None),
50 IntField("fib_index", None),
51 IntField("total_pkts", 0),
52 LongField("total_bytes", 0)]
53
54 def extract_padding(self, s):
55 return "", s
56
57
58# NAT HA protocol header
59class HANATStateSync(Packet):
60 name = "HA NAT state sync"
61 fields_desc = [XByteField("version", 1),
62 FlagsField("flags", 0, 8, ['ACK']),
63 FieldLenField("count", None, count_of="events"),
64 IntField("sequence_number", 1),
65 IntField("thread_index", 0),
66 PacketListField("events", [], Event,
Ole Troan9a475372019-03-05 16:58:24 +010067 count_from=lambda pkt: pkt.count)]
Matus Fabiande886752016-12-07 03:38:19 -080068
69
Martin Gálikd7f75cd2017-03-27 06:02:47 -070070class MethodHolder(VppTestCase):
Matus Fabian2ba92e32017-08-21 07:05:03 -070071 """ NAT create capture and verify method holder """
Matus Fabiande886752016-12-07 03:38:19 -080072
Matus Fabiana6110b62018-06-13 05:39:07 -070073 def clear_nat44(self):
74 """
75 Clear NAT44 configuration.
76 """
77 if hasattr(self, 'pg7') and hasattr(self, 'pg8'):
78 # I found no elegant way to do this
79 self.vapi.ip_add_del_route(
80 dst_address=self.pg7.remote_ip4n,
81 dst_address_length=32,
82 next_hop_address=self.pg7.remote_ip4n,
83 next_hop_sw_if_index=self.pg7.sw_if_index,
84 is_add=0)
85 self.vapi.ip_add_del_route(
86 dst_address=self.pg8.remote_ip4n,
87 dst_address_length=32,
88 next_hop_address=self.pg8.remote_ip4n,
89 next_hop_sw_if_index=self.pg8.sw_if_index,
90 is_add=0)
91
92 for intf in [self.pg7, self.pg8]:
Neale Ranns37029302018-08-10 05:30:06 -070093 self.vapi.ip_neighbor_add_del(
94 intf.sw_if_index,
95 intf.remote_mac,
96 intf.remote_ip4,
97 flags=(VppEnum.vl_api_ip_neighbor_flags_t.
98 IP_API_NEIGHBOR_FLAG_STATIC),
99 is_add=0)
Matus Fabiana6110b62018-06-13 05:39:07 -0700100
101 if self.pg7.has_ip4_config:
102 self.pg7.unconfig_ip4()
103
104 self.vapi.nat44_forwarding_enable_disable(0)
105
106 interfaces = self.vapi.nat44_interface_addr_dump()
107 for intf in interfaces:
Ole Troane1ade682019-03-04 23:55:43 +0100108 self.vapi.nat44_add_del_interface_addr(intf.sw_if_index,
109 twice_nat=intf.twice_nat,
110 is_add=0)
Matus Fabiana6110b62018-06-13 05:39:07 -0700111
Ole Troane1ade682019-03-04 23:55:43 +0100112 self.vapi.nat_ipfix_enable_disable(enable=0,
113 src_port=self.ipfix_src_port,
114 domain_id=self.ipfix_domain_id)
Matus Fabiana6110b62018-06-13 05:39:07 -0700115 self.ipfix_src_port = 4739
116 self.ipfix_domain_id = 1
117
Matus Fabianad1f3e12018-11-28 21:26:34 -0800118 self.vapi.syslog_set_filter(SYSLOG_SEVERITY.EMERG)
119
Matus Fabian34931eb2019-02-26 09:05:23 -0800120 self.vapi.nat_ha_set_listener('0.0.0.0', 0)
121 self.vapi.nat_ha_set_failover('0.0.0.0', 0)
122
Matus Fabiana6110b62018-06-13 05:39:07 -0700123 interfaces = self.vapi.nat44_interface_dump()
124 for intf in interfaces:
125 if intf.is_inside > 1:
126 self.vapi.nat44_interface_add_del_feature(intf.sw_if_index,
127 0,
128 is_add=0)
129 self.vapi.nat44_interface_add_del_feature(intf.sw_if_index,
130 intf.is_inside,
131 is_add=0)
132
133 interfaces = self.vapi.nat44_interface_output_feature_dump()
134 for intf in interfaces:
135 self.vapi.nat44_interface_add_del_output_feature(intf.sw_if_index,
136 intf.is_inside,
137 is_add=0)
138
139 static_mappings = self.vapi.nat44_static_mapping_dump()
140 for sm in static_mappings:
141 self.vapi.nat44_add_del_static_mapping(
142 sm.local_ip_address,
143 sm.external_ip_address,
144 local_port=sm.local_port,
145 external_port=sm.external_port,
146 addr_only=sm.addr_only,
147 vrf_id=sm.vrf_id,
148 protocol=sm.protocol,
149 twice_nat=sm.twice_nat,
150 self_twice_nat=sm.self_twice_nat,
151 out2in_only=sm.out2in_only,
152 tag=sm.tag,
153 external_sw_if_index=sm.external_sw_if_index,
154 is_add=0)
155
156 lb_static_mappings = self.vapi.nat44_lb_static_mapping_dump()
157 for lb_sm in lb_static_mappings:
158 self.vapi.nat44_add_del_lb_static_mapping(
159 lb_sm.external_addr,
160 lb_sm.external_port,
161 lb_sm.protocol,
Matus Fabiana6110b62018-06-13 05:39:07 -0700162 twice_nat=lb_sm.twice_nat,
163 self_twice_nat=lb_sm.self_twice_nat,
164 out2in_only=lb_sm.out2in_only,
165 tag=lb_sm.tag,
166 is_add=0,
167 local_num=0,
168 locals=[])
169
170 identity_mappings = self.vapi.nat44_identity_mapping_dump()
171 for id_m in identity_mappings:
172 self.vapi.nat44_add_del_identity_mapping(
173 addr_only=id_m.addr_only,
174 ip=id_m.ip_address,
175 port=id_m.port,
176 sw_if_index=id_m.sw_if_index,
177 vrf_id=id_m.vrf_id,
178 protocol=id_m.protocol,
179 is_add=0)
180
181 adresses = self.vapi.nat44_address_dump()
182 for addr in adresses:
183 self.vapi.nat44_add_del_address_range(addr.ip_address,
184 addr.ip_address,
185 twice_nat=addr.twice_nat,
186 is_add=0)
187
188 self.vapi.nat_set_reass()
189 self.vapi.nat_set_reass(is_ip6=1)
Matus Fabian68ba8802018-08-08 05:52:47 -0700190 self.verify_no_nat44_user()
Matus Fabian878c6462018-08-23 00:33:35 -0700191 self.vapi.nat_set_timeouts()
Matus Fabian5d28c7a2018-09-04 03:55:45 -0700192 self.vapi.nat_set_addr_and_port_alloc_alg()
Matus Fabianbb4e0222018-09-13 02:36:25 -0700193 self.vapi.nat_set_mss_clamping()
Matus Fabiana6110b62018-06-13 05:39:07 -0700194
195 def nat44_add_static_mapping(self, local_ip, external_ip='0.0.0.0',
196 local_port=0, external_port=0, vrf_id=0,
197 is_add=1, external_sw_if_index=0xFFFFFFFF,
198 proto=0, twice_nat=0, self_twice_nat=0,
199 out2in_only=0, tag=""):
200 """
201 Add/delete NAT44 static mapping
202
203 :param local_ip: Local IP address
204 :param external_ip: External IP address
205 :param local_port: Local port number (Optional)
206 :param external_port: External port number (Optional)
207 :param vrf_id: VRF ID (Default 0)
208 :param is_add: 1 if add, 0 if delete (Default add)
209 :param external_sw_if_index: External interface instead of IP address
210 :param proto: IP protocol (Mandatory if port specified)
211 :param twice_nat: 1 if translate external host address and port
212 :param self_twice_nat: 1 if translate external host address and port
213 whenever external host address equals
214 local address of internal host
215 :param out2in_only: if 1 rule is matching only out2in direction
216 :param tag: Opaque string tag
217 """
218 addr_only = 1
219 if local_port and external_port:
220 addr_only = 0
221 l_ip = socket.inet_pton(socket.AF_INET, local_ip)
222 e_ip = socket.inet_pton(socket.AF_INET, external_ip)
223 self.vapi.nat44_add_del_static_mapping(
224 l_ip,
225 e_ip,
226 external_sw_if_index,
227 local_port,
228 external_port,
229 addr_only,
230 vrf_id,
231 proto,
232 twice_nat,
233 self_twice_nat,
234 out2in_only,
235 tag,
236 is_add)
237
238 def nat44_add_address(self, ip, is_add=1, vrf_id=0xFFFFFFFF, twice_nat=0):
239 """
240 Add/delete NAT44 address
241
242 :param ip: IP address
243 :param is_add: 1 if add, 0 if delete (Default add)
244 :param twice_nat: twice NAT address for extenal hosts
245 """
246 nat_addr = socket.inet_pton(socket.AF_INET, ip)
247 self.vapi.nat44_add_del_address_range(nat_addr, nat_addr, is_add,
248 vrf_id=vrf_id,
249 twice_nat=twice_nat)
250
Juraj Slobodacba69362017-12-19 02:09:32 +0100251 def create_stream_in(self, in_if, out_if, dst_ip=None, ttl=64):
Matus Fabiande886752016-12-07 03:38:19 -0800252 """
253 Create packet stream for inside network
254
255 :param in_if: Inside interface
256 :param out_if: Outside interface
Juraj Slobodacba69362017-12-19 02:09:32 +0100257 :param dst_ip: Destination address
Juraj Slobodab33f4132017-02-08 23:54:21 -0800258 :param ttl: TTL of generated packets
Matus Fabiande886752016-12-07 03:38:19 -0800259 """
Juraj Slobodacba69362017-12-19 02:09:32 +0100260 if dst_ip is None:
261 dst_ip = out_if.remote_ip4
262
Matus Fabiande886752016-12-07 03:38:19 -0800263 pkts = []
264 # TCP
265 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
Juraj Slobodacba69362017-12-19 02:09:32 +0100266 IP(src=in_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Matus Fabian06596c52017-06-06 04:53:28 -0700267 TCP(sport=self.tcp_port_in, dport=20))
Matus Fabiande886752016-12-07 03:38:19 -0800268 pkts.append(p)
269
270 # UDP
271 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
Juraj Slobodacba69362017-12-19 02:09:32 +0100272 IP(src=in_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Matus Fabian06596c52017-06-06 04:53:28 -0700273 UDP(sport=self.udp_port_in, dport=20))
Matus Fabiande886752016-12-07 03:38:19 -0800274 pkts.append(p)
275
276 # ICMP
277 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
Juraj Slobodacba69362017-12-19 02:09:32 +0100278 IP(src=in_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Matus Fabiande886752016-12-07 03:38:19 -0800279 ICMP(id=self.icmp_id_in, type='echo-request'))
280 pkts.append(p)
281
282 return pkts
283
Matus Fabian428dc912017-06-21 06:15:18 -0700284 def compose_ip6(self, ip4, pref, plen):
285 """
286 Compose IPv4-embedded IPv6 addresses
287
288 :param ip4: IPv4 address
289 :param pref: IPv6 prefix
290 :param plen: IPv6 prefix length
291 :returns: IPv4-embedded IPv6 addresses
292 """
293 pref_n = list(socket.inet_pton(socket.AF_INET6, pref))
294 ip4_n = list(socket.inet_pton(socket.AF_INET, ip4))
295 if plen == 32:
296 pref_n[4] = ip4_n[0]
297 pref_n[5] = ip4_n[1]
298 pref_n[6] = ip4_n[2]
299 pref_n[7] = ip4_n[3]
300 elif plen == 40:
301 pref_n[5] = ip4_n[0]
302 pref_n[6] = ip4_n[1]
303 pref_n[7] = ip4_n[2]
304 pref_n[9] = ip4_n[3]
305 elif plen == 48:
306 pref_n[6] = ip4_n[0]
307 pref_n[7] = ip4_n[1]
308 pref_n[9] = ip4_n[2]
309 pref_n[10] = ip4_n[3]
310 elif plen == 56:
311 pref_n[7] = ip4_n[0]
312 pref_n[9] = ip4_n[1]
313 pref_n[10] = ip4_n[2]
314 pref_n[11] = ip4_n[3]
315 elif plen == 64:
316 pref_n[9] = ip4_n[0]
317 pref_n[10] = ip4_n[1]
318 pref_n[11] = ip4_n[2]
319 pref_n[12] = ip4_n[3]
320 elif plen == 96:
321 pref_n[12] = ip4_n[0]
322 pref_n[13] = ip4_n[1]
323 pref_n[14] = ip4_n[2]
324 pref_n[15] = ip4_n[3]
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700325 packed_pref_n = b''.join([scapy.compat.chb(x) for x in pref_n])
326 return socket.inet_ntop(socket.AF_INET6, packed_pref_n)
Matus Fabian428dc912017-06-21 06:15:18 -0700327
Juraj Slobodacba69362017-12-19 02:09:32 +0100328 def extract_ip4(self, ip6, plen):
329 """
330 Extract IPv4 address embedded in IPv6 addresses
331
332 :param ip6: IPv6 address
333 :param plen: IPv6 prefix length
334 :returns: extracted IPv4 address
335 """
336 ip6_n = list(socket.inet_pton(socket.AF_INET6, ip6))
337 ip4_n = [None] * 4
338 if plen == 32:
339 ip4_n[0] = ip6_n[4]
340 ip4_n[1] = ip6_n[5]
341 ip4_n[2] = ip6_n[6]
342 ip4_n[3] = ip6_n[7]
343 elif plen == 40:
344 ip4_n[0] = ip6_n[5]
345 ip4_n[1] = ip6_n[6]
346 ip4_n[2] = ip6_n[7]
347 ip4_n[3] = ip6_n[9]
348 elif plen == 48:
349 ip4_n[0] = ip6_n[6]
350 ip4_n[1] = ip6_n[7]
351 ip4_n[2] = ip6_n[9]
352 ip4_n[3] = ip6_n[10]
353 elif plen == 56:
354 ip4_n[0] = ip6_n[7]
355 ip4_n[1] = ip6_n[9]
356 ip4_n[2] = ip6_n[10]
357 ip4_n[3] = ip6_n[11]
358 elif plen == 64:
359 ip4_n[0] = ip6_n[9]
360 ip4_n[1] = ip6_n[10]
361 ip4_n[2] = ip6_n[11]
362 ip4_n[3] = ip6_n[12]
363 elif plen == 96:
364 ip4_n[0] = ip6_n[12]
365 ip4_n[1] = ip6_n[13]
366 ip4_n[2] = ip6_n[14]
367 ip4_n[3] = ip6_n[15]
368 return socket.inet_ntop(socket.AF_INET, ''.join(ip4_n))
369
Matus Fabian428dc912017-06-21 06:15:18 -0700370 def create_stream_in_ip6(self, in_if, out_if, hlim=64, pref=None, plen=0):
Matus Fabian06596c52017-06-06 04:53:28 -0700371 """
372 Create IPv6 packet stream for inside network
373
374 :param in_if: Inside interface
375 :param out_if: Outside interface
376 :param ttl: Hop Limit of generated packets
Matus Fabian428dc912017-06-21 06:15:18 -0700377 :param pref: NAT64 prefix
378 :param plen: NAT64 prefix length
Matus Fabian06596c52017-06-06 04:53:28 -0700379 """
380 pkts = []
Matus Fabian428dc912017-06-21 06:15:18 -0700381 if pref is None:
382 dst = ''.join(['64:ff9b::', out_if.remote_ip4])
383 else:
384 dst = self.compose_ip6(out_if.remote_ip4, pref, plen)
385
Matus Fabian06596c52017-06-06 04:53:28 -0700386 # TCP
387 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
388 IPv6(src=in_if.remote_ip6, dst=dst, hlim=hlim) /
389 TCP(sport=self.tcp_port_in, dport=20))
390 pkts.append(p)
391
392 # UDP
393 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
394 IPv6(src=in_if.remote_ip6, dst=dst, hlim=hlim) /
395 UDP(sport=self.udp_port_in, dport=20))
396 pkts.append(p)
397
398 # ICMP
399 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
400 IPv6(src=in_if.remote_ip6, dst=dst, hlim=hlim) /
401 ICMPv6EchoRequest(id=self.icmp_id_in))
402 pkts.append(p)
403
404 return pkts
405
Juraj Sloboda7b929792017-11-23 13:20:48 +0100406 def create_stream_out(self, out_if, dst_ip=None, ttl=64,
407 use_inside_ports=False):
Matus Fabiande886752016-12-07 03:38:19 -0800408 """
409 Create packet stream for outside network
410
411 :param out_if: Outside interface
Matus Fabian2ba92e32017-08-21 07:05:03 -0700412 :param dst_ip: Destination IP address (Default use global NAT address)
Juraj Slobodab33f4132017-02-08 23:54:21 -0800413 :param ttl: TTL of generated packets
Juraj Sloboda7b929792017-11-23 13:20:48 +0100414 :param use_inside_ports: Use inside NAT ports as destination ports
415 instead of outside ports
Matus Fabiande886752016-12-07 03:38:19 -0800416 """
417 if dst_ip is None:
Matus Fabian2ba92e32017-08-21 07:05:03 -0700418 dst_ip = self.nat_addr
Juraj Sloboda7b929792017-11-23 13:20:48 +0100419 if not use_inside_ports:
420 tcp_port = self.tcp_port_out
421 udp_port = self.udp_port_out
422 icmp_id = self.icmp_id_out
423 else:
424 tcp_port = self.tcp_port_in
425 udp_port = self.udp_port_in
426 icmp_id = self.icmp_id_in
Matus Fabiande886752016-12-07 03:38:19 -0800427 pkts = []
428 # TCP
429 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
Juraj Slobodab33f4132017-02-08 23:54:21 -0800430 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Juraj Sloboda7b929792017-11-23 13:20:48 +0100431 TCP(dport=tcp_port, sport=20))
Matus Fabiande886752016-12-07 03:38:19 -0800432 pkts.append(p)
433
434 # UDP
435 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
Juraj Slobodab33f4132017-02-08 23:54:21 -0800436 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Juraj Sloboda7b929792017-11-23 13:20:48 +0100437 UDP(dport=udp_port, sport=20))
Matus Fabiande886752016-12-07 03:38:19 -0800438 pkts.append(p)
439
440 # ICMP
441 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
Juraj Slobodab33f4132017-02-08 23:54:21 -0800442 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Juraj Sloboda7b929792017-11-23 13:20:48 +0100443 ICMP(id=icmp_id, type='echo-reply'))
Matus Fabiande886752016-12-07 03:38:19 -0800444 pkts.append(p)
445
446 return pkts
447
Juraj Slobodacba69362017-12-19 02:09:32 +0100448 def create_stream_out_ip6(self, out_if, src_ip, dst_ip, hl=64):
449 """
450 Create packet stream for outside network
451
452 :param out_if: Outside interface
453 :param dst_ip: Destination IP address (Default use global NAT address)
454 :param hl: HL of generated packets
455 """
456 pkts = []
457 # TCP
458 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
459 IPv6(src=src_ip, dst=dst_ip, hlim=hl) /
460 TCP(dport=self.tcp_port_out, sport=20))
461 pkts.append(p)
462
463 # UDP
464 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
465 IPv6(src=src_ip, dst=dst_ip, hlim=hl) /
466 UDP(dport=self.udp_port_out, sport=20))
467 pkts.append(p)
468
469 # ICMP
470 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
471 IPv6(src=src_ip, dst=dst_ip, hlim=hl) /
472 ICMPv6EchoReply(id=self.icmp_id_out))
473 pkts.append(p)
474
475 return pkts
476
Matus Fabiande886752016-12-07 03:38:19 -0800477 def verify_capture_out(self, capture, nat_ip=None, same_port=False,
Matus Fabian05ca4a32018-09-04 23:45:13 -0700478 dst_ip=None, is_ip6=False):
Matus Fabiande886752016-12-07 03:38:19 -0800479 """
480 Verify captured packets on outside network
481
482 :param capture: Captured packets
Matus Fabian2ba92e32017-08-21 07:05:03 -0700483 :param nat_ip: Translated IP address (Default use global NAT address)
Matus Fabiande886752016-12-07 03:38:19 -0800484 :param same_port: Sorce port number is not translated (Default False)
Matus Fabian06596c52017-06-06 04:53:28 -0700485 :param dst_ip: Destination IP address (Default do not verify)
Juraj Slobodacba69362017-12-19 02:09:32 +0100486 :param is_ip6: If L3 protocol is IPv6 (Default False)
Matus Fabiande886752016-12-07 03:38:19 -0800487 """
Juraj Slobodacba69362017-12-19 02:09:32 +0100488 if is_ip6:
489 IP46 = IPv6
490 ICMP46 = ICMPv6EchoRequest
491 else:
492 IP46 = IP
493 ICMP46 = ICMP
Matus Fabiande886752016-12-07 03:38:19 -0800494 if nat_ip is None:
Matus Fabian2ba92e32017-08-21 07:05:03 -0700495 nat_ip = self.nat_addr
Matus Fabiande886752016-12-07 03:38:19 -0800496 for packet in capture:
497 try:
Juraj Slobodacba69362017-12-19 02:09:32 +0100498 if not is_ip6:
Klement Sekerad81ae412018-05-16 10:52:54 +0200499 self.assert_packet_checksums_valid(packet)
Juraj Slobodacba69362017-12-19 02:09:32 +0100500 self.assertEqual(packet[IP46].src, nat_ip)
Matus Fabian06596c52017-06-06 04:53:28 -0700501 if dst_ip is not None:
Juraj Slobodacba69362017-12-19 02:09:32 +0100502 self.assertEqual(packet[IP46].dst, dst_ip)
Matus Fabiande886752016-12-07 03:38:19 -0800503 if packet.haslayer(TCP):
504 if same_port:
505 self.assertEqual(packet[TCP].sport, self.tcp_port_in)
506 else:
Klement Sekerada505f62017-01-04 12:58:53 +0100507 self.assertNotEqual(
508 packet[TCP].sport, self.tcp_port_in)
Matus Fabiande886752016-12-07 03:38:19 -0800509 self.tcp_port_out = packet[TCP].sport
Klement Sekerad81ae412018-05-16 10:52:54 +0200510 self.assert_packet_checksums_valid(packet)
Matus Fabiande886752016-12-07 03:38:19 -0800511 elif packet.haslayer(UDP):
512 if same_port:
513 self.assertEqual(packet[UDP].sport, self.udp_port_in)
514 else:
Klement Sekerada505f62017-01-04 12:58:53 +0100515 self.assertNotEqual(
516 packet[UDP].sport, self.udp_port_in)
Matus Fabiande886752016-12-07 03:38:19 -0800517 self.udp_port_out = packet[UDP].sport
518 else:
519 if same_port:
Juraj Slobodacba69362017-12-19 02:09:32 +0100520 self.assertEqual(packet[ICMP46].id, self.icmp_id_in)
Matus Fabiande886752016-12-07 03:38:19 -0800521 else:
Juraj Slobodacba69362017-12-19 02:09:32 +0100522 self.assertNotEqual(packet[ICMP46].id, self.icmp_id_in)
523 self.icmp_id_out = packet[ICMP46].id
Klement Sekerad81ae412018-05-16 10:52:54 +0200524 self.assert_packet_checksums_valid(packet)
Matus Fabiande886752016-12-07 03:38:19 -0800525 except:
Klement Sekera9225dee2016-12-12 08:36:58 +0100526 self.logger.error(ppp("Unexpected or invalid packet "
527 "(outside network):", packet))
Matus Fabiande886752016-12-07 03:38:19 -0800528 raise
529
Juraj Slobodacba69362017-12-19 02:09:32 +0100530 def verify_capture_out_ip6(self, capture, nat_ip, same_port=False,
Matus Fabian05ca4a32018-09-04 23:45:13 -0700531 dst_ip=None):
Juraj Slobodacba69362017-12-19 02:09:32 +0100532 """
533 Verify captured packets on outside network
534
535 :param capture: Captured packets
536 :param nat_ip: Translated IP address
537 :param same_port: Sorce port number is not translated (Default False)
Juraj Slobodacba69362017-12-19 02:09:32 +0100538 :param dst_ip: Destination IP address (Default do not verify)
539 """
Matus Fabian05ca4a32018-09-04 23:45:13 -0700540 return self.verify_capture_out(capture, nat_ip, same_port, dst_ip,
541 True)
Juraj Slobodacba69362017-12-19 02:09:32 +0100542
Matus Fabian05ca4a32018-09-04 23:45:13 -0700543 def verify_capture_in(self, capture, in_if):
Matus Fabiande886752016-12-07 03:38:19 -0800544 """
545 Verify captured packets on inside network
546
547 :param capture: Captured packets
548 :param in_if: Inside interface
Matus Fabiande886752016-12-07 03:38:19 -0800549 """
Matus Fabiande886752016-12-07 03:38:19 -0800550 for packet in capture:
551 try:
Klement Sekerad81ae412018-05-16 10:52:54 +0200552 self.assert_packet_checksums_valid(packet)
Matus Fabiande886752016-12-07 03:38:19 -0800553 self.assertEqual(packet[IP].dst, in_if.remote_ip4)
554 if packet.haslayer(TCP):
555 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
556 elif packet.haslayer(UDP):
557 self.assertEqual(packet[UDP].dport, self.udp_port_in)
558 else:
559 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
560 except:
Klement Sekera9225dee2016-12-12 08:36:58 +0100561 self.logger.error(ppp("Unexpected or invalid packet "
562 "(inside network):", packet))
Matus Fabiande886752016-12-07 03:38:19 -0800563 raise
564
Matus Fabian05ca4a32018-09-04 23:45:13 -0700565 def verify_capture_in_ip6(self, capture, src_ip, dst_ip):
Matus Fabian06596c52017-06-06 04:53:28 -0700566 """
567 Verify captured IPv6 packets on inside network
568
569 :param capture: Captured packets
570 :param src_ip: Source IP
571 :param dst_ip: Destination IP address
Matus Fabian06596c52017-06-06 04:53:28 -0700572 """
Matus Fabian06596c52017-06-06 04:53:28 -0700573 for packet in capture:
574 try:
575 self.assertEqual(packet[IPv6].src, src_ip)
576 self.assertEqual(packet[IPv6].dst, dst_ip)
Klement Sekerad81ae412018-05-16 10:52:54 +0200577 self.assert_packet_checksums_valid(packet)
Matus Fabian06596c52017-06-06 04:53:28 -0700578 if packet.haslayer(TCP):
579 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
580 elif packet.haslayer(UDP):
581 self.assertEqual(packet[UDP].dport, self.udp_port_in)
582 else:
583 self.assertEqual(packet[ICMPv6EchoReply].id,
584 self.icmp_id_in)
585 except:
586 self.logger.error(ppp("Unexpected or invalid packet "
587 "(inside network):", packet))
588 raise
589
Matus Fabian675a69c2017-01-18 01:46:01 -0800590 def verify_capture_no_translation(self, capture, ingress_if, egress_if):
591 """
592 Verify captured packet that don't have to be translated
593
594 :param capture: Captured packets
595 :param ingress_if: Ingress interface
596 :param egress_if: Egress interface
597 """
598 for packet in capture:
599 try:
600 self.assertEqual(packet[IP].src, ingress_if.remote_ip4)
601 self.assertEqual(packet[IP].dst, egress_if.remote_ip4)
602 if packet.haslayer(TCP):
603 self.assertEqual(packet[TCP].sport, self.tcp_port_in)
604 elif packet.haslayer(UDP):
605 self.assertEqual(packet[UDP].sport, self.udp_port_in)
606 else:
607 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
608 except:
609 self.logger.error(ppp("Unexpected or invalid packet "
610 "(inside network):", packet))
611 raise
612
Juraj Slobodab33f4132017-02-08 23:54:21 -0800613 def verify_capture_out_with_icmp_errors(self, capture, src_ip=None,
Matus Fabian05ca4a32018-09-04 23:45:13 -0700614 icmp_type=11):
Juraj Slobodab33f4132017-02-08 23:54:21 -0800615 """
616 Verify captured packets with ICMP errors on outside network
617
618 :param capture: Captured packets
619 :param src_ip: Translated IP address or IP address of VPP
Matus Fabian2ba92e32017-08-21 07:05:03 -0700620 (Default use global NAT address)
Juraj Slobodab33f4132017-02-08 23:54:21 -0800621 :param icmp_type: Type of error ICMP packet
622 we are expecting (Default 11)
623 """
624 if src_ip is None:
Matus Fabian2ba92e32017-08-21 07:05:03 -0700625 src_ip = self.nat_addr
Juraj Slobodab33f4132017-02-08 23:54:21 -0800626 for packet in capture:
627 try:
628 self.assertEqual(packet[IP].src, src_ip)
Paul Vinciguerra978aa642018-11-24 22:19:12 -0800629 self.assertEqual(packet.haslayer(ICMP), 1)
Juraj Slobodab33f4132017-02-08 23:54:21 -0800630 icmp = packet[ICMP]
631 self.assertEqual(icmp.type, icmp_type)
632 self.assertTrue(icmp.haslayer(IPerror))
633 inner_ip = icmp[IPerror]
634 if inner_ip.haslayer(TCPerror):
635 self.assertEqual(inner_ip[TCPerror].dport,
636 self.tcp_port_out)
637 elif inner_ip.haslayer(UDPerror):
638 self.assertEqual(inner_ip[UDPerror].dport,
639 self.udp_port_out)
640 else:
641 self.assertEqual(inner_ip[ICMPerror].id, self.icmp_id_out)
642 except:
643 self.logger.error(ppp("Unexpected or invalid packet "
644 "(outside network):", packet))
645 raise
646
Matus Fabian05ca4a32018-09-04 23:45:13 -0700647 def verify_capture_in_with_icmp_errors(self, capture, in_if, icmp_type=11):
Juraj Slobodab33f4132017-02-08 23:54:21 -0800648 """
649 Verify captured packets with ICMP errors on inside network
650
651 :param capture: Captured packets
652 :param in_if: Inside interface
Juraj Slobodab33f4132017-02-08 23:54:21 -0800653 :param icmp_type: Type of error ICMP packet
654 we are expecting (Default 11)
655 """
Juraj Slobodab33f4132017-02-08 23:54:21 -0800656 for packet in capture:
657 try:
658 self.assertEqual(packet[IP].dst, in_if.remote_ip4)
Paul Vinciguerra978aa642018-11-24 22:19:12 -0800659 self.assertEqual(packet.haslayer(ICMP), 1)
Juraj Slobodab33f4132017-02-08 23:54:21 -0800660 icmp = packet[ICMP]
661 self.assertEqual(icmp.type, icmp_type)
662 self.assertTrue(icmp.haslayer(IPerror))
663 inner_ip = icmp[IPerror]
664 if inner_ip.haslayer(TCPerror):
665 self.assertEqual(inner_ip[TCPerror].sport,
666 self.tcp_port_in)
667 elif inner_ip.haslayer(UDPerror):
668 self.assertEqual(inner_ip[UDPerror].sport,
669 self.udp_port_in)
670 else:
671 self.assertEqual(inner_ip[ICMPerror].id, self.icmp_id_in)
672 except:
673 self.logger.error(ppp("Unexpected or invalid packet "
674 "(inside network):", packet))
675 raise
676
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200677 def create_stream_frag(self, src_if, dst, sport, dport, data,
678 proto=IP_PROTOS.tcp, echo_reply=False):
Matus Fabianefcd1e92017-08-15 06:59:19 -0700679 """
680 Create fragmented packet stream
681
682 :param src_if: Source interface
683 :param dst: Destination IPv4 address
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200684 :param sport: Source port
685 :param dport: Destination port
Matus Fabianefcd1e92017-08-15 06:59:19 -0700686 :param data: Payload data
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200687 :param proto: protocol (TCP, UDP, ICMP)
688 :param echo_reply: use echo_reply if protocol is ICMP
Matus Fabianefcd1e92017-08-15 06:59:19 -0700689 :returns: Fragmets
690 """
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200691 if proto == IP_PROTOS.tcp:
692 p = (IP(src=src_if.remote_ip4, dst=dst) /
693 TCP(sport=sport, dport=dport) /
694 Raw(data))
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700695 p = p.__class__(scapy.compat.raw(p))
696 chksum = p[TCP].chksum
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200697 proto_header = TCP(sport=sport, dport=dport, chksum=chksum)
698 elif proto == IP_PROTOS.udp:
699 proto_header = UDP(sport=sport, dport=dport)
700 elif proto == IP_PROTOS.icmp:
701 if not echo_reply:
702 proto_header = ICMP(id=sport, type='echo-request')
703 else:
704 proto_header = ICMP(id=sport, type='echo-reply')
705 else:
706 raise Exception("Unsupported protocol")
Matus Fabianefcd1e92017-08-15 06:59:19 -0700707 id = random.randint(0, 65535)
Matus Fabianefcd1e92017-08-15 06:59:19 -0700708 pkts = []
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200709 if proto == IP_PROTOS.tcp:
710 raw = Raw(data[0:4])
711 else:
712 raw = Raw(data[0:16])
Matus Fabianefcd1e92017-08-15 06:59:19 -0700713 p = (Ether(src=src_if.remote_mac, dst=src_if.local_mac) /
714 IP(src=src_if.remote_ip4, dst=dst, flags="MF", frag=0, id=id) /
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200715 proto_header /
716 raw)
Matus Fabianefcd1e92017-08-15 06:59:19 -0700717 pkts.append(p)
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200718 if proto == IP_PROTOS.tcp:
719 raw = Raw(data[4:20])
720 else:
721 raw = Raw(data[16:32])
Matus Fabianefcd1e92017-08-15 06:59:19 -0700722 p = (Ether(src=src_if.remote_mac, dst=src_if.local_mac) /
723 IP(src=src_if.remote_ip4, dst=dst, flags="MF", frag=3, id=id,
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200724 proto=proto) /
725 raw)
Matus Fabianefcd1e92017-08-15 06:59:19 -0700726 pkts.append(p)
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200727 if proto == IP_PROTOS.tcp:
728 raw = Raw(data[20:])
729 else:
730 raw = Raw(data[32:])
Matus Fabianefcd1e92017-08-15 06:59:19 -0700731 p = (Ether(src=src_if.remote_mac, dst=src_if.local_mac) /
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200732 IP(src=src_if.remote_ip4, dst=dst, frag=5, proto=proto,
Matus Fabianefcd1e92017-08-15 06:59:19 -0700733 id=id) /
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200734 raw)
Matus Fabianefcd1e92017-08-15 06:59:19 -0700735 pkts.append(p)
736 return pkts
737
738 def create_stream_frag_ip6(self, src_if, dst, sport, dport, data,
739 pref=None, plen=0, frag_size=128):
740 """
741 Create fragmented packet stream
742
743 :param src_if: Source interface
744 :param dst: Destination IPv4 address
745 :param sport: Source TCP port
746 :param dport: Destination TCP port
747 :param data: Payload data
748 :param pref: NAT64 prefix
749 :param plen: NAT64 prefix length
750 :param fragsize: size of fragments
751 :returns: Fragmets
752 """
753 if pref is None:
754 dst_ip6 = ''.join(['64:ff9b::', dst])
755 else:
756 dst_ip6 = self.compose_ip6(dst, pref, plen)
757
758 p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
759 IPv6(src=src_if.remote_ip6, dst=dst_ip6) /
760 IPv6ExtHdrFragment(id=random.randint(0, 65535)) /
761 TCP(sport=sport, dport=dport) /
762 Raw(data))
763
764 return fragment6(p, frag_size)
765
766 def reass_frags_and_verify(self, frags, src, dst):
767 """
768 Reassemble and verify fragmented packet
769
770 :param frags: Captured fragments
771 :param src: Source IPv4 address to verify
772 :param dst: Destination IPv4 address to verify
773
774 :returns: Reassembled IPv4 packet
775 """
Ole Troan7f991832018-12-06 17:35:12 +0100776 buffer = BytesIO()
Matus Fabianefcd1e92017-08-15 06:59:19 -0700777 for p in frags:
778 self.assertEqual(p[IP].src, src)
779 self.assertEqual(p[IP].dst, dst)
Klement Sekerad81ae412018-05-16 10:52:54 +0200780 self.assert_ip_checksum_valid(p)
Matus Fabianefcd1e92017-08-15 06:59:19 -0700781 buffer.seek(p[IP].frag * 8)
Ole Troan7f991832018-12-06 17:35:12 +0100782 buffer.write(bytes(p[IP].payload))
Matus Fabianefcd1e92017-08-15 06:59:19 -0700783 ip = IP(src=frags[0][IP].src, dst=frags[0][IP].dst,
784 proto=frags[0][IP].proto)
785 if ip.proto == IP_PROTOS.tcp:
786 p = (ip / TCP(buffer.getvalue()))
Klement Sekerad81ae412018-05-16 10:52:54 +0200787 self.assert_tcp_checksum_valid(p)
Matus Fabianefcd1e92017-08-15 06:59:19 -0700788 elif ip.proto == IP_PROTOS.udp:
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200789 p = (ip / UDP(buffer.getvalue()[:8]) /
790 Raw(buffer.getvalue()[8:]))
791 elif ip.proto == IP_PROTOS.icmp:
792 p = (ip / ICMP(buffer.getvalue()))
Matus Fabianefcd1e92017-08-15 06:59:19 -0700793 return p
794
795 def reass_frags_and_verify_ip6(self, frags, src, dst):
796 """
797 Reassemble and verify fragmented packet
798
799 :param frags: Captured fragments
800 :param src: Source IPv6 address to verify
801 :param dst: Destination IPv6 address to verify
802
803 :returns: Reassembled IPv6 packet
804 """
Ole Troan7f991832018-12-06 17:35:12 +0100805 buffer = BytesIO()
Matus Fabianefcd1e92017-08-15 06:59:19 -0700806 for p in frags:
807 self.assertEqual(p[IPv6].src, src)
808 self.assertEqual(p[IPv6].dst, dst)
809 buffer.seek(p[IPv6ExtHdrFragment].offset * 8)
Ole Troan7f991832018-12-06 17:35:12 +0100810 buffer.write(bytes(p[IPv6ExtHdrFragment].payload))
Matus Fabianefcd1e92017-08-15 06:59:19 -0700811 ip = IPv6(src=frags[0][IPv6].src, dst=frags[0][IPv6].dst,
812 nh=frags[0][IPv6ExtHdrFragment].nh)
813 if ip.nh == IP_PROTOS.tcp:
814 p = (ip / TCP(buffer.getvalue()))
Matus Fabianefcd1e92017-08-15 06:59:19 -0700815 elif ip.nh == IP_PROTOS.udp:
816 p = (ip / UDP(buffer.getvalue()))
Klement Sekerad81ae412018-05-16 10:52:54 +0200817 self.assert_packet_checksums_valid(p)
Matus Fabianefcd1e92017-08-15 06:59:19 -0700818 return p
819
Matus Fabianebdf1902018-05-04 03:57:42 -0700820 def initiate_tcp_session(self, in_if, out_if):
821 """
822 Initiates TCP session
823
824 :param in_if: Inside interface
825 :param out_if: Outside interface
826 """
827 try:
828 # SYN packet in->out
829 p = (Ether(src=in_if.remote_mac, dst=in_if.local_mac) /
830 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4) /
831 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
832 flags="S"))
833 in_if.add_stream(p)
834 self.pg_enable_capture(self.pg_interfaces)
835 self.pg_start()
836 capture = out_if.get_capture(1)
837 p = capture[0]
838 self.tcp_port_out = p[TCP].sport
839
840 # SYN + ACK packet out->in
841 p = (Ether(src=out_if.remote_mac, dst=out_if.local_mac) /
842 IP(src=out_if.remote_ip4, dst=self.nat_addr) /
843 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
844 flags="SA"))
845 out_if.add_stream(p)
846 self.pg_enable_capture(self.pg_interfaces)
847 self.pg_start()
848 in_if.get_capture(1)
849
850 # ACK packet in->out
851 p = (Ether(src=in_if.remote_mac, dst=in_if.local_mac) /
852 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4) /
853 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
854 flags="A"))
855 in_if.add_stream(p)
856 self.pg_enable_capture(self.pg_interfaces)
857 self.pg_start()
858 out_if.get_capture(1)
859
860 except:
861 self.logger.error("TCP 3 way handshake failed")
862 raise
863
Matus Fabianeea28d72017-01-13 04:15:54 -0800864 def verify_ipfix_nat44_ses(self, data):
865 """
866 Verify IPFIX NAT44 session create/delete event
867
868 :param data: Decoded IPFIX data records
869 """
870 nat44_ses_create_num = 0
871 nat44_ses_delete_num = 0
872 self.assertEqual(6, len(data))
873 for record in data:
874 # natEvent
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700875 self.assertIn(scapy.compat.orb(record[230]), [4, 5])
876 if scapy.compat.orb(record[230]) == 4:
Matus Fabianeea28d72017-01-13 04:15:54 -0800877 nat44_ses_create_num += 1
878 else:
879 nat44_ses_delete_num += 1
880 # sourceIPv4Address
881 self.assertEqual(self.pg0.remote_ip4n, record[8])
882 # postNATSourceIPv4Address
Matus Fabian2ba92e32017-08-21 07:05:03 -0700883 self.assertEqual(socket.inet_pton(socket.AF_INET, self.nat_addr),
Matus Fabianeea28d72017-01-13 04:15:54 -0800884 record[225])
885 # ingressVRFID
886 self.assertEqual(struct.pack("!I", 0), record[234])
887 # protocolIdentifier/sourceTransportPort/postNAPTSourceTransportPort
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700888 if IP_PROTOS.icmp == scapy.compat.orb(record[4]):
Matus Fabianeea28d72017-01-13 04:15:54 -0800889 self.assertEqual(struct.pack("!H", self.icmp_id_in), record[7])
890 self.assertEqual(struct.pack("!H", self.icmp_id_out),
891 record[227])
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700892 elif IP_PROTOS.tcp == scapy.compat.orb(record[4]):
Matus Fabianeea28d72017-01-13 04:15:54 -0800893 self.assertEqual(struct.pack("!H", self.tcp_port_in),
894 record[7])
895 self.assertEqual(struct.pack("!H", self.tcp_port_out),
896 record[227])
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700897 elif IP_PROTOS.udp == scapy.compat.orb(record[4]):
Matus Fabianeea28d72017-01-13 04:15:54 -0800898 self.assertEqual(struct.pack("!H", self.udp_port_in),
899 record[7])
900 self.assertEqual(struct.pack("!H", self.udp_port_out),
901 record[227])
902 else:
903 self.fail("Invalid protocol")
904 self.assertEqual(3, nat44_ses_create_num)
905 self.assertEqual(3, nat44_ses_delete_num)
906
907 def verify_ipfix_addr_exhausted(self, data):
908 """
909 Verify IPFIX NAT addresses event
910
911 :param data: Decoded IPFIX data records
912 """
913 self.assertEqual(1, len(data))
914 record = data[0]
915 # natEvent
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700916 self.assertEqual(scapy.compat.orb(record[230]), 3)
Matus Fabianeea28d72017-01-13 04:15:54 -0800917 # natPoolID
918 self.assertEqual(struct.pack("!I", 0), record[283])
919
Matus Fabiana431ad12018-01-04 04:03:14 -0800920 def verify_ipfix_max_sessions(self, data, limit):
921 """
922 Verify IPFIX maximum session entries exceeded event
923
924 :param data: Decoded IPFIX data records
925 :param limit: Number of maximum session entries that can be created.
926 """
927 self.assertEqual(1, len(data))
928 record = data[0]
929 # natEvent
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700930 self.assertEqual(scapy.compat.orb(record[230]), 13)
Matus Fabiana431ad12018-01-04 04:03:14 -0800931 # natQuotaExceededEvent
932 self.assertEqual(struct.pack("I", 1), record[466])
933 # maxSessionEntries
934 self.assertEqual(struct.pack("I", limit), record[471])
935
936 def verify_ipfix_max_bibs(self, data, limit):
937 """
938 Verify IPFIX maximum BIB entries exceeded event
939
940 :param data: Decoded IPFIX data records
941 :param limit: Number of maximum BIB entries that can be created.
942 """
943 self.assertEqual(1, len(data))
944 record = data[0]
945 # natEvent
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700946 self.assertEqual(scapy.compat.orb(record[230]), 13)
Matus Fabiana431ad12018-01-04 04:03:14 -0800947 # natQuotaExceededEvent
948 self.assertEqual(struct.pack("I", 2), record[466])
949 # maxBIBEntries
950 self.assertEqual(struct.pack("I", limit), record[472])
951
952 def verify_ipfix_max_fragments_ip6(self, data, limit, src_addr):
953 """
954 Verify IPFIX maximum IPv6 fragments pending reassembly exceeded event
955
956 :param data: Decoded IPFIX data records
957 :param limit: Number of maximum fragments pending reassembly
958 :param src_addr: IPv6 source address
959 """
960 self.assertEqual(1, len(data))
961 record = data[0]
962 # natEvent
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700963 self.assertEqual(scapy.compat.orb(record[230]), 13)
Matus Fabiana431ad12018-01-04 04:03:14 -0800964 # natQuotaExceededEvent
965 self.assertEqual(struct.pack("I", 5), record[466])
966 # maxFragmentsPendingReassembly
967 self.assertEqual(struct.pack("I", limit), record[475])
968 # sourceIPv6Address
969 self.assertEqual(src_addr, record[27])
970
971 def verify_ipfix_max_fragments_ip4(self, data, limit, src_addr):
972 """
973 Verify IPFIX maximum IPv4 fragments pending reassembly exceeded event
974
975 :param data: Decoded IPFIX data records
976 :param limit: Number of maximum fragments pending reassembly
977 :param src_addr: IPv4 source address
978 """
979 self.assertEqual(1, len(data))
980 record = data[0]
981 # natEvent
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700982 self.assertEqual(scapy.compat.orb(record[230]), 13)
Matus Fabiana431ad12018-01-04 04:03:14 -0800983 # natQuotaExceededEvent
984 self.assertEqual(struct.pack("I", 5), record[466])
985 # maxFragmentsPendingReassembly
986 self.assertEqual(struct.pack("I", limit), record[475])
987 # sourceIPv4Address
988 self.assertEqual(src_addr, record[8])
989
990 def verify_ipfix_bib(self, data, is_create, src_addr):
991 """
992 Verify IPFIX NAT64 BIB create and delete events
993
994 :param data: Decoded IPFIX data records
995 :param is_create: Create event if nonzero value otherwise delete event
996 :param src_addr: IPv6 source address
997 """
998 self.assertEqual(1, len(data))
999 record = data[0]
1000 # natEvent
1001 if is_create:
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07001002 self.assertEqual(scapy.compat.orb(record[230]), 10)
Matus Fabiana431ad12018-01-04 04:03:14 -08001003 else:
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07001004 self.assertEqual(scapy.compat.orb(record[230]), 11)
Matus Fabiana431ad12018-01-04 04:03:14 -08001005 # sourceIPv6Address
1006 self.assertEqual(src_addr, record[27])
1007 # postNATSourceIPv4Address
1008 self.assertEqual(self.nat_addr_n, record[225])
1009 # protocolIdentifier
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07001010 self.assertEqual(IP_PROTOS.tcp, scapy.compat.orb(record[4]))
Matus Fabiana431ad12018-01-04 04:03:14 -08001011 # ingressVRFID
1012 self.assertEqual(struct.pack("!I", 0), record[234])
1013 # sourceTransportPort
1014 self.assertEqual(struct.pack("!H", self.tcp_port_in), record[7])
1015 # postNAPTSourceTransportPort
1016 self.assertEqual(struct.pack("!H", self.tcp_port_out), record[227])
1017
1018 def verify_ipfix_nat64_ses(self, data, is_create, src_addr, dst_addr,
1019 dst_port):
1020 """
1021 Verify IPFIX NAT64 session create and delete events
1022
1023 :param data: Decoded IPFIX data records
1024 :param is_create: Create event if nonzero value otherwise delete event
1025 :param src_addr: IPv6 source address
1026 :param dst_addr: IPv4 destination address
1027 :param dst_port: destination TCP port
1028 """
1029 self.assertEqual(1, len(data))
1030 record = data[0]
1031 # natEvent
1032 if is_create:
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07001033 self.assertEqual(scapy.compat.orb(record[230]), 6)
Matus Fabiana431ad12018-01-04 04:03:14 -08001034 else:
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07001035 self.assertEqual(scapy.compat.orb(record[230]), 7)
Matus Fabiana431ad12018-01-04 04:03:14 -08001036 # sourceIPv6Address
1037 self.assertEqual(src_addr, record[27])
1038 # destinationIPv6Address
1039 self.assertEqual(socket.inet_pton(socket.AF_INET6,
1040 self.compose_ip6(dst_addr,
1041 '64:ff9b::',
1042 96)),
1043 record[28])
1044 # postNATSourceIPv4Address
1045 self.assertEqual(self.nat_addr_n, record[225])
1046 # postNATDestinationIPv4Address
1047 self.assertEqual(socket.inet_pton(socket.AF_INET, dst_addr),
1048 record[226])
1049 # protocolIdentifier
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07001050 self.assertEqual(IP_PROTOS.tcp, scapy.compat.orb(record[4]))
Matus Fabiana431ad12018-01-04 04:03:14 -08001051 # ingressVRFID
1052 self.assertEqual(struct.pack("!I", 0), record[234])
1053 # sourceTransportPort
1054 self.assertEqual(struct.pack("!H", self.tcp_port_in), record[7])
1055 # postNAPTSourceTransportPort
1056 self.assertEqual(struct.pack("!H", self.tcp_port_out), record[227])
1057 # destinationTransportPort
1058 self.assertEqual(struct.pack("!H", dst_port), record[11])
1059 # postNAPTDestinationTransportPort
1060 self.assertEqual(struct.pack("!H", dst_port), record[228])
1061
Matus Fabian68ba8802018-08-08 05:52:47 -07001062 def verify_no_nat44_user(self):
1063 """ Verify that there is no NAT44 user """
1064 users = self.vapi.nat44_user_dump()
1065 self.assertEqual(len(users), 0)
Matus Fabianfd0d5082018-12-18 01:08:51 -08001066 users = self.statistics.get_counter('/nat44/total-users')
1067 self.assertEqual(users[0][0], 0)
1068 sessions = self.statistics.get_counter('/nat44/total-sessions')
1069 self.assertEqual(sessions[0][0], 0)
Matus Fabian68ba8802018-08-08 05:52:47 -07001070
Matus Fabian878c6462018-08-23 00:33:35 -07001071 def verify_ipfix_max_entries_per_user(self, data, limit, src_addr):
1072 """
1073 Verify IPFIX maximum entries per user exceeded event
1074
1075 :param data: Decoded IPFIX data records
1076 :param limit: Number of maximum entries per user
1077 :param src_addr: IPv4 source address
1078 """
1079 self.assertEqual(1, len(data))
1080 record = data[0]
1081 # natEvent
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07001082 self.assertEqual(scapy.compat.orb(record[230]), 13)
Matus Fabian878c6462018-08-23 00:33:35 -07001083 # natQuotaExceededEvent
1084 self.assertEqual(struct.pack("I", 3), record[466])
1085 # maxEntriesPerUser
1086 self.assertEqual(struct.pack("I", limit), record[473])
1087 # sourceIPv4Address
1088 self.assertEqual(src_addr, record[8])
1089
Matus Fabianad1f3e12018-11-28 21:26:34 -08001090 def verify_syslog_apmap(self, data, is_add=True):
1091 message = data.decode('utf-8')
1092 try:
1093 message = SyslogMessage.parse(message)
Paul Vinciguerrad7532092019-01-14 08:51:17 -08001094 except ParseError as e:
1095 self.logger.error(e)
1096 raise
1097 else:
Matus Fabianad1f3e12018-11-28 21:26:34 -08001098 self.assertEqual(message.severity, SyslogSeverity.info)
1099 self.assertEqual(message.appname, 'NAT')
1100 self.assertEqual(message.msgid, 'APMADD' if is_add else 'APMDEL')
1101 sd_params = message.sd.get('napmap')
1102 self.assertTrue(sd_params is not None)
1103 self.assertEqual(sd_params.get('IATYP'), 'IPv4')
1104 self.assertEqual(sd_params.get('ISADDR'), self.pg0.remote_ip4)
1105 self.assertEqual(sd_params.get('ISPORT'), "%d" % self.tcp_port_in)
1106 self.assertEqual(sd_params.get('XATYP'), 'IPv4')
1107 self.assertEqual(sd_params.get('XSADDR'), self.nat_addr)
1108 self.assertEqual(sd_params.get('XSPORT'), "%d" % self.tcp_port_out)
1109 self.assertEqual(sd_params.get('PROTO'), "%d" % IP_PROTOS.tcp)
1110 self.assertTrue(sd_params.get('SSUBIX') is not None)
1111 self.assertEqual(sd_params.get('SVLAN'), '0')
Matus Fabianad1f3e12018-11-28 21:26:34 -08001112
1113 def verify_syslog_sess(self, data, is_add=True, is_ip6=False):
1114 message = data.decode('utf-8')
1115 try:
1116 message = SyslogMessage.parse(message)
Paul Vinciguerrad7532092019-01-14 08:51:17 -08001117 except ParseError as e:
1118 self.logger.error(e)
1119 raise
1120 else:
Matus Fabianad1f3e12018-11-28 21:26:34 -08001121 self.assertEqual(message.severity, SyslogSeverity.info)
1122 self.assertEqual(message.appname, 'NAT')
1123 self.assertEqual(message.msgid, 'SADD' if is_add else 'SDEL')
1124 sd_params = message.sd.get('nsess')
1125 self.assertTrue(sd_params is not None)
1126 if is_ip6:
1127 self.assertEqual(sd_params.get('IATYP'), 'IPv6')
1128 self.assertEqual(sd_params.get('ISADDR'), self.pg0.remote_ip6)
1129 else:
1130 self.assertEqual(sd_params.get('IATYP'), 'IPv4')
1131 self.assertEqual(sd_params.get('ISADDR'), self.pg0.remote_ip4)
1132 self.assertTrue(sd_params.get('SSUBIX') is not None)
1133 self.assertEqual(sd_params.get('ISPORT'), "%d" % self.tcp_port_in)
1134 self.assertEqual(sd_params.get('XATYP'), 'IPv4')
1135 self.assertEqual(sd_params.get('XSADDR'), self.nat_addr)
1136 self.assertEqual(sd_params.get('XSPORT'), "%d" % self.tcp_port_out)
1137 self.assertEqual(sd_params.get('PROTO'), "%d" % IP_PROTOS.tcp)
1138 self.assertEqual(sd_params.get('SVLAN'), '0')
1139 self.assertEqual(sd_params.get('XDADDR'), self.pg1.remote_ip4)
1140 self.assertEqual(sd_params.get('XDPORT'),
1141 "%d" % self.tcp_external_port)
Matus Fabianad1f3e12018-11-28 21:26:34 -08001142
Matus Fabianbb4e0222018-09-13 02:36:25 -07001143 def verify_mss_value(self, pkt, mss):
1144 """
1145 Verify TCP MSS value
1146
1147 :param pkt:
1148 :param mss:
1149 """
1150 if not pkt.haslayer(IP) or not pkt.haslayer(TCP):
1151 raise TypeError("Not a TCP/IP packet")
1152
1153 for option in pkt[TCP].options:
1154 if option[0] == 'MSS':
1155 self.assertEqual(option[1], mss)
1156 self.assert_tcp_checksum_valid(pkt)
1157
Juraj Slobodafe0aa762018-07-23 12:22:54 +02001158 @staticmethod
1159 def proto2layer(proto):
1160 if proto == IP_PROTOS.tcp:
1161 return TCP
1162 elif proto == IP_PROTOS.udp:
1163 return UDP
1164 elif proto == IP_PROTOS.icmp:
1165 return ICMP
1166 else:
1167 raise Exception("Unsupported protocol")
1168
1169 def frag_in_order(self, proto=IP_PROTOS.tcp, dont_translate=False):
1170 layer = self.proto2layer(proto)
1171
1172 if proto == IP_PROTOS.tcp:
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07001173 data = b"A" * 4 + b"B" * 16 + b"C" * 3
Juraj Slobodafe0aa762018-07-23 12:22:54 +02001174 else:
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07001175 data = b"A" * 16 + b"B" * 16 + b"C" * 3
Juraj Slobodafe0aa762018-07-23 12:22:54 +02001176 self.port_in = random.randint(1025, 65535)
1177
1178 reass = self.vapi.nat_reass_dump()
1179 reass_n_start = len(reass)
1180
1181 # in2out
1182 pkts = self.create_stream_frag(self.pg0,
1183 self.pg1.remote_ip4,
1184 self.port_in,
1185 20,
1186 data,
1187 proto)
1188 self.pg0.add_stream(pkts)
1189 self.pg_enable_capture(self.pg_interfaces)
1190 self.pg_start()
1191 frags = self.pg1.get_capture(len(pkts))
1192 if not dont_translate:
1193 p = self.reass_frags_and_verify(frags,
1194 self.nat_addr,
1195 self.pg1.remote_ip4)
1196 else:
1197 p = self.reass_frags_and_verify(frags,
1198 self.pg0.remote_ip4,
1199 self.pg1.remote_ip4)
1200 if proto != IP_PROTOS.icmp:
1201 if not dont_translate:
1202 self.assertEqual(p[layer].dport, 20)
1203 self.assertNotEqual(p[layer].sport, self.port_in)
1204 else:
1205 self.assertEqual(p[layer].sport, self.port_in)
1206 else:
1207 if not dont_translate:
1208 self.assertNotEqual(p[layer].id, self.port_in)
1209 else:
1210 self.assertEqual(p[layer].id, self.port_in)
1211 self.assertEqual(data, p[Raw].load)
1212
1213 # out2in
1214 if not dont_translate:
1215 dst_addr = self.nat_addr
1216 else:
1217 dst_addr = self.pg0.remote_ip4
1218 if proto != IP_PROTOS.icmp:
1219 sport = 20
1220 dport = p[layer].sport
1221 else:
1222 sport = p[layer].id
1223 dport = 0
1224 pkts = self.create_stream_frag(self.pg1,
1225 dst_addr,
1226 sport,
1227 dport,
1228 data,
1229 proto,
1230 echo_reply=True)
1231 self.pg1.add_stream(pkts)
1232 self.pg_enable_capture(self.pg_interfaces)
1233 self.pg_start()
1234 frags = self.pg0.get_capture(len(pkts))
1235 p = self.reass_frags_and_verify(frags,
1236 self.pg1.remote_ip4,
1237 self.pg0.remote_ip4)
1238 if proto != IP_PROTOS.icmp:
1239 self.assertEqual(p[layer].sport, 20)
1240 self.assertEqual(p[layer].dport, self.port_in)
1241 else:
1242 self.assertEqual(p[layer].id, self.port_in)
1243 self.assertEqual(data, p[Raw].load)
1244
1245 reass = self.vapi.nat_reass_dump()
1246 reass_n_end = len(reass)
1247
1248 self.assertEqual(reass_n_end - reass_n_start, 2)
1249
1250 def frag_in_order_in_plus_out(self, proto=IP_PROTOS.tcp):
1251 layer = self.proto2layer(proto)
1252
1253 if proto == IP_PROTOS.tcp:
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07001254 data = b"A" * 4 + b"B" * 16 + b"C" * 3
Juraj Slobodafe0aa762018-07-23 12:22:54 +02001255 else:
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07001256 data = b"A" * 16 + b"B" * 16 + b"C" * 3
Juraj Slobodafe0aa762018-07-23 12:22:54 +02001257 self.port_in = random.randint(1025, 65535)
1258
1259 for i in range(2):
1260 reass = self.vapi.nat_reass_dump()
1261 reass_n_start = len(reass)
1262
1263 # out2in
1264 pkts = self.create_stream_frag(self.pg0,
1265 self.server_out_addr,
1266 self.port_in,
1267 self.server_out_port,
1268 data,
1269 proto)
1270 self.pg0.add_stream(pkts)
1271 self.pg_enable_capture(self.pg_interfaces)
1272 self.pg_start()
1273 frags = self.pg1.get_capture(len(pkts))
1274 p = self.reass_frags_and_verify(frags,
1275 self.pg0.remote_ip4,
1276 self.server_in_addr)
1277 if proto != IP_PROTOS.icmp:
1278 self.assertEqual(p[layer].sport, self.port_in)
1279 self.assertEqual(p[layer].dport, self.server_in_port)
1280 else:
1281 self.assertEqual(p[layer].id, self.port_in)
1282 self.assertEqual(data, p[Raw].load)
1283
1284 # in2out
1285 if proto != IP_PROTOS.icmp:
1286 pkts = self.create_stream_frag(self.pg1,
1287 self.pg0.remote_ip4,
1288 self.server_in_port,
1289 p[layer].sport,
1290 data,
1291 proto)
1292 else:
1293 pkts = self.create_stream_frag(self.pg1,
1294 self.pg0.remote_ip4,
1295 p[layer].id,
1296 0,
1297 data,
1298 proto,
1299 echo_reply=True)
1300 self.pg1.add_stream(pkts)
1301 self.pg_enable_capture(self.pg_interfaces)
1302 self.pg_start()
1303 frags = self.pg0.get_capture(len(pkts))
1304 p = self.reass_frags_and_verify(frags,
1305 self.server_out_addr,
1306 self.pg0.remote_ip4)
1307 if proto != IP_PROTOS.icmp:
1308 self.assertEqual(p[layer].sport, self.server_out_port)
1309 self.assertEqual(p[layer].dport, self.port_in)
1310 else:
1311 self.assertEqual(p[layer].id, self.port_in)
1312 self.assertEqual(data, p[Raw].load)
1313
1314 reass = self.vapi.nat_reass_dump()
1315 reass_n_end = len(reass)
1316
1317 self.assertEqual(reass_n_end - reass_n_start, 2)
1318
1319 def reass_hairpinning(self, proto=IP_PROTOS.tcp):
1320 layer = self.proto2layer(proto)
1321
1322 if proto == IP_PROTOS.tcp:
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07001323 data = b"A" * 4 + b"B" * 16 + b"C" * 3
Juraj Slobodafe0aa762018-07-23 12:22:54 +02001324 else:
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07001325 data = b"A" * 16 + b"B" * 16 + b"C" * 3
Juraj Slobodafe0aa762018-07-23 12:22:54 +02001326
1327 # send packet from host to server
1328 pkts = self.create_stream_frag(self.pg0,
1329 self.nat_addr,
1330 self.host_in_port,
1331 self.server_out_port,
1332 data,
1333 proto)
1334 self.pg0.add_stream(pkts)
1335 self.pg_enable_capture(self.pg_interfaces)
1336 self.pg_start()
1337 frags = self.pg0.get_capture(len(pkts))
1338 p = self.reass_frags_and_verify(frags,
1339 self.nat_addr,
1340 self.server.ip4)
1341 if proto != IP_PROTOS.icmp:
1342 self.assertNotEqual(p[layer].sport, self.host_in_port)
1343 self.assertEqual(p[layer].dport, self.server_in_port)
1344 else:
1345 self.assertNotEqual(p[layer].id, self.host_in_port)
1346 self.assertEqual(data, p[Raw].load)
1347
1348 def frag_out_of_order(self, proto=IP_PROTOS.tcp, dont_translate=False):
1349 layer = self.proto2layer(proto)
1350
1351 if proto == IP_PROTOS.tcp:
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07001352 data = b"A" * 4 + b"B" * 16 + b"C" * 3
Juraj Slobodafe0aa762018-07-23 12:22:54 +02001353 else:
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07001354 data = b"A" * 16 + b"B" * 16 + b"C" * 3
Juraj Slobodafe0aa762018-07-23 12:22:54 +02001355 self.port_in = random.randint(1025, 65535)
1356
1357 for i in range(2):
1358 # in2out
1359 pkts = self.create_stream_frag(self.pg0,
1360 self.pg1.remote_ip4,
1361 self.port_in,
1362 20,
1363 data,
1364 proto)
1365 pkts.reverse()
1366 self.pg0.add_stream(pkts)
1367 self.pg_enable_capture(self.pg_interfaces)
1368 self.pg_start()
1369 frags = self.pg1.get_capture(len(pkts))
1370 if not dont_translate:
1371 p = self.reass_frags_and_verify(frags,
1372 self.nat_addr,
1373 self.pg1.remote_ip4)
1374 else:
1375 p = self.reass_frags_and_verify(frags,
1376 self.pg0.remote_ip4,
1377 self.pg1.remote_ip4)
1378 if proto != IP_PROTOS.icmp:
1379 if not dont_translate:
1380 self.assertEqual(p[layer].dport, 20)
1381 self.assertNotEqual(p[layer].sport, self.port_in)
1382 else:
1383 self.assertEqual(p[layer].sport, self.port_in)
1384 else:
1385 if not dont_translate:
1386 self.assertNotEqual(p[layer].id, self.port_in)
1387 else:
1388 self.assertEqual(p[layer].id, self.port_in)
1389 self.assertEqual(data, p[Raw].load)
1390
1391 # out2in
1392 if not dont_translate:
1393 dst_addr = self.nat_addr
1394 else:
1395 dst_addr = self.pg0.remote_ip4
1396 if proto != IP_PROTOS.icmp:
1397 sport = 20
1398 dport = p[layer].sport
1399 else:
1400 sport = p[layer].id
1401 dport = 0
1402 pkts = self.create_stream_frag(self.pg1,
1403 dst_addr,
1404 sport,
1405 dport,
1406 data,
1407 proto,
1408 echo_reply=True)
1409 pkts.reverse()
1410 self.pg1.add_stream(pkts)
1411 self.pg_enable_capture(self.pg_interfaces)
1412 self.pg_start()
1413 frags = self.pg0.get_capture(len(pkts))
1414 p = self.reass_frags_and_verify(frags,
1415 self.pg1.remote_ip4,
1416 self.pg0.remote_ip4)
1417 if proto != IP_PROTOS.icmp:
1418 self.assertEqual(p[layer].sport, 20)
1419 self.assertEqual(p[layer].dport, self.port_in)
1420 else:
1421 self.assertEqual(p[layer].id, self.port_in)
1422 self.assertEqual(data, p[Raw].load)
1423
1424 def frag_out_of_order_in_plus_out(self, proto=IP_PROTOS.tcp):
1425 layer = self.proto2layer(proto)
1426
1427 if proto == IP_PROTOS.tcp:
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07001428 data = b"A" * 4 + b"B" * 16 + b"C" * 3
Juraj Slobodafe0aa762018-07-23 12:22:54 +02001429 else:
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07001430 data = b"A" * 16 + b"B" * 16 + b"C" * 3
Juraj Slobodafe0aa762018-07-23 12:22:54 +02001431 self.port_in = random.randint(1025, 65535)
1432
1433 for i in range(2):
1434 # out2in
1435 pkts = self.create_stream_frag(self.pg0,
1436 self.server_out_addr,
1437 self.port_in,
1438 self.server_out_port,
1439 data,
1440 proto)
1441 pkts.reverse()
1442 self.pg0.add_stream(pkts)
1443 self.pg_enable_capture(self.pg_interfaces)
1444 self.pg_start()
1445 frags = self.pg1.get_capture(len(pkts))
1446 p = self.reass_frags_and_verify(frags,
1447 self.pg0.remote_ip4,
1448 self.server_in_addr)
1449 if proto != IP_PROTOS.icmp:
1450 self.assertEqual(p[layer].dport, self.server_in_port)
1451 self.assertEqual(p[layer].sport, self.port_in)
1452 self.assertEqual(p[layer].dport, self.server_in_port)
1453 else:
1454 self.assertEqual(p[layer].id, self.port_in)
1455 self.assertEqual(data, p[Raw].load)
1456
1457 # in2out
1458 if proto != IP_PROTOS.icmp:
1459 pkts = self.create_stream_frag(self.pg1,
1460 self.pg0.remote_ip4,
1461 self.server_in_port,
1462 p[layer].sport,
1463 data,
1464 proto)
1465 else:
1466 pkts = self.create_stream_frag(self.pg1,
1467 self.pg0.remote_ip4,
1468 p[layer].id,
1469 0,
1470 data,
1471 proto,
1472 echo_reply=True)
1473 pkts.reverse()
1474 self.pg1.add_stream(pkts)
1475 self.pg_enable_capture(self.pg_interfaces)
1476 self.pg_start()
1477 frags = self.pg0.get_capture(len(pkts))
1478 p = self.reass_frags_and_verify(frags,
1479 self.server_out_addr,
1480 self.pg0.remote_ip4)
1481 if proto != IP_PROTOS.icmp:
1482 self.assertEqual(p[layer].sport, self.server_out_port)
1483 self.assertEqual(p[layer].dport, self.port_in)
1484 else:
1485 self.assertEqual(p[layer].id, self.port_in)
1486 self.assertEqual(data, p[Raw].load)
1487
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001488
Matus Fabian2ba92e32017-08-21 07:05:03 -07001489class TestNAT44(MethodHolder):
1490 """ NAT44 Test Cases """
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001491
1492 @classmethod
1493 def setUpClass(cls):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001494 super(TestNAT44, cls).setUpClass()
Matus Fabian229c1aa2018-05-28 04:09:52 -07001495 cls.vapi.cli("set log class nat level debug")
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001496
1497 try:
1498 cls.tcp_port_in = 6303
1499 cls.tcp_port_out = 6303
1500 cls.udp_port_in = 6304
1501 cls.udp_port_out = 6304
1502 cls.icmp_id_in = 6305
1503 cls.icmp_id_out = 6305
Matus Fabian2ba92e32017-08-21 07:05:03 -07001504 cls.nat_addr = '10.0.0.3'
Juraj Sloboda7b929792017-11-23 13:20:48 +01001505 cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
Matus Fabian6631e9c2017-05-24 01:52:20 -07001506 cls.ipfix_src_port = 4739
1507 cls.ipfix_domain_id = 1
Matus Fabianebdf1902018-05-04 03:57:42 -07001508 cls.tcp_external_port = 80
Matus Fabian34931eb2019-02-26 09:05:23 -08001509 cls.udp_external_port = 69
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001510
Matus Fabian36ea2d62017-10-24 04:13:49 -07001511 cls.create_pg_interfaces(range(10))
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001512 cls.interfaces = list(cls.pg_interfaces[0:4])
1513
1514 for i in cls.interfaces:
1515 i.admin_up()
1516 i.config_ip4()
1517 i.resolve_arp()
1518
Matus Fabian6fa74c62017-06-05 05:55:48 -07001519 cls.pg0.generate_remote_hosts(3)
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001520 cls.pg0.configure_ipv4_neighbors()
1521
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02001522 cls.pg1.generate_remote_hosts(1)
1523 cls.pg1.configure_ipv4_neighbors()
1524
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001525 cls.overlapping_interfaces = list(list(cls.pg_interfaces[4:7]))
Ole Troan9a475372019-03-05 16:58:24 +01001526 cls.vapi.ip_table_add_del(is_add=1, table_id=10)
1527 cls.vapi.ip_table_add_del(is_add=1, table_id=20)
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001528
1529 cls.pg4._local_ip4 = "172.16.255.1"
1530 cls.pg4._local_ip4n = socket.inet_pton(socket.AF_INET, i.local_ip4)
1531 cls.pg4._remote_hosts[0]._ip4 = "172.16.255.2"
1532 cls.pg4.set_table_ip4(10)
Matus Fabian69126282017-08-14 23:39:58 -07001533 cls.pg5._local_ip4 = "172.17.255.3"
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001534 cls.pg5._local_ip4n = socket.inet_pton(socket.AF_INET, i.local_ip4)
Matus Fabian69126282017-08-14 23:39:58 -07001535 cls.pg5._remote_hosts[0]._ip4 = "172.17.255.4"
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001536 cls.pg5.set_table_ip4(10)
1537 cls.pg6._local_ip4 = "172.16.255.1"
1538 cls.pg6._local_ip4n = socket.inet_pton(socket.AF_INET, i.local_ip4)
1539 cls.pg6._remote_hosts[0]._ip4 = "172.16.255.2"
1540 cls.pg6.set_table_ip4(20)
1541 for i in cls.overlapping_interfaces:
1542 i.config_ip4()
1543 i.admin_up()
1544 i.resolve_arp()
1545
1546 cls.pg7.admin_up()
Martin Gálik406eb1d2017-05-04 04:35:04 -07001547 cls.pg8.admin_up()
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001548
Matus Fabian36ea2d62017-10-24 04:13:49 -07001549 cls.pg9.generate_remote_hosts(2)
1550 cls.pg9.config_ip4()
1551 ip_addr_n = socket.inet_pton(socket.AF_INET, "10.0.0.1")
Ole Troan9a475372019-03-05 16:58:24 +01001552 cls.vapi.sw_interface_add_del_address(
1553 sw_if_index=cls.pg9.sw_if_index, address=ip_addr_n,
1554 address_length=24)
Matus Fabian36ea2d62017-10-24 04:13:49 -07001555 cls.pg9.admin_up()
1556 cls.pg9.resolve_arp()
1557 cls.pg9._remote_hosts[1]._ip4 = cls.pg9._remote_hosts[0]._ip4
1558 cls.pg4._remote_ip4 = cls.pg9._remote_hosts[0]._ip4 = "10.0.0.2"
1559 cls.pg9.resolve_arp()
1560
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001561 except Exception:
Matus Fabian2ba92e32017-08-21 07:05:03 -07001562 super(TestNAT44, cls).tearDownClass()
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001563 raise
1564
Matus Fabiande886752016-12-07 03:38:19 -08001565 def test_dynamic(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001566 """ NAT44 dynamic translation test """
Matus Fabian2ba92e32017-08-21 07:05:03 -07001567 self.nat44_add_address(self.nat_addr)
1568 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1569 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1570 is_inside=0)
Matus Fabiande886752016-12-07 03:38:19 -08001571
1572 # in2out
Matus Fabiana5e73762018-12-14 01:55:16 -08001573 tcpn = self.statistics.get_counter(
1574 '/err/nat44-in2out-slowpath/TCP packets')
1575 udpn = self.statistics.get_counter(
1576 '/err/nat44-in2out-slowpath/UDP packets')
1577 icmpn = self.statistics.get_counter(
1578 '/err/nat44-in2out-slowpath/ICMP packets')
1579 totaln = self.statistics.get_counter(
1580 '/err/nat44-in2out-slowpath/good in2out packets processed')
1581
Matus Fabiande886752016-12-07 03:38:19 -08001582 pkts = self.create_stream_in(self.pg0, self.pg1)
1583 self.pg0.add_stream(pkts)
1584 self.pg_enable_capture(self.pg_interfaces)
1585 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001586 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001587 self.verify_capture_out(capture)
1588
Matus Fabiana5e73762018-12-14 01:55:16 -08001589 err = self.statistics.get_counter(
1590 '/err/nat44-in2out-slowpath/TCP packets')
1591 self.assertEqual(err - tcpn, 1)
1592 err = self.statistics.get_counter(
1593 '/err/nat44-in2out-slowpath/UDP packets')
1594 self.assertEqual(err - udpn, 1)
1595 err = self.statistics.get_counter(
1596 '/err/nat44-in2out-slowpath/ICMP packets')
1597 self.assertEqual(err - icmpn, 1)
1598 err = self.statistics.get_counter(
1599 '/err/nat44-in2out-slowpath/good in2out packets processed')
1600 self.assertEqual(err - totaln, 3)
1601
Matus Fabiande886752016-12-07 03:38:19 -08001602 # out2in
Matus Fabiana5e73762018-12-14 01:55:16 -08001603 tcpn = self.statistics.get_counter('/err/nat44-out2in/TCP packets')
1604 udpn = self.statistics.get_counter('/err/nat44-out2in/UDP packets')
1605 icmpn = self.statistics.get_counter('/err/nat44-out2in/ICMP packets')
1606 totaln = self.statistics.get_counter(
1607 '/err/nat44-out2in/good out2in packets processed')
1608
Matus Fabiande886752016-12-07 03:38:19 -08001609 pkts = self.create_stream_out(self.pg1)
1610 self.pg1.add_stream(pkts)
1611 self.pg_enable_capture(self.pg_interfaces)
1612 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001613 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001614 self.verify_capture_in(capture, self.pg0)
1615
Matus Fabiana5e73762018-12-14 01:55:16 -08001616 err = self.statistics.get_counter('/err/nat44-out2in/TCP packets')
1617 self.assertEqual(err - tcpn, 1)
1618 err = self.statistics.get_counter('/err/nat44-out2in/UDP packets')
1619 self.assertEqual(err - udpn, 1)
1620 err = self.statistics.get_counter('/err/nat44-out2in/ICMP packets')
1621 self.assertEqual(err - icmpn, 1)
1622 err = self.statistics.get_counter(
1623 '/err/nat44-out2in/good out2in packets processed')
1624 self.assertEqual(err - totaln, 3)
1625
Matus Fabianfd0d5082018-12-18 01:08:51 -08001626 users = self.statistics.get_counter('/nat44/total-users')
1627 self.assertEqual(users[0][0], 1)
1628 sessions = self.statistics.get_counter('/nat44/total-sessions')
1629 self.assertEqual(sessions[0][0], 3)
1630
Juraj Slobodab33f4132017-02-08 23:54:21 -08001631 def test_dynamic_icmp_errors_in2out_ttl_1(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001632 """ NAT44 handling of client packets with TTL=1 """
Juraj Slobodab33f4132017-02-08 23:54:21 -08001633
Matus Fabian2ba92e32017-08-21 07:05:03 -07001634 self.nat44_add_address(self.nat_addr)
1635 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1636 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1637 is_inside=0)
Juraj Slobodab33f4132017-02-08 23:54:21 -08001638
1639 # Client side - generate traffic
1640 pkts = self.create_stream_in(self.pg0, self.pg1, ttl=1)
1641 self.pg0.add_stream(pkts)
1642 self.pg_enable_capture(self.pg_interfaces)
1643 self.pg_start()
1644
1645 # Client side - verify ICMP type 11 packets
1646 capture = self.pg0.get_capture(len(pkts))
1647 self.verify_capture_in_with_icmp_errors(capture, self.pg0)
1648
1649 def test_dynamic_icmp_errors_out2in_ttl_1(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001650 """ NAT44 handling of server packets with TTL=1 """
Juraj Slobodab33f4132017-02-08 23:54:21 -08001651
Matus Fabian2ba92e32017-08-21 07:05:03 -07001652 self.nat44_add_address(self.nat_addr)
1653 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1654 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1655 is_inside=0)
Juraj Slobodab33f4132017-02-08 23:54:21 -08001656
1657 # Client side - create sessions
1658 pkts = self.create_stream_in(self.pg0, self.pg1)
1659 self.pg0.add_stream(pkts)
1660 self.pg_enable_capture(self.pg_interfaces)
1661 self.pg_start()
1662
1663 # Server side - generate traffic
1664 capture = self.pg1.get_capture(len(pkts))
1665 self.verify_capture_out(capture)
1666 pkts = self.create_stream_out(self.pg1, ttl=1)
1667 self.pg1.add_stream(pkts)
1668 self.pg_enable_capture(self.pg_interfaces)
1669 self.pg_start()
1670
1671 # Server side - verify ICMP type 11 packets
1672 capture = self.pg1.get_capture(len(pkts))
1673 self.verify_capture_out_with_icmp_errors(capture,
1674 src_ip=self.pg1.local_ip4)
1675
1676 def test_dynamic_icmp_errors_in2out_ttl_2(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001677 """ NAT44 handling of error responses to client packets with TTL=2 """
Juraj Slobodab33f4132017-02-08 23:54:21 -08001678
Matus Fabian2ba92e32017-08-21 07:05:03 -07001679 self.nat44_add_address(self.nat_addr)
1680 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1681 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1682 is_inside=0)
Juraj Slobodab33f4132017-02-08 23:54:21 -08001683
1684 # Client side - generate traffic
1685 pkts = self.create_stream_in(self.pg0, self.pg1, ttl=2)
1686 self.pg0.add_stream(pkts)
1687 self.pg_enable_capture(self.pg_interfaces)
1688 self.pg_start()
1689
1690 # Server side - simulate ICMP type 11 response
1691 capture = self.pg1.get_capture(len(pkts))
1692 pkts = [Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07001693 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Juraj Slobodab33f4132017-02-08 23:54:21 -08001694 ICMP(type=11) / packet[IP] for packet in capture]
1695 self.pg1.add_stream(pkts)
1696 self.pg_enable_capture(self.pg_interfaces)
1697 self.pg_start()
1698
1699 # Client side - verify ICMP type 11 packets
1700 capture = self.pg0.get_capture(len(pkts))
1701 self.verify_capture_in_with_icmp_errors(capture, self.pg0)
1702
1703 def test_dynamic_icmp_errors_out2in_ttl_2(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001704 """ NAT44 handling of error responses to server packets with TTL=2 """
Juraj Slobodab33f4132017-02-08 23:54:21 -08001705
Matus Fabian2ba92e32017-08-21 07:05:03 -07001706 self.nat44_add_address(self.nat_addr)
1707 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1708 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1709 is_inside=0)
Juraj Slobodab33f4132017-02-08 23:54:21 -08001710
1711 # Client side - create sessions
1712 pkts = self.create_stream_in(self.pg0, self.pg1)
1713 self.pg0.add_stream(pkts)
1714 self.pg_enable_capture(self.pg_interfaces)
1715 self.pg_start()
1716
1717 # Server side - generate traffic
1718 capture = self.pg1.get_capture(len(pkts))
1719 self.verify_capture_out(capture)
1720 pkts = self.create_stream_out(self.pg1, ttl=2)
1721 self.pg1.add_stream(pkts)
1722 self.pg_enable_capture(self.pg_interfaces)
1723 self.pg_start()
1724
1725 # Client side - simulate ICMP type 11 response
1726 capture = self.pg0.get_capture(len(pkts))
1727 pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1728 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
1729 ICMP(type=11) / packet[IP] for packet in capture]
1730 self.pg0.add_stream(pkts)
1731 self.pg_enable_capture(self.pg_interfaces)
1732 self.pg_start()
1733
1734 # Server side - verify ICMP type 11 packets
1735 capture = self.pg1.get_capture(len(pkts))
1736 self.verify_capture_out_with_icmp_errors(capture)
1737
Juraj Sloboda665e4822017-02-16 17:17:19 -08001738 def test_ping_out_interface_from_outside(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001739 """ Ping NAT44 out interface from outside network """
Juraj Sloboda665e4822017-02-16 17:17:19 -08001740
Matus Fabian2ba92e32017-08-21 07:05:03 -07001741 self.nat44_add_address(self.nat_addr)
1742 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1743 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1744 is_inside=0)
Juraj Sloboda665e4822017-02-16 17:17:19 -08001745
1746 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1747 IP(src=self.pg1.remote_ip4, dst=self.pg1.local_ip4) /
1748 ICMP(id=self.icmp_id_out, type='echo-request'))
1749 pkts = [p]
1750 self.pg1.add_stream(pkts)
1751 self.pg_enable_capture(self.pg_interfaces)
1752 self.pg_start()
1753 capture = self.pg1.get_capture(len(pkts))
Juraj Sloboda665e4822017-02-16 17:17:19 -08001754 packet = capture[0]
1755 try:
1756 self.assertEqual(packet[IP].src, self.pg1.local_ip4)
1757 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
1758 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
1759 self.assertEqual(packet[ICMP].type, 0) # echo reply
1760 except:
1761 self.logger.error(ppp("Unexpected or invalid packet "
1762 "(outside network):", packet))
1763 raise
1764
Juraj Slobodad3677682017-04-14 03:24:45 +02001765 def test_ping_internal_host_from_outside(self):
1766 """ Ping internal host from outside network """
1767
Matus Fabian2ba92e32017-08-21 07:05:03 -07001768 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr)
1769 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1770 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1771 is_inside=0)
Juraj Slobodad3677682017-04-14 03:24:45 +02001772
1773 # out2in
1774 pkt = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07001775 IP(src=self.pg1.remote_ip4, dst=self.nat_addr, ttl=64) /
Juraj Slobodad3677682017-04-14 03:24:45 +02001776 ICMP(id=self.icmp_id_out, type='echo-request'))
1777 self.pg1.add_stream(pkt)
1778 self.pg_enable_capture(self.pg_interfaces)
1779 self.pg_start()
1780 capture = self.pg0.get_capture(1)
Matus Fabian05ca4a32018-09-04 23:45:13 -07001781 self.verify_capture_in(capture, self.pg0)
Juraj Slobodad3677682017-04-14 03:24:45 +02001782 self.assert_equal(capture[0][IP].proto, IP_PROTOS.icmp)
1783
1784 # in2out
1785 pkt = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1786 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4, ttl=64) /
1787 ICMP(id=self.icmp_id_in, type='echo-reply'))
1788 self.pg0.add_stream(pkt)
1789 self.pg_enable_capture(self.pg_interfaces)
1790 self.pg_start()
1791 capture = self.pg1.get_capture(1)
Matus Fabian05ca4a32018-09-04 23:45:13 -07001792 self.verify_capture_out(capture, same_port=True)
Juraj Slobodad3677682017-04-14 03:24:45 +02001793 self.assert_equal(capture[0][IP].proto, IP_PROTOS.icmp)
1794
Matus Fabianc79396e2018-07-23 00:05:22 -07001795 def test_forwarding(self):
Juraj Sloboda7b929792017-11-23 13:20:48 +01001796 """ NAT44 forwarding test """
1797
1798 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1799 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1800 is_inside=0)
1801 self.vapi.nat44_forwarding_enable_disable(1)
1802
1803 real_ip = self.pg0.remote_ip4n
1804 alias_ip = self.nat_addr_n
1805 self.vapi.nat44_add_del_static_mapping(local_ip=real_ip,
1806 external_ip=alias_ip)
1807
1808 try:
Matus Fabianc79396e2018-07-23 00:05:22 -07001809 # static mapping match
Juraj Sloboda7b929792017-11-23 13:20:48 +01001810
1811 pkts = self.create_stream_out(self.pg1)
1812 self.pg1.add_stream(pkts)
1813 self.pg_enable_capture(self.pg_interfaces)
1814 self.pg_start()
1815 capture = self.pg0.get_capture(len(pkts))
1816 self.verify_capture_in(capture, self.pg0)
1817
1818 pkts = self.create_stream_in(self.pg0, self.pg1)
1819 self.pg0.add_stream(pkts)
1820 self.pg_enable_capture(self.pg_interfaces)
1821 self.pg_start()
1822 capture = self.pg1.get_capture(len(pkts))
1823 self.verify_capture_out(capture, same_port=True)
1824
Matus Fabianc79396e2018-07-23 00:05:22 -07001825 # no static mapping match
Juraj Sloboda7b929792017-11-23 13:20:48 +01001826
1827 host0 = self.pg0.remote_hosts[0]
1828 self.pg0.remote_hosts[0] = self.pg0.remote_hosts[1]
1829 try:
1830 pkts = self.create_stream_out(self.pg1,
1831 dst_ip=self.pg0.remote_ip4,
1832 use_inside_ports=True)
1833 self.pg1.add_stream(pkts)
1834 self.pg_enable_capture(self.pg_interfaces)
1835 self.pg_start()
1836 capture = self.pg0.get_capture(len(pkts))
1837 self.verify_capture_in(capture, self.pg0)
1838
1839 pkts = self.create_stream_in(self.pg0, self.pg1)
1840 self.pg0.add_stream(pkts)
1841 self.pg_enable_capture(self.pg_interfaces)
1842 self.pg_start()
1843 capture = self.pg1.get_capture(len(pkts))
1844 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
1845 same_port=True)
1846 finally:
1847 self.pg0.remote_hosts[0] = host0
1848
1849 finally:
1850 self.vapi.nat44_forwarding_enable_disable(0)
1851 self.vapi.nat44_add_del_static_mapping(local_ip=real_ip,
1852 external_ip=alias_ip,
1853 is_add=0)
1854
Matus Fabiande886752016-12-07 03:38:19 -08001855 def test_static_in(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001856 """ 1:1 NAT initialized from inside network """
Matus Fabiande886752016-12-07 03:38:19 -08001857
1858 nat_ip = "10.0.0.10"
1859 self.tcp_port_out = 6303
1860 self.udp_port_out = 6304
1861 self.icmp_id_out = 6305
1862
Matus Fabian2ba92e32017-08-21 07:05:03 -07001863 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
1864 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1865 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1866 is_inside=0)
Matus Fabian5f224992018-01-25 21:59:16 -08001867 sm = self.vapi.nat44_static_mapping_dump()
1868 self.assertEqual(len(sm), 1)
1869 self.assertEqual((sm[0].tag).split('\0', 1)[0], '')
Matus Fabian9dba7812018-01-31 01:13:23 -08001870 self.assertEqual(sm[0].protocol, 0)
1871 self.assertEqual(sm[0].local_port, 0)
1872 self.assertEqual(sm[0].external_port, 0)
Matus Fabiande886752016-12-07 03:38:19 -08001873
1874 # in2out
1875 pkts = self.create_stream_in(self.pg0, self.pg1)
1876 self.pg0.add_stream(pkts)
1877 self.pg_enable_capture(self.pg_interfaces)
1878 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001879 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001880 self.verify_capture_out(capture, nat_ip, True)
1881
1882 # out2in
1883 pkts = self.create_stream_out(self.pg1, nat_ip)
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 def test_static_out(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001891 """ 1:1 NAT initialized from outside network """
Matus Fabiande886752016-12-07 03:38:19 -08001892
1893 nat_ip = "10.0.0.20"
1894 self.tcp_port_out = 6303
1895 self.udp_port_out = 6304
1896 self.icmp_id_out = 6305
Matus Fabian5f224992018-01-25 21:59:16 -08001897 tag = "testTAG"
Matus Fabiande886752016-12-07 03:38:19 -08001898
Matus Fabian5f224992018-01-25 21:59:16 -08001899 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip, tag=tag)
Matus Fabian2ba92e32017-08-21 07:05:03 -07001900 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1901 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1902 is_inside=0)
Matus Fabian5f224992018-01-25 21:59:16 -08001903 sm = self.vapi.nat44_static_mapping_dump()
1904 self.assertEqual(len(sm), 1)
1905 self.assertEqual((sm[0].tag).split('\0', 1)[0], tag)
Matus Fabiande886752016-12-07 03:38:19 -08001906
1907 # out2in
1908 pkts = self.create_stream_out(self.pg1, nat_ip)
1909 self.pg1.add_stream(pkts)
1910 self.pg_enable_capture(self.pg_interfaces)
1911 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001912 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001913 self.verify_capture_in(capture, self.pg0)
1914
1915 # in2out
1916 pkts = self.create_stream_in(self.pg0, self.pg1)
1917 self.pg0.add_stream(pkts)
1918 self.pg_enable_capture(self.pg_interfaces)
1919 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001920 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001921 self.verify_capture_out(capture, nat_ip, True)
1922
1923 def test_static_with_port_in(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001924 """ 1:1 NAPT initialized from inside network """
Matus Fabiande886752016-12-07 03:38:19 -08001925
1926 self.tcp_port_out = 3606
1927 self.udp_port_out = 3607
1928 self.icmp_id_out = 3608
1929
Matus Fabian2ba92e32017-08-21 07:05:03 -07001930 self.nat44_add_address(self.nat_addr)
1931 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1932 self.tcp_port_in, self.tcp_port_out,
1933 proto=IP_PROTOS.tcp)
1934 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1935 self.udp_port_in, self.udp_port_out,
1936 proto=IP_PROTOS.udp)
1937 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1938 self.icmp_id_in, self.icmp_id_out,
1939 proto=IP_PROTOS.icmp)
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)
Matus Fabiande886752016-12-07 03:38:19 -08001943
1944 # in2out
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()
Klement Sekeradab231a2016-12-21 08:50:14 +01001949 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001950 self.verify_capture_out(capture)
1951
1952 # out2in
1953 pkts = self.create_stream_out(self.pg1)
1954 self.pg1.add_stream(pkts)
1955 self.pg_enable_capture(self.pg_interfaces)
1956 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001957 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001958 self.verify_capture_in(capture, self.pg0)
1959
1960 def test_static_with_port_out(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001961 """ 1:1 NAPT initialized from outside network """
Matus Fabiande886752016-12-07 03:38:19 -08001962
1963 self.tcp_port_out = 30606
1964 self.udp_port_out = 30607
1965 self.icmp_id_out = 30608
1966
Matus Fabian2ba92e32017-08-21 07:05:03 -07001967 self.nat44_add_address(self.nat_addr)
1968 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1969 self.tcp_port_in, self.tcp_port_out,
1970 proto=IP_PROTOS.tcp)
1971 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1972 self.udp_port_in, self.udp_port_out,
1973 proto=IP_PROTOS.udp)
1974 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1975 self.icmp_id_in, self.icmp_id_out,
1976 proto=IP_PROTOS.icmp)
1977 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1978 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1979 is_inside=0)
Matus Fabiande886752016-12-07 03:38:19 -08001980
1981 # out2in
1982 pkts = self.create_stream_out(self.pg1)
1983 self.pg1.add_stream(pkts)
1984 self.pg_enable_capture(self.pg_interfaces)
1985 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001986 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001987 self.verify_capture_in(capture, self.pg0)
1988
1989 # in2out
1990 pkts = self.create_stream_in(self.pg0, self.pg1)
1991 self.pg0.add_stream(pkts)
1992 self.pg_enable_capture(self.pg_interfaces)
1993 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001994 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001995 self.verify_capture_out(capture)
1996
1997 def test_static_vrf_aware(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001998 """ 1:1 NAT VRF awareness """
Matus Fabiande886752016-12-07 03:38:19 -08001999
2000 nat_ip1 = "10.0.0.30"
2001 nat_ip2 = "10.0.0.40"
2002 self.tcp_port_out = 6303
2003 self.udp_port_out = 6304
2004 self.icmp_id_out = 6305
2005
Matus Fabian2ba92e32017-08-21 07:05:03 -07002006 self.nat44_add_static_mapping(self.pg4.remote_ip4, nat_ip1,
2007 vrf_id=10)
2008 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip2,
2009 vrf_id=10)
2010 self.vapi.nat44_interface_add_del_feature(self.pg3.sw_if_index,
2011 is_inside=0)
2012 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2013 self.vapi.nat44_interface_add_del_feature(self.pg4.sw_if_index)
Matus Fabiande886752016-12-07 03:38:19 -08002014
Matus Fabian2ba92e32017-08-21 07:05:03 -07002015 # inside interface VRF match NAT44 static mapping VRF
Matus Fabiande886752016-12-07 03:38:19 -08002016 pkts = self.create_stream_in(self.pg4, self.pg3)
2017 self.pg4.add_stream(pkts)
2018 self.pg_enable_capture(self.pg_interfaces)
2019 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002020 capture = self.pg3.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002021 self.verify_capture_out(capture, nat_ip1, True)
2022
Matus Fabian2ba92e32017-08-21 07:05:03 -07002023 # inside interface VRF don't match NAT44 static mapping VRF (packets
Matus Fabiande886752016-12-07 03:38:19 -08002024 # are dropped)
2025 pkts = self.create_stream_in(self.pg0, self.pg3)
2026 self.pg0.add_stream(pkts)
2027 self.pg_enable_capture(self.pg_interfaces)
2028 self.pg_start()
Klement Sekera9225dee2016-12-12 08:36:58 +01002029 self.pg3.assert_nothing_captured()
Matus Fabiande886752016-12-07 03:38:19 -08002030
Matus Fabianb793d092018-01-31 05:50:21 -08002031 def test_dynamic_to_static(self):
2032 """ Switch from dynamic translation to 1:1NAT """
2033 nat_ip = "10.0.0.10"
2034 self.tcp_port_out = 6303
2035 self.udp_port_out = 6304
2036 self.icmp_id_out = 6305
2037
2038 self.nat44_add_address(self.nat_addr)
2039 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2040 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2041 is_inside=0)
2042
2043 # dynamic
2044 pkts = self.create_stream_in(self.pg0, self.pg1)
2045 self.pg0.add_stream(pkts)
2046 self.pg_enable_capture(self.pg_interfaces)
2047 self.pg_start()
2048 capture = self.pg1.get_capture(len(pkts))
2049 self.verify_capture_out(capture)
2050
2051 # 1:1NAT
2052 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
2053 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
2054 self.assertEqual(len(sessions), 0)
2055 pkts = self.create_stream_in(self.pg0, self.pg1)
2056 self.pg0.add_stream(pkts)
2057 self.pg_enable_capture(self.pg_interfaces)
2058 self.pg_start()
2059 capture = self.pg1.get_capture(len(pkts))
2060 self.verify_capture_out(capture, nat_ip, True)
2061
Matus Fabianab7a8052017-11-28 04:29:41 -08002062 def test_identity_nat(self):
2063 """ Identity NAT """
2064
2065 self.vapi.nat44_add_del_identity_mapping(ip=self.pg0.remote_ip4n)
2066 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2067 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2068 is_inside=0)
2069
2070 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
2071 IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
2072 TCP(sport=12345, dport=56789))
2073 self.pg1.add_stream(p)
2074 self.pg_enable_capture(self.pg_interfaces)
2075 self.pg_start()
2076 capture = self.pg0.get_capture(1)
2077 p = capture[0]
2078 try:
2079 ip = p[IP]
2080 tcp = p[TCP]
2081 self.assertEqual(ip.dst, self.pg0.remote_ip4)
2082 self.assertEqual(ip.src, self.pg1.remote_ip4)
2083 self.assertEqual(tcp.dport, 56789)
2084 self.assertEqual(tcp.sport, 12345)
Klement Sekerad81ae412018-05-16 10:52:54 +02002085 self.assert_packet_checksums_valid(p)
Matus Fabianab7a8052017-11-28 04:29:41 -08002086 except:
2087 self.logger.error(ppp("Unexpected or invalid packet:", p))
2088 raise
2089
Matus Fabiane2f4e2f2018-10-07 21:28:23 -07002090 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
2091 self.assertEqual(len(sessions), 0)
Matus Fabian82b4ceb2018-10-11 04:28:48 -07002092 self.vapi.nat44_add_del_identity_mapping(ip=self.pg0.remote_ip4n,
2093 vrf_id=1)
2094 identity_mappings = self.vapi.nat44_identity_mapping_dump()
2095 self.assertEqual(len(identity_mappings), 2)
Matus Fabiane2f4e2f2018-10-07 21:28:23 -07002096
Matus Fabiande886752016-12-07 03:38:19 -08002097 def test_multiple_inside_interfaces(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002098 """ NAT44 multiple non-overlapping address space inside interfaces """
Matus Fabiande886752016-12-07 03:38:19 -08002099
Matus Fabian2ba92e32017-08-21 07:05:03 -07002100 self.nat44_add_address(self.nat_addr)
2101 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2102 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
2103 self.vapi.nat44_interface_add_del_feature(self.pg3.sw_if_index,
2104 is_inside=0)
Matus Fabiande886752016-12-07 03:38:19 -08002105
Matus Fabian2ba92e32017-08-21 07:05:03 -07002106 # between two NAT44 inside interfaces (no translation)
Matus Fabian675a69c2017-01-18 01:46:01 -08002107 pkts = self.create_stream_in(self.pg0, self.pg1)
2108 self.pg0.add_stream(pkts)
2109 self.pg_enable_capture(self.pg_interfaces)
2110 self.pg_start()
2111 capture = self.pg1.get_capture(len(pkts))
2112 self.verify_capture_no_translation(capture, self.pg0, self.pg1)
2113
Matus Fabian2ba92e32017-08-21 07:05:03 -07002114 # from NAT44 inside to interface without NAT44 feature (no translation)
Matus Fabian675a69c2017-01-18 01:46:01 -08002115 pkts = self.create_stream_in(self.pg0, self.pg2)
2116 self.pg0.add_stream(pkts)
2117 self.pg_enable_capture(self.pg_interfaces)
2118 self.pg_start()
2119 capture = self.pg2.get_capture(len(pkts))
2120 self.verify_capture_no_translation(capture, self.pg0, self.pg2)
2121
Matus Fabiande886752016-12-07 03:38:19 -08002122 # in2out 1st interface
2123 pkts = self.create_stream_in(self.pg0, self.pg3)
2124 self.pg0.add_stream(pkts)
2125 self.pg_enable_capture(self.pg_interfaces)
2126 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002127 capture = self.pg3.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002128 self.verify_capture_out(capture)
2129
2130 # out2in 1st interface
2131 pkts = self.create_stream_out(self.pg3)
2132 self.pg3.add_stream(pkts)
2133 self.pg_enable_capture(self.pg_interfaces)
2134 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002135 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002136 self.verify_capture_in(capture, self.pg0)
2137
2138 # in2out 2nd interface
2139 pkts = self.create_stream_in(self.pg1, self.pg3)
2140 self.pg1.add_stream(pkts)
2141 self.pg_enable_capture(self.pg_interfaces)
2142 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002143 capture = self.pg3.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002144 self.verify_capture_out(capture)
2145
2146 # out2in 2nd interface
2147 pkts = self.create_stream_out(self.pg3)
2148 self.pg3.add_stream(pkts)
2149 self.pg_enable_capture(self.pg_interfaces)
2150 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002151 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002152 self.verify_capture_in(capture, self.pg1)
2153
Matus Fabiande886752016-12-07 03:38:19 -08002154 def test_inside_overlapping_interfaces(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002155 """ NAT44 multiple inside interfaces with overlapping address space """
Matus Fabiande886752016-12-07 03:38:19 -08002156
Matus Fabian675a69c2017-01-18 01:46:01 -08002157 static_nat_ip = "10.0.0.10"
Matus Fabian2ba92e32017-08-21 07:05:03 -07002158 self.nat44_add_address(self.nat_addr)
2159 self.vapi.nat44_interface_add_del_feature(self.pg3.sw_if_index,
2160 is_inside=0)
2161 self.vapi.nat44_interface_add_del_feature(self.pg4.sw_if_index)
2162 self.vapi.nat44_interface_add_del_feature(self.pg5.sw_if_index)
2163 self.vapi.nat44_interface_add_del_feature(self.pg6.sw_if_index)
2164 self.nat44_add_static_mapping(self.pg6.remote_ip4, static_nat_ip,
2165 vrf_id=20)
Matus Fabian675a69c2017-01-18 01:46:01 -08002166
Matus Fabian2ba92e32017-08-21 07:05:03 -07002167 # between NAT44 inside interfaces with same VRF (no translation)
Matus Fabian675a69c2017-01-18 01:46:01 -08002168 pkts = self.create_stream_in(self.pg4, self.pg5)
2169 self.pg4.add_stream(pkts)
2170 self.pg_enable_capture(self.pg_interfaces)
2171 self.pg_start()
2172 capture = self.pg5.get_capture(len(pkts))
2173 self.verify_capture_no_translation(capture, self.pg4, self.pg5)
2174
Matus Fabian2ba92e32017-08-21 07:05:03 -07002175 # between NAT44 inside interfaces with different VRF (hairpinning)
Matus Fabian675a69c2017-01-18 01:46:01 -08002176 p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
2177 IP(src=self.pg4.remote_ip4, dst=static_nat_ip) /
2178 TCP(sport=1234, dport=5678))
2179 self.pg4.add_stream(p)
2180 self.pg_enable_capture(self.pg_interfaces)
2181 self.pg_start()
2182 capture = self.pg6.get_capture(1)
2183 p = capture[0]
2184 try:
2185 ip = p[IP]
2186 tcp = p[TCP]
Matus Fabian2ba92e32017-08-21 07:05:03 -07002187 self.assertEqual(ip.src, self.nat_addr)
Matus Fabian675a69c2017-01-18 01:46:01 -08002188 self.assertEqual(ip.dst, self.pg6.remote_ip4)
2189 self.assertNotEqual(tcp.sport, 1234)
2190 self.assertEqual(tcp.dport, 5678)
2191 except:
2192 self.logger.error(ppp("Unexpected or invalid packet:", p))
2193 raise
Matus Fabiande886752016-12-07 03:38:19 -08002194
2195 # in2out 1st interface
2196 pkts = self.create_stream_in(self.pg4, self.pg3)
2197 self.pg4.add_stream(pkts)
2198 self.pg_enable_capture(self.pg_interfaces)
2199 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002200 capture = self.pg3.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002201 self.verify_capture_out(capture)
2202
2203 # out2in 1st interface
2204 pkts = self.create_stream_out(self.pg3)
2205 self.pg3.add_stream(pkts)
2206 self.pg_enable_capture(self.pg_interfaces)
2207 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002208 capture = self.pg4.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002209 self.verify_capture_in(capture, self.pg4)
2210
2211 # in2out 2nd interface
2212 pkts = self.create_stream_in(self.pg5, self.pg3)
2213 self.pg5.add_stream(pkts)
2214 self.pg_enable_capture(self.pg_interfaces)
2215 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002216 capture = self.pg3.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002217 self.verify_capture_out(capture)
2218
2219 # out2in 2nd interface
2220 pkts = self.create_stream_out(self.pg3)
2221 self.pg3.add_stream(pkts)
2222 self.pg_enable_capture(self.pg_interfaces)
2223 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002224 capture = self.pg5.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002225 self.verify_capture_in(capture, self.pg5)
2226
magalik23caa882017-02-08 23:25:45 -08002227 # pg5 session dump
Matus Fabian2ba92e32017-08-21 07:05:03 -07002228 addresses = self.vapi.nat44_address_dump()
magalik23caa882017-02-08 23:25:45 -08002229 self.assertEqual(len(addresses), 1)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002230 sessions = self.vapi.nat44_user_session_dump(self.pg5.remote_ip4n, 10)
magalik23caa882017-02-08 23:25:45 -08002231 self.assertEqual(len(sessions), 3)
2232 for session in sessions:
2233 self.assertFalse(session.is_static)
2234 self.assertEqual(session.inside_ip_address[0:4],
2235 self.pg5.remote_ip4n)
2236 self.assertEqual(session.outside_ip_address,
2237 addresses[0].ip_address)
2238 self.assertEqual(sessions[0].protocol, IP_PROTOS.tcp)
2239 self.assertEqual(sessions[1].protocol, IP_PROTOS.udp)
2240 self.assertEqual(sessions[2].protocol, IP_PROTOS.icmp)
2241 self.assertEqual(sessions[0].inside_port, self.tcp_port_in)
2242 self.assertEqual(sessions[1].inside_port, self.udp_port_in)
2243 self.assertEqual(sessions[2].inside_port, self.icmp_id_in)
2244 self.assertEqual(sessions[0].outside_port, self.tcp_port_out)
2245 self.assertEqual(sessions[1].outside_port, self.udp_port_out)
2246 self.assertEqual(sessions[2].outside_port, self.icmp_id_out)
2247
Matus Fabiande886752016-12-07 03:38:19 -08002248 # in2out 3rd interface
2249 pkts = self.create_stream_in(self.pg6, self.pg3)
2250 self.pg6.add_stream(pkts)
2251 self.pg_enable_capture(self.pg_interfaces)
2252 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002253 capture = self.pg3.get_capture(len(pkts))
Matus Fabian675a69c2017-01-18 01:46:01 -08002254 self.verify_capture_out(capture, static_nat_ip, True)
Matus Fabiande886752016-12-07 03:38:19 -08002255
2256 # out2in 3rd interface
Matus Fabian675a69c2017-01-18 01:46:01 -08002257 pkts = self.create_stream_out(self.pg3, static_nat_ip)
Matus Fabiande886752016-12-07 03:38:19 -08002258 self.pg3.add_stream(pkts)
2259 self.pg_enable_capture(self.pg_interfaces)
2260 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002261 capture = self.pg6.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002262 self.verify_capture_in(capture, self.pg6)
2263
magalik23caa882017-02-08 23:25:45 -08002264 # general user and session dump verifications
Matus Fabian2ba92e32017-08-21 07:05:03 -07002265 users = self.vapi.nat44_user_dump()
Paul Vinciguerra3d2df212018-11-24 23:19:53 -08002266 self.assertGreaterEqual(len(users), 3)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002267 addresses = self.vapi.nat44_address_dump()
magalik23caa882017-02-08 23:25:45 -08002268 self.assertEqual(len(addresses), 1)
2269 for user in users:
Matus Fabian2ba92e32017-08-21 07:05:03 -07002270 sessions = self.vapi.nat44_user_session_dump(user.ip_address,
2271 user.vrf_id)
magalik23caa882017-02-08 23:25:45 -08002272 for session in sessions:
2273 self.assertEqual(user.ip_address, session.inside_ip_address)
2274 self.assertTrue(session.total_bytes > session.total_pkts > 0)
2275 self.assertTrue(session.protocol in
2276 [IP_PROTOS.tcp, IP_PROTOS.udp,
2277 IP_PROTOS.icmp])
Matus Fabian70a26ac2018-05-14 06:20:28 -07002278 self.assertFalse(session.ext_host_valid)
magalik23caa882017-02-08 23:25:45 -08002279
2280 # pg4 session dump
Matus Fabian2ba92e32017-08-21 07:05:03 -07002281 sessions = self.vapi.nat44_user_session_dump(self.pg4.remote_ip4n, 10)
Paul Vinciguerra3d2df212018-11-24 23:19:53 -08002282 self.assertGreaterEqual(len(sessions), 4)
magalik23caa882017-02-08 23:25:45 -08002283 for session in sessions:
2284 self.assertFalse(session.is_static)
2285 self.assertEqual(session.inside_ip_address[0:4],
2286 self.pg4.remote_ip4n)
2287 self.assertEqual(session.outside_ip_address,
2288 addresses[0].ip_address)
2289
2290 # pg6 session dump
Matus Fabian2ba92e32017-08-21 07:05:03 -07002291 sessions = self.vapi.nat44_user_session_dump(self.pg6.remote_ip4n, 20)
Paul Vinciguerra3d2df212018-11-24 23:19:53 -08002292 self.assertGreaterEqual(len(sessions), 3)
magalik23caa882017-02-08 23:25:45 -08002293 for session in sessions:
2294 self.assertTrue(session.is_static)
2295 self.assertEqual(session.inside_ip_address[0:4],
2296 self.pg6.remote_ip4n)
Matus Fabian34931eb2019-02-26 09:05:23 -08002297 self.assertEqual(session.outside_ip_address,
2298 socket.inet_pton(socket.AF_INET, static_nat_ip))
magalik23caa882017-02-08 23:25:45 -08002299 self.assertTrue(session.inside_port in
2300 [self.tcp_port_in, self.udp_port_in,
2301 self.icmp_id_in])
2302
Matus Fabianf78a70d2016-12-12 04:30:39 -08002303 def test_hairpinning(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002304 """ NAT44 hairpinning - 1:1 NAPT """
Matus Fabianf78a70d2016-12-12 04:30:39 -08002305
2306 host = self.pg0.remote_hosts[0]
2307 server = self.pg0.remote_hosts[1]
2308 host_in_port = 1234
2309 host_out_port = 0
2310 server_in_port = 5678
2311 server_out_port = 8765
2312
Matus Fabian2ba92e32017-08-21 07:05:03 -07002313 self.nat44_add_address(self.nat_addr)
2314 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2315 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2316 is_inside=0)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002317 # add static mapping for server
Matus Fabian2ba92e32017-08-21 07:05:03 -07002318 self.nat44_add_static_mapping(server.ip4, self.nat_addr,
2319 server_in_port, server_out_port,
2320 proto=IP_PROTOS.tcp)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002321
2322 # send packet from host to server
2323 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002324 IP(src=host.ip4, dst=self.nat_addr) /
Matus Fabianf78a70d2016-12-12 04:30:39 -08002325 TCP(sport=host_in_port, dport=server_out_port))
2326 self.pg0.add_stream(p)
2327 self.pg_enable_capture(self.pg_interfaces)
2328 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002329 capture = self.pg0.get_capture(1)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002330 p = capture[0]
2331 try:
2332 ip = p[IP]
2333 tcp = p[TCP]
Matus Fabian2ba92e32017-08-21 07:05:03 -07002334 self.assertEqual(ip.src, self.nat_addr)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002335 self.assertEqual(ip.dst, server.ip4)
2336 self.assertNotEqual(tcp.sport, host_in_port)
2337 self.assertEqual(tcp.dport, server_in_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02002338 self.assert_packet_checksums_valid(p)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002339 host_out_port = tcp.sport
2340 except:
Klement Sekera9225dee2016-12-12 08:36:58 +01002341 self.logger.error(ppp("Unexpected or invalid packet:", p))
Matus Fabianf78a70d2016-12-12 04:30:39 -08002342 raise
2343
2344 # send reply from server to host
2345 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002346 IP(src=server.ip4, dst=self.nat_addr) /
Matus Fabianf78a70d2016-12-12 04:30:39 -08002347 TCP(sport=server_in_port, dport=host_out_port))
2348 self.pg0.add_stream(p)
2349 self.pg_enable_capture(self.pg_interfaces)
2350 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002351 capture = self.pg0.get_capture(1)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002352 p = capture[0]
2353 try:
2354 ip = p[IP]
2355 tcp = p[TCP]
Matus Fabian2ba92e32017-08-21 07:05:03 -07002356 self.assertEqual(ip.src, self.nat_addr)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002357 self.assertEqual(ip.dst, host.ip4)
2358 self.assertEqual(tcp.sport, server_out_port)
2359 self.assertEqual(tcp.dport, host_in_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02002360 self.assert_packet_checksums_valid(p)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002361 except:
Matus Fabiane82488f2018-01-18 03:38:45 -08002362 self.logger.error(ppp("Unexpected or invalid packet:", p))
Matus Fabianf78a70d2016-12-12 04:30:39 -08002363 raise
2364
Matus Fabian6fa74c62017-06-05 05:55:48 -07002365 def test_hairpinning2(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002366 """ NAT44 hairpinning - 1:1 NAT"""
Matus Fabian6fa74c62017-06-05 05:55:48 -07002367
2368 server1_nat_ip = "10.0.0.10"
2369 server2_nat_ip = "10.0.0.11"
2370 host = self.pg0.remote_hosts[0]
2371 server1 = self.pg0.remote_hosts[1]
2372 server2 = self.pg0.remote_hosts[2]
2373 server_tcp_port = 22
2374 server_udp_port = 20
2375
Matus Fabian2ba92e32017-08-21 07:05:03 -07002376 self.nat44_add_address(self.nat_addr)
2377 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2378 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2379 is_inside=0)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002380
2381 # add static mapping for servers
Matus Fabian2ba92e32017-08-21 07:05:03 -07002382 self.nat44_add_static_mapping(server1.ip4, server1_nat_ip)
2383 self.nat44_add_static_mapping(server2.ip4, server2_nat_ip)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002384
2385 # host to server1
2386 pkts = []
2387 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2388 IP(src=host.ip4, dst=server1_nat_ip) /
2389 TCP(sport=self.tcp_port_in, dport=server_tcp_port))
2390 pkts.append(p)
2391 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2392 IP(src=host.ip4, dst=server1_nat_ip) /
2393 UDP(sport=self.udp_port_in, dport=server_udp_port))
2394 pkts.append(p)
2395 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2396 IP(src=host.ip4, dst=server1_nat_ip) /
2397 ICMP(id=self.icmp_id_in, type='echo-request'))
2398 pkts.append(p)
2399 self.pg0.add_stream(pkts)
2400 self.pg_enable_capture(self.pg_interfaces)
2401 self.pg_start()
2402 capture = self.pg0.get_capture(len(pkts))
2403 for packet in capture:
2404 try:
Matus Fabian2ba92e32017-08-21 07:05:03 -07002405 self.assertEqual(packet[IP].src, self.nat_addr)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002406 self.assertEqual(packet[IP].dst, server1.ip4)
2407 if packet.haslayer(TCP):
2408 self.assertNotEqual(packet[TCP].sport, self.tcp_port_in)
2409 self.assertEqual(packet[TCP].dport, server_tcp_port)
2410 self.tcp_port_out = packet[TCP].sport
Klement Sekerad81ae412018-05-16 10:52:54 +02002411 self.assert_packet_checksums_valid(packet)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002412 elif packet.haslayer(UDP):
2413 self.assertNotEqual(packet[UDP].sport, self.udp_port_in)
2414 self.assertEqual(packet[UDP].dport, server_udp_port)
2415 self.udp_port_out = packet[UDP].sport
2416 else:
2417 self.assertNotEqual(packet[ICMP].id, self.icmp_id_in)
2418 self.icmp_id_out = packet[ICMP].id
2419 except:
2420 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2421 raise
2422
2423 # server1 to host
2424 pkts = []
2425 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002426 IP(src=server1.ip4, dst=self.nat_addr) /
Matus Fabian6fa74c62017-06-05 05:55:48 -07002427 TCP(sport=server_tcp_port, dport=self.tcp_port_out))
2428 pkts.append(p)
2429 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002430 IP(src=server1.ip4, dst=self.nat_addr) /
Matus Fabian6fa74c62017-06-05 05:55:48 -07002431 UDP(sport=server_udp_port, dport=self.udp_port_out))
2432 pkts.append(p)
2433 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002434 IP(src=server1.ip4, dst=self.nat_addr) /
Matus Fabian6fa74c62017-06-05 05:55:48 -07002435 ICMP(id=self.icmp_id_out, type='echo-reply'))
2436 pkts.append(p)
2437 self.pg0.add_stream(pkts)
2438 self.pg_enable_capture(self.pg_interfaces)
2439 self.pg_start()
2440 capture = self.pg0.get_capture(len(pkts))
2441 for packet in capture:
2442 try:
2443 self.assertEqual(packet[IP].src, server1_nat_ip)
2444 self.assertEqual(packet[IP].dst, host.ip4)
2445 if packet.haslayer(TCP):
2446 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
2447 self.assertEqual(packet[TCP].sport, server_tcp_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02002448 self.assert_packet_checksums_valid(packet)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002449 elif packet.haslayer(UDP):
2450 self.assertEqual(packet[UDP].dport, self.udp_port_in)
2451 self.assertEqual(packet[UDP].sport, server_udp_port)
2452 else:
2453 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
2454 except:
2455 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2456 raise
2457
2458 # server2 to server1
2459 pkts = []
2460 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2461 IP(src=server2.ip4, dst=server1_nat_ip) /
2462 TCP(sport=self.tcp_port_in, dport=server_tcp_port))
2463 pkts.append(p)
2464 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2465 IP(src=server2.ip4, dst=server1_nat_ip) /
2466 UDP(sport=self.udp_port_in, dport=server_udp_port))
2467 pkts.append(p)
2468 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2469 IP(src=server2.ip4, dst=server1_nat_ip) /
2470 ICMP(id=self.icmp_id_in, type='echo-request'))
2471 pkts.append(p)
2472 self.pg0.add_stream(pkts)
2473 self.pg_enable_capture(self.pg_interfaces)
2474 self.pg_start()
2475 capture = self.pg0.get_capture(len(pkts))
2476 for packet in capture:
2477 try:
2478 self.assertEqual(packet[IP].src, server2_nat_ip)
2479 self.assertEqual(packet[IP].dst, server1.ip4)
2480 if packet.haslayer(TCP):
2481 self.assertEqual(packet[TCP].sport, self.tcp_port_in)
2482 self.assertEqual(packet[TCP].dport, server_tcp_port)
2483 self.tcp_port_out = packet[TCP].sport
Klement Sekerad81ae412018-05-16 10:52:54 +02002484 self.assert_packet_checksums_valid(packet)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002485 elif packet.haslayer(UDP):
2486 self.assertEqual(packet[UDP].sport, self.udp_port_in)
2487 self.assertEqual(packet[UDP].dport, server_udp_port)
2488 self.udp_port_out = packet[UDP].sport
2489 else:
2490 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
2491 self.icmp_id_out = packet[ICMP].id
2492 except:
2493 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2494 raise
2495
2496 # server1 to server2
2497 pkts = []
2498 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2499 IP(src=server1.ip4, dst=server2_nat_ip) /
2500 TCP(sport=server_tcp_port, dport=self.tcp_port_out))
2501 pkts.append(p)
2502 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2503 IP(src=server1.ip4, dst=server2_nat_ip) /
2504 UDP(sport=server_udp_port, dport=self.udp_port_out))
2505 pkts.append(p)
2506 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2507 IP(src=server1.ip4, dst=server2_nat_ip) /
2508 ICMP(id=self.icmp_id_out, type='echo-reply'))
2509 pkts.append(p)
2510 self.pg0.add_stream(pkts)
2511 self.pg_enable_capture(self.pg_interfaces)
2512 self.pg_start()
2513 capture = self.pg0.get_capture(len(pkts))
2514 for packet in capture:
2515 try:
2516 self.assertEqual(packet[IP].src, server1_nat_ip)
2517 self.assertEqual(packet[IP].dst, server2.ip4)
2518 if packet.haslayer(TCP):
2519 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
2520 self.assertEqual(packet[TCP].sport, server_tcp_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02002521 self.assert_packet_checksums_valid(packet)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002522 elif packet.haslayer(UDP):
2523 self.assertEqual(packet[UDP].dport, self.udp_port_in)
2524 self.assertEqual(packet[UDP].sport, server_udp_port)
2525 else:
2526 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
2527 except:
2528 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2529 raise
2530
Matus Fabian9902fcd2016-12-21 23:58:46 -08002531 def test_max_translations_per_user(self):
2532 """ MAX translations per user - recycle the least recently used """
2533
Matus Fabian2ba92e32017-08-21 07:05:03 -07002534 self.nat44_add_address(self.nat_addr)
2535 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2536 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2537 is_inside=0)
Matus Fabian9902fcd2016-12-21 23:58:46 -08002538
2539 # get maximum number of translations per user
Matus Fabian2ba92e32017-08-21 07:05:03 -07002540 nat44_config = self.vapi.nat_show_config()
Matus Fabian9902fcd2016-12-21 23:58:46 -08002541
2542 # send more than maximum number of translations per user packets
Matus Fabian2ba92e32017-08-21 07:05:03 -07002543 pkts_num = nat44_config.max_translations_per_user + 5
Matus Fabian9902fcd2016-12-21 23:58:46 -08002544 pkts = []
2545 for port in range(0, pkts_num):
2546 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2547 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2548 TCP(sport=1025 + port))
2549 pkts.append(p)
2550 self.pg0.add_stream(pkts)
2551 self.pg_enable_capture(self.pg_interfaces)
2552 self.pg_start()
2553
2554 # verify number of translated packet
Klement Sekeradab231a2016-12-21 08:50:14 +01002555 self.pg1.get_capture(pkts_num)
Matus Fabian9902fcd2016-12-21 23:58:46 -08002556
Matus Fabian132dc492018-05-09 04:51:03 -07002557 users = self.vapi.nat44_user_dump()
2558 for user in users:
2559 if user.ip_address == self.pg0.remote_ip4n:
2560 self.assertEqual(user.nsessions,
2561 nat44_config.max_translations_per_user)
2562 self.assertEqual(user.nstaticsessions, 0)
2563
2564 tcp_port = 22
2565 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
2566 tcp_port, tcp_port,
2567 proto=IP_PROTOS.tcp)
2568 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2569 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2570 TCP(sport=tcp_port))
2571 self.pg0.add_stream(p)
2572 self.pg_enable_capture(self.pg_interfaces)
2573 self.pg_start()
2574 self.pg1.get_capture(1)
2575 users = self.vapi.nat44_user_dump()
2576 for user in users:
2577 if user.ip_address == self.pg0.remote_ip4n:
2578 self.assertEqual(user.nsessions,
2579 nat44_config.max_translations_per_user - 1)
2580 self.assertEqual(user.nstaticsessions, 1)
2581
Matus Fabian8bf68e82017-01-12 04:24:35 -08002582 def test_interface_addr(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002583 """ Acquire NAT44 addresses from interface """
Ole Troane1ade682019-03-04 23:55:43 +01002584 self.vapi.nat44_add_del_interface_addr(self.pg7.sw_if_index)
Matus Fabian8bf68e82017-01-12 04:24:35 -08002585
2586 # no address in NAT pool
Matus Fabian2ba92e32017-08-21 07:05:03 -07002587 adresses = self.vapi.nat44_address_dump()
Matus Fabian8bf68e82017-01-12 04:24:35 -08002588 self.assertEqual(0, len(adresses))
2589
2590 # configure interface address and check NAT address pool
2591 self.pg7.config_ip4()
Matus Fabian2ba92e32017-08-21 07:05:03 -07002592 adresses = self.vapi.nat44_address_dump()
Matus Fabian8bf68e82017-01-12 04:24:35 -08002593 self.assertEqual(1, len(adresses))
Matus Fabian36532bd2017-01-23 23:42:28 -08002594 self.assertEqual(adresses[0].ip_address[0:4], self.pg7.local_ip4n)
Matus Fabian8bf68e82017-01-12 04:24:35 -08002595
2596 # remove interface address and check NAT address pool
2597 self.pg7.unconfig_ip4()
Matus Fabian2ba92e32017-08-21 07:05:03 -07002598 adresses = self.vapi.nat44_address_dump()
Matus Fabian8bf68e82017-01-12 04:24:35 -08002599 self.assertEqual(0, len(adresses))
2600
Matus Fabian36532bd2017-01-23 23:42:28 -08002601 def test_interface_addr_static_mapping(self):
2602 """ Static mapping with addresses from interface """
Matus Fabian5f224992018-01-25 21:59:16 -08002603 tag = "testTAG"
2604
Ole Troane1ade682019-03-04 23:55:43 +01002605 self.vapi.nat44_add_del_interface_addr(self.pg7.sw_if_index)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002606 self.nat44_add_static_mapping(
2607 '1.2.3.4',
Matus Fabian5f224992018-01-25 21:59:16 -08002608 external_sw_if_index=self.pg7.sw_if_index,
2609 tag=tag)
Matus Fabian36532bd2017-01-23 23:42:28 -08002610
Matus Fabiane22e5462017-02-14 23:33:43 -08002611 # static mappings with external interface
Matus Fabian2ba92e32017-08-21 07:05:03 -07002612 static_mappings = self.vapi.nat44_static_mapping_dump()
Matus Fabiane22e5462017-02-14 23:33:43 -08002613 self.assertEqual(1, len(static_mappings))
2614 self.assertEqual(self.pg7.sw_if_index,
2615 static_mappings[0].external_sw_if_index)
Matus Fabian5f224992018-01-25 21:59:16 -08002616 self.assertEqual((static_mappings[0].tag).split('\0', 1)[0], tag)
Matus Fabian36532bd2017-01-23 23:42:28 -08002617
2618 # configure interface address and check static mappings
2619 self.pg7.config_ip4()
Matus Fabian2ba92e32017-08-21 07:05:03 -07002620 static_mappings = self.vapi.nat44_static_mapping_dump()
Matus Fabianea2600a2018-03-28 04:06:26 -07002621 self.assertEqual(2, len(static_mappings))
2622 resolved = False
2623 for sm in static_mappings:
2624 if sm.external_sw_if_index == 0xFFFFFFFF:
2625 self.assertEqual(sm.external_ip_address[0:4],
2626 self.pg7.local_ip4n)
2627 self.assertEqual((sm.tag).split('\0', 1)[0], tag)
2628 resolved = True
2629 self.assertTrue(resolved)
Matus Fabian36532bd2017-01-23 23:42:28 -08002630
2631 # remove interface address and check static mappings
2632 self.pg7.unconfig_ip4()
Matus Fabian2ba92e32017-08-21 07:05:03 -07002633 static_mappings = self.vapi.nat44_static_mapping_dump()
Matus Fabianea2600a2018-03-28 04:06:26 -07002634 self.assertEqual(1, len(static_mappings))
2635 self.assertEqual(self.pg7.sw_if_index,
2636 static_mappings[0].external_sw_if_index)
2637 self.assertEqual((static_mappings[0].tag).split('\0', 1)[0], tag)
2638
2639 # configure interface address again and check static mappings
2640 self.pg7.config_ip4()
2641 static_mappings = self.vapi.nat44_static_mapping_dump()
2642 self.assertEqual(2, len(static_mappings))
2643 resolved = False
2644 for sm in static_mappings:
2645 if sm.external_sw_if_index == 0xFFFFFFFF:
2646 self.assertEqual(sm.external_ip_address[0:4],
2647 self.pg7.local_ip4n)
2648 self.assertEqual((sm.tag).split('\0', 1)[0], tag)
2649 resolved = True
2650 self.assertTrue(resolved)
2651
2652 # remove static mapping
2653 self.nat44_add_static_mapping(
2654 '1.2.3.4',
2655 external_sw_if_index=self.pg7.sw_if_index,
2656 tag=tag,
2657 is_add=0)
2658 static_mappings = self.vapi.nat44_static_mapping_dump()
Matus Fabian36532bd2017-01-23 23:42:28 -08002659 self.assertEqual(0, len(static_mappings))
2660
Matus Fabianab7a8052017-11-28 04:29:41 -08002661 def test_interface_addr_identity_nat(self):
2662 """ Identity NAT with addresses from interface """
2663
2664 port = 53053
Ole Troane1ade682019-03-04 23:55:43 +01002665 self.vapi.nat44_add_del_interface_addr(self.pg7.sw_if_index)
Matus Fabianab7a8052017-11-28 04:29:41 -08002666 self.vapi.nat44_add_del_identity_mapping(
2667 sw_if_index=self.pg7.sw_if_index,
2668 port=port,
2669 protocol=IP_PROTOS.tcp,
2670 addr_only=0)
2671
2672 # identity mappings with external interface
2673 identity_mappings = self.vapi.nat44_identity_mapping_dump()
2674 self.assertEqual(1, len(identity_mappings))
2675 self.assertEqual(self.pg7.sw_if_index,
2676 identity_mappings[0].sw_if_index)
2677
2678 # configure interface address and check identity mappings
2679 self.pg7.config_ip4()
2680 identity_mappings = self.vapi.nat44_identity_mapping_dump()
Matus Fabianea2600a2018-03-28 04:06:26 -07002681 resolved = False
2682 self.assertEqual(2, len(identity_mappings))
2683 for sm in identity_mappings:
2684 if sm.sw_if_index == 0xFFFFFFFF:
2685 self.assertEqual(identity_mappings[0].ip_address,
2686 self.pg7.local_ip4n)
2687 self.assertEqual(port, identity_mappings[0].port)
2688 self.assertEqual(IP_PROTOS.tcp, identity_mappings[0].protocol)
2689 resolved = True
2690 self.assertTrue(resolved)
Matus Fabianab7a8052017-11-28 04:29:41 -08002691
2692 # remove interface address and check identity mappings
2693 self.pg7.unconfig_ip4()
2694 identity_mappings = self.vapi.nat44_identity_mapping_dump()
Matus Fabianea2600a2018-03-28 04:06:26 -07002695 self.assertEqual(1, len(identity_mappings))
2696 self.assertEqual(self.pg7.sw_if_index,
2697 identity_mappings[0].sw_if_index)
Matus Fabianab7a8052017-11-28 04:29:41 -08002698
Matus Fabianeea28d72017-01-13 04:15:54 -08002699 def test_ipfix_nat44_sess(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002700 """ IPFIX logging NAT44 session created/delted """
Matus Fabian6631e9c2017-05-24 01:52:20 -07002701 self.ipfix_domain_id = 10
2702 self.ipfix_src_port = 20202
2703 colector_port = 30303
2704 bind_layers(UDP, IPFIX, dport=30303)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002705 self.nat44_add_address(self.nat_addr)
2706 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2707 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2708 is_inside=0)
Matus Fabianeea28d72017-01-13 04:15:54 -08002709 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
2710 src_address=self.pg3.local_ip4n,
2711 path_mtu=512,
Matus Fabian6631e9c2017-05-24 01:52:20 -07002712 template_interval=10,
2713 collector_port=colector_port)
Ole Troane1ade682019-03-04 23:55:43 +01002714 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
2715 src_port=self.ipfix_src_port)
Matus Fabianeea28d72017-01-13 04:15:54 -08002716
2717 pkts = self.create_stream_in(self.pg0, self.pg1)
2718 self.pg0.add_stream(pkts)
2719 self.pg_enable_capture(self.pg_interfaces)
2720 self.pg_start()
2721 capture = self.pg1.get_capture(len(pkts))
2722 self.verify_capture_out(capture)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002723 self.nat44_add_address(self.nat_addr, is_add=0)
Matus Fabianeea28d72017-01-13 04:15:54 -08002724 self.vapi.cli("ipfix flush") # FIXME this should be an API call
Matus Fabiana431ad12018-01-04 04:03:14 -08002725 capture = self.pg3.get_capture(9)
Matus Fabianeea28d72017-01-13 04:15:54 -08002726 ipfix = IPFIXDecoder()
2727 # first load template
2728 for p in capture:
2729 self.assertTrue(p.haslayer(IPFIX))
Matus Fabian6631e9c2017-05-24 01:52:20 -07002730 self.assertEqual(p[IP].src, self.pg3.local_ip4)
2731 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2732 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2733 self.assertEqual(p[UDP].dport, colector_port)
2734 self.assertEqual(p[IPFIX].observationDomainID,
2735 self.ipfix_domain_id)
Matus Fabianeea28d72017-01-13 04:15:54 -08002736 if p.haslayer(Template):
2737 ipfix.add_template(p.getlayer(Template))
2738 # verify events in data set
2739 for p in capture:
2740 if p.haslayer(Data):
2741 data = ipfix.decode_data_set(p.getlayer(Set))
2742 self.verify_ipfix_nat44_ses(data)
2743
2744 def test_ipfix_addr_exhausted(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002745 """ IPFIX logging NAT addresses exhausted """
2746 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2747 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2748 is_inside=0)
Matus Fabianeea28d72017-01-13 04:15:54 -08002749 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
2750 src_address=self.pg3.local_ip4n,
2751 path_mtu=512,
2752 template_interval=10)
Ole Troane1ade682019-03-04 23:55:43 +01002753 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
2754 src_port=self.ipfix_src_port)
Matus Fabianeea28d72017-01-13 04:15:54 -08002755
2756 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
2757 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2758 TCP(sport=3025))
2759 self.pg0.add_stream(p)
2760 self.pg_enable_capture(self.pg_interfaces)
2761 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07002762 self.pg1.assert_nothing_captured()
2763 sleep(1)
Matus Fabianeea28d72017-01-13 04:15:54 -08002764 self.vapi.cli("ipfix flush") # FIXME this should be an API call
Matus Fabiana431ad12018-01-04 04:03:14 -08002765 capture = self.pg3.get_capture(9)
Matus Fabianeea28d72017-01-13 04:15:54 -08002766 ipfix = IPFIXDecoder()
2767 # first load template
2768 for p in capture:
2769 self.assertTrue(p.haslayer(IPFIX))
Matus Fabian6631e9c2017-05-24 01:52:20 -07002770 self.assertEqual(p[IP].src, self.pg3.local_ip4)
2771 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2772 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2773 self.assertEqual(p[UDP].dport, 4739)
2774 self.assertEqual(p[IPFIX].observationDomainID,
2775 self.ipfix_domain_id)
Matus Fabianeea28d72017-01-13 04:15:54 -08002776 if p.haslayer(Template):
2777 ipfix.add_template(p.getlayer(Template))
2778 # verify events in data set
2779 for p in capture:
2780 if p.haslayer(Data):
2781 data = ipfix.decode_data_set(p.getlayer(Set))
2782 self.verify_ipfix_addr_exhausted(data)
2783
Paul Vinciguerradefde0f2018-12-06 07:46:13 -08002784 @unittest.skipUnless(running_extended_tests, "part of extended tests")
Matus Fabiana431ad12018-01-04 04:03:14 -08002785 def test_ipfix_max_sessions(self):
2786 """ IPFIX logging maximum session entries exceeded """
2787 self.nat44_add_address(self.nat_addr)
2788 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2789 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2790 is_inside=0)
2791
2792 nat44_config = self.vapi.nat_show_config()
2793 max_sessions = 10 * nat44_config.translation_buckets
2794
2795 pkts = []
2796 for i in range(0, max_sessions):
2797 src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
2798 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2799 IP(src=src, dst=self.pg1.remote_ip4) /
2800 TCP(sport=1025))
2801 pkts.append(p)
2802 self.pg0.add_stream(pkts)
2803 self.pg_enable_capture(self.pg_interfaces)
2804 self.pg_start()
2805
2806 self.pg1.get_capture(max_sessions)
2807 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
2808 src_address=self.pg3.local_ip4n,
2809 path_mtu=512,
2810 template_interval=10)
Ole Troane1ade682019-03-04 23:55:43 +01002811 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
2812 src_port=self.ipfix_src_port)
Matus Fabiana431ad12018-01-04 04:03:14 -08002813
2814 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2815 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2816 TCP(sport=1025))
2817 self.pg0.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()
2821 sleep(1)
Matus Fabiana431ad12018-01-04 04:03:14 -08002822 self.vapi.cli("ipfix flush") # FIXME this should be an API call
2823 capture = self.pg3.get_capture(9)
2824 ipfix = IPFIXDecoder()
2825 # first load template
2826 for p in capture:
2827 self.assertTrue(p.haslayer(IPFIX))
2828 self.assertEqual(p[IP].src, self.pg3.local_ip4)
2829 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2830 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2831 self.assertEqual(p[UDP].dport, 4739)
2832 self.assertEqual(p[IPFIX].observationDomainID,
2833 self.ipfix_domain_id)
2834 if p.haslayer(Template):
2835 ipfix.add_template(p.getlayer(Template))
2836 # verify events in data set
2837 for p in capture:
2838 if p.haslayer(Data):
2839 data = ipfix.decode_data_set(p.getlayer(Set))
2840 self.verify_ipfix_max_sessions(data, max_sessions)
2841
Matus Fabianad1f3e12018-11-28 21:26:34 -08002842 def test_syslog_apmap(self):
2843 """ Test syslog address and port mapping creation and deletion """
2844 self.vapi.syslog_set_filter(SYSLOG_SEVERITY.INFO)
Ole Troanf159f582019-02-28 20:20:47 +01002845 self.vapi.syslog_set_sender(self.pg3.local_ip4n, self.pg3.remote_ip4n)
Matus Fabianad1f3e12018-11-28 21:26:34 -08002846 self.nat44_add_address(self.nat_addr)
2847 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2848 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2849 is_inside=0)
2850
2851 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2852 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2853 TCP(sport=self.tcp_port_in, dport=20))
2854 self.pg0.add_stream(p)
2855 self.pg_enable_capture(self.pg_interfaces)
2856 self.pg_start()
2857 capture = self.pg1.get_capture(1)
2858 self.tcp_port_out = capture[0][TCP].sport
2859 capture = self.pg3.get_capture(1)
2860 self.verify_syslog_apmap(capture[0][Raw].load)
2861
2862 self.pg_enable_capture(self.pg_interfaces)
2863 self.pg_start()
2864 self.nat44_add_address(self.nat_addr, is_add=0)
2865 capture = self.pg3.get_capture(1)
2866 self.verify_syslog_apmap(capture[0][Raw].load, False)
2867
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002868 def test_pool_addr_fib(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002869 """ NAT44 add pool addresses to FIB """
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002870 static_addr = '10.0.0.10'
Matus Fabian2ba92e32017-08-21 07:05:03 -07002871 self.nat44_add_address(self.nat_addr)
2872 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2873 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2874 is_inside=0)
2875 self.nat44_add_static_mapping(self.pg0.remote_ip4, static_addr)
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002876
Matus Fabian2ba92e32017-08-21 07:05:03 -07002877 # NAT44 address
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002878 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002879 ARP(op=ARP.who_has, pdst=self.nat_addr,
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002880 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2881 self.pg1.add_stream(p)
2882 self.pg_enable_capture(self.pg_interfaces)
2883 self.pg_start()
2884 capture = self.pg1.get_capture(1)
2885 self.assertTrue(capture[0].haslayer(ARP))
2886 self.assertTrue(capture[0][ARP].op, ARP.is_at)
2887
2888 # 1:1 NAT address
2889 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2890 ARP(op=ARP.who_has, pdst=static_addr,
2891 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2892 self.pg1.add_stream(p)
2893 self.pg_enable_capture(self.pg_interfaces)
2894 self.pg_start()
2895 capture = self.pg1.get_capture(1)
2896 self.assertTrue(capture[0].haslayer(ARP))
2897 self.assertTrue(capture[0][ARP].op, ARP.is_at)
2898
Matus Fabian2ba92e32017-08-21 07:05:03 -07002899 # send ARP to non-NAT44 interface
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002900 p = (Ether(src=self.pg2.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002901 ARP(op=ARP.who_has, pdst=self.nat_addr,
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002902 psrc=self.pg2.remote_ip4, hwsrc=self.pg2.remote_mac))
2903 self.pg2.add_stream(p)
2904 self.pg_enable_capture(self.pg_interfaces)
2905 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07002906 self.pg1.assert_nothing_captured()
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002907
2908 # remove addresses and verify
Matus Fabian2ba92e32017-08-21 07:05:03 -07002909 self.nat44_add_address(self.nat_addr, is_add=0)
2910 self.nat44_add_static_mapping(self.pg0.remote_ip4, static_addr,
2911 is_add=0)
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002912
2913 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002914 ARP(op=ARP.who_has, pdst=self.nat_addr,
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002915 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2916 self.pg1.add_stream(p)
2917 self.pg_enable_capture(self.pg_interfaces)
2918 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07002919 self.pg1.assert_nothing_captured()
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002920
2921 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2922 ARP(op=ARP.who_has, pdst=static_addr,
2923 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2924 self.pg1.add_stream(p)
2925 self.pg_enable_capture(self.pg_interfaces)
2926 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07002927 self.pg1.assert_nothing_captured()
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002928
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002929 def test_vrf_mode(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002930 """ NAT44 tenant VRF aware address pool mode """
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002931
2932 vrf_id1 = 1
2933 vrf_id2 = 2
2934 nat_ip1 = "10.0.0.10"
2935 nat_ip2 = "10.0.0.11"
2936
2937 self.pg0.unconfig_ip4()
2938 self.pg1.unconfig_ip4()
Ole Troan9a475372019-03-05 16:58:24 +01002939 self.vapi.ip_table_add_del(is_add=1, table_id=vrf_id1)
2940 self.vapi.ip_table_add_del(is_add=1, table_id=vrf_id2)
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002941 self.pg0.set_table_ip4(vrf_id1)
2942 self.pg1.set_table_ip4(vrf_id2)
2943 self.pg0.config_ip4()
2944 self.pg1.config_ip4()
Matus Fabian8008d7c2018-07-09 01:34:20 -07002945 self.pg0.resolve_arp()
2946 self.pg1.resolve_arp()
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002947
Matus Fabian2ba92e32017-08-21 07:05:03 -07002948 self.nat44_add_address(nat_ip1, vrf_id=vrf_id1)
2949 self.nat44_add_address(nat_ip2, vrf_id=vrf_id2)
2950 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2951 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
2952 self.vapi.nat44_interface_add_del_feature(self.pg2.sw_if_index,
2953 is_inside=0)
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002954
Matus Fabian8008d7c2018-07-09 01:34:20 -07002955 try:
2956 # first VRF
2957 pkts = self.create_stream_in(self.pg0, self.pg2)
2958 self.pg0.add_stream(pkts)
2959 self.pg_enable_capture(self.pg_interfaces)
2960 self.pg_start()
2961 capture = self.pg2.get_capture(len(pkts))
2962 self.verify_capture_out(capture, nat_ip1)
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002963
Matus Fabian8008d7c2018-07-09 01:34:20 -07002964 # second VRF
2965 pkts = self.create_stream_in(self.pg1, self.pg2)
2966 self.pg1.add_stream(pkts)
2967 self.pg_enable_capture(self.pg_interfaces)
2968 self.pg_start()
2969 capture = self.pg2.get_capture(len(pkts))
2970 self.verify_capture_out(capture, nat_ip2)
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002971
Matus Fabian8008d7c2018-07-09 01:34:20 -07002972 finally:
2973 self.pg0.unconfig_ip4()
2974 self.pg1.unconfig_ip4()
2975 self.pg0.set_table_ip4(0)
2976 self.pg1.set_table_ip4(0)
2977 self.pg0.config_ip4()
2978 self.pg1.config_ip4()
2979 self.pg0.resolve_arp()
2980 self.pg1.resolve_arp()
Ole Troan9a475372019-03-05 16:58:24 +01002981 self.vapi.ip_table_add_del(is_add=0, table_id=vrf_id1)
2982 self.vapi.ip_table_add_del(is_add=0, table_id=vrf_id2)
Neale Ranns15002542017-09-10 04:39:11 -07002983
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002984 def test_vrf_feature_independent(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002985 """ NAT44 tenant VRF independent address pool mode """
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002986
2987 nat_ip1 = "10.0.0.10"
2988 nat_ip2 = "10.0.0.11"
2989
Matus Fabian2ba92e32017-08-21 07:05:03 -07002990 self.nat44_add_address(nat_ip1)
Matus Fabian51e759f2017-12-07 23:22:51 -08002991 self.nat44_add_address(nat_ip2, vrf_id=99)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002992 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2993 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
2994 self.vapi.nat44_interface_add_del_feature(self.pg2.sw_if_index,
2995 is_inside=0)
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002996
2997 # first VRF
2998 pkts = self.create_stream_in(self.pg0, self.pg2)
2999 self.pg0.add_stream(pkts)
3000 self.pg_enable_capture(self.pg_interfaces)
3001 self.pg_start()
3002 capture = self.pg2.get_capture(len(pkts))
3003 self.verify_capture_out(capture, nat_ip1)
3004
3005 # second VRF
3006 pkts = self.create_stream_in(self.pg1, self.pg2)
3007 self.pg1.add_stream(pkts)
3008 self.pg_enable_capture(self.pg_interfaces)
3009 self.pg_start()
3010 capture = self.pg2.get_capture(len(pkts))
3011 self.verify_capture_out(capture, nat_ip1)
3012
Martin Gálik406eb1d2017-05-04 04:35:04 -07003013 def test_dynamic_ipless_interfaces(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07003014 """ NAT44 interfaces without configured IP address """
Martin Gálik406eb1d2017-05-04 04:35:04 -07003015
Neale Ranns37029302018-08-10 05:30:06 -07003016 self.vapi.ip_neighbor_add_del(
3017 self.pg7.sw_if_index,
3018 self.pg7.remote_mac,
3019 self.pg7.remote_ip4,
3020 flags=(VppEnum.vl_api_ip_neighbor_flags_t.
3021 IP_API_NEIGHBOR_FLAG_STATIC))
3022 self.vapi.ip_neighbor_add_del(
3023 self.pg8.sw_if_index,
3024 self.pg8.remote_mac,
3025 self.pg8.remote_ip4,
3026 flags=(VppEnum.vl_api_ip_neighbor_flags_t.
3027 IP_API_NEIGHBOR_FLAG_STATIC))
Martin Gálik406eb1d2017-05-04 04:35:04 -07003028
3029 self.vapi.ip_add_del_route(dst_address=self.pg7.remote_ip4n,
3030 dst_address_length=32,
3031 next_hop_address=self.pg7.remote_ip4n,
3032 next_hop_sw_if_index=self.pg7.sw_if_index)
3033 self.vapi.ip_add_del_route(dst_address=self.pg8.remote_ip4n,
3034 dst_address_length=32,
3035 next_hop_address=self.pg8.remote_ip4n,
3036 next_hop_sw_if_index=self.pg8.sw_if_index)
3037
Matus Fabian2ba92e32017-08-21 07:05:03 -07003038 self.nat44_add_address(self.nat_addr)
3039 self.vapi.nat44_interface_add_del_feature(self.pg7.sw_if_index)
3040 self.vapi.nat44_interface_add_del_feature(self.pg8.sw_if_index,
3041 is_inside=0)
Martin Gálik406eb1d2017-05-04 04:35:04 -07003042
3043 # in2out
3044 pkts = self.create_stream_in(self.pg7, self.pg8)
3045 self.pg7.add_stream(pkts)
3046 self.pg_enable_capture(self.pg_interfaces)
3047 self.pg_start()
3048 capture = self.pg8.get_capture(len(pkts))
3049 self.verify_capture_out(capture)
3050
3051 # out2in
Matus Fabian2ba92e32017-08-21 07:05:03 -07003052 pkts = self.create_stream_out(self.pg8, self.nat_addr)
Martin Gálik406eb1d2017-05-04 04:35:04 -07003053 self.pg8.add_stream(pkts)
3054 self.pg_enable_capture(self.pg_interfaces)
3055 self.pg_start()
3056 capture = self.pg7.get_capture(len(pkts))
3057 self.verify_capture_in(capture, self.pg7)
3058
3059 def test_static_ipless_interfaces(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07003060 """ NAT44 interfaces without configured IP address - 1:1 NAT """
Martin Gálik406eb1d2017-05-04 04:35:04 -07003061
Neale Ranns37029302018-08-10 05:30:06 -07003062 self.vapi.ip_neighbor_add_del(
3063 self.pg7.sw_if_index,
3064 self.pg7.remote_mac,
3065 self.pg7.remote_ip4,
3066 flags=(VppEnum.vl_api_ip_neighbor_flags_t.
3067 IP_API_NEIGHBOR_FLAG_STATIC))
3068 self.vapi.ip_neighbor_add_del(
3069 self.pg8.sw_if_index,
3070 self.pg8.remote_mac,
3071 self.pg8.remote_ip4,
3072 flags=(VppEnum.vl_api_ip_neighbor_flags_t.
3073 IP_API_NEIGHBOR_FLAG_STATIC))
Martin Gálik406eb1d2017-05-04 04:35:04 -07003074
3075 self.vapi.ip_add_del_route(dst_address=self.pg7.remote_ip4n,
3076 dst_address_length=32,
3077 next_hop_address=self.pg7.remote_ip4n,
3078 next_hop_sw_if_index=self.pg7.sw_if_index)
3079 self.vapi.ip_add_del_route(dst_address=self.pg8.remote_ip4n,
3080 dst_address_length=32,
3081 next_hop_address=self.pg8.remote_ip4n,
3082 next_hop_sw_if_index=self.pg8.sw_if_index)
3083
Matus Fabian2ba92e32017-08-21 07:05:03 -07003084 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr)
3085 self.vapi.nat44_interface_add_del_feature(self.pg7.sw_if_index)
3086 self.vapi.nat44_interface_add_del_feature(self.pg8.sw_if_index,
3087 is_inside=0)
Martin Gálik406eb1d2017-05-04 04:35:04 -07003088
3089 # out2in
3090 pkts = self.create_stream_out(self.pg8)
3091 self.pg8.add_stream(pkts)
3092 self.pg_enable_capture(self.pg_interfaces)
3093 self.pg_start()
3094 capture = self.pg7.get_capture(len(pkts))
3095 self.verify_capture_in(capture, self.pg7)
3096
3097 # in2out
3098 pkts = self.create_stream_in(self.pg7, self.pg8)
3099 self.pg7.add_stream(pkts)
3100 self.pg_enable_capture(self.pg_interfaces)
3101 self.pg_start()
3102 capture = self.pg8.get_capture(len(pkts))
Matus Fabian2ba92e32017-08-21 07:05:03 -07003103 self.verify_capture_out(capture, self.nat_addr, True)
Martin Gálik406eb1d2017-05-04 04:35:04 -07003104
3105 def test_static_with_port_ipless_interfaces(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07003106 """ NAT44 interfaces without configured IP address - 1:1 NAPT """
Martin Gálik406eb1d2017-05-04 04:35:04 -07003107
3108 self.tcp_port_out = 30606
3109 self.udp_port_out = 30607
3110 self.icmp_id_out = 30608
3111
Neale Ranns37029302018-08-10 05:30:06 -07003112 self.vapi.ip_neighbor_add_del(
3113 self.pg7.sw_if_index,
3114 self.pg7.remote_mac,
3115 self.pg7.remote_ip4,
3116 flags=(VppEnum.vl_api_ip_neighbor_flags_t.
3117 IP_API_NEIGHBOR_FLAG_STATIC))
3118 self.vapi.ip_neighbor_add_del(
3119 self.pg8.sw_if_index,
3120 self.pg8.remote_mac,
3121 self.pg8.remote_ip4,
3122 flags=(VppEnum.vl_api_ip_neighbor_flags_t.
3123 IP_API_NEIGHBOR_FLAG_STATIC))
Martin Gálik406eb1d2017-05-04 04:35:04 -07003124
3125 self.vapi.ip_add_del_route(dst_address=self.pg7.remote_ip4n,
3126 dst_address_length=32,
3127 next_hop_address=self.pg7.remote_ip4n,
3128 next_hop_sw_if_index=self.pg7.sw_if_index)
3129 self.vapi.ip_add_del_route(dst_address=self.pg8.remote_ip4n,
3130 dst_address_length=32,
3131 next_hop_address=self.pg8.remote_ip4n,
3132 next_hop_sw_if_index=self.pg8.sw_if_index)
3133
Matus Fabian2ba92e32017-08-21 07:05:03 -07003134 self.nat44_add_address(self.nat_addr)
3135 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
3136 self.tcp_port_in, self.tcp_port_out,
3137 proto=IP_PROTOS.tcp)
3138 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
3139 self.udp_port_in, self.udp_port_out,
3140 proto=IP_PROTOS.udp)
3141 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
3142 self.icmp_id_in, self.icmp_id_out,
3143 proto=IP_PROTOS.icmp)
3144 self.vapi.nat44_interface_add_del_feature(self.pg7.sw_if_index)
3145 self.vapi.nat44_interface_add_del_feature(self.pg8.sw_if_index,
3146 is_inside=0)
Martin Gálik406eb1d2017-05-04 04:35:04 -07003147
3148 # out2in
3149 pkts = self.create_stream_out(self.pg8)
3150 self.pg8.add_stream(pkts)
3151 self.pg_enable_capture(self.pg_interfaces)
3152 self.pg_start()
3153 capture = self.pg7.get_capture(len(pkts))
3154 self.verify_capture_in(capture, self.pg7)
3155
3156 # in2out
3157 pkts = self.create_stream_in(self.pg7, self.pg8)
3158 self.pg7.add_stream(pkts)
3159 self.pg_enable_capture(self.pg_interfaces)
3160 self.pg_start()
3161 capture = self.pg8.get_capture(len(pkts))
3162 self.verify_capture_out(capture)
3163
Matus Fabian328dbc82017-06-19 04:28:04 -07003164 def test_static_unknown_proto(self):
3165 """ 1:1 NAT translate packet with unknown protocol """
3166 nat_ip = "10.0.0.10"
Matus Fabian2ba92e32017-08-21 07:05:03 -07003167 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
3168 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3169 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3170 is_inside=0)
Matus Fabian328dbc82017-06-19 04:28:04 -07003171
3172 # in2out
3173 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3174 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3175 GRE() /
Matus Fabian1e8db5f2017-06-20 01:45:49 -07003176 IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4) /
Matus Fabian328dbc82017-06-19 04:28:04 -07003177 TCP(sport=1234, dport=1234))
3178 self.pg0.add_stream(p)
3179 self.pg_enable_capture(self.pg_interfaces)
3180 self.pg_start()
3181 p = self.pg1.get_capture(1)
3182 packet = p[0]
3183 try:
3184 self.assertEqual(packet[IP].src, nat_ip)
3185 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
Paul Vinciguerra978aa642018-11-24 22:19:12 -08003186 self.assertEqual(packet.haslayer(GRE), 1)
Klement Sekerad81ae412018-05-16 10:52:54 +02003187 self.assert_packet_checksums_valid(packet)
Matus Fabian328dbc82017-06-19 04:28:04 -07003188 except:
3189 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3190 raise
3191
3192 # out2in
3193 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
3194 IP(src=self.pg1.remote_ip4, dst=nat_ip) /
3195 GRE() /
Matus Fabian1e8db5f2017-06-20 01:45:49 -07003196 IP(src=self.pg3.remote_ip4, dst=self.pg2.remote_ip4) /
Matus Fabian328dbc82017-06-19 04:28:04 -07003197 TCP(sport=1234, dport=1234))
3198 self.pg1.add_stream(p)
3199 self.pg_enable_capture(self.pg_interfaces)
3200 self.pg_start()
3201 p = self.pg0.get_capture(1)
3202 packet = p[0]
3203 try:
3204 self.assertEqual(packet[IP].src, self.pg1.remote_ip4)
3205 self.assertEqual(packet[IP].dst, self.pg0.remote_ip4)
Paul Vinciguerra978aa642018-11-24 22:19:12 -08003206 self.assertEqual(packet.haslayer(GRE), 1)
Klement Sekerad81ae412018-05-16 10:52:54 +02003207 self.assert_packet_checksums_valid(packet)
Matus Fabian328dbc82017-06-19 04:28:04 -07003208 except:
3209 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3210 raise
3211
Matus Fabian7968e6c2017-07-06 05:37:49 -07003212 def test_hairpinning_static_unknown_proto(self):
Matus Fabian1e8db5f2017-06-20 01:45:49 -07003213 """ 1:1 NAT translate packet with unknown protocol - hairpinning """
3214
3215 host = self.pg0.remote_hosts[0]
3216 server = self.pg0.remote_hosts[1]
3217
3218 host_nat_ip = "10.0.0.10"
3219 server_nat_ip = "10.0.0.11"
3220
Matus Fabian2ba92e32017-08-21 07:05:03 -07003221 self.nat44_add_static_mapping(host.ip4, host_nat_ip)
3222 self.nat44_add_static_mapping(server.ip4, server_nat_ip)
3223 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3224 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3225 is_inside=0)
Matus Fabian1e8db5f2017-06-20 01:45:49 -07003226
3227 # host to server
3228 p = (Ether(dst=self.pg0.local_mac, src=host.mac) /
3229 IP(src=host.ip4, dst=server_nat_ip) /
3230 GRE() /
3231 IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4) /
3232 TCP(sport=1234, dport=1234))
3233 self.pg0.add_stream(p)
3234 self.pg_enable_capture(self.pg_interfaces)
3235 self.pg_start()
3236 p = self.pg0.get_capture(1)
3237 packet = p[0]
3238 try:
3239 self.assertEqual(packet[IP].src, host_nat_ip)
3240 self.assertEqual(packet[IP].dst, server.ip4)
Paul Vinciguerra978aa642018-11-24 22:19:12 -08003241 self.assertEqual(packet.haslayer(GRE), 1)
Klement Sekerad81ae412018-05-16 10:52:54 +02003242 self.assert_packet_checksums_valid(packet)
Matus Fabian1e8db5f2017-06-20 01:45:49 -07003243 except:
3244 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3245 raise
3246
3247 # server to host
3248 p = (Ether(dst=self.pg0.local_mac, src=server.mac) /
3249 IP(src=server.ip4, dst=host_nat_ip) /
3250 GRE() /
3251 IP(src=self.pg3.remote_ip4, dst=self.pg2.remote_ip4) /
3252 TCP(sport=1234, dport=1234))
3253 self.pg0.add_stream(p)
3254 self.pg_enable_capture(self.pg_interfaces)
3255 self.pg_start()
3256 p = self.pg0.get_capture(1)
3257 packet = p[0]
3258 try:
3259 self.assertEqual(packet[IP].src, server_nat_ip)
3260 self.assertEqual(packet[IP].dst, host.ip4)
Paul Vinciguerra978aa642018-11-24 22:19:12 -08003261 self.assertEqual(packet.haslayer(GRE), 1)
Klement Sekerad81ae412018-05-16 10:52:54 +02003262 self.assert_packet_checksums_valid(packet)
Matus Fabian1e8db5f2017-06-20 01:45:49 -07003263 except:
3264 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3265 raise
3266
Matus Fabian93d84c92017-07-19 08:06:01 -07003267 def test_output_feature(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07003268 """ NAT44 interface output feature (in2out postrouting) """
3269 self.nat44_add_address(self.nat_addr)
3270 self.vapi.nat44_interface_add_del_output_feature(self.pg0.sw_if_index)
Matus Fabianb2d2fc72017-09-10 22:17:47 -07003271 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index)
3272 self.vapi.nat44_interface_add_del_output_feature(self.pg3.sw_if_index,
Matus Fabian2ba92e32017-08-21 07:05:03 -07003273 is_inside=0)
Matus Fabian93d84c92017-07-19 08:06:01 -07003274
3275 # in2out
Matus Fabianb2d2fc72017-09-10 22:17:47 -07003276 pkts = self.create_stream_in(self.pg0, self.pg3)
Matus Fabian93d84c92017-07-19 08:06:01 -07003277 self.pg0.add_stream(pkts)
3278 self.pg_enable_capture(self.pg_interfaces)
3279 self.pg_start()
Matus Fabianb2d2fc72017-09-10 22:17:47 -07003280 capture = self.pg3.get_capture(len(pkts))
Matus Fabian93d84c92017-07-19 08:06:01 -07003281 self.verify_capture_out(capture)
3282
3283 # out2in
Matus Fabianb2d2fc72017-09-10 22:17:47 -07003284 pkts = self.create_stream_out(self.pg3)
3285 self.pg3.add_stream(pkts)
Matus Fabian93d84c92017-07-19 08:06:01 -07003286 self.pg_enable_capture(self.pg_interfaces)
3287 self.pg_start()
3288 capture = self.pg0.get_capture(len(pkts))
3289 self.verify_capture_in(capture, self.pg0)
3290
Matus Fabianb2d2fc72017-09-10 22:17:47 -07003291 # from non-NAT interface to NAT inside interface
3292 pkts = self.create_stream_in(self.pg2, self.pg0)
3293 self.pg2.add_stream(pkts)
3294 self.pg_enable_capture(self.pg_interfaces)
3295 self.pg_start()
3296 capture = self.pg0.get_capture(len(pkts))
3297 self.verify_capture_no_translation(capture, self.pg2, self.pg0)
3298
Matus Fabian93d84c92017-07-19 08:06:01 -07003299 def test_output_feature_vrf_aware(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07003300 """ NAT44 interface output feature VRF aware (in2out postrouting) """
Matus Fabian93d84c92017-07-19 08:06:01 -07003301 nat_ip_vrf10 = "10.0.0.10"
3302 nat_ip_vrf20 = "10.0.0.20"
3303
3304 self.vapi.ip_add_del_route(dst_address=self.pg3.remote_ip4n,
3305 dst_address_length=32,
3306 next_hop_address=self.pg3.remote_ip4n,
3307 next_hop_sw_if_index=self.pg3.sw_if_index,
3308 table_id=10)
3309 self.vapi.ip_add_del_route(dst_address=self.pg3.remote_ip4n,
3310 dst_address_length=32,
3311 next_hop_address=self.pg3.remote_ip4n,
3312 next_hop_sw_if_index=self.pg3.sw_if_index,
3313 table_id=20)
3314
Matus Fabian2ba92e32017-08-21 07:05:03 -07003315 self.nat44_add_address(nat_ip_vrf10, vrf_id=10)
3316 self.nat44_add_address(nat_ip_vrf20, vrf_id=20)
3317 self.vapi.nat44_interface_add_del_output_feature(self.pg4.sw_if_index)
3318 self.vapi.nat44_interface_add_del_output_feature(self.pg6.sw_if_index)
3319 self.vapi.nat44_interface_add_del_output_feature(self.pg3.sw_if_index,
3320 is_inside=0)
Matus Fabian93d84c92017-07-19 08:06:01 -07003321
3322 # in2out VRF 10
3323 pkts = self.create_stream_in(self.pg4, self.pg3)
3324 self.pg4.add_stream(pkts)
3325 self.pg_enable_capture(self.pg_interfaces)
3326 self.pg_start()
3327 capture = self.pg3.get_capture(len(pkts))
3328 self.verify_capture_out(capture, nat_ip=nat_ip_vrf10)
3329
3330 # out2in VRF 10
3331 pkts = self.create_stream_out(self.pg3, dst_ip=nat_ip_vrf10)
3332 self.pg3.add_stream(pkts)
3333 self.pg_enable_capture(self.pg_interfaces)
3334 self.pg_start()
3335 capture = self.pg4.get_capture(len(pkts))
3336 self.verify_capture_in(capture, self.pg4)
3337
3338 # in2out VRF 20
3339 pkts = self.create_stream_in(self.pg6, self.pg3)
3340 self.pg6.add_stream(pkts)
3341 self.pg_enable_capture(self.pg_interfaces)
3342 self.pg_start()
3343 capture = self.pg3.get_capture(len(pkts))
3344 self.verify_capture_out(capture, nat_ip=nat_ip_vrf20)
3345
3346 # out2in VRF 20
3347 pkts = self.create_stream_out(self.pg3, dst_ip=nat_ip_vrf20)
3348 self.pg3.add_stream(pkts)
3349 self.pg_enable_capture(self.pg_interfaces)
3350 self.pg_start()
3351 capture = self.pg6.get_capture(len(pkts))
3352 self.verify_capture_in(capture, self.pg6)
3353
Matus Fabian161c59c2017-07-21 03:46:03 -07003354 def test_output_feature_hairpinning(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07003355 """ NAT44 interface output feature hairpinning (in2out postrouting) """
Matus Fabian93d84c92017-07-19 08:06:01 -07003356 host = self.pg0.remote_hosts[0]
3357 server = self.pg0.remote_hosts[1]
3358 host_in_port = 1234
3359 host_out_port = 0
3360 server_in_port = 5678
3361 server_out_port = 8765
3362
Matus Fabian2ba92e32017-08-21 07:05:03 -07003363 self.nat44_add_address(self.nat_addr)
3364 self.vapi.nat44_interface_add_del_output_feature(self.pg0.sw_if_index)
3365 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
3366 is_inside=0)
Matus Fabian93d84c92017-07-19 08:06:01 -07003367
3368 # add static mapping for server
Matus Fabian2ba92e32017-08-21 07:05:03 -07003369 self.nat44_add_static_mapping(server.ip4, self.nat_addr,
3370 server_in_port, server_out_port,
3371 proto=IP_PROTOS.tcp)
Matus Fabian93d84c92017-07-19 08:06:01 -07003372
3373 # send packet from host to server
3374 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07003375 IP(src=host.ip4, dst=self.nat_addr) /
Matus Fabian93d84c92017-07-19 08:06:01 -07003376 TCP(sport=host_in_port, dport=server_out_port))
3377 self.pg0.add_stream(p)
3378 self.pg_enable_capture(self.pg_interfaces)
3379 self.pg_start()
3380 capture = self.pg0.get_capture(1)
3381 p = capture[0]
3382 try:
3383 ip = p[IP]
3384 tcp = p[TCP]
Matus Fabian2ba92e32017-08-21 07:05:03 -07003385 self.assertEqual(ip.src, self.nat_addr)
Matus Fabian93d84c92017-07-19 08:06:01 -07003386 self.assertEqual(ip.dst, server.ip4)
3387 self.assertNotEqual(tcp.sport, host_in_port)
3388 self.assertEqual(tcp.dport, server_in_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02003389 self.assert_packet_checksums_valid(p)
Matus Fabian93d84c92017-07-19 08:06:01 -07003390 host_out_port = tcp.sport
3391 except:
3392 self.logger.error(ppp("Unexpected or invalid packet:", p))
3393 raise
3394
3395 # send reply from server to host
3396 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07003397 IP(src=server.ip4, dst=self.nat_addr) /
Matus Fabian93d84c92017-07-19 08:06:01 -07003398 TCP(sport=server_in_port, dport=host_out_port))
3399 self.pg0.add_stream(p)
3400 self.pg_enable_capture(self.pg_interfaces)
3401 self.pg_start()
3402 capture = self.pg0.get_capture(1)
3403 p = capture[0]
3404 try:
3405 ip = p[IP]
3406 tcp = p[TCP]
Matus Fabian2ba92e32017-08-21 07:05:03 -07003407 self.assertEqual(ip.src, self.nat_addr)
Matus Fabian93d84c92017-07-19 08:06:01 -07003408 self.assertEqual(ip.dst, host.ip4)
3409 self.assertEqual(tcp.sport, server_out_port)
3410 self.assertEqual(tcp.dport, host_in_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02003411 self.assert_packet_checksums_valid(p)
Matus Fabian93d84c92017-07-19 08:06:01 -07003412 except:
Matus Fabiane82488f2018-01-18 03:38:45 -08003413 self.logger.error(ppp("Unexpected or invalid packet:", p))
Matus Fabian93d84c92017-07-19 08:06:01 -07003414 raise
3415
Matus Fabian36ea2d62017-10-24 04:13:49 -07003416 def test_one_armed_nat44(self):
3417 """ One armed NAT44 """
3418 remote_host = self.pg9.remote_hosts[0]
3419 local_host = self.pg9.remote_hosts[1]
3420 external_port = 0
3421
3422 self.nat44_add_address(self.nat_addr)
3423 self.vapi.nat44_interface_add_del_feature(self.pg9.sw_if_index)
3424 self.vapi.nat44_interface_add_del_feature(self.pg9.sw_if_index,
3425 is_inside=0)
3426
3427 # in2out
3428 p = (Ether(src=self.pg9.remote_mac, dst=self.pg9.local_mac) /
3429 IP(src=local_host.ip4, dst=remote_host.ip4) /
3430 TCP(sport=12345, dport=80))
3431 self.pg9.add_stream(p)
3432 self.pg_enable_capture(self.pg_interfaces)
3433 self.pg_start()
3434 capture = self.pg9.get_capture(1)
3435 p = capture[0]
3436 try:
3437 ip = p[IP]
3438 tcp = p[TCP]
3439 self.assertEqual(ip.src, self.nat_addr)
3440 self.assertEqual(ip.dst, remote_host.ip4)
3441 self.assertNotEqual(tcp.sport, 12345)
3442 external_port = tcp.sport
3443 self.assertEqual(tcp.dport, 80)
Klement Sekerad81ae412018-05-16 10:52:54 +02003444 self.assert_packet_checksums_valid(p)
Matus Fabian36ea2d62017-10-24 04:13:49 -07003445 except:
3446 self.logger.error(ppp("Unexpected or invalid packet:", p))
3447 raise
3448
3449 # out2in
3450 p = (Ether(src=self.pg9.remote_mac, dst=self.pg9.local_mac) /
3451 IP(src=remote_host.ip4, dst=self.nat_addr) /
3452 TCP(sport=80, dport=external_port))
3453 self.pg9.add_stream(p)
3454 self.pg_enable_capture(self.pg_interfaces)
3455 self.pg_start()
3456 capture = self.pg9.get_capture(1)
3457 p = capture[0]
3458 try:
3459 ip = p[IP]
3460 tcp = p[TCP]
3461 self.assertEqual(ip.src, remote_host.ip4)
3462 self.assertEqual(ip.dst, local_host.ip4)
3463 self.assertEqual(tcp.sport, 80)
3464 self.assertEqual(tcp.dport, 12345)
Klement Sekerad81ae412018-05-16 10:52:54 +02003465 self.assert_packet_checksums_valid(p)
Matus Fabian36ea2d62017-10-24 04:13:49 -07003466 except:
3467 self.logger.error(ppp("Unexpected or invalid packet:", p))
3468 raise
3469
Matus Fabiana5e73762018-12-14 01:55:16 -08003470 err = self.statistics.get_counter('/err/nat44-classify/next in2out')
3471 self.assertEqual(err, 1)
3472 err = self.statistics.get_counter('/err/nat44-classify/next out2in')
3473 self.assertEqual(err, 1)
3474
Matus Fabian5ba86f72017-10-26 03:37:38 -07003475 def test_del_session(self):
3476 """ Delete NAT44 session """
3477 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
3482 pkts = self.create_stream_in(self.pg0, self.pg1)
3483 self.pg0.add_stream(pkts)
3484 self.pg_enable_capture(self.pg_interfaces)
3485 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07003486 self.pg1.get_capture(len(pkts))
Matus Fabian5ba86f72017-10-26 03:37:38 -07003487
3488 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
3489 nsessions = len(sessions)
3490
3491 self.vapi.nat44_del_session(sessions[0].inside_ip_address,
3492 sessions[0].inside_port,
3493 sessions[0].protocol)
3494 self.vapi.nat44_del_session(sessions[1].outside_ip_address,
3495 sessions[1].outside_port,
3496 sessions[1].protocol,
3497 is_in=0)
3498
3499 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
3500 self.assertEqual(nsessions - len(sessions), 2)
3501
Matus Fabian68ba8802018-08-08 05:52:47 -07003502 self.vapi.nat44_del_session(sessions[0].inside_ip_address,
3503 sessions[0].inside_port,
3504 sessions[0].protocol)
3505
3506 self.verify_no_nat44_user()
3507
Matus Fabianefcd1e92017-08-15 06:59:19 -07003508 def test_set_get_reass(self):
3509 """ NAT44 set/get virtual fragmentation reassembly """
3510 reas_cfg1 = self.vapi.nat_get_reass()
3511
3512 self.vapi.nat_set_reass(timeout=reas_cfg1.ip4_timeout + 5,
3513 max_reass=reas_cfg1.ip4_max_reass * 2,
3514 max_frag=reas_cfg1.ip4_max_frag * 2)
3515
3516 reas_cfg2 = self.vapi.nat_get_reass()
3517
3518 self.assertEqual(reas_cfg1.ip4_timeout + 5, reas_cfg2.ip4_timeout)
3519 self.assertEqual(reas_cfg1.ip4_max_reass * 2, reas_cfg2.ip4_max_reass)
3520 self.assertEqual(reas_cfg1.ip4_max_frag * 2, reas_cfg2.ip4_max_frag)
3521
3522 self.vapi.nat_set_reass(drop_frag=1)
3523 self.assertTrue(self.vapi.nat_get_reass().ip4_drop_frag)
3524
3525 def test_frag_in_order(self):
3526 """ NAT44 translate fragments arriving in order """
Juraj Slobodafe0aa762018-07-23 12:22:54 +02003527
Matus Fabianefcd1e92017-08-15 06:59:19 -07003528 self.nat44_add_address(self.nat_addr)
3529 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3530 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3531 is_inside=0)
3532
Matus Fabianda41d722018-10-19 04:01:19 -07003533 self.frag_in_order(proto=IP_PROTOS.tcp)
3534 self.frag_in_order(proto=IP_PROTOS.udp)
3535 self.frag_in_order(proto=IP_PROTOS.icmp)
Matus Fabianefcd1e92017-08-15 06:59:19 -07003536
Matus Fabian111add72018-11-20 02:19:05 -08003537 def test_frag_forwarding(self):
3538 """ NAT44 forwarding fragment test """
Ole Troane1ade682019-03-04 23:55:43 +01003539 self.vapi.nat44_add_del_interface_addr(self.pg1.sw_if_index)
Matus Fabian111add72018-11-20 02:19:05 -08003540 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3541 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3542 is_inside=0)
3543 self.vapi.nat44_forwarding_enable_disable(1)
3544
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07003545 data = b"A" * 16 + b"B" * 16 + b"C" * 3
Matus Fabian111add72018-11-20 02:19:05 -08003546 pkts = self.create_stream_frag(self.pg1,
3547 self.pg0.remote_ip4,
3548 4789,
3549 4789,
3550 data,
3551 proto=IP_PROTOS.udp)
3552 self.pg1.add_stream(pkts)
3553 self.pg_enable_capture(self.pg_interfaces)
3554 self.pg_start()
3555 frags = self.pg0.get_capture(len(pkts))
3556 p = self.reass_frags_and_verify(frags,
3557 self.pg1.remote_ip4,
3558 self.pg0.remote_ip4)
3559 self.assertEqual(p[UDP].sport, 4789)
3560 self.assertEqual(p[UDP].dport, 4789)
3561 self.assertEqual(data, p[Raw].load)
3562
Matus Fabianefcd1e92017-08-15 06:59:19 -07003563 def test_reass_hairpinning(self):
3564 """ NAT44 fragments hairpinning """
Juraj Slobodafe0aa762018-07-23 12:22:54 +02003565
Matus Fabianda41d722018-10-19 04:01:19 -07003566 self.server = self.pg0.remote_hosts[1]
3567 self.host_in_port = random.randint(1025, 65535)
3568 self.server_in_port = random.randint(1025, 65535)
3569 self.server_out_port = random.randint(1025, 65535)
Matus Fabianefcd1e92017-08-15 06:59:19 -07003570
3571 self.nat44_add_address(self.nat_addr)
3572 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3573 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3574 is_inside=0)
3575 # add static mapping for server
Matus Fabianda41d722018-10-19 04:01:19 -07003576 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr,
3577 self.server_in_port,
3578 self.server_out_port,
Matus Fabianefcd1e92017-08-15 06:59:19 -07003579 proto=IP_PROTOS.tcp)
Matus Fabianda41d722018-10-19 04:01:19 -07003580 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr,
3581 self.server_in_port,
3582 self.server_out_port,
3583 proto=IP_PROTOS.udp)
3584 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr)
Matus Fabianefcd1e92017-08-15 06:59:19 -07003585
Matus Fabianda41d722018-10-19 04:01:19 -07003586 self.reass_hairpinning(proto=IP_PROTOS.tcp)
3587 self.reass_hairpinning(proto=IP_PROTOS.udp)
3588 self.reass_hairpinning(proto=IP_PROTOS.icmp)
Matus Fabianefcd1e92017-08-15 06:59:19 -07003589
3590 def test_frag_out_of_order(self):
3591 """ NAT44 translate fragments arriving out of order """
Juraj Slobodafe0aa762018-07-23 12:22:54 +02003592
Matus Fabianefcd1e92017-08-15 06:59:19 -07003593 self.nat44_add_address(self.nat_addr)
3594 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3595 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3596 is_inside=0)
3597
Matus Fabianda41d722018-10-19 04:01:19 -07003598 self.frag_out_of_order(proto=IP_PROTOS.tcp)
3599 self.frag_out_of_order(proto=IP_PROTOS.udp)
3600 self.frag_out_of_order(proto=IP_PROTOS.icmp)
Matus Fabianefcd1e92017-08-15 06:59:19 -07003601
Matus Fabian27697102017-11-09 01:43:47 -08003602 def test_port_restricted(self):
3603 """ Port restricted NAT44 (MAP-E CE) """
3604 self.nat44_add_address(self.nat_addr)
3605 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3606 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3607 is_inside=0)
Matus Fabian5d28c7a2018-09-04 03:55:45 -07003608 self.vapi.nat_set_addr_and_port_alloc_alg(alg=1,
3609 psid_offset=6,
3610 psid_length=6,
3611 psid=10)
Matus Fabian27697102017-11-09 01:43:47 -08003612
3613 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3614 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3615 TCP(sport=4567, dport=22))
3616 self.pg0.add_stream(p)
3617 self.pg_enable_capture(self.pg_interfaces)
3618 self.pg_start()
3619 capture = self.pg1.get_capture(1)
3620 p = capture[0]
3621 try:
3622 ip = p[IP]
3623 tcp = p[TCP]
3624 self.assertEqual(ip.dst, self.pg1.remote_ip4)
3625 self.assertEqual(ip.src, self.nat_addr)
3626 self.assertEqual(tcp.dport, 22)
3627 self.assertNotEqual(tcp.sport, 4567)
3628 self.assertEqual((tcp.sport >> 6) & 63, 10)
Klement Sekerad81ae412018-05-16 10:52:54 +02003629 self.assert_packet_checksums_valid(p)
Matus Fabian27697102017-11-09 01:43:47 -08003630 except:
3631 self.logger.error(ppp("Unexpected or invalid packet:", p))
3632 raise
3633
Matus Fabian5d28c7a2018-09-04 03:55:45 -07003634 def test_port_range(self):
3635 """ External address port range """
3636 self.nat44_add_address(self.nat_addr)
3637 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3638 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3639 is_inside=0)
3640 self.vapi.nat_set_addr_and_port_alloc_alg(alg=2,
3641 start_port=1025,
3642 end_port=1027)
3643
3644 pkts = []
3645 for port in range(0, 5):
3646 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3647 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3648 TCP(sport=1125 + port))
3649 pkts.append(p)
3650 self.pg0.add_stream(pkts)
3651 self.pg_enable_capture(self.pg_interfaces)
3652 self.pg_start()
3653 capture = self.pg1.get_capture(3)
3654 for p in capture:
3655 tcp = p[TCP]
3656 self.assertGreaterEqual(tcp.sport, 1025)
3657 self.assertLessEqual(tcp.sport, 1027)
3658
Matus Fabiana6110b62018-06-13 05:39:07 -07003659 def test_ipfix_max_frags(self):
3660 """ IPFIX logging maximum fragments pending reassembly exceeded """
3661 self.nat44_add_address(self.nat_addr)
3662 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3663 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3664 is_inside=0)
Matus Fabiana7f8b222018-09-05 06:01:55 -07003665 self.vapi.nat_set_reass(max_frag=1)
Matus Fabiana6110b62018-06-13 05:39:07 -07003666 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
3667 src_address=self.pg3.local_ip4n,
3668 path_mtu=512,
3669 template_interval=10)
Ole Troane1ade682019-03-04 23:55:43 +01003670 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
3671 src_port=self.ipfix_src_port)
Matus Fabiana6110b62018-06-13 05:39:07 -07003672
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07003673 data = b"A" * 4 + b"B" * 16 + b"C" * 3
Matus Fabiana6110b62018-06-13 05:39:07 -07003674 self.tcp_port_in = random.randint(1025, 65535)
3675 pkts = self.create_stream_frag(self.pg0,
3676 self.pg1.remote_ip4,
3677 self.tcp_port_in,
3678 20,
3679 data)
Matus Fabiana7f8b222018-09-05 06:01:55 -07003680 pkts.reverse()
3681 self.pg0.add_stream(pkts)
Matus Fabiana6110b62018-06-13 05:39:07 -07003682 self.pg_enable_capture(self.pg_interfaces)
3683 self.pg_start()
3684 self.pg1.assert_nothing_captured()
3685 sleep(1)
3686 self.vapi.cli("ipfix flush") # FIXME this should be an API call
3687 capture = self.pg3.get_capture(9)
3688 ipfix = IPFIXDecoder()
3689 # first load template
3690 for p in capture:
3691 self.assertTrue(p.haslayer(IPFIX))
3692 self.assertEqual(p[IP].src, self.pg3.local_ip4)
3693 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
3694 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
3695 self.assertEqual(p[UDP].dport, 4739)
3696 self.assertEqual(p[IPFIX].observationDomainID,
3697 self.ipfix_domain_id)
3698 if p.haslayer(Template):
3699 ipfix.add_template(p.getlayer(Template))
3700 # verify events in data set
3701 for p in capture:
3702 if p.haslayer(Data):
3703 data = ipfix.decode_data_set(p.getlayer(Set))
Matus Fabiana7f8b222018-09-05 06:01:55 -07003704 self.verify_ipfix_max_fragments_ip4(data, 1,
Matus Fabiana6110b62018-06-13 05:39:07 -07003705 self.pg0.remote_ip4n)
3706
Matus Fabian8008d7c2018-07-09 01:34:20 -07003707 def test_multiple_outside_vrf(self):
3708 """ Multiple outside VRF """
3709 vrf_id1 = 1
3710 vrf_id2 = 2
3711
3712 self.pg1.unconfig_ip4()
3713 self.pg2.unconfig_ip4()
Ole Troan9a475372019-03-05 16:58:24 +01003714 self.vapi.ip_table_add_del(is_add=1, table_id=vrf_id1)
3715 self.vapi.ip_table_add_del(is_add=1, table_id=vrf_id2)
Matus Fabian8008d7c2018-07-09 01:34:20 -07003716 self.pg1.set_table_ip4(vrf_id1)
3717 self.pg2.set_table_ip4(vrf_id2)
3718 self.pg1.config_ip4()
3719 self.pg2.config_ip4()
3720 self.pg1.resolve_arp()
3721 self.pg2.resolve_arp()
3722
3723 self.nat44_add_address(self.nat_addr)
3724 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3725 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3726 is_inside=0)
3727 self.vapi.nat44_interface_add_del_feature(self.pg2.sw_if_index,
3728 is_inside=0)
3729
3730 try:
3731 # first VRF
3732 pkts = self.create_stream_in(self.pg0, self.pg1)
3733 self.pg0.add_stream(pkts)
3734 self.pg_enable_capture(self.pg_interfaces)
3735 self.pg_start()
3736 capture = self.pg1.get_capture(len(pkts))
3737 self.verify_capture_out(capture, self.nat_addr)
3738
3739 pkts = self.create_stream_out(self.pg1, self.nat_addr)
3740 self.pg1.add_stream(pkts)
3741 self.pg_enable_capture(self.pg_interfaces)
3742 self.pg_start()
3743 capture = self.pg0.get_capture(len(pkts))
3744 self.verify_capture_in(capture, self.pg0)
3745
3746 self.tcp_port_in = 60303
3747 self.udp_port_in = 60304
3748 self.icmp_id_in = 60305
3749
3750 # second VRF
3751 pkts = self.create_stream_in(self.pg0, self.pg2)
3752 self.pg0.add_stream(pkts)
3753 self.pg_enable_capture(self.pg_interfaces)
3754 self.pg_start()
3755 capture = self.pg2.get_capture(len(pkts))
3756 self.verify_capture_out(capture, self.nat_addr)
3757
3758 pkts = self.create_stream_out(self.pg2, self.nat_addr)
3759 self.pg2.add_stream(pkts)
3760 self.pg_enable_capture(self.pg_interfaces)
3761 self.pg_start()
3762 capture = self.pg0.get_capture(len(pkts))
3763 self.verify_capture_in(capture, self.pg0)
3764
3765 finally:
3766 self.pg1.unconfig_ip4()
3767 self.pg2.unconfig_ip4()
3768 self.pg1.set_table_ip4(0)
3769 self.pg2.set_table_ip4(0)
3770 self.pg1.config_ip4()
3771 self.pg2.config_ip4()
3772 self.pg1.resolve_arp()
3773 self.pg2.resolve_arp()
3774
Paul Vinciguerradefde0f2018-12-06 07:46:13 -08003775 @unittest.skipUnless(running_extended_tests, "part of extended tests")
Matus Fabian878c6462018-08-23 00:33:35 -07003776 def test_session_timeout(self):
3777 """ NAT44 session timeouts """
3778 self.nat44_add_address(self.nat_addr)
3779 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3780 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3781 is_inside=0)
3782 self.vapi.nat_set_timeouts(udp=5)
3783
3784 max_sessions = 1000
3785 pkts = []
3786 for i in range(0, max_sessions):
3787 src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
3788 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3789 IP(src=src, dst=self.pg1.remote_ip4) /
3790 UDP(sport=1025, dport=53))
3791 pkts.append(p)
3792 self.pg0.add_stream(pkts)
3793 self.pg_enable_capture(self.pg_interfaces)
3794 self.pg_start()
3795 self.pg1.get_capture(max_sessions)
3796
3797 sleep(6)
3798
3799 pkts = []
3800 for i in range(0, max_sessions):
3801 src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
3802 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3803 IP(src=src, dst=self.pg1.remote_ip4) /
3804 UDP(sport=1026, dport=53))
3805 pkts.append(p)
3806 self.pg0.add_stream(pkts)
3807 self.pg_enable_capture(self.pg_interfaces)
3808 self.pg_start()
3809 self.pg1.get_capture(max_sessions)
3810
3811 nsessions = 0
3812 users = self.vapi.nat44_user_dump()
3813 for user in users:
3814 nsessions = nsessions + user.nsessions
3815 self.assertLess(nsessions, 2 * max_sessions)
3816
Matus Fabianbb4e0222018-09-13 02:36:25 -07003817 def test_mss_clamping(self):
3818 """ TCP MSS clamping """
3819 self.nat44_add_address(self.nat_addr)
3820 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3821 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3822 is_inside=0)
3823
3824 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3825 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3826 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
3827 flags="S", options=[('MSS', 1400)]))
3828
3829 self.vapi.nat_set_mss_clamping(enable=1, mss_value=1000)
3830 self.pg0.add_stream(p)
3831 self.pg_enable_capture(self.pg_interfaces)
3832 self.pg_start()
3833 capture = self.pg1.get_capture(1)
3834 # Negotiated MSS value greater than configured - changed
3835 self.verify_mss_value(capture[0], 1000)
3836
3837 self.vapi.nat_set_mss_clamping(enable=0)
3838 self.pg0.add_stream(p)
3839 self.pg_enable_capture(self.pg_interfaces)
3840 self.pg_start()
3841 capture = self.pg1.get_capture(1)
3842 # MSS clamping disabled - negotiated MSS unchanged
3843 self.verify_mss_value(capture[0], 1400)
3844
3845 self.vapi.nat_set_mss_clamping(enable=1, mss_value=1500)
3846 self.pg0.add_stream(p)
3847 self.pg_enable_capture(self.pg_interfaces)
3848 self.pg_start()
3849 capture = self.pg1.get_capture(1)
3850 # Negotiated MSS value smaller than configured - unchanged
3851 self.verify_mss_value(capture[0], 1400)
3852
Matus Fabian34931eb2019-02-26 09:05:23 -08003853 @unittest.skipUnless(running_extended_tests, "part of extended tests")
3854 def test_ha_send(self):
3855 """ Send HA session synchronization events (active) """
3856 self.nat44_add_address(self.nat_addr)
3857 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3858 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3859 is_inside=0)
3860 self.vapi.nat_ha_set_listener(self.pg3.local_ip4, port=12345)
3861 self.vapi.nat_ha_set_failover(self.pg3.remote_ip4, port=12346)
3862 bind_layers(UDP, HANATStateSync, sport=12345)
3863
3864 # create sessions
3865 pkts = self.create_stream_in(self.pg0, self.pg1)
3866 self.pg0.add_stream(pkts)
3867 self.pg_enable_capture(self.pg_interfaces)
3868 self.pg_start()
3869 capture = self.pg1.get_capture(len(pkts))
3870 self.verify_capture_out(capture)
3871 # active send HA events
3872 self.vapi.nat_ha_flush()
3873 stats = self.statistics.get_counter('/nat44/ha/add-event-send')
3874 self.assertEqual(stats[0][0], 3)
3875 capture = self.pg3.get_capture(1)
3876 p = capture[0]
3877 self.assert_packet_checksums_valid(p)
3878 try:
3879 ip = p[IP]
3880 udp = p[UDP]
3881 hanat = p[HANATStateSync]
3882 except IndexError:
3883 self.logger.error(ppp("Invalid packet:", p))
3884 raise
3885 else:
3886 self.assertEqual(ip.src, self.pg3.local_ip4)
3887 self.assertEqual(ip.dst, self.pg3.remote_ip4)
3888 self.assertEqual(udp.sport, 12345)
3889 self.assertEqual(udp.dport, 12346)
3890 self.assertEqual(hanat.version, 1)
3891 self.assertEqual(hanat.thread_index, 0)
3892 self.assertEqual(hanat.count, 3)
3893 seq = hanat.sequence_number
3894 for event in hanat.events:
3895 self.assertEqual(event.event_type, 1)
3896 self.assertEqual(event.in_addr, self.pg0.remote_ip4)
3897 self.assertEqual(event.out_addr, self.nat_addr)
3898 self.assertEqual(event.fib_index, 0)
3899
3900 # ACK received events
3901 ack = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
3902 IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
3903 UDP(sport=12346, dport=12345) /
3904 HANATStateSync(sequence_number=seq, flags='ACK'))
3905 self.pg3.add_stream(ack)
3906 self.pg_start()
3907 stats = self.statistics.get_counter('/nat44/ha/ack-recv')
3908 self.assertEqual(stats[0][0], 1)
3909
3910 # delete one session
3911 self.pg_enable_capture(self.pg_interfaces)
3912 self.vapi.nat44_del_session(self.pg0.remote_ip4n, self.tcp_port_in,
3913 IP_PROTOS.tcp)
3914 self.vapi.nat_ha_flush()
3915 stats = self.statistics.get_counter('/nat44/ha/del-event-send')
3916 self.assertEqual(stats[0][0], 1)
3917 capture = self.pg3.get_capture(1)
3918 p = capture[0]
3919 try:
3920 hanat = p[HANATStateSync]
3921 except IndexError:
3922 self.logger.error(ppp("Invalid packet:", p))
3923 raise
3924 else:
3925 self.assertGreater(hanat.sequence_number, seq)
3926
3927 # do not send ACK, active retry send HA event again
3928 self.pg_enable_capture(self.pg_interfaces)
3929 sleep(12)
3930 stats = self.statistics.get_counter('/nat44/ha/retry-count')
3931 self.assertEqual(stats[0][0], 3)
3932 stats = self.statistics.get_counter('/nat44/ha/missed-count')
3933 self.assertEqual(stats[0][0], 1)
3934 capture = self.pg3.get_capture(3)
3935 for packet in capture:
3936 self.assertEqual(packet, p)
3937
3938 # session counters refresh
3939 pkts = self.create_stream_out(self.pg1)
3940 self.pg1.add_stream(pkts)
3941 self.pg_enable_capture(self.pg_interfaces)
3942 self.pg_start()
3943 self.pg0.get_capture(2)
3944 self.vapi.nat_ha_flush()
3945 stats = self.statistics.get_counter('/nat44/ha/refresh-event-send')
3946 self.assertEqual(stats[0][0], 2)
3947 capture = self.pg3.get_capture(1)
3948 p = capture[0]
3949 self.assert_packet_checksums_valid(p)
3950 try:
3951 ip = p[IP]
3952 udp = p[UDP]
3953 hanat = p[HANATStateSync]
3954 except IndexError:
3955 self.logger.error(ppp("Invalid packet:", p))
3956 raise
3957 else:
3958 self.assertEqual(ip.src, self.pg3.local_ip4)
3959 self.assertEqual(ip.dst, self.pg3.remote_ip4)
3960 self.assertEqual(udp.sport, 12345)
3961 self.assertEqual(udp.dport, 12346)
3962 self.assertEqual(hanat.version, 1)
3963 self.assertEqual(hanat.count, 2)
3964 seq = hanat.sequence_number
3965 for event in hanat.events:
3966 self.assertEqual(event.event_type, 3)
3967 self.assertEqual(event.out_addr, self.nat_addr)
3968 self.assertEqual(event.fib_index, 0)
3969 self.assertEqual(event.total_pkts, 2)
3970 self.assertGreater(event.total_bytes, 0)
3971
3972 ack = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
3973 IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
3974 UDP(sport=12346, dport=12345) /
3975 HANATStateSync(sequence_number=seq, flags='ACK'))
3976 self.pg3.add_stream(ack)
3977 self.pg_start()
3978 stats = self.statistics.get_counter('/nat44/ha/ack-recv')
3979 self.assertEqual(stats[0][0], 2)
3980
3981 def test_ha_recv(self):
3982 """ Receive HA session synchronization events (passive) """
3983 self.nat44_add_address(self.nat_addr)
3984 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3985 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3986 is_inside=0)
3987 self.vapi.nat_ha_set_listener(self.pg3.local_ip4, port=12345)
3988 bind_layers(UDP, HANATStateSync, sport=12345)
3989
3990 self.tcp_port_out = random.randint(1025, 65535)
3991 self.udp_port_out = random.randint(1025, 65535)
3992
3993 # send HA session add events to failover/passive
3994 p = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
3995 IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
3996 UDP(sport=12346, dport=12345) /
3997 HANATStateSync(sequence_number=1, events=[
3998 Event(event_type='add', protocol='tcp',
3999 in_addr=self.pg0.remote_ip4, out_addr=self.nat_addr,
4000 in_port=self.tcp_port_in, out_port=self.tcp_port_out,
4001 eh_addr=self.pg1.remote_ip4,
4002 ehn_addr=self.pg1.remote_ip4,
4003 eh_port=self.tcp_external_port,
4004 ehn_port=self.tcp_external_port, fib_index=0),
4005 Event(event_type='add', protocol='udp',
4006 in_addr=self.pg0.remote_ip4, out_addr=self.nat_addr,
4007 in_port=self.udp_port_in, out_port=self.udp_port_out,
4008 eh_addr=self.pg1.remote_ip4,
4009 ehn_addr=self.pg1.remote_ip4,
4010 eh_port=self.udp_external_port,
4011 ehn_port=self.udp_external_port, fib_index=0)]))
4012
4013 self.pg3.add_stream(p)
4014 self.pg_enable_capture(self.pg_interfaces)
4015 self.pg_start()
4016 # receive ACK
4017 capture = self.pg3.get_capture(1)
4018 p = capture[0]
4019 try:
4020 hanat = p[HANATStateSync]
4021 except IndexError:
4022 self.logger.error(ppp("Invalid packet:", p))
4023 raise
4024 else:
4025 self.assertEqual(hanat.sequence_number, 1)
4026 self.assertEqual(hanat.flags, 'ACK')
4027 self.assertEqual(hanat.version, 1)
4028 self.assertEqual(hanat.thread_index, 0)
4029 stats = self.statistics.get_counter('/nat44/ha/ack-send')
4030 self.assertEqual(stats[0][0], 1)
4031 stats = self.statistics.get_counter('/nat44/ha/add-event-recv')
4032 self.assertEqual(stats[0][0], 2)
4033 users = self.statistics.get_counter('/nat44/total-users')
4034 self.assertEqual(users[0][0], 1)
4035 sessions = self.statistics.get_counter('/nat44/total-sessions')
4036 self.assertEqual(sessions[0][0], 2)
4037 users = self.vapi.nat44_user_dump()
4038 self.assertEqual(len(users), 1)
4039 self.assertEqual(users[0].ip_address, self.pg0.remote_ip4n)
4040 # there should be 2 sessions created by HA
4041 sessions = self.vapi.nat44_user_session_dump(users[0].ip_address,
4042 users[0].vrf_id)
4043 self.assertEqual(len(sessions), 2)
4044 for session in sessions:
4045 self.assertEqual(session.inside_ip_address, self.pg0.remote_ip4n)
4046 self.assertEqual(session.outside_ip_address, self.nat_addr_n)
4047 self.assertIn(session.inside_port,
4048 [self.tcp_port_in, self.udp_port_in])
4049 self.assertIn(session.outside_port,
4050 [self.tcp_port_out, self.udp_port_out])
4051 self.assertIn(session.protocol, [IP_PROTOS.tcp, IP_PROTOS.udp])
4052
4053 # send HA session delete event to failover/passive
4054 p = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
4055 IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
4056 UDP(sport=12346, dport=12345) /
4057 HANATStateSync(sequence_number=2, events=[
4058 Event(event_type='del', protocol='udp',
4059 in_addr=self.pg0.remote_ip4, out_addr=self.nat_addr,
4060 in_port=self.udp_port_in, out_port=self.udp_port_out,
4061 eh_addr=self.pg1.remote_ip4,
4062 ehn_addr=self.pg1.remote_ip4,
4063 eh_port=self.udp_external_port,
4064 ehn_port=self.udp_external_port, fib_index=0)]))
4065
4066 self.pg3.add_stream(p)
4067 self.pg_enable_capture(self.pg_interfaces)
4068 self.pg_start()
4069 # receive ACK
4070 capture = self.pg3.get_capture(1)
4071 p = capture[0]
4072 try:
4073 hanat = p[HANATStateSync]
4074 except IndexError:
4075 self.logger.error(ppp("Invalid packet:", p))
4076 raise
4077 else:
4078 self.assertEqual(hanat.sequence_number, 2)
4079 self.assertEqual(hanat.flags, 'ACK')
4080 self.assertEqual(hanat.version, 1)
4081 users = self.vapi.nat44_user_dump()
4082 self.assertEqual(len(users), 1)
4083 self.assertEqual(users[0].ip_address, self.pg0.remote_ip4n)
4084 # now we should have only 1 session, 1 deleted by HA
4085 sessions = self.vapi.nat44_user_session_dump(users[0].ip_address,
4086 users[0].vrf_id)
4087 self.assertEqual(len(sessions), 1)
4088 stats = self.statistics.get_counter('/nat44/ha/del-event-recv')
4089 self.assertEqual(stats[0][0], 1)
4090
4091 stats = self.statistics.get_counter('/err/nat-ha/pkts-processed')
4092 self.assertEqual(stats, 2)
4093
4094 # send HA session refresh event to failover/passive
4095 p = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
4096 IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
4097 UDP(sport=12346, dport=12345) /
4098 HANATStateSync(sequence_number=3, events=[
4099 Event(event_type='refresh', protocol='tcp',
4100 in_addr=self.pg0.remote_ip4, out_addr=self.nat_addr,
4101 in_port=self.tcp_port_in, out_port=self.tcp_port_out,
4102 eh_addr=self.pg1.remote_ip4,
4103 ehn_addr=self.pg1.remote_ip4,
4104 eh_port=self.tcp_external_port,
4105 ehn_port=self.tcp_external_port, fib_index=0,
4106 total_bytes=1024, total_pkts=2)]))
4107 self.pg3.add_stream(p)
4108 self.pg_enable_capture(self.pg_interfaces)
4109 self.pg_start()
4110 # receive ACK
4111 capture = self.pg3.get_capture(1)
4112 p = capture[0]
4113 try:
4114 hanat = p[HANATStateSync]
4115 except IndexError:
4116 self.logger.error(ppp("Invalid packet:", p))
4117 raise
4118 else:
4119 self.assertEqual(hanat.sequence_number, 3)
4120 self.assertEqual(hanat.flags, 'ACK')
4121 self.assertEqual(hanat.version, 1)
4122 users = self.vapi.nat44_user_dump()
4123 self.assertEqual(len(users), 1)
4124 self.assertEqual(users[0].ip_address, self.pg0.remote_ip4n)
4125 sessions = self.vapi.nat44_user_session_dump(users[0].ip_address,
4126 users[0].vrf_id)
4127 self.assertEqual(len(sessions), 1)
4128 session = sessions[0]
4129 self.assertEqual(session.total_bytes, 1024)
4130 self.assertEqual(session.total_pkts, 2)
4131 stats = self.statistics.get_counter('/nat44/ha/refresh-event-recv')
4132 self.assertEqual(stats[0][0], 1)
4133
4134 stats = self.statistics.get_counter('/err/nat-ha/pkts-processed')
4135 self.assertEqual(stats, 3)
4136
4137 # send packet to test session created by HA
4138 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
4139 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4140 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out))
4141 self.pg1.add_stream(p)
4142 self.pg_enable_capture(self.pg_interfaces)
4143 self.pg_start()
4144 capture = self.pg0.get_capture(1)
4145 p = capture[0]
4146 try:
4147 ip = p[IP]
4148 tcp = p[TCP]
4149 except IndexError:
4150 self.logger.error(ppp("Invalid packet:", p))
4151 raise
4152 else:
4153 self.assertEqual(ip.src, self.pg1.remote_ip4)
4154 self.assertEqual(ip.dst, self.pg0.remote_ip4)
4155 self.assertEqual(tcp.sport, self.tcp_external_port)
4156 self.assertEqual(tcp.dport, self.tcp_port_in)
4157
Matus Fabiana6110b62018-06-13 05:39:07 -07004158 def tearDown(self):
4159 super(TestNAT44, self).tearDown()
4160 if not self.vpp_dead:
4161 self.logger.info(self.vapi.cli("show nat44 addresses"))
4162 self.logger.info(self.vapi.cli("show nat44 interfaces"))
4163 self.logger.info(self.vapi.cli("show nat44 static mappings"))
4164 self.logger.info(self.vapi.cli("show nat44 interface address"))
4165 self.logger.info(self.vapi.cli("show nat44 sessions detail"))
4166 self.logger.info(self.vapi.cli("show nat virtual-reassembly"))
4167 self.logger.info(self.vapi.cli("show nat44 hash tables detail"))
Matus Fabian878c6462018-08-23 00:33:35 -07004168 self.logger.info(self.vapi.cli("show nat timeouts"))
Matus Fabian5d28c7a2018-09-04 03:55:45 -07004169 self.logger.info(
4170 self.vapi.cli("show nat addr-port-assignment-alg"))
Matus Fabian34931eb2019-02-26 09:05:23 -08004171 self.logger.info(self.vapi.cli("show nat ha"))
Matus Fabiana6110b62018-06-13 05:39:07 -07004172 self.clear_nat44()
4173 self.vapi.cli("clear logging")
4174
4175
4176class TestNAT44EndpointDependent(MethodHolder):
4177 """ Endpoint-Dependent mapping and filtering test cases """
4178
4179 @classmethod
4180 def setUpConstants(cls):
4181 super(TestNAT44EndpointDependent, cls).setUpConstants()
4182 cls.vpp_cmdline.extend(["nat", "{", "endpoint-dependent", "}"])
4183
4184 @classmethod
4185 def setUpClass(cls):
4186 super(TestNAT44EndpointDependent, cls).setUpClass()
4187 cls.vapi.cli("set log class nat level debug")
4188 try:
4189 cls.tcp_port_in = 6303
4190 cls.tcp_port_out = 6303
4191 cls.udp_port_in = 6304
4192 cls.udp_port_out = 6304
4193 cls.icmp_id_in = 6305
4194 cls.icmp_id_out = 6305
4195 cls.nat_addr = '10.0.0.3'
4196 cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
4197 cls.ipfix_src_port = 4739
4198 cls.ipfix_domain_id = 1
4199 cls.tcp_external_port = 80
4200
Matus Fabian8008d7c2018-07-09 01:34:20 -07004201 cls.create_pg_interfaces(range(7))
Matus Fabiana6110b62018-06-13 05:39:07 -07004202 cls.interfaces = list(cls.pg_interfaces[0:3])
4203
4204 for i in cls.interfaces:
4205 i.admin_up()
4206 i.config_ip4()
4207 i.resolve_arp()
4208
4209 cls.pg0.generate_remote_hosts(3)
4210 cls.pg0.configure_ipv4_neighbors()
4211
4212 cls.pg3.admin_up()
4213
4214 cls.pg4.generate_remote_hosts(2)
4215 cls.pg4.config_ip4()
4216 ip_addr_n = socket.inet_pton(socket.AF_INET, "10.0.0.1")
Ole Troan9a475372019-03-05 16:58:24 +01004217 cls.vapi.sw_interface_add_del_address(
4218 sw_if_index=cls.pg4.sw_if_index, address=ip_addr_n,
4219 address_length=24)
Matus Fabiana6110b62018-06-13 05:39:07 -07004220 cls.pg4.admin_up()
4221 cls.pg4.resolve_arp()
4222 cls.pg4._remote_hosts[1]._ip4 = cls.pg4._remote_hosts[0]._ip4
4223 cls.pg4.resolve_arp()
4224
Matus Fabian8008d7c2018-07-09 01:34:20 -07004225 zero_ip4n = socket.inet_pton(socket.AF_INET, "0.0.0.0")
Ole Troan9a475372019-03-05 16:58:24 +01004226 cls.vapi.ip_table_add_del(is_add=1, table_id=1)
Matus Fabian8008d7c2018-07-09 01:34:20 -07004227
4228 cls.pg5._local_ip4 = "10.1.1.1"
4229 cls.pg5._local_ip4n = socket.inet_pton(socket.AF_INET,
4230 cls.pg5.local_ip4)
4231 cls.pg5._remote_hosts[0]._ip4 = "10.1.1.2"
4232 cls.pg5._remote_hosts[0]._ip4n = socket.inet_pton(
4233 socket.AF_INET, cls.pg5.remote_ip4)
4234 cls.pg5.set_table_ip4(1)
4235 cls.pg5.config_ip4()
4236 cls.pg5.admin_up()
4237 cls.vapi.ip_add_del_route(dst_address=cls.pg5.remote_ip4n,
4238 dst_address_length=32,
4239 table_id=1,
4240 next_hop_sw_if_index=cls.pg5.sw_if_index,
4241 next_hop_address=zero_ip4n)
4242
4243 cls.pg6._local_ip4 = "10.1.2.1"
4244 cls.pg6._local_ip4n = socket.inet_pton(socket.AF_INET,
4245 cls.pg6.local_ip4)
4246 cls.pg6._remote_hosts[0]._ip4 = "10.1.2.2"
4247 cls.pg6._remote_hosts[0]._ip4n = socket.inet_pton(
4248 socket.AF_INET, cls.pg6.remote_ip4)
4249 cls.pg6.set_table_ip4(1)
4250 cls.pg6.config_ip4()
4251 cls.pg6.admin_up()
4252 cls.vapi.ip_add_del_route(dst_address=cls.pg6.remote_ip4n,
4253 dst_address_length=32,
4254 table_id=1,
4255 next_hop_sw_if_index=cls.pg6.sw_if_index,
4256 next_hop_address=zero_ip4n)
4257
4258 cls.vapi.ip_add_del_route(dst_address=cls.pg6.remote_ip4n,
4259 dst_address_length=16,
4260 next_hop_address=zero_ip4n,
4261 table_id=0,
4262 next_hop_table_id=1)
4263 cls.vapi.ip_add_del_route(dst_address=zero_ip4n,
4264 dst_address_length=0,
4265 next_hop_address=zero_ip4n,
4266 table_id=1,
4267 next_hop_table_id=0)
4268 cls.vapi.ip_add_del_route(dst_address=zero_ip4n,
4269 dst_address_length=0,
4270 table_id=0,
4271 next_hop_sw_if_index=cls.pg1.sw_if_index,
4272 next_hop_address=cls.pg1.local_ip4n)
4273
4274 cls.pg5.resolve_arp()
4275 cls.pg6.resolve_arp()
4276
Matus Fabiana6110b62018-06-13 05:39:07 -07004277 except Exception:
4278 super(TestNAT44EndpointDependent, cls).tearDownClass()
4279 raise
4280
Juraj Slobodafe0aa762018-07-23 12:22:54 +02004281 def test_frag_in_order(self):
4282 """ NAT44 translate fragments arriving in order """
4283 self.nat44_add_address(self.nat_addr)
4284 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4285 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4286 is_inside=0)
4287 self.frag_in_order(proto=IP_PROTOS.tcp)
4288 self.frag_in_order(proto=IP_PROTOS.udp)
4289 self.frag_in_order(proto=IP_PROTOS.icmp)
4290
4291 def test_frag_in_order_dont_translate(self):
4292 """ NAT44 don't translate fragments arriving in order """
4293 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4294 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4295 is_inside=0)
4296 self.vapi.nat44_forwarding_enable_disable(enable=True)
4297 self.frag_in_order(proto=IP_PROTOS.tcp, dont_translate=True)
4298
4299 def test_frag_out_of_order(self):
4300 """ NAT44 translate fragments arriving out of order """
4301 self.nat44_add_address(self.nat_addr)
4302 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4303 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4304 is_inside=0)
4305 self.frag_out_of_order(proto=IP_PROTOS.tcp)
4306 self.frag_out_of_order(proto=IP_PROTOS.udp)
4307 self.frag_out_of_order(proto=IP_PROTOS.icmp)
4308
4309 def test_frag_out_of_order_dont_translate(self):
4310 """ NAT44 don't translate fragments arriving out of order """
4311 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4312 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4313 is_inside=0)
4314 self.vapi.nat44_forwarding_enable_disable(enable=True)
4315 self.frag_out_of_order(proto=IP_PROTOS.tcp, dont_translate=True)
4316
4317 def test_frag_in_order_in_plus_out(self):
4318 """ in+out interface fragments in order """
4319 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4320 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
4321 is_inside=0)
4322 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
4323 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4324 is_inside=0)
4325
4326 self.server = self.pg1.remote_hosts[0]
4327
4328 self.server_in_addr = self.server.ip4
4329 self.server_out_addr = '11.11.11.11'
4330 self.server_in_port = random.randint(1025, 65535)
4331 self.server_out_port = random.randint(1025, 65535)
4332
4333 self.nat44_add_address(self.server_out_addr)
4334
4335 # add static mappings for server
4336 self.nat44_add_static_mapping(self.server_in_addr,
4337 self.server_out_addr,
4338 self.server_in_port,
4339 self.server_out_port,
4340 proto=IP_PROTOS.tcp)
4341 self.nat44_add_static_mapping(self.server_in_addr,
4342 self.server_out_addr,
4343 self.server_in_port,
4344 self.server_out_port,
4345 proto=IP_PROTOS.udp)
4346 self.nat44_add_static_mapping(self.server_in_addr,
4347 self.server_out_addr,
4348 proto=IP_PROTOS.icmp)
4349
4350 self.vapi.nat_set_reass(timeout=10)
4351
4352 self.frag_in_order_in_plus_out(proto=IP_PROTOS.tcp)
4353 self.frag_in_order_in_plus_out(proto=IP_PROTOS.udp)
4354 self.frag_in_order_in_plus_out(proto=IP_PROTOS.icmp)
4355
4356 def test_frag_out_of_order_in_plus_out(self):
4357 """ in+out interface fragments out of order """
4358 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4359 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
4360 is_inside=0)
4361 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
4362 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4363 is_inside=0)
4364
4365 self.server = self.pg1.remote_hosts[0]
4366
4367 self.server_in_addr = self.server.ip4
4368 self.server_out_addr = '11.11.11.11'
4369 self.server_in_port = random.randint(1025, 65535)
4370 self.server_out_port = random.randint(1025, 65535)
4371
4372 self.nat44_add_address(self.server_out_addr)
4373
4374 # add static mappings for server
4375 self.nat44_add_static_mapping(self.server_in_addr,
4376 self.server_out_addr,
4377 self.server_in_port,
4378 self.server_out_port,
4379 proto=IP_PROTOS.tcp)
4380 self.nat44_add_static_mapping(self.server_in_addr,
4381 self.server_out_addr,
4382 self.server_in_port,
4383 self.server_out_port,
4384 proto=IP_PROTOS.udp)
4385 self.nat44_add_static_mapping(self.server_in_addr,
4386 self.server_out_addr,
4387 proto=IP_PROTOS.icmp)
4388
4389 self.vapi.nat_set_reass(timeout=10)
4390
4391 self.frag_out_of_order_in_plus_out(proto=IP_PROTOS.tcp)
4392 self.frag_out_of_order_in_plus_out(proto=IP_PROTOS.udp)
4393 self.frag_out_of_order_in_plus_out(proto=IP_PROTOS.icmp)
4394
4395 def test_reass_hairpinning(self):
4396 """ NAT44 fragments hairpinning """
4397 self.server = self.pg0.remote_hosts[1]
4398 self.host_in_port = random.randint(1025, 65535)
4399 self.server_in_port = random.randint(1025, 65535)
4400 self.server_out_port = random.randint(1025, 65535)
4401
4402 self.nat44_add_address(self.nat_addr)
4403 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4404 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4405 is_inside=0)
4406 # add static mapping for server
4407 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr,
4408 self.server_in_port,
4409 self.server_out_port,
4410 proto=IP_PROTOS.tcp)
4411 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr,
4412 self.server_in_port,
4413 self.server_out_port,
4414 proto=IP_PROTOS.udp)
Matus Fabianda41d722018-10-19 04:01:19 -07004415 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr)
Juraj Slobodafe0aa762018-07-23 12:22:54 +02004416
4417 self.reass_hairpinning(proto=IP_PROTOS.tcp)
4418 self.reass_hairpinning(proto=IP_PROTOS.udp)
4419 self.reass_hairpinning(proto=IP_PROTOS.icmp)
4420
Matus Fabiana6110b62018-06-13 05:39:07 -07004421 def test_dynamic(self):
4422 """ NAT44 dynamic translation test """
4423
4424 self.nat44_add_address(self.nat_addr)
4425 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4426 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4427 is_inside=0)
4428
Matus Fabian69ce30d2018-08-22 01:27:10 -07004429 nat_config = self.vapi.nat_show_config()
4430 self.assertEqual(1, nat_config.endpoint_dependent)
4431
Matus Fabiana6110b62018-06-13 05:39:07 -07004432 # in2out
Matus Fabiana5e73762018-12-14 01:55:16 -08004433 tcpn = self.statistics.get_counter(
4434 '/err/nat44-ed-in2out-slowpath/TCP packets')
4435 udpn = self.statistics.get_counter(
4436 '/err/nat44-ed-in2out-slowpath/UDP packets')
4437 icmpn = self.statistics.get_counter(
4438 '/err/nat44-ed-in2out-slowpath/ICMP packets')
4439 totaln = self.statistics.get_counter(
4440 '/err/nat44-ed-in2out-slowpath/good in2out packets processed')
4441
Matus Fabiana6110b62018-06-13 05:39:07 -07004442 pkts = self.create_stream_in(self.pg0, self.pg1)
4443 self.pg0.add_stream(pkts)
4444 self.pg_enable_capture(self.pg_interfaces)
4445 self.pg_start()
4446 capture = self.pg1.get_capture(len(pkts))
4447 self.verify_capture_out(capture)
4448
Matus Fabiana5e73762018-12-14 01:55:16 -08004449 err = self.statistics.get_counter(
4450 '/err/nat44-ed-in2out-slowpath/TCP packets')
4451 self.assertEqual(err - tcpn, 1)
4452 err = self.statistics.get_counter(
4453 '/err/nat44-ed-in2out-slowpath/UDP packets')
4454 self.assertEqual(err - udpn, 1)
4455 err = self.statistics.get_counter(
4456 '/err/nat44-ed-in2out-slowpath/ICMP packets')
4457 self.assertEqual(err - icmpn, 1)
4458 err = self.statistics.get_counter(
4459 '/err/nat44-ed-in2out-slowpath/good in2out packets processed')
4460 self.assertEqual(err - totaln, 3)
4461
Matus Fabiana6110b62018-06-13 05:39:07 -07004462 # out2in
Matus Fabiana5e73762018-12-14 01:55:16 -08004463 tcpn = self.statistics.get_counter('/err/nat44-ed-out2in/TCP packets')
4464 udpn = self.statistics.get_counter('/err/nat44-ed-out2in/UDP packets')
4465 icmpn = self.statistics.get_counter(
4466 '/err/nat44-ed-out2in-slowpath/ICMP packets')
4467 totaln = self.statistics.get_counter(
4468 '/err/nat44-ed-out2in/good out2in packets processed')
4469
Matus Fabiana6110b62018-06-13 05:39:07 -07004470 pkts = self.create_stream_out(self.pg1)
4471 self.pg1.add_stream(pkts)
4472 self.pg_enable_capture(self.pg_interfaces)
4473 self.pg_start()
4474 capture = self.pg0.get_capture(len(pkts))
4475 self.verify_capture_in(capture, self.pg0)
4476
Matus Fabiana5e73762018-12-14 01:55:16 -08004477 err = self.statistics.get_counter('/err/nat44-ed-out2in/TCP packets')
4478 self.assertEqual(err - tcpn, 1)
4479 err = self.statistics.get_counter('/err/nat44-ed-out2in/UDP packets')
4480 self.assertEqual(err - udpn, 1)
4481 err = self.statistics.get_counter(
4482 '/err/nat44-ed-out2in-slowpath/ICMP packets')
4483 self.assertEqual(err - icmpn, 1)
4484 err = self.statistics.get_counter(
4485 '/err/nat44-ed-out2in/good out2in packets processed')
4486 self.assertEqual(err - totaln, 2)
4487
Matus Fabianfd0d5082018-12-18 01:08:51 -08004488 users = self.statistics.get_counter('/nat44/total-users')
4489 self.assertEqual(users[0][0], 1)
4490 sessions = self.statistics.get_counter('/nat44/total-sessions')
4491 self.assertEqual(sessions[0][0], 3)
4492
Matus Fabiana6110b62018-06-13 05:39:07 -07004493 def test_forwarding(self):
4494 """ NAT44 forwarding test """
4495
4496 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4497 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4498 is_inside=0)
4499 self.vapi.nat44_forwarding_enable_disable(1)
4500
4501 real_ip = self.pg0.remote_ip4n
4502 alias_ip = self.nat_addr_n
4503 self.vapi.nat44_add_del_static_mapping(local_ip=real_ip,
4504 external_ip=alias_ip)
4505
4506 try:
4507 # in2out - static mapping match
4508
4509 pkts = self.create_stream_out(self.pg1)
4510 self.pg1.add_stream(pkts)
4511 self.pg_enable_capture(self.pg_interfaces)
4512 self.pg_start()
4513 capture = self.pg0.get_capture(len(pkts))
4514 self.verify_capture_in(capture, self.pg0)
4515
4516 pkts = self.create_stream_in(self.pg0, self.pg1)
4517 self.pg0.add_stream(pkts)
4518 self.pg_enable_capture(self.pg_interfaces)
4519 self.pg_start()
4520 capture = self.pg1.get_capture(len(pkts))
4521 self.verify_capture_out(capture, same_port=True)
4522
4523 # in2out - no static mapping match
4524
4525 host0 = self.pg0.remote_hosts[0]
4526 self.pg0.remote_hosts[0] = self.pg0.remote_hosts[1]
4527 try:
4528 pkts = self.create_stream_out(self.pg1,
4529 dst_ip=self.pg0.remote_ip4,
4530 use_inside_ports=True)
4531 self.pg1.add_stream(pkts)
4532 self.pg_enable_capture(self.pg_interfaces)
4533 self.pg_start()
4534 capture = self.pg0.get_capture(len(pkts))
4535 self.verify_capture_in(capture, self.pg0)
4536
4537 pkts = self.create_stream_in(self.pg0, self.pg1)
4538 self.pg0.add_stream(pkts)
4539 self.pg_enable_capture(self.pg_interfaces)
4540 self.pg_start()
4541 capture = self.pg1.get_capture(len(pkts))
4542 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
4543 same_port=True)
4544 finally:
4545 self.pg0.remote_hosts[0] = host0
4546
4547 user = self.pg0.remote_hosts[1]
4548 sessions = self.vapi.nat44_user_session_dump(user.ip4n, 0)
4549 self.assertEqual(len(sessions), 3)
4550 self.assertTrue(sessions[0].ext_host_valid)
4551 self.vapi.nat44_del_session(
4552 sessions[0].inside_ip_address,
4553 sessions[0].inside_port,
4554 sessions[0].protocol,
4555 ext_host_address=sessions[0].ext_host_address,
4556 ext_host_port=sessions[0].ext_host_port)
4557 sessions = self.vapi.nat44_user_session_dump(user.ip4n, 0)
4558 self.assertEqual(len(sessions), 2)
4559
4560 finally:
4561 self.vapi.nat44_forwarding_enable_disable(0)
4562 self.vapi.nat44_add_del_static_mapping(local_ip=real_ip,
4563 external_ip=alias_ip,
4564 is_add=0)
4565
4566 def test_static_lb(self):
4567 """ NAT44 local service load balancing """
4568 external_addr_n = socket.inet_pton(socket.AF_INET, self.nat_addr)
4569 external_port = 80
4570 local_port = 8080
4571 server1 = self.pg0.remote_hosts[0]
4572 server2 = self.pg0.remote_hosts[1]
4573
4574 locals = [{'addr': server1.ip4n,
4575 'port': local_port,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07004576 'probability': 70,
4577 'vrf_id': 0},
Matus Fabiana6110b62018-06-13 05:39:07 -07004578 {'addr': server2.ip4n,
4579 'port': local_port,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07004580 'probability': 30,
4581 'vrf_id': 0}]
Matus Fabiana6110b62018-06-13 05:39:07 -07004582
4583 self.nat44_add_address(self.nat_addr)
4584 self.vapi.nat44_add_del_lb_static_mapping(external_addr_n,
4585 external_port,
4586 IP_PROTOS.tcp,
4587 local_num=len(locals),
4588 locals=locals)
4589 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4590 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4591 is_inside=0)
4592
4593 # from client to service
4594 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4595 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4596 TCP(sport=12345, dport=external_port))
4597 self.pg1.add_stream(p)
4598 self.pg_enable_capture(self.pg_interfaces)
4599 self.pg_start()
4600 capture = self.pg0.get_capture(1)
4601 p = capture[0]
4602 server = None
4603 try:
4604 ip = p[IP]
4605 tcp = p[TCP]
4606 self.assertIn(ip.dst, [server1.ip4, server2.ip4])
4607 if ip.dst == server1.ip4:
4608 server = server1
4609 else:
4610 server = server2
4611 self.assertEqual(tcp.dport, local_port)
4612 self.assert_packet_checksums_valid(p)
4613 except:
4614 self.logger.error(ppp("Unexpected or invalid packet:", p))
4615 raise
4616
4617 # from service back to client
4618 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
4619 IP(src=server.ip4, dst=self.pg1.remote_ip4) /
4620 TCP(sport=local_port, dport=12345))
4621 self.pg0.add_stream(p)
4622 self.pg_enable_capture(self.pg_interfaces)
4623 self.pg_start()
4624 capture = self.pg1.get_capture(1)
4625 p = capture[0]
4626 try:
4627 ip = p[IP]
4628 tcp = p[TCP]
4629 self.assertEqual(ip.src, self.nat_addr)
4630 self.assertEqual(tcp.sport, external_port)
4631 self.assert_packet_checksums_valid(p)
4632 except:
4633 self.logger.error(ppp("Unexpected or invalid packet:", p))
4634 raise
4635
4636 sessions = self.vapi.nat44_user_session_dump(server.ip4n, 0)
4637 self.assertEqual(len(sessions), 1)
4638 self.assertTrue(sessions[0].ext_host_valid)
4639 self.vapi.nat44_del_session(
4640 sessions[0].inside_ip_address,
4641 sessions[0].inside_port,
4642 sessions[0].protocol,
4643 ext_host_address=sessions[0].ext_host_address,
4644 ext_host_port=sessions[0].ext_host_port)
4645 sessions = self.vapi.nat44_user_session_dump(server.ip4n, 0)
4646 self.assertEqual(len(sessions), 0)
4647
Paul Vinciguerradefde0f2018-12-06 07:46:13 -08004648 @unittest.skipUnless(running_extended_tests, "part of extended tests")
Matus Fabiana6110b62018-06-13 05:39:07 -07004649 def test_static_lb_multi_clients(self):
4650 """ NAT44 local service load balancing - multiple clients"""
4651
4652 external_addr_n = socket.inet_pton(socket.AF_INET, self.nat_addr)
4653 external_port = 80
4654 local_port = 8080
4655 server1 = self.pg0.remote_hosts[0]
4656 server2 = self.pg0.remote_hosts[1]
Matus Fabianb6865082018-12-06 03:11:09 -08004657 server3 = self.pg0.remote_hosts[2]
Matus Fabiana6110b62018-06-13 05:39:07 -07004658
4659 locals = [{'addr': server1.ip4n,
4660 'port': local_port,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07004661 'probability': 90,
4662 'vrf_id': 0},
Matus Fabiana6110b62018-06-13 05:39:07 -07004663 {'addr': server2.ip4n,
4664 'port': local_port,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07004665 'probability': 10,
4666 'vrf_id': 0}]
Matus Fabiana6110b62018-06-13 05:39:07 -07004667
4668 self.nat44_add_address(self.nat_addr)
4669 self.vapi.nat44_add_del_lb_static_mapping(external_addr_n,
4670 external_port,
4671 IP_PROTOS.tcp,
4672 local_num=len(locals),
4673 locals=locals)
4674 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4675 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4676 is_inside=0)
4677
4678 server1_n = 0
4679 server2_n = 0
4680 clients = ip4_range(self.pg1.remote_ip4, 10, 50)
4681 pkts = []
4682 for client in clients:
4683 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4684 IP(src=client, dst=self.nat_addr) /
4685 TCP(sport=12345, dport=external_port))
4686 pkts.append(p)
4687 self.pg1.add_stream(pkts)
4688 self.pg_enable_capture(self.pg_interfaces)
4689 self.pg_start()
4690 capture = self.pg0.get_capture(len(pkts))
4691 for p in capture:
4692 if p[IP].dst == server1.ip4:
4693 server1_n += 1
4694 else:
4695 server2_n += 1
Paul Vinciguerra3d2df212018-11-24 23:19:53 -08004696 self.assertGreater(server1_n, server2_n)
Matus Fabiana6110b62018-06-13 05:39:07 -07004697
Matus Fabianb6865082018-12-06 03:11:09 -08004698 # add new back-end
4699 self.vapi.nat44_lb_static_mapping_add_del_local(external_addr_n,
4700 external_port,
4701 server3.ip4n,
4702 local_port,
4703 IP_PROTOS.tcp,
4704 20)
4705 server1_n = 0
4706 server2_n = 0
4707 server3_n = 0
4708 clients = ip4_range(self.pg1.remote_ip4, 60, 110)
4709 pkts = []
4710 for client in clients:
4711 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4712 IP(src=client, dst=self.nat_addr) /
4713 TCP(sport=12346, dport=external_port))
4714 pkts.append(p)
4715 self.assertGreater(len(pkts), 0)
4716 self.pg1.add_stream(pkts)
4717 self.pg_enable_capture(self.pg_interfaces)
4718 self.pg_start()
4719 capture = self.pg0.get_capture(len(pkts))
4720 for p in capture:
4721 if p[IP].dst == server1.ip4:
4722 server1_n += 1
4723 elif p[IP].dst == server2.ip4:
4724 server2_n += 1
4725 else:
4726 server3_n += 1
4727 self.assertGreater(server1_n, 0)
4728 self.assertGreater(server2_n, 0)
4729 self.assertGreater(server3_n, 0)
4730
4731 # remove one back-end
4732 self.vapi.nat44_lb_static_mapping_add_del_local(external_addr_n,
4733 external_port,
4734 server2.ip4n,
4735 local_port,
4736 IP_PROTOS.tcp,
4737 10,
4738 is_add=0)
4739 server1_n = 0
4740 server2_n = 0
4741 server3_n = 0
4742 self.pg1.add_stream(pkts)
4743 self.pg_enable_capture(self.pg_interfaces)
4744 self.pg_start()
4745 capture = self.pg0.get_capture(len(pkts))
4746 for p in capture:
4747 if p[IP].dst == server1.ip4:
4748 server1_n += 1
4749 elif p[IP].dst == server2.ip4:
4750 server2_n += 1
4751 else:
4752 server3_n += 1
4753 self.assertGreater(server1_n, 0)
4754 self.assertEqual(server2_n, 0)
4755 self.assertGreater(server3_n, 0)
4756
Matus Fabiana6110b62018-06-13 05:39:07 -07004757 def test_static_lb_2(self):
4758 """ NAT44 local service load balancing (asymmetrical rule) """
4759 external_addr_n = socket.inet_pton(socket.AF_INET, self.nat_addr)
4760 external_port = 80
4761 local_port = 8080
4762 server1 = self.pg0.remote_hosts[0]
4763 server2 = self.pg0.remote_hosts[1]
4764
4765 locals = [{'addr': server1.ip4n,
4766 'port': local_port,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07004767 'probability': 70,
4768 'vrf_id': 0},
Matus Fabiana6110b62018-06-13 05:39:07 -07004769 {'addr': server2.ip4n,
4770 'port': local_port,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07004771 'probability': 30,
4772 'vrf_id': 0}]
Matus Fabiana6110b62018-06-13 05:39:07 -07004773
4774 self.vapi.nat44_forwarding_enable_disable(1)
4775 self.vapi.nat44_add_del_lb_static_mapping(external_addr_n,
4776 external_port,
4777 IP_PROTOS.tcp,
4778 out2in_only=1,
4779 local_num=len(locals),
4780 locals=locals)
4781 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4782 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4783 is_inside=0)
4784
4785 # from client to service
4786 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4787 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4788 TCP(sport=12345, dport=external_port))
4789 self.pg1.add_stream(p)
4790 self.pg_enable_capture(self.pg_interfaces)
4791 self.pg_start()
4792 capture = self.pg0.get_capture(1)
4793 p = capture[0]
4794 server = None
4795 try:
4796 ip = p[IP]
4797 tcp = p[TCP]
4798 self.assertIn(ip.dst, [server1.ip4, server2.ip4])
4799 if ip.dst == server1.ip4:
4800 server = server1
4801 else:
4802 server = server2
4803 self.assertEqual(tcp.dport, local_port)
4804 self.assert_packet_checksums_valid(p)
4805 except:
4806 self.logger.error(ppp("Unexpected or invalid packet:", p))
4807 raise
4808
4809 # from service back to client
4810 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
4811 IP(src=server.ip4, dst=self.pg1.remote_ip4) /
4812 TCP(sport=local_port, dport=12345))
4813 self.pg0.add_stream(p)
4814 self.pg_enable_capture(self.pg_interfaces)
4815 self.pg_start()
4816 capture = self.pg1.get_capture(1)
4817 p = capture[0]
4818 try:
4819 ip = p[IP]
4820 tcp = p[TCP]
4821 self.assertEqual(ip.src, self.nat_addr)
4822 self.assertEqual(tcp.sport, external_port)
4823 self.assert_packet_checksums_valid(p)
4824 except:
4825 self.logger.error(ppp("Unexpected or invalid packet:", p))
4826 raise
4827
4828 # from client to server (no translation)
4829 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4830 IP(src=self.pg1.remote_ip4, dst=server1.ip4) /
4831 TCP(sport=12346, dport=local_port))
4832 self.pg1.add_stream(p)
4833 self.pg_enable_capture(self.pg_interfaces)
4834 self.pg_start()
4835 capture = self.pg0.get_capture(1)
4836 p = capture[0]
4837 server = None
4838 try:
4839 ip = p[IP]
4840 tcp = p[TCP]
4841 self.assertEqual(ip.dst, server1.ip4)
4842 self.assertEqual(tcp.dport, local_port)
4843 self.assert_packet_checksums_valid(p)
4844 except:
4845 self.logger.error(ppp("Unexpected or invalid packet:", p))
4846 raise
4847
4848 # from service back to client (no translation)
4849 p = (Ether(src=server1.mac, dst=self.pg0.local_mac) /
4850 IP(src=server1.ip4, dst=self.pg1.remote_ip4) /
4851 TCP(sport=local_port, dport=12346))
4852 self.pg0.add_stream(p)
4853 self.pg_enable_capture(self.pg_interfaces)
4854 self.pg_start()
4855 capture = self.pg1.get_capture(1)
4856 p = capture[0]
4857 try:
4858 ip = p[IP]
4859 tcp = p[TCP]
4860 self.assertEqual(ip.src, server1.ip4)
4861 self.assertEqual(tcp.sport, local_port)
4862 self.assert_packet_checksums_valid(p)
4863 except:
4864 self.logger.error(ppp("Unexpected or invalid packet:", p))
4865 raise
4866
Matus Fabianea5b5be2018-09-03 05:02:23 -07004867 def test_lb_affinity(self):
4868 """ NAT44 local service load balancing affinity """
4869 external_addr_n = socket.inet_pton(socket.AF_INET, self.nat_addr)
4870 external_port = 80
4871 local_port = 8080
4872 server1 = self.pg0.remote_hosts[0]
4873 server2 = self.pg0.remote_hosts[1]
4874
4875 locals = [{'addr': server1.ip4n,
4876 'port': local_port,
4877 'probability': 50,
4878 'vrf_id': 0},
4879 {'addr': server2.ip4n,
4880 'port': local_port,
4881 'probability': 50,
4882 'vrf_id': 0}]
4883
4884 self.nat44_add_address(self.nat_addr)
4885 self.vapi.nat44_add_del_lb_static_mapping(external_addr_n,
4886 external_port,
4887 IP_PROTOS.tcp,
4888 affinity=10800,
4889 local_num=len(locals),
4890 locals=locals)
4891 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4892 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4893 is_inside=0)
4894
4895 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
4896 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4897 TCP(sport=1025, dport=external_port))
4898 self.pg1.add_stream(p)
4899 self.pg_enable_capture(self.pg_interfaces)
4900 self.pg_start()
4901 capture = self.pg0.get_capture(1)
4902 backend = capture[0][IP].dst
4903
4904 sessions = self.vapi.nat44_user_session_dump(
4905 socket.inet_pton(socket.AF_INET, backend), 0)
4906 self.assertEqual(len(sessions), 1)
4907 self.assertTrue(sessions[0].ext_host_valid)
4908 self.vapi.nat44_del_session(
4909 sessions[0].inside_ip_address,
4910 sessions[0].inside_port,
4911 sessions[0].protocol,
4912 ext_host_address=sessions[0].ext_host_address,
4913 ext_host_port=sessions[0].ext_host_port)
4914
4915 pkts = []
4916 for port in range(1030, 1100):
4917 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
4918 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4919 TCP(sport=port, dport=external_port))
4920 pkts.append(p)
4921 self.pg1.add_stream(pkts)
4922 self.pg_enable_capture(self.pg_interfaces)
4923 self.pg_start()
4924 capture = self.pg0.get_capture(len(pkts))
4925 for p in capture:
4926 self.assertEqual(p[IP].dst, backend)
4927
Matus Fabiana6110b62018-06-13 05:39:07 -07004928 def test_unknown_proto(self):
4929 """ NAT44 translate packet with unknown protocol """
4930 self.nat44_add_address(self.nat_addr)
4931 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4932 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4933 is_inside=0)
4934
4935 # in2out
4936 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
4937 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4938 TCP(sport=self.tcp_port_in, dport=20))
4939 self.pg0.add_stream(p)
4940 self.pg_enable_capture(self.pg_interfaces)
4941 self.pg_start()
4942 p = self.pg1.get_capture(1)
4943
4944 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
4945 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4946 GRE() /
4947 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
4948 TCP(sport=1234, dport=1234))
4949 self.pg0.add_stream(p)
4950 self.pg_enable_capture(self.pg_interfaces)
4951 self.pg_start()
4952 p = self.pg1.get_capture(1)
4953 packet = p[0]
4954 try:
4955 self.assertEqual(packet[IP].src, self.nat_addr)
4956 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
Paul Vinciguerra978aa642018-11-24 22:19:12 -08004957 self.assertEqual(packet.haslayer(GRE), 1)
Matus Fabiana6110b62018-06-13 05:39:07 -07004958 self.assert_packet_checksums_valid(packet)
4959 except:
4960 self.logger.error(ppp("Unexpected or invalid packet:", packet))
4961 raise
4962
4963 # out2in
4964 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
4965 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4966 GRE() /
4967 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
4968 TCP(sport=1234, dport=1234))
4969 self.pg1.add_stream(p)
4970 self.pg_enable_capture(self.pg_interfaces)
4971 self.pg_start()
4972 p = self.pg0.get_capture(1)
4973 packet = p[0]
4974 try:
4975 self.assertEqual(packet[IP].src, self.pg1.remote_ip4)
4976 self.assertEqual(packet[IP].dst, self.pg0.remote_ip4)
Paul Vinciguerra978aa642018-11-24 22:19:12 -08004977 self.assertEqual(packet.haslayer(GRE), 1)
Matus Fabiana6110b62018-06-13 05:39:07 -07004978 self.assert_packet_checksums_valid(packet)
4979 except:
4980 self.logger.error(ppp("Unexpected or invalid packet:", packet))
4981 raise
4982
4983 def test_hairpinning_unknown_proto(self):
4984 """ NAT44 translate packet with unknown protocol - hairpinning """
4985 host = self.pg0.remote_hosts[0]
4986 server = self.pg0.remote_hosts[1]
4987 host_in_port = 1234
4988 server_out_port = 8765
4989 server_nat_ip = "10.0.0.11"
4990
4991 self.nat44_add_address(self.nat_addr)
4992 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4993 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4994 is_inside=0)
4995
4996 # add static mapping for server
4997 self.nat44_add_static_mapping(server.ip4, server_nat_ip)
4998
4999 # host to server
5000 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
5001 IP(src=host.ip4, dst=server_nat_ip) /
5002 TCP(sport=host_in_port, dport=server_out_port))
5003 self.pg0.add_stream(p)
5004 self.pg_enable_capture(self.pg_interfaces)
5005 self.pg_start()
5006 self.pg0.get_capture(1)
5007
5008 p = (Ether(dst=self.pg0.local_mac, src=host.mac) /
5009 IP(src=host.ip4, dst=server_nat_ip) /
5010 GRE() /
5011 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
5012 TCP(sport=1234, dport=1234))
5013 self.pg0.add_stream(p)
5014 self.pg_enable_capture(self.pg_interfaces)
5015 self.pg_start()
5016 p = self.pg0.get_capture(1)
5017 packet = p[0]
5018 try:
5019 self.assertEqual(packet[IP].src, self.nat_addr)
5020 self.assertEqual(packet[IP].dst, server.ip4)
Paul Vinciguerra978aa642018-11-24 22:19:12 -08005021 self.assertEqual(packet.haslayer(GRE), 1)
Matus Fabiana6110b62018-06-13 05:39:07 -07005022 self.assert_packet_checksums_valid(packet)
5023 except:
5024 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5025 raise
5026
5027 # server to host
5028 p = (Ether(dst=self.pg0.local_mac, src=server.mac) /
5029 IP(src=server.ip4, dst=self.nat_addr) /
5030 GRE() /
5031 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
5032 TCP(sport=1234, dport=1234))
5033 self.pg0.add_stream(p)
5034 self.pg_enable_capture(self.pg_interfaces)
5035 self.pg_start()
5036 p = self.pg0.get_capture(1)
5037 packet = p[0]
5038 try:
5039 self.assertEqual(packet[IP].src, server_nat_ip)
5040 self.assertEqual(packet[IP].dst, host.ip4)
Paul Vinciguerra978aa642018-11-24 22:19:12 -08005041 self.assertEqual(packet.haslayer(GRE), 1)
Matus Fabiana6110b62018-06-13 05:39:07 -07005042 self.assert_packet_checksums_valid(packet)
5043 except:
5044 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5045 raise
5046
5047 def test_output_feature_and_service(self):
5048 """ NAT44 interface output feature and services """
5049 external_addr = '1.2.3.4'
5050 external_port = 80
5051 local_port = 8080
5052
5053 self.vapi.nat44_forwarding_enable_disable(1)
5054 self.nat44_add_address(self.nat_addr)
5055 self.vapi.nat44_add_del_identity_mapping(ip=self.pg1.remote_ip4n)
5056 self.nat44_add_static_mapping(self.pg0.remote_ip4, external_addr,
5057 local_port, external_port,
5058 proto=IP_PROTOS.tcp, out2in_only=1)
5059 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5060 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
5061 is_inside=0)
5062 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
5063 is_inside=0)
5064
5065 # from client to service
5066 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5067 IP(src=self.pg1.remote_ip4, dst=external_addr) /
5068 TCP(sport=12345, dport=external_port))
5069 self.pg1.add_stream(p)
5070 self.pg_enable_capture(self.pg_interfaces)
5071 self.pg_start()
5072 capture = self.pg0.get_capture(1)
5073 p = capture[0]
5074 try:
5075 ip = p[IP]
5076 tcp = p[TCP]
5077 self.assertEqual(ip.dst, self.pg0.remote_ip4)
5078 self.assertEqual(tcp.dport, local_port)
5079 self.assert_packet_checksums_valid(p)
5080 except:
5081 self.logger.error(ppp("Unexpected or invalid packet:", p))
5082 raise
5083
5084 # from service back to client
5085 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5086 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5087 TCP(sport=local_port, dport=12345))
5088 self.pg0.add_stream(p)
5089 self.pg_enable_capture(self.pg_interfaces)
5090 self.pg_start()
5091 capture = self.pg1.get_capture(1)
5092 p = capture[0]
5093 try:
5094 ip = p[IP]
5095 tcp = p[TCP]
5096 self.assertEqual(ip.src, external_addr)
5097 self.assertEqual(tcp.sport, external_port)
5098 self.assert_packet_checksums_valid(p)
5099 except:
5100 self.logger.error(ppp("Unexpected or invalid packet:", p))
5101 raise
5102
5103 # from local network host to external network
5104 pkts = self.create_stream_in(self.pg0, self.pg1)
5105 self.pg0.add_stream(pkts)
5106 self.pg_enable_capture(self.pg_interfaces)
5107 self.pg_start()
5108 capture = self.pg1.get_capture(len(pkts))
5109 self.verify_capture_out(capture)
5110 pkts = self.create_stream_in(self.pg0, self.pg1)
5111 self.pg0.add_stream(pkts)
5112 self.pg_enable_capture(self.pg_interfaces)
5113 self.pg_start()
5114 capture = self.pg1.get_capture(len(pkts))
5115 self.verify_capture_out(capture)
5116
5117 # from external network back to local network host
5118 pkts = self.create_stream_out(self.pg1)
5119 self.pg1.add_stream(pkts)
5120 self.pg_enable_capture(self.pg_interfaces)
5121 self.pg_start()
5122 capture = self.pg0.get_capture(len(pkts))
5123 self.verify_capture_in(capture, self.pg0)
5124
5125 def test_output_feature_and_service2(self):
5126 """ NAT44 interface output feature and service host direct access """
5127 self.vapi.nat44_forwarding_enable_disable(1)
5128 self.nat44_add_address(self.nat_addr)
5129 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
5130 is_inside=0)
5131
5132 # session initiaded from service host - translate
5133 pkts = self.create_stream_in(self.pg0, self.pg1)
5134 self.pg0.add_stream(pkts)
5135 self.pg_enable_capture(self.pg_interfaces)
5136 self.pg_start()
5137 capture = self.pg1.get_capture(len(pkts))
5138 self.verify_capture_out(capture)
5139
5140 pkts = self.create_stream_out(self.pg1)
5141 self.pg1.add_stream(pkts)
5142 self.pg_enable_capture(self.pg_interfaces)
5143 self.pg_start()
5144 capture = self.pg0.get_capture(len(pkts))
5145 self.verify_capture_in(capture, self.pg0)
5146
5147 # session initiaded from remote host - do not translate
5148 self.tcp_port_in = 60303
5149 self.udp_port_in = 60304
5150 self.icmp_id_in = 60305
5151 pkts = self.create_stream_out(self.pg1,
5152 self.pg0.remote_ip4,
5153 use_inside_ports=True)
5154 self.pg1.add_stream(pkts)
5155 self.pg_enable_capture(self.pg_interfaces)
5156 self.pg_start()
5157 capture = self.pg0.get_capture(len(pkts))
5158 self.verify_capture_in(capture, self.pg0)
5159
5160 pkts = self.create_stream_in(self.pg0, self.pg1)
5161 self.pg0.add_stream(pkts)
5162 self.pg_enable_capture(self.pg_interfaces)
5163 self.pg_start()
5164 capture = self.pg1.get_capture(len(pkts))
5165 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
5166 same_port=True)
5167
5168 def test_output_feature_and_service3(self):
5169 """ NAT44 interface output feature and DST NAT """
5170 external_addr = '1.2.3.4'
5171 external_port = 80
5172 local_port = 8080
5173
5174 self.vapi.nat44_forwarding_enable_disable(1)
5175 self.nat44_add_address(self.nat_addr)
5176 self.nat44_add_static_mapping(self.pg1.remote_ip4, external_addr,
5177 local_port, external_port,
5178 proto=IP_PROTOS.tcp, out2in_only=1)
5179 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5180 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
5181 is_inside=0)
5182 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
5183 is_inside=0)
5184
5185 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5186 IP(src=self.pg0.remote_ip4, dst=external_addr) /
5187 TCP(sport=12345, dport=external_port))
5188 self.pg0.add_stream(p)
5189 self.pg_enable_capture(self.pg_interfaces)
5190 self.pg_start()
5191 capture = self.pg1.get_capture(1)
5192 p = capture[0]
5193 try:
5194 ip = p[IP]
5195 tcp = p[TCP]
5196 self.assertEqual(ip.src, self.pg0.remote_ip4)
5197 self.assertEqual(tcp.sport, 12345)
5198 self.assertEqual(ip.dst, self.pg1.remote_ip4)
5199 self.assertEqual(tcp.dport, local_port)
5200 self.assert_packet_checksums_valid(p)
5201 except:
5202 self.logger.error(ppp("Unexpected or invalid packet:", p))
5203 raise
5204
5205 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5206 IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
5207 TCP(sport=local_port, dport=12345))
5208 self.pg1.add_stream(p)
5209 self.pg_enable_capture(self.pg_interfaces)
5210 self.pg_start()
5211 capture = self.pg0.get_capture(1)
5212 p = capture[0]
5213 try:
5214 ip = p[IP]
5215 tcp = p[TCP]
5216 self.assertEqual(ip.src, external_addr)
5217 self.assertEqual(tcp.sport, external_port)
5218 self.assertEqual(ip.dst, self.pg0.remote_ip4)
5219 self.assertEqual(tcp.dport, 12345)
5220 self.assert_packet_checksums_valid(p)
5221 except:
5222 self.logger.error(ppp("Unexpected or invalid packet:", p))
5223 raise
5224
Matus Fabian182e37e2018-08-14 04:21:26 -07005225 def test_next_src_nat(self):
5226 """ On way back forward packet to nat44-in2out node. """
5227 twice_nat_addr = '10.0.1.3'
5228 external_port = 80
5229 local_port = 8080
5230 post_twice_nat_port = 0
5231
5232 self.vapi.nat44_forwarding_enable_disable(1)
5233 self.nat44_add_address(twice_nat_addr, twice_nat=1)
5234 self.nat44_add_static_mapping(self.pg6.remote_ip4, self.pg1.remote_ip4,
5235 local_port, external_port,
5236 proto=IP_PROTOS.tcp, out2in_only=1,
5237 self_twice_nat=1, vrf_id=1)
5238 self.vapi.nat44_interface_add_del_feature(self.pg6.sw_if_index,
5239 is_inside=0)
5240
5241 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
5242 IP(src=self.pg6.remote_ip4, dst=self.pg1.remote_ip4) /
5243 TCP(sport=12345, dport=external_port))
5244 self.pg6.add_stream(p)
5245 self.pg_enable_capture(self.pg_interfaces)
5246 self.pg_start()
5247 capture = self.pg6.get_capture(1)
5248 p = capture[0]
5249 try:
5250 ip = p[IP]
5251 tcp = p[TCP]
5252 self.assertEqual(ip.src, twice_nat_addr)
5253 self.assertNotEqual(tcp.sport, 12345)
5254 post_twice_nat_port = tcp.sport
5255 self.assertEqual(ip.dst, self.pg6.remote_ip4)
5256 self.assertEqual(tcp.dport, local_port)
5257 self.assert_packet_checksums_valid(p)
5258 except:
5259 self.logger.error(ppp("Unexpected or invalid packet:", p))
5260 raise
5261
5262 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
5263 IP(src=self.pg6.remote_ip4, dst=twice_nat_addr) /
5264 TCP(sport=local_port, dport=post_twice_nat_port))
5265 self.pg6.add_stream(p)
5266 self.pg_enable_capture(self.pg_interfaces)
5267 self.pg_start()
5268 capture = self.pg6.get_capture(1)
5269 p = capture[0]
5270 try:
5271 ip = p[IP]
5272 tcp = p[TCP]
5273 self.assertEqual(ip.src, self.pg1.remote_ip4)
5274 self.assertEqual(tcp.sport, external_port)
5275 self.assertEqual(ip.dst, self.pg6.remote_ip4)
5276 self.assertEqual(tcp.dport, 12345)
5277 self.assert_packet_checksums_valid(p)
5278 except:
5279 self.logger.error(ppp("Unexpected or invalid packet:", p))
5280 raise
5281
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005282 def twice_nat_common(self, self_twice_nat=False, same_pg=False, lb=False,
5283 client_id=None):
Matus Fabianb932d262017-12-18 05:38:24 -08005284 twice_nat_addr = '10.0.1.3'
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005285
Matus Fabianb932d262017-12-18 05:38:24 -08005286 port_in = 8080
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005287 if lb:
5288 if not same_pg:
5289 port_in1 = port_in
5290 port_in2 = port_in
5291 else:
Ole Troan9a475372019-03-05 16:58:24 +01005292 port_in1 = port_in + 1
5293 port_in2 = port_in + 2
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005294
Matus Fabianb932d262017-12-18 05:38:24 -08005295 port_out = 80
5296 eh_port_out = 4567
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005297
5298 server1 = self.pg0.remote_hosts[0]
5299 server2 = self.pg0.remote_hosts[1]
5300 if lb and same_pg:
5301 server2 = server1
5302 if not lb:
5303 server = server1
5304
5305 pg0 = self.pg0
5306 if same_pg:
5307 pg1 = self.pg0
5308 else:
5309 pg1 = self.pg1
5310
5311 eh_translate = ((not self_twice_nat) or (not lb and same_pg) or
5312 client_id == 1)
5313
Matus Fabianb932d262017-12-18 05:38:24 -08005314 self.nat44_add_address(self.nat_addr)
5315 self.nat44_add_address(twice_nat_addr, twice_nat=1)
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005316 if not lb:
5317 self.nat44_add_static_mapping(pg0.remote_ip4, self.nat_addr,
5318 port_in, port_out,
5319 proto=IP_PROTOS.tcp,
5320 twice_nat=int(not self_twice_nat),
5321 self_twice_nat=int(self_twice_nat))
5322 else:
5323 locals = [{'addr': server1.ip4n,
5324 'port': port_in1,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07005325 'probability': 50,
5326 'vrf_id': 0},
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005327 {'addr': server2.ip4n,
5328 'port': port_in2,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07005329 'probability': 50,
5330 'vrf_id': 0}]
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005331 out_addr_n = socket.inet_pton(socket.AF_INET, self.nat_addr)
5332 self.vapi.nat44_add_del_lb_static_mapping(out_addr_n,
5333 port_out,
5334 IP_PROTOS.tcp,
5335 twice_nat=int(
5336 not self_twice_nat),
5337 self_twice_nat=int(
5338 self_twice_nat),
5339 local_num=len(locals),
5340 locals=locals)
5341 self.vapi.nat44_interface_add_del_feature(pg0.sw_if_index)
5342 self.vapi.nat44_interface_add_del_feature(pg1.sw_if_index,
Matus Fabianb932d262017-12-18 05:38:24 -08005343 is_inside=0)
5344
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005345 if same_pg:
5346 if not lb:
5347 client = server
5348 else:
5349 assert client_id is not None
5350 if client_id == 1:
5351 client = self.pg0.remote_hosts[0]
5352 elif client_id == 2:
5353 client = self.pg0.remote_hosts[1]
5354 else:
5355 client = pg1.remote_hosts[0]
5356 p = (Ether(src=pg1.remote_mac, dst=pg1.local_mac) /
5357 IP(src=client.ip4, dst=self.nat_addr) /
Matus Fabianb932d262017-12-18 05:38:24 -08005358 TCP(sport=eh_port_out, dport=port_out))
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005359 pg1.add_stream(p)
Matus Fabianb932d262017-12-18 05:38:24 -08005360 self.pg_enable_capture(self.pg_interfaces)
5361 self.pg_start()
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005362 capture = pg0.get_capture(1)
Matus Fabianb932d262017-12-18 05:38:24 -08005363 p = capture[0]
5364 try:
5365 ip = p[IP]
5366 tcp = p[TCP]
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005367 if lb:
5368 if ip.dst == server1.ip4:
5369 server = server1
5370 port_in = port_in1
5371 else:
5372 server = server2
5373 port_in = port_in2
5374 self.assertEqual(ip.dst, server.ip4)
5375 if lb and same_pg:
5376 self.assertIn(tcp.dport, [port_in1, port_in2])
5377 else:
5378 self.assertEqual(tcp.dport, port_in)
5379 if eh_translate:
5380 self.assertEqual(ip.src, twice_nat_addr)
5381 self.assertNotEqual(tcp.sport, eh_port_out)
5382 else:
5383 self.assertEqual(ip.src, client.ip4)
5384 self.assertEqual(tcp.sport, eh_port_out)
5385 eh_addr_in = ip.src
Matus Fabianb932d262017-12-18 05:38:24 -08005386 eh_port_in = tcp.sport
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005387 saved_port_in = tcp.dport
Klement Sekerad81ae412018-05-16 10:52:54 +02005388 self.assert_packet_checksums_valid(p)
Matus Fabianb932d262017-12-18 05:38:24 -08005389 except:
5390 self.logger.error(ppp("Unexpected or invalid packet:", p))
5391 raise
5392
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005393 p = (Ether(src=server.mac, dst=pg0.local_mac) /
5394 IP(src=server.ip4, dst=eh_addr_in) /
5395 TCP(sport=saved_port_in, dport=eh_port_in))
5396 pg0.add_stream(p)
Matus Fabianb932d262017-12-18 05:38:24 -08005397 self.pg_enable_capture(self.pg_interfaces)
5398 self.pg_start()
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005399 capture = pg1.get_capture(1)
Matus Fabianb932d262017-12-18 05:38:24 -08005400 p = capture[0]
5401 try:
5402 ip = p[IP]
5403 tcp = p[TCP]
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005404 self.assertEqual(ip.dst, client.ip4)
Matus Fabianb932d262017-12-18 05:38:24 -08005405 self.assertEqual(ip.src, self.nat_addr)
5406 self.assertEqual(tcp.dport, eh_port_out)
5407 self.assertEqual(tcp.sport, port_out)
Klement Sekerad81ae412018-05-16 10:52:54 +02005408 self.assert_packet_checksums_valid(p)
Matus Fabianb932d262017-12-18 05:38:24 -08005409 except:
5410 self.logger.error(ppp("Unexpected or invalid packet:", p))
5411 raise
5412
Matus Fabian70a26ac2018-05-14 06:20:28 -07005413 if eh_translate:
5414 sessions = self.vapi.nat44_user_session_dump(server.ip4n, 0)
5415 self.assertEqual(len(sessions), 1)
5416 self.assertTrue(sessions[0].ext_host_valid)
5417 self.assertTrue(sessions[0].is_twicenat)
5418 self.vapi.nat44_del_session(
5419 sessions[0].inside_ip_address,
5420 sessions[0].inside_port,
5421 sessions[0].protocol,
5422 ext_host_address=sessions[0].ext_host_nat_address,
5423 ext_host_port=sessions[0].ext_host_nat_port)
5424 sessions = self.vapi.nat44_user_session_dump(server.ip4n, 0)
5425 self.assertEqual(len(sessions), 0)
5426
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005427 def test_twice_nat(self):
5428 """ Twice NAT44 """
5429 self.twice_nat_common()
5430
5431 def test_self_twice_nat_positive(self):
5432 """ Self Twice NAT44 (positive test) """
5433 self.twice_nat_common(self_twice_nat=True, same_pg=True)
5434
5435 def test_self_twice_nat_negative(self):
5436 """ Self Twice NAT44 (negative test) """
5437 self.twice_nat_common(self_twice_nat=True)
5438
Matus Fabianb932d262017-12-18 05:38:24 -08005439 def test_twice_nat_lb(self):
5440 """ Twice NAT44 local service load balancing """
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005441 self.twice_nat_common(lb=True)
Matus Fabianb932d262017-12-18 05:38:24 -08005442
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005443 def test_self_twice_nat_lb_positive(self):
5444 """ Self Twice NAT44 local service load balancing (positive test) """
5445 self.twice_nat_common(lb=True, self_twice_nat=True, same_pg=True,
5446 client_id=1)
Matus Fabianb932d262017-12-18 05:38:24 -08005447
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005448 def test_self_twice_nat_lb_negative(self):
5449 """ Self Twice NAT44 local service load balancing (negative test) """
5450 self.twice_nat_common(lb=True, self_twice_nat=True, same_pg=True,
5451 client_id=2)
Matus Fabianb932d262017-12-18 05:38:24 -08005452
5453 def test_twice_nat_interface_addr(self):
5454 """ Acquire twice NAT44 addresses from interface """
Ole Troane1ade682019-03-04 23:55:43 +01005455 self.vapi.nat44_add_del_interface_addr(self.pg3.sw_if_index,
5456 twice_nat=1)
Matus Fabianb932d262017-12-18 05:38:24 -08005457
5458 # no address in NAT pool
5459 adresses = self.vapi.nat44_address_dump()
5460 self.assertEqual(0, len(adresses))
5461
5462 # configure interface address and check NAT address pool
Matus Fabiana6110b62018-06-13 05:39:07 -07005463 self.pg3.config_ip4()
Matus Fabianb932d262017-12-18 05:38:24 -08005464 adresses = self.vapi.nat44_address_dump()
5465 self.assertEqual(1, len(adresses))
Matus Fabiana6110b62018-06-13 05:39:07 -07005466 self.assertEqual(adresses[0].ip_address[0:4], self.pg3.local_ip4n)
Matus Fabianb932d262017-12-18 05:38:24 -08005467 self.assertEqual(adresses[0].twice_nat, 1)
5468
5469 # remove interface address and check NAT address pool
Matus Fabiana6110b62018-06-13 05:39:07 -07005470 self.pg3.unconfig_ip4()
Matus Fabianb932d262017-12-18 05:38:24 -08005471 adresses = self.vapi.nat44_address_dump()
5472 self.assertEqual(0, len(adresses))
5473
Matus Fabian6c01dce2018-11-16 04:41:31 -08005474 def test_tcp_close(self):
5475 """ Close TCP session from inside network - output feature """
5476 self.vapi.nat44_forwarding_enable_disable(1)
5477 self.nat44_add_address(self.pg1.local_ip4)
5478 twice_nat_addr = '10.0.1.3'
5479 service_ip = '192.168.16.150'
5480 self.nat44_add_address(twice_nat_addr, twice_nat=1)
5481 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5482 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
5483 is_inside=0)
5484 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
5485 is_inside=0)
5486 self.nat44_add_static_mapping(self.pg0.remote_ip4,
5487 service_ip,
5488 80,
5489 80,
5490 proto=IP_PROTOS.tcp,
5491 out2in_only=1,
5492 twice_nat=1)
5493 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
5494 start_sessnum = len(sessions)
5495
5496 # SYN packet out->in
5497 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5498 IP(src=self.pg1.remote_ip4, dst=service_ip) /
5499 TCP(sport=33898, dport=80, flags="S"))
5500 self.pg1.add_stream(p)
5501 self.pg_enable_capture(self.pg_interfaces)
5502 self.pg_start()
5503 capture = self.pg0.get_capture(1)
5504 p = capture[0]
5505 tcp_port = p[TCP].sport
5506
5507 # SYN + ACK packet in->out
5508 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5509 IP(src=self.pg0.remote_ip4, dst=twice_nat_addr) /
5510 TCP(sport=80, dport=tcp_port, flags="SA"))
5511 self.pg0.add_stream(p)
5512 self.pg_enable_capture(self.pg_interfaces)
5513 self.pg_start()
5514 self.pg1.get_capture(1)
5515
5516 # ACK packet out->in
5517 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5518 IP(src=self.pg1.remote_ip4, dst=service_ip) /
5519 TCP(sport=33898, dport=80, flags="A"))
5520 self.pg1.add_stream(p)
5521 self.pg_enable_capture(self.pg_interfaces)
5522 self.pg_start()
5523 self.pg0.get_capture(1)
5524
5525 # FIN packet in -> out
5526 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5527 IP(src=self.pg0.remote_ip4, dst=twice_nat_addr) /
5528 TCP(sport=80, dport=tcp_port, flags="FA", seq=100, ack=300))
5529 self.pg0.add_stream(p)
5530 self.pg_enable_capture(self.pg_interfaces)
5531 self.pg_start()
5532 self.pg1.get_capture(1)
5533
5534 # FIN+ACK packet out -> in
5535 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5536 IP(src=self.pg1.remote_ip4, dst=service_ip) /
5537 TCP(sport=33898, dport=80, flags="FA", seq=300, ack=101))
5538 self.pg1.add_stream(p)
5539 self.pg_enable_capture(self.pg_interfaces)
5540 self.pg_start()
5541 self.pg0.get_capture(1)
5542
5543 # ACK packet in -> out
5544 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5545 IP(src=self.pg0.remote_ip4, dst=twice_nat_addr) /
5546 TCP(sport=80, dport=tcp_port, flags="A", seq=101, ack=301))
5547 self.pg0.add_stream(p)
5548 self.pg_enable_capture(self.pg_interfaces)
5549 self.pg_start()
5550 self.pg1.get_capture(1)
5551
5552 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n,
5553 0)
5554 self.assertEqual(len(sessions) - start_sessnum, 0)
5555
Matus Fabianebdf1902018-05-04 03:57:42 -07005556 def test_tcp_session_close_in(self):
5557 """ Close TCP session from inside network """
Matus Fabian229c1aa2018-05-28 04:09:52 -07005558 self.tcp_port_out = 10505
Matus Fabianebdf1902018-05-04 03:57:42 -07005559 self.nat44_add_address(self.nat_addr)
Matus Fabian229c1aa2018-05-28 04:09:52 -07005560 self.nat44_add_static_mapping(self.pg0.remote_ip4,
5561 self.nat_addr,
5562 self.tcp_port_in,
5563 self.tcp_port_out,
5564 proto=IP_PROTOS.tcp,
5565 twice_nat=1)
Matus Fabianebdf1902018-05-04 03:57:42 -07005566 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5567 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
5568 is_inside=0)
5569
5570 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
5571 start_sessnum = len(sessions)
5572
5573 self.initiate_tcp_session(self.pg0, self.pg1)
5574
Matus Fabian229c1aa2018-05-28 04:09:52 -07005575 # FIN packet in -> out
5576 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5577 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5578 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
5579 flags="FA", seq=100, ack=300))
5580 self.pg0.add_stream(p)
5581 self.pg_enable_capture(self.pg_interfaces)
5582 self.pg_start()
5583 self.pg1.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07005584
Matus Fabian229c1aa2018-05-28 04:09:52 -07005585 pkts = []
Matus Fabianebdf1902018-05-04 03:57:42 -07005586
Matus Fabian229c1aa2018-05-28 04:09:52 -07005587 # ACK packet out -> in
5588 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5589 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5590 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
5591 flags="A", seq=300, ack=101))
5592 pkts.append(p)
Matus Fabianebdf1902018-05-04 03:57:42 -07005593
Matus Fabian229c1aa2018-05-28 04:09:52 -07005594 # FIN packet out -> in
5595 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5596 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5597 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
5598 flags="FA", seq=300, ack=101))
5599 pkts.append(p)
Matus Fabianebdf1902018-05-04 03:57:42 -07005600
Matus Fabian229c1aa2018-05-28 04:09:52 -07005601 self.pg1.add_stream(pkts)
5602 self.pg_enable_capture(self.pg_interfaces)
5603 self.pg_start()
5604 self.pg0.get_capture(2)
Matus Fabianebdf1902018-05-04 03:57:42 -07005605
Matus Fabian229c1aa2018-05-28 04:09:52 -07005606 # ACK packet in -> out
5607 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5608 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5609 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
5610 flags="A", seq=101, ack=301))
5611 self.pg0.add_stream(p)
5612 self.pg_enable_capture(self.pg_interfaces)
5613 self.pg_start()
5614 self.pg1.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07005615
Matus Fabian229c1aa2018-05-28 04:09:52 -07005616 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n,
5617 0)
5618 self.assertEqual(len(sessions) - start_sessnum, 0)
Matus Fabianebdf1902018-05-04 03:57:42 -07005619
5620 def test_tcp_session_close_out(self):
5621 """ Close TCP session from outside network """
Matus Fabian229c1aa2018-05-28 04:09:52 -07005622 self.tcp_port_out = 10505
Matus Fabianebdf1902018-05-04 03:57:42 -07005623 self.nat44_add_address(self.nat_addr)
Matus Fabian229c1aa2018-05-28 04:09:52 -07005624 self.nat44_add_static_mapping(self.pg0.remote_ip4,
5625 self.nat_addr,
5626 self.tcp_port_in,
5627 self.tcp_port_out,
5628 proto=IP_PROTOS.tcp,
5629 twice_nat=1)
Matus Fabianebdf1902018-05-04 03:57:42 -07005630 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5631 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
5632 is_inside=0)
5633
5634 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
5635 start_sessnum = len(sessions)
5636
5637 self.initiate_tcp_session(self.pg0, self.pg1)
5638
Matus Fabian229c1aa2018-05-28 04:09:52 -07005639 # FIN packet out -> in
5640 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5641 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5642 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
5643 flags="FA", seq=100, ack=300))
5644 self.pg1.add_stream(p)
5645 self.pg_enable_capture(self.pg_interfaces)
5646 self.pg_start()
5647 self.pg0.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07005648
Matus Fabian229c1aa2018-05-28 04:09:52 -07005649 # FIN+ACK packet in -> out
5650 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5651 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5652 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
5653 flags="FA", seq=300, ack=101))
Matus Fabianebdf1902018-05-04 03:57:42 -07005654
Matus Fabian229c1aa2018-05-28 04:09:52 -07005655 self.pg0.add_stream(p)
5656 self.pg_enable_capture(self.pg_interfaces)
5657 self.pg_start()
5658 self.pg1.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07005659
Matus Fabian229c1aa2018-05-28 04:09:52 -07005660 # ACK packet out -> in
5661 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5662 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5663 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
5664 flags="A", seq=101, ack=301))
5665 self.pg1.add_stream(p)
5666 self.pg_enable_capture(self.pg_interfaces)
5667 self.pg_start()
5668 self.pg0.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07005669
Matus Fabian229c1aa2018-05-28 04:09:52 -07005670 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n,
5671 0)
5672 self.assertEqual(len(sessions) - start_sessnum, 0)
Matus Fabianebdf1902018-05-04 03:57:42 -07005673
5674 def test_tcp_session_close_simultaneous(self):
5675 """ Close TCP session from inside network """
Matus Fabian229c1aa2018-05-28 04:09:52 -07005676 self.tcp_port_out = 10505
Matus Fabianebdf1902018-05-04 03:57:42 -07005677 self.nat44_add_address(self.nat_addr)
Matus Fabian229c1aa2018-05-28 04:09:52 -07005678 self.nat44_add_static_mapping(self.pg0.remote_ip4,
5679 self.nat_addr,
5680 self.tcp_port_in,
5681 self.tcp_port_out,
5682 proto=IP_PROTOS.tcp,
5683 twice_nat=1)
Matus Fabianebdf1902018-05-04 03:57:42 -07005684 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5685 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
5686 is_inside=0)
5687
5688 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
5689 start_sessnum = len(sessions)
5690
5691 self.initiate_tcp_session(self.pg0, self.pg1)
5692
Matus Fabian229c1aa2018-05-28 04:09:52 -07005693 # FIN packet in -> out
5694 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5695 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5696 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
5697 flags="FA", seq=100, ack=300))
5698 self.pg0.add_stream(p)
5699 self.pg_enable_capture(self.pg_interfaces)
5700 self.pg_start()
5701 self.pg1.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07005702
Matus Fabian229c1aa2018-05-28 04:09:52 -07005703 # FIN packet out -> in
5704 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5705 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5706 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
5707 flags="FA", seq=300, ack=100))
5708 self.pg1.add_stream(p)
5709 self.pg_enable_capture(self.pg_interfaces)
5710 self.pg_start()
5711 self.pg0.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07005712
Matus Fabian229c1aa2018-05-28 04:09:52 -07005713 # ACK packet in -> out
5714 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5715 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5716 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
5717 flags="A", seq=101, ack=301))
5718 self.pg0.add_stream(p)
5719 self.pg_enable_capture(self.pg_interfaces)
5720 self.pg_start()
5721 self.pg1.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07005722
Matus Fabian229c1aa2018-05-28 04:09:52 -07005723 # ACK packet out -> in
5724 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5725 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5726 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
5727 flags="A", seq=301, ack=101))
5728 self.pg1.add_stream(p)
5729 self.pg_enable_capture(self.pg_interfaces)
5730 self.pg_start()
5731 self.pg0.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07005732
Matus Fabian229c1aa2018-05-28 04:09:52 -07005733 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n,
5734 0)
5735 self.assertEqual(len(sessions) - start_sessnum, 0)
Matus Fabianebdf1902018-05-04 03:57:42 -07005736
Matus Fabiana6110b62018-06-13 05:39:07 -07005737 def test_one_armed_nat44_static(self):
5738 """ One armed NAT44 and 1:1 NAPT asymmetrical rule """
5739 remote_host = self.pg4.remote_hosts[0]
5740 local_host = self.pg4.remote_hosts[1]
5741 external_port = 80
5742 local_port = 8080
5743 eh_port_in = 0
5744
5745 self.vapi.nat44_forwarding_enable_disable(1)
5746 self.nat44_add_address(self.nat_addr, twice_nat=1)
5747 self.nat44_add_static_mapping(local_host.ip4, self.nat_addr,
5748 local_port, external_port,
5749 proto=IP_PROTOS.tcp, out2in_only=1,
5750 twice_nat=1)
5751 self.vapi.nat44_interface_add_del_feature(self.pg4.sw_if_index)
5752 self.vapi.nat44_interface_add_del_feature(self.pg4.sw_if_index,
5753 is_inside=0)
5754
5755 # from client to service
5756 p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
5757 IP(src=remote_host.ip4, dst=self.nat_addr) /
5758 TCP(sport=12345, dport=external_port))
5759 self.pg4.add_stream(p)
5760 self.pg_enable_capture(self.pg_interfaces)
5761 self.pg_start()
5762 capture = self.pg4.get_capture(1)
5763 p = capture[0]
5764 try:
5765 ip = p[IP]
5766 tcp = p[TCP]
5767 self.assertEqual(ip.dst, local_host.ip4)
5768 self.assertEqual(ip.src, self.nat_addr)
5769 self.assertEqual(tcp.dport, local_port)
5770 self.assertNotEqual(tcp.sport, 12345)
5771 eh_port_in = tcp.sport
5772 self.assert_packet_checksums_valid(p)
5773 except:
5774 self.logger.error(ppp("Unexpected or invalid packet:", p))
5775 raise
5776
5777 # from service back to client
5778 p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
5779 IP(src=local_host.ip4, dst=self.nat_addr) /
5780 TCP(sport=local_port, dport=eh_port_in))
5781 self.pg4.add_stream(p)
5782 self.pg_enable_capture(self.pg_interfaces)
5783 self.pg_start()
5784 capture = self.pg4.get_capture(1)
5785 p = capture[0]
5786 try:
5787 ip = p[IP]
5788 tcp = p[TCP]
5789 self.assertEqual(ip.src, self.nat_addr)
5790 self.assertEqual(ip.dst, remote_host.ip4)
5791 self.assertEqual(tcp.sport, external_port)
5792 self.assertEqual(tcp.dport, 12345)
5793 self.assert_packet_checksums_valid(p)
5794 except:
5795 self.logger.error(ppp("Unexpected or invalid packet:", p))
5796 raise
5797
5798 def test_static_with_port_out2(self):
5799 """ 1:1 NAPT asymmetrical rule """
5800
5801 external_port = 80
5802 local_port = 8080
5803
5804 self.vapi.nat44_forwarding_enable_disable(1)
5805 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
5806 local_port, external_port,
5807 proto=IP_PROTOS.tcp, out2in_only=1)
5808 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5809 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
5810 is_inside=0)
5811
5812 # from client to service
5813 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5814 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5815 TCP(sport=12345, dport=external_port))
5816 self.pg1.add_stream(p)
5817 self.pg_enable_capture(self.pg_interfaces)
5818 self.pg_start()
5819 capture = self.pg0.get_capture(1)
5820 p = capture[0]
5821 try:
5822 ip = p[IP]
5823 tcp = p[TCP]
5824 self.assertEqual(ip.dst, self.pg0.remote_ip4)
5825 self.assertEqual(tcp.dport, local_port)
5826 self.assert_packet_checksums_valid(p)
5827 except:
5828 self.logger.error(ppp("Unexpected or invalid packet:", p))
5829 raise
5830
5831 # ICMP error
5832 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5833 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5834 ICMP(type=11) / capture[0][IP])
5835 self.pg0.add_stream(p)
5836 self.pg_enable_capture(self.pg_interfaces)
5837 self.pg_start()
5838 capture = self.pg1.get_capture(1)
5839 p = capture[0]
5840 try:
5841 self.assertEqual(p[IP].src, self.nat_addr)
5842 inner = p[IPerror]
5843 self.assertEqual(inner.dst, self.nat_addr)
5844 self.assertEqual(inner[TCPerror].dport, external_port)
5845 except:
5846 self.logger.error(ppp("Unexpected or invalid packet:", p))
5847 raise
5848
5849 # from service back to client
5850 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5851 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5852 TCP(sport=local_port, dport=12345))
5853 self.pg0.add_stream(p)
5854 self.pg_enable_capture(self.pg_interfaces)
5855 self.pg_start()
5856 capture = self.pg1.get_capture(1)
5857 p = capture[0]
5858 try:
5859 ip = p[IP]
5860 tcp = p[TCP]
5861 self.assertEqual(ip.src, self.nat_addr)
5862 self.assertEqual(tcp.sport, external_port)
5863 self.assert_packet_checksums_valid(p)
5864 except:
5865 self.logger.error(ppp("Unexpected or invalid packet:", p))
5866 raise
5867
5868 # ICMP error
5869 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
5870 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5871 ICMP(type=11) / capture[0][IP])
5872 self.pg1.add_stream(p)
5873 self.pg_enable_capture(self.pg_interfaces)
5874 self.pg_start()
5875 capture = self.pg0.get_capture(1)
5876 p = capture[0]
5877 try:
5878 self.assertEqual(p[IP].dst, self.pg0.remote_ip4)
5879 inner = p[IPerror]
5880 self.assertEqual(inner.src, self.pg0.remote_ip4)
5881 self.assertEqual(inner[TCPerror].sport, local_port)
5882 except:
5883 self.logger.error(ppp("Unexpected or invalid packet:", p))
5884 raise
5885
5886 # from client to server (no translation)
5887 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5888 IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
5889 TCP(sport=12346, dport=local_port))
5890 self.pg1.add_stream(p)
5891 self.pg_enable_capture(self.pg_interfaces)
5892 self.pg_start()
5893 capture = self.pg0.get_capture(1)
5894 p = capture[0]
5895 try:
5896 ip = p[IP]
5897 tcp = p[TCP]
5898 self.assertEqual(ip.dst, self.pg0.remote_ip4)
5899 self.assertEqual(tcp.dport, local_port)
5900 self.assert_packet_checksums_valid(p)
5901 except:
5902 self.logger.error(ppp("Unexpected or invalid packet:", p))
5903 raise
5904
5905 # from service back to client (no translation)
5906 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5907 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5908 TCP(sport=local_port, dport=12346))
5909 self.pg0.add_stream(p)
5910 self.pg_enable_capture(self.pg_interfaces)
5911 self.pg_start()
5912 capture = self.pg1.get_capture(1)
5913 p = capture[0]
5914 try:
5915 ip = p[IP]
5916 tcp = p[TCP]
5917 self.assertEqual(ip.src, self.pg0.remote_ip4)
5918 self.assertEqual(tcp.sport, local_port)
5919 self.assert_packet_checksums_valid(p)
5920 except:
5921 self.logger.error(ppp("Unexpected or invalid packet:", p))
5922 raise
5923
Matus Fabian235a47e2018-06-25 16:42:36 -07005924 def test_output_feature(self):
5925 """ NAT44 interface output feature (in2out postrouting) """
5926 self.vapi.nat44_forwarding_enable_disable(1)
5927 self.nat44_add_address(self.nat_addr)
5928 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
5929 is_inside=0)
5930 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
5931 is_inside=0)
5932
5933 # in2out
5934 pkts = self.create_stream_in(self.pg0, self.pg1)
5935 self.pg0.add_stream(pkts)
5936 self.pg_enable_capture(self.pg_interfaces)
5937 self.pg_start()
5938 capture = self.pg1.get_capture(len(pkts))
5939 self.verify_capture_out(capture)
5940
5941 # out2in
5942 pkts = self.create_stream_out(self.pg1)
5943 self.pg1.add_stream(pkts)
5944 self.pg_enable_capture(self.pg_interfaces)
5945 self.pg_start()
5946 capture = self.pg0.get_capture(len(pkts))
5947 self.verify_capture_in(capture, self.pg0)
5948
Matus Fabian8008d7c2018-07-09 01:34:20 -07005949 def test_multiple_vrf(self):
5950 """ Multiple VRF setup """
5951 external_addr = '1.2.3.4'
5952 external_port = 80
5953 local_port = 8080
5954 port = 0
5955
5956 self.vapi.nat44_forwarding_enable_disable(1)
5957 self.nat44_add_address(self.nat_addr)
5958 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5959 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
5960 is_inside=0)
5961 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
5962 is_inside=0)
5963 self.vapi.nat44_interface_add_del_feature(self.pg5.sw_if_index)
5964 self.vapi.nat44_interface_add_del_feature(self.pg5.sw_if_index,
5965 is_inside=0)
5966 self.vapi.nat44_interface_add_del_feature(self.pg6.sw_if_index,
5967 is_inside=0)
5968 self.nat44_add_static_mapping(self.pg5.remote_ip4, external_addr,
5969 local_port, external_port, vrf_id=1,
5970 proto=IP_PROTOS.tcp, out2in_only=1)
5971 self.nat44_add_static_mapping(
Ole Troan9a475372019-03-05 16:58:24 +01005972 self.pg0.remote_ip4, external_sw_if_index=self.pg0.sw_if_index,
5973 local_port=local_port, vrf_id=0, external_port=external_port,
5974 proto=IP_PROTOS.tcp, out2in_only=1)
Matus Fabian8008d7c2018-07-09 01:34:20 -07005975
5976 # from client to service (both VRF1)
5977 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
5978 IP(src=self.pg6.remote_ip4, dst=external_addr) /
5979 TCP(sport=12345, dport=external_port))
5980 self.pg6.add_stream(p)
5981 self.pg_enable_capture(self.pg_interfaces)
5982 self.pg_start()
5983 capture = self.pg5.get_capture(1)
5984 p = capture[0]
5985 try:
5986 ip = p[IP]
5987 tcp = p[TCP]
5988 self.assertEqual(ip.dst, self.pg5.remote_ip4)
5989 self.assertEqual(tcp.dport, local_port)
5990 self.assert_packet_checksums_valid(p)
5991 except:
5992 self.logger.error(ppp("Unexpected or invalid packet:", p))
5993 raise
5994
5995 # from service back to client (both VRF1)
5996 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
5997 IP(src=self.pg5.remote_ip4, dst=self.pg6.remote_ip4) /
5998 TCP(sport=local_port, dport=12345))
5999 self.pg5.add_stream(p)
6000 self.pg_enable_capture(self.pg_interfaces)
6001 self.pg_start()
6002 capture = self.pg6.get_capture(1)
6003 p = capture[0]
6004 try:
6005 ip = p[IP]
6006 tcp = p[TCP]
6007 self.assertEqual(ip.src, external_addr)
6008 self.assertEqual(tcp.sport, external_port)
6009 self.assert_packet_checksums_valid(p)
6010 except:
6011 self.logger.error(ppp("Unexpected or invalid packet:", p))
6012 raise
6013
6014 # dynamic NAT from VRF1 to VRF0 (output-feature)
6015 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
6016 IP(src=self.pg5.remote_ip4, dst=self.pg1.remote_ip4) /
6017 TCP(sport=2345, dport=22))
6018 self.pg5.add_stream(p)
6019 self.pg_enable_capture(self.pg_interfaces)
6020 self.pg_start()
6021 capture = self.pg1.get_capture(1)
6022 p = capture[0]
6023 try:
6024 ip = p[IP]
6025 tcp = p[TCP]
6026 self.assertEqual(ip.src, self.nat_addr)
6027 self.assertNotEqual(tcp.sport, 2345)
6028 self.assert_packet_checksums_valid(p)
6029 port = tcp.sport
6030 except:
6031 self.logger.error(ppp("Unexpected or invalid packet:", p))
6032 raise
6033
6034 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6035 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6036 TCP(sport=22, dport=port))
6037 self.pg1.add_stream(p)
6038 self.pg_enable_capture(self.pg_interfaces)
6039 self.pg_start()
6040 capture = self.pg5.get_capture(1)
6041 p = capture[0]
6042 try:
6043 ip = p[IP]
6044 tcp = p[TCP]
6045 self.assertEqual(ip.dst, self.pg5.remote_ip4)
6046 self.assertEqual(tcp.dport, 2345)
6047 self.assert_packet_checksums_valid(p)
6048 except:
6049 self.logger.error(ppp("Unexpected or invalid packet:", p))
6050 raise
6051
6052 # from client VRF1 to service VRF0
6053 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
6054 IP(src=self.pg6.remote_ip4, dst=self.pg0.local_ip4) /
6055 TCP(sport=12346, dport=external_port))
6056 self.pg6.add_stream(p)
6057 self.pg_enable_capture(self.pg_interfaces)
6058 self.pg_start()
6059 capture = self.pg0.get_capture(1)
6060 p = capture[0]
6061 try:
6062 ip = p[IP]
6063 tcp = p[TCP]
6064 self.assertEqual(ip.dst, self.pg0.remote_ip4)
6065 self.assertEqual(tcp.dport, local_port)
6066 self.assert_packet_checksums_valid(p)
6067 except:
6068 self.logger.error(ppp("Unexpected or invalid packet:", p))
6069 raise
6070
6071 # from service VRF0 back to client VRF1
6072 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6073 IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
6074 TCP(sport=local_port, dport=12346))
6075 self.pg0.add_stream(p)
6076 self.pg_enable_capture(self.pg_interfaces)
6077 self.pg_start()
6078 capture = self.pg6.get_capture(1)
6079 p = capture[0]
6080 try:
6081 ip = p[IP]
6082 tcp = p[TCP]
6083 self.assertEqual(ip.src, self.pg0.local_ip4)
6084 self.assertEqual(tcp.sport, external_port)
6085 self.assert_packet_checksums_valid(p)
6086 except:
6087 self.logger.error(ppp("Unexpected or invalid packet:", p))
6088 raise
6089
6090 # from client VRF0 to service VRF1
6091 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6092 IP(src=self.pg0.remote_ip4, dst=external_addr) /
6093 TCP(sport=12347, dport=external_port))
6094 self.pg0.add_stream(p)
6095 self.pg_enable_capture(self.pg_interfaces)
6096 self.pg_start()
6097 capture = self.pg5.get_capture(1)
6098 p = capture[0]
6099 try:
6100 ip = p[IP]
6101 tcp = p[TCP]
6102 self.assertEqual(ip.dst, self.pg5.remote_ip4)
6103 self.assertEqual(tcp.dport, local_port)
6104 self.assert_packet_checksums_valid(p)
6105 except:
6106 self.logger.error(ppp("Unexpected or invalid packet:", p))
6107 raise
6108
6109 # from service VRF1 back to client VRF0
6110 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
6111 IP(src=self.pg5.remote_ip4, dst=self.pg0.remote_ip4) /
6112 TCP(sport=local_port, dport=12347))
6113 self.pg5.add_stream(p)
6114 self.pg_enable_capture(self.pg_interfaces)
6115 self.pg_start()
6116 capture = self.pg0.get_capture(1)
6117 p = capture[0]
6118 try:
6119 ip = p[IP]
6120 tcp = p[TCP]
6121 self.assertEqual(ip.src, external_addr)
6122 self.assertEqual(tcp.sport, external_port)
6123 self.assert_packet_checksums_valid(p)
6124 except:
6125 self.logger.error(ppp("Unexpected or invalid packet:", p))
6126 raise
6127
6128 # from client to server (both VRF1, no translation)
6129 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
6130 IP(src=self.pg6.remote_ip4, dst=self.pg5.remote_ip4) /
6131 TCP(sport=12348, dport=local_port))
6132 self.pg6.add_stream(p)
6133 self.pg_enable_capture(self.pg_interfaces)
6134 self.pg_start()
6135 capture = self.pg5.get_capture(1)
6136 p = capture[0]
6137 try:
6138 ip = p[IP]
6139 tcp = p[TCP]
6140 self.assertEqual(ip.dst, self.pg5.remote_ip4)
6141 self.assertEqual(tcp.dport, local_port)
6142 self.assert_packet_checksums_valid(p)
6143 except:
6144 self.logger.error(ppp("Unexpected or invalid packet:", p))
6145 raise
6146
6147 # from server back to client (both VRF1, no translation)
6148 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
6149 IP(src=self.pg5.remote_ip4, dst=self.pg6.remote_ip4) /
6150 TCP(sport=local_port, dport=12348))
6151 self.pg5.add_stream(p)
6152 self.pg_enable_capture(self.pg_interfaces)
6153 self.pg_start()
6154 capture = self.pg6.get_capture(1)
6155 p = capture[0]
6156 try:
6157 ip = p[IP]
6158 tcp = p[TCP]
6159 self.assertEqual(ip.src, self.pg5.remote_ip4)
6160 self.assertEqual(tcp.sport, local_port)
6161 self.assert_packet_checksums_valid(p)
6162 except:
6163 self.logger.error(ppp("Unexpected or invalid packet:", p))
6164 raise
6165
6166 # from client VRF1 to server VRF0 (no translation)
6167 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6168 IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
6169 TCP(sport=local_port, dport=12349))
6170 self.pg0.add_stream(p)
6171 self.pg_enable_capture(self.pg_interfaces)
6172 self.pg_start()
6173 capture = self.pg6.get_capture(1)
6174 p = capture[0]
6175 try:
6176 ip = p[IP]
6177 tcp = p[TCP]
6178 self.assertEqual(ip.src, self.pg0.remote_ip4)
6179 self.assertEqual(tcp.sport, local_port)
6180 self.assert_packet_checksums_valid(p)
6181 except:
6182 self.logger.error(ppp("Unexpected or invalid packet:", p))
6183 raise
6184
6185 # from server VRF0 back to client VRF1 (no translation)
6186 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6187 IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
6188 TCP(sport=local_port, dport=12349))
6189 self.pg0.add_stream(p)
6190 self.pg_enable_capture(self.pg_interfaces)
6191 self.pg_start()
6192 capture = self.pg6.get_capture(1)
6193 p = capture[0]
6194 try:
6195 ip = p[IP]
6196 tcp = p[TCP]
6197 self.assertEqual(ip.src, self.pg0.remote_ip4)
6198 self.assertEqual(tcp.sport, local_port)
6199 self.assert_packet_checksums_valid(p)
6200 except:
6201 self.logger.error(ppp("Unexpected or invalid packet:", p))
6202 raise
6203
6204 # from client VRF0 to server VRF1 (no translation)
6205 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6206 IP(src=self.pg0.remote_ip4, dst=self.pg5.remote_ip4) /
6207 TCP(sport=12344, dport=local_port))
6208 self.pg0.add_stream(p)
6209 self.pg_enable_capture(self.pg_interfaces)
6210 self.pg_start()
6211 capture = self.pg5.get_capture(1)
6212 p = capture[0]
6213 try:
6214 ip = p[IP]
6215 tcp = p[TCP]
6216 self.assertEqual(ip.dst, self.pg5.remote_ip4)
6217 self.assertEqual(tcp.dport, local_port)
6218 self.assert_packet_checksums_valid(p)
6219 except:
6220 self.logger.error(ppp("Unexpected or invalid packet:", p))
6221 raise
6222
6223 # from server VRF1 back to client VRF0 (no translation)
6224 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
6225 IP(src=self.pg5.remote_ip4, dst=self.pg0.remote_ip4) /
6226 TCP(sport=local_port, dport=12344))
6227 self.pg5.add_stream(p)
6228 self.pg_enable_capture(self.pg_interfaces)
6229 self.pg_start()
6230 capture = self.pg0.get_capture(1)
6231 p = capture[0]
6232 try:
6233 ip = p[IP]
6234 tcp = p[TCP]
6235 self.assertEqual(ip.src, self.pg5.remote_ip4)
6236 self.assertEqual(tcp.sport, local_port)
6237 self.assert_packet_checksums_valid(p)
6238 except:
6239 self.logger.error(ppp("Unexpected or invalid packet:", p))
6240 raise
6241
Paul Vinciguerradefde0f2018-12-06 07:46:13 -08006242 @unittest.skipUnless(running_extended_tests, "part of extended tests")
Matus Fabian878c6462018-08-23 00:33:35 -07006243 def test_session_timeout(self):
6244 """ NAT44 session timeouts """
6245 self.nat44_add_address(self.nat_addr)
6246 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
6247 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
6248 is_inside=0)
6249 self.vapi.nat_set_timeouts(icmp=5)
6250
6251 max_sessions = 1000
6252 pkts = []
6253 for i in range(0, max_sessions):
6254 src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
6255 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6256 IP(src=src, dst=self.pg1.remote_ip4) /
6257 ICMP(id=1025, type='echo-request'))
6258 pkts.append(p)
6259 self.pg0.add_stream(pkts)
6260 self.pg_enable_capture(self.pg_interfaces)
6261 self.pg_start()
6262 self.pg1.get_capture(max_sessions)
6263
6264 sleep(10)
6265
6266 pkts = []
6267 for i in range(0, max_sessions):
Matus Fabian7f8a8db2018-11-22 00:12:15 -08006268 src = "10.11.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
Matus Fabian878c6462018-08-23 00:33:35 -07006269 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6270 IP(src=src, dst=self.pg1.remote_ip4) /
6271 ICMP(id=1026, type='echo-request'))
6272 pkts.append(p)
6273 self.pg0.add_stream(pkts)
6274 self.pg_enable_capture(self.pg_interfaces)
6275 self.pg_start()
6276 self.pg1.get_capture(max_sessions)
6277
6278 nsessions = 0
6279 users = self.vapi.nat44_user_dump()
6280 for user in users:
6281 nsessions = nsessions + user.nsessions
6282 self.assertLess(nsessions, 2 * max_sessions)
6283
Paul Vinciguerradefde0f2018-12-06 07:46:13 -08006284 @unittest.skipUnless(running_extended_tests, "part of extended tests")
Matus Fabian15e8e682018-11-21 04:53:10 -08006285 def test_session_rst_timeout(self):
6286 """ NAT44 session RST timeouts """
6287 self.nat44_add_address(self.nat_addr)
6288 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
6289 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
6290 is_inside=0)
6291 self.vapi.nat_set_timeouts(tcp_transitory=5)
6292
Matus Fabian15e8e682018-11-21 04:53:10 -08006293 self.initiate_tcp_session(self.pg0, self.pg1)
6294 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6295 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6296 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6297 flags="R"))
6298 self.pg0.add_stream(p)
6299 self.pg_enable_capture(self.pg_interfaces)
6300 self.pg_start()
6301 self.pg1.get_capture(1)
6302
Matus Fabian15e8e682018-11-21 04:53:10 -08006303 sleep(6)
6304
6305 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6306 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6307 TCP(sport=self.tcp_port_in + 1, dport=self.tcp_external_port + 1,
6308 flags="S"))
6309 self.pg0.add_stream(p)
6310 self.pg_enable_capture(self.pg_interfaces)
6311 self.pg_start()
6312 self.pg1.get_capture(1)
6313
6314 nsessions = 0
6315 users = self.vapi.nat44_user_dump()
6316 self.assertEqual(len(users), 1)
6317 self.assertEqual(users[0].ip_address, self.pg0.remote_ip4n)
Matus Fabian7f8a8db2018-11-22 00:12:15 -08006318 self.assertEqual(users[0].nsessions, 1)
Matus Fabian15e8e682018-11-21 04:53:10 -08006319
Paul Vinciguerradefde0f2018-12-06 07:46:13 -08006320 @unittest.skipUnless(running_extended_tests, "part of extended tests")
Matus Fabian878c6462018-08-23 00:33:35 -07006321 def test_session_limit_per_user(self):
6322 """ Maximum sessions per user limit """
6323 self.nat44_add_address(self.nat_addr)
6324 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
6325 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
6326 is_inside=0)
6327 self.vapi.set_ipfix_exporter(collector_address=self.pg2.remote_ip4n,
6328 src_address=self.pg2.local_ip4n,
6329 path_mtu=512,
6330 template_interval=10)
Matus Fabian8fdc0152018-09-24 04:41:28 -07006331 self.vapi.nat_set_timeouts(udp=5)
Matus Fabian878c6462018-08-23 00:33:35 -07006332
6333 # get maximum number of translations per user
6334 nat44_config = self.vapi.nat_show_config()
6335
6336 pkts = []
6337 for port in range(0, nat44_config.max_translations_per_user):
6338 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6339 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6340 UDP(sport=1025 + port, dport=1025 + port))
6341 pkts.append(p)
6342
6343 self.pg0.add_stream(pkts)
6344 self.pg_enable_capture(self.pg_interfaces)
6345 self.pg_start()
6346 capture = self.pg1.get_capture(len(pkts))
6347
Ole Troane1ade682019-03-04 23:55:43 +01006348 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
6349 src_port=self.ipfix_src_port)
Matus Fabian878c6462018-08-23 00:33:35 -07006350
6351 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6352 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6353 UDP(sport=3001, dport=3002))
6354 self.pg0.add_stream(p)
6355 self.pg_enable_capture(self.pg_interfaces)
6356 self.pg_start()
6357 capture = self.pg1.assert_nothing_captured()
6358
6359 # verify IPFIX logging
6360 self.vapi.cli("ipfix flush") # FIXME this should be an API call
6361 sleep(1)
6362 capture = self.pg2.get_capture(10)
6363 ipfix = IPFIXDecoder()
6364 # first load template
6365 for p in capture:
6366 self.assertTrue(p.haslayer(IPFIX))
6367 if p.haslayer(Template):
6368 ipfix.add_template(p.getlayer(Template))
6369 # verify events in data set
6370 for p in capture:
6371 if p.haslayer(Data):
6372 data = ipfix.decode_data_set(p.getlayer(Set))
6373 self.verify_ipfix_max_entries_per_user(
6374 data,
6375 nat44_config.max_translations_per_user,
6376 self.pg0.remote_ip4n)
6377
Matus Fabian8fdc0152018-09-24 04:41:28 -07006378 sleep(6)
6379 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6380 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6381 UDP(sport=3001, dport=3002))
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
Matus Fabianad1f3e12018-11-28 21:26:34 -08006387 def test_syslog_sess(self):
6388 """ Test syslog session creation and deletion """
6389 self.vapi.syslog_set_filter(SYSLOG_SEVERITY.INFO)
Ole Troanf159f582019-02-28 20:20:47 +01006390 self.vapi.syslog_set_sender(self.pg2.local_ip4n, self.pg2.remote_ip4n)
Matus Fabianad1f3e12018-11-28 21:26:34 -08006391 self.nat44_add_address(self.nat_addr)
6392 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
6393 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
6394 is_inside=0)
6395
6396 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6397 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6398 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port))
6399 self.pg0.add_stream(p)
6400 self.pg_enable_capture(self.pg_interfaces)
6401 self.pg_start()
6402 capture = self.pg1.get_capture(1)
6403 self.tcp_port_out = capture[0][TCP].sport
6404 capture = self.pg2.get_capture(1)
6405 self.verify_syslog_sess(capture[0][Raw].load)
6406
6407 self.pg_enable_capture(self.pg_interfaces)
6408 self.pg_start()
6409 self.nat44_add_address(self.nat_addr, is_add=0)
6410 capture = self.pg2.get_capture(1)
6411 self.verify_syslog_sess(capture[0][Raw].load, False)
6412
Matus Fabiande886752016-12-07 03:38:19 -08006413 def tearDown(self):
Matus Fabiana6110b62018-06-13 05:39:07 -07006414 super(TestNAT44EndpointDependent, self).tearDown()
Matus Fabiande886752016-12-07 03:38:19 -08006415 if not self.vpp_dead:
Matus Fabian82119542018-01-25 01:13:22 -08006416 self.logger.info(self.vapi.cli("show nat44 addresses"))
6417 self.logger.info(self.vapi.cli("show nat44 interfaces"))
6418 self.logger.info(self.vapi.cli("show nat44 static mappings"))
6419 self.logger.info(self.vapi.cli("show nat44 interface address"))
6420 self.logger.info(self.vapi.cli("show nat44 sessions detail"))
Matus Fabian229c1aa2018-05-28 04:09:52 -07006421 self.logger.info(self.vapi.cli("show nat44 hash tables detail"))
Matus Fabian878c6462018-08-23 00:33:35 -07006422 self.logger.info(self.vapi.cli("show nat timeouts"))
Matus Fabian2ba92e32017-08-21 07:05:03 -07006423 self.clear_nat44()
Matus Fabian229c1aa2018-05-28 04:09:52 -07006424 self.vapi.cli("clear logging")
Matus Fabiande886752016-12-07 03:38:19 -08006425
Matus Fabianeea28d72017-01-13 04:15:54 -08006426
Juraj Slobodacba69362017-12-19 02:09:32 +01006427class TestNAT44Out2InDPO(MethodHolder):
6428 """ NAT44 Test Cases using out2in DPO """
6429
6430 @classmethod
6431 def setUpConstants(cls):
6432 super(TestNAT44Out2InDPO, cls).setUpConstants()
6433 cls.vpp_cmdline.extend(["nat", "{", "out2in dpo", "}"])
6434
6435 @classmethod
6436 def setUpClass(cls):
6437 super(TestNAT44Out2InDPO, cls).setUpClass()
Matus Fabian229c1aa2018-05-28 04:09:52 -07006438 cls.vapi.cli("set log class nat level debug")
Juraj Slobodacba69362017-12-19 02:09:32 +01006439
6440 try:
6441 cls.tcp_port_in = 6303
6442 cls.tcp_port_out = 6303
6443 cls.udp_port_in = 6304
6444 cls.udp_port_out = 6304
6445 cls.icmp_id_in = 6305
6446 cls.icmp_id_out = 6305
6447 cls.nat_addr = '10.0.0.3'
6448 cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
6449 cls.dst_ip4 = '192.168.70.1'
6450
6451 cls.create_pg_interfaces(range(2))
6452
6453 cls.pg0.admin_up()
6454 cls.pg0.config_ip4()
6455 cls.pg0.resolve_arp()
6456
6457 cls.pg1.admin_up()
6458 cls.pg1.config_ip6()
6459 cls.pg1.resolve_ndp()
6460
Ole Troan9a475372019-03-05 16:58:24 +01006461 cls.vapi.ip_add_del_route(is_ipv6=True, dst_address='\x00' * 16,
Juraj Slobodacba69362017-12-19 02:09:32 +01006462 dst_address_length=0,
6463 next_hop_address=cls.pg1.remote_ip6n,
6464 next_hop_sw_if_index=cls.pg1.sw_if_index)
6465
6466 except Exception:
6467 super(TestNAT44Out2InDPO, cls).tearDownClass()
6468 raise
6469
6470 def configure_xlat(self):
6471 self.dst_ip6_pfx = '1:2:3::'
6472 self.dst_ip6_pfx_n = socket.inet_pton(socket.AF_INET6,
6473 self.dst_ip6_pfx)
6474 self.dst_ip6_pfx_len = 96
6475 self.src_ip6_pfx = '4:5:6::'
6476 self.src_ip6_pfx_n = socket.inet_pton(socket.AF_INET6,
6477 self.src_ip6_pfx)
6478 self.src_ip6_pfx_len = 96
6479 self.vapi.map_add_domain(self.dst_ip6_pfx_n, self.dst_ip6_pfx_len,
6480 self.src_ip6_pfx_n, self.src_ip6_pfx_len,
Jon Loeligerfc7344f2018-12-20 11:47:30 -06006481 '\x00\x00\x00\x00', 0)
Juraj Slobodacba69362017-12-19 02:09:32 +01006482
Ole Troanffba3c32018-11-22 12:53:00 +01006483 @unittest.skip('Temporary disabled')
Juraj Slobodacba69362017-12-19 02:09:32 +01006484 def test_464xlat_ce(self):
6485 """ Test 464XLAT CE with NAT44 """
6486
Matus Fabian69ce30d2018-08-22 01:27:10 -07006487 nat_config = self.vapi.nat_show_config()
6488 self.assertEqual(1, nat_config.out2in_dpo)
6489
Juraj Slobodacba69362017-12-19 02:09:32 +01006490 self.configure_xlat()
6491
6492 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
6493 self.vapi.nat44_add_del_address_range(self.nat_addr_n, self.nat_addr_n)
6494
6495 out_src_ip6 = self.compose_ip6(self.dst_ip4, self.dst_ip6_pfx,
6496 self.dst_ip6_pfx_len)
6497 out_dst_ip6 = self.compose_ip6(self.nat_addr, self.src_ip6_pfx,
6498 self.src_ip6_pfx_len)
6499
6500 try:
6501 pkts = self.create_stream_in(self.pg0, self.pg1, self.dst_ip4)
6502 self.pg0.add_stream(pkts)
6503 self.pg_enable_capture(self.pg_interfaces)
6504 self.pg_start()
6505 capture = self.pg1.get_capture(len(pkts))
6506 self.verify_capture_out_ip6(capture, nat_ip=out_dst_ip6,
6507 dst_ip=out_src_ip6)
6508
6509 pkts = self.create_stream_out_ip6(self.pg1, out_src_ip6,
6510 out_dst_ip6)
6511 self.pg1.add_stream(pkts)
6512 self.pg_enable_capture(self.pg_interfaces)
6513 self.pg_start()
6514 capture = self.pg0.get_capture(len(pkts))
6515 self.verify_capture_in(capture, self.pg0)
6516 finally:
6517 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
6518 is_add=0)
6519 self.vapi.nat44_add_del_address_range(self.nat_addr_n,
6520 self.nat_addr_n, is_add=0)
6521
Ole Troanffba3c32018-11-22 12:53:00 +01006522 @unittest.skip('Temporary disabled')
Juraj Slobodacba69362017-12-19 02:09:32 +01006523 def test_464xlat_ce_no_nat(self):
6524 """ Test 464XLAT CE without NAT44 """
6525
6526 self.configure_xlat()
6527
6528 out_src_ip6 = self.compose_ip6(self.dst_ip4, self.dst_ip6_pfx,
6529 self.dst_ip6_pfx_len)
6530 out_dst_ip6 = self.compose_ip6(self.pg0.remote_ip4, self.src_ip6_pfx,
6531 self.src_ip6_pfx_len)
6532
6533 pkts = self.create_stream_in(self.pg0, self.pg1, self.dst_ip4)
6534 self.pg0.add_stream(pkts)
6535 self.pg_enable_capture(self.pg_interfaces)
6536 self.pg_start()
6537 capture = self.pg1.get_capture(len(pkts))
6538 self.verify_capture_out_ip6(capture, dst_ip=out_src_ip6,
6539 nat_ip=out_dst_ip6, same_port=True)
6540
6541 pkts = self.create_stream_out_ip6(self.pg1, out_src_ip6, out_dst_ip6)
6542 self.pg1.add_stream(pkts)
6543 self.pg_enable_capture(self.pg_interfaces)
6544 self.pg_start()
6545 capture = self.pg0.get_capture(len(pkts))
6546 self.verify_capture_in(capture, self.pg0)
6547
6548
Martin Gálikd7f75cd2017-03-27 06:02:47 -07006549class TestDeterministicNAT(MethodHolder):
Matus Fabian066f0342017-02-10 03:48:01 -08006550 """ Deterministic NAT Test Cases """
6551
6552 @classmethod
6553 def setUpConstants(cls):
6554 super(TestDeterministicNAT, cls).setUpConstants()
Matus Fabian2ba92e32017-08-21 07:05:03 -07006555 cls.vpp_cmdline.extend(["nat", "{", "deterministic", "}"])
Matus Fabian066f0342017-02-10 03:48:01 -08006556
6557 @classmethod
6558 def setUpClass(cls):
6559 super(TestDeterministicNAT, cls).setUpClass()
Matus Fabian229c1aa2018-05-28 04:09:52 -07006560 cls.vapi.cli("set log class nat level debug")
Matus Fabian066f0342017-02-10 03:48:01 -08006561
6562 try:
Martin Gálik977c1cb2017-03-30 23:21:51 -07006563 cls.tcp_port_in = 6303
Martin Gálik9806eae2017-04-25 01:25:08 -07006564 cls.tcp_external_port = 6303
Martin Gálik977c1cb2017-03-30 23:21:51 -07006565 cls.udp_port_in = 6304
Martin Gálik9806eae2017-04-25 01:25:08 -07006566 cls.udp_external_port = 6304
Martin Gálik977c1cb2017-03-30 23:21:51 -07006567 cls.icmp_id_in = 6305
Matus Fabian2ba92e32017-08-21 07:05:03 -07006568 cls.nat_addr = '10.0.0.3'
Martin Gálik977c1cb2017-03-30 23:21:51 -07006569
Matus Fabian2f2db1c2017-04-18 05:29:59 -07006570 cls.create_pg_interfaces(range(3))
Matus Fabian066f0342017-02-10 03:48:01 -08006571 cls.interfaces = list(cls.pg_interfaces)
6572
6573 for i in cls.interfaces:
6574 i.admin_up()
6575 i.config_ip4()
6576 i.resolve_arp()
6577
Martin Gálik977c1cb2017-03-30 23:21:51 -07006578 cls.pg0.generate_remote_hosts(2)
6579 cls.pg0.configure_ipv4_neighbors()
6580
Matus Fabian066f0342017-02-10 03:48:01 -08006581 except Exception:
6582 super(TestDeterministicNAT, cls).tearDownClass()
6583 raise
6584
Martin Gálik977c1cb2017-03-30 23:21:51 -07006585 def create_stream_in(self, in_if, out_if, ttl=64):
6586 """
6587 Create packet stream for inside network
6588
6589 :param in_if: Inside interface
6590 :param out_if: Outside interface
6591 :param ttl: TTL of generated packets
6592 """
6593 pkts = []
6594 # TCP
6595 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
6596 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006597 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07006598 pkts.append(p)
6599
6600 # UDP
6601 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
6602 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006603 UDP(sport=self.udp_port_in, dport=self.udp_external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07006604 pkts.append(p)
6605
6606 # ICMP
6607 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
6608 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
6609 ICMP(id=self.icmp_id_in, type='echo-request'))
6610 pkts.append(p)
6611
6612 return pkts
6613
6614 def create_stream_out(self, out_if, dst_ip=None, ttl=64):
6615 """
6616 Create packet stream for outside network
6617
6618 :param out_if: Outside interface
Matus Fabian2ba92e32017-08-21 07:05:03 -07006619 :param dst_ip: Destination IP address (Default use global NAT address)
Martin Gálik977c1cb2017-03-30 23:21:51 -07006620 :param ttl: TTL of generated packets
6621 """
6622 if dst_ip is None:
Matus Fabian2ba92e32017-08-21 07:05:03 -07006623 dst_ip = self.nat_addr
Martin Gálik977c1cb2017-03-30 23:21:51 -07006624 pkts = []
6625 # TCP
6626 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
6627 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006628 TCP(dport=self.tcp_port_out, sport=self.tcp_external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07006629 pkts.append(p)
6630
6631 # UDP
6632 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
6633 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006634 UDP(dport=self.udp_port_out, sport=self.udp_external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07006635 pkts.append(p)
6636
6637 # ICMP
6638 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
6639 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
6640 ICMP(id=self.icmp_external_id, type='echo-reply'))
6641 pkts.append(p)
6642
6643 return pkts
6644
Matus Fabian05ca4a32018-09-04 23:45:13 -07006645 def verify_capture_out(self, capture, nat_ip=None):
Martin Gálik977c1cb2017-03-30 23:21:51 -07006646 """
6647 Verify captured packets on outside network
6648
6649 :param capture: Captured packets
Matus Fabian2ba92e32017-08-21 07:05:03 -07006650 :param nat_ip: Translated IP address (Default use global NAT address)
Martin Gálik977c1cb2017-03-30 23:21:51 -07006651 :param same_port: Sorce port number is not translated (Default False)
Martin Gálik977c1cb2017-03-30 23:21:51 -07006652 """
6653 if nat_ip is None:
Matus Fabian2ba92e32017-08-21 07:05:03 -07006654 nat_ip = self.nat_addr
Martin Gálik977c1cb2017-03-30 23:21:51 -07006655 for packet in capture:
6656 try:
6657 self.assertEqual(packet[IP].src, nat_ip)
6658 if packet.haslayer(TCP):
Martin Gálik9806eae2017-04-25 01:25:08 -07006659 self.tcp_port_out = packet[TCP].sport
Martin Gálik977c1cb2017-03-30 23:21:51 -07006660 elif packet.haslayer(UDP):
Martin Gálik9806eae2017-04-25 01:25:08 -07006661 self.udp_port_out = packet[UDP].sport
Martin Gálik977c1cb2017-03-30 23:21:51 -07006662 else:
6663 self.icmp_external_id = packet[ICMP].id
6664 except:
6665 self.logger.error(ppp("Unexpected or invalid packet "
6666 "(outside network):", packet))
6667 raise
6668
Matus Fabian066f0342017-02-10 03:48:01 -08006669 def test_deterministic_mode(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07006670 """ NAT plugin run deterministic mode """
Matus Fabian066f0342017-02-10 03:48:01 -08006671 in_addr = '172.16.255.0'
6672 out_addr = '172.17.255.50'
6673 in_addr_t = '172.16.255.20'
6674 in_addr_n = socket.inet_aton(in_addr)
6675 out_addr_n = socket.inet_aton(out_addr)
6676 in_addr_t_n = socket.inet_aton(in_addr_t)
6677 in_plen = 24
6678 out_plen = 32
6679
Matus Fabian2ba92e32017-08-21 07:05:03 -07006680 nat_config = self.vapi.nat_show_config()
6681 self.assertEqual(1, nat_config.deterministic)
Matus Fabian066f0342017-02-10 03:48:01 -08006682
Matus Fabian2ba92e32017-08-21 07:05:03 -07006683 self.vapi.nat_det_add_del_map(in_addr_n, in_plen, out_addr_n, out_plen)
Matus Fabian066f0342017-02-10 03:48:01 -08006684
Matus Fabian2ba92e32017-08-21 07:05:03 -07006685 rep1 = self.vapi.nat_det_forward(in_addr_t_n)
Matus Fabian066f0342017-02-10 03:48:01 -08006686 self.assertEqual(rep1.out_addr[:4], out_addr_n)
Matus Fabian2ba92e32017-08-21 07:05:03 -07006687 rep2 = self.vapi.nat_det_reverse(out_addr_n, rep1.out_port_hi)
Matus Fabian066f0342017-02-10 03:48:01 -08006688 self.assertEqual(rep2.in_addr[:4], in_addr_t_n)
6689
Matus Fabian2ba92e32017-08-21 07:05:03 -07006690 deterministic_mappings = self.vapi.nat_det_map_dump()
Martin17a75cb2017-03-08 05:53:20 -08006691 self.assertEqual(len(deterministic_mappings), 1)
6692 dsm = deterministic_mappings[0]
6693 self.assertEqual(in_addr_n, dsm.in_addr[:4])
6694 self.assertEqual(in_plen, dsm.in_plen)
6695 self.assertEqual(out_addr_n, dsm.out_addr[:4])
6696 self.assertEqual(out_plen, dsm.out_plen)
6697
Matus Fabian2ba92e32017-08-21 07:05:03 -07006698 self.clear_nat_det()
6699 deterministic_mappings = self.vapi.nat_det_map_dump()
Martinb616e9f2017-03-14 02:25:45 -07006700 self.assertEqual(len(deterministic_mappings), 0)
6701
Matus Fabian6a0946f2017-04-12 03:36:13 -07006702 def test_set_timeouts(self):
6703 """ Set deterministic NAT timeouts """
Matus Fabian878c6462018-08-23 00:33:35 -07006704 timeouts_before = self.vapi.nat_get_timeouts()
Matus Fabian6a0946f2017-04-12 03:36:13 -07006705
Matus Fabian878c6462018-08-23 00:33:35 -07006706 self.vapi.nat_set_timeouts(timeouts_before.udp + 10,
6707 timeouts_before.tcp_established + 10,
6708 timeouts_before.tcp_transitory + 10,
6709 timeouts_before.icmp + 10)
Matus Fabian6a0946f2017-04-12 03:36:13 -07006710
Matus Fabian878c6462018-08-23 00:33:35 -07006711 timeouts_after = self.vapi.nat_get_timeouts()
Matus Fabian6a0946f2017-04-12 03:36:13 -07006712
6713 self.assertNotEqual(timeouts_before.udp, timeouts_after.udp)
6714 self.assertNotEqual(timeouts_before.icmp, timeouts_after.icmp)
6715 self.assertNotEqual(timeouts_before.tcp_established,
6716 timeouts_after.tcp_established)
6717 self.assertNotEqual(timeouts_before.tcp_transitory,
6718 timeouts_after.tcp_transitory)
6719
Martin Gálik977c1cb2017-03-30 23:21:51 -07006720 def test_det_in(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07006721 """ Deterministic NAT translation test (TCP, UDP, ICMP) """
Martin Gálik977c1cb2017-03-30 23:21:51 -07006722
6723 nat_ip = "10.0.0.10"
Martin Gálik977c1cb2017-03-30 23:21:51 -07006724
Matus Fabian2ba92e32017-08-21 07:05:03 -07006725 self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
6726 32,
6727 socket.inet_aton(nat_ip),
6728 32)
6729 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
6730 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
6731 is_inside=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07006732
6733 # in2out
6734 pkts = self.create_stream_in(self.pg0, self.pg1)
6735 self.pg0.add_stream(pkts)
6736 self.pg_enable_capture(self.pg_interfaces)
6737 self.pg_start()
6738 capture = self.pg1.get_capture(len(pkts))
6739 self.verify_capture_out(capture, nat_ip)
6740
6741 # out2in
6742 pkts = self.create_stream_out(self.pg1, nat_ip)
6743 self.pg1.add_stream(pkts)
6744 self.pg_enable_capture(self.pg_interfaces)
6745 self.pg_start()
6746 capture = self.pg0.get_capture(len(pkts))
6747 self.verify_capture_in(capture, self.pg0)
6748
Martin Gálik9806eae2017-04-25 01:25:08 -07006749 # session dump test
Matus Fabian2ba92e32017-08-21 07:05:03 -07006750 sessions = self.vapi.nat_det_session_dump(self.pg0.remote_ip4n)
Martin Gálik9806eae2017-04-25 01:25:08 -07006751 self.assertEqual(len(sessions), 3)
6752
6753 # TCP session
6754 s = sessions[0]
6755 self.assertEqual(s.ext_addr[:4], self.pg1.remote_ip4n)
6756 self.assertEqual(s.in_port, self.tcp_port_in)
6757 self.assertEqual(s.out_port, self.tcp_port_out)
6758 self.assertEqual(s.ext_port, self.tcp_external_port)
6759
6760 # UDP session
6761 s = sessions[1]
6762 self.assertEqual(s.ext_addr[:4], self.pg1.remote_ip4n)
6763 self.assertEqual(s.in_port, self.udp_port_in)
6764 self.assertEqual(s.out_port, self.udp_port_out)
6765 self.assertEqual(s.ext_port, self.udp_external_port)
6766
6767 # ICMP session
6768 s = sessions[2]
6769 self.assertEqual(s.ext_addr[:4], self.pg1.remote_ip4n)
6770 self.assertEqual(s.in_port, self.icmp_id_in)
6771 self.assertEqual(s.out_port, self.icmp_external_id)
6772
Martin Gálik977c1cb2017-03-30 23:21:51 -07006773 def test_multiple_users(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07006774 """ Deterministic NAT multiple users """
Martin Gálik977c1cb2017-03-30 23:21:51 -07006775
6776 nat_ip = "10.0.0.10"
6777 port_in = 80
Martin Gálik9806eae2017-04-25 01:25:08 -07006778 external_port = 6303
Martin Gálik977c1cb2017-03-30 23:21:51 -07006779
6780 host0 = self.pg0.remote_hosts[0]
6781 host1 = self.pg0.remote_hosts[1]
6782
Matus Fabian2ba92e32017-08-21 07:05:03 -07006783 self.vapi.nat_det_add_del_map(host0.ip4n,
6784 24,
6785 socket.inet_aton(nat_ip),
6786 32)
6787 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
6788 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
6789 is_inside=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07006790
6791 # host0 to out
6792 p = (Ether(src=host0.mac, dst=self.pg0.local_mac) /
6793 IP(src=host0.ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006794 TCP(sport=port_in, dport=external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07006795 self.pg0.add_stream(p)
6796 self.pg_enable_capture(self.pg_interfaces)
6797 self.pg_start()
6798 capture = self.pg1.get_capture(1)
6799 p = capture[0]
6800 try:
6801 ip = p[IP]
6802 tcp = p[TCP]
6803 self.assertEqual(ip.src, nat_ip)
6804 self.assertEqual(ip.dst, self.pg1.remote_ip4)
Martin Gálik9806eae2017-04-25 01:25:08 -07006805 self.assertEqual(tcp.dport, external_port)
6806 port_out0 = tcp.sport
Martin Gálik977c1cb2017-03-30 23:21:51 -07006807 except:
6808 self.logger.error(ppp("Unexpected or invalid packet:", p))
6809 raise
6810
6811 # host1 to out
6812 p = (Ether(src=host1.mac, dst=self.pg0.local_mac) /
6813 IP(src=host1.ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006814 TCP(sport=port_in, dport=external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07006815 self.pg0.add_stream(p)
6816 self.pg_enable_capture(self.pg_interfaces)
6817 self.pg_start()
6818 capture = self.pg1.get_capture(1)
6819 p = capture[0]
6820 try:
6821 ip = p[IP]
6822 tcp = p[TCP]
6823 self.assertEqual(ip.src, nat_ip)
6824 self.assertEqual(ip.dst, self.pg1.remote_ip4)
Martin Gálik9806eae2017-04-25 01:25:08 -07006825 self.assertEqual(tcp.dport, external_port)
6826 port_out1 = tcp.sport
Martin Gálik977c1cb2017-03-30 23:21:51 -07006827 except:
6828 self.logger.error(ppp("Unexpected or invalid packet:", p))
6829 raise
6830
Matus Fabian2ba92e32017-08-21 07:05:03 -07006831 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07006832 self.assertEqual(1, len(dms))
6833 self.assertEqual(2, dms[0].ses_num)
6834
6835 # out to host0
6836 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6837 IP(src=self.pg1.remote_ip4, dst=nat_ip) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006838 TCP(sport=external_port, dport=port_out0))
Martin Gálik977c1cb2017-03-30 23:21:51 -07006839 self.pg1.add_stream(p)
6840 self.pg_enable_capture(self.pg_interfaces)
6841 self.pg_start()
6842 capture = self.pg0.get_capture(1)
6843 p = capture[0]
6844 try:
6845 ip = p[IP]
6846 tcp = p[TCP]
6847 self.assertEqual(ip.src, self.pg1.remote_ip4)
6848 self.assertEqual(ip.dst, host0.ip4)
6849 self.assertEqual(tcp.dport, port_in)
Martin Gálik9806eae2017-04-25 01:25:08 -07006850 self.assertEqual(tcp.sport, external_port)
Martin Gálik977c1cb2017-03-30 23:21:51 -07006851 except:
6852 self.logger.error(ppp("Unexpected or invalid packet:", p))
6853 raise
6854
6855 # out to host1
6856 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6857 IP(src=self.pg1.remote_ip4, dst=nat_ip) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006858 TCP(sport=external_port, dport=port_out1))
Martin Gálik977c1cb2017-03-30 23:21:51 -07006859 self.pg1.add_stream(p)
6860 self.pg_enable_capture(self.pg_interfaces)
6861 self.pg_start()
6862 capture = self.pg0.get_capture(1)
6863 p = capture[0]
6864 try:
6865 ip = p[IP]
6866 tcp = p[TCP]
6867 self.assertEqual(ip.src, self.pg1.remote_ip4)
6868 self.assertEqual(ip.dst, host1.ip4)
6869 self.assertEqual(tcp.dport, port_in)
Martin Gálik9806eae2017-04-25 01:25:08 -07006870 self.assertEqual(tcp.sport, external_port)
Martin Gálik977c1cb2017-03-30 23:21:51 -07006871 except:
6872 self.logger.error(ppp("Unexpected or invalid packet", p))
6873 raise
6874
Martin Gálik6bc8c642017-04-19 01:12:27 -07006875 # session close api test
Matus Fabian2ba92e32017-08-21 07:05:03 -07006876 self.vapi.nat_det_close_session_out(socket.inet_aton(nat_ip),
6877 port_out1,
Martin Gálik6bc8c642017-04-19 01:12:27 -07006878 self.pg1.remote_ip4n,
Martin Gálik9806eae2017-04-25 01:25:08 -07006879 external_port)
Matus Fabian2ba92e32017-08-21 07:05:03 -07006880 dms = self.vapi.nat_det_map_dump()
6881 self.assertEqual(dms[0].ses_num, 1)
6882
6883 self.vapi.nat_det_close_session_in(host0.ip4n,
6884 port_in,
6885 self.pg1.remote_ip4n,
6886 external_port)
6887 dms = self.vapi.nat_det_map_dump()
Martin Gálik6bc8c642017-04-19 01:12:27 -07006888 self.assertEqual(dms[0].ses_num, 0)
6889
Martin Gálik977c1cb2017-03-30 23:21:51 -07006890 def test_tcp_session_close_detection_in(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07006891 """ Deterministic NAT TCP session close from inside network """
6892 self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
6893 32,
6894 socket.inet_aton(self.nat_addr),
6895 32)
6896 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
6897 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
6898 is_inside=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07006899
6900 self.initiate_tcp_session(self.pg0, self.pg1)
6901
6902 # close the session from inside
6903 try:
6904 # FIN packet in -> out
6905 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6906 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006907 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
Martin Gálik977c1cb2017-03-30 23:21:51 -07006908 flags="F"))
6909 self.pg0.add_stream(p)
6910 self.pg_enable_capture(self.pg_interfaces)
6911 self.pg_start()
6912 self.pg1.get_capture(1)
6913
6914 pkts = []
6915
6916 # ACK packet out -> in
6917 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07006918 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006919 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
Martin Gálik977c1cb2017-03-30 23:21:51 -07006920 flags="A"))
6921 pkts.append(p)
6922
6923 # FIN packet out -> in
6924 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07006925 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006926 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
Martin Gálik977c1cb2017-03-30 23:21:51 -07006927 flags="F"))
6928 pkts.append(p)
6929
6930 self.pg1.add_stream(pkts)
6931 self.pg_enable_capture(self.pg_interfaces)
6932 self.pg_start()
6933 self.pg0.get_capture(2)
6934
6935 # ACK packet in -> out
6936 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6937 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006938 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
Martin Gálik977c1cb2017-03-30 23:21:51 -07006939 flags="A"))
6940 self.pg0.add_stream(p)
6941 self.pg_enable_capture(self.pg_interfaces)
6942 self.pg_start()
6943 self.pg1.get_capture(1)
6944
Matus Fabian2ba92e32017-08-21 07:05:03 -07006945 # Check if deterministic NAT44 closed the session
6946 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07006947 self.assertEqual(0, dms[0].ses_num)
6948 except:
6949 self.logger.error("TCP session termination failed")
6950 raise
6951
6952 def test_tcp_session_close_detection_out(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07006953 """ Deterministic NAT TCP session close from outside network """
6954 self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
6955 32,
6956 socket.inet_aton(self.nat_addr),
6957 32)
6958 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
6959 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
6960 is_inside=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07006961
6962 self.initiate_tcp_session(self.pg0, self.pg1)
6963
6964 # close the session from outside
6965 try:
6966 # FIN packet out -> in
6967 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07006968 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006969 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
Martin Gálik977c1cb2017-03-30 23:21:51 -07006970 flags="F"))
6971 self.pg1.add_stream(p)
6972 self.pg_enable_capture(self.pg_interfaces)
6973 self.pg_start()
6974 self.pg0.get_capture(1)
6975
6976 pkts = []
6977
6978 # ACK packet in -> out
6979 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6980 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006981 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
Martin Gálik977c1cb2017-03-30 23:21:51 -07006982 flags="A"))
6983 pkts.append(p)
6984
6985 # ACK packet in -> out
6986 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6987 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006988 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
Martin Gálik977c1cb2017-03-30 23:21:51 -07006989 flags="F"))
6990 pkts.append(p)
6991
6992 self.pg0.add_stream(pkts)
6993 self.pg_enable_capture(self.pg_interfaces)
6994 self.pg_start()
6995 self.pg1.get_capture(2)
6996
6997 # ACK packet out -> in
6998 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07006999 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Martin Gálik9806eae2017-04-25 01:25:08 -07007000 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
Martin Gálik977c1cb2017-03-30 23:21:51 -07007001 flags="A"))
7002 self.pg1.add_stream(p)
7003 self.pg_enable_capture(self.pg_interfaces)
7004 self.pg_start()
7005 self.pg0.get_capture(1)
7006
Matus Fabian2ba92e32017-08-21 07:05:03 -07007007 # Check if deterministic NAT44 closed the session
7008 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07007009 self.assertEqual(0, dms[0].ses_num)
7010 except:
7011 self.logger.error("TCP session termination failed")
7012 raise
7013
Paul Vinciguerradefde0f2018-12-06 07:46:13 -08007014 @unittest.skipUnless(running_extended_tests, "part of extended tests")
Martin Gálik977c1cb2017-03-30 23:21:51 -07007015 def test_session_timeout(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07007016 """ Deterministic NAT session timeouts """
7017 self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
7018 32,
7019 socket.inet_aton(self.nat_addr),
7020 32)
7021 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
7022 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
7023 is_inside=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07007024
7025 self.initiate_tcp_session(self.pg0, self.pg1)
Matus Fabian878c6462018-08-23 00:33:35 -07007026 self.vapi.nat_set_timeouts(5, 5, 5, 5)
Martin Gálik977c1cb2017-03-30 23:21:51 -07007027 pkts = self.create_stream_in(self.pg0, self.pg1)
7028 self.pg0.add_stream(pkts)
7029 self.pg_enable_capture(self.pg_interfaces)
7030 self.pg_start()
7031 capture = self.pg1.get_capture(len(pkts))
7032 sleep(15)
7033
Matus Fabian2ba92e32017-08-21 07:05:03 -07007034 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07007035 self.assertEqual(0, dms[0].ses_num)
7036
Paul Vinciguerradefde0f2018-12-06 07:46:13 -08007037 @unittest.skipUnless(running_extended_tests, "part of extended tests")
Martin Gálik977c1cb2017-03-30 23:21:51 -07007038 def test_session_limit_per_user(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07007039 """ Deterministic NAT maximum sessions per user limit """
7040 self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
7041 32,
7042 socket.inet_aton(self.nat_addr),
7043 32)
7044 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
7045 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
7046 is_inside=0)
Matus Fabian2f2db1c2017-04-18 05:29:59 -07007047 self.vapi.set_ipfix_exporter(collector_address=self.pg2.remote_ip4n,
7048 src_address=self.pg2.local_ip4n,
7049 path_mtu=512,
7050 template_interval=10)
Ole Troane1ade682019-03-04 23:55:43 +01007051 self.vapi.nat_ipfix_enable_disable()
Martin Gálik977c1cb2017-03-30 23:21:51 -07007052
7053 pkts = []
7054 for port in range(1025, 2025):
7055 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7056 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
7057 UDP(sport=port, dport=port))
7058 pkts.append(p)
7059
7060 self.pg0.add_stream(pkts)
7061 self.pg_enable_capture(self.pg_interfaces)
7062 self.pg_start()
7063 capture = self.pg1.get_capture(len(pkts))
7064
7065 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7066 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálikf7e655d2017-04-27 02:13:26 -07007067 UDP(sport=3001, dport=3002))
Martin Gálik977c1cb2017-03-30 23:21:51 -07007068 self.pg0.add_stream(p)
7069 self.pg_enable_capture(self.pg_interfaces)
7070 self.pg_start()
7071 capture = self.pg1.assert_nothing_captured()
7072
Martin Gálikf7e655d2017-04-27 02:13:26 -07007073 # verify ICMP error packet
7074 capture = self.pg0.get_capture(1)
7075 p = capture[0]
7076 self.assertTrue(p.haslayer(ICMP))
7077 icmp = p[ICMP]
7078 self.assertEqual(icmp.type, 3)
7079 self.assertEqual(icmp.code, 1)
7080 self.assertTrue(icmp.haslayer(IPerror))
7081 inner_ip = icmp[IPerror]
7082 self.assertEqual(inner_ip[UDPerror].sport, 3001)
7083 self.assertEqual(inner_ip[UDPerror].dport, 3002)
7084
Matus Fabian2ba92e32017-08-21 07:05:03 -07007085 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07007086
7087 self.assertEqual(1000, dms[0].ses_num)
7088
Matus Fabian2f2db1c2017-04-18 05:29:59 -07007089 # verify IPFIX logging
7090 self.vapi.cli("ipfix flush") # FIXME this should be an API call
Matus Fabian7c0aecc2017-07-03 01:21:38 -07007091 sleep(1)
Matus Fabian2f2db1c2017-04-18 05:29:59 -07007092 capture = self.pg2.get_capture(2)
7093 ipfix = IPFIXDecoder()
7094 # first load template
7095 for p in capture:
7096 self.assertTrue(p.haslayer(IPFIX))
7097 if p.haslayer(Template):
7098 ipfix.add_template(p.getlayer(Template))
7099 # verify events in data set
7100 for p in capture:
7101 if p.haslayer(Data):
7102 data = ipfix.decode_data_set(p.getlayer(Set))
Matus Fabian878c6462018-08-23 00:33:35 -07007103 self.verify_ipfix_max_entries_per_user(data,
7104 1000,
7105 self.pg0.remote_ip4n)
Matus Fabian2f2db1c2017-04-18 05:29:59 -07007106
Matus Fabian2ba92e32017-08-21 07:05:03 -07007107 def clear_nat_det(self):
Martin17a75cb2017-03-08 05:53:20 -08007108 """
Matus Fabian2ba92e32017-08-21 07:05:03 -07007109 Clear deterministic NAT configuration.
Martin17a75cb2017-03-08 05:53:20 -08007110 """
Ole Troane1ade682019-03-04 23:55:43 +01007111 self.vapi.nat_ipfix_enable_disable(enable=0)
Matus Fabian878c6462018-08-23 00:33:35 -07007112 self.vapi.nat_set_timeouts()
Matus Fabian2ba92e32017-08-21 07:05:03 -07007113 deterministic_mappings = self.vapi.nat_det_map_dump()
Martin17a75cb2017-03-08 05:53:20 -08007114 for dsm in deterministic_mappings:
Matus Fabian2ba92e32017-08-21 07:05:03 -07007115 self.vapi.nat_det_add_del_map(dsm.in_addr,
7116 dsm.in_plen,
7117 dsm.out_addr,
7118 dsm.out_plen,
7119 is_add=0)
Martin17a75cb2017-03-08 05:53:20 -08007120
Matus Fabian2ba92e32017-08-21 07:05:03 -07007121 interfaces = self.vapi.nat44_interface_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07007122 for intf in interfaces:
Matus Fabian2ba92e32017-08-21 07:05:03 -07007123 self.vapi.nat44_interface_add_del_feature(intf.sw_if_index,
7124 intf.is_inside,
7125 is_add=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07007126
Matus Fabian066f0342017-02-10 03:48:01 -08007127 def tearDown(self):
7128 super(TestDeterministicNAT, self).tearDown()
7129 if not self.vpp_dead:
Matus Fabian82119542018-01-25 01:13:22 -08007130 self.logger.info(self.vapi.cli("show nat44 interfaces"))
Matus Fabian878c6462018-08-23 00:33:35 -07007131 self.logger.info(self.vapi.cli("show nat timeouts"))
Matus Fabian82119542018-01-25 01:13:22 -08007132 self.logger.info(
7133 self.vapi.cli("show nat44 deterministic mappings"))
7134 self.logger.info(
Matus Fabian82119542018-01-25 01:13:22 -08007135 self.vapi.cli("show nat44 deterministic sessions"))
Matus Fabian2ba92e32017-08-21 07:05:03 -07007136 self.clear_nat_det()
Matus Fabian066f0342017-02-10 03:48:01 -08007137
Matus Fabian06596c52017-06-06 04:53:28 -07007138
7139class TestNAT64(MethodHolder):
7140 """ NAT64 Test Cases """
7141
7142 @classmethod
Matus Fabiana431ad12018-01-04 04:03:14 -08007143 def setUpConstants(cls):
7144 super(TestNAT64, cls).setUpConstants()
7145 cls.vpp_cmdline.extend(["nat", "{", "nat64 bib hash buckets 128",
7146 "nat64 st hash buckets 256", "}"])
7147
7148 @classmethod
Matus Fabian06596c52017-06-06 04:53:28 -07007149 def setUpClass(cls):
7150 super(TestNAT64, cls).setUpClass()
7151
7152 try:
7153 cls.tcp_port_in = 6303
7154 cls.tcp_port_out = 6303
7155 cls.udp_port_in = 6304
7156 cls.udp_port_out = 6304
7157 cls.icmp_id_in = 6305
7158 cls.icmp_id_out = 6305
Matus Fabianad1f3e12018-11-28 21:26:34 -08007159 cls.tcp_external_port = 80
Matus Fabian06596c52017-06-06 04:53:28 -07007160 cls.nat_addr = '10.0.0.3'
7161 cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
Matus Fabian029f3d22017-06-15 02:28:50 -07007162 cls.vrf1_id = 10
7163 cls.vrf1_nat_addr = '10.0.10.3'
7164 cls.vrf1_nat_addr_n = socket.inet_pton(socket.AF_INET,
7165 cls.vrf1_nat_addr)
Matus Fabiana431ad12018-01-04 04:03:14 -08007166 cls.ipfix_src_port = 4739
7167 cls.ipfix_domain_id = 1
Matus Fabian06596c52017-06-06 04:53:28 -07007168
Juraj Slobodac746a152018-07-09 02:36:37 +02007169 cls.create_pg_interfaces(range(6))
Matus Fabian06596c52017-06-06 04:53:28 -07007170 cls.ip6_interfaces = list(cls.pg_interfaces[0:1])
Matus Fabian029f3d22017-06-15 02:28:50 -07007171 cls.ip6_interfaces.append(cls.pg_interfaces[2])
Matus Fabian06596c52017-06-06 04:53:28 -07007172 cls.ip4_interfaces = list(cls.pg_interfaces[1:2])
7173
Ole Troan9a475372019-03-05 16:58:24 +01007174 cls.vapi.ip_table_add_del(is_ipv6=1, is_add=1,
7175 table_id=cls.vrf1_id)
Neale Ranns15002542017-09-10 04:39:11 -07007176
Matus Fabian029f3d22017-06-15 02:28:50 -07007177 cls.pg_interfaces[2].set_table_ip6(cls.vrf1_id)
7178
7179 cls.pg0.generate_remote_hosts(2)
7180
Matus Fabian06596c52017-06-06 04:53:28 -07007181 for i in cls.ip6_interfaces:
7182 i.admin_up()
7183 i.config_ip6()
Matus Fabian029f3d22017-06-15 02:28:50 -07007184 i.configure_ipv6_neighbors()
Matus Fabian06596c52017-06-06 04:53:28 -07007185
7186 for i in cls.ip4_interfaces:
7187 i.admin_up()
7188 i.config_ip4()
7189 i.resolve_arp()
7190
Matus Fabian36ea2d62017-10-24 04:13:49 -07007191 cls.pg3.admin_up()
7192 cls.pg3.config_ip4()
7193 cls.pg3.resolve_arp()
7194 cls.pg3.config_ip6()
7195 cls.pg3.configure_ipv6_neighbors()
7196
Juraj Slobodac746a152018-07-09 02:36:37 +02007197 cls.pg5.admin_up()
7198 cls.pg5.config_ip6()
7199
Matus Fabian06596c52017-06-06 04:53:28 -07007200 except Exception:
7201 super(TestNAT64, cls).tearDownClass()
7202 raise
7203
Juraj Slobodac746a152018-07-09 02:36:37 +02007204 def test_nat64_inside_interface_handles_neighbor_advertisement(self):
7205 """ NAT64 inside interface handles Neighbor Advertisement """
7206
7207 self.vapi.nat64_add_del_interface(self.pg5.sw_if_index)
7208
7209 # Try to send ping
7210 ping = (Ether(dst=self.pg5.local_mac, src=self.pg5.remote_mac) /
7211 IPv6(src=self.pg5.remote_ip6, dst=self.pg5.local_ip6) /
7212 ICMPv6EchoRequest())
7213 pkts = [ping]
7214 self.pg5.add_stream(pkts)
7215 self.pg_enable_capture(self.pg_interfaces)
7216 self.pg_start()
7217
7218 # Wait for Neighbor Solicitation
7219 capture = self.pg5.get_capture(len(pkts))
Juraj Slobodac746a152018-07-09 02:36:37 +02007220 packet = capture[0]
7221 try:
7222 self.assertEqual(packet[IPv6].src, self.pg5.local_ip6)
Paul Vinciguerra978aa642018-11-24 22:19:12 -08007223 self.assertEqual(packet.haslayer(ICMPv6ND_NS), 1)
Juraj Slobodac746a152018-07-09 02:36:37 +02007224 tgt = packet[ICMPv6ND_NS].tgt
7225 except:
7226 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7227 raise
7228
7229 # Send Neighbor Advertisement
7230 p = (Ether(dst=self.pg5.local_mac, src=self.pg5.remote_mac) /
7231 IPv6(src=self.pg5.remote_ip6, dst=self.pg5.local_ip6) /
7232 ICMPv6ND_NA(tgt=tgt) /
7233 ICMPv6NDOptDstLLAddr(lladdr=self.pg5.remote_mac))
7234 pkts = [p]
7235 self.pg5.add_stream(pkts)
7236 self.pg_enable_capture(self.pg_interfaces)
7237 self.pg_start()
7238
7239 # Try to send ping again
7240 pkts = [ping]
7241 self.pg5.add_stream(pkts)
7242 self.pg_enable_capture(self.pg_interfaces)
7243 self.pg_start()
7244
7245 # Wait for ping reply
7246 capture = self.pg5.get_capture(len(pkts))
Juraj Slobodac746a152018-07-09 02:36:37 +02007247 packet = capture[0]
7248 try:
7249 self.assertEqual(packet[IPv6].src, self.pg5.local_ip6)
7250 self.assertEqual(packet[IPv6].dst, self.pg5.remote_ip6)
Paul Vinciguerra978aa642018-11-24 22:19:12 -08007251 self.assertEqual(packet.haslayer(ICMPv6EchoReply), 1)
Juraj Slobodac746a152018-07-09 02:36:37 +02007252 except:
7253 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7254 raise
7255
Matus Fabian06596c52017-06-06 04:53:28 -07007256 def test_pool(self):
7257 """ Add/delete address to NAT64 pool """
7258 nat_addr = socket.inet_pton(socket.AF_INET, '1.2.3.4')
7259
7260 self.vapi.nat64_add_del_pool_addr_range(nat_addr, nat_addr)
7261
7262 addresses = self.vapi.nat64_pool_addr_dump()
7263 self.assertEqual(len(addresses), 1)
7264 self.assertEqual(addresses[0].address, nat_addr)
7265
7266 self.vapi.nat64_add_del_pool_addr_range(nat_addr, nat_addr, is_add=0)
7267
7268 addresses = self.vapi.nat64_pool_addr_dump()
7269 self.assertEqual(len(addresses), 0)
7270
7271 def test_interface(self):
7272 """ Enable/disable NAT64 feature on the interface """
7273 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7274 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7275
7276 interfaces = self.vapi.nat64_interface_dump()
7277 self.assertEqual(len(interfaces), 2)
7278 pg0_found = False
7279 pg1_found = False
7280 for intf in interfaces:
7281 if intf.sw_if_index == self.pg0.sw_if_index:
7282 self.assertEqual(intf.is_inside, 1)
7283 pg0_found = True
7284 elif intf.sw_if_index == self.pg1.sw_if_index:
7285 self.assertEqual(intf.is_inside, 0)
7286 pg1_found = True
7287 self.assertTrue(pg0_found)
7288 self.assertTrue(pg1_found)
7289
7290 features = self.vapi.cli("show interface features pg0")
Paul Vinciguerra9a6dafd2019-03-06 15:11:28 -08007291 self.assertIn('nat64-in2out', features)
Matus Fabian06596c52017-06-06 04:53:28 -07007292 features = self.vapi.cli("show interface features pg1")
Paul Vinciguerra9a6dafd2019-03-06 15:11:28 -08007293 self.assertIn('nat64-out2in', features)
Matus Fabian06596c52017-06-06 04:53:28 -07007294
7295 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index, is_add=0)
7296 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_add=0)
7297
7298 interfaces = self.vapi.nat64_interface_dump()
7299 self.assertEqual(len(interfaces), 0)
7300
7301 def test_static_bib(self):
7302 """ Add/delete static BIB entry """
7303 in_addr = socket.inet_pton(socket.AF_INET6,
7304 '2001:db8:85a3::8a2e:370:7334')
7305 out_addr = socket.inet_pton(socket.AF_INET, '10.1.1.3')
7306 in_port = 1234
7307 out_port = 5678
7308 proto = IP_PROTOS.tcp
7309
7310 self.vapi.nat64_add_del_static_bib(in_addr,
7311 out_addr,
7312 in_port,
7313 out_port,
7314 proto)
7315 bib = self.vapi.nat64_bib_dump(IP_PROTOS.tcp)
7316 static_bib_num = 0
7317 for bibe in bib:
7318 if bibe.is_static:
7319 static_bib_num += 1
7320 self.assertEqual(bibe.i_addr, in_addr)
7321 self.assertEqual(bibe.o_addr, out_addr)
7322 self.assertEqual(bibe.i_port, in_port)
7323 self.assertEqual(bibe.o_port, out_port)
7324 self.assertEqual(static_bib_num, 1)
Matus Fabianfd0d5082018-12-18 01:08:51 -08007325 bibs = self.statistics.get_counter('/nat64/total-bibs')
7326 self.assertEqual(bibs[0][0], 1)
Matus Fabian06596c52017-06-06 04:53:28 -07007327
7328 self.vapi.nat64_add_del_static_bib(in_addr,
7329 out_addr,
7330 in_port,
7331 out_port,
7332 proto,
7333 is_add=0)
7334 bib = self.vapi.nat64_bib_dump(IP_PROTOS.tcp)
7335 static_bib_num = 0
7336 for bibe in bib:
7337 if bibe.is_static:
7338 static_bib_num += 1
7339 self.assertEqual(static_bib_num, 0)
Matus Fabianfd0d5082018-12-18 01:08:51 -08007340 bibs = self.statistics.get_counter('/nat64/total-bibs')
7341 self.assertEqual(bibs[0][0], 0)
Matus Fabian06596c52017-06-06 04:53:28 -07007342
7343 def test_set_timeouts(self):
7344 """ Set NAT64 timeouts """
7345 # verify default values
Matus Fabian878c6462018-08-23 00:33:35 -07007346 timeouts = self.vapi.nat_get_timeouts()
Matus Fabian06596c52017-06-06 04:53:28 -07007347 self.assertEqual(timeouts.udp, 300)
7348 self.assertEqual(timeouts.icmp, 60)
Matus Fabian878c6462018-08-23 00:33:35 -07007349 self.assertEqual(timeouts.tcp_transitory, 240)
7350 self.assertEqual(timeouts.tcp_established, 7440)
Matus Fabian06596c52017-06-06 04:53:28 -07007351
7352 # set and verify custom values
Matus Fabian878c6462018-08-23 00:33:35 -07007353 self.vapi.nat_set_timeouts(udp=200, icmp=30, tcp_transitory=250,
7354 tcp_established=7450)
7355 timeouts = self.vapi.nat_get_timeouts()
Matus Fabian06596c52017-06-06 04:53:28 -07007356 self.assertEqual(timeouts.udp, 200)
7357 self.assertEqual(timeouts.icmp, 30)
Matus Fabian878c6462018-08-23 00:33:35 -07007358 self.assertEqual(timeouts.tcp_transitory, 250)
7359 self.assertEqual(timeouts.tcp_established, 7450)
Matus Fabian06596c52017-06-06 04:53:28 -07007360
7361 def test_dynamic(self):
7362 """ NAT64 dynamic translation test """
7363 self.tcp_port_in = 6303
7364 self.udp_port_in = 6304
7365 self.icmp_id_in = 6305
7366
7367 ses_num_start = self.nat64_get_ses_num()
7368
7369 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7370 self.nat_addr_n)
7371 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7372 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7373
7374 # in2out
Matus Fabiana5e73762018-12-14 01:55:16 -08007375 tcpn = self.statistics.get_counter('/err/nat64-in2out/TCP packets')
7376 udpn = self.statistics.get_counter('/err/nat64-in2out/UDP packets')
7377 icmpn = self.statistics.get_counter('/err/nat64-in2out/ICMP packets')
7378 totaln = self.statistics.get_counter(
7379 '/err/nat64-in2out/good in2out packets processed')
7380
Matus Fabian06596c52017-06-06 04:53:28 -07007381 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
7382 self.pg0.add_stream(pkts)
7383 self.pg_enable_capture(self.pg_interfaces)
7384 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07007385 capture = self.pg1.get_capture(len(pkts))
7386 self.verify_capture_out(capture, nat_ip=self.nat_addr,
Matus Fabian06596c52017-06-06 04:53:28 -07007387 dst_ip=self.pg1.remote_ip4)
7388
Matus Fabiana5e73762018-12-14 01:55:16 -08007389 err = self.statistics.get_counter('/err/nat64-in2out/TCP packets')
7390 self.assertEqual(err - tcpn, 1)
7391 err = self.statistics.get_counter('/err/nat64-in2out/UDP packets')
7392 self.assertEqual(err - udpn, 1)
7393 err = self.statistics.get_counter('/err/nat64-in2out/ICMP packets')
7394 self.assertEqual(err - icmpn, 1)
7395 err = self.statistics.get_counter(
7396 '/err/nat64-in2out/good in2out packets processed')
7397 self.assertEqual(err - totaln, 3)
7398
Matus Fabian06596c52017-06-06 04:53:28 -07007399 # out2in
Matus Fabiana5e73762018-12-14 01:55:16 -08007400 tcpn = self.statistics.get_counter('/err/nat64-out2in/TCP packets')
7401 udpn = self.statistics.get_counter('/err/nat64-out2in/UDP packets')
7402 icmpn = self.statistics.get_counter('/err/nat64-out2in/ICMP packets')
7403 totaln = self.statistics.get_counter(
7404 '/err/nat64-out2in/good out2in packets processed')
7405
Matus Fabian06596c52017-06-06 04:53:28 -07007406 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
7407 self.pg1.add_stream(pkts)
7408 self.pg_enable_capture(self.pg_interfaces)
7409 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07007410 capture = self.pg0.get_capture(len(pkts))
Matus Fabian06596c52017-06-06 04:53:28 -07007411 ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
7412 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
7413
Matus Fabiana5e73762018-12-14 01:55:16 -08007414 err = self.statistics.get_counter('/err/nat64-out2in/TCP packets')
7415 self.assertEqual(err - tcpn, 1)
7416 err = self.statistics.get_counter('/err/nat64-out2in/UDP packets')
7417 self.assertEqual(err - udpn, 1)
7418 err = self.statistics.get_counter('/err/nat64-out2in/ICMP packets')
7419 self.assertEqual(err - icmpn, 1)
7420 err = self.statistics.get_counter(
7421 '/err/nat64-out2in/good out2in packets processed')
7422 self.assertEqual(err - totaln, 3)
7423
Matus Fabianfd0d5082018-12-18 01:08:51 -08007424 bibs = self.statistics.get_counter('/nat64/total-bibs')
7425 self.assertEqual(bibs[0][0], 3)
7426 sessions = self.statistics.get_counter('/nat64/total-sessions')
7427 self.assertEqual(sessions[0][0], 3)
7428
Matus Fabian06596c52017-06-06 04:53:28 -07007429 # in2out
7430 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
7431 self.pg0.add_stream(pkts)
7432 self.pg_enable_capture(self.pg_interfaces)
7433 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07007434 capture = self.pg1.get_capture(len(pkts))
7435 self.verify_capture_out(capture, nat_ip=self.nat_addr,
Matus Fabian06596c52017-06-06 04:53:28 -07007436 dst_ip=self.pg1.remote_ip4)
7437
7438 # out2in
7439 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
7440 self.pg1.add_stream(pkts)
7441 self.pg_enable_capture(self.pg_interfaces)
7442 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07007443 capture = self.pg0.get_capture(len(pkts))
Matus Fabian06596c52017-06-06 04:53:28 -07007444 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
7445
7446 ses_num_end = self.nat64_get_ses_num()
7447
7448 self.assertEqual(ses_num_end - ses_num_start, 3)
7449
Matus Fabian029f3d22017-06-15 02:28:50 -07007450 # tenant with specific VRF
7451 self.vapi.nat64_add_del_pool_addr_range(self.vrf1_nat_addr_n,
7452 self.vrf1_nat_addr_n,
7453 vrf_id=self.vrf1_id)
7454 self.vapi.nat64_add_del_interface(self.pg2.sw_if_index)
7455
7456 pkts = self.create_stream_in_ip6(self.pg2, self.pg1)
7457 self.pg2.add_stream(pkts)
7458 self.pg_enable_capture(self.pg_interfaces)
7459 self.pg_start()
7460 capture = self.pg1.get_capture(len(pkts))
7461 self.verify_capture_out(capture, nat_ip=self.vrf1_nat_addr,
7462 dst_ip=self.pg1.remote_ip4)
7463
7464 pkts = self.create_stream_out(self.pg1, dst_ip=self.vrf1_nat_addr)
7465 self.pg1.add_stream(pkts)
7466 self.pg_enable_capture(self.pg_interfaces)
7467 self.pg_start()
7468 capture = self.pg2.get_capture(len(pkts))
7469 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg2.remote_ip6)
7470
Matus Fabian06596c52017-06-06 04:53:28 -07007471 def test_static(self):
7472 """ NAT64 static translation test """
7473 self.tcp_port_in = 60303
7474 self.udp_port_in = 60304
7475 self.icmp_id_in = 60305
7476 self.tcp_port_out = 60303
7477 self.udp_port_out = 60304
7478 self.icmp_id_out = 60305
7479
7480 ses_num_start = self.nat64_get_ses_num()
7481
7482 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7483 self.nat_addr_n)
7484 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7485 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7486
7487 self.vapi.nat64_add_del_static_bib(self.pg0.remote_ip6n,
7488 self.nat_addr_n,
7489 self.tcp_port_in,
7490 self.tcp_port_out,
7491 IP_PROTOS.tcp)
7492 self.vapi.nat64_add_del_static_bib(self.pg0.remote_ip6n,
7493 self.nat_addr_n,
7494 self.udp_port_in,
7495 self.udp_port_out,
7496 IP_PROTOS.udp)
7497 self.vapi.nat64_add_del_static_bib(self.pg0.remote_ip6n,
7498 self.nat_addr_n,
7499 self.icmp_id_in,
7500 self.icmp_id_out,
7501 IP_PROTOS.icmp)
7502
7503 # in2out
7504 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
7505 self.pg0.add_stream(pkts)
7506 self.pg_enable_capture(self.pg_interfaces)
7507 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07007508 capture = self.pg1.get_capture(len(pkts))
7509 self.verify_capture_out(capture, nat_ip=self.nat_addr,
Matus Fabian06596c52017-06-06 04:53:28 -07007510 dst_ip=self.pg1.remote_ip4, same_port=True)
7511
7512 # out2in
7513 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
7514 self.pg1.add_stream(pkts)
7515 self.pg_enable_capture(self.pg_interfaces)
7516 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07007517 capture = self.pg0.get_capture(len(pkts))
Matus Fabian06596c52017-06-06 04:53:28 -07007518 ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
7519 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
7520
7521 ses_num_end = self.nat64_get_ses_num()
7522
7523 self.assertEqual(ses_num_end - ses_num_start, 3)
7524
Paul Vinciguerradefde0f2018-12-06 07:46:13 -08007525 @unittest.skipUnless(running_extended_tests, "part of extended tests")
Matus Fabian06596c52017-06-06 04:53:28 -07007526 def test_session_timeout(self):
7527 """ NAT64 session timeout """
7528 self.icmp_id_in = 1234
7529 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7530 self.nat_addr_n)
7531 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7532 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
Matus Fabian878c6462018-08-23 00:33:35 -07007533 self.vapi.nat_set_timeouts(icmp=5, tcp_transitory=5, tcp_established=5)
Matus Fabian06596c52017-06-06 04:53:28 -07007534
7535 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
7536 self.pg0.add_stream(pkts)
7537 self.pg_enable_capture(self.pg_interfaces)
7538 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07007539 capture = self.pg1.get_capture(len(pkts))
Matus Fabian06596c52017-06-06 04:53:28 -07007540
7541 ses_num_before_timeout = self.nat64_get_ses_num()
7542
7543 sleep(15)
7544
Matus Fabian8fed4242018-08-14 05:14:55 -07007545 # ICMP and TCP session after timeout
Matus Fabian06596c52017-06-06 04:53:28 -07007546 ses_num_after_timeout = self.nat64_get_ses_num()
Matus Fabian8fed4242018-08-14 05:14:55 -07007547 self.assertEqual(ses_num_before_timeout - ses_num_after_timeout, 2)
Matus Fabian06596c52017-06-06 04:53:28 -07007548
Matus Fabian732036d2017-06-08 05:24:28 -07007549 def test_icmp_error(self):
7550 """ NAT64 ICMP Error message translation """
7551 self.tcp_port_in = 6303
7552 self.udp_port_in = 6304
7553 self.icmp_id_in = 6305
7554
Matus Fabian732036d2017-06-08 05:24:28 -07007555 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7556 self.nat_addr_n)
7557 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7558 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7559
7560 # send some packets to create sessions
7561 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
7562 self.pg0.add_stream(pkts)
7563 self.pg_enable_capture(self.pg_interfaces)
7564 self.pg_start()
7565 capture_ip4 = self.pg1.get_capture(len(pkts))
Matus Fabian029f3d22017-06-15 02:28:50 -07007566 self.verify_capture_out(capture_ip4,
Matus Fabian732036d2017-06-08 05:24:28 -07007567 nat_ip=self.nat_addr,
7568 dst_ip=self.pg1.remote_ip4)
7569
7570 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
7571 self.pg1.add_stream(pkts)
7572 self.pg_enable_capture(self.pg_interfaces)
7573 self.pg_start()
7574 capture_ip6 = self.pg0.get_capture(len(pkts))
7575 ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
7576 self.verify_capture_in_ip6(capture_ip6, ip[IPv6].src,
7577 self.pg0.remote_ip6)
7578
7579 # in2out
7580 pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7581 IPv6(src=self.pg0.remote_ip6, dst=ip[IPv6].src) /
7582 ICMPv6DestUnreach(code=1) /
7583 packet[IPv6] for packet in capture_ip6]
7584 self.pg0.add_stream(pkts)
7585 self.pg_enable_capture(self.pg_interfaces)
7586 self.pg_start()
7587 capture = self.pg1.get_capture(len(pkts))
7588 for packet in capture:
7589 try:
7590 self.assertEqual(packet[IP].src, self.nat_addr)
7591 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
7592 self.assertEqual(packet[ICMP].type, 3)
7593 self.assertEqual(packet[ICMP].code, 13)
7594 inner = packet[IPerror]
7595 self.assertEqual(inner.src, self.pg1.remote_ip4)
7596 self.assertEqual(inner.dst, self.nat_addr)
Klement Sekerad81ae412018-05-16 10:52:54 +02007597 self.assert_packet_checksums_valid(packet)
Matus Fabian732036d2017-06-08 05:24:28 -07007598 if inner.haslayer(TCPerror):
7599 self.assertEqual(inner[TCPerror].dport, self.tcp_port_out)
7600 elif inner.haslayer(UDPerror):
7601 self.assertEqual(inner[UDPerror].dport, self.udp_port_out)
7602 else:
7603 self.assertEqual(inner[ICMPerror].id, self.icmp_id_out)
7604 except:
7605 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7606 raise
7607
7608 # out2in
7609 pkts = [Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
7610 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
7611 ICMP(type=3, code=13) /
7612 packet[IP] for packet in capture_ip4]
7613 self.pg1.add_stream(pkts)
7614 self.pg_enable_capture(self.pg_interfaces)
7615 self.pg_start()
7616 capture = self.pg0.get_capture(len(pkts))
7617 for packet in capture:
7618 try:
7619 self.assertEqual(packet[IPv6].src, ip.src)
7620 self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
7621 icmp = packet[ICMPv6DestUnreach]
7622 self.assertEqual(icmp.code, 1)
7623 inner = icmp[IPerror6]
7624 self.assertEqual(inner.src, self.pg0.remote_ip6)
7625 self.assertEqual(inner.dst, ip.src)
Klement Sekerad81ae412018-05-16 10:52:54 +02007626 self.assert_icmpv6_checksum_valid(packet)
Matus Fabian732036d2017-06-08 05:24:28 -07007627 if inner.haslayer(TCPerror):
7628 self.assertEqual(inner[TCPerror].sport, self.tcp_port_in)
7629 elif inner.haslayer(UDPerror):
7630 self.assertEqual(inner[UDPerror].sport, self.udp_port_in)
7631 else:
7632 self.assertEqual(inner[ICMPv6EchoRequest].id,
7633 self.icmp_id_in)
7634 except:
7635 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7636 raise
7637
Matus Fabian029f3d22017-06-15 02:28:50 -07007638 def test_hairpinning(self):
7639 """ NAT64 hairpinning """
7640
7641 client = self.pg0.remote_hosts[0]
7642 server = self.pg0.remote_hosts[1]
7643 server_tcp_in_port = 22
7644 server_tcp_out_port = 4022
7645 server_udp_in_port = 23
7646 server_udp_out_port = 4023
7647 client_tcp_in_port = 1234
7648 client_udp_in_port = 1235
7649 client_tcp_out_port = 0
7650 client_udp_out_port = 0
7651 ip = IPv6(src=''.join(['64:ff9b::', self.nat_addr]))
7652 nat_addr_ip6 = ip.src
7653
7654 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7655 self.nat_addr_n)
7656 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7657 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7658
7659 self.vapi.nat64_add_del_static_bib(server.ip6n,
7660 self.nat_addr_n,
7661 server_tcp_in_port,
7662 server_tcp_out_port,
7663 IP_PROTOS.tcp)
7664 self.vapi.nat64_add_del_static_bib(server.ip6n,
7665 self.nat_addr_n,
7666 server_udp_in_port,
7667 server_udp_out_port,
7668 IP_PROTOS.udp)
7669
7670 # client to server
7671 pkts = []
7672 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7673 IPv6(src=client.ip6, dst=nat_addr_ip6) /
7674 TCP(sport=client_tcp_in_port, dport=server_tcp_out_port))
7675 pkts.append(p)
7676 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7677 IPv6(src=client.ip6, dst=nat_addr_ip6) /
7678 UDP(sport=client_udp_in_port, dport=server_udp_out_port))
7679 pkts.append(p)
7680 self.pg0.add_stream(pkts)
7681 self.pg_enable_capture(self.pg_interfaces)
7682 self.pg_start()
7683 capture = self.pg0.get_capture(len(pkts))
7684 for packet in capture:
7685 try:
7686 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
7687 self.assertEqual(packet[IPv6].dst, server.ip6)
Klement Sekerad81ae412018-05-16 10:52:54 +02007688 self.assert_packet_checksums_valid(packet)
Matus Fabian029f3d22017-06-15 02:28:50 -07007689 if packet.haslayer(TCP):
7690 self.assertNotEqual(packet[TCP].sport, client_tcp_in_port)
7691 self.assertEqual(packet[TCP].dport, server_tcp_in_port)
Matus Fabian029f3d22017-06-15 02:28:50 -07007692 client_tcp_out_port = packet[TCP].sport
7693 else:
7694 self.assertNotEqual(packet[UDP].sport, client_udp_in_port)
7695 self.assertEqual(packet[UDP].dport, server_udp_in_port)
Matus Fabian029f3d22017-06-15 02:28:50 -07007696 client_udp_out_port = packet[UDP].sport
7697 except:
7698 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7699 raise
7700
7701 # server to client
7702 pkts = []
7703 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7704 IPv6(src=server.ip6, dst=nat_addr_ip6) /
7705 TCP(sport=server_tcp_in_port, dport=client_tcp_out_port))
7706 pkts.append(p)
7707 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7708 IPv6(src=server.ip6, dst=nat_addr_ip6) /
7709 UDP(sport=server_udp_in_port, dport=client_udp_out_port))
7710 pkts.append(p)
7711 self.pg0.add_stream(pkts)
7712 self.pg_enable_capture(self.pg_interfaces)
7713 self.pg_start()
7714 capture = self.pg0.get_capture(len(pkts))
7715 for packet in capture:
7716 try:
7717 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
7718 self.assertEqual(packet[IPv6].dst, client.ip6)
Klement Sekerad81ae412018-05-16 10:52:54 +02007719 self.assert_packet_checksums_valid(packet)
Matus Fabian029f3d22017-06-15 02:28:50 -07007720 if packet.haslayer(TCP):
7721 self.assertEqual(packet[TCP].sport, server_tcp_out_port)
7722 self.assertEqual(packet[TCP].dport, client_tcp_in_port)
Matus Fabian029f3d22017-06-15 02:28:50 -07007723 else:
7724 self.assertEqual(packet[UDP].sport, server_udp_out_port)
7725 self.assertEqual(packet[UDP].dport, client_udp_in_port)
Matus Fabian029f3d22017-06-15 02:28:50 -07007726 except:
7727 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7728 raise
7729
7730 # ICMP error
7731 pkts = []
7732 pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7733 IPv6(src=client.ip6, dst=nat_addr_ip6) /
7734 ICMPv6DestUnreach(code=1) /
7735 packet[IPv6] for packet in capture]
7736 self.pg0.add_stream(pkts)
7737 self.pg_enable_capture(self.pg_interfaces)
7738 self.pg_start()
7739 capture = self.pg0.get_capture(len(pkts))
7740 for packet in capture:
7741 try:
7742 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
7743 self.assertEqual(packet[IPv6].dst, server.ip6)
7744 icmp = packet[ICMPv6DestUnreach]
7745 self.assertEqual(icmp.code, 1)
7746 inner = icmp[IPerror6]
7747 self.assertEqual(inner.src, server.ip6)
7748 self.assertEqual(inner.dst, nat_addr_ip6)
Klement Sekerad81ae412018-05-16 10:52:54 +02007749 self.assert_packet_checksums_valid(packet)
Matus Fabian029f3d22017-06-15 02:28:50 -07007750 if inner.haslayer(TCPerror):
7751 self.assertEqual(inner[TCPerror].sport, server_tcp_in_port)
7752 self.assertEqual(inner[TCPerror].dport,
7753 client_tcp_out_port)
7754 else:
7755 self.assertEqual(inner[UDPerror].sport, server_udp_in_port)
7756 self.assertEqual(inner[UDPerror].dport,
7757 client_udp_out_port)
7758 except:
7759 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7760 raise
7761
Matus Fabian428dc912017-06-21 06:15:18 -07007762 def test_prefix(self):
7763 """ NAT64 Network-Specific Prefix """
7764
7765 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7766 self.nat_addr_n)
7767 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7768 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7769 self.vapi.nat64_add_del_pool_addr_range(self.vrf1_nat_addr_n,
7770 self.vrf1_nat_addr_n,
7771 vrf_id=self.vrf1_id)
7772 self.vapi.nat64_add_del_interface(self.pg2.sw_if_index)
7773
7774 # Add global prefix
7775 global_pref64 = "2001:db8::"
7776 global_pref64_n = socket.inet_pton(socket.AF_INET6, global_pref64)
7777 global_pref64_len = 32
7778 self.vapi.nat64_add_del_prefix(global_pref64_n, global_pref64_len)
7779
7780 prefix = self.vapi.nat64_prefix_dump()
7781 self.assertEqual(len(prefix), 1)
7782 self.assertEqual(prefix[0].prefix, global_pref64_n)
7783 self.assertEqual(prefix[0].prefix_len, global_pref64_len)
7784 self.assertEqual(prefix[0].vrf_id, 0)
7785
7786 # Add tenant specific prefix
7787 vrf1_pref64 = "2001:db8:122:300::"
7788 vrf1_pref64_n = socket.inet_pton(socket.AF_INET6, vrf1_pref64)
7789 vrf1_pref64_len = 56
7790 self.vapi.nat64_add_del_prefix(vrf1_pref64_n,
7791 vrf1_pref64_len,
7792 vrf_id=self.vrf1_id)
7793 prefix = self.vapi.nat64_prefix_dump()
7794 self.assertEqual(len(prefix), 2)
7795
7796 # Global prefix
7797 pkts = self.create_stream_in_ip6(self.pg0,
7798 self.pg1,
7799 pref=global_pref64,
7800 plen=global_pref64_len)
7801 self.pg0.add_stream(pkts)
7802 self.pg_enable_capture(self.pg_interfaces)
7803 self.pg_start()
7804 capture = self.pg1.get_capture(len(pkts))
7805 self.verify_capture_out(capture, nat_ip=self.nat_addr,
7806 dst_ip=self.pg1.remote_ip4)
7807
7808 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
7809 self.pg1.add_stream(pkts)
7810 self.pg_enable_capture(self.pg_interfaces)
7811 self.pg_start()
7812 capture = self.pg0.get_capture(len(pkts))
7813 dst_ip = self.compose_ip6(self.pg1.remote_ip4,
7814 global_pref64,
7815 global_pref64_len)
7816 self.verify_capture_in_ip6(capture, dst_ip, self.pg0.remote_ip6)
7817
7818 # Tenant specific prefix
7819 pkts = self.create_stream_in_ip6(self.pg2,
7820 self.pg1,
7821 pref=vrf1_pref64,
7822 plen=vrf1_pref64_len)
7823 self.pg2.add_stream(pkts)
7824 self.pg_enable_capture(self.pg_interfaces)
7825 self.pg_start()
7826 capture = self.pg1.get_capture(len(pkts))
7827 self.verify_capture_out(capture, nat_ip=self.vrf1_nat_addr,
7828 dst_ip=self.pg1.remote_ip4)
7829
7830 pkts = self.create_stream_out(self.pg1, dst_ip=self.vrf1_nat_addr)
7831 self.pg1.add_stream(pkts)
7832 self.pg_enable_capture(self.pg_interfaces)
7833 self.pg_start()
7834 capture = self.pg2.get_capture(len(pkts))
7835 dst_ip = self.compose_ip6(self.pg1.remote_ip4,
7836 vrf1_pref64,
7837 vrf1_pref64_len)
7838 self.verify_capture_in_ip6(capture, dst_ip, self.pg2.remote_ip6)
7839
Matus Fabianf8cd5812017-07-11 03:55:02 -07007840 def test_unknown_proto(self):
Matus Fabian7968e6c2017-07-06 05:37:49 -07007841 """ NAT64 translate packet with unknown protocol """
7842
7843 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7844 self.nat_addr_n)
7845 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7846 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7847 remote_ip6 = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
7848
7849 # in2out
7850 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7851 IPv6(src=self.pg0.remote_ip6, dst=remote_ip6) /
7852 TCP(sport=self.tcp_port_in, dport=20))
7853 self.pg0.add_stream(p)
7854 self.pg_enable_capture(self.pg_interfaces)
7855 self.pg_start()
7856 p = self.pg1.get_capture(1)
7857
7858 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabianf8cd5812017-07-11 03:55:02 -07007859 IPv6(src=self.pg0.remote_ip6, dst=remote_ip6, nh=47) /
Matus Fabian7968e6c2017-07-06 05:37:49 -07007860 GRE() /
7861 IP(src=self.pg2.local_ip4, dst=self.pg2.remote_ip4) /
7862 TCP(sport=1234, dport=1234))
7863 self.pg0.add_stream(p)
7864 self.pg_enable_capture(self.pg_interfaces)
7865 self.pg_start()
7866 p = self.pg1.get_capture(1)
7867 packet = p[0]
7868 try:
7869 self.assertEqual(packet[IP].src, self.nat_addr)
7870 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
Paul Vinciguerra978aa642018-11-24 22:19:12 -08007871 self.assertEqual(packet.haslayer(GRE), 1)
Klement Sekerad81ae412018-05-16 10:52:54 +02007872 self.assert_packet_checksums_valid(packet)
Matus Fabian7968e6c2017-07-06 05:37:49 -07007873 except:
7874 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7875 raise
7876
7877 # out2in
7878 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
7879 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
7880 GRE() /
7881 IP(src=self.pg2.remote_ip4, dst=self.pg2.local_ip4) /
7882 TCP(sport=1234, dport=1234))
7883 self.pg1.add_stream(p)
7884 self.pg_enable_capture(self.pg_interfaces)
7885 self.pg_start()
7886 p = self.pg0.get_capture(1)
7887 packet = p[0]
7888 try:
7889 self.assertEqual(packet[IPv6].src, remote_ip6)
Matus Fabianf8cd5812017-07-11 03:55:02 -07007890 self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
7891 self.assertEqual(packet[IPv6].nh, 47)
Matus Fabian7968e6c2017-07-06 05:37:49 -07007892 except:
7893 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7894 raise
7895
Matus Fabianf8cd5812017-07-11 03:55:02 -07007896 def test_hairpinning_unknown_proto(self):
Matus Fabian7968e6c2017-07-06 05:37:49 -07007897 """ NAT64 translate packet with unknown protocol - hairpinning """
7898
7899 client = self.pg0.remote_hosts[0]
7900 server = self.pg0.remote_hosts[1]
7901 server_tcp_in_port = 22
7902 server_tcp_out_port = 4022
7903 client_tcp_in_port = 1234
Matus Fabianf8cd5812017-07-11 03:55:02 -07007904 client_tcp_out_port = 1235
7905 server_nat_ip = "10.0.0.100"
7906 client_nat_ip = "10.0.0.110"
7907 server_nat_ip_n = socket.inet_pton(socket.AF_INET, server_nat_ip)
7908 client_nat_ip_n = socket.inet_pton(socket.AF_INET, client_nat_ip)
7909 server_nat_ip6 = self.compose_ip6(server_nat_ip, '64:ff9b::', 96)
7910 client_nat_ip6 = self.compose_ip6(client_nat_ip, '64:ff9b::', 96)
Matus Fabian7968e6c2017-07-06 05:37:49 -07007911
Matus Fabianf8cd5812017-07-11 03:55:02 -07007912 self.vapi.nat64_add_del_pool_addr_range(server_nat_ip_n,
7913 client_nat_ip_n)
Matus Fabian7968e6c2017-07-06 05:37:49 -07007914 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7915 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7916
7917 self.vapi.nat64_add_del_static_bib(server.ip6n,
Matus Fabianf8cd5812017-07-11 03:55:02 -07007918 server_nat_ip_n,
Matus Fabian7968e6c2017-07-06 05:37:49 -07007919 server_tcp_in_port,
7920 server_tcp_out_port,
7921 IP_PROTOS.tcp)
7922
Matus Fabianf8cd5812017-07-11 03:55:02 -07007923 self.vapi.nat64_add_del_static_bib(server.ip6n,
7924 server_nat_ip_n,
7925 0,
7926 0,
7927 IP_PROTOS.gre)
7928
7929 self.vapi.nat64_add_del_static_bib(client.ip6n,
7930 client_nat_ip_n,
7931 client_tcp_in_port,
7932 client_tcp_out_port,
7933 IP_PROTOS.tcp)
7934
Matus Fabian7968e6c2017-07-06 05:37:49 -07007935 # client to server
7936 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabianf8cd5812017-07-11 03:55:02 -07007937 IPv6(src=client.ip6, dst=server_nat_ip6) /
Matus Fabian7968e6c2017-07-06 05:37:49 -07007938 TCP(sport=client_tcp_in_port, dport=server_tcp_out_port))
7939 self.pg0.add_stream(p)
7940 self.pg_enable_capture(self.pg_interfaces)
7941 self.pg_start()
7942 p = self.pg0.get_capture(1)
7943
7944 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabianf8cd5812017-07-11 03:55:02 -07007945 IPv6(src=client.ip6, dst=server_nat_ip6, nh=IP_PROTOS.gre) /
Matus Fabian7968e6c2017-07-06 05:37:49 -07007946 GRE() /
7947 IP(src=self.pg2.local_ip4, dst=self.pg2.remote_ip4) /
7948 TCP(sport=1234, dport=1234))
7949 self.pg0.add_stream(p)
7950 self.pg_enable_capture(self.pg_interfaces)
7951 self.pg_start()
7952 p = self.pg0.get_capture(1)
7953 packet = p[0]
7954 try:
Matus Fabianf8cd5812017-07-11 03:55:02 -07007955 self.assertEqual(packet[IPv6].src, client_nat_ip6)
Matus Fabian7968e6c2017-07-06 05:37:49 -07007956 self.assertEqual(packet[IPv6].dst, server.ip6)
Matus Fabianf8cd5812017-07-11 03:55:02 -07007957 self.assertEqual(packet[IPv6].nh, IP_PROTOS.gre)
Matus Fabian7968e6c2017-07-06 05:37:49 -07007958 except:
7959 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7960 raise
7961
7962 # server to client
7963 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabianf8cd5812017-07-11 03:55:02 -07007964 IPv6(src=server.ip6, dst=client_nat_ip6, nh=IP_PROTOS.gre) /
Matus Fabian7968e6c2017-07-06 05:37:49 -07007965 GRE() /
7966 IP(src=self.pg2.remote_ip4, dst=self.pg2.local_ip4) /
7967 TCP(sport=1234, dport=1234))
7968 self.pg0.add_stream(p)
7969 self.pg_enable_capture(self.pg_interfaces)
7970 self.pg_start()
7971 p = self.pg0.get_capture(1)
7972 packet = p[0]
7973 try:
Matus Fabianf8cd5812017-07-11 03:55:02 -07007974 self.assertEqual(packet[IPv6].src, server_nat_ip6)
Matus Fabian7968e6c2017-07-06 05:37:49 -07007975 self.assertEqual(packet[IPv6].dst, client.ip6)
Matus Fabianf8cd5812017-07-11 03:55:02 -07007976 self.assertEqual(packet[IPv6].nh, IP_PROTOS.gre)
Matus Fabian7968e6c2017-07-06 05:37:49 -07007977 except:
7978 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7979 raise
7980
Matus Fabian36ea2d62017-10-24 04:13:49 -07007981 def test_one_armed_nat64(self):
7982 """ One armed NAT64 """
7983 external_port = 0
7984 remote_host_ip6 = self.compose_ip6(self.pg3.remote_ip4,
7985 '64:ff9b::',
7986 96)
7987
7988 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7989 self.nat_addr_n)
7990 self.vapi.nat64_add_del_interface(self.pg3.sw_if_index)
7991 self.vapi.nat64_add_del_interface(self.pg3.sw_if_index, is_inside=0)
7992
7993 # in2out
7994 p = (Ether(src=self.pg3.remote_mac, dst=self.pg3.local_mac) /
7995 IPv6(src=self.pg3.remote_ip6, dst=remote_host_ip6) /
7996 TCP(sport=12345, dport=80))
7997 self.pg3.add_stream(p)
7998 self.pg_enable_capture(self.pg_interfaces)
7999 self.pg_start()
8000 capture = self.pg3.get_capture(1)
8001 p = capture[0]
8002 try:
8003 ip = p[IP]
8004 tcp = p[TCP]
8005 self.assertEqual(ip.src, self.nat_addr)
8006 self.assertEqual(ip.dst, self.pg3.remote_ip4)
8007 self.assertNotEqual(tcp.sport, 12345)
8008 external_port = tcp.sport
8009 self.assertEqual(tcp.dport, 80)
Klement Sekerad81ae412018-05-16 10:52:54 +02008010 self.assert_packet_checksums_valid(p)
Matus Fabian36ea2d62017-10-24 04:13:49 -07008011 except:
8012 self.logger.error(ppp("Unexpected or invalid packet:", p))
8013 raise
8014
8015 # out2in
8016 p = (Ether(src=self.pg3.remote_mac, dst=self.pg3.local_mac) /
8017 IP(src=self.pg3.remote_ip4, dst=self.nat_addr) /
8018 TCP(sport=80, dport=external_port))
8019 self.pg3.add_stream(p)
8020 self.pg_enable_capture(self.pg_interfaces)
8021 self.pg_start()
8022 capture = self.pg3.get_capture(1)
8023 p = capture[0]
8024 try:
8025 ip = p[IPv6]
8026 tcp = p[TCP]
8027 self.assertEqual(ip.src, remote_host_ip6)
8028 self.assertEqual(ip.dst, self.pg3.remote_ip6)
8029 self.assertEqual(tcp.sport, 80)
8030 self.assertEqual(tcp.dport, 12345)
Klement Sekerad81ae412018-05-16 10:52:54 +02008031 self.assert_packet_checksums_valid(p)
Matus Fabian36ea2d62017-10-24 04:13:49 -07008032 except:
8033 self.logger.error(ppp("Unexpected or invalid packet:", p))
8034 raise
8035
Matus Fabianefcd1e92017-08-15 06:59:19 -07008036 def test_frag_in_order(self):
8037 """ NAT64 translate fragments arriving in order """
8038 self.tcp_port_in = random.randint(1025, 65535)
8039
8040 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
8041 self.nat_addr_n)
8042 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
8043 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
8044
8045 reass = self.vapi.nat_reass_dump()
8046 reass_n_start = len(reass)
8047
8048 # in2out
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07008049 data = b'a' * 200
Matus Fabianefcd1e92017-08-15 06:59:19 -07008050 pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
8051 self.tcp_port_in, 20, data)
8052 self.pg0.add_stream(pkts)
8053 self.pg_enable_capture(self.pg_interfaces)
8054 self.pg_start()
8055 frags = self.pg1.get_capture(len(pkts))
8056 p = self.reass_frags_and_verify(frags,
8057 self.nat_addr,
8058 self.pg1.remote_ip4)
8059 self.assertEqual(p[TCP].dport, 20)
8060 self.assertNotEqual(p[TCP].sport, self.tcp_port_in)
8061 self.tcp_port_out = p[TCP].sport
8062 self.assertEqual(data, p[Raw].load)
8063
8064 # out2in
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07008065 data = b"A" * 4 + b"b" * 16 + b"C" * 3
Matus Fabianefcd1e92017-08-15 06:59:19 -07008066 pkts = self.create_stream_frag(self.pg1,
8067 self.nat_addr,
8068 20,
8069 self.tcp_port_out,
8070 data)
8071 self.pg1.add_stream(pkts)
8072 self.pg_enable_capture(self.pg_interfaces)
8073 self.pg_start()
8074 frags = self.pg0.get_capture(len(pkts))
8075 src = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
8076 p = self.reass_frags_and_verify_ip6(frags, src, self.pg0.remote_ip6)
8077 self.assertEqual(p[TCP].sport, 20)
8078 self.assertEqual(p[TCP].dport, self.tcp_port_in)
8079 self.assertEqual(data, p[Raw].load)
8080
8081 reass = self.vapi.nat_reass_dump()
8082 reass_n_end = len(reass)
8083
8084 self.assertEqual(reass_n_end - reass_n_start, 2)
8085
8086 def test_reass_hairpinning(self):
8087 """ NAT64 fragments hairpinning """
8088 data = 'a' * 200
Matus Fabianefcd1e92017-08-15 06:59:19 -07008089 server = self.pg0.remote_hosts[1]
8090 server_in_port = random.randint(1025, 65535)
8091 server_out_port = random.randint(1025, 65535)
8092 client_in_port = random.randint(1025, 65535)
8093 ip = IPv6(src=''.join(['64:ff9b::', self.nat_addr]))
8094 nat_addr_ip6 = ip.src
8095
8096 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
8097 self.nat_addr_n)
8098 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
8099 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
8100
8101 # add static BIB entry for server
8102 self.vapi.nat64_add_del_static_bib(server.ip6n,
8103 self.nat_addr_n,
8104 server_in_port,
8105 server_out_port,
8106 IP_PROTOS.tcp)
8107
8108 # send packet from host to server
8109 pkts = self.create_stream_frag_ip6(self.pg0,
8110 self.nat_addr,
8111 client_in_port,
8112 server_out_port,
8113 data)
8114 self.pg0.add_stream(pkts)
8115 self.pg_enable_capture(self.pg_interfaces)
8116 self.pg_start()
8117 frags = self.pg0.get_capture(len(pkts))
8118 p = self.reass_frags_and_verify_ip6(frags, nat_addr_ip6, server.ip6)
8119 self.assertNotEqual(p[TCP].sport, client_in_port)
8120 self.assertEqual(p[TCP].dport, server_in_port)
8121 self.assertEqual(data, p[Raw].load)
8122
8123 def test_frag_out_of_order(self):
8124 """ NAT64 translate fragments arriving out of order """
8125 self.tcp_port_in = random.randint(1025, 65535)
8126
8127 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
8128 self.nat_addr_n)
8129 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
8130 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
8131
8132 # in2out
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07008133 data = b'a' * 200
Matus Fabianefcd1e92017-08-15 06:59:19 -07008134 pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
8135 self.tcp_port_in, 20, data)
8136 pkts.reverse()
8137 self.pg0.add_stream(pkts)
8138 self.pg_enable_capture(self.pg_interfaces)
8139 self.pg_start()
8140 frags = self.pg1.get_capture(len(pkts))
8141 p = self.reass_frags_and_verify(frags,
8142 self.nat_addr,
8143 self.pg1.remote_ip4)
8144 self.assertEqual(p[TCP].dport, 20)
8145 self.assertNotEqual(p[TCP].sport, self.tcp_port_in)
8146 self.tcp_port_out = p[TCP].sport
8147 self.assertEqual(data, p[Raw].load)
8148
8149 # out2in
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07008150 data = b"A" * 4 + b"B" * 16 + b"C" * 3
Matus Fabianefcd1e92017-08-15 06:59:19 -07008151 pkts = self.create_stream_frag(self.pg1,
8152 self.nat_addr,
8153 20,
8154 self.tcp_port_out,
8155 data)
8156 pkts.reverse()
8157 self.pg1.add_stream(pkts)
8158 self.pg_enable_capture(self.pg_interfaces)
8159 self.pg_start()
8160 frags = self.pg0.get_capture(len(pkts))
8161 src = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
8162 p = self.reass_frags_and_verify_ip6(frags, src, self.pg0.remote_ip6)
8163 self.assertEqual(p[TCP].sport, 20)
8164 self.assertEqual(p[TCP].dport, self.tcp_port_in)
8165 self.assertEqual(data, p[Raw].load)
8166
Matus Fabian0938dcf2017-11-08 01:59:38 -08008167 def test_interface_addr(self):
8168 """ Acquire NAT64 pool addresses from interface """
Ole Troane1ade682019-03-04 23:55:43 +01008169 self.vapi.nat64_add_del_interface_addr(self.pg4.sw_if_index)
Matus Fabian0938dcf2017-11-08 01:59:38 -08008170
8171 # no address in NAT64 pool
8172 adresses = self.vapi.nat44_address_dump()
8173 self.assertEqual(0, len(adresses))
8174
8175 # configure interface address and check NAT64 address pool
8176 self.pg4.config_ip4()
8177 addresses = self.vapi.nat64_pool_addr_dump()
8178 self.assertEqual(len(addresses), 1)
8179 self.assertEqual(addresses[0].address, self.pg4.local_ip4n)
8180
8181 # remove interface address and check NAT64 address pool
8182 self.pg4.unconfig_ip4()
8183 addresses = self.vapi.nat64_pool_addr_dump()
8184 self.assertEqual(0, len(adresses))
8185
Paul Vinciguerradefde0f2018-12-06 07:46:13 -08008186 @unittest.skipUnless(running_extended_tests, "part of extended tests")
Matus Fabiana431ad12018-01-04 04:03:14 -08008187 def test_ipfix_max_bibs_sessions(self):
8188 """ IPFIX logging maximum session and BIB entries exceeded """
8189 max_bibs = 1280
8190 max_sessions = 2560
8191 remote_host_ip6 = self.compose_ip6(self.pg1.remote_ip4,
8192 '64:ff9b::',
8193 96)
8194
8195 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
8196 self.nat_addr_n)
8197 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
8198 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
8199
8200 pkts = []
8201 src = ""
8202 for i in range(0, max_bibs):
8203 src = "fd01:aa::%x" % (i)
8204 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
8205 IPv6(src=src, dst=remote_host_ip6) /
8206 TCP(sport=12345, dport=80))
8207 pkts.append(p)
8208 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
8209 IPv6(src=src, dst=remote_host_ip6) /
8210 TCP(sport=12345, dport=22))
8211 pkts.append(p)
8212 self.pg0.add_stream(pkts)
8213 self.pg_enable_capture(self.pg_interfaces)
8214 self.pg_start()
8215 self.pg1.get_capture(max_sessions)
8216
8217 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
8218 src_address=self.pg3.local_ip4n,
8219 path_mtu=512,
8220 template_interval=10)
Ole Troane1ade682019-03-04 23:55:43 +01008221 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
8222 src_port=self.ipfix_src_port)
Matus Fabiana431ad12018-01-04 04:03:14 -08008223
8224 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
8225 IPv6(src=src, dst=remote_host_ip6) /
8226 TCP(sport=12345, dport=25))
8227 self.pg0.add_stream(p)
8228 self.pg_enable_capture(self.pg_interfaces)
8229 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07008230 self.pg1.assert_nothing_captured()
8231 sleep(1)
Matus Fabiana431ad12018-01-04 04:03:14 -08008232 self.vapi.cli("ipfix flush") # FIXME this should be an API call
8233 capture = self.pg3.get_capture(9)
8234 ipfix = IPFIXDecoder()
8235 # first load template
8236 for p in capture:
8237 self.assertTrue(p.haslayer(IPFIX))
8238 self.assertEqual(p[IP].src, self.pg3.local_ip4)
8239 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
8240 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
8241 self.assertEqual(p[UDP].dport, 4739)
8242 self.assertEqual(p[IPFIX].observationDomainID,
8243 self.ipfix_domain_id)
8244 if p.haslayer(Template):
8245 ipfix.add_template(p.getlayer(Template))
8246 # verify events in data set
8247 for p in capture:
8248 if p.haslayer(Data):
8249 data = ipfix.decode_data_set(p.getlayer(Set))
8250 self.verify_ipfix_max_sessions(data, max_sessions)
8251
8252 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
8253 IPv6(src=self.pg0.remote_ip6, dst=remote_host_ip6) /
8254 TCP(sport=12345, dport=80))
8255 self.pg0.add_stream(p)
8256 self.pg_enable_capture(self.pg_interfaces)
8257 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07008258 self.pg1.assert_nothing_captured()
8259 sleep(1)
Matus Fabiana431ad12018-01-04 04:03:14 -08008260 self.vapi.cli("ipfix flush") # FIXME this should be an API call
8261 capture = self.pg3.get_capture(1)
8262 # verify events in data set
8263 for p in capture:
8264 self.assertTrue(p.haslayer(IPFIX))
8265 self.assertEqual(p[IP].src, self.pg3.local_ip4)
8266 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
8267 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
8268 self.assertEqual(p[UDP].dport, 4739)
8269 self.assertEqual(p[IPFIX].observationDomainID,
8270 self.ipfix_domain_id)
8271 if p.haslayer(Data):
8272 data = ipfix.decode_data_set(p.getlayer(Set))
8273 self.verify_ipfix_max_bibs(data, max_bibs)
8274
8275 def test_ipfix_max_frags(self):
8276 """ IPFIX logging maximum fragments pending reassembly exceeded """
8277 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
8278 self.nat_addr_n)
8279 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
8280 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
Matus Fabiana7f8b222018-09-05 06:01:55 -07008281 self.vapi.nat_set_reass(max_frag=1, is_ip6=1)
Matus Fabiana431ad12018-01-04 04:03:14 -08008282 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
8283 src_address=self.pg3.local_ip4n,
8284 path_mtu=512,
8285 template_interval=10)
Ole Troane1ade682019-03-04 23:55:43 +01008286 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
8287 src_port=self.ipfix_src_port)
Matus Fabiana431ad12018-01-04 04:03:14 -08008288
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07008289 data = b'a' * 200
Matus Fabiana431ad12018-01-04 04:03:14 -08008290 pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
8291 self.tcp_port_in, 20, data)
Matus Fabiana7f8b222018-09-05 06:01:55 -07008292 pkts.reverse()
8293 self.pg0.add_stream(pkts)
Matus Fabiana431ad12018-01-04 04:03:14 -08008294 self.pg_enable_capture(self.pg_interfaces)
8295 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07008296 self.pg1.assert_nothing_captured()
8297 sleep(1)
Matus Fabiana431ad12018-01-04 04:03:14 -08008298 self.vapi.cli("ipfix flush") # FIXME this should be an API call
8299 capture = self.pg3.get_capture(9)
8300 ipfix = IPFIXDecoder()
8301 # first load template
8302 for p in capture:
8303 self.assertTrue(p.haslayer(IPFIX))
8304 self.assertEqual(p[IP].src, self.pg3.local_ip4)
8305 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
8306 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
8307 self.assertEqual(p[UDP].dport, 4739)
8308 self.assertEqual(p[IPFIX].observationDomainID,
8309 self.ipfix_domain_id)
8310 if p.haslayer(Template):
8311 ipfix.add_template(p.getlayer(Template))
8312 # verify events in data set
8313 for p in capture:
8314 if p.haslayer(Data):
8315 data = ipfix.decode_data_set(p.getlayer(Set))
Matus Fabiana7f8b222018-09-05 06:01:55 -07008316 self.verify_ipfix_max_fragments_ip6(data, 1,
Matus Fabiana431ad12018-01-04 04:03:14 -08008317 self.pg0.remote_ip6n)
8318
8319 def test_ipfix_bib_ses(self):
8320 """ IPFIX logging NAT64 BIB/session create and delete events """
8321 self.tcp_port_in = random.randint(1025, 65535)
8322 remote_host_ip6 = self.compose_ip6(self.pg1.remote_ip4,
8323 '64:ff9b::',
8324 96)
8325
8326 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
8327 self.nat_addr_n)
8328 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
8329 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
8330 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
8331 src_address=self.pg3.local_ip4n,
8332 path_mtu=512,
8333 template_interval=10)
Ole Troane1ade682019-03-04 23:55:43 +01008334 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
8335 src_port=self.ipfix_src_port)
Matus Fabiana431ad12018-01-04 04:03:14 -08008336
8337 # Create
8338 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
8339 IPv6(src=self.pg0.remote_ip6, dst=remote_host_ip6) /
8340 TCP(sport=self.tcp_port_in, dport=25))
8341 self.pg0.add_stream(p)
8342 self.pg_enable_capture(self.pg_interfaces)
8343 self.pg_start()
8344 p = self.pg1.get_capture(1)
8345 self.tcp_port_out = p[0][TCP].sport
8346 self.vapi.cli("ipfix flush") # FIXME this should be an API call
8347 capture = self.pg3.get_capture(10)
8348 ipfix = IPFIXDecoder()
8349 # first load template
8350 for p in capture:
8351 self.assertTrue(p.haslayer(IPFIX))
8352 self.assertEqual(p[IP].src, self.pg3.local_ip4)
8353 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
8354 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
8355 self.assertEqual(p[UDP].dport, 4739)
8356 self.assertEqual(p[IPFIX].observationDomainID,
8357 self.ipfix_domain_id)
8358 if p.haslayer(Template):
8359 ipfix.add_template(p.getlayer(Template))
8360 # verify events in data set
8361 for p in capture:
8362 if p.haslayer(Data):
8363 data = ipfix.decode_data_set(p.getlayer(Set))
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07008364 if scapy.compat.orb(data[0][230]) == 10:
Matus Fabiana431ad12018-01-04 04:03:14 -08008365 self.verify_ipfix_bib(data, 1, self.pg0.remote_ip6n)
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07008366 elif scapy.compat.orb(data[0][230]) == 6:
Matus Fabiana431ad12018-01-04 04:03:14 -08008367 self.verify_ipfix_nat64_ses(data,
8368 1,
8369 self.pg0.remote_ip6n,
8370 self.pg1.remote_ip4,
8371 25)
8372 else:
8373 self.logger.error(ppp("Unexpected or invalid packet: ", p))
8374
8375 # Delete
8376 self.pg_enable_capture(self.pg_interfaces)
8377 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
8378 self.nat_addr_n,
8379 is_add=0)
8380 self.vapi.cli("ipfix flush") # FIXME this should be an API call
8381 capture = self.pg3.get_capture(2)
8382 # verify events in data set
8383 for p in capture:
8384 self.assertTrue(p.haslayer(IPFIX))
8385 self.assertEqual(p[IP].src, self.pg3.local_ip4)
8386 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
8387 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
8388 self.assertEqual(p[UDP].dport, 4739)
8389 self.assertEqual(p[IPFIX].observationDomainID,
8390 self.ipfix_domain_id)
8391 if p.haslayer(Data):
8392 data = ipfix.decode_data_set(p.getlayer(Set))
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07008393 if scapy.compat.orb(data[0][230]) == 11:
Matus Fabiana431ad12018-01-04 04:03:14 -08008394 self.verify_ipfix_bib(data, 0, self.pg0.remote_ip6n)
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07008395 elif scapy.compat.orb(data[0][230]) == 7:
Matus Fabiana431ad12018-01-04 04:03:14 -08008396 self.verify_ipfix_nat64_ses(data,
8397 0,
8398 self.pg0.remote_ip6n,
8399 self.pg1.remote_ip4,
8400 25)
8401 else:
8402 self.logger.error(ppp("Unexpected or invalid packet: ", p))
8403
Matus Fabianad1f3e12018-11-28 21:26:34 -08008404 def test_syslog_sess(self):
8405 """ Test syslog session creation and deletion """
8406 self.tcp_port_in = random.randint(1025, 65535)
8407 remote_host_ip6 = self.compose_ip6(self.pg1.remote_ip4,
8408 '64:ff9b::',
8409 96)
8410
8411 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
8412 self.nat_addr_n)
8413 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
8414 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
8415 self.vapi.syslog_set_filter(SYSLOG_SEVERITY.INFO)
Ole Troanf159f582019-02-28 20:20:47 +01008416 self.vapi.syslog_set_sender(self.pg3.local_ip4n, self.pg3.remote_ip4n)
Matus Fabianad1f3e12018-11-28 21:26:34 -08008417
8418 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
8419 IPv6(src=self.pg0.remote_ip6, dst=remote_host_ip6) /
8420 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port))
8421 self.pg0.add_stream(p)
8422 self.pg_enable_capture(self.pg_interfaces)
8423 self.pg_start()
8424 p = self.pg1.get_capture(1)
8425 self.tcp_port_out = p[0][TCP].sport
8426 capture = self.pg3.get_capture(1)
8427 self.verify_syslog_sess(capture[0][Raw].load, is_ip6=True)
8428
8429 self.pg_enable_capture(self.pg_interfaces)
8430 self.pg_start()
8431 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
8432 self.nat_addr_n,
8433 is_add=0)
8434 capture = self.pg3.get_capture(1)
8435 self.verify_syslog_sess(capture[0][Raw].load, False, True)
8436
Matus Fabian06596c52017-06-06 04:53:28 -07008437 def nat64_get_ses_num(self):
8438 """
8439 Return number of active NAT64 sessions.
8440 """
Matus Fabianab9a59c2017-08-16 05:37:36 -07008441 st = self.vapi.nat64_st_dump()
8442 return len(st)
Matus Fabian06596c52017-06-06 04:53:28 -07008443
8444 def clear_nat64(self):
8445 """
8446 Clear NAT64 configuration.
8447 """
Ole Troane1ade682019-03-04 23:55:43 +01008448 self.vapi.nat_ipfix_enable_disable(enable=0,
8449 src_port=self.ipfix_src_port,
8450 domain_id=self.ipfix_domain_id)
Matus Fabiana431ad12018-01-04 04:03:14 -08008451 self.ipfix_src_port = 4739
8452 self.ipfix_domain_id = 1
8453
Matus Fabianad1f3e12018-11-28 21:26:34 -08008454 self.vapi.syslog_set_filter(SYSLOG_SEVERITY.EMERG)
8455
Matus Fabian878c6462018-08-23 00:33:35 -07008456 self.vapi.nat_set_timeouts()
Matus Fabian06596c52017-06-06 04:53:28 -07008457
8458 interfaces = self.vapi.nat64_interface_dump()
8459 for intf in interfaces:
Matus Fabian36ea2d62017-10-24 04:13:49 -07008460 if intf.is_inside > 1:
8461 self.vapi.nat64_add_del_interface(intf.sw_if_index,
8462 0,
8463 is_add=0)
Matus Fabian06596c52017-06-06 04:53:28 -07008464 self.vapi.nat64_add_del_interface(intf.sw_if_index,
8465 intf.is_inside,
8466 is_add=0)
8467
Matus Fabiana431ad12018-01-04 04:03:14 -08008468 bib = self.vapi.nat64_bib_dump(255)
Matus Fabian06596c52017-06-06 04:53:28 -07008469 for bibe in bib:
8470 if bibe.is_static:
8471 self.vapi.nat64_add_del_static_bib(bibe.i_addr,
8472 bibe.o_addr,
8473 bibe.i_port,
8474 bibe.o_port,
8475 bibe.proto,
8476 bibe.vrf_id,
8477 is_add=0)
8478
8479 adresses = self.vapi.nat64_pool_addr_dump()
8480 for addr in adresses:
8481 self.vapi.nat64_add_del_pool_addr_range(addr.address,
8482 addr.address,
Matus Fabian029f3d22017-06-15 02:28:50 -07008483 vrf_id=addr.vrf_id,
Matus Fabian06596c52017-06-06 04:53:28 -07008484 is_add=0)
8485
Matus Fabian428dc912017-06-21 06:15:18 -07008486 prefixes = self.vapi.nat64_prefix_dump()
8487 for prefix in prefixes:
8488 self.vapi.nat64_add_del_prefix(prefix.prefix,
8489 prefix.prefix_len,
8490 vrf_id=prefix.vrf_id,
8491 is_add=0)
8492
Matus Fabianfd0d5082018-12-18 01:08:51 -08008493 bibs = self.statistics.get_counter('/nat64/total-bibs')
8494 self.assertEqual(bibs[0][0], 0)
8495 sessions = self.statistics.get_counter('/nat64/total-sessions')
8496 self.assertEqual(sessions[0][0], 0)
8497
Matus Fabian06596c52017-06-06 04:53:28 -07008498 def tearDown(self):
8499 super(TestNAT64, self).tearDown()
8500 if not self.vpp_dead:
8501 self.logger.info(self.vapi.cli("show nat64 pool"))
8502 self.logger.info(self.vapi.cli("show nat64 interfaces"))
Matus Fabian428dc912017-06-21 06:15:18 -07008503 self.logger.info(self.vapi.cli("show nat64 prefix"))
Matus Fabianab9a59c2017-08-16 05:37:36 -07008504 self.logger.info(self.vapi.cli("show nat64 bib all"))
8505 self.logger.info(self.vapi.cli("show nat64 session table all"))
Matus Fabianefcd1e92017-08-15 06:59:19 -07008506 self.logger.info(self.vapi.cli("show nat virtual-reassembly"))
Matus Fabian06596c52017-06-06 04:53:28 -07008507 self.clear_nat64()
8508
Matus Fabian8ebe6252017-11-06 05:04:53 -08008509
8510class TestDSlite(MethodHolder):
8511 """ DS-Lite Test Cases """
8512
8513 @classmethod
8514 def setUpClass(cls):
8515 super(TestDSlite, cls).setUpClass()
8516
8517 try:
8518 cls.nat_addr = '10.0.0.3'
8519 cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
8520
Matus Fabianad1f3e12018-11-28 21:26:34 -08008521 cls.create_pg_interfaces(range(3))
Matus Fabian8ebe6252017-11-06 05:04:53 -08008522 cls.pg0.admin_up()
8523 cls.pg0.config_ip4()
8524 cls.pg0.resolve_arp()
8525 cls.pg1.admin_up()
8526 cls.pg1.config_ip6()
8527 cls.pg1.generate_remote_hosts(2)
8528 cls.pg1.configure_ipv6_neighbors()
Matus Fabianad1f3e12018-11-28 21:26:34 -08008529 cls.pg2.admin_up()
8530 cls.pg2.config_ip4()
8531 cls.pg2.resolve_arp()
Matus Fabian8ebe6252017-11-06 05:04:53 -08008532
8533 except Exception:
8534 super(TestDSlite, cls).tearDownClass()
8535 raise
8536
Matus Fabianad1f3e12018-11-28 21:26:34 -08008537 def verify_syslog_apmadd(self, data, isaddr, isport, xsaddr, xsport,
8538 sv6enc, proto):
8539 message = data.decode('utf-8')
8540 try:
8541 message = SyslogMessage.parse(message)
Paul Vinciguerrad7532092019-01-14 08:51:17 -08008542 except ParseError as e:
8543 self.logger.error(e)
8544 else:
Matus Fabianad1f3e12018-11-28 21:26:34 -08008545 self.assertEqual(message.severity, SyslogSeverity.info)
8546 self.assertEqual(message.appname, 'NAT')
8547 self.assertEqual(message.msgid, 'APMADD')
8548 sd_params = message.sd.get('napmap')
8549 self.assertTrue(sd_params is not None)
8550 self.assertEqual(sd_params.get('IATYP'), 'IPv4')
8551 self.assertEqual(sd_params.get('ISADDR'), isaddr)
8552 self.assertEqual(sd_params.get('ISPORT'), "%d" % isport)
8553 self.assertEqual(sd_params.get('XATYP'), 'IPv4')
8554 self.assertEqual(sd_params.get('XSADDR'), xsaddr)
8555 self.assertEqual(sd_params.get('XSPORT'), "%d" % xsport)
8556 self.assertEqual(sd_params.get('PROTO'), "%d" % proto)
8557 self.assertTrue(sd_params.get('SSUBIX') is not None)
8558 self.assertEqual(sd_params.get('SV6ENC'), sv6enc)
Matus Fabianad1f3e12018-11-28 21:26:34 -08008559
Matus Fabian8ebe6252017-11-06 05:04:53 -08008560 def test_dslite(self):
8561 """ Test DS-Lite """
Matus Fabian69ce30d2018-08-22 01:27:10 -07008562 nat_config = self.vapi.nat_show_config()
8563 self.assertEqual(0, nat_config.dslite_ce)
8564
Matus Fabian8ebe6252017-11-06 05:04:53 -08008565 self.vapi.dslite_add_del_pool_addr_range(self.nat_addr_n,
8566 self.nat_addr_n)
8567 aftr_ip4 = '192.0.0.1'
8568 aftr_ip4_n = socket.inet_pton(socket.AF_INET, aftr_ip4)
8569 aftr_ip6 = '2001:db8:85a3::8a2e:370:1'
8570 aftr_ip6_n = socket.inet_pton(socket.AF_INET6, aftr_ip6)
8571 self.vapi.dslite_set_aftr_addr(aftr_ip6_n, aftr_ip4_n)
Ole Troanf159f582019-02-28 20:20:47 +01008572 self.vapi.syslog_set_sender(self.pg2.local_ip4n, self.pg2.remote_ip4n)
Matus Fabian8ebe6252017-11-06 05:04:53 -08008573
8574 # UDP
8575 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8576 IPv6(dst=aftr_ip6, src=self.pg1.remote_hosts[0].ip6) /
8577 IP(dst=self.pg0.remote_ip4, src='192.168.1.1') /
8578 UDP(sport=20000, dport=10000))
8579 self.pg1.add_stream(p)
8580 self.pg_enable_capture(self.pg_interfaces)
8581 self.pg_start()
8582 capture = self.pg0.get_capture(1)
8583 capture = capture[0]
8584 self.assertFalse(capture.haslayer(IPv6))
8585 self.assertEqual(capture[IP].src, self.nat_addr)
8586 self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
8587 self.assertNotEqual(capture[UDP].sport, 20000)
8588 self.assertEqual(capture[UDP].dport, 10000)
Klement Sekerad81ae412018-05-16 10:52:54 +02008589 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08008590 out_port = capture[UDP].sport
Matus Fabianad1f3e12018-11-28 21:26:34 -08008591 capture = self.pg2.get_capture(1)
8592 self.verify_syslog_apmadd(capture[0][Raw].load, '192.168.1.1',
8593 20000, self.nat_addr, out_port,
8594 self.pg1.remote_hosts[0].ip6, IP_PROTOS.udp)
Matus Fabian8ebe6252017-11-06 05:04:53 -08008595
8596 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8597 IP(dst=self.nat_addr, src=self.pg0.remote_ip4) /
8598 UDP(sport=10000, dport=out_port))
8599 self.pg0.add_stream(p)
8600 self.pg_enable_capture(self.pg_interfaces)
8601 self.pg_start()
8602 capture = self.pg1.get_capture(1)
8603 capture = capture[0]
8604 self.assertEqual(capture[IPv6].src, aftr_ip6)
8605 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[0].ip6)
8606 self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
8607 self.assertEqual(capture[IP].dst, '192.168.1.1')
8608 self.assertEqual(capture[UDP].sport, 10000)
8609 self.assertEqual(capture[UDP].dport, 20000)
Klement Sekerad81ae412018-05-16 10:52:54 +02008610 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08008611
8612 # TCP
8613 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8614 IPv6(dst=aftr_ip6, src=self.pg1.remote_hosts[1].ip6) /
8615 IP(dst=self.pg0.remote_ip4, src='192.168.1.1') /
8616 TCP(sport=20001, dport=10001))
8617 self.pg1.add_stream(p)
8618 self.pg_enable_capture(self.pg_interfaces)
8619 self.pg_start()
8620 capture = self.pg0.get_capture(1)
8621 capture = capture[0]
8622 self.assertFalse(capture.haslayer(IPv6))
8623 self.assertEqual(capture[IP].src, self.nat_addr)
8624 self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
8625 self.assertNotEqual(capture[TCP].sport, 20001)
8626 self.assertEqual(capture[TCP].dport, 10001)
Klement Sekerad81ae412018-05-16 10:52:54 +02008627 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08008628 out_port = capture[TCP].sport
8629
8630 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8631 IP(dst=self.nat_addr, src=self.pg0.remote_ip4) /
8632 TCP(sport=10001, dport=out_port))
8633 self.pg0.add_stream(p)
8634 self.pg_enable_capture(self.pg_interfaces)
8635 self.pg_start()
8636 capture = self.pg1.get_capture(1)
8637 capture = capture[0]
8638 self.assertEqual(capture[IPv6].src, aftr_ip6)
8639 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[1].ip6)
8640 self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
8641 self.assertEqual(capture[IP].dst, '192.168.1.1')
8642 self.assertEqual(capture[TCP].sport, 10001)
8643 self.assertEqual(capture[TCP].dport, 20001)
Klement Sekerad81ae412018-05-16 10:52:54 +02008644 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08008645
8646 # ICMP
8647 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8648 IPv6(dst=aftr_ip6, src=self.pg1.remote_hosts[1].ip6) /
8649 IP(dst=self.pg0.remote_ip4, src='192.168.1.1') /
8650 ICMP(id=4000, type='echo-request'))
8651 self.pg1.add_stream(p)
8652 self.pg_enable_capture(self.pg_interfaces)
8653 self.pg_start()
8654 capture = self.pg0.get_capture(1)
8655 capture = capture[0]
8656 self.assertFalse(capture.haslayer(IPv6))
8657 self.assertEqual(capture[IP].src, self.nat_addr)
8658 self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
8659 self.assertNotEqual(capture[ICMP].id, 4000)
Klement Sekerad81ae412018-05-16 10:52:54 +02008660 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08008661 out_id = capture[ICMP].id
8662
8663 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8664 IP(dst=self.nat_addr, src=self.pg0.remote_ip4) /
8665 ICMP(id=out_id, type='echo-reply'))
8666 self.pg0.add_stream(p)
8667 self.pg_enable_capture(self.pg_interfaces)
8668 self.pg_start()
8669 capture = self.pg1.get_capture(1)
8670 capture = capture[0]
8671 self.assertEqual(capture[IPv6].src, aftr_ip6)
8672 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[1].ip6)
8673 self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
8674 self.assertEqual(capture[IP].dst, '192.168.1.1')
8675 self.assertEqual(capture[ICMP].id, 4000)
Klement Sekerad81ae412018-05-16 10:52:54 +02008676 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08008677
Matus Fabian331acc62017-12-08 03:38:51 -08008678 # ping DS-Lite AFTR tunnel endpoint address
8679 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8680 IPv6(src=self.pg1.remote_hosts[1].ip6, dst=aftr_ip6) /
8681 ICMPv6EchoRequest())
8682 self.pg1.add_stream(p)
8683 self.pg_enable_capture(self.pg_interfaces)
8684 self.pg_start()
8685 capture = self.pg1.get_capture(1)
Matus Fabian331acc62017-12-08 03:38:51 -08008686 capture = capture[0]
8687 self.assertEqual(capture[IPv6].src, aftr_ip6)
8688 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[1].ip6)
8689 self.assertTrue(capture.haslayer(ICMPv6EchoReply))
8690
Matus Fabianfd0d5082018-12-18 01:08:51 -08008691 b4s = self.statistics.get_counter('/dslite/total-b4s')
8692 self.assertEqual(b4s[0][0], 2)
8693 sessions = self.statistics.get_counter('/dslite/total-sessions')
8694 self.assertEqual(sessions[0][0], 3)
8695
Matus Fabian8ebe6252017-11-06 05:04:53 -08008696 def tearDown(self):
8697 super(TestDSlite, self).tearDown()
8698 if not self.vpp_dead:
8699 self.logger.info(self.vapi.cli("show dslite pool"))
8700 self.logger.info(
8701 self.vapi.cli("show dslite aftr-tunnel-endpoint-address"))
8702 self.logger.info(self.vapi.cli("show dslite sessions"))
8703
Juraj Slobodac5c6a332018-01-09 16:08:32 +01008704
8705class TestDSliteCE(MethodHolder):
8706 """ DS-Lite CE Test Cases """
8707
8708 @classmethod
8709 def setUpConstants(cls):
8710 super(TestDSliteCE, cls).setUpConstants()
8711 cls.vpp_cmdline.extend(["nat", "{", "dslite ce", "}"])
8712
8713 @classmethod
8714 def setUpClass(cls):
8715 super(TestDSliteCE, cls).setUpClass()
8716
8717 try:
8718 cls.create_pg_interfaces(range(2))
8719 cls.pg0.admin_up()
8720 cls.pg0.config_ip4()
8721 cls.pg0.resolve_arp()
8722 cls.pg1.admin_up()
8723 cls.pg1.config_ip6()
8724 cls.pg1.generate_remote_hosts(1)
8725 cls.pg1.configure_ipv6_neighbors()
8726
8727 except Exception:
8728 super(TestDSliteCE, cls).tearDownClass()
8729 raise
8730
8731 def test_dslite_ce(self):
8732 """ Test DS-Lite CE """
8733
Matus Fabian69ce30d2018-08-22 01:27:10 -07008734 nat_config = self.vapi.nat_show_config()
8735 self.assertEqual(1, nat_config.dslite_ce)
8736
Juraj Slobodac5c6a332018-01-09 16:08:32 +01008737 b4_ip4 = '192.0.0.2'
8738 b4_ip4_n = socket.inet_pton(socket.AF_INET, b4_ip4)
8739 b4_ip6 = '2001:db8:62aa::375e:f4c1:1'
8740 b4_ip6_n = socket.inet_pton(socket.AF_INET6, b4_ip6)
8741 self.vapi.dslite_set_b4_addr(b4_ip6_n, b4_ip4_n)
8742
8743 aftr_ip4 = '192.0.0.1'
8744 aftr_ip4_n = socket.inet_pton(socket.AF_INET, aftr_ip4)
8745 aftr_ip6 = '2001:db8:85a3::8a2e:370:1'
8746 aftr_ip6_n = socket.inet_pton(socket.AF_INET6, aftr_ip6)
8747 self.vapi.dslite_set_aftr_addr(aftr_ip6_n, aftr_ip4_n)
8748
8749 self.vapi.ip_add_del_route(dst_address=aftr_ip6_n,
8750 dst_address_length=128,
8751 next_hop_address=self.pg1.remote_ip6n,
8752 next_hop_sw_if_index=self.pg1.sw_if_index,
8753 is_ipv6=1)
8754
8755 # UDP encapsulation
8756 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8757 IP(dst=self.pg1.remote_ip4, src=self.pg0.remote_ip4) /
8758 UDP(sport=10000, dport=20000))
8759 self.pg0.add_stream(p)
8760 self.pg_enable_capture(self.pg_interfaces)
8761 self.pg_start()
8762 capture = self.pg1.get_capture(1)
8763 capture = capture[0]
8764 self.assertEqual(capture[IPv6].src, b4_ip6)
8765 self.assertEqual(capture[IPv6].dst, aftr_ip6)
8766 self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
8767 self.assertEqual(capture[IP].dst, self.pg1.remote_ip4)
8768 self.assertEqual(capture[UDP].sport, 10000)
8769 self.assertEqual(capture[UDP].dport, 20000)
Klement Sekerad81ae412018-05-16 10:52:54 +02008770 self.assert_packet_checksums_valid(capture)
Juraj Slobodac5c6a332018-01-09 16:08:32 +01008771
8772 # UDP decapsulation
8773 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8774 IPv6(dst=b4_ip6, src=aftr_ip6) /
8775 IP(dst=self.pg0.remote_ip4, src=self.pg1.remote_ip4) /
8776 UDP(sport=20000, dport=10000))
8777 self.pg1.add_stream(p)
8778 self.pg_enable_capture(self.pg_interfaces)
8779 self.pg_start()
8780 capture = self.pg0.get_capture(1)
8781 capture = capture[0]
8782 self.assertFalse(capture.haslayer(IPv6))
8783 self.assertEqual(capture[IP].src, self.pg1.remote_ip4)
8784 self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
8785 self.assertEqual(capture[UDP].sport, 20000)
8786 self.assertEqual(capture[UDP].dport, 10000)
Klement Sekerad81ae412018-05-16 10:52:54 +02008787 self.assert_packet_checksums_valid(capture)
Juraj Slobodac5c6a332018-01-09 16:08:32 +01008788
8789 # ping DS-Lite B4 tunnel endpoint address
8790 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8791 IPv6(src=self.pg1.remote_hosts[0].ip6, dst=b4_ip6) /
8792 ICMPv6EchoRequest())
8793 self.pg1.add_stream(p)
8794 self.pg_enable_capture(self.pg_interfaces)
8795 self.pg_start()
8796 capture = self.pg1.get_capture(1)
Juraj Slobodac5c6a332018-01-09 16:08:32 +01008797 capture = capture[0]
8798 self.assertEqual(capture[IPv6].src, b4_ip6)
8799 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[0].ip6)
8800 self.assertTrue(capture.haslayer(ICMPv6EchoReply))
8801
8802 def tearDown(self):
8803 super(TestDSliteCE, self).tearDown()
8804 if not self.vpp_dead:
8805 self.logger.info(
8806 self.vapi.cli("show dslite aftr-tunnel-endpoint-address"))
8807 self.logger.info(
8808 self.vapi.cli("show dslite b4-tunnel-endpoint-address"))
8809
Matus Fabianf2a23cc2018-01-22 03:41:53 -08008810
8811class TestNAT66(MethodHolder):
8812 """ NAT66 Test Cases """
8813
8814 @classmethod
8815 def setUpClass(cls):
8816 super(TestNAT66, cls).setUpClass()
8817
8818 try:
8819 cls.nat_addr = 'fd01:ff::2'
8820 cls.nat_addr_n = socket.inet_pton(socket.AF_INET6, cls.nat_addr)
8821
8822 cls.create_pg_interfaces(range(2))
8823 cls.interfaces = list(cls.pg_interfaces)
8824
8825 for i in cls.interfaces:
8826 i.admin_up()
8827 i.config_ip6()
8828 i.configure_ipv6_neighbors()
8829
8830 except Exception:
8831 super(TestNAT66, cls).tearDownClass()
8832 raise
8833
8834 def test_static(self):
8835 """ 1:1 NAT66 test """
8836 self.vapi.nat66_add_del_interface(self.pg0.sw_if_index)
8837 self.vapi.nat66_add_del_interface(self.pg1.sw_if_index, is_inside=0)
8838 self.vapi.nat66_add_del_static_mapping(self.pg0.remote_ip6n,
8839 self.nat_addr_n)
8840
8841 # in2out
8842 pkts = []
8843 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8844 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
8845 TCP())
8846 pkts.append(p)
8847 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8848 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
8849 UDP())
8850 pkts.append(p)
8851 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8852 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
8853 ICMPv6EchoRequest())
8854 pkts.append(p)
8855 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8856 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
8857 GRE() / IP() / TCP())
8858 pkts.append(p)
8859 self.pg0.add_stream(pkts)
8860 self.pg_enable_capture(self.pg_interfaces)
8861 self.pg_start()
8862 capture = self.pg1.get_capture(len(pkts))
8863 for packet in capture:
8864 try:
8865 self.assertEqual(packet[IPv6].src, self.nat_addr)
8866 self.assertEqual(packet[IPv6].dst, self.pg1.remote_ip6)
Klement Sekerad81ae412018-05-16 10:52:54 +02008867 self.assert_packet_checksums_valid(packet)
Matus Fabianf2a23cc2018-01-22 03:41:53 -08008868 except:
8869 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8870 raise
8871
8872 # out2in
8873 pkts = []
8874 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8875 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
8876 TCP())
8877 pkts.append(p)
8878 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8879 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
8880 UDP())
8881 pkts.append(p)
8882 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8883 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
8884 ICMPv6EchoReply())
8885 pkts.append(p)
8886 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8887 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
8888 GRE() / IP() / TCP())
8889 pkts.append(p)
8890 self.pg1.add_stream(pkts)
8891 self.pg_enable_capture(self.pg_interfaces)
8892 self.pg_start()
8893 capture = self.pg0.get_capture(len(pkts))
8894 for packet in capture:
8895 try:
8896 self.assertEqual(packet[IPv6].src, self.pg1.remote_ip6)
8897 self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
Klement Sekerad81ae412018-05-16 10:52:54 +02008898 self.assert_packet_checksums_valid(packet)
Matus Fabianf2a23cc2018-01-22 03:41:53 -08008899 except:
8900 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8901 raise
8902
8903 sm = self.vapi.nat66_static_mapping_dump()
8904 self.assertEqual(len(sm), 1)
8905 self.assertEqual(sm[0].total_pkts, 8)
8906
Juraj Sloboda9341e342018-04-13 12:00:46 +02008907 def test_check_no_translate(self):
8908 """ NAT66 translate only when egress interface is outside interface """
8909 self.vapi.nat66_add_del_interface(self.pg0.sw_if_index)
8910 self.vapi.nat66_add_del_interface(self.pg1.sw_if_index)
8911 self.vapi.nat66_add_del_static_mapping(self.pg0.remote_ip6n,
8912 self.nat_addr_n)
8913
8914 # in2out
8915 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8916 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
8917 UDP())
8918 self.pg0.add_stream([p])
8919 self.pg_enable_capture(self.pg_interfaces)
8920 self.pg_start()
8921 capture = self.pg1.get_capture(1)
8922 packet = capture[0]
8923 try:
8924 self.assertEqual(packet[IPv6].src, self.pg0.remote_ip6)
8925 self.assertEqual(packet[IPv6].dst, self.pg1.remote_ip6)
8926 except:
8927 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8928 raise
8929
Matus Fabianf2a23cc2018-01-22 03:41:53 -08008930 def clear_nat66(self):
8931 """
8932 Clear NAT66 configuration.
8933 """
8934 interfaces = self.vapi.nat66_interface_dump()
8935 for intf in interfaces:
8936 self.vapi.nat66_add_del_interface(intf.sw_if_index,
8937 intf.is_inside,
8938 is_add=0)
8939
8940 static_mappings = self.vapi.nat66_static_mapping_dump()
8941 for sm in static_mappings:
8942 self.vapi.nat66_add_del_static_mapping(sm.local_ip_address,
8943 sm.external_ip_address,
8944 sm.vrf_id,
8945 is_add=0)
8946
8947 def tearDown(self):
8948 super(TestNAT66, self).tearDown()
8949 if not self.vpp_dead:
8950 self.logger.info(self.vapi.cli("show nat66 interfaces"))
8951 self.logger.info(self.vapi.cli("show nat66 static mappings"))
8952 self.clear_nat66()
8953
Klement Sekerad81ae412018-05-16 10:52:54 +02008954
Matus Fabiande886752016-12-07 03:38:19 -08008955if __name__ == '__main__':
8956 unittest.main(testRunner=VppTestRunner)