blob: 69a18f8a097eafec7b98646b8705ed9c04c3b97e [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
Jakub Grajciare63325e2019-03-01 08:55:49 +010029from vpp_ip import VppIpAddress, VppIpPrefix
Matus Fabian34931eb2019-02-26 09:05:23 -080030from scapy.all import bind_layers, Packet, ByteEnumField, ShortField, \
31 IPField, IntField, LongField, XByteField, FlagsField, FieldLenField, \
32 PacketListField
33
34
35# NAT HA protocol event data
36class Event(Packet):
37 name = "Event"
38 fields_desc = [ByteEnumField("event_type", None,
39 {1: "add", 2: "del", 3: "refresh"}),
40 ByteEnumField("protocol", None,
41 {0: "udp", 1: "tcp", 2: "icmp"}),
42 ShortField("flags", 0),
43 IPField("in_addr", None),
44 IPField("out_addr", None),
45 ShortField("in_port", None),
46 ShortField("out_port", None),
47 IPField("eh_addr", None),
48 IPField("ehn_addr", None),
49 ShortField("eh_port", None),
50 ShortField("ehn_port", None),
51 IntField("fib_index", None),
52 IntField("total_pkts", 0),
53 LongField("total_bytes", 0)]
54
55 def extract_padding(self, s):
56 return "", s
57
58
59# NAT HA protocol header
60class HANATStateSync(Packet):
61 name = "HA NAT state sync"
62 fields_desc = [XByteField("version", 1),
63 FlagsField("flags", 0, 8, ['ACK']),
64 FieldLenField("count", None, count_of="events"),
65 IntField("sequence_number", 1),
66 IntField("thread_index", 0),
67 PacketListField("events", [], Event,
Ole Troan9a475372019-03-05 16:58:24 +010068 count_from=lambda pkt: pkt.count)]
Matus Fabiande886752016-12-07 03:38:19 -080069
70
Martin Gálikd7f75cd2017-03-27 06:02:47 -070071class MethodHolder(VppTestCase):
Matus Fabian2ba92e32017-08-21 07:05:03 -070072 """ NAT create capture and verify method holder """
Matus Fabiande886752016-12-07 03:38:19 -080073
Matus Fabiana6110b62018-06-13 05:39:07 -070074 def clear_nat44(self):
75 """
76 Clear NAT44 configuration.
77 """
78 if hasattr(self, 'pg7') and hasattr(self, 'pg8'):
79 # I found no elegant way to do this
80 self.vapi.ip_add_del_route(
81 dst_address=self.pg7.remote_ip4n,
82 dst_address_length=32,
83 next_hop_address=self.pg7.remote_ip4n,
84 next_hop_sw_if_index=self.pg7.sw_if_index,
85 is_add=0)
86 self.vapi.ip_add_del_route(
87 dst_address=self.pg8.remote_ip4n,
88 dst_address_length=32,
89 next_hop_address=self.pg8.remote_ip4n,
90 next_hop_sw_if_index=self.pg8.sw_if_index,
91 is_add=0)
92
93 for intf in [self.pg7, self.pg8]:
Neale Ranns37029302018-08-10 05:30:06 -070094 self.vapi.ip_neighbor_add_del(
95 intf.sw_if_index,
96 intf.remote_mac,
97 intf.remote_ip4,
98 flags=(VppEnum.vl_api_ip_neighbor_flags_t.
99 IP_API_NEIGHBOR_FLAG_STATIC),
100 is_add=0)
Matus Fabiana6110b62018-06-13 05:39:07 -0700101
102 if self.pg7.has_ip4_config:
103 self.pg7.unconfig_ip4()
104
105 self.vapi.nat44_forwarding_enable_disable(0)
106
107 interfaces = self.vapi.nat44_interface_addr_dump()
108 for intf in interfaces:
Ole Troane1ade682019-03-04 23:55:43 +0100109 self.vapi.nat44_add_del_interface_addr(intf.sw_if_index,
110 twice_nat=intf.twice_nat,
111 is_add=0)
Matus Fabiana6110b62018-06-13 05:39:07 -0700112
Ole Troane1ade682019-03-04 23:55:43 +0100113 self.vapi.nat_ipfix_enable_disable(enable=0,
114 src_port=self.ipfix_src_port,
115 domain_id=self.ipfix_domain_id)
Matus Fabiana6110b62018-06-13 05:39:07 -0700116 self.ipfix_src_port = 4739
117 self.ipfix_domain_id = 1
118
Matus Fabianad1f3e12018-11-28 21:26:34 -0800119 self.vapi.syslog_set_filter(SYSLOG_SEVERITY.EMERG)
120
Matus Fabian34931eb2019-02-26 09:05:23 -0800121 self.vapi.nat_ha_set_listener('0.0.0.0', 0)
122 self.vapi.nat_ha_set_failover('0.0.0.0', 0)
123
Matus Fabiana6110b62018-06-13 05:39:07 -0700124 interfaces = self.vapi.nat44_interface_dump()
125 for intf in interfaces:
126 if intf.is_inside > 1:
127 self.vapi.nat44_interface_add_del_feature(intf.sw_if_index,
128 0,
129 is_add=0)
130 self.vapi.nat44_interface_add_del_feature(intf.sw_if_index,
131 intf.is_inside,
132 is_add=0)
133
134 interfaces = self.vapi.nat44_interface_output_feature_dump()
135 for intf in interfaces:
136 self.vapi.nat44_interface_add_del_output_feature(intf.sw_if_index,
137 intf.is_inside,
138 is_add=0)
139
140 static_mappings = self.vapi.nat44_static_mapping_dump()
141 for sm in static_mappings:
142 self.vapi.nat44_add_del_static_mapping(
143 sm.local_ip_address,
144 sm.external_ip_address,
145 local_port=sm.local_port,
146 external_port=sm.external_port,
147 addr_only=sm.addr_only,
148 vrf_id=sm.vrf_id,
149 protocol=sm.protocol,
150 twice_nat=sm.twice_nat,
151 self_twice_nat=sm.self_twice_nat,
152 out2in_only=sm.out2in_only,
153 tag=sm.tag,
154 external_sw_if_index=sm.external_sw_if_index,
155 is_add=0)
156
157 lb_static_mappings = self.vapi.nat44_lb_static_mapping_dump()
158 for lb_sm in lb_static_mappings:
159 self.vapi.nat44_add_del_lb_static_mapping(
160 lb_sm.external_addr,
161 lb_sm.external_port,
162 lb_sm.protocol,
Matus Fabiana6110b62018-06-13 05:39:07 -0700163 twice_nat=lb_sm.twice_nat,
164 self_twice_nat=lb_sm.self_twice_nat,
165 out2in_only=lb_sm.out2in_only,
166 tag=lb_sm.tag,
167 is_add=0,
168 local_num=0,
169 locals=[])
170
171 identity_mappings = self.vapi.nat44_identity_mapping_dump()
172 for id_m in identity_mappings:
173 self.vapi.nat44_add_del_identity_mapping(
174 addr_only=id_m.addr_only,
175 ip=id_m.ip_address,
176 port=id_m.port,
177 sw_if_index=id_m.sw_if_index,
178 vrf_id=id_m.vrf_id,
179 protocol=id_m.protocol,
180 is_add=0)
181
182 adresses = self.vapi.nat44_address_dump()
183 for addr in adresses:
184 self.vapi.nat44_add_del_address_range(addr.ip_address,
185 addr.ip_address,
186 twice_nat=addr.twice_nat,
187 is_add=0)
188
189 self.vapi.nat_set_reass()
190 self.vapi.nat_set_reass(is_ip6=1)
Matus Fabian68ba8802018-08-08 05:52:47 -0700191 self.verify_no_nat44_user()
Matus Fabian878c6462018-08-23 00:33:35 -0700192 self.vapi.nat_set_timeouts()
Matus Fabian5d28c7a2018-09-04 03:55:45 -0700193 self.vapi.nat_set_addr_and_port_alloc_alg()
Matus Fabianbb4e0222018-09-13 02:36:25 -0700194 self.vapi.nat_set_mss_clamping()
Matus Fabiana6110b62018-06-13 05:39:07 -0700195
196 def nat44_add_static_mapping(self, local_ip, external_ip='0.0.0.0',
197 local_port=0, external_port=0, vrf_id=0,
198 is_add=1, external_sw_if_index=0xFFFFFFFF,
199 proto=0, twice_nat=0, self_twice_nat=0,
200 out2in_only=0, tag=""):
201 """
202 Add/delete NAT44 static mapping
203
204 :param local_ip: Local IP address
205 :param external_ip: External IP address
206 :param local_port: Local port number (Optional)
207 :param external_port: External port number (Optional)
208 :param vrf_id: VRF ID (Default 0)
209 :param is_add: 1 if add, 0 if delete (Default add)
210 :param external_sw_if_index: External interface instead of IP address
211 :param proto: IP protocol (Mandatory if port specified)
212 :param twice_nat: 1 if translate external host address and port
213 :param self_twice_nat: 1 if translate external host address and port
214 whenever external host address equals
215 local address of internal host
216 :param out2in_only: if 1 rule is matching only out2in direction
217 :param tag: Opaque string tag
218 """
219 addr_only = 1
220 if local_port and external_port:
221 addr_only = 0
222 l_ip = socket.inet_pton(socket.AF_INET, local_ip)
223 e_ip = socket.inet_pton(socket.AF_INET, external_ip)
224 self.vapi.nat44_add_del_static_mapping(
225 l_ip,
226 e_ip,
227 external_sw_if_index,
228 local_port,
229 external_port,
230 addr_only,
231 vrf_id,
232 proto,
233 twice_nat,
234 self_twice_nat,
235 out2in_only,
236 tag,
237 is_add)
238
239 def nat44_add_address(self, ip, is_add=1, vrf_id=0xFFFFFFFF, twice_nat=0):
240 """
241 Add/delete NAT44 address
242
243 :param ip: IP address
244 :param is_add: 1 if add, 0 if delete (Default add)
245 :param twice_nat: twice NAT address for extenal hosts
246 """
247 nat_addr = socket.inet_pton(socket.AF_INET, ip)
248 self.vapi.nat44_add_del_address_range(nat_addr, nat_addr, is_add,
249 vrf_id=vrf_id,
250 twice_nat=twice_nat)
251
Juraj Slobodacba69362017-12-19 02:09:32 +0100252 def create_stream_in(self, in_if, out_if, dst_ip=None, ttl=64):
Matus Fabiande886752016-12-07 03:38:19 -0800253 """
254 Create packet stream for inside network
255
256 :param in_if: Inside interface
257 :param out_if: Outside interface
Juraj Slobodacba69362017-12-19 02:09:32 +0100258 :param dst_ip: Destination address
Juraj Slobodab33f4132017-02-08 23:54:21 -0800259 :param ttl: TTL of generated packets
Matus Fabiande886752016-12-07 03:38:19 -0800260 """
Juraj Slobodacba69362017-12-19 02:09:32 +0100261 if dst_ip is None:
262 dst_ip = out_if.remote_ip4
263
Matus Fabiande886752016-12-07 03:38:19 -0800264 pkts = []
265 # TCP
266 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
Juraj Slobodacba69362017-12-19 02:09:32 +0100267 IP(src=in_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Matus Fabian06596c52017-06-06 04:53:28 -0700268 TCP(sport=self.tcp_port_in, dport=20))
Matus Fabiande886752016-12-07 03:38:19 -0800269 pkts.append(p)
270
271 # UDP
272 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
Juraj Slobodacba69362017-12-19 02:09:32 +0100273 IP(src=in_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Matus Fabian06596c52017-06-06 04:53:28 -0700274 UDP(sport=self.udp_port_in, dport=20))
Matus Fabiande886752016-12-07 03:38:19 -0800275 pkts.append(p)
276
277 # ICMP
278 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
Juraj Slobodacba69362017-12-19 02:09:32 +0100279 IP(src=in_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Matus Fabiande886752016-12-07 03:38:19 -0800280 ICMP(id=self.icmp_id_in, type='echo-request'))
281 pkts.append(p)
282
283 return pkts
284
Matus Fabian428dc912017-06-21 06:15:18 -0700285 def compose_ip6(self, ip4, pref, plen):
286 """
287 Compose IPv4-embedded IPv6 addresses
288
289 :param ip4: IPv4 address
290 :param pref: IPv6 prefix
291 :param plen: IPv6 prefix length
292 :returns: IPv4-embedded IPv6 addresses
293 """
294 pref_n = list(socket.inet_pton(socket.AF_INET6, pref))
295 ip4_n = list(socket.inet_pton(socket.AF_INET, ip4))
296 if plen == 32:
297 pref_n[4] = ip4_n[0]
298 pref_n[5] = ip4_n[1]
299 pref_n[6] = ip4_n[2]
300 pref_n[7] = ip4_n[3]
301 elif plen == 40:
302 pref_n[5] = ip4_n[0]
303 pref_n[6] = ip4_n[1]
304 pref_n[7] = ip4_n[2]
305 pref_n[9] = ip4_n[3]
306 elif plen == 48:
307 pref_n[6] = ip4_n[0]
308 pref_n[7] = ip4_n[1]
309 pref_n[9] = ip4_n[2]
310 pref_n[10] = ip4_n[3]
311 elif plen == 56:
312 pref_n[7] = ip4_n[0]
313 pref_n[9] = ip4_n[1]
314 pref_n[10] = ip4_n[2]
315 pref_n[11] = ip4_n[3]
316 elif plen == 64:
317 pref_n[9] = ip4_n[0]
318 pref_n[10] = ip4_n[1]
319 pref_n[11] = ip4_n[2]
320 pref_n[12] = ip4_n[3]
321 elif plen == 96:
322 pref_n[12] = ip4_n[0]
323 pref_n[13] = ip4_n[1]
324 pref_n[14] = ip4_n[2]
325 pref_n[15] = ip4_n[3]
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700326 packed_pref_n = b''.join([scapy.compat.chb(x) for x in pref_n])
327 return socket.inet_ntop(socket.AF_INET6, packed_pref_n)
Matus Fabian428dc912017-06-21 06:15:18 -0700328
Juraj Slobodacba69362017-12-19 02:09:32 +0100329 def extract_ip4(self, ip6, plen):
330 """
331 Extract IPv4 address embedded in IPv6 addresses
332
333 :param ip6: IPv6 address
334 :param plen: IPv6 prefix length
335 :returns: extracted IPv4 address
336 """
337 ip6_n = list(socket.inet_pton(socket.AF_INET6, ip6))
338 ip4_n = [None] * 4
339 if plen == 32:
340 ip4_n[0] = ip6_n[4]
341 ip4_n[1] = ip6_n[5]
342 ip4_n[2] = ip6_n[6]
343 ip4_n[3] = ip6_n[7]
344 elif plen == 40:
345 ip4_n[0] = ip6_n[5]
346 ip4_n[1] = ip6_n[6]
347 ip4_n[2] = ip6_n[7]
348 ip4_n[3] = ip6_n[9]
349 elif plen == 48:
350 ip4_n[0] = ip6_n[6]
351 ip4_n[1] = ip6_n[7]
352 ip4_n[2] = ip6_n[9]
353 ip4_n[3] = ip6_n[10]
354 elif plen == 56:
355 ip4_n[0] = ip6_n[7]
356 ip4_n[1] = ip6_n[9]
357 ip4_n[2] = ip6_n[10]
358 ip4_n[3] = ip6_n[11]
359 elif plen == 64:
360 ip4_n[0] = ip6_n[9]
361 ip4_n[1] = ip6_n[10]
362 ip4_n[2] = ip6_n[11]
363 ip4_n[3] = ip6_n[12]
364 elif plen == 96:
365 ip4_n[0] = ip6_n[12]
366 ip4_n[1] = ip6_n[13]
367 ip4_n[2] = ip6_n[14]
368 ip4_n[3] = ip6_n[15]
369 return socket.inet_ntop(socket.AF_INET, ''.join(ip4_n))
370
Matus Fabian428dc912017-06-21 06:15:18 -0700371 def create_stream_in_ip6(self, in_if, out_if, hlim=64, pref=None, plen=0):
Matus Fabian06596c52017-06-06 04:53:28 -0700372 """
373 Create IPv6 packet stream for inside network
374
375 :param in_if: Inside interface
376 :param out_if: Outside interface
377 :param ttl: Hop Limit of generated packets
Matus Fabian428dc912017-06-21 06:15:18 -0700378 :param pref: NAT64 prefix
379 :param plen: NAT64 prefix length
Matus Fabian06596c52017-06-06 04:53:28 -0700380 """
381 pkts = []
Matus Fabian428dc912017-06-21 06:15:18 -0700382 if pref is None:
383 dst = ''.join(['64:ff9b::', out_if.remote_ip4])
384 else:
385 dst = self.compose_ip6(out_if.remote_ip4, pref, plen)
386
Matus Fabian06596c52017-06-06 04:53:28 -0700387 # TCP
388 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
389 IPv6(src=in_if.remote_ip6, dst=dst, hlim=hlim) /
390 TCP(sport=self.tcp_port_in, dport=20))
391 pkts.append(p)
392
393 # UDP
394 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
395 IPv6(src=in_if.remote_ip6, dst=dst, hlim=hlim) /
396 UDP(sport=self.udp_port_in, dport=20))
397 pkts.append(p)
398
399 # ICMP
400 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
401 IPv6(src=in_if.remote_ip6, dst=dst, hlim=hlim) /
402 ICMPv6EchoRequest(id=self.icmp_id_in))
403 pkts.append(p)
404
405 return pkts
406
Juraj Sloboda7b929792017-11-23 13:20:48 +0100407 def create_stream_out(self, out_if, dst_ip=None, ttl=64,
408 use_inside_ports=False):
Matus Fabiande886752016-12-07 03:38:19 -0800409 """
410 Create packet stream for outside network
411
412 :param out_if: Outside interface
Matus Fabian2ba92e32017-08-21 07:05:03 -0700413 :param dst_ip: Destination IP address (Default use global NAT address)
Juraj Slobodab33f4132017-02-08 23:54:21 -0800414 :param ttl: TTL of generated packets
Juraj Sloboda7b929792017-11-23 13:20:48 +0100415 :param use_inside_ports: Use inside NAT ports as destination ports
416 instead of outside ports
Matus Fabiande886752016-12-07 03:38:19 -0800417 """
418 if dst_ip is None:
Matus Fabian2ba92e32017-08-21 07:05:03 -0700419 dst_ip = self.nat_addr
Juraj Sloboda7b929792017-11-23 13:20:48 +0100420 if not use_inside_ports:
421 tcp_port = self.tcp_port_out
422 udp_port = self.udp_port_out
423 icmp_id = self.icmp_id_out
424 else:
425 tcp_port = self.tcp_port_in
426 udp_port = self.udp_port_in
427 icmp_id = self.icmp_id_in
Matus Fabiande886752016-12-07 03:38:19 -0800428 pkts = []
429 # TCP
430 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
Juraj Slobodab33f4132017-02-08 23:54:21 -0800431 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Juraj Sloboda7b929792017-11-23 13:20:48 +0100432 TCP(dport=tcp_port, sport=20))
Matus Fabiande886752016-12-07 03:38:19 -0800433 pkts.append(p)
434
435 # UDP
436 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
Juraj Slobodab33f4132017-02-08 23:54:21 -0800437 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Juraj Sloboda7b929792017-11-23 13:20:48 +0100438 UDP(dport=udp_port, sport=20))
Matus Fabiande886752016-12-07 03:38:19 -0800439 pkts.append(p)
440
441 # ICMP
442 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
Juraj Slobodab33f4132017-02-08 23:54:21 -0800443 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Juraj Sloboda7b929792017-11-23 13:20:48 +0100444 ICMP(id=icmp_id, type='echo-reply'))
Matus Fabiande886752016-12-07 03:38:19 -0800445 pkts.append(p)
446
447 return pkts
448
Juraj Slobodacba69362017-12-19 02:09:32 +0100449 def create_stream_out_ip6(self, out_if, src_ip, dst_ip, hl=64):
450 """
451 Create packet stream for outside network
452
453 :param out_if: Outside interface
454 :param dst_ip: Destination IP address (Default use global NAT address)
455 :param hl: HL of generated packets
456 """
457 pkts = []
458 # TCP
459 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
460 IPv6(src=src_ip, dst=dst_ip, hlim=hl) /
461 TCP(dport=self.tcp_port_out, sport=20))
462 pkts.append(p)
463
464 # UDP
465 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
466 IPv6(src=src_ip, dst=dst_ip, hlim=hl) /
467 UDP(dport=self.udp_port_out, sport=20))
468 pkts.append(p)
469
470 # ICMP
471 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
472 IPv6(src=src_ip, dst=dst_ip, hlim=hl) /
473 ICMPv6EchoReply(id=self.icmp_id_out))
474 pkts.append(p)
475
476 return pkts
477
Matus Fabiande886752016-12-07 03:38:19 -0800478 def verify_capture_out(self, capture, nat_ip=None, same_port=False,
Matus Fabian05ca4a32018-09-04 23:45:13 -0700479 dst_ip=None, is_ip6=False):
Matus Fabiande886752016-12-07 03:38:19 -0800480 """
481 Verify captured packets on outside network
482
483 :param capture: Captured packets
Matus Fabian2ba92e32017-08-21 07:05:03 -0700484 :param nat_ip: Translated IP address (Default use global NAT address)
Matus Fabiande886752016-12-07 03:38:19 -0800485 :param same_port: Sorce port number is not translated (Default False)
Matus Fabian06596c52017-06-06 04:53:28 -0700486 :param dst_ip: Destination IP address (Default do not verify)
Juraj Slobodacba69362017-12-19 02:09:32 +0100487 :param is_ip6: If L3 protocol is IPv6 (Default False)
Matus Fabiande886752016-12-07 03:38:19 -0800488 """
Juraj Slobodacba69362017-12-19 02:09:32 +0100489 if is_ip6:
490 IP46 = IPv6
491 ICMP46 = ICMPv6EchoRequest
492 else:
493 IP46 = IP
494 ICMP46 = ICMP
Matus Fabiande886752016-12-07 03:38:19 -0800495 if nat_ip is None:
Matus Fabian2ba92e32017-08-21 07:05:03 -0700496 nat_ip = self.nat_addr
Matus Fabiande886752016-12-07 03:38:19 -0800497 for packet in capture:
498 try:
Juraj Slobodacba69362017-12-19 02:09:32 +0100499 if not is_ip6:
Klement Sekerad81ae412018-05-16 10:52:54 +0200500 self.assert_packet_checksums_valid(packet)
Juraj Slobodacba69362017-12-19 02:09:32 +0100501 self.assertEqual(packet[IP46].src, nat_ip)
Matus Fabian06596c52017-06-06 04:53:28 -0700502 if dst_ip is not None:
Juraj Slobodacba69362017-12-19 02:09:32 +0100503 self.assertEqual(packet[IP46].dst, dst_ip)
Matus Fabiande886752016-12-07 03:38:19 -0800504 if packet.haslayer(TCP):
505 if same_port:
506 self.assertEqual(packet[TCP].sport, self.tcp_port_in)
507 else:
Klement Sekerada505f62017-01-04 12:58:53 +0100508 self.assertNotEqual(
509 packet[TCP].sport, self.tcp_port_in)
Matus Fabiande886752016-12-07 03:38:19 -0800510 self.tcp_port_out = packet[TCP].sport
Klement Sekerad81ae412018-05-16 10:52:54 +0200511 self.assert_packet_checksums_valid(packet)
Matus Fabiande886752016-12-07 03:38:19 -0800512 elif packet.haslayer(UDP):
513 if same_port:
514 self.assertEqual(packet[UDP].sport, self.udp_port_in)
515 else:
Klement Sekerada505f62017-01-04 12:58:53 +0100516 self.assertNotEqual(
517 packet[UDP].sport, self.udp_port_in)
Matus Fabiande886752016-12-07 03:38:19 -0800518 self.udp_port_out = packet[UDP].sport
519 else:
520 if same_port:
Juraj Slobodacba69362017-12-19 02:09:32 +0100521 self.assertEqual(packet[ICMP46].id, self.icmp_id_in)
Matus Fabiande886752016-12-07 03:38:19 -0800522 else:
Juraj Slobodacba69362017-12-19 02:09:32 +0100523 self.assertNotEqual(packet[ICMP46].id, self.icmp_id_in)
524 self.icmp_id_out = packet[ICMP46].id
Klement Sekerad81ae412018-05-16 10:52:54 +0200525 self.assert_packet_checksums_valid(packet)
Matus Fabiande886752016-12-07 03:38:19 -0800526 except:
Klement Sekera9225dee2016-12-12 08:36:58 +0100527 self.logger.error(ppp("Unexpected or invalid packet "
528 "(outside network):", packet))
Matus Fabiande886752016-12-07 03:38:19 -0800529 raise
530
Juraj Slobodacba69362017-12-19 02:09:32 +0100531 def verify_capture_out_ip6(self, capture, nat_ip, same_port=False,
Matus Fabian05ca4a32018-09-04 23:45:13 -0700532 dst_ip=None):
Juraj Slobodacba69362017-12-19 02:09:32 +0100533 """
534 Verify captured packets on outside network
535
536 :param capture: Captured packets
537 :param nat_ip: Translated IP address
538 :param same_port: Sorce port number is not translated (Default False)
Juraj Slobodacba69362017-12-19 02:09:32 +0100539 :param dst_ip: Destination IP address (Default do not verify)
540 """
Matus Fabian05ca4a32018-09-04 23:45:13 -0700541 return self.verify_capture_out(capture, nat_ip, same_port, dst_ip,
542 True)
Juraj Slobodacba69362017-12-19 02:09:32 +0100543
Matus Fabian05ca4a32018-09-04 23:45:13 -0700544 def verify_capture_in(self, capture, in_if):
Matus Fabiande886752016-12-07 03:38:19 -0800545 """
546 Verify captured packets on inside network
547
548 :param capture: Captured packets
549 :param in_if: Inside interface
Matus Fabiande886752016-12-07 03:38:19 -0800550 """
Matus Fabiande886752016-12-07 03:38:19 -0800551 for packet in capture:
552 try:
Klement Sekerad81ae412018-05-16 10:52:54 +0200553 self.assert_packet_checksums_valid(packet)
Matus Fabiande886752016-12-07 03:38:19 -0800554 self.assertEqual(packet[IP].dst, in_if.remote_ip4)
555 if packet.haslayer(TCP):
556 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
557 elif packet.haslayer(UDP):
558 self.assertEqual(packet[UDP].dport, self.udp_port_in)
559 else:
560 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
561 except:
Klement Sekera9225dee2016-12-12 08:36:58 +0100562 self.logger.error(ppp("Unexpected or invalid packet "
563 "(inside network):", packet))
Matus Fabiande886752016-12-07 03:38:19 -0800564 raise
565
Matus Fabian05ca4a32018-09-04 23:45:13 -0700566 def verify_capture_in_ip6(self, capture, src_ip, dst_ip):
Matus Fabian06596c52017-06-06 04:53:28 -0700567 """
568 Verify captured IPv6 packets on inside network
569
570 :param capture: Captured packets
571 :param src_ip: Source IP
572 :param dst_ip: Destination IP address
Matus Fabian06596c52017-06-06 04:53:28 -0700573 """
Matus Fabian06596c52017-06-06 04:53:28 -0700574 for packet in capture:
575 try:
576 self.assertEqual(packet[IPv6].src, src_ip)
577 self.assertEqual(packet[IPv6].dst, dst_ip)
Klement Sekerad81ae412018-05-16 10:52:54 +0200578 self.assert_packet_checksums_valid(packet)
Matus Fabian06596c52017-06-06 04:53:28 -0700579 if packet.haslayer(TCP):
580 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
581 elif packet.haslayer(UDP):
582 self.assertEqual(packet[UDP].dport, self.udp_port_in)
583 else:
584 self.assertEqual(packet[ICMPv6EchoReply].id,
585 self.icmp_id_in)
586 except:
587 self.logger.error(ppp("Unexpected or invalid packet "
588 "(inside network):", packet))
589 raise
590
Matus Fabian675a69c2017-01-18 01:46:01 -0800591 def verify_capture_no_translation(self, capture, ingress_if, egress_if):
592 """
593 Verify captured packet that don't have to be translated
594
595 :param capture: Captured packets
596 :param ingress_if: Ingress interface
597 :param egress_if: Egress interface
598 """
599 for packet in capture:
600 try:
601 self.assertEqual(packet[IP].src, ingress_if.remote_ip4)
602 self.assertEqual(packet[IP].dst, egress_if.remote_ip4)
603 if packet.haslayer(TCP):
604 self.assertEqual(packet[TCP].sport, self.tcp_port_in)
605 elif packet.haslayer(UDP):
606 self.assertEqual(packet[UDP].sport, self.udp_port_in)
607 else:
608 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
609 except:
610 self.logger.error(ppp("Unexpected or invalid packet "
611 "(inside network):", packet))
612 raise
613
Juraj Slobodab33f4132017-02-08 23:54:21 -0800614 def verify_capture_out_with_icmp_errors(self, capture, src_ip=None,
Matus Fabian05ca4a32018-09-04 23:45:13 -0700615 icmp_type=11):
Juraj Slobodab33f4132017-02-08 23:54:21 -0800616 """
617 Verify captured packets with ICMP errors on outside network
618
619 :param capture: Captured packets
620 :param src_ip: Translated IP address or IP address of VPP
Matus Fabian2ba92e32017-08-21 07:05:03 -0700621 (Default use global NAT address)
Juraj Slobodab33f4132017-02-08 23:54:21 -0800622 :param icmp_type: Type of error ICMP packet
623 we are expecting (Default 11)
624 """
625 if src_ip is None:
Matus Fabian2ba92e32017-08-21 07:05:03 -0700626 src_ip = self.nat_addr
Juraj Slobodab33f4132017-02-08 23:54:21 -0800627 for packet in capture:
628 try:
629 self.assertEqual(packet[IP].src, src_ip)
Paul Vinciguerra978aa642018-11-24 22:19:12 -0800630 self.assertEqual(packet.haslayer(ICMP), 1)
Juraj Slobodab33f4132017-02-08 23:54:21 -0800631 icmp = packet[ICMP]
632 self.assertEqual(icmp.type, icmp_type)
633 self.assertTrue(icmp.haslayer(IPerror))
634 inner_ip = icmp[IPerror]
635 if inner_ip.haslayer(TCPerror):
636 self.assertEqual(inner_ip[TCPerror].dport,
637 self.tcp_port_out)
638 elif inner_ip.haslayer(UDPerror):
639 self.assertEqual(inner_ip[UDPerror].dport,
640 self.udp_port_out)
641 else:
642 self.assertEqual(inner_ip[ICMPerror].id, self.icmp_id_out)
643 except:
644 self.logger.error(ppp("Unexpected or invalid packet "
645 "(outside network):", packet))
646 raise
647
Matus Fabian05ca4a32018-09-04 23:45:13 -0700648 def verify_capture_in_with_icmp_errors(self, capture, in_if, icmp_type=11):
Juraj Slobodab33f4132017-02-08 23:54:21 -0800649 """
650 Verify captured packets with ICMP errors on inside network
651
652 :param capture: Captured packets
653 :param in_if: Inside interface
Juraj Slobodab33f4132017-02-08 23:54:21 -0800654 :param icmp_type: Type of error ICMP packet
655 we are expecting (Default 11)
656 """
Juraj Slobodab33f4132017-02-08 23:54:21 -0800657 for packet in capture:
658 try:
659 self.assertEqual(packet[IP].dst, in_if.remote_ip4)
Paul Vinciguerra978aa642018-11-24 22:19:12 -0800660 self.assertEqual(packet.haslayer(ICMP), 1)
Juraj Slobodab33f4132017-02-08 23:54:21 -0800661 icmp = packet[ICMP]
662 self.assertEqual(icmp.type, icmp_type)
663 self.assertTrue(icmp.haslayer(IPerror))
664 inner_ip = icmp[IPerror]
665 if inner_ip.haslayer(TCPerror):
666 self.assertEqual(inner_ip[TCPerror].sport,
667 self.tcp_port_in)
668 elif inner_ip.haslayer(UDPerror):
669 self.assertEqual(inner_ip[UDPerror].sport,
670 self.udp_port_in)
671 else:
672 self.assertEqual(inner_ip[ICMPerror].id, self.icmp_id_in)
673 except:
674 self.logger.error(ppp("Unexpected or invalid packet "
675 "(inside network):", packet))
676 raise
677
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200678 def create_stream_frag(self, src_if, dst, sport, dport, data,
679 proto=IP_PROTOS.tcp, echo_reply=False):
Matus Fabianefcd1e92017-08-15 06:59:19 -0700680 """
681 Create fragmented packet stream
682
683 :param src_if: Source interface
684 :param dst: Destination IPv4 address
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200685 :param sport: Source port
686 :param dport: Destination port
Matus Fabianefcd1e92017-08-15 06:59:19 -0700687 :param data: Payload data
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200688 :param proto: protocol (TCP, UDP, ICMP)
689 :param echo_reply: use echo_reply if protocol is ICMP
Matus Fabianefcd1e92017-08-15 06:59:19 -0700690 :returns: Fragmets
691 """
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200692 if proto == IP_PROTOS.tcp:
693 p = (IP(src=src_if.remote_ip4, dst=dst) /
694 TCP(sport=sport, dport=dport) /
695 Raw(data))
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700696 p = p.__class__(scapy.compat.raw(p))
697 chksum = p[TCP].chksum
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200698 proto_header = TCP(sport=sport, dport=dport, chksum=chksum)
699 elif proto == IP_PROTOS.udp:
700 proto_header = UDP(sport=sport, dport=dport)
701 elif proto == IP_PROTOS.icmp:
702 if not echo_reply:
703 proto_header = ICMP(id=sport, type='echo-request')
704 else:
705 proto_header = ICMP(id=sport, type='echo-reply')
706 else:
707 raise Exception("Unsupported protocol")
Matus Fabianefcd1e92017-08-15 06:59:19 -0700708 id = random.randint(0, 65535)
Matus Fabianefcd1e92017-08-15 06:59:19 -0700709 pkts = []
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200710 if proto == IP_PROTOS.tcp:
711 raw = Raw(data[0:4])
712 else:
713 raw = Raw(data[0:16])
Matus Fabianefcd1e92017-08-15 06:59:19 -0700714 p = (Ether(src=src_if.remote_mac, dst=src_if.local_mac) /
715 IP(src=src_if.remote_ip4, dst=dst, flags="MF", frag=0, id=id) /
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200716 proto_header /
717 raw)
Matus Fabianefcd1e92017-08-15 06:59:19 -0700718 pkts.append(p)
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200719 if proto == IP_PROTOS.tcp:
720 raw = Raw(data[4:20])
721 else:
722 raw = Raw(data[16:32])
Matus Fabianefcd1e92017-08-15 06:59:19 -0700723 p = (Ether(src=src_if.remote_mac, dst=src_if.local_mac) /
724 IP(src=src_if.remote_ip4, dst=dst, flags="MF", frag=3, id=id,
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200725 proto=proto) /
726 raw)
Matus Fabianefcd1e92017-08-15 06:59:19 -0700727 pkts.append(p)
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200728 if proto == IP_PROTOS.tcp:
729 raw = Raw(data[20:])
730 else:
731 raw = Raw(data[32:])
Matus Fabianefcd1e92017-08-15 06:59:19 -0700732 p = (Ether(src=src_if.remote_mac, dst=src_if.local_mac) /
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200733 IP(src=src_if.remote_ip4, dst=dst, frag=5, proto=proto,
Matus Fabianefcd1e92017-08-15 06:59:19 -0700734 id=id) /
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200735 raw)
Matus Fabianefcd1e92017-08-15 06:59:19 -0700736 pkts.append(p)
737 return pkts
738
739 def create_stream_frag_ip6(self, src_if, dst, sport, dport, data,
740 pref=None, plen=0, frag_size=128):
741 """
742 Create fragmented packet stream
743
744 :param src_if: Source interface
745 :param dst: Destination IPv4 address
746 :param sport: Source TCP port
747 :param dport: Destination TCP port
748 :param data: Payload data
749 :param pref: NAT64 prefix
750 :param plen: NAT64 prefix length
751 :param fragsize: size of fragments
752 :returns: Fragmets
753 """
754 if pref is None:
755 dst_ip6 = ''.join(['64:ff9b::', dst])
756 else:
757 dst_ip6 = self.compose_ip6(dst, pref, plen)
758
759 p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
760 IPv6(src=src_if.remote_ip6, dst=dst_ip6) /
761 IPv6ExtHdrFragment(id=random.randint(0, 65535)) /
762 TCP(sport=sport, dport=dport) /
763 Raw(data))
764
765 return fragment6(p, frag_size)
766
767 def reass_frags_and_verify(self, frags, src, dst):
768 """
769 Reassemble and verify fragmented packet
770
771 :param frags: Captured fragments
772 :param src: Source IPv4 address to verify
773 :param dst: Destination IPv4 address to verify
774
775 :returns: Reassembled IPv4 packet
776 """
Ole Troan7f991832018-12-06 17:35:12 +0100777 buffer = BytesIO()
Matus Fabianefcd1e92017-08-15 06:59:19 -0700778 for p in frags:
779 self.assertEqual(p[IP].src, src)
780 self.assertEqual(p[IP].dst, dst)
Klement Sekerad81ae412018-05-16 10:52:54 +0200781 self.assert_ip_checksum_valid(p)
Matus Fabianefcd1e92017-08-15 06:59:19 -0700782 buffer.seek(p[IP].frag * 8)
Ole Troan7f991832018-12-06 17:35:12 +0100783 buffer.write(bytes(p[IP].payload))
Matus Fabianefcd1e92017-08-15 06:59:19 -0700784 ip = IP(src=frags[0][IP].src, dst=frags[0][IP].dst,
785 proto=frags[0][IP].proto)
786 if ip.proto == IP_PROTOS.tcp:
787 p = (ip / TCP(buffer.getvalue()))
Klement Sekerad81ae412018-05-16 10:52:54 +0200788 self.assert_tcp_checksum_valid(p)
Matus Fabianefcd1e92017-08-15 06:59:19 -0700789 elif ip.proto == IP_PROTOS.udp:
Juraj Slobodafe0aa762018-07-23 12:22:54 +0200790 p = (ip / UDP(buffer.getvalue()[:8]) /
791 Raw(buffer.getvalue()[8:]))
792 elif ip.proto == IP_PROTOS.icmp:
793 p = (ip / ICMP(buffer.getvalue()))
Matus Fabianefcd1e92017-08-15 06:59:19 -0700794 return p
795
796 def reass_frags_and_verify_ip6(self, frags, src, dst):
797 """
798 Reassemble and verify fragmented packet
799
800 :param frags: Captured fragments
801 :param src: Source IPv6 address to verify
802 :param dst: Destination IPv6 address to verify
803
804 :returns: Reassembled IPv6 packet
805 """
Ole Troan7f991832018-12-06 17:35:12 +0100806 buffer = BytesIO()
Matus Fabianefcd1e92017-08-15 06:59:19 -0700807 for p in frags:
808 self.assertEqual(p[IPv6].src, src)
809 self.assertEqual(p[IPv6].dst, dst)
810 buffer.seek(p[IPv6ExtHdrFragment].offset * 8)
Ole Troan7f991832018-12-06 17:35:12 +0100811 buffer.write(bytes(p[IPv6ExtHdrFragment].payload))
Matus Fabianefcd1e92017-08-15 06:59:19 -0700812 ip = IPv6(src=frags[0][IPv6].src, dst=frags[0][IPv6].dst,
813 nh=frags[0][IPv6ExtHdrFragment].nh)
814 if ip.nh == IP_PROTOS.tcp:
815 p = (ip / TCP(buffer.getvalue()))
Matus Fabianefcd1e92017-08-15 06:59:19 -0700816 elif ip.nh == IP_PROTOS.udp:
817 p = (ip / UDP(buffer.getvalue()))
Klement Sekerad81ae412018-05-16 10:52:54 +0200818 self.assert_packet_checksums_valid(p)
Matus Fabianefcd1e92017-08-15 06:59:19 -0700819 return p
820
Matus Fabianebdf1902018-05-04 03:57:42 -0700821 def initiate_tcp_session(self, in_if, out_if):
822 """
823 Initiates TCP session
824
825 :param in_if: Inside interface
826 :param out_if: Outside interface
827 """
828 try:
829 # SYN packet in->out
830 p = (Ether(src=in_if.remote_mac, dst=in_if.local_mac) /
831 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4) /
832 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
833 flags="S"))
834 in_if.add_stream(p)
835 self.pg_enable_capture(self.pg_interfaces)
836 self.pg_start()
837 capture = out_if.get_capture(1)
838 p = capture[0]
839 self.tcp_port_out = p[TCP].sport
840
841 # SYN + ACK packet out->in
842 p = (Ether(src=out_if.remote_mac, dst=out_if.local_mac) /
843 IP(src=out_if.remote_ip4, dst=self.nat_addr) /
844 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
845 flags="SA"))
846 out_if.add_stream(p)
847 self.pg_enable_capture(self.pg_interfaces)
848 self.pg_start()
849 in_if.get_capture(1)
850
851 # ACK packet in->out
852 p = (Ether(src=in_if.remote_mac, dst=in_if.local_mac) /
853 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4) /
854 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
855 flags="A"))
856 in_if.add_stream(p)
857 self.pg_enable_capture(self.pg_interfaces)
858 self.pg_start()
859 out_if.get_capture(1)
860
861 except:
862 self.logger.error("TCP 3 way handshake failed")
863 raise
864
Matus Fabianeea28d72017-01-13 04:15:54 -0800865 def verify_ipfix_nat44_ses(self, data):
866 """
867 Verify IPFIX NAT44 session create/delete event
868
869 :param data: Decoded IPFIX data records
870 """
871 nat44_ses_create_num = 0
872 nat44_ses_delete_num = 0
873 self.assertEqual(6, len(data))
874 for record in data:
875 # natEvent
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700876 self.assertIn(scapy.compat.orb(record[230]), [4, 5])
877 if scapy.compat.orb(record[230]) == 4:
Matus Fabianeea28d72017-01-13 04:15:54 -0800878 nat44_ses_create_num += 1
879 else:
880 nat44_ses_delete_num += 1
881 # sourceIPv4Address
882 self.assertEqual(self.pg0.remote_ip4n, record[8])
883 # postNATSourceIPv4Address
Matus Fabian2ba92e32017-08-21 07:05:03 -0700884 self.assertEqual(socket.inet_pton(socket.AF_INET, self.nat_addr),
Matus Fabianeea28d72017-01-13 04:15:54 -0800885 record[225])
886 # ingressVRFID
887 self.assertEqual(struct.pack("!I", 0), record[234])
888 # protocolIdentifier/sourceTransportPort/postNAPTSourceTransportPort
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700889 if IP_PROTOS.icmp == scapy.compat.orb(record[4]):
Matus Fabianeea28d72017-01-13 04:15:54 -0800890 self.assertEqual(struct.pack("!H", self.icmp_id_in), record[7])
891 self.assertEqual(struct.pack("!H", self.icmp_id_out),
892 record[227])
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700893 elif IP_PROTOS.tcp == scapy.compat.orb(record[4]):
Matus Fabianeea28d72017-01-13 04:15:54 -0800894 self.assertEqual(struct.pack("!H", self.tcp_port_in),
895 record[7])
896 self.assertEqual(struct.pack("!H", self.tcp_port_out),
897 record[227])
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700898 elif IP_PROTOS.udp == scapy.compat.orb(record[4]):
Matus Fabianeea28d72017-01-13 04:15:54 -0800899 self.assertEqual(struct.pack("!H", self.udp_port_in),
900 record[7])
901 self.assertEqual(struct.pack("!H", self.udp_port_out),
902 record[227])
903 else:
904 self.fail("Invalid protocol")
905 self.assertEqual(3, nat44_ses_create_num)
906 self.assertEqual(3, nat44_ses_delete_num)
907
908 def verify_ipfix_addr_exhausted(self, data):
909 """
910 Verify IPFIX NAT addresses event
911
912 :param data: Decoded IPFIX data records
913 """
914 self.assertEqual(1, len(data))
915 record = data[0]
916 # natEvent
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700917 self.assertEqual(scapy.compat.orb(record[230]), 3)
Matus Fabianeea28d72017-01-13 04:15:54 -0800918 # natPoolID
919 self.assertEqual(struct.pack("!I", 0), record[283])
920
Matus Fabiana431ad12018-01-04 04:03:14 -0800921 def verify_ipfix_max_sessions(self, data, limit):
922 """
923 Verify IPFIX maximum session entries exceeded event
924
925 :param data: Decoded IPFIX data records
926 :param limit: Number of maximum session entries that can be created.
927 """
928 self.assertEqual(1, len(data))
929 record = data[0]
930 # natEvent
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700931 self.assertEqual(scapy.compat.orb(record[230]), 13)
Matus Fabiana431ad12018-01-04 04:03:14 -0800932 # natQuotaExceededEvent
933 self.assertEqual(struct.pack("I", 1), record[466])
934 # maxSessionEntries
935 self.assertEqual(struct.pack("I", limit), record[471])
936
937 def verify_ipfix_max_bibs(self, data, limit):
938 """
939 Verify IPFIX maximum BIB entries exceeded event
940
941 :param data: Decoded IPFIX data records
942 :param limit: Number of maximum BIB entries that can be created.
943 """
944 self.assertEqual(1, len(data))
945 record = data[0]
946 # natEvent
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700947 self.assertEqual(scapy.compat.orb(record[230]), 13)
Matus Fabiana431ad12018-01-04 04:03:14 -0800948 # natQuotaExceededEvent
949 self.assertEqual(struct.pack("I", 2), record[466])
950 # maxBIBEntries
951 self.assertEqual(struct.pack("I", limit), record[472])
952
953 def verify_ipfix_max_fragments_ip6(self, data, limit, src_addr):
954 """
955 Verify IPFIX maximum IPv6 fragments pending reassembly exceeded event
956
957 :param data: Decoded IPFIX data records
958 :param limit: Number of maximum fragments pending reassembly
959 :param src_addr: IPv6 source address
960 """
961 self.assertEqual(1, len(data))
962 record = data[0]
963 # natEvent
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700964 self.assertEqual(scapy.compat.orb(record[230]), 13)
Matus Fabiana431ad12018-01-04 04:03:14 -0800965 # natQuotaExceededEvent
966 self.assertEqual(struct.pack("I", 5), record[466])
967 # maxFragmentsPendingReassembly
968 self.assertEqual(struct.pack("I", limit), record[475])
969 # sourceIPv6Address
970 self.assertEqual(src_addr, record[27])
971
972 def verify_ipfix_max_fragments_ip4(self, data, limit, src_addr):
973 """
974 Verify IPFIX maximum IPv4 fragments pending reassembly exceeded event
975
976 :param data: Decoded IPFIX data records
977 :param limit: Number of maximum fragments pending reassembly
978 :param src_addr: IPv4 source address
979 """
980 self.assertEqual(1, len(data))
981 record = data[0]
982 # natEvent
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700983 self.assertEqual(scapy.compat.orb(record[230]), 13)
Matus Fabiana431ad12018-01-04 04:03:14 -0800984 # natQuotaExceededEvent
985 self.assertEqual(struct.pack("I", 5), record[466])
986 # maxFragmentsPendingReassembly
987 self.assertEqual(struct.pack("I", limit), record[475])
988 # sourceIPv4Address
989 self.assertEqual(src_addr, record[8])
990
991 def verify_ipfix_bib(self, data, is_create, src_addr):
992 """
993 Verify IPFIX NAT64 BIB create and delete events
994
995 :param data: Decoded IPFIX data records
996 :param is_create: Create event if nonzero value otherwise delete event
997 :param src_addr: IPv6 source address
998 """
999 self.assertEqual(1, len(data))
1000 record = data[0]
1001 # natEvent
1002 if is_create:
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07001003 self.assertEqual(scapy.compat.orb(record[230]), 10)
Matus Fabiana431ad12018-01-04 04:03:14 -08001004 else:
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07001005 self.assertEqual(scapy.compat.orb(record[230]), 11)
Matus Fabiana431ad12018-01-04 04:03:14 -08001006 # sourceIPv6Address
1007 self.assertEqual(src_addr, record[27])
1008 # postNATSourceIPv4Address
1009 self.assertEqual(self.nat_addr_n, record[225])
1010 # protocolIdentifier
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07001011 self.assertEqual(IP_PROTOS.tcp, scapy.compat.orb(record[4]))
Matus Fabiana431ad12018-01-04 04:03:14 -08001012 # ingressVRFID
1013 self.assertEqual(struct.pack("!I", 0), record[234])
1014 # sourceTransportPort
1015 self.assertEqual(struct.pack("!H", self.tcp_port_in), record[7])
1016 # postNAPTSourceTransportPort
1017 self.assertEqual(struct.pack("!H", self.tcp_port_out), record[227])
1018
1019 def verify_ipfix_nat64_ses(self, data, is_create, src_addr, dst_addr,
1020 dst_port):
1021 """
1022 Verify IPFIX NAT64 session create and delete events
1023
1024 :param data: Decoded IPFIX data records
1025 :param is_create: Create event if nonzero value otherwise delete event
1026 :param src_addr: IPv6 source address
1027 :param dst_addr: IPv4 destination address
1028 :param dst_port: destination TCP port
1029 """
1030 self.assertEqual(1, len(data))
1031 record = data[0]
1032 # natEvent
1033 if is_create:
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07001034 self.assertEqual(scapy.compat.orb(record[230]), 6)
Matus Fabiana431ad12018-01-04 04:03:14 -08001035 else:
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07001036 self.assertEqual(scapy.compat.orb(record[230]), 7)
Matus Fabiana431ad12018-01-04 04:03:14 -08001037 # sourceIPv6Address
1038 self.assertEqual(src_addr, record[27])
1039 # destinationIPv6Address
1040 self.assertEqual(socket.inet_pton(socket.AF_INET6,
1041 self.compose_ip6(dst_addr,
1042 '64:ff9b::',
1043 96)),
1044 record[28])
1045 # postNATSourceIPv4Address
1046 self.assertEqual(self.nat_addr_n, record[225])
1047 # postNATDestinationIPv4Address
1048 self.assertEqual(socket.inet_pton(socket.AF_INET, dst_addr),
1049 record[226])
1050 # protocolIdentifier
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07001051 self.assertEqual(IP_PROTOS.tcp, scapy.compat.orb(record[4]))
Matus Fabiana431ad12018-01-04 04:03:14 -08001052 # ingressVRFID
1053 self.assertEqual(struct.pack("!I", 0), record[234])
1054 # sourceTransportPort
1055 self.assertEqual(struct.pack("!H", self.tcp_port_in), record[7])
1056 # postNAPTSourceTransportPort
1057 self.assertEqual(struct.pack("!H", self.tcp_port_out), record[227])
1058 # destinationTransportPort
1059 self.assertEqual(struct.pack("!H", dst_port), record[11])
1060 # postNAPTDestinationTransportPort
1061 self.assertEqual(struct.pack("!H", dst_port), record[228])
1062
Matus Fabian68ba8802018-08-08 05:52:47 -07001063 def verify_no_nat44_user(self):
1064 """ Verify that there is no NAT44 user """
1065 users = self.vapi.nat44_user_dump()
1066 self.assertEqual(len(users), 0)
Matus Fabianfd0d5082018-12-18 01:08:51 -08001067 users = self.statistics.get_counter('/nat44/total-users')
1068 self.assertEqual(users[0][0], 0)
1069 sessions = self.statistics.get_counter('/nat44/total-sessions')
1070 self.assertEqual(sessions[0][0], 0)
Matus Fabian68ba8802018-08-08 05:52:47 -07001071
Matus Fabian878c6462018-08-23 00:33:35 -07001072 def verify_ipfix_max_entries_per_user(self, data, limit, src_addr):
1073 """
1074 Verify IPFIX maximum entries per user exceeded event
1075
1076 :param data: Decoded IPFIX data records
1077 :param limit: Number of maximum entries per user
1078 :param src_addr: IPv4 source address
1079 """
1080 self.assertEqual(1, len(data))
1081 record = data[0]
1082 # natEvent
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07001083 self.assertEqual(scapy.compat.orb(record[230]), 13)
Matus Fabian878c6462018-08-23 00:33:35 -07001084 # natQuotaExceededEvent
1085 self.assertEqual(struct.pack("I", 3), record[466])
1086 # maxEntriesPerUser
1087 self.assertEqual(struct.pack("I", limit), record[473])
1088 # sourceIPv4Address
1089 self.assertEqual(src_addr, record[8])
1090
Matus Fabianad1f3e12018-11-28 21:26:34 -08001091 def verify_syslog_apmap(self, data, is_add=True):
1092 message = data.decode('utf-8')
1093 try:
1094 message = SyslogMessage.parse(message)
Paul Vinciguerrad7532092019-01-14 08:51:17 -08001095 except ParseError as e:
1096 self.logger.error(e)
1097 raise
1098 else:
Matus Fabianad1f3e12018-11-28 21:26:34 -08001099 self.assertEqual(message.severity, SyslogSeverity.info)
1100 self.assertEqual(message.appname, 'NAT')
1101 self.assertEqual(message.msgid, 'APMADD' if is_add else 'APMDEL')
1102 sd_params = message.sd.get('napmap')
1103 self.assertTrue(sd_params is not None)
1104 self.assertEqual(sd_params.get('IATYP'), 'IPv4')
1105 self.assertEqual(sd_params.get('ISADDR'), self.pg0.remote_ip4)
1106 self.assertEqual(sd_params.get('ISPORT'), "%d" % self.tcp_port_in)
1107 self.assertEqual(sd_params.get('XATYP'), 'IPv4')
1108 self.assertEqual(sd_params.get('XSADDR'), self.nat_addr)
1109 self.assertEqual(sd_params.get('XSPORT'), "%d" % self.tcp_port_out)
1110 self.assertEqual(sd_params.get('PROTO'), "%d" % IP_PROTOS.tcp)
1111 self.assertTrue(sd_params.get('SSUBIX') is not None)
1112 self.assertEqual(sd_params.get('SVLAN'), '0')
Matus Fabianad1f3e12018-11-28 21:26:34 -08001113
1114 def verify_syslog_sess(self, data, is_add=True, is_ip6=False):
1115 message = data.decode('utf-8')
1116 try:
1117 message = SyslogMessage.parse(message)
Paul Vinciguerrad7532092019-01-14 08:51:17 -08001118 except ParseError as e:
1119 self.logger.error(e)
1120 raise
1121 else:
Matus Fabianad1f3e12018-11-28 21:26:34 -08001122 self.assertEqual(message.severity, SyslogSeverity.info)
1123 self.assertEqual(message.appname, 'NAT')
1124 self.assertEqual(message.msgid, 'SADD' if is_add else 'SDEL')
1125 sd_params = message.sd.get('nsess')
1126 self.assertTrue(sd_params is not None)
1127 if is_ip6:
1128 self.assertEqual(sd_params.get('IATYP'), 'IPv6')
1129 self.assertEqual(sd_params.get('ISADDR'), self.pg0.remote_ip6)
1130 else:
1131 self.assertEqual(sd_params.get('IATYP'), 'IPv4')
1132 self.assertEqual(sd_params.get('ISADDR'), self.pg0.remote_ip4)
1133 self.assertTrue(sd_params.get('SSUBIX') is not None)
1134 self.assertEqual(sd_params.get('ISPORT'), "%d" % self.tcp_port_in)
1135 self.assertEqual(sd_params.get('XATYP'), 'IPv4')
1136 self.assertEqual(sd_params.get('XSADDR'), self.nat_addr)
1137 self.assertEqual(sd_params.get('XSPORT'), "%d" % self.tcp_port_out)
1138 self.assertEqual(sd_params.get('PROTO'), "%d" % IP_PROTOS.tcp)
1139 self.assertEqual(sd_params.get('SVLAN'), '0')
1140 self.assertEqual(sd_params.get('XDADDR'), self.pg1.remote_ip4)
1141 self.assertEqual(sd_params.get('XDPORT'),
1142 "%d" % self.tcp_external_port)
Matus Fabianad1f3e12018-11-28 21:26:34 -08001143
Matus Fabianbb4e0222018-09-13 02:36:25 -07001144 def verify_mss_value(self, pkt, mss):
1145 """
1146 Verify TCP MSS value
1147
1148 :param pkt:
1149 :param mss:
1150 """
1151 if not pkt.haslayer(IP) or not pkt.haslayer(TCP):
1152 raise TypeError("Not a TCP/IP packet")
1153
1154 for option in pkt[TCP].options:
1155 if option[0] == 'MSS':
1156 self.assertEqual(option[1], mss)
1157 self.assert_tcp_checksum_valid(pkt)
1158
Juraj Slobodafe0aa762018-07-23 12:22:54 +02001159 @staticmethod
1160 def proto2layer(proto):
1161 if proto == IP_PROTOS.tcp:
1162 return TCP
1163 elif proto == IP_PROTOS.udp:
1164 return UDP
1165 elif proto == IP_PROTOS.icmp:
1166 return ICMP
1167 else:
1168 raise Exception("Unsupported protocol")
1169
1170 def frag_in_order(self, proto=IP_PROTOS.tcp, dont_translate=False):
1171 layer = self.proto2layer(proto)
1172
1173 if proto == IP_PROTOS.tcp:
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07001174 data = b"A" * 4 + b"B" * 16 + b"C" * 3
Juraj Slobodafe0aa762018-07-23 12:22:54 +02001175 else:
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07001176 data = b"A" * 16 + b"B" * 16 + b"C" * 3
Juraj Slobodafe0aa762018-07-23 12:22:54 +02001177 self.port_in = random.randint(1025, 65535)
1178
1179 reass = self.vapi.nat_reass_dump()
1180 reass_n_start = len(reass)
1181
1182 # in2out
1183 pkts = self.create_stream_frag(self.pg0,
1184 self.pg1.remote_ip4,
1185 self.port_in,
1186 20,
1187 data,
1188 proto)
1189 self.pg0.add_stream(pkts)
1190 self.pg_enable_capture(self.pg_interfaces)
1191 self.pg_start()
1192 frags = self.pg1.get_capture(len(pkts))
1193 if not dont_translate:
1194 p = self.reass_frags_and_verify(frags,
1195 self.nat_addr,
1196 self.pg1.remote_ip4)
1197 else:
1198 p = self.reass_frags_and_verify(frags,
1199 self.pg0.remote_ip4,
1200 self.pg1.remote_ip4)
1201 if proto != IP_PROTOS.icmp:
1202 if not dont_translate:
1203 self.assertEqual(p[layer].dport, 20)
1204 self.assertNotEqual(p[layer].sport, self.port_in)
1205 else:
1206 self.assertEqual(p[layer].sport, self.port_in)
1207 else:
1208 if not dont_translate:
1209 self.assertNotEqual(p[layer].id, self.port_in)
1210 else:
1211 self.assertEqual(p[layer].id, self.port_in)
1212 self.assertEqual(data, p[Raw].load)
1213
1214 # out2in
1215 if not dont_translate:
1216 dst_addr = self.nat_addr
1217 else:
1218 dst_addr = self.pg0.remote_ip4
1219 if proto != IP_PROTOS.icmp:
1220 sport = 20
1221 dport = p[layer].sport
1222 else:
1223 sport = p[layer].id
1224 dport = 0
1225 pkts = self.create_stream_frag(self.pg1,
1226 dst_addr,
1227 sport,
1228 dport,
1229 data,
1230 proto,
1231 echo_reply=True)
1232 self.pg1.add_stream(pkts)
1233 self.pg_enable_capture(self.pg_interfaces)
1234 self.pg_start()
1235 frags = self.pg0.get_capture(len(pkts))
1236 p = self.reass_frags_and_verify(frags,
1237 self.pg1.remote_ip4,
1238 self.pg0.remote_ip4)
1239 if proto != IP_PROTOS.icmp:
1240 self.assertEqual(p[layer].sport, 20)
1241 self.assertEqual(p[layer].dport, self.port_in)
1242 else:
1243 self.assertEqual(p[layer].id, self.port_in)
1244 self.assertEqual(data, p[Raw].load)
1245
1246 reass = self.vapi.nat_reass_dump()
1247 reass_n_end = len(reass)
1248
1249 self.assertEqual(reass_n_end - reass_n_start, 2)
1250
1251 def frag_in_order_in_plus_out(self, proto=IP_PROTOS.tcp):
1252 layer = self.proto2layer(proto)
1253
1254 if proto == IP_PROTOS.tcp:
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07001255 data = b"A" * 4 + b"B" * 16 + b"C" * 3
Juraj Slobodafe0aa762018-07-23 12:22:54 +02001256 else:
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07001257 data = b"A" * 16 + b"B" * 16 + b"C" * 3
Juraj Slobodafe0aa762018-07-23 12:22:54 +02001258 self.port_in = random.randint(1025, 65535)
1259
1260 for i in range(2):
1261 reass = self.vapi.nat_reass_dump()
1262 reass_n_start = len(reass)
1263
1264 # out2in
1265 pkts = self.create_stream_frag(self.pg0,
1266 self.server_out_addr,
1267 self.port_in,
1268 self.server_out_port,
1269 data,
1270 proto)
1271 self.pg0.add_stream(pkts)
1272 self.pg_enable_capture(self.pg_interfaces)
1273 self.pg_start()
1274 frags = self.pg1.get_capture(len(pkts))
1275 p = self.reass_frags_and_verify(frags,
1276 self.pg0.remote_ip4,
1277 self.server_in_addr)
1278 if proto != IP_PROTOS.icmp:
1279 self.assertEqual(p[layer].sport, self.port_in)
1280 self.assertEqual(p[layer].dport, self.server_in_port)
1281 else:
1282 self.assertEqual(p[layer].id, self.port_in)
1283 self.assertEqual(data, p[Raw].load)
1284
1285 # in2out
1286 if proto != IP_PROTOS.icmp:
1287 pkts = self.create_stream_frag(self.pg1,
1288 self.pg0.remote_ip4,
1289 self.server_in_port,
1290 p[layer].sport,
1291 data,
1292 proto)
1293 else:
1294 pkts = self.create_stream_frag(self.pg1,
1295 self.pg0.remote_ip4,
1296 p[layer].id,
1297 0,
1298 data,
1299 proto,
1300 echo_reply=True)
1301 self.pg1.add_stream(pkts)
1302 self.pg_enable_capture(self.pg_interfaces)
1303 self.pg_start()
1304 frags = self.pg0.get_capture(len(pkts))
1305 p = self.reass_frags_and_verify(frags,
1306 self.server_out_addr,
1307 self.pg0.remote_ip4)
1308 if proto != IP_PROTOS.icmp:
1309 self.assertEqual(p[layer].sport, self.server_out_port)
1310 self.assertEqual(p[layer].dport, self.port_in)
1311 else:
1312 self.assertEqual(p[layer].id, self.port_in)
1313 self.assertEqual(data, p[Raw].load)
1314
1315 reass = self.vapi.nat_reass_dump()
1316 reass_n_end = len(reass)
1317
1318 self.assertEqual(reass_n_end - reass_n_start, 2)
1319
1320 def reass_hairpinning(self, proto=IP_PROTOS.tcp):
1321 layer = self.proto2layer(proto)
1322
1323 if proto == IP_PROTOS.tcp:
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07001324 data = b"A" * 4 + b"B" * 16 + b"C" * 3
Juraj Slobodafe0aa762018-07-23 12:22:54 +02001325 else:
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07001326 data = b"A" * 16 + b"B" * 16 + b"C" * 3
Juraj Slobodafe0aa762018-07-23 12:22:54 +02001327
1328 # send packet from host to server
1329 pkts = self.create_stream_frag(self.pg0,
1330 self.nat_addr,
1331 self.host_in_port,
1332 self.server_out_port,
1333 data,
1334 proto)
1335 self.pg0.add_stream(pkts)
1336 self.pg_enable_capture(self.pg_interfaces)
1337 self.pg_start()
1338 frags = self.pg0.get_capture(len(pkts))
1339 p = self.reass_frags_and_verify(frags,
1340 self.nat_addr,
1341 self.server.ip4)
1342 if proto != IP_PROTOS.icmp:
1343 self.assertNotEqual(p[layer].sport, self.host_in_port)
1344 self.assertEqual(p[layer].dport, self.server_in_port)
1345 else:
1346 self.assertNotEqual(p[layer].id, self.host_in_port)
1347 self.assertEqual(data, p[Raw].load)
1348
1349 def frag_out_of_order(self, proto=IP_PROTOS.tcp, dont_translate=False):
1350 layer = self.proto2layer(proto)
1351
1352 if proto == IP_PROTOS.tcp:
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07001353 data = b"A" * 4 + b"B" * 16 + b"C" * 3
Juraj Slobodafe0aa762018-07-23 12:22:54 +02001354 else:
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07001355 data = b"A" * 16 + b"B" * 16 + b"C" * 3
Juraj Slobodafe0aa762018-07-23 12:22:54 +02001356 self.port_in = random.randint(1025, 65535)
1357
1358 for i in range(2):
1359 # in2out
1360 pkts = self.create_stream_frag(self.pg0,
1361 self.pg1.remote_ip4,
1362 self.port_in,
1363 20,
1364 data,
1365 proto)
1366 pkts.reverse()
1367 self.pg0.add_stream(pkts)
1368 self.pg_enable_capture(self.pg_interfaces)
1369 self.pg_start()
1370 frags = self.pg1.get_capture(len(pkts))
1371 if not dont_translate:
1372 p = self.reass_frags_and_verify(frags,
1373 self.nat_addr,
1374 self.pg1.remote_ip4)
1375 else:
1376 p = self.reass_frags_and_verify(frags,
1377 self.pg0.remote_ip4,
1378 self.pg1.remote_ip4)
1379 if proto != IP_PROTOS.icmp:
1380 if not dont_translate:
1381 self.assertEqual(p[layer].dport, 20)
1382 self.assertNotEqual(p[layer].sport, self.port_in)
1383 else:
1384 self.assertEqual(p[layer].sport, self.port_in)
1385 else:
1386 if not dont_translate:
1387 self.assertNotEqual(p[layer].id, self.port_in)
1388 else:
1389 self.assertEqual(p[layer].id, self.port_in)
1390 self.assertEqual(data, p[Raw].load)
1391
1392 # out2in
1393 if not dont_translate:
1394 dst_addr = self.nat_addr
1395 else:
1396 dst_addr = self.pg0.remote_ip4
1397 if proto != IP_PROTOS.icmp:
1398 sport = 20
1399 dport = p[layer].sport
1400 else:
1401 sport = p[layer].id
1402 dport = 0
1403 pkts = self.create_stream_frag(self.pg1,
1404 dst_addr,
1405 sport,
1406 dport,
1407 data,
1408 proto,
1409 echo_reply=True)
1410 pkts.reverse()
1411 self.pg1.add_stream(pkts)
1412 self.pg_enable_capture(self.pg_interfaces)
1413 self.pg_start()
1414 frags = self.pg0.get_capture(len(pkts))
1415 p = self.reass_frags_and_verify(frags,
1416 self.pg1.remote_ip4,
1417 self.pg0.remote_ip4)
1418 if proto != IP_PROTOS.icmp:
1419 self.assertEqual(p[layer].sport, 20)
1420 self.assertEqual(p[layer].dport, self.port_in)
1421 else:
1422 self.assertEqual(p[layer].id, self.port_in)
1423 self.assertEqual(data, p[Raw].load)
1424
1425 def frag_out_of_order_in_plus_out(self, proto=IP_PROTOS.tcp):
1426 layer = self.proto2layer(proto)
1427
1428 if proto == IP_PROTOS.tcp:
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07001429 data = b"A" * 4 + b"B" * 16 + b"C" * 3
Juraj Slobodafe0aa762018-07-23 12:22:54 +02001430 else:
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07001431 data = b"A" * 16 + b"B" * 16 + b"C" * 3
Juraj Slobodafe0aa762018-07-23 12:22:54 +02001432 self.port_in = random.randint(1025, 65535)
1433
1434 for i in range(2):
1435 # out2in
1436 pkts = self.create_stream_frag(self.pg0,
1437 self.server_out_addr,
1438 self.port_in,
1439 self.server_out_port,
1440 data,
1441 proto)
1442 pkts.reverse()
1443 self.pg0.add_stream(pkts)
1444 self.pg_enable_capture(self.pg_interfaces)
1445 self.pg_start()
1446 frags = self.pg1.get_capture(len(pkts))
1447 p = self.reass_frags_and_verify(frags,
1448 self.pg0.remote_ip4,
1449 self.server_in_addr)
1450 if proto != IP_PROTOS.icmp:
1451 self.assertEqual(p[layer].dport, self.server_in_port)
1452 self.assertEqual(p[layer].sport, self.port_in)
1453 self.assertEqual(p[layer].dport, self.server_in_port)
1454 else:
1455 self.assertEqual(p[layer].id, self.port_in)
1456 self.assertEqual(data, p[Raw].load)
1457
1458 # in2out
1459 if proto != IP_PROTOS.icmp:
1460 pkts = self.create_stream_frag(self.pg1,
1461 self.pg0.remote_ip4,
1462 self.server_in_port,
1463 p[layer].sport,
1464 data,
1465 proto)
1466 else:
1467 pkts = self.create_stream_frag(self.pg1,
1468 self.pg0.remote_ip4,
1469 p[layer].id,
1470 0,
1471 data,
1472 proto,
1473 echo_reply=True)
1474 pkts.reverse()
1475 self.pg1.add_stream(pkts)
1476 self.pg_enable_capture(self.pg_interfaces)
1477 self.pg_start()
1478 frags = self.pg0.get_capture(len(pkts))
1479 p = self.reass_frags_and_verify(frags,
1480 self.server_out_addr,
1481 self.pg0.remote_ip4)
1482 if proto != IP_PROTOS.icmp:
1483 self.assertEqual(p[layer].sport, self.server_out_port)
1484 self.assertEqual(p[layer].dport, self.port_in)
1485 else:
1486 self.assertEqual(p[layer].id, self.port_in)
1487 self.assertEqual(data, p[Raw].load)
1488
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001489
Matus Fabian2ba92e32017-08-21 07:05:03 -07001490class TestNAT44(MethodHolder):
1491 """ NAT44 Test Cases """
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001492
1493 @classmethod
1494 def setUpClass(cls):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001495 super(TestNAT44, cls).setUpClass()
Matus Fabian229c1aa2018-05-28 04:09:52 -07001496 cls.vapi.cli("set log class nat level debug")
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001497
1498 try:
1499 cls.tcp_port_in = 6303
1500 cls.tcp_port_out = 6303
1501 cls.udp_port_in = 6304
1502 cls.udp_port_out = 6304
1503 cls.icmp_id_in = 6305
1504 cls.icmp_id_out = 6305
Matus Fabian2ba92e32017-08-21 07:05:03 -07001505 cls.nat_addr = '10.0.0.3'
Juraj Sloboda7b929792017-11-23 13:20:48 +01001506 cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
Matus Fabian6631e9c2017-05-24 01:52:20 -07001507 cls.ipfix_src_port = 4739
1508 cls.ipfix_domain_id = 1
Matus Fabianebdf1902018-05-04 03:57:42 -07001509 cls.tcp_external_port = 80
Matus Fabian34931eb2019-02-26 09:05:23 -08001510 cls.udp_external_port = 69
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001511
Matus Fabian36ea2d62017-10-24 04:13:49 -07001512 cls.create_pg_interfaces(range(10))
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001513 cls.interfaces = list(cls.pg_interfaces[0:4])
1514
1515 for i in cls.interfaces:
1516 i.admin_up()
1517 i.config_ip4()
1518 i.resolve_arp()
1519
Matus Fabian6fa74c62017-06-05 05:55:48 -07001520 cls.pg0.generate_remote_hosts(3)
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001521 cls.pg0.configure_ipv4_neighbors()
1522
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02001523 cls.pg1.generate_remote_hosts(1)
1524 cls.pg1.configure_ipv4_neighbors()
1525
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001526 cls.overlapping_interfaces = list(list(cls.pg_interfaces[4:7]))
Ole Troan9a475372019-03-05 16:58:24 +01001527 cls.vapi.ip_table_add_del(is_add=1, table_id=10)
1528 cls.vapi.ip_table_add_del(is_add=1, table_id=20)
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001529
Jakub Grajciare63325e2019-03-01 08:55:49 +01001530 cls.pg4._local_ip4 = VppIpPrefix("172.16.255.1",
1531 cls.pg4.local_ip4_prefix.len)
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001532 cls.pg4._remote_hosts[0]._ip4 = "172.16.255.2"
1533 cls.pg4.set_table_ip4(10)
Jakub Grajciare63325e2019-03-01 08:55:49 +01001534 cls.pg5._local_ip4 = VppIpPrefix("172.17.255.3",
1535 cls.pg5.local_ip4_prefix.len)
Matus Fabian69126282017-08-14 23:39:58 -07001536 cls.pg5._remote_hosts[0]._ip4 = "172.17.255.4"
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001537 cls.pg5.set_table_ip4(10)
Jakub Grajciare63325e2019-03-01 08:55:49 +01001538 cls.pg6._local_ip4 = VppIpPrefix("172.16.255.1",
1539 cls.pg6.local_ip4_prefix.len)
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001540 cls.pg6._remote_hosts[0]._ip4 = "172.16.255.2"
1541 cls.pg6.set_table_ip4(20)
1542 for i in cls.overlapping_interfaces:
1543 i.config_ip4()
1544 i.admin_up()
1545 i.resolve_arp()
1546
1547 cls.pg7.admin_up()
Martin Gálik406eb1d2017-05-04 04:35:04 -07001548 cls.pg8.admin_up()
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001549
Matus Fabian36ea2d62017-10-24 04:13:49 -07001550 cls.pg9.generate_remote_hosts(2)
1551 cls.pg9.config_ip4()
Ole Troan9a475372019-03-05 16:58:24 +01001552 cls.vapi.sw_interface_add_del_address(
Jakub Grajciare63325e2019-03-01 08:55:49 +01001553 sw_if_index=cls.pg9.sw_if_index,
1554 prefix=VppIpPrefix("10.0.0.1", 24).encode())
1555
Matus Fabian36ea2d62017-10-24 04:13:49 -07001556 cls.pg9.admin_up()
1557 cls.pg9.resolve_arp()
1558 cls.pg9._remote_hosts[1]._ip4 = cls.pg9._remote_hosts[0]._ip4
1559 cls.pg4._remote_ip4 = cls.pg9._remote_hosts[0]._ip4 = "10.0.0.2"
1560 cls.pg9.resolve_arp()
1561
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001562 except Exception:
Matus Fabian2ba92e32017-08-21 07:05:03 -07001563 super(TestNAT44, cls).tearDownClass()
Martin Gálikd7f75cd2017-03-27 06:02:47 -07001564 raise
1565
Matus Fabiande886752016-12-07 03:38:19 -08001566 def test_dynamic(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001567 """ NAT44 dynamic translation test """
Matus Fabian2ba92e32017-08-21 07:05:03 -07001568 self.nat44_add_address(self.nat_addr)
1569 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1570 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1571 is_inside=0)
Matus Fabiande886752016-12-07 03:38:19 -08001572
1573 # in2out
Matus Fabiana5e73762018-12-14 01:55:16 -08001574 tcpn = self.statistics.get_counter(
1575 '/err/nat44-in2out-slowpath/TCP packets')
1576 udpn = self.statistics.get_counter(
1577 '/err/nat44-in2out-slowpath/UDP packets')
1578 icmpn = self.statistics.get_counter(
1579 '/err/nat44-in2out-slowpath/ICMP packets')
1580 totaln = self.statistics.get_counter(
1581 '/err/nat44-in2out-slowpath/good in2out packets processed')
1582
Matus Fabiande886752016-12-07 03:38:19 -08001583 pkts = self.create_stream_in(self.pg0, self.pg1)
1584 self.pg0.add_stream(pkts)
1585 self.pg_enable_capture(self.pg_interfaces)
1586 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001587 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001588 self.verify_capture_out(capture)
1589
Matus Fabiana5e73762018-12-14 01:55:16 -08001590 err = self.statistics.get_counter(
1591 '/err/nat44-in2out-slowpath/TCP packets')
1592 self.assertEqual(err - tcpn, 1)
1593 err = self.statistics.get_counter(
1594 '/err/nat44-in2out-slowpath/UDP packets')
1595 self.assertEqual(err - udpn, 1)
1596 err = self.statistics.get_counter(
1597 '/err/nat44-in2out-slowpath/ICMP packets')
1598 self.assertEqual(err - icmpn, 1)
1599 err = self.statistics.get_counter(
1600 '/err/nat44-in2out-slowpath/good in2out packets processed')
1601 self.assertEqual(err - totaln, 3)
1602
Matus Fabiande886752016-12-07 03:38:19 -08001603 # out2in
Matus Fabiana5e73762018-12-14 01:55:16 -08001604 tcpn = self.statistics.get_counter('/err/nat44-out2in/TCP packets')
1605 udpn = self.statistics.get_counter('/err/nat44-out2in/UDP packets')
1606 icmpn = self.statistics.get_counter('/err/nat44-out2in/ICMP packets')
1607 totaln = self.statistics.get_counter(
1608 '/err/nat44-out2in/good out2in packets processed')
1609
Matus Fabiande886752016-12-07 03:38:19 -08001610 pkts = self.create_stream_out(self.pg1)
1611 self.pg1.add_stream(pkts)
1612 self.pg_enable_capture(self.pg_interfaces)
1613 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001614 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001615 self.verify_capture_in(capture, self.pg0)
1616
Matus Fabiana5e73762018-12-14 01:55:16 -08001617 err = self.statistics.get_counter('/err/nat44-out2in/TCP packets')
1618 self.assertEqual(err - tcpn, 1)
1619 err = self.statistics.get_counter('/err/nat44-out2in/UDP packets')
1620 self.assertEqual(err - udpn, 1)
1621 err = self.statistics.get_counter('/err/nat44-out2in/ICMP packets')
1622 self.assertEqual(err - icmpn, 1)
1623 err = self.statistics.get_counter(
1624 '/err/nat44-out2in/good out2in packets processed')
1625 self.assertEqual(err - totaln, 3)
1626
Matus Fabianfd0d5082018-12-18 01:08:51 -08001627 users = self.statistics.get_counter('/nat44/total-users')
1628 self.assertEqual(users[0][0], 1)
1629 sessions = self.statistics.get_counter('/nat44/total-sessions')
1630 self.assertEqual(sessions[0][0], 3)
1631
Juraj Slobodab33f4132017-02-08 23:54:21 -08001632 def test_dynamic_icmp_errors_in2out_ttl_1(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001633 """ NAT44 handling of client packets with TTL=1 """
Juraj Slobodab33f4132017-02-08 23:54:21 -08001634
Matus Fabian2ba92e32017-08-21 07:05:03 -07001635 self.nat44_add_address(self.nat_addr)
1636 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1637 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1638 is_inside=0)
Juraj Slobodab33f4132017-02-08 23:54:21 -08001639
1640 # Client side - generate traffic
1641 pkts = self.create_stream_in(self.pg0, self.pg1, ttl=1)
1642 self.pg0.add_stream(pkts)
1643 self.pg_enable_capture(self.pg_interfaces)
1644 self.pg_start()
1645
1646 # Client side - verify ICMP type 11 packets
1647 capture = self.pg0.get_capture(len(pkts))
1648 self.verify_capture_in_with_icmp_errors(capture, self.pg0)
1649
1650 def test_dynamic_icmp_errors_out2in_ttl_1(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001651 """ NAT44 handling of server packets with TTL=1 """
Juraj Slobodab33f4132017-02-08 23:54:21 -08001652
Matus Fabian2ba92e32017-08-21 07:05:03 -07001653 self.nat44_add_address(self.nat_addr)
1654 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1655 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1656 is_inside=0)
Juraj Slobodab33f4132017-02-08 23:54:21 -08001657
1658 # Client side - create sessions
1659 pkts = self.create_stream_in(self.pg0, self.pg1)
1660 self.pg0.add_stream(pkts)
1661 self.pg_enable_capture(self.pg_interfaces)
1662 self.pg_start()
1663
1664 # Server side - generate traffic
1665 capture = self.pg1.get_capture(len(pkts))
1666 self.verify_capture_out(capture)
1667 pkts = self.create_stream_out(self.pg1, ttl=1)
1668 self.pg1.add_stream(pkts)
1669 self.pg_enable_capture(self.pg_interfaces)
1670 self.pg_start()
1671
1672 # Server side - verify ICMP type 11 packets
1673 capture = self.pg1.get_capture(len(pkts))
1674 self.verify_capture_out_with_icmp_errors(capture,
1675 src_ip=self.pg1.local_ip4)
1676
1677 def test_dynamic_icmp_errors_in2out_ttl_2(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001678 """ NAT44 handling of error responses to client packets with TTL=2 """
Juraj Slobodab33f4132017-02-08 23:54:21 -08001679
Matus Fabian2ba92e32017-08-21 07:05:03 -07001680 self.nat44_add_address(self.nat_addr)
1681 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1682 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1683 is_inside=0)
Juraj Slobodab33f4132017-02-08 23:54:21 -08001684
1685 # Client side - generate traffic
1686 pkts = self.create_stream_in(self.pg0, self.pg1, ttl=2)
1687 self.pg0.add_stream(pkts)
1688 self.pg_enable_capture(self.pg_interfaces)
1689 self.pg_start()
1690
1691 # Server side - simulate ICMP type 11 response
1692 capture = self.pg1.get_capture(len(pkts))
1693 pkts = [Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07001694 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Juraj Slobodab33f4132017-02-08 23:54:21 -08001695 ICMP(type=11) / packet[IP] for packet in capture]
1696 self.pg1.add_stream(pkts)
1697 self.pg_enable_capture(self.pg_interfaces)
1698 self.pg_start()
1699
1700 # Client side - verify ICMP type 11 packets
1701 capture = self.pg0.get_capture(len(pkts))
1702 self.verify_capture_in_with_icmp_errors(capture, self.pg0)
1703
1704 def test_dynamic_icmp_errors_out2in_ttl_2(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001705 """ NAT44 handling of error responses to server packets with TTL=2 """
Juraj Slobodab33f4132017-02-08 23:54:21 -08001706
Matus Fabian2ba92e32017-08-21 07:05:03 -07001707 self.nat44_add_address(self.nat_addr)
1708 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1709 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1710 is_inside=0)
Juraj Slobodab33f4132017-02-08 23:54:21 -08001711
1712 # Client side - create sessions
1713 pkts = self.create_stream_in(self.pg0, self.pg1)
1714 self.pg0.add_stream(pkts)
1715 self.pg_enable_capture(self.pg_interfaces)
1716 self.pg_start()
1717
1718 # Server side - generate traffic
1719 capture = self.pg1.get_capture(len(pkts))
1720 self.verify_capture_out(capture)
1721 pkts = self.create_stream_out(self.pg1, ttl=2)
1722 self.pg1.add_stream(pkts)
1723 self.pg_enable_capture(self.pg_interfaces)
1724 self.pg_start()
1725
1726 # Client side - simulate ICMP type 11 response
1727 capture = self.pg0.get_capture(len(pkts))
1728 pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1729 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
1730 ICMP(type=11) / packet[IP] for packet in capture]
1731 self.pg0.add_stream(pkts)
1732 self.pg_enable_capture(self.pg_interfaces)
1733 self.pg_start()
1734
1735 # Server side - verify ICMP type 11 packets
1736 capture = self.pg1.get_capture(len(pkts))
1737 self.verify_capture_out_with_icmp_errors(capture)
1738
Juraj Sloboda665e4822017-02-16 17:17:19 -08001739 def test_ping_out_interface_from_outside(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001740 """ Ping NAT44 out interface from outside network """
Juraj Sloboda665e4822017-02-16 17:17:19 -08001741
Matus Fabian2ba92e32017-08-21 07:05:03 -07001742 self.nat44_add_address(self.nat_addr)
1743 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1744 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1745 is_inside=0)
Juraj Sloboda665e4822017-02-16 17:17:19 -08001746
1747 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1748 IP(src=self.pg1.remote_ip4, dst=self.pg1.local_ip4) /
1749 ICMP(id=self.icmp_id_out, type='echo-request'))
1750 pkts = [p]
1751 self.pg1.add_stream(pkts)
1752 self.pg_enable_capture(self.pg_interfaces)
1753 self.pg_start()
1754 capture = self.pg1.get_capture(len(pkts))
Juraj Sloboda665e4822017-02-16 17:17:19 -08001755 packet = capture[0]
1756 try:
1757 self.assertEqual(packet[IP].src, self.pg1.local_ip4)
1758 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
1759 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
1760 self.assertEqual(packet[ICMP].type, 0) # echo reply
1761 except:
1762 self.logger.error(ppp("Unexpected or invalid packet "
1763 "(outside network):", packet))
1764 raise
1765
Juraj Slobodad3677682017-04-14 03:24:45 +02001766 def test_ping_internal_host_from_outside(self):
1767 """ Ping internal host from outside network """
1768
Matus Fabian2ba92e32017-08-21 07:05:03 -07001769 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr)
1770 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1771 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1772 is_inside=0)
Juraj Slobodad3677682017-04-14 03:24:45 +02001773
1774 # out2in
1775 pkt = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07001776 IP(src=self.pg1.remote_ip4, dst=self.nat_addr, ttl=64) /
Juraj Slobodad3677682017-04-14 03:24:45 +02001777 ICMP(id=self.icmp_id_out, type='echo-request'))
1778 self.pg1.add_stream(pkt)
1779 self.pg_enable_capture(self.pg_interfaces)
1780 self.pg_start()
1781 capture = self.pg0.get_capture(1)
Matus Fabian05ca4a32018-09-04 23:45:13 -07001782 self.verify_capture_in(capture, self.pg0)
Juraj Slobodad3677682017-04-14 03:24:45 +02001783 self.assert_equal(capture[0][IP].proto, IP_PROTOS.icmp)
1784
1785 # in2out
1786 pkt = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1787 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4, ttl=64) /
1788 ICMP(id=self.icmp_id_in, type='echo-reply'))
1789 self.pg0.add_stream(pkt)
1790 self.pg_enable_capture(self.pg_interfaces)
1791 self.pg_start()
1792 capture = self.pg1.get_capture(1)
Matus Fabian05ca4a32018-09-04 23:45:13 -07001793 self.verify_capture_out(capture, same_port=True)
Juraj Slobodad3677682017-04-14 03:24:45 +02001794 self.assert_equal(capture[0][IP].proto, IP_PROTOS.icmp)
1795
Matus Fabianc79396e2018-07-23 00:05:22 -07001796 def test_forwarding(self):
Juraj Sloboda7b929792017-11-23 13:20:48 +01001797 """ NAT44 forwarding test """
1798
1799 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1800 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1801 is_inside=0)
1802 self.vapi.nat44_forwarding_enable_disable(1)
1803
1804 real_ip = self.pg0.remote_ip4n
1805 alias_ip = self.nat_addr_n
1806 self.vapi.nat44_add_del_static_mapping(local_ip=real_ip,
1807 external_ip=alias_ip)
1808
1809 try:
Matus Fabianc79396e2018-07-23 00:05:22 -07001810 # static mapping match
Juraj Sloboda7b929792017-11-23 13:20:48 +01001811
1812 pkts = self.create_stream_out(self.pg1)
1813 self.pg1.add_stream(pkts)
1814 self.pg_enable_capture(self.pg_interfaces)
1815 self.pg_start()
1816 capture = self.pg0.get_capture(len(pkts))
1817 self.verify_capture_in(capture, self.pg0)
1818
1819 pkts = self.create_stream_in(self.pg0, self.pg1)
1820 self.pg0.add_stream(pkts)
1821 self.pg_enable_capture(self.pg_interfaces)
1822 self.pg_start()
1823 capture = self.pg1.get_capture(len(pkts))
1824 self.verify_capture_out(capture, same_port=True)
1825
Matus Fabianc79396e2018-07-23 00:05:22 -07001826 # no static mapping match
Juraj Sloboda7b929792017-11-23 13:20:48 +01001827
1828 host0 = self.pg0.remote_hosts[0]
1829 self.pg0.remote_hosts[0] = self.pg0.remote_hosts[1]
1830 try:
1831 pkts = self.create_stream_out(self.pg1,
1832 dst_ip=self.pg0.remote_ip4,
1833 use_inside_ports=True)
1834 self.pg1.add_stream(pkts)
1835 self.pg_enable_capture(self.pg_interfaces)
1836 self.pg_start()
1837 capture = self.pg0.get_capture(len(pkts))
1838 self.verify_capture_in(capture, self.pg0)
1839
1840 pkts = self.create_stream_in(self.pg0, self.pg1)
1841 self.pg0.add_stream(pkts)
1842 self.pg_enable_capture(self.pg_interfaces)
1843 self.pg_start()
1844 capture = self.pg1.get_capture(len(pkts))
1845 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
1846 same_port=True)
1847 finally:
1848 self.pg0.remote_hosts[0] = host0
1849
1850 finally:
1851 self.vapi.nat44_forwarding_enable_disable(0)
1852 self.vapi.nat44_add_del_static_mapping(local_ip=real_ip,
1853 external_ip=alias_ip,
1854 is_add=0)
1855
Matus Fabiande886752016-12-07 03:38:19 -08001856 def test_static_in(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001857 """ 1:1 NAT initialized from inside network """
Matus Fabiande886752016-12-07 03:38:19 -08001858
1859 nat_ip = "10.0.0.10"
1860 self.tcp_port_out = 6303
1861 self.udp_port_out = 6304
1862 self.icmp_id_out = 6305
1863
Matus Fabian2ba92e32017-08-21 07:05:03 -07001864 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
1865 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1866 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1867 is_inside=0)
Matus Fabian5f224992018-01-25 21:59:16 -08001868 sm = self.vapi.nat44_static_mapping_dump()
1869 self.assertEqual(len(sm), 1)
Paul Vinciguerra22ab6f72019-03-07 17:55:33 -08001870 self.assertEqual((sm[0].tag).split(b'\0', 1)[0], b'')
Matus Fabian9dba7812018-01-31 01:13:23 -08001871 self.assertEqual(sm[0].protocol, 0)
1872 self.assertEqual(sm[0].local_port, 0)
1873 self.assertEqual(sm[0].external_port, 0)
Matus Fabiande886752016-12-07 03:38:19 -08001874
1875 # in2out
1876 pkts = self.create_stream_in(self.pg0, self.pg1)
1877 self.pg0.add_stream(pkts)
1878 self.pg_enable_capture(self.pg_interfaces)
1879 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001880 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001881 self.verify_capture_out(capture, nat_ip, True)
1882
1883 # out2in
1884 pkts = self.create_stream_out(self.pg1, nat_ip)
1885 self.pg1.add_stream(pkts)
1886 self.pg_enable_capture(self.pg_interfaces)
1887 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001888 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001889 self.verify_capture_in(capture, self.pg0)
1890
1891 def test_static_out(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001892 """ 1:1 NAT initialized from outside network """
Matus Fabiande886752016-12-07 03:38:19 -08001893
1894 nat_ip = "10.0.0.20"
1895 self.tcp_port_out = 6303
1896 self.udp_port_out = 6304
1897 self.icmp_id_out = 6305
Paul Vinciguerra22ab6f72019-03-07 17:55:33 -08001898 tag = b"testTAG"
Matus Fabiande886752016-12-07 03:38:19 -08001899
Matus Fabian5f224992018-01-25 21:59:16 -08001900 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip, tag=tag)
Matus Fabian2ba92e32017-08-21 07:05:03 -07001901 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1902 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1903 is_inside=0)
Matus Fabian5f224992018-01-25 21:59:16 -08001904 sm = self.vapi.nat44_static_mapping_dump()
1905 self.assertEqual(len(sm), 1)
Paul Vinciguerra22ab6f72019-03-07 17:55:33 -08001906 self.assertEqual((sm[0].tag).split(b'\0', 1)[0], tag)
Matus Fabiande886752016-12-07 03:38:19 -08001907
1908 # out2in
1909 pkts = self.create_stream_out(self.pg1, nat_ip)
1910 self.pg1.add_stream(pkts)
1911 self.pg_enable_capture(self.pg_interfaces)
1912 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001913 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001914 self.verify_capture_in(capture, self.pg0)
1915
1916 # in2out
1917 pkts = self.create_stream_in(self.pg0, self.pg1)
1918 self.pg0.add_stream(pkts)
1919 self.pg_enable_capture(self.pg_interfaces)
1920 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001921 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001922 self.verify_capture_out(capture, nat_ip, True)
1923
1924 def test_static_with_port_in(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001925 """ 1:1 NAPT initialized from inside network """
Matus Fabiande886752016-12-07 03:38:19 -08001926
1927 self.tcp_port_out = 3606
1928 self.udp_port_out = 3607
1929 self.icmp_id_out = 3608
1930
Matus Fabian2ba92e32017-08-21 07:05:03 -07001931 self.nat44_add_address(self.nat_addr)
1932 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1933 self.tcp_port_in, self.tcp_port_out,
1934 proto=IP_PROTOS.tcp)
1935 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1936 self.udp_port_in, self.udp_port_out,
1937 proto=IP_PROTOS.udp)
1938 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1939 self.icmp_id_in, self.icmp_id_out,
1940 proto=IP_PROTOS.icmp)
1941 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1942 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1943 is_inside=0)
Matus Fabiande886752016-12-07 03:38:19 -08001944
1945 # in2out
1946 pkts = self.create_stream_in(self.pg0, self.pg1)
1947 self.pg0.add_stream(pkts)
1948 self.pg_enable_capture(self.pg_interfaces)
1949 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001950 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001951 self.verify_capture_out(capture)
1952
1953 # out2in
1954 pkts = self.create_stream_out(self.pg1)
1955 self.pg1.add_stream(pkts)
1956 self.pg_enable_capture(self.pg_interfaces)
1957 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001958 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001959 self.verify_capture_in(capture, self.pg0)
1960
1961 def test_static_with_port_out(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001962 """ 1:1 NAPT initialized from outside network """
Matus Fabiande886752016-12-07 03:38:19 -08001963
1964 self.tcp_port_out = 30606
1965 self.udp_port_out = 30607
1966 self.icmp_id_out = 30608
1967
Matus Fabian2ba92e32017-08-21 07:05:03 -07001968 self.nat44_add_address(self.nat_addr)
1969 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1970 self.tcp_port_in, self.tcp_port_out,
1971 proto=IP_PROTOS.tcp)
1972 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1973 self.udp_port_in, self.udp_port_out,
1974 proto=IP_PROTOS.udp)
1975 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1976 self.icmp_id_in, self.icmp_id_out,
1977 proto=IP_PROTOS.icmp)
1978 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1979 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1980 is_inside=0)
Matus Fabiande886752016-12-07 03:38:19 -08001981
1982 # out2in
1983 pkts = self.create_stream_out(self.pg1)
1984 self.pg1.add_stream(pkts)
1985 self.pg_enable_capture(self.pg_interfaces)
1986 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001987 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001988 self.verify_capture_in(capture, self.pg0)
1989
1990 # in2out
1991 pkts = self.create_stream_in(self.pg0, self.pg1)
1992 self.pg0.add_stream(pkts)
1993 self.pg_enable_capture(self.pg_interfaces)
1994 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01001995 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08001996 self.verify_capture_out(capture)
1997
1998 def test_static_vrf_aware(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07001999 """ 1:1 NAT VRF awareness """
Matus Fabiande886752016-12-07 03:38:19 -08002000
2001 nat_ip1 = "10.0.0.30"
2002 nat_ip2 = "10.0.0.40"
2003 self.tcp_port_out = 6303
2004 self.udp_port_out = 6304
2005 self.icmp_id_out = 6305
2006
Matus Fabian2ba92e32017-08-21 07:05:03 -07002007 self.nat44_add_static_mapping(self.pg4.remote_ip4, nat_ip1,
2008 vrf_id=10)
2009 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip2,
2010 vrf_id=10)
2011 self.vapi.nat44_interface_add_del_feature(self.pg3.sw_if_index,
2012 is_inside=0)
2013 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2014 self.vapi.nat44_interface_add_del_feature(self.pg4.sw_if_index)
Matus Fabiande886752016-12-07 03:38:19 -08002015
Matus Fabian2ba92e32017-08-21 07:05:03 -07002016 # inside interface VRF match NAT44 static mapping VRF
Matus Fabiande886752016-12-07 03:38:19 -08002017 pkts = self.create_stream_in(self.pg4, self.pg3)
2018 self.pg4.add_stream(pkts)
2019 self.pg_enable_capture(self.pg_interfaces)
2020 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002021 capture = self.pg3.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002022 self.verify_capture_out(capture, nat_ip1, True)
2023
Matus Fabian2ba92e32017-08-21 07:05:03 -07002024 # inside interface VRF don't match NAT44 static mapping VRF (packets
Matus Fabiande886752016-12-07 03:38:19 -08002025 # are dropped)
2026 pkts = self.create_stream_in(self.pg0, self.pg3)
2027 self.pg0.add_stream(pkts)
2028 self.pg_enable_capture(self.pg_interfaces)
2029 self.pg_start()
Klement Sekera9225dee2016-12-12 08:36:58 +01002030 self.pg3.assert_nothing_captured()
Matus Fabiande886752016-12-07 03:38:19 -08002031
Matus Fabianb793d092018-01-31 05:50:21 -08002032 def test_dynamic_to_static(self):
2033 """ Switch from dynamic translation to 1:1NAT """
2034 nat_ip = "10.0.0.10"
2035 self.tcp_port_out = 6303
2036 self.udp_port_out = 6304
2037 self.icmp_id_out = 6305
2038
2039 self.nat44_add_address(self.nat_addr)
2040 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2041 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2042 is_inside=0)
2043
2044 # dynamic
2045 pkts = self.create_stream_in(self.pg0, self.pg1)
2046 self.pg0.add_stream(pkts)
2047 self.pg_enable_capture(self.pg_interfaces)
2048 self.pg_start()
2049 capture = self.pg1.get_capture(len(pkts))
2050 self.verify_capture_out(capture)
2051
2052 # 1:1NAT
2053 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
2054 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
2055 self.assertEqual(len(sessions), 0)
2056 pkts = self.create_stream_in(self.pg0, self.pg1)
2057 self.pg0.add_stream(pkts)
2058 self.pg_enable_capture(self.pg_interfaces)
2059 self.pg_start()
2060 capture = self.pg1.get_capture(len(pkts))
2061 self.verify_capture_out(capture, nat_ip, True)
2062
Matus Fabianab7a8052017-11-28 04:29:41 -08002063 def test_identity_nat(self):
2064 """ Identity NAT """
2065
2066 self.vapi.nat44_add_del_identity_mapping(ip=self.pg0.remote_ip4n)
2067 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2068 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2069 is_inside=0)
2070
2071 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
2072 IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
2073 TCP(sport=12345, dport=56789))
2074 self.pg1.add_stream(p)
2075 self.pg_enable_capture(self.pg_interfaces)
2076 self.pg_start()
2077 capture = self.pg0.get_capture(1)
2078 p = capture[0]
2079 try:
2080 ip = p[IP]
2081 tcp = p[TCP]
2082 self.assertEqual(ip.dst, self.pg0.remote_ip4)
2083 self.assertEqual(ip.src, self.pg1.remote_ip4)
2084 self.assertEqual(tcp.dport, 56789)
2085 self.assertEqual(tcp.sport, 12345)
Klement Sekerad81ae412018-05-16 10:52:54 +02002086 self.assert_packet_checksums_valid(p)
Matus Fabianab7a8052017-11-28 04:29:41 -08002087 except:
2088 self.logger.error(ppp("Unexpected or invalid packet:", p))
2089 raise
2090
Matus Fabiane2f4e2f2018-10-07 21:28:23 -07002091 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
2092 self.assertEqual(len(sessions), 0)
Matus Fabian82b4ceb2018-10-11 04:28:48 -07002093 self.vapi.nat44_add_del_identity_mapping(ip=self.pg0.remote_ip4n,
2094 vrf_id=1)
2095 identity_mappings = self.vapi.nat44_identity_mapping_dump()
2096 self.assertEqual(len(identity_mappings), 2)
Matus Fabiane2f4e2f2018-10-07 21:28:23 -07002097
Matus Fabiande886752016-12-07 03:38:19 -08002098 def test_multiple_inside_interfaces(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002099 """ NAT44 multiple non-overlapping address space inside interfaces """
Matus Fabiande886752016-12-07 03:38:19 -08002100
Matus Fabian2ba92e32017-08-21 07:05:03 -07002101 self.nat44_add_address(self.nat_addr)
2102 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2103 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
2104 self.vapi.nat44_interface_add_del_feature(self.pg3.sw_if_index,
2105 is_inside=0)
Matus Fabiande886752016-12-07 03:38:19 -08002106
Matus Fabian2ba92e32017-08-21 07:05:03 -07002107 # between two NAT44 inside interfaces (no translation)
Matus Fabian675a69c2017-01-18 01:46:01 -08002108 pkts = self.create_stream_in(self.pg0, self.pg1)
2109 self.pg0.add_stream(pkts)
2110 self.pg_enable_capture(self.pg_interfaces)
2111 self.pg_start()
2112 capture = self.pg1.get_capture(len(pkts))
2113 self.verify_capture_no_translation(capture, self.pg0, self.pg1)
2114
Matus Fabian2ba92e32017-08-21 07:05:03 -07002115 # from NAT44 inside to interface without NAT44 feature (no translation)
Matus Fabian675a69c2017-01-18 01:46:01 -08002116 pkts = self.create_stream_in(self.pg0, self.pg2)
2117 self.pg0.add_stream(pkts)
2118 self.pg_enable_capture(self.pg_interfaces)
2119 self.pg_start()
2120 capture = self.pg2.get_capture(len(pkts))
2121 self.verify_capture_no_translation(capture, self.pg0, self.pg2)
2122
Matus Fabiande886752016-12-07 03:38:19 -08002123 # in2out 1st interface
2124 pkts = self.create_stream_in(self.pg0, self.pg3)
2125 self.pg0.add_stream(pkts)
2126 self.pg_enable_capture(self.pg_interfaces)
2127 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002128 capture = self.pg3.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002129 self.verify_capture_out(capture)
2130
2131 # out2in 1st interface
2132 pkts = self.create_stream_out(self.pg3)
2133 self.pg3.add_stream(pkts)
2134 self.pg_enable_capture(self.pg_interfaces)
2135 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002136 capture = self.pg0.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002137 self.verify_capture_in(capture, self.pg0)
2138
2139 # in2out 2nd interface
2140 pkts = self.create_stream_in(self.pg1, self.pg3)
2141 self.pg1.add_stream(pkts)
2142 self.pg_enable_capture(self.pg_interfaces)
2143 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002144 capture = self.pg3.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002145 self.verify_capture_out(capture)
2146
2147 # out2in 2nd interface
2148 pkts = self.create_stream_out(self.pg3)
2149 self.pg3.add_stream(pkts)
2150 self.pg_enable_capture(self.pg_interfaces)
2151 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002152 capture = self.pg1.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002153 self.verify_capture_in(capture, self.pg1)
2154
Matus Fabiande886752016-12-07 03:38:19 -08002155 def test_inside_overlapping_interfaces(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002156 """ NAT44 multiple inside interfaces with overlapping address space """
Matus Fabiande886752016-12-07 03:38:19 -08002157
Matus Fabian675a69c2017-01-18 01:46:01 -08002158 static_nat_ip = "10.0.0.10"
Matus Fabian2ba92e32017-08-21 07:05:03 -07002159 self.nat44_add_address(self.nat_addr)
2160 self.vapi.nat44_interface_add_del_feature(self.pg3.sw_if_index,
2161 is_inside=0)
2162 self.vapi.nat44_interface_add_del_feature(self.pg4.sw_if_index)
2163 self.vapi.nat44_interface_add_del_feature(self.pg5.sw_if_index)
2164 self.vapi.nat44_interface_add_del_feature(self.pg6.sw_if_index)
2165 self.nat44_add_static_mapping(self.pg6.remote_ip4, static_nat_ip,
2166 vrf_id=20)
Matus Fabian675a69c2017-01-18 01:46:01 -08002167
Matus Fabian2ba92e32017-08-21 07:05:03 -07002168 # between NAT44 inside interfaces with same VRF (no translation)
Matus Fabian675a69c2017-01-18 01:46:01 -08002169 pkts = self.create_stream_in(self.pg4, self.pg5)
2170 self.pg4.add_stream(pkts)
2171 self.pg_enable_capture(self.pg_interfaces)
2172 self.pg_start()
2173 capture = self.pg5.get_capture(len(pkts))
2174 self.verify_capture_no_translation(capture, self.pg4, self.pg5)
2175
Matus Fabian2ba92e32017-08-21 07:05:03 -07002176 # between NAT44 inside interfaces with different VRF (hairpinning)
Matus Fabian675a69c2017-01-18 01:46:01 -08002177 p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
2178 IP(src=self.pg4.remote_ip4, dst=static_nat_ip) /
2179 TCP(sport=1234, dport=5678))
2180 self.pg4.add_stream(p)
2181 self.pg_enable_capture(self.pg_interfaces)
2182 self.pg_start()
2183 capture = self.pg6.get_capture(1)
2184 p = capture[0]
2185 try:
2186 ip = p[IP]
2187 tcp = p[TCP]
Matus Fabian2ba92e32017-08-21 07:05:03 -07002188 self.assertEqual(ip.src, self.nat_addr)
Matus Fabian675a69c2017-01-18 01:46:01 -08002189 self.assertEqual(ip.dst, self.pg6.remote_ip4)
2190 self.assertNotEqual(tcp.sport, 1234)
2191 self.assertEqual(tcp.dport, 5678)
2192 except:
2193 self.logger.error(ppp("Unexpected or invalid packet:", p))
2194 raise
Matus Fabiande886752016-12-07 03:38:19 -08002195
2196 # in2out 1st interface
2197 pkts = self.create_stream_in(self.pg4, self.pg3)
2198 self.pg4.add_stream(pkts)
2199 self.pg_enable_capture(self.pg_interfaces)
2200 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002201 capture = self.pg3.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002202 self.verify_capture_out(capture)
2203
2204 # out2in 1st interface
2205 pkts = self.create_stream_out(self.pg3)
2206 self.pg3.add_stream(pkts)
2207 self.pg_enable_capture(self.pg_interfaces)
2208 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002209 capture = self.pg4.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002210 self.verify_capture_in(capture, self.pg4)
2211
2212 # in2out 2nd interface
2213 pkts = self.create_stream_in(self.pg5, self.pg3)
2214 self.pg5.add_stream(pkts)
2215 self.pg_enable_capture(self.pg_interfaces)
2216 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002217 capture = self.pg3.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002218 self.verify_capture_out(capture)
2219
2220 # out2in 2nd interface
2221 pkts = self.create_stream_out(self.pg3)
2222 self.pg3.add_stream(pkts)
2223 self.pg_enable_capture(self.pg_interfaces)
2224 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002225 capture = self.pg5.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002226 self.verify_capture_in(capture, self.pg5)
2227
magalik23caa882017-02-08 23:25:45 -08002228 # pg5 session dump
Matus Fabian2ba92e32017-08-21 07:05:03 -07002229 addresses = self.vapi.nat44_address_dump()
magalik23caa882017-02-08 23:25:45 -08002230 self.assertEqual(len(addresses), 1)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002231 sessions = self.vapi.nat44_user_session_dump(self.pg5.remote_ip4n, 10)
magalik23caa882017-02-08 23:25:45 -08002232 self.assertEqual(len(sessions), 3)
2233 for session in sessions:
2234 self.assertFalse(session.is_static)
2235 self.assertEqual(session.inside_ip_address[0:4],
2236 self.pg5.remote_ip4n)
2237 self.assertEqual(session.outside_ip_address,
2238 addresses[0].ip_address)
2239 self.assertEqual(sessions[0].protocol, IP_PROTOS.tcp)
2240 self.assertEqual(sessions[1].protocol, IP_PROTOS.udp)
2241 self.assertEqual(sessions[2].protocol, IP_PROTOS.icmp)
2242 self.assertEqual(sessions[0].inside_port, self.tcp_port_in)
2243 self.assertEqual(sessions[1].inside_port, self.udp_port_in)
2244 self.assertEqual(sessions[2].inside_port, self.icmp_id_in)
2245 self.assertEqual(sessions[0].outside_port, self.tcp_port_out)
2246 self.assertEqual(sessions[1].outside_port, self.udp_port_out)
2247 self.assertEqual(sessions[2].outside_port, self.icmp_id_out)
2248
Matus Fabiande886752016-12-07 03:38:19 -08002249 # in2out 3rd interface
2250 pkts = self.create_stream_in(self.pg6, self.pg3)
2251 self.pg6.add_stream(pkts)
2252 self.pg_enable_capture(self.pg_interfaces)
2253 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002254 capture = self.pg3.get_capture(len(pkts))
Matus Fabian675a69c2017-01-18 01:46:01 -08002255 self.verify_capture_out(capture, static_nat_ip, True)
Matus Fabiande886752016-12-07 03:38:19 -08002256
2257 # out2in 3rd interface
Matus Fabian675a69c2017-01-18 01:46:01 -08002258 pkts = self.create_stream_out(self.pg3, static_nat_ip)
Matus Fabiande886752016-12-07 03:38:19 -08002259 self.pg3.add_stream(pkts)
2260 self.pg_enable_capture(self.pg_interfaces)
2261 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002262 capture = self.pg6.get_capture(len(pkts))
Matus Fabiande886752016-12-07 03:38:19 -08002263 self.verify_capture_in(capture, self.pg6)
2264
magalik23caa882017-02-08 23:25:45 -08002265 # general user and session dump verifications
Matus Fabian2ba92e32017-08-21 07:05:03 -07002266 users = self.vapi.nat44_user_dump()
Paul Vinciguerra3d2df212018-11-24 23:19:53 -08002267 self.assertGreaterEqual(len(users), 3)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002268 addresses = self.vapi.nat44_address_dump()
magalik23caa882017-02-08 23:25:45 -08002269 self.assertEqual(len(addresses), 1)
2270 for user in users:
Matus Fabian2ba92e32017-08-21 07:05:03 -07002271 sessions = self.vapi.nat44_user_session_dump(user.ip_address,
2272 user.vrf_id)
magalik23caa882017-02-08 23:25:45 -08002273 for session in sessions:
2274 self.assertEqual(user.ip_address, session.inside_ip_address)
2275 self.assertTrue(session.total_bytes > session.total_pkts > 0)
2276 self.assertTrue(session.protocol in
2277 [IP_PROTOS.tcp, IP_PROTOS.udp,
2278 IP_PROTOS.icmp])
Matus Fabian70a26ac2018-05-14 06:20:28 -07002279 self.assertFalse(session.ext_host_valid)
magalik23caa882017-02-08 23:25:45 -08002280
2281 # pg4 session dump
Matus Fabian2ba92e32017-08-21 07:05:03 -07002282 sessions = self.vapi.nat44_user_session_dump(self.pg4.remote_ip4n, 10)
Paul Vinciguerra3d2df212018-11-24 23:19:53 -08002283 self.assertGreaterEqual(len(sessions), 4)
magalik23caa882017-02-08 23:25:45 -08002284 for session in sessions:
2285 self.assertFalse(session.is_static)
2286 self.assertEqual(session.inside_ip_address[0:4],
2287 self.pg4.remote_ip4n)
2288 self.assertEqual(session.outside_ip_address,
2289 addresses[0].ip_address)
2290
2291 # pg6 session dump
Matus Fabian2ba92e32017-08-21 07:05:03 -07002292 sessions = self.vapi.nat44_user_session_dump(self.pg6.remote_ip4n, 20)
Paul Vinciguerra3d2df212018-11-24 23:19:53 -08002293 self.assertGreaterEqual(len(sessions), 3)
magalik23caa882017-02-08 23:25:45 -08002294 for session in sessions:
2295 self.assertTrue(session.is_static)
2296 self.assertEqual(session.inside_ip_address[0:4],
2297 self.pg6.remote_ip4n)
Matus Fabian34931eb2019-02-26 09:05:23 -08002298 self.assertEqual(session.outside_ip_address,
2299 socket.inet_pton(socket.AF_INET, static_nat_ip))
magalik23caa882017-02-08 23:25:45 -08002300 self.assertTrue(session.inside_port in
2301 [self.tcp_port_in, self.udp_port_in,
2302 self.icmp_id_in])
2303
Matus Fabianf78a70d2016-12-12 04:30:39 -08002304 def test_hairpinning(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002305 """ NAT44 hairpinning - 1:1 NAPT """
Matus Fabianf78a70d2016-12-12 04:30:39 -08002306
2307 host = self.pg0.remote_hosts[0]
2308 server = self.pg0.remote_hosts[1]
2309 host_in_port = 1234
2310 host_out_port = 0
2311 server_in_port = 5678
2312 server_out_port = 8765
2313
Matus Fabian2ba92e32017-08-21 07:05:03 -07002314 self.nat44_add_address(self.nat_addr)
2315 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2316 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2317 is_inside=0)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002318 # add static mapping for server
Matus Fabian2ba92e32017-08-21 07:05:03 -07002319 self.nat44_add_static_mapping(server.ip4, self.nat_addr,
2320 server_in_port, server_out_port,
2321 proto=IP_PROTOS.tcp)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002322
2323 # send packet from host to server
2324 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002325 IP(src=host.ip4, dst=self.nat_addr) /
Matus Fabianf78a70d2016-12-12 04:30:39 -08002326 TCP(sport=host_in_port, dport=server_out_port))
2327 self.pg0.add_stream(p)
2328 self.pg_enable_capture(self.pg_interfaces)
2329 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002330 capture = self.pg0.get_capture(1)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002331 p = capture[0]
2332 try:
2333 ip = p[IP]
2334 tcp = p[TCP]
Matus Fabian2ba92e32017-08-21 07:05:03 -07002335 self.assertEqual(ip.src, self.nat_addr)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002336 self.assertEqual(ip.dst, server.ip4)
2337 self.assertNotEqual(tcp.sport, host_in_port)
2338 self.assertEqual(tcp.dport, server_in_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02002339 self.assert_packet_checksums_valid(p)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002340 host_out_port = tcp.sport
2341 except:
Klement Sekera9225dee2016-12-12 08:36:58 +01002342 self.logger.error(ppp("Unexpected or invalid packet:", p))
Matus Fabianf78a70d2016-12-12 04:30:39 -08002343 raise
2344
2345 # send reply from server to host
2346 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002347 IP(src=server.ip4, dst=self.nat_addr) /
Matus Fabianf78a70d2016-12-12 04:30:39 -08002348 TCP(sport=server_in_port, dport=host_out_port))
2349 self.pg0.add_stream(p)
2350 self.pg_enable_capture(self.pg_interfaces)
2351 self.pg_start()
Klement Sekeradab231a2016-12-21 08:50:14 +01002352 capture = self.pg0.get_capture(1)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002353 p = capture[0]
2354 try:
2355 ip = p[IP]
2356 tcp = p[TCP]
Matus Fabian2ba92e32017-08-21 07:05:03 -07002357 self.assertEqual(ip.src, self.nat_addr)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002358 self.assertEqual(ip.dst, host.ip4)
2359 self.assertEqual(tcp.sport, server_out_port)
2360 self.assertEqual(tcp.dport, host_in_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02002361 self.assert_packet_checksums_valid(p)
Matus Fabianf78a70d2016-12-12 04:30:39 -08002362 except:
Matus Fabiane82488f2018-01-18 03:38:45 -08002363 self.logger.error(ppp("Unexpected or invalid packet:", p))
Matus Fabianf78a70d2016-12-12 04:30:39 -08002364 raise
2365
Matus Fabian6fa74c62017-06-05 05:55:48 -07002366 def test_hairpinning2(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002367 """ NAT44 hairpinning - 1:1 NAT"""
Matus Fabian6fa74c62017-06-05 05:55:48 -07002368
2369 server1_nat_ip = "10.0.0.10"
2370 server2_nat_ip = "10.0.0.11"
2371 host = self.pg0.remote_hosts[0]
2372 server1 = self.pg0.remote_hosts[1]
2373 server2 = self.pg0.remote_hosts[2]
2374 server_tcp_port = 22
2375 server_udp_port = 20
2376
Matus Fabian2ba92e32017-08-21 07:05:03 -07002377 self.nat44_add_address(self.nat_addr)
2378 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2379 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2380 is_inside=0)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002381
2382 # add static mapping for servers
Matus Fabian2ba92e32017-08-21 07:05:03 -07002383 self.nat44_add_static_mapping(server1.ip4, server1_nat_ip)
2384 self.nat44_add_static_mapping(server2.ip4, server2_nat_ip)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002385
2386 # host to server1
2387 pkts = []
2388 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2389 IP(src=host.ip4, dst=server1_nat_ip) /
2390 TCP(sport=self.tcp_port_in, dport=server_tcp_port))
2391 pkts.append(p)
2392 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2393 IP(src=host.ip4, dst=server1_nat_ip) /
2394 UDP(sport=self.udp_port_in, dport=server_udp_port))
2395 pkts.append(p)
2396 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2397 IP(src=host.ip4, dst=server1_nat_ip) /
2398 ICMP(id=self.icmp_id_in, type='echo-request'))
2399 pkts.append(p)
2400 self.pg0.add_stream(pkts)
2401 self.pg_enable_capture(self.pg_interfaces)
2402 self.pg_start()
2403 capture = self.pg0.get_capture(len(pkts))
2404 for packet in capture:
2405 try:
Matus Fabian2ba92e32017-08-21 07:05:03 -07002406 self.assertEqual(packet[IP].src, self.nat_addr)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002407 self.assertEqual(packet[IP].dst, server1.ip4)
2408 if packet.haslayer(TCP):
2409 self.assertNotEqual(packet[TCP].sport, self.tcp_port_in)
2410 self.assertEqual(packet[TCP].dport, server_tcp_port)
2411 self.tcp_port_out = packet[TCP].sport
Klement Sekerad81ae412018-05-16 10:52:54 +02002412 self.assert_packet_checksums_valid(packet)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002413 elif packet.haslayer(UDP):
2414 self.assertNotEqual(packet[UDP].sport, self.udp_port_in)
2415 self.assertEqual(packet[UDP].dport, server_udp_port)
2416 self.udp_port_out = packet[UDP].sport
2417 else:
2418 self.assertNotEqual(packet[ICMP].id, self.icmp_id_in)
2419 self.icmp_id_out = packet[ICMP].id
2420 except:
2421 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2422 raise
2423
2424 # server1 to host
2425 pkts = []
2426 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002427 IP(src=server1.ip4, dst=self.nat_addr) /
Matus Fabian6fa74c62017-06-05 05:55:48 -07002428 TCP(sport=server_tcp_port, dport=self.tcp_port_out))
2429 pkts.append(p)
2430 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002431 IP(src=server1.ip4, dst=self.nat_addr) /
Matus Fabian6fa74c62017-06-05 05:55:48 -07002432 UDP(sport=server_udp_port, dport=self.udp_port_out))
2433 pkts.append(p)
2434 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002435 IP(src=server1.ip4, dst=self.nat_addr) /
Matus Fabian6fa74c62017-06-05 05:55:48 -07002436 ICMP(id=self.icmp_id_out, type='echo-reply'))
2437 pkts.append(p)
2438 self.pg0.add_stream(pkts)
2439 self.pg_enable_capture(self.pg_interfaces)
2440 self.pg_start()
2441 capture = self.pg0.get_capture(len(pkts))
2442 for packet in capture:
2443 try:
2444 self.assertEqual(packet[IP].src, server1_nat_ip)
2445 self.assertEqual(packet[IP].dst, host.ip4)
2446 if packet.haslayer(TCP):
2447 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
2448 self.assertEqual(packet[TCP].sport, server_tcp_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02002449 self.assert_packet_checksums_valid(packet)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002450 elif packet.haslayer(UDP):
2451 self.assertEqual(packet[UDP].dport, self.udp_port_in)
2452 self.assertEqual(packet[UDP].sport, server_udp_port)
2453 else:
2454 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
2455 except:
2456 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2457 raise
2458
2459 # server2 to server1
2460 pkts = []
2461 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2462 IP(src=server2.ip4, dst=server1_nat_ip) /
2463 TCP(sport=self.tcp_port_in, dport=server_tcp_port))
2464 pkts.append(p)
2465 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2466 IP(src=server2.ip4, dst=server1_nat_ip) /
2467 UDP(sport=self.udp_port_in, dport=server_udp_port))
2468 pkts.append(p)
2469 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2470 IP(src=server2.ip4, dst=server1_nat_ip) /
2471 ICMP(id=self.icmp_id_in, type='echo-request'))
2472 pkts.append(p)
2473 self.pg0.add_stream(pkts)
2474 self.pg_enable_capture(self.pg_interfaces)
2475 self.pg_start()
2476 capture = self.pg0.get_capture(len(pkts))
2477 for packet in capture:
2478 try:
2479 self.assertEqual(packet[IP].src, server2_nat_ip)
2480 self.assertEqual(packet[IP].dst, server1.ip4)
2481 if packet.haslayer(TCP):
2482 self.assertEqual(packet[TCP].sport, self.tcp_port_in)
2483 self.assertEqual(packet[TCP].dport, server_tcp_port)
2484 self.tcp_port_out = packet[TCP].sport
Klement Sekerad81ae412018-05-16 10:52:54 +02002485 self.assert_packet_checksums_valid(packet)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002486 elif packet.haslayer(UDP):
2487 self.assertEqual(packet[UDP].sport, self.udp_port_in)
2488 self.assertEqual(packet[UDP].dport, server_udp_port)
2489 self.udp_port_out = packet[UDP].sport
2490 else:
2491 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
2492 self.icmp_id_out = packet[ICMP].id
2493 except:
2494 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2495 raise
2496
2497 # server1 to server2
2498 pkts = []
2499 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2500 IP(src=server1.ip4, dst=server2_nat_ip) /
2501 TCP(sport=server_tcp_port, dport=self.tcp_port_out))
2502 pkts.append(p)
2503 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2504 IP(src=server1.ip4, dst=server2_nat_ip) /
2505 UDP(sport=server_udp_port, dport=self.udp_port_out))
2506 pkts.append(p)
2507 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2508 IP(src=server1.ip4, dst=server2_nat_ip) /
2509 ICMP(id=self.icmp_id_out, type='echo-reply'))
2510 pkts.append(p)
2511 self.pg0.add_stream(pkts)
2512 self.pg_enable_capture(self.pg_interfaces)
2513 self.pg_start()
2514 capture = self.pg0.get_capture(len(pkts))
2515 for packet in capture:
2516 try:
2517 self.assertEqual(packet[IP].src, server1_nat_ip)
2518 self.assertEqual(packet[IP].dst, server2.ip4)
2519 if packet.haslayer(TCP):
2520 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
2521 self.assertEqual(packet[TCP].sport, server_tcp_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02002522 self.assert_packet_checksums_valid(packet)
Matus Fabian6fa74c62017-06-05 05:55:48 -07002523 elif packet.haslayer(UDP):
2524 self.assertEqual(packet[UDP].dport, self.udp_port_in)
2525 self.assertEqual(packet[UDP].sport, server_udp_port)
2526 else:
2527 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
2528 except:
2529 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2530 raise
2531
Matus Fabian9902fcd2016-12-21 23:58:46 -08002532 def test_max_translations_per_user(self):
2533 """ MAX translations per user - recycle the least recently used """
2534
Matus Fabian2ba92e32017-08-21 07:05:03 -07002535 self.nat44_add_address(self.nat_addr)
2536 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2537 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2538 is_inside=0)
Matus Fabian9902fcd2016-12-21 23:58:46 -08002539
2540 # get maximum number of translations per user
Matus Fabian2ba92e32017-08-21 07:05:03 -07002541 nat44_config = self.vapi.nat_show_config()
Matus Fabian9902fcd2016-12-21 23:58:46 -08002542
2543 # send more than maximum number of translations per user packets
Matus Fabian2ba92e32017-08-21 07:05:03 -07002544 pkts_num = nat44_config.max_translations_per_user + 5
Matus Fabian9902fcd2016-12-21 23:58:46 -08002545 pkts = []
2546 for port in range(0, pkts_num):
2547 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2548 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2549 TCP(sport=1025 + port))
2550 pkts.append(p)
2551 self.pg0.add_stream(pkts)
2552 self.pg_enable_capture(self.pg_interfaces)
2553 self.pg_start()
2554
2555 # verify number of translated packet
Klement Sekeradab231a2016-12-21 08:50:14 +01002556 self.pg1.get_capture(pkts_num)
Matus Fabian9902fcd2016-12-21 23:58:46 -08002557
Matus Fabian132dc492018-05-09 04:51:03 -07002558 users = self.vapi.nat44_user_dump()
2559 for user in users:
2560 if user.ip_address == self.pg0.remote_ip4n:
2561 self.assertEqual(user.nsessions,
2562 nat44_config.max_translations_per_user)
2563 self.assertEqual(user.nstaticsessions, 0)
2564
2565 tcp_port = 22
2566 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
2567 tcp_port, tcp_port,
2568 proto=IP_PROTOS.tcp)
2569 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2570 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2571 TCP(sport=tcp_port))
2572 self.pg0.add_stream(p)
2573 self.pg_enable_capture(self.pg_interfaces)
2574 self.pg_start()
2575 self.pg1.get_capture(1)
2576 users = self.vapi.nat44_user_dump()
2577 for user in users:
2578 if user.ip_address == self.pg0.remote_ip4n:
2579 self.assertEqual(user.nsessions,
2580 nat44_config.max_translations_per_user - 1)
2581 self.assertEqual(user.nstaticsessions, 1)
2582
Matus Fabian8bf68e82017-01-12 04:24:35 -08002583 def test_interface_addr(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002584 """ Acquire NAT44 addresses from interface """
Ole Troane1ade682019-03-04 23:55:43 +01002585 self.vapi.nat44_add_del_interface_addr(self.pg7.sw_if_index)
Matus Fabian8bf68e82017-01-12 04:24:35 -08002586
2587 # no address in NAT pool
Matus Fabian2ba92e32017-08-21 07:05:03 -07002588 adresses = self.vapi.nat44_address_dump()
Matus Fabian8bf68e82017-01-12 04:24:35 -08002589 self.assertEqual(0, len(adresses))
2590
2591 # configure interface address and check NAT address pool
2592 self.pg7.config_ip4()
Matus Fabian2ba92e32017-08-21 07:05:03 -07002593 adresses = self.vapi.nat44_address_dump()
Matus Fabian8bf68e82017-01-12 04:24:35 -08002594 self.assertEqual(1, len(adresses))
Matus Fabian36532bd2017-01-23 23:42:28 -08002595 self.assertEqual(adresses[0].ip_address[0:4], self.pg7.local_ip4n)
Matus Fabian8bf68e82017-01-12 04:24:35 -08002596
2597 # remove interface address and check NAT address pool
2598 self.pg7.unconfig_ip4()
Matus Fabian2ba92e32017-08-21 07:05:03 -07002599 adresses = self.vapi.nat44_address_dump()
Matus Fabian8bf68e82017-01-12 04:24:35 -08002600 self.assertEqual(0, len(adresses))
2601
Matus Fabian36532bd2017-01-23 23:42:28 -08002602 def test_interface_addr_static_mapping(self):
2603 """ Static mapping with addresses from interface """
Paul Vinciguerra22ab6f72019-03-07 17:55:33 -08002604 tag = b"testTAG"
Matus Fabian5f224992018-01-25 21:59:16 -08002605
Ole Troane1ade682019-03-04 23:55:43 +01002606 self.vapi.nat44_add_del_interface_addr(self.pg7.sw_if_index)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002607 self.nat44_add_static_mapping(
2608 '1.2.3.4',
Matus Fabian5f224992018-01-25 21:59:16 -08002609 external_sw_if_index=self.pg7.sw_if_index,
2610 tag=tag)
Matus Fabian36532bd2017-01-23 23:42:28 -08002611
Matus Fabiane22e5462017-02-14 23:33:43 -08002612 # static mappings with external interface
Matus Fabian2ba92e32017-08-21 07:05:03 -07002613 static_mappings = self.vapi.nat44_static_mapping_dump()
Matus Fabiane22e5462017-02-14 23:33:43 -08002614 self.assertEqual(1, len(static_mappings))
2615 self.assertEqual(self.pg7.sw_if_index,
2616 static_mappings[0].external_sw_if_index)
Paul Vinciguerra22ab6f72019-03-07 17:55:33 -08002617 self.assertEqual((static_mappings[0].tag).split(b'\0', 1)[0], tag)
Matus Fabian36532bd2017-01-23 23:42:28 -08002618
2619 # configure interface address and check static mappings
2620 self.pg7.config_ip4()
Matus Fabian2ba92e32017-08-21 07:05:03 -07002621 static_mappings = self.vapi.nat44_static_mapping_dump()
Matus Fabianea2600a2018-03-28 04:06:26 -07002622 self.assertEqual(2, len(static_mappings))
2623 resolved = False
2624 for sm in static_mappings:
2625 if sm.external_sw_if_index == 0xFFFFFFFF:
2626 self.assertEqual(sm.external_ip_address[0:4],
2627 self.pg7.local_ip4n)
Paul Vinciguerra22ab6f72019-03-07 17:55:33 -08002628 self.assertEqual((sm.tag).split(b'\0', 1)[0], tag)
Matus Fabianea2600a2018-03-28 04:06:26 -07002629 resolved = True
2630 self.assertTrue(resolved)
Matus Fabian36532bd2017-01-23 23:42:28 -08002631
2632 # remove interface address and check static mappings
2633 self.pg7.unconfig_ip4()
Matus Fabian2ba92e32017-08-21 07:05:03 -07002634 static_mappings = self.vapi.nat44_static_mapping_dump()
Matus Fabianea2600a2018-03-28 04:06:26 -07002635 self.assertEqual(1, len(static_mappings))
2636 self.assertEqual(self.pg7.sw_if_index,
2637 static_mappings[0].external_sw_if_index)
Paul Vinciguerra22ab6f72019-03-07 17:55:33 -08002638 self.assertEqual((static_mappings[0].tag).split(b'\0', 1)[0], tag)
Matus Fabianea2600a2018-03-28 04:06:26 -07002639
2640 # configure interface address again and check static mappings
2641 self.pg7.config_ip4()
2642 static_mappings = self.vapi.nat44_static_mapping_dump()
2643 self.assertEqual(2, len(static_mappings))
2644 resolved = False
2645 for sm in static_mappings:
2646 if sm.external_sw_if_index == 0xFFFFFFFF:
2647 self.assertEqual(sm.external_ip_address[0:4],
2648 self.pg7.local_ip4n)
Paul Vinciguerra22ab6f72019-03-07 17:55:33 -08002649 self.assertEqual((sm.tag).split(b'\0', 1)[0], tag)
Matus Fabianea2600a2018-03-28 04:06:26 -07002650 resolved = True
2651 self.assertTrue(resolved)
2652
2653 # remove static mapping
2654 self.nat44_add_static_mapping(
2655 '1.2.3.4',
2656 external_sw_if_index=self.pg7.sw_if_index,
2657 tag=tag,
2658 is_add=0)
2659 static_mappings = self.vapi.nat44_static_mapping_dump()
Matus Fabian36532bd2017-01-23 23:42:28 -08002660 self.assertEqual(0, len(static_mappings))
2661
Matus Fabianab7a8052017-11-28 04:29:41 -08002662 def test_interface_addr_identity_nat(self):
2663 """ Identity NAT with addresses from interface """
2664
2665 port = 53053
Ole Troane1ade682019-03-04 23:55:43 +01002666 self.vapi.nat44_add_del_interface_addr(self.pg7.sw_if_index)
Matus Fabianab7a8052017-11-28 04:29:41 -08002667 self.vapi.nat44_add_del_identity_mapping(
2668 sw_if_index=self.pg7.sw_if_index,
2669 port=port,
2670 protocol=IP_PROTOS.tcp,
2671 addr_only=0)
2672
2673 # identity mappings with external interface
2674 identity_mappings = self.vapi.nat44_identity_mapping_dump()
2675 self.assertEqual(1, len(identity_mappings))
2676 self.assertEqual(self.pg7.sw_if_index,
2677 identity_mappings[0].sw_if_index)
2678
2679 # configure interface address and check identity mappings
2680 self.pg7.config_ip4()
2681 identity_mappings = self.vapi.nat44_identity_mapping_dump()
Matus Fabianea2600a2018-03-28 04:06:26 -07002682 resolved = False
2683 self.assertEqual(2, len(identity_mappings))
2684 for sm in identity_mappings:
2685 if sm.sw_if_index == 0xFFFFFFFF:
2686 self.assertEqual(identity_mappings[0].ip_address,
2687 self.pg7.local_ip4n)
2688 self.assertEqual(port, identity_mappings[0].port)
2689 self.assertEqual(IP_PROTOS.tcp, identity_mappings[0].protocol)
2690 resolved = True
2691 self.assertTrue(resolved)
Matus Fabianab7a8052017-11-28 04:29:41 -08002692
2693 # remove interface address and check identity mappings
2694 self.pg7.unconfig_ip4()
2695 identity_mappings = self.vapi.nat44_identity_mapping_dump()
Matus Fabianea2600a2018-03-28 04:06:26 -07002696 self.assertEqual(1, len(identity_mappings))
2697 self.assertEqual(self.pg7.sw_if_index,
2698 identity_mappings[0].sw_if_index)
Matus Fabianab7a8052017-11-28 04:29:41 -08002699
Matus Fabianeea28d72017-01-13 04:15:54 -08002700 def test_ipfix_nat44_sess(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002701 """ IPFIX logging NAT44 session created/delted """
Matus Fabian6631e9c2017-05-24 01:52:20 -07002702 self.ipfix_domain_id = 10
2703 self.ipfix_src_port = 20202
2704 colector_port = 30303
2705 bind_layers(UDP, IPFIX, dport=30303)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002706 self.nat44_add_address(self.nat_addr)
2707 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2708 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2709 is_inside=0)
Matus Fabianeea28d72017-01-13 04:15:54 -08002710 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
2711 src_address=self.pg3.local_ip4n,
2712 path_mtu=512,
Matus Fabian6631e9c2017-05-24 01:52:20 -07002713 template_interval=10,
2714 collector_port=colector_port)
Ole Troane1ade682019-03-04 23:55:43 +01002715 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
2716 src_port=self.ipfix_src_port)
Matus Fabianeea28d72017-01-13 04:15:54 -08002717
2718 pkts = self.create_stream_in(self.pg0, self.pg1)
2719 self.pg0.add_stream(pkts)
2720 self.pg_enable_capture(self.pg_interfaces)
2721 self.pg_start()
2722 capture = self.pg1.get_capture(len(pkts))
2723 self.verify_capture_out(capture)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002724 self.nat44_add_address(self.nat_addr, is_add=0)
Matus Fabianeea28d72017-01-13 04:15:54 -08002725 self.vapi.cli("ipfix flush") # FIXME this should be an API call
Matus Fabiana431ad12018-01-04 04:03:14 -08002726 capture = self.pg3.get_capture(9)
Matus Fabianeea28d72017-01-13 04:15:54 -08002727 ipfix = IPFIXDecoder()
2728 # first load template
2729 for p in capture:
2730 self.assertTrue(p.haslayer(IPFIX))
Matus Fabian6631e9c2017-05-24 01:52:20 -07002731 self.assertEqual(p[IP].src, self.pg3.local_ip4)
2732 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2733 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2734 self.assertEqual(p[UDP].dport, colector_port)
2735 self.assertEqual(p[IPFIX].observationDomainID,
2736 self.ipfix_domain_id)
Matus Fabianeea28d72017-01-13 04:15:54 -08002737 if p.haslayer(Template):
2738 ipfix.add_template(p.getlayer(Template))
2739 # verify events in data set
2740 for p in capture:
2741 if p.haslayer(Data):
2742 data = ipfix.decode_data_set(p.getlayer(Set))
2743 self.verify_ipfix_nat44_ses(data)
2744
2745 def test_ipfix_addr_exhausted(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002746 """ IPFIX logging NAT addresses exhausted """
2747 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2748 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2749 is_inside=0)
Matus Fabianeea28d72017-01-13 04:15:54 -08002750 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
2751 src_address=self.pg3.local_ip4n,
2752 path_mtu=512,
2753 template_interval=10)
Ole Troane1ade682019-03-04 23:55:43 +01002754 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
2755 src_port=self.ipfix_src_port)
Matus Fabianeea28d72017-01-13 04:15:54 -08002756
2757 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
2758 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2759 TCP(sport=3025))
2760 self.pg0.add_stream(p)
2761 self.pg_enable_capture(self.pg_interfaces)
2762 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07002763 self.pg1.assert_nothing_captured()
2764 sleep(1)
Matus Fabianeea28d72017-01-13 04:15:54 -08002765 self.vapi.cli("ipfix flush") # FIXME this should be an API call
Matus Fabiana431ad12018-01-04 04:03:14 -08002766 capture = self.pg3.get_capture(9)
Matus Fabianeea28d72017-01-13 04:15:54 -08002767 ipfix = IPFIXDecoder()
2768 # first load template
2769 for p in capture:
2770 self.assertTrue(p.haslayer(IPFIX))
Matus Fabian6631e9c2017-05-24 01:52:20 -07002771 self.assertEqual(p[IP].src, self.pg3.local_ip4)
2772 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2773 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2774 self.assertEqual(p[UDP].dport, 4739)
2775 self.assertEqual(p[IPFIX].observationDomainID,
2776 self.ipfix_domain_id)
Matus Fabianeea28d72017-01-13 04:15:54 -08002777 if p.haslayer(Template):
2778 ipfix.add_template(p.getlayer(Template))
2779 # verify events in data set
2780 for p in capture:
2781 if p.haslayer(Data):
2782 data = ipfix.decode_data_set(p.getlayer(Set))
2783 self.verify_ipfix_addr_exhausted(data)
2784
Paul Vinciguerradefde0f2018-12-06 07:46:13 -08002785 @unittest.skipUnless(running_extended_tests, "part of extended tests")
Matus Fabiana431ad12018-01-04 04:03:14 -08002786 def test_ipfix_max_sessions(self):
2787 """ IPFIX logging maximum session entries exceeded """
2788 self.nat44_add_address(self.nat_addr)
2789 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2790 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2791 is_inside=0)
2792
2793 nat44_config = self.vapi.nat_show_config()
2794 max_sessions = 10 * nat44_config.translation_buckets
2795
2796 pkts = []
2797 for i in range(0, max_sessions):
2798 src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
2799 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2800 IP(src=src, dst=self.pg1.remote_ip4) /
2801 TCP(sport=1025))
2802 pkts.append(p)
2803 self.pg0.add_stream(pkts)
2804 self.pg_enable_capture(self.pg_interfaces)
2805 self.pg_start()
2806
2807 self.pg1.get_capture(max_sessions)
2808 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
2809 src_address=self.pg3.local_ip4n,
2810 path_mtu=512,
2811 template_interval=10)
Ole Troane1ade682019-03-04 23:55:43 +01002812 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
2813 src_port=self.ipfix_src_port)
Matus Fabiana431ad12018-01-04 04:03:14 -08002814
2815 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2816 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2817 TCP(sport=1025))
2818 self.pg0.add_stream(p)
2819 self.pg_enable_capture(self.pg_interfaces)
2820 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07002821 self.pg1.assert_nothing_captured()
2822 sleep(1)
Matus Fabiana431ad12018-01-04 04:03:14 -08002823 self.vapi.cli("ipfix flush") # FIXME this should be an API call
2824 capture = self.pg3.get_capture(9)
2825 ipfix = IPFIXDecoder()
2826 # first load template
2827 for p in capture:
2828 self.assertTrue(p.haslayer(IPFIX))
2829 self.assertEqual(p[IP].src, self.pg3.local_ip4)
2830 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2831 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2832 self.assertEqual(p[UDP].dport, 4739)
2833 self.assertEqual(p[IPFIX].observationDomainID,
2834 self.ipfix_domain_id)
2835 if p.haslayer(Template):
2836 ipfix.add_template(p.getlayer(Template))
2837 # verify events in data set
2838 for p in capture:
2839 if p.haslayer(Data):
2840 data = ipfix.decode_data_set(p.getlayer(Set))
2841 self.verify_ipfix_max_sessions(data, max_sessions)
2842
Matus Fabianad1f3e12018-11-28 21:26:34 -08002843 def test_syslog_apmap(self):
2844 """ Test syslog address and port mapping creation and deletion """
2845 self.vapi.syslog_set_filter(SYSLOG_SEVERITY.INFO)
Ole Troanf159f582019-02-28 20:20:47 +01002846 self.vapi.syslog_set_sender(self.pg3.local_ip4n, self.pg3.remote_ip4n)
Matus Fabianad1f3e12018-11-28 21:26:34 -08002847 self.nat44_add_address(self.nat_addr)
2848 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2849 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2850 is_inside=0)
2851
2852 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2853 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2854 TCP(sport=self.tcp_port_in, dport=20))
2855 self.pg0.add_stream(p)
2856 self.pg_enable_capture(self.pg_interfaces)
2857 self.pg_start()
2858 capture = self.pg1.get_capture(1)
2859 self.tcp_port_out = capture[0][TCP].sport
2860 capture = self.pg3.get_capture(1)
2861 self.verify_syslog_apmap(capture[0][Raw].load)
2862
2863 self.pg_enable_capture(self.pg_interfaces)
2864 self.pg_start()
2865 self.nat44_add_address(self.nat_addr, is_add=0)
2866 capture = self.pg3.get_capture(1)
2867 self.verify_syslog_apmap(capture[0][Raw].load, False)
2868
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002869 def test_pool_addr_fib(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002870 """ NAT44 add pool addresses to FIB """
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002871 static_addr = '10.0.0.10'
Matus Fabian2ba92e32017-08-21 07:05:03 -07002872 self.nat44_add_address(self.nat_addr)
2873 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2874 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2875 is_inside=0)
2876 self.nat44_add_static_mapping(self.pg0.remote_ip4, static_addr)
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002877
Matus Fabian2ba92e32017-08-21 07:05:03 -07002878 # NAT44 address
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002879 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002880 ARP(op=ARP.who_has, pdst=self.nat_addr,
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002881 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2882 self.pg1.add_stream(p)
2883 self.pg_enable_capture(self.pg_interfaces)
2884 self.pg_start()
2885 capture = self.pg1.get_capture(1)
2886 self.assertTrue(capture[0].haslayer(ARP))
2887 self.assertTrue(capture[0][ARP].op, ARP.is_at)
2888
2889 # 1:1 NAT address
2890 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2891 ARP(op=ARP.who_has, pdst=static_addr,
2892 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2893 self.pg1.add_stream(p)
2894 self.pg_enable_capture(self.pg_interfaces)
2895 self.pg_start()
2896 capture = self.pg1.get_capture(1)
2897 self.assertTrue(capture[0].haslayer(ARP))
2898 self.assertTrue(capture[0][ARP].op, ARP.is_at)
2899
Matus Fabian2ba92e32017-08-21 07:05:03 -07002900 # send ARP to non-NAT44 interface
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002901 p = (Ether(src=self.pg2.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002902 ARP(op=ARP.who_has, pdst=self.nat_addr,
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002903 psrc=self.pg2.remote_ip4, hwsrc=self.pg2.remote_mac))
2904 self.pg2.add_stream(p)
2905 self.pg_enable_capture(self.pg_interfaces)
2906 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07002907 self.pg1.assert_nothing_captured()
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002908
2909 # remove addresses and verify
Matus Fabian2ba92e32017-08-21 07:05:03 -07002910 self.nat44_add_address(self.nat_addr, is_add=0)
2911 self.nat44_add_static_mapping(self.pg0.remote_ip4, static_addr,
2912 is_add=0)
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002913
2914 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
Matus Fabian2ba92e32017-08-21 07:05:03 -07002915 ARP(op=ARP.who_has, pdst=self.nat_addr,
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002916 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2917 self.pg1.add_stream(p)
2918 self.pg_enable_capture(self.pg_interfaces)
2919 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07002920 self.pg1.assert_nothing_captured()
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002921
2922 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2923 ARP(op=ARP.who_has, pdst=static_addr,
2924 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2925 self.pg1.add_stream(p)
2926 self.pg_enable_capture(self.pg_interfaces)
2927 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07002928 self.pg1.assert_nothing_captured()
Matus Fabiane1ae29a2017-01-27 00:47:58 -08002929
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002930 def test_vrf_mode(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002931 """ NAT44 tenant VRF aware address pool mode """
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002932
2933 vrf_id1 = 1
2934 vrf_id2 = 2
2935 nat_ip1 = "10.0.0.10"
2936 nat_ip2 = "10.0.0.11"
2937
2938 self.pg0.unconfig_ip4()
2939 self.pg1.unconfig_ip4()
Ole Troan9a475372019-03-05 16:58:24 +01002940 self.vapi.ip_table_add_del(is_add=1, table_id=vrf_id1)
2941 self.vapi.ip_table_add_del(is_add=1, table_id=vrf_id2)
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002942 self.pg0.set_table_ip4(vrf_id1)
2943 self.pg1.set_table_ip4(vrf_id2)
2944 self.pg0.config_ip4()
2945 self.pg1.config_ip4()
Matus Fabian8008d7c2018-07-09 01:34:20 -07002946 self.pg0.resolve_arp()
2947 self.pg1.resolve_arp()
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002948
Matus Fabian2ba92e32017-08-21 07:05:03 -07002949 self.nat44_add_address(nat_ip1, vrf_id=vrf_id1)
2950 self.nat44_add_address(nat_ip2, vrf_id=vrf_id2)
2951 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2952 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
2953 self.vapi.nat44_interface_add_del_feature(self.pg2.sw_if_index,
2954 is_inside=0)
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002955
Matus Fabian8008d7c2018-07-09 01:34:20 -07002956 try:
2957 # first VRF
2958 pkts = self.create_stream_in(self.pg0, self.pg2)
2959 self.pg0.add_stream(pkts)
2960 self.pg_enable_capture(self.pg_interfaces)
2961 self.pg_start()
2962 capture = self.pg2.get_capture(len(pkts))
2963 self.verify_capture_out(capture, nat_ip1)
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002964
Matus Fabian8008d7c2018-07-09 01:34:20 -07002965 # second VRF
2966 pkts = self.create_stream_in(self.pg1, self.pg2)
2967 self.pg1.add_stream(pkts)
2968 self.pg_enable_capture(self.pg_interfaces)
2969 self.pg_start()
2970 capture = self.pg2.get_capture(len(pkts))
2971 self.verify_capture_out(capture, nat_ip2)
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002972
Matus Fabian8008d7c2018-07-09 01:34:20 -07002973 finally:
2974 self.pg0.unconfig_ip4()
2975 self.pg1.unconfig_ip4()
2976 self.pg0.set_table_ip4(0)
2977 self.pg1.set_table_ip4(0)
2978 self.pg0.config_ip4()
2979 self.pg1.config_ip4()
2980 self.pg0.resolve_arp()
2981 self.pg1.resolve_arp()
Ole Troan9a475372019-03-05 16:58:24 +01002982 self.vapi.ip_table_add_del(is_add=0, table_id=vrf_id1)
2983 self.vapi.ip_table_add_del(is_add=0, table_id=vrf_id2)
Neale Ranns15002542017-09-10 04:39:11 -07002984
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002985 def test_vrf_feature_independent(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07002986 """ NAT44 tenant VRF independent address pool mode """
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002987
2988 nat_ip1 = "10.0.0.10"
2989 nat_ip2 = "10.0.0.11"
2990
Matus Fabian2ba92e32017-08-21 07:05:03 -07002991 self.nat44_add_address(nat_ip1)
Matus Fabian51e759f2017-12-07 23:22:51 -08002992 self.nat44_add_address(nat_ip2, vrf_id=99)
Matus Fabian2ba92e32017-08-21 07:05:03 -07002993 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2994 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
2995 self.vapi.nat44_interface_add_del_feature(self.pg2.sw_if_index,
2996 is_inside=0)
Juraj Slobodaeab38d92017-03-06 19:55:21 -08002997
2998 # first VRF
2999 pkts = self.create_stream_in(self.pg0, self.pg2)
3000 self.pg0.add_stream(pkts)
3001 self.pg_enable_capture(self.pg_interfaces)
3002 self.pg_start()
3003 capture = self.pg2.get_capture(len(pkts))
3004 self.verify_capture_out(capture, nat_ip1)
3005
3006 # second VRF
3007 pkts = self.create_stream_in(self.pg1, self.pg2)
3008 self.pg1.add_stream(pkts)
3009 self.pg_enable_capture(self.pg_interfaces)
3010 self.pg_start()
3011 capture = self.pg2.get_capture(len(pkts))
3012 self.verify_capture_out(capture, nat_ip1)
3013
Martin Gálik406eb1d2017-05-04 04:35:04 -07003014 def test_dynamic_ipless_interfaces(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07003015 """ NAT44 interfaces without configured IP address """
Martin Gálik406eb1d2017-05-04 04:35:04 -07003016
Neale Ranns37029302018-08-10 05:30:06 -07003017 self.vapi.ip_neighbor_add_del(
3018 self.pg7.sw_if_index,
3019 self.pg7.remote_mac,
3020 self.pg7.remote_ip4,
3021 flags=(VppEnum.vl_api_ip_neighbor_flags_t.
3022 IP_API_NEIGHBOR_FLAG_STATIC))
3023 self.vapi.ip_neighbor_add_del(
3024 self.pg8.sw_if_index,
3025 self.pg8.remote_mac,
3026 self.pg8.remote_ip4,
3027 flags=(VppEnum.vl_api_ip_neighbor_flags_t.
3028 IP_API_NEIGHBOR_FLAG_STATIC))
Martin Gálik406eb1d2017-05-04 04:35:04 -07003029
3030 self.vapi.ip_add_del_route(dst_address=self.pg7.remote_ip4n,
3031 dst_address_length=32,
3032 next_hop_address=self.pg7.remote_ip4n,
3033 next_hop_sw_if_index=self.pg7.sw_if_index)
3034 self.vapi.ip_add_del_route(dst_address=self.pg8.remote_ip4n,
3035 dst_address_length=32,
3036 next_hop_address=self.pg8.remote_ip4n,
3037 next_hop_sw_if_index=self.pg8.sw_if_index)
3038
Matus Fabian2ba92e32017-08-21 07:05:03 -07003039 self.nat44_add_address(self.nat_addr)
3040 self.vapi.nat44_interface_add_del_feature(self.pg7.sw_if_index)
3041 self.vapi.nat44_interface_add_del_feature(self.pg8.sw_if_index,
3042 is_inside=0)
Martin Gálik406eb1d2017-05-04 04:35:04 -07003043
3044 # in2out
3045 pkts = self.create_stream_in(self.pg7, self.pg8)
3046 self.pg7.add_stream(pkts)
3047 self.pg_enable_capture(self.pg_interfaces)
3048 self.pg_start()
3049 capture = self.pg8.get_capture(len(pkts))
3050 self.verify_capture_out(capture)
3051
3052 # out2in
Matus Fabian2ba92e32017-08-21 07:05:03 -07003053 pkts = self.create_stream_out(self.pg8, self.nat_addr)
Martin Gálik406eb1d2017-05-04 04:35:04 -07003054 self.pg8.add_stream(pkts)
3055 self.pg_enable_capture(self.pg_interfaces)
3056 self.pg_start()
3057 capture = self.pg7.get_capture(len(pkts))
3058 self.verify_capture_in(capture, self.pg7)
3059
3060 def test_static_ipless_interfaces(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07003061 """ NAT44 interfaces without configured IP address - 1:1 NAT """
Martin Gálik406eb1d2017-05-04 04:35:04 -07003062
Neale Ranns37029302018-08-10 05:30:06 -07003063 self.vapi.ip_neighbor_add_del(
3064 self.pg7.sw_if_index,
3065 self.pg7.remote_mac,
3066 self.pg7.remote_ip4,
3067 flags=(VppEnum.vl_api_ip_neighbor_flags_t.
3068 IP_API_NEIGHBOR_FLAG_STATIC))
3069 self.vapi.ip_neighbor_add_del(
3070 self.pg8.sw_if_index,
3071 self.pg8.remote_mac,
3072 self.pg8.remote_ip4,
3073 flags=(VppEnum.vl_api_ip_neighbor_flags_t.
3074 IP_API_NEIGHBOR_FLAG_STATIC))
Martin Gálik406eb1d2017-05-04 04:35:04 -07003075
3076 self.vapi.ip_add_del_route(dst_address=self.pg7.remote_ip4n,
3077 dst_address_length=32,
3078 next_hop_address=self.pg7.remote_ip4n,
3079 next_hop_sw_if_index=self.pg7.sw_if_index)
3080 self.vapi.ip_add_del_route(dst_address=self.pg8.remote_ip4n,
3081 dst_address_length=32,
3082 next_hop_address=self.pg8.remote_ip4n,
3083 next_hop_sw_if_index=self.pg8.sw_if_index)
3084
Matus Fabian2ba92e32017-08-21 07:05:03 -07003085 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr)
3086 self.vapi.nat44_interface_add_del_feature(self.pg7.sw_if_index)
3087 self.vapi.nat44_interface_add_del_feature(self.pg8.sw_if_index,
3088 is_inside=0)
Martin Gálik406eb1d2017-05-04 04:35:04 -07003089
3090 # out2in
3091 pkts = self.create_stream_out(self.pg8)
3092 self.pg8.add_stream(pkts)
3093 self.pg_enable_capture(self.pg_interfaces)
3094 self.pg_start()
3095 capture = self.pg7.get_capture(len(pkts))
3096 self.verify_capture_in(capture, self.pg7)
3097
3098 # in2out
3099 pkts = self.create_stream_in(self.pg7, self.pg8)
3100 self.pg7.add_stream(pkts)
3101 self.pg_enable_capture(self.pg_interfaces)
3102 self.pg_start()
3103 capture = self.pg8.get_capture(len(pkts))
Matus Fabian2ba92e32017-08-21 07:05:03 -07003104 self.verify_capture_out(capture, self.nat_addr, True)
Martin Gálik406eb1d2017-05-04 04:35:04 -07003105
3106 def test_static_with_port_ipless_interfaces(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07003107 """ NAT44 interfaces without configured IP address - 1:1 NAPT """
Martin Gálik406eb1d2017-05-04 04:35:04 -07003108
3109 self.tcp_port_out = 30606
3110 self.udp_port_out = 30607
3111 self.icmp_id_out = 30608
3112
Neale Ranns37029302018-08-10 05:30:06 -07003113 self.vapi.ip_neighbor_add_del(
3114 self.pg7.sw_if_index,
3115 self.pg7.remote_mac,
3116 self.pg7.remote_ip4,
3117 flags=(VppEnum.vl_api_ip_neighbor_flags_t.
3118 IP_API_NEIGHBOR_FLAG_STATIC))
3119 self.vapi.ip_neighbor_add_del(
3120 self.pg8.sw_if_index,
3121 self.pg8.remote_mac,
3122 self.pg8.remote_ip4,
3123 flags=(VppEnum.vl_api_ip_neighbor_flags_t.
3124 IP_API_NEIGHBOR_FLAG_STATIC))
Martin Gálik406eb1d2017-05-04 04:35:04 -07003125
3126 self.vapi.ip_add_del_route(dst_address=self.pg7.remote_ip4n,
3127 dst_address_length=32,
3128 next_hop_address=self.pg7.remote_ip4n,
3129 next_hop_sw_if_index=self.pg7.sw_if_index)
3130 self.vapi.ip_add_del_route(dst_address=self.pg8.remote_ip4n,
3131 dst_address_length=32,
3132 next_hop_address=self.pg8.remote_ip4n,
3133 next_hop_sw_if_index=self.pg8.sw_if_index)
3134
Matus Fabian2ba92e32017-08-21 07:05:03 -07003135 self.nat44_add_address(self.nat_addr)
3136 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
3137 self.tcp_port_in, self.tcp_port_out,
3138 proto=IP_PROTOS.tcp)
3139 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
3140 self.udp_port_in, self.udp_port_out,
3141 proto=IP_PROTOS.udp)
3142 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
3143 self.icmp_id_in, self.icmp_id_out,
3144 proto=IP_PROTOS.icmp)
3145 self.vapi.nat44_interface_add_del_feature(self.pg7.sw_if_index)
3146 self.vapi.nat44_interface_add_del_feature(self.pg8.sw_if_index,
3147 is_inside=0)
Martin Gálik406eb1d2017-05-04 04:35:04 -07003148
3149 # out2in
3150 pkts = self.create_stream_out(self.pg8)
3151 self.pg8.add_stream(pkts)
3152 self.pg_enable_capture(self.pg_interfaces)
3153 self.pg_start()
3154 capture = self.pg7.get_capture(len(pkts))
3155 self.verify_capture_in(capture, self.pg7)
3156
3157 # in2out
3158 pkts = self.create_stream_in(self.pg7, self.pg8)
3159 self.pg7.add_stream(pkts)
3160 self.pg_enable_capture(self.pg_interfaces)
3161 self.pg_start()
3162 capture = self.pg8.get_capture(len(pkts))
3163 self.verify_capture_out(capture)
3164
Matus Fabian328dbc82017-06-19 04:28:04 -07003165 def test_static_unknown_proto(self):
3166 """ 1:1 NAT translate packet with unknown protocol """
3167 nat_ip = "10.0.0.10"
Matus Fabian2ba92e32017-08-21 07:05:03 -07003168 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
3169 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3170 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3171 is_inside=0)
Matus Fabian328dbc82017-06-19 04:28:04 -07003172
3173 # in2out
3174 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3175 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3176 GRE() /
Matus Fabian1e8db5f2017-06-20 01:45:49 -07003177 IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4) /
Matus Fabian328dbc82017-06-19 04:28:04 -07003178 TCP(sport=1234, dport=1234))
3179 self.pg0.add_stream(p)
3180 self.pg_enable_capture(self.pg_interfaces)
3181 self.pg_start()
3182 p = self.pg1.get_capture(1)
3183 packet = p[0]
3184 try:
3185 self.assertEqual(packet[IP].src, nat_ip)
3186 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
Paul Vinciguerra978aa642018-11-24 22:19:12 -08003187 self.assertEqual(packet.haslayer(GRE), 1)
Klement Sekerad81ae412018-05-16 10:52:54 +02003188 self.assert_packet_checksums_valid(packet)
Matus Fabian328dbc82017-06-19 04:28:04 -07003189 except:
3190 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3191 raise
3192
3193 # out2in
3194 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
3195 IP(src=self.pg1.remote_ip4, dst=nat_ip) /
3196 GRE() /
Matus Fabian1e8db5f2017-06-20 01:45:49 -07003197 IP(src=self.pg3.remote_ip4, dst=self.pg2.remote_ip4) /
Matus Fabian328dbc82017-06-19 04:28:04 -07003198 TCP(sport=1234, dport=1234))
3199 self.pg1.add_stream(p)
3200 self.pg_enable_capture(self.pg_interfaces)
3201 self.pg_start()
3202 p = self.pg0.get_capture(1)
3203 packet = p[0]
3204 try:
3205 self.assertEqual(packet[IP].src, self.pg1.remote_ip4)
3206 self.assertEqual(packet[IP].dst, self.pg0.remote_ip4)
Paul Vinciguerra978aa642018-11-24 22:19:12 -08003207 self.assertEqual(packet.haslayer(GRE), 1)
Klement Sekerad81ae412018-05-16 10:52:54 +02003208 self.assert_packet_checksums_valid(packet)
Matus Fabian328dbc82017-06-19 04:28:04 -07003209 except:
3210 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3211 raise
3212
Matus Fabian7968e6c2017-07-06 05:37:49 -07003213 def test_hairpinning_static_unknown_proto(self):
Matus Fabian1e8db5f2017-06-20 01:45:49 -07003214 """ 1:1 NAT translate packet with unknown protocol - hairpinning """
3215
3216 host = self.pg0.remote_hosts[0]
3217 server = self.pg0.remote_hosts[1]
3218
3219 host_nat_ip = "10.0.0.10"
3220 server_nat_ip = "10.0.0.11"
3221
Matus Fabian2ba92e32017-08-21 07:05:03 -07003222 self.nat44_add_static_mapping(host.ip4, host_nat_ip)
3223 self.nat44_add_static_mapping(server.ip4, server_nat_ip)
3224 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3225 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3226 is_inside=0)
Matus Fabian1e8db5f2017-06-20 01:45:49 -07003227
3228 # host to server
3229 p = (Ether(dst=self.pg0.local_mac, src=host.mac) /
3230 IP(src=host.ip4, dst=server_nat_ip) /
3231 GRE() /
3232 IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4) /
3233 TCP(sport=1234, dport=1234))
3234 self.pg0.add_stream(p)
3235 self.pg_enable_capture(self.pg_interfaces)
3236 self.pg_start()
3237 p = self.pg0.get_capture(1)
3238 packet = p[0]
3239 try:
3240 self.assertEqual(packet[IP].src, host_nat_ip)
3241 self.assertEqual(packet[IP].dst, server.ip4)
Paul Vinciguerra978aa642018-11-24 22:19:12 -08003242 self.assertEqual(packet.haslayer(GRE), 1)
Klement Sekerad81ae412018-05-16 10:52:54 +02003243 self.assert_packet_checksums_valid(packet)
Matus Fabian1e8db5f2017-06-20 01:45:49 -07003244 except:
3245 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3246 raise
3247
3248 # server to host
3249 p = (Ether(dst=self.pg0.local_mac, src=server.mac) /
3250 IP(src=server.ip4, dst=host_nat_ip) /
3251 GRE() /
3252 IP(src=self.pg3.remote_ip4, dst=self.pg2.remote_ip4) /
3253 TCP(sport=1234, dport=1234))
3254 self.pg0.add_stream(p)
3255 self.pg_enable_capture(self.pg_interfaces)
3256 self.pg_start()
3257 p = self.pg0.get_capture(1)
3258 packet = p[0]
3259 try:
3260 self.assertEqual(packet[IP].src, server_nat_ip)
3261 self.assertEqual(packet[IP].dst, host.ip4)
Paul Vinciguerra978aa642018-11-24 22:19:12 -08003262 self.assertEqual(packet.haslayer(GRE), 1)
Klement Sekerad81ae412018-05-16 10:52:54 +02003263 self.assert_packet_checksums_valid(packet)
Matus Fabian1e8db5f2017-06-20 01:45:49 -07003264 except:
3265 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3266 raise
3267
Matus Fabian93d84c92017-07-19 08:06:01 -07003268 def test_output_feature(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07003269 """ NAT44 interface output feature (in2out postrouting) """
3270 self.nat44_add_address(self.nat_addr)
3271 self.vapi.nat44_interface_add_del_output_feature(self.pg0.sw_if_index)
Matus Fabianb2d2fc72017-09-10 22:17:47 -07003272 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index)
3273 self.vapi.nat44_interface_add_del_output_feature(self.pg3.sw_if_index,
Matus Fabian2ba92e32017-08-21 07:05:03 -07003274 is_inside=0)
Matus Fabian93d84c92017-07-19 08:06:01 -07003275
3276 # in2out
Matus Fabianb2d2fc72017-09-10 22:17:47 -07003277 pkts = self.create_stream_in(self.pg0, self.pg3)
Matus Fabian93d84c92017-07-19 08:06:01 -07003278 self.pg0.add_stream(pkts)
3279 self.pg_enable_capture(self.pg_interfaces)
3280 self.pg_start()
Matus Fabianb2d2fc72017-09-10 22:17:47 -07003281 capture = self.pg3.get_capture(len(pkts))
Matus Fabian93d84c92017-07-19 08:06:01 -07003282 self.verify_capture_out(capture)
3283
3284 # out2in
Matus Fabianb2d2fc72017-09-10 22:17:47 -07003285 pkts = self.create_stream_out(self.pg3)
3286 self.pg3.add_stream(pkts)
Matus Fabian93d84c92017-07-19 08:06:01 -07003287 self.pg_enable_capture(self.pg_interfaces)
3288 self.pg_start()
3289 capture = self.pg0.get_capture(len(pkts))
3290 self.verify_capture_in(capture, self.pg0)
3291
Matus Fabianb2d2fc72017-09-10 22:17:47 -07003292 # from non-NAT interface to NAT inside interface
3293 pkts = self.create_stream_in(self.pg2, self.pg0)
3294 self.pg2.add_stream(pkts)
3295 self.pg_enable_capture(self.pg_interfaces)
3296 self.pg_start()
3297 capture = self.pg0.get_capture(len(pkts))
3298 self.verify_capture_no_translation(capture, self.pg2, self.pg0)
3299
Matus Fabian93d84c92017-07-19 08:06:01 -07003300 def test_output_feature_vrf_aware(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07003301 """ NAT44 interface output feature VRF aware (in2out postrouting) """
Matus Fabian93d84c92017-07-19 08:06:01 -07003302 nat_ip_vrf10 = "10.0.0.10"
3303 nat_ip_vrf20 = "10.0.0.20"
3304
3305 self.vapi.ip_add_del_route(dst_address=self.pg3.remote_ip4n,
3306 dst_address_length=32,
3307 next_hop_address=self.pg3.remote_ip4n,
3308 next_hop_sw_if_index=self.pg3.sw_if_index,
3309 table_id=10)
3310 self.vapi.ip_add_del_route(dst_address=self.pg3.remote_ip4n,
3311 dst_address_length=32,
3312 next_hop_address=self.pg3.remote_ip4n,
3313 next_hop_sw_if_index=self.pg3.sw_if_index,
3314 table_id=20)
3315
Matus Fabian2ba92e32017-08-21 07:05:03 -07003316 self.nat44_add_address(nat_ip_vrf10, vrf_id=10)
3317 self.nat44_add_address(nat_ip_vrf20, vrf_id=20)
3318 self.vapi.nat44_interface_add_del_output_feature(self.pg4.sw_if_index)
3319 self.vapi.nat44_interface_add_del_output_feature(self.pg6.sw_if_index)
3320 self.vapi.nat44_interface_add_del_output_feature(self.pg3.sw_if_index,
3321 is_inside=0)
Matus Fabian93d84c92017-07-19 08:06:01 -07003322
3323 # in2out VRF 10
3324 pkts = self.create_stream_in(self.pg4, self.pg3)
3325 self.pg4.add_stream(pkts)
3326 self.pg_enable_capture(self.pg_interfaces)
3327 self.pg_start()
3328 capture = self.pg3.get_capture(len(pkts))
3329 self.verify_capture_out(capture, nat_ip=nat_ip_vrf10)
3330
3331 # out2in VRF 10
3332 pkts = self.create_stream_out(self.pg3, dst_ip=nat_ip_vrf10)
3333 self.pg3.add_stream(pkts)
3334 self.pg_enable_capture(self.pg_interfaces)
3335 self.pg_start()
3336 capture = self.pg4.get_capture(len(pkts))
3337 self.verify_capture_in(capture, self.pg4)
3338
3339 # in2out VRF 20
3340 pkts = self.create_stream_in(self.pg6, self.pg3)
3341 self.pg6.add_stream(pkts)
3342 self.pg_enable_capture(self.pg_interfaces)
3343 self.pg_start()
3344 capture = self.pg3.get_capture(len(pkts))
3345 self.verify_capture_out(capture, nat_ip=nat_ip_vrf20)
3346
3347 # out2in VRF 20
3348 pkts = self.create_stream_out(self.pg3, dst_ip=nat_ip_vrf20)
3349 self.pg3.add_stream(pkts)
3350 self.pg_enable_capture(self.pg_interfaces)
3351 self.pg_start()
3352 capture = self.pg6.get_capture(len(pkts))
3353 self.verify_capture_in(capture, self.pg6)
3354
Matus Fabian161c59c2017-07-21 03:46:03 -07003355 def test_output_feature_hairpinning(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07003356 """ NAT44 interface output feature hairpinning (in2out postrouting) """
Matus Fabian93d84c92017-07-19 08:06:01 -07003357 host = self.pg0.remote_hosts[0]
3358 server = self.pg0.remote_hosts[1]
3359 host_in_port = 1234
3360 host_out_port = 0
3361 server_in_port = 5678
3362 server_out_port = 8765
3363
Matus Fabian2ba92e32017-08-21 07:05:03 -07003364 self.nat44_add_address(self.nat_addr)
3365 self.vapi.nat44_interface_add_del_output_feature(self.pg0.sw_if_index)
3366 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
3367 is_inside=0)
Matus Fabian93d84c92017-07-19 08:06:01 -07003368
3369 # add static mapping for server
Matus Fabian2ba92e32017-08-21 07:05:03 -07003370 self.nat44_add_static_mapping(server.ip4, self.nat_addr,
3371 server_in_port, server_out_port,
3372 proto=IP_PROTOS.tcp)
Matus Fabian93d84c92017-07-19 08:06:01 -07003373
3374 # send packet from host to server
3375 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07003376 IP(src=host.ip4, dst=self.nat_addr) /
Matus Fabian93d84c92017-07-19 08:06:01 -07003377 TCP(sport=host_in_port, dport=server_out_port))
3378 self.pg0.add_stream(p)
3379 self.pg_enable_capture(self.pg_interfaces)
3380 self.pg_start()
3381 capture = self.pg0.get_capture(1)
3382 p = capture[0]
3383 try:
3384 ip = p[IP]
3385 tcp = p[TCP]
Matus Fabian2ba92e32017-08-21 07:05:03 -07003386 self.assertEqual(ip.src, self.nat_addr)
Matus Fabian93d84c92017-07-19 08:06:01 -07003387 self.assertEqual(ip.dst, server.ip4)
3388 self.assertNotEqual(tcp.sport, host_in_port)
3389 self.assertEqual(tcp.dport, server_in_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02003390 self.assert_packet_checksums_valid(p)
Matus Fabian93d84c92017-07-19 08:06:01 -07003391 host_out_port = tcp.sport
3392 except:
3393 self.logger.error(ppp("Unexpected or invalid packet:", p))
3394 raise
3395
3396 # send reply from server to host
3397 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07003398 IP(src=server.ip4, dst=self.nat_addr) /
Matus Fabian93d84c92017-07-19 08:06:01 -07003399 TCP(sport=server_in_port, dport=host_out_port))
3400 self.pg0.add_stream(p)
3401 self.pg_enable_capture(self.pg_interfaces)
3402 self.pg_start()
3403 capture = self.pg0.get_capture(1)
3404 p = capture[0]
3405 try:
3406 ip = p[IP]
3407 tcp = p[TCP]
Matus Fabian2ba92e32017-08-21 07:05:03 -07003408 self.assertEqual(ip.src, self.nat_addr)
Matus Fabian93d84c92017-07-19 08:06:01 -07003409 self.assertEqual(ip.dst, host.ip4)
3410 self.assertEqual(tcp.sport, server_out_port)
3411 self.assertEqual(tcp.dport, host_in_port)
Klement Sekerad81ae412018-05-16 10:52:54 +02003412 self.assert_packet_checksums_valid(p)
Matus Fabian93d84c92017-07-19 08:06:01 -07003413 except:
Matus Fabiane82488f2018-01-18 03:38:45 -08003414 self.logger.error(ppp("Unexpected or invalid packet:", p))
Matus Fabian93d84c92017-07-19 08:06:01 -07003415 raise
3416
Matus Fabian36ea2d62017-10-24 04:13:49 -07003417 def test_one_armed_nat44(self):
3418 """ One armed NAT44 """
3419 remote_host = self.pg9.remote_hosts[0]
3420 local_host = self.pg9.remote_hosts[1]
3421 external_port = 0
3422
3423 self.nat44_add_address(self.nat_addr)
3424 self.vapi.nat44_interface_add_del_feature(self.pg9.sw_if_index)
3425 self.vapi.nat44_interface_add_del_feature(self.pg9.sw_if_index,
3426 is_inside=0)
3427
3428 # in2out
3429 p = (Ether(src=self.pg9.remote_mac, dst=self.pg9.local_mac) /
3430 IP(src=local_host.ip4, dst=remote_host.ip4) /
3431 TCP(sport=12345, dport=80))
3432 self.pg9.add_stream(p)
3433 self.pg_enable_capture(self.pg_interfaces)
3434 self.pg_start()
3435 capture = self.pg9.get_capture(1)
3436 p = capture[0]
3437 try:
3438 ip = p[IP]
3439 tcp = p[TCP]
3440 self.assertEqual(ip.src, self.nat_addr)
3441 self.assertEqual(ip.dst, remote_host.ip4)
3442 self.assertNotEqual(tcp.sport, 12345)
3443 external_port = tcp.sport
3444 self.assertEqual(tcp.dport, 80)
Klement Sekerad81ae412018-05-16 10:52:54 +02003445 self.assert_packet_checksums_valid(p)
Matus Fabian36ea2d62017-10-24 04:13:49 -07003446 except:
3447 self.logger.error(ppp("Unexpected or invalid packet:", p))
3448 raise
3449
3450 # out2in
3451 p = (Ether(src=self.pg9.remote_mac, dst=self.pg9.local_mac) /
3452 IP(src=remote_host.ip4, dst=self.nat_addr) /
3453 TCP(sport=80, dport=external_port))
3454 self.pg9.add_stream(p)
3455 self.pg_enable_capture(self.pg_interfaces)
3456 self.pg_start()
3457 capture = self.pg9.get_capture(1)
3458 p = capture[0]
3459 try:
3460 ip = p[IP]
3461 tcp = p[TCP]
3462 self.assertEqual(ip.src, remote_host.ip4)
3463 self.assertEqual(ip.dst, local_host.ip4)
3464 self.assertEqual(tcp.sport, 80)
3465 self.assertEqual(tcp.dport, 12345)
Klement Sekerad81ae412018-05-16 10:52:54 +02003466 self.assert_packet_checksums_valid(p)
Matus Fabian36ea2d62017-10-24 04:13:49 -07003467 except:
3468 self.logger.error(ppp("Unexpected or invalid packet:", p))
3469 raise
3470
Matus Fabiana5e73762018-12-14 01:55:16 -08003471 err = self.statistics.get_counter('/err/nat44-classify/next in2out')
3472 self.assertEqual(err, 1)
3473 err = self.statistics.get_counter('/err/nat44-classify/next out2in')
3474 self.assertEqual(err, 1)
3475
Matus Fabian5ba86f72017-10-26 03:37:38 -07003476 def test_del_session(self):
3477 """ Delete NAT44 session """
3478 self.nat44_add_address(self.nat_addr)
3479 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3480 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3481 is_inside=0)
3482
3483 pkts = self.create_stream_in(self.pg0, self.pg1)
3484 self.pg0.add_stream(pkts)
3485 self.pg_enable_capture(self.pg_interfaces)
3486 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07003487 self.pg1.get_capture(len(pkts))
Matus Fabian5ba86f72017-10-26 03:37:38 -07003488
3489 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
3490 nsessions = len(sessions)
3491
3492 self.vapi.nat44_del_session(sessions[0].inside_ip_address,
3493 sessions[0].inside_port,
3494 sessions[0].protocol)
3495 self.vapi.nat44_del_session(sessions[1].outside_ip_address,
3496 sessions[1].outside_port,
3497 sessions[1].protocol,
3498 is_in=0)
3499
3500 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
3501 self.assertEqual(nsessions - len(sessions), 2)
3502
Matus Fabian68ba8802018-08-08 05:52:47 -07003503 self.vapi.nat44_del_session(sessions[0].inside_ip_address,
3504 sessions[0].inside_port,
3505 sessions[0].protocol)
3506
3507 self.verify_no_nat44_user()
3508
Matus Fabianefcd1e92017-08-15 06:59:19 -07003509 def test_set_get_reass(self):
3510 """ NAT44 set/get virtual fragmentation reassembly """
3511 reas_cfg1 = self.vapi.nat_get_reass()
3512
3513 self.vapi.nat_set_reass(timeout=reas_cfg1.ip4_timeout + 5,
3514 max_reass=reas_cfg1.ip4_max_reass * 2,
3515 max_frag=reas_cfg1.ip4_max_frag * 2)
3516
3517 reas_cfg2 = self.vapi.nat_get_reass()
3518
3519 self.assertEqual(reas_cfg1.ip4_timeout + 5, reas_cfg2.ip4_timeout)
3520 self.assertEqual(reas_cfg1.ip4_max_reass * 2, reas_cfg2.ip4_max_reass)
3521 self.assertEqual(reas_cfg1.ip4_max_frag * 2, reas_cfg2.ip4_max_frag)
3522
3523 self.vapi.nat_set_reass(drop_frag=1)
3524 self.assertTrue(self.vapi.nat_get_reass().ip4_drop_frag)
3525
3526 def test_frag_in_order(self):
3527 """ NAT44 translate fragments arriving in order """
Juraj Slobodafe0aa762018-07-23 12:22:54 +02003528
Matus Fabianefcd1e92017-08-15 06:59:19 -07003529 self.nat44_add_address(self.nat_addr)
3530 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3531 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3532 is_inside=0)
3533
Matus Fabianda41d722018-10-19 04:01:19 -07003534 self.frag_in_order(proto=IP_PROTOS.tcp)
3535 self.frag_in_order(proto=IP_PROTOS.udp)
3536 self.frag_in_order(proto=IP_PROTOS.icmp)
Matus Fabianefcd1e92017-08-15 06:59:19 -07003537
Matus Fabian111add72018-11-20 02:19:05 -08003538 def test_frag_forwarding(self):
3539 """ NAT44 forwarding fragment test """
Ole Troane1ade682019-03-04 23:55:43 +01003540 self.vapi.nat44_add_del_interface_addr(self.pg1.sw_if_index)
Matus Fabian111add72018-11-20 02:19:05 -08003541 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3542 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3543 is_inside=0)
3544 self.vapi.nat44_forwarding_enable_disable(1)
3545
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07003546 data = b"A" * 16 + b"B" * 16 + b"C" * 3
Matus Fabian111add72018-11-20 02:19:05 -08003547 pkts = self.create_stream_frag(self.pg1,
3548 self.pg0.remote_ip4,
3549 4789,
3550 4789,
3551 data,
3552 proto=IP_PROTOS.udp)
3553 self.pg1.add_stream(pkts)
3554 self.pg_enable_capture(self.pg_interfaces)
3555 self.pg_start()
3556 frags = self.pg0.get_capture(len(pkts))
3557 p = self.reass_frags_and_verify(frags,
3558 self.pg1.remote_ip4,
3559 self.pg0.remote_ip4)
3560 self.assertEqual(p[UDP].sport, 4789)
3561 self.assertEqual(p[UDP].dport, 4789)
3562 self.assertEqual(data, p[Raw].load)
3563
Matus Fabianefcd1e92017-08-15 06:59:19 -07003564 def test_reass_hairpinning(self):
3565 """ NAT44 fragments hairpinning """
Juraj Slobodafe0aa762018-07-23 12:22:54 +02003566
Matus Fabianda41d722018-10-19 04:01:19 -07003567 self.server = self.pg0.remote_hosts[1]
3568 self.host_in_port = random.randint(1025, 65535)
3569 self.server_in_port = random.randint(1025, 65535)
3570 self.server_out_port = random.randint(1025, 65535)
Matus Fabianefcd1e92017-08-15 06:59:19 -07003571
3572 self.nat44_add_address(self.nat_addr)
3573 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3574 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3575 is_inside=0)
3576 # add static mapping for server
Matus Fabianda41d722018-10-19 04:01:19 -07003577 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr,
3578 self.server_in_port,
3579 self.server_out_port,
Matus Fabianefcd1e92017-08-15 06:59:19 -07003580 proto=IP_PROTOS.tcp)
Matus Fabianda41d722018-10-19 04:01:19 -07003581 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr,
3582 self.server_in_port,
3583 self.server_out_port,
3584 proto=IP_PROTOS.udp)
3585 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr)
Matus Fabianefcd1e92017-08-15 06:59:19 -07003586
Matus Fabianda41d722018-10-19 04:01:19 -07003587 self.reass_hairpinning(proto=IP_PROTOS.tcp)
3588 self.reass_hairpinning(proto=IP_PROTOS.udp)
3589 self.reass_hairpinning(proto=IP_PROTOS.icmp)
Matus Fabianefcd1e92017-08-15 06:59:19 -07003590
3591 def test_frag_out_of_order(self):
3592 """ NAT44 translate fragments arriving out of order """
Juraj Slobodafe0aa762018-07-23 12:22:54 +02003593
Matus Fabianefcd1e92017-08-15 06:59:19 -07003594 self.nat44_add_address(self.nat_addr)
3595 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3596 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3597 is_inside=0)
3598
Matus Fabianda41d722018-10-19 04:01:19 -07003599 self.frag_out_of_order(proto=IP_PROTOS.tcp)
3600 self.frag_out_of_order(proto=IP_PROTOS.udp)
3601 self.frag_out_of_order(proto=IP_PROTOS.icmp)
Matus Fabianefcd1e92017-08-15 06:59:19 -07003602
Matus Fabian27697102017-11-09 01:43:47 -08003603 def test_port_restricted(self):
3604 """ Port restricted NAT44 (MAP-E CE) """
3605 self.nat44_add_address(self.nat_addr)
3606 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3607 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3608 is_inside=0)
Matus Fabian5d28c7a2018-09-04 03:55:45 -07003609 self.vapi.nat_set_addr_and_port_alloc_alg(alg=1,
3610 psid_offset=6,
3611 psid_length=6,
3612 psid=10)
Matus Fabian27697102017-11-09 01:43:47 -08003613
3614 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3615 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3616 TCP(sport=4567, dport=22))
3617 self.pg0.add_stream(p)
3618 self.pg_enable_capture(self.pg_interfaces)
3619 self.pg_start()
3620 capture = self.pg1.get_capture(1)
3621 p = capture[0]
3622 try:
3623 ip = p[IP]
3624 tcp = p[TCP]
3625 self.assertEqual(ip.dst, self.pg1.remote_ip4)
3626 self.assertEqual(ip.src, self.nat_addr)
3627 self.assertEqual(tcp.dport, 22)
3628 self.assertNotEqual(tcp.sport, 4567)
3629 self.assertEqual((tcp.sport >> 6) & 63, 10)
Klement Sekerad81ae412018-05-16 10:52:54 +02003630 self.assert_packet_checksums_valid(p)
Matus Fabian27697102017-11-09 01:43:47 -08003631 except:
3632 self.logger.error(ppp("Unexpected or invalid packet:", p))
3633 raise
3634
Matus Fabian5d28c7a2018-09-04 03:55:45 -07003635 def test_port_range(self):
3636 """ External address port range """
3637 self.nat44_add_address(self.nat_addr)
3638 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3639 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3640 is_inside=0)
3641 self.vapi.nat_set_addr_and_port_alloc_alg(alg=2,
3642 start_port=1025,
3643 end_port=1027)
3644
3645 pkts = []
3646 for port in range(0, 5):
3647 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3648 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3649 TCP(sport=1125 + port))
3650 pkts.append(p)
3651 self.pg0.add_stream(pkts)
3652 self.pg_enable_capture(self.pg_interfaces)
3653 self.pg_start()
3654 capture = self.pg1.get_capture(3)
3655 for p in capture:
3656 tcp = p[TCP]
3657 self.assertGreaterEqual(tcp.sport, 1025)
3658 self.assertLessEqual(tcp.sport, 1027)
3659
Matus Fabiana6110b62018-06-13 05:39:07 -07003660 def test_ipfix_max_frags(self):
3661 """ IPFIX logging maximum fragments pending reassembly exceeded """
3662 self.nat44_add_address(self.nat_addr)
3663 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3664 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3665 is_inside=0)
Matus Fabiana7f8b222018-09-05 06:01:55 -07003666 self.vapi.nat_set_reass(max_frag=1)
Matus Fabiana6110b62018-06-13 05:39:07 -07003667 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
3668 src_address=self.pg3.local_ip4n,
3669 path_mtu=512,
3670 template_interval=10)
Ole Troane1ade682019-03-04 23:55:43 +01003671 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
3672 src_port=self.ipfix_src_port)
Matus Fabiana6110b62018-06-13 05:39:07 -07003673
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07003674 data = b"A" * 4 + b"B" * 16 + b"C" * 3
Matus Fabiana6110b62018-06-13 05:39:07 -07003675 self.tcp_port_in = random.randint(1025, 65535)
3676 pkts = self.create_stream_frag(self.pg0,
3677 self.pg1.remote_ip4,
3678 self.tcp_port_in,
3679 20,
3680 data)
Matus Fabiana7f8b222018-09-05 06:01:55 -07003681 pkts.reverse()
3682 self.pg0.add_stream(pkts)
Matus Fabiana6110b62018-06-13 05:39:07 -07003683 self.pg_enable_capture(self.pg_interfaces)
3684 self.pg_start()
3685 self.pg1.assert_nothing_captured()
3686 sleep(1)
3687 self.vapi.cli("ipfix flush") # FIXME this should be an API call
3688 capture = self.pg3.get_capture(9)
3689 ipfix = IPFIXDecoder()
3690 # first load template
3691 for p in capture:
3692 self.assertTrue(p.haslayer(IPFIX))
3693 self.assertEqual(p[IP].src, self.pg3.local_ip4)
3694 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
3695 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
3696 self.assertEqual(p[UDP].dport, 4739)
3697 self.assertEqual(p[IPFIX].observationDomainID,
3698 self.ipfix_domain_id)
3699 if p.haslayer(Template):
3700 ipfix.add_template(p.getlayer(Template))
3701 # verify events in data set
3702 for p in capture:
3703 if p.haslayer(Data):
3704 data = ipfix.decode_data_set(p.getlayer(Set))
Matus Fabiana7f8b222018-09-05 06:01:55 -07003705 self.verify_ipfix_max_fragments_ip4(data, 1,
Matus Fabiana6110b62018-06-13 05:39:07 -07003706 self.pg0.remote_ip4n)
3707
Matus Fabian8008d7c2018-07-09 01:34:20 -07003708 def test_multiple_outside_vrf(self):
3709 """ Multiple outside VRF """
3710 vrf_id1 = 1
3711 vrf_id2 = 2
3712
3713 self.pg1.unconfig_ip4()
3714 self.pg2.unconfig_ip4()
Ole Troan9a475372019-03-05 16:58:24 +01003715 self.vapi.ip_table_add_del(is_add=1, table_id=vrf_id1)
3716 self.vapi.ip_table_add_del(is_add=1, table_id=vrf_id2)
Matus Fabian8008d7c2018-07-09 01:34:20 -07003717 self.pg1.set_table_ip4(vrf_id1)
3718 self.pg2.set_table_ip4(vrf_id2)
3719 self.pg1.config_ip4()
3720 self.pg2.config_ip4()
3721 self.pg1.resolve_arp()
3722 self.pg2.resolve_arp()
3723
3724 self.nat44_add_address(self.nat_addr)
3725 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3726 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3727 is_inside=0)
3728 self.vapi.nat44_interface_add_del_feature(self.pg2.sw_if_index,
3729 is_inside=0)
3730
3731 try:
3732 # first VRF
3733 pkts = self.create_stream_in(self.pg0, self.pg1)
3734 self.pg0.add_stream(pkts)
3735 self.pg_enable_capture(self.pg_interfaces)
3736 self.pg_start()
3737 capture = self.pg1.get_capture(len(pkts))
3738 self.verify_capture_out(capture, self.nat_addr)
3739
3740 pkts = self.create_stream_out(self.pg1, self.nat_addr)
3741 self.pg1.add_stream(pkts)
3742 self.pg_enable_capture(self.pg_interfaces)
3743 self.pg_start()
3744 capture = self.pg0.get_capture(len(pkts))
3745 self.verify_capture_in(capture, self.pg0)
3746
3747 self.tcp_port_in = 60303
3748 self.udp_port_in = 60304
3749 self.icmp_id_in = 60305
3750
3751 # second VRF
3752 pkts = self.create_stream_in(self.pg0, self.pg2)
3753 self.pg0.add_stream(pkts)
3754 self.pg_enable_capture(self.pg_interfaces)
3755 self.pg_start()
3756 capture = self.pg2.get_capture(len(pkts))
3757 self.verify_capture_out(capture, self.nat_addr)
3758
3759 pkts = self.create_stream_out(self.pg2, self.nat_addr)
3760 self.pg2.add_stream(pkts)
3761 self.pg_enable_capture(self.pg_interfaces)
3762 self.pg_start()
3763 capture = self.pg0.get_capture(len(pkts))
3764 self.verify_capture_in(capture, self.pg0)
3765
3766 finally:
3767 self.pg1.unconfig_ip4()
3768 self.pg2.unconfig_ip4()
3769 self.pg1.set_table_ip4(0)
3770 self.pg2.set_table_ip4(0)
3771 self.pg1.config_ip4()
3772 self.pg2.config_ip4()
3773 self.pg1.resolve_arp()
3774 self.pg2.resolve_arp()
3775
Paul Vinciguerradefde0f2018-12-06 07:46:13 -08003776 @unittest.skipUnless(running_extended_tests, "part of extended tests")
Matus Fabian878c6462018-08-23 00:33:35 -07003777 def test_session_timeout(self):
3778 """ NAT44 session timeouts """
3779 self.nat44_add_address(self.nat_addr)
3780 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3781 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3782 is_inside=0)
3783 self.vapi.nat_set_timeouts(udp=5)
3784
3785 max_sessions = 1000
3786 pkts = []
3787 for i in range(0, max_sessions):
3788 src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
3789 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3790 IP(src=src, dst=self.pg1.remote_ip4) /
3791 UDP(sport=1025, dport=53))
3792 pkts.append(p)
3793 self.pg0.add_stream(pkts)
3794 self.pg_enable_capture(self.pg_interfaces)
3795 self.pg_start()
3796 self.pg1.get_capture(max_sessions)
3797
3798 sleep(6)
3799
3800 pkts = []
3801 for i in range(0, max_sessions):
3802 src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
3803 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3804 IP(src=src, dst=self.pg1.remote_ip4) /
3805 UDP(sport=1026, dport=53))
3806 pkts.append(p)
3807 self.pg0.add_stream(pkts)
3808 self.pg_enable_capture(self.pg_interfaces)
3809 self.pg_start()
3810 self.pg1.get_capture(max_sessions)
3811
3812 nsessions = 0
3813 users = self.vapi.nat44_user_dump()
3814 for user in users:
3815 nsessions = nsessions + user.nsessions
3816 self.assertLess(nsessions, 2 * max_sessions)
3817
Matus Fabianbb4e0222018-09-13 02:36:25 -07003818 def test_mss_clamping(self):
3819 """ TCP MSS clamping """
3820 self.nat44_add_address(self.nat_addr)
3821 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3822 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3823 is_inside=0)
3824
3825 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3826 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3827 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
3828 flags="S", options=[('MSS', 1400)]))
3829
3830 self.vapi.nat_set_mss_clamping(enable=1, mss_value=1000)
3831 self.pg0.add_stream(p)
3832 self.pg_enable_capture(self.pg_interfaces)
3833 self.pg_start()
3834 capture = self.pg1.get_capture(1)
3835 # Negotiated MSS value greater than configured - changed
3836 self.verify_mss_value(capture[0], 1000)
3837
3838 self.vapi.nat_set_mss_clamping(enable=0)
3839 self.pg0.add_stream(p)
3840 self.pg_enable_capture(self.pg_interfaces)
3841 self.pg_start()
3842 capture = self.pg1.get_capture(1)
3843 # MSS clamping disabled - negotiated MSS unchanged
3844 self.verify_mss_value(capture[0], 1400)
3845
3846 self.vapi.nat_set_mss_clamping(enable=1, mss_value=1500)
3847 self.pg0.add_stream(p)
3848 self.pg_enable_capture(self.pg_interfaces)
3849 self.pg_start()
3850 capture = self.pg1.get_capture(1)
3851 # Negotiated MSS value smaller than configured - unchanged
3852 self.verify_mss_value(capture[0], 1400)
3853
Matus Fabian34931eb2019-02-26 09:05:23 -08003854 @unittest.skipUnless(running_extended_tests, "part of extended tests")
3855 def test_ha_send(self):
3856 """ Send HA session synchronization events (active) """
3857 self.nat44_add_address(self.nat_addr)
3858 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3859 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3860 is_inside=0)
3861 self.vapi.nat_ha_set_listener(self.pg3.local_ip4, port=12345)
3862 self.vapi.nat_ha_set_failover(self.pg3.remote_ip4, port=12346)
3863 bind_layers(UDP, HANATStateSync, sport=12345)
3864
3865 # create sessions
3866 pkts = self.create_stream_in(self.pg0, self.pg1)
3867 self.pg0.add_stream(pkts)
3868 self.pg_enable_capture(self.pg_interfaces)
3869 self.pg_start()
3870 capture = self.pg1.get_capture(len(pkts))
3871 self.verify_capture_out(capture)
3872 # active send HA events
3873 self.vapi.nat_ha_flush()
3874 stats = self.statistics.get_counter('/nat44/ha/add-event-send')
3875 self.assertEqual(stats[0][0], 3)
3876 capture = self.pg3.get_capture(1)
3877 p = capture[0]
3878 self.assert_packet_checksums_valid(p)
3879 try:
3880 ip = p[IP]
3881 udp = p[UDP]
3882 hanat = p[HANATStateSync]
3883 except IndexError:
3884 self.logger.error(ppp("Invalid packet:", p))
3885 raise
3886 else:
3887 self.assertEqual(ip.src, self.pg3.local_ip4)
3888 self.assertEqual(ip.dst, self.pg3.remote_ip4)
3889 self.assertEqual(udp.sport, 12345)
3890 self.assertEqual(udp.dport, 12346)
3891 self.assertEqual(hanat.version, 1)
3892 self.assertEqual(hanat.thread_index, 0)
3893 self.assertEqual(hanat.count, 3)
3894 seq = hanat.sequence_number
3895 for event in hanat.events:
3896 self.assertEqual(event.event_type, 1)
3897 self.assertEqual(event.in_addr, self.pg0.remote_ip4)
3898 self.assertEqual(event.out_addr, self.nat_addr)
3899 self.assertEqual(event.fib_index, 0)
3900
3901 # ACK received events
3902 ack = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
3903 IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
3904 UDP(sport=12346, dport=12345) /
3905 HANATStateSync(sequence_number=seq, flags='ACK'))
3906 self.pg3.add_stream(ack)
3907 self.pg_start()
3908 stats = self.statistics.get_counter('/nat44/ha/ack-recv')
3909 self.assertEqual(stats[0][0], 1)
3910
3911 # delete one session
3912 self.pg_enable_capture(self.pg_interfaces)
3913 self.vapi.nat44_del_session(self.pg0.remote_ip4n, self.tcp_port_in,
3914 IP_PROTOS.tcp)
3915 self.vapi.nat_ha_flush()
3916 stats = self.statistics.get_counter('/nat44/ha/del-event-send')
3917 self.assertEqual(stats[0][0], 1)
3918 capture = self.pg3.get_capture(1)
3919 p = capture[0]
3920 try:
3921 hanat = p[HANATStateSync]
3922 except IndexError:
3923 self.logger.error(ppp("Invalid packet:", p))
3924 raise
3925 else:
3926 self.assertGreater(hanat.sequence_number, seq)
3927
3928 # do not send ACK, active retry send HA event again
3929 self.pg_enable_capture(self.pg_interfaces)
3930 sleep(12)
3931 stats = self.statistics.get_counter('/nat44/ha/retry-count')
3932 self.assertEqual(stats[0][0], 3)
3933 stats = self.statistics.get_counter('/nat44/ha/missed-count')
3934 self.assertEqual(stats[0][0], 1)
3935 capture = self.pg3.get_capture(3)
3936 for packet in capture:
3937 self.assertEqual(packet, p)
3938
3939 # session counters refresh
3940 pkts = self.create_stream_out(self.pg1)
3941 self.pg1.add_stream(pkts)
3942 self.pg_enable_capture(self.pg_interfaces)
3943 self.pg_start()
3944 self.pg0.get_capture(2)
3945 self.vapi.nat_ha_flush()
3946 stats = self.statistics.get_counter('/nat44/ha/refresh-event-send')
3947 self.assertEqual(stats[0][0], 2)
3948 capture = self.pg3.get_capture(1)
3949 p = capture[0]
3950 self.assert_packet_checksums_valid(p)
3951 try:
3952 ip = p[IP]
3953 udp = p[UDP]
3954 hanat = p[HANATStateSync]
3955 except IndexError:
3956 self.logger.error(ppp("Invalid packet:", p))
3957 raise
3958 else:
3959 self.assertEqual(ip.src, self.pg3.local_ip4)
3960 self.assertEqual(ip.dst, self.pg3.remote_ip4)
3961 self.assertEqual(udp.sport, 12345)
3962 self.assertEqual(udp.dport, 12346)
3963 self.assertEqual(hanat.version, 1)
3964 self.assertEqual(hanat.count, 2)
3965 seq = hanat.sequence_number
3966 for event in hanat.events:
3967 self.assertEqual(event.event_type, 3)
3968 self.assertEqual(event.out_addr, self.nat_addr)
3969 self.assertEqual(event.fib_index, 0)
3970 self.assertEqual(event.total_pkts, 2)
3971 self.assertGreater(event.total_bytes, 0)
3972
3973 ack = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
3974 IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
3975 UDP(sport=12346, dport=12345) /
3976 HANATStateSync(sequence_number=seq, flags='ACK'))
3977 self.pg3.add_stream(ack)
3978 self.pg_start()
3979 stats = self.statistics.get_counter('/nat44/ha/ack-recv')
3980 self.assertEqual(stats[0][0], 2)
3981
3982 def test_ha_recv(self):
3983 """ Receive HA session synchronization events (passive) """
3984 self.nat44_add_address(self.nat_addr)
3985 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3986 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3987 is_inside=0)
3988 self.vapi.nat_ha_set_listener(self.pg3.local_ip4, port=12345)
3989 bind_layers(UDP, HANATStateSync, sport=12345)
3990
3991 self.tcp_port_out = random.randint(1025, 65535)
3992 self.udp_port_out = random.randint(1025, 65535)
3993
3994 # send HA session add events to failover/passive
3995 p = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
3996 IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
3997 UDP(sport=12346, dport=12345) /
3998 HANATStateSync(sequence_number=1, events=[
3999 Event(event_type='add', protocol='tcp',
4000 in_addr=self.pg0.remote_ip4, out_addr=self.nat_addr,
4001 in_port=self.tcp_port_in, out_port=self.tcp_port_out,
4002 eh_addr=self.pg1.remote_ip4,
4003 ehn_addr=self.pg1.remote_ip4,
4004 eh_port=self.tcp_external_port,
4005 ehn_port=self.tcp_external_port, fib_index=0),
4006 Event(event_type='add', protocol='udp',
4007 in_addr=self.pg0.remote_ip4, out_addr=self.nat_addr,
4008 in_port=self.udp_port_in, out_port=self.udp_port_out,
4009 eh_addr=self.pg1.remote_ip4,
4010 ehn_addr=self.pg1.remote_ip4,
4011 eh_port=self.udp_external_port,
4012 ehn_port=self.udp_external_port, fib_index=0)]))
4013
4014 self.pg3.add_stream(p)
4015 self.pg_enable_capture(self.pg_interfaces)
4016 self.pg_start()
4017 # receive ACK
4018 capture = self.pg3.get_capture(1)
4019 p = capture[0]
4020 try:
4021 hanat = p[HANATStateSync]
4022 except IndexError:
4023 self.logger.error(ppp("Invalid packet:", p))
4024 raise
4025 else:
4026 self.assertEqual(hanat.sequence_number, 1)
4027 self.assertEqual(hanat.flags, 'ACK')
4028 self.assertEqual(hanat.version, 1)
4029 self.assertEqual(hanat.thread_index, 0)
4030 stats = self.statistics.get_counter('/nat44/ha/ack-send')
4031 self.assertEqual(stats[0][0], 1)
4032 stats = self.statistics.get_counter('/nat44/ha/add-event-recv')
4033 self.assertEqual(stats[0][0], 2)
4034 users = self.statistics.get_counter('/nat44/total-users')
4035 self.assertEqual(users[0][0], 1)
4036 sessions = self.statistics.get_counter('/nat44/total-sessions')
4037 self.assertEqual(sessions[0][0], 2)
4038 users = self.vapi.nat44_user_dump()
4039 self.assertEqual(len(users), 1)
4040 self.assertEqual(users[0].ip_address, self.pg0.remote_ip4n)
4041 # there should be 2 sessions created by HA
4042 sessions = self.vapi.nat44_user_session_dump(users[0].ip_address,
4043 users[0].vrf_id)
4044 self.assertEqual(len(sessions), 2)
4045 for session in sessions:
4046 self.assertEqual(session.inside_ip_address, self.pg0.remote_ip4n)
4047 self.assertEqual(session.outside_ip_address, self.nat_addr_n)
4048 self.assertIn(session.inside_port,
4049 [self.tcp_port_in, self.udp_port_in])
4050 self.assertIn(session.outside_port,
4051 [self.tcp_port_out, self.udp_port_out])
4052 self.assertIn(session.protocol, [IP_PROTOS.tcp, IP_PROTOS.udp])
4053
4054 # send HA session delete event to failover/passive
4055 p = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
4056 IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
4057 UDP(sport=12346, dport=12345) /
4058 HANATStateSync(sequence_number=2, events=[
4059 Event(event_type='del', protocol='udp',
4060 in_addr=self.pg0.remote_ip4, out_addr=self.nat_addr,
4061 in_port=self.udp_port_in, out_port=self.udp_port_out,
4062 eh_addr=self.pg1.remote_ip4,
4063 ehn_addr=self.pg1.remote_ip4,
4064 eh_port=self.udp_external_port,
4065 ehn_port=self.udp_external_port, fib_index=0)]))
4066
4067 self.pg3.add_stream(p)
4068 self.pg_enable_capture(self.pg_interfaces)
4069 self.pg_start()
4070 # receive ACK
4071 capture = self.pg3.get_capture(1)
4072 p = capture[0]
4073 try:
4074 hanat = p[HANATStateSync]
4075 except IndexError:
4076 self.logger.error(ppp("Invalid packet:", p))
4077 raise
4078 else:
4079 self.assertEqual(hanat.sequence_number, 2)
4080 self.assertEqual(hanat.flags, 'ACK')
4081 self.assertEqual(hanat.version, 1)
4082 users = self.vapi.nat44_user_dump()
4083 self.assertEqual(len(users), 1)
4084 self.assertEqual(users[0].ip_address, self.pg0.remote_ip4n)
4085 # now we should have only 1 session, 1 deleted by HA
4086 sessions = self.vapi.nat44_user_session_dump(users[0].ip_address,
4087 users[0].vrf_id)
4088 self.assertEqual(len(sessions), 1)
4089 stats = self.statistics.get_counter('/nat44/ha/del-event-recv')
4090 self.assertEqual(stats[0][0], 1)
4091
4092 stats = self.statistics.get_counter('/err/nat-ha/pkts-processed')
4093 self.assertEqual(stats, 2)
4094
4095 # send HA session refresh event to failover/passive
4096 p = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
4097 IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
4098 UDP(sport=12346, dport=12345) /
4099 HANATStateSync(sequence_number=3, events=[
4100 Event(event_type='refresh', protocol='tcp',
4101 in_addr=self.pg0.remote_ip4, out_addr=self.nat_addr,
4102 in_port=self.tcp_port_in, out_port=self.tcp_port_out,
4103 eh_addr=self.pg1.remote_ip4,
4104 ehn_addr=self.pg1.remote_ip4,
4105 eh_port=self.tcp_external_port,
4106 ehn_port=self.tcp_external_port, fib_index=0,
4107 total_bytes=1024, total_pkts=2)]))
4108 self.pg3.add_stream(p)
4109 self.pg_enable_capture(self.pg_interfaces)
4110 self.pg_start()
4111 # receive ACK
4112 capture = self.pg3.get_capture(1)
4113 p = capture[0]
4114 try:
4115 hanat = p[HANATStateSync]
4116 except IndexError:
4117 self.logger.error(ppp("Invalid packet:", p))
4118 raise
4119 else:
4120 self.assertEqual(hanat.sequence_number, 3)
4121 self.assertEqual(hanat.flags, 'ACK')
4122 self.assertEqual(hanat.version, 1)
4123 users = self.vapi.nat44_user_dump()
4124 self.assertEqual(len(users), 1)
4125 self.assertEqual(users[0].ip_address, self.pg0.remote_ip4n)
4126 sessions = self.vapi.nat44_user_session_dump(users[0].ip_address,
4127 users[0].vrf_id)
4128 self.assertEqual(len(sessions), 1)
4129 session = sessions[0]
4130 self.assertEqual(session.total_bytes, 1024)
4131 self.assertEqual(session.total_pkts, 2)
4132 stats = self.statistics.get_counter('/nat44/ha/refresh-event-recv')
4133 self.assertEqual(stats[0][0], 1)
4134
4135 stats = self.statistics.get_counter('/err/nat-ha/pkts-processed')
4136 self.assertEqual(stats, 3)
4137
4138 # send packet to test session created by HA
4139 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
4140 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4141 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out))
4142 self.pg1.add_stream(p)
4143 self.pg_enable_capture(self.pg_interfaces)
4144 self.pg_start()
4145 capture = self.pg0.get_capture(1)
4146 p = capture[0]
4147 try:
4148 ip = p[IP]
4149 tcp = p[TCP]
4150 except IndexError:
4151 self.logger.error(ppp("Invalid packet:", p))
4152 raise
4153 else:
4154 self.assertEqual(ip.src, self.pg1.remote_ip4)
4155 self.assertEqual(ip.dst, self.pg0.remote_ip4)
4156 self.assertEqual(tcp.sport, self.tcp_external_port)
4157 self.assertEqual(tcp.dport, self.tcp_port_in)
4158
Matus Fabiana6110b62018-06-13 05:39:07 -07004159 def tearDown(self):
4160 super(TestNAT44, self).tearDown()
4161 if not self.vpp_dead:
4162 self.logger.info(self.vapi.cli("show nat44 addresses"))
4163 self.logger.info(self.vapi.cli("show nat44 interfaces"))
4164 self.logger.info(self.vapi.cli("show nat44 static mappings"))
4165 self.logger.info(self.vapi.cli("show nat44 interface address"))
4166 self.logger.info(self.vapi.cli("show nat44 sessions detail"))
4167 self.logger.info(self.vapi.cli("show nat virtual-reassembly"))
4168 self.logger.info(self.vapi.cli("show nat44 hash tables detail"))
Matus Fabian878c6462018-08-23 00:33:35 -07004169 self.logger.info(self.vapi.cli("show nat timeouts"))
Matus Fabian5d28c7a2018-09-04 03:55:45 -07004170 self.logger.info(
4171 self.vapi.cli("show nat addr-port-assignment-alg"))
Matus Fabian34931eb2019-02-26 09:05:23 -08004172 self.logger.info(self.vapi.cli("show nat ha"))
Matus Fabiana6110b62018-06-13 05:39:07 -07004173 self.clear_nat44()
4174 self.vapi.cli("clear logging")
4175
4176
4177class TestNAT44EndpointDependent(MethodHolder):
4178 """ Endpoint-Dependent mapping and filtering test cases """
4179
4180 @classmethod
4181 def setUpConstants(cls):
4182 super(TestNAT44EndpointDependent, cls).setUpConstants()
4183 cls.vpp_cmdline.extend(["nat", "{", "endpoint-dependent", "}"])
4184
4185 @classmethod
4186 def setUpClass(cls):
4187 super(TestNAT44EndpointDependent, cls).setUpClass()
4188 cls.vapi.cli("set log class nat level debug")
4189 try:
4190 cls.tcp_port_in = 6303
4191 cls.tcp_port_out = 6303
4192 cls.udp_port_in = 6304
4193 cls.udp_port_out = 6304
4194 cls.icmp_id_in = 6305
4195 cls.icmp_id_out = 6305
4196 cls.nat_addr = '10.0.0.3'
4197 cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
4198 cls.ipfix_src_port = 4739
4199 cls.ipfix_domain_id = 1
4200 cls.tcp_external_port = 80
4201
Matus Fabian8008d7c2018-07-09 01:34:20 -07004202 cls.create_pg_interfaces(range(7))
Matus Fabiana6110b62018-06-13 05:39:07 -07004203 cls.interfaces = list(cls.pg_interfaces[0:3])
4204
4205 for i in cls.interfaces:
4206 i.admin_up()
4207 i.config_ip4()
4208 i.resolve_arp()
4209
4210 cls.pg0.generate_remote_hosts(3)
4211 cls.pg0.configure_ipv4_neighbors()
4212
4213 cls.pg3.admin_up()
4214
4215 cls.pg4.generate_remote_hosts(2)
4216 cls.pg4.config_ip4()
Ole Troan9a475372019-03-05 16:58:24 +01004217 cls.vapi.sw_interface_add_del_address(
Jakub Grajciare63325e2019-03-01 08:55:49 +01004218 sw_if_index=cls.pg4.sw_if_index,
4219 prefix=VppIpPrefix("10.0.0.1", 24).encode())
4220
Matus Fabiana6110b62018-06-13 05:39:07 -07004221 cls.pg4.admin_up()
4222 cls.pg4.resolve_arp()
4223 cls.pg4._remote_hosts[1]._ip4 = cls.pg4._remote_hosts[0]._ip4
4224 cls.pg4.resolve_arp()
4225
Matus Fabian8008d7c2018-07-09 01:34:20 -07004226 zero_ip4n = socket.inet_pton(socket.AF_INET, "0.0.0.0")
Ole Troan9a475372019-03-05 16:58:24 +01004227 cls.vapi.ip_table_add_del(is_add=1, table_id=1)
Matus Fabian8008d7c2018-07-09 01:34:20 -07004228
Jakub Grajciare63325e2019-03-01 08:55:49 +01004229 cls.pg5._local_ip4 = VppIpPrefix("10.1.1.1",
4230 cls.pg5.local_ip4_prefix.len)
Matus Fabian8008d7c2018-07-09 01:34:20 -07004231 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,
Ole Troana5b2eec2019-03-11 19:23:25 +01004239 next_hop_address=zero_ip4n,
Matus Fabian8008d7c2018-07-09 01:34:20 -07004240 next_hop_sw_if_index=cls.pg5.sw_if_index,
Ole Troana5b2eec2019-03-11 19:23:25 +01004241 table_id=1)
Matus Fabian8008d7c2018-07-09 01:34:20 -07004242
Jakub Grajciare63325e2019-03-01 08:55:49 +01004243 cls.pg6._local_ip4 = VppIpPrefix("10.1.2.1",
4244 cls.pg6.local_ip4_prefix.len)
Matus Fabian8008d7c2018-07-09 01:34:20 -07004245 cls.pg6._remote_hosts[0]._ip4 = "10.1.2.2"
4246 cls.pg6._remote_hosts[0]._ip4n = socket.inet_pton(
4247 socket.AF_INET, cls.pg6.remote_ip4)
4248 cls.pg6.set_table_ip4(1)
4249 cls.pg6.config_ip4()
4250 cls.pg6.admin_up()
4251 cls.vapi.ip_add_del_route(dst_address=cls.pg6.remote_ip4n,
4252 dst_address_length=32,
Ole Troana5b2eec2019-03-11 19:23:25 +01004253 next_hop_address=zero_ip4n,
Matus Fabian8008d7c2018-07-09 01:34:20 -07004254 next_hop_sw_if_index=cls.pg6.sw_if_index,
Ole Troana5b2eec2019-03-11 19:23:25 +01004255 table_id=1)
Matus Fabian8008d7c2018-07-09 01:34:20 -07004256
4257 cls.vapi.ip_add_del_route(dst_address=cls.pg6.remote_ip4n,
4258 dst_address_length=16,
Ole Troana5b2eec2019-03-11 19:23:25 +01004259 next_hop_address=zero_ip4n, table_id=0,
Matus Fabian8008d7c2018-07-09 01:34:20 -07004260 next_hop_table_id=1)
4261 cls.vapi.ip_add_del_route(dst_address=zero_ip4n,
4262 dst_address_length=0,
Ole Troana5b2eec2019-03-11 19:23:25 +01004263 next_hop_address=zero_ip4n, table_id=1,
Matus Fabian8008d7c2018-07-09 01:34:20 -07004264 next_hop_table_id=0)
4265 cls.vapi.ip_add_del_route(dst_address=zero_ip4n,
4266 dst_address_length=0,
Ole Troana5b2eec2019-03-11 19:23:25 +01004267 next_hop_address=cls.pg1.local_ip4n,
Matus Fabian8008d7c2018-07-09 01:34:20 -07004268 next_hop_sw_if_index=cls.pg1.sw_if_index,
Ole Troana5b2eec2019-03-11 19:23:25 +01004269 table_id=0)
Matus Fabian8008d7c2018-07-09 01:34:20 -07004270
4271 cls.pg5.resolve_arp()
4272 cls.pg6.resolve_arp()
4273
Matus Fabiana6110b62018-06-13 05:39:07 -07004274 except Exception:
4275 super(TestNAT44EndpointDependent, cls).tearDownClass()
4276 raise
4277
Juraj Slobodafe0aa762018-07-23 12:22:54 +02004278 def test_frag_in_order(self):
4279 """ NAT44 translate fragments arriving in order """
4280 self.nat44_add_address(self.nat_addr)
4281 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4282 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4283 is_inside=0)
4284 self.frag_in_order(proto=IP_PROTOS.tcp)
4285 self.frag_in_order(proto=IP_PROTOS.udp)
4286 self.frag_in_order(proto=IP_PROTOS.icmp)
4287
4288 def test_frag_in_order_dont_translate(self):
4289 """ NAT44 don't translate fragments arriving in order """
4290 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4291 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4292 is_inside=0)
4293 self.vapi.nat44_forwarding_enable_disable(enable=True)
4294 self.frag_in_order(proto=IP_PROTOS.tcp, dont_translate=True)
4295
4296 def test_frag_out_of_order(self):
4297 """ NAT44 translate fragments arriving out of order """
4298 self.nat44_add_address(self.nat_addr)
4299 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4300 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4301 is_inside=0)
4302 self.frag_out_of_order(proto=IP_PROTOS.tcp)
4303 self.frag_out_of_order(proto=IP_PROTOS.udp)
4304 self.frag_out_of_order(proto=IP_PROTOS.icmp)
4305
4306 def test_frag_out_of_order_dont_translate(self):
4307 """ NAT44 don't translate fragments arriving out of order """
4308 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4309 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4310 is_inside=0)
4311 self.vapi.nat44_forwarding_enable_disable(enable=True)
4312 self.frag_out_of_order(proto=IP_PROTOS.tcp, dont_translate=True)
4313
4314 def test_frag_in_order_in_plus_out(self):
4315 """ in+out interface fragments in order """
4316 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4317 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
4318 is_inside=0)
4319 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
4320 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4321 is_inside=0)
4322
4323 self.server = self.pg1.remote_hosts[0]
4324
4325 self.server_in_addr = self.server.ip4
4326 self.server_out_addr = '11.11.11.11'
4327 self.server_in_port = random.randint(1025, 65535)
4328 self.server_out_port = random.randint(1025, 65535)
4329
4330 self.nat44_add_address(self.server_out_addr)
4331
4332 # add static mappings for server
4333 self.nat44_add_static_mapping(self.server_in_addr,
4334 self.server_out_addr,
4335 self.server_in_port,
4336 self.server_out_port,
4337 proto=IP_PROTOS.tcp)
4338 self.nat44_add_static_mapping(self.server_in_addr,
4339 self.server_out_addr,
4340 self.server_in_port,
4341 self.server_out_port,
4342 proto=IP_PROTOS.udp)
4343 self.nat44_add_static_mapping(self.server_in_addr,
4344 self.server_out_addr,
4345 proto=IP_PROTOS.icmp)
4346
4347 self.vapi.nat_set_reass(timeout=10)
4348
4349 self.frag_in_order_in_plus_out(proto=IP_PROTOS.tcp)
4350 self.frag_in_order_in_plus_out(proto=IP_PROTOS.udp)
4351 self.frag_in_order_in_plus_out(proto=IP_PROTOS.icmp)
4352
4353 def test_frag_out_of_order_in_plus_out(self):
4354 """ in+out interface fragments out of order """
4355 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4356 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
4357 is_inside=0)
4358 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
4359 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4360 is_inside=0)
4361
4362 self.server = self.pg1.remote_hosts[0]
4363
4364 self.server_in_addr = self.server.ip4
4365 self.server_out_addr = '11.11.11.11'
4366 self.server_in_port = random.randint(1025, 65535)
4367 self.server_out_port = random.randint(1025, 65535)
4368
4369 self.nat44_add_address(self.server_out_addr)
4370
4371 # add static mappings for server
4372 self.nat44_add_static_mapping(self.server_in_addr,
4373 self.server_out_addr,
4374 self.server_in_port,
4375 self.server_out_port,
4376 proto=IP_PROTOS.tcp)
4377 self.nat44_add_static_mapping(self.server_in_addr,
4378 self.server_out_addr,
4379 self.server_in_port,
4380 self.server_out_port,
4381 proto=IP_PROTOS.udp)
4382 self.nat44_add_static_mapping(self.server_in_addr,
4383 self.server_out_addr,
4384 proto=IP_PROTOS.icmp)
4385
4386 self.vapi.nat_set_reass(timeout=10)
4387
4388 self.frag_out_of_order_in_plus_out(proto=IP_PROTOS.tcp)
4389 self.frag_out_of_order_in_plus_out(proto=IP_PROTOS.udp)
4390 self.frag_out_of_order_in_plus_out(proto=IP_PROTOS.icmp)
4391
4392 def test_reass_hairpinning(self):
4393 """ NAT44 fragments hairpinning """
4394 self.server = self.pg0.remote_hosts[1]
4395 self.host_in_port = random.randint(1025, 65535)
4396 self.server_in_port = random.randint(1025, 65535)
4397 self.server_out_port = random.randint(1025, 65535)
4398
4399 self.nat44_add_address(self.nat_addr)
4400 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4401 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4402 is_inside=0)
4403 # add static mapping for server
4404 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr,
4405 self.server_in_port,
4406 self.server_out_port,
4407 proto=IP_PROTOS.tcp)
4408 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr,
4409 self.server_in_port,
4410 self.server_out_port,
4411 proto=IP_PROTOS.udp)
Matus Fabianda41d722018-10-19 04:01:19 -07004412 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr)
Juraj Slobodafe0aa762018-07-23 12:22:54 +02004413
4414 self.reass_hairpinning(proto=IP_PROTOS.tcp)
4415 self.reass_hairpinning(proto=IP_PROTOS.udp)
4416 self.reass_hairpinning(proto=IP_PROTOS.icmp)
4417
Matus Fabiana6110b62018-06-13 05:39:07 -07004418 def test_dynamic(self):
4419 """ NAT44 dynamic translation test """
4420
4421 self.nat44_add_address(self.nat_addr)
4422 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4423 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4424 is_inside=0)
4425
Matus Fabian69ce30d2018-08-22 01:27:10 -07004426 nat_config = self.vapi.nat_show_config()
4427 self.assertEqual(1, nat_config.endpoint_dependent)
4428
Matus Fabiana6110b62018-06-13 05:39:07 -07004429 # in2out
Matus Fabiana5e73762018-12-14 01:55:16 -08004430 tcpn = self.statistics.get_counter(
4431 '/err/nat44-ed-in2out-slowpath/TCP packets')
4432 udpn = self.statistics.get_counter(
4433 '/err/nat44-ed-in2out-slowpath/UDP packets')
4434 icmpn = self.statistics.get_counter(
4435 '/err/nat44-ed-in2out-slowpath/ICMP packets')
4436 totaln = self.statistics.get_counter(
4437 '/err/nat44-ed-in2out-slowpath/good in2out packets processed')
4438
Matus Fabiana6110b62018-06-13 05:39:07 -07004439 pkts = self.create_stream_in(self.pg0, self.pg1)
4440 self.pg0.add_stream(pkts)
4441 self.pg_enable_capture(self.pg_interfaces)
4442 self.pg_start()
4443 capture = self.pg1.get_capture(len(pkts))
4444 self.verify_capture_out(capture)
4445
Matus Fabiana5e73762018-12-14 01:55:16 -08004446 err = self.statistics.get_counter(
4447 '/err/nat44-ed-in2out-slowpath/TCP packets')
4448 self.assertEqual(err - tcpn, 1)
4449 err = self.statistics.get_counter(
4450 '/err/nat44-ed-in2out-slowpath/UDP packets')
4451 self.assertEqual(err - udpn, 1)
4452 err = self.statistics.get_counter(
4453 '/err/nat44-ed-in2out-slowpath/ICMP packets')
4454 self.assertEqual(err - icmpn, 1)
4455 err = self.statistics.get_counter(
4456 '/err/nat44-ed-in2out-slowpath/good in2out packets processed')
4457 self.assertEqual(err - totaln, 3)
4458
Matus Fabiana6110b62018-06-13 05:39:07 -07004459 # out2in
Matus Fabiana5e73762018-12-14 01:55:16 -08004460 tcpn = self.statistics.get_counter('/err/nat44-ed-out2in/TCP packets')
4461 udpn = self.statistics.get_counter('/err/nat44-ed-out2in/UDP packets')
4462 icmpn = self.statistics.get_counter(
4463 '/err/nat44-ed-out2in-slowpath/ICMP packets')
4464 totaln = self.statistics.get_counter(
4465 '/err/nat44-ed-out2in/good out2in packets processed')
4466
Matus Fabiana6110b62018-06-13 05:39:07 -07004467 pkts = self.create_stream_out(self.pg1)
4468 self.pg1.add_stream(pkts)
4469 self.pg_enable_capture(self.pg_interfaces)
4470 self.pg_start()
4471 capture = self.pg0.get_capture(len(pkts))
4472 self.verify_capture_in(capture, self.pg0)
4473
Matus Fabiana5e73762018-12-14 01:55:16 -08004474 err = self.statistics.get_counter('/err/nat44-ed-out2in/TCP packets')
4475 self.assertEqual(err - tcpn, 1)
4476 err = self.statistics.get_counter('/err/nat44-ed-out2in/UDP packets')
4477 self.assertEqual(err - udpn, 1)
4478 err = self.statistics.get_counter(
4479 '/err/nat44-ed-out2in-slowpath/ICMP packets')
4480 self.assertEqual(err - icmpn, 1)
4481 err = self.statistics.get_counter(
4482 '/err/nat44-ed-out2in/good out2in packets processed')
4483 self.assertEqual(err - totaln, 2)
4484
Matus Fabianfd0d5082018-12-18 01:08:51 -08004485 users = self.statistics.get_counter('/nat44/total-users')
4486 self.assertEqual(users[0][0], 1)
4487 sessions = self.statistics.get_counter('/nat44/total-sessions')
4488 self.assertEqual(sessions[0][0], 3)
4489
Matus Fabiana6110b62018-06-13 05:39:07 -07004490 def test_forwarding(self):
4491 """ NAT44 forwarding test """
4492
4493 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4494 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4495 is_inside=0)
4496 self.vapi.nat44_forwarding_enable_disable(1)
4497
4498 real_ip = self.pg0.remote_ip4n
4499 alias_ip = self.nat_addr_n
4500 self.vapi.nat44_add_del_static_mapping(local_ip=real_ip,
4501 external_ip=alias_ip)
4502
4503 try:
4504 # in2out - static mapping match
4505
4506 pkts = self.create_stream_out(self.pg1)
4507 self.pg1.add_stream(pkts)
4508 self.pg_enable_capture(self.pg_interfaces)
4509 self.pg_start()
4510 capture = self.pg0.get_capture(len(pkts))
4511 self.verify_capture_in(capture, self.pg0)
4512
4513 pkts = self.create_stream_in(self.pg0, self.pg1)
4514 self.pg0.add_stream(pkts)
4515 self.pg_enable_capture(self.pg_interfaces)
4516 self.pg_start()
4517 capture = self.pg1.get_capture(len(pkts))
4518 self.verify_capture_out(capture, same_port=True)
4519
4520 # in2out - no static mapping match
4521
4522 host0 = self.pg0.remote_hosts[0]
4523 self.pg0.remote_hosts[0] = self.pg0.remote_hosts[1]
4524 try:
4525 pkts = self.create_stream_out(self.pg1,
4526 dst_ip=self.pg0.remote_ip4,
4527 use_inside_ports=True)
4528 self.pg1.add_stream(pkts)
4529 self.pg_enable_capture(self.pg_interfaces)
4530 self.pg_start()
4531 capture = self.pg0.get_capture(len(pkts))
4532 self.verify_capture_in(capture, self.pg0)
4533
4534 pkts = self.create_stream_in(self.pg0, self.pg1)
4535 self.pg0.add_stream(pkts)
4536 self.pg_enable_capture(self.pg_interfaces)
4537 self.pg_start()
4538 capture = self.pg1.get_capture(len(pkts))
4539 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
4540 same_port=True)
4541 finally:
4542 self.pg0.remote_hosts[0] = host0
4543
4544 user = self.pg0.remote_hosts[1]
4545 sessions = self.vapi.nat44_user_session_dump(user.ip4n, 0)
4546 self.assertEqual(len(sessions), 3)
4547 self.assertTrue(sessions[0].ext_host_valid)
4548 self.vapi.nat44_del_session(
4549 sessions[0].inside_ip_address,
4550 sessions[0].inside_port,
4551 sessions[0].protocol,
4552 ext_host_address=sessions[0].ext_host_address,
4553 ext_host_port=sessions[0].ext_host_port)
4554 sessions = self.vapi.nat44_user_session_dump(user.ip4n, 0)
4555 self.assertEqual(len(sessions), 2)
4556
4557 finally:
4558 self.vapi.nat44_forwarding_enable_disable(0)
4559 self.vapi.nat44_add_del_static_mapping(local_ip=real_ip,
4560 external_ip=alias_ip,
4561 is_add=0)
4562
4563 def test_static_lb(self):
4564 """ NAT44 local service load balancing """
4565 external_addr_n = socket.inet_pton(socket.AF_INET, self.nat_addr)
4566 external_port = 80
4567 local_port = 8080
4568 server1 = self.pg0.remote_hosts[0]
4569 server2 = self.pg0.remote_hosts[1]
4570
4571 locals = [{'addr': server1.ip4n,
4572 'port': local_port,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07004573 'probability': 70,
4574 'vrf_id': 0},
Matus Fabiana6110b62018-06-13 05:39:07 -07004575 {'addr': server2.ip4n,
4576 'port': local_port,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07004577 'probability': 30,
4578 'vrf_id': 0}]
Matus Fabiana6110b62018-06-13 05:39:07 -07004579
4580 self.nat44_add_address(self.nat_addr)
4581 self.vapi.nat44_add_del_lb_static_mapping(external_addr_n,
4582 external_port,
4583 IP_PROTOS.tcp,
4584 local_num=len(locals),
4585 locals=locals)
4586 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4587 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4588 is_inside=0)
4589
4590 # from client to service
4591 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4592 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4593 TCP(sport=12345, dport=external_port))
4594 self.pg1.add_stream(p)
4595 self.pg_enable_capture(self.pg_interfaces)
4596 self.pg_start()
4597 capture = self.pg0.get_capture(1)
4598 p = capture[0]
4599 server = None
4600 try:
4601 ip = p[IP]
4602 tcp = p[TCP]
4603 self.assertIn(ip.dst, [server1.ip4, server2.ip4])
4604 if ip.dst == server1.ip4:
4605 server = server1
4606 else:
4607 server = server2
4608 self.assertEqual(tcp.dport, local_port)
4609 self.assert_packet_checksums_valid(p)
4610 except:
4611 self.logger.error(ppp("Unexpected or invalid packet:", p))
4612 raise
4613
4614 # from service back to client
4615 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
4616 IP(src=server.ip4, dst=self.pg1.remote_ip4) /
4617 TCP(sport=local_port, dport=12345))
4618 self.pg0.add_stream(p)
4619 self.pg_enable_capture(self.pg_interfaces)
4620 self.pg_start()
4621 capture = self.pg1.get_capture(1)
4622 p = capture[0]
4623 try:
4624 ip = p[IP]
4625 tcp = p[TCP]
4626 self.assertEqual(ip.src, self.nat_addr)
4627 self.assertEqual(tcp.sport, external_port)
4628 self.assert_packet_checksums_valid(p)
4629 except:
4630 self.logger.error(ppp("Unexpected or invalid packet:", p))
4631 raise
4632
4633 sessions = self.vapi.nat44_user_session_dump(server.ip4n, 0)
4634 self.assertEqual(len(sessions), 1)
4635 self.assertTrue(sessions[0].ext_host_valid)
4636 self.vapi.nat44_del_session(
4637 sessions[0].inside_ip_address,
4638 sessions[0].inside_port,
4639 sessions[0].protocol,
4640 ext_host_address=sessions[0].ext_host_address,
4641 ext_host_port=sessions[0].ext_host_port)
4642 sessions = self.vapi.nat44_user_session_dump(server.ip4n, 0)
4643 self.assertEqual(len(sessions), 0)
4644
Paul Vinciguerradefde0f2018-12-06 07:46:13 -08004645 @unittest.skipUnless(running_extended_tests, "part of extended tests")
Matus Fabiana6110b62018-06-13 05:39:07 -07004646 def test_static_lb_multi_clients(self):
4647 """ NAT44 local service load balancing - multiple clients"""
4648
4649 external_addr_n = socket.inet_pton(socket.AF_INET, self.nat_addr)
4650 external_port = 80
4651 local_port = 8080
4652 server1 = self.pg0.remote_hosts[0]
4653 server2 = self.pg0.remote_hosts[1]
Matus Fabianb6865082018-12-06 03:11:09 -08004654 server3 = self.pg0.remote_hosts[2]
Matus Fabiana6110b62018-06-13 05:39:07 -07004655
4656 locals = [{'addr': server1.ip4n,
4657 'port': local_port,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07004658 'probability': 90,
4659 'vrf_id': 0},
Matus Fabiana6110b62018-06-13 05:39:07 -07004660 {'addr': server2.ip4n,
4661 'port': local_port,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07004662 'probability': 10,
4663 'vrf_id': 0}]
Matus Fabiana6110b62018-06-13 05:39:07 -07004664
4665 self.nat44_add_address(self.nat_addr)
4666 self.vapi.nat44_add_del_lb_static_mapping(external_addr_n,
4667 external_port,
4668 IP_PROTOS.tcp,
4669 local_num=len(locals),
4670 locals=locals)
4671 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4672 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4673 is_inside=0)
4674
4675 server1_n = 0
4676 server2_n = 0
4677 clients = ip4_range(self.pg1.remote_ip4, 10, 50)
4678 pkts = []
4679 for client in clients:
4680 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4681 IP(src=client, dst=self.nat_addr) /
4682 TCP(sport=12345, dport=external_port))
4683 pkts.append(p)
4684 self.pg1.add_stream(pkts)
4685 self.pg_enable_capture(self.pg_interfaces)
4686 self.pg_start()
4687 capture = self.pg0.get_capture(len(pkts))
4688 for p in capture:
4689 if p[IP].dst == server1.ip4:
4690 server1_n += 1
4691 else:
4692 server2_n += 1
Paul Vinciguerra3d2df212018-11-24 23:19:53 -08004693 self.assertGreater(server1_n, server2_n)
Matus Fabiana6110b62018-06-13 05:39:07 -07004694
Matus Fabianb6865082018-12-06 03:11:09 -08004695 # add new back-end
4696 self.vapi.nat44_lb_static_mapping_add_del_local(external_addr_n,
4697 external_port,
4698 server3.ip4n,
4699 local_port,
4700 IP_PROTOS.tcp,
4701 20)
4702 server1_n = 0
4703 server2_n = 0
4704 server3_n = 0
4705 clients = ip4_range(self.pg1.remote_ip4, 60, 110)
4706 pkts = []
4707 for client in clients:
4708 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4709 IP(src=client, dst=self.nat_addr) /
4710 TCP(sport=12346, dport=external_port))
4711 pkts.append(p)
4712 self.assertGreater(len(pkts), 0)
4713 self.pg1.add_stream(pkts)
4714 self.pg_enable_capture(self.pg_interfaces)
4715 self.pg_start()
4716 capture = self.pg0.get_capture(len(pkts))
4717 for p in capture:
4718 if p[IP].dst == server1.ip4:
4719 server1_n += 1
4720 elif p[IP].dst == server2.ip4:
4721 server2_n += 1
4722 else:
4723 server3_n += 1
4724 self.assertGreater(server1_n, 0)
4725 self.assertGreater(server2_n, 0)
4726 self.assertGreater(server3_n, 0)
4727
4728 # remove one back-end
4729 self.vapi.nat44_lb_static_mapping_add_del_local(external_addr_n,
4730 external_port,
4731 server2.ip4n,
4732 local_port,
4733 IP_PROTOS.tcp,
4734 10,
4735 is_add=0)
4736 server1_n = 0
4737 server2_n = 0
4738 server3_n = 0
4739 self.pg1.add_stream(pkts)
4740 self.pg_enable_capture(self.pg_interfaces)
4741 self.pg_start()
4742 capture = self.pg0.get_capture(len(pkts))
4743 for p in capture:
4744 if p[IP].dst == server1.ip4:
4745 server1_n += 1
4746 elif p[IP].dst == server2.ip4:
4747 server2_n += 1
4748 else:
4749 server3_n += 1
4750 self.assertGreater(server1_n, 0)
4751 self.assertEqual(server2_n, 0)
4752 self.assertGreater(server3_n, 0)
4753
Matus Fabiana6110b62018-06-13 05:39:07 -07004754 def test_static_lb_2(self):
4755 """ NAT44 local service load balancing (asymmetrical rule) """
4756 external_addr_n = socket.inet_pton(socket.AF_INET, self.nat_addr)
4757 external_port = 80
4758 local_port = 8080
4759 server1 = self.pg0.remote_hosts[0]
4760 server2 = self.pg0.remote_hosts[1]
4761
4762 locals = [{'addr': server1.ip4n,
4763 'port': local_port,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07004764 'probability': 70,
4765 'vrf_id': 0},
Matus Fabiana6110b62018-06-13 05:39:07 -07004766 {'addr': server2.ip4n,
4767 'port': local_port,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07004768 'probability': 30,
4769 'vrf_id': 0}]
Matus Fabiana6110b62018-06-13 05:39:07 -07004770
4771 self.vapi.nat44_forwarding_enable_disable(1)
4772 self.vapi.nat44_add_del_lb_static_mapping(external_addr_n,
4773 external_port,
4774 IP_PROTOS.tcp,
4775 out2in_only=1,
4776 local_num=len(locals),
4777 locals=locals)
4778 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4779 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4780 is_inside=0)
4781
4782 # from client to service
4783 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4784 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4785 TCP(sport=12345, dport=external_port))
4786 self.pg1.add_stream(p)
4787 self.pg_enable_capture(self.pg_interfaces)
4788 self.pg_start()
4789 capture = self.pg0.get_capture(1)
4790 p = capture[0]
4791 server = None
4792 try:
4793 ip = p[IP]
4794 tcp = p[TCP]
4795 self.assertIn(ip.dst, [server1.ip4, server2.ip4])
4796 if ip.dst == server1.ip4:
4797 server = server1
4798 else:
4799 server = server2
4800 self.assertEqual(tcp.dport, local_port)
4801 self.assert_packet_checksums_valid(p)
4802 except:
4803 self.logger.error(ppp("Unexpected or invalid packet:", p))
4804 raise
4805
4806 # from service back to client
4807 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
4808 IP(src=server.ip4, dst=self.pg1.remote_ip4) /
4809 TCP(sport=local_port, dport=12345))
4810 self.pg0.add_stream(p)
4811 self.pg_enable_capture(self.pg_interfaces)
4812 self.pg_start()
4813 capture = self.pg1.get_capture(1)
4814 p = capture[0]
4815 try:
4816 ip = p[IP]
4817 tcp = p[TCP]
4818 self.assertEqual(ip.src, self.nat_addr)
4819 self.assertEqual(tcp.sport, external_port)
4820 self.assert_packet_checksums_valid(p)
4821 except:
4822 self.logger.error(ppp("Unexpected or invalid packet:", p))
4823 raise
4824
4825 # from client to server (no translation)
4826 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4827 IP(src=self.pg1.remote_ip4, dst=server1.ip4) /
4828 TCP(sport=12346, dport=local_port))
4829 self.pg1.add_stream(p)
4830 self.pg_enable_capture(self.pg_interfaces)
4831 self.pg_start()
4832 capture = self.pg0.get_capture(1)
4833 p = capture[0]
4834 server = None
4835 try:
4836 ip = p[IP]
4837 tcp = p[TCP]
4838 self.assertEqual(ip.dst, server1.ip4)
4839 self.assertEqual(tcp.dport, local_port)
4840 self.assert_packet_checksums_valid(p)
4841 except:
4842 self.logger.error(ppp("Unexpected or invalid packet:", p))
4843 raise
4844
4845 # from service back to client (no translation)
4846 p = (Ether(src=server1.mac, dst=self.pg0.local_mac) /
4847 IP(src=server1.ip4, dst=self.pg1.remote_ip4) /
4848 TCP(sport=local_port, dport=12346))
4849 self.pg0.add_stream(p)
4850 self.pg_enable_capture(self.pg_interfaces)
4851 self.pg_start()
4852 capture = self.pg1.get_capture(1)
4853 p = capture[0]
4854 try:
4855 ip = p[IP]
4856 tcp = p[TCP]
4857 self.assertEqual(ip.src, server1.ip4)
4858 self.assertEqual(tcp.sport, local_port)
4859 self.assert_packet_checksums_valid(p)
4860 except:
4861 self.logger.error(ppp("Unexpected or invalid packet:", p))
4862 raise
4863
Matus Fabianea5b5be2018-09-03 05:02:23 -07004864 def test_lb_affinity(self):
4865 """ NAT44 local service load balancing affinity """
4866 external_addr_n = socket.inet_pton(socket.AF_INET, self.nat_addr)
4867 external_port = 80
4868 local_port = 8080
4869 server1 = self.pg0.remote_hosts[0]
4870 server2 = self.pg0.remote_hosts[1]
4871
4872 locals = [{'addr': server1.ip4n,
4873 'port': local_port,
4874 'probability': 50,
4875 'vrf_id': 0},
4876 {'addr': server2.ip4n,
4877 'port': local_port,
4878 'probability': 50,
4879 'vrf_id': 0}]
4880
4881 self.nat44_add_address(self.nat_addr)
4882 self.vapi.nat44_add_del_lb_static_mapping(external_addr_n,
4883 external_port,
4884 IP_PROTOS.tcp,
4885 affinity=10800,
4886 local_num=len(locals),
4887 locals=locals)
4888 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4889 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4890 is_inside=0)
4891
4892 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
4893 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4894 TCP(sport=1025, dport=external_port))
4895 self.pg1.add_stream(p)
4896 self.pg_enable_capture(self.pg_interfaces)
4897 self.pg_start()
4898 capture = self.pg0.get_capture(1)
4899 backend = capture[0][IP].dst
4900
4901 sessions = self.vapi.nat44_user_session_dump(
4902 socket.inet_pton(socket.AF_INET, backend), 0)
4903 self.assertEqual(len(sessions), 1)
4904 self.assertTrue(sessions[0].ext_host_valid)
4905 self.vapi.nat44_del_session(
4906 sessions[0].inside_ip_address,
4907 sessions[0].inside_port,
4908 sessions[0].protocol,
4909 ext_host_address=sessions[0].ext_host_address,
4910 ext_host_port=sessions[0].ext_host_port)
4911
4912 pkts = []
4913 for port in range(1030, 1100):
4914 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
4915 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4916 TCP(sport=port, dport=external_port))
4917 pkts.append(p)
4918 self.pg1.add_stream(pkts)
4919 self.pg_enable_capture(self.pg_interfaces)
4920 self.pg_start()
4921 capture = self.pg0.get_capture(len(pkts))
4922 for p in capture:
4923 self.assertEqual(p[IP].dst, backend)
4924
Matus Fabiana6110b62018-06-13 05:39:07 -07004925 def test_unknown_proto(self):
4926 """ NAT44 translate packet with unknown protocol """
4927 self.nat44_add_address(self.nat_addr)
4928 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4929 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4930 is_inside=0)
4931
4932 # in2out
4933 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
4934 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4935 TCP(sport=self.tcp_port_in, dport=20))
4936 self.pg0.add_stream(p)
4937 self.pg_enable_capture(self.pg_interfaces)
4938 self.pg_start()
4939 p = self.pg1.get_capture(1)
4940
4941 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
4942 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4943 GRE() /
4944 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
4945 TCP(sport=1234, dport=1234))
4946 self.pg0.add_stream(p)
4947 self.pg_enable_capture(self.pg_interfaces)
4948 self.pg_start()
4949 p = self.pg1.get_capture(1)
4950 packet = p[0]
4951 try:
4952 self.assertEqual(packet[IP].src, self.nat_addr)
4953 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
Paul Vinciguerra978aa642018-11-24 22:19:12 -08004954 self.assertEqual(packet.haslayer(GRE), 1)
Matus Fabiana6110b62018-06-13 05:39:07 -07004955 self.assert_packet_checksums_valid(packet)
4956 except:
4957 self.logger.error(ppp("Unexpected or invalid packet:", packet))
4958 raise
4959
4960 # out2in
4961 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
4962 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4963 GRE() /
4964 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
4965 TCP(sport=1234, dport=1234))
4966 self.pg1.add_stream(p)
4967 self.pg_enable_capture(self.pg_interfaces)
4968 self.pg_start()
4969 p = self.pg0.get_capture(1)
4970 packet = p[0]
4971 try:
4972 self.assertEqual(packet[IP].src, self.pg1.remote_ip4)
4973 self.assertEqual(packet[IP].dst, self.pg0.remote_ip4)
Paul Vinciguerra978aa642018-11-24 22:19:12 -08004974 self.assertEqual(packet.haslayer(GRE), 1)
Matus Fabiana6110b62018-06-13 05:39:07 -07004975 self.assert_packet_checksums_valid(packet)
4976 except:
4977 self.logger.error(ppp("Unexpected or invalid packet:", packet))
4978 raise
4979
4980 def test_hairpinning_unknown_proto(self):
4981 """ NAT44 translate packet with unknown protocol - hairpinning """
4982 host = self.pg0.remote_hosts[0]
4983 server = self.pg0.remote_hosts[1]
4984 host_in_port = 1234
4985 server_out_port = 8765
4986 server_nat_ip = "10.0.0.11"
4987
4988 self.nat44_add_address(self.nat_addr)
4989 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4990 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4991 is_inside=0)
4992
4993 # add static mapping for server
4994 self.nat44_add_static_mapping(server.ip4, server_nat_ip)
4995
4996 # host to server
4997 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
4998 IP(src=host.ip4, dst=server_nat_ip) /
4999 TCP(sport=host_in_port, dport=server_out_port))
5000 self.pg0.add_stream(p)
5001 self.pg_enable_capture(self.pg_interfaces)
5002 self.pg_start()
5003 self.pg0.get_capture(1)
5004
5005 p = (Ether(dst=self.pg0.local_mac, src=host.mac) /
5006 IP(src=host.ip4, dst=server_nat_ip) /
5007 GRE() /
5008 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
5009 TCP(sport=1234, dport=1234))
5010 self.pg0.add_stream(p)
5011 self.pg_enable_capture(self.pg_interfaces)
5012 self.pg_start()
5013 p = self.pg0.get_capture(1)
5014 packet = p[0]
5015 try:
5016 self.assertEqual(packet[IP].src, self.nat_addr)
5017 self.assertEqual(packet[IP].dst, server.ip4)
Paul Vinciguerra978aa642018-11-24 22:19:12 -08005018 self.assertEqual(packet.haslayer(GRE), 1)
Matus Fabiana6110b62018-06-13 05:39:07 -07005019 self.assert_packet_checksums_valid(packet)
5020 except:
5021 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5022 raise
5023
5024 # server to host
5025 p = (Ether(dst=self.pg0.local_mac, src=server.mac) /
5026 IP(src=server.ip4, dst=self.nat_addr) /
5027 GRE() /
5028 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
5029 TCP(sport=1234, dport=1234))
5030 self.pg0.add_stream(p)
5031 self.pg_enable_capture(self.pg_interfaces)
5032 self.pg_start()
5033 p = self.pg0.get_capture(1)
5034 packet = p[0]
5035 try:
5036 self.assertEqual(packet[IP].src, server_nat_ip)
5037 self.assertEqual(packet[IP].dst, host.ip4)
Paul Vinciguerra978aa642018-11-24 22:19:12 -08005038 self.assertEqual(packet.haslayer(GRE), 1)
Matus Fabiana6110b62018-06-13 05:39:07 -07005039 self.assert_packet_checksums_valid(packet)
5040 except:
5041 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5042 raise
5043
5044 def test_output_feature_and_service(self):
5045 """ NAT44 interface output feature and services """
5046 external_addr = '1.2.3.4'
5047 external_port = 80
5048 local_port = 8080
5049
5050 self.vapi.nat44_forwarding_enable_disable(1)
5051 self.nat44_add_address(self.nat_addr)
5052 self.vapi.nat44_add_del_identity_mapping(ip=self.pg1.remote_ip4n)
5053 self.nat44_add_static_mapping(self.pg0.remote_ip4, external_addr,
5054 local_port, external_port,
5055 proto=IP_PROTOS.tcp, out2in_only=1)
5056 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5057 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
5058 is_inside=0)
5059 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
5060 is_inside=0)
5061
5062 # from client to service
5063 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5064 IP(src=self.pg1.remote_ip4, dst=external_addr) /
5065 TCP(sport=12345, dport=external_port))
5066 self.pg1.add_stream(p)
5067 self.pg_enable_capture(self.pg_interfaces)
5068 self.pg_start()
5069 capture = self.pg0.get_capture(1)
5070 p = capture[0]
5071 try:
5072 ip = p[IP]
5073 tcp = p[TCP]
5074 self.assertEqual(ip.dst, self.pg0.remote_ip4)
5075 self.assertEqual(tcp.dport, local_port)
5076 self.assert_packet_checksums_valid(p)
5077 except:
5078 self.logger.error(ppp("Unexpected or invalid packet:", p))
5079 raise
5080
5081 # from service back to client
5082 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5083 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5084 TCP(sport=local_port, dport=12345))
5085 self.pg0.add_stream(p)
5086 self.pg_enable_capture(self.pg_interfaces)
5087 self.pg_start()
5088 capture = self.pg1.get_capture(1)
5089 p = capture[0]
5090 try:
5091 ip = p[IP]
5092 tcp = p[TCP]
5093 self.assertEqual(ip.src, external_addr)
5094 self.assertEqual(tcp.sport, external_port)
5095 self.assert_packet_checksums_valid(p)
5096 except:
5097 self.logger.error(ppp("Unexpected or invalid packet:", p))
5098 raise
5099
5100 # from local network host to external network
5101 pkts = self.create_stream_in(self.pg0, self.pg1)
5102 self.pg0.add_stream(pkts)
5103 self.pg_enable_capture(self.pg_interfaces)
5104 self.pg_start()
5105 capture = self.pg1.get_capture(len(pkts))
5106 self.verify_capture_out(capture)
5107 pkts = self.create_stream_in(self.pg0, self.pg1)
5108 self.pg0.add_stream(pkts)
5109 self.pg_enable_capture(self.pg_interfaces)
5110 self.pg_start()
5111 capture = self.pg1.get_capture(len(pkts))
5112 self.verify_capture_out(capture)
5113
5114 # from external network back to local network host
5115 pkts = self.create_stream_out(self.pg1)
5116 self.pg1.add_stream(pkts)
5117 self.pg_enable_capture(self.pg_interfaces)
5118 self.pg_start()
5119 capture = self.pg0.get_capture(len(pkts))
5120 self.verify_capture_in(capture, self.pg0)
5121
5122 def test_output_feature_and_service2(self):
5123 """ NAT44 interface output feature and service host direct access """
5124 self.vapi.nat44_forwarding_enable_disable(1)
5125 self.nat44_add_address(self.nat_addr)
5126 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
5127 is_inside=0)
5128
5129 # session initiaded from service host - translate
5130 pkts = self.create_stream_in(self.pg0, self.pg1)
5131 self.pg0.add_stream(pkts)
5132 self.pg_enable_capture(self.pg_interfaces)
5133 self.pg_start()
5134 capture = self.pg1.get_capture(len(pkts))
5135 self.verify_capture_out(capture)
5136
5137 pkts = self.create_stream_out(self.pg1)
5138 self.pg1.add_stream(pkts)
5139 self.pg_enable_capture(self.pg_interfaces)
5140 self.pg_start()
5141 capture = self.pg0.get_capture(len(pkts))
5142 self.verify_capture_in(capture, self.pg0)
5143
5144 # session initiaded from remote host - do not translate
5145 self.tcp_port_in = 60303
5146 self.udp_port_in = 60304
5147 self.icmp_id_in = 60305
5148 pkts = self.create_stream_out(self.pg1,
5149 self.pg0.remote_ip4,
5150 use_inside_ports=True)
5151 self.pg1.add_stream(pkts)
5152 self.pg_enable_capture(self.pg_interfaces)
5153 self.pg_start()
5154 capture = self.pg0.get_capture(len(pkts))
5155 self.verify_capture_in(capture, self.pg0)
5156
5157 pkts = self.create_stream_in(self.pg0, self.pg1)
5158 self.pg0.add_stream(pkts)
5159 self.pg_enable_capture(self.pg_interfaces)
5160 self.pg_start()
5161 capture = self.pg1.get_capture(len(pkts))
5162 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
5163 same_port=True)
5164
5165 def test_output_feature_and_service3(self):
5166 """ NAT44 interface output feature and DST NAT """
5167 external_addr = '1.2.3.4'
5168 external_port = 80
5169 local_port = 8080
5170
5171 self.vapi.nat44_forwarding_enable_disable(1)
5172 self.nat44_add_address(self.nat_addr)
5173 self.nat44_add_static_mapping(self.pg1.remote_ip4, external_addr,
5174 local_port, external_port,
5175 proto=IP_PROTOS.tcp, out2in_only=1)
5176 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5177 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
5178 is_inside=0)
5179 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
5180 is_inside=0)
5181
5182 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5183 IP(src=self.pg0.remote_ip4, dst=external_addr) /
5184 TCP(sport=12345, dport=external_port))
5185 self.pg0.add_stream(p)
5186 self.pg_enable_capture(self.pg_interfaces)
5187 self.pg_start()
5188 capture = self.pg1.get_capture(1)
5189 p = capture[0]
5190 try:
5191 ip = p[IP]
5192 tcp = p[TCP]
5193 self.assertEqual(ip.src, self.pg0.remote_ip4)
5194 self.assertEqual(tcp.sport, 12345)
5195 self.assertEqual(ip.dst, self.pg1.remote_ip4)
5196 self.assertEqual(tcp.dport, local_port)
5197 self.assert_packet_checksums_valid(p)
5198 except:
5199 self.logger.error(ppp("Unexpected or invalid packet:", p))
5200 raise
5201
5202 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5203 IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
5204 TCP(sport=local_port, dport=12345))
5205 self.pg1.add_stream(p)
5206 self.pg_enable_capture(self.pg_interfaces)
5207 self.pg_start()
5208 capture = self.pg0.get_capture(1)
5209 p = capture[0]
5210 try:
5211 ip = p[IP]
5212 tcp = p[TCP]
5213 self.assertEqual(ip.src, external_addr)
5214 self.assertEqual(tcp.sport, external_port)
5215 self.assertEqual(ip.dst, self.pg0.remote_ip4)
5216 self.assertEqual(tcp.dport, 12345)
5217 self.assert_packet_checksums_valid(p)
5218 except:
5219 self.logger.error(ppp("Unexpected or invalid packet:", p))
5220 raise
5221
Matus Fabian182e37e2018-08-14 04:21:26 -07005222 def test_next_src_nat(self):
5223 """ On way back forward packet to nat44-in2out node. """
5224 twice_nat_addr = '10.0.1.3'
5225 external_port = 80
5226 local_port = 8080
5227 post_twice_nat_port = 0
5228
5229 self.vapi.nat44_forwarding_enable_disable(1)
5230 self.nat44_add_address(twice_nat_addr, twice_nat=1)
5231 self.nat44_add_static_mapping(self.pg6.remote_ip4, self.pg1.remote_ip4,
5232 local_port, external_port,
5233 proto=IP_PROTOS.tcp, out2in_only=1,
5234 self_twice_nat=1, vrf_id=1)
5235 self.vapi.nat44_interface_add_del_feature(self.pg6.sw_if_index,
5236 is_inside=0)
5237
5238 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
5239 IP(src=self.pg6.remote_ip4, dst=self.pg1.remote_ip4) /
5240 TCP(sport=12345, dport=external_port))
5241 self.pg6.add_stream(p)
5242 self.pg_enable_capture(self.pg_interfaces)
5243 self.pg_start()
5244 capture = self.pg6.get_capture(1)
5245 p = capture[0]
5246 try:
5247 ip = p[IP]
5248 tcp = p[TCP]
5249 self.assertEqual(ip.src, twice_nat_addr)
5250 self.assertNotEqual(tcp.sport, 12345)
5251 post_twice_nat_port = tcp.sport
5252 self.assertEqual(ip.dst, self.pg6.remote_ip4)
5253 self.assertEqual(tcp.dport, local_port)
5254 self.assert_packet_checksums_valid(p)
5255 except:
5256 self.logger.error(ppp("Unexpected or invalid packet:", p))
5257 raise
5258
5259 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
5260 IP(src=self.pg6.remote_ip4, dst=twice_nat_addr) /
5261 TCP(sport=local_port, dport=post_twice_nat_port))
5262 self.pg6.add_stream(p)
5263 self.pg_enable_capture(self.pg_interfaces)
5264 self.pg_start()
5265 capture = self.pg6.get_capture(1)
5266 p = capture[0]
5267 try:
5268 ip = p[IP]
5269 tcp = p[TCP]
5270 self.assertEqual(ip.src, self.pg1.remote_ip4)
5271 self.assertEqual(tcp.sport, external_port)
5272 self.assertEqual(ip.dst, self.pg6.remote_ip4)
5273 self.assertEqual(tcp.dport, 12345)
5274 self.assert_packet_checksums_valid(p)
5275 except:
5276 self.logger.error(ppp("Unexpected or invalid packet:", p))
5277 raise
5278
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005279 def twice_nat_common(self, self_twice_nat=False, same_pg=False, lb=False,
5280 client_id=None):
Matus Fabianb932d262017-12-18 05:38:24 -08005281 twice_nat_addr = '10.0.1.3'
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005282
Matus Fabianb932d262017-12-18 05:38:24 -08005283 port_in = 8080
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005284 if lb:
5285 if not same_pg:
5286 port_in1 = port_in
5287 port_in2 = port_in
5288 else:
Ole Troan9a475372019-03-05 16:58:24 +01005289 port_in1 = port_in + 1
5290 port_in2 = port_in + 2
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005291
Matus Fabianb932d262017-12-18 05:38:24 -08005292 port_out = 80
5293 eh_port_out = 4567
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005294
5295 server1 = self.pg0.remote_hosts[0]
5296 server2 = self.pg0.remote_hosts[1]
5297 if lb and same_pg:
5298 server2 = server1
5299 if not lb:
5300 server = server1
5301
5302 pg0 = self.pg0
5303 if same_pg:
5304 pg1 = self.pg0
5305 else:
5306 pg1 = self.pg1
5307
5308 eh_translate = ((not self_twice_nat) or (not lb and same_pg) or
5309 client_id == 1)
5310
Matus Fabianb932d262017-12-18 05:38:24 -08005311 self.nat44_add_address(self.nat_addr)
5312 self.nat44_add_address(twice_nat_addr, twice_nat=1)
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005313 if not lb:
5314 self.nat44_add_static_mapping(pg0.remote_ip4, self.nat_addr,
5315 port_in, port_out,
5316 proto=IP_PROTOS.tcp,
5317 twice_nat=int(not self_twice_nat),
5318 self_twice_nat=int(self_twice_nat))
5319 else:
5320 locals = [{'addr': server1.ip4n,
5321 'port': port_in1,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07005322 'probability': 50,
5323 'vrf_id': 0},
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005324 {'addr': server2.ip4n,
5325 'port': port_in2,
Matus Fabianc6c0d2a2018-07-19 22:45:25 -07005326 'probability': 50,
5327 'vrf_id': 0}]
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005328 out_addr_n = socket.inet_pton(socket.AF_INET, self.nat_addr)
5329 self.vapi.nat44_add_del_lb_static_mapping(out_addr_n,
5330 port_out,
5331 IP_PROTOS.tcp,
5332 twice_nat=int(
5333 not self_twice_nat),
5334 self_twice_nat=int(
5335 self_twice_nat),
5336 local_num=len(locals),
5337 locals=locals)
5338 self.vapi.nat44_interface_add_del_feature(pg0.sw_if_index)
5339 self.vapi.nat44_interface_add_del_feature(pg1.sw_if_index,
Matus Fabianb932d262017-12-18 05:38:24 -08005340 is_inside=0)
5341
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005342 if same_pg:
5343 if not lb:
5344 client = server
5345 else:
5346 assert client_id is not None
5347 if client_id == 1:
5348 client = self.pg0.remote_hosts[0]
5349 elif client_id == 2:
5350 client = self.pg0.remote_hosts[1]
5351 else:
5352 client = pg1.remote_hosts[0]
5353 p = (Ether(src=pg1.remote_mac, dst=pg1.local_mac) /
5354 IP(src=client.ip4, dst=self.nat_addr) /
Matus Fabianb932d262017-12-18 05:38:24 -08005355 TCP(sport=eh_port_out, dport=port_out))
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005356 pg1.add_stream(p)
Matus Fabianb932d262017-12-18 05:38:24 -08005357 self.pg_enable_capture(self.pg_interfaces)
5358 self.pg_start()
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005359 capture = pg0.get_capture(1)
Matus Fabianb932d262017-12-18 05:38:24 -08005360 p = capture[0]
5361 try:
5362 ip = p[IP]
5363 tcp = p[TCP]
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005364 if lb:
5365 if ip.dst == server1.ip4:
5366 server = server1
5367 port_in = port_in1
5368 else:
5369 server = server2
5370 port_in = port_in2
5371 self.assertEqual(ip.dst, server.ip4)
5372 if lb and same_pg:
5373 self.assertIn(tcp.dport, [port_in1, port_in2])
5374 else:
5375 self.assertEqual(tcp.dport, port_in)
5376 if eh_translate:
5377 self.assertEqual(ip.src, twice_nat_addr)
5378 self.assertNotEqual(tcp.sport, eh_port_out)
5379 else:
5380 self.assertEqual(ip.src, client.ip4)
5381 self.assertEqual(tcp.sport, eh_port_out)
5382 eh_addr_in = ip.src
Matus Fabianb932d262017-12-18 05:38:24 -08005383 eh_port_in = tcp.sport
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005384 saved_port_in = tcp.dport
Klement Sekerad81ae412018-05-16 10:52:54 +02005385 self.assert_packet_checksums_valid(p)
Matus Fabianb932d262017-12-18 05:38:24 -08005386 except:
5387 self.logger.error(ppp("Unexpected or invalid packet:", p))
5388 raise
5389
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005390 p = (Ether(src=server.mac, dst=pg0.local_mac) /
5391 IP(src=server.ip4, dst=eh_addr_in) /
5392 TCP(sport=saved_port_in, dport=eh_port_in))
5393 pg0.add_stream(p)
Matus Fabianb932d262017-12-18 05:38:24 -08005394 self.pg_enable_capture(self.pg_interfaces)
5395 self.pg_start()
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005396 capture = pg1.get_capture(1)
Matus Fabianb932d262017-12-18 05:38:24 -08005397 p = capture[0]
5398 try:
5399 ip = p[IP]
5400 tcp = p[TCP]
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005401 self.assertEqual(ip.dst, client.ip4)
Matus Fabianb932d262017-12-18 05:38:24 -08005402 self.assertEqual(ip.src, self.nat_addr)
5403 self.assertEqual(tcp.dport, eh_port_out)
5404 self.assertEqual(tcp.sport, port_out)
Klement Sekerad81ae412018-05-16 10:52:54 +02005405 self.assert_packet_checksums_valid(p)
Matus Fabianb932d262017-12-18 05:38:24 -08005406 except:
5407 self.logger.error(ppp("Unexpected or invalid packet:", p))
5408 raise
5409
Matus Fabian70a26ac2018-05-14 06:20:28 -07005410 if eh_translate:
5411 sessions = self.vapi.nat44_user_session_dump(server.ip4n, 0)
5412 self.assertEqual(len(sessions), 1)
5413 self.assertTrue(sessions[0].ext_host_valid)
5414 self.assertTrue(sessions[0].is_twicenat)
5415 self.vapi.nat44_del_session(
5416 sessions[0].inside_ip_address,
5417 sessions[0].inside_port,
5418 sessions[0].protocol,
5419 ext_host_address=sessions[0].ext_host_nat_address,
5420 ext_host_port=sessions[0].ext_host_nat_port)
5421 sessions = self.vapi.nat44_user_session_dump(server.ip4n, 0)
5422 self.assertEqual(len(sessions), 0)
5423
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005424 def test_twice_nat(self):
5425 """ Twice NAT44 """
5426 self.twice_nat_common()
5427
5428 def test_self_twice_nat_positive(self):
5429 """ Self Twice NAT44 (positive test) """
5430 self.twice_nat_common(self_twice_nat=True, same_pg=True)
5431
5432 def test_self_twice_nat_negative(self):
5433 """ Self Twice NAT44 (negative test) """
5434 self.twice_nat_common(self_twice_nat=True)
5435
Matus Fabianb932d262017-12-18 05:38:24 -08005436 def test_twice_nat_lb(self):
5437 """ Twice NAT44 local service load balancing """
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005438 self.twice_nat_common(lb=True)
Matus Fabianb932d262017-12-18 05:38:24 -08005439
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005440 def test_self_twice_nat_lb_positive(self):
5441 """ Self Twice NAT44 local service load balancing (positive test) """
5442 self.twice_nat_common(lb=True, self_twice_nat=True, same_pg=True,
5443 client_id=1)
Matus Fabianb932d262017-12-18 05:38:24 -08005444
Juraj Sloboda1e5c07d2018-04-10 13:51:54 +02005445 def test_self_twice_nat_lb_negative(self):
5446 """ Self Twice NAT44 local service load balancing (negative test) """
5447 self.twice_nat_common(lb=True, self_twice_nat=True, same_pg=True,
5448 client_id=2)
Matus Fabianb932d262017-12-18 05:38:24 -08005449
5450 def test_twice_nat_interface_addr(self):
5451 """ Acquire twice NAT44 addresses from interface """
Ole Troane1ade682019-03-04 23:55:43 +01005452 self.vapi.nat44_add_del_interface_addr(self.pg3.sw_if_index,
5453 twice_nat=1)
Matus Fabianb932d262017-12-18 05:38:24 -08005454
5455 # no address in NAT pool
5456 adresses = self.vapi.nat44_address_dump()
5457 self.assertEqual(0, len(adresses))
5458
5459 # configure interface address and check NAT address pool
Matus Fabiana6110b62018-06-13 05:39:07 -07005460 self.pg3.config_ip4()
Matus Fabianb932d262017-12-18 05:38:24 -08005461 adresses = self.vapi.nat44_address_dump()
5462 self.assertEqual(1, len(adresses))
Matus Fabiana6110b62018-06-13 05:39:07 -07005463 self.assertEqual(adresses[0].ip_address[0:4], self.pg3.local_ip4n)
Matus Fabianb932d262017-12-18 05:38:24 -08005464 self.assertEqual(adresses[0].twice_nat, 1)
5465
5466 # remove interface address and check NAT address pool
Matus Fabiana6110b62018-06-13 05:39:07 -07005467 self.pg3.unconfig_ip4()
Matus Fabianb932d262017-12-18 05:38:24 -08005468 adresses = self.vapi.nat44_address_dump()
5469 self.assertEqual(0, len(adresses))
5470
Matus Fabian6c01dce2018-11-16 04:41:31 -08005471 def test_tcp_close(self):
5472 """ Close TCP session from inside network - output feature """
5473 self.vapi.nat44_forwarding_enable_disable(1)
5474 self.nat44_add_address(self.pg1.local_ip4)
5475 twice_nat_addr = '10.0.1.3'
5476 service_ip = '192.168.16.150'
5477 self.nat44_add_address(twice_nat_addr, twice_nat=1)
5478 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5479 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
5480 is_inside=0)
5481 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
5482 is_inside=0)
5483 self.nat44_add_static_mapping(self.pg0.remote_ip4,
5484 service_ip,
5485 80,
5486 80,
5487 proto=IP_PROTOS.tcp,
5488 out2in_only=1,
5489 twice_nat=1)
5490 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
5491 start_sessnum = len(sessions)
5492
5493 # SYN packet out->in
5494 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5495 IP(src=self.pg1.remote_ip4, dst=service_ip) /
5496 TCP(sport=33898, dport=80, flags="S"))
5497 self.pg1.add_stream(p)
5498 self.pg_enable_capture(self.pg_interfaces)
5499 self.pg_start()
5500 capture = self.pg0.get_capture(1)
5501 p = capture[0]
5502 tcp_port = p[TCP].sport
5503
5504 # SYN + ACK packet in->out
5505 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5506 IP(src=self.pg0.remote_ip4, dst=twice_nat_addr) /
5507 TCP(sport=80, dport=tcp_port, flags="SA"))
5508 self.pg0.add_stream(p)
5509 self.pg_enable_capture(self.pg_interfaces)
5510 self.pg_start()
5511 self.pg1.get_capture(1)
5512
5513 # ACK packet out->in
5514 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5515 IP(src=self.pg1.remote_ip4, dst=service_ip) /
5516 TCP(sport=33898, dport=80, flags="A"))
5517 self.pg1.add_stream(p)
5518 self.pg_enable_capture(self.pg_interfaces)
5519 self.pg_start()
5520 self.pg0.get_capture(1)
5521
5522 # FIN packet in -> out
5523 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5524 IP(src=self.pg0.remote_ip4, dst=twice_nat_addr) /
5525 TCP(sport=80, dport=tcp_port, flags="FA", seq=100, ack=300))
5526 self.pg0.add_stream(p)
5527 self.pg_enable_capture(self.pg_interfaces)
5528 self.pg_start()
5529 self.pg1.get_capture(1)
5530
5531 # FIN+ACK packet out -> in
5532 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5533 IP(src=self.pg1.remote_ip4, dst=service_ip) /
5534 TCP(sport=33898, dport=80, flags="FA", seq=300, ack=101))
5535 self.pg1.add_stream(p)
5536 self.pg_enable_capture(self.pg_interfaces)
5537 self.pg_start()
5538 self.pg0.get_capture(1)
5539
5540 # ACK packet in -> out
5541 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5542 IP(src=self.pg0.remote_ip4, dst=twice_nat_addr) /
5543 TCP(sport=80, dport=tcp_port, flags="A", seq=101, ack=301))
5544 self.pg0.add_stream(p)
5545 self.pg_enable_capture(self.pg_interfaces)
5546 self.pg_start()
5547 self.pg1.get_capture(1)
5548
5549 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n,
5550 0)
5551 self.assertEqual(len(sessions) - start_sessnum, 0)
5552
Matus Fabianebdf1902018-05-04 03:57:42 -07005553 def test_tcp_session_close_in(self):
5554 """ Close TCP session from inside network """
Matus Fabian229c1aa2018-05-28 04:09:52 -07005555 self.tcp_port_out = 10505
Matus Fabianebdf1902018-05-04 03:57:42 -07005556 self.nat44_add_address(self.nat_addr)
Matus Fabian229c1aa2018-05-28 04:09:52 -07005557 self.nat44_add_static_mapping(self.pg0.remote_ip4,
5558 self.nat_addr,
5559 self.tcp_port_in,
5560 self.tcp_port_out,
5561 proto=IP_PROTOS.tcp,
5562 twice_nat=1)
Matus Fabianebdf1902018-05-04 03:57:42 -07005563 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5564 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
5565 is_inside=0)
5566
5567 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
5568 start_sessnum = len(sessions)
5569
5570 self.initiate_tcp_session(self.pg0, self.pg1)
5571
Matus Fabian229c1aa2018-05-28 04:09:52 -07005572 # FIN packet in -> out
5573 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5574 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5575 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
5576 flags="FA", seq=100, ack=300))
5577 self.pg0.add_stream(p)
5578 self.pg_enable_capture(self.pg_interfaces)
5579 self.pg_start()
5580 self.pg1.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07005581
Matus Fabian229c1aa2018-05-28 04:09:52 -07005582 pkts = []
Matus Fabianebdf1902018-05-04 03:57:42 -07005583
Matus Fabian229c1aa2018-05-28 04:09:52 -07005584 # ACK packet out -> in
5585 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5586 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5587 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
5588 flags="A", seq=300, ack=101))
5589 pkts.append(p)
Matus Fabianebdf1902018-05-04 03:57:42 -07005590
Matus Fabian229c1aa2018-05-28 04:09:52 -07005591 # FIN packet out -> in
5592 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5593 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5594 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
5595 flags="FA", seq=300, ack=101))
5596 pkts.append(p)
Matus Fabianebdf1902018-05-04 03:57:42 -07005597
Matus Fabian229c1aa2018-05-28 04:09:52 -07005598 self.pg1.add_stream(pkts)
5599 self.pg_enable_capture(self.pg_interfaces)
5600 self.pg_start()
5601 self.pg0.get_capture(2)
Matus Fabianebdf1902018-05-04 03:57:42 -07005602
Matus Fabian229c1aa2018-05-28 04:09:52 -07005603 # ACK packet in -> out
5604 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5605 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5606 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
5607 flags="A", seq=101, ack=301))
5608 self.pg0.add_stream(p)
5609 self.pg_enable_capture(self.pg_interfaces)
5610 self.pg_start()
5611 self.pg1.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07005612
Matus Fabian229c1aa2018-05-28 04:09:52 -07005613 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n,
5614 0)
5615 self.assertEqual(len(sessions) - start_sessnum, 0)
Matus Fabianebdf1902018-05-04 03:57:42 -07005616
5617 def test_tcp_session_close_out(self):
5618 """ Close TCP session from outside network """
Matus Fabian229c1aa2018-05-28 04:09:52 -07005619 self.tcp_port_out = 10505
Matus Fabianebdf1902018-05-04 03:57:42 -07005620 self.nat44_add_address(self.nat_addr)
Matus Fabian229c1aa2018-05-28 04:09:52 -07005621 self.nat44_add_static_mapping(self.pg0.remote_ip4,
5622 self.nat_addr,
5623 self.tcp_port_in,
5624 self.tcp_port_out,
5625 proto=IP_PROTOS.tcp,
5626 twice_nat=1)
Matus Fabianebdf1902018-05-04 03:57:42 -07005627 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5628 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
5629 is_inside=0)
5630
5631 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
5632 start_sessnum = len(sessions)
5633
5634 self.initiate_tcp_session(self.pg0, self.pg1)
5635
Matus Fabian229c1aa2018-05-28 04:09:52 -07005636 # FIN packet out -> in
5637 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5638 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5639 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
5640 flags="FA", seq=100, ack=300))
5641 self.pg1.add_stream(p)
5642 self.pg_enable_capture(self.pg_interfaces)
5643 self.pg_start()
5644 self.pg0.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07005645
Matus Fabian229c1aa2018-05-28 04:09:52 -07005646 # FIN+ACK packet in -> out
5647 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5648 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5649 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
5650 flags="FA", seq=300, ack=101))
Matus Fabianebdf1902018-05-04 03:57:42 -07005651
Matus Fabian229c1aa2018-05-28 04:09:52 -07005652 self.pg0.add_stream(p)
5653 self.pg_enable_capture(self.pg_interfaces)
5654 self.pg_start()
5655 self.pg1.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07005656
Matus Fabian229c1aa2018-05-28 04:09:52 -07005657 # ACK packet out -> in
5658 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5659 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5660 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
5661 flags="A", seq=101, ack=301))
5662 self.pg1.add_stream(p)
5663 self.pg_enable_capture(self.pg_interfaces)
5664 self.pg_start()
5665 self.pg0.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07005666
Matus Fabian229c1aa2018-05-28 04:09:52 -07005667 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n,
5668 0)
5669 self.assertEqual(len(sessions) - start_sessnum, 0)
Matus Fabianebdf1902018-05-04 03:57:42 -07005670
5671 def test_tcp_session_close_simultaneous(self):
5672 """ Close TCP session from inside network """
Matus Fabian229c1aa2018-05-28 04:09:52 -07005673 self.tcp_port_out = 10505
Matus Fabianebdf1902018-05-04 03:57:42 -07005674 self.nat44_add_address(self.nat_addr)
Matus Fabian229c1aa2018-05-28 04:09:52 -07005675 self.nat44_add_static_mapping(self.pg0.remote_ip4,
5676 self.nat_addr,
5677 self.tcp_port_in,
5678 self.tcp_port_out,
5679 proto=IP_PROTOS.tcp,
5680 twice_nat=1)
Matus Fabianebdf1902018-05-04 03:57:42 -07005681 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5682 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
5683 is_inside=0)
5684
5685 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
5686 start_sessnum = len(sessions)
5687
5688 self.initiate_tcp_session(self.pg0, self.pg1)
5689
Matus Fabian229c1aa2018-05-28 04:09:52 -07005690 # FIN packet in -> out
5691 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5692 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5693 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
5694 flags="FA", seq=100, ack=300))
5695 self.pg0.add_stream(p)
5696 self.pg_enable_capture(self.pg_interfaces)
5697 self.pg_start()
5698 self.pg1.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07005699
Matus Fabian229c1aa2018-05-28 04:09:52 -07005700 # FIN packet out -> in
5701 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5702 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5703 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
5704 flags="FA", seq=300, ack=100))
5705 self.pg1.add_stream(p)
5706 self.pg_enable_capture(self.pg_interfaces)
5707 self.pg_start()
5708 self.pg0.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07005709
Matus Fabian229c1aa2018-05-28 04:09:52 -07005710 # ACK packet in -> out
5711 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5712 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5713 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
5714 flags="A", seq=101, ack=301))
5715 self.pg0.add_stream(p)
5716 self.pg_enable_capture(self.pg_interfaces)
5717 self.pg_start()
5718 self.pg1.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07005719
Matus Fabian229c1aa2018-05-28 04:09:52 -07005720 # ACK packet out -> in
5721 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5722 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5723 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
5724 flags="A", seq=301, ack=101))
5725 self.pg1.add_stream(p)
5726 self.pg_enable_capture(self.pg_interfaces)
5727 self.pg_start()
5728 self.pg0.get_capture(1)
Matus Fabianebdf1902018-05-04 03:57:42 -07005729
Matus Fabian229c1aa2018-05-28 04:09:52 -07005730 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n,
5731 0)
5732 self.assertEqual(len(sessions) - start_sessnum, 0)
Matus Fabianebdf1902018-05-04 03:57:42 -07005733
Matus Fabiana6110b62018-06-13 05:39:07 -07005734 def test_one_armed_nat44_static(self):
5735 """ One armed NAT44 and 1:1 NAPT asymmetrical rule """
5736 remote_host = self.pg4.remote_hosts[0]
5737 local_host = self.pg4.remote_hosts[1]
5738 external_port = 80
5739 local_port = 8080
5740 eh_port_in = 0
5741
5742 self.vapi.nat44_forwarding_enable_disable(1)
5743 self.nat44_add_address(self.nat_addr, twice_nat=1)
5744 self.nat44_add_static_mapping(local_host.ip4, self.nat_addr,
5745 local_port, external_port,
5746 proto=IP_PROTOS.tcp, out2in_only=1,
5747 twice_nat=1)
5748 self.vapi.nat44_interface_add_del_feature(self.pg4.sw_if_index)
5749 self.vapi.nat44_interface_add_del_feature(self.pg4.sw_if_index,
5750 is_inside=0)
5751
5752 # from client to service
5753 p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
5754 IP(src=remote_host.ip4, dst=self.nat_addr) /
5755 TCP(sport=12345, dport=external_port))
5756 self.pg4.add_stream(p)
5757 self.pg_enable_capture(self.pg_interfaces)
5758 self.pg_start()
5759 capture = self.pg4.get_capture(1)
5760 p = capture[0]
5761 try:
5762 ip = p[IP]
5763 tcp = p[TCP]
5764 self.assertEqual(ip.dst, local_host.ip4)
5765 self.assertEqual(ip.src, self.nat_addr)
5766 self.assertEqual(tcp.dport, local_port)
5767 self.assertNotEqual(tcp.sport, 12345)
5768 eh_port_in = tcp.sport
5769 self.assert_packet_checksums_valid(p)
5770 except:
5771 self.logger.error(ppp("Unexpected or invalid packet:", p))
5772 raise
5773
5774 # from service back to client
5775 p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
5776 IP(src=local_host.ip4, dst=self.nat_addr) /
5777 TCP(sport=local_port, dport=eh_port_in))
5778 self.pg4.add_stream(p)
5779 self.pg_enable_capture(self.pg_interfaces)
5780 self.pg_start()
5781 capture = self.pg4.get_capture(1)
5782 p = capture[0]
5783 try:
5784 ip = p[IP]
5785 tcp = p[TCP]
5786 self.assertEqual(ip.src, self.nat_addr)
5787 self.assertEqual(ip.dst, remote_host.ip4)
5788 self.assertEqual(tcp.sport, external_port)
5789 self.assertEqual(tcp.dport, 12345)
5790 self.assert_packet_checksums_valid(p)
5791 except:
5792 self.logger.error(ppp("Unexpected or invalid packet:", p))
5793 raise
5794
5795 def test_static_with_port_out2(self):
5796 """ 1:1 NAPT asymmetrical rule """
5797
5798 external_port = 80
5799 local_port = 8080
5800
5801 self.vapi.nat44_forwarding_enable_disable(1)
5802 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
5803 local_port, external_port,
5804 proto=IP_PROTOS.tcp, out2in_only=1)
5805 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5806 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
5807 is_inside=0)
5808
5809 # from client to service
5810 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5811 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5812 TCP(sport=12345, dport=external_port))
5813 self.pg1.add_stream(p)
5814 self.pg_enable_capture(self.pg_interfaces)
5815 self.pg_start()
5816 capture = self.pg0.get_capture(1)
5817 p = capture[0]
5818 try:
5819 ip = p[IP]
5820 tcp = p[TCP]
5821 self.assertEqual(ip.dst, self.pg0.remote_ip4)
5822 self.assertEqual(tcp.dport, local_port)
5823 self.assert_packet_checksums_valid(p)
5824 except:
5825 self.logger.error(ppp("Unexpected or invalid packet:", p))
5826 raise
5827
5828 # ICMP error
5829 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5830 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5831 ICMP(type=11) / capture[0][IP])
5832 self.pg0.add_stream(p)
5833 self.pg_enable_capture(self.pg_interfaces)
5834 self.pg_start()
5835 capture = self.pg1.get_capture(1)
5836 p = capture[0]
5837 try:
5838 self.assertEqual(p[IP].src, self.nat_addr)
5839 inner = p[IPerror]
5840 self.assertEqual(inner.dst, self.nat_addr)
5841 self.assertEqual(inner[TCPerror].dport, external_port)
5842 except:
5843 self.logger.error(ppp("Unexpected or invalid packet:", p))
5844 raise
5845
5846 # from service back to client
5847 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5848 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5849 TCP(sport=local_port, dport=12345))
5850 self.pg0.add_stream(p)
5851 self.pg_enable_capture(self.pg_interfaces)
5852 self.pg_start()
5853 capture = self.pg1.get_capture(1)
5854 p = capture[0]
5855 try:
5856 ip = p[IP]
5857 tcp = p[TCP]
5858 self.assertEqual(ip.src, self.nat_addr)
5859 self.assertEqual(tcp.sport, external_port)
5860 self.assert_packet_checksums_valid(p)
5861 except:
5862 self.logger.error(ppp("Unexpected or invalid packet:", p))
5863 raise
5864
5865 # ICMP error
5866 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
5867 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5868 ICMP(type=11) / capture[0][IP])
5869 self.pg1.add_stream(p)
5870 self.pg_enable_capture(self.pg_interfaces)
5871 self.pg_start()
5872 capture = self.pg0.get_capture(1)
5873 p = capture[0]
5874 try:
5875 self.assertEqual(p[IP].dst, self.pg0.remote_ip4)
5876 inner = p[IPerror]
5877 self.assertEqual(inner.src, self.pg0.remote_ip4)
5878 self.assertEqual(inner[TCPerror].sport, local_port)
5879 except:
5880 self.logger.error(ppp("Unexpected or invalid packet:", p))
5881 raise
5882
5883 # from client to server (no translation)
5884 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5885 IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
5886 TCP(sport=12346, dport=local_port))
5887 self.pg1.add_stream(p)
5888 self.pg_enable_capture(self.pg_interfaces)
5889 self.pg_start()
5890 capture = self.pg0.get_capture(1)
5891 p = capture[0]
5892 try:
5893 ip = p[IP]
5894 tcp = p[TCP]
5895 self.assertEqual(ip.dst, self.pg0.remote_ip4)
5896 self.assertEqual(tcp.dport, local_port)
5897 self.assert_packet_checksums_valid(p)
5898 except:
5899 self.logger.error(ppp("Unexpected or invalid packet:", p))
5900 raise
5901
5902 # from service back to client (no translation)
5903 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5904 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5905 TCP(sport=local_port, dport=12346))
5906 self.pg0.add_stream(p)
5907 self.pg_enable_capture(self.pg_interfaces)
5908 self.pg_start()
5909 capture = self.pg1.get_capture(1)
5910 p = capture[0]
5911 try:
5912 ip = p[IP]
5913 tcp = p[TCP]
5914 self.assertEqual(ip.src, self.pg0.remote_ip4)
5915 self.assertEqual(tcp.sport, local_port)
5916 self.assert_packet_checksums_valid(p)
5917 except:
5918 self.logger.error(ppp("Unexpected or invalid packet:", p))
5919 raise
5920
Matus Fabian235a47e2018-06-25 16:42:36 -07005921 def test_output_feature(self):
5922 """ NAT44 interface output feature (in2out postrouting) """
5923 self.vapi.nat44_forwarding_enable_disable(1)
5924 self.nat44_add_address(self.nat_addr)
5925 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
5926 is_inside=0)
5927 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
5928 is_inside=0)
5929
5930 # in2out
5931 pkts = self.create_stream_in(self.pg0, self.pg1)
5932 self.pg0.add_stream(pkts)
5933 self.pg_enable_capture(self.pg_interfaces)
5934 self.pg_start()
5935 capture = self.pg1.get_capture(len(pkts))
5936 self.verify_capture_out(capture)
5937
5938 # out2in
5939 pkts = self.create_stream_out(self.pg1)
5940 self.pg1.add_stream(pkts)
5941 self.pg_enable_capture(self.pg_interfaces)
5942 self.pg_start()
5943 capture = self.pg0.get_capture(len(pkts))
5944 self.verify_capture_in(capture, self.pg0)
5945
Matus Fabian8008d7c2018-07-09 01:34:20 -07005946 def test_multiple_vrf(self):
5947 """ Multiple VRF setup """
5948 external_addr = '1.2.3.4'
5949 external_port = 80
5950 local_port = 8080
5951 port = 0
5952
5953 self.vapi.nat44_forwarding_enable_disable(1)
5954 self.nat44_add_address(self.nat_addr)
5955 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5956 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
5957 is_inside=0)
5958 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
5959 is_inside=0)
5960 self.vapi.nat44_interface_add_del_feature(self.pg5.sw_if_index)
5961 self.vapi.nat44_interface_add_del_feature(self.pg5.sw_if_index,
5962 is_inside=0)
5963 self.vapi.nat44_interface_add_del_feature(self.pg6.sw_if_index,
5964 is_inside=0)
5965 self.nat44_add_static_mapping(self.pg5.remote_ip4, external_addr,
5966 local_port, external_port, vrf_id=1,
5967 proto=IP_PROTOS.tcp, out2in_only=1)
5968 self.nat44_add_static_mapping(
Ole Troan9a475372019-03-05 16:58:24 +01005969 self.pg0.remote_ip4, external_sw_if_index=self.pg0.sw_if_index,
5970 local_port=local_port, vrf_id=0, external_port=external_port,
5971 proto=IP_PROTOS.tcp, out2in_only=1)
Matus Fabian8008d7c2018-07-09 01:34:20 -07005972
5973 # from client to service (both VRF1)
5974 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
5975 IP(src=self.pg6.remote_ip4, dst=external_addr) /
5976 TCP(sport=12345, dport=external_port))
5977 self.pg6.add_stream(p)
5978 self.pg_enable_capture(self.pg_interfaces)
5979 self.pg_start()
5980 capture = self.pg5.get_capture(1)
5981 p = capture[0]
5982 try:
5983 ip = p[IP]
5984 tcp = p[TCP]
5985 self.assertEqual(ip.dst, self.pg5.remote_ip4)
5986 self.assertEqual(tcp.dport, local_port)
5987 self.assert_packet_checksums_valid(p)
5988 except:
5989 self.logger.error(ppp("Unexpected or invalid packet:", p))
5990 raise
5991
5992 # from service back to client (both VRF1)
5993 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
5994 IP(src=self.pg5.remote_ip4, dst=self.pg6.remote_ip4) /
5995 TCP(sport=local_port, dport=12345))
5996 self.pg5.add_stream(p)
5997 self.pg_enable_capture(self.pg_interfaces)
5998 self.pg_start()
5999 capture = self.pg6.get_capture(1)
6000 p = capture[0]
6001 try:
6002 ip = p[IP]
6003 tcp = p[TCP]
6004 self.assertEqual(ip.src, external_addr)
6005 self.assertEqual(tcp.sport, external_port)
6006 self.assert_packet_checksums_valid(p)
6007 except:
6008 self.logger.error(ppp("Unexpected or invalid packet:", p))
6009 raise
6010
6011 # dynamic NAT from VRF1 to VRF0 (output-feature)
6012 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
6013 IP(src=self.pg5.remote_ip4, dst=self.pg1.remote_ip4) /
6014 TCP(sport=2345, dport=22))
6015 self.pg5.add_stream(p)
6016 self.pg_enable_capture(self.pg_interfaces)
6017 self.pg_start()
6018 capture = self.pg1.get_capture(1)
6019 p = capture[0]
6020 try:
6021 ip = p[IP]
6022 tcp = p[TCP]
6023 self.assertEqual(ip.src, self.nat_addr)
6024 self.assertNotEqual(tcp.sport, 2345)
6025 self.assert_packet_checksums_valid(p)
6026 port = tcp.sport
6027 except:
6028 self.logger.error(ppp("Unexpected or invalid packet:", p))
6029 raise
6030
6031 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6032 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6033 TCP(sport=22, dport=port))
6034 self.pg1.add_stream(p)
6035 self.pg_enable_capture(self.pg_interfaces)
6036 self.pg_start()
6037 capture = self.pg5.get_capture(1)
6038 p = capture[0]
6039 try:
6040 ip = p[IP]
6041 tcp = p[TCP]
6042 self.assertEqual(ip.dst, self.pg5.remote_ip4)
6043 self.assertEqual(tcp.dport, 2345)
6044 self.assert_packet_checksums_valid(p)
6045 except:
6046 self.logger.error(ppp("Unexpected or invalid packet:", p))
6047 raise
6048
6049 # from client VRF1 to service VRF0
6050 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
6051 IP(src=self.pg6.remote_ip4, dst=self.pg0.local_ip4) /
6052 TCP(sport=12346, dport=external_port))
6053 self.pg6.add_stream(p)
6054 self.pg_enable_capture(self.pg_interfaces)
6055 self.pg_start()
6056 capture = self.pg0.get_capture(1)
6057 p = capture[0]
6058 try:
6059 ip = p[IP]
6060 tcp = p[TCP]
6061 self.assertEqual(ip.dst, self.pg0.remote_ip4)
6062 self.assertEqual(tcp.dport, local_port)
6063 self.assert_packet_checksums_valid(p)
6064 except:
6065 self.logger.error(ppp("Unexpected or invalid packet:", p))
6066 raise
6067
6068 # from service VRF0 back to client VRF1
6069 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6070 IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
6071 TCP(sport=local_port, dport=12346))
6072 self.pg0.add_stream(p)
6073 self.pg_enable_capture(self.pg_interfaces)
6074 self.pg_start()
6075 capture = self.pg6.get_capture(1)
6076 p = capture[0]
6077 try:
6078 ip = p[IP]
6079 tcp = p[TCP]
6080 self.assertEqual(ip.src, self.pg0.local_ip4)
6081 self.assertEqual(tcp.sport, external_port)
6082 self.assert_packet_checksums_valid(p)
6083 except:
6084 self.logger.error(ppp("Unexpected or invalid packet:", p))
6085 raise
6086
6087 # from client VRF0 to service VRF1
6088 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6089 IP(src=self.pg0.remote_ip4, dst=external_addr) /
6090 TCP(sport=12347, dport=external_port))
6091 self.pg0.add_stream(p)
6092 self.pg_enable_capture(self.pg_interfaces)
6093 self.pg_start()
6094 capture = self.pg5.get_capture(1)
6095 p = capture[0]
6096 try:
6097 ip = p[IP]
6098 tcp = p[TCP]
6099 self.assertEqual(ip.dst, self.pg5.remote_ip4)
6100 self.assertEqual(tcp.dport, local_port)
6101 self.assert_packet_checksums_valid(p)
6102 except:
6103 self.logger.error(ppp("Unexpected or invalid packet:", p))
6104 raise
6105
6106 # from service VRF1 back to client VRF0
6107 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
6108 IP(src=self.pg5.remote_ip4, dst=self.pg0.remote_ip4) /
6109 TCP(sport=local_port, dport=12347))
6110 self.pg5.add_stream(p)
6111 self.pg_enable_capture(self.pg_interfaces)
6112 self.pg_start()
6113 capture = self.pg0.get_capture(1)
6114 p = capture[0]
6115 try:
6116 ip = p[IP]
6117 tcp = p[TCP]
6118 self.assertEqual(ip.src, external_addr)
6119 self.assertEqual(tcp.sport, external_port)
6120 self.assert_packet_checksums_valid(p)
6121 except:
6122 self.logger.error(ppp("Unexpected or invalid packet:", p))
6123 raise
6124
6125 # from client to server (both VRF1, no translation)
6126 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
6127 IP(src=self.pg6.remote_ip4, dst=self.pg5.remote_ip4) /
6128 TCP(sport=12348, dport=local_port))
6129 self.pg6.add_stream(p)
6130 self.pg_enable_capture(self.pg_interfaces)
6131 self.pg_start()
6132 capture = self.pg5.get_capture(1)
6133 p = capture[0]
6134 try:
6135 ip = p[IP]
6136 tcp = p[TCP]
6137 self.assertEqual(ip.dst, self.pg5.remote_ip4)
6138 self.assertEqual(tcp.dport, local_port)
6139 self.assert_packet_checksums_valid(p)
6140 except:
6141 self.logger.error(ppp("Unexpected or invalid packet:", p))
6142 raise
6143
6144 # from server back to client (both VRF1, no translation)
6145 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
6146 IP(src=self.pg5.remote_ip4, dst=self.pg6.remote_ip4) /
6147 TCP(sport=local_port, dport=12348))
6148 self.pg5.add_stream(p)
6149 self.pg_enable_capture(self.pg_interfaces)
6150 self.pg_start()
6151 capture = self.pg6.get_capture(1)
6152 p = capture[0]
6153 try:
6154 ip = p[IP]
6155 tcp = p[TCP]
6156 self.assertEqual(ip.src, self.pg5.remote_ip4)
6157 self.assertEqual(tcp.sport, local_port)
6158 self.assert_packet_checksums_valid(p)
6159 except:
6160 self.logger.error(ppp("Unexpected or invalid packet:", p))
6161 raise
6162
6163 # from client VRF1 to server VRF0 (no translation)
6164 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6165 IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
6166 TCP(sport=local_port, dport=12349))
6167 self.pg0.add_stream(p)
6168 self.pg_enable_capture(self.pg_interfaces)
6169 self.pg_start()
6170 capture = self.pg6.get_capture(1)
6171 p = capture[0]
6172 try:
6173 ip = p[IP]
6174 tcp = p[TCP]
6175 self.assertEqual(ip.src, self.pg0.remote_ip4)
6176 self.assertEqual(tcp.sport, local_port)
6177 self.assert_packet_checksums_valid(p)
6178 except:
6179 self.logger.error(ppp("Unexpected or invalid packet:", p))
6180 raise
6181
6182 # from server VRF0 back to client VRF1 (no translation)
6183 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6184 IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
6185 TCP(sport=local_port, dport=12349))
6186 self.pg0.add_stream(p)
6187 self.pg_enable_capture(self.pg_interfaces)
6188 self.pg_start()
6189 capture = self.pg6.get_capture(1)
6190 p = capture[0]
6191 try:
6192 ip = p[IP]
6193 tcp = p[TCP]
6194 self.assertEqual(ip.src, self.pg0.remote_ip4)
6195 self.assertEqual(tcp.sport, local_port)
6196 self.assert_packet_checksums_valid(p)
6197 except:
6198 self.logger.error(ppp("Unexpected or invalid packet:", p))
6199 raise
6200
6201 # from client VRF0 to server VRF1 (no translation)
6202 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6203 IP(src=self.pg0.remote_ip4, dst=self.pg5.remote_ip4) /
6204 TCP(sport=12344, dport=local_port))
6205 self.pg0.add_stream(p)
6206 self.pg_enable_capture(self.pg_interfaces)
6207 self.pg_start()
6208 capture = self.pg5.get_capture(1)
6209 p = capture[0]
6210 try:
6211 ip = p[IP]
6212 tcp = p[TCP]
6213 self.assertEqual(ip.dst, self.pg5.remote_ip4)
6214 self.assertEqual(tcp.dport, local_port)
6215 self.assert_packet_checksums_valid(p)
6216 except:
6217 self.logger.error(ppp("Unexpected or invalid packet:", p))
6218 raise
6219
6220 # from server VRF1 back to client VRF0 (no translation)
6221 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
6222 IP(src=self.pg5.remote_ip4, dst=self.pg0.remote_ip4) /
6223 TCP(sport=local_port, dport=12344))
6224 self.pg5.add_stream(p)
6225 self.pg_enable_capture(self.pg_interfaces)
6226 self.pg_start()
6227 capture = self.pg0.get_capture(1)
6228 p = capture[0]
6229 try:
6230 ip = p[IP]
6231 tcp = p[TCP]
6232 self.assertEqual(ip.src, self.pg5.remote_ip4)
6233 self.assertEqual(tcp.sport, local_port)
6234 self.assert_packet_checksums_valid(p)
6235 except:
6236 self.logger.error(ppp("Unexpected or invalid packet:", p))
6237 raise
6238
Paul Vinciguerradefde0f2018-12-06 07:46:13 -08006239 @unittest.skipUnless(running_extended_tests, "part of extended tests")
Matus Fabian878c6462018-08-23 00:33:35 -07006240 def test_session_timeout(self):
6241 """ NAT44 session timeouts """
6242 self.nat44_add_address(self.nat_addr)
6243 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
6244 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
6245 is_inside=0)
6246 self.vapi.nat_set_timeouts(icmp=5)
6247
6248 max_sessions = 1000
6249 pkts = []
6250 for i in range(0, max_sessions):
6251 src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
6252 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6253 IP(src=src, dst=self.pg1.remote_ip4) /
6254 ICMP(id=1025, type='echo-request'))
6255 pkts.append(p)
6256 self.pg0.add_stream(pkts)
6257 self.pg_enable_capture(self.pg_interfaces)
6258 self.pg_start()
6259 self.pg1.get_capture(max_sessions)
6260
6261 sleep(10)
6262
6263 pkts = []
6264 for i in range(0, max_sessions):
Matus Fabian7f8a8db2018-11-22 00:12:15 -08006265 src = "10.11.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
Matus Fabian878c6462018-08-23 00:33:35 -07006266 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6267 IP(src=src, dst=self.pg1.remote_ip4) /
6268 ICMP(id=1026, type='echo-request'))
6269 pkts.append(p)
6270 self.pg0.add_stream(pkts)
6271 self.pg_enable_capture(self.pg_interfaces)
6272 self.pg_start()
6273 self.pg1.get_capture(max_sessions)
6274
6275 nsessions = 0
6276 users = self.vapi.nat44_user_dump()
6277 for user in users:
6278 nsessions = nsessions + user.nsessions
6279 self.assertLess(nsessions, 2 * max_sessions)
6280
Paul Vinciguerradefde0f2018-12-06 07:46:13 -08006281 @unittest.skipUnless(running_extended_tests, "part of extended tests")
Matus Fabian15e8e682018-11-21 04:53:10 -08006282 def test_session_rst_timeout(self):
6283 """ NAT44 session RST timeouts """
6284 self.nat44_add_address(self.nat_addr)
6285 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
6286 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
6287 is_inside=0)
6288 self.vapi.nat_set_timeouts(tcp_transitory=5)
6289
Matus Fabian15e8e682018-11-21 04:53:10 -08006290 self.initiate_tcp_session(self.pg0, self.pg1)
6291 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6292 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6293 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6294 flags="R"))
6295 self.pg0.add_stream(p)
6296 self.pg_enable_capture(self.pg_interfaces)
6297 self.pg_start()
6298 self.pg1.get_capture(1)
6299
Matus Fabian15e8e682018-11-21 04:53:10 -08006300 sleep(6)
6301
6302 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6303 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6304 TCP(sport=self.tcp_port_in + 1, dport=self.tcp_external_port + 1,
6305 flags="S"))
6306 self.pg0.add_stream(p)
6307 self.pg_enable_capture(self.pg_interfaces)
6308 self.pg_start()
6309 self.pg1.get_capture(1)
6310
6311 nsessions = 0
6312 users = self.vapi.nat44_user_dump()
6313 self.assertEqual(len(users), 1)
6314 self.assertEqual(users[0].ip_address, self.pg0.remote_ip4n)
Matus Fabian7f8a8db2018-11-22 00:12:15 -08006315 self.assertEqual(users[0].nsessions, 1)
Matus Fabian15e8e682018-11-21 04:53:10 -08006316
Paul Vinciguerradefde0f2018-12-06 07:46:13 -08006317 @unittest.skipUnless(running_extended_tests, "part of extended tests")
Matus Fabian878c6462018-08-23 00:33:35 -07006318 def test_session_limit_per_user(self):
6319 """ Maximum sessions per user limit """
6320 self.nat44_add_address(self.nat_addr)
6321 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
6322 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
6323 is_inside=0)
6324 self.vapi.set_ipfix_exporter(collector_address=self.pg2.remote_ip4n,
6325 src_address=self.pg2.local_ip4n,
6326 path_mtu=512,
6327 template_interval=10)
Matus Fabian8fdc0152018-09-24 04:41:28 -07006328 self.vapi.nat_set_timeouts(udp=5)
Matus Fabian878c6462018-08-23 00:33:35 -07006329
6330 # get maximum number of translations per user
6331 nat44_config = self.vapi.nat_show_config()
6332
6333 pkts = []
6334 for port in range(0, nat44_config.max_translations_per_user):
6335 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6336 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6337 UDP(sport=1025 + port, dport=1025 + port))
6338 pkts.append(p)
6339
6340 self.pg0.add_stream(pkts)
6341 self.pg_enable_capture(self.pg_interfaces)
6342 self.pg_start()
6343 capture = self.pg1.get_capture(len(pkts))
6344
Ole Troane1ade682019-03-04 23:55:43 +01006345 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
6346 src_port=self.ipfix_src_port)
Matus Fabian878c6462018-08-23 00:33:35 -07006347
6348 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6349 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6350 UDP(sport=3001, dport=3002))
6351 self.pg0.add_stream(p)
6352 self.pg_enable_capture(self.pg_interfaces)
6353 self.pg_start()
6354 capture = self.pg1.assert_nothing_captured()
6355
6356 # verify IPFIX logging
6357 self.vapi.cli("ipfix flush") # FIXME this should be an API call
6358 sleep(1)
6359 capture = self.pg2.get_capture(10)
6360 ipfix = IPFIXDecoder()
6361 # first load template
6362 for p in capture:
6363 self.assertTrue(p.haslayer(IPFIX))
6364 if p.haslayer(Template):
6365 ipfix.add_template(p.getlayer(Template))
6366 # verify events in data set
6367 for p in capture:
6368 if p.haslayer(Data):
6369 data = ipfix.decode_data_set(p.getlayer(Set))
6370 self.verify_ipfix_max_entries_per_user(
6371 data,
6372 nat44_config.max_translations_per_user,
6373 self.pg0.remote_ip4n)
6374
Matus Fabian8fdc0152018-09-24 04:41:28 -07006375 sleep(6)
6376 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6377 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6378 UDP(sport=3001, dport=3002))
6379 self.pg0.add_stream(p)
6380 self.pg_enable_capture(self.pg_interfaces)
6381 self.pg_start()
6382 self.pg1.get_capture(1)
6383
Matus Fabianad1f3e12018-11-28 21:26:34 -08006384 def test_syslog_sess(self):
6385 """ Test syslog session creation and deletion """
6386 self.vapi.syslog_set_filter(SYSLOG_SEVERITY.INFO)
Ole Troanf159f582019-02-28 20:20:47 +01006387 self.vapi.syslog_set_sender(self.pg2.local_ip4n, self.pg2.remote_ip4n)
Matus Fabianad1f3e12018-11-28 21:26:34 -08006388 self.nat44_add_address(self.nat_addr)
6389 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
6390 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
6391 is_inside=0)
6392
6393 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6394 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6395 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port))
6396 self.pg0.add_stream(p)
6397 self.pg_enable_capture(self.pg_interfaces)
6398 self.pg_start()
6399 capture = self.pg1.get_capture(1)
6400 self.tcp_port_out = capture[0][TCP].sport
6401 capture = self.pg2.get_capture(1)
6402 self.verify_syslog_sess(capture[0][Raw].load)
6403
6404 self.pg_enable_capture(self.pg_interfaces)
6405 self.pg_start()
6406 self.nat44_add_address(self.nat_addr, is_add=0)
6407 capture = self.pg2.get_capture(1)
6408 self.verify_syslog_sess(capture[0][Raw].load, False)
6409
Matus Fabiande886752016-12-07 03:38:19 -08006410 def tearDown(self):
Matus Fabiana6110b62018-06-13 05:39:07 -07006411 super(TestNAT44EndpointDependent, self).tearDown()
Matus Fabiande886752016-12-07 03:38:19 -08006412 if not self.vpp_dead:
Matus Fabian82119542018-01-25 01:13:22 -08006413 self.logger.info(self.vapi.cli("show nat44 addresses"))
6414 self.logger.info(self.vapi.cli("show nat44 interfaces"))
6415 self.logger.info(self.vapi.cli("show nat44 static mappings"))
6416 self.logger.info(self.vapi.cli("show nat44 interface address"))
6417 self.logger.info(self.vapi.cli("show nat44 sessions detail"))
Matus Fabian229c1aa2018-05-28 04:09:52 -07006418 self.logger.info(self.vapi.cli("show nat44 hash tables detail"))
Matus Fabian878c6462018-08-23 00:33:35 -07006419 self.logger.info(self.vapi.cli("show nat timeouts"))
Matus Fabian2ba92e32017-08-21 07:05:03 -07006420 self.clear_nat44()
Matus Fabian229c1aa2018-05-28 04:09:52 -07006421 self.vapi.cli("clear logging")
Matus Fabiande886752016-12-07 03:38:19 -08006422
Matus Fabianeea28d72017-01-13 04:15:54 -08006423
Juraj Slobodacba69362017-12-19 02:09:32 +01006424class TestNAT44Out2InDPO(MethodHolder):
6425 """ NAT44 Test Cases using out2in DPO """
6426
6427 @classmethod
6428 def setUpConstants(cls):
6429 super(TestNAT44Out2InDPO, cls).setUpConstants()
6430 cls.vpp_cmdline.extend(["nat", "{", "out2in dpo", "}"])
6431
6432 @classmethod
6433 def setUpClass(cls):
6434 super(TestNAT44Out2InDPO, cls).setUpClass()
Matus Fabian229c1aa2018-05-28 04:09:52 -07006435 cls.vapi.cli("set log class nat level debug")
Juraj Slobodacba69362017-12-19 02:09:32 +01006436
6437 try:
6438 cls.tcp_port_in = 6303
6439 cls.tcp_port_out = 6303
6440 cls.udp_port_in = 6304
6441 cls.udp_port_out = 6304
6442 cls.icmp_id_in = 6305
6443 cls.icmp_id_out = 6305
6444 cls.nat_addr = '10.0.0.3'
6445 cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
6446 cls.dst_ip4 = '192.168.70.1'
6447
6448 cls.create_pg_interfaces(range(2))
6449
6450 cls.pg0.admin_up()
6451 cls.pg0.config_ip4()
6452 cls.pg0.resolve_arp()
6453
6454 cls.pg1.admin_up()
6455 cls.pg1.config_ip6()
6456 cls.pg1.resolve_ndp()
6457
Ole Troana5b2eec2019-03-11 19:23:25 +01006458 cls.vapi.ip_add_del_route(dst_address=b'\x00' * 16,
Juraj Slobodacba69362017-12-19 02:09:32 +01006459 dst_address_length=0,
6460 next_hop_address=cls.pg1.remote_ip6n,
Ole Troana5b2eec2019-03-11 19:23:25 +01006461 next_hop_sw_if_index=cls.pg1.sw_if_index,
6462 is_ipv6=True)
Juraj Slobodacba69362017-12-19 02:09:32 +01006463
6464 except Exception:
6465 super(TestNAT44Out2InDPO, cls).tearDownClass()
6466 raise
6467
6468 def configure_xlat(self):
6469 self.dst_ip6_pfx = '1:2:3::'
6470 self.dst_ip6_pfx_n = socket.inet_pton(socket.AF_INET6,
6471 self.dst_ip6_pfx)
6472 self.dst_ip6_pfx_len = 96
6473 self.src_ip6_pfx = '4:5:6::'
6474 self.src_ip6_pfx_n = socket.inet_pton(socket.AF_INET6,
6475 self.src_ip6_pfx)
6476 self.src_ip6_pfx_len = 96
6477 self.vapi.map_add_domain(self.dst_ip6_pfx_n, self.dst_ip6_pfx_len,
6478 self.src_ip6_pfx_n, self.src_ip6_pfx_len,
Jon Loeligerfc7344f2018-12-20 11:47:30 -06006479 '\x00\x00\x00\x00', 0)
Juraj Slobodacba69362017-12-19 02:09:32 +01006480
Ole Troanffba3c32018-11-22 12:53:00 +01006481 @unittest.skip('Temporary disabled')
Juraj Slobodacba69362017-12-19 02:09:32 +01006482 def test_464xlat_ce(self):
6483 """ Test 464XLAT CE with NAT44 """
6484
Matus Fabian69ce30d2018-08-22 01:27:10 -07006485 nat_config = self.vapi.nat_show_config()
6486 self.assertEqual(1, nat_config.out2in_dpo)
6487
Juraj Slobodacba69362017-12-19 02:09:32 +01006488 self.configure_xlat()
6489
6490 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
6491 self.vapi.nat44_add_del_address_range(self.nat_addr_n, self.nat_addr_n)
6492
6493 out_src_ip6 = self.compose_ip6(self.dst_ip4, self.dst_ip6_pfx,
6494 self.dst_ip6_pfx_len)
6495 out_dst_ip6 = self.compose_ip6(self.nat_addr, self.src_ip6_pfx,
6496 self.src_ip6_pfx_len)
6497
6498 try:
6499 pkts = self.create_stream_in(self.pg0, self.pg1, self.dst_ip4)
6500 self.pg0.add_stream(pkts)
6501 self.pg_enable_capture(self.pg_interfaces)
6502 self.pg_start()
6503 capture = self.pg1.get_capture(len(pkts))
6504 self.verify_capture_out_ip6(capture, nat_ip=out_dst_ip6,
6505 dst_ip=out_src_ip6)
6506
6507 pkts = self.create_stream_out_ip6(self.pg1, out_src_ip6,
6508 out_dst_ip6)
6509 self.pg1.add_stream(pkts)
6510 self.pg_enable_capture(self.pg_interfaces)
6511 self.pg_start()
6512 capture = self.pg0.get_capture(len(pkts))
6513 self.verify_capture_in(capture, self.pg0)
6514 finally:
6515 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
6516 is_add=0)
6517 self.vapi.nat44_add_del_address_range(self.nat_addr_n,
6518 self.nat_addr_n, is_add=0)
6519
Ole Troanffba3c32018-11-22 12:53:00 +01006520 @unittest.skip('Temporary disabled')
Juraj Slobodacba69362017-12-19 02:09:32 +01006521 def test_464xlat_ce_no_nat(self):
6522 """ Test 464XLAT CE without NAT44 """
6523
6524 self.configure_xlat()
6525
6526 out_src_ip6 = self.compose_ip6(self.dst_ip4, self.dst_ip6_pfx,
6527 self.dst_ip6_pfx_len)
6528 out_dst_ip6 = self.compose_ip6(self.pg0.remote_ip4, self.src_ip6_pfx,
6529 self.src_ip6_pfx_len)
6530
6531 pkts = self.create_stream_in(self.pg0, self.pg1, self.dst_ip4)
6532 self.pg0.add_stream(pkts)
6533 self.pg_enable_capture(self.pg_interfaces)
6534 self.pg_start()
6535 capture = self.pg1.get_capture(len(pkts))
6536 self.verify_capture_out_ip6(capture, dst_ip=out_src_ip6,
6537 nat_ip=out_dst_ip6, same_port=True)
6538
6539 pkts = self.create_stream_out_ip6(self.pg1, out_src_ip6, out_dst_ip6)
6540 self.pg1.add_stream(pkts)
6541 self.pg_enable_capture(self.pg_interfaces)
6542 self.pg_start()
6543 capture = self.pg0.get_capture(len(pkts))
6544 self.verify_capture_in(capture, self.pg0)
6545
6546
Martin Gálikd7f75cd2017-03-27 06:02:47 -07006547class TestDeterministicNAT(MethodHolder):
Matus Fabian066f0342017-02-10 03:48:01 -08006548 """ Deterministic NAT Test Cases """
6549
6550 @classmethod
6551 def setUpConstants(cls):
6552 super(TestDeterministicNAT, cls).setUpConstants()
Matus Fabian2ba92e32017-08-21 07:05:03 -07006553 cls.vpp_cmdline.extend(["nat", "{", "deterministic", "}"])
Matus Fabian066f0342017-02-10 03:48:01 -08006554
6555 @classmethod
6556 def setUpClass(cls):
6557 super(TestDeterministicNAT, cls).setUpClass()
Matus Fabian229c1aa2018-05-28 04:09:52 -07006558 cls.vapi.cli("set log class nat level debug")
Matus Fabian066f0342017-02-10 03:48:01 -08006559
6560 try:
Martin Gálik977c1cb2017-03-30 23:21:51 -07006561 cls.tcp_port_in = 6303
Martin Gálik9806eae2017-04-25 01:25:08 -07006562 cls.tcp_external_port = 6303
Martin Gálik977c1cb2017-03-30 23:21:51 -07006563 cls.udp_port_in = 6304
Martin Gálik9806eae2017-04-25 01:25:08 -07006564 cls.udp_external_port = 6304
Martin Gálik977c1cb2017-03-30 23:21:51 -07006565 cls.icmp_id_in = 6305
Matus Fabian2ba92e32017-08-21 07:05:03 -07006566 cls.nat_addr = '10.0.0.3'
Martin Gálik977c1cb2017-03-30 23:21:51 -07006567
Matus Fabian2f2db1c2017-04-18 05:29:59 -07006568 cls.create_pg_interfaces(range(3))
Matus Fabian066f0342017-02-10 03:48:01 -08006569 cls.interfaces = list(cls.pg_interfaces)
6570
6571 for i in cls.interfaces:
6572 i.admin_up()
6573 i.config_ip4()
6574 i.resolve_arp()
6575
Martin Gálik977c1cb2017-03-30 23:21:51 -07006576 cls.pg0.generate_remote_hosts(2)
6577 cls.pg0.configure_ipv4_neighbors()
6578
Matus Fabian066f0342017-02-10 03:48:01 -08006579 except Exception:
6580 super(TestDeterministicNAT, cls).tearDownClass()
6581 raise
6582
Martin Gálik977c1cb2017-03-30 23:21:51 -07006583 def create_stream_in(self, in_if, out_if, ttl=64):
6584 """
6585 Create packet stream for inside network
6586
6587 :param in_if: Inside interface
6588 :param out_if: Outside interface
6589 :param ttl: TTL of generated packets
6590 """
6591 pkts = []
6592 # TCP
6593 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
6594 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006595 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07006596 pkts.append(p)
6597
6598 # UDP
6599 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
6600 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006601 UDP(sport=self.udp_port_in, dport=self.udp_external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07006602 pkts.append(p)
6603
6604 # ICMP
6605 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
6606 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
6607 ICMP(id=self.icmp_id_in, type='echo-request'))
6608 pkts.append(p)
6609
6610 return pkts
6611
6612 def create_stream_out(self, out_if, dst_ip=None, ttl=64):
6613 """
6614 Create packet stream for outside network
6615
6616 :param out_if: Outside interface
Matus Fabian2ba92e32017-08-21 07:05:03 -07006617 :param dst_ip: Destination IP address (Default use global NAT address)
Martin Gálik977c1cb2017-03-30 23:21:51 -07006618 :param ttl: TTL of generated packets
6619 """
6620 if dst_ip is None:
Matus Fabian2ba92e32017-08-21 07:05:03 -07006621 dst_ip = self.nat_addr
Martin Gálik977c1cb2017-03-30 23:21:51 -07006622 pkts = []
6623 # TCP
6624 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
6625 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006626 TCP(dport=self.tcp_port_out, sport=self.tcp_external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07006627 pkts.append(p)
6628
6629 # UDP
6630 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
6631 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006632 UDP(dport=self.udp_port_out, sport=self.udp_external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07006633 pkts.append(p)
6634
6635 # ICMP
6636 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
6637 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
6638 ICMP(id=self.icmp_external_id, type='echo-reply'))
6639 pkts.append(p)
6640
6641 return pkts
6642
Matus Fabian05ca4a32018-09-04 23:45:13 -07006643 def verify_capture_out(self, capture, nat_ip=None):
Martin Gálik977c1cb2017-03-30 23:21:51 -07006644 """
6645 Verify captured packets on outside network
6646
6647 :param capture: Captured packets
Matus Fabian2ba92e32017-08-21 07:05:03 -07006648 :param nat_ip: Translated IP address (Default use global NAT address)
Martin Gálik977c1cb2017-03-30 23:21:51 -07006649 :param same_port: Sorce port number is not translated (Default False)
Martin Gálik977c1cb2017-03-30 23:21:51 -07006650 """
6651 if nat_ip is None:
Matus Fabian2ba92e32017-08-21 07:05:03 -07006652 nat_ip = self.nat_addr
Martin Gálik977c1cb2017-03-30 23:21:51 -07006653 for packet in capture:
6654 try:
6655 self.assertEqual(packet[IP].src, nat_ip)
6656 if packet.haslayer(TCP):
Martin Gálik9806eae2017-04-25 01:25:08 -07006657 self.tcp_port_out = packet[TCP].sport
Martin Gálik977c1cb2017-03-30 23:21:51 -07006658 elif packet.haslayer(UDP):
Martin Gálik9806eae2017-04-25 01:25:08 -07006659 self.udp_port_out = packet[UDP].sport
Martin Gálik977c1cb2017-03-30 23:21:51 -07006660 else:
6661 self.icmp_external_id = packet[ICMP].id
6662 except:
6663 self.logger.error(ppp("Unexpected or invalid packet "
6664 "(outside network):", packet))
6665 raise
6666
Matus Fabian066f0342017-02-10 03:48:01 -08006667 def test_deterministic_mode(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07006668 """ NAT plugin run deterministic mode """
Matus Fabian066f0342017-02-10 03:48:01 -08006669 in_addr = '172.16.255.0'
6670 out_addr = '172.17.255.50'
6671 in_addr_t = '172.16.255.20'
6672 in_addr_n = socket.inet_aton(in_addr)
6673 out_addr_n = socket.inet_aton(out_addr)
6674 in_addr_t_n = socket.inet_aton(in_addr_t)
6675 in_plen = 24
6676 out_plen = 32
6677
Matus Fabian2ba92e32017-08-21 07:05:03 -07006678 nat_config = self.vapi.nat_show_config()
6679 self.assertEqual(1, nat_config.deterministic)
Matus Fabian066f0342017-02-10 03:48:01 -08006680
Matus Fabian2ba92e32017-08-21 07:05:03 -07006681 self.vapi.nat_det_add_del_map(in_addr_n, in_plen, out_addr_n, out_plen)
Matus Fabian066f0342017-02-10 03:48:01 -08006682
Matus Fabian2ba92e32017-08-21 07:05:03 -07006683 rep1 = self.vapi.nat_det_forward(in_addr_t_n)
Matus Fabian066f0342017-02-10 03:48:01 -08006684 self.assertEqual(rep1.out_addr[:4], out_addr_n)
Matus Fabian2ba92e32017-08-21 07:05:03 -07006685 rep2 = self.vapi.nat_det_reverse(out_addr_n, rep1.out_port_hi)
Matus Fabian066f0342017-02-10 03:48:01 -08006686 self.assertEqual(rep2.in_addr[:4], in_addr_t_n)
6687
Matus Fabian2ba92e32017-08-21 07:05:03 -07006688 deterministic_mappings = self.vapi.nat_det_map_dump()
Martin17a75cb2017-03-08 05:53:20 -08006689 self.assertEqual(len(deterministic_mappings), 1)
6690 dsm = deterministic_mappings[0]
6691 self.assertEqual(in_addr_n, dsm.in_addr[:4])
6692 self.assertEqual(in_plen, dsm.in_plen)
6693 self.assertEqual(out_addr_n, dsm.out_addr[:4])
6694 self.assertEqual(out_plen, dsm.out_plen)
6695
Matus Fabian2ba92e32017-08-21 07:05:03 -07006696 self.clear_nat_det()
6697 deterministic_mappings = self.vapi.nat_det_map_dump()
Martinb616e9f2017-03-14 02:25:45 -07006698 self.assertEqual(len(deterministic_mappings), 0)
6699
Matus Fabian6a0946f2017-04-12 03:36:13 -07006700 def test_set_timeouts(self):
6701 """ Set deterministic NAT timeouts """
Matus Fabian878c6462018-08-23 00:33:35 -07006702 timeouts_before = self.vapi.nat_get_timeouts()
Matus Fabian6a0946f2017-04-12 03:36:13 -07006703
Matus Fabian878c6462018-08-23 00:33:35 -07006704 self.vapi.nat_set_timeouts(timeouts_before.udp + 10,
6705 timeouts_before.tcp_established + 10,
6706 timeouts_before.tcp_transitory + 10,
6707 timeouts_before.icmp + 10)
Matus Fabian6a0946f2017-04-12 03:36:13 -07006708
Matus Fabian878c6462018-08-23 00:33:35 -07006709 timeouts_after = self.vapi.nat_get_timeouts()
Matus Fabian6a0946f2017-04-12 03:36:13 -07006710
6711 self.assertNotEqual(timeouts_before.udp, timeouts_after.udp)
6712 self.assertNotEqual(timeouts_before.icmp, timeouts_after.icmp)
6713 self.assertNotEqual(timeouts_before.tcp_established,
6714 timeouts_after.tcp_established)
6715 self.assertNotEqual(timeouts_before.tcp_transitory,
6716 timeouts_after.tcp_transitory)
6717
Martin Gálik977c1cb2017-03-30 23:21:51 -07006718 def test_det_in(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07006719 """ Deterministic NAT translation test (TCP, UDP, ICMP) """
Martin Gálik977c1cb2017-03-30 23:21:51 -07006720
6721 nat_ip = "10.0.0.10"
Martin Gálik977c1cb2017-03-30 23:21:51 -07006722
Matus Fabian2ba92e32017-08-21 07:05:03 -07006723 self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
6724 32,
6725 socket.inet_aton(nat_ip),
6726 32)
6727 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
6728 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
6729 is_inside=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07006730
6731 # in2out
6732 pkts = self.create_stream_in(self.pg0, self.pg1)
6733 self.pg0.add_stream(pkts)
6734 self.pg_enable_capture(self.pg_interfaces)
6735 self.pg_start()
6736 capture = self.pg1.get_capture(len(pkts))
6737 self.verify_capture_out(capture, nat_ip)
6738
6739 # out2in
6740 pkts = self.create_stream_out(self.pg1, nat_ip)
6741 self.pg1.add_stream(pkts)
6742 self.pg_enable_capture(self.pg_interfaces)
6743 self.pg_start()
6744 capture = self.pg0.get_capture(len(pkts))
6745 self.verify_capture_in(capture, self.pg0)
6746
Martin Gálik9806eae2017-04-25 01:25:08 -07006747 # session dump test
Matus Fabian2ba92e32017-08-21 07:05:03 -07006748 sessions = self.vapi.nat_det_session_dump(self.pg0.remote_ip4n)
Martin Gálik9806eae2017-04-25 01:25:08 -07006749 self.assertEqual(len(sessions), 3)
6750
6751 # TCP session
6752 s = sessions[0]
6753 self.assertEqual(s.ext_addr[:4], self.pg1.remote_ip4n)
6754 self.assertEqual(s.in_port, self.tcp_port_in)
6755 self.assertEqual(s.out_port, self.tcp_port_out)
6756 self.assertEqual(s.ext_port, self.tcp_external_port)
6757
6758 # UDP session
6759 s = sessions[1]
6760 self.assertEqual(s.ext_addr[:4], self.pg1.remote_ip4n)
6761 self.assertEqual(s.in_port, self.udp_port_in)
6762 self.assertEqual(s.out_port, self.udp_port_out)
6763 self.assertEqual(s.ext_port, self.udp_external_port)
6764
6765 # ICMP session
6766 s = sessions[2]
6767 self.assertEqual(s.ext_addr[:4], self.pg1.remote_ip4n)
6768 self.assertEqual(s.in_port, self.icmp_id_in)
6769 self.assertEqual(s.out_port, self.icmp_external_id)
6770
Martin Gálik977c1cb2017-03-30 23:21:51 -07006771 def test_multiple_users(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07006772 """ Deterministic NAT multiple users """
Martin Gálik977c1cb2017-03-30 23:21:51 -07006773
6774 nat_ip = "10.0.0.10"
6775 port_in = 80
Martin Gálik9806eae2017-04-25 01:25:08 -07006776 external_port = 6303
Martin Gálik977c1cb2017-03-30 23:21:51 -07006777
6778 host0 = self.pg0.remote_hosts[0]
6779 host1 = self.pg0.remote_hosts[1]
6780
Matus Fabian2ba92e32017-08-21 07:05:03 -07006781 self.vapi.nat_det_add_del_map(host0.ip4n,
6782 24,
6783 socket.inet_aton(nat_ip),
6784 32)
6785 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
6786 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
6787 is_inside=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07006788
6789 # host0 to out
6790 p = (Ether(src=host0.mac, dst=self.pg0.local_mac) /
6791 IP(src=host0.ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006792 TCP(sport=port_in, dport=external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07006793 self.pg0.add_stream(p)
6794 self.pg_enable_capture(self.pg_interfaces)
6795 self.pg_start()
6796 capture = self.pg1.get_capture(1)
6797 p = capture[0]
6798 try:
6799 ip = p[IP]
6800 tcp = p[TCP]
6801 self.assertEqual(ip.src, nat_ip)
6802 self.assertEqual(ip.dst, self.pg1.remote_ip4)
Martin Gálik9806eae2017-04-25 01:25:08 -07006803 self.assertEqual(tcp.dport, external_port)
6804 port_out0 = tcp.sport
Martin Gálik977c1cb2017-03-30 23:21:51 -07006805 except:
6806 self.logger.error(ppp("Unexpected or invalid packet:", p))
6807 raise
6808
6809 # host1 to out
6810 p = (Ether(src=host1.mac, dst=self.pg0.local_mac) /
6811 IP(src=host1.ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006812 TCP(sport=port_in, dport=external_port))
Martin Gálik977c1cb2017-03-30 23:21:51 -07006813 self.pg0.add_stream(p)
6814 self.pg_enable_capture(self.pg_interfaces)
6815 self.pg_start()
6816 capture = self.pg1.get_capture(1)
6817 p = capture[0]
6818 try:
6819 ip = p[IP]
6820 tcp = p[TCP]
6821 self.assertEqual(ip.src, nat_ip)
6822 self.assertEqual(ip.dst, self.pg1.remote_ip4)
Martin Gálik9806eae2017-04-25 01:25:08 -07006823 self.assertEqual(tcp.dport, external_port)
6824 port_out1 = tcp.sport
Martin Gálik977c1cb2017-03-30 23:21:51 -07006825 except:
6826 self.logger.error(ppp("Unexpected or invalid packet:", p))
6827 raise
6828
Matus Fabian2ba92e32017-08-21 07:05:03 -07006829 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07006830 self.assertEqual(1, len(dms))
6831 self.assertEqual(2, dms[0].ses_num)
6832
6833 # out to host0
6834 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6835 IP(src=self.pg1.remote_ip4, dst=nat_ip) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006836 TCP(sport=external_port, dport=port_out0))
Martin Gálik977c1cb2017-03-30 23:21:51 -07006837 self.pg1.add_stream(p)
6838 self.pg_enable_capture(self.pg_interfaces)
6839 self.pg_start()
6840 capture = self.pg0.get_capture(1)
6841 p = capture[0]
6842 try:
6843 ip = p[IP]
6844 tcp = p[TCP]
6845 self.assertEqual(ip.src, self.pg1.remote_ip4)
6846 self.assertEqual(ip.dst, host0.ip4)
6847 self.assertEqual(tcp.dport, port_in)
Martin Gálik9806eae2017-04-25 01:25:08 -07006848 self.assertEqual(tcp.sport, external_port)
Martin Gálik977c1cb2017-03-30 23:21:51 -07006849 except:
6850 self.logger.error(ppp("Unexpected or invalid packet:", p))
6851 raise
6852
6853 # out to host1
6854 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6855 IP(src=self.pg1.remote_ip4, dst=nat_ip) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006856 TCP(sport=external_port, dport=port_out1))
Martin Gálik977c1cb2017-03-30 23:21:51 -07006857 self.pg1.add_stream(p)
6858 self.pg_enable_capture(self.pg_interfaces)
6859 self.pg_start()
6860 capture = self.pg0.get_capture(1)
6861 p = capture[0]
6862 try:
6863 ip = p[IP]
6864 tcp = p[TCP]
6865 self.assertEqual(ip.src, self.pg1.remote_ip4)
6866 self.assertEqual(ip.dst, host1.ip4)
6867 self.assertEqual(tcp.dport, port_in)
Martin Gálik9806eae2017-04-25 01:25:08 -07006868 self.assertEqual(tcp.sport, external_port)
Martin Gálik977c1cb2017-03-30 23:21:51 -07006869 except:
6870 self.logger.error(ppp("Unexpected or invalid packet", p))
6871 raise
6872
Martin Gálik6bc8c642017-04-19 01:12:27 -07006873 # session close api test
Matus Fabian2ba92e32017-08-21 07:05:03 -07006874 self.vapi.nat_det_close_session_out(socket.inet_aton(nat_ip),
6875 port_out1,
Martin Gálik6bc8c642017-04-19 01:12:27 -07006876 self.pg1.remote_ip4n,
Martin Gálik9806eae2017-04-25 01:25:08 -07006877 external_port)
Matus Fabian2ba92e32017-08-21 07:05:03 -07006878 dms = self.vapi.nat_det_map_dump()
6879 self.assertEqual(dms[0].ses_num, 1)
6880
6881 self.vapi.nat_det_close_session_in(host0.ip4n,
6882 port_in,
6883 self.pg1.remote_ip4n,
6884 external_port)
6885 dms = self.vapi.nat_det_map_dump()
Martin Gálik6bc8c642017-04-19 01:12:27 -07006886 self.assertEqual(dms[0].ses_num, 0)
6887
Martin Gálik977c1cb2017-03-30 23:21:51 -07006888 def test_tcp_session_close_detection_in(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07006889 """ Deterministic NAT TCP session close from inside network """
6890 self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
6891 32,
6892 socket.inet_aton(self.nat_addr),
6893 32)
6894 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
6895 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
6896 is_inside=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07006897
6898 self.initiate_tcp_session(self.pg0, self.pg1)
6899
6900 # close the session from inside
6901 try:
6902 # FIN packet in -> out
6903 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6904 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006905 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
Martin Gálik977c1cb2017-03-30 23:21:51 -07006906 flags="F"))
6907 self.pg0.add_stream(p)
6908 self.pg_enable_capture(self.pg_interfaces)
6909 self.pg_start()
6910 self.pg1.get_capture(1)
6911
6912 pkts = []
6913
6914 # ACK packet out -> in
6915 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07006916 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006917 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
Martin Gálik977c1cb2017-03-30 23:21:51 -07006918 flags="A"))
6919 pkts.append(p)
6920
6921 # FIN packet out -> in
6922 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07006923 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006924 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
Martin Gálik977c1cb2017-03-30 23:21:51 -07006925 flags="F"))
6926 pkts.append(p)
6927
6928 self.pg1.add_stream(pkts)
6929 self.pg_enable_capture(self.pg_interfaces)
6930 self.pg_start()
6931 self.pg0.get_capture(2)
6932
6933 # ACK packet in -> out
6934 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6935 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006936 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
Martin Gálik977c1cb2017-03-30 23:21:51 -07006937 flags="A"))
6938 self.pg0.add_stream(p)
6939 self.pg_enable_capture(self.pg_interfaces)
6940 self.pg_start()
6941 self.pg1.get_capture(1)
6942
Matus Fabian2ba92e32017-08-21 07:05:03 -07006943 # Check if deterministic NAT44 closed the session
6944 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07006945 self.assertEqual(0, dms[0].ses_num)
6946 except:
6947 self.logger.error("TCP session termination failed")
6948 raise
6949
6950 def test_tcp_session_close_detection_out(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07006951 """ Deterministic NAT TCP session close from outside network """
6952 self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
6953 32,
6954 socket.inet_aton(self.nat_addr),
6955 32)
6956 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
6957 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
6958 is_inside=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07006959
6960 self.initiate_tcp_session(self.pg0, self.pg1)
6961
6962 # close the session from outside
6963 try:
6964 # FIN packet out -> in
6965 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07006966 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006967 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
Martin Gálik977c1cb2017-03-30 23:21:51 -07006968 flags="F"))
6969 self.pg1.add_stream(p)
6970 self.pg_enable_capture(self.pg_interfaces)
6971 self.pg_start()
6972 self.pg0.get_capture(1)
6973
6974 pkts = []
6975
6976 # ACK packet in -> out
6977 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6978 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006979 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
Martin Gálik977c1cb2017-03-30 23:21:51 -07006980 flags="A"))
6981 pkts.append(p)
6982
6983 # ACK packet in -> out
6984 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6985 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006986 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
Martin Gálik977c1cb2017-03-30 23:21:51 -07006987 flags="F"))
6988 pkts.append(p)
6989
6990 self.pg0.add_stream(pkts)
6991 self.pg_enable_capture(self.pg_interfaces)
6992 self.pg_start()
6993 self.pg1.get_capture(2)
6994
6995 # ACK packet out -> in
6996 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
Matus Fabian2ba92e32017-08-21 07:05:03 -07006997 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
Martin Gálik9806eae2017-04-25 01:25:08 -07006998 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
Martin Gálik977c1cb2017-03-30 23:21:51 -07006999 flags="A"))
7000 self.pg1.add_stream(p)
7001 self.pg_enable_capture(self.pg_interfaces)
7002 self.pg_start()
7003 self.pg0.get_capture(1)
7004
Matus Fabian2ba92e32017-08-21 07:05:03 -07007005 # Check if deterministic NAT44 closed the session
7006 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07007007 self.assertEqual(0, dms[0].ses_num)
7008 except:
7009 self.logger.error("TCP session termination failed")
7010 raise
7011
Paul Vinciguerradefde0f2018-12-06 07:46:13 -08007012 @unittest.skipUnless(running_extended_tests, "part of extended tests")
Martin Gálik977c1cb2017-03-30 23:21:51 -07007013 def test_session_timeout(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07007014 """ Deterministic NAT session timeouts """
7015 self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
7016 32,
7017 socket.inet_aton(self.nat_addr),
7018 32)
7019 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
7020 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
7021 is_inside=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07007022
7023 self.initiate_tcp_session(self.pg0, self.pg1)
Matus Fabian878c6462018-08-23 00:33:35 -07007024 self.vapi.nat_set_timeouts(5, 5, 5, 5)
Martin Gálik977c1cb2017-03-30 23:21:51 -07007025 pkts = self.create_stream_in(self.pg0, self.pg1)
7026 self.pg0.add_stream(pkts)
7027 self.pg_enable_capture(self.pg_interfaces)
7028 self.pg_start()
7029 capture = self.pg1.get_capture(len(pkts))
7030 sleep(15)
7031
Matus Fabian2ba92e32017-08-21 07:05:03 -07007032 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07007033 self.assertEqual(0, dms[0].ses_num)
7034
Paul Vinciguerradefde0f2018-12-06 07:46:13 -08007035 @unittest.skipUnless(running_extended_tests, "part of extended tests")
Martin Gálik977c1cb2017-03-30 23:21:51 -07007036 def test_session_limit_per_user(self):
Matus Fabian2ba92e32017-08-21 07:05:03 -07007037 """ Deterministic NAT maximum sessions per user limit """
7038 self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
7039 32,
7040 socket.inet_aton(self.nat_addr),
7041 32)
7042 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
7043 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
7044 is_inside=0)
Matus Fabian2f2db1c2017-04-18 05:29:59 -07007045 self.vapi.set_ipfix_exporter(collector_address=self.pg2.remote_ip4n,
7046 src_address=self.pg2.local_ip4n,
7047 path_mtu=512,
7048 template_interval=10)
Ole Troane1ade682019-03-04 23:55:43 +01007049 self.vapi.nat_ipfix_enable_disable()
Martin Gálik977c1cb2017-03-30 23:21:51 -07007050
7051 pkts = []
7052 for port in range(1025, 2025):
7053 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7054 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
7055 UDP(sport=port, dport=port))
7056 pkts.append(p)
7057
7058 self.pg0.add_stream(pkts)
7059 self.pg_enable_capture(self.pg_interfaces)
7060 self.pg_start()
7061 capture = self.pg1.get_capture(len(pkts))
7062
7063 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7064 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
Martin Gálikf7e655d2017-04-27 02:13:26 -07007065 UDP(sport=3001, dport=3002))
Martin Gálik977c1cb2017-03-30 23:21:51 -07007066 self.pg0.add_stream(p)
7067 self.pg_enable_capture(self.pg_interfaces)
7068 self.pg_start()
7069 capture = self.pg1.assert_nothing_captured()
7070
Martin Gálikf7e655d2017-04-27 02:13:26 -07007071 # verify ICMP error packet
7072 capture = self.pg0.get_capture(1)
7073 p = capture[0]
7074 self.assertTrue(p.haslayer(ICMP))
7075 icmp = p[ICMP]
7076 self.assertEqual(icmp.type, 3)
7077 self.assertEqual(icmp.code, 1)
7078 self.assertTrue(icmp.haslayer(IPerror))
7079 inner_ip = icmp[IPerror]
7080 self.assertEqual(inner_ip[UDPerror].sport, 3001)
7081 self.assertEqual(inner_ip[UDPerror].dport, 3002)
7082
Matus Fabian2ba92e32017-08-21 07:05:03 -07007083 dms = self.vapi.nat_det_map_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07007084
7085 self.assertEqual(1000, dms[0].ses_num)
7086
Matus Fabian2f2db1c2017-04-18 05:29:59 -07007087 # verify IPFIX logging
7088 self.vapi.cli("ipfix flush") # FIXME this should be an API call
Matus Fabian7c0aecc2017-07-03 01:21:38 -07007089 sleep(1)
Matus Fabian2f2db1c2017-04-18 05:29:59 -07007090 capture = self.pg2.get_capture(2)
7091 ipfix = IPFIXDecoder()
7092 # first load template
7093 for p in capture:
7094 self.assertTrue(p.haslayer(IPFIX))
7095 if p.haslayer(Template):
7096 ipfix.add_template(p.getlayer(Template))
7097 # verify events in data set
7098 for p in capture:
7099 if p.haslayer(Data):
7100 data = ipfix.decode_data_set(p.getlayer(Set))
Matus Fabian878c6462018-08-23 00:33:35 -07007101 self.verify_ipfix_max_entries_per_user(data,
7102 1000,
7103 self.pg0.remote_ip4n)
Matus Fabian2f2db1c2017-04-18 05:29:59 -07007104
Matus Fabian2ba92e32017-08-21 07:05:03 -07007105 def clear_nat_det(self):
Martin17a75cb2017-03-08 05:53:20 -08007106 """
Matus Fabian2ba92e32017-08-21 07:05:03 -07007107 Clear deterministic NAT configuration.
Martin17a75cb2017-03-08 05:53:20 -08007108 """
Ole Troane1ade682019-03-04 23:55:43 +01007109 self.vapi.nat_ipfix_enable_disable(enable=0)
Matus Fabian878c6462018-08-23 00:33:35 -07007110 self.vapi.nat_set_timeouts()
Matus Fabian2ba92e32017-08-21 07:05:03 -07007111 deterministic_mappings = self.vapi.nat_det_map_dump()
Martin17a75cb2017-03-08 05:53:20 -08007112 for dsm in deterministic_mappings:
Matus Fabian2ba92e32017-08-21 07:05:03 -07007113 self.vapi.nat_det_add_del_map(dsm.in_addr,
7114 dsm.in_plen,
7115 dsm.out_addr,
7116 dsm.out_plen,
7117 is_add=0)
Martin17a75cb2017-03-08 05:53:20 -08007118
Matus Fabian2ba92e32017-08-21 07:05:03 -07007119 interfaces = self.vapi.nat44_interface_dump()
Martin Gálik977c1cb2017-03-30 23:21:51 -07007120 for intf in interfaces:
Matus Fabian2ba92e32017-08-21 07:05:03 -07007121 self.vapi.nat44_interface_add_del_feature(intf.sw_if_index,
7122 intf.is_inside,
7123 is_add=0)
Martin Gálik977c1cb2017-03-30 23:21:51 -07007124
Matus Fabian066f0342017-02-10 03:48:01 -08007125 def tearDown(self):
7126 super(TestDeterministicNAT, self).tearDown()
7127 if not self.vpp_dead:
Matus Fabian82119542018-01-25 01:13:22 -08007128 self.logger.info(self.vapi.cli("show nat44 interfaces"))
Matus Fabian878c6462018-08-23 00:33:35 -07007129 self.logger.info(self.vapi.cli("show nat timeouts"))
Matus Fabian82119542018-01-25 01:13:22 -08007130 self.logger.info(
7131 self.vapi.cli("show nat44 deterministic mappings"))
7132 self.logger.info(
Matus Fabian82119542018-01-25 01:13:22 -08007133 self.vapi.cli("show nat44 deterministic sessions"))
Matus Fabian2ba92e32017-08-21 07:05:03 -07007134 self.clear_nat_det()
Matus Fabian066f0342017-02-10 03:48:01 -08007135
Matus Fabian06596c52017-06-06 04:53:28 -07007136
7137class TestNAT64(MethodHolder):
7138 """ NAT64 Test Cases """
7139
7140 @classmethod
Matus Fabiana431ad12018-01-04 04:03:14 -08007141 def setUpConstants(cls):
7142 super(TestNAT64, cls).setUpConstants()
7143 cls.vpp_cmdline.extend(["nat", "{", "nat64 bib hash buckets 128",
7144 "nat64 st hash buckets 256", "}"])
7145
7146 @classmethod
Matus Fabian06596c52017-06-06 04:53:28 -07007147 def setUpClass(cls):
7148 super(TestNAT64, cls).setUpClass()
7149
7150 try:
7151 cls.tcp_port_in = 6303
7152 cls.tcp_port_out = 6303
7153 cls.udp_port_in = 6304
7154 cls.udp_port_out = 6304
7155 cls.icmp_id_in = 6305
7156 cls.icmp_id_out = 6305
Matus Fabianad1f3e12018-11-28 21:26:34 -08007157 cls.tcp_external_port = 80
Matus Fabian06596c52017-06-06 04:53:28 -07007158 cls.nat_addr = '10.0.0.3'
7159 cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
Matus Fabian029f3d22017-06-15 02:28:50 -07007160 cls.vrf1_id = 10
7161 cls.vrf1_nat_addr = '10.0.10.3'
7162 cls.vrf1_nat_addr_n = socket.inet_pton(socket.AF_INET,
7163 cls.vrf1_nat_addr)
Matus Fabiana431ad12018-01-04 04:03:14 -08007164 cls.ipfix_src_port = 4739
7165 cls.ipfix_domain_id = 1
Matus Fabian06596c52017-06-06 04:53:28 -07007166
Juraj Slobodac746a152018-07-09 02:36:37 +02007167 cls.create_pg_interfaces(range(6))
Matus Fabian06596c52017-06-06 04:53:28 -07007168 cls.ip6_interfaces = list(cls.pg_interfaces[0:1])
Matus Fabian029f3d22017-06-15 02:28:50 -07007169 cls.ip6_interfaces.append(cls.pg_interfaces[2])
Matus Fabian06596c52017-06-06 04:53:28 -07007170 cls.ip4_interfaces = list(cls.pg_interfaces[1:2])
7171
Ole Troan9a475372019-03-05 16:58:24 +01007172 cls.vapi.ip_table_add_del(is_ipv6=1, is_add=1,
7173 table_id=cls.vrf1_id)
Neale Ranns15002542017-09-10 04:39:11 -07007174
Matus Fabian029f3d22017-06-15 02:28:50 -07007175 cls.pg_interfaces[2].set_table_ip6(cls.vrf1_id)
7176
7177 cls.pg0.generate_remote_hosts(2)
7178
Matus Fabian06596c52017-06-06 04:53:28 -07007179 for i in cls.ip6_interfaces:
7180 i.admin_up()
7181 i.config_ip6()
Matus Fabian029f3d22017-06-15 02:28:50 -07007182 i.configure_ipv6_neighbors()
Matus Fabian06596c52017-06-06 04:53:28 -07007183
7184 for i in cls.ip4_interfaces:
7185 i.admin_up()
7186 i.config_ip4()
7187 i.resolve_arp()
7188
Matus Fabian36ea2d62017-10-24 04:13:49 -07007189 cls.pg3.admin_up()
7190 cls.pg3.config_ip4()
7191 cls.pg3.resolve_arp()
7192 cls.pg3.config_ip6()
7193 cls.pg3.configure_ipv6_neighbors()
7194
Juraj Slobodac746a152018-07-09 02:36:37 +02007195 cls.pg5.admin_up()
7196 cls.pg5.config_ip6()
7197
Matus Fabian06596c52017-06-06 04:53:28 -07007198 except Exception:
7199 super(TestNAT64, cls).tearDownClass()
7200 raise
7201
Juraj Slobodac746a152018-07-09 02:36:37 +02007202 def test_nat64_inside_interface_handles_neighbor_advertisement(self):
7203 """ NAT64 inside interface handles Neighbor Advertisement """
7204
7205 self.vapi.nat64_add_del_interface(self.pg5.sw_if_index)
7206
7207 # Try to send ping
7208 ping = (Ether(dst=self.pg5.local_mac, src=self.pg5.remote_mac) /
7209 IPv6(src=self.pg5.remote_ip6, dst=self.pg5.local_ip6) /
7210 ICMPv6EchoRequest())
7211 pkts = [ping]
7212 self.pg5.add_stream(pkts)
7213 self.pg_enable_capture(self.pg_interfaces)
7214 self.pg_start()
7215
7216 # Wait for Neighbor Solicitation
7217 capture = self.pg5.get_capture(len(pkts))
Juraj Slobodac746a152018-07-09 02:36:37 +02007218 packet = capture[0]
7219 try:
7220 self.assertEqual(packet[IPv6].src, self.pg5.local_ip6)
Paul Vinciguerra978aa642018-11-24 22:19:12 -08007221 self.assertEqual(packet.haslayer(ICMPv6ND_NS), 1)
Juraj Slobodac746a152018-07-09 02:36:37 +02007222 tgt = packet[ICMPv6ND_NS].tgt
7223 except:
7224 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7225 raise
7226
7227 # Send Neighbor Advertisement
7228 p = (Ether(dst=self.pg5.local_mac, src=self.pg5.remote_mac) /
7229 IPv6(src=self.pg5.remote_ip6, dst=self.pg5.local_ip6) /
7230 ICMPv6ND_NA(tgt=tgt) /
7231 ICMPv6NDOptDstLLAddr(lladdr=self.pg5.remote_mac))
7232 pkts = [p]
7233 self.pg5.add_stream(pkts)
7234 self.pg_enable_capture(self.pg_interfaces)
7235 self.pg_start()
7236
7237 # Try to send ping again
7238 pkts = [ping]
7239 self.pg5.add_stream(pkts)
7240 self.pg_enable_capture(self.pg_interfaces)
7241 self.pg_start()
7242
7243 # Wait for ping reply
7244 capture = self.pg5.get_capture(len(pkts))
Juraj Slobodac746a152018-07-09 02:36:37 +02007245 packet = capture[0]
7246 try:
7247 self.assertEqual(packet[IPv6].src, self.pg5.local_ip6)
7248 self.assertEqual(packet[IPv6].dst, self.pg5.remote_ip6)
Paul Vinciguerra978aa642018-11-24 22:19:12 -08007249 self.assertEqual(packet.haslayer(ICMPv6EchoReply), 1)
Juraj Slobodac746a152018-07-09 02:36:37 +02007250 except:
7251 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7252 raise
7253
Matus Fabian06596c52017-06-06 04:53:28 -07007254 def test_pool(self):
7255 """ Add/delete address to NAT64 pool """
7256 nat_addr = socket.inet_pton(socket.AF_INET, '1.2.3.4')
7257
7258 self.vapi.nat64_add_del_pool_addr_range(nat_addr, nat_addr)
7259
7260 addresses = self.vapi.nat64_pool_addr_dump()
7261 self.assertEqual(len(addresses), 1)
7262 self.assertEqual(addresses[0].address, nat_addr)
7263
7264 self.vapi.nat64_add_del_pool_addr_range(nat_addr, nat_addr, is_add=0)
7265
7266 addresses = self.vapi.nat64_pool_addr_dump()
7267 self.assertEqual(len(addresses), 0)
7268
7269 def test_interface(self):
7270 """ Enable/disable NAT64 feature on the interface """
7271 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7272 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7273
7274 interfaces = self.vapi.nat64_interface_dump()
7275 self.assertEqual(len(interfaces), 2)
7276 pg0_found = False
7277 pg1_found = False
7278 for intf in interfaces:
7279 if intf.sw_if_index == self.pg0.sw_if_index:
7280 self.assertEqual(intf.is_inside, 1)
7281 pg0_found = True
7282 elif intf.sw_if_index == self.pg1.sw_if_index:
7283 self.assertEqual(intf.is_inside, 0)
7284 pg1_found = True
7285 self.assertTrue(pg0_found)
7286 self.assertTrue(pg1_found)
7287
7288 features = self.vapi.cli("show interface features pg0")
Paul Vinciguerra9a6dafd2019-03-06 15:11:28 -08007289 self.assertIn('nat64-in2out', features)
Matus Fabian06596c52017-06-06 04:53:28 -07007290 features = self.vapi.cli("show interface features pg1")
Paul Vinciguerra9a6dafd2019-03-06 15:11:28 -08007291 self.assertIn('nat64-out2in', features)
Matus Fabian06596c52017-06-06 04:53:28 -07007292
7293 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index, is_add=0)
7294 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_add=0)
7295
7296 interfaces = self.vapi.nat64_interface_dump()
7297 self.assertEqual(len(interfaces), 0)
7298
7299 def test_static_bib(self):
7300 """ Add/delete static BIB entry """
7301 in_addr = socket.inet_pton(socket.AF_INET6,
7302 '2001:db8:85a3::8a2e:370:7334')
7303 out_addr = socket.inet_pton(socket.AF_INET, '10.1.1.3')
7304 in_port = 1234
7305 out_port = 5678
7306 proto = IP_PROTOS.tcp
7307
7308 self.vapi.nat64_add_del_static_bib(in_addr,
7309 out_addr,
7310 in_port,
7311 out_port,
7312 proto)
7313 bib = self.vapi.nat64_bib_dump(IP_PROTOS.tcp)
7314 static_bib_num = 0
7315 for bibe in bib:
7316 if bibe.is_static:
7317 static_bib_num += 1
7318 self.assertEqual(bibe.i_addr, in_addr)
7319 self.assertEqual(bibe.o_addr, out_addr)
7320 self.assertEqual(bibe.i_port, in_port)
7321 self.assertEqual(bibe.o_port, out_port)
7322 self.assertEqual(static_bib_num, 1)
Matus Fabianfd0d5082018-12-18 01:08:51 -08007323 bibs = self.statistics.get_counter('/nat64/total-bibs')
7324 self.assertEqual(bibs[0][0], 1)
Matus Fabian06596c52017-06-06 04:53:28 -07007325
7326 self.vapi.nat64_add_del_static_bib(in_addr,
7327 out_addr,
7328 in_port,
7329 out_port,
7330 proto,
7331 is_add=0)
7332 bib = self.vapi.nat64_bib_dump(IP_PROTOS.tcp)
7333 static_bib_num = 0
7334 for bibe in bib:
7335 if bibe.is_static:
7336 static_bib_num += 1
7337 self.assertEqual(static_bib_num, 0)
Matus Fabianfd0d5082018-12-18 01:08:51 -08007338 bibs = self.statistics.get_counter('/nat64/total-bibs')
7339 self.assertEqual(bibs[0][0], 0)
Matus Fabian06596c52017-06-06 04:53:28 -07007340
7341 def test_set_timeouts(self):
7342 """ Set NAT64 timeouts """
7343 # verify default values
Matus Fabian878c6462018-08-23 00:33:35 -07007344 timeouts = self.vapi.nat_get_timeouts()
Matus Fabian06596c52017-06-06 04:53:28 -07007345 self.assertEqual(timeouts.udp, 300)
7346 self.assertEqual(timeouts.icmp, 60)
Matus Fabian878c6462018-08-23 00:33:35 -07007347 self.assertEqual(timeouts.tcp_transitory, 240)
7348 self.assertEqual(timeouts.tcp_established, 7440)
Matus Fabian06596c52017-06-06 04:53:28 -07007349
7350 # set and verify custom values
Matus Fabian878c6462018-08-23 00:33:35 -07007351 self.vapi.nat_set_timeouts(udp=200, icmp=30, tcp_transitory=250,
7352 tcp_established=7450)
7353 timeouts = self.vapi.nat_get_timeouts()
Matus Fabian06596c52017-06-06 04:53:28 -07007354 self.assertEqual(timeouts.udp, 200)
7355 self.assertEqual(timeouts.icmp, 30)
Matus Fabian878c6462018-08-23 00:33:35 -07007356 self.assertEqual(timeouts.tcp_transitory, 250)
7357 self.assertEqual(timeouts.tcp_established, 7450)
Matus Fabian06596c52017-06-06 04:53:28 -07007358
7359 def test_dynamic(self):
7360 """ NAT64 dynamic translation test """
7361 self.tcp_port_in = 6303
7362 self.udp_port_in = 6304
7363 self.icmp_id_in = 6305
7364
7365 ses_num_start = self.nat64_get_ses_num()
7366
7367 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7368 self.nat_addr_n)
7369 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7370 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7371
7372 # in2out
Matus Fabiana5e73762018-12-14 01:55:16 -08007373 tcpn = self.statistics.get_counter('/err/nat64-in2out/TCP packets')
7374 udpn = self.statistics.get_counter('/err/nat64-in2out/UDP packets')
7375 icmpn = self.statistics.get_counter('/err/nat64-in2out/ICMP packets')
7376 totaln = self.statistics.get_counter(
7377 '/err/nat64-in2out/good in2out packets processed')
7378
Matus Fabian06596c52017-06-06 04:53:28 -07007379 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
7380 self.pg0.add_stream(pkts)
7381 self.pg_enable_capture(self.pg_interfaces)
7382 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07007383 capture = self.pg1.get_capture(len(pkts))
7384 self.verify_capture_out(capture, nat_ip=self.nat_addr,
Matus Fabian06596c52017-06-06 04:53:28 -07007385 dst_ip=self.pg1.remote_ip4)
7386
Matus Fabiana5e73762018-12-14 01:55:16 -08007387 err = self.statistics.get_counter('/err/nat64-in2out/TCP packets')
7388 self.assertEqual(err - tcpn, 1)
7389 err = self.statistics.get_counter('/err/nat64-in2out/UDP packets')
7390 self.assertEqual(err - udpn, 1)
7391 err = self.statistics.get_counter('/err/nat64-in2out/ICMP packets')
7392 self.assertEqual(err - icmpn, 1)
7393 err = self.statistics.get_counter(
7394 '/err/nat64-in2out/good in2out packets processed')
7395 self.assertEqual(err - totaln, 3)
7396
Matus Fabian06596c52017-06-06 04:53:28 -07007397 # out2in
Matus Fabiana5e73762018-12-14 01:55:16 -08007398 tcpn = self.statistics.get_counter('/err/nat64-out2in/TCP packets')
7399 udpn = self.statistics.get_counter('/err/nat64-out2in/UDP packets')
7400 icmpn = self.statistics.get_counter('/err/nat64-out2in/ICMP packets')
7401 totaln = self.statistics.get_counter(
7402 '/err/nat64-out2in/good out2in packets processed')
7403
Matus Fabian06596c52017-06-06 04:53:28 -07007404 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
7405 self.pg1.add_stream(pkts)
7406 self.pg_enable_capture(self.pg_interfaces)
7407 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07007408 capture = self.pg0.get_capture(len(pkts))
Matus Fabian06596c52017-06-06 04:53:28 -07007409 ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
7410 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
7411
Matus Fabiana5e73762018-12-14 01:55:16 -08007412 err = self.statistics.get_counter('/err/nat64-out2in/TCP packets')
7413 self.assertEqual(err - tcpn, 1)
7414 err = self.statistics.get_counter('/err/nat64-out2in/UDP packets')
7415 self.assertEqual(err - udpn, 1)
7416 err = self.statistics.get_counter('/err/nat64-out2in/ICMP packets')
7417 self.assertEqual(err - icmpn, 1)
7418 err = self.statistics.get_counter(
7419 '/err/nat64-out2in/good out2in packets processed')
7420 self.assertEqual(err - totaln, 3)
7421
Matus Fabianfd0d5082018-12-18 01:08:51 -08007422 bibs = self.statistics.get_counter('/nat64/total-bibs')
7423 self.assertEqual(bibs[0][0], 3)
7424 sessions = self.statistics.get_counter('/nat64/total-sessions')
7425 self.assertEqual(sessions[0][0], 3)
7426
Matus Fabian06596c52017-06-06 04:53:28 -07007427 # in2out
7428 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
7429 self.pg0.add_stream(pkts)
7430 self.pg_enable_capture(self.pg_interfaces)
7431 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07007432 capture = self.pg1.get_capture(len(pkts))
7433 self.verify_capture_out(capture, nat_ip=self.nat_addr,
Matus Fabian06596c52017-06-06 04:53:28 -07007434 dst_ip=self.pg1.remote_ip4)
7435
7436 # out2in
7437 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
7438 self.pg1.add_stream(pkts)
7439 self.pg_enable_capture(self.pg_interfaces)
7440 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07007441 capture = self.pg0.get_capture(len(pkts))
Matus Fabian06596c52017-06-06 04:53:28 -07007442 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
7443
7444 ses_num_end = self.nat64_get_ses_num()
7445
7446 self.assertEqual(ses_num_end - ses_num_start, 3)
7447
Matus Fabian029f3d22017-06-15 02:28:50 -07007448 # tenant with specific VRF
7449 self.vapi.nat64_add_del_pool_addr_range(self.vrf1_nat_addr_n,
7450 self.vrf1_nat_addr_n,
7451 vrf_id=self.vrf1_id)
7452 self.vapi.nat64_add_del_interface(self.pg2.sw_if_index)
7453
7454 pkts = self.create_stream_in_ip6(self.pg2, self.pg1)
7455 self.pg2.add_stream(pkts)
7456 self.pg_enable_capture(self.pg_interfaces)
7457 self.pg_start()
7458 capture = self.pg1.get_capture(len(pkts))
7459 self.verify_capture_out(capture, nat_ip=self.vrf1_nat_addr,
7460 dst_ip=self.pg1.remote_ip4)
7461
7462 pkts = self.create_stream_out(self.pg1, dst_ip=self.vrf1_nat_addr)
7463 self.pg1.add_stream(pkts)
7464 self.pg_enable_capture(self.pg_interfaces)
7465 self.pg_start()
7466 capture = self.pg2.get_capture(len(pkts))
7467 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg2.remote_ip6)
7468
Matus Fabian06596c52017-06-06 04:53:28 -07007469 def test_static(self):
7470 """ NAT64 static translation test """
7471 self.tcp_port_in = 60303
7472 self.udp_port_in = 60304
7473 self.icmp_id_in = 60305
7474 self.tcp_port_out = 60303
7475 self.udp_port_out = 60304
7476 self.icmp_id_out = 60305
7477
7478 ses_num_start = self.nat64_get_ses_num()
7479
7480 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7481 self.nat_addr_n)
7482 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7483 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7484
7485 self.vapi.nat64_add_del_static_bib(self.pg0.remote_ip6n,
7486 self.nat_addr_n,
7487 self.tcp_port_in,
7488 self.tcp_port_out,
7489 IP_PROTOS.tcp)
7490 self.vapi.nat64_add_del_static_bib(self.pg0.remote_ip6n,
7491 self.nat_addr_n,
7492 self.udp_port_in,
7493 self.udp_port_out,
7494 IP_PROTOS.udp)
7495 self.vapi.nat64_add_del_static_bib(self.pg0.remote_ip6n,
7496 self.nat_addr_n,
7497 self.icmp_id_in,
7498 self.icmp_id_out,
7499 IP_PROTOS.icmp)
7500
7501 # in2out
7502 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
7503 self.pg0.add_stream(pkts)
7504 self.pg_enable_capture(self.pg_interfaces)
7505 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07007506 capture = self.pg1.get_capture(len(pkts))
7507 self.verify_capture_out(capture, nat_ip=self.nat_addr,
Matus Fabian06596c52017-06-06 04:53:28 -07007508 dst_ip=self.pg1.remote_ip4, same_port=True)
7509
7510 # out2in
7511 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
7512 self.pg1.add_stream(pkts)
7513 self.pg_enable_capture(self.pg_interfaces)
7514 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07007515 capture = self.pg0.get_capture(len(pkts))
Matus Fabian06596c52017-06-06 04:53:28 -07007516 ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
7517 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
7518
7519 ses_num_end = self.nat64_get_ses_num()
7520
7521 self.assertEqual(ses_num_end - ses_num_start, 3)
7522
Paul Vinciguerradefde0f2018-12-06 07:46:13 -08007523 @unittest.skipUnless(running_extended_tests, "part of extended tests")
Matus Fabian06596c52017-06-06 04:53:28 -07007524 def test_session_timeout(self):
7525 """ NAT64 session timeout """
7526 self.icmp_id_in = 1234
7527 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7528 self.nat_addr_n)
7529 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7530 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
Matus Fabian878c6462018-08-23 00:33:35 -07007531 self.vapi.nat_set_timeouts(icmp=5, tcp_transitory=5, tcp_established=5)
Matus Fabian06596c52017-06-06 04:53:28 -07007532
7533 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
7534 self.pg0.add_stream(pkts)
7535 self.pg_enable_capture(self.pg_interfaces)
7536 self.pg_start()
Matus Fabian029f3d22017-06-15 02:28:50 -07007537 capture = self.pg1.get_capture(len(pkts))
Matus Fabian06596c52017-06-06 04:53:28 -07007538
7539 ses_num_before_timeout = self.nat64_get_ses_num()
7540
7541 sleep(15)
7542
Matus Fabian8fed4242018-08-14 05:14:55 -07007543 # ICMP and TCP session after timeout
Matus Fabian06596c52017-06-06 04:53:28 -07007544 ses_num_after_timeout = self.nat64_get_ses_num()
Matus Fabian8fed4242018-08-14 05:14:55 -07007545 self.assertEqual(ses_num_before_timeout - ses_num_after_timeout, 2)
Matus Fabian06596c52017-06-06 04:53:28 -07007546
Matus Fabian732036d2017-06-08 05:24:28 -07007547 def test_icmp_error(self):
7548 """ NAT64 ICMP Error message translation """
7549 self.tcp_port_in = 6303
7550 self.udp_port_in = 6304
7551 self.icmp_id_in = 6305
7552
Matus Fabian732036d2017-06-08 05:24:28 -07007553 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7554 self.nat_addr_n)
7555 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7556 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7557
7558 # send some packets to create sessions
7559 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
7560 self.pg0.add_stream(pkts)
7561 self.pg_enable_capture(self.pg_interfaces)
7562 self.pg_start()
7563 capture_ip4 = self.pg1.get_capture(len(pkts))
Matus Fabian029f3d22017-06-15 02:28:50 -07007564 self.verify_capture_out(capture_ip4,
Matus Fabian732036d2017-06-08 05:24:28 -07007565 nat_ip=self.nat_addr,
7566 dst_ip=self.pg1.remote_ip4)
7567
7568 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
7569 self.pg1.add_stream(pkts)
7570 self.pg_enable_capture(self.pg_interfaces)
7571 self.pg_start()
7572 capture_ip6 = self.pg0.get_capture(len(pkts))
7573 ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
7574 self.verify_capture_in_ip6(capture_ip6, ip[IPv6].src,
7575 self.pg0.remote_ip6)
7576
7577 # in2out
7578 pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7579 IPv6(src=self.pg0.remote_ip6, dst=ip[IPv6].src) /
7580 ICMPv6DestUnreach(code=1) /
7581 packet[IPv6] for packet in capture_ip6]
7582 self.pg0.add_stream(pkts)
7583 self.pg_enable_capture(self.pg_interfaces)
7584 self.pg_start()
7585 capture = self.pg1.get_capture(len(pkts))
7586 for packet in capture:
7587 try:
7588 self.assertEqual(packet[IP].src, self.nat_addr)
7589 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
7590 self.assertEqual(packet[ICMP].type, 3)
7591 self.assertEqual(packet[ICMP].code, 13)
7592 inner = packet[IPerror]
7593 self.assertEqual(inner.src, self.pg1.remote_ip4)
7594 self.assertEqual(inner.dst, self.nat_addr)
Klement Sekerad81ae412018-05-16 10:52:54 +02007595 self.assert_packet_checksums_valid(packet)
Matus Fabian732036d2017-06-08 05:24:28 -07007596 if inner.haslayer(TCPerror):
7597 self.assertEqual(inner[TCPerror].dport, self.tcp_port_out)
7598 elif inner.haslayer(UDPerror):
7599 self.assertEqual(inner[UDPerror].dport, self.udp_port_out)
7600 else:
7601 self.assertEqual(inner[ICMPerror].id, self.icmp_id_out)
7602 except:
7603 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7604 raise
7605
7606 # out2in
7607 pkts = [Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
7608 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
7609 ICMP(type=3, code=13) /
7610 packet[IP] for packet in capture_ip4]
7611 self.pg1.add_stream(pkts)
7612 self.pg_enable_capture(self.pg_interfaces)
7613 self.pg_start()
7614 capture = self.pg0.get_capture(len(pkts))
7615 for packet in capture:
7616 try:
7617 self.assertEqual(packet[IPv6].src, ip.src)
7618 self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
7619 icmp = packet[ICMPv6DestUnreach]
7620 self.assertEqual(icmp.code, 1)
7621 inner = icmp[IPerror6]
7622 self.assertEqual(inner.src, self.pg0.remote_ip6)
7623 self.assertEqual(inner.dst, ip.src)
Klement Sekerad81ae412018-05-16 10:52:54 +02007624 self.assert_icmpv6_checksum_valid(packet)
Matus Fabian732036d2017-06-08 05:24:28 -07007625 if inner.haslayer(TCPerror):
7626 self.assertEqual(inner[TCPerror].sport, self.tcp_port_in)
7627 elif inner.haslayer(UDPerror):
7628 self.assertEqual(inner[UDPerror].sport, self.udp_port_in)
7629 else:
7630 self.assertEqual(inner[ICMPv6EchoRequest].id,
7631 self.icmp_id_in)
7632 except:
7633 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7634 raise
7635
Matus Fabian029f3d22017-06-15 02:28:50 -07007636 def test_hairpinning(self):
7637 """ NAT64 hairpinning """
7638
7639 client = self.pg0.remote_hosts[0]
7640 server = self.pg0.remote_hosts[1]
7641 server_tcp_in_port = 22
7642 server_tcp_out_port = 4022
7643 server_udp_in_port = 23
7644 server_udp_out_port = 4023
7645 client_tcp_in_port = 1234
7646 client_udp_in_port = 1235
7647 client_tcp_out_port = 0
7648 client_udp_out_port = 0
7649 ip = IPv6(src=''.join(['64:ff9b::', self.nat_addr]))
7650 nat_addr_ip6 = ip.src
7651
7652 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7653 self.nat_addr_n)
7654 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7655 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7656
7657 self.vapi.nat64_add_del_static_bib(server.ip6n,
7658 self.nat_addr_n,
7659 server_tcp_in_port,
7660 server_tcp_out_port,
7661 IP_PROTOS.tcp)
7662 self.vapi.nat64_add_del_static_bib(server.ip6n,
7663 self.nat_addr_n,
7664 server_udp_in_port,
7665 server_udp_out_port,
7666 IP_PROTOS.udp)
7667
7668 # client to server
7669 pkts = []
7670 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7671 IPv6(src=client.ip6, dst=nat_addr_ip6) /
7672 TCP(sport=client_tcp_in_port, dport=server_tcp_out_port))
7673 pkts.append(p)
7674 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7675 IPv6(src=client.ip6, dst=nat_addr_ip6) /
7676 UDP(sport=client_udp_in_port, dport=server_udp_out_port))
7677 pkts.append(p)
7678 self.pg0.add_stream(pkts)
7679 self.pg_enable_capture(self.pg_interfaces)
7680 self.pg_start()
7681 capture = self.pg0.get_capture(len(pkts))
7682 for packet in capture:
7683 try:
7684 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
7685 self.assertEqual(packet[IPv6].dst, server.ip6)
Klement Sekerad81ae412018-05-16 10:52:54 +02007686 self.assert_packet_checksums_valid(packet)
Matus Fabian029f3d22017-06-15 02:28:50 -07007687 if packet.haslayer(TCP):
7688 self.assertNotEqual(packet[TCP].sport, client_tcp_in_port)
7689 self.assertEqual(packet[TCP].dport, server_tcp_in_port)
Matus Fabian029f3d22017-06-15 02:28:50 -07007690 client_tcp_out_port = packet[TCP].sport
7691 else:
7692 self.assertNotEqual(packet[UDP].sport, client_udp_in_port)
7693 self.assertEqual(packet[UDP].dport, server_udp_in_port)
Matus Fabian029f3d22017-06-15 02:28:50 -07007694 client_udp_out_port = packet[UDP].sport
7695 except:
7696 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7697 raise
7698
7699 # server to client
7700 pkts = []
7701 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7702 IPv6(src=server.ip6, dst=nat_addr_ip6) /
7703 TCP(sport=server_tcp_in_port, dport=client_tcp_out_port))
7704 pkts.append(p)
7705 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7706 IPv6(src=server.ip6, dst=nat_addr_ip6) /
7707 UDP(sport=server_udp_in_port, dport=client_udp_out_port))
7708 pkts.append(p)
7709 self.pg0.add_stream(pkts)
7710 self.pg_enable_capture(self.pg_interfaces)
7711 self.pg_start()
7712 capture = self.pg0.get_capture(len(pkts))
7713 for packet in capture:
7714 try:
7715 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
7716 self.assertEqual(packet[IPv6].dst, client.ip6)
Klement Sekerad81ae412018-05-16 10:52:54 +02007717 self.assert_packet_checksums_valid(packet)
Matus Fabian029f3d22017-06-15 02:28:50 -07007718 if packet.haslayer(TCP):
7719 self.assertEqual(packet[TCP].sport, server_tcp_out_port)
7720 self.assertEqual(packet[TCP].dport, client_tcp_in_port)
Matus Fabian029f3d22017-06-15 02:28:50 -07007721 else:
7722 self.assertEqual(packet[UDP].sport, server_udp_out_port)
7723 self.assertEqual(packet[UDP].dport, client_udp_in_port)
Matus Fabian029f3d22017-06-15 02:28:50 -07007724 except:
7725 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7726 raise
7727
7728 # ICMP error
7729 pkts = []
7730 pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7731 IPv6(src=client.ip6, dst=nat_addr_ip6) /
7732 ICMPv6DestUnreach(code=1) /
7733 packet[IPv6] for packet in capture]
7734 self.pg0.add_stream(pkts)
7735 self.pg_enable_capture(self.pg_interfaces)
7736 self.pg_start()
7737 capture = self.pg0.get_capture(len(pkts))
7738 for packet in capture:
7739 try:
7740 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
7741 self.assertEqual(packet[IPv6].dst, server.ip6)
7742 icmp = packet[ICMPv6DestUnreach]
7743 self.assertEqual(icmp.code, 1)
7744 inner = icmp[IPerror6]
7745 self.assertEqual(inner.src, server.ip6)
7746 self.assertEqual(inner.dst, nat_addr_ip6)
Klement Sekerad81ae412018-05-16 10:52:54 +02007747 self.assert_packet_checksums_valid(packet)
Matus Fabian029f3d22017-06-15 02:28:50 -07007748 if inner.haslayer(TCPerror):
7749 self.assertEqual(inner[TCPerror].sport, server_tcp_in_port)
7750 self.assertEqual(inner[TCPerror].dport,
7751 client_tcp_out_port)
7752 else:
7753 self.assertEqual(inner[UDPerror].sport, server_udp_in_port)
7754 self.assertEqual(inner[UDPerror].dport,
7755 client_udp_out_port)
7756 except:
7757 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7758 raise
7759
Matus Fabian428dc912017-06-21 06:15:18 -07007760 def test_prefix(self):
7761 """ NAT64 Network-Specific Prefix """
7762
7763 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7764 self.nat_addr_n)
7765 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7766 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7767 self.vapi.nat64_add_del_pool_addr_range(self.vrf1_nat_addr_n,
7768 self.vrf1_nat_addr_n,
7769 vrf_id=self.vrf1_id)
7770 self.vapi.nat64_add_del_interface(self.pg2.sw_if_index)
7771
7772 # Add global prefix
7773 global_pref64 = "2001:db8::"
7774 global_pref64_n = socket.inet_pton(socket.AF_INET6, global_pref64)
7775 global_pref64_len = 32
7776 self.vapi.nat64_add_del_prefix(global_pref64_n, global_pref64_len)
7777
7778 prefix = self.vapi.nat64_prefix_dump()
7779 self.assertEqual(len(prefix), 1)
7780 self.assertEqual(prefix[0].prefix, global_pref64_n)
7781 self.assertEqual(prefix[0].prefix_len, global_pref64_len)
7782 self.assertEqual(prefix[0].vrf_id, 0)
7783
7784 # Add tenant specific prefix
7785 vrf1_pref64 = "2001:db8:122:300::"
7786 vrf1_pref64_n = socket.inet_pton(socket.AF_INET6, vrf1_pref64)
7787 vrf1_pref64_len = 56
7788 self.vapi.nat64_add_del_prefix(vrf1_pref64_n,
7789 vrf1_pref64_len,
7790 vrf_id=self.vrf1_id)
7791 prefix = self.vapi.nat64_prefix_dump()
7792 self.assertEqual(len(prefix), 2)
7793
7794 # Global prefix
7795 pkts = self.create_stream_in_ip6(self.pg0,
7796 self.pg1,
7797 pref=global_pref64,
7798 plen=global_pref64_len)
7799 self.pg0.add_stream(pkts)
7800 self.pg_enable_capture(self.pg_interfaces)
7801 self.pg_start()
7802 capture = self.pg1.get_capture(len(pkts))
7803 self.verify_capture_out(capture, nat_ip=self.nat_addr,
7804 dst_ip=self.pg1.remote_ip4)
7805
7806 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
7807 self.pg1.add_stream(pkts)
7808 self.pg_enable_capture(self.pg_interfaces)
7809 self.pg_start()
7810 capture = self.pg0.get_capture(len(pkts))
7811 dst_ip = self.compose_ip6(self.pg1.remote_ip4,
7812 global_pref64,
7813 global_pref64_len)
7814 self.verify_capture_in_ip6(capture, dst_ip, self.pg0.remote_ip6)
7815
7816 # Tenant specific prefix
7817 pkts = self.create_stream_in_ip6(self.pg2,
7818 self.pg1,
7819 pref=vrf1_pref64,
7820 plen=vrf1_pref64_len)
7821 self.pg2.add_stream(pkts)
7822 self.pg_enable_capture(self.pg_interfaces)
7823 self.pg_start()
7824 capture = self.pg1.get_capture(len(pkts))
7825 self.verify_capture_out(capture, nat_ip=self.vrf1_nat_addr,
7826 dst_ip=self.pg1.remote_ip4)
7827
7828 pkts = self.create_stream_out(self.pg1, dst_ip=self.vrf1_nat_addr)
7829 self.pg1.add_stream(pkts)
7830 self.pg_enable_capture(self.pg_interfaces)
7831 self.pg_start()
7832 capture = self.pg2.get_capture(len(pkts))
7833 dst_ip = self.compose_ip6(self.pg1.remote_ip4,
7834 vrf1_pref64,
7835 vrf1_pref64_len)
7836 self.verify_capture_in_ip6(capture, dst_ip, self.pg2.remote_ip6)
7837
Matus Fabianf8cd5812017-07-11 03:55:02 -07007838 def test_unknown_proto(self):
Matus Fabian7968e6c2017-07-06 05:37:49 -07007839 """ NAT64 translate packet with unknown protocol """
7840
7841 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7842 self.nat_addr_n)
7843 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7844 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7845 remote_ip6 = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
7846
7847 # in2out
7848 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7849 IPv6(src=self.pg0.remote_ip6, dst=remote_ip6) /
7850 TCP(sport=self.tcp_port_in, dport=20))
7851 self.pg0.add_stream(p)
7852 self.pg_enable_capture(self.pg_interfaces)
7853 self.pg_start()
7854 p = self.pg1.get_capture(1)
7855
7856 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabianf8cd5812017-07-11 03:55:02 -07007857 IPv6(src=self.pg0.remote_ip6, dst=remote_ip6, nh=47) /
Matus Fabian7968e6c2017-07-06 05:37:49 -07007858 GRE() /
7859 IP(src=self.pg2.local_ip4, dst=self.pg2.remote_ip4) /
7860 TCP(sport=1234, dport=1234))
7861 self.pg0.add_stream(p)
7862 self.pg_enable_capture(self.pg_interfaces)
7863 self.pg_start()
7864 p = self.pg1.get_capture(1)
7865 packet = p[0]
7866 try:
7867 self.assertEqual(packet[IP].src, self.nat_addr)
7868 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
Paul Vinciguerra978aa642018-11-24 22:19:12 -08007869 self.assertEqual(packet.haslayer(GRE), 1)
Klement Sekerad81ae412018-05-16 10:52:54 +02007870 self.assert_packet_checksums_valid(packet)
Matus Fabian7968e6c2017-07-06 05:37:49 -07007871 except:
7872 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7873 raise
7874
7875 # out2in
7876 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
7877 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
7878 GRE() /
7879 IP(src=self.pg2.remote_ip4, dst=self.pg2.local_ip4) /
7880 TCP(sport=1234, dport=1234))
7881 self.pg1.add_stream(p)
7882 self.pg_enable_capture(self.pg_interfaces)
7883 self.pg_start()
7884 p = self.pg0.get_capture(1)
7885 packet = p[0]
7886 try:
7887 self.assertEqual(packet[IPv6].src, remote_ip6)
Matus Fabianf8cd5812017-07-11 03:55:02 -07007888 self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
7889 self.assertEqual(packet[IPv6].nh, 47)
Matus Fabian7968e6c2017-07-06 05:37:49 -07007890 except:
7891 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7892 raise
7893
Matus Fabianf8cd5812017-07-11 03:55:02 -07007894 def test_hairpinning_unknown_proto(self):
Matus Fabian7968e6c2017-07-06 05:37:49 -07007895 """ NAT64 translate packet with unknown protocol - hairpinning """
7896
7897 client = self.pg0.remote_hosts[0]
7898 server = self.pg0.remote_hosts[1]
7899 server_tcp_in_port = 22
7900 server_tcp_out_port = 4022
7901 client_tcp_in_port = 1234
Matus Fabianf8cd5812017-07-11 03:55:02 -07007902 client_tcp_out_port = 1235
7903 server_nat_ip = "10.0.0.100"
7904 client_nat_ip = "10.0.0.110"
7905 server_nat_ip_n = socket.inet_pton(socket.AF_INET, server_nat_ip)
7906 client_nat_ip_n = socket.inet_pton(socket.AF_INET, client_nat_ip)
7907 server_nat_ip6 = self.compose_ip6(server_nat_ip, '64:ff9b::', 96)
7908 client_nat_ip6 = self.compose_ip6(client_nat_ip, '64:ff9b::', 96)
Matus Fabian7968e6c2017-07-06 05:37:49 -07007909
Matus Fabianf8cd5812017-07-11 03:55:02 -07007910 self.vapi.nat64_add_del_pool_addr_range(server_nat_ip_n,
7911 client_nat_ip_n)
Matus Fabian7968e6c2017-07-06 05:37:49 -07007912 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7913 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7914
7915 self.vapi.nat64_add_del_static_bib(server.ip6n,
Matus Fabianf8cd5812017-07-11 03:55:02 -07007916 server_nat_ip_n,
Matus Fabian7968e6c2017-07-06 05:37:49 -07007917 server_tcp_in_port,
7918 server_tcp_out_port,
7919 IP_PROTOS.tcp)
7920
Matus Fabianf8cd5812017-07-11 03:55:02 -07007921 self.vapi.nat64_add_del_static_bib(server.ip6n,
7922 server_nat_ip_n,
7923 0,
7924 0,
7925 IP_PROTOS.gre)
7926
7927 self.vapi.nat64_add_del_static_bib(client.ip6n,
7928 client_nat_ip_n,
7929 client_tcp_in_port,
7930 client_tcp_out_port,
7931 IP_PROTOS.tcp)
7932
Matus Fabian7968e6c2017-07-06 05:37:49 -07007933 # client to server
7934 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabianf8cd5812017-07-11 03:55:02 -07007935 IPv6(src=client.ip6, dst=server_nat_ip6) /
Matus Fabian7968e6c2017-07-06 05:37:49 -07007936 TCP(sport=client_tcp_in_port, dport=server_tcp_out_port))
7937 self.pg0.add_stream(p)
7938 self.pg_enable_capture(self.pg_interfaces)
7939 self.pg_start()
7940 p = self.pg0.get_capture(1)
7941
7942 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabianf8cd5812017-07-11 03:55:02 -07007943 IPv6(src=client.ip6, dst=server_nat_ip6, nh=IP_PROTOS.gre) /
Matus Fabian7968e6c2017-07-06 05:37:49 -07007944 GRE() /
7945 IP(src=self.pg2.local_ip4, dst=self.pg2.remote_ip4) /
7946 TCP(sport=1234, dport=1234))
7947 self.pg0.add_stream(p)
7948 self.pg_enable_capture(self.pg_interfaces)
7949 self.pg_start()
7950 p = self.pg0.get_capture(1)
7951 packet = p[0]
7952 try:
Matus Fabianf8cd5812017-07-11 03:55:02 -07007953 self.assertEqual(packet[IPv6].src, client_nat_ip6)
Matus Fabian7968e6c2017-07-06 05:37:49 -07007954 self.assertEqual(packet[IPv6].dst, server.ip6)
Matus Fabianf8cd5812017-07-11 03:55:02 -07007955 self.assertEqual(packet[IPv6].nh, IP_PROTOS.gre)
Matus Fabian7968e6c2017-07-06 05:37:49 -07007956 except:
7957 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7958 raise
7959
7960 # server to client
7961 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
Matus Fabianf8cd5812017-07-11 03:55:02 -07007962 IPv6(src=server.ip6, dst=client_nat_ip6, nh=IP_PROTOS.gre) /
Matus Fabian7968e6c2017-07-06 05:37:49 -07007963 GRE() /
7964 IP(src=self.pg2.remote_ip4, dst=self.pg2.local_ip4) /
7965 TCP(sport=1234, dport=1234))
7966 self.pg0.add_stream(p)
7967 self.pg_enable_capture(self.pg_interfaces)
7968 self.pg_start()
7969 p = self.pg0.get_capture(1)
7970 packet = p[0]
7971 try:
Matus Fabianf8cd5812017-07-11 03:55:02 -07007972 self.assertEqual(packet[IPv6].src, server_nat_ip6)
Matus Fabian7968e6c2017-07-06 05:37:49 -07007973 self.assertEqual(packet[IPv6].dst, client.ip6)
Matus Fabianf8cd5812017-07-11 03:55:02 -07007974 self.assertEqual(packet[IPv6].nh, IP_PROTOS.gre)
Matus Fabian7968e6c2017-07-06 05:37:49 -07007975 except:
7976 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7977 raise
7978
Matus Fabian36ea2d62017-10-24 04:13:49 -07007979 def test_one_armed_nat64(self):
7980 """ One armed NAT64 """
7981 external_port = 0
7982 remote_host_ip6 = self.compose_ip6(self.pg3.remote_ip4,
7983 '64:ff9b::',
7984 96)
7985
7986 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7987 self.nat_addr_n)
7988 self.vapi.nat64_add_del_interface(self.pg3.sw_if_index)
7989 self.vapi.nat64_add_del_interface(self.pg3.sw_if_index, is_inside=0)
7990
7991 # in2out
7992 p = (Ether(src=self.pg3.remote_mac, dst=self.pg3.local_mac) /
7993 IPv6(src=self.pg3.remote_ip6, dst=remote_host_ip6) /
7994 TCP(sport=12345, dport=80))
7995 self.pg3.add_stream(p)
7996 self.pg_enable_capture(self.pg_interfaces)
7997 self.pg_start()
7998 capture = self.pg3.get_capture(1)
7999 p = capture[0]
8000 try:
8001 ip = p[IP]
8002 tcp = p[TCP]
8003 self.assertEqual(ip.src, self.nat_addr)
8004 self.assertEqual(ip.dst, self.pg3.remote_ip4)
8005 self.assertNotEqual(tcp.sport, 12345)
8006 external_port = tcp.sport
8007 self.assertEqual(tcp.dport, 80)
Klement Sekerad81ae412018-05-16 10:52:54 +02008008 self.assert_packet_checksums_valid(p)
Matus Fabian36ea2d62017-10-24 04:13:49 -07008009 except:
8010 self.logger.error(ppp("Unexpected or invalid packet:", p))
8011 raise
8012
8013 # out2in
8014 p = (Ether(src=self.pg3.remote_mac, dst=self.pg3.local_mac) /
8015 IP(src=self.pg3.remote_ip4, dst=self.nat_addr) /
8016 TCP(sport=80, dport=external_port))
8017 self.pg3.add_stream(p)
8018 self.pg_enable_capture(self.pg_interfaces)
8019 self.pg_start()
8020 capture = self.pg3.get_capture(1)
8021 p = capture[0]
8022 try:
8023 ip = p[IPv6]
8024 tcp = p[TCP]
8025 self.assertEqual(ip.src, remote_host_ip6)
8026 self.assertEqual(ip.dst, self.pg3.remote_ip6)
8027 self.assertEqual(tcp.sport, 80)
8028 self.assertEqual(tcp.dport, 12345)
Klement Sekerad81ae412018-05-16 10:52:54 +02008029 self.assert_packet_checksums_valid(p)
Matus Fabian36ea2d62017-10-24 04:13:49 -07008030 except:
8031 self.logger.error(ppp("Unexpected or invalid packet:", p))
8032 raise
8033
Matus Fabianefcd1e92017-08-15 06:59:19 -07008034 def test_frag_in_order(self):
8035 """ NAT64 translate fragments arriving in order """
8036 self.tcp_port_in = random.randint(1025, 65535)
8037
8038 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
8039 self.nat_addr_n)
8040 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
8041 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
8042
8043 reass = self.vapi.nat_reass_dump()
8044 reass_n_start = len(reass)
8045
8046 # in2out
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07008047 data = b'a' * 200
Matus Fabianefcd1e92017-08-15 06:59:19 -07008048 pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
8049 self.tcp_port_in, 20, data)
8050 self.pg0.add_stream(pkts)
8051 self.pg_enable_capture(self.pg_interfaces)
8052 self.pg_start()
8053 frags = self.pg1.get_capture(len(pkts))
8054 p = self.reass_frags_and_verify(frags,
8055 self.nat_addr,
8056 self.pg1.remote_ip4)
8057 self.assertEqual(p[TCP].dport, 20)
8058 self.assertNotEqual(p[TCP].sport, self.tcp_port_in)
8059 self.tcp_port_out = p[TCP].sport
8060 self.assertEqual(data, p[Raw].load)
8061
8062 # out2in
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07008063 data = b"A" * 4 + b"b" * 16 + b"C" * 3
Matus Fabianefcd1e92017-08-15 06:59:19 -07008064 pkts = self.create_stream_frag(self.pg1,
8065 self.nat_addr,
8066 20,
8067 self.tcp_port_out,
8068 data)
8069 self.pg1.add_stream(pkts)
8070 self.pg_enable_capture(self.pg_interfaces)
8071 self.pg_start()
8072 frags = self.pg0.get_capture(len(pkts))
8073 src = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
8074 p = self.reass_frags_and_verify_ip6(frags, src, self.pg0.remote_ip6)
8075 self.assertEqual(p[TCP].sport, 20)
8076 self.assertEqual(p[TCP].dport, self.tcp_port_in)
8077 self.assertEqual(data, p[Raw].load)
8078
8079 reass = self.vapi.nat_reass_dump()
8080 reass_n_end = len(reass)
8081
8082 self.assertEqual(reass_n_end - reass_n_start, 2)
8083
8084 def test_reass_hairpinning(self):
8085 """ NAT64 fragments hairpinning """
8086 data = 'a' * 200
Matus Fabianefcd1e92017-08-15 06:59:19 -07008087 server = self.pg0.remote_hosts[1]
8088 server_in_port = random.randint(1025, 65535)
8089 server_out_port = random.randint(1025, 65535)
8090 client_in_port = random.randint(1025, 65535)
8091 ip = IPv6(src=''.join(['64:ff9b::', self.nat_addr]))
8092 nat_addr_ip6 = ip.src
8093
8094 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
8095 self.nat_addr_n)
8096 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
8097 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
8098
8099 # add static BIB entry for server
8100 self.vapi.nat64_add_del_static_bib(server.ip6n,
8101 self.nat_addr_n,
8102 server_in_port,
8103 server_out_port,
8104 IP_PROTOS.tcp)
8105
8106 # send packet from host to server
8107 pkts = self.create_stream_frag_ip6(self.pg0,
8108 self.nat_addr,
8109 client_in_port,
8110 server_out_port,
8111 data)
8112 self.pg0.add_stream(pkts)
8113 self.pg_enable_capture(self.pg_interfaces)
8114 self.pg_start()
8115 frags = self.pg0.get_capture(len(pkts))
8116 p = self.reass_frags_and_verify_ip6(frags, nat_addr_ip6, server.ip6)
8117 self.assertNotEqual(p[TCP].sport, client_in_port)
8118 self.assertEqual(p[TCP].dport, server_in_port)
8119 self.assertEqual(data, p[Raw].load)
8120
8121 def test_frag_out_of_order(self):
8122 """ NAT64 translate fragments arriving out of order """
8123 self.tcp_port_in = random.randint(1025, 65535)
8124
8125 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
8126 self.nat_addr_n)
8127 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
8128 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
8129
8130 # in2out
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07008131 data = b'a' * 200
Matus Fabianefcd1e92017-08-15 06:59:19 -07008132 pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
8133 self.tcp_port_in, 20, data)
8134 pkts.reverse()
8135 self.pg0.add_stream(pkts)
8136 self.pg_enable_capture(self.pg_interfaces)
8137 self.pg_start()
8138 frags = self.pg1.get_capture(len(pkts))
8139 p = self.reass_frags_and_verify(frags,
8140 self.nat_addr,
8141 self.pg1.remote_ip4)
8142 self.assertEqual(p[TCP].dport, 20)
8143 self.assertNotEqual(p[TCP].sport, self.tcp_port_in)
8144 self.tcp_port_out = p[TCP].sport
8145 self.assertEqual(data, p[Raw].load)
8146
8147 # out2in
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07008148 data = b"A" * 4 + b"B" * 16 + b"C" * 3
Matus Fabianefcd1e92017-08-15 06:59:19 -07008149 pkts = self.create_stream_frag(self.pg1,
8150 self.nat_addr,
8151 20,
8152 self.tcp_port_out,
8153 data)
8154 pkts.reverse()
8155 self.pg1.add_stream(pkts)
8156 self.pg_enable_capture(self.pg_interfaces)
8157 self.pg_start()
8158 frags = self.pg0.get_capture(len(pkts))
8159 src = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
8160 p = self.reass_frags_and_verify_ip6(frags, src, self.pg0.remote_ip6)
8161 self.assertEqual(p[TCP].sport, 20)
8162 self.assertEqual(p[TCP].dport, self.tcp_port_in)
8163 self.assertEqual(data, p[Raw].load)
8164
Matus Fabian0938dcf2017-11-08 01:59:38 -08008165 def test_interface_addr(self):
8166 """ Acquire NAT64 pool addresses from interface """
Ole Troane1ade682019-03-04 23:55:43 +01008167 self.vapi.nat64_add_del_interface_addr(self.pg4.sw_if_index)
Matus Fabian0938dcf2017-11-08 01:59:38 -08008168
8169 # no address in NAT64 pool
8170 adresses = self.vapi.nat44_address_dump()
8171 self.assertEqual(0, len(adresses))
8172
8173 # configure interface address and check NAT64 address pool
8174 self.pg4.config_ip4()
8175 addresses = self.vapi.nat64_pool_addr_dump()
8176 self.assertEqual(len(addresses), 1)
8177 self.assertEqual(addresses[0].address, self.pg4.local_ip4n)
8178
8179 # remove interface address and check NAT64 address pool
8180 self.pg4.unconfig_ip4()
8181 addresses = self.vapi.nat64_pool_addr_dump()
8182 self.assertEqual(0, len(adresses))
8183
Paul Vinciguerradefde0f2018-12-06 07:46:13 -08008184 @unittest.skipUnless(running_extended_tests, "part of extended tests")
Matus Fabiana431ad12018-01-04 04:03:14 -08008185 def test_ipfix_max_bibs_sessions(self):
8186 """ IPFIX logging maximum session and BIB entries exceeded """
8187 max_bibs = 1280
8188 max_sessions = 2560
8189 remote_host_ip6 = self.compose_ip6(self.pg1.remote_ip4,
8190 '64:ff9b::',
8191 96)
8192
8193 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
8194 self.nat_addr_n)
8195 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
8196 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
8197
8198 pkts = []
8199 src = ""
8200 for i in range(0, max_bibs):
8201 src = "fd01:aa::%x" % (i)
8202 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
8203 IPv6(src=src, dst=remote_host_ip6) /
8204 TCP(sport=12345, dport=80))
8205 pkts.append(p)
8206 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
8207 IPv6(src=src, dst=remote_host_ip6) /
8208 TCP(sport=12345, dport=22))
8209 pkts.append(p)
8210 self.pg0.add_stream(pkts)
8211 self.pg_enable_capture(self.pg_interfaces)
8212 self.pg_start()
8213 self.pg1.get_capture(max_sessions)
8214
8215 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
8216 src_address=self.pg3.local_ip4n,
8217 path_mtu=512,
8218 template_interval=10)
Ole Troane1ade682019-03-04 23:55:43 +01008219 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
8220 src_port=self.ipfix_src_port)
Matus Fabiana431ad12018-01-04 04:03:14 -08008221
8222 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
8223 IPv6(src=src, dst=remote_host_ip6) /
8224 TCP(sport=12345, dport=25))
8225 self.pg0.add_stream(p)
8226 self.pg_enable_capture(self.pg_interfaces)
8227 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07008228 self.pg1.assert_nothing_captured()
8229 sleep(1)
Matus Fabiana431ad12018-01-04 04:03:14 -08008230 self.vapi.cli("ipfix flush") # FIXME this should be an API call
8231 capture = self.pg3.get_capture(9)
8232 ipfix = IPFIXDecoder()
8233 # first load template
8234 for p in capture:
8235 self.assertTrue(p.haslayer(IPFIX))
8236 self.assertEqual(p[IP].src, self.pg3.local_ip4)
8237 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
8238 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
8239 self.assertEqual(p[UDP].dport, 4739)
8240 self.assertEqual(p[IPFIX].observationDomainID,
8241 self.ipfix_domain_id)
8242 if p.haslayer(Template):
8243 ipfix.add_template(p.getlayer(Template))
8244 # verify events in data set
8245 for p in capture:
8246 if p.haslayer(Data):
8247 data = ipfix.decode_data_set(p.getlayer(Set))
8248 self.verify_ipfix_max_sessions(data, max_sessions)
8249
8250 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
8251 IPv6(src=self.pg0.remote_ip6, dst=remote_host_ip6) /
8252 TCP(sport=12345, dport=80))
8253 self.pg0.add_stream(p)
8254 self.pg_enable_capture(self.pg_interfaces)
8255 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07008256 self.pg1.assert_nothing_captured()
8257 sleep(1)
Matus Fabiana431ad12018-01-04 04:03:14 -08008258 self.vapi.cli("ipfix flush") # FIXME this should be an API call
8259 capture = self.pg3.get_capture(1)
8260 # verify events in data set
8261 for p in capture:
8262 self.assertTrue(p.haslayer(IPFIX))
8263 self.assertEqual(p[IP].src, self.pg3.local_ip4)
8264 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
8265 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
8266 self.assertEqual(p[UDP].dport, 4739)
8267 self.assertEqual(p[IPFIX].observationDomainID,
8268 self.ipfix_domain_id)
8269 if p.haslayer(Data):
8270 data = ipfix.decode_data_set(p.getlayer(Set))
8271 self.verify_ipfix_max_bibs(data, max_bibs)
8272
8273 def test_ipfix_max_frags(self):
8274 """ IPFIX logging maximum fragments pending reassembly exceeded """
8275 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
8276 self.nat_addr_n)
8277 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
8278 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
Matus Fabiana7f8b222018-09-05 06:01:55 -07008279 self.vapi.nat_set_reass(max_frag=1, is_ip6=1)
Matus Fabiana431ad12018-01-04 04:03:14 -08008280 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
8281 src_address=self.pg3.local_ip4n,
8282 path_mtu=512,
8283 template_interval=10)
Ole Troane1ade682019-03-04 23:55:43 +01008284 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
8285 src_port=self.ipfix_src_port)
Matus Fabiana431ad12018-01-04 04:03:14 -08008286
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07008287 data = b'a' * 200
Matus Fabiana431ad12018-01-04 04:03:14 -08008288 pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
8289 self.tcp_port_in, 20, data)
Matus Fabiana7f8b222018-09-05 06:01:55 -07008290 pkts.reverse()
8291 self.pg0.add_stream(pkts)
Matus Fabiana431ad12018-01-04 04:03:14 -08008292 self.pg_enable_capture(self.pg_interfaces)
8293 self.pg_start()
Matus Fabian229c1aa2018-05-28 04:09:52 -07008294 self.pg1.assert_nothing_captured()
8295 sleep(1)
Matus Fabiana431ad12018-01-04 04:03:14 -08008296 self.vapi.cli("ipfix flush") # FIXME this should be an API call
8297 capture = self.pg3.get_capture(9)
8298 ipfix = IPFIXDecoder()
8299 # first load template
8300 for p in capture:
8301 self.assertTrue(p.haslayer(IPFIX))
8302 self.assertEqual(p[IP].src, self.pg3.local_ip4)
8303 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
8304 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
8305 self.assertEqual(p[UDP].dport, 4739)
8306 self.assertEqual(p[IPFIX].observationDomainID,
8307 self.ipfix_domain_id)
8308 if p.haslayer(Template):
8309 ipfix.add_template(p.getlayer(Template))
8310 # verify events in data set
8311 for p in capture:
8312 if p.haslayer(Data):
8313 data = ipfix.decode_data_set(p.getlayer(Set))
Matus Fabiana7f8b222018-09-05 06:01:55 -07008314 self.verify_ipfix_max_fragments_ip6(data, 1,
Matus Fabiana431ad12018-01-04 04:03:14 -08008315 self.pg0.remote_ip6n)
8316
8317 def test_ipfix_bib_ses(self):
8318 """ IPFIX logging NAT64 BIB/session create and delete events """
8319 self.tcp_port_in = random.randint(1025, 65535)
8320 remote_host_ip6 = self.compose_ip6(self.pg1.remote_ip4,
8321 '64:ff9b::',
8322 96)
8323
8324 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
8325 self.nat_addr_n)
8326 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
8327 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
8328 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
8329 src_address=self.pg3.local_ip4n,
8330 path_mtu=512,
8331 template_interval=10)
Ole Troane1ade682019-03-04 23:55:43 +01008332 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
8333 src_port=self.ipfix_src_port)
Matus Fabiana431ad12018-01-04 04:03:14 -08008334
8335 # Create
8336 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
8337 IPv6(src=self.pg0.remote_ip6, dst=remote_host_ip6) /
8338 TCP(sport=self.tcp_port_in, dport=25))
8339 self.pg0.add_stream(p)
8340 self.pg_enable_capture(self.pg_interfaces)
8341 self.pg_start()
8342 p = self.pg1.get_capture(1)
8343 self.tcp_port_out = p[0][TCP].sport
8344 self.vapi.cli("ipfix flush") # FIXME this should be an API call
8345 capture = self.pg3.get_capture(10)
8346 ipfix = IPFIXDecoder()
8347 # first load template
8348 for p in capture:
8349 self.assertTrue(p.haslayer(IPFIX))
8350 self.assertEqual(p[IP].src, self.pg3.local_ip4)
8351 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
8352 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
8353 self.assertEqual(p[UDP].dport, 4739)
8354 self.assertEqual(p[IPFIX].observationDomainID,
8355 self.ipfix_domain_id)
8356 if p.haslayer(Template):
8357 ipfix.add_template(p.getlayer(Template))
8358 # verify events in data set
8359 for p in capture:
8360 if p.haslayer(Data):
8361 data = ipfix.decode_data_set(p.getlayer(Set))
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07008362 if scapy.compat.orb(data[0][230]) == 10:
Matus Fabiana431ad12018-01-04 04:03:14 -08008363 self.verify_ipfix_bib(data, 1, self.pg0.remote_ip6n)
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07008364 elif scapy.compat.orb(data[0][230]) == 6:
Matus Fabiana431ad12018-01-04 04:03:14 -08008365 self.verify_ipfix_nat64_ses(data,
8366 1,
8367 self.pg0.remote_ip6n,
8368 self.pg1.remote_ip4,
8369 25)
8370 else:
8371 self.logger.error(ppp("Unexpected or invalid packet: ", p))
8372
8373 # Delete
8374 self.pg_enable_capture(self.pg_interfaces)
8375 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
8376 self.nat_addr_n,
8377 is_add=0)
8378 self.vapi.cli("ipfix flush") # FIXME this should be an API call
8379 capture = self.pg3.get_capture(2)
8380 # verify events in data set
8381 for p in capture:
8382 self.assertTrue(p.haslayer(IPFIX))
8383 self.assertEqual(p[IP].src, self.pg3.local_ip4)
8384 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
8385 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
8386 self.assertEqual(p[UDP].dport, 4739)
8387 self.assertEqual(p[IPFIX].observationDomainID,
8388 self.ipfix_domain_id)
8389 if p.haslayer(Data):
8390 data = ipfix.decode_data_set(p.getlayer(Set))
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07008391 if scapy.compat.orb(data[0][230]) == 11:
Matus Fabiana431ad12018-01-04 04:03:14 -08008392 self.verify_ipfix_bib(data, 0, self.pg0.remote_ip6n)
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07008393 elif scapy.compat.orb(data[0][230]) == 7:
Matus Fabiana431ad12018-01-04 04:03:14 -08008394 self.verify_ipfix_nat64_ses(data,
8395 0,
8396 self.pg0.remote_ip6n,
8397 self.pg1.remote_ip4,
8398 25)
8399 else:
8400 self.logger.error(ppp("Unexpected or invalid packet: ", p))
8401
Matus Fabianad1f3e12018-11-28 21:26:34 -08008402 def test_syslog_sess(self):
8403 """ Test syslog session creation and deletion """
8404 self.tcp_port_in = random.randint(1025, 65535)
8405 remote_host_ip6 = self.compose_ip6(self.pg1.remote_ip4,
8406 '64:ff9b::',
8407 96)
8408
8409 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
8410 self.nat_addr_n)
8411 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
8412 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
8413 self.vapi.syslog_set_filter(SYSLOG_SEVERITY.INFO)
Ole Troanf159f582019-02-28 20:20:47 +01008414 self.vapi.syslog_set_sender(self.pg3.local_ip4n, self.pg3.remote_ip4n)
Matus Fabianad1f3e12018-11-28 21:26:34 -08008415
8416 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
8417 IPv6(src=self.pg0.remote_ip6, dst=remote_host_ip6) /
8418 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port))
8419 self.pg0.add_stream(p)
8420 self.pg_enable_capture(self.pg_interfaces)
8421 self.pg_start()
8422 p = self.pg1.get_capture(1)
8423 self.tcp_port_out = p[0][TCP].sport
8424 capture = self.pg3.get_capture(1)
8425 self.verify_syslog_sess(capture[0][Raw].load, is_ip6=True)
8426
8427 self.pg_enable_capture(self.pg_interfaces)
8428 self.pg_start()
8429 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
8430 self.nat_addr_n,
8431 is_add=0)
8432 capture = self.pg3.get_capture(1)
8433 self.verify_syslog_sess(capture[0][Raw].load, False, True)
8434
Matus Fabian06596c52017-06-06 04:53:28 -07008435 def nat64_get_ses_num(self):
8436 """
8437 Return number of active NAT64 sessions.
8438 """
Matus Fabianab9a59c2017-08-16 05:37:36 -07008439 st = self.vapi.nat64_st_dump()
8440 return len(st)
Matus Fabian06596c52017-06-06 04:53:28 -07008441
8442 def clear_nat64(self):
8443 """
8444 Clear NAT64 configuration.
8445 """
Ole Troane1ade682019-03-04 23:55:43 +01008446 self.vapi.nat_ipfix_enable_disable(enable=0,
8447 src_port=self.ipfix_src_port,
8448 domain_id=self.ipfix_domain_id)
Matus Fabiana431ad12018-01-04 04:03:14 -08008449 self.ipfix_src_port = 4739
8450 self.ipfix_domain_id = 1
8451
Matus Fabianad1f3e12018-11-28 21:26:34 -08008452 self.vapi.syslog_set_filter(SYSLOG_SEVERITY.EMERG)
8453
Matus Fabian878c6462018-08-23 00:33:35 -07008454 self.vapi.nat_set_timeouts()
Matus Fabian06596c52017-06-06 04:53:28 -07008455
8456 interfaces = self.vapi.nat64_interface_dump()
8457 for intf in interfaces:
Matus Fabian36ea2d62017-10-24 04:13:49 -07008458 if intf.is_inside > 1:
8459 self.vapi.nat64_add_del_interface(intf.sw_if_index,
8460 0,
8461 is_add=0)
Matus Fabian06596c52017-06-06 04:53:28 -07008462 self.vapi.nat64_add_del_interface(intf.sw_if_index,
8463 intf.is_inside,
8464 is_add=0)
8465
Matus Fabiana431ad12018-01-04 04:03:14 -08008466 bib = self.vapi.nat64_bib_dump(255)
Matus Fabian06596c52017-06-06 04:53:28 -07008467 for bibe in bib:
8468 if bibe.is_static:
8469 self.vapi.nat64_add_del_static_bib(bibe.i_addr,
8470 bibe.o_addr,
8471 bibe.i_port,
8472 bibe.o_port,
8473 bibe.proto,
8474 bibe.vrf_id,
8475 is_add=0)
8476
8477 adresses = self.vapi.nat64_pool_addr_dump()
8478 for addr in adresses:
8479 self.vapi.nat64_add_del_pool_addr_range(addr.address,
8480 addr.address,
Matus Fabian029f3d22017-06-15 02:28:50 -07008481 vrf_id=addr.vrf_id,
Matus Fabian06596c52017-06-06 04:53:28 -07008482 is_add=0)
8483
Matus Fabian428dc912017-06-21 06:15:18 -07008484 prefixes = self.vapi.nat64_prefix_dump()
8485 for prefix in prefixes:
8486 self.vapi.nat64_add_del_prefix(prefix.prefix,
8487 prefix.prefix_len,
8488 vrf_id=prefix.vrf_id,
8489 is_add=0)
8490
Matus Fabianfd0d5082018-12-18 01:08:51 -08008491 bibs = self.statistics.get_counter('/nat64/total-bibs')
8492 self.assertEqual(bibs[0][0], 0)
8493 sessions = self.statistics.get_counter('/nat64/total-sessions')
8494 self.assertEqual(sessions[0][0], 0)
8495
Matus Fabian06596c52017-06-06 04:53:28 -07008496 def tearDown(self):
8497 super(TestNAT64, self).tearDown()
8498 if not self.vpp_dead:
8499 self.logger.info(self.vapi.cli("show nat64 pool"))
8500 self.logger.info(self.vapi.cli("show nat64 interfaces"))
Matus Fabian428dc912017-06-21 06:15:18 -07008501 self.logger.info(self.vapi.cli("show nat64 prefix"))
Matus Fabianab9a59c2017-08-16 05:37:36 -07008502 self.logger.info(self.vapi.cli("show nat64 bib all"))
8503 self.logger.info(self.vapi.cli("show nat64 session table all"))
Matus Fabianefcd1e92017-08-15 06:59:19 -07008504 self.logger.info(self.vapi.cli("show nat virtual-reassembly"))
Matus Fabian06596c52017-06-06 04:53:28 -07008505 self.clear_nat64()
8506
Matus Fabian8ebe6252017-11-06 05:04:53 -08008507
8508class TestDSlite(MethodHolder):
8509 """ DS-Lite Test Cases """
8510
8511 @classmethod
8512 def setUpClass(cls):
8513 super(TestDSlite, cls).setUpClass()
8514
8515 try:
8516 cls.nat_addr = '10.0.0.3'
8517 cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
8518
Matus Fabianad1f3e12018-11-28 21:26:34 -08008519 cls.create_pg_interfaces(range(3))
Matus Fabian8ebe6252017-11-06 05:04:53 -08008520 cls.pg0.admin_up()
8521 cls.pg0.config_ip4()
8522 cls.pg0.resolve_arp()
8523 cls.pg1.admin_up()
8524 cls.pg1.config_ip6()
8525 cls.pg1.generate_remote_hosts(2)
8526 cls.pg1.configure_ipv6_neighbors()
Matus Fabianad1f3e12018-11-28 21:26:34 -08008527 cls.pg2.admin_up()
8528 cls.pg2.config_ip4()
8529 cls.pg2.resolve_arp()
Matus Fabian8ebe6252017-11-06 05:04:53 -08008530
8531 except Exception:
8532 super(TestDSlite, cls).tearDownClass()
8533 raise
8534
Matus Fabianad1f3e12018-11-28 21:26:34 -08008535 def verify_syslog_apmadd(self, data, isaddr, isport, xsaddr, xsport,
8536 sv6enc, proto):
8537 message = data.decode('utf-8')
8538 try:
8539 message = SyslogMessage.parse(message)
Paul Vinciguerrad7532092019-01-14 08:51:17 -08008540 except ParseError as e:
8541 self.logger.error(e)
8542 else:
Matus Fabianad1f3e12018-11-28 21:26:34 -08008543 self.assertEqual(message.severity, SyslogSeverity.info)
8544 self.assertEqual(message.appname, 'NAT')
8545 self.assertEqual(message.msgid, 'APMADD')
8546 sd_params = message.sd.get('napmap')
8547 self.assertTrue(sd_params is not None)
8548 self.assertEqual(sd_params.get('IATYP'), 'IPv4')
8549 self.assertEqual(sd_params.get('ISADDR'), isaddr)
8550 self.assertEqual(sd_params.get('ISPORT'), "%d" % isport)
8551 self.assertEqual(sd_params.get('XATYP'), 'IPv4')
8552 self.assertEqual(sd_params.get('XSADDR'), xsaddr)
8553 self.assertEqual(sd_params.get('XSPORT'), "%d" % xsport)
8554 self.assertEqual(sd_params.get('PROTO'), "%d" % proto)
8555 self.assertTrue(sd_params.get('SSUBIX') is not None)
8556 self.assertEqual(sd_params.get('SV6ENC'), sv6enc)
Matus Fabianad1f3e12018-11-28 21:26:34 -08008557
Matus Fabian8ebe6252017-11-06 05:04:53 -08008558 def test_dslite(self):
8559 """ Test DS-Lite """
Matus Fabian69ce30d2018-08-22 01:27:10 -07008560 nat_config = self.vapi.nat_show_config()
8561 self.assertEqual(0, nat_config.dslite_ce)
8562
Matus Fabian8ebe6252017-11-06 05:04:53 -08008563 self.vapi.dslite_add_del_pool_addr_range(self.nat_addr_n,
8564 self.nat_addr_n)
8565 aftr_ip4 = '192.0.0.1'
8566 aftr_ip4_n = socket.inet_pton(socket.AF_INET, aftr_ip4)
8567 aftr_ip6 = '2001:db8:85a3::8a2e:370:1'
8568 aftr_ip6_n = socket.inet_pton(socket.AF_INET6, aftr_ip6)
8569 self.vapi.dslite_set_aftr_addr(aftr_ip6_n, aftr_ip4_n)
Ole Troanf159f582019-02-28 20:20:47 +01008570 self.vapi.syslog_set_sender(self.pg2.local_ip4n, self.pg2.remote_ip4n)
Matus Fabian8ebe6252017-11-06 05:04:53 -08008571
8572 # UDP
8573 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8574 IPv6(dst=aftr_ip6, src=self.pg1.remote_hosts[0].ip6) /
8575 IP(dst=self.pg0.remote_ip4, src='192.168.1.1') /
8576 UDP(sport=20000, dport=10000))
8577 self.pg1.add_stream(p)
8578 self.pg_enable_capture(self.pg_interfaces)
8579 self.pg_start()
8580 capture = self.pg0.get_capture(1)
8581 capture = capture[0]
8582 self.assertFalse(capture.haslayer(IPv6))
8583 self.assertEqual(capture[IP].src, self.nat_addr)
8584 self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
8585 self.assertNotEqual(capture[UDP].sport, 20000)
8586 self.assertEqual(capture[UDP].dport, 10000)
Klement Sekerad81ae412018-05-16 10:52:54 +02008587 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08008588 out_port = capture[UDP].sport
Matus Fabianad1f3e12018-11-28 21:26:34 -08008589 capture = self.pg2.get_capture(1)
8590 self.verify_syslog_apmadd(capture[0][Raw].load, '192.168.1.1',
8591 20000, self.nat_addr, out_port,
8592 self.pg1.remote_hosts[0].ip6, IP_PROTOS.udp)
Matus Fabian8ebe6252017-11-06 05:04:53 -08008593
8594 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8595 IP(dst=self.nat_addr, src=self.pg0.remote_ip4) /
8596 UDP(sport=10000, dport=out_port))
8597 self.pg0.add_stream(p)
8598 self.pg_enable_capture(self.pg_interfaces)
8599 self.pg_start()
8600 capture = self.pg1.get_capture(1)
8601 capture = capture[0]
8602 self.assertEqual(capture[IPv6].src, aftr_ip6)
8603 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[0].ip6)
8604 self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
8605 self.assertEqual(capture[IP].dst, '192.168.1.1')
8606 self.assertEqual(capture[UDP].sport, 10000)
8607 self.assertEqual(capture[UDP].dport, 20000)
Klement Sekerad81ae412018-05-16 10:52:54 +02008608 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08008609
8610 # TCP
8611 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8612 IPv6(dst=aftr_ip6, src=self.pg1.remote_hosts[1].ip6) /
8613 IP(dst=self.pg0.remote_ip4, src='192.168.1.1') /
8614 TCP(sport=20001, dport=10001))
8615 self.pg1.add_stream(p)
8616 self.pg_enable_capture(self.pg_interfaces)
8617 self.pg_start()
8618 capture = self.pg0.get_capture(1)
8619 capture = capture[0]
8620 self.assertFalse(capture.haslayer(IPv6))
8621 self.assertEqual(capture[IP].src, self.nat_addr)
8622 self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
8623 self.assertNotEqual(capture[TCP].sport, 20001)
8624 self.assertEqual(capture[TCP].dport, 10001)
Klement Sekerad81ae412018-05-16 10:52:54 +02008625 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08008626 out_port = capture[TCP].sport
8627
8628 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8629 IP(dst=self.nat_addr, src=self.pg0.remote_ip4) /
8630 TCP(sport=10001, dport=out_port))
8631 self.pg0.add_stream(p)
8632 self.pg_enable_capture(self.pg_interfaces)
8633 self.pg_start()
8634 capture = self.pg1.get_capture(1)
8635 capture = capture[0]
8636 self.assertEqual(capture[IPv6].src, aftr_ip6)
8637 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[1].ip6)
8638 self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
8639 self.assertEqual(capture[IP].dst, '192.168.1.1')
8640 self.assertEqual(capture[TCP].sport, 10001)
8641 self.assertEqual(capture[TCP].dport, 20001)
Klement Sekerad81ae412018-05-16 10:52:54 +02008642 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08008643
8644 # ICMP
8645 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8646 IPv6(dst=aftr_ip6, src=self.pg1.remote_hosts[1].ip6) /
8647 IP(dst=self.pg0.remote_ip4, src='192.168.1.1') /
8648 ICMP(id=4000, type='echo-request'))
8649 self.pg1.add_stream(p)
8650 self.pg_enable_capture(self.pg_interfaces)
8651 self.pg_start()
8652 capture = self.pg0.get_capture(1)
8653 capture = capture[0]
8654 self.assertFalse(capture.haslayer(IPv6))
8655 self.assertEqual(capture[IP].src, self.nat_addr)
8656 self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
8657 self.assertNotEqual(capture[ICMP].id, 4000)
Klement Sekerad81ae412018-05-16 10:52:54 +02008658 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08008659 out_id = capture[ICMP].id
8660
8661 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8662 IP(dst=self.nat_addr, src=self.pg0.remote_ip4) /
8663 ICMP(id=out_id, type='echo-reply'))
8664 self.pg0.add_stream(p)
8665 self.pg_enable_capture(self.pg_interfaces)
8666 self.pg_start()
8667 capture = self.pg1.get_capture(1)
8668 capture = capture[0]
8669 self.assertEqual(capture[IPv6].src, aftr_ip6)
8670 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[1].ip6)
8671 self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
8672 self.assertEqual(capture[IP].dst, '192.168.1.1')
8673 self.assertEqual(capture[ICMP].id, 4000)
Klement Sekerad81ae412018-05-16 10:52:54 +02008674 self.assert_packet_checksums_valid(capture)
Matus Fabian8ebe6252017-11-06 05:04:53 -08008675
Matus Fabian331acc62017-12-08 03:38:51 -08008676 # ping DS-Lite AFTR tunnel endpoint address
8677 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8678 IPv6(src=self.pg1.remote_hosts[1].ip6, dst=aftr_ip6) /
8679 ICMPv6EchoRequest())
8680 self.pg1.add_stream(p)
8681 self.pg_enable_capture(self.pg_interfaces)
8682 self.pg_start()
8683 capture = self.pg1.get_capture(1)
Matus Fabian331acc62017-12-08 03:38:51 -08008684 capture = capture[0]
8685 self.assertEqual(capture[IPv6].src, aftr_ip6)
8686 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[1].ip6)
8687 self.assertTrue(capture.haslayer(ICMPv6EchoReply))
8688
Matus Fabianfd0d5082018-12-18 01:08:51 -08008689 b4s = self.statistics.get_counter('/dslite/total-b4s')
8690 self.assertEqual(b4s[0][0], 2)
8691 sessions = self.statistics.get_counter('/dslite/total-sessions')
8692 self.assertEqual(sessions[0][0], 3)
8693
Matus Fabian8ebe6252017-11-06 05:04:53 -08008694 def tearDown(self):
8695 super(TestDSlite, self).tearDown()
8696 if not self.vpp_dead:
8697 self.logger.info(self.vapi.cli("show dslite pool"))
8698 self.logger.info(
8699 self.vapi.cli("show dslite aftr-tunnel-endpoint-address"))
8700 self.logger.info(self.vapi.cli("show dslite sessions"))
8701
Juraj Slobodac5c6a332018-01-09 16:08:32 +01008702
8703class TestDSliteCE(MethodHolder):
8704 """ DS-Lite CE Test Cases """
8705
8706 @classmethod
8707 def setUpConstants(cls):
8708 super(TestDSliteCE, cls).setUpConstants()
8709 cls.vpp_cmdline.extend(["nat", "{", "dslite ce", "}"])
8710
8711 @classmethod
8712 def setUpClass(cls):
8713 super(TestDSliteCE, cls).setUpClass()
8714
8715 try:
8716 cls.create_pg_interfaces(range(2))
8717 cls.pg0.admin_up()
8718 cls.pg0.config_ip4()
8719 cls.pg0.resolve_arp()
8720 cls.pg1.admin_up()
8721 cls.pg1.config_ip6()
8722 cls.pg1.generate_remote_hosts(1)
8723 cls.pg1.configure_ipv6_neighbors()
8724
8725 except Exception:
8726 super(TestDSliteCE, cls).tearDownClass()
8727 raise
8728
8729 def test_dslite_ce(self):
8730 """ Test DS-Lite CE """
8731
Matus Fabian69ce30d2018-08-22 01:27:10 -07008732 nat_config = self.vapi.nat_show_config()
8733 self.assertEqual(1, nat_config.dslite_ce)
8734
Juraj Slobodac5c6a332018-01-09 16:08:32 +01008735 b4_ip4 = '192.0.0.2'
8736 b4_ip4_n = socket.inet_pton(socket.AF_INET, b4_ip4)
8737 b4_ip6 = '2001:db8:62aa::375e:f4c1:1'
8738 b4_ip6_n = socket.inet_pton(socket.AF_INET6, b4_ip6)
8739 self.vapi.dslite_set_b4_addr(b4_ip6_n, b4_ip4_n)
8740
8741 aftr_ip4 = '192.0.0.1'
8742 aftr_ip4_n = socket.inet_pton(socket.AF_INET, aftr_ip4)
8743 aftr_ip6 = '2001:db8:85a3::8a2e:370:1'
8744 aftr_ip6_n = socket.inet_pton(socket.AF_INET6, aftr_ip6)
8745 self.vapi.dslite_set_aftr_addr(aftr_ip6_n, aftr_ip4_n)
8746
8747 self.vapi.ip_add_del_route(dst_address=aftr_ip6_n,
8748 dst_address_length=128,
8749 next_hop_address=self.pg1.remote_ip6n,
8750 next_hop_sw_if_index=self.pg1.sw_if_index,
8751 is_ipv6=1)
8752
8753 # UDP encapsulation
8754 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8755 IP(dst=self.pg1.remote_ip4, src=self.pg0.remote_ip4) /
8756 UDP(sport=10000, dport=20000))
8757 self.pg0.add_stream(p)
8758 self.pg_enable_capture(self.pg_interfaces)
8759 self.pg_start()
8760 capture = self.pg1.get_capture(1)
8761 capture = capture[0]
8762 self.assertEqual(capture[IPv6].src, b4_ip6)
8763 self.assertEqual(capture[IPv6].dst, aftr_ip6)
8764 self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
8765 self.assertEqual(capture[IP].dst, self.pg1.remote_ip4)
8766 self.assertEqual(capture[UDP].sport, 10000)
8767 self.assertEqual(capture[UDP].dport, 20000)
Klement Sekerad81ae412018-05-16 10:52:54 +02008768 self.assert_packet_checksums_valid(capture)
Juraj Slobodac5c6a332018-01-09 16:08:32 +01008769
8770 # UDP decapsulation
8771 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8772 IPv6(dst=b4_ip6, src=aftr_ip6) /
8773 IP(dst=self.pg0.remote_ip4, src=self.pg1.remote_ip4) /
8774 UDP(sport=20000, dport=10000))
8775 self.pg1.add_stream(p)
8776 self.pg_enable_capture(self.pg_interfaces)
8777 self.pg_start()
8778 capture = self.pg0.get_capture(1)
8779 capture = capture[0]
8780 self.assertFalse(capture.haslayer(IPv6))
8781 self.assertEqual(capture[IP].src, self.pg1.remote_ip4)
8782 self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
8783 self.assertEqual(capture[UDP].sport, 20000)
8784 self.assertEqual(capture[UDP].dport, 10000)
Klement Sekerad81ae412018-05-16 10:52:54 +02008785 self.assert_packet_checksums_valid(capture)
Juraj Slobodac5c6a332018-01-09 16:08:32 +01008786
8787 # ping DS-Lite B4 tunnel endpoint address
8788 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8789 IPv6(src=self.pg1.remote_hosts[0].ip6, dst=b4_ip6) /
8790 ICMPv6EchoRequest())
8791 self.pg1.add_stream(p)
8792 self.pg_enable_capture(self.pg_interfaces)
8793 self.pg_start()
8794 capture = self.pg1.get_capture(1)
Juraj Slobodac5c6a332018-01-09 16:08:32 +01008795 capture = capture[0]
8796 self.assertEqual(capture[IPv6].src, b4_ip6)
8797 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[0].ip6)
8798 self.assertTrue(capture.haslayer(ICMPv6EchoReply))
8799
8800 def tearDown(self):
8801 super(TestDSliteCE, self).tearDown()
8802 if not self.vpp_dead:
8803 self.logger.info(
8804 self.vapi.cli("show dslite aftr-tunnel-endpoint-address"))
8805 self.logger.info(
8806 self.vapi.cli("show dslite b4-tunnel-endpoint-address"))
8807
Matus Fabianf2a23cc2018-01-22 03:41:53 -08008808
8809class TestNAT66(MethodHolder):
8810 """ NAT66 Test Cases """
8811
8812 @classmethod
8813 def setUpClass(cls):
8814 super(TestNAT66, cls).setUpClass()
8815
8816 try:
8817 cls.nat_addr = 'fd01:ff::2'
8818 cls.nat_addr_n = socket.inet_pton(socket.AF_INET6, cls.nat_addr)
8819
8820 cls.create_pg_interfaces(range(2))
8821 cls.interfaces = list(cls.pg_interfaces)
8822
8823 for i in cls.interfaces:
8824 i.admin_up()
8825 i.config_ip6()
8826 i.configure_ipv6_neighbors()
8827
8828 except Exception:
8829 super(TestNAT66, cls).tearDownClass()
8830 raise
8831
8832 def test_static(self):
8833 """ 1:1 NAT66 test """
8834 self.vapi.nat66_add_del_interface(self.pg0.sw_if_index)
8835 self.vapi.nat66_add_del_interface(self.pg1.sw_if_index, is_inside=0)
8836 self.vapi.nat66_add_del_static_mapping(self.pg0.remote_ip6n,
8837 self.nat_addr_n)
8838
8839 # in2out
8840 pkts = []
8841 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8842 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
8843 TCP())
8844 pkts.append(p)
8845 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8846 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
8847 UDP())
8848 pkts.append(p)
8849 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8850 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
8851 ICMPv6EchoRequest())
8852 pkts.append(p)
8853 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8854 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
8855 GRE() / IP() / TCP())
8856 pkts.append(p)
8857 self.pg0.add_stream(pkts)
8858 self.pg_enable_capture(self.pg_interfaces)
8859 self.pg_start()
8860 capture = self.pg1.get_capture(len(pkts))
8861 for packet in capture:
8862 try:
8863 self.assertEqual(packet[IPv6].src, self.nat_addr)
8864 self.assertEqual(packet[IPv6].dst, self.pg1.remote_ip6)
Klement Sekerad81ae412018-05-16 10:52:54 +02008865 self.assert_packet_checksums_valid(packet)
Matus Fabianf2a23cc2018-01-22 03:41:53 -08008866 except:
8867 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8868 raise
8869
8870 # out2in
8871 pkts = []
8872 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8873 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
8874 TCP())
8875 pkts.append(p)
8876 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8877 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
8878 UDP())
8879 pkts.append(p)
8880 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8881 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
8882 ICMPv6EchoReply())
8883 pkts.append(p)
8884 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8885 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
8886 GRE() / IP() / TCP())
8887 pkts.append(p)
8888 self.pg1.add_stream(pkts)
8889 self.pg_enable_capture(self.pg_interfaces)
8890 self.pg_start()
8891 capture = self.pg0.get_capture(len(pkts))
8892 for packet in capture:
8893 try:
8894 self.assertEqual(packet[IPv6].src, self.pg1.remote_ip6)
8895 self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
Klement Sekerad81ae412018-05-16 10:52:54 +02008896 self.assert_packet_checksums_valid(packet)
Matus Fabianf2a23cc2018-01-22 03:41:53 -08008897 except:
8898 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8899 raise
8900
8901 sm = self.vapi.nat66_static_mapping_dump()
8902 self.assertEqual(len(sm), 1)
8903 self.assertEqual(sm[0].total_pkts, 8)
8904
Juraj Sloboda9341e342018-04-13 12:00:46 +02008905 def test_check_no_translate(self):
8906 """ NAT66 translate only when egress interface is outside interface """
8907 self.vapi.nat66_add_del_interface(self.pg0.sw_if_index)
8908 self.vapi.nat66_add_del_interface(self.pg1.sw_if_index)
8909 self.vapi.nat66_add_del_static_mapping(self.pg0.remote_ip6n,
8910 self.nat_addr_n)
8911
8912 # in2out
8913 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8914 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
8915 UDP())
8916 self.pg0.add_stream([p])
8917 self.pg_enable_capture(self.pg_interfaces)
8918 self.pg_start()
8919 capture = self.pg1.get_capture(1)
8920 packet = capture[0]
8921 try:
8922 self.assertEqual(packet[IPv6].src, self.pg0.remote_ip6)
8923 self.assertEqual(packet[IPv6].dst, self.pg1.remote_ip6)
8924 except:
8925 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8926 raise
8927
Matus Fabianf2a23cc2018-01-22 03:41:53 -08008928 def clear_nat66(self):
8929 """
8930 Clear NAT66 configuration.
8931 """
8932 interfaces = self.vapi.nat66_interface_dump()
8933 for intf in interfaces:
8934 self.vapi.nat66_add_del_interface(intf.sw_if_index,
8935 intf.is_inside,
8936 is_add=0)
8937
8938 static_mappings = self.vapi.nat66_static_mapping_dump()
8939 for sm in static_mappings:
8940 self.vapi.nat66_add_del_static_mapping(sm.local_ip_address,
8941 sm.external_ip_address,
8942 sm.vrf_id,
8943 is_add=0)
8944
8945 def tearDown(self):
8946 super(TestNAT66, self).tearDown()
8947 if not self.vpp_dead:
8948 self.logger.info(self.vapi.cli("show nat66 interfaces"))
8949 self.logger.info(self.vapi.cli("show nat66 static mappings"))
8950 self.clear_nat66()
8951
Klement Sekerad81ae412018-05-16 10:52:54 +02008952
Matus Fabiande886752016-12-07 03:38:19 -08008953if __name__ == '__main__':
8954 unittest.main(testRunner=VppTestRunner)