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